diff --git a/[refs] b/[refs] index afd51eb63c5e..7d28e1af8f90 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: d3818c92afabecfe6b8e5d2e3734c8753522987c +refs/heads/master: 62f8dc529c76aca43113312079299d40741407dd diff --git a/trunk/Documentation/devicetree/bindings/net/can/fsl-flexcan.txt b/trunk/Documentation/devicetree/bindings/net/can/fsl-flexcan.txt index 8ff324eaa889..f31b686d4556 100644 --- a/trunk/Documentation/devicetree/bindings/net/can/fsl-flexcan.txt +++ b/trunk/Documentation/devicetree/bindings/net/can/fsl-flexcan.txt @@ -11,9 +11,6 @@ Required properties: - reg : Offset and length of the register set for this device - interrupts : Interrupt tuple for this device - -Optional properties: - - clock-frequency : The oscillator frequency driving the flexcan device Example: diff --git a/trunk/Documentation/networking/ip-sysctl.txt b/trunk/Documentation/networking/ip-sysctl.txt index e1e021594cff..47b6c79e9b05 100644 --- a/trunk/Documentation/networking/ip-sysctl.txt +++ b/trunk/Documentation/networking/ip-sysctl.txt @@ -551,25 +551,6 @@ tcp_thin_dupack - BOOLEAN Documentation/networking/tcp-thin.txt Default: 0 -tcp_limit_output_bytes - INTEGER - Controls TCP Small Queue limit per tcp socket. - TCP bulk sender tends to increase packets in flight until it - gets losses notifications. With SNDBUF autotuning, this can - result in a large amount of packets queued in qdisc/device - on the local machine, hurting latency of other flows, for - typical pfifo_fast qdiscs. - tcp_limit_output_bytes limits the number of bytes on qdisc - or device to reduce artificial RTT/cwnd and reduce bufferbloat. - Note: For GSO/TSO enabled flows, we try to have at least two - packets in flight. Reducing tcp_limit_output_bytes might also - reduce the size of individual GSO packet (64KB being the max) - Default: 131072 - -tcp_challenge_ack_limit - INTEGER - Limits number of Challenge ACK sent per second, as recommended - in RFC 5961 (Improving TCP's Robustness to Blind In-Window Attacks) - Default: 100 - UDP variables: udp_mem - vector of 3 INTEGERs: min, pressure, max diff --git a/trunk/Documentation/networking/s2io.txt b/trunk/Documentation/networking/s2io.txt index d2a9f43b5546..4be0c039edbc 100644 --- a/trunk/Documentation/networking/s2io.txt +++ b/trunk/Documentation/networking/s2io.txt @@ -136,6 +136,16 @@ For more information, please review the AMD8131 errata at http://vip.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/ 26310_AMD-8131_HyperTransport_PCI-X_Tunnel_Revision_Guide_rev_3_18.pdf -6. Support +6. Available Downloads +Neterion "s2io" driver in Red Hat and Suse 2.6-based distributions is kept up +to date, also the latest "s2io" code (including support for 2.4 kernels) is +available via "Support" link on the Neterion site: http://www.neterion.com. + +For Xframe User Guide (Programming manual), visit ftp site ns1.s2io.com, +user: linuxdocs password: HALdocs + +7. Support For further support please contact either your 10GbE Xframe NIC vendor (IBM, -HP, SGI etc.) +HP, SGI etc.) or click on the "Support" link on the Neterion site: +http://www.neterion.com. + diff --git a/trunk/Documentation/networking/vxge.txt b/trunk/Documentation/networking/vxge.txt index bb76c667a476..d2e2997e6fa0 100644 --- a/trunk/Documentation/networking/vxge.txt +++ b/trunk/Documentation/networking/vxge.txt @@ -91,3 +91,10 @@ v) addr_learn_en virtualization environment. Valid range: 0,1 (disabled, enabled respectively) Default: 0 + +4) Troubleshooting: +------------------- + +To resolve an issue with the source code or X3100 series adapter, please collect +the statistics, register dumps using ethool, relevant logs and email them to +support@neterion.com. diff --git a/trunk/Documentation/nfc/nfc-hci.txt b/trunk/Documentation/nfc/nfc-hci.txt index 89a339c9b079..320f9336c781 100644 --- a/trunk/Documentation/nfc/nfc-hci.txt +++ b/trunk/Documentation/nfc/nfc-hci.txt @@ -178,36 +178,3 @@ ANY_GET_PARAMETER to the reader A gate to get information on the target that was discovered). Typically, such an event will be propagated to NFC Core from MSGRXWQ context. - -Error management ----------------- - -Errors that occur synchronously with the execution of an NFC Core request are -simply returned as the execution result of the request. These are easy. - -Errors that occur asynchronously (e.g. in a background protocol handling thread) -must be reported such that upper layers don't stay ignorant that something -went wrong below and know that expected events will probably never happen. -Handling of these errors is done as follows: - -- driver (pn544) fails to deliver an incoming frame: it stores the error such -that any subsequent call to the driver will result in this error. Then it calls -the standard nfc_shdlc_recv_frame() with a NULL argument to report the problem -above. shdlc stores a EREMOTEIO sticky status, which will trigger SMW to -report above in turn. - -- SMW is basically a background thread to handle incoming and outgoing shdlc -frames. This thread will also check the shdlc sticky status and report to HCI -when it discovers it is not able to run anymore because of an unrecoverable -error that happened within shdlc or below. If the problem occurs during shdlc -connection, the error is reported through the connect completion. - -- HCI: if an internal HCI error happens (frame is lost), or HCI is reported an -error from a lower layer, HCI will either complete the currently executing -command with that error, or notify NFC Core directly if no command is executing. - -- NFC Core: when NFC Core is notified of an error from below and polling is -active, it will send a tag discovered event with an empty tag list to the user -space to let it know that the poll operation will never be able to detect a tag. -If polling is not active and the error was sticky, lower levels will return it -at next invocation. diff --git a/trunk/MAINTAINERS b/trunk/MAINTAINERS index b4321fb74698..8da1373bd6d1 100644 --- a/trunk/MAINTAINERS +++ b/trunk/MAINTAINERS @@ -3661,6 +3661,14 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi.git S: Supported F: drivers/net/wireless/iwlwifi/ +INTEL WIRELESS MULTICOMM 3200 WIFI (iwmc3200wifi) +M: Samuel Ortiz +M: Intel Linux Wireless +L: linux-wireless@vger.kernel.org +S: Supported +W: http://wireless.kernel.org/en/users/Drivers/iwmc3200wifi +F: drivers/net/wireless/iwmc3200wifi/ + INTEL MANAGEMENT ENGINE (mei) M: Tomas Winkler L: linux-kernel@vger.kernel.org @@ -4630,6 +4638,8 @@ F: net/sched/sch_netem.c NETERION 10GbE DRIVERS (s2io/vxge) M: Jon Mason L: netdev@vger.kernel.org +W: http://trac.neterion.com/cgi-bin/trac.cgi/wiki/Linux?Anonymous +W: http://trac.neterion.com/cgi-bin/trac.cgi/wiki/X3100Linux?Anonymous S: Supported F: Documentation/networking/s2io.txt F: Documentation/networking/vxge.txt diff --git a/trunk/arch/blackfin/mach-bf537/boards/stamp.c b/trunk/arch/blackfin/mach-bf537/boards/stamp.c index 5ed654ae66e1..c9d9473a5ab2 100644 --- a/trunk/arch/blackfin/mach-bf537/boards/stamp.c +++ b/trunk/arch/blackfin/mach-bf537/boards/stamp.c @@ -873,7 +873,7 @@ static struct adf702x_platform_data adf7021_platform_data = { }; static inline void adf702x_mac_init(void) { - eth_random_addr(adf7021_platform_data.mac_addr); + random_ether_addr(adf7021_platform_data.mac_addr); } #else static inline void adf702x_mac_init(void) {} diff --git a/trunk/arch/c6x/kernel/soc.c b/trunk/arch/c6x/kernel/soc.c index 3ac74080fded..0748c94ebef6 100644 --- a/trunk/arch/c6x/kernel/soc.c +++ b/trunk/arch/c6x/kernel/soc.c @@ -80,7 +80,7 @@ int soc_mac_addr(unsigned int index, u8 *addr) if (have_fuse_mac) memcpy(addr, c6x_fuse_mac, 6); else - eth_random_addr(addr); + random_ether_addr(addr); } /* adjust for specific EMAC device */ diff --git a/trunk/arch/m68k/include/asm/mcf8390.h b/trunk/arch/m68k/include/asm/mcfne.h similarity index 54% rename from trunk/arch/m68k/include/asm/mcf8390.h rename to trunk/arch/m68k/include/asm/mcfne.h index a72a20819a54..bf638be0958c 100644 --- a/trunk/arch/m68k/include/asm/mcf8390.h +++ b/trunk/arch/m68k/include/asm/mcfne.h @@ -1,7 +1,7 @@ /****************************************************************************/ /* - * mcf8390.h -- NS8390 support for ColdFire eval boards. + * mcfne.h -- NE2000 in ColdFire eval boards. * * (C) Copyright 1999-2000, Greg Ungerer (gerg@snapgear.com) * (C) Copyright 2000, Lineo (www.lineo.com) @@ -14,8 +14,8 @@ */ /****************************************************************************/ -#ifndef mcf8390_h -#define mcf8390_h +#ifndef mcfne_h +#define mcfne_h /****************************************************************************/ @@ -37,7 +37,6 @@ #if defined(CONFIG_ARN5206) #define NE2000_ADDR 0x40000300 #define NE2000_ODDOFFSET 0x00010000 -#define NE2000_ADDRSIZE 0x00020000 #define NE2000_IRQ_VECTOR 0xf0 #define NE2000_IRQ_PRIORITY 2 #define NE2000_IRQ_LEVEL 4 @@ -47,7 +46,6 @@ #if defined(CONFIG_M5206eC3) #define NE2000_ADDR 0x40000300 #define NE2000_ODDOFFSET 0x00010000 -#define NE2000_ADDRSIZE 0x00020000 #define NE2000_IRQ_VECTOR 0x1c #define NE2000_IRQ_PRIORITY 2 #define NE2000_IRQ_LEVEL 4 @@ -56,7 +54,6 @@ #if defined(CONFIG_M5206e) && defined(CONFIG_NETtel) #define NE2000_ADDR 0x30000300 -#define NE2000_ADDRSIZE 0x00001000 #define NE2000_IRQ_VECTOR 25 #define NE2000_IRQ_PRIORITY 1 #define NE2000_IRQ_LEVEL 3 @@ -66,7 +63,6 @@ #if defined(CONFIG_M5307C3) #define NE2000_ADDR 0x40000300 #define NE2000_ODDOFFSET 0x00010000 -#define NE2000_ADDRSIZE 0x00020000 #define NE2000_IRQ_VECTOR 0x1b #define NE2000_BYTE volatile unsigned short #endif @@ -74,7 +70,6 @@ #if defined(CONFIG_M5272) && defined(CONFIG_NETtel) #define NE2000_ADDR 0x30600300 #define NE2000_ODDOFFSET 0x00008000 -#define NE2000_ADDRSIZE 0x00010000 #define NE2000_IRQ_VECTOR 67 #undef BSWAP #define BSWAP(w) (w) @@ -87,7 +82,6 @@ #define NE2000_ADDR0 0x30600300 #define NE2000_ADDR1 0x30800300 #define NE2000_ODDOFFSET 0x00008000 -#define NE2000_ADDRSIZE 0x00010000 #define NE2000_IRQ_VECTOR0 27 #define NE2000_IRQ_VECTOR1 29 #undef BSWAP @@ -100,7 +94,6 @@ #if defined(CONFIG_M5307) && defined(CONFIG_SECUREEDGEMP3) #define NE2000_ADDR 0x30600300 #define NE2000_ODDOFFSET 0x00008000 -#define NE2000_ADDRSIZE 0x00010000 #define NE2000_IRQ_VECTOR 27 #undef BSWAP #define BSWAP(w) (w) @@ -112,7 +105,6 @@ #if defined(CONFIG_ARN5307) #define NE2000_ADDR 0xfe600300 #define NE2000_ODDOFFSET 0x00010000 -#define NE2000_ADDRSIZE 0x00020000 #define NE2000_IRQ_VECTOR 0x1b #define NE2000_IRQ_PRIORITY 2 #define NE2000_IRQ_LEVEL 3 @@ -122,10 +114,129 @@ #if defined(CONFIG_M5407C3) #define NE2000_ADDR 0x40000300 #define NE2000_ODDOFFSET 0x00010000 -#define NE2000_ADDRSIZE 0x00020000 #define NE2000_IRQ_VECTOR 0x1b #define NE2000_BYTE volatile unsigned short #endif /****************************************************************************/ -#endif /* mcf8390_h */ + +/* + * Side-band address space for odd address requires re-mapping + * many of the standard ISA access functions. + */ +#ifdef NE2000_ODDOFFSET + +#undef outb +#undef outb_p +#undef inb +#undef inb_p +#undef outsb +#undef outsw +#undef insb +#undef insw + +#define outb ne2000_outb +#define inb ne2000_inb +#define outb_p ne2000_outb +#define inb_p ne2000_inb +#define outsb ne2000_outsb +#define outsw ne2000_outsw +#define insb ne2000_insb +#define insw ne2000_insw + + +#ifndef COLDFIRE_NE2000_FUNCS + +void ne2000_outb(unsigned int val, unsigned int addr); +int ne2000_inb(unsigned int addr); +void ne2000_insb(unsigned int addr, void *vbuf, int unsigned long len); +void ne2000_insw(unsigned int addr, void *vbuf, unsigned long len); +void ne2000_outsb(unsigned int addr, void *vbuf, unsigned long len); +void ne2000_outsw(unsigned int addr, void *vbuf, unsigned long len); + +#else + +/* + * This macro converts a conventional register address into the + * real memory pointer of the mapped NE2000 device. + * On most NE2000 implementations on ColdFire boards the chip is + * mapped in kinda funny, due to its ISA heritage. + */ +#define NE2000_PTR(addr) ((addr&0x1)?(NE2000_ODDOFFSET+addr-1):(addr)) +#define NE2000_DATA_PTR(addr) (addr) + + +void ne2000_outb(unsigned int val, unsigned int addr) +{ + NE2000_BYTE *rp; + + rp = (NE2000_BYTE *) NE2000_PTR(addr); + *rp = RSWAP(val); +} + +int ne2000_inb(unsigned int addr) +{ + NE2000_BYTE *rp, val; + + rp = (NE2000_BYTE *) NE2000_PTR(addr); + val = *rp; + return((int) ((NE2000_BYTE) RSWAP(val))); +} + +void ne2000_insb(unsigned int addr, void *vbuf, int unsigned long len) +{ + NE2000_BYTE *rp, val; + unsigned char *buf; + + buf = (unsigned char *) vbuf; + rp = (NE2000_BYTE *) NE2000_DATA_PTR(addr); + for (; (len > 0); len--) { + val = *rp; + *buf++ = RSWAP(val); + } +} + +void ne2000_insw(unsigned int addr, void *vbuf, unsigned long len) +{ + volatile unsigned short *rp; + unsigned short w, *buf; + + buf = (unsigned short *) vbuf; + rp = (volatile unsigned short *) NE2000_DATA_PTR(addr); + for (; (len > 0); len--) { + w = *rp; + *buf++ = BSWAP(w); + } +} + +void ne2000_outsb(unsigned int addr, const void *vbuf, unsigned long len) +{ + NE2000_BYTE *rp, val; + unsigned char *buf; + + buf = (unsigned char *) vbuf; + rp = (NE2000_BYTE *) NE2000_DATA_PTR(addr); + for (; (len > 0); len--) { + val = *buf++; + *rp = RSWAP(val); + } +} + +void ne2000_outsw(unsigned int addr, const void *vbuf, unsigned long len) +{ + volatile unsigned short *rp; + unsigned short w, *buf; + + buf = (unsigned short *) vbuf; + rp = (volatile unsigned short *) NE2000_DATA_PTR(addr); + for (; (len > 0); len--) { + w = *buf++; + *rp = BSWAP(w); + } +} + +#endif /* COLDFIRE_NE2000_FUNCS */ +#endif /* NE2000_OFFOFFSET */ + +/****************************************************************************/ +#endif /* mcfne_h */ diff --git a/trunk/arch/mips/ar7/platform.c b/trunk/arch/mips/ar7/platform.c index 1bbc24b08685..1a24d317e7a3 100644 --- a/trunk/arch/mips/ar7/platform.c +++ b/trunk/arch/mips/ar7/platform.c @@ -310,10 +310,10 @@ static void __init cpmac_get_mac(int instance, unsigned char *dev_addr) &dev_addr[4], &dev_addr[5]) != 6) { pr_warning("cannot parse mac address, " "using random address\n"); - eth_random_addr(dev_addr); + random_ether_addr(dev_addr); } } else - eth_random_addr(dev_addr); + random_ether_addr(dev_addr); } /***************************************************************************** diff --git a/trunk/arch/mips/powertv/powertv_setup.c b/trunk/arch/mips/powertv/powertv_setup.c index 820b8480f222..3933c373a438 100644 --- a/trunk/arch/mips/powertv/powertv_setup.c +++ b/trunk/arch/mips/powertv/powertv_setup.c @@ -254,7 +254,7 @@ early_param("rfmac", rfmac_param); * Generates an Ethernet MAC address that is highly likely to be unique for * this particular system on a network with other systems of the same type. * - * The problem we are solving is that, when eth_random_addr() is used to + * The problem we are solving is that, when random_ether_addr() is used to * generate MAC addresses at startup, there isn't much entropy for the random * number generator to use and the addresses it produces are fairly likely to * be the same as those of other identical systems on the same local network. @@ -269,7 +269,7 @@ early_param("rfmac", rfmac_param); * Still, this does give us something to work with. * * The approach we take is: - * 1. If we can't get the RF MAC Address, just call eth_random_addr. + * 1. If we can't get the RF MAC Address, just call random_ether_addr. * 2. Use the 24-bit NIC-specific bits of the RF MAC address as the last 24 * bits of the new address. This is very likely to be unique, except for * the current box. @@ -299,7 +299,7 @@ void platform_random_ether_addr(u8 addr[ETH_ALEN]) if (!have_rfmac) { pr_warning("rfmac not available on command line; " "generating random MAC address\n"); - eth_random_addr(addr); + random_ether_addr(addr); } else { diff --git a/trunk/arch/um/drivers/net_kern.c b/trunk/arch/um/drivers/net_kern.c index 458d324f062d..0d60c5685c26 100644 --- a/trunk/arch/um/drivers/net_kern.c +++ b/trunk/arch/um/drivers/net_kern.c @@ -339,7 +339,7 @@ static int setup_etheraddr(char *str, unsigned char *addr, char *name) random: printk(KERN_INFO "Choosing a random ethernet address for device %s\n", name); - eth_random_addr(addr); + random_ether_addr(addr); return 1; } diff --git a/trunk/drivers/bcma/bcma_private.h b/trunk/drivers/bcma/bcma_private.h index f6589eb7c45f..b81755bb4798 100644 --- a/trunk/drivers/bcma/bcma_private.h +++ b/trunk/drivers/bcma/bcma_private.h @@ -10,15 +10,6 @@ #define BCMA_CORE_SIZE 0x1000 -#define bcma_err(bus, fmt, ...) \ - pr_err("bus%d: " fmt, (bus)->num, ##__VA_ARGS__) -#define bcma_warn(bus, fmt, ...) \ - pr_warn("bus%d: " fmt, (bus)->num, ##__VA_ARGS__) -#define bcma_info(bus, fmt, ...) \ - pr_info("bus%d: " fmt, (bus)->num, ##__VA_ARGS__) -#define bcma_debug(bus, fmt, ...) \ - pr_debug("bus%d: " fmt, (bus)->num, ##__VA_ARGS__) - struct bcma_bus; /* main.c */ diff --git a/trunk/drivers/bcma/core.c b/trunk/drivers/bcma/core.c index 63c8b470536f..bc6e89212ad3 100644 --- a/trunk/drivers/bcma/core.c +++ b/trunk/drivers/bcma/core.c @@ -75,7 +75,7 @@ void bcma_core_set_clockmode(struct bcma_device *core, udelay(10); } if (i) - bcma_err(core->bus, "HT force timeout\n"); + pr_err("HT force timeout\n"); break; case BCMA_CLKMODE_DYNAMIC: bcma_set32(core, BCMA_CLKCTLST, ~BCMA_CLKCTLST_FORCEHT); @@ -102,9 +102,9 @@ void bcma_core_pll_ctl(struct bcma_device *core, u32 req, u32 status, bool on) udelay(10); } if (i) - bcma_err(core->bus, "PLL enable timeout\n"); + pr_err("PLL enable timeout\n"); } else { - bcma_warn(core->bus, "Disabling PLL not supported yet!\n"); + pr_warn("Disabling PLL not supported yet!\n"); } } EXPORT_SYMBOL_GPL(bcma_core_pll_ctl); @@ -120,8 +120,8 @@ u32 bcma_core_dma_translation(struct bcma_device *core) else return BCMA_DMA_TRANSLATION_DMA32_CMT; default: - bcma_err(core->bus, "DMA translation unknown for host %d\n", - core->bus->hosttype); + pr_err("DMA translation unknown for host %d\n", + core->bus->hosttype); } return BCMA_DMA_TRANSLATION_NONE; } diff --git a/trunk/drivers/bcma/driver_chipcommon.c b/trunk/drivers/bcma/driver_chipcommon.c index a4c3ebcc4c86..e9f1b3fd252c 100644 --- a/trunk/drivers/bcma/driver_chipcommon.c +++ b/trunk/drivers/bcma/driver_chipcommon.c @@ -44,7 +44,7 @@ void bcma_core_chipcommon_init(struct bcma_drv_cc *cc) if (cc->capabilities & BCMA_CC_CAP_PMU) bcma_pmu_init(cc); if (cc->capabilities & BCMA_CC_CAP_PCTL) - bcma_err(cc->core->bus, "Power control not implemented!\n"); + pr_err("Power control not implemented!\n"); if (cc->core->id.rev >= 16) { if (cc->core->bus->sprom.leddc_on_time && @@ -137,7 +137,8 @@ void bcma_chipco_serial_init(struct bcma_drv_cc *cc) | BCMA_CC_CORECTL_UARTCLKEN); } } else { - bcma_err(cc->core->bus, "serial not supported on this device ccrev: 0x%x\n", ccrev); + pr_err("serial not supported on this device ccrev: 0x%x\n", + ccrev); return; } diff --git a/trunk/drivers/bcma/driver_chipcommon_pmu.c b/trunk/drivers/bcma/driver_chipcommon_pmu.c index 44326178db29..61ce4054b3c3 100644 --- a/trunk/drivers/bcma/driver_chipcommon_pmu.c +++ b/trunk/drivers/bcma/driver_chipcommon_pmu.c @@ -3,8 +3,7 @@ * ChipCommon Power Management Unit driver * * Copyright 2009, Michael Buesch - * Copyright 2007, 2011, Broadcom Corporation - * Copyright 2011, 2012, Hauke Mehrtens + * Copyright 2007, Broadcom Corporation * * Licensed under the GNU/GPL. See COPYING for details. */ @@ -55,19 +54,39 @@ void bcma_chipco_regctl_maskset(struct bcma_drv_cc *cc, u32 offset, u32 mask, } EXPORT_SYMBOL_GPL(bcma_chipco_regctl_maskset); +static void bcma_pmu_pll_init(struct bcma_drv_cc *cc) +{ + struct bcma_bus *bus = cc->core->bus; + + switch (bus->chipinfo.id) { + case 0x4313: + case 0x4331: + case 43224: + case 43225: + break; + default: + pr_err("PLL init unknown for device 0x%04X\n", + bus->chipinfo.id); + } +} + static void bcma_pmu_resources_init(struct bcma_drv_cc *cc) { struct bcma_bus *bus = cc->core->bus; u32 min_msk = 0, max_msk = 0; switch (bus->chipinfo.id) { - case BCMA_CHIP_ID_BCM4313: + case 0x4313: min_msk = 0x200D; max_msk = 0xFFFF; break; + case 0x4331: + case 43224: + case 43225: + break; default: - bcma_debug(bus, "PMU resource config unknown or not needed for device 0x%04X\n", - bus->chipinfo.id); + pr_err("PMU resource config unknown for device 0x%04X\n", + bus->chipinfo.id); } /* Set the resource masks. */ @@ -75,9 +94,22 @@ static void bcma_pmu_resources_init(struct bcma_drv_cc *cc) bcma_cc_write32(cc, BCMA_CC_PMU_MINRES_MSK, min_msk); if (max_msk) bcma_cc_write32(cc, BCMA_CC_PMU_MAXRES_MSK, max_msk); +} + +void bcma_pmu_swreg_init(struct bcma_drv_cc *cc) +{ + struct bcma_bus *bus = cc->core->bus; - /* Add some delay; allow resources to come up and settle. */ - mdelay(2); + switch (bus->chipinfo.id) { + case 0x4313: + case 0x4331: + case 43224: + case 43225: + break; + default: + pr_err("PMU switch/regulators init unknown for device " + "0x%04X\n", bus->chipinfo.id); + } } /* Disable to allow reading SPROM. Don't know the adventages of enabling it. */ @@ -91,11 +123,8 @@ void bcma_chipco_bcm4331_ext_pa_lines_ctl(struct bcma_drv_cc *cc, bool enable) val |= BCMA_CHIPCTL_4331_EXTPA_EN; if (bus->chipinfo.pkg == 9 || bus->chipinfo.pkg == 11) val |= BCMA_CHIPCTL_4331_EXTPA_ON_GPIO2_5; - else if (bus->chipinfo.rev > 0) - val |= BCMA_CHIPCTL_4331_EXTPA_EN2; } else { val &= ~BCMA_CHIPCTL_4331_EXTPA_EN; - val &= ~BCMA_CHIPCTL_4331_EXTPA_EN2; val &= ~BCMA_CHIPCTL_4331_EXTPA_ON_GPIO2_5; } bcma_cc_write32(cc, BCMA_CC_CHIPCTL, val); @@ -106,38 +135,28 @@ void bcma_pmu_workarounds(struct bcma_drv_cc *cc) struct bcma_bus *bus = cc->core->bus; switch (bus->chipinfo.id) { - case BCMA_CHIP_ID_BCM4313: - /* enable 12 mA drive strenth for 4313 and set chipControl - register bit 1 */ - bcma_chipco_chipctl_maskset(cc, 0, - BCMA_CCTRL_4313_12MA_LED_DRIVE, - BCMA_CCTRL_4313_12MA_LED_DRIVE); + case 0x4313: + bcma_chipco_chipctl_maskset(cc, 0, ~0, 0x7); break; - case BCMA_CHIP_ID_BCM4331: - case BCMA_CHIP_ID_BCM43431: + case 0x4331: + case 43431: /* Ext PA lines must be enabled for tx on BCM4331 */ bcma_chipco_bcm4331_ext_pa_lines_ctl(cc, true); break; - case BCMA_CHIP_ID_BCM43224: - case BCMA_CHIP_ID_BCM43421: - /* enable 12 mA drive strenth for 43224 and set chipControl - register bit 15 */ + case 43224: if (bus->chipinfo.rev == 0) { - bcma_cc_maskset32(cc, BCMA_CC_CHIPCTL, - BCMA_CCTRL_43224_GPIO_TOGGLE, - BCMA_CCTRL_43224_GPIO_TOGGLE); - bcma_chipco_chipctl_maskset(cc, 0, - BCMA_CCTRL_43224A0_12MA_LED_DRIVE, - BCMA_CCTRL_43224A0_12MA_LED_DRIVE); + pr_err("Workarounds for 43224 rev 0 not fully " + "implemented\n"); + bcma_chipco_chipctl_maskset(cc, 0, ~0, 0x00F000F0); } else { - bcma_chipco_chipctl_maskset(cc, 0, - BCMA_CCTRL_43224B0_12MA_LED_DRIVE, - BCMA_CCTRL_43224B0_12MA_LED_DRIVE); + bcma_chipco_chipctl_maskset(cc, 0, ~0, 0xF0); } break; + case 43225: + break; default: - bcma_debug(bus, "Workarounds unknown or not needed for device 0x%04X\n", - bus->chipinfo.id); + pr_err("Workarounds unknown for device 0x%04X\n", + bus->chipinfo.id); } } @@ -148,8 +167,8 @@ void bcma_pmu_init(struct bcma_drv_cc *cc) pmucap = bcma_cc_read32(cc, BCMA_CC_PMU_CAP); cc->pmu.rev = (pmucap & BCMA_CC_PMU_CAP_REVISION); - bcma_debug(cc->core->bus, "Found rev %u PMU (capabilities 0x%08X)\n", - cc->pmu.rev, pmucap); + pr_debug("Found rev %u PMU (capabilities 0x%08X)\n", cc->pmu.rev, + pmucap); if (cc->pmu.rev == 1) bcma_cc_mask32(cc, BCMA_CC_PMU_CTL, @@ -158,7 +177,12 @@ void bcma_pmu_init(struct bcma_drv_cc *cc) bcma_cc_set32(cc, BCMA_CC_PMU_CTL, BCMA_CC_PMU_CTL_NOILPONW); + if (cc->core->id.id == 0x4329 && cc->core->id.rev == 2) + pr_err("Fix for 4329b0 bad LPOM state not implemented!\n"); + + bcma_pmu_pll_init(cc); bcma_pmu_resources_init(cc); + bcma_pmu_swreg_init(cc); bcma_pmu_workarounds(cc); } @@ -167,22 +191,23 @@ u32 bcma_pmu_alp_clock(struct bcma_drv_cc *cc) struct bcma_bus *bus = cc->core->bus; switch (bus->chipinfo.id) { - case BCMA_CHIP_ID_BCM4716: - case BCMA_CHIP_ID_BCM4748: - case BCMA_CHIP_ID_BCM47162: - case BCMA_CHIP_ID_BCM4313: - case BCMA_CHIP_ID_BCM5357: - case BCMA_CHIP_ID_BCM4749: - case BCMA_CHIP_ID_BCM53572: + case 0x4716: + case 0x4748: + case 47162: + case 0x4313: + case 0x5357: + case 0x4749: + case 53572: /* always 20Mhz */ return 20000 * 1000; - case BCMA_CHIP_ID_BCM5356: - case BCMA_CHIP_ID_BCM4706: + case 0x5356: + case 0x5300: /* always 25Mhz */ return 25000 * 1000; default: - bcma_warn(bus, "No ALP clock specified for %04X device, pmu rev. %d, using default %d Hz\n", - bus->chipinfo.id, cc->pmu.rev, BCMA_CC_PMU_ALP_CLOCK); + pr_warn("No ALP clock specified for %04X device, " + "pmu rev. %d, using default %d Hz\n", + bus->chipinfo.id, cc->pmu.rev, BCMA_CC_PMU_ALP_CLOCK); } return BCMA_CC_PMU_ALP_CLOCK; } @@ -199,8 +224,7 @@ static u32 bcma_pmu_clock(struct bcma_drv_cc *cc, u32 pll0, u32 m) BUG_ON(!m || m > 4); - if (bus->chipinfo.id == BCMA_CHIP_ID_BCM5357 || - bus->chipinfo.id == BCMA_CHIP_ID_BCM4749) { + if (bus->chipinfo.id == 0x5357 || bus->chipinfo.id == 0x4749) { /* Detect failure in clock setting */ tmp = bcma_cc_read32(cc, BCMA_CC_CHIPSTAT); if (tmp & 0x40000) @@ -226,62 +250,33 @@ static u32 bcma_pmu_clock(struct bcma_drv_cc *cc, u32 pll0, u32 m) return (fc / div) * 1000000; } -static u32 bcma_pmu_clock_bcm4706(struct bcma_drv_cc *cc, u32 pll0, u32 m) -{ - u32 tmp, ndiv, p1div, p2div; - u32 clock; - - BUG_ON(!m || m > 4); - - /* Get N, P1 and P2 dividers to determine CPU clock */ - tmp = bcma_chipco_pll_read(cc, pll0 + BCMA_CC_PMU6_4706_PROCPLL_OFF); - ndiv = (tmp & BCMA_CC_PMU6_4706_PROC_NDIV_INT_MASK) - >> BCMA_CC_PMU6_4706_PROC_NDIV_INT_SHIFT; - p1div = (tmp & BCMA_CC_PMU6_4706_PROC_P1DIV_MASK) - >> BCMA_CC_PMU6_4706_PROC_P1DIV_SHIFT; - p2div = (tmp & BCMA_CC_PMU6_4706_PROC_P2DIV_MASK) - >> BCMA_CC_PMU6_4706_PROC_P2DIV_SHIFT; - - tmp = bcma_cc_read32(cc, BCMA_CC_CHIPSTAT); - if (tmp & BCMA_CC_CHIPST_4706_PKG_OPTION) - /* Low cost bonding: Fixed reference clock 25MHz and m = 4 */ - clock = (25000000 / 4) * ndiv * p2div / p1div; - else - /* Fixed reference clock 25MHz and m = 2 */ - clock = (25000000 / 2) * ndiv * p2div / p1div; - - if (m == BCMA_CC_PMU5_MAINPLL_SSB) - clock = clock / 4; - - return clock; -} - /* query bus clock frequency for PMU-enabled chipcommon */ u32 bcma_pmu_get_clockcontrol(struct bcma_drv_cc *cc) { struct bcma_bus *bus = cc->core->bus; switch (bus->chipinfo.id) { - case BCMA_CHIP_ID_BCM4716: - case BCMA_CHIP_ID_BCM4748: - case BCMA_CHIP_ID_BCM47162: + case 0x4716: + case 0x4748: + case 47162: return bcma_pmu_clock(cc, BCMA_CC_PMU4716_MAINPLL_PLL0, BCMA_CC_PMU5_MAINPLL_SSB); - case BCMA_CHIP_ID_BCM5356: + case 0x5356: return bcma_pmu_clock(cc, BCMA_CC_PMU5356_MAINPLL_PLL0, BCMA_CC_PMU5_MAINPLL_SSB); - case BCMA_CHIP_ID_BCM5357: - case BCMA_CHIP_ID_BCM4749: + case 0x5357: + case 0x4749: return bcma_pmu_clock(cc, BCMA_CC_PMU5357_MAINPLL_PLL0, BCMA_CC_PMU5_MAINPLL_SSB); - case BCMA_CHIP_ID_BCM4706: - return bcma_pmu_clock_bcm4706(cc, BCMA_CC_PMU4706_MAINPLL_PLL0, - BCMA_CC_PMU5_MAINPLL_SSB); - case BCMA_CHIP_ID_BCM53572: + case 0x5300: + return bcma_pmu_clock(cc, BCMA_CC_PMU4706_MAINPLL_PLL0, + BCMA_CC_PMU5_MAINPLL_SSB); + case 53572: return 75000000; default: - bcma_warn(bus, "No backplane clock specified for %04X device, pmu rev. %d, using default %d Hz\n", - bus->chipinfo.id, cc->pmu.rev, BCMA_CC_PMU_HT_CLOCK); + pr_warn("No backplane clock specified for %04X device, " + "pmu rev. %d, using default %d Hz\n", + bus->chipinfo.id, cc->pmu.rev, BCMA_CC_PMU_HT_CLOCK); } return BCMA_CC_PMU_HT_CLOCK; } @@ -291,21 +286,17 @@ u32 bcma_pmu_get_clockcpu(struct bcma_drv_cc *cc) { struct bcma_bus *bus = cc->core->bus; - if (bus->chipinfo.id == BCMA_CHIP_ID_BCM53572) + if (bus->chipinfo.id == 53572) return 300000000; if (cc->pmu.rev >= 5) { u32 pll; switch (bus->chipinfo.id) { - case BCMA_CHIP_ID_BCM4706: - return bcma_pmu_clock_bcm4706(cc, - BCMA_CC_PMU4706_MAINPLL_PLL0, - BCMA_CC_PMU5_MAINPLL_CPU); - case BCMA_CHIP_ID_BCM5356: + case 0x5356: pll = BCMA_CC_PMU5356_MAINPLL_PLL0; break; - case BCMA_CHIP_ID_BCM5357: - case BCMA_CHIP_ID_BCM4749: + case 0x5357: + case 0x4749: pll = BCMA_CC_PMU5357_MAINPLL_PLL0; break; default: @@ -313,188 +304,10 @@ u32 bcma_pmu_get_clockcpu(struct bcma_drv_cc *cc) break; } + /* TODO: if (bus->chipinfo.id == 0x5300) + return si_4706_pmu_clock(sih, osh, cc, PMU4706_MAINPLL_PLL0, PMU5_MAINPLL_CPU); */ return bcma_pmu_clock(cc, pll, BCMA_CC_PMU5_MAINPLL_CPU); } return bcma_pmu_get_clockcontrol(cc); } - -static void bcma_pmu_spuravoid_pll_write(struct bcma_drv_cc *cc, u32 offset, - u32 value) -{ - bcma_cc_write32(cc, BCMA_CC_PLLCTL_ADDR, offset); - bcma_cc_write32(cc, BCMA_CC_PLLCTL_DATA, value); -} - -void bcma_pmu_spuravoid_pllupdate(struct bcma_drv_cc *cc, int spuravoid) -{ - u32 tmp = 0; - u8 phypll_offset = 0; - u8 bcm5357_bcm43236_p1div[] = {0x1, 0x5, 0x5}; - u8 bcm5357_bcm43236_ndiv[] = {0x30, 0xf6, 0xfc}; - struct bcma_bus *bus = cc->core->bus; - - switch (bus->chipinfo.id) { - case BCMA_CHIP_ID_BCM5357: - case BCMA_CHIP_ID_BCM4749: - case BCMA_CHIP_ID_BCM53572: - /* 5357[ab]0, 43236[ab]0, and 6362b0 */ - - /* BCM5357 needs to touch PLL1_PLLCTL[02], - so offset PLL0_PLLCTL[02] by 6 */ - phypll_offset = (bus->chipinfo.id == BCMA_CHIP_ID_BCM5357 || - bus->chipinfo.id == BCMA_CHIP_ID_BCM4749 || - bus->chipinfo.id == BCMA_CHIP_ID_BCM53572) ? 6 : 0; - - /* RMW only the P1 divider */ - bcma_cc_write32(cc, BCMA_CC_PLLCTL_ADDR, - BCMA_CC_PMU_PLL_CTL0 + phypll_offset); - tmp = bcma_cc_read32(cc, BCMA_CC_PLLCTL_DATA); - tmp &= (~(BCMA_CC_PMU1_PLL0_PC0_P1DIV_MASK)); - tmp |= (bcm5357_bcm43236_p1div[spuravoid] << BCMA_CC_PMU1_PLL0_PC0_P1DIV_SHIFT); - bcma_cc_write32(cc, BCMA_CC_PLLCTL_DATA, tmp); - - /* RMW only the int feedback divider */ - bcma_cc_write32(cc, BCMA_CC_PLLCTL_ADDR, - BCMA_CC_PMU_PLL_CTL2 + phypll_offset); - tmp = bcma_cc_read32(cc, BCMA_CC_PLLCTL_DATA); - tmp &= ~(BCMA_CC_PMU1_PLL0_PC2_NDIV_INT_MASK); - tmp |= (bcm5357_bcm43236_ndiv[spuravoid]) << BCMA_CC_PMU1_PLL0_PC2_NDIV_INT_SHIFT; - bcma_cc_write32(cc, BCMA_CC_PLLCTL_DATA, tmp); - - tmp = 1 << 10; - break; - - case BCMA_CHIP_ID_BCM4331: - case BCMA_CHIP_ID_BCM43431: - if (spuravoid == 2) { - bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL0, - 0x11500014); - bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2, - 0x0FC00a08); - } else if (spuravoid == 1) { - bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL0, - 0x11500014); - bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2, - 0x0F600a08); - } else { - bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL0, - 0x11100014); - bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2, - 0x03000a08); - } - tmp = 1 << 10; - break; - - case BCMA_CHIP_ID_BCM43224: - case BCMA_CHIP_ID_BCM43225: - case BCMA_CHIP_ID_BCM43421: - if (spuravoid == 1) { - bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL0, - 0x11500010); - bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL1, - 0x000C0C06); - bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2, - 0x0F600a08); - bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL3, - 0x00000000); - bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL4, - 0x2001E920); - bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL5, - 0x88888815); - } else { - bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL0, - 0x11100010); - bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL1, - 0x000c0c06); - bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2, - 0x03000a08); - bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL3, - 0x00000000); - bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL4, - 0x200005c0); - bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL5, - 0x88888815); - } - tmp = 1 << 10; - break; - - case BCMA_CHIP_ID_BCM4716: - case BCMA_CHIP_ID_BCM4748: - case BCMA_CHIP_ID_BCM47162: - if (spuravoid == 1) { - bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL0, - 0x11500060); - bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL1, - 0x080C0C06); - bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2, - 0x0F600000); - bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL3, - 0x00000000); - bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL4, - 0x2001E924); - bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL5, - 0x88888815); - } else { - bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL0, - 0x11100060); - bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL1, - 0x080c0c06); - bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2, - 0x03000000); - bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL3, - 0x00000000); - bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL4, - 0x200005c0); - bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL5, - 0x88888815); - } - - tmp = 3 << 9; - break; - - case BCMA_CHIP_ID_BCM43227: - case BCMA_CHIP_ID_BCM43228: - case BCMA_CHIP_ID_BCM43428: - /* LCNXN */ - /* PLL Settings for spur avoidance on/off mode, - no on2 support for 43228A0 */ - if (spuravoid == 1) { - bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL0, - 0x01100014); - bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL1, - 0x040C0C06); - bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2, - 0x03140A08); - bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL3, - 0x00333333); - bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL4, - 0x202C2820); - bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL5, - 0x88888815); - } else { - bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL0, - 0x11100014); - bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL1, - 0x040c0c06); - bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2, - 0x03000a08); - bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL3, - 0x00000000); - bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL4, - 0x200005c0); - bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL5, - 0x88888815); - } - tmp = 1 << 10; - break; - default: - bcma_err(bus, "Unknown spuravoidance settings for chip 0x%04X, not changing PLL\n", - bus->chipinfo.id); - break; - } - - tmp |= bcma_cc_read32(cc, BCMA_CC_PMU_CTL); - bcma_cc_write32(cc, BCMA_CC_PMU_CTL, tmp); -} -EXPORT_SYMBOL_GPL(bcma_pmu_spuravoid_pllupdate); diff --git a/trunk/drivers/bcma/driver_mips.c b/trunk/drivers/bcma/driver_mips.c index ef34ed25bf00..c3e9dff4224e 100644 --- a/trunk/drivers/bcma/driver_mips.c +++ b/trunk/drivers/bcma/driver_mips.c @@ -22,15 +22,15 @@ /* The 47162a0 hangs when reading MIPS DMP registers registers */ static inline bool bcma_core_mips_bcm47162a0_quirk(struct bcma_device *dev) { - return dev->bus->chipinfo.id == BCMA_CHIP_ID_BCM47162 && - dev->bus->chipinfo.rev == 0 && dev->id.id == BCMA_CORE_MIPS_74K; + return dev->bus->chipinfo.id == 47162 && dev->bus->chipinfo.rev == 0 && + dev->id.id == BCMA_CORE_MIPS_74K; } /* The 5357b0 hangs when reading USB20H DMP registers */ static inline bool bcma_core_mips_bcm5357b0_quirk(struct bcma_device *dev) { - return (dev->bus->chipinfo.id == BCMA_CHIP_ID_BCM5357 || - dev->bus->chipinfo.id == BCMA_CHIP_ID_BCM4749) && + return (dev->bus->chipinfo.id == 0x5357 || + dev->bus->chipinfo.id == 0x4749) && dev->bus->chipinfo.pkg == 11 && dev->id.id == BCMA_CORE_USB20_HOST; } @@ -143,8 +143,8 @@ static void bcma_core_mips_set_irq(struct bcma_device *dev, unsigned int irq) 1 << irqflag); } - bcma_info(bus, "set_irq: core 0x%04x, irq %d => %d\n", - dev->id.id, oldirq + 2, irq + 2); + pr_info("set_irq: core 0x%04x, irq %d => %d\n", + dev->id.id, oldirq + 2, irq + 2); } static void bcma_core_mips_print_irq(struct bcma_device *dev, unsigned int irq) @@ -173,7 +173,7 @@ u32 bcma_cpu_clock(struct bcma_drv_mips *mcore) if (bus->drv_cc.capabilities & BCMA_CC_CAP_PMU) return bcma_pmu_get_clockcpu(&bus->drv_cc); - bcma_err(bus, "No PMU available, need this to get the cpu clock\n"); + pr_err("No PMU available, need this to get the cpu clock\n"); return 0; } EXPORT_SYMBOL(bcma_cpu_clock); @@ -185,10 +185,10 @@ static void bcma_core_mips_flash_detect(struct bcma_drv_mips *mcore) switch (bus->drv_cc.capabilities & BCMA_CC_CAP_FLASHT) { case BCMA_CC_FLASHT_STSER: case BCMA_CC_FLASHT_ATSER: - bcma_err(bus, "Serial flash not supported.\n"); + pr_err("Serial flash not supported.\n"); break; case BCMA_CC_FLASHT_PARA: - bcma_info(bus, "found parallel flash.\n"); + pr_info("found parallel flash.\n"); bus->drv_cc.pflash.window = 0x1c000000; bus->drv_cc.pflash.window_size = 0x02000000; @@ -199,7 +199,7 @@ static void bcma_core_mips_flash_detect(struct bcma_drv_mips *mcore) bus->drv_cc.pflash.buswidth = 2; break; default: - bcma_err(bus, "flash not supported.\n"); + pr_err("flash not supported.\n"); } } @@ -209,7 +209,7 @@ void bcma_core_mips_init(struct bcma_drv_mips *mcore) struct bcma_device *core; bus = mcore->core->bus; - bcma_info(bus, "Initializing MIPS core...\n"); + pr_info("Initializing MIPS core...\n"); if (!mcore->setup_done) mcore->assigned_irqs = 1; @@ -244,7 +244,7 @@ void bcma_core_mips_init(struct bcma_drv_mips *mcore) break; } } - bcma_info(bus, "IRQ reconfiguration done\n"); + pr_info("IRQ reconfiguration done\n"); bcma_core_mips_dump_irq(bus); if (mcore->setup_done) diff --git a/trunk/drivers/bcma/driver_pci_host.c b/trunk/drivers/bcma/driver_pci_host.c index cbae2c231336..b9a86edfec39 100644 --- a/trunk/drivers/bcma/driver_pci_host.c +++ b/trunk/drivers/bcma/driver_pci_host.c @@ -36,7 +36,7 @@ bool __devinit bcma_core_pci_is_in_hostmode(struct bcma_drv_pci *pc) return false; if (bus->sprom.boardflags_lo & BCMA_CORE_PCI_BFL_NOPCI) { - bcma_info(bus, "This PCI core is disabled and not working\n"); + pr_info("This PCI core is disabled and not working\n"); return false; } @@ -215,8 +215,7 @@ static int bcma_extpci_write_config(struct bcma_drv_pci *pc, unsigned int dev, } else { writel(val, mmio); - if (chipid == BCMA_CHIP_ID_BCM4716 || - chipid == BCMA_CHIP_ID_BCM4748) + if (chipid == 0x4716 || chipid == 0x4748) readl(mmio); } @@ -341,7 +340,6 @@ static u8 __devinit bcma_find_pci_capability(struct bcma_drv_pci *pc, */ static void __devinit bcma_core_pci_enable_crs(struct bcma_drv_pci *pc) { - struct bcma_bus *bus = pc->core->bus; u8 cap_ptr, root_ctrl, root_cap, dev; u16 val16; int i; @@ -380,8 +378,7 @@ static void __devinit bcma_core_pci_enable_crs(struct bcma_drv_pci *pc) udelay(10); } if (val16 == 0x1) - bcma_err(bus, "PCI: Broken device in slot %d\n", - dev); + pr_err("PCI: Broken device in slot %d\n", dev); } } } @@ -394,11 +391,11 @@ void __devinit bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc) u32 pci_membase_1G; unsigned long io_map_base; - bcma_info(bus, "PCIEcore in host mode found\n"); + pr_info("PCIEcore in host mode found\n"); pc_host = kzalloc(sizeof(*pc_host), GFP_KERNEL); if (!pc_host) { - bcma_err(bus, "can not allocate memory"); + pr_err("can not allocate memory"); return; } @@ -437,14 +434,13 @@ void __devinit bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc) * as mips can't generate 64-bit address on the * backplane. */ - if (bus->chipinfo.id == BCMA_CHIP_ID_BCM4716 || - bus->chipinfo.id == BCMA_CHIP_ID_BCM4748) { + if (bus->chipinfo.id == 0x4716 || bus->chipinfo.id == 0x4748) { pc_host->mem_resource.start = BCMA_SOC_PCI_MEM; pc_host->mem_resource.end = BCMA_SOC_PCI_MEM + BCMA_SOC_PCI_MEM_SZ - 1; pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI0, BCMA_CORE_PCI_SBTOPCI_MEM | BCMA_SOC_PCI_MEM); - } else if (bus->chipinfo.id == BCMA_CHIP_ID_BCM4706) { + } else if (bus->chipinfo.id == 0x5300) { tmp = BCMA_CORE_PCI_SBTOPCI_MEM; tmp |= BCMA_CORE_PCI_SBTOPCI_PREF; tmp |= BCMA_CORE_PCI_SBTOPCI_BURST; diff --git a/trunk/drivers/bcma/host_pci.c b/trunk/drivers/bcma/host_pci.c index 11b32d2642df..6c05cf470f96 100644 --- a/trunk/drivers/bcma/host_pci.c +++ b/trunk/drivers/bcma/host_pci.c @@ -18,7 +18,7 @@ static void bcma_host_pci_switch_core(struct bcma_device *core) pci_write_config_dword(core->bus->host_pci, BCMA_PCI_BAR0_WIN2, core->wrap); core->bus->mapped_core = core; - bcma_debug(core->bus, "Switched to core: 0x%X\n", core->id.id); + pr_debug("Switched to core: 0x%X\n", core->id.id); } /* Provides access to the requested core. Returns base offset that has to be @@ -188,7 +188,7 @@ static int __devinit bcma_host_pci_probe(struct pci_dev *dev, /* SSB needed additional powering up, do we have any AMBA PCI cards? */ if (!pci_is_pcie(dev)) - bcma_err(bus, "PCI card detected, report problems.\n"); + pr_err("PCI card detected, report problems.\n"); /* Map MMIO */ err = -ENOMEM; @@ -268,7 +268,6 @@ static SIMPLE_DEV_PM_OPS(bcma_pm_ops, bcma_host_pci_suspend, static DEFINE_PCI_DEVICE_TABLE(bcma_pci_bridge_tbl) = { { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x0576) }, - { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 43224) }, { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4331) }, { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4353) }, { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4357) }, diff --git a/trunk/drivers/bcma/main.c b/trunk/drivers/bcma/main.c index 7ff4bac6f9e1..7e138ec21357 100644 --- a/trunk/drivers/bcma/main.c +++ b/trunk/drivers/bcma/main.c @@ -118,9 +118,8 @@ static int bcma_register_cores(struct bcma_bus *bus) err = device_register(&core->dev); if (err) { - bcma_err(bus, - "Could not register dev for core 0x%03X\n", - core->id.id); + pr_err("Could not register dev for core 0x%03X\n", + core->id.id); continue; } core->dev_registered = true; @@ -152,7 +151,7 @@ int __devinit bcma_bus_register(struct bcma_bus *bus) /* Scan for devices (cores) */ err = bcma_bus_scan(bus); if (err) { - bcma_err(bus, "Failed to scan: %d\n", err); + pr_err("Failed to scan: %d\n", err); return -1; } @@ -180,14 +179,14 @@ int __devinit bcma_bus_register(struct bcma_bus *bus) /* Try to get SPROM */ err = bcma_sprom_get(bus); if (err == -ENOENT) { - bcma_err(bus, "No SPROM available\n"); + pr_err("No SPROM available\n"); } else if (err) - bcma_err(bus, "Failed to get SPROM: %d\n", err); + pr_err("Failed to get SPROM: %d\n", err); /* Register found cores */ bcma_register_cores(bus); - bcma_info(bus, "Bus registered\n"); + pr_info("Bus registered\n"); return 0; } @@ -215,7 +214,7 @@ int __init bcma_bus_early_register(struct bcma_bus *bus, /* Scan for chip common core */ err = bcma_bus_scan_early(bus, &match, core_cc); if (err) { - bcma_err(bus, "Failed to scan for common core: %d\n", err); + pr_err("Failed to scan for common core: %d\n", err); return -1; } @@ -227,7 +226,7 @@ int __init bcma_bus_early_register(struct bcma_bus *bus, /* Scan for mips core */ err = bcma_bus_scan_early(bus, &match, core_mips); if (err) { - bcma_err(bus, "Failed to scan for mips core: %d\n", err); + pr_err("Failed to scan for mips core: %d\n", err); return -1; } @@ -245,7 +244,7 @@ int __init bcma_bus_early_register(struct bcma_bus *bus, bcma_core_mips_init(&bus->drv_mips); } - bcma_info(bus, "Early bus registered\n"); + pr_info("Early bus registered\n"); return 0; } diff --git a/trunk/drivers/bcma/scan.c b/trunk/drivers/bcma/scan.c index a0272bbfc4f6..a3420585d942 100644 --- a/trunk/drivers/bcma/scan.c +++ b/trunk/drivers/bcma/scan.c @@ -340,7 +340,7 @@ static int bcma_get_next_core(struct bcma_bus *bus, u32 __iomem **eromptr, if (tmp <= 0) { return -EILSEQ; } else { - bcma_info(bus, "Bridge found\n"); + pr_info("Bridge found\n"); return -ENXIO; } } @@ -427,8 +427,8 @@ void bcma_init_bus(struct bcma_bus *bus) chipinfo->id = (tmp & BCMA_CC_ID_ID) >> BCMA_CC_ID_ID_SHIFT; chipinfo->rev = (tmp & BCMA_CC_ID_REV) >> BCMA_CC_ID_REV_SHIFT; chipinfo->pkg = (tmp & BCMA_CC_ID_PKG) >> BCMA_CC_ID_PKG_SHIFT; - bcma_info(bus, "Found chip with id 0x%04X, rev 0x%02X and package 0x%02X\n", - chipinfo->id, chipinfo->rev, chipinfo->pkg); + pr_info("Found chip with id 0x%04X, rev 0x%02X and package 0x%02X\n", + chipinfo->id, chipinfo->rev, chipinfo->pkg); bus->init_done = true; } @@ -482,10 +482,11 @@ int bcma_bus_scan(struct bcma_bus *bus) other_core = bcma_find_core_reverse(bus, core->id.id); core->core_unit = (other_core == NULL) ? 0 : other_core->core_unit + 1; - bcma_info(bus, "Core %d found: %s (manuf 0x%03X, id 0x%03X, rev 0x%02X, class 0x%X)\n", - core->core_index, bcma_device_name(&core->id), - core->id.manuf, core->id.id, core->id.rev, - core->id.class); + pr_info("Core %d found: %s " + "(manuf 0x%03X, id 0x%03X, rev 0x%02X, class 0x%X)\n", + core->core_index, bcma_device_name(&core->id), + core->id.manuf, core->id.id, core->id.rev, + core->id.class); list_add(&core->list, &bus->cores); } @@ -537,10 +538,11 @@ int __init bcma_bus_scan_early(struct bcma_bus *bus, core->core_index = core_num++; bus->nr_cores++; - bcma_info(bus, "Core %d found: %s (manuf 0x%03X, id 0x%03X, rev 0x%02X, class 0x%X)\n", - core->core_index, bcma_device_name(&core->id), - core->id.manuf, core->id.id, core->id.rev, - core->id.class); + pr_info("Core %d found: %s " + "(manuf 0x%03X, id 0x%03X, rev 0x%02X, class 0x%X)\n", + core->core_index, bcma_device_name(&core->id), + core->id.manuf, core->id.id, core->id.rev, + core->id.class); list_add(&core->list, &bus->cores); err = 0; diff --git a/trunk/drivers/bcma/sprom.c b/trunk/drivers/bcma/sprom.c index 26823d97fd9f..f16f42d36071 100644 --- a/trunk/drivers/bcma/sprom.c +++ b/trunk/drivers/bcma/sprom.c @@ -60,11 +60,11 @@ static int bcma_fill_sprom_with_fallback(struct bcma_bus *bus, if (err) goto fail; - bcma_debug(bus, "Using SPROM revision %d provided by platform.\n", - bus->sprom.revision); + pr_debug("Using SPROM revision %d provided by" + " platform.\n", bus->sprom.revision); return 0; fail: - bcma_warn(bus, "Using fallback SPROM failed (err %d)\n", err); + pr_warn("Using fallback SPROM failed (err %d)\n", err); return err; } @@ -468,11 +468,11 @@ static bool bcma_sprom_ext_available(struct bcma_bus *bus) /* older chipcommon revisions use chip status register */ chip_status = bcma_read32(bus->drv_cc.core, BCMA_CC_CHIPSTAT); switch (bus->chipinfo.id) { - case BCMA_CHIP_ID_BCM4313: + case 0x4313: present_mask = BCMA_CC_CHIPST_4313_SPROM_PRESENT; break; - case BCMA_CHIP_ID_BCM4331: + case 0x4331: present_mask = BCMA_CC_CHIPST_4331_SPROM_PRESENT; break; @@ -494,16 +494,16 @@ static bool bcma_sprom_onchip_available(struct bcma_bus *bus) chip_status = bcma_read32(bus->drv_cc.core, BCMA_CC_CHIPSTAT); switch (bus->chipinfo.id) { - case BCMA_CHIP_ID_BCM4313: + case 0x4313: present = chip_status & BCMA_CC_CHIPST_4313_OTP_PRESENT; break; - case BCMA_CHIP_ID_BCM4331: + case 0x4331: present = chip_status & BCMA_CC_CHIPST_4331_OTP_PRESENT; break; - case BCMA_CHIP_ID_BCM43224: - case BCMA_CHIP_ID_BCM43225: + case 43224: + case 43225: /* for these chips OTP is always available */ present = true; break; @@ -579,15 +579,13 @@ int bcma_sprom_get(struct bcma_bus *bus) if (!sprom) return -ENOMEM; - if (bus->chipinfo.id == BCMA_CHIP_ID_BCM4331 || - bus->chipinfo.id == BCMA_CHIP_ID_BCM43431) + if (bus->chipinfo.id == 0x4331 || bus->chipinfo.id == 43431) bcma_chipco_bcm4331_ext_pa_lines_ctl(&bus->drv_cc, false); - bcma_debug(bus, "SPROM offset 0x%x\n", offset); + pr_debug("SPROM offset 0x%x\n", offset); bcma_sprom_read(bus, offset, sprom); - if (bus->chipinfo.id == BCMA_CHIP_ID_BCM4331 || - bus->chipinfo.id == BCMA_CHIP_ID_BCM43431) + if (bus->chipinfo.id == 0x4331 || bus->chipinfo.id == 43431) bcma_chipco_bcm4331_ext_pa_lines_ctl(&bus->drv_cc, true); err = bcma_sprom_valid(sprom); diff --git a/trunk/drivers/connector/cn_proc.c b/trunk/drivers/connector/cn_proc.c index 3e92b7d3fcd2..77e1e6cd66ce 100644 --- a/trunk/drivers/connector/cn_proc.c +++ b/trunk/drivers/connector/cn_proc.c @@ -46,7 +46,7 @@ static DEFINE_PER_CPU(__u32, proc_event_counts) = { 0 }; static inline void get_seq(__u32 *ts, int *cpu) { preempt_disable(); - *ts = __this_cpu_inc_return(proc_event_counts) - 1; + *ts = __this_cpu_inc_return(proc_event_counts) -1; *cpu = smp_processor_id(); preempt_enable(); } @@ -62,8 +62,8 @@ void proc_fork_connector(struct task_struct *task) if (atomic_read(&proc_event_num_listeners) < 1) return; - msg = (struct cn_msg *)buffer; - ev = (struct proc_event *)msg->data; + msg = (struct cn_msg*)buffer; + ev = (struct proc_event*)msg->data; get_seq(&msg->seq, &ev->cpu); ktime_get_ts(&ts); /* get high res monotonic timestamp */ put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns); @@ -93,8 +93,8 @@ void proc_exec_connector(struct task_struct *task) if (atomic_read(&proc_event_num_listeners) < 1) return; - msg = (struct cn_msg *)buffer; - ev = (struct proc_event *)msg->data; + msg = (struct cn_msg*)buffer; + ev = (struct proc_event*)msg->data; get_seq(&msg->seq, &ev->cpu); ktime_get_ts(&ts); /* get high res monotonic timestamp */ put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns); @@ -119,8 +119,8 @@ void proc_id_connector(struct task_struct *task, int which_id) if (atomic_read(&proc_event_num_listeners) < 1) return; - msg = (struct cn_msg *)buffer; - ev = (struct proc_event *)msg->data; + msg = (struct cn_msg*)buffer; + ev = (struct proc_event*)msg->data; ev->what = which_id; ev->event_data.id.process_pid = task->pid; ev->event_data.id.process_tgid = task->tgid; @@ -134,7 +134,7 @@ void proc_id_connector(struct task_struct *task, int which_id) ev->event_data.id.e.egid = cred->egid; } else { rcu_read_unlock(); - return; + return; } rcu_read_unlock(); get_seq(&msg->seq, &ev->cpu); @@ -241,8 +241,8 @@ void proc_exit_connector(struct task_struct *task) if (atomic_read(&proc_event_num_listeners) < 1) return; - msg = (struct cn_msg *)buffer; - ev = (struct proc_event *)msg->data; + msg = (struct cn_msg*)buffer; + ev = (struct proc_event*)msg->data; get_seq(&msg->seq, &ev->cpu); ktime_get_ts(&ts); /* get high res monotonic timestamp */ put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns); @@ -276,8 +276,8 @@ static void cn_proc_ack(int err, int rcvd_seq, int rcvd_ack) if (atomic_read(&proc_event_num_listeners) < 1) return; - msg = (struct cn_msg *)buffer; - ev = (struct proc_event *)msg->data; + msg = (struct cn_msg*)buffer; + ev = (struct proc_event*)msg->data; msg->seq = rcvd_seq; ktime_get_ts(&ts); /* get high res monotonic timestamp */ put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns); @@ -303,7 +303,7 @@ static void cn_proc_mcast_ctl(struct cn_msg *msg, if (msg->len != sizeof(*mc_op)) return; - mc_op = (enum proc_cn_mcast_op *)msg->data; + mc_op = (enum proc_cn_mcast_op*)msg->data; switch (*mc_op) { case PROC_CN_MCAST_LISTEN: atomic_inc(&proc_event_num_listeners); @@ -325,11 +325,11 @@ static void cn_proc_mcast_ctl(struct cn_msg *msg, */ static int __init cn_proc_init(void) { - int err = cn_add_callback(&cn_proc_event_id, - "cn_proc", - &cn_proc_mcast_ctl); - if (err) { - pr_warn("cn_proc failed to register\n"); + int err; + + if ((err = cn_add_callback(&cn_proc_event_id, "cn_proc", + &cn_proc_mcast_ctl))) { + printk(KERN_WARNING "cn_proc failed to register\n"); return err; } return 0; diff --git a/trunk/drivers/connector/cn_queue.c b/trunk/drivers/connector/cn_queue.c index 1f8bf054d11c..c42c9d517790 100644 --- a/trunk/drivers/connector/cn_queue.c +++ b/trunk/drivers/connector/cn_queue.c @@ -1,5 +1,5 @@ /* - * cn_queue.c + * cn_queue.c * * 2004+ Copyright (c) Evgeniy Polyakov * All rights reserved. @@ -34,14 +34,13 @@ static struct cn_callback_entry * cn_queue_alloc_callback_entry(struct cn_queue_dev *dev, const char *name, struct cb_id *id, - void (*callback)(struct cn_msg *, - struct netlink_skb_parms *)) + void (*callback)(struct cn_msg *, struct netlink_skb_parms *)) { struct cn_callback_entry *cbq; cbq = kzalloc(sizeof(*cbq), GFP_KERNEL); if (!cbq) { - pr_err("Failed to create new callback queue.\n"); + printk(KERN_ERR "Failed to create new callback queue.\n"); return NULL; } @@ -72,8 +71,7 @@ int cn_cb_equal(struct cb_id *i1, struct cb_id *i2) int cn_queue_add_callback(struct cn_queue_dev *dev, const char *name, struct cb_id *id, - void (*callback)(struct cn_msg *, - struct netlink_skb_parms *)) + void (*callback)(struct cn_msg *, struct netlink_skb_parms *)) { struct cn_callback_entry *cbq, *__cbq; int found = 0; @@ -151,7 +149,7 @@ void cn_queue_free_dev(struct cn_queue_dev *dev) spin_unlock_bh(&dev->queue_lock); while (atomic_read(&dev->refcnt)) { - pr_info("Waiting for %s to become free: refcnt=%d.\n", + printk(KERN_INFO "Waiting for %s to become free: refcnt=%d.\n", dev->name, atomic_read(&dev->refcnt)); msleep(1000); } diff --git a/trunk/drivers/connector/connector.c b/trunk/drivers/connector/connector.c index 82fa4f0f91d6..116cf8d02834 100644 --- a/trunk/drivers/connector/connector.c +++ b/trunk/drivers/connector/connector.c @@ -1,5 +1,5 @@ /* - * connector.c + * connector.c * * 2004+ Copyright (c) Evgeniy Polyakov * All rights reserved. @@ -185,8 +185,7 @@ static void cn_rx_skb(struct sk_buff *__skb) * May sleep. */ int cn_add_callback(struct cb_id *id, const char *name, - void (*callback)(struct cn_msg *, - struct netlink_skb_parms *)) + void (*callback)(struct cn_msg *, struct netlink_skb_parms *)) { int err; struct cn_dev *dev = &cdev; diff --git a/trunk/drivers/ieee802154/at86rf230.c b/trunk/drivers/ieee802154/at86rf230.c index 5d309408395d..902e38bb382f 100644 --- a/trunk/drivers/ieee802154/at86rf230.c +++ b/trunk/drivers/ieee802154/at86rf230.c @@ -543,13 +543,6 @@ at86rf230_xmit(struct ieee802154_dev *dev, struct sk_buff *skb) int rc; unsigned long flags; - spin_lock(&lp->lock); - if (lp->irq_disabled) { - spin_unlock(&lp->lock); - return -EBUSY; - } - spin_unlock(&lp->lock); - might_sleep(); rc = at86rf230_state(dev, STATE_FORCE_TX_ON); @@ -599,8 +592,12 @@ static int at86rf230_rx(struct at86rf230_local *lp) if (!skb) return -ENOMEM; - if (at86rf230_read_fbuf(lp, skb_put(skb, len), &len, &lqi)) + if (at86rf230_write_subreg(lp, SR_RX_PDT_DIS, 1) || + at86rf230_read_fbuf(lp, skb_put(skb, len), &len, &lqi) || + at86rf230_write_subreg(lp, SR_RX_SAFE_MODE, 1) || + at86rf230_write_subreg(lp, SR_RX_PDT_DIS, 0)) { goto err; + } if (len < 2) goto err; @@ -636,6 +633,7 @@ static void at86rf230_irqwork(struct work_struct *work) int rc; unsigned long flags; + spin_lock_irqsave(&lp->lock, flags); rc = at86rf230_read_subreg(lp, RG_IRQ_STATUS, 0xff, 0, &val); status |= val; @@ -645,33 +643,31 @@ static void at86rf230_irqwork(struct work_struct *work) status &= ~IRQ_TRX_UR; /* FIXME: possibly handle ???*/ if (status & IRQ_TRX_END) { - spin_lock_irqsave(&lp->lock, flags); status &= ~IRQ_TRX_END; if (lp->is_tx) { lp->is_tx = 0; - spin_unlock_irqrestore(&lp->lock, flags); complete(&lp->tx_complete); } else { - spin_unlock_irqrestore(&lp->lock, flags); at86rf230_rx(lp); } } - spin_lock_irqsave(&lp->lock, flags); - lp->irq_disabled = 0; + if (lp->irq_disabled) { + lp->irq_disabled = 0; + enable_irq(lp->spi->irq); + } spin_unlock_irqrestore(&lp->lock, flags); - - enable_irq(lp->spi->irq); } static irqreturn_t at86rf230_isr(int irq, void *data) { struct at86rf230_local *lp = data; - disable_irq_nosync(irq); - spin_lock(&lp->lock); - lp->irq_disabled = 1; + if (!lp->irq_disabled) { + disable_irq_nosync(irq); + lp->irq_disabled = 1; + } spin_unlock(&lp->lock); schedule_work(&lp->irqwork); diff --git a/trunk/drivers/infiniband/hw/mlx4/main.c b/trunk/drivers/infiniband/hw/mlx4/main.c index 8a3a2037b005..3530c41fcd1f 100644 --- a/trunk/drivers/infiniband/hw/mlx4/main.c +++ b/trunk/drivers/infiniband/hw/mlx4/main.c @@ -718,53 +718,26 @@ int mlx4_ib_add_mc(struct mlx4_ib_dev *mdev, struct mlx4_ib_qp *mqp, return ret; } -struct mlx4_ib_steering { - struct list_head list; - u64 reg_id; - union ib_gid gid; -}; - static int mlx4_ib_mcg_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) { int err; struct mlx4_ib_dev *mdev = to_mdev(ibqp->device); struct mlx4_ib_qp *mqp = to_mqp(ibqp); - u64 reg_id; - struct mlx4_ib_steering *ib_steering = NULL; - - if (mdev->dev->caps.steering_mode == - MLX4_STEERING_MODE_DEVICE_MANAGED) { - ib_steering = kmalloc(sizeof(*ib_steering), GFP_KERNEL); - if (!ib_steering) - return -ENOMEM; - } - err = mlx4_multicast_attach(mdev->dev, &mqp->mqp, gid->raw, mqp->port, - !!(mqp->flags & - MLX4_IB_QP_BLOCK_MULTICAST_LOOPBACK), - MLX4_PROT_IB_IPV6, ®_id); + err = mlx4_multicast_attach(mdev->dev, &mqp->mqp, gid->raw, + !!(mqp->flags & MLX4_IB_QP_BLOCK_MULTICAST_LOOPBACK), + MLX4_PROT_IB_IPV6); if (err) - goto err_malloc; + return err; err = add_gid_entry(ibqp, gid); if (err) goto err_add; - if (ib_steering) { - memcpy(ib_steering->gid.raw, gid->raw, 16); - ib_steering->reg_id = reg_id; - mutex_lock(&mqp->mutex); - list_add(&ib_steering->list, &mqp->steering_rules); - mutex_unlock(&mqp->mutex); - } return 0; err_add: - mlx4_multicast_detach(mdev->dev, &mqp->mqp, gid->raw, - MLX4_PROT_IB_IPV6, reg_id); -err_malloc: - kfree(ib_steering); - + mlx4_multicast_detach(mdev->dev, &mqp->mqp, gid->raw, MLX4_PROT_IB_IPV6); return err; } @@ -792,30 +765,9 @@ static int mlx4_ib_mcg_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) u8 mac[6]; struct net_device *ndev; struct mlx4_ib_gid_entry *ge; - u64 reg_id = 0; - - if (mdev->dev->caps.steering_mode == - MLX4_STEERING_MODE_DEVICE_MANAGED) { - struct mlx4_ib_steering *ib_steering; - - mutex_lock(&mqp->mutex); - list_for_each_entry(ib_steering, &mqp->steering_rules, list) { - if (!memcmp(ib_steering->gid.raw, gid->raw, 16)) { - list_del(&ib_steering->list); - break; - } - } - mutex_unlock(&mqp->mutex); - if (&ib_steering->list == &mqp->steering_rules) { - pr_err("Couldn't find reg_id for mgid. Steering rule is left attached\n"); - return -EINVAL; - } - reg_id = ib_steering->reg_id; - kfree(ib_steering); - } - err = mlx4_multicast_detach(mdev->dev, &mqp->mqp, gid->raw, - MLX4_PROT_IB_IPV6, reg_id); + err = mlx4_multicast_detach(mdev->dev, + &mqp->mqp, gid->raw, MLX4_PROT_IB_IPV6); if (err) return err; diff --git a/trunk/drivers/infiniband/hw/mlx4/mlx4_ib.h b/trunk/drivers/infiniband/hw/mlx4/mlx4_ib.h index 42df4f7a6a5b..ff36655d23d3 100644 --- a/trunk/drivers/infiniband/hw/mlx4/mlx4_ib.h +++ b/trunk/drivers/infiniband/hw/mlx4/mlx4_ib.h @@ -163,7 +163,6 @@ struct mlx4_ib_qp { u8 state; int mlx_type; struct list_head gid_list; - struct list_head steering_rules; }; struct mlx4_ib_srq { diff --git a/trunk/drivers/infiniband/hw/mlx4/qp.c b/trunk/drivers/infiniband/hw/mlx4/qp.c index 6af19f6c2b11..8d4ed24aef93 100644 --- a/trunk/drivers/infiniband/hw/mlx4/qp.c +++ b/trunk/drivers/infiniband/hw/mlx4/qp.c @@ -495,7 +495,6 @@ static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd, spin_lock_init(&qp->sq.lock); spin_lock_init(&qp->rq.lock); INIT_LIST_HEAD(&qp->gid_list); - INIT_LIST_HEAD(&qp->steering_rules); qp->state = IB_QPS_RESET; if (init_attr->sq_sig_type == IB_SIGNAL_ALL_WR) diff --git a/trunk/drivers/infiniband/ulp/ipoib/ipoib_cm.c b/trunk/drivers/infiniband/ulp/ipoib/ipoib_cm.c index 1ca732201f33..014504d8e43c 100644 --- a/trunk/drivers/infiniband/ulp/ipoib/ipoib_cm.c +++ b/trunk/drivers/infiniband/ulp/ipoib/ipoib_cm.c @@ -1397,7 +1397,7 @@ void ipoib_cm_skb_too_long(struct net_device *dev, struct sk_buff *skb, int e = skb_queue_empty(&priv->cm.skb_queue); if (skb_dst(skb)) - skb_dst(skb)->ops->update_pmtu(skb_dst(skb), NULL, skb, mtu); + skb_dst(skb)->ops->update_pmtu(skb_dst(skb), mtu); skb_queue_tail(&priv->cm.skb_queue, skb); if (e) diff --git a/trunk/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/trunk/drivers/infiniband/ulp/ipoib/ipoib_ib.c index f10221f40803..5c1bc995e560 100644 --- a/trunk/drivers/infiniband/ulp/ipoib/ipoib_ib.c +++ b/trunk/drivers/infiniband/ulp/ipoib/ipoib_ib.c @@ -123,7 +123,7 @@ static void ipoib_ud_skb_put_frags(struct ipoib_dev_priv *priv, skb_frag_size_set(frag, size); skb->data_len += size; - skb->truesize += PAGE_SIZE; + skb->truesize += size; } else skb_put(skb, length); @@ -156,18 +156,14 @@ static struct sk_buff *ipoib_alloc_rx_skb(struct net_device *dev, int id) struct ipoib_dev_priv *priv = netdev_priv(dev); struct sk_buff *skb; int buf_size; - int tailroom; u64 *mapping; - if (ipoib_ud_need_sg(priv->max_ib_mtu)) { + if (ipoib_ud_need_sg(priv->max_ib_mtu)) buf_size = IPOIB_UD_HEAD_SIZE; - tailroom = 128; /* reserve some tailroom for IP/TCP headers */ - } else { + else buf_size = IPOIB_UD_BUF_SIZE(priv->max_ib_mtu); - tailroom = 0; - } - skb = dev_alloc_skb(buf_size + tailroom + 4); + skb = dev_alloc_skb(buf_size + 4); if (unlikely(!skb)) return NULL; diff --git a/trunk/drivers/isdn/gigaset/capi.c b/trunk/drivers/isdn/gigaset/capi.c index 68452b768da2..27e4a3e21d64 100644 --- a/trunk/drivers/isdn/gigaset/capi.c +++ b/trunk/drivers/isdn/gigaset/capi.c @@ -288,7 +288,6 @@ static inline void dump_rawmsg(enum debuglevel level, const char *tag, * format CAPI IE as string */ -#ifdef CONFIG_GIGASET_DEBUG static const char *format_ie(const char *ie) { static char result[3 * MAX_FMT_IE_LEN]; @@ -314,7 +313,6 @@ static const char *format_ie(const char *ie) *--pout = 0; return result; } -#endif /* * emit DATA_B3_CONF message diff --git a/trunk/drivers/isdn/mISDN/stack.c b/trunk/drivers/isdn/mISDN/stack.c index 5f21f629b7ae..1a0ae4445ff2 100644 --- a/trunk/drivers/isdn/mISDN/stack.c +++ b/trunk/drivers/isdn/mISDN/stack.c @@ -135,8 +135,8 @@ send_layer2(struct mISDNstack *st, struct sk_buff *skb) skb = NULL; else if (*debug & DEBUG_SEND_ERR) printk(KERN_DEBUG - "%s mgr prim(%x) err %d\n", - __func__, hh->prim, ret); + "%s ch%d mgr prim(%x) addr(%x) err %d\n", + __func__, ch->nr, hh->prim, ch->addr, ret); } out: mutex_unlock(&st->lmutex); diff --git a/trunk/drivers/misc/Kconfig b/trunk/drivers/misc/Kconfig index 154f3ef07631..2661f6e366f9 100644 --- a/trunk/drivers/misc/Kconfig +++ b/trunk/drivers/misc/Kconfig @@ -511,6 +511,7 @@ config USB_SWITCH_FSA9480 source "drivers/misc/c2port/Kconfig" source "drivers/misc/eeprom/Kconfig" source "drivers/misc/cb710/Kconfig" +source "drivers/misc/iwmc3200top/Kconfig" source "drivers/misc/ti-st/Kconfig" source "drivers/misc/lis3lv02d/Kconfig" source "drivers/misc/carma/Kconfig" diff --git a/trunk/drivers/misc/Makefile b/trunk/drivers/misc/Makefile index b88df7a350b8..456972faaeb3 100644 --- a/trunk/drivers/misc/Makefile +++ b/trunk/drivers/misc/Makefile @@ -36,6 +36,7 @@ obj-$(CONFIG_EP93XX_PWM) += ep93xx_pwm.o obj-$(CONFIG_DS1682) += ds1682.o obj-$(CONFIG_TI_DAC7512) += ti_dac7512.o obj-$(CONFIG_C2PORT) += c2port/ +obj-$(CONFIG_IWMC3200TOP) += iwmc3200top/ obj-$(CONFIG_HMC6352) += hmc6352.o obj-y += eeprom/ obj-y += cb710/ diff --git a/trunk/drivers/misc/iwmc3200top/Kconfig b/trunk/drivers/misc/iwmc3200top/Kconfig new file mode 100644 index 000000000000..9e4b88fb57f1 --- /dev/null +++ b/trunk/drivers/misc/iwmc3200top/Kconfig @@ -0,0 +1,20 @@ +config IWMC3200TOP + tristate "Intel Wireless MultiCom Top Driver" + depends on MMC && EXPERIMENTAL + select FW_LOADER + ---help--- + Intel Wireless MultiCom 3200 Top driver is responsible for + for firmware load and enabled coms enumeration + +config IWMC3200TOP_DEBUG + bool "Enable full debug output of iwmc3200top Driver" + depends on IWMC3200TOP + ---help--- + Enable full debug output of iwmc3200top Driver + +config IWMC3200TOP_DEBUGFS + bool "Enable Debugfs debugging interface for iwmc3200top" + depends on IWMC3200TOP + ---help--- + Enable creation of debugfs files for iwmc3200top + diff --git a/trunk/drivers/misc/iwmc3200top/Makefile b/trunk/drivers/misc/iwmc3200top/Makefile new file mode 100644 index 000000000000..fbf53fb4634e --- /dev/null +++ b/trunk/drivers/misc/iwmc3200top/Makefile @@ -0,0 +1,29 @@ +# iwmc3200top - Intel Wireless MultiCom 3200 Top Driver +# drivers/misc/iwmc3200top/Makefile +# +# Copyright (C) 2009 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 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., 51 Franklin Street, Fifth Floor, Boston, MA +# 02110-1301, USA. +# +# +# Author Name: Maxim Grabarnik +# - +# +# + +obj-$(CONFIG_IWMC3200TOP) += iwmc3200top.o +iwmc3200top-objs := main.o fw-download.o +iwmc3200top-$(CONFIG_IWMC3200TOP_DEBUG) += log.o +iwmc3200top-$(CONFIG_IWMC3200TOP_DEBUGFS) += debugfs.o diff --git a/trunk/drivers/misc/iwmc3200top/debugfs.c b/trunk/drivers/misc/iwmc3200top/debugfs.c new file mode 100644 index 000000000000..62fbaec48207 --- /dev/null +++ b/trunk/drivers/misc/iwmc3200top/debugfs.c @@ -0,0 +1,137 @@ +/* + * iwmc3200top - Intel Wireless MultiCom 3200 Top Driver + * drivers/misc/iwmc3200top/debufs.c + * + * Copyright (C) 2009 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 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + * + * + * Author Name: Maxim Grabarnik + * - + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "iwmc3200top.h" +#include "fw-msg.h" +#include "log.h" +#include "debugfs.h" + + + +/* Constants definition */ +#define HEXADECIMAL_RADIX 16 + +/* Functions definition */ + + +#define DEBUGFS_ADD(name, parent) do { \ + dbgfs->dbgfs_##parent##_files.file_##name = \ + debugfs_create_file(#name, 0644, dbgfs->dir_##parent, priv, \ + &iwmct_dbgfs_##name##_ops); \ +} while (0) + +#define DEBUGFS_RM(name) do { \ + debugfs_remove(name); \ + name = NULL; \ +} while (0) + +#define DEBUGFS_READ_FUNC(name) \ +ssize_t iwmct_dbgfs_##name##_read(struct file *file, \ + char __user *user_buf, \ + size_t count, loff_t *ppos); + +#define DEBUGFS_WRITE_FUNC(name) \ +ssize_t iwmct_dbgfs_##name##_write(struct file *file, \ + const char __user *user_buf, \ + size_t count, loff_t *ppos); + +#define DEBUGFS_READ_FILE_OPS(name) \ + DEBUGFS_READ_FUNC(name) \ + static const struct file_operations iwmct_dbgfs_##name##_ops = { \ + .read = iwmct_dbgfs_##name##_read, \ + .open = iwmct_dbgfs_open_file_generic, \ + .llseek = generic_file_llseek, \ + }; + +#define DEBUGFS_WRITE_FILE_OPS(name) \ + DEBUGFS_WRITE_FUNC(name) \ + static const struct file_operations iwmct_dbgfs_##name##_ops = { \ + .write = iwmct_dbgfs_##name##_write, \ + .open = iwmct_dbgfs_open_file_generic, \ + .llseek = generic_file_llseek, \ + }; + +#define DEBUGFS_READ_WRITE_FILE_OPS(name) \ + DEBUGFS_READ_FUNC(name) \ + DEBUGFS_WRITE_FUNC(name) \ + static const struct file_operations iwmct_dbgfs_##name##_ops = {\ + .write = iwmct_dbgfs_##name##_write, \ + .read = iwmct_dbgfs_##name##_read, \ + .open = iwmct_dbgfs_open_file_generic, \ + .llseek = generic_file_llseek, \ + }; + + +/* Debugfs file ops definitions */ + +/* + * Create the debugfs files and directories + * + */ +void iwmct_dbgfs_register(struct iwmct_priv *priv, const char *name) +{ + struct iwmct_debugfs *dbgfs; + + dbgfs = kzalloc(sizeof(struct iwmct_debugfs), GFP_KERNEL); + if (!dbgfs) { + LOG_ERROR(priv, DEBUGFS, "failed to allocate %zd bytes\n", + sizeof(struct iwmct_debugfs)); + return; + } + + priv->dbgfs = dbgfs; + dbgfs->name = name; + dbgfs->dir_drv = debugfs_create_dir(name, NULL); + if (!dbgfs->dir_drv) { + LOG_ERROR(priv, DEBUGFS, "failed to create debugfs dir\n"); + return; + } + + return; +} + +/** + * Remove the debugfs files and directories + * + */ +void iwmct_dbgfs_unregister(struct iwmct_debugfs *dbgfs) +{ + if (!dbgfs) + return; + + DEBUGFS_RM(dbgfs->dir_drv); + kfree(dbgfs); + dbgfs = NULL; +} + diff --git a/trunk/drivers/misc/iwmc3200top/debugfs.h b/trunk/drivers/misc/iwmc3200top/debugfs.h new file mode 100644 index 000000000000..71d45759b40f --- /dev/null +++ b/trunk/drivers/misc/iwmc3200top/debugfs.h @@ -0,0 +1,58 @@ +/* + * iwmc3200top - Intel Wireless MultiCom 3200 Top Driver + * drivers/misc/iwmc3200top/debufs.h + * + * Copyright (C) 2009 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 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + * + * + * Author Name: Maxim Grabarnik + * - + * + */ + +#ifndef __DEBUGFS_H__ +#define __DEBUGFS_H__ + + +#ifdef CONFIG_IWMC3200TOP_DEBUGFS + +struct iwmct_debugfs { + const char *name; + struct dentry *dir_drv; + struct dir_drv_files { + } dbgfs_drv_files; +}; + +void iwmct_dbgfs_register(struct iwmct_priv *priv, const char *name); +void iwmct_dbgfs_unregister(struct iwmct_debugfs *dbgfs); + +#else /* CONFIG_IWMC3200TOP_DEBUGFS */ + +struct iwmct_debugfs; + +static inline void +iwmct_dbgfs_register(struct iwmct_priv *priv, const char *name) +{} + +static inline void +iwmct_dbgfs_unregister(struct iwmct_debugfs *dbgfs) +{} + +#endif /* CONFIG_IWMC3200TOP_DEBUGFS */ + +#endif /* __DEBUGFS_H__ */ + diff --git a/trunk/drivers/misc/iwmc3200top/fw-download.c b/trunk/drivers/misc/iwmc3200top/fw-download.c new file mode 100644 index 000000000000..e27afde6e99f --- /dev/null +++ b/trunk/drivers/misc/iwmc3200top/fw-download.c @@ -0,0 +1,358 @@ +/* + * iwmc3200top - Intel Wireless MultiCom 3200 Top Driver + * drivers/misc/iwmc3200top/fw-download.c + * + * Copyright (C) 2009 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 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + * + * + * Author Name: Maxim Grabarnik + * - + * + */ + +#include +#include +#include +#include + +#include "iwmc3200top.h" +#include "log.h" +#include "fw-msg.h" + +#define CHECKSUM_BYTES_NUM sizeof(u32) + +/** + init parser struct with file + */ +static int iwmct_fw_parser_init(struct iwmct_priv *priv, const u8 *file, + size_t file_size, size_t block_size) +{ + struct iwmct_parser *parser = &priv->parser; + struct iwmct_fw_hdr *fw_hdr = &parser->versions; + + LOG_TRACE(priv, FW_DOWNLOAD, "-->\n"); + + LOG_INFO(priv, FW_DOWNLOAD, "file_size=%zd\n", file_size); + + parser->file = file; + parser->file_size = file_size; + parser->cur_pos = 0; + parser->entry_point = 0; + parser->buf = kzalloc(block_size, GFP_KERNEL); + if (!parser->buf) { + LOG_ERROR(priv, FW_DOWNLOAD, "kzalloc error\n"); + return -ENOMEM; + } + parser->buf_size = block_size; + + /* extract fw versions */ + memcpy(fw_hdr, parser->file, sizeof(struct iwmct_fw_hdr)); + LOG_INFO(priv, FW_DOWNLOAD, "fw versions are:\n" + "top %u.%u.%u gps %u.%u.%u bt %u.%u.%u tic %s\n", + fw_hdr->top_major, fw_hdr->top_minor, fw_hdr->top_revision, + fw_hdr->gps_major, fw_hdr->gps_minor, fw_hdr->gps_revision, + fw_hdr->bt_major, fw_hdr->bt_minor, fw_hdr->bt_revision, + fw_hdr->tic_name); + + parser->cur_pos += sizeof(struct iwmct_fw_hdr); + + LOG_TRACE(priv, FW_DOWNLOAD, "<--\n"); + return 0; +} + +static bool iwmct_checksum(struct iwmct_priv *priv) +{ + struct iwmct_parser *parser = &priv->parser; + __le32 *file = (__le32 *)parser->file; + int i, pad, steps; + u32 accum = 0; + u32 checksum; + u32 mask = 0xffffffff; + + pad = (parser->file_size - CHECKSUM_BYTES_NUM) % 4; + steps = (parser->file_size - CHECKSUM_BYTES_NUM) / 4; + + LOG_INFO(priv, FW_DOWNLOAD, "pad=%d steps=%d\n", pad, steps); + + for (i = 0; i < steps; i++) + accum += le32_to_cpu(file[i]); + + if (pad) { + mask <<= 8 * (4 - pad); + accum += le32_to_cpu(file[steps]) & mask; + } + + checksum = get_unaligned_le32((__le32 *)(parser->file + + parser->file_size - CHECKSUM_BYTES_NUM)); + + LOG_INFO(priv, FW_DOWNLOAD, + "compare checksum accum=0x%x to checksum=0x%x\n", + accum, checksum); + + return checksum == accum; +} + +static int iwmct_parse_next_section(struct iwmct_priv *priv, const u8 **p_sec, + size_t *sec_size, __le32 *sec_addr) +{ + struct iwmct_parser *parser = &priv->parser; + struct iwmct_dbg *dbg = &priv->dbg; + struct iwmct_fw_sec_hdr *sec_hdr; + + LOG_TRACE(priv, FW_DOWNLOAD, "-->\n"); + + while (parser->cur_pos + sizeof(struct iwmct_fw_sec_hdr) + <= parser->file_size) { + + sec_hdr = (struct iwmct_fw_sec_hdr *) + (parser->file + parser->cur_pos); + parser->cur_pos += sizeof(struct iwmct_fw_sec_hdr); + + LOG_INFO(priv, FW_DOWNLOAD, + "sec hdr: type=%s addr=0x%x size=%d\n", + sec_hdr->type, sec_hdr->target_addr, + sec_hdr->data_size); + + if (strcmp(sec_hdr->type, "ENT") == 0) + parser->entry_point = le32_to_cpu(sec_hdr->target_addr); + else if (strcmp(sec_hdr->type, "LBL") == 0) + strcpy(dbg->label_fw, parser->file + parser->cur_pos); + else if (((strcmp(sec_hdr->type, "TOP") == 0) && + (priv->barker & BARKER_DNLOAD_TOP_MSK)) || + ((strcmp(sec_hdr->type, "GPS") == 0) && + (priv->barker & BARKER_DNLOAD_GPS_MSK)) || + ((strcmp(sec_hdr->type, "BTH") == 0) && + (priv->barker & BARKER_DNLOAD_BT_MSK))) { + *sec_addr = sec_hdr->target_addr; + *sec_size = le32_to_cpu(sec_hdr->data_size); + *p_sec = parser->file + parser->cur_pos; + parser->cur_pos += le32_to_cpu(sec_hdr->data_size); + return 1; + } else if (strcmp(sec_hdr->type, "LOG") != 0) + LOG_WARNING(priv, FW_DOWNLOAD, + "skipping section type %s\n", + sec_hdr->type); + + parser->cur_pos += le32_to_cpu(sec_hdr->data_size); + LOG_INFO(priv, FW_DOWNLOAD, + "finished with section cur_pos=%zd\n", parser->cur_pos); + } + + LOG_TRACE(priv, INIT, "<--\n"); + return 0; +} + +static int iwmct_download_section(struct iwmct_priv *priv, const u8 *p_sec, + size_t sec_size, __le32 addr) +{ + struct iwmct_parser *parser = &priv->parser; + struct iwmct_fw_load_hdr *hdr = (struct iwmct_fw_load_hdr *)parser->buf; + const u8 *cur_block = p_sec; + size_t sent = 0; + int cnt = 0; + int ret = 0; + u32 cmd = 0; + + LOG_TRACE(priv, FW_DOWNLOAD, "-->\n"); + LOG_INFO(priv, FW_DOWNLOAD, "Download address 0x%x size 0x%zx\n", + addr, sec_size); + + while (sent < sec_size) { + int i; + u32 chksm = 0; + u32 reset = atomic_read(&priv->reset); + /* actual FW data */ + u32 data_size = min(parser->buf_size - sizeof(*hdr), + sec_size - sent); + /* Pad to block size */ + u32 trans_size = (data_size + sizeof(*hdr) + + IWMC_SDIO_BLK_SIZE - 1) & + ~(IWMC_SDIO_BLK_SIZE - 1); + ++cnt; + + /* in case of reset, interrupt FW DOWNLAOD */ + if (reset) { + LOG_INFO(priv, FW_DOWNLOAD, + "Reset detected. Abort FW download!!!"); + ret = -ECANCELED; + goto exit; + } + + memset(parser->buf, 0, parser->buf_size); + cmd |= IWMC_OPCODE_WRITE << CMD_HDR_OPCODE_POS; + cmd |= IWMC_CMD_SIGNATURE << CMD_HDR_SIGNATURE_POS; + cmd |= (priv->dbg.direct ? 1 : 0) << CMD_HDR_DIRECT_ACCESS_POS; + cmd |= (priv->dbg.checksum ? 1 : 0) << CMD_HDR_USE_CHECKSUM_POS; + hdr->data_size = cpu_to_le32(data_size); + hdr->target_addr = addr; + + /* checksum is allowed for sizes divisible by 4 */ + if (data_size & 0x3) + cmd &= ~CMD_HDR_USE_CHECKSUM_MSK; + + memcpy(hdr->data, cur_block, data_size); + + + if (cmd & CMD_HDR_USE_CHECKSUM_MSK) { + + chksm = data_size + le32_to_cpu(addr) + cmd; + for (i = 0; i < data_size >> 2; i++) + chksm += ((u32 *)cur_block)[i]; + + hdr->block_chksm = cpu_to_le32(chksm); + LOG_INFO(priv, FW_DOWNLOAD, "Checksum = 0x%X\n", + hdr->block_chksm); + } + + LOG_INFO(priv, FW_DOWNLOAD, "trans#%d, len=%d, sent=%zd, " + "sec_size=%zd, startAddress 0x%X\n", + cnt, trans_size, sent, sec_size, addr); + + if (priv->dbg.dump) + LOG_HEXDUMP(FW_DOWNLOAD, parser->buf, trans_size); + + + hdr->cmd = cpu_to_le32(cmd); + /* send it down */ + /* TODO: add more proper sending and error checking */ + ret = iwmct_tx(priv, parser->buf, trans_size); + if (ret != 0) { + LOG_INFO(priv, FW_DOWNLOAD, + "iwmct_tx returned %d\n", ret); + goto exit; + } + + addr = cpu_to_le32(le32_to_cpu(addr) + data_size); + sent += data_size; + cur_block = p_sec + sent; + + if (priv->dbg.blocks && (cnt + 1) >= priv->dbg.blocks) { + LOG_INFO(priv, FW_DOWNLOAD, + "Block number limit is reached [%d]\n", + priv->dbg.blocks); + break; + } + } + + if (sent < sec_size) + ret = -EINVAL; +exit: + LOG_TRACE(priv, FW_DOWNLOAD, "<--\n"); + return ret; +} + +static int iwmct_kick_fw(struct iwmct_priv *priv, bool jump) +{ + struct iwmct_parser *parser = &priv->parser; + struct iwmct_fw_load_hdr *hdr = (struct iwmct_fw_load_hdr *)parser->buf; + int ret; + u32 cmd; + + LOG_TRACE(priv, FW_DOWNLOAD, "-->\n"); + + memset(parser->buf, 0, parser->buf_size); + cmd = IWMC_CMD_SIGNATURE << CMD_HDR_SIGNATURE_POS; + if (jump) { + cmd |= IWMC_OPCODE_JUMP << CMD_HDR_OPCODE_POS; + hdr->target_addr = cpu_to_le32(parser->entry_point); + LOG_INFO(priv, FW_DOWNLOAD, "jump address 0x%x\n", + parser->entry_point); + } else { + cmd |= IWMC_OPCODE_LAST_COMMAND << CMD_HDR_OPCODE_POS; + LOG_INFO(priv, FW_DOWNLOAD, "last command\n"); + } + + hdr->cmd = cpu_to_le32(cmd); + + LOG_HEXDUMP(FW_DOWNLOAD, parser->buf, sizeof(*hdr)); + /* send it down */ + /* TODO: add more proper sending and error checking */ + ret = iwmct_tx(priv, parser->buf, IWMC_SDIO_BLK_SIZE); + if (ret) + LOG_INFO(priv, FW_DOWNLOAD, "iwmct_tx returned %d", ret); + + LOG_TRACE(priv, FW_DOWNLOAD, "<--\n"); + return 0; +} + +int iwmct_fw_load(struct iwmct_priv *priv) +{ + const u8 *fw_name = FW_NAME(FW_API_VER); + const struct firmware *raw; + const u8 *pdata; + size_t len; + __le32 addr; + int ret; + + + LOG_INFO(priv, FW_DOWNLOAD, "barker download request 0x%x is:\n", + priv->barker); + LOG_INFO(priv, FW_DOWNLOAD, "******* Top FW %s requested ********\n", + (priv->barker & BARKER_DNLOAD_TOP_MSK) ? "was" : "not"); + LOG_INFO(priv, FW_DOWNLOAD, "******* GPS FW %s requested ********\n", + (priv->barker & BARKER_DNLOAD_GPS_MSK) ? "was" : "not"); + LOG_INFO(priv, FW_DOWNLOAD, "******* BT FW %s requested ********\n", + (priv->barker & BARKER_DNLOAD_BT_MSK) ? "was" : "not"); + + + /* get the firmware */ + ret = request_firmware(&raw, fw_name, &priv->func->dev); + if (ret < 0) { + LOG_ERROR(priv, FW_DOWNLOAD, "%s request_firmware failed %d\n", + fw_name, ret); + goto exit; + } + + if (raw->size < sizeof(struct iwmct_fw_sec_hdr)) { + LOG_ERROR(priv, FW_DOWNLOAD, "%s smaller then (%zd) (%zd)\n", + fw_name, sizeof(struct iwmct_fw_sec_hdr), raw->size); + goto exit; + } + + LOG_INFO(priv, FW_DOWNLOAD, "Read firmware '%s'\n", fw_name); + + /* clear parser struct */ + ret = iwmct_fw_parser_init(priv, raw->data, raw->size, priv->trans_len); + if (ret < 0) { + LOG_ERROR(priv, FW_DOWNLOAD, + "iwmct_parser_init failed: Reason %d\n", ret); + goto exit; + } + + if (!iwmct_checksum(priv)) { + LOG_ERROR(priv, FW_DOWNLOAD, "checksum error\n"); + ret = -EINVAL; + goto exit; + } + + /* download firmware to device */ + while (iwmct_parse_next_section(priv, &pdata, &len, &addr)) { + ret = iwmct_download_section(priv, pdata, len, addr); + if (ret) { + LOG_ERROR(priv, FW_DOWNLOAD, + "%s download section failed\n", fw_name); + goto exit; + } + } + + ret = iwmct_kick_fw(priv, !!(priv->barker & BARKER_DNLOAD_JUMP_MSK)); + +exit: + kfree(priv->parser.buf); + release_firmware(raw); + return ret; +} diff --git a/trunk/drivers/misc/iwmc3200top/fw-msg.h b/trunk/drivers/misc/iwmc3200top/fw-msg.h new file mode 100644 index 000000000000..9e26b75bd482 --- /dev/null +++ b/trunk/drivers/misc/iwmc3200top/fw-msg.h @@ -0,0 +1,113 @@ +/* + * iwmc3200top - Intel Wireless MultiCom 3200 Top Driver + * drivers/misc/iwmc3200top/fw-msg.h + * + * Copyright (C) 2009 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 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + * + * + * Author Name: Maxim Grabarnik + * - + * + */ + +#ifndef __FWMSG_H__ +#define __FWMSG_H__ + +#define COMM_TYPE_D2H 0xFF +#define COMM_TYPE_H2D 0xEE + +#define COMM_CATEGORY_OPERATIONAL 0x00 +#define COMM_CATEGORY_DEBUG 0x01 +#define COMM_CATEGORY_TESTABILITY 0x02 +#define COMM_CATEGORY_DIAGNOSTICS 0x03 + +#define OP_DBG_ZSTR_MSG cpu_to_le16(0x1A) + +#define FW_LOG_SRC_MAX 32 +#define FW_LOG_SRC_ALL 255 + +#define FW_STRING_TABLE_ADDR cpu_to_le32(0x0C000000) + +#define CMD_DBG_LOG_LEVEL cpu_to_le16(0x0001) +#define CMD_TST_DEV_RESET cpu_to_le16(0x0060) +#define CMD_TST_FUNC_RESET cpu_to_le16(0x0062) +#define CMD_TST_IFACE_RESET cpu_to_le16(0x0064) +#define CMD_TST_CPU_UTILIZATION cpu_to_le16(0x0065) +#define CMD_TST_TOP_DEEP_SLEEP cpu_to_le16(0x0080) +#define CMD_TST_WAKEUP cpu_to_le16(0x0081) +#define CMD_TST_FUNC_WAKEUP cpu_to_le16(0x0082) +#define CMD_TST_FUNC_DEEP_SLEEP_REQUEST cpu_to_le16(0x0083) +#define CMD_TST_GET_MEM_DUMP cpu_to_le16(0x0096) + +#define OP_OPR_ALIVE cpu_to_le16(0x0010) +#define OP_OPR_CMD_ACK cpu_to_le16(0x001F) +#define OP_OPR_CMD_NACK cpu_to_le16(0x0020) +#define OP_TST_MEM_DUMP cpu_to_le16(0x0043) + +#define CMD_FLAG_PADDING_256 0x80 + +#define FW_HCMD_BLOCK_SIZE 256 + +struct msg_hdr { + u8 type; + u8 category; + __le16 opcode; + u8 seqnum; + u8 flags; + __le16 length; +} __attribute__((__packed__)); + +struct log_hdr { + __le32 timestamp; + u8 severity; + u8 logsource; + __le16 reserved; +} __attribute__((__packed__)); + +struct mdump_hdr { + u8 dmpid; + u8 frag; + __le16 size; + __le32 addr; +} __attribute__((__packed__)); + +struct top_msg { + struct msg_hdr hdr; + union { + /* D2H messages */ + struct { + struct log_hdr log_hdr; + u8 data[1]; + } __attribute__((__packed__)) log; + + struct { + struct log_hdr log_hdr; + struct mdump_hdr md_hdr; + u8 data[1]; + } __attribute__((__packed__)) mdump; + + /* H2D messages */ + struct { + u8 logsource; + u8 sevmask; + } __attribute__((__packed__)) logdefs[FW_LOG_SRC_MAX]; + struct mdump_hdr mdump_req; + } u; +} __attribute__((__packed__)); + + +#endif /* __FWMSG_H__ */ diff --git a/trunk/drivers/misc/iwmc3200top/iwmc3200top.h b/trunk/drivers/misc/iwmc3200top/iwmc3200top.h new file mode 100644 index 000000000000..620973ed8bf9 --- /dev/null +++ b/trunk/drivers/misc/iwmc3200top/iwmc3200top.h @@ -0,0 +1,205 @@ +/* + * iwmc3200top - Intel Wireless MultiCom 3200 Top Driver + * drivers/misc/iwmc3200top/iwmc3200top.h + * + * Copyright (C) 2009 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 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + * + * + * Author Name: Maxim Grabarnik + * - + * + */ + +#ifndef __IWMC3200TOP_H__ +#define __IWMC3200TOP_H__ + +#include + +#define DRV_NAME "iwmc3200top" +#define FW_API_VER 1 +#define _FW_NAME(api) DRV_NAME "." #api ".fw" +#define FW_NAME(api) _FW_NAME(api) + +#define IWMC_SDIO_BLK_SIZE 256 +#define IWMC_DEFAULT_TR_BLK 64 +#define IWMC_SDIO_DATA_ADDR 0x0 +#define IWMC_SDIO_INTR_ENABLE_ADDR 0x14 +#define IWMC_SDIO_INTR_STATUS_ADDR 0x13 +#define IWMC_SDIO_INTR_CLEAR_ADDR 0x13 +#define IWMC_SDIO_INTR_GET_SIZE_ADDR 0x2C + +#define COMM_HUB_HEADER_LENGTH 16 +#define LOGGER_HEADER_LENGTH 10 + + +#define BARKER_DNLOAD_BT_POS 0 +#define BARKER_DNLOAD_BT_MSK BIT(BARKER_DNLOAD_BT_POS) +#define BARKER_DNLOAD_GPS_POS 1 +#define BARKER_DNLOAD_GPS_MSK BIT(BARKER_DNLOAD_GPS_POS) +#define BARKER_DNLOAD_TOP_POS 2 +#define BARKER_DNLOAD_TOP_MSK BIT(BARKER_DNLOAD_TOP_POS) +#define BARKER_DNLOAD_RESERVED1_POS 3 +#define BARKER_DNLOAD_RESERVED1_MSK BIT(BARKER_DNLOAD_RESERVED1_POS) +#define BARKER_DNLOAD_JUMP_POS 4 +#define BARKER_DNLOAD_JUMP_MSK BIT(BARKER_DNLOAD_JUMP_POS) +#define BARKER_DNLOAD_SYNC_POS 5 +#define BARKER_DNLOAD_SYNC_MSK BIT(BARKER_DNLOAD_SYNC_POS) +#define BARKER_DNLOAD_RESERVED2_POS 6 +#define BARKER_DNLOAD_RESERVED2_MSK (0x3 << BARKER_DNLOAD_RESERVED2_POS) +#define BARKER_DNLOAD_BARKER_POS 8 +#define BARKER_DNLOAD_BARKER_MSK (0xffffff << BARKER_DNLOAD_BARKER_POS) + +#define IWMC_BARKER_REBOOT (0xdeadbe << BARKER_DNLOAD_BARKER_POS) +/* whole field barker */ +#define IWMC_BARKER_ACK 0xfeedbabe + +#define IWMC_CMD_SIGNATURE 0xcbbc + +#define CMD_HDR_OPCODE_POS 0 +#define CMD_HDR_OPCODE_MSK_MSK (0xf << CMD_HDR_OPCODE_MSK_POS) +#define CMD_HDR_RESPONSE_CODE_POS 4 +#define CMD_HDR_RESPONSE_CODE_MSK (0xf << CMD_HDR_RESPONSE_CODE_POS) +#define CMD_HDR_USE_CHECKSUM_POS 8 +#define CMD_HDR_USE_CHECKSUM_MSK BIT(CMD_HDR_USE_CHECKSUM_POS) +#define CMD_HDR_RESPONSE_REQUIRED_POS 9 +#define CMD_HDR_RESPONSE_REQUIRED_MSK BIT(CMD_HDR_RESPONSE_REQUIRED_POS) +#define CMD_HDR_DIRECT_ACCESS_POS 10 +#define CMD_HDR_DIRECT_ACCESS_MSK BIT(CMD_HDR_DIRECT_ACCESS_POS) +#define CMD_HDR_RESERVED_POS 11 +#define CMD_HDR_RESERVED_MSK BIT(0x1f << CMD_HDR_RESERVED_POS) +#define CMD_HDR_SIGNATURE_POS 16 +#define CMD_HDR_SIGNATURE_MSK BIT(0xffff << CMD_HDR_SIGNATURE_POS) + +enum { + IWMC_OPCODE_PING = 0, + IWMC_OPCODE_READ = 1, + IWMC_OPCODE_WRITE = 2, + IWMC_OPCODE_JUMP = 3, + IWMC_OPCODE_REBOOT = 4, + IWMC_OPCODE_PERSISTENT_WRITE = 5, + IWMC_OPCODE_PERSISTENT_READ = 6, + IWMC_OPCODE_READ_MODIFY_WRITE = 7, + IWMC_OPCODE_LAST_COMMAND = 15 +}; + +struct iwmct_fw_load_hdr { + __le32 cmd; + __le32 target_addr; + __le32 data_size; + __le32 block_chksm; + u8 data[0]; +}; + +/** + * struct iwmct_fw_hdr + * holds all sw components versions + */ +struct iwmct_fw_hdr { + u8 top_major; + u8 top_minor; + u8 top_revision; + u8 gps_major; + u8 gps_minor; + u8 gps_revision; + u8 bt_major; + u8 bt_minor; + u8 bt_revision; + u8 tic_name[31]; +}; + +/** + * struct iwmct_fw_sec_hdr + * @type: function type + * @data_size: section's data size + * @target_addr: download address + */ +struct iwmct_fw_sec_hdr { + u8 type[4]; + __le32 data_size; + __le32 target_addr; +}; + +/** + * struct iwmct_parser + * @file: fw image + * @file_size: fw size + * @cur_pos: position in file + * @buf: temp buf for download + * @buf_size: size of buf + * @entry_point: address to jump in fw kick-off + */ +struct iwmct_parser { + const u8 *file; + size_t file_size; + size_t cur_pos; + u8 *buf; + size_t buf_size; + u32 entry_point; + struct iwmct_fw_hdr versions; +}; + + +struct iwmct_work_struct { + struct list_head list; + ssize_t iosize; +}; + +struct iwmct_dbg { + int blocks; + bool dump; + bool jump; + bool direct; + bool checksum; + bool fw_download; + int block_size; + int download_trans_blks; + + char label_fw[256]; +}; + +struct iwmct_debugfs; + +struct iwmct_priv { + struct sdio_func *func; + struct iwmct_debugfs *dbgfs; + struct iwmct_parser parser; + atomic_t reset; + atomic_t dev_sync; + u32 trans_len; + u32 barker; + struct iwmct_dbg dbg; + + /* drivers work items */ + struct work_struct bus_rescan_worker; + struct work_struct isr_worker; + + /* drivers wait queue */ + wait_queue_head_t wait_q; + + /* rx request list */ + struct list_head read_req_list; +}; + +extern int iwmct_tx(struct iwmct_priv *priv, void *src, int count); +extern int iwmct_fw_load(struct iwmct_priv *priv); + +extern void iwmct_dbg_init_params(struct iwmct_priv *drv); +extern void iwmct_dbg_init_drv_attrs(struct device_driver *drv); +extern void iwmct_dbg_remove_drv_attrs(struct device_driver *drv); +extern int iwmct_send_hcmd(struct iwmct_priv *priv, u8 *cmd, u16 len); + +#endif /* __IWMC3200TOP_H__ */ diff --git a/trunk/drivers/misc/iwmc3200top/log.c b/trunk/drivers/misc/iwmc3200top/log.c new file mode 100644 index 000000000000..a36a55a49cac --- /dev/null +++ b/trunk/drivers/misc/iwmc3200top/log.c @@ -0,0 +1,348 @@ +/* + * iwmc3200top - Intel Wireless MultiCom 3200 Top Driver + * drivers/misc/iwmc3200top/log.c + * + * Copyright (C) 2009 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 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + * + * + * Author Name: Maxim Grabarnik + * - + * + */ + +#include +#include +#include +#include +#include "fw-msg.h" +#include "iwmc3200top.h" +#include "log.h" + +/* Maximal hexadecimal string size of the FW memdump message */ +#define LOG_MSG_SIZE_MAX 12400 + +/* iwmct_logdefs is a global used by log macros */ +u8 iwmct_logdefs[LOG_SRC_MAX]; +static u8 iwmct_fw_logdefs[FW_LOG_SRC_MAX]; + + +static int _log_set_log_filter(u8 *logdefs, int size, u8 src, u8 logmask) +{ + int i; + + if (src < size) + logdefs[src] = logmask; + else if (src == LOG_SRC_ALL) + for (i = 0; i < size; i++) + logdefs[i] = logmask; + else + return -1; + + return 0; +} + + +int iwmct_log_set_filter(u8 src, u8 logmask) +{ + return _log_set_log_filter(iwmct_logdefs, LOG_SRC_MAX, src, logmask); +} + + +int iwmct_log_set_fw_filter(u8 src, u8 logmask) +{ + return _log_set_log_filter(iwmct_fw_logdefs, + FW_LOG_SRC_MAX, src, logmask); +} + + +static int log_msg_format_hex(char *str, int slen, u8 *ibuf, + int ilen, char *pref) +{ + int pos = 0; + int i; + int len; + + for (pos = 0, i = 0; pos < slen - 2 && pref[i] != '\0'; i++, pos++) + str[pos] = pref[i]; + + for (i = 0; pos < slen - 2 && i < ilen; pos += len, i++) + len = snprintf(&str[pos], slen - pos - 1, " %2.2X", ibuf[i]); + + if (i < ilen) + return -1; + + return 0; +} + +/* NOTE: This function is not thread safe. + Currently it's called only from sdio rx worker - no race there +*/ +void iwmct_log_top_message(struct iwmct_priv *priv, u8 *buf, int len) +{ + struct top_msg *msg; + static char logbuf[LOG_MSG_SIZE_MAX]; + + msg = (struct top_msg *)buf; + + if (len < sizeof(msg->hdr) + sizeof(msg->u.log.log_hdr)) { + LOG_ERROR(priv, FW_MSG, "Log message from TOP " + "is too short %d (expected %zd)\n", + len, sizeof(msg->hdr) + sizeof(msg->u.log.log_hdr)); + return; + } + + if (!(iwmct_fw_logdefs[msg->u.log.log_hdr.logsource] & + BIT(msg->u.log.log_hdr.severity)) || + !(iwmct_logdefs[LOG_SRC_FW_MSG] & BIT(msg->u.log.log_hdr.severity))) + return; + + switch (msg->hdr.category) { + case COMM_CATEGORY_TESTABILITY: + if (!(iwmct_logdefs[LOG_SRC_TST] & + BIT(msg->u.log.log_hdr.severity))) + return; + if (log_msg_format_hex(logbuf, LOG_MSG_SIZE_MAX, buf, + le16_to_cpu(msg->hdr.length) + + sizeof(msg->hdr), "")) + LOG_WARNING(priv, TST, + "TOP TST message is too long, truncating..."); + LOG_WARNING(priv, TST, "%s\n", logbuf); + break; + case COMM_CATEGORY_DEBUG: + if (msg->hdr.opcode == OP_DBG_ZSTR_MSG) + LOG_INFO(priv, FW_MSG, "%s %s", "", + ((u8 *)msg) + sizeof(msg->hdr) + + sizeof(msg->u.log.log_hdr)); + else { + if (log_msg_format_hex(logbuf, LOG_MSG_SIZE_MAX, buf, + le16_to_cpu(msg->hdr.length) + + sizeof(msg->hdr), + "")) + LOG_WARNING(priv, FW_MSG, + "TOP DBG message is too long," + "truncating..."); + LOG_WARNING(priv, FW_MSG, "%s\n", logbuf); + } + break; + default: + break; + } +} + +static int _log_get_filter_str(u8 *logdefs, int logdefsz, char *buf, int size) +{ + int i, pos, len; + for (i = 0, pos = 0; (pos < size-1) && (i < logdefsz); i++) { + len = snprintf(&buf[pos], size - pos - 1, "0x%02X%02X,", + i, logdefs[i]); + pos += len; + } + buf[pos-1] = '\n'; + buf[pos] = '\0'; + + if (i < logdefsz) + return -1; + return 0; +} + +int log_get_filter_str(char *buf, int size) +{ + return _log_get_filter_str(iwmct_logdefs, LOG_SRC_MAX, buf, size); +} + +int log_get_fw_filter_str(char *buf, int size) +{ + return _log_get_filter_str(iwmct_fw_logdefs, FW_LOG_SRC_MAX, buf, size); +} + +#define HEXADECIMAL_RADIX 16 +#define LOG_SRC_FORMAT 7 /* log level is in format of "0xXXXX," */ + +ssize_t show_iwmct_log_level(struct device *d, + struct device_attribute *attr, char *buf) +{ + struct iwmct_priv *priv = dev_get_drvdata(d); + char *str_buf; + int buf_size; + ssize_t ret; + + buf_size = (LOG_SRC_FORMAT * LOG_SRC_MAX) + 1; + str_buf = kzalloc(buf_size, GFP_KERNEL); + if (!str_buf) { + LOG_ERROR(priv, DEBUGFS, + "failed to allocate %d bytes\n", buf_size); + ret = -ENOMEM; + goto exit; + } + + if (log_get_filter_str(str_buf, buf_size) < 0) { + ret = -EINVAL; + goto exit; + } + + ret = sprintf(buf, "%s", str_buf); + +exit: + kfree(str_buf); + return ret; +} + +ssize_t store_iwmct_log_level(struct device *d, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct iwmct_priv *priv = dev_get_drvdata(d); + char *token, *str_buf = NULL; + long val; + ssize_t ret = count; + u8 src, mask; + + if (!count) + goto exit; + + str_buf = kzalloc(count, GFP_KERNEL); + if (!str_buf) { + LOG_ERROR(priv, DEBUGFS, + "failed to allocate %zd bytes\n", count); + ret = -ENOMEM; + goto exit; + } + + memcpy(str_buf, buf, count); + + while ((token = strsep(&str_buf, ",")) != NULL) { + while (isspace(*token)) + ++token; + if (strict_strtol(token, HEXADECIMAL_RADIX, &val)) { + LOG_ERROR(priv, DEBUGFS, + "failed to convert string to long %s\n", + token); + ret = -EINVAL; + goto exit; + } + + mask = val & 0xFF; + src = (val & 0XFF00) >> 8; + iwmct_log_set_filter(src, mask); + } + +exit: + kfree(str_buf); + return ret; +} + +ssize_t show_iwmct_log_level_fw(struct device *d, + struct device_attribute *attr, char *buf) +{ + struct iwmct_priv *priv = dev_get_drvdata(d); + char *str_buf; + int buf_size; + ssize_t ret; + + buf_size = (LOG_SRC_FORMAT * FW_LOG_SRC_MAX) + 2; + + str_buf = kzalloc(buf_size, GFP_KERNEL); + if (!str_buf) { + LOG_ERROR(priv, DEBUGFS, + "failed to allocate %d bytes\n", buf_size); + ret = -ENOMEM; + goto exit; + } + + if (log_get_fw_filter_str(str_buf, buf_size) < 0) { + ret = -EINVAL; + goto exit; + } + + ret = sprintf(buf, "%s", str_buf); + +exit: + kfree(str_buf); + return ret; +} + +ssize_t store_iwmct_log_level_fw(struct device *d, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct iwmct_priv *priv = dev_get_drvdata(d); + struct top_msg cmd; + char *token, *str_buf = NULL; + ssize_t ret = count; + u16 cmdlen = 0; + int i; + long val; + u8 src, mask; + + if (!count) + goto exit; + + str_buf = kzalloc(count, GFP_KERNEL); + if (!str_buf) { + LOG_ERROR(priv, DEBUGFS, + "failed to allocate %zd bytes\n", count); + ret = -ENOMEM; + goto exit; + } + + memcpy(str_buf, buf, count); + + cmd.hdr.type = COMM_TYPE_H2D; + cmd.hdr.category = COMM_CATEGORY_DEBUG; + cmd.hdr.opcode = CMD_DBG_LOG_LEVEL; + + for (i = 0; ((token = strsep(&str_buf, ",")) != NULL) && + (i < FW_LOG_SRC_MAX); i++) { + + while (isspace(*token)) + ++token; + + if (strict_strtol(token, HEXADECIMAL_RADIX, &val)) { + LOG_ERROR(priv, DEBUGFS, + "failed to convert string to long %s\n", + token); + ret = -EINVAL; + goto exit; + } + + mask = val & 0xFF; /* LSB */ + src = (val & 0XFF00) >> 8; /* 2nd least significant byte. */ + iwmct_log_set_fw_filter(src, mask); + + cmd.u.logdefs[i].logsource = src; + cmd.u.logdefs[i].sevmask = mask; + } + + cmd.hdr.length = cpu_to_le16(i * sizeof(cmd.u.logdefs[0])); + cmdlen = (i * sizeof(cmd.u.logdefs[0]) + sizeof(cmd.hdr)); + + ret = iwmct_send_hcmd(priv, (u8 *)&cmd, cmdlen); + if (ret) { + LOG_ERROR(priv, DEBUGFS, + "Failed to send %d bytes of fwcmd, ret=%zd\n", + cmdlen, ret); + goto exit; + } else + LOG_INFO(priv, DEBUGFS, "fwcmd sent (%d bytes)\n", cmdlen); + + ret = count; + +exit: + kfree(str_buf); + return ret; +} + diff --git a/trunk/drivers/misc/iwmc3200top/log.h b/trunk/drivers/misc/iwmc3200top/log.h new file mode 100644 index 000000000000..4434bb16cea7 --- /dev/null +++ b/trunk/drivers/misc/iwmc3200top/log.h @@ -0,0 +1,171 @@ +/* + * iwmc3200top - Intel Wireless MultiCom 3200 Top Driver + * drivers/misc/iwmc3200top/log.h + * + * Copyright (C) 2009 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 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + * + * + * Author Name: Maxim Grabarnik + * - + * + */ + +#ifndef __LOG_H__ +#define __LOG_H__ + + +/* log severity: + * The log levels here match FW log levels + * so values need to stay as is */ +#define LOG_SEV_CRITICAL 0 +#define LOG_SEV_ERROR 1 +#define LOG_SEV_WARNING 2 +#define LOG_SEV_INFO 3 +#define LOG_SEV_INFOEX 4 + +/* Log levels not defined for FW */ +#define LOG_SEV_TRACE 5 +#define LOG_SEV_DUMP 6 + +#define LOG_SEV_FW_FILTER_ALL \ + (BIT(LOG_SEV_CRITICAL) | \ + BIT(LOG_SEV_ERROR) | \ + BIT(LOG_SEV_WARNING) | \ + BIT(LOG_SEV_INFO) | \ + BIT(LOG_SEV_INFOEX)) + +#define LOG_SEV_FILTER_ALL \ + (BIT(LOG_SEV_CRITICAL) | \ + BIT(LOG_SEV_ERROR) | \ + BIT(LOG_SEV_WARNING) | \ + BIT(LOG_SEV_INFO) | \ + BIT(LOG_SEV_INFOEX) | \ + BIT(LOG_SEV_TRACE) | \ + BIT(LOG_SEV_DUMP)) + +/* log source */ +#define LOG_SRC_INIT 0 +#define LOG_SRC_DEBUGFS 1 +#define LOG_SRC_FW_DOWNLOAD 2 +#define LOG_SRC_FW_MSG 3 +#define LOG_SRC_TST 4 +#define LOG_SRC_IRQ 5 + +#define LOG_SRC_MAX 6 +#define LOG_SRC_ALL 0xFF + +/** + * Default intitialization runtime log level + */ +#ifndef LOG_SEV_FILTER_RUNTIME +#define LOG_SEV_FILTER_RUNTIME \ + (BIT(LOG_SEV_CRITICAL) | \ + BIT(LOG_SEV_ERROR) | \ + BIT(LOG_SEV_WARNING)) +#endif + +#ifndef FW_LOG_SEV_FILTER_RUNTIME +#define FW_LOG_SEV_FILTER_RUNTIME LOG_SEV_FILTER_ALL +#endif + +#ifdef CONFIG_IWMC3200TOP_DEBUG +/** + * Log macros + */ + +#define priv2dev(priv) (&(priv->func)->dev) + +#define LOG_CRITICAL(priv, src, fmt, args...) \ +do { \ + if (iwmct_logdefs[LOG_SRC_ ## src] & BIT(LOG_SEV_CRITICAL)) \ + dev_crit(priv2dev(priv), "%s %d: " fmt, \ + __func__, __LINE__, ##args); \ +} while (0) + +#define LOG_ERROR(priv, src, fmt, args...) \ +do { \ + if (iwmct_logdefs[LOG_SRC_ ## src] & BIT(LOG_SEV_ERROR)) \ + dev_err(priv2dev(priv), "%s %d: " fmt, \ + __func__, __LINE__, ##args); \ +} while (0) + +#define LOG_WARNING(priv, src, fmt, args...) \ +do { \ + if (iwmct_logdefs[LOG_SRC_ ## src] & BIT(LOG_SEV_WARNING)) \ + dev_warn(priv2dev(priv), "%s %d: " fmt, \ + __func__, __LINE__, ##args); \ +} while (0) + +#define LOG_INFO(priv, src, fmt, args...) \ +do { \ + if (iwmct_logdefs[LOG_SRC_ ## src] & BIT(LOG_SEV_INFO)) \ + dev_info(priv2dev(priv), "%s %d: " fmt, \ + __func__, __LINE__, ##args); \ +} while (0) + +#define LOG_TRACE(priv, src, fmt, args...) \ +do { \ + if (iwmct_logdefs[LOG_SRC_ ## src] & BIT(LOG_SEV_TRACE)) \ + dev_dbg(priv2dev(priv), "%s %d: " fmt, \ + __func__, __LINE__, ##args); \ +} while (0) + +#define LOG_HEXDUMP(src, ptr, len) \ +do { \ + if (iwmct_logdefs[LOG_SRC_ ## src] & BIT(LOG_SEV_DUMP)) \ + print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_NONE, \ + 16, 1, ptr, len, false); \ +} while (0) + +void iwmct_log_top_message(struct iwmct_priv *priv, u8 *buf, int len); + +extern u8 iwmct_logdefs[]; + +int iwmct_log_set_filter(u8 src, u8 logmask); +int iwmct_log_set_fw_filter(u8 src, u8 logmask); + +ssize_t show_iwmct_log_level(struct device *d, + struct device_attribute *attr, char *buf); +ssize_t store_iwmct_log_level(struct device *d, + struct device_attribute *attr, + const char *buf, size_t count); +ssize_t show_iwmct_log_level_fw(struct device *d, + struct device_attribute *attr, char *buf); +ssize_t store_iwmct_log_level_fw(struct device *d, + struct device_attribute *attr, + const char *buf, size_t count); + +#else + +#define LOG_CRITICAL(priv, src, fmt, args...) +#define LOG_ERROR(priv, src, fmt, args...) +#define LOG_WARNING(priv, src, fmt, args...) +#define LOG_INFO(priv, src, fmt, args...) +#define LOG_TRACE(priv, src, fmt, args...) +#define LOG_HEXDUMP(src, ptr, len) + +static inline void iwmct_log_top_message(struct iwmct_priv *priv, + u8 *buf, int len) {} +static inline int iwmct_log_set_filter(u8 src, u8 logmask) { return 0; } +static inline int iwmct_log_set_fw_filter(u8 src, u8 logmask) { return 0; } + +#endif /* CONFIG_IWMC3200TOP_DEBUG */ + +int log_get_filter_str(char *buf, int size); +int log_get_fw_filter_str(char *buf, int size); + +#endif /* __LOG_H__ */ diff --git a/trunk/drivers/misc/iwmc3200top/main.c b/trunk/drivers/misc/iwmc3200top/main.c new file mode 100644 index 000000000000..701eb600b127 --- /dev/null +++ b/trunk/drivers/misc/iwmc3200top/main.c @@ -0,0 +1,662 @@ +/* + * iwmc3200top - Intel Wireless MultiCom 3200 Top Driver + * drivers/misc/iwmc3200top/main.c + * + * Copyright (C) 2009 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 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + * + * + * Author Name: Maxim Grabarnik + * - + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "iwmc3200top.h" +#include "log.h" +#include "fw-msg.h" +#include "debugfs.h" + + +#define DRIVER_DESCRIPTION "Intel(R) IWMC 3200 Top Driver" +#define DRIVER_COPYRIGHT "Copyright (c) 2008 Intel Corporation." + +#define DRIVER_VERSION "0.1.62" + +MODULE_DESCRIPTION(DRIVER_DESCRIPTION); +MODULE_VERSION(DRIVER_VERSION); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR(DRIVER_COPYRIGHT); +MODULE_FIRMWARE(FW_NAME(FW_API_VER)); + + +static inline int __iwmct_tx(struct iwmct_priv *priv, void *src, int count) +{ + return sdio_memcpy_toio(priv->func, IWMC_SDIO_DATA_ADDR, src, count); + +} +int iwmct_tx(struct iwmct_priv *priv, void *src, int count) +{ + int ret; + sdio_claim_host(priv->func); + ret = __iwmct_tx(priv, src, count); + sdio_release_host(priv->func); + return ret; +} +/* + * This workers main task is to wait for OP_OPR_ALIVE + * from TOP FW until ALIVE_MSG_TIMOUT timeout is elapsed. + * When OP_OPR_ALIVE received it will issue + * a call to "bus_rescan_devices". + */ +static void iwmct_rescan_worker(struct work_struct *ws) +{ + struct iwmct_priv *priv; + int ret; + + priv = container_of(ws, struct iwmct_priv, bus_rescan_worker); + + LOG_INFO(priv, FW_MSG, "Calling bus_rescan\n"); + + ret = bus_rescan_devices(priv->func->dev.bus); + if (ret < 0) + LOG_INFO(priv, INIT, "bus_rescan_devices FAILED!!!\n"); +} + +static void op_top_message(struct iwmct_priv *priv, struct top_msg *msg) +{ + switch (msg->hdr.opcode) { + case OP_OPR_ALIVE: + LOG_INFO(priv, FW_MSG, "Got ALIVE from device, wake rescan\n"); + schedule_work(&priv->bus_rescan_worker); + break; + default: + LOG_INFO(priv, FW_MSG, "Received msg opcode 0x%X\n", + msg->hdr.opcode); + break; + } +} + + +static void handle_top_message(struct iwmct_priv *priv, u8 *buf, int len) +{ + struct top_msg *msg; + + msg = (struct top_msg *)buf; + + if (msg->hdr.type != COMM_TYPE_D2H) { + LOG_ERROR(priv, FW_MSG, + "Message from TOP with invalid message type 0x%X\n", + msg->hdr.type); + return; + } + + if (len < sizeof(msg->hdr)) { + LOG_ERROR(priv, FW_MSG, + "Message from TOP is too short for message header " + "received %d bytes, expected at least %zd bytes\n", + len, sizeof(msg->hdr)); + return; + } + + if (len < le16_to_cpu(msg->hdr.length) + sizeof(msg->hdr)) { + LOG_ERROR(priv, FW_MSG, + "Message length (%d bytes) is shorter than " + "in header (%d bytes)\n", + len, le16_to_cpu(msg->hdr.length)); + return; + } + + switch (msg->hdr.category) { + case COMM_CATEGORY_OPERATIONAL: + op_top_message(priv, (struct top_msg *)buf); + break; + + case COMM_CATEGORY_DEBUG: + case COMM_CATEGORY_TESTABILITY: + case COMM_CATEGORY_DIAGNOSTICS: + iwmct_log_top_message(priv, buf, len); + break; + + default: + LOG_ERROR(priv, FW_MSG, + "Message from TOP with unknown category 0x%X\n", + msg->hdr.category); + break; + } +} + +int iwmct_send_hcmd(struct iwmct_priv *priv, u8 *cmd, u16 len) +{ + int ret; + u8 *buf; + + LOG_TRACE(priv, FW_MSG, "Sending hcmd:\n"); + + /* add padding to 256 for IWMC */ + ((struct top_msg *)cmd)->hdr.flags |= CMD_FLAG_PADDING_256; + + LOG_HEXDUMP(FW_MSG, cmd, len); + + if (len > FW_HCMD_BLOCK_SIZE) { + LOG_ERROR(priv, FW_MSG, "size %d exceeded hcmd max size %d\n", + len, FW_HCMD_BLOCK_SIZE); + return -1; + } + + buf = kzalloc(FW_HCMD_BLOCK_SIZE, GFP_KERNEL); + if (!buf) { + LOG_ERROR(priv, FW_MSG, "kzalloc error, buf size %d\n", + FW_HCMD_BLOCK_SIZE); + return -1; + } + + memcpy(buf, cmd, len); + ret = iwmct_tx(priv, buf, FW_HCMD_BLOCK_SIZE); + + kfree(buf); + return ret; +} + + +static void iwmct_irq_read_worker(struct work_struct *ws) +{ + struct iwmct_priv *priv; + struct iwmct_work_struct *read_req; + __le32 *buf = NULL; + int ret; + int iosize; + u32 barker; + bool is_barker; + + priv = container_of(ws, struct iwmct_priv, isr_worker); + + LOG_TRACE(priv, IRQ, "enter iwmct_irq_read_worker %p\n", ws); + + /* --------------------- Handshake with device -------------------- */ + sdio_claim_host(priv->func); + + /* all list manipulations have to be protected by + * sdio_claim_host/sdio_release_host */ + if (list_empty(&priv->read_req_list)) { + LOG_ERROR(priv, IRQ, "read_req_list empty in read worker\n"); + goto exit_release; + } + + read_req = list_entry(priv->read_req_list.next, + struct iwmct_work_struct, list); + + list_del(&read_req->list); + iosize = read_req->iosize; + kfree(read_req); + + buf = kzalloc(iosize, GFP_KERNEL); + if (!buf) { + LOG_ERROR(priv, IRQ, "kzalloc error, buf size %d\n", iosize); + goto exit_release; + } + + LOG_INFO(priv, IRQ, "iosize=%d, buf=%p, func=%d\n", + iosize, buf, priv->func->num); + + /* read from device */ + ret = sdio_memcpy_fromio(priv->func, buf, IWMC_SDIO_DATA_ADDR, iosize); + if (ret) { + LOG_ERROR(priv, IRQ, "error %d reading buffer\n", ret); + goto exit_release; + } + + LOG_HEXDUMP(IRQ, (u8 *)buf, iosize); + + barker = le32_to_cpu(buf[0]); + + /* Verify whether it's a barker and if not - treat as regular Rx */ + if (barker == IWMC_BARKER_ACK || + (barker & BARKER_DNLOAD_BARKER_MSK) == IWMC_BARKER_REBOOT) { + + /* Valid Barker is equal on first 4 dwords */ + is_barker = (buf[1] == buf[0]) && + (buf[2] == buf[0]) && + (buf[3] == buf[0]); + + if (!is_barker) { + LOG_WARNING(priv, IRQ, + "Potentially inconsistent barker " + "%08X_%08X_%08X_%08X\n", + le32_to_cpu(buf[0]), le32_to_cpu(buf[1]), + le32_to_cpu(buf[2]), le32_to_cpu(buf[3])); + } + } else { + is_barker = false; + } + + /* Handle Top CommHub message */ + if (!is_barker) { + sdio_release_host(priv->func); + handle_top_message(priv, (u8 *)buf, iosize); + goto exit; + } else if (barker == IWMC_BARKER_ACK) { /* Handle barkers */ + if (atomic_read(&priv->dev_sync) == 0) { + LOG_ERROR(priv, IRQ, + "ACK barker arrived out-of-sync\n"); + goto exit_release; + } + + /* Continuing to FW download (after Sync is completed)*/ + atomic_set(&priv->dev_sync, 0); + LOG_INFO(priv, IRQ, "ACK barker arrived " + "- starting FW download\n"); + } else { /* REBOOT barker */ + LOG_INFO(priv, IRQ, "Received reboot barker: %x\n", barker); + priv->barker = barker; + + if (barker & BARKER_DNLOAD_SYNC_MSK) { + /* Send the same barker back */ + ret = __iwmct_tx(priv, buf, iosize); + if (ret) { + LOG_ERROR(priv, IRQ, + "error %d echoing barker\n", ret); + goto exit_release; + } + LOG_INFO(priv, IRQ, "Echoing barker to device\n"); + atomic_set(&priv->dev_sync, 1); + goto exit_release; + } + + /* Continuing to FW download (without Sync) */ + LOG_INFO(priv, IRQ, "No sync requested " + "- starting FW download\n"); + } + + sdio_release_host(priv->func); + + if (priv->dbg.fw_download) + iwmct_fw_load(priv); + else + LOG_ERROR(priv, IRQ, "FW download not allowed\n"); + + goto exit; + +exit_release: + sdio_release_host(priv->func); +exit: + kfree(buf); + LOG_TRACE(priv, IRQ, "exit iwmct_irq_read_worker\n"); +} + +static void iwmct_irq(struct sdio_func *func) +{ + struct iwmct_priv *priv; + int val, ret; + int iosize; + int addr = IWMC_SDIO_INTR_GET_SIZE_ADDR; + struct iwmct_work_struct *read_req; + + priv = sdio_get_drvdata(func); + + LOG_TRACE(priv, IRQ, "enter iwmct_irq\n"); + + /* read the function's status register */ + val = sdio_readb(func, IWMC_SDIO_INTR_STATUS_ADDR, &ret); + + LOG_TRACE(priv, IRQ, "iir value = %d, ret=%d\n", val, ret); + + if (!val) { + LOG_ERROR(priv, IRQ, "iir = 0, exiting ISR\n"); + goto exit_clear_intr; + } + + + /* + * read 2 bytes of the transaction size + * IMPORTANT: sdio transaction size has to be read before clearing + * sdio interrupt!!! + */ + val = sdio_readb(priv->func, addr++, &ret); + iosize = val; + val = sdio_readb(priv->func, addr++, &ret); + iosize += val << 8; + + LOG_INFO(priv, IRQ, "READ size %d\n", iosize); + + if (iosize == 0) { + LOG_ERROR(priv, IRQ, "READ size %d, exiting ISR\n", iosize); + goto exit_clear_intr; + } + + /* allocate a work structure to pass iosize to the worker */ + read_req = kzalloc(sizeof(struct iwmct_work_struct), GFP_KERNEL); + if (!read_req) { + LOG_ERROR(priv, IRQ, "failed to allocate read_req, exit ISR\n"); + goto exit_clear_intr; + } + + INIT_LIST_HEAD(&read_req->list); + read_req->iosize = iosize; + + list_add_tail(&priv->read_req_list, &read_req->list); + + /* clear the function's interrupt request bit (write 1 to clear) */ + sdio_writeb(func, 1, IWMC_SDIO_INTR_CLEAR_ADDR, &ret); + + schedule_work(&priv->isr_worker); + + LOG_TRACE(priv, IRQ, "exit iwmct_irq\n"); + + return; + +exit_clear_intr: + /* clear the function's interrupt request bit (write 1 to clear) */ + sdio_writeb(func, 1, IWMC_SDIO_INTR_CLEAR_ADDR, &ret); +} + + +static int blocks; +module_param(blocks, int, 0604); +MODULE_PARM_DESC(blocks, "max_blocks_to_send"); + +static bool dump; +module_param(dump, bool, 0604); +MODULE_PARM_DESC(dump, "dump_hex_content"); + +static bool jump = 1; +module_param(jump, bool, 0604); + +static bool direct = 1; +module_param(direct, bool, 0604); + +static bool checksum = 1; +module_param(checksum, bool, 0604); + +static bool fw_download = 1; +module_param(fw_download, bool, 0604); + +static int block_size = IWMC_SDIO_BLK_SIZE; +module_param(block_size, int, 0404); + +static int download_trans_blks = IWMC_DEFAULT_TR_BLK; +module_param(download_trans_blks, int, 0604); + +static bool rubbish_barker; +module_param(rubbish_barker, bool, 0604); + +#ifdef CONFIG_IWMC3200TOP_DEBUG +static int log_level[LOG_SRC_MAX]; +static unsigned int log_level_argc; +module_param_array(log_level, int, &log_level_argc, 0604); +MODULE_PARM_DESC(log_level, "log_level"); + +static int log_level_fw[FW_LOG_SRC_MAX]; +static unsigned int log_level_fw_argc; +module_param_array(log_level_fw, int, &log_level_fw_argc, 0604); +MODULE_PARM_DESC(log_level_fw, "log_level_fw"); +#endif + +void iwmct_dbg_init_params(struct iwmct_priv *priv) +{ +#ifdef CONFIG_IWMC3200TOP_DEBUG + int i; + + for (i = 0; i < log_level_argc; i++) { + dev_notice(&priv->func->dev, "log_level[%d]=0x%X\n", + i, log_level[i]); + iwmct_log_set_filter((log_level[i] >> 8) & 0xFF, + log_level[i] & 0xFF); + } + for (i = 0; i < log_level_fw_argc; i++) { + dev_notice(&priv->func->dev, "log_level_fw[%d]=0x%X\n", + i, log_level_fw[i]); + iwmct_log_set_fw_filter((log_level_fw[i] >> 8) & 0xFF, + log_level_fw[i] & 0xFF); + } +#endif + + priv->dbg.blocks = blocks; + LOG_INFO(priv, INIT, "blocks=%d\n", blocks); + priv->dbg.dump = (bool)dump; + LOG_INFO(priv, INIT, "dump=%d\n", dump); + priv->dbg.jump = (bool)jump; + LOG_INFO(priv, INIT, "jump=%d\n", jump); + priv->dbg.direct = (bool)direct; + LOG_INFO(priv, INIT, "direct=%d\n", direct); + priv->dbg.checksum = (bool)checksum; + LOG_INFO(priv, INIT, "checksum=%d\n", checksum); + priv->dbg.fw_download = (bool)fw_download; + LOG_INFO(priv, INIT, "fw_download=%d\n", fw_download); + priv->dbg.block_size = block_size; + LOG_INFO(priv, INIT, "block_size=%d\n", block_size); + priv->dbg.download_trans_blks = download_trans_blks; + LOG_INFO(priv, INIT, "download_trans_blks=%d\n", download_trans_blks); +} + +/***************************************************************************** + * + * sysfs attributes + * + *****************************************************************************/ +static ssize_t show_iwmct_fw_version(struct device *d, + struct device_attribute *attr, char *buf) +{ + struct iwmct_priv *priv = dev_get_drvdata(d); + return sprintf(buf, "%s\n", priv->dbg.label_fw); +} +static DEVICE_ATTR(cc_label_fw, S_IRUGO, show_iwmct_fw_version, NULL); + +#ifdef CONFIG_IWMC3200TOP_DEBUG +static DEVICE_ATTR(log_level, S_IWUSR | S_IRUGO, + show_iwmct_log_level, store_iwmct_log_level); +static DEVICE_ATTR(log_level_fw, S_IWUSR | S_IRUGO, + show_iwmct_log_level_fw, store_iwmct_log_level_fw); +#endif + +static struct attribute *iwmct_sysfs_entries[] = { + &dev_attr_cc_label_fw.attr, +#ifdef CONFIG_IWMC3200TOP_DEBUG + &dev_attr_log_level.attr, + &dev_attr_log_level_fw.attr, +#endif + NULL +}; + +static struct attribute_group iwmct_attribute_group = { + .name = NULL, /* put in device directory */ + .attrs = iwmct_sysfs_entries, +}; + + +static int iwmct_probe(struct sdio_func *func, + const struct sdio_device_id *id) +{ + struct iwmct_priv *priv; + int ret; + int val = 1; + int addr = IWMC_SDIO_INTR_ENABLE_ADDR; + + dev_dbg(&func->dev, "enter iwmct_probe\n"); + + dev_dbg(&func->dev, "IRQ polling period id %u msecs, HZ is %d\n", + jiffies_to_msecs(2147483647), HZ); + + priv = kzalloc(sizeof(struct iwmct_priv), GFP_KERNEL); + if (!priv) { + dev_err(&func->dev, "kzalloc error\n"); + return -ENOMEM; + } + priv->func = func; + sdio_set_drvdata(func, priv); + + INIT_WORK(&priv->bus_rescan_worker, iwmct_rescan_worker); + INIT_WORK(&priv->isr_worker, iwmct_irq_read_worker); + + init_waitqueue_head(&priv->wait_q); + + sdio_claim_host(func); + /* FIXME: Remove after it is fixed in the Boot ROM upgrade */ + func->enable_timeout = 10; + + /* In our HW, setting the block size also wakes up the boot rom. */ + ret = sdio_set_block_size(func, priv->dbg.block_size); + if (ret) { + LOG_ERROR(priv, INIT, + "sdio_set_block_size() failure: %d\n", ret); + goto error_sdio_enable; + } + + ret = sdio_enable_func(func); + if (ret) { + LOG_ERROR(priv, INIT, "sdio_enable_func() failure: %d\n", ret); + goto error_sdio_enable; + } + + /* init reset and dev_sync states */ + atomic_set(&priv->reset, 0); + atomic_set(&priv->dev_sync, 0); + + /* init read req queue */ + INIT_LIST_HEAD(&priv->read_req_list); + + /* process configurable parameters */ + iwmct_dbg_init_params(priv); + ret = sysfs_create_group(&func->dev.kobj, &iwmct_attribute_group); + if (ret) { + LOG_ERROR(priv, INIT, "Failed to register attributes and " + "initialize module_params\n"); + goto error_dev_attrs; + } + + iwmct_dbgfs_register(priv, DRV_NAME); + + if (!priv->dbg.direct && priv->dbg.download_trans_blks > 8) { + LOG_INFO(priv, INIT, + "Reducing transaction to 8 blocks = 2K (from %d)\n", + priv->dbg.download_trans_blks); + priv->dbg.download_trans_blks = 8; + } + priv->trans_len = priv->dbg.download_trans_blks * priv->dbg.block_size; + LOG_INFO(priv, INIT, "Transaction length = %d\n", priv->trans_len); + + ret = sdio_claim_irq(func, iwmct_irq); + if (ret) { + LOG_ERROR(priv, INIT, "sdio_claim_irq() failure: %d\n", ret); + goto error_claim_irq; + } + + + /* Enable function's interrupt */ + sdio_writeb(priv->func, val, addr, &ret); + if (ret) { + LOG_ERROR(priv, INIT, "Failure writing to " + "Interrupt Enable Register (%d): %d\n", addr, ret); + goto error_enable_int; + } + + sdio_release_host(func); + + LOG_INFO(priv, INIT, "exit iwmct_probe\n"); + + return ret; + +error_enable_int: + sdio_release_irq(func); +error_claim_irq: + sdio_disable_func(func); +error_dev_attrs: + iwmct_dbgfs_unregister(priv->dbgfs); + sysfs_remove_group(&func->dev.kobj, &iwmct_attribute_group); +error_sdio_enable: + sdio_release_host(func); + return ret; +} + +static void iwmct_remove(struct sdio_func *func) +{ + struct iwmct_work_struct *read_req; + struct iwmct_priv *priv = sdio_get_drvdata(func); + + LOG_INFO(priv, INIT, "enter\n"); + + sdio_claim_host(func); + sdio_release_irq(func); + sdio_release_host(func); + + /* Make sure works are finished */ + flush_work_sync(&priv->bus_rescan_worker); + flush_work_sync(&priv->isr_worker); + + sdio_claim_host(func); + sdio_disable_func(func); + sysfs_remove_group(&func->dev.kobj, &iwmct_attribute_group); + iwmct_dbgfs_unregister(priv->dbgfs); + sdio_release_host(func); + + /* free read requests */ + while (!list_empty(&priv->read_req_list)) { + read_req = list_entry(priv->read_req_list.next, + struct iwmct_work_struct, list); + + list_del(&read_req->list); + kfree(read_req); + } + + kfree(priv); +} + + +static const struct sdio_device_id iwmct_ids[] = { + /* Intel Wireless MultiCom 3200 Top Driver */ + { SDIO_DEVICE(SDIO_VENDOR_ID_INTEL, 0x1404)}, + { }, /* Terminating entry */ +}; + +MODULE_DEVICE_TABLE(sdio, iwmct_ids); + +static struct sdio_driver iwmct_driver = { + .probe = iwmct_probe, + .remove = iwmct_remove, + .name = DRV_NAME, + .id_table = iwmct_ids, +}; + +static int __init iwmct_init(void) +{ + int rc; + + /* Default log filter settings */ + iwmct_log_set_filter(LOG_SRC_ALL, LOG_SEV_FILTER_RUNTIME); + iwmct_log_set_filter(LOG_SRC_FW_MSG, LOG_SEV_FW_FILTER_ALL); + iwmct_log_set_fw_filter(LOG_SRC_ALL, FW_LOG_SEV_FILTER_RUNTIME); + + rc = sdio_register_driver(&iwmct_driver); + + return rc; +} + +static void __exit iwmct_exit(void) +{ + sdio_unregister_driver(&iwmct_driver); +} + +module_init(iwmct_init); +module_exit(iwmct_exit); + diff --git a/trunk/drivers/net/bonding/bond_debugfs.c b/trunk/drivers/net/bonding/bond_debugfs.c index 2cf084eb9d52..3680aa251dea 100644 --- a/trunk/drivers/net/bonding/bond_debugfs.c +++ b/trunk/drivers/net/bonding/bond_debugfs.c @@ -6,7 +6,7 @@ #include "bonding.h" #include "bond_alb.h" -#if defined(CONFIG_DEBUG_FS) && !defined(CONFIG_NET_NS) +#ifdef CONFIG_DEBUG_FS #include #include diff --git a/trunk/drivers/net/bonding/bond_main.c b/trunk/drivers/net/bonding/bond_main.c index 1eb3979d0af5..f5a40b925f5e 100644 --- a/trunk/drivers/net/bonding/bond_main.c +++ b/trunk/drivers/net/bonding/bond_main.c @@ -1240,7 +1240,9 @@ static inline int slave_enable_netpoll(struct slave *slave) if (!np) goto out; - err = __netpoll_setup(np, slave->dev); + np->dev = slave->dev; + strlcpy(np->dev_name, slave->dev->name, IFNAMSIZ); + err = __netpoll_setup(np); if (err) { kfree(np); goto out; @@ -3228,12 +3230,6 @@ static int bond_master_netdev_event(unsigned long event, switch (event) { case NETDEV_CHANGENAME: return bond_event_changename(event_bond); - case NETDEV_UNREGISTER: - bond_remove_proc_entry(event_bond); - break; - case NETDEV_REGISTER: - bond_create_proc_entry(event_bond); - break; default: break; } @@ -4418,6 +4414,8 @@ static void bond_uninit(struct net_device *bond_dev) bond_work_cancel_all(bond); + bond_remove_proc_entry(bond); + bond_debug_unregister(bond); __hw_addr_flush(&bond->mc_list); @@ -4819,6 +4817,7 @@ static int bond_init(struct net_device *bond_dev) bond_set_lockdep_class(bond_dev); + bond_create_proc_entry(bond); list_add_tail(&bond->bond_list, &bn->dev_list); bond_prepare_sysfs_group(bond); diff --git a/trunk/drivers/net/can/cc770/cc770.c b/trunk/drivers/net/can/cc770/cc770.c index a138db11cbf0..d42a6a7396f2 100644 --- a/trunk/drivers/net/can/cc770/cc770.c +++ b/trunk/drivers/net/can/cc770/cc770.c @@ -695,7 +695,7 @@ static void cc770_tx_interrupt(struct net_device *dev, unsigned int o) netif_wake_queue(dev); } -static irqreturn_t cc770_interrupt(int irq, void *dev_id) +irqreturn_t cc770_interrupt(int irq, void *dev_id) { struct net_device *dev = (struct net_device *)dev_id; struct cc770_priv *priv = netdev_priv(dev); diff --git a/trunk/drivers/net/can/dev.c b/trunk/drivers/net/can/dev.c index 963e2ccd10db..239e4dd92ca1 100644 --- a/trunk/drivers/net/can/dev.c +++ b/trunk/drivers/net/can/dev.c @@ -401,7 +401,7 @@ EXPORT_SYMBOL_GPL(can_free_echo_skb); /* * CAN device restart for bus-off recovery */ -static void can_restart(unsigned long data) +void can_restart(unsigned long data) { struct net_device *dev = (struct net_device *)data; struct can_priv *priv = netdev_priv(dev); diff --git a/trunk/drivers/net/can/flexcan.c b/trunk/drivers/net/can/flexcan.c index 1b6f5621ce89..0f88cd3bb928 100644 --- a/trunk/drivers/net/can/flexcan.c +++ b/trunk/drivers/net/can/flexcan.c @@ -34,7 +34,6 @@ #include #include #include -#include #include #include @@ -166,21 +165,10 @@ struct flexcan_regs { u32 imask1; /* 0x28 */ u32 iflag2; /* 0x2c */ u32 iflag1; /* 0x30 */ - u32 crl2; /* 0x34 */ - u32 esr2; /* 0x38 */ - u32 imeur; /* 0x3c */ - u32 lrfr; /* 0x40 */ - u32 crcr; /* 0x44 */ - u32 rxfgmask; /* 0x48 */ - u32 rxfir; /* 0x4c */ - u32 _reserved3[12]; + u32 _reserved2[19]; struct flexcan_mb cantxfg[64]; }; -struct flexcan_devtype_data { - u32 hw_ver; /* hardware controller version */ -}; - struct flexcan_priv { struct can_priv can; struct net_device *dev; @@ -192,15 +180,6 @@ struct flexcan_priv { struct clk *clk; struct flexcan_platform_data *pdata; - const struct flexcan_devtype_data *devtype_data; -}; - -static struct flexcan_devtype_data fsl_p1010_devtype_data = { - .hw_ver = 3, -}; - -static struct flexcan_devtype_data fsl_imx6q_devtype_data = { - .hw_ver = 10, }; static struct can_bittiming_const flexcan_bittiming_const = { @@ -771,9 +750,6 @@ static int flexcan_chip_start(struct net_device *dev) flexcan_write(0x0, ®s->rx14mask); flexcan_write(0x0, ®s->rx15mask); - if (priv->devtype_data->hw_ver >= 10) - flexcan_write(0x0, ®s->rxfgmask); - flexcan_transceiver_switch(priv, 1); /* synchronize with the can bus */ @@ -946,21 +922,8 @@ static void __devexit unregister_flexcandev(struct net_device *dev) unregister_candev(dev); } -static const struct of_device_id flexcan_of_match[] = { - { .compatible = "fsl,p1010-flexcan", .data = &fsl_p1010_devtype_data, }, - { .compatible = "fsl,imx6q-flexcan", .data = &fsl_imx6q_devtype_data, }, - { /* sentinel */ }, -}; - -static const struct platform_device_id flexcan_id_table[] = { - { .name = "flexcan", .driver_data = (kernel_ulong_t)&fsl_p1010_devtype_data, }, - { /* sentinel */ }, -}; - static int __devinit flexcan_probe(struct platform_device *pdev) { - const struct of_device_id *of_id; - const struct flexcan_devtype_data *devtype_data; struct net_device *dev; struct flexcan_priv *priv; struct resource *mem; @@ -975,9 +938,14 @@ static int __devinit flexcan_probe(struct platform_device *pdev) if (IS_ERR(pinctrl)) return PTR_ERR(pinctrl); - if (pdev->dev.of_node) - of_property_read_u32(pdev->dev.of_node, - "clock-frequency", &clock_freq); + if (pdev->dev.of_node) { + const __be32 *clock_freq_p; + + clock_freq_p = of_get_property(pdev->dev.of_node, + "clock-frequency", NULL); + if (clock_freq_p) + clock_freq = be32_to_cpup(clock_freq_p); + } if (!clock_freq) { clk = clk_get(&pdev->dev, NULL); @@ -1014,17 +982,6 @@ static int __devinit flexcan_probe(struct platform_device *pdev) goto failed_alloc; } - of_id = of_match_device(flexcan_of_match, &pdev->dev); - if (of_id) { - devtype_data = of_id->data; - } else if (pdev->id_entry->driver_data) { - devtype_data = (struct flexcan_devtype_data *) - pdev->id_entry->driver_data; - } else { - err = -ENODEV; - goto failed_devtype; - } - dev->netdev_ops = &flexcan_netdev_ops; dev->irq = irq; dev->flags |= IFF_ECHO; @@ -1041,7 +998,6 @@ static int __devinit flexcan_probe(struct platform_device *pdev) priv->dev = dev; priv->clk = clk; priv->pdata = pdev->dev.platform_data; - priv->devtype_data = devtype_data; netif_napi_add(dev, &priv->napi, flexcan_poll, FLEXCAN_NAPI_WEIGHT); @@ -1060,7 +1016,6 @@ static int __devinit flexcan_probe(struct platform_device *pdev) return 0; failed_register: - failed_devtype: free_candev(dev); failed_alloc: iounmap(base); @@ -1094,6 +1049,13 @@ static int __devexit flexcan_remove(struct platform_device *pdev) return 0; } +static struct of_device_id flexcan_of_match[] = { + { + .compatible = "fsl,p1010-flexcan", + }, + {}, +}; + #ifdef CONFIG_PM static int flexcan_suspend(struct platform_device *pdev, pm_message_t state) { @@ -1140,7 +1102,6 @@ static struct platform_driver flexcan_driver = { .remove = __devexit_p(flexcan_remove), .suspend = flexcan_suspend, .resume = flexcan_resume, - .id_table = flexcan_id_table, }; module_platform_driver(flexcan_driver); diff --git a/trunk/drivers/net/can/mscan/mpc5xxx_can.c b/trunk/drivers/net/can/mscan/mpc5xxx_can.c index 06adf881ea24..5caa572d71e3 100644 --- a/trunk/drivers/net/can/mscan/mpc5xxx_can.c +++ b/trunk/drivers/net/can/mscan/mpc5xxx_can.c @@ -251,7 +251,7 @@ static struct of_device_id mpc5xxx_can_table[]; static int __devinit mpc5xxx_can_probe(struct platform_device *ofdev) { const struct of_device_id *match; - const struct mpc5xxx_can_data *data; + struct mpc5xxx_can_data *data; struct device_node *np = ofdev->dev.of_node; struct net_device *dev; struct mscan_priv *priv; diff --git a/trunk/drivers/net/can/softing/softing_main.c b/trunk/drivers/net/can/softing/softing_main.c index f2a221e7b968..a7c77c744ee9 100644 --- a/trunk/drivers/net/can/softing/softing_main.c +++ b/trunk/drivers/net/can/softing/softing_main.c @@ -826,12 +826,12 @@ static __devinit int softing_pdev_probe(struct platform_device *pdev) goto sysfs_failed; } + ret = -ENOMEM; for (j = 0; j < ARRAY_SIZE(card->net); ++j) { card->net[j] = netdev = softing_netdev_create(card, card->id.chip[j]); if (!netdev) { dev_alert(&pdev->dev, "failed to make can[%i]", j); - ret = -ENOMEM; goto netdev_failed; } priv = netdev_priv(card->net[j]); diff --git a/trunk/drivers/net/cris/eth_v10.c b/trunk/drivers/net/cris/eth_v10.c index f0c8bd54ce29..9c755db6b16d 100644 --- a/trunk/drivers/net/cris/eth_v10.c +++ b/trunk/drivers/net/cris/eth_v10.c @@ -1008,7 +1008,7 @@ e100_send_mdio_bit(unsigned char bit) } static unsigned char -e100_receive_mdio_bit(void) +e100_receive_mdio_bit() { unsigned char bit; *R_NETWORK_MGM_CTRL = 0; diff --git a/trunk/drivers/net/ethernet/3com/3c501.c b/trunk/drivers/net/ethernet/3com/3c501.c index 2038eaabaea4..bf73e1a02293 100644 --- a/trunk/drivers/net/ethernet/3com/3c501.c +++ b/trunk/drivers/net/ethernet/3com/3c501.c @@ -143,7 +143,7 @@ static int irq = 5; static int mem_start; /** - * el1_probe - probe for a 3c501 + * el1_probe: - probe for a 3c501 * @dev: The device structure passed in to probe. * * This can be called from two places. The network layer will probe using diff --git a/trunk/drivers/net/ethernet/8390/Kconfig b/trunk/drivers/net/ethernet/8390/Kconfig index e1219e037c04..2e538676924d 100644 --- a/trunk/drivers/net/ethernet/8390/Kconfig +++ b/trunk/drivers/net/ethernet/8390/Kconfig @@ -162,20 +162,6 @@ config MAC8390 and read the Ethernet-HOWTO, available from . -config MCF8390 - tristate "ColdFire NS8390 based Ethernet support" - depends on COLDFIRE - select CRC32 - ---help--- - This driver is for Ethernet devices using an NS8390-compatible - chipset on many common ColdFire CPU based boards. Many of the older - Freescale dev boards use this, and some other common boards like - some SnapGear routers do as well. - - If you have one of these boards and want to use the network interface - on them then choose Y. To compile this driver as a module, choose M - here, the module will be called mcf8390. - config NE2000 tristate "NE2000/NE1000 support" depends on (ISA || (Q40 && m) || M32R || MACH_TX49XX) diff --git a/trunk/drivers/net/ethernet/8390/Makefile b/trunk/drivers/net/ethernet/8390/Makefile index f43038babf86..d13790b7fd27 100644 --- a/trunk/drivers/net/ethernet/8390/Makefile +++ b/trunk/drivers/net/ethernet/8390/Makefile @@ -14,7 +14,6 @@ obj-$(CONFIG_HPLAN_PLUS) += hp-plus.o 8390p.o obj-$(CONFIG_HPLAN) += hp.o 8390p.o obj-$(CONFIG_HYDRA) += hydra.o 8390.o obj-$(CONFIG_LNE390) += lne390.o 8390.o -obj-$(CONFIG_MCF8390) += mcf8390.o 8390.o obj-$(CONFIG_NE2000) += ne.o 8390p.o obj-$(CONFIG_NE2_MCA) += ne2.o 8390p.o obj-$(CONFIG_NE2K_PCI) += ne2k-pci.o 8390.o diff --git a/trunk/drivers/net/ethernet/8390/mcf8390.c b/trunk/drivers/net/ethernet/8390/mcf8390.c deleted file mode 100644 index 230efd6fa5d5..000000000000 --- a/trunk/drivers/net/ethernet/8390/mcf8390.c +++ /dev/null @@ -1,480 +0,0 @@ -/* - * Support for ColdFire CPU based boards using a NS8390 Ethernet device. - * - * Derived from the many other 8390 drivers. - * - * (C) Copyright 2012, Greg Ungerer - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of the Linux - * distribution for more details. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static const char version[] = - "mcf8390.c: (15-06-2012) Greg Ungerer "; - -#define NE_CMD 0x00 -#define NE_DATAPORT 0x10 /* NatSemi-defined port window offset */ -#define NE_RESET 0x1f /* Issue a read to reset ,a write to clear */ -#define NE_EN0_ISR 0x07 -#define NE_EN0_DCFG 0x0e -#define NE_EN0_RSARLO 0x08 -#define NE_EN0_RSARHI 0x09 -#define NE_EN0_RCNTLO 0x0a -#define NE_EN0_RXCR 0x0c -#define NE_EN0_TXCR 0x0d -#define NE_EN0_RCNTHI 0x0b -#define NE_EN0_IMR 0x0f - -#define NESM_START_PG 0x40 /* First page of TX buffer */ -#define NESM_STOP_PG 0x80 /* Last page +1 of RX ring */ - -#ifdef NE2000_ODDOFFSET -/* - * A lot of the ColdFire boards use a separate address region for odd offset - * register addresses. The following functions convert and map as required. - * Note that the data port accesses are treated a little differently, and - * always accessed via the insX/outsX functions. - */ -static inline u32 NE_PTR(u32 addr) -{ - if (addr & 1) - return addr - 1 + NE2000_ODDOFFSET; - return addr; -} - -static inline u32 NE_DATA_PTR(u32 addr) -{ - return addr; -} - -void ei_outb(u32 val, u32 addr) -{ - NE2000_BYTE *rp; - - rp = (NE2000_BYTE *) NE_PTR(addr); - *rp = RSWAP(val); -} - -#define ei_inb ei_inb -u8 ei_inb(u32 addr) -{ - NE2000_BYTE *rp, val; - - rp = (NE2000_BYTE *) NE_PTR(addr); - val = *rp; - return (u8) (RSWAP(val) & 0xff); -} - -void ei_insb(u32 addr, void *vbuf, int len) -{ - NE2000_BYTE *rp, val; - u8 *buf; - - buf = (u8 *) vbuf; - rp = (NE2000_BYTE *) NE_DATA_PTR(addr); - for (; (len > 0); len--) { - val = *rp; - *buf++ = RSWAP(val); - } -} - -void ei_insw(u32 addr, void *vbuf, int len) -{ - volatile u16 *rp; - u16 w, *buf; - - buf = (u16 *) vbuf; - rp = (volatile u16 *) NE_DATA_PTR(addr); - for (; (len > 0); len--) { - w = *rp; - *buf++ = BSWAP(w); - } -} - -void ei_outsb(u32 addr, const void *vbuf, int len) -{ - NE2000_BYTE *rp, val; - u8 *buf; - - buf = (u8 *) vbuf; - rp = (NE2000_BYTE *) NE_DATA_PTR(addr); - for (; (len > 0); len--) { - val = *buf++; - *rp = RSWAP(val); - } -} - -void ei_outsw(u32 addr, const void *vbuf, int len) -{ - volatile u16 *rp; - u16 w, *buf; - - buf = (u16 *) vbuf; - rp = (volatile u16 *) NE_DATA_PTR(addr); - for (; (len > 0); len--) { - w = *buf++; - *rp = BSWAP(w); - } -} - -#else /* !NE2000_ODDOFFSET */ - -#define ei_inb inb -#define ei_outb outb -#define ei_insb insb -#define ei_insw insw -#define ei_outsb outsb -#define ei_outsw outsw - -#endif /* !NE2000_ODDOFFSET */ - -#define ei_inb_p ei_inb -#define ei_outb_p ei_outb - -#include "lib8390.c" - -/* - * Hard reset the card. This used to pause for the same period that a - * 8390 reset command required, but that shouldn't be necessary. - */ -static void mcf8390_reset_8390(struct net_device *dev) -{ - unsigned long reset_start_time = jiffies; - u32 addr = dev->base_addr; - - if (ei_debug > 1) - netdev_dbg(dev, "resetting the 8390 t=%ld...\n", jiffies); - - ei_outb(ei_inb(addr + NE_RESET), addr + NE_RESET); - - ei_status.txing = 0; - ei_status.dmaing = 0; - - /* This check _should_not_ be necessary, omit eventually. */ - while ((ei_inb(addr + NE_EN0_ISR) & ENISR_RESET) == 0) { - if (time_after(jiffies, reset_start_time + 2 * HZ / 100)) { - netdev_warn(dev, "%s: did not complete\n", __func__); - break; - } - } - - ei_outb(ENISR_RESET, addr + NE_EN0_ISR); -} - -/* - * This *shouldn't* happen. - * If it does, it's the last thing you'll see - */ -static void mcf8390_dmaing_err(const char *func, struct net_device *dev, - struct ei_device *ei_local) -{ - netdev_err(dev, "%s: DMAing conflict [DMAstat:%d][irqlock:%d]\n", - func, ei_local->dmaing, ei_local->irqlock); -} - -/* - * Grab the 8390 specific header. Similar to the block_input routine, but - * we don't need to be concerned with ring wrap as the header will be at - * the start of a page, so we optimize accordingly. - */ -static void mcf8390_get_8390_hdr(struct net_device *dev, - struct e8390_pkt_hdr *hdr, int ring_page) -{ - struct ei_device *ei_local = netdev_priv(dev); - u32 addr = dev->base_addr; - - if (ei_local->dmaing) { - mcf8390_dmaing_err(__func__, dev, ei_local); - return; - } - - ei_local->dmaing |= 0x01; - ei_outb(E8390_NODMA + E8390_PAGE0 + E8390_START, addr + NE_CMD); - ei_outb(ENISR_RDC, addr + NE_EN0_ISR); - ei_outb(sizeof(struct e8390_pkt_hdr), addr + NE_EN0_RCNTLO); - ei_outb(0, addr + NE_EN0_RCNTHI); - ei_outb(0, addr + NE_EN0_RSARLO); /* On page boundary */ - ei_outb(ring_page, addr + NE_EN0_RSARHI); - ei_outb(E8390_RREAD + E8390_START, addr + NE_CMD); - - ei_insw(addr + NE_DATAPORT, hdr, sizeof(struct e8390_pkt_hdr) >> 1); - - outb(ENISR_RDC, addr + NE_EN0_ISR); /* Ack intr */ - ei_local->dmaing &= ~0x01; - - hdr->count = cpu_to_le16(hdr->count); -} - -/* - * Block input and output, similar to the Crynwr packet driver. - * If you are porting to a new ethercard, look at the packet driver source - * for hints. The NEx000 doesn't share the on-board packet memory -- - * you have to put the packet out through the "remote DMA" dataport - * using z_writeb. - */ -static void mcf8390_block_input(struct net_device *dev, int count, - struct sk_buff *skb, int ring_offset) -{ - struct ei_device *ei_local = netdev_priv(dev); - u32 addr = dev->base_addr; - char *buf = skb->data; - - if (ei_local->dmaing) { - mcf8390_dmaing_err(__func__, dev, ei_local); - return; - } - - ei_local->dmaing |= 0x01; - ei_outb(E8390_NODMA + E8390_PAGE0 + E8390_START, addr + NE_CMD); - ei_outb(ENISR_RDC, addr + NE_EN0_ISR); - ei_outb(count & 0xff, addr + NE_EN0_RCNTLO); - ei_outb(count >> 8, addr + NE_EN0_RCNTHI); - ei_outb(ring_offset & 0xff, addr + NE_EN0_RSARLO); - ei_outb(ring_offset >> 8, addr + NE_EN0_RSARHI); - ei_outb(E8390_RREAD + E8390_START, addr + NE_CMD); - - ei_insw(addr + NE_DATAPORT, buf, count >> 1); - if (count & 1) - buf[count - 1] = ei_inb(addr + NE_DATAPORT); - - ei_outb(ENISR_RDC, addr + NE_EN0_ISR); /* Ack intr */ - ei_local->dmaing &= ~0x01; -} - -static void mcf8390_block_output(struct net_device *dev, int count, - const unsigned char *buf, - const int start_page) -{ - struct ei_device *ei_local = netdev_priv(dev); - u32 addr = dev->base_addr; - unsigned long dma_start; - - /* Make sure we transfer all bytes if 16bit IO writes */ - if (count & 0x1) - count++; - - if (ei_local->dmaing) { - mcf8390_dmaing_err(__func__, dev, ei_local); - return; - } - - ei_local->dmaing |= 0x01; - /* We should already be in page 0, but to be safe... */ - ei_outb(E8390_PAGE0 + E8390_START + E8390_NODMA, addr + NE_CMD); - - ei_outb(ENISR_RDC, addr + NE_EN0_ISR); - - /* Now the normal output. */ - ei_outb(count & 0xff, addr + NE_EN0_RCNTLO); - ei_outb(count >> 8, addr + NE_EN0_RCNTHI); - ei_outb(0x00, addr + NE_EN0_RSARLO); - ei_outb(start_page, addr + NE_EN0_RSARHI); - ei_outb(E8390_RWRITE + E8390_START, addr + NE_CMD); - - ei_outsw(addr + NE_DATAPORT, buf, count >> 1); - - dma_start = jiffies; - while ((ei_inb(addr + NE_EN0_ISR) & ENISR_RDC) == 0) { - if (time_after(jiffies, dma_start + 2 * HZ / 100)) { /* 20ms */ - netdev_err(dev, "timeout waiting for Tx RDC\n"); - mcf8390_reset_8390(dev); - __NS8390_init(dev, 1); - break; - } - } - - ei_outb(ENISR_RDC, addr + NE_EN0_ISR); /* Ack intr */ - ei_local->dmaing &= ~0x01; -} - -static const struct net_device_ops mcf8390_netdev_ops = { - .ndo_open = __ei_open, - .ndo_stop = __ei_close, - .ndo_start_xmit = __ei_start_xmit, - .ndo_tx_timeout = __ei_tx_timeout, - .ndo_get_stats = __ei_get_stats, - .ndo_set_rx_mode = __ei_set_multicast_list, - .ndo_validate_addr = eth_validate_addr, - .ndo_set_mac_address = eth_mac_addr, - .ndo_change_mtu = eth_change_mtu, -#ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = __ei_poll, -#endif -}; - -static int mcf8390_init(struct net_device *dev) -{ - static u32 offsets[] = { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - }; - struct ei_device *ei_local = netdev_priv(dev); - unsigned char SA_prom[32]; - u32 addr = dev->base_addr; - int start_page, stop_page; - int i, ret; - - mcf8390_reset_8390(dev); - - /* - * Read the 16 bytes of station address PROM. - * We must first initialize registers, - * similar to NS8390_init(eifdev, 0). - * We can't reliably read the SAPROM address without this. - * (I learned the hard way!). - */ - { - static const struct { - u32 value; - u32 offset; - } program_seq[] = { - {E8390_NODMA + E8390_PAGE0 + E8390_STOP, NE_CMD}, - /* Select page 0 */ - {0x48, NE_EN0_DCFG}, /* 0x48: Set byte-wide access */ - {0x00, NE_EN0_RCNTLO}, /* Clear the count regs */ - {0x00, NE_EN0_RCNTHI}, - {0x00, NE_EN0_IMR}, /* Mask completion irq */ - {0xFF, NE_EN0_ISR}, - {E8390_RXOFF, NE_EN0_RXCR}, /* 0x20 Set to monitor */ - {E8390_TXOFF, NE_EN0_TXCR}, /* 0x02 and loopback mode */ - {32, NE_EN0_RCNTLO}, - {0x00, NE_EN0_RCNTHI}, - {0x00, NE_EN0_RSARLO}, /* DMA starting at 0x0000 */ - {0x00, NE_EN0_RSARHI}, - {E8390_RREAD + E8390_START, NE_CMD}, - }; - for (i = 0; i < ARRAY_SIZE(program_seq); i++) { - ei_outb(program_seq[i].value, - addr + program_seq[i].offset); - } - } - - for (i = 0; i < 16; i++) { - SA_prom[i] = ei_inb(addr + NE_DATAPORT); - ei_inb(addr + NE_DATAPORT); - } - - /* We must set the 8390 for word mode. */ - ei_outb(0x49, addr + NE_EN0_DCFG); - start_page = NESM_START_PG; - stop_page = NESM_STOP_PG; - - /* Install the Interrupt handler */ - ret = request_irq(dev->irq, __ei_interrupt, 0, dev->name, dev); - if (ret) - return ret; - - for (i = 0; i < ETH_ALEN; i++) - dev->dev_addr[i] = SA_prom[i]; - - netdev_dbg(dev, "Found ethernet address: %pM\n", dev->dev_addr); - - ei_local->name = "mcf8390"; - ei_local->tx_start_page = start_page; - ei_local->stop_page = stop_page; - ei_local->word16 = 1; - ei_local->rx_start_page = start_page + TX_PAGES; - ei_local->reset_8390 = mcf8390_reset_8390; - ei_local->block_input = mcf8390_block_input; - ei_local->block_output = mcf8390_block_output; - ei_local->get_8390_hdr = mcf8390_get_8390_hdr; - ei_local->reg_offset = offsets; - - dev->netdev_ops = &mcf8390_netdev_ops; - __NS8390_init(dev, 0); - ret = register_netdev(dev); - if (ret) { - free_irq(dev->irq, dev); - return ret; - } - - netdev_info(dev, "addr=0x%08x irq=%d, Ethernet Address %pM\n", - addr, dev->irq, dev->dev_addr); - return 0; -} - -static int mcf8390_probe(struct platform_device *pdev) -{ - struct net_device *dev; - struct ei_device *ei_local; - struct resource *mem, *irq; - resource_size_t msize; - int ret; - - irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); - if (irq == NULL) { - dev_err(&pdev->dev, "no IRQ specified?\n"); - return -ENXIO; - } - - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (mem == NULL) { - dev_err(&pdev->dev, "no memory address specified?\n"); - return -ENXIO; - } - msize = resource_size(mem); - if (!request_mem_region(mem->start, msize, pdev->name)) - return -EBUSY; - - dev = ____alloc_ei_netdev(0); - if (dev == NULL) { - release_mem_region(mem->start, msize); - return -ENOMEM; - } - - SET_NETDEV_DEV(dev, &pdev->dev); - platform_set_drvdata(pdev, dev); - ei_local = netdev_priv(dev); - - dev->irq = irq->start; - dev->base_addr = mem->start; - - ret = mcf8390_init(dev); - if (ret) { - release_mem_region(mem->start, msize); - free_netdev(dev); - return ret; - } - return 0; -} - -static int mcf8390_remove(struct platform_device *pdev) -{ - struct net_device *dev = platform_get_drvdata(pdev); - struct resource *mem; - - unregister_netdev(dev); - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (mem) - release_mem_region(mem->start, resource_size(mem)); - free_netdev(dev); - return 0; -} - -static struct platform_driver mcf8390_drv = { - .driver = { - .name = "mcf8390", - .owner = THIS_MODULE, - }, - .probe = mcf8390_probe, - .remove = mcf8390_remove, -}; - -module_platform_driver(mcf8390_drv); - -MODULE_DESCRIPTION("MCF8390 ColdFire NS8390 driver"); -MODULE_AUTHOR("Greg Ungerer "); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:mcf8390"); diff --git a/trunk/drivers/net/ethernet/amd/lance.c b/trunk/drivers/net/ethernet/amd/lance.c index 5c728436b85e..a6e2e840884e 100644 --- a/trunk/drivers/net/ethernet/amd/lance.c +++ b/trunk/drivers/net/ethernet/amd/lance.c @@ -873,9 +873,10 @@ lance_init_ring(struct net_device *dev, gfp_t gfp) skb = alloc_skb(PKT_BUF_SZ, GFP_DMA | gfp); lp->rx_skbuff[i] = skb; - if (skb) + if (skb) { + skb->dev = dev; rx_buff = skb->data; - else + } else rx_buff = kmalloc(PKT_BUF_SZ, GFP_DMA | gfp); if (rx_buff == NULL) lp->rx_ring[i].base = 0; diff --git a/trunk/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c b/trunk/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c index 21e261ffbe10..801f0126512d 100644 --- a/trunk/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c +++ b/trunk/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c @@ -199,7 +199,7 @@ int atl1c_read_mac_addr(struct atl1c_hw *hw) err = atl1c_get_permanent_address(hw); if (err) - eth_random_addr(hw->perm_mac_addr); + random_ether_addr(hw->perm_mac_addr); memcpy(hw->mac_addr, hw->perm_mac_addr, sizeof(hw->perm_mac_addr)); return err; diff --git a/trunk/drivers/net/ethernet/atheros/atl1c/atl1c_main.c b/trunk/drivers/net/ethernet/atheros/atl1c/atl1c_main.c index 36d3783ebfa0..85717cb306d1 100644 --- a/trunk/drivers/net/ethernet/atheros/atl1c/atl1c_main.c +++ b/trunk/drivers/net/ethernet/atheros/atl1c/atl1c_main.c @@ -166,7 +166,7 @@ static void atl1c_reset_pcie(struct atl1c_hw *hw, u32 flag) msleep(5); } -/** +/* * atl1c_irq_enable - Enable default interrupt generation settings * @adapter: board private structure */ @@ -179,7 +179,7 @@ static inline void atl1c_irq_enable(struct atl1c_adapter *adapter) } } -/** +/* * atl1c_irq_disable - Mask off interrupt generation on the NIC * @adapter: board private structure */ @@ -192,7 +192,7 @@ static inline void atl1c_irq_disable(struct atl1c_adapter *adapter) synchronize_irq(adapter->pdev->irq); } -/** +/* * atl1c_irq_reset - reset interrupt confiure on the NIC * @adapter: board private structure */ @@ -220,7 +220,7 @@ static u32 atl1c_wait_until_idle(struct atl1c_hw *hw, u32 modu_ctrl) return data; } -/** +/* * atl1c_phy_config - Timer Call-back * @data: pointer to netdev cast into an unsigned long */ @@ -261,6 +261,7 @@ static void atl1c_check_link_status(struct atl1c_adapter *adapter) if ((phy_data & BMSR_LSTATUS) == 0) { /* link down */ netif_carrier_off(netdev); + netif_stop_queue(netdev); hw->hibernate = true; if (atl1c_reset_mac(hw) != 0) if (netif_msg_hw(adapter)) @@ -360,7 +361,7 @@ static void atl1c_del_timer(struct atl1c_adapter *adapter) } -/** +/* * atl1c_tx_timeout - Respond to a Tx Hang * @netdev: network interface device structure */ @@ -373,7 +374,7 @@ static void atl1c_tx_timeout(struct net_device *netdev) schedule_work(&adapter->common_task); } -/** +/* * atl1c_set_multi - Multicast and Promiscuous mode set * @netdev: network interface device structure * @@ -452,7 +453,7 @@ static void atl1c_restore_vlan(struct atl1c_adapter *adapter) atl1c_vlan_mode(adapter->netdev, adapter->netdev->features); } -/** +/* * atl1c_set_mac - Change the Ethernet Address of the NIC * @netdev: network interface device structure * @p: pointer to an address structure @@ -517,7 +518,7 @@ static int atl1c_set_features(struct net_device *netdev, return 0; } -/** +/* * atl1c_change_mtu - Change the Maximum Transfer Unit * @netdev: network interface device structure * @new_mtu: new value for maximum frame size @@ -576,6 +577,12 @@ static void atl1c_mdio_write(struct net_device *netdev, int phy_id, atl1c_write_phy_reg(&adapter->hw, reg_num, val); } +/* + * atl1c_mii_ioctl - + * @netdev: + * @ifreq: + * @cmd: + */ static int atl1c_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) { @@ -626,6 +633,12 @@ static int atl1c_mii_ioctl(struct net_device *netdev, return retval; } +/* + * atl1c_ioctl - + * @netdev: + * @ifreq: + * @cmd: + */ static int atl1c_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) { switch (cmd) { @@ -638,7 +651,7 @@ static int atl1c_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) } } -/** +/* * atl1c_alloc_queues - Allocate memory for all rings * @adapter: board private structure to initialize * @@ -742,7 +755,7 @@ static void __devinit atl1c_patch_assign(struct atl1c_hw *hw) i++; } } -/** +/* * atl1c_sw_init - Initialize general software structures (struct atl1c_adapter) * @adapter: board private structure to initialize * @@ -840,7 +853,7 @@ static inline void atl1c_clean_buffer(struct pci_dev *pdev, buffer_info->skb = NULL; ATL1C_SET_BUFFER_STATE(buffer_info, ATL1C_BUFFER_FREE); } -/** +/* * atl1c_clean_tx_ring - Free Tx-skb * @adapter: board private structure */ @@ -865,7 +878,7 @@ static void atl1c_clean_tx_ring(struct atl1c_adapter *adapter, tpd_ring->next_to_use = 0; } -/** +/* * atl1c_clean_rx_ring - Free rx-reservation skbs * @adapter: board private structure */ @@ -918,7 +931,7 @@ static void atl1c_init_ring_ptrs(struct atl1c_adapter *adapter) } } -/** +/* * atl1c_free_ring_resources - Free Tx / RX descriptor Resources * @adapter: board private structure * @@ -941,7 +954,7 @@ static void atl1c_free_ring_resources(struct atl1c_adapter *adapter) } } -/** +/* * atl1c_setup_mem_resources - allocate Tx / RX descriptor resources * @adapter: board private structure * @@ -1350,7 +1363,7 @@ static void atl1c_set_aspm(struct atl1c_hw *hw, u16 link_speed) return; } -/** +/* * atl1c_configure - Configure Transmit&Receive Unit after Reset * @adapter: board private structure * @@ -1464,7 +1477,7 @@ static void atl1c_update_hw_stats(struct atl1c_adapter *adapter) } } -/** +/* * atl1c_get_stats - Get System Network Statistics * @netdev: network interface device structure * @@ -1545,10 +1558,11 @@ static bool atl1c_clean_tx_irq(struct atl1c_adapter *adapter, return true; } -/** +/* * atl1c_intr - Interrupt Handler * @irq: interrupt number * @data: pointer to a network interface device structure + * @pt_regs: CPU registers structure */ static irqreturn_t atl1c_intr(int irq, void *data) { @@ -1799,8 +1813,9 @@ static void atl1c_clean_rx_irq(struct atl1c_adapter *adapter, atl1c_alloc_rx_buffer(adapter); } -/** +/* * atl1c_clean - NAPI Rx polling callback + * @adapter: board private structure */ static int atl1c_clean(struct napi_struct *napi, int budget) { @@ -2255,7 +2270,7 @@ static void atl1c_down(struct atl1c_adapter *adapter) atl1c_reset_dma_ring(adapter); } -/** +/* * atl1c_open - Called when a network interface is made active * @netdev: network interface device structure * @@ -2294,7 +2309,7 @@ static int atl1c_open(struct net_device *netdev) return err; } -/** +/* * atl1c_close - Disables a network interface * @netdev: network interface device structure * @@ -2417,7 +2432,7 @@ static int atl1c_init_netdev(struct net_device *netdev, struct pci_dev *pdev) return 0; } -/** +/* * atl1c_probe - Device Initialization Routine * @pdev: PCI device information struct * @ent: entry in atl1c_pci_tbl @@ -2564,7 +2579,7 @@ static int __devinit atl1c_probe(struct pci_dev *pdev, return err; } -/** +/* * atl1c_remove - Device Removal Routine * @pdev: PCI device information struct * @@ -2590,7 +2605,7 @@ static void __devexit atl1c_remove(struct pci_dev *pdev) free_netdev(netdev); } -/** +/* * atl1c_io_error_detected - called when PCI error is detected * @pdev: Pointer to PCI device * @state: The current pci connection state @@ -2618,7 +2633,7 @@ static pci_ers_result_t atl1c_io_error_detected(struct pci_dev *pdev, return PCI_ERS_RESULT_NEED_RESET; } -/** +/* * atl1c_io_slot_reset - called after the pci bus has been reset. * @pdev: Pointer to PCI device * @@ -2646,7 +2661,7 @@ static pci_ers_result_t atl1c_io_slot_reset(struct pci_dev *pdev) return PCI_ERS_RESULT_RECOVERED; } -/** +/* * atl1c_io_resume - called when traffic can start flowing again. * @pdev: Pointer to PCI device * @@ -2689,7 +2704,7 @@ static struct pci_driver atl1c_driver = { .driver.pm = &atl1c_pm_ops, }; -/** +/* * atl1c_init_module - Driver Registration Routine * * atl1c_init_module is the first routine called when the driver is @@ -2700,7 +2715,7 @@ static int __init atl1c_init_module(void) return pci_register_driver(&atl1c_driver); } -/** +/* * atl1c_exit_module - Driver Exit Cleanup Routine * * atl1c_exit_module is called just before the driver is removed diff --git a/trunk/drivers/net/ethernet/atheros/atl1e/atl1e_main.c b/trunk/drivers/net/ethernet/atheros/atl1e/atl1e_main.c index a98acc8a956f..0aed82e1bb3e 100644 --- a/trunk/drivers/net/ethernet/atheros/atl1e/atl1e_main.c +++ b/trunk/drivers/net/ethernet/atheros/atl1e/atl1e_main.c @@ -89,7 +89,7 @@ static const u16 atl1e_pay_load_size[] = { 128, 256, 512, 1024, 2048, 4096, }; -/** +/* * atl1e_irq_enable - Enable default interrupt generation settings * @adapter: board private structure */ @@ -102,7 +102,7 @@ static inline void atl1e_irq_enable(struct atl1e_adapter *adapter) } } -/** +/* * atl1e_irq_disable - Mask off interrupt generation on the NIC * @adapter: board private structure */ @@ -114,7 +114,7 @@ static inline void atl1e_irq_disable(struct atl1e_adapter *adapter) synchronize_irq(adapter->pdev->irq); } -/** +/* * atl1e_irq_reset - reset interrupt confiure on the NIC * @adapter: board private structure */ @@ -126,7 +126,7 @@ static inline void atl1e_irq_reset(struct atl1e_adapter *adapter) AT_WRITE_FLUSH(&adapter->hw); } -/** +/* * atl1e_phy_config - Timer Call-back * @data: pointer to netdev cast into an unsigned long */ @@ -210,7 +210,7 @@ static int atl1e_check_link(struct atl1e_adapter *adapter) return 0; } -/** +/* * atl1e_link_chg_task - deal with link change event Out of interrupt context * @netdev: network interface device structure */ @@ -259,7 +259,7 @@ static void atl1e_cancel_work(struct atl1e_adapter *adapter) cancel_work_sync(&adapter->link_chg_task); } -/** +/* * atl1e_tx_timeout - Respond to a Tx Hang * @netdev: network interface device structure */ @@ -271,7 +271,7 @@ static void atl1e_tx_timeout(struct net_device *netdev) schedule_work(&adapter->reset_task); } -/** +/* * atl1e_set_multi - Multicast and Promiscuous mode set * @netdev: network interface device structure * @@ -345,7 +345,7 @@ static void atl1e_restore_vlan(struct atl1e_adapter *adapter) atl1e_vlan_mode(adapter->netdev, adapter->netdev->features); } -/** +/* * atl1e_set_mac - Change the Ethernet Address of the NIC * @netdev: network interface device structure * @p: pointer to an address structure @@ -397,7 +397,7 @@ static int atl1e_set_features(struct net_device *netdev, return 0; } -/** +/* * atl1e_change_mtu - Change the Maximum Transfer Unit * @netdev: network interface device structure * @new_mtu: new value for maximum frame size @@ -449,6 +449,12 @@ static void atl1e_mdio_write(struct net_device *netdev, int phy_id, atl1e_write_phy_reg(&adapter->hw, reg_num & MDIO_REG_ADDR_MASK, val); } +/* + * atl1e_mii_ioctl - + * @netdev: + * @ifreq: + * @cmd: + */ static int atl1e_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) { @@ -499,6 +505,12 @@ static int atl1e_mii_ioctl(struct net_device *netdev, } +/* + * atl1e_ioctl - + * @netdev: + * @ifreq: + * @cmd: + */ static int atl1e_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) { switch (cmd) { @@ -529,7 +541,7 @@ static void atl1e_setup_pcicmd(struct pci_dev *pdev) msleep(1); } -/** +/* * atl1e_alloc_queues - Allocate memory for all rings * @adapter: board private structure to initialize * @@ -539,7 +551,7 @@ static int __devinit atl1e_alloc_queues(struct atl1e_adapter *adapter) return 0; } -/** +/* * atl1e_sw_init - Initialize general software structures (struct atl1e_adapter) * @adapter: board private structure to initialize * @@ -623,7 +635,7 @@ static int __devinit atl1e_sw_init(struct atl1e_adapter *adapter) return 0; } -/** +/* * atl1e_clean_tx_ring - Free Tx-skb * @adapter: board private structure */ @@ -666,7 +678,7 @@ static void atl1e_clean_tx_ring(struct atl1e_adapter *adapter) ring_count); } -/** +/* * atl1e_clean_rx_ring - Free rx-reservation skbs * @adapter: board private structure */ @@ -749,7 +761,7 @@ static void atl1e_init_ring_ptrs(struct atl1e_adapter *adapter) } } -/** +/* * atl1e_free_ring_resources - Free Tx / RX descriptor Resources * @adapter: board private structure * @@ -774,7 +786,7 @@ static void atl1e_free_ring_resources(struct atl1e_adapter *adapter) } } -/** +/* * atl1e_setup_mem_resources - allocate Tx / RX descriptor resources * @adapter: board private structure * @@ -1063,7 +1075,7 @@ static void atl1e_setup_mac_ctrl(struct atl1e_adapter *adapter) AT_WRITE_REG(hw, REG_MAC_CTRL, value); } -/** +/* * atl1e_configure - Configure Transmit&Receive Unit after Reset * @adapter: board private structure * @@ -1133,7 +1145,7 @@ static int atl1e_configure(struct atl1e_adapter *adapter) return 0; } -/** +/* * atl1e_get_stats - Get System Network Statistics * @netdev: network interface device structure * @@ -1245,10 +1257,11 @@ static bool atl1e_clean_tx_irq(struct atl1e_adapter *adapter) return true; } -/** +/* * atl1e_intr - Interrupt Handler * @irq: interrupt number * @data: pointer to a network interface device structure + * @pt_regs: CPU registers structure */ static irqreturn_t atl1e_intr(int irq, void *data) { @@ -1476,8 +1489,9 @@ static void atl1e_clean_rx_irq(struct atl1e_adapter *adapter, u8 que, schedule_work(&adapter->reset_task); } -/** +/* * atl1e_clean - NAPI Rx polling callback + * @adapter: board private structure */ static int atl1e_clean(struct napi_struct *napi, int budget) { @@ -1942,7 +1956,7 @@ void atl1e_down(struct atl1e_adapter *adapter) atl1e_clean_rx_ring(adapter); } -/** +/* * atl1e_open - Called when a network interface is made active * @netdev: network interface device structure * @@ -1988,7 +2002,7 @@ static int atl1e_open(struct net_device *netdev) return err; } -/** +/* * atl1e_close - Disables a network interface * @netdev: network interface device structure * @@ -2224,7 +2238,7 @@ static int atl1e_init_netdev(struct net_device *netdev, struct pci_dev *pdev) return 0; } -/** +/* * atl1e_probe - Device Initialization Routine * @pdev: PCI device information struct * @ent: entry in atl1e_pci_tbl @@ -2378,7 +2392,7 @@ static int __devinit atl1e_probe(struct pci_dev *pdev, return err; } -/** +/* * atl1e_remove - Device Removal Routine * @pdev: PCI device information struct * @@ -2410,7 +2424,7 @@ static void __devexit atl1e_remove(struct pci_dev *pdev) pci_disable_device(pdev); } -/** +/* * atl1e_io_error_detected - called when PCI error is detected * @pdev: Pointer to PCI device * @state: The current pci connection state @@ -2438,7 +2452,7 @@ atl1e_io_error_detected(struct pci_dev *pdev, pci_channel_state_t state) return PCI_ERS_RESULT_NEED_RESET; } -/** +/* * atl1e_io_slot_reset - called after the pci bus has been reset. * @pdev: Pointer to PCI device * @@ -2465,7 +2479,7 @@ static pci_ers_result_t atl1e_io_slot_reset(struct pci_dev *pdev) return PCI_ERS_RESULT_RECOVERED; } -/** +/* * atl1e_io_resume - called when traffic can start flowing again. * @pdev: Pointer to PCI device * @@ -2509,7 +2523,7 @@ static struct pci_driver atl1e_driver = { .err_handler = &atl1e_err_handler }; -/** +/* * atl1e_init_module - Driver Registration Routine * * atl1e_init_module is the first routine called when the driver is @@ -2520,7 +2534,7 @@ static int __init atl1e_init_module(void) return pci_register_driver(&atl1e_driver); } -/** +/* * atl1e_exit_module - Driver Exit Cleanup Routine * * atl1e_exit_module is called just before the driver is removed diff --git a/trunk/drivers/net/ethernet/atheros/atl1e/atl1e_param.c b/trunk/drivers/net/ethernet/atheros/atl1e/atl1e_param.c index b5086f1e637f..0ce60b6e7ef0 100644 --- a/trunk/drivers/net/ethernet/atheros/atl1e/atl1e_param.c +++ b/trunk/drivers/net/ethernet/atheros/atl1e/atl1e_param.c @@ -168,7 +168,7 @@ static int __devinit atl1e_validate_option(int *value, struct atl1e_option *opt, return -1; } -/** +/* * atl1e_check_options - Range Checking for Command Line Parameters * @adapter: board private structure * diff --git a/trunk/drivers/net/ethernet/atheros/atlx/atl1.c b/trunk/drivers/net/ethernet/atheros/atlx/atl1.c index 7bae2ad7a7c0..149a294d54e9 100644 --- a/trunk/drivers/net/ethernet/atheros/atlx/atl1.c +++ b/trunk/drivers/net/ethernet/atheros/atlx/atl1.c @@ -195,7 +195,7 @@ static int __devinit atl1_validate_option(int *value, struct atl1_option *opt, return -1; } -/** +/* * atl1_check_options - Range Checking for Command Line Parameters * @adapter: board private structure * @@ -538,7 +538,7 @@ static s32 atl1_read_mac_addr(struct atl1_hw *hw) u16 i; if (atl1_get_permanent_address(hw)) { - eth_random_addr(hw->perm_mac_addr); + random_ether_addr(hw->perm_mac_addr); ret = 1; } @@ -937,7 +937,7 @@ static void atl1_set_mac_addr(struct atl1_hw *hw) iowrite32(value, (hw->hw_addr + REG_MAC_STA_ADDR) + (1 << 2)); } -/** +/* * atl1_sw_init - Initialize general software structures (struct atl1_adapter) * @adapter: board private structure to initialize * @@ -1014,6 +1014,12 @@ static void mdio_write(struct net_device *netdev, int phy_id, int reg_num, atl1_write_phy_reg(&adapter->hw, reg_num, val); } +/* + * atl1_mii_ioctl - + * @netdev: + * @ifreq: + * @cmd: + */ static int atl1_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) { struct atl1_adapter *adapter = netdev_priv(netdev); @@ -1030,7 +1036,7 @@ static int atl1_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) return retval; } -/** +/* * atl1_setup_mem_resources - allocate Tx / RX descriptor resources * @adapter: board private structure * @@ -1141,7 +1147,7 @@ static void atl1_init_ring_ptrs(struct atl1_adapter *adapter) atomic_set(&rrd_ring->next_to_clean, 0); } -/** +/* * atl1_clean_rx_ring - Free RFD Buffers * @adapter: board private structure */ @@ -1181,7 +1187,7 @@ static void atl1_clean_rx_ring(struct atl1_adapter *adapter) atomic_set(&rrd_ring->next_to_clean, 0); } -/** +/* * atl1_clean_tx_ring - Free Tx Buffers * @adapter: board private structure */ @@ -1221,7 +1227,7 @@ static void atl1_clean_tx_ring(struct atl1_adapter *adapter) atomic_set(&tpd_ring->next_to_clean, 0); } -/** +/* * atl1_free_ring_resources - Free Tx / RX descriptor Resources * @adapter: board private structure * @@ -1464,7 +1470,7 @@ static void set_flow_ctrl_new(struct atl1_hw *hw) iowrite32(value, hw->hw_addr + REG_RXQ_RRD_PAUSE_THRESH); } -/** +/* * atl1_configure - Configure Transmit&Receive Unit after Reset * @adapter: board private structure * @@ -1838,7 +1844,7 @@ static void atl1_rx_checksum(struct atl1_adapter *adapter, } } -/** +/* * atl1_alloc_rx_buffers - Replace used receive buffers * @adapter: address of board private structure */ @@ -2483,10 +2489,11 @@ static inline int atl1_sched_rings_clean(struct atl1_adapter* adapter) return 1; } -/** +/* * atl1_intr - Interrupt Handler * @irq: interrupt number * @data: pointer to a network interface device structure + * @pt_regs: CPU registers structure */ static irqreturn_t atl1_intr(int irq, void *data) { @@ -2567,7 +2574,7 @@ static irqreturn_t atl1_intr(int irq, void *data) } -/** +/* * atl1_phy_config - Timer Call-back * @data: pointer to netdev cast into an unsigned long */ @@ -2686,7 +2693,7 @@ static void atl1_reset_dev_task(struct work_struct *work) netif_device_attach(netdev); } -/** +/* * atl1_change_mtu - Change the Maximum Transfer Unit * @netdev: network interface device structure * @new_mtu: new value for maximum frame size @@ -2720,7 +2727,7 @@ static int atl1_change_mtu(struct net_device *netdev, int new_mtu) return 0; } -/** +/* * atl1_open - Called when a network interface is made active * @netdev: network interface device structure * @@ -2755,7 +2762,7 @@ static int atl1_open(struct net_device *netdev) return err; } -/** +/* * atl1_close - Disables a network interface * @netdev: network interface device structure * @@ -2923,7 +2930,7 @@ static const struct net_device_ops atl1_netdev_ops = { #endif }; -/** +/* * atl1_probe - Device Initialization Routine * @pdev: PCI device information struct * @ent: entry in atl1_pci_tbl @@ -3104,7 +3111,7 @@ static int __devinit atl1_probe(struct pci_dev *pdev, return err; } -/** +/* * atl1_remove - Device Removal Routine * @pdev: PCI device information struct * @@ -3151,7 +3158,7 @@ static struct pci_driver atl1_driver = { .driver.pm = ATL1_PM_OPS, }; -/** +/* * atl1_exit_module - Driver Exit Cleanup Routine * * atl1_exit_module is called just before the driver is removed @@ -3162,7 +3169,7 @@ static void __exit atl1_exit_module(void) pci_unregister_driver(&atl1_driver); } -/** +/* * atl1_init_module - Driver Registration Routine * * atl1_init_module is the first routine called when the driver is diff --git a/trunk/drivers/net/ethernet/atheros/atlx/atl2.c b/trunk/drivers/net/ethernet/atheros/atlx/atl2.c index 57d64b80fd72..6762dc406b25 100644 --- a/trunk/drivers/net/ethernet/atheros/atlx/atl2.c +++ b/trunk/drivers/net/ethernet/atheros/atlx/atl2.c @@ -75,7 +75,7 @@ static void atl2_set_ethtool_ops(struct net_device *netdev); static void atl2_check_options(struct atl2_adapter *adapter); -/** +/* * atl2_sw_init - Initialize general software structures (struct atl2_adapter) * @adapter: board private structure to initialize * @@ -123,7 +123,7 @@ static int __devinit atl2_sw_init(struct atl2_adapter *adapter) return 0; } -/** +/* * atl2_set_multi - Multicast and Promiscuous mode set * @netdev: network interface device structure * @@ -177,7 +177,7 @@ static void init_ring_ptrs(struct atl2_adapter *adapter) adapter->txs_next_clear = 0; } -/** +/* * atl2_configure - Configure Transmit&Receive Unit after Reset * @adapter: board private structure * @@ -283,7 +283,7 @@ static int atl2_configure(struct atl2_adapter *adapter) return value; } -/** +/* * atl2_setup_ring_resources - allocate Tx / RX descriptor resources * @adapter: board private structure * @@ -340,7 +340,7 @@ static s32 atl2_setup_ring_resources(struct atl2_adapter *adapter) return 0; } -/** +/* * atl2_irq_enable - Enable default interrupt generation settings * @adapter: board private structure */ @@ -350,7 +350,7 @@ static inline void atl2_irq_enable(struct atl2_adapter *adapter) ATL2_WRITE_FLUSH(&adapter->hw); } -/** +/* * atl2_irq_disable - Mask off interrupt generation on the NIC * @adapter: board private structure */ @@ -599,10 +599,11 @@ static inline void atl2_clear_phy_int(struct atl2_adapter *adapter) spin_unlock(&adapter->stats_lock); } -/** +/* * atl2_intr - Interrupt Handler * @irq: interrupt number * @data: pointer to a network interface device structure + * @pt_regs: CPU registers structure */ static irqreturn_t atl2_intr(int irq, void *data) { @@ -678,7 +679,7 @@ static int atl2_request_irq(struct atl2_adapter *adapter) netdev); } -/** +/* * atl2_free_ring_resources - Free Tx / RX descriptor Resources * @adapter: board private structure * @@ -691,7 +692,7 @@ static void atl2_free_ring_resources(struct atl2_adapter *adapter) adapter->ring_dma); } -/** +/* * atl2_open - Called when a network interface is made active * @netdev: network interface device structure * @@ -797,7 +798,7 @@ static void atl2_free_irq(struct atl2_adapter *adapter) #endif } -/** +/* * atl2_close - Disables a network interface * @netdev: network interface device structure * @@ -917,7 +918,7 @@ static netdev_tx_t atl2_xmit_frame(struct sk_buff *skb, return NETDEV_TX_OK; } -/** +/* * atl2_change_mtu - Change the Maximum Transfer Unit * @netdev: network interface device structure * @new_mtu: new value for maximum frame size @@ -942,7 +943,7 @@ static int atl2_change_mtu(struct net_device *netdev, int new_mtu) return 0; } -/** +/* * atl2_set_mac - Change the Ethernet Address of the NIC * @netdev: network interface device structure * @p: pointer to an address structure @@ -968,6 +969,12 @@ static int atl2_set_mac(struct net_device *netdev, void *p) return 0; } +/* + * atl2_mii_ioctl - + * @netdev: + * @ifreq: + * @cmd: + */ static int atl2_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) { struct atl2_adapter *adapter = netdev_priv(netdev); @@ -1004,6 +1011,12 @@ static int atl2_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) return 0; } +/* + * atl2_ioctl - + * @netdev: + * @ifreq: + * @cmd: + */ static int atl2_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) { switch (cmd) { @@ -1020,7 +1033,7 @@ static int atl2_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) } } -/** +/* * atl2_tx_timeout - Respond to a Tx Hang * @netdev: network interface device structure */ @@ -1032,7 +1045,7 @@ static void atl2_tx_timeout(struct net_device *netdev) schedule_work(&adapter->reset_task); } -/** +/* * atl2_watchdog - Timer Call-back * @data: pointer to netdev cast into an unsigned long */ @@ -1057,7 +1070,7 @@ static void atl2_watchdog(unsigned long data) } } -/** +/* * atl2_phy_config - Timer Call-back * @data: pointer to netdev cast into an unsigned long */ @@ -1261,8 +1274,9 @@ static int atl2_check_link(struct atl2_adapter *adapter) return 0; } -/** +/* * atl2_link_chg_task - deal with link change event Out of interrupt context + * @netdev: network interface device structure */ static void atl2_link_chg_task(struct work_struct *work) { @@ -1327,7 +1341,7 @@ static const struct net_device_ops atl2_netdev_ops = { #endif }; -/** +/* * atl2_probe - Device Initialization Routine * @pdev: PCI device information struct * @ent: entry in atl2_pci_tbl @@ -1487,7 +1501,7 @@ static int __devinit atl2_probe(struct pci_dev *pdev, return err; } -/** +/* * atl2_remove - Device Removal Routine * @pdev: PCI device information struct * @@ -1714,7 +1728,7 @@ static struct pci_driver atl2_driver = { .shutdown = atl2_shutdown, }; -/** +/* * atl2_init_module - Driver Registration Routine * * atl2_init_module is the first routine called when the driver is @@ -1729,7 +1743,7 @@ static int __init atl2_init_module(void) } module_init(atl2_init_module); -/** +/* * atl2_exit_module - Driver Exit Cleanup Routine * * atl2_exit_module is called just before the driver is removed @@ -2346,7 +2360,7 @@ static s32 atl2_read_mac_addr(struct atl2_hw *hw) { if (get_permanent_address(hw)) { /* for test */ - /* FIXME: shouldn't we use eth_random_addr() here? */ + /* FIXME: shouldn't we use random_ether_addr() here? */ hw->perm_mac_addr[0] = 0x00; hw->perm_mac_addr[1] = 0x13; hw->perm_mac_addr[2] = 0x74; @@ -2983,7 +2997,7 @@ static int __devinit atl2_validate_option(int *value, struct atl2_option *opt) return -1; } -/** +/* * atl2_check_options - Range Checking for Command Line Parameters * @adapter: board private structure * diff --git a/trunk/drivers/net/ethernet/atheros/atlx/atlx.c b/trunk/drivers/net/ethernet/atheros/atlx/atlx.c index 77ffbc4a5071..b4f3aa49a7fc 100644 --- a/trunk/drivers/net/ethernet/atheros/atlx/atlx.c +++ b/trunk/drivers/net/ethernet/atheros/atlx/atlx.c @@ -64,7 +64,7 @@ static int atlx_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) } } -/** +/* * atlx_set_mac - Change the Ethernet Address of the NIC * @netdev: network interface device structure * @p: pointer to an address structure @@ -115,7 +115,7 @@ static void atlx_check_for_link(struct atlx_adapter *adapter) schedule_work(&adapter->link_chg_task); } -/** +/* * atlx_set_multi - Multicast and Promiscuous mode set * @netdev: network interface device structure * @@ -162,7 +162,7 @@ static inline void atlx_imr_set(struct atlx_adapter *adapter, ioread32(adapter->hw.hw_addr + REG_IMR); } -/** +/* * atlx_irq_enable - Enable default interrupt generation settings * @adapter: board private structure */ @@ -172,7 +172,7 @@ static void atlx_irq_enable(struct atlx_adapter *adapter) adapter->int_enabled = true; } -/** +/* * atlx_irq_disable - Mask off interrupt generation on the NIC * @adapter: board private structure */ @@ -193,7 +193,7 @@ static void atlx_clear_phy_int(struct atlx_adapter *adapter) spin_unlock_irqrestore(&adapter->lock, flags); } -/** +/* * atlx_tx_timeout - Respond to a Tx Hang * @netdev: network interface device structure */ diff --git a/trunk/drivers/net/ethernet/broadcom/b44.c b/trunk/drivers/net/ethernet/broadcom/b44.c index d09c6b583d17..46b8b7d81633 100644 --- a/trunk/drivers/net/ethernet/broadcom/b44.c +++ b/trunk/drivers/net/ethernet/broadcom/b44.c @@ -656,7 +656,7 @@ static int b44_alloc_rx_skb(struct b44 *bp, int src_idx, u32 dest_idx_unmasked) dma_unmap_single(bp->sdev->dma_dev, mapping, RX_PKT_BUF_SZ, DMA_FROM_DEVICE); dev_kfree_skb_any(skb); - skb = alloc_skb(RX_PKT_BUF_SZ, GFP_ATOMIC | GFP_DMA); + skb = __netdev_alloc_skb(bp->dev, RX_PKT_BUF_SZ, GFP_ATOMIC|GFP_DMA); if (skb == NULL) return -ENOMEM; mapping = dma_map_single(bp->sdev->dma_dev, skb->data, @@ -967,7 +967,7 @@ static netdev_tx_t b44_start_xmit(struct sk_buff *skb, struct net_device *dev) dma_unmap_single(bp->sdev->dma_dev, mapping, len, DMA_TO_DEVICE); - bounce_skb = alloc_skb(len, GFP_ATOMIC | GFP_DMA); + bounce_skb = __netdev_alloc_skb(dev, len, GFP_ATOMIC | GFP_DMA); if (!bounce_skb) goto err_out; diff --git a/trunk/drivers/net/ethernet/broadcom/bnx2.c b/trunk/drivers/net/ethernet/broadcom/bnx2.c index 79cebd8525ce..1901da153312 100644 --- a/trunk/drivers/net/ethernet/broadcom/bnx2.c +++ b/trunk/drivers/net/ethernet/broadcom/bnx2.c @@ -5377,7 +5377,7 @@ bnx2_free_tx_skbs(struct bnx2 *bp) int k, last; if (skb == NULL) { - j = NEXT_TX_BD(j); + j++; continue; } @@ -5389,8 +5389,8 @@ bnx2_free_tx_skbs(struct bnx2 *bp) tx_buf->skb = NULL; last = tx_buf->nr_frags; - j = NEXT_TX_BD(j); - for (k = 0; k < last; k++, j = NEXT_TX_BD(j)) { + j++; + for (k = 0; k < last; k++, j++) { tx_buf = &txr->tx_buf_ring[TX_RING_IDX(j)]; dma_unmap_page(&bp->pdev->dev, dma_unmap_addr(tx_buf, mapping), @@ -6388,7 +6388,6 @@ bnx2_reset_task(struct work_struct *work) { struct bnx2 *bp = container_of(work, struct bnx2, reset_task); int rc; - u16 pcicmd; rtnl_lock(); if (!netif_running(bp->dev)) { @@ -6398,12 +6397,6 @@ bnx2_reset_task(struct work_struct *work) bnx2_netif_stop(bp, true); - pci_read_config_word(bp->pdev, PCI_COMMAND, &pcicmd); - if (!(pcicmd & PCI_COMMAND_MEMORY)) { - /* in case PCI block has reset */ - pci_restore_state(bp->pdev); - pci_save_state(bp->pdev); - } rc = bnx2_init_nic(bp, 1); if (rc) { netdev_err(bp->dev, "failed to reset NIC, closing\n"); diff --git a/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h b/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h index dbe97918a7fd..362d16f1d256 100644 --- a/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h +++ b/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h @@ -454,7 +454,6 @@ struct bnx2x_agg_info { u16 vlan_tag; u16 len_on_bd; u32 rxhash; - bool l4_rxhash; u16 gro_size; u16 full_page; }; @@ -614,22 +613,6 @@ struct bnx2x_fastpath { #define TX_BD(x) ((x) & MAX_TX_BD) #define TX_BD_POFF(x) ((x) & MAX_TX_DESC_CNT) -/* number of NEXT_PAGE descriptors may be required during placement */ -#define NEXT_CNT_PER_TX_PKT(bds) \ - (((bds) + MAX_TX_DESC_CNT - 1) / \ - MAX_TX_DESC_CNT * NEXT_PAGE_TX_DESC_CNT) -/* max BDs per tx packet w/o next_pages: - * START_BD - describes packed - * START_BD(splitted) - includes unpaged data segment for GSO - * PARSING_BD - for TSO and CSUM data - * Frag BDs - decribes pages for frags - */ -#define BDS_PER_TX_PKT 3 -#define MAX_BDS_PER_TX_PKT (MAX_SKB_FRAGS + BDS_PER_TX_PKT) -/* max BDs per tx packet including next pages */ -#define MAX_DESC_PER_TX_PKT (MAX_BDS_PER_TX_PKT + \ - NEXT_CNT_PER_TX_PKT(MAX_BDS_PER_TX_PKT)) - /* The RX BD ring is special, each bd is 8 bytes but the last one is 16 */ #define NUM_RX_RINGS 8 #define RX_DESC_CNT (BCM_PAGE_SIZE / sizeof(struct eth_rx_bd)) @@ -1756,6 +1739,15 @@ struct bnx2x_func_init_params { int bnx2x_set_mac_one(struct bnx2x *bp, u8 *mac, struct bnx2x_vlan_mac_obj *obj, bool set, int mac_type, unsigned long *ramrod_flags); +/** + * Deletes all MACs configured for the specific MAC object. + * + * @param bp Function driver instance + * @param mac_obj MAC object to cleanup + * + * @return zero if all MACs were cleaned + */ + /** * bnx2x_del_all_macs - delete all MACs configured for the specific MAC object * diff --git a/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c index e879e19eb0d6..00951b3aa62b 100644 --- a/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c +++ b/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c @@ -221,7 +221,7 @@ int bnx2x_tx_int(struct bnx2x *bp, struct bnx2x_fp_txdata *txdata) if ((netif_tx_queue_stopped(txq)) && (bp->state == BNX2X_STATE_OPEN) && - (bnx2x_tx_avail(bp, txdata) >= MAX_DESC_PER_TX_PKT)) + (bnx2x_tx_avail(bp, txdata) >= MAX_SKB_FRAGS + 4)) netif_tx_wake_queue(txq); __netif_tx_unlock(txq); @@ -295,20 +295,12 @@ static inline void bnx2x_update_sge_prod(struct bnx2x_fastpath *fp, * CQE (calculated by HW). */ static u32 bnx2x_get_rxhash(const struct bnx2x *bp, - const struct eth_fast_path_rx_cqe *cqe, - bool *l4_rxhash) + const struct eth_fast_path_rx_cqe *cqe) { /* Set Toeplitz hash from CQE */ if ((bp->dev->features & NETIF_F_RXHASH) && - (cqe->status_flags & ETH_FAST_PATH_RX_CQE_RSS_HASH_FLG)) { - enum eth_rss_hash_type htype; - - htype = cqe->status_flags & ETH_FAST_PATH_RX_CQE_RSS_HASH_TYPE; - *l4_rxhash = (htype == TCP_IPV4_HASH_TYPE) || - (htype == TCP_IPV6_HASH_TYPE); + (cqe->status_flags & ETH_FAST_PATH_RX_CQE_RSS_HASH_FLG)) return le32_to_cpu(cqe->rss_hash_result); - } - *l4_rxhash = false; return 0; } @@ -362,7 +354,7 @@ static void bnx2x_tpa_start(struct bnx2x_fastpath *fp, u16 queue, tpa_info->tpa_state = BNX2X_TPA_START; tpa_info->len_on_bd = le16_to_cpu(cqe->len_on_bd); tpa_info->placement_offset = cqe->placement_offset; - tpa_info->rxhash = bnx2x_get_rxhash(bp, cqe, &tpa_info->l4_rxhash); + tpa_info->rxhash = bnx2x_get_rxhash(bp, cqe); if (fp->mode == TPA_MODE_GRO) { u16 gro_size = le16_to_cpu(cqe->pkt_len_or_gro_seg_len); tpa_info->full_page = @@ -597,7 +589,6 @@ static void bnx2x_tpa_stop(struct bnx2x *bp, struct bnx2x_fastpath *fp, skb_reserve(skb, pad + NET_SKB_PAD); skb_put(skb, len); skb->rxhash = tpa_info->rxhash; - skb->l4_rxhash = tpa_info->l4_rxhash; skb->protocol = eth_type_trans(skb, bp->dev); skb->ip_summed = CHECKSUM_UNNECESSARY; @@ -721,7 +712,6 @@ int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget) enum eth_rx_cqe_type cqe_fp_type; u16 len, pad, queue; u8 *data; - bool l4_rxhash; #ifdef BNX2X_STOP_ON_ERROR if (unlikely(bp->panic)) @@ -865,8 +855,7 @@ int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget) skb->protocol = eth_type_trans(skb, bp->dev); /* Set Toeplitz hash for a none-LRO skb */ - skb->rxhash = bnx2x_get_rxhash(bp, cqe_fp, &l4_rxhash); - skb->l4_rxhash = l4_rxhash; + skb->rxhash = bnx2x_get_rxhash(bp, cqe_fp); skb_checksum_none_assert(skb); @@ -2948,9 +2937,7 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev) txdata->cid, fp_index, txdata_index, txdata, fp); */ if (unlikely(bnx2x_tx_avail(bp, txdata) < - skb_shinfo(skb)->nr_frags + - BDS_PER_TX_PKT + - NEXT_CNT_PER_TX_PKT(MAX_BDS_PER_TX_PKT))) { + (skb_shinfo(skb)->nr_frags + 3))) { bnx2x_fp_qstats(bp, txdata->parent_fp)->driver_xoff++; netif_tx_stop_queue(txq); BNX2X_ERR("BUG! Tx ring full when queue awake!\n"); @@ -3225,7 +3212,7 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev) txdata->tx_bd_prod += nbd; - if (unlikely(bnx2x_tx_avail(bp, txdata) < MAX_DESC_PER_TX_PKT)) { + if (unlikely(bnx2x_tx_avail(bp, txdata) < MAX_SKB_FRAGS + 4)) { netif_tx_stop_queue(txq); /* paired memory barrier is in bnx2x_tx_int(), we have to keep @@ -3234,7 +3221,7 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev) smp_mb(); bnx2x_fp_qstats(bp, txdata->parent_fp)->driver_xoff++; - if (bnx2x_tx_avail(bp, txdata) >= MAX_DESC_PER_TX_PKT) + if (bnx2x_tx_avail(bp, txdata) >= MAX_SKB_FRAGS + 4) netif_tx_wake_queue(txq); } txdata->tx_pkt++; diff --git a/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h b/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h index dfa757e74296..53659f321d51 100644 --- a/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h +++ b/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h @@ -90,7 +90,7 @@ void bnx2x_send_unload_done(struct bnx2x *bp); * bnx2x_config_rss_pf - configure RSS parameters in a PF. * * @bp: driver handle - * @rss_obj: RSS object to use + * @rss_obj RSS object to use * @ind_table: indirection table to configure * @config_hash: re-configure RSS hash keys configuration */ 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 bbc66ced9c25..426f77aa721a 100644 --- a/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_fw_defs.h +++ b/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_fw_defs.h @@ -321,7 +321,9 @@ #define DISABLE_STATISTIC_COUNTER_ID_VALUE 0 -/* This file defines HSI constants common to all microcode flows */ +/** + * This file defines HSI constants common to all microcode flows + */ #define PROTOCOL_STATE_BIT_OFFSET 6 diff --git a/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h b/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h index 51cac8130051..c05f9d94938f 100644 --- a/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h +++ b/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h @@ -493,7 +493,8 @@ struct bnx2x_ets_params { struct bnx2x_ets_cos_params cos[DCBX_MAX_NUM_COS]; }; -/* Used to update the PFC attributes in EMAC, BMAC, NIG and BRB +/** + * Used to update the PFC attributes in EMAC, BMAC, NIG and BRB * when link is already up */ int bnx2x_update_pfc(struct link_params *params, diff --git a/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index 08eca3ff7db6..5b8b521bdbc3 100644 --- a/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c @@ -11560,7 +11560,8 @@ static void bnx2x_prep_ops(const u8 *_source, u8 *_target, u32 n) } } -/* IRO array is stored in the following format: +/** + * IRO array is stored in the following format: * {base(24bit), m1(16bit), m2(16bit), m3(16bit), size(16bit) } */ static void bnx2x_prep_iro(const u8 *_source, u8 *_target, u32 n) diff --git a/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h b/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h index ec62a5c8bd37..f371e3c06094 100644 --- a/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h +++ b/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h @@ -7275,7 +7275,8 @@ Theotherbitsarereservedandshouldbezero*/ #define CDU_REGION_NUMBER_UCM_AG 4 -/* String-to-compress [31:8] = CID (all 24 bits) +/** + * String-to-compress [31:8] = CID (all 24 bits) * String-to-compress [7:4] = Region * String-to-compress [3:0] = Type */ diff --git a/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h b/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h index f83e033da6da..76818ef08f9b 100644 --- a/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h +++ b/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h @@ -167,8 +167,9 @@ typedef int (*exe_q_remove)(struct bnx2x *bp, union bnx2x_qable_obj *o, struct bnx2x_exeq_elem *elem); -/* Return positive if entry was optimized, 0 - if not, negative - * in case of an error. +/** + * @return positive is entry was optimized, 0 - if not, negative + * in case of an error. */ typedef int (*exe_q_optimize)(struct bnx2x *bp, union bnx2x_qable_obj *o, @@ -1285,11 +1286,12 @@ void bnx2x_init_rx_mode_obj(struct bnx2x *bp, struct bnx2x_rx_mode_obj *o); /** - * bnx2x_config_rx_mode - Send and RX_MODE ramrod according to the provided parameters. + * Send and RX_MODE ramrod according to the provided parameters. * - * @p: Command parameters + * @param bp + * @param p Command parameters * - * Return: 0 - if operation was successfull and there is no pending completions, + * @return 0 - if operation was successfull and there is no pending completions, * positive number - if there are pending completions, * negative - if there were errors */ @@ -1306,11 +1308,7 @@ void bnx2x_init_mcast_obj(struct bnx2x *bp, bnx2x_obj_type type); /** - * bnx2x_config_mcast - Configure multicast MACs list. - * - * @cmd: command to execute: BNX2X_MCAST_CMD_X - * - * May configure a new list + * Configure multicast MACs list. May configure a new list * provided in p->mcast_list (BNX2X_MCAST_CMD_ADD), clean up * (BNX2X_MCAST_CMD_DEL) or restore (BNX2X_MCAST_CMD_RESTORE) a current * configuration, continue to execute the pending commands @@ -1321,7 +1319,11 @@ void bnx2x_init_mcast_obj(struct bnx2x *bp, * the current command will be enqueued to the tail of the * pending commands list. * - * Return: 0 is operation was sucessfull and there are no pending completions, + * @param bp + * @param p + * @param command to execute: BNX2X_MCAST_CMD_X + * + * @return 0 is operation was sucessfull and there are no pending completions, * negative if there were errors, positive if there are pending * completions. */ @@ -1346,17 +1348,21 @@ void bnx2x_init_rss_config_obj(struct bnx2x *bp, bnx2x_obj_type type); /** - * bnx2x_config_rss - Updates RSS configuration according to provided parameters + * Updates RSS configuration according to provided parameters. + * + * @param bp + * @param p * - * Return: 0 in case of success + * @return 0 in case of success */ int bnx2x_config_rss(struct bnx2x *bp, struct bnx2x_config_rss_params *p); /** - * bnx2x_get_rss_ind_table - Return the current ind_table configuration. + * Return the current ind_table configuration. * - * @ind_table: buffer to fill with the current indirection + * @param bp + * @param ind_table buffer to fill with the current indirection * table content. Should be at least * T_ETH_INDIRECTION_TABLE_SIZE bytes long. */ diff --git a/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c b/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c index 667d89042d35..514a528f6ddf 100644 --- a/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c +++ b/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c @@ -1321,9 +1321,12 @@ static void bnx2x_port_stats_base_init(struct bnx2x *bp) bnx2x_stats_comp(bp); } -/* This function will prepare the statistics ramrod data the way +/** + * This function will prepare the statistics ramrod data the way * we will only have to increment the statistics counter and * send the ramrod each time we have to. + * + * @param bp */ static void bnx2x_prep_fw_stats_req(struct bnx2x *bp) { diff --git a/trunk/drivers/net/ethernet/broadcom/cnic.c b/trunk/drivers/net/ethernet/broadcom/cnic.c index 3b4fc61f24cf..22ad7b6d9048 100644 --- a/trunk/drivers/net/ethernet/broadcom/cnic.c +++ b/trunk/drivers/net/ethernet/broadcom/cnic.c @@ -542,8 +542,7 @@ int cnic_unregister_driver(int ulp_type) } if (atomic_read(&ulp_ops->ref_count) != 0) - pr_warn("%s: Failed waiting for ref count to go to zero\n", - __func__); + netdev_warn(dev->netdev, "Failed waiting for ref count to go to zero\n"); return 0; out_unlock: @@ -5543,7 +5542,9 @@ static void cnic_rcv_netevent(struct cnic_local *cp, unsigned long event, rcu_read_unlock(); } -/* netdev event handler */ +/** + * netdev event handler + */ static int cnic_netdev_event(struct notifier_block *this, unsigned long event, void *ptr) { diff --git a/trunk/drivers/net/ethernet/broadcom/tg3.c b/trunk/drivers/net/ethernet/broadcom/tg3.c index fce4c1e4dd3f..6cbab0369738 100644 --- a/trunk/drivers/net/ethernet/broadcom/tg3.c +++ b/trunk/drivers/net/ethernet/broadcom/tg3.c @@ -44,10 +44,6 @@ #include #include #include -#if IS_ENABLED(CONFIG_HWMON) -#include -#include -#endif #include #include @@ -302,7 +298,6 @@ static DEFINE_PCI_DEVICE_TABLE(tg3_pci_tbl) = { {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57795)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5719)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5720)}, - {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57762)}, {PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_9DXX)}, {PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_9MXX)}, {PCI_DEVICE(PCI_VENDOR_ID_ALTIMA, PCI_DEVICE_ID_ALTIMA_AC1000)}, @@ -735,131 +730,44 @@ static void tg3_ape_unlock(struct tg3 *tp, int locknum) tg3_ape_write32(tp, gnt + 4 * locknum, bit); } -static int tg3_ape_event_lock(struct tg3 *tp, u32 timeout_us) +static void tg3_ape_send_event(struct tg3 *tp, u32 event) { + int i; u32 apedata; - while (timeout_us) { - if (tg3_ape_lock(tp, TG3_APE_LOCK_MEM)) - return -EBUSY; - - apedata = tg3_ape_read32(tp, TG3_APE_EVENT_STATUS); - if (!(apedata & APE_EVENT_STATUS_EVENT_PENDING)) - break; - - tg3_ape_unlock(tp, TG3_APE_LOCK_MEM); - - udelay(10); - timeout_us -= (timeout_us > 10) ? 10 : timeout_us; - } - - return timeout_us ? 0 : -EBUSY; -} - -static int tg3_ape_wait_for_event(struct tg3 *tp, u32 timeout_us) -{ - u32 i, apedata; - - for (i = 0; i < timeout_us / 10; i++) { - apedata = tg3_ape_read32(tp, TG3_APE_EVENT_STATUS); - - if (!(apedata & APE_EVENT_STATUS_EVENT_PENDING)) - break; - - udelay(10); - } - - return i == timeout_us / 10; -} - -int tg3_ape_scratchpad_read(struct tg3 *tp, u32 *data, u32 base_off, u32 len) -{ - int err; - u32 i, bufoff, msgoff, maxlen, apedata; - - if (!tg3_flag(tp, APE_HAS_NCSI)) - return 0; + /* NCSI does not support APE events */ + if (tg3_flag(tp, APE_HAS_NCSI)) + return; apedata = tg3_ape_read32(tp, TG3_APE_SEG_SIG); if (apedata != APE_SEG_SIG_MAGIC) - return -ENODEV; + return; apedata = tg3_ape_read32(tp, TG3_APE_FW_STATUS); if (!(apedata & APE_FW_STATUS_READY)) - return -EAGAIN; - - bufoff = tg3_ape_read32(tp, TG3_APE_SEG_MSG_BUF_OFF) + - TG3_APE_SHMEM_BASE; - msgoff = bufoff + 2 * sizeof(u32); - maxlen = tg3_ape_read32(tp, TG3_APE_SEG_MSG_BUF_LEN); - - while (len) { - u32 length; - - /* Cap xfer sizes to scratchpad limits. */ - length = (len > maxlen) ? maxlen : len; - len -= length; - - apedata = tg3_ape_read32(tp, TG3_APE_FW_STATUS); - if (!(apedata & APE_FW_STATUS_READY)) - return -EAGAIN; + return; - /* Wait for up to 1 msec for APE to service previous event. */ - err = tg3_ape_event_lock(tp, 1000); - if (err) - return err; + /* Wait for up to 1 millisecond for APE to service previous event. */ + for (i = 0; i < 10; i++) { + if (tg3_ape_lock(tp, TG3_APE_LOCK_MEM)) + return; - apedata = APE_EVENT_STATUS_DRIVER_EVNT | - APE_EVENT_STATUS_SCRTCHPD_READ | - APE_EVENT_STATUS_EVENT_PENDING; - tg3_ape_write32(tp, TG3_APE_EVENT_STATUS, apedata); + apedata = tg3_ape_read32(tp, TG3_APE_EVENT_STATUS); - tg3_ape_write32(tp, bufoff, base_off); - tg3_ape_write32(tp, bufoff + sizeof(u32), length); + if (!(apedata & APE_EVENT_STATUS_EVENT_PENDING)) + tg3_ape_write32(tp, TG3_APE_EVENT_STATUS, + event | APE_EVENT_STATUS_EVENT_PENDING); tg3_ape_unlock(tp, TG3_APE_LOCK_MEM); - tg3_ape_write32(tp, TG3_APE_EVENT, APE_EVENT_1); - - base_off += length; - if (tg3_ape_wait_for_event(tp, 30000)) - return -EAGAIN; + if (!(apedata & APE_EVENT_STATUS_EVENT_PENDING)) + break; - for (i = 0; length; i += 4, length -= 4) { - u32 val = tg3_ape_read32(tp, msgoff + i); - memcpy(data, &val, sizeof(u32)); - data++; - } + udelay(100); } - return 0; -} - -static int tg3_ape_send_event(struct tg3 *tp, u32 event) -{ - int err; - u32 apedata; - - apedata = tg3_ape_read32(tp, TG3_APE_SEG_SIG); - if (apedata != APE_SEG_SIG_MAGIC) - return -EAGAIN; - - apedata = tg3_ape_read32(tp, TG3_APE_FW_STATUS); - if (!(apedata & APE_FW_STATUS_READY)) - return -EAGAIN; - - /* Wait for up to 1 millisecond for APE to service previous event. */ - err = tg3_ape_event_lock(tp, 1000); - if (err) - return err; - - tg3_ape_write32(tp, TG3_APE_EVENT_STATUS, - event | APE_EVENT_STATUS_EVENT_PENDING); - - tg3_ape_unlock(tp, TG3_APE_LOCK_MEM); - tg3_ape_write32(tp, TG3_APE_EVENT, APE_EVENT_1); - - return 0; + if (!(apedata & APE_EVENT_STATUS_EVENT_PENDING)) + tg3_ape_write32(tp, TG3_APE_EVENT, APE_EVENT_1); } static void tg3_ape_driver_state_change(struct tg3 *tp, int kind) @@ -9485,110 +9393,6 @@ 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; - - for (i = 0; i < TG3_SD_NUM_RECS; i++, ocir++) { - u32 off = i * TG3_OCIR_LEN, len = TG3_OCIR_LEN; - - tg3_ape_scratchpad_read(tp, (u32 *) ocir, off, len); - off += len; - - if (ocir->signature != TG3_OCIR_SIG_MAGIC || - !(ocir->version_flags & TG3_OCIR_FLAG_ACTIVE)) - memset(ocir, 0, TG3_OCIR_LEN); - } -} - -/* sysfs attributes for hwmon */ -static ssize_t tg3_show_temp(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - struct pci_dev *pdev = to_pci_dev(dev); - struct net_device *netdev = pci_get_drvdata(pdev); - struct tg3 *tp = netdev_priv(netdev); - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - u32 temperature; - - spin_lock_bh(&tp->lock); - tg3_ape_scratchpad_read(tp, &temperature, attr->index, - sizeof(temperature)); - spin_unlock_bh(&tp->lock); - return sprintf(buf, "%u\n", temperature); -} - - -static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, tg3_show_temp, NULL, - TG3_TEMP_SENSOR_OFFSET); -static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, tg3_show_temp, NULL, - TG3_TEMP_CAUTION_OFFSET); -static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO, tg3_show_temp, NULL, - TG3_TEMP_MAX_OFFSET); - -static struct attribute *tg3_attributes[] = { - &sensor_dev_attr_temp1_input.dev_attr.attr, - &sensor_dev_attr_temp1_crit.dev_attr.attr, - &sensor_dev_attr_temp1_max.dev_attr.attr, - NULL -}; - -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; - struct tg3_ocir ocirs[TG3_SD_NUM_RECS]; - - tg3_sd_scan_scratchpad(tp, ocirs); - - for (i = 0; i < TG3_SD_NUM_RECS; i++) { - if (!ocirs[i].src_data_length) - continue; - - size += ocirs[i].src_hdr_length; - size += ocirs[i].src_data_length; - } - - if (!size) - return; - - /* Register hwmon sysfs hooks */ - err = sysfs_create_group(&pdev->dev.kobj, &tg3_group); - if (err) { - dev_err(&pdev->dev, "Cannot create sysfs group, aborting\n"); - return; - } - - tp->hwmon_dev = hwmon_device_register(&pdev->dev); - if (IS_ERR(tp->hwmon_dev)) { - tp->hwmon_dev = NULL; - dev_err(&pdev->dev, "Cannot register hwmon device, aborting\n"); - sysfs_remove_group(&pdev->dev.kobj, &tg3_group); - } -#endif -} - - #define TG3_STAT_ADD32(PSTAT, REG) \ do { u32 __val = tr32(REG); \ (PSTAT)->low += __val; \ @@ -10297,8 +10101,6 @@ static int tg3_open(struct net_device *dev) tg3_phy_start(tp); - tg3_hwmon_open(tp); - tg3_full_lock(tp, 0); tg3_timer_start(tp); @@ -10348,8 +10150,6 @@ static int tg3_close(struct net_device *dev) tg3_timer_stop(tp); - tg3_hwmon_close(tp); - tg3_phy_stop(tp); tg3_full_lock(tp, 1); @@ -14057,9 +13857,14 @@ static void __devinit tg3_read_mgmtfw_ver(struct tg3 *tp) } } -static void __devinit tg3_probe_ncsi(struct tg3 *tp) +static void __devinit tg3_read_dash_ver(struct tg3 *tp) { + int vlen; u32 apedata; + char *fwtype; + + if (!tg3_flag(tp, ENABLE_APE) || !tg3_flag(tp, ENABLE_ASF)) + return; apedata = tg3_ape_read32(tp, TG3_APE_SEG_SIG); if (apedata != APE_SEG_SIG_MAGIC) @@ -14069,22 +13874,14 @@ static void __devinit tg3_probe_ncsi(struct tg3 *tp) if (!(apedata & APE_FW_STATUS_READY)) return; - if (tg3_ape_read32(tp, TG3_APE_FW_FEATURES) & TG3_APE_FW_FEATURE_NCSI) - tg3_flag_set(tp, APE_HAS_NCSI); -} - -static void __devinit tg3_read_dash_ver(struct tg3 *tp) -{ - int vlen; - u32 apedata; - char *fwtype; - apedata = tg3_ape_read32(tp, TG3_APE_FW_VERSION); - if (tg3_flag(tp, APE_HAS_NCSI)) + if (tg3_ape_read32(tp, TG3_APE_FW_FEATURES) & TG3_APE_FW_FEATURE_NCSI) { + tg3_flag_set(tp, APE_HAS_NCSI); fwtype = "NCSI"; - else + } else { fwtype = "DASH"; + } vlen = strlen(tp->fw_ver); @@ -14118,17 +13915,20 @@ static void __devinit tg3_read_fw_ver(struct tg3 *tp) tg3_read_sb_ver(tp, val); else if ((val & TG3_EEPROM_MAGIC_HW_MSK) == TG3_EEPROM_MAGIC_HW) tg3_read_hwsb_ver(tp); + else + return; - if (tg3_flag(tp, ENABLE_ASF)) { - if (tg3_flag(tp, ENABLE_APE)) { - tg3_probe_ncsi(tp); - if (!vpd_vers) - tg3_read_dash_ver(tp); - } else if (!vpd_vers) { - tg3_read_mgmtfw_ver(tp); - } + if (vpd_vers) + goto done; + + if (tg3_flag(tp, ENABLE_APE)) { + if (tg3_flag(tp, ENABLE_ASF)) + tg3_read_dash_ver(tp); + } else if (tg3_flag(tp, ENABLE_ASF)) { + tg3_read_mgmtfw_ver(tp); } +done: tp->fw_ver[TG3_VER_SIZE - 1] = 0; } diff --git a/trunk/drivers/net/ethernet/broadcom/tg3.h b/trunk/drivers/net/ethernet/broadcom/tg3.h index a1b75cd67b9d..93865f899a4f 100644 --- a/trunk/drivers/net/ethernet/broadcom/tg3.h +++ b/trunk/drivers/net/ethernet/broadcom/tg3.h @@ -2311,11 +2311,10 @@ #define APE_LOCK_REQ_DRIVER 0x00001000 #define TG3_APE_LOCK_GRANT 0x004c #define APE_LOCK_GRANT_DRIVER 0x00001000 - -/* APE shared memory. Accessible through BAR1 */ -#define TG3_APE_SHMEM_BASE 0x4000 #define TG3_APE_SEG_SIG 0x4000 #define APE_SEG_SIG_MAGIC 0x41504521 + +/* APE shared memory. Accessible through BAR1 */ #define TG3_APE_FW_STATUS 0x400c #define APE_FW_STATUS_READY 0x00000100 #define TG3_APE_FW_FEATURES 0x4010 @@ -2328,8 +2327,6 @@ #define APE_FW_VERSION_REVMSK 0x0000ff00 #define APE_FW_VERSION_REVSFT 8 #define APE_FW_VERSION_BLDMSK 0x000000ff -#define TG3_APE_SEG_MSG_BUF_OFF 0x401c -#define TG3_APE_SEG_MSG_BUF_LEN 0x4020 #define TG3_APE_HOST_SEG_SIG 0x4200 #define APE_HOST_SEG_SIG_MAGIC 0x484f5354 #define TG3_APE_HOST_SEG_LEN 0x4204 @@ -2356,8 +2353,6 @@ #define APE_EVENT_STATUS_DRIVER_EVNT 0x00000010 #define APE_EVENT_STATUS_STATE_CHNGE 0x00000500 -#define APE_EVENT_STATUS_SCRTCHPD_READ 0x00001600 -#define APE_EVENT_STATUS_SCRTCHPD_WRITE 0x00001700 #define APE_EVENT_STATUS_STATE_START 0x00010000 #define APE_EVENT_STATUS_STATE_UNLOAD 0x00020000 #define APE_EVENT_STATUS_STATE_WOL 0x00030000 @@ -2676,40 +2671,6 @@ struct tg3_hw_stats { u8 __reserved4[0xb00-0x9c8]; }; -#define TG3_SD_NUM_RECS 3 -#define TG3_OCIR_LEN (sizeof(struct tg3_ocir)) -#define TG3_OCIR_SIG_MAGIC 0x5253434f -#define TG3_OCIR_FLAG_ACTIVE 0x00000001 - -#define TG3_TEMP_CAUTION_OFFSET 0xc8 -#define TG3_TEMP_MAX_OFFSET 0xcc -#define TG3_TEMP_SENSOR_OFFSET 0xd4 - - -struct tg3_ocir { - u32 signature; - u16 version_flags; - u16 refresh_int; - u32 refresh_tmr; - u32 update_tmr; - u32 dst_base_addr; - u16 src_hdr_offset; - u16 src_hdr_length; - u16 src_data_offset; - u16 src_data_length; - u16 dst_hdr_offset; - u16 dst_data_offset; - u16 dst_reg_upd_offset; - u16 dst_sem_offset; - u32 reserved1[2]; - u32 port0_flags; - u32 port1_flags; - u32 port2_flags; - u32 port3_flags; - u32 reserved2[1]; -}; - - /* 'mapping' is superfluous as the chip does not write into * the tx/rx post rings so we could just fetch it from there. * But the cache behavior is better how we are doing it now. @@ -3245,10 +3206,6 @@ struct tg3 { const char *fw_needed; const struct firmware *fw; u32 fw_len; /* includes BSS */ - -#if IS_ENABLED(CONFIG_HWMON) - struct device *hwmon_dev; -#endif }; #endif /* !(_T3_H) */ diff --git a/trunk/drivers/net/ethernet/brocade/bna/bfa_cee.c b/trunk/drivers/net/ethernet/brocade/bna/bfa_cee.c index 550d2521ba76..689e5e19cc0b 100644 --- a/trunk/drivers/net/ethernet/brocade/bna/bfa_cee.c +++ b/trunk/drivers/net/ethernet/brocade/bna/bfa_cee.c @@ -52,7 +52,13 @@ bfa_cee_format_lldp_cfg(struct bfa_cee_lldp_cfg *lldp_cfg) } /** - * bfa_cee_attr_meminfo - Returns the size of the DMA memory needed by CEE attributes + * bfa_cee_attr_meminfo() + * + * @brief Returns the size of the DMA memory needed by CEE attributes + * + * @param[in] void + * + * @return Size of DMA region */ static u32 bfa_cee_attr_meminfo(void) @@ -60,7 +66,13 @@ bfa_cee_attr_meminfo(void) return roundup(sizeof(struct bfa_cee_attr), BFA_DMA_ALIGN_SZ); } /** - * bfa_cee_stats_meminfo - Returns the size of the DMA memory needed by CEE stats + * bfa_cee_stats_meminfo() + * + * @brief Returns the size of the DMA memory needed by CEE stats + * + * @param[in] void + * + * @return Size of DMA region */ static u32 bfa_cee_stats_meminfo(void) @@ -69,10 +81,14 @@ bfa_cee_stats_meminfo(void) } /** - * bfa_cee_get_attr_isr - CEE ISR for get-attributes responses from f/w + * bfa_cee_get_attr_isr() + * + * @brief CEE ISR for get-attributes responses from f/w + * + * @param[in] cee - Pointer to the CEE module + * status - Return status from the f/w * - * @cee: Pointer to the CEE module - * @status: Return status from the f/w + * @return void */ static void bfa_cee_get_attr_isr(struct bfa_cee *cee, enum bfa_status status) @@ -89,10 +105,14 @@ bfa_cee_get_attr_isr(struct bfa_cee *cee, enum bfa_status status) } /** - * bfa_cee_get_attr_isr - CEE ISR for get-stats responses from f/w + * bfa_cee_get_attr_isr() + * + * @brief CEE ISR for get-stats responses from f/w * - * @cee: Pointer to the CEE module - * @status: Return status from the f/w + * @param[in] cee - Pointer to the CEE module + * status - Return status from the f/w + * + * @return void */ static void bfa_cee_get_stats_isr(struct bfa_cee *cee, enum bfa_status status) @@ -127,7 +147,13 @@ bfa_cee_reset_stats_isr(struct bfa_cee *cee, enum bfa_status status) cee->cbfn.reset_stats_cbfn(cee->cbfn.reset_stats_cbarg, status); } /** - * bfa_nw_cee_meminfo - Returns the size of the DMA memory needed by CEE module + * bfa_nw_cee_meminfo() + * + * @brief Returns the size of the DMA memory needed by CEE module + * + * @param[in] void + * + * @return Size of DMA region */ u32 bfa_nw_cee_meminfo(void) @@ -136,11 +162,15 @@ bfa_nw_cee_meminfo(void) } /** - * bfa_nw_cee_mem_claim - Initialized CEE DMA Memory + * bfa_nw_cee_mem_claim() + * + * @brief Initialized CEE DMA Memory + * + * @param[in] cee CEE module pointer + * dma_kva Kernel Virtual Address of CEE DMA Memory + * dma_pa Physical Address of CEE DMA Memory * - * @cee: CEE module pointer - * @dma_kva: Kernel Virtual Address of CEE DMA Memory - * @dma_pa: Physical Address of CEE DMA Memory + * @return void */ void bfa_nw_cee_mem_claim(struct bfa_cee *cee, u8 *dma_kva, u64 dma_pa) @@ -155,11 +185,13 @@ bfa_nw_cee_mem_claim(struct bfa_cee *cee, u8 *dma_kva, u64 dma_pa) } /** - * bfa_cee_get_attr - Send the request to the f/w to fetch CEE attributes. + * bfa_cee_get_attr() + * + * @brief Send the request to the f/w to fetch CEE attributes. * - * @cee: Pointer to the CEE module data structure. + * @param[in] Pointer to the CEE module data structure. * - * Return: status + * @return Status */ enum bfa_status bfa_nw_cee_get_attr(struct bfa_cee *cee, struct bfa_cee_attr *attr, @@ -188,7 +220,13 @@ bfa_nw_cee_get_attr(struct bfa_cee *cee, struct bfa_cee_attr *attr, } /** - * bfa_cee_isrs - Handles Mail-box interrupts for CEE module. + * bfa_cee_isrs() + * + * @brief Handles Mail-box interrupts for CEE module. + * + * @param[in] Pointer to the CEE module data structure. + * + * @return void */ static void @@ -215,9 +253,14 @@ bfa_cee_isr(void *cbarg, struct bfi_mbmsg *m) } /** - * bfa_cee_notify - CEE module heart-beat failure handler. + * bfa_cee_notify() + * + * @brief CEE module heart-beat failure handler. + * @brief CEE module IOC event handler. + * + * @param[in] IOC event type * - * @event: IOC event type + * @return void */ static void @@ -264,13 +307,17 @@ bfa_cee_notify(void *arg, enum bfa_ioc_event event) } /** - * bfa_nw_cee_attach - CEE module-attach API + * bfa_nw_cee_attach() + * + * @brief CEE module-attach API * - * @cee: Pointer to the CEE module data structure - * @ioc: Pointer to the ioc module data structure - * @dev: Pointer to the device driver module data structure. - * The device driver specific mbox ISR functions have - * this pointer as one of the parameters. + * @param[in] cee - Pointer to the CEE module data structure + * ioc - Pointer to the ioc module data structure + * dev - Pointer to the device driver module data structure + * The device driver specific mbox ISR functions have + * this pointer as one of the parameters. + * + * @return void */ void bfa_nw_cee_attach(struct bfa_cee *cee, struct bfa_ioc *ioc, diff --git a/trunk/drivers/net/ethernet/brocade/bna/bfa_cs.h b/trunk/drivers/net/ethernet/brocade/bna/bfa_cs.h index ad004a4c3897..3da1a946ccdd 100644 --- a/trunk/drivers/net/ethernet/brocade/bna/bfa_cs.h +++ b/trunk/drivers/net/ethernet/brocade/bna/bfa_cs.h @@ -16,18 +16,23 @@ * www.brocade.com */ -/* BFA common services */ +/** + * @file bfa_cs.h BFA common services + */ #ifndef __BFA_CS_H__ #define __BFA_CS_H__ #include "cna.h" -/* BFA state machine interfaces */ +/** + * @ BFA state machine interfaces + */ typedef void (*bfa_sm_t)(void *sm, int event); -/* oc - object class eg. bfa_ioc +/** + * oc - object class eg. bfa_ioc * st - state, eg. reset * otype - object type, eg. struct bfa_ioc * etype - object type, eg. enum ioc_event @@ -40,7 +45,9 @@ typedef void (*bfa_sm_t)(void *sm, int event); #define bfa_sm_get_state(_sm) ((_sm)->sm) #define bfa_sm_cmp_state(_sm, _state) ((_sm)->sm == (bfa_sm_t)(_state)) -/* For converting from state machine function to state encoding. */ +/** + * For converting from state machine function to state encoding. + */ struct bfa_sm_table { bfa_sm_t sm; /*!< state machine function */ int state; /*!< state machine encoding */ @@ -48,10 +55,13 @@ struct bfa_sm_table { }; #define BFA_SM(_sm) ((bfa_sm_t)(_sm)) -/* State machine with entry actions. */ +/** + * State machine with entry actions. + */ typedef void (*bfa_fsm_t)(void *fsm, int event); -/* oc - object class eg. bfa_ioc +/** + * oc - object class eg. bfa_ioc * st - state, eg. reset * otype - object type, eg. struct bfa_ioc * etype - object type, eg. enum ioc_event @@ -80,7 +90,9 @@ bfa_sm_to_state(const struct bfa_sm_table *smt, bfa_sm_t sm) return smt[i].state; } -/* Generic wait counter. */ +/** + * @ Generic wait counter. + */ typedef void (*bfa_wc_resume_t) (void *cbarg); @@ -104,7 +116,9 @@ bfa_wc_down(struct bfa_wc *wc) wc->wc_resume(wc->wc_cbarg); } -/* Initialize a waiting counter. */ +/** + * Initialize a waiting counter. + */ static inline void bfa_wc_init(struct bfa_wc *wc, bfa_wc_resume_t wc_resume, void *wc_cbarg) { @@ -114,7 +128,9 @@ bfa_wc_init(struct bfa_wc *wc, bfa_wc_resume_t wc_resume, void *wc_cbarg) bfa_wc_up(wc); } -/* Wait for counter to reach zero */ +/** + * Wait for counter to reach zero + */ static inline void bfa_wc_wait(struct bfa_wc *wc) { diff --git a/trunk/drivers/net/ethernet/brocade/bna/bfa_defs.h b/trunk/drivers/net/ethernet/brocade/bna/bfa_defs.h index e423f82da490..48f877337390 100644 --- a/trunk/drivers/net/ethernet/brocade/bna/bfa_defs.h +++ b/trunk/drivers/net/ethernet/brocade/bna/bfa_defs.h @@ -26,9 +26,13 @@ #define BFA_STRING_32 32 #define BFA_VERSION_LEN 64 -/* ---------------------- adapter definitions ------------ */ +/** + * ---------------------- adapter definitions ------------ + */ -/* BFA adapter level attributes. */ +/** + * BFA adapter level attributes. + */ enum { BFA_ADAPTER_SERIAL_NUM_LEN = STRSZ(BFA_MFG_SERIALNUM_SIZE), /* @@ -70,14 +74,18 @@ struct bfa_adapter_attr { u8 trunk_capable; }; -/* ---------------------- IOC definitions ------------ */ +/** + * ---------------------- IOC definitions ------------ + */ enum { BFA_IOC_DRIVER_LEN = 16, BFA_IOC_CHIP_REV_LEN = 8, }; -/* Driver and firmware versions. */ +/** + * Driver and firmware versions. + */ struct bfa_ioc_driver_attr { char driver[BFA_IOC_DRIVER_LEN]; /*!< driver name */ char driver_ver[BFA_VERSION_LEN]; /*!< driver version */ @@ -87,7 +95,9 @@ struct bfa_ioc_driver_attr { char ob_ver[BFA_VERSION_LEN]; /*!< openboot version */ }; -/* IOC PCI device attributes */ +/** + * IOC PCI device attributes + */ struct bfa_ioc_pci_attr { u16 vendor_id; /*!< PCI vendor ID */ u16 device_id; /*!< PCI device ID */ @@ -98,7 +108,9 @@ struct bfa_ioc_pci_attr { char chip_rev[BFA_IOC_CHIP_REV_LEN]; /*!< chip revision */ }; -/* IOC states */ +/** + * IOC states + */ enum bfa_ioc_state { BFA_IOC_UNINIT = 1, /*!< IOC is in uninit state */ BFA_IOC_RESET = 2, /*!< IOC is in reset state */ @@ -115,7 +127,9 @@ enum bfa_ioc_state { BFA_IOC_HWFAIL = 13, /*!< PCI mapping doesn't exist */ }; -/* IOC firmware stats */ +/** + * IOC firmware stats + */ struct bfa_fw_ioc_stats { u32 enable_reqs; u32 disable_reqs; @@ -125,7 +139,9 @@ struct bfa_fw_ioc_stats { u32 unknown_reqs; }; -/* IOC driver stats */ +/** + * IOC driver stats + */ struct bfa_ioc_drv_stats { u32 ioc_isrs; u32 ioc_enables; @@ -141,7 +157,9 @@ struct bfa_ioc_drv_stats { u32 rsvd; }; -/* IOC statistics */ +/** + * IOC statistics + */ struct bfa_ioc_stats { struct bfa_ioc_drv_stats drv_stats; /*!< driver IOC stats */ struct bfa_fw_ioc_stats fw_stats; /*!< firmware IOC stats */ @@ -153,7 +171,9 @@ enum bfa_ioc_type { BFA_IOC_TYPE_LL = 3, }; -/* IOC attributes returned in queries */ +/** + * IOC attributes returned in queries + */ struct bfa_ioc_attr { enum bfa_ioc_type ioc_type; enum bfa_ioc_state state; /*!< IOC state */ @@ -167,16 +187,22 @@ struct bfa_ioc_attr { u8 rsvd[4]; /*!< 64bit align */ }; -/* Adapter capability mask definition */ +/** + * Adapter capability mask definition + */ enum { BFA_CM_HBA = 0x01, BFA_CM_CNA = 0x02, BFA_CM_NIC = 0x04, }; -/* ---------------------- mfg definitions ------------ */ +/** + * ---------------------- mfg definitions ------------ + */ -/* Checksum size */ +/** + * Checksum size + */ #define BFA_MFG_CHKSUM_SIZE 16 #define BFA_MFG_PARTNUM_SIZE 14 @@ -187,7 +213,8 @@ enum { #pragma pack(1) -/* BFA adapter manufacturing block definition. +/** + * @brief BFA adapter manufacturing block definition. * * All numerical fields are in big-endian format. */ @@ -229,7 +256,9 @@ struct bfa_mfg_block { #pragma pack() -/* ---------------------- pci definitions ------------ */ +/** + * ---------------------- pci definitions ------------ + */ /* * PCI device ID information @@ -246,7 +275,9 @@ enum { #define bfa_asic_id_ctc(device) \ (bfa_asic_id_ct(device) || bfa_asic_id_ct2(device)) -/* PCI sub-system device and vendor ID information */ +/** + * PCI sub-system device and vendor ID information + */ enum { BFA_PCI_FCOE_SSDEVICE_ID = 0x14, BFA_PCI_CT2_SSID_FCoE = 0x22, diff --git a/trunk/drivers/net/ethernet/brocade/bna/bfa_defs_cna.h b/trunk/drivers/net/ethernet/brocade/bna/bfa_defs_cna.h index b39c5f23974b..8ab33ee2c2bc 100644 --- a/trunk/drivers/net/ethernet/brocade/bna/bfa_defs_cna.h +++ b/trunk/drivers/net/ethernet/brocade/bna/bfa_defs_cna.h @@ -20,7 +20,10 @@ #include "bfa_defs.h" -/* FC physical port statistics. */ +/** + * @brief + * FC physical port statistics. + */ struct bfa_port_fc_stats { u64 secs_reset; /*!< Seconds since stats is reset */ u64 tx_frames; /*!< Tx frames */ @@ -56,7 +59,10 @@ struct bfa_port_fc_stats { u64 bbsc_link_resets; /*!< Credit Recovery-Link Resets */ }; -/* Eth Physical Port statistics. */ +/** + * @brief + * Eth Physical Port statistics. + */ struct bfa_port_eth_stats { u64 secs_reset; /*!< Seconds since stats is reset */ u64 frame_64; /*!< Frames 64 bytes */ @@ -102,7 +108,10 @@ struct bfa_port_eth_stats { u64 tx_iscsi_zero_pause; /*!< Tx iSCSI zero pause */ }; -/* Port statistics. */ +/** + * @brief + * Port statistics. + */ union bfa_port_stats_u { struct bfa_port_fc_stats fc; struct bfa_port_eth_stats eth; diff --git a/trunk/drivers/net/ethernet/brocade/bna/bfa_defs_mfg_comm.h b/trunk/drivers/net/ethernet/brocade/bna/bfa_defs_mfg_comm.h index 7fb396fe679d..6681fe87c1e1 100644 --- a/trunk/drivers/net/ethernet/brocade/bna/bfa_defs_mfg_comm.h +++ b/trunk/drivers/net/ethernet/brocade/bna/bfa_defs_mfg_comm.h @@ -20,23 +20,33 @@ #include "bfa_defs.h" -/* Manufacturing block version */ +/** + * Manufacturing block version + */ #define BFA_MFG_VERSION 3 #define BFA_MFG_VERSION_UNINIT 0xFF -/* Manufacturing block encrypted version */ +/** + * Manufacturing block encrypted version + */ #define BFA_MFG_ENC_VER 2 -/* Manufacturing block version 1 length */ +/** + * Manufacturing block version 1 length + */ #define BFA_MFG_VER1_LEN 128 -/* Manufacturing block header length */ +/** + * Manufacturing block header length + */ #define BFA_MFG_HDR_LEN 4 #define BFA_MFG_SERIALNUM_SIZE 11 #define STRSZ(_n) (((_n) + 4) & ~3) -/* Manufacturing card type */ +/** + * Manufacturing card type + */ enum { BFA_MFG_TYPE_CB_MAX = 825, /*!< Crossbow card type max */ BFA_MFG_TYPE_FC8P2 = 825, /*!< 8G 2port FC card */ @@ -60,7 +70,9 @@ enum { #pragma pack(1) -/* Check if Mezz card */ +/** + * Check if Mezz card + */ #define bfa_mfg_is_mezz(type) (( \ (type) == BFA_MFG_TYPE_JAYHAWK || \ (type) == BFA_MFG_TYPE_WANCHESE || \ @@ -115,7 +127,9 @@ do { \ } \ } while (0) -/* VPD data length */ +/** + * VPD data length + */ #define BFA_MFG_VPD_LEN 512 #define BFA_MFG_VPD_LEN_INVALID 0 @@ -123,7 +137,9 @@ do { \ #define BFA_MFG_VPD_PCI_VER_MASK 0x07 /*!< version mask 3 bits */ #define BFA_MFG_VPD_PCI_VDR_MASK 0xf8 /*!< vendor mask 5 bits */ -/* VPD vendor tag */ +/** + * VPD vendor tag + */ enum { BFA_MFG_VPD_UNKNOWN = 0, /*!< vendor unknown */ BFA_MFG_VPD_IBM = 1, /*!< vendor IBM */ @@ -135,7 +151,8 @@ enum { BFA_MFG_VPD_PCI_BRCD = 0xf8, /*!< PCI VPD Brocade */ }; -/* BFA adapter flash vpd data definition. +/** + * @brief BFA adapter flash vpd data definition. * * All numerical fields are in big-endian format. */ diff --git a/trunk/drivers/net/ethernet/brocade/bna/bfa_defs_status.h b/trunk/drivers/net/ethernet/brocade/bna/bfa_defs_status.h index ea9af9ae754d..7c5fe6c2e80e 100644 --- a/trunk/drivers/net/ethernet/brocade/bna/bfa_defs_status.h +++ b/trunk/drivers/net/ethernet/brocade/bna/bfa_defs_status.h @@ -18,7 +18,8 @@ #ifndef __BFA_DEFS_STATUS_H__ #define __BFA_DEFS_STATUS_H__ -/* API status return values +/** + * API status return values * * NOTE: The error msgs are auto generated from the comments. Only singe line * comments are supported diff --git a/trunk/drivers/net/ethernet/brocade/bna/bfa_ioc.c b/trunk/drivers/net/ethernet/brocade/bna/bfa_ioc.c index 959c58ef972a..0b640fafbda3 100644 --- a/trunk/drivers/net/ethernet/brocade/bna/bfa_ioc.c +++ b/trunk/drivers/net/ethernet/brocade/bna/bfa_ioc.c @@ -20,9 +20,13 @@ #include "bfi_reg.h" #include "bfa_defs.h" -/* IOC local definitions */ +/** + * IOC local definitions + */ -/* Asic specific macros : see bfa_hw_cb.c and bfa_hw_ct.c for details. */ +/** + * Asic specific macros : see bfa_hw_cb.c and bfa_hw_ct.c for details. + */ #define bfa_ioc_firmware_lock(__ioc) \ ((__ioc)->ioc_hwif->ioc_firmware_lock(__ioc)) @@ -92,7 +96,9 @@ static void bfa_ioc_get_adapter_manufacturer(struct bfa_ioc *ioc, static void bfa_ioc_get_adapter_model(struct bfa_ioc *ioc, char *model); static u64 bfa_ioc_get_pwwn(struct bfa_ioc *ioc); -/* IOC state machine definitions/declarations */ +/** + * IOC state machine definitions/declarations + */ enum ioc_event { IOC_E_RESET = 1, /*!< IOC reset request */ IOC_E_ENABLE = 2, /*!< IOC enable request */ @@ -142,7 +148,9 @@ static void bfa_iocpf_initfail(struct bfa_ioc *ioc); static void bfa_iocpf_getattrfail(struct bfa_ioc *ioc); static void bfa_iocpf_stop(struct bfa_ioc *ioc); -/* IOCPF state machine events */ +/** + * IOCPF state machine events + */ enum iocpf_event { IOCPF_E_ENABLE = 1, /*!< IOCPF enable request */ IOCPF_E_DISABLE = 2, /*!< IOCPF disable request */ @@ -158,7 +166,9 @@ enum iocpf_event { IOCPF_E_SEM_ERROR = 12, /*!< h/w sem mapping error */ }; -/* IOCPF states */ +/** + * IOCPF states + */ enum bfa_iocpf_state { BFA_IOCPF_RESET = 1, /*!< IOC is in reset state */ BFA_IOCPF_SEMWAIT = 2, /*!< Waiting for IOC h/w semaphore */ @@ -205,15 +215,21 @@ static struct bfa_sm_table iocpf_sm_table[] = { {BFA_SM(bfa_iocpf_sm_disabled), BFA_IOCPF_DISABLED}, }; -/* IOC State Machine */ +/** + * IOC State Machine + */ -/* Beginning state. IOC uninit state. */ +/** + * Beginning state. IOC uninit state. + */ static void bfa_ioc_sm_uninit_entry(struct bfa_ioc *ioc) { } -/* IOC is in uninit state. */ +/** + * IOC is in uninit state. + */ static void bfa_ioc_sm_uninit(struct bfa_ioc *ioc, enum ioc_event event) { @@ -227,14 +243,18 @@ bfa_ioc_sm_uninit(struct bfa_ioc *ioc, enum ioc_event event) } } -/* Reset entry actions -- initialize state machine */ +/** + * Reset entry actions -- initialize state machine + */ static void bfa_ioc_sm_reset_entry(struct bfa_ioc *ioc) { bfa_fsm_set_state(&ioc->iocpf, bfa_iocpf_sm_reset); } -/* IOC is in reset state. */ +/** + * IOC is in reset state. + */ static void bfa_ioc_sm_reset(struct bfa_ioc *ioc, enum ioc_event event) { @@ -262,7 +282,8 @@ bfa_ioc_sm_enabling_entry(struct bfa_ioc *ioc) bfa_iocpf_enable(ioc); } -/* Host IOC function is being enabled, awaiting response from firmware. +/** + * Host IOC function is being enabled, awaiting response from firmware. * Semaphore is acquired. */ static void @@ -304,7 +325,9 @@ bfa_ioc_sm_enabling(struct bfa_ioc *ioc, enum ioc_event event) } } -/* Semaphore should be acquired for version check. */ +/** + * Semaphore should be acquired for version check. + */ static void bfa_ioc_sm_getattr_entry(struct bfa_ioc *ioc) { @@ -313,7 +336,9 @@ bfa_ioc_sm_getattr_entry(struct bfa_ioc *ioc) bfa_ioc_send_getattr(ioc); } -/* IOC configuration in progress. Timer is active. */ +/** + * IOC configuration in progress. Timer is active. + */ static void bfa_ioc_sm_getattr(struct bfa_ioc *ioc, enum ioc_event event) { @@ -394,7 +419,9 @@ bfa_ioc_sm_disabling_entry(struct bfa_ioc *ioc) bfa_iocpf_disable(ioc); } -/* IOC is being disabled */ +/** + * IOC is being disabled + */ static void bfa_ioc_sm_disabling(struct bfa_ioc *ioc, enum ioc_event event) { @@ -422,7 +449,9 @@ bfa_ioc_sm_disabling(struct bfa_ioc *ioc, enum ioc_event event) } } -/* IOC disable completion entry. */ +/** + * IOC disable completion entry. + */ static void bfa_ioc_sm_disabled_entry(struct bfa_ioc *ioc) { @@ -456,7 +485,9 @@ bfa_ioc_sm_fail_retry_entry(struct bfa_ioc *ioc) { } -/* Hardware initialization retry. */ +/** + * Hardware initialization retry. + */ static void bfa_ioc_sm_fail_retry(struct bfa_ioc *ioc, enum ioc_event event) { @@ -503,7 +534,9 @@ bfa_ioc_sm_fail_entry(struct bfa_ioc *ioc) { } -/* IOC failure. */ +/** + * IOC failure. + */ static void bfa_ioc_sm_fail(struct bfa_ioc *ioc, enum ioc_event event) { @@ -535,7 +568,9 @@ bfa_ioc_sm_hwfail_entry(struct bfa_ioc *ioc) { } -/* IOC failure. */ +/** + * IOC failure. + */ static void bfa_ioc_sm_hwfail(struct bfa_ioc *ioc, enum ioc_event event) { @@ -558,9 +593,13 @@ bfa_ioc_sm_hwfail(struct bfa_ioc *ioc, enum ioc_event event) } } -/* IOCPF State Machine */ +/** + * IOCPF State Machine + */ -/* Reset entry actions -- initialize state machine */ +/** + * Reset entry actions -- initialize state machine + */ static void bfa_iocpf_sm_reset_entry(struct bfa_iocpf *iocpf) { @@ -568,7 +607,9 @@ bfa_iocpf_sm_reset_entry(struct bfa_iocpf *iocpf) iocpf->auto_recover = bfa_nw_auto_recover; } -/* Beginning state. IOC is in reset state. */ +/** + * Beginning state. IOC is in reset state. + */ static void bfa_iocpf_sm_reset(struct bfa_iocpf *iocpf, enum iocpf_event event) { @@ -585,7 +626,9 @@ bfa_iocpf_sm_reset(struct bfa_iocpf *iocpf, enum iocpf_event event) } } -/* Semaphore should be acquired for version check. */ +/** + * Semaphore should be acquired for version check. + */ static void bfa_iocpf_sm_fwcheck_entry(struct bfa_iocpf *iocpf) { @@ -593,7 +636,9 @@ bfa_iocpf_sm_fwcheck_entry(struct bfa_iocpf *iocpf) bfa_ioc_hw_sem_get(iocpf->ioc); } -/* Awaiting h/w semaphore to continue with version check. */ +/** + * Awaiting h/w semaphore to continue with version check. + */ static void bfa_iocpf_sm_fwcheck(struct bfa_iocpf *iocpf, enum iocpf_event event) { @@ -638,7 +683,9 @@ bfa_iocpf_sm_fwcheck(struct bfa_iocpf *iocpf, enum iocpf_event event) } } -/* Notify enable completion callback */ +/** + * Notify enable completion callback + */ static void bfa_iocpf_sm_mismatch_entry(struct bfa_iocpf *iocpf) { @@ -651,7 +698,9 @@ bfa_iocpf_sm_mismatch_entry(struct bfa_iocpf *iocpf) msecs_to_jiffies(BFA_IOC_TOV)); } -/* Awaiting firmware version match. */ +/** + * Awaiting firmware version match. + */ static void bfa_iocpf_sm_mismatch(struct bfa_iocpf *iocpf, enum iocpf_event event) { @@ -678,14 +727,18 @@ bfa_iocpf_sm_mismatch(struct bfa_iocpf *iocpf, enum iocpf_event event) } } -/* Request for semaphore. */ +/** + * Request for semaphore. + */ static void bfa_iocpf_sm_semwait_entry(struct bfa_iocpf *iocpf) { bfa_ioc_hw_sem_get(iocpf->ioc); } -/* Awaiting semaphore for h/w initialzation. */ +/** + * Awaiting semaphore for h/w initialzation. + */ static void bfa_iocpf_sm_semwait(struct bfa_iocpf *iocpf, enum iocpf_event event) { @@ -725,7 +778,8 @@ bfa_iocpf_sm_hwinit_entry(struct bfa_iocpf *iocpf) bfa_ioc_reset(iocpf->ioc, false); } -/* Hardware is being initialized. Interrupts are enabled. +/** + * Hardware is being initialized. Interrupts are enabled. * Holding hardware semaphore lock. */ static void @@ -768,7 +822,8 @@ bfa_iocpf_sm_enabling_entry(struct bfa_iocpf *iocpf) bfa_ioc_send_enable(iocpf->ioc); } -/* Host IOC function is being enabled, awaiting response from firmware. +/** + * Host IOC function is being enabled, awaiting response from firmware. * Semaphore is acquired. */ static void @@ -841,7 +896,9 @@ bfa_iocpf_sm_disabling_entry(struct bfa_iocpf *iocpf) bfa_ioc_send_disable(iocpf->ioc); } -/* IOC is being disabled */ +/** + * IOC is being disabled + */ static void bfa_iocpf_sm_disabling(struct bfa_iocpf *iocpf, enum iocpf_event event) { @@ -878,7 +935,9 @@ bfa_iocpf_sm_disabling_sync_entry(struct bfa_iocpf *iocpf) bfa_ioc_hw_sem_get(iocpf->ioc); } -/* IOC hb ack request is being removed. */ +/** + * IOC hb ack request is being removed. + */ static void bfa_iocpf_sm_disabling_sync(struct bfa_iocpf *iocpf, enum iocpf_event event) { @@ -904,7 +963,9 @@ bfa_iocpf_sm_disabling_sync(struct bfa_iocpf *iocpf, enum iocpf_event event) } } -/* IOC disable completion entry. */ +/** + * IOC disable completion entry. + */ static void bfa_iocpf_sm_disabled_entry(struct bfa_iocpf *iocpf) { @@ -939,7 +1000,9 @@ bfa_iocpf_sm_initfail_sync_entry(struct bfa_iocpf *iocpf) bfa_ioc_hw_sem_get(iocpf->ioc); } -/* Hardware initialization failed. */ +/** + * Hardware initialization failed. + */ static void bfa_iocpf_sm_initfail_sync(struct bfa_iocpf *iocpf, enum iocpf_event event) { @@ -983,7 +1046,9 @@ bfa_iocpf_sm_initfail_entry(struct bfa_iocpf *iocpf) { } -/* Hardware initialization failed. */ +/** + * Hardware initialization failed. + */ static void bfa_iocpf_sm_initfail(struct bfa_iocpf *iocpf, enum iocpf_event event) { @@ -1019,7 +1084,9 @@ bfa_iocpf_sm_fail_sync_entry(struct bfa_iocpf *iocpf) bfa_ioc_hw_sem_get(iocpf->ioc); } -/* IOC is in failed state. */ +/** + * IOC is in failed state. + */ static void bfa_iocpf_sm_fail_sync(struct bfa_iocpf *iocpf, enum iocpf_event event) { @@ -1067,7 +1134,10 @@ bfa_iocpf_sm_fail_entry(struct bfa_iocpf *iocpf) { } -/* IOC is in failed state. */ +/** + * @brief + * IOC is in failed state. + */ static void bfa_iocpf_sm_fail(struct bfa_iocpf *iocpf, enum iocpf_event event) { @@ -1081,9 +1151,13 @@ bfa_iocpf_sm_fail(struct bfa_iocpf *iocpf, enum iocpf_event event) } } -/* BFA IOC private functions */ +/** + * BFA IOC private functions + */ -/* Notify common modules registered for notification. */ +/** + * Notify common modules registered for notification. + */ static void bfa_ioc_event_notify(struct bfa_ioc *ioc, enum bfa_ioc_event event) { @@ -1224,7 +1298,10 @@ bfa_ioc_hw_sem_get_cancel(struct bfa_ioc *ioc) del_timer(&ioc->sem_timer); } -/* Initialize LPU local memory (aka secondary memory / SRAM) */ +/** + * @brief + * Initialize LPU local memory (aka secondary memory / SRAM) + */ static void bfa_ioc_lmem_init(struct bfa_ioc *ioc) { @@ -1289,7 +1366,9 @@ bfa_ioc_lpu_stop(struct bfa_ioc *ioc) writel(pss_ctl, ioc->ioc_regs.pss_ctl_reg); } -/* Get driver and firmware versions. */ +/** + * Get driver and firmware versions. + */ void bfa_nw_ioc_fwver_get(struct bfa_ioc *ioc, struct bfi_ioc_image_hdr *fwhdr) { @@ -1309,7 +1388,9 @@ bfa_nw_ioc_fwver_get(struct bfa_ioc *ioc, struct bfi_ioc_image_hdr *fwhdr) } } -/* Returns TRUE if same. */ +/** + * Returns TRUE if same. + */ bool bfa_nw_ioc_fwver_cmp(struct bfa_ioc *ioc, struct bfi_ioc_image_hdr *fwhdr) { @@ -1327,7 +1408,8 @@ bfa_nw_ioc_fwver_cmp(struct bfa_ioc *ioc, struct bfi_ioc_image_hdr *fwhdr) return true; } -/* Return true if current running version is valid. Firmware signature and +/** + * Return true if current running version is valid. Firmware signature and * execution context (driver/bios) must match. */ static bool @@ -1348,7 +1430,9 @@ bfa_ioc_fwver_valid(struct bfa_ioc *ioc, u32 boot_env) return bfa_nw_ioc_fwver_cmp(ioc, &fwhdr); } -/* Conditionally flush any pending message from firmware at start. */ +/** + * Conditionally flush any pending message from firmware at start. + */ static void bfa_ioc_msgflush(struct bfa_ioc *ioc) { @@ -1359,6 +1443,9 @@ bfa_ioc_msgflush(struct bfa_ioc *ioc) writel(1, ioc->ioc_regs.lpu_mbox_cmd); } +/** + * @img ioc_init_logic.jpg + */ static void bfa_ioc_hwinit(struct bfa_ioc *ioc, bool force) { @@ -1516,7 +1603,10 @@ bfa_ioc_hb_stop(struct bfa_ioc *ioc) del_timer(&ioc->hb_timer); } -/* Initiate a full firmware download. */ +/** + * @brief + * Initiate a full firmware download. + */ static void bfa_ioc_download_fw(struct bfa_ioc *ioc, u32 boot_type, u32 boot_env) @@ -1582,7 +1672,9 @@ bfa_ioc_reset(struct bfa_ioc *ioc, bool force) bfa_ioc_hwinit(ioc, force); } -/* BFA ioc enable reply by firmware */ +/** + * BFA ioc enable reply by firmware + */ static void bfa_ioc_enable_reply(struct bfa_ioc *ioc, enum bfa_mode port_mode, u8 cap_bm) @@ -1594,7 +1686,10 @@ bfa_ioc_enable_reply(struct bfa_ioc *ioc, enum bfa_mode port_mode, bfa_fsm_send_event(iocpf, IOCPF_E_FWRSP_ENABLE); } -/* Update BFA configuration from firmware configuration. */ +/** + * @brief + * Update BFA configuration from firmware configuration. + */ static void bfa_ioc_getattr_reply(struct bfa_ioc *ioc) { @@ -1607,7 +1702,9 @@ bfa_ioc_getattr_reply(struct bfa_ioc *ioc) bfa_fsm_send_event(ioc, IOC_E_FWRSP_GETATTR); } -/* Attach time initialization of mbox logic. */ +/** + * Attach time initialization of mbox logic. + */ static void bfa_ioc_mbox_attach(struct bfa_ioc *ioc) { @@ -1621,7 +1718,9 @@ bfa_ioc_mbox_attach(struct bfa_ioc *ioc) } } -/* Mbox poll timer -- restarts any pending mailbox requests. */ +/** + * Mbox poll timer -- restarts any pending mailbox requests. + */ static void bfa_ioc_mbox_poll(struct bfa_ioc *ioc) { @@ -1661,7 +1760,9 @@ bfa_ioc_mbox_poll(struct bfa_ioc *ioc) } } -/* Cleanup any pending requests. */ +/** + * Cleanup any pending requests. + */ static void bfa_ioc_mbox_flush(struct bfa_ioc *ioc) { @@ -1673,12 +1774,12 @@ bfa_ioc_mbox_flush(struct bfa_ioc *ioc) } /** - * bfa_nw_ioc_smem_read - Read data from SMEM to host through PCI memmap + * Read data from SMEM to host through PCI memmap * - * @ioc: memory for IOC - * @tbuf: app memory to store data from smem - * @soff: smem offset - * @sz: size of smem in bytes + * @param[in] ioc memory for IOC + * @param[in] tbuf app memory to store data from smem + * @param[in] soff smem offset + * @param[in] sz size of smem in bytes */ static int bfa_nw_ioc_smem_read(struct bfa_ioc *ioc, void *tbuf, u32 soff, u32 sz) @@ -1725,7 +1826,9 @@ bfa_nw_ioc_smem_read(struct bfa_ioc *ioc, void *tbuf, u32 soff, u32 sz) return 0; } -/* Retrieve saved firmware trace from a prior IOC failure. */ +/** + * Retrieve saved firmware trace from a prior IOC failure. + */ int bfa_nw_ioc_debug_fwtrc(struct bfa_ioc *ioc, void *trcdata, int *trclen) { @@ -1741,7 +1844,9 @@ bfa_nw_ioc_debug_fwtrc(struct bfa_ioc *ioc, void *trcdata, int *trclen) return status; } -/* Save firmware trace if configured. */ +/** + * Save firmware trace if configured. + */ static void bfa_nw_ioc_debug_save_ftrc(struct bfa_ioc *ioc) { @@ -1756,7 +1861,9 @@ bfa_nw_ioc_debug_save_ftrc(struct bfa_ioc *ioc) } } -/* Retrieve saved firmware trace from a prior IOC failure. */ +/** + * Retrieve saved firmware trace from a prior IOC failure. + */ int bfa_nw_ioc_debug_fwsave(struct bfa_ioc *ioc, void *trcdata, int *trclen) { @@ -1785,7 +1892,9 @@ bfa_ioc_fail_notify(struct bfa_ioc *ioc) bfa_nw_ioc_debug_save_ftrc(ioc); } -/* IOCPF to IOC interface */ +/** + * IOCPF to IOC interface + */ static void bfa_ioc_pf_enabled(struct bfa_ioc *ioc) { @@ -1819,7 +1928,9 @@ bfa_ioc_pf_fwmismatch(struct bfa_ioc *ioc) ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE); } -/* IOC public */ +/** + * IOC public + */ static enum bfa_status bfa_ioc_pll_init(struct bfa_ioc *ioc) { @@ -1843,7 +1954,8 @@ bfa_ioc_pll_init(struct bfa_ioc *ioc) return BFA_STATUS_OK; } -/* Interface used by diag module to do firmware boot with memory test +/** + * Interface used by diag module to do firmware boot with memory test * as the entry vector. */ static void @@ -1871,7 +1983,9 @@ bfa_ioc_boot(struct bfa_ioc *ioc, enum bfi_fwboot_type boot_type, bfa_ioc_lpu_start(ioc); } -/* Enable/disable IOC failure auto recovery. */ +/** + * Enable/disable IOC failure auto recovery. + */ void bfa_nw_ioc_auto_recover(bool auto_recover) { @@ -1942,10 +2056,10 @@ bfa_ioc_isr(struct bfa_ioc *ioc, struct bfi_mbmsg *m) } /** - * bfa_nw_ioc_attach - IOC attach time initialization and setup. + * IOC attach time initialization and setup. * - * @ioc: memory for IOC - * @bfa: driver instance structure + * @param[in] ioc memory for IOC + * @param[in] bfa driver instance structure */ void bfa_nw_ioc_attach(struct bfa_ioc *ioc, void *bfa, struct bfa_ioc_cbfn *cbfn) @@ -1964,7 +2078,9 @@ bfa_nw_ioc_attach(struct bfa_ioc *ioc, void *bfa, struct bfa_ioc_cbfn *cbfn) bfa_fsm_send_event(ioc, IOC_E_RESET); } -/* Driver detach time IOC cleanup. */ +/** + * Driver detach time IOC cleanup. + */ void bfa_nw_ioc_detach(struct bfa_ioc *ioc) { @@ -1975,9 +2091,9 @@ bfa_nw_ioc_detach(struct bfa_ioc *ioc) } /** - * bfa_nw_ioc_pci_init - Setup IOC PCI properties. + * Setup IOC PCI properties. * - * @pcidev: PCI device information for this IOC + * @param[in] pcidev PCI device information for this IOC */ void bfa_nw_ioc_pci_init(struct bfa_ioc *ioc, struct bfa_pcidev *pcidev, @@ -2044,10 +2160,10 @@ bfa_nw_ioc_pci_init(struct bfa_ioc *ioc, struct bfa_pcidev *pcidev, } /** - * bfa_nw_ioc_mem_claim - Initialize IOC dma memory + * Initialize IOC dma memory * - * @dm_kva: kernel virtual address of IOC dma memory - * @dm_pa: physical address of IOC dma memory + * @param[in] dm_kva kernel virtual address of IOC dma memory + * @param[in] dm_pa physical address of IOC dma memory */ void bfa_nw_ioc_mem_claim(struct bfa_ioc *ioc, u8 *dm_kva, u64 dm_pa) @@ -2060,7 +2176,9 @@ bfa_nw_ioc_mem_claim(struct bfa_ioc *ioc, u8 *dm_kva, u64 dm_pa) ioc->attr = (struct bfi_ioc_attr *) dm_kva; } -/* Return size of dma memory required. */ +/** + * Return size of dma memory required. + */ u32 bfa_nw_ioc_meminfo(void) { @@ -2083,7 +2201,9 @@ bfa_nw_ioc_disable(struct bfa_ioc *ioc) bfa_fsm_send_event(ioc, IOC_E_DISABLE); } -/* Initialize memory for saving firmware trace. */ +/** + * Initialize memory for saving firmware trace. + */ void bfa_nw_ioc_debug_memclaim(struct bfa_ioc *ioc, void *dbg_fwsave) { @@ -2097,7 +2217,9 @@ bfa_ioc_smem_pgnum(struct bfa_ioc *ioc, u32 fmaddr) return PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, fmaddr); } -/* Register mailbox message handler function, to be called by common modules */ +/** + * Register mailbox message handler function, to be called by common modules + */ void bfa_nw_ioc_mbox_regisr(struct bfa_ioc *ioc, enum bfi_mclass mc, bfa_ioc_mbox_mcfunc_t cbfn, void *cbarg) @@ -2109,12 +2231,11 @@ bfa_nw_ioc_mbox_regisr(struct bfa_ioc *ioc, enum bfi_mclass mc, } /** - * bfa_nw_ioc_mbox_queue - Queue a mailbox command request to firmware. + * Queue a mailbox command request to firmware. Waits if mailbox is busy. + * Responsibility of caller to serialize * - * @ioc: IOC instance - * @cmd: Mailbox command - * - * Waits if mailbox is busy. Responsibility of caller to serialize + * @param[in] ioc IOC instance + * @param[i] cmd Mailbox command */ bool bfa_nw_ioc_mbox_queue(struct bfa_ioc *ioc, struct bfa_mbox_cmd *cmd, @@ -2151,7 +2272,9 @@ bfa_nw_ioc_mbox_queue(struct bfa_ioc *ioc, struct bfa_mbox_cmd *cmd, return false; } -/* Handle mailbox interrupts */ +/** + * Handle mailbox interrupts + */ void bfa_nw_ioc_mbox_isr(struct bfa_ioc *ioc) { @@ -2191,7 +2314,9 @@ bfa_nw_ioc_error_isr(struct bfa_ioc *ioc) bfa_fsm_send_event(ioc, IOC_E_HWERROR); } -/* return true if IOC is disabled */ +/** + * return true if IOC is disabled + */ bool bfa_nw_ioc_is_disabled(struct bfa_ioc *ioc) { @@ -2199,14 +2324,17 @@ bfa_nw_ioc_is_disabled(struct bfa_ioc *ioc) bfa_fsm_cmp_state(ioc, bfa_ioc_sm_disabled); } -/* return true if IOC is operational */ +/** + * return true if IOC is operational + */ bool bfa_nw_ioc_is_operational(struct bfa_ioc *ioc) { return bfa_fsm_cmp_state(ioc, bfa_ioc_sm_op); } -/* Add to IOC heartbeat failure notification queue. To be used by common +/** + * Add to IOC heartbeat failure notification queue. To be used by common * modules such as cee, port, diag. */ void @@ -2390,7 +2518,9 @@ bfa_nw_ioc_get_attr(struct bfa_ioc *ioc, struct bfa_ioc_attr *ioc_attr) bfa_ioc_get_pci_chip_rev(ioc, ioc_attr->pci_attr.chip_rev); } -/* WWN public */ +/** + * WWN public + */ static u64 bfa_ioc_get_pwwn(struct bfa_ioc *ioc) { @@ -2403,7 +2533,9 @@ bfa_nw_ioc_get_mac(struct bfa_ioc *ioc) return ioc->attr->mac; } -/* Firmware failure detected. Start recovery actions. */ +/** + * Firmware failure detected. Start recovery actions. + */ static void bfa_ioc_recover(struct bfa_ioc *ioc) { @@ -2413,7 +2545,10 @@ bfa_ioc_recover(struct bfa_ioc *ioc) bfa_fsm_send_event(ioc, IOC_E_HBFAIL); } -/* BFA IOC PF private functions */ +/** + * @dg hal_iocpf_pvt BFA IOC PF private functions + * @{ + */ static void bfa_iocpf_enable(struct bfa_ioc *ioc) @@ -2534,6 +2669,8 @@ bfa_flash_notify(void *cbarg, enum bfa_ioc_event event) /* * Send flash write request. + * + * @param[in] cbarg - callback argument */ static void bfa_flash_write_send(struct bfa_flash *flash) @@ -2562,10 +2699,10 @@ bfa_flash_write_send(struct bfa_flash *flash) flash->offset += len; } -/** - * bfa_flash_read_send - Send flash read request. +/* + * Send flash read request. * - * @cbarg: callback argument + * @param[in] cbarg - callback argument */ static void bfa_flash_read_send(void *cbarg) @@ -2587,11 +2724,11 @@ bfa_flash_read_send(void *cbarg) bfa_nw_ioc_mbox_queue(flash->ioc, &flash->mb, NULL, NULL); } -/** - * bfa_flash_intr - Process flash response messages upon receiving interrupts. +/* + * Process flash response messages upon receiving interrupts. * - * @flasharg: flash structure - * @msg: message structure + * @param[in] flasharg - flash structure + * @param[in] msg - message structure */ static void bfa_flash_intr(void *flasharg, struct bfi_mbmsg *msg) @@ -2684,12 +2821,12 @@ bfa_nw_flash_meminfo(void) return roundup(BFA_FLASH_DMA_BUF_SZ, BFA_DMA_ALIGN_SZ); } -/** - * bfa_nw_flash_attach - Flash attach API. +/* + * Flash attach API. * - * @flash: flash structure - * @ioc: ioc structure - * @dev: device structure + * @param[in] flash - flash structure + * @param[in] ioc - ioc structure + * @param[in] dev - device structure */ void bfa_nw_flash_attach(struct bfa_flash *flash, struct bfa_ioc *ioc, void *dev) @@ -2705,12 +2842,12 @@ bfa_nw_flash_attach(struct bfa_flash *flash, struct bfa_ioc *ioc, void *dev) list_add_tail(&flash->ioc_notify.qe, &flash->ioc->notify_q); } -/** - * bfa_nw_flash_memclaim - Claim memory for flash +/* + * Claim memory for flash * - * @flash: flash structure - * @dm_kva: pointer to virtual memory address - * @dm_pa: physical memory address + * @param[in] flash - flash structure + * @param[in] dm_kva - pointer to virtual memory address + * @param[in] dm_pa - physical memory address */ void bfa_nw_flash_memclaim(struct bfa_flash *flash, u8 *dm_kva, u64 dm_pa) @@ -2722,13 +2859,13 @@ bfa_nw_flash_memclaim(struct bfa_flash *flash, u8 *dm_kva, u64 dm_pa) dm_pa += roundup(BFA_FLASH_DMA_BUF_SZ, BFA_DMA_ALIGN_SZ); } -/** - * bfa_nw_flash_get_attr - Get flash attribute. +/* + * Get flash attribute. * - * @flash: flash structure - * @attr: flash attribute structure - * @cbfn: callback function - * @cbarg: callback argument + * @param[in] flash - flash structure + * @param[in] attr - flash attribute structure + * @param[in] cbfn - callback function + * @param[in] cbarg - callback argument * * Return status. */ @@ -2758,17 +2895,17 @@ bfa_nw_flash_get_attr(struct bfa_flash *flash, struct bfa_flash_attr *attr, return BFA_STATUS_OK; } -/** - * bfa_nw_flash_update_part - Update flash partition. +/* + * Update flash partition. * - * @flash: flash structure - * @type: flash partition type - * @instance: flash partition instance - * @buf: update data buffer - * @len: data buffer length - * @offset: offset relative to the partition starting address - * @cbfn: callback function - * @cbarg: callback argument + * @param[in] flash - flash structure + * @param[in] type - flash partition type + * @param[in] instance - flash partition instance + * @param[in] buf - update data buffer + * @param[in] len - data buffer length + * @param[in] offset - offset relative to the partition starting address + * @param[in] cbfn - callback function + * @param[in] cbarg - callback argument * * Return status. */ @@ -2807,17 +2944,17 @@ bfa_nw_flash_update_part(struct bfa_flash *flash, u32 type, u8 instance, return BFA_STATUS_OK; } -/** - * bfa_nw_flash_read_part - Read flash partition. +/* + * Read flash partition. * - * @flash: flash structure - * @type: flash partition type - * @instance: flash partition instance - * @buf: read data buffer - * @len: data buffer length - * @offset: offset relative to the partition starting address - * @cbfn: callback function - * @cbarg: callback argument + * @param[in] flash - flash structure + * @param[in] type - flash partition type + * @param[in] instance - flash partition instance + * @param[in] buf - read data buffer + * @param[in] len - data buffer length + * @param[in] offset - offset relative to the partition starting address + * @param[in] cbfn - callback function + * @param[in] cbarg - callback argument * * Return status. */ diff --git a/trunk/drivers/net/ethernet/brocade/bna/bfa_ioc.h b/trunk/drivers/net/ethernet/brocade/bna/bfa_ioc.h index 63a85e555df8..3b4460fdc148 100644 --- a/trunk/drivers/net/ethernet/brocade/bna/bfa_ioc.h +++ b/trunk/drivers/net/ethernet/brocade/bna/bfa_ioc.h @@ -30,7 +30,9 @@ #define BNA_DBG_FWTRC_LEN (BFI_IOC_TRC_ENTS * BFI_IOC_TRC_ENT_SZ + \ BFI_IOC_TRC_HDR_SZ) -/* PCI device information required by IOC */ +/** + * PCI device information required by IOC + */ struct bfa_pcidev { int pci_slot; u8 pci_func; @@ -39,7 +41,8 @@ struct bfa_pcidev { void __iomem *pci_bar_kva; }; -/* Structure used to remember the DMA-able memory block's KVA and Physical +/** + * Structure used to remember the DMA-able memory block's KVA and Physical * Address */ struct bfa_dma { @@ -49,11 +52,15 @@ struct bfa_dma { #define BFA_DMA_ALIGN_SZ 256 -/* smem size for Crossbow and Catapult */ +/** + * smem size for Crossbow and Catapult + */ #define BFI_SMEM_CB_SIZE 0x200000U /* ! 2MB for crossbow */ #define BFI_SMEM_CT_SIZE 0x280000U /* ! 2.5MB for catapult */ -/* BFA dma address assignment macro. (big endian format) */ +/** + * @brief BFA dma address assignment macro. (big endian format) + */ #define bfa_dma_be_addr_set(dma_addr, pa) \ __bfa_dma_be_addr_set(&dma_addr, (u64)pa) static inline void @@ -101,7 +108,9 @@ struct bfa_ioc_regs { u32 smem_pg0; }; -/* IOC Mailbox structures */ +/** + * IOC Mailbox structures + */ typedef void (*bfa_mbox_cmd_cbfn_t)(void *cbarg); struct bfa_mbox_cmd { struct list_head qe; @@ -110,7 +119,9 @@ struct bfa_mbox_cmd { u32 msg[BFI_IOC_MSGSZ]; }; -/* IOC mailbox module */ +/** + * IOC mailbox module + */ typedef void (*bfa_ioc_mbox_mcfunc_t)(void *cbarg, struct bfi_mbmsg *m); struct bfa_ioc_mbox_mod { struct list_head cmd_q; /*!< pending mbox queue */ @@ -121,7 +132,9 @@ struct bfa_ioc_mbox_mod { } mbhdlr[BFI_MC_MAX]; }; -/* IOC callback function interfaces */ +/** + * IOC callback function interfaces + */ typedef void (*bfa_ioc_enable_cbfn_t)(void *bfa, enum bfa_status status); typedef void (*bfa_ioc_disable_cbfn_t)(void *bfa); typedef void (*bfa_ioc_hbfail_cbfn_t)(void *bfa); @@ -133,7 +146,9 @@ struct bfa_ioc_cbfn { bfa_ioc_reset_cbfn_t reset_cbfn; }; -/* IOC event notification mechanism. */ +/** + * IOC event notification mechanism. + */ enum bfa_ioc_event { BFA_IOC_E_ENABLED = 1, BFA_IOC_E_DISABLED = 2, @@ -148,7 +163,9 @@ struct bfa_ioc_notify { void *cbarg; }; -/* Initialize a IOC event notification structure */ +/** + * Initialize a IOC event notification structure + */ #define bfa_ioc_notify_init(__notify, __cbfn, __cbarg) do { \ (__notify)->cbfn = (__cbfn); \ (__notify)->cbarg = (__cbarg); \ @@ -244,7 +261,9 @@ struct bfa_ioc_hwif { #define BFA_IOC_FLASH_OFFSET_IN_CHUNK(off) (off % BFI_FLASH_CHUNK_SZ_WORDS) #define BFA_IOC_FLASH_CHUNK_ADDR(chunkno) (chunkno * BFI_FLASH_CHUNK_SZ_WORDS) -/* IOC mailbox interface */ +/** + * IOC mailbox interface + */ bool bfa_nw_ioc_mbox_queue(struct bfa_ioc *ioc, struct bfa_mbox_cmd *cmd, bfa_mbox_cmd_cbfn_t cbfn, void *cbarg); @@ -252,7 +271,9 @@ void bfa_nw_ioc_mbox_isr(struct bfa_ioc *ioc); void bfa_nw_ioc_mbox_regisr(struct bfa_ioc *ioc, enum bfi_mclass mc, bfa_ioc_mbox_mcfunc_t cbfn, void *cbarg); -/* IOC interfaces */ +/** + * IOC interfaces + */ #define bfa_ioc_pll_init_asic(__ioc) \ ((__ioc)->ioc_hwif->ioc_pll_init((__ioc)->pcidev.pci_bar_kva, \ diff --git a/trunk/drivers/net/ethernet/brocade/bna/bfa_ioc_ct.c b/trunk/drivers/net/ethernet/brocade/bna/bfa_ioc_ct.c index 5df0b0c68c5a..b6b036a143ae 100644 --- a/trunk/drivers/net/ethernet/brocade/bna/bfa_ioc_ct.c +++ b/trunk/drivers/net/ethernet/brocade/bna/bfa_ioc_ct.c @@ -87,7 +87,9 @@ static const struct bfa_ioc_hwif nw_hwif_ct2 = { .ioc_sync_complete = bfa_ioc_ct_sync_complete, }; -/* Called from bfa_ioc_attach() to map asic specific calls. */ +/** + * Called from bfa_ioc_attach() to map asic specific calls. + */ void bfa_nw_ioc_set_ct_hwif(struct bfa_ioc *ioc) { @@ -100,7 +102,9 @@ bfa_nw_ioc_set_ct2_hwif(struct bfa_ioc *ioc) ioc->ioc_hwif = &nw_hwif_ct2; } -/* Return true if firmware of current driver matches the running firmware. */ +/** + * Return true if firmware of current driver matches the running firmware. + */ static bool bfa_ioc_ct_firmware_lock(struct bfa_ioc *ioc) { @@ -178,7 +182,9 @@ bfa_ioc_ct_firmware_unlock(struct bfa_ioc *ioc) bfa_nw_ioc_sem_release(ioc->ioc_regs.ioc_usage_sem_reg); } -/* Notify other functions on HB failure. */ +/** + * Notify other functions on HB failure. + */ static void bfa_ioc_ct_notify_fail(struct bfa_ioc *ioc) { @@ -189,7 +195,9 @@ bfa_ioc_ct_notify_fail(struct bfa_ioc *ioc) readl(ioc->ioc_regs.alt_ll_halt); } -/* Host to LPU mailbox message addresses */ +/** + * Host to LPU mailbox message addresses + */ static const struct { u32 hfn_mbox; u32 lpu_mbox; @@ -201,7 +209,9 @@ static const struct { { HOSTFN3_LPU_MBOX0_8, LPU_HOSTFN3_MBOX0_8, HOST_PAGE_NUM_FN3 } }; -/* Host <-> LPU mailbox command/status registers - port 0 */ +/** + * Host <-> LPU mailbox command/status registers - port 0 + */ static const struct { u32 hfn; u32 lpu; @@ -212,7 +222,9 @@ static const struct { { HOSTFN3_LPU0_CMD_STAT, LPU0_HOSTFN3_CMD_STAT } }; -/* Host <-> LPU mailbox command/status registers - port 1 */ +/** + * Host <-> LPU mailbox command/status registers - port 1 + */ static const struct { u32 hfn; u32 lpu; @@ -356,7 +368,9 @@ bfa_ioc_ct2_reg_init(struct bfa_ioc *ioc) ioc->ioc_regs.err_set = rb + ERR_SET_REG; } -/* Initialize IOC to port mapping. */ +/** + * Initialize IOC to port mapping. + */ #define FNC_PERS_FN_SHIFT(__fn) ((__fn) * 8) static void @@ -384,7 +398,9 @@ bfa_ioc_ct2_map_port(struct bfa_ioc *ioc) ioc->port_id = ((r32 & __FC_LL_PORT_MAP__MK) >> __FC_LL_PORT_MAP__SH); } -/* Set interrupt mode for a function: INTX or MSIX */ +/** + * Set interrupt mode for a function: INTX or MSIX + */ static void bfa_ioc_ct_isr_mode_set(struct bfa_ioc *ioc, bool msix) { @@ -427,7 +443,9 @@ bfa_ioc_ct2_lpu_read_stat(struct bfa_ioc *ioc) return false; } -/* MSI-X resource allocation for 1860 with no asic block */ +/** + * MSI-X resource allocation for 1860 with no asic block + */ #define HOSTFN_MSIX_DEFAULT 64 #define HOSTFN_MSIX_VT_INDEX_MBOX_ERR 0x30138 #define HOSTFN_MSIX_VT_OFST_NUMVT 0x3013c @@ -455,7 +473,9 @@ bfa_nw_ioc_ct2_poweron(struct bfa_ioc *ioc) rb + HOSTFN_MSIX_VT_INDEX_MBOX_ERR); } -/* Cleanup hw semaphore and usecnt registers */ +/** + * Cleanup hw semaphore and usecnt registers + */ static void bfa_ioc_ct_ownership_reset(struct bfa_ioc *ioc) { @@ -472,7 +492,9 @@ bfa_ioc_ct_ownership_reset(struct bfa_ioc *ioc) bfa_nw_ioc_hw_sem_release(ioc); } -/* Synchronized IOC failure processing routines */ +/** + * Synchronized IOC failure processing routines + */ static bool bfa_ioc_ct_sync_start(struct bfa_ioc *ioc) { @@ -496,7 +518,9 @@ bfa_ioc_ct_sync_start(struct bfa_ioc *ioc) return bfa_ioc_ct_sync_complete(ioc); } -/* Synchronized IOC failure processing routines */ +/** + * Synchronized IOC failure processing routines + */ static void bfa_ioc_ct_sync_join(struct bfa_ioc *ioc) { diff --git a/trunk/drivers/net/ethernet/brocade/bna/bfa_msgq.c b/trunk/drivers/net/ethernet/brocade/bna/bfa_msgq.c index 55067d0d25cf..dd36427f4752 100644 --- a/trunk/drivers/net/ethernet/brocade/bna/bfa_msgq.c +++ b/trunk/drivers/net/ethernet/brocade/bna/bfa_msgq.c @@ -16,7 +16,9 @@ * www.brocade.com */ -/* MSGQ module source file. */ +/** + * @file bfa_msgq.c MSGQ module source file. + */ #include "bfi.h" #include "bfa_msgq.h" diff --git a/trunk/drivers/net/ethernet/brocade/bna/bfi.h b/trunk/drivers/net/ethernet/brocade/bna/bfi.h index 1f24c23dc786..0d9df695397a 100644 --- a/trunk/drivers/net/ethernet/brocade/bna/bfi.h +++ b/trunk/drivers/net/ethernet/brocade/bna/bfi.h @@ -22,11 +22,15 @@ #pragma pack(1) -/* BFI FW image type */ +/** + * BFI FW image type + */ #define BFI_FLASH_CHUNK_SZ 256 /*!< Flash chunk size */ #define BFI_FLASH_CHUNK_SZ_WORDS (BFI_FLASH_CHUNK_SZ/sizeof(u32)) -/* Msg header common to all msgs */ +/** + * Msg header common to all msgs + */ struct bfi_mhdr { u8 msg_class; /*!< @ref enum bfi_mclass */ u8 msg_id; /*!< msg opcode with in the class */ @@ -61,14 +65,17 @@ struct bfi_mhdr { #define BFI_I2H_OPCODE_BASE 128 #define BFA_I2HM(_x) ((_x) + BFI_I2H_OPCODE_BASE) -/**************************************************************************** +/** + **************************************************************************** * * Scatter Gather Element and Page definition * **************************************************************************** */ -/* DMA addresses */ +/** + * DMA addresses + */ union bfi_addr_u { struct { u32 addr_lo; @@ -76,7 +83,9 @@ union bfi_addr_u { } a32; }; -/* Generic DMA addr-len pair. */ +/** + * Generic DMA addr-len pair. + */ struct bfi_alen { union bfi_addr_u al_addr; /* DMA addr of buffer */ u32 al_len; /* length of buffer */ @@ -89,20 +98,26 @@ struct bfi_alen { #define BFI_LMSG_PL_WSZ \ ((BFI_LMSG_SZ - sizeof(struct bfi_mhdr)) / 4) -/* Mailbox message structure */ +/** + * Mailbox message structure + */ #define BFI_MBMSG_SZ 7 struct bfi_mbmsg { struct bfi_mhdr mh; u32 pl[BFI_MBMSG_SZ]; }; -/* Supported PCI function class codes (personality) */ +/** + * Supported PCI function class codes (personality) + */ enum bfi_pcifn_class { BFI_PCIFN_CLASS_FC = 0x0c04, BFI_PCIFN_CLASS_ETH = 0x0200, }; -/* Message Classes */ +/** + * Message Classes + */ enum bfi_mclass { BFI_MC_IOC = 1, /*!< IO Controller (IOC) */ BFI_MC_DIAG = 2, /*!< Diagnostic Msgs */ @@ -144,12 +159,15 @@ enum bfi_mclass { #define BFI_FWBOOT_ENV_OS 0 -/*---------------------------------------------------------------------- +/** + *---------------------------------------------------------------------- * IOC *---------------------------------------------------------------------- */ -/* Different asic generations */ +/** + * Different asic generations + */ enum bfi_asic_gen { BFI_ASIC_GEN_CB = 1, BFI_ASIC_GEN_CT = 2, @@ -178,7 +196,9 @@ enum bfi_ioc_i2h_msgs { BFI_IOC_I2H_HBEAT = BFA_I2HM(4), }; -/* BFI_IOC_H2I_GETATTR_REQ message */ +/** + * BFI_IOC_H2I_GETATTR_REQ message + */ struct bfi_ioc_getattr_req { struct bfi_mhdr mh; union bfi_addr_u attr_addr; @@ -211,22 +231,30 @@ struct bfi_ioc_attr { u32 card_type; /*!< card type */ }; -/* BFI_IOC_I2H_GETATTR_REPLY message */ +/** + * BFI_IOC_I2H_GETATTR_REPLY message + */ struct bfi_ioc_getattr_reply { struct bfi_mhdr mh; /*!< Common msg header */ u8 status; /*!< cfg reply status */ u8 rsvd[3]; }; -/* Firmware memory page offsets */ +/** + * Firmware memory page offsets + */ #define BFI_IOC_SMEM_PG0_CB (0x40) #define BFI_IOC_SMEM_PG0_CT (0x180) -/* Firmware statistic offset */ +/** + * Firmware statistic offset + */ #define BFI_IOC_FWSTATS_OFF (0x6B40) #define BFI_IOC_FWSTATS_SZ (4096) -/* Firmware trace offset */ +/** + * Firmware trace offset + */ #define BFI_IOC_TRC_OFF (0x4b00) #define BFI_IOC_TRC_ENTS 256 #define BFI_IOC_TRC_ENT_SZ 16 @@ -271,7 +299,9 @@ struct bfi_ioc_hbeat { u32 hb_count; /*!< current heart beat count */ }; -/* IOC hardware/firmware state */ +/** + * IOC hardware/firmware state + */ enum bfi_ioc_state { BFI_IOC_UNINIT = 0, /*!< not initialized */ BFI_IOC_INITING = 1, /*!< h/w is being initialized */ @@ -315,7 +345,9 @@ enum { ((__adap_type) & (BFI_ADAPTER_TTV | BFI_ADAPTER_PROTO | \ BFI_ADAPTER_UNSUPP)) -/* BFI_IOC_H2I_ENABLE_REQ & BFI_IOC_H2I_DISABLE_REQ messages */ +/** + * BFI_IOC_H2I_ENABLE_REQ & BFI_IOC_H2I_DISABLE_REQ messages + */ struct bfi_ioc_ctrl_req { struct bfi_mhdr mh; u16 clscode; @@ -323,7 +355,9 @@ struct bfi_ioc_ctrl_req { u32 tv_sec; }; -/* BFI_IOC_I2H_ENABLE_REPLY & BFI_IOC_I2H_DISABLE_REPLY messages */ +/** + * BFI_IOC_I2H_ENABLE_REPLY & BFI_IOC_I2H_DISABLE_REPLY messages + */ struct bfi_ioc_ctrl_reply { struct bfi_mhdr mh; /*!< Common msg header */ u8 status; /*!< enable/disable status */ @@ -333,7 +367,9 @@ struct bfi_ioc_ctrl_reply { }; #define BFI_IOC_MSGSZ 8 -/* H2I Messages */ +/** + * H2I Messages + */ union bfi_ioc_h2i_msg_u { struct bfi_mhdr mh; struct bfi_ioc_ctrl_req enable_req; @@ -342,14 +378,17 @@ union bfi_ioc_h2i_msg_u { u32 mboxmsg[BFI_IOC_MSGSZ]; }; -/* I2H Messages */ +/** + * I2H Messages + */ union bfi_ioc_i2h_msg_u { struct bfi_mhdr mh; struct bfi_ioc_ctrl_reply fw_event; u32 mboxmsg[BFI_IOC_MSGSZ]; }; -/*---------------------------------------------------------------------- +/** + *---------------------------------------------------------------------- * MSGQ *---------------------------------------------------------------------- */ diff --git a/trunk/drivers/net/ethernet/brocade/bna/bfi_cna.h b/trunk/drivers/net/ethernet/brocade/bna/bfi_cna.h index 6704a4392973..4eecabea397b 100644 --- a/trunk/drivers/net/ethernet/brocade/bna/bfi_cna.h +++ b/trunk/drivers/net/ethernet/brocade/bna/bfi_cna.h @@ -37,14 +37,18 @@ enum bfi_port_i2h { BFI_PORT_I2H_CLEAR_STATS_RSP = BFA_I2HM(4), }; -/* Generic REQ type */ +/** + * Generic REQ type + */ struct bfi_port_generic_req { struct bfi_mhdr mh; /*!< msg header */ u32 msgtag; /*!< msgtag for reply */ u32 rsvd; }; -/* Generic RSP type */ +/** + * Generic RSP type + */ struct bfi_port_generic_rsp { struct bfi_mhdr mh; /*!< common msg header */ u8 status; /*!< port enable status */ @@ -52,12 +56,44 @@ struct bfi_port_generic_rsp { u32 msgtag; /*!< msgtag for reply */ }; -/* BFI_PORT_H2I_GET_STATS_REQ */ +/** + * @todo + * BFI_PORT_H2I_ENABLE_REQ + */ + +/** + * @todo + * BFI_PORT_I2H_ENABLE_RSP + */ + +/** + * BFI_PORT_H2I_DISABLE_REQ + */ + +/** + * BFI_PORT_I2H_DISABLE_RSP + */ + +/** + * BFI_PORT_H2I_GET_STATS_REQ + */ struct bfi_port_get_stats_req { struct bfi_mhdr mh; /*!< common msg header */ union bfi_addr_u dma_addr; }; +/** + * BFI_PORT_I2H_GET_STATS_RSP + */ + +/** + * BFI_PORT_H2I_CLEAR_STATS_REQ + */ + +/** + * BFI_PORT_I2H_CLEAR_STATS_RSP + */ + union bfi_port_h2i_msg_u { struct bfi_mhdr mh; struct bfi_port_generic_req enable_req; diff --git a/trunk/drivers/net/ethernet/brocade/bna/bfi_enet.h b/trunk/drivers/net/ethernet/brocade/bna/bfi_enet.h index eef6e1f8aecc..a90f1cf46b41 100644 --- a/trunk/drivers/net/ethernet/brocade/bna/bfi_enet.h +++ b/trunk/drivers/net/ethernet/brocade/bna/bfi_enet.h @@ -16,9 +16,12 @@ * www.brocade.com */ -/* BNA Hardware and Firmware Interface */ +/** + * @file bfi_enet.h BNA Hardware and Firmware Interface + */ -/* Skipping statistics collection to avoid clutter. +/** + * Skipping statistics collection to avoid clutter. * Command is no longer needed: * MTU * TxQ Stop @@ -61,7 +64,9 @@ union bfi_addr_be_u { } a32; }; -/* T X Q U E U E D E F I N E S */ +/** + * T X Q U E U E D E F I N E S + */ /* TxQ Vector (a.k.a. Tx-Buffer Descriptor) */ /* TxQ Entry Opcodes */ #define BFI_ENET_TXQ_WI_SEND (0x402) /* Single Frame Transmission */ @@ -101,7 +106,10 @@ struct bfi_enet_txq_wi_vector { /* Tx Buffer Descriptor */ union bfi_addr_be_u addr; }; -/* TxQ Entry Structure */ +/** + * TxQ Entry Structure + * + */ struct bfi_enet_txq_entry { union { struct bfi_enet_txq_wi_base base; @@ -116,12 +124,16 @@ struct bfi_enet_txq_entry { #define BFI_ENET_TXQ_WI_L4_HDR_N_OFFSET(_hdr_size, _offset) \ (((_hdr_size) << 10) | ((_offset) & 0x3FF)) -/* R X Q U E U E D E F I N E S */ +/** + * R X Q U E U E D E F I N E S + */ struct bfi_enet_rxq_entry { union bfi_addr_be_u rx_buffer; }; -/* R X C O M P L E T I O N Q U E U E D E F I N E S */ +/** + * R X C O M P L E T I O N Q U E U E D E F I N E S + */ /* CQ Entry Flags */ #define BFI_ENET_CQ_EF_MAC_ERROR (1 << 0) #define BFI_ENET_CQ_EF_FCS_ERROR (1 << 1) @@ -162,7 +174,9 @@ struct bfi_enet_cq_entry { u8 rxq_id; }; -/* E N E T C O N T R O L P A T H C O M M A N D S */ +/** + * E N E T C O N T R O L P A T H C O M M A N D S + */ struct bfi_enet_q { union bfi_addr_u pg_tbl; union bfi_addr_u first_entry; @@ -208,7 +222,9 @@ struct bfi_enet_ib { u16 rsvd; }; -/* ENET command messages */ +/** + * ENET command messages + */ enum bfi_enet_h2i_msgs { /* Rx Commands */ BFI_ENET_H2I_RX_CFG_SET_REQ = 1, @@ -334,7 +350,9 @@ enum bfi_enet_i2h_msgs { BFI_ENET_I2H_BW_UPDATE_AEN = BFA_I2HM(BFI_ENET_H2I_MAX + 4), }; -/* The following error codes can be returned by the enet commands */ +/** + * The following error codes can be returned by the enet commands + */ enum bfi_enet_err { BFI_ENET_CMD_OK = 0, BFI_ENET_CMD_FAIL = 1, @@ -346,7 +364,8 @@ enum bfi_enet_err { BFI_ENET_CMD_PORT_DISABLED = 7, /* !< port in disabled state */ }; -/* Generic Request +/** + * Generic Request * * bfi_enet_req is used by: * BFI_ENET_H2I_RX_CFG_CLR_REQ @@ -356,7 +375,8 @@ struct bfi_enet_req { struct bfi_msgq_mhdr mh; }; -/* Enable/Disable Request +/** + * Enable/Disable Request * * bfi_enet_enable_req is used by: * BFI_ENET_H2I_RSS_ENABLE_REQ (enet_id must be zero) @@ -371,7 +391,9 @@ struct bfi_enet_enable_req { u8 rsvd[3]; }; -/* Generic Response */ +/** + * Generic Response + */ struct bfi_enet_rsp { struct bfi_msgq_mhdr mh; u8 error; /*!< if error see cmd_offset */ @@ -379,16 +401,20 @@ struct bfi_enet_rsp { u16 cmd_offset; /*!< offset to invalid parameter */ }; -/* GLOBAL CONFIGURATION */ +/** + * GLOBAL CONFIGURATION + */ -/* bfi_enet_attr_req is used by: +/** + * bfi_enet_attr_req is used by: * BFI_ENET_H2I_GET_ATTR_REQ */ struct bfi_enet_attr_req { struct bfi_msgq_mhdr mh; }; -/* bfi_enet_attr_rsp is used by: +/** + * bfi_enet_attr_rsp is used by: * BFI_ENET_I2H_GET_ATTR_RSP */ struct bfi_enet_attr_rsp { @@ -401,7 +427,8 @@ struct bfi_enet_attr_rsp { u32 rit_size; }; -/* Tx Configuration +/** + * Tx Configuration * * bfi_enet_tx_cfg is used by: * BFI_ENET_H2I_TX_CFG_SET_REQ @@ -450,7 +477,8 @@ struct bfi_enet_tx_cfg_rsp { } q_handles[BFI_ENET_TXQ_PRIO_MAX]; }; -/* Rx Configuration +/** + * Rx Configuration * * bfi_enet_rx_cfg is used by: * BFI_ENET_H2I_RX_CFG_SET_REQ @@ -525,7 +553,8 @@ struct bfi_enet_rx_cfg_rsp { } q_handles[BFI_ENET_RX_QSET_MAX]; }; -/* RIT +/** + * RIT * * bfi_enet_rit_req is used by: * BFI_ENET_H2I_RIT_CFG_REQ @@ -537,7 +566,8 @@ struct bfi_enet_rit_req { u8 table[BFI_ENET_RSS_RIT_MAX]; }; -/* RSS +/** + * RSS * * bfi_enet_rss_cfg_req is used by: * BFI_ENET_H2I_RSS_CFG_REQ @@ -561,7 +591,8 @@ struct bfi_enet_rss_cfg_req { struct bfi_enet_rss_cfg cfg; }; -/* MAC Unicast +/** + * MAC Unicast * * bfi_enet_rx_vlan_req is used by: * BFI_ENET_H2I_MAC_UCAST_SET_REQ @@ -575,14 +606,17 @@ struct bfi_enet_ucast_req { u8 rsvd[2]; }; -/* MAC Unicast + VLAN */ +/** + * MAC Unicast + VLAN + */ struct bfi_enet_mac_n_vlan_req { struct bfi_msgq_mhdr mh; u16 vlan_id; mac_t mac_addr; }; -/* MAC Multicast +/** + * MAC Multicast * * bfi_enet_mac_mfilter_add_req is used by: * BFI_ENET_H2I_MAC_MCAST_ADD_REQ @@ -593,7 +627,8 @@ struct bfi_enet_mcast_add_req { u8 rsvd[2]; }; -/* bfi_enet_mac_mfilter_add_rsp is used by: +/** + * bfi_enet_mac_mfilter_add_rsp is used by: * BFI_ENET_I2H_MAC_MCAST_ADD_RSP */ struct bfi_enet_mcast_add_rsp { @@ -605,7 +640,8 @@ struct bfi_enet_mcast_add_rsp { u8 rsvd1[2]; }; -/* bfi_enet_mac_mfilter_del_req is used by: +/** + * bfi_enet_mac_mfilter_del_req is used by: * BFI_ENET_H2I_MAC_MCAST_DEL_REQ */ struct bfi_enet_mcast_del_req { @@ -614,7 +650,8 @@ struct bfi_enet_mcast_del_req { u8 rsvd[2]; }; -/* VLAN +/** + * VLAN * * bfi_enet_rx_vlan_req is used by: * BFI_ENET_H2I_RX_VLAN_SET_REQ @@ -626,7 +663,8 @@ struct bfi_enet_rx_vlan_req { u32 bit_mask[BFI_ENET_VLAN_WORDS_MAX]; }; -/* PAUSE +/** + * PAUSE * * bfi_enet_set_pause_req is used by: * BFI_ENET_H2I_SET_PAUSE_REQ @@ -638,7 +676,8 @@ struct bfi_enet_set_pause_req { u8 rx_pause; /* 1 = enable; 0 = disable */ }; -/* DIAGNOSTICS +/** + * DIAGNOSTICS * * bfi_enet_diag_lb_req is used by: * BFI_ENET_H2I_DIAG_LOOPBACK @@ -650,13 +689,16 @@ struct bfi_enet_diag_lb_req { u8 enable; /* 1 = enable; 0 = disable */ }; -/* enum for Loopback opmodes */ +/** + * enum for Loopback opmodes + */ enum { BFI_ENET_DIAG_LB_OPMODE_EXT = 0, BFI_ENET_DIAG_LB_OPMODE_CBL = 1, }; -/* STATISTICS +/** + * STATISTICS * * bfi_enet_stats_req is used by: * BFI_ENET_H2I_STATS_GET_REQ @@ -671,7 +713,9 @@ struct bfi_enet_stats_req { union bfi_addr_u host_buffer; }; -/* defines for "stats_mask" above. */ +/** + * defines for "stats_mask" above. + */ #define BFI_ENET_STATS_MAC (1 << 0) /* !< MAC Statistics */ #define BFI_ENET_STATS_BPC (1 << 1) /* !< Pause Stats from BPC */ #define BFI_ENET_STATS_RAD (1 << 2) /* !< Rx Admission Statistics */ @@ -837,7 +881,8 @@ struct bfi_enet_stats_mac { u64 tx_fragments; }; -/* Complete statistics, DMAed from fw to host followed by +/** + * Complete statistics, DMAed from fw to host followed by * BFI_ENET_I2H_STATS_GET_RSP */ struct bfi_enet_stats { diff --git a/trunk/drivers/net/ethernet/brocade/bna/bfi_reg.h b/trunk/drivers/net/ethernet/brocade/bna/bfi_reg.h index c49fa312ddbd..0e094fe46dfd 100644 --- a/trunk/drivers/net/ethernet/brocade/bna/bfi_reg.h +++ b/trunk/drivers/net/ethernet/brocade/bna/bfi_reg.h @@ -221,7 +221,9 @@ enum { #define __PMM_1T_RESET_P 0x00000001 #define PMM_1T_RESET_REG_P1 0x00023c1c -/* Brocade 1860 Adapter specific defines */ +/** + * Brocade 1860 Adapter specific defines + */ #define CT2_PCI_CPQ_BASE 0x00030000 #define CT2_PCI_APP_BASE 0x00030100 #define CT2_PCI_ETH_BASE 0x00030400 diff --git a/trunk/drivers/net/ethernet/brocade/bna/bna.h b/trunk/drivers/net/ethernet/brocade/bna/bna.h index ede532b4e9db..4d7a5de08e12 100644 --- a/trunk/drivers/net/ethernet/brocade/bna/bna.h +++ b/trunk/drivers/net/ethernet/brocade/bna/bna.h @@ -25,7 +25,11 @@ extern const u32 bna_napi_dim_vector[][BNA_BIAS_T_MAX]; -/* Macros and constants */ +/** + * + * Macros and constants + * + */ #define BNA_IOC_TIMER_FREQ 200 @@ -352,7 +356,11 @@ do { \ } \ } while (0) -/* Inline functions */ +/** + * + * Inline functions + * + */ static inline struct bna_mac *bna_mac_find(struct list_head *q, u8 *addr) { @@ -369,9 +377,15 @@ static inline struct bna_mac *bna_mac_find(struct list_head *q, u8 *addr) #define bna_attr(_bna) (&(_bna)->ioceth.attr) -/* Function prototypes */ +/** + * + * Function prototypes + * + */ -/* BNA */ +/** + * BNA + */ /* FW response handlers */ void bna_bfi_stats_clr_rsp(struct bna *bna, struct bfi_msgq_mhdr *msghdr); @@ -399,19 +413,24 @@ struct bna_mcam_handle *bna_mcam_mod_handle_get(struct bna_mcam_mod *mod); void bna_mcam_mod_handle_put(struct bna_mcam_mod *mcam_mod, struct bna_mcam_handle *handle); -/* MBOX */ +/** + * MBOX + */ /* API for BNAD */ void bna_mbox_handler(struct bna *bna, u32 intr_status); -/* ETHPORT */ +/** + * ETHPORT + */ /* Callbacks for RX */ void bna_ethport_cb_rx_started(struct bna_ethport *ethport); void bna_ethport_cb_rx_stopped(struct bna_ethport *ethport); -/* TX MODULE AND TX */ - +/** + * TX MODULE AND TX + */ /* FW response handelrs */ void bna_bfi_tx_enet_start_rsp(struct bna_tx *tx, struct bfi_msgq_mhdr *msghdr); @@ -443,7 +462,9 @@ void bna_tx_disable(struct bna_tx *tx, enum bna_cleanup_type type, void bna_tx_cleanup_complete(struct bna_tx *tx); void bna_tx_coalescing_timeo_set(struct bna_tx *tx, int coalescing_timeo); -/* RX MODULE, RX, RXF */ +/** + * RX MODULE, RX, RXF + */ /* FW response handlers */ void bna_bfi_rx_enet_start_rsp(struct bna_rx *rx, @@ -501,7 +522,9 @@ bna_rx_mode_set(struct bna_rx *rx, enum bna_rxmode rxmode, void bna_rx_vlan_add(struct bna_rx *rx, int vlan_id); void bna_rx_vlan_del(struct bna_rx *rx, int vlan_id); void bna_rx_vlanfilter_enable(struct bna_rx *rx); -/* ENET */ +/** + * ENET + */ /* API for RX */ int bna_enet_mtu_get(struct bna_enet *enet); @@ -521,14 +544,18 @@ void bna_enet_mtu_set(struct bna_enet *enet, int mtu, void (*cbfn)(struct bnad *)); void bna_enet_perm_mac_get(struct bna_enet *enet, mac_t *mac); -/* IOCETH */ +/** + * IOCETH + */ /* APIs for BNAD */ void bna_ioceth_enable(struct bna_ioceth *ioceth); void bna_ioceth_disable(struct bna_ioceth *ioceth, enum bna_cleanup_type type); -/* BNAD */ +/** + * BNAD + */ /* Callbacks for ENET */ void bnad_cb_ethport_link_status(struct bnad *bnad, diff --git a/trunk/drivers/net/ethernet/brocade/bna/bna_enet.c b/trunk/drivers/net/ethernet/brocade/bna/bna_enet.c index db14f69d63bc..9ccc586e3767 100644 --- a/trunk/drivers/net/ethernet/brocade/bna/bna_enet.c +++ b/trunk/drivers/net/ethernet/brocade/bna/bna_enet.c @@ -378,8 +378,9 @@ bna_msgq_rsp_handler(void *arg, struct bfi_msgq_mhdr *msghdr) } } -/* ETHPORT */ - +/** + * ETHPORT + */ #define call_ethport_stop_cbfn(_ethport) \ do { \ if ((_ethport)->stop_cbfn) { \ @@ -803,8 +804,9 @@ bna_ethport_cb_rx_stopped(struct bna_ethport *ethport) } } -/* ENET */ - +/** + * ENET + */ #define bna_enet_chld_start(enet) \ do { \ enum bna_tx_type tx_type = \ @@ -1326,8 +1328,9 @@ bna_enet_perm_mac_get(struct bna_enet *enet, mac_t *mac) *mac = bfa_nw_ioc_get_mac(&enet->bna->ioceth.ioc); } -/* IOCETH */ - +/** + * IOCETH + */ #define enable_mbox_intr(_ioceth) \ do { \ u32 intr_status; \ diff --git a/trunk/drivers/net/ethernet/brocade/bna/bna_hw_defs.h b/trunk/drivers/net/ethernet/brocade/bna/bna_hw_defs.h index b8c4e21fbf4c..4c6aab2a9534 100644 --- a/trunk/drivers/net/ethernet/brocade/bna/bna_hw_defs.h +++ b/trunk/drivers/net/ethernet/brocade/bna/bna_hw_defs.h @@ -16,15 +16,20 @@ * www.brocade.com */ -/* File for interrupt macros and functions */ +/** + * File for interrupt macros and functions + */ #ifndef __BNA_HW_DEFS_H__ #define __BNA_HW_DEFS_H__ #include "bfi_reg.h" -/* SW imposed limits */ - +/** + * + * SW imposed limits + * + */ #define BFI_ENET_DEF_TXQ 1 #define BFI_ENET_DEF_RXP 1 #define BFI_ENET_DEF_UCAM 1 @@ -136,8 +141,11 @@ } #define bna_port_id_get(_bna) ((_bna)->ioceth.ioc.port_id) - -/* Interrupt related bits, flags and macros */ +/** + * + * Interrupt related bits, flags and macros + * + */ #define IB_STATUS_BITS 0x0000ffff @@ -272,7 +280,11 @@ do { \ (writel(BNA_DOORBELL_Q_PRD_IDX((_rcb)->producer_index), \ (_rcb)->q_dbell)); -/* TxQ, RxQ, CQ related bits, offsets, macros */ +/** + * + * TxQ, RxQ, CQ related bits, offsets, macros + * + */ /* TxQ Entry Opcodes */ #define BNA_TXQ_WI_SEND (0x402) /* Single Frame Transmission */ @@ -322,7 +334,11 @@ do { \ #define BNA_CQ_EF_LOCAL (1 << 20) -/* Data structures */ +/** + * + * Data structures + * + */ struct bna_reg_offset { u32 fn_int_status; @@ -355,7 +371,8 @@ struct bna_txq_wi_vector { struct bna_dma_addr host_addr; /* Tx-Buf DMA addr */ }; -/* TxQ Entry Structure +/** + * TxQ Entry Structure * * BEWARE: Load values into this structure with correct endianess. */ diff --git a/trunk/drivers/net/ethernet/brocade/bna/bna_tx_rx.c b/trunk/drivers/net/ethernet/brocade/bna/bna_tx_rx.c index 71144b396e02..276fcb589f4b 100644 --- a/trunk/drivers/net/ethernet/brocade/bna/bna_tx_rx.c +++ b/trunk/drivers/net/ethernet/brocade/bna/bna_tx_rx.c @@ -18,7 +18,9 @@ #include "bna.h" #include "bfi.h" -/* IB */ +/** + * IB + */ static void bna_ib_coalescing_timeo_set(struct bna_ib *ib, u8 coalescing_timeo) { @@ -27,7 +29,9 @@ bna_ib_coalescing_timeo_set(struct bna_ib *ib, u8 coalescing_timeo) (u32)ib->coalescing_timeo, 0); } -/* RXF */ +/** + * RXF + */ #define bna_rxf_vlan_cfg_soft_reset(rxf) \ do { \ @@ -1308,7 +1312,9 @@ bna_rxf_vlan_strip_cfg_apply(struct bna_rxf *rxf) return 0; } -/* RX */ +/** + * RX + */ #define BNA_GET_RXQS(qcfg) (((qcfg)->rxp_type == BNA_RXP_SINGLE) ? \ (qcfg)->num_paths : ((qcfg)->num_paths * 2)) @@ -2785,8 +2791,9 @@ const u32 bna_napi_dim_vector[BNA_LOAD_T_MAX][BNA_BIAS_T_MAX] = { {1, 2}, }; -/* TX */ - +/** + * TX + */ #define call_tx_stop_cbfn(tx) \ do { \ if ((tx)->stop_cbfn) { \ diff --git a/trunk/drivers/net/ethernet/brocade/bna/bna_types.h b/trunk/drivers/net/ethernet/brocade/bna/bna_types.h index d3eb8bddfb2a..e8d3ab7ea6cb 100644 --- a/trunk/drivers/net/ethernet/brocade/bna/bna_types.h +++ b/trunk/drivers/net/ethernet/brocade/bna/bna_types.h @@ -23,7 +23,11 @@ #include "bfa_cee.h" #include "bfa_msgq.h" -/* Forward declarations */ +/** + * + * Forward declarations + * + */ struct bna_mcam_handle; struct bna_txq; @@ -36,7 +40,11 @@ struct bna_enet; struct bna; struct bnad; -/* Enums, primitive data types */ +/** + * + * Enums, primitive data types + * + */ enum bna_status { BNA_STATUS_T_DISABLED = 0, @@ -323,7 +331,11 @@ struct bna_attr { int max_rit_size; }; -/* IOCEth */ +/** + * + * IOCEth + * + */ struct bna_ioceth { bfa_fsm_t fsm; @@ -339,7 +351,11 @@ struct bna_ioceth { struct bna *bna; }; -/* Enet */ +/** + * + * Enet + * + */ /* Pause configuration */ struct bna_pause_config { @@ -374,7 +390,11 @@ struct bna_enet { struct bna *bna; }; -/* Ethport */ +/** + * + * Ethport + * + */ struct bna_ethport { bfa_fsm_t fsm; @@ -399,7 +419,11 @@ struct bna_ethport { struct bna *bna; }; -/* Interrupt Block */ +/** + * + * Interrupt Block + * + */ /* Doorbell structure */ struct bna_ib_dbell { @@ -423,7 +447,11 @@ struct bna_ib { int interpkt_timeo; }; -/* Tx object */ +/** + * + * Tx object + * + */ /* Tx datapath control structure */ #define BNA_Q_NAME_SIZE 16 @@ -557,7 +585,11 @@ struct bna_tx_mod { struct bna *bna; }; -/* Rx object */ +/** + * + * Rx object + * + */ /* Rx datapath control structure */ struct bna_rcb { @@ -866,7 +898,11 @@ struct bna_rx_mod { u32 rid_mask; }; -/* CAM */ +/** + * + * CAM + * + */ struct bna_ucam_mod { struct bna_mac *ucmac; /* BFI_MAX_UCMAC entries */ @@ -891,7 +927,11 @@ struct bna_mcam_mod { struct bna *bna; }; -/* Statistics */ +/** + * + * Statistics + * + */ struct bna_stats { struct bna_dma_addr hw_stats_dma; @@ -909,7 +949,11 @@ struct bna_stats_mod { struct bfi_enet_stats_req stats_clr; }; -/* BNA */ +/** + * + * BNA + * + */ struct bna { struct bna_ident ident; diff --git a/trunk/drivers/net/ethernet/brocade/bna/bnad.c b/trunk/drivers/net/ethernet/brocade/bna/bnad.c index b441f33258e7..67cd2ed0306a 100644 --- a/trunk/drivers/net/ethernet/brocade/bna/bnad.c +++ b/trunk/drivers/net/ethernet/brocade/bna/bnad.c @@ -1302,7 +1302,8 @@ bnad_txrx_irq_alloc(struct bnad *bnad, enum bnad_intr_source src, return 0; } -/* NOTE: Should be called for MSIX only +/** + * NOTE: Should be called for MSIX only * Unregisters Tx MSIX vector(s) from the kernel */ static void @@ -1321,7 +1322,8 @@ bnad_tx_msix_unregister(struct bnad *bnad, struct bnad_tx_info *tx_info, } } -/* NOTE: Should be called for MSIX only +/** + * NOTE: Should be called for MSIX only * Registers Tx MSIX vector(s) and ISR(s), cookie with the kernel */ static int @@ -1352,7 +1354,8 @@ bnad_tx_msix_register(struct bnad *bnad, struct bnad_tx_info *tx_info, return -1; } -/* NOTE: Should be called for MSIX only +/** + * NOTE: Should be called for MSIX only * Unregisters Rx MSIX vector(s) from the kernel */ static void @@ -1372,7 +1375,8 @@ bnad_rx_msix_unregister(struct bnad *bnad, struct bnad_rx_info *rx_info, } } -/* NOTE: Should be called for MSIX only +/** + * NOTE: Should be called for MSIX only * Registers Tx MSIX vector(s) and ISR(s), cookie with the kernel */ static int diff --git a/trunk/drivers/net/ethernet/brocade/bna/bnad.h b/trunk/drivers/net/ethernet/brocade/bna/bnad.h index d78339224751..72742be11277 100644 --- a/trunk/drivers/net/ethernet/brocade/bna/bnad.h +++ b/trunk/drivers/net/ethernet/brocade/bna/bnad.h @@ -389,7 +389,9 @@ extern void bnad_netdev_hwstats_fill(struct bnad *bnad, void bnad_debugfs_init(struct bnad *bnad); void bnad_debugfs_uninit(struct bnad *bnad); -/* MACROS */ +/** + * MACROS + */ /* To set & get the stats counters */ #define BNAD_UPDATE_CTR(_bnad, _ctr) \ (((_bnad)->stats.drv_stats._ctr)++) diff --git a/trunk/drivers/net/ethernet/cadence/macb.c b/trunk/drivers/net/ethernet/cadence/macb.c index 033064b7b576..1466bc4e3dda 100644 --- a/trunk/drivers/net/ethernet/cadence/macb.c +++ b/trunk/drivers/net/ethernet/cadence/macb.c @@ -179,16 +179,13 @@ static void macb_handle_link_change(struct net_device *dev) spin_unlock_irqrestore(&bp->lock, flags); if (status_change) { - if (phydev->link) { - netif_carrier_on(dev); + if (phydev->link) netdev_info(dev, "link up (%d/%s)\n", phydev->speed, phydev->duplex == DUPLEX_FULL ? "Full" : "Half"); - } else { - netif_carrier_off(dev); + else netdev_info(dev, "link down\n"); - } } } @@ -1036,9 +1033,6 @@ static int macb_open(struct net_device *dev) netdev_dbg(bp->dev, "open\n"); - /* carrier starts down */ - netif_carrier_off(dev); - /* if the phy is not yet register, retry later*/ if (!bp->phy_dev) return -EAGAIN; @@ -1412,8 +1406,6 @@ static int __init macb_probe(struct platform_device *pdev) platform_set_drvdata(pdev, dev); - netif_carrier_off(dev); - netdev_info(dev, "Cadence %s at 0x%08lx irq %d (%pM)\n", macb_is_gem(bp) ? "GEM" : "MACB", dev->base_addr, dev->irq, dev->dev_addr); @@ -1477,7 +1469,6 @@ static int macb_suspend(struct platform_device *pdev, pm_message_t state) struct net_device *netdev = platform_get_drvdata(pdev); struct macb *bp = netdev_priv(netdev); - netif_carrier_off(netdev); netif_device_detach(netdev); clk_disable(bp->hclk); diff --git a/trunk/drivers/net/ethernet/calxeda/xgmac.c b/trunk/drivers/net/ethernet/calxeda/xgmac.c index 2b4b4f529ab4..11f667f6131a 100644 --- a/trunk/drivers/net/ethernet/calxeda/xgmac.c +++ b/trunk/drivers/net/ethernet/calxeda/xgmac.c @@ -264,7 +264,7 @@ #define XGMAC_OMR_FEF 0x00000080 /* Forward Error Frames */ #define XGMAC_OMR_DT 0x00000040 /* Drop TCP/IP csum Errors */ #define XGMAC_OMR_RSF 0x00000020 /* RX FIFO Store and Forward */ -#define XGMAC_OMR_RTC_256 0x00000018 /* RX Threshhold Ctrl */ +#define XGMAC_OMR_RTC 0x00000010 /* RX Threshhold Ctrl */ #define XGMAC_OMR_RTC_MASK 0x00000018 /* RX Threshhold Ctrl MASK */ /* XGMAC HW Features Register */ @@ -671,23 +671,26 @@ static void xgmac_rx_refill(struct xgmac_priv *priv) p = priv->dma_rx + entry; - if (priv->rx_skbuff[entry] == NULL) { - skb = __skb_dequeue(&priv->rx_recycle); - if (skb == NULL) - skb = netdev_alloc_skb(priv->dev, priv->dma_buf_sz); - if (unlikely(skb == NULL)) - break; - - priv->rx_skbuff[entry] = skb; - paddr = dma_map_single(priv->device, skb->data, - priv->dma_buf_sz, DMA_FROM_DEVICE); - desc_set_buf_addr(p, paddr, priv->dma_buf_sz); - } + if (priv->rx_skbuff[entry] != NULL) + continue; + + skb = __skb_dequeue(&priv->rx_recycle); + if (skb == NULL) + skb = netdev_alloc_skb(priv->dev, priv->dma_buf_sz); + if (unlikely(skb == NULL)) + break; + + priv->rx_skbuff[entry] = skb; + paddr = dma_map_single(priv->device, skb->data, + priv->dma_buf_sz, DMA_FROM_DEVICE); + desc_set_buf_addr(p, paddr, priv->dma_buf_sz); netdev_dbg(priv->dev, "rx ring: head %d, tail %d\n", priv->rx_head, priv->rx_tail); priv->rx_head = dma_ring_incr(priv->rx_head, DMA_RX_RING_SZ); + /* Ensure descriptor is in memory before handing to h/w */ + wmb(); desc_set_rx_owner(p); } } @@ -930,7 +933,6 @@ static void xgmac_tx_err(struct xgmac_priv *priv) desc_init_tx_desc(priv->dma_tx, DMA_TX_RING_SZ); priv->tx_tail = 0; priv->tx_head = 0; - writel(priv->dma_tx_phy, priv->base + XGMAC_DMA_TX_BASE_ADDR); writel(reg | DMA_CONTROL_ST, priv->base + XGMAC_DMA_CONTROL); writel(DMA_STATUS_TU | DMA_STATUS_TPS | DMA_STATUS_NIS | DMA_STATUS_AIS, @@ -970,7 +972,7 @@ static int xgmac_hw_init(struct net_device *dev) writel(DMA_INTR_DEFAULT_MASK, ioaddr + XGMAC_DMA_INTR_ENA); /* XGMAC requires AXI bus init. This is a 'magic number' for now */ - writel(0x0077000E, ioaddr + XGMAC_DMA_AXI_BUS); + writel(0x000100E, ioaddr + XGMAC_DMA_AXI_BUS); ctrl |= XGMAC_CONTROL_DDIC | XGMAC_CONTROL_JE | XGMAC_CONTROL_ACS | XGMAC_CONTROL_CAR; @@ -982,8 +984,7 @@ static int xgmac_hw_init(struct net_device *dev) writel(value, ioaddr + XGMAC_DMA_CONTROL); /* Set the HW DMA mode and the COE */ - writel(XGMAC_OMR_TSF | XGMAC_OMR_RFD | XGMAC_OMR_RFA | - XGMAC_OMR_RTC_256, + writel(XGMAC_OMR_TSF | XGMAC_OMR_RSF | XGMAC_OMR_RFD | XGMAC_OMR_RFA, ioaddr + XGMAC_OMR); /* Reset the MMC counters */ diff --git a/trunk/drivers/net/ethernet/chelsio/cxgb3/sge.c b/trunk/drivers/net/ethernet/chelsio/cxgb3/sge.c index dd901c5061b9..cfb60e1f51da 100644 --- a/trunk/drivers/net/ethernet/chelsio/cxgb3/sge.c +++ b/trunk/drivers/net/ethernet/chelsio/cxgb3/sge.c @@ -2877,7 +2877,7 @@ static void sge_timer_tx(unsigned long data) mod_timer(&qs->tx_reclaim_timer, jiffies + next_period); } -/** +/* * sge_timer_rx - perform periodic maintenance of an SGE qset * @data: the SGE queue set to maintain * diff --git a/trunk/drivers/net/ethernet/chelsio/cxgb3/t3_hw.c b/trunk/drivers/net/ethernet/chelsio/cxgb3/t3_hw.c index bff8a3cdd3df..44ac2f40b644 100644 --- a/trunk/drivers/net/ethernet/chelsio/cxgb3/t3_hw.c +++ b/trunk/drivers/net/ethernet/chelsio/cxgb3/t3_hw.c @@ -1076,7 +1076,7 @@ static int t3_flash_erase_sectors(struct adapter *adapter, int start, int end) return 0; } -/** +/* * t3_load_fw - download firmware * @adapter: the adapter * @fw_data: the firmware image to write diff --git a/trunk/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c b/trunk/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c index fa947dfa4c30..32e1dd566a14 100644 --- a/trunk/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c +++ b/trunk/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c @@ -2010,7 +2010,7 @@ int t4_fwaddrspace_write(struct adapter *adap, unsigned int mbox, return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL); } -/** +/* * t4_mem_win_read_len - read memory through PCIE memory window * @adap: the adapter * @addr: address of first byte requested aligned on 32b. diff --git a/trunk/drivers/net/ethernet/cisco/enic/enic_main.c b/trunk/drivers/net/ethernet/cisco/enic/enic_main.c index ad1468b3ab91..8132c785cea8 100644 --- a/trunk/drivers/net/ethernet/cisco/enic/enic_main.c +++ b/trunk/drivers/net/ethernet/cisco/enic/enic_main.c @@ -1300,6 +1300,8 @@ static void enic_rq_indicate_buf(struct vnic_rq *rq, skb->ip_summed = CHECKSUM_COMPLETE; } + skb->dev = netdev; + if (vlan_stripped) __vlan_hwaccel_put_tag(skb, vlan_tci); diff --git a/trunk/drivers/net/ethernet/emulex/benet/be.h b/trunk/drivers/net/ethernet/emulex/benet/be.h index d266c86a53f7..7a71fb66c6dc 100644 --- a/trunk/drivers/net/ethernet/emulex/benet/be.h +++ b/trunk/drivers/net/ethernet/emulex/benet/be.h @@ -34,7 +34,7 @@ #include "be_hw.h" #include "be_roce.h" -#define DRV_VER "4.4.31.0u" +#define DRV_VER "4.2.248.0u" #define DRV_NAME "be2net" #define BE_NAME "ServerEngines BladeEngine2 10Gbps NIC" #define BE3_NAME "ServerEngines BladeEngine3 10Gbps NIC" @@ -389,7 +389,6 @@ struct be_adapter { struct delayed_work work; u16 work_counter; - struct delayed_work func_recovery_work; u32 flags; /* Ethtool knobs and info */ char fw_ver[FW_VER_LEN]; @@ -397,10 +396,9 @@ struct be_adapter { u32 *pmac_id; /* MAC addr handle used by BE card */ u32 beacon_state; /* for set_phys_id */ - bool eeh_error; + bool eeh_err; + bool ue_detected; bool fw_timeout; - bool hw_error; - u32 port_num; bool promiscuous; u32 function_mode; @@ -437,7 +435,6 @@ struct be_adapter { u32 max_pmac_cnt; /* Max secondary UC MACs programmable */ u32 uc_macs; /* Count of secondary UC MAC programmed */ u32 msg_enable; - int be_get_temp_freq; }; #define be_physfn(adapter) (!adapter->virtfn) @@ -457,9 +454,6 @@ struct be_adapter { #define lancer_chip(adapter) ((adapter->pdev->device == OC_DEVICE_ID3) || \ (adapter->pdev->device == OC_DEVICE_ID4)) -#define skyhawk_chip(adapter) (adapter->pdev->device == OC_DEVICE_ID5) - - #define be_roce_supported(adapter) ((adapter->if_type == SLI_INTF_TYPE_3 || \ adapter->sli_family == SKYHAWK_SLI_FAMILY) && \ (adapter->function_mode & RDMA_ENABLED)) @@ -581,7 +575,7 @@ static inline u8 is_udp_pkt(struct sk_buff *skb) static inline bool is_ipv4_pkt(struct sk_buff *skb) { - return skb->protocol == htons(ETH_P_IP) && ip_hdr(skb)->version == 4; + return skb->protocol == ntohs(ETH_P_IP) && ip_hdr(skb)->version == 4; } static inline void be_vf_eth_addr_generate(struct be_adapter *adapter, u8 *mac) @@ -604,19 +598,7 @@ static inline bool be_multi_rxq(const struct be_adapter *adapter) static inline bool be_error(struct be_adapter *adapter) { - return adapter->eeh_error || adapter->hw_error || adapter->fw_timeout; -} - -static inline bool be_crit_error(struct be_adapter *adapter) -{ - return adapter->eeh_error || adapter->hw_error; -} - -static inline void be_clear_all_error(struct be_adapter *adapter) -{ - adapter->eeh_error = false; - adapter->hw_error = false; - adapter->fw_timeout = false; + return adapter->eeh_err || adapter->ue_detected || adapter->fw_timeout; } static inline bool be_is_wol_excluded(struct be_adapter *adapter) diff --git a/trunk/drivers/net/ethernet/emulex/benet/be_cmds.c b/trunk/drivers/net/ethernet/emulex/benet/be_cmds.c index ddfca658559d..5eab791b7162 100644 --- a/trunk/drivers/net/ethernet/emulex/benet/be_cmds.c +++ b/trunk/drivers/net/ethernet/emulex/benet/be_cmds.c @@ -19,6 +19,9 @@ #include "be.h" #include "be_cmds.h" +/* Must be a power of 2 or else MODULO will BUG_ON */ +static int be_get_temp_freq = 64; + static inline void *embedded_payload(struct be_mcc_wrb *wrb) { return wrb->payload.embedded_payload; @@ -112,7 +115,7 @@ static int be_mcc_compl_process(struct be_adapter *adapter, } } else { if (opcode == OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES) - adapter->be_get_temp_freq = 0; + be_get_temp_freq = 0; if (compl_status == MCC_STATUS_NOT_SUPPORTED || compl_status == MCC_STATUS_ILLEGAL_REQUEST) @@ -349,7 +352,7 @@ static int be_mbox_db_ready_wait(struct be_adapter *adapter, void __iomem *db) if (msecs > 4000) { dev_err(&adapter->pdev->dev, "FW not responding\n"); adapter->fw_timeout = true; - be_detect_error(adapter); + be_detect_dump_ue(adapter); return -1; } @@ -426,65 +429,12 @@ static int be_POST_stage_get(struct be_adapter *adapter, u16 *stage) return 0; } -int lancer_wait_ready(struct be_adapter *adapter) -{ -#define SLIPORT_READY_TIMEOUT 30 - u32 sliport_status; - int status = 0, i; - - for (i = 0; i < SLIPORT_READY_TIMEOUT; i++) { - sliport_status = ioread32(adapter->db + SLIPORT_STATUS_OFFSET); - if (sliport_status & SLIPORT_STATUS_RDY_MASK) - break; - - msleep(1000); - } - - if (i == SLIPORT_READY_TIMEOUT) - status = -1; - - return status; -} - -int lancer_test_and_set_rdy_state(struct be_adapter *adapter) -{ - int status; - u32 sliport_status, err, reset_needed; - status = lancer_wait_ready(adapter); - if (!status) { - sliport_status = ioread32(adapter->db + SLIPORT_STATUS_OFFSET); - err = sliport_status & SLIPORT_STATUS_ERR_MASK; - reset_needed = sliport_status & SLIPORT_STATUS_RN_MASK; - if (err && reset_needed) { - iowrite32(SLI_PORT_CONTROL_IP_MASK, - adapter->db + SLIPORT_CONTROL_OFFSET); - - /* check adapter has corrected the error */ - status = lancer_wait_ready(adapter); - sliport_status = ioread32(adapter->db + - SLIPORT_STATUS_OFFSET); - sliport_status &= (SLIPORT_STATUS_ERR_MASK | - SLIPORT_STATUS_RN_MASK); - if (status || sliport_status) - status = -1; - } else if (err || reset_needed) { - status = -1; - } - } - return status; -} - -int be_fw_wait_ready(struct be_adapter *adapter) +int be_cmd_POST(struct be_adapter *adapter) { u16 stage; int status, timeout = 0; struct device *dev = &adapter->pdev->dev; - if (lancer_chip(adapter)) { - status = lancer_wait_ready(adapter); - return status; - } - do { status = be_POST_stage_get(adapter, &stage); if (status) { @@ -615,9 +565,6 @@ int be_cmd_fw_init(struct be_adapter *adapter) u8 *wrb; int status; - if (lancer_chip(adapter)) - return 0; - if (mutex_lock_interruptible(&adapter->mbox_lock)) return -1; @@ -645,9 +592,6 @@ int be_cmd_fw_clean(struct be_adapter *adapter) u8 *wrb; int status; - if (lancer_chip(adapter)) - return 0; - if (mutex_lock_interruptible(&adapter->mbox_lock)) return -1; @@ -666,7 +610,6 @@ int be_cmd_fw_clean(struct be_adapter *adapter) mutex_unlock(&adapter->mbox_lock); return status; } - int be_cmd_eq_create(struct be_adapter *adapter, struct be_queue_info *eq, int eq_delay) { @@ -1263,6 +1206,9 @@ int be_cmd_get_stats(struct be_adapter *adapter, struct be_dma_mem *nonemb_cmd) struct be_cmd_req_hdr *hdr; int status = 0; + if (MODULO(adapter->work_counter, be_get_temp_freq) == 0) + be_cmd_get_die_temperature(adapter); + spin_lock_bh(&adapter->mcc_lock); wrb = wrb_from_mccq(adapter); @@ -1742,20 +1688,6 @@ int be_cmd_reset_function(struct be_adapter *adapter) struct be_cmd_req_hdr *req; int status; - if (lancer_chip(adapter)) { - status = lancer_wait_ready(adapter); - if (!status) { - iowrite32(SLI_PORT_CONTROL_IP_MASK, - adapter->db + SLIPORT_CONTROL_OFFSET); - status = lancer_test_and_set_rdy_state(adapter); - } - if (status) { - dev_err(&adapter->pdev->dev, - "Adapter in non recoverable error\n"); - } - return status; - } - if (mutex_lock_interruptible(&adapter->mbox_lock)) return -1; @@ -1792,13 +1724,6 @@ int be_cmd_rss_config(struct be_adapter *adapter, u8 *rsstable, u16 table_size) req->if_id = cpu_to_le32(adapter->if_handle); req->enable_rss = cpu_to_le16(RSS_ENABLE_TCP_IPV4 | RSS_ENABLE_IPV4 | RSS_ENABLE_TCP_IPV6 | RSS_ENABLE_IPV6); - - if (lancer_chip(adapter) || skyhawk_chip(adapter)) { - req->hdr.version = 1; - req->enable_rss |= cpu_to_le16(RSS_ENABLE_UDP_IPV4 | - RSS_ENABLE_UDP_IPV6); - } - req->cpu_table_size_log2 = cpu_to_le16(fls(table_size) - 1); memcpy(req->cpu_table, rsstable, table_size); memcpy(req->hash, myhash, sizeof(myhash)); @@ -1876,9 +1801,8 @@ int be_cmd_get_beacon_state(struct be_adapter *adapter, u8 port_num, u32 *state) } int lancer_cmd_write_object(struct be_adapter *adapter, struct be_dma_mem *cmd, - u32 data_size, u32 data_offset, - const char *obj_name, u32 *data_written, - u8 *change_status, u8 *addn_status) + u32 data_size, u32 data_offset, const char *obj_name, + u32 *data_written, u8 *addn_status) { struct be_mcc_wrb *wrb; struct lancer_cmd_req_write_object *req; @@ -1934,12 +1858,10 @@ int lancer_cmd_write_object(struct be_adapter *adapter, struct be_dma_mem *cmd, status = adapter->flash_status; resp = embedded_payload(wrb); - if (!status) { + if (!status) *data_written = le32_to_cpu(resp->actual_write_len); - *change_status = resp->change_status; - } else { + else *addn_status = resp->additional_status; - } return status; @@ -2723,44 +2645,6 @@ int be_cmd_set_ext_fat_capabilites(struct be_adapter *adapter, return status; } -int be_cmd_query_port_name(struct be_adapter *adapter, u8 *port_name) -{ - struct be_mcc_wrb *wrb; - struct be_cmd_req_get_port_name *req; - int status; - - if (!lancer_chip(adapter)) { - *port_name = adapter->hba_port_num + '0'; - return 0; - } - - spin_lock_bh(&adapter->mcc_lock); - - wrb = wrb_from_mccq(adapter); - if (!wrb) { - status = -EBUSY; - goto err; - } - - req = embedded_payload(wrb); - - be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, - OPCODE_COMMON_GET_PORT_NAME, sizeof(*req), wrb, - NULL); - req->hdr.version = 1; - - status = be_mcc_notify_wait(adapter); - if (!status) { - struct be_cmd_resp_get_port_name *resp = embedded_payload(wrb); - *port_name = resp->port_name[adapter->hba_port_num]; - } else { - *port_name = adapter->hba_port_num + '0'; - } -err: - spin_unlock_bh(&adapter->mcc_lock); - return status; -} - int be_roce_mcc_cmd(void *netdev_handle, void *wrb_payload, int wrb_payload_size, u16 *cmd_status, u16 *ext_status) { diff --git a/trunk/drivers/net/ethernet/emulex/benet/be_cmds.h b/trunk/drivers/net/ethernet/emulex/benet/be_cmds.h index d5a4dedf1132..3c938f55c00b 100644 --- a/trunk/drivers/net/ethernet/emulex/benet/be_cmds.h +++ b/trunk/drivers/net/ethernet/emulex/benet/be_cmds.h @@ -186,7 +186,6 @@ struct be_mcc_mailbox { #define OPCODE_COMMON_ENABLE_DISABLE_BEACON 69 #define OPCODE_COMMON_GET_BEACON_STATE 70 #define OPCODE_COMMON_READ_TRANSRECV_DATA 73 -#define OPCODE_COMMON_GET_PORT_NAME 77 #define OPCODE_COMMON_GET_PHY_DETAILS 102 #define OPCODE_COMMON_SET_DRIVER_FUNCTION_CAP 103 #define OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES 121 @@ -1082,25 +1081,13 @@ struct be_cmd_resp_query_fw_cfg { u32 function_caps; }; -/******************** RSS Config ****************************************/ -/* RSS type Input parameters used to compute RX hash - * RSS_ENABLE_IPV4 SRC IPv4, DST IPv4 - * RSS_ENABLE_TCP_IPV4 SRC IPv4, DST IPv4, TCP SRC PORT, TCP DST PORT - * RSS_ENABLE_IPV6 SRC IPv6, DST IPv6 - * RSS_ENABLE_TCP_IPV6 SRC IPv6, DST IPv6, TCP SRC PORT, TCP DST PORT - * RSS_ENABLE_UDP_IPV4 SRC IPv4, DST IPv4, UDP SRC PORT, UDP DST PORT - * RSS_ENABLE_UDP_IPV6 SRC IPv6, DST IPv6, UDP SRC PORT, UDP DST PORT - * - * When multiple RSS types are enabled, HW picks the best hash policy - * based on the type of the received packet. - */ +/******************** RSS Config *******************/ +/* RSS types */ #define RSS_ENABLE_NONE 0x0 #define RSS_ENABLE_IPV4 0x1 #define RSS_ENABLE_TCP_IPV4 0x2 #define RSS_ENABLE_IPV6 0x4 #define RSS_ENABLE_TCP_IPV6 0x8 -#define RSS_ENABLE_UDP_IPV4 0x10 -#define RSS_ENABLE_UDP_IPV6 0x20 struct be_cmd_req_rss_config { struct be_cmd_req_hdr hdr; @@ -1176,8 +1163,6 @@ struct lancer_cmd_req_write_object { u32 addr_high; }; -#define LANCER_NO_RESET_NEEDED 0x00 -#define LANCER_FW_RESET_NEEDED 0x02 struct lancer_cmd_resp_write_object { u8 opcode; u8 subsystem; @@ -1188,8 +1173,6 @@ struct lancer_cmd_resp_write_object { u32 resp_len; u32 actual_resp_len; u32 actual_write_len; - u8 change_status; - u8 rsvd3[3]; }; /************************ Lancer Read FW info **************/ @@ -1519,17 +1502,6 @@ struct be_cmd_resp_get_hsw_config { u32 rsvd; }; -/******************* get port names ***************/ -struct be_cmd_req_get_port_name { - struct be_cmd_req_hdr hdr; - u32 rsvd0; -}; - -struct be_cmd_resp_get_port_name { - struct be_cmd_req_hdr hdr; - u8 port_name[4]; -}; - /*************** HW Stats Get v1 **********************************/ #define BE_TXP_SW_SZ 48 struct be_port_rxf_stats_v1 { @@ -1684,7 +1656,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_POST(struct be_adapter *adapter); extern int be_cmd_mac_addr_query(struct be_adapter *adapter, u8 *mac_addr, u8 type, bool permanent, u32 if_handle, u32 pmac_id); extern int be_cmd_pmac_add(struct be_adapter *adapter, u8 *mac_addr, @@ -1746,11 +1718,10 @@ extern int be_cmd_write_flashrom(struct be_adapter *adapter, struct be_dma_mem *cmd, u32 flash_oper, u32 flash_opcode, u32 buf_size); extern int lancer_cmd_write_object(struct be_adapter *adapter, - struct be_dma_mem *cmd, - u32 data_size, u32 data_offset, - const char *obj_name, - u32 *data_written, u8 *change_status, - u8 *addn_status); + struct be_dma_mem *cmd, + u32 data_size, u32 data_offset, + const char *obj_name, + u32 *data_written, u8 *addn_status); int lancer_cmd_read_object(struct be_adapter *adapter, struct be_dma_mem *cmd, u32 data_size, u32 data_offset, const char *obj_name, u32 *data_read, u32 *eof, u8 *addn_status); @@ -1773,7 +1744,7 @@ extern int be_cmd_set_loopback(struct be_adapter *adapter, u8 port_num, u8 loopback_type, u8 enable); extern int be_cmd_get_phy_info(struct be_adapter *adapter); extern int be_cmd_set_qos(struct be_adapter *adapter, u32 bps, u32 domain); -extern void be_detect_error(struct be_adapter *adapter); +extern void be_detect_dump_ue(struct be_adapter *adapter); extern int be_cmd_get_die_temperature(struct be_adapter *adapter); extern int be_cmd_get_cntl_attributes(struct be_adapter *adapter); extern int be_cmd_req_native_mode(struct be_adapter *adapter); @@ -1794,7 +1765,4 @@ extern int be_cmd_get_ext_fat_capabilites(struct be_adapter *adapter, extern int be_cmd_set_ext_fat_capabilites(struct be_adapter *adapter, struct be_dma_mem *cmd, struct be_fat_conf_params *cfgs); -extern int lancer_wait_ready(struct be_adapter *adapter); -extern int lancer_test_and_set_rdy_state(struct be_adapter *adapter); -extern int be_cmd_query_port_name(struct be_adapter *adapter, u8 *port_name); diff --git a/trunk/drivers/net/ethernet/emulex/benet/be_ethtool.c b/trunk/drivers/net/ethernet/emulex/benet/be_ethtool.c index e34be1c7ae8a..63e51d476900 100644 --- a/trunk/drivers/net/ethernet/emulex/benet/be_ethtool.c +++ b/trunk/drivers/net/ethernet/emulex/benet/be_ethtool.c @@ -648,7 +648,7 @@ be_set_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *ecmd) struct be_adapter *adapter = netdev_priv(netdev); int status; - if (ecmd->autoneg != adapter->phy.fc_autoneg) + if (ecmd->autoneg != 0) return -EINVAL; adapter->tx_fc = ecmd->tx_pause; adapter->rx_fc = ecmd->rx_pause; diff --git a/trunk/drivers/net/ethernet/emulex/benet/be_hw.h b/trunk/drivers/net/ethernet/emulex/benet/be_hw.h index b755f7061dce..7c8a710eac2f 100644 --- a/trunk/drivers/net/ethernet/emulex/benet/be_hw.h +++ b/trunk/drivers/net/ethernet/emulex/benet/be_hw.h @@ -45,19 +45,18 @@ #define POST_STAGE_ARMFW_RDY 0xc000 /* FW is done with POST */ -/* Lancer SLIPORT registers */ +/* Lancer SLIPORT_CONTROL SLIPORT_STATUS registers */ #define SLIPORT_STATUS_OFFSET 0x404 #define SLIPORT_CONTROL_OFFSET 0x408 #define SLIPORT_ERROR1_OFFSET 0x40C #define SLIPORT_ERROR2_OFFSET 0x410 -#define PHYSDEV_CONTROL_OFFSET 0x414 #define SLIPORT_STATUS_ERR_MASK 0x80000000 #define SLIPORT_STATUS_RN_MASK 0x01000000 #define SLIPORT_STATUS_RDY_MASK 0x00800000 + + #define SLI_PORT_CONTROL_IP_MASK 0x08000000 -#define PHYSDEV_CONTROL_FW_RESET_MASK 0x00000002 -#define PHYSDEV_CONTROL_INP_MASK 0x40000000 /********* Memory BAR register ************/ #define PCICFG_MEMBAR_CTRL_INT_CTRL_OFFSET 0xfc diff --git a/trunk/drivers/net/ethernet/emulex/benet/be_main.c b/trunk/drivers/net/ethernet/emulex/benet/be_main.c index f18375cd75ee..2141bd784751 100644 --- a/trunk/drivers/net/ethernet/emulex/benet/be_main.c +++ b/trunk/drivers/net/ethernet/emulex/benet/be_main.c @@ -155,7 +155,7 @@ static void be_intr_set(struct be_adapter *adapter, bool enable) { u32 reg, enabled; - if (adapter->eeh_error) + if (adapter->eeh_err) return; pci_read_config_dword(adapter->pdev, PCICFG_MEMBAR_CTRL_INT_CTRL_OFFSET, @@ -201,7 +201,7 @@ static void be_eq_notify(struct be_adapter *adapter, u16 qid, val |= ((qid & DB_EQ_RING_ID_EXT_MASK) << DB_EQ_RING_ID_EXT_MASK_SHIFT); - if (adapter->eeh_error) + if (adapter->eeh_err) return; if (arm) @@ -220,7 +220,7 @@ void be_cq_notify(struct be_adapter *adapter, u16 qid, bool arm, u16 num_popped) val |= ((qid & DB_CQ_RING_ID_EXT_MASK) << DB_CQ_RING_ID_EXT_MASK_SHIFT); - if (adapter->eeh_error) + if (adapter->eeh_err) return; if (arm) @@ -1228,16 +1228,16 @@ static void skb_fill_rx_data(struct be_rx_obj *rxo, struct sk_buff *skb, /* Copy data in the first descriptor of this completion */ curr_frag_len = min(rxcp->pkt_size, rx_frag_size); + /* Copy the header portion into skb_data */ + hdr_len = min(BE_HDR_LEN, curr_frag_len); + memcpy(skb->data, start, hdr_len); skb->len = curr_frag_len; if (curr_frag_len <= BE_HDR_LEN) { /* tiny packet */ - memcpy(skb->data, start, curr_frag_len); /* Complete packet has now been moved to data */ put_page(page_info->page); skb->data_len = 0; skb->tail += curr_frag_len; } else { - hdr_len = ETH_HLEN; - memcpy(skb->data, start, hdr_len); skb_shinfo(skb)->nr_frags = 1; skb_frag_set_page(skb, 0, page_info->page); skb_shinfo(skb)->frags[0].page_offset = @@ -1734,10 +1734,9 @@ static void be_evt_queues_destroy(struct be_adapter *adapter) int i; for_all_evt_queues(adapter, eqo, i) { - if (eqo->q.created) { - be_eq_clean(eqo); + be_eq_clean(eqo); + if (eqo->q.created) be_cmd_q_destroy(adapter, &eqo->q, QTYPE_EQ); - } be_queue_free(adapter, &eqo->q); } } @@ -2099,13 +2098,13 @@ int be_poll(struct napi_struct *napi, int budget) return max_work; } -void be_detect_error(struct be_adapter *adapter) +void be_detect_dump_ue(struct be_adapter *adapter) { u32 ue_lo = 0, ue_hi = 0, ue_lo_mask = 0, ue_hi_mask = 0; u32 sliport_status = 0, sliport_err1 = 0, sliport_err2 = 0; u32 i; - if (be_crit_error(adapter)) + if (adapter->eeh_err || adapter->ue_detected) return; if (lancer_chip(adapter)) { @@ -2126,24 +2125,16 @@ void be_detect_error(struct be_adapter *adapter) pci_read_config_dword(adapter->pdev, PCICFG_UE_STATUS_HI_MASK, &ue_hi_mask); - ue_lo = (ue_lo & ~ue_lo_mask); - ue_hi = (ue_hi & ~ue_hi_mask); + ue_lo = (ue_lo & (~ue_lo_mask)); + ue_hi = (ue_hi & (~ue_hi_mask)); } if (ue_lo || ue_hi || sliport_status & SLIPORT_STATUS_ERR_MASK) { - adapter->hw_error = true; - dev_err(&adapter->pdev->dev, - "Error detected in the card\n"); - } - - if (sliport_status & SLIPORT_STATUS_ERR_MASK) { - dev_err(&adapter->pdev->dev, - "ERR: sliport status 0x%x\n", sliport_status); - dev_err(&adapter->pdev->dev, - "ERR: sliport error1 0x%x\n", sliport_err1); + adapter->ue_detected = true; + adapter->eeh_err = true; dev_err(&adapter->pdev->dev, - "ERR: sliport error2 0x%x\n", sliport_err2); + "Unrecoverable error in the card\n"); } if (ue_lo) { @@ -2153,7 +2144,6 @@ void be_detect_error(struct be_adapter *adapter) "UE: %s bit set\n", ue_status_low_desc[i]); } } - if (ue_hi) { for (i = 0; ue_hi; ue_hi >>= 1, i++) { if (ue_hi & 1) @@ -2162,6 +2152,14 @@ void be_detect_error(struct be_adapter *adapter) } } + if (sliport_status & SLIPORT_STATUS_ERR_MASK) { + dev_err(&adapter->pdev->dev, + "sliport status 0x%x\n", sliport_status); + dev_err(&adapter->pdev->dev, + "sliport error1 0x%x\n", sliport_err1); + dev_err(&adapter->pdev->dev, + "sliport error2 0x%x\n", sliport_err2); + } } static void be_msix_disable(struct be_adapter *adapter) @@ -2575,6 +2573,9 @@ static int be_clear(struct be_adapter *adapter) be_tx_queues_destroy(adapter); be_evt_queues_destroy(adapter); + /* tell fw we're done with firing cmds */ + be_cmd_fw_clean(adapter); + be_msix_disable(adapter); return 0; } @@ -3069,40 +3070,6 @@ static int get_ufigen_type(struct flash_file_hdr_g2 *fhdr) return 0; } -static int lancer_wait_idle(struct be_adapter *adapter) -{ -#define SLIPORT_IDLE_TIMEOUT 30 - u32 reg_val; - int status = 0, i; - - for (i = 0; i < SLIPORT_IDLE_TIMEOUT; i++) { - reg_val = ioread32(adapter->db + PHYSDEV_CONTROL_OFFSET); - if ((reg_val & PHYSDEV_CONTROL_INP_MASK) == 0) - break; - - ssleep(1); - } - - if (i == SLIPORT_IDLE_TIMEOUT) - status = -1; - - return status; -} - -static int lancer_fw_reset(struct be_adapter *adapter) -{ - int status = 0; - - status = lancer_wait_idle(adapter); - if (status) - return status; - - iowrite32(PHYSDEV_CONTROL_FW_RESET_MASK, adapter->db + - PHYSDEV_CONTROL_OFFSET); - - return status; -} - static int lancer_fw_download(struct be_adapter *adapter, const struct firmware *fw) { @@ -3117,7 +3084,6 @@ static int lancer_fw_download(struct be_adapter *adapter, u32 offset = 0; int status = 0; u8 add_status = 0; - u8 change_status; if (!IS_ALIGNED(fw->size, sizeof(u32))) { dev_err(&adapter->pdev->dev, @@ -3150,10 +3116,9 @@ static int lancer_fw_download(struct be_adapter *adapter, memcpy(dest_image_ptr, data_ptr, chunk_size); status = lancer_cmd_write_object(adapter, &flash_cmd, - chunk_size, offset, - LANCER_FW_DOWNLOAD_LOCATION, - &data_written, &change_status, - &add_status); + chunk_size, offset, LANCER_FW_DOWNLOAD_LOCATION, + &data_written, &add_status); + if (status) break; @@ -3165,10 +3130,8 @@ static int lancer_fw_download(struct be_adapter *adapter, if (!status) { /* Commit the FW written */ status = lancer_cmd_write_object(adapter, &flash_cmd, - 0, offset, - LANCER_FW_DOWNLOAD_LOCATION, - &data_written, &change_status, - &add_status); + 0, offset, LANCER_FW_DOWNLOAD_LOCATION, + &data_written, &add_status); } dma_free_coherent(&adapter->pdev->dev, flash_cmd.size, flash_cmd.va, @@ -3181,20 +3144,6 @@ static int lancer_fw_download(struct be_adapter *adapter, goto lancer_fw_exit; } - if (change_status == LANCER_FW_RESET_NEEDED) { - status = lancer_fw_reset(adapter); - if (status) { - dev_err(&adapter->pdev->dev, - "Adapter busy for FW reset.\n" - "New FW will not be active.\n"); - goto lancer_fw_exit; - } - } else if (change_status != LANCER_NO_RESET_NEEDED) { - dev_err(&adapter->pdev->dev, - "System reboot required for new FW" - " to be active\n"); - } - dev_info(&adapter->pdev->dev, "Firmware flashed successfully\n"); lancer_fw_exit: return status; @@ -3523,15 +3472,10 @@ static void __devexit be_remove(struct pci_dev *pdev) be_roce_dev_remove(adapter); - cancel_delayed_work_sync(&adapter->func_recovery_work); - unregister_netdev(adapter->netdev); be_clear(adapter); - /* tell fw we're done with firing cmds */ - be_cmd_fw_clean(adapter); - be_stats_cleanup(adapter); be_ctrl_cleanup(adapter); @@ -3623,9 +3567,6 @@ static int be_get_initial_config(struct be_adapter *adapter) if (be_is_wol_supported(adapter)) adapter->wol = true; - /* Must be a power of 2 or else MODULO will BUG_ON */ - adapter->be_get_temp_freq = 64; - level = be_get_fw_log_level(adapter); adapter->msg_enable = level <= FW_LOG_LEVEL_DEFAULT ? NETIF_MSG_HW : 0; @@ -3681,68 +3622,101 @@ static int be_dev_type_check(struct be_adapter *adapter) return 0; } -static int lancer_recover_func(struct be_adapter *adapter) +static int lancer_wait_ready(struct be_adapter *adapter) { - int status; - - status = lancer_test_and_set_rdy_state(adapter); - if (status) - goto err; +#define SLIPORT_READY_TIMEOUT 30 + u32 sliport_status; + int status = 0, i; - if (netif_running(adapter->netdev)) - be_close(adapter->netdev); + for (i = 0; i < SLIPORT_READY_TIMEOUT; i++) { + sliport_status = ioread32(adapter->db + SLIPORT_STATUS_OFFSET); + if (sliport_status & SLIPORT_STATUS_RDY_MASK) + break; - be_clear(adapter); + msleep(1000); + } - adapter->hw_error = false; - adapter->fw_timeout = false; + if (i == SLIPORT_READY_TIMEOUT) + status = -1; - status = be_setup(adapter); - if (status) - goto err; + return status; +} - if (netif_running(adapter->netdev)) { - status = be_open(adapter->netdev); - if (status) - goto err; +static int lancer_test_and_set_rdy_state(struct be_adapter *adapter) +{ + int status; + u32 sliport_status, err, reset_needed; + status = lancer_wait_ready(adapter); + if (!status) { + sliport_status = ioread32(adapter->db + SLIPORT_STATUS_OFFSET); + err = sliport_status & SLIPORT_STATUS_ERR_MASK; + reset_needed = sliport_status & SLIPORT_STATUS_RN_MASK; + if (err && reset_needed) { + iowrite32(SLI_PORT_CONTROL_IP_MASK, + adapter->db + SLIPORT_CONTROL_OFFSET); + + /* check adapter has corrected the error */ + status = lancer_wait_ready(adapter); + sliport_status = ioread32(adapter->db + + SLIPORT_STATUS_OFFSET); + sliport_status &= (SLIPORT_STATUS_ERR_MASK | + SLIPORT_STATUS_RN_MASK); + if (status || sliport_status) + status = -1; + } else if (err || reset_needed) { + status = -1; + } } - - dev_err(&adapter->pdev->dev, - "Adapter SLIPORT recovery succeeded\n"); - return 0; -err: - dev_err(&adapter->pdev->dev, - "Adapter SLIPORT recovery failed\n"); - return status; } -static void be_func_recovery_task(struct work_struct *work) +static void lancer_test_and_recover_fn_err(struct be_adapter *adapter) { - struct be_adapter *adapter = - container_of(work, struct be_adapter, func_recovery_work.work); int status; + u32 sliport_status; - be_detect_error(adapter); + if (adapter->eeh_err || adapter->ue_detected) + return; - if (adapter->hw_error && lancer_chip(adapter)) { + sliport_status = ioread32(adapter->db + SLIPORT_STATUS_OFFSET); - if (adapter->eeh_error) - goto out; + if (sliport_status & SLIPORT_STATUS_ERR_MASK) { + dev_err(&adapter->pdev->dev, + "Adapter in error state." + "Trying to recover.\n"); + + status = lancer_test_and_set_rdy_state(adapter); + if (status) + goto err; - rtnl_lock(); netif_device_detach(adapter->netdev); - rtnl_unlock(); - status = lancer_recover_func(adapter); + if (netif_running(adapter->netdev)) + be_close(adapter->netdev); - if (!status) - netif_device_attach(adapter->netdev); - } + be_clear(adapter); -out: - schedule_delayed_work(&adapter->func_recovery_work, - msecs_to_jiffies(1000)); + adapter->fw_timeout = false; + + status = be_setup(adapter); + if (status) + goto err; + + if (netif_running(adapter->netdev)) { + status = be_open(adapter->netdev); + if (status) + goto err; + } + + netif_device_attach(adapter->netdev); + + dev_err(&adapter->pdev->dev, + "Adapter error recovery succeeded\n"); + } + return; +err: + dev_err(&adapter->pdev->dev, + "Adapter error recovery failed\n"); } static void be_worker(struct work_struct *work) @@ -3753,6 +3727,11 @@ static void be_worker(struct work_struct *work) struct be_eq_obj *eqo; int i; + if (lancer_chip(adapter)) + lancer_test_and_recover_fn_err(adapter); + + be_detect_dump_ue(adapter); + /* when interrupts are not yet enabled, just reap any pending * mcc completions */ if (!netif_running(adapter->netdev)) { @@ -3768,9 +3747,6 @@ static void be_worker(struct work_struct *work) be_cmd_get_stats(adapter, &adapter->stats_cmd); } - if (MODULO(adapter->work_counter, adapter->be_get_temp_freq) == 0) - be_cmd_get_die_temperature(adapter); - for_all_rx_queues(adapter, rxo, i) { if (rxo->rx_post_starved) { rxo->rx_post_starved = false; @@ -3797,7 +3773,6 @@ static int __devinit be_probe(struct pci_dev *pdev, int status = 0; struct be_adapter *adapter; struct net_device *netdev; - char port_name; status = pci_enable_device(pdev); if (status) @@ -3839,9 +3814,22 @@ static int __devinit be_probe(struct pci_dev *pdev, if (status) goto free_netdev; + if (lancer_chip(adapter)) { + status = lancer_wait_ready(adapter); + if (!status) { + iowrite32(SLI_PORT_CONTROL_IP_MASK, + adapter->db + SLIPORT_CONTROL_OFFSET); + status = lancer_test_and_set_rdy_state(adapter); + } + if (status) { + dev_err(&pdev->dev, "Adapter in non recoverable error\n"); + goto ctrl_clean; + } + } + /* sync up with fw's ready state */ if (be_physfn(adapter)) { - status = be_fw_wait_ready(adapter); + status = be_cmd_POST(adapter); if (status) goto ctrl_clean; } @@ -3872,7 +3860,6 @@ static int __devinit be_probe(struct pci_dev *pdev, goto stats_clean; INIT_DELAYED_WORK(&adapter->work, be_worker); - INIT_DELAYED_WORK(&adapter->func_recovery_work, be_func_recovery_task); adapter->rx_fc = adapter->tx_fc = true; status = be_setup(adapter); @@ -3886,13 +3873,8 @@ static int __devinit be_probe(struct pci_dev *pdev, be_roce_dev_add(adapter); - schedule_delayed_work(&adapter->func_recovery_work, - msecs_to_jiffies(1000)); - - be_cmd_query_port_name(adapter, &port_name); - - dev_info(&pdev->dev, "%s: %s port %c\n", netdev->name, nic_name(pdev), - port_name); + dev_info(&pdev->dev, "%s: %s port %d\n", netdev->name, nic_name(pdev), + adapter->port_num); return 0; @@ -3924,8 +3906,6 @@ static int be_suspend(struct pci_dev *pdev, pm_message_t state) if (adapter->wol) be_setup_wol(adapter, true); - cancel_delayed_work_sync(&adapter->func_recovery_work); - netif_device_detach(netdev); if (netif_running(netdev)) { rtnl_lock(); @@ -3966,9 +3946,6 @@ static int be_resume(struct pci_dev *pdev) be_open(netdev); rtnl_unlock(); } - - schedule_delayed_work(&adapter->func_recovery_work, - msecs_to_jiffies(1000)); netif_device_attach(netdev); if (adapter->wol) @@ -3988,7 +3965,6 @@ static void be_shutdown(struct pci_dev *pdev) return; cancel_delayed_work_sync(&adapter->work); - cancel_delayed_work_sync(&adapter->func_recovery_work); netif_device_detach(adapter->netdev); @@ -4008,13 +3984,9 @@ static pci_ers_result_t be_eeh_err_detected(struct pci_dev *pdev, dev_err(&adapter->pdev->dev, "EEH error detected\n"); - adapter->eeh_error = true; - - cancel_delayed_work_sync(&adapter->func_recovery_work); + adapter->eeh_err = true; - rtnl_lock(); netif_device_detach(netdev); - rtnl_unlock(); if (netif_running(netdev)) { rtnl_lock(); @@ -4042,7 +4014,9 @@ static pci_ers_result_t be_eeh_reset(struct pci_dev *pdev) int status; dev_info(&adapter->pdev->dev, "EEH reset\n"); - be_clear_all_error(adapter); + adapter->eeh_err = false; + adapter->ue_detected = false; + adapter->fw_timeout = false; status = pci_enable_device(pdev); if (status) @@ -4053,7 +4027,7 @@ static pci_ers_result_t be_eeh_reset(struct pci_dev *pdev) pci_restore_state(pdev); /* Check if card is ok and fw is ready */ - status = be_fw_wait_ready(adapter); + status = be_cmd_POST(adapter); if (status) return PCI_ERS_RESULT_DISCONNECT; @@ -4075,10 +4049,6 @@ static void be_eeh_resume(struct pci_dev *pdev) if (status) goto err; - status = be_cmd_reset_function(adapter); - if (status) - goto err; - status = be_setup(adapter); if (status) goto err; @@ -4088,9 +4058,6 @@ static void be_eeh_resume(struct pci_dev *pdev) if (status) goto err; } - - schedule_delayed_work(&adapter->func_recovery_work, - msecs_to_jiffies(1000)); netif_device_attach(netdev); return; err: diff --git a/trunk/drivers/net/ethernet/ethoc.c b/trunk/drivers/net/ethernet/ethoc.c index 94b7bfcdb24e..a38167810546 100644 --- a/trunk/drivers/net/ethernet/ethoc.c +++ b/trunk/drivers/net/ethernet/ethoc.c @@ -902,7 +902,7 @@ static const struct net_device_ops ethoc_netdev_ops = { }; /** - * ethoc_probe - initialize OpenCores ethernet MAC + * ethoc_probe() - initialize OpenCores ethernet MAC * pdev: platform device */ static int __devinit ethoc_probe(struct platform_device *pdev) @@ -1057,7 +1057,7 @@ static int __devinit ethoc_probe(struct platform_device *pdev) /* Check the MAC again for validity, if it still isn't choose and * program a random one. */ if (!is_valid_ether_addr(netdev->dev_addr)) { - eth_random_addr(netdev->dev_addr); + random_ether_addr(netdev->dev_addr); random_mac = true; } @@ -1140,7 +1140,7 @@ static int __devinit ethoc_probe(struct platform_device *pdev) } /** - * ethoc_remove - shutdown OpenCores ethernet MAC + * ethoc_remove() - shutdown OpenCores ethernet MAC * @pdev: platform device */ static int __devexit ethoc_remove(struct platform_device *pdev) diff --git a/trunk/drivers/net/ethernet/freescale/fec.c b/trunk/drivers/net/ethernet/freescale/fec.c index fffd20528b5d..dafd797a6069 100644 --- a/trunk/drivers/net/ethernet/freescale/fec.c +++ b/trunk/drivers/net/ethernet/freescale/fec.c @@ -1389,8 +1389,8 @@ fec_set_mac_address(struct net_device *ndev, void *p) } #ifdef CONFIG_NET_POLL_CONTROLLER -/** - * fec_poll_controller - FEC Poll controller function +/* + * fec_poll_controller: FEC Poll controller function * @dev: The FEC network adapter * * Polled functionality used by netconsole and others in non interrupt mode diff --git a/trunk/drivers/net/ethernet/freescale/fsl_pq_mdio.c b/trunk/drivers/net/ethernet/freescale/fsl_pq_mdio.c index 9527b28d70d1..f7f0bf5d037b 100644 --- a/trunk/drivers/net/ethernet/freescale/fsl_pq_mdio.c +++ b/trunk/drivers/net/ethernet/freescale/fsl_pq_mdio.c @@ -47,9 +47,6 @@ #include "gianfar.h" #include "fsl_pq_mdio.h" -/* Number of microseconds to wait for an MII register to respond */ -#define MII_TIMEOUT 1000 - struct fsl_pq_mdio_priv { void __iomem *map; struct fsl_pq_mdio __iomem *regs; @@ -67,8 +64,6 @@ struct fsl_pq_mdio_priv { int fsl_pq_local_mdio_write(struct fsl_pq_mdio __iomem *regs, int mii_id, int regnum, u16 value) { - u32 status; - /* Set the PHY address and the register address we want to write */ out_be32(®s->miimadd, (mii_id << 8) | regnum); @@ -76,10 +71,10 @@ int fsl_pq_local_mdio_write(struct fsl_pq_mdio __iomem *regs, int mii_id, out_be32(®s->miimcon, value); /* Wait for the transaction to finish */ - status = spin_event_timeout(!(in_be32(®s->miimind) & MIIMIND_BUSY), - MII_TIMEOUT, 0); + while (in_be32(®s->miimind) & MIIMIND_BUSY) + cpu_relax(); - return status ? 0 : -ETIMEDOUT; + return 0; } /* @@ -96,7 +91,6 @@ int fsl_pq_local_mdio_read(struct fsl_pq_mdio __iomem *regs, int mii_id, int regnum) { u16 value; - u32 status; /* Set the PHY address and the register address we want to read */ out_be32(®s->miimadd, (mii_id << 8) | regnum); @@ -105,12 +99,9 @@ int fsl_pq_local_mdio_read(struct fsl_pq_mdio __iomem *regs, out_be32(®s->miimcom, 0); out_be32(®s->miimcom, MII_READ_COMMAND); - /* Wait for the transaction to finish, normally less than 100us */ - status = spin_event_timeout(!(in_be32(®s->miimind) & - (MIIMIND_NOTVALID | MIIMIND_BUSY)), - MII_TIMEOUT, 0); - if (!status) - return -ETIMEDOUT; + /* Wait for the transaction to finish */ + while (in_be32(®s->miimind) & (MIIMIND_NOTVALID | MIIMIND_BUSY)) + cpu_relax(); /* Grab the value of the register from miimstat */ value = in_be32(®s->miimstat); @@ -153,7 +144,7 @@ int fsl_pq_mdio_read(struct mii_bus *bus, int mii_id, int regnum) static int fsl_pq_mdio_reset(struct mii_bus *bus) { struct fsl_pq_mdio __iomem *regs = fsl_pq_mdio_get_regs(bus); - u32 status; + int timeout = PHY_INIT_TIMEOUT; mutex_lock(&bus->mdio_lock); @@ -164,12 +155,12 @@ static int fsl_pq_mdio_reset(struct mii_bus *bus) out_be32(®s->miimcfg, MIIMCFG_INIT_VALUE); /* Wait until the bus is free */ - status = spin_event_timeout(!(in_be32(®s->miimind) & MIIMIND_BUSY), - MII_TIMEOUT, 0); + while ((in_be32(®s->miimind) & MIIMIND_BUSY) && timeout--) + cpu_relax(); mutex_unlock(&bus->mdio_lock); - if (!status) { + if (timeout < 0) { printk(KERN_ERR "%s: The MII Bus is stuck!\n", bus->name); return -EBUSY; diff --git a/trunk/drivers/net/ethernet/freescale/gianfar.c b/trunk/drivers/net/ethernet/freescale/gianfar.c index 4605f7246687..af16f9fbc353 100644 --- a/trunk/drivers/net/ethernet/freescale/gianfar.c +++ b/trunk/drivers/net/ethernet/freescale/gianfar.c @@ -2077,9 +2077,10 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev) return NETDEV_TX_OK; } - if (skb->sk) - skb_set_owner_w(skb_new, skb->sk); - consume_skb(skb); + /* Steal sock reference for processing TX time stamps */ + swap(skb_new->sk, skb->sk); + swap(skb_new->destructor, skb->destructor); + kfree_skb(skb); skb = skb_new; } diff --git a/trunk/drivers/net/ethernet/ibm/ehea/ehea_qmr.c b/trunk/drivers/net/ethernet/ibm/ehea/ehea_qmr.c index cb66f574dc97..4fb47f14dbfe 100644 --- a/trunk/drivers/net/ethernet/ibm/ehea/ehea_qmr.c +++ b/trunk/drivers/net/ethernet/ibm/ehea/ehea_qmr.c @@ -376,7 +376,9 @@ int ehea_destroy_eq(struct ehea_eq *eq) return 0; } -/* allocates memory for a queue and registers pages in phyp */ +/** + * allocates memory for a queue and registers pages in phyp + */ static int ehea_qp_alloc_register(struct ehea_qp *qp, struct hw_queue *hw_queue, int nr_pages, int wqe_size, int act_nr_sges, struct ehea_adapter *adapter, int h_call_q_selector) diff --git a/trunk/drivers/net/ethernet/intel/e1000/e1000_hw.c b/trunk/drivers/net/ethernet/intel/e1000/e1000_hw.c index 3d6839528761..c526279e4927 100644 --- a/trunk/drivers/net/ethernet/intel/e1000/e1000_hw.c +++ b/trunk/drivers/net/ethernet/intel/e1000/e1000_hw.c @@ -399,7 +399,7 @@ void e1000_set_media_type(struct e1000_hw *hw) } /** - * e1000_reset_hw - reset the hardware completely + * e1000_reset_hw: reset the hardware completely * @hw: Struct containing variables accessed by shared code * * Reset the transmit and receive units; mask and clear all interrupts. @@ -546,7 +546,7 @@ s32 e1000_reset_hw(struct e1000_hw *hw) } /** - * e1000_init_hw - Performs basic configuration of the adapter. + * e1000_init_hw: Performs basic configuration of the adapter. * @hw: Struct containing variables accessed by shared code * * Assumes that the controller has previously been reset and is in a @@ -2591,7 +2591,7 @@ s32 e1000_check_for_link(struct e1000_hw *hw) * @hw: Struct containing variables accessed by shared code * @speed: Speed of the connection * @duplex: Duplex setting of the connection - * + * Detects the current speed and duplex settings of the hardware. */ s32 e1000_get_speed_and_duplex(struct e1000_hw *hw, u16 *speed, u16 *duplex) @@ -2959,7 +2959,7 @@ static s32 e1000_read_phy_reg_ex(struct e1000_hw *hw, u32 reg_addr, * @hw: Struct containing variables accessed by shared code * @reg_addr: address of the PHY register to write * @data: data to write to the PHY - * + * Writes a value to a PHY register */ s32 e1000_write_phy_reg(struct e1000_hw *hw, u32 reg_addr, u16 phy_data) diff --git a/trunk/drivers/net/ethernet/intel/e1000/e1000_main.c b/trunk/drivers/net/ethernet/intel/e1000/e1000_main.c index 3bfbb8df8989..183a4a3224ba 100644 --- a/trunk/drivers/net/ethernet/intel/e1000/e1000_main.c +++ b/trunk/drivers/net/ethernet/intel/e1000/e1000_main.c @@ -721,7 +721,9 @@ void e1000_reset(struct e1000_adapter *adapter) e1000_release_manageability(adapter); } -/* Dump the eeprom for users having checksum issues */ +/** + * Dump the eeprom for users having checksum issues + **/ static void e1000_dump_eeprom(struct e1000_adapter *adapter) { struct net_device *netdev = adapter->netdev; @@ -3054,13 +3056,14 @@ static void e1000_tx_queue(struct e1000_adapter *adapter, mmiowb(); } -/* 82547 workaround to avoid controller hang in half-duplex environment. +/** + * 82547 workaround to avoid controller hang in half-duplex environment. * The workaround is to avoid queuing a large packet that would span * the internal Tx FIFO ring boundary by notifying the stack to resend * the packet at a later time. This gives the Tx FIFO an opportunity to * flush all packets. When that occurs, we reset the Tx FIFO pointers * to the beginning of the Tx FIFO. - */ + **/ #define E1000_FIFO_HDR 0x10 #define E1000_82547_PAD_LEN 0x3E0 diff --git a/trunk/drivers/net/ethernet/intel/e1000e/82571.c b/trunk/drivers/net/ethernet/intel/e1000e/82571.c index 19f4cb9582b5..36db4df09aed 100644 --- a/trunk/drivers/net/ethernet/intel/e1000e/82571.c +++ b/trunk/drivers/net/ethernet/intel/e1000e/82571.c @@ -1677,18 +1677,16 @@ static s32 e1000_check_for_serdes_link_82571(struct e1000_hw *hw) e_dbg("ANYSTATE -> DOWN\n"); } else { /* - * Check several times, if SYNCH bit and CONFIG - * bit both are consistently 1 then simply ignore - * the IV bit and restart Autoneg + * Check several times, if Sync and Config + * both are consistently 1 then simply ignore + * the Invalid bit and restart Autoneg */ for (i = 0; i < AN_RETRY_COUNT; i++) { udelay(10); rxcw = er32(RXCW); - if ((rxcw & E1000_RXCW_SYNCH) && - (rxcw & E1000_RXCW_C)) - continue; - - if (rxcw & E1000_RXCW_IV) { + if ((rxcw & E1000_RXCW_IV) && + !((rxcw & E1000_RXCW_SYNCH) && + (rxcw & E1000_RXCW_C))) { mac->serdes_has_link = false; mac->serdes_link_state = e1000_serdes_link_down; diff --git a/trunk/drivers/net/ethernet/intel/e1000e/e1000.h b/trunk/drivers/net/ethernet/intel/e1000e/e1000.h index cd153326c3cf..6e6fffb34581 100644 --- a/trunk/drivers/net/ethernet/intel/e1000e/e1000.h +++ b/trunk/drivers/net/ethernet/intel/e1000e/e1000.h @@ -514,7 +514,6 @@ extern void e1000e_set_interrupt_capability(struct e1000_adapter *adapter); extern void e1000e_reset_interrupt_capability(struct e1000_adapter *adapter); extern void e1000e_get_hw_control(struct e1000_adapter *adapter); extern void e1000e_release_hw_control(struct e1000_adapter *adapter); -extern void e1000e_write_itr(struct e1000_adapter *adapter, u32 itr); extern unsigned int copybreak; diff --git a/trunk/drivers/net/ethernet/intel/e1000e/ethtool.c b/trunk/drivers/net/ethernet/intel/e1000e/ethtool.c index 105d554ea9db..905e2147d918 100644 --- a/trunk/drivers/net/ethernet/intel/e1000e/ethtool.c +++ b/trunk/drivers/net/ethernet/intel/e1000e/ethtool.c @@ -1897,6 +1897,7 @@ static int e1000_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *ec) { struct e1000_adapter *adapter = netdev_priv(netdev); + struct e1000_hw *hw = &adapter->hw; if ((ec->rx_coalesce_usecs > E1000_MAX_ITR_USECS) || ((ec->rx_coalesce_usecs > 4) && @@ -1915,9 +1916,9 @@ static int e1000_set_coalesce(struct net_device *netdev, } if (adapter->itr_setting != 0) - e1000e_write_itr(adapter, adapter->itr); + ew32(ITR, 1000000000 / (adapter->itr * 256)); else - e1000e_write_itr(adapter, 0); + ew32(ITR, 0); return 0; } diff --git a/trunk/drivers/net/ethernet/intel/e1000e/netdev.c b/trunk/drivers/net/ethernet/intel/e1000e/netdev.c index 95b245310f17..a166efc2fead 100644 --- a/trunk/drivers/net/ethernet/intel/e1000e/netdev.c +++ b/trunk/drivers/net/ethernet/intel/e1000e/netdev.c @@ -2159,7 +2159,7 @@ void e1000e_release_hw_control(struct e1000_adapter *adapter) } /** - * e1000_alloc_ring_dma - allocate memory for a ring structure + * @e1000_alloc_ring - allocate memory for a ring structure **/ static int e1000_alloc_ring_dma(struct e1000_adapter *adapter, struct e1000_ring *ring) @@ -2473,30 +2473,6 @@ static void e1000_set_itr(struct e1000_adapter *adapter) } } -/** - * e1000e_write_itr - write the ITR value to the appropriate registers - * @adapter: address of board private structure - * @itr: new ITR value to program - * - * e1000e_write_itr determines if the adapter is in MSI-X mode - * and, if so, writes the EITR registers with the ITR value. - * Otherwise, it writes the ITR value into the ITR register. - **/ -void e1000e_write_itr(struct e1000_adapter *adapter, u32 itr) -{ - struct e1000_hw *hw = &adapter->hw; - u32 new_itr = itr ? 1000000000 / (itr * 256) : 0; - - if (adapter->msix_entries) { - int vector; - - for (vector = 0; vector < adapter->num_vectors; vector++) - writel(new_itr, hw->hw_addr + E1000_EITR_82574(vector)); - } else { - ew32(ITR, new_itr); - } -} - /** * e1000_alloc_queues - Allocate memory for all rings * @adapter: board private structure to initialize @@ -3083,7 +3059,7 @@ static void e1000_configure_rx(struct e1000_adapter *adapter) /* irq moderation */ ew32(RADV, adapter->rx_abs_int_delay); if ((adapter->itr_setting != 0) && (adapter->itr != 0)) - e1000e_write_itr(adapter, adapter->itr); + ew32(ITR, 1000000000 / (adapter->itr * 256)); ctrl_ext = er32(CTRL_EXT); /* Auto-Mask interrupts upon ICR access */ @@ -3510,14 +3486,14 @@ void e1000e_reset(struct e1000_adapter *adapter) dev_info(&adapter->pdev->dev, "Interrupt Throttle Rate turned off\n"); adapter->flags2 |= FLAG2_DISABLE_AIM; - e1000e_write_itr(adapter, 0); + ew32(ITR, 0); } } else if (adapter->flags2 & FLAG2_DISABLE_AIM) { dev_info(&adapter->pdev->dev, "Interrupt Throttle Rate turned on\n"); adapter->flags2 &= ~FLAG2_DISABLE_AIM; adapter->itr = 20000; - e1000e_write_itr(adapter, adapter->itr); + ew32(ITR, 1000000000 / (adapter->itr * 256)); } } @@ -4600,7 +4576,7 @@ static void e1000_watchdog_task(struct work_struct *work) adapter->gorc - adapter->gotc) / 10000; u32 itr = goc > 0 ? (dif * 6000 / goc + 2000) : 8000; - e1000e_write_itr(adapter, itr); + ew32(ITR, 1000000000 / (itr * 256)); } /* Cause software interrupt to ensure Rx ring is cleaned */ diff --git a/trunk/drivers/net/ethernet/intel/igb/igb_main.c b/trunk/drivers/net/ethernet/intel/igb/igb_main.c index 8adeca9787ca..01ced68d3aac 100644 --- a/trunk/drivers/net/ethernet/intel/igb/igb_main.c +++ b/trunk/drivers/net/ethernet/intel/igb/igb_main.c @@ -5008,7 +5008,7 @@ static int igb_vf_configure(struct igb_adapter *adapter, int vf) unsigned int device_id; u16 thisvf_devfn; - eth_random_addr(mac_addr); + random_ether_addr(mac_addr); igb_set_vf_mac(adapter, vf, mac_addr); switch (adapter->hw.mac.type) { @@ -5417,7 +5417,7 @@ static void igb_vf_reset_event(struct igb_adapter *adapter, u32 vf) /* generate a new mac address as we were hotplug removed/added */ if (!(adapter->vf_data[vf].flags & IGB_VF_FLAG_PF_SET_MAC)) - eth_random_addr(vf_mac); + random_ether_addr(vf_mac); /* process remaining reset events */ igb_vf_reset(adapter, vf); @@ -5777,7 +5777,6 @@ static void igb_tx_hwtstamp(struct igb_q_vector *q_vector, /** * igb_clean_tx_irq - Reclaim resources after transmit completes * @q_vector: pointer to q_vector containing needed info - * * returns true if ring is completely cleaned **/ static bool igb_clean_tx_irq(struct igb_q_vector *q_vector) diff --git a/trunk/drivers/net/ethernet/intel/igbvf/netdev.c b/trunk/drivers/net/ethernet/intel/igbvf/netdev.c index 0696abfe9944..8ec74b07f940 100644 --- a/trunk/drivers/net/ethernet/intel/igbvf/netdev.c +++ b/trunk/drivers/net/ethernet/intel/igbvf/netdev.c @@ -766,7 +766,6 @@ static void igbvf_set_itr(struct igbvf_adapter *adapter) /** * igbvf_clean_tx_irq - Reclaim resources after transmit completes * @adapter: board private structure - * * returns true if ring is completely cleaned **/ static bool igbvf_clean_tx_irq(struct igbvf_ring *tx_ring) diff --git a/trunk/drivers/net/ethernet/intel/igbvf/vf.c b/trunk/drivers/net/ethernet/intel/igbvf/vf.c index eea0e10ce12f..30a6cc426037 100644 --- a/trunk/drivers/net/ethernet/intel/igbvf/vf.c +++ b/trunk/drivers/net/ethernet/intel/igbvf/vf.c @@ -283,8 +283,7 @@ static s32 e1000_set_vfta_vf(struct e1000_hw *hw, u16 vid, bool set) return err; } -/** - * e1000_rlpml_set_vf - Set the maximum receive packet length +/** e1000_rlpml_set_vf - Set the maximum receive packet length * @hw: pointer to the HW structure * @max_size: value to assign to max frame size **/ @@ -303,7 +302,7 @@ void e1000_rlpml_set_vf(struct e1000_hw *hw, u16 max_size) * e1000_rar_set_vf - set device MAC address * @hw: pointer to the HW structure * @addr: pointer to the receive address - * @index: receive address array register + * @index receive address array register **/ static void e1000_rar_set_vf(struct e1000_hw *hw, u8 * addr, u32 index) { diff --git a/trunk/drivers/net/ethernet/intel/ixgb/ixgb_main.c b/trunk/drivers/net/ethernet/intel/ixgb/ixgb_main.c index aab649f8c5f0..5fce363d810a 100644 --- a/trunk/drivers/net/ethernet/intel/ixgb/ixgb_main.c +++ b/trunk/drivers/net/ethernet/intel/ixgb/ixgb_main.c @@ -2276,9 +2276,9 @@ static void ixgb_netpoll(struct net_device *dev) #endif /** - * ixgb_io_error_detected - called when PCI error is detected - * @pdev: pointer to pci device with error - * @state: pci channel state after error + * ixgb_io_error_detected() - called when PCI error is detected + * @pdev pointer to pci device with error + * @state pci channel state after error * * This callback is called by the PCI subsystem whenever * a PCI bus error is detected. diff --git a/trunk/drivers/net/ethernet/intel/ixgbe/ixgbe.h b/trunk/drivers/net/ethernet/intel/ixgbe/ixgbe.h index 5a75a9c8b813..d1acf2451d52 100644 --- a/trunk/drivers/net/ethernet/intel/ixgbe/ixgbe.h +++ b/trunk/drivers/net/ethernet/intel/ixgbe/ixgbe.h @@ -278,10 +278,8 @@ enum ixgbe_ring_f_enum { #define MAX_TX_QUEUES IXGBE_MAX_FDIR_INDICES #endif /* IXGBE_FCOE */ struct ixgbe_ring_feature { - u16 limit; /* upper limit on feature indices */ - u16 indices; /* current value of indices */ - u16 mask; /* Mask used for feature to ring mapping */ - u16 offset; /* offset to start of feature */ + int indices; + int mask; } ____cacheline_internodealigned_in_smp; /* @@ -317,7 +315,7 @@ struct ixgbe_ring_container { ? 8 : 1) #define MAX_TX_PACKET_BUFFERS MAX_RX_PACKET_BUFFERS -/* MAX_Q_VECTORS of these are allocated, +/* MAX_MSIX_Q_VECTORS of these are allocated, * but we only use one per queue-specific vector. */ struct ixgbe_q_vector { @@ -403,11 +401,11 @@ static inline u16 ixgbe_desc_unused(struct ixgbe_ring *ring) #define NON_Q_VECTORS (OTHER_VECTOR) #define MAX_MSIX_VECTORS_82599 64 -#define MAX_Q_VECTORS_82599 64 +#define MAX_MSIX_Q_VECTORS_82599 64 #define MAX_MSIX_VECTORS_82598 18 -#define MAX_Q_VECTORS_82598 16 +#define MAX_MSIX_Q_VECTORS_82598 16 -#define MAX_Q_VECTORS MAX_Q_VECTORS_82599 +#define MAX_MSIX_Q_VECTORS MAX_MSIX_Q_VECTORS_82599 #define MAX_MSIX_COUNT MAX_MSIX_VECTORS_82599 #define MIN_MSIX_Q_VECTORS 1 @@ -498,7 +496,7 @@ struct ixgbe_adapter { u32 alloc_rx_page_failed; u32 alloc_rx_buff_failed; - struct ixgbe_q_vector *q_vector[MAX_Q_VECTORS]; + struct ixgbe_q_vector *q_vector[MAX_MSIX_Q_VECTORS]; /* DCB parameters */ struct ieee_pfc *ixgbe_ieee_pfc; @@ -509,8 +507,8 @@ struct ixgbe_adapter { u8 dcbx_cap; enum ixgbe_fc_mode last_lfc_mode; - int num_q_vectors; /* current number of q_vectors for device */ - int max_q_vectors; /* true count of q_vectors for device */ + int num_msix_vectors; + int max_msix_q_vectors; /* true count of q_vectors for device */ struct ixgbe_ring_feature ring_feature[RING_F_ARRAY_SIZE]; struct msix_entry *msix_entries; @@ -707,7 +705,6 @@ extern u8 ixgbe_fcoe_setapp(struct ixgbe_adapter *adapter, u8 up); extern int ixgbe_fcoe_get_wwn(struct net_device *netdev, u64 *wwn, int type); extern int ixgbe_fcoe_get_hbainfo(struct net_device *netdev, struct netdev_fcoe_hbainfo *info); -extern u8 ixgbe_fcoe_get_tc(struct ixgbe_adapter *adapter); #endif /* IXGBE_FCOE */ static inline struct netdev_queue *txring_txq(const struct ixgbe_ring *ring) diff --git a/trunk/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c b/trunk/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c index bb7fde45c057..77ac41feb0fe 100644 --- a/trunk/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c +++ b/trunk/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c @@ -3132,7 +3132,7 @@ s32 ixgbe_check_mac_link_generic(struct ixgbe_hw *hw, ixgbe_link_speed *speed, } /** - * ixgbe_get_wwn_prefix_generic - Get alternative WWNN/WWPN prefix from + * ixgbe_get_wwn_prefix_generic Get alternative WWNN/WWPN prefix from * the EEPROM * @hw: pointer to hardware structure * @wwnn_prefix: the alternative WWNN prefix @@ -3325,7 +3325,6 @@ void ixgbe_set_rxpba_generic(struct ixgbe_hw *hw, * ixgbe_calculate_checksum - Calculate checksum for buffer * @buffer: pointer to EEPROM * @length: size of EEPROM to calculate a checksum for - * * Calculates the checksum for some buffer on a specified length. The * checksum calculated is returned. **/ diff --git a/trunk/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb.c b/trunk/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb.c index 5442b359141e..8bfaaee5ac5b 100644 --- a/trunk/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb.c +++ b/trunk/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb.c @@ -180,79 +180,67 @@ s32 ixgbe_dcb_calculate_tc_credits(struct ixgbe_hw *hw, void ixgbe_dcb_unpack_pfc(struct ixgbe_dcb_config *cfg, u8 *pfc_en) { - struct tc_configuration *tc_config = &cfg->tc_config[0]; - int tc; + int i; - for (*pfc_en = 0, tc = 0; tc < MAX_TRAFFIC_CLASS; tc++) { - if (tc_config[tc].dcb_pfc != pfc_disabled) - *pfc_en |= 1 << tc; - } + *pfc_en = 0; + for (i = 0; i < MAX_TRAFFIC_CLASS; i++) + *pfc_en |= !!(cfg->tc_config[i].dcb_pfc & 0xF) << i; } void ixgbe_dcb_unpack_refill(struct ixgbe_dcb_config *cfg, int direction, u16 *refill) { - struct tc_configuration *tc_config = &cfg->tc_config[0]; - int tc; + struct tc_bw_alloc *p; + int i; - for (tc = 0; tc < MAX_TRAFFIC_CLASS; tc++) - refill[tc] = tc_config[tc].path[direction].data_credits_refill; + for (i = 0; i < MAX_TRAFFIC_CLASS; i++) { + p = &cfg->tc_config[i].path[direction]; + refill[i] = p->data_credits_refill; + } } void ixgbe_dcb_unpack_max(struct ixgbe_dcb_config *cfg, u16 *max) { - struct tc_configuration *tc_config = &cfg->tc_config[0]; - int tc; + int i; - for (tc = 0; tc < MAX_TRAFFIC_CLASS; tc++) - max[tc] = tc_config[tc].desc_credits_max; + for (i = 0; i < MAX_TRAFFIC_CLASS; i++) + max[i] = cfg->tc_config[i].desc_credits_max; } void ixgbe_dcb_unpack_bwgid(struct ixgbe_dcb_config *cfg, int direction, u8 *bwgid) { - struct tc_configuration *tc_config = &cfg->tc_config[0]; - int tc; + struct tc_bw_alloc *p; + int i; - for (tc = 0; tc < MAX_TRAFFIC_CLASS; tc++) - bwgid[tc] = tc_config[tc].path[direction].bwg_id; + for (i = 0; i < MAX_TRAFFIC_CLASS; i++) { + p = &cfg->tc_config[i].path[direction]; + bwgid[i] = p->bwg_id; + } } void ixgbe_dcb_unpack_prio(struct ixgbe_dcb_config *cfg, int direction, u8 *ptype) { - struct tc_configuration *tc_config = &cfg->tc_config[0]; - int tc; - - for (tc = 0; tc < MAX_TRAFFIC_CLASS; tc++) - ptype[tc] = tc_config[tc].path[direction].prio_type; -} - -u8 ixgbe_dcb_get_tc_from_up(struct ixgbe_dcb_config *cfg, int direction, u8 up) -{ - struct tc_configuration *tc_config = &cfg->tc_config[0]; - u8 prio_mask = 1 << up; - u8 tc; + struct tc_bw_alloc *p; + int i; - /* - * Test for TCs 7 through 1 and report the first match we find. If - * we find no match we can assume that the TC is 0 since the TC must - * be set for all user priorities - */ - for (tc = MAX_TRAFFIC_CLASS - 1; tc; tc--) { - if (prio_mask & tc_config[tc].path[direction].up_to_tc_bitmap) - break; + for (i = 0; i < MAX_TRAFFIC_CLASS; i++) { + p = &cfg->tc_config[i].path[direction]; + ptype[i] = p->prio_type; } - - return tc; } void ixgbe_dcb_unpack_map(struct ixgbe_dcb_config *cfg, int direction, u8 *map) { - u8 up; + int i, up; + unsigned long bitmap; - for (up = 0; up < MAX_USER_PRIORITY; up++) - map[up] = ixgbe_dcb_get_tc_from_up(cfg, direction, up); + for (i = 0; i < MAX_TRAFFIC_CLASS; i++) { + bitmap = cfg->tc_config[i].path[direction].up_to_tc_bitmap; + for_each_set_bit(up, &bitmap, MAX_USER_PRIORITY) + map[up] = i; + } } /** diff --git a/trunk/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb.h b/trunk/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb.h index 1f4108ee154b..24333b718166 100644 --- a/trunk/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb.h +++ b/trunk/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb.h @@ -146,7 +146,6 @@ void ixgbe_dcb_unpack_max(struct ixgbe_dcb_config *, u16 *); void ixgbe_dcb_unpack_bwgid(struct ixgbe_dcb_config *, int, u8 *); void ixgbe_dcb_unpack_prio(struct ixgbe_dcb_config *, int, u8 *); void ixgbe_dcb_unpack_map(struct ixgbe_dcb_config *, int, u8 *); -u8 ixgbe_dcb_get_tc_from_up(struct ixgbe_dcb_config *, int, u8); /* DCB credits calculation */ s32 ixgbe_dcb_calculate_tc_credits(struct ixgbe_hw *, diff --git a/trunk/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_nl.c b/trunk/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_nl.c index f1e002d5fa8f..5164a21b13ca 100644 --- a/trunk/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_nl.c +++ b/trunk/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_nl.c @@ -151,21 +151,34 @@ static u8 ixgbe_dcbnl_get_state(struct net_device *netdev) static u8 ixgbe_dcbnl_set_state(struct net_device *netdev, u8 state) { - struct ixgbe_adapter *adapter = netdev_priv(netdev); int err = 0; + u8 prio_tc[MAX_USER_PRIORITY] = {0}; + int i; + struct ixgbe_adapter *adapter = netdev_priv(netdev); /* Fail command if not in CEE mode */ if (!(adapter->dcbx_cap & DCB_CAP_DCBX_VER_CEE)) return 1; /* verify there is something to do, if not then exit */ - if (!state == !(adapter->flags & IXGBE_FLAG_DCB_ENABLED)) + if (!!state != !(adapter->flags & IXGBE_FLAG_DCB_ENABLED)) + goto out; + + if (state > 0) { + err = ixgbe_setup_tc(netdev, adapter->dcb_cfg.num_tcs.pg_tcs); + ixgbe_dcb_unpack_map(&adapter->dcb_cfg, DCB_TX_CONFIG, prio_tc); + } else { + err = ixgbe_setup_tc(netdev, 0); + } + + if (err) goto out; - err = ixgbe_setup_tc(netdev, - state ? adapter->dcb_cfg.num_tcs.pg_tcs : 0); + for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) + netdev_set_prio_tc_map(netdev, i, prio_tc[i]); + out: - return !!err; + return err ? 1 : 0; } static void ixgbe_dcbnl_get_perm_hw_addr(struct net_device *netdev, @@ -571,6 +584,9 @@ static int ixgbe_dcbnl_ieee_setets(struct net_device *dev, if (err) goto err_out; + for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) + netdev_set_prio_tc_map(dev, i, ets->prio_tc[i]); + err = ixgbe_dcb_hw_ets(&adapter->hw, ets, max_frame); err_out: return err; diff --git a/trunk/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c b/trunk/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c index 8e1be50af70a..bbc7da5cdb4d 100644 --- a/trunk/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c +++ b/trunk/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c @@ -2090,6 +2090,7 @@ static int ixgbe_set_coalesce(struct net_device *netdev, struct ixgbe_adapter *adapter = netdev_priv(netdev); struct ixgbe_q_vector *q_vector; int i; + int num_vectors; u16 tx_itr_param, rx_itr_param; bool need_reset = false; @@ -2125,7 +2126,12 @@ static int ixgbe_set_coalesce(struct net_device *netdev, /* check the old value and enable RSC if necessary */ need_reset = ixgbe_update_rsc(adapter); - for (i = 0; i < adapter->num_q_vectors; i++) { + if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) + num_vectors = adapter->num_msix_vectors - NON_Q_VECTORS; + else + num_vectors = 1; + + for (i = 0; i < num_vectors; i++) { q_vector = adapter->q_vector[i]; if (q_vector->tx.count && !q_vector->rx.count) /* tx only */ diff --git a/trunk/drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c b/trunk/drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c index cc28c44a048c..bc07933d67da 100644 --- a/trunk/drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c +++ b/trunk/drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c @@ -38,7 +38,7 @@ /** * ixgbe_fcoe_clear_ddp - clear the given ddp context - * @ddp: ptr to the ixgbe_fcoe_ddp + * @ddp - ptr to the ixgbe_fcoe_ddp * * Returns : none * @@ -674,7 +674,7 @@ void ixgbe_configure_fcoe(struct ixgbe_adapter *adapter) if (adapter->ring_feature[RING_F_FCOE].indices) { /* Use multiple rx queues for FCoE by redirection table */ for (i = 0; i < IXGBE_FCRETA_SIZE; i++) { - fcoe_i = f->offset + i % f->indices; + fcoe_i = f->mask + i % f->indices; fcoe_i &= IXGBE_FCRETA_ENTRY_MASK; fcoe_q = adapter->rx_ring[fcoe_i]->reg_idx; IXGBE_WRITE_REG(hw, IXGBE_FCRETA(i), fcoe_q); @@ -683,7 +683,7 @@ void ixgbe_configure_fcoe(struct ixgbe_adapter *adapter) IXGBE_WRITE_REG(hw, IXGBE_ETQS(IXGBE_ETQF_FILTER_FCOE), 0); } else { /* Use single rx queue for FCoE */ - fcoe_i = f->offset; + fcoe_i = f->mask; fcoe_q = adapter->rx_ring[fcoe_i]->reg_idx; IXGBE_WRITE_REG(hw, IXGBE_FCRECTL, 0); IXGBE_WRITE_REG(hw, IXGBE_ETQS(IXGBE_ETQF_FILTER_FCOE), @@ -691,7 +691,7 @@ void ixgbe_configure_fcoe(struct ixgbe_adapter *adapter) (fcoe_q << IXGBE_ETQS_RX_QUEUE_SHIFT)); } /* send FIP frames to the first FCoE queue */ - fcoe_i = f->offset; + fcoe_i = f->mask; fcoe_q = adapter->rx_ring[fcoe_i]->reg_idx; IXGBE_WRITE_REG(hw, IXGBE_ETQS(IXGBE_ETQF_FILTER_FIP), IXGBE_ETQS_QUEUE_EN | @@ -770,7 +770,7 @@ int ixgbe_fcoe_enable(struct net_device *netdev) ixgbe_clear_interrupt_scheme(adapter); adapter->flags |= IXGBE_FLAG_FCOE_ENABLED; - adapter->ring_feature[RING_F_FCOE].limit = IXGBE_FCRETA_SIZE; + adapter->ring_feature[RING_F_FCOE].indices = IXGBE_FCRETA_SIZE; netdev->features |= NETIF_F_FCOE_CRC; netdev->features |= NETIF_F_FSO; netdev->features |= NETIF_F_FCOE_MTU; @@ -960,18 +960,3 @@ int ixgbe_fcoe_get_hbainfo(struct net_device *netdev, return 0; } - -/** - * ixgbe_fcoe_get_tc - get the current TC that fcoe is mapped to - * @adapter - pointer to the device adapter structure - * - * Return : TC that FCoE is mapped to - */ -u8 ixgbe_fcoe_get_tc(struct ixgbe_adapter *adapter) -{ -#ifdef CONFIG_IXGBE_DCB - return netdev_get_prio_tc_map(adapter->netdev, adapter->fcoe.up); -#else - return 0; -#endif -} diff --git a/trunk/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c b/trunk/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c index d308e7140171..c377706e81a8 100644 --- a/trunk/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c +++ b/trunk/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c @@ -28,7 +28,29 @@ #include "ixgbe.h" #include "ixgbe_sriov.h" +/** + * ixgbe_cache_ring_rss - Descriptor ring to register mapping for RSS + * @adapter: board private structure to initialize + * + * Cache the descriptor ring offsets for RSS to the assigned rings. + * + **/ +static inline bool ixgbe_cache_ring_rss(struct ixgbe_adapter *adapter) +{ + int i; + + if (!(adapter->flags & IXGBE_FLAG_RSS_ENABLED)) + return false; + + for (i = 0; i < adapter->num_rx_queues; i++) + adapter->rx_ring[i]->reg_idx = i; + for (i = 0; i < adapter->num_tx_queues; i++) + adapter->tx_ring[i]->reg_idx = i; + + return true; +} #ifdef CONFIG_IXGBE_DCB + /* ixgbe_get_first_reg_idx - Return first register index associated with ring */ static void ixgbe_get_first_reg_idx(struct ixgbe_adapter *adapter, u8 tc, unsigned int *tx, unsigned int *rx) @@ -114,48 +136,84 @@ static inline bool ixgbe_cache_ring_dcb(struct ixgbe_adapter *adapter) return true; } - #endif + /** - * ixgbe_cache_ring_sriov - Descriptor ring to register mapping for sriov + * ixgbe_cache_ring_fdir - Descriptor ring to register mapping for Flow Director * @adapter: board private structure to initialize * - * SR-IOV doesn't use any descriptor rings but changes the default if - * no other mapping is used. + * Cache the descriptor ring offsets for Flow Director to the assigned rings. * - */ -static inline bool ixgbe_cache_ring_sriov(struct ixgbe_adapter *adapter) + **/ +static inline bool ixgbe_cache_ring_fdir(struct ixgbe_adapter *adapter) { - adapter->rx_ring[0]->reg_idx = adapter->num_vfs * 2; - adapter->tx_ring[0]->reg_idx = adapter->num_vfs * 2; - if (adapter->num_vfs) - return true; - else - return false; + int i; + bool ret = false; + + if ((adapter->flags & IXGBE_FLAG_RSS_ENABLED) && + (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE)) { + for (i = 0; i < adapter->num_rx_queues; i++) + adapter->rx_ring[i]->reg_idx = i; + for (i = 0; i < adapter->num_tx_queues; i++) + adapter->tx_ring[i]->reg_idx = i; + ret = true; + } + + return ret; } +#ifdef IXGBE_FCOE /** - * ixgbe_cache_ring_rss - Descriptor ring to register mapping for RSS + * ixgbe_cache_ring_fcoe - Descriptor ring to register mapping for the FCoE * @adapter: board private structure to initialize * - * Cache the descriptor ring offsets for RSS to the assigned rings. + * Cache the descriptor ring offsets for FCoE mode to the assigned rings. * - **/ -static bool ixgbe_cache_ring_rss(struct ixgbe_adapter *adapter) + */ +static inline bool ixgbe_cache_ring_fcoe(struct ixgbe_adapter *adapter) { + struct ixgbe_ring_feature *f = &adapter->ring_feature[RING_F_FCOE]; int i; + u8 fcoe_rx_i = 0, fcoe_tx_i = 0; - if (!(adapter->flags & IXGBE_FLAG_RSS_ENABLED)) + if (!(adapter->flags & IXGBE_FLAG_FCOE_ENABLED)) return false; - for (i = 0; i < adapter->num_rx_queues; i++) - adapter->rx_ring[i]->reg_idx = i; - for (i = 0; i < adapter->num_tx_queues; i++) - adapter->tx_ring[i]->reg_idx = i; + if (adapter->flags & IXGBE_FLAG_RSS_ENABLED) { + if (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE) + ixgbe_cache_ring_fdir(adapter); + else + ixgbe_cache_ring_rss(adapter); + fcoe_rx_i = f->mask; + fcoe_tx_i = f->mask; + } + for (i = 0; i < f->indices; i++, fcoe_rx_i++, fcoe_tx_i++) { + adapter->rx_ring[f->mask + i]->reg_idx = fcoe_rx_i; + adapter->tx_ring[f->mask + i]->reg_idx = fcoe_tx_i; + } return true; } +#endif /* IXGBE_FCOE */ +/** + * ixgbe_cache_ring_sriov - Descriptor ring to register mapping for sriov + * @adapter: board private structure to initialize + * + * SR-IOV doesn't use any descriptor rings but changes the default if + * no other mapping is used. + * + */ +static inline bool ixgbe_cache_ring_sriov(struct ixgbe_adapter *adapter) +{ + adapter->rx_ring[0]->reg_idx = adapter->num_vfs * 2; + adapter->tx_ring[0]->reg_idx = adapter->num_vfs * 2; + if (adapter->num_vfs) + return true; + else + return false; +} + /** * ixgbe_cache_ring_register - Descriptor ring to register mapping * @adapter: board private structure to initialize @@ -181,11 +239,20 @@ static void ixgbe_cache_ring_register(struct ixgbe_adapter *adapter) return; #endif - ixgbe_cache_ring_rss(adapter); +#ifdef IXGBE_FCOE + if (ixgbe_cache_ring_fcoe(adapter)) + return; +#endif /* IXGBE_FCOE */ + + if (ixgbe_cache_ring_fdir(adapter)) + return; + + if (ixgbe_cache_ring_rss(adapter)) + return; } /** - * ixgbe_set_sriov_queues - Allocate queues for IOV use + * ixgbe_set_sriov_queues: Allocate queues for IOV use * @adapter: board private structure to initialize * * IOV doesn't actually use anything, so just NAK the @@ -197,149 +264,153 @@ static inline bool ixgbe_set_sriov_queues(struct ixgbe_adapter *adapter) return false; } -#define IXGBE_RSS_16Q_MASK 0xF -#define IXGBE_RSS_8Q_MASK 0x7 -#define IXGBE_RSS_4Q_MASK 0x3 -#define IXGBE_RSS_2Q_MASK 0x1 -#define IXGBE_RSS_DISABLED_MASK 0x0 - -#ifdef CONFIG_IXGBE_DCB -static bool ixgbe_set_dcb_queues(struct ixgbe_adapter *adapter) +/** + * ixgbe_set_rss_queues: Allocate queues for RSS + * @adapter: board private structure to initialize + * + * This is our "base" multiqueue mode. RSS (Receive Side Scaling) will try + * to allocate one Rx queue per CPU, and if available, one Tx queue per CPU. + * + **/ +static inline bool ixgbe_set_rss_queues(struct ixgbe_adapter *adapter) { - struct net_device *dev = adapter->netdev; - struct ixgbe_ring_feature *f; - int rss_i, rss_m, i; - int tcs; - - /* Map queue offset and counts onto allocated tx queues */ - tcs = netdev_get_num_tc(dev); + bool ret = false; + struct ixgbe_ring_feature *f = &adapter->ring_feature[RING_F_RSS]; + + if (adapter->flags & IXGBE_FLAG_RSS_ENABLED) { + f->mask = 0xF; + adapter->num_rx_queues = f->indices; + adapter->num_tx_queues = f->indices; + ret = true; + } - /* verify we have DCB queueing enabled before proceeding */ - if (tcs <= 1) - return false; + return ret; +} - /* determine the upper limit for our current DCB mode */ - rss_i = dev->num_tx_queues / tcs; - if (adapter->hw.mac.type == ixgbe_mac_82598EB) { - /* 8 TC w/ 4 queues per TC */ - rss_i = min_t(u16, rss_i, 4); - rss_m = IXGBE_RSS_4Q_MASK; - } else if (tcs > 4) { - /* 8 TC w/ 8 queues per TC */ - rss_i = min_t(u16, rss_i, 8); - rss_m = IXGBE_RSS_8Q_MASK; - } else { - /* 4 TC w/ 16 queues per TC */ - rss_i = min_t(u16, rss_i, 16); - rss_m = IXGBE_RSS_16Q_MASK; - } +/** + * ixgbe_set_fdir_queues: Allocate queues for Flow Director + * @adapter: board private structure to initialize + * + * Flow Director is an advanced Rx filter, attempting to get Rx flows back + * to the original CPU that initiated the Tx session. This runs in addition + * to RSS, so if a packet doesn't match an FDIR filter, we can still spread the + * Rx load across CPUs using RSS. + * + **/ +static inline bool ixgbe_set_fdir_queues(struct ixgbe_adapter *adapter) +{ + bool ret = false; + struct ixgbe_ring_feature *f_fdir = &adapter->ring_feature[RING_F_FDIR]; - /* set RSS mask and indices */ - f = &adapter->ring_feature[RING_F_RSS]; - rss_i = min_t(int, rss_i, f->limit); - f->indices = rss_i; - f->mask = rss_m; + f_fdir->indices = min_t(int, num_online_cpus(), f_fdir->indices); + f_fdir->mask = 0; -#ifdef IXGBE_FCOE - /* FCoE enabled queues require special configuration indexed - * by feature specific indices and offset. Here we map FCoE - * indices onto the DCB queue pairs allowing FCoE to own - * configuration later. + /* + * Use RSS in addition to Flow Director to ensure the best + * distribution of flows across cores, even when an FDIR flow + * isn't matched. */ - if (adapter->flags & IXGBE_FLAG_FCOE_ENABLED) { - u8 tc = ixgbe_fcoe_get_tc(adapter); - - f = &adapter->ring_feature[RING_F_FCOE]; - f->indices = min_t(u16, rss_i, f->limit); - f->offset = rss_i * tc; + if ((adapter->flags & IXGBE_FLAG_RSS_ENABLED) && + (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE)) { + adapter->num_tx_queues = f_fdir->indices; + adapter->num_rx_queues = f_fdir->indices; + ret = true; + } else { + adapter->flags &= ~IXGBE_FLAG_FDIR_HASH_CAPABLE; } - -#endif /* IXGBE_FCOE */ - for (i = 0; i < tcs; i++) - netdev_set_tc_queue(dev, i, rss_i, rss_i * i); - - adapter->num_tx_queues = rss_i * tcs; - adapter->num_rx_queues = rss_i * tcs; - - return true; + return ret; } -#endif +#ifdef IXGBE_FCOE /** - * ixgbe_set_rss_queues - Allocate queues for RSS + * ixgbe_set_fcoe_queues: Allocate queues for Fiber Channel over Ethernet (FCoE) * @adapter: board private structure to initialize * - * This is our "base" multiqueue mode. RSS (Receive Side Scaling) will try - * to allocate one Rx queue per CPU, and if available, one Tx queue per CPU. + * FCoE RX FCRETA can use up to 8 rx queues for up to 8 different exchanges. + * The ring feature mask is not used as a mask for FCoE, as it can take any 8 + * rx queues out of the max number of rx queues, instead, it is used as the + * index of the first rx queue used by FCoE. * **/ -static bool ixgbe_set_rss_queues(struct ixgbe_adapter *adapter) +static inline bool ixgbe_set_fcoe_queues(struct ixgbe_adapter *adapter) { - struct ixgbe_ring_feature *f; - u16 rss_i; + struct ixgbe_ring_feature *f = &adapter->ring_feature[RING_F_FCOE]; - if (!(adapter->flags & IXGBE_FLAG_RSS_ENABLED)) { - adapter->flags &= ~IXGBE_FLAG_FDIR_HASH_CAPABLE; + if (!(adapter->flags & IXGBE_FLAG_FCOE_ENABLED)) return false; - } - - /* set mask for 16 queue limit of RSS */ - f = &adapter->ring_feature[RING_F_RSS]; - rss_i = f->limit; - f->indices = rss_i; - f->mask = IXGBE_RSS_16Q_MASK; + f->indices = min_t(int, num_online_cpus(), f->indices); - /* - * Use Flow Director in addition to RSS to ensure the best - * distribution of flows across cores, even when an FDIR flow - * isn't matched. - */ - if (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE) { - f = &adapter->ring_feature[RING_F_FDIR]; + adapter->num_rx_queues = 1; + adapter->num_tx_queues = 1; - f->indices = min_t(u16, num_online_cpus(), f->limit); - rss_i = max_t(u16, rss_i, f->indices); + if (adapter->flags & IXGBE_FLAG_RSS_ENABLED) { + e_info(probe, "FCoE enabled with RSS\n"); + if (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE) + ixgbe_set_fdir_queues(adapter); + else + ixgbe_set_rss_queues(adapter); } -#ifdef IXGBE_FCOE - /* - * FCoE can exist on the same rings as standard network traffic - * however it is preferred to avoid that if possible. In order - * to get the best performance we allocate as many FCoE queues - * as we can and we place them at the end of the ring array to - * avoid sharing queues with standard RSS on systems with 24 or - * more CPUs. - */ - if (adapter->flags & IXGBE_FLAG_FCOE_ENABLED) { - struct net_device *dev = adapter->netdev; - u16 fcoe_i; + /* adding FCoE rx rings to the end */ + f->mask = adapter->num_rx_queues; + adapter->num_rx_queues += f->indices; + adapter->num_tx_queues += f->indices; - f = &adapter->ring_feature[RING_F_FCOE]; + return true; +} +#endif /* IXGBE_FCOE */ - /* merge FCoE queues with RSS queues */ - fcoe_i = min_t(u16, f->limit + rss_i, num_online_cpus()); - fcoe_i = min_t(u16, fcoe_i, dev->num_tx_queues); +/* Artificial max queue cap per traffic class in DCB mode */ +#define DCB_QUEUE_CAP 8 - /* limit indices to rss_i if MSI-X is disabled */ - if (!(adapter->flags & IXGBE_FLAG_MSIX_ENABLED)) - fcoe_i = rss_i; +#ifdef CONFIG_IXGBE_DCB +static inline bool ixgbe_set_dcb_queues(struct ixgbe_adapter *adapter) +{ + int per_tc_q, q, i, offset = 0; + struct net_device *dev = adapter->netdev; + int tcs = netdev_get_num_tc(dev); + + if (!tcs) + return false; + + /* Map queue offset and counts onto allocated tx queues */ + per_tc_q = min_t(unsigned int, dev->num_tx_queues / tcs, DCB_QUEUE_CAP); + q = min_t(int, num_online_cpus(), per_tc_q); - /* attempt to reserve some queues for just FCoE */ - f->indices = min_t(u16, fcoe_i, f->limit); - f->offset = fcoe_i - f->indices; - rss_i = max_t(u16, fcoe_i, rss_i); + for (i = 0; i < tcs; i++) { + netdev_set_tc_queue(dev, i, q, offset); + offset += q; } -#endif /* IXGBE_FCOE */ - adapter->num_rx_queues = rss_i; - adapter->num_tx_queues = rss_i; + adapter->num_tx_queues = q * tcs; + adapter->num_rx_queues = q * tcs; + +#ifdef IXGBE_FCOE + /* FCoE enabled queues require special configuration indexed + * by feature specific indices and mask. Here we map FCoE + * indices onto the DCB queue pairs allowing FCoE to own + * configuration later. + */ + if (adapter->flags & IXGBE_FLAG_FCOE_ENABLED) { + u8 prio_tc[MAX_USER_PRIORITY] = {0}; + int tc; + struct ixgbe_ring_feature *f = + &adapter->ring_feature[RING_F_FCOE]; + + ixgbe_dcb_unpack_map(&adapter->dcb_cfg, DCB_TX_CONFIG, prio_tc); + tc = prio_tc[adapter->fcoe.up]; + f->indices = dev->tc_to_txq[tc].count; + f->mask = dev->tc_to_txq[tc].offset; + } +#endif return true; } +#endif /** - * ixgbe_set_num_queues - Allocate queues for device, feature dependent + * ixgbe_set_num_queues: Allocate queues for device, feature dependent * @adapter: board private structure to initialize * * This is the top level queue allocation routine. The order here is very @@ -365,6 +436,14 @@ static int ixgbe_set_num_queues(struct ixgbe_adapter *adapter) goto done; #endif +#ifdef IXGBE_FCOE + if (ixgbe_set_fcoe_queues(adapter)) + goto done; + +#endif /* IXGBE_FCOE */ + if (ixgbe_set_fdir_queues(adapter)) + goto done; + if (ixgbe_set_rss_queues(adapter)) goto done; @@ -428,8 +507,8 @@ static void ixgbe_acquire_msix_vectors(struct ixgbe_adapter *adapter, * of max_msix_q_vectors + NON_Q_VECTORS, or the number of * vectors we were allocated. */ - vectors -= NON_Q_VECTORS; - adapter->num_q_vectors = min(vectors, adapter->max_q_vectors); + adapter->num_msix_vectors = min(vectors, + adapter->max_msix_q_vectors + NON_Q_VECTORS); } } @@ -553,8 +632,8 @@ static int ixgbe_alloc_q_vector(struct ixgbe_adapter *adapter, if (adapter->netdev->features & NETIF_F_FCOE_MTU) { struct ixgbe_ring_feature *f; f = &adapter->ring_feature[RING_F_FCOE]; - if ((rxr_idx >= f->offset) && - (rxr_idx < f->offset + f->indices)) + if ((rxr_idx >= f->mask) && + (rxr_idx < f->mask + f->indices)) set_bit(__IXGBE_RX_FCOE, &ring->state); } @@ -616,7 +695,7 @@ static void ixgbe_free_q_vector(struct ixgbe_adapter *adapter, int v_idx) **/ static int ixgbe_alloc_q_vectors(struct ixgbe_adapter *adapter) { - int q_vectors = adapter->num_q_vectors; + int q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS; int rxr_remaining = adapter->num_rx_queues; int txr_remaining = adapter->num_tx_queues; int rxr_idx = 0, txr_idx = 0, v_idx = 0; @@ -660,12 +739,10 @@ static int ixgbe_alloc_q_vectors(struct ixgbe_adapter *adapter) return 0; err_out: - adapter->num_tx_queues = 0; - adapter->num_rx_queues = 0; - adapter->num_q_vectors = 0; - - while (v_idx--) + while (v_idx) { + v_idx--; ixgbe_free_q_vector(adapter, v_idx); + } return -ENOMEM; } @@ -680,13 +757,14 @@ static int ixgbe_alloc_q_vectors(struct ixgbe_adapter *adapter) **/ static void ixgbe_free_q_vectors(struct ixgbe_adapter *adapter) { - int v_idx = adapter->num_q_vectors; + int v_idx, q_vectors; - adapter->num_tx_queues = 0; - adapter->num_rx_queues = 0; - adapter->num_q_vectors = 0; + if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) + q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS; + else + q_vectors = 1; - while (v_idx--) + for (v_idx = 0; v_idx < q_vectors; v_idx++) ixgbe_free_q_vector(adapter, v_idx); } @@ -766,8 +844,6 @@ static int ixgbe_set_interrupt_capability(struct ixgbe_adapter *adapter) if (err) return err; - adapter->num_q_vectors = 1; - err = pci_enable_msi(adapter->pdev); if (!err) { adapter->flags |= IXGBE_FLAG_MSI_ENABLED; diff --git a/trunk/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/trunk/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index ee230f533ee3..5afbb37a738c 100644 --- a/trunk/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/trunk/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -516,7 +516,7 @@ static void ixgbe_get_hw_control(struct ixgbe_adapter *adapter) ctrl_ext | IXGBE_CTRL_EXT_DRV_LOAD); } -/** +/* * ixgbe_set_ivar - set the IVAR registers, mapping interrupt causes to vectors * @adapter: pointer to adapter struct * @direction: 0 for Rx, 1 for Tx, -1 for other causes @@ -993,6 +993,7 @@ static void ixgbe_update_dca(struct ixgbe_q_vector *q_vector) static void ixgbe_setup_dca(struct ixgbe_adapter *adapter) { + int num_q_vectors; int i; if (!(adapter->flags & IXGBE_FLAG_DCA_ENABLED)) @@ -1001,7 +1002,12 @@ static void ixgbe_setup_dca(struct ixgbe_adapter *adapter) /* always use CB2 mode, difference is masked in the CB driver */ IXGBE_WRITE_REG(&adapter->hw, IXGBE_DCA_CTRL, 2); - for (i = 0; i < adapter->num_q_vectors; i++) { + if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) + num_q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS; + else + num_q_vectors = 1; + + for (i = 0; i < num_q_vectors; i++) { adapter->q_vector[i]->cpu = -1; ixgbe_update_dca(adapter->q_vector[i]); } @@ -1825,9 +1831,11 @@ static bool ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector, static void ixgbe_configure_msix(struct ixgbe_adapter *adapter) { struct ixgbe_q_vector *q_vector; - int v_idx; + int q_vectors, v_idx; u32 mask; + q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS; + /* Populate MSIX to EITR Select */ if (adapter->num_vfs > 32) { u32 eitrsel = (1 << (adapter->num_vfs - 32)) - 1; @@ -1838,7 +1846,7 @@ static void ixgbe_configure_msix(struct ixgbe_adapter *adapter) * Populate the IVAR table and set the ITR values to the * corresponding register. */ - for (v_idx = 0; v_idx < adapter->num_q_vectors; v_idx++) { + for (v_idx = 0; v_idx < q_vectors; v_idx++) { struct ixgbe_ring *ring; q_vector = adapter->q_vector[v_idx]; @@ -2402,10 +2410,11 @@ int ixgbe_poll(struct napi_struct *napi, int budget) static int ixgbe_request_msix_irqs(struct ixgbe_adapter *adapter) { struct net_device *netdev = adapter->netdev; + int q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS; int vector, err; int ri = 0, ti = 0; - for (vector = 0; vector < adapter->num_q_vectors; vector++) { + for (vector = 0; vector < q_vectors; vector++) { struct ixgbe_q_vector *q_vector = adapter->q_vector[vector]; struct msix_entry *entry = &adapter->msix_entries[vector]; @@ -2560,28 +2569,30 @@ static int ixgbe_request_irq(struct ixgbe_adapter *adapter) static void ixgbe_free_irq(struct ixgbe_adapter *adapter) { - int vector; - - if (!(adapter->flags & IXGBE_FLAG_MSIX_ENABLED)) { - free_irq(adapter->pdev->irq, adapter); - return; - } + if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) { + int i, q_vectors; - for (vector = 0; vector < adapter->num_q_vectors; vector++) { - struct ixgbe_q_vector *q_vector = adapter->q_vector[vector]; - struct msix_entry *entry = &adapter->msix_entries[vector]; + q_vectors = adapter->num_msix_vectors; + i = q_vectors - 1; + free_irq(adapter->msix_entries[i].vector, adapter); + i--; - /* free only the irqs that were actually requested */ - if (!q_vector->rx.ring && !q_vector->tx.ring) - continue; + for (; i >= 0; i--) { + /* free only the irqs that were actually requested */ + if (!adapter->q_vector[i]->rx.ring && + !adapter->q_vector[i]->tx.ring) + continue; - /* clear the affinity_mask in the IRQ descriptor */ - irq_set_affinity_hint(entry->vector, NULL); + /* clear the affinity_mask in the IRQ descriptor */ + irq_set_affinity_hint(adapter->msix_entries[i].vector, + NULL); - free_irq(entry->vector, q_vector); + free_irq(adapter->msix_entries[i].vector, + adapter->q_vector[i]); + } + } else { + free_irq(adapter->pdev->irq, adapter); } - - free_irq(adapter->msix_entries[vector++].vector, adapter); } /** @@ -2605,12 +2616,9 @@ static inline void ixgbe_irq_disable(struct ixgbe_adapter *adapter) } IXGBE_WRITE_FLUSH(&adapter->hw); if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) { - int vector; - - for (vector = 0; vector < adapter->num_q_vectors; vector++) - synchronize_irq(adapter->msix_entries[vector].vector); - - synchronize_irq(adapter->msix_entries[vector++].vector); + int i; + for (i = 0; i < adapter->num_msix_vectors; i++) + synchronize_irq(adapter->msix_entries[i].vector); } else { synchronize_irq(adapter->pdev->irq); } @@ -2847,34 +2855,40 @@ static void ixgbe_set_rx_drop_en(struct ixgbe_adapter *adapter) static void ixgbe_configure_srrctl(struct ixgbe_adapter *adapter, struct ixgbe_ring *rx_ring) { - struct ixgbe_hw *hw = &adapter->hw; u32 srrctl; u8 reg_idx = rx_ring->reg_idx; - if (hw->mac.type == ixgbe_mac_82598EB) { - u16 mask = adapter->ring_feature[RING_F_RSS].mask; - - /* - * if VMDq is not active we must program one srrctl register - * per RSS queue since we have enabled RDRXCTL.MVMEN - */ - reg_idx &= mask; + switch (adapter->hw.mac.type) { + case ixgbe_mac_82598EB: { + struct ixgbe_ring_feature *feature = adapter->ring_feature; + const int mask = feature[RING_F_RSS].mask; + reg_idx = reg_idx & mask; + } + break; + case ixgbe_mac_82599EB: + case ixgbe_mac_X540: + default: + break; } - /* configure header buffer length, needed for RSC */ - srrctl = IXGBE_RX_HDR_SIZE << IXGBE_SRRCTL_BSIZEHDRSIZE_SHIFT; + srrctl = IXGBE_READ_REG(&adapter->hw, IXGBE_SRRCTL(reg_idx)); + + srrctl &= ~IXGBE_SRRCTL_BSIZEHDR_MASK; + srrctl &= ~IXGBE_SRRCTL_BSIZEPKT_MASK; + if (adapter->num_vfs) + srrctl |= IXGBE_SRRCTL_DROP_EN; + + srrctl |= (IXGBE_RX_HDR_SIZE << IXGBE_SRRCTL_BSIZEHDRSIZE_SHIFT) & + IXGBE_SRRCTL_BSIZEHDR_MASK; - /* configure the packet buffer length */ #if PAGE_SIZE > IXGBE_MAX_RXBUFFER srrctl |= IXGBE_MAX_RXBUFFER >> IXGBE_SRRCTL_BSIZEPKT_SHIFT; #else srrctl |= ixgbe_rx_bufsz(rx_ring) >> IXGBE_SRRCTL_BSIZEPKT_SHIFT; #endif - - /* configure descriptor type */ srrctl |= IXGBE_SRRCTL_DESCTYPE_ADV_ONEBUF; - IXGBE_WRITE_REG(hw, IXGBE_SRRCTL(reg_idx), srrctl); + IXGBE_WRITE_REG(&adapter->hw, IXGBE_SRRCTL(reg_idx), srrctl); } static void ixgbe_setup_mrqc(struct ixgbe_adapter *adapter) @@ -3547,21 +3561,37 @@ void ixgbe_set_rx_mode(struct net_device *netdev) static void ixgbe_napi_enable_all(struct ixgbe_adapter *adapter) { int q_idx; + struct ixgbe_q_vector *q_vector; + int q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS; - for (q_idx = 0; q_idx < adapter->num_q_vectors; q_idx++) - napi_enable(&adapter->q_vector[q_idx]->napi); + /* legacy and MSI only use one vector */ + if (!(adapter->flags & IXGBE_FLAG_MSIX_ENABLED)) + q_vectors = 1; + + for (q_idx = 0; q_idx < q_vectors; q_idx++) { + q_vector = adapter->q_vector[q_idx]; + napi_enable(&q_vector->napi); + } } static void ixgbe_napi_disable_all(struct ixgbe_adapter *adapter) { int q_idx; + struct ixgbe_q_vector *q_vector; + int q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS; + + /* legacy and MSI only use one vector */ + if (!(adapter->flags & IXGBE_FLAG_MSIX_ENABLED)) + q_vectors = 1; - for (q_idx = 0; q_idx < adapter->num_q_vectors; q_idx++) - napi_disable(&adapter->q_vector[q_idx]->napi); + for (q_idx = 0; q_idx < q_vectors; q_idx++) { + q_vector = adapter->q_vector[q_idx]; + napi_disable(&q_vector->napi); + } } #ifdef CONFIG_IXGBE_DCB -/** +/* * ixgbe_configure_dcb - Configure DCB hardware * @adapter: ixgbe adapter struct * @@ -3610,17 +3640,16 @@ static void ixgbe_configure_dcb(struct ixgbe_adapter *adapter) if (hw->mac.type != ixgbe_mac_82598EB) { int i; u32 reg = 0; - u8 msb = 0; - u8 rss_i = adapter->netdev->tc_to_txq[0].count - 1; - while (rss_i) { - msb++; - rss_i >>= 1; - } + for (i = 0; i < MAX_TRAFFIC_CLASS; i++) { + u8 msb = 0; + u8 cnt = adapter->netdev->tc_to_txq[i].count; - for (i = 0; i < MAX_TRAFFIC_CLASS; i++) - reg |= msb << IXGBE_RQTC_SHIFT_TC(i); + while (cnt >>= 1) + msb++; + reg |= msb << IXGBE_RQTC_SHIFT_TC(i); + } IXGBE_WRITE_REG(hw, IXGBE_RQTC, reg); } } @@ -3629,11 +3658,11 @@ static void ixgbe_configure_dcb(struct ixgbe_adapter *adapter) /* Additional bittime to account for IXGBE framing */ #define IXGBE_ETH_FRAMING 20 -/** +/* * ixgbe_hpbthresh - calculate high water mark for flow control * * @adapter: board private structure to calculate for - * @pb: packet buffer to calculate + * @pb - packet buffer to calculate */ static int ixgbe_hpbthresh(struct ixgbe_adapter *adapter, int pb) { @@ -3647,12 +3676,18 @@ static int ixgbe_hpbthresh(struct ixgbe_adapter *adapter, int pb) #ifdef IXGBE_FCOE /* FCoE traffic class uses FCOE jumbo frames */ - if ((dev->features & NETIF_F_FCOE_MTU) && - (tc < IXGBE_FCOE_JUMBO_FRAME_SIZE) && - (pb == ixgbe_fcoe_get_tc(adapter))) - tc = IXGBE_FCOE_JUMBO_FRAME_SIZE; + if (dev->features & NETIF_F_FCOE_MTU) { + int fcoe_pb = 0; +#ifdef CONFIG_IXGBE_DCB + fcoe_pb = netdev_get_prio_tc_map(dev, adapter->fcoe.up); + +#endif + if (fcoe_pb == pb && tc < IXGBE_FCOE_JUMBO_FRAME_SIZE) + tc = IXGBE_FCOE_JUMBO_FRAME_SIZE; + } #endif + /* Calculate delay value for device */ switch (hw->mac.type) { case ixgbe_mac_X540: @@ -3687,11 +3722,11 @@ static int ixgbe_hpbthresh(struct ixgbe_adapter *adapter, int pb) return marker; } -/** +/* * ixgbe_lpbthresh - calculate low water mark for for flow control * * @adapter: board private structure to calculate for - * @pb: packet buffer to calculate + * @pb - packet buffer to calculate */ static int ixgbe_lpbthresh(struct ixgbe_adapter *adapter) { @@ -4375,18 +4410,18 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter) /* Set capability flags */ rss = min_t(int, IXGBE_MAX_RSS_INDICES, num_online_cpus()); - adapter->ring_feature[RING_F_RSS].limit = rss; + adapter->ring_feature[RING_F_RSS].indices = rss; adapter->flags |= IXGBE_FLAG_RSS_ENABLED; switch (hw->mac.type) { case ixgbe_mac_82598EB: if (hw->device_id == IXGBE_DEV_ID_82598AT) adapter->flags |= IXGBE_FLAG_FAN_FAIL_CAPABLE; - adapter->max_q_vectors = MAX_Q_VECTORS_82598; + adapter->max_msix_q_vectors = MAX_MSIX_Q_VECTORS_82598; break; case ixgbe_mac_X540: adapter->flags2 |= IXGBE_FLAG2_TEMP_SENSOR_CAPABLE; case ixgbe_mac_82599EB: - adapter->max_q_vectors = MAX_Q_VECTORS_82599; + adapter->max_msix_q_vectors = MAX_MSIX_Q_VECTORS_82599; adapter->flags2 |= IXGBE_FLAG2_RSC_CAPABLE; adapter->flags2 |= IXGBE_FLAG2_RSC_ENABLED; if (hw->device_id == IXGBE_DEV_ID_82599_T3_LOM) @@ -4394,12 +4429,13 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter) /* Flow Director hash filters enabled */ adapter->flags |= IXGBE_FLAG_FDIR_HASH_CAPABLE; adapter->atr_sample_rate = 20; - adapter->ring_feature[RING_F_FDIR].limit = + adapter->ring_feature[RING_F_FDIR].indices = IXGBE_MAX_FDIR_INDICES; adapter->fdir_pballoc = IXGBE_FDIR_PBALLOC_64K; #ifdef IXGBE_FCOE adapter->flags |= IXGBE_FLAG_FCOE_CAPABLE; adapter->flags &= ~IXGBE_FLAG_FCOE_ENABLED; + adapter->ring_feature[RING_F_FCOE].indices = 0; #ifdef CONFIG_IXGBE_DCB /* Default traffic class to use for FCoE */ adapter->fcoe.up = IXGBE_FCOE_DEFTC; @@ -5207,7 +5243,7 @@ void ixgbe_update_stats(struct ixgbe_adapter *adapter) /** * ixgbe_fdir_reinit_subtask - worker thread to reinit FDIR filter table - * @adapter: pointer to the device adapter structure + * @adapter - pointer to the device adapter structure **/ static void ixgbe_fdir_reinit_subtask(struct ixgbe_adapter *adapter) { @@ -5243,7 +5279,7 @@ static void ixgbe_fdir_reinit_subtask(struct ixgbe_adapter *adapter) /** * ixgbe_check_hang_subtask - check for hung queues and dropped interrupts - * @adapter: pointer to the device adapter structure + * @adapter - pointer to the device adapter structure * * This function serves two purposes. First it strobes the interrupt lines * in order to make certain interrupts are occurring. Secondly it sets the @@ -5277,7 +5313,7 @@ static void ixgbe_check_hang_subtask(struct ixgbe_adapter *adapter) (IXGBE_EICS_TCP_TIMER | IXGBE_EICS_OTHER)); } else { /* get one bit for every active tx/rx interrupt vector */ - for (i = 0; i < adapter->num_q_vectors; i++) { + for (i = 0; i < adapter->num_msix_vectors - NON_Q_VECTORS; i++) { struct ixgbe_q_vector *qv = adapter->q_vector[i]; if (qv->rx.ring || qv->tx.ring) eics |= ((u64)1 << i); @@ -5291,8 +5327,8 @@ static void ixgbe_check_hang_subtask(struct ixgbe_adapter *adapter) /** * ixgbe_watchdog_update_link - update the link status - * @adapter: pointer to the device adapter structure - * @link_speed: pointer to a u32 to store the link_speed + * @adapter - pointer to the device adapter structure + * @link_speed - pointer to a u32 to store the link_speed **/ static void ixgbe_watchdog_update_link(struct ixgbe_adapter *adapter) { @@ -5335,7 +5371,7 @@ static void ixgbe_watchdog_update_link(struct ixgbe_adapter *adapter) /** * ixgbe_watchdog_link_is_up - update netif_carrier status and * print link up message - * @adapter: pointer to the device adapter structure + * @adapter - pointer to the device adapter structure **/ static void ixgbe_watchdog_link_is_up(struct ixgbe_adapter *adapter) { @@ -5395,7 +5431,7 @@ static void ixgbe_watchdog_link_is_up(struct ixgbe_adapter *adapter) /** * ixgbe_watchdog_link_is_down - update netif_carrier status and * print link down message - * @adapter: pointer to the adapter structure + * @adapter - pointer to the adapter structure **/ static void ixgbe_watchdog_link_is_down(struct ixgbe_adapter *adapter) { @@ -5423,7 +5459,7 @@ static void ixgbe_watchdog_link_is_down(struct ixgbe_adapter *adapter) /** * ixgbe_watchdog_flush_tx - flush queues on link down - * @adapter: pointer to the device adapter structure + * @adapter - pointer to the device adapter structure **/ static void ixgbe_watchdog_flush_tx(struct ixgbe_adapter *adapter) { @@ -5472,7 +5508,7 @@ static void ixgbe_spoof_check(struct ixgbe_adapter *adapter) /** * ixgbe_watchdog_subtask - check and bring link up - * @adapter: pointer to the device adapter structure + * @adapter - pointer to the device adapter structure **/ static void ixgbe_watchdog_subtask(struct ixgbe_adapter *adapter) { @@ -5496,7 +5532,7 @@ static void ixgbe_watchdog_subtask(struct ixgbe_adapter *adapter) /** * ixgbe_sfp_detection_subtask - poll for SFP+ cable - * @adapter: the ixgbe adapter structure + * @adapter - the ixgbe adapter structure **/ static void ixgbe_sfp_detection_subtask(struct ixgbe_adapter *adapter) { @@ -5563,7 +5599,7 @@ static void ixgbe_sfp_detection_subtask(struct ixgbe_adapter *adapter) /** * ixgbe_sfp_link_config_subtask - set up link SFP after module install - * @adapter: the ixgbe adapter structure + * @adapter - the ixgbe adapter structure **/ static void ixgbe_sfp_link_config_subtask(struct ixgbe_adapter *adapter) { @@ -6194,14 +6230,8 @@ static u16 ixgbe_select_queue(struct net_device *dev, struct sk_buff *skb) if (((protocol == htons(ETH_P_FCOE)) || (protocol == htons(ETH_P_FIP))) && (adapter->flags & IXGBE_FLAG_FCOE_ENABLED)) { - struct ixgbe_ring_feature *f; - - f = &adapter->ring_feature[RING_F_FCOE]; - - while (txq >= f->indices) - txq -= f->indices; - txq += adapter->ring_feature[RING_F_FCOE].offset; - + txq &= (adapter->ring_feature[RING_F_FCOE].indices - 1); + txq += adapter->ring_feature[RING_F_FCOE].mask; return txq; } #endif @@ -6495,8 +6525,11 @@ static void ixgbe_netpoll(struct net_device *netdev) adapter->flags |= IXGBE_FLAG_IN_NETPOLL; if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) { - for (i = 0; i < adapter->num_q_vectors; i++) - ixgbe_msix_clean_rings(0, adapter->q_vector[i]); + int num_q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS; + for (i = 0; i < num_q_vectors; i++) { + struct ixgbe_q_vector *q_vector = adapter->q_vector[i]; + ixgbe_msix_clean_rings(0, q_vector); + } } else { ixgbe_intr(adapter->pdev->irq, netdev); } @@ -6553,9 +6586,8 @@ static struct rtnl_link_stats64 *ixgbe_get_stats64(struct net_device *netdev, } #ifdef CONFIG_IXGBE_DCB -/** - * ixgbe_validate_rtr - verify 802.1Qp to Rx packet buffer mapping is valid. - * @adapter: pointer to ixgbe_adapter +/* ixgbe_validate_rtr - verify 802.1Qp to Rx packet buffer mapping is valid. + * #adapter: pointer to ixgbe_adapter * @tc: number of traffic classes currently enabled * * Configure a valid 802.1Qp to Rx packet buffer mapping ie confirm @@ -6590,33 +6622,8 @@ static void ixgbe_validate_rtr(struct ixgbe_adapter *adapter, u8 tc) return; } -/** - * ixgbe_set_prio_tc_map - Configure netdev prio tc map - * @adapter: Pointer to adapter struct - * - * Populate the netdev user priority to tc map - */ -static void ixgbe_set_prio_tc_map(struct ixgbe_adapter *adapter) -{ - struct net_device *dev = adapter->netdev; - struct ixgbe_dcb_config *dcb_cfg = &adapter->dcb_cfg; - struct ieee_ets *ets = adapter->ixgbe_ieee_ets; - u8 prio; - - for (prio = 0; prio < MAX_USER_PRIORITY; prio++) { - u8 tc = 0; - - if (adapter->dcbx_cap & DCB_CAP_DCBX_VER_CEE) - tc = ixgbe_dcb_get_tc_from_up(dcb_cfg, 0, prio); - else if (ets) - tc = ets->prio_tc[prio]; - - netdev_set_prio_tc_map(dev, prio, tc); - } -} - -/** - * ixgbe_setup_tc - configure net_device for multiple traffic classes +/* ixgbe_setup_tc - routine to configure net_device for multiple traffic + * classes. * * @netdev: net device to configure * @tc: number of traffic classes to enable @@ -6632,11 +6639,6 @@ int ixgbe_setup_tc(struct net_device *dev, u8 tc) return -EINVAL; } - if (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED) { - e_err(drv, "Enable failed, SR-IOV enabled\n"); - return -EINVAL; - } - /* Hardware supports up to 8 traffic classes */ if (tc > adapter->dcb_cfg.num_tcs.pg_tcs || (hw->mac.type == ixgbe_mac_82598EB && @@ -6653,8 +6655,6 @@ int ixgbe_setup_tc(struct net_device *dev, u8 tc) if (tc) { netdev_set_num_tc(dev, tc); - ixgbe_set_prio_tc_map(adapter); - adapter->flags |= IXGBE_FLAG_DCB_ENABLED; adapter->flags &= ~IXGBE_FLAG_FDIR_HASH_CAPABLE; @@ -6664,7 +6664,6 @@ int ixgbe_setup_tc(struct net_device *dev, u8 tc) } } else { netdev_reset_tc(dev); - if (adapter->hw.mac.type == ixgbe_mac_82598EB) adapter->hw.fc.requested_mode = adapter->last_lfc_mode; @@ -7028,11 +7027,7 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, #endif if (ii->mac == ixgbe_mac_82598EB) -#ifdef CONFIG_IXGBE_DCB - indices = min_t(unsigned int, indices, MAX_TRAFFIC_CLASS * 4); -#else indices = min_t(unsigned int, indices, IXGBE_MAX_RSS_INDICES); -#endif else indices = min_t(unsigned int, indices, IXGBE_MAX_FDIR_INDICES); diff --git a/trunk/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c b/trunk/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c index 3456d5617143..daddd844691f 100644 --- a/trunk/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c +++ b/trunk/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c @@ -107,7 +107,7 @@ static struct sock_filter ptp_filter[] = { /** * ixgbe_ptp_read - read raw cycle counter (to be used by time counter) - * @cc: the cyclecounter structure + * @cc - the cyclecounter structure * * this function reads the cyclecounter registers and is called by the * cyclecounter structure used to construct a ns counter from the @@ -128,8 +128,8 @@ static cycle_t ixgbe_ptp_read(const struct cyclecounter *cc) /** * ixgbe_ptp_adjfreq - * @ptp: the ptp clock structure - * @ppb: parts per billion adjustment from base + * @ptp - the ptp clock structure + * @ppb - parts per billion adjustment from base * * adjust the frequency of the ptp cycle counter by the * indicated ppb from the base frequency. @@ -175,8 +175,8 @@ static int ixgbe_ptp_adjfreq(struct ptp_clock_info *ptp, s32 ppb) /** * ixgbe_ptp_adjtime - * @ptp: the ptp clock structure - * @delta: offset to adjust the cycle counter by + * @ptp - the ptp clock structure + * @delta - offset to adjust the cycle counter by * * adjust the timer by resetting the timecounter structure. */ @@ -203,8 +203,8 @@ static int ixgbe_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta) /** * ixgbe_ptp_gettime - * @ptp: the ptp clock structure - * @ts: timespec structure to hold the current time value + * @ptp - the ptp clock structure + * @ts - timespec structure to hold the current time value * * read the timecounter and return the correct value on ns, * after converting it into a struct timespec. @@ -229,8 +229,8 @@ static int ixgbe_ptp_gettime(struct ptp_clock_info *ptp, struct timespec *ts) /** * ixgbe_ptp_settime - * @ptp: the ptp clock structure - * @ts: the timespec containing the new time for the cycle counter + * @ptp - the ptp clock structure + * @ts - the timespec containing the new time for the cycle counter * * reset the timecounter to use a new base value instead of the kernel * wall timer value. @@ -256,9 +256,9 @@ static int ixgbe_ptp_settime(struct ptp_clock_info *ptp, /** * ixgbe_ptp_enable - * @ptp: the ptp clock structure - * @rq: the requested feature to change - * @on: whether to enable or disable the feature + * @ptp - the ptp clock structure + * @rq - the requested feature to change + * @on - whether to enable or disable the feature * * enable (or disable) ancillary features of the phc subsystem. * our driver only supports the PPS feature on the X540 @@ -294,8 +294,8 @@ static int ixgbe_ptp_enable(struct ptp_clock_info *ptp, /** * ixgbe_ptp_check_pps_event - * @adapter: the private adapter structure - * @eicr: the interrupt cause register value + * @adapter - the private adapter structure + * @eicr - the interrupt cause register value * * This function is called by the interrupt routine when checking for * interrupts. It will check and handle a pps event. @@ -325,8 +325,8 @@ void ixgbe_ptp_check_pps_event(struct ixgbe_adapter *adapter, u32 eicr) /** * ixgbe_ptp_enable_sdp - * @hw: the hardware private structure - * @shift: the clock shift for calculating nanoseconds + * @hw - the hardware private structure + * @shift - the clock shift for calculating nanoseconds * * this function enables the clock out feature on the sdp0 for the * X540 device. It will create a 1second periodic output that can be @@ -399,7 +399,7 @@ static void ixgbe_ptp_enable_sdp(struct ixgbe_hw *hw, int shift) /** * ixgbe_ptp_disable_sdp - * @hw: the private hardware structure + * @hw - the private hardware structure * * this function disables the auxiliary SDP clock out feature */ @@ -769,7 +769,7 @@ int ixgbe_ptp_hwtstamp_ioctl(struct ixgbe_adapter *adapter, /** * ixgbe_ptp_start_cyclecounter - create the cycle counter from hw - * @adapter: pointer to the adapter structure + * @adapter - pointer to the adapter structure * * this function initializes the timecounter and cyclecounter * structures for use in generated a ns counter from the arbitrary @@ -905,7 +905,7 @@ void ixgbe_ptp_start_cyclecounter(struct ixgbe_adapter *adapter) /** * ixgbe_ptp_init - * @adapter: the ixgbe private adapter structure + * @adapter - the ixgbe private adapter structure * * This function performs the required steps for enabling ptp * support. If ptp support has already been loaded it simply calls the diff --git a/trunk/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c b/trunk/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c index eb3f67c854a7..2d971d18696e 100644 --- a/trunk/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c +++ b/trunk/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c @@ -467,7 +467,7 @@ int ixgbe_vf_configuration(struct pci_dev *pdev, unsigned int event_mask) bool enable = ((event_mask & 0x10000000U) != 0); if (enable) { - eth_random_addr(vf_mac_addr); + random_ether_addr(vf_mac_addr); e_info(probe, "IOV: VF %d is enabled MAC %pM\n", vfn, vf_mac_addr); /* diff --git a/trunk/drivers/net/ethernet/intel/ixgbe/ixgbe_sysfs.c b/trunk/drivers/net/ethernet/intel/ixgbe/ixgbe_sysfs.c index 16ddf14e8ba4..2334fce47018 100644 --- a/trunk/drivers/net/ethernet/intel/ixgbe/ixgbe_sysfs.c +++ b/trunk/drivers/net/ethernet/intel/ixgbe/ixgbe_sysfs.c @@ -95,11 +95,11 @@ static ssize_t ixgbe_hwmon_show_maxopthresh(struct device *dev, return sprintf(buf, "%u\n", value); } -/** +/* * ixgbe_add_hwmon_attr - Create hwmon attr table for a hwmon sysfs file. - * @adapter: pointer to the adapter structure - * @offset: offset in the eeprom sensor data table - * @type: type of sensor data to display + * @ adapter: pointer to the adapter structure + * @ offset: offset in the eeprom sensor data table + * @ type: type of sensor data to display * * For each file we want in hwmon's sysfs interface we need a device_attribute * This is included in our hwmon_attr struct that contains the references to diff --git a/trunk/drivers/net/ethernet/intel/ixgbevf/defines.h b/trunk/drivers/net/ethernet/intel/ixgbevf/defines.h index 10cede503fe8..e09a6cc633bb 100644 --- a/trunk/drivers/net/ethernet/intel/ixgbevf/defines.h +++ b/trunk/drivers/net/ethernet/intel/ixgbevf/defines.h @@ -264,9 +264,32 @@ struct ixgbe_adv_tx_context_desc { /* Interrupt register bitmasks */ +/* Extended Interrupt Cause Read */ +#define IXGBE_EICR_RTX_QUEUE 0x0000FFFF /* RTx Queue Interrupt */ +#define IXGBE_EICR_MAILBOX 0x00080000 /* VF to PF Mailbox Interrupt */ +#define IXGBE_EICR_OTHER 0x80000000 /* Interrupt Cause Active */ + +/* Extended Interrupt Cause Set */ +#define IXGBE_EICS_RTX_QUEUE IXGBE_EICR_RTX_QUEUE /* RTx Queue Interrupt */ +#define IXGBE_EICS_MAILBOX IXGBE_EICR_MAILBOX /* VF to PF Mailbox Int */ +#define IXGBE_EICS_OTHER IXGBE_EICR_OTHER /* INT Cause Active */ + +/* Extended Interrupt Mask Set */ +#define IXGBE_EIMS_RTX_QUEUE IXGBE_EICR_RTX_QUEUE /* RTx Queue Interrupt */ +#define IXGBE_EIMS_MAILBOX IXGBE_EICR_MAILBOX /* VF to PF Mailbox Int */ +#define IXGBE_EIMS_OTHER IXGBE_EICR_OTHER /* INT Cause Active */ + +/* Extended Interrupt Mask Clear */ +#define IXGBE_EIMC_RTX_QUEUE IXGBE_EICR_RTX_QUEUE /* RTx Queue Interrupt */ +#define IXGBE_EIMC_MAILBOX IXGBE_EICR_MAILBOX /* VF to PF Mailbox Int */ +#define IXGBE_EIMC_OTHER IXGBE_EICR_OTHER /* INT Cause Active */ + +#define IXGBE_EIMS_ENABLE_MASK ( \ + IXGBE_EIMS_RTX_QUEUE | \ + IXGBE_EIMS_MAILBOX | \ + IXGBE_EIMS_OTHER) + #define IXGBE_EITR_CNT_WDIS 0x80000000 -#define IXGBE_MAX_EITR 0x00000FF8 -#define IXGBE_MIN_EITR 8 /* Error Codes */ #define IXGBE_ERR_INVALID_MAC_ADDR -1 diff --git a/trunk/drivers/net/ethernet/intel/ixgbevf/ethtool.c b/trunk/drivers/net/ethernet/intel/ixgbevf/ethtool.c index 15947c9122e1..e8dddf572d38 100644 --- a/trunk/drivers/net/ethernet/intel/ixgbevf/ethtool.c +++ b/trunk/drivers/net/ethernet/intel/ixgbevf/ethtool.c @@ -43,6 +43,7 @@ #define IXGBE_ALL_RAR_ENTRIES 16 +#ifdef ETHTOOL_GSTATS struct ixgbe_stats { char stat_string[ETH_GSTRING_LEN]; int sizeof_stat; @@ -74,17 +75,21 @@ static const struct ixgbe_stats ixgbe_gstrings_stats[] = { zero_base)}, {"tx_csum_offload_ctxt", IXGBEVF_STAT(hw_csum_tx_good, zero_base, zero_base)}, + {"rx_header_split", IXGBEVF_STAT(rx_hdr_split, zero_base, zero_base)}, }; #define IXGBE_QUEUE_STATS_LEN 0 #define IXGBE_GLOBAL_STATS_LEN ARRAY_SIZE(ixgbe_gstrings_stats) #define IXGBEVF_STATS_LEN (IXGBE_GLOBAL_STATS_LEN + IXGBE_QUEUE_STATS_LEN) +#endif /* ETHTOOL_GSTATS */ +#ifdef ETHTOOL_TEST static const char ixgbe_gstrings_test[][ETH_GSTRING_LEN] = { "Register test (offline)", "Link test (on/offline)" }; #define IXGBE_TEST_LEN (sizeof(ixgbe_gstrings_test) / ETH_GSTRING_LEN) +#endif /* ETHTOOL_TEST */ static int ixgbevf_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) @@ -364,6 +369,7 @@ static int ixgbevf_set_ringparam(struct net_device *netdev, } goto err_tx_ring_setup; } + tx_ring[i].v_idx = adapter->tx_ring[i].v_idx; } memcpy(rx_ring, adapter->rx_ring, @@ -379,6 +385,7 @@ static int ixgbevf_set_ringparam(struct net_device *netdev, } goto err_rx_ring_setup; } + rx_ring[i].v_idx = adapter->rx_ring[i].v_idx; } /* @@ -667,8 +674,10 @@ static int ixgbevf_nway_reset(struct net_device *netdev) { struct ixgbevf_adapter *adapter = netdev_priv(netdev); - if (netif_running(netdev)) - ixgbevf_reinit_locked(adapter); + if (netif_running(netdev)) { + if (!adapter->dev_closed) + ixgbevf_reinit_locked(adapter); + } return 0; } diff --git a/trunk/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h b/trunk/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h index f92daca249f8..0a1b99240d43 100644 --- a/trunk/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h +++ b/trunk/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h @@ -52,10 +52,12 @@ struct ixgbevf_tx_buffer { struct ixgbevf_rx_buffer { struct sk_buff *skb; dma_addr_t dma; + struct page *page; + dma_addr_t page_dma; + unsigned int page_offset; }; struct ixgbevf_ring { - struct ixgbevf_ring *next; struct ixgbevf_adapter *adapter; /* backlink */ void *desc; /* descriptor ring memory */ dma_addr_t dma; /* phys. address of descriptor ring */ @@ -81,9 +83,29 @@ struct ixgbevf_ring { * offset associated with this ring, which is different * for DCB and RSS modes */ +#if defined(CONFIG_DCA) || defined(CONFIG_DCA_MODULE) + /* cpu for tx queue */ + int cpu; +#endif + + u64 v_idx; /* maps directly to the index for this ring in the hardware + * vector array, can also be used for finding the bit in EICR + * and friends that represents the vector for this ring */ + + u16 work_limit; /* max work per interrupt */ u16 rx_buf_len; }; +enum ixgbevf_ring_f_enum { + RING_F_NONE = 0, + RING_F_ARRAY_SIZE /* must be last in enum set */ +}; + +struct ixgbevf_ring_feature { + int indices; + int mask; +}; + /* How many Rx Buffers do we bundle into one write to the hardware ? */ #define IXGBEVF_RX_BUFFER_WRITE 16 /* Must be power of 2 */ @@ -98,6 +120,8 @@ struct ixgbevf_ring { #define IXGBEVF_MIN_RXD 64 /* Supported Rx Buffer Sizes */ +#define IXGBEVF_RXBUFFER_64 64 /* Used for packet split */ +#define IXGBEVF_RXBUFFER_128 128 /* Used for packet split */ #define IXGBEVF_RXBUFFER_256 256 /* Used for packet split */ #define IXGBEVF_RXBUFFER_2048 2048 #define IXGBEVF_MAX_RXBUFFER 16384 /* largest size for single descriptor */ @@ -116,42 +140,22 @@ struct ixgbevf_ring { #define IXGBE_TX_FLAGS_VLAN_PRIO_MASK 0x0000e000 #define IXGBE_TX_FLAGS_VLAN_SHIFT 16 -struct ixgbevf_ring_container { - struct ixgbevf_ring *ring; /* pointer to linked list of rings */ - unsigned int total_bytes; /* total bytes processed this int */ - unsigned int total_packets; /* total packets processed this int */ - u8 count; /* total number of rings in vector */ - u8 itr; /* current ITR setting for ring */ -}; - -/* iterator for handling rings in ring container */ -#define ixgbevf_for_each_ring(pos, head) \ - for (pos = (head).ring; pos != NULL; pos = pos->next) - /* MAX_MSIX_Q_VECTORS of these are allocated, * but we only use one per queue-specific vector. */ struct ixgbevf_q_vector { struct ixgbevf_adapter *adapter; - u16 v_idx; /* index of q_vector within array, also used for - * finding the bit in EICR and friends that - * represents the vector for this ring */ - u16 itr; /* Interrupt throttle rate written to EITR */ struct napi_struct napi; - struct ixgbevf_ring_container rx, tx; - char name[IFNAMSIZ + 9]; + DECLARE_BITMAP(rxr_idx, MAX_RX_QUEUES); /* Rx ring indices */ + DECLARE_BITMAP(txr_idx, MAX_TX_QUEUES); /* Tx ring indices */ + u8 rxr_count; /* Rx ring count assigned to this vector */ + u8 txr_count; /* Tx ring count assigned to this vector */ + u8 tx_itr; + u8 rx_itr; + u32 eitr; + int v_idx; /* vector index in list */ }; -/* - * microsecond values for various ITR rates shifted by 2 to fit itr register - * with the first 3 bits reserved 0 - */ -#define IXGBE_MIN_RSC_ITR 24 -#define IXGBE_100K_ITR 40 -#define IXGBE_20K_ITR 200 -#define IXGBE_10K_ITR 400 -#define IXGBE_8K_ITR 500 - /* Helper macros to switch between ints/sec and what the register uses. * And yes, it's the same math going both ways. The lowest value * supported by all of the ixgbe hardware is 8. @@ -177,8 +181,9 @@ struct ixgbevf_q_vector { #define NON_Q_VECTORS (OTHER_VECTOR) #define MAX_MSIX_Q_VECTORS 2 +#define MAX_MSIX_COUNT 2 -#define MIN_MSIX_Q_VECTORS 1 +#define MIN_MSIX_Q_VECTORS 2 #define MIN_MSIX_COUNT (MIN_MSIX_Q_VECTORS + NON_Q_VECTORS) /* board specific private data structure */ @@ -188,14 +193,12 @@ struct ixgbevf_adapter { u16 bd_number; struct work_struct reset_task; struct ixgbevf_q_vector *q_vector[MAX_MSIX_Q_VECTORS]; + char name[MAX_MSIX_COUNT][IFNAMSIZ + 9]; /* Interrupt Throttle Rate */ - u16 rx_itr_setting; - u16 tx_itr_setting; - - /* interrupt masks */ - u32 eims_enable_mask; - u32 eims_other; + u32 itr_setting; + u16 eitr_low; + u16 eitr_high; /* TX */ struct ixgbevf_ring *tx_ring; /* One per active queue */ @@ -210,13 +213,18 @@ struct ixgbevf_adapter { /* RX */ struct ixgbevf_ring *rx_ring; /* One per active queue */ int num_rx_queues; + int num_rx_pools; /* == num_rx_queues in 82598 */ + int num_rx_queues_per_pool; /* 1 if 82598, can be many if 82599 */ u64 hw_csum_rx_error; u64 hw_rx_no_dma_resources; u64 hw_csum_rx_good; u64 non_eop_descs; int num_msix_vectors; + int max_msix_q_vectors; /* true count of q_vectors for device */ + struct ixgbevf_ring_feature ring_feature[RING_F_ARRAY_SIZE]; struct msix_entry *msix_entries; + u64 rx_hdr_split; u32 alloc_rx_page_failed; u32 alloc_rx_buff_failed; @@ -224,8 +232,15 @@ struct ixgbevf_adapter { * thus the additional *_CAPABLE flags. */ u32 flags; -#define IXGBE_FLAG_IN_WATCHDOG_TASK (u32)(1) - +#define IXGBE_FLAG_RX_CSUM_ENABLED (u32)(1) +#define IXGBE_FLAG_RX_1BUF_CAPABLE (u32)(1 << 1) +#define IXGBE_FLAG_RX_PS_CAPABLE (u32)(1 << 2) +#define IXGBE_FLAG_RX_PS_ENABLED (u32)(1 << 3) +#define IXGBE_FLAG_IN_NETPOLL (u32)(1 << 4) +#define IXGBE_FLAG_IMIR_ENABLED (u32)(1 << 5) +#define IXGBE_FLAG_MQ_CAPABLE (u32)(1 << 6) +#define IXGBE_FLAG_NEED_LINK_UPDATE (u32)(1 << 7) +#define IXGBE_FLAG_IN_WATCHDOG_TASK (u32)(1 << 8) /* OS defined structs */ struct net_device *netdev; struct pci_dev *pdev; @@ -239,14 +254,18 @@ struct ixgbevf_adapter { u32 eitr_param; unsigned long state; + u32 *config_space; u64 tx_busy; unsigned int tx_ring_count; unsigned int rx_ring_count; u32 link_speed; bool link_up; + unsigned long link_check_timeout; struct work_struct watchdog_task; + bool netdev_registered; + bool dev_closed; }; enum ixbgevf_state_t { @@ -282,9 +301,11 @@ extern void ixgbevf_free_rx_resources(struct ixgbevf_adapter *, extern void ixgbevf_free_tx_resources(struct ixgbevf_adapter *, struct ixgbevf_ring *); extern void ixgbevf_update_stats(struct ixgbevf_adapter *adapter); -void ixgbevf_write_eitr(struct ixgbevf_q_vector *); + +#ifdef ETHTOOL_OPS_COMPAT extern int ethtool_ioctl(struct ifreq *ifr); +#endif extern void ixgbe_napi_add_all(struct ixgbevf_adapter *adapter); extern void ixgbe_napi_del_all(struct ixgbevf_adapter *adapter); diff --git a/trunk/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c b/trunk/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c index 8e022c6f4b90..f69ec4288b10 100644 --- a/trunk/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c +++ b/trunk/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c @@ -97,7 +97,9 @@ module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)"); /* forward decls */ -static void ixgbevf_set_itr(struct ixgbevf_q_vector *q_vector); +static void ixgbevf_set_itr_msix(struct ixgbevf_q_vector *q_vector); +static void ixgbevf_write_eitr(struct ixgbevf_adapter *adapter, int v_idx, + u32 itr_reg); static inline void ixgbevf_release_rx_desc(struct ixgbe_hw *hw, struct ixgbevf_ring *rx_ring, @@ -113,7 +115,7 @@ static inline void ixgbevf_release_rx_desc(struct ixgbe_hw *hw, IXGBE_WRITE_REG(hw, IXGBE_VFRDT(rx_ring->reg_idx), val); } -/** +/* * ixgbevf_set_ivar - set IVAR registers - maps interrupt causes to vectors * @adapter: pointer to adapter struct * @direction: 0 for Rx, 1 for Tx, -1 for other causes @@ -173,21 +175,27 @@ static void ixgbevf_unmap_and_free_tx_resource(struct ixgbevf_adapter *adapter, #define IXGBE_MAX_DATA_PER_TXD (1 << IXGBE_MAX_TXD_PWR) /* Tx Descriptors needed, worst case */ -#define TXD_USE_COUNT(S) DIV_ROUND_UP((S), IXGBE_MAX_DATA_PER_TXD) -#define DESC_NEEDED (MAX_SKB_FRAGS + 4) +#define TXD_USE_COUNT(S) (((S) >> IXGBE_MAX_TXD_PWR) + \ + (((S) & (IXGBE_MAX_DATA_PER_TXD - 1)) ? 1 : 0)) +#ifdef MAX_SKB_FRAGS +#define DESC_NEEDED (TXD_USE_COUNT(IXGBE_MAX_DATA_PER_TXD) /* skb->data */ + \ + MAX_SKB_FRAGS * TXD_USE_COUNT(PAGE_SIZE) + 1) /* for context */ +#else +#define DESC_NEEDED TXD_USE_COUNT(IXGBE_MAX_DATA_PER_TXD) +#endif static void ixgbevf_tx_timeout(struct net_device *netdev); /** * ixgbevf_clean_tx_irq - Reclaim resources after transmit completes - * @q_vector: board private structure + * @adapter: board private structure * @tx_ring: tx ring to clean **/ -static bool ixgbevf_clean_tx_irq(struct ixgbevf_q_vector *q_vector, +static bool ixgbevf_clean_tx_irq(struct ixgbevf_adapter *adapter, struct ixgbevf_ring *tx_ring) { - struct ixgbevf_adapter *adapter = q_vector->adapter; struct net_device *netdev = adapter->netdev; + struct ixgbe_hw *hw = &adapter->hw; union ixgbe_adv_tx_desc *tx_desc, *eop_desc; struct ixgbevf_tx_buffer *tx_buffer_info; unsigned int i, eop, count = 0; @@ -198,7 +206,7 @@ static bool ixgbevf_clean_tx_irq(struct ixgbevf_q_vector *q_vector, eop_desc = IXGBE_TX_DESC_ADV(*tx_ring, eop); while ((eop_desc->wb.status & cpu_to_le32(IXGBE_TXD_STAT_DD)) && - (count < tx_ring->count)) { + (count < tx_ring->work_limit)) { bool cleaned = false; rmb(); /* read buffer_info after eop_desc */ /* eop could change between read and DD-check */ @@ -247,11 +255,25 @@ static bool ixgbevf_clean_tx_irq(struct ixgbevf_q_vector *q_vector, * sees the new next_to_clean. */ smp_mb(); +#ifdef HAVE_TX_MQ if (__netif_subqueue_stopped(netdev, tx_ring->queue_index) && !test_bit(__IXGBEVF_DOWN, &adapter->state)) { netif_wake_subqueue(netdev, tx_ring->queue_index); ++adapter->restart_queue; } +#else + if (netif_queue_stopped(netdev) && + !test_bit(__IXGBEVF_DOWN, &adapter->state)) { + netif_wake_queue(netdev); + ++adapter->restart_queue; + } +#endif + } + + /* re-arm the interrupt */ + if ((count >= tx_ring->work_limit) && + (!test_bit(__IXGBEVF_DOWN, &adapter->state))) { + IXGBE_WRITE_REG(hw, IXGBE_VTEICS, tx_ring->v_idx); } u64_stats_update_begin(&tx_ring->syncp); @@ -259,7 +281,7 @@ static bool ixgbevf_clean_tx_irq(struct ixgbevf_q_vector *q_vector, tx_ring->total_packets += total_packets; u64_stats_update_end(&tx_ring->syncp); - return count < tx_ring->count; + return count < tx_ring->work_limit; } /** @@ -282,7 +304,10 @@ static void ixgbevf_receive_skb(struct ixgbevf_q_vector *q_vector, if (is_vlan && test_bit(tag, adapter->active_vlans)) __vlan_hwaccel_put_tag(skb, tag); - napi_gro_receive(&q_vector->napi, skb); + if (!(adapter->flags & IXGBE_FLAG_IN_NETPOLL)) + napi_gro_receive(&q_vector->napi, skb); + else + netif_rx(skb); } /** @@ -297,7 +322,7 @@ static inline void ixgbevf_rx_checksum(struct ixgbevf_adapter *adapter, skb_checksum_none_assert(skb); /* Rx csum disabled */ - if (!(adapter->netdev->features & NETIF_F_RXCSUM)) + if (!(adapter->flags & IXGBE_FLAG_RX_CSUM_ENABLED)) return; /* if IP and error */ @@ -340,6 +365,27 @@ static void ixgbevf_alloc_rx_buffers(struct ixgbevf_adapter *adapter, while (cleaned_count--) { rx_desc = IXGBE_RX_DESC_ADV(*rx_ring, i); + + if (!bi->page_dma && + (adapter->flags & IXGBE_FLAG_RX_PS_ENABLED)) { + if (!bi->page) { + bi->page = alloc_page(GFP_ATOMIC | __GFP_COLD); + if (!bi->page) { + adapter->alloc_rx_page_failed++; + goto no_buffers; + } + bi->page_offset = 0; + } else { + /* use a half page if we're re-using */ + bi->page_offset ^= (PAGE_SIZE / 2); + } + + bi->page_dma = dma_map_page(&pdev->dev, bi->page, + bi->page_offset, + (PAGE_SIZE / 2), + DMA_FROM_DEVICE); + } + skb = bi->skb; if (!skb) { skb = netdev_alloc_skb(adapter->netdev, @@ -364,7 +410,14 @@ static void ixgbevf_alloc_rx_buffers(struct ixgbevf_adapter *adapter, rx_ring->rx_buf_len, DMA_FROM_DEVICE); } - rx_desc->read.pkt_addr = cpu_to_le64(bi->dma); + /* Refresh the desc even if buffer_addrs didn't change because + * each write-back erases this info. */ + if (adapter->flags & IXGBE_FLAG_RX_PS_ENABLED) { + rx_desc->read.pkt_addr = cpu_to_le64(bi->page_dma); + rx_desc->read.hdr_addr = cpu_to_le64(bi->dma); + } else { + rx_desc->read.pkt_addr = cpu_to_le64(bi->dma); + } i++; if (i == rx_ring->count) @@ -383,16 +436,28 @@ static void ixgbevf_alloc_rx_buffers(struct ixgbevf_adapter *adapter, } static inline void ixgbevf_irq_enable_queues(struct ixgbevf_adapter *adapter, - u32 qmask) + u64 qmask) { + u32 mask; struct ixgbe_hw *hw = &adapter->hw; - IXGBE_WRITE_REG(hw, IXGBE_VTEIMS, qmask); + mask = (qmask & 0xFFFFFFFF); + IXGBE_WRITE_REG(hw, IXGBE_VTEIMS, mask); +} + +static inline u16 ixgbevf_get_hdr_info(union ixgbe_adv_rx_desc *rx_desc) +{ + return rx_desc->wb.lower.lo_dword.hs_rss.hdr_info; +} + +static inline u16 ixgbevf_get_pkt_info(union ixgbe_adv_rx_desc *rx_desc) +{ + return rx_desc->wb.lower.lo_dword.hs_rss.pkt_info; } static bool ixgbevf_clean_rx_irq(struct ixgbevf_q_vector *q_vector, struct ixgbevf_ring *rx_ring, - int budget) + int *work_done, int work_to_do) { struct ixgbevf_adapter *adapter = q_vector->adapter; struct pci_dev *pdev = adapter->pdev; @@ -401,6 +466,8 @@ static bool ixgbevf_clean_rx_irq(struct ixgbevf_q_vector *q_vector, struct sk_buff *skb; unsigned int i; u32 len, staterr; + u16 hdr_info; + bool cleaned = false; int cleaned_count = 0; unsigned int total_rx_bytes = 0, total_rx_packets = 0; @@ -410,12 +477,25 @@ static bool ixgbevf_clean_rx_irq(struct ixgbevf_q_vector *q_vector, rx_buffer_info = &rx_ring->rx_buffer_info[i]; while (staterr & IXGBE_RXD_STAT_DD) { - if (!budget) + u32 upper_len = 0; + if (*work_done >= work_to_do) break; - budget--; + (*work_done)++; rmb(); /* read descriptor and rx_buffer_info after status DD */ - len = le16_to_cpu(rx_desc->wb.upper.length); + if (adapter->flags & IXGBE_FLAG_RX_PS_ENABLED) { + hdr_info = le16_to_cpu(ixgbevf_get_hdr_info(rx_desc)); + len = (hdr_info & IXGBE_RXDADV_HDRBUFLEN_MASK) >> + IXGBE_RXDADV_HDRBUFLEN_SHIFT; + if (hdr_info & IXGBE_RXDADV_SPH) + adapter->rx_hdr_split++; + if (len > IXGBEVF_RX_HDR_SIZE) + len = IXGBEVF_RX_HDR_SIZE; + upper_len = le16_to_cpu(rx_desc->wb.upper.length); + } else { + len = le16_to_cpu(rx_desc->wb.upper.length); + } + cleaned = true; skb = rx_buffer_info->skb; prefetch(skb->data - NET_IP_ALIGN); rx_buffer_info->skb = NULL; @@ -428,6 +508,26 @@ static bool ixgbevf_clean_rx_irq(struct ixgbevf_q_vector *q_vector, skb_put(skb, len); } + if (upper_len) { + dma_unmap_page(&pdev->dev, rx_buffer_info->page_dma, + PAGE_SIZE / 2, DMA_FROM_DEVICE); + rx_buffer_info->page_dma = 0; + skb_fill_page_desc(skb, skb_shinfo(skb)->nr_frags, + rx_buffer_info->page, + rx_buffer_info->page_offset, + upper_len); + + if ((rx_ring->rx_buf_len > (PAGE_SIZE / 2)) || + (page_count(rx_buffer_info->page) != 1)) + rx_buffer_info->page = NULL; + else + get_page(rx_buffer_info->page); + + skb->len += upper_len; + skb->data_len += upper_len; + skb->truesize += upper_len; + } + i++; if (i == rx_ring->count) i = 0; @@ -439,8 +539,15 @@ static bool ixgbevf_clean_rx_irq(struct ixgbevf_q_vector *q_vector, next_buffer = &rx_ring->rx_buffer_info[i]; if (!(staterr & IXGBE_RXD_STAT_EOP)) { - skb->next = next_buffer->skb; - skb->next->prev = skb; + if (adapter->flags & IXGBE_FLAG_RX_PS_ENABLED) { + rx_buffer_info->skb = next_buffer->skb; + rx_buffer_info->dma = next_buffer->dma; + next_buffer->skb = skb; + next_buffer->dma = 0; + } else { + skb->next = next_buffer->skb; + skb->next->prev = skb; + } adapter->non_eop_descs++; goto next_desc; } @@ -498,52 +605,92 @@ static bool ixgbevf_clean_rx_irq(struct ixgbevf_q_vector *q_vector, rx_ring->total_bytes += total_rx_bytes; u64_stats_update_end(&rx_ring->syncp); - return !!budget; + return cleaned; } /** - * ixgbevf_poll - NAPI polling calback + * ixgbevf_clean_rxonly - msix (aka one shot) rx clean routine * @napi: napi struct with our devices info in it * @budget: amount of work driver is allowed to do this pass, in packets * - * This function will clean more than one or more rings associated with a - * q_vector. + * This function is optimized for cleaning one queue only on a single + * q_vector!!! **/ -static int ixgbevf_poll(struct napi_struct *napi, int budget) +static int ixgbevf_clean_rxonly(struct napi_struct *napi, int budget) { struct ixgbevf_q_vector *q_vector = container_of(napi, struct ixgbevf_q_vector, napi); struct ixgbevf_adapter *adapter = q_vector->adapter; - struct ixgbevf_ring *ring; - int per_ring_budget; - bool clean_complete = true; + struct ixgbevf_ring *rx_ring = NULL; + int work_done = 0; + long r_idx; + + r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues); + rx_ring = &(adapter->rx_ring[r_idx]); - ixgbevf_for_each_ring(ring, q_vector->tx) - clean_complete &= ixgbevf_clean_tx_irq(q_vector, ring); + ixgbevf_clean_rx_irq(q_vector, rx_ring, &work_done, budget); + + /* If all Rx work done, exit the polling mode */ + if (work_done < budget) { + napi_complete(napi); + if (adapter->itr_setting & 1) + ixgbevf_set_itr_msix(q_vector); + if (!test_bit(__IXGBEVF_DOWN, &adapter->state)) + ixgbevf_irq_enable_queues(adapter, rx_ring->v_idx); + } + + return work_done; +} + +/** + * ixgbevf_clean_rxonly_many - msix (aka one shot) rx clean routine + * @napi: napi struct with our devices info in it + * @budget: amount of work driver is allowed to do this pass, in packets + * + * This function will clean more than one rx queue associated with a + * q_vector. + **/ +static int ixgbevf_clean_rxonly_many(struct napi_struct *napi, int budget) +{ + struct ixgbevf_q_vector *q_vector = + container_of(napi, struct ixgbevf_q_vector, napi); + struct ixgbevf_adapter *adapter = q_vector->adapter; + struct ixgbevf_ring *rx_ring = NULL; + int work_done = 0, i; + long r_idx; + u64 enable_mask = 0; /* attempt to distribute budget to each queue fairly, but don't allow * the budget to go below 1 because we'll exit polling */ - if (q_vector->rx.count > 1) - per_ring_budget = max(budget/q_vector->rx.count, 1); - else - per_ring_budget = budget; - - ixgbevf_for_each_ring(ring, q_vector->rx) - clean_complete &= ixgbevf_clean_rx_irq(q_vector, ring, - per_ring_budget); - - /* If all work not completed, return budget and keep polling */ - if (!clean_complete) - return budget; - /* all work done, exit the polling mode */ - napi_complete(napi); - if (adapter->rx_itr_setting & 1) - ixgbevf_set_itr(q_vector); - if (!test_bit(__IXGBEVF_DOWN, &adapter->state)) - ixgbevf_irq_enable_queues(adapter, - 1 << q_vector->v_idx); + budget /= (q_vector->rxr_count ?: 1); + budget = max(budget, 1); + r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues); + for (i = 0; i < q_vector->rxr_count; i++) { + rx_ring = &(adapter->rx_ring[r_idx]); + ixgbevf_clean_rx_irq(q_vector, rx_ring, &work_done, budget); + enable_mask |= rx_ring->v_idx; + r_idx = find_next_bit(q_vector->rxr_idx, adapter->num_rx_queues, + r_idx + 1); + } - return 0; +#ifndef HAVE_NETDEV_NAPI_LIST + if (!netif_running(adapter->netdev)) + work_done = 0; + +#endif + r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues); + rx_ring = &(adapter->rx_ring[r_idx]); + + /* If all Rx work done, exit the polling mode */ + if (work_done < budget) { + napi_complete(napi); + if (adapter->itr_setting & 1) + ixgbevf_set_itr_msix(q_vector); + if (!test_bit(__IXGBEVF_DOWN, &adapter->state)) + ixgbevf_irq_enable_queues(adapter, enable_mask); + } + + return work_done; } @@ -557,49 +704,56 @@ static int ixgbevf_poll(struct napi_struct *napi, int budget) static void ixgbevf_configure_msix(struct ixgbevf_adapter *adapter) { struct ixgbevf_q_vector *q_vector; - int q_vectors, v_idx; + struct ixgbe_hw *hw = &adapter->hw; + int i, j, q_vectors, v_idx, r_idx; + u32 mask; q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS; - adapter->eims_enable_mask = 0; /* * Populate the IVAR table and set the ITR values to the * corresponding register. */ for (v_idx = 0; v_idx < q_vectors; v_idx++) { - struct ixgbevf_ring *ring; q_vector = adapter->q_vector[v_idx]; - - ixgbevf_for_each_ring(ring, q_vector->rx) - ixgbevf_set_ivar(adapter, 0, ring->reg_idx, v_idx); - - ixgbevf_for_each_ring(ring, q_vector->tx) - ixgbevf_set_ivar(adapter, 1, ring->reg_idx, v_idx); - - if (q_vector->tx.ring && !q_vector->rx.ring) { - /* tx only vector */ - if (adapter->tx_itr_setting == 1) - q_vector->itr = IXGBE_10K_ITR; - else - q_vector->itr = adapter->tx_itr_setting; - } else { - /* rx or rx/tx vector */ - if (adapter->rx_itr_setting == 1) - q_vector->itr = IXGBE_20K_ITR; - else - q_vector->itr = adapter->rx_itr_setting; + /* XXX for_each_set_bit(...) */ + r_idx = find_first_bit(q_vector->rxr_idx, + adapter->num_rx_queues); + + for (i = 0; i < q_vector->rxr_count; i++) { + j = adapter->rx_ring[r_idx].reg_idx; + ixgbevf_set_ivar(adapter, 0, j, v_idx); + r_idx = find_next_bit(q_vector->rxr_idx, + adapter->num_rx_queues, + r_idx + 1); + } + r_idx = find_first_bit(q_vector->txr_idx, + adapter->num_tx_queues); + + for (i = 0; i < q_vector->txr_count; i++) { + j = adapter->tx_ring[r_idx].reg_idx; + ixgbevf_set_ivar(adapter, 1, j, v_idx); + r_idx = find_next_bit(q_vector->txr_idx, + adapter->num_tx_queues, + r_idx + 1); } - /* add q_vector eims value to global eims_enable_mask */ - adapter->eims_enable_mask |= 1 << v_idx; + /* if this is a tx only vector halve the interrupt rate */ + if (q_vector->txr_count && !q_vector->rxr_count) + q_vector->eitr = (adapter->eitr_param >> 1); + else if (q_vector->rxr_count) + /* rx only */ + q_vector->eitr = adapter->eitr_param; - ixgbevf_write_eitr(q_vector); + ixgbevf_write_eitr(adapter, v_idx, q_vector->eitr); } ixgbevf_set_ivar(adapter, -1, 1, v_idx); - /* setup eims_other and add value to global eims_enable_mask */ - adapter->eims_other = 1 << v_idx; - adapter->eims_enable_mask |= adapter->eims_other; + + /* set up to autoclear timer, and the vectors */ + mask = IXGBE_EIMS_ENABLE_MASK; + mask &= ~IXGBE_EIMS_OTHER; + IXGBE_WRITE_REG(hw, IXGBE_VTEIAC, mask); } enum latency_range { @@ -611,8 +765,11 @@ enum latency_range { /** * ixgbevf_update_itr - update the dynamic ITR value based on statistics - * @q_vector: structure containing interrupt and ring information - * @ring_container: structure containing ring performance data + * @adapter: pointer to adapter + * @eitr: eitr setting (ints per sec) to give last timeslice + * @itr_setting: current throttle rate in ints/second + * @packets: the number of packets during this measurement interval + * @bytes: the number of bytes during this measurement interval * * Stores a new ITR value based on packets and byte * counts during the last interrupt. The advantage of per interrupt @@ -622,17 +779,17 @@ enum latency_range { * on testing data as well as attempting to minimize response time * while increasing bulk throughput. **/ -static void ixgbevf_update_itr(struct ixgbevf_q_vector *q_vector, - struct ixgbevf_ring_container *ring_container) +static u8 ixgbevf_update_itr(struct ixgbevf_adapter *adapter, + u32 eitr, u8 itr_setting, + int packets, int bytes) { - int bytes = ring_container->total_bytes; - int packets = ring_container->total_packets; + unsigned int retval = itr_setting; u32 timepassed_us; u64 bytes_perint; - u8 itr_setting = ring_container->itr; if (packets == 0) - return; + goto update_itr_done; + /* simple throttlerate management * 0-20MB/s lowest (100000 ints/s) @@ -640,48 +797,46 @@ static void ixgbevf_update_itr(struct ixgbevf_q_vector *q_vector, * 100-1249MB/s bulk (8000 ints/s) */ /* what was last interrupt timeslice? */ - timepassed_us = q_vector->itr >> 2; + timepassed_us = 1000000/eitr; bytes_perint = bytes / timepassed_us; /* bytes/usec */ switch (itr_setting) { case lowest_latency: - if (bytes_perint > 10) - itr_setting = low_latency; + if (bytes_perint > adapter->eitr_low) + retval = low_latency; break; case low_latency: - if (bytes_perint > 20) - itr_setting = bulk_latency; - else if (bytes_perint <= 10) - itr_setting = lowest_latency; + if (bytes_perint > adapter->eitr_high) + retval = bulk_latency; + else if (bytes_perint <= adapter->eitr_low) + retval = lowest_latency; break; case bulk_latency: - if (bytes_perint <= 20) - itr_setting = low_latency; + if (bytes_perint <= adapter->eitr_high) + retval = low_latency; break; } - /* clear work counters since we have the values we need */ - ring_container->total_bytes = 0; - ring_container->total_packets = 0; - - /* write updated itr to ring container */ - ring_container->itr = itr_setting; +update_itr_done: + return retval; } /** * ixgbevf_write_eitr - write VTEITR register in hardware specific way - * @q_vector: structure containing interrupt and ring information + * @adapter: pointer to adapter struct + * @v_idx: vector index into q_vector array + * @itr_reg: new value to be written in *register* format, not ints/s * * This function is made to be called by ethtool and by the driver * when it needs to update VTEITR registers at runtime. Hardware * specific quirks/differences are taken care of here. */ -void ixgbevf_write_eitr(struct ixgbevf_q_vector *q_vector) +static void ixgbevf_write_eitr(struct ixgbevf_adapter *adapter, int v_idx, + u32 itr_reg) { - struct ixgbevf_adapter *adapter = q_vector->adapter; struct ixgbe_hw *hw = &adapter->hw; - int v_idx = q_vector->v_idx; - u32 itr_reg = q_vector->itr & IXGBE_MAX_EITR; + + itr_reg = EITR_INTS_PER_SEC_TO_REG(itr_reg); /* * set the WDIS bit to not clear the timer bits and cause an @@ -692,49 +847,84 @@ void ixgbevf_write_eitr(struct ixgbevf_q_vector *q_vector) IXGBE_WRITE_REG(hw, IXGBE_VTEITR(v_idx), itr_reg); } -static void ixgbevf_set_itr(struct ixgbevf_q_vector *q_vector) +static void ixgbevf_set_itr_msix(struct ixgbevf_q_vector *q_vector) { - u32 new_itr = q_vector->itr; - u8 current_itr; - - ixgbevf_update_itr(q_vector, &q_vector->tx); - ixgbevf_update_itr(q_vector, &q_vector->rx); - - current_itr = max(q_vector->rx.itr, q_vector->tx.itr); + struct ixgbevf_adapter *adapter = q_vector->adapter; + u32 new_itr; + u8 current_itr, ret_itr; + int i, r_idx, v_idx = q_vector->v_idx; + struct ixgbevf_ring *rx_ring, *tx_ring; + + r_idx = find_first_bit(q_vector->txr_idx, adapter->num_tx_queues); + for (i = 0; i < q_vector->txr_count; i++) { + tx_ring = &(adapter->tx_ring[r_idx]); + ret_itr = ixgbevf_update_itr(adapter, q_vector->eitr, + q_vector->tx_itr, + tx_ring->total_packets, + tx_ring->total_bytes); + /* if the result for this queue would decrease interrupt + * rate for this vector then use that result */ + q_vector->tx_itr = ((q_vector->tx_itr > ret_itr) ? + q_vector->tx_itr - 1 : ret_itr); + r_idx = find_next_bit(q_vector->txr_idx, adapter->num_tx_queues, + r_idx + 1); + } + + r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues); + for (i = 0; i < q_vector->rxr_count; i++) { + rx_ring = &(adapter->rx_ring[r_idx]); + ret_itr = ixgbevf_update_itr(adapter, q_vector->eitr, + q_vector->rx_itr, + rx_ring->total_packets, + rx_ring->total_bytes); + /* if the result for this queue would decrease interrupt + * rate for this vector then use that result */ + q_vector->rx_itr = ((q_vector->rx_itr > ret_itr) ? + q_vector->rx_itr - 1 : ret_itr); + r_idx = find_next_bit(q_vector->rxr_idx, adapter->num_rx_queues, + r_idx + 1); + } + + current_itr = max(q_vector->rx_itr, q_vector->tx_itr); switch (current_itr) { /* counts and packets in update_itr are dependent on these numbers */ case lowest_latency: - new_itr = IXGBE_100K_ITR; + new_itr = 100000; break; case low_latency: - new_itr = IXGBE_20K_ITR; + new_itr = 20000; /* aka hwitr = ~200 */ break; case bulk_latency: default: - new_itr = IXGBE_8K_ITR; + new_itr = 8000; break; } - if (new_itr != q_vector->itr) { - /* do an exponential smoothing */ - new_itr = (10 * new_itr * q_vector->itr) / - ((9 * new_itr) + q_vector->itr); - - /* save the algorithm value here */ - q_vector->itr = new_itr; + if (new_itr != q_vector->eitr) { + u32 itr_reg; - ixgbevf_write_eitr(q_vector); + /* save the algorithm value here, not the smoothed one */ + q_vector->eitr = new_itr; + /* do an exponential smoothing */ + new_itr = ((q_vector->eitr * 90)/100) + ((new_itr * 10)/100); + itr_reg = EITR_INTS_PER_SEC_TO_REG(new_itr); + ixgbevf_write_eitr(adapter, v_idx, itr_reg); } } static irqreturn_t ixgbevf_msix_mbx(int irq, void *data) { - struct ixgbevf_adapter *adapter = data; + struct net_device *netdev = data; + struct ixgbevf_adapter *adapter = netdev_priv(netdev); struct ixgbe_hw *hw = &adapter->hw; + u32 eicr; u32 msg; bool got_ack = false; + eicr = IXGBE_READ_REG(hw, IXGBE_VTEICS); + IXGBE_WRITE_REG(hw, IXGBE_VTEICR, eicr); + if (!hw->mbx.ops.check_for_ack(hw)) got_ack = true; @@ -763,24 +953,75 @@ static irqreturn_t ixgbevf_msix_mbx(int irq, void *data) if (got_ack) hw->mbx.v2p_mailbox |= IXGBE_VFMAILBOX_PFACK; - IXGBE_WRITE_REG(hw, IXGBE_VTEIMS, adapter->eims_other); - return IRQ_HANDLED; } +static irqreturn_t ixgbevf_msix_clean_tx(int irq, void *data) +{ + struct ixgbevf_q_vector *q_vector = data; + struct ixgbevf_adapter *adapter = q_vector->adapter; + struct ixgbevf_ring *tx_ring; + int i, r_idx; + + if (!q_vector->txr_count) + return IRQ_HANDLED; + + r_idx = find_first_bit(q_vector->txr_idx, adapter->num_tx_queues); + for (i = 0; i < q_vector->txr_count; i++) { + tx_ring = &(adapter->tx_ring[r_idx]); + tx_ring->total_bytes = 0; + tx_ring->total_packets = 0; + ixgbevf_clean_tx_irq(adapter, tx_ring); + r_idx = find_next_bit(q_vector->txr_idx, adapter->num_tx_queues, + r_idx + 1); + } + + if (adapter->itr_setting & 1) + ixgbevf_set_itr_msix(q_vector); + + return IRQ_HANDLED; +} /** - * ixgbevf_msix_clean_rings - single unshared vector rx clean (all queues) + * ixgbevf_msix_clean_rx - single unshared vector rx clean (all queues) * @irq: unused * @data: pointer to our q_vector struct for this interrupt vector **/ -static irqreturn_t ixgbevf_msix_clean_rings(int irq, void *data) +static irqreturn_t ixgbevf_msix_clean_rx(int irq, void *data) { struct ixgbevf_q_vector *q_vector = data; + struct ixgbevf_adapter *adapter = q_vector->adapter; + struct ixgbe_hw *hw = &adapter->hw; + struct ixgbevf_ring *rx_ring; + int r_idx; + int i; + + r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues); + for (i = 0; i < q_vector->rxr_count; i++) { + rx_ring = &(adapter->rx_ring[r_idx]); + rx_ring->total_bytes = 0; + rx_ring->total_packets = 0; + r_idx = find_next_bit(q_vector->rxr_idx, adapter->num_rx_queues, + r_idx + 1); + } + + if (!q_vector->rxr_count) + return IRQ_HANDLED; + + r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues); + rx_ring = &(adapter->rx_ring[r_idx]); + /* disable interrupts on this vector only */ + IXGBE_WRITE_REG(hw, IXGBE_VTEIMC, rx_ring->v_idx); + napi_schedule(&q_vector->napi); - /* EIAM disabled interrupts (on this vector) for us */ - if (q_vector->rx.ring || q_vector->tx.ring) - napi_schedule(&q_vector->napi); + + return IRQ_HANDLED; +} + +static irqreturn_t ixgbevf_msix_clean_many(int irq, void *data) +{ + ixgbevf_msix_clean_rx(irq, data); + ixgbevf_msix_clean_tx(irq, data); return IRQ_HANDLED; } @@ -790,9 +1031,9 @@ static inline void map_vector_to_rxq(struct ixgbevf_adapter *a, int v_idx, { struct ixgbevf_q_vector *q_vector = a->q_vector[v_idx]; - a->rx_ring[r_idx].next = q_vector->rx.ring; - q_vector->rx.ring = &a->rx_ring[r_idx]; - q_vector->rx.count++; + set_bit(r_idx, q_vector->rxr_idx); + q_vector->rxr_count++; + a->rx_ring[r_idx].v_idx = 1 << v_idx; } static inline void map_vector_to_txq(struct ixgbevf_adapter *a, int v_idx, @@ -800,9 +1041,9 @@ static inline void map_vector_to_txq(struct ixgbevf_adapter *a, int v_idx, { struct ixgbevf_q_vector *q_vector = a->q_vector[v_idx]; - a->tx_ring[t_idx].next = q_vector->tx.ring; - q_vector->tx.ring = &a->tx_ring[t_idx]; - q_vector->tx.count++; + set_bit(t_idx, q_vector->txr_idx); + q_vector->txr_count++; + a->tx_ring[t_idx].v_idx = 1 << v_idx; } /** @@ -878,30 +1119,37 @@ static int ixgbevf_map_rings_to_vectors(struct ixgbevf_adapter *adapter) static int ixgbevf_request_msix_irqs(struct ixgbevf_adapter *adapter) { struct net_device *netdev = adapter->netdev; - int q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS; - int vector, err; + irqreturn_t (*handler)(int, void *); + int i, vector, q_vectors, err; int ri = 0, ti = 0; + /* Decrement for Other and TCP Timer vectors */ + q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS; + +#define SET_HANDLER(_v) (((_v)->rxr_count && (_v)->txr_count) \ + ? &ixgbevf_msix_clean_many : \ + (_v)->rxr_count ? &ixgbevf_msix_clean_rx : \ + (_v)->txr_count ? &ixgbevf_msix_clean_tx : \ + NULL) for (vector = 0; vector < q_vectors; vector++) { - struct ixgbevf_q_vector *q_vector = adapter->q_vector[vector]; - struct msix_entry *entry = &adapter->msix_entries[vector]; - - if (q_vector->tx.ring && q_vector->rx.ring) { - snprintf(q_vector->name, sizeof(q_vector->name) - 1, - "%s-%s-%d", netdev->name, "TxRx", ri++); - ti++; - } else if (q_vector->rx.ring) { - snprintf(q_vector->name, sizeof(q_vector->name) - 1, - "%s-%s-%d", netdev->name, "rx", ri++); - } else if (q_vector->tx.ring) { - snprintf(q_vector->name, sizeof(q_vector->name) - 1, - "%s-%s-%d", netdev->name, "tx", ti++); + handler = SET_HANDLER(adapter->q_vector[vector]); + + if (handler == &ixgbevf_msix_clean_rx) { + sprintf(adapter->name[vector], "%s-%s-%d", + netdev->name, "rx", ri++); + } else if (handler == &ixgbevf_msix_clean_tx) { + sprintf(adapter->name[vector], "%s-%s-%d", + netdev->name, "tx", ti++); + } else if (handler == &ixgbevf_msix_clean_many) { + sprintf(adapter->name[vector], "%s-%s-%d", + netdev->name, "TxRx", vector); } else { /* skip this unused q_vector */ continue; } - err = request_irq(entry->vector, &ixgbevf_msix_clean_rings, 0, - q_vector->name, q_vector); + err = request_irq(adapter->msix_entries[vector].vector, + handler, 0, adapter->name[vector], + adapter->q_vector[vector]); if (err) { hw_dbg(&adapter->hw, "request_irq failed for MSIX interrupt " @@ -910,8 +1158,9 @@ static int ixgbevf_request_msix_irqs(struct ixgbevf_adapter *adapter) } } + sprintf(adapter->name[vector], "%s:mbx", netdev->name); err = request_irq(adapter->msix_entries[vector].vector, - &ixgbevf_msix_mbx, 0, netdev->name, adapter); + &ixgbevf_msix_mbx, 0, adapter->name[vector], netdev); if (err) { hw_dbg(&adapter->hw, "request_irq for msix_mbx failed: %d\n", err); @@ -921,11 +1170,9 @@ static int ixgbevf_request_msix_irqs(struct ixgbevf_adapter *adapter) return 0; free_queue_irqs: - while (vector) { - vector--; - free_irq(adapter->msix_entries[vector].vector, - adapter->q_vector[vector]); - } + for (i = vector - 1; i >= 0; i--) + free_irq(adapter->msix_entries[--vector].vector, + &(adapter->q_vector[i])); pci_disable_msix(adapter->pdev); kfree(adapter->msix_entries); adapter->msix_entries = NULL; @@ -938,10 +1185,11 @@ static inline void ixgbevf_reset_q_vectors(struct ixgbevf_adapter *adapter) for (i = 0; i < q_vectors; i++) { struct ixgbevf_q_vector *q_vector = adapter->q_vector[i]; - q_vector->rx.ring = NULL; - q_vector->tx.ring = NULL; - q_vector->rx.count = 0; - q_vector->tx.count = 0; + bitmap_zero(q_vector->rxr_idx, MAX_RX_QUEUES); + bitmap_zero(q_vector->txr_idx, MAX_TX_QUEUES); + q_vector->rxr_count = 0; + q_vector->txr_count = 0; + q_vector->eitr = adapter->eitr_param; } } @@ -967,20 +1215,17 @@ static int ixgbevf_request_irq(struct ixgbevf_adapter *adapter) static void ixgbevf_free_irq(struct ixgbevf_adapter *adapter) { + struct net_device *netdev = adapter->netdev; int i, q_vectors; q_vectors = adapter->num_msix_vectors; + i = q_vectors - 1; - free_irq(adapter->msix_entries[i].vector, adapter); + free_irq(adapter->msix_entries[i].vector, netdev); i--; for (; i >= 0; i--) { - /* free only the irqs that were actually requested */ - if (!adapter->q_vector[i]->rx.ring && - !adapter->q_vector[i]->tx.ring) - continue; - free_irq(adapter->msix_entries[i].vector, adapter->q_vector[i]); } @@ -994,12 +1239,10 @@ static void ixgbevf_free_irq(struct ixgbevf_adapter *adapter) **/ static inline void ixgbevf_irq_disable(struct ixgbevf_adapter *adapter) { - struct ixgbe_hw *hw = &adapter->hw; int i; + struct ixgbe_hw *hw = &adapter->hw; - IXGBE_WRITE_REG(hw, IXGBE_VTEIAM, 0); IXGBE_WRITE_REG(hw, IXGBE_VTEIMC, ~0); - IXGBE_WRITE_REG(hw, IXGBE_VTEIAC, 0); IXGBE_WRITE_FLUSH(hw); @@ -1011,13 +1254,23 @@ static inline void ixgbevf_irq_disable(struct ixgbevf_adapter *adapter) * ixgbevf_irq_enable - Enable default interrupt generation settings * @adapter: board private structure **/ -static inline void ixgbevf_irq_enable(struct ixgbevf_adapter *adapter) +static inline void ixgbevf_irq_enable(struct ixgbevf_adapter *adapter, + bool queues, bool flush) { struct ixgbe_hw *hw = &adapter->hw; + u32 mask; + u64 qmask; - IXGBE_WRITE_REG(hw, IXGBE_VTEIAM, adapter->eims_enable_mask); - IXGBE_WRITE_REG(hw, IXGBE_VTEIAC, adapter->eims_enable_mask); - IXGBE_WRITE_REG(hw, IXGBE_VTEIMS, adapter->eims_enable_mask); + mask = (IXGBE_EIMS_ENABLE_MASK & ~IXGBE_EIMS_RTX_QUEUE); + qmask = ~0; + + IXGBE_WRITE_REG(hw, IXGBE_VTEIMS, mask); + + if (queues) + ixgbevf_irq_enable_queues(adapter, qmask); + + if (flush) + IXGBE_WRITE_FLUSH(hw); } /** @@ -1067,14 +1320,29 @@ static void ixgbevf_configure_srrctl(struct ixgbevf_adapter *adapter, int index) srrctl = IXGBE_SRRCTL_DROP_EN; - srrctl |= IXGBE_SRRCTL_DESCTYPE_ADV_ONEBUF; + if (adapter->flags & IXGBE_FLAG_RX_PS_ENABLED) { + u16 bufsz = IXGBEVF_RXBUFFER_2048; + /* grow the amount we can receive on large page machines */ + if (bufsz < (PAGE_SIZE / 2)) + bufsz = (PAGE_SIZE / 2); + /* cap the bufsz at our largest descriptor size */ + bufsz = min((u16)IXGBEVF_MAX_RXBUFFER, bufsz); + + srrctl |= bufsz >> IXGBE_SRRCTL_BSIZEPKT_SHIFT; + srrctl |= IXGBE_SRRCTL_DESCTYPE_HDR_SPLIT_ALWAYS; + srrctl |= ((IXGBEVF_RX_HDR_SIZE << + IXGBE_SRRCTL_BSIZEHDRSIZE_SHIFT) & + IXGBE_SRRCTL_BSIZEHDR_MASK); + } else { + srrctl |= IXGBE_SRRCTL_DESCTYPE_ADV_ONEBUF; - if (rx_ring->rx_buf_len == MAXIMUM_ETHERNET_VLAN_SIZE) - srrctl |= IXGBEVF_RXBUFFER_2048 >> - IXGBE_SRRCTL_BSIZEPKT_SHIFT; - else - srrctl |= rx_ring->rx_buf_len >> - IXGBE_SRRCTL_BSIZEPKT_SHIFT; + if (rx_ring->rx_buf_len == MAXIMUM_ETHERNET_VLAN_SIZE) + srrctl |= IXGBEVF_RXBUFFER_2048 >> + IXGBE_SRRCTL_BSIZEPKT_SHIFT; + else + srrctl |= rx_ring->rx_buf_len >> + IXGBE_SRRCTL_BSIZEPKT_SHIFT; + } IXGBE_WRITE_REG(hw, IXGBE_VFSRRCTL(index), srrctl); } @@ -1094,12 +1362,36 @@ static void ixgbevf_configure_rx(struct ixgbevf_adapter *adapter) u32 rdlen; int rx_buf_len; - /* PSRTYPE must be initialized in 82599 */ - IXGBE_WRITE_REG(hw, IXGBE_VFPSRTYPE, 0); - if (netdev->mtu <= ETH_DATA_LEN) - rx_buf_len = MAXIMUM_ETHERNET_VLAN_SIZE; - else - rx_buf_len = ALIGN(max_frame, 1024); + /* Decide whether to use packet split mode or not */ + if (netdev->mtu > ETH_DATA_LEN) { + if (adapter->flags & IXGBE_FLAG_RX_PS_CAPABLE) + adapter->flags |= IXGBE_FLAG_RX_PS_ENABLED; + else + adapter->flags &= ~IXGBE_FLAG_RX_PS_ENABLED; + } else { + if (adapter->flags & IXGBE_FLAG_RX_1BUF_CAPABLE) + adapter->flags &= ~IXGBE_FLAG_RX_PS_ENABLED; + else + adapter->flags |= IXGBE_FLAG_RX_PS_ENABLED; + } + + /* Set the RX buffer length according to the mode */ + if (adapter->flags & IXGBE_FLAG_RX_PS_ENABLED) { + /* PSRTYPE must be initialized in 82599 */ + u32 psrtype = IXGBE_PSRTYPE_TCPHDR | + IXGBE_PSRTYPE_UDPHDR | + IXGBE_PSRTYPE_IPV4HDR | + IXGBE_PSRTYPE_IPV6HDR | + IXGBE_PSRTYPE_L2HDR; + IXGBE_WRITE_REG(hw, IXGBE_VFPSRTYPE, psrtype); + rx_buf_len = IXGBEVF_RX_HDR_SIZE; + } else { + IXGBE_WRITE_REG(hw, IXGBE_VFPSRTYPE, 0); + if (netdev->mtu <= ETH_DATA_LEN) + rx_buf_len = MAXIMUM_ETHERNET_VLAN_SIZE; + else + rx_buf_len = ALIGN(max_frame, 1024); + } rdlen = adapter->rx_ring[0].count * sizeof(union ixgbe_adv_rx_desc); /* Setup the HW Rx Head and Tail Descriptor Pointers and @@ -1210,8 +1502,15 @@ static void ixgbevf_napi_enable_all(struct ixgbevf_adapter *adapter) int q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS; for (q_idx = 0; q_idx < q_vectors; q_idx++) { + struct napi_struct *napi; q_vector = adapter->q_vector[q_idx]; - napi_enable(&q_vector->napi); + if (!q_vector->rxr_count) + continue; + napi = &q_vector->napi; + if (q_vector->rxr_count > 1) + napi->poll = &ixgbevf_clean_rxonly_many; + + napi_enable(napi); } } @@ -1223,6 +1522,8 @@ static void ixgbevf_napi_disable_all(struct ixgbevf_adapter *adapter) for (q_idx = 0; q_idx < q_vectors; q_idx++) { q_vector = adapter->q_vector[q_idx]; + if (!q_vector->rxr_count) + continue; napi_disable(&q_vector->napi); } } @@ -1366,6 +1667,10 @@ static void ixgbevf_up_complete(struct ixgbevf_adapter *adapter) ixgbevf_save_reset_stats(adapter); ixgbevf_init_last_counter_stats(adapter); + /* bring the link up in the watchdog, this could race with our first + * link up interrupt but shouldn't be a problem */ + adapter->flags |= IXGBE_FLAG_NEED_LINK_UPDATE; + adapter->link_check_timeout = jiffies; mod_timer(&adapter->watchdog_timer, jiffies); } @@ -1380,7 +1685,7 @@ void ixgbevf_up(struct ixgbevf_adapter *adapter) /* clear any pending interrupts, may auto mask */ IXGBE_READ_REG(hw, IXGBE_VTEICR); - ixgbevf_irq_enable(adapter); + ixgbevf_irq_enable(adapter, true, true); } /** @@ -1418,6 +1723,14 @@ static void ixgbevf_clean_rx_ring(struct ixgbevf_adapter *adapter, dev_kfree_skb(this); } while (skb); } + if (!rx_buffer_info->page) + continue; + dma_unmap_page(&pdev->dev, rx_buffer_info->page_dma, + PAGE_SIZE / 2, DMA_FROM_DEVICE); + rx_buffer_info->page_dma = 0; + put_page(rx_buffer_info->page); + rx_buffer_info->page = NULL; + rx_buffer_info->page_offset = 0; } size = sizeof(struct ixgbevf_rx_buffer) * rx_ring->count; @@ -1587,9 +1900,10 @@ static void ixgbevf_acquire_msix_vectors(struct ixgbevf_adapter *adapter, { int err, vector_threshold; - /* We'll want at least 2 (vector_threshold): - * 1) TxQ[0] + RxQ[0] handler - * 2) Other (Link Status Change, etc.) + /* We'll want at least 3 (vector_threshold): + * 1) TxQ[0] Cleanup + * 2) RxQ[0] Cleanup + * 3) Other (Link Status Change, etc.) */ vector_threshold = MIN_MSIX_COUNT; @@ -1628,8 +1942,8 @@ static void ixgbevf_acquire_msix_vectors(struct ixgbevf_adapter *adapter, } } -/** - * ixgbevf_set_num_queues - Allocate queues for device, feature dependent +/* + * ixgbevf_set_num_queues: Allocate queues for device, feature dependent * @adapter: board private structure to initialize * * This is the top level queue allocation routine. The order here is very @@ -1644,6 +1958,8 @@ static void ixgbevf_set_num_queues(struct ixgbevf_adapter *adapter) /* Start with base case */ adapter->num_rx_queues = 1; adapter->num_tx_queues = 1; + adapter->num_rx_pools = adapter->num_rx_queues; + adapter->num_rx_queues_per_pool = 1; } /** @@ -1704,12 +2020,10 @@ static int ixgbevf_set_interrupt_capability(struct ixgbevf_adapter *adapter) * It's easy to be greedy for MSI-X vectors, but it really * doesn't do us much good if we have a lot more vectors * than CPU's. So let's be conservative and only ask for - * (roughly) the same number of vectors as there are CPU's. - * The default is to use pairs of vectors. + * (roughly) twice the number of vectors as there are CPU's. */ - v_budget = max(adapter->num_rx_queues, adapter->num_tx_queues); - v_budget = min_t(int, v_budget, num_online_cpus()); - v_budget += NON_Q_VECTORS; + v_budget = min(adapter->num_rx_queues + adapter->num_tx_queues, + (int)(num_online_cpus() * 2)) + NON_Q_VECTORS; /* A failure in MSI-X entry allocation isn't fatal, but it does * mean we disable MSI-X capabilities of the adapter. */ @@ -1740,8 +2054,12 @@ static int ixgbevf_alloc_q_vectors(struct ixgbevf_adapter *adapter) { int q_idx, num_q_vectors; struct ixgbevf_q_vector *q_vector; + int napi_vectors; + int (*poll)(struct napi_struct *, int); num_q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS; + napi_vectors = adapter->num_rx_queues; + poll = &ixgbevf_clean_rxonly; for (q_idx = 0; q_idx < num_q_vectors; q_idx++) { q_vector = kzalloc(sizeof(struct ixgbevf_q_vector), GFP_KERNEL); @@ -1749,8 +2067,10 @@ static int ixgbevf_alloc_q_vectors(struct ixgbevf_adapter *adapter) goto err_out; q_vector->adapter = adapter; q_vector->v_idx = q_idx; - netif_napi_add(adapter->netdev, &q_vector->napi, - ixgbevf_poll, 64); + q_vector->eitr = adapter->eitr_param; + if (q_idx < napi_vectors) + netif_napi_add(adapter->netdev, &q_vector->napi, + (*poll), 64); adapter->q_vector[q_idx] = q_vector; } @@ -1897,13 +2217,20 @@ static int __devinit ixgbevf_sw_init(struct ixgbevf_adapter *adapter) } /* Enable dynamic interrupt throttling rates */ - adapter->rx_itr_setting = 1; - adapter->tx_itr_setting = 1; + adapter->eitr_param = 20000; + adapter->itr_setting = 1; + + /* set defaults for eitr in MegaBytes */ + adapter->eitr_low = 10; + adapter->eitr_high = 20; /* set default ring sizes */ adapter->tx_ring_count = IXGBEVF_DEFAULT_TXD; adapter->rx_ring_count = IXGBEVF_DEFAULT_RXD; + /* enable rx csum by default */ + adapter->flags |= IXGBE_FLAG_RX_CSUM_ENABLED; + set_bit(__IXGBEVF_DOWN, &adapter->state); return 0; @@ -1963,7 +2290,7 @@ static void ixgbevf_watchdog(unsigned long data) { struct ixgbevf_adapter *adapter = (struct ixgbevf_adapter *)data; struct ixgbe_hw *hw = &adapter->hw; - u32 eics = 0; + u64 eics = 0; int i; /* @@ -1977,11 +2304,11 @@ static void ixgbevf_watchdog(unsigned long data) /* get one bit for every active tx/rx interrupt vector */ for (i = 0; i < adapter->num_msix_vectors - NON_Q_VECTORS; i++) { struct ixgbevf_q_vector *qv = adapter->q_vector[i]; - if (qv->rx.ring || qv->tx.ring) - eics |= 1 << i; + if (qv->rxr_count || qv->txr_count) + eics |= (1 << i); } - IXGBE_WRITE_REG(hw, IXGBE_VTEICS, eics); + IXGBE_WRITE_REG(hw, IXGBE_VTEICS, (u32)eics); watchdog_short_circuit: schedule_work(&adapter->watchdog_task); @@ -2151,6 +2478,7 @@ int ixgbevf_setup_tx_resources(struct ixgbevf_adapter *adapter, tx_ring->next_to_use = 0; tx_ring->next_to_clean = 0; + tx_ring->work_limit = tx_ring->count; return 0; err: @@ -2354,7 +2682,7 @@ static int ixgbevf_open(struct net_device *netdev) if (err) goto err_req_irq; - ixgbevf_irq_enable(adapter); + ixgbevf_irq_enable(adapter, true, true); return 0; @@ -2762,30 +3090,11 @@ static int ixgbevf_xmit_frame(struct sk_buff *skb, struct net_device *netdev) unsigned int tx_flags = 0; u8 hdr_len = 0; int r_idx = 0, tso; - u16 count = TXD_USE_COUNT(skb_headlen(skb)); -#if PAGE_SIZE > IXGBE_MAX_DATA_PER_TXD - unsigned short f; -#endif + int count = 0; - tx_ring = &adapter->tx_ring[r_idx]; + unsigned int f; - /* - * need: 1 descriptor per page * PAGE_SIZE/IXGBE_MAX_DATA_PER_TXD, - * + 1 desc for skb_headlen/IXGBE_MAX_DATA_PER_TXD, - * + 2 desc gap to keep tail from touching head, - * + 1 desc for context descriptor, - * otherwise try next time - */ -#if PAGE_SIZE > IXGBE_MAX_DATA_PER_TXD - for (f = 0; f < skb_shinfo(skb)->nr_frags; f++) - count += TXD_USE_COUNT(skb_shinfo(skb)->frags[f].size); -#else - count += skb_shinfo(skb)->nr_frags; -#endif - if (ixgbevf_maybe_stop_tx(netdev, tx_ring, count + 3)) { - adapter->tx_busy++; - return NETDEV_TX_BUSY; - } + tx_ring = &adapter->tx_ring[r_idx]; if (vlan_tx_tag_present(skb)) { tx_flags |= vlan_tx_tag_get(skb); @@ -2793,6 +3102,21 @@ static int ixgbevf_xmit_frame(struct sk_buff *skb, struct net_device *netdev) tx_flags |= IXGBE_TX_FLAGS_VLAN; } + /* four things can cause us to need a context descriptor */ + if (skb_is_gso(skb) || + (skb->ip_summed == CHECKSUM_PARTIAL) || + (tx_flags & IXGBE_TX_FLAGS_VLAN)) + count++; + + count += TXD_USE_COUNT(skb_headlen(skb)); + for (f = 0; f < skb_shinfo(skb)->nr_frags; f++) + count += TXD_USE_COUNT(skb_frag_size(&skb_shinfo(skb)->frags[f])); + + if (ixgbevf_maybe_stop_tx(netdev, tx_ring, count)) { + adapter->tx_busy++; + return NETDEV_TX_BUSY; + } + first = tx_ring->next_to_use; if (skb->protocol == htons(ETH_P_IP)) @@ -2896,7 +3220,9 @@ static void ixgbevf_shutdown(struct pci_dev *pdev) ixgbevf_free_all_rx_resources(adapter); } +#ifdef CONFIG_PM pci_save_state(pdev); +#endif pci_disable_device(pdev); } @@ -2939,6 +3265,19 @@ static struct rtnl_link_stats64 *ixgbevf_get_stats(struct net_device *netdev, return stats; } +static int ixgbevf_set_features(struct net_device *netdev, + netdev_features_t features) +{ + struct ixgbevf_adapter *adapter = netdev_priv(netdev); + + if (features & NETIF_F_RXCSUM) + adapter->flags |= IXGBE_FLAG_RX_CSUM_ENABLED; + else + adapter->flags &= ~IXGBE_FLAG_RX_CSUM_ENABLED; + + return 0; +} + static const struct net_device_ops ixgbe_netdev_ops = { .ndo_open = ixgbevf_open, .ndo_stop = ixgbevf_close, @@ -2951,6 +3290,7 @@ static const struct net_device_ops ixgbe_netdev_ops = { .ndo_tx_timeout = ixgbevf_tx_timeout, .ndo_vlan_rx_add_vid = ixgbevf_vlan_rx_add_vid, .ndo_vlan_rx_kill_vid = ixgbevf_vlan_rx_kill_vid, + .ndo_set_features = ixgbevf_set_features, }; static void ixgbevf_assign_netdev_ops(struct net_device *dev) @@ -3010,8 +3350,12 @@ static int __devinit ixgbevf_probe(struct pci_dev *pdev, pci_set_master(pdev); +#ifdef HAVE_TX_MQ netdev = alloc_etherdev_mq(sizeof(struct ixgbevf_adapter), MAX_TX_QUEUES); +#else + netdev = alloc_etherdev(sizeof(struct ixgbevf_adapter)); +#endif if (!netdev) { err = -ENOMEM; goto err_alloc_etherdev; @@ -3052,6 +3396,10 @@ static int __devinit ixgbevf_probe(struct pci_dev *pdev, memcpy(&hw->mbx.ops, &ixgbevf_mbx_ops, sizeof(struct ixgbe_mbx_operations)); + adapter->flags &= ~IXGBE_FLAG_RX_PS_CAPABLE; + adapter->flags &= ~IXGBE_FLAG_RX_PS_ENABLED; + adapter->flags |= IXGBE_FLAG_RX_1BUF_CAPABLE; + /* setup the private structure */ err = ixgbevf_sw_init(adapter); if (err) @@ -3110,6 +3458,8 @@ static int __devinit ixgbevf_probe(struct pci_dev *pdev, if (err) goto err_register; + adapter->netdev_registered = true; + netif_carrier_off(netdev); ixgbevf_init_last_counter_stats(adapter); @@ -3119,6 +3469,8 @@ static int __devinit ixgbevf_probe(struct pci_dev *pdev, hw_dbg(hw, "MAC: %d\n", hw->mac.type); + hw_dbg(hw, "LRO is disabled\n"); + hw_dbg(hw, "Intel(R) 82599 Virtual Function\n"); cards_found++; return 0; @@ -3158,8 +3510,10 @@ static void __devexit ixgbevf_remove(struct pci_dev *pdev) cancel_work_sync(&adapter->reset_task); cancel_work_sync(&adapter->watchdog_task); - if (netdev->reg_state == NETREG_REGISTERED) + if (adapter->netdev_registered) { unregister_netdev(netdev); + adapter->netdev_registered = false; + } ixgbevf_reset_interrupt_capability(adapter); diff --git a/trunk/drivers/net/ethernet/lantiq_etop.c b/trunk/drivers/net/ethernet/lantiq_etop.c index 003c5bc7189f..5dc9cbd51514 100644 --- a/trunk/drivers/net/ethernet/lantiq_etop.c +++ b/trunk/drivers/net/ethernet/lantiq_etop.c @@ -149,6 +149,7 @@ ltq_etop_hw_receive(struct ltq_etop_chan *ch) spin_unlock_irqrestore(&priv->lock, flags); skb_put(skb, len); + skb->dev = ch->netdev; skb->protocol = eth_type_trans(skb, ch->netdev); netif_receive_skb(skb); } @@ -645,7 +646,7 @@ ltq_etop_init(struct net_device *dev) memcpy(&mac, &priv->pldata->mac, sizeof(struct sockaddr)); if (!is_valid_ether_addr(mac.sa_data)) { pr_warn("etop: invalid MAC, using random\n"); - eth_random_addr(mac.sa_data); + random_ether_addr(mac.sa_data); random_mac = true; } diff --git a/trunk/drivers/net/ethernet/marvell/sky2.c b/trunk/drivers/net/ethernet/marvell/sky2.c index 2b0748dba8b8..28a54451a3e5 100644 --- a/trunk/drivers/net/ethernet/marvell/sky2.c +++ b/trunk/drivers/net/ethernet/marvell/sky2.c @@ -141,7 +141,6 @@ static DEFINE_PCI_DEVICE_TABLE(sky2_id_table) = { { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4370) }, /* 88E8075 */ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4380) }, /* 88E8057 */ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4381) }, /* 88E8059 */ - { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4382) }, /* 88E8079 */ { 0 } }; @@ -3080,10 +3079,8 @@ static irqreturn_t sky2_intr(int irq, void *dev_id) /* Reading this mask interrupts as side effect */ status = sky2_read32(hw, B0_Y2_SP_ISRC2); - if (status == 0 || status == ~0) { - sky2_write32(hw, B0_Y2_SP_ICR, 2); + if (status == 0 || status == ~0) return IRQ_NONE; - } prefetch(&hw->st_le[hw->st_idx]); @@ -3352,17 +3349,6 @@ static void sky2_reset(struct sky2_hw *hw) sky2_pci_write16(hw, pdev->pcie_cap + PCI_EXP_LNKCTL, reg); - if (hw->chip_id == CHIP_ID_YUKON_PRM && - hw->chip_rev == CHIP_REV_YU_PRM_A0) { - /* change PHY Interrupt polarity to low active */ - reg = sky2_read16(hw, GPHY_CTRL); - sky2_write16(hw, GPHY_CTRL, reg | GPC_INTPOL); - - /* adapt HW for low active PHY Interrupt */ - reg = sky2_read16(hw, Y2_CFG_SPC + PCI_LDO_CTRL); - sky2_write16(hw, Y2_CFG_SPC + PCI_LDO_CTRL, reg | PHY_M_UNDOC1); - } - sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF); /* re-enable PEX PM in PEX PHY debug reg. 8 (clear bit 12) */ @@ -4885,7 +4871,7 @@ static const char *sky2_name(u8 chipid, char *buf, int sz) "UL 2", /* 0xba */ "Unknown", /* 0xbb */ "Optima", /* 0xbc */ - "OptimaEEE", /* 0xbd */ + "Optima Prime", /* 0xbd */ "Optima 2", /* 0xbe */ }; diff --git a/trunk/drivers/net/ethernet/marvell/sky2.h b/trunk/drivers/net/ethernet/marvell/sky2.h index 615ac63ea860..3c896ce80b71 100644 --- a/trunk/drivers/net/ethernet/marvell/sky2.h +++ b/trunk/drivers/net/ethernet/marvell/sky2.h @@ -23,7 +23,6 @@ enum { PSM_CONFIG_REG3 = 0x164, PSM_CONFIG_REG4 = 0x168, - PCI_LDO_CTRL = 0xbc, }; /* Yukon-2 */ @@ -587,10 +586,6 @@ enum yukon_supr_rev { CHIP_REV_YU_SU_B1 = 3, }; -enum yukon_prm_rev { - CHIP_REV_YU_PRM_Z1 = 1, - CHIP_REV_YU_PRM_A0 = 2, -}; /* B2_Y2_CLK_GATE 8 bit Clock Gating (Yukon-2 only) */ enum { diff --git a/trunk/drivers/net/ethernet/mellanox/mlx4/cmd.c b/trunk/drivers/net/ethernet/mellanox/mlx4/cmd.c index 7e94987d030c..842c8ce9494e 100644 --- a/trunk/drivers/net/ethernet/mellanox/mlx4/cmd.c +++ b/trunk/drivers/net/ethernet/mellanox/mlx4/cmd.c @@ -1080,25 +1080,6 @@ static struct mlx4_cmd_info cmd_info[] = { .verify = NULL, .wrapper = NULL }, - /* flow steering commands */ - { - .opcode = MLX4_QP_FLOW_STEERING_ATTACH, - .has_inbox = true, - .has_outbox = false, - .out_is_imm = true, - .encode_slave_id = false, - .verify = NULL, - .wrapper = mlx4_QP_FLOW_STEERING_ATTACH_wrapper - }, - { - .opcode = MLX4_QP_FLOW_STEERING_DETACH, - .has_inbox = false, - .has_outbox = false, - .out_is_imm = false, - .encode_slave_id = false, - .verify = NULL, - .wrapper = mlx4_QP_FLOW_STEERING_DETACH_wrapper - }, }; static int mlx4_master_process_vhcr(struct mlx4_dev *dev, int slave, diff --git a/trunk/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c b/trunk/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c index dd6a77b21149..72901ce2b088 100644 --- a/trunk/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c +++ b/trunk/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c @@ -38,10 +38,6 @@ #include "mlx4_en.h" #include "en_port.h" -#define EN_ETHTOOL_QP_ATTACH (1ull << 63) -#define EN_ETHTOOL_MAC_MASK 0xffffffffffffULL -#define EN_ETHTOOL_SHORT_MASK cpu_to_be16(0xffff) -#define EN_ETHTOOL_WORD_MASK cpu_to_be32(0xffffffff) static void mlx4_en_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo) @@ -603,369 +599,16 @@ static int mlx4_en_set_rxfh_indir(struct net_device *dev, return err; } -#define all_zeros_or_all_ones(field) \ - ((field) == 0 || (field) == (__force typeof(field))-1) - -static int mlx4_en_validate_flow(struct net_device *dev, - struct ethtool_rxnfc *cmd) -{ - struct ethtool_usrip4_spec *l3_mask; - struct ethtool_tcpip4_spec *l4_mask; - struct ethhdr *eth_mask; - u64 full_mac = ~0ull; - u64 zero_mac = 0; - - if (cmd->fs.location >= MAX_NUM_OF_FS_RULES) - return -EINVAL; - - switch (cmd->fs.flow_type & ~FLOW_EXT) { - case TCP_V4_FLOW: - case UDP_V4_FLOW: - if (cmd->fs.m_u.tcp_ip4_spec.tos) - return -EINVAL; - l4_mask = &cmd->fs.m_u.tcp_ip4_spec; - /* don't allow mask which isn't all 0 or 1 */ - if (!all_zeros_or_all_ones(l4_mask->ip4src) || - !all_zeros_or_all_ones(l4_mask->ip4dst) || - !all_zeros_or_all_ones(l4_mask->psrc) || - !all_zeros_or_all_ones(l4_mask->pdst)) - return -EINVAL; - break; - case IP_USER_FLOW: - l3_mask = &cmd->fs.m_u.usr_ip4_spec; - if (l3_mask->l4_4_bytes || l3_mask->tos || l3_mask->proto || - cmd->fs.h_u.usr_ip4_spec.ip_ver != ETH_RX_NFC_IP4 || - (!l3_mask->ip4src && !l3_mask->ip4dst) || - !all_zeros_or_all_ones(l3_mask->ip4src) || - !all_zeros_or_all_ones(l3_mask->ip4dst)) - return -EINVAL; - break; - case ETHER_FLOW: - eth_mask = &cmd->fs.m_u.ether_spec; - /* source mac mask must not be set */ - if (memcmp(eth_mask->h_source, &zero_mac, ETH_ALEN)) - return -EINVAL; - - /* dest mac mask must be ff:ff:ff:ff:ff:ff */ - if (memcmp(eth_mask->h_dest, &full_mac, ETH_ALEN)) - return -EINVAL; - - if (!all_zeros_or_all_ones(eth_mask->h_proto)) - return -EINVAL; - break; - default: - return -EINVAL; - } - - if ((cmd->fs.flow_type & FLOW_EXT)) { - if (cmd->fs.m_ext.vlan_etype || - !(cmd->fs.m_ext.vlan_tci == 0 || - cmd->fs.m_ext.vlan_tci == cpu_to_be16(0xfff))) - return -EINVAL; - } - - return 0; -} - -static int add_ip_rule(struct mlx4_en_priv *priv, - struct ethtool_rxnfc *cmd, - struct list_head *list_h) -{ - struct mlx4_spec_list *spec_l3; - struct ethtool_usrip4_spec *l3_mask = &cmd->fs.m_u.usr_ip4_spec; - - spec_l3 = kzalloc(sizeof *spec_l3, GFP_KERNEL); - if (!spec_l3) { - en_err(priv, "Fail to alloc ethtool rule.\n"); - return -ENOMEM; - } - - spec_l3->id = MLX4_NET_TRANS_RULE_ID_IPV4; - spec_l3->ipv4.src_ip = cmd->fs.h_u.usr_ip4_spec.ip4src; - if (l3_mask->ip4src) - spec_l3->ipv4.src_ip_msk = EN_ETHTOOL_WORD_MASK; - spec_l3->ipv4.dst_ip = cmd->fs.h_u.usr_ip4_spec.ip4dst; - if (l3_mask->ip4dst) - spec_l3->ipv4.dst_ip_msk = EN_ETHTOOL_WORD_MASK; - list_add_tail(&spec_l3->list, list_h); - - return 0; -} - -static int add_tcp_udp_rule(struct mlx4_en_priv *priv, - struct ethtool_rxnfc *cmd, - struct list_head *list_h, int proto) -{ - struct mlx4_spec_list *spec_l3; - struct mlx4_spec_list *spec_l4; - struct ethtool_tcpip4_spec *l4_mask = &cmd->fs.m_u.tcp_ip4_spec; - - spec_l3 = kzalloc(sizeof *spec_l3, GFP_KERNEL); - spec_l4 = kzalloc(sizeof *spec_l4, GFP_KERNEL); - if (!spec_l4 || !spec_l3) { - en_err(priv, "Fail to alloc ethtool rule.\n"); - kfree(spec_l3); - kfree(spec_l4); - return -ENOMEM; - } - - spec_l3->id = MLX4_NET_TRANS_RULE_ID_IPV4; - - if (proto == TCP_V4_FLOW) { - spec_l4->id = MLX4_NET_TRANS_RULE_ID_TCP; - spec_l3->ipv4.src_ip = cmd->fs.h_u.tcp_ip4_spec.ip4src; - spec_l3->ipv4.dst_ip = cmd->fs.h_u.tcp_ip4_spec.ip4dst; - spec_l4->tcp_udp.src_port = cmd->fs.h_u.tcp_ip4_spec.psrc; - spec_l4->tcp_udp.dst_port = cmd->fs.h_u.tcp_ip4_spec.pdst; - } else { - spec_l4->id = MLX4_NET_TRANS_RULE_ID_UDP; - spec_l3->ipv4.src_ip = cmd->fs.h_u.udp_ip4_spec.ip4src; - spec_l3->ipv4.dst_ip = cmd->fs.h_u.udp_ip4_spec.ip4dst; - spec_l4->tcp_udp.src_port = cmd->fs.h_u.udp_ip4_spec.psrc; - spec_l4->tcp_udp.dst_port = cmd->fs.h_u.udp_ip4_spec.pdst; - } - - if (l4_mask->ip4src) - spec_l3->ipv4.src_ip_msk = EN_ETHTOOL_WORD_MASK; - if (l4_mask->ip4dst) - spec_l3->ipv4.dst_ip_msk = EN_ETHTOOL_WORD_MASK; - - if (l4_mask->psrc) - spec_l4->tcp_udp.src_port_msk = EN_ETHTOOL_SHORT_MASK; - if (l4_mask->pdst) - spec_l4->tcp_udp.dst_port_msk = EN_ETHTOOL_SHORT_MASK; - - list_add_tail(&spec_l3->list, list_h); - list_add_tail(&spec_l4->list, list_h); - - return 0; -} - -static int mlx4_en_ethtool_to_net_trans_rule(struct net_device *dev, - struct ethtool_rxnfc *cmd, - struct list_head *rule_list_h) -{ - int err; - u64 mac; - __be64 be_mac; - struct ethhdr *eth_spec; - struct mlx4_en_priv *priv = netdev_priv(dev); - struct mlx4_spec_list *spec_l2; - __be64 mac_msk = cpu_to_be64(EN_ETHTOOL_MAC_MASK << 16); - - err = mlx4_en_validate_flow(dev, cmd); - if (err) - return err; - - spec_l2 = kzalloc(sizeof *spec_l2, GFP_KERNEL); - if (!spec_l2) - return -ENOMEM; - - mac = priv->mac & EN_ETHTOOL_MAC_MASK; - be_mac = cpu_to_be64(mac << 16); - - spec_l2->id = MLX4_NET_TRANS_RULE_ID_ETH; - memcpy(spec_l2->eth.dst_mac_msk, &mac_msk, ETH_ALEN); - if ((cmd->fs.flow_type & ~FLOW_EXT) != ETHER_FLOW) - memcpy(spec_l2->eth.dst_mac, &be_mac, ETH_ALEN); - - if ((cmd->fs.flow_type & FLOW_EXT) && cmd->fs.m_ext.vlan_tci) { - spec_l2->eth.vlan_id = cmd->fs.h_ext.vlan_tci; - spec_l2->eth.vlan_id_msk = cpu_to_be16(0xfff); - } - - list_add_tail(&spec_l2->list, rule_list_h); - - switch (cmd->fs.flow_type & ~FLOW_EXT) { - case ETHER_FLOW: - eth_spec = &cmd->fs.h_u.ether_spec; - memcpy(&spec_l2->eth.dst_mac, eth_spec->h_dest, ETH_ALEN); - spec_l2->eth.ether_type = eth_spec->h_proto; - if (eth_spec->h_proto) - spec_l2->eth.ether_type_enable = 1; - break; - case IP_USER_FLOW: - err = add_ip_rule(priv, cmd, rule_list_h); - break; - case TCP_V4_FLOW: - err = add_tcp_udp_rule(priv, cmd, rule_list_h, TCP_V4_FLOW); - break; - case UDP_V4_FLOW: - err = add_tcp_udp_rule(priv, cmd, rule_list_h, UDP_V4_FLOW); - break; - } - - return err; -} - -static int mlx4_en_flow_replace(struct net_device *dev, - struct ethtool_rxnfc *cmd) -{ - int err; - struct mlx4_en_priv *priv = netdev_priv(dev); - struct ethtool_flow_id *loc_rule; - struct mlx4_spec_list *spec, *tmp_spec; - u32 qpn; - u64 reg_id; - - struct mlx4_net_trans_rule rule = { - .queue_mode = MLX4_NET_TRANS_Q_FIFO, - .exclusive = 0, - .allow_loopback = 1, - .promisc_mode = MLX4_FS_PROMISC_NONE, - }; - - rule.port = priv->port; - rule.priority = MLX4_DOMAIN_ETHTOOL | cmd->fs.location; - INIT_LIST_HEAD(&rule.list); - - /* Allow direct QP attaches if the EN_ETHTOOL_QP_ATTACH flag is set */ - if (cmd->fs.ring_cookie == RX_CLS_FLOW_DISC) - qpn = priv->drop_qp.qpn; - else if (cmd->fs.ring_cookie & EN_ETHTOOL_QP_ATTACH) { - qpn = cmd->fs.ring_cookie & (EN_ETHTOOL_QP_ATTACH - 1); - } else { - if (cmd->fs.ring_cookie >= priv->rx_ring_num) { - en_warn(priv, "rxnfc: RX ring (%llu) doesn't exist.\n", - cmd->fs.ring_cookie); - return -EINVAL; - } - qpn = priv->rss_map.qps[cmd->fs.ring_cookie].qpn; - if (!qpn) { - en_warn(priv, "rxnfc: RX ring (%llu) is inactive.\n", - cmd->fs.ring_cookie); - return -EINVAL; - } - } - rule.qpn = qpn; - err = mlx4_en_ethtool_to_net_trans_rule(dev, cmd, &rule.list); - if (err) - goto out_free_list; - - loc_rule = &priv->ethtool_rules[cmd->fs.location]; - if (loc_rule->id) { - err = mlx4_flow_detach(priv->mdev->dev, loc_rule->id); - if (err) { - en_err(priv, "Fail to detach network rule at location %d. registration id = %llx\n", - cmd->fs.location, loc_rule->id); - goto out_free_list; - } - loc_rule->id = 0; - memset(&loc_rule->flow_spec, 0, - sizeof(struct ethtool_rx_flow_spec)); - } - err = mlx4_flow_attach(priv->mdev->dev, &rule, ®_id); - if (err) { - en_err(priv, "Fail to attach network rule at location %d.\n", - cmd->fs.location); - goto out_free_list; - } - loc_rule->id = reg_id; - memcpy(&loc_rule->flow_spec, &cmd->fs, - sizeof(struct ethtool_rx_flow_spec)); - -out_free_list: - list_for_each_entry_safe(spec, tmp_spec, &rule.list, list) { - list_del(&spec->list); - kfree(spec); - } - return err; -} - -static int mlx4_en_flow_detach(struct net_device *dev, - struct ethtool_rxnfc *cmd) -{ - int err = 0; - struct ethtool_flow_id *rule; - struct mlx4_en_priv *priv = netdev_priv(dev); - - if (cmd->fs.location >= MAX_NUM_OF_FS_RULES) - return -EINVAL; - - rule = &priv->ethtool_rules[cmd->fs.location]; - if (!rule->id) { - err = -ENOENT; - goto out; - } - - err = mlx4_flow_detach(priv->mdev->dev, rule->id); - if (err) { - en_err(priv, "Fail to detach network rule at location %d. registration id = 0x%llx\n", - cmd->fs.location, rule->id); - goto out; - } - rule->id = 0; - memset(&rule->flow_spec, 0, sizeof(struct ethtool_rx_flow_spec)); -out: - return err; - -} - -static int mlx4_en_get_flow(struct net_device *dev, struct ethtool_rxnfc *cmd, - int loc) -{ - int err = 0; - struct ethtool_flow_id *rule; - struct mlx4_en_priv *priv = netdev_priv(dev); - - if (loc < 0 || loc >= MAX_NUM_OF_FS_RULES) - return -EINVAL; - - rule = &priv->ethtool_rules[loc]; - if (rule->id) - memcpy(&cmd->fs, &rule->flow_spec, - sizeof(struct ethtool_rx_flow_spec)); - else - err = -ENOENT; - - return err; -} - -static int mlx4_en_get_num_flows(struct mlx4_en_priv *priv) -{ - - int i, res = 0; - for (i = 0; i < MAX_NUM_OF_FS_RULES; i++) { - if (priv->ethtool_rules[i].id) - res++; - } - return res; - -} - static int mlx4_en_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd, u32 *rule_locs) { struct mlx4_en_priv *priv = netdev_priv(dev); - struct mlx4_en_dev *mdev = priv->mdev; int err = 0; - int i = 0, priority = 0; - - if ((cmd->cmd == ETHTOOL_GRXCLSRLCNT || - cmd->cmd == ETHTOOL_GRXCLSRULE || - cmd->cmd == ETHTOOL_GRXCLSRLALL) && - mdev->dev->caps.steering_mode != MLX4_STEERING_MODE_DEVICE_MANAGED) - return -EINVAL; switch (cmd->cmd) { case ETHTOOL_GRXRINGS: cmd->data = priv->rx_ring_num; break; - case ETHTOOL_GRXCLSRLCNT: - cmd->rule_cnt = mlx4_en_get_num_flows(priv); - break; - case ETHTOOL_GRXCLSRULE: - err = mlx4_en_get_flow(dev, cmd, cmd->fs.location); - break; - case ETHTOOL_GRXCLSRLALL: - while ((!err || err == -ENOENT) && priority < cmd->rule_cnt) { - err = mlx4_en_get_flow(dev, cmd, i); - if (!err) - rule_locs[priority++] = i; - i++; - } - err = 0; - break; default: err = -EOPNOTSUPP; break; @@ -974,30 +617,6 @@ static int mlx4_en_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd, return err; } -static int mlx4_en_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd) -{ - int err = 0; - struct mlx4_en_priv *priv = netdev_priv(dev); - struct mlx4_en_dev *mdev = priv->mdev; - - if (mdev->dev->caps.steering_mode != MLX4_STEERING_MODE_DEVICE_MANAGED) - return -EINVAL; - - switch (cmd->cmd) { - case ETHTOOL_SRXCLSRLINS: - err = mlx4_en_flow_replace(dev, cmd); - break; - case ETHTOOL_SRXCLSRLDEL: - err = mlx4_en_flow_detach(dev, cmd); - break; - default: - en_warn(priv, "Unsupported ethtool command. (%d)\n", cmd->cmd); - return -EINVAL; - } - - return err; -} - const struct ethtool_ops mlx4_en_ethtool_ops = { .get_drvinfo = mlx4_en_get_drvinfo, .get_settings = mlx4_en_get_settings, @@ -1018,7 +637,6 @@ const struct ethtool_ops mlx4_en_ethtool_ops = { .get_ringparam = mlx4_en_get_ringparam, .set_ringparam = mlx4_en_set_ringparam, .get_rxnfc = mlx4_en_get_rxnfc, - .set_rxnfc = mlx4_en_set_rxnfc, .get_rxfh_indir_size = mlx4_en_get_rxfh_indir_size, .get_rxfh_indir = mlx4_en_get_rxfh_indir, .set_rxfh_indir = mlx4_en_set_rxfh_indir, diff --git a/trunk/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/trunk/drivers/net/ethernet/mellanox/mlx4/en_netdev.c index 4ce5ca81a010..073b85b45fc5 100644 --- a/trunk/drivers/net/ethernet/mellanox/mlx4/en_netdev.c +++ b/trunk/drivers/net/ethernet/mellanox/mlx4/en_netdev.c @@ -170,81 +170,33 @@ static void mlx4_en_do_set_mac(struct work_struct *work) static void mlx4_en_clear_list(struct net_device *dev) { struct mlx4_en_priv *priv = netdev_priv(dev); - struct mlx4_en_mc_list *tmp, *mc_to_del; - list_for_each_entry_safe(mc_to_del, tmp, &priv->mc_list, list) { - list_del(&mc_to_del->list); - kfree(mc_to_del); - } + kfree(priv->mc_addrs); + priv->mc_addrs = NULL; + priv->mc_addrs_cnt = 0; } static void mlx4_en_cache_mclist(struct net_device *dev) { struct mlx4_en_priv *priv = netdev_priv(dev); struct netdev_hw_addr *ha; - struct mlx4_en_mc_list *tmp; + char *mc_addrs; + int mc_addrs_cnt = netdev_mc_count(dev); + int i; - mlx4_en_clear_list(dev); - netdev_for_each_mc_addr(ha, dev) { - tmp = kzalloc(sizeof(struct mlx4_en_mc_list), GFP_ATOMIC); - if (!tmp) { - en_err(priv, "failed to allocate multicast list\n"); - mlx4_en_clear_list(dev); - return; - } - memcpy(tmp->addr, ha->addr, ETH_ALEN); - list_add_tail(&tmp->list, &priv->mc_list); + mc_addrs = kmalloc(mc_addrs_cnt * ETH_ALEN, GFP_ATOMIC); + if (!mc_addrs) { + en_err(priv, "failed to allocate multicast list\n"); + return; } + i = 0; + netdev_for_each_mc_addr(ha, dev) + memcpy(mc_addrs + i++ * ETH_ALEN, ha->addr, ETH_ALEN); + mlx4_en_clear_list(dev); + priv->mc_addrs = mc_addrs; + priv->mc_addrs_cnt = mc_addrs_cnt; } -static void update_mclist_flags(struct mlx4_en_priv *priv, - struct list_head *dst, - struct list_head *src) -{ - struct mlx4_en_mc_list *dst_tmp, *src_tmp, *new_mc; - bool found; - - /* Find all the entries that should be removed from dst, - * These are the entries that are not found in src - */ - list_for_each_entry(dst_tmp, dst, list) { - found = false; - list_for_each_entry(src_tmp, src, list) { - if (!memcmp(dst_tmp->addr, src_tmp->addr, ETH_ALEN)) { - found = true; - break; - } - } - if (!found) - dst_tmp->action = MCLIST_REM; - } - - /* Add entries that exist in src but not in dst - * mark them as need to add - */ - list_for_each_entry(src_tmp, src, list) { - found = false; - list_for_each_entry(dst_tmp, dst, list) { - if (!memcmp(dst_tmp->addr, src_tmp->addr, ETH_ALEN)) { - dst_tmp->action = MCLIST_NONE; - found = true; - break; - } - } - if (!found) { - new_mc = kmalloc(sizeof(struct mlx4_en_mc_list), - GFP_KERNEL); - if (!new_mc) { - en_err(priv, "Failed to allocate current multicast list\n"); - return; - } - memcpy(new_mc, src_tmp, - sizeof(struct mlx4_en_mc_list)); - new_mc->action = MCLIST_ADD; - list_add_tail(&new_mc->list, dst); - } - } -} static void mlx4_en_set_multicast(struct net_device *dev) { @@ -262,10 +214,9 @@ static void mlx4_en_do_set_multicast(struct work_struct *work) mcast_task); struct mlx4_en_dev *mdev = priv->mdev; struct net_device *dev = priv->dev; - struct mlx4_en_mc_list *mclist, *tmp; u64 mcast_addr = 0; u8 mc_list[16] = {0}; - int err = 0; + int err; mutex_lock(&mdev->state_lock); if (!mdev->device_up) { @@ -300,46 +251,16 @@ static void mlx4_en_do_set_multicast(struct work_struct *work) priv->flags |= MLX4_EN_FLAG_PROMISC; /* Enable promiscouos mode */ - switch (mdev->dev->caps.steering_mode) { - case MLX4_STEERING_MODE_DEVICE_MANAGED: - err = mlx4_flow_steer_promisc_add(mdev->dev, - priv->port, - priv->base_qpn, - MLX4_FS_PROMISC_UPLINK); - if (err) - en_err(priv, "Failed enabling promiscuous mode\n"); - priv->flags |= MLX4_EN_FLAG_MC_PROMISC; - break; - - case MLX4_STEERING_MODE_B0: - err = mlx4_unicast_promisc_add(mdev->dev, - priv->base_qpn, + if (!(mdev->dev->caps.flags & + MLX4_DEV_CAP_FLAG_VEP_UC_STEER)) + err = mlx4_SET_PORT_qpn_calc(mdev->dev, priv->port, + priv->base_qpn, 1); + else + err = mlx4_unicast_promisc_add(mdev->dev, priv->base_qpn, priv->port); - if (err) - en_err(priv, "Failed enabling unicast promiscuous mode\n"); - - /* Add the default qp number as multicast - * promisc - */ - if (!(priv->flags & MLX4_EN_FLAG_MC_PROMISC)) { - err = mlx4_multicast_promisc_add(mdev->dev, - priv->base_qpn, - priv->port); - if (err) - en_err(priv, "Failed enabling multicast promiscuous mode\n"); - priv->flags |= MLX4_EN_FLAG_MC_PROMISC; - } - break; - - case MLX4_STEERING_MODE_A0: - err = mlx4_SET_PORT_qpn_calc(mdev->dev, - priv->port, - priv->base_qpn, - 1); - if (err) - en_err(priv, "Failed enabling promiscuous mode\n"); - break; - } + if (err) + en_err(priv, "Failed enabling " + "promiscuous mode\n"); /* Disable port multicast filter (unconditionally) */ err = mlx4_SET_MCAST_FLTR(mdev->dev, priv->port, 0, @@ -348,6 +269,15 @@ static void mlx4_en_do_set_multicast(struct work_struct *work) en_err(priv, "Failed disabling " "multicast filter\n"); + /* Add the default qp number as multicast promisc */ + if (!(priv->flags & MLX4_EN_FLAG_MC_PROMISC)) { + err = mlx4_multicast_promisc_add(mdev->dev, priv->base_qpn, + priv->port); + if (err) + en_err(priv, "Failed entering multicast promisc mode\n"); + priv->flags |= MLX4_EN_FLAG_MC_PROMISC; + } + /* Disable port VLAN filter */ err = mlx4_SET_VLAN_FLTR(mdev->dev, priv); if (err) @@ -366,40 +296,22 @@ static void mlx4_en_do_set_multicast(struct work_struct *work) priv->flags &= ~MLX4_EN_FLAG_PROMISC; /* Disable promiscouos mode */ - switch (mdev->dev->caps.steering_mode) { - case MLX4_STEERING_MODE_DEVICE_MANAGED: - err = mlx4_flow_steer_promisc_remove(mdev->dev, - priv->port, - MLX4_FS_PROMISC_UPLINK); - if (err) - en_err(priv, "Failed disabling promiscuous mode\n"); - priv->flags &= ~MLX4_EN_FLAG_MC_PROMISC; - break; - - case MLX4_STEERING_MODE_B0: - err = mlx4_unicast_promisc_remove(mdev->dev, - priv->base_qpn, + if (!(mdev->dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER)) + err = mlx4_SET_PORT_qpn_calc(mdev->dev, priv->port, + priv->base_qpn, 0); + else + err = mlx4_unicast_promisc_remove(mdev->dev, priv->base_qpn, priv->port); - if (err) - en_err(priv, "Failed disabling unicast promiscuous mode\n"); - /* Disable Multicast promisc */ - if (priv->flags & MLX4_EN_FLAG_MC_PROMISC) { - err = mlx4_multicast_promisc_remove(mdev->dev, - priv->base_qpn, - priv->port); - if (err) - en_err(priv, "Failed disabling multicast promiscuous mode\n"); - priv->flags &= ~MLX4_EN_FLAG_MC_PROMISC; - } - break; + if (err) + en_err(priv, "Failed disabling promiscuous mode\n"); - case MLX4_STEERING_MODE_A0: - err = mlx4_SET_PORT_qpn_calc(mdev->dev, - priv->port, - priv->base_qpn, 0); + /* Disable Multicast promisc */ + if (priv->flags & MLX4_EN_FLAG_MC_PROMISC) { + err = mlx4_multicast_promisc_remove(mdev->dev, priv->base_qpn, + priv->port); if (err) - en_err(priv, "Failed disabling promiscuous mode\n"); - break; + en_err(priv, "Failed disabling multicast promiscuous mode\n"); + priv->flags &= ~MLX4_EN_FLAG_MC_PROMISC; } /* Enable port VLAN filter */ @@ -417,46 +329,18 @@ static void mlx4_en_do_set_multicast(struct work_struct *work) /* Add the default qp number as multicast promisc */ if (!(priv->flags & MLX4_EN_FLAG_MC_PROMISC)) { - switch (mdev->dev->caps.steering_mode) { - case MLX4_STEERING_MODE_DEVICE_MANAGED: - err = mlx4_flow_steer_promisc_add(mdev->dev, - priv->port, - priv->base_qpn, - MLX4_FS_PROMISC_ALL_MULTI); - break; - - case MLX4_STEERING_MODE_B0: - err = mlx4_multicast_promisc_add(mdev->dev, - priv->base_qpn, - priv->port); - break; - - case MLX4_STEERING_MODE_A0: - break; - } + err = mlx4_multicast_promisc_add(mdev->dev, priv->base_qpn, + priv->port); if (err) en_err(priv, "Failed entering multicast promisc mode\n"); priv->flags |= MLX4_EN_FLAG_MC_PROMISC; } } else { + int i; /* Disable Multicast promisc */ if (priv->flags & MLX4_EN_FLAG_MC_PROMISC) { - switch (mdev->dev->caps.steering_mode) { - case MLX4_STEERING_MODE_DEVICE_MANAGED: - err = mlx4_flow_steer_promisc_remove(mdev->dev, - priv->port, - MLX4_FS_PROMISC_ALL_MULTI); - break; - - case MLX4_STEERING_MODE_B0: - err = mlx4_multicast_promisc_remove(mdev->dev, - priv->base_qpn, - priv->port); - break; - - case MLX4_STEERING_MODE_A0: - break; - } + err = mlx4_multicast_promisc_remove(mdev->dev, priv->base_qpn, + priv->port); if (err) en_err(priv, "Failed disabling multicast promiscuous mode\n"); priv->flags &= ~MLX4_EN_FLAG_MC_PROMISC; @@ -467,6 +351,13 @@ static void mlx4_en_do_set_multicast(struct work_struct *work) if (err) en_err(priv, "Failed disabling multicast filter\n"); + /* Detach our qp from all the multicast addresses */ + for (i = 0; i < priv->mc_addrs_cnt; i++) { + memcpy(&mc_list[10], priv->mc_addrs + i * ETH_ALEN, ETH_ALEN); + mc_list[5] = priv->port; + mlx4_multicast_detach(mdev->dev, &priv->rss_map.indir_qp, + mc_list, MLX4_PROT_ETH); + } /* Flush mcast filter and init it with broadcast address */ mlx4_SET_MCAST_FLTR(mdev->dev, priv->port, ETH_BCAST, 1, MLX4_MCAST_CONFIG); @@ -476,8 +367,13 @@ static void mlx4_en_do_set_multicast(struct work_struct *work) netif_tx_lock_bh(dev); mlx4_en_cache_mclist(dev); netif_tx_unlock_bh(dev); - list_for_each_entry(mclist, &priv->mc_list, list) { - mcast_addr = mlx4_en_mac_to_u64(mclist->addr); + for (i = 0; i < priv->mc_addrs_cnt; i++) { + mcast_addr = + mlx4_en_mac_to_u64(priv->mc_addrs + i * ETH_ALEN); + memcpy(&mc_list[10], priv->mc_addrs + i * ETH_ALEN, ETH_ALEN); + mc_list[5] = priv->port; + mlx4_multicast_attach(mdev->dev, &priv->rss_map.indir_qp, + mc_list, 0, MLX4_PROT_ETH); mlx4_SET_MCAST_FLTR(mdev->dev, priv->port, mcast_addr, 0, MLX4_MCAST_CONFIG); } @@ -485,40 +381,6 @@ static void mlx4_en_do_set_multicast(struct work_struct *work) 0, MLX4_MCAST_ENABLE); if (err) en_err(priv, "Failed enabling multicast filter\n"); - - update_mclist_flags(priv, &priv->curr_list, &priv->mc_list); - list_for_each_entry_safe(mclist, tmp, &priv->curr_list, list) { - if (mclist->action == MCLIST_REM) { - /* detach this address and delete from list */ - memcpy(&mc_list[10], mclist->addr, ETH_ALEN); - mc_list[5] = priv->port; - err = mlx4_multicast_detach(mdev->dev, - &priv->rss_map.indir_qp, - mc_list, - MLX4_PROT_ETH, - mclist->reg_id); - if (err) - en_err(priv, "Fail to detach multicast address\n"); - - /* remove from list */ - list_del(&mclist->list); - kfree(mclist); - } else if (mclist->action == MCLIST_ADD) { - /* attach the address */ - memcpy(&mc_list[10], mclist->addr, ETH_ALEN); - /* needed for B0 steering support */ - mc_list[5] = priv->port; - err = mlx4_multicast_attach(mdev->dev, - &priv->rss_map.indir_qp, - mc_list, - priv->port, 0, - MLX4_PROT_ETH, - &mclist->reg_id); - if (err) - en_err(priv, "Fail to attach multicast address\n"); - - } - } } out: mutex_unlock(&mdev->state_lock); @@ -743,9 +605,6 @@ int mlx4_en_start_port(struct net_device *dev) return 0; } - INIT_LIST_HEAD(&priv->mc_list); - INIT_LIST_HEAD(&priv->curr_list); - /* Calculate Rx buf size */ dev->mtu = min(dev->mtu, priv->max_mtu); mlx4_en_calc_rx_buf(dev); @@ -794,10 +653,6 @@ int mlx4_en_start_port(struct net_device *dev) goto mac_err; } - err = mlx4_en_create_drop_qp(priv); - if (err) - goto rss_err; - /* Configure tx cq's and rings */ for (i = 0; i < priv->tx_ring_num; i++) { /* Configure cq */ @@ -865,23 +720,13 @@ int mlx4_en_start_port(struct net_device *dev) /* Attach rx QP to bradcast address */ memset(&mc_list[10], 0xff, ETH_ALEN); - mc_list[5] = priv->port; /* needed for B0 steering support */ + mc_list[5] = priv->port; if (mlx4_multicast_attach(mdev->dev, &priv->rss_map.indir_qp, mc_list, - priv->port, 0, MLX4_PROT_ETH, - &priv->broadcast_id)) + 0, MLX4_PROT_ETH)) mlx4_warn(mdev, "Failed Attaching Broadcast\n"); /* Must redo promiscuous mode setup. */ priv->flags &= ~(MLX4_EN_FLAG_PROMISC | MLX4_EN_FLAG_MC_PROMISC); - if (mdev->dev->caps.steering_mode == - MLX4_STEERING_MODE_DEVICE_MANAGED) { - mlx4_flow_steer_promisc_remove(mdev->dev, - priv->port, - MLX4_FS_PROMISC_UPLINK); - mlx4_flow_steer_promisc_remove(mdev->dev, - priv->port, - MLX4_FS_PROMISC_ALL_MULTI); - } /* Schedule multicast task to populate multicast list */ queue_work(mdev->workqueue, &priv->mcast_task); @@ -897,8 +742,7 @@ int mlx4_en_start_port(struct net_device *dev) mlx4_en_deactivate_tx_ring(priv, &priv->tx_ring[tx_index]); mlx4_en_deactivate_cq(priv, &priv->tx_cq[tx_index]); } - mlx4_en_destroy_drop_qp(priv); -rss_err: + mlx4_en_release_rss_steer(priv); mac_err: mlx4_put_eth_qp(mdev->dev, priv->port, priv->mac, priv->base_qpn); @@ -916,7 +760,6 @@ void mlx4_en_stop_port(struct net_device *dev) { struct mlx4_en_priv *priv = netdev_priv(dev); struct mlx4_en_dev *mdev = priv->mdev; - struct mlx4_en_mc_list *mclist, *tmp; int i; u8 mc_list[16] = {0}; @@ -935,26 +778,19 @@ void mlx4_en_stop_port(struct net_device *dev) /* Detach All multicasts */ memset(&mc_list[10], 0xff, ETH_ALEN); - mc_list[5] = priv->port; /* needed for B0 steering support */ + mc_list[5] = priv->port; mlx4_multicast_detach(mdev->dev, &priv->rss_map.indir_qp, mc_list, - MLX4_PROT_ETH, priv->broadcast_id); - list_for_each_entry(mclist, &priv->curr_list, list) { - memcpy(&mc_list[10], mclist->addr, ETH_ALEN); + MLX4_PROT_ETH); + for (i = 0; i < priv->mc_addrs_cnt; i++) { + memcpy(&mc_list[10], priv->mc_addrs + i * ETH_ALEN, ETH_ALEN); mc_list[5] = priv->port; mlx4_multicast_detach(mdev->dev, &priv->rss_map.indir_qp, - mc_list, MLX4_PROT_ETH, mclist->reg_id); + mc_list, MLX4_PROT_ETH); } mlx4_en_clear_list(dev); - list_for_each_entry_safe(mclist, tmp, &priv->curr_list, list) { - list_del(&mclist->list); - kfree(mclist); - } - /* Flush multicast filter */ mlx4_SET_MCAST_FLTR(mdev->dev, priv->port, 0, 1, MLX4_MCAST_CONFIG); - mlx4_en_destroy_drop_qp(priv); - /* Free TX Rings */ for (i = 0; i < priv->tx_ring_num; i++) { mlx4_en_deactivate_tx_ring(priv, &priv->tx_ring[i]); diff --git a/trunk/drivers/net/ethernet/mellanox/mlx4/en_rx.c b/trunk/drivers/net/ethernet/mellanox/mlx4/en_rx.c index a04cbf767eb5..d49a7ac3187d 100644 --- a/trunk/drivers/net/ethernet/mellanox/mlx4/en_rx.c +++ b/trunk/drivers/net/ethernet/mellanox/mlx4/en_rx.c @@ -844,36 +844,6 @@ static int mlx4_en_config_rss_qp(struct mlx4_en_priv *priv, int qpn, return err; } -int mlx4_en_create_drop_qp(struct mlx4_en_priv *priv) -{ - int err; - u32 qpn; - - err = mlx4_qp_reserve_range(priv->mdev->dev, 1, 1, &qpn); - if (err) { - en_err(priv, "Failed reserving drop qpn\n"); - return err; - } - err = mlx4_qp_alloc(priv->mdev->dev, qpn, &priv->drop_qp); - if (err) { - en_err(priv, "Failed allocating drop qp\n"); - mlx4_qp_release_range(priv->mdev->dev, qpn, 1); - return err; - } - - return 0; -} - -void mlx4_en_destroy_drop_qp(struct mlx4_en_priv *priv) -{ - u32 qpn; - - qpn = priv->drop_qp.qpn; - mlx4_qp_remove(priv->mdev->dev, &priv->drop_qp); - mlx4_qp_free(priv->mdev->dev, &priv->drop_qp); - mlx4_qp_release_range(priv->mdev->dev, qpn, 1); -} - /* Allocate rx qp's and configure them according to rss map */ int mlx4_en_config_rss_steer(struct mlx4_en_priv *priv) { diff --git a/trunk/drivers/net/ethernet/mellanox/mlx4/fw.c b/trunk/drivers/net/ethernet/mellanox/mlx4/fw.c index 1d70657058a5..9c83bb8151ea 100644 --- a/trunk/drivers/net/ethernet/mellanox/mlx4/fw.c +++ b/trunk/drivers/net/ethernet/mellanox/mlx4/fw.c @@ -123,8 +123,7 @@ static void dump_dev_cap_flags2(struct mlx4_dev *dev, u64 flags) static const char * const fname[] = { [0] = "RSS support", [1] = "RSS Toeplitz Hash Function support", - [2] = "RSS XOR Hash Function support", - [3] = "Device manage flow steering support" + [2] = "RSS XOR Hash Function support" }; int i; @@ -392,8 +391,6 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) #define QUERY_DEV_CAP_RSVD_XRC_OFFSET 0x66 #define QUERY_DEV_CAP_MAX_XRC_OFFSET 0x67 #define QUERY_DEV_CAP_MAX_COUNTERS_OFFSET 0x68 -#define QUERY_DEV_CAP_FLOW_STEERING_RANGE_EN_OFFSET 0x76 -#define QUERY_DEV_CAP_FLOW_STEERING_MAX_QP_OFFSET 0x77 #define QUERY_DEV_CAP_RDMARC_ENTRY_SZ_OFFSET 0x80 #define QUERY_DEV_CAP_QPC_ENTRY_SZ_OFFSET 0x82 #define QUERY_DEV_CAP_AUX_ENTRY_SZ_OFFSET 0x84 @@ -477,12 +474,6 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) dev_cap->num_ports = field & 0xf; MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_MSG_SZ_OFFSET); dev_cap->max_msg_sz = 1 << (field & 0x1f); - MLX4_GET(field, outbox, QUERY_DEV_CAP_FLOW_STEERING_RANGE_EN_OFFSET); - if (field & 0x80) - dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_FS_EN; - dev_cap->fs_log_max_ucast_qp_range_size = field & 0x1f; - MLX4_GET(field, outbox, QUERY_DEV_CAP_FLOW_STEERING_MAX_QP_OFFSET); - dev_cap->fs_max_num_qp_per_entry = field; MLX4_GET(stat_rate, outbox, QUERY_DEV_CAP_RATE_SUPPORT_OFFSET); dev_cap->stat_rate_support = stat_rate; MLX4_GET(ext_flags, outbox, QUERY_DEV_CAP_EXT_FLAGS_OFFSET); @@ -1070,15 +1061,6 @@ int mlx4_INIT_HCA(struct mlx4_dev *dev, struct mlx4_init_hca_param *param) #define INIT_HCA_LOG_MC_HASH_SZ_OFFSET (INIT_HCA_MCAST_OFFSET + 0x16) #define INIT_HCA_UC_STEERING_OFFSET (INIT_HCA_MCAST_OFFSET + 0x18) #define INIT_HCA_LOG_MC_TABLE_SZ_OFFSET (INIT_HCA_MCAST_OFFSET + 0x1b) -#define INIT_HCA_DEVICE_MANAGED_FLOW_STEERING_EN 0x6 -#define INIT_HCA_FS_PARAM_OFFSET 0x1d0 -#define INIT_HCA_FS_BASE_OFFSET (INIT_HCA_FS_PARAM_OFFSET + 0x00) -#define INIT_HCA_FS_LOG_ENTRY_SZ_OFFSET (INIT_HCA_FS_PARAM_OFFSET + 0x12) -#define INIT_HCA_FS_LOG_TABLE_SZ_OFFSET (INIT_HCA_FS_PARAM_OFFSET + 0x1b) -#define INIT_HCA_FS_ETH_BITS_OFFSET (INIT_HCA_FS_PARAM_OFFSET + 0x21) -#define INIT_HCA_FS_ETH_NUM_ADDRS_OFFSET (INIT_HCA_FS_PARAM_OFFSET + 0x22) -#define INIT_HCA_FS_IB_BITS_OFFSET (INIT_HCA_FS_PARAM_OFFSET + 0x25) -#define INIT_HCA_FS_IB_NUM_ADDRS_OFFSET (INIT_HCA_FS_PARAM_OFFSET + 0x26) #define INIT_HCA_TPT_OFFSET 0x0f0 #define INIT_HCA_DMPT_BASE_OFFSET (INIT_HCA_TPT_OFFSET + 0x00) #define INIT_HCA_LOG_MPT_SZ_OFFSET (INIT_HCA_TPT_OFFSET + 0x0b) @@ -1137,44 +1119,14 @@ int mlx4_INIT_HCA(struct mlx4_dev *dev, struct mlx4_init_hca_param *param) MLX4_PUT(inbox, param->rdmarc_base, INIT_HCA_RDMARC_BASE_OFFSET); MLX4_PUT(inbox, param->log_rd_per_qp, INIT_HCA_LOG_RD_OFFSET); - /* steering attributes */ - if (dev->caps.steering_mode == - MLX4_STEERING_MODE_DEVICE_MANAGED) { - *(inbox + INIT_HCA_FLAGS_OFFSET / 4) |= - cpu_to_be32(1 << - INIT_HCA_DEVICE_MANAGED_FLOW_STEERING_EN); - - MLX4_PUT(inbox, param->mc_base, INIT_HCA_FS_BASE_OFFSET); - MLX4_PUT(inbox, param->log_mc_entry_sz, - INIT_HCA_FS_LOG_ENTRY_SZ_OFFSET); - MLX4_PUT(inbox, param->log_mc_table_sz, - INIT_HCA_FS_LOG_TABLE_SZ_OFFSET); - /* Enable Ethernet flow steering - * with udp unicast and tcp unicast - */ - MLX4_PUT(inbox, param->fs_hash_enable_bits, - INIT_HCA_FS_ETH_BITS_OFFSET); - MLX4_PUT(inbox, (u16) MLX4_FS_NUM_OF_L2_ADDR, - INIT_HCA_FS_ETH_NUM_ADDRS_OFFSET); - /* Enable IPoIB flow steering - * with udp unicast and tcp unicast - */ - MLX4_PUT(inbox, param->fs_hash_enable_bits, - INIT_HCA_FS_IB_BITS_OFFSET); - MLX4_PUT(inbox, (u16) MLX4_FS_NUM_OF_L2_ADDR, - INIT_HCA_FS_IB_NUM_ADDRS_OFFSET); - } else { - MLX4_PUT(inbox, param->mc_base, INIT_HCA_MC_BASE_OFFSET); - MLX4_PUT(inbox, param->log_mc_entry_sz, - INIT_HCA_LOG_MC_ENTRY_SZ_OFFSET); - MLX4_PUT(inbox, param->log_mc_hash_sz, - INIT_HCA_LOG_MC_HASH_SZ_OFFSET); - MLX4_PUT(inbox, param->log_mc_table_sz, - INIT_HCA_LOG_MC_TABLE_SZ_OFFSET); - if (dev->caps.steering_mode == MLX4_STEERING_MODE_B0) - MLX4_PUT(inbox, (u8) (1 << 3), - INIT_HCA_UC_STEERING_OFFSET); - } + /* multicast attributes */ + + MLX4_PUT(inbox, param->mc_base, INIT_HCA_MC_BASE_OFFSET); + MLX4_PUT(inbox, param->log_mc_entry_sz, INIT_HCA_LOG_MC_ENTRY_SZ_OFFSET); + MLX4_PUT(inbox, param->log_mc_hash_sz, INIT_HCA_LOG_MC_HASH_SZ_OFFSET); + if (dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER) + MLX4_PUT(inbox, (u8) (1 << 3), INIT_HCA_UC_STEERING_OFFSET); + MLX4_PUT(inbox, param->log_mc_table_sz, INIT_HCA_LOG_MC_TABLE_SZ_OFFSET); /* TPT attributes */ @@ -1236,24 +1188,15 @@ int mlx4_QUERY_HCA(struct mlx4_dev *dev, MLX4_GET(param->rdmarc_base, outbox, INIT_HCA_RDMARC_BASE_OFFSET); MLX4_GET(param->log_rd_per_qp, outbox, INIT_HCA_LOG_RD_OFFSET); - /* steering attributes */ - if (dev->caps.steering_mode == - MLX4_STEERING_MODE_DEVICE_MANAGED) { + /* multicast attributes */ - MLX4_GET(param->mc_base, outbox, INIT_HCA_FS_BASE_OFFSET); - MLX4_GET(param->log_mc_entry_sz, outbox, - INIT_HCA_FS_LOG_ENTRY_SZ_OFFSET); - MLX4_GET(param->log_mc_table_sz, outbox, - INIT_HCA_FS_LOG_TABLE_SZ_OFFSET); - } else { - MLX4_GET(param->mc_base, outbox, INIT_HCA_MC_BASE_OFFSET); - MLX4_GET(param->log_mc_entry_sz, outbox, - INIT_HCA_LOG_MC_ENTRY_SZ_OFFSET); - MLX4_GET(param->log_mc_hash_sz, outbox, - INIT_HCA_LOG_MC_HASH_SZ_OFFSET); - MLX4_GET(param->log_mc_table_sz, outbox, - INIT_HCA_LOG_MC_TABLE_SZ_OFFSET); - } + MLX4_GET(param->mc_base, outbox, INIT_HCA_MC_BASE_OFFSET); + MLX4_GET(param->log_mc_entry_sz, outbox, + INIT_HCA_LOG_MC_ENTRY_SZ_OFFSET); + MLX4_GET(param->log_mc_hash_sz, outbox, + INIT_HCA_LOG_MC_HASH_SZ_OFFSET); + MLX4_GET(param->log_mc_table_sz, outbox, + INIT_HCA_LOG_MC_TABLE_SZ_OFFSET); /* TPT attributes */ diff --git a/trunk/drivers/net/ethernet/mellanox/mlx4/fw.h b/trunk/drivers/net/ethernet/mellanox/mlx4/fw.h index 83fcbbf1b169..64c0399e4b78 100644 --- a/trunk/drivers/net/ethernet/mellanox/mlx4/fw.h +++ b/trunk/drivers/net/ethernet/mellanox/mlx4/fw.h @@ -78,8 +78,6 @@ struct mlx4_dev_cap { u16 wavelength[MLX4_MAX_PORTS + 1]; u64 trans_code[MLX4_MAX_PORTS + 1]; u16 stat_rate_support; - int fs_log_max_ucast_qp_range_size; - int fs_max_num_qp_per_entry; u64 flags; u64 flags2; int reserved_uars; @@ -167,7 +165,6 @@ struct mlx4_init_hca_param { u8 log_mpt_sz; u8 log_uar_sz; u8 uar_page_sz; /* log pg sz in 4k chunks */ - u8 fs_hash_enable_bits; }; struct mlx4_init_ib_param { diff --git a/trunk/drivers/net/ethernet/mellanox/mlx4/main.c b/trunk/drivers/net/ethernet/mellanox/mlx4/main.c index 42645166bae2..14d9c762b60f 100644 --- a/trunk/drivers/net/ethernet/mellanox/mlx4/main.c +++ b/trunk/drivers/net/ethernet/mellanox/mlx4/main.c @@ -91,9 +91,7 @@ module_param_named(log_num_mgm_entry_size, MODULE_PARM_DESC(log_num_mgm_entry_size, "log mgm size, that defines the num" " of qp per mcg, for example:" " 10 gives 248.range: 9<=" - " log_num_mgm_entry_size <= 12." - " Not in use with device managed" - " flow steering"); + " log_num_mgm_entry_size <= 12"); #define MLX4_VF (1 << 0) @@ -246,6 +244,7 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) dev->caps.reserved_srqs = dev_cap->reserved_srqs; dev->caps.max_sq_desc_sz = dev_cap->max_sq_desc_sz; dev->caps.max_rq_desc_sz = dev_cap->max_rq_desc_sz; + dev->caps.num_qp_per_mgm = mlx4_get_qp_per_mgm(dev); /* * Subtract 1 from the limit because we need to allocate a * spare CQE so the HCA HW can tell the difference between an @@ -276,28 +275,6 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) dev->caps.max_gso_sz = dev_cap->max_gso_sz; dev->caps.max_rss_tbl_sz = dev_cap->max_rss_tbl_sz; - if (dev_cap->flags2 & MLX4_DEV_CAP_FLAG2_FS_EN) { - dev->caps.steering_mode = MLX4_STEERING_MODE_DEVICE_MANAGED; - dev->caps.num_qp_per_mgm = dev_cap->fs_max_num_qp_per_entry; - dev->caps.fs_log_max_ucast_qp_range_size = - dev_cap->fs_log_max_ucast_qp_range_size; - } else { - if (dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER && - dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER) { - dev->caps.steering_mode = MLX4_STEERING_MODE_B0; - } else { - dev->caps.steering_mode = MLX4_STEERING_MODE_A0; - - if (dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER || - dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER) - mlx4_warn(dev, "Must have UC_STEER and MC_STEER flags " - "set to use B0 steering. Falling back to A0 steering mode.\n"); - } - dev->caps.num_qp_per_mgm = mlx4_get_qp_per_mgm(dev); - } - mlx4_dbg(dev, "Steering mode is: %s\n", - mlx4_steering_mode_str(dev->caps.steering_mode)); - /* Sense port always allowed on supported devices for ConnectX1 and 2 */ if (dev->pdev->device != 0x1003) dev->caps.flags |= MLX4_DEV_CAP_FLAG_SENSE_SUPPORT; @@ -991,11 +968,9 @@ static int mlx4_init_icm(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap, } /* - * For flow steering device managed mode it is required to use - * mlx4_init_icm_table. For B0 steering mode it's not strictly - * required, but for simplicity just map the whole multicast - * group table now. The table isn't very big and it's a lot - * easier than trying to track ref counts. + * It's not strictly required, but for simplicity just map the + * whole multicast group table now. The table isn't very big + * and it's a lot easier than trying to track ref counts. */ err = mlx4_init_icm_table(dev, &priv->mcg_table.table, init_hca->mc_base, @@ -1231,26 +1206,7 @@ static int mlx4_init_hca(struct mlx4_dev *dev) goto err_stop_fw; } - priv->fs_hash_mode = MLX4_FS_L2_HASH; - - switch (priv->fs_hash_mode) { - case MLX4_FS_L2_HASH: - init_hca.fs_hash_enable_bits = 0; - break; - - case MLX4_FS_L2_L3_L4_HASH: - /* Enable flow steering with - * udp unicast and tcp unicast - */ - init_hca.fs_hash_enable_bits = - MLX4_FS_UDP_UC_EN | MLX4_FS_TCP_UC_EN; - break; - } - profile = default_profile; - if (dev->caps.steering_mode == - MLX4_STEERING_MODE_DEVICE_MANAGED) - profile.num_mcg = MLX4_FS_NUM_MCG; icm_size = mlx4_make_profile(dev, &profile, &dev_cap, &init_hca); diff --git a/trunk/drivers/net/ethernet/mellanox/mlx4/mcg.c b/trunk/drivers/net/ethernet/mellanox/mlx4/mcg.c index 5bac0dfafbd8..f4a8f98e402a 100644 --- a/trunk/drivers/net/ethernet/mellanox/mlx4/mcg.c +++ b/trunk/drivers/net/ethernet/mellanox/mlx4/mcg.c @@ -41,7 +41,6 @@ #define MGM_QPN_MASK 0x00FFFFFF #define MGM_BLCK_LB_BIT 30 -#define MLX4_MAC_MASK 0xffffffffffffULL static const u8 zero_gid[16]; /* automatically initialized to 0 */ @@ -55,12 +54,7 @@ struct mlx4_mgm { int mlx4_get_mgm_entry_size(struct mlx4_dev *dev) { - if (dev->caps.steering_mode == - MLX4_STEERING_MODE_DEVICE_MANAGED) - return 1 << MLX4_FS_MGM_LOG_ENTRY_SIZE; - else - return min((1 << mlx4_log_num_mgm_entry_size), - MLX4_MAX_MGM_ENTRY_SIZE); + return min((1 << mlx4_log_num_mgm_entry_size), MLX4_MAX_MGM_ENTRY_SIZE); } int mlx4_get_qp_per_mgm(struct mlx4_dev *dev) @@ -68,35 +62,6 @@ int mlx4_get_qp_per_mgm(struct mlx4_dev *dev) return 4 * (mlx4_get_mgm_entry_size(dev) / 16 - 2); } -static int mlx4_QP_FLOW_STEERING_ATTACH(struct mlx4_dev *dev, - struct mlx4_cmd_mailbox *mailbox, - u32 size, - u64 *reg_id) -{ - u64 imm; - int err = 0; - - err = mlx4_cmd_imm(dev, mailbox->dma, &imm, size, 0, - MLX4_QP_FLOW_STEERING_ATTACH, MLX4_CMD_TIME_CLASS_A, - MLX4_CMD_NATIVE); - if (err) - return err; - *reg_id = imm; - - return err; -} - -static int mlx4_QP_FLOW_STEERING_DETACH(struct mlx4_dev *dev, u64 regid) -{ - int err = 0; - - err = mlx4_cmd(dev, regid, 0, 0, - MLX4_QP_FLOW_STEERING_DETACH, MLX4_CMD_TIME_CLASS_A, - MLX4_CMD_NATIVE); - - return err; -} - static int mlx4_READ_ENTRY(struct mlx4_dev *dev, int index, struct mlx4_cmd_mailbox *mailbox) { @@ -649,311 +614,6 @@ static int find_entry(struct mlx4_dev *dev, u8 port, return err; } -struct mlx4_net_trans_rule_hw_ctrl { - __be32 ctrl; - __be32 vf_vep_port; - __be32 qpn; - __be32 reserved; -}; - -static void trans_rule_ctrl_to_hw(struct mlx4_net_trans_rule *ctrl, - struct mlx4_net_trans_rule_hw_ctrl *hw) -{ - static const u8 __promisc_mode[] = { - [MLX4_FS_PROMISC_NONE] = 0x0, - [MLX4_FS_PROMISC_UPLINK] = 0x1, - [MLX4_FS_PROMISC_FUNCTION_PORT] = 0x2, - [MLX4_FS_PROMISC_ALL_MULTI] = 0x3, - }; - - u32 dw = 0; - - dw = ctrl->queue_mode == MLX4_NET_TRANS_Q_LIFO ? 1 : 0; - dw |= ctrl->exclusive ? (1 << 2) : 0; - dw |= ctrl->allow_loopback ? (1 << 3) : 0; - dw |= __promisc_mode[ctrl->promisc_mode] << 8; - dw |= ctrl->priority << 16; - - hw->ctrl = cpu_to_be32(dw); - hw->vf_vep_port = cpu_to_be32(ctrl->port); - hw->qpn = cpu_to_be32(ctrl->qpn); -} - -struct mlx4_net_trans_rule_hw_ib { - u8 size; - u8 rsvd1; - __be16 id; - u32 rsvd2; - __be32 qpn; - __be32 qpn_mask; - u8 dst_gid[16]; - u8 dst_gid_msk[16]; -} __packed; - -struct mlx4_net_trans_rule_hw_eth { - u8 size; - u8 rsvd; - __be16 id; - u8 rsvd1[6]; - u8 dst_mac[6]; - u16 rsvd2; - u8 dst_mac_msk[6]; - u16 rsvd3; - u8 src_mac[6]; - u16 rsvd4; - u8 src_mac_msk[6]; - u8 rsvd5; - u8 ether_type_enable; - __be16 ether_type; - __be16 vlan_id_msk; - __be16 vlan_id; -} __packed; - -struct mlx4_net_trans_rule_hw_tcp_udp { - u8 size; - u8 rsvd; - __be16 id; - __be16 rsvd1[3]; - __be16 dst_port; - __be16 rsvd2; - __be16 dst_port_msk; - __be16 rsvd3; - __be16 src_port; - __be16 rsvd4; - __be16 src_port_msk; -} __packed; - -struct mlx4_net_trans_rule_hw_ipv4 { - u8 size; - u8 rsvd; - __be16 id; - __be32 rsvd1; - __be32 dst_ip; - __be32 dst_ip_msk; - __be32 src_ip; - __be32 src_ip_msk; -} __packed; - -struct _rule_hw { - union { - struct { - u8 size; - u8 rsvd; - __be16 id; - }; - struct mlx4_net_trans_rule_hw_eth eth; - struct mlx4_net_trans_rule_hw_ib ib; - struct mlx4_net_trans_rule_hw_ipv4 ipv4; - struct mlx4_net_trans_rule_hw_tcp_udp tcp_udp; - }; -}; - -static int parse_trans_rule(struct mlx4_dev *dev, struct mlx4_spec_list *spec, - struct _rule_hw *rule_hw) -{ - static const u16 __sw_id_hw[] = { - [MLX4_NET_TRANS_RULE_ID_ETH] = 0xE001, - [MLX4_NET_TRANS_RULE_ID_IB] = 0xE005, - [MLX4_NET_TRANS_RULE_ID_IPV6] = 0xE003, - [MLX4_NET_TRANS_RULE_ID_IPV4] = 0xE002, - [MLX4_NET_TRANS_RULE_ID_TCP] = 0xE004, - [MLX4_NET_TRANS_RULE_ID_UDP] = 0xE006 - }; - - static const size_t __rule_hw_sz[] = { - [MLX4_NET_TRANS_RULE_ID_ETH] = - sizeof(struct mlx4_net_trans_rule_hw_eth), - [MLX4_NET_TRANS_RULE_ID_IB] = - sizeof(struct mlx4_net_trans_rule_hw_ib), - [MLX4_NET_TRANS_RULE_ID_IPV6] = 0, - [MLX4_NET_TRANS_RULE_ID_IPV4] = - sizeof(struct mlx4_net_trans_rule_hw_ipv4), - [MLX4_NET_TRANS_RULE_ID_TCP] = - sizeof(struct mlx4_net_trans_rule_hw_tcp_udp), - [MLX4_NET_TRANS_RULE_ID_UDP] = - sizeof(struct mlx4_net_trans_rule_hw_tcp_udp) - }; - if (spec->id >= MLX4_NET_TRANS_RULE_NUM) { - mlx4_err(dev, "Invalid network rule id. id = %d\n", spec->id); - return -EINVAL; - } - memset(rule_hw, 0, __rule_hw_sz[spec->id]); - rule_hw->id = cpu_to_be16(__sw_id_hw[spec->id]); - rule_hw->size = __rule_hw_sz[spec->id] >> 2; - - switch (spec->id) { - case MLX4_NET_TRANS_RULE_ID_ETH: - memcpy(rule_hw->eth.dst_mac, spec->eth.dst_mac, ETH_ALEN); - memcpy(rule_hw->eth.dst_mac_msk, spec->eth.dst_mac_msk, - ETH_ALEN); - memcpy(rule_hw->eth.src_mac, spec->eth.src_mac, ETH_ALEN); - memcpy(rule_hw->eth.src_mac_msk, spec->eth.src_mac_msk, - ETH_ALEN); - if (spec->eth.ether_type_enable) { - rule_hw->eth.ether_type_enable = 1; - rule_hw->eth.ether_type = spec->eth.ether_type; - } - rule_hw->eth.vlan_id = spec->eth.vlan_id; - rule_hw->eth.vlan_id_msk = spec->eth.vlan_id_msk; - break; - - case MLX4_NET_TRANS_RULE_ID_IB: - rule_hw->ib.qpn = spec->ib.r_qpn; - rule_hw->ib.qpn_mask = spec->ib.qpn_msk; - memcpy(&rule_hw->ib.dst_gid, &spec->ib.dst_gid, 16); - memcpy(&rule_hw->ib.dst_gid_msk, &spec->ib.dst_gid_msk, 16); - break; - - case MLX4_NET_TRANS_RULE_ID_IPV6: - return -EOPNOTSUPP; - - case MLX4_NET_TRANS_RULE_ID_IPV4: - rule_hw->ipv4.src_ip = spec->ipv4.src_ip; - rule_hw->ipv4.src_ip_msk = spec->ipv4.src_ip_msk; - rule_hw->ipv4.dst_ip = spec->ipv4.dst_ip; - rule_hw->ipv4.dst_ip_msk = spec->ipv4.dst_ip_msk; - break; - - case MLX4_NET_TRANS_RULE_ID_TCP: - case MLX4_NET_TRANS_RULE_ID_UDP: - rule_hw->tcp_udp.dst_port = spec->tcp_udp.dst_port; - rule_hw->tcp_udp.dst_port_msk = spec->tcp_udp.dst_port_msk; - rule_hw->tcp_udp.src_port = spec->tcp_udp.src_port; - rule_hw->tcp_udp.src_port_msk = spec->tcp_udp.src_port_msk; - break; - - default: - return -EINVAL; - } - - return __rule_hw_sz[spec->id]; -} - -static void mlx4_err_rule(struct mlx4_dev *dev, char *str, - struct mlx4_net_trans_rule *rule) -{ -#define BUF_SIZE 256 - struct mlx4_spec_list *cur; - char buf[BUF_SIZE]; - int len = 0; - - mlx4_err(dev, "%s", str); - len += snprintf(buf + len, BUF_SIZE - len, - "port = %d prio = 0x%x qp = 0x%x ", - rule->port, rule->priority, rule->qpn); - - list_for_each_entry(cur, &rule->list, list) { - switch (cur->id) { - case MLX4_NET_TRANS_RULE_ID_ETH: - len += snprintf(buf + len, BUF_SIZE - len, - "dmac = %pM ", &cur->eth.dst_mac); - if (cur->eth.ether_type) - len += snprintf(buf + len, BUF_SIZE - len, - "ethertype = 0x%x ", - be16_to_cpu(cur->eth.ether_type)); - if (cur->eth.vlan_id) - len += snprintf(buf + len, BUF_SIZE - len, - "vlan-id = %d ", - be16_to_cpu(cur->eth.vlan_id)); - break; - - case MLX4_NET_TRANS_RULE_ID_IPV4: - if (cur->ipv4.src_ip) - len += snprintf(buf + len, BUF_SIZE - len, - "src-ip = %pI4 ", - &cur->ipv4.src_ip); - if (cur->ipv4.dst_ip) - len += snprintf(buf + len, BUF_SIZE - len, - "dst-ip = %pI4 ", - &cur->ipv4.dst_ip); - break; - - case MLX4_NET_TRANS_RULE_ID_TCP: - case MLX4_NET_TRANS_RULE_ID_UDP: - if (cur->tcp_udp.src_port) - len += snprintf(buf + len, BUF_SIZE - len, - "src-port = %d ", - be16_to_cpu(cur->tcp_udp.src_port)); - if (cur->tcp_udp.dst_port) - len += snprintf(buf + len, BUF_SIZE - len, - "dst-port = %d ", - be16_to_cpu(cur->tcp_udp.dst_port)); - break; - - case MLX4_NET_TRANS_RULE_ID_IB: - len += snprintf(buf + len, BUF_SIZE - len, - "dst-gid = %pI6\n", cur->ib.dst_gid); - len += snprintf(buf + len, BUF_SIZE - len, - "dst-gid-mask = %pI6\n", - cur->ib.dst_gid_msk); - break; - - case MLX4_NET_TRANS_RULE_ID_IPV6: - break; - - default: - break; - } - } - len += snprintf(buf + len, BUF_SIZE - len, "\n"); - mlx4_err(dev, "%s", buf); - - if (len >= BUF_SIZE) - mlx4_err(dev, "Network rule error message was truncated, print buffer is too small.\n"); -} - -int mlx4_flow_attach(struct mlx4_dev *dev, - struct mlx4_net_trans_rule *rule, u64 *reg_id) -{ - struct mlx4_cmd_mailbox *mailbox; - struct mlx4_spec_list *cur; - u32 size = 0; - int ret; - - mailbox = mlx4_alloc_cmd_mailbox(dev); - if (IS_ERR(mailbox)) - return PTR_ERR(mailbox); - - memset(mailbox->buf, 0, sizeof(struct mlx4_net_trans_rule_hw_ctrl)); - trans_rule_ctrl_to_hw(rule, mailbox->buf); - - size += sizeof(struct mlx4_net_trans_rule_hw_ctrl); - - list_for_each_entry(cur, &rule->list, list) { - ret = parse_trans_rule(dev, cur, mailbox->buf + size); - if (ret < 0) { - mlx4_free_cmd_mailbox(dev, mailbox); - return -EINVAL; - } - size += ret; - } - - ret = mlx4_QP_FLOW_STEERING_ATTACH(dev, mailbox, size >> 2, reg_id); - if (ret == -ENOMEM) - mlx4_err_rule(dev, - "mcg table is full. Fail to register network rule.\n", - rule); - else if (ret) - mlx4_err_rule(dev, "Fail to register network rule.\n", rule); - - mlx4_free_cmd_mailbox(dev, mailbox); - - return ret; -} -EXPORT_SYMBOL_GPL(mlx4_flow_attach); - -int mlx4_flow_detach(struct mlx4_dev *dev, u64 reg_id) -{ - int err; - - err = mlx4_QP_FLOW_STEERING_DETACH(dev, reg_id); - if (err) - mlx4_err(dev, "Fail to detach network rule. registration id = 0x%llx\n", - reg_id); - return err; -} -EXPORT_SYMBOL_GPL(mlx4_flow_detach); - int mlx4_qp_attach_common(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16], int block_mcast_loopback, enum mlx4_protocol prot, enum mlx4_steer_type steer) @@ -1206,159 +866,49 @@ static int mlx4_QP_ATTACH(struct mlx4_dev *dev, struct mlx4_qp *qp, } int mlx4_multicast_attach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16], - u8 port, int block_mcast_loopback, - enum mlx4_protocol prot, u64 *reg_id) + int block_mcast_loopback, enum mlx4_protocol prot) { + if (prot == MLX4_PROT_ETH && + !(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER)) + return 0; - switch (dev->caps.steering_mode) { - case MLX4_STEERING_MODE_A0: - if (prot == MLX4_PROT_ETH) - return 0; - - case MLX4_STEERING_MODE_B0: - if (prot == MLX4_PROT_ETH) - gid[7] |= (MLX4_MC_STEER << 1); - - if (mlx4_is_mfunc(dev)) - return mlx4_QP_ATTACH(dev, qp, gid, 1, - block_mcast_loopback, prot); - return mlx4_qp_attach_common(dev, qp, gid, - block_mcast_loopback, prot, - MLX4_MC_STEER); - - case MLX4_STEERING_MODE_DEVICE_MANAGED: { - struct mlx4_spec_list spec = { {NULL} }; - __be64 mac_mask = cpu_to_be64(MLX4_MAC_MASK << 16); - - struct mlx4_net_trans_rule rule = { - .queue_mode = MLX4_NET_TRANS_Q_FIFO, - .exclusive = 0, - .promisc_mode = MLX4_FS_PROMISC_NONE, - .priority = MLX4_DOMAIN_NIC, - }; - - rule.allow_loopback = ~block_mcast_loopback; - rule.port = port; - rule.qpn = qp->qpn; - INIT_LIST_HEAD(&rule.list); - - switch (prot) { - case MLX4_PROT_ETH: - spec.id = MLX4_NET_TRANS_RULE_ID_ETH; - memcpy(spec.eth.dst_mac, &gid[10], ETH_ALEN); - memcpy(spec.eth.dst_mac_msk, &mac_mask, ETH_ALEN); - break; - - case MLX4_PROT_IB_IPV6: - spec.id = MLX4_NET_TRANS_RULE_ID_IB; - memcpy(spec.ib.dst_gid, gid, 16); - memset(&spec.ib.dst_gid_msk, 0xff, 16); - break; - default: - return -EINVAL; - } - list_add_tail(&spec.list, &rule.list); + if (prot == MLX4_PROT_ETH) + gid[7] |= (MLX4_MC_STEER << 1); - return mlx4_flow_attach(dev, &rule, reg_id); - } + if (mlx4_is_mfunc(dev)) + return mlx4_QP_ATTACH(dev, qp, gid, 1, + block_mcast_loopback, prot); - default: - return -EINVAL; - } + return mlx4_qp_attach_common(dev, qp, gid, block_mcast_loopback, + prot, MLX4_MC_STEER); } EXPORT_SYMBOL_GPL(mlx4_multicast_attach); int mlx4_multicast_detach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16], - enum mlx4_protocol prot, u64 reg_id) + enum mlx4_protocol prot) { - switch (dev->caps.steering_mode) { - case MLX4_STEERING_MODE_A0: - if (prot == MLX4_PROT_ETH) - return 0; - - case MLX4_STEERING_MODE_B0: - if (prot == MLX4_PROT_ETH) - gid[7] |= (MLX4_MC_STEER << 1); - - if (mlx4_is_mfunc(dev)) - return mlx4_QP_ATTACH(dev, qp, gid, 0, 0, prot); + if (prot == MLX4_PROT_ETH && + !(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER)) + return 0; - return mlx4_qp_detach_common(dev, qp, gid, prot, - MLX4_MC_STEER); + if (prot == MLX4_PROT_ETH) + gid[7] |= (MLX4_MC_STEER << 1); - case MLX4_STEERING_MODE_DEVICE_MANAGED: - return mlx4_flow_detach(dev, reg_id); + if (mlx4_is_mfunc(dev)) + return mlx4_QP_ATTACH(dev, qp, gid, 0, 0, prot); - default: - return -EINVAL; - } + return mlx4_qp_detach_common(dev, qp, gid, prot, MLX4_MC_STEER); } EXPORT_SYMBOL_GPL(mlx4_multicast_detach); -int mlx4_flow_steer_promisc_add(struct mlx4_dev *dev, u8 port, - u32 qpn, enum mlx4_net_trans_promisc_mode mode) -{ - struct mlx4_net_trans_rule rule; - u64 *regid_p; - - switch (mode) { - case MLX4_FS_PROMISC_UPLINK: - case MLX4_FS_PROMISC_FUNCTION_PORT: - regid_p = &dev->regid_promisc_array[port]; - break; - case MLX4_FS_PROMISC_ALL_MULTI: - regid_p = &dev->regid_allmulti_array[port]; - break; - default: - return -1; - } - - if (*regid_p != 0) - return -1; - - rule.promisc_mode = mode; - rule.port = port; - rule.qpn = qpn; - INIT_LIST_HEAD(&rule.list); - mlx4_err(dev, "going promisc on %x\n", port); - - return mlx4_flow_attach(dev, &rule, regid_p); -} -EXPORT_SYMBOL_GPL(mlx4_flow_steer_promisc_add); - -int mlx4_flow_steer_promisc_remove(struct mlx4_dev *dev, u8 port, - enum mlx4_net_trans_promisc_mode mode) -{ - int ret; - u64 *regid_p; - - switch (mode) { - case MLX4_FS_PROMISC_UPLINK: - case MLX4_FS_PROMISC_FUNCTION_PORT: - regid_p = &dev->regid_promisc_array[port]; - break; - case MLX4_FS_PROMISC_ALL_MULTI: - regid_p = &dev->regid_allmulti_array[port]; - break; - default: - return -1; - } - - if (*regid_p == 0) - return -1; - - ret = mlx4_flow_detach(dev, *regid_p); - if (ret == 0) - *regid_p = 0; - - return ret; -} -EXPORT_SYMBOL_GPL(mlx4_flow_steer_promisc_remove); - int mlx4_unicast_attach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16], int block_mcast_loopback, enum mlx4_protocol prot) { + if (prot == MLX4_PROT_ETH && + !(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER)) + return 0; + if (prot == MLX4_PROT_ETH) gid[7] |= (MLX4_UC_STEER << 1); @@ -1374,6 +924,10 @@ EXPORT_SYMBOL_GPL(mlx4_unicast_attach); int mlx4_unicast_detach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16], enum mlx4_protocol prot) { + if (prot == MLX4_PROT_ETH && + !(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER)) + return 0; + if (prot == MLX4_PROT_ETH) gid[7] |= (MLX4_UC_STEER << 1); @@ -1414,6 +968,9 @@ static int mlx4_PROMISC(struct mlx4_dev *dev, u32 qpn, int mlx4_multicast_promisc_add(struct mlx4_dev *dev, u32 qpn, u8 port) { + if (!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER)) + return 0; + if (mlx4_is_mfunc(dev)) return mlx4_PROMISC(dev, qpn, MLX4_MC_STEER, 1, port); @@ -1423,6 +980,9 @@ EXPORT_SYMBOL_GPL(mlx4_multicast_promisc_add); int mlx4_multicast_promisc_remove(struct mlx4_dev *dev, u32 qpn, u8 port) { + if (!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER)) + return 0; + if (mlx4_is_mfunc(dev)) return mlx4_PROMISC(dev, qpn, MLX4_MC_STEER, 0, port); @@ -1432,6 +992,9 @@ EXPORT_SYMBOL_GPL(mlx4_multicast_promisc_remove); int mlx4_unicast_promisc_add(struct mlx4_dev *dev, u32 qpn, u8 port) { + if (!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER)) + return 0; + if (mlx4_is_mfunc(dev)) return mlx4_PROMISC(dev, qpn, MLX4_UC_STEER, 1, port); @@ -1441,6 +1004,9 @@ EXPORT_SYMBOL_GPL(mlx4_unicast_promisc_add); int mlx4_unicast_promisc_remove(struct mlx4_dev *dev, u32 qpn, u8 port) { + if (!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER)) + return 0; + if (mlx4_is_mfunc(dev)) return mlx4_PROMISC(dev, qpn, MLX4_UC_STEER, 0, port); @@ -1453,10 +1019,6 @@ int mlx4_init_mcg_table(struct mlx4_dev *dev) struct mlx4_priv *priv = mlx4_priv(dev); int err; - /* No need for mcg_table when fw managed the mcg table*/ - if (dev->caps.steering_mode == - MLX4_STEERING_MODE_DEVICE_MANAGED) - return 0; err = mlx4_bitmap_init(&priv->mcg_table.bitmap, dev->caps.num_amgms, dev->caps.num_amgms - 1, 0, 0); if (err) @@ -1469,7 +1031,5 @@ int mlx4_init_mcg_table(struct mlx4_dev *dev) void mlx4_cleanup_mcg_table(struct mlx4_dev *dev) { - if (dev->caps.steering_mode != - MLX4_STEERING_MODE_DEVICE_MANAGED) - mlx4_bitmap_cleanup(&mlx4_priv(dev)->mcg_table.bitmap); + mlx4_bitmap_cleanup(&mlx4_priv(dev)->mcg_table.bitmap); } diff --git a/trunk/drivers/net/ethernet/mellanox/mlx4/mlx4.h b/trunk/drivers/net/ethernet/mellanox/mlx4/mlx4.h index d2c436b10fbf..e5d20220762c 100644 --- a/trunk/drivers/net/ethernet/mellanox/mlx4/mlx4.h +++ b/trunk/drivers/net/ethernet/mellanox/mlx4/mlx4.h @@ -39,7 +39,6 @@ #include #include -#include #include #include #include @@ -54,17 +53,6 @@ #define DRV_VERSION "1.1" #define DRV_RELDATE "Dec, 2011" -#define MLX4_FS_UDP_UC_EN (1 << 1) -#define MLX4_FS_TCP_UC_EN (1 << 2) -#define MLX4_FS_NUM_OF_L2_ADDR 8 -#define MLX4_FS_MGM_LOG_ENTRY_SIZE 7 -#define MLX4_FS_NUM_MCG (1 << 17) - -enum { - MLX4_FS_L2_HASH = 0, - MLX4_FS_L2_L3_L4_HASH, -}; - #define MLX4_NUM_UP 8 #define MLX4_NUM_TC 8 #define MLX4_RATELIMIT_UNITS 3 /* 100 Mbps */ @@ -149,7 +137,6 @@ enum mlx4_resource { RES_VLAN, RES_EQ, RES_COUNTER, - RES_FS_RULE, MLX4_NUM_OF_RESOURCE_TYPE }; @@ -522,7 +509,7 @@ struct slave_list { struct mlx4_resource_tracker { spinlock_t lock; /* tree for each resources */ - struct rb_root res_tree[MLX4_NUM_OF_RESOURCE_TYPE]; + struct radix_tree_root res_tree[MLX4_NUM_OF_RESOURCE_TYPE]; /* num_of_slave's lists, one per slave */ struct slave_list *slave_list; }; @@ -716,7 +703,6 @@ struct mlx4_set_port_rqp_calc_context { struct mlx4_mac_entry { u64 mac; - u64 reg_id; }; struct mlx4_port_info { @@ -790,7 +776,6 @@ struct mlx4_priv { struct mutex bf_mutex; struct io_mapping *bf_mapping; int reserved_mtts; - int fs_hash_mode; }; static inline struct mlx4_priv *mlx4_priv(struct mlx4_dev *dev) @@ -1047,7 +1032,7 @@ int mlx4_SET_PORT(struct mlx4_dev *dev, u8 port); /* resource tracker functions*/ int mlx4_get_slave_from_resource_id(struct mlx4_dev *dev, enum mlx4_resource resource_type, - u64 resource_id, int *slave); + int resource_id, int *slave); void mlx4_delete_all_resources_for_slave(struct mlx4_dev *dev, int slave_id); int mlx4_init_resource_tracker(struct mlx4_dev *dev); @@ -1132,16 +1117,6 @@ int mlx4_QUERY_IF_STAT_wrapper(struct mlx4_dev *dev, int slave, struct mlx4_cmd_mailbox *inbox, struct mlx4_cmd_mailbox *outbox, struct mlx4_cmd_info *cmd); -int mlx4_QP_FLOW_STEERING_ATTACH_wrapper(struct mlx4_dev *dev, int slave, - struct mlx4_vhcr *vhcr, - struct mlx4_cmd_mailbox *inbox, - struct mlx4_cmd_mailbox *outbox, - struct mlx4_cmd_info *cmd); -int mlx4_QP_FLOW_STEERING_DETACH_wrapper(struct mlx4_dev *dev, int slave, - struct mlx4_vhcr *vhcr, - struct mlx4_cmd_mailbox *inbox, - struct mlx4_cmd_mailbox *outbox, - struct mlx4_cmd_info *cmd); int mlx4_get_mgm_entry_size(struct mlx4_dev *dev); int mlx4_get_qp_per_mgm(struct mlx4_dev *dev); diff --git a/trunk/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h b/trunk/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h index a12632150b34..225c20d47900 100644 --- a/trunk/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h +++ b/trunk/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h @@ -75,7 +75,6 @@ #define STAMP_SHIFT 31 #define STAMP_VAL 0x7fffffff #define STATS_DELAY (HZ / 4) -#define MAX_NUM_OF_FS_RULES 256 /* Typical TSO descriptor with 16 gather entries is 352 bytes... */ #define MAX_DESC_SIZE 512 @@ -405,19 +404,6 @@ struct mlx4_en_perf_stats { #define NUM_PERF_COUNTERS 6 }; -enum mlx4_en_mclist_act { - MCLIST_NONE, - MCLIST_REM, - MCLIST_ADD, -}; - -struct mlx4_en_mc_list { - struct list_head list; - enum mlx4_en_mclist_act action; - u8 addr[ETH_ALEN]; - u64 reg_id; -}; - struct mlx4_en_frag_info { u16 frag_size; u16 frag_prefix_size; @@ -436,11 +422,6 @@ struct mlx4_en_frag_info { #endif -struct ethtool_flow_id { - struct ethtool_rx_flow_spec flow_spec; - u64 id; -}; - struct mlx4_en_priv { struct mlx4_en_dev *mdev; struct mlx4_en_port_profile *prof; @@ -450,7 +431,6 @@ struct mlx4_en_priv { struct net_device_stats ret_stats; struct mlx4_en_port_state port_state; spinlock_t stats_lock; - struct ethtool_flow_id ethtool_rules[MAX_NUM_OF_FS_RULES]; unsigned long last_moder_packets[MAX_RX_RINGS]; unsigned long last_moder_tx_packets; @@ -500,7 +480,6 @@ struct mlx4_en_priv { struct mlx4_en_rx_ring rx_ring[MAX_RX_RINGS]; struct mlx4_en_cq *tx_cq; struct mlx4_en_cq rx_cq[MAX_RX_RINGS]; - struct mlx4_qp drop_qp; struct work_struct mcast_task; struct work_struct mac_task; struct work_struct watchdog_task; @@ -510,9 +489,8 @@ struct mlx4_en_priv { struct mlx4_en_pkt_stats pkstats; struct mlx4_en_port_stats port_stats; u64 stats_bitmap; - struct list_head mc_list; - struct list_head curr_list; - u64 broadcast_id; + char *mc_addrs; + int mc_addrs_cnt; struct mlx4_en_stat_out_mbox hw_stats; int vids[128]; bool wol; @@ -587,8 +565,6 @@ void mlx4_en_unmap_buffer(struct mlx4_buf *buf); void mlx4_en_calc_rx_buf(struct net_device *dev); int mlx4_en_config_rss_steer(struct mlx4_en_priv *priv); void mlx4_en_release_rss_steer(struct mlx4_en_priv *priv); -int mlx4_en_create_drop_qp(struct mlx4_en_priv *priv); -void mlx4_en_destroy_drop_qp(struct mlx4_en_priv *priv); int mlx4_en_free_tx_buf(struct net_device *dev, struct mlx4_en_tx_ring *ring); void mlx4_en_rx_irq(struct mlx4_cq *mcq); diff --git a/trunk/drivers/net/ethernet/mellanox/mlx4/port.c b/trunk/drivers/net/ethernet/mellanox/mlx4/port.c index a51d1b9bf1d1..a8fb52992c64 100644 --- a/trunk/drivers/net/ethernet/mellanox/mlx4/port.c +++ b/trunk/drivers/net/ethernet/mellanox/mlx4/port.c @@ -75,54 +75,21 @@ void mlx4_init_vlan_table(struct mlx4_dev *dev, struct mlx4_vlan_table *table) table->total = 0; } -static int mlx4_uc_steer_add(struct mlx4_dev *dev, u8 port, - u64 mac, int *qpn, u64 *reg_id) +static int mlx4_uc_steer_add(struct mlx4_dev *dev, u8 port, u64 mac, int *qpn) { + struct mlx4_qp qp; + u8 gid[16] = {0}; __be64 be_mac; int err; - mac &= MLX4_MAC_MASK; - be_mac = cpu_to_be64(mac << 16); - - switch (dev->caps.steering_mode) { - case MLX4_STEERING_MODE_B0: { - struct mlx4_qp qp; - u8 gid[16] = {0}; - - qp.qpn = *qpn; - memcpy(&gid[10], &be_mac, ETH_ALEN); - gid[5] = port; - - err = mlx4_unicast_attach(dev, &qp, gid, 0, MLX4_PROT_ETH); - break; - } - case MLX4_STEERING_MODE_DEVICE_MANAGED: { - struct mlx4_spec_list spec_eth = { {NULL} }; - __be64 mac_mask = cpu_to_be64(MLX4_MAC_MASK << 16); - - struct mlx4_net_trans_rule rule = { - .queue_mode = MLX4_NET_TRANS_Q_FIFO, - .exclusive = 0, - .allow_loopback = 1, - .promisc_mode = MLX4_FS_PROMISC_NONE, - .priority = MLX4_DOMAIN_NIC, - }; + qp.qpn = *qpn; - rule.port = port; - rule.qpn = *qpn; - INIT_LIST_HEAD(&rule.list); - - spec_eth.id = MLX4_NET_TRANS_RULE_ID_ETH; - memcpy(spec_eth.eth.dst_mac, &be_mac, ETH_ALEN); - memcpy(spec_eth.eth.dst_mac_msk, &mac_mask, ETH_ALEN); - list_add_tail(&spec_eth.list, &rule.list); + mac &= 0xffffffffffffULL; + be_mac = cpu_to_be64(mac << 16); + memcpy(&gid[10], &be_mac, ETH_ALEN); + gid[5] = port; - err = mlx4_flow_attach(dev, &rule, reg_id); - break; - } - default: - return -EINVAL; - } + err = mlx4_unicast_attach(dev, &qp, gid, 0, MLX4_PROT_ETH); if (err) mlx4_warn(dev, "Failed Attaching Unicast\n"); @@ -130,30 +97,19 @@ static int mlx4_uc_steer_add(struct mlx4_dev *dev, u8 port, } static void mlx4_uc_steer_release(struct mlx4_dev *dev, u8 port, - u64 mac, int qpn, u64 reg_id) + u64 mac, int qpn) { - switch (dev->caps.steering_mode) { - case MLX4_STEERING_MODE_B0: { - struct mlx4_qp qp; - u8 gid[16] = {0}; - __be64 be_mac; + struct mlx4_qp qp; + u8 gid[16] = {0}; + __be64 be_mac; - qp.qpn = qpn; - mac &= MLX4_MAC_MASK; - be_mac = cpu_to_be64(mac << 16); - memcpy(&gid[10], &be_mac, ETH_ALEN); - gid[5] = port; + qp.qpn = qpn; + mac &= 0xffffffffffffULL; + be_mac = cpu_to_be64(mac << 16); + memcpy(&gid[10], &be_mac, ETH_ALEN); + gid[5] = port; - mlx4_unicast_detach(dev, &qp, gid, MLX4_PROT_ETH); - break; - } - case MLX4_STEERING_MODE_DEVICE_MANAGED: { - mlx4_flow_detach(dev, reg_id); - break; - } - default: - mlx4_err(dev, "Invalid steering mode.\n"); - } + mlx4_unicast_detach(dev, &qp, gid, MLX4_PROT_ETH); } static int validate_index(struct mlx4_dev *dev, @@ -188,7 +144,6 @@ int mlx4_get_eth_qp(struct mlx4_dev *dev, u8 port, u64 mac, int *qpn) struct mlx4_mac_entry *entry; int index = 0; int err = 0; - u64 reg_id; mlx4_dbg(dev, "Registering MAC: 0x%llx for adding\n", (unsigned long long) mac); @@ -200,7 +155,7 @@ int mlx4_get_eth_qp(struct mlx4_dev *dev, u8 port, u64 mac, int *qpn) return err; } - if (dev->caps.steering_mode == MLX4_STEERING_MODE_A0) { + if (!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER)) { *qpn = info->base_qpn + index; return 0; } @@ -212,7 +167,7 @@ int mlx4_get_eth_qp(struct mlx4_dev *dev, u8 port, u64 mac, int *qpn) goto qp_err; } - err = mlx4_uc_steer_add(dev, port, mac, qpn, ®_id); + err = mlx4_uc_steer_add(dev, port, mac, qpn); if (err) goto steer_err; @@ -222,7 +177,6 @@ int mlx4_get_eth_qp(struct mlx4_dev *dev, u8 port, u64 mac, int *qpn) goto alloc_err; } entry->mac = mac; - entry->reg_id = reg_id; err = radix_tree_insert(&info->mac_tree, *qpn, entry); if (err) goto insert_err; @@ -232,7 +186,7 @@ int mlx4_get_eth_qp(struct mlx4_dev *dev, u8 port, u64 mac, int *qpn) kfree(entry); alloc_err: - mlx4_uc_steer_release(dev, port, mac, *qpn, reg_id); + mlx4_uc_steer_release(dev, port, mac, *qpn); steer_err: mlx4_qp_release_range(dev, *qpn, 1); @@ -252,14 +206,13 @@ void mlx4_put_eth_qp(struct mlx4_dev *dev, u8 port, u64 mac, int qpn) (unsigned long long) mac); mlx4_unregister_mac(dev, port, mac); - if (dev->caps.steering_mode != MLX4_STEERING_MODE_A0) { + if (dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER) { entry = radix_tree_lookup(&info->mac_tree, qpn); if (entry) { mlx4_dbg(dev, "Releasing qp: port %d, mac 0x%llx," " qpn %d\n", port, (unsigned long long) mac, qpn); - mlx4_uc_steer_release(dev, port, entry->mac, - qpn, entry->reg_id); + mlx4_uc_steer_release(dev, port, entry->mac, qpn); mlx4_qp_release_range(dev, qpn, 1); radix_tree_delete(&info->mac_tree, qpn); kfree(entry); @@ -406,18 +359,15 @@ int mlx4_replace_mac(struct mlx4_dev *dev, u8 port, int qpn, u64 new_mac) int index = qpn - info->base_qpn; int err = 0; - if (dev->caps.steering_mode != MLX4_STEERING_MODE_A0) { + if (dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER) { entry = radix_tree_lookup(&info->mac_tree, qpn); if (!entry) return -EINVAL; - mlx4_uc_steer_release(dev, port, entry->mac, - qpn, entry->reg_id); + mlx4_uc_steer_release(dev, port, entry->mac, qpn); mlx4_unregister_mac(dev, port, entry->mac); entry->mac = new_mac; - entry->reg_id = 0; mlx4_register_mac(dev, port, new_mac); - err = mlx4_uc_steer_add(dev, port, entry->mac, - &qpn, &entry->reg_id); + err = mlx4_uc_steer_add(dev, port, entry->mac, &qpn); return err; } @@ -853,7 +803,8 @@ int mlx4_SET_PORT_qpn_calc(struct mlx4_dev *dev, u8 port, u32 base_qpn, u32 m_promisc = (dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER) ? MCAST_DIRECT : MCAST_DEFAULT; - if (dev->caps.steering_mode != MLX4_STEERING_MODE_A0) + if (dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER && + dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER) return 0; mailbox = mlx4_alloc_cmd_mailbox(dev); diff --git a/trunk/drivers/net/ethernet/mellanox/mlx4/profile.c b/trunk/drivers/net/ethernet/mellanox/mlx4/profile.c index 9ee4725363d5..b83bc928d52a 100644 --- a/trunk/drivers/net/ethernet/mellanox/mlx4/profile.c +++ b/trunk/drivers/net/ethernet/mellanox/mlx4/profile.c @@ -237,19 +237,13 @@ u64 mlx4_make_profile(struct mlx4_dev *dev, init_hca->mtt_base = profile[i].start; break; case MLX4_RES_MCG: + dev->caps.num_mgms = profile[i].num >> 1; + dev->caps.num_amgms = profile[i].num >> 1; init_hca->mc_base = profile[i].start; init_hca->log_mc_entry_sz = ilog2(mlx4_get_mgm_entry_size(dev)); init_hca->log_mc_table_sz = profile[i].log_num; - if (dev->caps.steering_mode == - MLX4_STEERING_MODE_DEVICE_MANAGED) { - dev->caps.num_mgms = profile[i].num; - } else { - init_hca->log_mc_hash_sz = - profile[i].log_num - 1; - dev->caps.num_mgms = profile[i].num >> 1; - dev->caps.num_amgms = profile[i].num >> 1; - } + init_hca->log_mc_hash_sz = profile[i].log_num - 1; break; default: break; diff --git a/trunk/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c b/trunk/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c index c3fa91986190..766b8c5a235e 100644 --- a/trunk/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c +++ b/trunk/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c @@ -57,8 +57,7 @@ struct mac_res { struct res_common { struct list_head list; - struct rb_node node; - u64 res_id; + u32 res_id; int owner; int state; int from_state; @@ -190,58 +189,6 @@ struct res_xrcdn { int port; }; -enum res_fs_rule_states { - RES_FS_RULE_BUSY = RES_ANY_BUSY, - RES_FS_RULE_ALLOCATED, -}; - -struct res_fs_rule { - struct res_common com; -}; - -static void *res_tracker_lookup(struct rb_root *root, u64 res_id) -{ - struct rb_node *node = root->rb_node; - - while (node) { - struct res_common *res = container_of(node, struct res_common, - node); - - if (res_id < res->res_id) - node = node->rb_left; - else if (res_id > res->res_id) - node = node->rb_right; - else - return res; - } - return NULL; -} - -static int res_tracker_insert(struct rb_root *root, struct res_common *res) -{ - struct rb_node **new = &(root->rb_node), *parent = NULL; - - /* Figure out where to put new node */ - while (*new) { - struct res_common *this = container_of(*new, struct res_common, - node); - - parent = *new; - if (res->res_id < this->res_id) - new = &((*new)->rb_left); - else if (res->res_id > this->res_id) - new = &((*new)->rb_right); - else - return -EEXIST; - } - - /* Add new node and rebalance tree. */ - rb_link_node(&res->node, parent, new); - rb_insert_color(&res->node, root); - - return 0; -} - /* For Debug uses */ static const char *ResourceType(enum mlx4_resource rt) { @@ -254,7 +201,6 @@ static const char *ResourceType(enum mlx4_resource rt) case RES_MAC: return "RES_MAC"; case RES_EQ: return "RES_EQ"; case RES_COUNTER: return "RES_COUNTER"; - case RES_FS_RULE: return "RES_FS_RULE"; case RES_XRCD: return "RES_XRCD"; default: return "Unknown resource type !!!"; }; @@ -282,7 +228,8 @@ int mlx4_init_resource_tracker(struct mlx4_dev *dev) mlx4_dbg(dev, "Started init_resource_tracker: %ld slaves\n", dev->num_slaves); for (i = 0 ; i < MLX4_NUM_OF_RESOURCE_TYPE; i++) - priv->mfunc.master.res_tracker.res_tree[i] = RB_ROOT; + INIT_RADIX_TREE(&priv->mfunc.master.res_tracker.res_tree[i], + GFP_ATOMIC|__GFP_NOWARN); spin_lock_init(&priv->mfunc.master.res_tracker.lock); return 0 ; @@ -330,11 +277,11 @@ static void *find_res(struct mlx4_dev *dev, int res_id, { struct mlx4_priv *priv = mlx4_priv(dev); - return res_tracker_lookup(&priv->mfunc.master.res_tracker.res_tree[type], - res_id); + return radix_tree_lookup(&priv->mfunc.master.res_tracker.res_tree[type], + res_id); } -static int get_res(struct mlx4_dev *dev, int slave, u64 res_id, +static int get_res(struct mlx4_dev *dev, int slave, int res_id, enum mlx4_resource type, void *res) { @@ -360,7 +307,7 @@ static int get_res(struct mlx4_dev *dev, int slave, u64 res_id, r->from_state = r->state; r->state = RES_ANY_BUSY; - mlx4_dbg(dev, "res %s id 0x%llx to busy\n", + mlx4_dbg(dev, "res %s id 0x%x to busy\n", ResourceType(type), r->res_id); if (res) @@ -373,7 +320,7 @@ static int get_res(struct mlx4_dev *dev, int slave, u64 res_id, int mlx4_get_slave_from_resource_id(struct mlx4_dev *dev, enum mlx4_resource type, - u64 res_id, int *slave) + int res_id, int *slave) { struct res_common *r; @@ -394,7 +341,7 @@ int mlx4_get_slave_from_resource_id(struct mlx4_dev *dev, return err; } -static void put_res(struct mlx4_dev *dev, int slave, u64 res_id, +static void put_res(struct mlx4_dev *dev, int slave, int res_id, enum mlx4_resource type) { struct res_common *r; @@ -526,21 +473,7 @@ static struct res_common *alloc_xrcdn_tr(int id) return &ret->com; } -static struct res_common *alloc_fs_rule_tr(u64 id) -{ - struct res_fs_rule *ret; - - ret = kzalloc(sizeof *ret, GFP_KERNEL); - if (!ret) - return NULL; - - ret->com.res_id = id; - ret->com.state = RES_FS_RULE_ALLOCATED; - - return &ret->com; -} - -static struct res_common *alloc_tr(u64 id, enum mlx4_resource type, int slave, +static struct res_common *alloc_tr(int id, enum mlx4_resource type, int slave, int extra) { struct res_common *ret; @@ -573,9 +506,6 @@ static struct res_common *alloc_tr(u64 id, enum mlx4_resource type, int slave, case RES_XRCD: ret = alloc_xrcdn_tr(id); break; - case RES_FS_RULE: - ret = alloc_fs_rule_tr(id); - break; default: return NULL; } @@ -585,7 +515,7 @@ static struct res_common *alloc_tr(u64 id, enum mlx4_resource type, int slave, return ret; } -static int add_res_range(struct mlx4_dev *dev, int slave, u64 base, int count, +static int add_res_range(struct mlx4_dev *dev, int slave, int base, int count, enum mlx4_resource type, int extra) { int i; @@ -593,7 +523,7 @@ static int add_res_range(struct mlx4_dev *dev, int slave, u64 base, int count, struct mlx4_priv *priv = mlx4_priv(dev); struct res_common **res_arr; struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker; - struct rb_root *root = &tracker->res_tree[type]; + struct radix_tree_root *root = &tracker->res_tree[type]; res_arr = kzalloc(count * sizeof *res_arr, GFP_KERNEL); if (!res_arr) @@ -616,7 +546,7 @@ static int add_res_range(struct mlx4_dev *dev, int slave, u64 base, int count, err = -EEXIST; goto undo; } - err = res_tracker_insert(root, res_arr[i]); + err = radix_tree_insert(root, base + i, res_arr[i]); if (err) goto undo; list_add_tail(&res_arr[i]->list, @@ -629,7 +559,7 @@ static int add_res_range(struct mlx4_dev *dev, int slave, u64 base, int count, undo: for (--i; i >= base; --i) - rb_erase(&res_arr[i]->node, root); + radix_tree_delete(&tracker->res_tree[type], i); spin_unlock_irq(mlx4_tlock(dev)); @@ -708,16 +638,6 @@ static int remove_xrcdn_ok(struct res_xrcdn *res) return 0; } -static int remove_fs_rule_ok(struct res_fs_rule *res) -{ - if (res->com.state == RES_FS_RULE_BUSY) - return -EBUSY; - else if (res->com.state != RES_FS_RULE_ALLOCATED) - return -EPERM; - - return 0; -} - static int remove_cq_ok(struct res_cq *res) { if (res->com.state == RES_CQ_BUSY) @@ -759,17 +679,15 @@ static int remove_ok(struct res_common *res, enum mlx4_resource type, int extra) return remove_counter_ok((struct res_counter *)res); case RES_XRCD: return remove_xrcdn_ok((struct res_xrcdn *)res); - case RES_FS_RULE: - return remove_fs_rule_ok((struct res_fs_rule *)res); default: return -EINVAL; } } -static int rem_res_range(struct mlx4_dev *dev, int slave, u64 base, int count, +static int rem_res_range(struct mlx4_dev *dev, int slave, int base, int count, enum mlx4_resource type, int extra) { - u64 i; + int i; int err; struct mlx4_priv *priv = mlx4_priv(dev); struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker; @@ -777,7 +695,7 @@ static int rem_res_range(struct mlx4_dev *dev, int slave, u64 base, int count, spin_lock_irq(mlx4_tlock(dev)); for (i = base; i < base + count; ++i) { - r = res_tracker_lookup(&tracker->res_tree[type], i); + r = radix_tree_lookup(&tracker->res_tree[type], i); if (!r) { err = -ENOENT; goto out; @@ -792,8 +710,8 @@ static int rem_res_range(struct mlx4_dev *dev, int slave, u64 base, int count, } for (i = base; i < base + count; ++i) { - r = res_tracker_lookup(&tracker->res_tree[type], i); - rb_erase(&r->node, &tracker->res_tree[type]); + r = radix_tree_lookup(&tracker->res_tree[type], i); + radix_tree_delete(&tracker->res_tree[type], i); list_del(&r->list); kfree(r); } @@ -815,7 +733,7 @@ static int qp_res_start_move_to(struct mlx4_dev *dev, int slave, int qpn, int err = 0; spin_lock_irq(mlx4_tlock(dev)); - r = res_tracker_lookup(&tracker->res_tree[RES_QP], qpn); + r = radix_tree_lookup(&tracker->res_tree[RES_QP], qpn); if (!r) err = -ENOENT; else if (r->com.owner != slave) @@ -823,7 +741,7 @@ static int qp_res_start_move_to(struct mlx4_dev *dev, int slave, int qpn, else { switch (state) { case RES_QP_BUSY: - mlx4_dbg(dev, "%s: failed RES_QP, 0x%llx\n", + mlx4_dbg(dev, "%s: failed RES_QP, 0x%x\n", __func__, r->com.res_id); err = -EBUSY; break; @@ -832,7 +750,7 @@ static int qp_res_start_move_to(struct mlx4_dev *dev, int slave, int qpn, if (r->com.state == RES_QP_MAPPED && !alloc) break; - mlx4_dbg(dev, "failed RES_QP, 0x%llx\n", r->com.res_id); + mlx4_dbg(dev, "failed RES_QP, 0x%x\n", r->com.res_id); err = -EINVAL; break; @@ -841,7 +759,7 @@ static int qp_res_start_move_to(struct mlx4_dev *dev, int slave, int qpn, r->com.state == RES_QP_HW) break; else { - mlx4_dbg(dev, "failed RES_QP, 0x%llx\n", + mlx4_dbg(dev, "failed RES_QP, 0x%x\n", r->com.res_id); err = -EINVAL; } @@ -879,7 +797,7 @@ static int mr_res_start_move_to(struct mlx4_dev *dev, int slave, int index, int err = 0; spin_lock_irq(mlx4_tlock(dev)); - r = res_tracker_lookup(&tracker->res_tree[RES_MPT], index); + r = radix_tree_lookup(&tracker->res_tree[RES_MPT], index); if (!r) err = -ENOENT; else if (r->com.owner != slave) @@ -932,7 +850,7 @@ static int eq_res_start_move_to(struct mlx4_dev *dev, int slave, int index, int err = 0; spin_lock_irq(mlx4_tlock(dev)); - r = res_tracker_lookup(&tracker->res_tree[RES_EQ], index); + r = radix_tree_lookup(&tracker->res_tree[RES_EQ], index); if (!r) err = -ENOENT; else if (r->com.owner != slave) @@ -980,7 +898,7 @@ static int cq_res_start_move_to(struct mlx4_dev *dev, int slave, int cqn, int err; spin_lock_irq(mlx4_tlock(dev)); - r = res_tracker_lookup(&tracker->res_tree[RES_CQ], cqn); + r = radix_tree_lookup(&tracker->res_tree[RES_CQ], cqn); if (!r) err = -ENOENT; else if (r->com.owner != slave) @@ -1034,7 +952,7 @@ static int srq_res_start_move_to(struct mlx4_dev *dev, int slave, int index, int err = 0; spin_lock_irq(mlx4_tlock(dev)); - r = res_tracker_lookup(&tracker->res_tree[RES_SRQ], index); + r = radix_tree_lookup(&tracker->res_tree[RES_SRQ], index); if (!r) err = -ENOENT; else if (r->com.owner != slave) @@ -1083,7 +1001,7 @@ static void res_abort_move(struct mlx4_dev *dev, int slave, struct res_common *r; spin_lock_irq(mlx4_tlock(dev)); - r = res_tracker_lookup(&tracker->res_tree[type], id); + r = radix_tree_lookup(&tracker->res_tree[type], id); if (r && (r->owner == slave)) r->state = r->from_state; spin_unlock_irq(mlx4_tlock(dev)); @@ -1097,7 +1015,7 @@ static void res_end_move(struct mlx4_dev *dev, int slave, struct res_common *r; spin_lock_irq(mlx4_tlock(dev)); - r = res_tracker_lookup(&tracker->res_tree[type], id); + r = radix_tree_lookup(&tracker->res_tree[type], id); if (r && (r->owner == slave)) r->state = r->to_state; spin_unlock_irq(mlx4_tlock(dev)); @@ -2777,60 +2695,6 @@ int mlx4_QP_ATTACH_wrapper(struct mlx4_dev *dev, int slave, return err; } -int mlx4_QP_FLOW_STEERING_ATTACH_wrapper(struct mlx4_dev *dev, int slave, - struct mlx4_vhcr *vhcr, - struct mlx4_cmd_mailbox *inbox, - struct mlx4_cmd_mailbox *outbox, - struct mlx4_cmd_info *cmd) -{ - int err; - - if (dev->caps.steering_mode != - MLX4_STEERING_MODE_DEVICE_MANAGED) - return -EOPNOTSUPP; - - err = mlx4_cmd_imm(dev, inbox->dma, &vhcr->out_param, - vhcr->in_modifier, 0, - MLX4_QP_FLOW_STEERING_ATTACH, MLX4_CMD_TIME_CLASS_A, - MLX4_CMD_NATIVE); - if (err) - return err; - - err = add_res_range(dev, slave, vhcr->out_param, 1, RES_FS_RULE, 0); - if (err) { - mlx4_err(dev, "Fail to add flow steering resources.\n "); - /* detach rule*/ - mlx4_cmd(dev, vhcr->out_param, 0, 0, - MLX4_QP_FLOW_STEERING_ATTACH, MLX4_CMD_TIME_CLASS_A, - MLX4_CMD_NATIVE); - } - return err; -} - -int mlx4_QP_FLOW_STEERING_DETACH_wrapper(struct mlx4_dev *dev, int slave, - struct mlx4_vhcr *vhcr, - struct mlx4_cmd_mailbox *inbox, - struct mlx4_cmd_mailbox *outbox, - struct mlx4_cmd_info *cmd) -{ - int err; - - if (dev->caps.steering_mode != - MLX4_STEERING_MODE_DEVICE_MANAGED) - return -EOPNOTSUPP; - - err = rem_res_range(dev, slave, vhcr->in_param, 1, RES_FS_RULE, 0); - if (err) { - mlx4_err(dev, "Fail to remove flow steering resources.\n "); - return err; - } - - err = mlx4_cmd(dev, vhcr->in_param, 0, 0, - MLX4_QP_FLOW_STEERING_DETACH, MLX4_CMD_TIME_CLASS_A, - MLX4_CMD_NATIVE); - return err; -} - enum { BUSY_MAX_RETRIES = 10 }; @@ -2887,7 +2751,7 @@ static int _move_all_busy(struct mlx4_dev *dev, int slave, if (r->state == RES_ANY_BUSY) { if (print) mlx4_dbg(dev, - "%s id 0x%llx is busy\n", + "%s id 0x%x is busy\n", ResourceType(type), r->res_id); ++busy; @@ -2953,8 +2817,8 @@ static void rem_slave_qps(struct mlx4_dev *dev, int slave) switch (state) { case RES_QP_RESERVED: spin_lock_irq(mlx4_tlock(dev)); - rb_erase(&qp->com.node, - &tracker->res_tree[RES_QP]); + radix_tree_delete(&tracker->res_tree[RES_QP], + qp->com.res_id); list_del(&qp->com.list); spin_unlock_irq(mlx4_tlock(dev)); kfree(qp); @@ -3024,8 +2888,8 @@ static void rem_slave_srqs(struct mlx4_dev *dev, int slave) case RES_SRQ_ALLOCATED: __mlx4_srq_free_icm(dev, srqn); spin_lock_irq(mlx4_tlock(dev)); - rb_erase(&srq->com.node, - &tracker->res_tree[RES_SRQ]); + radix_tree_delete(&tracker->res_tree[RES_SRQ], + srqn); list_del(&srq->com.list); spin_unlock_irq(mlx4_tlock(dev)); kfree(srq); @@ -3090,8 +2954,8 @@ static void rem_slave_cqs(struct mlx4_dev *dev, int slave) case RES_CQ_ALLOCATED: __mlx4_cq_free_icm(dev, cqn); spin_lock_irq(mlx4_tlock(dev)); - rb_erase(&cq->com.node, - &tracker->res_tree[RES_CQ]); + radix_tree_delete(&tracker->res_tree[RES_CQ], + cqn); list_del(&cq->com.list); spin_unlock_irq(mlx4_tlock(dev)); kfree(cq); @@ -3153,8 +3017,8 @@ static void rem_slave_mrs(struct mlx4_dev *dev, int slave) case RES_MPT_RESERVED: __mlx4_mr_release(dev, mpt->key); spin_lock_irq(mlx4_tlock(dev)); - rb_erase(&mpt->com.node, - &tracker->res_tree[RES_MPT]); + radix_tree_delete(&tracker->res_tree[RES_MPT], + mptn); list_del(&mpt->com.list); spin_unlock_irq(mlx4_tlock(dev)); kfree(mpt); @@ -3222,8 +3086,8 @@ static void rem_slave_mtts(struct mlx4_dev *dev, int slave) __mlx4_free_mtt_range(dev, base, mtt->order); spin_lock_irq(mlx4_tlock(dev)); - rb_erase(&mtt->com.node, - &tracker->res_tree[RES_MTT]); + radix_tree_delete(&tracker->res_tree[RES_MTT], + base); list_del(&mtt->com.list); spin_unlock_irq(mlx4_tlock(dev)); kfree(mtt); @@ -3240,58 +3104,6 @@ static void rem_slave_mtts(struct mlx4_dev *dev, int slave) spin_unlock_irq(mlx4_tlock(dev)); } -static void rem_slave_fs_rule(struct mlx4_dev *dev, int slave) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - struct mlx4_resource_tracker *tracker = - &priv->mfunc.master.res_tracker; - struct list_head *fs_rule_list = - &tracker->slave_list[slave].res_list[RES_FS_RULE]; - struct res_fs_rule *fs_rule; - struct res_fs_rule *tmp; - int state; - u64 base; - int err; - - err = move_all_busy(dev, slave, RES_FS_RULE); - if (err) - mlx4_warn(dev, "rem_slave_fs_rule: Could not move all mtts to busy for slave %d\n", - slave); - - spin_lock_irq(mlx4_tlock(dev)); - list_for_each_entry_safe(fs_rule, tmp, fs_rule_list, com.list) { - spin_unlock_irq(mlx4_tlock(dev)); - if (fs_rule->com.owner == slave) { - base = fs_rule->com.res_id; - state = fs_rule->com.from_state; - while (state != 0) { - switch (state) { - case RES_FS_RULE_ALLOCATED: - /* detach rule */ - err = mlx4_cmd(dev, base, 0, 0, - MLX4_QP_FLOW_STEERING_DETACH, - MLX4_CMD_TIME_CLASS_A, - MLX4_CMD_NATIVE); - - spin_lock_irq(mlx4_tlock(dev)); - rb_erase(&fs_rule->com.node, - &tracker->res_tree[RES_FS_RULE]); - list_del(&fs_rule->com.list); - spin_unlock_irq(mlx4_tlock(dev)); - kfree(fs_rule); - state = 0; - break; - - default: - state = 0; - } - } - } - spin_lock_irq(mlx4_tlock(dev)); - } - spin_unlock_irq(mlx4_tlock(dev)); -} - static void rem_slave_eqs(struct mlx4_dev *dev, int slave) { struct mlx4_priv *priv = mlx4_priv(dev); @@ -3321,8 +3133,8 @@ static void rem_slave_eqs(struct mlx4_dev *dev, int slave) switch (state) { case RES_EQ_RESERVED: spin_lock_irq(mlx4_tlock(dev)); - rb_erase(&eq->com.node, - &tracker->res_tree[RES_EQ]); + radix_tree_delete(&tracker->res_tree[RES_EQ], + eqn); list_del(&eq->com.list); spin_unlock_irq(mlx4_tlock(dev)); kfree(eq); @@ -3379,8 +3191,7 @@ static void rem_slave_counters(struct mlx4_dev *dev, int slave) list_for_each_entry_safe(counter, tmp, counter_list, com.list) { if (counter->com.owner == slave) { index = counter->com.res_id; - rb_erase(&counter->com.node, - &tracker->res_tree[RES_COUNTER]); + radix_tree_delete(&tracker->res_tree[RES_COUNTER], index); list_del(&counter->com.list); kfree(counter); __mlx4_counter_free(dev, index); @@ -3409,7 +3220,7 @@ static void rem_slave_xrcdns(struct mlx4_dev *dev, int slave) list_for_each_entry_safe(xrcd, tmp, xrcdn_list, com.list) { if (xrcd->com.owner == slave) { xrcdn = xrcd->com.res_id; - rb_erase(&xrcd->com.node, &tracker->res_tree[RES_XRCD]); + radix_tree_delete(&tracker->res_tree[RES_XRCD], xrcdn); list_del(&xrcd->com.list); kfree(xrcd); __mlx4_xrcd_free(dev, xrcdn); @@ -3433,6 +3244,5 @@ void mlx4_delete_all_resources_for_slave(struct mlx4_dev *dev, int slave) rem_slave_mtts(dev, slave); rem_slave_counters(dev, slave); rem_slave_xrcdns(dev, slave); - rem_slave_fs_rule(dev, slave); mutex_unlock(&priv->mfunc.master.res_tracker.slave_list[slave].mutex); } diff --git a/trunk/drivers/net/ethernet/micrel/ks8851.c b/trunk/drivers/net/ethernet/micrel/ks8851.c index 1540ebeb8669..5e313e9a252f 100644 --- a/trunk/drivers/net/ethernet/micrel/ks8851.c +++ b/trunk/drivers/net/ethernet/micrel/ks8851.c @@ -422,7 +422,7 @@ static void ks8851_read_mac_addr(struct net_device *dev) * * Get or create the initial mac address for the device and then set that * into the station address register. If there is an EEPROM present, then - * we try that. If no valid mac address is found we use eth_random_addr() + * we try that. If no valid mac address is found we use random_ether_addr() * to create a new one. */ static void ks8851_init_mac(struct ks8851_net *ks) diff --git a/trunk/drivers/net/ethernet/micrel/ks8851_mll.c b/trunk/drivers/net/ethernet/micrel/ks8851_mll.c index 38529edfe350..875dd5e264eb 100644 --- a/trunk/drivers/net/ethernet/micrel/ks8851_mll.c +++ b/trunk/drivers/net/ethernet/micrel/ks8851_mll.c @@ -16,7 +16,8 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* Supports: +/** + * Supports: * KS8851 16bit MLL chip from Micrel Inc. */ @@ -464,7 +465,8 @@ static int msg_enable; #define BE1 0x2000 /* Byte Enable 1 */ #define BE0 0x1000 /* Byte Enable 0 */ -/* register read/write calls. +/** + * register read/write calls. * * All these calls issue transactions to access the chip's registers. They * all require that the necessary lock is held to prevent accesses when the @@ -1101,7 +1103,7 @@ static void ks_set_grpaddr(struct ks_net *ks) } } /* ks_set_grpaddr */ -/** +/* * ks_clear_mcast - clear multicast information * * @ks : The chip information @@ -1609,7 +1611,7 @@ static int __devinit ks8851_probe(struct platform_device *pdev) memcpy(ks->mac_addr, pdata->mac_addr, 6); if (!is_valid_ether_addr(ks->mac_addr)) { /* Use random MAC address if none passed */ - eth_random_addr(ks->mac_addr); + random_ether_addr(ks->mac_addr); netdev_info(netdev, "Using random mac address\n"); } netdev_info(netdev, "Mac address is: %pM\n", ks->mac_addr); diff --git a/trunk/drivers/net/ethernet/micrel/ksz884x.c b/trunk/drivers/net/ethernet/micrel/ksz884x.c index 318fee91c79d..eaf9ff0262a9 100644 --- a/trunk/drivers/net/ethernet/micrel/ksz884x.c +++ b/trunk/drivers/net/ethernet/micrel/ksz884x.c @@ -3913,7 +3913,7 @@ static void hw_start_rx(struct ksz_hw *hw) hw->rx_stop = 2; } -/** +/* * hw_stop_rx - stop receiving * @hw: The hardware instance. * @@ -4480,12 +4480,14 @@ static void ksz_init_rx_buffers(struct dev_info *adapter) dma_buf->len = adapter->mtu; if (!dma_buf->skb) dma_buf->skb = alloc_skb(dma_buf->len, GFP_ATOMIC); - if (dma_buf->skb && !dma_buf->dma) + if (dma_buf->skb && !dma_buf->dma) { + dma_buf->skb->dev = adapter->dev; dma_buf->dma = pci_map_single( adapter->pdev, skb_tail_pointer(dma_buf->skb), dma_buf->len, PCI_DMA_FROMDEVICE); + } /* Set descriptor. */ set_rx_buf(desc, dma_buf->dma); @@ -4879,8 +4881,8 @@ static netdev_tx_t netdev_tx(struct sk_buff *skb, struct net_device *dev) left = hw_alloc_pkt(hw, skb->len, num); if (left) { if (left < num || - (CHECKSUM_PARTIAL == skb->ip_summed && - skb->protocol == htons(ETH_P_IPV6))) { + ((CHECKSUM_PARTIAL == skb->ip_summed) && + (ETH_P_IPV6 == htons(skb->protocol)))) { struct sk_buff *org_skb = skb; skb = netdev_alloc_skb(dev, org_skb->len); diff --git a/trunk/drivers/net/ethernet/neterion/s2io.c b/trunk/drivers/net/ethernet/neterion/s2io.c index d958c2299372..e7cd587d8ae7 100644 --- a/trunk/drivers/net/ethernet/neterion/s2io.c +++ b/trunk/drivers/net/ethernet/neterion/s2io.c @@ -3377,7 +3377,7 @@ static int wait_for_cmd_complete(void __iomem *addr, u64 busy_bit, } while (cnt < 20); return ret; } -/** +/* * check_pci_device_id - Checks if the device id is supported * @id : device id * Description: Function to check if the pci device id is supported by driver. @@ -5238,7 +5238,7 @@ static u64 do_s2io_read_unicast_mc(struct s2io_nic *sp, int offset) } /** - * s2io_set_mac_addr - driver entry point + * s2io_set_mac_addr driver entry point */ static int s2io_set_mac_addr(struct net_device *dev, void *p) @@ -6088,7 +6088,7 @@ static int s2io_bist_test(struct s2io_nic *sp, uint64_t *data) } /** - * s2io_link_test - verifies the link state of the nic + * s2io-link_test - verifies the link state of the nic * @sp ; private member of the device structure, which is a pointer to the * s2io_nic structure. * @data: variable that returns the result of each of the test conducted by @@ -6116,9 +6116,9 @@ static int s2io_link_test(struct s2io_nic *sp, uint64_t *data) /** * s2io_rldram_test - offline test for access to the RldRam chip on the NIC - * @sp: private member of the device structure, which is a pointer to the + * @sp - private member of the device structure, which is a pointer to the * s2io_nic structure. - * @data: variable that returns the result of each of the test + * @data - variable that returns the result of each of the test * conducted by the driver. * Description: * This is one of the offline test that tests the read and write diff --git a/trunk/drivers/net/ethernet/neterion/vxge/vxge-main.c b/trunk/drivers/net/ethernet/neterion/vxge/vxge-main.c index 4e20c5f02712..2fd1edbc5e0e 100644 --- a/trunk/drivers/net/ethernet/neterion/vxge/vxge-main.c +++ b/trunk/drivers/net/ethernet/neterion/vxge/vxge-main.c @@ -4261,7 +4261,9 @@ static int vxge_probe_fw_update(struct vxgedev *vdev) if (VXGE_FW_VER(VXGE_CERT_FW_VER_MAJOR, VXGE_CERT_FW_VER_MINOR, 0) > VXGE_FW_VER(maj, min, 0)) { vxge_debug_init(VXGE_ERR, "%s: Firmware %d.%d.%d is too old to" - " be used with this driver.", + " be used with this driver.\n" + "Please get the latest version from " + "ftp://ftp.s2io.com/pub/X3100-Drivers/FIRMWARE", VXGE_DRIVER_NAME, maj, min, bld); return -EINVAL; } diff --git a/trunk/drivers/net/ethernet/neterion/vxge/vxge-main.h b/trunk/drivers/net/ethernet/neterion/vxge/vxge-main.h index 36ca40f8f249..35f3e7552ec2 100644 --- a/trunk/drivers/net/ethernet/neterion/vxge/vxge-main.h +++ b/trunk/drivers/net/ethernet/neterion/vxge/vxge-main.h @@ -430,7 +430,8 @@ void vxge_initialize_ethtool_ops(struct net_device *ndev); enum vxge_hw_status vxge_reset_all_vpaths(struct vxgedev *vdev); int vxge_fw_upgrade(struct vxgedev *vdev, char *fw_name, int override); -/* #define VXGE_DEBUG_INIT: debug for initialization functions +/** + * #define VXGE_DEBUG_INIT: debug for initialization functions * #define VXGE_DEBUG_TX : debug transmit related functions * #define VXGE_DEBUG_RX : debug recevice related functions * #define VXGE_DEBUG_MEM : debug memory module diff --git a/trunk/drivers/net/ethernet/nvidia/forcedeth.c b/trunk/drivers/net/ethernet/nvidia/forcedeth.c index 8b7c5129c7e1..928913c4f3ff 100644 --- a/trunk/drivers/net/ethernet/nvidia/forcedeth.c +++ b/trunk/drivers/net/ethernet/nvidia/forcedeth.c @@ -3218,7 +3218,7 @@ static void nv_force_linkspeed(struct net_device *dev, int speed, int duplex) } /** - * nv_update_linkspeed - Setup the MAC according to the link partner + * nv_update_linkspeed: Setup the MAC according to the link partner * @dev: Network device to be configured * * The function queries the PHY and checks if there is a link partner. @@ -3552,7 +3552,8 @@ static irqreturn_t nv_nic_irq(int foo, void *data) return IRQ_HANDLED; } -/* All _optimized functions are used to help increase performance +/** + * All _optimized functions are used to help increase performance * (reduce CPU and increase throughput). They use descripter version 3, * compiler directives, and reduce memory accesses. */ diff --git a/trunk/drivers/net/ethernet/nxp/lpc_eth.c b/trunk/drivers/net/ethernet/nxp/lpc_eth.c index 4069edab229e..e7d2496a4738 100644 --- a/trunk/drivers/net/ethernet/nxp/lpc_eth.c +++ b/trunk/drivers/net/ethernet/nxp/lpc_eth.c @@ -44,6 +44,7 @@ #include #include +#include #include #include #include diff --git a/trunk/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_api.c b/trunk/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_api.c index 5ae03e815ee9..e48f084ad226 100644 --- a/trunk/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_api.c +++ b/trunk/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_api.c @@ -60,7 +60,7 @@ static void pch_gbe_plat_get_bus_info(struct pch_gbe_hw *hw) /** * pch_gbe_plat_init_hw - Initialize hardware * @hw: Pointer to the HW structure - * Returns: + * Returns * 0: Successfully * Negative value: Failed-EBUSY */ @@ -108,7 +108,7 @@ static void pch_gbe_plat_init_function_pointers(struct pch_gbe_hw *hw) /** * pch_gbe_hal_setup_init_funcs - Initializes function pointers * @hw: Pointer to the HW structure - * Returns: + * Returns * 0: Successfully * ENOSYS: Function is not registered */ @@ -137,7 +137,7 @@ inline void pch_gbe_hal_get_bus_info(struct pch_gbe_hw *hw) /** * pch_gbe_hal_init_hw - Initialize hardware * @hw: Pointer to the HW structure - * Returns: + * Returns * 0: Successfully * ENOSYS: Function is not registered */ @@ -155,7 +155,7 @@ inline s32 pch_gbe_hal_init_hw(struct pch_gbe_hw *hw) * @hw: Pointer to the HW structure * @offset: The register to read * @data: The buffer to store the 16-bit read. - * Returns: + * Returns * 0: Successfully * Negative value: Failed */ @@ -172,7 +172,7 @@ inline s32 pch_gbe_hal_read_phy_reg(struct pch_gbe_hw *hw, u32 offset, * @hw: Pointer to the HW structure * @offset: The register to read * @data: The value to write. - * Returns: + * Returns * 0: Successfully * Negative value: Failed */ @@ -211,7 +211,7 @@ inline void pch_gbe_hal_phy_sw_reset(struct pch_gbe_hw *hw) /** * pch_gbe_hal_read_mac_addr - Reads MAC address * @hw: Pointer to the HW structure - * Returns: + * Returns * 0: Successfully * ENOSYS: Function is not registered */ diff --git a/trunk/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_ethtool.c b/trunk/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_ethtool.c index 9dbf38c10a68..ac4e72d529e5 100644 --- a/trunk/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_ethtool.c +++ b/trunk/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_ethtool.c @@ -77,7 +77,7 @@ static const struct pch_gbe_stats pch_gbe_gstrings_stats[] = { * pch_gbe_get_settings - Get device-specific settings * @netdev: Network interface device structure * @ecmd: Ethtool command - * Returns: + * Returns * 0: Successful. * Negative value: Failed. */ @@ -100,7 +100,7 @@ static int pch_gbe_get_settings(struct net_device *netdev, * pch_gbe_set_settings - Set device-specific settings * @netdev: Network interface device structure * @ecmd: Ethtool command - * Returns: + * Returns * 0: Successful. * Negative value: Failed. */ @@ -220,7 +220,7 @@ static void pch_gbe_get_wol(struct net_device *netdev, * pch_gbe_set_wol - Turn Wake-on-Lan on or off * @netdev: Network interface device structure * @wol: Pointer of wake-on-Lan information straucture - * Returns: + * Returns * 0: Successful. * Negative value: Failed. */ @@ -248,7 +248,7 @@ static int pch_gbe_set_wol(struct net_device *netdev, /** * pch_gbe_nway_reset - Restart autonegotiation * @netdev: Network interface device structure - * Returns: + * Returns * 0: Successful. * Negative value: Failed. */ @@ -398,7 +398,7 @@ static void pch_gbe_get_pauseparam(struct net_device *netdev, * pch_gbe_set_pauseparam - Set pause paramters * @netdev: Network interface device structure * @pause: Pause parameters structure - * Returns: + * Returns * 0: Successful. * Negative value: Failed. */ diff --git a/trunk/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c b/trunk/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c index b1006563f736..3787c64ee71c 100644 --- a/trunk/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c +++ b/trunk/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c @@ -301,7 +301,7 @@ inline void pch_gbe_mac_load_mac_addr(struct pch_gbe_hw *hw) /** * pch_gbe_mac_read_mac_addr - Read MAC address * @hw: Pointer to the HW structure - * Returns: + * Returns * 0: Successful. */ s32 pch_gbe_mac_read_mac_addr(struct pch_gbe_hw *hw) @@ -483,7 +483,7 @@ static void pch_gbe_mac_mc_addr_list_update(struct pch_gbe_hw *hw, /** * pch_gbe_mac_force_mac_fc - Force the MAC's flow control settings * @hw: Pointer to the HW structure - * Returns: + * Returns * 0: Successful. * Negative value: Failed. */ @@ -639,7 +639,7 @@ static void pch_gbe_mac_set_pause_packet(struct pch_gbe_hw *hw) /** * pch_gbe_alloc_queues - Allocate memory for all rings * @adapter: Board private structure to initialize - * Returns: + * Returns * 0: Successfully * Negative value: Failed */ @@ -670,7 +670,7 @@ static void pch_gbe_init_stats(struct pch_gbe_adapter *adapter) /** * pch_gbe_init_phy - Initialize PHY * @adapter: Board private structure to initialize - * Returns: + * Returns * 0: Successfully * Negative value: Failed */ @@ -720,7 +720,7 @@ static int pch_gbe_init_phy(struct pch_gbe_adapter *adapter) * @netdev: Network interface device structure * @addr: Phy ID * @reg: Access location - * Returns: + * Returns * 0: Successfully * Negative value: Failed */ @@ -1364,7 +1364,7 @@ static void pch_gbe_start_receive(struct pch_gbe_hw *hw) * pch_gbe_intr - Interrupt Handler * @irq: Interrupt number * @data: Pointer to a network interface device structure - * Returns: + * Returns * - IRQ_HANDLED: Our interrupt * - IRQ_NONE: Not our interrupt */ @@ -1566,7 +1566,7 @@ static void pch_gbe_alloc_tx_buffers(struct pch_gbe_adapter *adapter, * pch_gbe_clean_tx - Reclaim resources after transmit completes * @adapter: Board private structure * @tx_ring: Tx descriptor ring - * Returns: + * Returns * true: Cleaned the descriptor * false: Not cleaned the descriptor */ @@ -1660,7 +1660,7 @@ pch_gbe_clean_tx(struct pch_gbe_adapter *adapter, * @rx_ring: Rx descriptor ring * @work_done: Completed count * @work_to_do: Request count - * Returns: + * Returns * true: Cleaned the descriptor * false: Not cleaned the descriptor */ @@ -1775,7 +1775,7 @@ pch_gbe_clean_rx(struct pch_gbe_adapter *adapter, * pch_gbe_setup_tx_resources - Allocate Tx resources (Descriptors) * @adapter: Board private structure * @tx_ring: Tx descriptor ring (for a specific queue) to setup - * Returns: + * Returns * 0: Successfully * Negative value: Failed */ @@ -1822,7 +1822,7 @@ int pch_gbe_setup_tx_resources(struct pch_gbe_adapter *adapter, * pch_gbe_setup_rx_resources - Allocate Rx resources (Descriptors) * @adapter: Board private structure * @rx_ring: Rx descriptor ring (for a specific queue) to setup - * Returns: + * Returns * 0: Successfully * Negative value: Failed */ @@ -1899,7 +1899,7 @@ void pch_gbe_free_rx_resources(struct pch_gbe_adapter *adapter, /** * pch_gbe_request_irq - Allocate an interrupt line * @adapter: Board private structure - * Returns: + * Returns * 0: Successfully * Negative value: Failed */ @@ -1932,7 +1932,7 @@ static int pch_gbe_request_irq(struct pch_gbe_adapter *adapter) /** * pch_gbe_up - Up GbE network device * @adapter: Board private structure - * Returns: + * Returns * 0: Successfully * Negative value: Failed */ @@ -2018,7 +2018,7 @@ void pch_gbe_down(struct pch_gbe_adapter *adapter) /** * pch_gbe_sw_init - Initialize general software structures (struct pch_gbe_adapter) * @adapter: Board private structure to initialize - * Returns: + * Returns * 0: Successfully * Negative value: Failed */ @@ -2057,7 +2057,7 @@ static int pch_gbe_sw_init(struct pch_gbe_adapter *adapter) /** * pch_gbe_open - Called when a network interface is made active * @netdev: Network interface device structure - * Returns: + * Returns * 0: Successfully * Negative value: Failed */ @@ -2097,7 +2097,7 @@ static int pch_gbe_open(struct net_device *netdev) /** * pch_gbe_stop - Disables a network interface * @netdev: Network interface device structure - * Returns: + * Returns * 0: Successfully */ static int pch_gbe_stop(struct net_device *netdev) @@ -2117,7 +2117,7 @@ static int pch_gbe_stop(struct net_device *netdev) * pch_gbe_xmit_frame - Packet transmitting start * @skb: Socket buffer structure * @netdev: Network interface device structure - * Returns: + * Returns * - NETDEV_TX_OK: Normal end * - NETDEV_TX_BUSY: Error end */ @@ -2225,7 +2225,7 @@ static void pch_gbe_set_multi(struct net_device *netdev) * pch_gbe_set_mac - Change the Ethernet Address of the NIC * @netdev: Network interface device structure * @addr: Pointer to an address structure - * Returns: + * Returns * 0: Successfully * -EADDRNOTAVAIL: Failed */ @@ -2256,7 +2256,7 @@ static int pch_gbe_set_mac(struct net_device *netdev, void *addr) * pch_gbe_change_mtu - Change the Maximum Transfer Unit * @netdev: Network interface device structure * @new_mtu: New value for maximum frame size - * Returns: + * Returns * 0: Successfully * -EINVAL: Failed */ @@ -2309,7 +2309,7 @@ static int pch_gbe_change_mtu(struct net_device *netdev, int new_mtu) * pch_gbe_set_features - Reset device after features changed * @netdev: Network interface device structure * @features: New features - * Returns: + * Returns * 0: HW state updated successfully */ static int pch_gbe_set_features(struct net_device *netdev, @@ -2334,7 +2334,7 @@ static int pch_gbe_set_features(struct net_device *netdev, * @netdev: Network interface device structure * @ifr: Pointer to ifr structure * @cmd: Control command - * Returns: + * Returns * 0: Successfully * Negative value: Failed */ @@ -2369,7 +2369,7 @@ static void pch_gbe_tx_timeout(struct net_device *netdev) * pch_gbe_napi_poll - NAPI receive and transfer polling callback * @napi: Pointer of polling device struct * @budget: The maximum number of a packet - * Returns: + * Returns * false: Exit the polling mode * true: Continue the polling mode */ diff --git a/trunk/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_param.c b/trunk/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_param.c index 8653c3b81f84..29e23bec809c 100644 --- a/trunk/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_param.c +++ b/trunk/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_param.c @@ -139,7 +139,7 @@ MODULE_PARM_DESC(XsumTX, "Disable or enable Transmit Checksum offload"); /** * pch_gbe_option - Force the MAC's flow control settings * @hw: Pointer to the HW structure - * Returns: + * Returns * 0: Successful. * Negative value: Failed. */ @@ -220,7 +220,7 @@ static const struct pch_gbe_opt_list fc_list[] = { * @value: value * @opt: option * @adapter: Board private structure - * Returns: + * Returns * 0: Successful. * Negative value: Failed. */ diff --git a/trunk/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c b/trunk/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c index bc165f4d0f65..8694124ef77d 100644 --- a/trunk/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c +++ b/trunk/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c @@ -1437,6 +1437,8 @@ netxen_handle_linkevent(struct netxen_adapter *adapter, nx_fw_msg_t *msg) netdev->name, cable_len); } + netxen_advert_link_change(adapter, link_status); + /* update link parameters */ if (duplex == LINKEVENT_FULL_DUPLEX) adapter->link_duplex = DUPLEX_FULL; @@ -1445,8 +1447,6 @@ netxen_handle_linkevent(struct netxen_adapter *adapter, nx_fw_msg_t *msg) adapter->module_type = module; adapter->link_autoneg = autoneg; adapter->link_speed = link_speed; - - netxen_advert_link_change(adapter, link_status); } static void @@ -1532,6 +1532,8 @@ static struct sk_buff *netxen_process_rxbuf(struct netxen_adapter *adapter, } else skb->ip_summed = CHECKSUM_NONE; + skb->dev = adapter->netdev; + buffer->skb = NULL; no_skb: buffer->state = NETXEN_BUFFER_FREE; diff --git a/trunk/drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c b/trunk/drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c index 0bcda9c51e9b..8620b696aca8 100644 --- a/trunk/drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c +++ b/trunk/drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c @@ -1488,6 +1488,8 @@ static struct sk_buff *qlcnic_process_rxbuf(struct qlcnic_adapter *adapter, skb_checksum_none_assert(skb); } + skb->dev = adapter->netdev; + buffer->skb = NULL; return skb; diff --git a/trunk/drivers/net/ethernet/qlogic/qlge/qlge.h b/trunk/drivers/net/ethernet/qlogic/qlge/qlge.h index a131d7b5d2fe..5a639df33f18 100644 --- a/trunk/drivers/net/ethernet/qlogic/qlge/qlge.h +++ b/trunk/drivers/net/ethernet/qlogic/qlge/qlge.h @@ -18,15 +18,13 @@ */ #define DRV_NAME "qlge" #define DRV_STRING "QLogic 10 Gigabit PCI-E Ethernet Driver " -#define DRV_VERSION "v1.00.00.31" +#define DRV_VERSION "v1.00.00.30.00.00-01" #define WQ_ADDR_ALIGN 0x3 /* 4 byte alignment */ #define QLGE_VENDOR_ID 0x1077 #define QLGE_DEVICE_ID_8012 0x8012 #define QLGE_DEVICE_ID_8000 0x8000 -#define QLGE_MEZZ_SSYS_ID_068 0x0068 -#define QLGE_MEZZ_SSYS_ID_180 0x0180 #define MAX_CPUS 8 #define MAX_TX_RINGS MAX_CPUS #define MAX_RX_RINGS ((MAX_CPUS * 2) + 1) @@ -1399,6 +1397,7 @@ struct tx_ring { struct tx_ring_desc *q; /* descriptor list for the queue */ spinlock_t lock; atomic_t tx_count; /* counts down for every outstanding IO */ + atomic_t queue_stopped; /* Turns queue off when full. */ struct delayed_work tx_work; struct ql_adapter *qdev; u64 tx_packets; @@ -1536,14 +1535,6 @@ struct nic_stats { u64 rx_1024_to_1518_pkts; u64 rx_1519_to_max_pkts; u64 rx_len_err_pkts; - /* Receive Mac Err stats */ - u64 rx_code_err; - u64 rx_oversize_err; - u64 rx_undersize_err; - u64 rx_preamble_err; - u64 rx_frame_len_err; - u64 rx_crc_err; - u64 rx_err_count; /* * These stats come from offset 500h to 5C8h * in the XGMAC register. diff --git a/trunk/drivers/net/ethernet/qlogic/qlge/qlge_ethtool.c b/trunk/drivers/net/ethernet/qlogic/qlge/qlge_ethtool.c index 3d4462bd9de7..8e2c2a74f3a5 100644 --- a/trunk/drivers/net/ethernet/qlogic/qlge/qlge_ethtool.c +++ b/trunk/drivers/net/ethernet/qlogic/qlge/qlge_ethtool.c @@ -35,152 +35,10 @@ #include "qlge.h" -struct ql_stats { - char stat_string[ETH_GSTRING_LEN]; - int sizeof_stat; - int stat_offset; -}; - -#define QL_SIZEOF(m) FIELD_SIZEOF(struct ql_adapter, m) -#define QL_OFF(m) offsetof(struct ql_adapter, m) - -static const struct ql_stats ql_gstrings_stats[] = { - {"tx_pkts", QL_SIZEOF(nic_stats.tx_pkts), QL_OFF(nic_stats.tx_pkts)}, - {"tx_bytes", QL_SIZEOF(nic_stats.tx_bytes), QL_OFF(nic_stats.tx_bytes)}, - {"tx_mcast_pkts", QL_SIZEOF(nic_stats.tx_mcast_pkts), - QL_OFF(nic_stats.tx_mcast_pkts)}, - {"tx_bcast_pkts", QL_SIZEOF(nic_stats.tx_bcast_pkts), - QL_OFF(nic_stats.tx_bcast_pkts)}, - {"tx_ucast_pkts", QL_SIZEOF(nic_stats.tx_ucast_pkts), - QL_OFF(nic_stats.tx_ucast_pkts)}, - {"tx_ctl_pkts", QL_SIZEOF(nic_stats.tx_ctl_pkts), - QL_OFF(nic_stats.tx_ctl_pkts)}, - {"tx_pause_pkts", QL_SIZEOF(nic_stats.tx_pause_pkts), - QL_OFF(nic_stats.tx_pause_pkts)}, - {"tx_64_pkts", QL_SIZEOF(nic_stats.tx_64_pkt), - QL_OFF(nic_stats.tx_64_pkt)}, - {"tx_65_to_127_pkts", QL_SIZEOF(nic_stats.tx_65_to_127_pkt), - QL_OFF(nic_stats.tx_65_to_127_pkt)}, - {"tx_128_to_255_pkts", QL_SIZEOF(nic_stats.tx_128_to_255_pkt), - QL_OFF(nic_stats.tx_128_to_255_pkt)}, - {"tx_256_511_pkts", QL_SIZEOF(nic_stats.tx_256_511_pkt), - QL_OFF(nic_stats.tx_256_511_pkt)}, - {"tx_512_to_1023_pkts", QL_SIZEOF(nic_stats.tx_512_to_1023_pkt), - QL_OFF(nic_stats.tx_512_to_1023_pkt)}, - {"tx_1024_to_1518_pkts", QL_SIZEOF(nic_stats.tx_1024_to_1518_pkt), - QL_OFF(nic_stats.tx_1024_to_1518_pkt)}, - {"tx_1519_to_max_pkts", QL_SIZEOF(nic_stats.tx_1519_to_max_pkt), - QL_OFF(nic_stats.tx_1519_to_max_pkt)}, - {"tx_undersize_pkts", QL_SIZEOF(nic_stats.tx_undersize_pkt), - QL_OFF(nic_stats.tx_undersize_pkt)}, - {"tx_oversize_pkts", QL_SIZEOF(nic_stats.tx_oversize_pkt), - QL_OFF(nic_stats.tx_oversize_pkt)}, - {"rx_bytes", QL_SIZEOF(nic_stats.rx_bytes), QL_OFF(nic_stats.rx_bytes)}, - {"rx_bytes_ok", QL_SIZEOF(nic_stats.rx_bytes_ok), - QL_OFF(nic_stats.rx_bytes_ok)}, - {"rx_pkts", QL_SIZEOF(nic_stats.rx_pkts), QL_OFF(nic_stats.rx_pkts)}, - {"rx_pkts_ok", QL_SIZEOF(nic_stats.rx_pkts_ok), - QL_OFF(nic_stats.rx_pkts_ok)}, - {"rx_bcast_pkts", QL_SIZEOF(nic_stats.rx_bcast_pkts), - QL_OFF(nic_stats.rx_bcast_pkts)}, - {"rx_mcast_pkts", QL_SIZEOF(nic_stats.rx_mcast_pkts), - QL_OFF(nic_stats.rx_mcast_pkts)}, - {"rx_ucast_pkts", QL_SIZEOF(nic_stats.rx_ucast_pkts), - QL_OFF(nic_stats.rx_ucast_pkts)}, - {"rx_undersize_pkts", QL_SIZEOF(nic_stats.rx_undersize_pkts), - QL_OFF(nic_stats.rx_undersize_pkts)}, - {"rx_oversize_pkts", QL_SIZEOF(nic_stats.rx_oversize_pkts), - QL_OFF(nic_stats.rx_oversize_pkts)}, - {"rx_jabber_pkts", QL_SIZEOF(nic_stats.rx_jabber_pkts), - QL_OFF(nic_stats.rx_jabber_pkts)}, - {"rx_undersize_fcerr_pkts", - QL_SIZEOF(nic_stats.rx_undersize_fcerr_pkts), - QL_OFF(nic_stats.rx_undersize_fcerr_pkts)}, - {"rx_drop_events", QL_SIZEOF(nic_stats.rx_drop_events), - QL_OFF(nic_stats.rx_drop_events)}, - {"rx_fcerr_pkts", QL_SIZEOF(nic_stats.rx_fcerr_pkts), - QL_OFF(nic_stats.rx_fcerr_pkts)}, - {"rx_align_err", QL_SIZEOF(nic_stats.rx_align_err), - QL_OFF(nic_stats.rx_align_err)}, - {"rx_symbol_err", QL_SIZEOF(nic_stats.rx_symbol_err), - QL_OFF(nic_stats.rx_symbol_err)}, - {"rx_mac_err", QL_SIZEOF(nic_stats.rx_mac_err), - QL_OFF(nic_stats.rx_mac_err)}, - {"rx_ctl_pkts", QL_SIZEOF(nic_stats.rx_ctl_pkts), - QL_OFF(nic_stats.rx_ctl_pkts)}, - {"rx_pause_pkts", QL_SIZEOF(nic_stats.rx_pause_pkts), - QL_OFF(nic_stats.rx_pause_pkts)}, - {"rx_64_pkts", QL_SIZEOF(nic_stats.rx_64_pkts), - QL_OFF(nic_stats.rx_64_pkts)}, - {"rx_65_to_127_pkts", QL_SIZEOF(nic_stats.rx_65_to_127_pkts), - QL_OFF(nic_stats.rx_65_to_127_pkts)}, - {"rx_128_255_pkts", QL_SIZEOF(nic_stats.rx_128_255_pkts), - QL_OFF(nic_stats.rx_128_255_pkts)}, - {"rx_256_511_pkts", QL_SIZEOF(nic_stats.rx_256_511_pkts), - QL_OFF(nic_stats.rx_256_511_pkts)}, - {"rx_512_to_1023_pkts", QL_SIZEOF(nic_stats.rx_512_to_1023_pkts), - QL_OFF(nic_stats.rx_512_to_1023_pkts)}, - {"rx_1024_to_1518_pkts", QL_SIZEOF(nic_stats.rx_1024_to_1518_pkts), - QL_OFF(nic_stats.rx_1024_to_1518_pkts)}, - {"rx_1519_to_max_pkts", QL_SIZEOF(nic_stats.rx_1519_to_max_pkts), - QL_OFF(nic_stats.rx_1519_to_max_pkts)}, - {"rx_len_err_pkts", QL_SIZEOF(nic_stats.rx_len_err_pkts), - QL_OFF(nic_stats.rx_len_err_pkts)}, - {"rx_code_err", QL_SIZEOF(nic_stats.rx_code_err), - QL_OFF(nic_stats.rx_code_err)}, - {"rx_oversize_err", QL_SIZEOF(nic_stats.rx_oversize_err), - QL_OFF(nic_stats.rx_oversize_err)}, - {"rx_undersize_err", QL_SIZEOF(nic_stats.rx_undersize_err), - QL_OFF(nic_stats.rx_undersize_err)}, - {"rx_preamble_err", QL_SIZEOF(nic_stats.rx_preamble_err), - QL_OFF(nic_stats.rx_preamble_err)}, - {"rx_frame_len_err", QL_SIZEOF(nic_stats.rx_frame_len_err), - QL_OFF(nic_stats.rx_frame_len_err)}, - {"rx_crc_err", QL_SIZEOF(nic_stats.rx_crc_err), - QL_OFF(nic_stats.rx_crc_err)}, - {"rx_err_count", QL_SIZEOF(nic_stats.rx_err_count), - QL_OFF(nic_stats.rx_err_count)}, - {"tx_cbfc_pause_frames0", QL_SIZEOF(nic_stats.tx_cbfc_pause_frames0), - QL_OFF(nic_stats.tx_cbfc_pause_frames0)}, - {"tx_cbfc_pause_frames1", QL_SIZEOF(nic_stats.tx_cbfc_pause_frames1), - QL_OFF(nic_stats.tx_cbfc_pause_frames1)}, - {"tx_cbfc_pause_frames2", QL_SIZEOF(nic_stats.tx_cbfc_pause_frames2), - QL_OFF(nic_stats.tx_cbfc_pause_frames2)}, - {"tx_cbfc_pause_frames3", QL_SIZEOF(nic_stats.tx_cbfc_pause_frames3), - QL_OFF(nic_stats.tx_cbfc_pause_frames3)}, - {"tx_cbfc_pause_frames4", QL_SIZEOF(nic_stats.tx_cbfc_pause_frames4), - QL_OFF(nic_stats.tx_cbfc_pause_frames4)}, - {"tx_cbfc_pause_frames5", QL_SIZEOF(nic_stats.tx_cbfc_pause_frames5), - QL_OFF(nic_stats.tx_cbfc_pause_frames5)}, - {"tx_cbfc_pause_frames6", QL_SIZEOF(nic_stats.tx_cbfc_pause_frames6), - QL_OFF(nic_stats.tx_cbfc_pause_frames6)}, - {"tx_cbfc_pause_frames7", QL_SIZEOF(nic_stats.tx_cbfc_pause_frames7), - QL_OFF(nic_stats.tx_cbfc_pause_frames7)}, - {"rx_cbfc_pause_frames0", QL_SIZEOF(nic_stats.rx_cbfc_pause_frames0), - QL_OFF(nic_stats.rx_cbfc_pause_frames0)}, - {"rx_cbfc_pause_frames1", QL_SIZEOF(nic_stats.rx_cbfc_pause_frames1), - QL_OFF(nic_stats.rx_cbfc_pause_frames1)}, - {"rx_cbfc_pause_frames2", QL_SIZEOF(nic_stats.rx_cbfc_pause_frames2), - QL_OFF(nic_stats.rx_cbfc_pause_frames2)}, - {"rx_cbfc_pause_frames3", QL_SIZEOF(nic_stats.rx_cbfc_pause_frames3), - QL_OFF(nic_stats.rx_cbfc_pause_frames3)}, - {"rx_cbfc_pause_frames4", QL_SIZEOF(nic_stats.rx_cbfc_pause_frames4), - QL_OFF(nic_stats.rx_cbfc_pause_frames4)}, - {"rx_cbfc_pause_frames5", QL_SIZEOF(nic_stats.rx_cbfc_pause_frames5), - QL_OFF(nic_stats.rx_cbfc_pause_frames5)}, - {"rx_cbfc_pause_frames6", QL_SIZEOF(nic_stats.rx_cbfc_pause_frames6), - QL_OFF(nic_stats.rx_cbfc_pause_frames6)}, - {"rx_cbfc_pause_frames7", QL_SIZEOF(nic_stats.rx_cbfc_pause_frames7), - QL_OFF(nic_stats.rx_cbfc_pause_frames7)}, - {"rx_nic_fifo_drop", QL_SIZEOF(nic_stats.rx_nic_fifo_drop), - QL_OFF(nic_stats.rx_nic_fifo_drop)}, -}; - static const char ql_gstrings_test[][ETH_GSTRING_LEN] = { "Loopback test (offline)" }; #define QLGE_TEST_LEN (sizeof(ql_gstrings_test) / ETH_GSTRING_LEN) -#define QLGE_STATS_LEN ARRAY_SIZE(ql_gstrings_stats) static int ql_update_ring_coalescing(struct ql_adapter *qdev) { @@ -325,19 +183,73 @@ static void ql_update_stats(struct ql_adapter *qdev) QL_DUMP_STAT(qdev); } +static char ql_stats_str_arr[][ETH_GSTRING_LEN] = { + {"tx_pkts"}, + {"tx_bytes"}, + {"tx_mcast_pkts"}, + {"tx_bcast_pkts"}, + {"tx_ucast_pkts"}, + {"tx_ctl_pkts"}, + {"tx_pause_pkts"}, + {"tx_64_pkts"}, + {"tx_65_to_127_pkts"}, + {"tx_128_to_255_pkts"}, + {"tx_256_511_pkts"}, + {"tx_512_to_1023_pkts"}, + {"tx_1024_to_1518_pkts"}, + {"tx_1519_to_max_pkts"}, + {"tx_undersize_pkts"}, + {"tx_oversize_pkts"}, + {"rx_bytes"}, + {"rx_bytes_ok"}, + {"rx_pkts"}, + {"rx_pkts_ok"}, + {"rx_bcast_pkts"}, + {"rx_mcast_pkts"}, + {"rx_ucast_pkts"}, + {"rx_undersize_pkts"}, + {"rx_oversize_pkts"}, + {"rx_jabber_pkts"}, + {"rx_undersize_fcerr_pkts"}, + {"rx_drop_events"}, + {"rx_fcerr_pkts"}, + {"rx_align_err"}, + {"rx_symbol_err"}, + {"rx_mac_err"}, + {"rx_ctl_pkts"}, + {"rx_pause_pkts"}, + {"rx_64_pkts"}, + {"rx_65_to_127_pkts"}, + {"rx_128_255_pkts"}, + {"rx_256_511_pkts"}, + {"rx_512_to_1023_pkts"}, + {"rx_1024_to_1518_pkts"}, + {"rx_1519_to_max_pkts"}, + {"rx_len_err_pkts"}, + {"tx_cbfc_pause_frames0"}, + {"tx_cbfc_pause_frames1"}, + {"tx_cbfc_pause_frames2"}, + {"tx_cbfc_pause_frames3"}, + {"tx_cbfc_pause_frames4"}, + {"tx_cbfc_pause_frames5"}, + {"tx_cbfc_pause_frames6"}, + {"tx_cbfc_pause_frames7"}, + {"rx_cbfc_pause_frames0"}, + {"rx_cbfc_pause_frames1"}, + {"rx_cbfc_pause_frames2"}, + {"rx_cbfc_pause_frames3"}, + {"rx_cbfc_pause_frames4"}, + {"rx_cbfc_pause_frames5"}, + {"rx_cbfc_pause_frames6"}, + {"rx_cbfc_pause_frames7"}, + {"rx_nic_fifo_drop"}, +}; + static void ql_get_strings(struct net_device *dev, u32 stringset, u8 *buf) { - int index; switch (stringset) { - case ETH_SS_TEST: - memcpy(buf, *ql_gstrings_test, QLGE_TEST_LEN * ETH_GSTRING_LEN); - break; case ETH_SS_STATS: - for (index = 0; index < QLGE_STATS_LEN; index++) { - memcpy(buf + index * ETH_GSTRING_LEN, - ql_gstrings_stats[index].stat_string, - ETH_GSTRING_LEN); - } + memcpy(buf, ql_stats_str_arr, sizeof(ql_stats_str_arr)); break; } } @@ -348,7 +260,7 @@ static int ql_get_sset_count(struct net_device *dev, int sset) case ETH_SS_TEST: return QLGE_TEST_LEN; case ETH_SS_STATS: - return QLGE_STATS_LEN; + return ARRAY_SIZE(ql_stats_str_arr); default: return -EOPNOTSUPP; } @@ -359,17 +271,69 @@ ql_get_ethtool_stats(struct net_device *ndev, struct ethtool_stats *stats, u64 *data) { struct ql_adapter *qdev = netdev_priv(ndev); - int index, length; + struct nic_stats *s = &qdev->nic_stats; - length = QLGE_STATS_LEN; ql_update_stats(qdev); - for (index = 0; index < length; index++) { - char *p = (char *)qdev + - ql_gstrings_stats[index].stat_offset; - *data++ = (ql_gstrings_stats[index].sizeof_stat == - sizeof(u64)) ? *(u64 *)p : (*(u32 *)p); - } + *data++ = s->tx_pkts; + *data++ = s->tx_bytes; + *data++ = s->tx_mcast_pkts; + *data++ = s->tx_bcast_pkts; + *data++ = s->tx_ucast_pkts; + *data++ = s->tx_ctl_pkts; + *data++ = s->tx_pause_pkts; + *data++ = s->tx_64_pkt; + *data++ = s->tx_65_to_127_pkt; + *data++ = s->tx_128_to_255_pkt; + *data++ = s->tx_256_511_pkt; + *data++ = s->tx_512_to_1023_pkt; + *data++ = s->tx_1024_to_1518_pkt; + *data++ = s->tx_1519_to_max_pkt; + *data++ = s->tx_undersize_pkt; + *data++ = s->tx_oversize_pkt; + *data++ = s->rx_bytes; + *data++ = s->rx_bytes_ok; + *data++ = s->rx_pkts; + *data++ = s->rx_pkts_ok; + *data++ = s->rx_bcast_pkts; + *data++ = s->rx_mcast_pkts; + *data++ = s->rx_ucast_pkts; + *data++ = s->rx_undersize_pkts; + *data++ = s->rx_oversize_pkts; + *data++ = s->rx_jabber_pkts; + *data++ = s->rx_undersize_fcerr_pkts; + *data++ = s->rx_drop_events; + *data++ = s->rx_fcerr_pkts; + *data++ = s->rx_align_err; + *data++ = s->rx_symbol_err; + *data++ = s->rx_mac_err; + *data++ = s->rx_ctl_pkts; + *data++ = s->rx_pause_pkts; + *data++ = s->rx_64_pkts; + *data++ = s->rx_65_to_127_pkts; + *data++ = s->rx_128_255_pkts; + *data++ = s->rx_256_511_pkts; + *data++ = s->rx_512_to_1023_pkts; + *data++ = s->rx_1024_to_1518_pkts; + *data++ = s->rx_1519_to_max_pkts; + *data++ = s->rx_len_err_pkts; + *data++ = s->tx_cbfc_pause_frames0; + *data++ = s->tx_cbfc_pause_frames1; + *data++ = s->tx_cbfc_pause_frames2; + *data++ = s->tx_cbfc_pause_frames3; + *data++ = s->tx_cbfc_pause_frames4; + *data++ = s->tx_cbfc_pause_frames5; + *data++ = s->tx_cbfc_pause_frames6; + *data++ = s->tx_cbfc_pause_frames7; + *data++ = s->rx_cbfc_pause_frames0; + *data++ = s->rx_cbfc_pause_frames1; + *data++ = s->rx_cbfc_pause_frames2; + *data++ = s->rx_cbfc_pause_frames3; + *data++ = s->rx_cbfc_pause_frames4; + *data++ = s->rx_cbfc_pause_frames5; + *data++ = s->rx_cbfc_pause_frames6; + *data++ = s->rx_cbfc_pause_frames7; + *data++ = s->rx_nic_fifo_drop; } static int ql_get_settings(struct net_device *ndev, @@ -424,33 +388,30 @@ static void ql_get_drvinfo(struct net_device *ndev, static void ql_get_wol(struct net_device *ndev, struct ethtool_wolinfo *wol) { struct ql_adapter *qdev = netdev_priv(ndev); - unsigned short ssys_dev = qdev->pdev->subsystem_device; - - /* WOL is only supported for mezz card. */ - if (ssys_dev == QLGE_MEZZ_SSYS_ID_068 || - ssys_dev == QLGE_MEZZ_SSYS_ID_180) { - wol->supported = WAKE_MAGIC; - wol->wolopts = qdev->wol; - } + /* What we support. */ + wol->supported = WAKE_MAGIC; + /* What we've currently got set. */ + wol->wolopts = qdev->wol; } static int ql_set_wol(struct net_device *ndev, struct ethtool_wolinfo *wol) { struct ql_adapter *qdev = netdev_priv(ndev); - unsigned short ssys_dev = qdev->pdev->subsystem_device; + int status; - /* WOL is only supported for mezz card. */ - if (ssys_dev != QLGE_MEZZ_SSYS_ID_068 || - ssys_dev != QLGE_MEZZ_SSYS_ID_180) { - netif_info(qdev, drv, qdev->ndev, - "WOL is only supported for mezz card\n"); - return -EOPNOTSUPP; - } if (wol->wolopts & ~WAKE_MAGIC) return -EINVAL; qdev->wol = wol->wolopts; netif_info(qdev, drv, qdev->ndev, "Set wol option 0x%x\n", qdev->wol); + if (!qdev->wol) { + u32 wol = 0; + status = ql_mb_wol_mode(qdev, wol); + netif_err(qdev, drv, qdev->ndev, "WOL %s (wol code 0x%x)\n", + status == 0 ? "cleared successfully" : "clear failed", + wol); + } + return 0; } @@ -567,8 +528,6 @@ static void ql_self_test(struct net_device *ndev, { struct ql_adapter *qdev = netdev_priv(ndev); - memset(data, 0, sizeof(u64) * QLGE_TEST_LEN); - if (netif_running(ndev)) { set_bit(QL_SELFTEST, &qdev->flags); if (eth_test->flags == ETH_TEST_FL_OFFLINE) { diff --git a/trunk/drivers/net/ethernet/qlogic/qlge/qlge_main.c b/trunk/drivers/net/ethernet/qlogic/qlge/qlge_main.c index 3769f5711cc3..3c3499d928b9 100644 --- a/trunk/drivers/net/ethernet/qlogic/qlge/qlge_main.c +++ b/trunk/drivers/net/ethernet/qlogic/qlge/qlge_main.c @@ -1433,36 +1433,6 @@ static int ql_map_send(struct ql_adapter *qdev, return NETDEV_TX_BUSY; } -/* Categorizing receive firmware frame errors */ -static void ql_categorize_rx_err(struct ql_adapter *qdev, u8 rx_err) -{ - struct nic_stats *stats = &qdev->nic_stats; - - stats->rx_err_count++; - - switch (rx_err & IB_MAC_IOCB_RSP_ERR_MASK) { - case IB_MAC_IOCB_RSP_ERR_CODE_ERR: - stats->rx_code_err++; - break; - case IB_MAC_IOCB_RSP_ERR_OVERSIZE: - stats->rx_oversize_err++; - break; - case IB_MAC_IOCB_RSP_ERR_UNDERSIZE: - stats->rx_undersize_err++; - break; - case IB_MAC_IOCB_RSP_ERR_PREAMBLE: - stats->rx_preamble_err++; - break; - case IB_MAC_IOCB_RSP_ERR_FRAME_LEN: - stats->rx_frame_len_err++; - break; - case IB_MAC_IOCB_RSP_ERR_CRC: - stats->rx_crc_err++; - default: - break; - } -} - /* Process an inbound completion from an rx ring. */ static void ql_process_mac_rx_gro_page(struct ql_adapter *qdev, struct rx_ring *rx_ring, @@ -1529,6 +1499,15 @@ static void ql_process_mac_rx_page(struct ql_adapter *qdev, addr = lbq_desc->p.pg_chunk.va; prefetch(addr); + + /* Frame error, so drop the packet. */ + if (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_ERR_MASK) { + netif_info(qdev, drv, qdev->ndev, + "Receive error, flags2 = 0x%x\n", ib_mac_rsp->flags2); + rx_ring->rx_errors++; + goto err_out; + } + /* The max framesize filter on this chip is set higher than * MTU since FCoE uses 2k frames. */ @@ -1567,7 +1546,7 @@ static void ql_process_mac_rx_page(struct ql_adapter *qdev, struct iphdr *iph = (struct iphdr *) ((u8 *)addr + ETH_HLEN); if (!(iph->frag_off & - htons(IP_MF|IP_OFFSET))) { + cpu_to_be16(IP_MF|IP_OFFSET))) { skb->ip_summed = CHECKSUM_UNNECESSARY; netif_printk(qdev, rx_status, KERN_DEBUG, qdev->ndev, @@ -1614,6 +1593,15 @@ static void ql_process_mac_rx_skb(struct ql_adapter *qdev, memcpy(skb_put(new_skb, length), skb->data, length); skb = new_skb; + /* Frame error, so drop the packet. */ + if (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_ERR_MASK) { + netif_info(qdev, drv, qdev->ndev, + "Receive error, flags2 = 0x%x\n", ib_mac_rsp->flags2); + dev_kfree_skb_any(skb); + rx_ring->rx_errors++; + return; + } + /* loopback self test for ethtool */ if (test_bit(QL_SELFTEST, &qdev->flags)) { ql_check_lb_frame(qdev, skb); @@ -1631,6 +1619,7 @@ static void ql_process_mac_rx_skb(struct ql_adapter *qdev, } prefetch(skb->data); + skb->dev = ndev; if (ib_mac_rsp->flags1 & IB_MAC_IOCB_RSP_M_MASK) { netif_printk(qdev, rx_status, KERN_DEBUG, qdev->ndev, "%s Multicast.\n", @@ -1665,7 +1654,7 @@ static void ql_process_mac_rx_skb(struct ql_adapter *qdev, /* Unfragmented ipv4 UDP frame. */ struct iphdr *iph = (struct iphdr *) skb->data; if (!(iph->frag_off & - htons(IP_MF|IP_OFFSET))) { + ntohs(IP_MF|IP_OFFSET))) { skb->ip_summed = CHECKSUM_UNNECESSARY; netif_printk(qdev, rx_status, KERN_DEBUG, qdev->ndev, @@ -1919,6 +1908,15 @@ static void ql_process_mac_split_rx_intr(struct ql_adapter *qdev, return; } + /* Frame error, so drop the packet. */ + if (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_ERR_MASK) { + netif_info(qdev, drv, qdev->ndev, + "Receive error, flags2 = 0x%x\n", ib_mac_rsp->flags2); + dev_kfree_skb_any(skb); + rx_ring->rx_errors++; + return; + } + /* The max framesize filter on this chip is set higher than * MTU since FCoE uses 2k frames. */ @@ -1936,6 +1934,7 @@ static void ql_process_mac_split_rx_intr(struct ql_adapter *qdev, } prefetch(skb->data); + skb->dev = ndev; if (ib_mac_rsp->flags1 & IB_MAC_IOCB_RSP_M_MASK) { netif_printk(qdev, rx_status, KERN_DEBUG, qdev->ndev, "%s Multicast.\n", (ib_mac_rsp->flags1 & IB_MAC_IOCB_RSP_M_MASK) == @@ -1969,7 +1968,7 @@ static void ql_process_mac_split_rx_intr(struct ql_adapter *qdev, /* Unfragmented ipv4 UDP frame. */ struct iphdr *iph = (struct iphdr *) skb->data; if (!(iph->frag_off & - htons(IP_MF|IP_OFFSET))) { + ntohs(IP_MF|IP_OFFSET))) { skb->ip_summed = CHECKSUM_UNNECESSARY; netif_printk(qdev, rx_status, KERN_DEBUG, qdev->ndev, "TCP checksum done!\n"); @@ -2000,12 +1999,6 @@ static unsigned long ql_process_mac_rx_intr(struct ql_adapter *qdev, QL_DUMP_IB_MAC_RSP(ib_mac_rsp); - /* Frame error, so drop the packet. */ - if (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_ERR_MASK) { - ql_categorize_rx_err(qdev, ib_mac_rsp->flags2); - return (unsigned long)length; - } - if (ib_mac_rsp->flags4 & IB_MAC_IOCB_RSP_HV) { /* The data and headers are split into * separate buffers. @@ -2180,7 +2173,8 @@ static int ql_clean_outbound_rx_ring(struct rx_ring *rx_ring) ql_write_cq_idx(rx_ring); tx_ring = &qdev->tx_ring[net_rsp->txq_idx]; if (__netif_subqueue_stopped(qdev->ndev, tx_ring->wq_id)) { - if ((atomic_read(&tx_ring->tx_count) > (tx_ring->wq_len / 4))) + if (atomic_read(&tx_ring->queue_stopped) && + (atomic_read(&tx_ring->tx_count) > (tx_ring->wq_len / 4))) /* * The queue got stopped because the tx_ring was full. * Wake it up, because it's now at least 25% empty. @@ -2564,9 +2558,10 @@ static netdev_tx_t qlge_send(struct sk_buff *skb, struct net_device *ndev) if (unlikely(atomic_read(&tx_ring->tx_count) < 2)) { netif_info(qdev, tx_queued, qdev->ndev, - "%s: BUG! shutting down tx queue %d due to lack of resources.\n", + "%s: shutting down tx queue %d du to lack of resources.\n", __func__, tx_ring_idx); netif_stop_subqueue(ndev, tx_ring->wq_id); + atomic_inc(&tx_ring->queue_stopped); tx_ring->tx_errors++; return NETDEV_TX_BUSY; } @@ -2617,16 +2612,6 @@ static netdev_tx_t qlge_send(struct sk_buff *skb, struct net_device *ndev) tx_ring->prod_idx, skb->len); atomic_dec(&tx_ring->tx_count); - - if (unlikely(atomic_read(&tx_ring->tx_count) < 2)) { - netif_stop_subqueue(ndev, tx_ring->wq_id); - if ((atomic_read(&tx_ring->tx_count) > (tx_ring->wq_len / 4))) - /* - * The queue got stopped because the tx_ring was full. - * Wake it up, because it's now at least 25% empty. - */ - netif_wake_subqueue(qdev->ndev, tx_ring->wq_id); - } return NETDEV_TX_OK; } @@ -2695,6 +2680,7 @@ static void ql_init_tx_ring(struct ql_adapter *qdev, struct tx_ring *tx_ring) tx_ring_desc++; } atomic_set(&tx_ring->tx_count, tx_ring->wq_len); + atomic_set(&tx_ring->queue_stopped, 0); } static void ql_free_tx_resources(struct ql_adapter *qdev, @@ -2717,9 +2703,10 @@ static int ql_alloc_tx_resources(struct ql_adapter *qdev, &tx_ring->wq_base_dma); if ((tx_ring->wq_base == NULL) || - tx_ring->wq_base_dma & WQ_ADDR_ALIGN) - goto pci_alloc_err; - + tx_ring->wq_base_dma & WQ_ADDR_ALIGN) { + netif_err(qdev, ifup, qdev->ndev, "tx_ring alloc failed.\n"); + return -ENOMEM; + } tx_ring->q = kmalloc(tx_ring->wq_len * sizeof(struct tx_ring_desc), GFP_KERNEL); if (tx_ring->q == NULL) @@ -2729,9 +2716,6 @@ static int ql_alloc_tx_resources(struct ql_adapter *qdev, err: pci_free_consistent(qdev->pdev, tx_ring->wq_size, tx_ring->wq_base, tx_ring->wq_base_dma); - tx_ring->wq_base = NULL; -pci_alloc_err: - netif_err(qdev, ifup, qdev->ndev, "tx_ring alloc failed.\n"); return -ENOMEM; } diff --git a/trunk/drivers/net/ethernet/rdc/r6040.c b/trunk/drivers/net/ethernet/rdc/r6040.c index 557a26545d75..d1827e887f4e 100644 --- a/trunk/drivers/net/ethernet/rdc/r6040.c +++ b/trunk/drivers/net/ethernet/rdc/r6040.c @@ -1256,6 +1256,7 @@ static void __devexit r6040_remove_one(struct pci_dev *pdev) kfree(lp->mii_bus->irq); mdiobus_free(lp->mii_bus); netif_napi_del(&lp->napi); + pci_set_drvdata(pdev, NULL); pci_iounmap(pdev, lp->base); pci_release_regions(pdev); free_netdev(dev); @@ -1277,4 +1278,17 @@ static struct pci_driver r6040_driver = { .remove = __devexit_p(r6040_remove_one), }; -module_pci_driver(r6040_driver); + +static int __init r6040_init(void) +{ + return pci_register_driver(&r6040_driver); +} + + +static void __exit r6040_cleanup(void) +{ + pci_unregister_driver(&r6040_driver); +} + +module_init(r6040_init); +module_exit(r6040_cleanup); diff --git a/trunk/drivers/net/ethernet/realtek/r8169.c b/trunk/drivers/net/ethernet/realtek/r8169.c index c29c5fb3aecf..d7a04e091101 100644 --- a/trunk/drivers/net/ethernet/realtek/r8169.c +++ b/trunk/drivers/net/ethernet/realtek/r8169.c @@ -46,8 +46,6 @@ #define FIRMWARE_8105E_1 "rtl_nic/rtl8105e-1.fw" #define FIRMWARE_8402_1 "rtl_nic/rtl8402-1.fw" #define FIRMWARE_8411_1 "rtl_nic/rtl8411-1.fw" -#define FIRMWARE_8106E_1 "rtl_nic/rtl8106e-1.fw" -#define FIRMWARE_8168G_1 "rtl_nic/rtl8168g-1.fw" #ifdef RTL8169_DEBUG #define assert(expr) \ @@ -143,9 +141,6 @@ enum mac_version { RTL_GIGA_MAC_VER_36, RTL_GIGA_MAC_VER_37, RTL_GIGA_MAC_VER_38, - RTL_GIGA_MAC_VER_39, - RTL_GIGA_MAC_VER_40, - RTL_GIGA_MAC_VER_41, RTL_GIGA_MAC_NONE = 0xff, }; @@ -264,14 +259,6 @@ static const struct { [RTL_GIGA_MAC_VER_38] = _R("RTL8411", RTL_TD_1, FIRMWARE_8411_1, JUMBO_9K, false), - [RTL_GIGA_MAC_VER_39] = - _R("RTL8106e", RTL_TD_1, FIRMWARE_8106E_1, - JUMBO_1K, true), - [RTL_GIGA_MAC_VER_40] = - _R("RTL8168g/8111g", RTL_TD_1, FIRMWARE_8168G_1, - JUMBO_9K, false), - [RTL_GIGA_MAC_VER_41] = - _R("RTL8168g/8111g", RTL_TD_1, NULL, JUMBO_9K, false), }; #undef _R @@ -402,12 +389,8 @@ enum rtl8168_8101_registers { TWSI = 0xd2, MCU = 0xd3, #define NOW_IS_OOB (1 << 7) -#define TX_EMPTY (1 << 5) -#define RX_EMPTY (1 << 4) -#define RXTX_EMPTY (TX_EMPTY | RX_EMPTY) #define EN_NDP (1 << 3) #define EN_OOB_RESET (1 << 2) -#define LINK_LIST_RDY (1 << 1) EFUSEAR = 0xdc, #define EFUSEAR_FLAG 0x80000000 #define EFUSEAR_WRITE_CMD 0x80000000 @@ -433,7 +416,6 @@ enum rtl8168_registers { #define ERIAR_MASK_SHIFT 12 #define ERIAR_MASK_0001 (0x1 << ERIAR_MASK_SHIFT) #define ERIAR_MASK_0011 (0x3 << ERIAR_MASK_SHIFT) -#define ERIAR_MASK_0101 (0x5 << ERIAR_MASK_SHIFT) #define ERIAR_MASK_1111 (0xf << ERIAR_MASK_SHIFT) EPHY_RXER_NUM = 0x7c, OCPDR = 0xb0, /* OCP GPHY access */ @@ -446,14 +428,10 @@ enum rtl8168_registers { #define OCPAR_FLAG 0x80000000 #define OCPAR_GPHY_WRITE_CMD 0x8000f060 #define OCPAR_GPHY_READ_CMD 0x0000f060 - GPHY_OCP = 0xb8, RDSAR1 = 0xd0, /* 8168c only. Undocumented on 8168dp */ MISC = 0xf0, /* 8168e only. */ #define TXPLA_RST (1 << 29) -#define DISABLE_LAN_EN (1 << 23) /* Enable GPIO pin */ #define PWM_EN (1 << 22) -#define RXDV_GATED_EN (1 << 19) -#define EARLY_TALLY_EN (1 << 16) }; enum rtl_register_content { @@ -743,8 +721,8 @@ struct rtl8169_private { u16 event_slow; struct mdio_ops { - void (*write)(struct rtl8169_private *, int, int); - int (*read)(struct rtl8169_private *, int); + void (*write)(void __iomem *, int, int); + int (*read)(void __iomem *, int); } mdio_ops; struct pll_power_ops { @@ -758,8 +736,8 @@ struct rtl8169_private { } jumbo_ops; struct csi_ops { - void (*write)(struct rtl8169_private *, int, int); - u32 (*read)(struct rtl8169_private *, int); + void (*write)(void __iomem *, int, int); + u32 (*read)(void __iomem *, int); } csi_ops; int (*set_speed)(struct net_device *, u8 aneg, u16 sp, u8 dpx, u32 adv); @@ -796,8 +774,6 @@ struct rtl8169_private { } phy_action; } *rtl_fw; #define RTL_FIRMWARE_UNKNOWN ERR_PTR(-EAGAIN) - - u32 ocp_base; }; MODULE_AUTHOR("Realtek and the Linux r8169 crew "); @@ -818,8 +794,6 @@ MODULE_FIRMWARE(FIRMWARE_8168F_1); MODULE_FIRMWARE(FIRMWARE_8168F_2); MODULE_FIRMWARE(FIRMWARE_8402_1); MODULE_FIRMWARE(FIRMWARE_8411_1); -MODULE_FIRMWARE(FIRMWARE_8106E_1); -MODULE_FIRMWARE(FIRMWARE_8168G_1); static void rtl_lock_work(struct rtl8169_private *tp) { @@ -844,113 +818,47 @@ static void rtl_tx_performance_tweak(struct pci_dev *pdev, u16 force) } } -struct rtl_cond { - bool (*check)(struct rtl8169_private *); - const char *msg; -}; - -static void rtl_udelay(unsigned int d) -{ - udelay(d); -} - -static bool rtl_loop_wait(struct rtl8169_private *tp, const struct rtl_cond *c, - void (*delay)(unsigned int), unsigned int d, int n, - bool high) -{ - int i; - - for (i = 0; i < n; i++) { - delay(d); - if (c->check(tp) == high) - return true; - } - netif_err(tp, drv, tp->dev, c->msg); - return false; -} - -static bool rtl_udelay_loop_wait_high(struct rtl8169_private *tp, - const struct rtl_cond *c, - unsigned int d, int n) -{ - return rtl_loop_wait(tp, c, rtl_udelay, d, n, true); -} - -static bool rtl_udelay_loop_wait_low(struct rtl8169_private *tp, - const struct rtl_cond *c, - unsigned int d, int n) -{ - return rtl_loop_wait(tp, c, rtl_udelay, d, n, false); -} - -static bool rtl_msleep_loop_wait_high(struct rtl8169_private *tp, - const struct rtl_cond *c, - unsigned int d, int n) -{ - return rtl_loop_wait(tp, c, msleep, d, n, true); -} - -static bool rtl_msleep_loop_wait_low(struct rtl8169_private *tp, - const struct rtl_cond *c, - unsigned int d, int n) -{ - return rtl_loop_wait(tp, c, msleep, d, n, false); -} - -#define DECLARE_RTL_COND(name) \ -static bool name ## _check(struct rtl8169_private *); \ - \ -static const struct rtl_cond name = { \ - .check = name ## _check, \ - .msg = #name \ -}; \ - \ -static bool name ## _check(struct rtl8169_private *tp) - -DECLARE_RTL_COND(rtl_ocpar_cond) -{ - void __iomem *ioaddr = tp->mmio_addr; - - return RTL_R32(OCPAR) & OCPAR_FLAG; -} - static u32 ocp_read(struct rtl8169_private *tp, u8 mask, u16 reg) { void __iomem *ioaddr = tp->mmio_addr; + int i; RTL_W32(OCPAR, ((u32)mask & 0x0f) << 12 | (reg & 0x0fff)); - - return rtl_udelay_loop_wait_high(tp, &rtl_ocpar_cond, 100, 20) ? - RTL_R32(OCPDR) : ~0; + for (i = 0; i < 20; i++) { + udelay(100); + if (RTL_R32(OCPAR) & OCPAR_FLAG) + break; + } + return RTL_R32(OCPDR); } static void ocp_write(struct rtl8169_private *tp, u8 mask, u16 reg, u32 data) { void __iomem *ioaddr = tp->mmio_addr; + int i; RTL_W32(OCPDR, data); RTL_W32(OCPAR, OCPAR_FLAG | ((u32)mask & 0x0f) << 12 | (reg & 0x0fff)); - - rtl_udelay_loop_wait_low(tp, &rtl_ocpar_cond, 100, 20); -} - -DECLARE_RTL_COND(rtl_eriar_cond) -{ - void __iomem *ioaddr = tp->mmio_addr; - - return RTL_R32(ERIAR) & ERIAR_FLAG; + for (i = 0; i < 20; i++) { + udelay(100); + if ((RTL_R32(OCPAR) & OCPAR_FLAG) == 0) + break; + } } static void rtl8168_oob_notify(struct rtl8169_private *tp, u8 cmd) { void __iomem *ioaddr = tp->mmio_addr; + int i; RTL_W8(ERIDR, cmd); RTL_W32(ERIAR, 0x800010e8); msleep(2); - - if (!rtl_udelay_loop_wait_low(tp, &rtl_eriar_cond, 100, 5)) - return; + for (i = 0; i < 5; i++) { + udelay(100); + if (!(RTL_R32(ERIAR) & ERIAR_FLAG)) + break; + } ocp_write(tp, 0x1, 0x30, 0x00000001); } @@ -964,27 +872,36 @@ static u16 rtl8168_get_ocp_reg(struct rtl8169_private *tp) return (tp->mac_version == RTL_GIGA_MAC_VER_31) ? 0xb8 : 0x10; } -DECLARE_RTL_COND(rtl_ocp_read_cond) +static void rtl8168_driver_start(struct rtl8169_private *tp) { u16 reg; + int i; - reg = rtl8168_get_ocp_reg(tp); - - return ocp_read(tp, 0x0f, reg) & 0x00000800; -} - -static void rtl8168_driver_start(struct rtl8169_private *tp) -{ rtl8168_oob_notify(tp, OOB_CMD_DRIVER_START); - rtl_msleep_loop_wait_high(tp, &rtl_ocp_read_cond, 10, 10); + reg = rtl8168_get_ocp_reg(tp); + + for (i = 0; i < 10; i++) { + msleep(10); + if (ocp_read(tp, 0x0f, reg) & 0x00000800) + break; + } } static void rtl8168_driver_stop(struct rtl8169_private *tp) { + u16 reg; + int i; + rtl8168_oob_notify(tp, OOB_CMD_DRIVER_STOP); - rtl_msleep_loop_wait_low(tp, &rtl_ocp_read_cond, 10, 10); + reg = rtl8168_get_ocp_reg(tp); + + for (i = 0; i < 10; i++) { + msleep(10); + if ((ocp_read(tp, 0x0f, reg) & 0x00000800) == 0) + break; + } } static int r8168dp_check_dash(struct rtl8169_private *tp) @@ -994,124 +911,21 @@ static int r8168dp_check_dash(struct rtl8169_private *tp) return (ocp_read(tp, 0x0f, reg) & 0x00008000) ? 1 : 0; } -static bool rtl_ocp_reg_failure(struct rtl8169_private *tp, u32 reg) -{ - if (reg & 0xffff0001) { - netif_err(tp, drv, tp->dev, "Invalid ocp reg %x!\n", reg); - return true; - } - return false; -} - -DECLARE_RTL_COND(rtl_ocp_gphy_cond) -{ - void __iomem *ioaddr = tp->mmio_addr; - - return RTL_R32(GPHY_OCP) & OCPAR_FLAG; -} - -static void r8168_phy_ocp_write(struct rtl8169_private *tp, u32 reg, u32 data) -{ - void __iomem *ioaddr = tp->mmio_addr; - - if (rtl_ocp_reg_failure(tp, reg)) - return; - - RTL_W32(GPHY_OCP, OCPAR_FLAG | (reg << 15) | data); - - rtl_udelay_loop_wait_low(tp, &rtl_ocp_gphy_cond, 25, 10); -} - -static u16 r8168_phy_ocp_read(struct rtl8169_private *tp, u32 reg) -{ - void __iomem *ioaddr = tp->mmio_addr; - - if (rtl_ocp_reg_failure(tp, reg)) - return 0; - - RTL_W32(GPHY_OCP, reg << 15); - - return rtl_udelay_loop_wait_high(tp, &rtl_ocp_gphy_cond, 25, 10) ? - (RTL_R32(GPHY_OCP) & 0xffff) : ~0; -} - -static void rtl_w1w0_phy_ocp(struct rtl8169_private *tp, int reg, int p, int m) +static void r8169_mdio_write(void __iomem *ioaddr, int reg_addr, int value) { - int val; - - val = r8168_phy_ocp_read(tp, reg); - r8168_phy_ocp_write(tp, reg, (val | p) & ~m); -} - -DECLARE_RTL_COND(rtl_ocpdr_cond) -{ - void __iomem *ioaddr = tp->mmio_addr; - - return RTL_R32(OCPDR) & OCPAR_FLAG; -} - -static void r8168_mac_ocp_write(struct rtl8169_private *tp, u32 reg, u32 data) -{ - void __iomem *ioaddr = tp->mmio_addr; - - if (rtl_ocp_reg_failure(tp, reg)) - return; - - RTL_W32(OCPDR, OCPAR_FLAG | (reg << 15) | data); - - rtl_udelay_loop_wait_low(tp, &rtl_ocpdr_cond, 25, 10); -} - -static u16 r8168_mac_ocp_read(struct rtl8169_private *tp, u32 reg) -{ - void __iomem *ioaddr = tp->mmio_addr; - - if (rtl_ocp_reg_failure(tp, reg)) - return 0; - - RTL_W32(OCPDR, reg << 15); - - return rtl_udelay_loop_wait_high(tp, &rtl_ocpdr_cond, 25, 10) ? - RTL_R32(OCPDR) : ~0; -} + int i; -#define OCP_STD_PHY_BASE 0xa400 + RTL_W32(PHYAR, 0x80000000 | (reg_addr & 0x1f) << 16 | (value & 0xffff)); -static void r8168g_mdio_write(struct rtl8169_private *tp, int reg, int value) -{ - if (reg == 0x1f) { - tp->ocp_base = value ? value << 4 : OCP_STD_PHY_BASE; - return; + for (i = 20; i > 0; i--) { + /* + * Check if the RTL8169 has completed writing to the specified + * MII register. + */ + if (!(RTL_R32(PHYAR) & 0x80000000)) + break; + udelay(25); } - - if (tp->ocp_base != OCP_STD_PHY_BASE) - reg -= 0x10; - - r8168_phy_ocp_write(tp, tp->ocp_base + reg * 2, value); -} - -static int r8168g_mdio_read(struct rtl8169_private *tp, int reg) -{ - if (tp->ocp_base != OCP_STD_PHY_BASE) - reg -= 0x10; - - return r8168_phy_ocp_read(tp, tp->ocp_base + reg * 2); -} - -DECLARE_RTL_COND(rtl_phyar_cond) -{ - void __iomem *ioaddr = tp->mmio_addr; - - return RTL_R32(PHYAR) & 0x80000000; -} - -static void r8169_mdio_write(struct rtl8169_private *tp, int reg, int value) -{ - void __iomem *ioaddr = tp->mmio_addr; - - RTL_W32(PHYAR, 0x80000000 | (reg & 0x1f) << 16 | (value & 0xffff)); - - rtl_udelay_loop_wait_low(tp, &rtl_phyar_cond, 25, 20); /* * According to hardware specs a 20us delay is required after write * complete indication, but before sending next command. @@ -1119,16 +933,23 @@ static void r8169_mdio_write(struct rtl8169_private *tp, int reg, int value) udelay(20); } -static int r8169_mdio_read(struct rtl8169_private *tp, int reg) +static int r8169_mdio_read(void __iomem *ioaddr, int reg_addr) { - void __iomem *ioaddr = tp->mmio_addr; - int value; + int i, value = -1; - RTL_W32(PHYAR, 0x0 | (reg & 0x1f) << 16); - - value = rtl_udelay_loop_wait_high(tp, &rtl_phyar_cond, 25, 20) ? - RTL_R32(PHYAR) & 0xffff : ~0; + RTL_W32(PHYAR, 0x0 | (reg_addr & 0x1f) << 16); + for (i = 20; i > 0; i--) { + /* + * Check if the RTL8169 has completed retrieving data from + * the specified MII register. + */ + if (RTL_R32(PHYAR) & 0x80000000) { + value = RTL_R32(PHYAR) & 0xffff; + break; + } + udelay(25); + } /* * According to hardware specs a 20us delay is required after read * complete indication, but before sending next command. @@ -1138,35 +959,45 @@ static int r8169_mdio_read(struct rtl8169_private *tp, int reg) return value; } -static void r8168dp_1_mdio_access(struct rtl8169_private *tp, int reg, u32 data) +static void r8168dp_1_mdio_access(void __iomem *ioaddr, int reg_addr, u32 data) { - void __iomem *ioaddr = tp->mmio_addr; + int i; - RTL_W32(OCPDR, data | ((reg & OCPDR_REG_MASK) << OCPDR_GPHY_REG_SHIFT)); + RTL_W32(OCPDR, data | + ((reg_addr & OCPDR_REG_MASK) << OCPDR_GPHY_REG_SHIFT)); RTL_W32(OCPAR, OCPAR_GPHY_WRITE_CMD); RTL_W32(EPHY_RXER_NUM, 0); - rtl_udelay_loop_wait_low(tp, &rtl_ocpar_cond, 1000, 100); + for (i = 0; i < 100; i++) { + mdelay(1); + if (!(RTL_R32(OCPAR) & OCPAR_FLAG)) + break; + } } -static void r8168dp_1_mdio_write(struct rtl8169_private *tp, int reg, int value) +static void r8168dp_1_mdio_write(void __iomem *ioaddr, int reg_addr, int value) { - r8168dp_1_mdio_access(tp, reg, - OCPDR_WRITE_CMD | (value & OCPDR_DATA_MASK)); + r8168dp_1_mdio_access(ioaddr, reg_addr, OCPDR_WRITE_CMD | + (value & OCPDR_DATA_MASK)); } -static int r8168dp_1_mdio_read(struct rtl8169_private *tp, int reg) +static int r8168dp_1_mdio_read(void __iomem *ioaddr, int reg_addr) { - void __iomem *ioaddr = tp->mmio_addr; + int i; - r8168dp_1_mdio_access(tp, reg, OCPDR_READ_CMD); + r8168dp_1_mdio_access(ioaddr, reg_addr, OCPDR_READ_CMD); mdelay(1); RTL_W32(OCPAR, OCPAR_GPHY_READ_CMD); RTL_W32(EPHY_RXER_NUM, 0); - return rtl_udelay_loop_wait_high(tp, &rtl_ocpar_cond, 1000, 100) ? - RTL_R32(OCPDR) & OCPDR_DATA_MASK : ~0; + for (i = 0; i < 100; i++) { + mdelay(1); + if (RTL_R32(OCPAR) & OCPAR_FLAG) + break; + } + + return RTL_R32(OCPDR) & OCPDR_DATA_MASK; } #define R8168DP_1_MDIO_ACCESS_BIT 0x00020000 @@ -1181,25 +1012,22 @@ static void r8168dp_2_mdio_stop(void __iomem *ioaddr) RTL_W32(0xd0, RTL_R32(0xd0) | R8168DP_1_MDIO_ACCESS_BIT); } -static void r8168dp_2_mdio_write(struct rtl8169_private *tp, int reg, int value) +static void r8168dp_2_mdio_write(void __iomem *ioaddr, int reg_addr, int value) { - void __iomem *ioaddr = tp->mmio_addr; - r8168dp_2_mdio_start(ioaddr); - r8169_mdio_write(tp, reg, value); + r8169_mdio_write(ioaddr, reg_addr, value); r8168dp_2_mdio_stop(ioaddr); } -static int r8168dp_2_mdio_read(struct rtl8169_private *tp, int reg) +static int r8168dp_2_mdio_read(void __iomem *ioaddr, int reg_addr) { - void __iomem *ioaddr = tp->mmio_addr; int value; r8168dp_2_mdio_start(ioaddr); - value = r8169_mdio_read(tp, reg); + value = r8169_mdio_read(ioaddr, reg_addr); r8168dp_2_mdio_stop(ioaddr); @@ -1208,12 +1036,12 @@ static int r8168dp_2_mdio_read(struct rtl8169_private *tp, int reg) static void rtl_writephy(struct rtl8169_private *tp, int location, u32 val) { - tp->mdio_ops.write(tp, location, val); + tp->mdio_ops.write(tp->mmio_addr, location, val); } static int rtl_readphy(struct rtl8169_private *tp, int location) { - return tp->mdio_ops.read(tp, location); + return tp->mdio_ops.read(tp->mmio_addr, location); } static void rtl_patchphy(struct rtl8169_private *tp, int reg_addr, int value) @@ -1244,64 +1072,79 @@ static int rtl_mdio_read(struct net_device *dev, int phy_id, int location) return rtl_readphy(tp, location); } -DECLARE_RTL_COND(rtl_ephyar_cond) +static void rtl_ephy_write(void __iomem *ioaddr, int reg_addr, int value) { - void __iomem *ioaddr = tp->mmio_addr; - - return RTL_R32(EPHYAR) & EPHYAR_FLAG; -} - -static void rtl_ephy_write(struct rtl8169_private *tp, int reg_addr, int value) -{ - void __iomem *ioaddr = tp->mmio_addr; + unsigned int i; RTL_W32(EPHYAR, EPHYAR_WRITE_CMD | (value & EPHYAR_DATA_MASK) | (reg_addr & EPHYAR_REG_MASK) << EPHYAR_REG_SHIFT); - rtl_udelay_loop_wait_low(tp, &rtl_ephyar_cond, 10, 100); - - udelay(10); + for (i = 0; i < 100; i++) { + if (!(RTL_R32(EPHYAR) & EPHYAR_FLAG)) + break; + udelay(10); + } } -static u16 rtl_ephy_read(struct rtl8169_private *tp, int reg_addr) +static u16 rtl_ephy_read(void __iomem *ioaddr, int reg_addr) { - void __iomem *ioaddr = tp->mmio_addr; + u16 value = 0xffff; + unsigned int i; RTL_W32(EPHYAR, (reg_addr & EPHYAR_REG_MASK) << EPHYAR_REG_SHIFT); - return rtl_udelay_loop_wait_high(tp, &rtl_ephyar_cond, 10, 100) ? - RTL_R32(EPHYAR) & EPHYAR_DATA_MASK : ~0; + for (i = 0; i < 100; i++) { + if (RTL_R32(EPHYAR) & EPHYAR_FLAG) { + value = RTL_R32(EPHYAR) & EPHYAR_DATA_MASK; + break; + } + udelay(10); + } + + return value; } -static void rtl_eri_write(struct rtl8169_private *tp, int addr, u32 mask, - u32 val, int type) +static +void rtl_eri_write(void __iomem *ioaddr, int addr, u32 mask, u32 val, int type) { - void __iomem *ioaddr = tp->mmio_addr; + unsigned int i; BUG_ON((addr & 3) || (mask == 0)); RTL_W32(ERIDR, val); RTL_W32(ERIAR, ERIAR_WRITE_CMD | type | mask | addr); - rtl_udelay_loop_wait_low(tp, &rtl_eriar_cond, 100, 100); + for (i = 0; i < 100; i++) { + if (!(RTL_R32(ERIAR) & ERIAR_FLAG)) + break; + udelay(100); + } } -static u32 rtl_eri_read(struct rtl8169_private *tp, int addr, int type) +static u32 rtl_eri_read(void __iomem *ioaddr, int addr, int type) { - void __iomem *ioaddr = tp->mmio_addr; + u32 value = ~0x00; + unsigned int i; RTL_W32(ERIAR, ERIAR_READ_CMD | type | ERIAR_MASK_1111 | addr); - return rtl_udelay_loop_wait_high(tp, &rtl_eriar_cond, 100, 100) ? - RTL_R32(ERIDR) : ~0; + for (i = 0; i < 100; i++) { + if (RTL_R32(ERIAR) & ERIAR_FLAG) { + value = RTL_R32(ERIDR); + break; + } + udelay(100); + } + + return value; } -static void rtl_w1w0_eri(struct rtl8169_private *tp, int addr, u32 mask, u32 p, - u32 m, int type) +static void +rtl_w1w0_eri(void __iomem *ioaddr, int addr, u32 mask, u32 p, u32 m, int type) { u32 val; - val = rtl_eri_read(tp, addr, type); - rtl_eri_write(tp, addr, mask, (val & ~m) | p, type); + val = rtl_eri_read(ioaddr, addr, type); + rtl_eri_write(ioaddr, addr, mask, (val & ~m) | p, type); } struct exgmac_reg { @@ -1310,30 +1153,31 @@ struct exgmac_reg { u32 val; }; -static void rtl_write_exgmac_batch(struct rtl8169_private *tp, +static void rtl_write_exgmac_batch(void __iomem *ioaddr, const struct exgmac_reg *r, int len) { while (len-- > 0) { - rtl_eri_write(tp, r->addr, r->mask, r->val, ERIAR_EXGMAC); + rtl_eri_write(ioaddr, r->addr, r->mask, r->val, ERIAR_EXGMAC); r++; } } -DECLARE_RTL_COND(rtl_efusear_cond) +static u8 rtl8168d_efuse_read(void __iomem *ioaddr, int reg_addr) { - void __iomem *ioaddr = tp->mmio_addr; - - return RTL_R32(EFUSEAR) & EFUSEAR_FLAG; -} - -static u8 rtl8168d_efuse_read(struct rtl8169_private *tp, int reg_addr) -{ - void __iomem *ioaddr = tp->mmio_addr; + u8 value = 0xff; + unsigned int i; RTL_W32(EFUSEAR, (reg_addr & EFUSEAR_REG_MASK) << EFUSEAR_REG_SHIFT); - return rtl_udelay_loop_wait_high(tp, &rtl_efusear_cond, 100, 300) ? - RTL_R32(EFUSEAR) & EFUSEAR_DATA_MASK : ~0; + for (i = 0; i < 300; i++) { + if (RTL_R32(EFUSEAR) & EFUSEAR_FLAG) { + value = RTL_R32(EFUSEAR) & EFUSEAR_DATA_MASK; + break; + } + udelay(100); + } + + return value; } static u16 rtl_get_events(struct rtl8169_private *tp) @@ -1432,48 +1276,48 @@ static void rtl_link_chg_patch(struct rtl8169_private *tp) if (tp->mac_version == RTL_GIGA_MAC_VER_34 || tp->mac_version == RTL_GIGA_MAC_VER_38) { if (RTL_R8(PHYstatus) & _1000bpsF) { - rtl_eri_write(tp, 0x1bc, ERIAR_MASK_1111, 0x00000011, - ERIAR_EXGMAC); - rtl_eri_write(tp, 0x1dc, ERIAR_MASK_1111, 0x00000005, - ERIAR_EXGMAC); + rtl_eri_write(ioaddr, 0x1bc, ERIAR_MASK_1111, + 0x00000011, ERIAR_EXGMAC); + rtl_eri_write(ioaddr, 0x1dc, ERIAR_MASK_1111, + 0x00000005, ERIAR_EXGMAC); } else if (RTL_R8(PHYstatus) & _100bps) { - rtl_eri_write(tp, 0x1bc, ERIAR_MASK_1111, 0x0000001f, - ERIAR_EXGMAC); - rtl_eri_write(tp, 0x1dc, ERIAR_MASK_1111, 0x00000005, - ERIAR_EXGMAC); + rtl_eri_write(ioaddr, 0x1bc, ERIAR_MASK_1111, + 0x0000001f, ERIAR_EXGMAC); + rtl_eri_write(ioaddr, 0x1dc, ERIAR_MASK_1111, + 0x00000005, ERIAR_EXGMAC); } else { - rtl_eri_write(tp, 0x1bc, ERIAR_MASK_1111, 0x0000001f, - ERIAR_EXGMAC); - rtl_eri_write(tp, 0x1dc, ERIAR_MASK_1111, 0x0000003f, - ERIAR_EXGMAC); + rtl_eri_write(ioaddr, 0x1bc, ERIAR_MASK_1111, + 0x0000001f, ERIAR_EXGMAC); + rtl_eri_write(ioaddr, 0x1dc, ERIAR_MASK_1111, + 0x0000003f, ERIAR_EXGMAC); } /* Reset packet filter */ - rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x00, 0x01, + rtl_w1w0_eri(ioaddr, 0xdc, ERIAR_MASK_0001, 0x00, 0x01, ERIAR_EXGMAC); - rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x01, 0x00, + rtl_w1w0_eri(ioaddr, 0xdc, ERIAR_MASK_0001, 0x01, 0x00, ERIAR_EXGMAC); } else if (tp->mac_version == RTL_GIGA_MAC_VER_35 || tp->mac_version == RTL_GIGA_MAC_VER_36) { if (RTL_R8(PHYstatus) & _1000bpsF) { - rtl_eri_write(tp, 0x1bc, ERIAR_MASK_1111, 0x00000011, - ERIAR_EXGMAC); - rtl_eri_write(tp, 0x1dc, ERIAR_MASK_1111, 0x00000005, - ERIAR_EXGMAC); + rtl_eri_write(ioaddr, 0x1bc, ERIAR_MASK_1111, + 0x00000011, ERIAR_EXGMAC); + rtl_eri_write(ioaddr, 0x1dc, ERIAR_MASK_1111, + 0x00000005, ERIAR_EXGMAC); } else { - rtl_eri_write(tp, 0x1bc, ERIAR_MASK_1111, 0x0000001f, - ERIAR_EXGMAC); - rtl_eri_write(tp, 0x1dc, ERIAR_MASK_1111, 0x0000003f, - ERIAR_EXGMAC); + rtl_eri_write(ioaddr, 0x1bc, ERIAR_MASK_1111, + 0x0000001f, ERIAR_EXGMAC); + rtl_eri_write(ioaddr, 0x1dc, ERIAR_MASK_1111, + 0x0000003f, ERIAR_EXGMAC); } } else if (tp->mac_version == RTL_GIGA_MAC_VER_37) { if (RTL_R8(PHYstatus) & _10bps) { - rtl_eri_write(tp, 0x1d0, ERIAR_MASK_0011, 0x4d02, - ERIAR_EXGMAC); - rtl_eri_write(tp, 0x1dc, ERIAR_MASK_0011, 0x0060, - ERIAR_EXGMAC); + rtl_eri_write(ioaddr, 0x1d0, ERIAR_MASK_0011, + 0x4d02, ERIAR_EXGMAC); + rtl_eri_write(ioaddr, 0x1dc, ERIAR_MASK_0011, + 0x0060, ERIAR_EXGMAC); } else { - rtl_eri_write(tp, 0x1d0, ERIAR_MASK_0011, 0x0000, - ERIAR_EXGMAC); + rtl_eri_write(ioaddr, 0x1d0, ERIAR_MASK_0011, + 0x0000, ERIAR_EXGMAC); } } } @@ -1940,13 +1784,6 @@ static int rtl8169_get_sset_count(struct net_device *dev, int sset) } } -DECLARE_RTL_COND(rtl_counters_cond) -{ - void __iomem *ioaddr = tp->mmio_addr; - - return RTL_R32(CounterAddrLow) & CounterDump; -} - static void rtl8169_update_counters(struct net_device *dev) { struct rtl8169_private *tp = netdev_priv(dev); @@ -1955,6 +1792,7 @@ static void rtl8169_update_counters(struct net_device *dev) struct rtl8169_counters *counters; dma_addr_t paddr; u32 cmd; + int wait = 1000; /* * Some chips are unable to dump tally counters when the receiver @@ -1972,8 +1810,13 @@ static void rtl8169_update_counters(struct net_device *dev) RTL_W32(CounterAddrLow, cmd); RTL_W32(CounterAddrLow, cmd | CounterDump); - if (rtl_udelay_loop_wait_low(tp, &rtl_counters_cond, 10, 1000)) - memcpy(&tp->counters, counters, sizeof(*counters)); + while (wait--) { + if ((RTL_R32(CounterAddrLow) & CounterDump) == 0) { + memcpy(&tp->counters, counters, sizeof(*counters)); + break; + } + udelay(10); + } RTL_W32(CounterAddrLow, 0); RTL_W32(CounterAddrHigh, 0); @@ -2051,10 +1894,6 @@ static void rtl8169_get_mac_version(struct rtl8169_private *tp, u32 val; int mac_version; } mac_info[] = { - /* 8168G family. */ - { 0x7cf00000, 0x4c100000, RTL_GIGA_MAC_VER_41 }, - { 0x7cf00000, 0x4c000000, RTL_GIGA_MAC_VER_40 }, - /* 8168F family. */ { 0x7c800000, 0x48800000, RTL_GIGA_MAC_VER_38 }, { 0x7cf00000, 0x48100000, RTL_GIGA_MAC_VER_36 }, @@ -2094,8 +1933,6 @@ static void rtl8169_get_mac_version(struct rtl8169_private *tp, { 0x7c800000, 0x30000000, RTL_GIGA_MAC_VER_11 }, /* 8101 family. */ - { 0x7cf00000, 0x44900000, RTL_GIGA_MAC_VER_39 }, - { 0x7c800000, 0x44800000, RTL_GIGA_MAC_VER_39 }, { 0x7c800000, 0x44000000, RTL_GIGA_MAC_VER_37 }, { 0x7cf00000, 0x40b00000, RTL_GIGA_MAC_VER_30 }, { 0x7cf00000, 0x40a00000, RTL_GIGA_MAC_VER_30 }, @@ -2349,7 +2186,7 @@ static void rtl_phy_write_fw(struct rtl8169_private *tp, struct rtl_fw *rtl_fw) index -= regno; break; case PHY_READ_EFUSE: - predata = rtl8168d_efuse_read(tp, regno); + predata = rtl8168d_efuse_read(tp->mmio_addr, regno); index++; break; case PHY_CLEAR_READCOUNT: @@ -2789,6 +2626,7 @@ static void rtl8168d_1_hw_phy_config(struct rtl8169_private *tp) { 0x1f, 0x0000 }, { 0x0d, 0xf880 } }; + void __iomem *ioaddr = tp->mmio_addr; rtl_writephy_batch(tp, phy_reg_init_0, ARRAY_SIZE(phy_reg_init_0)); @@ -2800,7 +2638,7 @@ static void rtl8168d_1_hw_phy_config(struct rtl8169_private *tp) rtl_w1w0_phy(tp, 0x0b, 0x0010, 0x00ef); rtl_w1w0_phy(tp, 0x0c, 0xa200, 0x5d00); - if (rtl8168d_efuse_read(tp, 0x01) == 0xb1) { + if (rtl8168d_efuse_read(ioaddr, 0x01) == 0xb1) { static const struct phy_reg phy_reg_init[] = { { 0x1f, 0x0002 }, { 0x05, 0x669a }, @@ -2900,10 +2738,11 @@ static void rtl8168d_2_hw_phy_config(struct rtl8169_private *tp) { 0x1f, 0x0000 }, { 0x0d, 0xf880 } }; + void __iomem *ioaddr = tp->mmio_addr; rtl_writephy_batch(tp, phy_reg_init_0, ARRAY_SIZE(phy_reg_init_0)); - if (rtl8168d_efuse_read(tp, 0x01) == 0xb1) { + if (rtl8168d_efuse_read(ioaddr, 0x01) == 0xb1) { static const struct phy_reg phy_reg_init[] = { { 0x1f, 0x0002 }, { 0x05, 0x669a }, @@ -3171,7 +3010,8 @@ static void rtl8168e_2_hw_phy_config(struct rtl8169_private *tp) rtl_writephy(tp, 0x1f, 0x0000); /* EEE setting */ - rtl_w1w0_eri(tp, 0x1b0, ERIAR_MASK_1111, 0x0000, 0x0003, ERIAR_EXGMAC); + rtl_w1w0_eri(tp->mmio_addr, 0x1b0, ERIAR_MASK_1111, 0x0000, 0x0003, + ERIAR_EXGMAC); rtl_writephy(tp, 0x1f, 0x0005); rtl_writephy(tp, 0x05, 0x8b85); rtl_w1w0_phy(tp, 0x06, 0x0000, 0x2000); @@ -3275,6 +3115,7 @@ static void rtl8168f_2_hw_phy_config(struct rtl8169_private *tp) static void rtl8411_hw_phy_config(struct rtl8169_private *tp) { + void __iomem *ioaddr = tp->mmio_addr; static const struct phy_reg phy_reg_init[] = { /* Channel estimation fine tune */ { 0x1f, 0x0003 }, @@ -3348,7 +3189,7 @@ static void rtl8411_hw_phy_config(struct rtl8169_private *tp) rtl_writephy(tp, 0x1f, 0x0000); /* eee setting */ - rtl_w1w0_eri(tp, 0x1b0, ERIAR_MASK_0001, 0x00, 0x03, ERIAR_EXGMAC); + rtl_w1w0_eri(ioaddr, 0x1b0, ERIAR_MASK_0001, 0x00, 0x03, ERIAR_EXGMAC); rtl_writephy(tp, 0x1f, 0x0005); rtl_writephy(tp, 0x05, 0x8b85); rtl_w1w0_phy(tp, 0x06, 0x0000, 0x2000); @@ -3370,55 +3211,6 @@ static void rtl8411_hw_phy_config(struct rtl8169_private *tp) rtl_writephy(tp, 0x1f, 0x0000); } -static void rtl8168g_1_hw_phy_config(struct rtl8169_private *tp) -{ - static const u16 mac_ocp_patch[] = { - 0xe008, 0xe01b, 0xe01d, 0xe01f, - 0xe021, 0xe023, 0xe025, 0xe027, - 0x49d2, 0xf10d, 0x766c, 0x49e2, - 0xf00a, 0x1ec0, 0x8ee1, 0xc60a, - - 0x77c0, 0x4870, 0x9fc0, 0x1ea0, - 0xc707, 0x8ee1, 0x9d6c, 0xc603, - 0xbe00, 0xb416, 0x0076, 0xe86c, - 0xc602, 0xbe00, 0x0000, 0xc602, - - 0xbe00, 0x0000, 0xc602, 0xbe00, - 0x0000, 0xc602, 0xbe00, 0x0000, - 0xc602, 0xbe00, 0x0000, 0xc602, - 0xbe00, 0x0000, 0xc602, 0xbe00, - - 0x0000, 0x0000, 0x0000, 0x0000 - }; - u32 i; - - /* Patch code for GPHY reset */ - for (i = 0; i < ARRAY_SIZE(mac_ocp_patch); i++) - r8168_mac_ocp_write(tp, 0xf800 + 2*i, mac_ocp_patch[i]); - r8168_mac_ocp_write(tp, 0xfc26, 0x8000); - r8168_mac_ocp_write(tp, 0xfc28, 0x0075); - - rtl_apply_firmware(tp); - - if (r8168_phy_ocp_read(tp, 0xa460) & 0x0100) - rtl_w1w0_phy_ocp(tp, 0xbcc4, 0x0000, 0x8000); - else - rtl_w1w0_phy_ocp(tp, 0xbcc4, 0x8000, 0x0000); - - if (r8168_phy_ocp_read(tp, 0xa466) & 0x0100) - rtl_w1w0_phy_ocp(tp, 0xc41a, 0x0002, 0x0000); - else - rtl_w1w0_phy_ocp(tp, 0xbcc4, 0x0000, 0x0002); - - rtl_w1w0_phy_ocp(tp, 0xa442, 0x000c, 0x0000); - rtl_w1w0_phy_ocp(tp, 0xa4b2, 0x0004, 0x0000); - - r8168_phy_ocp_write(tp, 0xa436, 0x8012); - rtl_w1w0_phy_ocp(tp, 0xa438, 0x8000, 0x0000); - - rtl_w1w0_phy_ocp(tp, 0xc422, 0x4000, 0x2000); -} - static void rtl8102e_hw_phy_config(struct rtl8169_private *tp) { static const struct phy_reg phy_reg_init[] = { @@ -3464,6 +3256,8 @@ static void rtl8105e_hw_phy_config(struct rtl8169_private *tp) static void rtl8402_hw_phy_config(struct rtl8169_private *tp) { + void __iomem *ioaddr = tp->mmio_addr; + /* Disable ALDPS before setting firmware */ rtl_writephy(tp, 0x1f, 0x0000); rtl_writephy(tp, 0x18, 0x0310); @@ -3472,35 +3266,13 @@ static void rtl8402_hw_phy_config(struct rtl8169_private *tp) rtl_apply_firmware(tp); /* EEE setting */ - rtl_eri_write(tp, 0x1b0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC); + rtl_eri_write(ioaddr, 0x1b0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC); rtl_writephy(tp, 0x1f, 0x0004); rtl_writephy(tp, 0x10, 0x401f); rtl_writephy(tp, 0x19, 0x7030); rtl_writephy(tp, 0x1f, 0x0000); } -static void rtl8106e_hw_phy_config(struct rtl8169_private *tp) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0004 }, - { 0x10, 0xc07f }, - { 0x19, 0x7030 }, - { 0x1f, 0x0000 } - }; - - /* Disable ALDPS before ram code */ - rtl_writephy(tp, 0x1f, 0x0000); - rtl_writephy(tp, 0x18, 0x0310); - msleep(100); - - rtl_apply_firmware(tp); - - rtl_eri_write(tp, 0x1b0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC); - rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - rtl_eri_write(tp, 0x1d0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC); -} - static void rtl_hw_phy_config(struct net_device *dev) { struct rtl8169_private *tp = netdev_priv(dev); @@ -3597,15 +3369,6 @@ static void rtl_hw_phy_config(struct net_device *dev) rtl8411_hw_phy_config(tp); break; - case RTL_GIGA_MAC_VER_39: - rtl8106e_hw_phy_config(tp); - break; - - case RTL_GIGA_MAC_VER_40: - rtl8168g_1_hw_phy_config(tp); - break; - - case RTL_GIGA_MAC_VER_41: default: break; } @@ -3663,16 +3426,18 @@ static void rtl8169_release_board(struct pci_dev *pdev, struct net_device *dev, free_netdev(dev); } -DECLARE_RTL_COND(rtl_phy_reset_cond) -{ - return tp->phy_reset_pending(tp); -} - static void rtl8169_phy_reset(struct net_device *dev, struct rtl8169_private *tp) { + unsigned int i; + tp->phy_reset_enable(tp); - rtl_msleep_loop_wait_low(tp, &rtl_phy_reset_cond, 1, 100); + for (i = 0; i < 100; i++) { + if (!tp->phy_reset_pending(tp)) + return; + msleep(1); + } + netif_err(tp, link, dev, "PHY reset failed\n"); } static bool rtl_tbi_enabled(struct rtl8169_private *tp) @@ -3747,7 +3512,7 @@ static void rtl_rar_set(struct rtl8169_private *tp, u8 *addr) low >> 16 }, }; - rtl_write_exgmac_batch(tp, e, ARRAY_SIZE(e)); + rtl_write_exgmac_batch(ioaddr, e, ARRAY_SIZE(e)); } RTL_W8(Cfg9346, Cfg9346_Lock); @@ -3824,11 +3589,6 @@ static void __devinit rtl_init_mdio_ops(struct rtl8169_private *tp) ops->write = r8168dp_2_mdio_write; ops->read = r8168dp_2_mdio_read; break; - case RTL_GIGA_MAC_VER_40: - case RTL_GIGA_MAC_VER_41: - ops->write = r8168g_mdio_write; - ops->read = r8168g_mdio_read; - break; default: ops->write = r8169_mdio_write; ops->read = r8169_mdio_read; @@ -3848,9 +3608,6 @@ static void rtl_wol_suspend_quirk(struct rtl8169_private *tp) case RTL_GIGA_MAC_VER_34: case RTL_GIGA_MAC_VER_37: case RTL_GIGA_MAC_VER_38: - case RTL_GIGA_MAC_VER_39: - case RTL_GIGA_MAC_VER_40: - case RTL_GIGA_MAC_VER_41: RTL_W32(RxConfig, RTL_R32(RxConfig) | AcceptBroadcast | AcceptMulticast | AcceptMyPhys); break; @@ -4004,7 +3761,7 @@ static void r8168_pll_power_down(struct rtl8169_private *tp) if (tp->mac_version == RTL_GIGA_MAC_VER_32 || tp->mac_version == RTL_GIGA_MAC_VER_33) - rtl_ephy_write(tp, 0x19, 0xff64); + rtl_ephy_write(ioaddr, 0x19, 0xff64); if (rtl_wol_pll_power_down(tp)) return; @@ -4073,7 +3830,6 @@ static void __devinit rtl_init_pll_power_ops(struct rtl8169_private *tp) case RTL_GIGA_MAC_VER_29: case RTL_GIGA_MAC_VER_30: case RTL_GIGA_MAC_VER_37: - case RTL_GIGA_MAC_VER_39: ops->down = r810x_pll_power_down; ops->up = r810x_pll_power_up; break; @@ -4099,8 +3855,6 @@ static void __devinit rtl_init_pll_power_ops(struct rtl8169_private *tp) case RTL_GIGA_MAC_VER_35: case RTL_GIGA_MAC_VER_36: case RTL_GIGA_MAC_VER_38: - case RTL_GIGA_MAC_VER_40: - case RTL_GIGA_MAC_VER_41: ops->down = r8168_pll_power_down; ops->up = r8168_pll_power_up; break; @@ -4297,8 +4051,6 @@ static void __devinit rtl_init_jumbo_ops(struct rtl8169_private *tp) * No action needed for jumbo frames with 8169. * No jumbo for 810x at all. */ - case RTL_GIGA_MAC_VER_40: - case RTL_GIGA_MAC_VER_41: default: ops->disable = NULL; ops->enable = NULL; @@ -4306,20 +4058,20 @@ static void __devinit rtl_init_jumbo_ops(struct rtl8169_private *tp) } } -DECLARE_RTL_COND(rtl_chipcmd_cond) -{ - void __iomem *ioaddr = tp->mmio_addr; - - return RTL_R8(ChipCmd) & CmdReset; -} - static void rtl_hw_reset(struct rtl8169_private *tp) { void __iomem *ioaddr = tp->mmio_addr; + int i; + /* Soft reset the chip. */ RTL_W8(ChipCmd, CmdReset); - rtl_udelay_loop_wait_low(tp, &rtl_chipcmd_cond, 100, 100); + /* Check that the chip has finished the reset. */ + for (i = 0; i < 100; i++) { + if ((RTL_R8(ChipCmd) & CmdReset) == 0) + break; + udelay(100); + } } static void rtl_request_uncached_firmware(struct rtl8169_private *tp) @@ -4373,20 +4125,6 @@ static void rtl_rx_close(struct rtl8169_private *tp) RTL_W32(RxConfig, RTL_R32(RxConfig) & ~RX_CONFIG_ACCEPT_MASK); } -DECLARE_RTL_COND(rtl_npq_cond) -{ - void __iomem *ioaddr = tp->mmio_addr; - - return RTL_R8(TxPoll) & NPQ; -} - -DECLARE_RTL_COND(rtl_txcfg_empty_cond) -{ - void __iomem *ioaddr = tp->mmio_addr; - - return RTL_R32(TxConfig) & TXCFG_EMPTY; -} - static void rtl8169_hw_reset(struct rtl8169_private *tp) { void __iomem *ioaddr = tp->mmio_addr; @@ -4399,16 +4137,16 @@ static void rtl8169_hw_reset(struct rtl8169_private *tp) if (tp->mac_version == RTL_GIGA_MAC_VER_27 || tp->mac_version == RTL_GIGA_MAC_VER_28 || tp->mac_version == RTL_GIGA_MAC_VER_31) { - rtl_udelay_loop_wait_low(tp, &rtl_npq_cond, 20, 42*42); + while (RTL_R8(TxPoll) & NPQ) + udelay(20); } else if (tp->mac_version == RTL_GIGA_MAC_VER_34 || tp->mac_version == RTL_GIGA_MAC_VER_35 || tp->mac_version == RTL_GIGA_MAC_VER_36 || tp->mac_version == RTL_GIGA_MAC_VER_37 || - tp->mac_version == RTL_GIGA_MAC_VER_40 || - tp->mac_version == RTL_GIGA_MAC_VER_41 || tp->mac_version == RTL_GIGA_MAC_VER_38) { RTL_W8(ChipCmd, RTL_R8(ChipCmd) | StopReq); - rtl_udelay_loop_wait_high(tp, &rtl_txcfg_empty_cond, 100, 666); + while (!(RTL_R32(TxConfig) & TXCFG_EMPTY)) + udelay(100); } else { RTL_W8(ChipCmd, RTL_R8(ChipCmd) | StopReq); udelay(100); @@ -4614,12 +4352,15 @@ static void rtl_hw_start_8169(struct net_device *dev) static void rtl_csi_write(struct rtl8169_private *tp, int addr, int value) { if (tp->csi_ops.write) - tp->csi_ops.write(tp, addr, value); + tp->csi_ops.write(tp->mmio_addr, addr, value); } static u32 rtl_csi_read(struct rtl8169_private *tp, int addr) { - return tp->csi_ops.read ? tp->csi_ops.read(tp, addr) : ~0; + if (tp->csi_ops.read) + return tp->csi_ops.read(tp->mmio_addr, addr); + else + return ~0; } static void rtl_csi_access_enable(struct rtl8169_private *tp, u32 bits) @@ -4640,56 +4381,73 @@ static void rtl_csi_access_enable_2(struct rtl8169_private *tp) rtl_csi_access_enable(tp, 0x27000000); } -DECLARE_RTL_COND(rtl_csiar_cond) -{ - void __iomem *ioaddr = tp->mmio_addr; - - return RTL_R32(CSIAR) & CSIAR_FLAG; -} - -static void r8169_csi_write(struct rtl8169_private *tp, int addr, int value) +static void r8169_csi_write(void __iomem *ioaddr, int addr, int value) { - void __iomem *ioaddr = tp->mmio_addr; + unsigned int i; RTL_W32(CSIDR, value); RTL_W32(CSIAR, CSIAR_WRITE_CMD | (addr & CSIAR_ADDR_MASK) | CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT); - rtl_udelay_loop_wait_low(tp, &rtl_csiar_cond, 10, 100); + for (i = 0; i < 100; i++) { + if (!(RTL_R32(CSIAR) & CSIAR_FLAG)) + break; + udelay(10); + } } -static u32 r8169_csi_read(struct rtl8169_private *tp, int addr) +static u32 r8169_csi_read(void __iomem *ioaddr, int addr) { - void __iomem *ioaddr = tp->mmio_addr; + u32 value = ~0x00; + unsigned int i; RTL_W32(CSIAR, (addr & CSIAR_ADDR_MASK) | CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT); - return rtl_udelay_loop_wait_high(tp, &rtl_csiar_cond, 10, 100) ? - RTL_R32(CSIDR) : ~0; + for (i = 0; i < 100; i++) { + if (RTL_R32(CSIAR) & CSIAR_FLAG) { + value = RTL_R32(CSIDR); + break; + } + udelay(10); + } + + return value; } -static void r8402_csi_write(struct rtl8169_private *tp, int addr, int value) +static void r8402_csi_write(void __iomem *ioaddr, int addr, int value) { - void __iomem *ioaddr = tp->mmio_addr; + unsigned int i; RTL_W32(CSIDR, value); RTL_W32(CSIAR, CSIAR_WRITE_CMD | (addr & CSIAR_ADDR_MASK) | CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT | CSIAR_FUNC_NIC); - rtl_udelay_loop_wait_low(tp, &rtl_csiar_cond, 10, 100); + for (i = 0; i < 100; i++) { + if (!(RTL_R32(CSIAR) & CSIAR_FLAG)) + break; + udelay(10); + } } -static u32 r8402_csi_read(struct rtl8169_private *tp, int addr) +static u32 r8402_csi_read(void __iomem *ioaddr, int addr) { - void __iomem *ioaddr = tp->mmio_addr; + u32 value = ~0x00; + unsigned int i; RTL_W32(CSIAR, (addr & CSIAR_ADDR_MASK) | CSIAR_FUNC_NIC | CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT); - return rtl_udelay_loop_wait_high(tp, &rtl_csiar_cond, 10, 100) ? - RTL_R32(CSIDR) : ~0; + for (i = 0; i < 100; i++) { + if (RTL_R32(CSIAR) & CSIAR_FLAG) { + value = RTL_R32(CSIDR); + break; + } + udelay(10); + } + + return value; } static void __devinit rtl_init_csi_ops(struct rtl8169_private *tp) @@ -4734,14 +4492,13 @@ struct ephy_info { u16 bits; }; -static void rtl_ephy_init(struct rtl8169_private *tp, const struct ephy_info *e, - int len) +static void rtl_ephy_init(void __iomem *ioaddr, const struct ephy_info *e, int len) { u16 w; while (len-- > 0) { - w = (rtl_ephy_read(tp, e->offset) & ~e->mask) | e->bits; - rtl_ephy_write(tp, e->offset, w); + w = (rtl_ephy_read(ioaddr, e->offset) & ~e->mask) | e->bits; + rtl_ephy_write(ioaddr, e->offset, w); e++; } } @@ -4825,6 +4582,7 @@ static void __rtl_hw_start_8168cp(struct rtl8169_private *tp) static void rtl_hw_start_8168cp_1(struct rtl8169_private *tp) { + void __iomem *ioaddr = tp->mmio_addr; static const struct ephy_info e_info_8168cp[] = { { 0x01, 0, 0x0001 }, { 0x02, 0x0800, 0x1000 }, @@ -4835,7 +4593,7 @@ static void rtl_hw_start_8168cp_1(struct rtl8169_private *tp) rtl_csi_access_enable_2(tp); - rtl_ephy_init(tp, e_info_8168cp, ARRAY_SIZE(e_info_8168cp)); + rtl_ephy_init(ioaddr, e_info_8168cp, ARRAY_SIZE(e_info_8168cp)); __rtl_hw_start_8168cp(tp); } @@ -4886,13 +4644,14 @@ static void rtl_hw_start_8168c_1(struct rtl8169_private *tp) RTL_W8(DBG_REG, 0x06 | FIX_NAK_1 | FIX_NAK_2); - rtl_ephy_init(tp, e_info_8168c_1, ARRAY_SIZE(e_info_8168c_1)); + rtl_ephy_init(ioaddr, e_info_8168c_1, ARRAY_SIZE(e_info_8168c_1)); __rtl_hw_start_8168cp(tp); } static void rtl_hw_start_8168c_2(struct rtl8169_private *tp) { + void __iomem *ioaddr = tp->mmio_addr; static const struct ephy_info e_info_8168c_2[] = { { 0x01, 0, 0x0001 }, { 0x03, 0x0400, 0x0220 } @@ -4900,7 +4659,7 @@ static void rtl_hw_start_8168c_2(struct rtl8169_private *tp) rtl_csi_access_enable_2(tp); - rtl_ephy_init(tp, e_info_8168c_2, ARRAY_SIZE(e_info_8168c_2)); + rtl_ephy_init(ioaddr, e_info_8168c_2, ARRAY_SIZE(e_info_8168c_2)); __rtl_hw_start_8168cp(tp); } @@ -4968,8 +4727,8 @@ static void rtl_hw_start_8168d_4(struct rtl8169_private *tp) const struct ephy_info *e = e_info_8168d_4 + i; u16 w; - w = rtl_ephy_read(tp, e->offset); - rtl_ephy_write(tp, 0x03, (w & e->mask) | e->bits); + w = rtl_ephy_read(ioaddr, e->offset); + rtl_ephy_write(ioaddr, 0x03, (w & e->mask) | e->bits); } rtl_enable_clock_request(pdev); @@ -4997,7 +4756,7 @@ static void rtl_hw_start_8168e_1(struct rtl8169_private *tp) rtl_csi_access_enable_2(tp); - rtl_ephy_init(tp, e_info_8168e_1, ARRAY_SIZE(e_info_8168e_1)); + rtl_ephy_init(ioaddr, e_info_8168e_1, ARRAY_SIZE(e_info_8168e_1)); rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); @@ -5023,18 +4782,19 @@ static void rtl_hw_start_8168e_2(struct rtl8169_private *tp) rtl_csi_access_enable_1(tp); - rtl_ephy_init(tp, e_info_8168e_2, ARRAY_SIZE(e_info_8168e_2)); + rtl_ephy_init(ioaddr, e_info_8168e_2, ARRAY_SIZE(e_info_8168e_2)); rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - rtl_eri_write(tp, 0xc0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC); - rtl_eri_write(tp, 0xb8, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC); - rtl_eri_write(tp, 0xc8, ERIAR_MASK_1111, 0x00100002, ERIAR_EXGMAC); - rtl_eri_write(tp, 0xe8, ERIAR_MASK_1111, 0x00100006, ERIAR_EXGMAC); - rtl_eri_write(tp, 0xcc, ERIAR_MASK_1111, 0x00000050, ERIAR_EXGMAC); - rtl_eri_write(tp, 0xd0, ERIAR_MASK_1111, 0x07ff0060, ERIAR_EXGMAC); - rtl_w1w0_eri(tp, 0x1b0, ERIAR_MASK_0001, 0x10, 0x00, ERIAR_EXGMAC); - rtl_w1w0_eri(tp, 0x0d4, ERIAR_MASK_0011, 0x0c00, 0xff00, ERIAR_EXGMAC); + rtl_eri_write(ioaddr, 0xc0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC); + rtl_eri_write(ioaddr, 0xb8, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC); + rtl_eri_write(ioaddr, 0xc8, ERIAR_MASK_1111, 0x00100002, ERIAR_EXGMAC); + rtl_eri_write(ioaddr, 0xe8, ERIAR_MASK_1111, 0x00100006, ERIAR_EXGMAC); + rtl_eri_write(ioaddr, 0xcc, ERIAR_MASK_1111, 0x00000050, ERIAR_EXGMAC); + rtl_eri_write(ioaddr, 0xd0, ERIAR_MASK_1111, 0x07ff0060, ERIAR_EXGMAC); + rtl_w1w0_eri(ioaddr, 0x1b0, ERIAR_MASK_0001, 0x10, 0x00, ERIAR_EXGMAC); + rtl_w1w0_eri(ioaddr, 0x0d4, ERIAR_MASK_0011, 0x0c00, 0xff00, + ERIAR_EXGMAC); RTL_W8(MaxTxPacketSize, EarlySize); @@ -5060,16 +4820,16 @@ static void rtl_hw_start_8168f(struct rtl8169_private *tp) rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - rtl_eri_write(tp, 0xc0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC); - rtl_eri_write(tp, 0xb8, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC); - rtl_eri_write(tp, 0xc8, ERIAR_MASK_1111, 0x00100002, ERIAR_EXGMAC); - rtl_eri_write(tp, 0xe8, ERIAR_MASK_1111, 0x00100006, ERIAR_EXGMAC); - rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x00, 0x01, ERIAR_EXGMAC); - rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x01, 0x00, ERIAR_EXGMAC); - rtl_w1w0_eri(tp, 0x1b0, ERIAR_MASK_0001, 0x10, 0x00, ERIAR_EXGMAC); - rtl_w1w0_eri(tp, 0x1d0, ERIAR_MASK_0001, 0x10, 0x00, ERIAR_EXGMAC); - rtl_eri_write(tp, 0xcc, ERIAR_MASK_1111, 0x00000050, ERIAR_EXGMAC); - rtl_eri_write(tp, 0xd0, ERIAR_MASK_1111, 0x00000060, ERIAR_EXGMAC); + rtl_eri_write(ioaddr, 0xc0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC); + rtl_eri_write(ioaddr, 0xb8, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC); + rtl_eri_write(ioaddr, 0xc8, ERIAR_MASK_1111, 0x00100002, ERIAR_EXGMAC); + rtl_eri_write(ioaddr, 0xe8, ERIAR_MASK_1111, 0x00100006, ERIAR_EXGMAC); + rtl_w1w0_eri(ioaddr, 0xdc, ERIAR_MASK_0001, 0x00, 0x01, ERIAR_EXGMAC); + rtl_w1w0_eri(ioaddr, 0xdc, ERIAR_MASK_0001, 0x01, 0x00, ERIAR_EXGMAC); + rtl_w1w0_eri(ioaddr, 0x1b0, ERIAR_MASK_0001, 0x10, 0x00, ERIAR_EXGMAC); + rtl_w1w0_eri(ioaddr, 0x1d0, ERIAR_MASK_0001, 0x10, 0x00, ERIAR_EXGMAC); + rtl_eri_write(ioaddr, 0xcc, ERIAR_MASK_1111, 0x00000050, ERIAR_EXGMAC); + rtl_eri_write(ioaddr, 0xd0, ERIAR_MASK_1111, 0x00000060, ERIAR_EXGMAC); RTL_W8(MaxTxPacketSize, EarlySize); @@ -5094,9 +4854,10 @@ static void rtl_hw_start_8168f_1(struct rtl8169_private *tp) rtl_hw_start_8168f(tp); - rtl_ephy_init(tp, e_info_8168f_1, ARRAY_SIZE(e_info_8168f_1)); + rtl_ephy_init(ioaddr, e_info_8168f_1, ARRAY_SIZE(e_info_8168f_1)); - rtl_w1w0_eri(tp, 0x0d4, ERIAR_MASK_0011, 0x0c00, 0xff00, ERIAR_EXGMAC); + rtl_w1w0_eri(ioaddr, 0x0d4, ERIAR_MASK_0011, 0x0c00, 0xff00, + ERIAR_EXGMAC); /* Adjust EEE LED frequency */ RTL_W8(EEE_LED, RTL_R8(EEE_LED) & ~0x07); @@ -5104,6 +4865,7 @@ static void rtl_hw_start_8168f_1(struct rtl8169_private *tp) static void rtl_hw_start_8411(struct rtl8169_private *tp) { + void __iomem *ioaddr = tp->mmio_addr; static const struct ephy_info e_info_8168f_1[] = { { 0x06, 0x00c0, 0x0020 }, { 0x0f, 0xffff, 0x5200 }, @@ -5113,39 +4875,10 @@ static void rtl_hw_start_8411(struct rtl8169_private *tp) rtl_hw_start_8168f(tp); - rtl_ephy_init(tp, e_info_8168f_1, ARRAY_SIZE(e_info_8168f_1)); + rtl_ephy_init(ioaddr, e_info_8168f_1, ARRAY_SIZE(e_info_8168f_1)); - rtl_w1w0_eri(tp, 0x0d4, ERIAR_MASK_0011, 0x0c00, 0x0000, ERIAR_EXGMAC); -} - -static void rtl_hw_start_8168g_1(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - struct pci_dev *pdev = tp->pci_dev; - - rtl_eri_write(tp, 0xc8, ERIAR_MASK_0101, 0x080002, ERIAR_EXGMAC); - rtl_eri_write(tp, 0xcc, ERIAR_MASK_0001, 0x38, ERIAR_EXGMAC); - rtl_eri_write(tp, 0xd0, ERIAR_MASK_0001, 0x48, ERIAR_EXGMAC); - rtl_eri_write(tp, 0xe8, ERIAR_MASK_1111, 0x00100006, ERIAR_EXGMAC); - - rtl_csi_access_enable_1(tp); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x00, 0x01, ERIAR_EXGMAC); - rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x01, 0x00, ERIAR_EXGMAC); - - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - RTL_W32(MISC, RTL_R32(MISC) & ~RXDV_GATED_EN); - RTL_W8(MaxTxPacketSize, EarlySize); - - rtl_eri_write(tp, 0xc0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC); - rtl_eri_write(tp, 0xb8, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC); - - /* Adjust EEE LED frequency */ - RTL_W8(EEE_LED, RTL_R8(EEE_LED) & ~0x07); - - rtl_w1w0_eri(tp, 0x2fc, ERIAR_MASK_0001, 0x01, 0x02, ERIAR_EXGMAC); + rtl_w1w0_eri(ioaddr, 0x0d4, ERIAR_MASK_0011, 0x0c00, 0x0000, + ERIAR_EXGMAC); } static void rtl_hw_start_8168(struct net_device *dev) @@ -5249,11 +4982,6 @@ static void rtl_hw_start_8168(struct net_device *dev) rtl_hw_start_8411(tp); break; - case RTL_GIGA_MAC_VER_40: - case RTL_GIGA_MAC_VER_41: - rtl_hw_start_8168g_1(tp); - break; - default: printk(KERN_ERR PFX "%s: unknown chipset (mac_version = %d).\n", dev->name, tp->mac_version); @@ -5308,7 +5036,7 @@ static void rtl_hw_start_8102e_1(struct rtl8169_private *tp) if ((cfg1 & LEDS0) && (cfg1 & LEDS1)) RTL_W8(Config1, cfg1 & ~LEDS0); - rtl_ephy_init(tp, e_info_8102e_1, ARRAY_SIZE(e_info_8102e_1)); + rtl_ephy_init(ioaddr, e_info_8102e_1, ARRAY_SIZE(e_info_8102e_1)); } static void rtl_hw_start_8102e_2(struct rtl8169_private *tp) @@ -5328,7 +5056,7 @@ static void rtl_hw_start_8102e_3(struct rtl8169_private *tp) { rtl_hw_start_8102e_2(tp); - rtl_ephy_write(tp, 0x03, 0xc2f9); + rtl_ephy_write(tp->mmio_addr, 0x03, 0xc2f9); } static void rtl_hw_start_8105e_1(struct rtl8169_private *tp) @@ -5354,13 +5082,15 @@ static void rtl_hw_start_8105e_1(struct rtl8169_private *tp) RTL_W8(MCU, RTL_R8(MCU) | EN_NDP | EN_OOB_RESET); RTL_W8(DLLPR, RTL_R8(DLLPR) | PFM_EN); - rtl_ephy_init(tp, e_info_8105e_1, ARRAY_SIZE(e_info_8105e_1)); + rtl_ephy_init(ioaddr, e_info_8105e_1, ARRAY_SIZE(e_info_8105e_1)); } static void rtl_hw_start_8105e_2(struct rtl8169_private *tp) { + void __iomem *ioaddr = tp->mmio_addr; + rtl_hw_start_8105e_1(tp); - rtl_ephy_write(tp, 0x1e, rtl_ephy_read(tp, 0x1e) | 0x8000); + rtl_ephy_write(ioaddr, 0x1e, rtl_ephy_read(ioaddr, 0x1e) | 0x8000); } static void rtl_hw_start_8402(struct rtl8169_private *tp) @@ -5379,29 +5109,18 @@ static void rtl_hw_start_8402(struct rtl8169_private *tp) RTL_W32(TxConfig, RTL_R32(TxConfig) | TXCFG_AUTO_FIFO); RTL_W8(MCU, RTL_R8(MCU) & ~NOW_IS_OOB); - rtl_ephy_init(tp, e_info_8402, ARRAY_SIZE(e_info_8402)); + rtl_ephy_init(ioaddr, e_info_8402, ARRAY_SIZE(e_info_8402)); rtl_tx_performance_tweak(tp->pci_dev, 0x5 << MAX_READ_REQUEST_SHIFT); - rtl_eri_write(tp, 0xc8, ERIAR_MASK_1111, 0x00000002, ERIAR_EXGMAC); - rtl_eri_write(tp, 0xe8, ERIAR_MASK_1111, 0x00000006, ERIAR_EXGMAC); - rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x00, 0x01, ERIAR_EXGMAC); - rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x01, 0x00, ERIAR_EXGMAC); - rtl_eri_write(tp, 0xc0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC); - rtl_eri_write(tp, 0xb8, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC); - rtl_w1w0_eri(tp, 0x0d4, ERIAR_MASK_0011, 0x0e00, 0xff00, ERIAR_EXGMAC); -} - -static void rtl_hw_start_8106(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - - /* Force LAN exit from ASPM if Rx/Tx are not idle */ - RTL_W32(FuncEvent, RTL_R32(FuncEvent) | 0x002800); - - RTL_W32(MISC, (RTL_R32(MISC) | DISABLE_LAN_EN) & ~EARLY_TALLY_EN); - RTL_W8(MCU, RTL_R8(MCU) | EN_NDP | EN_OOB_RESET); - RTL_W8(DLLPR, RTL_R8(DLLPR) & ~PFM_EN); + rtl_eri_write(ioaddr, 0xc8, ERIAR_MASK_1111, 0x00000002, ERIAR_EXGMAC); + rtl_eri_write(ioaddr, 0xe8, ERIAR_MASK_1111, 0x00000006, ERIAR_EXGMAC); + rtl_w1w0_eri(ioaddr, 0xdc, ERIAR_MASK_0001, 0x00, 0x01, ERIAR_EXGMAC); + rtl_w1w0_eri(ioaddr, 0xdc, ERIAR_MASK_0001, 0x01, 0x00, ERIAR_EXGMAC); + rtl_eri_write(ioaddr, 0xc0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC); + rtl_eri_write(ioaddr, 0xb8, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC); + rtl_w1w0_eri(ioaddr, 0x0d4, ERIAR_MASK_0011, 0x0e00, 0xff00, + ERIAR_EXGMAC); } static void rtl_hw_start_8101(struct net_device *dev) @@ -5448,10 +5167,6 @@ static void rtl_hw_start_8101(struct net_device *dev) case RTL_GIGA_MAC_VER_37: rtl_hw_start_8402(tp); break; - - case RTL_GIGA_MAC_VER_39: - rtl_hw_start_8106(tp); - break; } RTL_W8(Cfg9346, Cfg9346_Lock); @@ -6720,67 +6435,6 @@ static unsigned rtl_try_msi(struct rtl8169_private *tp, return msi; } -DECLARE_RTL_COND(rtl_link_list_ready_cond) -{ - void __iomem *ioaddr = tp->mmio_addr; - - return RTL_R8(MCU) & LINK_LIST_RDY; -} - -DECLARE_RTL_COND(rtl_rxtx_empty_cond) -{ - void __iomem *ioaddr = tp->mmio_addr; - - return (RTL_R8(MCU) & RXTX_EMPTY) == RXTX_EMPTY; -} - -static void __devinit rtl_hw_init_8168g(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - u32 data; - - tp->ocp_base = OCP_STD_PHY_BASE; - - RTL_W32(MISC, RTL_R32(MISC) | RXDV_GATED_EN); - - if (!rtl_udelay_loop_wait_high(tp, &rtl_txcfg_empty_cond, 100, 42)) - return; - - if (!rtl_udelay_loop_wait_high(tp, &rtl_rxtx_empty_cond, 100, 42)) - return; - - RTL_W8(ChipCmd, RTL_R8(ChipCmd) & ~(CmdTxEnb | CmdRxEnb)); - msleep(1); - RTL_W8(MCU, RTL_R8(MCU) & ~NOW_IS_OOB); - - data = r8168_mac_ocp_read(tp, 0xe8de); - data &= ~(1 << 14); - r8168_mac_ocp_write(tp, 0xe8de, data); - - if (!rtl_udelay_loop_wait_high(tp, &rtl_link_list_ready_cond, 100, 42)) - return; - - data = r8168_mac_ocp_read(tp, 0xe8de); - data |= (1 << 15); - r8168_mac_ocp_write(tp, 0xe8de, data); - - if (!rtl_udelay_loop_wait_high(tp, &rtl_link_list_ready_cond, 100, 42)) - return; -} - -static void __devinit rtl_hw_initialize(struct rtl8169_private *tp) -{ - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_40: - case RTL_GIGA_MAC_VER_41: - rtl_hw_init_8168g(tp); - break; - - default: - break; - } -} - static int __devinit rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { @@ -6890,8 +6544,6 @@ rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) rtl_irq_disable(tp); - rtl_hw_initialize(tp); - rtl_hw_reset(tp); rtl_ack_events(tp, 0xffff); diff --git a/trunk/drivers/net/ethernet/sfc/filter.c b/trunk/drivers/net/ethernet/sfc/filter.c index fea7f7300675..c3fd61f0a95c 100644 --- a/trunk/drivers/net/ethernet/sfc/filter.c +++ b/trunk/drivers/net/ethernet/sfc/filter.c @@ -662,7 +662,7 @@ s32 efx_filter_insert_filter(struct efx_nic *efx, struct efx_filter_spec *spec, struct efx_filter_table *table = efx_filter_spec_table(state, spec); struct efx_filter_spec *saved_spec; efx_oword_t filter; - unsigned int filter_idx, depth; + unsigned int filter_idx, depth = 0; u32 key; int rc; diff --git a/trunk/drivers/net/ethernet/sfc/mcdi_pcol.h b/trunk/drivers/net/ethernet/sfc/mcdi_pcol.h index db4beed97669..0310b9f08c9b 100644 --- a/trunk/drivers/net/ethernet/sfc/mcdi_pcol.h +++ b/trunk/drivers/net/ethernet/sfc/mcdi_pcol.h @@ -48,7 +48,8 @@ /* Unused commands: 0x23, 0x27, 0x30, 0x31 */ -/* MCDI version 1 +/** + * MCDI version 1 * * Each MCDI request starts with an MCDI_HEADER, which is a 32byte * structure, filled in by the client. diff --git a/trunk/drivers/net/ethernet/sfc/net_driver.h b/trunk/drivers/net/ethernet/sfc/net_driver.h index a1965c07d1e3..0e575359af17 100644 --- a/trunk/drivers/net/ethernet/sfc/net_driver.h +++ b/trunk/drivers/net/ethernet/sfc/net_driver.h @@ -527,7 +527,7 @@ struct efx_phy_operations { }; /** - * enum efx_phy_mode - PHY operating mode flags + * @enum efx_phy_mode - PHY operating mode flags * @PHY_MODE_NORMAL: on and should pass traffic * @PHY_MODE_TX_DISABLED: on with TX disabled * @PHY_MODE_LOW_POWER: set to low power through MDIO diff --git a/trunk/drivers/net/ethernet/sfc/rx.c b/trunk/drivers/net/ethernet/sfc/rx.c index fca61fea38e0..243e91f3dff9 100644 --- a/trunk/drivers/net/ethernet/sfc/rx.c +++ b/trunk/drivers/net/ethernet/sfc/rx.c @@ -336,7 +336,6 @@ static void efx_recycle_rx_buffer(struct efx_channel *channel, /** * efx_fast_push_rx_descriptors - push new RX descriptors quickly * @rx_queue: RX descriptor queue - * * This will aim to fill the RX descriptor queue up to * @rx_queue->@max_fill. If there is insufficient atomic * memory to do so, a slow fill will be scheduled. diff --git a/trunk/drivers/net/ethernet/smsc/smc911x.c b/trunk/drivers/net/ethernet/smsc/smc911x.c index 8d15f7a74b45..8814b2f5d46f 100644 --- a/trunk/drivers/net/ethernet/smsc/smc911x.c +++ b/trunk/drivers/net/ethernet/smsc/smc911x.c @@ -773,7 +773,7 @@ static int smc911x_phy_fixed(struct net_device *dev) return 1; } -/** +/* * smc911x_phy_reset - reset the phy * @dev: net device * @phy: phy address @@ -819,7 +819,7 @@ static int smc911x_phy_reset(struct net_device *dev, int phy) return reg & PMT_CTRL_PHY_RST_; } -/** +/* * smc911x_phy_powerdown - powerdown phy * @dev: net device * @phy: phy address @@ -837,7 +837,7 @@ static void smc911x_phy_powerdown(struct net_device *dev, int phy) SMC_SET_PHY_BMCR(lp, phy, bmcr); } -/** +/* * smc911x_phy_check_media - check the media status and adjust BMCR * @dev: net device * @init: set true for initialisation diff --git a/trunk/drivers/net/ethernet/smsc/smc91x.c b/trunk/drivers/net/ethernet/smsc/smc91x.c index 318adc935a53..fee449355014 100644 --- a/trunk/drivers/net/ethernet/smsc/smc91x.c +++ b/trunk/drivers/net/ethernet/smsc/smc91x.c @@ -942,7 +942,7 @@ static int smc_phy_fixed(struct net_device *dev) return 1; } -/** +/* * smc_phy_reset - reset the phy * @dev: net device * @phy: phy address @@ -976,7 +976,7 @@ static int smc_phy_reset(struct net_device *dev, int phy) return bmcr & BMCR_RESET; } -/** +/* * smc_phy_powerdown - powerdown phy * @dev: net device * @@ -1000,7 +1000,7 @@ static void smc_phy_powerdown(struct net_device *dev) smc_phy_write(dev, phy, MII_BMCR, bmcr | BMCR_PDOWN); } -/** +/* * smc_phy_check_media - check the media status and adjust TCR * @dev: net device * @init: set true for initialisation diff --git a/trunk/drivers/net/ethernet/smsc/smsc911x.c b/trunk/drivers/net/ethernet/smsc/smsc911x.c index 62d1baf111ea..54ca99dbb406 100644 --- a/trunk/drivers/net/ethernet/smsc/smsc911x.c +++ b/trunk/drivers/net/ethernet/smsc/smsc911x.c @@ -2488,7 +2488,7 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev) eth_hw_addr_random(dev); smsc911x_set_hw_mac_address(pdata, dev->dev_addr); SMSC_TRACE(pdata, probe, - "MAC Address is set to eth_random_addr"); + "MAC Address is set to random_ether_addr"); } } diff --git a/trunk/drivers/net/ethernet/stmicro/stmmac/ring_mode.c b/trunk/drivers/net/ethernet/stmicro/stmmac/ring_mode.c index 4b785e10f2ed..fb8377da1687 100644 --- a/trunk/drivers/net/ethernet/stmicro/stmmac/ring_mode.c +++ b/trunk/drivers/net/ethernet/stmicro/stmmac/ring_mode.c @@ -51,7 +51,7 @@ static unsigned int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int csum) desc->des3 = desc->des2 + BUF_SIZE_4KiB; priv->hw->desc->prepare_tx_desc(desc, 1, bmax, csum); - wmb(); + entry = (++priv->cur_tx) % txsize; desc = priv->dma_tx + entry; @@ -59,7 +59,6 @@ static unsigned int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int csum) len, DMA_TO_DEVICE); desc->des3 = desc->des2 + BUF_SIZE_4KiB; priv->hw->desc->prepare_tx_desc(desc, 0, len, csum); - wmb(); priv->hw->desc->set_tx_owner(desc); priv->tx_skbuff[entry] = NULL; } else { diff --git a/trunk/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/trunk/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index f6b04c1a3672..ea3bc0963bd7 100644 --- a/trunk/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/trunk/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -1334,7 +1334,6 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev) priv->hw->desc->prepare_tx_desc(desc, 0, len, csum_insertion); wmb(); priv->hw->desc->set_tx_owner(desc); - wmb(); } /* Interrupt on completition only for the latest segment */ @@ -1350,7 +1349,6 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev) /* To avoid raise condition */ priv->hw->desc->set_tx_owner(first); - wmb(); priv->cur_tx++; @@ -1414,7 +1412,6 @@ static inline void stmmac_rx_refill(struct stmmac_priv *priv) } wmb(); priv->hw->desc->set_rx_owner(p + entry); - wmb(); } } diff --git a/trunk/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c b/trunk/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c index 13afb8edfadc..cf826e6b6aa1 100644 --- a/trunk/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c +++ b/trunk/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c @@ -125,7 +125,7 @@ static int __devinit stmmac_pci_probe(struct pci_dev *pdev, } /** - * stmmac_pci_remove + * stmmac_dvr_remove * * @pdev: platform device pointer * Description: this function calls the main to free the net resources diff --git a/trunk/drivers/net/ethernet/sun/sunbmac.c b/trunk/drivers/net/ethernet/sun/sunbmac.c index 967fe8cb476e..2a83fc57edba 100644 --- a/trunk/drivers/net/ethernet/sun/sunbmac.c +++ b/trunk/drivers/net/ethernet/sun/sunbmac.c @@ -233,6 +233,7 @@ static void bigmac_init_rings(struct bigmac *bp, int from_irq) continue; bp->rx_skbs[i] = skb; + skb->dev = dev; /* Because we reserve afterwards. */ skb_put(skb, ETH_FRAME_LEN); @@ -837,6 +838,7 @@ static void bigmac_rx(struct bigmac *bp) RX_BUF_ALLOC_SIZE - 34, DMA_FROM_DEVICE); bp->rx_skbs[elem] = new_skb; + new_skb->dev = bp->dev; skb_put(new_skb, ETH_FRAME_LEN); skb_reserve(new_skb, 34); this->rx_addr = diff --git a/trunk/drivers/net/ethernet/sun/sungem.c b/trunk/drivers/net/ethernet/sun/sungem.c index 9ae12d0c9632..3cf4ab755838 100644 --- a/trunk/drivers/net/ethernet/sun/sungem.c +++ b/trunk/drivers/net/ethernet/sun/sungem.c @@ -752,6 +752,7 @@ static __inline__ struct sk_buff *gem_alloc_skb(struct net_device *dev, int size if (likely(skb)) { unsigned long offset = ALIGNED_RX_SKB_ADDR(skb->data); skb_reserve(skb, offset); + skb->dev = dev; } return skb; } diff --git a/trunk/drivers/net/ethernet/sun/sunhme.c b/trunk/drivers/net/ethernet/sun/sunhme.c index 73f341b8befb..dfc00c4683e5 100644 --- a/trunk/drivers/net/ethernet/sun/sunhme.c +++ b/trunk/drivers/net/ethernet/sun/sunhme.c @@ -1249,6 +1249,7 @@ static void happy_meal_clean_rings(struct happy_meal *hp) static void happy_meal_init_rings(struct happy_meal *hp) { struct hmeal_init_block *hb = hp->happy_block; + struct net_device *dev = hp->dev; int i; HMD(("happy_meal_init_rings: counters to zero, ")); @@ -1269,6 +1270,7 @@ static void happy_meal_init_rings(struct happy_meal *hp) continue; } hp->rx_skbs[i] = skb; + skb->dev = dev; /* Because we reserve afterwards. */ skb_put(skb, (ETH_FRAME_LEN + RX_OFFSET + 4)); @@ -2029,6 +2031,7 @@ static void happy_meal_rx(struct happy_meal *hp, struct net_device *dev) } dma_unmap_single(hp->dma_dev, dma_addr, RX_BUF_ALLOC_SIZE, DMA_FROM_DEVICE); hp->rx_skbs[elem] = new_skb; + new_skb->dev = dev; skb_put(new_skb, (ETH_FRAME_LEN + RX_OFFSET + 4)); hme_write_rxd(hp, this, (RXFLAG_OWN|((RX_BUF_ALLOC_SIZE-RX_OFFSET)<<16)), diff --git a/trunk/drivers/net/ethernet/tehuti/tehuti.c b/trunk/drivers/net/ethernet/tehuti/tehuti.c index 6ce9edd95c04..447a6932cab3 100644 --- a/trunk/drivers/net/ethernet/tehuti/tehuti.c +++ b/trunk/drivers/net/ethernet/tehuti/tehuti.c @@ -137,15 +137,14 @@ static void print_eth_id(struct net_device *ndev) #define bdx_disable_interrupts(priv) \ do { WRITE_REG(priv, regIMR, 0); } while (0) -/** - * bdx_fifo_init - create TX/RX descriptor fifo for host-NIC communication. - * @priv: NIC private structure - * @f: fifo to initialize - * @fsz_type: fifo size type: 0-4KB, 1-8KB, 2-16KB, 3-32KB - * @reg_XXX: offsets of registers relative to base address - * +/* bdx_fifo_init + * create TX/RX descriptor fifo for host-NIC communication. * 1K extra space is allocated at the end of the fifo to simplify * processing of descriptors that wraps around fifo's end + * @priv - NIC private structure + * @f - fifo to initialize + * @fsz_type - fifo size type: 0-4KB, 1-8KB, 2-16KB, 3-32KB + * @reg_XXX - offsets of registers relative to base address * * Returns 0 on success, negative value on failure * @@ -178,10 +177,9 @@ bdx_fifo_init(struct bdx_priv *priv, struct fifo *f, int fsz_type, RET(0); } -/** - * bdx_fifo_free - free all resources used by fifo - * @priv: NIC private structure - * @f: fifo to release +/* bdx_fifo_free - free all resources used by fifo + * @priv - NIC private structure + * @f - fifo to release */ static void bdx_fifo_free(struct bdx_priv *priv, struct fifo *f) { @@ -194,9 +192,9 @@ static void bdx_fifo_free(struct bdx_priv *priv, struct fifo *f) RET(); } -/** +/* * bdx_link_changed - notifies OS about hw link state. - * @priv: hw adapter structure + * @bdx_priv - hw adapter structure */ static void bdx_link_changed(struct bdx_priv *priv) { @@ -235,10 +233,10 @@ static void bdx_isr_extra(struct bdx_priv *priv, u32 isr) } -/** - * bdx_isr_napi - Interrupt Service Routine for Bordeaux NIC - * @irq: interrupt number - * @dev: network device +/* bdx_isr - Interrupt Service Routine for Bordeaux NIC + * @irq - interrupt number + * @ndev - network device + * @regs - CPU registers * * Return IRQ_NONE if it was not our interrupt, IRQ_HANDLED - otherwise * @@ -309,10 +307,8 @@ static int bdx_poll(struct napi_struct *napi, int budget) return work_done; } -/** - * bdx_fw_load - loads firmware to NIC - * @priv: NIC private structure - * +/* bdx_fw_load - loads firmware to NIC + * @priv - NIC private structure * Firmware is loaded via TXD fifo, so it must be initialized first. * Firware must be loaded once per NIC not per PCI device provided by NIC (NIC * can have few of them). So all drivers use semaphore register to choose one @@ -384,9 +380,8 @@ static void bdx_restore_mac(struct net_device *ndev, struct bdx_priv *priv) RET(); } -/** - * bdx_hw_start - inits registers and starts HW's Rx and Tx engines - * @priv: NIC private structure +/* bdx_hw_start - inits registers and starts HW's Rx and Tx engines + * @priv - NIC private structure */ static int bdx_hw_start(struct bdx_priv *priv) { @@ -696,13 +691,12 @@ static int bdx_ioctl(struct net_device *ndev, struct ifreq *ifr, int cmd) RET(-EOPNOTSUPP); } -/** +/* * __bdx_vlan_rx_vid - private helper for adding/killing VLAN vid - * @ndev: network device - * @vid: VLAN vid - * @op: add or kill operation - * - * Passes VLAN filter table to hardware + * by passing VLAN filter table to hardware + * @ndev network device + * @vid VLAN vid + * @op add or kill operation */ static void __bdx_vlan_rx_vid(struct net_device *ndev, uint16_t vid, int enable) { @@ -728,10 +722,10 @@ static void __bdx_vlan_rx_vid(struct net_device *ndev, uint16_t vid, int enable) RET(); } -/** +/* * bdx_vlan_rx_add_vid - kernel hook for adding VLAN vid to hw filtering table - * @ndev: network device - * @vid: VLAN vid to add + * @ndev network device + * @vid VLAN vid to add */ static int bdx_vlan_rx_add_vid(struct net_device *ndev, uint16_t vid) { @@ -739,10 +733,10 @@ static int bdx_vlan_rx_add_vid(struct net_device *ndev, uint16_t vid) return 0; } -/** +/* * bdx_vlan_rx_kill_vid - kernel hook for killing VLAN vid in hw filtering table - * @ndev: network device - * @vid: VLAN vid to kill + * @ndev network device + * @vid VLAN vid to kill */ static int bdx_vlan_rx_kill_vid(struct net_device *ndev, unsigned short vid) { @@ -980,9 +974,8 @@ static inline void bdx_rxdb_free_elem(struct rxdb *db, int n) * Rx Init * *************************************************************************/ -/** - * bdx_rx_init - initialize RX all related HW and SW resources - * @priv: NIC private structure +/* bdx_rx_init - initialize RX all related HW and SW resources + * @priv - NIC private structure * * Returns 0 on success, negative value on failure * @@ -1023,10 +1016,9 @@ static int bdx_rx_init(struct bdx_priv *priv) return -ENOMEM; } -/** - * bdx_rx_free_skbs - frees and unmaps all skbs allocated for the fifo - * @priv: NIC private structure - * @f: RXF fifo +/* bdx_rx_free_skbs - frees and unmaps all skbs allocated for the fifo + * @priv - NIC private structure + * @f - RXF fifo */ static void bdx_rx_free_skbs(struct bdx_priv *priv, struct rxf_fifo *f) { @@ -1053,10 +1045,8 @@ static void bdx_rx_free_skbs(struct bdx_priv *priv, struct rxf_fifo *f) } } -/** - * bdx_rx_free - release all Rx resources - * @priv: NIC private structure - * +/* bdx_rx_free - release all Rx resources + * @priv - NIC private structure * It assumes that Rx is desabled in HW */ static void bdx_rx_free(struct bdx_priv *priv) @@ -1077,11 +1067,9 @@ static void bdx_rx_free(struct bdx_priv *priv) * Rx Engine * *************************************************************************/ -/** - * bdx_rx_alloc_skbs - fill rxf fifo with new skbs - * @priv: nic's private structure - * @f: RXF fifo that needs skbs - * +/* bdx_rx_alloc_skbs - fill rxf fifo with new skbs + * @priv - nic's private structure + * @f - RXF fifo that needs skbs * It allocates skbs, build rxf descs and push it (rxf descr) into rxf fifo. * skb's virtual and physical addresses are stored in skb db. * To calculate free space, func uses cached values of RPTR and WPTR @@ -1191,15 +1179,13 @@ static void bdx_recycle_skb(struct bdx_priv *priv, struct rxd_desc *rxdd) RET(); } -/** - * bdx_rx_receive - receives full packets from RXD fifo and pass them to OS +/* bdx_rx_receive - receives full packets from RXD fifo and pass them to OS * NOTE: a special treatment is given to non-continuous descriptors * that start near the end, wraps around and continue at the beginning. a second * part is copied right after the first, and then descriptor is interpreted as * normal. fifo has an extra space to allow such operations - * @priv: nic's private structure - * @f: RXF fifo that needs skbs - * @budget: maximum number of packets to receive + * @priv - nic's private structure + * @f - RXF fifo that needs skbs */ /* TBD: replace memcpy func call by explicite inline asm */ @@ -1389,10 +1375,9 @@ static inline int bdx_tx_db_size(struct txdb *db) return db->size - taken; } -/** - * __bdx_tx_db_ptr_next - helper function, increment read/write pointer + wrap - * @db: tx data base - * @pptr: read or write pointer +/* __bdx_tx_ptr_next - helper function, increment read/write pointer + wrap + * @d - tx data base + * @ptr - read or write pointer */ static inline void __bdx_tx_db_ptr_next(struct txdb *db, struct tx_map **pptr) { @@ -1409,9 +1394,8 @@ static inline void __bdx_tx_db_ptr_next(struct txdb *db, struct tx_map **pptr) *pptr = db->start; } -/** - * bdx_tx_db_inc_rptr - increment read pointer - * @db: tx data base +/* bdx_tx_db_inc_rptr - increment read pointer + * @d - tx data base */ static inline void bdx_tx_db_inc_rptr(struct txdb *db) { @@ -1419,9 +1403,8 @@ static inline void bdx_tx_db_inc_rptr(struct txdb *db) __bdx_tx_db_ptr_next(db, &db->rptr); } -/** - * bdx_tx_db_inc_wptr - increment write pointer - * @db: tx data base +/* bdx_tx_db_inc_rptr - increment write pointer + * @d - tx data base */ static inline void bdx_tx_db_inc_wptr(struct txdb *db) { @@ -1430,11 +1413,9 @@ static inline void bdx_tx_db_inc_wptr(struct txdb *db) a result of write */ } -/** - * bdx_tx_db_init - creates and initializes tx db - * @d: tx data base - * @sz_type: size of tx fifo - * +/* bdx_tx_db_init - creates and initializes tx db + * @d - tx data base + * @sz_type - size of tx fifo * Returns 0 on success, error code otherwise */ static int bdx_tx_db_init(struct txdb *d, int sz_type) @@ -1460,9 +1441,8 @@ static int bdx_tx_db_init(struct txdb *d, int sz_type) return 0; } -/** - * bdx_tx_db_close - closes tx db and frees all memory - * @d: tx data base +/* bdx_tx_db_close - closes tx db and frees all memory + * @d - tx data base */ static void bdx_tx_db_close(struct txdb *d) { @@ -1483,11 +1463,9 @@ static struct { u16 qwords; /* qword = 64 bit */ } txd_sizes[MAX_SKB_FRAGS + 1]; -/** - * bdx_tx_map_skb - creates and stores dma mappings for skb's data blocks - * @priv: NIC private structure - * @skb: socket buffer to map - * @txdd: TX descriptor to use +/* txdb_map_skb - creates and stores dma mappings for skb's data blocks + * @priv - NIC private structure + * @skb - socket buffer to map * * It makes dma mappings for skb's data blocks and writes them to PBL of * new tx descriptor. It also stores them in the tx db, so they could be @@ -1584,10 +1562,9 @@ static int bdx_tx_init(struct bdx_priv *priv) return -ENOMEM; } -/** +/* * bdx_tx_space - calculates available space in TX fifo - * @priv: NIC private structure - * + * @priv - NIC private structure * Returns available space in TX fifo in bytes */ static inline int bdx_tx_space(struct bdx_priv *priv) @@ -1602,10 +1579,9 @@ static inline int bdx_tx_space(struct bdx_priv *priv) return fsize; } -/** - * bdx_tx_transmit - send packet to NIC - * @skb: packet to send - * @ndev: network device assigned to NIC +/* bdx_tx_transmit - send packet to NIC + * @skb - packet to send + * ndev - network device assigned to NIC * Return codes: * o NETDEV_TX_OK everything ok. * o NETDEV_TX_BUSY Cannot transmit packet, try later @@ -1723,10 +1699,8 @@ static netdev_tx_t bdx_tx_transmit(struct sk_buff *skb, return NETDEV_TX_OK; } -/** - * bdx_tx_cleanup - clean TXF fifo, run in the context of IRQ. - * @priv: bdx adapter - * +/* bdx_tx_cleanup - clean TXF fifo, run in the context of IRQ. + * @priv - bdx adapter * It scans TXF fifo for descriptors, frees DMA mappings and reports to OS * that those packets were sent */ @@ -1787,8 +1761,7 @@ static void bdx_tx_cleanup(struct bdx_priv *priv) spin_unlock(&priv->tx_lock); } -/** - * bdx_tx_free_skbs - frees all skbs from TXD fifo. +/* bdx_tx_free_skbs - frees all skbs from TXD fifo. * It gets called when OS stops this dev, eg upon "ifconfig down" or rmmod */ static void bdx_tx_free_skbs(struct bdx_priv *priv) @@ -1817,11 +1790,10 @@ static void bdx_tx_free(struct bdx_priv *priv) bdx_tx_db_close(&priv->txdb); } -/** - * bdx_tx_push_desc - push descriptor to TxD fifo - * @priv: NIC private structure - * @data: desc's data - * @size: desc's size +/* bdx_tx_push_desc - push descriptor to TxD fifo + * @priv - NIC private structure + * @data - desc's data + * @size - desc's size * * Pushes desc to TxD fifo and overlaps it if needed. * NOTE: this func does not check for available space. this is responsibility @@ -1847,11 +1819,10 @@ static void bdx_tx_push_desc(struct bdx_priv *priv, void *data, int size) WRITE_REG(priv, f->m.reg_WPTR, f->m.wptr & TXF_WPTR_WR_PTR); } -/** - * bdx_tx_push_desc_safe - push descriptor to TxD fifo in a safe way - * @priv: NIC private structure - * @data: desc's data - * @size: desc's size +/* bdx_tx_push_desc_safe - push descriptor to TxD fifo in a safe way + * @priv - NIC private structure + * @data - desc's data + * @size - desc's size * * NOTE: this func does check for available space and, if necessary, waits for * NIC to read existing data before writing new one. diff --git a/trunk/drivers/net/ethernet/ti/cpsw.c b/trunk/drivers/net/ethernet/ti/cpsw.c index ca381d3f9fa8..6685bbb5705a 100644 --- a/trunk/drivers/net/ethernet/ti/cpsw.c +++ b/trunk/drivers/net/ethernet/ti/cpsw.c @@ -748,7 +748,7 @@ static int __devinit cpsw_probe(struct platform_device *pdev) memcpy(priv->mac_addr, data->slave_data[0].mac_addr, ETH_ALEN); pr_info("Detected MACID = %pM", priv->mac_addr); } else { - eth_random_addr(priv->mac_addr); + random_ether_addr(priv->mac_addr); pr_info("Random MACID = %pM", priv->mac_addr); } diff --git a/trunk/drivers/net/ethernet/ti/davinci_emac.c b/trunk/drivers/net/ethernet/ti/davinci_emac.c index ab0bbb78699a..4da93a5d7ec6 100644 --- a/trunk/drivers/net/ethernet/ti/davinci_emac.c +++ b/trunk/drivers/net/ethernet/ti/davinci_emac.c @@ -375,7 +375,7 @@ static char *emac_rxhost_errcodes[16] = { #define emac_ctrl_write(reg, val) iowrite32(val, (priv->ctrl_base + (reg))) /** - * emac_dump_regs - Dump important EMAC registers to debug terminal + * emac_dump_regs: Dump important EMAC registers to debug terminal * @priv: The DaVinci EMAC private adapter structure * * Executes ethtool set cmd & sets phy mode @@ -466,7 +466,7 @@ static void emac_dump_regs(struct emac_priv *priv) } /** - * emac_get_drvinfo - Get EMAC driver information + * emac_get_drvinfo: Get EMAC driver information * @ndev: The DaVinci EMAC network adapter * @info: ethtool info structure containing name and version * @@ -481,7 +481,7 @@ static void emac_get_drvinfo(struct net_device *ndev, } /** - * emac_get_settings - Get EMAC settings + * emac_get_settings: Get EMAC settings * @ndev: The DaVinci EMAC network adapter * @ecmd: ethtool command * @@ -500,7 +500,7 @@ static int emac_get_settings(struct net_device *ndev, } /** - * emac_set_settings - Set EMAC settings + * emac_set_settings: Set EMAC settings * @ndev: The DaVinci EMAC network adapter * @ecmd: ethtool command * @@ -518,7 +518,7 @@ static int emac_set_settings(struct net_device *ndev, struct ethtool_cmd *ecmd) } /** - * emac_get_coalesce - Get interrupt coalesce settings for this device + * emac_get_coalesce : Get interrupt coalesce settings for this device * @ndev : The DaVinci EMAC network adapter * @coal : ethtool coalesce settings structure * @@ -536,7 +536,7 @@ static int emac_get_coalesce(struct net_device *ndev, } /** - * emac_set_coalesce - Set interrupt coalesce settings for this device + * emac_set_coalesce : Set interrupt coalesce settings for this device * @ndev : The DaVinci EMAC network adapter * @coal : ethtool coalesce settings structure * @@ -614,9 +614,11 @@ static int emac_set_coalesce(struct net_device *ndev, } -/* ethtool_ops: DaVinci EMAC Ethtool structure +/** + * ethtool_ops: DaVinci EMAC Ethtool structure * * Ethtool support for EMAC adapter + * */ static const struct ethtool_ops ethtool_ops = { .get_drvinfo = emac_get_drvinfo, @@ -629,7 +631,7 @@ static const struct ethtool_ops ethtool_ops = { }; /** - * emac_update_phystatus - Update Phy status + * emac_update_phystatus: Update Phy status * @priv: The DaVinci EMAC private adapter structure * * Updates phy status and takes action for network queue if required @@ -695,7 +697,7 @@ static void emac_update_phystatus(struct emac_priv *priv) } /** - * hash_get - Calculate hash value from mac address + * hash_get: Calculate hash value from mac address * @addr: mac address to delete from hash table * * Calculates hash value from mac address @@ -721,9 +723,9 @@ static u32 hash_get(u8 *addr) } /** - * hash_add - Hash function to add mac addr from hash table + * hash_add: Hash function to add mac addr from hash table * @priv: The DaVinci EMAC private adapter structure - * @mac_addr: mac address to delete from hash table + * mac_addr: mac address to delete from hash table * * Adds mac address to the internal hash table * @@ -763,9 +765,9 @@ static int hash_add(struct emac_priv *priv, u8 *mac_addr) } /** - * hash_del - Hash function to delete mac addr from hash table + * hash_del: Hash function to delete mac addr from hash table * @priv: The DaVinci EMAC private adapter structure - * @mac_addr: mac address to delete from hash table + * mac_addr: mac address to delete from hash table * * Removes mac address from the internal hash table * @@ -805,7 +807,7 @@ static int hash_del(struct emac_priv *priv, u8 *mac_addr) #define EMAC_ALL_MULTI_CLR 3 /** - * emac_add_mcast - Set multicast address in the EMAC adapter (Internal) + * emac_add_mcast: Set multicast address in the EMAC adapter (Internal) * @priv: The DaVinci EMAC private adapter structure * @action: multicast operation to perform * mac_addr: mac address to set @@ -853,7 +855,7 @@ static void emac_add_mcast(struct emac_priv *priv, u32 action, u8 *mac_addr) } /** - * emac_dev_mcast_set - Set multicast address in the EMAC adapter + * emac_dev_mcast_set: Set multicast address in the EMAC adapter * @ndev: The DaVinci EMAC network adapter * * Set multicast addresses in EMAC adapter @@ -899,7 +901,7 @@ static void emac_dev_mcast_set(struct net_device *ndev) *************************************************************************/ /** - * emac_int_disable - Disable EMAC module interrupt (from adapter) + * emac_int_disable: Disable EMAC module interrupt (from adapter) * @priv: The DaVinci EMAC private adapter structure * * Disable EMAC interrupt on the adapter @@ -929,7 +931,7 @@ static void emac_int_disable(struct emac_priv *priv) } /** - * emac_int_enable - Enable EMAC module interrupt (from adapter) + * emac_int_enable: Enable EMAC module interrupt (from adapter) * @priv: The DaVinci EMAC private adapter structure * * Enable EMAC interrupt on the adapter @@ -965,7 +967,7 @@ static void emac_int_enable(struct emac_priv *priv) } /** - * emac_irq - EMAC interrupt handler + * emac_irq: EMAC interrupt handler * @irq: interrupt number * @dev_id: EMAC network adapter data structure ptr * @@ -1058,7 +1060,7 @@ static void emac_tx_handler(void *token, int len, int status) } /** - * emac_dev_xmit - EMAC Transmit function + * emac_dev_xmit: EMAC Transmit function * @skb: SKB pointer * @ndev: The DaVinci EMAC network adapter * @@ -1109,7 +1111,7 @@ static int emac_dev_xmit(struct sk_buff *skb, struct net_device *ndev) } /** - * emac_dev_tx_timeout - EMAC Transmit timeout function + * emac_dev_tx_timeout: EMAC Transmit timeout function * @ndev: The DaVinci EMAC network adapter * * Called when system detects that a skb timeout period has expired @@ -1136,7 +1138,7 @@ static void emac_dev_tx_timeout(struct net_device *ndev) } /** - * emac_set_type0addr - Set EMAC Type0 mac address + * emac_set_type0addr: Set EMAC Type0 mac address * @priv: The DaVinci EMAC private adapter structure * @ch: RX channel number * @mac_addr: MAC address to set in device @@ -1163,7 +1165,7 @@ static void emac_set_type0addr(struct emac_priv *priv, u32 ch, char *mac_addr) } /** - * emac_set_type1addr - Set EMAC Type1 mac address + * emac_set_type1addr: Set EMAC Type1 mac address * @priv: The DaVinci EMAC private adapter structure * @ch: RX channel number * @mac_addr: MAC address to set in device @@ -1185,7 +1187,7 @@ static void emac_set_type1addr(struct emac_priv *priv, u32 ch, char *mac_addr) } /** - * emac_set_type2addr - Set EMAC Type2 mac address + * emac_set_type2addr: Set EMAC Type2 mac address * @priv: The DaVinci EMAC private adapter structure * @ch: RX channel number * @mac_addr: MAC address to set in device @@ -1211,7 +1213,7 @@ static void emac_set_type2addr(struct emac_priv *priv, u32 ch, } /** - * emac_setmac - Set mac address in the adapter (internal function) + * emac_setmac: Set mac address in the adapter (internal function) * @priv: The DaVinci EMAC private adapter structure * @ch: RX channel number * @mac_addr: MAC address to set in device @@ -1240,7 +1242,7 @@ static void emac_setmac(struct emac_priv *priv, u32 ch, char *mac_addr) } /** - * emac_dev_setmac_addr - Set mac address in the adapter + * emac_dev_setmac_addr: Set mac address in the adapter * @ndev: The DaVinci EMAC network adapter * @addr: MAC address to set in device * @@ -1275,7 +1277,7 @@ static int emac_dev_setmac_addr(struct net_device *ndev, void *addr) } /** - * emac_hw_enable - Enable EMAC hardware for packet transmission/reception + * emac_hw_enable: Enable EMAC hardware for packet transmission/reception * @priv: The DaVinci EMAC private adapter structure * * Enables EMAC hardware for packet processing - enables PHY, enables RX @@ -1345,7 +1347,7 @@ static int emac_hw_enable(struct emac_priv *priv) } /** - * emac_poll - EMAC NAPI Poll function + * emac_poll: EMAC NAPI Poll function * @ndev: The DaVinci EMAC network adapter * @budget: Number of receive packets to process (as told by NAPI layer) * @@ -1428,7 +1430,7 @@ static int emac_poll(struct napi_struct *napi, int budget) #ifdef CONFIG_NET_POLL_CONTROLLER /** - * emac_poll_controller - EMAC Poll controller function + * emac_poll_controller: EMAC Poll controller function * @ndev: The DaVinci EMAC network adapter * * Polled functionality used by netconsole and others in non interrupt mode @@ -1487,7 +1489,7 @@ static void emac_adjust_link(struct net_device *ndev) *************************************************************************/ /** - * emac_devioctl - EMAC adapter ioctl + * emac_devioctl: EMAC adapter ioctl * @ndev: The DaVinci EMAC network adapter * @ifrq: request parameter * @cmd: command parameter @@ -1514,7 +1516,7 @@ static int match_first_device(struct device *dev, void *data) } /** - * emac_dev_open - EMAC device open + * emac_dev_open: EMAC device open * @ndev: The DaVinci EMAC network adapter * * Called when system wants to start the interface. We init TX/RX channels @@ -1647,7 +1649,7 @@ static int emac_dev_open(struct net_device *ndev) } /** - * emac_dev_stop - EMAC device stop + * emac_dev_stop: EMAC device stop * @ndev: The DaVinci EMAC network adapter * * Called when system wants to stop or down the interface. We stop the network @@ -1689,7 +1691,7 @@ static int emac_dev_stop(struct net_device *ndev) } /** - * emac_dev_getnetstats - EMAC get statistics function + * emac_dev_getnetstats: EMAC get statistics function * @ndev: The DaVinci EMAC network adapter * * Called when system wants to get statistics from the device. @@ -1761,7 +1763,7 @@ static const struct net_device_ops emac_netdev_ops = { }; /** - * davinci_emac_probe - EMAC device probe + * davinci_emac_probe: EMAC device probe * @pdev: The DaVinci EMAC device that we are removing * * Called when probing for emac devicesr. We get details of instances and @@ -1947,7 +1949,7 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev) } /** - * davinci_emac_remove - EMAC device remove + * davinci_emac_remove: EMAC device remove * @pdev: The DaVinci EMAC device that we are removing * * Called when removing the device driver. We disable clock usage and release @@ -2013,7 +2015,9 @@ static const struct dev_pm_ops davinci_emac_pm_ops = { .resume = davinci_emac_resume, }; -/* davinci_emac_driver: EMAC platform driver structure */ +/** + * davinci_emac_driver: EMAC platform driver structure + */ static struct platform_driver davinci_emac_driver = { .driver = { .name = "davinci_emac", @@ -2025,7 +2029,7 @@ static struct platform_driver davinci_emac_driver = { }; /** - * davinci_emac_init - EMAC driver module init + * davinci_emac_init: EMAC driver module init * * Called when initializing the driver. We register the driver with * the platform. @@ -2037,7 +2041,7 @@ static int __init davinci_emac_init(void) late_initcall(davinci_emac_init); /** - * davinci_emac_exit - EMAC driver module exit + * davinci_emac_exit: EMAC driver module exit * * Called when exiting the driver completely. We unregister the driver with * the platform and exit diff --git a/trunk/drivers/net/ethernet/tile/tilegx.c b/trunk/drivers/net/ethernet/tile/tilegx.c index 7f500288f6b3..83b4b388ad49 100644 --- a/trunk/drivers/net/ethernet/tile/tilegx.c +++ b/trunk/drivers/net/ethernet/tile/tilegx.c @@ -1844,7 +1844,7 @@ static void tile_net_dev_init(const char *name, const uint8_t *mac) memcpy(dev->dev_addr, mac, 6); dev->addr_len = 6; } else { - eth_random_addr(dev->dev_addr); + random_ether_addr(dev->dev_addr); } /* Register the network device. */ diff --git a/trunk/drivers/net/ethernet/toshiba/spider_net.c b/trunk/drivers/net/ethernet/toshiba/spider_net.c index c1ebfe9efcb3..6199f6b387b6 100644 --- a/trunk/drivers/net/ethernet/toshiba/spider_net.c +++ b/trunk/drivers/net/ethernet/toshiba/spider_net.c @@ -114,8 +114,7 @@ spider_net_write_reg(struct spider_net_card *card, u32 reg, u32 value) out_be32(card->regs + reg, value); } -/** - * spider_net_write_phy - write to phy register +/** spider_net_write_phy - write to phy register * @netdev: adapter to be written to * @mii_id: id of MII * @reg: PHY register @@ -138,8 +137,7 @@ spider_net_write_phy(struct net_device *netdev, int mii_id, spider_net_write_reg(card, SPIDER_NET_GPCWOPCMD, writevalue); } -/** - * spider_net_read_phy - read from phy register +/** spider_net_read_phy - read from phy register * @netdev: network device to be read from * @mii_id: id of MII * @reg: PHY register diff --git a/trunk/drivers/net/ethernet/wiznet/w5100.c b/trunk/drivers/net/ethernet/wiznet/w5100.c index a5826a3111a6..a75e9ef5a4ce 100644 --- a/trunk/drivers/net/ethernet/wiznet/w5100.c +++ b/trunk/drivers/net/ethernet/wiznet/w5100.c @@ -637,7 +637,7 @@ static int __devinit w5100_hw_probe(struct platform_device *pdev) if (data && is_valid_ether_addr(data->mac_addr)) { memcpy(ndev->dev_addr, data->mac_addr, ETH_ALEN); } else { - eth_random_addr(ndev->dev_addr); + random_ether_addr(ndev->dev_addr); ndev->addr_assign_type |= NET_ADDR_RANDOM; } diff --git a/trunk/drivers/net/ethernet/wiznet/w5300.c b/trunk/drivers/net/ethernet/wiznet/w5300.c index bdd8891c215a..3306a20ec211 100644 --- a/trunk/drivers/net/ethernet/wiznet/w5300.c +++ b/trunk/drivers/net/ethernet/wiznet/w5300.c @@ -557,7 +557,7 @@ static int __devinit w5300_hw_probe(struct platform_device *pdev) if (data && is_valid_ether_addr(data->mac_addr)) { memcpy(ndev->dev_addr, data->mac_addr, ETH_ALEN); } else { - eth_random_addr(ndev->dev_addr); + random_ether_addr(ndev->dev_addr); ndev->addr_assign_type |= NET_ADDR_RANDOM; } diff --git a/trunk/drivers/net/ethernet/xilinx/ll_temac_main.c b/trunk/drivers/net/ethernet/xilinx/ll_temac_main.c index f8e351880119..1eaf7128afee 100644 --- a/trunk/drivers/net/ethernet/xilinx/ll_temac_main.c +++ b/trunk/drivers/net/ethernet/xilinx/ll_temac_main.c @@ -197,7 +197,7 @@ static int temac_dcr_setup(struct temac_local *lp, struct platform_device *op, #endif /** - * temac_dma_bd_release - Release buffer descriptor rings + * * temac_dma_bd_release - Release buffer descriptor rings */ static void temac_dma_bd_release(struct net_device *ndev) { @@ -768,6 +768,7 @@ static void ll_temac_recv(struct net_device *ndev) DMA_FROM_DEVICE); skb_put(skb, length); + skb->dev = ndev; skb->protocol = eth_type_trans(skb, ndev); skb_checksum_none_assert(skb); diff --git a/trunk/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/trunk/drivers/net/ethernet/xilinx/xilinx_axienet_main.c index 0793299bd39e..9c365e192a31 100644 --- a/trunk/drivers/net/ethernet/xilinx/xilinx_axienet_main.c +++ b/trunk/drivers/net/ethernet/xilinx/xilinx_axienet_main.c @@ -312,7 +312,7 @@ static void axienet_set_mac_address(struct net_device *ndev, void *address) if (address) memcpy(ndev->dev_addr, address, ETH_ALEN); if (!is_valid_ether_addr(ndev->dev_addr)) - eth_random_addr(ndev->dev_addr); + random_ether_addr(ndev->dev_addr); /* Set up unicast MAC address filter set its mac address */ axienet_iow(lp, XAE_UAW0_OFFSET, diff --git a/trunk/drivers/net/hyperv/hyperv_net.h b/trunk/drivers/net/hyperv/hyperv_net.h index 95ceb3593043..2857ab078aac 100644 --- a/trunk/drivers/net/hyperv/hyperv_net.h +++ b/trunk/drivers/net/hyperv/hyperv_net.h @@ -131,7 +131,6 @@ int rndis_filter_send(struct hv_device *dev, struct hv_netvsc_packet *pkt); int rndis_filter_set_packet_filter(struct rndis_device *dev, u32 new_filter); -int rndis_filter_set_device_mac(struct hv_device *hdev, char *mac); #define NVSP_INVALID_PROTOCOL_VERSION ((u32)0xFFFFFFFF) diff --git a/trunk/drivers/net/hyperv/netvsc_drv.c b/trunk/drivers/net/hyperv/netvsc_drv.c index 8e23c084c4a7..8f8ed3320425 100644 --- a/trunk/drivers/net/hyperv/netvsc_drv.c +++ b/trunk/drivers/net/hyperv/netvsc_drv.c @@ -341,34 +341,6 @@ static int netvsc_change_mtu(struct net_device *ndev, int mtu) return 0; } - -static int netvsc_set_mac_addr(struct net_device *ndev, void *p) -{ - struct net_device_context *ndevctx = netdev_priv(ndev); - struct hv_device *hdev = ndevctx->device_ctx; - struct sockaddr *addr = p; - char save_adr[14]; - unsigned char save_aatype; - int err; - - memcpy(save_adr, ndev->dev_addr, ETH_ALEN); - save_aatype = ndev->addr_assign_type; - - err = eth_mac_addr(ndev, p); - if (err != 0) - return err; - - err = rndis_filter_set_device_mac(hdev, addr->sa_data); - if (err != 0) { - /* roll back to saved MAC */ - memcpy(ndev->dev_addr, save_adr, ETH_ALEN); - ndev->addr_assign_type = save_aatype; - } - - return err; -} - - static const struct ethtool_ops ethtool_ops = { .get_drvinfo = netvsc_get_drvinfo, .get_link = ethtool_op_get_link, @@ -381,7 +353,7 @@ static const struct net_device_ops device_ops = { .ndo_set_rx_mode = netvsc_set_multicast_list, .ndo_change_mtu = netvsc_change_mtu, .ndo_validate_addr = eth_validate_addr, - .ndo_set_mac_address = netvsc_set_mac_addr, + .ndo_set_mac_address = eth_mac_addr, }; /* diff --git a/trunk/drivers/net/hyperv/rndis_filter.c b/trunk/drivers/net/hyperv/rndis_filter.c index fbf539468205..981ebb115637 100644 --- a/trunk/drivers/net/hyperv/rndis_filter.c +++ b/trunk/drivers/net/hyperv/rndis_filter.c @@ -27,7 +27,6 @@ #include #include #include -#include #include "hyperv_net.h" @@ -48,7 +47,6 @@ struct rndis_request { struct hv_page_buffer buf; /* FIXME: We assumed a fixed size request here. */ struct rndis_message request_msg; - u8 ext[100]; }; static void rndis_filter_send_completion(void *ctx); @@ -513,83 +511,6 @@ static int rndis_filter_query_device_mac(struct rndis_device *dev) dev->hw_mac_adr, &size); } -#define NWADR_STR "NetworkAddress" -#define NWADR_STRLEN 14 - -int rndis_filter_set_device_mac(struct hv_device *hdev, char *mac) -{ - struct netvsc_device *nvdev = hv_get_drvdata(hdev); - struct rndis_device *rdev = nvdev->extension; - struct net_device *ndev = nvdev->ndev; - struct rndis_request *request; - struct rndis_set_request *set; - struct rndis_config_parameter_info *cpi; - wchar_t *cfg_nwadr, *cfg_mac; - struct rndis_set_complete *set_complete; - char macstr[2*ETH_ALEN+1]; - u32 extlen = sizeof(struct rndis_config_parameter_info) + - 2*NWADR_STRLEN + 4*ETH_ALEN; - int ret, t; - - request = get_rndis_request(rdev, RNDIS_MSG_SET, - RNDIS_MESSAGE_SIZE(struct rndis_set_request) + extlen); - if (!request) - return -ENOMEM; - - set = &request->request_msg.msg.set_req; - set->oid = RNDIS_OID_GEN_RNDIS_CONFIG_PARAMETER; - set->info_buflen = extlen; - set->info_buf_offset = sizeof(struct rndis_set_request); - set->dev_vc_handle = 0; - - cpi = (struct rndis_config_parameter_info *)((ulong)set + - set->info_buf_offset); - cpi->parameter_name_offset = - sizeof(struct rndis_config_parameter_info); - /* Multiply by 2 because host needs 2 bytes (utf16) for each char */ - cpi->parameter_name_length = 2*NWADR_STRLEN; - cpi->parameter_type = RNDIS_CONFIG_PARAM_TYPE_STRING; - cpi->parameter_value_offset = - cpi->parameter_name_offset + cpi->parameter_name_length; - /* Multiply by 4 because each MAC byte displayed as 2 utf16 chars */ - cpi->parameter_value_length = 4*ETH_ALEN; - - cfg_nwadr = (wchar_t *)((ulong)cpi + cpi->parameter_name_offset); - cfg_mac = (wchar_t *)((ulong)cpi + cpi->parameter_value_offset); - ret = utf8s_to_utf16s(NWADR_STR, NWADR_STRLEN, UTF16_HOST_ENDIAN, - cfg_nwadr, NWADR_STRLEN); - if (ret < 0) - goto cleanup; - snprintf(macstr, 2*ETH_ALEN+1, "%pm", mac); - ret = utf8s_to_utf16s(macstr, 2*ETH_ALEN, UTF16_HOST_ENDIAN, - cfg_mac, 2*ETH_ALEN); - if (ret < 0) - goto cleanup; - - ret = rndis_filter_send_request(rdev, request); - if (ret != 0) - goto cleanup; - - t = wait_for_completion_timeout(&request->wait_event, 5*HZ); - if (t == 0) { - netdev_err(ndev, "timeout before we got a set response...\n"); - /* - * can't put_rndis_request, since we may still receive a - * send-completion. - */ - return -EBUSY; - } else { - set_complete = &request->response_msg.msg.set_complete; - if (set_complete->status != RNDIS_STATUS_SUCCESS) - ret = -EINVAL; - } - -cleanup: - put_rndis_request(rdev, request); - return ret; -} - - static int rndis_filter_query_device_link_status(struct rndis_device *dev) { u32 size = sizeof(u32); diff --git a/trunk/drivers/net/phy/amd.c b/trunk/drivers/net/phy/amd.c index a3fb5ceb6487..cfabd5fe5372 100644 --- a/trunk/drivers/net/phy/amd.c +++ b/trunk/drivers/net/phy/amd.c @@ -77,7 +77,13 @@ static struct phy_driver am79c_driver = { static int __init am79c_init(void) { - return phy_driver_register(&am79c_driver); + int ret; + + ret = phy_driver_register(&am79c_driver); + if (ret) + return ret; + + return 0; } static void __exit am79c_exit(void) diff --git a/trunk/drivers/net/phy/bcm63xx.c b/trunk/drivers/net/phy/bcm63xx.c index 84c7a39b1c65..cd802eb25fd2 100644 --- a/trunk/drivers/net/phy/bcm63xx.c +++ b/trunk/drivers/net/phy/bcm63xx.c @@ -71,8 +71,7 @@ static int bcm63xx_config_intr(struct phy_device *phydev) return err; } -static struct phy_driver bcm63xx_driver[] = { -{ +static struct phy_driver bcm63xx_1_driver = { .phy_id = 0x00406000, .phy_id_mask = 0xfffffc00, .name = "Broadcom BCM63XX (1)", @@ -85,8 +84,10 @@ static struct phy_driver bcm63xx_driver[] = { .ack_interrupt = bcm63xx_ack_interrupt, .config_intr = bcm63xx_config_intr, .driver = { .owner = THIS_MODULE }, -}, { - /* same phy as above, with just a different OUI */ +}; + +/* same phy as above, with just a different OUI */ +static struct phy_driver bcm63xx_2_driver = { .phy_id = 0x002bdc00, .phy_id_mask = 0xfffffc00, .name = "Broadcom BCM63XX (2)", @@ -98,18 +99,30 @@ static struct phy_driver bcm63xx_driver[] = { .ack_interrupt = bcm63xx_ack_interrupt, .config_intr = bcm63xx_config_intr, .driver = { .owner = THIS_MODULE }, -} }; +}; static int __init bcm63xx_phy_init(void) { - return phy_drivers_register(bcm63xx_driver, - ARRAY_SIZE(bcm63xx_driver)); + int ret; + + ret = phy_driver_register(&bcm63xx_1_driver); + if (ret) + goto out_63xx_1; + ret = phy_driver_register(&bcm63xx_2_driver); + if (ret) + goto out_63xx_2; + return ret; + +out_63xx_2: + phy_driver_unregister(&bcm63xx_1_driver); +out_63xx_1: + return ret; } static void __exit bcm63xx_phy_exit(void) { - phy_drivers_unregister(bcm63xx_driver, - ARRAY_SIZE(bcm63xx_driver)); + phy_driver_unregister(&bcm63xx_1_driver); + phy_driver_unregister(&bcm63xx_2_driver); } module_init(bcm63xx_phy_init); diff --git a/trunk/drivers/net/phy/bcm87xx.c b/trunk/drivers/net/phy/bcm87xx.c index 2346b38b9837..f5f0562934db 100644 --- a/trunk/drivers/net/phy/bcm87xx.c +++ b/trunk/drivers/net/phy/bcm87xx.c @@ -22,7 +22,7 @@ #if IS_ENABLED(CONFIG_OF_MDIO) /* Set and/or override some configuration registers based on the - * broadcom,c45-reg-init property stored in the of_node for the phydev. + * marvell,reg-init property stored in the of_node for the phydev. * * broadcom,c45-reg-init = ,...; * @@ -89,7 +89,6 @@ static int bcm87xx_config_init(struct phy_device *phydev) phydev->supported = SUPPORTED_10000baseR_FEC; phydev->advertising = ADVERTISED_10000baseR_FEC; phydev->state = PHY_NOLINK; - phydev->autoneg = AUTONEG_DISABLE; bcm87xx_of_reg_init(phydev); @@ -187,8 +186,7 @@ static int bcm8727_match_phy_device(struct phy_device *phydev) return phydev->c45_ids.device_ids[4] == PHY_ID_BCM8727; } -static struct phy_driver bcm87xx_driver[] = { -{ +static struct phy_driver bcm8706_driver = { .phy_id = PHY_ID_BCM8706, .phy_id_mask = 0xffffffff, .name = "Broadcom BCM8706", @@ -201,7 +199,9 @@ static struct phy_driver bcm87xx_driver[] = { .did_interrupt = bcm87xx_did_interrupt, .match_phy_device = bcm8706_match_phy_device, .driver = { .owner = THIS_MODULE }, -}, { +}; + +static struct phy_driver bcm8727_driver = { .phy_id = PHY_ID_BCM8727, .phy_id_mask = 0xffffffff, .name = "Broadcom BCM8727", @@ -214,18 +214,25 @@ static struct phy_driver bcm87xx_driver[] = { .did_interrupt = bcm87xx_did_interrupt, .match_phy_device = bcm8727_match_phy_device, .driver = { .owner = THIS_MODULE }, -} }; +}; static int __init bcm87xx_init(void) { - return phy_drivers_register(bcm87xx_driver, - ARRAY_SIZE(bcm87xx_driver)); + int ret; + + ret = phy_driver_register(&bcm8706_driver); + if (ret) + goto err; + + ret = phy_driver_register(&bcm8727_driver); +err: + return ret; } module_init(bcm87xx_init); static void __exit bcm87xx_exit(void) { - phy_drivers_unregister(bcm87xx_driver, - ARRAY_SIZE(bcm87xx_driver)); + phy_driver_unregister(&bcm8706_driver); + phy_driver_unregister(&bcm8727_driver); } module_exit(bcm87xx_exit); diff --git a/trunk/drivers/net/phy/broadcom.c b/trunk/drivers/net/phy/broadcom.c index f8c90ea75108..60338ff63092 100644 --- a/trunk/drivers/net/phy/broadcom.c +++ b/trunk/drivers/net/phy/broadcom.c @@ -682,8 +682,7 @@ static int brcm_fet_config_intr(struct phy_device *phydev) return err; } -static struct phy_driver broadcom_drivers[] = { -{ +static struct phy_driver bcm5411_driver = { .phy_id = PHY_ID_BCM5411, .phy_id_mask = 0xfffffff0, .name = "Broadcom BCM5411", @@ -696,7 +695,9 @@ static struct phy_driver broadcom_drivers[] = { .ack_interrupt = bcm54xx_ack_interrupt, .config_intr = bcm54xx_config_intr, .driver = { .owner = THIS_MODULE }, -}, { +}; + +static struct phy_driver bcm5421_driver = { .phy_id = PHY_ID_BCM5421, .phy_id_mask = 0xfffffff0, .name = "Broadcom BCM5421", @@ -709,7 +710,9 @@ static struct phy_driver broadcom_drivers[] = { .ack_interrupt = bcm54xx_ack_interrupt, .config_intr = bcm54xx_config_intr, .driver = { .owner = THIS_MODULE }, -}, { +}; + +static struct phy_driver bcm5461_driver = { .phy_id = PHY_ID_BCM5461, .phy_id_mask = 0xfffffff0, .name = "Broadcom BCM5461", @@ -722,7 +725,9 @@ static struct phy_driver broadcom_drivers[] = { .ack_interrupt = bcm54xx_ack_interrupt, .config_intr = bcm54xx_config_intr, .driver = { .owner = THIS_MODULE }, -}, { +}; + +static struct phy_driver bcm5464_driver = { .phy_id = PHY_ID_BCM5464, .phy_id_mask = 0xfffffff0, .name = "Broadcom BCM5464", @@ -735,7 +740,9 @@ static struct phy_driver broadcom_drivers[] = { .ack_interrupt = bcm54xx_ack_interrupt, .config_intr = bcm54xx_config_intr, .driver = { .owner = THIS_MODULE }, -}, { +}; + +static struct phy_driver bcm5481_driver = { .phy_id = PHY_ID_BCM5481, .phy_id_mask = 0xfffffff0, .name = "Broadcom BCM5481", @@ -748,7 +755,9 @@ static struct phy_driver broadcom_drivers[] = { .ack_interrupt = bcm54xx_ack_interrupt, .config_intr = bcm54xx_config_intr, .driver = { .owner = THIS_MODULE }, -}, { +}; + +static struct phy_driver bcm5482_driver = { .phy_id = PHY_ID_BCM5482, .phy_id_mask = 0xfffffff0, .name = "Broadcom BCM5482", @@ -761,7 +770,9 @@ static struct phy_driver broadcom_drivers[] = { .ack_interrupt = bcm54xx_ack_interrupt, .config_intr = bcm54xx_config_intr, .driver = { .owner = THIS_MODULE }, -}, { +}; + +static struct phy_driver bcm50610_driver = { .phy_id = PHY_ID_BCM50610, .phy_id_mask = 0xfffffff0, .name = "Broadcom BCM50610", @@ -774,7 +785,9 @@ static struct phy_driver broadcom_drivers[] = { .ack_interrupt = bcm54xx_ack_interrupt, .config_intr = bcm54xx_config_intr, .driver = { .owner = THIS_MODULE }, -}, { +}; + +static struct phy_driver bcm50610m_driver = { .phy_id = PHY_ID_BCM50610M, .phy_id_mask = 0xfffffff0, .name = "Broadcom BCM50610M", @@ -787,7 +800,9 @@ static struct phy_driver broadcom_drivers[] = { .ack_interrupt = bcm54xx_ack_interrupt, .config_intr = bcm54xx_config_intr, .driver = { .owner = THIS_MODULE }, -}, { +}; + +static struct phy_driver bcm57780_driver = { .phy_id = PHY_ID_BCM57780, .phy_id_mask = 0xfffffff0, .name = "Broadcom BCM57780", @@ -800,7 +815,9 @@ static struct phy_driver broadcom_drivers[] = { .ack_interrupt = bcm54xx_ack_interrupt, .config_intr = bcm54xx_config_intr, .driver = { .owner = THIS_MODULE }, -}, { +}; + +static struct phy_driver bcmac131_driver = { .phy_id = PHY_ID_BCMAC131, .phy_id_mask = 0xfffffff0, .name = "Broadcom BCMAC131", @@ -813,7 +830,9 @@ static struct phy_driver broadcom_drivers[] = { .ack_interrupt = brcm_fet_ack_interrupt, .config_intr = brcm_fet_config_intr, .driver = { .owner = THIS_MODULE }, -}, { +}; + +static struct phy_driver bcm5241_driver = { .phy_id = PHY_ID_BCM5241, .phy_id_mask = 0xfffffff0, .name = "Broadcom BCM5241", @@ -826,18 +845,84 @@ static struct phy_driver broadcom_drivers[] = { .ack_interrupt = brcm_fet_ack_interrupt, .config_intr = brcm_fet_config_intr, .driver = { .owner = THIS_MODULE }, -} }; +}; static int __init broadcom_init(void) { - return phy_drivers_register(broadcom_drivers, - ARRAY_SIZE(broadcom_drivers)); + int ret; + + ret = phy_driver_register(&bcm5411_driver); + if (ret) + goto out_5411; + ret = phy_driver_register(&bcm5421_driver); + if (ret) + goto out_5421; + ret = phy_driver_register(&bcm5461_driver); + if (ret) + goto out_5461; + ret = phy_driver_register(&bcm5464_driver); + if (ret) + goto out_5464; + ret = phy_driver_register(&bcm5481_driver); + if (ret) + goto out_5481; + ret = phy_driver_register(&bcm5482_driver); + if (ret) + goto out_5482; + ret = phy_driver_register(&bcm50610_driver); + if (ret) + goto out_50610; + ret = phy_driver_register(&bcm50610m_driver); + if (ret) + goto out_50610m; + ret = phy_driver_register(&bcm57780_driver); + if (ret) + goto out_57780; + ret = phy_driver_register(&bcmac131_driver); + if (ret) + goto out_ac131; + ret = phy_driver_register(&bcm5241_driver); + if (ret) + goto out_5241; + return ret; + +out_5241: + phy_driver_unregister(&bcmac131_driver); +out_ac131: + phy_driver_unregister(&bcm57780_driver); +out_57780: + phy_driver_unregister(&bcm50610m_driver); +out_50610m: + phy_driver_unregister(&bcm50610_driver); +out_50610: + phy_driver_unregister(&bcm5482_driver); +out_5482: + phy_driver_unregister(&bcm5481_driver); +out_5481: + phy_driver_unregister(&bcm5464_driver); +out_5464: + phy_driver_unregister(&bcm5461_driver); +out_5461: + phy_driver_unregister(&bcm5421_driver); +out_5421: + phy_driver_unregister(&bcm5411_driver); +out_5411: + return ret; } static void __exit broadcom_exit(void) { - phy_drivers_unregister(broadcom_drivers, - ARRAY_SIZE(broadcom_drivers)); + phy_driver_unregister(&bcm5241_driver); + phy_driver_unregister(&bcmac131_driver); + phy_driver_unregister(&bcm57780_driver); + phy_driver_unregister(&bcm50610m_driver); + phy_driver_unregister(&bcm50610_driver); + phy_driver_unregister(&bcm5482_driver); + phy_driver_unregister(&bcm5481_driver); + phy_driver_unregister(&bcm5464_driver); + phy_driver_unregister(&bcm5461_driver); + phy_driver_unregister(&bcm5421_driver); + phy_driver_unregister(&bcm5411_driver); } module_init(broadcom_init); diff --git a/trunk/drivers/net/phy/cicada.c b/trunk/drivers/net/phy/cicada.c index db472ffb6e89..d28173161c21 100644 --- a/trunk/drivers/net/phy/cicada.c +++ b/trunk/drivers/net/phy/cicada.c @@ -102,8 +102,7 @@ static int cis820x_config_intr(struct phy_device *phydev) } /* Cicada 8201, a.k.a Vitesse VSC8201 */ -static struct phy_driver cis820x_driver[] = { -{ +static struct phy_driver cis8201_driver = { .phy_id = 0x000fc410, .name = "Cicada Cis8201", .phy_id_mask = 0x000ffff0, @@ -114,8 +113,11 @@ static struct phy_driver cis820x_driver[] = { .read_status = &genphy_read_status, .ack_interrupt = &cis820x_ack_interrupt, .config_intr = &cis820x_config_intr, - .driver = { .owner = THIS_MODULE,}, -}, { + .driver = { .owner = THIS_MODULE,}, +}; + +/* Cicada 8204 */ +static struct phy_driver cis8204_driver = { .phy_id = 0x000fc440, .name = "Cicada Cis8204", .phy_id_mask = 0x000fffc0, @@ -126,19 +128,32 @@ static struct phy_driver cis820x_driver[] = { .read_status = &genphy_read_status, .ack_interrupt = &cis820x_ack_interrupt, .config_intr = &cis820x_config_intr, - .driver = { .owner = THIS_MODULE,}, -} }; + .driver = { .owner = THIS_MODULE,}, +}; static int __init cicada_init(void) { - return phy_drivers_register(cis820x_driver, - ARRAY_SIZE(cis820x_driver)); + int ret; + + ret = phy_driver_register(&cis8204_driver); + if (ret) + goto err1; + + ret = phy_driver_register(&cis8201_driver); + if (ret) + goto err2; + return 0; + +err2: + phy_driver_unregister(&cis8204_driver); +err1: + return ret; } static void __exit cicada_exit(void) { - phy_drivers_unregister(cis820x_driver, - ARRAY_SIZE(cis820x_driver)); + phy_driver_unregister(&cis8204_driver); + phy_driver_unregister(&cis8201_driver); } module_init(cicada_init); diff --git a/trunk/drivers/net/phy/davicom.c b/trunk/drivers/net/phy/davicom.c index 81c7bc010dd8..5f59cc064778 100644 --- a/trunk/drivers/net/phy/davicom.c +++ b/trunk/drivers/net/phy/davicom.c @@ -144,8 +144,7 @@ static int dm9161_ack_interrupt(struct phy_device *phydev) return (err < 0) ? err : 0; } -static struct phy_driver dm91xx_driver[] = { -{ +static struct phy_driver dm9161e_driver = { .phy_id = 0x0181b880, .name = "Davicom DM9161E", .phy_id_mask = 0x0ffffff0, @@ -154,7 +153,9 @@ static struct phy_driver dm91xx_driver[] = { .config_aneg = dm9161_config_aneg, .read_status = genphy_read_status, .driver = { .owner = THIS_MODULE,}, -}, { +}; + +static struct phy_driver dm9161a_driver = { .phy_id = 0x0181b8a0, .name = "Davicom DM9161A", .phy_id_mask = 0x0ffffff0, @@ -163,7 +164,9 @@ static struct phy_driver dm91xx_driver[] = { .config_aneg = dm9161_config_aneg, .read_status = genphy_read_status, .driver = { .owner = THIS_MODULE,}, -}, { +}; + +static struct phy_driver dm9131_driver = { .phy_id = 0x00181b80, .name = "Davicom DM9131", .phy_id_mask = 0x0ffffff0, @@ -174,18 +177,38 @@ static struct phy_driver dm91xx_driver[] = { .ack_interrupt = dm9161_ack_interrupt, .config_intr = dm9161_config_intr, .driver = { .owner = THIS_MODULE,}, -} }; +}; static int __init davicom_init(void) { - return phy_drivers_register(dm91xx_driver, - ARRAY_SIZE(dm91xx_driver)); + int ret; + + ret = phy_driver_register(&dm9161e_driver); + if (ret) + goto err1; + + ret = phy_driver_register(&dm9161a_driver); + if (ret) + goto err2; + + ret = phy_driver_register(&dm9131_driver); + if (ret) + goto err3; + return 0; + + err3: + phy_driver_unregister(&dm9161a_driver); + err2: + phy_driver_unregister(&dm9161e_driver); + err1: + return ret; } static void __exit davicom_exit(void) { - phy_drivers_unregister(dm91xx_driver, - ARRAY_SIZE(dm91xx_driver)); + phy_driver_unregister(&dm9161e_driver); + phy_driver_unregister(&dm9161a_driver); + phy_driver_unregister(&dm9131_driver); } module_init(davicom_init); diff --git a/trunk/drivers/net/phy/icplus.c b/trunk/drivers/net/phy/icplus.c index d5199cb4caec..47f8e8939266 100644 --- a/trunk/drivers/net/phy/icplus.c +++ b/trunk/drivers/net/phy/icplus.c @@ -202,8 +202,7 @@ static int ip101a_g_ack_interrupt(struct phy_device *phydev) return 0; } -static struct phy_driver icplus_driver[] = { -{ +static struct phy_driver ip175c_driver = { .phy_id = 0x02430d80, .name = "ICPlus IP175C", .phy_id_mask = 0x0ffffff0, @@ -214,7 +213,9 @@ static struct phy_driver icplus_driver[] = { .suspend = genphy_suspend, .resume = genphy_resume, .driver = { .owner = THIS_MODULE,}, -}, { +}; + +static struct phy_driver ip1001_driver = { .phy_id = 0x02430d90, .name = "ICPlus IP1001", .phy_id_mask = 0x0ffffff0, @@ -226,7 +227,9 @@ static struct phy_driver icplus_driver[] = { .suspend = genphy_suspend, .resume = genphy_resume, .driver = { .owner = THIS_MODULE,}, -}, { +}; + +static struct phy_driver ip101a_g_driver = { .phy_id = 0x02430c54, .name = "ICPlus IP101A/G", .phy_id_mask = 0x0ffffff0, @@ -240,18 +243,28 @@ static struct phy_driver icplus_driver[] = { .suspend = genphy_suspend, .resume = genphy_resume, .driver = { .owner = THIS_MODULE,}, -} }; +}; static int __init icplus_init(void) { - return phy_drivers_register(icplus_driver, - ARRAY_SIZE(icplus_driver)); + int ret = 0; + + ret = phy_driver_register(&ip1001_driver); + if (ret < 0) + return -ENODEV; + + ret = phy_driver_register(&ip101a_g_driver); + if (ret < 0) + return -ENODEV; + + return phy_driver_register(&ip175c_driver); } static void __exit icplus_exit(void) { - phy_drivers_unregister(icplus_driver, - ARRAY_SIZE(icplus_driver)); + phy_driver_unregister(&ip1001_driver); + phy_driver_unregister(&ip101a_g_driver); + phy_driver_unregister(&ip175c_driver); } module_init(icplus_init); diff --git a/trunk/drivers/net/phy/lxt.c b/trunk/drivers/net/phy/lxt.c index 6d1e3fcc43e2..6f6e8b616a62 100644 --- a/trunk/drivers/net/phy/lxt.c +++ b/trunk/drivers/net/phy/lxt.c @@ -149,8 +149,7 @@ static int lxt973_config_aneg(struct phy_device *phydev) return phydev->priv ? 0 : genphy_config_aneg(phydev); } -static struct phy_driver lxt97x_driver[] = { -{ +static struct phy_driver lxt970_driver = { .phy_id = 0x78100000, .name = "LXT970", .phy_id_mask = 0xfffffff0, @@ -161,8 +160,10 @@ static struct phy_driver lxt97x_driver[] = { .read_status = genphy_read_status, .ack_interrupt = lxt970_ack_interrupt, .config_intr = lxt970_config_intr, - .driver = { .owner = THIS_MODULE,}, -}, { + .driver = { .owner = THIS_MODULE,}, +}; + +static struct phy_driver lxt971_driver = { .phy_id = 0x001378e0, .name = "LXT971", .phy_id_mask = 0xfffffff0, @@ -172,8 +173,10 @@ static struct phy_driver lxt97x_driver[] = { .read_status = genphy_read_status, .ack_interrupt = lxt971_ack_interrupt, .config_intr = lxt971_config_intr, - .driver = { .owner = THIS_MODULE,}, -}, { + .driver = { .owner = THIS_MODULE,}, +}; + +static struct phy_driver lxt973_driver = { .phy_id = 0x00137a10, .name = "LXT973", .phy_id_mask = 0xfffffff0, @@ -182,19 +185,39 @@ static struct phy_driver lxt97x_driver[] = { .probe = lxt973_probe, .config_aneg = lxt973_config_aneg, .read_status = genphy_read_status, - .driver = { .owner = THIS_MODULE,}, -} }; + .driver = { .owner = THIS_MODULE,}, +}; static int __init lxt_init(void) { - return phy_drivers_register(lxt97x_driver, - ARRAY_SIZE(lxt97x_driver)); + int ret; + + ret = phy_driver_register(&lxt970_driver); + if (ret) + goto err1; + + ret = phy_driver_register(&lxt971_driver); + if (ret) + goto err2; + + ret = phy_driver_register(&lxt973_driver); + if (ret) + goto err3; + return 0; + + err3: + phy_driver_unregister(&lxt971_driver); + err2: + phy_driver_unregister(&lxt970_driver); + err1: + return ret; } static void __exit lxt_exit(void) { - phy_drivers_unregister(lxt97x_driver, - ARRAY_SIZE(lxt97x_driver)); + phy_driver_unregister(&lxt970_driver); + phy_driver_unregister(&lxt971_driver); + phy_driver_unregister(&lxt973_driver); } module_init(lxt_init); diff --git a/trunk/drivers/net/phy/marvell.c b/trunk/drivers/net/phy/marvell.c index 5d2a3f215887..418928d644bf 100644 --- a/trunk/drivers/net/phy/marvell.c +++ b/trunk/drivers/net/phy/marvell.c @@ -826,14 +826,28 @@ static struct phy_driver marvell_drivers[] = { static int __init marvell_init(void) { - return phy_drivers_register(marvell_drivers, - ARRAY_SIZE(marvell_drivers)); + int ret; + int i; + + for (i = 0; i < ARRAY_SIZE(marvell_drivers); i++) { + ret = phy_driver_register(&marvell_drivers[i]); + + if (ret) { + while (i-- > 0) + phy_driver_unregister(&marvell_drivers[i]); + return ret; + } + } + + return 0; } static void __exit marvell_exit(void) { - phy_drivers_unregister(marvell_drivers, - ARRAY_SIZE(marvell_drivers)); + int i; + + for (i = 0; i < ARRAY_SIZE(marvell_drivers); i++) + phy_driver_unregister(&marvell_drivers[i]); } module_init(marvell_init); diff --git a/trunk/drivers/net/phy/mdio-mux.c b/trunk/drivers/net/phy/mdio-mux.c index 5c120189ec86..39ea0674dcde 100644 --- a/trunk/drivers/net/phy/mdio-mux.c +++ b/trunk/drivers/net/phy/mdio-mux.c @@ -46,13 +46,7 @@ static int mdio_mux_read(struct mii_bus *bus, int phy_id, int regnum) struct mdio_mux_parent_bus *pb = cb->parent; int r; - /* In theory multiple mdio_mux could be stacked, thus creating - * more than a single level of nesting. But in practice, - * SINGLE_DEPTH_NESTING will cover the vast majority of use - * cases. We use it, instead of trying to handle the general - * case. - */ - mutex_lock_nested(&pb->mii_bus->mdio_lock, SINGLE_DEPTH_NESTING); + mutex_lock(&pb->mii_bus->mdio_lock); r = pb->switch_fn(pb->current_child, cb->bus_number, pb->switch_data); if (r) goto out; @@ -77,7 +71,7 @@ static int mdio_mux_write(struct mii_bus *bus, int phy_id, int r; - mutex_lock_nested(&pb->mii_bus->mdio_lock, SINGLE_DEPTH_NESTING); + mutex_lock(&pb->mii_bus->mdio_lock); r = pb->switch_fn(pb->current_child, cb->bus_number, pb->switch_data); if (r) goto out; diff --git a/trunk/drivers/net/phy/micrel.c b/trunk/drivers/net/phy/micrel.c index cf287e0eb408..9d6c80c8a0cf 100644 --- a/trunk/drivers/net/phy/micrel.c +++ b/trunk/drivers/net/phy/micrel.c @@ -114,8 +114,7 @@ static int ks8051_config_init(struct phy_device *phydev) return 0; } -static struct phy_driver ksphy_driver[] = { -{ +static struct phy_driver ks8737_driver = { .phy_id = PHY_ID_KS8737, .phy_id_mask = 0x00fffff0, .name = "Micrel KS8737", @@ -127,7 +126,9 @@ static struct phy_driver ksphy_driver[] = { .ack_interrupt = kszphy_ack_interrupt, .config_intr = ks8737_config_intr, .driver = { .owner = THIS_MODULE,}, -}, { +}; + +static struct phy_driver ks8041_driver = { .phy_id = PHY_ID_KS8041, .phy_id_mask = 0x00fffff0, .name = "Micrel KS8041", @@ -140,7 +141,9 @@ static struct phy_driver ksphy_driver[] = { .ack_interrupt = kszphy_ack_interrupt, .config_intr = kszphy_config_intr, .driver = { .owner = THIS_MODULE,}, -}, { +}; + +static struct phy_driver ks8051_driver = { .phy_id = PHY_ID_KS8051, .phy_id_mask = 0x00fffff0, .name = "Micrel KS8051", @@ -153,7 +156,9 @@ static struct phy_driver ksphy_driver[] = { .ack_interrupt = kszphy_ack_interrupt, .config_intr = kszphy_config_intr, .driver = { .owner = THIS_MODULE,}, -}, { +}; + +static struct phy_driver ks8001_driver = { .phy_id = PHY_ID_KS8001, .name = "Micrel KS8001 or KS8721", .phy_id_mask = 0x00ffffff, @@ -165,7 +170,9 @@ static struct phy_driver ksphy_driver[] = { .ack_interrupt = kszphy_ack_interrupt, .config_intr = kszphy_config_intr, .driver = { .owner = THIS_MODULE,}, -}, { +}; + +static struct phy_driver ksz9021_driver = { .phy_id = PHY_ID_KSZ9021, .phy_id_mask = 0x000ffffe, .name = "Micrel KSZ9021 Gigabit PHY", @@ -178,18 +185,51 @@ static struct phy_driver ksphy_driver[] = { .ack_interrupt = kszphy_ack_interrupt, .config_intr = ksz9021_config_intr, .driver = { .owner = THIS_MODULE, }, -} }; +}; static int __init ksphy_init(void) { - return phy_drivers_register(ksphy_driver, - ARRAY_SIZE(ksphy_driver)); + int ret; + + ret = phy_driver_register(&ks8001_driver); + if (ret) + goto err1; + + ret = phy_driver_register(&ksz9021_driver); + if (ret) + goto err2; + + ret = phy_driver_register(&ks8737_driver); + if (ret) + goto err3; + ret = phy_driver_register(&ks8041_driver); + if (ret) + goto err4; + ret = phy_driver_register(&ks8051_driver); + if (ret) + goto err5; + + return 0; + +err5: + phy_driver_unregister(&ks8041_driver); +err4: + phy_driver_unregister(&ks8737_driver); +err3: + phy_driver_unregister(&ksz9021_driver); +err2: + phy_driver_unregister(&ks8001_driver); +err1: + return ret; } static void __exit ksphy_exit(void) { - phy_drivers_unregister(ksphy_driver, - ARRAY_SIZE(ksphy_driver)); + phy_driver_unregister(&ks8001_driver); + phy_driver_unregister(&ks8737_driver); + phy_driver_unregister(&ksz9021_driver); + phy_driver_unregister(&ks8041_driver); + phy_driver_unregister(&ks8051_driver); } module_init(ksphy_init); diff --git a/trunk/drivers/net/phy/phy_device.c b/trunk/drivers/net/phy/phy_device.c index 8af46e88a181..47e02e7dc737 100644 --- a/trunk/drivers/net/phy/phy_device.c +++ b/trunk/drivers/net/phy/phy_device.c @@ -1079,37 +1079,12 @@ int phy_driver_register(struct phy_driver *new_driver) } EXPORT_SYMBOL(phy_driver_register); -int phy_drivers_register(struct phy_driver *new_driver, int n) -{ - int i, ret = 0; - - for (i = 0; i < n; i++) { - ret = phy_driver_register(new_driver + i); - if (ret) { - while (i-- > 0) - phy_driver_unregister(new_driver + i); - break; - } - } - return ret; -} -EXPORT_SYMBOL(phy_drivers_register); - void phy_driver_unregister(struct phy_driver *drv) { driver_unregister(&drv->driver); } EXPORT_SYMBOL(phy_driver_unregister); -void phy_drivers_unregister(struct phy_driver *drv, int n) -{ - int i; - for (i = 0; i < n; i++) { - phy_driver_unregister(drv + i); - } -} -EXPORT_SYMBOL(phy_drivers_unregister); - static struct phy_driver genphy_driver = { .phy_id = 0xffffffff, .phy_id_mask = 0xffffffff, diff --git a/trunk/drivers/net/phy/realtek.c b/trunk/drivers/net/phy/realtek.c index 72f93470ea35..f414ffb5b728 100644 --- a/trunk/drivers/net/phy/realtek.c +++ b/trunk/drivers/net/phy/realtek.c @@ -65,7 +65,11 @@ static struct phy_driver rtl821x_driver = { static int __init realtek_init(void) { - return phy_driver_register(&rtl821x_driver); + int ret; + + ret = phy_driver_register(&rtl821x_driver); + + return ret; } static void __exit realtek_exit(void) diff --git a/trunk/drivers/net/phy/smsc.c b/trunk/drivers/net/phy/smsc.c index c6b06d311fee..fc3e7e96c88c 100644 --- a/trunk/drivers/net/phy/smsc.c +++ b/trunk/drivers/net/phy/smsc.c @@ -61,8 +61,7 @@ static int lan911x_config_init(struct phy_device *phydev) return smsc_phy_ack_interrupt(phydev); } -static struct phy_driver smsc_phy_driver[] = { -{ +static struct phy_driver lan83c185_driver = { .phy_id = 0x0007c0a0, /* OUI=0x00800f, Model#=0x0a */ .phy_id_mask = 0xfffffff0, .name = "SMSC LAN83C185", @@ -84,7 +83,9 @@ static struct phy_driver smsc_phy_driver[] = { .resume = genphy_resume, .driver = { .owner = THIS_MODULE, } -}, { +}; + +static struct phy_driver lan8187_driver = { .phy_id = 0x0007c0b0, /* OUI=0x00800f, Model#=0x0b */ .phy_id_mask = 0xfffffff0, .name = "SMSC LAN8187", @@ -106,7 +107,9 @@ static struct phy_driver smsc_phy_driver[] = { .resume = genphy_resume, .driver = { .owner = THIS_MODULE, } -}, { +}; + +static struct phy_driver lan8700_driver = { .phy_id = 0x0007c0c0, /* OUI=0x00800f, Model#=0x0c */ .phy_id_mask = 0xfffffff0, .name = "SMSC LAN8700", @@ -128,7 +131,9 @@ static struct phy_driver smsc_phy_driver[] = { .resume = genphy_resume, .driver = { .owner = THIS_MODULE, } -}, { +}; + +static struct phy_driver lan911x_int_driver = { .phy_id = 0x0007c0d0, /* OUI=0x00800f, Model#=0x0d */ .phy_id_mask = 0xfffffff0, .name = "SMSC LAN911x Internal PHY", @@ -150,7 +155,9 @@ static struct phy_driver smsc_phy_driver[] = { .resume = genphy_resume, .driver = { .owner = THIS_MODULE, } -}, { +}; + +static struct phy_driver lan8710_driver = { .phy_id = 0x0007c0f0, /* OUI=0x00800f, Model#=0x0f */ .phy_id_mask = 0xfffffff0, .name = "SMSC LAN8710/LAN8720", @@ -172,18 +179,53 @@ static struct phy_driver smsc_phy_driver[] = { .resume = genphy_resume, .driver = { .owner = THIS_MODULE, } -} }; +}; static int __init smsc_init(void) { - return phy_drivers_register(smsc_phy_driver, - ARRAY_SIZE(smsc_phy_driver)); + int ret; + + ret = phy_driver_register (&lan83c185_driver); + if (ret) + goto err1; + + ret = phy_driver_register (&lan8187_driver); + if (ret) + goto err2; + + ret = phy_driver_register (&lan8700_driver); + if (ret) + goto err3; + + ret = phy_driver_register (&lan911x_int_driver); + if (ret) + goto err4; + + ret = phy_driver_register (&lan8710_driver); + if (ret) + goto err5; + + return 0; + +err5: + phy_driver_unregister (&lan911x_int_driver); +err4: + phy_driver_unregister (&lan8700_driver); +err3: + phy_driver_unregister (&lan8187_driver); +err2: + phy_driver_unregister (&lan83c185_driver); +err1: + return ret; } static void __exit smsc_exit(void) { - return phy_drivers_unregister(smsc_phy_driver, - ARRAY_SIZE(smsc_phy_driver)); + phy_driver_unregister (&lan8710_driver); + phy_driver_unregister (&lan911x_int_driver); + phy_driver_unregister (&lan8700_driver); + phy_driver_unregister (&lan8187_driver); + phy_driver_unregister (&lan83c185_driver); } MODULE_DESCRIPTION("SMSC PHY driver"); diff --git a/trunk/drivers/net/phy/ste10Xp.c b/trunk/drivers/net/phy/ste10Xp.c index 5e1eb138916f..187a2fa814f2 100644 --- a/trunk/drivers/net/phy/ste10Xp.c +++ b/trunk/drivers/net/phy/ste10Xp.c @@ -81,8 +81,7 @@ static int ste10Xp_ack_interrupt(struct phy_device *phydev) return 0; } -static struct phy_driver ste10xp_pdriver[] = { -{ +static struct phy_driver ste101p_pdriver = { .phy_id = STE101P_PHY_ID, .phy_id_mask = 0xfffffff0, .name = "STe101p", @@ -96,7 +95,9 @@ static struct phy_driver ste10xp_pdriver[] = { .suspend = genphy_suspend, .resume = genphy_resume, .driver = {.owner = THIS_MODULE,} -}, { +}; + +static struct phy_driver ste100p_pdriver = { .phy_id = STE100P_PHY_ID, .phy_id_mask = 0xffffffff, .name = "STe100p", @@ -110,18 +111,22 @@ static struct phy_driver ste10xp_pdriver[] = { .suspend = genphy_suspend, .resume = genphy_resume, .driver = {.owner = THIS_MODULE,} -} }; +}; static int __init ste10Xp_init(void) { - return phy_drivers_register(ste10xp_pdriver, - ARRAY_SIZE(ste10xp_pdriver)); + int retval; + + retval = phy_driver_register(&ste100p_pdriver); + if (retval < 0) + return retval; + return phy_driver_register(&ste101p_pdriver); } static void __exit ste10Xp_exit(void) { - phy_drivers_unregister(ste10xp_pdriver, - ARRAY_SIZE(ste10xp_pdriver)); + phy_driver_unregister(&ste100p_pdriver); + phy_driver_unregister(&ste101p_pdriver); } module_init(ste10Xp_init); diff --git a/trunk/drivers/net/phy/vitesse.c b/trunk/drivers/net/phy/vitesse.c index 2585c383e623..0ec8e09cc2ac 100644 --- a/trunk/drivers/net/phy/vitesse.c +++ b/trunk/drivers/net/phy/vitesse.c @@ -138,6 +138,21 @@ static int vsc82xx_config_intr(struct phy_device *phydev) return err; } +/* Vitesse 824x */ +static struct phy_driver vsc8244_driver = { + .phy_id = PHY_ID_VSC8244, + .name = "Vitesse VSC8244", + .phy_id_mask = 0x000fffc0, + .features = PHY_GBIT_FEATURES, + .flags = PHY_HAS_INTERRUPT, + .config_init = &vsc824x_config_init, + .config_aneg = &genphy_config_aneg, + .read_status = &genphy_read_status, + .ack_interrupt = &vsc824x_ack_interrupt, + .config_intr = &vsc82xx_config_intr, + .driver = { .owner = THIS_MODULE,}, +}; + static int vsc8221_config_init(struct phy_device *phydev) { int err; @@ -150,22 +165,8 @@ static int vsc8221_config_init(struct phy_device *phydev) Options are 802.3Z SerDes or SGMII */ } -/* Vitesse 824x */ -static struct phy_driver vsc82xx_driver[] = { -{ - .phy_id = PHY_ID_VSC8244, - .name = "Vitesse VSC8244", - .phy_id_mask = 0x000fffc0, - .features = PHY_GBIT_FEATURES, - .flags = PHY_HAS_INTERRUPT, - .config_init = &vsc824x_config_init, - .config_aneg = &genphy_config_aneg, - .read_status = &genphy_read_status, - .ack_interrupt = &vsc824x_ack_interrupt, - .config_intr = &vsc82xx_config_intr, - .driver = { .owner = THIS_MODULE,}, -}, { - /* Vitesse 8221 */ +/* Vitesse 8221 */ +static struct phy_driver vsc8221_driver = { .phy_id = PHY_ID_VSC8221, .phy_id_mask = 0x000ffff0, .name = "Vitesse VSC8221", @@ -176,19 +177,26 @@ static struct phy_driver vsc82xx_driver[] = { .read_status = &genphy_read_status, .ack_interrupt = &vsc824x_ack_interrupt, .config_intr = &vsc82xx_config_intr, - .driver = { .owner = THIS_MODULE,}, -} }; + .driver = { .owner = THIS_MODULE,}, +}; static int __init vsc82xx_init(void) { - return phy_drivers_register(vsc82xx_driver, - ARRAY_SIZE(vsc82xx_driver)); + int err; + + err = phy_driver_register(&vsc8244_driver); + if (err < 0) + return err; + err = phy_driver_register(&vsc8221_driver); + if (err < 0) + phy_driver_unregister(&vsc8244_driver); + return err; } static void __exit vsc82xx_exit(void) { - return phy_drivers_unregister(vsc82xx_driver, - ARRAY_SIZE(vsc82xx_driver)); + phy_driver_unregister(&vsc8244_driver); + phy_driver_unregister(&vsc8221_driver); } module_init(vsc82xx_init); diff --git a/trunk/drivers/net/team/Kconfig b/trunk/drivers/net/team/Kconfig index 6a7260b03a1e..89024d5fc33a 100644 --- a/trunk/drivers/net/team/Kconfig +++ b/trunk/drivers/net/team/Kconfig @@ -15,17 +15,6 @@ menuconfig NET_TEAM if NET_TEAM -config NET_TEAM_MODE_BROADCAST - tristate "Broadcast mode support" - depends on NET_TEAM - ---help--- - Basic mode where packets are transmitted always by all suitable ports. - - All added ports are setup to have team's mac address. - - To compile this team mode as a module, choose M here: the module - will be called team_mode_broadcast. - config NET_TEAM_MODE_ROUNDROBIN tristate "Round-robin mode support" depends on NET_TEAM @@ -33,7 +22,7 @@ config NET_TEAM_MODE_ROUNDROBIN Basic mode where port used for transmitting packets is selected in round-robin fashion using packet counter. - All added ports are setup to have team's mac address. + All added ports are setup to have bond's mac address. To compile this team mode as a module, choose M here: the module will be called team_mode_roundrobin. diff --git a/trunk/drivers/net/team/Makefile b/trunk/drivers/net/team/Makefile index 975763014e5a..fb9f4c1c51ff 100644 --- a/trunk/drivers/net/team/Makefile +++ b/trunk/drivers/net/team/Makefile @@ -3,7 +3,6 @@ # obj-$(CONFIG_NET_TEAM) += team.o -obj-$(CONFIG_NET_TEAM_MODE_BROADCAST) += team_mode_broadcast.o obj-$(CONFIG_NET_TEAM_MODE_ROUNDROBIN) += team_mode_roundrobin.o obj-$(CONFIG_NET_TEAM_MODE_ACTIVEBACKUP) += team_mode_activebackup.o obj-$(CONFIG_NET_TEAM_MODE_LOADBALANCE) += team_mode_loadbalance.o diff --git a/trunk/drivers/net/team/team.c b/trunk/drivers/net/team/team.c index 1a13470dee07..9b94f53a9d4b 100644 --- a/trunk/drivers/net/team/team.c +++ b/trunk/drivers/net/team/team.c @@ -18,7 +18,6 @@ #include #include #include -#include #include #include #include @@ -672,6 +671,12 @@ static bool team_port_find(const struct team *team, return false; } +bool team_port_enabled(struct team_port *port) +{ + return port->index != -1; +} +EXPORT_SYMBOL(team_port_enabled); + /* * Enable/disable port by adding to enabled port hashlist and setting * port->index (Might be racy so reader could see incorrect ifindex when @@ -788,58 +793,6 @@ static void team_port_leave(struct team *team, struct team_port *port) dev_put(team->dev); } -#ifdef CONFIG_NET_POLL_CONTROLLER -static int team_port_enable_netpoll(struct team *team, struct team_port *port) -{ - struct netpoll *np; - int err; - - np = kzalloc(sizeof(*np), GFP_KERNEL); - if (!np) - return -ENOMEM; - - err = __netpoll_setup(np, port->dev); - if (err) { - kfree(np); - return err; - } - port->np = np; - return err; -} - -static void team_port_disable_netpoll(struct team_port *port) -{ - struct netpoll *np = port->np; - - if (!np) - return; - port->np = NULL; - - /* Wait for transmitting packets to finish before freeing. */ - synchronize_rcu_bh(); - __netpoll_cleanup(np); - kfree(np); -} - -static struct netpoll_info *team_netpoll_info(struct team *team) -{ - return team->dev->npinfo; -} - -#else -static int team_port_enable_netpoll(struct team *team, struct team_port *port) -{ - return 0; -} -static void team_port_disable_netpoll(struct team_port *port) -{ -} -static struct netpoll_info *team_netpoll_info(struct team *team) -{ - return NULL; -} -#endif - static void __team_port_change_check(struct team_port *port, bool linkup); static int team_port_add(struct team *team, struct net_device *port_dev) @@ -906,15 +859,6 @@ static int team_port_add(struct team *team, struct net_device *port_dev) goto err_vids_add; } - if (team_netpoll_info(team)) { - err = team_port_enable_netpoll(team, port); - if (err) { - netdev_err(dev, "Failed to enable netpoll on device %s\n", - portname); - goto err_enable_netpoll; - } - } - err = netdev_set_master(port_dev, dev); if (err) { netdev_err(dev, "Device %s failed to set master\n", portname); @@ -954,9 +898,6 @@ static int team_port_add(struct team *team, struct net_device *port_dev) netdev_set_master(port_dev, NULL); err_set_master: - team_port_disable_netpoll(port); - -err_enable_netpoll: vlan_vids_del_by_dev(port_dev, dev); err_vids_add: @@ -997,7 +938,6 @@ static int team_port_del(struct team *team, struct net_device *port_dev) list_del_rcu(&port->list); netdev_rx_handler_unregister(port_dev); netdev_set_master(port_dev, NULL); - team_port_disable_netpoll(port); vlan_vids_del_by_dev(port_dev, dev); dev_close(port_dev); team_port_leave(team, port); @@ -1373,48 +1313,6 @@ static int team_vlan_rx_kill_vid(struct net_device *dev, uint16_t vid) return 0; } -#ifdef CONFIG_NET_POLL_CONTROLLER -static void team_poll_controller(struct net_device *dev) -{ -} - -static void __team_netpoll_cleanup(struct team *team) -{ - struct team_port *port; - - list_for_each_entry(port, &team->port_list, list) - team_port_disable_netpoll(port); -} - -static void team_netpoll_cleanup(struct net_device *dev) -{ - struct team *team = netdev_priv(dev); - - mutex_lock(&team->lock); - __team_netpoll_cleanup(team); - mutex_unlock(&team->lock); -} - -static int team_netpoll_setup(struct net_device *dev, - struct netpoll_info *npifo) -{ - struct team *team = netdev_priv(dev); - struct team_port *port; - int err; - - mutex_lock(&team->lock); - list_for_each_entry(port, &team->port_list, list) { - err = team_port_enable_netpoll(team, port); - if (err) { - __team_netpoll_cleanup(team); - break; - } - } - mutex_unlock(&team->lock); - return err; -} -#endif - static int team_add_slave(struct net_device *dev, struct net_device *port_dev) { struct team *team = netdev_priv(dev); @@ -1471,11 +1369,6 @@ static const struct net_device_ops team_netdev_ops = { .ndo_get_stats64 = team_get_stats64, .ndo_vlan_rx_add_vid = team_vlan_rx_add_vid, .ndo_vlan_rx_kill_vid = team_vlan_rx_kill_vid, -#ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = team_poll_controller, - .ndo_netpoll_setup = team_netpoll_setup, - .ndo_netpoll_cleanup = team_netpoll_cleanup, -#endif .ndo_add_slave = team_add_slave, .ndo_del_slave = team_del_slave, .ndo_fix_features = team_fix_features, diff --git a/trunk/drivers/net/team/team_mode_activebackup.c b/trunk/drivers/net/team/team_mode_activebackup.c index 6262b4defd93..253b8a5f3427 100644 --- a/trunk/drivers/net/team/team_mode_activebackup.c +++ b/trunk/drivers/net/team/team_mode_activebackup.c @@ -43,7 +43,8 @@ static bool ab_transmit(struct team *team, struct sk_buff *skb) active_port = rcu_dereference_bh(ab_priv(team)->active_port); if (unlikely(!active_port)) goto drop; - if (team_dev_queue_xmit(team, active_port, skb)) + skb->dev = active_port->dev; + if (dev_queue_xmit(skb)) return false; return true; diff --git a/trunk/drivers/net/team/team_mode_broadcast.c b/trunk/drivers/net/team/team_mode_broadcast.c deleted file mode 100644 index c96e4d2967f0..000000000000 --- a/trunk/drivers/net/team/team_mode_broadcast.c +++ /dev/null @@ -1,87 +0,0 @@ -/* - * drivers/net/team/team_mode_broadcast.c - Broadcast mode for team - * Copyright (c) 2012 Jiri Pirko - * - * 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. - */ - -#include -#include -#include -#include -#include -#include -#include - -static bool bc_transmit(struct team *team, struct sk_buff *skb) -{ - struct team_port *cur; - struct team_port *last = NULL; - struct sk_buff *skb2; - bool ret; - bool sum_ret = false; - - list_for_each_entry_rcu(cur, &team->port_list, list) { - if (team_port_txable(cur)) { - if (last) { - skb2 = skb_clone(skb, GFP_ATOMIC); - if (skb2) { - ret = team_dev_queue_xmit(team, last, - skb2); - if (!sum_ret) - sum_ret = ret; - } - } - last = cur; - } - } - if (last) { - ret = team_dev_queue_xmit(team, last, skb); - if (!sum_ret) - sum_ret = ret; - } - return sum_ret; -} - -static int bc_port_enter(struct team *team, struct team_port *port) -{ - return team_port_set_team_mac(port); -} - -static void bc_port_change_mac(struct team *team, struct team_port *port) -{ - team_port_set_team_mac(port); -} - -static const struct team_mode_ops bc_mode_ops = { - .transmit = bc_transmit, - .port_enter = bc_port_enter, - .port_change_mac = bc_port_change_mac, -}; - -static const struct team_mode bc_mode = { - .kind = "broadcast", - .owner = THIS_MODULE, - .ops = &bc_mode_ops, -}; - -static int __init bc_init_module(void) -{ - return team_mode_register(&bc_mode); -} - -static void __exit bc_cleanup_module(void) -{ - team_mode_unregister(&bc_mode); -} - -module_init(bc_init_module); -module_exit(bc_cleanup_module); - -MODULE_LICENSE("GPL v2"); -MODULE_AUTHOR("Jiri Pirko "); -MODULE_DESCRIPTION("Broadcast mode for team"); -MODULE_ALIAS("team-mode-broadcast"); diff --git a/trunk/drivers/net/team/team_mode_loadbalance.c b/trunk/drivers/net/team/team_mode_loadbalance.c index cdc31b5ea15e..51a4b199c75c 100644 --- a/trunk/drivers/net/team/team_mode_loadbalance.c +++ b/trunk/drivers/net/team/team_mode_loadbalance.c @@ -217,7 +217,8 @@ static bool lb_transmit(struct team *team, struct sk_buff *skb) port = select_tx_port_func(team, lb_priv, skb, hash); if (unlikely(!port)) goto drop; - if (team_dev_queue_xmit(team, port, skb)) + skb->dev = port->dev; + if (dev_queue_xmit(skb)) return false; lb_update_tx_stats(tx_bytes, lb_priv, get_lb_port_priv(port), hash); return true; diff --git a/trunk/drivers/net/team/team_mode_roundrobin.c b/trunk/drivers/net/team/team_mode_roundrobin.c index ad7ed0ec544c..52dd0ec9cd1f 100644 --- a/trunk/drivers/net/team/team_mode_roundrobin.c +++ b/trunk/drivers/net/team/team_mode_roundrobin.c @@ -30,16 +30,16 @@ static struct team_port *__get_first_port_up(struct team *team, { struct team_port *cur; - if (team_port_txable(port)) + if (port->linkup) return port; cur = port; list_for_each_entry_continue_rcu(cur, &team->port_list, list) - if (team_port_txable(port)) + if (cur->linkup) return cur; list_for_each_entry_rcu(cur, &team->port_list, list) { if (cur == port) break; - if (team_port_txable(port)) + if (cur->linkup) return cur; } return NULL; @@ -55,7 +55,8 @@ static bool rr_transmit(struct team *team, struct sk_buff *skb) port = __get_first_port_up(team, port); if (unlikely(!port)) goto drop; - if (team_dev_queue_xmit(team, port, skb)) + skb->dev = port->dev; + if (dev_queue_xmit(skb)) return false; return true; diff --git a/trunk/drivers/net/tun.c b/trunk/drivers/net/tun.c index 961fad1f7053..987aeefbc774 100644 --- a/trunk/drivers/net/tun.c +++ b/trunk/drivers/net/tun.c @@ -22,7 +22,7 @@ * Add TUNSETLINK ioctl to set the link encapsulation * * Mark Smith - * Use eth_random_addr() for tap MAC address. + * Use random_ether_addr() for tap MAC address. * * Harald Roelle 2004/04/20 * Fixes in packet dropping, queue length setting and queue wakeup. diff --git a/trunk/drivers/net/usb/Makefile b/trunk/drivers/net/usb/Makefile index bf063008c1af..a2e2d72c52a0 100644 --- a/trunk/drivers/net/usb/Makefile +++ b/trunk/drivers/net/usb/Makefile @@ -8,7 +8,6 @@ obj-$(CONFIG_USB_PEGASUS) += pegasus.o obj-$(CONFIG_USB_RTL8150) += rtl8150.o obj-$(CONFIG_USB_HSO) += hso.o obj-$(CONFIG_USB_NET_AX8817X) += asix.o -asix-y := asix_devices.o asix_common.o ax88172a.o obj-$(CONFIG_USB_NET_CDCETHER) += cdc_ether.o obj-$(CONFIG_USB_NET_CDC_EEM) += cdc_eem.o obj-$(CONFIG_USB_NET_DM9601) += dm9601.o diff --git a/trunk/drivers/net/usb/asix_devices.c b/trunk/drivers/net/usb/asix.c similarity index 62% rename from trunk/drivers/net/usb/asix_devices.c rename to trunk/drivers/net/usb/asix.c index ed9403b0c437..3ae80eccd0ef 100644 --- a/trunk/drivers/net/usb/asix_devices.c +++ b/trunk/drivers/net/usb/asix.c @@ -20,7 +20,137 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "asix.h" +// #define DEBUG // error path messages, extra info +// #define VERBOSE // more; success messages + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRIVER_VERSION "22-Dec-2011" +#define DRIVER_NAME "asix" + +/* ASIX AX8817X based USB 2.0 Ethernet Devices */ + +#define AX_CMD_SET_SW_MII 0x06 +#define AX_CMD_READ_MII_REG 0x07 +#define AX_CMD_WRITE_MII_REG 0x08 +#define AX_CMD_SET_HW_MII 0x0a +#define AX_CMD_READ_EEPROM 0x0b +#define AX_CMD_WRITE_EEPROM 0x0c +#define AX_CMD_WRITE_ENABLE 0x0d +#define AX_CMD_WRITE_DISABLE 0x0e +#define AX_CMD_READ_RX_CTL 0x0f +#define AX_CMD_WRITE_RX_CTL 0x10 +#define AX_CMD_READ_IPG012 0x11 +#define AX_CMD_WRITE_IPG0 0x12 +#define AX_CMD_WRITE_IPG1 0x13 +#define AX_CMD_READ_NODE_ID 0x13 +#define AX_CMD_WRITE_NODE_ID 0x14 +#define AX_CMD_WRITE_IPG2 0x14 +#define AX_CMD_WRITE_MULTI_FILTER 0x16 +#define AX88172_CMD_READ_NODE_ID 0x17 +#define AX_CMD_READ_PHY_ID 0x19 +#define AX_CMD_READ_MEDIUM_STATUS 0x1a +#define AX_CMD_WRITE_MEDIUM_MODE 0x1b +#define AX_CMD_READ_MONITOR_MODE 0x1c +#define AX_CMD_WRITE_MONITOR_MODE 0x1d +#define AX_CMD_READ_GPIOS 0x1e +#define AX_CMD_WRITE_GPIOS 0x1f +#define AX_CMD_SW_RESET 0x20 +#define AX_CMD_SW_PHY_STATUS 0x21 +#define AX_CMD_SW_PHY_SELECT 0x22 + +#define AX_MONITOR_MODE 0x01 +#define AX_MONITOR_LINK 0x02 +#define AX_MONITOR_MAGIC 0x04 +#define AX_MONITOR_HSFS 0x10 + +/* AX88172 Medium Status Register values */ +#define AX88172_MEDIUM_FD 0x02 +#define AX88172_MEDIUM_TX 0x04 +#define AX88172_MEDIUM_FC 0x10 +#define AX88172_MEDIUM_DEFAULT \ + ( AX88172_MEDIUM_FD | AX88172_MEDIUM_TX | AX88172_MEDIUM_FC ) + +#define AX_MCAST_FILTER_SIZE 8 +#define AX_MAX_MCAST 64 + +#define AX_SWRESET_CLEAR 0x00 +#define AX_SWRESET_RR 0x01 +#define AX_SWRESET_RT 0x02 +#define AX_SWRESET_PRTE 0x04 +#define AX_SWRESET_PRL 0x08 +#define AX_SWRESET_BZ 0x10 +#define AX_SWRESET_IPRL 0x20 +#define AX_SWRESET_IPPD 0x40 + +#define AX88772_IPG0_DEFAULT 0x15 +#define AX88772_IPG1_DEFAULT 0x0c +#define AX88772_IPG2_DEFAULT 0x12 + +/* AX88772 & AX88178 Medium Mode Register */ +#define AX_MEDIUM_PF 0x0080 +#define AX_MEDIUM_JFE 0x0040 +#define AX_MEDIUM_TFC 0x0020 +#define AX_MEDIUM_RFC 0x0010 +#define AX_MEDIUM_ENCK 0x0008 +#define AX_MEDIUM_AC 0x0004 +#define AX_MEDIUM_FD 0x0002 +#define AX_MEDIUM_GM 0x0001 +#define AX_MEDIUM_SM 0x1000 +#define AX_MEDIUM_SBP 0x0800 +#define AX_MEDIUM_PS 0x0200 +#define AX_MEDIUM_RE 0x0100 + +#define AX88178_MEDIUM_DEFAULT \ + (AX_MEDIUM_PS | AX_MEDIUM_FD | AX_MEDIUM_AC | \ + AX_MEDIUM_RFC | AX_MEDIUM_TFC | AX_MEDIUM_JFE | \ + AX_MEDIUM_RE) + +#define AX88772_MEDIUM_DEFAULT \ + (AX_MEDIUM_FD | AX_MEDIUM_RFC | \ + AX_MEDIUM_TFC | AX_MEDIUM_PS | \ + AX_MEDIUM_AC | AX_MEDIUM_RE) + +/* AX88772 & AX88178 RX_CTL values */ +#define AX_RX_CTL_SO 0x0080 +#define AX_RX_CTL_AP 0x0020 +#define AX_RX_CTL_AM 0x0010 +#define AX_RX_CTL_AB 0x0008 +#define AX_RX_CTL_SEP 0x0004 +#define AX_RX_CTL_AMALL 0x0002 +#define AX_RX_CTL_PRO 0x0001 +#define AX_RX_CTL_MFB_2048 0x0000 +#define AX_RX_CTL_MFB_4096 0x0100 +#define AX_RX_CTL_MFB_8192 0x0200 +#define AX_RX_CTL_MFB_16384 0x0300 + +#define AX_DEFAULT_RX_CTL (AX_RX_CTL_SO | AX_RX_CTL_AB) + +/* GPIO 0 .. 2 toggles */ +#define AX_GPIO_GPO0EN 0x01 /* GPIO0 Output enable */ +#define AX_GPIO_GPO_0 0x02 /* GPIO0 Output value */ +#define AX_GPIO_GPO1EN 0x04 /* GPIO1 Output enable */ +#define AX_GPIO_GPO_1 0x08 /* GPIO1 Output value */ +#define AX_GPIO_GPO2EN 0x10 /* GPIO2 Output enable */ +#define AX_GPIO_GPO_2 0x20 /* GPIO2 Output value */ +#define AX_GPIO_RESERVED 0x40 /* Reserved */ +#define AX_GPIO_RSE 0x80 /* Reload serial EEPROM */ + +#define AX_EEPROM_MAGIC 0xdeadbeef +#define AX88172_EEPROM_LEN 0x40 +#define AX88772_EEPROM_LEN 0xff #define PHY_MODE_MARVELL 0x0000 #define MII_MARVELL_LED_CTRL 0x0018 @@ -36,6 +166,15 @@ #define PHY_MODE_RTL8211CL 0x000C +/* This structure cannot exceed sizeof(unsigned long [5]) AKA 20 bytes */ +struct asix_data { + u8 multi_filter[AX_MCAST_FILTER_SIZE]; + u8 mac_addr[ETH_ALEN]; + u8 phymode; + u8 ledmode; + u8 eeprom_len; +}; + struct ax88172_int_data { __le16 res1; u8 link; @@ -44,6 +183,209 @@ struct ax88172_int_data { __le16 res3; } __packed; +static int asix_read_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index, + u16 size, void *data) +{ + void *buf; + int err = -ENOMEM; + + netdev_dbg(dev->net, "asix_read_cmd() cmd=0x%02x value=0x%04x index=0x%04x size=%d\n", + cmd, value, index, size); + + buf = kmalloc(size, GFP_KERNEL); + if (!buf) + goto out; + + err = usb_control_msg( + dev->udev, + usb_rcvctrlpipe(dev->udev, 0), + cmd, + USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + value, + index, + buf, + size, + USB_CTRL_GET_TIMEOUT); + if (err == size) + memcpy(data, buf, size); + else if (err >= 0) + err = -EINVAL; + kfree(buf); + +out: + return err; +} + +static int asix_write_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index, + u16 size, void *data) +{ + void *buf = NULL; + int err = -ENOMEM; + + netdev_dbg(dev->net, "asix_write_cmd() cmd=0x%02x value=0x%04x index=0x%04x size=%d\n", + cmd, value, index, size); + + if (data) { + buf = kmemdup(data, size, GFP_KERNEL); + if (!buf) + goto out; + } + + err = usb_control_msg( + dev->udev, + usb_sndctrlpipe(dev->udev, 0), + cmd, + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + value, + index, + buf, + size, + USB_CTRL_SET_TIMEOUT); + kfree(buf); + +out: + return err; +} + +static void asix_async_cmd_callback(struct urb *urb) +{ + struct usb_ctrlrequest *req = (struct usb_ctrlrequest *)urb->context; + int status = urb->status; + + if (status < 0) + printk(KERN_DEBUG "asix_async_cmd_callback() failed with %d", + status); + + kfree(req); + usb_free_urb(urb); +} + +static void +asix_write_cmd_async(struct usbnet *dev, u8 cmd, u16 value, u16 index, + u16 size, void *data) +{ + struct usb_ctrlrequest *req; + int status; + struct urb *urb; + + netdev_dbg(dev->net, "asix_write_cmd_async() cmd=0x%02x value=0x%04x index=0x%04x size=%d\n", + cmd, value, index, size); + + urb = usb_alloc_urb(0, GFP_ATOMIC); + if (!urb) { + netdev_err(dev->net, "Error allocating URB in write_cmd_async!\n"); + return; + } + + req = kmalloc(sizeof(struct usb_ctrlrequest), GFP_ATOMIC); + if (!req) { + netdev_err(dev->net, "Failed to allocate memory for control request\n"); + usb_free_urb(urb); + return; + } + + req->bRequestType = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE; + req->bRequest = cmd; + req->wValue = cpu_to_le16(value); + req->wIndex = cpu_to_le16(index); + req->wLength = cpu_to_le16(size); + + usb_fill_control_urb(urb, dev->udev, + usb_sndctrlpipe(dev->udev, 0), + (void *)req, data, size, + asix_async_cmd_callback, req); + + status = usb_submit_urb(urb, GFP_ATOMIC); + if (status < 0) { + netdev_err(dev->net, "Error submitting the control message: status=%d\n", + status); + kfree(req); + usb_free_urb(urb); + } +} + +static int asix_rx_fixup(struct usbnet *dev, struct sk_buff *skb) +{ + int offset = 0; + + while (offset + sizeof(u32) < skb->len) { + struct sk_buff *ax_skb; + u16 size; + u32 header = get_unaligned_le32(skb->data + offset); + + offset += sizeof(u32); + + /* get the packet length */ + size = (u16) (header & 0x7ff); + if (size != ((~header >> 16) & 0x07ff)) { + netdev_err(dev->net, "asix_rx_fixup() Bad Header Length\n"); + return 0; + } + + if ((size > dev->net->mtu + ETH_HLEN + VLAN_HLEN) || + (size + offset > skb->len)) { + netdev_err(dev->net, "asix_rx_fixup() Bad RX Length %d\n", + size); + return 0; + } + ax_skb = netdev_alloc_skb_ip_align(dev->net, size); + if (!ax_skb) + return 0; + + skb_put(ax_skb, size); + memcpy(ax_skb->data, skb->data + offset, size); + usbnet_skb_return(dev, ax_skb); + + offset += (size + 1) & 0xfffe; + } + + if (skb->len != offset) { + netdev_err(dev->net, "asix_rx_fixup() Bad SKB Length %d\n", + skb->len); + return 0; + } + return 1; +} + +static struct sk_buff *asix_tx_fixup(struct usbnet *dev, struct sk_buff *skb, + gfp_t flags) +{ + int padlen; + int headroom = skb_headroom(skb); + int tailroom = skb_tailroom(skb); + u32 packet_len; + u32 padbytes = 0xffff0000; + + padlen = ((skb->len + 4) & (dev->maxpacket - 1)) ? 0 : 4; + + if ((!skb_cloned(skb)) && + ((headroom + tailroom) >= (4 + padlen))) { + if ((headroom < 4) || (tailroom < padlen)) { + skb->data = memmove(skb->head + 4, skb->data, skb->len); + skb_set_tail_pointer(skb, skb->len); + } + } else { + struct sk_buff *skb2; + skb2 = skb_copy_expand(skb, 4, padlen, flags); + dev_kfree_skb_any(skb); + skb = skb2; + if (!skb) + return NULL; + } + + skb_push(skb, 4); + packet_len = (((skb->len - 4) ^ 0x0000ffff) << 16) + (skb->len - 4); + cpu_to_le32s(&packet_len); + skb_copy_to_linear_data(skb, &packet_len, sizeof(packet_len)); + + if (padlen) { + cpu_to_le32s(&padbytes); + memcpy(skb_tail_pointer(skb), &padbytes, sizeof(padbytes)); + skb_put(skb, sizeof(padbytes)); + } + return skb; +} + static void asix_status(struct usbnet *dev, struct urb *urb) { struct ax88172_int_data *event; @@ -64,6 +406,200 @@ static void asix_status(struct usbnet *dev, struct urb *urb) } } +static inline int asix_set_sw_mii(struct usbnet *dev) +{ + int ret; + ret = asix_write_cmd(dev, AX_CMD_SET_SW_MII, 0x0000, 0, 0, NULL); + if (ret < 0) + netdev_err(dev->net, "Failed to enable software MII access\n"); + return ret; +} + +static inline int asix_set_hw_mii(struct usbnet *dev) +{ + int ret; + ret = asix_write_cmd(dev, AX_CMD_SET_HW_MII, 0x0000, 0, 0, NULL); + if (ret < 0) + netdev_err(dev->net, "Failed to enable hardware MII access\n"); + return ret; +} + +static inline int asix_get_phy_addr(struct usbnet *dev) +{ + u8 buf[2]; + int ret = asix_read_cmd(dev, AX_CMD_READ_PHY_ID, 0, 0, 2, buf); + + netdev_dbg(dev->net, "asix_get_phy_addr()\n"); + + if (ret < 0) { + netdev_err(dev->net, "Error reading PHYID register: %02x\n", ret); + goto out; + } + netdev_dbg(dev->net, "asix_get_phy_addr() returning 0x%04x\n", + *((__le16 *)buf)); + ret = buf[1]; + +out: + return ret; +} + +static int asix_sw_reset(struct usbnet *dev, u8 flags) +{ + int ret; + + ret = asix_write_cmd(dev, AX_CMD_SW_RESET, flags, 0, 0, NULL); + if (ret < 0) + netdev_err(dev->net, "Failed to send software reset: %02x\n", ret); + + return ret; +} + +static u16 asix_read_rx_ctl(struct usbnet *dev) +{ + __le16 v; + int ret = asix_read_cmd(dev, AX_CMD_READ_RX_CTL, 0, 0, 2, &v); + + if (ret < 0) { + netdev_err(dev->net, "Error reading RX_CTL register: %02x\n", ret); + goto out; + } + ret = le16_to_cpu(v); +out: + return ret; +} + +static int asix_write_rx_ctl(struct usbnet *dev, u16 mode) +{ + int ret; + + netdev_dbg(dev->net, "asix_write_rx_ctl() - mode = 0x%04x\n", mode); + ret = asix_write_cmd(dev, AX_CMD_WRITE_RX_CTL, mode, 0, 0, NULL); + if (ret < 0) + netdev_err(dev->net, "Failed to write RX_CTL mode to 0x%04x: %02x\n", + mode, ret); + + return ret; +} + +static u16 asix_read_medium_status(struct usbnet *dev) +{ + __le16 v; + int ret = asix_read_cmd(dev, AX_CMD_READ_MEDIUM_STATUS, 0, 0, 2, &v); + + if (ret < 0) { + netdev_err(dev->net, "Error reading Medium Status register: %02x\n", + ret); + return ret; /* TODO: callers not checking for error ret */ + } + + return le16_to_cpu(v); + +} + +static int asix_write_medium_mode(struct usbnet *dev, u16 mode) +{ + int ret; + + netdev_dbg(dev->net, "asix_write_medium_mode() - mode = 0x%04x\n", mode); + ret = asix_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE, mode, 0, 0, NULL); + if (ret < 0) + netdev_err(dev->net, "Failed to write Medium Mode mode to 0x%04x: %02x\n", + mode, ret); + + return ret; +} + +static int asix_write_gpio(struct usbnet *dev, u16 value, int sleep) +{ + int ret; + + netdev_dbg(dev->net, "asix_write_gpio() - value = 0x%04x\n", value); + ret = asix_write_cmd(dev, AX_CMD_WRITE_GPIOS, value, 0, 0, NULL); + if (ret < 0) + netdev_err(dev->net, "Failed to write GPIO value 0x%04x: %02x\n", + value, ret); + + if (sleep) + msleep(sleep); + + return ret; +} + +/* + * AX88772 & AX88178 have a 16-bit RX_CTL value + */ +static void asix_set_multicast(struct net_device *net) +{ + struct usbnet *dev = netdev_priv(net); + struct asix_data *data = (struct asix_data *)&dev->data; + u16 rx_ctl = AX_DEFAULT_RX_CTL; + + if (net->flags & IFF_PROMISC) { + rx_ctl |= AX_RX_CTL_PRO; + } else if (net->flags & IFF_ALLMULTI || + netdev_mc_count(net) > AX_MAX_MCAST) { + rx_ctl |= AX_RX_CTL_AMALL; + } else if (netdev_mc_empty(net)) { + /* just broadcast and directed */ + } else { + /* We use the 20 byte dev->data + * for our 8 byte filter buffer + * to avoid allocating memory that + * is tricky to free later */ + struct netdev_hw_addr *ha; + u32 crc_bits; + + memset(data->multi_filter, 0, AX_MCAST_FILTER_SIZE); + + /* Build the multicast hash filter. */ + netdev_for_each_mc_addr(ha, net) { + crc_bits = ether_crc(ETH_ALEN, ha->addr) >> 26; + data->multi_filter[crc_bits >> 3] |= + 1 << (crc_bits & 7); + } + + asix_write_cmd_async(dev, AX_CMD_WRITE_MULTI_FILTER, 0, 0, + AX_MCAST_FILTER_SIZE, data->multi_filter); + + rx_ctl |= AX_RX_CTL_AM; + } + + asix_write_cmd_async(dev, AX_CMD_WRITE_RX_CTL, rx_ctl, 0, 0, NULL); +} + +static int asix_mdio_read(struct net_device *netdev, int phy_id, int loc) +{ + struct usbnet *dev = netdev_priv(netdev); + __le16 res; + + mutex_lock(&dev->phy_mutex); + asix_set_sw_mii(dev); + asix_read_cmd(dev, AX_CMD_READ_MII_REG, phy_id, + (__u16)loc, 2, &res); + asix_set_hw_mii(dev); + mutex_unlock(&dev->phy_mutex); + + netdev_dbg(dev->net, "asix_mdio_read() phy_id=0x%02x, loc=0x%02x, returns=0x%04x\n", + phy_id, loc, le16_to_cpu(res)); + + return le16_to_cpu(res); +} + +static void +asix_mdio_write(struct net_device *netdev, int phy_id, int loc, int val) +{ + struct usbnet *dev = netdev_priv(netdev); + __le16 res = cpu_to_le16(val); + + netdev_dbg(dev->net, "asix_mdio_write() phy_id=0x%02x, loc=0x%02x, val=0x%04x\n", + phy_id, loc, val); + mutex_lock(&dev->phy_mutex); + asix_set_sw_mii(dev); + asix_write_cmd(dev, AX_CMD_WRITE_MII_REG, phy_id, (__u16)loc, 2, &res); + asix_set_hw_mii(dev); + mutex_unlock(&dev->phy_mutex); +} + /* Get the PHY Identifier from the PHYSID1 & PHYSID2 MII registers */ static u32 asix_get_phyid(struct usbnet *dev) { @@ -93,6 +629,88 @@ static u32 asix_get_phyid(struct usbnet *dev) return phy_id; } +static void +asix_get_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo) +{ + struct usbnet *dev = netdev_priv(net); + u8 opt; + + if (asix_read_cmd(dev, AX_CMD_READ_MONITOR_MODE, 0, 0, 1, &opt) < 0) { + wolinfo->supported = 0; + wolinfo->wolopts = 0; + return; + } + wolinfo->supported = WAKE_PHY | WAKE_MAGIC; + wolinfo->wolopts = 0; + if (opt & AX_MONITOR_LINK) + wolinfo->wolopts |= WAKE_PHY; + if (opt & AX_MONITOR_MAGIC) + wolinfo->wolopts |= WAKE_MAGIC; +} + +static int +asix_set_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo) +{ + struct usbnet *dev = netdev_priv(net); + u8 opt = 0; + + if (wolinfo->wolopts & WAKE_PHY) + opt |= AX_MONITOR_LINK; + if (wolinfo->wolopts & WAKE_MAGIC) + opt |= AX_MONITOR_MAGIC; + + if (asix_write_cmd(dev, AX_CMD_WRITE_MONITOR_MODE, + opt, 0, 0, NULL) < 0) + return -EINVAL; + + return 0; +} + +static int asix_get_eeprom_len(struct net_device *net) +{ + struct usbnet *dev = netdev_priv(net); + struct asix_data *data = (struct asix_data *)&dev->data; + + return data->eeprom_len; +} + +static int asix_get_eeprom(struct net_device *net, + struct ethtool_eeprom *eeprom, u8 *data) +{ + struct usbnet *dev = netdev_priv(net); + __le16 *ebuf = (__le16 *)data; + int i; + + /* Crude hack to ensure that we don't overwrite memory + * if an odd length is supplied + */ + if (eeprom->len % 2) + return -EINVAL; + + eeprom->magic = AX_EEPROM_MAGIC; + + /* ax8817x returns 2 bytes from eeprom on read */ + for (i=0; i < eeprom->len / 2; i++) { + if (asix_read_cmd(dev, AX_CMD_READ_EEPROM, + eeprom->offset + i, 0, 2, &ebuf[i]) < 0) + return -EINVAL; + } + return 0; +} + +static void asix_get_drvinfo (struct net_device *net, + struct ethtool_drvinfo *info) +{ + struct usbnet *dev = netdev_priv(net); + struct asix_data *data = (struct asix_data *)&dev->data; + + /* Inherit standard device info */ + usbnet_get_drvinfo(net, info); + strncpy (info->driver, DRIVER_NAME, sizeof info->driver); + strncpy (info->version, DRIVER_VERSION, sizeof info->version); + info->eedump_len = data->eeprom_len; +} + static u32 asix_get_link(struct net_device *net) { struct usbnet *dev = netdev_priv(net); @@ -107,6 +725,30 @@ static int asix_ioctl (struct net_device *net, struct ifreq *rq, int cmd) return generic_mii_ioctl(&dev->mii, if_mii(rq), cmd, NULL); } +static int asix_set_mac_address(struct net_device *net, void *p) +{ + struct usbnet *dev = netdev_priv(net); + struct asix_data *data = (struct asix_data *)&dev->data; + struct sockaddr *addr = p; + + if (netif_running(net)) + return -EBUSY; + if (!is_valid_ether_addr(addr->sa_data)) + return -EADDRNOTAVAIL; + + memcpy(net->dev_addr, addr->sa_data, ETH_ALEN); + + /* We use the 20 byte dev->data + * for our 6 byte mac buffer + * to avoid allocating memory that + * is tricky to free later */ + memcpy(data->mac_addr, addr->sa_data, ETH_ALEN); + asix_write_cmd_async(dev, AX_CMD_WRITE_NODE_ID, 0, 0, ETH_ALEN, + data->mac_addr); + + return 0; +} + /* We need to override some ethtool_ops so we require our own structure so we don't interfere with other usbnet devices that may be connected at the same time. */ @@ -238,8 +880,6 @@ static int ax88172_bind(struct usbnet *dev, struct usb_interface *intf) dev->net->netdev_ops = &ax88172_netdev_ops; dev->net->ethtool_ops = &ax88172_ethtool_ops; - dev->net->needed_headroom = 4; /* cf asix_tx_fixup() */ - dev->net->needed_tailroom = 4; /* cf asix_tx_fixup() */ asix_mdio_write(dev->net, dev->mii.phy_id, MII_BMCR, BMCR_RESET); asix_mdio_write(dev->net, dev->mii.phy_id, MII_ADVERTISE, @@ -435,8 +1075,6 @@ static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf) dev->net->netdev_ops = &ax88772_netdev_ops; dev->net->ethtool_ops = &ax88772_ethtool_ops; - dev->net->needed_headroom = 4; /* cf asix_tx_fixup() */ - dev->net->needed_tailroom = 4; /* cf asix_tx_fixup() */ embd_phy = ((dev->mii.phy_id & 0x1f) == 0x10 ? 1 : 0); @@ -872,8 +1510,6 @@ static const struct driver_info ax88178_info = { .tx_fixup = asix_tx_fixup, }; -extern const struct driver_info ax88172a_info; - static const struct usb_device_id products [] = { { // Linksys USB200M @@ -999,10 +1635,6 @@ static const struct usb_device_id products [] = { // Asus USB Ethernet Adapter USB_DEVICE (0x0b95, 0x7e2b), .driver_info = (unsigned long) &ax88772_info, -}, { - /* ASIX 88172a demo board */ - USB_DEVICE(0x0b95, 0x172a), - .driver_info = (unsigned long) &ax88172a_info, }, { }, // END }; diff --git a/trunk/drivers/net/usb/asix.h b/trunk/drivers/net/usb/asix.h deleted file mode 100644 index 77d9e4c1e235..000000000000 --- a/trunk/drivers/net/usb/asix.h +++ /dev/null @@ -1,217 +0,0 @@ -/* - * ASIX AX8817X based USB 2.0 Ethernet Devices - * Copyright (C) 2003-2006 David Hollis - * Copyright (C) 2005 Phil Chang - * Copyright (C) 2006 James Painter - * Copyright (c) 2002-2003 TiVo Inc. - * - * 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 _ASIX_H -#define _ASIX_H - -// #define DEBUG // error path messages, extra info -// #define VERBOSE // more; success messages - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define DRIVER_VERSION "22-Dec-2011" -#define DRIVER_NAME "asix" - -/* ASIX AX8817X based USB 2.0 Ethernet Devices */ - -#define AX_CMD_SET_SW_MII 0x06 -#define AX_CMD_READ_MII_REG 0x07 -#define AX_CMD_WRITE_MII_REG 0x08 -#define AX_CMD_SET_HW_MII 0x0a -#define AX_CMD_READ_EEPROM 0x0b -#define AX_CMD_WRITE_EEPROM 0x0c -#define AX_CMD_WRITE_ENABLE 0x0d -#define AX_CMD_WRITE_DISABLE 0x0e -#define AX_CMD_READ_RX_CTL 0x0f -#define AX_CMD_WRITE_RX_CTL 0x10 -#define AX_CMD_READ_IPG012 0x11 -#define AX_CMD_WRITE_IPG0 0x12 -#define AX_CMD_WRITE_IPG1 0x13 -#define AX_CMD_READ_NODE_ID 0x13 -#define AX_CMD_WRITE_NODE_ID 0x14 -#define AX_CMD_WRITE_IPG2 0x14 -#define AX_CMD_WRITE_MULTI_FILTER 0x16 -#define AX88172_CMD_READ_NODE_ID 0x17 -#define AX_CMD_READ_PHY_ID 0x19 -#define AX_CMD_READ_MEDIUM_STATUS 0x1a -#define AX_CMD_WRITE_MEDIUM_MODE 0x1b -#define AX_CMD_READ_MONITOR_MODE 0x1c -#define AX_CMD_WRITE_MONITOR_MODE 0x1d -#define AX_CMD_READ_GPIOS 0x1e -#define AX_CMD_WRITE_GPIOS 0x1f -#define AX_CMD_SW_RESET 0x20 -#define AX_CMD_SW_PHY_STATUS 0x21 -#define AX_CMD_SW_PHY_SELECT 0x22 - -#define AX_PHY_SELECT_MASK (BIT(3) | BIT(2)) -#define AX_PHY_SELECT_INTERNAL 0 -#define AX_PHY_SELECT_EXTERNAL BIT(2) - -#define AX_MONITOR_MODE 0x01 -#define AX_MONITOR_LINK 0x02 -#define AX_MONITOR_MAGIC 0x04 -#define AX_MONITOR_HSFS 0x10 - -/* AX88172 Medium Status Register values */ -#define AX88172_MEDIUM_FD 0x02 -#define AX88172_MEDIUM_TX 0x04 -#define AX88172_MEDIUM_FC 0x10 -#define AX88172_MEDIUM_DEFAULT \ - ( AX88172_MEDIUM_FD | AX88172_MEDIUM_TX | AX88172_MEDIUM_FC ) - -#define AX_MCAST_FILTER_SIZE 8 -#define AX_MAX_MCAST 64 - -#define AX_SWRESET_CLEAR 0x00 -#define AX_SWRESET_RR 0x01 -#define AX_SWRESET_RT 0x02 -#define AX_SWRESET_PRTE 0x04 -#define AX_SWRESET_PRL 0x08 -#define AX_SWRESET_BZ 0x10 -#define AX_SWRESET_IPRL 0x20 -#define AX_SWRESET_IPPD 0x40 - -#define AX88772_IPG0_DEFAULT 0x15 -#define AX88772_IPG1_DEFAULT 0x0c -#define AX88772_IPG2_DEFAULT 0x12 - -/* AX88772 & AX88178 Medium Mode Register */ -#define AX_MEDIUM_PF 0x0080 -#define AX_MEDIUM_JFE 0x0040 -#define AX_MEDIUM_TFC 0x0020 -#define AX_MEDIUM_RFC 0x0010 -#define AX_MEDIUM_ENCK 0x0008 -#define AX_MEDIUM_AC 0x0004 -#define AX_MEDIUM_FD 0x0002 -#define AX_MEDIUM_GM 0x0001 -#define AX_MEDIUM_SM 0x1000 -#define AX_MEDIUM_SBP 0x0800 -#define AX_MEDIUM_PS 0x0200 -#define AX_MEDIUM_RE 0x0100 - -#define AX88178_MEDIUM_DEFAULT \ - (AX_MEDIUM_PS | AX_MEDIUM_FD | AX_MEDIUM_AC | \ - AX_MEDIUM_RFC | AX_MEDIUM_TFC | AX_MEDIUM_JFE | \ - AX_MEDIUM_RE) - -#define AX88772_MEDIUM_DEFAULT \ - (AX_MEDIUM_FD | AX_MEDIUM_RFC | \ - AX_MEDIUM_TFC | AX_MEDIUM_PS | \ - AX_MEDIUM_AC | AX_MEDIUM_RE) - -/* AX88772 & AX88178 RX_CTL values */ -#define AX_RX_CTL_SO 0x0080 -#define AX_RX_CTL_AP 0x0020 -#define AX_RX_CTL_AM 0x0010 -#define AX_RX_CTL_AB 0x0008 -#define AX_RX_CTL_SEP 0x0004 -#define AX_RX_CTL_AMALL 0x0002 -#define AX_RX_CTL_PRO 0x0001 -#define AX_RX_CTL_MFB_2048 0x0000 -#define AX_RX_CTL_MFB_4096 0x0100 -#define AX_RX_CTL_MFB_8192 0x0200 -#define AX_RX_CTL_MFB_16384 0x0300 - -#define AX_DEFAULT_RX_CTL (AX_RX_CTL_SO | AX_RX_CTL_AB) - -/* GPIO 0 .. 2 toggles */ -#define AX_GPIO_GPO0EN 0x01 /* GPIO0 Output enable */ -#define AX_GPIO_GPO_0 0x02 /* GPIO0 Output value */ -#define AX_GPIO_GPO1EN 0x04 /* GPIO1 Output enable */ -#define AX_GPIO_GPO_1 0x08 /* GPIO1 Output value */ -#define AX_GPIO_GPO2EN 0x10 /* GPIO2 Output enable */ -#define AX_GPIO_GPO_2 0x20 /* GPIO2 Output value */ -#define AX_GPIO_RESERVED 0x40 /* Reserved */ -#define AX_GPIO_RSE 0x80 /* Reload serial EEPROM */ - -#define AX_EEPROM_MAGIC 0xdeadbeef -#define AX88172_EEPROM_LEN 0x40 -#define AX88772_EEPROM_LEN 0xff - -/* This structure cannot exceed sizeof(unsigned long [5]) AKA 20 bytes */ -struct asix_data { - u8 multi_filter[AX_MCAST_FILTER_SIZE]; - u8 mac_addr[ETH_ALEN]; - u8 phymode; - u8 ledmode; - u8 eeprom_len; -}; - -int asix_read_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index, - u16 size, void *data); - -int asix_write_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index, - u16 size, void *data); - -void asix_write_cmd_async(struct usbnet *dev, u8 cmd, u16 value, - u16 index, u16 size, void *data); - -int asix_rx_fixup(struct usbnet *dev, struct sk_buff *skb); - -struct sk_buff *asix_tx_fixup(struct usbnet *dev, struct sk_buff *skb, - gfp_t flags); - -int asix_set_sw_mii(struct usbnet *dev); -int asix_set_hw_mii(struct usbnet *dev); - -int asix_read_phy_addr(struct usbnet *dev, int internal); -int asix_get_phy_addr(struct usbnet *dev); - -int asix_sw_reset(struct usbnet *dev, u8 flags); - -u16 asix_read_rx_ctl(struct usbnet *dev); -int asix_write_rx_ctl(struct usbnet *dev, u16 mode); - -u16 asix_read_medium_status(struct usbnet *dev); -int asix_write_medium_mode(struct usbnet *dev, u16 mode); - -int asix_write_gpio(struct usbnet *dev, u16 value, int sleep); - -void asix_set_multicast(struct net_device *net); - -int asix_mdio_read(struct net_device *netdev, int phy_id, int loc); -void asix_mdio_write(struct net_device *netdev, int phy_id, int loc, int val); - -void asix_get_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo); -int asix_set_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo); - -int asix_get_eeprom_len(struct net_device *net); -int asix_get_eeprom(struct net_device *net, struct ethtool_eeprom *eeprom, - u8 *data); - -void asix_get_drvinfo(struct net_device *net, struct ethtool_drvinfo *info); - -int asix_set_mac_address(struct net_device *net, void *p); - -#endif /* _ASIX_H */ diff --git a/trunk/drivers/net/usb/asix_common.c b/trunk/drivers/net/usb/asix_common.c deleted file mode 100644 index 336f75567091..000000000000 --- a/trunk/drivers/net/usb/asix_common.c +++ /dev/null @@ -1,545 +0,0 @@ -/* - * ASIX AX8817X based USB 2.0 Ethernet Devices - * Copyright (C) 2003-2006 David Hollis - * Copyright (C) 2005 Phil Chang - * Copyright (C) 2006 James Painter - * Copyright (c) 2002-2003 TiVo Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "asix.h" - -int asix_read_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index, - u16 size, void *data) -{ - void *buf; - int err = -ENOMEM; - - netdev_dbg(dev->net, "asix_read_cmd() cmd=0x%02x value=0x%04x index=0x%04x size=%d\n", - cmd, value, index, size); - - buf = kmalloc(size, GFP_KERNEL); - if (!buf) - goto out; - - err = usb_control_msg( - dev->udev, - usb_rcvctrlpipe(dev->udev, 0), - cmd, - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - value, - index, - buf, - size, - USB_CTRL_GET_TIMEOUT); - if (err == size) - memcpy(data, buf, size); - else if (err >= 0) - err = -EINVAL; - kfree(buf); - -out: - return err; -} - -int asix_write_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index, - u16 size, void *data) -{ - void *buf = NULL; - int err = -ENOMEM; - - netdev_dbg(dev->net, "asix_write_cmd() cmd=0x%02x value=0x%04x index=0x%04x size=%d\n", - cmd, value, index, size); - - if (data) { - buf = kmemdup(data, size, GFP_KERNEL); - if (!buf) - goto out; - } - - err = usb_control_msg( - dev->udev, - usb_sndctrlpipe(dev->udev, 0), - cmd, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - value, - index, - buf, - size, - USB_CTRL_SET_TIMEOUT); - kfree(buf); - -out: - return err; -} - -static void asix_async_cmd_callback(struct urb *urb) -{ - struct usb_ctrlrequest *req = (struct usb_ctrlrequest *)urb->context; - int status = urb->status; - - if (status < 0) - printk(KERN_DEBUG "asix_async_cmd_callback() failed with %d", - status); - - kfree(req); - usb_free_urb(urb); -} - -void asix_write_cmd_async(struct usbnet *dev, u8 cmd, u16 value, u16 index, - u16 size, void *data) -{ - struct usb_ctrlrequest *req; - int status; - struct urb *urb; - - netdev_dbg(dev->net, "asix_write_cmd_async() cmd=0x%02x value=0x%04x index=0x%04x size=%d\n", - cmd, value, index, size); - - urb = usb_alloc_urb(0, GFP_ATOMIC); - if (!urb) { - netdev_err(dev->net, "Error allocating URB in write_cmd_async!\n"); - return; - } - - req = kmalloc(sizeof(struct usb_ctrlrequest), GFP_ATOMIC); - if (!req) { - netdev_err(dev->net, "Failed to allocate memory for control request\n"); - usb_free_urb(urb); - return; - } - - req->bRequestType = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE; - req->bRequest = cmd; - req->wValue = cpu_to_le16(value); - req->wIndex = cpu_to_le16(index); - req->wLength = cpu_to_le16(size); - - usb_fill_control_urb(urb, dev->udev, - usb_sndctrlpipe(dev->udev, 0), - (void *)req, data, size, - asix_async_cmd_callback, req); - - status = usb_submit_urb(urb, GFP_ATOMIC); - if (status < 0) { - netdev_err(dev->net, "Error submitting the control message: status=%d\n", - status); - kfree(req); - usb_free_urb(urb); - } -} - -int asix_rx_fixup(struct usbnet *dev, struct sk_buff *skb) -{ - int offset = 0; - - while (offset + sizeof(u32) < skb->len) { - struct sk_buff *ax_skb; - u16 size; - u32 header = get_unaligned_le32(skb->data + offset); - - offset += sizeof(u32); - - /* get the packet length */ - size = (u16) (header & 0x7ff); - if (size != ((~header >> 16) & 0x07ff)) { - netdev_err(dev->net, "asix_rx_fixup() Bad Header Length\n"); - return 0; - } - - if ((size > dev->net->mtu + ETH_HLEN + VLAN_HLEN) || - (size + offset > skb->len)) { - netdev_err(dev->net, "asix_rx_fixup() Bad RX Length %d\n", - size); - return 0; - } - ax_skb = netdev_alloc_skb_ip_align(dev->net, size); - if (!ax_skb) - return 0; - - skb_put(ax_skb, size); - memcpy(ax_skb->data, skb->data + offset, size); - usbnet_skb_return(dev, ax_skb); - - offset += (size + 1) & 0xfffe; - } - - if (skb->len != offset) { - netdev_err(dev->net, "asix_rx_fixup() Bad SKB Length %d\n", - skb->len); - return 0; - } - return 1; -} - -struct sk_buff *asix_tx_fixup(struct usbnet *dev, struct sk_buff *skb, - gfp_t flags) -{ - int padlen; - int headroom = skb_headroom(skb); - int tailroom = skb_tailroom(skb); - u32 packet_len; - u32 padbytes = 0xffff0000; - - padlen = ((skb->len + 4) & (dev->maxpacket - 1)) ? 0 : 4; - - /* We need to push 4 bytes in front of frame (packet_len) - * and maybe add 4 bytes after the end (if padlen is 4) - * - * Avoid skb_copy_expand() expensive call, using following rules : - * - We are allowed to push 4 bytes in headroom if skb_header_cloned() - * is false (and if we have 4 bytes of headroom) - * - We are allowed to put 4 bytes at tail if skb_cloned() - * is false (and if we have 4 bytes of tailroom) - * - * TCP packets for example are cloned, but skb_header_release() - * was called in tcp stack, allowing us to use headroom for our needs. - */ - if (!skb_header_cloned(skb) && - !(padlen && skb_cloned(skb)) && - headroom + tailroom >= 4 + padlen) { - /* following should not happen, but better be safe */ - if (headroom < 4 || - tailroom < padlen) { - skb->data = memmove(skb->head + 4, skb->data, skb->len); - skb_set_tail_pointer(skb, skb->len); - } - } else { - struct sk_buff *skb2; - - skb2 = skb_copy_expand(skb, 4, padlen, flags); - dev_kfree_skb_any(skb); - skb = skb2; - if (!skb) - return NULL; - } - - packet_len = ((skb->len ^ 0x0000ffff) << 16) + skb->len; - skb_push(skb, 4); - cpu_to_le32s(&packet_len); - skb_copy_to_linear_data(skb, &packet_len, sizeof(packet_len)); - - if (padlen) { - cpu_to_le32s(&padbytes); - memcpy(skb_tail_pointer(skb), &padbytes, sizeof(padbytes)); - skb_put(skb, sizeof(padbytes)); - } - return skb; -} - -int asix_set_sw_mii(struct usbnet *dev) -{ - int ret; - ret = asix_write_cmd(dev, AX_CMD_SET_SW_MII, 0x0000, 0, 0, NULL); - if (ret < 0) - netdev_err(dev->net, "Failed to enable software MII access\n"); - return ret; -} - -int asix_set_hw_mii(struct usbnet *dev) -{ - int ret; - ret = asix_write_cmd(dev, AX_CMD_SET_HW_MII, 0x0000, 0, 0, NULL); - if (ret < 0) - netdev_err(dev->net, "Failed to enable hardware MII access\n"); - return ret; -} - -int asix_read_phy_addr(struct usbnet *dev, int internal) -{ - int offset = (internal ? 1 : 0); - u8 buf[2]; - int ret = asix_read_cmd(dev, AX_CMD_READ_PHY_ID, 0, 0, 2, buf); - - netdev_dbg(dev->net, "asix_get_phy_addr()\n"); - - if (ret < 0) { - netdev_err(dev->net, "Error reading PHYID register: %02x\n", ret); - goto out; - } - netdev_dbg(dev->net, "asix_get_phy_addr() returning 0x%04x\n", - *((__le16 *)buf)); - ret = buf[offset]; - -out: - return ret; -} - -int asix_get_phy_addr(struct usbnet *dev) -{ - /* return the address of the internal phy */ - return asix_read_phy_addr(dev, 1); -} - - -int asix_sw_reset(struct usbnet *dev, u8 flags) -{ - int ret; - - ret = asix_write_cmd(dev, AX_CMD_SW_RESET, flags, 0, 0, NULL); - if (ret < 0) - netdev_err(dev->net, "Failed to send software reset: %02x\n", ret); - - return ret; -} - -u16 asix_read_rx_ctl(struct usbnet *dev) -{ - __le16 v; - int ret = asix_read_cmd(dev, AX_CMD_READ_RX_CTL, 0, 0, 2, &v); - - if (ret < 0) { - netdev_err(dev->net, "Error reading RX_CTL register: %02x\n", ret); - goto out; - } - ret = le16_to_cpu(v); -out: - return ret; -} - -int asix_write_rx_ctl(struct usbnet *dev, u16 mode) -{ - int ret; - - netdev_dbg(dev->net, "asix_write_rx_ctl() - mode = 0x%04x\n", mode); - ret = asix_write_cmd(dev, AX_CMD_WRITE_RX_CTL, mode, 0, 0, NULL); - if (ret < 0) - netdev_err(dev->net, "Failed to write RX_CTL mode to 0x%04x: %02x\n", - mode, ret); - - return ret; -} - -u16 asix_read_medium_status(struct usbnet *dev) -{ - __le16 v; - int ret = asix_read_cmd(dev, AX_CMD_READ_MEDIUM_STATUS, 0, 0, 2, &v); - - if (ret < 0) { - netdev_err(dev->net, "Error reading Medium Status register: %02x\n", - ret); - return ret; /* TODO: callers not checking for error ret */ - } - - return le16_to_cpu(v); - -} - -int asix_write_medium_mode(struct usbnet *dev, u16 mode) -{ - int ret; - - netdev_dbg(dev->net, "asix_write_medium_mode() - mode = 0x%04x\n", mode); - ret = asix_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE, mode, 0, 0, NULL); - if (ret < 0) - netdev_err(dev->net, "Failed to write Medium Mode mode to 0x%04x: %02x\n", - mode, ret); - - return ret; -} - -int asix_write_gpio(struct usbnet *dev, u16 value, int sleep) -{ - int ret; - - netdev_dbg(dev->net, "asix_write_gpio() - value = 0x%04x\n", value); - ret = asix_write_cmd(dev, AX_CMD_WRITE_GPIOS, value, 0, 0, NULL); - if (ret < 0) - netdev_err(dev->net, "Failed to write GPIO value 0x%04x: %02x\n", - value, ret); - - if (sleep) - msleep(sleep); - - return ret; -} - -/* - * AX88772 & AX88178 have a 16-bit RX_CTL value - */ -void asix_set_multicast(struct net_device *net) -{ - struct usbnet *dev = netdev_priv(net); - struct asix_data *data = (struct asix_data *)&dev->data; - u16 rx_ctl = AX_DEFAULT_RX_CTL; - - if (net->flags & IFF_PROMISC) { - rx_ctl |= AX_RX_CTL_PRO; - } else if (net->flags & IFF_ALLMULTI || - netdev_mc_count(net) > AX_MAX_MCAST) { - rx_ctl |= AX_RX_CTL_AMALL; - } else if (netdev_mc_empty(net)) { - /* just broadcast and directed */ - } else { - /* We use the 20 byte dev->data - * for our 8 byte filter buffer - * to avoid allocating memory that - * is tricky to free later */ - struct netdev_hw_addr *ha; - u32 crc_bits; - - memset(data->multi_filter, 0, AX_MCAST_FILTER_SIZE); - - /* Build the multicast hash filter. */ - netdev_for_each_mc_addr(ha, net) { - crc_bits = ether_crc(ETH_ALEN, ha->addr) >> 26; - data->multi_filter[crc_bits >> 3] |= - 1 << (crc_bits & 7); - } - - asix_write_cmd_async(dev, AX_CMD_WRITE_MULTI_FILTER, 0, 0, - AX_MCAST_FILTER_SIZE, data->multi_filter); - - rx_ctl |= AX_RX_CTL_AM; - } - - asix_write_cmd_async(dev, AX_CMD_WRITE_RX_CTL, rx_ctl, 0, 0, NULL); -} - -int asix_mdio_read(struct net_device *netdev, int phy_id, int loc) -{ - struct usbnet *dev = netdev_priv(netdev); - __le16 res; - - mutex_lock(&dev->phy_mutex); - asix_set_sw_mii(dev); - asix_read_cmd(dev, AX_CMD_READ_MII_REG, phy_id, - (__u16)loc, 2, &res); - asix_set_hw_mii(dev); - mutex_unlock(&dev->phy_mutex); - - netdev_dbg(dev->net, "asix_mdio_read() phy_id=0x%02x, loc=0x%02x, returns=0x%04x\n", - phy_id, loc, le16_to_cpu(res)); - - return le16_to_cpu(res); -} - -void asix_mdio_write(struct net_device *netdev, int phy_id, int loc, int val) -{ - struct usbnet *dev = netdev_priv(netdev); - __le16 res = cpu_to_le16(val); - - netdev_dbg(dev->net, "asix_mdio_write() phy_id=0x%02x, loc=0x%02x, val=0x%04x\n", - phy_id, loc, val); - mutex_lock(&dev->phy_mutex); - asix_set_sw_mii(dev); - asix_write_cmd(dev, AX_CMD_WRITE_MII_REG, phy_id, (__u16)loc, 2, &res); - asix_set_hw_mii(dev); - mutex_unlock(&dev->phy_mutex); -} - -void asix_get_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo) -{ - struct usbnet *dev = netdev_priv(net); - u8 opt; - - if (asix_read_cmd(dev, AX_CMD_READ_MONITOR_MODE, 0, 0, 1, &opt) < 0) { - wolinfo->supported = 0; - wolinfo->wolopts = 0; - return; - } - wolinfo->supported = WAKE_PHY | WAKE_MAGIC; - wolinfo->wolopts = 0; - if (opt & AX_MONITOR_LINK) - wolinfo->wolopts |= WAKE_PHY; - if (opt & AX_MONITOR_MAGIC) - wolinfo->wolopts |= WAKE_MAGIC; -} - -int asix_set_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo) -{ - struct usbnet *dev = netdev_priv(net); - u8 opt = 0; - - if (wolinfo->wolopts & WAKE_PHY) - opt |= AX_MONITOR_LINK; - if (wolinfo->wolopts & WAKE_MAGIC) - opt |= AX_MONITOR_MAGIC; - - if (asix_write_cmd(dev, AX_CMD_WRITE_MONITOR_MODE, - opt, 0, 0, NULL) < 0) - return -EINVAL; - - return 0; -} - -int asix_get_eeprom_len(struct net_device *net) -{ - struct usbnet *dev = netdev_priv(net); - struct asix_data *data = (struct asix_data *)&dev->data; - - return data->eeprom_len; -} - -int asix_get_eeprom(struct net_device *net, struct ethtool_eeprom *eeprom, - u8 *data) -{ - struct usbnet *dev = netdev_priv(net); - __le16 *ebuf = (__le16 *)data; - int i; - - /* Crude hack to ensure that we don't overwrite memory - * if an odd length is supplied - */ - if (eeprom->len % 2) - return -EINVAL; - - eeprom->magic = AX_EEPROM_MAGIC; - - /* ax8817x returns 2 bytes from eeprom on read */ - for (i=0; i < eeprom->len / 2; i++) { - if (asix_read_cmd(dev, AX_CMD_READ_EEPROM, - eeprom->offset + i, 0, 2, &ebuf[i]) < 0) - return -EINVAL; - } - return 0; -} - -void asix_get_drvinfo(struct net_device *net, struct ethtool_drvinfo *info) -{ - struct usbnet *dev = netdev_priv(net); - struct asix_data *data = (struct asix_data *)&dev->data; - - /* Inherit standard device info */ - usbnet_get_drvinfo(net, info); - strncpy (info->driver, DRIVER_NAME, sizeof info->driver); - strncpy (info->version, DRIVER_VERSION, sizeof info->version); - info->eedump_len = data->eeprom_len; -} - -int asix_set_mac_address(struct net_device *net, void *p) -{ - struct usbnet *dev = netdev_priv(net); - struct asix_data *data = (struct asix_data *)&dev->data; - struct sockaddr *addr = p; - - if (netif_running(net)) - return -EBUSY; - if (!is_valid_ether_addr(addr->sa_data)) - return -EADDRNOTAVAIL; - - memcpy(net->dev_addr, addr->sa_data, ETH_ALEN); - - /* We use the 20 byte dev->data - * for our 6 byte mac buffer - * to avoid allocating memory that - * is tricky to free later */ - memcpy(data->mac_addr, addr->sa_data, ETH_ALEN); - asix_write_cmd_async(dev, AX_CMD_WRITE_NODE_ID, 0, 0, ETH_ALEN, - data->mac_addr); - - return 0; -} diff --git a/trunk/drivers/net/usb/ax88172a.c b/trunk/drivers/net/usb/ax88172a.c deleted file mode 100644 index 534a144bd9e7..000000000000 --- a/trunk/drivers/net/usb/ax88172a.c +++ /dev/null @@ -1,415 +0,0 @@ -/* - * ASIX AX88172A based USB 2.0 Ethernet Devices - * Copyright (C) 2012 OMICRON electronics GmbH - * - * Supports external PHYs via phylib. Based on the driver for the - * AX88772. Original copyrights follow: - * - * Copyright (C) 2003-2006 David Hollis - * Copyright (C) 2005 Phil Chang - * Copyright (C) 2006 James Painter - * Copyright (c) 2002-2003 TiVo Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "asix.h" -#include - -struct ax88172a_private { - struct mii_bus *mdio; - struct phy_device *phydev; - char phy_name[20]; - u16 phy_addr; - u16 oldmode; - int use_embdphy; -}; - -/* MDIO read and write wrappers for phylib */ -static int asix_mdio_bus_read(struct mii_bus *bus, int phy_id, int regnum) -{ - return asix_mdio_read(((struct usbnet *)bus->priv)->net, phy_id, - regnum); -} - -static int asix_mdio_bus_write(struct mii_bus *bus, int phy_id, int regnum, - u16 val) -{ - asix_mdio_write(((struct usbnet *)bus->priv)->net, phy_id, regnum, val); - return 0; -} - -static int ax88172a_ioctl(struct net_device *net, struct ifreq *rq, int cmd) -{ - if (!netif_running(net)) - return -EINVAL; - - if (!net->phydev) - return -ENODEV; - - return phy_mii_ioctl(net->phydev, rq, cmd); -} - -/* set MAC link settings according to information from phylib */ -static void ax88172a_adjust_link(struct net_device *netdev) -{ - struct phy_device *phydev = netdev->phydev; - struct usbnet *dev = netdev_priv(netdev); - struct ax88172a_private *priv = dev->driver_priv; - u16 mode = 0; - - if (phydev->link) { - mode = AX88772_MEDIUM_DEFAULT; - - if (phydev->duplex == DUPLEX_HALF) - mode &= ~AX_MEDIUM_FD; - - if (phydev->speed != SPEED_100) - mode &= ~AX_MEDIUM_PS; - } - - if (mode != priv->oldmode) { - asix_write_medium_mode(dev, mode); - priv->oldmode = mode; - netdev_dbg(netdev, "speed %u duplex %d, setting mode to 0x%04x\n", - phydev->speed, phydev->duplex, mode); - phy_print_status(phydev); - } -} - -static void ax88172a_status(struct usbnet *dev, struct urb *urb) -{ - /* link changes are detected by polling the phy */ -} - -/* use phylib infrastructure */ -static int ax88172a_init_mdio(struct usbnet *dev) -{ - struct ax88172a_private *priv = dev->driver_priv; - int ret, i; - - priv->mdio = mdiobus_alloc(); - if (!priv->mdio) { - netdev_err(dev->net, "Could not allocate MDIO bus\n"); - return -ENOMEM; - } - - priv->mdio->priv = (void *)dev; - priv->mdio->read = &asix_mdio_bus_read; - priv->mdio->write = &asix_mdio_bus_write; - priv->mdio->name = "Asix MDIO Bus"; - /* mii bus name is usb-- */ - snprintf(priv->mdio->id, MII_BUS_ID_SIZE, "usb-%03d:%03d", - dev->udev->bus->busnum, dev->udev->devnum); - - priv->mdio->irq = kzalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL); - if (!priv->mdio->irq) { - netdev_err(dev->net, "Could not allocate mdio->irq\n"); - ret = -ENOMEM; - goto mfree; - } - for (i = 0; i < PHY_MAX_ADDR; i++) - priv->mdio->irq[i] = PHY_POLL; - - ret = mdiobus_register(priv->mdio); - if (ret) { - netdev_err(dev->net, "Could not register MDIO bus\n"); - goto ifree; - } - - netdev_info(dev->net, "registered mdio bus %s\n", priv->mdio->id); - return 0; - -ifree: - kfree(priv->mdio->irq); -mfree: - mdiobus_free(priv->mdio); - return ret; -} - -static void ax88172a_remove_mdio(struct usbnet *dev) -{ - struct ax88172a_private *priv = dev->driver_priv; - - netdev_info(dev->net, "deregistering mdio bus %s\n", priv->mdio->id); - mdiobus_unregister(priv->mdio); - kfree(priv->mdio->irq); - mdiobus_free(priv->mdio); -} - -static const struct net_device_ops ax88172a_netdev_ops = { - .ndo_open = usbnet_open, - .ndo_stop = usbnet_stop, - .ndo_start_xmit = usbnet_start_xmit, - .ndo_tx_timeout = usbnet_tx_timeout, - .ndo_change_mtu = usbnet_change_mtu, - .ndo_set_mac_address = asix_set_mac_address, - .ndo_validate_addr = eth_validate_addr, - .ndo_do_ioctl = ax88172a_ioctl, - .ndo_set_rx_mode = asix_set_multicast, -}; - -int ax88172a_get_settings(struct net_device *net, struct ethtool_cmd *cmd) -{ - if (!net->phydev) - return -ENODEV; - - return phy_ethtool_gset(net->phydev, cmd); -} - -int ax88172a_set_settings(struct net_device *net, struct ethtool_cmd *cmd) -{ - if (!net->phydev) - return -ENODEV; - - return phy_ethtool_sset(net->phydev, cmd); -} - -int ax88172a_nway_reset(struct net_device *net) -{ - if (!net->phydev) - return -ENODEV; - - return phy_start_aneg(net->phydev); -} - -static const struct ethtool_ops ax88172a_ethtool_ops = { - .get_drvinfo = asix_get_drvinfo, - .get_link = usbnet_get_link, - .get_msglevel = usbnet_get_msglevel, - .set_msglevel = usbnet_set_msglevel, - .get_wol = asix_get_wol, - .set_wol = asix_set_wol, - .get_eeprom_len = asix_get_eeprom_len, - .get_eeprom = asix_get_eeprom, - .get_settings = ax88172a_get_settings, - .set_settings = ax88172a_set_settings, - .nway_reset = ax88172a_nway_reset, -}; - -static int ax88172a_reset_phy(struct usbnet *dev, int embd_phy) -{ - int ret; - - ret = asix_sw_reset(dev, AX_SWRESET_IPPD); - if (ret < 0) - goto err; - - msleep(150); - ret = asix_sw_reset(dev, AX_SWRESET_CLEAR); - if (ret < 0) - goto err; - - msleep(150); - - ret = asix_sw_reset(dev, embd_phy ? AX_SWRESET_IPRL : AX_SWRESET_IPPD); - if (ret < 0) - goto err; - - return 0; - -err: - return ret; -} - - -static int ax88172a_bind(struct usbnet *dev, struct usb_interface *intf) -{ - int ret; - struct asix_data *data = (struct asix_data *)&dev->data; - u8 buf[ETH_ALEN]; - struct ax88172a_private *priv; - - data->eeprom_len = AX88772_EEPROM_LEN; - - usbnet_get_endpoints(dev, intf); - - priv = kzalloc(sizeof(*priv), GFP_KERNEL); - if (!priv) { - netdev_err(dev->net, "Could not allocate memory for private data\n"); - return -ENOMEM; - } - dev->driver_priv = priv; - - /* Get the MAC address */ - ret = asix_read_cmd(dev, AX_CMD_READ_NODE_ID, 0, 0, ETH_ALEN, buf); - if (ret < 0) { - netdev_err(dev->net, "Failed to read MAC address: %d\n", ret); - goto free; - } - memcpy(dev->net->dev_addr, buf, ETH_ALEN); - - dev->net->netdev_ops = &ax88172a_netdev_ops; - dev->net->ethtool_ops = &ax88172a_ethtool_ops; - - /* are we using the internal or the external phy? */ - ret = asix_read_cmd(dev, AX_CMD_SW_PHY_STATUS, 0, 0, 1, buf); - if (ret < 0) { - netdev_err(dev->net, "Failed to read software interface selection register: %d\n", - ret); - goto free; - } - - netdev_dbg(dev->net, "AX_CMD_SW_PHY_STATUS = 0x%02x\n", buf[0]); - switch (buf[0] & AX_PHY_SELECT_MASK) { - case AX_PHY_SELECT_INTERNAL: - netdev_dbg(dev->net, "use internal phy\n"); - priv->use_embdphy = 1; - break; - case AX_PHY_SELECT_EXTERNAL: - netdev_dbg(dev->net, "use external phy\n"); - priv->use_embdphy = 0; - break; - default: - netdev_err(dev->net, "Interface mode not supported by driver\n"); - goto free; - } - - priv->phy_addr = asix_read_phy_addr(dev, priv->use_embdphy); - ax88172a_reset_phy(dev, priv->use_embdphy); - - /* Asix framing packs multiple eth frames into a 2K usb bulk transfer */ - if (dev->driver_info->flags & FLAG_FRAMING_AX) { - /* hard_mtu is still the default - the device does not support - jumbo eth frames */ - dev->rx_urb_size = 2048; - } - - /* init MDIO bus */ - ret = ax88172a_init_mdio(dev); - if (ret) - goto free; - - return 0; - -free: - kfree(priv); - return ret; -} - -static int ax88172a_stop(struct usbnet *dev) -{ - struct ax88172a_private *priv = dev->driver_priv; - - netdev_dbg(dev->net, "Stopping interface\n"); - - if (priv->phydev) { - netdev_info(dev->net, "Disconnecting from phy %s\n", - priv->phy_name); - phy_stop(priv->phydev); - phy_disconnect(priv->phydev); - } - - return 0; -} - -static void ax88172a_unbind(struct usbnet *dev, struct usb_interface *intf) -{ - struct ax88172a_private *priv = dev->driver_priv; - - ax88172a_remove_mdio(dev); - kfree(priv); -} - -static int ax88172a_reset(struct usbnet *dev) -{ - struct asix_data *data = (struct asix_data *)&dev->data; - struct ax88172a_private *priv = dev->driver_priv; - int ret; - u16 rx_ctl; - - ax88172a_reset_phy(dev, priv->use_embdphy); - - msleep(150); - rx_ctl = asix_read_rx_ctl(dev); - netdev_dbg(dev->net, "RX_CTL is 0x%04x after software reset\n", rx_ctl); - ret = asix_write_rx_ctl(dev, 0x0000); - if (ret < 0) - goto out; - - rx_ctl = asix_read_rx_ctl(dev); - netdev_dbg(dev->net, "RX_CTL is 0x%04x setting to 0x0000\n", rx_ctl); - - msleep(150); - - ret = asix_write_cmd(dev, AX_CMD_WRITE_IPG0, - AX88772_IPG0_DEFAULT | AX88772_IPG1_DEFAULT, - AX88772_IPG2_DEFAULT, 0, NULL); - if (ret < 0) { - netdev_err(dev->net, "Write IPG,IPG1,IPG2 failed: %d\n", ret); - goto out; - } - - /* Rewrite MAC address */ - memcpy(data->mac_addr, dev->net->dev_addr, ETH_ALEN); - ret = asix_write_cmd(dev, AX_CMD_WRITE_NODE_ID, 0, 0, ETH_ALEN, - data->mac_addr); - if (ret < 0) - goto out; - - /* Set RX_CTL to default values with 2k buffer, and enable cactus */ - ret = asix_write_rx_ctl(dev, AX_DEFAULT_RX_CTL); - if (ret < 0) - goto out; - - rx_ctl = asix_read_rx_ctl(dev); - netdev_dbg(dev->net, "RX_CTL is 0x%04x after all initializations\n", - rx_ctl); - - rx_ctl = asix_read_medium_status(dev); - netdev_dbg(dev->net, "Medium Status is 0x%04x after all initializations\n", - rx_ctl); - - /* Connect to PHY */ - snprintf(priv->phy_name, 20, PHY_ID_FMT, - priv->mdio->id, priv->phy_addr); - - priv->phydev = phy_connect(dev->net, priv->phy_name, - &ax88172a_adjust_link, - 0, PHY_INTERFACE_MODE_MII); - if (IS_ERR(priv->phydev)) { - netdev_err(dev->net, "Could not connect to PHY device %s\n", - priv->phy_name); - ret = PTR_ERR(priv->phydev); - goto out; - } - - netdev_info(dev->net, "Connected to phy %s\n", priv->phy_name); - - /* During power-up, the AX88172A set the power down (BMCR_PDOWN) - * bit of the PHY. Bring the PHY up again. - */ - genphy_resume(priv->phydev); - phy_start(priv->phydev); - - return 0; - -out: - return ret; - -} - -const struct driver_info ax88172a_info = { - .description = "ASIX AX88172A USB 2.0 Ethernet", - .bind = ax88172a_bind, - .reset = ax88172a_reset, - .stop = ax88172a_stop, - .unbind = ax88172a_unbind, - .status = ax88172a_status, - .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_LINK_INTR | - FLAG_MULTI_PACKET, - .rx_fixup = asix_rx_fixup, - .tx_fixup = asix_tx_fixup, -}; diff --git a/trunk/drivers/net/usb/qmi_wwan.c b/trunk/drivers/net/usb/qmi_wwan.c index 85c983d52527..b9cc5f703d7d 100644 --- a/trunk/drivers/net/usb/qmi_wwan.c +++ b/trunk/drivers/net/usb/qmi_wwan.c @@ -374,15 +374,6 @@ static const struct driver_info qmi_wwan_force_int1 = { .data = BIT(1), /* interface whitelist bitmap */ }; -static const struct driver_info qmi_wwan_force_int2 = { - .description = "Qualcomm WWAN/QMI device", - .flags = FLAG_WWAN, - .bind = qmi_wwan_bind_shared, - .unbind = qmi_wwan_unbind, - .manage_power = qmi_wwan_manage_power, - .data = BIT(2), /* interface whitelist bitmap */ -}; - static const struct driver_info qmi_wwan_force_int3 = { .description = "Qualcomm WWAN/QMI device", .flags = FLAG_WWAN, @@ -535,15 +526,6 @@ static const struct usb_device_id products[] = { .bInterfaceProtocol = 0xff, .driver_info = (unsigned long)&qmi_wwan_force_int4, }, - { /* ZTE MF60 */ - .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, - .idVendor = 0x19d2, - .idProduct = 0x1402, - .bInterfaceClass = 0xff, - .bInterfaceSubClass = 0xff, - .bInterfaceProtocol = 0xff, - .driver_info = (unsigned long)&qmi_wwan_force_int2, - }, { /* Sierra Wireless MC77xx in QMI mode */ .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, .idVendor = 0x1199, diff --git a/trunk/drivers/net/usb/smsc75xx.c b/trunk/drivers/net/usb/smsc75xx.c index 6c0c5b76fc41..1c6e51588da7 100644 --- a/trunk/drivers/net/usb/smsc75xx.c +++ b/trunk/drivers/net/usb/smsc75xx.c @@ -616,7 +616,7 @@ static void smsc75xx_init_mac_address(struct usbnet *dev) /* no eeprom, or eeprom values are invalid. generate random MAC */ eth_hw_addr_random(dev->net); - netif_dbg(dev, ifup, dev->net, "MAC address set to eth_random_addr"); + netif_dbg(dev, ifup, dev->net, "MAC address set to random_ether_addr"); } static int smsc75xx_set_mac_address(struct usbnet *dev) diff --git a/trunk/drivers/net/usb/smsc95xx.c b/trunk/drivers/net/usb/smsc95xx.c index 25cc3a15a4ea..b1112e753859 100644 --- a/trunk/drivers/net/usb/smsc95xx.c +++ b/trunk/drivers/net/usb/smsc95xx.c @@ -578,36 +578,6 @@ static int smsc95xx_ethtool_set_eeprom(struct net_device *netdev, return smsc95xx_write_eeprom(dev, ee->offset, ee->len, data); } -static int smsc95xx_ethtool_getregslen(struct net_device *netdev) -{ - /* all smsc95xx registers */ - return COE_CR - ID_REV + 1; -} - -static void -smsc95xx_ethtool_getregs(struct net_device *netdev, struct ethtool_regs *regs, - void *buf) -{ - struct usbnet *dev = netdev_priv(netdev); - unsigned int i, j; - int retval; - u32 *data = buf; - - retval = smsc95xx_read_reg(dev, ID_REV, ®s->version); - if (retval < 0) { - netdev_warn(netdev, "REGS: cannot read ID_REV\n"); - return; - } - - for (i = ID_REV, j = 0; i <= COE_CR; i += (sizeof(u32)), j++) { - retval = smsc95xx_read_reg(dev, i, &data[j]); - if (retval < 0) { - netdev_warn(netdev, "REGS: cannot read reg[%x]\n", i); - return; - } - } -} - static const struct ethtool_ops smsc95xx_ethtool_ops = { .get_link = usbnet_get_link, .nway_reset = usbnet_nway_reset, @@ -619,8 +589,6 @@ static const struct ethtool_ops smsc95xx_ethtool_ops = { .get_eeprom_len = smsc95xx_ethtool_get_eeprom_len, .get_eeprom = smsc95xx_ethtool_get_eeprom, .set_eeprom = smsc95xx_ethtool_set_eeprom, - .get_regs_len = smsc95xx_ethtool_getregslen, - .get_regs = smsc95xx_ethtool_getregs, }; static int smsc95xx_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd) @@ -647,7 +615,7 @@ static void smsc95xx_init_mac_address(struct usbnet *dev) /* no eeprom, or eeprom values are invalid. generate random MAC */ eth_hw_addr_random(dev->net); - netif_dbg(dev, ifup, dev->net, "MAC address set to eth_random_addr\n"); + netif_dbg(dev, ifup, dev->net, "MAC address set to random_ether_addr\n"); } static int smsc95xx_set_mac_address(struct usbnet *dev) diff --git a/trunk/drivers/net/usb/usbnet.c b/trunk/drivers/net/usb/usbnet.c index 8531c1caac28..e92c057f794a 100644 --- a/trunk/drivers/net/usb/usbnet.c +++ b/trunk/drivers/net/usb/usbnet.c @@ -1593,7 +1593,7 @@ static int __init usbnet_init(void) BUILD_BUG_ON( FIELD_SIZEOF(struct sk_buff, cb) < sizeof(struct skb_data)); - eth_random_addr(node_id); + random_ether_addr(node_id); return 0; } module_init(usbnet_init); diff --git a/trunk/drivers/net/wimax/i2400m/Kconfig b/trunk/drivers/net/wimax/i2400m/Kconfig index 71453db14258..672de18a776c 100644 --- a/trunk/drivers/net/wimax/i2400m/Kconfig +++ b/trunk/drivers/net/wimax/i2400m/Kconfig @@ -7,6 +7,9 @@ config WIMAX_I2400M comment "Enable USB support to see WiMAX USB drivers" depends on USB = n +comment "Enable MMC support to see WiMAX SDIO drivers" + depends on MMC = n + config WIMAX_I2400M_USB tristate "Intel Wireless WiMAX Connection 2400 over USB (including 5x50)" depends on WIMAX && USB @@ -18,6 +21,25 @@ config WIMAX_I2400M_USB If unsure, it is safe to select M (module). +config WIMAX_I2400M_SDIO + tristate "Intel Wireless WiMAX Connection 2400 over SDIO" + depends on WIMAX && MMC + select WIMAX_I2400M + help + Select if you have a device based on the Intel WiMAX + Connection 2400 over SDIO. + + If unsure, it is safe to select M (module). + +config WIMAX_IWMC3200_SDIO + bool "Intel Wireless Multicom WiMAX Connection 3200 over SDIO (EXPERIMENTAL)" + depends on WIMAX_I2400M_SDIO + depends on EXPERIMENTAL + select IWMC3200TOP + help + Select if you have a device based on the Intel Multicom WiMAX + Connection 3200 over SDIO. + config WIMAX_I2400M_DEBUG_LEVEL int "WiMAX i2400m debug level" depends on WIMAX_I2400M diff --git a/trunk/drivers/net/wimax/i2400m/Makefile b/trunk/drivers/net/wimax/i2400m/Makefile index f6d19c348082..5d9e018d31af 100644 --- a/trunk/drivers/net/wimax/i2400m/Makefile +++ b/trunk/drivers/net/wimax/i2400m/Makefile @@ -1,6 +1,7 @@ obj-$(CONFIG_WIMAX_I2400M) += i2400m.o obj-$(CONFIG_WIMAX_I2400M_USB) += i2400m-usb.o +obj-$(CONFIG_WIMAX_I2400M_SDIO) += i2400m-sdio.o i2400m-y := \ control.o \ @@ -20,3 +21,10 @@ i2400m-usb-y := \ usb-tx.o \ usb-rx.o \ usb.o + + +i2400m-sdio-y := \ + sdio.o \ + sdio-tx.o \ + sdio-fw.o \ + sdio-rx.o diff --git a/trunk/drivers/net/wimax/i2400m/driver.c b/trunk/drivers/net/wimax/i2400m/driver.c index 025426132754..47cae7150bc1 100644 --- a/trunk/drivers/net/wimax/i2400m/driver.c +++ b/trunk/drivers/net/wimax/i2400m/driver.c @@ -754,7 +754,8 @@ EXPORT_SYMBOL_GPL(i2400m_error_recovery); /* * Alloc the command and ack buffers for boot mode * - * Get the buffers needed to deal with boot mode messages. + * Get the buffers needed to deal with boot mode messages. These + * buffers need to be allocated before the sdio receive irq is setup. */ static int i2400m_bm_buf_alloc(struct i2400m *i2400m) @@ -896,7 +897,7 @@ int i2400m_setup(struct i2400m *i2400m, enum i2400m_bri bm_flags) result = i2400m_read_mac_addr(i2400m); if (result < 0) goto error_read_mac_addr; - eth_random_addr(i2400m->src_mac_addr); + random_ether_addr(i2400m->src_mac_addr); i2400m->pm_notifier.notifier_call = i2400m_pm_notifier; register_pm_notifier(&i2400m->pm_notifier); diff --git a/trunk/drivers/net/wimax/i2400m/fw.c b/trunk/drivers/net/wimax/i2400m/fw.c index 283237f6f074..d09e44970e63 100644 --- a/trunk/drivers/net/wimax/i2400m/fw.c +++ b/trunk/drivers/net/wimax/i2400m/fw.c @@ -51,7 +51,8 @@ * firmware. Normal hardware takes only signed firmware. * * On boot mode, in USB, we write to the device using the bulk out - * endpoint and read from it in the notification endpoint. + * endpoint and read from it in the notification endpoint. In SDIO we + * talk to it via the write address and read from the read address. * * Upon entrance to boot mode, the device sends (preceded with a few * zero length packets (ZLPs) on the notification endpoint in USB) a diff --git a/trunk/drivers/net/wimax/i2400m/i2400m-sdio.h b/trunk/drivers/net/wimax/i2400m/i2400m-sdio.h new file mode 100644 index 000000000000..1d63ffdedfde --- /dev/null +++ b/trunk/drivers/net/wimax/i2400m/i2400m-sdio.h @@ -0,0 +1,157 @@ +/* + * Intel Wireless WiMAX Connection 2400m + * SDIO-specific i2400m driver definitions + * + * + * Copyright (C) 2007-2008 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * + * Intel Corporation + * Brian Bian + * Dirk Brandewie + * Inaky Perez-Gonzalez + * Yanir Lubetkin + * - Initial implementation + * + * + * This driver implements the bus-specific part of the i2400m for + * SDIO. Check i2400m.h for a generic driver description. + * + * ARCHITECTURE + * + * This driver sits under the bus-generic i2400m driver, providing the + * connection to the device. + * + * When probed, all the function pointers are setup and then the + * bus-generic code called. The generic driver will then use the + * provided pointers for uploading firmware (i2400ms_bus_bm*() in + * sdio-fw.c) and then setting up the device (i2400ms_dev_*() in + * sdio.c). + * + * Once firmware is uploaded, TX functions (sdio-tx.c) are called when + * data is ready for transmission in the TX fifo; then the SDIO IRQ is + * fired and data is available (sdio-rx.c), it is sent to the generic + * driver for processing with i2400m_rx. + */ + +#ifndef __I2400M_SDIO_H__ +#define __I2400M_SDIO_H__ + +#include "i2400m.h" + +/* Host-Device interface for SDIO */ +enum { + I2400M_SDIO_BOOT_RETRIES = 3, + I2400MS_BLK_SIZE = 256, + I2400MS_PL_SIZE_MAX = 0x3E00, + + I2400MS_DATA_ADDR = 0x0, + I2400MS_INTR_STATUS_ADDR = 0x13, + I2400MS_INTR_CLEAR_ADDR = 0x13, + I2400MS_INTR_ENABLE_ADDR = 0x14, + I2400MS_INTR_GET_SIZE_ADDR = 0x2C, + /* The number of ticks to wait for the device to signal that + * it is ready */ + I2400MS_INIT_SLEEP_INTERVAL = 100, + /* How long to wait for the device to settle after reset */ + I2400MS_SETTLE_TIME = 40, + /* The number of msec to wait for IOR after sending IOE */ + IWMC3200_IOR_TIMEOUT = 10, +}; + + +/** + * struct i2400ms - descriptor for a SDIO connected i2400m + * + * @i2400m: bus-generic i2400m implementation; has to be first (see + * it's documentation in i2400m.h). + * + * @func: pointer to our SDIO function + * + * @tx_worker: workqueue struct used to TX data when the bus-generic + * code signals packets are pending for transmission to the device. + * + * @tx_workqueue: workqeueue used for data TX; we don't use the + * system's workqueue as that might cause deadlocks with code in + * the bus-generic driver. The read/write operation to the queue + * is protected with spinlock (tx_lock in struct i2400m) to avoid + * the queue being destroyed in the middle of a the queue read/write + * operation. + * + * @debugfs_dentry: dentry for the SDIO specific debugfs files + * + * Note this value is set to NULL upon destruction; this is + * because some routinges use it to determine if we are inside the + * probe() path or some other path. When debugfs is disabled, + * creation sets the dentry to '(void*) -ENODEV', which is valid + * for the test. + */ +struct i2400ms { + struct i2400m i2400m; /* FIRST! See doc */ + struct sdio_func *func; + + struct work_struct tx_worker; + struct workqueue_struct *tx_workqueue; + char tx_wq_name[32]; + + struct dentry *debugfs_dentry; + + wait_queue_head_t bm_wfa_wq; + int bm_wait_result; + size_t bm_ack_size; + + /* Device is any of the iwmc3200 SKUs */ + unsigned iwmc3200:1; +}; + + +static inline +void i2400ms_init(struct i2400ms *i2400ms) +{ + i2400m_init(&i2400ms->i2400m); +} + + +extern int i2400ms_rx_setup(struct i2400ms *); +extern void i2400ms_rx_release(struct i2400ms *); + +extern int i2400ms_tx_setup(struct i2400ms *); +extern void i2400ms_tx_release(struct i2400ms *); +extern void i2400ms_bus_tx_kick(struct i2400m *); + +extern ssize_t i2400ms_bus_bm_cmd_send(struct i2400m *, + const struct i2400m_bootrom_header *, + size_t, int); +extern ssize_t i2400ms_bus_bm_wait_for_ack(struct i2400m *, + struct i2400m_bootrom_header *, + size_t); +extern void i2400ms_bus_bm_release(struct i2400m *); +extern int i2400ms_bus_bm_setup(struct i2400m *); + +#endif /* #ifndef __I2400M_SDIO_H__ */ diff --git a/trunk/drivers/net/wimax/i2400m/i2400m.h b/trunk/drivers/net/wimax/i2400m/i2400m.h index 79c6505b5c20..c806d4550212 100644 --- a/trunk/drivers/net/wimax/i2400m/i2400m.h +++ b/trunk/drivers/net/wimax/i2400m/i2400m.h @@ -46,7 +46,7 @@ * - bus generic driver (this part) * * The bus specific driver sets up stuff specific to the bus the - * device is connected to (USB, PCI, tam-tam...non-authoritative + * device is connected to (USB, SDIO, PCI, tam-tam...non-authoritative * nor binding list) which is basically the device-model management * (probe/disconnect, etc), moving data from device to kernel and * back, doing the power saving details and reseting the device. @@ -238,13 +238,14 @@ struct i2400m_barker_db; * amount needed for loading firmware, where us dev_start/stop setup * the rest needed to do full data/control traffic. * - * @bus_tx_block_size: [fill] USB imposes a 16 block size, but other - * busses will differ. So we have a tx_blk_size variable that the - * bus layer sets to tell the engine how much of that we need. + * @bus_tx_block_size: [fill] SDIO imposes a 256 block size, USB 16, + * so we have a tx_blk_size variable that the bus layer sets to + * tell the engine how much of that we need. * * @bus_tx_room_min: [fill] Minimum room required while allocating - * TX queue's buffer space for message header. USB requires - * 16 bytes. Refer to bus specific driver code for details. + * TX queue's buffer space for message header. SDIO requires + * 224 bytes and USB 16 bytes. Refer bus specific driver code + * for details. * * @bus_pl_size_max: [fill] Maximum payload size. * diff --git a/trunk/drivers/net/wimax/i2400m/sdio-debug-levels.h b/trunk/drivers/net/wimax/i2400m/sdio-debug-levels.h new file mode 100644 index 000000000000..c51998741301 --- /dev/null +++ b/trunk/drivers/net/wimax/i2400m/sdio-debug-levels.h @@ -0,0 +1,22 @@ +/* + * debug levels control file for the i2400m module's + */ +#ifndef __debug_levels__h__ +#define __debug_levels__h__ + +/* Maximum compile and run time debug level for all submodules */ +#define D_MODULENAME i2400m_sdio +#define D_MASTER CONFIG_WIMAX_I2400M_DEBUG_LEVEL + +#include + +/* List of all the enabled modules */ +enum d_module { + D_SUBMODULE_DECLARE(main), + D_SUBMODULE_DECLARE(tx), + D_SUBMODULE_DECLARE(rx), + D_SUBMODULE_DECLARE(fw) +}; + + +#endif /* #ifndef __debug_levels__h__ */ diff --git a/trunk/drivers/net/wimax/i2400m/sdio-fw.c b/trunk/drivers/net/wimax/i2400m/sdio-fw.c new file mode 100644 index 000000000000..8e025418f5be --- /dev/null +++ b/trunk/drivers/net/wimax/i2400m/sdio-fw.c @@ -0,0 +1,210 @@ +/* + * Intel Wireless WiMAX Connection 2400m + * Firmware uploader's SDIO specifics + * + * + * Copyright (C) 2007-2008 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * + * Intel Corporation + * Yanir Lubetkin + * Inaky Perez-Gonzalez + * - Initial implementation + * + * Inaky Perez-Gonzalez + * - Bus generic/specific split for USB + * + * Dirk Brandewie + * - Initial implementation for SDIO + * + * Inaky Perez-Gonzalez + * - SDIO rehash for changes in the bus-driver model + * + * Dirk Brandewie + * - Make it IRQ based, not polling + * + * THE PROCEDURE + * + * See fw.c for the generic description of this procedure. + * + * This file implements only the SDIO specifics. It boils down to how + * to send a command and waiting for an acknowledgement from the + * device. + * + * All this code is sequential -- all i2400ms_bus_bm_*() functions are + * executed in the same thread, except i2400ms_bm_irq() [on its own by + * the SDIO driver]. This makes it possible to avoid locking. + * + * COMMAND EXECUTION + * + * The generic firmware upload code will call i2400m_bus_bm_cmd_send() + * to send commands. + * + * The SDIO devices expects things in 256 byte blocks, so it will pad + * it, compute the checksum (if needed) and pass it to SDIO. + * + * ACK RECEPTION + * + * This works in IRQ mode -- the fw loader says when to wait for data + * and for that it calls i2400ms_bus_bm_wait_for_ack(). + * + * This checks if there is any data available (RX size > 0); if not, + * waits for the IRQ handler to notify about it. Once there is data, + * it is read and passed to the caller. Doing it this way we don't + * need much coordination/locking, and it makes it much more difficult + * for an interrupt to be lost and the wait_for_ack() function getting + * stuck even when data is pending. + */ +#include +#include "i2400m-sdio.h" + + +#define D_SUBMODULE fw +#include "sdio-debug-levels.h" + + +/* + * Send a boot-mode command to the SDIO function + * + * We use a bounce buffer (i2400m->bm_cmd_buf) because we need to + * touch the header if the RAW flag is not set. + * + * @flags: pass thru from i2400m_bm_cmd() + * @return: cmd_size if ok, < 0 errno code on error. + * + * Note the command is padded to the SDIO block size for the device. + */ +ssize_t i2400ms_bus_bm_cmd_send(struct i2400m *i2400m, + const struct i2400m_bootrom_header *_cmd, + size_t cmd_size, int flags) +{ + ssize_t result; + struct device *dev = i2400m_dev(i2400m); + struct i2400ms *i2400ms = container_of(i2400m, struct i2400ms, i2400m); + int opcode = _cmd == NULL ? -1 : i2400m_brh_get_opcode(_cmd); + struct i2400m_bootrom_header *cmd; + /* SDIO restriction */ + size_t cmd_size_a = ALIGN(cmd_size, I2400MS_BLK_SIZE); + + d_fnstart(5, dev, "(i2400m %p cmd %p size %zu)\n", + i2400m, _cmd, cmd_size); + result = -E2BIG; + if (cmd_size > I2400M_BM_CMD_BUF_SIZE) + goto error_too_big; + + if (_cmd != i2400m->bm_cmd_buf) + memmove(i2400m->bm_cmd_buf, _cmd, cmd_size); + cmd = i2400m->bm_cmd_buf; + if (cmd_size_a > cmd_size) /* Zero pad space */ + memset(i2400m->bm_cmd_buf + cmd_size, 0, cmd_size_a - cmd_size); + if ((flags & I2400M_BM_CMD_RAW) == 0) { + if (WARN_ON(i2400m_brh_get_response_required(cmd) == 0)) + dev_warn(dev, "SW BUG: response_required == 0\n"); + i2400m_bm_cmd_prepare(cmd); + } + d_printf(4, dev, "BM cmd %d: %zu bytes (%zu padded)\n", + opcode, cmd_size, cmd_size_a); + d_dump(5, dev, cmd, cmd_size); + + sdio_claim_host(i2400ms->func); /* Send & check */ + result = sdio_memcpy_toio(i2400ms->func, I2400MS_DATA_ADDR, + i2400m->bm_cmd_buf, cmd_size_a); + sdio_release_host(i2400ms->func); + if (result < 0) { + dev_err(dev, "BM cmd %d: cannot send: %ld\n", + opcode, (long) result); + goto error_cmd_send; + } + result = cmd_size; +error_cmd_send: +error_too_big: + d_fnend(5, dev, "(i2400m %p cmd %p size %zu) = %d\n", + i2400m, _cmd, cmd_size, (int) result); + return result; +} + + +/* + * Read an ack from the device's boot-mode + * + * @i2400m: + * @_ack: pointer to where to store the read data + * @ack_size: how many bytes we should read + * + * Returns: < 0 errno code on error; otherwise, amount of received bytes. + * + * The ACK for a BM command is always at least sizeof(*ack) bytes, so + * check for that. We don't need to check for device reboots + * + */ +ssize_t i2400ms_bus_bm_wait_for_ack(struct i2400m *i2400m, + struct i2400m_bootrom_header *ack, + size_t ack_size) +{ + ssize_t result; + struct i2400ms *i2400ms = container_of(i2400m, struct i2400ms, i2400m); + struct sdio_func *func = i2400ms->func; + struct device *dev = &func->dev; + int size; + + BUG_ON(sizeof(*ack) > ack_size); + + d_fnstart(5, dev, "(i2400m %p ack %p size %zu)\n", + i2400m, ack, ack_size); + + result = wait_event_timeout(i2400ms->bm_wfa_wq, + i2400ms->bm_ack_size != -EINPROGRESS, + 2 * HZ); + if (result == 0) { + result = -ETIMEDOUT; + dev_err(dev, "BM: error waiting for an ack\n"); + goto error_timeout; + } + + spin_lock(&i2400m->rx_lock); + result = i2400ms->bm_ack_size; + BUG_ON(result == -EINPROGRESS); + if (result < 0) /* so we exit when rx_release() is called */ + dev_err(dev, "BM: %s failed: %zd\n", __func__, result); + else { + size = min(ack_size, i2400ms->bm_ack_size); + memcpy(ack, i2400m->bm_ack_buf, size); + } + /* + * Remember always to clear the bm_ack_size to -EINPROGRESS + * after the RX data is processed + */ + i2400ms->bm_ack_size = -EINPROGRESS; + spin_unlock(&i2400m->rx_lock); + +error_timeout: + d_fnend(5, dev, "(i2400m %p ack %p size %zu) = %zd\n", + i2400m, ack, ack_size, result); + return result; +} diff --git a/trunk/drivers/net/wimax/i2400m/sdio-rx.c b/trunk/drivers/net/wimax/i2400m/sdio-rx.c new file mode 100644 index 000000000000..fb6396dd115f --- /dev/null +++ b/trunk/drivers/net/wimax/i2400m/sdio-rx.c @@ -0,0 +1,301 @@ +/* + * Intel Wireless WiMAX Connection 2400m + * SDIO RX handling + * + * + * Copyright (C) 2007-2008 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * + * Intel Corporation + * Dirk Brandewie + * - Initial implementation + * + * + * This handles the RX path on SDIO. + * + * The SDIO bus driver calls the "irq" routine when data is available. + * This is not a traditional interrupt routine since the SDIO bus + * driver calls us from its irq thread context. Because of this + * sleeping in the SDIO RX IRQ routine is okay. + * + * From there on, we obtain the size of the data that is available, + * allocate an skb, copy it and then pass it to the generic driver's + * RX routine [i2400m_rx()]. + * + * ROADMAP + * + * i2400ms_irq() + * i2400ms_rx() + * __i2400ms_rx_get_size() + * i2400m_is_boot_barker() + * i2400m_rx() + * + * i2400ms_rx_setup() + * + * i2400ms_rx_release() + */ +#include +#include +#include +#include +#include +#include +#include "i2400m-sdio.h" + +#define D_SUBMODULE rx +#include "sdio-debug-levels.h" + +static const __le32 i2400m_ACK_BARKER[4] = { + __constant_cpu_to_le32(I2400M_ACK_BARKER), + __constant_cpu_to_le32(I2400M_ACK_BARKER), + __constant_cpu_to_le32(I2400M_ACK_BARKER), + __constant_cpu_to_le32(I2400M_ACK_BARKER) +}; + + +/* + * Read and return the amount of bytes available for RX + * + * The RX size has to be read like this: byte reads of three + * sequential locations; then glue'em together. + * + * sdio_readl() doesn't work. + */ +static ssize_t __i2400ms_rx_get_size(struct i2400ms *i2400ms) +{ + int ret, cnt, val; + ssize_t rx_size; + unsigned xfer_size_addr; + struct sdio_func *func = i2400ms->func; + struct device *dev = &i2400ms->func->dev; + + d_fnstart(7, dev, "(i2400ms %p)\n", i2400ms); + xfer_size_addr = I2400MS_INTR_GET_SIZE_ADDR; + rx_size = 0; + for (cnt = 0; cnt < 3; cnt++) { + val = sdio_readb(func, xfer_size_addr + cnt, &ret); + if (ret < 0) { + dev_err(dev, "RX: Can't read byte %d of RX size from " + "0x%08x: %d\n", cnt, xfer_size_addr + cnt, ret); + rx_size = ret; + goto error_read; + } + rx_size = rx_size << 8 | (val & 0xff); + } + d_printf(6, dev, "RX: rx_size is %ld\n", (long) rx_size); +error_read: + d_fnend(7, dev, "(i2400ms %p) = %ld\n", i2400ms, (long) rx_size); + return rx_size; +} + + +/* + * Read data from the device (when in normal) + * + * Allocate an SKB of the right size, read the data in and then + * deliver it to the generic layer. + * + * We also check for a reboot barker. That means the device died and + * we have to reboot it. + */ +static +void i2400ms_rx(struct i2400ms *i2400ms) +{ + int ret; + struct sdio_func *func = i2400ms->func; + struct device *dev = &func->dev; + struct i2400m *i2400m = &i2400ms->i2400m; + struct sk_buff *skb; + ssize_t rx_size; + + d_fnstart(7, dev, "(i2400ms %p)\n", i2400ms); + rx_size = __i2400ms_rx_get_size(i2400ms); + if (rx_size < 0) { + ret = rx_size; + goto error_get_size; + } + /* + * Hardware quirk: make sure to clear the INTR status register + * AFTER getting the data transfer size. + */ + sdio_writeb(func, 1, I2400MS_INTR_CLEAR_ADDR, &ret); + + ret = -ENOMEM; + skb = alloc_skb(rx_size, GFP_ATOMIC); + if (NULL == skb) { + dev_err(dev, "RX: unable to alloc skb\n"); + goto error_alloc_skb; + } + ret = sdio_memcpy_fromio(func, skb->data, + I2400MS_DATA_ADDR, rx_size); + if (ret < 0) { + dev_err(dev, "RX: SDIO data read failed: %d\n", ret); + goto error_memcpy_fromio; + } + + rmb(); /* make sure we get boot_mode from dev_reset_handle */ + if (unlikely(i2400m->boot_mode == 1)) { + spin_lock(&i2400m->rx_lock); + i2400ms->bm_ack_size = rx_size; + spin_unlock(&i2400m->rx_lock); + memcpy(i2400m->bm_ack_buf, skb->data, rx_size); + wake_up(&i2400ms->bm_wfa_wq); + d_printf(5, dev, "RX: SDIO boot mode message\n"); + kfree_skb(skb); + goto out; + } + ret = -EIO; + if (unlikely(rx_size < sizeof(__le32))) { + dev_err(dev, "HW BUG? only %zu bytes received\n", rx_size); + goto error_bad_size; + } + if (likely(i2400m_is_d2h_barker(skb->data))) { + skb_put(skb, rx_size); + i2400m_rx(i2400m, skb); + } else if (unlikely(i2400m_is_boot_barker(i2400m, + skb->data, rx_size))) { + ret = i2400m_dev_reset_handle(i2400m, "device rebooted"); + dev_err(dev, "RX: SDIO reboot barker\n"); + kfree_skb(skb); + } else { + i2400m_unknown_barker(i2400m, skb->data, rx_size); + kfree_skb(skb); + } +out: + d_fnend(7, dev, "(i2400ms %p) = void\n", i2400ms); + return; + +error_memcpy_fromio: + kfree_skb(skb); +error_alloc_skb: +error_get_size: +error_bad_size: + d_fnend(7, dev, "(i2400ms %p) = %d\n", i2400ms, ret); +} + + +/* + * Process an interrupt from the SDIO card + * + * FIXME: need to process other events that are not just ready-to-read + * + * Checks there is data ready and then proceeds to read it. + */ +static +void i2400ms_irq(struct sdio_func *func) +{ + int ret; + struct i2400ms *i2400ms = sdio_get_drvdata(func); + struct device *dev = &func->dev; + int val; + + d_fnstart(6, dev, "(i2400ms %p)\n", i2400ms); + val = sdio_readb(func, I2400MS_INTR_STATUS_ADDR, &ret); + if (ret < 0) { + dev_err(dev, "RX: Can't read interrupt status: %d\n", ret); + goto error_no_irq; + } + if (!val) { + dev_err(dev, "RX: BUG? got IRQ but no interrupt ready?\n"); + goto error_no_irq; + } + i2400ms_rx(i2400ms); +error_no_irq: + d_fnend(6, dev, "(i2400ms %p) = void\n", i2400ms); +} + + +/* + * Setup SDIO RX + * + * Hooks up the IRQ handler and then enables IRQs. + */ +int i2400ms_rx_setup(struct i2400ms *i2400ms) +{ + int result; + struct sdio_func *func = i2400ms->func; + struct device *dev = &func->dev; + struct i2400m *i2400m = &i2400ms->i2400m; + + d_fnstart(5, dev, "(i2400ms %p)\n", i2400ms); + + init_waitqueue_head(&i2400ms->bm_wfa_wq); + spin_lock(&i2400m->rx_lock); + i2400ms->bm_wait_result = -EINPROGRESS; + /* + * Before we are about to enable the RX interrupt, make sure + * bm_ack_size is cleared to -EINPROGRESS which indicates + * no RX interrupt happened yet or the previous interrupt + * has been handled, we are ready to take the new interrupt + */ + i2400ms->bm_ack_size = -EINPROGRESS; + spin_unlock(&i2400m->rx_lock); + + sdio_claim_host(func); + result = sdio_claim_irq(func, i2400ms_irq); + if (result < 0) { + dev_err(dev, "Cannot claim IRQ: %d\n", result); + goto error_irq_claim; + } + result = 0; + sdio_writeb(func, 1, I2400MS_INTR_ENABLE_ADDR, &result); + if (result < 0) { + sdio_release_irq(func); + dev_err(dev, "Failed to enable interrupts %d\n", result); + } +error_irq_claim: + sdio_release_host(func); + d_fnend(5, dev, "(i2400ms %p) = %d\n", i2400ms, result); + return result; +} + + +/* + * Tear down SDIO RX + * + * Disables IRQs in the device and removes the IRQ handler. + */ +void i2400ms_rx_release(struct i2400ms *i2400ms) +{ + int result; + struct sdio_func *func = i2400ms->func; + struct device *dev = &func->dev; + struct i2400m *i2400m = &i2400ms->i2400m; + + d_fnstart(5, dev, "(i2400ms %p)\n", i2400ms); + spin_lock(&i2400m->rx_lock); + i2400ms->bm_ack_size = -EINTR; + spin_unlock(&i2400m->rx_lock); + wake_up_all(&i2400ms->bm_wfa_wq); + sdio_claim_host(func); + sdio_writeb(func, 0, I2400MS_INTR_ENABLE_ADDR, &result); + sdio_release_irq(func); + sdio_release_host(func); + d_fnend(5, dev, "(i2400ms %p) = %d\n", i2400ms, result); +} diff --git a/trunk/drivers/net/wimax/i2400m/sdio-tx.c b/trunk/drivers/net/wimax/i2400m/sdio-tx.c new file mode 100644 index 000000000000..b53cd1c80e3e --- /dev/null +++ b/trunk/drivers/net/wimax/i2400m/sdio-tx.c @@ -0,0 +1,177 @@ +/* + * Intel Wireless WiMAX Connection 2400m + * SDIO TX transaction backends + * + * + * Copyright (C) 2007-2008 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * + * Intel Corporation + * Dirk Brandewie + * - Initial implementation + * + * + * Takes the TX messages in the i2400m's driver TX FIFO and sends them + * to the device until there are no more. + * + * If we fail sending the message, we just drop it. There isn't much + * we can do at this point. Most of the traffic is network, which has + * recovery methods for dropped packets. + * + * The SDIO functions are not atomic, so we can't run from the context + * where i2400m->bus_tx_kick() [i2400ms_bus_tx_kick()] is being called + * (some times atomic). Thus, the actual TX work is deferred to a + * workqueue. + * + * ROADMAP + * + * i2400ms_bus_tx_kick() + * i2400ms_tx_submit() [through workqueue] + * + * i2400m_tx_setup() + * + * i2400m_tx_release() + */ +#include +#include "i2400m-sdio.h" + +#define D_SUBMODULE tx +#include "sdio-debug-levels.h" + + +/* + * Pull TX transations from the TX FIFO and send them to the device + * until there are no more. + */ +static +void i2400ms_tx_submit(struct work_struct *ws) +{ + int result; + struct i2400ms *i2400ms = container_of(ws, struct i2400ms, tx_worker); + struct i2400m *i2400m = &i2400ms->i2400m; + struct sdio_func *func = i2400ms->func; + struct device *dev = &func->dev; + struct i2400m_msg_hdr *tx_msg; + size_t tx_msg_size; + + d_fnstart(4, dev, "(i2400ms %p, i2400m %p)\n", i2400ms, i2400ms); + + while (NULL != (tx_msg = i2400m_tx_msg_get(i2400m, &tx_msg_size))) { + d_printf(2, dev, "TX: submitting %zu bytes\n", tx_msg_size); + d_dump(5, dev, tx_msg, tx_msg_size); + + sdio_claim_host(func); + result = sdio_memcpy_toio(func, 0, tx_msg, tx_msg_size); + sdio_release_host(func); + + i2400m_tx_msg_sent(i2400m); + + if (result < 0) { + dev_err(dev, "TX: cannot submit TX; tx_msg @%zu %zu B:" + " %d\n", (void *) tx_msg - i2400m->tx_buf, + tx_msg_size, result); + } + + if (result == -ETIMEDOUT) { + i2400m_error_recovery(i2400m); + break; + } + d_printf(2, dev, "TX: %zub submitted\n", tx_msg_size); + } + + d_fnend(4, dev, "(i2400ms %p) = void\n", i2400ms); +} + + +/* + * The generic driver notifies us that there is data ready for TX + * + * Schedule a run of i2400ms_tx_submit() to handle it. + */ +void i2400ms_bus_tx_kick(struct i2400m *i2400m) +{ + struct i2400ms *i2400ms = container_of(i2400m, struct i2400ms, i2400m); + struct device *dev = &i2400ms->func->dev; + unsigned long flags; + + d_fnstart(3, dev, "(i2400m %p) = void\n", i2400m); + + /* schedule tx work, this is because tx may block, therefore + * it has to run in a thread context. + */ + spin_lock_irqsave(&i2400m->tx_lock, flags); + if (i2400ms->tx_workqueue != NULL) + queue_work(i2400ms->tx_workqueue, &i2400ms->tx_worker); + spin_unlock_irqrestore(&i2400m->tx_lock, flags); + + d_fnend(3, dev, "(i2400m %p) = void\n", i2400m); +} + +int i2400ms_tx_setup(struct i2400ms *i2400ms) +{ + int result; + struct device *dev = &i2400ms->func->dev; + struct i2400m *i2400m = &i2400ms->i2400m; + struct workqueue_struct *tx_workqueue; + unsigned long flags; + + d_fnstart(5, dev, "(i2400ms %p)\n", i2400ms); + + INIT_WORK(&i2400ms->tx_worker, i2400ms_tx_submit); + snprintf(i2400ms->tx_wq_name, sizeof(i2400ms->tx_wq_name), + "%s-tx", i2400m->wimax_dev.name); + tx_workqueue = + create_singlethread_workqueue(i2400ms->tx_wq_name); + if (tx_workqueue == NULL) { + dev_err(dev, "TX: failed to create workqueue\n"); + result = -ENOMEM; + } else + result = 0; + spin_lock_irqsave(&i2400m->tx_lock, flags); + i2400ms->tx_workqueue = tx_workqueue; + spin_unlock_irqrestore(&i2400m->tx_lock, flags); + d_fnend(5, dev, "(i2400ms %p) = %d\n", i2400ms, result); + return result; +} + +void i2400ms_tx_release(struct i2400ms *i2400ms) +{ + struct i2400m *i2400m = &i2400ms->i2400m; + struct workqueue_struct *tx_workqueue; + unsigned long flags; + + tx_workqueue = i2400ms->tx_workqueue; + + spin_lock_irqsave(&i2400m->tx_lock, flags); + i2400ms->tx_workqueue = NULL; + spin_unlock_irqrestore(&i2400m->tx_lock, flags); + + if (tx_workqueue) + destroy_workqueue(tx_workqueue); +} diff --git a/trunk/drivers/net/wimax/i2400m/sdio.c b/trunk/drivers/net/wimax/i2400m/sdio.c new file mode 100644 index 000000000000..21a9edd6e75d --- /dev/null +++ b/trunk/drivers/net/wimax/i2400m/sdio.c @@ -0,0 +1,602 @@ +/* + * Intel Wireless WiMAX Connection 2400m + * Linux driver model glue for the SDIO device, reset & fw upload + * + * + * Copyright (C) 2007-2008 Intel Corporation + * Dirk Brandewie + * Inaky Perez-Gonzalez + * Yanir Lubetkin + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + * + * + * See i2400m-sdio.h for a general description of this driver. + * + * This file implements driver model glue, and hook ups for the + * generic driver to implement the bus-specific functions (device + * communication setup/tear down, firmware upload and resetting). + * + * ROADMAP + * + * i2400m_probe() + * alloc_netdev() + * i2400ms_netdev_setup() + * i2400ms_init() + * i2400m_netdev_setup() + * i2400ms_enable_function() + * i2400m_setup() + * + * i2400m_remove() + * i2400m_release() + * free_netdev(net_dev) + * + * i2400ms_bus_reset() Called by i2400m_reset + * __i2400ms_reset() + * __i2400ms_send_barker() + */ + +#include +#include +#include +#include +#include +#include "i2400m-sdio.h" +#include +#include + +#define D_SUBMODULE main +#include "sdio-debug-levels.h" + +/* IOE WiMAX function timeout in seconds */ +static int ioe_timeout = 2; +module_param(ioe_timeout, int, 0); + +static char i2400ms_debug_params[128]; +module_param_string(debug, i2400ms_debug_params, sizeof(i2400ms_debug_params), + 0644); +MODULE_PARM_DESC(debug, + "String of space-separated NAME:VALUE pairs, where NAMEs " + "are the different debug submodules and VALUE are the " + "initial debug value to set."); + +/* Our firmware file name list */ +static const char *i2400ms_bus_fw_names[] = { +#define I2400MS_FW_FILE_NAME "i2400m-fw-sdio-1.3.sbcf" + I2400MS_FW_FILE_NAME, + NULL +}; + + +static const struct i2400m_poke_table i2400ms_pokes[] = { + I2400M_FW_POKE(0x6BE260, 0x00000088), + I2400M_FW_POKE(0x080550, 0x00000005), + I2400M_FW_POKE(0xAE0000, 0x00000000), + I2400M_FW_POKE(0x000000, 0x00000000), /* MUST be 0 terminated or bad + * things will happen */ +}; + +/* + * Enable the SDIO function + * + * Tries to enable the SDIO function; might fail if it is still not + * ready (in some hardware, the SDIO WiMAX function is only enabled + * when we ask it to explicitly doing). Tries until a timeout is + * reached. + * + * The @maxtries argument indicates how many times (at most) it should + * be tried to enable the function. 0 means forever. This acts along + * with the timeout (ie: it'll stop trying as soon as the maximum + * number of tries is reached _or_ as soon as the timeout is reached). + * + * The reverse of this is...sdio_disable_function() + * + * Returns: 0 if the SDIO function was enabled, < 0 errno code on + * error (-ENODEV when it was unable to enable the function). + */ +static +int i2400ms_enable_function(struct i2400ms *i2400ms, unsigned maxtries) +{ + struct sdio_func *func = i2400ms->func; + u64 timeout; + int err; + struct device *dev = &func->dev; + unsigned tries = 0; + + d_fnstart(3, dev, "(func %p)\n", func); + /* Setup timeout (FIXME: This needs to read the CIS table to + * get a real timeout) and then wait for the device to signal + * it is ready */ + timeout = get_jiffies_64() + ioe_timeout * HZ; + err = -ENODEV; + while (err != 0 && time_before64(get_jiffies_64(), timeout)) { + sdio_claim_host(func); + /* + * There is a sillicon bug on the IWMC3200, where the + * IOE timeout will cause problems on Moorestown + * platforms (system hang). We explicitly overwrite + * func->enable_timeout here to work around the issue. + */ + if (i2400ms->iwmc3200) + func->enable_timeout = IWMC3200_IOR_TIMEOUT; + err = sdio_enable_func(func); + if (0 == err) { + sdio_release_host(func); + d_printf(2, dev, "SDIO function enabled\n"); + goto function_enabled; + } + d_printf(2, dev, "SDIO function failed to enable: %d\n", err); + sdio_release_host(func); + if (maxtries > 0 && ++tries >= maxtries) { + err = -ETIME; + break; + } + msleep(I2400MS_INIT_SLEEP_INTERVAL); + } + /* If timed out, device is not there yet -- get -ENODEV so + * the device driver core will retry later on. */ + if (err == -ETIME) { + dev_err(dev, "Can't enable WiMAX function; " + " has the function been enabled?\n"); + err = -ENODEV; + } +function_enabled: + d_fnend(3, dev, "(func %p) = %d\n", func, err); + return err; +} + + +/* + * Setup minimal device communication infrastructure needed to at + * least be able to update the firmware. + * + * Note the ugly trick: if we are in the probe path + * (i2400ms->debugfs_dentry == NULL), we only retry function + * enablement one, to avoid racing with the iwmc3200 top controller. + */ +static +int i2400ms_bus_setup(struct i2400m *i2400m) +{ + int result; + struct i2400ms *i2400ms = + container_of(i2400m, struct i2400ms, i2400m); + struct device *dev = i2400m_dev(i2400m); + struct sdio_func *func = i2400ms->func; + int retries; + + sdio_claim_host(func); + result = sdio_set_block_size(func, I2400MS_BLK_SIZE); + sdio_release_host(func); + if (result < 0) { + dev_err(dev, "Failed to set block size: %d\n", result); + goto error_set_blk_size; + } + + if (i2400ms->iwmc3200 && i2400ms->debugfs_dentry == NULL) + retries = 1; + else + retries = 0; + result = i2400ms_enable_function(i2400ms, retries); + if (result < 0) { + dev_err(dev, "Cannot enable SDIO function: %d\n", result); + goto error_func_enable; + } + + result = i2400ms_tx_setup(i2400ms); + if (result < 0) + goto error_tx_setup; + result = i2400ms_rx_setup(i2400ms); + if (result < 0) + goto error_rx_setup; + return 0; + +error_rx_setup: + i2400ms_tx_release(i2400ms); +error_tx_setup: + sdio_claim_host(func); + sdio_disable_func(func); + sdio_release_host(func); +error_func_enable: +error_set_blk_size: + return result; +} + + +/* + * Tear down minimal device communication infrastructure needed to at + * least be able to update the firmware. + */ +static +void i2400ms_bus_release(struct i2400m *i2400m) +{ + struct i2400ms *i2400ms = + container_of(i2400m, struct i2400ms, i2400m); + struct sdio_func *func = i2400ms->func; + + i2400ms_rx_release(i2400ms); + i2400ms_tx_release(i2400ms); + sdio_claim_host(func); + sdio_disable_func(func); + sdio_release_host(func); +} + + +/* + * Setup driver resources needed to communicate with the device + * + * The fw needs some time to settle, and it was just uploaded, + * so give it a break first. I'd prefer to just wait for the device to + * send something, but seems the poking we do to enable SDIO stuff + * interferes with it, so just give it a break before starting... + */ +static +int i2400ms_bus_dev_start(struct i2400m *i2400m) +{ + struct i2400ms *i2400ms = container_of(i2400m, struct i2400ms, i2400m); + struct sdio_func *func = i2400ms->func; + struct device *dev = &func->dev; + + d_fnstart(3, dev, "(i2400m %p)\n", i2400m); + msleep(200); + d_fnend(3, dev, "(i2400m %p) = %d\n", i2400m, 0); + return 0; +} + + +/* + * Sends a barker buffer to the device + * + * This helper will allocate a kmalloced buffer and use it to transmit + * (then free it). Reason for this is that the SDIO host controller + * expects alignment (unknown exactly which) which the stack won't + * really provide and certain arches/host-controller combinations + * cannot use stack/vmalloc/text areas for DMA transfers. + */ +static +int __i2400ms_send_barker(struct i2400ms *i2400ms, + const __le32 *barker, size_t barker_size) +{ + int ret; + struct sdio_func *func = i2400ms->func; + struct device *dev = &func->dev; + void *buffer; + + ret = -ENOMEM; + buffer = kmalloc(I2400MS_BLK_SIZE, GFP_KERNEL); + if (buffer == NULL) + goto error_kzalloc; + + memcpy(buffer, barker, barker_size); + sdio_claim_host(func); + ret = sdio_memcpy_toio(func, 0, buffer, I2400MS_BLK_SIZE); + sdio_release_host(func); + + if (ret < 0) + d_printf(0, dev, "E: barker error: %d\n", ret); + + kfree(buffer); +error_kzalloc: + return ret; +} + + +/* + * Reset a device at different levels (warm, cold or bus) + * + * @i2400ms: device descriptor + * @reset_type: soft, warm or bus reset (I2400M_RT_WARM/SOFT/BUS) + * + * FIXME: not tested -- need to confirm expected effects + * + * Warm and cold resets get an SDIO reset if they fail (unimplemented) + * + * Warm reset: + * + * The device will be fully reset internally, but won't be + * disconnected from the bus (so no reenumeration will + * happen). Firmware upload will be necessary. + * + * The device will send a reboot barker that will trigger the driver + * to reinitialize the state via __i2400m_dev_reset_handle. + * + * + * Cold and bus reset: + * + * The device will be fully reset internally, disconnected from the + * bus an a reenumeration will happen. Firmware upload will be + * necessary. Thus, we don't do any locking or struct + * reinitialization, as we are going to be fully disconnected and + * reenumerated. + * + * Note we need to return -ENODEV if a warm reset was requested and we + * had to resort to a bus reset. See i2400m_op_reset(), wimax_reset() + * and wimax_dev->op_reset. + * + * WARNING: no driver state saved/fixed + */ +static +int i2400ms_bus_reset(struct i2400m *i2400m, enum i2400m_reset_type rt) +{ + int result = 0; + struct i2400ms *i2400ms = + container_of(i2400m, struct i2400ms, i2400m); + struct device *dev = i2400m_dev(i2400m); + static const __le32 i2400m_WARM_BOOT_BARKER[4] = { + cpu_to_le32(I2400M_WARM_RESET_BARKER), + cpu_to_le32(I2400M_WARM_RESET_BARKER), + cpu_to_le32(I2400M_WARM_RESET_BARKER), + cpu_to_le32(I2400M_WARM_RESET_BARKER), + }; + static const __le32 i2400m_COLD_BOOT_BARKER[4] = { + cpu_to_le32(I2400M_COLD_RESET_BARKER), + cpu_to_le32(I2400M_COLD_RESET_BARKER), + cpu_to_le32(I2400M_COLD_RESET_BARKER), + cpu_to_le32(I2400M_COLD_RESET_BARKER), + }; + + if (rt == I2400M_RT_WARM) + result = __i2400ms_send_barker(i2400ms, i2400m_WARM_BOOT_BARKER, + sizeof(i2400m_WARM_BOOT_BARKER)); + else if (rt == I2400M_RT_COLD) + result = __i2400ms_send_barker(i2400ms, i2400m_COLD_BOOT_BARKER, + sizeof(i2400m_COLD_BOOT_BARKER)); + else if (rt == I2400M_RT_BUS) { +do_bus_reset: + + i2400ms_bus_release(i2400m); + + /* Wait for the device to settle */ + msleep(40); + + result = i2400ms_bus_setup(i2400m); + } else + BUG(); + if (result < 0 && rt != I2400M_RT_BUS) { + dev_err(dev, "%s reset failed (%d); trying SDIO reset\n", + rt == I2400M_RT_WARM ? "warm" : "cold", result); + rt = I2400M_RT_BUS; + goto do_bus_reset; + } + return result; +} + + +static +void i2400ms_netdev_setup(struct net_device *net_dev) +{ + struct i2400m *i2400m = net_dev_to_i2400m(net_dev); + struct i2400ms *i2400ms = container_of(i2400m, struct i2400ms, i2400m); + i2400ms_init(i2400ms); + i2400m_netdev_setup(net_dev); +} + + +/* + * Debug levels control; see debug.h + */ +struct d_level D_LEVEL[] = { + D_SUBMODULE_DEFINE(main), + D_SUBMODULE_DEFINE(tx), + D_SUBMODULE_DEFINE(rx), + D_SUBMODULE_DEFINE(fw), +}; +size_t D_LEVEL_SIZE = ARRAY_SIZE(D_LEVEL); + + +#define __debugfs_register(prefix, name, parent) \ +do { \ + result = d_level_register_debugfs(prefix, name, parent); \ + if (result < 0) \ + goto error; \ +} while (0) + + +static +int i2400ms_debugfs_add(struct i2400ms *i2400ms) +{ + int result; + struct dentry *dentry = i2400ms->i2400m.wimax_dev.debugfs_dentry; + + dentry = debugfs_create_dir("i2400m-sdio", dentry); + result = PTR_ERR(dentry); + if (IS_ERR(dentry)) { + if (result == -ENODEV) + result = 0; /* No debugfs support */ + goto error; + } + i2400ms->debugfs_dentry = dentry; + __debugfs_register("dl_", main, dentry); + __debugfs_register("dl_", tx, dentry); + __debugfs_register("dl_", rx, dentry); + __debugfs_register("dl_", fw, dentry); + + return 0; + +error: + debugfs_remove_recursive(i2400ms->debugfs_dentry); + i2400ms->debugfs_dentry = NULL; + return result; +} + + +static struct device_type i2400ms_type = { + .name = "wimax", +}; + +/* + * Probe a i2400m interface and register it + * + * @func: SDIO function + * @id: SDIO device ID + * @returns: 0 if ok, < 0 errno code on error. + * + * Alloc a net device, initialize the bus-specific details and then + * calls the bus-generic initialization routine. That will register + * the wimax and netdev devices, upload the firmware [using + * _bus_bm_*()], call _bus_dev_start() to finalize the setup of the + * communication with the device and then will start to talk to it to + * finnish setting it up. + * + * Initialization is tricky; some instances of the hw are packed with + * others in a way that requires a third driver that enables the WiMAX + * function. In those cases, we can't enable the SDIO function and + * we'll return with -ENODEV. When the driver that enables the WiMAX + * function does its thing, it has to do a bus_rescan_devices() on the + * SDIO bus so this driver is called again to enumerate the WiMAX + * function. + */ +static +int i2400ms_probe(struct sdio_func *func, + const struct sdio_device_id *id) +{ + int result; + struct net_device *net_dev; + struct device *dev = &func->dev; + struct i2400m *i2400m; + struct i2400ms *i2400ms; + + /* Allocate instance [calls i2400m_netdev_setup() on it]. */ + result = -ENOMEM; + net_dev = alloc_netdev(sizeof(*i2400ms), "wmx%d", + i2400ms_netdev_setup); + if (net_dev == NULL) { + dev_err(dev, "no memory for network device instance\n"); + goto error_alloc_netdev; + } + SET_NETDEV_DEV(net_dev, dev); + SET_NETDEV_DEVTYPE(net_dev, &i2400ms_type); + i2400m = net_dev_to_i2400m(net_dev); + i2400ms = container_of(i2400m, struct i2400ms, i2400m); + i2400m->wimax_dev.net_dev = net_dev; + i2400ms->func = func; + sdio_set_drvdata(func, i2400ms); + + i2400m->bus_tx_block_size = I2400MS_BLK_SIZE; + /* + * Room required in the TX queue for SDIO message to accommodate + * a smallest payload while allocating header space is 224 bytes, + * which is the smallest message size(the block size 256 bytes) + * minus the smallest message header size(32 bytes). + */ + i2400m->bus_tx_room_min = I2400MS_BLK_SIZE - I2400M_PL_ALIGN * 2; + i2400m->bus_pl_size_max = I2400MS_PL_SIZE_MAX; + i2400m->bus_setup = i2400ms_bus_setup; + i2400m->bus_dev_start = i2400ms_bus_dev_start; + i2400m->bus_dev_stop = NULL; + i2400m->bus_release = i2400ms_bus_release; + i2400m->bus_tx_kick = i2400ms_bus_tx_kick; + i2400m->bus_reset = i2400ms_bus_reset; + /* The iwmc3200-wimax sometimes requires the driver to try + * hard when we paint it into a corner. */ + i2400m->bus_bm_retries = I2400M_SDIO_BOOT_RETRIES; + i2400m->bus_bm_cmd_send = i2400ms_bus_bm_cmd_send; + i2400m->bus_bm_wait_for_ack = i2400ms_bus_bm_wait_for_ack; + i2400m->bus_fw_names = i2400ms_bus_fw_names; + i2400m->bus_bm_mac_addr_impaired = 1; + i2400m->bus_bm_pokes_table = &i2400ms_pokes[0]; + + switch (func->device) { + case SDIO_DEVICE_ID_INTEL_IWMC3200WIMAX: + case SDIO_DEVICE_ID_INTEL_IWMC3200WIMAX_2G5: + i2400ms->iwmc3200 = 1; + break; + default: + i2400ms->iwmc3200 = 0; + } + + result = i2400m_setup(i2400m, I2400M_BRI_NO_REBOOT); + if (result < 0) { + dev_err(dev, "cannot setup device: %d\n", result); + goto error_setup; + } + + result = i2400ms_debugfs_add(i2400ms); + if (result < 0) { + dev_err(dev, "cannot create SDIO debugfs: %d\n", + result); + goto error_debugfs_add; + } + return 0; + +error_debugfs_add: + i2400m_release(i2400m); +error_setup: + sdio_set_drvdata(func, NULL); + free_netdev(net_dev); +error_alloc_netdev: + return result; +} + + +static +void i2400ms_remove(struct sdio_func *func) +{ + struct device *dev = &func->dev; + struct i2400ms *i2400ms = sdio_get_drvdata(func); + struct i2400m *i2400m = &i2400ms->i2400m; + struct net_device *net_dev = i2400m->wimax_dev.net_dev; + + d_fnstart(3, dev, "SDIO func %p\n", func); + debugfs_remove_recursive(i2400ms->debugfs_dentry); + i2400ms->debugfs_dentry = NULL; + i2400m_release(i2400m); + sdio_set_drvdata(func, NULL); + free_netdev(net_dev); + d_fnend(3, dev, "SDIO func %p\n", func); +} + +static +const struct sdio_device_id i2400ms_sdio_ids[] = { + /* Intel: i2400m WiMAX (iwmc3200) over SDIO */ + { SDIO_DEVICE(SDIO_VENDOR_ID_INTEL, + SDIO_DEVICE_ID_INTEL_IWMC3200WIMAX) }, + { SDIO_DEVICE(SDIO_VENDOR_ID_INTEL, + SDIO_DEVICE_ID_INTEL_IWMC3200WIMAX_2G5) }, + { /* end: all zeroes */ }, +}; +MODULE_DEVICE_TABLE(sdio, i2400ms_sdio_ids); + + +static +struct sdio_driver i2400m_sdio_driver = { + .name = KBUILD_MODNAME, + .probe = i2400ms_probe, + .remove = i2400ms_remove, + .id_table = i2400ms_sdio_ids, +}; + + +static +int __init i2400ms_driver_init(void) +{ + d_parse_params(D_LEVEL, D_LEVEL_SIZE, i2400ms_debug_params, + "i2400m_sdio.debug"); + return sdio_register_driver(&i2400m_sdio_driver); +} +module_init(i2400ms_driver_init); + + +static +void __exit i2400ms_driver_exit(void) +{ + sdio_unregister_driver(&i2400m_sdio_driver); +} +module_exit(i2400ms_driver_exit); + + +MODULE_AUTHOR("Intel Corporation "); +MODULE_DESCRIPTION("Intel 2400M WiMAX networking for SDIO"); +MODULE_LICENSE("GPL"); +MODULE_FIRMWARE(I2400MS_FW_FILE_NAME); diff --git a/trunk/drivers/net/wireless/Kconfig b/trunk/drivers/net/wireless/Kconfig index 6deaae18db57..5f58fa53238c 100644 --- a/trunk/drivers/net/wireless/Kconfig +++ b/trunk/drivers/net/wireless/Kconfig @@ -276,6 +276,7 @@ source "drivers/net/wireless/hostap/Kconfig" source "drivers/net/wireless/ipw2x00/Kconfig" source "drivers/net/wireless/iwlwifi/Kconfig" source "drivers/net/wireless/iwlegacy/Kconfig" +source "drivers/net/wireless/iwmc3200wifi/Kconfig" source "drivers/net/wireless/libertas/Kconfig" source "drivers/net/wireless/orinoco/Kconfig" source "drivers/net/wireless/p54/Kconfig" diff --git a/trunk/drivers/net/wireless/Makefile b/trunk/drivers/net/wireless/Makefile index 062dfdff6364..0ce218b931d4 100644 --- a/trunk/drivers/net/wireless/Makefile +++ b/trunk/drivers/net/wireless/Makefile @@ -53,6 +53,8 @@ obj-$(CONFIG_MAC80211_HWSIM) += mac80211_hwsim.o obj-$(CONFIG_WL_TI) += ti/ +obj-$(CONFIG_IWM) += iwmc3200wifi/ + obj-$(CONFIG_MWIFIEX) += mwifiex/ obj-$(CONFIG_BRCMFMAC) += brcm80211/ diff --git a/trunk/drivers/net/wireless/adm8211.c b/trunk/drivers/net/wireless/adm8211.c index 689a71c1af71..97afcec24759 100644 --- a/trunk/drivers/net/wireless/adm8211.c +++ b/trunk/drivers/net/wireless/adm8211.c @@ -1854,7 +1854,7 @@ static int __devinit adm8211_probe(struct pci_dev *pdev, if (!is_valid_ether_addr(perm_addr)) { printk(KERN_WARNING "%s (adm8211): Invalid hwaddr in EEPROM!\n", pci_name(pdev)); - eth_random_addr(perm_addr); + random_ether_addr(perm_addr); } SET_IEEE80211_PERM_ADDR(dev, perm_addr); diff --git a/trunk/drivers/net/wireless/ath/ath5k/Kconfig b/trunk/drivers/net/wireless/ath/ath5k/Kconfig index 338c5c42357d..e18a9aa7b6ca 100644 --- a/trunk/drivers/net/wireless/ath/ath5k/Kconfig +++ b/trunk/drivers/net/wireless/ath/ath5k/Kconfig @@ -64,11 +64,3 @@ config ATH5K_PCI ---help--- This adds support for PCI type chipsets of the 5xxx Atheros family. - -config ATH5K_TEST_CHANNELS - bool "Enables testing channels on ath5k" - depends on ATH5K && CFG80211_CERTIFICATION_ONUS - ---help--- - This enables non-standard IEEE 802.11 channels on ath5k, which - can be used for research purposes. This option should be disabled - unless doing research. diff --git a/trunk/drivers/net/wireless/ath/ath5k/base.c b/trunk/drivers/net/wireless/ath/ath5k/base.c index 8c4c040a47b8..44ad6fe0278f 100644 --- a/trunk/drivers/net/wireless/ath/ath5k/base.c +++ b/trunk/drivers/net/wireless/ath/ath5k/base.c @@ -74,6 +74,10 @@ bool ath5k_modparam_nohwcrypt; module_param_named(nohwcrypt, ath5k_modparam_nohwcrypt, bool, S_IRUGO); MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); +static bool modparam_all_channels; +module_param_named(all_channels, modparam_all_channels, bool, S_IRUGO); +MODULE_PARM_DESC(all_channels, "Expose all channels the device can use."); + static bool modparam_fastchanswitch; module_param_named(fastchanswitch, modparam_fastchanswitch, bool, S_IRUGO); MODULE_PARM_DESC(fastchanswitch, "Enable fast channel switching for AR2413/AR5413 radios."); @@ -254,15 +258,8 @@ static int ath5k_reg_notifier(struct wiphy *wiphy, struct regulatory_request *re \********************/ /* - * Returns true for the channel numbers used. + * Returns true for the channel numbers used without all_channels modparam. */ -#ifdef CONFIG_ATH5K_TEST_CHANNELS -static bool ath5k_is_standard_channel(short chan, enum ieee80211_band band) -{ - return true; -} - -#else static bool ath5k_is_standard_channel(short chan, enum ieee80211_band band) { if (band == IEEE80211_BAND_2GHZ && chan <= 14) @@ -279,7 +276,6 @@ static bool ath5k_is_standard_channel(short chan, enum ieee80211_band band) /* 802.11j 4.9GHz (20MHz) */ (chan == 184 || chan == 188 || chan == 192 || chan == 196)); } -#endif static unsigned int ath5k_setup_channels(struct ath5k_hw *ah, struct ieee80211_channel *channels, @@ -320,7 +316,8 @@ ath5k_setup_channels(struct ath5k_hw *ah, struct ieee80211_channel *channels, if (!ath5k_channel_ok(ah, &channels[count])) continue; - if (!ath5k_is_standard_channel(ch, band)) + if (!modparam_all_channels && + !ath5k_is_standard_channel(ch, band)) continue; count++; diff --git a/trunk/drivers/net/wireless/ath/ath6kl/cfg80211.c b/trunk/drivers/net/wireless/ath/ath6kl/cfg80211.c index aca1d2689e90..fd7dbd4609df 100644 --- a/trunk/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/trunk/drivers/net/wireless/ath/ath6kl/cfg80211.c @@ -3627,7 +3627,6 @@ int ath6kl_cfg80211_init(struct ath6kl *ar) wiphy->cipher_suites = cipher_suites; wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); -#ifdef CONFIG_PM wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT | WIPHY_WOWLAN_DISCONNECT | WIPHY_WOWLAN_GTK_REKEY_FAILURE | @@ -3637,7 +3636,6 @@ int ath6kl_cfg80211_init(struct ath6kl *ar) wiphy->wowlan.n_patterns = WOW_MAX_FILTERS_PER_LIST; wiphy->wowlan.pattern_min_len = 1; wiphy->wowlan.pattern_max_len = WOW_PATTERN_SIZE; -#endif wiphy->max_sched_scan_ssids = MAX_PROBED_SSIDS; diff --git a/trunk/drivers/net/wireless/ath/ath9k/ahb.c b/trunk/drivers/net/wireless/ath/ath9k/ahb.c index 3a69804f4c16..4a4e8a2b9d2c 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/ahb.c +++ b/trunk/drivers/net/wireless/ath/ath9k/ahb.c @@ -35,10 +35,6 @@ static const struct platform_device_id ath9k_platform_id_table[] = { .name = "ar934x_wmac", .driver_data = AR9300_DEVID_AR9340, }, - { - .name = "qca955x_wmac", - .driver_data = AR9300_DEVID_QCA955X, - }, {}, }; diff --git a/trunk/drivers/net/wireless/ath/ath9k/ar9003_calib.c b/trunk/drivers/net/wireless/ath/ath9k/ar9003_calib.c index 84b558d126ca..d7deb8c9f299 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/ar9003_calib.c +++ b/trunk/drivers/net/wireless/ath/ath9k/ar9003_calib.c @@ -159,11 +159,14 @@ static bool ar9003_hw_calibrate(struct ath_hw *ah, } } - /* - * Do NF cal only at longer intervals. Get the value from - * the previous NF cal and update history buffer. - */ - if (longcal && ath9k_hw_getnf(ah, chan)) { + /* Do NF cal only at longer intervals */ + if (longcal) { + /* + * Get the value from the previous NF cal and update + * history buffer. + */ + ath9k_hw_getnf(ah, chan); + /* * Load the NF from history buffer of the current channel. * NF is slow time-variant, so it is OK to use a historical diff --git a/trunk/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/trunk/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c index ab2bfcb3bed2..b1e59236d245 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/trunk/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c @@ -3509,7 +3509,7 @@ static void ar9003_hw_xpa_bias_level_apply(struct ath_hw *ah, bool is2ghz) if (AR_SREV_9485(ah) || AR_SREV_9330(ah) || AR_SREV_9340(ah)) REG_RMW_FIELD(ah, AR_CH0_TOP2, AR_CH0_TOP2_XPABIASLVL, bias); - else if (AR_SREV_9462(ah) || AR_SREV_9550(ah)) + else if (AR_SREV_9462(ah)) REG_RMW_FIELD(ah, AR_CH0_TOP, AR_CH0_TOP_XPABIASLVL, bias); else { REG_RMW_FIELD(ah, AR_CH0_TOP, AR_CH0_TOP_XPABIASLVL, bias); @@ -3591,9 +3591,6 @@ static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz) if (AR_SREV_9462(ah)) { REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM, AR_SWITCH_TABLE_COM_AR9462_ALL, value); - } else if (AR_SREV_9550(ah)) { - REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM, - AR_SWITCH_TABLE_COM_AR9550_ALL, value); } else REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM, AR_SWITCH_TABLE_COM_ALL, value); @@ -3960,7 +3957,7 @@ static void ath9k_hw_ar9300_set_board_values(struct ath_hw *ah, ar9003_hw_drive_strength_apply(ah); ar9003_hw_atten_apply(ah, chan); ar9003_hw_quick_drop_apply(ah, chan->channel); - if (!AR_SREV_9330(ah) && !AR_SREV_9340(ah) && !AR_SREV_9550(ah)) + if (!AR_SREV_9330(ah) && !AR_SREV_9340(ah)) ar9003_hw_internal_regulator_apply(ah); if (AR_SREV_9485(ah) || AR_SREV_9330(ah) || AR_SREV_9340(ah)) ar9003_hw_apply_tuning_caps(ah); diff --git a/trunk/drivers/net/wireless/ath/ath9k/ar9003_hw.c b/trunk/drivers/net/wireless/ath/ath9k/ar9003_hw.c index 41e88c660e48..a0e3394b10dc 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/ar9003_hw.c +++ b/trunk/drivers/net/wireless/ath/ath9k/ar9003_hw.c @@ -21,7 +21,6 @@ #include "ar9340_initvals.h" #include "ar9330_1p1_initvals.h" #include "ar9330_1p2_initvals.h" -#include "ar955x_1p0_initvals.h" #include "ar9580_1p0_initvals.h" #include "ar9462_2p0_initvals.h" @@ -328,61 +327,7 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah) INIT_INI_ARRAY(&ah->ini_japan2484, AR9462_BBC_TXIFR_COEFFJ, ARRAY_SIZE(AR9462_BBC_TXIFR_COEFFJ), 2); - } else if (AR_SREV_9550(ah)) { - /* mac */ - INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0); - INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE], - ar955x_1p0_mac_core, - ARRAY_SIZE(ar955x_1p0_mac_core), 2); - INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST], - ar955x_1p0_mac_postamble, - ARRAY_SIZE(ar955x_1p0_mac_postamble), 5); - - /* bb */ - INIT_INI_ARRAY(&ah->iniBB[ATH_INI_PRE], NULL, 0, 0); - INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE], - ar955x_1p0_baseband_core, - ARRAY_SIZE(ar955x_1p0_baseband_core), 2); - INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST], - ar955x_1p0_baseband_postamble, - ARRAY_SIZE(ar955x_1p0_baseband_postamble), 5); - - /* radio */ - INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_PRE], NULL, 0, 0); - INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE], - ar955x_1p0_radio_core, - ARRAY_SIZE(ar955x_1p0_radio_core), 2); - INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST], - ar955x_1p0_radio_postamble, - ARRAY_SIZE(ar955x_1p0_radio_postamble), 5); - - /* soc */ - INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE], - ar955x_1p0_soc_preamble, - ARRAY_SIZE(ar955x_1p0_soc_preamble), 2); - INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_CORE], NULL, 0, 0); - INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST], - ar955x_1p0_soc_postamble, - ARRAY_SIZE(ar955x_1p0_soc_postamble), 5); - /* rx/tx gain */ - INIT_INI_ARRAY(&ah->iniModesRxGain, - ar955x_1p0_common_wo_xlna_rx_gain_table, - ARRAY_SIZE(ar955x_1p0_common_wo_xlna_rx_gain_table), - 2); - INIT_INI_ARRAY(&ah->ini_modes_rx_gain_bounds, - ar955x_1p0_common_wo_xlna_rx_gain_bounds, - ARRAY_SIZE(ar955x_1p0_common_wo_xlna_rx_gain_bounds), - 5); - INIT_INI_ARRAY(&ah->iniModesTxGain, - ar955x_1p0_modes_xpa_tx_gain_table, - ARRAY_SIZE(ar955x_1p0_modes_xpa_tx_gain_table), - 9); - - /* Fast clock modal settings */ - INIT_INI_ARRAY(&ah->iniModesFastClock, - ar955x_1p0_modes_fast_clock, - ARRAY_SIZE(ar955x_1p0_modes_fast_clock), 3); } else if (AR_SREV_9580(ah)) { /* mac */ INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0); @@ -525,11 +470,6 @@ static void ar9003_tx_gain_table_mode0(struct ath_hw *ah) ar9485_modes_lowest_ob_db_tx_gain_1_1, ARRAY_SIZE(ar9485_modes_lowest_ob_db_tx_gain_1_1), 5); - else if (AR_SREV_9550(ah)) - INIT_INI_ARRAY(&ah->iniModesTxGain, - ar955x_1p0_modes_xpa_tx_gain_table, - ARRAY_SIZE(ar955x_1p0_modes_xpa_tx_gain_table), - 9); else if (AR_SREV_9580(ah)) INIT_INI_ARRAY(&ah->iniModesTxGain, ar9580_1p0_lowest_ob_db_tx_gain_table, @@ -574,11 +514,6 @@ static void ar9003_tx_gain_table_mode1(struct ath_hw *ah) ar9580_1p0_high_ob_db_tx_gain_table, ARRAY_SIZE(ar9580_1p0_high_ob_db_tx_gain_table), 5); - else if (AR_SREV_9550(ah)) - INIT_INI_ARRAY(&ah->iniModesTxGain, - ar955x_1p0_modes_no_xpa_tx_gain_table, - ARRAY_SIZE(ar955x_1p0_modes_no_xpa_tx_gain_table), - 9); else if (AR_SREV_9462_20(ah)) INIT_INI_ARRAY(&ah->iniModesTxGain, ar9462_modes_high_ob_db_tx_gain_table_2p0, @@ -700,16 +635,7 @@ static void ar9003_rx_gain_table_mode0(struct ath_hw *ah) ar9485Common_wo_xlna_rx_gain_1_1, ARRAY_SIZE(ar9485Common_wo_xlna_rx_gain_1_1), 2); - else if (AR_SREV_9550(ah)) { - INIT_INI_ARRAY(&ah->iniModesRxGain, - ar955x_1p0_common_rx_gain_table, - ARRAY_SIZE(ar955x_1p0_common_rx_gain_table), - 2); - INIT_INI_ARRAY(&ah->ini_modes_rx_gain_bounds, - ar955x_1p0_common_rx_gain_bounds, - ARRAY_SIZE(ar955x_1p0_common_rx_gain_bounds), - 5); - } else if (AR_SREV_9580(ah)) + else if (AR_SREV_9580(ah)) INIT_INI_ARRAY(&ah->iniModesRxGain, ar9580_1p0_rx_gain_table, ARRAY_SIZE(ar9580_1p0_rx_gain_table), @@ -753,16 +679,7 @@ static void ar9003_rx_gain_table_mode1(struct ath_hw *ah) ar9462_common_wo_xlna_rx_gain_table_2p0, ARRAY_SIZE(ar9462_common_wo_xlna_rx_gain_table_2p0), 2); - else if (AR_SREV_9550(ah)) { - INIT_INI_ARRAY(&ah->iniModesRxGain, - ar955x_1p0_common_wo_xlna_rx_gain_table, - ARRAY_SIZE(ar955x_1p0_common_wo_xlna_rx_gain_table), - 2); - INIT_INI_ARRAY(&ah->ini_modes_rx_gain_bounds, - ar955x_1p0_common_wo_xlna_rx_gain_bounds, - ARRAY_SIZE(ar955x_1p0_common_wo_xlna_rx_gain_bounds), - 5); - } else if (AR_SREV_9580(ah)) + else if (AR_SREV_9580(ah)) INIT_INI_ARRAY(&ah->iniModesRxGain, ar9580_1p0_wo_xlna_rx_gain_table, ARRAY_SIZE(ar9580_1p0_wo_xlna_rx_gain_table), diff --git a/trunk/drivers/net/wireless/ath/ath9k/ar9003_mci.c b/trunk/drivers/net/wireless/ath/ath9k/ar9003_mci.c index 9a34fcaae3ff..61558375bfbf 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/ar9003_mci.c +++ b/trunk/drivers/net/wireless/ath/ath9k/ar9003_mci.c @@ -1015,9 +1015,12 @@ void ar9003_mci_2g5g_switch(struct ath_hw *ah, bool force) return; if (mci->is_2g) { - ar9003_mci_send_2g5g_status(ah, true); - ar9003_mci_send_lna_transfer(ah, true); - udelay(5); + if (!force) { + ar9003_mci_send_2g5g_status(ah, true); + + ar9003_mci_send_lna_transfer(ah, true); + udelay(5); + } REG_CLR_BIT(ah, AR_MCI_TX_CTRL, AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE); @@ -1027,8 +1030,10 @@ 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); } else { - ar9003_mci_send_lna_take(ah, true); - udelay(5); + if (!force) { + ar9003_mci_send_lna_take(ah, true); + udelay(5); + } REG_SET_BIT(ah, AR_MCI_TX_CTRL, AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE); @@ -1036,7 +1041,8 @@ void ar9003_mci_2g5g_switch(struct ath_hw *ah, bool force) AR_BTCOEX_CTRL_BT_OWN_SPDT_CTRL); ar9003_mci_osla_setup(ah, false); - ar9003_mci_send_2g5g_status(ah, true); + if (!force) + ar9003_mci_send_2g5g_status(ah, true); } } diff --git a/trunk/drivers/net/wireless/ath/ath9k/ar9003_paprd.c b/trunk/drivers/net/wireless/ath/ath9k/ar9003_paprd.c index 2c9f7d7ed4cc..3d400e8d6535 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/ar9003_paprd.c +++ b/trunk/drivers/net/wireless/ath/ath9k/ar9003_paprd.c @@ -211,7 +211,7 @@ static int ar9003_paprd_setup_single_table(struct ath_hw *ah) AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_NUM_CORR_STAGES, 7); REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3, AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_MIN_LOOPBACK_DEL, 1); - if (AR_SREV_9485(ah) || AR_SREV_9462(ah) || AR_SREV_9550(ah)) + if (AR_SREV_9485(ah) || AR_SREV_9462(ah)) REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3, AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_QUICK_DROP, -3); diff --git a/trunk/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/trunk/drivers/net/wireless/ath/ath9k/ar9003_phy.c index d2346dbad6cd..6b91ebb158fe 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/trunk/drivers/net/wireless/ath/ath9k/ar9003_phy.c @@ -99,7 +99,7 @@ static int ar9003_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan) channelSel = (freq * 4) / 120; chan_frac = (((freq * 4) % 120) * 0x20000) / 120; channelSel = (channelSel << 17) | chan_frac; - } else if (AR_SREV_9340(ah) || AR_SREV_9550(ah)) { + } else if (AR_SREV_9340(ah)) { if (ah->is_clk_25mhz) { u32 chan_frac; @@ -113,8 +113,7 @@ static int ar9003_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan) /* Set to 2G mode */ bMode = 1; } else { - if ((AR_SREV_9340(ah) || AR_SREV_9550(ah)) && - ah->is_clk_25mhz) { + if (AR_SREV_9340(ah) && ah->is_clk_25mhz) { u32 chan_frac; channelSel = (freq * 2) / 75; @@ -181,8 +180,7 @@ static void ar9003_hw_spur_mitigate_mrc_cck(struct ath_hw *ah, * is out-of-band and can be ignored. */ - if (AR_SREV_9485(ah) || AR_SREV_9340(ah) || AR_SREV_9330(ah) || - AR_SREV_9550(ah)) { + if (AR_SREV_9485(ah) || AR_SREV_9340(ah) || AR_SREV_9330(ah)) { if (spur_fbin_ptr[0] == 0) /* No spur */ return; max_spur_cnts = 5; @@ -207,8 +205,7 @@ static void ar9003_hw_spur_mitigate_mrc_cck(struct ath_hw *ah, if (AR_SREV_9462(ah) && (i == 0 || i == 3)) continue; negative = 0; - if (AR_SREV_9485(ah) || AR_SREV_9340(ah) || AR_SREV_9330(ah) || - AR_SREV_9550(ah)) + if (AR_SREV_9485(ah) || AR_SREV_9340(ah) || AR_SREV_9330(ah)) cur_bb_spur = ath9k_hw_fbin2freq(spur_fbin_ptr[i], IS_CHAN_2GHZ(chan)); else @@ -621,50 +618,6 @@ static void ar9003_hw_prog_ini(struct ath_hw *ah, } } -static int ar9550_hw_get_modes_txgain_index(struct ath_hw *ah, - struct ath9k_channel *chan) -{ - int ret; - - switch (chan->chanmode) { - case CHANNEL_A: - case CHANNEL_A_HT20: - if (chan->channel <= 5350) - ret = 1; - else if ((chan->channel > 5350) && (chan->channel <= 5600)) - ret = 3; - else - ret = 5; - break; - - case CHANNEL_A_HT40PLUS: - case CHANNEL_A_HT40MINUS: - if (chan->channel <= 5350) - ret = 2; - else if ((chan->channel > 5350) && (chan->channel <= 5600)) - ret = 4; - else - ret = 6; - break; - - case CHANNEL_G: - case CHANNEL_G_HT20: - case CHANNEL_B: - ret = 8; - break; - - case CHANNEL_G_HT40PLUS: - case CHANNEL_G_HT40MINUS: - ret = 7; - break; - - default: - ret = -EINVAL; - } - - return ret; -} - static int ar9003_hw_process_ini(struct ath_hw *ah, struct ath9k_channel *chan) { @@ -706,22 +659,7 @@ static int ar9003_hw_process_ini(struct ath_hw *ah, } REG_WRITE_ARRAY(&ah->iniModesRxGain, 1, regWrites); - if (AR_SREV_9550(ah)) - REG_WRITE_ARRAY(&ah->ini_modes_rx_gain_bounds, modesIndex, - regWrites); - - if (AR_SREV_9550(ah)) { - int modes_txgain_index; - - modes_txgain_index = ar9550_hw_get_modes_txgain_index(ah, chan); - if (modes_txgain_index < 0) - return -EINVAL; - - REG_WRITE_ARRAY(&ah->iniModesTxGain, modes_txgain_index, - regWrites); - } else { - REG_WRITE_ARRAY(&ah->iniModesTxGain, modesIndex, regWrites); - } + REG_WRITE_ARRAY(&ah->iniModesTxGain, modesIndex, regWrites); /* * For 5GHz channels requiring Fast Clock, apply diff --git a/trunk/drivers/net/wireless/ath/ath9k/ar9003_phy.h b/trunk/drivers/net/wireless/ath/ath9k/ar9003_phy.h index 751c83b21493..ed662c3bae5b 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/ar9003_phy.h +++ b/trunk/drivers/net/wireless/ath/ath9k/ar9003_phy.h @@ -636,8 +636,8 @@ #define AR_CH0_TOP (AR_SREV_9300(ah) ? 0x16288 : \ ((AR_SREV_9462(ah) ? 0x1628c : 0x16280))) -#define AR_CH0_TOP_XPABIASLVL (AR_SREV_9550(ah) ? 0x3c0 : 0x300) -#define AR_CH0_TOP_XPABIASLVL_S (AR_SREV_9550(ah) ? 6 : 8) +#define AR_CH0_TOP_XPABIASLVL (0x300) +#define AR_CH0_TOP_XPABIASLVL_S (8) #define AR_CH0_THERM (AR_SREV_9300(ah) ? 0x16290 : \ ((AR_SREV_9485(ah) ? 0x1628c : 0x16294))) @@ -650,8 +650,6 @@ #define AR_SWITCH_TABLE_COM_ALL_S (0) #define AR_SWITCH_TABLE_COM_AR9462_ALL (0xffffff) #define AR_SWITCH_TABLE_COM_AR9462_ALL_S (0) -#define AR_SWITCH_TABLE_COM_AR9550_ALL (0xffffff) -#define AR_SWITCH_TABLE_COM_AR9550_ALL_S (0) #define AR_SWITCH_TABLE_COM_SPDT (0x00f00000) #define AR_SWITCH_TABLE_COM_SPDT_ALL (0x0000fff0) #define AR_SWITCH_TABLE_COM_SPDT_ALL_S (4) diff --git a/trunk/drivers/net/wireless/ath/ath9k/ar955x_1p0_initvals.h b/trunk/drivers/net/wireless/ath/ath9k/ar955x_1p0_initvals.h deleted file mode 100644 index df97f21c52dc..000000000000 --- a/trunk/drivers/net/wireless/ath/ath9k/ar955x_1p0_initvals.h +++ /dev/null @@ -1,1284 +0,0 @@ -/* - * Copyright (c) 2010-2011 Atheros Communications Inc. - * Copyright (c) 2011-2012 Qualcomm Atheros Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef INITVALS_955X_1P0_H -#define INITVALS_955X_1P0_H - -/* AR955X 1.0 */ - -static const u32 ar955x_1p0_radio_postamble[][5] = { - /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x00016098, 0xd2dd5554, 0xd2dd5554, 0xd28b3330, 0xd28b3330}, - {0x0001609c, 0x0a566f3a, 0x0a566f3a, 0x06345f2a, 0x06345f2a}, - {0x000160ac, 0xa4647c00, 0xa4647c00, 0xa4646800, 0xa4646800}, - {0x000160b0, 0x01885f52, 0x01885f52, 0x04accf3a, 0x04accf3a}, - {0x00016104, 0xb7a00001, 0xb7a00001, 0xb7a00001, 0xb7a00001}, - {0x0001610c, 0xc0000000, 0xc0000000, 0xc0000000, 0xc0000000}, - {0x00016140, 0x10804008, 0x10804008, 0x10804008, 0x10804008}, - {0x00016504, 0xb7a00001, 0xb7a00001, 0xb7a00001, 0xb7a00001}, - {0x0001650c, 0xc0000000, 0xc0000000, 0xc0000000, 0xc0000000}, - {0x00016540, 0x10804008, 0x10804008, 0x10804008, 0x10804008}, - {0x00016904, 0xb7a00001, 0xb7a00001, 0xb7a00001, 0xb7a00001}, - {0x0001690c, 0xc0000000, 0xc0000000, 0xc0000000, 0xc0000000}, - {0x00016940, 0x10804008, 0x10804008, 0x10804008, 0x10804008}, -}; - -static const u32 ar955x_1p0_baseband_core_txfir_coeff_japan_2484[][2] = { - /* Addr allmodes */ - {0x0000a398, 0x00000000}, - {0x0000a39c, 0x6f7f0301}, - {0x0000a3a0, 0xca9228ee}, -}; - -static const u32 ar955x_1p0_baseband_postamble[][5] = { - /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8011, 0xd00a8011}, - {0x00009820, 0x206a022e, 0x206a022e, 0x206a012e, 0x206a012e}, - {0x00009824, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0}, - {0x00009828, 0x06903081, 0x06903081, 0x06903881, 0x06903881}, - {0x0000982c, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4}, - {0x00009830, 0x0000059c, 0x0000059c, 0x0000119c, 0x0000119c}, - {0x00009c00, 0x000000c4, 0x000000c4, 0x000000c4, 0x000000c4}, - {0x00009e00, 0x0372111a, 0x0372111a, 0x037216a0, 0x037216a0}, - {0x00009e04, 0x001c2020, 0x001c2020, 0x001c2020, 0x001c2020}, - {0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2}, - {0x00009e10, 0x7ec88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x7ec84d2e}, - {0x00009e14, 0x37b95d5e, 0x37b9605e, 0x3379605e, 0x33795d5e}, - {0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c}, - {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce}, - {0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021}, - {0x00009e3c, 0xcfa10820, 0xcfa10820, 0xcfa10822, 0xcfa10822}, - {0x00009e44, 0xfe321e27, 0xfe321e27, 0xfe291e27, 0xfe291e27}, - {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012}, - {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000}, - {0x0000a204, 0x005c0ec0, 0x005c0ec4, 0x005c0ec4, 0x005c0ec0}, - {0x0000a208, 0x00000104, 0x00000104, 0x00000004, 0x00000004}, - {0x0000a22c, 0x07e26a2f, 0x07e26a2f, 0x01026a2f, 0x01026a2f}, - {0x0000a230, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b}, - {0x0000a234, 0x00000fff, 0x10000fff, 0x10000fff, 0x00000fff}, - {0x0000a238, 0xffb01018, 0xffb01018, 0xffb01018, 0xffb01018}, - {0x0000a250, 0x00000000, 0x00000000, 0x00000210, 0x00000108}, - {0x0000a254, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898}, - {0x0000a258, 0x02020002, 0x02020002, 0x02020002, 0x02020002}, - {0x0000a25c, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e}, - {0x0000a260, 0x0a021501, 0x0a021501, 0x3a021501, 0x3a021501}, - {0x0000a264, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e}, - {0x0000a280, 0x00000007, 0x00000007, 0x0000000b, 0x0000000b}, - {0x0000a284, 0x00000000, 0x00000000, 0x00000010, 0x00000010}, - {0x0000a288, 0x00000110, 0x00000110, 0x00000110, 0x00000110}, - {0x0000a28c, 0x00022222, 0x00022222, 0x00022222, 0x00022222}, - {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18}, - {0x0000a2cc, 0x18c50033, 0x18c43433, 0x18c41033, 0x18c44c33}, - {0x0000a2d0, 0x00041982, 0x00041982, 0x00041982, 0x00041982}, - {0x0000a2d8, 0x7999a83b, 0x7999a83b, 0x7999a83b, 0x7999a83b}, - {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a830, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c}, - {0x0000ae04, 0x001c0000, 0x001c0000, 0x001c0000, 0x001c0000}, - {0x0000ae18, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000ae1c, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c}, - {0x0000ae20, 0x000001b5, 0x000001b5, 0x000001ce, 0x000001ce}, - {0x0000b284, 0x00000000, 0x00000000, 0x00000010, 0x00000010}, - {0x0000b830, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c}, - {0x0000be04, 0x001c0000, 0x001c0000, 0x001c0000, 0x001c0000}, - {0x0000be18, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000be1c, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c}, - {0x0000be20, 0x000001b5, 0x000001b5, 0x000001ce, 0x000001ce}, - {0x0000c284, 0x00000000, 0x00000000, 0x00000010, 0x00000010}, -}; - -static const u32 ar955x_1p0_radio_core[][2] = { - /* Addr allmodes */ - {0x00016000, 0x36db6db6}, - {0x00016004, 0x6db6db40}, - {0x00016008, 0x73f00000}, - {0x0001600c, 0x00000000}, - {0x00016040, 0x7f80fff8}, - {0x0001604c, 0x76d005b5}, - {0x00016050, 0x557cf031}, - {0x00016054, 0x13449440}, - {0x00016058, 0x0c51c92c}, - {0x0001605c, 0x3db7fffc}, - {0x00016060, 0xfffffffc}, - {0x00016064, 0x000f0278}, - {0x00016068, 0x6db6db6c}, - {0x0001606c, 0x6db60000}, - {0x00016080, 0x00080000}, - {0x00016084, 0x0e48048c}, - {0x00016088, 0x14214514}, - {0x0001608c, 0x119f101e}, - {0x00016090, 0x24926490}, - {0x00016094, 0x00000000}, - {0x000160a0, 0x0a108ffe}, - {0x000160a4, 0x812fc370}, - {0x000160a8, 0x423c8000}, - {0x000160b4, 0x92480080}, - {0x000160c0, 0x006db6d0}, - {0x000160c4, 0x6db6db60}, - {0x000160c8, 0x6db6db6c}, - {0x000160cc, 0x01e6c000}, - {0x00016100, 0x11999601}, - {0x00016108, 0x00080010}, - {0x00016144, 0x02084080}, - {0x00016148, 0x000080c0}, - {0x00016280, 0x01800804}, - {0x00016284, 0x00038dc5}, - {0x00016288, 0x00000000}, - {0x0001628c, 0x00000040}, - {0x00016380, 0x00000000}, - {0x00016384, 0x00000000}, - {0x00016388, 0x00400705}, - {0x0001638c, 0x00800700}, - {0x00016390, 0x00800700}, - {0x00016394, 0x00000000}, - {0x00016398, 0x00000000}, - {0x0001639c, 0x00000000}, - {0x000163a0, 0x00000001}, - {0x000163a4, 0x00000001}, - {0x000163a8, 0x00000000}, - {0x000163ac, 0x00000000}, - {0x000163b0, 0x00000000}, - {0x000163b4, 0x00000000}, - {0x000163b8, 0x00000000}, - {0x000163bc, 0x00000000}, - {0x000163c0, 0x000000a0}, - {0x000163c4, 0x000c0000}, - {0x000163c8, 0x14021402}, - {0x000163cc, 0x00001402}, - {0x000163d0, 0x00000000}, - {0x000163d4, 0x00000000}, - {0x00016400, 0x36db6db6}, - {0x00016404, 0x6db6db40}, - {0x00016408, 0x73f00000}, - {0x0001640c, 0x00000000}, - {0x00016440, 0x7f80fff8}, - {0x0001644c, 0x76d005b5}, - {0x00016450, 0x557cf031}, - {0x00016454, 0x13449440}, - {0x00016458, 0x0c51c92c}, - {0x0001645c, 0x3db7fffc}, - {0x00016460, 0xfffffffc}, - {0x00016464, 0x000f0278}, - {0x00016468, 0x6db6db6c}, - {0x0001646c, 0x6db60000}, - {0x00016500, 0x11999601}, - {0x00016508, 0x00080010}, - {0x00016544, 0x02084080}, - {0x00016548, 0x000080c0}, - {0x00016780, 0x00000000}, - {0x00016784, 0x00000000}, - {0x00016788, 0x00400705}, - {0x0001678c, 0x00800700}, - {0x00016790, 0x00800700}, - {0x00016794, 0x00000000}, - {0x00016798, 0x00000000}, - {0x0001679c, 0x00000000}, - {0x000167a0, 0x00000001}, - {0x000167a4, 0x00000001}, - {0x000167a8, 0x00000000}, - {0x000167ac, 0x00000000}, - {0x000167b0, 0x00000000}, - {0x000167b4, 0x00000000}, - {0x000167b8, 0x00000000}, - {0x000167bc, 0x00000000}, - {0x000167c0, 0x000000a0}, - {0x000167c4, 0x000c0000}, - {0x000167c8, 0x14021402}, - {0x000167cc, 0x00001402}, - {0x000167d0, 0x00000000}, - {0x000167d4, 0x00000000}, - {0x00016800, 0x36db6db6}, - {0x00016804, 0x6db6db40}, - {0x00016808, 0x73f00000}, - {0x0001680c, 0x00000000}, - {0x00016840, 0x7f80fff8}, - {0x0001684c, 0x76d005b5}, - {0x00016850, 0x557cf031}, - {0x00016854, 0x13449440}, - {0x00016858, 0x0c51c92c}, - {0x0001685c, 0x3db7fffc}, - {0x00016860, 0xfffffffc}, - {0x00016864, 0x000f0278}, - {0x00016868, 0x6db6db6c}, - {0x0001686c, 0x6db60000}, - {0x00016900, 0x11999601}, - {0x00016908, 0x00080010}, - {0x00016944, 0x02084080}, - {0x00016948, 0x000080c0}, - {0x00016b80, 0x00000000}, - {0x00016b84, 0x00000000}, - {0x00016b88, 0x00400705}, - {0x00016b8c, 0x00800700}, - {0x00016b90, 0x00800700}, - {0x00016b94, 0x00000000}, - {0x00016b98, 0x00000000}, - {0x00016b9c, 0x00000000}, - {0x00016ba0, 0x00000001}, - {0x00016ba4, 0x00000001}, - {0x00016ba8, 0x00000000}, - {0x00016bac, 0x00000000}, - {0x00016bb0, 0x00000000}, - {0x00016bb4, 0x00000000}, - {0x00016bb8, 0x00000000}, - {0x00016bbc, 0x00000000}, - {0x00016bc0, 0x000000a0}, - {0x00016bc4, 0x000c0000}, - {0x00016bc8, 0x14021402}, - {0x00016bcc, 0x00001402}, - {0x00016bd0, 0x00000000}, - {0x00016bd4, 0x00000000}, -}; - -static const u32 ar955x_1p0_modes_xpa_tx_gain_table[][9] = { - /* Addr 5G_HT20_L 5G_HT40_L 5G_HT20_M 5G_HT40_M 5G_HT20_H 5G_HT40_H 2G_HT40 2G_HT20 */ - {0x0000a2dc, 0xffffaaaa, 0xffffaaaa, 0xffffaaaa, 0xffffaaaa, 0xffffaaaa, 0xffffaaaa, 0xfffd5aaa, 0xfffd5aaa}, - {0x0000a2e0, 0xffffcccc, 0xffffcccc, 0xffffcccc, 0xffffcccc, 0xffffcccc, 0xffffcccc, 0xfffe9ccc, 0xfffe9ccc}, - {0x0000a2e4, 0xfffff0f0, 0xfffff0f0, 0xfffff0f0, 0xfffff0f0, 0xfffff0f0, 0xfffff0f0, 0xffffe0f0, 0xffffe0f0}, - {0x0000a2e8, 0xffffff00, 0xffffff00, 0xffffff00, 0xffffff00, 0xffffff00, 0xffffff00, 0xfffcff00, 0xfffcff00}, - {0x0000a410, 0x000050de, 0x000050de, 0x000050de, 0x000050de, 0x000050de, 0x000050de, 0x000050da, 0x000050da}, - {0x0000a500, 0x00000003, 0x00000003, 0x00000003, 0x00000003, 0x00000003, 0x00000003, 0x00000000, 0x00000000}, - {0x0000a504, 0x04000005, 0x04000005, 0x04000005, 0x04000005, 0x04000005, 0x04000005, 0x04000002, 0x04000002}, - {0x0000a508, 0x08000009, 0x08000009, 0x08000009, 0x08000009, 0x08000009, 0x08000009, 0x08000004, 0x08000004}, - {0x0000a50c, 0x0c00000b, 0x0c00000b, 0x0c00000b, 0x0c00000b, 0x0c00000b, 0x0c00000b, 0x0c000006, 0x0c000006}, - {0x0000a510, 0x1000000d, 0x1000000d, 0x1000000d, 0x1000000d, 0x1000000d, 0x1000000d, 0x0f00000a, 0x0f00000a}, - {0x0000a514, 0x14000011, 0x14000011, 0x14000011, 0x14000011, 0x14000011, 0x14000011, 0x1300000c, 0x1300000c}, - {0x0000a518, 0x19004008, 0x19004008, 0x19004008, 0x19004008, 0x18004008, 0x18004008, 0x1700000e, 0x1700000e}, - {0x0000a51c, 0x1d00400a, 0x1d00400a, 0x1d00400a, 0x1d00400a, 0x1c00400a, 0x1c00400a, 0x1b000064, 0x1b000064}, - {0x0000a520, 0x230020a2, 0x230020a2, 0x210020a2, 0x210020a2, 0x200020a2, 0x200020a2, 0x1f000242, 0x1f000242}, - {0x0000a524, 0x2500006e, 0x2500006e, 0x2500006e, 0x2500006e, 0x2400006e, 0x2400006e, 0x23000229, 0x23000229}, - {0x0000a528, 0x29022221, 0x29022221, 0x28022221, 0x28022221, 0x27022221, 0x27022221, 0x270002a2, 0x270002a2}, - {0x0000a52c, 0x2d00062a, 0x2d00062a, 0x2c00062a, 0x2c00062a, 0x2a00062a, 0x2a00062a, 0x2c001203, 0x2c001203}, - {0x0000a530, 0x340220a5, 0x340220a5, 0x320220a5, 0x320220a5, 0x2f0220a5, 0x2f0220a5, 0x30001803, 0x30001803}, - {0x0000a534, 0x380022c5, 0x380022c5, 0x350022c5, 0x350022c5, 0x320022c5, 0x320022c5, 0x33000881, 0x33000881}, - {0x0000a538, 0x3b002486, 0x3b002486, 0x39002486, 0x39002486, 0x36002486, 0x36002486, 0x38001809, 0x38001809}, - {0x0000a53c, 0x3f00248a, 0x3f00248a, 0x3d00248a, 0x3d00248a, 0x3a00248a, 0x3a00248a, 0x3a000814, 0x3a000814}, - {0x0000a540, 0x4202242c, 0x4202242c, 0x4102242c, 0x4102242c, 0x3f02242c, 0x3f02242c, 0x3f001a0c, 0x3f001a0c}, - {0x0000a544, 0x490044c6, 0x490044c6, 0x460044c6, 0x460044c6, 0x420044c6, 0x420044c6, 0x43001a0e, 0x43001a0e}, - {0x0000a548, 0x4d024485, 0x4d024485, 0x4a024485, 0x4a024485, 0x46024485, 0x46024485, 0x46001812, 0x46001812}, - {0x0000a54c, 0x51044483, 0x51044483, 0x4e044483, 0x4e044483, 0x4a044483, 0x4a044483, 0x49001884, 0x49001884}, - {0x0000a550, 0x5404a40c, 0x5404a40c, 0x5204a40c, 0x5204a40c, 0x4d04a40c, 0x4d04a40c, 0x4d001e84, 0x4d001e84}, - {0x0000a554, 0x57024632, 0x57024632, 0x55024632, 0x55024632, 0x52024632, 0x52024632, 0x50001e69, 0x50001e69}, - {0x0000a558, 0x5c00a634, 0x5c00a634, 0x5900a634, 0x5900a634, 0x5600a634, 0x5600a634, 0x550006f4, 0x550006f4}, - {0x0000a55c, 0x5f026832, 0x5f026832, 0x5d026832, 0x5d026832, 0x5a026832, 0x5a026832, 0x59000ad3, 0x59000ad3}, - {0x0000a560, 0x6602b012, 0x6602b012, 0x6202b012, 0x6202b012, 0x5d02b012, 0x5d02b012, 0x5e000ad5, 0x5e000ad5}, - {0x0000a564, 0x6e02d0e1, 0x6e02d0e1, 0x6802d0e1, 0x6802d0e1, 0x6002d0e1, 0x6002d0e1, 0x61001ced, 0x61001ced}, - {0x0000a568, 0x7202b4c4, 0x7202b4c4, 0x6c02b4c4, 0x6c02b4c4, 0x6502b4c4, 0x6502b4c4, 0x660018d4, 0x660018d4}, - {0x0000a56c, 0x75007894, 0x75007894, 0x70007894, 0x70007894, 0x6b007894, 0x6b007894, 0x660018d4, 0x660018d4}, - {0x0000a570, 0x7b025c74, 0x7b025c74, 0x75025c74, 0x75025c74, 0x70025c74, 0x70025c74, 0x660018d4, 0x660018d4}, - {0x0000a574, 0x8300bcb5, 0x8300bcb5, 0x7a00bcb5, 0x7a00bcb5, 0x7600bcb5, 0x7600bcb5, 0x660018d4, 0x660018d4}, - {0x0000a578, 0x8a04dc74, 0x8a04dc74, 0x7f04dc74, 0x7f04dc74, 0x7c04dc74, 0x7c04dc74, 0x660018d4, 0x660018d4}, - {0x0000a57c, 0x8a04dc74, 0x8a04dc74, 0x7f04dc74, 0x7f04dc74, 0x7c04dc74, 0x7c04dc74, 0x660018d4, 0x660018d4}, - {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x03804000, 0x03804000}, - {0x0000a610, 0x04c08c01, 0x04c08c01, 0x04808b01, 0x04808b01, 0x04808a01, 0x04808a01, 0x0300ca02, 0x0300ca02}, - {0x0000a614, 0x00c0c303, 0x00c0c303, 0x00c0c303, 0x00c0c303, 0x00c0c303, 0x00c0c303, 0x00000e04, 0x00000e04}, - {0x0000a618, 0x04010c01, 0x04010c01, 0x03c10b01, 0x03c10b01, 0x03810a01, 0x03810a01, 0x03014000, 0x03014000}, - {0x0000a61c, 0x03814e05, 0x03814e05, 0x03414d05, 0x03414d05, 0x03414d05, 0x03414d05, 0x00000000, 0x00000000}, - {0x0000a620, 0x04010303, 0x04010303, 0x03c10303, 0x03c10303, 0x03810303, 0x03810303, 0x00000000, 0x00000000}, - {0x0000a624, 0x03814e05, 0x03814e05, 0x03414d05, 0x03414d05, 0x03414d05, 0x03414d05, 0x03014000, 0x03014000}, - {0x0000a628, 0x00c0c000, 0x00c0c000, 0x00c0c000, 0x00c0c000, 0x00c0c000, 0x00c0c000, 0x03804c05, 0x03804c05}, - {0x0000a62c, 0x00c0c303, 0x00c0c303, 0x00c0c303, 0x00c0c303, 0x00c0c303, 0x00c0c303, 0x0701de06, 0x0701de06}, - {0x0000a630, 0x03418000, 0x03418000, 0x03018000, 0x03018000, 0x02c18000, 0x02c18000, 0x07819c07, 0x07819c07}, - {0x0000a634, 0x03815004, 0x03815004, 0x03414f04, 0x03414f04, 0x03414e04, 0x03414e04, 0x0701dc07, 0x0701dc07}, - {0x0000a638, 0x03005302, 0x03005302, 0x02c05202, 0x02c05202, 0x02805202, 0x02805202, 0x0701dc07, 0x0701dc07}, - {0x0000a63c, 0x04c09302, 0x04c09302, 0x04809202, 0x04809202, 0x04809202, 0x04809202, 0x0701dc07, 0x0701dc07}, - {0x0000b2dc, 0xffffaaaa, 0xffffaaaa, 0xffffaaaa, 0xffffaaaa, 0xffffaaaa, 0xffffaaaa, 0xfffd5aaa, 0xfffd5aaa}, - {0x0000b2e0, 0xffffcccc, 0xffffcccc, 0xffffcccc, 0xffffcccc, 0xffffcccc, 0xffffcccc, 0xfffe9ccc, 0xfffe9ccc}, - {0x0000b2e4, 0xfffff0f0, 0xfffff0f0, 0xfffff0f0, 0xfffff0f0, 0xfffff0f0, 0xfffff0f0, 0xffffe0f0, 0xffffe0f0}, - {0x0000b2e8, 0xffffff00, 0xffffff00, 0xffffff00, 0xffffff00, 0xffffff00, 0xffffff00, 0xfffcff00, 0xfffcff00}, - {0x0000c2dc, 0xffffaaaa, 0xffffaaaa, 0xffffaaaa, 0xffffaaaa, 0xffffaaaa, 0xffffaaaa, 0xfffd5aaa, 0xfffd5aaa}, - {0x0000c2e0, 0xffffcccc, 0xffffcccc, 0xffffcccc, 0xffffcccc, 0xffffcccc, 0xffffcccc, 0xfffe9ccc, 0xfffe9ccc}, - {0x0000c2e4, 0xfffff0f0, 0xfffff0f0, 0xfffff0f0, 0xfffff0f0, 0xfffff0f0, 0xfffff0f0, 0xffffe0f0, 0xffffe0f0}, - {0x0000c2e8, 0xffffff00, 0xffffff00, 0xffffff00, 0xffffff00, 0xffffff00, 0xffffff00, 0xfffcff00, 0xfffcff00}, - {0x00016044, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x010002d4, 0x010002d4}, - {0x00016048, 0x62482401, 0x62482401, 0x62482401, 0x62482401, 0x62482401, 0x62482401, 0x66482401, 0x66482401}, - {0x00016280, 0x01801e84, 0x01801e84, 0x01801e84, 0x01801e84, 0x01801e84, 0x01801e84, 0x01808e84, 0x01808e84}, - {0x00016444, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x010002d4, 0x010002d4}, - {0x00016448, 0x62482401, 0x62482401, 0x62482401, 0x62482401, 0x62482401, 0x62482401, 0x66482401, 0x66482401}, - {0x00016844, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x010002d4, 0x010002d4}, - {0x00016848, 0x62482401, 0x62482401, 0x62482401, 0x62482401, 0x62482401, 0x62482401, 0x66482401, 0x66482401}, -}; - -static const u32 ar955x_1p0_mac_core[][2] = { - /* Addr allmodes */ - {0x00000008, 0x00000000}, - {0x00000030, 0x00020085}, - {0x00000034, 0x00000005}, - {0x00000040, 0x00000000}, - {0x00000044, 0x00000000}, - {0x00000048, 0x00000008}, - {0x0000004c, 0x00000010}, - {0x00000050, 0x00000000}, - {0x00001040, 0x002ffc0f}, - {0x00001044, 0x002ffc0f}, - {0x00001048, 0x002ffc0f}, - {0x0000104c, 0x002ffc0f}, - {0x00001050, 0x002ffc0f}, - {0x00001054, 0x002ffc0f}, - {0x00001058, 0x002ffc0f}, - {0x0000105c, 0x002ffc0f}, - {0x00001060, 0x002ffc0f}, - {0x00001064, 0x002ffc0f}, - {0x000010f0, 0x00000100}, - {0x00001270, 0x00000000}, - {0x000012b0, 0x00000000}, - {0x000012f0, 0x00000000}, - {0x0000143c, 0x00000000}, - {0x0000147c, 0x00000000}, - {0x00008000, 0x00000000}, - {0x00008004, 0x00000000}, - {0x00008008, 0x00000000}, - {0x0000800c, 0x00000000}, - {0x00008018, 0x00000000}, - {0x00008020, 0x00000000}, - {0x00008038, 0x00000000}, - {0x0000803c, 0x00000000}, - {0x00008040, 0x00000000}, - {0x00008044, 0x00000000}, - {0x00008048, 0x00000000}, - {0x0000804c, 0xffffffff}, - {0x00008054, 0x00000000}, - {0x00008058, 0x00000000}, - {0x0000805c, 0x000fc78f}, - {0x00008060, 0x0000000f}, - {0x00008064, 0x00000000}, - {0x00008070, 0x00000310}, - {0x00008074, 0x00000020}, - {0x00008078, 0x00000000}, - {0x0000809c, 0x0000000f}, - {0x000080a0, 0x00000000}, - {0x000080a4, 0x02ff0000}, - {0x000080a8, 0x0e070605}, - {0x000080ac, 0x0000000d}, - {0x000080b0, 0x00000000}, - {0x000080b4, 0x00000000}, - {0x000080b8, 0x00000000}, - {0x000080bc, 0x00000000}, - {0x000080c0, 0x2a800000}, - {0x000080c4, 0x06900168}, - {0x000080c8, 0x13881c22}, - {0x000080cc, 0x01f40000}, - {0x000080d0, 0x00252500}, - {0x000080d4, 0x00a00000}, - {0x000080d8, 0x00400000}, - {0x000080dc, 0x00000000}, - {0x000080e0, 0xffffffff}, - {0x000080e4, 0x0000ffff}, - {0x000080e8, 0x3f3f3f3f}, - {0x000080ec, 0x00000000}, - {0x000080f0, 0x00000000}, - {0x000080f4, 0x00000000}, - {0x000080fc, 0x00020000}, - {0x00008100, 0x00000000}, - {0x00008108, 0x00000052}, - {0x0000810c, 0x00000000}, - {0x00008110, 0x00000000}, - {0x00008114, 0x000007ff}, - {0x00008118, 0x000000aa}, - {0x0000811c, 0x00003210}, - {0x00008124, 0x00000000}, - {0x00008128, 0x00000000}, - {0x0000812c, 0x00000000}, - {0x00008130, 0x00000000}, - {0x00008134, 0x00000000}, - {0x00008138, 0x00000000}, - {0x0000813c, 0x0000ffff}, - {0x00008140, 0x000000fe}, - {0x00008144, 0xffffffff}, - {0x00008168, 0x00000000}, - {0x0000816c, 0x00000000}, - {0x000081c0, 0x00000000}, - {0x000081c4, 0x33332210}, - {0x000081ec, 0x00000000}, - {0x000081f0, 0x00000000}, - {0x000081f4, 0x00000000}, - {0x000081f8, 0x00000000}, - {0x000081fc, 0x00000000}, - {0x00008240, 0x00100000}, - {0x00008244, 0x0010f400}, - {0x00008248, 0x00000800}, - {0x0000824c, 0x0001e800}, - {0x00008250, 0x00000000}, - {0x00008254, 0x00000000}, - {0x00008258, 0x00000000}, - {0x0000825c, 0x40000000}, - {0x00008260, 0x00080922}, - {0x00008264, 0x9d400010}, - {0x00008268, 0xffffffff}, - {0x0000826c, 0x0000ffff}, - {0x00008270, 0x00000000}, - {0x00008274, 0x40000000}, - {0x00008278, 0x003e4180}, - {0x0000827c, 0x00000004}, - {0x00008284, 0x0000002c}, - {0x00008288, 0x0000002c}, - {0x0000828c, 0x000000ff}, - {0x00008294, 0x00000000}, - {0x00008298, 0x00000000}, - {0x0000829c, 0x00000000}, - {0x00008300, 0x00001d40}, - {0x00008314, 0x00000000}, - {0x0000831c, 0x0000010d}, - {0x00008328, 0x00000000}, - {0x0000832c, 0x0000001f}, - {0x00008330, 0x00000302}, - {0x00008334, 0x00000700}, - {0x00008338, 0xffff0000}, - {0x0000833c, 0x02400000}, - {0x00008340, 0x000107ff}, - {0x00008344, 0xaa48107b}, - {0x00008348, 0x008f0000}, - {0x0000835c, 0x00000000}, - {0x00008360, 0xffffffff}, - {0x00008364, 0xffffffff}, - {0x00008368, 0x00000000}, - {0x00008370, 0x00000000}, - {0x00008374, 0x000000ff}, - {0x00008378, 0x00000000}, - {0x0000837c, 0x00000000}, - {0x00008380, 0xffffffff}, - {0x00008384, 0xffffffff}, - {0x00008390, 0xffffffff}, - {0x00008394, 0xffffffff}, - {0x00008398, 0x00000000}, - {0x0000839c, 0x00000000}, - {0x000083a0, 0x00000000}, - {0x000083a4, 0x0000fa14}, - {0x000083a8, 0x000f0c00}, - {0x000083ac, 0x33332210}, - {0x000083b0, 0x33332210}, - {0x000083b4, 0x33332210}, - {0x000083b8, 0x33332210}, - {0x000083bc, 0x00000000}, - {0x000083c0, 0x00000000}, - {0x000083c4, 0x00000000}, - {0x000083c8, 0x00000000}, - {0x000083cc, 0x00000200}, - {0x000083d0, 0x8c7901ff}, -}; - -static const u32 ar955x_1p0_common_rx_gain_table[][2] = { - /* Addr allmodes */ - {0x0000a000, 0x00010000}, - {0x0000a004, 0x00030002}, - {0x0000a008, 0x00050004}, - {0x0000a00c, 0x00810080}, - {0x0000a010, 0x00830082}, - {0x0000a014, 0x01810180}, - {0x0000a018, 0x01830182}, - {0x0000a01c, 0x01850184}, - {0x0000a020, 0x01890188}, - {0x0000a024, 0x018b018a}, - {0x0000a028, 0x018d018c}, - {0x0000a02c, 0x01910190}, - {0x0000a030, 0x01930192}, - {0x0000a034, 0x01950194}, - {0x0000a038, 0x038a0196}, - {0x0000a03c, 0x038c038b}, - {0x0000a040, 0x0390038d}, - {0x0000a044, 0x03920391}, - {0x0000a048, 0x03940393}, - {0x0000a04c, 0x03960395}, - {0x0000a050, 0x00000000}, - {0x0000a054, 0x00000000}, - {0x0000a058, 0x00000000}, - {0x0000a05c, 0x00000000}, - {0x0000a060, 0x00000000}, - {0x0000a064, 0x00000000}, - {0x0000a068, 0x00000000}, - {0x0000a06c, 0x00000000}, - {0x0000a070, 0x00000000}, - {0x0000a074, 0x00000000}, - {0x0000a078, 0x00000000}, - {0x0000a07c, 0x00000000}, - {0x0000a080, 0x22222229}, - {0x0000a084, 0x1d1d1d1d}, - {0x0000a088, 0x1d1d1d1d}, - {0x0000a08c, 0x1d1d1d1d}, - {0x0000a090, 0x171d1d1d}, - {0x0000a094, 0x11111717}, - {0x0000a098, 0x00030311}, - {0x0000a09c, 0x00000000}, - {0x0000a0a0, 0x00000000}, - {0x0000a0a4, 0x00000000}, - {0x0000a0a8, 0x00000000}, - {0x0000a0ac, 0x00000000}, - {0x0000a0b0, 0x00000000}, - {0x0000a0b4, 0x00000000}, - {0x0000a0b8, 0x00000000}, - {0x0000a0bc, 0x00000000}, - {0x0000a0c0, 0x001f0000}, - {0x0000a0c4, 0x01000101}, - {0x0000a0c8, 0x011e011f}, - {0x0000a0cc, 0x011c011d}, - {0x0000a0d0, 0x02030204}, - {0x0000a0d4, 0x02010202}, - {0x0000a0d8, 0x021f0200}, - {0x0000a0dc, 0x0302021e}, - {0x0000a0e0, 0x03000301}, - {0x0000a0e4, 0x031e031f}, - {0x0000a0e8, 0x0402031d}, - {0x0000a0ec, 0x04000401}, - {0x0000a0f0, 0x041e041f}, - {0x0000a0f4, 0x0502041d}, - {0x0000a0f8, 0x05000501}, - {0x0000a0fc, 0x051e051f}, - {0x0000a100, 0x06010602}, - {0x0000a104, 0x061f0600}, - {0x0000a108, 0x061d061e}, - {0x0000a10c, 0x07020703}, - {0x0000a110, 0x07000701}, - {0x0000a114, 0x00000000}, - {0x0000a118, 0x00000000}, - {0x0000a11c, 0x00000000}, - {0x0000a120, 0x00000000}, - {0x0000a124, 0x00000000}, - {0x0000a128, 0x00000000}, - {0x0000a12c, 0x00000000}, - {0x0000a130, 0x00000000}, - {0x0000a134, 0x00000000}, - {0x0000a138, 0x00000000}, - {0x0000a13c, 0x00000000}, - {0x0000a140, 0x001f0000}, - {0x0000a144, 0x01000101}, - {0x0000a148, 0x011e011f}, - {0x0000a14c, 0x011c011d}, - {0x0000a150, 0x02030204}, - {0x0000a154, 0x02010202}, - {0x0000a158, 0x021f0200}, - {0x0000a15c, 0x0302021e}, - {0x0000a160, 0x03000301}, - {0x0000a164, 0x031e031f}, - {0x0000a168, 0x0402031d}, - {0x0000a16c, 0x04000401}, - {0x0000a170, 0x041e041f}, - {0x0000a174, 0x0502041d}, - {0x0000a178, 0x05000501}, - {0x0000a17c, 0x051e051f}, - {0x0000a180, 0x06010602}, - {0x0000a184, 0x061f0600}, - {0x0000a188, 0x061d061e}, - {0x0000a18c, 0x07020703}, - {0x0000a190, 0x07000701}, - {0x0000a194, 0x00000000}, - {0x0000a198, 0x00000000}, - {0x0000a19c, 0x00000000}, - {0x0000a1a0, 0x00000000}, - {0x0000a1a4, 0x00000000}, - {0x0000a1a8, 0x00000000}, - {0x0000a1ac, 0x00000000}, - {0x0000a1b0, 0x00000000}, - {0x0000a1b4, 0x00000000}, - {0x0000a1b8, 0x00000000}, - {0x0000a1bc, 0x00000000}, - {0x0000a1c0, 0x00000000}, - {0x0000a1c4, 0x00000000}, - {0x0000a1c8, 0x00000000}, - {0x0000a1cc, 0x00000000}, - {0x0000a1d0, 0x00000000}, - {0x0000a1d4, 0x00000000}, - {0x0000a1d8, 0x00000000}, - {0x0000a1dc, 0x00000000}, - {0x0000a1e0, 0x00000000}, - {0x0000a1e4, 0x00000000}, - {0x0000a1e8, 0x00000000}, - {0x0000a1ec, 0x00000000}, - {0x0000a1f0, 0x00000396}, - {0x0000a1f4, 0x00000396}, - {0x0000a1f8, 0x00000396}, - {0x0000a1fc, 0x00000196}, - {0x0000b000, 0x00010000}, - {0x0000b004, 0x00030002}, - {0x0000b008, 0x00050004}, - {0x0000b00c, 0x00810080}, - {0x0000b010, 0x00830082}, - {0x0000b014, 0x01810180}, - {0x0000b018, 0x01830182}, - {0x0000b01c, 0x01850184}, - {0x0000b020, 0x02810280}, - {0x0000b024, 0x02830282}, - {0x0000b028, 0x02850284}, - {0x0000b02c, 0x02890288}, - {0x0000b030, 0x028b028a}, - {0x0000b034, 0x0388028c}, - {0x0000b038, 0x038a0389}, - {0x0000b03c, 0x038c038b}, - {0x0000b040, 0x0390038d}, - {0x0000b044, 0x03920391}, - {0x0000b048, 0x03940393}, - {0x0000b04c, 0x03960395}, - {0x0000b050, 0x00000000}, - {0x0000b054, 0x00000000}, - {0x0000b058, 0x00000000}, - {0x0000b05c, 0x00000000}, - {0x0000b060, 0x00000000}, - {0x0000b064, 0x00000000}, - {0x0000b068, 0x00000000}, - {0x0000b06c, 0x00000000}, - {0x0000b070, 0x00000000}, - {0x0000b074, 0x00000000}, - {0x0000b078, 0x00000000}, - {0x0000b07c, 0x00000000}, - {0x0000b080, 0x23232323}, - {0x0000b084, 0x21232323}, - {0x0000b088, 0x19191c1e}, - {0x0000b08c, 0x12141417}, - {0x0000b090, 0x07070e0e}, - {0x0000b094, 0x03030305}, - {0x0000b098, 0x00000003}, - {0x0000b09c, 0x00000000}, - {0x0000b0a0, 0x00000000}, - {0x0000b0a4, 0x00000000}, - {0x0000b0a8, 0x00000000}, - {0x0000b0ac, 0x00000000}, - {0x0000b0b0, 0x00000000}, - {0x0000b0b4, 0x00000000}, - {0x0000b0b8, 0x00000000}, - {0x0000b0bc, 0x00000000}, - {0x0000b0c0, 0x003f0020}, - {0x0000b0c4, 0x00400041}, - {0x0000b0c8, 0x0140005f}, - {0x0000b0cc, 0x0160015f}, - {0x0000b0d0, 0x017e017f}, - {0x0000b0d4, 0x02410242}, - {0x0000b0d8, 0x025f0240}, - {0x0000b0dc, 0x027f0260}, - {0x0000b0e0, 0x0341027e}, - {0x0000b0e4, 0x035f0340}, - {0x0000b0e8, 0x037f0360}, - {0x0000b0ec, 0x04400441}, - {0x0000b0f0, 0x0460045f}, - {0x0000b0f4, 0x0541047f}, - {0x0000b0f8, 0x055f0540}, - {0x0000b0fc, 0x057f0560}, - {0x0000b100, 0x06400641}, - {0x0000b104, 0x0660065f}, - {0x0000b108, 0x067e067f}, - {0x0000b10c, 0x07410742}, - {0x0000b110, 0x075f0740}, - {0x0000b114, 0x077f0760}, - {0x0000b118, 0x07800781}, - {0x0000b11c, 0x07a0079f}, - {0x0000b120, 0x07c107bf}, - {0x0000b124, 0x000007c0}, - {0x0000b128, 0x00000000}, - {0x0000b12c, 0x00000000}, - {0x0000b130, 0x00000000}, - {0x0000b134, 0x00000000}, - {0x0000b138, 0x00000000}, - {0x0000b13c, 0x00000000}, - {0x0000b140, 0x003f0020}, - {0x0000b144, 0x00400041}, - {0x0000b148, 0x0140005f}, - {0x0000b14c, 0x0160015f}, - {0x0000b150, 0x017e017f}, - {0x0000b154, 0x02410242}, - {0x0000b158, 0x025f0240}, - {0x0000b15c, 0x027f0260}, - {0x0000b160, 0x0341027e}, - {0x0000b164, 0x035f0340}, - {0x0000b168, 0x037f0360}, - {0x0000b16c, 0x04400441}, - {0x0000b170, 0x0460045f}, - {0x0000b174, 0x0541047f}, - {0x0000b178, 0x055f0540}, - {0x0000b17c, 0x057f0560}, - {0x0000b180, 0x06400641}, - {0x0000b184, 0x0660065f}, - {0x0000b188, 0x067e067f}, - {0x0000b18c, 0x07410742}, - {0x0000b190, 0x075f0740}, - {0x0000b194, 0x077f0760}, - {0x0000b198, 0x07800781}, - {0x0000b19c, 0x07a0079f}, - {0x0000b1a0, 0x07c107bf}, - {0x0000b1a4, 0x000007c0}, - {0x0000b1a8, 0x00000000}, - {0x0000b1ac, 0x00000000}, - {0x0000b1b0, 0x00000000}, - {0x0000b1b4, 0x00000000}, - {0x0000b1b8, 0x00000000}, - {0x0000b1bc, 0x00000000}, - {0x0000b1c0, 0x00000000}, - {0x0000b1c4, 0x00000000}, - {0x0000b1c8, 0x00000000}, - {0x0000b1cc, 0x00000000}, - {0x0000b1d0, 0x00000000}, - {0x0000b1d4, 0x00000000}, - {0x0000b1d8, 0x00000000}, - {0x0000b1dc, 0x00000000}, - {0x0000b1e0, 0x00000000}, - {0x0000b1e4, 0x00000000}, - {0x0000b1e8, 0x00000000}, - {0x0000b1ec, 0x00000000}, - {0x0000b1f0, 0x00000396}, - {0x0000b1f4, 0x00000396}, - {0x0000b1f8, 0x00000396}, - {0x0000b1fc, 0x00000196}, -}; - -static const u32 ar955x_1p0_baseband_core[][2] = { - /* Addr allmodes */ - {0x00009800, 0xafe68e30}, - {0x00009804, 0xfd14e000}, - {0x00009808, 0x9c0a9f6b}, - {0x0000980c, 0x04900000}, - {0x00009814, 0x0280c00a}, - {0x00009818, 0x00000000}, - {0x0000981c, 0x00020028}, - {0x00009834, 0x6400a190}, - {0x00009838, 0x0108ecff}, - {0x0000983c, 0x14000600}, - {0x00009880, 0x201fff00}, - {0x00009884, 0x00001042}, - {0x000098a4, 0x00200400}, - {0x000098b0, 0x32840bbe}, - {0x000098bc, 0x00000002}, - {0x000098d0, 0x004b6a8e}, - {0x000098d4, 0x00000820}, - {0x000098dc, 0x00000000}, - {0x000098f0, 0x00000000}, - {0x000098f4, 0x00000000}, - {0x00009c04, 0xff55ff55}, - {0x00009c08, 0x0320ff55}, - {0x00009c0c, 0x00000000}, - {0x00009c10, 0x00000000}, - {0x00009c14, 0x00046384}, - {0x00009c18, 0x05b6b440}, - {0x00009c1c, 0x00b6b440}, - {0x00009d00, 0xc080a333}, - {0x00009d04, 0x40206c10}, - {0x00009d08, 0x009c4060}, - {0x00009d0c, 0x9883800a}, - {0x00009d10, 0x01834061}, - {0x00009d14, 0x00c0040b}, - {0x00009d18, 0x00000000}, - {0x00009e08, 0x0038230c}, - {0x00009e24, 0x990bb515}, - {0x00009e28, 0x0c6f0000}, - {0x00009e30, 0x06336f77}, - {0x00009e34, 0x6af6532f}, - {0x00009e38, 0x0cc80c00}, - {0x00009e40, 0x0d261820}, - {0x00009e4c, 0x00001004}, - {0x00009e50, 0x00ff03f1}, - {0x00009fc0, 0x813e4788}, - {0x00009fc4, 0x0001efb5}, - {0x00009fcc, 0x40000014}, - {0x00009fd0, 0x01193b93}, - {0x0000a20c, 0x00000000}, - {0x0000a220, 0x00000000}, - {0x0000a224, 0x00000000}, - {0x0000a228, 0x10002310}, - {0x0000a23c, 0x00000000}, - {0x0000a244, 0x0c000000}, - {0x0000a248, 0x00000140}, - {0x0000a2a0, 0x00000007}, - {0x0000a2c0, 0x00000007}, - {0x0000a2c8, 0x00000000}, - {0x0000a2d4, 0x00000000}, - {0x0000a2ec, 0x00000000}, - {0x0000a2f0, 0x00000000}, - {0x0000a2f4, 0x00000000}, - {0x0000a2f8, 0x00000000}, - {0x0000a344, 0x00000000}, - {0x0000a34c, 0x00000000}, - {0x0000a350, 0x0000a000}, - {0x0000a364, 0x00000000}, - {0x0000a370, 0x00000000}, - {0x0000a390, 0x00000001}, - {0x0000a394, 0x00000444}, - {0x0000a398, 0x1f020503}, - {0x0000a39c, 0x29180c03}, - {0x0000a3a0, 0x9a8b6844}, - {0x0000a3a4, 0x00000000}, - {0x0000a3a8, 0xaaaaaaaa}, - {0x0000a3ac, 0x3c466478}, - {0x0000a3c0, 0x20202020}, - {0x0000a3c4, 0x22222220}, - {0x0000a3c8, 0x20200020}, - {0x0000a3cc, 0x20202020}, - {0x0000a3d0, 0x20202020}, - {0x0000a3d4, 0x20202020}, - {0x0000a3d8, 0x20202020}, - {0x0000a3dc, 0x20202020}, - {0x0000a3e0, 0x20202020}, - {0x0000a3e4, 0x20202020}, - {0x0000a3e8, 0x20202020}, - {0x0000a3ec, 0x20202020}, - {0x0000a3f0, 0x00000000}, - {0x0000a3f4, 0x00000000}, - {0x0000a3f8, 0x0c9bd380}, - {0x0000a3fc, 0x000f0f01}, - {0x0000a400, 0x8fa91f01}, - {0x0000a404, 0x00000000}, - {0x0000a408, 0x0e79e5c6}, - {0x0000a40c, 0x00820820}, - {0x0000a414, 0x1ce739ce}, - {0x0000a418, 0x2d001dce}, - {0x0000a41c, 0x1ce739ce}, - {0x0000a420, 0x000001ce}, - {0x0000a424, 0x1ce739ce}, - {0x0000a428, 0x000001ce}, - {0x0000a42c, 0x1ce739ce}, - {0x0000a430, 0x1ce739ce}, - {0x0000a434, 0x00000000}, - {0x0000a438, 0x00001801}, - {0x0000a43c, 0x00100000}, - {0x0000a444, 0x00000000}, - {0x0000a448, 0x05000080}, - {0x0000a44c, 0x00000001}, - {0x0000a450, 0x00010000}, - {0x0000a458, 0x00000000}, - {0x0000a644, 0x3fad9d74}, - {0x0000a648, 0x0048060a}, - {0x0000a64c, 0x00003c37}, - {0x0000a670, 0x03020100}, - {0x0000a674, 0x09080504}, - {0x0000a678, 0x0d0c0b0a}, - {0x0000a67c, 0x13121110}, - {0x0000a680, 0x31301514}, - {0x0000a684, 0x35343332}, - {0x0000a688, 0x00000036}, - {0x0000a690, 0x00000838}, - {0x0000a7cc, 0x00000000}, - {0x0000a7d0, 0x00000000}, - {0x0000a7d4, 0x00000004}, - {0x0000a7dc, 0x00000000}, - {0x0000a8d0, 0x004b6a8e}, - {0x0000a8d4, 0x00000820}, - {0x0000a8dc, 0x00000000}, - {0x0000a8f0, 0x00000000}, - {0x0000a8f4, 0x00000000}, - {0x0000b2d0, 0x00000080}, - {0x0000b2d4, 0x00000000}, - {0x0000b2ec, 0x00000000}, - {0x0000b2f0, 0x00000000}, - {0x0000b2f4, 0x00000000}, - {0x0000b2f8, 0x00000000}, - {0x0000b408, 0x0e79e5c0}, - {0x0000b40c, 0x00820820}, - {0x0000b420, 0x00000000}, - {0x0000b8d0, 0x004b6a8e}, - {0x0000b8d4, 0x00000820}, - {0x0000b8dc, 0x00000000}, - {0x0000b8f0, 0x00000000}, - {0x0000b8f4, 0x00000000}, - {0x0000c2d0, 0x00000080}, - {0x0000c2d4, 0x00000000}, - {0x0000c2ec, 0x00000000}, - {0x0000c2f0, 0x00000000}, - {0x0000c2f4, 0x00000000}, - {0x0000c2f8, 0x00000000}, - {0x0000c408, 0x0e79e5c0}, - {0x0000c40c, 0x00820820}, - {0x0000c420, 0x00000000}, -}; - -static const u32 ar955x_1p0_common_wo_xlna_rx_gain_table[][2] = { - /* Addr allmodes */ - {0x0000a000, 0x00010000}, - {0x0000a004, 0x00030002}, - {0x0000a008, 0x00050004}, - {0x0000a00c, 0x00810080}, - {0x0000a010, 0x00830082}, - {0x0000a014, 0x01810180}, - {0x0000a018, 0x01830182}, - {0x0000a01c, 0x01850184}, - {0x0000a020, 0x01890188}, - {0x0000a024, 0x018b018a}, - {0x0000a028, 0x018d018c}, - {0x0000a02c, 0x03820190}, - {0x0000a030, 0x03840383}, - {0x0000a034, 0x03880385}, - {0x0000a038, 0x038a0389}, - {0x0000a03c, 0x038c038b}, - {0x0000a040, 0x0390038d}, - {0x0000a044, 0x03920391}, - {0x0000a048, 0x03940393}, - {0x0000a04c, 0x03960395}, - {0x0000a050, 0x00000000}, - {0x0000a054, 0x00000000}, - {0x0000a058, 0x00000000}, - {0x0000a05c, 0x00000000}, - {0x0000a060, 0x00000000}, - {0x0000a064, 0x00000000}, - {0x0000a068, 0x00000000}, - {0x0000a06c, 0x00000000}, - {0x0000a070, 0x00000000}, - {0x0000a074, 0x00000000}, - {0x0000a078, 0x00000000}, - {0x0000a07c, 0x00000000}, - {0x0000a080, 0x29292929}, - {0x0000a084, 0x29292929}, - {0x0000a088, 0x29292929}, - {0x0000a08c, 0x29292929}, - {0x0000a090, 0x22292929}, - {0x0000a094, 0x1d1d2222}, - {0x0000a098, 0x0c111117}, - {0x0000a09c, 0x00030303}, - {0x0000a0a0, 0x00000000}, - {0x0000a0a4, 0x00000000}, - {0x0000a0a8, 0x00000000}, - {0x0000a0ac, 0x00000000}, - {0x0000a0b0, 0x00000000}, - {0x0000a0b4, 0x00000000}, - {0x0000a0b8, 0x00000000}, - {0x0000a0bc, 0x00000000}, - {0x0000a0c0, 0x001f0000}, - {0x0000a0c4, 0x01000101}, - {0x0000a0c8, 0x011e011f}, - {0x0000a0cc, 0x011c011d}, - {0x0000a0d0, 0x02030204}, - {0x0000a0d4, 0x02010202}, - {0x0000a0d8, 0x021f0200}, - {0x0000a0dc, 0x0302021e}, - {0x0000a0e0, 0x03000301}, - {0x0000a0e4, 0x031e031f}, - {0x0000a0e8, 0x0402031d}, - {0x0000a0ec, 0x04000401}, - {0x0000a0f0, 0x041e041f}, - {0x0000a0f4, 0x0502041d}, - {0x0000a0f8, 0x05000501}, - {0x0000a0fc, 0x051e051f}, - {0x0000a100, 0x06010602}, - {0x0000a104, 0x061f0600}, - {0x0000a108, 0x061d061e}, - {0x0000a10c, 0x07020703}, - {0x0000a110, 0x07000701}, - {0x0000a114, 0x00000000}, - {0x0000a118, 0x00000000}, - {0x0000a11c, 0x00000000}, - {0x0000a120, 0x00000000}, - {0x0000a124, 0x00000000}, - {0x0000a128, 0x00000000}, - {0x0000a12c, 0x00000000}, - {0x0000a130, 0x00000000}, - {0x0000a134, 0x00000000}, - {0x0000a138, 0x00000000}, - {0x0000a13c, 0x00000000}, - {0x0000a140, 0x001f0000}, - {0x0000a144, 0x01000101}, - {0x0000a148, 0x011e011f}, - {0x0000a14c, 0x011c011d}, - {0x0000a150, 0x02030204}, - {0x0000a154, 0x02010202}, - {0x0000a158, 0x021f0200}, - {0x0000a15c, 0x0302021e}, - {0x0000a160, 0x03000301}, - {0x0000a164, 0x031e031f}, - {0x0000a168, 0x0402031d}, - {0x0000a16c, 0x04000401}, - {0x0000a170, 0x041e041f}, - {0x0000a174, 0x0502041d}, - {0x0000a178, 0x05000501}, - {0x0000a17c, 0x051e051f}, - {0x0000a180, 0x06010602}, - {0x0000a184, 0x061f0600}, - {0x0000a188, 0x061d061e}, - {0x0000a18c, 0x07020703}, - {0x0000a190, 0x07000701}, - {0x0000a194, 0x00000000}, - {0x0000a198, 0x00000000}, - {0x0000a19c, 0x00000000}, - {0x0000a1a0, 0x00000000}, - {0x0000a1a4, 0x00000000}, - {0x0000a1a8, 0x00000000}, - {0x0000a1ac, 0x00000000}, - {0x0000a1b0, 0x00000000}, - {0x0000a1b4, 0x00000000}, - {0x0000a1b8, 0x00000000}, - {0x0000a1bc, 0x00000000}, - {0x0000a1c0, 0x00000000}, - {0x0000a1c4, 0x00000000}, - {0x0000a1c8, 0x00000000}, - {0x0000a1cc, 0x00000000}, - {0x0000a1d0, 0x00000000}, - {0x0000a1d4, 0x00000000}, - {0x0000a1d8, 0x00000000}, - {0x0000a1dc, 0x00000000}, - {0x0000a1e0, 0x00000000}, - {0x0000a1e4, 0x00000000}, - {0x0000a1e8, 0x00000000}, - {0x0000a1ec, 0x00000000}, - {0x0000a1f0, 0x00000396}, - {0x0000a1f4, 0x00000396}, - {0x0000a1f8, 0x00000396}, - {0x0000a1fc, 0x00000196}, - {0x0000b000, 0x00010000}, - {0x0000b004, 0x00030002}, - {0x0000b008, 0x00050004}, - {0x0000b00c, 0x00810080}, - {0x0000b010, 0x00830082}, - {0x0000b014, 0x01810180}, - {0x0000b018, 0x01830182}, - {0x0000b01c, 0x01850184}, - {0x0000b020, 0x02810280}, - {0x0000b024, 0x02830282}, - {0x0000b028, 0x02850284}, - {0x0000b02c, 0x02890288}, - {0x0000b030, 0x028b028a}, - {0x0000b034, 0x0388028c}, - {0x0000b038, 0x038a0389}, - {0x0000b03c, 0x038c038b}, - {0x0000b040, 0x0390038d}, - {0x0000b044, 0x03920391}, - {0x0000b048, 0x03940393}, - {0x0000b04c, 0x03960395}, - {0x0000b050, 0x00000000}, - {0x0000b054, 0x00000000}, - {0x0000b058, 0x00000000}, - {0x0000b05c, 0x00000000}, - {0x0000b060, 0x00000000}, - {0x0000b064, 0x00000000}, - {0x0000b068, 0x00000000}, - {0x0000b06c, 0x00000000}, - {0x0000b070, 0x00000000}, - {0x0000b074, 0x00000000}, - {0x0000b078, 0x00000000}, - {0x0000b07c, 0x00000000}, - {0x0000b080, 0x32323232}, - {0x0000b084, 0x2f2f3232}, - {0x0000b088, 0x23282a2d}, - {0x0000b08c, 0x1c1e2123}, - {0x0000b090, 0x14171919}, - {0x0000b094, 0x0e0e1214}, - {0x0000b098, 0x03050707}, - {0x0000b09c, 0x00030303}, - {0x0000b0a0, 0x00000000}, - {0x0000b0a4, 0x00000000}, - {0x0000b0a8, 0x00000000}, - {0x0000b0ac, 0x00000000}, - {0x0000b0b0, 0x00000000}, - {0x0000b0b4, 0x00000000}, - {0x0000b0b8, 0x00000000}, - {0x0000b0bc, 0x00000000}, - {0x0000b0c0, 0x003f0020}, - {0x0000b0c4, 0x00400041}, - {0x0000b0c8, 0x0140005f}, - {0x0000b0cc, 0x0160015f}, - {0x0000b0d0, 0x017e017f}, - {0x0000b0d4, 0x02410242}, - {0x0000b0d8, 0x025f0240}, - {0x0000b0dc, 0x027f0260}, - {0x0000b0e0, 0x0341027e}, - {0x0000b0e4, 0x035f0340}, - {0x0000b0e8, 0x037f0360}, - {0x0000b0ec, 0x04400441}, - {0x0000b0f0, 0x0460045f}, - {0x0000b0f4, 0x0541047f}, - {0x0000b0f8, 0x055f0540}, - {0x0000b0fc, 0x057f0560}, - {0x0000b100, 0x06400641}, - {0x0000b104, 0x0660065f}, - {0x0000b108, 0x067e067f}, - {0x0000b10c, 0x07410742}, - {0x0000b110, 0x075f0740}, - {0x0000b114, 0x077f0760}, - {0x0000b118, 0x07800781}, - {0x0000b11c, 0x07a0079f}, - {0x0000b120, 0x07c107bf}, - {0x0000b124, 0x000007c0}, - {0x0000b128, 0x00000000}, - {0x0000b12c, 0x00000000}, - {0x0000b130, 0x00000000}, - {0x0000b134, 0x00000000}, - {0x0000b138, 0x00000000}, - {0x0000b13c, 0x00000000}, - {0x0000b140, 0x003f0020}, - {0x0000b144, 0x00400041}, - {0x0000b148, 0x0140005f}, - {0x0000b14c, 0x0160015f}, - {0x0000b150, 0x017e017f}, - {0x0000b154, 0x02410242}, - {0x0000b158, 0x025f0240}, - {0x0000b15c, 0x027f0260}, - {0x0000b160, 0x0341027e}, - {0x0000b164, 0x035f0340}, - {0x0000b168, 0x037f0360}, - {0x0000b16c, 0x04400441}, - {0x0000b170, 0x0460045f}, - {0x0000b174, 0x0541047f}, - {0x0000b178, 0x055f0540}, - {0x0000b17c, 0x057f0560}, - {0x0000b180, 0x06400641}, - {0x0000b184, 0x0660065f}, - {0x0000b188, 0x067e067f}, - {0x0000b18c, 0x07410742}, - {0x0000b190, 0x075f0740}, - {0x0000b194, 0x077f0760}, - {0x0000b198, 0x07800781}, - {0x0000b19c, 0x07a0079f}, - {0x0000b1a0, 0x07c107bf}, - {0x0000b1a4, 0x000007c0}, - {0x0000b1a8, 0x00000000}, - {0x0000b1ac, 0x00000000}, - {0x0000b1b0, 0x00000000}, - {0x0000b1b4, 0x00000000}, - {0x0000b1b8, 0x00000000}, - {0x0000b1bc, 0x00000000}, - {0x0000b1c0, 0x00000000}, - {0x0000b1c4, 0x00000000}, - {0x0000b1c8, 0x00000000}, - {0x0000b1cc, 0x00000000}, - {0x0000b1d0, 0x00000000}, - {0x0000b1d4, 0x00000000}, - {0x0000b1d8, 0x00000000}, - {0x0000b1dc, 0x00000000}, - {0x0000b1e0, 0x00000000}, - {0x0000b1e4, 0x00000000}, - {0x0000b1e8, 0x00000000}, - {0x0000b1ec, 0x00000000}, - {0x0000b1f0, 0x00000396}, - {0x0000b1f4, 0x00000396}, - {0x0000b1f8, 0x00000396}, - {0x0000b1fc, 0x00000196}, -}; - -static const u32 ar955x_1p0_soc_preamble[][2] = { - /* Addr allmodes */ - {0x00007000, 0x00000000}, - {0x00007004, 0x00000000}, - {0x00007008, 0x00000000}, - {0x0000700c, 0x00000000}, - {0x0000701c, 0x00000000}, - {0x00007020, 0x00000000}, - {0x00007024, 0x00000000}, - {0x00007028, 0x00000000}, - {0x0000702c, 0x00000000}, - {0x00007030, 0x00000000}, - {0x00007034, 0x00000002}, - {0x00007038, 0x000004c2}, - {0x00007048, 0x00000000}, -}; - -static const u32 ar955x_1p0_common_wo_xlna_rx_gain_bounds[][5] = { - /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x00009e44, 0xfe321e27, 0xfe321e27, 0xfe291e27, 0xfe291e27}, - {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012}, -}; - -static const u32 ar955x_1p0_mac_postamble[][5] = { - /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160}, - {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c}, - {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38}, - {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00}, - {0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b}, - {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810}, - {0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a}, - {0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440}, -}; - -static const u32 ar955x_1p0_common_rx_gain_bounds[][5] = { - /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x00009e44, 0xfe321e27, 0xfe321e27, 0xfe291e27, 0xfe291e27}, - {0x00009e48, 0x5030201a, 0x5030201a, 0x50302018, 0x50302018}, -}; - -static const u32 ar955x_1p0_modes_no_xpa_tx_gain_table[][9] = { - /* Addr 5G_HT20_L 5G_HT40_L 5G_HT20_M 5G_HT40_M 5G_HT20_H 5G_HT40_H 2G_HT40 2G_HT20 */ - {0x0000a2dc, 0x01feee00, 0x01feee00, 0x01feee00, 0x01feee00, 0x01feee00, 0x01feee00, 0xfffe5aaa, 0xfffe5aaa}, - {0x0000a2e0, 0x0000f000, 0x0000f000, 0x0000f000, 0x0000f000, 0x0000f000, 0x0000f000, 0xfffe9ccc, 0xfffe9ccc}, - {0x0000a2e4, 0x01ff0000, 0x01ff0000, 0x01ff0000, 0x01ff0000, 0x01ff0000, 0x01ff0000, 0xffffe0f0, 0xffffe0f0}, - {0x0000a2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffef00, 0xffffef00}, - {0x0000a410, 0x000050d8, 0x000050d8, 0x000050d8, 0x000050d8, 0x000050d8, 0x000050d8, 0x000050d7, 0x000050d7}, - {0x0000a500, 0x00002220, 0x00002220, 0x00002220, 0x00002220, 0x00002220, 0x00002220, 0x00000000, 0x00000000}, - {0x0000a504, 0x04002222, 0x04002222, 0x04002222, 0x04002222, 0x04002222, 0x04002222, 0x04000002, 0x04000002}, - {0x0000a508, 0x09002421, 0x09002421, 0x09002421, 0x09002421, 0x09002421, 0x09002421, 0x08000004, 0x08000004}, - {0x0000a50c, 0x0d002621, 0x0d002621, 0x0d002621, 0x0d002621, 0x0d002621, 0x0d002621, 0x0b000006, 0x0b000006}, - {0x0000a510, 0x13004620, 0x13004620, 0x13004620, 0x13004620, 0x13004620, 0x13004620, 0x0f00000a, 0x0f00000a}, - {0x0000a514, 0x19004a20, 0x19004a20, 0x19004a20, 0x19004a20, 0x19004a20, 0x19004a20, 0x1300000c, 0x1300000c}, - {0x0000a518, 0x1d004e20, 0x1d004e20, 0x1d004e20, 0x1d004e20, 0x1d004e20, 0x1d004e20, 0x1700000e, 0x1700000e}, - {0x0000a51c, 0x21005420, 0x21005420, 0x21005420, 0x21005420, 0x21005420, 0x21005420, 0x1b000012, 0x1b000012}, - {0x0000a520, 0x26005e20, 0x26005e20, 0x26005e20, 0x26005e20, 0x26005e20, 0x26005e20, 0x1f00004a, 0x1f00004a}, - {0x0000a524, 0x2b005e40, 0x2b005e40, 0x2b005e40, 0x2b005e40, 0x2b005e40, 0x2b005e40, 0x23000244, 0x23000244}, - {0x0000a528, 0x2f005e42, 0x2f005e42, 0x2f005e42, 0x2f005e42, 0x2f005e42, 0x2f005e42, 0x2700022b, 0x2700022b}, - {0x0000a52c, 0x33005e44, 0x33005e44, 0x33005e44, 0x33005e44, 0x33005e44, 0x33005e44, 0x2b000625, 0x2b000625}, - {0x0000a530, 0x38005e65, 0x38005e65, 0x38005e65, 0x38005e65, 0x38005e65, 0x38005e65, 0x2f001006, 0x2f001006}, - {0x0000a534, 0x3c005e69, 0x3c005e69, 0x3c005e69, 0x3c005e69, 0x3c005e69, 0x3c005e69, 0x330008a0, 0x330008a0}, - {0x0000a538, 0x40005e6b, 0x40005e6b, 0x40005e6b, 0x40005e6b, 0x40005e6b, 0x40005e6b, 0x37000a2a, 0x37000a2a}, - {0x0000a53c, 0x44005e6d, 0x44005e6d, 0x44005e6d, 0x44005e6d, 0x44005e6d, 0x44005e6d, 0x3b001c23, 0x3b001c23}, - {0x0000a540, 0x49005e72, 0x49005e72, 0x49005e72, 0x49005e72, 0x49005e72, 0x49005e72, 0x3f0014a0, 0x3f0014a0}, - {0x0000a544, 0x4e005eb2, 0x4e005eb2, 0x4e005eb2, 0x4e005eb2, 0x4e005eb2, 0x4e005eb2, 0x43001882, 0x43001882}, - {0x0000a548, 0x53005f12, 0x53005f12, 0x53005f12, 0x53005f12, 0x53005f12, 0x53005f12, 0x47001ca2, 0x47001ca2}, - {0x0000a54c, 0x59025eb2, 0x59025eb2, 0x59025eb2, 0x59025eb2, 0x59025eb2, 0x59025eb2, 0x4b001ec3, 0x4b001ec3}, - {0x0000a550, 0x5e025f12, 0x5e025f12, 0x5e025f12, 0x5e025f12, 0x5e025f12, 0x5e025f12, 0x4f00148c, 0x4f00148c}, - {0x0000a554, 0x61027f12, 0x61027f12, 0x61027f12, 0x61027f12, 0x61027f12, 0x61027f12, 0x53001c6e, 0x53001c6e}, - {0x0000a558, 0x6702bf12, 0x6702bf12, 0x6702bf12, 0x6702bf12, 0x6702bf12, 0x6702bf12, 0x57001c92, 0x57001c92}, - {0x0000a55c, 0x6b02bf14, 0x6b02bf14, 0x6b02bf14, 0x6b02bf14, 0x6b02bf14, 0x6b02bf14, 0x5c001af6, 0x5c001af6}, - {0x0000a560, 0x6f02bf16, 0x6f02bf16, 0x6f02bf16, 0x6f02bf16, 0x6f02bf16, 0x6f02bf16, 0x5c001af6, 0x5c001af6}, - {0x0000a564, 0x6f02bf16, 0x6f02bf16, 0x6f02bf16, 0x6f02bf16, 0x6f02bf16, 0x6f02bf16, 0x5c001af6, 0x5c001af6}, - {0x0000a568, 0x6f02bf16, 0x6f02bf16, 0x6f02bf16, 0x6f02bf16, 0x6f02bf16, 0x6f02bf16, 0x5c001af6, 0x5c001af6}, - {0x0000a56c, 0x6f02bf16, 0x6f02bf16, 0x6f02bf16, 0x6f02bf16, 0x6f02bf16, 0x6f02bf16, 0x5c001af6, 0x5c001af6}, - {0x0000a570, 0x6f02bf16, 0x6f02bf16, 0x6f02bf16, 0x6f02bf16, 0x6f02bf16, 0x6f02bf16, 0x5c001af6, 0x5c001af6}, - {0x0000a574, 0x6f02bf16, 0x6f02bf16, 0x6f02bf16, 0x6f02bf16, 0x6f02bf16, 0x6f02bf16, 0x5c001af6, 0x5c001af6}, - {0x0000a578, 0x6f02bf16, 0x6f02bf16, 0x6f02bf16, 0x6f02bf16, 0x6f02bf16, 0x6f02bf16, 0x5c001af6, 0x5c001af6}, - {0x0000a57c, 0x6f02bf16, 0x6f02bf16, 0x6f02bf16, 0x6f02bf16, 0x6f02bf16, 0x6f02bf16, 0x5c001af6, 0x5c001af6}, - {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a610, 0x00804000, 0x00804000, 0x00804000, 0x00804000, 0x00804000, 0x00804000, 0x04005001, 0x04005001}, - {0x0000a614, 0x00804201, 0x00804201, 0x00804201, 0x00804201, 0x00804201, 0x00804201, 0x03808e02, 0x03808e02}, - {0x0000a618, 0x0280c802, 0x0280c802, 0x0280c802, 0x0280c802, 0x0280c802, 0x0280c802, 0x0300c000, 0x0300c000}, - {0x0000a61c, 0x0280ca03, 0x0280ca03, 0x0280ca03, 0x0280ca03, 0x0280ca03, 0x0280ca03, 0x03808e02, 0x03808e02}, - {0x0000a620, 0x04c15104, 0x04c15104, 0x04c15104, 0x04c15104, 0x04c15104, 0x04c15104, 0x03410c03, 0x03410c03}, - {0x0000a624, 0x04c15305, 0x04c15305, 0x04c15305, 0x04c15305, 0x04c15305, 0x04c15305, 0x04014c03, 0x04014c03}, - {0x0000a628, 0x04c15305, 0x04c15305, 0x04c15305, 0x04c15305, 0x04c15305, 0x04c15305, 0x05818d04, 0x05818d04}, - {0x0000a62c, 0x04c15305, 0x04c15305, 0x04c15305, 0x04c15305, 0x04c15305, 0x04c15305, 0x0801cd04, 0x0801cd04}, - {0x0000a630, 0x04c15305, 0x04c15305, 0x04c15305, 0x04c15305, 0x04c15305, 0x04c15305, 0x0801e007, 0x0801e007}, - {0x0000a634, 0x04c15305, 0x04c15305, 0x04c15305, 0x04c15305, 0x04c15305, 0x04c15305, 0x0801e007, 0x0801e007}, - {0x0000a638, 0x04c15305, 0x04c15305, 0x04c15305, 0x04c15305, 0x04c15305, 0x04c15305, 0x0801e007, 0x0801e007}, - {0x0000a63c, 0x04c15305, 0x04c15305, 0x04c15305, 0x04c15305, 0x04c15305, 0x04c15305, 0x0801e007, 0x0801e007}, - {0x0000b2dc, 0x01feee00, 0x01feee00, 0x01feee00, 0x01feee00, 0x01feee00, 0x01feee00, 0xfffe5aaa, 0xfffe5aaa}, - {0x0000b2e0, 0x0000f000, 0x0000f000, 0x0000f000, 0x0000f000, 0x0000f000, 0x0000f000, 0xfffe9ccc, 0xfffe9ccc}, - {0x0000b2e4, 0x01ff0000, 0x01ff0000, 0x01ff0000, 0x01ff0000, 0x01ff0000, 0x01ff0000, 0xffffe0f0, 0xffffe0f0}, - {0x0000b2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffef00, 0xffffef00}, - {0x0000c2dc, 0x01feee00, 0x01feee00, 0x01feee00, 0x01feee00, 0x01feee00, 0x01feee00, 0xfffe5aaa, 0xfffe5aaa}, - {0x0000c2e0, 0x0000f000, 0x0000f000, 0x0000f000, 0x0000f000, 0x0000f000, 0x0000f000, 0xfffe9ccc, 0xfffe9ccc}, - {0x0000c2e4, 0x01ff0000, 0x01ff0000, 0x01ff0000, 0x01ff0000, 0x01ff0000, 0x01ff0000, 0xffffe0f0, 0xffffe0f0}, - {0x0000c2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffef00, 0xffffef00}, - {0x00016044, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x054922d4, 0x054922d4}, - {0x00016048, 0x66482401, 0x66482401, 0x66482401, 0x66482401, 0x66482401, 0x66482401, 0x66482401, 0x66482401}, - {0x00016444, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x054922d4, 0x054922d4}, - {0x00016448, 0x66482401, 0x66482401, 0x66482401, 0x66482401, 0x66482401, 0x66482401, 0x66482401, 0x66482401}, - {0x00016844, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x054922d4, 0x054922d4}, - {0x00016848, 0x66482401, 0x66482401, 0x66482401, 0x66482401, 0x66482401, 0x66482401, 0x66482401, 0x66482401}, -}; - -static const u32 ar955x_1p0_soc_postamble[][5] = { - /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x00007010, 0x00000023, 0x00000023, 0x00000023, 0x00000023}, -}; - -static const u32 ar955x_1p0_modes_fast_clock[][3] = { - /* Addr 5G_HT20 5G_HT40 */ - {0x00001030, 0x00000268, 0x000004d0}, - {0x00001070, 0x0000018c, 0x00000318}, - {0x000010b0, 0x00000fd0, 0x00001fa0}, - {0x00008014, 0x044c044c, 0x08980898}, - {0x0000801c, 0x148ec02b, 0x148ec057}, - {0x00008318, 0x000044c0, 0x00008980}, - {0x00009e00, 0x0372131c, 0x0372131c}, - {0x0000a230, 0x0000000b, 0x00000016}, - {0x0000a254, 0x00000898, 0x00001130}, -}; - -#endif /* INITVALS_955X_1P0_H */ diff --git a/trunk/drivers/net/wireless/ath/ath9k/ath9k.h b/trunk/drivers/net/wireless/ath/ath9k/ath9k.h index 79840d6deef2..fe39eb4c42a1 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/trunk/drivers/net/wireless/ath/ath9k/ath9k.h @@ -481,7 +481,6 @@ void ath9k_btcoex_timer_resume(struct ath_softc *sc); void ath9k_btcoex_timer_pause(struct ath_softc *sc); void ath9k_btcoex_handle_interrupt(struct ath_softc *sc, u32 status); u16 ath9k_btcoex_aggr_limit(struct ath_softc *sc, u32 max_4ms_framelen); -void ath9k_btcoex_stop_gen_timer(struct ath_softc *sc); #else static inline int ath9k_init_btcoex(struct ath_softc *sc) { @@ -505,9 +504,6 @@ static inline u16 ath9k_btcoex_aggr_limit(struct ath_softc *sc, { return 0; } -static inline void ath9k_btcoex_stop_gen_timer(struct ath_softc *sc) -{ -} #endif /* CONFIG_ATH9K_BTCOEX_SUPPORT */ /********************/ diff --git a/trunk/drivers/net/wireless/ath/ath9k/gpio.c b/trunk/drivers/net/wireless/ath/ath9k/gpio.c index bacdb8fb4ef4..9ae6a4d97691 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/gpio.c +++ b/trunk/drivers/net/wireless/ath/ath9k/gpio.c @@ -194,14 +194,6 @@ static void ath_btcoex_period_timer(unsigned long data) struct ath_mci_profile *mci = &btcoex->mci; u32 timer_period; bool is_btscan; - unsigned long flags; - - spin_lock_irqsave(&sc->sc_pm_lock, flags); - if (sc->sc_ah->power_mode == ATH9K_PM_NETWORK_SLEEP) { - spin_unlock_irqrestore(&sc->sc_pm_lock, flags); - goto skip_hw_wakeup; - } - spin_unlock_irqrestore(&sc->sc_pm_lock, flags); ath9k_ps_wakeup(sc); if (!(ah->caps.hw_caps & ATH9K_HW_CAP_MCI)) @@ -240,7 +232,6 @@ static void ath_btcoex_period_timer(unsigned long data) } ath9k_ps_restore(sc); -skip_hw_wakeup: timer_period = btcoex->btcoex_period; mod_timer(&btcoex->period_timer, jiffies + msecs_to_jiffies(timer_period)); } @@ -314,8 +305,7 @@ void ath9k_btcoex_timer_resume(struct ath_softc *sc) btcoex->bt_priority_cnt = 0; btcoex->bt_priority_time = jiffies; - clear_bit(BT_OP_PRIORITY_DETECTED, &btcoex->op_flags); - clear_bit(BT_OP_SCAN, &btcoex->op_flags); + btcoex->op_flags &= ~(BT_OP_PRIORITY_DETECTED | BT_OP_SCAN); mod_timer(&btcoex->period_timer, jiffies); } @@ -337,13 +327,6 @@ void ath9k_btcoex_timer_pause(struct ath_softc *sc) btcoex->hw_timer_enabled = false; } -void ath9k_btcoex_stop_gen_timer(struct ath_softc *sc) -{ - struct ath_btcoex *btcoex = &sc->btcoex; - - ath9k_gen_timer_stop(sc->sc_ah, btcoex->no_stomp_timer); -} - u16 ath9k_btcoex_aggr_limit(struct ath_softc *sc, u32 max_4ms_framelen) { struct ath_btcoex *btcoex = &sc->btcoex; @@ -393,9 +376,9 @@ void ath9k_stop_btcoex(struct ath_softc *sc) if (ah->btcoex_hw.enabled && ath9k_hw_get_btcoex_scheme(ah) != ATH_BTCOEX_CFG_NONE) { + ath9k_hw_btcoex_disable(ah); 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)) ath_mci_flush_profile(&sc->btcoex.mci); } @@ -403,13 +386,11 @@ void ath9k_stop_btcoex(struct ath_softc *sc) void ath9k_deinit_btcoex(struct ath_softc *sc) { - struct ath_hw *ah = sc->sc_ah; - if ((sc->btcoex.no_stomp_timer) && ath9k_hw_get_btcoex_scheme(sc->sc_ah) == ATH_BTCOEX_CFG_3WIRE) ath_gen_timer_free(sc->sc_ah, sc->btcoex.no_stomp_timer); - if (ath9k_hw_mci_is_enabled(ah)) + if (AR_SREV_9462(sc->sc_ah)) ath_mci_cleanup(sc); } diff --git a/trunk/drivers/net/wireless/ath/ath9k/hw.c b/trunk/drivers/net/wireless/ath/ath9k/hw.c index c1659d079513..ebfb2a3c645c 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/hw.c +++ b/trunk/drivers/net/wireless/ath/ath9k/hw.c @@ -342,9 +342,6 @@ static void ath9k_hw_read_revisions(struct ath_hw *ah) val = REG_READ(ah, AR_SREV); ah->hw_version.macRev = MS(val, AR_SREV_REVISION2); return; - case AR9300_DEVID_QCA955X: - ah->hw_version.macVersion = AR_SREV_VERSION_9550; - return; } val = REG_READ(ah, AR_SREV) & AR_SREV_ID; @@ -649,7 +646,6 @@ static int __ath9k_hw_init(struct ath_hw *ah) case AR_SREV_VERSION_9485: case AR_SREV_VERSION_9340: case AR_SREV_VERSION_9462: - case AR_SREV_VERSION_9550: break; default: ath_err(common, @@ -659,7 +655,7 @@ static int __ath9k_hw_init(struct ath_hw *ah) } if (AR_SREV_9271(ah) || AR_SREV_9100(ah) || AR_SREV_9340(ah) || - AR_SREV_9330(ah) || AR_SREV_9550(ah)) + AR_SREV_9330(ah)) ah->is_pciexpress = false; ah->hw_version.phyRev = REG_READ(ah, AR_PHY_CHIP_ID); @@ -731,7 +727,6 @@ int ath9k_hw_init(struct ath_hw *ah) case AR9300_DEVID_AR9485_PCIE: case AR9300_DEVID_AR9330: case AR9300_DEVID_AR9340: - case AR9300_DEVID_QCA955X: case AR9300_DEVID_AR9580: case AR9300_DEVID_AR9462: break; @@ -870,7 +865,7 @@ static void ath9k_hw_init_pll(struct ath_hw *ah, /* program BB PLL phase_shift */ REG_RMW_FIELD(ah, AR_CH0_BB_DPLL3, AR_CH0_BB_DPLL3_PHASE_SHIFT, 0x1); - } else if (AR_SREV_9340(ah) || AR_SREV_9550(ah)) { + } else if (AR_SREV_9340(ah)) { u32 regval, pll2_divint, pll2_divfrac, refdiv; REG_WRITE(ah, AR_RTC_PLL_CONTROL, 0x1142c); @@ -884,15 +879,9 @@ static void ath9k_hw_init_pll(struct ath_hw *ah, pll2_divfrac = 0x1eb85; refdiv = 3; } else { - if (AR_SREV_9340(ah)) { - pll2_divint = 88; - pll2_divfrac = 0; - refdiv = 5; - } else { - pll2_divint = 0x11; - pll2_divfrac = 0x26666; - refdiv = 1; - } + pll2_divint = 88; + pll2_divfrac = 0; + refdiv = 5; } regval = REG_READ(ah, AR_PHY_PLL_MODE); @@ -905,12 +894,8 @@ static void ath9k_hw_init_pll(struct ath_hw *ah, udelay(100); regval = REG_READ(ah, AR_PHY_PLL_MODE); - if (AR_SREV_9340(ah)) - regval = (regval & 0x80071fff) | (0x1 << 30) | - (0x1 << 13) | (0x4 << 26) | (0x18 << 19); - else - regval = (regval & 0x80071fff) | (0x3 << 30) | - (0x1 << 13) | (0x4 << 26) | (0x60 << 19); + regval = (regval & 0x80071fff) | (0x1 << 30) | (0x1 << 13) | + (0x4 << 26) | (0x18 << 19); REG_WRITE(ah, AR_PHY_PLL_MODE, regval); REG_WRITE(ah, AR_PHY_PLL_MODE, REG_READ(ah, AR_PHY_PLL_MODE) & 0xfffeffff); @@ -921,8 +906,7 @@ static void ath9k_hw_init_pll(struct ath_hw *ah, REG_WRITE(ah, AR_RTC_PLL_CONTROL, pll); - if (AR_SREV_9485(ah) || AR_SREV_9340(ah) || AR_SREV_9330(ah) || - AR_SREV_9550(ah)) + if (AR_SREV_9485(ah) || AR_SREV_9340(ah) || AR_SREV_9330(ah)) udelay(1000); /* Switch the core clock for ar9271 to 117Mhz */ @@ -935,7 +919,7 @@ static void ath9k_hw_init_pll(struct ath_hw *ah, REG_WRITE(ah, AR_RTC_SLEEP_CLK, AR_RTC_FORCE_DERIVED_CLK); - if (AR_SREV_9340(ah) || AR_SREV_9550(ah)) { + if (AR_SREV_9340(ah)) { if (ah->is_clk_25mhz) { REG_WRITE(ah, AR_RTC_DERIVED_CLK, 0x17c << 1); REG_WRITE(ah, AR_SLP32_MODE, 0x0010f3d7); @@ -959,7 +943,7 @@ static void ath9k_hw_init_interrupt_masks(struct ath_hw *ah, AR_IMR_RXORN | AR_IMR_BCNMISC; - if (AR_SREV_9340(ah) || AR_SREV_9550(ah)) + if (AR_SREV_9340(ah)) sync_default &= ~AR_INTR_SYNC_HOST1_FATAL; if (AR_SREV_9300_20_OR_LATER(ah)) { @@ -1965,6 +1949,9 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, if (!ath9k_hw_init_cal(ah, chan)) return -EIO; + ath9k_hw_loadnf(ah, chan); + ath9k_hw_start_nfcal(ah, true); + if (ath9k_hw_mci_is_enabled(ah) && ar9003_mci_end_reset(ah, chan, caldata)) return -EIO; @@ -2000,8 +1987,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, REG_WRITE(ah, AR_CFG, AR_CFG_SWTD | AR_CFG_SWRD); } #ifdef __BIG_ENDIAN - else if (AR_SREV_9330(ah) || AR_SREV_9340(ah) || - AR_SREV_9550(ah)) + else if (AR_SREV_9330(ah) || AR_SREV_9340(ah)) REG_RMW(ah, AR_CFG, AR_CFG_SWRB | AR_CFG_SWTB, 0); else REG_WRITE(ah, AR_CFG, AR_CFG_SWTD | AR_CFG_SWRD); @@ -2014,9 +2000,6 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, if (ath9k_hw_mci_is_enabled(ah)) ar9003_mci_check_bt(ah); - ath9k_hw_loadnf(ah, chan); - ath9k_hw_start_nfcal(ah, true); - if (AR_SREV_9300_20_OR_LATER(ah)) { ar9003_hw_bb_watchdog_config(ah); @@ -3154,7 +3137,6 @@ static struct { { AR_SREV_VERSION_9340, "9340" }, { AR_SREV_VERSION_9485, "9485" }, { AR_SREV_VERSION_9462, "9462" }, - { AR_SREV_VERSION_9550, "9550" }, }; /* For devices with external radios */ diff --git a/trunk/drivers/net/wireless/ath/ath9k/hw.h b/trunk/drivers/net/wireless/ath/ath9k/hw.h index 26da1732978d..94096607cbdd 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/hw.h +++ b/trunk/drivers/net/wireless/ath/ath9k/hw.h @@ -48,7 +48,6 @@ #define AR9300_DEVID_AR9580 0x0033 #define AR9300_DEVID_AR9462 0x0034 #define AR9300_DEVID_AR9330 0x0035 -#define AR9300_DEVID_QCA955X 0x0038 #define AR5416_AR9100_DEVID 0x000b @@ -819,7 +818,6 @@ struct ath_hw { struct ar5416IniArray iniModesFastClock; struct ar5416IniArray iniAdditional; struct ar5416IniArray iniModesRxGain; - struct ar5416IniArray ini_modes_rx_gain_bounds; struct ar5416IniArray iniModesTxGain; struct ar5416IniArray iniCckfirNormal; struct ar5416IniArray iniCckfirJapan2484; diff --git a/trunk/drivers/net/wireless/ath/ath9k/mac.c b/trunk/drivers/net/wireless/ath/ath9k/mac.c index 7990cd55599c..04ef775ccee1 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/mac.c +++ b/trunk/drivers/net/wireless/ath/ath9k/mac.c @@ -810,7 +810,7 @@ void ath9k_hw_enable_interrupts(struct ath_hw *ah) return; } - if (AR_SREV_9340(ah) || AR_SREV_9550(ah)) + if (AR_SREV_9340(ah)) sync_default &= ~AR_INTR_SYNC_HOST1_FATAL; async_mask = AR_INTR_MAC_IRQ; diff --git a/trunk/drivers/net/wireless/ath/ath9k/mac.h b/trunk/drivers/net/wireless/ath/ath9k/mac.h index 0eba36dca6f8..21c955609e6c 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/mac.h +++ b/trunk/drivers/net/wireless/ath/ath9k/mac.h @@ -646,7 +646,6 @@ enum ath9k_rx_filter { ATH9K_RX_FILTER_PHYRADAR = 0x00002000, ATH9K_RX_FILTER_MCAST_BCAST_ALL = 0x00008000, ATH9K_RX_FILTER_CONTROL_WRAPPER = 0x00080000, - ATH9K_RX_FILTER_4ADDRESS = 0x00100000, }; #define ATH9K_RATESERIES_RTS_CTS 0x0001 diff --git a/trunk/drivers/net/wireless/ath/ath9k/main.c b/trunk/drivers/net/wireless/ath/ath9k/main.c index 248e5b24acfa..e4e73f061a22 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/main.c +++ b/trunk/drivers/net/wireless/ath/ath9k/main.c @@ -130,8 +130,6 @@ void ath9k_ps_restore(struct ath_softc *sc) PS_WAIT_FOR_PSPOLL_DATA | PS_WAIT_FOR_TX_ACK))) { mode = ATH9K_PM_NETWORK_SLEEP; - if (ath9k_hw_btcoex_is_enabled(sc->sc_ah)) - ath9k_btcoex_stop_gen_timer(sc); } else { goto unlock; } @@ -171,8 +169,7 @@ static void ath_restart_work(struct ath_softc *sc) ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0); - if (AR_SREV_9340(sc->sc_ah) || AR_SREV_9485(sc->sc_ah) || - AR_SREV_9550(sc->sc_ah)) + if (AR_SREV_9485(sc->sc_ah) || AR_SREV_9340(sc->sc_ah)) ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work, msecs_to_jiffies(ATH_PLL_WORK_INTERVAL)); @@ -669,6 +666,8 @@ static int ath9k_start(struct ieee80211_hw *hw) spin_unlock_bh(&sc->sc_pcu_lock); + ath9k_start_btcoex(sc); + if (ah->caps.pcie_lcr_extsync_en && common->bus_ops->extn_synch_en) common->bus_ops->extn_synch_en(common); @@ -775,6 +774,8 @@ static void ath9k_stop(struct ieee80211_hw *hw) /* Ensure HW is awake when we try to shut it down. */ ath9k_ps_wakeup(sc); + ath9k_stop_btcoex(sc); + spin_lock_bh(&sc->sc_pcu_lock); /* prevent tasklets to enable interrupts once we disable them */ @@ -1138,17 +1139,14 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) if (changed & IEEE80211_CONF_CHANGE_IDLE) { sc->ps_idle = !!(conf->flags & IEEE80211_CONF_IDLE); - if (sc->ps_idle) { + if (sc->ps_idle) ath_cancel_work(sc); - ath9k_stop_btcoex(sc); - } else { - ath9k_start_btcoex(sc); + else /* * The chip needs a reset to properly wake up from * full sleep */ reset_channel = ah->chip_fullsleep; - } } /* diff --git a/trunk/drivers/net/wireless/ath/ath9k/mci.c b/trunk/drivers/net/wireless/ath/ath9k/mci.c index 87acff7fdaae..64cc782587d8 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/mci.c +++ b/trunk/drivers/net/wireless/ath/ath9k/mci.c @@ -174,8 +174,8 @@ static void ath_mci_update_scheme(struct ath_softc *sc) btcoex->btcoex_period >>= 1; } - ath9k_btcoex_timer_pause(sc); ath9k_hw_btcoex_disable(sc->sc_ah); + ath9k_btcoex_timer_pause(sc); if (IS_CHAN_5GHZ(sc->sc_ah->curchan)) return; diff --git a/trunk/drivers/net/wireless/ath/ath9k/recv.c b/trunk/drivers/net/wireless/ath/ath9k/recv.c index 11f3703a420a..6a7dd26f2a13 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/recv.c +++ b/trunk/drivers/net/wireless/ath/ath9k/recv.c @@ -430,9 +430,6 @@ u32 ath_calcrxfilter(struct ath_softc *sc) rfilt |= ATH9K_RX_FILTER_MCAST_BCAST_ALL; } - if (AR_SREV_9550(sc->sc_ah)) - rfilt |= ATH9K_RX_FILTER_4ADDRESS; - return rfilt; } diff --git a/trunk/drivers/net/wireless/ath/ath9k/reg.h b/trunk/drivers/net/wireless/ath/ath9k/reg.h index 6592c07ac646..5046b282a93c 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/reg.h +++ b/trunk/drivers/net/wireless/ath/ath9k/reg.h @@ -798,7 +798,6 @@ #define AR_SREV_REVISION_9580_10 4 /* AR9580 1.0 */ #define AR_SREV_VERSION_9462 0x280 #define AR_SREV_REVISION_9462_20 2 -#define AR_SREV_VERSION_9550 0x400 #define AR_SREV_5416(_ah) \ (((_ah)->hw_version.macVersion == AR_SREV_VERSION_5416_PCI) || \ @@ -906,9 +905,6 @@ (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9462) && \ ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9462_20)) -#define AR_SREV_9550(_ah) \ - (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9550)) - #define AR_SREV_9580(_ah) \ (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9580) && \ ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9580_10)) @@ -1647,11 +1643,11 @@ enum { #define AR_TPC 0x80e8 #define AR_TPC_ACK 0x0000003f -#define AR_TPC_ACK_S 0 +#define AR_TPC_ACK_S 0x00 #define AR_TPC_CTS 0x00003f00 -#define AR_TPC_CTS_S 8 +#define AR_TPC_CTS_S 0x08 #define AR_TPC_CHIRP 0x003f0000 -#define AR_TPC_CHIRP_S 16 +#define AR_TPC_CHIRP_S 0x16 #define AR_QUIET1 0x80fc #define AR_QUIET1_NEXT_QUIET_S 0 @@ -2081,6 +2077,12 @@ enum { AR_MCI_INTERRUPT_RX_MSG_REMOTE_RESET| \ AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING | \ AR_MCI_INTERRUPT_RX_MSG_SYS_SLEEPING| \ + AR_MCI_INTERRUPT_RX_MSG_SCHD_INFO | \ + AR_MCI_INTERRUPT_RX_MSG_LNA_CONTROL | \ + AR_MCI_INTERRUPT_RX_MSG_LNA_INFO | \ + AR_MCI_INTERRUPT_RX_MSG_CONT_NACK | \ + AR_MCI_INTERRUPT_RX_MSG_CONT_INFO | \ + AR_MCI_INTERRUPT_RX_MSG_CONT_RST | \ AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE) #define AR_MCI_CPU_INT 0x1840 diff --git a/trunk/drivers/net/wireless/ath/carl9170/carl9170.h b/trunk/drivers/net/wireless/ath/carl9170/carl9170.h index 376be11161c0..0cea20e3e250 100644 --- a/trunk/drivers/net/wireless/ath/carl9170/carl9170.h +++ b/trunk/drivers/net/wireless/ath/carl9170/carl9170.h @@ -289,7 +289,6 @@ struct ar9170 { unsigned int mem_block_size; unsigned int rx_size; unsigned int tx_seq_table; - bool ba_filter; } fw; /* interface configuration combinations */ @@ -426,10 +425,6 @@ struct ar9170 { struct sk_buff *rx_failover; int rx_failover_missing; - /* FIFO for collecting outstanding BlockAckRequest */ - struct list_head bar_list[__AR9170_NUM_TXQ]; - spinlock_t bar_list_lock[__AR9170_NUM_TXQ]; - #ifdef CONFIG_CARL9170_WPC struct { bool pbc_state; @@ -473,12 +468,6 @@ enum carl9170_ps_off_override_reasons { PS_OFF_BCN = BIT(1), }; -struct carl9170_bar_list_entry { - struct list_head list; - struct rcu_head head; - struct sk_buff *skb; -}; - struct carl9170_ba_stats { u8 ampdu_len; u8 ampdu_ack_len; diff --git a/trunk/drivers/net/wireless/ath/carl9170/fw.c b/trunk/drivers/net/wireless/ath/carl9170/fw.c index c5ca6f1f5836..5c73c03872f3 100644 --- a/trunk/drivers/net/wireless/ath/carl9170/fw.c +++ b/trunk/drivers/net/wireless/ath/carl9170/fw.c @@ -307,9 +307,6 @@ static int carl9170_fw(struct ar9170 *ar, const __u8 *data, size_t len) if (SUPP(CARL9170FW_WOL)) device_set_wakeup_enable(&ar->udev->dev, true); - if (SUPP(CARL9170FW_RX_BA_FILTER)) - ar->fw.ba_filter = true; - if_comb_types = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_P2P_CLIENT); diff --git a/trunk/drivers/net/wireless/ath/carl9170/fwdesc.h b/trunk/drivers/net/wireless/ath/carl9170/fwdesc.h index 66848d47c88e..6d9c0891ce7f 100644 --- a/trunk/drivers/net/wireless/ath/carl9170/fwdesc.h +++ b/trunk/drivers/net/wireless/ath/carl9170/fwdesc.h @@ -78,9 +78,6 @@ enum carl9170fw_feature_list { /* HW (ANI, CCA, MIB) tally counters */ CARL9170FW_HW_COUNTERS, - /* Firmware will pass BA when BARs are queued */ - CARL9170FW_RX_BA_FILTER, - /* KEEP LAST */ __CARL9170FW_FEATURE_NUM }; diff --git a/trunk/drivers/net/wireless/ath/carl9170/main.c b/trunk/drivers/net/wireless/ath/carl9170/main.c index 858e58dfc4dc..8d2523b3f722 100644 --- a/trunk/drivers/net/wireless/ath/carl9170/main.c +++ b/trunk/drivers/net/wireless/ath/carl9170/main.c @@ -949,9 +949,6 @@ static void carl9170_op_configure_filter(struct ieee80211_hw *hw, if (ar->fw.rx_filter && changed_flags & ar->rx_filter_caps) { u32 rx_filter = 0; - if (!ar->fw.ba_filter) - rx_filter |= CARL9170_RX_FILTER_CTL_OTHER; - if (!(*new_flags & (FIF_FCSFAIL | FIF_PLCPFAIL))) rx_filter |= CARL9170_RX_FILTER_BAD; @@ -1756,9 +1753,6 @@ void *carl9170_alloc(size_t priv_size) for (i = 0; i < ar->hw->queues; i++) { skb_queue_head_init(&ar->tx_status[i]); skb_queue_head_init(&ar->tx_pending[i]); - - INIT_LIST_HEAD(&ar->bar_list[i]); - spin_lock_init(&ar->bar_list_lock[i]); } INIT_WORK(&ar->ps_work, carl9170_ps_work); INIT_WORK(&ar->ping_work, carl9170_ping_work); diff --git a/trunk/drivers/net/wireless/ath/carl9170/rx.c b/trunk/drivers/net/wireless/ath/carl9170/rx.c index 6f6a34155667..7a8e90eaad83 100644 --- a/trunk/drivers/net/wireless/ath/carl9170/rx.c +++ b/trunk/drivers/net/wireless/ath/carl9170/rx.c @@ -576,53 +576,6 @@ static void carl9170_ps_beacon(struct ar9170 *ar, void *data, unsigned int len) } } -static void carl9170_ba_check(struct ar9170 *ar, void *data, unsigned int len) -{ - struct ieee80211_bar *bar = (void *) data; - struct carl9170_bar_list_entry *entry; - unsigned int queue; - - if (likely(!ieee80211_is_back(bar->frame_control))) - return; - - if (len <= sizeof(*bar) + FCS_LEN) - return; - - queue = TID_TO_WME_AC(((le16_to_cpu(bar->control) & - IEEE80211_BAR_CTRL_TID_INFO_MASK) >> - IEEE80211_BAR_CTRL_TID_INFO_SHIFT) & 7); - - rcu_read_lock(); - list_for_each_entry_rcu(entry, &ar->bar_list[queue], list) { - struct sk_buff *entry_skb = entry->skb; - struct _carl9170_tx_superframe *super = (void *)entry_skb->data; - struct ieee80211_bar *entry_bar = (void *)super->frame_data; - -#define TID_CHECK(a, b) ( \ - ((a) & cpu_to_le16(IEEE80211_BAR_CTRL_TID_INFO_MASK)) == \ - ((b) & cpu_to_le16(IEEE80211_BAR_CTRL_TID_INFO_MASK))) \ - - if (bar->start_seq_num == entry_bar->start_seq_num && - TID_CHECK(bar->control, entry_bar->control) && - compare_ether_addr(bar->ra, entry_bar->ta) == 0 && - compare_ether_addr(bar->ta, entry_bar->ra) == 0) { - struct ieee80211_tx_info *tx_info; - - tx_info = IEEE80211_SKB_CB(entry_skb); - tx_info->flags |= IEEE80211_TX_STAT_ACK; - - spin_lock_bh(&ar->bar_list_lock[queue]); - list_del_rcu(&entry->list); - spin_unlock_bh(&ar->bar_list_lock[queue]); - kfree_rcu(entry, head); - break; - } - } - rcu_read_unlock(); - -#undef TID_CHECK -} - static bool carl9170_ampdu_check(struct ar9170 *ar, u8 *buf, u8 ms) { __le16 fc; @@ -785,8 +738,6 @@ static void carl9170_handle_mpdu(struct ar9170 *ar, u8 *buf, int len) carl9170_ps_beacon(ar, buf, mpdu_len); - carl9170_ba_check(ar, buf, mpdu_len); - skb = carl9170_rx_copy_data(buf, mpdu_len); if (!skb) goto drop; diff --git a/trunk/drivers/net/wireless/ath/carl9170/tx.c b/trunk/drivers/net/wireless/ath/carl9170/tx.c index 6a8681407a1d..aed305177af6 100644 --- a/trunk/drivers/net/wireless/ath/carl9170/tx.c +++ b/trunk/drivers/net/wireless/ath/carl9170/tx.c @@ -277,11 +277,11 @@ static void carl9170_tx_release(struct kref *ref) return; BUILD_BUG_ON( - offsetof(struct ieee80211_tx_info, status.ack_signal) != 20); + offsetof(struct ieee80211_tx_info, status.ampdu_ack_len) != 23); - memset(&txinfo->status.ack_signal, 0, + memset(&txinfo->status.ampdu_ack_len, 0, sizeof(struct ieee80211_tx_info) - - offsetof(struct ieee80211_tx_info, status.ack_signal)); + offsetof(struct ieee80211_tx_info, status.ampdu_ack_len)); if (atomic_read(&ar->tx_total_queued)) ar->tx_schedule = true; @@ -436,45 +436,6 @@ static void carl9170_tx_status_process_ampdu(struct ar9170 *ar, rcu_read_unlock(); } -static void carl9170_tx_bar_status(struct ar9170 *ar, struct sk_buff *skb, - struct ieee80211_tx_info *tx_info) -{ - struct _carl9170_tx_superframe *super = (void *) skb->data; - struct ieee80211_bar *bar = (void *) super->frame_data; - - /* - * Unlike all other frames, the status report for BARs does - * not directly come from the hardware as it is incapable of - * matching a BA to a previously send BAR. - * Instead the RX-path will scan for incoming BAs and set the - * IEEE80211_TX_STAT_ACK if it sees one that was likely - * caused by a BAR from us. - */ - - if (unlikely(ieee80211_is_back_req(bar->frame_control)) && - !(tx_info->flags & IEEE80211_TX_STAT_ACK)) { - struct carl9170_bar_list_entry *entry; - int queue = skb_get_queue_mapping(skb); - - rcu_read_lock(); - list_for_each_entry_rcu(entry, &ar->bar_list[queue], list) { - if (entry->skb == skb) { - spin_lock_bh(&ar->bar_list_lock[queue]); - list_del_rcu(&entry->list); - spin_unlock_bh(&ar->bar_list_lock[queue]); - kfree_rcu(entry, head); - goto out; - } - } - - WARN(1, "bar not found in %d - ra:%pM ta:%pM c:%x ssn:%x\n", - queue, bar->ra, bar->ta, bar->control, - bar->start_seq_num); -out: - rcu_read_unlock(); - } -} - void carl9170_tx_status(struct ar9170 *ar, struct sk_buff *skb, const bool success) { @@ -484,8 +445,6 @@ void carl9170_tx_status(struct ar9170 *ar, struct sk_buff *skb, txinfo = IEEE80211_SKB_CB(skb); - carl9170_tx_bar_status(ar, skb, txinfo); - if (success) txinfo->flags |= IEEE80211_TX_STAT_ACK; else @@ -1306,26 +1265,6 @@ static bool carl9170_tx_ps_drop(struct ar9170 *ar, struct sk_buff *skb) return false; } -static void carl9170_bar_check(struct ar9170 *ar, struct sk_buff *skb) -{ - struct _carl9170_tx_superframe *super = (void *) skb->data; - struct ieee80211_bar *bar = (void *) super->frame_data; - - if (unlikely(ieee80211_is_back_req(bar->frame_control)) && - skb->len >= sizeof(struct ieee80211_bar)) { - struct carl9170_bar_list_entry *entry; - unsigned int queue = skb_get_queue_mapping(skb); - - entry = kmalloc(sizeof(*entry), GFP_ATOMIC); - if (!WARN_ON_ONCE(!entry)) { - entry->skb = skb; - spin_lock_bh(&ar->bar_list_lock[queue]); - list_add_tail_rcu(&entry->list, &ar->bar_list[queue]); - spin_unlock_bh(&ar->bar_list_lock[queue]); - } - } -} - static void carl9170_tx(struct ar9170 *ar) { struct sk_buff *skb; @@ -1348,8 +1287,6 @@ static void carl9170_tx(struct ar9170 *ar) if (unlikely(carl9170_tx_ps_drop(ar, skb))) continue; - carl9170_bar_check(ar, skb); - atomic_inc(&ar->tx_total_pending); q = __carl9170_get_queue(ar, i); diff --git a/trunk/drivers/net/wireless/ath/carl9170/version.h b/trunk/drivers/net/wireless/ath/carl9170/version.h index 2ec3e9191e4d..e651db856344 100644 --- a/trunk/drivers/net/wireless/ath/carl9170/version.h +++ b/trunk/drivers/net/wireless/ath/carl9170/version.h @@ -1,7 +1,7 @@ #ifndef __CARL9170_SHARED_VERSION_H #define __CARL9170_SHARED_VERSION_H -#define CARL9170FW_VERSION_YEAR 12 -#define CARL9170FW_VERSION_MONTH 7 -#define CARL9170FW_VERSION_DAY 7 -#define CARL9170FW_VERSION_GIT "1.9.6" +#define CARL9170FW_VERSION_YEAR 11 +#define CARL9170FW_VERSION_MONTH 8 +#define CARL9170FW_VERSION_DAY 15 +#define CARL9170FW_VERSION_GIT "1.9.4" #endif /* __CARL9170_SHARED_VERSION_H */ diff --git a/trunk/drivers/net/wireless/b43/phy_n.c b/trunk/drivers/net/wireless/b43/phy_n.c index b92bb9c92ad1..108118820b36 100644 --- a/trunk/drivers/net/wireless/b43/phy_n.c +++ b/trunk/drivers/net/wireless/b43/phy_n.c @@ -1369,7 +1369,7 @@ static void b43_nphy_rev3_rssi_cal(struct b43_wldev *dev) i << 2); b43_nphy_poll_rssi(dev, 2, results[i], 8); } - for (i = 0; i < 4; i += 2) { + for (i = 0; i < 4; i++) { s32 curr; s32 mind = 40; s32 minpoll = 249; @@ -1415,15 +1415,14 @@ static void b43_nphy_rev3_rssi_cal(struct b43_wldev *dev) b43_nphy_scale_offset_rssi(dev, 0, 0, core + 1, 1, i); b43_nphy_poll_rssi(dev, i, poll_results, 8); for (j = 0; j < 4; j++) { - if (j / 2 == core) { + if (j / 2 == core) offset[j] = 232 - poll_results[j]; - if (offset[j] < 0) - offset[j] = -(abs(offset[j] + 4) / 8); - else - offset[j] = (offset[j] + 4) / 8; - b43_nphy_scale_offset_rssi(dev, 0, - offset[2 * core], core + 1, j % 2, i); - } + if (offset[j] < 0) + offset[j] = -(abs(offset[j] + 4) / 8); + else + offset[j] = (offset[j] + 4) / 8; + b43_nphy_scale_offset_rssi(dev, 0, + offset[2 * core], core + 1, j % 2, i); } } } diff --git a/trunk/drivers/net/wireless/b43legacy/dma.c b/trunk/drivers/net/wireless/b43legacy/dma.c index 2d3c6644f82d..ff50cb4290e4 100644 --- a/trunk/drivers/net/wireless/b43legacy/dma.c +++ b/trunk/drivers/net/wireless/b43legacy/dma.c @@ -1072,7 +1072,7 @@ static int dma_tx_fragment(struct b43legacy_dmaring *ring, meta->dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1); /* create a bounce buffer in zone_dma on mapping failure. */ if (b43legacy_dma_mapping_error(ring, meta->dmaaddr, skb->len, 1)) { - bounce_skb = alloc_skb(skb->len, GFP_ATOMIC | GFP_DMA); + bounce_skb = __dev_alloc_skb(skb->len, GFP_ATOMIC | GFP_DMA); if (!bounce_skb) { ring->current_slot = old_top_slot; ring->used_slots = old_used_slots; diff --git a/trunk/drivers/net/wireless/brcm80211/brcmsmac/aiutils.c b/trunk/drivers/net/wireless/brcm80211/brcmsmac/aiutils.c index 8c9345dd37d2..3c6f9b1e8d05 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmsmac/aiutils.c +++ b/trunk/drivers/net/wireless/brcm80211/brcmsmac/aiutils.c @@ -318,6 +318,10 @@ #define IS_SIM(chippkg) \ ((chippkg == HDLSIM_PKG_ID) || (chippkg == HWSIM_PKG_ID)) +#define PCIE(sih) (ai_get_buscoretype(sih) == PCIE_CORE_ID) + +#define PCI_FORCEHT(sih) (PCIE(sih) && (ai_get_chip_id(sih) == BCM4716_CHIP_ID)) + #ifdef DEBUG #define SI_MSG(fmt, ...) pr_debug(fmt, ##__VA_ARGS__) #else @@ -469,6 +473,9 @@ ai_buscore_setup(struct si_info *sii, struct bcma_device *cc) sii->pub.pmurev = sii->pub.pmucaps & PCAP_REV_MASK; } + /* figure out buscore */ + sii->buscore = ai_findcore(&sii->pub, PCIE_CORE_ID, 0); + return true; } @@ -476,7 +483,11 @@ static struct si_info *ai_doattach(struct si_info *sii, struct bcma_bus *pbus) { struct si_pub *sih = &sii->pub; + u32 w, savewin; struct bcma_device *cc; + struct ssb_sprom *sprom = &pbus->sprom; + + savewin = 0; sii->icbus = pbus; sii->pcibus = pbus->host_pci; @@ -499,7 +510,47 @@ static struct si_info *ai_doattach(struct si_info *sii, /* PMU specific initializations */ if (ai_get_cccaps(sih) & CC_CAP_PMU) { + si_pmu_init(sih); (void)si_pmu_measure_alpclk(sih); + si_pmu_res_init(sih); + } + + /* setup the GPIO based LED powersave register */ + w = (sprom->leddc_on_time << BCMA_CC_GPIOTIMER_ONTIME_SHIFT) | + (sprom->leddc_off_time << BCMA_CC_GPIOTIMER_OFFTIME_SHIFT); + if (w == 0) + w = DEFAULT_GPIOTIMERVAL; + ai_cc_reg(sih, offsetof(struct chipcregs, gpiotimerval), + ~0, w); + + if (ai_get_chip_id(sih) == BCM43224_CHIP_ID) { + /* + * enable 12 mA drive strenth for 43224 and + * set chipControl register bit 15 + */ + if (ai_get_chiprev(sih) == 0) { + SI_MSG("Applying 43224A0 WARs\n"); + ai_cc_reg(sih, offsetof(struct chipcregs, chipcontrol), + CCTRL43224_GPIO_TOGGLE, + CCTRL43224_GPIO_TOGGLE); + si_pmu_chipcontrol(sih, 0, CCTRL_43224A0_12MA_LED_DRIVE, + CCTRL_43224A0_12MA_LED_DRIVE); + } + if (ai_get_chiprev(sih) >= 1) { + SI_MSG("Applying 43224B0+ WARs\n"); + si_pmu_chipcontrol(sih, 0, CCTRL_43224B0_12MA_LED_DRIVE, + CCTRL_43224B0_12MA_LED_DRIVE); + } + } + + if (ai_get_chip_id(sih) == BCM4313_CHIP_ID) { + /* + * enable 12 mA drive strenth for 4313 and + * set chipControl register bit 1 + */ + SI_MSG("Applying 4313 WARs\n"); + si_pmu_chipcontrol(sih, 0, CCTRL_4313_12MA_LED_DRIVE, + CCTRL_4313_12MA_LED_DRIVE); } return sii; @@ -538,7 +589,7 @@ void ai_detach(struct si_pub *sih) struct si_pub *si_local = NULL; memcpy(&si_local, &sih, sizeof(struct si_pub **)); - sii = container_of(sih, struct si_info, pub); + sii = (struct si_info *)sih; if (sii == NULL) return; @@ -546,6 +597,27 @@ void ai_detach(struct si_pub *sih) kfree(sii); } +/* return index of coreid or BADIDX if not found */ +struct bcma_device *ai_findcore(struct si_pub *sih, u16 coreid, u16 coreunit) +{ + struct bcma_device *core; + struct si_info *sii; + uint found; + + sii = (struct si_info *)sih; + + found = 0; + + list_for_each_entry(core, &sii->icbus->cores, list) + if (core->id.id == coreid) { + if (found == coreunit) + return core; + found++; + } + + return NULL; +} + /* * read/modify chipcommon core register. */ @@ -555,7 +627,7 @@ uint ai_cc_reg(struct si_pub *sih, uint regoff, u32 mask, u32 val) u32 w; struct si_info *sii; - sii = container_of(sih, struct si_info, pub); + sii = (struct si_info *)sih; cc = sii->icbus->drv_cc.core; /* mask and set */ @@ -621,13 +693,12 @@ ai_clkctl_setdelay(struct si_pub *sih, struct bcma_device *cc) /* initialize power control delay registers */ void ai_clkctl_init(struct si_pub *sih) { - struct si_info *sii = container_of(sih, struct si_info, pub); struct bcma_device *cc; if (!(ai_get_cccaps(sih) & CC_CAP_PWR_CTL)) return; - cc = sii->icbus->drv_cc.core; + cc = ai_findcore(sih, BCMA_CORE_CHIPCOMMON, 0); if (cc == NULL) return; @@ -649,7 +720,7 @@ u16 ai_clkctl_fast_pwrup_delay(struct si_pub *sih) uint slowminfreq; u16 fpdelay; - sii = container_of(sih, struct si_info, pub); + sii = (struct si_info *)sih; if (ai_get_cccaps(sih) & CC_CAP_PMU) { fpdelay = si_pmu_fast_pwrup_delay(sih); return fpdelay; @@ -659,7 +730,7 @@ u16 ai_clkctl_fast_pwrup_delay(struct si_pub *sih) return 0; fpdelay = 0; - cc = sii->icbus->drv_cc.core; + cc = ai_findcore(sih, CC_CORE_ID, 0); if (cc) { slowminfreq = ai_slowclk_freq(sih, false, cc); fpdelay = (((bcma_read32(cc, CHIPCREGOFFS(pll_on_delay)) + 2) @@ -681,9 +752,12 @@ bool ai_clkctl_cc(struct si_pub *sih, enum bcma_clkmode mode) struct si_info *sii; struct bcma_device *cc; - sii = container_of(sih, struct si_info, pub); + sii = (struct si_info *)sih; - cc = sii->icbus->drv_cc.core; + if (PCI_FORCEHT(sih)) + return mode == BCMA_CLKMODE_FAST; + + cc = ai_findcore(&sii->pub, BCMA_CORE_CHIPCOMMON, 0); bcma_core_set_clockmode(cc, mode); return mode == BCMA_CLKMODE_FAST; } @@ -691,10 +765,16 @@ bool ai_clkctl_cc(struct si_pub *sih, enum bcma_clkmode mode) void ai_pci_up(struct si_pub *sih) { struct si_info *sii; + struct bcma_device *cc; - sii = container_of(sih, struct si_info, pub); + sii = (struct si_info *)sih; - if (sii->icbus->hosttype == BCMA_HOSTTYPE_PCI) + if (PCI_FORCEHT(sih)) { + cc = ai_findcore(&sii->pub, BCMA_CORE_CHIPCOMMON, 0); + bcma_core_set_clockmode(cc, BCMA_CLKMODE_FAST); + } + + if (PCIE(sih)) bcma_core_pci_extend_L1timer(&sii->icbus->drv_pci, true); } @@ -702,20 +782,26 @@ void ai_pci_up(struct si_pub *sih) void ai_pci_down(struct si_pub *sih) { struct si_info *sii; + struct bcma_device *cc; - sii = container_of(sih, struct si_info, pub); + sii = (struct si_info *)sih; - if (sii->icbus->hosttype == BCMA_HOSTTYPE_PCI) + /* release FORCEHT since chip is going to "down" state */ + if (PCI_FORCEHT(sih)) { + cc = ai_findcore(&sii->pub, BCMA_CORE_CHIPCOMMON, 0); + bcma_core_set_clockmode(cc, BCMA_CLKMODE_DYNAMIC); + } + + if (PCIE(sih)) bcma_core_pci_extend_L1timer(&sii->icbus->drv_pci, false); } /* Enable BT-COEX & Ex-PA for 4313 */ void ai_epa_4313war(struct si_pub *sih) { - struct si_info *sii = container_of(sih, struct si_info, pub); struct bcma_device *cc; - cc = sii->icbus->drv_cc.core; + cc = ai_findcore(sih, CC_CORE_ID, 0); /* EPA Fix */ bcma_set32(cc, CHIPCREGOFFS(gpiocontrol), GPIO_CTRL_EPA_EN_MASK); @@ -727,7 +813,7 @@ bool ai_deviceremoved(struct si_pub *sih) u32 w; struct si_info *sii; - sii = container_of(sih, struct si_info, pub); + sii = (struct si_info *)sih; if (sii->icbus->hosttype != BCMA_HOSTTYPE_PCI) return false; @@ -738,3 +824,15 @@ bool ai_deviceremoved(struct si_pub *sih) return false; } + +uint ai_get_buscoretype(struct si_pub *sih) +{ + struct si_info *sii = (struct si_info *)sih; + return sii->buscore->id.id; +} + +uint ai_get_buscorerev(struct si_pub *sih) +{ + struct si_info *sii = (struct si_info *)sih; + return sii->buscore->id.rev; +} diff --git a/trunk/drivers/net/wireless/brcm80211/brcmsmac/aiutils.h b/trunk/drivers/net/wireless/brcm80211/brcmsmac/aiutils.h index 89562c1fbf49..d6fa9829af9a 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmsmac/aiutils.h +++ b/trunk/drivers/net/wireless/brcm80211/brcmsmac/aiutils.h @@ -88,6 +88,16 @@ #define CLKD_OTP 0x000f0000 #define CLKD_OTP_SHIFT 16 +/* Package IDs */ +#define BCM4717_PKG_ID 9 /* 4717 package id */ +#define BCM4718_PKG_ID 10 /* 4718 package id */ +#define BCM43224_FAB_SMIC 0xa /* the chip is manufactured by SMIC */ + +/* these are router chips */ +#define BCM4716_CHIP_ID 0x4716 /* 4716 chipcommon chipid */ +#define BCM47162_CHIP_ID 47162 /* 47162 chipcommon chipid */ +#define BCM4748_CHIP_ID 0x4748 /* 4716 chipcommon chipid (OTP, RBBU) */ + /* dynamic clock control defines */ #define LPOMINFREQ 25000 /* low power oscillator min */ #define LPOMAXFREQ 43000 /* low power oscillator max */ @@ -158,6 +168,7 @@ struct si_info { struct si_pub pub; /* back plane public state (must be first) */ struct bcma_bus *icbus; /* handle to soc interconnect bus */ struct pci_dev *pcibus; /* handle to pci bus */ + struct bcma_device *buscore; u32 chipst; /* chip status */ }; @@ -172,6 +183,8 @@ struct si_info { /* AMBA Interconnect exported externs */ +extern struct bcma_device *ai_findcore(struct si_pub *sih, + u16 coreid, u16 coreunit); extern u32 ai_core_cflags(struct bcma_device *core, u32 mask, u32 val); /* === exported functions === */ @@ -189,6 +202,9 @@ extern void ai_pci_up(struct si_pub *sih); /* Enable Ex-PA for 4313 */ extern void ai_epa_4313war(struct si_pub *sih); +extern uint ai_get_buscoretype(struct si_pub *sih); +extern uint ai_get_buscorerev(struct si_pub *sih); + static inline u32 ai_get_cccaps(struct si_pub *sih) { return sih->cccaps; diff --git a/trunk/drivers/net/wireless/brcm80211/brcmsmac/channel.c b/trunk/drivers/net/wireless/brcm80211/brcmsmac/channel.c index 9a4c63f927cb..2d365d3486df 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmsmac/channel.c +++ b/trunk/drivers/net/wireless/brcm80211/brcmsmac/channel.c @@ -763,17 +763,20 @@ void brcms_c_regd_init(struct brcms_c_info *wlc) int band_idx, i; /* Disable any channels not supported by the phy */ - for (band_idx = 0; band_idx < wlc->pub->_nbands; band_idx++) { - band = wlc->bandstate[band_idx]; + for (band_idx = 0; band_idx < IEEE80211_NUM_BANDS; band_idx++) { + if (band_idx == IEEE80211_BAND_2GHZ) + band = wlc->bandstate[BAND_2G_INDEX]; + else + band = wlc->bandstate[BAND_5G_INDEX]; + + /* skip if band not initialized */ + if (band->pi == NULL) + continue; wlc_phy_chanspec_band_validch(band->pi, band->bandtype, &sup_chan); - if (band_idx == BAND_2G_INDEX) - sband = wiphy->bands[IEEE80211_BAND_2GHZ]; - else - sband = wiphy->bands[IEEE80211_BAND_5GHZ]; - + sband = wiphy->bands[band_idx]; for (i = 0; i < sband->n_channels; i++) { ch = &sband->channels[i]; if (!isset(sup_chan.vec, ch->hw_value)) diff --git a/trunk/drivers/net/wireless/brcm80211/brcmsmac/dma.c b/trunk/drivers/net/wireless/brcm80211/brcmsmac/dma.c index 5e53305bd9a9..7516639412ec 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmsmac/dma.c +++ b/trunk/drivers/net/wireless/brcm80211/brcmsmac/dma.c @@ -573,7 +573,6 @@ struct dma_pub *dma_attach(char *name, struct si_pub *sih, struct dma_info *di; u8 rev = core->id.rev; uint size; - struct si_info *sii = container_of(sih, struct si_info, pub); /* allocate private info structure */ di = kzalloc(sizeof(struct dma_info), GFP_ATOMIC); @@ -634,20 +633,16 @@ struct dma_pub *dma_attach(char *name, struct si_pub *sih, */ di->ddoffsetlow = 0; di->dataoffsetlow = 0; - /* for pci bus, add offset */ - if (sii->icbus->hosttype == BCMA_HOSTTYPE_PCI) { - /* add offset for pcie with DMA64 bus */ - di->ddoffsetlow = 0; - di->ddoffsethigh = SI_PCIE_DMA_H32; - } + /* add offset for pcie with DMA64 bus */ + di->ddoffsetlow = 0; + di->ddoffsethigh = SI_PCIE_DMA_H32; di->dataoffsetlow = di->ddoffsetlow; di->dataoffsethigh = di->ddoffsethigh; - /* WAR64450 : DMACtl.Addr ext fields are not supported in SDIOD core. */ - if ((core->id.id == BCMA_CORE_SDIO_DEV) + if ((core->id.id == SDIOD_CORE_ID) && ((rev > 0) && (rev <= 2))) di->addrext = false; - else if ((core->id.id == BCMA_CORE_I2S) && + else if ((core->id.id == I2S_CORE_ID) && ((rev == 0) || (rev == 1))) di->addrext = false; else diff --git a/trunk/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c b/trunk/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c index 2b57f57a7927..2d5a40412690 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c +++ b/trunk/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c @@ -319,7 +319,8 @@ static void brcms_ops_stop(struct ieee80211_hw *hw) return; spin_lock_bh(&wl->lock); - status = brcms_c_chipmatch(wl->wlc->hw->d11core); + status = brcms_c_chipmatch(wl->wlc->hw->vendorid, + wl->wlc->hw->deviceid); spin_unlock_bh(&wl->lock); if (!status) { wiphy_err(wl->wiphy, diff --git a/trunk/drivers/net/wireless/brcm80211/brcmsmac/main.c b/trunk/drivers/net/wireless/brcm80211/brcmsmac/main.c index cb73f2250b11..bb00b6528d8f 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmsmac/main.c +++ b/trunk/drivers/net/wireless/brcm80211/brcmsmac/main.c @@ -269,7 +269,7 @@ struct brcms_c_bit_desc { */ /* Starting corerev for the fifo size table */ -#define XMTFIFOTBL_STARTREV 17 +#define XMTFIFOTBL_STARTREV 20 struct d11init { __le16 addr; @@ -333,12 +333,6 @@ const u8 wlc_prio2prec_map[] = { }; static const u16 xmtfifo_sz[][NFIFO] = { - /* corerev 17: 5120, 49152, 49152, 5376, 4352, 1280 */ - {20, 192, 192, 21, 17, 5}, - /* corerev 18: */ - {0, 0, 0, 0, 0, 0}, - /* corerev 19: */ - {0, 0, 0, 0, 0, 0}, /* corerev 20: 5120, 49152, 49152, 5376, 4352, 1280 */ {20, 192, 192, 21, 17, 5}, /* corerev 21: 2304, 14848, 5632, 3584, 3584, 1280 */ @@ -349,14 +343,6 @@ static const u16 xmtfifo_sz[][NFIFO] = { {20, 192, 192, 21, 17, 5}, /* corerev 24: 2304, 14848, 5632, 3584, 3584, 1280 */ {9, 58, 22, 14, 14, 5}, - /* corerev 25: */ - {0, 0, 0, 0, 0, 0}, - /* corerev 26: */ - {0, 0, 0, 0, 0, 0}, - /* corerev 27: */ - {0, 0, 0, 0, 0, 0}, - /* corerev 28: 2304, 14848, 5632, 3584, 3584, 1280 */ - {9, 58, 22, 14, 14, 5}, }; #ifdef DEBUG @@ -1956,8 +1942,7 @@ static bool brcms_b_radio_read_hwdisabled(struct brcms_hardware *wlc_hw) * accesses phyreg throughput mac. This can be skipped since * only mac reg is accessed below */ - if (D11REV_GE(wlc_hw->corerev, 18)) - flags |= SICF_PCLKE; + flags |= SICF_PCLKE; /* * TODO: test suspend/resume @@ -2038,8 +2023,7 @@ void brcms_b_corereset(struct brcms_hardware *wlc_hw, u32 flags) * phyreg throughput mac, AND phy_reset is skipped at early stage when * band->pi is invalid. need to enable PHY CLK */ - if (D11REV_GE(wlc_hw->corerev, 18)) - flags |= SICF_PCLKE; + flags |= SICF_PCLKE; /* * reset the core @@ -2142,8 +2126,8 @@ void brcms_b_switch_macfreq(struct brcms_hardware *wlc_hw, u8 spurmode) { struct bcma_device *core = wlc_hw->d11core; - if ((ai_get_chip_id(wlc_hw->sih) == BCMA_CHIP_ID_BCM43224) || - (ai_get_chip_id(wlc_hw->sih) == BCMA_CHIP_ID_BCM43225)) { + if ((ai_get_chip_id(wlc_hw->sih) == BCM43224_CHIP_ID) || + (ai_get_chip_id(wlc_hw->sih) == BCM43225_CHIP_ID)) { if (spurmode == WL_SPURAVOID_ON2) { /* 126Mhz */ bcma_write16(core, D11REGOFFS(tsf_clk_frac_l), 0x2082); bcma_write16(core, D11REGOFFS(tsf_clk_frac_h), 0x8); @@ -2807,7 +2791,7 @@ void brcms_b_core_phypll_ctl(struct brcms_hardware *wlc_hw, bool on) tmp = 0; if (on) { - if ((ai_get_chip_id(wlc_hw->sih) == BCMA_CHIP_ID_BCM4313)) { + if ((ai_get_chip_id(wlc_hw->sih) == BCM4313_CHIP_ID)) { bcma_set32(core, D11REGOFFS(clk_ctl_st), CCS_ERSRC_REQ_HT | CCS_ERSRC_REQ_D11PLL | @@ -4234,8 +4218,9 @@ static void brcms_c_radio_timer(void *arg) } /* common low-level watchdog code */ -static void brcms_b_watchdog(struct brcms_c_info *wlc) +static void brcms_b_watchdog(void *arg) { + struct brcms_c_info *wlc = (struct brcms_c_info *) arg; struct brcms_hardware *wlc_hw = wlc->hw; BCMMSG(wlc->wiphy, "wl%d\n", wlc_hw->unit); @@ -4256,8 +4241,10 @@ static void brcms_b_watchdog(struct brcms_c_info *wlc) } /* common watchdog code */ -static void brcms_c_watchdog(struct brcms_c_info *wlc) +static void brcms_c_watchdog(void *arg) { + struct brcms_c_info *wlc = (struct brcms_c_info *) arg; + BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit); if (!wlc->pub->up) @@ -4297,9 +4284,7 @@ static void brcms_c_watchdog(struct brcms_c_info *wlc) static void brcms_c_watchdog_by_timer(void *arg) { - struct brcms_c_info *wlc = (struct brcms_c_info *) arg; - - brcms_c_watchdog(wlc); + brcms_c_watchdog(arg); } static bool brcms_c_timers_init(struct brcms_c_info *wlc, int unit) @@ -4469,9 +4454,11 @@ static int brcms_b_attach(struct brcms_c_info *wlc, struct bcma_device *core, } /* verify again the device is supported */ - if (!brcms_c_chipmatch(core)) { - wiphy_err(wiphy, "wl%d: brcms_b_attach: Unsupported device\n", - unit); + if (core->bus->hosttype == BCMA_HOSTTYPE_PCI && + !brcms_c_chipmatch(pcidev->vendor, pcidev->device)) { + wiphy_err(wiphy, "wl%d: brcms_b_attach: Unsupported " + "vendor/device (0x%x/0x%x)\n", + unit, pcidev->vendor, pcidev->device); err = 12; goto fail; } @@ -4541,7 +4528,7 @@ static int brcms_b_attach(struct brcms_c_info *wlc, struct bcma_device *core, else wlc_hw->_nbands = 1; - if ((ai_get_chip_id(wlc_hw->sih) == BCMA_CHIP_ID_BCM43225)) + if ((ai_get_chip_id(wlc_hw->sih) == BCM43225_CHIP_ID)) wlc_hw->_nbands = 1; /* BMAC_NOTE: remove init of pub values when brcms_c_attach() @@ -4608,12 +4595,8 @@ static int brcms_b_attach(struct brcms_c_info *wlc, struct bcma_device *core, wlc_hw->machwcap_backup = wlc_hw->machwcap; /* init tx fifo size */ - WARN_ON((wlc_hw->corerev - XMTFIFOTBL_STARTREV) < 0 || - (wlc_hw->corerev - XMTFIFOTBL_STARTREV) > - ARRAY_SIZE(xmtfifo_sz)); wlc_hw->xmtfifo_sz = xmtfifo_sz[(wlc_hw->corerev - XMTFIFOTBL_STARTREV)]; - WARN_ON(!wlc_hw->xmtfifo_sz[0]); /* Get a phy for this band */ wlc_hw->band->pi = @@ -5053,7 +5036,7 @@ static void brcms_b_hw_up(struct brcms_hardware *wlc_hw) wlc_hw->wlc->pub->hw_up = true; if ((wlc_hw->boardflags & BFL_FEM) - && (ai_get_chip_id(wlc_hw->sih) == BCMA_CHIP_ID_BCM4313)) { + && (ai_get_chip_id(wlc_hw->sih) == BCM4313_CHIP_ID)) { if (! (wlc_hw->boardrev >= 0x1250 && (wlc_hw->boardflags & BFL_FEM_BT))) @@ -5147,7 +5130,7 @@ int brcms_c_up(struct brcms_c_info *wlc) } if ((wlc->pub->boardflags & BFL_FEM) - && (ai_get_chip_id(wlc->hw->sih) == BCMA_CHIP_ID_BCM4313)) { + && (ai_get_chip_id(wlc->hw->sih) == BCM4313_CHIP_ID)) { if (wlc->pub->boardrev >= 0x1250 && (wlc->pub->boardflags & BFL_FEM_BT)) brcms_b_mhf(wlc->hw, MHF5, MHF5_4313_GPIOCTRL, @@ -5784,12 +5767,8 @@ void brcms_c_print_txstatus(struct tx_status *txs) (txs->ackphyrxsh & PRXS1_SQ_MASK) >> PRXS1_SQ_SHIFT); } -static bool brcms_c_chipmatch_pci(struct bcma_device *core) +bool brcms_c_chipmatch(u16 vendor, u16 device) { - struct pci_dev *pcidev = core->bus->host_pci; - u16 vendor = pcidev->vendor; - u16 device = pcidev->device; - if (vendor != PCI_VENDOR_ID_BROADCOM) { pr_err("unknown vendor id %04x\n", vendor); return false; @@ -5808,30 +5787,6 @@ static bool brcms_c_chipmatch_pci(struct bcma_device *core) return false; } -static bool brcms_c_chipmatch_soc(struct bcma_device *core) -{ - struct bcma_chipinfo *chipinfo = &core->bus->chipinfo; - - if (chipinfo->id == BCMA_CHIP_ID_BCM4716) - return true; - - pr_err("unknown chip id %04x\n", chipinfo->id); - return false; -} - -bool brcms_c_chipmatch(struct bcma_device *core) -{ - switch (core->bus->hosttype) { - case BCMA_HOSTTYPE_PCI: - return brcms_c_chipmatch_pci(core); - case BCMA_HOSTTYPE_SOC: - return brcms_c_chipmatch_soc(core); - default: - pr_err("unknown host type: %i\n", core->bus->hosttype); - return false; - } -} - #if defined(DEBUG) void brcms_c_print_txdesc(struct d11txh *txh) { diff --git a/trunk/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_cmn.c b/trunk/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_cmn.c index 91937c5025ce..264f8c4c703d 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_cmn.c +++ b/trunk/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_cmn.c @@ -198,8 +198,6 @@ u16 read_radio_reg(struct brcms_phy *pi, u16 addr) void write_radio_reg(struct brcms_phy *pi, u16 addr, u16 val) { - struct si_info *sii = container_of(pi->sh->sih, struct si_info, pub); - if ((D11REV_GE(pi->sh->corerev, 24)) || (D11REV_IS(pi->sh->corerev, 22) && (pi->pubpi.phy_type != PHY_TYPE_SSN))) { @@ -211,8 +209,7 @@ void write_radio_reg(struct brcms_phy *pi, u16 addr, u16 val) bcma_write16(pi->d11core, D11REGOFFS(phy4wdatalo), val); } - if ((sii->icbus->hosttype == BCMA_HOSTTYPE_PCI) && - (++pi->phy_wreg >= pi->phy_wreg_limit)) { + if (++pi->phy_wreg >= pi->phy_wreg_limit) { (void)bcma_read32(pi->d11core, D11REGOFFS(maccontrol)); pi->phy_wreg = 0; } @@ -295,13 +292,10 @@ void write_phy_reg(struct brcms_phy *pi, u16 addr, u16 val) bcma_wflush16(pi->d11core, D11REGOFFS(phyregaddr), addr); bcma_write16(pi->d11core, D11REGOFFS(phyregdata), val); if (addr == 0x72) - (void)bcma_read16(pi->d11core, D11REGOFFS(phyregdata)); + (void)bcma_read16(pi->d11core, D11REGOFFS(phyversion)); #else - struct si_info *sii = container_of(pi->sh->sih, struct si_info, pub); - bcma_write32(pi->d11core, D11REGOFFS(phyregaddr), addr | (val << 16)); - if ((sii->icbus->hosttype == BCMA_HOSTTYPE_PCI) && - (++pi->phy_wreg >= pi->phy_wreg_limit)) { + if (++pi->phy_wreg >= pi->phy_wreg_limit) { pi->phy_wreg = 0; (void)bcma_read16(pi->d11core, D11REGOFFS(phyversion)); } @@ -843,7 +837,7 @@ wlc_phy_table_addr(struct brcms_phy *pi, uint tbl_id, uint tbl_offset, pi->tbl_data_hi = tblDataHi; pi->tbl_data_lo = tblDataLo; - if (pi->sh->chip == BCMA_CHIP_ID_BCM43224 && + if (pi->sh->chip == BCM43224_CHIP_ID && pi->sh->chiprev == 1) { pi->tbl_addr = tblAddr; pi->tbl_save_id = tbl_id; @@ -853,7 +847,7 @@ wlc_phy_table_addr(struct brcms_phy *pi, uint tbl_id, uint tbl_offset, void wlc_phy_table_data_write(struct brcms_phy *pi, uint width, u32 val) { - if ((pi->sh->chip == BCMA_CHIP_ID_BCM43224) && + if ((pi->sh->chip == BCM43224_CHIP_ID) && (pi->sh->chiprev == 1) && (pi->tbl_save_id == NPHY_TBL_ID_ANTSWCTRLLUT)) { read_phy_reg(pi, pi->tbl_data_lo); @@ -887,7 +881,7 @@ wlc_phy_write_table(struct brcms_phy *pi, const struct phytbl_info *ptbl_info, for (idx = 0; idx < ptbl_info->tbl_len; idx++) { - if ((pi->sh->chip == BCMA_CHIP_ID_BCM43224) && + if ((pi->sh->chip == BCM43224_CHIP_ID) && (pi->sh->chiprev == 1) && (tbl_id == NPHY_TBL_ID_ANTSWCTRLLUT)) { read_phy_reg(pi, tblDataLo); @@ -924,7 +918,7 @@ wlc_phy_read_table(struct brcms_phy *pi, const struct phytbl_info *ptbl_info, for (idx = 0; idx < ptbl_info->tbl_len; idx++) { - if ((pi->sh->chip == BCMA_CHIP_ID_BCM43224) && + if ((pi->sh->chip == BCM43224_CHIP_ID) && (pi->sh->chiprev == 1)) { (void)read_phy_reg(pi, tblDataLo); @@ -2900,7 +2894,7 @@ const u8 *wlc_phy_get_ofdm_rate_lookup(void) void wlc_lcnphy_epa_switch(struct brcms_phy *pi, bool mode) { - if ((pi->sh->chip == BCMA_CHIP_ID_BCM4313) && + if ((pi->sh->chip == BCM4313_CHIP_ID) && (pi->sh->boardflags & BFL_FEM)) { if (mode) { u16 txant = 0; diff --git a/trunk/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c b/trunk/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c index 65db9b7458dc..366718146418 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c +++ b/trunk/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c @@ -17893,8 +17893,6 @@ static u32 *wlc_phy_get_ipa_gaintbl_nphy(struct brcms_phy *pi) nphy_tpc_txgain_ipa_2g_2057rev7; } else if (NREV_IS(pi->pubpi.phy_rev, 6)) { tx_pwrctrl_tbl = nphy_tpc_txgain_ipa_rev6; - if (pi->sh->chip == BCMA_CHIP_ID_BCM47162) - tx_pwrctrl_tbl = nphy_tpc_txgain_ipa_rev5; } else if (NREV_IS(pi->pubpi.phy_rev, 5)) { tx_pwrctrl_tbl = nphy_tpc_txgain_ipa_rev5; } else { @@ -19256,14 +19254,8 @@ static void wlc_phy_spurwar_nphy(struct brcms_phy *pi) case 38: case 102: case 118: - if ((pi->sh->chip == BCMA_CHIP_ID_BCM4716) && - (pi->sh->chippkg == BCMA_PKG_ID_BCM4717)) { - nphy_adj_tone_id_buf[0] = 32; - nphy_adj_noise_var_buf[0] = 0x21f; - } else { - nphy_adj_tone_id_buf[0] = 0; - nphy_adj_noise_var_buf[0] = 0x0; - } + nphy_adj_tone_id_buf[0] = 0; + nphy_adj_noise_var_buf[0] = 0x0; break; case 134: nphy_adj_tone_id_buf[0] = 32; @@ -19317,8 +19309,8 @@ void wlc_phy_init_nphy(struct brcms_phy *pi) pi->measure_hold |= PHY_HOLD_FOR_NOT_ASSOC; if ((ISNPHY(pi)) && (NREV_GE(pi->pubpi.phy_rev, 5)) && - ((pi->sh->chippkg == BCMA_PKG_ID_BCM4717) || - (pi->sh->chippkg == BCMA_PKG_ID_BCM4718))) { + ((pi->sh->chippkg == BCM4717_PKG_ID) || + (pi->sh->chippkg == BCM4718_PKG_ID))) { if ((pi->sh->boardflags & BFL_EXTLNA) && (CHSPEC_IS2G(pi->radio_chanspec))) ai_cc_reg(pi->sh->sih, @@ -19326,10 +19318,6 @@ void wlc_phy_init_nphy(struct brcms_phy *pi) 0x40, 0x40); } - if ((!PHY_IPA(pi)) && (pi->sh->chip == BCMA_CHIP_ID_BCM5357)) - si_pmu_chipcontrol(pi->sh->sih, 1, CCTRL5357_EXTPA, - CCTRL5357_EXTPA); - if ((pi->nphy_gband_spurwar2_en) && CHSPEC_IS2G(pi->radio_chanspec) && CHSPEC_IS40(pi->radio_chanspec)) { @@ -20707,22 +20695,12 @@ wlc_phy_chanspec_radio2056_setup(struct brcms_phy *pi, write_radio_reg(pi, RADIO_2056_SYN_PLL_LOOPFILTER2 | RADIO_2056_SYN, 0x1f); - if ((pi->sh->chip == BCMA_CHIP_ID_BCM4716) || - (pi->sh->chip == BCMA_CHIP_ID_BCM47162)) { - write_radio_reg(pi, - RADIO_2056_SYN_PLL_LOOPFILTER4 | - RADIO_2056_SYN, 0x14); - write_radio_reg(pi, - RADIO_2056_SYN_PLL_CP2 | - RADIO_2056_SYN, 0x00); - } else { - write_radio_reg(pi, - RADIO_2056_SYN_PLL_LOOPFILTER4 | - RADIO_2056_SYN, 0xb); - write_radio_reg(pi, - RADIO_2056_SYN_PLL_CP2 | - RADIO_2056_SYN, 0x14); - } + write_radio_reg(pi, + RADIO_2056_SYN_PLL_LOOPFILTER4 | + RADIO_2056_SYN, 0xb); + write_radio_reg(pi, + RADIO_2056_SYN_PLL_CP2 | + RADIO_2056_SYN, 0x14); } } @@ -20769,31 +20747,25 @@ wlc_phy_chanspec_radio2056_setup(struct brcms_phy *pi, WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, PADG_IDAC, 0xcc); - if ((pi->sh->chip == BCMA_CHIP_ID_BCM4716) || - (pi->sh->chip == BCMA_CHIP_ID_BCM47162)) { - bias = 0x40; - cascbias = 0x45; - pag_boost_tune = 0x5; - pgag_boost_tune = 0x33; - padg_boost_tune = 0x77; - mixg_boost_tune = 0x55; - } else { - bias = 0x25; - cascbias = 0x20; + bias = 0x25; + cascbias = 0x20; - if ((pi->sh->chip == BCMA_CHIP_ID_BCM43224 || - pi->sh->chip == BCMA_CHIP_ID_BCM43225) && - pi->sh->chippkg == BCMA_PKG_ID_BCM43224_FAB_SMIC) { + if ((pi->sh->chip == + BCM43224_CHIP_ID) + || (pi->sh->chip == + BCM43225_CHIP_ID)) { + if (pi->sh->chippkg == + BCM43224_FAB_SMIC) { bias = 0x2a; cascbias = 0x38; } - - pag_boost_tune = 0x4; - pgag_boost_tune = 0x03; - padg_boost_tune = 0x77; - mixg_boost_tune = 0x65; } + pag_boost_tune = 0x4; + pgag_boost_tune = 0x03; + padg_boost_tune = 0x77; + mixg_boost_tune = 0x65; + WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, INTPAG_IMAIN_STAT, bias); WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, @@ -20891,10 +20863,11 @@ wlc_phy_chanspec_radio2056_setup(struct brcms_phy *pi, cascbias = 0x30; - if ((pi->sh->chip == BCMA_CHIP_ID_BCM43224 || - pi->sh->chip == BCMA_CHIP_ID_BCM43225) && - pi->sh->chippkg == BCMA_PKG_ID_BCM43224_FAB_SMIC) - cascbias = 0x35; + if ((pi->sh->chip == BCM43224_CHIP_ID) || + (pi->sh->chip == BCM43225_CHIP_ID)) { + if (pi->sh->chippkg == BCM43224_FAB_SMIC) + cascbias = 0x35; + } pabias = (pi->phy_pabias == 0) ? 0x30 : pi->phy_pabias; @@ -21133,7 +21106,6 @@ wlc_phy_chanspec_nphy_setup(struct brcms_phy *pi, u16 chanspec, const struct nphy_sfo_cfg *ci) { u16 val; - struct si_info *sii = container_of(pi->sh->sih, struct si_info, pub); val = read_phy_reg(pi, 0x09) & NPHY_BandControl_currentBand; if (CHSPEC_IS5G(chanspec) && !val) { @@ -21206,32 +21178,22 @@ wlc_phy_chanspec_nphy_setup(struct brcms_phy *pi, u16 chanspec, } else if (NREV_GE(pi->pubpi.phy_rev, 7)) { if (val == 54) spuravoid = 1; - } else if (pi->nphy_aband_spurwar_en && - ((val == 38) || (val == 102) || (val == 118))) { - if ((pi->sh->chip == BCMA_CHIP_ID_BCM4716) - && (pi->sh->chippkg == BCMA_PKG_ID_BCM4717)) { - spuravoid = 0; - } else { + } else { + if (pi->nphy_aband_spurwar_en && + ((val == 38) || (val == 102) + || (val == 118))) spuravoid = 1; - } } if (pi->phy_spuravoid == SPURAVOID_FORCEON) spuravoid = 1; - if ((pi->sh->chip == BCMA_CHIP_ID_BCM4716) || - (pi->sh->chip == BCMA_CHIP_ID_BCM43225)) { - bcma_pmu_spuravoid_pllupdate(&sii->icbus->drv_cc, - spuravoid); - } else { - wlapi_bmac_core_phypll_ctl(pi->sh->physhim, false); - bcma_pmu_spuravoid_pllupdate(&sii->icbus->drv_cc, - spuravoid); - wlapi_bmac_core_phypll_ctl(pi->sh->physhim, true); - } + wlapi_bmac_core_phypll_ctl(pi->sh->physhim, false); + si_pmu_spuravoid_pllupdate(pi->sh->sih, spuravoid); + wlapi_bmac_core_phypll_ctl(pi->sh->physhim, true); - if ((pi->sh->chip == BCMA_CHIP_ID_BCM43224) || - (pi->sh->chip == BCMA_CHIP_ID_BCM43225)) { + if ((pi->sh->chip == BCM43224_CHIP_ID) || + (pi->sh->chip == BCM43225_CHIP_ID)) { if (spuravoid == 1) { bcma_write16(pi->d11core, D11REGOFFS(tsf_clk_frac_l), @@ -21247,9 +21209,7 @@ wlc_phy_chanspec_nphy_setup(struct brcms_phy *pi, u16 chanspec, } } - if (!((pi->sh->chip == BCMA_CHIP_ID_BCM4716) || - (pi->sh->chip == BCMA_CHIP_ID_BCM47162))) - wlapi_bmac_core_phypll_reset(pi->sh->physhim); + wlapi_bmac_core_phypll_reset(pi->sh->physhim); mod_phy_reg(pi, 0x01, (0x1 << 15), ((spuravoid > 0) ? (0x1 << 15) : 0)); @@ -22211,15 +22171,9 @@ s16 wlc_phy_tempsense_nphy(struct brcms_phy *pi) wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x03, 16, &auxADC_rssi_ctrlH_save); - if (pi->sh->chip == BCMA_CHIP_ID_BCM5357) { - radio_temp[0] = (193 * (radio_temp[1] + radio_temp2[1]) - + 88 * (auxADC_Vl) - 27111 + - 128) / 256; - } else { - radio_temp[0] = (179 * (radio_temp[1] + radio_temp2[1]) - + 82 * (auxADC_Vl) - 28861 + - 128) / 256; - } + radio_temp[0] = (179 * (radio_temp[1] + radio_temp2[1]) + + 82 * (auxADC_Vl) - 28861 + + 128) / 256; offset = (s16) pi->phy_tempsense_offset; @@ -24969,16 +24923,14 @@ wlc_phy_a2_nphy(struct brcms_phy *pi, struct nphy_ipa_txcalgains *txgains, if (txgains->useindex) { phy_a4 = 15 - ((txgains->index) >> 3); if (CHSPEC_IS2G(pi->radio_chanspec)) { - if (NREV_GE(pi->pubpi.phy_rev, 6) && - pi->sh->chip == BCMA_CHIP_ID_BCM47162) { - phy_a5 = 0x10f7 | (phy_a4 << 8); - } else if (NREV_GE(pi->pubpi.phy_rev, 6)) { + if (NREV_GE(pi->pubpi.phy_rev, 6)) phy_a5 = 0x00f7 | (phy_a4 << 8); - } else if (NREV_IS(pi->pubpi.phy_rev, 5)) { + + else + if (NREV_IS(pi->pubpi.phy_rev, 5)) phy_a5 = 0x10f7 | (phy_a4 << 8); - } else { + else phy_a5 = 0x50f7 | (phy_a4 << 8); - } } else { phy_a5 = 0x70f7 | (phy_a4 << 8); } diff --git a/trunk/drivers/net/wireless/brcm80211/brcmsmac/pmu.c b/trunk/drivers/net/wireless/brcm80211/brcmsmac/pmu.c index 7e9df566c733..4931d29d077b 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmsmac/pmu.c +++ b/trunk/drivers/net/wireless/brcm80211/brcmsmac/pmu.c @@ -74,6 +74,16 @@ * PMU_PLL_XX where is PMU corerev and is an arbitrary * number to differentiate different PLLs controlled by the same PMU rev. */ +/* pllcontrol registers: + * ndiv_pwrdn, pwrdn_ch, refcomp_pwrdn, dly_ch, + * p1div, p2div, _bypass_sdmod + */ +#define PMU1_PLL0_PLLCTL0 0 +#define PMU1_PLL0_PLLCTL1 1 +#define PMU1_PLL0_PLLCTL2 2 +#define PMU1_PLL0_PLLCTL3 3 +#define PMU1_PLL0_PLLCTL4 4 +#define PMU1_PLL0_PLLCTL5 5 /* pmu XtalFreqRatio */ #define PMU_XTALFREQ_REG_ILPCTR_MASK 0x00001FFF @@ -98,14 +108,118 @@ #define RES4313_HT_AVAIL_RSRC 14 #define RES4313_MACPHY_CLK_AVAIL_RSRC 15 +/* Determine min/max rsrc masks. Value 0 leaves hardware at default. */ +static void si_pmu_res_masks(struct si_pub *sih, u32 * pmin, u32 * pmax) +{ + u32 min_mask = 0, max_mask = 0; + uint rsrcs; + + /* # resources */ + rsrcs = (ai_get_pmucaps(sih) & PCAP_RC_MASK) >> PCAP_RC_SHIFT; + + /* determine min/max rsrc masks */ + switch (ai_get_chip_id(sih)) { + case BCM43224_CHIP_ID: + case BCM43225_CHIP_ID: + /* ??? */ + break; + + case BCM4313_CHIP_ID: + min_mask = PMURES_BIT(RES4313_BB_PU_RSRC) | + PMURES_BIT(RES4313_XTAL_PU_RSRC) | + PMURES_BIT(RES4313_ALP_AVAIL_RSRC) | + PMURES_BIT(RES4313_BB_PLL_PWRSW_RSRC); + max_mask = 0xffff; + break; + default: + break; + } + + *pmin = min_mask; + *pmax = max_mask; +} + +void si_pmu_spuravoid_pllupdate(struct si_pub *sih, u8 spuravoid) +{ + u32 tmp = 0; + struct bcma_device *core; + + /* switch to chipc */ + core = ai_findcore(sih, BCMA_CORE_CHIPCOMMON, 0); + + switch (ai_get_chip_id(sih)) { + case BCM43224_CHIP_ID: + case BCM43225_CHIP_ID: + if (spuravoid == 1) { + bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr), + PMU1_PLL0_PLLCTL0); + bcma_write32(core, CHIPCREGOFFS(pllcontrol_data), + 0x11500010); + bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr), + PMU1_PLL0_PLLCTL1); + bcma_write32(core, CHIPCREGOFFS(pllcontrol_data), + 0x000C0C06); + bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr), + PMU1_PLL0_PLLCTL2); + bcma_write32(core, CHIPCREGOFFS(pllcontrol_data), + 0x0F600a08); + bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr), + PMU1_PLL0_PLLCTL3); + bcma_write32(core, CHIPCREGOFFS(pllcontrol_data), + 0x00000000); + bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr), + PMU1_PLL0_PLLCTL4); + bcma_write32(core, CHIPCREGOFFS(pllcontrol_data), + 0x2001E920); + bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr), + PMU1_PLL0_PLLCTL5); + bcma_write32(core, CHIPCREGOFFS(pllcontrol_data), + 0x88888815); + } else { + bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr), + PMU1_PLL0_PLLCTL0); + bcma_write32(core, CHIPCREGOFFS(pllcontrol_data), + 0x11100010); + bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr), + PMU1_PLL0_PLLCTL1); + bcma_write32(core, CHIPCREGOFFS(pllcontrol_data), + 0x000c0c06); + bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr), + PMU1_PLL0_PLLCTL2); + bcma_write32(core, CHIPCREGOFFS(pllcontrol_data), + 0x03000a08); + bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr), + PMU1_PLL0_PLLCTL3); + bcma_write32(core, CHIPCREGOFFS(pllcontrol_data), + 0x00000000); + bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr), + PMU1_PLL0_PLLCTL4); + bcma_write32(core, CHIPCREGOFFS(pllcontrol_data), + 0x200005c0); + bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr), + PMU1_PLL0_PLLCTL5); + bcma_write32(core, CHIPCREGOFFS(pllcontrol_data), + 0x88888815); + } + tmp = 1 << 10; + break; + + default: + /* bail out */ + return; + } + + bcma_set32(core, CHIPCREGOFFS(pmucontrol), tmp); +} + u16 si_pmu_fast_pwrup_delay(struct si_pub *sih) { uint delay = PMU_MAX_TRANSITION_DLY; switch (ai_get_chip_id(sih)) { - case BCMA_CHIP_ID_BCM43224: - case BCMA_CHIP_ID_BCM43225: - case BCMA_CHIP_ID_BCM4313: + case BCM43224_CHIP_ID: + case BCM43225_CHIP_ID: + case BCM4313_CHIP_ID: delay = 3700; break; default: @@ -156,9 +270,9 @@ u32 si_pmu_alp_clock(struct si_pub *sih) return clock; switch (ai_get_chip_id(sih)) { - case BCMA_CHIP_ID_BCM43224: - case BCMA_CHIP_ID_BCM43225: - case BCMA_CHIP_ID_BCM4313: + case BCM43224_CHIP_ID: + case BCM43225_CHIP_ID: + case BCM4313_CHIP_ID: /* always 20Mhz */ clock = 20000 * 1000; break; @@ -169,9 +283,51 @@ u32 si_pmu_alp_clock(struct si_pub *sih) return clock; } +/* initialize PMU */ +void si_pmu_init(struct si_pub *sih) +{ + struct bcma_device *core; + + /* select chipc */ + core = ai_findcore(sih, BCMA_CORE_CHIPCOMMON, 0); + + if (ai_get_pmurev(sih) == 1) + bcma_mask32(core, CHIPCREGOFFS(pmucontrol), + ~PCTL_NOILP_ON_WAIT); + else if (ai_get_pmurev(sih) >= 2) + bcma_set32(core, CHIPCREGOFFS(pmucontrol), PCTL_NOILP_ON_WAIT); +} + +/* initialize PMU resources */ +void si_pmu_res_init(struct si_pub *sih) +{ + struct bcma_device *core; + u32 min_mask = 0, max_mask = 0; + + /* select to chipc */ + core = ai_findcore(sih, BCMA_CORE_CHIPCOMMON, 0); + + /* Determine min/max rsrc masks */ + si_pmu_res_masks(sih, &min_mask, &max_mask); + + /* It is required to program max_mask first and then min_mask */ + + /* Program max resource mask */ + + if (max_mask) + bcma_write32(core, CHIPCREGOFFS(max_res_mask), max_mask); + + /* Program min resource mask */ + + if (min_mask) + bcma_write32(core, CHIPCREGOFFS(min_res_mask), min_mask); + + /* Add some delay; allow resources to come up and settle. */ + mdelay(2); +} + u32 si_pmu_measure_alpclk(struct si_pub *sih) { - struct si_info *sii = container_of(sih, struct si_info, pub); struct bcma_device *core; u32 alp_khz; @@ -179,7 +335,7 @@ u32 si_pmu_measure_alpclk(struct si_pub *sih) return 0; /* Remember original core before switch to chipc */ - core = sii->icbus->drv_cc.core; + core = ai_findcore(sih, BCMA_CORE_CHIPCOMMON, 0); if (bcma_read32(core, CHIPCREGOFFS(pmustatus)) & PST_EXTLPOAVAIL) { u32 ilp_ctr, alp_hz; diff --git a/trunk/drivers/net/wireless/brcm80211/brcmsmac/pmu.h b/trunk/drivers/net/wireless/brcm80211/brcmsmac/pmu.h index f7cff873578b..3e39c5e0f9ff 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmsmac/pmu.h +++ b/trunk/drivers/net/wireless/brcm80211/brcmsmac/pmu.h @@ -26,7 +26,10 @@ extern u32 si_pmu_chipcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val); extern u32 si_pmu_regcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val); extern u32 si_pmu_alp_clock(struct si_pub *sih); extern void si_pmu_pllupd(struct si_pub *sih); +extern void si_pmu_spuravoid_pllupdate(struct si_pub *sih, u8 spuravoid); extern u32 si_pmu_pllcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val); +extern void si_pmu_init(struct si_pub *sih); +extern void si_pmu_res_init(struct si_pub *sih); extern u32 si_pmu_measure_alpclk(struct si_pub *sih); #endif /* _BRCM_PMU_H_ */ diff --git a/trunk/drivers/net/wireless/brcm80211/brcmsmac/pub.h b/trunk/drivers/net/wireless/brcm80211/brcmsmac/pub.h index 5855f4fd16dc..aa5d67f8d874 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmsmac/pub.h +++ b/trunk/drivers/net/wireless/brcm80211/brcmsmac/pub.h @@ -311,7 +311,7 @@ extern uint brcms_c_detach(struct brcms_c_info *wlc); extern int brcms_c_up(struct brcms_c_info *wlc); extern uint brcms_c_down(struct brcms_c_info *wlc); -extern bool brcms_c_chipmatch(struct bcma_device *core); +extern bool brcms_c_chipmatch(u16 vendor, u16 device); extern void brcms_c_init(struct brcms_c_info *wlc, bool mute_tx); extern void brcms_c_reset(struct brcms_c_info *wlc); diff --git a/trunk/drivers/net/wireless/brcm80211/include/soc.h b/trunk/drivers/net/wireless/brcm80211/include/soc.h index 123cfa854a0d..4e9b7e4827ea 100644 --- a/trunk/drivers/net/wireless/brcm80211/include/soc.h +++ b/trunk/drivers/net/wireless/brcm80211/include/soc.h @@ -19,6 +19,68 @@ #define SI_ENUM_BASE 0x18000000 /* Enumeration space base */ +/* core codes */ +#define NODEV_CORE_ID 0x700 /* Invalid coreid */ +#define CC_CORE_ID 0x800 /* chipcommon core */ +#define ILINE20_CORE_ID 0x801 /* iline20 core */ +#define SRAM_CORE_ID 0x802 /* sram core */ +#define SDRAM_CORE_ID 0x803 /* sdram core */ +#define PCI_CORE_ID 0x804 /* pci core */ +#define MIPS_CORE_ID 0x805 /* mips core */ +#define ENET_CORE_ID 0x806 /* enet mac core */ +#define CODEC_CORE_ID 0x807 /* v90 codec core */ +#define USB_CORE_ID 0x808 /* usb 1.1 host/device core */ +#define ADSL_CORE_ID 0x809 /* ADSL core */ +#define ILINE100_CORE_ID 0x80a /* iline100 core */ +#define IPSEC_CORE_ID 0x80b /* ipsec core */ +#define UTOPIA_CORE_ID 0x80c /* utopia core */ +#define PCMCIA_CORE_ID 0x80d /* pcmcia core */ +#define SOCRAM_CORE_ID 0x80e /* internal memory core */ +#define MEMC_CORE_ID 0x80f /* memc sdram core */ +#define OFDM_CORE_ID 0x810 /* OFDM phy core */ +#define EXTIF_CORE_ID 0x811 /* external interface core */ +#define D11_CORE_ID 0x812 /* 802.11 MAC core */ +#define APHY_CORE_ID 0x813 /* 802.11a phy core */ +#define BPHY_CORE_ID 0x814 /* 802.11b phy core */ +#define GPHY_CORE_ID 0x815 /* 802.11g phy core */ +#define MIPS33_CORE_ID 0x816 /* mips3302 core */ +#define USB11H_CORE_ID 0x817 /* usb 1.1 host core */ +#define USB11D_CORE_ID 0x818 /* usb 1.1 device core */ +#define USB20H_CORE_ID 0x819 /* usb 2.0 host core */ +#define USB20D_CORE_ID 0x81a /* usb 2.0 device core */ +#define SDIOH_CORE_ID 0x81b /* sdio host core */ +#define ROBO_CORE_ID 0x81c /* roboswitch core */ +#define ATA100_CORE_ID 0x81d /* parallel ATA core */ +#define SATAXOR_CORE_ID 0x81e /* serial ATA & XOR DMA core */ +#define GIGETH_CORE_ID 0x81f /* gigabit ethernet core */ +#define PCIE_CORE_ID 0x820 /* pci express core */ +#define NPHY_CORE_ID 0x821 /* 802.11n 2x2 phy core */ +#define SRAMC_CORE_ID 0x822 /* SRAM controller core */ +#define MINIMAC_CORE_ID 0x823 /* MINI MAC/phy core */ +#define ARM11_CORE_ID 0x824 /* ARM 1176 core */ +#define ARM7S_CORE_ID 0x825 /* ARM7tdmi-s core */ +#define LPPHY_CORE_ID 0x826 /* 802.11a/b/g phy core */ +#define PMU_CORE_ID 0x827 /* PMU core */ +#define SSNPHY_CORE_ID 0x828 /* 802.11n single-stream phy core */ +#define SDIOD_CORE_ID 0x829 /* SDIO device core */ +#define ARMCM3_CORE_ID 0x82a /* ARM Cortex M3 core */ +#define HTPHY_CORE_ID 0x82b /* 802.11n 4x4 phy core */ +#define MIPS74K_CORE_ID 0x82c /* mips 74k core */ +#define GMAC_CORE_ID 0x82d /* Gigabit MAC core */ +#define DMEMC_CORE_ID 0x82e /* DDR1/2 memory controller core */ +#define PCIERC_CORE_ID 0x82f /* PCIE Root Complex core */ +#define OCP_CORE_ID 0x830 /* OCP2OCP bridge core */ +#define SC_CORE_ID 0x831 /* shared common core */ +#define AHB_CORE_ID 0x832 /* OCP2AHB bridge core */ +#define SPIH_CORE_ID 0x833 /* SPI host core */ +#define I2S_CORE_ID 0x834 /* I2S core */ +#define DMEMS_CORE_ID 0x835 /* SDR/DDR1 memory controller core */ +#define DEF_SHIM_COMP 0x837 /* SHIM component in ubus/6362 */ +#define OOB_ROUTER_CORE_ID 0x367 /* OOB router core ID */ +#define DEF_AI_COMP 0xfff /* Default component, in ai chips it + * maps all unused address ranges + */ + /* Common core control flags */ #define SICF_BIST_EN 0x8000 #define SICF_PME_EN 0x4000 diff --git a/trunk/drivers/net/wireless/iwlegacy/3945-rs.c b/trunk/drivers/net/wireless/iwlegacy/3945-rs.c index d4fd29ad90dc..4b10157d8686 100644 --- a/trunk/drivers/net/wireless/iwlegacy/3945-rs.c +++ b/trunk/drivers/net/wireless/iwlegacy/3945-rs.c @@ -946,7 +946,7 @@ il3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id) case IEEE80211_BAND_5GHZ: rs_sta->expected_tpt = il3945_expected_tpt_a; break; - default: + case IEEE80211_NUM_BANDS: BUG(); break; } diff --git a/trunk/drivers/net/wireless/iwlegacy/4965-mac.c b/trunk/drivers/net/wireless/iwlegacy/4965-mac.c index 34f61a0581a2..d24eaf89ffb5 100644 --- a/trunk/drivers/net/wireless/iwlegacy/4965-mac.c +++ b/trunk/drivers/net/wireless/iwlegacy/4965-mac.c @@ -3405,7 +3405,7 @@ il4965_remove_dynamic_key(struct il_priv *il, return 0; } - if (il->stations[sta_id].sta.key.key_flags & STA_KEY_FLG_INVALID) { + if (il->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET) { IL_WARN("Removing wrong key %d 0x%x\n", keyconf->keyidx, key_flags); spin_unlock_irqrestore(&il->sta_lock, flags); @@ -3420,7 +3420,7 @@ il4965_remove_dynamic_key(struct il_priv *il, memset(&il->stations[sta_id].sta.key, 0, sizeof(struct il4965_keyinfo)); il->stations[sta_id].sta.key.key_flags = STA_KEY_FLG_NO_ENC | STA_KEY_FLG_INVALID; - il->stations[sta_id].sta.key.key_offset = keyconf->hw_key_idx; + il->stations[sta_id].sta.key.key_offset = WEP_INVALID_OFFSET; il->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK; il->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; diff --git a/trunk/drivers/net/wireless/iwlegacy/common.c b/trunk/drivers/net/wireless/iwlegacy/common.c index 0f8a7703eea3..763c7529921b 100644 --- a/trunk/drivers/net/wireless/iwlegacy/common.c +++ b/trunk/drivers/net/wireless/iwlegacy/common.c @@ -4768,12 +4768,14 @@ il_bg_watchdog(unsigned long data) return; /* monitor and check for other stuck queues */ - for (cnt = 0; cnt < il->hw_params.max_txq_num; cnt++) { - /* skip as we already checked the command queue */ - if (cnt == il->cmd_queue) - continue; - if (il_check_stuck_queue(il, cnt)) - return; + if (il_is_any_associated(il)) { + for (cnt = 0; cnt < il->hw_params.max_txq_num; cnt++) { + /* skip as we already checked the command queue */ + if (cnt == il->cmd_queue) + continue; + if (il_check_stuck_queue(il, cnt)) + return; + } } mod_timer(&il->watchdog, diff --git a/trunk/drivers/net/wireless/iwlwifi/dvm/commands.h b/trunk/drivers/net/wireless/iwlwifi/dvm/commands.h index 97bea16f3592..64811cd91635 100644 --- a/trunk/drivers/net/wireless/iwlwifi/dvm/commands.h +++ b/trunk/drivers/net/wireless/iwlwifi/dvm/commands.h @@ -190,44 +190,6 @@ enum { REPLY_MAX = 0xff }; -/* - * Minimum number of queues. MAX_NUM is defined in hw specific files. - * Set the minimum to accommodate - * - 4 standard TX queues - * - the command queue - * - 4 PAN TX queues - * - the PAN multicast queue, and - * - the AUX (TX during scan dwell) queue. - */ -#define IWL_MIN_NUM_QUEUES 11 - -/* - * Command queue depends on iPAN support. - */ -#define IWL_DEFAULT_CMD_QUEUE_NUM 4 -#define IWL_IPAN_CMD_QUEUE_NUM 9 - -#define IWL_TX_FIFO_BK 0 /* shared */ -#define IWL_TX_FIFO_BE 1 -#define IWL_TX_FIFO_VI 2 /* shared */ -#define IWL_TX_FIFO_VO 3 -#define IWL_TX_FIFO_BK_IPAN IWL_TX_FIFO_BK -#define IWL_TX_FIFO_BE_IPAN 4 -#define IWL_TX_FIFO_VI_IPAN IWL_TX_FIFO_VI -#define IWL_TX_FIFO_VO_IPAN 5 -/* re-uses the VO FIFO, uCode will properly flush/schedule */ -#define IWL_TX_FIFO_AUX 5 -#define IWL_TX_FIFO_UNUSED 255 - -#define IWLAGN_CMD_FIFO_NUM 7 - -/* - * This queue number is required for proper operation - * because the ucode will stop/start the scheduler as - * required. - */ -#define IWL_IPAN_MCAST_QUEUE 8 - /****************************************************************************** * (0) * Commonly used structures and definitions: @@ -793,6 +755,8 @@ struct iwl_qosparam_cmd { #define IWLAGN_BROADCAST_ID 15 #define IWLAGN_STATION_COUNT 16 +#define IWL_INVALID_STATION 255 +#define IWL_MAX_TID_COUNT 8 #define IWL_TID_NON_QOS IWL_MAX_TID_COUNT #define STA_FLG_TX_RATE_MSK cpu_to_le32(1 << 2) diff --git a/trunk/drivers/net/wireless/iwlwifi/dvm/debugfs.c b/trunk/drivers/net/wireless/iwlwifi/dvm/debugfs.c index 46782f1102ac..b0eff1c340c7 100644 --- a/trunk/drivers/net/wireless/iwlwifi/dvm/debugfs.c +++ b/trunk/drivers/net/wireless/iwlwifi/dvm/debugfs.c @@ -83,7 +83,7 @@ static ssize_t iwl_dbgfs_##name##_write(struct file *file, \ #define DEBUGFS_READ_FILE_OPS(name) \ DEBUGFS_READ_FUNC(name); \ static const struct file_operations iwl_dbgfs_##name##_ops = { \ - .read = iwl_dbgfs_##name##_read, \ + .read = iwl_dbgfs_##name##_read, \ .open = simple_open, \ .llseek = generic_file_llseek, \ }; @@ -2255,10 +2255,6 @@ static ssize_t iwl_dbgfs_log_event_write(struct file *file, char buf[8]; int buf_size; - /* check that the interface is up */ - if (!iwl_is_ready(priv)) - return -EAGAIN; - memset(buf, 0, sizeof(buf)); buf_size = min(count, sizeof(buf) - 1); if (copy_from_user(buf, user_buf, buf_size)) diff --git a/trunk/drivers/net/wireless/iwlwifi/dvm/dev.h b/trunk/drivers/net/wireless/iwlwifi/dvm/dev.h index 054f728f6266..54cf085ddc89 100644 --- a/trunk/drivers/net/wireless/iwlwifi/dvm/dev.h +++ b/trunk/drivers/net/wireless/iwlwifi/dvm/dev.h @@ -90,6 +90,22 @@ #define IWL_NUM_SCAN_RATES (2) +/* + * Minimum number of queues. MAX_NUM is defined in hw specific files. + * Set the minimum to accommodate + * - 4 standard TX queues + * - the command queue + * - 4 PAN TX queues + * - the PAN multicast queue, and + * - the AUX (TX during scan dwell) queue. + */ +#define IWL_MIN_NUM_QUEUES 11 + +/* + * Command queue depends on iPAN support. + */ +#define IWL_DEFAULT_CMD_QUEUE_NUM 4 +#define IWL_IPAN_CMD_QUEUE_NUM 9 #define IEEE80211_DATA_LEN 2304 #define IEEE80211_4ADDR_LEN 30 diff --git a/trunk/drivers/net/wireless/iwlwifi/dvm/main.c b/trunk/drivers/net/wireless/iwlwifi/dvm/main.c index 612f05d757db..abfd7916bde6 100644 --- a/trunk/drivers/net/wireless/iwlwifi/dvm/main.c +++ b/trunk/drivers/net/wireless/iwlwifi/dvm/main.c @@ -518,6 +518,49 @@ static void iwl_bg_tx_flush(struct work_struct *work) * queue/FIFO/AC mapping definitions */ +#define IWL_TX_FIFO_BK 0 /* shared */ +#define IWL_TX_FIFO_BE 1 +#define IWL_TX_FIFO_VI 2 /* shared */ +#define IWL_TX_FIFO_VO 3 +#define IWL_TX_FIFO_BK_IPAN IWL_TX_FIFO_BK +#define IWL_TX_FIFO_BE_IPAN 4 +#define IWL_TX_FIFO_VI_IPAN IWL_TX_FIFO_VI +#define IWL_TX_FIFO_VO_IPAN 5 +/* re-uses the VO FIFO, uCode will properly flush/schedule */ +#define IWL_TX_FIFO_AUX 5 +#define IWL_TX_FIFO_UNUSED -1 + +#define IWLAGN_CMD_FIFO_NUM 7 + +/* + * This queue number is required for proper operation + * because the ucode will stop/start the scheduler as + * required. + */ +#define IWL_IPAN_MCAST_QUEUE 8 + +static const u8 iwlagn_default_queue_to_tx_fifo[] = { + IWL_TX_FIFO_VO, + IWL_TX_FIFO_VI, + IWL_TX_FIFO_BE, + IWL_TX_FIFO_BK, + IWLAGN_CMD_FIFO_NUM, +}; + +static const u8 iwlagn_ipan_queue_to_tx_fifo[] = { + IWL_TX_FIFO_VO, + IWL_TX_FIFO_VI, + IWL_TX_FIFO_BE, + IWL_TX_FIFO_BK, + IWL_TX_FIFO_BK_IPAN, + IWL_TX_FIFO_BE_IPAN, + IWL_TX_FIFO_VI_IPAN, + IWL_TX_FIFO_VO_IPAN, + IWL_TX_FIFO_BE_IPAN, + IWLAGN_CMD_FIFO_NUM, + IWL_TX_FIFO_AUX, +}; + static const u8 iwlagn_bss_ac_to_fifo[] = { IWL_TX_FIFO_VO, IWL_TX_FIFO_VI, @@ -1307,7 +1350,6 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans, else trans_cfg.queue_watchdog_timeout = IWL_WATCHDOG_DISABLED; trans_cfg.command_names = iwl_dvm_cmd_strings; - trans_cfg.cmd_fifo = IWLAGN_CMD_FIFO_NUM; WARN_ON(sizeof(priv->transport_queue_stop) * BITS_PER_BYTE < priv->cfg->base_params->num_of_queues); @@ -1321,9 +1363,15 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans, if (ucode_flags & IWL_UCODE_TLV_FLAGS_PAN) { priv->sta_key_max_num = STA_KEY_MAX_NUM_PAN; trans_cfg.cmd_queue = IWL_IPAN_CMD_QUEUE_NUM; + trans_cfg.queue_to_fifo = iwlagn_ipan_queue_to_tx_fifo; + trans_cfg.n_queue_to_fifo = + ARRAY_SIZE(iwlagn_ipan_queue_to_tx_fifo); } else { priv->sta_key_max_num = STA_KEY_MAX_NUM; trans_cfg.cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM; + trans_cfg.queue_to_fifo = iwlagn_default_queue_to_tx_fifo; + trans_cfg.n_queue_to_fifo = + ARRAY_SIZE(iwlagn_default_queue_to_tx_fifo); } /* Configure transport layer */ @@ -1412,6 +1460,9 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans, ucode_flags &= ~IWL_UCODE_TLV_FLAGS_P2P; priv->sta_key_max_num = STA_KEY_MAX_NUM; trans_cfg.cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM; + trans_cfg.queue_to_fifo = iwlagn_default_queue_to_tx_fifo; + trans_cfg.n_queue_to_fifo = + ARRAY_SIZE(iwlagn_default_queue_to_tx_fifo); /* Configure transport layer again*/ iwl_trans_configure(priv->trans, &trans_cfg); @@ -1429,6 +1480,9 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans, atomic_set(&priv->queue_stop_count[i], 0); } + WARN_ON(trans_cfg.queue_to_fifo[trans_cfg.cmd_queue] != + IWLAGN_CMD_FIFO_NUM); + if (iwl_init_drv(priv)) goto out_free_eeprom; diff --git a/trunk/drivers/net/wireless/iwlwifi/dvm/scan.c b/trunk/drivers/net/wireless/iwlwifi/dvm/scan.c index e3467fa86899..6633074258c7 100644 --- a/trunk/drivers/net/wireless/iwlwifi/dvm/scan.c +++ b/trunk/drivers/net/wireless/iwlwifi/dvm/scan.c @@ -396,21 +396,15 @@ static u16 iwl_get_active_dwell_time(struct iwl_priv *priv, static u16 iwl_limit_dwell(struct iwl_priv *priv, u16 dwell_time) { struct iwl_rxon_context *ctx; - int limits[NUM_IWL_RXON_CTX] = {}; - int n_active = 0; - u16 limit; - - BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2); /* * If we're associated, we clamp the dwell time 98% - * of the beacon interval (minus 2 * channel tune time) - * If both contexts are active, we have to restrict to - * 1/2 of the minimum of them, because they might be in - * lock-step with the time inbetween only half of what - * time we'd have in each of them. + * of the smallest beacon interval (minus 2 * channel + * tune time) */ for_each_context(priv, ctx) { + u16 value; + switch (ctx->staging.dev_type) { case RXON_DEV_TYPE_P2P: /* no timing constraints */ @@ -430,25 +424,14 @@ static u16 iwl_limit_dwell(struct iwl_priv *priv, u16 dwell_time) break; } - limits[n_active++] = ctx->beacon_int ?: IWL_PASSIVE_DWELL_BASE; + value = ctx->beacon_int; + if (!value) + value = IWL_PASSIVE_DWELL_BASE; + value = (value * 98) / 100 - IWL_CHANNEL_TUNE_TIME * 2; + dwell_time = min(value, dwell_time); } - switch (n_active) { - case 0: - return dwell_time; - case 2: - limit = (limits[1] * 98) / 100 - IWL_CHANNEL_TUNE_TIME * 2; - limit /= 2; - dwell_time = min(limit, dwell_time); - /* fall through to limit further */ - case 1: - limit = (limits[0] * 98) / 100 - IWL_CHANNEL_TUNE_TIME * 2; - limit /= n_active; - return min(limit, dwell_time); - default: - WARN_ON_ONCE(1); - return dwell_time; - } + return dwell_time; } static u16 iwl_get_passive_dwell_time(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 6d8d6dd7943f..b3a314ba48c7 100644 --- a/trunk/drivers/net/wireless/iwlwifi/dvm/ucode.c +++ b/trunk/drivers/net/wireless/iwlwifi/dvm/ucode.c @@ -226,50 +226,13 @@ int iwl_send_bt_env(struct iwl_priv *priv, u8 action, u8 type) return ret; } -static const u8 iwlagn_default_queue_to_tx_fifo[] = { - IWL_TX_FIFO_VO, - IWL_TX_FIFO_VI, - IWL_TX_FIFO_BE, - IWL_TX_FIFO_BK, -}; - -static const u8 iwlagn_ipan_queue_to_tx_fifo[] = { - IWL_TX_FIFO_VO, - IWL_TX_FIFO_VI, - IWL_TX_FIFO_BE, - IWL_TX_FIFO_BK, - IWL_TX_FIFO_BK_IPAN, - IWL_TX_FIFO_BE_IPAN, - IWL_TX_FIFO_VI_IPAN, - IWL_TX_FIFO_VO_IPAN, - IWL_TX_FIFO_BE_IPAN, - IWL_TX_FIFO_UNUSED, - IWL_TX_FIFO_AUX, -}; static int iwl_alive_notify(struct iwl_priv *priv) { - const u8 *queue_to_txf; - u8 n_queues; int ret; - int i; iwl_trans_fw_alive(priv->trans); - if (priv->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_PAN && - priv->eeprom_data->sku & EEPROM_SKU_CAP_IPAN_ENABLE) { - n_queues = ARRAY_SIZE(iwlagn_ipan_queue_to_tx_fifo); - queue_to_txf = iwlagn_ipan_queue_to_tx_fifo; - } else { - n_queues = ARRAY_SIZE(iwlagn_default_queue_to_tx_fifo); - queue_to_txf = iwlagn_default_queue_to_tx_fifo; - } - - for (i = 0; i < n_queues; i++) - if (queue_to_txf[i] != IWL_TX_FIFO_UNUSED) - iwl_trans_ac_txq_enable(priv->trans, i, - queue_to_txf[i]); - priv->passive_no_rx = false; priv->transport_queue_stop = 0; diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-debug.c b/trunk/drivers/net/wireless/iwlwifi/iwl-debug.c index 87535a67de76..0f8fcd1d4fe2 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-debug.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-debug.c @@ -61,9 +61,6 @@ * *****************************************************************************/ -#define DEBUG - -#include #include #include #include "iwl-debug.h" @@ -127,7 +124,7 @@ void __iwl_dbg(struct device *dev, #ifdef CONFIG_IWLWIFI_DEBUG if (iwl_have_debug_level(level) && (!limit || net_ratelimit())) - dev_dbg(dev, "%c %s %pV", in_interrupt() ? 'I' : 'U', + dev_err(dev, "%c %s %pV", in_interrupt() ? 'I' : 'U', function, &vaf); #endif trace_iwlwifi_dbg(level, in_interrupt(), function, &vaf); diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-devtrace.h b/trunk/drivers/net/wireless/iwlwifi/iwl-devtrace.h index 06ca505bb2cc..65364793021f 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-devtrace.h +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-devtrace.h @@ -176,7 +176,7 @@ TRACE_EVENT(iwlwifi_dev_ucode_wrap_event, #undef TRACE_SYSTEM #define TRACE_SYSTEM iwlwifi_msg -#define MAX_MSG_LEN 110 +#define MAX_MSG_LEN 100 DECLARE_EVENT_CLASS(iwlwifi_msg_event, TP_PROTO(struct va_format *vaf), @@ -189,7 +189,7 @@ DECLARE_EVENT_CLASS(iwlwifi_msg_event, MAX_MSG_LEN, vaf->fmt, *vaf->va) >= MAX_MSG_LEN); ), - TP_printk("%s", __get_str(msg)) + TP_printk("%s", (char *)__get_dynamic_array(msg)) ); DEFINE_EVENT(iwlwifi_msg_event, iwlwifi_err, diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-drv.c b/trunk/drivers/net/wireless/iwlwifi/iwl-drv.c index cc41cfaedfbd..a175997e7829 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-drv.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-drv.c @@ -1013,7 +1013,6 @@ struct iwl_mod_params iwlwifi_mod_params = { .power_level = IWL_POWER_INDEX_1, .bt_ch_announce = true, .auto_agg = true, - .wd_disable = true, /* the rest are 0 by default */ }; EXPORT_SYMBOL_GPL(iwlwifi_mod_params); diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-trans.h b/trunk/drivers/net/wireless/iwlwifi/iwl-trans.h index 867d8e194da4..00efde8e5536 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-trans.h @@ -290,17 +290,16 @@ static inline struct page *rxb_steal_page(struct iwl_rx_cmd_buffer *r) * currently supports */ #define IWL_MAX_HW_QUEUES 32 -#define IWL_INVALID_STATION 255 -#define IWL_MAX_TID_COUNT 8 -#define IWL_FRAME_LIMIT 64 /** * struct iwl_trans_config - transport configuration * * @op_mode: pointer to the upper layer. + * @queue_to_fifo: queue to FIFO mapping to set up by + * default + * @n_queue_to_fifo: number of queues to set up * @cmd_queue: the index of the command queue. * Must be set before start_fw. - * @cmd_fifo: the fifo for host commands * @no_reclaim_cmds: Some devices erroneously don't set the * SEQ_RX_FRAME bit on some notifications, this is the * list of such notifications to filter. Max length is @@ -315,9 +314,10 @@ static inline struct page *rxb_steal_page(struct iwl_rx_cmd_buffer *r) */ struct iwl_trans_config { struct iwl_op_mode *op_mode; + const u8 *queue_to_fifo; + u8 n_queue_to_fifo; u8 cmd_queue; - u8 cmd_fifo; const u8 *no_reclaim_cmds; int n_no_reclaim_cmds; @@ -355,9 +355,9 @@ struct iwl_trans; * Must be atomic * @reclaim: free packet until ssn. Returns a list of freed packets. * Must be atomic - * @txq_enable: setup a queue. To setup an AC queue, use the - * iwl_trans_ac_txq_enable wrapper. fw_alive must have been called before - * this one. The op_mode must not configure the HCMD queue. May sleep. + * @txq_enable: setup a tx queue for AMPDU - will be called once the HW is + * ready and a successful ADDBA response has been received. + * May sleep * @txq_disable: de-configure a Tx queue to send AMPDUs * Must be atomic * @wait_tx_queue_empty: wait until all tx queues are empty @@ -497,9 +497,9 @@ static inline void iwl_trans_fw_alive(struct iwl_trans *trans) { might_sleep(); - trans->state = IWL_TRANS_FW_ALIVE; - trans->ops->fw_alive(trans); + + trans->state = IWL_TRANS_FW_ALIVE; } static inline int iwl_trans_start_fw(struct iwl_trans *trans, @@ -593,13 +593,6 @@ static inline void iwl_trans_txq_enable(struct iwl_trans *trans, int queue, frame_limit, ssn); } -static inline void iwl_trans_ac_txq_enable(struct iwl_trans *trans, int queue, - int fifo) -{ - iwl_trans_txq_enable(trans, queue, fifo, IWL_INVALID_STATION, - IWL_MAX_TID_COUNT, IWL_FRAME_LIMIT, 0); -} - static inline int iwl_trans_wait_tx_queue_empty(struct iwl_trans *trans) { WARN_ONCE(trans->state != IWL_TRANS_FW_ALIVE, diff --git a/trunk/drivers/net/wireless/iwlwifi/pcie/internal.h b/trunk/drivers/net/wireless/iwlwifi/pcie/internal.h index d9694c58208c..5024fb662bf6 100644 --- a/trunk/drivers/net/wireless/iwlwifi/pcie/internal.h +++ b/trunk/drivers/net/wireless/iwlwifi/pcie/internal.h @@ -269,9 +269,10 @@ struct iwl_trans_pcie { wait_queue_head_t ucode_write_waitq; unsigned long status; u8 cmd_queue; - u8 cmd_fifo; u8 n_no_reclaim_cmds; u8 no_reclaim_cmds[MAX_NO_RECLAIM_CMDS]; + u8 setup_q_to_fifo[IWL_MAX_HW_QUEUES]; + u8 n_q_to_fifo; bool rx_buf_size_8k; u32 rx_page_order; diff --git a/trunk/drivers/net/wireless/iwlwifi/pcie/rx.c b/trunk/drivers/net/wireless/iwlwifi/pcie/rx.c index 39a6ca1f009c..be143eb4aa4f 100644 --- a/trunk/drivers/net/wireless/iwlwifi/pcie/rx.c +++ b/trunk/drivers/net/wireless/iwlwifi/pcie/rx.c @@ -879,6 +879,9 @@ static irqreturn_t iwl_isr(int irq, void *data) lockdep_assert_held(&trans_pcie->irq_lock); + if (!trans) + return IRQ_NONE; + trace_iwlwifi_dev_irq(trans->dev); /* Disable (but don't clear!) interrupts here to avoid diff --git a/trunk/drivers/net/wireless/iwlwifi/pcie/trans.c b/trunk/drivers/net/wireless/iwlwifi/pcie/trans.c index 09795afccb23..d1950838f17f 100644 --- a/trunk/drivers/net/wireless/iwlwifi/pcie/trans.c +++ b/trunk/drivers/net/wireless/iwlwifi/pcie/trans.c @@ -1059,7 +1059,7 @@ static void iwl_tx_start(struct iwl_trans *trans) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); u32 a; - int chan; + int i, chan; u32 reg_val; /* make sure all queue are not stopped/used */ @@ -1091,8 +1091,12 @@ static void iwl_tx_start(struct iwl_trans *trans) */ iwl_write_prph(trans, SCD_CHAINEXT_EN, 0); - iwl_trans_ac_txq_enable(trans, trans_pcie->cmd_queue, - trans_pcie->cmd_fifo); + for (i = 0; i < trans_pcie->n_q_to_fifo; i++) { + int fifo = trans_pcie->setup_q_to_fifo[i]; + + iwl_trans_pcie_txq_enable(trans, i, fifo, IWL_INVALID_STATION, + IWL_TID_NON_QOS, SCD_FRAME_LIMIT, 0); + } /* Activate all Tx DMA/FIFO channels */ iwl_trans_txq_set_sched(trans, IWL_MASK(0, 7)); @@ -1141,7 +1145,7 @@ static int iwl_trans_tx_stop(struct iwl_trans *trans) FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(ch), 1000); if (ret < 0) IWL_ERR(trans, - "Failing on timeout while stopping DMA channel %d [0x%08x]\n", + "Failing on timeout while stopping DMA channel %d [0x%08x]", ch, iwl_read_direct32(trans, FH_TSSR_TX_STATUS_REG)); @@ -1149,8 +1153,7 @@ static int iwl_trans_tx_stop(struct iwl_trans *trans) spin_unlock_irqrestore(&trans_pcie->irq_lock, flags); if (!trans_pcie->txq) { - IWL_WARN(trans, - "Stopping tx queues that aren't allocated...\n"); + IWL_WARN(trans, "Stopping tx queues that aren't allocated..."); return 0; } @@ -1427,7 +1430,7 @@ static int iwl_trans_pcie_start_hw(struct iwl_trans *trans) err = iwl_prepare_card_hw(trans); if (err) { - IWL_ERR(trans, "Error while preparing HW: %d\n", err); + IWL_ERR(trans, "Error while preparing HW: %d", err); goto err_free_irq; } @@ -1525,7 +1528,6 @@ static void iwl_trans_pcie_configure(struct iwl_trans *trans, struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); trans_pcie->cmd_queue = trans_cfg->cmd_queue; - trans_pcie->cmd_fifo = trans_cfg->cmd_fifo; if (WARN_ON(trans_cfg->n_no_reclaim_cmds > MAX_NO_RECLAIM_CMDS)) trans_pcie->n_no_reclaim_cmds = 0; else @@ -1534,6 +1536,17 @@ static void iwl_trans_pcie_configure(struct iwl_trans *trans, memcpy(trans_pcie->no_reclaim_cmds, trans_cfg->no_reclaim_cmds, trans_pcie->n_no_reclaim_cmds * sizeof(u8)); + trans_pcie->n_q_to_fifo = trans_cfg->n_queue_to_fifo; + + if (WARN_ON(trans_pcie->n_q_to_fifo > IWL_MAX_HW_QUEUES)) + trans_pcie->n_q_to_fifo = IWL_MAX_HW_QUEUES; + + /* at least the command queue must be mapped */ + WARN_ON(!trans_pcie->n_q_to_fifo); + + memcpy(trans_pcie->setup_q_to_fifo, trans_cfg->queue_to_fifo, + trans_pcie->n_q_to_fifo * sizeof(u8)); + trans_pcie->rx_buf_size_8k = trans_cfg->rx_buf_size_8k; if (trans_pcie->rx_buf_size_8k) trans_pcie->rx_page_order = get_order(8 * 1024); @@ -2128,14 +2141,13 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, err = pci_request_regions(pdev, DRV_NAME); if (err) { - dev_printk(KERN_ERR, &pdev->dev, - "pci_request_regions failed\n"); + dev_printk(KERN_ERR, &pdev->dev, "pci_request_regions failed"); goto out_pci_disable_device; } trans_pcie->hw_base = pci_ioremap_bar(pdev, 0); if (!trans_pcie->hw_base) { - dev_printk(KERN_ERR, &pdev->dev, "pci_ioremap_bar failed\n"); + dev_printk(KERN_ERR, &pdev->dev, "pci_ioremap_bar failed"); err = -ENODEV; goto out_pci_release_regions; } @@ -2156,7 +2168,7 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, err = pci_enable_msi(pdev); if (err) dev_printk(KERN_ERR, &pdev->dev, - "pci_enable_msi failed(0X%x)\n", err); + "pci_enable_msi failed(0X%x)", err); trans->dev = &pdev->dev; trans_pcie->irq = pdev->irq; diff --git a/trunk/drivers/net/wireless/iwmc3200wifi/Kconfig b/trunk/drivers/net/wireless/iwmc3200wifi/Kconfig new file mode 100644 index 000000000000..7107ce53d4d4 --- /dev/null +++ b/trunk/drivers/net/wireless/iwmc3200wifi/Kconfig @@ -0,0 +1,39 @@ +config IWM + tristate "Intel Wireless Multicomm 3200 WiFi driver (EXPERIMENTAL)" + depends on MMC && EXPERIMENTAL + depends on CFG80211 + select FW_LOADER + select IWMC3200TOP + help + The Intel Wireless Multicomm 3200 hardware is a combo + card with GPS, Bluetooth, WiMax and 802.11 radios. It + runs over SDIO and is typically found on Moorestown + based platform. This driver takes care of the 802.11 + part, which is a fullmac one. + + If you choose to build it as a module, it'll be called + iwmc3200wifi.ko. + +config IWM_DEBUG + bool "Enable full debugging output in iwmc3200wifi" + depends on IWM && DEBUG_FS + help + This option will enable debug tracing and setting for iwm + + You can set the debug level and module through debugfs. By + default all modules are set to the IWL_DL_ERR level. + To see the list of debug modules and levels, see iwm/debug.h + + For example, if you want the full MLME debug output: + echo 0xff > /sys/kernel/debug/iwm/phyN/debug/mlme + + Or, if you want the full debug, for all modules: + echo 0xff > /sys/kernel/debug/iwm/phyN/debug/level + echo 0xff > /sys/kernel/debug/iwm/phyN/debug/modules + +config IWM_TRACING + bool "Enable event tracing for iwmc3200wifi" + depends on IWM && EVENT_TRACING + help + Say Y here to trace all the commands and responses between + the driver and firmware (including TX/RX frames) with ftrace. diff --git a/trunk/drivers/net/wireless/iwmc3200wifi/Makefile b/trunk/drivers/net/wireless/iwmc3200wifi/Makefile new file mode 100644 index 000000000000..cdc7e07ba113 --- /dev/null +++ b/trunk/drivers/net/wireless/iwmc3200wifi/Makefile @@ -0,0 +1,10 @@ +obj-$(CONFIG_IWM) := iwmc3200wifi.o +iwmc3200wifi-objs += main.o netdev.o rx.o tx.o sdio.o hal.o fw.o +iwmc3200wifi-objs += commands.o cfg80211.o eeprom.o + +iwmc3200wifi-$(CONFIG_IWM_DEBUG) += debugfs.o +iwmc3200wifi-$(CONFIG_IWM_TRACING) += trace.o + +CFLAGS_trace.o := -I$(src) + +ccflags-y += -D__CHECK_ENDIAN__ diff --git a/trunk/drivers/net/wireless/iwmc3200wifi/bus.h b/trunk/drivers/net/wireless/iwmc3200wifi/bus.h new file mode 100644 index 000000000000..62edd5888a7b --- /dev/null +++ b/trunk/drivers/net/wireless/iwmc3200wifi/bus.h @@ -0,0 +1,57 @@ +/* + * Intel Wireless Multicomm 3200 WiFi driver + * + * Copyright (C) 2009 Intel Corporation + * Samuel Ortiz + * Zhu Yi + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + * + */ + +#ifndef __IWM_BUS_H__ +#define __IWM_BUS_H__ + +#include "iwm.h" + +struct iwm_if_ops { + int (*enable)(struct iwm_priv *iwm); + int (*disable)(struct iwm_priv *iwm); + int (*send_chunk)(struct iwm_priv *iwm, u8* buf, int count); + + void (*debugfs_init)(struct iwm_priv *iwm, struct dentry *parent_dir); + void (*debugfs_exit)(struct iwm_priv *iwm); + + const char *umac_name; + const char *calib_lmac_name; + const char *lmac_name; +}; + +static inline int iwm_bus_send_chunk(struct iwm_priv *iwm, u8 *buf, int count) +{ + return iwm->bus_ops->send_chunk(iwm, buf, count); +} + +static inline int iwm_bus_enable(struct iwm_priv *iwm) +{ + return iwm->bus_ops->enable(iwm); +} + +static inline int iwm_bus_disable(struct iwm_priv *iwm) +{ + return iwm->bus_ops->disable(iwm); +} + +#endif diff --git a/trunk/drivers/net/wireless/iwmc3200wifi/cfg80211.c b/trunk/drivers/net/wireless/iwmc3200wifi/cfg80211.c new file mode 100644 index 000000000000..48e8218fd23b --- /dev/null +++ b/trunk/drivers/net/wireless/iwmc3200wifi/cfg80211.c @@ -0,0 +1,882 @@ +/* + * Intel Wireless Multicomm 3200 WiFi driver + * + * Copyright (C) 2009 Intel Corporation + * Samuel Ortiz + * Zhu Yi + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "iwm.h" +#include "commands.h" +#include "cfg80211.h" +#include "debug.h" + +#define RATETAB_ENT(_rate, _rateid, _flags) \ + { \ + .bitrate = (_rate), \ + .hw_value = (_rateid), \ + .flags = (_flags), \ + } + +#define CHAN2G(_channel, _freq, _flags) { \ + .band = IEEE80211_BAND_2GHZ, \ + .center_freq = (_freq), \ + .hw_value = (_channel), \ + .flags = (_flags), \ + .max_antenna_gain = 0, \ + .max_power = 30, \ +} + +#define CHAN5G(_channel, _flags) { \ + .band = IEEE80211_BAND_5GHZ, \ + .center_freq = 5000 + (5 * (_channel)), \ + .hw_value = (_channel), \ + .flags = (_flags), \ + .max_antenna_gain = 0, \ + .max_power = 30, \ +} + +static struct ieee80211_rate iwm_rates[] = { + RATETAB_ENT(10, 0x1, 0), + RATETAB_ENT(20, 0x2, 0), + RATETAB_ENT(55, 0x4, 0), + RATETAB_ENT(110, 0x8, 0), + RATETAB_ENT(60, 0x10, 0), + RATETAB_ENT(90, 0x20, 0), + RATETAB_ENT(120, 0x40, 0), + RATETAB_ENT(180, 0x80, 0), + RATETAB_ENT(240, 0x100, 0), + RATETAB_ENT(360, 0x200, 0), + RATETAB_ENT(480, 0x400, 0), + RATETAB_ENT(540, 0x800, 0), +}; + +#define iwm_a_rates (iwm_rates + 4) +#define iwm_a_rates_size 8 +#define iwm_g_rates (iwm_rates + 0) +#define iwm_g_rates_size 12 + +static struct ieee80211_channel iwm_2ghz_channels[] = { + CHAN2G(1, 2412, 0), + CHAN2G(2, 2417, 0), + CHAN2G(3, 2422, 0), + CHAN2G(4, 2427, 0), + CHAN2G(5, 2432, 0), + CHAN2G(6, 2437, 0), + CHAN2G(7, 2442, 0), + CHAN2G(8, 2447, 0), + CHAN2G(9, 2452, 0), + CHAN2G(10, 2457, 0), + CHAN2G(11, 2462, 0), + CHAN2G(12, 2467, 0), + CHAN2G(13, 2472, 0), + CHAN2G(14, 2484, 0), +}; + +static struct ieee80211_channel iwm_5ghz_a_channels[] = { + CHAN5G(34, 0), CHAN5G(36, 0), + CHAN5G(38, 0), CHAN5G(40, 0), + CHAN5G(42, 0), CHAN5G(44, 0), + CHAN5G(46, 0), CHAN5G(48, 0), + CHAN5G(52, 0), CHAN5G(56, 0), + CHAN5G(60, 0), CHAN5G(64, 0), + CHAN5G(100, 0), CHAN5G(104, 0), + CHAN5G(108, 0), CHAN5G(112, 0), + CHAN5G(116, 0), CHAN5G(120, 0), + CHAN5G(124, 0), CHAN5G(128, 0), + CHAN5G(132, 0), CHAN5G(136, 0), + CHAN5G(140, 0), CHAN5G(149, 0), + CHAN5G(153, 0), CHAN5G(157, 0), + CHAN5G(161, 0), CHAN5G(165, 0), + CHAN5G(184, 0), CHAN5G(188, 0), + CHAN5G(192, 0), CHAN5G(196, 0), + CHAN5G(200, 0), CHAN5G(204, 0), + CHAN5G(208, 0), CHAN5G(212, 0), + CHAN5G(216, 0), +}; + +static struct ieee80211_supported_band iwm_band_2ghz = { + .channels = iwm_2ghz_channels, + .n_channels = ARRAY_SIZE(iwm_2ghz_channels), + .bitrates = iwm_g_rates, + .n_bitrates = iwm_g_rates_size, +}; + +static struct ieee80211_supported_band iwm_band_5ghz = { + .channels = iwm_5ghz_a_channels, + .n_channels = ARRAY_SIZE(iwm_5ghz_a_channels), + .bitrates = iwm_a_rates, + .n_bitrates = iwm_a_rates_size, +}; + +static int iwm_key_init(struct iwm_key *key, u8 key_index, + const u8 *mac_addr, struct key_params *params) +{ + key->hdr.key_idx = key_index; + if (!mac_addr || is_broadcast_ether_addr(mac_addr)) { + key->hdr.multicast = 1; + memset(key->hdr.mac, 0xff, ETH_ALEN); + } else { + key->hdr.multicast = 0; + memcpy(key->hdr.mac, mac_addr, ETH_ALEN); + } + + if (params) { + if (params->key_len > WLAN_MAX_KEY_LEN || + params->seq_len > IW_ENCODE_SEQ_MAX_SIZE) + return -EINVAL; + + key->cipher = params->cipher; + key->key_len = params->key_len; + key->seq_len = params->seq_len; + memcpy(key->key, params->key, key->key_len); + memcpy(key->seq, params->seq, key->seq_len); + } + + return 0; +} + +static int iwm_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev, + u8 key_index, bool pairwise, const u8 *mac_addr, + struct key_params *params) +{ + struct iwm_priv *iwm = ndev_to_iwm(ndev); + struct iwm_key *key; + int ret; + + IWM_DBG_WEXT(iwm, DBG, "Adding key for %pM\n", mac_addr); + + if (key_index >= IWM_NUM_KEYS) + return -ENOENT; + + key = &iwm->keys[key_index]; + memset(key, 0, sizeof(struct iwm_key)); + ret = iwm_key_init(key, key_index, mac_addr, params); + if (ret < 0) { + IWM_ERR(iwm, "Invalid key_params\n"); + return ret; + } + + return iwm_set_key(iwm, 0, key); +} + +static int iwm_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev, + u8 key_index, bool pairwise, const u8 *mac_addr, + void *cookie, + void (*callback)(void *cookie, + struct key_params*)) +{ + struct iwm_priv *iwm = ndev_to_iwm(ndev); + struct iwm_key *key; + struct key_params params; + + IWM_DBG_WEXT(iwm, DBG, "Getting key %d\n", key_index); + + if (key_index >= IWM_NUM_KEYS) + return -ENOENT; + + memset(¶ms, 0, sizeof(params)); + + key = &iwm->keys[key_index]; + params.cipher = key->cipher; + params.key_len = key->key_len; + params.seq_len = key->seq_len; + params.seq = key->seq; + params.key = key->key; + + callback(cookie, ¶ms); + + return key->key_len ? 0 : -ENOENT; +} + + +static int iwm_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev, + u8 key_index, bool pairwise, const u8 *mac_addr) +{ + struct iwm_priv *iwm = ndev_to_iwm(ndev); + struct iwm_key *key; + + if (key_index >= IWM_NUM_KEYS) + return -ENOENT; + + key = &iwm->keys[key_index]; + if (!iwm->keys[key_index].key_len) { + IWM_DBG_WEXT(iwm, DBG, "Key %d not used\n", key_index); + return 0; + } + + if (key_index == iwm->default_key) + iwm->default_key = -1; + + return iwm_set_key(iwm, 1, key); +} + +static int iwm_cfg80211_set_default_key(struct wiphy *wiphy, + struct net_device *ndev, + u8 key_index, bool unicast, + bool multicast) +{ + struct iwm_priv *iwm = ndev_to_iwm(ndev); + + IWM_DBG_WEXT(iwm, DBG, "Default key index is: %d\n", key_index); + + if (key_index >= IWM_NUM_KEYS) + return -ENOENT; + + if (!iwm->keys[key_index].key_len) { + IWM_ERR(iwm, "Key %d not used\n", key_index); + return -EINVAL; + } + + iwm->default_key = key_index; + + return iwm_set_tx_key(iwm, key_index); +} + +static int iwm_cfg80211_get_station(struct wiphy *wiphy, + struct net_device *ndev, + u8 *mac, struct station_info *sinfo) +{ + struct iwm_priv *iwm = ndev_to_iwm(ndev); + + if (memcmp(mac, iwm->bssid, ETH_ALEN)) + return -ENOENT; + + sinfo->filled |= STATION_INFO_TX_BITRATE; + sinfo->txrate.legacy = iwm->rate * 10; + + if (test_bit(IWM_STATUS_ASSOCIATED, &iwm->status)) { + sinfo->filled |= STATION_INFO_SIGNAL; + sinfo->signal = iwm->wstats.qual.level; + } + + return 0; +} + + +int iwm_cfg80211_inform_bss(struct iwm_priv *iwm) +{ + struct wiphy *wiphy = iwm_to_wiphy(iwm); + struct iwm_bss_info *bss; + struct iwm_umac_notif_bss_info *umac_bss; + struct ieee80211_mgmt *mgmt; + struct ieee80211_channel *channel; + struct ieee80211_supported_band *band; + s32 signal; + int freq; + + list_for_each_entry(bss, &iwm->bss_list, node) { + umac_bss = bss->bss; + mgmt = (struct ieee80211_mgmt *)(umac_bss->frame_buf); + + if (umac_bss->band == UMAC_BAND_2GHZ) + band = wiphy->bands[IEEE80211_BAND_2GHZ]; + else if (umac_bss->band == UMAC_BAND_5GHZ) + band = wiphy->bands[IEEE80211_BAND_5GHZ]; + else { + IWM_ERR(iwm, "Invalid band: %d\n", umac_bss->band); + return -EINVAL; + } + + freq = ieee80211_channel_to_frequency(umac_bss->channel, + band->band); + channel = ieee80211_get_channel(wiphy, freq); + signal = umac_bss->rssi * 100; + + if (!cfg80211_inform_bss_frame(wiphy, channel, mgmt, + le16_to_cpu(umac_bss->frame_len), + signal, GFP_KERNEL)) + return -EINVAL; + } + + return 0; +} + +static int iwm_cfg80211_change_iface(struct wiphy *wiphy, + struct net_device *ndev, + enum nl80211_iftype type, u32 *flags, + struct vif_params *params) +{ + struct wireless_dev *wdev; + struct iwm_priv *iwm; + u32 old_mode; + + wdev = ndev->ieee80211_ptr; + iwm = ndev_to_iwm(ndev); + old_mode = iwm->conf.mode; + + switch (type) { + case NL80211_IFTYPE_STATION: + iwm->conf.mode = UMAC_MODE_BSS; + break; + case NL80211_IFTYPE_ADHOC: + iwm->conf.mode = UMAC_MODE_IBSS; + break; + default: + return -EOPNOTSUPP; + } + + wdev->iftype = type; + + if ((old_mode == iwm->conf.mode) || !iwm->umac_profile) + return 0; + + iwm->umac_profile->mode = cpu_to_le32(iwm->conf.mode); + + if (iwm->umac_profile_active) + iwm_invalidate_mlme_profile(iwm); + + return 0; +} + +static int iwm_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, + struct cfg80211_scan_request *request) +{ + struct iwm_priv *iwm = ndev_to_iwm(ndev); + int ret; + + if (!test_bit(IWM_STATUS_READY, &iwm->status)) { + IWM_ERR(iwm, "Scan while device is not ready\n"); + return -EIO; + } + + if (test_bit(IWM_STATUS_SCANNING, &iwm->status)) { + IWM_ERR(iwm, "Scanning already\n"); + return -EAGAIN; + } + + if (test_bit(IWM_STATUS_SCAN_ABORTING, &iwm->status)) { + IWM_ERR(iwm, "Scanning being aborted\n"); + return -EAGAIN; + } + + set_bit(IWM_STATUS_SCANNING, &iwm->status); + + ret = iwm_scan_ssids(iwm, request->ssids, request->n_ssids); + if (ret) { + clear_bit(IWM_STATUS_SCANNING, &iwm->status); + return ret; + } + + iwm->scan_request = request; + return 0; +} + +static int iwm_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed) +{ + struct iwm_priv *iwm = wiphy_to_iwm(wiphy); + + if (changed & WIPHY_PARAM_RTS_THRESHOLD && + (iwm->conf.rts_threshold != wiphy->rts_threshold)) { + int ret; + + iwm->conf.rts_threshold = wiphy->rts_threshold; + + ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX, + CFG_RTS_THRESHOLD, + iwm->conf.rts_threshold); + if (ret < 0) + return ret; + } + + if (changed & WIPHY_PARAM_FRAG_THRESHOLD && + (iwm->conf.frag_threshold != wiphy->frag_threshold)) { + int ret; + + iwm->conf.frag_threshold = wiphy->frag_threshold; + + ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_FA_CFG_FIX, + CFG_FRAG_THRESHOLD, + iwm->conf.frag_threshold); + if (ret < 0) + return ret; + } + + return 0; +} + +static int iwm_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev, + struct cfg80211_ibss_params *params) +{ + struct iwm_priv *iwm = wiphy_to_iwm(wiphy); + struct ieee80211_channel *chan = params->channel; + + if (!test_bit(IWM_STATUS_READY, &iwm->status)) + return -EIO; + + /* UMAC doesn't support creating or joining an IBSS network + * with specified bssid. */ + if (params->bssid) + return -EOPNOTSUPP; + + iwm->channel = ieee80211_frequency_to_channel(chan->center_freq); + iwm->umac_profile->ibss.band = chan->band; + iwm->umac_profile->ibss.channel = iwm->channel; + iwm->umac_profile->ssid.ssid_len = params->ssid_len; + memcpy(iwm->umac_profile->ssid.ssid, params->ssid, params->ssid_len); + + return iwm_send_mlme_profile(iwm); +} + +static int iwm_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev) +{ + struct iwm_priv *iwm = wiphy_to_iwm(wiphy); + + if (iwm->umac_profile_active) + return iwm_invalidate_mlme_profile(iwm); + + return 0; +} + +static int iwm_set_auth_type(struct iwm_priv *iwm, + enum nl80211_auth_type sme_auth_type) +{ + u8 *auth_type = &iwm->umac_profile->sec.auth_type; + + switch (sme_auth_type) { + case NL80211_AUTHTYPE_AUTOMATIC: + case NL80211_AUTHTYPE_OPEN_SYSTEM: + IWM_DBG_WEXT(iwm, DBG, "OPEN auth\n"); + *auth_type = UMAC_AUTH_TYPE_OPEN; + break; + case NL80211_AUTHTYPE_SHARED_KEY: + if (iwm->umac_profile->sec.flags & + (UMAC_SEC_FLG_WPA_ON_MSK | UMAC_SEC_FLG_RSNA_ON_MSK)) { + IWM_DBG_WEXT(iwm, DBG, "WPA auth alg\n"); + *auth_type = UMAC_AUTH_TYPE_RSNA_PSK; + } else { + IWM_DBG_WEXT(iwm, DBG, "WEP shared key auth alg\n"); + *auth_type = UMAC_AUTH_TYPE_LEGACY_PSK; + } + + break; + default: + IWM_ERR(iwm, "Unsupported auth alg: 0x%x\n", sme_auth_type); + return -ENOTSUPP; + } + + return 0; +} + +static int iwm_set_wpa_version(struct iwm_priv *iwm, u32 wpa_version) +{ + IWM_DBG_WEXT(iwm, DBG, "wpa_version: %d\n", wpa_version); + + if (!wpa_version) { + iwm->umac_profile->sec.flags = UMAC_SEC_FLG_LEGACY_PROFILE; + return 0; + } + + if (wpa_version & NL80211_WPA_VERSION_1) + iwm->umac_profile->sec.flags = UMAC_SEC_FLG_WPA_ON_MSK; + + if (wpa_version & NL80211_WPA_VERSION_2) + iwm->umac_profile->sec.flags = UMAC_SEC_FLG_RSNA_ON_MSK; + + return 0; +} + +static int iwm_set_cipher(struct iwm_priv *iwm, u32 cipher, bool ucast) +{ + u8 *profile_cipher = ucast ? &iwm->umac_profile->sec.ucast_cipher : + &iwm->umac_profile->sec.mcast_cipher; + + if (!cipher) { + *profile_cipher = UMAC_CIPHER_TYPE_NONE; + return 0; + } + + IWM_DBG_WEXT(iwm, DBG, "%ccast cipher is 0x%x\n", ucast ? 'u' : 'm', + cipher); + + switch (cipher) { + case IW_AUTH_CIPHER_NONE: + *profile_cipher = UMAC_CIPHER_TYPE_NONE; + break; + case WLAN_CIPHER_SUITE_WEP40: + *profile_cipher = UMAC_CIPHER_TYPE_WEP_40; + break; + case WLAN_CIPHER_SUITE_WEP104: + *profile_cipher = UMAC_CIPHER_TYPE_WEP_104; + break; + case WLAN_CIPHER_SUITE_TKIP: + *profile_cipher = UMAC_CIPHER_TYPE_TKIP; + break; + case WLAN_CIPHER_SUITE_CCMP: + *profile_cipher = UMAC_CIPHER_TYPE_CCMP; + break; + default: + IWM_ERR(iwm, "Unsupported cipher: 0x%x\n", cipher); + return -ENOTSUPP; + } + + return 0; +} + +static int iwm_set_key_mgt(struct iwm_priv *iwm, u32 key_mgt) +{ + u8 *auth_type = &iwm->umac_profile->sec.auth_type; + + IWM_DBG_WEXT(iwm, DBG, "key_mgt: 0x%x\n", key_mgt); + + if (key_mgt == WLAN_AKM_SUITE_8021X) + *auth_type = UMAC_AUTH_TYPE_8021X; + else if (key_mgt == WLAN_AKM_SUITE_PSK) { + if (iwm->umac_profile->sec.flags & + (UMAC_SEC_FLG_WPA_ON_MSK | UMAC_SEC_FLG_RSNA_ON_MSK)) + *auth_type = UMAC_AUTH_TYPE_RSNA_PSK; + else + *auth_type = UMAC_AUTH_TYPE_LEGACY_PSK; + } else { + IWM_ERR(iwm, "Invalid key mgt: 0x%x\n", key_mgt); + return -EINVAL; + } + + return 0; +} + + +static int iwm_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, + struct cfg80211_connect_params *sme) +{ + struct iwm_priv *iwm = wiphy_to_iwm(wiphy); + struct ieee80211_channel *chan = sme->channel; + struct key_params key_param; + int ret; + + if (!test_bit(IWM_STATUS_READY, &iwm->status)) + return -EIO; + + if (!sme->ssid) + return -EINVAL; + + if (iwm->umac_profile_active) { + ret = iwm_invalidate_mlme_profile(iwm); + if (ret) { + IWM_ERR(iwm, "Couldn't invalidate profile\n"); + return ret; + } + } + + if (chan) + iwm->channel = + ieee80211_frequency_to_channel(chan->center_freq); + + iwm->umac_profile->ssid.ssid_len = sme->ssid_len; + memcpy(iwm->umac_profile->ssid.ssid, sme->ssid, sme->ssid_len); + + if (sme->bssid) { + IWM_DBG_WEXT(iwm, DBG, "BSSID: %pM\n", sme->bssid); + memcpy(&iwm->umac_profile->bssid[0], sme->bssid, ETH_ALEN); + iwm->umac_profile->bss_num = 1; + } else { + memset(&iwm->umac_profile->bssid[0], 0, ETH_ALEN); + iwm->umac_profile->bss_num = 0; + } + + ret = iwm_set_wpa_version(iwm, sme->crypto.wpa_versions); + if (ret < 0) + return ret; + + ret = iwm_set_auth_type(iwm, sme->auth_type); + if (ret < 0) + return ret; + + if (sme->crypto.n_ciphers_pairwise) { + ret = iwm_set_cipher(iwm, sme->crypto.ciphers_pairwise[0], + true); + if (ret < 0) + return ret; + } + + ret = iwm_set_cipher(iwm, sme->crypto.cipher_group, false); + if (ret < 0) + return ret; + + if (sme->crypto.n_akm_suites) { + ret = iwm_set_key_mgt(iwm, sme->crypto.akm_suites[0]); + if (ret < 0) + return ret; + } + + /* + * We save the WEP key in case we want to do shared authentication. + * We have to do it so because UMAC will assert whenever it gets a + * key before a profile. + */ + if (sme->key) { + key_param.key = kmemdup(sme->key, sme->key_len, GFP_KERNEL); + if (key_param.key == NULL) + return -ENOMEM; + key_param.key_len = sme->key_len; + key_param.seq_len = 0; + key_param.cipher = sme->crypto.ciphers_pairwise[0]; + + ret = iwm_key_init(&iwm->keys[sme->key_idx], sme->key_idx, + NULL, &key_param); + kfree(key_param.key); + if (ret < 0) { + IWM_ERR(iwm, "Invalid key_params\n"); + return ret; + } + + iwm->default_key = sme->key_idx; + } + + /* WPA and open AUTH type from wpa_s means WPS (a.k.a. WSC) */ + if ((iwm->umac_profile->sec.flags & + (UMAC_SEC_FLG_WPA_ON_MSK | UMAC_SEC_FLG_RSNA_ON_MSK)) && + iwm->umac_profile->sec.auth_type == UMAC_AUTH_TYPE_OPEN) { + iwm->umac_profile->sec.flags = UMAC_SEC_FLG_WSC_ON_MSK; + } + + ret = iwm_send_mlme_profile(iwm); + + if (iwm->umac_profile->sec.auth_type != UMAC_AUTH_TYPE_LEGACY_PSK || + sme->key == NULL) + return ret; + + /* + * We want to do shared auth. + * We need to actually set the key we previously cached, + * and then tell the UMAC it's the default one. + * That will trigger the auth+assoc UMAC machinery, and again, + * this must be done after setting the profile. + */ + ret = iwm_set_key(iwm, 0, &iwm->keys[sme->key_idx]); + if (ret < 0) + return ret; + + return iwm_set_tx_key(iwm, iwm->default_key); +} + +static int iwm_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev, + u16 reason_code) +{ + struct iwm_priv *iwm = wiphy_to_iwm(wiphy); + + IWM_DBG_WEXT(iwm, DBG, "Active: %d\n", iwm->umac_profile_active); + + if (iwm->umac_profile_active) + iwm_invalidate_mlme_profile(iwm); + + return 0; +} + +static int iwm_cfg80211_set_txpower(struct wiphy *wiphy, + enum nl80211_tx_power_setting type, int mbm) +{ + struct iwm_priv *iwm = wiphy_to_iwm(wiphy); + int ret; + + switch (type) { + case NL80211_TX_POWER_AUTOMATIC: + return 0; + case NL80211_TX_POWER_FIXED: + if (mbm < 0 || (mbm % 100)) + return -EOPNOTSUPP; + + if (!test_bit(IWM_STATUS_READY, &iwm->status)) + return 0; + + ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX, + CFG_TX_PWR_LIMIT_USR, + MBM_TO_DBM(mbm) * 2); + if (ret < 0) + return ret; + + return iwm_tx_power_trigger(iwm); + default: + IWM_ERR(iwm, "Unsupported power type: %d\n", type); + return -EOPNOTSUPP; + } + + return 0; +} + +static int iwm_cfg80211_get_txpower(struct wiphy *wiphy, int *dbm) +{ + struct iwm_priv *iwm = wiphy_to_iwm(wiphy); + + *dbm = iwm->txpower >> 1; + + return 0; +} + +static int iwm_cfg80211_set_power_mgmt(struct wiphy *wiphy, + struct net_device *dev, + bool enabled, int timeout) +{ + struct iwm_priv *iwm = wiphy_to_iwm(wiphy); + u32 power_index; + + if (enabled) + power_index = IWM_POWER_INDEX_DEFAULT; + else + power_index = IWM_POWER_INDEX_MIN; + + if (power_index == iwm->conf.power_index) + return 0; + + iwm->conf.power_index = power_index; + + return iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX, + CFG_POWER_INDEX, iwm->conf.power_index); +} + +static int iwm_cfg80211_set_pmksa(struct wiphy *wiphy, + struct net_device *netdev, + struct cfg80211_pmksa *pmksa) +{ + struct iwm_priv *iwm = wiphy_to_iwm(wiphy); + + return iwm_send_pmkid_update(iwm, pmksa, IWM_CMD_PMKID_ADD); +} + +static int iwm_cfg80211_del_pmksa(struct wiphy *wiphy, + struct net_device *netdev, + struct cfg80211_pmksa *pmksa) +{ + struct iwm_priv *iwm = wiphy_to_iwm(wiphy); + + return iwm_send_pmkid_update(iwm, pmksa, IWM_CMD_PMKID_DEL); +} + +static int iwm_cfg80211_flush_pmksa(struct wiphy *wiphy, + struct net_device *netdev) +{ + struct iwm_priv *iwm = wiphy_to_iwm(wiphy); + struct cfg80211_pmksa pmksa; + + memset(&pmksa, 0, sizeof(struct cfg80211_pmksa)); + + return iwm_send_pmkid_update(iwm, &pmksa, IWM_CMD_PMKID_FLUSH); +} + + +static struct cfg80211_ops iwm_cfg80211_ops = { + .change_virtual_intf = iwm_cfg80211_change_iface, + .add_key = iwm_cfg80211_add_key, + .get_key = iwm_cfg80211_get_key, + .del_key = iwm_cfg80211_del_key, + .set_default_key = iwm_cfg80211_set_default_key, + .get_station = iwm_cfg80211_get_station, + .scan = iwm_cfg80211_scan, + .set_wiphy_params = iwm_cfg80211_set_wiphy_params, + .connect = iwm_cfg80211_connect, + .disconnect = iwm_cfg80211_disconnect, + .join_ibss = iwm_cfg80211_join_ibss, + .leave_ibss = iwm_cfg80211_leave_ibss, + .set_tx_power = iwm_cfg80211_set_txpower, + .get_tx_power = iwm_cfg80211_get_txpower, + .set_power_mgmt = iwm_cfg80211_set_power_mgmt, + .set_pmksa = iwm_cfg80211_set_pmksa, + .del_pmksa = iwm_cfg80211_del_pmksa, + .flush_pmksa = iwm_cfg80211_flush_pmksa, +}; + +static const u32 cipher_suites[] = { + WLAN_CIPHER_SUITE_WEP40, + WLAN_CIPHER_SUITE_WEP104, + WLAN_CIPHER_SUITE_TKIP, + WLAN_CIPHER_SUITE_CCMP, +}; + +struct wireless_dev *iwm_wdev_alloc(int sizeof_bus, struct device *dev) +{ + int ret = 0; + struct wireless_dev *wdev; + + /* + * We're trying to have the following memory + * layout: + * + * +-------------------------+ + * | struct wiphy | + * +-------------------------+ + * | struct iwm_priv | + * +-------------------------+ + * | bus private data | + * | (e.g. iwm_priv_sdio) | + * +-------------------------+ + * + */ + + wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL); + if (!wdev) { + dev_err(dev, "Couldn't allocate wireless device\n"); + return ERR_PTR(-ENOMEM); + } + + wdev->wiphy = wiphy_new(&iwm_cfg80211_ops, + sizeof(struct iwm_priv) + sizeof_bus); + if (!wdev->wiphy) { + dev_err(dev, "Couldn't allocate wiphy device\n"); + ret = -ENOMEM; + goto out_err_new; + } + + set_wiphy_dev(wdev->wiphy, dev); + wdev->wiphy->max_scan_ssids = UMAC_WIFI_IF_PROBE_OPTION_MAX; + wdev->wiphy->max_num_pmkids = UMAC_MAX_NUM_PMKIDS; + wdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | + BIT(NL80211_IFTYPE_ADHOC); + wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &iwm_band_2ghz; + wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &iwm_band_5ghz; + wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; + + wdev->wiphy->cipher_suites = cipher_suites; + wdev->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); + + ret = wiphy_register(wdev->wiphy); + if (ret < 0) { + dev_err(dev, "Couldn't register wiphy device\n"); + goto out_err_register; + } + + return wdev; + + out_err_register: + wiphy_free(wdev->wiphy); + + out_err_new: + kfree(wdev); + + return ERR_PTR(ret); +} + +void iwm_wdev_free(struct iwm_priv *iwm) +{ + struct wireless_dev *wdev = iwm_to_wdev(iwm); + + if (!wdev) + return; + + wiphy_unregister(wdev->wiphy); + wiphy_free(wdev->wiphy); + kfree(wdev); +} diff --git a/trunk/drivers/net/wireless/iwmc3200wifi/cfg80211.h b/trunk/drivers/net/wireless/iwmc3200wifi/cfg80211.h new file mode 100644 index 000000000000..56a34145acbf --- /dev/null +++ b/trunk/drivers/net/wireless/iwmc3200wifi/cfg80211.h @@ -0,0 +1,31 @@ +/* + * Intel Wireless Multicomm 3200 WiFi driver + * + * Copyright (C) 2009 Intel Corporation + * Samuel Ortiz + * Zhu Yi + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + * + */ + +#ifndef __IWM_CFG80211_H__ +#define __IWM_CFG80211_H__ + +int iwm_cfg80211_inform_bss(struct iwm_priv *iwm); +struct wireless_dev *iwm_wdev_alloc(int sizeof_bus, struct device *dev); +void iwm_wdev_free(struct iwm_priv *iwm); + +#endif diff --git a/trunk/drivers/net/wireless/iwmc3200wifi/commands.c b/trunk/drivers/net/wireless/iwmc3200wifi/commands.c new file mode 100644 index 000000000000..bd75078c454b --- /dev/null +++ b/trunk/drivers/net/wireless/iwmc3200wifi/commands.c @@ -0,0 +1,1002 @@ +/* + * Intel Wireless Multicomm 3200 WiFi driver + * + * Copyright (C) 2009 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * + * Intel Corporation + * Samuel Ortiz + * Zhu Yi + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "iwm.h" +#include "bus.h" +#include "hal.h" +#include "umac.h" +#include "commands.h" +#include "debug.h" + +static int iwm_send_lmac_ptrough_cmd(struct iwm_priv *iwm, + u8 lmac_cmd_id, + const void *lmac_payload, + u16 lmac_payload_size, + u8 resp) +{ + struct iwm_udma_wifi_cmd udma_cmd = UDMA_LMAC_INIT; + struct iwm_umac_cmd umac_cmd; + struct iwm_lmac_cmd lmac_cmd; + + lmac_cmd.id = lmac_cmd_id; + + umac_cmd.id = UMAC_CMD_OPCODE_WIFI_PASS_THROUGH; + umac_cmd.resp = resp; + + return iwm_hal_send_host_cmd(iwm, &udma_cmd, &umac_cmd, &lmac_cmd, + lmac_payload, lmac_payload_size); +} + +int iwm_send_wifi_if_cmd(struct iwm_priv *iwm, void *payload, u16 payload_size, + bool resp) +{ + struct iwm_umac_wifi_if *hdr = (struct iwm_umac_wifi_if *)payload; + struct iwm_udma_wifi_cmd udma_cmd = UDMA_UMAC_INIT; + struct iwm_umac_cmd umac_cmd; + int ret; + u8 oid = hdr->oid; + + if (!test_bit(IWM_STATUS_READY, &iwm->status)) { + IWM_ERR(iwm, "Interface is not ready yet"); + return -EAGAIN; + } + + umac_cmd.id = UMAC_CMD_OPCODE_WIFI_IF_WRAPPER; + umac_cmd.resp = resp; + + ret = iwm_hal_send_umac_cmd(iwm, &udma_cmd, &umac_cmd, + payload, payload_size); + + if (resp) { + ret = wait_event_interruptible_timeout(iwm->wifi_ntfy_queue, + test_and_clear_bit(oid, &iwm->wifi_ntfy[0]), + 3 * HZ); + + return ret ? 0 : -EBUSY; + } + + return ret; +} + +static int modparam_wiwi = COEX_MODE_CM; +module_param_named(wiwi, modparam_wiwi, int, 0644); +MODULE_PARM_DESC(wiwi, "Wifi-WiMAX coexistence: 1=SA, 2=XOR, 3=CM (default)"); + +static struct coex_event iwm_sta_xor_prio_tbl[COEX_EVENTS_NUM] = +{ + {4, 3, 0, COEX_UNASSOC_IDLE_FLAGS}, + {4, 3, 0, COEX_UNASSOC_MANUAL_SCAN_FLAGS}, + {4, 3, 0, COEX_UNASSOC_AUTO_SCAN_FLAGS}, + {4, 3, 0, COEX_CALIBRATION_FLAGS}, + {4, 3, 0, COEX_PERIODIC_CALIBRATION_FLAGS}, + {4, 3, 0, COEX_CONNECTION_ESTAB_FLAGS}, + {4, 3, 0, COEX_ASSOCIATED_IDLE_FLAGS}, + {4, 3, 0, COEX_ASSOC_MANUAL_SCAN_FLAGS}, + {4, 3, 0, COEX_ASSOC_AUTO_SCAN_FLAGS}, + {4, 3, 0, COEX_ASSOC_ACTIVE_LEVEL_FLAGS}, + {6, 3, 0, COEX_XOR_RF_ON_FLAGS}, + {4, 3, 0, COEX_RF_OFF_FLAGS}, + {6, 6, 0, COEX_STAND_ALONE_DEBUG_FLAGS}, + {4, 3, 0, COEX_IPAN_ASSOC_LEVEL_FLAGS}, + {4, 3, 0, COEX_RSRVD1_FLAGS}, + {4, 3, 0, COEX_RSRVD2_FLAGS} +}; + +static struct coex_event iwm_sta_cm_prio_tbl[COEX_EVENTS_NUM] = +{ + {1, 1, 0, COEX_UNASSOC_IDLE_FLAGS}, + {4, 4, 0, COEX_UNASSOC_MANUAL_SCAN_FLAGS}, + {3, 3, 0, COEX_UNASSOC_AUTO_SCAN_FLAGS}, + {6, 6, 0, COEX_CALIBRATION_FLAGS}, + {3, 3, 0, COEX_PERIODIC_CALIBRATION_FLAGS}, + {6, 5, 0, COEX_CONNECTION_ESTAB_FLAGS}, + {4, 4, 0, COEX_ASSOCIATED_IDLE_FLAGS}, + {4, 4, 0, COEX_ASSOC_MANUAL_SCAN_FLAGS}, + {4, 4, 0, COEX_ASSOC_AUTO_SCAN_FLAGS}, + {4, 4, 0, COEX_ASSOC_ACTIVE_LEVEL_FLAGS}, + {1, 1, 0, COEX_RF_ON_FLAGS}, + {1, 1, 0, COEX_RF_OFF_FLAGS}, + {7, 7, 0, COEX_STAND_ALONE_DEBUG_FLAGS}, + {5, 4, 0, COEX_IPAN_ASSOC_LEVEL_FLAGS}, + {1, 1, 0, COEX_RSRVD1_FLAGS}, + {1, 1, 0, COEX_RSRVD2_FLAGS} +}; + +int iwm_send_prio_table(struct iwm_priv *iwm) +{ + struct iwm_coex_prio_table_cmd coex_table_cmd; + u32 coex_enabled, mode_enabled; + + memset(&coex_table_cmd, 0, sizeof(struct iwm_coex_prio_table_cmd)); + + coex_table_cmd.flags = COEX_FLAGS_STA_TABLE_VALID_MSK; + + switch (modparam_wiwi) { + case COEX_MODE_XOR: + case COEX_MODE_CM: + coex_enabled = 1; + break; + default: + coex_enabled = 0; + break; + } + + switch (iwm->conf.mode) { + case UMAC_MODE_BSS: + case UMAC_MODE_IBSS: + mode_enabled = 1; + break; + default: + mode_enabled = 0; + break; + } + + if (coex_enabled && mode_enabled) { + coex_table_cmd.flags |= COEX_FLAGS_COEX_ENABLE_MSK | + COEX_FLAGS_ASSOC_WAKEUP_UMASK_MSK | + COEX_FLAGS_UNASSOC_WAKEUP_UMASK_MSK; + + switch (modparam_wiwi) { + case COEX_MODE_XOR: + memcpy(coex_table_cmd.sta_prio, iwm_sta_xor_prio_tbl, + sizeof(iwm_sta_xor_prio_tbl)); + break; + case COEX_MODE_CM: + memcpy(coex_table_cmd.sta_prio, iwm_sta_cm_prio_tbl, + sizeof(iwm_sta_cm_prio_tbl)); + break; + default: + IWM_ERR(iwm, "Invalid coex_mode 0x%x\n", + modparam_wiwi); + break; + } + } else + IWM_WARN(iwm, "coexistense disabled\n"); + + return iwm_send_lmac_ptrough_cmd(iwm, COEX_PRIORITY_TABLE_CMD, + &coex_table_cmd, + sizeof(struct iwm_coex_prio_table_cmd), 0); +} + +int iwm_send_init_calib_cfg(struct iwm_priv *iwm, u8 calib_requested) +{ + struct iwm_lmac_cal_cfg_cmd cal_cfg_cmd; + + memset(&cal_cfg_cmd, 0, sizeof(struct iwm_lmac_cal_cfg_cmd)); + + cal_cfg_cmd.ucode_cfg.init.enable = cpu_to_le32(calib_requested); + cal_cfg_cmd.ucode_cfg.init.start = cpu_to_le32(calib_requested); + cal_cfg_cmd.ucode_cfg.init.send_res = cpu_to_le32(calib_requested); + cal_cfg_cmd.ucode_cfg.flags = + cpu_to_le32(CALIB_CFG_FLAG_SEND_COMPLETE_NTFY_AFTER_MSK); + + return iwm_send_lmac_ptrough_cmd(iwm, CALIBRATION_CFG_CMD, &cal_cfg_cmd, + sizeof(struct iwm_lmac_cal_cfg_cmd), 1); +} + +int iwm_send_periodic_calib_cfg(struct iwm_priv *iwm, u8 calib_requested) +{ + struct iwm_lmac_cal_cfg_cmd cal_cfg_cmd; + + memset(&cal_cfg_cmd, 0, sizeof(struct iwm_lmac_cal_cfg_cmd)); + + cal_cfg_cmd.ucode_cfg.periodic.enable = cpu_to_le32(calib_requested); + cal_cfg_cmd.ucode_cfg.periodic.start = cpu_to_le32(calib_requested); + + return iwm_send_lmac_ptrough_cmd(iwm, CALIBRATION_CFG_CMD, &cal_cfg_cmd, + sizeof(struct iwm_lmac_cal_cfg_cmd), 0); +} + +int iwm_store_rxiq_calib_result(struct iwm_priv *iwm) +{ + struct iwm_calib_rxiq *rxiq; + u8 *eeprom_rxiq = iwm_eeprom_access(iwm, IWM_EEPROM_CALIB_RXIQ); + int grplen = sizeof(struct iwm_calib_rxiq_group); + + rxiq = kzalloc(sizeof(struct iwm_calib_rxiq), GFP_KERNEL); + if (!rxiq) { + IWM_ERR(iwm, "Couldn't alloc memory for RX IQ\n"); + return -ENOMEM; + } + + eeprom_rxiq = iwm_eeprom_access(iwm, IWM_EEPROM_CALIB_RXIQ); + if (IS_ERR(eeprom_rxiq)) { + IWM_ERR(iwm, "Couldn't access EEPROM RX IQ entry\n"); + kfree(rxiq); + return PTR_ERR(eeprom_rxiq); + } + + iwm->calib_res[SHILOH_PHY_CALIBRATE_RX_IQ_CMD].buf = (u8 *)rxiq; + iwm->calib_res[SHILOH_PHY_CALIBRATE_RX_IQ_CMD].size = sizeof(*rxiq); + + rxiq->hdr.opcode = SHILOH_PHY_CALIBRATE_RX_IQ_CMD; + rxiq->hdr.first_grp = 0; + rxiq->hdr.grp_num = 1; + rxiq->hdr.all_data_valid = 1; + + memcpy(&rxiq->group[0], eeprom_rxiq, 4 * grplen); + memcpy(&rxiq->group[4], eeprom_rxiq + 6 * grplen, grplen); + + return 0; +} + +int iwm_send_calib_results(struct iwm_priv *iwm) +{ + int i, ret = 0; + + for (i = PHY_CALIBRATE_OPCODES_NUM; i < CALIBRATION_CMD_NUM; i++) { + if (test_bit(i - PHY_CALIBRATE_OPCODES_NUM, + &iwm->calib_done_map)) { + IWM_DBG_CMD(iwm, DBG, + "Send calibration %d result\n", i); + ret |= iwm_send_lmac_ptrough_cmd(iwm, + REPLY_PHY_CALIBRATION_CMD, + iwm->calib_res[i].buf, + iwm->calib_res[i].size, 0); + + kfree(iwm->calib_res[i].buf); + iwm->calib_res[i].buf = NULL; + iwm->calib_res[i].size = 0; + } + } + + return ret; +} + +int iwm_send_ct_kill_cfg(struct iwm_priv *iwm, u8 entry, u8 exit) +{ + struct iwm_ct_kill_cfg_cmd cmd; + + cmd.entry_threshold = entry; + cmd.exit_threshold = exit; + + return iwm_send_lmac_ptrough_cmd(iwm, REPLY_CT_KILL_CONFIG_CMD, &cmd, + sizeof(struct iwm_ct_kill_cfg_cmd), 0); +} + +int iwm_send_umac_reset(struct iwm_priv *iwm, __le32 reset_flags, bool resp) +{ + struct iwm_udma_wifi_cmd udma_cmd = UDMA_UMAC_INIT; + struct iwm_umac_cmd umac_cmd; + struct iwm_umac_cmd_reset reset; + + reset.flags = reset_flags; + + umac_cmd.id = UMAC_CMD_OPCODE_RESET; + umac_cmd.resp = resp; + + return iwm_hal_send_umac_cmd(iwm, &udma_cmd, &umac_cmd, &reset, + sizeof(struct iwm_umac_cmd_reset)); +} + +int iwm_umac_set_config_fix(struct iwm_priv *iwm, u16 tbl, u16 key, u32 value) +{ + struct iwm_udma_wifi_cmd udma_cmd = UDMA_UMAC_INIT; + struct iwm_umac_cmd umac_cmd; + struct iwm_umac_cmd_set_param_fix param; + + if ((tbl != UMAC_PARAM_TBL_CFG_FIX) && + (tbl != UMAC_PARAM_TBL_FA_CFG_FIX)) + return -EINVAL; + + umac_cmd.id = UMAC_CMD_OPCODE_SET_PARAM_FIX; + umac_cmd.resp = 0; + + param.tbl = cpu_to_le16(tbl); + param.key = cpu_to_le16(key); + param.value = cpu_to_le32(value); + + return iwm_hal_send_umac_cmd(iwm, &udma_cmd, &umac_cmd, ¶m, + sizeof(struct iwm_umac_cmd_set_param_fix)); +} + +int iwm_umac_set_config_var(struct iwm_priv *iwm, u16 key, + void *payload, u16 payload_size) +{ + struct iwm_udma_wifi_cmd udma_cmd = UDMA_UMAC_INIT; + struct iwm_umac_cmd umac_cmd; + struct iwm_umac_cmd_set_param_var *param_hdr; + u8 *param; + int ret; + + param = kzalloc(payload_size + + sizeof(struct iwm_umac_cmd_set_param_var), GFP_KERNEL); + if (!param) { + IWM_ERR(iwm, "Couldn't allocate param\n"); + return -ENOMEM; + } + + param_hdr = (struct iwm_umac_cmd_set_param_var *)param; + + umac_cmd.id = UMAC_CMD_OPCODE_SET_PARAM_VAR; + umac_cmd.resp = 0; + + param_hdr->tbl = cpu_to_le16(UMAC_PARAM_TBL_CFG_VAR); + param_hdr->key = cpu_to_le16(key); + param_hdr->len = cpu_to_le16(payload_size); + memcpy(param + sizeof(struct iwm_umac_cmd_set_param_var), + payload, payload_size); + + ret = iwm_hal_send_umac_cmd(iwm, &udma_cmd, &umac_cmd, param, + sizeof(struct iwm_umac_cmd_set_param_var) + + payload_size); + kfree(param); + + return ret; +} + +int iwm_send_umac_config(struct iwm_priv *iwm, __le32 reset_flags) +{ + int ret; + + /* Use UMAC default values */ + ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX, + CFG_POWER_INDEX, iwm->conf.power_index); + if (ret < 0) + return ret; + + ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_FA_CFG_FIX, + CFG_FRAG_THRESHOLD, + iwm->conf.frag_threshold); + if (ret < 0) + return ret; + + ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX, + CFG_RTS_THRESHOLD, + iwm->conf.rts_threshold); + if (ret < 0) + return ret; + + ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX, + CFG_CTS_TO_SELF, iwm->conf.cts_to_self); + if (ret < 0) + return ret; + + ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX, + CFG_WIRELESS_MODE, + iwm->conf.wireless_mode); + if (ret < 0) + return ret; + + ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX, + CFG_COEX_MODE, modparam_wiwi); + if (ret < 0) + return ret; + + /* + ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX, + CFG_ASSOCIATION_TIMEOUT, + iwm->conf.assoc_timeout); + if (ret < 0) + return ret; + + ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX, + CFG_ROAM_TIMEOUT, + iwm->conf.roam_timeout); + if (ret < 0) + return ret; + + ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX, + CFG_WIRELESS_MODE, + WIRELESS_MODE_11A | WIRELESS_MODE_11G); + if (ret < 0) + return ret; + */ + + ret = iwm_umac_set_config_var(iwm, CFG_NET_ADDR, + iwm_to_ndev(iwm)->dev_addr, ETH_ALEN); + if (ret < 0) + return ret; + + /* UMAC PM static configurations */ + ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX, + CFG_PM_LEGACY_RX_TIMEOUT, 0x12C); + if (ret < 0) + return ret; + + ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX, + CFG_PM_LEGACY_TX_TIMEOUT, 0x15E); + if (ret < 0) + return ret; + + ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX, + CFG_PM_CTRL_FLAGS, 0x1); + if (ret < 0) + return ret; + + ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX, + CFG_PM_KEEP_ALIVE_IN_BEACONS, 0x80); + if (ret < 0) + return ret; + + /* reset UMAC */ + ret = iwm_send_umac_reset(iwm, reset_flags, 1); + if (ret < 0) + return ret; + + ret = iwm_notif_handle(iwm, UMAC_CMD_OPCODE_RESET, IWM_SRC_UMAC, + WAIT_NOTIF_TIMEOUT); + if (ret) { + IWM_ERR(iwm, "Wait for UMAC RESET timeout\n"); + return ret; + } + + return ret; +} + +int iwm_send_packet(struct iwm_priv *iwm, struct sk_buff *skb, int pool_id) +{ + struct iwm_udma_wifi_cmd udma_cmd; + struct iwm_umac_cmd umac_cmd; + struct iwm_tx_info *tx_info = skb_to_tx_info(skb); + + udma_cmd.eop = 1; /* always set eop for non-concatenated Tx */ + udma_cmd.credit_group = pool_id; + udma_cmd.ra_tid = tx_info->sta << 4 | tx_info->tid; + udma_cmd.lmac_offset = 0; + + umac_cmd.id = REPLY_TX; + umac_cmd.color = tx_info->color; + umac_cmd.resp = 0; + + return iwm_hal_send_umac_cmd(iwm, &udma_cmd, &umac_cmd, + skb->data, skb->len); +} + +static int iwm_target_read(struct iwm_priv *iwm, __le32 address, + u8 *response, u32 resp_size) +{ + struct iwm_udma_nonwifi_cmd target_cmd; + struct iwm_nonwifi_cmd *cmd; + u16 seq_num; + int ret = 0; + + target_cmd.opcode = UMAC_HDI_OUT_OPCODE_READ; + target_cmd.addr = address; + target_cmd.op1_sz = cpu_to_le32(resp_size); + target_cmd.op2 = 0; + target_cmd.handle_by_hw = 0; + target_cmd.resp = 1; + target_cmd.eop = 1; + + ret = iwm_hal_send_target_cmd(iwm, &target_cmd, NULL); + if (ret < 0) { + IWM_ERR(iwm, "Couldn't send READ command\n"); + return ret; + } + + /* When succeeding, the send_target routine returns the seq number */ + seq_num = ret; + + ret = wait_event_interruptible_timeout(iwm->nonwifi_queue, + (cmd = iwm_get_pending_nonwifi_cmd(iwm, seq_num, + UMAC_HDI_OUT_OPCODE_READ)) != NULL, + 2 * HZ); + + if (!ret) { + IWM_ERR(iwm, "Didn't receive a target READ answer\n"); + return ret; + } + + memcpy(response, cmd->buf.hdr + sizeof(struct iwm_udma_in_hdr), + resp_size); + + kfree(cmd); + + return 0; +} + +int iwm_read_mac(struct iwm_priv *iwm, u8 *mac) +{ + int ret; + u8 mac_align[ALIGN(ETH_ALEN, 8)]; + + ret = iwm_target_read(iwm, cpu_to_le32(WICO_MAC_ADDRESS_ADDR), + mac_align, sizeof(mac_align)); + if (ret) + return ret; + + if (is_valid_ether_addr(mac_align)) + memcpy(mac, mac_align, ETH_ALEN); + else { + IWM_ERR(iwm, "Invalid EEPROM MAC\n"); + memcpy(mac, iwm->conf.mac_addr, ETH_ALEN); + get_random_bytes(&mac[3], 3); + } + + return 0; +} + +static int iwm_check_profile(struct iwm_priv *iwm) +{ + if (!iwm->umac_profile_active) + return -EAGAIN; + + if (iwm->umac_profile->sec.ucast_cipher != UMAC_CIPHER_TYPE_WEP_40 && + iwm->umac_profile->sec.ucast_cipher != UMAC_CIPHER_TYPE_WEP_104 && + iwm->umac_profile->sec.ucast_cipher != UMAC_CIPHER_TYPE_TKIP && + iwm->umac_profile->sec.ucast_cipher != UMAC_CIPHER_TYPE_CCMP) { + IWM_ERR(iwm, "Wrong unicast cipher: 0x%x\n", + iwm->umac_profile->sec.ucast_cipher); + return -EAGAIN; + } + + if (iwm->umac_profile->sec.mcast_cipher != UMAC_CIPHER_TYPE_WEP_40 && + iwm->umac_profile->sec.mcast_cipher != UMAC_CIPHER_TYPE_WEP_104 && + iwm->umac_profile->sec.mcast_cipher != UMAC_CIPHER_TYPE_TKIP && + iwm->umac_profile->sec.mcast_cipher != UMAC_CIPHER_TYPE_CCMP) { + IWM_ERR(iwm, "Wrong multicast cipher: 0x%x\n", + iwm->umac_profile->sec.mcast_cipher); + return -EAGAIN; + } + + if ((iwm->umac_profile->sec.ucast_cipher == UMAC_CIPHER_TYPE_WEP_40 || + iwm->umac_profile->sec.ucast_cipher == UMAC_CIPHER_TYPE_WEP_104) && + (iwm->umac_profile->sec.ucast_cipher != + iwm->umac_profile->sec.mcast_cipher)) { + IWM_ERR(iwm, "Unicast and multicast ciphers differ for WEP\n"); + } + + return 0; +} + +int iwm_set_tx_key(struct iwm_priv *iwm, u8 key_idx) +{ + struct iwm_umac_tx_key_id tx_key_id; + int ret; + + ret = iwm_check_profile(iwm); + if (ret < 0) + return ret; + + /* UMAC only allows to set default key for WEP and auth type is + * NOT 802.1X or RSNA. */ + if ((iwm->umac_profile->sec.ucast_cipher != UMAC_CIPHER_TYPE_WEP_40 && + iwm->umac_profile->sec.ucast_cipher != UMAC_CIPHER_TYPE_WEP_104) || + iwm->umac_profile->sec.auth_type == UMAC_AUTH_TYPE_8021X || + iwm->umac_profile->sec.auth_type == UMAC_AUTH_TYPE_RSNA_PSK) + return 0; + + tx_key_id.hdr.oid = UMAC_WIFI_IF_CMD_GLOBAL_TX_KEY_ID; + tx_key_id.hdr.buf_size = cpu_to_le16(sizeof(struct iwm_umac_tx_key_id) - + sizeof(struct iwm_umac_wifi_if)); + + tx_key_id.key_idx = key_idx; + + return iwm_send_wifi_if_cmd(iwm, &tx_key_id, sizeof(tx_key_id), 1); +} + +int iwm_set_key(struct iwm_priv *iwm, bool remove, struct iwm_key *key) +{ + int ret = 0; + u8 cmd[64], *sta_addr, *key_data, key_len; + s8 key_idx; + u16 cmd_size = 0; + struct iwm_umac_key_hdr *key_hdr = &key->hdr; + struct iwm_umac_key_wep40 *wep40 = (struct iwm_umac_key_wep40 *)cmd; + struct iwm_umac_key_wep104 *wep104 = (struct iwm_umac_key_wep104 *)cmd; + struct iwm_umac_key_tkip *tkip = (struct iwm_umac_key_tkip *)cmd; + struct iwm_umac_key_ccmp *ccmp = (struct iwm_umac_key_ccmp *)cmd; + + if (!remove) { + ret = iwm_check_profile(iwm); + if (ret < 0) + return ret; + } + + sta_addr = key->hdr.mac; + key_data = key->key; + key_len = key->key_len; + key_idx = key->hdr.key_idx; + + if (!remove) { + u8 auth_type = iwm->umac_profile->sec.auth_type; + + IWM_DBG_WEXT(iwm, DBG, "key_idx:%d\n", key_idx); + IWM_DBG_WEXT(iwm, DBG, "key_len:%d\n", key_len); + IWM_DBG_WEXT(iwm, DBG, "MAC:%pM, idx:%d, multicast:%d\n", + key_hdr->mac, key_hdr->key_idx, key_hdr->multicast); + + IWM_DBG_WEXT(iwm, DBG, "profile: mcast:0x%x, ucast:0x%x\n", + iwm->umac_profile->sec.mcast_cipher, + iwm->umac_profile->sec.ucast_cipher); + IWM_DBG_WEXT(iwm, DBG, "profile: auth_type:0x%x, flags:0x%x\n", + iwm->umac_profile->sec.auth_type, + iwm->umac_profile->sec.flags); + + switch (key->cipher) { + case WLAN_CIPHER_SUITE_WEP40: + wep40->hdr.oid = UMAC_WIFI_IF_CMD_ADD_WEP40_KEY; + wep40->hdr.buf_size = + cpu_to_le16(sizeof(struct iwm_umac_key_wep40) - + sizeof(struct iwm_umac_wifi_if)); + + memcpy(&wep40->key_hdr, key_hdr, + sizeof(struct iwm_umac_key_hdr)); + memcpy(wep40->key, key_data, key_len); + wep40->static_key = + !!((auth_type != UMAC_AUTH_TYPE_8021X) && + (auth_type != UMAC_AUTH_TYPE_RSNA_PSK)); + + cmd_size = sizeof(struct iwm_umac_key_wep40); + break; + + case WLAN_CIPHER_SUITE_WEP104: + wep104->hdr.oid = UMAC_WIFI_IF_CMD_ADD_WEP104_KEY; + wep104->hdr.buf_size = + cpu_to_le16(sizeof(struct iwm_umac_key_wep104) - + sizeof(struct iwm_umac_wifi_if)); + + memcpy(&wep104->key_hdr, key_hdr, + sizeof(struct iwm_umac_key_hdr)); + memcpy(wep104->key, key_data, key_len); + wep104->static_key = + !!((auth_type != UMAC_AUTH_TYPE_8021X) && + (auth_type != UMAC_AUTH_TYPE_RSNA_PSK)); + + cmd_size = sizeof(struct iwm_umac_key_wep104); + break; + + case WLAN_CIPHER_SUITE_CCMP: + key_hdr->key_idx++; + ccmp->hdr.oid = UMAC_WIFI_IF_CMD_ADD_CCMP_KEY; + ccmp->hdr.buf_size = + cpu_to_le16(sizeof(struct iwm_umac_key_ccmp) - + sizeof(struct iwm_umac_wifi_if)); + + memcpy(&ccmp->key_hdr, key_hdr, + sizeof(struct iwm_umac_key_hdr)); + + memcpy(ccmp->key, key_data, key_len); + + if (key->seq_len) + memcpy(ccmp->iv_count, key->seq, key->seq_len); + + cmd_size = sizeof(struct iwm_umac_key_ccmp); + break; + + case WLAN_CIPHER_SUITE_TKIP: + key_hdr->key_idx++; + tkip->hdr.oid = UMAC_WIFI_IF_CMD_ADD_TKIP_KEY; + tkip->hdr.buf_size = + cpu_to_le16(sizeof(struct iwm_umac_key_tkip) - + sizeof(struct iwm_umac_wifi_if)); + + memcpy(&tkip->key_hdr, key_hdr, + sizeof(struct iwm_umac_key_hdr)); + + memcpy(tkip->tkip_key, key_data, IWM_TKIP_KEY_SIZE); + memcpy(tkip->mic_tx_key, key_data + IWM_TKIP_KEY_SIZE, + IWM_TKIP_MIC_SIZE); + memcpy(tkip->mic_rx_key, + key_data + IWM_TKIP_KEY_SIZE + IWM_TKIP_MIC_SIZE, + IWM_TKIP_MIC_SIZE); + + if (key->seq_len) + memcpy(ccmp->iv_count, key->seq, key->seq_len); + + cmd_size = sizeof(struct iwm_umac_key_tkip); + break; + + default: + return -ENOTSUPP; + } + + if ((key->cipher == WLAN_CIPHER_SUITE_TKIP) || + (key->cipher == WLAN_CIPHER_SUITE_CCMP)) + /* + * UGLY_UGLY_UGLY + * Copied HACK from the MWG driver. + * Without it, the key is set before the second + * EAPOL frame is sent, and the latter is thus + * encrypted. + */ + schedule_timeout_interruptible(usecs_to_jiffies(300)); + + ret = iwm_send_wifi_if_cmd(iwm, cmd, cmd_size, 1); + } else { + struct iwm_umac_key_remove key_remove; + + IWM_DBG_WEXT(iwm, ERR, "Removing key_idx:%d\n", key_idx); + + key_remove.hdr.oid = UMAC_WIFI_IF_CMD_REMOVE_KEY; + key_remove.hdr.buf_size = + cpu_to_le16(sizeof(struct iwm_umac_key_remove) - + sizeof(struct iwm_umac_wifi_if)); + memcpy(&key_remove.key_hdr, key_hdr, + sizeof(struct iwm_umac_key_hdr)); + + ret = iwm_send_wifi_if_cmd(iwm, &key_remove, + sizeof(struct iwm_umac_key_remove), + 1); + if (ret) + return ret; + + iwm->keys[key_idx].key_len = 0; + } + + return ret; +} + + +int iwm_send_mlme_profile(struct iwm_priv *iwm) +{ + int ret; + struct iwm_umac_profile profile; + + memcpy(&profile, iwm->umac_profile, sizeof(profile)); + + profile.hdr.oid = UMAC_WIFI_IF_CMD_SET_PROFILE; + profile.hdr.buf_size = cpu_to_le16(sizeof(struct iwm_umac_profile) - + sizeof(struct iwm_umac_wifi_if)); + + ret = iwm_send_wifi_if_cmd(iwm, &profile, sizeof(profile), 1); + if (ret) { + IWM_ERR(iwm, "Send profile command failed\n"); + return ret; + } + + set_bit(IWM_STATUS_SME_CONNECTING, &iwm->status); + return 0; +} + +int __iwm_invalidate_mlme_profile(struct iwm_priv *iwm) +{ + struct iwm_umac_invalidate_profile invalid; + + invalid.hdr.oid = UMAC_WIFI_IF_CMD_INVALIDATE_PROFILE; + invalid.hdr.buf_size = + cpu_to_le16(sizeof(struct iwm_umac_invalidate_profile) - + sizeof(struct iwm_umac_wifi_if)); + + invalid.reason = WLAN_REASON_UNSPECIFIED; + + return iwm_send_wifi_if_cmd(iwm, &invalid, sizeof(invalid), 1); +} + +int iwm_invalidate_mlme_profile(struct iwm_priv *iwm) +{ + int ret; + + ret = __iwm_invalidate_mlme_profile(iwm); + if (ret) + return ret; + + ret = wait_event_interruptible_timeout(iwm->mlme_queue, + (iwm->umac_profile_active == 0), 5 * HZ); + + return ret ? 0 : -EBUSY; +} + +int iwm_tx_power_trigger(struct iwm_priv *iwm) +{ + struct iwm_umac_pwr_trigger pwr_trigger; + + pwr_trigger.hdr.oid = UMAC_WIFI_IF_CMD_TX_PWR_TRIGGER; + pwr_trigger.hdr.buf_size = + cpu_to_le16(sizeof(struct iwm_umac_pwr_trigger) - + sizeof(struct iwm_umac_wifi_if)); + + + return iwm_send_wifi_if_cmd(iwm, &pwr_trigger, sizeof(pwr_trigger), 1); +} + +int iwm_send_umac_stats_req(struct iwm_priv *iwm, u32 flags) +{ + struct iwm_udma_wifi_cmd udma_cmd = UDMA_UMAC_INIT; + struct iwm_umac_cmd umac_cmd; + struct iwm_umac_cmd_stats_req stats_req; + + stats_req.flags = cpu_to_le32(flags); + + umac_cmd.id = UMAC_CMD_OPCODE_STATISTIC_REQUEST; + umac_cmd.resp = 0; + + return iwm_hal_send_umac_cmd(iwm, &udma_cmd, &umac_cmd, &stats_req, + sizeof(struct iwm_umac_cmd_stats_req)); +} + +int iwm_send_umac_channel_list(struct iwm_priv *iwm) +{ + struct iwm_udma_wifi_cmd udma_cmd = UDMA_UMAC_INIT; + struct iwm_umac_cmd umac_cmd; + struct iwm_umac_cmd_get_channel_list *ch_list; + int size = sizeof(struct iwm_umac_cmd_get_channel_list) + + sizeof(struct iwm_umac_channel_info) * 4; + int ret; + + ch_list = kzalloc(size, GFP_KERNEL); + if (!ch_list) { + IWM_ERR(iwm, "Couldn't allocate channel list cmd\n"); + return -ENOMEM; + } + + ch_list->ch[0].band = UMAC_BAND_2GHZ; + ch_list->ch[0].type = UMAC_CHANNEL_WIDTH_20MHZ; + ch_list->ch[0].flags = UMAC_CHANNEL_FLAG_VALID; + + ch_list->ch[1].band = UMAC_BAND_5GHZ; + ch_list->ch[1].type = UMAC_CHANNEL_WIDTH_20MHZ; + ch_list->ch[1].flags = UMAC_CHANNEL_FLAG_VALID; + + ch_list->ch[2].band = UMAC_BAND_2GHZ; + ch_list->ch[2].type = UMAC_CHANNEL_WIDTH_20MHZ; + ch_list->ch[2].flags = UMAC_CHANNEL_FLAG_VALID | UMAC_CHANNEL_FLAG_IBSS; + + ch_list->ch[3].band = UMAC_BAND_5GHZ; + ch_list->ch[3].type = UMAC_CHANNEL_WIDTH_20MHZ; + ch_list->ch[3].flags = UMAC_CHANNEL_FLAG_VALID | UMAC_CHANNEL_FLAG_IBSS; + + ch_list->count = cpu_to_le16(4); + + umac_cmd.id = UMAC_CMD_OPCODE_GET_CHAN_INFO_LIST; + umac_cmd.resp = 1; + + ret = iwm_hal_send_umac_cmd(iwm, &udma_cmd, &umac_cmd, ch_list, size); + + kfree(ch_list); + + return ret; +} + +int iwm_scan_ssids(struct iwm_priv *iwm, struct cfg80211_ssid *ssids, + int ssid_num) +{ + struct iwm_umac_cmd_scan_request req; + int i, ret; + + memset(&req, 0, sizeof(struct iwm_umac_cmd_scan_request)); + + req.hdr.oid = UMAC_WIFI_IF_CMD_SCAN_REQUEST; + req.hdr.buf_size = cpu_to_le16(sizeof(struct iwm_umac_cmd_scan_request) + - sizeof(struct iwm_umac_wifi_if)); + req.type = UMAC_WIFI_IF_SCAN_TYPE_USER; + req.timeout = 2; + req.seq_num = iwm->scan_id; + req.ssid_num = min(ssid_num, UMAC_WIFI_IF_PROBE_OPTION_MAX); + + for (i = 0; i < req.ssid_num; i++) { + memcpy(req.ssids[i].ssid, ssids[i].ssid, ssids[i].ssid_len); + req.ssids[i].ssid_len = ssids[i].ssid_len; + } + + ret = iwm_send_wifi_if_cmd(iwm, &req, sizeof(req), 0); + if (ret) { + IWM_ERR(iwm, "Couldn't send scan request\n"); + return ret; + } + + iwm->scan_id = (iwm->scan_id + 1) % IWM_SCAN_ID_MAX; + + return 0; +} + +int iwm_scan_one_ssid(struct iwm_priv *iwm, u8 *ssid, int ssid_len) +{ + struct cfg80211_ssid one_ssid; + + if (test_and_set_bit(IWM_STATUS_SCANNING, &iwm->status)) + return 0; + + one_ssid.ssid_len = min(ssid_len, IEEE80211_MAX_SSID_LEN); + memcpy(&one_ssid.ssid, ssid, one_ssid.ssid_len); + + return iwm_scan_ssids(iwm, &one_ssid, 1); +} + +int iwm_target_reset(struct iwm_priv *iwm) +{ + struct iwm_udma_nonwifi_cmd target_cmd; + + target_cmd.opcode = UMAC_HDI_OUT_OPCODE_REBOOT; + target_cmd.addr = 0; + target_cmd.op1_sz = 0; + target_cmd.op2 = 0; + target_cmd.handle_by_hw = 0; + target_cmd.resp = 0; + target_cmd.eop = 1; + + return iwm_hal_send_target_cmd(iwm, &target_cmd, NULL); +} + +int iwm_send_umac_stop_resume_tx(struct iwm_priv *iwm, + struct iwm_umac_notif_stop_resume_tx *ntf) +{ + struct iwm_udma_wifi_cmd udma_cmd = UDMA_UMAC_INIT; + struct iwm_umac_cmd umac_cmd; + struct iwm_umac_cmd_stop_resume_tx stp_res_cmd; + struct iwm_sta_info *sta_info; + u8 sta_id = STA_ID_N_COLOR_ID(ntf->sta_id); + int i; + + sta_info = &iwm->sta_table[sta_id]; + if (!sta_info->valid) { + IWM_ERR(iwm, "Invalid STA: %d\n", sta_id); + return -EINVAL; + } + + umac_cmd.id = UMAC_CMD_OPCODE_STOP_RESUME_STA_TX; + umac_cmd.resp = 0; + + stp_res_cmd.flags = ntf->flags; + stp_res_cmd.sta_id = ntf->sta_id; + stp_res_cmd.stop_resume_tid_msk = ntf->stop_resume_tid_msk; + for (i = 0; i < IWM_UMAC_TID_NR; i++) + stp_res_cmd.last_seq_num[i] = + sta_info->tid_info[i].last_seq_num; + + return iwm_hal_send_umac_cmd(iwm, &udma_cmd, &umac_cmd, &stp_res_cmd, + sizeof(struct iwm_umac_cmd_stop_resume_tx)); + +} + +int iwm_send_pmkid_update(struct iwm_priv *iwm, + struct cfg80211_pmksa *pmksa, u32 command) +{ + struct iwm_umac_pmkid_update update; + int ret; + + memset(&update, 0, sizeof(struct iwm_umac_pmkid_update)); + + update.hdr.oid = UMAC_WIFI_IF_CMD_PMKID_UPDATE; + update.hdr.buf_size = cpu_to_le16(sizeof(struct iwm_umac_pmkid_update) - + sizeof(struct iwm_umac_wifi_if)); + + update.command = cpu_to_le32(command); + if (pmksa->bssid) + memcpy(&update.bssid, pmksa->bssid, ETH_ALEN); + if (pmksa->pmkid) + memcpy(&update.pmkid, pmksa->pmkid, WLAN_PMKID_LEN); + + ret = iwm_send_wifi_if_cmd(iwm, &update, + sizeof(struct iwm_umac_pmkid_update), 0); + if (ret) { + IWM_ERR(iwm, "PMKID update command failed\n"); + return ret; + } + + return 0; +} diff --git a/trunk/drivers/net/wireless/iwmc3200wifi/commands.h b/trunk/drivers/net/wireless/iwmc3200wifi/commands.h new file mode 100644 index 000000000000..6421689f5e8e --- /dev/null +++ b/trunk/drivers/net/wireless/iwmc3200wifi/commands.h @@ -0,0 +1,509 @@ +/* + * Intel Wireless Multicomm 3200 WiFi driver + * + * Copyright (C) 2009 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * + * Intel Corporation + * Samuel Ortiz + * Zhu Yi + * + */ + +#ifndef __IWM_COMMANDS_H__ +#define __IWM_COMMANDS_H__ + +#include + +#define IWM_BARKER_REBOOT_NOTIFICATION 0xF +#define IWM_ACK_BARKER_NOTIFICATION 0x10 + +/* UMAC commands */ +#define UMAC_RST_CTRL_FLG_LARC_CLK_EN 0x0001 +#define UMAC_RST_CTRL_FLG_LARC_RESET 0x0002 +#define UMAC_RST_CTRL_FLG_FUNC_RESET 0x0004 +#define UMAC_RST_CTRL_FLG_DEV_RESET 0x0008 +#define UMAC_RST_CTRL_FLG_WIFI_CORE_EN 0x0010 +#define UMAC_RST_CTRL_FLG_WIFI_LINK_EN 0x0040 +#define UMAC_RST_CTRL_FLG_WIFI_MLME_EN 0x0080 +#define UMAC_RST_CTRL_FLG_NVM_RELOAD 0x0100 + +struct iwm_umac_cmd_reset { + __le32 flags; +} __packed; + +#define UMAC_PARAM_TBL_ORD_FIX 0x0 +#define UMAC_PARAM_TBL_ORD_VAR 0x1 +#define UMAC_PARAM_TBL_CFG_FIX 0x2 +#define UMAC_PARAM_TBL_CFG_VAR 0x3 +#define UMAC_PARAM_TBL_BSS_TRK 0x4 +#define UMAC_PARAM_TBL_FA_CFG_FIX 0x5 +#define UMAC_PARAM_TBL_STA 0x6 +#define UMAC_PARAM_TBL_CHN 0x7 +#define UMAC_PARAM_TBL_STATISTICS 0x8 + +/* fast access table */ +enum { + CFG_FRAG_THRESHOLD = 0, + CFG_FRAME_RETRY_LIMIT, + CFG_OS_QUEUE_UTIL_TH, + CFG_RX_FILTER, + /* <-- LAST --> */ + FAST_ACCESS_CFG_TBL_FIX_LAST +}; + +/* fixed size table */ +enum { + CFG_POWER_INDEX = 0, + CFG_PM_LEGACY_RX_TIMEOUT, + CFG_PM_LEGACY_TX_TIMEOUT, + CFG_PM_CTRL_FLAGS, + CFG_PM_KEEP_ALIVE_IN_BEACONS, + CFG_BT_ON_THRESHOLD, + CFG_RTS_THRESHOLD, + CFG_CTS_TO_SELF, + CFG_COEX_MODE, + CFG_WIRELESS_MODE, + CFG_ASSOCIATION_TIMEOUT, + CFG_ROAM_TIMEOUT, + CFG_CAPABILITY_SUPPORTED_RATES, + CFG_SCAN_ALLOWED_UNASSOC_FLAGS, + CFG_SCAN_ALLOWED_MAIN_ASSOC_FLAGS, + CFG_SCAN_ALLOWED_PAN_ASSOC_FLAGS, + CFG_SCAN_INTERNAL_PERIODIC_ENABLED, + CFG_SCAN_IMM_INTERNAL_PERIODIC_SCAN_ON_INIT, + CFG_SCAN_DEFAULT_PERIODIC_FREQ_SEC, + CFG_SCAN_NUM_PASSIVE_CHAN_PER_PARTIAL_SCAN, + CFG_TLC_SUPPORTED_TX_HT_RATES, + CFG_TLC_SUPPORTED_TX_RATES, + CFG_TLC_SPATIAL_STREAM_SUPPORTED, + CFG_TLC_RETRY_PER_RATE, + CFG_TLC_RETRY_PER_HT_RATE, + CFG_TLC_FIXED_MCS, + CFG_TLC_CONTROL_FLAGS, + CFG_TLC_SR_MIN_FAIL, + CFG_TLC_SR_MIN_PASS, + CFG_TLC_HT_STAY_IN_COL_PASS_THRESH, + CFG_TLC_HT_STAY_IN_COL_FAIL_THRESH, + CFG_TLC_LEGACY_STAY_IN_COL_PASS_THRESH, + CFG_TLC_LEGACY_STAY_IN_COL_FAIL_THRESH, + CFG_TLC_HT_FLUSH_STATS_PACKETS, + CFG_TLC_LEGACY_FLUSH_STATS_PACKETS, + CFG_TLC_LEGACY_FLUSH_STATS_MS, + CFG_TLC_HT_FLUSH_STATS_MS, + CFG_TLC_STAY_IN_COL_TIME_OUT, + CFG_TLC_AGG_SHORT_LIM, + CFG_TLC_AGG_LONG_LIM, + CFG_TLC_HT_SR_NO_DECREASE, + CFG_TLC_LEGACY_SR_NO_DECREASE, + CFG_TLC_SR_FORCE_DECREASE, + CFG_TLC_SR_ALLOW_INCREASE, + CFG_TLC_AGG_SET_LONG, + CFG_TLC_AUTO_AGGREGATION, + CFG_TLC_AGG_THRESHOLD, + CFG_TLC_TID_LOAD_THRESHOLD, + CFG_TLC_BLOCK_ACK_TIMEOUT, + CFG_TLC_NO_BA_COUNTED_AS_ONE, + CFG_TLC_NUM_BA_STREAMS_ALLOWED, + CFG_TLC_NUM_BA_STREAMS_PRESENT, + CFG_TLC_RENEW_ADDBA_DELAY, + CFG_TLC_NUM_OF_MULTISEC_TO_COUN_LOAD, + CFG_TLC_IS_STABLE_IN_HT, + CFG_TLC_SR_SIC_1ST_FAIL, + CFG_TLC_SR_SIC_1ST_PASS, + CFG_TLC_SR_SIC_TOTAL_FAIL, + CFG_TLC_SR_SIC_TOTAL_PASS, + CFG_RLC_CHAIN_CTRL, + CFG_TRK_TABLE_OP_MODE, + CFG_TRK_TABLE_RSSI_THRESHOLD, + CFG_TX_PWR_TARGET, /* Used By xVT */ + CFG_TX_PWR_LIMIT_USR, + CFG_TX_PWR_LIMIT_BSS, /* 11d limit */ + CFG_TX_PWR_LIMIT_BSS_CONSTRAINT, /* 11h constraint */ + CFG_TX_PWR_MODE, + CFG_MLME_DBG_NOTIF_BLOCK, + CFG_BT_OFF_BECONS_INTERVALS, + CFG_BT_FRAG_DURATION, + CFG_ACTIVE_CHAINS, + CFG_CALIB_CTRL, + CFG_CAPABILITY_SUPPORTED_HT_RATES, + CFG_HT_MAC_PARAM_INFO, + CFG_MIMO_PS_MODE, + CFG_HT_DEFAULT_CAPABILIES_INFO, + CFG_LED_SC_RESOLUTION_FACTOR, + CFG_PTAM_ENERGY_CCK_DET_DEFAULT, + CFG_PTAM_CORR40_4_TH_ADD_MIN_MRC_DEFAULT, + CFG_PTAM_CORR40_4_TH_ADD_MIN_DEFAULT, + CFG_PTAM_CORR32_4_TH_ADD_MIN_MRC_DEFAULT, + CFG_PTAM_CORR32_4_TH_ADD_MIN_DEFAULT, + CFG_PTAM_CORR32_1_TH_ADD_MIN_MRC_DEFAULT, + CFG_PTAM_CORR32_1_TH_ADD_MIN_DEFAULT, + CFG_PTAM_ENERGY_CCK_DET_MIN_VAL, + CFG_PTAM_CORR40_4_TH_ADD_MIN_MRC_MIN_VAL, + CFG_PTAM_CORR40_4_TH_ADD_MIN_MIN_VAL, + CFG_PTAM_CORR32_4_TH_ADD_MIN_MRC_MIN_VAL, + CFG_PTAM_CORR32_4_TH_ADD_MIN_MIN_VAL, + CFG_PTAM_CORR32_1_TH_ADD_MIN_MRC_MIN_VAL, + CFG_PTAM_CORR32_1_TH_ADD_MIN_MIN_VAL, + CFG_PTAM_ENERGY_CCK_DET_MAX_VAL, + CFG_PTAM_CORR40_4_TH_ADD_MIN_MRC_MAX_VAL, + CFG_PTAM_CORR40_4_TH_ADD_MIN_MAX_VAL, + CFG_PTAM_CORR32_4_TH_ADD_MIN_MRC_MAX_VAL, + CFG_PTAM_CORR32_4_TH_ADD_MIN_MAX_VAL, + CFG_PTAM_CORR32_1_TH_ADD_MIN_MRC_MAX_VAL, + CFG_PTAM_CORR32_1_TH_ADD_MIN_MAX_VAL, + CFG_PTAM_ENERGY_CCK_DET_STEP_VAL, + CFG_PTAM_CORR40_4_TH_ADD_MIN_MRC_STEP_VAL, + CFG_PTAM_CORR40_4_TH_ADD_MIN_STEP_VAL, + CFG_PTAM_CORR32_4_TH_ADD_MIN_MRC_STEP_VAL, + CFG_PTAM_CORR32_4_TH_ADD_MIN_STEP_VAL, + CFG_PTAM_CORR32_1_TH_ADD_MIN_MRC_STEP_VAL, + CFG_PTAM_CORR32_1_TH_ADD_MIN_STEP_VAL, + CFG_PTAM_LINK_SENS_FA_OFDM_MAX, + CFG_PTAM_LINK_SENS_FA_OFDM_MIN, + CFG_PTAM_LINK_SENS_FA_CCK_MAX, + CFG_PTAM_LINK_SENS_FA_CCK_MIN, + CFG_PTAM_LINK_SENS_NRG_DIFF, + CFG_PTAM_LINK_SENS_NRG_MARGIN, + CFG_PTAM_LINK_SENS_MAX_NUMBER_OF_TIMES_IN_CCK_NO_FA, + CFG_PTAM_LINK_SENS_AUTO_CORR_MAX_TH_CCK, + CFG_AGG_MGG_TID_LOAD_ADDBA_THRESHOLD, + CFG_AGG_MGG_TID_LOAD_DELBA_THRESHOLD, + CFG_AGG_MGG_ADDBA_BUF_SIZE, + CFG_AGG_MGG_ADDBA_INACTIVE_TIMEOUT, + CFG_AGG_MGG_ADDBA_DEBUG_FLAGS, + CFG_SCAN_PERIODIC_RSSI_HIGH_THRESHOLD, + CFG_SCAN_PERIODIC_COEF_RSSI_HIGH, + CFG_11D_ENABLED, + CFG_11H_FEATURE_FLAGS, + + /* <-- LAST --> */ + CFG_TBL_FIX_LAST +}; + +/* variable size table */ +enum { + CFG_NET_ADDR = 0, + CFG_LED_PATTERN_TABLE, + + /* <-- LAST --> */ + CFG_TBL_VAR_LAST +}; + +struct iwm_umac_cmd_set_param_fix { + __le16 tbl; + __le16 key; + __le32 value; +} __packed; + +struct iwm_umac_cmd_set_param_var { + __le16 tbl; + __le16 key; + __le16 len; + __le16 reserved; +} __packed; + +struct iwm_umac_cmd_get_param { + __le16 tbl; + __le16 key; +} __packed; + +struct iwm_umac_cmd_get_param_resp { + __le16 tbl; + __le16 key; + __le16 len; + __le16 reserved; +} __packed; + +struct iwm_umac_cmd_eeprom_proxy_hdr { + __le32 type; + __le32 offset; + __le32 len; +} __packed; + +struct iwm_umac_cmd_eeprom_proxy { + struct iwm_umac_cmd_eeprom_proxy_hdr hdr; + u8 buf[0]; +} __packed; + +#define IWM_UMAC_CMD_EEPROM_TYPE_READ 0x1 +#define IWM_UMAC_CMD_EEPROM_TYPE_WRITE 0x2 + +#define UMAC_CHANNEL_FLAG_VALID BIT(0) +#define UMAC_CHANNEL_FLAG_IBSS BIT(1) +#define UMAC_CHANNEL_FLAG_ACTIVE BIT(3) +#define UMAC_CHANNEL_FLAG_RADAR BIT(4) +#define UMAC_CHANNEL_FLAG_DFS BIT(7) + +struct iwm_umac_channel_info { + u8 band; + u8 type; + u8 reserved; + u8 flags; + __le32 channels_mask; +} __packed; + +struct iwm_umac_cmd_get_channel_list { + __le16 count; + __le16 reserved; + struct iwm_umac_channel_info ch[0]; +} __packed; + + +/* UMAC WiFi interface commands */ + +/* Coexistence mode */ +#define COEX_MODE_SA 0x1 +#define COEX_MODE_XOR 0x2 +#define COEX_MODE_CM 0x3 +#define COEX_MODE_MAX 0x4 + +/* Wireless mode */ +#define WIRELESS_MODE_11A 0x1 +#define WIRELESS_MODE_11G 0x2 +#define WIRELESS_MODE_11N 0x4 + +#define UMAC_PROFILE_EX_IE_REQUIRED 0x1 +#define UMAC_PROFILE_QOS_ALLOWED 0x2 + +/* Scanning */ +#define UMAC_WIFI_IF_PROBE_OPTION_MAX 10 + +#define UMAC_WIFI_IF_SCAN_TYPE_USER 0x0 +#define UMAC_WIFI_IF_SCAN_TYPE_UMAC_RESERVED 0x1 +#define UMAC_WIFI_IF_SCAN_TYPE_HOST_PERIODIC 0x2 +#define UMAC_WIFI_IF_SCAN_TYPE_MAX 0x3 + +struct iwm_umac_ssid { + u8 ssid_len; + u8 ssid[IEEE80211_MAX_SSID_LEN]; + u8 reserved[3]; +} __packed; + +struct iwm_umac_cmd_scan_request { + struct iwm_umac_wifi_if hdr; + __le32 type; /* UMAC_WIFI_IF_SCAN_TYPE_* */ + u8 ssid_num; + u8 seq_num; + u8 timeout; /* In seconds */ + u8 reserved; + struct iwm_umac_ssid ssids[UMAC_WIFI_IF_PROBE_OPTION_MAX]; +} __packed; + +#define UMAC_CIPHER_TYPE_NONE 0xFF +#define UMAC_CIPHER_TYPE_USE_GROUPCAST 0x00 +#define UMAC_CIPHER_TYPE_WEP_40 0x01 +#define UMAC_CIPHER_TYPE_WEP_104 0x02 +#define UMAC_CIPHER_TYPE_TKIP 0x04 +#define UMAC_CIPHER_TYPE_CCMP 0x08 + +/* Supported authentication types - bitmap */ +#define UMAC_AUTH_TYPE_OPEN 0x00 +#define UMAC_AUTH_TYPE_LEGACY_PSK 0x01 +#define UMAC_AUTH_TYPE_8021X 0x02 +#define UMAC_AUTH_TYPE_RSNA_PSK 0x04 + +/* iwm_umac_security.flag is WPA supported -- bits[0:0] */ +#define UMAC_SEC_FLG_WPA_ON_POS 0 +#define UMAC_SEC_FLG_WPA_ON_SEED 1 +#define UMAC_SEC_FLG_WPA_ON_MSK (UMAC_SEC_FLG_WPA_ON_SEED << \ + UMAC_SEC_FLG_WPA_ON_POS) + +/* iwm_umac_security.flag is WPA2 supported -- bits [1:1] */ +#define UMAC_SEC_FLG_RSNA_ON_POS 1 +#define UMAC_SEC_FLG_RSNA_ON_SEED 1 +#define UMAC_SEC_FLG_RSNA_ON_MSK (UMAC_SEC_FLG_RSNA_ON_SEED << \ + UMAC_SEC_FLG_RSNA_ON_POS) + +/* iwm_umac_security.flag is WSC mode on -- bits [2:2] */ +#define UMAC_SEC_FLG_WSC_ON_POS 2 +#define UMAC_SEC_FLG_WSC_ON_SEED 1 +#define UMAC_SEC_FLG_WSC_ON_MSK (UMAC_SEC_FLG_WSC_ON_SEED << \ + UMAC_SEC_FLG_WSC_ON_POS) + + +/* Legacy profile can use only WEP40 and WEP104 for encryption and + * OPEN or PSK for authentication */ +#define UMAC_SEC_FLG_LEGACY_PROFILE 0 + +struct iwm_umac_security { + u8 auth_type; + u8 ucast_cipher; + u8 mcast_cipher; + u8 flags; +} __packed; + +struct iwm_umac_ibss { + u8 beacon_interval; /* in millisecond */ + u8 atim; /* in millisecond */ + s8 join_only; + u8 band; + u8 channel; + u8 reserved[3]; +} __packed; + +#define UMAC_MODE_BSS 0 +#define UMAC_MODE_IBSS 1 + +#define UMAC_BSSID_MAX 4 + +struct iwm_umac_profile { + struct iwm_umac_wifi_if hdr; + __le32 mode; + struct iwm_umac_ssid ssid; + u8 bssid[UMAC_BSSID_MAX][ETH_ALEN]; + struct iwm_umac_security sec; + struct iwm_umac_ibss ibss; + __le32 channel_2ghz; + __le32 channel_5ghz; + __le16 flags; + u8 wireless_mode; + u8 bss_num; +} __packed; + +struct iwm_umac_invalidate_profile { + struct iwm_umac_wifi_if hdr; + u8 reason; + u8 reserved[3]; +} __packed; + +/* Encryption key commands */ +struct iwm_umac_key_wep40 { + struct iwm_umac_wifi_if hdr; + struct iwm_umac_key_hdr key_hdr; + u8 key[WLAN_KEY_LEN_WEP40]; + u8 static_key; + u8 reserved[2]; +} __packed; + +struct iwm_umac_key_wep104 { + struct iwm_umac_wifi_if hdr; + struct iwm_umac_key_hdr key_hdr; + u8 key[WLAN_KEY_LEN_WEP104]; + u8 static_key; + u8 reserved[2]; +} __packed; + +#define IWM_TKIP_KEY_SIZE 16 +#define IWM_TKIP_MIC_SIZE 8 +struct iwm_umac_key_tkip { + struct iwm_umac_wifi_if hdr; + struct iwm_umac_key_hdr key_hdr; + u8 iv_count[6]; + u8 reserved[2]; + u8 tkip_key[IWM_TKIP_KEY_SIZE]; + u8 mic_rx_key[IWM_TKIP_MIC_SIZE]; + u8 mic_tx_key[IWM_TKIP_MIC_SIZE]; +} __packed; + +struct iwm_umac_key_ccmp { + struct iwm_umac_wifi_if hdr; + struct iwm_umac_key_hdr key_hdr; + u8 iv_count[6]; + u8 reserved[2]; + u8 key[WLAN_KEY_LEN_CCMP]; +} __packed; + +struct iwm_umac_key_remove { + struct iwm_umac_wifi_if hdr; + struct iwm_umac_key_hdr key_hdr; +} __packed; + +struct iwm_umac_tx_key_id { + struct iwm_umac_wifi_if hdr; + u8 key_idx; + u8 reserved[3]; +} __packed; + +struct iwm_umac_pwr_trigger { + struct iwm_umac_wifi_if hdr; + __le32 reseved; +} __packed; + +struct iwm_umac_cmd_stats_req { + __le32 flags; +} __packed; + +struct iwm_umac_cmd_stop_resume_tx { + u8 flags; + u8 sta_id; + __le16 stop_resume_tid_msk; + __le16 last_seq_num[IWM_UMAC_TID_NR]; + u16 reserved; +} __packed; + +#define IWM_CMD_PMKID_ADD 1 +#define IWM_CMD_PMKID_DEL 2 +#define IWM_CMD_PMKID_FLUSH 3 + +struct iwm_umac_pmkid_update { + struct iwm_umac_wifi_if hdr; + __le32 command; + u8 bssid[ETH_ALEN]; + __le16 reserved; + u8 pmkid[WLAN_PMKID_LEN]; +} __packed; + +/* LMAC commands */ +int iwm_read_mac(struct iwm_priv *iwm, u8 *mac); +int iwm_send_prio_table(struct iwm_priv *iwm); +int iwm_send_init_calib_cfg(struct iwm_priv *iwm, u8 calib_requested); +int iwm_send_periodic_calib_cfg(struct iwm_priv *iwm, u8 calib_requested); +int iwm_send_calib_results(struct iwm_priv *iwm); +int iwm_store_rxiq_calib_result(struct iwm_priv *iwm); +int iwm_send_ct_kill_cfg(struct iwm_priv *iwm, u8 entry, u8 exit); + +/* UMAC commands */ +int iwm_send_wifi_if_cmd(struct iwm_priv *iwm, void *payload, u16 payload_size, + bool resp); +int iwm_send_umac_reset(struct iwm_priv *iwm, __le32 reset_flags, bool resp); +int iwm_umac_set_config_fix(struct iwm_priv *iwm, u16 tbl, u16 key, u32 value); +int iwm_umac_set_config_var(struct iwm_priv *iwm, u16 key, + void *payload, u16 payload_size); +int iwm_send_umac_config(struct iwm_priv *iwm, __le32 reset_flags); +int iwm_send_mlme_profile(struct iwm_priv *iwm); +int __iwm_invalidate_mlme_profile(struct iwm_priv *iwm); +int iwm_invalidate_mlme_profile(struct iwm_priv *iwm); +int iwm_send_packet(struct iwm_priv *iwm, struct sk_buff *skb, int pool_id); +int iwm_set_tx_key(struct iwm_priv *iwm, u8 key_idx); +int iwm_set_key(struct iwm_priv *iwm, bool remove, struct iwm_key *key); +int iwm_tx_power_trigger(struct iwm_priv *iwm); +int iwm_send_umac_stats_req(struct iwm_priv *iwm, u32 flags); +int iwm_send_umac_channel_list(struct iwm_priv *iwm); +int iwm_scan_ssids(struct iwm_priv *iwm, struct cfg80211_ssid *ssids, + int ssid_num); +int iwm_scan_one_ssid(struct iwm_priv *iwm, u8 *ssid, int ssid_len); +int iwm_send_umac_stop_resume_tx(struct iwm_priv *iwm, + struct iwm_umac_notif_stop_resume_tx *ntf); +int iwm_send_pmkid_update(struct iwm_priv *iwm, + struct cfg80211_pmksa *pmksa, u32 command); + +/* UDMA commands */ +int iwm_target_reset(struct iwm_priv *iwm); +#endif diff --git a/trunk/drivers/net/wireless/iwmc3200wifi/debug.h b/trunk/drivers/net/wireless/iwmc3200wifi/debug.h new file mode 100644 index 000000000000..a0c13a49ab3c --- /dev/null +++ b/trunk/drivers/net/wireless/iwmc3200wifi/debug.h @@ -0,0 +1,123 @@ +/* + * Intel Wireless Multicomm 3200 WiFi driver + * + * Copyright (C) 2009 Intel Corporation + * Samuel Ortiz + * Zhu Yi + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + * + */ + +#ifndef __IWM_DEBUG_H__ +#define __IWM_DEBUG_H__ + +#define IWM_ERR(p, f, a...) dev_err(iwm_to_dev(p), f, ## a) +#define IWM_WARN(p, f, a...) dev_warn(iwm_to_dev(p), f, ## a) +#define IWM_INFO(p, f, a...) dev_info(iwm_to_dev(p), f, ## a) +#define IWM_CRIT(p, f, a...) dev_crit(iwm_to_dev(p), f, ## a) + +#ifdef CONFIG_IWM_DEBUG + +#define IWM_DEBUG_MODULE(i, level, module, f, a...) \ +do { \ + if (unlikely(i->dbg.dbg_module[IWM_DM_##module] >= (IWM_DL_##level)))\ + dev_printk(KERN_INFO, (iwm_to_dev(i)), \ + "%s " f, __func__ , ## a); \ +} while (0) + +#define IWM_HEXDUMP(i, level, module, pref, buf, len) \ +do { \ + if (unlikely(i->dbg.dbg_module[IWM_DM_##module] >= (IWM_DL_##level)))\ + print_hex_dump(KERN_INFO, pref, DUMP_PREFIX_OFFSET, \ + 16, 1, buf, len, 1); \ +} while (0) + +#else + +#define IWM_DEBUG_MODULE(i, level, module, f, a...) +#define IWM_HEXDUMP(i, level, module, pref, buf, len) + +#endif /* CONFIG_IWM_DEBUG */ + +/* Debug modules */ +enum iwm_debug_module_id { + IWM_DM_BOOT = 0, + IWM_DM_FW, + IWM_DM_SDIO, + IWM_DM_NTF, + IWM_DM_RX, + IWM_DM_TX, + IWM_DM_MLME, + IWM_DM_CMD, + IWM_DM_WEXT, + __IWM_DM_NR, +}; +#define IWM_DM_DEFAULT 0 + +#define IWM_DBG_BOOT(i, l, f, a...) IWM_DEBUG_MODULE(i, l, BOOT, f, ## a) +#define IWM_DBG_FW(i, l, f, a...) IWM_DEBUG_MODULE(i, l, FW, f, ## a) +#define IWM_DBG_SDIO(i, l, f, a...) IWM_DEBUG_MODULE(i, l, SDIO, f, ## a) +#define IWM_DBG_NTF(i, l, f, a...) IWM_DEBUG_MODULE(i, l, NTF, f, ## a) +#define IWM_DBG_RX(i, l, f, a...) IWM_DEBUG_MODULE(i, l, RX, f, ## a) +#define IWM_DBG_TX(i, l, f, a...) IWM_DEBUG_MODULE(i, l, TX, f, ## a) +#define IWM_DBG_MLME(i, l, f, a...) IWM_DEBUG_MODULE(i, l, MLME, f, ## a) +#define IWM_DBG_CMD(i, l, f, a...) IWM_DEBUG_MODULE(i, l, CMD, f, ## a) +#define IWM_DBG_WEXT(i, l, f, a...) IWM_DEBUG_MODULE(i, l, WEXT, f, ## a) + +/* Debug levels */ +enum iwm_debug_level { + IWM_DL_NONE = 0, + IWM_DL_ERR, + IWM_DL_WARN, + IWM_DL_INFO, + IWM_DL_DBG, +}; +#define IWM_DL_DEFAULT IWM_DL_ERR + +struct iwm_debugfs { + struct iwm_priv *iwm; + struct dentry *rootdir; + struct dentry *devdir; + struct dentry *dbgdir; + struct dentry *txdir; + struct dentry *rxdir; + struct dentry *busdir; + + u32 dbg_level; + struct dentry *dbg_level_dentry; + + unsigned long dbg_modules; + struct dentry *dbg_modules_dentry; + + u8 dbg_module[__IWM_DM_NR]; + struct dentry *dbg_module_dentries[__IWM_DM_NR]; + + struct dentry *txq_dentry; + struct dentry *tx_credit_dentry; + struct dentry *rx_ticket_dentry; + + struct dentry *fw_err_dentry; +}; + +#ifdef CONFIG_IWM_DEBUG +void iwm_debugfs_init(struct iwm_priv *iwm); +void iwm_debugfs_exit(struct iwm_priv *iwm); +#else +static inline void iwm_debugfs_init(struct iwm_priv *iwm) {} +static inline void iwm_debugfs_exit(struct iwm_priv *iwm) {} +#endif + +#endif diff --git a/trunk/drivers/net/wireless/iwmc3200wifi/debugfs.c b/trunk/drivers/net/wireless/iwmc3200wifi/debugfs.c new file mode 100644 index 000000000000..b6199d124bb9 --- /dev/null +++ b/trunk/drivers/net/wireless/iwmc3200wifi/debugfs.c @@ -0,0 +1,488 @@ +/* + * Intel Wireless Multicomm 3200 WiFi driver + * + * Copyright (C) 2009 Intel Corporation + * Samuel Ortiz + * Zhu Yi + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + * + */ + +#include +#include +#include +#include +#include + +#include "iwm.h" +#include "bus.h" +#include "rx.h" +#include "debug.h" + +static struct { + u8 id; + char *name; +} iwm_debug_module[__IWM_DM_NR] = { + {IWM_DM_BOOT, "boot"}, + {IWM_DM_FW, "fw"}, + {IWM_DM_SDIO, "sdio"}, + {IWM_DM_NTF, "ntf"}, + {IWM_DM_RX, "rx"}, + {IWM_DM_TX, "tx"}, + {IWM_DM_MLME, "mlme"}, + {IWM_DM_CMD, "cmd"}, + {IWM_DM_WEXT, "wext"}, +}; + +#define add_dbg_module(dbg, name, id, initlevel) \ +do { \ + dbg.dbg_module[id] = (initlevel); \ + dbg.dbg_module_dentries[id] = \ + debugfs_create_x8(name, 0600, \ + dbg.dbgdir, \ + &(dbg.dbg_module[id])); \ +} while (0) + +static int iwm_debugfs_u32_read(void *data, u64 *val) +{ + struct iwm_priv *iwm = data; + + *val = iwm->dbg.dbg_level; + return 0; +} + +static int iwm_debugfs_dbg_level_write(void *data, u64 val) +{ + struct iwm_priv *iwm = data; + int i; + + iwm->dbg.dbg_level = val; + + for (i = 0; i < __IWM_DM_NR; i++) + iwm->dbg.dbg_module[i] = val; + + return 0; +} +DEFINE_SIMPLE_ATTRIBUTE(fops_iwm_dbg_level, + iwm_debugfs_u32_read, iwm_debugfs_dbg_level_write, + "%llu\n"); + +static int iwm_debugfs_dbg_modules_write(void *data, u64 val) +{ + struct iwm_priv *iwm = data; + int i, bit; + + iwm->dbg.dbg_modules = val; + + for (i = 0; i < __IWM_DM_NR; i++) + iwm->dbg.dbg_module[i] = 0; + + for_each_set_bit(bit, &iwm->dbg.dbg_modules, __IWM_DM_NR) + iwm->dbg.dbg_module[bit] = iwm->dbg.dbg_level; + + return 0; +} +DEFINE_SIMPLE_ATTRIBUTE(fops_iwm_dbg_modules, + iwm_debugfs_u32_read, iwm_debugfs_dbg_modules_write, + "%llu\n"); + + +static ssize_t iwm_debugfs_txq_read(struct file *filp, char __user *buffer, + size_t count, loff_t *ppos) +{ + struct iwm_priv *iwm = filp->private_data; + char *buf; + int i, buf_len = 4096; + size_t len = 0; + ssize_t ret; + + if (*ppos != 0) + return 0; + if (count < sizeof(buf)) + return -ENOSPC; + + buf = kzalloc(buf_len, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + for (i = 0; i < IWM_TX_QUEUES; i++) { + struct iwm_tx_queue *txq = &iwm->txq[i]; + struct sk_buff *skb; + int j; + unsigned long flags; + + spin_lock_irqsave(&txq->queue.lock, flags); + + skb = (struct sk_buff *)&txq->queue; + + len += snprintf(buf + len, buf_len - len, "TXQ #%d\n", i); + len += snprintf(buf + len, buf_len - len, "\tStopped: %d\n", + __netif_subqueue_stopped(iwm_to_ndev(iwm), + txq->id)); + len += snprintf(buf + len, buf_len - len, "\tConcat count:%d\n", + txq->concat_count); + len += snprintf(buf + len, buf_len - len, "\tQueue len: %d\n", + skb_queue_len(&txq->queue)); + for (j = 0; j < skb_queue_len(&txq->queue); j++) { + struct iwm_tx_info *tx_info; + + skb = skb->next; + tx_info = skb_to_tx_info(skb); + + len += snprintf(buf + len, buf_len - len, + "\tSKB #%d\n", j); + len += snprintf(buf + len, buf_len - len, + "\t\tsta: %d\n", tx_info->sta); + len += snprintf(buf + len, buf_len - len, + "\t\tcolor: %d\n", tx_info->color); + len += snprintf(buf + len, buf_len - len, + "\t\ttid: %d\n", tx_info->tid); + } + + spin_unlock_irqrestore(&txq->queue.lock, flags); + + spin_lock_irqsave(&txq->stopped_queue.lock, flags); + + len += snprintf(buf + len, buf_len - len, + "\tStopped Queue len: %d\n", + skb_queue_len(&txq->stopped_queue)); + for (j = 0; j < skb_queue_len(&txq->stopped_queue); j++) { + struct iwm_tx_info *tx_info; + + skb = skb->next; + tx_info = skb_to_tx_info(skb); + + len += snprintf(buf + len, buf_len - len, + "\tSKB #%d\n", j); + len += snprintf(buf + len, buf_len - len, + "\t\tsta: %d\n", tx_info->sta); + len += snprintf(buf + len, buf_len - len, + "\t\tcolor: %d\n", tx_info->color); + len += snprintf(buf + len, buf_len - len, + "\t\ttid: %d\n", tx_info->tid); + } + + spin_unlock_irqrestore(&txq->stopped_queue.lock, flags); + } + + ret = simple_read_from_buffer(buffer, len, ppos, buf, buf_len); + kfree(buf); + + return ret; +} + +static ssize_t iwm_debugfs_tx_credit_read(struct file *filp, + char __user *buffer, + size_t count, loff_t *ppos) +{ + struct iwm_priv *iwm = filp->private_data; + struct iwm_tx_credit *credit = &iwm->tx_credit; + char *buf; + int i, buf_len = 4096; + size_t len = 0; + ssize_t ret; + + if (*ppos != 0) + return 0; + if (count < sizeof(buf)) + return -ENOSPC; + + buf = kzalloc(buf_len, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + len += snprintf(buf + len, buf_len - len, + "NR pools: %d\n", credit->pool_nr); + len += snprintf(buf + len, buf_len - len, + "pools map: 0x%lx\n", credit->full_pools_map); + + len += snprintf(buf + len, buf_len - len, "\n### POOLS ###\n"); + for (i = 0; i < IWM_MACS_OUT_GROUPS; i++) { + len += snprintf(buf + len, buf_len - len, + "pools entry #%d\n", i); + len += snprintf(buf + len, buf_len - len, + "\tid: %d\n", + credit->pools[i].id); + len += snprintf(buf + len, buf_len - len, + "\tsid: %d\n", + credit->pools[i].sid); + len += snprintf(buf + len, buf_len - len, + "\tmin_pages: %d\n", + credit->pools[i].min_pages); + len += snprintf(buf + len, buf_len - len, + "\tmax_pages: %d\n", + credit->pools[i].max_pages); + len += snprintf(buf + len, buf_len - len, + "\talloc_pages: %d\n", + credit->pools[i].alloc_pages); + len += snprintf(buf + len, buf_len - len, + "\tfreed_pages: %d\n", + credit->pools[i].total_freed_pages); + } + + len += snprintf(buf + len, buf_len - len, "\n### SPOOLS ###\n"); + for (i = 0; i < IWM_MACS_OUT_SGROUPS; i++) { + len += snprintf(buf + len, buf_len - len, + "spools entry #%d\n", i); + len += snprintf(buf + len, buf_len - len, + "\tid: %d\n", + credit->spools[i].id); + len += snprintf(buf + len, buf_len - len, + "\tmax_pages: %d\n", + credit->spools[i].max_pages); + len += snprintf(buf + len, buf_len - len, + "\talloc_pages: %d\n", + credit->spools[i].alloc_pages); + + } + + ret = simple_read_from_buffer(buffer, len, ppos, buf, buf_len); + kfree(buf); + + return ret; +} + +static ssize_t iwm_debugfs_rx_ticket_read(struct file *filp, + char __user *buffer, + size_t count, loff_t *ppos) +{ + struct iwm_priv *iwm = filp->private_data; + struct iwm_rx_ticket_node *ticket; + char *buf; + int buf_len = 4096, i; + size_t len = 0; + ssize_t ret; + + if (*ppos != 0) + return 0; + if (count < sizeof(buf)) + return -ENOSPC; + + buf = kzalloc(buf_len, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + spin_lock(&iwm->ticket_lock); + list_for_each_entry(ticket, &iwm->rx_tickets, node) { + len += snprintf(buf + len, buf_len - len, "Ticket #%d\n", + ticket->ticket->id); + len += snprintf(buf + len, buf_len - len, "\taction: 0x%x\n", + ticket->ticket->action); + len += snprintf(buf + len, buf_len - len, "\tflags: 0x%x\n", + ticket->ticket->flags); + } + spin_unlock(&iwm->ticket_lock); + + for (i = 0; i < IWM_RX_ID_HASH; i++) { + struct iwm_rx_packet *packet; + struct list_head *pkt_list = &iwm->rx_packets[i]; + + if (!list_empty(pkt_list)) { + len += snprintf(buf + len, buf_len - len, + "Packet hash #%d\n", i); + spin_lock(&iwm->packet_lock[i]); + list_for_each_entry(packet, pkt_list, node) { + len += snprintf(buf + len, buf_len - len, + "\tPacket id: %d\n", + packet->id); + len += snprintf(buf + len, buf_len - len, + "\tPacket length: %lu\n", + packet->pkt_size); + } + spin_unlock(&iwm->packet_lock[i]); + } + } + + ret = simple_read_from_buffer(buffer, len, ppos, buf, buf_len); + kfree(buf); + + return ret; +} + +static ssize_t iwm_debugfs_fw_err_read(struct file *filp, + char __user *buffer, + size_t count, loff_t *ppos) +{ + + struct iwm_priv *iwm = filp->private_data; + char buf[512]; + int buf_len = 512; + size_t len = 0; + + if (*ppos != 0) + return 0; + if (count < sizeof(buf)) + return -ENOSPC; + + if (!iwm->last_fw_err) + return -ENOMEM; + + if (iwm->last_fw_err->line_num == 0) + goto out; + + len += snprintf(buf + len, buf_len - len, "%cMAC FW ERROR:\n", + (le32_to_cpu(iwm->last_fw_err->category) == UMAC_SYS_ERR_CAT_LMAC) + ? 'L' : 'U'); + len += snprintf(buf + len, buf_len - len, + "\tCategory: %d\n", + le32_to_cpu(iwm->last_fw_err->category)); + + len += snprintf(buf + len, buf_len - len, + "\tStatus: 0x%x\n", + le32_to_cpu(iwm->last_fw_err->status)); + + len += snprintf(buf + len, buf_len - len, + "\tPC: 0x%x\n", + le32_to_cpu(iwm->last_fw_err->pc)); + + len += snprintf(buf + len, buf_len - len, + "\tblink1: %d\n", + le32_to_cpu(iwm->last_fw_err->blink1)); + + len += snprintf(buf + len, buf_len - len, + "\tblink2: %d\n", + le32_to_cpu(iwm->last_fw_err->blink2)); + + len += snprintf(buf + len, buf_len - len, + "\tilink1: %d\n", + le32_to_cpu(iwm->last_fw_err->ilink1)); + + len += snprintf(buf + len, buf_len - len, + "\tilink2: %d\n", + le32_to_cpu(iwm->last_fw_err->ilink2)); + + len += snprintf(buf + len, buf_len - len, + "\tData1: 0x%x\n", + le32_to_cpu(iwm->last_fw_err->data1)); + + len += snprintf(buf + len, buf_len - len, + "\tData2: 0x%x\n", + le32_to_cpu(iwm->last_fw_err->data2)); + + len += snprintf(buf + len, buf_len - len, + "\tLine number: %d\n", + le32_to_cpu(iwm->last_fw_err->line_num)); + + len += snprintf(buf + len, buf_len - len, + "\tUMAC status: 0x%x\n", + le32_to_cpu(iwm->last_fw_err->umac_status)); + + len += snprintf(buf + len, buf_len - len, + "\tLMAC status: 0x%x\n", + le32_to_cpu(iwm->last_fw_err->lmac_status)); + + len += snprintf(buf + len, buf_len - len, + "\tSDIO status: 0x%x\n", + le32_to_cpu(iwm->last_fw_err->sdio_status)); + +out: + + return simple_read_from_buffer(buffer, len, ppos, buf, buf_len); +} + +static const struct file_operations iwm_debugfs_txq_fops = { + .owner = THIS_MODULE, + .open = simple_open, + .read = iwm_debugfs_txq_read, + .llseek = default_llseek, +}; + +static const struct file_operations iwm_debugfs_tx_credit_fops = { + .owner = THIS_MODULE, + .open = simple_open, + .read = iwm_debugfs_tx_credit_read, + .llseek = default_llseek, +}; + +static const struct file_operations iwm_debugfs_rx_ticket_fops = { + .owner = THIS_MODULE, + .open = simple_open, + .read = iwm_debugfs_rx_ticket_read, + .llseek = default_llseek, +}; + +static const struct file_operations iwm_debugfs_fw_err_fops = { + .owner = THIS_MODULE, + .open = simple_open, + .read = iwm_debugfs_fw_err_read, + .llseek = default_llseek, +}; + +void iwm_debugfs_init(struct iwm_priv *iwm) +{ + int i; + + iwm->dbg.rootdir = debugfs_create_dir(KBUILD_MODNAME, NULL); + iwm->dbg.devdir = debugfs_create_dir(wiphy_name(iwm_to_wiphy(iwm)), + iwm->dbg.rootdir); + iwm->dbg.dbgdir = debugfs_create_dir("debug", iwm->dbg.devdir); + iwm->dbg.rxdir = debugfs_create_dir("rx", iwm->dbg.devdir); + iwm->dbg.txdir = debugfs_create_dir("tx", iwm->dbg.devdir); + iwm->dbg.busdir = debugfs_create_dir("bus", iwm->dbg.devdir); + if (iwm->bus_ops->debugfs_init) + iwm->bus_ops->debugfs_init(iwm, iwm->dbg.busdir); + + iwm->dbg.dbg_level = IWM_DL_NONE; + iwm->dbg.dbg_level_dentry = + debugfs_create_file("level", 0200, iwm->dbg.dbgdir, iwm, + &fops_iwm_dbg_level); + + iwm->dbg.dbg_modules = IWM_DM_DEFAULT; + iwm->dbg.dbg_modules_dentry = + debugfs_create_file("modules", 0200, iwm->dbg.dbgdir, iwm, + &fops_iwm_dbg_modules); + + for (i = 0; i < __IWM_DM_NR; i++) + add_dbg_module(iwm->dbg, iwm_debug_module[i].name, + iwm_debug_module[i].id, IWM_DL_DEFAULT); + + iwm->dbg.txq_dentry = debugfs_create_file("queues", 0200, + iwm->dbg.txdir, iwm, + &iwm_debugfs_txq_fops); + iwm->dbg.tx_credit_dentry = debugfs_create_file("credits", 0200, + iwm->dbg.txdir, iwm, + &iwm_debugfs_tx_credit_fops); + iwm->dbg.rx_ticket_dentry = debugfs_create_file("tickets", 0200, + iwm->dbg.rxdir, iwm, + &iwm_debugfs_rx_ticket_fops); + iwm->dbg.fw_err_dentry = debugfs_create_file("last_fw_err", 0200, + iwm->dbg.dbgdir, iwm, + &iwm_debugfs_fw_err_fops); +} + +void iwm_debugfs_exit(struct iwm_priv *iwm) +{ + int i; + + for (i = 0; i < __IWM_DM_NR; i++) + debugfs_remove(iwm->dbg.dbg_module_dentries[i]); + + debugfs_remove(iwm->dbg.dbg_modules_dentry); + debugfs_remove(iwm->dbg.dbg_level_dentry); + debugfs_remove(iwm->dbg.txq_dentry); + debugfs_remove(iwm->dbg.tx_credit_dentry); + debugfs_remove(iwm->dbg.rx_ticket_dentry); + debugfs_remove(iwm->dbg.fw_err_dentry); + if (iwm->bus_ops->debugfs_exit) + iwm->bus_ops->debugfs_exit(iwm); + + debugfs_remove(iwm->dbg.busdir); + debugfs_remove(iwm->dbg.dbgdir); + debugfs_remove(iwm->dbg.txdir); + debugfs_remove(iwm->dbg.rxdir); + debugfs_remove(iwm->dbg.devdir); + debugfs_remove(iwm->dbg.rootdir); +} diff --git a/trunk/drivers/net/wireless/iwmc3200wifi/eeprom.c b/trunk/drivers/net/wireless/iwmc3200wifi/eeprom.c new file mode 100644 index 000000000000..e80e776b74f7 --- /dev/null +++ b/trunk/drivers/net/wireless/iwmc3200wifi/eeprom.c @@ -0,0 +1,234 @@ +/* + * Intel Wireless Multicomm 3200 WiFi driver + * + * Copyright (C) 2009 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * + * Intel Corporation + * Samuel Ortiz + * Zhu Yi + * + */ + +#include +#include + +#include "iwm.h" +#include "umac.h" +#include "commands.h" +#include "eeprom.h" + +static struct iwm_eeprom_entry eeprom_map[] = { + [IWM_EEPROM_SIG] = + {"Signature", IWM_EEPROM_SIG_OFF, IWM_EEPROM_SIG_LEN}, + + [IWM_EEPROM_VERSION] = + {"Version", IWM_EEPROM_VERSION_OFF, IWM_EEPROM_VERSION_LEN}, + + [IWM_EEPROM_OEM_HW_VERSION] = + {"OEM HW version", IWM_EEPROM_OEM_HW_VERSION_OFF, + IWM_EEPROM_OEM_HW_VERSION_LEN}, + + [IWM_EEPROM_MAC_VERSION] = + {"MAC version", IWM_EEPROM_MAC_VERSION_OFF, IWM_EEPROM_MAC_VERSION_LEN}, + + [IWM_EEPROM_CARD_ID] = + {"Card ID", IWM_EEPROM_CARD_ID_OFF, IWM_EEPROM_CARD_ID_LEN}, + + [IWM_EEPROM_RADIO_CONF] = + {"Radio config", IWM_EEPROM_RADIO_CONF_OFF, IWM_EEPROM_RADIO_CONF_LEN}, + + [IWM_EEPROM_SKU_CAP] = + {"SKU capabilities", IWM_EEPROM_SKU_CAP_OFF, IWM_EEPROM_SKU_CAP_LEN}, + + [IWM_EEPROM_FAT_CHANNELS_CAP] = + {"HT channels capabilities", IWM_EEPROM_FAT_CHANNELS_CAP_OFF, + IWM_EEPROM_FAT_CHANNELS_CAP_LEN}, + + [IWM_EEPROM_CALIB_RXIQ_OFFSET] = + {"RX IQ offset", IWM_EEPROM_CALIB_RXIQ_OFF, IWM_EEPROM_INDIRECT_LEN}, + + [IWM_EEPROM_CALIB_RXIQ] = + {"Calib RX IQ", 0, IWM_EEPROM_CALIB_RXIQ_LEN}, +}; + + +static int iwm_eeprom_read(struct iwm_priv *iwm, u8 eeprom_id) +{ + int ret; + u32 entry_size, chunk_size, data_offset = 0, addr_offset = 0; + u32 addr; + struct iwm_udma_wifi_cmd udma_cmd; + struct iwm_umac_cmd umac_cmd; + struct iwm_umac_cmd_eeprom_proxy eeprom_cmd; + + if (eeprom_id > (IWM_EEPROM_LAST - 1)) + return -EINVAL; + + entry_size = eeprom_map[eeprom_id].length; + + if (eeprom_id >= IWM_EEPROM_INDIRECT_DATA) { + /* indirect data */ + u32 off_id = eeprom_id - IWM_EEPROM_INDIRECT_DATA + + IWM_EEPROM_INDIRECT_OFFSET; + + eeprom_map[eeprom_id].offset = + *(u16 *)(iwm->eeprom + eeprom_map[off_id].offset) << 1; + } + + addr = eeprom_map[eeprom_id].offset; + + udma_cmd.eop = 1; + udma_cmd.credit_group = 0x4; + udma_cmd.ra_tid = UMAC_HDI_ACT_TBL_IDX_HOST_CMD; + udma_cmd.lmac_offset = 0; + + umac_cmd.id = UMAC_CMD_OPCODE_EEPROM_PROXY; + umac_cmd.resp = 1; + + while (entry_size > 0) { + chunk_size = min_t(u32, entry_size, IWM_MAX_EEPROM_DATA_LEN); + + eeprom_cmd.hdr.type = + cpu_to_le32(IWM_UMAC_CMD_EEPROM_TYPE_READ); + eeprom_cmd.hdr.offset = cpu_to_le32(addr + addr_offset); + eeprom_cmd.hdr.len = cpu_to_le32(chunk_size); + + ret = iwm_hal_send_umac_cmd(iwm, &udma_cmd, + &umac_cmd, &eeprom_cmd, + sizeof(struct iwm_umac_cmd_eeprom_proxy)); + if (ret < 0) { + IWM_ERR(iwm, "Couldn't read eeprom\n"); + return ret; + } + + ret = iwm_notif_handle(iwm, UMAC_CMD_OPCODE_EEPROM_PROXY, + IWM_SRC_UMAC, 2*HZ); + if (ret < 0) { + IWM_ERR(iwm, "Did not get any eeprom answer\n"); + return ret; + } + + data_offset += chunk_size; + addr_offset += chunk_size; + entry_size -= chunk_size; + } + + return 0; +} + +u8 *iwm_eeprom_access(struct iwm_priv *iwm, u8 eeprom_id) +{ + if (!iwm->eeprom) + return ERR_PTR(-ENODEV); + + return iwm->eeprom + eeprom_map[eeprom_id].offset; +} + +int iwm_eeprom_fat_channels(struct iwm_priv *iwm) +{ + struct wiphy *wiphy = iwm_to_wiphy(iwm); + struct ieee80211_supported_band *band; + u16 *channels, i; + + channels = (u16 *)iwm_eeprom_access(iwm, IWM_EEPROM_FAT_CHANNELS_CAP); + if (IS_ERR(channels)) + return PTR_ERR(channels); + + band = wiphy->bands[IEEE80211_BAND_2GHZ]; + band->ht_cap.ht_supported = true; + + for (i = 0; i < IWM_EEPROM_FAT_CHANNELS_24; i++) + if (!(channels[i] & IWM_EEPROM_FAT_CHANNEL_ENABLED)) + band->ht_cap.ht_supported = false; + + band = wiphy->bands[IEEE80211_BAND_5GHZ]; + band->ht_cap.ht_supported = true; + for (i = IWM_EEPROM_FAT_CHANNELS_24; i < IWM_EEPROM_FAT_CHANNELS; i++) + if (!(channels[i] & IWM_EEPROM_FAT_CHANNEL_ENABLED)) + band->ht_cap.ht_supported = false; + + return 0; +} + +u32 iwm_eeprom_wireless_mode(struct iwm_priv *iwm) +{ + u16 sku_cap; + u32 wireless_mode = 0; + + sku_cap = *((u16 *)iwm_eeprom_access(iwm, IWM_EEPROM_SKU_CAP)); + + if (sku_cap & IWM_EEPROM_SKU_CAP_BAND_24GHZ) + wireless_mode |= WIRELESS_MODE_11G; + + if (sku_cap & IWM_EEPROM_SKU_CAP_BAND_52GHZ) + wireless_mode |= WIRELESS_MODE_11A; + + if (sku_cap & IWM_EEPROM_SKU_CAP_11N_ENABLE) + wireless_mode |= WIRELESS_MODE_11N; + + return wireless_mode; +} + + +int iwm_eeprom_init(struct iwm_priv *iwm) +{ + int i, ret = 0; + char name[32]; + + iwm->eeprom = kzalloc(IWM_EEPROM_LEN, GFP_KERNEL); + if (!iwm->eeprom) + return -ENOMEM; + + for (i = IWM_EEPROM_FIRST; i < IWM_EEPROM_LAST; i++) { + ret = iwm_eeprom_read(iwm, i); + if (ret < 0) { + IWM_ERR(iwm, "Couldn't read eeprom entry #%d: %s\n", + i, eeprom_map[i].name); + break; + } + } + + IWM_DBG_BOOT(iwm, DBG, "EEPROM dump:\n"); + for (i = IWM_EEPROM_FIRST; i < IWM_EEPROM_LAST; i++) { + memset(name, 0, 32); + sprintf(name, "%s: ", eeprom_map[i].name); + + IWM_HEXDUMP(iwm, DBG, BOOT, name, + iwm->eeprom + eeprom_map[i].offset, + eeprom_map[i].length); + } + + return ret; +} + +void iwm_eeprom_exit(struct iwm_priv *iwm) +{ + kfree(iwm->eeprom); +} diff --git a/trunk/drivers/net/wireless/iwmc3200wifi/eeprom.h b/trunk/drivers/net/wireless/iwmc3200wifi/eeprom.h new file mode 100644 index 000000000000..4e3a3fdab0d3 --- /dev/null +++ b/trunk/drivers/net/wireless/iwmc3200wifi/eeprom.h @@ -0,0 +1,127 @@ +/* + * Intel Wireless Multicomm 3200 WiFi driver + * + * Copyright (C) 2009 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * + * Intel Corporation + * Samuel Ortiz + * Zhu Yi + * + */ + +#ifndef __IWM_EEPROM_H__ +#define __IWM_EEPROM_H__ + +enum { + IWM_EEPROM_SIG = 0, + IWM_EEPROM_FIRST = IWM_EEPROM_SIG, + IWM_EEPROM_VERSION, + IWM_EEPROM_OEM_HW_VERSION, + IWM_EEPROM_MAC_VERSION, + IWM_EEPROM_CARD_ID, + IWM_EEPROM_RADIO_CONF, + IWM_EEPROM_SKU_CAP, + IWM_EEPROM_FAT_CHANNELS_CAP, + + IWM_EEPROM_INDIRECT_OFFSET, + IWM_EEPROM_CALIB_RXIQ_OFFSET = IWM_EEPROM_INDIRECT_OFFSET, + + IWM_EEPROM_INDIRECT_DATA, + IWM_EEPROM_CALIB_RXIQ = IWM_EEPROM_INDIRECT_DATA, + + IWM_EEPROM_LAST, +}; + +#define IWM_EEPROM_SIG_OFF 0x00 +#define IWM_EEPROM_VERSION_OFF (0x54 << 1) +#define IWM_EEPROM_OEM_HW_VERSION_OFF (0x56 << 1) +#define IWM_EEPROM_MAC_VERSION_OFF (0x30 << 1) +#define IWM_EEPROM_CARD_ID_OFF (0x5d << 1) +#define IWM_EEPROM_RADIO_CONF_OFF (0x58 << 1) +#define IWM_EEPROM_SKU_CAP_OFF (0x55 << 1) +#define IWM_EEPROM_CALIB_CONFIG_OFF (0x7c << 1) +#define IWM_EEPROM_FAT_CHANNELS_CAP_OFF (0xde << 1) + +#define IWM_EEPROM_SIG_LEN 4 +#define IWM_EEPROM_VERSION_LEN 2 +#define IWM_EEPROM_OEM_HW_VERSION_LEN 2 +#define IWM_EEPROM_MAC_VERSION_LEN 1 +#define IWM_EEPROM_CARD_ID_LEN 2 +#define IWM_EEPROM_RADIO_CONF_LEN 2 +#define IWM_EEPROM_SKU_CAP_LEN 2 +#define IWM_EEPROM_FAT_CHANNELS_CAP_LEN 40 +#define IWM_EEPROM_INDIRECT_LEN 2 + +#define IWM_MAX_EEPROM_DATA_LEN 240 +#define IWM_EEPROM_LEN 0x800 + +#define IWM_EEPROM_MIN_ALLOWED_VERSION 0x0610 +#define IWM_EEPROM_MAX_ALLOWED_VERSION 0x0700 +#define IWM_EEPROM_CURRENT_VERSION 0x0612 + +#define IWM_EEPROM_SKU_CAP_BAND_24GHZ (1 << 4) +#define IWM_EEPROM_SKU_CAP_BAND_52GHZ (1 << 5) +#define IWM_EEPROM_SKU_CAP_11N_ENABLE (1 << 6) + +#define IWM_EEPROM_FAT_CHANNELS 20 +/* 2.4 gHz FAT primary channels: 1, 2, 3, 4, 5, 6, 7, 8, 9 */ +#define IWM_EEPROM_FAT_CHANNELS_24 9 +/* 5.2 gHz FAT primary channels: 36,44,52,60,100,108,116,124,132,149,157 */ +#define IWM_EEPROM_FAT_CHANNELS_52 11 + +#define IWM_EEPROM_FAT_CHANNEL_ENABLED (1 << 0) + +enum { + IWM_EEPROM_CALIB_CAL_HDR, + IWM_EEPROM_CALIB_TX_POWER, + IWM_EEPROM_CALIB_XTAL, + IWM_EEPROM_CALIB_TEMPERATURE, + IWM_EEPROM_CALIB_RX_BB_FILTER, + IWM_EEPROM_CALIB_RX_IQ, + IWM_EEPROM_CALIB_MAX, +}; + +#define IWM_EEPROM_CALIB_RXIQ_OFF (IWM_EEPROM_CALIB_CONFIG_OFF + \ + (IWM_EEPROM_CALIB_RX_IQ << 1)) +#define IWM_EEPROM_CALIB_RXIQ_LEN sizeof(struct iwm_lmac_calib_rxiq) + +struct iwm_eeprom_entry { + char *name; + u32 offset; + u32 length; +}; + +int iwm_eeprom_init(struct iwm_priv *iwm); +void iwm_eeprom_exit(struct iwm_priv *iwm); +u8 *iwm_eeprom_access(struct iwm_priv *iwm, u8 eeprom_id); +int iwm_eeprom_fat_channels(struct iwm_priv *iwm); +u32 iwm_eeprom_wireless_mode(struct iwm_priv *iwm); + +#endif diff --git a/trunk/drivers/net/wireless/iwmc3200wifi/fw.c b/trunk/drivers/net/wireless/iwmc3200wifi/fw.c new file mode 100644 index 000000000000..6f1afe6bbc8c --- /dev/null +++ b/trunk/drivers/net/wireless/iwmc3200wifi/fw.c @@ -0,0 +1,416 @@ +/* + * Intel Wireless Multicomm 3200 WiFi driver + * + * Copyright (C) 2009 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * + * Intel Corporation + * Samuel Ortiz + * Zhu Yi + * + */ + +#include +#include + +#include "iwm.h" +#include "bus.h" +#include "hal.h" +#include "umac.h" +#include "debug.h" +#include "fw.h" +#include "commands.h" + +static const char fw_barker[] = "*WESTOPFORNOONE*"; + +/* + * @op_code: Op code we're looking for. + * @index: There can be several instances of the same opcode within + * the firmware. Index specifies which one we're looking for. + */ +static int iwm_fw_op_offset(struct iwm_priv *iwm, const struct firmware *fw, + u16 op_code, u32 index) +{ + int offset = -EINVAL, fw_offset; + u32 op_index = 0; + const u8 *fw_ptr; + struct iwm_fw_hdr_rec *rec; + + fw_offset = 0; + fw_ptr = fw->data; + + /* We first need to look for the firmware barker */ + if (memcmp(fw_ptr, fw_barker, IWM_HDR_BARKER_LEN)) { + IWM_ERR(iwm, "No barker string in this FW\n"); + return -EINVAL; + } + + if (fw->size < IWM_HDR_LEN) { + IWM_ERR(iwm, "FW is too small (%zu)\n", fw->size); + return -EINVAL; + } + + fw_offset += IWM_HDR_BARKER_LEN; + + while (fw_offset < fw->size) { + rec = (struct iwm_fw_hdr_rec *)(fw_ptr + fw_offset); + + IWM_DBG_FW(iwm, DBG, "FW: op_code: 0x%x, len: %d @ 0x%x\n", + rec->op_code, rec->len, fw_offset); + + if (rec->op_code == IWM_HDR_REC_OP_INVALID) { + IWM_DBG_FW(iwm, DBG, "Reached INVALID op code\n"); + break; + } + + if (rec->op_code == op_code) { + if (op_index == index) { + fw_offset += sizeof(struct iwm_fw_hdr_rec); + offset = fw_offset; + goto out; + } + op_index++; + } + + fw_offset += sizeof(struct iwm_fw_hdr_rec) + rec->len; + } + + out: + return offset; +} + +static int iwm_load_firmware_chunk(struct iwm_priv *iwm, + const struct firmware *fw, + struct iwm_fw_img_desc *img_desc) +{ + struct iwm_udma_nonwifi_cmd target_cmd; + u32 chunk_size; + const u8 *chunk_ptr; + int ret = 0; + + IWM_DBG_FW(iwm, INFO, "Loading FW chunk: %d bytes @ 0x%x\n", + img_desc->length, img_desc->address); + + target_cmd.opcode = UMAC_HDI_OUT_OPCODE_WRITE; + target_cmd.handle_by_hw = 1; + target_cmd.op2 = 0; + target_cmd.resp = 0; + target_cmd.eop = 1; + + chunk_size = img_desc->length; + chunk_ptr = fw->data + img_desc->offset; + + while (chunk_size > 0) { + u32 tmp_chunk_size; + + tmp_chunk_size = min_t(u32, chunk_size, + IWM_MAX_NONWIFI_CMD_BUFF_SIZE); + + target_cmd.addr = cpu_to_le32(img_desc->address + + (chunk_ptr - fw->data - img_desc->offset)); + target_cmd.op1_sz = cpu_to_le32(tmp_chunk_size); + + IWM_DBG_FW(iwm, DBG, "\t%d bytes @ 0x%x\n", + tmp_chunk_size, target_cmd.addr); + + ret = iwm_hal_send_target_cmd(iwm, &target_cmd, chunk_ptr); + if (ret < 0) { + IWM_ERR(iwm, "Couldn't load FW chunk\n"); + break; + } + + chunk_size -= tmp_chunk_size; + chunk_ptr += tmp_chunk_size; + } + + return ret; +} +/* + * To load a fw image to the target, we basically go through the + * fw, looking for OP_MEM_DESC records. Once we found one, we + * pass it to iwm_load_firmware_chunk(). + * The OP_MEM_DESC records contain the actuall memory chunk to be + * sent, but also the destination address. + */ +static int iwm_load_img(struct iwm_priv *iwm, const char *img_name) +{ + const struct firmware *fw; + struct iwm_fw_img_desc *img_desc; + struct iwm_fw_img_ver *ver; + int ret = 0, fw_offset; + u32 opcode_idx = 0, build_date; + char *build_tag; + + ret = request_firmware(&fw, img_name, iwm_to_dev(iwm)); + if (ret) { + IWM_ERR(iwm, "Request firmware failed"); + return ret; + } + + IWM_DBG_FW(iwm, INFO, "Start to load FW %s\n", img_name); + + while (1) { + fw_offset = iwm_fw_op_offset(iwm, fw, + IWM_HDR_REC_OP_MEM_DESC, + opcode_idx); + if (fw_offset < 0) + break; + + img_desc = (struct iwm_fw_img_desc *)(fw->data + fw_offset); + ret = iwm_load_firmware_chunk(iwm, fw, img_desc); + if (ret < 0) + goto err_release_fw; + opcode_idx++; + } + + /* Read firmware version */ + fw_offset = iwm_fw_op_offset(iwm, fw, IWM_HDR_REC_OP_SW_VER, 0); + if (fw_offset < 0) + goto err_release_fw; + + ver = (struct iwm_fw_img_ver *)(fw->data + fw_offset); + + /* Read build tag */ + fw_offset = iwm_fw_op_offset(iwm, fw, IWM_HDR_REC_OP_BUILD_TAG, 0); + if (fw_offset < 0) + goto err_release_fw; + + build_tag = (char *)(fw->data + fw_offset); + + /* Read build date */ + fw_offset = iwm_fw_op_offset(iwm, fw, IWM_HDR_REC_OP_BUILD_DATE, 0); + if (fw_offset < 0) + goto err_release_fw; + + build_date = *(u32 *)(fw->data + fw_offset); + + IWM_INFO(iwm, "%s:\n", img_name); + IWM_INFO(iwm, "\tVersion: %02X.%02X\n", ver->major, ver->minor); + IWM_INFO(iwm, "\tBuild tag: %s\n", build_tag); + IWM_INFO(iwm, "\tBuild date: %x-%x-%x\n", + IWM_BUILD_YEAR(build_date), IWM_BUILD_MONTH(build_date), + IWM_BUILD_DAY(build_date)); + + if (!strcmp(img_name, iwm->bus_ops->umac_name)) + sprintf(iwm->umac_version, "%02X.%02X", + ver->major, ver->minor); + + if (!strcmp(img_name, iwm->bus_ops->lmac_name)) + sprintf(iwm->lmac_version, "%02X.%02X", + ver->major, ver->minor); + + err_release_fw: + release_firmware(fw); + + return ret; +} + +static int iwm_load_umac(struct iwm_priv *iwm) +{ + struct iwm_udma_nonwifi_cmd target_cmd; + int ret; + + ret = iwm_load_img(iwm, iwm->bus_ops->umac_name); + if (ret < 0) + return ret; + + /* We've loaded the UMAC, we can tell the target to jump there */ + target_cmd.opcode = UMAC_HDI_OUT_OPCODE_JUMP; + target_cmd.addr = cpu_to_le32(UMAC_MU_FW_INST_DATA_12_ADDR); + target_cmd.op1_sz = 0; + target_cmd.op2 = 0; + target_cmd.handle_by_hw = 0; + target_cmd.resp = 1 ; + target_cmd.eop = 1; + + ret = iwm_hal_send_target_cmd(iwm, &target_cmd, NULL); + if (ret < 0) + IWM_ERR(iwm, "Couldn't send JMP command\n"); + + return ret; +} + +static int iwm_load_lmac(struct iwm_priv *iwm, const char *img_name) +{ + int ret; + + ret = iwm_load_img(iwm, img_name); + if (ret < 0) + return ret; + + return iwm_send_umac_reset(iwm, + cpu_to_le32(UMAC_RST_CTRL_FLG_LARC_CLK_EN), 0); +} + +static int iwm_init_calib(struct iwm_priv *iwm, unsigned long cfg_bitmap, + unsigned long expected_bitmap, u8 rx_iq_cmd) +{ + /* Read RX IQ calibration result from EEPROM */ + if (test_bit(rx_iq_cmd, &cfg_bitmap)) { + iwm_store_rxiq_calib_result(iwm); + set_bit(PHY_CALIBRATE_RX_IQ_CMD, &iwm->calib_done_map); + } + + iwm_send_prio_table(iwm); + iwm_send_init_calib_cfg(iwm, cfg_bitmap); + + while (iwm->calib_done_map != expected_bitmap) { + if (iwm_notif_handle(iwm, CALIBRATION_RES_NOTIFICATION, + IWM_SRC_LMAC, WAIT_NOTIF_TIMEOUT)) { + IWM_DBG_FW(iwm, DBG, "Initial calibration timeout\n"); + return -ETIMEDOUT; + } + + IWM_DBG_FW(iwm, DBG, "Got calibration result. calib_done_map: " + "0x%lx, expected calibrations: 0x%lx\n", + iwm->calib_done_map, expected_bitmap); + } + + return 0; +} + +/* + * We currently have to load 3 FWs: + * 1) The UMAC (Upper MAC). + * 2) The calibration LMAC (Lower MAC). + * We then send the calibration init command, so that the device can + * run a first calibration round. + * 3) The operational LMAC, which replaces the calibration one when it's + * done with the first calibration round. + * + * Once those 3 FWs have been loaded, we send the periodic calibration + * command, and then the device is available for regular 802.11 operations. + */ +int iwm_load_fw(struct iwm_priv *iwm) +{ + unsigned long init_calib_map, periodic_calib_map; + unsigned long expected_calib_map; + int ret; + + /* We first start downloading the UMAC */ + ret = iwm_load_umac(iwm); + if (ret < 0) { + IWM_ERR(iwm, "UMAC loading failed\n"); + return ret; + } + + /* Handle UMAC_ALIVE notification */ + ret = iwm_notif_handle(iwm, UMAC_NOTIFY_OPCODE_ALIVE, IWM_SRC_UMAC, + WAIT_NOTIF_TIMEOUT); + if (ret) { + IWM_ERR(iwm, "Handle UMAC_ALIVE failed: %d\n", ret); + return ret; + } + + /* UMAC is alive, we can download the calibration LMAC */ + ret = iwm_load_lmac(iwm, iwm->bus_ops->calib_lmac_name); + if (ret) { + IWM_ERR(iwm, "Calibration LMAC loading failed\n"); + return ret; + } + + /* Handle UMAC_INIT_COMPLETE notification */ + ret = iwm_notif_handle(iwm, UMAC_NOTIFY_OPCODE_INIT_COMPLETE, + IWM_SRC_UMAC, WAIT_NOTIF_TIMEOUT); + if (ret) { + IWM_ERR(iwm, "Handle INIT_COMPLETE failed for calibration " + "LMAC: %d\n", ret); + return ret; + } + + /* Read EEPROM data */ + ret = iwm_eeprom_init(iwm); + if (ret < 0) { + IWM_ERR(iwm, "Couldn't init eeprom array\n"); + return ret; + } + + init_calib_map = iwm->conf.calib_map & IWM_CALIB_MAP_INIT_MSK; + expected_calib_map = iwm->conf.expected_calib_map & + IWM_CALIB_MAP_INIT_MSK; + periodic_calib_map = IWM_CALIB_MAP_PER_LMAC(iwm->conf.calib_map); + + ret = iwm_init_calib(iwm, init_calib_map, expected_calib_map, + CALIB_CFG_RX_IQ_IDX); + if (ret < 0) { + /* Let's try the old way */ + ret = iwm_init_calib(iwm, expected_calib_map, + expected_calib_map, + PHY_CALIBRATE_RX_IQ_CMD); + if (ret < 0) { + IWM_ERR(iwm, "Calibration result timeout\n"); + goto out; + } + } + + /* Handle LMAC CALIBRATION_COMPLETE notification */ + ret = iwm_notif_handle(iwm, CALIBRATION_COMPLETE_NOTIFICATION, + IWM_SRC_LMAC, WAIT_NOTIF_TIMEOUT); + if (ret) { + IWM_ERR(iwm, "Wait for CALIBRATION_COMPLETE timeout\n"); + goto out; + } + + IWM_INFO(iwm, "LMAC calibration done: 0x%lx\n", iwm->calib_done_map); + + iwm_send_umac_reset(iwm, cpu_to_le32(UMAC_RST_CTRL_FLG_LARC_RESET), 1); + + ret = iwm_notif_handle(iwm, UMAC_CMD_OPCODE_RESET, IWM_SRC_UMAC, + WAIT_NOTIF_TIMEOUT); + if (ret) { + IWM_ERR(iwm, "Wait for UMAC RESET timeout\n"); + goto out; + } + + /* Download the operational LMAC */ + ret = iwm_load_lmac(iwm, iwm->bus_ops->lmac_name); + if (ret) { + IWM_ERR(iwm, "LMAC loading failed\n"); + goto out; + } + + ret = iwm_notif_handle(iwm, UMAC_NOTIFY_OPCODE_INIT_COMPLETE, + IWM_SRC_UMAC, WAIT_NOTIF_TIMEOUT); + if (ret) { + IWM_ERR(iwm, "Handle INIT_COMPLETE failed for LMAC: %d\n", ret); + goto out; + } + + iwm_send_prio_table(iwm); + iwm_send_calib_results(iwm); + iwm_send_periodic_calib_cfg(iwm, periodic_calib_map); + iwm_send_ct_kill_cfg(iwm, iwm->conf.ct_kill_entry, + iwm->conf.ct_kill_exit); + + return 0; + + out: + iwm_eeprom_exit(iwm); + return ret; +} diff --git a/trunk/drivers/net/wireless/iwmc3200wifi/fw.h b/trunk/drivers/net/wireless/iwmc3200wifi/fw.h new file mode 100644 index 000000000000..c70a3b40dad3 --- /dev/null +++ b/trunk/drivers/net/wireless/iwmc3200wifi/fw.h @@ -0,0 +1,100 @@ +/* + * Intel Wireless Multicomm 3200 WiFi driver + * + * Copyright (C) 2009 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * + * Intel Corporation + * Samuel Ortiz + * Zhu Yi + * + */ + +#ifndef __IWM_FW_H__ +#define __IWM_FW_H__ + +/** + * struct iwm_fw_hdr_rec - An iwm firmware image is a + * concatenation of various records. Each of them is + * defined by an ID (aka op code), a length, and the + * actual data. + * @op_code: The record ID, see IWM_HDR_REC_OP_* + * + * @len: The record payload length + * + * @buf: The record payload + */ +struct iwm_fw_hdr_rec { + u16 op_code; + u16 len; + u8 buf[0]; +}; + +/* Header's definitions */ +#define IWM_HDR_LEN (512) +#define IWM_HDR_BARKER_LEN (16) + +/* Header's opcodes */ +#define IWM_HDR_REC_OP_INVALID (0x00) +#define IWM_HDR_REC_OP_BUILD_DATE (0x01) +#define IWM_HDR_REC_OP_BUILD_TAG (0x02) +#define IWM_HDR_REC_OP_SW_VER (0x03) +#define IWM_HDR_REC_OP_HW_SKU (0x04) +#define IWM_HDR_REC_OP_BUILD_OPT (0x05) +#define IWM_HDR_REC_OP_MEM_DESC (0x06) +#define IWM_HDR_REC_USERDEFS (0x07) + +/* Header's records length (in bytes) */ +#define IWM_HDR_REC_LEN_BUILD_DATE (4) +#define IWM_HDR_REC_LEN_BUILD_TAG (64) +#define IWM_HDR_REC_LEN_SW_VER (4) +#define IWM_HDR_REC_LEN_HW_SKU (4) +#define IWM_HDR_REC_LEN_BUILD_OPT (4) +#define IWM_HDR_REC_LEN_MEM_DESC (12) +#define IWM_HDR_REC_LEN_USERDEF (64) + +#define IWM_BUILD_YEAR(date) ((date >> 16) & 0xffff) +#define IWM_BUILD_MONTH(date) ((date >> 8) & 0xff) +#define IWM_BUILD_DAY(date) (date & 0xff) + +struct iwm_fw_img_desc { + u32 offset; + u32 address; + u32 length; +}; + +struct iwm_fw_img_ver { + u8 minor; + u8 major; + u16 reserved; +}; + +int iwm_load_fw(struct iwm_priv *iwm); + +#endif diff --git a/trunk/drivers/net/wireless/iwmc3200wifi/hal.c b/trunk/drivers/net/wireless/iwmc3200wifi/hal.c new file mode 100644 index 000000000000..1cabcb39643f --- /dev/null +++ b/trunk/drivers/net/wireless/iwmc3200wifi/hal.c @@ -0,0 +1,470 @@ +/* + * Intel Wireless Multicomm 3200 WiFi driver + * + * Copyright (C) 2009 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * + * Intel Corporation + * Samuel Ortiz + * Zhu Yi + * + */ + +/* + * Hardware Abstraction Layer for iwm. + * + * This file mostly defines an abstraction API for + * sending various commands to the target. + * + * We have 2 types of commands: wifi and non-wifi ones. + * + * - wifi commands: + * They are used for sending LMAC and UMAC commands, + * and thus are the most commonly used ones. + * There are 2 different wifi command types, the regular + * one and the LMAC one. The former is used to send + * UMAC commands (see UMAC_CMD_OPCODE_* from umac.h) + * while the latter is used for sending commands to the + * LMAC. If you look at LMAC commands you'll se that they + * are actually regular iwlwifi target commands encapsulated + * into a special UMAC command called UMAC passthrough. + * This is due to the fact the host talks exclusively + * to the UMAC and so there needs to be a special UMAC + * command for talking to the LMAC. + * This is how a wifi command is laid out: + * ------------------------ + * | iwm_udma_out_wifi_hdr | + * ------------------------ + * | SW meta_data (32 bits) | + * ------------------------ + * | iwm_dev_cmd_hdr | + * ------------------------ + * | payload | + * | .... | + * + * - non-wifi, or general commands: + * Those commands are handled by the device's bootrom, + * and are typically sent when the UMAC and the LMAC + * are not yet available. + * * This is how a non-wifi command is laid out: + * --------------------------- + * | iwm_udma_out_nonwifi_hdr | + * --------------------------- + * | payload | + * | .... | + + * + * All the commands start with a UDMA header, which is + * basically a 32 bits field. The 4 LSB there define + * an opcode that allows the target to differentiate + * between wifi (opcode is 0xf) and non-wifi commands + * (opcode is [0..0xe]). + * + * When a command (wifi or non-wifi) is supposed to receive + * an answer, we queue the command buffer. When we do receive + * a command response from the UMAC, we go through the list + * of pending command, and pass both the command and the answer + * to the rx handler. Each command is sent with a unique + * sequence id, and the answer is sent with the same one. This + * is how we're supposed to match an answer with its command. + * See rx.c:iwm_rx_handle_[non]wifi() and iwm_get_pending_[non]wifi() + * for the implementation details. + */ +#include +#include +#include + +#include "iwm.h" +#include "bus.h" +#include "hal.h" +#include "umac.h" +#include "debug.h" +#include "trace.h" + +static int iwm_nonwifi_cmd_init(struct iwm_priv *iwm, + struct iwm_nonwifi_cmd *cmd, + struct iwm_udma_nonwifi_cmd *udma_cmd) +{ + INIT_LIST_HEAD(&cmd->pending); + + spin_lock(&iwm->cmd_lock); + + cmd->resp_received = 0; + + cmd->seq_num = iwm->nonwifi_seq_num; + udma_cmd->seq_num = cpu_to_le16(cmd->seq_num); + + iwm->nonwifi_seq_num++; + iwm->nonwifi_seq_num %= UMAC_NONWIFI_SEQ_NUM_MAX; + + if (udma_cmd->resp) + list_add_tail(&cmd->pending, &iwm->nonwifi_pending_cmd); + + spin_unlock(&iwm->cmd_lock); + + cmd->buf.start = cmd->buf.payload; + cmd->buf.len = 0; + + memcpy(&cmd->udma_cmd, udma_cmd, sizeof(*udma_cmd)); + + return cmd->seq_num; +} + +u16 iwm_alloc_wifi_cmd_seq(struct iwm_priv *iwm) +{ + u16 seq_num = iwm->wifi_seq_num; + + iwm->wifi_seq_num++; + iwm->wifi_seq_num %= UMAC_WIFI_SEQ_NUM_MAX; + + return seq_num; +} + +static void iwm_wifi_cmd_init(struct iwm_priv *iwm, + struct iwm_wifi_cmd *cmd, + struct iwm_udma_wifi_cmd *udma_cmd, + struct iwm_umac_cmd *umac_cmd, + struct iwm_lmac_cmd *lmac_cmd, + u16 payload_size) +{ + INIT_LIST_HEAD(&cmd->pending); + + spin_lock(&iwm->cmd_lock); + + cmd->seq_num = iwm_alloc_wifi_cmd_seq(iwm); + umac_cmd->seq_num = cpu_to_le16(cmd->seq_num); + + if (umac_cmd->resp) + list_add_tail(&cmd->pending, &iwm->wifi_pending_cmd); + + spin_unlock(&iwm->cmd_lock); + + cmd->buf.start = cmd->buf.payload; + cmd->buf.len = 0; + + if (lmac_cmd) { + cmd->buf.start -= sizeof(struct iwm_lmac_hdr); + + lmac_cmd->seq_num = cpu_to_le16(cmd->seq_num); + lmac_cmd->count = cpu_to_le16(payload_size); + + memcpy(&cmd->lmac_cmd, lmac_cmd, sizeof(*lmac_cmd)); + + umac_cmd->count = cpu_to_le16(sizeof(struct iwm_lmac_hdr)); + } else + umac_cmd->count = 0; + + umac_cmd->count = cpu_to_le16(payload_size + + le16_to_cpu(umac_cmd->count)); + udma_cmd->count = cpu_to_le16(sizeof(struct iwm_umac_fw_cmd_hdr) + + le16_to_cpu(umac_cmd->count)); + + memcpy(&cmd->udma_cmd, udma_cmd, sizeof(*udma_cmd)); + memcpy(&cmd->umac_cmd, umac_cmd, sizeof(*umac_cmd)); +} + +void iwm_cmd_flush(struct iwm_priv *iwm) +{ + struct iwm_wifi_cmd *wcmd, *wnext; + struct iwm_nonwifi_cmd *nwcmd, *nwnext; + + list_for_each_entry_safe(wcmd, wnext, &iwm->wifi_pending_cmd, pending) { + list_del(&wcmd->pending); + kfree(wcmd); + } + + list_for_each_entry_safe(nwcmd, nwnext, &iwm->nonwifi_pending_cmd, + pending) { + list_del(&nwcmd->pending); + kfree(nwcmd); + } +} + +struct iwm_wifi_cmd *iwm_get_pending_wifi_cmd(struct iwm_priv *iwm, u16 seq_num) +{ + struct iwm_wifi_cmd *cmd; + + list_for_each_entry(cmd, &iwm->wifi_pending_cmd, pending) + if (cmd->seq_num == seq_num) { + list_del(&cmd->pending); + return cmd; + } + + return NULL; +} + +struct iwm_nonwifi_cmd *iwm_get_pending_nonwifi_cmd(struct iwm_priv *iwm, + u8 seq_num, u8 cmd_opcode) +{ + struct iwm_nonwifi_cmd *cmd; + + list_for_each_entry(cmd, &iwm->nonwifi_pending_cmd, pending) + if ((cmd->seq_num == seq_num) && + (cmd->udma_cmd.opcode == cmd_opcode) && + (cmd->resp_received)) { + list_del(&cmd->pending); + return cmd; + } + + return NULL; +} + +static void iwm_build_udma_nonwifi_hdr(struct iwm_priv *iwm, + struct iwm_udma_out_nonwifi_hdr *hdr, + struct iwm_udma_nonwifi_cmd *cmd) +{ + memset(hdr, 0, sizeof(*hdr)); + + SET_VAL32(hdr->cmd, UMAC_HDI_OUT_CMD_OPCODE, cmd->opcode); + SET_VAL32(hdr->cmd, UDMA_HDI_OUT_NW_CMD_RESP, cmd->resp); + SET_VAL32(hdr->cmd, UMAC_HDI_OUT_CMD_EOT, 1); + SET_VAL32(hdr->cmd, UDMA_HDI_OUT_NW_CMD_HANDLE_BY_HW, + cmd->handle_by_hw); + SET_VAL32(hdr->cmd, UMAC_HDI_OUT_CMD_SIGNATURE, UMAC_HDI_OUT_SIGNATURE); + SET_VAL32(hdr->cmd, UDMA_HDI_OUT_CMD_NON_WIFI_HW_SEQ_NUM, + le16_to_cpu(cmd->seq_num)); + + hdr->addr = cmd->addr; + hdr->op1_sz = cmd->op1_sz; + hdr->op2 = cmd->op2; +} + +static int iwm_send_udma_nonwifi_cmd(struct iwm_priv *iwm, + struct iwm_nonwifi_cmd *cmd) +{ + struct iwm_udma_out_nonwifi_hdr *udma_hdr; + struct iwm_nonwifi_cmd_buff *buf; + struct iwm_udma_nonwifi_cmd *udma_cmd = &cmd->udma_cmd; + + buf = &cmd->buf; + + buf->start -= sizeof(struct iwm_umac_nonwifi_out_hdr); + buf->len += sizeof(struct iwm_umac_nonwifi_out_hdr); + + udma_hdr = (struct iwm_udma_out_nonwifi_hdr *)(buf->start); + + iwm_build_udma_nonwifi_hdr(iwm, udma_hdr, udma_cmd); + + IWM_DBG_CMD(iwm, DBG, + "Send UDMA nonwifi cmd: opcode = 0x%x, resp = 0x%x, " + "hw = 0x%x, seqnum = %d, addr = 0x%x, op1_sz = 0x%x, " + "op2 = 0x%x\n", udma_cmd->opcode, udma_cmd->resp, + udma_cmd->handle_by_hw, cmd->seq_num, udma_cmd->addr, + udma_cmd->op1_sz, udma_cmd->op2); + + trace_iwm_tx_nonwifi_cmd(iwm, udma_hdr); + return iwm_bus_send_chunk(iwm, buf->start, buf->len); +} + +void iwm_udma_wifi_hdr_set_eop(struct iwm_priv *iwm, u8 *buf, u8 eop) +{ + struct iwm_udma_out_wifi_hdr *hdr = (struct iwm_udma_out_wifi_hdr *)buf; + + SET_VAL32(hdr->cmd, UMAC_HDI_OUT_CMD_EOT, eop); +} + +void iwm_build_udma_wifi_hdr(struct iwm_priv *iwm, + struct iwm_udma_out_wifi_hdr *hdr, + struct iwm_udma_wifi_cmd *cmd) +{ + memset(hdr, 0, sizeof(*hdr)); + + SET_VAL32(hdr->cmd, UMAC_HDI_OUT_CMD_OPCODE, UMAC_HDI_OUT_OPCODE_WIFI); + SET_VAL32(hdr->cmd, UMAC_HDI_OUT_CMD_EOT, cmd->eop); + SET_VAL32(hdr->cmd, UMAC_HDI_OUT_CMD_SIGNATURE, UMAC_HDI_OUT_SIGNATURE); + + SET_VAL32(hdr->meta_data, UMAC_HDI_OUT_BYTE_COUNT, + le16_to_cpu(cmd->count)); + SET_VAL32(hdr->meta_data, UMAC_HDI_OUT_CREDIT_GRP, cmd->credit_group); + SET_VAL32(hdr->meta_data, UMAC_HDI_OUT_RATID, cmd->ra_tid); + SET_VAL32(hdr->meta_data, UMAC_HDI_OUT_LMAC_OFFSET, cmd->lmac_offset); +} + +void iwm_build_umac_hdr(struct iwm_priv *iwm, + struct iwm_umac_fw_cmd_hdr *hdr, + struct iwm_umac_cmd *cmd) +{ + memset(hdr, 0, sizeof(*hdr)); + + SET_VAL32(hdr->meta_data, UMAC_FW_CMD_BYTE_COUNT, + le16_to_cpu(cmd->count)); + SET_VAL32(hdr->meta_data, UMAC_FW_CMD_TX_STA_COLOR, cmd->color); + SET_VAL8(hdr->cmd.flags, UMAC_DEV_CMD_FLAGS_RESP_REQ, cmd->resp); + + hdr->cmd.cmd = cmd->id; + hdr->cmd.seq_num = cmd->seq_num; +} + +static int iwm_send_udma_wifi_cmd(struct iwm_priv *iwm, + struct iwm_wifi_cmd *cmd) +{ + struct iwm_umac_wifi_out_hdr *umac_hdr; + struct iwm_wifi_cmd_buff *buf; + struct iwm_udma_wifi_cmd *udma_cmd = &cmd->udma_cmd; + struct iwm_umac_cmd *umac_cmd = &cmd->umac_cmd; + int ret; + + buf = &cmd->buf; + + buf->start -= sizeof(struct iwm_umac_wifi_out_hdr); + buf->len += sizeof(struct iwm_umac_wifi_out_hdr); + + umac_hdr = (struct iwm_umac_wifi_out_hdr *)(buf->start); + + iwm_build_udma_wifi_hdr(iwm, &umac_hdr->hw_hdr, udma_cmd); + iwm_build_umac_hdr(iwm, &umac_hdr->sw_hdr, umac_cmd); + + IWM_DBG_CMD(iwm, DBG, + "Send UDMA wifi cmd: opcode = 0x%x, UMAC opcode = 0x%x, " + "eop = 0x%x, count = 0x%x, credit_group = 0x%x, " + "ra_tid = 0x%x, lmac_offset = 0x%x, seqnum = %d\n", + UMAC_HDI_OUT_OPCODE_WIFI, umac_cmd->id, + udma_cmd->eop, udma_cmd->count, udma_cmd->credit_group, + udma_cmd->ra_tid, udma_cmd->lmac_offset, cmd->seq_num); + + if (umac_cmd->id == UMAC_CMD_OPCODE_WIFI_PASS_THROUGH) + IWM_DBG_CMD(iwm, DBG, "\tLMAC opcode: 0x%x\n", + cmd->lmac_cmd.id); + + ret = iwm_tx_credit_alloc(iwm, udma_cmd->credit_group, buf->len); + + /* We keep sending UMAC reset regardless of the command credits. + * The UMAC is supposed to be reset anyway and the Tx credits are + * reinitialized afterwards. If we are lucky, the reset could + * still be done even though we have run out of credits for the + * command pool at this moment.*/ + if (ret && (umac_cmd->id != UMAC_CMD_OPCODE_RESET)) { + IWM_DBG_TX(iwm, DBG, "Failed to alloc tx credit for cmd %d\n", + umac_cmd->id); + return ret; + } + + trace_iwm_tx_wifi_cmd(iwm, umac_hdr); + return iwm_bus_send_chunk(iwm, buf->start, buf->len); +} + +/* target_cmd a.k.a udma_nonwifi_cmd can be sent when UMAC is not available */ +int iwm_hal_send_target_cmd(struct iwm_priv *iwm, + struct iwm_udma_nonwifi_cmd *udma_cmd, + const void *payload) +{ + struct iwm_nonwifi_cmd *cmd; + int ret, seq_num; + + cmd = kzalloc(sizeof(struct iwm_nonwifi_cmd), GFP_KERNEL); + if (!cmd) { + IWM_ERR(iwm, "Couldn't alloc memory for hal cmd\n"); + return -ENOMEM; + } + + seq_num = iwm_nonwifi_cmd_init(iwm, cmd, udma_cmd); + + if (cmd->udma_cmd.opcode == UMAC_HDI_OUT_OPCODE_WRITE || + cmd->udma_cmd.opcode == UMAC_HDI_OUT_OPCODE_WRITE_PERSISTENT) { + cmd->buf.len = le32_to_cpu(cmd->udma_cmd.op1_sz); + memcpy(&cmd->buf.payload, payload, cmd->buf.len); + } + + ret = iwm_send_udma_nonwifi_cmd(iwm, cmd); + + if (!udma_cmd->resp) + kfree(cmd); + + if (ret < 0) + return ret; + + return seq_num; +} + +static void iwm_build_lmac_hdr(struct iwm_priv *iwm, struct iwm_lmac_hdr *hdr, + struct iwm_lmac_cmd *cmd) +{ + memset(hdr, 0, sizeof(*hdr)); + + hdr->id = cmd->id; + hdr->flags = 0; /* Is this ever used? */ + hdr->seq_num = cmd->seq_num; +} + +/* + * iwm_hal_send_host_cmd(): sends commands to the UMAC or the LMAC. + * Sending command to the LMAC is equivalent to sending a + * regular UMAC command with the LMAC passthrough or the LMAC + * wrapper UMAC command IDs. + */ +int iwm_hal_send_host_cmd(struct iwm_priv *iwm, + struct iwm_udma_wifi_cmd *udma_cmd, + struct iwm_umac_cmd *umac_cmd, + struct iwm_lmac_cmd *lmac_cmd, + const void *payload, u16 payload_size) +{ + struct iwm_wifi_cmd *cmd; + struct iwm_lmac_hdr *hdr; + int lmac_hdr_len = 0; + int ret; + + cmd = kzalloc(sizeof(struct iwm_wifi_cmd), GFP_KERNEL); + if (!cmd) { + IWM_ERR(iwm, "Couldn't alloc memory for wifi hal cmd\n"); + return -ENOMEM; + } + + iwm_wifi_cmd_init(iwm, cmd, udma_cmd, umac_cmd, lmac_cmd, payload_size); + + if (lmac_cmd) { + hdr = (struct iwm_lmac_hdr *)(cmd->buf.start); + + iwm_build_lmac_hdr(iwm, hdr, &cmd->lmac_cmd); + lmac_hdr_len = sizeof(struct iwm_lmac_hdr); + } + + memcpy(cmd->buf.payload, payload, payload_size); + cmd->buf.len = le16_to_cpu(umac_cmd->count); + + ret = iwm_send_udma_wifi_cmd(iwm, cmd); + + /* We free the cmd if we're not expecting any response */ + if (!umac_cmd->resp) + kfree(cmd); + return ret; +} + +/* + * iwm_hal_send_umac_cmd(): This is a special case for + * iwm_hal_send_host_cmd() to send direct UMAC cmd (without + * LMAC involved). + */ +int iwm_hal_send_umac_cmd(struct iwm_priv *iwm, + struct iwm_udma_wifi_cmd *udma_cmd, + struct iwm_umac_cmd *umac_cmd, + const void *payload, u16 payload_size) +{ + return iwm_hal_send_host_cmd(iwm, udma_cmd, umac_cmd, NULL, + payload, payload_size); +} diff --git a/trunk/drivers/net/wireless/iwmc3200wifi/hal.h b/trunk/drivers/net/wireless/iwmc3200wifi/hal.h new file mode 100644 index 000000000000..c20936d9b6b7 --- /dev/null +++ b/trunk/drivers/net/wireless/iwmc3200wifi/hal.h @@ -0,0 +1,237 @@ +/* + * Intel Wireless Multicomm 3200 WiFi driver + * + * Copyright (C) 2009 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * + * Intel Corporation + * Samuel Ortiz + * Zhu Yi + * + */ + +#ifndef _IWM_HAL_H_ +#define _IWM_HAL_H_ + +#include "umac.h" + +#define GET_VAL8(s, name) ((s >> name##_POS) & name##_SEED) +#define GET_VAL16(s, name) ((le16_to_cpu(s) >> name##_POS) & name##_SEED) +#define GET_VAL32(s, name) ((le32_to_cpu(s) >> name##_POS) & name##_SEED) + +#define SET_VAL8(s, name, val) \ +do { \ + s = (s & ~(name##_SEED << name##_POS)) | \ + ((val & name##_SEED) << name##_POS); \ +} while (0) + +#define SET_VAL16(s, name, val) \ +do { \ + s = cpu_to_le16((le16_to_cpu(s) & ~(name##_SEED << name##_POS)) | \ + ((val & name##_SEED) << name##_POS)); \ +} while (0) + +#define SET_VAL32(s, name, val) \ +do { \ + s = cpu_to_le32((le32_to_cpu(s) & ~(name##_SEED << name##_POS)) | \ + ((val & name##_SEED) << name##_POS)); \ +} while (0) + + +#define UDMA_UMAC_INIT { .eop = 1, \ + .credit_group = 0x4, \ + .ra_tid = UMAC_HDI_ACT_TBL_IDX_HOST_CMD, \ + .lmac_offset = 0 } +#define UDMA_LMAC_INIT { .eop = 1, \ + .credit_group = 0x4, \ + .ra_tid = UMAC_HDI_ACT_TBL_IDX_HOST_CMD, \ + .lmac_offset = 4 } + + +/* UDMA IN OP CODE -- cmd bits [3:0] */ +#define UDMA_HDI_IN_NW_CMD_OPCODE_POS 0 +#define UDMA_HDI_IN_NW_CMD_OPCODE_SEED 0xF + +#define UDMA_IN_OPCODE_GENERAL_RESP 0x0 +#define UDMA_IN_OPCODE_READ_RESP 0x1 +#define UDMA_IN_OPCODE_WRITE_RESP 0x2 +#define UDMA_IN_OPCODE_PERS_WRITE_RESP 0x5 +#define UDMA_IN_OPCODE_PERS_READ_RESP 0x6 +#define UDMA_IN_OPCODE_RD_MDFY_WR_RESP 0x7 +#define UDMA_IN_OPCODE_EP_MNGMT_MSG 0x8 +#define UDMA_IN_OPCODE_CRDT_CHNG_MSG 0x9 +#define UDMA_IN_OPCODE_CNTRL_DATABASE_MSG 0xA +#define UDMA_IN_OPCODE_SW_MSG 0xB +#define UDMA_IN_OPCODE_WIFI 0xF +#define UDMA_IN_OPCODE_WIFI_LMAC 0x1F +#define UDMA_IN_OPCODE_WIFI_UMAC 0x2F + +/* HW API: udma_hdi_nonwifi API (OUT and IN) */ + +/* iwm_udma_nonwifi_cmd request response -- bits [9:9] */ +#define UDMA_HDI_OUT_NW_CMD_RESP_POS 9 +#define UDMA_HDI_OUT_NW_CMD_RESP_SEED 0x1 + +/* iwm_udma_nonwifi_cmd handle by HW -- bits [11:11] */ +#define UDMA_HDI_OUT_NW_CMD_HANDLE_BY_HW_POS 11 +#define UDMA_HDI_OUT_NW_CMD_HANDLE_BY_HW_SEED 0x1 + +/* iwm_udma_nonwifi_cmd sequence-number -- bits [12:15] */ +#define UDMA_HDI_OUT_NW_CMD_SEQ_NUM_POS 12 +#define UDMA_HDI_OUT_NW_CMD_SEQ_NUM_SEED 0xF + +/* UDMA IN Non-WIFI HW sequence number -- bits [12:15] */ +#define UDMA_IN_NW_HW_SEQ_NUM_POS 12 +#define UDMA_IN_NW_HW_SEQ_NUM_SEED 0xF + +/* UDMA IN Non-WIFI HW signature -- bits [16:31] */ +#define UDMA_IN_NW_HW_SIG_POS 16 +#define UDMA_IN_NW_HW_SIG_SEED 0xFFFF + +/* fixed signature */ +#define UDMA_IN_NW_HW_SIG 0xCBBC + +/* UDMA IN Non-WIFI HW block length -- bits [32:35] */ +#define UDMA_IN_NW_HW_LENGTH_SEED 0xF +#define UDMA_IN_NW_HW_LENGTH_POS 32 + +/* End of HW API: udma_hdi_nonwifi API (OUT and IN) */ + +#define IWM_SDIO_FW_MAX_CHUNK_SIZE 2032 +#define IWM_MAX_WIFI_HEADERS_SIZE 32 +#define IWM_MAX_NONWIFI_HEADERS_SIZE 16 +#define IWM_MAX_NONWIFI_CMD_BUFF_SIZE (IWM_SDIO_FW_MAX_CHUNK_SIZE - \ + IWM_MAX_NONWIFI_HEADERS_SIZE) +#define IWM_MAX_WIFI_CMD_BUFF_SIZE (IWM_SDIO_FW_MAX_CHUNK_SIZE - \ + IWM_MAX_WIFI_HEADERS_SIZE) + +#define IWM_HAL_CONCATENATE_BUF_SIZE (32 * 1024) + +struct iwm_wifi_cmd_buff { + u16 len; + u8 *start; + u8 hdr[IWM_MAX_WIFI_HEADERS_SIZE]; + u8 payload[IWM_MAX_WIFI_CMD_BUFF_SIZE]; +}; + +struct iwm_nonwifi_cmd_buff { + u16 len; + u8 *start; + u8 hdr[IWM_MAX_NONWIFI_HEADERS_SIZE]; + u8 payload[IWM_MAX_NONWIFI_CMD_BUFF_SIZE]; +}; + +struct iwm_udma_nonwifi_cmd { + u8 opcode; + u8 eop; + u8 resp; + u8 handle_by_hw; + __le32 addr; + __le32 op1_sz; + __le32 op2; + __le16 seq_num; +}; + +struct iwm_udma_wifi_cmd { + __le16 count; + u8 eop; + u8 credit_group; + u8 ra_tid; + u8 lmac_offset; +}; + +struct iwm_umac_cmd { + u8 id; + __le16 count; + u8 resp; + __le16 seq_num; + u8 color; +}; + +struct iwm_lmac_cmd { + u8 id; + __le16 count; + u8 resp; + __le16 seq_num; +}; + +struct iwm_nonwifi_cmd { + u16 seq_num; + bool resp_received; + struct list_head pending; + struct iwm_udma_nonwifi_cmd udma_cmd; + struct iwm_umac_cmd umac_cmd; + struct iwm_lmac_cmd lmac_cmd; + struct iwm_nonwifi_cmd_buff buf; + u32 flags; +}; + +struct iwm_wifi_cmd { + u16 seq_num; + struct list_head pending; + struct iwm_udma_wifi_cmd udma_cmd; + struct iwm_umac_cmd umac_cmd; + struct iwm_lmac_cmd lmac_cmd; + struct iwm_wifi_cmd_buff buf; + u32 flags; +}; + +void iwm_cmd_flush(struct iwm_priv *iwm); + +struct iwm_wifi_cmd *iwm_get_pending_wifi_cmd(struct iwm_priv *iwm, + u16 seq_num); +struct iwm_nonwifi_cmd *iwm_get_pending_nonwifi_cmd(struct iwm_priv *iwm, + u8 seq_num, u8 cmd_opcode); + + +int iwm_hal_send_target_cmd(struct iwm_priv *iwm, + struct iwm_udma_nonwifi_cmd *ucmd, + const void *payload); + +int iwm_hal_send_host_cmd(struct iwm_priv *iwm, + struct iwm_udma_wifi_cmd *udma_cmd, + struct iwm_umac_cmd *umac_cmd, + struct iwm_lmac_cmd *lmac_cmd, + const void *payload, u16 payload_size); + +int iwm_hal_send_umac_cmd(struct iwm_priv *iwm, + struct iwm_udma_wifi_cmd *udma_cmd, + struct iwm_umac_cmd *umac_cmd, + const void *payload, u16 payload_size); + +u16 iwm_alloc_wifi_cmd_seq(struct iwm_priv *iwm); + +void iwm_udma_wifi_hdr_set_eop(struct iwm_priv *iwm, u8 *buf, u8 eop); +void iwm_build_udma_wifi_hdr(struct iwm_priv *iwm, + struct iwm_udma_out_wifi_hdr *hdr, + struct iwm_udma_wifi_cmd *cmd); +void iwm_build_umac_hdr(struct iwm_priv *iwm, + struct iwm_umac_fw_cmd_hdr *hdr, + struct iwm_umac_cmd *cmd); +#endif /* _IWM_HAL_H_ */ diff --git a/trunk/drivers/net/wireless/iwmc3200wifi/iwm.h b/trunk/drivers/net/wireless/iwmc3200wifi/iwm.h new file mode 100644 index 000000000000..51d7efa15ae6 --- /dev/null +++ b/trunk/drivers/net/wireless/iwmc3200wifi/iwm.h @@ -0,0 +1,367 @@ +/* + * Intel Wireless Multicomm 3200 WiFi driver + * + * Copyright (C) 2009 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * + * Intel Corporation + * Samuel Ortiz + * Zhu Yi + * + */ + +#ifndef __IWM_H__ +#define __IWM_H__ + +#include +#include +#include + +#include "debug.h" +#include "hal.h" +#include "umac.h" +#include "lmac.h" +#include "eeprom.h" +#include "trace.h" + +#define IWM_COPYRIGHT "Copyright(c) 2009 Intel Corporation" +#define IWM_AUTHOR "" + +#define IWM_SRC_LMAC UMAC_HDI_IN_SOURCE_FHRX +#define IWM_SRC_UDMA UMAC_HDI_IN_SOURCE_UDMA +#define IWM_SRC_UMAC UMAC_HDI_IN_SOURCE_FW +#define IWM_SRC_NUM 3 + +#define IWM_POWER_INDEX_MIN 0 +#define IWM_POWER_INDEX_MAX 5 +#define IWM_POWER_INDEX_DEFAULT 3 + +struct iwm_conf { + u32 sdio_ior_timeout; + unsigned long calib_map; + unsigned long expected_calib_map; + u8 ct_kill_entry; + u8 ct_kill_exit; + bool reset_on_fatal_err; + bool auto_connect; + bool wimax_not_present; + bool enable_qos; + u32 mode; + + u32 power_index; + u32 frag_threshold; + u32 rts_threshold; + bool cts_to_self; + + u32 assoc_timeout; + u32 roam_timeout; + u32 wireless_mode; + + u8 ibss_band; + u8 ibss_channel; + + u8 mac_addr[ETH_ALEN]; +}; + +enum { + COEX_MODE_SA = 1, + COEX_MODE_XOR, + COEX_MODE_CM, + COEX_MODE_MAX, +}; + +struct iwm_if_ops; +struct iwm_wifi_cmd; + +struct pool_entry { + int id; /* group id */ + int sid; /* super group id */ + int min_pages; /* min capacity in pages */ + int max_pages; /* max capacity in pages */ + int alloc_pages; /* allocated # of pages. incresed by driver */ + int total_freed_pages; /* total freed # of pages. incresed by UMAC */ +}; + +struct spool_entry { + int id; + int max_pages; + int alloc_pages; +}; + +struct iwm_tx_credit { + spinlock_t lock; + int pool_nr; + unsigned long full_pools_map; /* bitmap for # of filled tx pools */ + struct pool_entry pools[IWM_MACS_OUT_GROUPS]; + struct spool_entry spools[IWM_MACS_OUT_SGROUPS]; +}; + +struct iwm_notif { + struct list_head pending; + u32 cmd_id; + void *cmd; + u8 src; + void *buf; + unsigned long buf_size; +}; + +struct iwm_tid_info { + __le16 last_seq_num; + bool stopped; + struct mutex mutex; +}; + +struct iwm_sta_info { + u8 addr[ETH_ALEN]; + bool valid; + bool qos; + u8 color; + struct iwm_tid_info tid_info[IWM_UMAC_TID_NR]; +}; + +struct iwm_tx_info { + u8 sta; + u8 color; + u8 tid; +}; + +struct iwm_rx_info { + unsigned long rx_size; + unsigned long rx_buf_size; +}; + +#define IWM_NUM_KEYS 4 + +struct iwm_umac_key_hdr { + u8 mac[ETH_ALEN]; + u8 key_idx; + u8 multicast; /* BCast encrypt & BCast decrypt of frames FROM mac */ +} __packed; + +struct iwm_key { + struct iwm_umac_key_hdr hdr; + u32 cipher; + u8 key[WLAN_MAX_KEY_LEN]; + u8 seq[IW_ENCODE_SEQ_MAX_SIZE]; + int key_len; + int seq_len; +}; + +#define IWM_RX_ID_HASH 0xff +#define IWM_RX_ID_GET_HASH(id) ((id) % IWM_RX_ID_HASH) + +#define IWM_STA_TABLE_NUM 16 +#define IWM_TX_LIST_SIZE 64 +#define IWM_RX_LIST_SIZE 256 + +#define IWM_SCAN_ID_MAX 0xff + +#define IWM_STATUS_READY 0 +#define IWM_STATUS_SCANNING 1 +#define IWM_STATUS_SCAN_ABORTING 2 +#define IWM_STATUS_SME_CONNECTING 3 +#define IWM_STATUS_ASSOCIATED 4 +#define IWM_STATUS_RESETTING 5 + +struct iwm_tx_queue { + int id; + struct sk_buff_head queue; + struct sk_buff_head stopped_queue; + spinlock_t lock; + struct workqueue_struct *wq; + struct work_struct worker; + u8 concat_buf[IWM_HAL_CONCATENATE_BUF_SIZE]; + int concat_count; + u8 *concat_ptr; +}; + +/* Queues 0 ~ 3 for AC data, 5 for iPAN */ +#define IWM_TX_QUEUES 5 +#define IWM_TX_DATA_QUEUES 4 +#define IWM_TX_CMD_QUEUE 4 + +struct iwm_bss_info { + struct list_head node; + struct cfg80211_bss *cfg_bss; + struct iwm_umac_notif_bss_info *bss; +}; + +typedef int (*iwm_handler)(struct iwm_priv *priv, u8 *buf, + unsigned long buf_size, struct iwm_wifi_cmd *cmd); + +#define IWM_WATCHDOG_PERIOD (6 * HZ) + +struct iwm_priv { + struct wireless_dev *wdev; + struct iwm_if_ops *bus_ops; + + struct iwm_conf conf; + + unsigned long status; + + struct list_head pending_notif; + wait_queue_head_t notif_queue; + + wait_queue_head_t nonwifi_queue; + + unsigned long calib_done_map; + struct { + u8 *buf; + u32 size; + } calib_res[CALIBRATION_CMD_NUM]; + + struct iwm_umac_profile *umac_profile; + bool umac_profile_active; + + u8 bssid[ETH_ALEN]; + u8 channel; + u16 rate; + u32 txpower; + + struct iwm_sta_info sta_table[IWM_STA_TABLE_NUM]; + struct list_head bss_list; + + void (*nonwifi_rx_handlers[UMAC_HDI_IN_OPCODE_NONWIFI_MAX]) + (struct iwm_priv *priv, u8 *buf, unsigned long buf_size); + + const iwm_handler *umac_handlers; + const iwm_handler *lmac_handlers; + DECLARE_BITMAP(lmac_handler_map, LMAC_COMMAND_ID_NUM); + DECLARE_BITMAP(umac_handler_map, LMAC_COMMAND_ID_NUM); + DECLARE_BITMAP(udma_handler_map, LMAC_COMMAND_ID_NUM); + + struct list_head wifi_pending_cmd; + struct list_head nonwifi_pending_cmd; + u16 wifi_seq_num; + u8 nonwifi_seq_num; + spinlock_t cmd_lock; + + u32 core_enabled; + + u8 scan_id; + struct cfg80211_scan_request *scan_request; + + struct sk_buff_head rx_list; + struct list_head rx_tickets; + spinlock_t ticket_lock; + struct list_head rx_packets[IWM_RX_ID_HASH]; + spinlock_t packet_lock[IWM_RX_ID_HASH]; + struct workqueue_struct *rx_wq; + struct work_struct rx_worker; + + struct iwm_tx_credit tx_credit; + struct iwm_tx_queue txq[IWM_TX_QUEUES]; + + struct iwm_key keys[IWM_NUM_KEYS]; + s8 default_key; + + DECLARE_BITMAP(wifi_ntfy, WIFI_IF_NTFY_MAX); + wait_queue_head_t wifi_ntfy_queue; + + wait_queue_head_t mlme_queue; + + struct iw_statistics wstats; + struct delayed_work stats_request; + struct delayed_work disconnect; + struct delayed_work ct_kill_delay; + + struct iwm_debugfs dbg; + + u8 *eeprom; + struct timer_list watchdog; + struct work_struct reset_worker; + struct work_struct auth_retry_worker; + struct mutex mutex; + + u8 *req_ie; + int req_ie_len; + u8 *resp_ie; + int resp_ie_len; + + struct iwm_fw_error_hdr *last_fw_err; + char umac_version[8]; + char lmac_version[8]; + + char private[0] __attribute__((__aligned__(NETDEV_ALIGN))); +}; + +static inline void *iwm_private(struct iwm_priv *iwm) +{ + BUG_ON(!iwm); + return &iwm->private; +} + +#define hw_to_iwm(h) (h->iwm) +#define iwm_to_dev(i) (wiphy_dev(i->wdev->wiphy)) +#define iwm_to_wiphy(i) (i->wdev->wiphy) +#define wiphy_to_iwm(w) (struct iwm_priv *)(wiphy_priv(w)) +#define iwm_to_wdev(i) (i->wdev) +#define wdev_to_iwm(w) (struct iwm_priv *)(wdev_priv(w)) +#define iwm_to_ndev(i) (i->wdev->netdev) +#define ndev_to_iwm(n) (wdev_to_iwm(n->ieee80211_ptr)) +#define skb_to_rx_info(s) ((struct iwm_rx_info *)(s->cb)) +#define skb_to_tx_info(s) ((struct iwm_tx_info *)s->cb) + +void *iwm_if_alloc(int sizeof_bus, struct device *dev, + struct iwm_if_ops *if_ops); +void iwm_if_free(struct iwm_priv *iwm); +int iwm_if_add(struct iwm_priv *iwm); +void iwm_if_remove(struct iwm_priv *iwm); +int iwm_mode_to_nl80211_iftype(int mode); +int iwm_priv_init(struct iwm_priv *iwm); +void iwm_priv_deinit(struct iwm_priv *iwm); +void iwm_reset(struct iwm_priv *iwm); +void iwm_resetting(struct iwm_priv *iwm); +void iwm_tx_credit_init_pools(struct iwm_priv *iwm, + struct iwm_umac_notif_alive *alive); +int iwm_tx_credit_alloc(struct iwm_priv *iwm, int id, int nb); +int iwm_notif_send(struct iwm_priv *iwm, struct iwm_wifi_cmd *cmd, + u8 cmd_id, u8 source, u8 *buf, unsigned long buf_size); +int iwm_notif_handle(struct iwm_priv *iwm, u32 cmd, u8 source, long timeout); +void iwm_init_default_profile(struct iwm_priv *iwm, + struct iwm_umac_profile *profile); +void iwm_link_on(struct iwm_priv *iwm); +void iwm_link_off(struct iwm_priv *iwm); +int iwm_up(struct iwm_priv *iwm); +int iwm_down(struct iwm_priv *iwm); + +/* TX API */ +int iwm_tid_to_queue(u16 tid); +void iwm_tx_credit_inc(struct iwm_priv *iwm, int id, int total_freed_pages); +void iwm_tx_worker(struct work_struct *work); +int iwm_xmit_frame(struct sk_buff *skb, struct net_device *netdev); + +/* RX API */ +void iwm_rx_setup_handlers(struct iwm_priv *iwm); +int iwm_rx_handle(struct iwm_priv *iwm, u8 *buf, unsigned long buf_size); +int iwm_rx_handle_resp(struct iwm_priv *iwm, u8 *buf, unsigned long buf_size, + struct iwm_wifi_cmd *cmd); +void iwm_rx_free(struct iwm_priv *iwm); + +#endif diff --git a/trunk/drivers/net/wireless/iwmc3200wifi/lmac.h b/trunk/drivers/net/wireless/iwmc3200wifi/lmac.h new file mode 100644 index 000000000000..5ddcdf8c70c0 --- /dev/null +++ b/trunk/drivers/net/wireless/iwmc3200wifi/lmac.h @@ -0,0 +1,484 @@ +/* + * Intel Wireless Multicomm 3200 WiFi driver + * + * Copyright (C) 2009 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * + * Intel Corporation + * Samuel Ortiz + * Zhu Yi + * + */ + +#ifndef __IWM_LMAC_H__ +#define __IWM_LMAC_H__ + +struct iwm_lmac_hdr { + u8 id; + u8 flags; + __le16 seq_num; +} __packed; + +/* LMAC commands */ +#define CALIB_CFG_FLAG_SEND_COMPLETE_NTFY_AFTER_MSK 0x1 + +struct iwm_lmac_cal_cfg_elt { + __le32 enable; /* 1 means LMAC needs to do something */ + __le32 start; /* 1 to start calibration, 0 to stop */ + __le32 send_res; /* 1 for sending back results */ + __le32 apply_res; /* 1 for applying calibration results to HW */ + __le32 reserved; +} __packed; + +struct iwm_lmac_cal_cfg_status { + struct iwm_lmac_cal_cfg_elt init; + struct iwm_lmac_cal_cfg_elt periodic; + __le32 flags; /* CALIB_CFG_FLAG_SEND_COMPLETE_NTFY_AFTER_MSK */ +} __packed; + +struct iwm_lmac_cal_cfg_cmd { + struct iwm_lmac_cal_cfg_status ucode_cfg; + struct iwm_lmac_cal_cfg_status driver_cfg; + __le32 reserved; +} __packed; + +struct iwm_lmac_cal_cfg_resp { + __le32 status; +} __packed; + +#define IWM_CARD_STATE_SW_HW_ENABLED 0x00 +#define IWM_CARD_STATE_HW_DISABLED 0x01 +#define IWM_CARD_STATE_SW_DISABLED 0x02 +#define IWM_CARD_STATE_CTKILL_DISABLED 0x04 +#define IWM_CARD_STATE_IS_RXON 0x10 + +struct iwm_lmac_card_state { + __le32 flags; +} __packed; + +/** + * COEX_PRIORITY_TABLE_CMD + * + * Priority entry for each state + * Will keep two tables, for STA and WIPAN + */ +enum { + /* UN-ASSOCIATION PART */ + COEX_UNASSOC_IDLE = 0, + COEX_UNASSOC_MANUAL_SCAN, + COEX_UNASSOC_AUTO_SCAN, + + /* CALIBRATION */ + COEX_CALIBRATION, + COEX_PERIODIC_CALIBRATION, + + /* CONNECTION */ + COEX_CONNECTION_ESTAB, + + /* ASSOCIATION PART */ + COEX_ASSOCIATED_IDLE, + COEX_ASSOC_MANUAL_SCAN, + COEX_ASSOC_AUTO_SCAN, + COEX_ASSOC_ACTIVE_LEVEL, + + /* RF ON/OFF */ + COEX_RF_ON, + COEX_RF_OFF, + COEX_STAND_ALONE_DEBUG, + + /* IPNN */ + COEX_IPAN_ASSOC_LEVEL, + + /* RESERVED */ + COEX_RSRVD1, + COEX_RSRVD2, + + COEX_EVENTS_NUM +}; + +#define COEX_EVT_FLAG_MEDIUM_FREE_NTFY_MSK 0x1 +#define COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_MSK 0x2 +#define COEX_EVT_FLAG_DELAY_MEDIUM_FREE_NTFY_MSK 0x4 + +struct coex_event { + u8 req_prio; + u8 win_med_prio; + u8 reserved; + u8 flags; +} __packed; + +#define COEX_FLAGS_STA_TABLE_VALID_MSK 0x1 +#define COEX_FLAGS_UNASSOC_WAKEUP_UMASK_MSK 0x4 +#define COEX_FLAGS_ASSOC_WAKEUP_UMASK_MSK 0x8 +#define COEX_FLAGS_COEX_ENABLE_MSK 0x80 + +struct iwm_coex_prio_table_cmd { + u8 flags; + u8 reserved[3]; + struct coex_event sta_prio[COEX_EVENTS_NUM]; +} __packed; + +/* Coexistence definitions + * + * Constants to fill in the Priorities' Tables + * RP - Requested Priority + * WP - Win Medium Priority: priority assigned when the contention has been won + * FLAGS - Combination of COEX_EVT_FLAG_MEDIUM_FREE_NTFY_MSK and + * COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_MSK + */ + +#define COEX_UNASSOC_IDLE_FLAGS 0 +#define COEX_UNASSOC_MANUAL_SCAN_FLAGS (COEX_EVT_FLAG_MEDIUM_FREE_NTFY_MSK | \ + COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_MSK) +#define COEX_UNASSOC_AUTO_SCAN_FLAGS (COEX_EVT_FLAG_MEDIUM_FREE_NTFY_MSK | \ + COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_MSK) +#define COEX_CALIBRATION_FLAGS (COEX_EVT_FLAG_MEDIUM_FREE_NTFY_MSK | \ + COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_MSK) +#define COEX_PERIODIC_CALIBRATION_FLAGS 0 +/* COEX_CONNECTION_ESTAB: we need DELAY_MEDIUM_FREE_NTFY to let WiMAX + * disconnect from network. */ +#define COEX_CONNECTION_ESTAB_FLAGS (COEX_EVT_FLAG_MEDIUM_FREE_NTFY_MSK | \ + COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_MSK | \ + COEX_EVT_FLAG_DELAY_MEDIUM_FREE_NTFY_MSK) +#define COEX_ASSOCIATED_IDLE_FLAGS 0 +#define COEX_ASSOC_MANUAL_SCAN_FLAGS (COEX_EVT_FLAG_MEDIUM_FREE_NTFY_MSK | \ + COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_MSK) +#define COEX_ASSOC_AUTO_SCAN_FLAGS (COEX_EVT_FLAG_MEDIUM_FREE_NTFY_MSK | \ + COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_MSK) +#define COEX_ASSOC_ACTIVE_LEVEL_FLAGS 0 +#define COEX_RF_ON_FLAGS 0 +#define COEX_RF_OFF_FLAGS 0 +#define COEX_STAND_ALONE_DEBUG_FLAGS (COEX_EVT_FLAG_MEDIUM_FREE_NTFY_MSK | \ + COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_MSK) +#define COEX_IPAN_ASSOC_LEVEL_FLAGS (COEX_EVT_FLAG_MEDIUM_FREE_NTFY_MSK | \ + COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_MSK | \ + COEX_EVT_FLAG_DELAY_MEDIUM_FREE_NTFY_MSK) +#define COEX_RSRVD1_FLAGS 0 +#define COEX_RSRVD2_FLAGS 0 +/* XOR_RF_ON is the event wrapping all radio ownership. We need + * DELAY_MEDIUM_FREE_NTFY to let WiMAX disconnect from network. */ +#define COEX_XOR_RF_ON_FLAGS (COEX_EVT_FLAG_MEDIUM_FREE_NTFY_MSK | \ + COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_MSK | \ + COEX_EVT_FLAG_DELAY_MEDIUM_FREE_NTFY_MSK) + +/* CT kill config command */ +struct iwm_ct_kill_cfg_cmd { + u32 exit_threshold; + u32 reserved; + u32 entry_threshold; +} __packed; + + +/* LMAC OP CODES */ +#define REPLY_PAD 0x0 +#define REPLY_ALIVE 0x1 +#define REPLY_ERROR 0x2 +#define REPLY_ECHO 0x3 +#define REPLY_HALT 0x6 + +/* RXON state commands */ +#define REPLY_RX_ON 0x10 +#define REPLY_RX_ON_ASSOC 0x11 +#define REPLY_RX_OFF 0x12 +#define REPLY_QOS_PARAM 0x13 +#define REPLY_RX_ON_TIMING 0x14 +#define REPLY_INTERNAL_QOS_PARAM 0x15 +#define REPLY_RX_INT_TIMEOUT_CNFG 0x16 +#define REPLY_NULL 0x17 + +/* Multi-Station support */ +#define REPLY_ADD_STA 0x18 +#define REPLY_REMOVE_STA 0x19 +#define REPLY_RESET_ALL_STA 0x1a + +/* RX, TX */ +#define REPLY_ALM_RX 0x1b +#define REPLY_TX 0x1c +#define REPLY_TXFIFO_FLUSH 0x1e + +/* MISC commands */ +#define REPLY_MGMT_MCAST_KEY 0x1f +#define REPLY_WEPKEY 0x20 +#define REPLY_INIT_IV 0x21 +#define REPLY_WRITE_MIB 0x22 +#define REPLY_READ_MIB 0x23 +#define REPLY_RADIO_FE 0x24 +#define REPLY_TXFIFO_CFG 0x25 +#define REPLY_WRITE_READ 0x26 +#define REPLY_INSTALL_SEC_KEY 0x27 + + +#define REPLY_RATE_SCALE 0x47 +#define REPLY_LEDS_CMD 0x48 +#define REPLY_TX_LINK_QUALITY_CMD 0x4e +#define REPLY_ANA_MIB_OVERRIDE_CMD 0x4f +#define REPLY_WRITE2REG_CMD 0x50 + +/* winfi-wifi coexistence */ +#define COEX_PRIORITY_TABLE_CMD 0x5a +#define COEX_MEDIUM_NOTIFICATION 0x5b +#define COEX_EVENT_CMD 0x5c + +/* more Protocol and Protocol-test commands */ +#define REPLY_MAX_SLEEP_TIME_CMD 0x61 +#define CALIBRATION_CFG_CMD 0x65 +#define CALIBRATION_RES_NOTIFICATION 0x66 +#define CALIBRATION_COMPLETE_NOTIFICATION 0x67 + +/* Measurements */ +#define REPLY_QUIET_CMD 0x71 +#define REPLY_CHANNEL_SWITCH 0x72 +#define CHANNEL_SWITCH_NOTIFICATION 0x73 + +#define REPLY_SPECTRUM_MEASUREMENT_CMD 0x74 +#define SPECTRUM_MEASURE_NOTIFICATION 0x75 +#define REPLY_MEASUREMENT_ABORT_CMD 0x76 + +/* Power Management */ +#define POWER_TABLE_CMD 0x77 +#define SAVE_RESTORE_ADDRESS_CMD 0x78 +#define REPLY_WATERMARK_CMD 0x79 +#define PM_DEBUG_STATISTIC_NOTIFIC 0x7B +#define PD_FLUSH_N_NOTIFICATION 0x7C + +/* Scan commands and notifications */ +#define REPLY_SCAN_REQUEST_CMD 0x80 +#define REPLY_SCAN_ABORT_CMD 0x81 +#define SCAN_START_NOTIFICATION 0x82 +#define SCAN_RESULTS_NOTIFICATION 0x83 +#define SCAN_COMPLETE_NOTIFICATION 0x84 + +/* Continuous TX commands */ +#define REPLY_CONT_TX_CMD 0x85 +#define END_OF_CONT_TX_NOTIFICATION 0x86 + +/* Timer/Eeprom commands */ +#define TIMER_CMD 0x87 +#define EEPROM_WRITE_CMD 0x88 + +/* PAPD commands */ +#define FEEDBACK_REQUEST_NOTIFICATION 0x8b +#define REPLY_CW_CMD 0x8c + +/* IBSS/AP commands Continue */ +#define BEACON_NOTIFICATION 0x90 +#define REPLY_TX_BEACON 0x91 +#define REPLY_REQUEST_ATIM 0x93 +#define WHO_IS_AWAKE_NOTIFICATION 0x94 +#define TX_PWR_DBM_LIMIT_CMD 0x95 +#define QUIET_NOTIFICATION 0x96 +#define TX_PWR_TABLE_CMD 0x97 +#define TX_ANT_CONFIGURATION_CMD 0x98 +#define MEASURE_ABORT_NOTIFICATION 0x99 +#define REPLY_CALIBRATION_TUNE 0x9a + +/* bt config command */ +#define REPLY_BT_CONFIG 0x9b +#define REPLY_STATISTICS_CMD 0x9c +#define STATISTICS_NOTIFICATION 0x9d + +/* RF-KILL commands and notifications */ +#define REPLY_CARD_STATE_CMD 0xa0 +#define CARD_STATE_NOTIFICATION 0xa1 + +/* Missed beacons notification */ +#define MISSED_BEACONS_NOTIFICATION 0xa2 +#define MISSED_BEACONS_NOTIFICATION_TH_CMD 0xa3 + +#define REPLY_CT_KILL_CONFIG_CMD 0xa4 + +/* HD commands and notifications */ +#define REPLY_HD_PARAMS_CMD 0xa6 +#define HD_PARAMS_NOTIFICATION 0xa7 +#define SENSITIVITY_CMD 0xa8 +#define U_APSD_PARAMS_CMD 0xa9 +#define NOISY_PLATFORM_CMD 0xaa +#define ILLEGAL_CMD 0xac +#define REPLY_PHY_CALIBRATION_CMD 0xb0 +#define REPLAY_RX_GAIN_CALIB_CMD 0xb1 + +/* WiPAN commands */ +#define REPLY_WIPAN_PARAMS_CMD 0xb2 +#define REPLY_WIPAN_RX_ON_CMD 0xb3 +#define REPLY_WIPAN_RX_ON_TIMING 0xb4 +#define REPLY_WIPAN_TX_PWR_TABLE_CMD 0xb5 +#define REPLY_WIPAN_RXON_ASSOC_CMD 0xb6 +#define REPLY_WIPAN_QOS_PARAM 0xb7 +#define WIPAN_REPLY_WEPKEY 0xb8 + +/* BeamForming commands */ +#define BEAMFORMER_CFG_CMD 0xba +#define BEAMFORMEE_NOTIFICATION 0xbb + +/* TGn new Commands */ +#define REPLY_RX_PHY_CMD 0xc0 +#define REPLY_RX_MPDU_CMD 0xc1 +#define REPLY_MULTICAST_HASH 0xc2 +#define REPLY_KDR_RX 0xc3 +#define REPLY_RX_DSP_EXT_INFO 0xc4 +#define REPLY_COMPRESSED_BA 0xc5 + +/* PNC commands */ +#define PNC_CONFIG_CMD 0xc8 +#define PNC_UPDATE_TABLE_CMD 0xc9 +#define XVT_GENERAL_CTRL_CMD 0xca +#define REPLY_LEGACY_RADIO_FE 0xdd + +/* WoWLAN commands */ +#define WOWLAN_PATTERNS 0xe0 +#define WOWLAN_WAKEUP_FILTER 0xe1 +#define WOWLAN_TSC_RSC_PARAM 0xe2 +#define WOWLAN_TKIP_PARAM 0xe3 +#define WOWLAN_KEK_KCK_MATERIAL 0xe4 +#define WOWLAN_GET_STATUSES 0xe5 +#define WOWLAN_TX_POWER_PER_DB 0xe6 +#define REPLY_WOWLAN_GET_STATUSES WOWLAN_GET_STATUSES + +#define REPLY_DEBUG_CMD 0xf0 +#define REPLY_DSP_DEBUG_CMD 0xf1 +#define REPLY_DEBUG_MONITOR_CMD 0xf2 +#define REPLY_DEBUG_XVT_CMD 0xf3 +#define REPLY_DEBUG_DC_CALIB 0xf4 +#define REPLY_DYNAMIC_BP 0xf5 + +/* General purpose Commands */ +#define REPLY_GP1_CMD 0xfa +#define REPLY_GP2_CMD 0xfb +#define REPLY_GP3_CMD 0xfc +#define REPLY_GP4_CMD 0xfd +#define REPLY_REPLAY_WRAPPER 0xfe +#define REPLY_FRAME_DURATION_CALC_CMD 0xff + +#define LMAC_COMMAND_ID_MAX 0xff +#define LMAC_COMMAND_ID_NUM (LMAC_COMMAND_ID_MAX + 1) + + +/* Calibration */ + +enum { + PHY_CALIBRATE_DC_CMD = 0, + PHY_CALIBRATE_LO_CMD = 1, + PHY_CALIBRATE_RX_BB_CMD = 2, + PHY_CALIBRATE_TX_IQ_CMD = 3, + PHY_CALIBRATE_RX_IQ_CMD = 4, + PHY_CALIBRATION_NOISE_CMD = 5, + PHY_CALIBRATE_AGC_TABLE_CMD = 6, + PHY_CALIBRATE_CRYSTAL_FRQ_CMD = 7, + PHY_CALIBRATE_OPCODES_NUM, + SHILOH_PHY_CALIBRATE_DC_CMD = 8, + SHILOH_PHY_CALIBRATE_LO_CMD = 9, + SHILOH_PHY_CALIBRATE_RX_BB_CMD = 10, + SHILOH_PHY_CALIBRATE_TX_IQ_CMD = 11, + SHILOH_PHY_CALIBRATE_RX_IQ_CMD = 12, + SHILOH_PHY_CALIBRATION_NOISE_CMD = 13, + SHILOH_PHY_CALIBRATE_AGC_TABLE_CMD = 14, + SHILOH_PHY_CALIBRATE_CRYSTAL_FRQ_CMD = 15, + SHILOH_PHY_CALIBRATE_BASE_BAND_CMD = 16, + SHILOH_PHY_CALIBRATE_TXIQ_PERIODIC_CMD = 17, + CALIBRATION_CMD_NUM, +}; + +enum { + CALIB_CFG_RX_BB_IDX = 0, + CALIB_CFG_DC_IDX = 1, + CALIB_CFG_LO_IDX = 2, + CALIB_CFG_TX_IQ_IDX = 3, + CALIB_CFG_RX_IQ_IDX = 4, + CALIB_CFG_NOISE_IDX = 5, + CALIB_CFG_CRYSTAL_IDX = 6, + CALIB_CFG_TEMPERATURE_IDX = 7, + CALIB_CFG_PAPD_IDX = 8, + CALIB_CFG_LAST_IDX = CALIB_CFG_PAPD_IDX, + CALIB_CFG_MODULE_NUM, +}; + +#define IWM_CALIB_MAP_INIT_MSK 0xFFFF +#define IWM_CALIB_MAP_PER_LMAC(m) ((m & 0xFF0000) >> 16) +#define IWM_CALIB_MAP_PER_UMAC(m) ((m & 0xFF000000) >> 24) +#define IWM_CALIB_OPCODE_TO_INDEX(op) (op - PHY_CALIBRATE_OPCODES_NUM) + +struct iwm_lmac_calib_hdr { + u8 opcode; + u8 first_grp; + u8 grp_num; + u8 all_data_valid; +} __packed; + +#define IWM_LMAC_CALIB_FREQ_GROUPS_NR 7 +#define IWM_CALIB_FREQ_GROUPS_NR 5 +#define IWM_CALIB_DC_MODES_NR 12 + +struct iwm_calib_rxiq_entry { + u16 ptam_postdist_ars; + u16 ptam_postdist_arc; +} __packed; + +struct iwm_calib_rxiq_group { + struct iwm_calib_rxiq_entry mode[IWM_CALIB_DC_MODES_NR]; +} __packed; + +struct iwm_lmac_calib_rxiq { + struct iwm_calib_rxiq_group group[IWM_LMAC_CALIB_FREQ_GROUPS_NR]; +} __packed; + +struct iwm_calib_rxiq { + struct iwm_lmac_calib_hdr hdr; + struct iwm_calib_rxiq_group group[IWM_CALIB_FREQ_GROUPS_NR]; +} __packed; + +#define LMAC_STA_ID_SEED 0x0f +#define LMAC_STA_ID_POS 0 + +#define LMAC_STA_COLOR_SEED 0x7 +#define LMAC_STA_COLOR_POS 4 + +struct iwm_lmac_power_report { + u8 pa_status; + u8 pa_integ_res_A[3]; + u8 pa_integ_res_B[3]; + u8 pa_integ_res_C[3]; +} __packed; + +struct iwm_lmac_tx_resp { + u8 frame_cnt; /* 1-no aggregation, greater then 1 - aggregation */ + u8 bt_kill_cnt; + __le16 retry_cnt; + __le32 initial_tx_rate; + __le16 wireless_media_time; + struct iwm_lmac_power_report power_report; + __le32 tfd_info; + __le16 seq_ctl; + __le16 byte_cnt; + u8 tlc_rate_info; + u8 ra_tid; + __le16 frame_ctl; + __le32 status; +} __packed; + +#endif diff --git a/trunk/drivers/net/wireless/iwmc3200wifi/main.c b/trunk/drivers/net/wireless/iwmc3200wifi/main.c new file mode 100644 index 000000000000..1f868b166d10 --- /dev/null +++ b/trunk/drivers/net/wireless/iwmc3200wifi/main.c @@ -0,0 +1,847 @@ +/* + * Intel Wireless Multicomm 3200 WiFi driver + * + * Copyright (C) 2009 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * + * Intel Corporation + * Samuel Ortiz + * Zhu Yi + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "iwm.h" +#include "debug.h" +#include "bus.h" +#include "umac.h" +#include "commands.h" +#include "hal.h" +#include "fw.h" +#include "rx.h" + +static struct iwm_conf def_iwm_conf = { + + .sdio_ior_timeout = 5000, + .calib_map = BIT(CALIB_CFG_DC_IDX) | + BIT(CALIB_CFG_LO_IDX) | + BIT(CALIB_CFG_TX_IQ_IDX) | + BIT(CALIB_CFG_RX_IQ_IDX) | + BIT(SHILOH_PHY_CALIBRATE_BASE_BAND_CMD), + .expected_calib_map = BIT(PHY_CALIBRATE_DC_CMD) | + BIT(PHY_CALIBRATE_LO_CMD) | + BIT(PHY_CALIBRATE_TX_IQ_CMD) | + BIT(PHY_CALIBRATE_RX_IQ_CMD) | + BIT(SHILOH_PHY_CALIBRATE_BASE_BAND_CMD), + .ct_kill_entry = 110, + .ct_kill_exit = 110, + .reset_on_fatal_err = 1, + .auto_connect = 1, + .enable_qos = 1, + .mode = UMAC_MODE_BSS, + + /* UMAC configuration */ + .power_index = 0, + .frag_threshold = IEEE80211_MAX_FRAG_THRESHOLD, + .rts_threshold = IEEE80211_MAX_RTS_THRESHOLD, + .cts_to_self = 0, + + .assoc_timeout = 2, + .roam_timeout = 10, + .wireless_mode = WIRELESS_MODE_11A | WIRELESS_MODE_11G | + WIRELESS_MODE_11N, + + /* IBSS */ + .ibss_band = UMAC_BAND_2GHZ, + .ibss_channel = 1, + + .mac_addr = {0x00, 0x02, 0xb3, 0x01, 0x02, 0x03}, +}; + +static bool modparam_reset; +module_param_named(reset, modparam_reset, bool, 0644); +MODULE_PARM_DESC(reset, "reset on firmware errors (default 0 [not reset])"); + +static bool modparam_wimax_enable = true; +module_param_named(wimax_enable, modparam_wimax_enable, bool, 0644); +MODULE_PARM_DESC(wimax_enable, "Enable wimax core (default 1 [wimax enabled])"); + +int iwm_mode_to_nl80211_iftype(int mode) +{ + switch (mode) { + case UMAC_MODE_BSS: + return NL80211_IFTYPE_STATION; + case UMAC_MODE_IBSS: + return NL80211_IFTYPE_ADHOC; + default: + return NL80211_IFTYPE_UNSPECIFIED; + } + + return 0; +} + +static void iwm_statistics_request(struct work_struct *work) +{ + struct iwm_priv *iwm = + container_of(work, struct iwm_priv, stats_request.work); + + iwm_send_umac_stats_req(iwm, 0); +} + +static void iwm_disconnect_work(struct work_struct *work) +{ + struct iwm_priv *iwm = + container_of(work, struct iwm_priv, disconnect.work); + + if (iwm->umac_profile_active) + iwm_invalidate_mlme_profile(iwm); + + clear_bit(IWM_STATUS_ASSOCIATED, &iwm->status); + iwm->umac_profile_active = false; + memset(iwm->bssid, 0, ETH_ALEN); + iwm->channel = 0; + + iwm_link_off(iwm); + + wake_up_interruptible(&iwm->mlme_queue); + + cfg80211_disconnected(iwm_to_ndev(iwm), 0, NULL, 0, GFP_KERNEL); +} + +static void iwm_ct_kill_work(struct work_struct *work) +{ + struct iwm_priv *iwm = + container_of(work, struct iwm_priv, ct_kill_delay.work); + struct wiphy *wiphy = iwm_to_wiphy(iwm); + + IWM_INFO(iwm, "CT kill delay timeout\n"); + + wiphy_rfkill_set_hw_state(wiphy, false); +} + +static int __iwm_up(struct iwm_priv *iwm); +static int __iwm_down(struct iwm_priv *iwm); + +static void iwm_reset_worker(struct work_struct *work) +{ + struct iwm_priv *iwm; + struct iwm_umac_profile *profile = NULL; + int uninitialized_var(ret), retry = 0; + + iwm = container_of(work, struct iwm_priv, reset_worker); + + /* + * XXX: The iwm->mutex is introduced purely for this reset work, + * because the other users for iwm_up and iwm_down are only netdev + * ndo_open and ndo_stop which are already protected by rtnl. + * Please remove iwm->mutex together if iwm_reset_worker() is not + * required in the future. + */ + if (!mutex_trylock(&iwm->mutex)) { + IWM_WARN(iwm, "We are in the middle of interface bringing " + "UP/DOWN. Skip driver resetting.\n"); + return; + } + + if (iwm->umac_profile_active) { + profile = kmalloc(sizeof(struct iwm_umac_profile), GFP_KERNEL); + if (profile) + memcpy(profile, iwm->umac_profile, sizeof(*profile)); + else + IWM_ERR(iwm, "Couldn't alloc memory for profile\n"); + } + + __iwm_down(iwm); + + while (retry++ < 3) { + ret = __iwm_up(iwm); + if (!ret) + break; + + schedule_timeout_uninterruptible(10 * HZ); + } + + if (ret) { + IWM_WARN(iwm, "iwm_up() failed: %d\n", ret); + + kfree(profile); + goto out; + } + + if (profile) { + IWM_DBG_MLME(iwm, DBG, "Resend UMAC profile\n"); + memcpy(iwm->umac_profile, profile, sizeof(*profile)); + iwm_send_mlme_profile(iwm); + kfree(profile); + } else + clear_bit(IWM_STATUS_RESETTING, &iwm->status); + + out: + mutex_unlock(&iwm->mutex); +} + +static void iwm_auth_retry_worker(struct work_struct *work) +{ + struct iwm_priv *iwm; + int i, ret; + + iwm = container_of(work, struct iwm_priv, auth_retry_worker); + if (iwm->umac_profile_active) { + ret = iwm_invalidate_mlme_profile(iwm); + if (ret < 0) + return; + } + + iwm->umac_profile->sec.auth_type = UMAC_AUTH_TYPE_LEGACY_PSK; + + ret = iwm_send_mlme_profile(iwm); + if (ret < 0) + return; + + for (i = 0; i < IWM_NUM_KEYS; i++) + if (iwm->keys[i].key_len) + iwm_set_key(iwm, 0, &iwm->keys[i]); + + iwm_set_tx_key(iwm, iwm->default_key); +} + + + +static void iwm_watchdog(unsigned long data) +{ + struct iwm_priv *iwm = (struct iwm_priv *)data; + + IWM_WARN(iwm, "Watchdog expired: UMAC stalls!\n"); + + if (modparam_reset) + iwm_resetting(iwm); +} + +int iwm_priv_init(struct iwm_priv *iwm) +{ + int i, j; + char name[32]; + + iwm->status = 0; + INIT_LIST_HEAD(&iwm->pending_notif); + init_waitqueue_head(&iwm->notif_queue); + init_waitqueue_head(&iwm->nonwifi_queue); + init_waitqueue_head(&iwm->wifi_ntfy_queue); + init_waitqueue_head(&iwm->mlme_queue); + memcpy(&iwm->conf, &def_iwm_conf, sizeof(struct iwm_conf)); + spin_lock_init(&iwm->tx_credit.lock); + INIT_LIST_HEAD(&iwm->wifi_pending_cmd); + INIT_LIST_HEAD(&iwm->nonwifi_pending_cmd); + iwm->wifi_seq_num = UMAC_WIFI_SEQ_NUM_BASE; + iwm->nonwifi_seq_num = UMAC_NONWIFI_SEQ_NUM_BASE; + spin_lock_init(&iwm->cmd_lock); + iwm->scan_id = 1; + INIT_DELAYED_WORK(&iwm->stats_request, iwm_statistics_request); + INIT_DELAYED_WORK(&iwm->disconnect, iwm_disconnect_work); + INIT_DELAYED_WORK(&iwm->ct_kill_delay, iwm_ct_kill_work); + INIT_WORK(&iwm->reset_worker, iwm_reset_worker); + INIT_WORK(&iwm->auth_retry_worker, iwm_auth_retry_worker); + INIT_LIST_HEAD(&iwm->bss_list); + + skb_queue_head_init(&iwm->rx_list); + INIT_LIST_HEAD(&iwm->rx_tickets); + spin_lock_init(&iwm->ticket_lock); + for (i = 0; i < IWM_RX_ID_HASH; i++) { + INIT_LIST_HEAD(&iwm->rx_packets[i]); + spin_lock_init(&iwm->packet_lock[i]); + } + + INIT_WORK(&iwm->rx_worker, iwm_rx_worker); + + iwm->rx_wq = create_singlethread_workqueue(KBUILD_MODNAME "_rx"); + if (!iwm->rx_wq) + return -EAGAIN; + + for (i = 0; i < IWM_TX_QUEUES; i++) { + INIT_WORK(&iwm->txq[i].worker, iwm_tx_worker); + snprintf(name, 32, KBUILD_MODNAME "_tx_%d", i); + iwm->txq[i].id = i; + iwm->txq[i].wq = create_singlethread_workqueue(name); + if (!iwm->txq[i].wq) + return -EAGAIN; + + skb_queue_head_init(&iwm->txq[i].queue); + skb_queue_head_init(&iwm->txq[i].stopped_queue); + spin_lock_init(&iwm->txq[i].lock); + } + + for (i = 0; i < IWM_NUM_KEYS; i++) + memset(&iwm->keys[i], 0, sizeof(struct iwm_key)); + + iwm->default_key = -1; + + for (i = 0; i < IWM_STA_TABLE_NUM; i++) + for (j = 0; j < IWM_UMAC_TID_NR; j++) { + mutex_init(&iwm->sta_table[i].tid_info[j].mutex); + iwm->sta_table[i].tid_info[j].stopped = false; + } + + init_timer(&iwm->watchdog); + iwm->watchdog.function = iwm_watchdog; + iwm->watchdog.data = (unsigned long)iwm; + mutex_init(&iwm->mutex); + + iwm->last_fw_err = kzalloc(sizeof(struct iwm_fw_error_hdr), + GFP_KERNEL); + if (iwm->last_fw_err == NULL) + return -ENOMEM; + + return 0; +} + +void iwm_priv_deinit(struct iwm_priv *iwm) +{ + int i; + + for (i = 0; i < IWM_TX_QUEUES; i++) + destroy_workqueue(iwm->txq[i].wq); + + destroy_workqueue(iwm->rx_wq); + kfree(iwm->last_fw_err); +} + +/* + * We reset all the structures, and we reset the UMAC. + * After calling this routine, you're expected to reload + * the firmware. + */ +void iwm_reset(struct iwm_priv *iwm) +{ + struct iwm_notif *notif, *next; + + if (test_bit(IWM_STATUS_READY, &iwm->status)) + iwm_target_reset(iwm); + + if (test_bit(IWM_STATUS_RESETTING, &iwm->status)) { + iwm->status = 0; + set_bit(IWM_STATUS_RESETTING, &iwm->status); + } else + iwm->status = 0; + iwm->scan_id = 1; + + list_for_each_entry_safe(notif, next, &iwm->pending_notif, pending) { + list_del(¬if->pending); + kfree(notif->buf); + kfree(notif); + } + + iwm_cmd_flush(iwm); + + flush_workqueue(iwm->rx_wq); + + iwm_link_off(iwm); +} + +void iwm_resetting(struct iwm_priv *iwm) +{ + set_bit(IWM_STATUS_RESETTING, &iwm->status); + + schedule_work(&iwm->reset_worker); +} + +/* + * Notification code: + * + * We're faced with the following issue: Any host command can + * have an answer or not, and if there's an answer to expect, + * it can be treated synchronously or asynchronously. + * To work around the synchronous answer case, we implemented + * our notification mechanism. + * When a code path needs to wait for a command response + * synchronously, it calls notif_handle(), which waits for the + * right notification to show up, and then process it. Before + * starting to wait, it registered as a waiter for this specific + * answer (by toggling a bit in on of the handler_map), so that + * the rx code knows that it needs to send a notification to the + * waiting processes. It does so by calling iwm_notif_send(), + * which adds the notification to the pending notifications list, + * and then wakes the waiting processes up. + */ +int iwm_notif_send(struct iwm_priv *iwm, struct iwm_wifi_cmd *cmd, + u8 cmd_id, u8 source, u8 *buf, unsigned long buf_size) +{ + struct iwm_notif *notif; + + notif = kzalloc(sizeof(struct iwm_notif), GFP_KERNEL); + if (!notif) { + IWM_ERR(iwm, "Couldn't alloc memory for notification\n"); + return -ENOMEM; + } + + INIT_LIST_HEAD(¬if->pending); + notif->cmd = cmd; + notif->cmd_id = cmd_id; + notif->src = source; + notif->buf = kzalloc(buf_size, GFP_KERNEL); + if (!notif->buf) { + IWM_ERR(iwm, "Couldn't alloc notification buffer\n"); + kfree(notif); + return -ENOMEM; + } + notif->buf_size = buf_size; + memcpy(notif->buf, buf, buf_size); + list_add_tail(¬if->pending, &iwm->pending_notif); + + wake_up_interruptible(&iwm->notif_queue); + + return 0; +} + +static struct iwm_notif *iwm_notif_find(struct iwm_priv *iwm, u32 cmd, + u8 source) +{ + struct iwm_notif *notif; + + list_for_each_entry(notif, &iwm->pending_notif, pending) { + if ((notif->cmd_id == cmd) && (notif->src == source)) { + list_del(¬if->pending); + return notif; + } + } + + return NULL; +} + +static struct iwm_notif *iwm_notif_wait(struct iwm_priv *iwm, u32 cmd, + u8 source, long timeout) +{ + int ret; + struct iwm_notif *notif; + unsigned long *map = NULL; + + switch (source) { + case IWM_SRC_LMAC: + map = &iwm->lmac_handler_map[0]; + break; + case IWM_SRC_UMAC: + map = &iwm->umac_handler_map[0]; + break; + case IWM_SRC_UDMA: + map = &iwm->udma_handler_map[0]; + break; + } + + set_bit(cmd, map); + + ret = wait_event_interruptible_timeout(iwm->notif_queue, + ((notif = iwm_notif_find(iwm, cmd, source)) != NULL), + timeout); + clear_bit(cmd, map); + + if (!ret) + return NULL; + + return notif; +} + +int iwm_notif_handle(struct iwm_priv *iwm, u32 cmd, u8 source, long timeout) +{ + int ret; + struct iwm_notif *notif; + + notif = iwm_notif_wait(iwm, cmd, source, timeout); + if (!notif) + return -ETIME; + + ret = iwm_rx_handle_resp(iwm, notif->buf, notif->buf_size, notif->cmd); + kfree(notif->buf); + kfree(notif); + + return ret; +} + +static int iwm_config_boot_params(struct iwm_priv *iwm) +{ + struct iwm_udma_nonwifi_cmd target_cmd; + int ret; + + /* check Wimax is off and config debug monitor */ + if (!modparam_wimax_enable) { + u32 data1 = 0x1f; + u32 addr1 = 0x606BE258; + + u32 data2_set = 0x0; + u32 data2_clr = 0x1; + u32 addr2 = 0x606BE100; + + u32 data3 = 0x1; + u32 addr3 = 0x606BEC00; + + target_cmd.resp = 0; + target_cmd.handle_by_hw = 0; + target_cmd.eop = 1; + + target_cmd.opcode = UMAC_HDI_OUT_OPCODE_WRITE; + target_cmd.addr = cpu_to_le32(addr1); + target_cmd.op1_sz = cpu_to_le32(sizeof(u32)); + target_cmd.op2 = 0; + + ret = iwm_hal_send_target_cmd(iwm, &target_cmd, &data1); + if (ret < 0) { + IWM_ERR(iwm, "iwm_hal_send_target_cmd failed\n"); + return ret; + } + + target_cmd.opcode = UMAC_HDI_OUT_OPCODE_READ_MODIFY_WRITE; + target_cmd.addr = cpu_to_le32(addr2); + target_cmd.op1_sz = cpu_to_le32(data2_set); + target_cmd.op2 = cpu_to_le32(data2_clr); + + ret = iwm_hal_send_target_cmd(iwm, &target_cmd, &data1); + if (ret < 0) { + IWM_ERR(iwm, "iwm_hal_send_target_cmd failed\n"); + return ret; + } + + target_cmd.opcode = UMAC_HDI_OUT_OPCODE_WRITE; + target_cmd.addr = cpu_to_le32(addr3); + target_cmd.op1_sz = cpu_to_le32(sizeof(u32)); + target_cmd.op2 = 0; + + ret = iwm_hal_send_target_cmd(iwm, &target_cmd, &data3); + if (ret < 0) { + IWM_ERR(iwm, "iwm_hal_send_target_cmd failed\n"); + return ret; + } + } + + return 0; +} + +void iwm_init_default_profile(struct iwm_priv *iwm, + struct iwm_umac_profile *profile) +{ + memset(profile, 0, sizeof(struct iwm_umac_profile)); + + profile->sec.auth_type = UMAC_AUTH_TYPE_OPEN; + profile->sec.flags = UMAC_SEC_FLG_LEGACY_PROFILE; + profile->sec.ucast_cipher = UMAC_CIPHER_TYPE_NONE; + profile->sec.mcast_cipher = UMAC_CIPHER_TYPE_NONE; + + if (iwm->conf.enable_qos) + profile->flags |= cpu_to_le16(UMAC_PROFILE_QOS_ALLOWED); + + profile->wireless_mode = iwm->conf.wireless_mode; + profile->mode = cpu_to_le32(iwm->conf.mode); + + profile->ibss.atim = 0; + profile->ibss.beacon_interval = 100; + profile->ibss.join_only = 0; + profile->ibss.band = iwm->conf.ibss_band; + profile->ibss.channel = iwm->conf.ibss_channel; +} + +void iwm_link_on(struct iwm_priv *iwm) +{ + netif_carrier_on(iwm_to_ndev(iwm)); + netif_tx_wake_all_queues(iwm_to_ndev(iwm)); + + iwm_send_umac_stats_req(iwm, 0); +} + +void iwm_link_off(struct iwm_priv *iwm) +{ + struct iw_statistics *wstats = &iwm->wstats; + int i; + + netif_tx_stop_all_queues(iwm_to_ndev(iwm)); + netif_carrier_off(iwm_to_ndev(iwm)); + + for (i = 0; i < IWM_TX_QUEUES; i++) { + skb_queue_purge(&iwm->txq[i].queue); + skb_queue_purge(&iwm->txq[i].stopped_queue); + + iwm->txq[i].concat_count = 0; + iwm->txq[i].concat_ptr = iwm->txq[i].concat_buf; + + flush_workqueue(iwm->txq[i].wq); + } + + iwm_rx_free(iwm); + + cancel_delayed_work_sync(&iwm->stats_request); + memset(wstats, 0, sizeof(struct iw_statistics)); + wstats->qual.updated = IW_QUAL_ALL_INVALID; + + kfree(iwm->req_ie); + iwm->req_ie = NULL; + iwm->req_ie_len = 0; + kfree(iwm->resp_ie); + iwm->resp_ie = NULL; + iwm->resp_ie_len = 0; + + del_timer_sync(&iwm->watchdog); +} + +static void iwm_bss_list_clean(struct iwm_priv *iwm) +{ + struct iwm_bss_info *bss, *next; + + list_for_each_entry_safe(bss, next, &iwm->bss_list, node) { + list_del(&bss->node); + kfree(bss->bss); + kfree(bss); + } +} + +static int iwm_channels_init(struct iwm_priv *iwm) +{ + int ret; + + ret = iwm_send_umac_channel_list(iwm); + if (ret) { + IWM_ERR(iwm, "Send channel list failed\n"); + return ret; + } + + ret = iwm_notif_handle(iwm, UMAC_CMD_OPCODE_GET_CHAN_INFO_LIST, + IWM_SRC_UMAC, WAIT_NOTIF_TIMEOUT); + if (ret) { + IWM_ERR(iwm, "Didn't get a channel list notification\n"); + return ret; + } + + return 0; +} + +static int __iwm_up(struct iwm_priv *iwm) +{ + int ret; + struct iwm_notif *notif_reboot, *notif_ack = NULL; + struct wiphy *wiphy = iwm_to_wiphy(iwm); + u32 wireless_mode; + + ret = iwm_bus_enable(iwm); + if (ret) { + IWM_ERR(iwm, "Couldn't enable function\n"); + return ret; + } + + iwm_rx_setup_handlers(iwm); + + /* Wait for initial BARKER_REBOOT from hardware */ + notif_reboot = iwm_notif_wait(iwm, IWM_BARKER_REBOOT_NOTIFICATION, + IWM_SRC_UDMA, 2 * HZ); + if (!notif_reboot) { + IWM_ERR(iwm, "Wait for REBOOT_BARKER timeout\n"); + goto err_disable; + } + + /* We send the barker back */ + ret = iwm_bus_send_chunk(iwm, notif_reboot->buf, 16); + if (ret) { + IWM_ERR(iwm, "REBOOT barker response failed\n"); + kfree(notif_reboot); + goto err_disable; + } + + kfree(notif_reboot->buf); + kfree(notif_reboot); + + /* Wait for ACK_BARKER from hardware */ + notif_ack = iwm_notif_wait(iwm, IWM_ACK_BARKER_NOTIFICATION, + IWM_SRC_UDMA, 2 * HZ); + if (!notif_ack) { + IWM_ERR(iwm, "Wait for ACK_BARKER timeout\n"); + goto err_disable; + } + + kfree(notif_ack->buf); + kfree(notif_ack); + + /* We start to config static boot parameters */ + ret = iwm_config_boot_params(iwm); + if (ret) { + IWM_ERR(iwm, "Config boot parameters failed\n"); + goto err_disable; + } + + ret = iwm_read_mac(iwm, iwm_to_ndev(iwm)->dev_addr); + if (ret) { + IWM_ERR(iwm, "MAC reading failed\n"); + goto err_disable; + } + memcpy(iwm_to_ndev(iwm)->perm_addr, iwm_to_ndev(iwm)->dev_addr, + ETH_ALEN); + + /* We can load the FWs */ + ret = iwm_load_fw(iwm); + if (ret) { + IWM_ERR(iwm, "FW loading failed\n"); + goto err_disable; + } + + ret = iwm_eeprom_fat_channels(iwm); + if (ret) { + IWM_ERR(iwm, "Couldnt read HT channels EEPROM entries\n"); + goto err_fw; + } + + /* + * Read our SKU capabilities. + * If it's valid, we AND the configured wireless mode with the + * device EEPROM value as the current profile wireless mode. + */ + wireless_mode = iwm_eeprom_wireless_mode(iwm); + if (wireless_mode) { + iwm->conf.wireless_mode &= wireless_mode; + if (iwm->umac_profile) + iwm->umac_profile->wireless_mode = + iwm->conf.wireless_mode; + } else + IWM_ERR(iwm, "Wrong SKU capabilities: 0x%x\n", + *((u16 *)iwm_eeprom_access(iwm, IWM_EEPROM_SKU_CAP))); + + snprintf(wiphy->fw_version, sizeof(wiphy->fw_version), "L%s_U%s", + iwm->lmac_version, iwm->umac_version); + + /* We configure the UMAC and enable the wifi module */ + ret = iwm_send_umac_config(iwm, + cpu_to_le32(UMAC_RST_CTRL_FLG_WIFI_CORE_EN) | + cpu_to_le32(UMAC_RST_CTRL_FLG_WIFI_LINK_EN) | + cpu_to_le32(UMAC_RST_CTRL_FLG_WIFI_MLME_EN)); + if (ret) { + IWM_ERR(iwm, "UMAC config failed\n"); + goto err_fw; + } + + ret = iwm_notif_handle(iwm, UMAC_NOTIFY_OPCODE_WIFI_CORE_STATUS, + IWM_SRC_UMAC, WAIT_NOTIF_TIMEOUT); + if (ret) { + IWM_ERR(iwm, "Didn't get a wifi core status notification\n"); + goto err_fw; + } + + if (iwm->core_enabled != (UMAC_NTFY_WIFI_CORE_STATUS_LINK_EN | + UMAC_NTFY_WIFI_CORE_STATUS_MLME_EN)) { + IWM_DBG_BOOT(iwm, DBG, "Not all cores enabled:0x%x\n", + iwm->core_enabled); + ret = iwm_notif_handle(iwm, UMAC_NOTIFY_OPCODE_WIFI_CORE_STATUS, + IWM_SRC_UMAC, WAIT_NOTIF_TIMEOUT); + if (ret) { + IWM_ERR(iwm, "Didn't get a core status notification\n"); + goto err_fw; + } + + if (iwm->core_enabled != (UMAC_NTFY_WIFI_CORE_STATUS_LINK_EN | + UMAC_NTFY_WIFI_CORE_STATUS_MLME_EN)) { + IWM_ERR(iwm, "Not all cores enabled: 0x%x\n", + iwm->core_enabled); + goto err_fw; + } else { + IWM_INFO(iwm, "All cores enabled\n"); + } + } + + ret = iwm_channels_init(iwm); + if (ret < 0) { + IWM_ERR(iwm, "Couldn't init channels\n"); + goto err_fw; + } + + /* Set the READY bit to indicate interface is brought up successfully */ + set_bit(IWM_STATUS_READY, &iwm->status); + + return 0; + + err_fw: + iwm_eeprom_exit(iwm); + + err_disable: + ret = iwm_bus_disable(iwm); + if (ret < 0) + IWM_ERR(iwm, "Couldn't disable function\n"); + + return -EIO; +} + +int iwm_up(struct iwm_priv *iwm) +{ + int ret; + + mutex_lock(&iwm->mutex); + ret = __iwm_up(iwm); + mutex_unlock(&iwm->mutex); + + return ret; +} + +static int __iwm_down(struct iwm_priv *iwm) +{ + int ret; + + /* The interface is already down */ + if (!test_bit(IWM_STATUS_READY, &iwm->status)) + return 0; + + if (iwm->scan_request) { + cfg80211_scan_done(iwm->scan_request, true); + iwm->scan_request = NULL; + } + + clear_bit(IWM_STATUS_READY, &iwm->status); + + iwm_eeprom_exit(iwm); + iwm_bss_list_clean(iwm); + iwm_init_default_profile(iwm, iwm->umac_profile); + iwm->umac_profile_active = false; + iwm->default_key = -1; + iwm->core_enabled = 0; + + ret = iwm_bus_disable(iwm); + if (ret < 0) { + IWM_ERR(iwm, "Couldn't disable function\n"); + return ret; + } + + return 0; +} + +int iwm_down(struct iwm_priv *iwm) +{ + int ret; + + mutex_lock(&iwm->mutex); + ret = __iwm_down(iwm); + mutex_unlock(&iwm->mutex); + + return ret; +} diff --git a/trunk/drivers/net/wireless/iwmc3200wifi/netdev.c b/trunk/drivers/net/wireless/iwmc3200wifi/netdev.c new file mode 100644 index 000000000000..5091d77e02ce --- /dev/null +++ b/trunk/drivers/net/wireless/iwmc3200wifi/netdev.c @@ -0,0 +1,191 @@ +/* + * Intel Wireless Multicomm 3200 WiFi driver + * + * Copyright (C) 2009 Intel Corporation + * Samuel Ortiz + * Zhu Yi + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + * + */ + +/* + * This is the netdev related hooks for iwm. + * + * Some interesting code paths: + * + * iwm_open() (Called at netdev interface bringup time) + * -> iwm_up() (main.c) + * -> iwm_bus_enable() + * -> if_sdio_enable() (In case of an SDIO bus) + * -> sdio_enable_func() + * -> iwm_notif_wait(BARKER_REBOOT) (wait for reboot barker) + * -> iwm_notif_wait(ACK_BARKER) (wait for ACK barker) + * -> iwm_load_fw() (fw.c) + * -> iwm_load_umac() + * -> iwm_load_lmac() (Calibration LMAC) + * -> iwm_load_lmac() (Operational LMAC) + * -> iwm_send_umac_config() + * + * iwm_stop() (Called at netdev interface bringdown time) + * -> iwm_down() + * -> iwm_bus_disable() + * -> if_sdio_disable() (In case of an SDIO bus) + * -> sdio_disable_func() + */ +#include +#include + +#include "iwm.h" +#include "commands.h" +#include "cfg80211.h" +#include "debug.h" + +static int iwm_open(struct net_device *ndev) +{ + struct iwm_priv *iwm = ndev_to_iwm(ndev); + + return iwm_up(iwm); +} + +static int iwm_stop(struct net_device *ndev) +{ + struct iwm_priv *iwm = ndev_to_iwm(ndev); + + return iwm_down(iwm); +} + +/* + * iwm AC to queue mapping + * + * AC_VO -> queue 3 + * AC_VI -> queue 2 + * AC_BE -> queue 1 + * AC_BK -> queue 0 + */ +static const u16 iwm_1d_to_queue[8] = { 1, 0, 0, 1, 2, 2, 3, 3 }; + +int iwm_tid_to_queue(u16 tid) +{ + if (tid > IWM_UMAC_TID_NR - 2) + return -EINVAL; + + return iwm_1d_to_queue[tid]; +} + +static u16 iwm_select_queue(struct net_device *dev, struct sk_buff *skb) +{ + skb->priority = cfg80211_classify8021d(skb); + + return iwm_1d_to_queue[skb->priority]; +} + +static const struct net_device_ops iwm_netdev_ops = { + .ndo_open = iwm_open, + .ndo_stop = iwm_stop, + .ndo_start_xmit = iwm_xmit_frame, + .ndo_select_queue = iwm_select_queue, +}; + +void *iwm_if_alloc(int sizeof_bus, struct device *dev, + struct iwm_if_ops *if_ops) +{ + struct net_device *ndev; + struct wireless_dev *wdev; + struct iwm_priv *iwm; + int ret = 0; + + wdev = iwm_wdev_alloc(sizeof_bus, dev); + if (IS_ERR(wdev)) + return wdev; + + iwm = wdev_to_iwm(wdev); + iwm->bus_ops = if_ops; + iwm->wdev = wdev; + + ret = iwm_priv_init(iwm); + if (ret) { + dev_err(dev, "failed to init iwm_priv\n"); + goto out_wdev; + } + + wdev->iftype = iwm_mode_to_nl80211_iftype(iwm->conf.mode); + + ndev = alloc_netdev_mq(0, "wlan%d", ether_setup, IWM_TX_QUEUES); + if (!ndev) { + dev_err(dev, "no memory for network device instance\n"); + ret = -ENOMEM; + goto out_priv; + } + + ndev->netdev_ops = &iwm_netdev_ops; + ndev->ieee80211_ptr = wdev; + SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy)); + wdev->netdev = ndev; + + iwm->umac_profile = kmalloc(sizeof(struct iwm_umac_profile), + GFP_KERNEL); + if (!iwm->umac_profile) { + dev_err(dev, "Couldn't alloc memory for profile\n"); + ret = -ENOMEM; + goto out_profile; + } + + iwm_init_default_profile(iwm, iwm->umac_profile); + + return iwm; + + out_profile: + free_netdev(ndev); + + out_priv: + iwm_priv_deinit(iwm); + + out_wdev: + iwm_wdev_free(iwm); + return ERR_PTR(ret); +} + +void iwm_if_free(struct iwm_priv *iwm) +{ + if (!iwm_to_ndev(iwm)) + return; + + cancel_delayed_work_sync(&iwm->ct_kill_delay); + free_netdev(iwm_to_ndev(iwm)); + iwm_priv_deinit(iwm); + kfree(iwm->umac_profile); + iwm->umac_profile = NULL; + iwm_wdev_free(iwm); +} + +int iwm_if_add(struct iwm_priv *iwm) +{ + struct net_device *ndev = iwm_to_ndev(iwm); + int ret; + + ret = register_netdev(ndev); + if (ret < 0) { + dev_err(&ndev->dev, "Failed to register netdev: %d\n", ret); + return ret; + } + + return 0; +} + +void iwm_if_remove(struct iwm_priv *iwm) +{ + unregister_netdev(iwm_to_ndev(iwm)); +} diff --git a/trunk/drivers/net/wireless/iwmc3200wifi/rx.c b/trunk/drivers/net/wireless/iwmc3200wifi/rx.c new file mode 100644 index 000000000000..7d708f4395f3 --- /dev/null +++ b/trunk/drivers/net/wireless/iwmc3200wifi/rx.c @@ -0,0 +1,1701 @@ +/* + * Intel Wireless Multicomm 3200 WiFi driver + * + * Copyright (C) 2009 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * + * Intel Corporation + * Samuel Ortiz + * Zhu Yi + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "iwm.h" +#include "debug.h" +#include "hal.h" +#include "umac.h" +#include "lmac.h" +#include "commands.h" +#include "rx.h" +#include "cfg80211.h" +#include "eeprom.h" + +static int iwm_rx_check_udma_hdr(struct iwm_udma_in_hdr *hdr) +{ + if ((le32_to_cpu(hdr->cmd) == UMAC_PAD_TERMINAL) || + (le32_to_cpu(hdr->size) == UMAC_PAD_TERMINAL)) + return -EINVAL; + + return 0; +} + +static inline int iwm_rx_resp_size(struct iwm_udma_in_hdr *hdr) +{ + return ALIGN(le32_to_cpu(hdr->size) + sizeof(struct iwm_udma_in_hdr), + 16); +} + +/* + * Notification handlers: + * + * For every possible notification we can receive from the + * target, we have a handler. + * When we get a target notification, and there is no one + * waiting for it, it's just processed through the rx code + * path: + * + * iwm_rx_handle() + * -> iwm_rx_handle_umac() + * -> iwm_rx_handle_wifi() + * -> iwm_rx_handle_resp() + * -> iwm_ntf_*() + * + * OR + * + * -> iwm_rx_handle_non_wifi() + * + * If there are processes waiting for this notification, then + * iwm_rx_handle_wifi() just wakes those processes up and they + * grab the pending notification. + */ +static int iwm_ntf_error(struct iwm_priv *iwm, u8 *buf, + unsigned long buf_size, struct iwm_wifi_cmd *cmd) +{ + struct iwm_umac_notif_error *error; + struct iwm_fw_error_hdr *fw_err; + + error = (struct iwm_umac_notif_error *)buf; + fw_err = &error->err; + + memcpy(iwm->last_fw_err, fw_err, sizeof(struct iwm_fw_error_hdr)); + + IWM_ERR(iwm, "%cMAC FW ERROR:\n", + (le32_to_cpu(fw_err->category) == UMAC_SYS_ERR_CAT_LMAC) ? 'L' : 'U'); + IWM_ERR(iwm, "\tCategory: %d\n", le32_to_cpu(fw_err->category)); + IWM_ERR(iwm, "\tStatus: 0x%x\n", le32_to_cpu(fw_err->status)); + IWM_ERR(iwm, "\tPC: 0x%x\n", le32_to_cpu(fw_err->pc)); + IWM_ERR(iwm, "\tblink1: %d\n", le32_to_cpu(fw_err->blink1)); + IWM_ERR(iwm, "\tblink2: %d\n", le32_to_cpu(fw_err->blink2)); + IWM_ERR(iwm, "\tilink1: %d\n", le32_to_cpu(fw_err->ilink1)); + IWM_ERR(iwm, "\tilink2: %d\n", le32_to_cpu(fw_err->ilink2)); + IWM_ERR(iwm, "\tData1: 0x%x\n", le32_to_cpu(fw_err->data1)); + IWM_ERR(iwm, "\tData2: 0x%x\n", le32_to_cpu(fw_err->data2)); + IWM_ERR(iwm, "\tLine number: %d\n", le32_to_cpu(fw_err->line_num)); + IWM_ERR(iwm, "\tUMAC status: 0x%x\n", le32_to_cpu(fw_err->umac_status)); + IWM_ERR(iwm, "\tLMAC status: 0x%x\n", le32_to_cpu(fw_err->lmac_status)); + IWM_ERR(iwm, "\tSDIO status: 0x%x\n", le32_to_cpu(fw_err->sdio_status)); + + iwm_resetting(iwm); + + return 0; +} + +static int iwm_ntf_umac_alive(struct iwm_priv *iwm, u8 *buf, + unsigned long buf_size, struct iwm_wifi_cmd *cmd) +{ + struct iwm_umac_notif_alive *alive_resp = + (struct iwm_umac_notif_alive *)(buf); + u16 status = le16_to_cpu(alive_resp->status); + + if (status == UMAC_NTFY_ALIVE_STATUS_ERR) { + IWM_ERR(iwm, "Receive error UMAC_ALIVE\n"); + return -EIO; + } + + iwm_tx_credit_init_pools(iwm, alive_resp); + + return 0; +} + +static int iwm_ntf_init_complete(struct iwm_priv *iwm, u8 *buf, + unsigned long buf_size, + struct iwm_wifi_cmd *cmd) +{ + struct wiphy *wiphy = iwm_to_wiphy(iwm); + struct iwm_umac_notif_init_complete *init_complete = + (struct iwm_umac_notif_init_complete *)(buf); + u16 status = le16_to_cpu(init_complete->status); + bool blocked = (status == UMAC_NTFY_INIT_COMPLETE_STATUS_ERR); + + if (blocked) + IWM_DBG_NTF(iwm, DBG, "Hardware rf kill is on (radio off)\n"); + else + IWM_DBG_NTF(iwm, DBG, "Hardware rf kill is off (radio on)\n"); + + wiphy_rfkill_set_hw_state(wiphy, blocked); + + return 0; +} + +static int iwm_ntf_tx_credit_update(struct iwm_priv *iwm, u8 *buf, + unsigned long buf_size, + struct iwm_wifi_cmd *cmd) +{ + int pool_nr, total_freed_pages; + unsigned long pool_map; + int i, id; + struct iwm_umac_notif_page_dealloc *dealloc = + (struct iwm_umac_notif_page_dealloc *)buf; + + pool_nr = GET_VAL32(dealloc->changes, UMAC_DEALLOC_NTFY_CHANGES_CNT); + pool_map = GET_VAL32(dealloc->changes, UMAC_DEALLOC_NTFY_CHANGES_MSK); + + IWM_DBG_TX(iwm, DBG, "UMAC dealloc notification: pool nr %d, " + "update map 0x%lx\n", pool_nr, pool_map); + + spin_lock(&iwm->tx_credit.lock); + + for (i = 0; i < pool_nr; i++) { + id = GET_VAL32(dealloc->grp_info[i], + UMAC_DEALLOC_NTFY_GROUP_NUM); + if (test_bit(id, &pool_map)) { + total_freed_pages = GET_VAL32(dealloc->grp_info[i], + UMAC_DEALLOC_NTFY_PAGE_CNT); + iwm_tx_credit_inc(iwm, id, total_freed_pages); + } + } + + spin_unlock(&iwm->tx_credit.lock); + + return 0; +} + +static int iwm_ntf_umac_reset(struct iwm_priv *iwm, u8 *buf, + unsigned long buf_size, struct iwm_wifi_cmd *cmd) +{ + IWM_DBG_NTF(iwm, DBG, "UMAC RESET done\n"); + + return 0; +} + +static int iwm_ntf_lmac_version(struct iwm_priv *iwm, u8 *buf, + unsigned long buf_size, + struct iwm_wifi_cmd *cmd) +{ + IWM_DBG_NTF(iwm, INFO, "LMAC Version: %x.%x\n", buf[9], buf[8]); + + return 0; +} + +static int iwm_ntf_tx(struct iwm_priv *iwm, u8 *buf, + unsigned long buf_size, struct iwm_wifi_cmd *cmd) +{ + struct iwm_lmac_tx_resp *tx_resp; + struct iwm_umac_wifi_in_hdr *hdr; + + tx_resp = (struct iwm_lmac_tx_resp *) + (buf + sizeof(struct iwm_umac_wifi_in_hdr)); + hdr = (struct iwm_umac_wifi_in_hdr *)buf; + + IWM_DBG_TX(iwm, DBG, "REPLY_TX, buf size: %lu\n", buf_size); + + IWM_DBG_TX(iwm, DBG, "Seqnum: %d\n", + le16_to_cpu(hdr->sw_hdr.cmd.seq_num)); + IWM_DBG_TX(iwm, DBG, "\tFrame cnt: %d\n", tx_resp->frame_cnt); + IWM_DBG_TX(iwm, DBG, "\tRetry cnt: %d\n", + le16_to_cpu(tx_resp->retry_cnt)); + IWM_DBG_TX(iwm, DBG, "\tSeq ctl: %d\n", le16_to_cpu(tx_resp->seq_ctl)); + IWM_DBG_TX(iwm, DBG, "\tByte cnt: %d\n", + le16_to_cpu(tx_resp->byte_cnt)); + IWM_DBG_TX(iwm, DBG, "\tStatus: 0x%x\n", le32_to_cpu(tx_resp->status)); + + return 0; +} + + +static int iwm_ntf_calib_res(struct iwm_priv *iwm, u8 *buf, + unsigned long buf_size, struct iwm_wifi_cmd *cmd) +{ + u8 opcode; + u8 *calib_buf; + struct iwm_lmac_calib_hdr *hdr = (struct iwm_lmac_calib_hdr *) + (buf + sizeof(struct iwm_umac_wifi_in_hdr)); + + opcode = hdr->opcode; + + BUG_ON(opcode >= CALIBRATION_CMD_NUM || + opcode < PHY_CALIBRATE_OPCODES_NUM); + + IWM_DBG_NTF(iwm, DBG, "Store calibration result for opcode: %d\n", + opcode); + + buf_size -= sizeof(struct iwm_umac_wifi_in_hdr); + calib_buf = iwm->calib_res[opcode].buf; + + if (!calib_buf || (iwm->calib_res[opcode].size < buf_size)) { + kfree(calib_buf); + calib_buf = kzalloc(buf_size, GFP_KERNEL); + if (!calib_buf) { + IWM_ERR(iwm, "Memory allocation failed: calib_res\n"); + return -ENOMEM; + } + iwm->calib_res[opcode].buf = calib_buf; + iwm->calib_res[opcode].size = buf_size; + } + + memcpy(calib_buf, hdr, buf_size); + set_bit(opcode - PHY_CALIBRATE_OPCODES_NUM, &iwm->calib_done_map); + + return 0; +} + +static int iwm_ntf_calib_complete(struct iwm_priv *iwm, u8 *buf, + unsigned long buf_size, + struct iwm_wifi_cmd *cmd) +{ + IWM_DBG_NTF(iwm, DBG, "Calibration completed\n"); + + return 0; +} + +static int iwm_ntf_calib_cfg(struct iwm_priv *iwm, u8 *buf, + unsigned long buf_size, struct iwm_wifi_cmd *cmd) +{ + struct iwm_lmac_cal_cfg_resp *cal_resp; + + cal_resp = (struct iwm_lmac_cal_cfg_resp *) + (buf + sizeof(struct iwm_umac_wifi_in_hdr)); + + IWM_DBG_NTF(iwm, DBG, "Calibration CFG command status: %d\n", + le32_to_cpu(cal_resp->status)); + + return 0; +} + +static int iwm_ntf_wifi_status(struct iwm_priv *iwm, u8 *buf, + unsigned long buf_size, struct iwm_wifi_cmd *cmd) +{ + struct iwm_umac_notif_wifi_status *status = + (struct iwm_umac_notif_wifi_status *)buf; + + iwm->core_enabled |= le16_to_cpu(status->status); + + return 0; +} + +static struct iwm_rx_ticket_node * +iwm_rx_ticket_node_alloc(struct iwm_priv *iwm, struct iwm_rx_ticket *ticket) +{ + struct iwm_rx_ticket_node *ticket_node; + + ticket_node = kzalloc(sizeof(struct iwm_rx_ticket_node), GFP_KERNEL); + if (!ticket_node) { + IWM_ERR(iwm, "Couldn't allocate ticket node\n"); + return ERR_PTR(-ENOMEM); + } + + ticket_node->ticket = kmemdup(ticket, sizeof(struct iwm_rx_ticket), + GFP_KERNEL); + if (!ticket_node->ticket) { + IWM_ERR(iwm, "Couldn't allocate RX ticket\n"); + kfree(ticket_node); + return ERR_PTR(-ENOMEM); + } + + INIT_LIST_HEAD(&ticket_node->node); + + return ticket_node; +} + +static void iwm_rx_ticket_node_free(struct iwm_rx_ticket_node *ticket_node) +{ + kfree(ticket_node->ticket); + kfree(ticket_node); +} + +static struct iwm_rx_packet *iwm_rx_packet_get(struct iwm_priv *iwm, u16 id) +{ + u8 id_hash = IWM_RX_ID_GET_HASH(id); + struct iwm_rx_packet *packet; + + spin_lock(&iwm->packet_lock[id_hash]); + list_for_each_entry(packet, &iwm->rx_packets[id_hash], node) + if (packet->id == id) { + list_del(&packet->node); + spin_unlock(&iwm->packet_lock[id_hash]); + return packet; + } + + spin_unlock(&iwm->packet_lock[id_hash]); + return NULL; +} + +static struct iwm_rx_packet *iwm_rx_packet_alloc(struct iwm_priv *iwm, u8 *buf, + u32 size, u16 id) +{ + struct iwm_rx_packet *packet; + + packet = kzalloc(sizeof(struct iwm_rx_packet), GFP_KERNEL); + if (!packet) { + IWM_ERR(iwm, "Couldn't allocate packet\n"); + return ERR_PTR(-ENOMEM); + } + + packet->skb = dev_alloc_skb(size); + if (!packet->skb) { + IWM_ERR(iwm, "Couldn't allocate packet SKB\n"); + kfree(packet); + return ERR_PTR(-ENOMEM); + } + + packet->pkt_size = size; + + skb_put(packet->skb, size); + memcpy(packet->skb->data, buf, size); + INIT_LIST_HEAD(&packet->node); + packet->id = id; + + return packet; +} + +void iwm_rx_free(struct iwm_priv *iwm) +{ + struct iwm_rx_ticket_node *ticket, *nt; + struct iwm_rx_packet *packet, *np; + int i; + + spin_lock(&iwm->ticket_lock); + list_for_each_entry_safe(ticket, nt, &iwm->rx_tickets, node) { + list_del(&ticket->node); + iwm_rx_ticket_node_free(ticket); + } + spin_unlock(&iwm->ticket_lock); + + for (i = 0; i < IWM_RX_ID_HASH; i++) { + spin_lock(&iwm->packet_lock[i]); + list_for_each_entry_safe(packet, np, &iwm->rx_packets[i], + node) { + list_del(&packet->node); + kfree_skb(packet->skb); + kfree(packet); + } + spin_unlock(&iwm->packet_lock[i]); + } +} + +static int iwm_ntf_rx_ticket(struct iwm_priv *iwm, u8 *buf, + unsigned long buf_size, struct iwm_wifi_cmd *cmd) +{ + struct iwm_umac_notif_rx_ticket *ntf_rx_ticket = + (struct iwm_umac_notif_rx_ticket *)buf; + struct iwm_rx_ticket *ticket = + (struct iwm_rx_ticket *)ntf_rx_ticket->tickets; + int i, schedule_rx = 0; + + for (i = 0; i < ntf_rx_ticket->num_tickets; i++) { + struct iwm_rx_ticket_node *ticket_node; + + switch (le16_to_cpu(ticket->action)) { + case IWM_RX_TICKET_RELEASE: + case IWM_RX_TICKET_DROP: + /* We can push the packet to the stack */ + ticket_node = iwm_rx_ticket_node_alloc(iwm, ticket); + if (IS_ERR(ticket_node)) + return PTR_ERR(ticket_node); + + IWM_DBG_RX(iwm, DBG, "TICKET %s(%d)\n", + __le16_to_cpu(ticket->action) == + IWM_RX_TICKET_RELEASE ? + "RELEASE" : "DROP", + ticket->id); + spin_lock(&iwm->ticket_lock); + list_add_tail(&ticket_node->node, &iwm->rx_tickets); + spin_unlock(&iwm->ticket_lock); + + /* + * We received an Rx ticket, most likely there's + * a packet pending for it, it's not worth going + * through the packet hash list to double check. + * Let's just fire the rx worker.. + */ + schedule_rx = 1; + + break; + + default: + IWM_ERR(iwm, "Invalid RX ticket action: 0x%x\n", + ticket->action); + } + + ticket++; + } + + if (schedule_rx) + queue_work(iwm->rx_wq, &iwm->rx_worker); + + return 0; +} + +static int iwm_ntf_rx_packet(struct iwm_priv *iwm, u8 *buf, + unsigned long buf_size, struct iwm_wifi_cmd *cmd) +{ + struct iwm_umac_wifi_in_hdr *wifi_hdr; + struct iwm_rx_packet *packet; + u16 id, buf_offset; + u32 packet_size; + u8 id_hash; + + IWM_DBG_RX(iwm, DBG, "\n"); + + wifi_hdr = (struct iwm_umac_wifi_in_hdr *)buf; + id = le16_to_cpu(wifi_hdr->sw_hdr.cmd.seq_num); + buf_offset = sizeof(struct iwm_umac_wifi_in_hdr); + packet_size = buf_size - sizeof(struct iwm_umac_wifi_in_hdr); + + IWM_DBG_RX(iwm, DBG, "CMD:0x%x, seqnum: %d, packet size: %d\n", + wifi_hdr->sw_hdr.cmd.cmd, id, packet_size); + IWM_DBG_RX(iwm, DBG, "Packet id: %d\n", id); + IWM_HEXDUMP(iwm, DBG, RX, "PACKET: ", buf + buf_offset, packet_size); + + packet = iwm_rx_packet_alloc(iwm, buf + buf_offset, packet_size, id); + if (IS_ERR(packet)) + return PTR_ERR(packet); + + id_hash = IWM_RX_ID_GET_HASH(id); + spin_lock(&iwm->packet_lock[id_hash]); + list_add_tail(&packet->node, &iwm->rx_packets[id_hash]); + spin_unlock(&iwm->packet_lock[id_hash]); + + /* We might (unlikely) have received the packet _after_ the ticket */ + queue_work(iwm->rx_wq, &iwm->rx_worker); + + return 0; +} + +/* MLME handlers */ +static int iwm_mlme_assoc_start(struct iwm_priv *iwm, u8 *buf, + unsigned long buf_size, + struct iwm_wifi_cmd *cmd) +{ + struct iwm_umac_notif_assoc_start *start; + + start = (struct iwm_umac_notif_assoc_start *)buf; + + IWM_DBG_MLME(iwm, INFO, "Association with %pM Started, reason: %d\n", + start->bssid, le32_to_cpu(start->roam_reason)); + + wake_up_interruptible(&iwm->mlme_queue); + + return 0; +} + +static u8 iwm_is_open_wep_profile(struct iwm_priv *iwm) +{ + if ((iwm->umac_profile->sec.ucast_cipher == UMAC_CIPHER_TYPE_WEP_40 || + iwm->umac_profile->sec.ucast_cipher == UMAC_CIPHER_TYPE_WEP_104) && + (iwm->umac_profile->sec.ucast_cipher == + iwm->umac_profile->sec.mcast_cipher) && + (iwm->umac_profile->sec.auth_type == UMAC_AUTH_TYPE_OPEN)) + return 1; + + return 0; +} + +static int iwm_mlme_assoc_complete(struct iwm_priv *iwm, u8 *buf, + unsigned long buf_size, + struct iwm_wifi_cmd *cmd) +{ + struct wiphy *wiphy = iwm_to_wiphy(iwm); + struct ieee80211_channel *chan; + struct iwm_umac_notif_assoc_complete *complete = + (struct iwm_umac_notif_assoc_complete *)buf; + + IWM_DBG_MLME(iwm, INFO, "Association with %pM completed, status: %d\n", + complete->bssid, complete->status); + + switch (le32_to_cpu(complete->status)) { + case UMAC_ASSOC_COMPLETE_SUCCESS: + chan = ieee80211_get_channel(wiphy, + ieee80211_channel_to_frequency(complete->channel, + complete->band == UMAC_BAND_2GHZ ? + IEEE80211_BAND_2GHZ : + IEEE80211_BAND_5GHZ)); + if (!chan || chan->flags & IEEE80211_CHAN_DISABLED) { + /* Associated to a unallowed channel, disassociate. */ + __iwm_invalidate_mlme_profile(iwm); + IWM_WARN(iwm, "Couldn't associate with %pM due to " + "channel %d is disabled. Check your local " + "regulatory setting.\n", + complete->bssid, complete->channel); + goto failure; + } + + set_bit(IWM_STATUS_ASSOCIATED, &iwm->status); + memcpy(iwm->bssid, complete->bssid, ETH_ALEN); + iwm->channel = complete->channel; + + /* Internal roaming state, avoid notifying SME. */ + if (!test_and_clear_bit(IWM_STATUS_SME_CONNECTING, &iwm->status) + && iwm->conf.mode == UMAC_MODE_BSS) { + cancel_delayed_work(&iwm->disconnect); + cfg80211_roamed(iwm_to_ndev(iwm), NULL, + complete->bssid, + iwm->req_ie, iwm->req_ie_len, + iwm->resp_ie, iwm->resp_ie_len, + GFP_KERNEL); + break; + } + + iwm_link_on(iwm); + + if (iwm->conf.mode == UMAC_MODE_IBSS) + goto ibss; + + if (!test_bit(IWM_STATUS_RESETTING, &iwm->status)) + cfg80211_connect_result(iwm_to_ndev(iwm), + complete->bssid, + iwm->req_ie, iwm->req_ie_len, + iwm->resp_ie, iwm->resp_ie_len, + WLAN_STATUS_SUCCESS, + GFP_KERNEL); + else + cfg80211_roamed(iwm_to_ndev(iwm), NULL, + complete->bssid, + iwm->req_ie, iwm->req_ie_len, + iwm->resp_ie, iwm->resp_ie_len, + GFP_KERNEL); + break; + case UMAC_ASSOC_COMPLETE_FAILURE: + failure: + clear_bit(IWM_STATUS_ASSOCIATED, &iwm->status); + memset(iwm->bssid, 0, ETH_ALEN); + iwm->channel = 0; + + /* Internal roaming state, avoid notifying SME. */ + if (!test_and_clear_bit(IWM_STATUS_SME_CONNECTING, &iwm->status) + && iwm->conf.mode == UMAC_MODE_BSS) { + cancel_delayed_work(&iwm->disconnect); + break; + } + + iwm_link_off(iwm); + + if (iwm->conf.mode == UMAC_MODE_IBSS) + goto ibss; + + if (!test_bit(IWM_STATUS_RESETTING, &iwm->status)) + if (!iwm_is_open_wep_profile(iwm)) { + cfg80211_connect_result(iwm_to_ndev(iwm), + complete->bssid, + NULL, 0, NULL, 0, + WLAN_STATUS_UNSPECIFIED_FAILURE, + GFP_KERNEL); + } else { + /* Let's try shared WEP auth */ + IWM_ERR(iwm, "Trying WEP shared auth\n"); + schedule_work(&iwm->auth_retry_worker); + } + else + cfg80211_disconnected(iwm_to_ndev(iwm), 0, NULL, 0, + GFP_KERNEL); + break; + default: + break; + } + + clear_bit(IWM_STATUS_RESETTING, &iwm->status); + return 0; + + ibss: + cfg80211_ibss_joined(iwm_to_ndev(iwm), iwm->bssid, GFP_KERNEL); + clear_bit(IWM_STATUS_RESETTING, &iwm->status); + return 0; +} + +static int iwm_mlme_profile_invalidate(struct iwm_priv *iwm, u8 *buf, + unsigned long buf_size, + struct iwm_wifi_cmd *cmd) +{ + struct iwm_umac_notif_profile_invalidate *invalid; + u32 reason; + + invalid = (struct iwm_umac_notif_profile_invalidate *)buf; + reason = le32_to_cpu(invalid->reason); + + IWM_DBG_MLME(iwm, INFO, "Profile Invalidated. Reason: %d\n", reason); + + if (reason != UMAC_PROFILE_INVALID_REQUEST && + test_bit(IWM_STATUS_SME_CONNECTING, &iwm->status)) + cfg80211_connect_result(iwm_to_ndev(iwm), NULL, NULL, 0, NULL, + 0, WLAN_STATUS_UNSPECIFIED_FAILURE, + GFP_KERNEL); + + clear_bit(IWM_STATUS_SME_CONNECTING, &iwm->status); + clear_bit(IWM_STATUS_ASSOCIATED, &iwm->status); + + iwm->umac_profile_active = false; + memset(iwm->bssid, 0, ETH_ALEN); + iwm->channel = 0; + + iwm_link_off(iwm); + + wake_up_interruptible(&iwm->mlme_queue); + + return 0; +} + +#define IWM_DISCONNECT_INTERVAL (5 * HZ) + +static int iwm_mlme_connection_terminated(struct iwm_priv *iwm, u8 *buf, + unsigned long buf_size, + struct iwm_wifi_cmd *cmd) +{ + IWM_DBG_MLME(iwm, DBG, "Connection terminated\n"); + + schedule_delayed_work(&iwm->disconnect, IWM_DISCONNECT_INTERVAL); + + return 0; +} + +static int iwm_mlme_scan_complete(struct iwm_priv *iwm, u8 *buf, + unsigned long buf_size, + struct iwm_wifi_cmd *cmd) +{ + int ret; + struct iwm_umac_notif_scan_complete *scan_complete = + (struct iwm_umac_notif_scan_complete *)buf; + u32 result = le32_to_cpu(scan_complete->result); + + IWM_DBG_MLME(iwm, INFO, "type:0x%x result:0x%x seq:%d\n", + le32_to_cpu(scan_complete->type), + le32_to_cpu(scan_complete->result), + scan_complete->seq_num); + + if (!test_and_clear_bit(IWM_STATUS_SCANNING, &iwm->status)) { + IWM_ERR(iwm, "Scan complete while device not scanning\n"); + return -EIO; + } + if (!iwm->scan_request) + return 0; + + ret = iwm_cfg80211_inform_bss(iwm); + + cfg80211_scan_done(iwm->scan_request, + (result & UMAC_SCAN_RESULT_ABORTED) ? 1 : !!ret); + iwm->scan_request = NULL; + + return ret; +} + +static int iwm_mlme_update_sta_table(struct iwm_priv *iwm, u8 *buf, + unsigned long buf_size, + struct iwm_wifi_cmd *cmd) +{ + struct iwm_umac_notif_sta_info *umac_sta = + (struct iwm_umac_notif_sta_info *)buf; + struct iwm_sta_info *sta; + int i; + + switch (le32_to_cpu(umac_sta->opcode)) { + case UMAC_OPCODE_ADD_MODIFY: + sta = &iwm->sta_table[GET_VAL8(umac_sta->sta_id, LMAC_STA_ID)]; + + IWM_DBG_MLME(iwm, INFO, "%s STA: ID = %d, Color = %d, " + "addr = %pM, qos = %d\n", + sta->valid ? "Modify" : "Add", + GET_VAL8(umac_sta->sta_id, LMAC_STA_ID), + GET_VAL8(umac_sta->sta_id, LMAC_STA_COLOR), + umac_sta->mac_addr, + umac_sta->flags & UMAC_STA_FLAG_QOS); + + sta->valid = true; + sta->qos = umac_sta->flags & UMAC_STA_FLAG_QOS; + sta->color = GET_VAL8(umac_sta->sta_id, LMAC_STA_COLOR); + memcpy(sta->addr, umac_sta->mac_addr, ETH_ALEN); + break; + case UMAC_OPCODE_REMOVE: + IWM_DBG_MLME(iwm, INFO, "Remove STA: ID = %d, Color = %d, " + "addr = %pM\n", + GET_VAL8(umac_sta->sta_id, LMAC_STA_ID), + GET_VAL8(umac_sta->sta_id, LMAC_STA_COLOR), + umac_sta->mac_addr); + + sta = &iwm->sta_table[GET_VAL8(umac_sta->sta_id, LMAC_STA_ID)]; + + if (!memcmp(sta->addr, umac_sta->mac_addr, ETH_ALEN)) + sta->valid = false; + + break; + case UMAC_OPCODE_CLEAR_ALL: + for (i = 0; i < IWM_STA_TABLE_NUM; i++) + iwm->sta_table[i].valid = false; + + break; + default: + break; + } + + return 0; +} + +static int iwm_mlme_medium_lost(struct iwm_priv *iwm, u8 *buf, + unsigned long buf_size, + struct iwm_wifi_cmd *cmd) +{ + struct wiphy *wiphy = iwm_to_wiphy(iwm); + + IWM_DBG_NTF(iwm, DBG, "WiFi/WiMax coexistence radio is OFF\n"); + + wiphy_rfkill_set_hw_state(wiphy, true); + + return 0; +} + +static int iwm_mlme_update_bss_table(struct iwm_priv *iwm, u8 *buf, + unsigned long buf_size, + struct iwm_wifi_cmd *cmd) +{ + struct wiphy *wiphy = iwm_to_wiphy(iwm); + struct ieee80211_mgmt *mgmt; + struct iwm_umac_notif_bss_info *umac_bss = + (struct iwm_umac_notif_bss_info *)buf; + struct ieee80211_channel *channel; + struct ieee80211_supported_band *band; + struct iwm_bss_info *bss; + s32 signal; + int freq; + u16 frame_len = le16_to_cpu(umac_bss->frame_len); + size_t bss_len = sizeof(struct iwm_umac_notif_bss_info) + frame_len; + + mgmt = (struct ieee80211_mgmt *)(umac_bss->frame_buf); + + IWM_DBG_MLME(iwm, DBG, "New BSS info entry: %pM\n", mgmt->bssid); + IWM_DBG_MLME(iwm, DBG, "\tType: 0x%x\n", le32_to_cpu(umac_bss->type)); + IWM_DBG_MLME(iwm, DBG, "\tTimestamp: %d\n", + le32_to_cpu(umac_bss->timestamp)); + IWM_DBG_MLME(iwm, DBG, "\tTable Index: %d\n", + le16_to_cpu(umac_bss->table_idx)); + IWM_DBG_MLME(iwm, DBG, "\tBand: %d\n", umac_bss->band); + IWM_DBG_MLME(iwm, DBG, "\tChannel: %d\n", umac_bss->channel); + IWM_DBG_MLME(iwm, DBG, "\tRSSI: %d\n", umac_bss->rssi); + IWM_DBG_MLME(iwm, DBG, "\tFrame Length: %d\n", frame_len); + + list_for_each_entry(bss, &iwm->bss_list, node) + if (bss->bss->table_idx == umac_bss->table_idx) + break; + + if (&bss->node != &iwm->bss_list) { + /* Remove the old BSS entry, we will add it back later. */ + list_del(&bss->node); + kfree(bss->bss); + } else { + /* New BSS entry */ + + bss = kzalloc(sizeof(struct iwm_bss_info), GFP_KERNEL); + if (!bss) { + IWM_ERR(iwm, "Couldn't allocate bss_info\n"); + return -ENOMEM; + } + } + + bss->bss = kzalloc(bss_len, GFP_KERNEL); + if (!bss->bss) { + kfree(bss); + IWM_ERR(iwm, "Couldn't allocate bss\n"); + return -ENOMEM; + } + + INIT_LIST_HEAD(&bss->node); + memcpy(bss->bss, umac_bss, bss_len); + + if (umac_bss->band == UMAC_BAND_2GHZ) + band = wiphy->bands[IEEE80211_BAND_2GHZ]; + else if (umac_bss->band == UMAC_BAND_5GHZ) + band = wiphy->bands[IEEE80211_BAND_5GHZ]; + else { + IWM_ERR(iwm, "Invalid band: %d\n", umac_bss->band); + goto err; + } + + freq = ieee80211_channel_to_frequency(umac_bss->channel, band->band); + channel = ieee80211_get_channel(wiphy, freq); + signal = umac_bss->rssi * 100; + + bss->cfg_bss = cfg80211_inform_bss_frame(wiphy, channel, + mgmt, frame_len, + signal, GFP_KERNEL); + if (!bss->cfg_bss) + goto err; + + list_add_tail(&bss->node, &iwm->bss_list); + + return 0; + err: + kfree(bss->bss); + kfree(bss); + + return -EINVAL; +} + +static int iwm_mlme_remove_bss(struct iwm_priv *iwm, u8 *buf, + unsigned long buf_size, struct iwm_wifi_cmd *cmd) +{ + struct iwm_umac_notif_bss_removed *bss_rm = + (struct iwm_umac_notif_bss_removed *)buf; + struct iwm_bss_info *bss, *next; + u16 table_idx; + int i; + + for (i = 0; i < le32_to_cpu(bss_rm->count); i++) { + table_idx = le16_to_cpu(bss_rm->entries[i]) & + IWM_BSS_REMOVE_INDEX_MSK; + list_for_each_entry_safe(bss, next, &iwm->bss_list, node) + if (bss->bss->table_idx == cpu_to_le16(table_idx)) { + struct ieee80211_mgmt *mgmt; + + mgmt = (struct ieee80211_mgmt *) + (bss->bss->frame_buf); + IWM_DBG_MLME(iwm, ERR, "BSS removed: %pM\n", + mgmt->bssid); + list_del(&bss->node); + kfree(bss->bss); + kfree(bss); + } + } + + return 0; +} + +static int iwm_mlme_mgt_frame(struct iwm_priv *iwm, u8 *buf, + unsigned long buf_size, struct iwm_wifi_cmd *cmd) +{ + struct iwm_umac_notif_mgt_frame *mgt_frame = + (struct iwm_umac_notif_mgt_frame *)buf; + struct ieee80211_mgmt *mgt = (struct ieee80211_mgmt *)mgt_frame->frame; + + IWM_HEXDUMP(iwm, DBG, MLME, "MGT: ", mgt_frame->frame, + le16_to_cpu(mgt_frame->len)); + + if (ieee80211_is_assoc_req(mgt->frame_control)) { + iwm->req_ie_len = le16_to_cpu(mgt_frame->len) + - offsetof(struct ieee80211_mgmt, + u.assoc_req.variable); + kfree(iwm->req_ie); + iwm->req_ie = kmemdup(mgt->u.assoc_req.variable, + iwm->req_ie_len, GFP_KERNEL); + } else if (ieee80211_is_reassoc_req(mgt->frame_control)) { + iwm->req_ie_len = le16_to_cpu(mgt_frame->len) + - offsetof(struct ieee80211_mgmt, + u.reassoc_req.variable); + kfree(iwm->req_ie); + iwm->req_ie = kmemdup(mgt->u.reassoc_req.variable, + iwm->req_ie_len, GFP_KERNEL); + } else if (ieee80211_is_assoc_resp(mgt->frame_control)) { + iwm->resp_ie_len = le16_to_cpu(mgt_frame->len) + - offsetof(struct ieee80211_mgmt, + u.assoc_resp.variable); + kfree(iwm->resp_ie); + iwm->resp_ie = kmemdup(mgt->u.assoc_resp.variable, + iwm->resp_ie_len, GFP_KERNEL); + } else if (ieee80211_is_reassoc_resp(mgt->frame_control)) { + iwm->resp_ie_len = le16_to_cpu(mgt_frame->len) + - offsetof(struct ieee80211_mgmt, + u.reassoc_resp.variable); + kfree(iwm->resp_ie); + iwm->resp_ie = kmemdup(mgt->u.reassoc_resp.variable, + iwm->resp_ie_len, GFP_KERNEL); + } else { + IWM_ERR(iwm, "Unsupported management frame: 0x%x", + le16_to_cpu(mgt->frame_control)); + return 0; + } + + return 0; +} + +static int iwm_ntf_mlme(struct iwm_priv *iwm, u8 *buf, + unsigned long buf_size, struct iwm_wifi_cmd *cmd) +{ + struct iwm_umac_notif_wifi_if *notif = + (struct iwm_umac_notif_wifi_if *)buf; + + switch (notif->status) { + case WIFI_IF_NTFY_ASSOC_START: + return iwm_mlme_assoc_start(iwm, buf, buf_size, cmd); + case WIFI_IF_NTFY_ASSOC_COMPLETE: + return iwm_mlme_assoc_complete(iwm, buf, buf_size, cmd); + case WIFI_IF_NTFY_PROFILE_INVALIDATE_COMPLETE: + return iwm_mlme_profile_invalidate(iwm, buf, buf_size, cmd); + case WIFI_IF_NTFY_CONNECTION_TERMINATED: + return iwm_mlme_connection_terminated(iwm, buf, buf_size, cmd); + case WIFI_IF_NTFY_SCAN_COMPLETE: + return iwm_mlme_scan_complete(iwm, buf, buf_size, cmd); + case WIFI_IF_NTFY_STA_TABLE_CHANGE: + return iwm_mlme_update_sta_table(iwm, buf, buf_size, cmd); + case WIFI_IF_NTFY_EXTENDED_IE_REQUIRED: + IWM_DBG_MLME(iwm, DBG, "Extended IE required\n"); + break; + case WIFI_IF_NTFY_RADIO_PREEMPTION: + return iwm_mlme_medium_lost(iwm, buf, buf_size, cmd); + case WIFI_IF_NTFY_BSS_TRK_TABLE_CHANGED: + return iwm_mlme_update_bss_table(iwm, buf, buf_size, cmd); + case WIFI_IF_NTFY_BSS_TRK_ENTRIES_REMOVED: + return iwm_mlme_remove_bss(iwm, buf, buf_size, cmd); + break; + case WIFI_IF_NTFY_MGMT_FRAME: + return iwm_mlme_mgt_frame(iwm, buf, buf_size, cmd); + case WIFI_DBG_IF_NTFY_SCAN_SUPER_JOB_START: + case WIFI_DBG_IF_NTFY_SCAN_SUPER_JOB_COMPLETE: + case WIFI_DBG_IF_NTFY_SCAN_CHANNEL_START: + case WIFI_DBG_IF_NTFY_SCAN_CHANNEL_RESULT: + case WIFI_DBG_IF_NTFY_SCAN_MINI_JOB_START: + case WIFI_DBG_IF_NTFY_SCAN_MINI_JOB_COMPLETE: + case WIFI_DBG_IF_NTFY_CNCT_ATC_START: + case WIFI_DBG_IF_NTFY_COEX_NOTIFICATION: + case WIFI_DBG_IF_NTFY_COEX_HANDLE_ENVELOP: + case WIFI_DBG_IF_NTFY_COEX_HANDLE_RELEASE_ENVELOP: + IWM_DBG_MLME(iwm, DBG, "MLME debug notification: 0x%x\n", + notif->status); + break; + default: + IWM_ERR(iwm, "Unhandled notification: 0x%x\n", notif->status); + break; + } + + return 0; +} + +#define IWM_STATS_UPDATE_INTERVAL (2 * HZ) + +static int iwm_ntf_statistics(struct iwm_priv *iwm, u8 *buf, + unsigned long buf_size, struct iwm_wifi_cmd *cmd) +{ + struct iwm_umac_notif_stats *stats = (struct iwm_umac_notif_stats *)buf; + struct iw_statistics *wstats = &iwm->wstats; + u16 max_rate = 0; + int i; + + IWM_DBG_MLME(iwm, DBG, "Statistics notification received\n"); + + if (test_bit(IWM_STATUS_ASSOCIATED, &iwm->status)) { + for (i = 0; i < UMAC_NTF_RATE_SAMPLE_NR; i++) { + max_rate = max_t(u16, max_rate, + max(le16_to_cpu(stats->tx_rate[i]), + le16_to_cpu(stats->rx_rate[i]))); + } + /* UMAC passes rate info multiplies by 2 */ + iwm->rate = max_rate >> 1; + } + iwm->txpower = le32_to_cpu(stats->tx_power); + + wstats->status = 0; + + wstats->discard.nwid = le32_to_cpu(stats->rx_drop_other_bssid); + wstats->discard.code = le32_to_cpu(stats->rx_drop_decode); + wstats->discard.fragment = le32_to_cpu(stats->rx_drop_reassembly); + wstats->discard.retries = le32_to_cpu(stats->tx_drop_max_retry); + + wstats->miss.beacon = le32_to_cpu(stats->missed_beacons); + + /* according to cfg80211 */ + if (stats->rssi_dbm < -110) + wstats->qual.qual = 0; + else if (stats->rssi_dbm > -40) + wstats->qual.qual = 70; + else + wstats->qual.qual = stats->rssi_dbm + 110; + + wstats->qual.level = stats->rssi_dbm; + wstats->qual.noise = stats->noise_dbm; + wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM; + + schedule_delayed_work(&iwm->stats_request, IWM_STATS_UPDATE_INTERVAL); + + mod_timer(&iwm->watchdog, round_jiffies(jiffies + IWM_WATCHDOG_PERIOD)); + + return 0; +} + +static int iwm_ntf_eeprom_proxy(struct iwm_priv *iwm, u8 *buf, + unsigned long buf_size, + struct iwm_wifi_cmd *cmd) +{ + struct iwm_umac_cmd_eeprom_proxy *eeprom_proxy = + (struct iwm_umac_cmd_eeprom_proxy *) + (buf + sizeof(struct iwm_umac_wifi_in_hdr)); + struct iwm_umac_cmd_eeprom_proxy_hdr *hdr = &eeprom_proxy->hdr; + u32 hdr_offset = le32_to_cpu(hdr->offset); + u32 hdr_len = le32_to_cpu(hdr->len); + u32 hdr_type = le32_to_cpu(hdr->type); + + IWM_DBG_NTF(iwm, DBG, "type: 0x%x, len: %d, offset: 0x%x\n", + hdr_type, hdr_len, hdr_offset); + + if ((hdr_offset + hdr_len) > IWM_EEPROM_LEN) + return -EINVAL; + + switch (hdr_type) { + case IWM_UMAC_CMD_EEPROM_TYPE_READ: + memcpy(iwm->eeprom + hdr_offset, eeprom_proxy->buf, hdr_len); + break; + case IWM_UMAC_CMD_EEPROM_TYPE_WRITE: + default: + return -ENOTSUPP; + } + + return 0; +} + +static int iwm_ntf_channel_info_list(struct iwm_priv *iwm, u8 *buf, + unsigned long buf_size, + struct iwm_wifi_cmd *cmd) +{ + struct iwm_umac_cmd_get_channel_list *ch_list = + (struct iwm_umac_cmd_get_channel_list *) + (buf + sizeof(struct iwm_umac_wifi_in_hdr)); + struct wiphy *wiphy = iwm_to_wiphy(iwm); + struct ieee80211_supported_band *band; + int i; + + band = wiphy->bands[IEEE80211_BAND_2GHZ]; + + for (i = 0; i < band->n_channels; i++) { + unsigned long ch_mask_0 = + le32_to_cpu(ch_list->ch[0].channels_mask); + unsigned long ch_mask_2 = + le32_to_cpu(ch_list->ch[2].channels_mask); + + if (!test_bit(i, &ch_mask_0)) + band->channels[i].flags |= IEEE80211_CHAN_DISABLED; + + if (!test_bit(i, &ch_mask_2)) + band->channels[i].flags |= IEEE80211_CHAN_NO_IBSS; + } + + band = wiphy->bands[IEEE80211_BAND_5GHZ]; + + for (i = 0; i < min(band->n_channels, 32); i++) { + unsigned long ch_mask_1 = + le32_to_cpu(ch_list->ch[1].channels_mask); + unsigned long ch_mask_3 = + le32_to_cpu(ch_list->ch[3].channels_mask); + + if (!test_bit(i, &ch_mask_1)) + band->channels[i].flags |= IEEE80211_CHAN_DISABLED; + + if (!test_bit(i, &ch_mask_3)) + band->channels[i].flags |= IEEE80211_CHAN_NO_IBSS; + } + + return 0; +} + +static int iwm_ntf_stop_resume_tx(struct iwm_priv *iwm, u8 *buf, + unsigned long buf_size, + struct iwm_wifi_cmd *cmd) +{ + struct iwm_umac_notif_stop_resume_tx *stp_res_tx = + (struct iwm_umac_notif_stop_resume_tx *)buf; + struct iwm_sta_info *sta_info; + struct iwm_tid_info *tid_info; + u8 sta_id = STA_ID_N_COLOR_ID(stp_res_tx->sta_id); + u16 tid_msk = le16_to_cpu(stp_res_tx->stop_resume_tid_msk); + int bit, ret = 0; + bool stop = false; + + IWM_DBG_NTF(iwm, DBG, "stop/resume notification:\n" + "\tflags: 0x%x\n" + "\tSTA id: %d\n" + "\tTID bitmask: 0x%x\n", + stp_res_tx->flags, stp_res_tx->sta_id, + stp_res_tx->stop_resume_tid_msk); + + if (stp_res_tx->flags & UMAC_STOP_TX_FLAG) + stop = true; + + sta_info = &iwm->sta_table[sta_id]; + if (!sta_info->valid) { + IWM_ERR(iwm, "Stoping an invalid STA: %d %d\n", + sta_id, stp_res_tx->sta_id); + return -EINVAL; + } + + for_each_set_bit(bit, (unsigned long *)&tid_msk, IWM_UMAC_TID_NR) { + tid_info = &sta_info->tid_info[bit]; + + mutex_lock(&tid_info->mutex); + tid_info->stopped = stop; + mutex_unlock(&tid_info->mutex); + + if (!stop) { + struct iwm_tx_queue *txq; + int queue = iwm_tid_to_queue(bit); + + if (queue < 0) + continue; + + txq = &iwm->txq[queue]; + /* + * If we resume, we have to move our SKBs + * back to the tx queue and queue some work. + */ + spin_lock_bh(&txq->lock); + skb_queue_splice_init(&txq->queue, &txq->stopped_queue); + spin_unlock_bh(&txq->lock); + + queue_work(txq->wq, &txq->worker); + } + + } + + /* We send an ACK only for the stop case */ + if (stop) + ret = iwm_send_umac_stop_resume_tx(iwm, stp_res_tx); + + return ret; +} + +static int iwm_ntf_wifi_if_wrapper(struct iwm_priv *iwm, u8 *buf, + unsigned long buf_size, + struct iwm_wifi_cmd *cmd) +{ + struct iwm_umac_wifi_if *hdr; + + if (cmd == NULL) { + IWM_ERR(iwm, "Couldn't find expected wifi command\n"); + return -EINVAL; + } + + hdr = (struct iwm_umac_wifi_if *)cmd->buf.payload; + + IWM_DBG_NTF(iwm, DBG, "WIFI_IF_WRAPPER cmd is delivered to UMAC: " + "oid is 0x%x\n", hdr->oid); + + set_bit(hdr->oid, &iwm->wifi_ntfy[0]); + wake_up_interruptible(&iwm->wifi_ntfy_queue); + + switch (hdr->oid) { + case UMAC_WIFI_IF_CMD_SET_PROFILE: + iwm->umac_profile_active = true; + break; + default: + break; + } + + return 0; +} + +#define CT_KILL_DELAY (30 * HZ) +static int iwm_ntf_card_state(struct iwm_priv *iwm, u8 *buf, + unsigned long buf_size, struct iwm_wifi_cmd *cmd) +{ + struct wiphy *wiphy = iwm_to_wiphy(iwm); + struct iwm_lmac_card_state *state = (struct iwm_lmac_card_state *) + (buf + sizeof(struct iwm_umac_wifi_in_hdr)); + u32 flags = le32_to_cpu(state->flags); + + IWM_INFO(iwm, "HW RF Kill %s, CT Kill %s\n", + flags & IWM_CARD_STATE_HW_DISABLED ? "ON" : "OFF", + flags & IWM_CARD_STATE_CTKILL_DISABLED ? "ON" : "OFF"); + + if (flags & IWM_CARD_STATE_CTKILL_DISABLED) { + /* + * We got a CTKILL event: We bring the interface down in + * oder to cool the device down, and try to bring it up + * 30 seconds later. If it's still too hot, we'll go through + * this code path again. + */ + cancel_delayed_work_sync(&iwm->ct_kill_delay); + schedule_delayed_work(&iwm->ct_kill_delay, CT_KILL_DELAY); + } + + wiphy_rfkill_set_hw_state(wiphy, flags & + (IWM_CARD_STATE_HW_DISABLED | + IWM_CARD_STATE_CTKILL_DISABLED)); + + return 0; +} + +static int iwm_rx_handle_wifi(struct iwm_priv *iwm, u8 *buf, + unsigned long buf_size) +{ + struct iwm_umac_wifi_in_hdr *wifi_hdr; + struct iwm_wifi_cmd *cmd; + u8 source, cmd_id; + u16 seq_num; + u32 count; + + wifi_hdr = (struct iwm_umac_wifi_in_hdr *)buf; + cmd_id = wifi_hdr->sw_hdr.cmd.cmd; + source = GET_VAL32(wifi_hdr->hw_hdr.cmd, UMAC_HDI_IN_CMD_SOURCE); + if (source >= IWM_SRC_NUM) { + IWM_CRIT(iwm, "invalid source %d\n", source); + return -EINVAL; + } + + if (cmd_id == REPLY_RX_MPDU_CMD) + trace_iwm_rx_packet(iwm, buf, buf_size); + else if ((cmd_id == UMAC_NOTIFY_OPCODE_RX_TICKET) && + (source == UMAC_HDI_IN_SOURCE_FW)) + trace_iwm_rx_ticket(iwm, buf, buf_size); + else + trace_iwm_rx_wifi_cmd(iwm, wifi_hdr); + + count = GET_VAL32(wifi_hdr->sw_hdr.meta_data, UMAC_FW_CMD_BYTE_COUNT); + count += sizeof(struct iwm_umac_wifi_in_hdr) - + sizeof(struct iwm_dev_cmd_hdr); + if (count > buf_size) { + IWM_CRIT(iwm, "count %d, buf size:%ld\n", count, buf_size); + return -EINVAL; + } + + seq_num = le16_to_cpu(wifi_hdr->sw_hdr.cmd.seq_num); + + IWM_DBG_RX(iwm, DBG, "CMD:0x%x, source: 0x%x, seqnum: %d\n", + cmd_id, source, seq_num); + + /* + * If this is a response to a previously sent command, there must + * be a pending command for this sequence number. + */ + cmd = iwm_get_pending_wifi_cmd(iwm, seq_num); + + /* Notify the caller only for sync commands. */ + switch (source) { + case UMAC_HDI_IN_SOURCE_FHRX: + if (iwm->lmac_handlers[cmd_id] && + test_bit(cmd_id, &iwm->lmac_handler_map[0])) + return iwm_notif_send(iwm, cmd, cmd_id, source, + buf, count); + break; + case UMAC_HDI_IN_SOURCE_FW: + if (iwm->umac_handlers[cmd_id] && + test_bit(cmd_id, &iwm->umac_handler_map[0])) + return iwm_notif_send(iwm, cmd, cmd_id, source, + buf, count); + break; + case UMAC_HDI_IN_SOURCE_UDMA: + break; + } + + return iwm_rx_handle_resp(iwm, buf, count, cmd); +} + +int iwm_rx_handle_resp(struct iwm_priv *iwm, u8 *buf, unsigned long buf_size, + struct iwm_wifi_cmd *cmd) +{ + u8 source, cmd_id; + struct iwm_umac_wifi_in_hdr *wifi_hdr; + int ret = 0; + + wifi_hdr = (struct iwm_umac_wifi_in_hdr *)buf; + cmd_id = wifi_hdr->sw_hdr.cmd.cmd; + + source = GET_VAL32(wifi_hdr->hw_hdr.cmd, UMAC_HDI_IN_CMD_SOURCE); + + IWM_DBG_RX(iwm, DBG, "CMD:0x%x, source: 0x%x\n", cmd_id, source); + + switch (source) { + case UMAC_HDI_IN_SOURCE_FHRX: + if (iwm->lmac_handlers[cmd_id]) + ret = iwm->lmac_handlers[cmd_id] + (iwm, buf, buf_size, cmd); + break; + case UMAC_HDI_IN_SOURCE_FW: + if (iwm->umac_handlers[cmd_id]) + ret = iwm->umac_handlers[cmd_id] + (iwm, buf, buf_size, cmd); + break; + case UMAC_HDI_IN_SOURCE_UDMA: + ret = -EINVAL; + break; + } + + kfree(cmd); + + return ret; +} + +static int iwm_rx_handle_nonwifi(struct iwm_priv *iwm, u8 *buf, + unsigned long buf_size) +{ + u8 seq_num; + struct iwm_udma_in_hdr *hdr = (struct iwm_udma_in_hdr *)buf; + struct iwm_nonwifi_cmd *cmd; + + trace_iwm_rx_nonwifi_cmd(iwm, buf, buf_size); + seq_num = GET_VAL32(hdr->cmd, UDMA_HDI_IN_CMD_NON_WIFI_HW_SEQ_NUM); + + /* + * We received a non wifi answer. + * Let's check if there's a pending command for it, and if so + * replace the command payload with the buffer, and then wake the + * callers up. + * That means we only support synchronised non wifi command response + * schemes. + */ + list_for_each_entry(cmd, &iwm->nonwifi_pending_cmd, pending) + if (cmd->seq_num == seq_num) { + cmd->resp_received = true; + cmd->buf.len = buf_size; + memcpy(cmd->buf.hdr, buf, buf_size); + wake_up_interruptible(&iwm->nonwifi_queue); + } + + return 0; +} + +static int iwm_rx_handle_umac(struct iwm_priv *iwm, u8 *buf, + unsigned long buf_size) +{ + int ret = 0; + u8 op_code; + unsigned long buf_offset = 0; + struct iwm_udma_in_hdr *hdr; + + /* + * To allow for a more efficient bus usage, UMAC + * messages are encapsulated into UDMA ones. This + * way we can have several UMAC messages in one bus + * transfer. + * A UDMA frame size is always aligned on 16 bytes, + * and a UDMA frame must not start with a UMAC_PAD_TERMINAL + * word. This is how we parse a bus frame into several + * UDMA ones. + */ + while (buf_offset < buf_size) { + + hdr = (struct iwm_udma_in_hdr *)(buf + buf_offset); + + if (iwm_rx_check_udma_hdr(hdr) < 0) { + IWM_DBG_RX(iwm, DBG, "End of frame\n"); + break; + } + + op_code = GET_VAL32(hdr->cmd, UMAC_HDI_IN_CMD_OPCODE); + + IWM_DBG_RX(iwm, DBG, "Op code: 0x%x\n", op_code); + + if (op_code == UMAC_HDI_IN_OPCODE_WIFI) { + ret |= iwm_rx_handle_wifi(iwm, buf + buf_offset, + buf_size - buf_offset); + } else if (op_code < UMAC_HDI_IN_OPCODE_NONWIFI_MAX) { + if (GET_VAL32(hdr->cmd, + UDMA_HDI_IN_CMD_NON_WIFI_HW_SIG) != + UDMA_HDI_IN_CMD_NON_WIFI_HW_SIG) { + IWM_ERR(iwm, "Incorrect hw signature\n"); + return -EINVAL; + } + ret |= iwm_rx_handle_nonwifi(iwm, buf + buf_offset, + buf_size - buf_offset); + } else { + IWM_ERR(iwm, "Invalid RX opcode: 0x%x\n", op_code); + ret |= -EINVAL; + } + + buf_offset += iwm_rx_resp_size(hdr); + } + + return ret; +} + +int iwm_rx_handle(struct iwm_priv *iwm, u8 *buf, unsigned long buf_size) +{ + struct iwm_udma_in_hdr *hdr; + + hdr = (struct iwm_udma_in_hdr *)buf; + + switch (le32_to_cpu(hdr->cmd)) { + case UMAC_REBOOT_BARKER: + if (test_bit(IWM_STATUS_READY, &iwm->status)) { + IWM_ERR(iwm, "Unexpected BARKER\n"); + + schedule_work(&iwm->reset_worker); + + return 0; + } + + return iwm_notif_send(iwm, NULL, IWM_BARKER_REBOOT_NOTIFICATION, + IWM_SRC_UDMA, buf, buf_size); + case UMAC_ACK_BARKER: + return iwm_notif_send(iwm, NULL, IWM_ACK_BARKER_NOTIFICATION, + IWM_SRC_UDMA, NULL, 0); + default: + IWM_DBG_RX(iwm, DBG, "Received cmd: 0x%x\n", hdr->cmd); + return iwm_rx_handle_umac(iwm, buf, buf_size); + } + + return 0; +} + +static const iwm_handler iwm_umac_handlers[] = +{ + [UMAC_NOTIFY_OPCODE_ERROR] = iwm_ntf_error, + [UMAC_NOTIFY_OPCODE_ALIVE] = iwm_ntf_umac_alive, + [UMAC_NOTIFY_OPCODE_INIT_COMPLETE] = iwm_ntf_init_complete, + [UMAC_NOTIFY_OPCODE_WIFI_CORE_STATUS] = iwm_ntf_wifi_status, + [UMAC_NOTIFY_OPCODE_WIFI_IF_WRAPPER] = iwm_ntf_mlme, + [UMAC_NOTIFY_OPCODE_PAGE_DEALLOC] = iwm_ntf_tx_credit_update, + [UMAC_NOTIFY_OPCODE_RX_TICKET] = iwm_ntf_rx_ticket, + [UMAC_CMD_OPCODE_RESET] = iwm_ntf_umac_reset, + [UMAC_NOTIFY_OPCODE_STATS] = iwm_ntf_statistics, + [UMAC_CMD_OPCODE_EEPROM_PROXY] = iwm_ntf_eeprom_proxy, + [UMAC_CMD_OPCODE_GET_CHAN_INFO_LIST] = iwm_ntf_channel_info_list, + [UMAC_CMD_OPCODE_STOP_RESUME_STA_TX] = iwm_ntf_stop_resume_tx, + [REPLY_RX_MPDU_CMD] = iwm_ntf_rx_packet, + [UMAC_CMD_OPCODE_WIFI_IF_WRAPPER] = iwm_ntf_wifi_if_wrapper, +}; + +static const iwm_handler iwm_lmac_handlers[] = +{ + [REPLY_TX] = iwm_ntf_tx, + [REPLY_ALIVE] = iwm_ntf_lmac_version, + [CALIBRATION_RES_NOTIFICATION] = iwm_ntf_calib_res, + [CALIBRATION_COMPLETE_NOTIFICATION] = iwm_ntf_calib_complete, + [CALIBRATION_CFG_CMD] = iwm_ntf_calib_cfg, + [REPLY_RX_MPDU_CMD] = iwm_ntf_rx_packet, + [CARD_STATE_NOTIFICATION] = iwm_ntf_card_state, +}; + +void iwm_rx_setup_handlers(struct iwm_priv *iwm) +{ + iwm->umac_handlers = (iwm_handler *) iwm_umac_handlers; + iwm->lmac_handlers = (iwm_handler *) iwm_lmac_handlers; +} + +static void iwm_remove_iv(struct sk_buff *skb, u32 hdr_total_len) +{ + struct ieee80211_hdr *hdr; + unsigned int hdr_len; + + hdr = (struct ieee80211_hdr *)skb->data; + + if (!ieee80211_has_protected(hdr->frame_control)) + return; + + hdr_len = ieee80211_hdrlen(hdr->frame_control); + if (hdr_total_len <= hdr_len) + return; + + memmove(skb->data + (hdr_total_len - hdr_len), skb->data, hdr_len); + skb_pull(skb, (hdr_total_len - hdr_len)); +} + +static void iwm_rx_adjust_packet(struct iwm_priv *iwm, + struct iwm_rx_packet *packet, + struct iwm_rx_ticket_node *ticket_node) +{ + u32 payload_offset = 0, payload_len; + struct iwm_rx_ticket *ticket = ticket_node->ticket; + struct iwm_rx_mpdu_hdr *mpdu_hdr; + struct ieee80211_hdr *hdr; + + mpdu_hdr = (struct iwm_rx_mpdu_hdr *)packet->skb->data; + payload_offset += sizeof(struct iwm_rx_mpdu_hdr); + /* Padding is 0 or 2 bytes */ + payload_len = le16_to_cpu(mpdu_hdr->len) + + (le16_to_cpu(ticket->flags) & IWM_RX_TICKET_PAD_SIZE_MSK); + payload_len -= ticket->tail_len; + + IWM_DBG_RX(iwm, DBG, "Packet adjusted, len:%d, offset:%d, " + "ticket offset:%d ticket tail len:%d\n", + payload_len, payload_offset, ticket->payload_offset, + ticket->tail_len); + + IWM_HEXDUMP(iwm, DBG, RX, "RAW: ", packet->skb->data, packet->skb->len); + + skb_pull(packet->skb, payload_offset); + skb_trim(packet->skb, payload_len); + + iwm_remove_iv(packet->skb, ticket->payload_offset); + + hdr = (struct ieee80211_hdr *) packet->skb->data; + if (ieee80211_is_data_qos(hdr->frame_control)) { + /* UMAC handed QOS_DATA frame with 2 padding bytes appended + * to the qos_ctl field in IEEE 802.11 headers. */ + memmove(packet->skb->data + IEEE80211_QOS_CTL_LEN + 2, + packet->skb->data, + ieee80211_hdrlen(hdr->frame_control) - + IEEE80211_QOS_CTL_LEN); + hdr = (struct ieee80211_hdr *) skb_pull(packet->skb, + IEEE80211_QOS_CTL_LEN + 2); + hdr->frame_control &= ~cpu_to_le16(IEEE80211_STYPE_QOS_DATA); + } + + IWM_HEXDUMP(iwm, DBG, RX, "ADJUSTED: ", + packet->skb->data, packet->skb->len); +} + +static void classify8023(struct sk_buff *skb) +{ + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; + + if (ieee80211_is_data_qos(hdr->frame_control)) { + u8 *qc = ieee80211_get_qos_ctl(hdr); + /* frame has qos control */ + skb->priority = *qc & IEEE80211_QOS_CTL_TID_MASK; + } else { + skb->priority = 0; + } +} + +static void iwm_rx_process_amsdu(struct iwm_priv *iwm, struct sk_buff *skb) +{ + struct wireless_dev *wdev = iwm_to_wdev(iwm); + struct net_device *ndev = iwm_to_ndev(iwm); + struct sk_buff_head list; + struct sk_buff *frame; + + IWM_HEXDUMP(iwm, DBG, RX, "A-MSDU: ", skb->data, skb->len); + + __skb_queue_head_init(&list); + ieee80211_amsdu_to_8023s(skb, &list, ndev->dev_addr, wdev->iftype, 0, + true); + + while ((frame = __skb_dequeue(&list))) { + ndev->stats.rx_packets++; + ndev->stats.rx_bytes += frame->len; + + frame->protocol = eth_type_trans(frame, ndev); + frame->ip_summed = CHECKSUM_NONE; + memset(frame->cb, 0, sizeof(frame->cb)); + + if (netif_rx_ni(frame) == NET_RX_DROP) { + IWM_ERR(iwm, "Packet dropped\n"); + ndev->stats.rx_dropped++; + } + } +} + +static void iwm_rx_process_packet(struct iwm_priv *iwm, + struct iwm_rx_packet *packet, + struct iwm_rx_ticket_node *ticket_node) +{ + int ret; + struct sk_buff *skb = packet->skb; + struct wireless_dev *wdev = iwm_to_wdev(iwm); + struct net_device *ndev = iwm_to_ndev(iwm); + + IWM_DBG_RX(iwm, DBG, "Processing packet ID %d\n", packet->id); + + switch (le16_to_cpu(ticket_node->ticket->action)) { + case IWM_RX_TICKET_RELEASE: + IWM_DBG_RX(iwm, DBG, "RELEASE packet\n"); + + iwm_rx_adjust_packet(iwm, packet, ticket_node); + skb->dev = iwm_to_ndev(iwm); + classify8023(skb); + + if (le16_to_cpu(ticket_node->ticket->flags) & + IWM_RX_TICKET_AMSDU_MSK) { + iwm_rx_process_amsdu(iwm, skb); + break; + } + + ret = ieee80211_data_to_8023(skb, ndev->dev_addr, wdev->iftype); + if (ret < 0) { + IWM_DBG_RX(iwm, DBG, "Couldn't convert 802.11 header - " + "%d\n", ret); + kfree_skb(packet->skb); + break; + } + + IWM_HEXDUMP(iwm, DBG, RX, "802.3: ", skb->data, skb->len); + + ndev->stats.rx_packets++; + ndev->stats.rx_bytes += skb->len; + + skb->protocol = eth_type_trans(skb, ndev); + skb->ip_summed = CHECKSUM_NONE; + memset(skb->cb, 0, sizeof(skb->cb)); + + if (netif_rx_ni(skb) == NET_RX_DROP) { + IWM_ERR(iwm, "Packet dropped\n"); + ndev->stats.rx_dropped++; + } + break; + case IWM_RX_TICKET_DROP: + IWM_DBG_RX(iwm, DBG, "DROP packet: 0x%x\n", + le16_to_cpu(ticket_node->ticket->flags)); + kfree_skb(packet->skb); + break; + default: + IWM_ERR(iwm, "Unknown ticket action: %d\n", + le16_to_cpu(ticket_node->ticket->action)); + kfree_skb(packet->skb); + } + + kfree(packet); + iwm_rx_ticket_node_free(ticket_node); +} + +/* + * Rx data processing: + * + * We're receiving Rx packet from the LMAC, and Rx ticket from + * the UMAC. + * To forward a target data packet upstream (i.e. to the + * kernel network stack), we must have received an Rx ticket + * that tells us we're allowed to release this packet (ticket + * action is IWM_RX_TICKET_RELEASE). The Rx ticket also indicates, + * among other things, where valid data actually starts in the Rx + * packet. + */ +void iwm_rx_worker(struct work_struct *work) +{ + struct iwm_priv *iwm; + struct iwm_rx_ticket_node *ticket, *next; + + iwm = container_of(work, struct iwm_priv, rx_worker); + + /* + * We go through the tickets list and if there is a pending + * packet for it, we push it upstream. + * We stop whenever a ticket is missing its packet, as we're + * supposed to send the packets in order. + */ + spin_lock(&iwm->ticket_lock); + list_for_each_entry_safe(ticket, next, &iwm->rx_tickets, node) { + struct iwm_rx_packet *packet = + iwm_rx_packet_get(iwm, le16_to_cpu(ticket->ticket->id)); + + if (!packet) { + IWM_DBG_RX(iwm, DBG, "Skip rx_work: Wait for ticket %d " + "to be handled first\n", + le16_to_cpu(ticket->ticket->id)); + break; + } + + list_del(&ticket->node); + iwm_rx_process_packet(iwm, packet, ticket); + } + spin_unlock(&iwm->ticket_lock); +} + diff --git a/trunk/drivers/net/wireless/iwmc3200wifi/rx.h b/trunk/drivers/net/wireless/iwmc3200wifi/rx.h new file mode 100644 index 000000000000..da0db91cee59 --- /dev/null +++ b/trunk/drivers/net/wireless/iwmc3200wifi/rx.h @@ -0,0 +1,60 @@ +/* + * Intel Wireless Multicomm 3200 WiFi driver + * + * Copyright (C) 2009 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * + * Intel Corporation + * Samuel Ortiz + * Zhu Yi + * + */ + +#ifndef __IWM_RX_H__ +#define __IWM_RX_H__ + +#include + +#include "umac.h" + +struct iwm_rx_ticket_node { + struct list_head node; + struct iwm_rx_ticket *ticket; +}; + +struct iwm_rx_packet { + struct list_head node; + u16 id; + struct sk_buff *skb; + unsigned long pkt_size; +}; + +void iwm_rx_worker(struct work_struct *work); + +#endif diff --git a/trunk/drivers/net/wireless/iwmc3200wifi/sdio.c b/trunk/drivers/net/wireless/iwmc3200wifi/sdio.c new file mode 100644 index 000000000000..0042f204b07f --- /dev/null +++ b/trunk/drivers/net/wireless/iwmc3200wifi/sdio.c @@ -0,0 +1,509 @@ +/* + * Intel Wireless Multicomm 3200 WiFi driver + * + * Copyright (C) 2009 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * + * Intel Corporation + * Samuel Ortiz + * Zhu Yi + * + */ + +/* + * This is the SDIO bus specific hooks for iwm. + * It also is the module's entry point. + * + * Interesting code paths: + * iwm_sdio_probe() (Called by an SDIO bus scan) + * -> iwm_if_alloc() (netdev.c) + * -> iwm_wdev_alloc() (cfg80211.c, allocates and register our wiphy) + * -> wiphy_new() + * -> wiphy_register() + * -> alloc_netdev_mq() + * -> register_netdev() + * + * iwm_sdio_remove() + * -> iwm_if_free() (netdev.c) + * -> unregister_netdev() + * -> iwm_wdev_free() (cfg80211.c) + * -> wiphy_unregister() + * -> wiphy_free() + * + * iwm_sdio_isr() (called in process context from the SDIO core code) + * -> queue_work(.., isr_worker) + * -- [async] --> iwm_sdio_isr_worker() + * -> iwm_rx_handle() + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "iwm.h" +#include "debug.h" +#include "bus.h" +#include "sdio.h" + +static void iwm_sdio_isr_worker(struct work_struct *work) +{ + struct iwm_sdio_priv *hw; + struct iwm_priv *iwm; + struct iwm_rx_info *rx_info; + struct sk_buff *skb; + u8 *rx_buf; + unsigned long rx_size; + + hw = container_of(work, struct iwm_sdio_priv, isr_worker); + iwm = hw_to_iwm(hw); + + while (!skb_queue_empty(&iwm->rx_list)) { + skb = skb_dequeue(&iwm->rx_list); + rx_info = skb_to_rx_info(skb); + rx_size = rx_info->rx_size; + rx_buf = skb->data; + + IWM_HEXDUMP(iwm, DBG, SDIO, "RX: ", rx_buf, rx_size); + if (iwm_rx_handle(iwm, rx_buf, rx_size) < 0) + IWM_WARN(iwm, "RX error\n"); + + kfree_skb(skb); + } +} + +static void iwm_sdio_isr(struct sdio_func *func) +{ + struct iwm_priv *iwm; + struct iwm_sdio_priv *hw; + struct iwm_rx_info *rx_info; + struct sk_buff *skb; + unsigned long buf_size, read_size; + int ret; + u8 val; + + hw = sdio_get_drvdata(func); + iwm = hw_to_iwm(hw); + + buf_size = hw->blk_size; + + /* We're checking the status */ + val = sdio_readb(func, IWM_SDIO_INTR_STATUS_ADDR, &ret); + if (val == 0 || ret < 0) { + IWM_ERR(iwm, "Wrong INTR_STATUS\n"); + return; + } + + /* See if we have free buffers */ + if (skb_queue_len(&iwm->rx_list) > IWM_RX_LIST_SIZE) { + IWM_ERR(iwm, "No buffer for more Rx frames\n"); + return; + } + + /* We first read the transaction size */ + read_size = sdio_readb(func, IWM_SDIO_INTR_GET_SIZE_ADDR + 1, &ret); + read_size = read_size << 8; + + if (ret < 0) { + IWM_ERR(iwm, "Couldn't read the xfer size\n"); + return; + } + + /* We need to clear the INT register */ + sdio_writeb(func, 1, IWM_SDIO_INTR_CLEAR_ADDR, &ret); + if (ret < 0) { + IWM_ERR(iwm, "Couldn't clear the INT register\n"); + return; + } + + while (buf_size < read_size) + buf_size <<= 1; + + skb = dev_alloc_skb(buf_size); + if (!skb) { + IWM_ERR(iwm, "Couldn't alloc RX skb\n"); + return; + } + rx_info = skb_to_rx_info(skb); + rx_info->rx_size = read_size; + rx_info->rx_buf_size = buf_size; + + /* Now we can read the actual buffer */ + ret = sdio_memcpy_fromio(func, skb_put(skb, read_size), + IWM_SDIO_DATA_ADDR, read_size); + + /* The skb is put on a driver's specific Rx SKB list */ + skb_queue_tail(&iwm->rx_list, skb); + + /* We can now schedule the actual worker */ + queue_work(hw->isr_wq, &hw->isr_worker); +} + +static void iwm_sdio_rx_free(struct iwm_sdio_priv *hw) +{ + struct iwm_priv *iwm = hw_to_iwm(hw); + + flush_workqueue(hw->isr_wq); + + skb_queue_purge(&iwm->rx_list); +} + +/* Bus ops */ +static int if_sdio_enable(struct iwm_priv *iwm) +{ + struct iwm_sdio_priv *hw = iwm_to_if_sdio(iwm); + int ret; + + sdio_claim_host(hw->func); + + ret = sdio_enable_func(hw->func); + if (ret) { + IWM_ERR(iwm, "Couldn't enable the device: is TOP driver " + "loaded and functional?\n"); + goto release_host; + } + + iwm_reset(iwm); + + ret = sdio_claim_irq(hw->func, iwm_sdio_isr); + if (ret) { + IWM_ERR(iwm, "Failed to claim irq: %d\n", ret); + goto release_host; + } + + sdio_writeb(hw->func, 1, IWM_SDIO_INTR_ENABLE_ADDR, &ret); + if (ret < 0) { + IWM_ERR(iwm, "Couldn't enable INTR: %d\n", ret); + goto release_irq; + } + + sdio_release_host(hw->func); + + IWM_DBG_SDIO(iwm, INFO, "IWM SDIO enable\n"); + + return 0; + + release_irq: + sdio_release_irq(hw->func); + release_host: + sdio_release_host(hw->func); + + return ret; +} + +static int if_sdio_disable(struct iwm_priv *iwm) +{ + struct iwm_sdio_priv *hw = iwm_to_if_sdio(iwm); + int ret; + + sdio_claim_host(hw->func); + sdio_writeb(hw->func, 0, IWM_SDIO_INTR_ENABLE_ADDR, &ret); + if (ret < 0) + IWM_WARN(iwm, "Couldn't disable INTR: %d\n", ret); + + sdio_release_irq(hw->func); + sdio_disable_func(hw->func); + sdio_release_host(hw->func); + + iwm_sdio_rx_free(hw); + + iwm_reset(iwm); + + IWM_DBG_SDIO(iwm, INFO, "IWM SDIO disable\n"); + + return 0; +} + +static int if_sdio_send_chunk(struct iwm_priv *iwm, u8 *buf, int count) +{ + struct iwm_sdio_priv *hw = iwm_to_if_sdio(iwm); + int aligned_count = ALIGN(count, hw->blk_size); + int ret; + + if ((unsigned long)buf & 0x3) { + IWM_ERR(iwm, "buf <%p> is not dword aligned\n", buf); + /* TODO: Is this a hardware limitation? use get_unligned */ + return -EINVAL; + } + + sdio_claim_host(hw->func); + ret = sdio_memcpy_toio(hw->func, IWM_SDIO_DATA_ADDR, buf, + aligned_count); + sdio_release_host(hw->func); + + return ret; +} + +static ssize_t iwm_debugfs_sdio_read(struct file *filp, char __user *buffer, + size_t count, loff_t *ppos) +{ + struct iwm_priv *iwm = filp->private_data; + struct iwm_sdio_priv *hw = iwm_to_if_sdio(iwm); + char *buf; + u8 cccr; + int buf_len = 4096, ret; + size_t len = 0; + + if (*ppos != 0) + return 0; + if (count < sizeof(buf)) + return -ENOSPC; + + buf = kzalloc(buf_len, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + sdio_claim_host(hw->func); + + cccr = sdio_f0_readb(hw->func, SDIO_CCCR_IOEx, &ret); + if (ret) { + IWM_ERR(iwm, "Could not read SDIO_CCCR_IOEx\n"); + goto err; + } + len += snprintf(buf + len, buf_len - len, "CCCR_IOEx: 0x%x\n", cccr); + + cccr = sdio_f0_readb(hw->func, SDIO_CCCR_IORx, &ret); + if (ret) { + IWM_ERR(iwm, "Could not read SDIO_CCCR_IORx\n"); + goto err; + } + len += snprintf(buf + len, buf_len - len, "CCCR_IORx: 0x%x\n", cccr); + + + cccr = sdio_f0_readb(hw->func, SDIO_CCCR_IENx, &ret); + if (ret) { + IWM_ERR(iwm, "Could not read SDIO_CCCR_IENx\n"); + goto err; + } + len += snprintf(buf + len, buf_len - len, "CCCR_IENx: 0x%x\n", cccr); + + + cccr = sdio_f0_readb(hw->func, SDIO_CCCR_INTx, &ret); + if (ret) { + IWM_ERR(iwm, "Could not read SDIO_CCCR_INTx\n"); + goto err; + } + len += snprintf(buf + len, buf_len - len, "CCCR_INTx: 0x%x\n", cccr); + + + cccr = sdio_f0_readb(hw->func, SDIO_CCCR_ABORT, &ret); + if (ret) { + IWM_ERR(iwm, "Could not read SDIO_CCCR_ABORTx\n"); + goto err; + } + len += snprintf(buf + len, buf_len - len, "CCCR_ABORT: 0x%x\n", cccr); + + cccr = sdio_f0_readb(hw->func, SDIO_CCCR_IF, &ret); + if (ret) { + IWM_ERR(iwm, "Could not read SDIO_CCCR_IF\n"); + goto err; + } + len += snprintf(buf + len, buf_len - len, "CCCR_IF: 0x%x\n", cccr); + + + cccr = sdio_f0_readb(hw->func, SDIO_CCCR_CAPS, &ret); + if (ret) { + IWM_ERR(iwm, "Could not read SDIO_CCCR_CAPS\n"); + goto err; + } + len += snprintf(buf + len, buf_len - len, "CCCR_CAPS: 0x%x\n", cccr); + + cccr = sdio_f0_readb(hw->func, SDIO_CCCR_CIS, &ret); + if (ret) { + IWM_ERR(iwm, "Could not read SDIO_CCCR_CIS\n"); + goto err; + } + len += snprintf(buf + len, buf_len - len, "CCCR_CIS: 0x%x\n", cccr); + + ret = simple_read_from_buffer(buffer, len, ppos, buf, buf_len); +err: + sdio_release_host(hw->func); + + kfree(buf); + + return ret; +} + +static const struct file_operations iwm_debugfs_sdio_fops = { + .owner = THIS_MODULE, + .open = simple_open, + .read = iwm_debugfs_sdio_read, + .llseek = default_llseek, +}; + +static void if_sdio_debugfs_init(struct iwm_priv *iwm, struct dentry *parent_dir) +{ + struct iwm_sdio_priv *hw = iwm_to_if_sdio(iwm); + + hw->cccr_dentry = debugfs_create_file("cccr", 0200, + parent_dir, iwm, + &iwm_debugfs_sdio_fops); +} + +static void if_sdio_debugfs_exit(struct iwm_priv *iwm) +{ + struct iwm_sdio_priv *hw = iwm_to_if_sdio(iwm); + + debugfs_remove(hw->cccr_dentry); +} + +static struct iwm_if_ops if_sdio_ops = { + .enable = if_sdio_enable, + .disable = if_sdio_disable, + .send_chunk = if_sdio_send_chunk, + .debugfs_init = if_sdio_debugfs_init, + .debugfs_exit = if_sdio_debugfs_exit, + .umac_name = "iwmc3200wifi-umac-sdio.bin", + .calib_lmac_name = "iwmc3200wifi-calib-sdio.bin", + .lmac_name = "iwmc3200wifi-lmac-sdio.bin", +}; +MODULE_FIRMWARE("iwmc3200wifi-umac-sdio.bin"); +MODULE_FIRMWARE("iwmc3200wifi-calib-sdio.bin"); +MODULE_FIRMWARE("iwmc3200wifi-lmac-sdio.bin"); + +static int iwm_sdio_probe(struct sdio_func *func, + const struct sdio_device_id *id) +{ + struct iwm_priv *iwm; + struct iwm_sdio_priv *hw; + struct device *dev = &func->dev; + int ret; + + /* check if TOP has already initialized the card */ + sdio_claim_host(func); + ret = sdio_enable_func(func); + if (ret) { + dev_err(dev, "wait for TOP to enable the device\n"); + sdio_release_host(func); + return ret; + } + + ret = sdio_set_block_size(func, IWM_SDIO_BLK_SIZE); + + sdio_disable_func(func); + sdio_release_host(func); + + if (ret < 0) { + dev_err(dev, "Failed to set block size: %d\n", ret); + return ret; + } + + iwm = iwm_if_alloc(sizeof(struct iwm_sdio_priv), dev, &if_sdio_ops); + if (IS_ERR(iwm)) { + dev_err(dev, "allocate SDIO interface failed\n"); + return PTR_ERR(iwm); + } + + hw = iwm_private(iwm); + hw->iwm = iwm; + + iwm_debugfs_init(iwm); + + sdio_set_drvdata(func, hw); + + hw->func = func; + hw->blk_size = IWM_SDIO_BLK_SIZE; + + hw->isr_wq = create_singlethread_workqueue(KBUILD_MODNAME "_sdio"); + if (!hw->isr_wq) { + ret = -ENOMEM; + goto debugfs_exit; + } + + INIT_WORK(&hw->isr_worker, iwm_sdio_isr_worker); + + ret = iwm_if_add(iwm); + if (ret) { + dev_err(dev, "add SDIO interface failed\n"); + goto destroy_wq; + } + + dev_info(dev, "IWM SDIO probe\n"); + + return 0; + + destroy_wq: + destroy_workqueue(hw->isr_wq); + debugfs_exit: + iwm_debugfs_exit(iwm); + iwm_if_free(iwm); + return ret; +} + +static void iwm_sdio_remove(struct sdio_func *func) +{ + struct iwm_sdio_priv *hw = sdio_get_drvdata(func); + struct iwm_priv *iwm = hw_to_iwm(hw); + struct device *dev = &func->dev; + + iwm_if_remove(iwm); + destroy_workqueue(hw->isr_wq); + iwm_debugfs_exit(iwm); + iwm_if_free(iwm); + + sdio_set_drvdata(func, NULL); + + dev_info(dev, "IWM SDIO remove\n"); +} + +static const struct sdio_device_id iwm_sdio_ids[] = { + /* Global/AGN SKU */ + { SDIO_DEVICE(SDIO_VENDOR_ID_INTEL, 0x1403) }, + /* BGN SKU */ + { SDIO_DEVICE(SDIO_VENDOR_ID_INTEL, 0x1408) }, + { /* end: all zeroes */ }, +}; +MODULE_DEVICE_TABLE(sdio, iwm_sdio_ids); + +static struct sdio_driver iwm_sdio_driver = { + .name = "iwm_sdio", + .id_table = iwm_sdio_ids, + .probe = iwm_sdio_probe, + .remove = iwm_sdio_remove, +}; + +static int __init iwm_sdio_init_module(void) +{ + return sdio_register_driver(&iwm_sdio_driver); +} + +static void __exit iwm_sdio_exit_module(void) +{ + sdio_unregister_driver(&iwm_sdio_driver); +} + +module_init(iwm_sdio_init_module); +module_exit(iwm_sdio_exit_module); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR(IWM_COPYRIGHT " " IWM_AUTHOR); diff --git a/trunk/drivers/net/wireless/iwmc3200wifi/sdio.h b/trunk/drivers/net/wireless/iwmc3200wifi/sdio.h new file mode 100644 index 000000000000..aab6b6892e45 --- /dev/null +++ b/trunk/drivers/net/wireless/iwmc3200wifi/sdio.h @@ -0,0 +1,64 @@ +/* + * Intel Wireless Multicomm 3200 WiFi driver + * + * Copyright (C) 2009 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * + * Intel Corporation + * Samuel Ortiz + * Zhu Yi + * + */ + +#ifndef __IWM_SDIO_H__ +#define __IWM_SDIO_H__ + +#define IWM_SDIO_DATA_ADDR 0x0 +#define IWM_SDIO_INTR_ENABLE_ADDR 0x14 +#define IWM_SDIO_INTR_STATUS_ADDR 0x13 +#define IWM_SDIO_INTR_CLEAR_ADDR 0x13 +#define IWM_SDIO_INTR_GET_SIZE_ADDR 0x2C + +#define IWM_SDIO_BLK_SIZE 256 + +#define iwm_to_if_sdio(i) (struct iwm_sdio_priv *)(iwm->private) + +struct iwm_sdio_priv { + struct sdio_func *func; + struct iwm_priv *iwm; + + struct workqueue_struct *isr_wq; + struct work_struct isr_worker; + + struct dentry *cccr_dentry; + + unsigned int blk_size; +}; + +#endif diff --git a/trunk/drivers/net/wireless/iwmc3200wifi/trace.c b/trunk/drivers/net/wireless/iwmc3200wifi/trace.c new file mode 100644 index 000000000000..904d36f22311 --- /dev/null +++ b/trunk/drivers/net/wireless/iwmc3200wifi/trace.c @@ -0,0 +1,3 @@ +#include "iwm.h" +#define CREATE_TRACE_POINTS +#include "trace.h" diff --git a/trunk/drivers/net/wireless/iwmc3200wifi/trace.h b/trunk/drivers/net/wireless/iwmc3200wifi/trace.h new file mode 100644 index 000000000000..f5f7070b7e22 --- /dev/null +++ b/trunk/drivers/net/wireless/iwmc3200wifi/trace.h @@ -0,0 +1,283 @@ +#if !defined(__IWM_TRACE_H__) || defined(TRACE_HEADER_MULTI_READ) +#define __IWM_TRACE_H__ + +#include + +#if !defined(CONFIG_IWM_TRACING) +#undef TRACE_EVENT +#define TRACE_EVENT(name, proto, ...) \ +static inline void trace_ ## name(proto) {} +#endif + +#undef TRACE_SYSTEM +#define TRACE_SYSTEM iwm + +#define IWM_ENTRY __array(char, ndev_name, 16) +#define IWM_ASSIGN strlcpy(__entry->ndev_name, iwm_to_ndev(iwm)->name, 16) +#define IWM_PR_FMT "%s" +#define IWM_PR_ARG __entry->ndev_name + +TRACE_EVENT(iwm_tx_nonwifi_cmd, + TP_PROTO(struct iwm_priv *iwm, struct iwm_udma_out_nonwifi_hdr *hdr), + + TP_ARGS(iwm, hdr), + + TP_STRUCT__entry( + IWM_ENTRY + __field(u8, opcode) + __field(u8, resp) + __field(u8, eot) + __field(u8, hw) + __field(u16, seq) + __field(u32, addr) + __field(u32, op1) + __field(u32, op2) + ), + + TP_fast_assign( + IWM_ASSIGN; + __entry->opcode = GET_VAL32(hdr->cmd, UMAC_HDI_OUT_CMD_OPCODE); + __entry->resp = GET_VAL32(hdr->cmd, UDMA_HDI_OUT_NW_CMD_RESP); + __entry->eot = GET_VAL32(hdr->cmd, UMAC_HDI_OUT_CMD_EOT); + __entry->hw = GET_VAL32(hdr->cmd, UDMA_HDI_OUT_NW_CMD_HANDLE_BY_HW); + __entry->seq = GET_VAL32(hdr->cmd, UDMA_HDI_OUT_CMD_NON_WIFI_HW_SEQ_NUM); + __entry->addr = le32_to_cpu(hdr->addr); + __entry->op1 = le32_to_cpu(hdr->op1_sz); + __entry->op2 = le32_to_cpu(hdr->op2); + ), + + TP_printk( + IWM_PR_FMT " Tx TARGET CMD: opcode 0x%x, resp %d, eot %d, " + "hw %d, seq 0x%x, addr 0x%x, op1 0x%x, op2 0x%x", + IWM_PR_ARG, __entry->opcode, __entry->resp, __entry->eot, + __entry->hw, __entry->seq, __entry->addr, __entry->op1, + __entry->op2 + ) +); + +TRACE_EVENT(iwm_tx_wifi_cmd, + TP_PROTO(struct iwm_priv *iwm, struct iwm_umac_wifi_out_hdr *hdr), + + TP_ARGS(iwm, hdr), + + TP_STRUCT__entry( + IWM_ENTRY + __field(u8, opcode) + __field(u8, lmac) + __field(u8, resp) + __field(u8, eot) + __field(u8, ra_tid) + __field(u8, credit_group) + __field(u8, color) + __field(u16, seq) + ), + + TP_fast_assign( + IWM_ASSIGN; + __entry->opcode = hdr->sw_hdr.cmd.cmd; + __entry->lmac = 0; + __entry->seq = __le16_to_cpu(hdr->sw_hdr.cmd.seq_num); + __entry->resp = GET_VAL8(hdr->sw_hdr.cmd.flags, UMAC_DEV_CMD_FLAGS_RESP_REQ); + __entry->color = GET_VAL32(hdr->sw_hdr.meta_data, UMAC_FW_CMD_TX_STA_COLOR); + __entry->eot = GET_VAL32(hdr->hw_hdr.cmd, UMAC_HDI_OUT_CMD_EOT); + __entry->ra_tid = GET_VAL32(hdr->hw_hdr.meta_data, UMAC_HDI_OUT_RATID); + __entry->credit_group = GET_VAL32(hdr->hw_hdr.meta_data, UMAC_HDI_OUT_CREDIT_GRP); + if (__entry->opcode == UMAC_CMD_OPCODE_WIFI_PASS_THROUGH || + __entry->opcode == UMAC_CMD_OPCODE_WIFI_IF_WRAPPER) { + __entry->lmac = 1; + __entry->opcode = ((struct iwm_lmac_hdr *)(hdr + 1))->id; + } + ), + + TP_printk( + IWM_PR_FMT " Tx %cMAC CMD: opcode 0x%x, resp %d, eot %d, " + "seq 0x%x, sta_color 0x%x, ra_tid 0x%x, credit_group 0x%x", + IWM_PR_ARG, __entry->lmac ? 'L' : 'U', __entry->opcode, + __entry->resp, __entry->eot, __entry->seq, __entry->color, + __entry->ra_tid, __entry->credit_group + ) +); + +TRACE_EVENT(iwm_tx_packets, + TP_PROTO(struct iwm_priv *iwm, u8 *buf, int len), + + TP_ARGS(iwm, buf, len), + + TP_STRUCT__entry( + IWM_ENTRY + __field(u8, eot) + __field(u8, ra_tid) + __field(u8, credit_group) + __field(u8, color) + __field(u16, seq) + __field(u8, npkt) + __field(u32, bytes) + ), + + TP_fast_assign( + struct iwm_umac_wifi_out_hdr *hdr = + (struct iwm_umac_wifi_out_hdr *)buf; + + IWM_ASSIGN; + __entry->eot = GET_VAL32(hdr->hw_hdr.cmd, UMAC_HDI_OUT_CMD_EOT); + __entry->ra_tid = GET_VAL32(hdr->hw_hdr.meta_data, UMAC_HDI_OUT_RATID); + __entry->credit_group = GET_VAL32(hdr->hw_hdr.meta_data, UMAC_HDI_OUT_CREDIT_GRP); + __entry->color = GET_VAL32(hdr->sw_hdr.meta_data, UMAC_FW_CMD_TX_STA_COLOR); + __entry->seq = __le16_to_cpu(hdr->sw_hdr.cmd.seq_num); + __entry->npkt = 1; + __entry->bytes = len; + + if (!__entry->eot) { + int count; + u8 *ptr = buf; + + __entry->npkt = 0; + while (ptr < buf + len) { + count = GET_VAL32(hdr->sw_hdr.meta_data, + UMAC_FW_CMD_BYTE_COUNT); + ptr += ALIGN(sizeof(*hdr) + count, 16); + hdr = (struct iwm_umac_wifi_out_hdr *)ptr; + __entry->npkt++; + } + } + ), + + TP_printk( + IWM_PR_FMT " Tx %spacket: eot %d, seq 0x%x, sta_color 0x%x, " + "ra_tid 0x%x, credit_group 0x%x, embedded_packets %d, %d bytes", + IWM_PR_ARG, !__entry->eot ? "concatenated " : "", + __entry->eot, __entry->seq, __entry->color, __entry->ra_tid, + __entry->credit_group, __entry->npkt, __entry->bytes + ) +); + +TRACE_EVENT(iwm_rx_nonwifi_cmd, + TP_PROTO(struct iwm_priv *iwm, void *buf, int len), + + TP_ARGS(iwm, buf, len), + + TP_STRUCT__entry( + IWM_ENTRY + __field(u8, opcode) + __field(u16, seq) + __field(u32, len) + ), + + TP_fast_assign( + struct iwm_udma_in_hdr *hdr = buf; + + IWM_ASSIGN; + __entry->opcode = GET_VAL32(hdr->cmd, UDMA_HDI_IN_NW_CMD_OPCODE); + __entry->seq = GET_VAL32(hdr->cmd, UDMA_HDI_IN_CMD_NON_WIFI_HW_SEQ_NUM); + __entry->len = len; + ), + + TP_printk( + IWM_PR_FMT " Rx TARGET RESP: opcode 0x%x, seq 0x%x, len 0x%x", + IWM_PR_ARG, __entry->opcode, __entry->seq, __entry->len + ) +); + +TRACE_EVENT(iwm_rx_wifi_cmd, + TP_PROTO(struct iwm_priv *iwm, struct iwm_umac_wifi_in_hdr *hdr), + + TP_ARGS(iwm, hdr), + + TP_STRUCT__entry( + IWM_ENTRY + __field(u8, cmd) + __field(u8, source) + __field(u16, seq) + __field(u32, count) + ), + + TP_fast_assign( + IWM_ASSIGN; + __entry->cmd = hdr->sw_hdr.cmd.cmd; + __entry->source = GET_VAL32(hdr->hw_hdr.cmd, UMAC_HDI_IN_CMD_SOURCE); + __entry->count = GET_VAL32(hdr->sw_hdr.meta_data, UMAC_FW_CMD_BYTE_COUNT); + __entry->seq = le16_to_cpu(hdr->sw_hdr.cmd.seq_num); + ), + + TP_printk( + IWM_PR_FMT " Rx %s RESP: cmd 0x%x, seq 0x%x, count 0x%x", + IWM_PR_ARG, __entry->source == UMAC_HDI_IN_SOURCE_FHRX ? "LMAC" : + __entry->source == UMAC_HDI_IN_SOURCE_FW ? "UMAC" : "UDMA", + __entry->cmd, __entry->seq, __entry->count + ) +); + +#define iwm_ticket_action_symbol \ + { IWM_RX_TICKET_DROP, "DROP" }, \ + { IWM_RX_TICKET_RELEASE, "RELEASE" }, \ + { IWM_RX_TICKET_SNIFFER, "SNIFFER" }, \ + { IWM_RX_TICKET_ENQUEUE, "ENQUEUE" } + +TRACE_EVENT(iwm_rx_ticket, + TP_PROTO(struct iwm_priv *iwm, void *buf, int len), + + TP_ARGS(iwm, buf, len), + + TP_STRUCT__entry( + IWM_ENTRY + __field(u8, action) + __field(u8, reason) + __field(u16, id) + __field(u16, flags) + ), + + TP_fast_assign( + struct iwm_rx_ticket *ticket = + ((struct iwm_umac_notif_rx_ticket *)buf)->tickets; + + IWM_ASSIGN; + __entry->id = le16_to_cpu(ticket->id); + __entry->action = le16_to_cpu(ticket->action); + __entry->flags = le16_to_cpu(ticket->flags); + __entry->reason = (__entry->flags & IWM_RX_TICKET_DROP_REASON_MSK) >> IWM_RX_TICKET_DROP_REASON_POS; + ), + + TP_printk( + IWM_PR_FMT " Rx ticket: id 0x%x, action %s, %s 0x%x%s", + IWM_PR_ARG, __entry->id, + __print_symbolic(__entry->action, iwm_ticket_action_symbol), + __entry->reason ? "reason" : "flags", + __entry->reason ? __entry->reason : __entry->flags, + __entry->flags & IWM_RX_TICKET_AMSDU_MSK ? ", AMSDU frame" : "" + ) +); + +TRACE_EVENT(iwm_rx_packet, + TP_PROTO(struct iwm_priv *iwm, void *buf, int len), + + TP_ARGS(iwm, buf, len), + + TP_STRUCT__entry( + IWM_ENTRY + __field(u8, source) + __field(u16, id) + __field(u32, len) + ), + + TP_fast_assign( + struct iwm_umac_wifi_in_hdr *hdr = buf; + + IWM_ASSIGN; + __entry->source = GET_VAL32(hdr->hw_hdr.cmd, UMAC_HDI_IN_CMD_SOURCE); + __entry->id = le16_to_cpu(hdr->sw_hdr.cmd.seq_num); + __entry->len = len - sizeof(*hdr); + ), + + TP_printk( + IWM_PR_FMT " Rx %s packet: id 0x%x, %d bytes", + IWM_PR_ARG, __entry->source == UMAC_HDI_IN_SOURCE_FHRX ? + "LMAC" : "UMAC", __entry->id, __entry->len + ) +); +#endif + +#undef TRACE_INCLUDE_PATH +#define TRACE_INCLUDE_PATH . +#undef TRACE_INCLUDE_FILE +#define TRACE_INCLUDE_FILE trace +#include diff --git a/trunk/drivers/net/wireless/iwmc3200wifi/tx.c b/trunk/drivers/net/wireless/iwmc3200wifi/tx.c new file mode 100644 index 000000000000..be98074c0608 --- /dev/null +++ b/trunk/drivers/net/wireless/iwmc3200wifi/tx.c @@ -0,0 +1,529 @@ +/* + * Intel Wireless Multicomm 3200 WiFi driver + * + * Copyright (C) 2009 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * + * Intel Corporation + * Samuel Ortiz + * Zhu Yi + * + */ + +/* + * iwm Tx theory of operation: + * + * 1) We receive a 802.3 frame from the stack + * 2) We convert it to a 802.11 frame [iwm_xmit_frame] + * 3) We queue it to its corresponding tx queue [iwm_xmit_frame] + * 4) We schedule the tx worker. There is one worker per tx + * queue. [iwm_xmit_frame] + * 5) The tx worker is scheduled + * 6) We go through every queued skb on the tx queue, and for each + * and every one of them: [iwm_tx_worker] + * a) We check if we have enough Tx credits (see below for a Tx + * credits description) for the frame length. [iwm_tx_worker] + * b) If we do, we aggregate the Tx frame into a UDMA one, by + * concatenating one REPLY_TX command per Tx frame. [iwm_tx_worker] + * c) When we run out of credits, or when we reach the maximum + * concatenation size, we actually send the concatenated UDMA + * frame. [iwm_tx_worker] + * + * When we run out of Tx credits, the skbs are filling the tx queue, + * and eventually we will stop the netdev queue. [iwm_tx_worker] + * The tx queue is emptied as we're getting new tx credits, by + * scheduling the tx_worker. [iwm_tx_credit_inc] + * The netdev queue is started again when we have enough tx credits, + * and when our tx queue has some reasonable amout of space available + * (i.e. half of the max size). [iwm_tx_worker] + */ + +#include +#include +#include +#include + +#include "iwm.h" +#include "debug.h" +#include "commands.h" +#include "hal.h" +#include "umac.h" +#include "bus.h" + +#define IWM_UMAC_PAGE_ALLOC_WRAP 0xffff + +#define BYTES_TO_PAGES(n) (1 + ((n) >> ilog2(IWM_UMAC_PAGE_SIZE)) - \ + (((n) & (IWM_UMAC_PAGE_SIZE - 1)) == 0)) + +#define pool_id_to_queue(id) ((id < IWM_TX_CMD_QUEUE) ? id : id - 1) +#define queue_to_pool_id(q) ((q < IWM_TX_CMD_QUEUE) ? q : q + 1) + +/* require to hold tx_credit lock */ +static int iwm_tx_credit_get(struct iwm_tx_credit *tx_credit, int id) +{ + struct pool_entry *pool = &tx_credit->pools[id]; + struct spool_entry *spool = &tx_credit->spools[pool->sid]; + int spool_pages; + + /* number of pages can be taken from spool by this pool */ + spool_pages = spool->max_pages - spool->alloc_pages + + max(pool->min_pages - pool->alloc_pages, 0); + + return min(pool->max_pages - pool->alloc_pages, spool_pages); +} + +static bool iwm_tx_credit_ok(struct iwm_priv *iwm, int id, int nb) +{ + u32 npages = BYTES_TO_PAGES(nb); + + if (npages <= iwm_tx_credit_get(&iwm->tx_credit, id)) + return 1; + + set_bit(id, &iwm->tx_credit.full_pools_map); + + IWM_DBG_TX(iwm, DBG, "LINK: stop txq[%d], available credit: %d\n", + pool_id_to_queue(id), + iwm_tx_credit_get(&iwm->tx_credit, id)); + + return 0; +} + +void iwm_tx_credit_inc(struct iwm_priv *iwm, int id, int total_freed_pages) +{ + struct pool_entry *pool; + struct spool_entry *spool; + int freed_pages; + int queue; + + BUG_ON(id >= IWM_MACS_OUT_GROUPS); + + pool = &iwm->tx_credit.pools[id]; + spool = &iwm->tx_credit.spools[pool->sid]; + + freed_pages = total_freed_pages - pool->total_freed_pages; + IWM_DBG_TX(iwm, DBG, "Free %d pages for pool[%d]\n", freed_pages, id); + + if (!freed_pages) { + IWM_DBG_TX(iwm, DBG, "No pages are freed by UMAC\n"); + return; + } else if (freed_pages < 0) + freed_pages += IWM_UMAC_PAGE_ALLOC_WRAP + 1; + + if (pool->alloc_pages > pool->min_pages) { + int spool_pages = pool->alloc_pages - pool->min_pages; + spool_pages = min(spool_pages, freed_pages); + spool->alloc_pages -= spool_pages; + } + + pool->alloc_pages -= freed_pages; + pool->total_freed_pages = total_freed_pages; + + IWM_DBG_TX(iwm, DBG, "Pool[%d] pages alloc: %d, total_freed: %d, " + "Spool[%d] pages alloc: %d\n", id, pool->alloc_pages, + pool->total_freed_pages, pool->sid, spool->alloc_pages); + + if (test_bit(id, &iwm->tx_credit.full_pools_map) && + (pool->alloc_pages < pool->max_pages / 2)) { + clear_bit(id, &iwm->tx_credit.full_pools_map); + + queue = pool_id_to_queue(id); + + IWM_DBG_TX(iwm, DBG, "LINK: start txq[%d], available " + "credit: %d\n", queue, + iwm_tx_credit_get(&iwm->tx_credit, id)); + queue_work(iwm->txq[queue].wq, &iwm->txq[queue].worker); + } +} + +static void iwm_tx_credit_dec(struct iwm_priv *iwm, int id, int alloc_pages) +{ + struct pool_entry *pool; + struct spool_entry *spool; + int spool_pages; + + IWM_DBG_TX(iwm, DBG, "Allocate %d pages for pool[%d]\n", + alloc_pages, id); + + BUG_ON(id >= IWM_MACS_OUT_GROUPS); + + pool = &iwm->tx_credit.pools[id]; + spool = &iwm->tx_credit.spools[pool->sid]; + + spool_pages = pool->alloc_pages + alloc_pages - pool->min_pages; + + if (pool->alloc_pages >= pool->min_pages) + spool->alloc_pages += alloc_pages; + else if (spool_pages > 0) + spool->alloc_pages += spool_pages; + + pool->alloc_pages += alloc_pages; + + IWM_DBG_TX(iwm, DBG, "Pool[%d] pages alloc: %d, total_freed: %d, " + "Spool[%d] pages alloc: %d\n", id, pool->alloc_pages, + pool->total_freed_pages, pool->sid, spool->alloc_pages); +} + +int iwm_tx_credit_alloc(struct iwm_priv *iwm, int id, int nb) +{ + u32 npages = BYTES_TO_PAGES(nb); + int ret = 0; + + spin_lock(&iwm->tx_credit.lock); + + if (!iwm_tx_credit_ok(iwm, id, nb)) { + IWM_DBG_TX(iwm, DBG, "No credit available for pool[%d]\n", id); + ret = -ENOSPC; + goto out; + } + + iwm_tx_credit_dec(iwm, id, npages); + + out: + spin_unlock(&iwm->tx_credit.lock); + return ret; +} + +/* + * Since we're on an SDIO or USB bus, we are not sharing memory + * for storing to be transmitted frames. The host needs to push + * them upstream. As a consequence there needs to be a way for + * the target to let us know if it can actually take more TX frames + * or not. This is what Tx credits are for. + * + * For each Tx HW queue, we have a Tx pool, and then we have one + * unique super pool (spool), which is actually a global pool of + * all the UMAC pages. + * For each Tx pool we have a min_pages, a max_pages fields, and a + * alloc_pages fields. The alloc_pages tracks the number of pages + * currently allocated from the tx pool. + * Here are the rules to check if given a tx frame we have enough + * tx credits for it: + * 1) We translate the frame length into a number of UMAC pages. + * Let's call them n_pages. + * 2) For the corresponding tx pool, we check if n_pages + + * pool->alloc_pages is higher than pool->min_pages. min_pages + * represent a set of pre-allocated pages on the tx pool. If + * that's the case, then we need to allocate those pages from + * the spool. We can do so until we reach spool->max_pages. + * 3) Each tx pool is not allowed to allocate more than pool->max_pages + * from the spool, so once we're over min_pages, we can allocate + * pages from the spool, but not more than max_pages. + * + * When the tx code path needs to send a tx frame, it checks first + * if it has enough tx credits, following those rules. [iwm_tx_credit_get] + * If it does, it then updates the pool and spool counters and + * then send the frame. [iwm_tx_credit_alloc and iwm_tx_credit_dec] + * On the other side, when the UMAC is done transmitting frames, it + * will send a credit update notification to the host. This is when + * the pool and spool counters gets to be decreased. [iwm_tx_credit_inc, + * called from rx.c:iwm_ntf_tx_credit_update] + * + */ +void iwm_tx_credit_init_pools(struct iwm_priv *iwm, + struct iwm_umac_notif_alive *alive) +{ + int i, sid, pool_pages; + + spin_lock(&iwm->tx_credit.lock); + + iwm->tx_credit.pool_nr = le16_to_cpu(alive->page_grp_count); + iwm->tx_credit.full_pools_map = 0; + memset(&iwm->tx_credit.spools[0], 0, sizeof(struct spool_entry)); + + IWM_DBG_TX(iwm, DBG, "Pools number is %d\n", iwm->tx_credit.pool_nr); + + for (i = 0; i < iwm->tx_credit.pool_nr; i++) { + __le32 page_grp_state = alive->page_grp_state[i]; + + iwm->tx_credit.pools[i].id = GET_VAL32(page_grp_state, + UMAC_ALIVE_PAGE_STS_GRP_NUM); + iwm->tx_credit.pools[i].sid = GET_VAL32(page_grp_state, + UMAC_ALIVE_PAGE_STS_SGRP_NUM); + iwm->tx_credit.pools[i].min_pages = GET_VAL32(page_grp_state, + UMAC_ALIVE_PAGE_STS_GRP_MIN_SIZE); + iwm->tx_credit.pools[i].max_pages = GET_VAL32(page_grp_state, + UMAC_ALIVE_PAGE_STS_GRP_MAX_SIZE); + iwm->tx_credit.pools[i].alloc_pages = 0; + iwm->tx_credit.pools[i].total_freed_pages = 0; + + sid = iwm->tx_credit.pools[i].sid; + pool_pages = iwm->tx_credit.pools[i].min_pages; + + if (iwm->tx_credit.spools[sid].max_pages == 0) { + iwm->tx_credit.spools[sid].id = sid; + iwm->tx_credit.spools[sid].max_pages = + GET_VAL32(page_grp_state, + UMAC_ALIVE_PAGE_STS_SGRP_MAX_SIZE); + iwm->tx_credit.spools[sid].alloc_pages = 0; + } + + iwm->tx_credit.spools[sid].alloc_pages += pool_pages; + + IWM_DBG_TX(iwm, DBG, "Pool idx: %d, id: %d, sid: %d, capacity " + "min: %d, max: %d, pool alloc: %d, total_free: %d, " + "super poll alloc: %d\n", + i, iwm->tx_credit.pools[i].id, + iwm->tx_credit.pools[i].sid, + iwm->tx_credit.pools[i].min_pages, + iwm->tx_credit.pools[i].max_pages, + iwm->tx_credit.pools[i].alloc_pages, + iwm->tx_credit.pools[i].total_freed_pages, + iwm->tx_credit.spools[sid].alloc_pages); + } + + spin_unlock(&iwm->tx_credit.lock); +} + +#define IWM_UDMA_HDR_LEN sizeof(struct iwm_umac_wifi_out_hdr) + +static __le16 iwm_tx_build_packet(struct iwm_priv *iwm, struct sk_buff *skb, + int pool_id, u8 *buf) +{ + struct iwm_umac_wifi_out_hdr *hdr = (struct iwm_umac_wifi_out_hdr *)buf; + struct iwm_udma_wifi_cmd udma_cmd; + struct iwm_umac_cmd umac_cmd; + struct iwm_tx_info *tx_info = skb_to_tx_info(skb); + + udma_cmd.count = cpu_to_le16(skb->len + + sizeof(struct iwm_umac_fw_cmd_hdr)); + /* set EOP to 0 here. iwm_udma_wifi_hdr_set_eop() will be + * called later to set EOP for the last packet. */ + udma_cmd.eop = 0; + udma_cmd.credit_group = pool_id; + udma_cmd.ra_tid = tx_info->sta << 4 | tx_info->tid; + udma_cmd.lmac_offset = 0; + + umac_cmd.id = REPLY_TX; + umac_cmd.count = cpu_to_le16(skb->len); + umac_cmd.color = tx_info->color; + umac_cmd.resp = 0; + umac_cmd.seq_num = cpu_to_le16(iwm_alloc_wifi_cmd_seq(iwm)); + + iwm_build_udma_wifi_hdr(iwm, &hdr->hw_hdr, &udma_cmd); + iwm_build_umac_hdr(iwm, &hdr->sw_hdr, &umac_cmd); + + memcpy(buf + sizeof(*hdr), skb->data, skb->len); + + return umac_cmd.seq_num; +} + +static int iwm_tx_send_concat_packets(struct iwm_priv *iwm, + struct iwm_tx_queue *txq) +{ + int ret; + + if (!txq->concat_count) + return 0; + + IWM_DBG_TX(iwm, DBG, "Send concatenated Tx: queue %d, %d bytes\n", + txq->id, txq->concat_count); + + /* mark EOP for the last packet */ + iwm_udma_wifi_hdr_set_eop(iwm, txq->concat_ptr, 1); + + trace_iwm_tx_packets(iwm, txq->concat_buf, txq->concat_count); + ret = iwm_bus_send_chunk(iwm, txq->concat_buf, txq->concat_count); + + txq->concat_count = 0; + txq->concat_ptr = txq->concat_buf; + + return ret; +} + +void iwm_tx_worker(struct work_struct *work) +{ + struct iwm_priv *iwm; + struct iwm_tx_info *tx_info = NULL; + struct sk_buff *skb; + struct iwm_tx_queue *txq; + struct iwm_sta_info *sta_info; + struct iwm_tid_info *tid_info; + int cmdlen, ret, pool_id; + + txq = container_of(work, struct iwm_tx_queue, worker); + iwm = container_of(txq, struct iwm_priv, txq[txq->id]); + + pool_id = queue_to_pool_id(txq->id); + + while (!test_bit(pool_id, &iwm->tx_credit.full_pools_map) && + !skb_queue_empty(&txq->queue)) { + + spin_lock_bh(&txq->lock); + skb = skb_dequeue(&txq->queue); + spin_unlock_bh(&txq->lock); + + tx_info = skb_to_tx_info(skb); + sta_info = &iwm->sta_table[tx_info->sta]; + if (!sta_info->valid) { + IWM_ERR(iwm, "Trying to send a frame to unknown STA\n"); + kfree_skb(skb); + continue; + } + + tid_info = &sta_info->tid_info[tx_info->tid]; + + mutex_lock(&tid_info->mutex); + + /* + * If the RAxTID is stopped, we queue the skb to the stopped + * queue. + * Whenever we'll get a UMAC notification to resume the tx flow + * for this RAxTID, we'll merge back the stopped queue into the + * regular queue. See iwm_ntf_stop_resume_tx() from rx.c. + */ + if (tid_info->stopped) { + IWM_DBG_TX(iwm, DBG, "%dx%d stopped\n", + tx_info->sta, tx_info->tid); + spin_lock_bh(&txq->lock); + skb_queue_tail(&txq->stopped_queue, skb); + spin_unlock_bh(&txq->lock); + + mutex_unlock(&tid_info->mutex); + continue; + } + + cmdlen = IWM_UDMA_HDR_LEN + skb->len; + + IWM_DBG_TX(iwm, DBG, "Tx frame on queue %d: skb: 0x%p, sta: " + "%d, color: %d\n", txq->id, skb, tx_info->sta, + tx_info->color); + + if (txq->concat_count + cmdlen > IWM_HAL_CONCATENATE_BUF_SIZE) + iwm_tx_send_concat_packets(iwm, txq); + + ret = iwm_tx_credit_alloc(iwm, pool_id, cmdlen); + if (ret) { + IWM_DBG_TX(iwm, DBG, "not enough tx_credit for queue " + "%d, Tx worker stopped\n", txq->id); + spin_lock_bh(&txq->lock); + skb_queue_head(&txq->queue, skb); + spin_unlock_bh(&txq->lock); + + mutex_unlock(&tid_info->mutex); + break; + } + + txq->concat_ptr = txq->concat_buf + txq->concat_count; + tid_info->last_seq_num = + iwm_tx_build_packet(iwm, skb, pool_id, txq->concat_ptr); + txq->concat_count += ALIGN(cmdlen, 16); + + mutex_unlock(&tid_info->mutex); + + kfree_skb(skb); + } + + iwm_tx_send_concat_packets(iwm, txq); + + if (__netif_subqueue_stopped(iwm_to_ndev(iwm), txq->id) && + !test_bit(pool_id, &iwm->tx_credit.full_pools_map) && + (skb_queue_len(&txq->queue) < IWM_TX_LIST_SIZE / 2)) { + IWM_DBG_TX(iwm, DBG, "LINK: start netif_subqueue[%d]", txq->id); + netif_wake_subqueue(iwm_to_ndev(iwm), txq->id); + } +} + +int iwm_xmit_frame(struct sk_buff *skb, struct net_device *netdev) +{ + struct iwm_priv *iwm = ndev_to_iwm(netdev); + struct wireless_dev *wdev = iwm_to_wdev(iwm); + struct iwm_tx_info *tx_info; + struct iwm_tx_queue *txq; + struct iwm_sta_info *sta_info; + u8 *dst_addr, sta_id; + u16 queue; + int ret; + + + if (!test_bit(IWM_STATUS_ASSOCIATED, &iwm->status)) { + IWM_DBG_TX(iwm, DBG, "LINK: stop netif_all_queues: " + "not associated\n"); + netif_tx_stop_all_queues(netdev); + goto drop; + } + + queue = skb_get_queue_mapping(skb); + BUG_ON(queue >= IWM_TX_DATA_QUEUES); /* no iPAN yet */ + + txq = &iwm->txq[queue]; + + /* No free space for Tx, tx_worker is too slow */ + if ((skb_queue_len(&txq->queue) > IWM_TX_LIST_SIZE) || + (skb_queue_len(&txq->stopped_queue) > IWM_TX_LIST_SIZE)) { + IWM_DBG_TX(iwm, DBG, "LINK: stop netif_subqueue[%d]\n", queue); + netif_stop_subqueue(netdev, queue); + return NETDEV_TX_BUSY; + } + + ret = ieee80211_data_from_8023(skb, netdev->dev_addr, wdev->iftype, + iwm->bssid, 0); + if (ret) { + IWM_ERR(iwm, "build wifi header failed\n"); + goto drop; + } + + dst_addr = ((struct ieee80211_hdr *)(skb->data))->addr1; + + for (sta_id = 0; sta_id < IWM_STA_TABLE_NUM; sta_id++) { + sta_info = &iwm->sta_table[sta_id]; + if (sta_info->valid && + !memcmp(dst_addr, sta_info->addr, ETH_ALEN)) + break; + } + + if (sta_id == IWM_STA_TABLE_NUM) { + IWM_ERR(iwm, "STA %pM not found in sta_table, Tx ignored\n", + dst_addr); + goto drop; + } + + tx_info = skb_to_tx_info(skb); + tx_info->sta = sta_id; + tx_info->color = sta_info->color; + /* UMAC uses TID 8 (vs. 0) for non QoS packets */ + if (sta_info->qos) + tx_info->tid = skb->priority; + else + tx_info->tid = IWM_UMAC_MGMT_TID; + + spin_lock_bh(&iwm->txq[queue].lock); + skb_queue_tail(&iwm->txq[queue].queue, skb); + spin_unlock_bh(&iwm->txq[queue].lock); + + queue_work(iwm->txq[queue].wq, &iwm->txq[queue].worker); + + netdev->stats.tx_packets++; + netdev->stats.tx_bytes += skb->len; + return NETDEV_TX_OK; + + drop: + netdev->stats.tx_dropped++; + dev_kfree_skb_any(skb); + return NETDEV_TX_OK; +} diff --git a/trunk/drivers/net/wireless/iwmc3200wifi/umac.h b/trunk/drivers/net/wireless/iwmc3200wifi/umac.h new file mode 100644 index 000000000000..4a137d334a42 --- /dev/null +++ b/trunk/drivers/net/wireless/iwmc3200wifi/umac.h @@ -0,0 +1,789 @@ +/* + * Intel Wireless Multicomm 3200 WiFi driver + * + * Copyright (C) 2009 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * + * Intel Corporation + * Samuel Ortiz + * Zhu Yi + * + */ + +#ifndef __IWM_UMAC_H__ +#define __IWM_UMAC_H__ + +struct iwm_udma_in_hdr { + __le32 cmd; + __le32 size; +} __packed; + +struct iwm_udma_out_nonwifi_hdr { + __le32 cmd; + __le32 addr; + __le32 op1_sz; + __le32 op2; +} __packed; + +struct iwm_udma_out_wifi_hdr { + __le32 cmd; + __le32 meta_data; +} __packed; + +/* Sequence numbering */ +#define UMAC_WIFI_SEQ_NUM_BASE 1 +#define UMAC_WIFI_SEQ_NUM_MAX 0x4000 +#define UMAC_NONWIFI_SEQ_NUM_BASE 1 +#define UMAC_NONWIFI_SEQ_NUM_MAX 0x10 + +/* MAC address address */ +#define WICO_MAC_ADDRESS_ADDR 0x604008F8 + +/* RA / TID */ +#define UMAC_HDI_ACT_TBL_IDX_TID_POS 0 +#define UMAC_HDI_ACT_TBL_IDX_TID_SEED 0xF + +#define UMAC_HDI_ACT_TBL_IDX_RA_POS 4 +#define UMAC_HDI_ACT_TBL_IDX_RA_SEED 0xF + +#define UMAC_HDI_ACT_TBL_IDX_RA_UMAC 0xF +#define UMAC_HDI_ACT_TBL_IDX_TID_UMAC 0x9 +#define UMAC_HDI_ACT_TBL_IDX_TID_LMAC 0xA + +#define UMAC_HDI_ACT_TBL_IDX_HOST_CMD \ + ((UMAC_HDI_ACT_TBL_IDX_RA_UMAC << UMAC_HDI_ACT_TBL_IDX_RA_POS) |\ + (UMAC_HDI_ACT_TBL_IDX_TID_UMAC << UMAC_HDI_ACT_TBL_IDX_TID_POS)) +#define UMAC_HDI_ACT_TBL_IDX_UMAC_CMD \ + ((UMAC_HDI_ACT_TBL_IDX_RA_UMAC << UMAC_HDI_ACT_TBL_IDX_RA_POS) |\ + (UMAC_HDI_ACT_TBL_IDX_TID_LMAC << UMAC_HDI_ACT_TBL_IDX_TID_POS)) + +/* STA ID and color */ +#define STA_ID_SEED (0x0f) +#define STA_ID_POS (0) +#define STA_ID_MSK (STA_ID_SEED << STA_ID_POS) + +#define STA_COLOR_SEED (0x7) +#define STA_COLOR_POS (4) +#define STA_COLOR_MSK (STA_COLOR_SEED << STA_COLOR_POS) + +#define STA_ID_N_COLOR_COLOR(id_n_color) \ + (((id_n_color) & STA_COLOR_MSK) >> STA_COLOR_POS) +#define STA_ID_N_COLOR_ID(id_n_color) \ + (((id_n_color) & STA_ID_MSK) >> STA_ID_POS) + +/* iwm_umac_notif_alive.page_grp_state Group number -- bits [3:0] */ +#define UMAC_ALIVE_PAGE_STS_GRP_NUM_POS 0 +#define UMAC_ALIVE_PAGE_STS_GRP_NUM_SEED 0xF + +/* iwm_umac_notif_alive.page_grp_state Super group number -- bits [7:4] */ +#define UMAC_ALIVE_PAGE_STS_SGRP_NUM_POS 4 +#define UMAC_ALIVE_PAGE_STS_SGRP_NUM_SEED 0xF + +/* iwm_umac_notif_alive.page_grp_state Group min size -- bits [15:8] */ +#define UMAC_ALIVE_PAGE_STS_GRP_MIN_SIZE_POS 8 +#define UMAC_ALIVE_PAGE_STS_GRP_MIN_SIZE_SEED 0xFF + +/* iwm_umac_notif_alive.page_grp_state Group max size -- bits [23:16] */ +#define UMAC_ALIVE_PAGE_STS_GRP_MAX_SIZE_POS 16 +#define UMAC_ALIVE_PAGE_STS_GRP_MAX_SIZE_SEED 0xFF + +/* iwm_umac_notif_alive.page_grp_state Super group max size -- bits [31:24] */ +#define UMAC_ALIVE_PAGE_STS_SGRP_MAX_SIZE_POS 24 +#define UMAC_ALIVE_PAGE_STS_SGRP_MAX_SIZE_SEED 0xFF + +/* Barkers */ +#define UMAC_REBOOT_BARKER 0xdeadbeef +#define UMAC_ACK_BARKER 0xfeedbabe +#define UMAC_PAD_TERMINAL 0xadadadad + +/* UMAC JMP address */ +#define UMAC_MU_FW_INST_DATA_12_ADDR 0xBF0000 + +/* iwm_umac_hdi_out_hdr.cmd OP code -- bits [3:0] */ +#define UMAC_HDI_OUT_CMD_OPCODE_POS 0 +#define UMAC_HDI_OUT_CMD_OPCODE_SEED 0xF + +/* iwm_umac_hdi_out_hdr.cmd End-Of-Transfer -- bits [10:10] */ +#define UMAC_HDI_OUT_CMD_EOT_POS 10 +#define UMAC_HDI_OUT_CMD_EOT_SEED 0x1 + +/* iwm_umac_hdi_out_hdr.cmd UTFD only usage -- bits [11:11] */ +#define UMAC_HDI_OUT_CMD_UTFD_ONLY_POS 11 +#define UMAC_HDI_OUT_CMD_UTFD_ONLY_SEED 0x1 + +/* iwm_umac_hdi_out_hdr.cmd Non-WiFi HW sequence number -- bits [12:15] */ +#define UDMA_HDI_OUT_CMD_NON_WIFI_HW_SEQ_NUM_POS 12 +#define UDMA_HDI_OUT_CMD_NON_WIFI_HW_SEQ_NUM_SEED 0xF + +/* iwm_umac_hdi_out_hdr.cmd Signature -- bits [31:16] */ +#define UMAC_HDI_OUT_CMD_SIGNATURE_POS 16 +#define UMAC_HDI_OUT_CMD_SIGNATURE_SEED 0xFFFF + +/* iwm_umac_hdi_out_hdr.meta_data Byte count -- bits [11:0] */ +#define UMAC_HDI_OUT_BYTE_COUNT_POS 0 +#define UMAC_HDI_OUT_BYTE_COUNT_SEED 0xFFF + +/* iwm_umac_hdi_out_hdr.meta_data Credit group -- bits [15:12] */ +#define UMAC_HDI_OUT_CREDIT_GRP_POS 12 +#define UMAC_HDI_OUT_CREDIT_GRP_SEED 0xF + +/* iwm_umac_hdi_out_hdr.meta_data RA/TID -- bits [23:16] */ +#define UMAC_HDI_OUT_RATID_POS 16 +#define UMAC_HDI_OUT_RATID_SEED 0xFF + +/* iwm_umac_hdi_out_hdr.meta_data LMAC offset -- bits [31:24] */ +#define UMAC_HDI_OUT_LMAC_OFFSET_POS 24 +#define UMAC_HDI_OUT_LMAC_OFFSET_SEED 0xFF + +/* Signature */ +#define UMAC_HDI_OUT_SIGNATURE 0xCBBC + +/* buffer alignment */ +#define UMAC_HDI_BUF_ALIGN_MSK 0xF + +/* iwm_umac_hdi_in_hdr.cmd OP code -- bits [3:0] */ +#define UMAC_HDI_IN_CMD_OPCODE_POS 0 +#define UMAC_HDI_IN_CMD_OPCODE_SEED 0xF + +/* iwm_umac_hdi_in_hdr.cmd Non-WiFi API response -- bits [6:4] */ +#define UMAC_HDI_IN_CMD_NON_WIFI_RESP_POS 4 +#define UMAC_HDI_IN_CMD_NON_WIFI_RESP_SEED 0x7 + +/* iwm_umac_hdi_in_hdr.cmd WiFi API source -- bits [5:4] */ +#define UMAC_HDI_IN_CMD_SOURCE_POS 4 +#define UMAC_HDI_IN_CMD_SOURCE_SEED 0x3 + +/* iwm_umac_hdi_in_hdr.cmd WiFi API EOT -- bits [6:6] */ +#define UMAC_HDI_IN_CMD_EOT_POS 6 +#define UMAC_HDI_IN_CMD_EOT_SEED 0x1 + +/* iwm_umac_hdi_in_hdr.cmd timestamp present -- bits [7:7] */ +#define UMAC_HDI_IN_CMD_TIME_STAMP_PRESENT_POS 7 +#define UMAC_HDI_IN_CMD_TIME_STAMP_PRESENT_SEED 0x1 + +/* iwm_umac_hdi_in_hdr.cmd WiFi Non-last AMSDU -- bits [8:8] */ +#define UMAC_HDI_IN_CMD_NON_LAST_AMSDU_POS 8 +#define UMAC_HDI_IN_CMD_NON_LAST_AMSDU_SEED 0x1 + +/* iwm_umac_hdi_in_hdr.cmd WiFi HW sequence number -- bits [31:9] */ +#define UMAC_HDI_IN_CMD_HW_SEQ_NUM_POS 9 +#define UMAC_HDI_IN_CMD_HW_SEQ_NUM_SEED 0x7FFFFF + +/* iwm_umac_hdi_in_hdr.cmd Non-WiFi HW sequence number -- bits [12:15] */ +#define UDMA_HDI_IN_CMD_NON_WIFI_HW_SEQ_NUM_POS 12 +#define UDMA_HDI_IN_CMD_NON_WIFI_HW_SEQ_NUM_SEED 0xF + +/* iwm_umac_hdi_in_hdr.cmd Non-WiFi HW signature -- bits [16:31] */ +#define UDMA_HDI_IN_CMD_NON_WIFI_HW_SIG_POS 16 +#define UDMA_HDI_IN_CMD_NON_WIFI_HW_SIG_SEED 0xFFFF + +/* Fixed Non-WiFi signature */ +#define UDMA_HDI_IN_CMD_NON_WIFI_HW_SIG 0xCBBC + +/* IN NTFY op-codes */ +#define UMAC_NOTIFY_OPCODE_ALIVE 0xA1 +#define UMAC_NOTIFY_OPCODE_INIT_COMPLETE 0xA2 +#define UMAC_NOTIFY_OPCODE_WIFI_CORE_STATUS 0xA3 +#define UMAC_NOTIFY_OPCODE_ERROR 0xA4 +#define UMAC_NOTIFY_OPCODE_DEBUG 0xA5 +#define UMAC_NOTIFY_OPCODE_WIFI_IF_WRAPPER 0xB0 +#define UMAC_NOTIFY_OPCODE_STATS 0xB1 +#define UMAC_NOTIFY_OPCODE_PAGE_DEALLOC 0xB3 +#define UMAC_NOTIFY_OPCODE_RX_TICKET 0xB4 +#define UMAC_NOTIFY_OPCODE_MAX (UMAC_NOTIFY_OPCODE_RX_TICKET -\ + UMAC_NOTIFY_OPCODE_ALIVE + 1) +#define UMAC_NOTIFY_OPCODE_FIRST (UMAC_NOTIFY_OPCODE_ALIVE) + +/* HDI OUT OP CODE */ +#define UMAC_HDI_OUT_OPCODE_PING 0x0 +#define UMAC_HDI_OUT_OPCODE_READ 0x1 +#define UMAC_HDI_OUT_OPCODE_WRITE 0x2 +#define UMAC_HDI_OUT_OPCODE_JUMP 0x3 +#define UMAC_HDI_OUT_OPCODE_REBOOT 0x4 +#define UMAC_HDI_OUT_OPCODE_WRITE_PERSISTENT 0x5 +#define UMAC_HDI_OUT_OPCODE_READ_PERSISTENT 0x6 +#define UMAC_HDI_OUT_OPCODE_READ_MODIFY_WRITE 0x7 +/* #define UMAC_HDI_OUT_OPCODE_RESERVED 0x8..0xA */ +#define UMAC_HDI_OUT_OPCODE_WRITE_AUX_REG 0xB +#define UMAC_HDI_OUT_OPCODE_WIFI 0xF + +/* HDI IN OP CODE -- Non WiFi*/ +#define UMAC_HDI_IN_OPCODE_PING 0x0 +#define UMAC_HDI_IN_OPCODE_READ 0x1 +#define UMAC_HDI_IN_OPCODE_WRITE 0x2 +#define UMAC_HDI_IN_OPCODE_WRITE_PERSISTENT 0x5 +#define UMAC_HDI_IN_OPCODE_READ_PERSISTENT 0x6 +#define UMAC_HDI_IN_OPCODE_READ_MODIFY_WRITE 0x7 +#define UMAC_HDI_IN_OPCODE_EP_MGMT 0x8 +#define UMAC_HDI_IN_OPCODE_CREDIT_CHANGE 0x9 +#define UMAC_HDI_IN_OPCODE_CTRL_DATABASE 0xA +#define UMAC_HDI_IN_OPCODE_WRITE_AUX_REG 0xB +#define UMAC_HDI_IN_OPCODE_NONWIFI_MAX \ + (UMAC_HDI_IN_OPCODE_WRITE_AUX_REG + 1) +#define UMAC_HDI_IN_OPCODE_WIFI 0xF + +/* HDI IN SOURCE */ +#define UMAC_HDI_IN_SOURCE_FHRX 0x0 +#define UMAC_HDI_IN_SOURCE_UDMA 0x1 +#define UMAC_HDI_IN_SOURCE_FW 0x2 +#define UMAC_HDI_IN_SOURCE_RESERVED 0x3 + +/* OUT CMD op-codes */ +#define UMAC_CMD_OPCODE_ECHO 0x01 +#define UMAC_CMD_OPCODE_HALT 0x02 +#define UMAC_CMD_OPCODE_RESET 0x03 +#define UMAC_CMD_OPCODE_BULK_EP_INACT_TIMEOUT 0x09 +#define UMAC_CMD_OPCODE_URB_CANCEL_ACK 0x0A +#define UMAC_CMD_OPCODE_DCACHE_FLUSH 0x0B +#define UMAC_CMD_OPCODE_EEPROM_PROXY 0x0C +#define UMAC_CMD_OPCODE_TX_ECHO 0x0D +#define UMAC_CMD_OPCODE_DBG_MON 0x0E +#define UMAC_CMD_OPCODE_INTERNAL_TX 0x0F +#define UMAC_CMD_OPCODE_SET_PARAM_FIX 0x10 +#define UMAC_CMD_OPCODE_SET_PARAM_VAR 0x11 +#define UMAC_CMD_OPCODE_GET_PARAM 0x12 +#define UMAC_CMD_OPCODE_DBG_EVENT_WRAPPER 0x13 +#define UMAC_CMD_OPCODE_TARGET 0x14 +#define UMAC_CMD_OPCODE_STATISTIC_REQUEST 0x15 +#define UMAC_CMD_OPCODE_GET_CHAN_INFO_LIST 0x16 +#define UMAC_CMD_OPCODE_SET_PARAM_LIST 0x17 +#define UMAC_CMD_OPCODE_GET_PARAM_LIST 0x18 +#define UMAC_CMD_OPCODE_STOP_RESUME_STA_TX 0x19 +#define UMAC_CMD_OPCODE_TEST_BLOCK_ACK 0x1A + +#define UMAC_CMD_OPCODE_BASE_WRAPPER 0xFA +#define UMAC_CMD_OPCODE_LMAC_WRAPPER 0xFB +#define UMAC_CMD_OPCODE_HW_TEST_WRAPPER 0xFC +#define UMAC_CMD_OPCODE_WIFI_IF_WRAPPER 0xFD +#define UMAC_CMD_OPCODE_WIFI_WRAPPER 0xFE +#define UMAC_CMD_OPCODE_WIFI_PASS_THROUGH 0xFF + +/* UMAC WiFi interface op-codes */ +#define UMAC_WIFI_IF_CMD_SET_PROFILE 0x11 +#define UMAC_WIFI_IF_CMD_INVALIDATE_PROFILE 0x12 +#define UMAC_WIFI_IF_CMD_SET_EXCLUDE_LIST 0x13 +#define UMAC_WIFI_IF_CMD_SCAN_REQUEST 0x14 +#define UMAC_WIFI_IF_CMD_SCAN_CONFIG 0x15 +#define UMAC_WIFI_IF_CMD_ADD_WEP40_KEY 0x16 +#define UMAC_WIFI_IF_CMD_ADD_WEP104_KEY 0x17 +#define UMAC_WIFI_IF_CMD_ADD_TKIP_KEY 0x18 +#define UMAC_WIFI_IF_CMD_ADD_CCMP_KEY 0x19 +#define UMAC_WIFI_IF_CMD_REMOVE_KEY 0x1A +#define UMAC_WIFI_IF_CMD_GLOBAL_TX_KEY_ID 0x1B +#define UMAC_WIFI_IF_CMD_SET_HOST_EXTENDED_IE 0x1C +#define UMAC_WIFI_IF_CMD_GET_SUPPORTED_CHANNELS 0x1E +#define UMAC_WIFI_IF_CMD_PMKID_UPDATE 0x1F +#define UMAC_WIFI_IF_CMD_TX_PWR_TRIGGER 0x20 + +/* UMAC WiFi interface ports */ +#define UMAC_WIFI_IF_FLG_PORT_DEF 0x00 +#define UMAC_WIFI_IF_FLG_PORT_PAN 0x01 +#define UMAC_WIFI_IF_FLG_PORT_PAN_INVALID WIFI_IF_FLG_PORT_DEF + +/* UMAC WiFi interface actions */ +#define UMAC_WIFI_IF_FLG_ACT_GET 0x10 +#define UMAC_WIFI_IF_FLG_ACT_SET 0x20 + +/* iwm_umac_fw_cmd_hdr.meta_data byte count -- bits [11:0] */ +#define UMAC_FW_CMD_BYTE_COUNT_POS 0 +#define UMAC_FW_CMD_BYTE_COUNT_SEED 0xFFF + +/* iwm_umac_fw_cmd_hdr.meta_data status -- bits [15:12] */ +#define UMAC_FW_CMD_STATUS_POS 12 +#define UMAC_FW_CMD_STATUS_SEED 0xF + +/* iwm_umac_fw_cmd_hdr.meta_data full TX command by Driver -- bits [16:16] */ +#define UMAC_FW_CMD_TX_DRV_FULL_CMD_POS 16 +#define UMAC_FW_CMD_TX_DRV_FULL_CMD_SEED 0x1 + +/* iwm_umac_fw_cmd_hdr.meta_data TX command by FW -- bits [17:17] */ +#define UMAC_FW_CMD_TX_FW_CMD_POS 17 +#define UMAC_FW_CMD_TX_FW_CMD_SEED 0x1 + +/* iwm_umac_fw_cmd_hdr.meta_data TX plaintext mode -- bits [18:18] */ +#define UMAC_FW_CMD_TX_PLAINTEXT_POS 18 +#define UMAC_FW_CMD_TX_PLAINTEXT_SEED 0x1 + +/* iwm_umac_fw_cmd_hdr.meta_data STA color -- bits [22:20] */ +#define UMAC_FW_CMD_TX_STA_COLOR_POS 20 +#define UMAC_FW_CMD_TX_STA_COLOR_SEED 0x7 + +/* iwm_umac_fw_cmd_hdr.meta_data TX life time (TU) -- bits [31:24] */ +#define UMAC_FW_CMD_TX_LIFETIME_TU_POS 24 +#define UMAC_FW_CMD_TX_LIFETIME_TU_SEED 0xFF + +/* iwm_dev_cmd_hdr.flags Response required -- bits [5:5] */ +#define UMAC_DEV_CMD_FLAGS_RESP_REQ_POS 5 +#define UMAC_DEV_CMD_FLAGS_RESP_REQ_SEED 0x1 + +/* iwm_dev_cmd_hdr.flags Aborted command -- bits [6:6] */ +#define UMAC_DEV_CMD_FLAGS_ABORT_POS 6 +#define UMAC_DEV_CMD_FLAGS_ABORT_SEED 0x1 + +/* iwm_dev_cmd_hdr.flags Internal command -- bits [7:7] */ +#define DEV_CMD_FLAGS_FLD_INTERNAL_POS 7 +#define DEV_CMD_FLAGS_FLD_INTERNAL_SEED 0x1 + +/* Rx */ +/* Rx actions */ +#define IWM_RX_TICKET_DROP 0x0 +#define IWM_RX_TICKET_RELEASE 0x1 +#define IWM_RX_TICKET_SNIFFER 0x2 +#define IWM_RX_TICKET_ENQUEUE 0x3 + +/* Rx flags */ +#define IWM_RX_TICKET_PAD_SIZE_MSK 0x2 +#define IWM_RX_TICKET_SPECIAL_SNAP_MSK 0x4 +#define IWM_RX_TICKET_AMSDU_MSK 0x8 +#define IWM_RX_TICKET_DROP_REASON_POS 4 +#define IWM_RX_TICKET_DROP_REASON_MSK (0x1F << IWM_RX_TICKET_DROP_REASON_POS) + +#define IWM_RX_DROP_NO_DROP 0x0 +#define IWM_RX_DROP_BAD_CRC 0x1 +/* L2P no address match */ +#define IWM_RX_DROP_LMAC_ADDR_FILTER 0x2 +/* Multicast address not in list */ +#define IWM_RX_DROP_MCAST_ADDR_FILTER 0x3 +/* Control frames are not sent to the driver */ +#define IWM_RX_DROP_CTL_FRAME 0x4 +/* Our frame is back */ +#define IWM_RX_DROP_OUR_TX 0x5 +/* Association class filtering */ +#define IWM_RX_DROP_CLASS_FILTER 0x6 +/* Duplicated frame */ +#define IWM_RX_DROP_DUPLICATE_FILTER 0x7 +/* Decryption error */ +#define IWM_RX_DROP_SEC_ERR 0x8 +/* Unencrypted frame while encryption is on */ +#define IWM_RX_DROP_SEC_NO_ENCRYPTION 0x9 +/* Replay check failure */ +#define IWM_RX_DROP_SEC_REPLAY_ERR 0xa +/* uCode and FW key color mismatch, check before replay */ +#define IWM_RX_DROP_SEC_KEY_COLOR_MISMATCH 0xb +#define IWM_RX_DROP_SEC_TKIP_COUNTER_MEASURE 0xc +/* No fragmentations Db is found */ +#define IWM_RX_DROP_FRAG_NO_RESOURCE 0xd +/* Fragmention Db has seqCtl mismatch Vs. non-1st frag */ +#define IWM_RX_DROP_FRAG_ERR 0xe +#define IWM_RX_DROP_FRAG_LOST 0xf +#define IWM_RX_DROP_FRAG_COMPLETE 0x10 +/* Should be handled by UMAC */ +#define IWM_RX_DROP_MANAGEMENT 0x11 +/* STA not found by UMAC */ +#define IWM_RX_DROP_NO_STATION 0x12 +/* NULL or QoS NULL */ +#define IWM_RX_DROP_NULL_DATA 0x13 +#define IWM_RX_DROP_BA_REORDER_OLD_SEQCTL 0x14 +#define IWM_RX_DROP_BA_REORDER_DUPLICATE 0x15 + +struct iwm_rx_ticket { + __le16 action; + __le16 id; + __le16 flags; + u8 payload_offset; /* includes: MAC header, pad, IV */ + u8 tail_len; /* includes: MIC, ICV, CRC (w/o STATUS) */ +} __packed; + +struct iwm_rx_mpdu_hdr { + __le16 len; + __le16 reserved; +} __packed; + +/* UMAC SW WIFI API */ + +struct iwm_dev_cmd_hdr { + u8 cmd; + u8 flags; + __le16 seq_num; +} __packed; + +struct iwm_umac_fw_cmd_hdr { + __le32 meta_data; + struct iwm_dev_cmd_hdr cmd; +} __packed; + +struct iwm_umac_wifi_out_hdr { + struct iwm_udma_out_wifi_hdr hw_hdr; + struct iwm_umac_fw_cmd_hdr sw_hdr; +} __packed; + +struct iwm_umac_nonwifi_out_hdr { + struct iwm_udma_out_nonwifi_hdr hw_hdr; +} __packed; + +struct iwm_umac_wifi_in_hdr { + struct iwm_udma_in_hdr hw_hdr; + struct iwm_umac_fw_cmd_hdr sw_hdr; +} __packed; + +struct iwm_umac_nonwifi_in_hdr { + struct iwm_udma_in_hdr hw_hdr; + __le32 time_stamp; +} __packed; + +#define IWM_UMAC_PAGE_SIZE 0x200 + +/* Notify structures */ +struct iwm_fw_version { + u8 minor; + u8 major; + __le16 id; +}; + +struct iwm_fw_build { + u8 type; + u8 subtype; + u8 platform; + u8 opt; +}; + +struct iwm_fw_alive_hdr { + struct iwm_fw_version ver; + struct iwm_fw_build build; + __le32 os_build; + __le32 log_hdr_addr; + __le32 log_buf_addr; + __le32 sys_timer_addr; +}; + +#define WAIT_NOTIF_TIMEOUT (2 * HZ) +#define SCAN_COMPLETE_TIMEOUT (3 * HZ) + +#define UMAC_NTFY_ALIVE_STATUS_ERR 0xDEAD +#define UMAC_NTFY_ALIVE_STATUS_OK 0xCAFE + +#define UMAC_NTFY_INIT_COMPLETE_STATUS_ERR 0xDEAD +#define UMAC_NTFY_INIT_COMPLETE_STATUS_OK 0xCAFE + +#define UMAC_NTFY_WIFI_CORE_STATUS_LINK_EN 0x40 +#define UMAC_NTFY_WIFI_CORE_STATUS_MLME_EN 0x80 + +#define IWM_MACS_OUT_GROUPS 6 +#define IWM_MACS_OUT_SGROUPS 1 + + +#define WIFI_IF_NTFY_ASSOC_START 0x80 +#define WIFI_IF_NTFY_ASSOC_COMPLETE 0x81 +#define WIFI_IF_NTFY_PROFILE_INVALIDATE_COMPLETE 0x82 +#define WIFI_IF_NTFY_CONNECTION_TERMINATED 0x83 +#define WIFI_IF_NTFY_SCAN_COMPLETE 0x84 +#define WIFI_IF_NTFY_STA_TABLE_CHANGE 0x85 +#define WIFI_IF_NTFY_EXTENDED_IE_REQUIRED 0x86 +#define WIFI_IF_NTFY_RADIO_PREEMPTION 0x87 +#define WIFI_IF_NTFY_BSS_TRK_TABLE_CHANGED 0x88 +#define WIFI_IF_NTFY_BSS_TRK_ENTRIES_REMOVED 0x89 +#define WIFI_IF_NTFY_LINK_QUALITY_STATISTICS 0x8A +#define WIFI_IF_NTFY_MGMT_FRAME 0x8B + +/* DEBUG INDICATIONS */ +#define WIFI_DBG_IF_NTFY_SCAN_SUPER_JOB_START 0xE0 +#define WIFI_DBG_IF_NTFY_SCAN_SUPER_JOB_COMPLETE 0xE1 +#define WIFI_DBG_IF_NTFY_SCAN_CHANNEL_START 0xE2 +#define WIFI_DBG_IF_NTFY_SCAN_CHANNEL_RESULT 0xE3 +#define WIFI_DBG_IF_NTFY_SCAN_MINI_JOB_START 0xE4 +#define WIFI_DBG_IF_NTFY_SCAN_MINI_JOB_COMPLETE 0xE5 +#define WIFI_DBG_IF_NTFY_CNCT_ATC_START 0xE6 +#define WIFI_DBG_IF_NTFY_COEX_NOTIFICATION 0xE7 +#define WIFI_DBG_IF_NTFY_COEX_HANDLE_ENVELOP 0xE8 +#define WIFI_DBG_IF_NTFY_COEX_HANDLE_RELEASE_ENVELOP 0xE9 + +#define WIFI_IF_NTFY_MAX 0xff + +/* Notification structures */ +struct iwm_umac_notif_wifi_if { + struct iwm_umac_wifi_in_hdr hdr; + u8 status; + u8 flags; + __le16 buf_size; +} __packed; + +#define UMAC_ROAM_REASON_FIRST_SELECTION 0x1 +#define UMAC_ROAM_REASON_AP_DEAUTH 0x2 +#define UMAC_ROAM_REASON_AP_CONNECT_LOST 0x3 +#define UMAC_ROAM_REASON_RSSI 0x4 +#define UMAC_ROAM_REASON_AP_ASSISTED_ROAM 0x5 +#define UMAC_ROAM_REASON_IBSS_COALESCING 0x6 + +struct iwm_umac_notif_assoc_start { + struct iwm_umac_notif_wifi_if mlme_hdr; + __le32 roam_reason; + u8 bssid[ETH_ALEN]; + u8 reserved[2]; +} __packed; + +#define UMAC_ASSOC_COMPLETE_SUCCESS 0x0 +#define UMAC_ASSOC_COMPLETE_FAILURE 0x1 + +struct iwm_umac_notif_assoc_complete { + struct iwm_umac_notif_wifi_if mlme_hdr; + __le32 status; + u8 bssid[ETH_ALEN]; + u8 band; + u8 channel; +} __packed; + +#define UMAC_PROFILE_INVALID_ASSOC_TIMEOUT 0x0 +#define UMAC_PROFILE_INVALID_ROAM_TIMEOUT 0x1 +#define UMAC_PROFILE_INVALID_REQUEST 0x2 +#define UMAC_PROFILE_INVALID_RF_PREEMPTED 0x3 + +struct iwm_umac_notif_profile_invalidate { + struct iwm_umac_notif_wifi_if mlme_hdr; + __le32 reason; +} __packed; + +#define UMAC_SCAN_RESULT_SUCCESS 0x0 +#define UMAC_SCAN_RESULT_ABORTED 0x1 +#define UMAC_SCAN_RESULT_REJECTED 0x2 +#define UMAC_SCAN_RESULT_FAILED 0x3 + +struct iwm_umac_notif_scan_complete { + struct iwm_umac_notif_wifi_if mlme_hdr; + __le32 type; + __le32 result; + u8 seq_num; +} __packed; + +#define UMAC_OPCODE_ADD_MODIFY 0x0 +#define UMAC_OPCODE_REMOVE 0x1 +#define UMAC_OPCODE_CLEAR_ALL 0x2 + +#define UMAC_STA_FLAG_QOS 0x1 + +struct iwm_umac_notif_sta_info { + struct iwm_umac_notif_wifi_if mlme_hdr; + __le32 opcode; + u8 mac_addr[ETH_ALEN]; + u8 sta_id; /* bits 0-3: station ID, bits 4-7: station color */ + u8 flags; +} __packed; + +#define UMAC_BAND_2GHZ 0 +#define UMAC_BAND_5GHZ 1 + +#define UMAC_CHANNEL_WIDTH_20MHZ 0 +#define UMAC_CHANNEL_WIDTH_40MHZ 1 + +struct iwm_umac_notif_bss_info { + struct iwm_umac_notif_wifi_if mlme_hdr; + __le32 type; + __le32 timestamp; + __le16 table_idx; + __le16 frame_len; + u8 band; + u8 channel; + s8 rssi; + u8 reserved; + u8 frame_buf[1]; +} __packed; + +#define IWM_BSS_REMOVE_INDEX_MSK 0x0fff +#define IWM_BSS_REMOVE_FLAGS_MSK 0xfc00 + +#define IWM_BSS_REMOVE_FLG_AGE 0x1000 +#define IWM_BSS_REMOVE_FLG_TIMEOUT 0x2000 +#define IWM_BSS_REMOVE_FLG_TABLE_FULL 0x4000 + +struct iwm_umac_notif_bss_removed { + struct iwm_umac_notif_wifi_if mlme_hdr; + __le32 count; + __le16 entries[0]; +} __packed; + +struct iwm_umac_notif_mgt_frame { + struct iwm_umac_notif_wifi_if mlme_hdr; + __le16 len; + u8 frame[1]; +} __packed; + +struct iwm_umac_notif_alive { + struct iwm_umac_wifi_in_hdr hdr; + __le16 status; + __le16 reserved1; + struct iwm_fw_alive_hdr alive_data; + __le16 reserved2; + __le16 page_grp_count; + __le32 page_grp_state[IWM_MACS_OUT_GROUPS]; +} __packed; + +struct iwm_umac_notif_init_complete { + struct iwm_umac_wifi_in_hdr hdr; + __le16 status; + __le16 reserved; +} __packed; + +/* error categories */ +enum { + UMAC_SYS_ERR_CAT_NONE = 0, + UMAC_SYS_ERR_CAT_BOOT, + UMAC_SYS_ERR_CAT_UMAC, + UMAC_SYS_ERR_CAT_UAXM, + UMAC_SYS_ERR_CAT_LMAC, + UMAC_SYS_ERR_CAT_MAX +}; + +struct iwm_fw_error_hdr { + __le32 category; + __le32 status; + __le32 pc; + __le32 blink1; + __le32 blink2; + __le32 ilink1; + __le32 ilink2; + __le32 data1; + __le32 data2; + __le32 line_num; + __le32 umac_status; + __le32 lmac_status; + __le32 sdio_status; + __le32 dbm_sample_ctrl; + __le32 dbm_buf_base; + __le32 dbm_buf_end; + __le32 dbm_buf_write_ptr; + __le32 dbm_buf_cycle_cnt; +} __packed; + +struct iwm_umac_notif_error { + struct iwm_umac_wifi_in_hdr hdr; + struct iwm_fw_error_hdr err; +} __packed; + +#define UMAC_DEALLOC_NTFY_CHANGES_CNT_POS 0 +#define UMAC_DEALLOC_NTFY_CHANGES_CNT_SEED 0xff +#define UMAC_DEALLOC_NTFY_CHANGES_MSK_POS 8 +#define UMAC_DEALLOC_NTFY_CHANGES_MSK_SEED 0xffffff +#define UMAC_DEALLOC_NTFY_PAGE_CNT_POS 0 +#define UMAC_DEALLOC_NTFY_PAGE_CNT_SEED 0xffffff +#define UMAC_DEALLOC_NTFY_GROUP_NUM_POS 24 +#define UMAC_DEALLOC_NTFY_GROUP_NUM_SEED 0xf + +struct iwm_umac_notif_page_dealloc { + struct iwm_umac_wifi_in_hdr hdr; + __le32 changes; + __le32 grp_info[IWM_MACS_OUT_GROUPS]; +} __packed; + +struct iwm_umac_notif_wifi_status { + struct iwm_umac_wifi_in_hdr hdr; + __le16 status; + __le16 reserved; +} __packed; + +struct iwm_umac_notif_rx_ticket { + struct iwm_umac_wifi_in_hdr hdr; + u8 num_tickets; + u8 reserved[3]; + struct iwm_rx_ticket tickets[1]; +} __packed; + +/* Tx/Rx rates window (number of max of last update window per second) */ +#define UMAC_NTF_RATE_SAMPLE_NR 4 + +/* Max numbers of bits required to go through all antennae in bitmasks */ +#define UMAC_PHY_NUM_CHAINS 3 + +#define IWM_UMAC_MGMT_TID 8 +#define IWM_UMAC_TID_NR 9 /* 8 TIDs + MGMT */ + +struct iwm_umac_notif_stats { + struct iwm_umac_wifi_in_hdr hdr; + __le32 flags; + __le32 timestamp; + __le16 tid_load[IWM_UMAC_TID_NR + 1]; /* 1 non-QoS + 1 dword align */ + __le16 tx_rate[UMAC_NTF_RATE_SAMPLE_NR]; + __le16 rx_rate[UMAC_NTF_RATE_SAMPLE_NR]; + __le32 chain_energy[UMAC_PHY_NUM_CHAINS]; + s32 rssi_dbm; + s32 noise_dbm; + __le32 supp_rates; + __le32 supp_ht_rates; + __le32 missed_beacons; + __le32 rx_beacons; + __le32 rx_dir_pkts; + __le32 rx_nondir_pkts; + __le32 rx_multicast; + __le32 rx_errors; + __le32 rx_drop_other_bssid; + __le32 rx_drop_decode; + __le32 rx_drop_reassembly; + __le32 rx_drop_bad_len; + __le32 rx_drop_overflow; + __le32 rx_drop_crc; + __le32 rx_drop_missed; + __le32 tx_dir_pkts; + __le32 tx_nondir_pkts; + __le32 tx_failure; + __le32 tx_errors; + __le32 tx_drop_max_retry; + __le32 tx_err_abort; + __le32 tx_err_carrier; + __le32 rx_bytes; + __le32 tx_bytes; + __le32 tx_power; + __le32 tx_max_power; + __le32 roam_threshold; + __le32 ap_assoc_nr; + __le32 scan_full; + __le32 scan_abort; + __le32 ap_nr; + __le32 roam_nr; + __le32 roam_missed_beacons; + __le32 roam_rssi; + __le32 roam_unassoc; + __le32 roam_deauth; + __le32 roam_ap_loadblance; +} __packed; + +#define UMAC_STOP_TX_FLAG 0x1 +#define UMAC_RESUME_TX_FLAG 0x2 + +#define LAST_SEQ_NUM_INVALID 0xFFFF + +struct iwm_umac_notif_stop_resume_tx { + struct iwm_umac_wifi_in_hdr hdr; + u8 flags; /* UMAC_*_TX_FLAG_* */ + u8 sta_id; + __le16 stop_resume_tid_msk; /* tid bitmask */ +} __packed; + +#define UMAC_MAX_NUM_PMKIDS 4 + +/* WiFi interface wrapper header */ +struct iwm_umac_wifi_if { + u8 oid; + u8 flags; + __le16 buf_size; +} __packed; + +#define IWM_SEQ_NUM_HOST_MSK 0x0000 +#define IWM_SEQ_NUM_UMAC_MSK 0x4000 +#define IWM_SEQ_NUM_LMAC_MSK 0x8000 +#define IWM_SEQ_NUM_MSK 0xC000 + +#endif diff --git a/trunk/drivers/net/wireless/libertas/host.h b/trunk/drivers/net/wireless/libertas/host.h index 96726f79a1dd..2e2dbfa2ee50 100644 --- a/trunk/drivers/net/wireless/libertas/host.h +++ b/trunk/drivers/net/wireless/libertas/host.h @@ -68,6 +68,7 @@ #define CMD_802_11_BEACON_STOP 0x0049 #define CMD_802_11_MAC_ADDRESS 0x004d #define CMD_802_11_LED_GPIO_CTRL 0x004e +#define CMD_802_11_EEPROM_ACCESS 0x0059 #define CMD_802_11_BAND_CONFIG 0x0058 #define CMD_GSPI_BUS_CONFIG 0x005a #define CMD_802_11D_DOMAIN_INFO 0x005b diff --git a/trunk/drivers/net/wireless/mac80211_hwsim.c b/trunk/drivers/net/wireless/mac80211_hwsim.c index 200bcc0ead98..f578d0b2172d 100644 --- a/trunk/drivers/net/wireless/mac80211_hwsim.c +++ b/trunk/drivers/net/wireless/mac80211_hwsim.c @@ -292,7 +292,7 @@ struct mac80211_hwsim_data { struct list_head list; struct ieee80211_hw *hw; struct device *dev; - struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS]; + struct ieee80211_supported_band bands[2]; struct ieee80211_channel channels_2ghz[ARRAY_SIZE(hwsim_channels_2ghz)]; struct ieee80211_channel channels_5ghz[ARRAY_SIZE(hwsim_channels_5ghz)]; struct ieee80211_rate rates[ARRAY_SIZE(hwsim_rates)]; @@ -1082,8 +1082,6 @@ enum hwsim_testmode_attr { enum hwsim_testmode_cmd { HWSIM_TM_CMD_SET_PS = 0, HWSIM_TM_CMD_GET_PS = 1, - HWSIM_TM_CMD_STOP_QUEUES = 2, - HWSIM_TM_CMD_WAKE_QUEUES = 3, }; static const struct nla_policy hwsim_testmode_policy[HWSIM_TM_ATTR_MAX + 1] = { @@ -1123,12 +1121,6 @@ static int mac80211_hwsim_testmode_cmd(struct ieee80211_hw *hw, if (nla_put_u32(skb, HWSIM_TM_ATTR_PS, hwsim->ps)) goto nla_put_failure; return cfg80211_testmode_reply(skb); - case HWSIM_TM_CMD_STOP_QUEUES: - ieee80211_stop_queues(hw); - return 0; - case HWSIM_TM_CMD_WAKE_QUEUES: - ieee80211_wake_queues(hw); - return 0; default: return -EOPNOTSUPP; } @@ -1863,7 +1855,7 @@ static int __init init_mac80211_hwsim(void) sband->n_bitrates = ARRAY_SIZE(hwsim_rates) - 4; break; default: - continue; + break; } sband->ht_cap.ht_supported = true; diff --git a/trunk/drivers/net/wireless/mwifiex/cfg80211.c b/trunk/drivers/net/wireless/mwifiex/cfg80211.c index c7a177c62625..4b2733af1a0e 100644 --- a/trunk/drivers/net/wireless/mwifiex/cfg80211.c +++ b/trunk/drivers/net/wireless/mwifiex/cfg80211.c @@ -914,69 +914,6 @@ static int mwifiex_cfg80211_set_cqm_rssi_config(struct wiphy *wiphy, return 0; } -/* cfg80211 operation handler for change_beacon. - * Function retrieves and sets modified management IEs to FW. - */ -static int mwifiex_cfg80211_change_beacon(struct wiphy *wiphy, - struct net_device *dev, - struct cfg80211_beacon_data *data) -{ - struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); - - if (priv->bss_type != MWIFIEX_BSS_TYPE_UAP) { - wiphy_err(wiphy, "%s: bss_type mismatched\n", __func__); - return -EINVAL; - } - - if (!priv->bss_started) { - wiphy_err(wiphy, "%s: bss not started\n", __func__); - return -EINVAL; - } - - if (mwifiex_set_mgmt_ies(priv, data)) { - wiphy_err(wiphy, "%s: setting mgmt ies failed\n", __func__); - return -EFAULT; - } - - return 0; -} - -static int -mwifiex_cfg80211_set_antenna(struct wiphy *wiphy, u32 tx_ant, u32 rx_ant) -{ - struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy); - struct mwifiex_private *priv = mwifiex_get_priv(adapter, - MWIFIEX_BSS_ROLE_ANY); - struct mwifiex_ds_ant_cfg ant_cfg; - - if (!tx_ant || !rx_ant) - return -EOPNOTSUPP; - - if (adapter->hw_dev_mcs_support != HT_STREAM_2X2) { - /* Not a MIMO chip. User should provide specific antenna number - * for Tx/Rx path or enable all antennas for diversity - */ - if (tx_ant != rx_ant) - return -EOPNOTSUPP; - - if ((tx_ant & (tx_ant - 1)) && - (tx_ant != BIT(adapter->number_of_antenna) - 1)) - return -EOPNOTSUPP; - - if ((tx_ant == BIT(adapter->number_of_antenna) - 1) && - (priv->adapter->number_of_antenna > 1)) { - tx_ant = RF_ANTENNA_AUTO; - rx_ant = RF_ANTENNA_AUTO; - } - } - - ant_cfg.tx_ant = tx_ant; - ant_cfg.rx_ant = rx_ant; - - return mwifiex_send_cmd_sync(priv, HostCmd_CMD_RF_ANTENNA, - HostCmd_ACT_GEN_SET, 0, &ant_cfg); -} - /* cfg80211 operation handler for stop ap. * Function stops BSS running at uAP interface. */ @@ -1010,7 +947,7 @@ static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy, if (priv->bss_type != MWIFIEX_BSS_TYPE_UAP) return -1; - if (mwifiex_set_mgmt_ies(priv, ¶ms->beacon)) + if (mwifiex_set_mgmt_ies(priv, params)) return -1; bss_cfg = kzalloc(sizeof(struct mwifiex_uap_bss_param), GFP_KERNEL); @@ -1039,7 +976,6 @@ static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy, case NL80211_HIDDEN_SSID_ZERO_CONTENTS: /* firmware doesn't support this type of hidden SSID */ default: - kfree(bss_cfg); return -EINVAL; } @@ -1760,9 +1696,7 @@ static struct cfg80211_ops mwifiex_cfg80211_ops = { .set_bitrate_mask = mwifiex_cfg80211_set_bitrate_mask, .start_ap = mwifiex_cfg80211_start_ap, .stop_ap = mwifiex_cfg80211_stop_ap, - .change_beacon = mwifiex_cfg80211_change_beacon, .set_cqm_rssi_config = mwifiex_cfg80211_set_cqm_rssi_config, - .set_antenna = mwifiex_cfg80211_set_antenna, }; /* @@ -1809,14 +1743,7 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter) memcpy(wiphy->perm_addr, priv->curr_addr, ETH_ALEN); wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; - wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME | - WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD; - - wiphy->probe_resp_offload = NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS | - 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->flags |= WIPHY_FLAG_HAVE_AP_SME; /* 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/fw.h b/trunk/drivers/net/wireless/mwifiex/fw.h index 14e985d01dee..ffb6cdfdb797 100644 --- a/trunk/drivers/net/wireless/mwifiex/fw.h +++ b/trunk/drivers/net/wireless/mwifiex/fw.h @@ -227,7 +227,6 @@ enum MWIFIEX_802_11_PRIVACY_FILTER { #define HostCmd_CMD_PMIC_REG_ACCESS 0x00ad #define HostCmd_CMD_802_11_RF_CHANNEL 0x001d #define HostCmd_CMD_RF_TX_PWR 0x001e -#define HostCmd_CMD_RF_ANTENNA 0x0020 #define HostCmd_CMD_802_11_DEAUTHENTICATE 0x0024 #define HostCmd_CMD_MAC_CONTROL 0x0028 #define HostCmd_CMD_802_11_AD_HOC_START 0x002b @@ -323,12 +322,6 @@ enum ENH_PS_MODES { #define HostCmd_BSS_TYPE_MASK 0xf000 -#define HostCmd_ACT_SET_RX 0x0001 -#define HostCmd_ACT_SET_TX 0x0002 -#define HostCmd_ACT_SET_BOTH 0x0003 - -#define RF_ANTENNA_AUTO 0xFFFF - #define HostCmd_SET_SEQ_NO_BSS_INFO(seq, num, type) { \ (((seq) & 0x00ff) | \ (((num) & 0x000f) << 8)) | \ @@ -891,18 +884,6 @@ struct host_cmd_ds_rf_tx_pwr { u8 min_power; } __packed; -struct host_cmd_ds_rf_ant_mimo { - __le16 action_tx; - __le16 tx_ant_mode; - __le16 action_rx; - __le16 rx_ant_mode; -}; - -struct host_cmd_ds_rf_ant_siso { - __le16 action; - __le16 ant_mode; -}; - struct mwifiex_bcn_param { u8 bssid[ETH_ALEN]; u8 rssi; @@ -1389,8 +1370,6 @@ struct host_cmd_ds_command { struct host_cmd_ds_tx_rate_cfg tx_rate_cfg; struct host_cmd_ds_txpwr_cfg txp_cfg; struct host_cmd_ds_rf_tx_pwr txp; - struct host_cmd_ds_rf_ant_mimo ant_mimo; - struct host_cmd_ds_rf_ant_siso ant_siso; struct host_cmd_ds_802_11_ps_mode_enh psmode_enh; struct host_cmd_ds_802_11_hs_cfg_enh opt_hs_cfg; struct host_cmd_ds_802_11_scan scan; diff --git a/trunk/drivers/net/wireless/mwifiex/ie.c b/trunk/drivers/net/wireless/mwifiex/ie.c index 1d8dd003e396..8374e33f195a 100644 --- a/trunk/drivers/net/wireless/mwifiex/ie.c +++ b/trunk/drivers/net/wireless/mwifiex/ie.c @@ -51,7 +51,8 @@ mwifiex_ie_get_autoidx(struct mwifiex_private *priv, u16 subtype_mask, for (i = 0; i < priv->adapter->max_mgmt_ie_index; i++) { mask = le16_to_cpu(priv->mgmt_ie[i].mgmt_subtype_mask); - len = le16_to_cpu(ie->ie_length); + len = le16_to_cpu(priv->mgmt_ie[i].ie_length) + + le16_to_cpu(ie->ie_length); if (mask == MWIFIEX_AUTO_IDX_MASK) continue; @@ -107,8 +108,10 @@ mwifiex_update_autoindex_ies(struct mwifiex_private *priv, return -1; tmp = (u8 *)&priv->mgmt_ie[index].ie_buffer; + tmp += le16_to_cpu(priv->mgmt_ie[index].ie_length); memcpy(tmp, &ie->ie_buffer, le16_to_cpu(ie->ie_length)); - priv->mgmt_ie[index].ie_length = ie->ie_length; + le16_add_cpu(&priv->mgmt_ie[index].ie_length, + le16_to_cpu(ie->ie_length)); priv->mgmt_ie[index].ie_index = cpu_to_le16(index); priv->mgmt_ie[index].mgmt_subtype_mask = cpu_to_le16(mask); @@ -214,107 +217,34 @@ mwifiex_update_uap_custom_ie(struct mwifiex_private *priv, return ret; } -/* 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 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_wps_ie(const u8 *ies, int ies_len, - struct mwifiex_ie **ie_ptr, u16 mask) -{ - struct ieee_types_header *wps_ie; - struct mwifiex_ie *ie = NULL; - const u8 *vendor_ie; - - vendor_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, - WLAN_OUI_TYPE_MICROSOFT_WPS, - ies, ies_len); - if (vendor_ie) { - ie = kmalloc(sizeof(struct mwifiex_ie), GFP_KERNEL); - if (!ie) - return -ENOMEM; - - 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); - } - - *ie_ptr = ie; - return 0; -} - -/* This function parses beacon IEs, probe response IEs, association response IEs - * from cfg80211_ap_settings->beacon and sets these IE to FW. - */ -static int mwifiex_set_mgmt_beacon_data_ies(struct mwifiex_private *priv, - struct cfg80211_beacon_data *data) -{ - struct mwifiex_ie *beacon_ie = NULL, *pr_ie = NULL, *ar_ie = NULL; - u16 beacon_idx = MWIFIEX_AUTO_IDX_MASK, pr_idx = MWIFIEX_AUTO_IDX_MASK; - u16 ar_idx = MWIFIEX_AUTO_IDX_MASK; - int ret = 0; - - 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_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_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, - &beacon_idx, pr_ie, - &pr_idx, ar_ie, &ar_idx); - if (ret) - goto done; - } - - priv->beacon_idx = beacon_idx; - priv->proberesp_idx = pr_idx; - priv->assocresp_idx = ar_idx; - -done: - kfree(beacon_ie); - kfree(pr_ie); - kfree(ar_ie); - - return ret; -} - -/* This function parses different IEs-tail IEs, beacon IEs, probe response IEs, +/* This function parses different IEs- Tail IEs, beacon IEs, probe response IEs, * association response IEs from cfg80211_ap_settings function and sets these IE * to FW. */ int mwifiex_set_mgmt_ies(struct mwifiex_private *priv, - struct cfg80211_beacon_data *info) + struct cfg80211_ap_settings *params) { - struct mwifiex_ie *gen_ie; - struct ieee_types_header *rsn_ie, *wpa_ie = NULL; - u16 rsn_idx = MWIFIEX_AUTO_IDX_MASK, ie_len = 0; + struct mwifiex_ie *beacon_ie = NULL, *pr_ie = NULL; + struct mwifiex_ie *ar_ie = NULL, *gen_ie = NULL; + struct ieee_types_header *rsn_ie = NULL, *wpa_ie = NULL; + u16 beacon_idx = MWIFIEX_AUTO_IDX_MASK, pr_idx = MWIFIEX_AUTO_IDX_MASK; + u16 ar_idx = MWIFIEX_AUTO_IDX_MASK, rsn_idx = MWIFIEX_AUTO_IDX_MASK; + u16 mask, ie_len = 0; const u8 *vendor_ie; + int ret = 0; - if (info->tail && info->tail_len) { + if (params->beacon.tail && params->beacon.tail_len) { gen_ie = kzalloc(sizeof(struct mwifiex_ie), GFP_KERNEL); if (!gen_ie) return -ENOMEM; gen_ie->ie_index = cpu_to_le16(rsn_idx); - gen_ie->mgmt_subtype_mask = cpu_to_le16(MGMT_MASK_BEACON | - MGMT_MASK_PROBE_RESP | - MGMT_MASK_ASSOC_RESP); + mask = MGMT_MASK_BEACON | MGMT_MASK_PROBE_RESP | + MGMT_MASK_ASSOC_RESP; + gen_ie->mgmt_subtype_mask = cpu_to_le16(mask); rsn_ie = (void *)cfg80211_find_ie(WLAN_EID_RSN, - info->tail, info->tail_len); + params->beacon.tail, + params->beacon.tail_len); if (rsn_ie) { memcpy(gen_ie->ie_buffer, rsn_ie, rsn_ie->len + 2); ie_len = rsn_ie->len + 2; @@ -323,8 +253,8 @@ int mwifiex_set_mgmt_ies(struct mwifiex_private *priv, vendor_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, WLAN_OUI_TYPE_MICROSOFT_WPA, - info->tail, - info->tail_len); + params->beacon.tail, + params->beacon.tail_len); if (vendor_ie) { wpa_ie = (struct ieee_types_header *)vendor_ie; memcpy(gen_ie->ie_buffer + ie_len, @@ -337,16 +267,79 @@ int mwifiex_set_mgmt_ies(struct mwifiex_private *priv, if (mwifiex_update_uap_custom_ie(priv, gen_ie, &rsn_idx, NULL, NULL, NULL, NULL)) { - kfree(gen_ie); - return -1; + ret = -1; + goto done; } + priv->rsn_idx = rsn_idx; } + } + + if (params->beacon.beacon_ies && params->beacon.beacon_ies_len) { + beacon_ie = kmalloc(sizeof(struct mwifiex_ie), GFP_KERNEL); + if (!beacon_ie) { + ret = -ENOMEM; + goto done; + } + + beacon_ie->ie_index = cpu_to_le16(beacon_idx); + beacon_ie->mgmt_subtype_mask = cpu_to_le16(MGMT_MASK_BEACON); + beacon_ie->ie_length = + cpu_to_le16(params->beacon.beacon_ies_len); + memcpy(beacon_ie->ie_buffer, params->beacon.beacon_ies, + params->beacon.beacon_ies_len); + } + + if (params->beacon.proberesp_ies && params->beacon.proberesp_ies_len) { + pr_ie = kmalloc(sizeof(struct mwifiex_ie), GFP_KERNEL); + if (!pr_ie) { + ret = -ENOMEM; + goto done; + } + + pr_ie->ie_index = cpu_to_le16(pr_idx); + pr_ie->mgmt_subtype_mask = cpu_to_le16(MGMT_MASK_PROBE_RESP); + pr_ie->ie_length = + cpu_to_le16(params->beacon.proberesp_ies_len); + memcpy(pr_ie->ie_buffer, params->beacon.proberesp_ies, + params->beacon.proberesp_ies_len); + } + + if (params->beacon.assocresp_ies && params->beacon.assocresp_ies_len) { + ar_ie = kmalloc(sizeof(struct mwifiex_ie), GFP_KERNEL); + if (!ar_ie) { + ret = -ENOMEM; + goto done; + } - kfree(gen_ie); + ar_ie->ie_index = cpu_to_le16(ar_idx); + mask = MGMT_MASK_ASSOC_RESP | MGMT_MASK_REASSOC_RESP; + ar_ie->mgmt_subtype_mask = cpu_to_le16(mask); + ar_ie->ie_length = + cpu_to_le16(params->beacon.assocresp_ies_len); + memcpy(ar_ie->ie_buffer, params->beacon.assocresp_ies, + params->beacon.assocresp_ies_len); + } + + if (beacon_ie || pr_ie || ar_ie) { + ret = mwifiex_update_uap_custom_ie(priv, beacon_ie, + &beacon_idx, pr_ie, + &pr_idx, ar_ie, &ar_idx); + if (ret) + goto done; } - return mwifiex_set_mgmt_beacon_data_ies(priv, info); + priv->beacon_idx = beacon_idx; + priv->proberesp_idx = pr_idx; + priv->assocresp_idx = ar_idx; + +done: + kfree(beacon_ie); + kfree(pr_ie); + kfree(ar_ie); + kfree(gen_ie); + + return ret; } /* This function removes management IE set */ diff --git a/trunk/drivers/net/wireless/mwifiex/ioctl.h b/trunk/drivers/net/wireless/mwifiex/ioctl.h index e121294cc1ac..9f088fb88cb7 100644 --- a/trunk/drivers/net/wireless/mwifiex/ioctl.h +++ b/trunk/drivers/net/wireless/mwifiex/ioctl.h @@ -277,11 +277,6 @@ struct mwifiex_ds_11n_amsdu_aggr_ctrl { u16 curr_buf_size; }; -struct mwifiex_ds_ant_cfg { - u32 tx_ant; - u32 rx_ant; -}; - #define MWIFIEX_NUM_OF_CMD_BUFFER 20 #define MWIFIEX_SIZE_OF_CMD_BUFFER 2048 diff --git a/trunk/drivers/net/wireless/mwifiex/main.h b/trunk/drivers/net/wireless/mwifiex/main.h index 9e636535cbf6..7cd95cc99a85 100644 --- a/trunk/drivers/net/wireless/mwifiex/main.h +++ b/trunk/drivers/net/wireless/mwifiex/main.h @@ -1013,7 +1013,7 @@ int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct net_device *dev); void mwifiex_set_sys_config_invalid_data(struct mwifiex_uap_bss_param *config); int mwifiex_set_mgmt_ies(struct mwifiex_private *priv, - struct cfg80211_beacon_data *data); + struct cfg80211_ap_settings *params); int mwifiex_del_mgmt_ies(struct mwifiex_private *priv); u8 *mwifiex_11d_code_2_region(u8 code); diff --git a/trunk/drivers/net/wireless/mwifiex/sta_cmd.c b/trunk/drivers/net/wireless/mwifiex/sta_cmd.c index 225d4c776177..b9cd9ed48c45 100644 --- a/trunk/drivers/net/wireless/mwifiex/sta_cmd.c +++ b/trunk/drivers/net/wireless/mwifiex/sta_cmd.c @@ -276,39 +276,6 @@ static int mwifiex_cmd_rf_tx_power(struct mwifiex_private *priv, return 0; } -/* - * This function prepares command to set rf antenna. - */ -static int mwifiex_cmd_rf_antenna(struct mwifiex_private *priv, - struct host_cmd_ds_command *cmd, - u16 cmd_action, - struct mwifiex_ds_ant_cfg *ant_cfg) -{ - struct host_cmd_ds_rf_ant_mimo *ant_mimo = &cmd->params.ant_mimo; - struct host_cmd_ds_rf_ant_siso *ant_siso = &cmd->params.ant_siso; - - cmd->command = cpu_to_le16(HostCmd_CMD_RF_ANTENNA); - - if (cmd_action != HostCmd_ACT_GEN_SET) - return 0; - - if (priv->adapter->hw_dev_mcs_support == HT_STREAM_2X2) { - cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_rf_ant_mimo) + - S_DS_GEN); - ant_mimo->action_tx = cpu_to_le16(HostCmd_ACT_SET_TX); - ant_mimo->tx_ant_mode = cpu_to_le16((u16)ant_cfg->tx_ant); - ant_mimo->action_rx = cpu_to_le16(HostCmd_ACT_SET_RX); - ant_mimo->rx_ant_mode = cpu_to_le16((u16)ant_cfg->rx_ant); - } else { - cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_rf_ant_siso) + - S_DS_GEN); - ant_siso->action = cpu_to_le16(HostCmd_ACT_SET_BOTH); - ant_siso->ant_mode = cpu_to_le16((u16)ant_cfg->tx_ant); - } - - return 0; -} - /* * This function prepares command to set Host Sleep configuration. * @@ -1103,10 +1070,6 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no, ret = mwifiex_cmd_rf_tx_power(priv, cmd_ptr, cmd_action, data_buf); break; - case HostCmd_CMD_RF_ANTENNA: - ret = mwifiex_cmd_rf_antenna(priv, cmd_ptr, cmd_action, - data_buf); - break; case HostCmd_CMD_802_11_PS_MODE_ENH: ret = mwifiex_cmd_enh_power_mode(priv, cmd_ptr, cmd_action, (uint16_t)cmd_oid, data_buf); diff --git a/trunk/drivers/net/wireless/mwifiex/sta_cmdresp.c b/trunk/drivers/net/wireless/mwifiex/sta_cmdresp.c index 97715dfbdf58..78fc352c85c4 100644 --- a/trunk/drivers/net/wireless/mwifiex/sta_cmdresp.c +++ b/trunk/drivers/net/wireless/mwifiex/sta_cmdresp.c @@ -474,33 +474,6 @@ static int mwifiex_ret_rf_tx_power(struct mwifiex_private *priv, return 0; } -/* - * This function handles the command response of set rf antenna - */ -static int mwifiex_ret_rf_antenna(struct mwifiex_private *priv, - struct host_cmd_ds_command *resp) -{ - struct host_cmd_ds_rf_ant_mimo *ant_mimo = &resp->params.ant_mimo; - struct host_cmd_ds_rf_ant_siso *ant_siso = &resp->params.ant_siso; - struct mwifiex_adapter *adapter = priv->adapter; - - if (adapter->hw_dev_mcs_support == HT_STREAM_2X2) - dev_dbg(adapter->dev, - "RF_ANT_RESP: Tx action = 0x%x, Tx Mode = 0x%04x" - " Rx action = 0x%x, Rx Mode = 0x%04x\n", - le16_to_cpu(ant_mimo->action_tx), - le16_to_cpu(ant_mimo->tx_ant_mode), - le16_to_cpu(ant_mimo->action_rx), - le16_to_cpu(ant_mimo->rx_ant_mode)); - else - dev_dbg(adapter->dev, - "RF_ANT_RESP: action = 0x%x, Mode = 0x%04x\n", - le16_to_cpu(ant_siso->action), - le16_to_cpu(ant_siso->ant_mode)); - - return 0; -} - /* * This function handles the command response of set/get MAC address. * @@ -895,9 +868,6 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no, case HostCmd_CMD_RF_TX_PWR: ret = mwifiex_ret_rf_tx_power(priv, resp); break; - case HostCmd_CMD_RF_ANTENNA: - ret = mwifiex_ret_rf_antenna(priv, resp); - break; case HostCmd_CMD_802_11_PS_MODE_ENH: ret = mwifiex_ret_enh_power_mode(priv, resp, data_buf); break; diff --git a/trunk/drivers/net/wireless/p54/eeprom.c b/trunk/drivers/net/wireless/p54/eeprom.c index 14037092ba89..636daf2860cc 100644 --- a/trunk/drivers/net/wireless/p54/eeprom.c +++ b/trunk/drivers/net/wireless/p54/eeprom.c @@ -857,7 +857,7 @@ int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len) wiphy_warn(dev->wiphy, "Invalid hwaddr! Using randomly generated MAC addr\n"); - eth_random_addr(perm_addr); + random_ether_addr(perm_addr); SET_IEEE80211_PERM_ADDR(dev, perm_addr); } diff --git a/trunk/drivers/net/wireless/p54/txrx.c b/trunk/drivers/net/wireless/p54/txrx.c index f38786e02623..82a1cac920bd 100644 --- a/trunk/drivers/net/wireless/p54/txrx.c +++ b/trunk/drivers/net/wireless/p54/txrx.c @@ -422,11 +422,11 @@ static void p54_rx_frame_sent(struct p54_common *priv, struct sk_buff *skb) * Clear manually, ieee80211_tx_info_clear_status would * clear the counts too and we need them. */ - memset(&info->status.ack_signal, 0, + memset(&info->status.ampdu_ack_len, 0, sizeof(struct ieee80211_tx_info) - - offsetof(struct ieee80211_tx_info, status.ack_signal)); + offsetof(struct ieee80211_tx_info, status.ampdu_ack_len)); BUILD_BUG_ON(offsetof(struct ieee80211_tx_info, - status.ack_signal) != 20); + status.ampdu_ack_len) != 23); if (entry_hdr->flags & cpu_to_le16(P54_HDR_FLAG_DATA_ALIGN)) pad = entry_data->align[0]; diff --git a/trunk/drivers/net/wireless/rt2x00/rt2400pci.c b/trunk/drivers/net/wireless/rt2x00/rt2400pci.c index 8b9dbd76a252..5e6b50143165 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/trunk/drivers/net/wireless/rt2x00/rt2400pci.c @@ -1455,7 +1455,7 @@ static int rt2400pci_validate_eeprom(struct rt2x00_dev *rt2x00dev) */ mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0); if (!is_valid_ether_addr(mac)) { - eth_random_addr(mac); + random_ether_addr(mac); EEPROM(rt2x00dev, "MAC: %pM\n", mac); } diff --git a/trunk/drivers/net/wireless/rt2x00/rt2500pci.c b/trunk/drivers/net/wireless/rt2x00/rt2500pci.c index d2cf8a4bc8b5..136b849f11b5 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/trunk/drivers/net/wireless/rt2x00/rt2500pci.c @@ -1585,7 +1585,7 @@ static int rt2500pci_validate_eeprom(struct rt2x00_dev *rt2x00dev) */ mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0); if (!is_valid_ether_addr(mac)) { - eth_random_addr(mac); + random_ether_addr(mac); EEPROM(rt2x00dev, "MAC: %pM\n", mac); } diff --git a/trunk/drivers/net/wireless/rt2x00/rt2500usb.c b/trunk/drivers/net/wireless/rt2x00/rt2500usb.c index 3aae36bb0a9e..669aecdb411d 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/trunk/drivers/net/wireless/rt2x00/rt2500usb.c @@ -1352,7 +1352,7 @@ static int rt2500usb_validate_eeprom(struct rt2x00_dev *rt2x00dev) */ mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0); if (!is_valid_ether_addr(mac)) { - eth_random_addr(mac); + random_ether_addr(mac); EEPROM(rt2x00dev, "MAC: %pM\n", mac); } diff --git a/trunk/drivers/net/wireless/rt2x00/rt2800lib.c b/trunk/drivers/net/wireless/rt2x00/rt2800lib.c index 88455b1b9fe0..068276ee8aff 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/trunk/drivers/net/wireless/rt2x00/rt2800lib.c @@ -1940,8 +1940,10 @@ static void rt2800_config_channel_rf3052(struct rt2x00_dev *rt2x00dev, rt2800_rfcsr_write(rt2x00dev, 7, rfcsr); } -#define POWER_BOUND 0x27 -#define FREQ_OFFSET_BOUND 0x5f +#define RT3290_POWER_BOUND 0x27 +#define RT3290_FREQ_OFFSET_BOUND 0x5f +#define RT5390_POWER_BOUND 0x27 +#define RT5390_FREQ_OFFSET_BOUND 0x5f static void rt2800_config_channel_rf3290(struct rt2x00_dev *rt2x00dev, struct ieee80211_conf *conf, @@ -1957,15 +1959,16 @@ static void rt2800_config_channel_rf3290(struct rt2x00_dev *rt2x00dev, rt2800_rfcsr_write(rt2x00dev, 11, rfcsr); rt2800_rfcsr_read(rt2x00dev, 49, &rfcsr); - if (info->default_power1 > POWER_BOUND) - rt2x00_set_field8(&rfcsr, RFCSR49_TX, POWER_BOUND); + if (info->default_power1 > RT3290_POWER_BOUND) + rt2x00_set_field8(&rfcsr, RFCSR49_TX, RT3290_POWER_BOUND); else rt2x00_set_field8(&rfcsr, RFCSR49_TX, info->default_power1); rt2800_rfcsr_write(rt2x00dev, 49, rfcsr); rt2800_rfcsr_read(rt2x00dev, 17, &rfcsr); - if (rt2x00dev->freq_offset > FREQ_OFFSET_BOUND) - rt2x00_set_field8(&rfcsr, RFCSR17_CODE, FREQ_OFFSET_BOUND); + if (rt2x00dev->freq_offset > RT3290_FREQ_OFFSET_BOUND) + rt2x00_set_field8(&rfcsr, RFCSR17_CODE, + RT3290_FREQ_OFFSET_BOUND); else rt2x00_set_field8(&rfcsr, RFCSR17_CODE, rt2x00dev->freq_offset); rt2800_rfcsr_write(rt2x00dev, 17, rfcsr); @@ -1999,16 +2002,17 @@ static void rt2800_config_channel_rf53xx(struct rt2x00_dev *rt2x00dev, rt2800_rfcsr_write(rt2x00dev, 11, rfcsr); rt2800_rfcsr_read(rt2x00dev, 49, &rfcsr); - if (info->default_power1 > POWER_BOUND) - rt2x00_set_field8(&rfcsr, RFCSR49_TX, POWER_BOUND); + if (info->default_power1 > RT5390_POWER_BOUND) + rt2x00_set_field8(&rfcsr, RFCSR49_TX, RT5390_POWER_BOUND); else rt2x00_set_field8(&rfcsr, RFCSR49_TX, info->default_power1); rt2800_rfcsr_write(rt2x00dev, 49, rfcsr); if (rt2x00_rt(rt2x00dev, RT5392)) { rt2800_rfcsr_read(rt2x00dev, 50, &rfcsr); - if (info->default_power1 > POWER_BOUND) - rt2x00_set_field8(&rfcsr, RFCSR50_TX, POWER_BOUND); + if (info->default_power1 > RT5390_POWER_BOUND) + rt2x00_set_field8(&rfcsr, RFCSR50_TX, + RT5390_POWER_BOUND); else rt2x00_set_field8(&rfcsr, RFCSR50_TX, info->default_power2); @@ -2027,8 +2031,9 @@ static void rt2800_config_channel_rf53xx(struct rt2x00_dev *rt2x00dev, rt2800_rfcsr_write(rt2x00dev, 1, rfcsr); rt2800_rfcsr_read(rt2x00dev, 17, &rfcsr); - if (rt2x00dev->freq_offset > FREQ_OFFSET_BOUND) - rt2x00_set_field8(&rfcsr, RFCSR17_CODE, FREQ_OFFSET_BOUND); + if (rt2x00dev->freq_offset > RT5390_FREQ_OFFSET_BOUND) + rt2x00_set_field8(&rfcsr, RFCSR17_CODE, + RT5390_FREQ_OFFSET_BOUND); else rt2x00_set_field8(&rfcsr, RFCSR17_CODE, rt2x00dev->freq_offset); rt2800_rfcsr_write(rt2x00dev, 17, rfcsr); @@ -4335,7 +4340,7 @@ int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev) */ mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0); if (!is_valid_ether_addr(mac)) { - eth_random_addr(mac); + random_ether_addr(mac); EEPROM(rt2x00dev, "MAC: %pM\n", mac); } diff --git a/trunk/drivers/net/wireless/rt2x00/rt2800pci.c b/trunk/drivers/net/wireless/rt2x00/rt2800pci.c index 235376e9cb04..dd436125fe3d 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/trunk/drivers/net/wireless/rt2x00/rt2800pci.c @@ -986,7 +986,7 @@ static int rt2800_enable_wlan_rt3290(struct rt2x00_dev *rt2x00dev) int i, count; rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL, ®); - if (rt2x00_get_field32(reg, WLAN_EN)) + if ((rt2x00_get_field32(reg, WLAN_EN) == 1)) return 0; rt2x00_set_field32(®, WLAN_GPIO_OUT_OE_BIT_ALL, 0xff); @@ -1004,9 +1004,9 @@ static int rt2800_enable_wlan_rt3290(struct rt2x00_dev *rt2x00dev) */ for (i = 0; i < REGISTER_BUSY_COUNT; i++) { rt2800_register_read(rt2x00dev, CMB_CTRL, ®); - if (rt2x00_get_field32(reg, PLL_LD) && - rt2x00_get_field32(reg, XTAL_RDY)) - break; + if ((rt2x00_get_field32(reg, PLL_LD) == 1) && + (rt2x00_get_field32(reg, XTAL_RDY) == 1)) + break; udelay(REGISTER_BUSY_DELAY); } diff --git a/trunk/drivers/net/wireless/rt2x00/rt2x00queue.c b/trunk/drivers/net/wireless/rt2x00/rt2x00queue.c index f7e74a0a7759..2fd830103415 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/trunk/drivers/net/wireless/rt2x00/rt2x00queue.c @@ -774,7 +774,9 @@ int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev, bool rt2x00queue_for_each_entry(struct data_queue *queue, enum queue_index start, enum queue_index end, - bool (*fn)(struct queue_entry *entry)) + void *data, + bool (*fn)(struct queue_entry *entry, + void *data)) { unsigned long irqflags; unsigned int index_start; @@ -805,17 +807,17 @@ bool rt2x00queue_for_each_entry(struct data_queue *queue, */ if (index_start < index_end) { for (i = index_start; i < index_end; i++) { - if (fn(&queue->entries[i])) + if (fn(&queue->entries[i], data)) return true; } } else { for (i = index_start; i < queue->limit; i++) { - if (fn(&queue->entries[i])) + if (fn(&queue->entries[i], data)) return true; } for (i = 0; i < index_end; i++) { - if (fn(&queue->entries[i])) + if (fn(&queue->entries[i], data)) return true; } } diff --git a/trunk/drivers/net/wireless/rt2x00/rt2x00queue.h b/trunk/drivers/net/wireless/rt2x00/rt2x00queue.h index 9b8c10a86dee..5f1392c72673 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2x00queue.h +++ b/trunk/drivers/net/wireless/rt2x00/rt2x00queue.h @@ -584,6 +584,7 @@ struct data_queue_desc { * @queue: Pointer to @data_queue * @start: &enum queue_index Pointer to start index * @end: &enum queue_index Pointer to end index + * @data: Data to pass to the callback function * @fn: The function to call for each &struct queue_entry * * This will walk through all entries in the queue, in chronological @@ -596,7 +597,9 @@ struct data_queue_desc { bool rt2x00queue_for_each_entry(struct data_queue *queue, enum queue_index start, enum queue_index end, - bool (*fn)(struct queue_entry *entry)); + void *data, + bool (*fn)(struct queue_entry *entry, + void *data)); /** * rt2x00queue_empty - Check if the queue is empty. diff --git a/trunk/drivers/net/wireless/rt2x00/rt2x00usb.c b/trunk/drivers/net/wireless/rt2x00/rt2x00usb.c index 40ea80725a96..d357d1ed92f6 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/trunk/drivers/net/wireless/rt2x00/rt2x00usb.c @@ -285,7 +285,7 @@ static void rt2x00usb_interrupt_txdone(struct urb *urb) queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work); } -static bool rt2x00usb_kick_tx_entry(struct queue_entry *entry) +static bool rt2x00usb_kick_tx_entry(struct queue_entry *entry, void* data) { struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev); @@ -390,7 +390,7 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb) queue_work(rt2x00dev->workqueue, &rt2x00dev->rxdone_work); } -static bool rt2x00usb_kick_rx_entry(struct queue_entry *entry) +static bool rt2x00usb_kick_rx_entry(struct queue_entry *entry, void* data) { struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev); @@ -427,12 +427,18 @@ void rt2x00usb_kick_queue(struct data_queue *queue) case QID_AC_BE: case QID_AC_BK: if (!rt2x00queue_empty(queue)) - rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX, + rt2x00queue_for_each_entry(queue, + Q_INDEX_DONE, + Q_INDEX, + NULL, rt2x00usb_kick_tx_entry); break; case QID_RX: if (!rt2x00queue_full(queue)) - rt2x00queue_for_each_entry(queue, Q_INDEX, Q_INDEX_DONE, + rt2x00queue_for_each_entry(queue, + Q_INDEX_DONE, + Q_INDEX, + NULL, rt2x00usb_kick_rx_entry); break; default: @@ -441,7 +447,7 @@ void rt2x00usb_kick_queue(struct data_queue *queue) } EXPORT_SYMBOL_GPL(rt2x00usb_kick_queue); -static bool rt2x00usb_flush_entry(struct queue_entry *entry) +static bool rt2x00usb_flush_entry(struct queue_entry *entry, void* data) { struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; struct queue_entry_priv_usb *entry_priv = entry->priv_data; @@ -468,7 +474,7 @@ void rt2x00usb_flush_queue(struct data_queue *queue, bool drop) unsigned int i; if (drop) - rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX, + rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX, NULL, rt2x00usb_flush_entry); /* @@ -559,7 +565,7 @@ void rt2x00usb_clear_entry(struct queue_entry *entry) entry->flags = 0; if (entry->queue->qid == QID_RX) - rt2x00usb_kick_rx_entry(entry); + rt2x00usb_kick_rx_entry(entry, NULL); } EXPORT_SYMBOL_GPL(rt2x00usb_clear_entry); diff --git a/trunk/drivers/net/wireless/rt2x00/rt61pci.c b/trunk/drivers/net/wireless/rt2x00/rt61pci.c index f32259686b45..ee22bd74579d 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt61pci.c +++ b/trunk/drivers/net/wireless/rt2x00/rt61pci.c @@ -2415,7 +2415,7 @@ static int rt61pci_validate_eeprom(struct rt2x00_dev *rt2x00dev) */ mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0); if (!is_valid_ether_addr(mac)) { - eth_random_addr(mac); + random_ether_addr(mac); EEPROM(rt2x00dev, "MAC: %pM\n", mac); } diff --git a/trunk/drivers/net/wireless/rt2x00/rt73usb.c b/trunk/drivers/net/wireless/rt2x00/rt73usb.c index ba6e434b859d..77ccbbc7da41 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt73usb.c +++ b/trunk/drivers/net/wireless/rt2x00/rt73usb.c @@ -1770,7 +1770,7 @@ static int rt73usb_validate_eeprom(struct rt2x00_dev *rt2x00dev) */ mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0); if (!is_valid_ether_addr(mac)) { - eth_random_addr(mac); + random_ether_addr(mac); EEPROM(rt2x00dev, "MAC: %pM\n", mac); } diff --git a/trunk/drivers/net/wireless/rtl818x/rtl8180/dev.c b/trunk/drivers/net/wireless/rtl818x/rtl8180/dev.c index aceaf689f737..3b505395d869 100644 --- a/trunk/drivers/net/wireless/rtl818x/rtl8180/dev.c +++ b/trunk/drivers/net/wireless/rtl818x/rtl8180/dev.c @@ -1078,7 +1078,7 @@ static int __devinit rtl8180_probe(struct pci_dev *pdev, if (!is_valid_ether_addr(mac_addr)) { printk(KERN_WARNING "%s (rtl8180): Invalid hwaddr! Using" " randomly generated MAC addr\n", pci_name(pdev)); - eth_random_addr(mac_addr); + random_ether_addr(mac_addr); } SET_IEEE80211_PERM_ADDR(dev, mac_addr); diff --git a/trunk/drivers/net/wireless/rtl818x/rtl8187/dev.c b/trunk/drivers/net/wireless/rtl818x/rtl8187/dev.c index 71a30b026089..4fb1ca1b86b9 100644 --- a/trunk/drivers/net/wireless/rtl818x/rtl8187/dev.c +++ b/trunk/drivers/net/wireless/rtl818x/rtl8187/dev.c @@ -1486,7 +1486,7 @@ static int __devinit rtl8187_probe(struct usb_interface *intf, if (!is_valid_ether_addr(mac_addr)) { printk(KERN_WARNING "rtl8187: Invalid hwaddr! Using randomly " "generated MAC address\n"); - eth_random_addr(mac_addr); + random_ether_addr(mac_addr); } SET_IEEE80211_PERM_ADDR(dev, mac_addr); diff --git a/trunk/drivers/net/wireless/ti/wl12xx/main.c b/trunk/drivers/net/wireless/ti/wl12xx/main.c index 3d6c71b7a3c7..47ba2e0017f4 100644 --- a/trunk/drivers/net/wireless/ti/wl12xx/main.c +++ b/trunk/drivers/net/wireless/ti/wl12xx/main.c @@ -242,7 +242,7 @@ static struct wlcore_conf wl12xx_conf = { .psm_entry_retries = 8, .psm_exit_retries = 16, .psm_entry_nullfunc_retries = 3, - .dynamic_ps_timeout = 1500, + .dynamic_ps_timeout = 200, .forced_ps = false, .keep_alive_interval = 55000, .max_listen_interval = 20, @@ -590,13 +590,13 @@ static const int wl12xx_rtable[REG_TABLE_LEN] = { }; /* TODO: maybe move to a new header file? */ -#define WL127X_FW_NAME_MULTI "ti-connectivity/wl127x-fw-5-mr.bin" -#define WL127X_FW_NAME_SINGLE "ti-connectivity/wl127x-fw-5-sr.bin" -#define WL127X_PLT_FW_NAME "ti-connectivity/wl127x-fw-5-plt.bin" +#define WL127X_FW_NAME_MULTI "ti-connectivity/wl127x-fw-4-mr.bin" +#define WL127X_FW_NAME_SINGLE "ti-connectivity/wl127x-fw-4-sr.bin" +#define WL127X_PLT_FW_NAME "ti-connectivity/wl127x-fw-4-plt.bin" -#define WL128X_FW_NAME_MULTI "ti-connectivity/wl128x-fw-5-mr.bin" -#define WL128X_FW_NAME_SINGLE "ti-connectivity/wl128x-fw-5-sr.bin" -#define WL128X_PLT_FW_NAME "ti-connectivity/wl128x-fw-5-plt.bin" +#define WL128X_FW_NAME_MULTI "ti-connectivity/wl128x-fw-4-mr.bin" +#define WL128X_FW_NAME_SINGLE "ti-connectivity/wl128x-fw-4-sr.bin" +#define WL128X_PLT_FW_NAME "ti-connectivity/wl128x-fw-4-plt.bin" static int wl127x_prepare_read(struct wl1271 *wl, u32 rx_desc, u32 len) { @@ -637,7 +637,6 @@ static int wl12xx_identify_chip(struct wl1271 *wl) wl->chip.id); wl->quirks |= WLCORE_QUIRK_LEGACY_NVS | - WLCORE_QUIRK_DUAL_PROBE_TMPL | WLCORE_QUIRK_TKIP_HEADER_SPACE; wl->sr_fw_name = WL127X_FW_NAME_SINGLE; wl->mr_fw_name = WL127X_FW_NAME_MULTI; @@ -647,9 +646,6 @@ static int wl12xx_identify_chip(struct wl1271 *wl) /* read data preparation is only needed by wl127x */ wl->ops->prepare_read = wl127x_prepare_read; - wlcore_set_min_fw_ver(wl, WL127X_CHIP_VER, WL127X_IFTYPE_VER, - WL127X_MAJOR_VER, WL127X_SUBTYPE_VER, - WL127X_MINOR_VER); break; case CHIP_ID_1271_PG20: @@ -657,7 +653,6 @@ static int wl12xx_identify_chip(struct wl1271 *wl) wl->chip.id); wl->quirks |= WLCORE_QUIRK_LEGACY_NVS | - WLCORE_QUIRK_DUAL_PROBE_TMPL | WLCORE_QUIRK_TKIP_HEADER_SPACE; wl->plt_fw_name = WL127X_PLT_FW_NAME; wl->sr_fw_name = WL127X_FW_NAME_SINGLE; @@ -668,9 +663,6 @@ static int wl12xx_identify_chip(struct wl1271 *wl) /* read data preparation is only needed by wl127x */ wl->ops->prepare_read = wl127x_prepare_read; - wlcore_set_min_fw_ver(wl, WL127X_CHIP_VER, WL127X_IFTYPE_VER, - WL127X_MAJOR_VER, WL127X_SUBTYPE_VER, - WL127X_MINOR_VER); break; case CHIP_ID_1283_PG20: @@ -682,12 +674,8 @@ static int wl12xx_identify_chip(struct wl1271 *wl) /* wl128x requires TX blocksize alignment */ wl->quirks |= WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN | - WLCORE_QUIRK_DUAL_PROBE_TMPL | WLCORE_QUIRK_TKIP_HEADER_SPACE; - wlcore_set_min_fw_ver(wl, WL128X_CHIP_VER, WL128X_IFTYPE_VER, - WL128X_MAJOR_VER, WL128X_SUBTYPE_VER, - WL128X_MINOR_VER); break; case CHIP_ID_1283_PG10: default: diff --git a/trunk/drivers/net/wireless/ti/wl12xx/wl12xx.h b/trunk/drivers/net/wireless/ti/wl12xx/wl12xx.h index 26990fb4edea..de1132410876 100644 --- a/trunk/drivers/net/wireless/ti/wl12xx/wl12xx.h +++ b/trunk/drivers/net/wireless/ti/wl12xx/wl12xx.h @@ -24,20 +24,6 @@ #include "conf.h" -/* minimum FW required for driver for wl127x */ -#define WL127X_CHIP_VER 6 -#define WL127X_IFTYPE_VER 3 -#define WL127X_MAJOR_VER 10 -#define WL127X_SUBTYPE_VER 2 -#define WL127X_MINOR_VER 115 - -/* minimum FW required for driver for wl128x */ -#define WL128X_CHIP_VER 7 -#define WL128X_IFTYPE_VER 3 -#define WL128X_MAJOR_VER 10 -#define WL128X_SUBTYPE_VER 2 -#define WL128X_MINOR_VER 115 - struct wl127x_rx_mem_pool_addr { u32 addr; u32 addr_extra; diff --git a/trunk/drivers/net/wireless/ti/wl18xx/main.c b/trunk/drivers/net/wireless/ti/wl18xx/main.c index b378b34c4a6a..5e583be8f674 100644 --- a/trunk/drivers/net/wireless/ti/wl18xx/main.c +++ b/trunk/drivers/net/wireless/ti/wl18xx/main.c @@ -369,7 +369,7 @@ static struct wlcore_conf wl18xx_conf = { .psm_entry_retries = 8, .psm_exit_retries = 16, .psm_entry_nullfunc_retries = 3, - .dynamic_ps_timeout = 1500, + .dynamic_ps_timeout = 200, .forced_ps = false, .keep_alive_interval = 55000, .max_listen_interval = 20, @@ -609,12 +609,7 @@ static int wl18xx_identify_chip(struct wl1271 *wl) wl->quirks |= WLCORE_QUIRK_NO_ELP | WLCORE_QUIRK_RX_BLOCKSIZE_ALIGN | WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN | - WLCORE_QUIRK_NO_SCHED_SCAN_WHILE_CONN | WLCORE_QUIRK_TX_PAD_LAST_FRAME; - - wlcore_set_min_fw_ver(wl, WL18XX_CHIP_VER, WL18XX_IFTYPE_VER, - WL18XX_MAJOR_VER, WL18XX_SUBTYPE_VER, - WL18XX_MINOR_VER); break; case CHIP_ID_185x_PG10: wl1271_warning("chip id 0x%x (185x PG10) is deprecated", @@ -1025,24 +1020,14 @@ static u32 wl18xx_sta_get_ap_rate_mask(struct wl1271 *wl, static u32 wl18xx_ap_get_mimo_wide_rate_mask(struct wl1271 *wl, struct wl12xx_vif *wlvif) { - struct wl18xx_priv *priv = wl->priv; - - if (wlvif->channel_type == NL80211_CHAN_HT40MINUS || - wlvif->channel_type == NL80211_CHAN_HT40PLUS) { + if ((wlvif->channel_type == NL80211_CHAN_HT40MINUS || + wlvif->channel_type == NL80211_CHAN_HT40PLUS) && + !strcmp(ht_mode_param, "wide")) { wl1271_debug(DEBUG_ACX, "using wide channel rate mask"); - - /* sanity check - we don't support this */ - if (WARN_ON(wlvif->band != IEEE80211_BAND_5GHZ)) - return 0; - return CONF_TX_RATE_USE_WIDE_CHAN; - } else if (priv->conf.phy.number_of_assembled_ant2_4 >= 2 && - wlvif->band == IEEE80211_BAND_2GHZ) { + } else if (!strcmp(ht_mode_param, "mimo")) { wl1271_debug(DEBUG_ACX, "using MIMO rate mask"); - /* - * we don't care about HT channel here - if a peer doesn't - * support MIMO, we won't enable it in its rates - */ + return CONF_TX_MIMO_RATES; } else { return 0; diff --git a/trunk/drivers/net/wireless/ti/wl18xx/wl18xx.h b/trunk/drivers/net/wireless/ti/wl18xx/wl18xx.h index 6452396fa1d4..bc67a4750615 100644 --- a/trunk/drivers/net/wireless/ti/wl18xx/wl18xx.h +++ b/trunk/drivers/net/wireless/ti/wl18xx/wl18xx.h @@ -24,13 +24,6 @@ #include "conf.h" -/* minimum FW required for driver */ -#define WL18XX_CHIP_VER 8 -#define WL18XX_IFTYPE_VER 2 -#define WL18XX_MAJOR_VER 0 -#define WL18XX_SUBTYPE_VER 0 -#define WL18XX_MINOR_VER 100 - #define WL18XX_CMD_MAX_SIZE 740 struct wl18xx_priv { diff --git a/trunk/drivers/net/wireless/ti/wlcore/boot.c b/trunk/drivers/net/wireless/ti/wlcore/boot.c index 375ea574eafb..8965960b841a 100644 --- a/trunk/drivers/net/wireless/ti/wlcore/boot.c +++ b/trunk/drivers/net/wireless/ti/wlcore/boot.c @@ -81,53 +81,6 @@ static int wlcore_boot_parse_fw_ver(struct wl1271 *wl, return ret; } -static int wlcore_validate_fw_ver(struct wl1271 *wl) -{ - unsigned int *fw_ver = wl->chip.fw_ver; - unsigned int *min_ver = wl->min_fw_ver; - - /* the chip must be exactly equal */ - if (min_ver[FW_VER_CHIP] != fw_ver[FW_VER_CHIP]) - goto fail; - - /* always check the next digit if all previous ones are equal */ - - if (min_ver[FW_VER_IF_TYPE] < fw_ver[FW_VER_IF_TYPE]) - goto out; - else if (min_ver[FW_VER_IF_TYPE] > fw_ver[FW_VER_IF_TYPE]) - goto fail; - - if (min_ver[FW_VER_MAJOR] < fw_ver[FW_VER_MAJOR]) - goto out; - else if (min_ver[FW_VER_MAJOR] > fw_ver[FW_VER_MAJOR]) - goto fail; - - if (min_ver[FW_VER_SUBTYPE] < fw_ver[FW_VER_SUBTYPE]) - goto out; - else if (min_ver[FW_VER_SUBTYPE] > fw_ver[FW_VER_SUBTYPE]) - goto fail; - - if (min_ver[FW_VER_MINOR] < fw_ver[FW_VER_MINOR]) - goto out; - else if (min_ver[FW_VER_MINOR] > fw_ver[FW_VER_MINOR]) - goto fail; - -out: - return 0; - -fail: - wl1271_error("Your WiFi FW version (%u.%u.%u.%u.%u) is outdated.\n" - "Please use at least FW %u.%u.%u.%u.%u.\n" - "You can get more information at:\n" - "http://wireless.kernel.org/en/users/Drivers/wl12xx", - fw_ver[FW_VER_CHIP], fw_ver[FW_VER_IF_TYPE], - fw_ver[FW_VER_MAJOR], fw_ver[FW_VER_SUBTYPE], - fw_ver[FW_VER_MINOR], min_ver[FW_VER_CHIP], - min_ver[FW_VER_IF_TYPE], min_ver[FW_VER_MAJOR], - min_ver[FW_VER_SUBTYPE], min_ver[FW_VER_MINOR]); - return -EINVAL; -} - static int wlcore_boot_static_data(struct wl1271 *wl) { struct wl1271_static_data *static_data; @@ -148,10 +101,6 @@ static int wlcore_boot_static_data(struct wl1271 *wl) if (ret < 0) goto out_free; - ret = wlcore_validate_fw_ver(wl); - if (ret < 0) - goto out_free; - ret = wlcore_handle_static_data(wl, static_data); if (ret < 0) goto out_free; @@ -192,7 +141,7 @@ static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf, partition.mem.start = dest; ret = wlcore_set_partition(wl, &partition); if (ret < 0) - goto out; + return ret; /* 10.1 set partition limit and chunk num */ chunk_num = 0; @@ -208,7 +157,7 @@ static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf, partition.mem.start = addr; ret = wlcore_set_partition(wl, &partition); if (ret < 0) - goto out; + return ret; } /* 10.3 upload the chunk */ diff --git a/trunk/drivers/net/wireless/ti/wlcore/cmd.c b/trunk/drivers/net/wireless/ti/wlcore/cmd.c index a23949cdaebc..56c7a2342fdf 100644 --- a/trunk/drivers/net/wireless/ti/wlcore/cmd.c +++ b/trunk/drivers/net/wireless/ti/wlcore/cmd.c @@ -39,7 +39,6 @@ #include "hw_ops.h" #define WL1271_CMD_FAST_POLL_COUNT 50 -#define WL1271_WAIT_EVENT_FAST_POLL_COUNT 20 /* * send command to firmware @@ -139,7 +138,6 @@ static int wl1271_cmd_wait_for_event_or_timeout(struct wl1271 *wl, u32 *events_vector; u32 event; unsigned long timeout_time; - u16 poll_count = 0; int ret = 0; *timeout = false; @@ -158,11 +156,7 @@ static int wl1271_cmd_wait_for_event_or_timeout(struct wl1271 *wl, goto out; } - poll_count++; - if (poll_count < WL1271_WAIT_EVENT_FAST_POLL_COUNT) - usleep_range(50, 51); - else - usleep_range(1000, 5000); + msleep(1); /* read from both event fields */ ret = wlcore_read(wl, wl->mbox_ptr[0], events_vector, @@ -1013,14 +1007,12 @@ int wl1271_cmd_build_ps_poll(struct wl1271 *wl, struct wl12xx_vif *wlvif, int wl12xx_cmd_build_probe_req(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 role_id, u8 band, const u8 *ssid, size_t ssid_len, - const u8 *ie, size_t ie_len, bool sched_scan) + const u8 *ie, size_t ie_len) { struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif); struct sk_buff *skb; int ret; u32 rate; - u16 template_id_2_4 = CMD_TEMPL_CFG_PROBE_REQ_2_4; - u16 template_id_5 = CMD_TEMPL_CFG_PROBE_REQ_5; skb = ieee80211_probereq_get(wl->hw, vif, ssid, ssid_len, ie, ie_len); @@ -1031,20 +1023,14 @@ int wl12xx_cmd_build_probe_req(struct wl1271 *wl, struct wl12xx_vif *wlvif, wl1271_dump(DEBUG_SCAN, "PROBE REQ: ", skb->data, skb->len); - if (!sched_scan && - (wl->quirks & WLCORE_QUIRK_DUAL_PROBE_TMPL)) { - template_id_2_4 = CMD_TEMPL_APP_PROBE_REQ_2_4; - template_id_5 = CMD_TEMPL_APP_PROBE_REQ_5; - } - rate = wl1271_tx_min_rate_get(wl, wlvif->bitrate_masks[band]); if (band == IEEE80211_BAND_2GHZ) ret = wl1271_cmd_template_set(wl, role_id, - template_id_2_4, + CMD_TEMPL_CFG_PROBE_REQ_2_4, skb->data, skb->len, 0, rate); else ret = wl1271_cmd_template_set(wl, role_id, - template_id_5, + CMD_TEMPL_CFG_PROBE_REQ_5, skb->data, skb->len, 0, rate); out: diff --git a/trunk/drivers/net/wireless/ti/wlcore/cmd.h b/trunk/drivers/net/wireless/ti/wlcore/cmd.h index d7d9f801e506..c8a6510c72cb 100644 --- a/trunk/drivers/net/wireless/ti/wlcore/cmd.h +++ b/trunk/drivers/net/wireless/ti/wlcore/cmd.h @@ -58,7 +58,7 @@ int wl1271_cmd_build_ps_poll(struct wl1271 *wl, struct wl12xx_vif *wlvif, int wl12xx_cmd_build_probe_req(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 role_id, u8 band, const u8 *ssid, size_t ssid_len, - const u8 *ie, size_t ie_len, bool sched_scan); + const u8 *ie, size_t ie_len); struct sk_buff *wl1271_cmd_build_ap_probe_req(struct wl1271 *wl, struct wl12xx_vif *wlvif, struct sk_buff *skb); @@ -172,8 +172,8 @@ enum cmd_templ { CMD_TEMPL_PS_POLL, CMD_TEMPL_KLV, CMD_TEMPL_DISCONNECT, - CMD_TEMPL_APP_PROBE_REQ_2_4, - CMD_TEMPL_APP_PROBE_REQ_5, + CMD_TEMPL_PROBE_REQ_2_4, /* for firmware internal use only */ + CMD_TEMPL_PROBE_REQ_5, /* for firmware internal use only */ CMD_TEMPL_BAR, /* for firmware internal use only */ CMD_TEMPL_CTS, /* * For CTS-to-self (FastCTS) mechanism diff --git a/trunk/drivers/net/wireless/ti/wlcore/init.c b/trunk/drivers/net/wireless/ti/wlcore/init.c index a3c867786df8..8a8a8971befa 100644 --- a/trunk/drivers/net/wireless/ti/wlcore/init.c +++ b/trunk/drivers/net/wireless/ti/wlcore/init.c @@ -54,22 +54,6 @@ int wl1271_init_templates_config(struct wl1271 *wl) if (ret < 0) return ret; - if (wl->quirks & WLCORE_QUIRK_DUAL_PROBE_TMPL) { - ret = wl1271_cmd_template_set(wl, WL12XX_INVALID_ROLE_ID, - CMD_TEMPL_APP_PROBE_REQ_2_4, NULL, - WL1271_CMD_TEMPL_MAX_SIZE, - 0, WL1271_RATE_AUTOMATIC); - if (ret < 0) - return ret; - - ret = wl1271_cmd_template_set(wl, WL12XX_INVALID_ROLE_ID, - CMD_TEMPL_APP_PROBE_REQ_5, NULL, - WL1271_CMD_TEMPL_MAX_SIZE, - 0, WL1271_RATE_AUTOMATIC); - if (ret < 0) - return ret; - } - ret = wl1271_cmd_template_set(wl, WL12XX_INVALID_ROLE_ID, CMD_TEMPL_NULL_DATA, NULL, sizeof(struct wl12xx_null_data_template), diff --git a/trunk/drivers/net/wireless/ti/wlcore/io.c b/trunk/drivers/net/wireless/ti/wlcore/io.c index 68e74eefd296..9976219c4e49 100644 --- a/trunk/drivers/net/wireless/ti/wlcore/io.c +++ b/trunk/drivers/net/wireless/ti/wlcore/io.c @@ -60,12 +60,6 @@ void wlcore_enable_interrupts(struct wl1271 *wl) } EXPORT_SYMBOL_GPL(wlcore_enable_interrupts); -void wlcore_synchronize_interrupts(struct wl1271 *wl) -{ - synchronize_irq(wl->irq); -} -EXPORT_SYMBOL_GPL(wlcore_synchronize_interrupts); - int wlcore_translate_addr(struct wl1271 *wl, int addr) { struct wlcore_partition_set *part = &wl->curr_part; diff --git a/trunk/drivers/net/wireless/ti/wlcore/io.h b/trunk/drivers/net/wireless/ti/wlcore/io.h index 259149f36fae..fef80adc8bf5 100644 --- a/trunk/drivers/net/wireless/ti/wlcore/io.h +++ b/trunk/drivers/net/wireless/ti/wlcore/io.h @@ -47,7 +47,6 @@ struct wl1271; void wlcore_disable_interrupts(struct wl1271 *wl); void wlcore_disable_interrupts_nosync(struct wl1271 *wl); void wlcore_enable_interrupts(struct wl1271 *wl); -void wlcore_synchronize_interrupts(struct wl1271 *wl); void wl1271_io_reset(struct wl1271 *wl); void wl1271_io_init(struct wl1271 *wl); @@ -60,12 +59,12 @@ static inline int __must_check wlcore_raw_write(struct wl1271 *wl, int addr, { int ret; - if (test_bit(WL1271_FLAG_IO_FAILED, &wl->flags)) + if (test_bit(WL1271_FLAG_SDIO_FAILED, &wl->flags)) return -EIO; ret = wl->if_ops->write(wl->dev, addr, buf, len, fixed); - if (ret && wl->state != WL1271_STATE_OFF) - set_bit(WL1271_FLAG_IO_FAILED, &wl->flags); + if (ret) + set_bit(WL1271_FLAG_SDIO_FAILED, &wl->flags); return ret; } @@ -76,12 +75,12 @@ static inline int __must_check wlcore_raw_read(struct wl1271 *wl, int addr, { int ret; - if (test_bit(WL1271_FLAG_IO_FAILED, &wl->flags)) + if (test_bit(WL1271_FLAG_SDIO_FAILED, &wl->flags)) return -EIO; ret = wl->if_ops->read(wl->dev, addr, buf, len, fixed); - if (ret && wl->state != WL1271_STATE_OFF) - set_bit(WL1271_FLAG_IO_FAILED, &wl->flags); + if (ret) + set_bit(WL1271_FLAG_SDIO_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 9f04b64dfa33..2240cca597ac 100644 --- a/trunk/drivers/net/wireless/ti/wlcore/main.c +++ b/trunk/drivers/net/wireless/ti/wlcore/main.c @@ -62,7 +62,7 @@ static bool no_recovery; static void __wl1271_op_remove_interface(struct wl1271 *wl, struct ieee80211_vif *vif, bool reset_tx_queues); -static void wlcore_op_stop_locked(struct wl1271 *wl); +static void wl1271_op_stop(struct ieee80211_hw *hw); static void wl1271_free_ap_keys(struct wl1271 *wl, struct wl12xx_vif *wlvif); static int wl12xx_set_authorized(struct wl1271 *wl, @@ -916,16 +916,16 @@ static void wl1271_recovery_work(struct work_struct *work) if (wl->state != WL1271_STATE_ON || wl->plt) goto out_unlock; - if (!test_bit(WL1271_FLAG_INTENDED_FW_RECOVERY, &wl->flags)) { - wl12xx_read_fwlog_panic(wl); - wlcore_print_recovery(wl); - } + wl12xx_read_fwlog_panic(wl); + + wlcore_print_recovery(wl); BUG_ON(bug_on_recovery && !test_bit(WL1271_FLAG_INTENDED_FW_RECOVERY, &wl->flags)); if (no_recovery) { wl1271_info("No recovery (chosen on module load). Fw will remain stuck."); + clear_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags); goto out_unlock; } @@ -956,8 +956,9 @@ static void wl1271_recovery_work(struct work_struct *work) vif = wl12xx_wlvif_to_vif(wlvif); __wl1271_op_remove_interface(wl, vif, false); } - - wlcore_op_stop_locked(wl); + wl->watchdog_recovery = false; + mutex_unlock(&wl->mutex); + wl1271_op_stop(wl->hw); ieee80211_restart_hw(wl->hw); @@ -966,10 +967,9 @@ static void wl1271_recovery_work(struct work_struct *work) * to restart the HW. */ wlcore_wake_queues(wl, WLCORE_QUEUE_STOP_REASON_FW_RESTART); - + return; out_unlock: - wl->watchdog_recovery = false; - clear_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags); + wl->watchdog_recovery = false; mutex_unlock(&wl->mutex); } @@ -1211,9 +1211,7 @@ static void wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) * The workqueue is slow to process the tx_queue and we need stop * the queue here, otherwise the queue will get too long. */ - if (wl->tx_queue_count[q] >= WL1271_TX_QUEUE_HIGH_WATERMARK && - !wlcore_is_queue_stopped_by_reason(wl, q, - WLCORE_QUEUE_STOP_REASON_WATERMARK)) { + if (wl->tx_queue_count[q] >= WL1271_TX_QUEUE_HIGH_WATERMARK) { wl1271_debug(DEBUG_TX, "op_tx: stopping queues for q %d", q); wlcore_stop_queue_locked(wl, q, WLCORE_QUEUE_STOP_REASON_WATERMARK); @@ -1799,15 +1797,33 @@ static int wl1271_op_start(struct ieee80211_hw *hw) return 0; } -static void wlcore_op_stop_locked(struct wl1271 *wl) +static void wl1271_op_stop(struct ieee80211_hw *hw) { + struct wl1271 *wl = hw->priv; int i; + wl1271_debug(DEBUG_MAC80211, "mac80211 stop"); + + /* + * Interrupts must be disabled before setting the state to OFF. + * Otherwise, the interrupt handler might be called and exit without + * reading the interrupt status. + */ + wlcore_disable_interrupts(wl); + mutex_lock(&wl->mutex); if (wl->state == WL1271_STATE_OFF) { if (test_and_clear_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags)) wlcore_enable_interrupts(wl); + mutex_unlock(&wl->mutex); + + /* + * This will not necessarily enable interrupts as interrupts + * may have been disabled when op_stop was called. It will, + * however, balance the above call to disable_interrupts(). + */ + wlcore_enable_interrupts(wl); return; } @@ -1816,16 +1832,8 @@ static void wlcore_op_stop_locked(struct wl1271 *wl) * functions don't perform further work. */ wl->state = WL1271_STATE_OFF; - - /* - * Use the nosync variant to disable interrupts, so the mutex could be - * held while doing so without deadlocking. - */ - wlcore_disable_interrupts_nosync(wl); - mutex_unlock(&wl->mutex); - wlcore_synchronize_interrupts(wl); wl1271_flush_deferred_work(wl); cancel_delayed_work_sync(&wl->scan_complete_work); cancel_work_sync(&wl->netstack_work); @@ -1892,17 +1900,6 @@ static void wlcore_op_stop_locked(struct wl1271 *wl) wl->tx_res_if = NULL; kfree(wl->target_mem_map); wl->target_mem_map = NULL; -} - -static void wlcore_op_stop(struct ieee80211_hw *hw) -{ - struct wl1271 *wl = hw->priv; - - wl1271_debug(DEBUG_MAC80211, "mac80211 stop"); - - mutex_lock(&wl->mutex); - - wlcore_op_stop_locked(wl); mutex_unlock(&wl->mutex); } @@ -4569,7 +4566,7 @@ static int wl12xx_set_bitrate_mask(struct ieee80211_hw *hw, mutex_lock(&wl->mutex); - for (i = 0; i < WLCORE_NUM_BANDS; i++) + for (i = 0; i < IEEE80211_NUM_BANDS; i++) wlvif->bitrate_masks[i] = wl1271_tx_enabled_rates_get(wl, mask->control[i].legacy, @@ -4637,13 +4634,6 @@ static void wl12xx_op_channel_switch(struct ieee80211_hw *hw, mutex_unlock(&wl->mutex); } -static void wlcore_op_flush(struct ieee80211_hw *hw, bool drop) -{ - struct wl1271 *wl = hw->priv; - - wl1271_tx_flush(wl); -} - static bool wl1271_tx_frames_pending(struct ieee80211_hw *hw) { struct wl1271 *wl = hw->priv; @@ -4806,7 +4796,7 @@ static struct ieee80211_supported_band wl1271_band_5ghz = { static const struct ieee80211_ops wl1271_ops = { .start = wl1271_op_start, - .stop = wlcore_op_stop, + .stop = wl1271_op_stop, .add_interface = wl1271_op_add_interface, .remove_interface = wl1271_op_remove_interface, .change_interface = wl12xx_op_change_interface, @@ -4834,7 +4824,6 @@ static const struct ieee80211_ops wl1271_ops = { .tx_frames_pending = wl1271_tx_frames_pending, .set_bitrate_mask = wl12xx_set_bitrate_mask, .channel_switch = wl12xx_op_channel_switch, - .flush = wlcore_op_flush, CFG80211_TESTMODE_CMD(wl1271_tm_cmd) }; @@ -5515,7 +5504,6 @@ int __devinit wlcore_probe(struct wl1271 *wl, struct platform_device *pdev) goto out_free_hw; } -#ifdef CONFIG_PM ret = enable_irq_wake(wl->irq); if (!ret) { wl->irq_wake_enabled = true; @@ -5529,7 +5517,6 @@ int __devinit wlcore_probe(struct wl1271 *wl, struct platform_device *pdev) WL1271_RX_FILTER_MAX_PATTERN_SIZE; } } -#endif disable_irq(wl->irq); ret = wl12xx_get_hw_info(wl); diff --git a/trunk/drivers/net/wireless/ti/wlcore/scan.c b/trunk/drivers/net/wireless/ti/wlcore/scan.c index dbeca1bfbb2c..d9daed53ceb7 100644 --- a/trunk/drivers/net/wireless/ti/wlcore/scan.c +++ b/trunk/drivers/net/wireless/ti/wlcore/scan.c @@ -226,7 +226,7 @@ static int wl1271_scan_send(struct wl1271 *wl, struct ieee80211_vif *vif, cmd->params.role_id, band, wl->scan.ssid, wl->scan.ssid_len, wl->scan.req->ie, - wl->scan.req->ie_len, false); + wl->scan.req->ie_len); if (ret < 0) { wl1271_error("PROBE request template failed"); goto out; @@ -633,7 +633,7 @@ wl12xx_scan_sched_scan_ssid_list(struct wl1271 *wl, for (j = 0; j < cmd->n_ssids; j++) if ((req->ssids[i].ssid_len == - cmd->ssids[j].len) && + req->ssids[j].ssid_len) && !memcmp(req->ssids[i].ssid, cmd->ssids[j].ssid, req->ssids[i].ssid_len)) { @@ -722,7 +722,7 @@ int wl1271_scan_sched_scan_config(struct wl1271 *wl, req->ssids[0].ssid, req->ssids[0].ssid_len, ies->ie[band], - ies->len[band], true); + ies->len[band]); if (ret < 0) { wl1271_error("2.4GHz PROBE request template failed"); goto out; @@ -736,7 +736,7 @@ int wl1271_scan_sched_scan_config(struct wl1271 *wl, req->ssids[0].ssid, req->ssids[0].ssid_len, ies->ie[band], - ies->len[band], true); + ies->len[band]); if (ret < 0) { wl1271_error("5GHz PROBE request template failed"); goto out; @@ -766,8 +766,7 @@ int wl1271_scan_sched_scan_start(struct wl1271 *wl, struct wl12xx_vif *wlvif) if (wlvif->bss_type != BSS_TYPE_STA_BSS) return -EOPNOTSUPP; - if ((wl->quirks & WLCORE_QUIRK_NO_SCHED_SCAN_WHILE_CONN) && - test_bit(WLVIF_FLAG_IN_USE, &wlvif->flags)) + if (test_bit(WLVIF_FLAG_IN_USE, &wlvif->flags)) return -EBUSY; start = kzalloc(sizeof(*start), GFP_KERNEL); diff --git a/trunk/drivers/net/wireless/ti/wlcore/sdio.c b/trunk/drivers/net/wireless/ti/wlcore/sdio.c index 73ace4b2604e..204e69fa9327 100644 --- a/trunk/drivers/net/wireless/ti/wlcore/sdio.c +++ b/trunk/drivers/net/wireless/ti/wlcore/sdio.c @@ -411,3 +411,9 @@ MODULE_PARM_DESC(dump, "Enable sdio read/write dumps."); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Luciano Coelho "); MODULE_AUTHOR("Juuso Oikarinen "); +MODULE_FIRMWARE(WL127X_FW_NAME_SINGLE); +MODULE_FIRMWARE(WL127X_FW_NAME_MULTI); +MODULE_FIRMWARE(WL127X_PLT_FW_NAME); +MODULE_FIRMWARE(WL128X_FW_NAME_SINGLE); +MODULE_FIRMWARE(WL128X_FW_NAME_MULTI); +MODULE_FIRMWARE(WL128X_PLT_FW_NAME); diff --git a/trunk/drivers/net/wireless/ti/wlcore/spi.c b/trunk/drivers/net/wireless/ti/wlcore/spi.c index 8da4ed243ebc..6420abae40ee 100644 --- a/trunk/drivers/net/wireless/ti/wlcore/spi.c +++ b/trunk/drivers/net/wireless/ti/wlcore/spi.c @@ -435,4 +435,10 @@ module_exit(wl1271_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Luciano Coelho "); MODULE_AUTHOR("Juuso Oikarinen "); +MODULE_FIRMWARE(WL127X_FW_NAME_SINGLE); +MODULE_FIRMWARE(WL127X_FW_NAME_MULTI); +MODULE_FIRMWARE(WL127X_PLT_FW_NAME); +MODULE_FIRMWARE(WL128X_FW_NAME_SINGLE); +MODULE_FIRMWARE(WL128X_FW_NAME_MULTI); +MODULE_FIRMWARE(WL128X_PLT_FW_NAME); MODULE_ALIAS("spi:wl1271"); diff --git a/trunk/drivers/net/wireless/ti/wlcore/testmode.c b/trunk/drivers/net/wireless/ti/wlcore/testmode.c index d6f57e2c03cf..eeb339d61d1e 100644 --- a/trunk/drivers/net/wireless/ti/wlcore/testmode.c +++ b/trunk/drivers/net/wireless/ti/wlcore/testmode.c @@ -40,7 +40,7 @@ enum wl1271_tm_commands { WL1271_TM_CMD_CONFIGURE, WL1271_TM_CMD_NVS_PUSH, /* Not in use. Keep to not break ABI */ WL1271_TM_CMD_SET_PLT_MODE, - WL1271_TM_CMD_RECOVER, /* Not in use. Keep to not break ABI */ + WL1271_TM_CMD_RECOVER, WL1271_TM_CMD_GET_MAC, __WL1271_TM_CMD_AFTER_LAST @@ -272,6 +272,15 @@ static int wl1271_tm_cmd_set_plt_mode(struct wl1271 *wl, struct nlattr *tb[]) return ret; } +static int wl1271_tm_cmd_recover(struct wl1271 *wl, struct nlattr *tb[]) +{ + wl1271_debug(DEBUG_TESTMODE, "testmode cmd recover"); + + wl12xx_queue_recovery_work(wl); + + return 0; +} + static int wl12xx_tm_cmd_get_mac(struct wl1271 *wl, struct nlattr *tb[]) { struct sk_buff *skb; @@ -341,6 +350,8 @@ int wl1271_tm_cmd(struct ieee80211_hw *hw, void *data, int len) return wl1271_tm_cmd_configure(wl, tb); case WL1271_TM_CMD_SET_PLT_MODE: return wl1271_tm_cmd_set_plt_mode(wl, tb); + case WL1271_TM_CMD_RECOVER: + return wl1271_tm_cmd_recover(wl, tb); case WL1271_TM_CMD_GET_MAC: return wl12xx_tm_cmd_get_mac(wl, tb); default: diff --git a/trunk/drivers/net/wireless/ti/wlcore/wlcore.h b/trunk/drivers/net/wireless/ti/wlcore/wlcore.h index 27ccc275a1c1..e796974df59b 100644 --- a/trunk/drivers/net/wireless/ti/wlcore/wlcore.h +++ b/trunk/drivers/net/wireless/ti/wlcore/wlcore.h @@ -304,7 +304,7 @@ struct wl1271 { s8 noise; /* bands supported by this instance of wl12xx */ - struct ieee80211_supported_band bands[WLCORE_NUM_BANDS]; + struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS]; /* * wowlan trigger was configured during suspend. @@ -371,7 +371,7 @@ struct wl1271 { u8 hw_min_ht_rate; /* HW HT (11n) capabilities */ - struct ieee80211_sta_ht_cap ht_cap[WLCORE_NUM_BANDS]; + struct ieee80211_sta_ht_cap ht_cap[IEEE80211_NUM_BANDS]; /* size of the private FW status data */ size_t fw_status_priv_len; @@ -390,9 +390,6 @@ struct wl1271 { /* sleep auth value currently configured to FW */ int sleep_auth; - - /* the minimum FW version required for the driver to work */ - unsigned int min_fw_ver[NUM_FW_VER]; }; int __devinit wlcore_probe(struct wl1271 *wl, struct platform_device *pdev); @@ -411,18 +408,6 @@ wlcore_set_ht_cap(struct wl1271 *wl, enum ieee80211_band band, memcpy(&wl->ht_cap[band], ht_cap, sizeof(*ht_cap)); } -static inline void -wlcore_set_min_fw_ver(struct wl1271 *wl, unsigned int chip, - unsigned int iftype, unsigned int major, - unsigned int subtype, unsigned int minor) -{ - wl->min_fw_ver[FW_VER_CHIP] = chip; - wl->min_fw_ver[FW_VER_IF_TYPE] = iftype; - wl->min_fw_ver[FW_VER_MAJOR] = major; - wl->min_fw_ver[FW_VER_SUBTYPE] = subtype; - wl->min_fw_ver[FW_VER_MINOR] = minor; -} - /* Firmware image load chunk size */ #define CHUNK_SIZE 16384 @@ -452,12 +437,6 @@ wlcore_set_min_fw_ver(struct wl1271 *wl, unsigned int chip, /* extra header space is required for TKIP */ #define WLCORE_QUIRK_TKIP_HEADER_SPACE BIT(8) -/* Some firmwares not support sched scans while connected */ -#define WLCORE_QUIRK_NO_SCHED_SCAN_WHILE_CONN BIT(9) - -/* separate probe response templates for one-shot and sched scans */ -#define WLCORE_QUIRK_DUAL_PROBE_TMPL BIT(10) - /* TODO: move to the lower drivers when all usages are abstracted */ #define CHIP_ID_1271_PG10 (0x4030101) #define CHIP_ID_1271_PG20 (0x4030111) diff --git a/trunk/drivers/net/wireless/ti/wlcore/wlcore_i.h b/trunk/drivers/net/wireless/ti/wlcore/wlcore_i.h index 0187eef4fb07..4273a21cdde1 100644 --- a/trunk/drivers/net/wireless/ti/wlcore/wlcore_i.h +++ b/trunk/drivers/net/wireless/ti/wlcore/wlcore_i.h @@ -35,6 +35,15 @@ #include "conf.h" #include "ini.h" +#define WL127X_FW_NAME_MULTI "ti-connectivity/wl127x-fw-4-mr.bin" +#define WL127X_FW_NAME_SINGLE "ti-connectivity/wl127x-fw-4-sr.bin" + +#define WL128X_FW_NAME_MULTI "ti-connectivity/wl128x-fw-4-mr.bin" +#define WL128X_FW_NAME_SINGLE "ti-connectivity/wl128x-fw-4-sr.bin" + +#define WL127X_PLT_FW_NAME "ti-connectivity/wl127x-fw-4-plt.bin" +#define WL128X_PLT_FW_NAME "ti-connectivity/wl128x-fw-4-plt.bin" + /* * wl127x and wl128x are using the same NVS file name. However, the * ini parameters between them are different. The driver validates @@ -62,9 +71,6 @@ #define WL12XX_INVALID_ROLE_ID 0xff #define WL12XX_INVALID_LINK_ID 0xff -/* the driver supports the 2.4Ghz and 5Ghz bands */ -#define WLCORE_NUM_BANDS 2 - #define WL12XX_MAX_RATE_POLICIES 16 /* Defined by FW as 0. Will not be freed or allocated. */ @@ -241,7 +247,7 @@ enum wl12xx_flags { WL1271_FLAG_RECOVERY_IN_PROGRESS, WL1271_FLAG_VIF_CHANGE_IN_PROGRESS, WL1271_FLAG_INTENDED_FW_RECOVERY, - WL1271_FLAG_IO_FAILED, + WL1271_FLAG_SDIO_FAILED, }; enum wl12xx_vif_flags { @@ -363,7 +369,7 @@ struct wl12xx_vif { int channel; enum nl80211_channel_type channel_type; - u32 bitrate_masks[WLCORE_NUM_BANDS]; + u32 bitrate_masks[IEEE80211_NUM_BANDS]; u32 basic_rate_set; /* diff --git a/trunk/drivers/nfc/nfcwilink.c b/trunk/drivers/nfc/nfcwilink.c index e7fd4938f9bc..1f74a77d040d 100644 --- a/trunk/drivers/nfc/nfcwilink.c +++ b/trunk/drivers/nfc/nfcwilink.c @@ -535,10 +535,9 @@ static int nfcwilink_probe(struct platform_device *pdev) drv->pdev = pdev; protocols = NFC_PROTO_JEWEL_MASK - | NFC_PROTO_MIFARE_MASK | NFC_PROTO_FELICA_MASK - | NFC_PROTO_ISO14443_MASK - | NFC_PROTO_ISO14443_B_MASK - | NFC_PROTO_NFC_DEP_MASK; + | NFC_PROTO_MIFARE_MASK | NFC_PROTO_FELICA_MASK + | NFC_PROTO_ISO14443_MASK + | NFC_PROTO_NFC_DEP_MASK; drv->ndev = nci_allocate_device(&nfcwilink_ops, protocols, diff --git a/trunk/drivers/nfc/pn533.c b/trunk/drivers/nfc/pn533.c index d606f52fec84..9ac829e22e73 100644 --- a/trunk/drivers/nfc/pn533.c +++ b/trunk/drivers/nfc/pn533.c @@ -38,44 +38,9 @@ #define SCM_VENDOR_ID 0x4E6 #define SCL3711_PRODUCT_ID 0x5591 -#define SONY_VENDOR_ID 0x054c -#define PASORI_PRODUCT_ID 0x02e1 - -#define PN533_QUIRKS_TYPE_A BIT(0) -#define PN533_QUIRKS_TYPE_F BIT(1) -#define PN533_QUIRKS_DEP BIT(2) -#define PN533_QUIRKS_RAW_EXCHANGE BIT(3) - -#define PN533_DEVICE_STD 0x1 -#define PN533_DEVICE_PASORI 0x2 - -#define PN533_ALL_PROTOCOLS (NFC_PROTO_JEWEL_MASK | NFC_PROTO_MIFARE_MASK |\ - NFC_PROTO_FELICA_MASK | NFC_PROTO_ISO14443_MASK |\ - NFC_PROTO_NFC_DEP_MASK |\ - NFC_PROTO_ISO14443_B_MASK) - -#define PN533_NO_TYPE_B_PROTOCOLS (NFC_PROTO_JEWEL_MASK | \ - NFC_PROTO_MIFARE_MASK | \ - NFC_PROTO_FELICA_MASK | \ - NFC_PROTO_ISO14443_MASK | \ - NFC_PROTO_NFC_DEP_MASK) - static const struct usb_device_id pn533_table[] = { - { .match_flags = USB_DEVICE_ID_MATCH_DEVICE, - .idVendor = PN533_VENDOR_ID, - .idProduct = PN533_PRODUCT_ID, - .driver_info = PN533_DEVICE_STD, - }, - { .match_flags = USB_DEVICE_ID_MATCH_DEVICE, - .idVendor = SCM_VENDOR_ID, - .idProduct = SCL3711_PRODUCT_ID, - .driver_info = PN533_DEVICE_STD, - }, - { .match_flags = USB_DEVICE_ID_MATCH_DEVICE, - .idVendor = SONY_VENDOR_ID, - .idProduct = PASORI_PRODUCT_ID, - .driver_info = PN533_DEVICE_PASORI, - }, + { USB_DEVICE(PN533_VENDOR_ID, PN533_PRODUCT_ID) }, + { USB_DEVICE(SCM_VENDOR_ID, SCL3711_PRODUCT_ID) }, { } }; MODULE_DEVICE_TABLE(usb, pn533_table); @@ -107,7 +72,6 @@ MODULE_DEVICE_TABLE(usb, pn533_table); #define PN533_CMD_GET_FIRMWARE_VERSION 0x02 #define PN533_CMD_RF_CONFIGURATION 0x32 #define PN533_CMD_IN_DATA_EXCHANGE 0x40 -#define PN533_CMD_IN_COMM_THRU 0x42 #define PN533_CMD_IN_LIST_PASSIVE_TARGET 0x4A #define PN533_CMD_IN_ATR 0x50 #define PN533_CMD_IN_RELEASE 0x52 @@ -145,7 +109,6 @@ struct pn533_fw_version { /* PN533_CMD_RF_CONFIGURATION */ #define PN533_CFGITEM_TIMING 0x02 #define PN533_CFGITEM_MAX_RETRIES 0x05 -#define PN533_CFGITEM_PASORI 0x82 #define PN533_CONFIG_TIMING_102 0xb #define PN533_CONFIG_TIMING_204 0xc @@ -381,8 +344,6 @@ struct pn533 { u8 tgt_available_prots; u8 tgt_active_prot; u8 tgt_mode; - - u32 device_type; }; struct pn533_frame { @@ -989,7 +950,7 @@ static int pn533_target_found_type_b(struct nfc_target *nfc_tgt, u8 *tgt_data, if (!pn533_target_type_b_is_valid(tgt_type_b, tgt_data_len)) return -EPROTO; - nfc_tgt->supported_protocols = NFC_PROTO_ISO14443_B_MASK; + nfc_tgt->supported_protocols = NFC_PROTO_ISO14443_MASK; return 0; } @@ -1096,7 +1057,7 @@ static void pn533_poll_create_mod_list(struct pn533 *dev, if (im_protocols & NFC_PROTO_JEWEL_MASK) pn533_poll_add_mod(dev, PN533_POLL_MOD_106KBPS_JEWEL); - if (im_protocols & NFC_PROTO_ISO14443_B_MASK) + if (im_protocols & NFC_PROTO_ISO14443_MASK) pn533_poll_add_mod(dev, PN533_POLL_MOD_847KBPS_B); if (tm_protocols) @@ -1807,30 +1768,13 @@ static int pn533_build_tx_frame(struct pn533 *dev, struct sk_buff *skb, } if (target == true) { - switch (dev->device_type) { - case PN533_DEVICE_PASORI: - if (dev->tgt_active_prot == NFC_PROTO_FELICA) { - skb_push(skb, PN533_CMD_DATAEXCH_HEAD_LEN - 1); - out_frame = (struct pn533_frame *) skb->data; - pn533_tx_frame_init(out_frame, - PN533_CMD_IN_COMM_THRU); - - break; - } - - default: - skb_push(skb, PN533_CMD_DATAEXCH_HEAD_LEN); - out_frame = (struct pn533_frame *) skb->data; - pn533_tx_frame_init(out_frame, - PN533_CMD_IN_DATA_EXCHANGE); - tg = 1; - memcpy(PN533_FRAME_CMD_PARAMS_PTR(out_frame), - &tg, sizeof(u8)); - out_frame->datalen += sizeof(u8); - - break; - } + skb_push(skb, PN533_CMD_DATAEXCH_HEAD_LEN); + out_frame = (struct pn533_frame *) skb->data; + pn533_tx_frame_init(out_frame, PN533_CMD_IN_DATA_EXCHANGE); + tg = 1; + memcpy(PN533_FRAME_CMD_PARAMS_PTR(out_frame), &tg, sizeof(u8)); + out_frame->datalen += sizeof(u8); } else { skb_push(skb, PN533_CMD_DATAEXCH_HEAD_LEN - 1); out_frame = (struct pn533_frame *) skb->data; @@ -2157,28 +2101,7 @@ static int pn533_set_configuration(struct pn533 *dev, u8 cfgitem, u8 *cfgdata, return rc; } -static int pn533_fw_reset(struct pn533 *dev) -{ - int rc; - u8 *params; - - nfc_dev_dbg(&dev->interface->dev, "%s", __func__); - - pn533_tx_frame_init(dev->out_frame, 0x18); - - params = PN533_FRAME_CMD_PARAMS_PTR(dev->out_frame); - params[0] = 0x1; - dev->out_frame->datalen += 1; - - pn533_tx_frame_finish(dev->out_frame); - - rc = pn533_send_cmd_frame_sync(dev, dev->out_frame, dev->in_frame, - dev->in_maxlen); - - return rc; -} - -static struct nfc_ops pn533_nfc_ops = { +struct nfc_ops pn533_nfc_ops = { .dev_up = NULL, .dev_down = NULL, .dep_link_up = pn533_dep_link_up, @@ -2191,84 +2114,6 @@ static struct nfc_ops pn533_nfc_ops = { .tm_send = pn533_tm_send, }; -static int pn533_setup(struct pn533 *dev) -{ - struct pn533_config_max_retries max_retries; - struct pn533_config_timing timing; - u8 pasori_cfg[3] = {0x08, 0x01, 0x08}; - int rc; - - switch (dev->device_type) { - case PN533_DEVICE_STD: - max_retries.mx_rty_atr = PN533_CONFIG_MAX_RETRIES_ENDLESS; - max_retries.mx_rty_psl = 2; - max_retries.mx_rty_passive_act = - PN533_CONFIG_MAX_RETRIES_NO_RETRY; - - timing.rfu = PN533_CONFIG_TIMING_102; - timing.atr_res_timeout = PN533_CONFIG_TIMING_204; - timing.dep_timeout = PN533_CONFIG_TIMING_409; - - break; - - case PN533_DEVICE_PASORI: - max_retries.mx_rty_atr = 0x2; - max_retries.mx_rty_psl = 0x1; - max_retries.mx_rty_passive_act = - PN533_CONFIG_MAX_RETRIES_NO_RETRY; - - timing.rfu = PN533_CONFIG_TIMING_102; - timing.atr_res_timeout = PN533_CONFIG_TIMING_102; - timing.dep_timeout = PN533_CONFIG_TIMING_204; - - break; - - default: - nfc_dev_err(&dev->interface->dev, "Unknown device type %d\n", - dev->device_type); - return -EINVAL; - } - - rc = pn533_set_configuration(dev, PN533_CFGITEM_MAX_RETRIES, - (u8 *)&max_retries, sizeof(max_retries)); - if (rc) { - nfc_dev_err(&dev->interface->dev, - "Error on setting MAX_RETRIES config"); - return rc; - } - - - rc = pn533_set_configuration(dev, PN533_CFGITEM_TIMING, - (u8 *)&timing, sizeof(timing)); - if (rc) { - nfc_dev_err(&dev->interface->dev, - "Error on setting RF timings"); - return rc; - } - - switch (dev->device_type) { - case PN533_DEVICE_STD: - break; - - case PN533_DEVICE_PASORI: - pn533_fw_reset(dev); - - rc = pn533_set_configuration(dev, PN533_CFGITEM_PASORI, - pasori_cfg, 3); - if (rc) { - nfc_dev_err(&dev->interface->dev, - "Error while settings PASORI config"); - return rc; - } - - pn533_fw_reset(dev); - - break; - } - - return 0; -} - static int pn533_probe(struct usb_interface *interface, const struct usb_device_id *id) { @@ -2276,6 +2121,8 @@ static int pn533_probe(struct usb_interface *interface, struct pn533 *dev; struct usb_host_interface *iface_desc; struct usb_endpoint_descriptor *endpoint; + struct pn533_config_max_retries max_retries; + struct pn533_config_timing timing; int in_endpoint = 0; int out_endpoint = 0; int rc = -ENOMEM; @@ -2361,22 +2208,10 @@ static int pn533_probe(struct usb_interface *interface, nfc_dev_info(&dev->interface->dev, "NXP PN533 firmware ver %d.%d now" " attached", fw_ver->ver, fw_ver->rev); - dev->device_type = id->driver_info; - switch (dev->device_type) { - case PN533_DEVICE_STD: - protocols = PN533_ALL_PROTOCOLS; - break; - - case PN533_DEVICE_PASORI: - protocols = PN533_NO_TYPE_B_PROTOCOLS; - break; - - default: - nfc_dev_err(&dev->interface->dev, "Unknown device type %d\n", - dev->device_type); - rc = -EINVAL; - goto destroy_wq; - } + protocols = NFC_PROTO_JEWEL_MASK + | NFC_PROTO_MIFARE_MASK | NFC_PROTO_FELICA_MASK + | NFC_PROTO_ISO14443_MASK + | NFC_PROTO_NFC_DEP_MASK; dev->nfc_dev = nfc_allocate_device(&pn533_nfc_ops, protocols, PN533_CMD_DATAEXCH_HEAD_LEN, @@ -2391,9 +2226,30 @@ static int pn533_probe(struct usb_interface *interface, if (rc) goto free_nfc_dev; - rc = pn533_setup(dev); - if (rc) + max_retries.mx_rty_atr = PN533_CONFIG_MAX_RETRIES_ENDLESS; + max_retries.mx_rty_psl = 2; + max_retries.mx_rty_passive_act = PN533_CONFIG_MAX_RETRIES_NO_RETRY; + + rc = pn533_set_configuration(dev, PN533_CFGITEM_MAX_RETRIES, + (u8 *) &max_retries, sizeof(max_retries)); + + if (rc) { + nfc_dev_err(&dev->interface->dev, "Error on setting MAX_RETRIES" + " config"); + goto unregister_nfc_dev; + } + + timing.rfu = PN533_CONFIG_TIMING_102; + timing.atr_res_timeout = PN533_CONFIG_TIMING_204; + timing.dep_timeout = PN533_CONFIG_TIMING_409; + + rc = pn533_set_configuration(dev, PN533_CFGITEM_TIMING, + (u8 *) &timing, sizeof(timing)); + if (rc) { + nfc_dev_err(&dev->interface->dev, + "Error on setting RF timings"); goto unregister_nfc_dev; + } return 0; diff --git a/trunk/drivers/nfc/pn544_hci.c b/trunk/drivers/nfc/pn544_hci.c index aa71807189ba..457eac35dc74 100644 --- a/trunk/drivers/nfc/pn544_hci.c +++ b/trunk/drivers/nfc/pn544_hci.c @@ -108,22 +108,16 @@ enum pn544_state { #define PN544_NFC_WI_MGMT_GATE 0xA1 -static struct nfc_hci_gate pn544_gates[] = { - {NFC_HCI_ADMIN_GATE, NFC_HCI_INVALID_PIPE}, - {NFC_HCI_LOOPBACK_GATE, NFC_HCI_INVALID_PIPE}, - {NFC_HCI_ID_MGMT_GATE, NFC_HCI_INVALID_PIPE}, - {NFC_HCI_LINK_MGMT_GATE, NFC_HCI_INVALID_PIPE}, - {NFC_HCI_RF_READER_B_GATE, NFC_HCI_INVALID_PIPE}, - {NFC_HCI_RF_READER_A_GATE, NFC_HCI_INVALID_PIPE}, - {PN544_SYS_MGMT_GATE, NFC_HCI_INVALID_PIPE}, - {PN544_SWP_MGMT_GATE, NFC_HCI_INVALID_PIPE}, - {PN544_POLLING_LOOP_MGMT_GATE, NFC_HCI_INVALID_PIPE}, - {PN544_NFC_WI_MGMT_GATE, NFC_HCI_INVALID_PIPE}, - {PN544_RF_READER_F_GATE, NFC_HCI_INVALID_PIPE}, - {PN544_RF_READER_JEWEL_GATE, NFC_HCI_INVALID_PIPE}, - {PN544_RF_READER_ISO15693_GATE, NFC_HCI_INVALID_PIPE}, - {PN544_RF_READER_NFCIP1_INITIATOR_GATE, NFC_HCI_INVALID_PIPE}, - {PN544_RF_READER_NFCIP1_TARGET_GATE, NFC_HCI_INVALID_PIPE} +static u8 pn544_custom_gates[] = { + PN544_SYS_MGMT_GATE, + PN544_SWP_MGMT_GATE, + PN544_POLLING_LOOP_MGMT_GATE, + PN544_NFC_WI_MGMT_GATE, + PN544_RF_READER_F_GATE, + PN544_RF_READER_JEWEL_GATE, + PN544_RF_READER_ISO15693_GATE, + PN544_RF_READER_NFCIP1_INITIATOR_GATE, + PN544_RF_READER_NFCIP1_TARGET_GATE }; /* Largest headroom needed for outgoing custom commands */ @@ -383,9 +377,6 @@ static int pn544_hci_open(struct nfc_shdlc *shdlc) r = pn544_hci_enable(info, HCI_MODE); - if (r == 0) - info->state = PN544_ST_READY; - out: mutex_unlock(&info->info_lock); return r; @@ -402,8 +393,6 @@ static void pn544_hci_close(struct nfc_shdlc *shdlc) pn544_hci_disable(info); - info->state = PN544_ST_COLD; - out: mutex_unlock(&info->info_lock); } @@ -855,9 +844,10 @@ static int __devinit pn544_hci_probe(struct i2c_client *client, goto err_rti; } - init_data.gate_count = ARRAY_SIZE(pn544_gates); + init_data.gate_count = ARRAY_SIZE(pn544_custom_gates); - memcpy(init_data.gates, pn544_gates, sizeof(pn544_gates)); + memcpy(init_data.gates, pn544_custom_gates, + ARRAY_SIZE(pn544_custom_gates)); /* * TODO: Session id must include the driver name + some bus addr @@ -869,7 +859,6 @@ static int __devinit pn544_hci_probe(struct i2c_client *client, NFC_PROTO_MIFARE_MASK | NFC_PROTO_FELICA_MASK | NFC_PROTO_ISO14443_MASK | - NFC_PROTO_ISO14443_B_MASK | NFC_PROTO_NFC_DEP_MASK; info->shdlc = nfc_shdlc_allocate(&pn544_shdlc_ops, diff --git a/trunk/drivers/s390/net/qeth_l2_main.c b/trunk/drivers/s390/net/qeth_l2_main.c index b09355c14ee1..426986518e96 100644 --- a/trunk/drivers/s390/net/qeth_l2_main.c +++ b/trunk/drivers/s390/net/qeth_l2_main.c @@ -647,7 +647,7 @@ static int qeth_l2_request_initial_mac(struct qeth_card *card) } QETH_DBF_HEX(SETUP, 2, card->dev->dev_addr, OSA_ADDR_LEN); } else { - eth_random_addr(card->dev->dev_addr); + random_ether_addr(card->dev->dev_addr); memcpy(card->dev->dev_addr, vendor_pre, 3); } return 0; diff --git a/trunk/drivers/s390/net/qeth_l3_main.c b/trunk/drivers/s390/net/qeth_l3_main.c index bada7f66c146..73ac63d901c9 100644 --- a/trunk/drivers/s390/net/qeth_l3_main.c +++ b/trunk/drivers/s390/net/qeth_l3_main.c @@ -1473,7 +1473,7 @@ static int qeth_l3_iqd_read_initial_mac_cb(struct qeth_card *card, memcpy(card->dev->dev_addr, cmd->data.create_destroy_addr.unique_id, ETH_ALEN); else - eth_random_addr(card->dev->dev_addr); + random_ether_addr(card->dev->dev_addr); return 0; } diff --git a/trunk/drivers/scsi/bnx2i/bnx2i_init.c b/trunk/drivers/scsi/bnx2i/bnx2i_init.c index b17637aab9a7..7729a5223b33 100644 --- a/trunk/drivers/scsi/bnx2i/bnx2i_init.c +++ b/trunk/drivers/scsi/bnx2i/bnx2i_init.c @@ -400,7 +400,7 @@ int bnx2i_get_stats(void *handle) if (!stats) return -ENOMEM; - strlcpy(stats->version, DRV_MODULE_VERSION, sizeof(stats->version)); + memcpy(stats->version, DRV_MODULE_VERSION, sizeof(stats->version)); memcpy(stats->mac_add1 + 2, hba->cnic->mac_addr, ETH_ALEN); stats->max_frame_size = hba->netdev->mtu; diff --git a/trunk/drivers/usb/atm/xusbatm.c b/trunk/drivers/usb/atm/xusbatm.c index b3b1bb78b2ef..14ec9f0c5924 100644 --- a/trunk/drivers/usb/atm/xusbatm.c +++ b/trunk/drivers/usb/atm/xusbatm.c @@ -20,7 +20,7 @@ ******************************************************************************/ #include -#include /* for eth_random_addr() */ +#include /* for random_ether_addr() */ #include "usbatm.h" @@ -163,7 +163,7 @@ static int xusbatm_atm_start(struct usbatm_data *usbatm, atm_dbg(usbatm, "%s entered\n", __func__); /* use random MAC as we've no way to get it from the device */ - eth_random_addr(atm_dev->esi); + random_ether_addr(atm_dev->esi); return 0; } diff --git a/trunk/drivers/usb/gadget/u_ether.c b/trunk/drivers/usb/gadget/u_ether.c index b9e1925b2df0..47cf48b51c9d 100644 --- a/trunk/drivers/usb/gadget/u_ether.c +++ b/trunk/drivers/usb/gadget/u_ether.c @@ -724,7 +724,7 @@ static int get_ether_addr(const char *str, u8 *dev_addr) if (is_valid_ether_addr(dev_addr)) return 0; } - eth_random_addr(dev_addr); + random_ether_addr(dev_addr); return 1; } diff --git a/trunk/include/linux/bcma/bcma.h b/trunk/include/linux/bcma/bcma.h index 03b2f30d2ace..12334f9190cb 100644 --- a/trunk/include/linux/bcma/bcma.h +++ b/trunk/include/linux/bcma/bcma.h @@ -137,36 +137,6 @@ struct bcma_host_ops { #define BCMA_MAX_NR_CORES 16 -/* Chip IDs of PCIe devices */ -#define BCMA_CHIP_ID_BCM4313 0x4313 -#define BCMA_CHIP_ID_BCM43224 43224 -#define BCMA_PKG_ID_BCM43224_FAB_CSM 0x8 -#define BCMA_PKG_ID_BCM43224_FAB_SMIC 0xa -#define BCMA_CHIP_ID_BCM43225 43225 -#define BCMA_CHIP_ID_BCM43227 43227 -#define BCMA_CHIP_ID_BCM43228 43228 -#define BCMA_CHIP_ID_BCM43421 43421 -#define BCMA_CHIP_ID_BCM43428 43428 -#define BCMA_CHIP_ID_BCM43431 43431 -#define BCMA_CHIP_ID_BCM43460 43460 -#define BCMA_CHIP_ID_BCM4331 0x4331 -#define BCMA_CHIP_ID_BCM6362 0x6362 -#define BCMA_CHIP_ID_BCM4360 0x4360 -#define BCMA_CHIP_ID_BCM4352 0x4352 - -/* Chip IDs of SoCs */ -#define BCMA_CHIP_ID_BCM4706 0x5300 -#define BCMA_CHIP_ID_BCM4716 0x4716 -#define BCMA_PKG_ID_BCM4716 8 -#define BCMA_PKG_ID_BCM4717 9 -#define BCMA_PKG_ID_BCM4718 10 -#define BCMA_CHIP_ID_BCM47162 47162 -#define BCMA_CHIP_ID_BCM4748 0x4748 -#define BCMA_CHIP_ID_BCM4749 0x4749 -#define BCMA_CHIP_ID_BCM5356 0x5356 -#define BCMA_CHIP_ID_BCM5357 0x5357 -#define BCMA_CHIP_ID_BCM53572 53572 - struct bcma_device { struct bcma_bus *bus; struct bcma_device_id id; diff --git a/trunk/include/linux/bcma/bcma_driver_chipcommon.h b/trunk/include/linux/bcma/bcma_driver_chipcommon.h index fbd0d49dc4d2..8bbfe31fbac8 100644 --- a/trunk/include/linux/bcma/bcma_driver_chipcommon.h +++ b/trunk/include/linux/bcma/bcma_driver_chipcommon.h @@ -88,11 +88,6 @@ #define BCMA_CC_CHIPST_4313_OTP_PRESENT 2 #define BCMA_CC_CHIPST_4331_SPROM_PRESENT 2 #define BCMA_CC_CHIPST_4331_OTP_PRESENT 4 -#define BCMA_CC_CHIPST_4706_PKG_OPTION BIT(0) /* 0: full-featured package 1: low-cost package */ -#define BCMA_CC_CHIPST_4706_SFLASH_PRESENT BIT(1) /* 0: parallel, 1: serial flash is present */ -#define BCMA_CC_CHIPST_4706_SFLASH_TYPE BIT(2) /* 0: 8b-p/ST-s flash, 1: 16b-p/Atmal-s flash */ -#define BCMA_CC_CHIPST_4706_MIPS_BENDIAN BIT(3) /* 0: little, 1: big endian */ -#define BCMA_CC_CHIPST_4706_PCIE1_DISABLE BIT(5) /* PCIE1 enable strap pin */ #define BCMA_CC_JCMD 0x0030 /* Rev >= 10 only */ #define BCMA_CC_JCMD_START 0x80000000 #define BCMA_CC_JCMD_BUSY 0x80000000 @@ -285,15 +280,6 @@ /* 4706 PMU */ #define BCMA_CC_PMU4706_MAINPLL_PLL0 0 -#define BCMA_CC_PMU6_4706_PROCPLL_OFF 4 /* The CPU PLL */ -#define BCMA_CC_PMU6_4706_PROC_P2DIV_MASK 0x000f0000 -#define BCMA_CC_PMU6_4706_PROC_P2DIV_SHIFT 16 -#define BCMA_CC_PMU6_4706_PROC_P1DIV_MASK 0x0000f000 -#define BCMA_CC_PMU6_4706_PROC_P1DIV_SHIFT 12 -#define BCMA_CC_PMU6_4706_PROC_NDIV_INT_MASK 0x00000ff8 -#define BCMA_CC_PMU6_4706_PROC_NDIV_INT_SHIFT 3 -#define BCMA_CC_PMU6_4706_PROC_NDIV_MODE_MASK 0x00000007 -#define BCMA_CC_PMU6_4706_PROC_NDIV_MODE_SHIFT 0 /* ALP clock on pre-PMU chips */ #define BCMA_CC_PMU_ALP_CLOCK 20000000 @@ -322,19 +308,6 @@ #define BCMA_CC_PPL_PCHI_OFF 5 #define BCMA_CC_PPL_PCHI_MASK 0x0000003f -#define BCMA_CC_PMU_PLL_CTL0 0 -#define BCMA_CC_PMU_PLL_CTL1 1 -#define BCMA_CC_PMU_PLL_CTL2 2 -#define BCMA_CC_PMU_PLL_CTL3 3 -#define BCMA_CC_PMU_PLL_CTL4 4 -#define BCMA_CC_PMU_PLL_CTL5 5 - -#define BCMA_CC_PMU1_PLL0_PC0_P1DIV_MASK 0x00f00000 -#define BCMA_CC_PMU1_PLL0_PC0_P1DIV_SHIFT 20 - -#define BCMA_CC_PMU1_PLL0_PC2_NDIV_INT_MASK 0x1ff00000 -#define BCMA_CC_PMU1_PLL0_PC2_NDIV_INT_SHIFT 20 - /* BCM4331 ChipControl numbers. */ #define BCMA_CHIPCTL_4331_BT_COEXIST BIT(0) /* 0 disable */ #define BCMA_CHIPCTL_4331_SECI BIT(1) /* 0 SECI is disabled (JATG functional) */ @@ -348,18 +321,9 @@ #define BCMA_CHIPCTL_4331_OVR_PIPEAUXPWRDOWN BIT(9) /* override core control on pipe_AuxPowerDown */ #define BCMA_CHIPCTL_4331_PCIE_AUXCLKEN BIT(10) /* pcie_auxclkenable */ #define BCMA_CHIPCTL_4331_PCIE_PIPE_PLLDOWN BIT(11) /* pcie_pipe_pllpowerdown */ -#define BCMA_CHIPCTL_4331_EXTPA_EN2 BIT(12) /* 0 ext pa disable, 1 ext pa enabled */ #define BCMA_CHIPCTL_4331_BT_SHD0_ON_GPIO4 BIT(16) /* enable bt_shd0 at gpio4 */ #define BCMA_CHIPCTL_4331_BT_SHD1_ON_GPIO5 BIT(17) /* enable bt_shd1 at gpio5 */ -/* 43224 chip-specific ChipControl register bits */ -#define BCMA_CCTRL_43224_GPIO_TOGGLE 0x8000 /* gpio[3:0] pins as btcoex or s/w gpio */ -#define BCMA_CCTRL_43224A0_12MA_LED_DRIVE 0x00F000F0 /* 12 mA drive strength */ -#define BCMA_CCTRL_43224B0_12MA_LED_DRIVE 0xF0 /* 12 mA drive strength for later 43224s */ - -/* 4313 Chip specific ChipControl register bits */ -#define BCMA_CCTRL_4313_12MA_LED_DRIVE 0x00000007 /* 12 mA drive strengh for later 4313 */ - /* Data for the PMU, if available. * Check availability with ((struct bcma_chipcommon)->capabilities & BCMA_CC_CAP_PMU) */ @@ -447,6 +411,5 @@ extern void bcma_chipco_chipctl_maskset(struct bcma_drv_cc *cc, u32 offset, u32 mask, u32 set); extern void bcma_chipco_regctl_maskset(struct bcma_drv_cc *cc, u32 offset, u32 mask, u32 set); -extern void bcma_pmu_spuravoid_pllupdate(struct bcma_drv_cc *cc, int spuravoid); #endif /* LINUX_BCMA_DRIVER_CC_H_ */ diff --git a/trunk/include/linux/can.h b/trunk/include/linux/can.h index 018055efc034..1a66cf6112ae 100644 --- a/trunk/include/linux/can.h +++ b/trunk/include/linux/can.h @@ -38,9 +38,6 @@ */ typedef __u32 canid_t; -#define CAN_SFF_ID_BITS 11 -#define CAN_EFF_ID_BITS 29 - /* * Controller Area Network Error Message Frame Mask structure * diff --git a/trunk/include/linux/etherdevice.h b/trunk/include/linux/etherdevice.h index d426336d92d9..3d406e0ede6d 100644 --- a/trunk/include/linux/etherdevice.h +++ b/trunk/include/linux/etherdevice.h @@ -124,30 +124,17 @@ static inline bool is_valid_ether_addr(const u8 *addr) } /** - * eth_random_addr - Generate software assigned random Ethernet address + * random_ether_addr - Generate software assigned random Ethernet address * @addr: Pointer to a six-byte array containing the Ethernet address * * Generate a random Ethernet address (MAC) that is not multicast * and has the local assigned bit set. */ -static inline void eth_random_addr(u8 *addr) +static inline void random_ether_addr(u8 *addr) { - get_random_bytes(addr, ETH_ALEN); - addr[0] &= 0xfe; /* clear multicast bit */ - addr[0] |= 0x02; /* set local assignment bit (IEEE802) */ -} - -#define random_ether_addr(addr) eth_random_addr(addr) - -/** - * eth_broadcast_addr - Assign broadcast address - * @addr: Pointer to a six-byte array containing the Ethernet address - * - * Assign the broadcast address to the given address array. - */ -static inline void eth_broadcast_addr(u8 *addr) -{ - memset(addr, 0xff, ETH_ALEN); + get_random_bytes (addr, ETH_ALEN); + addr [0] &= 0xfe; /* clear multicast bit */ + addr [0] |= 0x02; /* set local assignment bit (IEEE802) */ } /** @@ -162,7 +149,7 @@ static inline void eth_broadcast_addr(u8 *addr) static inline void eth_hw_addr_random(struct net_device *dev) { dev->addr_assign_type |= NET_ADDR_RANDOM; - eth_random_addr(dev->dev_addr); + random_ether_addr(dev->dev_addr); } /** diff --git a/trunk/include/linux/ieee80211.h b/trunk/include/linux/ieee80211.h index e02fc682bb68..318fc1f705b1 100644 --- a/trunk/include/linux/ieee80211.h +++ b/trunk/include/linux/ieee80211.h @@ -47,7 +47,6 @@ #define IEEE80211_FCTL_MOREDATA 0x2000 #define IEEE80211_FCTL_PROTECTED 0x4000 #define IEEE80211_FCTL_ORDER 0x8000 -#define IEEE80211_FCTL_CTL_EXT 0x0f00 #define IEEE80211_SCTL_FRAG 0x000F #define IEEE80211_SCTL_SEQ 0xFFF0 @@ -55,7 +54,6 @@ #define IEEE80211_FTYPE_MGMT 0x0000 #define IEEE80211_FTYPE_CTL 0x0004 #define IEEE80211_FTYPE_DATA 0x0008 -#define IEEE80211_FTYPE_EXT 0x000c /* management */ #define IEEE80211_STYPE_ASSOC_REQ 0x0000 @@ -72,7 +70,6 @@ #define IEEE80211_STYPE_ACTION 0x00D0 /* control */ -#define IEEE80211_STYPE_CTL_EXT 0x0060 #define IEEE80211_STYPE_BACK_REQ 0x0080 #define IEEE80211_STYPE_BACK 0x0090 #define IEEE80211_STYPE_PSPOLL 0x00A0 @@ -100,18 +97,6 @@ #define IEEE80211_STYPE_QOS_CFPOLL 0x00E0 #define IEEE80211_STYPE_QOS_CFACKPOLL 0x00F0 -/* extension, added by 802.11ad */ -#define IEEE80211_STYPE_DMG_BEACON 0x0000 - -/* control extension - for IEEE80211_FTYPE_CTL | IEEE80211_STYPE_CTL_EXT */ -#define IEEE80211_CTL_EXT_POLL 0x2000 -#define IEEE80211_CTL_EXT_SPR 0x3000 -#define IEEE80211_CTL_EXT_GRANT 0x4000 -#define IEEE80211_CTL_EXT_DMG_CTS 0x5000 -#define IEEE80211_CTL_EXT_DMG_DTS 0x6000 -#define IEEE80211_CTL_EXT_SSW 0x8000 -#define IEEE80211_CTL_EXT_SSW_FBACK 0x9000 -#define IEEE80211_CTL_EXT_SSW_ACK 0xa000 /* miscellaneous IEEE 802.11 constants */ #define IEEE80211_MAX_FRAG_THRESHOLD 2352 @@ -1107,73 +1092,6 @@ struct ieee80211_ht_operation { #define WLAN_HT_SMPS_CONTROL_STATIC 1 #define WLAN_HT_SMPS_CONTROL_DYNAMIC 3 -#define VHT_MCS_SUPPORTED_SET_SIZE 8 - -struct ieee80211_vht_capabilities { - __le32 vht_capabilities_info; - u8 vht_supported_mcs_set[VHT_MCS_SUPPORTED_SET_SIZE]; -} __packed; - -struct ieee80211_vht_operation { - u8 vht_op_info_chwidth; - u8 vht_op_info_chan_center_freq_seg1_idx; - u8 vht_op_info_chan_center_freq_seg2_idx; - __le16 vht_basic_mcs_set; -} __packed; - -/** - * struct ieee80211_vht_mcs_info - VHT MCS information - * @rx_mcs_map: RX MCS map 2 bits for each stream, total 8 streams - * @rx_highest: Indicates highest long GI VHT PPDU data rate - * STA can receive. Rate expressed in units of 1 Mbps. - * If this field is 0 this value should not be used to - * consider the highest RX data rate supported. - * @tx_mcs_map: TX MCS map 2 bits for each stream, total 8 streams - * @tx_highest: Indicates highest long GI VHT PPDU data rate - * STA can transmit. Rate expressed in units of 1 Mbps. - * If this field is 0 this value should not be used to - * consider the highest TX data rate supported. - */ -struct ieee80211_vht_mcs_info { - __le16 rx_mcs_map; - __le16 rx_highest; - __le16 tx_mcs_map; - __le16 tx_highest; -} __packed; - -#define IEEE80211_VHT_MCS_ZERO_TO_SEVEN_SUPPORT 0 -#define IEEE80211_VHT_MCS_ZERO_TO_EIGHT_SUPPORT 1 -#define IEEE80211_VHT_MCS_ZERO_TO_NINE_SUPPORT 2 -#define IEEE80211_VHT_MCS_NOT_SUPPORTED 3 - -/* 802.11ac VHT Capabilities */ -#define IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895 0x00000000 -#define IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991 0x00000001 -#define IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 0x00000002 -#define IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ 0x00000004 -#define IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ 0x00000008 -#define IEEE80211_VHT_CAP_RXLDPC 0x00000010 -#define IEEE80211_VHT_CAP_SHORT_GI_80 0x00000020 -#define IEEE80211_VHT_CAP_SHORT_GI_160 0x00000040 -#define IEEE80211_VHT_CAP_TXSTBC 0x00000080 -#define IEEE80211_VHT_CAP_RXSTBC_1 0x00000100 -#define IEEE80211_VHT_CAP_RXSTBC_2 0x00000200 -#define IEEE80211_VHT_CAP_RXSTBC_3 0x00000300 -#define IEEE80211_VHT_CAP_RXSTBC_4 0x00000400 -#define IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE 0x00000800 -#define IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE 0x00001000 -#define IEEE80211_VHT_CAP_BEAMFORMER_ANTENNAS_MAX 0x00006000 -#define IEEE80211_VHT_CAP_SOUNDING_DIMENTION_MAX 0x00030000 -#define IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE 0x00080000 -#define IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE 0x00100000 -#define IEEE80211_VHT_CAP_VHT_TXOP_PS 0x00200000 -#define IEEE80211_VHT_CAP_HTC_VHT 0x00400000 -#define IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT 0x00800000 -#define IEEE80211_VHT_CAP_VHT_LINK_ADAPTATION_VHT_UNSOL_MFB 0x08000000 -#define IEEE80211_VHT_CAP_VHT_LINK_ADAPTATION_VHT_MRQ_MFB 0x0c000000 -#define IEEE80211_VHT_CAP_RX_ANTENNA_PATTERN 0x10000000 -#define IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN 0x20000000 - /* Authentication algorithms */ #define WLAN_AUTH_OPEN 0 #define WLAN_AUTH_SHARED_KEY 1 @@ -1206,21 +1124,6 @@ struct ieee80211_vht_mcs_info { #define WLAN_CAPABILITY_QOS (1<<9) #define WLAN_CAPABILITY_SHORT_SLOT_TIME (1<<10) #define WLAN_CAPABILITY_DSSS_OFDM (1<<13) - -/* DMG (60gHz) 802.11ad */ -/* type - bits 0..1 */ -#define WLAN_CAPABILITY_DMG_TYPE_IBSS (1<<0) /* Tx by: STA */ -#define WLAN_CAPABILITY_DMG_TYPE_PBSS (2<<0) /* Tx by: PCP */ -#define WLAN_CAPABILITY_DMG_TYPE_AP (3<<0) /* Tx by: AP */ - -#define WLAN_CAPABILITY_DMG_CBAP_ONLY (1<<2) -#define WLAN_CAPABILITY_DMG_CBAP_SOURCE (1<<3) -#define WLAN_CAPABILITY_DMG_PRIVACY (1<<4) -#define WLAN_CAPABILITY_DMG_ECPAC (1<<5) - -#define WLAN_CAPABILITY_DMG_SPECTRUM_MGMT (1<<8) -#define WLAN_CAPABILITY_DMG_RADIO_MEASURE (1<<12) - /* measurement */ #define IEEE80211_SPCT_MSR_RPRT_MODE_LATE (1<<0) #define IEEE80211_SPCT_MSR_RPRT_MODE_INCAPABLE (1<<1) @@ -1230,6 +1133,7 @@ struct ieee80211_vht_mcs_info { #define IEEE80211_SPCT_MSR_RPRT_TYPE_CCA 1 #define IEEE80211_SPCT_MSR_RPRT_TYPE_RPI 2 + /* 802.11g ERP information element */ #define WLAN_ERP_NON_ERP_PRESENT (1<<0) #define WLAN_ERP_USE_PROTECTION (1<<1) @@ -1241,16 +1145,6 @@ enum { WLAN_ERP_PREAMBLE_LONG = 1, }; -/* Band ID, 802.11ad #8.4.1.45 */ -enum { - IEEE80211_BANDID_TV_WS = 0, /* TV white spaces */ - IEEE80211_BANDID_SUB1 = 1, /* Sub-1 GHz (excluding TV white spaces) */ - IEEE80211_BANDID_2G = 2, /* 2.4 GHz */ - IEEE80211_BANDID_3G = 3, /* 3.6 GHz */ - IEEE80211_BANDID_5G = 4, /* 4.9 and 5 GHz */ - IEEE80211_BANDID_60G = 5, /* 60 GHz */ -}; - /* Status codes */ enum ieee80211_statuscode { WLAN_STATUS_SUCCESS = 0, @@ -1302,17 +1196,6 @@ enum ieee80211_statuscode { WLAN_STATUS_ANTI_CLOG_REQUIRED = 76, WLAN_STATUS_FCG_NOT_SUPP = 78, WLAN_STATUS_STA_NO_TBTT = 78, - /* 802.11ad */ - WLAN_STATUS_REJECTED_WITH_SUGGESTED_CHANGES = 39, - WLAN_STATUS_REJECTED_FOR_DELAY_PERIOD = 47, - WLAN_STATUS_REJECT_WITH_SCHEDULE = 83, - WLAN_STATUS_PENDING_ADMITTING_FST_SESSION = 86, - WLAN_STATUS_PERFORMING_FST_NOW = 87, - WLAN_STATUS_PENDING_GAP_IN_BA_WINDOW = 88, - WLAN_STATUS_REJECT_U_PID_SETTING = 89, - WLAN_STATUS_REJECT_DSE_BAND = 96, - WLAN_STATUS_DENIED_WITH_SUGGESTED_BAND_AND_CHANNEL = 99, - WLAN_STATUS_DENIED_DUE_TO_SPECTRUM_MANAGEMENT = 103, }; @@ -1469,43 +1352,6 @@ enum ieee80211_eid { WLAN_EID_DSE_REGISTERED_LOCATION = 58, WLAN_EID_SUPPORTED_REGULATORY_CLASSES = 59, WLAN_EID_EXT_CHANSWITCH_ANN = 60, - - WLAN_EID_VHT_CAPABILITY = 191, - WLAN_EID_VHT_OPERATION = 192, - - /* 802.11ad */ - WLAN_EID_NON_TX_BSSID_CAP = 83, - WLAN_EID_WAKEUP_SCHEDULE = 143, - WLAN_EID_EXT_SCHEDULE = 144, - WLAN_EID_STA_AVAILABILITY = 145, - WLAN_EID_DMG_TSPEC = 146, - WLAN_EID_DMG_AT = 147, - WLAN_EID_DMG_CAP = 148, - WLAN_EID_DMG_OPERATION = 151, - WLAN_EID_DMG_BSS_PARAM_CHANGE = 152, - WLAN_EID_DMG_BEAM_REFINEMENT = 153, - WLAN_EID_CHANNEL_MEASURE_FEEDBACK = 154, - WLAN_EID_AWAKE_WINDOW = 157, - WLAN_EID_MULTI_BAND = 158, - WLAN_EID_ADDBA_EXT = 159, - WLAN_EID_NEXT_PCP_LIST = 160, - WLAN_EID_PCP_HANDOVER = 161, - WLAN_EID_DMG_LINK_MARGIN = 162, - WLAN_EID_SWITCHING_STREAM = 163, - WLAN_EID_SESSION_TRANSITION = 164, - WLAN_EID_DYN_TONE_PAIRING_REPORT = 165, - WLAN_EID_CLUSTER_REPORT = 166, - WLAN_EID_RELAY_CAP = 167, - WLAN_EID_RELAY_XFER_PARAM_SET = 168, - WLAN_EID_BEAM_LINK_MAINT = 169, - WLAN_EID_MULTIPLE_MAC_ADDR = 170, - WLAN_EID_U_PID = 171, - WLAN_EID_DMG_LINK_ADAPT_ACK = 172, - WLAN_EID_QUIET_PERIOD_REQ = 175, - WLAN_EID_QUIET_PERIOD_RESP = 177, - WLAN_EID_EPAC_POLICY = 182, - WLAN_EID_CLISTER_TIME_OFF = 183, - WLAN_EID_ANTENNA_SECTOR_ID_PATTERN = 190, }; /* Action category code */ @@ -1522,10 +1368,7 @@ enum ieee80211_category { WLAN_CATEGORY_MESH_ACTION = 13, WLAN_CATEGORY_MULTIHOP_ACTION = 14, WLAN_CATEGORY_SELF_PROTECTED = 15, - WLAN_CATEGORY_DMG = 16, WLAN_CATEGORY_WMM = 17, - WLAN_CATEGORY_FST = 18, - WLAN_CATEGORY_UNPROT_DMG = 20, WLAN_CATEGORY_VENDOR_SPECIFIC_PROTECTED = 126, WLAN_CATEGORY_VENDOR_SPECIFIC = 127, }; @@ -1773,7 +1616,6 @@ enum ieee80211_sa_query_action { #define WLAN_CIPHER_SUITE_CCMP 0x000FAC04 #define WLAN_CIPHER_SUITE_WEP104 0x000FAC05 #define WLAN_CIPHER_SUITE_AES_CMAC 0x000FAC06 -#define WLAN_CIPHER_SUITE_GCMP 0x000FAC08 #define WLAN_CIPHER_SUITE_SMS4 0x00147201 diff --git a/trunk/include/linux/if_team.h b/trunk/include/linux/if_team.h index 7fd0cdeb9444..99efd60fa8c9 100644 --- a/trunk/include/linux/if_team.h +++ b/trunk/include/linux/if_team.h @@ -13,8 +13,6 @@ #ifdef __KERNEL__ -#include - struct team_pcpu_stats { u64 rx_packets; u64 rx_bytes; @@ -62,49 +60,10 @@ struct team_port { unsigned int mtu; } orig; -#ifdef CONFIG_NET_POLL_CONTROLLER - struct netpoll *np; -#endif - long mode_priv[0]; }; -static inline bool team_port_enabled(struct team_port *port) -{ - return port->index != -1; -} - -static inline bool team_port_txable(struct team_port *port) -{ - return port->linkup && team_port_enabled(port); -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -static inline void team_netpoll_send_skb(struct team_port *port, - struct sk_buff *skb) -{ - struct netpoll *np = port->np; - - if (np) - netpoll_send_skb(np, skb); -} -#else -static inline void team_netpoll_send_skb(struct team_port *port, - struct sk_buff *skb) -{ -} -#endif - -static inline int team_dev_queue_xmit(struct team *team, struct team_port *port, - struct sk_buff *skb) -{ - skb->dev = port->dev; - if (unlikely(netpoll_tx_running(port->dev))) { - team_netpoll_send_skb(port, skb); - return 0; - } - return dev_queue_xmit(skb); -} +extern bool team_port_enabled(struct team_port *port); struct team_mode_ops { int (*init)(struct team *team); diff --git a/trunk/include/linux/ipv6.h b/trunk/include/linux/ipv6.h index 379e433e15e0..8260ef779762 100644 --- a/trunk/include/linux/ipv6.h +++ b/trunk/include/linux/ipv6.h @@ -299,9 +299,9 @@ struct ipv6_pinfo { struct in6_addr rcv_saddr; struct in6_addr daddr; struct in6_pktinfo sticky_pktinfo; - const struct in6_addr *daddr_cache; + struct in6_addr *daddr_cache; #ifdef CONFIG_IPV6_SUBTREES - const struct in6_addr *saddr_cache; + struct in6_addr *saddr_cache; #endif __be32 flow_label; @@ -410,22 +410,6 @@ struct tcp6_sock { extern int inet6_sk_rebuild_header(struct sock *sk); -struct inet6_timewait_sock { - struct in6_addr tw_v6_daddr; - struct in6_addr tw_v6_rcv_saddr; -}; - -struct tcp6_timewait_sock { - struct tcp_timewait_sock tcp6tw_tcp; - struct inet6_timewait_sock tcp6tw_inet6; -}; - -static inline struct inet6_timewait_sock *inet6_twsk(const struct sock *sk) -{ - return (struct inet6_timewait_sock *)(((u8 *)sk) + - inet_twsk(sk)->tw_ipv6_offset); -} - #if IS_ENABLED(CONFIG_IPV6) static inline struct ipv6_pinfo * inet6_sk(const struct sock *__sk) { @@ -475,12 +459,28 @@ static inline void inet_sk_copy_descendant(struct sock *sk_to, #define __ipv6_only_sock(sk) (inet6_sk(sk)->ipv6only) #define ipv6_only_sock(sk) ((sk)->sk_family == PF_INET6 && __ipv6_only_sock(sk)) +struct inet6_timewait_sock { + struct in6_addr tw_v6_daddr; + struct in6_addr tw_v6_rcv_saddr; +}; + +struct tcp6_timewait_sock { + struct tcp_timewait_sock tcp6tw_tcp; + struct inet6_timewait_sock tcp6tw_inet6; +}; + static inline u16 inet6_tw_offset(const struct proto *prot) { return prot->twsk_prot->twsk_obj_size - sizeof(struct inet6_timewait_sock); } +static inline struct inet6_timewait_sock *inet6_twsk(const struct sock *sk) +{ + return (struct inet6_timewait_sock *)(((u8 *)sk) + + inet_twsk(sk)->tw_ipv6_offset); +} + static inline struct in6_addr *__inet6_rcv_saddr(const struct sock *sk) { return likely(sk->sk_state != TCP_TIME_WAIT) ? diff --git a/trunk/include/linux/mlx4/cmd.h b/trunk/include/linux/mlx4/cmd.h index 260695186256..1f3860a8a109 100644 --- a/trunk/include/linux/mlx4/cmd.h +++ b/trunk/include/linux/mlx4/cmd.h @@ -154,10 +154,6 @@ enum { /* set port opcode modifiers */ MLX4_SET_PORT_PRIO2TC = 0x8, MLX4_SET_PORT_SCHEDULER = 0x9, - - /* register/delete flow steering network rules */ - MLX4_QP_FLOW_STEERING_ATTACH = 0x65, - MLX4_QP_FLOW_STEERING_DETACH = 0x66, }; enum { diff --git a/trunk/include/linux/mlx4/device.h b/trunk/include/linux/mlx4/device.h index 6f0d133cc7ad..6a8f002b8ed3 100644 --- a/trunk/include/linux/mlx4/device.h +++ b/trunk/include/linux/mlx4/device.h @@ -70,36 +70,6 @@ enum { MLX4_MFUNC_EQE_MASK = (MLX4_MFUNC_MAX_EQES - 1) }; -/* Driver supports 3 diffrent device methods to manage traffic steering: - * -device managed - High level API for ib and eth flow steering. FW is - * managing flow steering tables. - * - B0 steering mode - Common low level API for ib and (if supported) eth. - * - A0 steering mode - Limited low level API for eth. In case of IB, - * B0 mode is in use. - */ -enum { - MLX4_STEERING_MODE_A0, - MLX4_STEERING_MODE_B0, - MLX4_STEERING_MODE_DEVICE_MANAGED -}; - -static inline const char *mlx4_steering_mode_str(int steering_mode) -{ - switch (steering_mode) { - case MLX4_STEERING_MODE_A0: - return "A0 steering"; - - case MLX4_STEERING_MODE_B0: - return "B0 steering"; - - case MLX4_STEERING_MODE_DEVICE_MANAGED: - return "Device managed flow steering"; - - default: - return "Unrecognize steering mode"; - } -} - enum { MLX4_DEV_CAP_FLAG_RC = 1LL << 0, MLX4_DEV_CAP_FLAG_UC = 1LL << 1, @@ -132,8 +102,7 @@ enum { enum { MLX4_DEV_CAP_FLAG2_RSS = 1LL << 0, MLX4_DEV_CAP_FLAG2_RSS_TOP = 1LL << 1, - MLX4_DEV_CAP_FLAG2_RSS_XOR = 1LL << 2, - MLX4_DEV_CAP_FLAG2_FS_EN = 1LL << 3 + MLX4_DEV_CAP_FLAG2_RSS_XOR = 1LL << 2 }; #define MLX4_ATTR_EXTENDED_PORT_INFO cpu_to_be16(0xff90) @@ -326,8 +295,6 @@ struct mlx4_caps { int num_amgms; int reserved_mcgs; int num_qp_per_mgm; - int steering_mode; - int fs_log_max_ucast_qp_range_size; int num_pds; int reserved_pds; int max_xrcds; @@ -542,8 +509,6 @@ struct mlx4_dev { u8 rev_id; char board_id[MLX4_BOARD_ID_LEN]; int num_vfs; - u64 regid_promisc_array[MLX4_MAX_PORTS + 1]; - u64 regid_allmulti_array[MLX4_MAX_PORTS + 1]; }; struct mlx4_init_port_param { @@ -658,99 +623,9 @@ int mlx4_unicast_attach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16], int mlx4_unicast_detach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16], enum mlx4_protocol prot); int mlx4_multicast_attach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16], - u8 port, int block_mcast_loopback, - enum mlx4_protocol protocol, u64 *reg_id); + int block_mcast_loopback, enum mlx4_protocol protocol); int mlx4_multicast_detach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16], - enum mlx4_protocol protocol, u64 reg_id); - -enum { - MLX4_DOMAIN_UVERBS = 0x1000, - MLX4_DOMAIN_ETHTOOL = 0x2000, - MLX4_DOMAIN_RFS = 0x3000, - MLX4_DOMAIN_NIC = 0x5000, -}; - -enum mlx4_net_trans_rule_id { - MLX4_NET_TRANS_RULE_ID_ETH = 0, - MLX4_NET_TRANS_RULE_ID_IB, - MLX4_NET_TRANS_RULE_ID_IPV6, - MLX4_NET_TRANS_RULE_ID_IPV4, - MLX4_NET_TRANS_RULE_ID_TCP, - MLX4_NET_TRANS_RULE_ID_UDP, - MLX4_NET_TRANS_RULE_NUM, /* should be last */ -}; - -enum mlx4_net_trans_promisc_mode { - MLX4_FS_PROMISC_NONE = 0, - MLX4_FS_PROMISC_UPLINK, - /* For future use. Not implemented yet */ - MLX4_FS_PROMISC_FUNCTION_PORT, - MLX4_FS_PROMISC_ALL_MULTI, -}; - -struct mlx4_spec_eth { - u8 dst_mac[6]; - u8 dst_mac_msk[6]; - u8 src_mac[6]; - u8 src_mac_msk[6]; - u8 ether_type_enable; - __be16 ether_type; - __be16 vlan_id_msk; - __be16 vlan_id; -}; - -struct mlx4_spec_tcp_udp { - __be16 dst_port; - __be16 dst_port_msk; - __be16 src_port; - __be16 src_port_msk; -}; - -struct mlx4_spec_ipv4 { - __be32 dst_ip; - __be32 dst_ip_msk; - __be32 src_ip; - __be32 src_ip_msk; -}; - -struct mlx4_spec_ib { - __be32 r_qpn; - __be32 qpn_msk; - u8 dst_gid[16]; - u8 dst_gid_msk[16]; -}; - -struct mlx4_spec_list { - struct list_head list; - enum mlx4_net_trans_rule_id id; - union { - struct mlx4_spec_eth eth; - struct mlx4_spec_ib ib; - struct mlx4_spec_ipv4 ipv4; - struct mlx4_spec_tcp_udp tcp_udp; - }; -}; - -enum mlx4_net_trans_hw_rule_queue { - MLX4_NET_TRANS_Q_FIFO, - MLX4_NET_TRANS_Q_LIFO, -}; - -struct mlx4_net_trans_rule { - struct list_head list; - enum mlx4_net_trans_hw_rule_queue queue_mode; - bool exclusive; - bool allow_loopback; - enum mlx4_net_trans_promisc_mode promisc_mode; - u8 port; - u16 priority; - u32 qpn; -}; - -int mlx4_flow_steer_promisc_add(struct mlx4_dev *dev, u8 port, u32 qpn, - enum mlx4_net_trans_promisc_mode mode); -int mlx4_flow_steer_promisc_remove(struct mlx4_dev *dev, u8 port, - enum mlx4_net_trans_promisc_mode mode); + enum mlx4_protocol protocol); int mlx4_multicast_promisc_add(struct mlx4_dev *dev, u32 qpn, u8 port); int mlx4_multicast_promisc_remove(struct mlx4_dev *dev, u32 qpn, u8 port); int mlx4_unicast_promisc_add(struct mlx4_dev *dev, u32 qpn, u8 port); @@ -793,8 +668,4 @@ int mlx4_wol_write(struct mlx4_dev *dev, u64 config, int port); int mlx4_counter_alloc(struct mlx4_dev *dev, u32 *idx); void mlx4_counter_free(struct mlx4_dev *dev, u32 idx); -int mlx4_flow_attach(struct mlx4_dev *dev, - struct mlx4_net_trans_rule *rule, u64 *reg_id); -int mlx4_flow_detach(struct mlx4_dev *dev, u64 reg_id); - #endif /* MLX4_DEVICE_H */ diff --git a/trunk/include/linux/netfilter/nfnetlink_conntrack.h b/trunk/include/linux/netfilter/nfnetlink_conntrack.h index f649f7423ca2..768883370080 100644 --- a/trunk/include/linux/netfilter/nfnetlink_conntrack.h +++ b/trunk/include/linux/netfilter/nfnetlink_conntrack.h @@ -7,8 +7,6 @@ enum cntl_msg_types { IPCTNL_MSG_CT_GET, IPCTNL_MSG_CT_DELETE, IPCTNL_MSG_CT_GET_CTRZERO, - IPCTNL_MSG_CT_GET_STATS_CPU, - IPCTNL_MSG_CT_GET_STATS, IPCTNL_MSG_MAX }; @@ -17,7 +15,6 @@ enum ctnl_exp_msg_types { IPCTNL_MSG_EXP_NEW, IPCTNL_MSG_EXP_GET, IPCTNL_MSG_EXP_DELETE, - IPCTNL_MSG_EXP_GET_STATS_CPU, IPCTNL_MSG_EXP_MAX }; @@ -206,39 +203,4 @@ enum ctattr_secctx { }; #define CTA_SECCTX_MAX (__CTA_SECCTX_MAX - 1) -enum ctattr_stats_cpu { - CTA_STATS_UNSPEC, - CTA_STATS_SEARCHED, - CTA_STATS_FOUND, - CTA_STATS_NEW, - CTA_STATS_INVALID, - CTA_STATS_IGNORE, - CTA_STATS_DELETE, - CTA_STATS_DELETE_LIST, - CTA_STATS_INSERT, - CTA_STATS_INSERT_FAILED, - CTA_STATS_DROP, - CTA_STATS_EARLY_DROP, - CTA_STATS_ERROR, - CTA_STATS_SEARCH_RESTART, - __CTA_STATS_MAX, -}; -#define CTA_STATS_MAX (__CTA_STATS_MAX - 1) - -enum ctattr_stats_global { - CTA_STATS_GLOBAL_UNSPEC, - CTA_STATS_GLOBAL_ENTRIES, - __CTA_STATS_GLOBAL_MAX, -}; -#define CTA_STATS_GLOBAL_MAX (__CTA_STATS_GLOBAL_MAX - 1) - -enum ctattr_expect_stats { - CTA_STATS_EXP_UNSPEC, - CTA_STATS_EXP_NEW, - CTA_STATS_EXP_CREATE, - CTA_STATS_EXP_DELETE, - __CTA_STATS_EXP_MAX, -}; -#define CTA_STATS_EXP_MAX (__CTA_STATS_EXP_MAX - 1) - #endif /* _IPCONNTRACK_NETLINK_H */ diff --git a/trunk/include/linux/netfilter/nfnetlink_queue.h b/trunk/include/linux/netfilter/nfnetlink_queue.h index 3b1c1360aedf..e0d8fd8d4d24 100644 --- a/trunk/include/linux/netfilter/nfnetlink_queue.h +++ b/trunk/include/linux/netfilter/nfnetlink_queue.h @@ -95,6 +95,5 @@ enum nfqnl_attr_config { /* Flags for NFQA_CFG_FLAGS */ #define NFQA_CFG_F_FAIL_OPEN (1 << 0) #define NFQA_CFG_F_CONNTRACK (1 << 1) -#define NFQA_CFG_F_MAX (1 << 2) #endif /* _NFNETLINK_QUEUE_H */ diff --git a/trunk/include/linux/netpoll.h b/trunk/include/linux/netpoll.h index 28f5389c924b..5dfa091c3347 100644 --- a/trunk/include/linux/netpoll.h +++ b/trunk/include/linux/netpoll.h @@ -43,7 +43,7 @@ struct netpoll_info { void netpoll_send_udp(struct netpoll *np, const char *msg, int len); void netpoll_print_options(struct netpoll *np); int netpoll_parse_options(struct netpoll *np, char *opt); -int __netpoll_setup(struct netpoll *np, struct net_device *ndev); +int __netpoll_setup(struct netpoll *np); int netpoll_setup(struct netpoll *np); int netpoll_trap(void); void netpoll_set_trap(int trap); diff --git a/trunk/include/linux/nfc.h b/trunk/include/linux/nfc.h index 6189f27e305b..f4e6dd915b1c 100644 --- a/trunk/include/linux/nfc.h +++ b/trunk/include/linux/nfc.h @@ -136,9 +136,8 @@ enum nfc_attrs { #define NFC_PROTO_FELICA 3 #define NFC_PROTO_ISO14443 4 #define NFC_PROTO_NFC_DEP 5 -#define NFC_PROTO_ISO14443_B 6 -#define NFC_PROTO_MAX 7 +#define NFC_PROTO_MAX 6 /* NFC communication modes */ #define NFC_COMM_ACTIVE 0 @@ -150,12 +149,11 @@ enum nfc_attrs { #define NFC_RF_NONE 2 /* NFC protocols masks used in bitsets */ -#define NFC_PROTO_JEWEL_MASK (1 << NFC_PROTO_JEWEL) -#define NFC_PROTO_MIFARE_MASK (1 << NFC_PROTO_MIFARE) -#define NFC_PROTO_FELICA_MASK (1 << NFC_PROTO_FELICA) -#define NFC_PROTO_ISO14443_MASK (1 << NFC_PROTO_ISO14443) -#define NFC_PROTO_NFC_DEP_MASK (1 << NFC_PROTO_NFC_DEP) -#define NFC_PROTO_ISO14443_B_MASK (1 << NFC_PROTO_ISO14443_B) +#define NFC_PROTO_JEWEL_MASK (1 << NFC_PROTO_JEWEL) +#define NFC_PROTO_MIFARE_MASK (1 << NFC_PROTO_MIFARE) +#define NFC_PROTO_FELICA_MASK (1 << NFC_PROTO_FELICA) +#define NFC_PROTO_ISO14443_MASK (1 << NFC_PROTO_ISO14443) +#define NFC_PROTO_NFC_DEP_MASK (1 << NFC_PROTO_NFC_DEP) struct sockaddr_nfc { sa_family_t sa_family; diff --git a/trunk/include/linux/nl80211.h b/trunk/include/linux/nl80211.h index db961a59247f..c0fc5d277338 100644 --- a/trunk/include/linux/nl80211.h +++ b/trunk/include/linux/nl80211.h @@ -1638,20 +1638,12 @@ struct nl80211_sta_flag_update { * * These attribute types are used with %NL80211_STA_INFO_TXRATE * when getting information about the bitrate of a station. - * There are 2 attributes for bitrate, a legacy one that represents - * a 16-bit value, and new one that represents a 32-bit value. - * If the rate value fits into 16 bit, both attributes are reported - * with the same value. If the rate is too high to fit into 16 bits - * (>6.5535Gbps) only 32-bit attribute is included. - * User space tools encouraged to use the 32-bit attribute and fall - * back to the 16-bit one for compatibility with older kernels. * * @__NL80211_RATE_INFO_INVALID: attribute number 0 is reserved * @NL80211_RATE_INFO_BITRATE: total bitrate (u16, 100kbit/s) * @NL80211_RATE_INFO_MCS: mcs index for 802.11n (u8) * @NL80211_RATE_INFO_40_MHZ_WIDTH: 40 Mhz dualchannel bitrate * @NL80211_RATE_INFO_SHORT_GI: 400ns guard interval - * @NL80211_RATE_INFO_BITRATE32: total bitrate (u32, 100kbit/s) * @NL80211_RATE_INFO_MAX: highest rate_info number currently defined * @__NL80211_RATE_INFO_AFTER_LAST: internal use */ @@ -1661,7 +1653,6 @@ enum nl80211_rate_info { NL80211_RATE_INFO_MCS, NL80211_RATE_INFO_40_MHZ_WIDTH, NL80211_RATE_INFO_SHORT_GI, - NL80211_RATE_INFO_BITRATE32, /* keep last */ __NL80211_RATE_INFO_AFTER_LAST, @@ -1822,9 +1813,6 @@ enum nl80211_mpath_info { * @NL80211_BAND_ATTR_HT_CAPA: HT capabilities, as in the HT information IE * @NL80211_BAND_ATTR_HT_AMPDU_FACTOR: A-MPDU factor, as in 11n * @NL80211_BAND_ATTR_HT_AMPDU_DENSITY: A-MPDU density, as in 11n - * @NL80211_BAND_ATTR_VHT_MCS_SET: 32-byte attribute containing the MCS set as - * defined in 802.11ac - * @NL80211_BAND_ATTR_VHT_CAPA: VHT capabilities, as in the HT information IE * @NL80211_BAND_ATTR_MAX: highest band attribute currently defined * @__NL80211_BAND_ATTR_AFTER_LAST: internal use */ @@ -1838,9 +1826,6 @@ enum nl80211_band_attr { NL80211_BAND_ATTR_HT_AMPDU_FACTOR, NL80211_BAND_ATTR_HT_AMPDU_DENSITY, - NL80211_BAND_ATTR_VHT_MCS_SET, - NL80211_BAND_ATTR_VHT_CAPA, - /* keep last */ __NL80211_BAND_ATTR_AFTER_LAST, NL80211_BAND_ATTR_MAX = __NL80211_BAND_ATTR_AFTER_LAST - 1 @@ -2554,12 +2539,10 @@ enum nl80211_tx_rate_attributes { * enum nl80211_band - Frequency band * @NL80211_BAND_2GHZ: 2.4 GHz ISM band * @NL80211_BAND_5GHZ: around 5 GHz band (4.9 - 5.7 GHz) - * @NL80211_BAND_60GHZ: around 60 GHz band (58.32 - 64.80 GHz) */ enum nl80211_band { NL80211_BAND_2GHZ, NL80211_BAND_5GHZ, - NL80211_BAND_60GHZ, }; /** diff --git a/trunk/include/linux/phy.h b/trunk/include/linux/phy.h index 93b3cf77f564..c35299e4da8e 100644 --- a/trunk/include/linux/phy.h +++ b/trunk/include/linux/phy.h @@ -533,9 +533,7 @@ int genphy_read_status(struct phy_device *phydev); int genphy_suspend(struct phy_device *phydev); int genphy_resume(struct phy_device *phydev); void phy_driver_unregister(struct phy_driver *drv); -void phy_drivers_unregister(struct phy_driver *drv, int n); int phy_driver_register(struct phy_driver *new_driver); -int phy_drivers_register(struct phy_driver *new_driver, int n); void phy_state_machine(struct work_struct *work); void phy_start_machine(struct phy_device *phydev, void (*handler)(struct net_device *)); diff --git a/trunk/include/linux/pkt_cls.h b/trunk/include/linux/pkt_cls.h index 082eafaf026b..defbde203d07 100644 --- a/trunk/include/linux/pkt_cls.h +++ b/trunk/include/linux/pkt_cls.h @@ -451,10 +451,8 @@ enum { #define TCF_EM_U32 3 #define TCF_EM_META 4 #define TCF_EM_TEXT 5 -#define TCF_EM_VLAN 6 -#define TCF_EM_CANID 7 -#define TCF_EM_IPSET 8 -#define TCF_EM_MAX 8 +#define TCF_EM_VLAN 6 +#define TCF_EM_MAX 6 enum { TCF_EM_PROG_TC diff --git a/trunk/include/linux/rtnetlink.h b/trunk/include/linux/rtnetlink.h index db71c4ad8624..ea60b0854109 100644 --- a/trunk/include/linux/rtnetlink.h +++ b/trunk/include/linux/rtnetlink.h @@ -619,7 +619,8 @@ extern void rtnl_notify(struct sk_buff *skb, struct net *net, u32 pid, extern void rtnl_set_sk_err(struct net *net, u32 group, int error); extern int rtnetlink_put_metrics(struct sk_buff *skb, u32 *metrics); extern int rtnl_put_cacheinfo(struct sk_buff *skb, struct dst_entry *dst, - u32 id, long expires, u32 error); + u32 id, u32 ts, u32 tsage, long expires, + u32 error); extern void rtmsg_ifinfo(int type, struct net_device *dev, unsigned change); diff --git a/trunk/include/linux/snmp.h b/trunk/include/linux/snmp.h index e5fcbd079e4a..2e68f5ba0389 100644 --- a/trunk/include/linux/snmp.h +++ b/trunk/include/linux/snmp.h @@ -208,6 +208,7 @@ enum LINUX_MIB_TCPDSACKOFOSENT, /* TCPDSACKOfoSent */ LINUX_MIB_TCPDSACKRECV, /* TCPDSACKRecv */ LINUX_MIB_TCPDSACKOFORECV, /* TCPDSACKOfoRecv */ + LINUX_MIB_TCPABORTONSYN, /* TCPAbortOnSyn */ LINUX_MIB_TCPABORTONDATA, /* TCPAbortOnData */ LINUX_MIB_TCPABORTONCLOSE, /* TCPAbortOnClose */ LINUX_MIB_TCPABORTONMEMORY, /* TCPAbortOnMemory */ @@ -232,12 +233,7 @@ enum LINUX_MIB_TCPREQQFULLDOCOOKIES, /* TCPReqQFullDoCookies */ LINUX_MIB_TCPREQQFULLDROP, /* TCPReqQFullDrop */ LINUX_MIB_TCPRETRANSFAIL, /* TCPRetransFail */ - LINUX_MIB_TCPRCVCOALESCE, /* TCPRcvCoalesce */ - LINUX_MIB_TCPOFOQUEUE, /* TCPOFOQueue */ - LINUX_MIB_TCPOFODROP, /* TCPOFODrop */ - LINUX_MIB_TCPOFOMERGE, /* TCPOFOMerge */ - LINUX_MIB_TCPCHALLENGEACK, /* TCPChallengeACK */ - LINUX_MIB_TCPSYNCHALLENGE, /* TCPSYNChallenge */ + LINUX_MIB_TCPRCVCOALESCE, /* TCPRcvCoalesce */ __LINUX_MIB_MAX }; diff --git a/trunk/include/linux/sock_diag.h b/trunk/include/linux/sock_diag.h index e3e395acc2fd..6793fac5eab5 100644 --- a/trunk/include/linux/sock_diag.h +++ b/trunk/include/linux/sock_diag.h @@ -44,5 +44,6 @@ void sock_diag_save_cookie(void *sk, __u32 *cookie); int sock_diag_put_meminfo(struct sock *sk, struct sk_buff *skb, int attr); +extern struct sock *sock_diag_nlsk; #endif /* KERNEL */ #endif diff --git a/trunk/include/linux/tcp.h b/trunk/include/linux/tcp.h index 1888169e07c7..7d3bcedc062a 100644 --- a/trunk/include/linux/tcp.h +++ b/trunk/include/linux/tcp.h @@ -339,9 +339,6 @@ struct tcp_sock { u32 rcv_tstamp; /* timestamp of last received ACK (for keepalives) */ u32 lsndtime; /* timestamp of last sent data packet (for restart window) */ - struct list_head tsq_node; /* anchor in tsq_tasklet.head list */ - unsigned long tsq_flags; - /* Data for direct copy to user */ struct { struct sk_buff_head prequeue; @@ -497,12 +494,6 @@ struct tcp_sock { struct tcp_cookie_values *cookie_values; }; -enum tsq_flags { - TSQ_THROTTLED, - TSQ_QUEUED, - TSQ_OWNED, /* tcp_tasklet_func() found socket was locked */ -}; - static inline struct tcp_sock *tcp_sk(const struct sock *sk) { return (struct tcp_sock *)sk; @@ -515,6 +506,7 @@ struct tcp_timewait_sock { u32 tw_rcv_wnd; u32 tw_ts_recent; long tw_ts_recent_stamp; + struct inet_peer *tw_peer; #ifdef CONFIG_TCP_MD5SIG struct tcp_md5sig_key *tw_md5_key; #endif diff --git a/trunk/include/linux/tipc_config.h b/trunk/include/linux/tipc_config.h index c98928420100..9730b0e51e46 100644 --- a/trunk/include/linux/tipc_config.h +++ b/trunk/include/linux/tipc_config.h @@ -102,8 +102,8 @@ #define TIPC_CMD_SET_LINK_TOL 0x4107 /* tx link_config, rx none */ #define TIPC_CMD_SET_LINK_PRI 0x4108 /* tx link_config, rx none */ #define TIPC_CMD_SET_LINK_WINDOW 0x4109 /* tx link_config, rx none */ -#define TIPC_CMD_SET_LOG_SIZE 0x410A /* obsoleted */ -#define TIPC_CMD_DUMP_LOG 0x410B /* obsoleted */ +#define TIPC_CMD_SET_LOG_SIZE 0x410A /* tx unsigned, rx none */ +#define TIPC_CMD_DUMP_LOG 0x410B /* tx none, rx ultra_string */ #define TIPC_CMD_RESET_LINK_STATS 0x410C /* tx link_name, rx none */ /* diff --git a/trunk/include/net/cfg80211.h b/trunk/include/net/cfg80211.h index 51f67a9003a9..061c01957e54 100644 --- a/trunk/include/net/cfg80211.h +++ b/trunk/include/net/cfg80211.h @@ -70,13 +70,11 @@ * * @IEEE80211_BAND_2GHZ: 2.4GHz ISM band * @IEEE80211_BAND_5GHZ: around 5GHz band (4.9-5.7) - * @IEEE80211_BAND_60GHZ: around 60 GHz band (58.32 - 64.80 GHz) * @IEEE80211_NUM_BANDS: number of defined bands */ enum ieee80211_band { IEEE80211_BAND_2GHZ = NL80211_BAND_2GHZ, IEEE80211_BAND_5GHZ = NL80211_BAND_5GHZ, - IEEE80211_BAND_60GHZ = NL80211_BAND_60GHZ, /* keep last */ IEEE80211_NUM_BANDS @@ -212,22 +210,6 @@ struct ieee80211_sta_ht_cap { struct ieee80211_mcs_info mcs; }; -/** - * struct ieee80211_sta_vht_cap - STA's VHT capabilities - * - * This structure describes most essential parameters needed - * to describe 802.11ac VHT capabilities for an STA. - * - * @vht_supported: is VHT supported by the STA - * @cap: VHT capabilities map as described in 802.11ac spec - * @vht_mcs: Supported VHT MCS rates - */ -struct ieee80211_sta_vht_cap { - bool vht_supported; - u32 cap; /* use IEEE80211_VHT_CAP_ */ - struct ieee80211_vht_mcs_info vht_mcs; -}; - /** * struct ieee80211_supported_band - frequency band definition * @@ -251,7 +233,6 @@ struct ieee80211_supported_band { int n_channels; int n_bitrates; struct ieee80211_sta_ht_cap ht_cap; - struct ieee80211_sta_vht_cap vht_cap; }; /* @@ -580,13 +561,11 @@ enum station_info_flags { * @RATE_INFO_FLAGS_MCS: @tx_bitrate_mcs filled * @RATE_INFO_FLAGS_40_MHZ_WIDTH: 40 Mhz width transmission * @RATE_INFO_FLAGS_SHORT_GI: 400ns guard interval - * @RATE_INFO_FLAGS_60G: 60gHz MCS */ enum rate_info_flags { RATE_INFO_FLAGS_MCS = 1<<0, RATE_INFO_FLAGS_40_MHZ_WIDTH = 1<<1, RATE_INFO_FLAGS_SHORT_GI = 1<<2, - RATE_INFO_FLAGS_60G = 1<<3, }; /** @@ -1503,8 +1482,9 @@ struct cfg80211_gtk_rekey_data { * interfaces are active this callback should reject the configuration. * If no interfaces are active or the device is down, the channel should * be stored for when a monitor interface becomes active. - * @set_monitor_enabled: Notify driver that there are only monitor - * interfaces running. + * @get_channel: Get the current operating channel, should return %NULL if + * there's no single defined operating channel if for example the + * device implements channel hopping for multi-channel virtual interfaces. * * @scan: Request to do a scan. If returning zero, the scan request is given * the driver, and will be valid until passed to cfg80211_scan_done(). @@ -1811,14 +1791,15 @@ struct cfg80211_ops { struct net_device *dev, u16 noack_map); + struct ieee80211_channel *(*get_channel)(struct wiphy *wiphy, + enum nl80211_channel_type *type); + int (*get_et_sset_count)(struct wiphy *wiphy, struct net_device *dev, int sset); void (*get_et_stats)(struct wiphy *wiphy, struct net_device *dev, struct ethtool_stats *stats, u64 *data); void (*get_et_strings)(struct wiphy *wiphy, struct net_device *dev, u32 sset, u8 *data); - - void (*set_monitor_enabled)(struct wiphy *wiphy, bool enabled); }; /* @@ -2172,9 +2153,7 @@ struct wiphy { char fw_version[ETHTOOL_BUSINFO_LEN]; u32 hw_version; -#ifdef CONFIG_PM struct wiphy_wowlan_support wowlan; -#endif u16 max_remain_on_channel_duration; @@ -2410,11 +2389,6 @@ struct wireless_dev { struct ieee80211_channel *preset_chan; enum nl80211_channel_type preset_chantype; - /* for AP and mesh channel tracking */ - struct ieee80211_channel *channel; - - bool ibss_fixed; - bool ps; int ps_timeout; @@ -3489,7 +3463,7 @@ void cfg80211_ch_switch_notify(struct net_device *dev, int freq, * * return 0 if MCS index >= 32 */ -u32 cfg80211_calculate_bitrate(struct rate_info *rate); +u16 cfg80211_calculate_bitrate(struct rate_info *rate); /* Logging, debugging and troubleshooting/diagnostic helpers. */ diff --git a/trunk/include/net/dst.h b/trunk/include/net/dst.h index 51610468c63d..b2634e446613 100644 --- a/trunk/include/net/dst.h +++ b/trunk/include/net/dst.h @@ -209,6 +209,12 @@ static inline unsigned long dst_metric_rtt(const struct dst_entry *dst, int metr return msecs_to_jiffies(dst_metric(dst, metric)); } +static inline void set_dst_metric_rtt(struct dst_entry *dst, int metric, + unsigned long rtt) +{ + dst_metric_set(dst, metric, jiffies_to_msecs(rtt)); +} + static inline u32 dst_allfrag(const struct dst_entry *dst) { diff --git a/trunk/include/net/dst_ops.h b/trunk/include/net/dst_ops.h index d079fc61c123..4badc86e45d1 100644 --- a/trunk/include/net/dst_ops.h +++ b/trunk/include/net/dst_ops.h @@ -24,10 +24,7 @@ struct dst_ops { struct net_device *dev, int how); struct dst_entry * (*negative_advice)(struct dst_entry *); void (*link_failure)(struct sk_buff *); - void (*update_pmtu)(struct dst_entry *dst, struct sock *sk, - struct sk_buff *skb, u32 mtu); - void (*redirect)(struct dst_entry *dst, struct sock *sk, - struct sk_buff *skb); + void (*update_pmtu)(struct dst_entry *dst, u32 mtu); int (*local_out)(struct sk_buff *skb); struct neighbour * (*neigh_lookup)(const struct dst_entry *dst, struct sk_buff *skb, diff --git a/trunk/include/net/flow.h b/trunk/include/net/flow.h index ce9cb7656b47..bd524f598561 100644 --- a/trunk/include/net/flow.h +++ b/trunk/include/net/flow.h @@ -20,8 +20,9 @@ struct flowi_common { __u8 flowic_proto; __u8 flowic_flags; #define FLOWI_FLAG_ANYSRC 0x01 -#define FLOWI_FLAG_CAN_SLEEP 0x02 -#define FLOWI_FLAG_RT_NOCACHE 0x04 +#define FLOWI_FLAG_PRECOW_METRICS 0x02 +#define FLOWI_FLAG_CAN_SLEEP 0x04 +#define FLOWI_FLAG_RT_NOCACHE 0x08 __u32 flowic_secid; }; diff --git a/trunk/include/net/inet6_connection_sock.h b/trunk/include/net/inet6_connection_sock.h index 04642c920431..df2a857e853d 100644 --- a/trunk/include/net/inet6_connection_sock.h +++ b/trunk/include/net/inet6_connection_sock.h @@ -43,6 +43,4 @@ extern void inet6_csk_reqsk_queue_hash_add(struct sock *sk, extern void inet6_csk_addr2sockaddr(struct sock *sk, struct sockaddr *uaddr); extern int inet6_csk_xmit(struct sk_buff *skb, struct flowi *fl); - -extern struct dst_entry *inet6_csk_update_pmtu(struct sock *sk, u32 mtu); #endif /* _INET6_CONNECTION_SOCK_H */ diff --git a/trunk/include/net/inet_connection_sock.h b/trunk/include/net/inet_connection_sock.h index 2cf44b4ed2e6..af3c743a40e4 100644 --- a/trunk/include/net/inet_connection_sock.h +++ b/trunk/include/net/inet_connection_sock.h @@ -43,6 +43,7 @@ struct inet_connection_sock_af_ops { struct sock *(*syn_recv_sock)(struct sock *sk, struct sk_buff *skb, struct request_sock *req, struct dst_entry *dst); + struct inet_peer *(*get_peer)(struct sock *sk); u16 net_header_len; u16 net_frag_header_len; u16 sockaddr_len; @@ -337,6 +338,4 @@ extern int inet_csk_compat_getsockopt(struct sock *sk, int level, int optname, char __user *optval, int __user *optlen); extern int inet_csk_compat_setsockopt(struct sock *sk, int level, int optname, char __user *optval, unsigned int optlen); - -extern struct dst_entry *inet_csk_update_pmtu(struct sock *sk, u32 mtu); #endif /* _INET_CONNECTION_SOCK_H */ diff --git a/trunk/include/net/inet_sock.h b/trunk/include/net/inet_sock.h index 924d7b98ab60..ae17e1352d7e 100644 --- a/trunk/include/net/inet_sock.h +++ b/trunk/include/net/inet_sock.h @@ -245,6 +245,8 @@ static inline __u8 inet_sk_flowi_flags(const struct sock *sk) if (inet_sk(sk)->transparent || inet_sk(sk)->hdrincl) flags |= FLOWI_FLAG_ANYSRC; + if (sk->sk_protocol == IPPROTO_TCP) + flags |= FLOWI_FLAG_PRECOW_METRICS; return flags; } diff --git a/trunk/include/net/inetpeer.h b/trunk/include/net/inetpeer.h index 53f464d7cddc..c27c8f10ebdc 100644 --- a/trunk/include/net/inetpeer.h +++ b/trunk/include/net/inetpeer.h @@ -36,19 +36,25 @@ struct inet_peer { u32 metrics[RTAX_MAX]; u32 rate_tokens; /* rate limiting for ICMP */ unsigned long rate_last; + unsigned long pmtu_expires; + u32 pmtu_orig; + u32 pmtu_learned; + struct inetpeer_addr_base redirect_learned; union { struct list_head gc_list; struct rcu_head gc_rcu; }; /* * Once inet_peer is queued for deletion (refcnt == -1), following fields - * are not available: rid, ip_id_count + * are not available: rid, ip_id_count, tcp_ts, tcp_ts_stamp * We can share memory with rcu_head to help keep inet_peer small. */ union { struct { atomic_t rid; /* Frag reception counter */ atomic_t ip_id_count; /* IP ID for the next packet */ + __u32 tcp_ts; + __u32 tcp_ts_stamp; }; struct rcu_head rcu; struct inet_peer *gc_next; diff --git a/trunk/include/net/ip6_route.h b/trunk/include/net/ip6_route.h index 5fa2af00634a..58cb3fc34879 100644 --- a/trunk/include/net/ip6_route.h +++ b/trunk/include/net/ip6_route.h @@ -133,12 +133,17 @@ extern int rt6_route_rcv(struct net_device *dev, u8 *opt, int len, const struct in6_addr *gwaddr); +extern void rt6_redirect(const struct in6_addr *dest, + const struct in6_addr *src, + const struct in6_addr *saddr, + struct neighbour *neigh, + u8 *lladdr, + int on_link); + extern void ip6_update_pmtu(struct sk_buff *skb, struct net *net, __be32 mtu, int oif, u32 mark); extern void ip6_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, __be32 mtu); -extern void ip6_redirect(struct sk_buff *skb, struct net *net, int oif, u32 mark); -extern void ip6_sk_redirect(struct sk_buff *skb, struct sock *sk); struct netlink_callback; @@ -158,8 +163,7 @@ extern void rt6_remove_prefsrc(struct inet6_ifaddr *ifp); * Store a destination cache entry in a socket */ static inline void __ip6_dst_store(struct sock *sk, struct dst_entry *dst, - const struct in6_addr *daddr, - const struct in6_addr *saddr) + struct in6_addr *daddr, struct in6_addr *saddr) { struct ipv6_pinfo *np = inet6_sk(sk); struct rt6_info *rt = (struct rt6_info *) dst; diff --git a/trunk/include/net/ip_fib.h b/trunk/include/net/ip_fib.h index e9ee1ca07087..539c6721f810 100644 --- a/trunk/include/net/ip_fib.h +++ b/trunk/include/net/ip_fib.h @@ -18,7 +18,6 @@ #include #include -#include #include #include @@ -47,22 +46,6 @@ struct fib_config { struct fib_info; -struct fib_nh_exception { - struct fib_nh_exception __rcu *fnhe_next; - __be32 fnhe_daddr; - u32 fnhe_pmtu; - u32 fnhe_gw; - unsigned long fnhe_expires; - unsigned long fnhe_stamp; -}; - -struct fnhe_hash_bucket { - struct fib_nh_exception __rcu *chain; -}; - -#define FNHE_HASH_SIZE 2048 -#define FNHE_RECLAIM_DEPTH 5 - struct fib_nh { struct net_device *nh_dev; struct hlist_node nh_hash; @@ -80,7 +63,6 @@ struct fib_nh { __be32 nh_gw; __be32 nh_saddr; int nh_saddr_genid; - struct fnhe_hash_bucket *nh_exceptions; }; /* @@ -124,10 +106,12 @@ struct fib_result { unsigned char nh_sel; unsigned char type; unsigned char scope; - u32 tclassid; struct fib_info *fi; struct fib_table *table; struct list_head *fa_head; +#ifdef CONFIG_IP_MULTIPLE_TABLES + struct fib_rule *r; +#endif }; struct fib_result_nl { @@ -178,6 +162,7 @@ struct fib_table { u32 tb_id; int tb_default; int tb_num_default; + struct inet_peer_base tb_peers; unsigned long tb_data[0]; }; @@ -231,6 +216,10 @@ static inline int fib_lookup(struct net *net, const struct flowi4 *flp, extern int __net_init fib4_rules_init(struct net *net); extern void __net_exit fib4_rules_exit(struct net *net); +#ifdef CONFIG_IP_ROUTE_CLASSID +extern u32 fib_rules_tclass(const struct fib_result *res); +#endif + extern struct fib_table *fib_new_table(struct net *net, u32 id); extern struct fib_table *fib_get_table(struct net *net, u32 id); @@ -241,7 +230,6 @@ static inline int fib_lookup(struct net *net, struct flowi4 *flp, struct fib_result *res) { if (!net->ipv4.fib_has_custom_rules) { - res->tclassid = 0; if (net->ipv4.fib_local && !fib_table_lookup(net->ipv4.fib_local, flp, res, FIB_LOOKUP_NOREF)) @@ -301,7 +289,7 @@ static inline void fib_combine_itag(u32 *itag, const struct fib_result *res) #endif *itag = FIB_RES_NH(*res).nh_tclassid<<16; #ifdef CONFIG_IP_MULTIPLE_TABLES - rtag = res->tclassid; + rtag = fib_rules_tclass(res); if (*itag == 0) *itag = (rtag<<16); *itag |= (rtag>>16); diff --git a/trunk/include/net/ipv6.h b/trunk/include/net/ipv6.h index f695f39e8926..aecf88436abf 100644 --- a/trunk/include/net/ipv6.h +++ b/trunk/include/net/ipv6.h @@ -251,8 +251,6 @@ static inline void fl6_sock_release(struct ip6_flowlabel *fl) atomic_dec(&fl->users); } -extern void icmpv6_notify(struct sk_buff *skb, u8 type, u8 code, __be32 info); - extern int ip6_ra_control(struct sock *sk, int sel); extern int ipv6_parse_hopopts(struct sk_buff *skb); @@ -300,23 +298,14 @@ static inline int ipv6_addr_cmp(const struct in6_addr *a1, const struct in6_addr return memcmp(a1, a2, sizeof(struct in6_addr)); } -static inline bool +static inline int ipv6_masked_addr_cmp(const struct in6_addr *a1, const struct in6_addr *m, const struct in6_addr *a2) { -#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && BITS_PER_LONG == 64 - const unsigned long *ul1 = (const unsigned long *)a1; - const unsigned long *ulm = (const unsigned long *)m; - const unsigned long *ul2 = (const unsigned long *)a2; - - return !!(((ul1[0] ^ ul2[0]) & ulm[0]) | - ((ul1[1] ^ ul2[1]) & ulm[1])); -#else return !!(((a1->s6_addr32[0] ^ a2->s6_addr32[0]) & m->s6_addr32[0]) | ((a1->s6_addr32[1] ^ a2->s6_addr32[1]) & m->s6_addr32[1]) | ((a1->s6_addr32[2] ^ a2->s6_addr32[2]) & m->s6_addr32[2]) | ((a1->s6_addr32[3] ^ a2->s6_addr32[3]) & m->s6_addr32[3])); -#endif } static inline void ipv6_addr_prefix(struct in6_addr *pfx, @@ -346,17 +335,10 @@ static inline void ipv6_addr_set(struct in6_addr *addr, static inline bool ipv6_addr_equal(const struct in6_addr *a1, const struct in6_addr *a2) { -#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && BITS_PER_LONG == 64 - const unsigned long *ul1 = (const unsigned long *)a1; - const unsigned long *ul2 = (const unsigned long *)a2; - - return ((ul1[0] ^ ul2[0]) | (ul1[1] ^ ul2[1])) == 0UL; -#else return ((a1->s6_addr32[0] ^ a2->s6_addr32[0]) | (a1->s6_addr32[1] ^ a2->s6_addr32[1]) | (a1->s6_addr32[2] ^ a2->s6_addr32[2]) | (a1->s6_addr32[3] ^ a2->s6_addr32[3])) == 0; -#endif } static inline bool __ipv6_prefix_equal(const __be32 *a1, const __be32 *a2, @@ -409,14 +391,8 @@ bool ip6_frag_match(struct inet_frag_queue *q, void *a); static inline bool ipv6_addr_any(const struct in6_addr *a) { -#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && BITS_PER_LONG == 64 - const unsigned long *ul = (const unsigned long *)a; - - return (ul[0] | ul[1]) == 0UL; -#else return (a->s6_addr32[0] | a->s6_addr32[1] | a->s6_addr32[2] | a->s6_addr32[3]) == 0; -#endif } static inline bool ipv6_addr_loopback(const struct in6_addr *a) diff --git a/trunk/include/net/mac80211.h b/trunk/include/net/mac80211.h index e3fa90ce9ecb..670a58ba8a41 100644 --- a/trunk/include/net/mac80211.h +++ b/trunk/include/net/mac80211.h @@ -475,7 +475,7 @@ enum mac80211_rate_control_flags { #define IEEE80211_TX_INFO_RATE_DRIVER_DATA_SIZE 24 /* maximum number of rate stages */ -#define IEEE80211_TX_MAX_RATES 4 +#define IEEE80211_TX_MAX_RATES 5 /** * struct ieee80211_tx_rate - rate selection/status @@ -563,11 +563,11 @@ struct ieee80211_tx_info { } control; struct { struct ieee80211_tx_rate rates[IEEE80211_TX_MAX_RATES]; - int ack_signal; u8 ampdu_ack_len; + int ack_signal; u8 ampdu_len; u8 antenna; - /* 21 bytes free */ + /* 14 bytes free */ } status; struct { struct ieee80211_tx_rate driver_rates[ @@ -634,7 +634,7 @@ ieee80211_tx_info_clear_status(struct ieee80211_tx_info *info) info->status.rates[i].count = 0; BUILD_BUG_ON( - offsetof(struct ieee80211_tx_info, status.ack_signal) != 20); + offsetof(struct ieee80211_tx_info, status.ampdu_ack_len) != 23); memset(&info->status.ampdu_ack_len, 0, sizeof(struct ieee80211_tx_info) - offsetof(struct ieee80211_tx_info, status.ampdu_ack_len)); @@ -1896,6 +1896,19 @@ enum ieee80211_rate_control_changed { * The low-level driver should send the frame out based on * configuration in the TX control data. This handler should, * preferably, never fail and stop queues appropriately. + * This must be implemented if @tx_frags is not. + * Must be atomic. + * + * @tx_frags: Called to transmit multiple fragments of a single MSDU. + * This handler must consume all fragments, sending out some of + * them only is useless and it can't ask for some of them to be + * queued again. If the frame is not fragmented the queue has a + * single SKB only. To avoid issues with the networking stack + * when TX status is reported the frames should be removed from + * the skb queue. + * If this is used, the tx_info @vif and @sta pointers will be + * invalid -- you must not use them in that case. + * This must be implemented if @tx isn't. * Must be atomic. * * @start: Called before the first netdevice attached to the hardware @@ -2244,21 +2257,11 @@ enum ieee80211_rate_control_changed { * @get_rssi: Get current signal strength in dBm, the function is optional * and can sleep. * - * @mgd_prepare_tx: Prepare for transmitting a management frame for association - * before associated. In multi-channel scenarios, a virtual interface is - * bound to a channel before it is associated, but as it isn't associated - * yet it need not necessarily be given airtime, in particular since any - * transmission to a P2P GO needs to be synchronized against the GO's - * powersave state. mac80211 will call this function before transmitting a - * management frame prior to having successfully associated to allow the - * driver to give it channel time for the transmission, to get a response - * and to be able to synchronize with the GO. - * The callback will be called before each transmission and upon return - * mac80211 will transmit the frame right away. - * The callback is optional and can (should!) sleep. */ struct ieee80211_ops { void (*tx)(struct ieee80211_hw *hw, struct sk_buff *skb); + void (*tx_frags)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_sta *sta, struct sk_buff_head *skbs); int (*start)(struct ieee80211_hw *hw); void (*stop)(struct ieee80211_hw *hw); #ifdef CONFIG_PM @@ -2395,9 +2398,6 @@ struct ieee80211_ops { u32 sset, u8 *data); int (*get_rssi)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta, s8 *rssi_dbm); - - void (*mgd_prepare_tx)(struct ieee80211_hw *hw, - struct ieee80211_vif *vif); }; /** @@ -3832,6 +3832,12 @@ void ieee80211_enable_rssi_reports(struct ieee80211_vif *vif, void ieee80211_disable_rssi_reports(struct ieee80211_vif *vif); +int ieee80211_add_srates_ie(struct ieee80211_vif *vif, + struct sk_buff *skb, bool need_basic); + +int ieee80211_add_ext_srates_ie(struct ieee80211_vif *vif, + struct sk_buff *skb, bool need_basic); + /** * ieee80211_ave_rssi - report the average rssi for the specified interface * diff --git a/trunk/include/net/ndisc.h b/trunk/include/net/ndisc.h index 96a3b5c03e37..c02b6ad3f6c5 100644 --- a/trunk/include/net/ndisc.h +++ b/trunk/include/net/ndisc.h @@ -47,8 +47,6 @@ enum { #include #include #include -#include -#include #include @@ -82,54 +80,6 @@ struct nd_opt_hdr { __u8 nd_opt_len; } __packed; -/* ND options */ -struct ndisc_options { - struct nd_opt_hdr *nd_opt_array[__ND_OPT_ARRAY_MAX]; -#ifdef CONFIG_IPV6_ROUTE_INFO - struct nd_opt_hdr *nd_opts_ri; - struct nd_opt_hdr *nd_opts_ri_end; -#endif - struct nd_opt_hdr *nd_useropts; - struct nd_opt_hdr *nd_useropts_end; -}; - -#define nd_opts_src_lladdr nd_opt_array[ND_OPT_SOURCE_LL_ADDR] -#define nd_opts_tgt_lladdr nd_opt_array[ND_OPT_TARGET_LL_ADDR] -#define nd_opts_pi nd_opt_array[ND_OPT_PREFIX_INFO] -#define nd_opts_pi_end nd_opt_array[__ND_OPT_PREFIX_INFO_END] -#define nd_opts_rh nd_opt_array[ND_OPT_REDIRECT_HDR] -#define nd_opts_mtu nd_opt_array[ND_OPT_MTU] - -#define NDISC_OPT_SPACE(len) (((len)+2+7)&~7) - -extern struct ndisc_options *ndisc_parse_options(u8 *opt, int opt_len, - struct ndisc_options *ndopts); - -/* - * Return the padding between the option length and the start of the - * link addr. Currently only IP-over-InfiniBand needs this, although - * if RFC 3831 IPv6-over-Fibre Channel is ever implemented it may - * also need a pad of 2. - */ -static int ndisc_addr_option_pad(unsigned short type) -{ - switch (type) { - case ARPHRD_INFINIBAND: return 2; - default: return 0; - } -} - -static inline u8 *ndisc_opt_addr_data(struct nd_opt_hdr *p, - struct net_device *dev) -{ - u8 *lladdr = (u8 *)(p + 1); - int lladdrlen = p->nd_opt_len << 3; - int prepad = ndisc_addr_option_pad(dev->type); - if (lladdrlen != NDISC_OPT_SPACE(dev->addr_len + prepad)) - return NULL; - return lladdr + prepad; -} - static inline u32 ndisc_hashfn(const void *pkey, const struct net_device *dev, __u32 *hash_rnd) { const u32 *p32 = pkey; diff --git a/trunk/include/net/net_namespace.h b/trunk/include/net/net_namespace.h index ae1cd6c9ba52..ac9195e6a062 100644 --- a/trunk/include/net/net_namespace.h +++ b/trunk/include/net/net_namespace.h @@ -101,7 +101,6 @@ struct net { struct netns_xfrm xfrm; #endif struct netns_ipvs *ipvs; - struct sock *diag_nlsk; }; diff --git a/trunk/include/net/netfilter/nf_conntrack_ecache.h b/trunk/include/net/netfilter/nf_conntrack_ecache.h index e1ce1048fe5f..a88fb6939387 100644 --- a/trunk/include/net/netfilter/nf_conntrack_ecache.h +++ b/trunk/include/net/netfilter/nf_conntrack_ecache.h @@ -78,7 +78,7 @@ nf_conntrack_event_cache(enum ip_conntrack_events event, struct nf_conn *ct) struct net *net = nf_ct_net(ct); struct nf_conntrack_ecache *e; - if (!rcu_access_pointer(net->ct.nf_conntrack_event_cb)) + if (net->ct.nf_conntrack_event_cb == NULL) return; e = nf_ct_ecache_find(ct); diff --git a/trunk/include/net/netfilter/nf_conntrack_l4proto.h b/trunk/include/net/netfilter/nf_conntrack_l4proto.h index c3be4aef6bf7..81c52b5205f2 100644 --- a/trunk/include/net/netfilter/nf_conntrack_l4proto.h +++ b/trunk/include/net/netfilter/nf_conntrack_l4proto.h @@ -97,10 +97,7 @@ struct nf_conntrack_l4proto { #endif int *net_id; /* Init l4proto pernet data */ - int (*init_net)(struct net *net, u_int16_t proto); - - /* Return the per-net protocol part. */ - struct nf_proto_net *(*get_net_proto)(struct net *net); + int (*init_net)(struct net *net); /* Protocol name */ const char *name; @@ -127,14 +124,6 @@ extern int nf_conntrack_l4proto_register(struct net *net, extern void nf_conntrack_l4proto_unregister(struct net *net, struct nf_conntrack_l4proto *proto); -static inline void nf_ct_kfree_compat_sysctl_table(struct nf_proto_net *pn) -{ -#if defined(CONFIG_SYSCTL) && defined(CONFIG_NF_CONNTRACK_PROC_COMPAT) - kfree(pn->ctl_compat_table); - pn->ctl_compat_table = NULL; -#endif -} - /* Generic netlink helpers */ extern int nf_ct_port_tuple_to_nlattr(struct sk_buff *skb, const struct nf_conntrack_tuple *tuple); diff --git a/trunk/include/net/netns/ipv4.h b/trunk/include/net/netns/ipv4.h index 2e089a99d603..599e48fa97cb 100644 --- a/trunk/include/net/netns/ipv4.h +++ b/trunk/include/net/netns/ipv4.h @@ -7,7 +7,6 @@ #include -struct tcpm_hash_bucket; struct ctl_table_header; struct ipv4_devconf; struct fib_rules_ops; @@ -40,8 +39,6 @@ struct netns_ipv4 { struct sock **icmp_sk; struct sock *tcp_sock; struct inet_peer_base *peers; - struct tcpm_hash_bucket *tcp_metrics_hash; - unsigned int tcp_metrics_hash_mask; struct netns_frags frags; #ifdef CONFIG_NETFILTER struct xt_table *iptable_filter; diff --git a/trunk/include/net/nfc/hci.h b/trunk/include/net/nfc/hci.h index f5169b04f082..e30e6a869714 100644 --- a/trunk/include/net/nfc/hci.h +++ b/trunk/include/net/nfc/hci.h @@ -44,20 +44,10 @@ struct nfc_hci_ops { struct nfc_target *target); }; -/* Pipes */ -#define NFC_HCI_INVALID_PIPE 0x80 -#define NFC_HCI_LINK_MGMT_PIPE 0x00 -#define NFC_HCI_ADMIN_PIPE 0x01 - -struct nfc_hci_gate { - u8 gate; - u8 pipe; -}; - -#define NFC_HCI_MAX_CUSTOM_GATES 50 +#define NFC_HCI_MAX_CUSTOM_GATES 15 struct nfc_hci_init_data { u8 gate_count; - struct nfc_hci_gate gates[NFC_HCI_MAX_CUSTOM_GATES]; + u8 gates[NFC_HCI_MAX_CUSTOM_GATES]; char session_id[9]; }; @@ -122,8 +112,6 @@ void nfc_hci_unregister_device(struct nfc_hci_dev *hdev); void nfc_hci_set_clientdata(struct nfc_hci_dev *hdev, void *clientdata); void *nfc_hci_get_clientdata(struct nfc_hci_dev *hdev); -void nfc_hci_driver_failure(struct nfc_hci_dev *hdev, int err); - /* Host IDs */ #define NFC_HCI_HOST_CONTROLLER_ID 0x00 #define NFC_HCI_TERMINAL_HOST_ID 0x01 @@ -192,8 +180,7 @@ void nfc_hci_event_received(struct nfc_hci_dev *hdev, u8 pipe, u8 event, void nfc_hci_recv_frame(struct nfc_hci_dev *hdev, struct sk_buff *skb); /* connecting to gates and sending hci instructions */ -int nfc_hci_connect_gate(struct nfc_hci_dev *hdev, u8 dest_host, u8 dest_gate, - u8 pipe); +int nfc_hci_connect_gate(struct nfc_hci_dev *hdev, u8 dest_host, u8 dest_gate); int nfc_hci_disconnect_gate(struct nfc_hci_dev *hdev, u8 gate); int nfc_hci_disconnect_all_gates(struct nfc_hci_dev *hdev); int nfc_hci_get_param(struct nfc_hci_dev *hdev, u8 gate, u8 idx, diff --git a/trunk/include/net/nfc/nfc.h b/trunk/include/net/nfc/nfc.h index 6431f5e39022..180964b954ab 100644 --- a/trunk/include/net/nfc/nfc.h +++ b/trunk/include/net/nfc/nfc.h @@ -204,6 +204,4 @@ int nfc_tm_activated(struct nfc_dev *dev, u32 protocol, u8 comm_mode, int nfc_tm_deactivated(struct nfc_dev *dev); int nfc_tm_data_received(struct nfc_dev *dev, struct sk_buff *skb); -void nfc_driver_failure(struct nfc_dev *dev, int err); - #endif /* __NET_NFC_H */ diff --git a/trunk/include/net/route.h b/trunk/include/net/route.h index ace3cb442519..211e2665139b 100644 --- a/trunk/include/net/route.h +++ b/trunk/include/net/route.h @@ -40,6 +40,7 @@ #define RT_CONN_FLAGS(sk) (RT_TOS(inet_sk(sk)->tos) | sock_flag(sk, SOCK_LOCALROUTE)) struct fib_nh; +struct inet_peer; struct fib_info; struct rtable { struct dst_entry dst; @@ -64,10 +65,45 @@ struct rtable { __be32 rt_gateway; /* Miscellaneous cached information */ - u32 rt_pmtu; + u32 rt_peer_genid; + unsigned long _peer; /* long-living peer info */ struct fib_info *fi; /* for client ref to shared metrics */ }; +static inline struct inet_peer *rt_peer_ptr(struct rtable *rt) +{ + return inetpeer_ptr(rt->_peer); +} + +static inline bool rt_has_peer(struct rtable *rt) +{ + return inetpeer_ptr_is_peer(rt->_peer); +} + +static inline void __rt_set_peer(struct rtable *rt, struct inet_peer *peer) +{ + __inetpeer_ptr_set_peer(&rt->_peer, peer); +} + +static inline bool rt_set_peer(struct rtable *rt, struct inet_peer *peer) +{ + return inetpeer_ptr_set_peer(&rt->_peer, peer); +} + +static inline void rt_init_peer(struct rtable *rt, struct inet_peer_base *base) +{ + inetpeer_init_ptr(&rt->_peer, base); +} + +static inline void rt_transfer_peer(struct rtable *rt, struct rtable *ort) +{ + rt->_peer = ort->_peer; + if (rt_has_peer(ort)) { + struct inet_peer *peer = rt_peer_ptr(ort); + atomic_inc(&peer->refcnt); + } +} + static inline bool rt_is_input_route(const struct rtable *rt) { return rt->rt_route_iif != 0; @@ -108,6 +144,8 @@ extern struct ip_rt_acct __percpu *ip_rt_acct; struct in_device; extern int ip_rt_init(void); +extern void ip_rt_redirect(__be32 old_gw, __be32 dst, __be32 new_gw, + __be32 src, struct net_device *dev); extern void rt_cache_flush(struct net *net, int how); extern void rt_cache_flush_batch(struct net *net); extern struct rtable *__ip_route_output_key(struct net *, struct flowi4 *flp); @@ -179,9 +217,6 @@ static inline int ip_route_input_noref(struct sk_buff *skb, __be32 dst, __be32 s extern void ipv4_update_pmtu(struct sk_buff *skb, struct net *net, u32 mtu, int oif, u32 mark, u8 protocol, int flow_flags); extern void ipv4_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, u32 mtu); -extern void ipv4_redirect(struct sk_buff *skb, struct net *net, - int oif, u32 mark, u8 protocol, int flow_flags); -extern void ipv4_sk_redirect(struct sk_buff *skb, struct sock *sk); extern void ip_rt_send_redirect(struct sk_buff *skb); extern unsigned int inet_addr_type(struct net *net, __be32 addr); @@ -243,6 +278,8 @@ static inline void ip_route_connect_init(struct flowi4 *fl4, __be32 dst, __be32 if (inet_sk(sk)->transparent) flow_flags |= FLOWI_FLAG_ANYSRC; + if (protocol == IPPROTO_TCP) + flow_flags |= FLOWI_FLAG_PRECOW_METRICS; if (can_sleep) flow_flags |= FLOWI_FLAG_CAN_SLEEP; @@ -291,6 +328,27 @@ static inline struct rtable *ip_route_newports(struct flowi4 *fl4, struct rtable return rt; } +extern void rt_bind_peer(struct rtable *rt, __be32 daddr, int create); + +static inline struct inet_peer *__rt_get_peer(struct rtable *rt, __be32 daddr, int create) +{ + if (rt_has_peer(rt)) + return rt_peer_ptr(rt); + + rt_bind_peer(rt, daddr, create); + return (rt_has_peer(rt) ? rt_peer_ptr(rt) : NULL); +} + +static inline struct inet_peer *rt_get_peer(struct rtable *rt, __be32 daddr) +{ + return __rt_get_peer(rt, daddr, 0); +} + +static inline struct inet_peer *rt_get_peer_create(struct rtable *rt, __be32 daddr) +{ + return __rt_get_peer(rt, daddr, 1); +} + static inline int inet_iif(const struct sk_buff *skb) { return skb_rtable(skb)->rt_iif; diff --git a/trunk/include/net/sctp/sctp.h b/trunk/include/net/sctp/sctp.h index ff499640528b..a2ef81466b00 100644 --- a/trunk/include/net/sctp/sctp.h +++ b/trunk/include/net/sctp/sctp.h @@ -162,8 +162,6 @@ struct sock *sctp_err_lookup(int family, struct sk_buff *, void sctp_err_finish(struct sock *, struct sctp_association *); void sctp_icmp_frag_needed(struct sock *, struct sctp_association *, struct sctp_transport *t, __u32 pmtu); -void sctp_icmp_redirect(struct sock *, struct sctp_transport *, - struct sk_buff *); void sctp_icmp_proto_unreachable(struct sock *sk, struct sctp_association *asoc, struct sctp_transport *t); @@ -519,10 +517,10 @@ static inline int sctp_frag_point(const struct sctp_association *asoc, int pmtu) return frag; } -static inline void sctp_assoc_pending_pmtu(struct sock *sk, struct sctp_association *asoc) +static inline void sctp_assoc_pending_pmtu(struct sctp_association *asoc) { - sctp_assoc_sync_pmtu(sk, asoc); + sctp_assoc_sync_pmtu(asoc); asoc->pmtu_pending = 0; } diff --git a/trunk/include/net/sctp/structs.h b/trunk/include/net/sctp/structs.h index 536e439ddf1d..fecdf31816f2 100644 --- a/trunk/include/net/sctp/structs.h +++ b/trunk/include/net/sctp/structs.h @@ -1091,7 +1091,7 @@ void sctp_transport_burst_limited(struct sctp_transport *); void sctp_transport_burst_reset(struct sctp_transport *); unsigned long sctp_transport_timeout(struct sctp_transport *); void sctp_transport_reset(struct sctp_transport *); -void sctp_transport_update_pmtu(struct sock *, struct sctp_transport *, u32); +void sctp_transport_update_pmtu(struct sctp_transport *, u32); void sctp_transport_immediate_rtx(struct sctp_transport *); @@ -2003,7 +2003,7 @@ void sctp_assoc_update(struct sctp_association *old, __u32 sctp_association_get_next_tsn(struct sctp_association *); -void sctp_assoc_sync_pmtu(struct sock *, struct sctp_association *); +void sctp_assoc_sync_pmtu(struct sctp_association *); void sctp_assoc_rwnd_increase(struct sctp_association *, unsigned int); void sctp_assoc_rwnd_decrease(struct sctp_association *, unsigned int); void sctp_assoc_set_primary(struct sctp_association *, diff --git a/trunk/include/net/sock.h b/trunk/include/net/sock.h index 88de092df50f..dcb54a0793ec 100644 --- a/trunk/include/net/sock.h +++ b/trunk/include/net/sock.h @@ -858,8 +858,6 @@ struct proto { int (*backlog_rcv) (struct sock *sk, struct sk_buff *skb); - void (*release_cb)(struct sock *sk); - /* Keeping track of sk's, looking them up, and port selection methods. */ void (*hash)(struct sock *sk); void (*unhash)(struct sock *sk); diff --git a/trunk/include/net/tcp.h b/trunk/include/net/tcp.h index 85c5090bfe25..53fb7d814170 100644 --- a/trunk/include/net/tcp.h +++ b/trunk/include/net/tcp.h @@ -253,8 +253,6 @@ extern int sysctl_tcp_cookie_size; extern int sysctl_tcp_thin_linear_timeouts; extern int sysctl_tcp_thin_dupack; extern int sysctl_tcp_early_retrans; -extern int sysctl_tcp_limit_output_bytes; -extern int sysctl_tcp_challenge_ack_limit; extern atomic_long_t tcp_memory_allocated; extern struct percpu_counter tcp_sockets_allocated; @@ -323,8 +321,6 @@ extern struct proto tcp_prot; extern void tcp_init_mem(struct net *net); -extern void tcp_tasklet_init(void); - extern void tcp_v4_err(struct sk_buff *skb, u32); extern void tcp_shutdown (struct sock *sk, int how); @@ -338,7 +334,6 @@ extern int tcp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, size_t size); extern int tcp_sendpage(struct sock *sk, struct page *page, int offset, size_t size, int flags); -extern void tcp_release_cb(struct sock *sk); extern int tcp_ioctl(struct sock *sk, int cmd, unsigned long arg); extern int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb, const struct tcphdr *th, unsigned int len); @@ -393,13 +388,6 @@ extern void tcp_enter_frto(struct sock *sk); extern void tcp_enter_loss(struct sock *sk, int how); extern void tcp_clear_retrans(struct tcp_sock *tp); extern void tcp_update_metrics(struct sock *sk); -extern void tcp_init_metrics(struct sock *sk); -extern void tcp_metrics_init(void); -extern bool tcp_peer_is_proven(struct request_sock *req, struct dst_entry *dst, bool paws_check); -extern bool tcp_remember_stamp(struct sock *sk); -extern bool tcp_tw_remember_stamp(struct inet_timewait_sock *tw); -extern void tcp_fetch_timewait_stamp(struct sock *sk, struct dst_entry *dst); -extern void tcp_disable_fack(struct tcp_sock *tp); extern void tcp_close(struct sock *sk, long timeout); extern void tcp_init_sock(struct sock *sk); extern unsigned int tcp_poll(struct file * file, struct socket *sock, @@ -568,8 +556,6 @@ static inline u32 __tcp_set_rto(const struct tcp_sock *tp) return (tp->srtt >> 3) + tp->rttvar; } -extern void tcp_set_rto(struct sock *sk); - static inline void __tcp_fast_path_on(struct tcp_sock *tp, u32 snd_wnd) { tp->pred_flags = htonl((tp->tcp_header_len << 26) | diff --git a/trunk/net/8021q/vlan.c b/trunk/net/8021q/vlan.c index 9096bcb08132..6089f0cf23b4 100644 --- a/trunk/net/8021q/vlan.c +++ b/trunk/net/8021q/vlan.c @@ -403,9 +403,6 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event, break; case NETDEV_DOWN: - if (dev->features & NETIF_F_HW_VLAN_FILTER) - vlan_vid_del(dev, 0); - /* Put all VLANs for this dev in the down state too. */ for (i = 0; i < VLAN_N_VID; i++) { vlandev = vlan_group_get_device(grp, i); diff --git a/trunk/net/8021q/vlan_dev.c b/trunk/net/8021q/vlan_dev.c index 73a2a83ee2da..da1bc9c3cf38 100644 --- a/trunk/net/8021q/vlan_dev.c +++ b/trunk/net/8021q/vlan_dev.c @@ -681,7 +681,10 @@ static int vlan_dev_netpoll_setup(struct net_device *dev, struct netpoll_info *n if (!netpoll) goto out; - err = __netpoll_setup(netpoll, real_dev); + netpoll->dev = real_dev; + strlcpy(netpoll->dev_name, real_dev->name, IFNAMSIZ); + + err = __netpoll_setup(netpoll); if (err) { kfree(netpoll); goto out; diff --git a/trunk/net/9p/trans_virtio.c b/trunk/net/9p/trans_virtio.c index 35b8911b1c8e..2a167658bb95 100644 --- a/trunk/net/9p/trans_virtio.c +++ b/trunk/net/9p/trans_virtio.c @@ -212,7 +212,7 @@ static int p9_virtio_cancel(struct p9_client *client, struct p9_req_t *req) * this takes a list of pages. * @sg: scatter/gather list to pack into * @start: which segment of the sg_list to start at - * @pdata: a list of pages to add into sg. + * @**pdata: a list of pages to add into sg. * @nr_pages: number of pages to pack into the scatter/gather list * @data: data to pack into scatter/gather list * @count: amount of data to pack into the scatter/gather list diff --git a/trunk/net/appletalk/ddp.c b/trunk/net/appletalk/ddp.c index 33475291c9c1..86852963b7f7 100644 --- a/trunk/net/appletalk/ddp.c +++ b/trunk/net/appletalk/ddp.c @@ -129,8 +129,8 @@ static struct sock *atalk_search_socket(struct sockaddr_at *to, /** * atalk_find_or_insert_socket - Try to find a socket matching ADDR - * @sk: socket to insert in the list if it is not there already - * @sat: address to search for + * @sk - socket to insert in the list if it is not there already + * @sat - address to search for * * Try to find a socket matching ADDR in the socket list, if found then return * it. If not, insert SK into the socket list. @@ -1066,8 +1066,8 @@ static int atalk_release(struct socket *sock) /** * atalk_pick_and_bind_port - Pick a source port when one is not given - * @sk: socket to insert into the tables - * @sat: address to search for + * @sk - socket to insert into the tables + * @sat - address to search for * * Pick a source port when one is not given. If we can find a suitable free * one, we insert the socket into the tables using it. diff --git a/trunk/net/ax25/ax25_addr.c b/trunk/net/ax25/ax25_addr.c index e7c9b0ea17a1..9162409559cf 100644 --- a/trunk/net/ax25/ax25_addr.c +++ b/trunk/net/ax25/ax25_addr.c @@ -189,10 +189,8 @@ const unsigned char *ax25_addr_parse(const unsigned char *buf, int len, digi->ndigi = 0; while (!(buf[-1] & AX25_EBIT)) { - if (d >= AX25_MAX_DIGIS) - return NULL; - if (len < AX25_ADDR_LEN) - return NULL; + if (d >= AX25_MAX_DIGIS) return NULL; /* Max of 6 digis */ + if (len < 7) return NULL; /* Short packet */ memcpy(&digi->calls[d], buf, AX25_ADDR_LEN); digi->ndigi = d + 1; diff --git a/trunk/net/batman-adv/bridge_loop_avoidance.c b/trunk/net/batman-adv/bridge_loop_avoidance.c index 6705d35b17ce..49e10d91c00b 100644 --- a/trunk/net/batman-adv/bridge_loop_avoidance.c +++ b/trunk/net/batman-adv/bridge_loop_avoidance.c @@ -162,13 +162,12 @@ static struct batadv_claim *batadv_claim_hash_find(struct batadv_priv *bat_priv, return claim_tmp; } -/** - * batadv_backbone_hash_find - looks for a claim in the hash - * @bat_priv: the bat priv with all the soft interface information +/* @bat_priv: the bat priv with all the soft interface information * @addr: the address of the originator * @vid: the VLAN ID * - * Returns claim if found or NULL otherwise. + * looks for a claim in the hash, and returns it if found + * or NULL otherwise. */ static struct batadv_backbone_gw * batadv_backbone_hash_find(struct batadv_priv *bat_priv, @@ -243,12 +242,12 @@ batadv_bla_del_backbone_claims(struct batadv_backbone_gw *backbone_gw) backbone_gw->crc = BATADV_BLA_CRC_INIT; } -/** - * batadv_bla_send_claim - sends a claim frame according to the provided info - * @bat_priv: the bat priv with all the soft interface information +/* @bat_priv: the bat priv with all the soft interface information * @orig: the mac address to be announced within the claim * @vid: the VLAN ID * @claimtype: the type of the claim (CLAIM, UNCLAIM, ANNOUNCE, ...) + * + * sends a claim frame according to the provided info. */ static void batadv_bla_send_claim(struct batadv_priv *bat_priv, uint8_t *mac, short vid, int claimtype) @@ -349,9 +348,7 @@ static void batadv_bla_send_claim(struct batadv_priv *bat_priv, uint8_t *mac, batadv_hardif_free_ref(primary_if); } -/** - * batadv_bla_get_backbone_gw - * @bat_priv: the bat priv with all the soft interface information +/* @bat_priv: the bat priv with all the soft interface information * @orig: the mac address of the originator * @vid: the VLAN ID * @@ -523,12 +520,12 @@ static void batadv_bla_send_announce(struct batadv_priv *bat_priv, } -/** - * batadv_bla_add_claim - Adds a claim in the claim hash - * @bat_priv: the bat priv with all the soft interface information +/* @bat_priv: the bat priv with all the soft interface information * @mac: the mac address of the claim * @vid: the VLAN ID of the frame * @backbone_gw: the backbone gateway which claims it + * + * Adds a claim in the claim hash. */ static void batadv_bla_add_claim(struct batadv_priv *bat_priv, const uint8_t *mac, const short vid, @@ -746,9 +743,7 @@ static int batadv_handle_claim(struct batadv_priv *bat_priv, return 1; } -/** - * batadv_check_claim_group - * @bat_priv: the bat priv with all the soft interface information +/* @bat_priv: the bat priv with all the soft interface information * @hw_src: the Hardware source in the ARP Header * @hw_dst: the Hardware destination in the ARP Header * @ethhdr: pointer to the Ethernet header of the claim frame @@ -980,9 +975,7 @@ static void batadv_bla_purge_backbone_gw(struct batadv_priv *bat_priv, int now) } } -/** - * batadv_bla_purge_claims - * @bat_priv: the bat priv with all the soft interface information +/* @bat_priv: the bat priv with all the soft interface information * @primary_if: the selected primary interface, may be NULL if now is set * @now: whether the whole hash shall be wiped now * @@ -1030,9 +1023,7 @@ static void batadv_bla_purge_claims(struct batadv_priv *bat_priv, } } -/** - * batadv_bla_update_orig_address - * @bat_priv: the bat priv with all the soft interface information +/* @bat_priv: the bat priv with all the soft interface information * @primary_if: the new selected primary_if * @oldif: the old primary interface, may be NULL * @@ -1202,9 +1193,7 @@ int batadv_bla_init(struct batadv_priv *bat_priv) return 0; } -/** - * batadv_bla_check_bcast_duplist - * @bat_priv: the bat priv with all the soft interface information +/* @bat_priv: the bat priv with all the soft interface information * @bcast_packet: originator mac address * @hdr_size: maximum length of the frame * @@ -1308,9 +1297,7 @@ int batadv_bla_is_backbone_gw_orig(struct batadv_priv *bat_priv, uint8_t *orig) } -/** - * batadv_bla_is_backbone_gw - * @skb: the frame to be checked +/* @skb: the frame to be checked * @orig_node: the orig_node of the frame * @hdr_size: maximum length of the frame * @@ -1376,12 +1363,9 @@ void batadv_bla_free(struct batadv_priv *bat_priv) batadv_hardif_free_ref(primary_if); } -/** - * batadv_bla_rx - * @bat_priv: the bat priv with all the soft interface information +/* @bat_priv: the bat priv with all the soft interface information * @skb: the frame to be checked * @vid: the VLAN ID of the frame - * @is_bcast: the packet came in a broadcast packet type. * * bla_rx avoidance checks if: * * we have to race for a claim @@ -1391,8 +1375,7 @@ void batadv_bla_free(struct batadv_priv *bat_priv) * returns 1, otherwise it returns 0 and the caller shall further * process the skb. */ -int batadv_bla_rx(struct batadv_priv *bat_priv, struct sk_buff *skb, short vid, - bool is_bcast) +int batadv_bla_rx(struct batadv_priv *bat_priv, struct sk_buff *skb, short vid) { struct ethhdr *ethhdr; struct batadv_claim search_claim, *claim = NULL; @@ -1411,7 +1394,7 @@ int batadv_bla_rx(struct batadv_priv *bat_priv, struct sk_buff *skb, short vid, if (unlikely(atomic_read(&bat_priv->bla_num_requests))) /* don't allow broadcasts while requests are in flight */ - if (is_multicast_ether_addr(ethhdr->h_dest) && is_bcast) + if (is_multicast_ether_addr(ethhdr->h_dest)) goto handled; memcpy(search_claim.addr, ethhdr->h_source, ETH_ALEN); @@ -1437,13 +1420,8 @@ int batadv_bla_rx(struct batadv_priv *bat_priv, struct sk_buff *skb, short vid, } /* if it is a broadcast ... */ - if (is_multicast_ether_addr(ethhdr->h_dest) && is_bcast) { - /* ... drop it. the responsible gateway is in charge. - * - * We need to check is_bcast because with the gateway - * feature, broadcasts (like DHCP requests) may be sent - * using a unicast packet type. - */ + if (is_multicast_ether_addr(ethhdr->h_dest)) { + /* ... drop it. the responsible gateway is in charge. */ goto handled; } else { /* seems the client considers us as its best gateway. @@ -1472,9 +1450,7 @@ int batadv_bla_rx(struct batadv_priv *bat_priv, struct sk_buff *skb, short vid, return ret; } -/** - * batadv_bla_tx - * @bat_priv: the bat priv with all the soft interface information +/* @bat_priv: the bat priv with all the soft interface information * @skb: the frame to be checked * @vid: the VLAN ID of the frame * diff --git a/trunk/net/batman-adv/bridge_loop_avoidance.h b/trunk/net/batman-adv/bridge_loop_avoidance.h index 563cfbf94a7f..08d13cb1e3df 100644 --- a/trunk/net/batman-adv/bridge_loop_avoidance.h +++ b/trunk/net/batman-adv/bridge_loop_avoidance.h @@ -21,8 +21,7 @@ #define _NET_BATMAN_ADV_BLA_H_ #ifdef CONFIG_BATMAN_ADV_BLA -int batadv_bla_rx(struct batadv_priv *bat_priv, struct sk_buff *skb, short vid, - bool is_bcast); +int batadv_bla_rx(struct batadv_priv *bat_priv, struct sk_buff *skb, short vid); int batadv_bla_tx(struct batadv_priv *bat_priv, struct sk_buff *skb, short vid); int batadv_bla_is_backbone_gw(struct sk_buff *skb, struct batadv_orig_node *orig_node, int hdr_size); @@ -41,8 +40,7 @@ void batadv_bla_free(struct batadv_priv *bat_priv); #else /* ifdef CONFIG_BATMAN_ADV_BLA */ static inline int batadv_bla_rx(struct batadv_priv *bat_priv, - struct sk_buff *skb, short vid, - bool is_bcast) + struct sk_buff *skb, short vid) { return 0; } diff --git a/trunk/net/batman-adv/hash.h b/trunk/net/batman-adv/hash.h index 977de9c75fc2..83990e318e43 100644 --- a/trunk/net/batman-adv/hash.h +++ b/trunk/net/batman-adv/hash.h @@ -81,8 +81,7 @@ static inline void batadv_hash_delete(struct batadv_hashtable *hash, batadv_hash_destroy(hash); } -/** - * batadv_hash_add - adds data to the hashtable +/* hash_add - adds data to the hashtable * @hash: storage hash table * @compare: callback to determine if 2 hash elements are identical * @choose: callback calculating the hash index diff --git a/trunk/net/batman-adv/main.h b/trunk/net/batman-adv/main.h index 5d8fa0757947..b8d4ac17f001 100644 --- a/trunk/net/batman-adv/main.h +++ b/trunk/net/batman-adv/main.h @@ -216,8 +216,7 @@ static inline int batadv_compare_eth(const void *data1, const void *data2) return (memcmp(data1, data2, ETH_ALEN) == 0 ? 1 : 0); } -/** - * has_timed_out - compares current time (jiffies) and timestamp + timeout +/* has_timed_out - compares current time (jiffies) and timestamp + timeout * @timestamp: base value to compare with (in jiffies) * @timeout: added to base value before comparing (in milliseconds) * diff --git a/trunk/net/batman-adv/soft-interface.c b/trunk/net/batman-adv/soft-interface.c index 109ea2aae96c..9e4bb61301ec 100644 --- a/trunk/net/batman-adv/soft-interface.c +++ b/trunk/net/batman-adv/soft-interface.c @@ -267,12 +267,8 @@ void batadv_interface_rx(struct net_device *soft_iface, struct batadv_priv *bat_priv = netdev_priv(soft_iface); struct ethhdr *ethhdr; struct vlan_ethhdr *vhdr; - struct batadv_header *batadv_header = (struct batadv_header *)skb->data; short vid __maybe_unused = -1; __be16 ethertype = __constant_htons(BATADV_ETH_P_BATMAN); - bool is_bcast; - - is_bcast = (batadv_header->packet_type == BATADV_BCAST); /* check if enough space is available for pulling, and pull */ if (!pskb_may_pull(skb, hdr_size)) @@ -319,7 +315,7 @@ void batadv_interface_rx(struct net_device *soft_iface, /* Let the bridge loop avoidance check the packet. If will * not handle it, we can safely push it up. */ - if (batadv_bla_rx(bat_priv, skb, vid, is_bcast)) + if (batadv_bla_rx(bat_priv, skb, vid)) goto out; netif_rx(skb); diff --git a/trunk/net/batman-adv/types.h b/trunk/net/batman-adv/types.h index 12635fd2c3d3..2141c1304898 100644 --- a/trunk/net/batman-adv/types.h +++ b/trunk/net/batman-adv/types.h @@ -44,8 +44,7 @@ struct batadv_hard_iface { struct rcu_head rcu; }; -/** - * struct batadv_orig_node - structure for orig_list maintaining nodes of mesh +/* batadv_orig_node - structure for orig_list maintaining nodes of mesh * @primary_addr: hosts primary interface address * @last_seen: when last packet from this node was received * @bcast_seqno_reset: time when the broadcast seqno window was reset diff --git a/trunk/net/bridge/br_device.c b/trunk/net/bridge/br_device.c index f4be1bbfef26..929e48aed444 100644 --- a/trunk/net/bridge/br_device.c +++ b/trunk/net/bridge/br_device.c @@ -246,7 +246,10 @@ int br_netpoll_enable(struct net_bridge_port *p) if (!np) goto out; - err = __netpoll_setup(np, p->dev); + np->dev = p->dev; + strlcpy(np->dev_name, p->dev->name, IFNAMSIZ); + + err = __netpoll_setup(np); if (err) { kfree(np); goto out; diff --git a/trunk/net/bridge/br_multicast.c b/trunk/net/bridge/br_multicast.c index 241743417f49..b66581208cb2 100644 --- a/trunk/net/bridge/br_multicast.c +++ b/trunk/net/bridge/br_multicast.c @@ -540,11 +540,10 @@ static struct net_bridge_mdb_entry *br_multicast_get_group( if (mdb->size >= max) { max *= 2; - if (unlikely(max > br->hash_max)) { - br_warn(br, "Multicast hash table maximum of %d " - "reached, disabling snooping: %s\n", - br->hash_max, - port ? port->dev->name : br->dev->name); + if (unlikely(max >= br->hash_max)) { + br_warn(br, "Multicast hash table maximum " + "reached, disabling snooping: %s, %d\n", + port ? port->dev->name : br->dev->name, max); err = -E2BIG; disable: br->multicast_disabled = 1; @@ -1161,7 +1160,7 @@ static int br_ip6_multicast_query(struct net_bridge *br, goto out; } mld = (struct mld_msg *) icmp6_hdr(skb); - max_delay = msecs_to_jiffies(ntohs(mld->mld_maxdelay)); + max_delay = msecs_to_jiffies(htons(mld->mld_maxdelay)); if (max_delay) group = &mld->mld_mca; } else if (skb->len >= sizeof(*mld2q)) { diff --git a/trunk/net/bridge/br_netfilter.c b/trunk/net/bridge/br_netfilter.c index 68e8f364bbf8..b98d3d78ca7f 100644 --- a/trunk/net/bridge/br_netfilter.c +++ b/trunk/net/bridge/br_netfilter.c @@ -111,13 +111,7 @@ static inline __be16 pppoe_proto(const struct sk_buff *skb) pppoe_proto(skb) == htons(PPP_IPV6) && \ brnf_filter_pppoe_tagged) -static void fake_update_pmtu(struct dst_entry *dst, struct sock *sk, - struct sk_buff *skb, u32 mtu) -{ -} - -static void fake_redirect(struct dst_entry *dst, struct sock *sk, - struct sk_buff *skb) +static void fake_update_pmtu(struct dst_entry *dst, u32 mtu) { } @@ -142,7 +136,6 @@ static struct dst_ops fake_dst_ops = { .family = AF_INET, .protocol = cpu_to_be16(ETH_P_IP), .update_pmtu = fake_update_pmtu, - .redirect = fake_redirect, .cow_metrics = fake_cow_metrics, .neigh_lookup = fake_neigh_lookup, .mtu = fake_mtu, diff --git a/trunk/net/can/af_can.h b/trunk/net/can/af_can.h index 1dccb4c33894..fd882dbadad3 100644 --- a/trunk/net/can/af_can.h +++ b/trunk/net/can/af_can.h @@ -104,9 +104,6 @@ struct s_pstats { unsigned long rcv_entries_max; }; -/* receive filters subscribed for 'all' CAN devices */ -extern struct dev_rcv_lists can_rx_alldev_list; - /* function prototypes for the CAN networklayer procfs (proc.c) */ extern void can_init_proc(void); extern void can_remove_proc(void); diff --git a/trunk/net/can/gw.c b/trunk/net/can/gw.c index b54d5e695b03..b41acf25668f 100644 --- a/trunk/net/can/gw.c +++ b/trunk/net/can/gw.c @@ -444,14 +444,11 @@ static int cgw_notifier(struct notifier_block *nb, return NOTIFY_DONE; } -static int cgw_put_job(struct sk_buff *skb, struct cgw_job *gwj, int type, - u32 pid, u32 seq, int flags) +static int cgw_put_job(struct sk_buff *skb, struct cgw_job *gwj) { struct cgw_frame_mod mb; struct rtcanmsg *rtcan; - struct nlmsghdr *nlh; - - nlh = nlmsg_put(skb, pid, seq, type, sizeof(*rtcan), flags); + struct nlmsghdr *nlh = nlmsg_put(skb, 0, 0, 0, sizeof(*rtcan), 0); if (!nlh) return -EMSGSIZE; @@ -465,11 +462,15 @@ static int cgw_put_job(struct sk_buff *skb, struct cgw_job *gwj, int type, if (gwj->handled_frames) { if (nla_put_u32(skb, CGW_HANDLED, gwj->handled_frames) < 0) goto cancel; + else + nlh->nlmsg_len += NLA_HDRLEN + NLA_ALIGN(sizeof(u32)); } if (gwj->dropped_frames) { if (nla_put_u32(skb, CGW_DROPPED, gwj->dropped_frames) < 0) goto cancel; + else + nlh->nlmsg_len += NLA_HDRLEN + NLA_ALIGN(sizeof(u32)); } /* check non default settings of attributes */ @@ -479,6 +480,8 @@ static int cgw_put_job(struct sk_buff *skb, struct cgw_job *gwj, int type, mb.modtype = gwj->mod.modtype.and; if (nla_put(skb, CGW_MOD_AND, sizeof(mb), &mb) < 0) goto cancel; + else + nlh->nlmsg_len += NLA_HDRLEN + NLA_ALIGN(sizeof(mb)); } if (gwj->mod.modtype.or) { @@ -486,6 +489,8 @@ static int cgw_put_job(struct sk_buff *skb, struct cgw_job *gwj, int type, mb.modtype = gwj->mod.modtype.or; if (nla_put(skb, CGW_MOD_OR, sizeof(mb), &mb) < 0) goto cancel; + else + nlh->nlmsg_len += NLA_HDRLEN + NLA_ALIGN(sizeof(mb)); } if (gwj->mod.modtype.xor) { @@ -493,6 +498,8 @@ static int cgw_put_job(struct sk_buff *skb, struct cgw_job *gwj, int type, mb.modtype = gwj->mod.modtype.xor; if (nla_put(skb, CGW_MOD_XOR, sizeof(mb), &mb) < 0) goto cancel; + else + nlh->nlmsg_len += NLA_HDRLEN + NLA_ALIGN(sizeof(mb)); } if (gwj->mod.modtype.set) { @@ -500,18 +507,26 @@ static int cgw_put_job(struct sk_buff *skb, struct cgw_job *gwj, int type, mb.modtype = gwj->mod.modtype.set; if (nla_put(skb, CGW_MOD_SET, sizeof(mb), &mb) < 0) goto cancel; + else + nlh->nlmsg_len += NLA_HDRLEN + NLA_ALIGN(sizeof(mb)); } if (gwj->mod.csumfunc.crc8) { if (nla_put(skb, CGW_CS_CRC8, CGW_CS_CRC8_LEN, &gwj->mod.csum.crc8) < 0) goto cancel; + else + nlh->nlmsg_len += NLA_HDRLEN + \ + NLA_ALIGN(CGW_CS_CRC8_LEN); } if (gwj->mod.csumfunc.xor) { if (nla_put(skb, CGW_CS_XOR, CGW_CS_XOR_LEN, &gwj->mod.csum.xor) < 0) goto cancel; + else + nlh->nlmsg_len += NLA_HDRLEN + \ + NLA_ALIGN(CGW_CS_XOR_LEN); } if (gwj->gwtype == CGW_TYPE_CAN_CAN) { @@ -520,16 +535,23 @@ static int cgw_put_job(struct sk_buff *skb, struct cgw_job *gwj, int type, if (nla_put(skb, CGW_FILTER, sizeof(struct can_filter), &gwj->ccgw.filter) < 0) goto cancel; + else + nlh->nlmsg_len += NLA_HDRLEN + + NLA_ALIGN(sizeof(struct can_filter)); } if (nla_put_u32(skb, CGW_SRC_IF, gwj->ccgw.src_idx) < 0) goto cancel; + else + nlh->nlmsg_len += NLA_HDRLEN + NLA_ALIGN(sizeof(u32)); if (nla_put_u32(skb, CGW_DST_IF, gwj->ccgw.dst_idx) < 0) goto cancel; + else + nlh->nlmsg_len += NLA_HDRLEN + NLA_ALIGN(sizeof(u32)); } - return nlmsg_end(skb, nlh); + return skb->len; cancel: nlmsg_cancel(skb, nlh); @@ -549,8 +571,7 @@ static int cgw_dump_jobs(struct sk_buff *skb, struct netlink_callback *cb) if (idx < s_idx) goto cont; - if (cgw_put_job(skb, gwj, RTM_NEWROUTE, NETLINK_CB(cb->skb).pid, - cb->nlh->nlmsg_seq, NLM_F_MULTI) < 0) + if (cgw_put_job(skb, gwj) < 0) break; cont: idx++; @@ -562,18 +583,6 @@ static int cgw_dump_jobs(struct sk_buff *skb, struct netlink_callback *cb) return skb->len; } -static const struct nla_policy cgw_policy[CGW_MAX+1] = { - [CGW_MOD_AND] = { .len = sizeof(struct cgw_frame_mod) }, - [CGW_MOD_OR] = { .len = sizeof(struct cgw_frame_mod) }, - [CGW_MOD_XOR] = { .len = sizeof(struct cgw_frame_mod) }, - [CGW_MOD_SET] = { .len = sizeof(struct cgw_frame_mod) }, - [CGW_CS_XOR] = { .len = sizeof(struct cgw_csum_xor) }, - [CGW_CS_CRC8] = { .len = sizeof(struct cgw_csum_crc8) }, - [CGW_SRC_IF] = { .type = NLA_U32 }, - [CGW_DST_IF] = { .type = NLA_U32 }, - [CGW_FILTER] = { .len = sizeof(struct can_filter) }, -}; - /* check for common and gwtype specific attributes */ static int cgw_parse_attr(struct nlmsghdr *nlh, struct cf_mod *mod, u8 gwtype, void *gwtypeattr) @@ -586,14 +595,14 @@ static int cgw_parse_attr(struct nlmsghdr *nlh, struct cf_mod *mod, /* initialize modification & checksum data space */ memset(mod, 0, sizeof(*mod)); - err = nlmsg_parse(nlh, sizeof(struct rtcanmsg), tb, CGW_MAX, - cgw_policy); + err = nlmsg_parse(nlh, sizeof(struct rtcanmsg), tb, CGW_MAX, NULL); if (err < 0) return err; /* check for AND/OR/XOR/SET modifications */ - if (tb[CGW_MOD_AND]) { + if (tb[CGW_MOD_AND] && + nla_len(tb[CGW_MOD_AND]) == CGW_MODATTR_LEN) { nla_memcpy(&mb, tb[CGW_MOD_AND], CGW_MODATTR_LEN); canframecpy(&mod->modframe.and, &mb.cf); @@ -609,7 +618,8 @@ static int cgw_parse_attr(struct nlmsghdr *nlh, struct cf_mod *mod, mod->modfunc[modidx++] = mod_and_data; } - if (tb[CGW_MOD_OR]) { + if (tb[CGW_MOD_OR] && + nla_len(tb[CGW_MOD_OR]) == CGW_MODATTR_LEN) { nla_memcpy(&mb, tb[CGW_MOD_OR], CGW_MODATTR_LEN); canframecpy(&mod->modframe.or, &mb.cf); @@ -625,7 +635,8 @@ static int cgw_parse_attr(struct nlmsghdr *nlh, struct cf_mod *mod, mod->modfunc[modidx++] = mod_or_data; } - if (tb[CGW_MOD_XOR]) { + if (tb[CGW_MOD_XOR] && + nla_len(tb[CGW_MOD_XOR]) == CGW_MODATTR_LEN) { nla_memcpy(&mb, tb[CGW_MOD_XOR], CGW_MODATTR_LEN); canframecpy(&mod->modframe.xor, &mb.cf); @@ -641,7 +652,8 @@ static int cgw_parse_attr(struct nlmsghdr *nlh, struct cf_mod *mod, mod->modfunc[modidx++] = mod_xor_data; } - if (tb[CGW_MOD_SET]) { + if (tb[CGW_MOD_SET] && + nla_len(tb[CGW_MOD_SET]) == CGW_MODATTR_LEN) { nla_memcpy(&mb, tb[CGW_MOD_SET], CGW_MODATTR_LEN); canframecpy(&mod->modframe.set, &mb.cf); @@ -660,8 +672,11 @@ static int cgw_parse_attr(struct nlmsghdr *nlh, struct cf_mod *mod, /* check for checksum operations after CAN frame modifications */ if (modidx) { - if (tb[CGW_CS_CRC8]) { - struct cgw_csum_crc8 *c = nla_data(tb[CGW_CS_CRC8]); + if (tb[CGW_CS_CRC8] && + nla_len(tb[CGW_CS_CRC8]) == CGW_CS_CRC8_LEN) { + + struct cgw_csum_crc8 *c = (struct cgw_csum_crc8 *)\ + nla_data(tb[CGW_CS_CRC8]); err = cgw_chk_csum_parms(c->from_idx, c->to_idx, c->result_idx); @@ -684,8 +699,11 @@ static int cgw_parse_attr(struct nlmsghdr *nlh, struct cf_mod *mod, mod->csumfunc.crc8 = cgw_csum_crc8_neg; } - if (tb[CGW_CS_XOR]) { - struct cgw_csum_xor *c = nla_data(tb[CGW_CS_XOR]); + if (tb[CGW_CS_XOR] && + nla_len(tb[CGW_CS_XOR]) == CGW_CS_XOR_LEN) { + + struct cgw_csum_xor *c = (struct cgw_csum_xor *)\ + nla_data(tb[CGW_CS_XOR]); err = cgw_chk_csum_parms(c->from_idx, c->to_idx, c->result_idx); @@ -717,7 +735,8 @@ static int cgw_parse_attr(struct nlmsghdr *nlh, struct cf_mod *mod, memset(ccgw, 0, sizeof(*ccgw)); /* check for can_filter in attributes */ - if (tb[CGW_FILTER]) + if (tb[CGW_FILTER] && + nla_len(tb[CGW_FILTER]) == sizeof(struct can_filter)) nla_memcpy(&ccgw->filter, tb[CGW_FILTER], sizeof(struct can_filter)); @@ -727,8 +746,13 @@ static int cgw_parse_attr(struct nlmsghdr *nlh, struct cf_mod *mod, if (!tb[CGW_SRC_IF] || !tb[CGW_DST_IF]) return err; - ccgw->src_idx = nla_get_u32(tb[CGW_SRC_IF]); - ccgw->dst_idx = nla_get_u32(tb[CGW_DST_IF]); + if (nla_len(tb[CGW_SRC_IF]) == sizeof(u32)) + nla_memcpy(&ccgw->src_idx, tb[CGW_SRC_IF], + sizeof(u32)); + + if (nla_len(tb[CGW_DST_IF]) == sizeof(u32)) + nla_memcpy(&ccgw->dst_idx, tb[CGW_DST_IF], + sizeof(u32)); /* both indices set to 0 for flushing all routing entries */ if (!ccgw->src_idx && !ccgw->dst_idx) diff --git a/trunk/net/can/proc.c b/trunk/net/can/proc.c index 3b6dd3180492..ba873c36d2fd 100644 --- a/trunk/net/can/proc.c +++ b/trunk/net/can/proc.c @@ -83,6 +83,9 @@ static const char rx_list_name[][8] = { [RX_EFF] = "rx_eff", }; +/* receive filters subscribed for 'all' CAN devices */ +extern struct dev_rcv_lists can_rx_alldev_list; + /* * af_can statistics stuff */ diff --git a/trunk/net/ceph/pagelist.c b/trunk/net/ceph/pagelist.c index 665cd23020ff..13cb409a7bba 100644 --- a/trunk/net/ceph/pagelist.c +++ b/trunk/net/ceph/pagelist.c @@ -72,7 +72,8 @@ int ceph_pagelist_append(struct ceph_pagelist *pl, const void *buf, size_t len) } EXPORT_SYMBOL(ceph_pagelist_append); -/* Allocate enough pages for a pagelist to append the given amount +/** + * Allocate enough pages for a pagelist to append the given amount * of data without without allocating. * Returns: 0 on success, -ENOMEM on error. */ @@ -94,7 +95,9 @@ int ceph_pagelist_reserve(struct ceph_pagelist *pl, size_t space) } EXPORT_SYMBOL(ceph_pagelist_reserve); -/* Free any pages that have been preallocated. */ +/** + * Free any pages that have been preallocated. + */ int ceph_pagelist_free_reserve(struct ceph_pagelist *pl) { while (!list_empty(&pl->free_list)) { @@ -109,7 +112,9 @@ int ceph_pagelist_free_reserve(struct ceph_pagelist *pl) } EXPORT_SYMBOL(ceph_pagelist_free_reserve); -/* Create a truncation point. */ +/** + * Create a truncation point. + */ void ceph_pagelist_set_cursor(struct ceph_pagelist *pl, struct ceph_pagelist_cursor *c) { @@ -119,7 +124,8 @@ void ceph_pagelist_set_cursor(struct ceph_pagelist *pl, } EXPORT_SYMBOL(ceph_pagelist_set_cursor); -/* Truncate a pagelist to the given point. Move extra pages to reserve. +/** + * Truncate a pagelist to the given point. Move extra pages to reserve. * This won't sleep. * Returns: 0 on success, * -EINVAL if the pagelist doesn't match the trunc point pagelist diff --git a/trunk/net/core/dev.c b/trunk/net/core/dev.c index 73e87c7b4377..69f7a1a393d8 100644 --- a/trunk/net/core/dev.c +++ b/trunk/net/core/dev.c @@ -1691,8 +1691,7 @@ static void dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev) rcu_read_unlock(); } -/** - * netif_setup_tc - Handle tc mappings on real_num_tx_queues change +/* netif_setup_tc - Handle tc mappings on real_num_tx_queues change * @dev: Network device * @txq: number of queues available * @@ -1794,13 +1793,12 @@ int netif_set_real_num_rx_queues(struct net_device *dev, unsigned int rxq) EXPORT_SYMBOL(netif_set_real_num_rx_queues); #endif -/** - * netif_get_num_default_rss_queues - default number of RSS queues +/* netif_get_num_default_rss_queues - default number of RSS queues * * This routine should set an upper limit on the number of RSS queues * used by default by multiqueue devices. */ -int netif_get_num_default_rss_queues(void) +int netif_get_num_default_rss_queues() { return min_t(int, DEFAULT_MAX_NUM_RSS_QUEUES, num_online_cpus()); } @@ -2457,12 +2455,8 @@ static void skb_update_prio(struct sk_buff *skb) { struct netprio_map *map = rcu_dereference_bh(skb->dev->priomap); - if (!skb->priority && skb->sk && map) { - unsigned int prioidx = skb->sk->sk_cgrp_prioidx; - - if (prioidx < map->priomap_len) - skb->priority = map->priomap[prioidx]; - } + if ((!skb->priority) && (skb->sk) && map) + skb->priority = map->priomap[skb->sk->sk_cgrp_prioidx]; } #else #define skb_update_prio(skb) @@ -5676,7 +5670,7 @@ int netdev_refcnt_read(const struct net_device *dev) } EXPORT_SYMBOL(netdev_refcnt_read); -/** +/* * netdev_wait_allrefs - wait until all references are gone. * * This is called when unregistering network devices. diff --git a/trunk/net/core/netpoll.c b/trunk/net/core/netpoll.c index b4c90e42b443..f9f40b932e4b 100644 --- a/trunk/net/core/netpoll.c +++ b/trunk/net/core/netpoll.c @@ -715,16 +715,14 @@ int netpoll_parse_options(struct netpoll *np, char *opt) } EXPORT_SYMBOL(netpoll_parse_options); -int __netpoll_setup(struct netpoll *np, struct net_device *ndev) +int __netpoll_setup(struct netpoll *np) { + struct net_device *ndev = np->dev; struct netpoll_info *npinfo; const struct net_device_ops *ops; unsigned long flags; int err; - np->dev = ndev; - strlcpy(np->dev_name, ndev->name, IFNAMSIZ); - if ((ndev->priv_flags & IFF_DISABLE_NETPOLL) || !ndev->netdev_ops->ndo_poll_controller) { np_err(np, "%s doesn't support polling, aborting\n", @@ -853,11 +851,13 @@ int netpoll_setup(struct netpoll *np) np_info(np, "local IP %pI4\n", &np->local_ip); } + np->dev = ndev; + /* fill up the skb queue */ refill_skbs(); rtnl_lock(); - err = __netpoll_setup(np, ndev); + err = __netpoll_setup(np); rtnl_unlock(); if (err) diff --git a/trunk/net/core/netprio_cgroup.c b/trunk/net/core/netprio_cgroup.c index 3e953eaddbfc..5b8aa2fae48b 100644 --- a/trunk/net/core/netprio_cgroup.c +++ b/trunk/net/core/netprio_cgroup.c @@ -49,9 +49,8 @@ static int get_prioidx(u32 *prio) return -ENOSPC; } set_bit(prioidx, prioidx_map); - if (atomic_read(&max_prioidx) < prioidx) - atomic_set(&max_prioidx, prioidx); spin_unlock_irqrestore(&prioidx_map_lock, flags); + atomic_set(&max_prioidx, prioidx); *prio = prioidx; return 0; } @@ -142,7 +141,7 @@ static void cgrp_destroy(struct cgroup *cgrp) rtnl_lock(); for_each_netdev(&init_net, dev) { map = rtnl_dereference(dev->priomap); - if (map && cs->prioidx < map->priomap_len) + if (map) map->priomap[cs->prioidx] = 0; } rtnl_unlock(); @@ -166,7 +165,7 @@ static int read_priomap(struct cgroup *cont, struct cftype *cft, rcu_read_lock(); for_each_netdev_rcu(&init_net, dev) { map = rcu_dereference(dev->priomap); - priority = (map && prioidx < map->priomap_len) ? map->priomap[prioidx] : 0; + priority = map ? map->priomap[prioidx] : 0; cb->fill(cb, dev->name, priority); } rcu_read_unlock(); diff --git a/trunk/net/core/rtnetlink.c b/trunk/net/core/rtnetlink.c index 045db8ad87c8..2b325c340b44 100644 --- a/trunk/net/core/rtnetlink.c +++ b/trunk/net/core/rtnetlink.c @@ -615,7 +615,7 @@ int rtnetlink_put_metrics(struct sk_buff *skb, u32 *metrics) EXPORT_SYMBOL(rtnetlink_put_metrics); int rtnl_put_cacheinfo(struct sk_buff *skb, struct dst_entry *dst, u32 id, - long expires, u32 error) + u32 ts, u32 tsage, long expires, u32 error) { struct rta_cacheinfo ci = { .rta_lastuse = jiffies_to_clock_t(jiffies - dst->lastuse), @@ -623,6 +623,8 @@ int rtnl_put_cacheinfo(struct sk_buff *skb, struct dst_entry *dst, u32 id, .rta_clntref = atomic_read(&(dst->__refcnt)), .rta_error = error, .rta_id = id, + .rta_ts = ts, + .rta_tsage = tsage, }; if (expires) @@ -2174,7 +2176,7 @@ static int nlmsg_populate_fdb(struct sk_buff *skb, } /** - * ndo_dflt_fdb_dump - default netdevice operation to dump an FDB table. + * ndo_dflt_fdb_dump: default netdevice operation to dump an FDB table. * @nlh: netlink message header * @dev: netdevice * diff --git a/trunk/net/core/skbuff.c b/trunk/net/core/skbuff.c index 8b6d38fdb443..5a789a807ec3 100644 --- a/trunk/net/core/skbuff.c +++ b/trunk/net/core/skbuff.c @@ -296,12 +296,9 @@ EXPORT_SYMBOL(build_skb); struct netdev_alloc_cache { struct page *page; unsigned int offset; - unsigned int pagecnt_bias; }; static DEFINE_PER_CPU(struct netdev_alloc_cache, netdev_alloc_cache); -#define NETDEV_PAGECNT_BIAS (PAGE_SIZE / SMP_CACHE_BYTES) - /** * netdev_alloc_frag - allocate a page fragment * @fragsz: fragment size @@ -320,26 +317,17 @@ void *netdev_alloc_frag(unsigned int fragsz) if (unlikely(!nc->page)) { refill: nc->page = alloc_page(GFP_ATOMIC | __GFP_COLD); - if (unlikely(!nc->page)) - goto end; -recycle: - atomic_set(&nc->page->_count, NETDEV_PAGECNT_BIAS); - nc->pagecnt_bias = NETDEV_PAGECNT_BIAS; nc->offset = 0; } - - if (nc->offset + fragsz > PAGE_SIZE) { - /* avoid unnecessary locked operations if possible */ - if ((atomic_read(&nc->page->_count) == nc->pagecnt_bias) || - atomic_sub_and_test(nc->pagecnt_bias, &nc->page->_count)) - goto recycle; - goto refill; + if (likely(nc->page)) { + if (nc->offset + fragsz > PAGE_SIZE) { + put_page(nc->page); + goto refill; + } + data = page_address(nc->page) + nc->offset; + nc->offset += fragsz; + get_page(nc->page); } - - data = page_address(nc->page) + nc->offset; - nc->offset += fragsz; - nc->pagecnt_bias--; -end: local_irq_restore(flags); return data; } @@ -725,8 +713,7 @@ struct sk_buff *skb_morph(struct sk_buff *dst, struct sk_buff *src) } EXPORT_SYMBOL_GPL(skb_morph); -/** - * skb_copy_ubufs - copy userspace skb frags buffers to kernel +/* skb_copy_ubufs - copy userspace skb frags buffers to kernel * @skb: the skb to modify * @gfp_mask: allocation priority * @@ -2627,7 +2614,7 @@ unsigned int skb_find_text(struct sk_buff *skb, unsigned int from, EXPORT_SYMBOL(skb_find_text); /** - * skb_append_datato_frags - append the user data to a skb + * skb_append_datato_frags: - append the user data to a skb * @sk: sock structure * @skb: skb structure to be appened with user data. * @getfrag: call back function to be used for getting the user data diff --git a/trunk/net/core/sock.c b/trunk/net/core/sock.c index 24039ac12426..929bdcc2383b 100644 --- a/trunk/net/core/sock.c +++ b/trunk/net/core/sock.c @@ -2159,10 +2159,6 @@ void release_sock(struct sock *sk) spin_lock_bh(&sk->sk_lock.slock); if (sk->sk_backlog.tail) __release_sock(sk); - - if (sk->sk_prot->release_cb) - sk->sk_prot->release_cb(sk); - sk->sk_lock.owned = 0; if (waitqueue_active(&sk->sk_lock.wq)) wake_up(&sk->sk_lock.wq); diff --git a/trunk/net/core/sock_diag.c b/trunk/net/core/sock_diag.c index 9d8755e4a7a5..07a29eb34a41 100644 --- a/trunk/net/core/sock_diag.c +++ b/trunk/net/core/sock_diag.c @@ -166,36 +166,23 @@ static void sock_diag_rcv(struct sk_buff *skb) mutex_unlock(&sock_diag_mutex); } -static int __net_init diag_net_init(struct net *net) +struct sock *sock_diag_nlsk; +EXPORT_SYMBOL_GPL(sock_diag_nlsk); + +static int __init sock_diag_init(void) { struct netlink_kernel_cfg cfg = { .input = sock_diag_rcv, }; - net->diag_nlsk = netlink_kernel_create(net, NETLINK_SOCK_DIAG, + sock_diag_nlsk = netlink_kernel_create(&init_net, NETLINK_SOCK_DIAG, THIS_MODULE, &cfg); - return net->diag_nlsk == NULL ? -ENOMEM : 0; -} - -static void __net_exit diag_net_exit(struct net *net) -{ - netlink_kernel_release(net->diag_nlsk); - net->diag_nlsk = NULL; -} - -static struct pernet_operations diag_net_ops = { - .init = diag_net_init, - .exit = diag_net_exit, -}; - -static int __init sock_diag_init(void) -{ - return register_pernet_subsys(&diag_net_ops); + return sock_diag_nlsk == NULL ? -ENOMEM : 0; } static void __exit sock_diag_exit(void) { - unregister_pernet_subsys(&diag_net_ops); + netlink_kernel_release(sock_diag_nlsk); } module_init(sock_diag_init); diff --git a/trunk/net/dcb/dcbnl.c b/trunk/net/dcb/dcbnl.c index 81f2bb62dea3..013da86575e8 100644 --- a/trunk/net/dcb/dcbnl.c +++ b/trunk/net/dcb/dcbnl.c @@ -28,7 +28,8 @@ #include #include -/* Data Center Bridging (DCB) is a collection of Ethernet enhancements +/** + * Data Center Bridging (DCB) is a collection of Ethernet enhancements * intended to allow network traffic with differing requirements * (highly reliable, no drops vs. best effort vs. low latency) to operate * and co-exist on Ethernet. Current DCB features are: diff --git a/trunk/net/dccp/ackvec.h b/trunk/net/dccp/ackvec.h index a269aa7f7923..e2ab0627a5ff 100644 --- a/trunk/net/dccp/ackvec.h +++ b/trunk/net/dccp/ackvec.h @@ -50,8 +50,7 @@ static inline u8 dccp_ackvec_state(const u8 *cell) return *cell & ~DCCPAV_MAX_RUNLEN; } -/** - * struct dccp_ackvec - Ack Vector main data structure +/** struct dccp_ackvec - Ack Vector main data structure * * This implements a fixed-size circular buffer within an array and is largely * based on Appendix A of RFC 4340. @@ -77,8 +76,7 @@ struct dccp_ackvec { struct list_head av_records; }; -/** - * struct dccp_ackvec_record - Records information about sent Ack Vectors +/** struct dccp_ackvec_record - Records information about sent Ack Vectors * * These list entries define the additional information which the HC-Receiver * keeps about recently-sent Ack Vectors; again refer to RFC 4340, Appendix A. @@ -123,7 +121,6 @@ static inline bool dccp_ackvec_is_empty(const struct dccp_ackvec *av) * @len: length of @vec * @nonce: whether @vec had an ECN nonce of 0 or 1 * @node: FIFO - arranged in descending order of ack_ackno - * * This structure is used by CCIDs to access Ack Vectors in a received skb. */ struct dccp_ackvec_parsed { diff --git a/trunk/net/dccp/ccid.c b/trunk/net/dccp/ccid.c index 597557254ddb..48b585a5cba7 100644 --- a/trunk/net/dccp/ccid.c +++ b/trunk/net/dccp/ccid.c @@ -46,7 +46,6 @@ bool ccid_support_check(u8 const *ccid_array, u8 array_len) * ccid_get_builtin_ccids - Populate a list of built-in CCIDs * @ccid_array: pointer to copy into * @array_len: value to return length into - * * This function allocates memory - caller must see that it is freed after use. */ int ccid_get_builtin_ccids(u8 **ccid_array, u8 *array_len) diff --git a/trunk/net/dccp/ccids/ccid3.c b/trunk/net/dccp/ccids/ccid3.c index d65e98798eca..8c67bedf85b0 100644 --- a/trunk/net/dccp/ccids/ccid3.c +++ b/trunk/net/dccp/ccids/ccid3.c @@ -113,7 +113,6 @@ static u32 ccid3_hc_tx_idle_rtt(struct ccid3_hc_tx_sock *hc, ktime_t now) /** * ccid3_hc_tx_update_x - Update allowed sending rate X * @stamp: most recent time if available - can be left NULL. - * * This function tracks draft rfc3448bis, check there for latest details. * * Note: X and X_recv are both stored in units of 64 * bytes/second, to support @@ -162,11 +161,9 @@ static void ccid3_hc_tx_update_x(struct sock *sk, ktime_t *stamp) } } -/** - * ccid3_hc_tx_update_s - Track the mean packet size `s' +/* + * Track the mean packet size `s' (cf. RFC 4342, 5.3 and RFC 3448, 4.1) * @len: DCCP packet payload size in bytes - * - * cf. RFC 4342, 5.3 and RFC 3448, 4.1 */ static inline void ccid3_hc_tx_update_s(struct ccid3_hc_tx_sock *hc, int len) { @@ -273,7 +270,6 @@ static void ccid3_hc_tx_no_feedback_timer(unsigned long data) /** * ccid3_hc_tx_send_packet - Delay-based dequeueing of TX packets * @skb: next packet candidate to send on @sk - * * This function uses the convention of ccid_packet_dequeue_eval() and * returns a millisecond-delay value between 0 and t_mbi = 64000 msec. */ diff --git a/trunk/net/dccp/ccids/lib/loss_interval.c b/trunk/net/dccp/ccids/lib/loss_interval.c index 57f9fd78c4df..497723c4d4bb 100644 --- a/trunk/net/dccp/ccids/lib/loss_interval.c +++ b/trunk/net/dccp/ccids/lib/loss_interval.c @@ -133,7 +133,6 @@ static inline u8 tfrc_lh_is_new_loss(struct tfrc_loss_interval *cur, * @rh: Receive history containing a fresh loss event * @calc_first_li: Caller-dependent routine to compute length of first interval * @sk: Used by @calc_first_li in caller-specific way (subtyping) - * * Updates I_mean and returns 1 if a new interval has in fact been added to @lh. */ int tfrc_lh_interval_add(struct tfrc_loss_hist *lh, struct tfrc_rx_hist *rh, diff --git a/trunk/net/dccp/ccids/lib/packet_history.c b/trunk/net/dccp/ccids/lib/packet_history.c index 08df7a3acb3d..de8fe294bf0b 100644 --- a/trunk/net/dccp/ccids/lib/packet_history.c +++ b/trunk/net/dccp/ccids/lib/packet_history.c @@ -315,7 +315,6 @@ static void __three_after_loss(struct tfrc_rx_hist *h) * @ndp: The NDP count belonging to @skb * @calc_first_li: Caller-dependent computation of first loss interval in @lh * @sk: Used by @calc_first_li (see tfrc_lh_interval_add) - * * Chooses action according to pending loss, updates LI database when a new * loss was detected, and does required post-processing. Returns 1 when caller * should send feedback, 0 otherwise. @@ -388,7 +387,7 @@ static inline struct tfrc_rx_hist_entry * } /** - * tfrc_rx_hist_rtt_prev_s - previously suitable (wrt rtt_last_s) RTT-sampling entry + * tfrc_rx_hist_rtt_prev_s: previously suitable (wrt rtt_last_s) RTT-sampling entry */ static inline struct tfrc_rx_hist_entry * tfrc_rx_hist_rtt_prev_s(const struct tfrc_rx_hist *h) diff --git a/trunk/net/dccp/ccids/lib/tfrc_equation.c b/trunk/net/dccp/ccids/lib/tfrc_equation.c index 88ef98285bec..a052a4377e26 100644 --- a/trunk/net/dccp/ccids/lib/tfrc_equation.c +++ b/trunk/net/dccp/ccids/lib/tfrc_equation.c @@ -611,7 +611,6 @@ static inline u32 tfrc_binsearch(u32 fval, u8 small) * @s: packet size in bytes * @R: RTT scaled by 1000000 (i.e., microseconds) * @p: loss ratio estimate scaled by 1000000 - * * Returns X_calc in bytes per second (not scaled). */ u32 tfrc_calc_x(u16 s, u32 R, u32 p) @@ -660,7 +659,6 @@ u32 tfrc_calc_x(u16 s, u32 R, u32 p) /** * tfrc_calc_x_reverse_lookup - try to find p given f(p) * @fvalue: function value to match, scaled by 1000000 - * * Returns closest match for p, also scaled by 1000000 */ u32 tfrc_calc_x_reverse_lookup(u32 fvalue) diff --git a/trunk/net/dccp/dccp.h b/trunk/net/dccp/dccp.h index 708e75bf623d..9040be049d8c 100644 --- a/trunk/net/dccp/dccp.h +++ b/trunk/net/dccp/dccp.h @@ -352,7 +352,6 @@ static inline int dccp_bad_service_code(const struct sock *sk, * @dccpd_opt_len: total length of all options (5.8) in the packet * @dccpd_seq: sequence number * @dccpd_ack_seq: acknowledgment number subheader field value - * * This is used for transmission as well as for reception. */ struct dccp_skb_cb { diff --git a/trunk/net/dccp/feat.c b/trunk/net/dccp/feat.c index 9733ddbc96cb..78a2ad70e1b0 100644 --- a/trunk/net/dccp/feat.c +++ b/trunk/net/dccp/feat.c @@ -350,7 +350,6 @@ static int __dccp_feat_activate(struct sock *sk, const int idx, * @feat_num: feature to activate, one of %dccp_feature_numbers * @local: whether local (1) or remote (0) @feat_num is meant * @fval: the value (SP or NN) to activate, or NULL to use the default value - * * For general use this function is preferable over __dccp_feat_activate(). */ static int dccp_feat_activate(struct sock *sk, u8 feat_num, bool local, @@ -447,7 +446,6 @@ static struct dccp_feat_entry *dccp_feat_list_lookup(struct list_head *fn_list, * @head: list to add to * @feat: feature number * @local: whether the local (1) or remote feature with number @feat is meant - * * This is the only constructor and serves to ensure the above invariants. */ static struct dccp_feat_entry * @@ -506,7 +504,6 @@ static int dccp_feat_push_change(struct list_head *fn_list, u8 feat, u8 local, * @feat: one of %dccp_feature_numbers * @local: whether local (1) or remote (0) @feat_num is being confirmed * @fval: pointer to NN/SP value to be inserted or NULL - * * Returns 0 on success, a Reset code for further processing otherwise. */ static int dccp_feat_push_confirm(struct list_head *fn_list, u8 feat, u8 local, @@ -694,7 +691,6 @@ int dccp_feat_insert_opts(struct dccp_sock *dp, struct dccp_request_sock *dreq, * @feat: an NN feature from %dccp_feature_numbers * @mandatory: use Mandatory option if 1 * @nn_val: value to register (restricted to 4 bytes) - * * Note that NN features are local by definition (RFC 4340, 6.3.2). */ static int __feat_register_nn(struct list_head *fn, u8 feat, @@ -764,7 +760,6 @@ int dccp_feat_register_sp(struct sock *sk, u8 feat, u8 is_local, * dccp_feat_nn_get - Query current/pending value of NN feature * @sk: DCCP socket of an established connection * @feat: NN feature number from %dccp_feature_numbers - * * For a known NN feature, returns value currently being negotiated, or * current (confirmed) value if no negotiation is going on. */ @@ -795,7 +790,6 @@ EXPORT_SYMBOL_GPL(dccp_feat_nn_get); * @sk: DCCP socket of an established connection * @feat: NN feature number from %dccp_feature_numbers * @nn_val: the new value to use - * * This function is used to communicate NN updates out-of-band. */ int dccp_feat_signal_nn_change(struct sock *sk, u8 feat, u64 nn_val) @@ -936,7 +930,6 @@ static const struct ccid_dependency *dccp_feat_ccid_deps(u8 ccid, bool is_local) * @fn: feature-negotiation list to update * @id: CCID number to track * @is_local: whether TX CCID (1) or RX CCID (0) is meant - * * This function needs to be called after registering all other features. */ static int dccp_feat_propagate_ccid(struct list_head *fn, u8 id, bool is_local) @@ -960,7 +953,6 @@ static int dccp_feat_propagate_ccid(struct list_head *fn, u8 id, bool is_local) /** * dccp_feat_finalise_settings - Finalise settings before starting negotiation * @dp: client or listening socket (settings will be inherited) - * * This is called after all registrations (socket initialisation, sysctls, and * sockopt calls), and before sending the first packet containing Change options * (ie. client-Request or server-Response), to ensure internal consistency. @@ -1292,7 +1284,6 @@ static u8 dccp_feat_confirm_recv(struct list_head *fn, u8 is_mandatory, u8 opt, * @feat: NN number, one of %dccp_feature_numbers * @val: NN value * @len: length of @val in bytes - * * This function combines the functionality of change_recv/confirm_recv, with * the following differences (reset codes are the same): * - cleanup after receiving the Confirm; @@ -1388,7 +1379,6 @@ static u8 dccp_feat_handle_nn_established(struct sock *sk, u8 mandatory, u8 opt, * @feat: one of %dccp_feature_numbers * @val: value contents of @opt * @len: length of @val in bytes - * * Returns 0 on success, a Reset code for ending the connection otherwise. */ int dccp_feat_parse_options(struct sock *sk, struct dccp_request_sock *dreq, diff --git a/trunk/net/dccp/input.c b/trunk/net/dccp/input.c index 14cdafad7a90..bc93a333931e 100644 --- a/trunk/net/dccp/input.c +++ b/trunk/net/dccp/input.c @@ -710,7 +710,6 @@ EXPORT_SYMBOL_GPL(dccp_rcv_state_process); /** * dccp_sample_rtt - Validate and finalise computation of RTT sample * @delta: number of microseconds between packet and acknowledgment - * * The routine is kept generic to work in different contexts. It should be * called immediately when the ACK used for the RTT sample arrives. */ diff --git a/trunk/net/dccp/ipv4.c b/trunk/net/dccp/ipv4.c index ab4f44c9bb21..3eb76b5f221a 100644 --- a/trunk/net/dccp/ipv4.c +++ b/trunk/net/dccp/ipv4.c @@ -161,10 +161,17 @@ static inline void dccp_do_pmtu_discovery(struct sock *sk, if (sk->sk_state == DCCP_LISTEN) return; - dst = inet_csk_update_pmtu(sk, mtu); - if (!dst) + /* We don't check in the destentry if pmtu discovery is forbidden + * on this route. We just assume that no packet_to_big packets + * are send back when pmtu discovery is not active. + * There is a small race when the user changes this flag in the + * route, but I think that's acceptable. + */ + if ((dst = __sk_dst_check(sk, 0)) == NULL) return; + dst->ops->update_pmtu(dst, mtu); + /* Something is about to be wrong... Remember soft error * for the case, if this connection will not able to recover. */ @@ -188,14 +195,6 @@ static inline void dccp_do_pmtu_discovery(struct sock *sk, } /* else let the usual retransmit timer handle it */ } -static void dccp_do_redirect(struct sk_buff *skb, struct sock *sk) -{ - struct dst_entry *dst = __sk_dst_check(sk, 0); - - if (dst) - dst->ops->redirect(dst, sk, skb); -} - /* * This routine is called by the ICMP module when it gets some sort of error * condition. If err < 0 then the socket should be closed and the error @@ -260,9 +259,6 @@ static void dccp_v4_err(struct sk_buff *skb, u32 info) } switch (type) { - case ICMP_REDIRECT: - dccp_do_redirect(skb, sk); - goto out; case ICMP_SOURCE_QUENCH: /* Just silently ignore these. */ goto out; diff --git a/trunk/net/dccp/ipv6.c b/trunk/net/dccp/ipv6.c index 56840b249f3b..02162cfa5048 100644 --- a/trunk/net/dccp/ipv6.c +++ b/trunk/net/dccp/ipv6.c @@ -130,13 +130,6 @@ static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, np = inet6_sk(sk); - if (type == NDISC_REDIRECT) { - struct dst_entry *dst = __sk_dst_check(sk, np->dst_cookie); - - if (dst) - dst->ops->redirect(dst, sk, skb); - } - if (type == ICMPV6_PKT_TOOBIG) { struct dst_entry *dst = NULL; @@ -145,12 +138,39 @@ static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, if ((1 << sk->sk_state) & (DCCPF_LISTEN | DCCPF_CLOSED)) goto out; - dst = inet6_csk_update_pmtu(sk, ntohl(info)); - if (!dst) - goto out; + /* icmp should have updated the destination cache entry */ + dst = __sk_dst_check(sk, np->dst_cookie); + if (dst == NULL) { + struct inet_sock *inet = inet_sk(sk); + struct flowi6 fl6; + + /* BUGGG_FUTURE: Again, it is not clear how + to handle rthdr case. Ignore this complexity + for now. + */ + memset(&fl6, 0, sizeof(fl6)); + fl6.flowi6_proto = IPPROTO_DCCP; + fl6.daddr = np->daddr; + fl6.saddr = np->saddr; + fl6.flowi6_oif = sk->sk_bound_dev_if; + fl6.fl6_dport = inet->inet_dport; + fl6.fl6_sport = inet->inet_sport; + security_sk_classify_flow(sk, flowi6_to_flowi(&fl6)); + + dst = ip6_dst_lookup_flow(sk, &fl6, NULL, false); + if (IS_ERR(dst)) { + sk->sk_err_soft = -PTR_ERR(dst); + goto out; + } + } else + dst_hold(dst); + + dst->ops->update_pmtu(dst, ntohl(info)); - if (inet_csk(sk)->icsk_pmtu_cookie > dst_mtu(dst)) + if (inet_csk(sk)->icsk_pmtu_cookie > dst_mtu(dst)) { dccp_sync_mss(sk, dst_mtu(dst)); + } /* else let the usual retransmit timer handle it */ + dst_release(dst); goto out; } diff --git a/trunk/net/dccp/options.c b/trunk/net/dccp/options.c index a58e0b634050..68fa6b7a3e01 100644 --- a/trunk/net/dccp/options.c +++ b/trunk/net/dccp/options.c @@ -527,7 +527,6 @@ int dccp_insert_option_mandatory(struct sk_buff *skb) * @val: NN value or SP array (preferred element first) to copy * @len: true length of @val in bytes (excluding first element repetition) * @repeat_first: whether to copy the first element of @val twice - * * The last argument is used to construct Confirm options, where the preferred * value and the preference list appear separately (RFC 4340, 6.3.1). Preference * lists are kept such that the preferred entry is always first, so we only need diff --git a/trunk/net/dccp/output.c b/trunk/net/dccp/output.c index d17fc90a74b6..787367308797 100644 --- a/trunk/net/dccp/output.c +++ b/trunk/net/dccp/output.c @@ -214,7 +214,6 @@ void dccp_write_space(struct sock *sk) * dccp_wait_for_ccid - Await CCID send permission * @sk: socket to wait for * @delay: timeout in jiffies - * * This is used by CCIDs which need to delay the send time in process context. */ static int dccp_wait_for_ccid(struct sock *sk, unsigned long delay) diff --git a/trunk/net/decnet/dn_route.c b/trunk/net/decnet/dn_route.c index 47de90d8fe94..6e74b3f110bc 100644 --- a/trunk/net/decnet/dn_route.c +++ b/trunk/net/decnet/dn_route.c @@ -117,10 +117,7 @@ static void dn_dst_destroy(struct dst_entry *); static void dn_dst_ifdown(struct dst_entry *, struct net_device *dev, int how); static struct dst_entry *dn_dst_negative_advice(struct dst_entry *); static void dn_dst_link_failure(struct sk_buff *); -static void dn_dst_update_pmtu(struct dst_entry *dst, struct sock *sk, - struct sk_buff *skb , u32 mtu); -static void dn_dst_redirect(struct dst_entry *dst, struct sock *sk, - struct sk_buff *skb); +static void dn_dst_update_pmtu(struct dst_entry *dst, u32 mtu); static struct neighbour *dn_dst_neigh_lookup(const struct dst_entry *dst, struct sk_buff *skb, const void *daddr); @@ -148,7 +145,6 @@ static struct dst_ops dn_dst_ops = { .negative_advice = dn_dst_negative_advice, .link_failure = dn_dst_link_failure, .update_pmtu = dn_dst_update_pmtu, - .redirect = dn_dst_redirect, .neigh_lookup = dn_dst_neigh_lookup, }; @@ -268,8 +264,7 @@ static int dn_dst_gc(struct dst_ops *ops) * We update both the mtu and the advertised mss (i.e. the segment size we * advertise to the other end). */ -static void dn_dst_update_pmtu(struct dst_entry *dst, struct sock *sk, - struct sk_buff *skb, u32 mtu) +static void dn_dst_update_pmtu(struct dst_entry *dst, u32 mtu) { struct dn_route *rt = (struct dn_route *) dst; struct neighbour *n = rt->n; @@ -297,11 +292,6 @@ static void dn_dst_update_pmtu(struct dst_entry *dst, struct sock *sk, } } -static void dn_dst_redirect(struct dst_entry *dst, struct sock *sk, - struct sk_buff *skb) -{ -} - /* * When a route has been marked obsolete. (e.g. routing cache flush) */ @@ -1600,7 +1590,7 @@ static int dn_rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq, goto errout; expires = rt->dst.expires ? rt->dst.expires - jiffies : 0; - if (rtnl_put_cacheinfo(skb, &rt->dst, 0, expires, + if (rtnl_put_cacheinfo(skb, &rt->dst, 0, 0, 0, expires, rt->dst.error) < 0) goto errout; @@ -1822,11 +1812,12 @@ static int dn_rt_cache_seq_show(struct seq_file *seq, void *v) char buf1[DN_ASCBUF_LEN], buf2[DN_ASCBUF_LEN]; seq_printf(seq, "%-8s %-7s %-7s %04d %04d %04d\n", - rt->dst.dev ? rt->dst.dev->name : "*", - dn_addr2asc(le16_to_cpu(rt->rt_daddr), buf1), - dn_addr2asc(le16_to_cpu(rt->rt_saddr), buf2), - atomic_read(&rt->dst.__refcnt), - rt->dst.__use, 0); + rt->dst.dev ? rt->dst.dev->name : "*", + dn_addr2asc(le16_to_cpu(rt->rt_daddr), buf1), + dn_addr2asc(le16_to_cpu(rt->rt_saddr), buf2), + atomic_read(&rt->dst.__refcnt), + rt->dst.__use, + (int) dst_metric(&rt->dst, RTAX_RTT)); return 0; } diff --git a/trunk/net/ethernet/eth.c b/trunk/net/ethernet/eth.c index 4efad533e5f6..db6a6c17d790 100644 --- a/trunk/net/ethernet/eth.c +++ b/trunk/net/ethernet/eth.c @@ -232,7 +232,6 @@ EXPORT_SYMBOL(eth_header_parse); * @neigh: source neighbour * @hh: destination cache entry * @type: Ethernet type field - * * Create an Ethernet header template from the neighbour. */ int eth_header_cache(const struct neighbour *neigh, struct hh_cache *hh, __be16 type) @@ -275,7 +274,6 @@ EXPORT_SYMBOL(eth_header_cache_update); * eth_mac_addr - set new Ethernet hardware address * @dev: network device * @p: socket address - * * Change hardware address of device. * * This doesn't change hardware matching, so needs to be overridden @@ -333,7 +331,6 @@ const struct header_ops eth_header_ops ____cacheline_aligned = { /** * ether_setup - setup Ethernet network device * @dev: network device - * * Fill in the fields of the device structure with Ethernet-generic values. */ void ether_setup(struct net_device *dev) diff --git a/trunk/net/ieee802154/6lowpan.c b/trunk/net/ieee802154/6lowpan.c index 6a095225148e..f4070e54d1a1 100644 --- a/trunk/net/ieee802154/6lowpan.c +++ b/trunk/net/ieee802154/6lowpan.c @@ -113,6 +113,7 @@ struct lowpan_dev_record { struct lowpan_fragment { struct sk_buff *skb; /* skb to be assembled */ + spinlock_t lock; /* concurency lock */ u16 length; /* length to be assemled */ u32 bytes_rcv; /* bytes received */ u16 tag; /* current fragment tag */ @@ -122,7 +123,7 @@ struct lowpan_fragment { static unsigned short fragment_tag; static LIST_HEAD(lowpan_fragments); -static DEFINE_SPINLOCK(flist_lock); +spinlock_t flist_lock; static inline struct lowpan_dev_info *lowpan_dev_info(const struct net_device *dev) @@ -302,7 +303,7 @@ static inline int lowpan_fetch_skb_u16(struct sk_buff *skb, u16 *val) if (unlikely(!pskb_may_pull(skb, 2))) return -EINVAL; - *val = (skb->data[0] << 8) | skb->data[1]; + *val = skb->data[0] | (skb->data[1] << 8); skb_pull(skb, 2); return 0; @@ -314,9 +315,6 @@ lowpan_uncompress_udp_header(struct sk_buff *skb) struct udphdr *uh = udp_hdr(skb); u8 tmp; - if (!uh) - goto err; - if (lowpan_fetch_skb_u8(skb, &tmp)) goto err; @@ -639,13 +637,16 @@ static void lowpan_fragment_timer_expired(unsigned long entry_addr) pr_debug("timer expired for frame with tag %d\n", entry->tag); + spin_lock(&flist_lock); list_del(&entry->list); + spin_unlock(&flist_lock); + dev_kfree_skb(entry->skb); kfree(entry); } static struct lowpan_fragment * -lowpan_alloc_new_frame(struct sk_buff *skb, u8 len, u16 tag) +lowpan_alloc_new_frame(struct sk_buff *skb, u8 iphc0, u8 len, u8 tag) { struct lowpan_fragment *frame; @@ -656,12 +657,12 @@ lowpan_alloc_new_frame(struct sk_buff *skb, u8 len, u16 tag) INIT_LIST_HEAD(&frame->list); - frame->length = len; + frame->length = (iphc0 & 7) | (len << 3); frame->tag = tag; /* allocate buffer for frame assembling */ - frame->skb = netdev_alloc_skb_ip_align(skb->dev, frame->length + - sizeof(struct ipv6hdr)); + frame->skb = alloc_skb(frame->length + + sizeof(struct ipv6hdr), GFP_ATOMIC); if (!frame->skb) goto skb_err; @@ -714,23 +715,19 @@ lowpan_process_data(struct sk_buff *skb) case LOWPAN_DISPATCH_FRAGN: { struct lowpan_fragment *frame; - /* slen stores the rightmost 8 bits of the 11 bits length */ - u8 slen, offset; - u16 len, tag; + u8 len, offset; + u16 tag; bool found = false; - if (lowpan_fetch_skb_u8(skb, &slen) || /* frame length */ + if (lowpan_fetch_skb_u8(skb, &len) || /* frame length */ lowpan_fetch_skb_u16(skb, &tag)) /* fragment tag */ goto drop; - /* adds the 3 MSB to the 8 LSB to retrieve the 11 bits length */ - len = ((iphc0 & 7) << 8) | slen; - /* * check if frame assembling with the same tag is * already in progress */ - spin_lock_bh(&flist_lock); + spin_lock(&flist_lock); list_for_each_entry(frame, &lowpan_fragments, list) if (frame->tag == tag) { @@ -740,7 +737,7 @@ lowpan_process_data(struct sk_buff *skb) /* alloc new frame structure */ if (!found) { - frame = lowpan_alloc_new_frame(skb, len, tag); + frame = lowpan_alloc_new_frame(skb, iphc0, len, tag); if (!frame) goto unlock_and_drop; } @@ -764,9 +761,9 @@ lowpan_process_data(struct sk_buff *skb) if ((frame->bytes_rcv == frame->length) && frame->timer.expires > jiffies) { /* if timer haven't expired - first of all delete it */ - del_timer_sync(&frame->timer); + del_timer(&frame->timer); list_del(&frame->list); - spin_unlock_bh(&flist_lock); + spin_unlock(&flist_lock); dev_kfree_skb(skb); skb = frame->skb; @@ -777,7 +774,7 @@ lowpan_process_data(struct sk_buff *skb) break; } - spin_unlock_bh(&flist_lock); + spin_unlock(&flist_lock); return kfree_skb(skb), 0; } @@ -932,7 +929,7 @@ lowpan_process_data(struct sk_buff *skb) return lowpan_skb_deliver(skb, &hdr); unlock_and_drop: - spin_unlock_bh(&flist_lock); + spin_unlock(&flist_lock); drop: kfree_skb(skb); return -EINVAL; @@ -1008,10 +1005,10 @@ lowpan_skb_fragmentation(struct sk_buff *skb) tag = fragment_tag++; /* first fragment header */ - head[0] = LOWPAN_DISPATCH_FRAG1 | ((payload_length >> 8) & 0x7); - head[1] = payload_length & 0xff; - head[2] = tag >> 8; - head[3] = tag & 0xff; + head[0] = LOWPAN_DISPATCH_FRAG1 | (payload_length & 0x7); + head[1] = (payload_length >> 3) & 0xff; + head[2] = tag & 0xff; + head[3] = tag >> 8; err = lowpan_fragment_xmit(skb, head, header_length, 0, 0); @@ -1189,6 +1186,8 @@ static int lowpan_newlink(struct net *src_net, struct net_device *dev, list_add_tail(&entry->list, &lowpan_devices); mutex_unlock(&lowpan_dev_info(dev)->dev_list_mtx); + spin_lock_init(&flist_lock); + register_netdevice(dev); return 0; @@ -1199,9 +1198,19 @@ static void lowpan_dellink(struct net_device *dev, struct list_head *head) struct lowpan_dev_info *lowpan_dev = lowpan_dev_info(dev); struct net_device *real_dev = lowpan_dev->real_dev; struct lowpan_dev_record *entry, *tmp; + struct lowpan_fragment *frame, *tframe; ASSERT_RTNL(); + spin_lock(&flist_lock); + list_for_each_entry_safe(frame, tframe, &lowpan_fragments, list) { + del_timer(&frame->timer); + list_del(&frame->list); + dev_kfree_skb(frame->skb); + kfree(frame); + } + spin_unlock(&flist_lock); + mutex_lock(&lowpan_dev_info(dev)->dev_list_mtx); list_for_each_entry_safe(entry, tmp, &lowpan_devices, list) { if (entry->ldev == dev) { @@ -1257,24 +1266,9 @@ static int __init lowpan_init_module(void) static void __exit lowpan_cleanup_module(void) { - struct lowpan_fragment *frame, *tframe; - lowpan_netlink_fini(); dev_remove_pack(&lowpan_packet_type); - - /* Now 6lowpan packet_type is removed, so no new fragments are - * expected on RX, therefore that's the time to clean incomplete - * fragments. - */ - spin_lock_bh(&flist_lock); - list_for_each_entry_safe(frame, tframe, &lowpan_fragments, list) { - del_timer_sync(&frame->timer); - list_del(&frame->list); - dev_kfree_skb(frame->skb); - kfree(frame); - } - spin_unlock_bh(&flist_lock); } module_init(lowpan_init_module); diff --git a/trunk/net/ieee802154/dgram.c b/trunk/net/ieee802154/dgram.c index 16705611589a..6fbb2ad7bb6d 100644 --- a/trunk/net/ieee802154/dgram.c +++ b/trunk/net/ieee802154/dgram.c @@ -230,12 +230,6 @@ static int dgram_sendmsg(struct kiocb *iocb, struct sock *sk, mtu = dev->mtu; pr_debug("name = %s, mtu = %u\n", dev->name, mtu); - if (size > mtu) { - pr_debug("size = %Zu, mtu = %u\n", size, mtu); - err = -EINVAL; - goto out_dev; - } - hlen = LL_RESERVED_SPACE(dev); tlen = dev->needed_tailroom; skb = sock_alloc_send_skb(sk, hlen + tlen + size, @@ -264,6 +258,12 @@ static int dgram_sendmsg(struct kiocb *iocb, struct sock *sk, if (err < 0) goto out_skb; + if (size > mtu) { + pr_debug("size = %Zu, mtu = %u\n", size, mtu); + err = -EINVAL; + goto out_skb; + } + skb->dev = dev; skb->sk = sk; skb->protocol = htons(ETH_P_IEEE802154); diff --git a/trunk/net/ipv4/Makefile b/trunk/net/ipv4/Makefile index 5a23e8b37106..ff75d3bbcd6a 100644 --- a/trunk/net/ipv4/Makefile +++ b/trunk/net/ipv4/Makefile @@ -7,7 +7,7 @@ obj-y := route.o inetpeer.o protocol.o \ ip_output.o ip_sockglue.o inet_hashtables.o \ inet_timewait_sock.o inet_connection_sock.o \ tcp.o tcp_input.o tcp_output.o tcp_timer.o tcp_ipv4.o \ - tcp_minisocks.o tcp_cong.o tcp_metrics.o \ + tcp_minisocks.o tcp_cong.o \ datagram.o raw.o udp.o udplite.o \ arp.o icmp.o devinet.o af_inet.o igmp.o \ fib_frontend.o fib_semantics.o fib_trie.o \ diff --git a/trunk/net/ipv4/ah4.c b/trunk/net/ipv4/ah4.c index a0d8392491c3..916d5ecaf6c6 100644 --- a/trunk/net/ipv4/ah4.c +++ b/trunk/net/ipv4/ah4.c @@ -398,25 +398,17 @@ static void ah4_err(struct sk_buff *skb, u32 info) struct ip_auth_hdr *ah = (struct ip_auth_hdr *)(skb->data+(iph->ihl<<2)); struct xfrm_state *x; - switch (icmp_hdr(skb)->type) { - case ICMP_DEST_UNREACH: - if (icmp_hdr(skb)->code != ICMP_FRAG_NEEDED) - return; - case ICMP_REDIRECT: - break; - default: + if (icmp_hdr(skb)->type != ICMP_DEST_UNREACH || + icmp_hdr(skb)->code != ICMP_FRAG_NEEDED) return; - } x = xfrm_state_lookup(net, skb->mark, (const xfrm_address_t *)&iph->daddr, ah->spi, IPPROTO_AH, AF_INET); if (!x) return; - - if (icmp_hdr(skb)->type == ICMP_DEST_UNREACH) - ipv4_update_pmtu(skb, net, info, 0, 0, IPPROTO_AH, 0); - else - ipv4_redirect(skb, net, 0, 0, IPPROTO_AH, 0); + pr_debug("pmtu discovery on SA AH/%08x/%08x\n", + ntohl(ah->spi), ntohl(iph->daddr)); + ipv4_update_pmtu(skb, net, info, 0, 0, IPPROTO_AH, 0); xfrm_state_put(x); } diff --git a/trunk/net/ipv4/esp4.c b/trunk/net/ipv4/esp4.c index b61e9deb7c7e..7b95b49a36ce 100644 --- a/trunk/net/ipv4/esp4.c +++ b/trunk/net/ipv4/esp4.c @@ -484,25 +484,17 @@ static void esp4_err(struct sk_buff *skb, u32 info) struct ip_esp_hdr *esph = (struct ip_esp_hdr *)(skb->data+(iph->ihl<<2)); struct xfrm_state *x; - switch (icmp_hdr(skb)->type) { - case ICMP_DEST_UNREACH: - if (icmp_hdr(skb)->code != ICMP_FRAG_NEEDED) - return; - case ICMP_REDIRECT: - break; - default: + if (icmp_hdr(skb)->type != ICMP_DEST_UNREACH || + icmp_hdr(skb)->code != ICMP_FRAG_NEEDED) return; - } x = xfrm_state_lookup(net, skb->mark, (const xfrm_address_t *)&iph->daddr, esph->spi, IPPROTO_ESP, AF_INET); if (!x) return; - - if (icmp_hdr(skb)->type == ICMP_DEST_UNREACH) - ipv4_update_pmtu(skb, net, info, 0, 0, IPPROTO_ESP, 0); - else - ipv4_redirect(skb, net, 0, 0, IPPROTO_ESP, 0); + NETDEBUG(KERN_DEBUG "pmtu discovery on SA ESP/%08x/%08x\n", + ntohl(esph->spi), ntohl(iph->daddr)); + ipv4_update_pmtu(skb, net, info, 0, 0, IPPROTO_ESP, 0); xfrm_state_put(x); } diff --git a/trunk/net/ipv4/fib_frontend.c b/trunk/net/ipv4/fib_frontend.c index 7a31194ec633..81f85716a894 100644 --- a/trunk/net/ipv4/fib_frontend.c +++ b/trunk/net/ipv4/fib_frontend.c @@ -169,6 +169,10 @@ static inline unsigned int __inet_dev_addr_type(struct net *net, if (ipv4_is_multicast(addr)) return RTN_MULTICAST; +#ifdef CONFIG_IP_MULTIPLE_TABLES + res.r = NULL; +#endif + local_table = fib_get_table(net, RT_TABLE_LOCAL); if (local_table) { ret = RTN_UNICAST; @@ -930,6 +934,10 @@ static void nl_fib_lookup(struct fib_result_nl *frn, struct fib_table *tb) .flowi4_scope = frn->fl_scope, }; +#ifdef CONFIG_IP_MULTIPLE_TABLES + res.r = NULL; +#endif + frn->err = -ENOENT; if (tb) { local_bh_disable(); diff --git a/trunk/net/ipv4/fib_rules.c b/trunk/net/ipv4/fib_rules.c index a83d74e498d2..c06da93b0b70 100644 --- a/trunk/net/ipv4/fib_rules.c +++ b/trunk/net/ipv4/fib_rules.c @@ -47,6 +47,13 @@ struct fib4_rule { #endif }; +#ifdef CONFIG_IP_ROUTE_CLASSID +u32 fib_rules_tclass(const struct fib_result *res) +{ + return res->r ? ((struct fib4_rule *) res->r)->tclassid : 0; +} +#endif + int __fib_lookup(struct net *net, struct flowi4 *flp, struct fib_result *res) { struct fib_lookup_arg arg = { @@ -56,12 +63,8 @@ int __fib_lookup(struct net *net, struct flowi4 *flp, struct fib_result *res) int err; err = fib_rules_lookup(net->ipv4.rules_ops, flowi4_to_flowi(flp), 0, &arg); -#ifdef CONFIG_IP_ROUTE_CLASSID - if (arg.rule) - res->tclassid = ((struct fib4_rule *)arg.rule)->tclassid; - else - res->tclassid = 0; -#endif + res->r = arg.rule; + return err; } EXPORT_SYMBOL_GPL(__fib_lookup); diff --git a/trunk/net/ipv4/fib_semantics.c b/trunk/net/ipv4/fib_semantics.c index 2b57d768240d..ae301c897a19 100644 --- a/trunk/net/ipv4/fib_semantics.c +++ b/trunk/net/ipv4/fib_semantics.c @@ -140,27 +140,6 @@ const struct fib_prop fib_props[RTN_MAX + 1] = { }, }; -static void free_nh_exceptions(struct fib_nh *nh) -{ - struct fnhe_hash_bucket *hash = nh->nh_exceptions; - int i; - - for (i = 0; i < FNHE_HASH_SIZE; i++) { - struct fib_nh_exception *fnhe; - - fnhe = rcu_dereference_protected(hash[i].chain, 1); - while (fnhe) { - struct fib_nh_exception *next; - - next = rcu_dereference_protected(fnhe->fnhe_next, 1); - kfree(fnhe); - - fnhe = next; - } - } - kfree(hash); -} - /* Release a nexthop info record */ static void free_fib_info_rcu(struct rcu_head *head) { @@ -169,8 +148,6 @@ static void free_fib_info_rcu(struct rcu_head *head) change_nexthops(fi) { if (nexthop_nh->nh_dev) dev_put(nexthop_nh->nh_dev); - if (nexthop_nh->nh_exceptions) - free_nh_exceptions(nexthop_nh); } endfor_nexthops(fi); release_net(fi->fib_net); @@ -817,8 +794,6 @@ struct fib_info *fib_create_info(struct fib_config *cfg) val = nla_get_u32(nla); if (type == RTAX_ADVMSS && val > 65535 - 40) val = 65535 - 40; - if (type == RTAX_MTU && val > 65535 - 15) - val = 65535 - 15; fi->fib_metrics[type - 1] = val; } } diff --git a/trunk/net/ipv4/fib_trie.c b/trunk/net/ipv4/fib_trie.c index 18cbc15b20d5..9b0f25930fbc 100644 --- a/trunk/net/ipv4/fib_trie.c +++ b/trunk/net/ipv4/fib_trie.c @@ -1843,6 +1843,8 @@ int fib_table_flush(struct fib_table *tb) if (ll && hlist_empty(&ll->list)) trie_leaf_remove(t, ll); + inetpeer_invalidate_tree(&tb->tb_peers); + pr_debug("trie_flush found=%d\n", found); return found; } @@ -1991,6 +1993,7 @@ struct fib_table *fib_trie_table(u32 id) tb->tb_id = id; tb->tb_default = -1; tb->tb_num_default = 0; + inet_peer_base_init(&tb->tb_peers); t = (struct trie *) tb->tb_data; memset(t, 0, sizeof(*t)); diff --git a/trunk/net/ipv4/icmp.c b/trunk/net/ipv4/icmp.c index ea3a996de95b..4bce5a2830aa 100644 --- a/trunk/net/ipv4/icmp.c +++ b/trunk/net/ipv4/icmp.c @@ -254,10 +254,9 @@ static inline bool icmpv4_xrlim_allow(struct net *net, struct rtable *rt, /* Limit if icmp type is enabled in ratemask. */ if ((1 << type) & net->ipv4.sysctl_icmp_ratemask) { - struct inet_peer *peer = inet_getpeer_v4(net->ipv4.peers, fl4->daddr, 1); + struct inet_peer *peer = rt_get_peer_create(rt, fl4->daddr); rc = inet_peer_xrlim_allow(peer, net->ipv4.sysctl_icmp_ratelimit); - inet_putpeer(peer); } out: return rc; @@ -634,37 +633,18 @@ out:; EXPORT_SYMBOL(icmp_send); -static void icmp_socket_deliver(struct sk_buff *skb, u32 info) -{ - const struct iphdr *iph = (const struct iphdr *) skb->data; - const struct net_protocol *ipprot; - int protocol = iph->protocol; - - /* Checkin full IP header plus 8 bytes of protocol to - * avoid additional coding at protocol handlers. - */ - if (!pskb_may_pull(skb, iph->ihl * 4 + 8)) - return; - - raw_icmp_error(skb, protocol, info); - - rcu_read_lock(); - ipprot = rcu_dereference(inet_protos[protocol]); - if (ipprot && ipprot->err_handler) - ipprot->err_handler(skb, info); - rcu_read_unlock(); -} - /* * Handle ICMP_DEST_UNREACH, ICMP_TIME_EXCEED, and ICMP_QUENCH. */ static void icmp_unreach(struct sk_buff *skb) { + const struct net_protocol *ipprot; const struct iphdr *iph; struct icmphdr *icmph; struct net *net; u32 info = 0; + int protocol; net = dev_net(skb_dst(skb)->dev); @@ -739,7 +719,25 @@ static void icmp_unreach(struct sk_buff *skb) goto out; } - icmp_socket_deliver(skb, info); + /* Checkin full IP header plus 8 bytes of protocol to + * avoid additional coding at protocol handlers. + */ + if (!pskb_may_pull(skb, iph->ihl * 4 + 8)) + goto out; + + iph = (const struct iphdr *)skb->data; + protocol = iph->protocol; + + /* + * Deliver ICMP message to raw sockets. Pretty useless feature? + */ + raw_icmp_error(skb, protocol, info); + + rcu_read_lock(); + ipprot = rcu_dereference(inet_protos[protocol]); + if (ipprot && ipprot->err_handler) + ipprot->err_handler(skb, info); + rcu_read_unlock(); out: return; @@ -755,15 +753,46 @@ static void icmp_unreach(struct sk_buff *skb) static void icmp_redirect(struct sk_buff *skb) { - if (skb->len < sizeof(struct iphdr)) { - ICMP_INC_STATS_BH(dev_net(skb->dev), ICMP_MIB_INERRORS); - return; - } + const struct iphdr *iph; + if (skb->len < sizeof(struct iphdr)) + goto out_err; + + /* + * Get the copied header of the packet that caused the redirect + */ if (!pskb_may_pull(skb, sizeof(struct iphdr))) - return; + goto out; + + iph = (const struct iphdr *)skb->data; + + switch (icmp_hdr(skb)->code & 7) { + case ICMP_REDIR_NET: + case ICMP_REDIR_NETTOS: + /* + * As per RFC recommendations now handle it as a host redirect. + */ + case ICMP_REDIR_HOST: + case ICMP_REDIR_HOSTTOS: + ip_rt_redirect(ip_hdr(skb)->saddr, iph->daddr, + icmp_hdr(skb)->un.gateway, + iph->saddr, skb->dev); + break; + } - icmp_socket_deliver(skb, icmp_hdr(skb)->un.gateway); + /* Ping wants to see redirects. + * Let's pretend they are errors of sorts... */ + if (iph->protocol == IPPROTO_ICMP && + iph->ihl >= 5 && + pskb_may_pull(skb, (iph->ihl<<2)+8)) { + ping_err(skb, icmp_hdr(skb)->un.gateway); + } + +out: + return; +out_err: + ICMP_INC_STATS_BH(dev_net(skb->dev), ICMP_MIB_INERRORS); + goto out; } /* diff --git a/trunk/net/ipv4/inet_connection_sock.c b/trunk/net/ipv4/inet_connection_sock.c index c7a4de05ca04..034ddbe42adf 100644 --- a/trunk/net/ipv4/inet_connection_sock.c +++ b/trunk/net/ipv4/inet_connection_sock.c @@ -375,7 +375,7 @@ struct dst_entry *inet_csk_route_req(struct sock *sk, const struct inet_request_sock *ireq = inet_rsk(req); struct ip_options_rcu *opt = inet_rsk(req)->opt; struct net *net = sock_net(sk); - int flags = inet_sk_flowi_flags(sk); + int flags = inet_sk_flowi_flags(sk) & ~FLOWI_FLAG_PRECOW_METRICS; if (nocache) flags |= FLOWI_FLAG_RT_NOCACHE; @@ -803,49 +803,3 @@ int inet_csk_compat_setsockopt(struct sock *sk, int level, int optname, } EXPORT_SYMBOL_GPL(inet_csk_compat_setsockopt); #endif - -static struct dst_entry *inet_csk_rebuild_route(struct sock *sk, struct flowi *fl) -{ - const struct inet_sock *inet = inet_sk(sk); - const struct ip_options_rcu *inet_opt; - __be32 daddr = inet->inet_daddr; - struct flowi4 *fl4; - struct rtable *rt; - - rcu_read_lock(); - inet_opt = rcu_dereference(inet->inet_opt); - if (inet_opt && inet_opt->opt.srr) - daddr = inet_opt->opt.faddr; - fl4 = &fl->u.ip4; - rt = ip_route_output_ports(sock_net(sk), fl4, sk, daddr, - inet->inet_saddr, inet->inet_dport, - inet->inet_sport, sk->sk_protocol, - RT_CONN_FLAGS(sk), sk->sk_bound_dev_if); - if (IS_ERR(rt)) - rt = NULL; - if (rt) - sk_setup_caps(sk, &rt->dst); - rcu_read_unlock(); - - return &rt->dst; -} - -struct dst_entry *inet_csk_update_pmtu(struct sock *sk, u32 mtu) -{ - struct dst_entry *dst = __sk_dst_check(sk, 0); - struct inet_sock *inet = inet_sk(sk); - - if (!dst) { - dst = inet_csk_rebuild_route(sk, &inet->cork.fl); - if (!dst) - goto out; - } - dst->ops->update_pmtu(dst, sk, NULL, mtu); - - dst = __sk_dst_check(sk, 0); - if (!dst) - dst = inet_csk_rebuild_route(sk, &inet->cork.fl); -out: - return dst; -} -EXPORT_SYMBOL_GPL(inet_csk_update_pmtu); diff --git a/trunk/net/ipv4/inet_diag.c b/trunk/net/ipv4/inet_diag.c index 570e61f9611f..38064a285cca 100644 --- a/trunk/net/ipv4/inet_diag.c +++ b/trunk/net/ipv4/inet_diag.c @@ -272,17 +272,16 @@ int inet_diag_dump_one_icsk(struct inet_hashinfo *hashinfo, struct sk_buff *in_s int err; struct sock *sk; struct sk_buff *rep; - struct net *net = sock_net(in_skb->sk); err = -EINVAL; if (req->sdiag_family == AF_INET) { - sk = inet_lookup(net, hashinfo, req->id.idiag_dst[0], + sk = inet_lookup(&init_net, hashinfo, req->id.idiag_dst[0], req->id.idiag_dport, req->id.idiag_src[0], req->id.idiag_sport, req->id.idiag_if); } #if IS_ENABLED(CONFIG_IPV6) else if (req->sdiag_family == AF_INET6) { - sk = inet6_lookup(net, hashinfo, + sk = inet6_lookup(&init_net, hashinfo, (struct in6_addr *)req->id.idiag_dst, req->id.idiag_dport, (struct in6_addr *)req->id.idiag_src, @@ -318,7 +317,7 @@ int inet_diag_dump_one_icsk(struct inet_hashinfo *hashinfo, struct sk_buff *in_s nlmsg_free(rep); goto out; } - err = netlink_unicast(net->diag_nlsk, rep, NETLINK_CB(in_skb).pid, + err = netlink_unicast(sock_diag_nlsk, rep, NETLINK_CB(in_skb).pid, MSG_DONTWAIT); if (err > 0) err = 0; @@ -725,7 +724,6 @@ void inet_diag_dump_icsk(struct inet_hashinfo *hashinfo, struct sk_buff *skb, { int i, num; int s_i, s_num; - struct net *net = sock_net(skb->sk); s_i = cb->args[1]; s_num = num = cb->args[2]; @@ -745,9 +743,6 @@ void inet_diag_dump_icsk(struct inet_hashinfo *hashinfo, struct sk_buff *skb, sk_nulls_for_each(sk, node, &ilb->head) { struct inet_sock *inet = inet_sk(sk); - if (!net_eq(sock_net(sk), net)) - continue; - if (num < s_num) { num++; continue; @@ -818,8 +813,6 @@ void inet_diag_dump_icsk(struct inet_hashinfo *hashinfo, struct sk_buff *skb, sk_nulls_for_each(sk, node, &head->chain) { struct inet_sock *inet = inet_sk(sk); - if (!net_eq(sock_net(sk), net)) - continue; if (num < s_num) goto next_normal; if (!(r->idiag_states & (1 << sk->sk_state))) @@ -846,8 +839,6 @@ void inet_diag_dump_icsk(struct inet_hashinfo *hashinfo, struct sk_buff *skb, inet_twsk_for_each(tw, node, &head->twchain) { - if (!net_eq(twsk_net(tw), net)) - continue; if (num < s_num) goto next_dying; @@ -952,7 +943,6 @@ static int inet_diag_get_exact_compat(struct sk_buff *in_skb, static int inet_diag_rcv_msg_compat(struct sk_buff *skb, struct nlmsghdr *nlh) { int hdrlen = sizeof(struct inet_diag_req); - struct net *net = sock_net(skb->sk); if (nlh->nlmsg_type >= INET_DIAG_GETSOCK_MAX || nlmsg_len(nlh) < hdrlen) @@ -973,7 +963,7 @@ static int inet_diag_rcv_msg_compat(struct sk_buff *skb, struct nlmsghdr *nlh) struct netlink_dump_control c = { .dump = inet_diag_dump_compat, }; - return netlink_dump_start(net->diag_nlsk, skb, nlh, &c); + return netlink_dump_start(sock_diag_nlsk, skb, nlh, &c); } } @@ -983,7 +973,6 @@ static int inet_diag_rcv_msg_compat(struct sk_buff *skb, struct nlmsghdr *nlh) static int inet_diag_handler_dump(struct sk_buff *skb, struct nlmsghdr *h) { int hdrlen = sizeof(struct inet_diag_req_v2); - struct net *net = sock_net(skb->sk); if (nlmsg_len(h) < hdrlen) return -EINVAL; @@ -1002,7 +991,7 @@ static int inet_diag_handler_dump(struct sk_buff *skb, struct nlmsghdr *h) struct netlink_dump_control c = { .dump = inet_diag_dump, }; - return netlink_dump_start(net->diag_nlsk, skb, h, &c); + return netlink_dump_start(sock_diag_nlsk, skb, h, &c); } } diff --git a/trunk/net/ipv4/inetpeer.c b/trunk/net/ipv4/inetpeer.c index e1e0a4e8fd34..da90a8cab614 100644 --- a/trunk/net/ipv4/inetpeer.c +++ b/trunk/net/ipv4/inetpeer.c @@ -508,9 +508,13 @@ struct inet_peer *inet_getpeer(struct inet_peer_base *base, (daddr->family == AF_INET) ? secure_ip_id(daddr->addr.a4) : secure_ipv6_id(daddr->addr.a6)); + p->tcp_ts_stamp = 0; p->metrics[RTAX_LOCK-1] = INETPEER_METRICS_NEW; p->rate_tokens = 0; p->rate_last = 0; + p->pmtu_expires = 0; + p->pmtu_orig = 0; + memset(&p->redirect_learned, 0, sizeof(p->redirect_learned)); 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 42c44b1403c9..594cec35ac4d 100644 --- a/trunk/net/ipv4/ip_gre.c +++ b/trunk/net/ipv4/ip_gre.c @@ -528,9 +528,6 @@ static void ipgre_err(struct sk_buff *skb, u32 info) if (code != ICMP_EXC_TTL) return; break; - - case ICMP_REDIRECT: - break; } rcu_read_lock(); @@ -546,11 +543,7 @@ static void ipgre_err(struct sk_buff *skb, u32 info) t->parms.link, 0, IPPROTO_GRE, 0); goto out; } - if (type == ICMP_REDIRECT) { - ipv4_redirect(skb, dev_net(skb->dev), t->parms.link, 0, - IPPROTO_GRE, 0); - goto out; - } + if (t->parms.iph.daddr == 0 || ipv4_is_multicast(t->parms.iph.daddr)) goto out; @@ -833,7 +826,7 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev mtu = skb_dst(skb) ? dst_mtu(skb_dst(skb)) : dev->mtu; if (skb_dst(skb)) - skb_dst(skb)->ops->update_pmtu(skb_dst(skb), NULL, skb, mtu); + skb_dst(skb)->ops->update_pmtu(skb_dst(skb), mtu); if (skb->protocol == htons(ETH_P_IP)) { df |= (old_iph->frag_off&htons(IP_DF)); diff --git a/trunk/net/ipv4/ipcomp.c b/trunk/net/ipv4/ipcomp.c index d3ab47e19a89..b91375482d84 100644 --- a/trunk/net/ipv4/ipcomp.c +++ b/trunk/net/ipv4/ipcomp.c @@ -31,26 +31,18 @@ static void ipcomp4_err(struct sk_buff *skb, u32 info) struct ip_comp_hdr *ipch = (struct ip_comp_hdr *)(skb->data+(iph->ihl<<2)); struct xfrm_state *x; - switch (icmp_hdr(skb)->type) { - case ICMP_DEST_UNREACH: - if (icmp_hdr(skb)->code != ICMP_FRAG_NEEDED) - return; - case ICMP_REDIRECT: - break; - default: + if (icmp_hdr(skb)->type != ICMP_DEST_UNREACH || + icmp_hdr(skb)->code != ICMP_FRAG_NEEDED) return; - } spi = htonl(ntohs(ipch->cpi)); x = xfrm_state_lookup(net, skb->mark, (const xfrm_address_t *)&iph->daddr, spi, IPPROTO_COMP, AF_INET); if (!x) return; - - if (icmp_hdr(skb)->type == ICMP_DEST_UNREACH) - ipv4_update_pmtu(skb, net, info, 0, 0, IPPROTO_COMP, 0); - else - ipv4_redirect(skb, net, 0, 0, IPPROTO_COMP, 0); + NETDEBUG(KERN_DEBUG "pmtu discovery on SA IPCOMP/%08x/%pI4\n", + spi, &iph->daddr); + ipv4_update_pmtu(skb, net, info, 0, 0, IPPROTO_COMP, 0); xfrm_state_put(x); } diff --git a/trunk/net/ipv4/ipip.c b/trunk/net/ipv4/ipip.c index 2c2c35bace76..715338a1b205 100644 --- a/trunk/net/ipv4/ipip.c +++ b/trunk/net/ipv4/ipip.c @@ -360,8 +360,6 @@ static int ipip_err(struct sk_buff *skb, u32 info) if (code != ICMP_EXC_TTL) return 0; break; - case ICMP_REDIRECT: - break; } err = -ENOENT; @@ -378,13 +376,6 @@ static int ipip_err(struct sk_buff *skb, u32 info) goto out; } - if (type == ICMP_REDIRECT) { - ipv4_redirect(skb, dev_net(skb->dev), t->dev->ifindex, 0, - IPPROTO_IPIP, 0); - err = 0; - goto out; - } - if (t->parms.iph.daddr == 0) goto out; @@ -519,7 +510,7 @@ static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) } if (skb_dst(skb)) - skb_dst(skb)->ops->update_pmtu(skb_dst(skb), NULL, skb, mtu); + skb_dst(skb)->ops->update_pmtu(skb_dst(skb), mtu); if ((old_iph->frag_off & htons(IP_DF)) && mtu < ntohs(old_iph->tot_len)) { diff --git a/trunk/net/ipv4/ipmr.c b/trunk/net/ipv4/ipmr.c index 5716c6b808d6..b4ac39f11d19 100644 --- a/trunk/net/ipv4/ipmr.c +++ b/trunk/net/ipv4/ipmr.c @@ -524,8 +524,8 @@ static struct net_device *ipmr_reg_vif(struct net *net, struct mr_table *mrt) } #endif -/** - * vif_delete - Delete a VIF entry +/* + * Delete a VIF entry * @notify: Set to 1, if the caller is a notifier_call */ diff --git a/trunk/net/ipv4/netfilter/nf_conntrack_proto_icmp.c b/trunk/net/ipv4/netfilter/nf_conntrack_proto_icmp.c index 5241d997ab75..041923cb67ad 100644 --- a/trunk/net/ipv4/netfilter/nf_conntrack_proto_icmp.c +++ b/trunk/net/ipv4/netfilter/nf_conntrack_proto_icmp.c @@ -337,62 +337,34 @@ static struct ctl_table icmp_compat_sysctl_table[] = { #endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */ #endif /* CONFIG_SYSCTL */ -static int icmp_kmemdup_sysctl_table(struct nf_proto_net *pn, - struct nf_icmp_net *in) +static int icmp_init_net(struct net *net) { + struct nf_icmp_net *in = icmp_pernet(net); + struct nf_proto_net *pn = (struct nf_proto_net *)in; + in->timeout = nf_ct_icmp_timeout; + #ifdef CONFIG_SYSCTL pn->ctl_table = kmemdup(icmp_sysctl_table, sizeof(icmp_sysctl_table), GFP_KERNEL); if (!pn->ctl_table) return -ENOMEM; - pn->ctl_table[0].data = &in->timeout; -#endif - return 0; -} - -static int icmp_kmemdup_compat_sysctl_table(struct nf_proto_net *pn, - struct nf_icmp_net *in) -{ -#ifdef CONFIG_SYSCTL #ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT pn->ctl_compat_table = kmemdup(icmp_compat_sysctl_table, sizeof(icmp_compat_sysctl_table), GFP_KERNEL); - if (!pn->ctl_compat_table) + if (!pn->ctl_compat_table) { + kfree(pn->ctl_table); + pn->ctl_table = NULL; return -ENOMEM; - + } pn->ctl_compat_table[0].data = &in->timeout; #endif #endif return 0; } -static int icmp_init_net(struct net *net, u_int16_t proto) -{ - int ret; - struct nf_icmp_net *in = icmp_pernet(net); - struct nf_proto_net *pn = &in->pn; - - in->timeout = nf_ct_icmp_timeout; - - ret = icmp_kmemdup_compat_sysctl_table(pn, in); - if (ret < 0) - return ret; - - ret = icmp_kmemdup_sysctl_table(pn, in); - if (ret < 0) - nf_ct_kfree_compat_sysctl_table(pn); - - return ret; -} - -static struct nf_proto_net *icmp_get_net_proto(struct net *net) -{ - return &net->ct.nf_ct_proto.icmp.pn; -} - struct nf_conntrack_l4proto nf_conntrack_l4proto_icmp __read_mostly = { .l3proto = PF_INET, @@ -423,5 +395,4 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_icmp __read_mostly = }, #endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */ .init_net = icmp_init_net, - .get_net_proto = icmp_get_net_proto, }; diff --git a/trunk/net/ipv4/ping.c b/trunk/net/ipv4/ping.c index 6232d476f37e..340fcf29a966 100644 --- a/trunk/net/ipv4/ping.c +++ b/trunk/net/ipv4/ping.c @@ -387,7 +387,6 @@ void ping_err(struct sk_buff *skb, u32 info) break; case ICMP_REDIRECT: /* See ICMP_SOURCE_QUENCH */ - ipv4_sk_redirect(skb, sk); err = EREMOTEIO; break; } diff --git a/trunk/net/ipv4/proc.c b/trunk/net/ipv4/proc.c index 2a5240b2ea61..8af0d44e4e22 100644 --- a/trunk/net/ipv4/proc.c +++ b/trunk/net/ipv4/proc.c @@ -232,6 +232,7 @@ static const struct snmp_mib snmp4_net_list[] = { SNMP_MIB_ITEM("TCPDSACKOfoSent", LINUX_MIB_TCPDSACKOFOSENT), SNMP_MIB_ITEM("TCPDSACKRecv", LINUX_MIB_TCPDSACKRECV), SNMP_MIB_ITEM("TCPDSACKOfoRecv", LINUX_MIB_TCPDSACKOFORECV), + SNMP_MIB_ITEM("TCPAbortOnSyn", LINUX_MIB_TCPABORTONSYN), SNMP_MIB_ITEM("TCPAbortOnData", LINUX_MIB_TCPABORTONDATA), SNMP_MIB_ITEM("TCPAbortOnClose", LINUX_MIB_TCPABORTONCLOSE), SNMP_MIB_ITEM("TCPAbortOnMemory", LINUX_MIB_TCPABORTONMEMORY), @@ -257,11 +258,6 @@ static const struct snmp_mib snmp4_net_list[] = { SNMP_MIB_ITEM("TCPReqQFullDrop", LINUX_MIB_TCPREQQFULLDROP), SNMP_MIB_ITEM("TCPRetransFail", LINUX_MIB_TCPRETRANSFAIL), SNMP_MIB_ITEM("TCPRcvCoalesce", LINUX_MIB_TCPRCVCOALESCE), - SNMP_MIB_ITEM("TCPOFOQueue", LINUX_MIB_TCPOFOQUEUE), - SNMP_MIB_ITEM("TCPOFODrop", LINUX_MIB_TCPOFODROP), - SNMP_MIB_ITEM("TCPOFOMerge", LINUX_MIB_TCPOFOMERGE), - SNMP_MIB_ITEM("TCPChallengeACK", LINUX_MIB_TCPCHALLENGEACK), - SNMP_MIB_ITEM("TCPSYNChallenge", LINUX_MIB_TCPSYNCHALLENGE), SNMP_MIB_SENTINEL }; diff --git a/trunk/net/ipv4/raw.c b/trunk/net/ipv4/raw.c index ff0f071969ea..659ddfb10947 100644 --- a/trunk/net/ipv4/raw.c +++ b/trunk/net/ipv4/raw.c @@ -218,8 +218,6 @@ static void raw_err(struct sock *sk, struct sk_buff *skb, u32 info) if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) ipv4_sk_update_pmtu(skb, sk, info); - else if (type == ICMP_REDIRECT) - ipv4_sk_redirect(skb, sk); /* Report error on raw socket, if: 1. User requested ip_recverr. diff --git a/trunk/net/ipv4/route.c b/trunk/net/ipv4/route.c index f67e70236728..72e88c208025 100644 --- a/trunk/net/ipv4/route.c +++ b/trunk/net/ipv4/route.c @@ -148,10 +148,7 @@ static unsigned int ipv4_mtu(const struct dst_entry *dst); static void ipv4_dst_destroy(struct dst_entry *dst); static struct dst_entry *ipv4_negative_advice(struct dst_entry *dst); static void ipv4_link_failure(struct sk_buff *skb); -static void ip_rt_update_pmtu(struct dst_entry *dst, struct sock *sk, - struct sk_buff *skb, u32 mtu); -static void ip_do_redirect(struct dst_entry *dst, struct sock *sk, - struct sk_buff *skb); +static void ip_rt_update_pmtu(struct dst_entry *dst, u32 mtu); static int rt_garbage_collect(struct dst_ops *ops); static void ipv4_dst_ifdown(struct dst_entry *dst, struct net_device *dev, @@ -161,8 +158,34 @@ static void ipv4_dst_ifdown(struct dst_entry *dst, struct net_device *dev, static u32 *ipv4_cow_metrics(struct dst_entry *dst, unsigned long old) { - WARN_ON(1); - return NULL; + struct rtable *rt = (struct rtable *) dst; + struct inet_peer *peer; + u32 *p = NULL; + + peer = rt_get_peer_create(rt, rt->rt_dst); + if (peer) { + u32 *old_p = __DST_METRICS_PTR(old); + unsigned long prev, new; + + p = peer->metrics; + if (inet_metrics_new(peer)) + memcpy(p, old_p, sizeof(u32) * RTAX_MAX); + + new = (unsigned long) p; + prev = cmpxchg(&dst->_metrics, old, new); + + if (prev != old) { + p = __DST_METRICS_PTR(prev); + if (prev & DST_METRICS_READ_ONLY) + p = NULL; + } else { + if (rt->fi) { + fib_info_put(rt->fi); + rt->fi = NULL; + } + } + } + return p; } static struct neighbour *ipv4_neigh_lookup(const struct dst_entry *dst, @@ -182,7 +205,6 @@ static struct dst_ops ipv4_dst_ops = { .negative_advice = ipv4_negative_advice, .link_failure = ipv4_link_failure, .update_pmtu = ip_rt_update_pmtu, - .redirect = ip_do_redirect, .local_out = __ip_local_out, .neigh_lookup = ipv4_neigh_lookup, }; @@ -401,16 +423,18 @@ static int rt_cache_seq_show(struct seq_file *seq, void *v) int len; seq_printf(seq, "%s\t%08X\t%08X\t%8X\t%d\t%u\t%d\t" - "%08X\t%d\t%u\t%u\t%02X\t%d\t%1d\t%08X%n", - r->dst.dev ? r->dst.dev->name : "*", - (__force u32)r->rt_dst, - (__force u32)r->rt_gateway, - r->rt_flags, atomic_read(&r->dst.__refcnt), - r->dst.__use, 0, (__force u32)r->rt_src, - dst_metric_advmss(&r->dst) + 40, - dst_metric(&r->dst, RTAX_WINDOW), 0, - r->rt_key_tos, - -1, 0, 0, &len); + "%08X\t%d\t%u\t%u\t%02X\t%d\t%1d\t%08X%n", + r->dst.dev ? r->dst.dev->name : "*", + (__force u32)r->rt_dst, + (__force u32)r->rt_gateway, + r->rt_flags, atomic_read(&r->dst.__refcnt), + r->dst.__use, 0, (__force u32)r->rt_src, + dst_metric_advmss(&r->dst) + 40, + dst_metric(&r->dst, RTAX_WINDOW), + (int)((dst_metric(&r->dst, RTAX_RTT) >> 3) + + dst_metric(&r->dst, RTAX_RTTVAR)), + r->rt_key_tos, + -1, 0, 0, &len); seq_printf(seq, "%*s\n", 127 - len, ""); } @@ -647,7 +671,7 @@ static inline int rt_fast_clean(struct rtable *rth) static inline int rt_valuable(struct rtable *rth) { return (rth->rt_flags & (RTCF_REDIRECTED | RTCF_NOTIFY)) || - rth->dst.expires; + (rt_has_peer(rth) && rt_peer_ptr(rth)->pmtu_expires); } static int rt_may_expire(struct rtable *rth, unsigned long tmo1, unsigned long tmo2) @@ -893,6 +917,7 @@ static void rt_cache_invalidate(struct net *net) get_random_bytes(&shuffle, sizeof(shuffle)); atomic_add(shuffle + 1U, &net->ipv4.rt_genid); + inetpeer_invalidate_family(AF_INET); } /* @@ -1219,6 +1244,31 @@ static struct rtable *rt_intern_hash(unsigned int hash, struct rtable *rt, return rt; } +static atomic_t __rt_peer_genid = ATOMIC_INIT(0); + +static u32 rt_peer_genid(void) +{ + return atomic_read(&__rt_peer_genid); +} + +void rt_bind_peer(struct rtable *rt, __be32 daddr, int create) +{ + struct inet_peer_base *base; + struct inet_peer *peer; + + base = inetpeer_base_ptr(rt->_peer); + if (!base) + return; + + peer = inet_getpeer_v4(base, daddr, create); + if (peer) { + if (!rt_set_peer(rt, peer)) + inet_putpeer(peer); + else + rt->rt_peer_genid = rt_peer_genid(); + } +} + /* * Peer allocation may fail only in serious out-of-memory conditions. However * we still can generate some output. @@ -1241,15 +1291,20 @@ static void ip_select_fb_ident(struct iphdr *iph) void __ip_select_ident(struct iphdr *iph, struct dst_entry *dst, int more) { - struct net *net = dev_net(dst->dev); - struct inet_peer *peer; + struct rtable *rt = (struct rtable *) dst; - peer = inet_getpeer_v4(net->ipv4.peers, iph->daddr, 1); - if (peer) { - iph->id = htons(inet_getid(peer, more)); - inet_putpeer(peer); - return; - } + if (rt && !(rt->dst.flags & DST_NOPEER)) { + struct inet_peer *peer = rt_get_peer_create(rt, rt->rt_dst); + + /* If peer is attached to destination, it is never detached, + so that we need not to grab a lock to dereference it. + */ + if (peer) { + iph->id = htons(inet_getid(peer, more)); + return; + } + } else if (!rt) + pr_debug("rt_bind_peer(0) @%p\n", __builtin_return_address(0)); ip_select_fb_ident(iph); } @@ -1275,157 +1330,41 @@ static void rt_del(unsigned int hash, struct rtable *rt) spin_unlock_bh(rt_hash_lock_addr(hash)); } -static void __build_flow_key(struct flowi4 *fl4, const struct sock *sk, - const struct iphdr *iph, - int oif, u8 tos, - u8 prot, u32 mark, int flow_flags) -{ - if (sk) { - const struct inet_sock *inet = inet_sk(sk); - - oif = sk->sk_bound_dev_if; - mark = sk->sk_mark; - tos = RT_CONN_FLAGS(sk); - prot = inet->hdrincl ? IPPROTO_RAW : sk->sk_protocol; - } - flowi4_init_output(fl4, oif, mark, tos, - RT_SCOPE_UNIVERSE, prot, - flow_flags, - iph->daddr, iph->saddr, 0, 0); -} - -static void build_skb_flow_key(struct flowi4 *fl4, const struct sk_buff *skb, - const struct sock *sk) -{ - const struct iphdr *iph = ip_hdr(skb); - int oif = skb->dev->ifindex; - u8 tos = RT_TOS(iph->tos); - u8 prot = iph->protocol; - u32 mark = skb->mark; - - __build_flow_key(fl4, sk, iph, oif, tos, prot, mark, 0); -} - -static void build_sk_flow_key(struct flowi4 *fl4, const struct sock *sk) +static void check_peer_redir(struct dst_entry *dst, struct inet_peer *peer) { - const struct inet_sock *inet = inet_sk(sk); - const struct ip_options_rcu *inet_opt; - __be32 daddr = inet->inet_daddr; - - rcu_read_lock(); - inet_opt = rcu_dereference(inet->inet_opt); - if (inet_opt && inet_opt->opt.srr) - daddr = inet_opt->opt.faddr; - flowi4_init_output(fl4, sk->sk_bound_dev_if, sk->sk_mark, - RT_CONN_FLAGS(sk), RT_SCOPE_UNIVERSE, - inet->hdrincl ? IPPROTO_RAW : sk->sk_protocol, - inet_sk_flowi_flags(sk), - daddr, inet->inet_saddr, 0, 0); - rcu_read_unlock(); -} - -static void ip_rt_build_flow_key(struct flowi4 *fl4, const struct sock *sk, - const struct sk_buff *skb) -{ - if (skb) - build_skb_flow_key(fl4, skb, sk); - else - build_sk_flow_key(fl4, sk); -} - -static DEFINE_SPINLOCK(fnhe_lock); - -static struct fib_nh_exception *fnhe_oldest(struct fnhe_hash_bucket *hash, __be32 daddr) -{ - struct fib_nh_exception *fnhe, *oldest; - - oldest = rcu_dereference(hash->chain); - for (fnhe = rcu_dereference(oldest->fnhe_next); fnhe; - fnhe = rcu_dereference(fnhe->fnhe_next)) { - if (time_before(fnhe->fnhe_stamp, oldest->fnhe_stamp)) - oldest = fnhe; - } - return oldest; -} - -static inline u32 fnhe_hashfun(__be32 daddr) -{ - u32 hval; - - hval = (__force u32) daddr; - hval ^= (hval >> 11) ^ (hval >> 22); - - return hval & (FNHE_HASH_SIZE - 1); -} - -static struct fib_nh_exception *find_or_create_fnhe(struct fib_nh *nh, __be32 daddr) -{ - struct fnhe_hash_bucket *hash = nh->nh_exceptions; - struct fib_nh_exception *fnhe; - int depth; - u32 hval; + struct rtable *rt = (struct rtable *) dst; + __be32 orig_gw = rt->rt_gateway; + struct neighbour *n; - if (!hash) { - hash = nh->nh_exceptions = kzalloc(FNHE_HASH_SIZE * sizeof(*hash), - GFP_ATOMIC); - if (!hash) - return NULL; - } + dst_confirm(&rt->dst); - hval = fnhe_hashfun(daddr); - hash += hval; + rt->rt_gateway = peer->redirect_learned.a4; - depth = 0; - for (fnhe = rcu_dereference(hash->chain); fnhe; - fnhe = rcu_dereference(fnhe->fnhe_next)) { - if (fnhe->fnhe_daddr == daddr) - goto out; - depth++; + n = ipv4_neigh_lookup(&rt->dst, NULL, &rt->rt_gateway); + if (!n) { + rt->rt_gateway = orig_gw; + return; } - - if (depth > FNHE_RECLAIM_DEPTH) { - fnhe = fnhe_oldest(hash + hval, daddr); - goto out_daddr; + if (!(n->nud_state & NUD_VALID)) { + neigh_event_send(n, NULL); + } else { + rt->rt_flags |= RTCF_REDIRECTED; + call_netevent_notifiers(NETEVENT_NEIGH_UPDATE, n); } - fnhe = kzalloc(sizeof(*fnhe), GFP_ATOMIC); - if (!fnhe) - return NULL; - - fnhe->fnhe_next = hash->chain; - rcu_assign_pointer(hash->chain, fnhe); - -out_daddr: - fnhe->fnhe_daddr = daddr; -out: - fnhe->fnhe_stamp = jiffies; - return fnhe; + neigh_release(n); } -static void __ip_do_redirect(struct rtable *rt, struct sk_buff *skb, struct flowi4 *fl4) +/* called in rcu_read_lock() section */ +void ip_rt_redirect(__be32 old_gw, __be32 daddr, __be32 new_gw, + __be32 saddr, struct net_device *dev) { - __be32 new_gw = icmp_hdr(skb)->un.gateway; - __be32 old_gw = ip_hdr(skb)->saddr; - struct net_device *dev = skb->dev; - struct in_device *in_dev; - struct fib_result res; - struct neighbour *n; + int s, i; + struct in_device *in_dev = __in_dev_get_rcu(dev); + __be32 skeys[2] = { saddr, 0 }; + int ikeys[2] = { dev->ifindex, 0 }; + struct inet_peer *peer; struct net *net; - switch (icmp_hdr(skb)->code & 7) { - case ICMP_REDIR_NET: - case ICMP_REDIR_NETTOS: - case ICMP_REDIR_HOST: - case ICMP_REDIR_HOSTTOS: - break; - - default: - return; - } - - if (rt->rt_gateway != old_gw) - return; - - in_dev = __in_dev_get_rcu(dev); if (!in_dev) return; @@ -1445,54 +1384,69 @@ static void __ip_do_redirect(struct rtable *rt, struct sk_buff *skb, struct flow goto reject_redirect; } - n = ipv4_neigh_lookup(&rt->dst, NULL, &new_gw); - if (n) { - if (!(n->nud_state & NUD_VALID)) { - neigh_event_send(n, NULL); - } else { - if (fib_lookup(net, fl4, &res) == 0) { - struct fib_nh *nh = &FIB_RES_NH(res); - struct fib_nh_exception *fnhe; - - spin_lock_bh(&fnhe_lock); - fnhe = find_or_create_fnhe(nh, fl4->daddr); - if (fnhe) - fnhe->fnhe_gw = new_gw; - spin_unlock_bh(&fnhe_lock); + for (s = 0; s < 2; s++) { + for (i = 0; i < 2; i++) { + unsigned int hash; + struct rtable __rcu **rthp; + struct rtable *rt; + + hash = rt_hash(daddr, skeys[s], ikeys[i], rt_genid(net)); + + rthp = &rt_hash_table[hash].chain; + + while ((rt = rcu_dereference(*rthp)) != NULL) { + rthp = &rt->dst.rt_next; + + if (rt->rt_key_dst != daddr || + rt->rt_key_src != skeys[s] || + rt->rt_oif != ikeys[i] || + rt_is_input_route(rt) || + rt_is_expired(rt) || + !net_eq(dev_net(rt->dst.dev), net) || + rt->dst.error || + rt->dst.dev != dev || + rt->rt_gateway != old_gw) + continue; + + peer = rt_get_peer_create(rt, rt->rt_dst); + if (peer) { + if (peer->redirect_learned.a4 != new_gw) { + peer->redirect_learned.a4 = new_gw; + atomic_inc(&__rt_peer_genid); + } + check_peer_redir(&rt->dst, peer); + } } - rt->rt_gateway = new_gw; - rt->rt_flags |= RTCF_REDIRECTED; - call_netevent_notifiers(NETEVENT_NEIGH_UPDATE, n); } - neigh_release(n); } return; reject_redirect: #ifdef CONFIG_IP_ROUTE_VERBOSE - if (IN_DEV_LOG_MARTIANS(in_dev)) { - const struct iphdr *iph = (const struct iphdr *) skb->data; - __be32 daddr = iph->daddr; - __be32 saddr = iph->saddr; - + if (IN_DEV_LOG_MARTIANS(in_dev)) net_info_ratelimited("Redirect from %pI4 on %s about %pI4 ignored\n" " Advised path = %pI4 -> %pI4\n", &old_gw, dev->name, &new_gw, &saddr, &daddr); - } #endif ; } -static void ip_do_redirect(struct dst_entry *dst, struct sock *sk, struct sk_buff *skb) +static bool peer_pmtu_expired(struct inet_peer *peer) { - struct rtable *rt; - struct flowi4 fl4; + unsigned long orig = ACCESS_ONCE(peer->pmtu_expires); - rt = (struct rtable *) dst; + return orig && + time_after_eq(jiffies, orig) && + cmpxchg(&peer->pmtu_expires, orig, 0) == orig; +} - ip_rt_build_flow_key(&fl4, sk, skb); - __ip_do_redirect(rt, skb, &fl4); +static bool peer_pmtu_cleaned(struct inet_peer *peer) +{ + unsigned long orig = ACCESS_ONCE(peer->pmtu_expires); + + return orig && + cmpxchg(&peer->pmtu_expires, orig, 0) == orig; } static struct dst_entry *ipv4_negative_advice(struct dst_entry *dst) @@ -1504,13 +1458,16 @@ static struct dst_entry *ipv4_negative_advice(struct dst_entry *dst) if (dst->obsolete > 0) { ip_rt_put(rt); ret = NULL; - } else if ((rt->rt_flags & RTCF_REDIRECTED) || - rt->dst.expires) { + } else if (rt->rt_flags & RTCF_REDIRECTED) { unsigned int hash = rt_hash(rt->rt_key_dst, rt->rt_key_src, rt->rt_oif, rt_genid(dev_net(dst->dev))); rt_del(hash, rt); ret = NULL; + } else if (rt_has_peer(rt)) { + struct inet_peer *peer = rt_peer_ptr(rt); + if (peer_pmtu_expired(peer)) + dst_metric_set(dst, RTAX_MTU, peer->pmtu_orig); } } return ret; @@ -1537,7 +1494,6 @@ void ip_rt_send_redirect(struct sk_buff *skb) struct rtable *rt = skb_rtable(skb); struct in_device *in_dev; struct inet_peer *peer; - struct net *net; int log_martians; rcu_read_lock(); @@ -1549,8 +1505,7 @@ void ip_rt_send_redirect(struct sk_buff *skb) log_martians = IN_DEV_LOG_MARTIANS(in_dev); rcu_read_unlock(); - net = dev_net(rt->dst.dev); - peer = inet_getpeer_v4(net->ipv4.peers, ip_hdr(skb)->saddr, 1); + peer = rt_get_peer_create(rt, rt->rt_dst); if (!peer) { icmp_send(skb, ICMP_REDIRECT, ICMP_REDIR_HOST, rt->rt_gateway); return; @@ -1567,7 +1522,7 @@ void ip_rt_send_redirect(struct sk_buff *skb) */ if (peer->rate_tokens >= ip_rt_redirect_number) { peer->rate_last = jiffies; - goto out_put_peer; + return; } /* Check for load limit; set rate_last to the latest sent @@ -1588,8 +1543,6 @@ void ip_rt_send_redirect(struct sk_buff *skb) &rt->rt_dst, &rt->rt_gateway); #endif } -out_put_peer: - inet_putpeer(peer); } static int ip_error(struct sk_buff *skb) @@ -1632,7 +1585,7 @@ static int ip_error(struct sk_buff *skb) break; } - peer = inet_getpeer_v4(net->ipv4.peers, ip_hdr(skb)->saddr, 1); + peer = rt_get_peer_create(rt, rt->rt_dst); send = true; if (peer) { @@ -1645,7 +1598,6 @@ static int ip_error(struct sk_buff *skb) peer->rate_tokens -= ip_rt_error_cost; else send = false; - inet_putpeer(peer); } if (send) icmp_send(skb, ICMP_DEST_UNREACH, code, 0); @@ -1654,51 +1606,65 @@ out: kfree_skb(skb); return 0; } -static void __ip_rt_update_pmtu(struct rtable *rt, struct flowi4 *fl4, u32 mtu) +static void check_peer_pmtu(struct dst_entry *dst, struct inet_peer *peer) { - struct fib_result res; - - if (mtu < ip_rt_min_pmtu) - mtu = ip_rt_min_pmtu; + unsigned long expires = ACCESS_ONCE(peer->pmtu_expires); - if (fib_lookup(dev_net(rt->dst.dev), fl4, &res) == 0) { - struct fib_nh *nh = &FIB_RES_NH(res); - struct fib_nh_exception *fnhe; - - spin_lock_bh(&fnhe_lock); - fnhe = find_or_create_fnhe(nh, fl4->daddr); - if (fnhe) { - fnhe->fnhe_pmtu = mtu; - fnhe->fnhe_expires = jiffies + ip_rt_mtu_expires; + if (!expires) + return; + if (time_before(jiffies, expires)) { + u32 orig_dst_mtu = dst_mtu(dst); + if (peer->pmtu_learned < orig_dst_mtu) { + if (!peer->pmtu_orig) + peer->pmtu_orig = dst_metric_raw(dst, RTAX_MTU); + dst_metric_set(dst, RTAX_MTU, peer->pmtu_learned); } - spin_unlock_bh(&fnhe_lock); - } - rt->rt_pmtu = mtu; - dst_set_expires(&rt->dst, ip_rt_mtu_expires); + } else if (cmpxchg(&peer->pmtu_expires, expires, 0) == expires) + dst_metric_set(dst, RTAX_MTU, peer->pmtu_orig); } -static void ip_rt_update_pmtu(struct dst_entry *dst, struct sock *sk, - struct sk_buff *skb, u32 mtu) +static void ip_rt_update_pmtu(struct dst_entry *dst, u32 mtu) { struct rtable *rt = (struct rtable *) dst; - struct flowi4 fl4; + struct inet_peer *peer; + + dst_confirm(dst); + + peer = rt_get_peer_create(rt, rt->rt_dst); + if (peer) { + unsigned long pmtu_expires = ACCESS_ONCE(peer->pmtu_expires); - ip_rt_build_flow_key(&fl4, sk, skb); - __ip_rt_update_pmtu(rt, &fl4, mtu); + if (mtu < ip_rt_min_pmtu) + mtu = ip_rt_min_pmtu; + if (!pmtu_expires || mtu < peer->pmtu_learned) { + + pmtu_expires = jiffies + ip_rt_mtu_expires; + if (!pmtu_expires) + pmtu_expires = 1UL; + + peer->pmtu_learned = mtu; + peer->pmtu_expires = pmtu_expires; + + atomic_inc(&__rt_peer_genid); + rt->rt_peer_genid = rt_peer_genid(); + } + check_peer_pmtu(dst, peer); + } } void ipv4_update_pmtu(struct sk_buff *skb, struct net *net, u32 mtu, int oif, u32 mark, u8 protocol, int flow_flags) { - const struct iphdr *iph = (const struct iphdr *) skb->data; + const struct iphdr *iph = (const struct iphdr *)skb->data; struct flowi4 fl4; struct rtable *rt; - __build_flow_key(&fl4, NULL, iph, oif, - RT_TOS(iph->tos), protocol, mark, flow_flags); + flowi4_init_output(&fl4, oif, mark, RT_TOS(iph->tos), RT_SCOPE_UNIVERSE, + protocol, flow_flags | FLOWI_FLAG_PRECOW_METRICS, + iph->daddr, iph->saddr, 0, 0); rt = __ip_route_output_key(net, &fl4); if (!IS_ERR(rt)) { - __ip_rt_update_pmtu(rt, &fl4, mtu); + ip_rt_update_pmtu(&rt->dst, mtu); ip_rt_put(rt); } } @@ -1706,50 +1672,31 @@ EXPORT_SYMBOL_GPL(ipv4_update_pmtu); void ipv4_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, u32 mtu) { - const struct iphdr *iph = (const struct iphdr *) skb->data; - struct flowi4 fl4; - struct rtable *rt; + const struct inet_sock *inet = inet_sk(sk); - __build_flow_key(&fl4, sk, iph, 0, 0, 0, 0, 0); - rt = __ip_route_output_key(sock_net(sk), &fl4); - if (!IS_ERR(rt)) { - __ip_rt_update_pmtu(rt, &fl4, mtu); - ip_rt_put(rt); - } + return ipv4_update_pmtu(skb, sock_net(sk), mtu, + sk->sk_bound_dev_if, sk->sk_mark, + inet->hdrincl ? IPPROTO_RAW : sk->sk_protocol, + inet_sk_flowi_flags(sk)); } EXPORT_SYMBOL_GPL(ipv4_sk_update_pmtu); -void ipv4_redirect(struct sk_buff *skb, struct net *net, - int oif, u32 mark, u8 protocol, int flow_flags) +static void ipv4_validate_peer(struct rtable *rt) { - const struct iphdr *iph = (const struct iphdr *) skb->data; - struct flowi4 fl4; - struct rtable *rt; + if (rt->rt_peer_genid != rt_peer_genid()) { + struct inet_peer *peer = rt_get_peer(rt, rt->rt_dst); - __build_flow_key(&fl4, NULL, iph, oif, - RT_TOS(iph->tos), protocol, mark, flow_flags); - rt = __ip_route_output_key(net, &fl4); - if (!IS_ERR(rt)) { - __ip_do_redirect(rt, skb, &fl4); - ip_rt_put(rt); - } -} -EXPORT_SYMBOL_GPL(ipv4_redirect); + if (peer) { + check_peer_pmtu(&rt->dst, peer); -void ipv4_sk_redirect(struct sk_buff *skb, struct sock *sk) -{ - const struct iphdr *iph = (const struct iphdr *) skb->data; - struct flowi4 fl4; - struct rtable *rt; + if (peer->redirect_learned.a4 && + peer->redirect_learned.a4 != rt->rt_gateway) + check_peer_redir(&rt->dst, peer); + } - __build_flow_key(&fl4, sk, iph, 0, 0, 0, 0, 0); - rt = __ip_route_output_key(sock_net(sk), &fl4); - if (!IS_ERR(rt)) { - __ip_do_redirect(rt, skb, &fl4); - ip_rt_put(rt); + rt->rt_peer_genid = rt_peer_genid(); } } -EXPORT_SYMBOL_GPL(ipv4_sk_redirect); static struct dst_entry *ipv4_dst_check(struct dst_entry *dst, u32 cookie) { @@ -1757,6 +1704,7 @@ static struct dst_entry *ipv4_dst_check(struct dst_entry *dst, u32 cookie) if (rt_is_expired(rt)) return NULL; + ipv4_validate_peer(rt); return dst; } @@ -1768,6 +1716,10 @@ static void ipv4_dst_destroy(struct dst_entry *dst) fib_info_put(rt->fi); rt->fi = NULL; } + if (rt_has_peer(rt)) { + struct inet_peer *peer = rt_peer_ptr(rt); + inet_putpeer(peer); + } } @@ -1778,8 +1730,11 @@ static void ipv4_link_failure(struct sk_buff *skb) icmp_send(skb, ICMP_DEST_UNREACH, ICMP_HOST_UNREACH, 0); rt = skb_rtable(skb); - if (rt) - dst_set_expires(&rt->dst, 0); + if (rt && rt_has_peer(rt)) { + struct inet_peer *peer = rt_peer_ptr(rt); + if (peer_pmtu_cleaned(peer)) + dst_metric_set(&rt->dst, RTAX_MTU, peer->pmtu_orig); + } } static int ip_rt_bug(struct sk_buff *skb) @@ -1859,13 +1814,7 @@ static unsigned int ipv4_default_advmss(const struct dst_entry *dst) static unsigned int ipv4_mtu(const struct dst_entry *dst) { const struct rtable *rt = (const struct rtable *) dst; - unsigned int mtu = rt->rt_pmtu; - - if (mtu && time_after_eq(jiffies, rt->dst.expires)) - mtu = 0; - - if (!mtu) - mtu = dst_metric_raw(dst, RTAX_MTU); + unsigned int mtu = dst_metric_raw(dst, RTAX_MTU); if (mtu && rt_is_output_route(rt)) return mtu; @@ -1887,38 +1836,41 @@ static unsigned int ipv4_mtu(const struct dst_entry *dst) static void rt_init_metrics(struct rtable *rt, const struct flowi4 *fl4, struct fib_info *fi) { - if (fi->fib_metrics != (u32 *) dst_default_metrics) { - rt->fi = fi; - atomic_inc(&fi->fib_clntref); - } - dst_init_metrics(&rt->dst, fi->fib_metrics, true); -} - -static void rt_bind_exception(struct rtable *rt, struct fib_nh *nh, __be32 daddr) -{ - struct fnhe_hash_bucket *hash = nh->nh_exceptions; - struct fib_nh_exception *fnhe; - u32 hval; + struct inet_peer_base *base; + struct inet_peer *peer; + int create = 0; - hval = fnhe_hashfun(daddr); + /* If a peer entry exists for this destination, we must hook + * it up in order to get at cached metrics. + */ + if (fl4 && (fl4->flowi4_flags & FLOWI_FLAG_PRECOW_METRICS)) + create = 1; - for (fnhe = rcu_dereference(hash[hval].chain); fnhe; - fnhe = rcu_dereference(fnhe->fnhe_next)) { - if (fnhe->fnhe_daddr == daddr) { - if (fnhe->fnhe_pmtu) { - unsigned long expires = fnhe->fnhe_expires; - unsigned long diff = jiffies - expires; + base = inetpeer_base_ptr(rt->_peer); + BUG_ON(!base); - if (time_before(jiffies, expires)) { - rt->rt_pmtu = fnhe->fnhe_pmtu; - dst_set_expires(&rt->dst, diff); - } - } - if (fnhe->fnhe_gw) - rt->rt_gateway = fnhe->fnhe_gw; - fnhe->fnhe_stamp = jiffies; - break; + peer = inet_getpeer_v4(base, rt->rt_dst, create); + if (peer) { + __rt_set_peer(rt, peer); + rt->rt_peer_genid = rt_peer_genid(); + if (inet_metrics_new(peer)) + memcpy(peer->metrics, fi->fib_metrics, + sizeof(u32) * RTAX_MAX); + dst_init_metrics(&rt->dst, peer->metrics, false); + + check_peer_pmtu(&rt->dst, peer); + + if (peer->redirect_learned.a4 && + peer->redirect_learned.a4 != rt->rt_gateway) { + rt->rt_gateway = peer->redirect_learned.a4; + rt->rt_flags |= RTCF_REDIRECTED; } + } else { + if (fi->fib_metrics != (u32 *) dst_default_metrics) { + rt->fi = fi; + atomic_inc(&fi->fib_clntref); + } + dst_init_metrics(&rt->dst, fi->fib_metrics, true); } } @@ -1926,22 +1878,24 @@ static void rt_set_nexthop(struct rtable *rt, const struct flowi4 *fl4, const struct fib_result *res, struct fib_info *fi, u16 type, u32 itag) { - if (fi) { - struct fib_nh *nh = &FIB_RES_NH(*res); + struct dst_entry *dst = &rt->dst; - if (nh->nh_gw && nh->nh_scope == RT_SCOPE_LINK) - rt->rt_gateway = nh->nh_gw; - if (unlikely(nh->nh_exceptions)) - rt_bind_exception(rt, nh, fl4->daddr); + if (fi) { + if (FIB_RES_GW(*res) && + FIB_RES_NH(*res).nh_scope == RT_SCOPE_LINK) + rt->rt_gateway = FIB_RES_GW(*res); rt_init_metrics(rt, fl4, fi); #ifdef CONFIG_IP_ROUTE_CLASSID - rt->dst.tclassid = FIB_RES_NH(*res).nh_tclassid; + dst->tclassid = FIB_RES_NH(*res).nh_tclassid; #endif } + if (dst_mtu(dst) > IP_MAX_MTU) + dst_metric_set(dst, RTAX_MTU, IP_MAX_MTU); + #ifdef CONFIG_IP_ROUTE_CLASSID #ifdef CONFIG_IP_MULTIPLE_TABLES - set_class_tag(rt, res->tclassid); + set_class_tag(rt, fib_rules_tclass(res)); #endif set_class_tag(rt, itag); #endif @@ -2010,8 +1964,9 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr, rth->rt_iif = dev->ifindex; rth->rt_oif = 0; rth->rt_mark = skb->mark; - rth->rt_pmtu = 0; rth->rt_gateway = daddr; + rth->rt_peer_genid = 0; + rt_init_peer(rth, dev_net(dev)->ipv4.peers); rth->fi = NULL; if (our) { rth->dst.input= ip_local_deliver; @@ -2135,8 +2090,9 @@ static int __mkroute_input(struct sk_buff *skb, rth->rt_iif = in_dev->dev->ifindex; rth->rt_oif = 0; rth->rt_mark = skb->mark; - rth->rt_pmtu = 0; rth->rt_gateway = daddr; + rth->rt_peer_genid = 0; + rt_init_peer(rth, &res->table->tb_peers); rth->fi = NULL; rth->dst.input = ip_forward; @@ -2313,8 +2269,9 @@ out: return err; rth->rt_iif = dev->ifindex; rth->rt_oif = 0; rth->rt_mark = skb->mark; - rth->rt_pmtu = 0; rth->rt_gateway = daddr; + rth->rt_peer_genid = 0; + rt_init_peer(rth, net->ipv4.peers); rth->fi = NULL; if (res.type == RTN_UNREACHABLE) { rth->dst.input= ip_error; @@ -2389,6 +2346,7 @@ int ip_route_input_common(struct sk_buff *skb, __be32 daddr, __be32 saddr, rth->rt_mark == skb->mark && net_eq(dev_net(rth->dst.dev), net) && !rt_is_expired(rth)) { + ipv4_validate_peer(rth); if (noref) { dst_use_noref(&rth->dst, jiffies); skb_dst_set_noref(skb, &rth->dst); @@ -2510,8 +2468,11 @@ static struct rtable *__mkroute_output(const struct fib_result *res, rth->rt_iif = orig_oif ? : dev_out->ifindex; rth->rt_oif = orig_oif; rth->rt_mark = fl4->flowi4_mark; - rth->rt_pmtu = 0; rth->rt_gateway = fl4->daddr; + rth->rt_peer_genid = 0; + rt_init_peer(rth, (res->table ? + &res->table->tb_peers : + dev_net(dev_out)->ipv4.peers)); rth->fi = NULL; RT_CACHE_STAT_INC(out_slow_tot); @@ -2559,9 +2520,11 @@ static struct rtable *ip_route_output_slow(struct net *net, struct flowi4 *fl4) __be32 orig_saddr; int orig_oif; - res.tclassid = 0; res.fi = NULL; res.table = NULL; +#ifdef CONFIG_IP_MULTIPLE_TABLES + res.r = NULL; +#endif orig_daddr = fl4->daddr; orig_saddr = fl4->saddr; @@ -2763,6 +2726,7 @@ struct rtable *__ip_route_output_key(struct net *net, struct flowi4 *flp4) (IPTOS_RT_MASK | RTO_ONLINK)) && net_eq(dev_net(rth->dst.dev), net) && !rt_is_expired(rth)) { + ipv4_validate_peer(rth); dst_use(&rth->dst, jiffies); RT_CACHE_STAT_INC(out_hit); rcu_read_unlock_bh(); @@ -2793,13 +2757,7 @@ static unsigned int ipv4_blackhole_mtu(const struct dst_entry *dst) return mtu ? : dst->dev->mtu; } -static void ipv4_rt_blackhole_update_pmtu(struct dst_entry *dst, struct sock *sk, - struct sk_buff *skb, u32 mtu) -{ -} - -static void ipv4_rt_blackhole_redirect(struct dst_entry *dst, struct sock *sk, - struct sk_buff *skb) +static void ipv4_rt_blackhole_update_pmtu(struct dst_entry *dst, u32 mtu) { } @@ -2817,7 +2775,6 @@ static struct dst_ops ipv4_dst_blackhole_ops = { .mtu = ipv4_blackhole_mtu, .default_advmss = ipv4_default_advmss, .update_pmtu = ipv4_rt_blackhole_update_pmtu, - .redirect = ipv4_rt_blackhole_redirect, .cow_metrics = ipv4_rt_blackhole_cow_metrics, .neigh_lookup = ipv4_neigh_lookup, }; @@ -2833,6 +2790,7 @@ struct dst_entry *ipv4_blackhole_route(struct net *net, struct dst_entry *dst_or new->__use = 1; new->input = dst_discard; new->output = dst_discard; + dst_copy_metrics(new, &ort->dst); new->dev = ort->dst.dev; if (new->dev) @@ -2845,7 +2803,6 @@ struct dst_entry *ipv4_blackhole_route(struct net *net, struct dst_entry *dst_or rt->rt_iif = ort->rt_iif; rt->rt_oif = ort->rt_oif; rt->rt_mark = ort->rt_mark; - rt->rt_pmtu = ort->rt_pmtu; rt->rt_genid = rt_genid(net); rt->rt_flags = ort->rt_flags; @@ -2853,6 +2810,7 @@ struct dst_entry *ipv4_blackhole_route(struct net *net, struct dst_entry *dst_or rt->rt_dst = ort->rt_dst; rt->rt_src = ort->rt_src; rt->rt_gateway = ort->rt_gateway; + rt_transfer_peer(rt, ort); rt->fi = ort->fi; if (rt->fi) atomic_inc(&rt->fi->fib_clntref); @@ -2890,7 +2848,7 @@ static int rt_fill_info(struct net *net, struct rtmsg *r; struct nlmsghdr *nlh; unsigned long expires = 0; - u32 error; + u32 id = 0, ts = 0, tsage = 0, error; nlh = nlmsg_put(skb, pid, seq, event, sizeof(*r), flags); if (nlh == NULL) @@ -2943,12 +2901,21 @@ static int rt_fill_info(struct net *net, goto nla_put_failure; error = rt->dst.error; - expires = rt->dst.expires; - if (expires) { - if (time_before(jiffies, expires)) - expires -= jiffies; - else - expires = 0; + if (rt_has_peer(rt)) { + const struct inet_peer *peer = rt_peer_ptr(rt); + inet_peer_refcheck(peer); + id = atomic_read(&peer->ip_id_count) & 0xffff; + if (peer->tcp_ts_stamp) { + ts = peer->tcp_ts; + tsage = get_seconds() - peer->tcp_ts_stamp; + } + expires = ACCESS_ONCE(peer->pmtu_expires); + if (expires) { + if (time_before(jiffies, expires)) + expires -= jiffies; + else + expires = 0; + } } if (rt_is_input_route(rt)) { @@ -2977,7 +2944,8 @@ static int rt_fill_info(struct net *net, goto nla_put_failure; } - if (rtnl_put_cacheinfo(skb, &rt->dst, 0, expires, error) < 0) + if (rtnl_put_cacheinfo(skb, &rt->dst, id, ts, tsage, + expires, error) < 0) goto nla_put_failure; return nlmsg_end(skb, nlh); diff --git a/trunk/net/ipv4/sysctl_net_ipv4.c b/trunk/net/ipv4/sysctl_net_ipv4.c index 3f6a1e762e9c..12aa0c5867c4 100644 --- a/trunk/net/ipv4/sysctl_net_ipv4.c +++ b/trunk/net/ipv4/sysctl_net_ipv4.c @@ -598,20 +598,6 @@ static struct ctl_table ipv4_table[] = { .mode = 0644, .proc_handler = proc_dointvec }, - { - .procname = "tcp_limit_output_bytes", - .data = &sysctl_tcp_limit_output_bytes, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = proc_dointvec - }, - { - .procname = "tcp_challenge_ack_limit", - .data = &sysctl_tcp_challenge_ack_limit, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = proc_dointvec - }, #ifdef CONFIG_NET_DMA { .procname = "tcp_dma_copybreak", diff --git a/trunk/net/ipv4/tcp.c b/trunk/net/ipv4/tcp.c index 4252cd8f39fd..3ba605f60e4e 100644 --- a/trunk/net/ipv4/tcp.c +++ b/trunk/net/ipv4/tcp.c @@ -376,7 +376,6 @@ void tcp_init_sock(struct sock *sk) skb_queue_head_init(&tp->out_of_order_queue); tcp_init_xmit_timers(sk); tcp_prequeue_init(tp); - INIT_LIST_HEAD(&tp->tsq_node); icsk->icsk_rto = TCP_TIMEOUT_INIT; tp->mdev = TCP_TIMEOUT_INIT; @@ -797,10 +796,6 @@ static unsigned int tcp_xmit_size_goal(struct sock *sk, u32 mss_now, inet_csk(sk)->icsk_ext_hdr_len - tp->tcp_header_len); - /* TSQ : try to have two TSO segments in flight */ - xmit_size_goal = min_t(u32, xmit_size_goal, - sysctl_tcp_limit_output_bytes >> 1); - xmit_size_goal = tcp_bound_to_half_wnd(tp, xmit_size_goal); /* We try hard to avoid divides here */ @@ -3315,7 +3310,8 @@ EXPORT_SYMBOL(tcp_md5_hash_key); #endif -/* Each Responder maintains up to two secret values concurrently for +/** + * Each Responder maintains up to two secret values concurrently for * efficient secret rollover. Each secret value has 4 states: * * Generating. (tcp_secret_generating != tcp_secret_primary) @@ -3567,8 +3563,6 @@ void __init tcp_init(void) pr_info("Hash tables configured (established %u bind %u)\n", tcp_hashinfo.ehash_mask + 1, tcp_hashinfo.bhash_size); - tcp_metrics_init(); - tcp_register_congestion_control(&tcp_reno); memset(&tcp_secret_one.secrets[0], 0, sizeof(tcp_secret_one.secrets)); @@ -3579,5 +3573,4 @@ void __init tcp_init(void) tcp_secret_primary = &tcp_secret_one; tcp_secret_retiring = &tcp_secret_two; tcp_secret_secondary = &tcp_secret_two; - tcp_tasklet_init(); } diff --git a/trunk/net/ipv4/tcp_input.c b/trunk/net/ipv4/tcp_input.c index 8aaec5536111..ca0d0e7c9778 100644 --- a/trunk/net/ipv4/tcp_input.c +++ b/trunk/net/ipv4/tcp_input.c @@ -88,14 +88,12 @@ int sysctl_tcp_app_win __read_mostly = 31; int sysctl_tcp_adv_win_scale __read_mostly = 1; EXPORT_SYMBOL(sysctl_tcp_adv_win_scale); -/* rfc5961 challenge ack rate limiting */ -int sysctl_tcp_challenge_ack_limit = 100; - int sysctl_tcp_stdurg __read_mostly; int sysctl_tcp_rfc1337 __read_mostly; int sysctl_tcp_max_orphans __read_mostly = NR_FILE; int sysctl_tcp_frto __read_mostly = 2; int sysctl_tcp_frto_response __read_mostly; +int sysctl_tcp_nometrics_save __read_mostly; int sysctl_tcp_thin_dupack __read_mostly; @@ -703,7 +701,7 @@ static void tcp_rtt_estimator(struct sock *sk, const __u32 mrtt) /* Calculate rto without backoff. This is the second half of Van Jacobson's * routine referred to above. */ -void tcp_set_rto(struct sock *sk) +static inline void tcp_set_rto(struct sock *sk) { const struct tcp_sock *tp = tcp_sk(sk); /* Old crap is replaced with new one. 8) @@ -730,6 +728,109 @@ void tcp_set_rto(struct sock *sk) tcp_bound_rto(sk); } +/* Save metrics learned by this TCP session. + This function is called only, when TCP finishes successfully + i.e. when it enters TIME-WAIT or goes from LAST-ACK to CLOSE. + */ +void tcp_update_metrics(struct sock *sk) +{ + struct tcp_sock *tp = tcp_sk(sk); + struct dst_entry *dst = __sk_dst_get(sk); + + if (sysctl_tcp_nometrics_save) + return; + + if (dst && (dst->flags & DST_HOST)) { + const struct inet_connection_sock *icsk = inet_csk(sk); + int m; + unsigned long rtt; + + dst_confirm(dst); + + if (icsk->icsk_backoff || !tp->srtt) { + /* This session failed to estimate rtt. Why? + * Probably, no packets returned in time. + * Reset our results. + */ + if (!(dst_metric_locked(dst, RTAX_RTT))) + dst_metric_set(dst, RTAX_RTT, 0); + return; + } + + rtt = dst_metric_rtt(dst, RTAX_RTT); + m = rtt - tp->srtt; + + /* If newly calculated rtt larger than stored one, + * store new one. Otherwise, use EWMA. Remember, + * rtt overestimation is always better than underestimation. + */ + if (!(dst_metric_locked(dst, RTAX_RTT))) { + if (m <= 0) + set_dst_metric_rtt(dst, RTAX_RTT, tp->srtt); + else + set_dst_metric_rtt(dst, RTAX_RTT, rtt - (m >> 3)); + } + + if (!(dst_metric_locked(dst, RTAX_RTTVAR))) { + unsigned long var; + if (m < 0) + m = -m; + + /* Scale deviation to rttvar fixed point */ + m >>= 1; + if (m < tp->mdev) + m = tp->mdev; + + var = dst_metric_rtt(dst, RTAX_RTTVAR); + if (m >= var) + var = m; + else + var -= (var - m) >> 2; + + set_dst_metric_rtt(dst, RTAX_RTTVAR, var); + } + + if (tcp_in_initial_slowstart(tp)) { + /* Slow start still did not finish. */ + if (dst_metric(dst, RTAX_SSTHRESH) && + !dst_metric_locked(dst, RTAX_SSTHRESH) && + (tp->snd_cwnd >> 1) > dst_metric(dst, RTAX_SSTHRESH)) + dst_metric_set(dst, RTAX_SSTHRESH, tp->snd_cwnd >> 1); + if (!dst_metric_locked(dst, RTAX_CWND) && + tp->snd_cwnd > dst_metric(dst, RTAX_CWND)) + dst_metric_set(dst, RTAX_CWND, tp->snd_cwnd); + } else if (tp->snd_cwnd > tp->snd_ssthresh && + icsk->icsk_ca_state == TCP_CA_Open) { + /* Cong. avoidance phase, cwnd is reliable. */ + if (!dst_metric_locked(dst, RTAX_SSTHRESH)) + dst_metric_set(dst, RTAX_SSTHRESH, + max(tp->snd_cwnd >> 1, tp->snd_ssthresh)); + if (!dst_metric_locked(dst, RTAX_CWND)) + dst_metric_set(dst, RTAX_CWND, + (dst_metric(dst, RTAX_CWND) + + tp->snd_cwnd) >> 1); + } else { + /* Else slow start did not finish, cwnd is non-sense, + ssthresh may be also invalid. + */ + if (!dst_metric_locked(dst, RTAX_CWND)) + dst_metric_set(dst, RTAX_CWND, + (dst_metric(dst, RTAX_CWND) + + tp->snd_ssthresh) >> 1); + if (dst_metric(dst, RTAX_SSTHRESH) && + !dst_metric_locked(dst, RTAX_SSTHRESH) && + tp->snd_ssthresh > dst_metric(dst, RTAX_SSTHRESH)) + dst_metric_set(dst, RTAX_SSTHRESH, tp->snd_ssthresh); + } + + if (!dst_metric_locked(dst, RTAX_REORDERING)) { + if (dst_metric(dst, RTAX_REORDERING) < tp->reordering && + tp->reordering != sysctl_tcp_reordering) + dst_metric_set(dst, RTAX_REORDERING, tp->reordering); + } + } +} + __u32 tcp_init_cwnd(const struct tcp_sock *tp, const struct dst_entry *dst) { __u32 cwnd = (dst ? dst_metric(dst, RTAX_INITCWND) : 0); @@ -766,7 +867,7 @@ void tcp_enter_cwr(struct sock *sk, const int set_ssthresh) * Packet counting of FACK is based on in-order assumptions, therefore TCP * disables it when reordering is detected */ -void tcp_disable_fack(struct tcp_sock *tp) +static void tcp_disable_fack(struct tcp_sock *tp) { /* RFC3517 uses different metric in lost marker => reset on change */ if (tcp_is_fack(tp)) @@ -780,6 +881,86 @@ static void tcp_dsack_seen(struct tcp_sock *tp) tp->rx_opt.sack_ok |= TCP_DSACK_SEEN; } +/* Initialize metrics on socket. */ + +static void tcp_init_metrics(struct sock *sk) +{ + struct tcp_sock *tp = tcp_sk(sk); + struct dst_entry *dst = __sk_dst_get(sk); + + if (dst == NULL) + goto reset; + + dst_confirm(dst); + + if (dst_metric_locked(dst, RTAX_CWND)) + tp->snd_cwnd_clamp = dst_metric(dst, RTAX_CWND); + if (dst_metric(dst, RTAX_SSTHRESH)) { + tp->snd_ssthresh = dst_metric(dst, RTAX_SSTHRESH); + if (tp->snd_ssthresh > tp->snd_cwnd_clamp) + tp->snd_ssthresh = tp->snd_cwnd_clamp; + } else { + /* ssthresh may have been reduced unnecessarily during. + * 3WHS. Restore it back to its initial default. + */ + tp->snd_ssthresh = TCP_INFINITE_SSTHRESH; + } + if (dst_metric(dst, RTAX_REORDERING) && + tp->reordering != dst_metric(dst, RTAX_REORDERING)) { + tcp_disable_fack(tp); + tcp_disable_early_retrans(tp); + tp->reordering = dst_metric(dst, RTAX_REORDERING); + } + + if (dst_metric(dst, RTAX_RTT) == 0 || tp->srtt == 0) + goto reset; + + /* Initial rtt is determined from SYN,SYN-ACK. + * The segment is small and rtt may appear much + * less than real one. Use per-dst memory + * to make it more realistic. + * + * A bit of theory. RTT is time passed after "normal" sized packet + * is sent until it is ACKed. In normal circumstances sending small + * packets force peer to delay ACKs and calculation is correct too. + * The algorithm is adaptive and, provided we follow specs, it + * NEVER underestimate RTT. BUT! If peer tries to make some clever + * tricks sort of "quick acks" for time long enough to decrease RTT + * to low value, and then abruptly stops to do it and starts to delay + * ACKs, wait for troubles. + */ + if (dst_metric_rtt(dst, RTAX_RTT) > tp->srtt) { + tp->srtt = dst_metric_rtt(dst, RTAX_RTT); + tp->rtt_seq = tp->snd_nxt; + } + if (dst_metric_rtt(dst, RTAX_RTTVAR) > tp->mdev) { + tp->mdev = dst_metric_rtt(dst, RTAX_RTTVAR); + tp->mdev_max = tp->rttvar = max(tp->mdev, tcp_rto_min(sk)); + } + tcp_set_rto(sk); +reset: + if (tp->srtt == 0) { + /* RFC6298: 5.7 We've failed to get a valid RTT sample from + * 3WHS. This is most likely due to retransmission, + * including spurious one. Reset the RTO back to 3secs + * from the more aggressive 1sec to avoid more spurious + * retransmission. + */ + tp->mdev = tp->mdev_max = tp->rttvar = TCP_TIMEOUT_FALLBACK; + inet_csk(sk)->icsk_rto = TCP_TIMEOUT_FALLBACK; + } + /* Cut cwnd down to 1 per RFC5681 if SYN or SYN-ACK has been + * retransmitted. In light of RFC6298 more aggressive 1sec + * initRTO, we only reset cwnd when more than 1 SYN/SYN-ACK + * retransmission has occurred. + */ + if (tp->total_retrans > 1) + tp->snd_cwnd = 1; + else + tp->snd_cwnd = tcp_init_cwnd(tp, dst); + tp->snd_cwnd_stamp = tcp_time_stamp; +} + static void tcp_update_reordering(struct sock *sk, const int metric, const int ts) { @@ -4400,8 +4581,8 @@ static void tcp_data_queue_ofo(struct sock *sk, struct sk_buff *skb) TCP_ECN_check_ce(tp, skb); - if (unlikely(tcp_try_rmem_schedule(sk, skb->truesize))) { - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPOFODROP); + if (tcp_try_rmem_schedule(sk, skb->truesize)) { + /* TODO: should increment a counter */ __kfree_skb(skb); return; } @@ -4410,7 +4591,6 @@ static void tcp_data_queue_ofo(struct sock *sk, struct sk_buff *skb) tp->pred_flags = 0; inet_csk_schedule_ack(sk); - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPOFOQUEUE); SOCK_DEBUG(sk, "out of order segment: rcv_next %X seq %X - %X\n", tp->rcv_nxt, TCP_SKB_CB(skb)->seq, TCP_SKB_CB(skb)->end_seq); @@ -4464,7 +4644,6 @@ static void tcp_data_queue_ofo(struct sock *sk, struct sk_buff *skb) if (skb1 && before(seq, TCP_SKB_CB(skb1)->end_seq)) { if (!after(end_seq, TCP_SKB_CB(skb1)->end_seq)) { /* All the bits are present. Drop. */ - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPOFOMERGE); __kfree_skb(skb); skb = NULL; tcp_dsack_set(sk, seq, end_seq); @@ -4503,7 +4682,6 @@ static void tcp_data_queue_ofo(struct sock *sk, struct sk_buff *skb) __skb_unlink(skb1, &tp->out_of_order_queue); tcp_dsack_extend(sk, TCP_SKB_CB(skb1)->seq, TCP_SKB_CB(skb1)->end_seq); - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPOFOMERGE); __kfree_skb(skb1); } @@ -5250,28 +5428,11 @@ static bool tcp_dma_try_early_copy(struct sock *sk, struct sk_buff *skb, } #endif /* CONFIG_NET_DMA */ -static void tcp_send_challenge_ack(struct sock *sk) -{ - /* unprotected vars, we dont care of overwrites */ - static u32 challenge_timestamp; - static unsigned int challenge_count; - u32 now = jiffies / HZ; - - if (now != challenge_timestamp) { - challenge_timestamp = now; - challenge_count = 0; - } - if (++challenge_count <= sysctl_tcp_challenge_ack_limit) { - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPCHALLENGEACK); - tcp_send_ack(sk); - } -} - /* Does PAWS and seqno based validation of an incoming segment, flags will * play significant role here. */ -static bool tcp_validate_incoming(struct sock *sk, struct sk_buff *skb, - const struct tcphdr *th, int syn_inerr) +static int tcp_validate_incoming(struct sock *sk, struct sk_buff *skb, + const struct tcphdr *th, int syn_inerr) { const u8 *hash_location; struct tcp_sock *tp = tcp_sk(sk); @@ -5303,16 +5464,7 @@ static bool tcp_validate_incoming(struct sock *sk, struct sk_buff *skb, /* Step 2: check RST bit */ if (th->rst) { - /* RFC 5961 3.2 : - * If sequence number exactly matches RCV.NXT, then - * RESET the connection - * else - * Send a challenge ACK - */ - if (TCP_SKB_CB(skb)->seq == tp->rcv_nxt) - tcp_reset(sk); - else - tcp_send_challenge_ack(sk); + tcp_reset(sk); goto discard; } @@ -5323,22 +5475,20 @@ static bool tcp_validate_incoming(struct sock *sk, struct sk_buff *skb, /* step 3: check security and precedence [ignored] */ - /* step 4: Check for a SYN - * RFC 5691 4.2 : Send a challenge ack - */ - if (th->syn) { + /* step 4: Check for a SYN in window. */ + if (th->syn && !before(TCP_SKB_CB(skb)->seq, tp->rcv_nxt)) { if (syn_inerr) TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_INERRS); - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPSYNCHALLENGE); - tcp_send_challenge_ack(sk); - goto discard; + NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPABORTONSYN); + tcp_reset(sk); + return -1; } - return true; + return 1; discard: __kfree_skb(skb); - return false; + return 0; } /* @@ -5368,6 +5518,7 @@ int tcp_rcv_established(struct sock *sk, struct sk_buff *skb, const struct tcphdr *th, unsigned int len) { struct tcp_sock *tp = tcp_sk(sk); + int res; if (sk->sk_rx_dst) { struct dst_entry *dst = sk->sk_rx_dst; @@ -5556,8 +5707,9 @@ int tcp_rcv_established(struct sock *sk, struct sk_buff *skb, * Standard slow path. */ - if (!tcp_validate_incoming(sk, skb, th, 1)) - return 0; + res = tcp_validate_incoming(sk, skb, th, 1); + if (res <= 0) + return -res; step5: if (th->ack && tcp_ack(sk, skb, FLAG_SLOWPATH) < 0) @@ -5877,6 +6029,7 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb, struct tcp_sock *tp = tcp_sk(sk); struct inet_connection_sock *icsk = inet_csk(sk); int queued = 0; + int res; tp->rx_opt.saw_tstamp = 0; @@ -5931,8 +6084,9 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb, return 0; } - if (!tcp_validate_incoming(sk, skb, th, 0)) - return 0; + res = tcp_validate_incoming(sk, skb, th, 0); + if (res <= 0) + return -res; /* step 5: check the ACK field */ if (th->ack) { diff --git a/trunk/net/ipv4/tcp_ipv4.c b/trunk/net/ipv4/tcp_ipv4.c index d9caf5c07aae..64568fa21d05 100644 --- a/trunk/net/ipv4/tcp_ipv4.c +++ b/trunk/net/ipv4/tcp_ipv4.c @@ -209,8 +209,22 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) } if (tcp_death_row.sysctl_tw_recycle && - !tp->rx_opt.ts_recent_stamp && fl4->daddr == daddr) - tcp_fetch_timewait_stamp(sk, &rt->dst); + !tp->rx_opt.ts_recent_stamp && fl4->daddr == daddr) { + struct inet_peer *peer = rt_get_peer(rt, fl4->daddr); + /* + * VJ's idea. We save last timestamp seen from + * the destination in peer table, when entering state + * TIME-WAIT * and initialize rx_opt.ts_recent from it, + * when trying new connection. + */ + if (peer) { + inet_peer_refcheck(peer); + if ((u32)get_seconds() - peer->tcp_ts_stamp <= TCP_PAWS_MSL) { + tp->rx_opt.ts_recent_stamp = peer->tcp_ts_stamp; + tp->rx_opt.ts_recent = peer->tcp_ts; + } + } + } inet->inet_dport = usin->sin_port; inet->inet_daddr = daddr; @@ -289,10 +303,17 @@ static void do_pmtu_discovery(struct sock *sk, const struct iphdr *iph, u32 mtu) if (sk->sk_state == TCP_LISTEN) return; - dst = inet_csk_update_pmtu(sk, mtu); - if (!dst) + /* We don't check in the destentry if pmtu discovery is forbidden + * on this route. We just assume that no packet_to_big packets + * are send back when pmtu discovery is not active. + * There is a small race when the user changes this flag in the + * route, but I think that's acceptable. + */ + if ((dst = __sk_dst_check(sk, 0)) == NULL) return; + dst->ops->update_pmtu(dst, mtu); + /* Something is about to be wrong... Remember soft error * for the case, if this connection will not able to recover. */ @@ -314,14 +335,6 @@ static void do_pmtu_discovery(struct sock *sk, const struct iphdr *iph, u32 mtu) } /* else let the usual retransmit timer handle it */ } -static void do_redirect(struct sk_buff *skb, struct sock *sk) -{ - struct dst_entry *dst = __sk_dst_check(sk, 0); - - if (dst) - dst->ops->redirect(dst, sk, skb); -} - /* * This routine is called by the ICMP module when it gets some * sort of error condition. If err < 0 then the socket should @@ -395,9 +408,6 @@ void tcp_v4_err(struct sk_buff *icmp_skb, u32 info) } switch (type) { - case ICMP_REDIRECT: - do_redirect(icmp_skb, sk); - goto out; case ICMP_SOURCE_QUENCH: /* Just silently ignore these. */ goto out; @@ -1365,6 +1375,7 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) isn = cookie_v4_init_sequence(sk, skb, &req->mss); req->cookie_ts = tmp_opt.tstamp_ok; } else if (!isn) { + struct inet_peer *peer = NULL; struct flowi4 fl4; /* VJ's idea. We save last timestamp seen @@ -1379,8 +1390,12 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) if (tmp_opt.saw_tstamp && tcp_death_row.sysctl_tw_recycle && (dst = inet_csk_route_req(sk, &fl4, req, want_cookie)) != NULL && - fl4.daddr == saddr) { - if (!tcp_peer_is_proven(req, dst, true)) { + fl4.daddr == saddr && + (peer = rt_get_peer((struct rtable *)dst, fl4.daddr)) != NULL) { + inet_peer_refcheck(peer); + if ((u32)get_seconds() - peer->tcp_ts_stamp < TCP_PAWS_MSL && + (s32)(peer->tcp_ts - req->ts_recent) > + TCP_PAWS_WINDOW) { NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_PAWSPASSIVEREJECTED); goto drop_and_release; } @@ -1389,7 +1404,8 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) else if (!sysctl_tcp_syncookies && (sysctl_max_syn_backlog - inet_csk_reqsk_queue_len(sk) < (sysctl_max_syn_backlog >> 2)) && - !tcp_peer_is_proven(req, dst, false)) { + (!peer || !peer->tcp_ts_stamp) && + (!dst || !dst_metric(dst, RTAX_RTT))) { /* Without syncookies last quarter of * backlog is filled with destinations, * proven to be alive. @@ -1851,6 +1867,21 @@ int tcp_v4_rcv(struct sk_buff *skb) goto discard_it; } +struct inet_peer *tcp_v4_get_peer(struct sock *sk) +{ + struct rtable *rt = (struct rtable *) __sk_dst_get(sk); + struct inet_sock *inet = inet_sk(sk); + + /* If we don't have a valid cached route, or we're doing IP + * options which make the IPv4 header destination address + * different from our peer's, do not bother with this. + */ + if (!rt || inet->cork.fl.u.ip4.daddr != inet->inet_daddr) + return NULL; + return rt_get_peer_create(rt, inet->inet_daddr); +} +EXPORT_SYMBOL(tcp_v4_get_peer); + static struct timewait_sock_ops tcp_timewait_sock_ops = { .twsk_obj_size = sizeof(struct tcp_timewait_sock), .twsk_unique = tcp_twsk_unique, @@ -1863,6 +1894,7 @@ const struct inet_connection_sock_af_ops ipv4_specific = { .rebuild_header = inet_sk_rebuild_header, .conn_request = tcp_v4_conn_request, .syn_recv_sock = tcp_v4_syn_recv_sock, + .get_peer = tcp_v4_get_peer, .net_header_len = sizeof(struct iphdr), .setsockopt = ip_setsockopt, .getsockopt = ip_getsockopt, @@ -2592,7 +2624,6 @@ struct proto tcp_prot = { .sendmsg = tcp_sendmsg, .sendpage = tcp_sendpage, .backlog_rcv = tcp_v4_do_rcv, - .release_cb = tcp_release_cb, .hash = inet_hash, .unhash = inet_unhash, .get_port = inet_csk_get_port, diff --git a/trunk/net/ipv4/tcp_metrics.c b/trunk/net/ipv4/tcp_metrics.c deleted file mode 100644 index 5a38a2d5a95b..000000000000 --- a/trunk/net/ipv4/tcp_metrics.c +++ /dev/null @@ -1,697 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -int sysctl_tcp_nometrics_save __read_mostly; - -enum tcp_metric_index { - TCP_METRIC_RTT, - TCP_METRIC_RTTVAR, - TCP_METRIC_SSTHRESH, - TCP_METRIC_CWND, - TCP_METRIC_REORDERING, - - /* Always last. */ - TCP_METRIC_MAX, -}; - -struct tcp_metrics_block { - struct tcp_metrics_block __rcu *tcpm_next; - struct inetpeer_addr tcpm_addr; - unsigned long tcpm_stamp; - u32 tcpm_ts; - u32 tcpm_ts_stamp; - u32 tcpm_lock; - u32 tcpm_vals[TCP_METRIC_MAX]; -}; - -static bool tcp_metric_locked(struct tcp_metrics_block *tm, - enum tcp_metric_index idx) -{ - return tm->tcpm_lock & (1 << idx); -} - -static u32 tcp_metric_get(struct tcp_metrics_block *tm, - enum tcp_metric_index idx) -{ - return tm->tcpm_vals[idx]; -} - -static u32 tcp_metric_get_jiffies(struct tcp_metrics_block *tm, - enum tcp_metric_index idx) -{ - return msecs_to_jiffies(tm->tcpm_vals[idx]); -} - -static void tcp_metric_set(struct tcp_metrics_block *tm, - enum tcp_metric_index idx, - u32 val) -{ - tm->tcpm_vals[idx] = val; -} - -static void tcp_metric_set_msecs(struct tcp_metrics_block *tm, - enum tcp_metric_index idx, - u32 val) -{ - tm->tcpm_vals[idx] = jiffies_to_msecs(val); -} - -static bool addr_same(const struct inetpeer_addr *a, - const struct inetpeer_addr *b) -{ - const struct in6_addr *a6, *b6; - - if (a->family != b->family) - return false; - if (a->family == AF_INET) - return a->addr.a4 == b->addr.a4; - - a6 = (const struct in6_addr *) &a->addr.a6[0]; - b6 = (const struct in6_addr *) &b->addr.a6[0]; - - return ipv6_addr_equal(a6, b6); -} - -struct tcpm_hash_bucket { - struct tcp_metrics_block __rcu *chain; -}; - -static DEFINE_SPINLOCK(tcp_metrics_lock); - -static void tcpm_suck_dst(struct tcp_metrics_block *tm, struct dst_entry *dst) -{ - u32 val; - - val = 0; - if (dst_metric_locked(dst, RTAX_RTT)) - val |= 1 << TCP_METRIC_RTT; - if (dst_metric_locked(dst, RTAX_RTTVAR)) - val |= 1 << TCP_METRIC_RTTVAR; - if (dst_metric_locked(dst, RTAX_SSTHRESH)) - val |= 1 << TCP_METRIC_SSTHRESH; - if (dst_metric_locked(dst, RTAX_CWND)) - val |= 1 << TCP_METRIC_CWND; - if (dst_metric_locked(dst, RTAX_REORDERING)) - val |= 1 << TCP_METRIC_REORDERING; - tm->tcpm_lock = val; - - tm->tcpm_vals[TCP_METRIC_RTT] = dst_metric_raw(dst, RTAX_RTT); - tm->tcpm_vals[TCP_METRIC_RTTVAR] = dst_metric_raw(dst, RTAX_RTTVAR); - tm->tcpm_vals[TCP_METRIC_SSTHRESH] = dst_metric_raw(dst, RTAX_SSTHRESH); - tm->tcpm_vals[TCP_METRIC_CWND] = dst_metric_raw(dst, RTAX_CWND); - tm->tcpm_vals[TCP_METRIC_REORDERING] = dst_metric_raw(dst, RTAX_REORDERING); - tm->tcpm_ts = 0; - tm->tcpm_ts_stamp = 0; -} - -static struct tcp_metrics_block *tcpm_new(struct dst_entry *dst, - struct inetpeer_addr *addr, - unsigned int hash, - bool reclaim) -{ - struct tcp_metrics_block *tm; - struct net *net; - - spin_lock_bh(&tcp_metrics_lock); - net = dev_net(dst->dev); - if (unlikely(reclaim)) { - struct tcp_metrics_block *oldest; - - oldest = rcu_dereference(net->ipv4.tcp_metrics_hash[hash].chain); - for (tm = rcu_dereference(oldest->tcpm_next); tm; - tm = rcu_dereference(tm->tcpm_next)) { - if (time_before(tm->tcpm_stamp, oldest->tcpm_stamp)) - oldest = tm; - } - tm = oldest; - } else { - tm = kmalloc(sizeof(*tm), GFP_ATOMIC); - if (!tm) - goto out_unlock; - } - tm->tcpm_addr = *addr; - tm->tcpm_stamp = jiffies; - - tcpm_suck_dst(tm, dst); - - if (likely(!reclaim)) { - tm->tcpm_next = net->ipv4.tcp_metrics_hash[hash].chain; - rcu_assign_pointer(net->ipv4.tcp_metrics_hash[hash].chain, tm); - } - -out_unlock: - spin_unlock_bh(&tcp_metrics_lock); - return tm; -} - -#define TCP_METRICS_TIMEOUT (60 * 60 * HZ) - -static void tcpm_check_stamp(struct tcp_metrics_block *tm, struct dst_entry *dst) -{ - if (tm && unlikely(time_after(jiffies, tm->tcpm_stamp + TCP_METRICS_TIMEOUT))) - tcpm_suck_dst(tm, dst); -} - -#define TCP_METRICS_RECLAIM_DEPTH 5 -#define TCP_METRICS_RECLAIM_PTR (struct tcp_metrics_block *) 0x1UL - -static struct tcp_metrics_block *tcp_get_encode(struct tcp_metrics_block *tm, int depth) -{ - if (tm) - return tm; - if (depth > TCP_METRICS_RECLAIM_DEPTH) - return TCP_METRICS_RECLAIM_PTR; - return NULL; -} - -static struct tcp_metrics_block *__tcp_get_metrics(const struct inetpeer_addr *addr, - struct net *net, unsigned int hash) -{ - struct tcp_metrics_block *tm; - int depth = 0; - - for (tm = rcu_dereference(net->ipv4.tcp_metrics_hash[hash].chain); tm; - tm = rcu_dereference(tm->tcpm_next)) { - if (addr_same(&tm->tcpm_addr, addr)) - break; - depth++; - } - return tcp_get_encode(tm, depth); -} - -static struct tcp_metrics_block *__tcp_get_metrics_req(struct request_sock *req, - struct dst_entry *dst) -{ - struct tcp_metrics_block *tm; - struct inetpeer_addr addr; - unsigned int hash; - struct net *net; - - addr.family = req->rsk_ops->family; - switch (addr.family) { - case AF_INET: - addr.addr.a4 = inet_rsk(req)->rmt_addr; - hash = (__force unsigned int) addr.addr.a4; - break; - case AF_INET6: - *(struct in6_addr *)addr.addr.a6 = inet6_rsk(req)->rmt_addr; - hash = ((__force unsigned int) addr.addr.a6[0] ^ - (__force unsigned int) addr.addr.a6[1] ^ - (__force unsigned int) addr.addr.a6[2] ^ - (__force unsigned int) addr.addr.a6[3]); - break; - default: - return NULL; - } - - hash ^= (hash >> 24) ^ (hash >> 16) ^ (hash >> 8); - - net = dev_net(dst->dev); - hash &= net->ipv4.tcp_metrics_hash_mask; - - for (tm = rcu_dereference(net->ipv4.tcp_metrics_hash[hash].chain); tm; - tm = rcu_dereference(tm->tcpm_next)) { - if (addr_same(&tm->tcpm_addr, &addr)) - break; - } - tcpm_check_stamp(tm, dst); - return tm; -} - -static struct tcp_metrics_block *__tcp_get_metrics_tw(struct inet_timewait_sock *tw) -{ - struct inet6_timewait_sock *tw6; - struct tcp_metrics_block *tm; - struct inetpeer_addr addr; - unsigned int hash; - struct net *net; - - addr.family = tw->tw_family; - switch (addr.family) { - case AF_INET: - addr.addr.a4 = tw->tw_daddr; - hash = (__force unsigned int) addr.addr.a4; - break; - case AF_INET6: - tw6 = inet6_twsk((struct sock *)tw); - *(struct in6_addr *)addr.addr.a6 = tw6->tw_v6_daddr; - hash = ((__force unsigned int) addr.addr.a6[0] ^ - (__force unsigned int) addr.addr.a6[1] ^ - (__force unsigned int) addr.addr.a6[2] ^ - (__force unsigned int) addr.addr.a6[3]); - break; - default: - return NULL; - } - - hash ^= (hash >> 24) ^ (hash >> 16) ^ (hash >> 8); - - net = twsk_net(tw); - hash &= net->ipv4.tcp_metrics_hash_mask; - - for (tm = rcu_dereference(net->ipv4.tcp_metrics_hash[hash].chain); tm; - tm = rcu_dereference(tm->tcpm_next)) { - if (addr_same(&tm->tcpm_addr, &addr)) - break; - } - return tm; -} - -static struct tcp_metrics_block *tcp_get_metrics(struct sock *sk, - struct dst_entry *dst, - bool create) -{ - struct tcp_metrics_block *tm; - struct inetpeer_addr addr; - unsigned int hash; - struct net *net; - bool reclaim; - - addr.family = sk->sk_family; - switch (addr.family) { - case AF_INET: - addr.addr.a4 = inet_sk(sk)->inet_daddr; - hash = (__force unsigned int) addr.addr.a4; - break; - case AF_INET6: - *(struct in6_addr *)addr.addr.a6 = inet6_sk(sk)->daddr; - hash = ((__force unsigned int) addr.addr.a6[0] ^ - (__force unsigned int) addr.addr.a6[1] ^ - (__force unsigned int) addr.addr.a6[2] ^ - (__force unsigned int) addr.addr.a6[3]); - break; - default: - return NULL; - } - - hash ^= (hash >> 24) ^ (hash >> 16) ^ (hash >> 8); - - net = dev_net(dst->dev); - hash &= net->ipv4.tcp_metrics_hash_mask; - - tm = __tcp_get_metrics(&addr, net, hash); - reclaim = false; - if (tm == TCP_METRICS_RECLAIM_PTR) { - reclaim = true; - tm = NULL; - } - if (!tm && create) - tm = tcpm_new(dst, &addr, hash, reclaim); - else - tcpm_check_stamp(tm, dst); - - return tm; -} - -/* Save metrics learned by this TCP session. This function is called - * only, when TCP finishes successfully i.e. when it enters TIME-WAIT - * or goes from LAST-ACK to CLOSE. - */ -void tcp_update_metrics(struct sock *sk) -{ - const struct inet_connection_sock *icsk = inet_csk(sk); - struct dst_entry *dst = __sk_dst_get(sk); - struct tcp_sock *tp = tcp_sk(sk); - struct tcp_metrics_block *tm; - unsigned long rtt; - u32 val; - int m; - - if (sysctl_tcp_nometrics_save || !dst) - return; - - if (dst->flags & DST_HOST) - dst_confirm(dst); - - rcu_read_lock(); - if (icsk->icsk_backoff || !tp->srtt) { - /* This session failed to estimate rtt. Why? - * Probably, no packets returned in time. Reset our - * results. - */ - tm = tcp_get_metrics(sk, dst, false); - if (tm && !tcp_metric_locked(tm, TCP_METRIC_RTT)) - tcp_metric_set(tm, TCP_METRIC_RTT, 0); - goto out_unlock; - } else - tm = tcp_get_metrics(sk, dst, true); - - if (!tm) - goto out_unlock; - - rtt = tcp_metric_get_jiffies(tm, TCP_METRIC_RTT); - m = rtt - tp->srtt; - - /* If newly calculated rtt larger than stored one, store new - * one. Otherwise, use EWMA. Remember, rtt overestimation is - * always better than underestimation. - */ - if (!tcp_metric_locked(tm, TCP_METRIC_RTT)) { - if (m <= 0) - rtt = tp->srtt; - else - rtt -= (m >> 3); - tcp_metric_set_msecs(tm, TCP_METRIC_RTT, rtt); - } - - if (!tcp_metric_locked(tm, TCP_METRIC_RTTVAR)) { - unsigned long var; - - if (m < 0) - m = -m; - - /* Scale deviation to rttvar fixed point */ - m >>= 1; - if (m < tp->mdev) - m = tp->mdev; - - var = tcp_metric_get_jiffies(tm, TCP_METRIC_RTTVAR); - if (m >= var) - var = m; - else - var -= (var - m) >> 2; - - tcp_metric_set_msecs(tm, TCP_METRIC_RTTVAR, var); - } - - if (tcp_in_initial_slowstart(tp)) { - /* Slow start still did not finish. */ - if (!tcp_metric_locked(tm, TCP_METRIC_SSTHRESH)) { - val = tcp_metric_get(tm, TCP_METRIC_SSTHRESH); - if (val && (tp->snd_cwnd >> 1) > val) - tcp_metric_set(tm, TCP_METRIC_SSTHRESH, - tp->snd_cwnd >> 1); - } - if (!tcp_metric_locked(tm, TCP_METRIC_CWND)) { - val = tcp_metric_get(tm, TCP_METRIC_CWND); - if (tp->snd_cwnd > val) - tcp_metric_set(tm, TCP_METRIC_CWND, - tp->snd_cwnd); - } - } else if (tp->snd_cwnd > tp->snd_ssthresh && - icsk->icsk_ca_state == TCP_CA_Open) { - /* Cong. avoidance phase, cwnd is reliable. */ - if (!tcp_metric_locked(tm, TCP_METRIC_SSTHRESH)) - tcp_metric_set(tm, TCP_METRIC_SSTHRESH, - max(tp->snd_cwnd >> 1, tp->snd_ssthresh)); - if (!tcp_metric_locked(tm, TCP_METRIC_CWND)) { - val = tcp_metric_get(tm, TCP_METRIC_CWND); - tcp_metric_set(tm, TCP_METRIC_CWND, (val + tp->snd_cwnd) >> 1); - } - } else { - /* Else slow start did not finish, cwnd is non-sense, - * ssthresh may be also invalid. - */ - if (!tcp_metric_locked(tm, TCP_METRIC_CWND)) { - val = tcp_metric_get(tm, TCP_METRIC_CWND); - tcp_metric_set(tm, TCP_METRIC_CWND, - (val + tp->snd_ssthresh) >> 1); - } - if (!tcp_metric_locked(tm, TCP_METRIC_SSTHRESH)) { - val = tcp_metric_get(tm, TCP_METRIC_SSTHRESH); - if (val && tp->snd_ssthresh > val) - tcp_metric_set(tm, TCP_METRIC_SSTHRESH, - tp->snd_ssthresh); - } - if (!tcp_metric_locked(tm, TCP_METRIC_REORDERING)) { - val = tcp_metric_get(tm, TCP_METRIC_REORDERING); - if (val < tp->reordering && - tp->reordering != sysctl_tcp_reordering) - tcp_metric_set(tm, TCP_METRIC_REORDERING, - tp->reordering); - } - } - tm->tcpm_stamp = jiffies; -out_unlock: - rcu_read_unlock(); -} - -/* Initialize metrics on socket. */ - -void tcp_init_metrics(struct sock *sk) -{ - struct dst_entry *dst = __sk_dst_get(sk); - struct tcp_sock *tp = tcp_sk(sk); - struct tcp_metrics_block *tm; - u32 val; - - if (dst == NULL) - goto reset; - - dst_confirm(dst); - - rcu_read_lock(); - tm = tcp_get_metrics(sk, dst, true); - if (!tm) { - rcu_read_unlock(); - goto reset; - } - - if (tcp_metric_locked(tm, TCP_METRIC_CWND)) - tp->snd_cwnd_clamp = tcp_metric_get(tm, TCP_METRIC_CWND); - - val = tcp_metric_get(tm, TCP_METRIC_SSTHRESH); - if (val) { - tp->snd_ssthresh = val; - if (tp->snd_ssthresh > tp->snd_cwnd_clamp) - tp->snd_ssthresh = tp->snd_cwnd_clamp; - } else { - /* ssthresh may have been reduced unnecessarily during. - * 3WHS. Restore it back to its initial default. - */ - tp->snd_ssthresh = TCP_INFINITE_SSTHRESH; - } - val = tcp_metric_get(tm, TCP_METRIC_REORDERING); - if (val && tp->reordering != val) { - tcp_disable_fack(tp); - tcp_disable_early_retrans(tp); - tp->reordering = val; - } - - val = tcp_metric_get(tm, TCP_METRIC_RTT); - if (val == 0 || tp->srtt == 0) { - rcu_read_unlock(); - goto reset; - } - /* Initial rtt is determined from SYN,SYN-ACK. - * The segment is small and rtt may appear much - * less than real one. Use per-dst memory - * to make it more realistic. - * - * A bit of theory. RTT is time passed after "normal" sized packet - * is sent until it is ACKed. In normal circumstances sending small - * packets force peer to delay ACKs and calculation is correct too. - * The algorithm is adaptive and, provided we follow specs, it - * NEVER underestimate RTT. BUT! If peer tries to make some clever - * tricks sort of "quick acks" for time long enough to decrease RTT - * to low value, and then abruptly stops to do it and starts to delay - * ACKs, wait for troubles. - */ - val = msecs_to_jiffies(val); - if (val > tp->srtt) { - tp->srtt = val; - tp->rtt_seq = tp->snd_nxt; - } - val = tcp_metric_get_jiffies(tm, TCP_METRIC_RTTVAR); - if (val > tp->mdev) { - tp->mdev = val; - tp->mdev_max = tp->rttvar = max(tp->mdev, tcp_rto_min(sk)); - } - rcu_read_unlock(); - - tcp_set_rto(sk); -reset: - if (tp->srtt == 0) { - /* RFC6298: 5.7 We've failed to get a valid RTT sample from - * 3WHS. This is most likely due to retransmission, - * including spurious one. Reset the RTO back to 3secs - * from the more aggressive 1sec to avoid more spurious - * retransmission. - */ - tp->mdev = tp->mdev_max = tp->rttvar = TCP_TIMEOUT_FALLBACK; - inet_csk(sk)->icsk_rto = TCP_TIMEOUT_FALLBACK; - } - /* Cut cwnd down to 1 per RFC5681 if SYN or SYN-ACK has been - * retransmitted. In light of RFC6298 more aggressive 1sec - * initRTO, we only reset cwnd when more than 1 SYN/SYN-ACK - * retransmission has occurred. - */ - if (tp->total_retrans > 1) - tp->snd_cwnd = 1; - else - tp->snd_cwnd = tcp_init_cwnd(tp, dst); - tp->snd_cwnd_stamp = tcp_time_stamp; -} - -bool tcp_peer_is_proven(struct request_sock *req, struct dst_entry *dst, bool paws_check) -{ - struct tcp_metrics_block *tm; - bool ret; - - if (!dst) - return false; - - rcu_read_lock(); - tm = __tcp_get_metrics_req(req, dst); - if (paws_check) { - if (tm && - (u32)get_seconds() - tm->tcpm_ts_stamp < TCP_PAWS_MSL && - (s32)(tm->tcpm_ts - req->ts_recent) > TCP_PAWS_WINDOW) - ret = false; - else - ret = true; - } else { - if (tm && tcp_metric_get(tm, TCP_METRIC_RTT) && tm->tcpm_ts_stamp) - ret = true; - else - ret = false; - } - rcu_read_unlock(); - - return ret; -} -EXPORT_SYMBOL_GPL(tcp_peer_is_proven); - -void tcp_fetch_timewait_stamp(struct sock *sk, struct dst_entry *dst) -{ - struct tcp_metrics_block *tm; - - rcu_read_lock(); - tm = tcp_get_metrics(sk, dst, true); - if (tm) { - struct tcp_sock *tp = tcp_sk(sk); - - if ((u32)get_seconds() - tm->tcpm_ts_stamp <= TCP_PAWS_MSL) { - tp->rx_opt.ts_recent_stamp = tm->tcpm_ts_stamp; - tp->rx_opt.ts_recent = tm->tcpm_ts; - } - } - rcu_read_unlock(); -} -EXPORT_SYMBOL_GPL(tcp_fetch_timewait_stamp); - -/* VJ's idea. Save last timestamp seen from this destination and hold - * it at least for normal timewait interval to use for duplicate - * segment detection in subsequent connections, before they enter - * synchronized state. - */ -bool tcp_remember_stamp(struct sock *sk) -{ - struct dst_entry *dst = __sk_dst_get(sk); - bool ret = false; - - if (dst) { - struct tcp_metrics_block *tm; - - rcu_read_lock(); - tm = tcp_get_metrics(sk, dst, true); - if (tm) { - struct tcp_sock *tp = tcp_sk(sk); - - if ((s32)(tm->tcpm_ts - tp->rx_opt.ts_recent) <= 0 || - ((u32)get_seconds() - tm->tcpm_ts_stamp > TCP_PAWS_MSL && - tm->tcpm_ts_stamp <= (u32)tp->rx_opt.ts_recent_stamp)) { - tm->tcpm_ts_stamp = (u32)tp->rx_opt.ts_recent_stamp; - tm->tcpm_ts = tp->rx_opt.ts_recent; - } - ret = true; - } - rcu_read_unlock(); - } - return ret; -} - -bool tcp_tw_remember_stamp(struct inet_timewait_sock *tw) -{ - struct tcp_metrics_block *tm; - bool ret = false; - - rcu_read_lock(); - tm = __tcp_get_metrics_tw(tw); - if (tw) { - const struct tcp_timewait_sock *tcptw; - struct sock *sk = (struct sock *) tw; - - tcptw = tcp_twsk(sk); - if ((s32)(tm->tcpm_ts - tcptw->tw_ts_recent) <= 0 || - ((u32)get_seconds() - tm->tcpm_ts_stamp > TCP_PAWS_MSL && - tm->tcpm_ts_stamp <= (u32)tcptw->tw_ts_recent_stamp)) { - tm->tcpm_ts_stamp = (u32)tcptw->tw_ts_recent_stamp; - tm->tcpm_ts = tcptw->tw_ts_recent; - } - ret = true; - } - rcu_read_unlock(); - - return ret; -} - -static unsigned long tcpmhash_entries; -static int __init set_tcpmhash_entries(char *str) -{ - ssize_t ret; - - if (!str) - return 0; - - ret = kstrtoul(str, 0, &tcpmhash_entries); - if (ret) - return 0; - - return 1; -} -__setup("tcpmhash_entries=", set_tcpmhash_entries); - -static int __net_init tcp_net_metrics_init(struct net *net) -{ - int slots, size; - - slots = tcpmhash_entries; - if (!slots) { - if (totalram_pages >= 128 * 1024) - slots = 16 * 1024; - else - slots = 8 * 1024; - } - - size = slots * sizeof(struct tcpm_hash_bucket); - - net->ipv4.tcp_metrics_hash = kzalloc(size, GFP_KERNEL); - if (!net->ipv4.tcp_metrics_hash) - return -ENOMEM; - - net->ipv4.tcp_metrics_hash_mask = (slots - 1); - - return 0; -} - -static void __net_exit tcp_net_metrics_exit(struct net *net) -{ - kfree(net->ipv4.tcp_metrics_hash); -} - -static __net_initdata struct pernet_operations tcp_net_metrics_ops = { - .init = tcp_net_metrics_init, - .exit = tcp_net_metrics_exit, -}; - -void __init tcp_metrics_init(void) -{ - register_pernet_subsys(&tcp_net_metrics_ops); -} diff --git a/trunk/net/ipv4/tcp_minisocks.c b/trunk/net/ipv4/tcp_minisocks.c index c66f2ede160e..72b7c63b1a39 100644 --- a/trunk/net/ipv4/tcp_minisocks.c +++ b/trunk/net/ipv4/tcp_minisocks.c @@ -49,6 +49,52 @@ struct inet_timewait_death_row tcp_death_row = { }; EXPORT_SYMBOL_GPL(tcp_death_row); +/* VJ's idea. Save last timestamp seen from this destination + * and hold it at least for normal timewait interval to use for duplicate + * segment detection in subsequent connections, before they enter synchronized + * state. + */ + +static bool tcp_remember_stamp(struct sock *sk) +{ + const struct inet_connection_sock *icsk = inet_csk(sk); + struct tcp_sock *tp = tcp_sk(sk); + struct inet_peer *peer; + + peer = icsk->icsk_af_ops->get_peer(sk); + if (peer) { + if ((s32)(peer->tcp_ts - tp->rx_opt.ts_recent) <= 0 || + ((u32)get_seconds() - peer->tcp_ts_stamp > TCP_PAWS_MSL && + peer->tcp_ts_stamp <= (u32)tp->rx_opt.ts_recent_stamp)) { + peer->tcp_ts_stamp = (u32)tp->rx_opt.ts_recent_stamp; + peer->tcp_ts = tp->rx_opt.ts_recent; + } + return true; + } + + return false; +} + +static bool tcp_tw_remember_stamp(struct inet_timewait_sock *tw) +{ + const struct tcp_timewait_sock *tcptw; + struct sock *sk = (struct sock *) tw; + struct inet_peer *peer; + + tcptw = tcp_twsk(sk); + peer = tcptw->tw_peer; + if (peer) { + if ((s32)(peer->tcp_ts - tcptw->tw_ts_recent) <= 0 || + ((u32)get_seconds() - peer->tcp_ts_stamp > TCP_PAWS_MSL && + peer->tcp_ts_stamp <= (u32)tcptw->tw_ts_recent_stamp)) { + peer->tcp_ts_stamp = (u32)tcptw->tw_ts_recent_stamp; + peer->tcp_ts = tcptw->tw_ts_recent; + } + return true; + } + return false; +} + static bool tcp_in_window(u32 seq, u32 end_seq, u32 s_win, u32 e_win) { if (seq == s_win) @@ -267,9 +313,12 @@ void tcp_time_wait(struct sock *sk, int state, int timeo) const struct inet_connection_sock *icsk = inet_csk(sk); const struct tcp_sock *tp = tcp_sk(sk); bool recycle_ok = false; + bool recycle_on = false; - if (tcp_death_row.sysctl_tw_recycle && tp->rx_opt.ts_recent_stamp) + if (tcp_death_row.sysctl_tw_recycle && tp->rx_opt.ts_recent_stamp) { recycle_ok = tcp_remember_stamp(sk); + recycle_on = true; + } if (tcp_death_row.tw_count < tcp_death_row.sysctl_max_tw_buckets) tw = inet_twsk_alloc(sk, state); @@ -278,6 +327,7 @@ void tcp_time_wait(struct sock *sk, int state, int timeo) struct tcp_timewait_sock *tcptw = tcp_twsk((struct sock *)tw); const int rto = (icsk->icsk_rto << 2) - (icsk->icsk_rto >> 1); struct inet_sock *inet = inet_sk(sk); + struct inet_peer *peer = NULL; tw->tw_transparent = inet->transparent; tw->tw_rcv_wscale = tp->rx_opt.rcv_wscale; @@ -301,6 +351,12 @@ void tcp_time_wait(struct sock *sk, int state, int timeo) } #endif + if (recycle_on) + peer = icsk->icsk_af_ops->get_peer(sk); + tcptw->tw_peer = peer; + if (peer) + atomic_inc(&peer->refcnt); + #ifdef CONFIG_TCP_MD5SIG /* * The timewait bucket does not have the key DB from the @@ -352,9 +408,11 @@ void tcp_time_wait(struct sock *sk, int state, int timeo) void tcp_twsk_destructor(struct sock *sk) { -#ifdef CONFIG_TCP_MD5SIG struct tcp_timewait_sock *twsk = tcp_twsk(sk); + if (twsk->tw_peer) + inet_putpeer(twsk->tw_peer); +#ifdef CONFIG_TCP_MD5SIG if (twsk->tw_md5_key) { tcp_free_md5sig_pool(); kfree_rcu(twsk->tw_md5_key, rcu); @@ -424,7 +482,6 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct request_sock *req, treq->snt_isn + 1 + tcp_s_data_size(oldtp); tcp_prequeue_init(newtp); - INIT_LIST_HEAD(&newtp->tsq_node); tcp_init_wl(newtp, treq->rcv_isn); diff --git a/trunk/net/ipv4/tcp_output.c b/trunk/net/ipv4/tcp_output.c index 15a7c7bc3e58..c465d3e51e28 100644 --- a/trunk/net/ipv4/tcp_output.c +++ b/trunk/net/ipv4/tcp_output.c @@ -50,9 +50,6 @@ int sysctl_tcp_retrans_collapse __read_mostly = 1; */ int sysctl_tcp_workaround_signed_windows __read_mostly = 0; -/* Default TSQ limit of two TSO segments */ -int sysctl_tcp_limit_output_bytes __read_mostly = 131072; - /* This limits the percentage of the congestion window which we * will allow a single TSO frame to consume. Building TSO frames * which are too large can cause TCP streams to be bursty. @@ -68,8 +65,6 @@ int sysctl_tcp_slow_start_after_idle __read_mostly = 1; int sysctl_tcp_cookie_size __read_mostly = 0; /* TCP_COOKIE_MAX */ EXPORT_SYMBOL_GPL(sysctl_tcp_cookie_size); -static bool tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle, - int push_one, gfp_t gfp); /* Account for new data that has been sent to the network. */ static void tcp_event_new_data_sent(struct sock *sk, const struct sk_buff *skb) @@ -788,140 +783,6 @@ static unsigned int tcp_established_options(struct sock *sk, struct sk_buff *skb return size; } - -/* TCP SMALL QUEUES (TSQ) - * - * TSQ goal is to keep small amount of skbs per tcp flow in tx queues (qdisc+dev) - * to reduce RTT and bufferbloat. - * We do this using a special skb destructor (tcp_wfree). - * - * Its important tcp_wfree() can be replaced by sock_wfree() in the event skb - * needs to be reallocated in a driver. - * The invariant being skb->truesize substracted from sk->sk_wmem_alloc - * - * Since transmit from skb destructor is forbidden, we use a tasklet - * to process all sockets that eventually need to send more skbs. - * We use one tasklet per cpu, with its own queue of sockets. - */ -struct tsq_tasklet { - struct tasklet_struct tasklet; - struct list_head head; /* queue of tcp sockets */ -}; -static DEFINE_PER_CPU(struct tsq_tasklet, tsq_tasklet); - -/* - * One tasklest per cpu tries to send more skbs. - * We run in tasklet context but need to disable irqs when - * transfering tsq->head because tcp_wfree() might - * interrupt us (non NAPI drivers) - */ -static void tcp_tasklet_func(unsigned long data) -{ - struct tsq_tasklet *tsq = (struct tsq_tasklet *)data; - LIST_HEAD(list); - unsigned long flags; - struct list_head *q, *n; - struct tcp_sock *tp; - struct sock *sk; - - local_irq_save(flags); - list_splice_init(&tsq->head, &list); - local_irq_restore(flags); - - list_for_each_safe(q, n, &list) { - tp = list_entry(q, struct tcp_sock, tsq_node); - list_del(&tp->tsq_node); - - sk = (struct sock *)tp; - bh_lock_sock(sk); - - if (!sock_owned_by_user(sk)) { - if ((1 << sk->sk_state) & - (TCPF_ESTABLISHED | TCPF_FIN_WAIT1 | - TCPF_CLOSING | TCPF_CLOSE_WAIT | TCPF_LAST_ACK)) - tcp_write_xmit(sk, - tcp_current_mss(sk), - 0, 0, - GFP_ATOMIC); - } else { - /* defer the work to tcp_release_cb() */ - set_bit(TSQ_OWNED, &tp->tsq_flags); - } - bh_unlock_sock(sk); - - clear_bit(TSQ_QUEUED, &tp->tsq_flags); - sk_free(sk); - } -} - -/** - * tcp_release_cb - tcp release_sock() callback - * @sk: socket - * - * called from release_sock() to perform protocol dependent - * actions before socket release. - */ -void tcp_release_cb(struct sock *sk) -{ - struct tcp_sock *tp = tcp_sk(sk); - - if (test_and_clear_bit(TSQ_OWNED, &tp->tsq_flags)) { - if ((1 << sk->sk_state) & - (TCPF_ESTABLISHED | TCPF_FIN_WAIT1 | - TCPF_CLOSING | TCPF_CLOSE_WAIT | TCPF_LAST_ACK)) - tcp_write_xmit(sk, - tcp_current_mss(sk), - 0, 0, - GFP_ATOMIC); - } -} -EXPORT_SYMBOL(tcp_release_cb); - -void __init tcp_tasklet_init(void) -{ - int i; - - for_each_possible_cpu(i) { - struct tsq_tasklet *tsq = &per_cpu(tsq_tasklet, i); - - INIT_LIST_HEAD(&tsq->head); - tasklet_init(&tsq->tasklet, - tcp_tasklet_func, - (unsigned long)tsq); - } -} - -/* - * Write buffer destructor automatically called from kfree_skb. - * We cant xmit new skbs from this context, as we might already - * hold qdisc lock. - */ -void tcp_wfree(struct sk_buff *skb) -{ - struct sock *sk = skb->sk; - struct tcp_sock *tp = tcp_sk(sk); - - if (test_and_clear_bit(TSQ_THROTTLED, &tp->tsq_flags) && - !test_and_set_bit(TSQ_QUEUED, &tp->tsq_flags)) { - unsigned long flags; - struct tsq_tasklet *tsq; - - /* Keep a ref on socket. - * This last ref will be released in tcp_tasklet_func() - */ - atomic_sub(skb->truesize - 1, &sk->sk_wmem_alloc); - - /* queue this socket to tasklet queue */ - local_irq_save(flags); - tsq = &__get_cpu_var(tsq_tasklet); - list_add(&tp->tsq_node, &tsq->head); - tasklet_schedule(&tsq->tasklet); - local_irq_restore(flags); - } else { - sock_wfree(skb); - } -} - /* This routine actually transmits TCP packets queued in by * tcp_do_sendmsg(). This is used by both the initial * transmission and possible later retransmissions. @@ -983,12 +844,7 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it, skb_push(skb, tcp_header_size); skb_reset_transport_header(skb); - - skb_orphan(skb); - skb->sk = sk; - skb->destructor = (sysctl_tcp_limit_output_bytes > 0) ? - tcp_wfree : sock_wfree; - atomic_add(skb->truesize, &sk->sk_wmem_alloc); + skb_set_owner_w(skb, sk); /* Build TCP header and checksum it. */ th = tcp_hdr(skb); @@ -1924,7 +1780,6 @@ static bool tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle, while ((skb = tcp_send_head(sk))) { unsigned int limit; - tso_segs = tcp_init_tso_segs(sk, skb, mss_now); BUG_ON(!tso_segs); @@ -1945,13 +1800,6 @@ static bool tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle, break; } - /* TSQ : sk_wmem_alloc accounts skb truesize, - * including skb overhead. But thats OK. - */ - if (atomic_read(&sk->sk_wmem_alloc) >= sysctl_tcp_limit_output_bytes) { - set_bit(TSQ_THROTTLED, &tp->tsq_flags); - break; - } limit = mss_now; if (tso_segs > 1 && !tcp_urg_mode(tp)) limit = tcp_mss_split_point(sk, skb, mss_now, diff --git a/trunk/net/ipv4/udp.c b/trunk/net/ipv4/udp.c index b4c3582a991f..ee37d47d472e 100644 --- a/trunk/net/ipv4/udp.c +++ b/trunk/net/ipv4/udp.c @@ -630,9 +630,6 @@ void __udp4_lib_err(struct sk_buff *skb, u32 info, struct udp_table *udptable) err = icmp_err_convert[code].errno; } break; - case ICMP_REDIRECT: - ipv4_sk_redirect(skb, sk); - break; } /* diff --git a/trunk/net/ipv4/udp_diag.c b/trunk/net/ipv4/udp_diag.c index 16d0960062be..a7f86a3cd502 100644 --- a/trunk/net/ipv4/udp_diag.c +++ b/trunk/net/ipv4/udp_diag.c @@ -34,16 +34,15 @@ static int udp_dump_one(struct udp_table *tbl, struct sk_buff *in_skb, int err = -EINVAL; struct sock *sk; struct sk_buff *rep; - struct net *net = sock_net(in_skb->sk); if (req->sdiag_family == AF_INET) - sk = __udp4_lib_lookup(net, + sk = __udp4_lib_lookup(&init_net, req->id.idiag_src[0], req->id.idiag_sport, req->id.idiag_dst[0], req->id.idiag_dport, req->id.idiag_if, tbl); #if IS_ENABLED(CONFIG_IPV6) else if (req->sdiag_family == AF_INET6) - sk = __udp6_lib_lookup(net, + sk = __udp6_lib_lookup(&init_net, (struct in6_addr *)req->id.idiag_src, req->id.idiag_sport, (struct in6_addr *)req->id.idiag_dst, @@ -76,7 +75,7 @@ static int udp_dump_one(struct udp_table *tbl, struct sk_buff *in_skb, kfree_skb(rep); goto out; } - err = netlink_unicast(net->diag_nlsk, rep, NETLINK_CB(in_skb).pid, + err = netlink_unicast(sock_diag_nlsk, rep, NETLINK_CB(in_skb).pid, MSG_DONTWAIT); if (err > 0) err = 0; @@ -91,7 +90,6 @@ static void udp_dump(struct udp_table *table, struct sk_buff *skb, struct netlin struct inet_diag_req_v2 *r, struct nlattr *bc) { int num, s_num, slot, s_slot; - struct net *net = sock_net(skb->sk); s_slot = cb->args[0]; num = s_num = cb->args[1]; @@ -108,8 +106,6 @@ static void udp_dump(struct udp_table *table, struct sk_buff *skb, struct netlin sk_nulls_for_each(sk, node, &hslot->head) { struct inet_sock *inet = inet_sk(sk); - if (!net_eq(sock_net(sk), net)) - continue; if (num < s_num) goto next; if (!(r->idiag_states & (1 << sk->sk_state))) diff --git a/trunk/net/ipv4/xfrm4_policy.c b/trunk/net/ipv4/xfrm4_policy.c index fcf7678bc009..9815ea0bca7f 100644 --- a/trunk/net/ipv4/xfrm4_policy.c +++ b/trunk/net/ipv4/xfrm4_policy.c @@ -90,6 +90,8 @@ static int xfrm4_fill_dst(struct xfrm_dst *xdst, struct net_device *dev, xdst->u.dst.dev = dev; dev_hold(dev); + rt_transfer_peer(&xdst->u.rt, rt); + /* Sheit... I remember I did this right. Apparently, * it was magically lost, so this code needs audit */ xdst->u.rt.rt_flags = rt->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST | @@ -98,7 +100,6 @@ static int xfrm4_fill_dst(struct xfrm_dst *xdst, struct net_device *dev, xdst->u.rt.rt_src = rt->rt_src; xdst->u.rt.rt_dst = rt->rt_dst; xdst->u.rt.rt_gateway = rt->rt_gateway; - xdst->u.rt.rt_pmtu = rt->rt_pmtu; return 0; } @@ -194,22 +195,12 @@ static inline int xfrm4_garbage_collect(struct dst_ops *ops) return (dst_entries_get_slow(ops) > ops->gc_thresh * 2); } -static void xfrm4_update_pmtu(struct dst_entry *dst, struct sock *sk, - struct sk_buff *skb, u32 mtu) +static void xfrm4_update_pmtu(struct dst_entry *dst, u32 mtu) { struct xfrm_dst *xdst = (struct xfrm_dst *)dst; struct dst_entry *path = xdst->route; - path->ops->update_pmtu(path, sk, skb, mtu); -} - -static void xfrm4_redirect(struct dst_entry *dst, struct sock *sk, - struct sk_buff *skb) -{ - struct xfrm_dst *xdst = (struct xfrm_dst *)dst; - struct dst_entry *path = xdst->route; - - path->ops->redirect(path, sk, skb); + path->ops->update_pmtu(path, mtu); } static void xfrm4_dst_destroy(struct dst_entry *dst) @@ -218,6 +209,11 @@ static void xfrm4_dst_destroy(struct dst_entry *dst) dst_destroy_metrics_generic(dst); + if (rt_has_peer(&xdst->u.rt)) { + struct inet_peer *peer = rt_peer_ptr(&xdst->u.rt); + inet_putpeer(peer); + } + xfrm_dst_destroy(xdst); } @@ -235,7 +231,6 @@ static struct dst_ops xfrm4_dst_ops = { .protocol = cpu_to_be16(ETH_P_IP), .gc = xfrm4_garbage_collect, .update_pmtu = xfrm4_update_pmtu, - .redirect = xfrm4_redirect, .cow_metrics = dst_cow_metrics_generic, .destroy = xfrm4_dst_destroy, .ifdown = xfrm4_dst_ifdown, diff --git a/trunk/net/ipv6/ah6.c b/trunk/net/ipv6/ah6.c index 7e6139508ee7..49d4d26bda88 100644 --- a/trunk/net/ipv6/ah6.c +++ b/trunk/net/ipv6/ah6.c @@ -613,18 +613,16 @@ static void ah6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, struct xfrm_state *x; if (type != ICMPV6_DEST_UNREACH && - type != ICMPV6_PKT_TOOBIG && - type != NDISC_REDIRECT) + type != ICMPV6_PKT_TOOBIG) return; x = xfrm_state_lookup(net, skb->mark, (xfrm_address_t *)&iph->daddr, ah->spi, IPPROTO_AH, AF_INET6); if (!x) return; - if (type == NDISC_REDIRECT) - ip6_redirect(skb, net, 0, 0); - else - ip6_update_pmtu(skb, net, info, 0, 0); + NETDEBUG(KERN_DEBUG "pmtu discovery on SA AH/%08x/%pI6\n", + ntohl(ah->spi), &iph->daddr); + ip6_update_pmtu(skb, net, info, 0, 0); xfrm_state_put(x); } diff --git a/trunk/net/ipv6/esp6.c b/trunk/net/ipv6/esp6.c index 6dc7fd353ef5..89a615ba84f8 100644 --- a/trunk/net/ipv6/esp6.c +++ b/trunk/net/ipv6/esp6.c @@ -434,19 +434,16 @@ static void esp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, struct xfrm_state *x; if (type != ICMPV6_DEST_UNREACH && - type != ICMPV6_PKT_TOOBIG && - type != NDISC_REDIRECT) + type != ICMPV6_PKT_TOOBIG) return; x = xfrm_state_lookup(net, skb->mark, (const xfrm_address_t *)&iph->daddr, esph->spi, IPPROTO_ESP, AF_INET6); if (!x) return; - - if (type == NDISC_REDIRECT) - ip6_redirect(skb, net, 0, 0); - else - ip6_update_pmtu(skb, net, info, 0, 0); + pr_debug("pmtu discovery on SA ESP/%08x/%pI6\n", + ntohl(esph->spi), &iph->daddr); + ip6_update_pmtu(skb, net, info, 0, 0); xfrm_state_put(x); } diff --git a/trunk/net/ipv6/icmp.c b/trunk/net/ipv6/icmp.c index 24d69dbca4d6..c7da1422cbde 100644 --- a/trunk/net/ipv6/icmp.c +++ b/trunk/net/ipv6/icmp.c @@ -194,10 +194,8 @@ static inline bool icmpv6_xrlim_allow(struct sock *sk, u8 type, if (rt->rt6i_dst.plen < 128) tmo >>= ((128 - rt->rt6i_dst.plen)>>5); - peer = inet_getpeer_v6(net->ipv6.peers, &rt->rt6i_dst.addr, 1); + peer = rt6_get_peer_create(rt); res = inet_peer_xrlim_allow(peer, tmo); - if (peer) - inet_putpeer(peer); } dst_release(dst); return res; @@ -598,7 +596,7 @@ static void icmpv6_echo_reply(struct sk_buff *skb) icmpv6_xmit_unlock(sk); } -void icmpv6_notify(struct sk_buff *skb, u8 type, u8 code, __be32 info) +static void icmpv6_notify(struct sk_buff *skb, u8 type, u8 code, __be32 info) { const struct inet6_protocol *ipprot; int inner_offset; diff --git a/trunk/net/ipv6/inet6_connection_sock.c b/trunk/net/ipv6/inet6_connection_sock.c index 0251a6005be8..bceb14450a1d 100644 --- a/trunk/net/ipv6/inet6_connection_sock.c +++ b/trunk/net/ipv6/inet6_connection_sock.c @@ -171,8 +171,7 @@ EXPORT_SYMBOL_GPL(inet6_csk_addr2sockaddr); static inline void __inet6_csk_dst_store(struct sock *sk, struct dst_entry *dst, - const struct in6_addr *daddr, - const struct in6_addr *saddr) + struct in6_addr *daddr, struct in6_addr *saddr) { __ip6_dst_store(sk, dst, daddr, saddr); @@ -204,52 +203,43 @@ struct dst_entry *__inet6_csk_dst_check(struct sock *sk, u32 cookie) return dst; } -static struct dst_entry *inet6_csk_route_socket(struct sock *sk, - struct flowi6 *fl6) +int inet6_csk_xmit(struct sk_buff *skb, struct flowi *fl_unused) { + struct sock *sk = skb->sk; struct inet_sock *inet = inet_sk(sk); struct ipv6_pinfo *np = inet6_sk(sk); - struct in6_addr *final_p, final; + struct flowi6 fl6; struct dst_entry *dst; + struct in6_addr *final_p, final; + int res; - memset(fl6, 0, sizeof(*fl6)); - fl6->flowi6_proto = sk->sk_protocol; - fl6->daddr = np->daddr; - fl6->saddr = np->saddr; - fl6->flowlabel = np->flow_label; - IP6_ECN_flow_xmit(sk, fl6->flowlabel); - fl6->flowi6_oif = sk->sk_bound_dev_if; - fl6->flowi6_mark = sk->sk_mark; - fl6->fl6_sport = inet->inet_sport; - fl6->fl6_dport = inet->inet_dport; - security_sk_classify_flow(sk, flowi6_to_flowi(fl6)); + memset(&fl6, 0, sizeof(fl6)); + fl6.flowi6_proto = sk->sk_protocol; + fl6.daddr = np->daddr; + fl6.saddr = np->saddr; + fl6.flowlabel = np->flow_label; + IP6_ECN_flow_xmit(sk, fl6.flowlabel); + fl6.flowi6_oif = sk->sk_bound_dev_if; + fl6.flowi6_mark = sk->sk_mark; + fl6.fl6_sport = inet->inet_sport; + fl6.fl6_dport = inet->inet_dport; + security_sk_classify_flow(sk, flowi6_to_flowi(&fl6)); - final_p = fl6_update_dst(fl6, np->opt, &final); + final_p = fl6_update_dst(&fl6, np->opt, &final); dst = __inet6_csk_dst_check(sk, np->dst_cookie); - if (!dst) { - dst = ip6_dst_lookup_flow(sk, fl6, final_p, false); - if (!IS_ERR(dst)) - __inet6_csk_dst_store(sk, dst, NULL, NULL); - } - return dst; -} + if (dst == NULL) { + dst = ip6_dst_lookup_flow(sk, &fl6, final_p, false); -int inet6_csk_xmit(struct sk_buff *skb, struct flowi *fl_unused) -{ - struct sock *sk = skb->sk; - struct ipv6_pinfo *np = inet6_sk(sk); - struct flowi6 fl6; - struct dst_entry *dst; - int res; + if (IS_ERR(dst)) { + sk->sk_err_soft = -PTR_ERR(dst); + sk->sk_route_caps = 0; + kfree_skb(skb); + return PTR_ERR(dst); + } - dst = inet6_csk_route_socket(sk, &fl6); - if (IS_ERR(dst)) { - sk->sk_err_soft = -PTR_ERR(dst); - sk->sk_route_caps = 0; - kfree_skb(skb); - return PTR_ERR(dst); + __inet6_csk_dst_store(sk, dst, NULL, NULL); } rcu_read_lock(); @@ -263,16 +253,3 @@ int inet6_csk_xmit(struct sk_buff *skb, struct flowi *fl_unused) return res; } EXPORT_SYMBOL_GPL(inet6_csk_xmit); - -struct dst_entry *inet6_csk_update_pmtu(struct sock *sk, u32 mtu) -{ - struct flowi6 fl6; - struct dst_entry *dst = inet6_csk_route_socket(sk, &fl6); - - if (IS_ERR(dst)) - return NULL; - dst->ops->update_pmtu(dst, sk, NULL, mtu); - - return inet6_csk_route_socket(sk, &fl6); -} -EXPORT_SYMBOL_GPL(inet6_csk_update_pmtu); diff --git a/trunk/net/ipv6/ip6_output.c b/trunk/net/ipv6/ip6_output.c index 5b2d63ed793e..c6af5963a202 100644 --- a/trunk/net/ipv6/ip6_output.c +++ b/trunk/net/ipv6/ip6_output.c @@ -466,15 +466,13 @@ int ip6_forward(struct sk_buff *skb) else target = &hdr->daddr; - peer = inet_getpeer_v6(net->ipv6.peers, &rt->rt6i_dst.addr, 1); + peer = rt6_get_peer_create(rt); /* Limit redirects both by destination (here) and by source (inside ndisc_send_redirect) */ if (inet_peer_xrlim_allow(peer, 1*HZ)) ndisc_send_redirect(skb, target); - if (peer) - inet_putpeer(peer); } else { int addrtype = ipv6_addr_type(&hdr->saddr); @@ -594,14 +592,10 @@ void ipv6_select_ident(struct frag_hdr *fhdr, struct rt6_info *rt) int old, new; if (rt && !(rt->dst.flags & DST_NOPEER)) { - struct inet_peer *peer; - struct net *net; + struct inet_peer *peer = rt6_get_peer_create(rt); - net = dev_net(rt->dst.dev); - peer = inet_getpeer_v6(net->ipv6.peers, &rt->rt6i_dst.addr, 1); if (peer) { fhdr->identification = htonl(inet_getid(peer, 0)); - inet_putpeer(peer); return; } } diff --git a/trunk/net/ipv6/ip6_tunnel.c b/trunk/net/ipv6/ip6_tunnel.c index db3284667968..04a3cba2c123 100644 --- a/trunk/net/ipv6/ip6_tunnel.c +++ b/trunk/net/ipv6/ip6_tunnel.c @@ -252,7 +252,7 @@ static void ip6_dev_free(struct net_device *dev) } /** - * ip6_tnl_create - create a new tunnel + * ip6_tnl_create() - create a new tunnel * @p: tunnel parameters * @pt: pointer to new tunnel * @@ -550,9 +550,6 @@ ip4ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, rel_type = ICMP_DEST_UNREACH; rel_code = ICMP_FRAG_NEEDED; break; - case NDISC_REDIRECT: - rel_type = ICMP_REDIRECT; - rel_code = ICMP_REDIR_HOST; default: return 0; } @@ -609,10 +606,8 @@ ip4ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, if (rel_info > dst_mtu(skb_dst(skb2))) goto out; - skb_dst(skb2)->ops->update_pmtu(skb_dst(skb2), NULL, skb2, rel_info); + skb_dst(skb2)->ops->update_pmtu(skb_dst(skb2), rel_info); } - if (rel_type == ICMP_REDIRECT) - skb_dst(skb2)->ops->redirect(skb_dst(skb2), NULL, skb2); icmp_send(skb2, rel_type, rel_code, htonl(rel_info)); @@ -952,7 +947,7 @@ static int ip6_tnl_xmit2(struct sk_buff *skb, if (mtu < IPV6_MIN_MTU) mtu = IPV6_MIN_MTU; if (skb_dst(skb)) - skb_dst(skb)->ops->update_pmtu(skb_dst(skb), NULL, skb, mtu); + skb_dst(skb)->ops->update_pmtu(skb_dst(skb), mtu); if (skb->len > mtu) { *pmtu = mtu; err = -EMSGSIZE; diff --git a/trunk/net/ipv6/ipcomp6.c b/trunk/net/ipv6/ipcomp6.c index 7af5aee75d98..92832385a8ef 100644 --- a/trunk/net/ipv6/ipcomp6.c +++ b/trunk/net/ipv6/ipcomp6.c @@ -64,9 +64,7 @@ static void ipcomp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, (struct ip_comp_hdr *)(skb->data + offset); struct xfrm_state *x; - if (type != ICMPV6_DEST_UNREACH && - type != ICMPV6_PKT_TOOBIG && - type != NDISC_REDIRECT) + if (type != ICMPV6_DEST_UNREACH && type != ICMPV6_PKT_TOOBIG) return; spi = htonl(ntohs(ipcomph->cpi)); @@ -75,10 +73,9 @@ static void ipcomp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, if (!x) return; - if (type == NDISC_REDIRECT) - ip6_redirect(skb, net, 0, 0); - else - ip6_update_pmtu(skb, net, info, 0, 0); + pr_debug("pmtu discovery on SA IPCOMP/%08x/%pI6\n", + spi, &iph->daddr); + ip6_update_pmtu(skb, net, info, 0, 0); xfrm_state_put(x); } diff --git a/trunk/net/ipv6/mcast.c b/trunk/net/ipv6/mcast.c index 92f8e48e4ba4..6d0f5dc8e3a6 100644 --- a/trunk/net/ipv6/mcast.c +++ b/trunk/net/ipv6/mcast.c @@ -211,9 +211,6 @@ int ipv6_sock_mc_drop(struct sock *sk, int ifindex, const struct in6_addr *addr) struct ipv6_mc_socklist __rcu **lnk; struct net *net = sock_net(sk); - if (!ipv6_addr_is_multicast(addr)) - return -EINVAL; - spin_lock(&ipv6_sk_mc_lock); for (lnk = &np->ipv6_mc_list; (mc_lst = rcu_dereference_protected(*lnk, diff --git a/trunk/net/ipv6/ndisc.c b/trunk/net/ipv6/ndisc.c index ff36194a71aa..69a6330dea91 100644 --- a/trunk/net/ipv6/ndisc.c +++ b/trunk/net/ipv6/ndisc.c @@ -143,6 +143,40 @@ struct neigh_table nd_tbl = { .gc_thresh3 = 1024, }; +/* ND options */ +struct ndisc_options { + struct nd_opt_hdr *nd_opt_array[__ND_OPT_ARRAY_MAX]; +#ifdef CONFIG_IPV6_ROUTE_INFO + struct nd_opt_hdr *nd_opts_ri; + struct nd_opt_hdr *nd_opts_ri_end; +#endif + struct nd_opt_hdr *nd_useropts; + struct nd_opt_hdr *nd_useropts_end; +}; + +#define nd_opts_src_lladdr nd_opt_array[ND_OPT_SOURCE_LL_ADDR] +#define nd_opts_tgt_lladdr nd_opt_array[ND_OPT_TARGET_LL_ADDR] +#define nd_opts_pi nd_opt_array[ND_OPT_PREFIX_INFO] +#define nd_opts_pi_end nd_opt_array[__ND_OPT_PREFIX_INFO_END] +#define nd_opts_rh nd_opt_array[ND_OPT_REDIRECT_HDR] +#define nd_opts_mtu nd_opt_array[ND_OPT_MTU] + +#define NDISC_OPT_SPACE(len) (((len)+2+7)&~7) + +/* + * Return the padding between the option length and the start of the + * link addr. Currently only IP-over-InfiniBand needs this, although + * if RFC 3831 IPv6-over-Fibre Channel is ever implemented it may + * also need a pad of 2. + */ +static int ndisc_addr_option_pad(unsigned short type) +{ + switch (type) { + case ARPHRD_INFINIBAND: return 2; + default: return 0; + } +} + static inline int ndisc_opt_addr_space(struct net_device *dev) { return NDISC_OPT_SPACE(dev->addr_len + ndisc_addr_option_pad(dev->type)); @@ -199,8 +233,8 @@ static struct nd_opt_hdr *ndisc_next_useropt(struct nd_opt_hdr *cur, return cur <= end && ndisc_is_useropt(cur) ? cur : NULL; } -struct ndisc_options *ndisc_parse_options(u8 *opt, int opt_len, - struct ndisc_options *ndopts) +static struct ndisc_options *ndisc_parse_options(u8 *opt, int opt_len, + struct ndisc_options *ndopts) { struct nd_opt_hdr *nd_opt = (struct nd_opt_hdr *)opt; @@ -263,6 +297,17 @@ struct ndisc_options *ndisc_parse_options(u8 *opt, int opt_len, return ndopts; } +static inline u8 *ndisc_opt_addr_data(struct nd_opt_hdr *p, + struct net_device *dev) +{ + u8 *lladdr = (u8 *)(p + 1); + int lladdrlen = p->nd_opt_len << 3; + int prepad = ndisc_addr_option_pad(dev->type); + if (lladdrlen != NDISC_OPT_SPACE(dev->addr_len + prepad)) + return NULL; + return lladdr + prepad; +} + int ndisc_mc_map(const struct in6_addr *addr, char *buf, struct net_device *dev, int dir) { switch (dev->type) { @@ -1334,6 +1379,16 @@ static void ndisc_router_discovery(struct sk_buff *skb) static void ndisc_redirect_rcv(struct sk_buff *skb) { + struct inet6_dev *in6_dev; + struct icmp6hdr *icmph; + const struct in6_addr *dest; + const struct in6_addr *target; /* new first hop to destination */ + struct neighbour *neigh; + int on_link = 0; + struct ndisc_options ndopts; + int optlen; + u8 *lladdr = NULL; + #ifdef CONFIG_IPV6_NDISC_NODETYPE switch (skb->ndisc_nodetype) { case NDISC_NODETYPE_HOST: @@ -1350,7 +1405,65 @@ static void ndisc_redirect_rcv(struct sk_buff *skb) return; } - icmpv6_notify(skb, NDISC_REDIRECT, 0, 0); + optlen = skb->tail - skb->transport_header; + optlen -= sizeof(struct icmp6hdr) + 2 * sizeof(struct in6_addr); + + if (optlen < 0) { + ND_PRINTK(2, warn, "Redirect: packet too short\n"); + return; + } + + icmph = icmp6_hdr(skb); + target = (const struct in6_addr *) (icmph + 1); + dest = target + 1; + + if (ipv6_addr_is_multicast(dest)) { + ND_PRINTK(2, warn, + "Redirect: destination address is multicast\n"); + return; + } + + if (ipv6_addr_equal(dest, target)) { + on_link = 1; + } else if (ipv6_addr_type(target) != + (IPV6_ADDR_UNICAST|IPV6_ADDR_LINKLOCAL)) { + ND_PRINTK(2, warn, + "Redirect: target address is not link-local unicast\n"); + return; + } + + in6_dev = __in6_dev_get(skb->dev); + if (!in6_dev) + return; + if (in6_dev->cnf.forwarding || !in6_dev->cnf.accept_redirects) + return; + + /* RFC2461 8.1: + * The IP source address of the Redirect MUST be the same as the current + * first-hop router for the specified ICMP Destination Address. + */ + + if (!ndisc_parse_options((u8*)(dest + 1), optlen, &ndopts)) { + ND_PRINTK(2, warn, "Redirect: invalid ND options\n"); + return; + } + if (ndopts.nd_opts_tgt_lladdr) { + lladdr = ndisc_opt_addr_data(ndopts.nd_opts_tgt_lladdr, + skb->dev); + if (!lladdr) { + ND_PRINTK(2, warn, + "Redirect: invalid link-layer address length\n"); + return; + } + } + + neigh = __neigh_lookup(&nd_tbl, target, skb->dev, 1); + if (neigh) { + rt6_redirect(dest, &ipv6_hdr(skb)->daddr, + &ipv6_hdr(skb)->saddr, neigh, lladdr, + on_link); + neigh_release(neigh); + } } void ndisc_send_redirect(struct sk_buff *skb, const struct in6_addr *target) @@ -1373,7 +1486,6 @@ void ndisc_send_redirect(struct sk_buff *skb, const struct in6_addr *target) int rd_len; int err; u8 ha_buf[MAX_ADDR_LEN], *ha = NULL; - bool ret; if (ipv6_get_lladdr(dev, &saddr_buf, IFA_F_TENTATIVE)) { ND_PRINTK(2, warn, "Redirect: no link-local address on %s\n", @@ -1407,11 +1519,8 @@ void ndisc_send_redirect(struct sk_buff *skb, const struct in6_addr *target) "Redirect: destination is not a neighbour\n"); goto release; } - peer = inet_getpeer_v6(net->ipv6.peers, &rt->rt6i_dst.addr, 1); - ret = inet_peer_xrlim_allow(peer, 1*HZ); - if (peer) - inet_putpeer(peer); - if (!ret) + peer = rt6_get_peer_create(rt); + if (!inet_peer_xrlim_allow(peer, 1*HZ)) goto release; if (dev->addr_len) { diff --git a/trunk/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c b/trunk/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c index 2d54b2061d68..63ed0121836c 100644 --- a/trunk/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c +++ b/trunk/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c @@ -333,36 +333,22 @@ static struct ctl_table icmpv6_sysctl_table[] = { }; #endif /* CONFIG_SYSCTL */ -static int icmpv6_kmemdup_sysctl_table(struct nf_proto_net *pn, - struct nf_icmp_net *in) +static int icmpv6_init_net(struct net *net) { + struct nf_icmp_net *in = icmpv6_pernet(net); + struct nf_proto_net *pn = (struct nf_proto_net *)in; + in->timeout = nf_ct_icmpv6_timeout; #ifdef CONFIG_SYSCTL pn->ctl_table = kmemdup(icmpv6_sysctl_table, sizeof(icmpv6_sysctl_table), GFP_KERNEL); if (!pn->ctl_table) return -ENOMEM; - pn->ctl_table[0].data = &in->timeout; #endif return 0; } -static int icmpv6_init_net(struct net *net, u_int16_t proto) -{ - struct nf_icmp_net *in = icmpv6_pernet(net); - struct nf_proto_net *pn = &in->pn; - - in->timeout = nf_ct_icmpv6_timeout; - - return icmpv6_kmemdup_sysctl_table(pn, in); -} - -static struct nf_proto_net *icmpv6_get_net_proto(struct net *net) -{ - return &net->ct.nf_ct_proto.icmpv6.pn; -} - struct nf_conntrack_l4proto nf_conntrack_l4proto_icmpv6 __read_mostly = { .l3proto = PF_INET6, @@ -391,5 +377,4 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_icmpv6 __read_mostly = }, #endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */ .init_net = icmpv6_init_net, - .get_net_proto = icmpv6_get_net_proto, }; diff --git a/trunk/net/ipv6/raw.c b/trunk/net/ipv6/raw.c index ef0579d5bca6..b5c1dcb27737 100644 --- a/trunk/net/ipv6/raw.c +++ b/trunk/net/ipv6/raw.c @@ -332,8 +332,6 @@ static void rawv6_err(struct sock *sk, struct sk_buff *skb, ip6_sk_update_pmtu(skb, sk, info); harderr = (np->pmtudisc == IPV6_PMTUDISC_DO); } - if (type == NDISC_REDIRECT) - ip6_sk_redirect(skb, sk); if (np->recverr) { u8 *payload = skb->data; if (!inet->hdrincl) diff --git a/trunk/net/ipv6/route.c b/trunk/net/ipv6/route.c index 84f6564dd372..6cc6c881f54f 100644 --- a/trunk/net/ipv6/route.c +++ b/trunk/net/ipv6/route.c @@ -78,10 +78,7 @@ static int ip6_dst_gc(struct dst_ops *ops); static int ip6_pkt_discard(struct sk_buff *skb); static int ip6_pkt_discard_out(struct sk_buff *skb); static void ip6_link_failure(struct sk_buff *skb); -static void ip6_rt_update_pmtu(struct dst_entry *dst, struct sock *sk, - struct sk_buff *skb, u32 mtu); -static void rt6_do_redirect(struct dst_entry *dst, struct sock *sk, - struct sk_buff *skb); +static void ip6_rt_update_pmtu(struct dst_entry *dst, u32 mtu); #ifdef CONFIG_IPV6_ROUTE_INFO static struct rt6_info *rt6_add_route_info(struct net *net, @@ -177,7 +174,6 @@ static struct dst_ops ip6_dst_ops_template = { .negative_advice = ip6_negative_advice, .link_failure = ip6_link_failure, .update_pmtu = ip6_rt_update_pmtu, - .redirect = rt6_do_redirect, .local_out = __ip6_local_out, .neigh_lookup = ip6_neigh_lookup, }; @@ -189,13 +185,7 @@ static unsigned int ip6_blackhole_mtu(const struct dst_entry *dst) return mtu ? : dst->dev->mtu; } -static void ip6_rt_blackhole_update_pmtu(struct dst_entry *dst, struct sock *sk, - struct sk_buff *skb, u32 mtu) -{ -} - -static void ip6_rt_blackhole_redirect(struct dst_entry *dst, struct sock *sk, - struct sk_buff *skb) +static void ip6_rt_blackhole_update_pmtu(struct dst_entry *dst, u32 mtu) { } @@ -213,7 +203,6 @@ static struct dst_ops ip6_dst_blackhole_ops = { .mtu = ip6_blackhole_mtu, .default_advmss = ip6_default_advmss, .update_pmtu = ip6_rt_blackhole_update_pmtu, - .redirect = ip6_rt_blackhole_redirect, .cow_metrics = ip6_rt_blackhole_cow_metrics, .neigh_lookup = ip6_neigh_lookup, }; @@ -284,9 +273,8 @@ static inline struct rt6_info *ip6_dst_alloc(struct net *net, 0, 0, flags); if (rt) { - struct dst_entry *dst = &rt->dst; - - memset(dst + 1, 0, sizeof(*rt) - sizeof(*dst)); + memset(&rt->n, 0, + sizeof(*rt) - sizeof(struct dst_entry)); rt6_init_peer(rt, table ? &table->tb6_peers : net->ipv6.peers); } return rt; @@ -987,11 +975,11 @@ struct dst_entry *ip6_blackhole_route(struct net *net, struct dst_entry *dst_ori rt = dst_alloc(&ip6_dst_blackhole_ops, ort->dst.dev, 1, 0, 0); if (rt) { - new = &rt->dst; - - memset(new + 1, 0, sizeof(*rt) - sizeof(*new)); + memset(&rt->rt6i_table, 0, sizeof(*rt) - sizeof(struct dst_entry)); rt6_init_peer(rt, net->ipv6.peers); + new = &rt->dst; + new->__use = 1; new->input = dst_discard; new->output = dst_discard; @@ -1075,8 +1063,7 @@ static void ip6_link_failure(struct sk_buff *skb) } } -static void ip6_rt_update_pmtu(struct dst_entry *dst, struct sock *sk, - struct sk_buff *skb, u32 mtu) +static void ip6_rt_update_pmtu(struct dst_entry *dst, u32 mtu) { struct rt6_info *rt6 = (struct rt6_info*)dst; @@ -1106,14 +1093,14 @@ void ip6_update_pmtu(struct sk_buff *skb, struct net *net, __be32 mtu, memset(&fl6, 0, sizeof(fl6)); fl6.flowi6_oif = oif; fl6.flowi6_mark = mark; - fl6.flowi6_flags = 0; + fl6.flowi6_flags = FLOWI_FLAG_PRECOW_METRICS; fl6.daddr = iph->daddr; fl6.saddr = iph->saddr; fl6.flowlabel = (*(__be32 *) iph) & IPV6_FLOWINFO_MASK; dst = ip6_route_output(net, NULL, &fl6); if (!dst->error) - ip6_rt_update_pmtu(dst, NULL, skb, ntohl(mtu)); + ip6_rt_update_pmtu(dst, ntohl(mtu)); dst_release(dst); } EXPORT_SYMBOL_GPL(ip6_update_pmtu); @@ -1125,33 +1112,6 @@ void ip6_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, __be32 mtu) } EXPORT_SYMBOL_GPL(ip6_sk_update_pmtu); -void ip6_redirect(struct sk_buff *skb, struct net *net, int oif, u32 mark) -{ - const struct ipv6hdr *iph = (struct ipv6hdr *) skb->data; - struct dst_entry *dst; - struct flowi6 fl6; - - memset(&fl6, 0, sizeof(fl6)); - fl6.flowi6_oif = oif; - fl6.flowi6_mark = mark; - fl6.flowi6_flags = 0; - fl6.daddr = iph->daddr; - fl6.saddr = iph->saddr; - fl6.flowlabel = (*(__be32 *) iph) & IPV6_FLOWINFO_MASK; - - dst = ip6_route_output(net, NULL, &fl6); - if (!dst->error) - rt6_do_redirect(dst, NULL, skb); - dst_release(dst); -} -EXPORT_SYMBOL_GPL(ip6_redirect); - -void ip6_sk_redirect(struct sk_buff *skb, struct sock *sk) -{ - ip6_redirect(skb, sock_net(sk), sk->sk_bound_dev_if, sk->sk_mark); -} -EXPORT_SYMBOL_GPL(ip6_sk_redirect); - static unsigned int ip6_default_advmss(const struct dst_entry *dst) { struct net_device *dev = dst->dev; @@ -1644,93 +1604,107 @@ static int ip6_route_del(struct fib6_config *cfg) return err; } -static void rt6_do_redirect(struct dst_entry *dst, struct sock *sk, struct sk_buff *skb) +/* + * Handle redirects + */ +struct ip6rd_flowi { + struct flowi6 fl6; + struct in6_addr gateway; +}; + +static struct rt6_info *__ip6_route_redirect(struct net *net, + struct fib6_table *table, + struct flowi6 *fl6, + int flags) { - struct net *net = dev_net(skb->dev); - struct netevent_redirect netevent; - struct rt6_info *rt, *nrt = NULL; - const struct in6_addr *target; - struct ndisc_options ndopts; - const struct in6_addr *dest; - struct neighbour *old_neigh; - struct inet6_dev *in6_dev; - struct neighbour *neigh; - struct icmp6hdr *icmph; - int optlen, on_link; - u8 *lladdr; + struct ip6rd_flowi *rdfl = (struct ip6rd_flowi *)fl6; + struct rt6_info *rt; + struct fib6_node *fn; - optlen = skb->tail - skb->transport_header; - optlen -= sizeof(struct icmp6hdr) + 2 * sizeof(struct in6_addr); + /* + * Get the "current" route for this destination and + * check if the redirect has come from approriate router. + * + * RFC 2461 specifies that redirects should only be + * accepted if they come from the nexthop to the target. + * Due to the way the routes are chosen, this notion + * is a bit fuzzy and one might need to check all possible + * routes. + */ - if (optlen < 0) { - net_dbg_ratelimited("rt6_do_redirect: packet too short\n"); - return; + read_lock_bh(&table->tb6_lock); + fn = fib6_lookup(&table->tb6_root, &fl6->daddr, &fl6->saddr); +restart: + for (rt = fn->leaf; rt; rt = rt->dst.rt6_next) { + /* + * Current route is on-link; redirect is always invalid. + * + * Seems, previous statement is not true. It could + * be node, which looks for us as on-link (f.e. proxy ndisc) + * But then router serving it might decide, that we should + * know truth 8)8) --ANK (980726). + */ + if (rt6_check_expired(rt)) + continue; + if (!(rt->rt6i_flags & RTF_GATEWAY)) + continue; + if (fl6->flowi6_oif != rt->dst.dev->ifindex) + continue; + if (!ipv6_addr_equal(&rdfl->gateway, &rt->rt6i_gateway)) + continue; + break; } - icmph = icmp6_hdr(skb); - target = (const struct in6_addr *) (icmph + 1); - dest = target + 1; - - if (ipv6_addr_is_multicast(dest)) { - net_dbg_ratelimited("rt6_do_redirect: destination address is multicast\n"); - return; - } + if (!rt) + rt = net->ipv6.ip6_null_entry; + BACKTRACK(net, &fl6->saddr); +out: + dst_hold(&rt->dst); - on_link = 0; - if (ipv6_addr_equal(dest, target)) { - on_link = 1; - } else if (ipv6_addr_type(target) != - (IPV6_ADDR_UNICAST|IPV6_ADDR_LINKLOCAL)) { - net_dbg_ratelimited("rt6_do_redirect: target address is not link-local unicast\n"); - return; - } + read_unlock_bh(&table->tb6_lock); - in6_dev = __in6_dev_get(skb->dev); - if (!in6_dev) - return; - if (in6_dev->cnf.forwarding || !in6_dev->cnf.accept_redirects) - return; + return rt; +}; - /* RFC2461 8.1: - * The IP source address of the Redirect MUST be the same as the current - * first-hop router for the specified ICMP Destination Address. - */ +static struct rt6_info *ip6_route_redirect(const struct in6_addr *dest, + const struct in6_addr *src, + const struct in6_addr *gateway, + struct net_device *dev) +{ + int flags = RT6_LOOKUP_F_HAS_SADDR; + struct net *net = dev_net(dev); + struct ip6rd_flowi rdfl = { + .fl6 = { + .flowi6_oif = dev->ifindex, + .daddr = *dest, + .saddr = *src, + }, + }; - if (!ndisc_parse_options((u8*)(dest + 1), optlen, &ndopts)) { - net_dbg_ratelimited("rt6_redirect: invalid ND options\n"); - return; - } + rdfl.gateway = *gateway; - lladdr = NULL; - if (ndopts.nd_opts_tgt_lladdr) { - lladdr = ndisc_opt_addr_data(ndopts.nd_opts_tgt_lladdr, - skb->dev); - if (!lladdr) { - net_dbg_ratelimited("rt6_redirect: invalid link-layer address length\n"); - return; - } - } + if (rt6_need_strict(dest)) + flags |= RT6_LOOKUP_F_IFACE; - rt = (struct rt6_info *) dst; - if (rt == net->ipv6.ip6_null_entry) { - net_dbg_ratelimited("rt6_redirect: source isn't a valid nexthop for redirect target\n"); - return; - } + return (struct rt6_info *)fib6_rule_lookup(net, &rdfl.fl6, + flags, __ip6_route_redirect); +} - /* Redirect received -> path was valid. - * Look, redirects are sent only in response to data packets, - * so that this nexthop apparently is reachable. --ANK - */ - dst_confirm(&rt->dst); +void rt6_redirect(const struct in6_addr *dest, const struct in6_addr *src, + const struct in6_addr *saddr, + struct neighbour *neigh, u8 *lladdr, int on_link) +{ + struct rt6_info *rt, *nrt = NULL; + struct netevent_redirect netevent; + struct net *net = dev_net(neigh->dev); + struct neighbour *old_neigh; - neigh = __neigh_lookup(&nd_tbl, target, skb->dev, 1); - if (!neigh) - return; + rt = ip6_route_redirect(dest, src, saddr, neigh->dev); - /* Duplicate redirect: silently ignore. */ - old_neigh = rt->n; - if (neigh == old_neigh) + if (rt == net->ipv6.ip6_null_entry) { + net_dbg_ratelimited("rt6_redirect: source isn't a valid nexthop for redirect target\n"); goto out; + } /* * We have finally decided to accept it. @@ -1743,6 +1717,18 @@ static void rt6_do_redirect(struct dst_entry *dst, struct sock *sk, struct sk_bu NEIGH_UPDATE_F_ISROUTER)) ); + /* + * Redirect received -> path was valid. + * Look, redirects are sent only in response to data packets, + * so that this nexthop apparently is reachable. --ANK + */ + dst_confirm(&rt->dst); + + /* Duplicate redirect: silently ignore. */ + old_neigh = rt->n; + if (neigh == old_neigh) + goto out; + nrt = ip6_rt_copy(rt, dest); if (!nrt) goto out; @@ -1765,12 +1751,12 @@ static void rt6_do_redirect(struct dst_entry *dst, struct sock *sk, struct sk_bu call_netevent_notifiers(NETEVENT_REDIRECT, &netevent); if (rt->rt6i_flags & RTF_CACHE) { - rt = (struct rt6_info *) dst_clone(&rt->dst); ip6_del_rt(rt); + return; } out: - neigh_release(neigh); + dst_release(&rt->dst); } /* @@ -2362,11 +2348,13 @@ static int rt6_fill_node(struct net *net, int iif, int type, u32 pid, u32 seq, int prefix, int nowait, unsigned int flags) { + const struct inet_peer *peer; struct rtmsg *rtm; struct nlmsghdr *nlh; long expires; u32 table; struct neighbour *n; + u32 ts, tsage; if (prefix) { /* user wants prefix routes only */ if (!(rt->rt6i_flags & RTF_PREFIX_RT)) { @@ -2404,12 +2392,10 @@ static int rt6_fill_node(struct net *net, rtm->rtm_protocol = rt->rt6i_protocol; if (rt->rt6i_flags & RTF_DYNAMIC) rtm->rtm_protocol = RTPROT_REDIRECT; - else if (rt->rt6i_flags & RTF_ADDRCONF) { - if (rt->rt6i_flags & (RTF_DEFAULT | RTF_ROUTEINFO)) - rtm->rtm_protocol = RTPROT_RA; - else - rtm->rtm_protocol = RTPROT_KERNEL; - } + else if (rt->rt6i_flags & RTF_ADDRCONF) + rtm->rtm_protocol = RTPROT_KERNEL; + else if (rt->rt6i_flags & RTF_DEFAULT) + rtm->rtm_protocol = RTPROT_RA; if (rt->rt6i_flags & RTF_CACHE) rtm->rtm_flags |= RTM_F_CLONED; @@ -2487,7 +2473,17 @@ static int rt6_fill_node(struct net *net, else expires = INT_MAX; - if (rtnl_put_cacheinfo(skb, &rt->dst, 0, expires, rt->dst.error) < 0) + peer = NULL; + if (rt6_has_peer(rt)) + peer = rt6_peer_ptr(rt); + ts = tsage = 0; + if (peer && peer->tcp_ts_stamp) { + ts = peer->tcp_ts; + tsage = get_seconds() - peer->tcp_ts_stamp; + } + + if (rtnl_put_cacheinfo(skb, &rt->dst, 0, ts, tsage, + expires, rt->dst.error) < 0) goto nla_put_failure; return nlmsg_end(skb, nlh); diff --git a/trunk/net/ipv6/sit.c b/trunk/net/ipv6/sit.c index 3bd1bfc01f85..49aea94c9be3 100644 --- a/trunk/net/ipv6/sit.c +++ b/trunk/net/ipv6/sit.c @@ -539,8 +539,6 @@ static int ipip6_err(struct sk_buff *skb, u32 info) if (code != ICMP_EXC_TTL) return 0; break; - case ICMP_REDIRECT: - break; } err = -ENOENT; @@ -559,12 +557,6 @@ static int ipip6_err(struct sk_buff *skb, u32 info) err = 0; goto out; } - if (type == ICMP_REDIRECT) { - ipv4_redirect(skb, dev_net(skb->dev), t->dev->ifindex, 0, - IPPROTO_IPV6, 0); - err = 0; - goto out; - } if (t->parms.iph.daddr == 0) goto out; @@ -807,7 +799,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb, } if (tunnel->parms.iph.daddr && skb_dst(skb)) - skb_dst(skb)->ops->update_pmtu(skb_dst(skb), NULL, skb, mtu); + skb_dst(skb)->ops->update_pmtu(skb_dst(skb), mtu); if (skb->len > mtu) { icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); diff --git a/trunk/net/ipv6/tcp_ipv6.c b/trunk/net/ipv6/tcp_ipv6.c index c9dabdd832d7..6cc67ed6c2e6 100644 --- a/trunk/net/ipv6/tcp_ipv6.c +++ b/trunk/net/ipv6/tcp_ipv6.c @@ -277,8 +277,22 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, rt = (struct rt6_info *) dst; if (tcp_death_row.sysctl_tw_recycle && !tp->rx_opt.ts_recent_stamp && - ipv6_addr_equal(&rt->rt6i_dst.addr, &np->daddr)) - tcp_fetch_timewait_stamp(sk, dst); + ipv6_addr_equal(&rt->rt6i_dst.addr, &np->daddr)) { + struct inet_peer *peer = rt6_get_peer(rt); + /* + * VJ's idea. We save last timestamp seen from + * the destination in peer table, when entering state + * TIME-WAIT * and initialize rx_opt.ts_recent from it, + * when trying new connection. + */ + if (peer) { + inet_peer_refcheck(peer); + if ((u32)get_seconds() - peer->tcp_ts_stamp <= TCP_PAWS_MSL) { + tp->rx_opt.ts_recent_stamp = peer->tcp_ts_stamp; + tp->rx_opt.ts_recent = peer->tcp_ts; + } + } + } icsk->icsk_ext_hdr_len = 0; if (np->opt) @@ -363,13 +377,6 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, np = inet6_sk(sk); - if (type == NDISC_REDIRECT) { - struct dst_entry *dst = __sk_dst_check(sk, np->dst_cookie); - - if (dst) - dst->ops->redirect(dst, sk, skb); - } - if (type == ICMPV6_PKT_TOOBIG) { struct dst_entry *dst; @@ -378,14 +385,43 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, if ((1 << sk->sk_state) & (TCPF_LISTEN | TCPF_CLOSE)) goto out; - dst = inet6_csk_update_pmtu(sk, ntohl(info)); - if (!dst) - goto out; + /* icmp should have updated the destination cache entry */ + dst = __sk_dst_check(sk, np->dst_cookie); + + if (dst == NULL) { + struct inet_sock *inet = inet_sk(sk); + struct flowi6 fl6; + + /* BUGGG_FUTURE: Again, it is not clear how + to handle rthdr case. Ignore this complexity + for now. + */ + memset(&fl6, 0, sizeof(fl6)); + fl6.flowi6_proto = IPPROTO_TCP; + fl6.daddr = np->daddr; + fl6.saddr = np->saddr; + fl6.flowi6_oif = sk->sk_bound_dev_if; + fl6.flowi6_mark = sk->sk_mark; + fl6.fl6_dport = inet->inet_dport; + fl6.fl6_sport = inet->inet_sport; + security_skb_classify_flow(skb, flowi6_to_flowi(&fl6)); + + dst = ip6_dst_lookup_flow(sk, &fl6, NULL, false); + if (IS_ERR(dst)) { + sk->sk_err_soft = -PTR_ERR(dst); + goto out; + } + + } else + dst_hold(dst); + + dst->ops->update_pmtu(dst, ntohl(info)); if (inet_csk(sk)->icsk_pmtu_cookie > dst_mtu(dst)) { tcp_sync_mss(sk, dst_mtu(dst)); tcp_simple_retransmit(sk); - } + } /* else let the usual retransmit timer handle it */ + dst_release(dst); goto out; } @@ -1098,6 +1134,8 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb) treq->iif = inet6_iif(skb); if (!isn) { + struct inet_peer *peer = NULL; + if (ipv6_opt_accepted(sk, skb) || np->rxopt.bits.rxinfo || np->rxopt.bits.rxoinfo || np->rxopt.bits.rxhlim || np->rxopt.bits.rxohlim) { @@ -1122,8 +1160,14 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb) */ if (tmp_opt.saw_tstamp && tcp_death_row.sysctl_tw_recycle && - (dst = inet6_csk_route_req(sk, &fl6, req)) != NULL) { - if (!tcp_peer_is_proven(req, dst, true)) { + (dst = inet6_csk_route_req(sk, &fl6, req)) != NULL && + (peer = rt6_get_peer((struct rt6_info *)dst)) != NULL && + ipv6_addr_equal((struct in6_addr *)peer->daddr.addr.a6, + &treq->rmt_addr)) { + inet_peer_refcheck(peer); + if ((u32)get_seconds() - peer->tcp_ts_stamp < TCP_PAWS_MSL && + (s32)(peer->tcp_ts - req->ts_recent) > + TCP_PAWS_WINDOW) { NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_PAWSPASSIVEREJECTED); goto drop_and_release; } @@ -1132,7 +1176,8 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb) else if (!sysctl_tcp_syncookies && (sysctl_max_syn_backlog - inet_csk_reqsk_queue_len(sk) < (sysctl_max_syn_backlog >> 2)) && - !tcp_peer_is_proven(req, dst, false)) { + (!peer || !peer->tcp_ts_stamp) && + (!dst || !dst_metric(dst, RTAX_RTT))) { /* Without syncookies last quarter of * backlog is filled with destinations, * proven to be alive. @@ -1667,6 +1712,20 @@ static int tcp_v6_rcv(struct sk_buff *skb) goto discard_it; } +static struct inet_peer *tcp_v6_get_peer(struct sock *sk) +{ + struct rt6_info *rt = (struct rt6_info *) __sk_dst_get(sk); + struct ipv6_pinfo *np = inet6_sk(sk); + + /* If we don't have a valid cached route, or we're doing IP + * options which make the IPv6 header destination address + * different from our peer's, do not bother with this. + */ + if (!rt || !ipv6_addr_equal(&np->daddr, &rt->rt6i_dst.addr)) + return NULL; + return rt6_get_peer_create(rt); +} + static struct timewait_sock_ops tcp6_timewait_sock_ops = { .twsk_obj_size = sizeof(struct tcp6_timewait_sock), .twsk_unique = tcp_twsk_unique, @@ -1679,6 +1738,7 @@ static const struct inet_connection_sock_af_ops ipv6_specific = { .rebuild_header = inet6_sk_rebuild_header, .conn_request = tcp_v6_conn_request, .syn_recv_sock = tcp_v6_syn_recv_sock, + .get_peer = tcp_v6_get_peer, .net_header_len = sizeof(struct ipv6hdr), .net_frag_header_len = sizeof(struct frag_hdr), .setsockopt = ipv6_setsockopt, @@ -1710,6 +1770,7 @@ static const struct inet_connection_sock_af_ops ipv6_mapped = { .rebuild_header = inet_sk_rebuild_header, .conn_request = tcp_v6_conn_request, .syn_recv_sock = tcp_v6_syn_recv_sock, + .get_peer = tcp_v4_get_peer, .net_header_len = sizeof(struct iphdr), .setsockopt = ipv6_setsockopt, .getsockopt = ipv6_getsockopt, @@ -1948,7 +2009,6 @@ struct proto tcpv6_prot = { .sendmsg = tcp_sendmsg, .sendpage = tcp_sendpage, .backlog_rcv = tcp_v6_do_rcv, - .release_cb = tcp_release_cb, .hash = tcp_v6_hash, .unhash = inet_unhash, .get_port = inet_csk_get_port, diff --git a/trunk/net/ipv6/udp.c b/trunk/net/ipv6/udp.c index 99d0077b56b8..1ecd10249488 100644 --- a/trunk/net/ipv6/udp.c +++ b/trunk/net/ipv6/udp.c @@ -483,8 +483,6 @@ void __udp6_lib_err(struct sk_buff *skb, struct inet6_skb_parm *opt, if (type == ICMPV6_PKT_TOOBIG) ip6_sk_update_pmtu(skb, sk, info); - if (type == NDISC_REDIRECT) - ip6_sk_redirect(skb, sk); np = inet6_sk(sk); diff --git a/trunk/net/ipv6/xfrm6_policy.c b/trunk/net/ipv6/xfrm6_policy.c index ef39812107b1..bb02038b822b 100644 --- a/trunk/net/ipv6/xfrm6_policy.c +++ b/trunk/net/ipv6/xfrm6_policy.c @@ -207,22 +207,12 @@ static inline int xfrm6_garbage_collect(struct dst_ops *ops) return dst_entries_get_fast(ops) > ops->gc_thresh * 2; } -static void xfrm6_update_pmtu(struct dst_entry *dst, struct sock *sk, - struct sk_buff *skb, u32 mtu) +static void xfrm6_update_pmtu(struct dst_entry *dst, u32 mtu) { struct xfrm_dst *xdst = (struct xfrm_dst *)dst; struct dst_entry *path = xdst->route; - path->ops->update_pmtu(path, sk, skb, mtu); -} - -static void xfrm6_redirect(struct dst_entry *dst, struct sock *sk, - struct sk_buff *skb) -{ - struct xfrm_dst *xdst = (struct xfrm_dst *)dst; - struct dst_entry *path = xdst->route; - - path->ops->redirect(path, sk, skb); + path->ops->update_pmtu(path, mtu); } static void xfrm6_dst_destroy(struct dst_entry *dst) @@ -271,7 +261,6 @@ static struct dst_ops xfrm6_dst_ops = { .protocol = cpu_to_be16(ETH_P_IPV6), .gc = xfrm6_garbage_collect, .update_pmtu = xfrm6_update_pmtu, - .redirect = xfrm6_redirect, .cow_metrics = dst_cow_metrics_generic, .destroy = xfrm6_dst_destroy, .ifdown = xfrm6_dst_ifdown, diff --git a/trunk/net/irda/af_irda.c b/trunk/net/irda/af_irda.c index bb738c9f9146..bb14c3477680 100644 --- a/trunk/net/irda/af_irda.c +++ b/trunk/net/irda/af_irda.c @@ -955,7 +955,7 @@ static int irda_accept(struct socket *sock, struct socket *newsock, int flags) * The main difference with a "standard" connect is that with IrDA we need * to resolve the service name into a TSAP selector (in TCP, port number * doesn't have to be resolved). - * Because of this service name resolution, we can offer "auto-connect", + * Because of this service name resoltion, we can offer "auto-connect", * where we connect to a service without specifying a destination address. * * Note : by consulting "errno", the user space caller may learn the cause diff --git a/trunk/net/irda/irlan/irlan_provider.c b/trunk/net/irda/irlan/irlan_provider.c index 4664855222f4..32dcaac70b0c 100644 --- a/trunk/net/irda/irlan/irlan_provider.c +++ b/trunk/net/irda/irlan/irlan_provider.c @@ -296,7 +296,7 @@ void irlan_provider_send_reply(struct irlan_cb *self, int command, skb = alloc_skb(IRLAN_MAX_HEADER + IRLAN_CMD_HEADER + /* Bigger param length comes from CMD_GET_MEDIA_CHAR */ IRLAN_STRING_PARAMETER_LEN("FILTER_TYPE", "DIRECTED") + - IRLAN_STRING_PARAMETER_LEN("FILTER_TYPE", "BROADCAST") + + IRLAN_STRING_PARAMETER_LEN("FILTER_TYPE", "BORADCAST") + IRLAN_STRING_PARAMETER_LEN("FILTER_TYPE", "MULTICAST") + IRLAN_STRING_PARAMETER_LEN("ACCESS_TYPE", "HOSTED"), GFP_ATOMIC); diff --git a/trunk/net/llc/af_llc.c b/trunk/net/llc/af_llc.c index f6fe4d400502..fe5453c3e719 100644 --- a/trunk/net/llc/af_llc.c +++ b/trunk/net/llc/af_llc.c @@ -1024,7 +1024,7 @@ static int llc_ui_ioctl(struct socket *sock, unsigned int cmd, * @sock: Socket to set options on. * @level: Socket level user is requesting operations on. * @optname: Operation name. - * @optval: User provided operation data. + * @optval User provided operation data. * @optlen: Length of optval. * * Set various connection specific parameters. diff --git a/trunk/net/llc/llc_station.c b/trunk/net/llc/llc_station.c index 39a8d8924b9c..cf4aea3ba30f 100644 --- a/trunk/net/llc/llc_station.c +++ b/trunk/net/llc/llc_station.c @@ -30,12 +30,12 @@ * * SAP and connection resource manager, one per adapter. * - * @state: state of station - * @xid_r_count: XID response PDU counter - * @mac_sa: MAC source address - * @sap_list: list of related SAPs - * @ev_q: events entering state mach. - * @mac_pdu_q: PDUs ready to send to MAC + * @state - state of station + * @xid_r_count - XID response PDU counter + * @mac_sa - MAC source address + * @sap_list - list of related SAPs + * @ev_q - events entering state mach. + * @mac_pdu_q - PDUs ready to send to MAC */ struct llc_station { u8 state; @@ -646,7 +646,7 @@ static void llc_station_service_events(void) } /** - * llc_station_state_process - queue event and try to process queue. + * llc_station_state_process: queue event and try to process queue. * @skb: Address of the event * * Queues an event (on the station event queue) for handling by the @@ -672,7 +672,7 @@ static void llc_station_ack_tmr_cb(unsigned long timeout_data) } } -/** +/* * llc_station_rcv - send received pdu to the station state machine * @skb: received frame. * diff --git a/trunk/net/mac80211/cfg.c b/trunk/net/mac80211/cfg.c index ccbe2413142a..c2a2dcbfdf01 100644 --- a/trunk/net/mac80211/cfg.c +++ b/trunk/net/mac80211/cfg.c @@ -2668,8 +2668,8 @@ ieee80211_prep_tdls_encap_data(struct wiphy *wiphy, struct net_device *dev, tf->u.setup_req.capability = cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata)); - ieee80211_add_srates_ie(sdata, skb, false); - ieee80211_add_ext_srates_ie(sdata, skb, false); + ieee80211_add_srates_ie(&sdata->vif, skb, false); + ieee80211_add_ext_srates_ie(&sdata->vif, skb, false); ieee80211_tdls_add_ext_capab(skb); break; case WLAN_TDLS_SETUP_RESPONSE: @@ -2682,8 +2682,8 @@ ieee80211_prep_tdls_encap_data(struct wiphy *wiphy, struct net_device *dev, tf->u.setup_resp.capability = cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata)); - ieee80211_add_srates_ie(sdata, skb, false); - ieee80211_add_ext_srates_ie(sdata, skb, false); + ieee80211_add_srates_ie(&sdata->vif, skb, false); + ieee80211_add_ext_srates_ie(&sdata->vif, skb, false); ieee80211_tdls_add_ext_capab(skb); break; case WLAN_TDLS_SETUP_CONFIRM: @@ -2743,8 +2743,8 @@ ieee80211_prep_tdls_direct(struct wiphy *wiphy, struct net_device *dev, mgmt->u.action.u.tdls_discover_resp.capability = cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata)); - ieee80211_add_srates_ie(sdata, skb, false); - ieee80211_add_ext_srates_ie(sdata, skb, false); + ieee80211_add_srates_ie(&sdata->vif, skb, false); + ieee80211_add_ext_srates_ie(&sdata->vif, skb, false); ieee80211_tdls_add_ext_capab(skb); break; default: @@ -2980,14 +2980,14 @@ static int ieee80211_probe_client(struct wiphy *wiphy, struct net_device *dev, return 0; } -static void ieee80211_set_monitor_enabled(struct wiphy *wiphy, bool enabled) +static struct ieee80211_channel * +ieee80211_wiphy_get_channel(struct wiphy *wiphy, + enum nl80211_channel_type *type) { struct ieee80211_local *local = wiphy_priv(wiphy); - if (enabled) - WARN_ON(ieee80211_add_virtual_monitor(local)); - else - ieee80211_del_virtual_monitor(local); + *type = local->_oper_channel_type; + return local->oper_channel; } #ifdef CONFIG_PM @@ -3063,8 +3063,8 @@ struct cfg80211_ops mac80211_config_ops = { .tdls_oper = ieee80211_tdls_oper, .tdls_mgmt = ieee80211_tdls_mgmt, .probe_client = ieee80211_probe_client, + .get_channel = ieee80211_wiphy_get_channel, .set_noack_map = ieee80211_set_noack_map, - .set_monitor_enabled = ieee80211_set_monitor_enabled, #ifdef CONFIG_PM .set_wakeup = ieee80211_set_wakeup, #endif diff --git a/trunk/net/mac80211/debugfs_key.c b/trunk/net/mac80211/debugfs_key.c index 090d08ff22c4..7932767bb482 100644 --- a/trunk/net/mac80211/debugfs_key.c +++ b/trunk/net/mac80211/debugfs_key.c @@ -283,11 +283,6 @@ void ieee80211_debugfs_key_update_default(struct ieee80211_sub_if_data *sdata) lockdep_assert_held(&sdata->local->key_mtx); - if (sdata->debugfs.default_unicast_key) { - debugfs_remove(sdata->debugfs.default_unicast_key); - sdata->debugfs.default_unicast_key = NULL; - } - if (sdata->default_unicast_key) { key = key_mtx_dereference(sdata->local, sdata->default_unicast_key); @@ -295,11 +290,9 @@ void ieee80211_debugfs_key_update_default(struct ieee80211_sub_if_data *sdata) sdata->debugfs.default_unicast_key = debugfs_create_symlink("default_unicast_key", sdata->debugfs.dir, buf); - } - - if (sdata->debugfs.default_multicast_key) { - debugfs_remove(sdata->debugfs.default_multicast_key); - sdata->debugfs.default_multicast_key = NULL; + } else { + debugfs_remove(sdata->debugfs.default_unicast_key); + sdata->debugfs.default_unicast_key = NULL; } if (sdata->default_multicast_key) { @@ -309,6 +302,9 @@ void ieee80211_debugfs_key_update_default(struct ieee80211_sub_if_data *sdata) sdata->debugfs.default_multicast_key = debugfs_create_symlink("default_multicast_key", sdata->debugfs.dir, buf); + } else { + debugfs_remove(sdata->debugfs.default_multicast_key); + sdata->debugfs.default_multicast_key = NULL; } } diff --git a/trunk/net/mac80211/driver-ops.h b/trunk/net/mac80211/driver-ops.h index df9203199102..44e8c1242781 100644 --- a/trunk/net/mac80211/driver-ops.h +++ b/trunk/net/mac80211/driver-ops.h @@ -27,6 +27,14 @@ static inline void drv_tx(struct ieee80211_local *local, struct sk_buff *skb) local->ops->tx(&local->hw, skb); } +static inline void drv_tx_frags(struct ieee80211_local *local, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, + struct sk_buff_head *skbs) +{ + local->ops->tx_frags(&local->hw, vif, sta, skbs); +} + static inline void drv_get_et_strings(struct ieee80211_sub_if_data *sdata, u32 sset, u8 *data) { @@ -852,18 +860,4 @@ static inline int drv_get_rssi(struct ieee80211_local *local, return ret; } - -static inline void drv_mgd_prepare_tx(struct ieee80211_local *local, - struct ieee80211_sub_if_data *sdata) -{ - might_sleep(); - - check_sdata_in_driver(sdata); - WARN_ON_ONCE(sdata->vif.type != NL80211_IFTYPE_STATION); - - trace_drv_mgd_prepare_tx(local, sdata); - if (local->ops->mgd_prepare_tx) - local->ops->mgd_prepare_tx(&local->hw, &sdata->vif); - trace_drv_return_void(local); -} #endif /* __MAC80211_DRIVER_OPS */ diff --git a/trunk/net/mac80211/ieee80211_i.h b/trunk/net/mac80211/ieee80211_i.h index e0423f8c0ce1..f834a005e1c5 100644 --- a/trunk/net/mac80211/ieee80211_i.h +++ b/trunk/net/mac80211/ieee80211_i.h @@ -1284,6 +1284,7 @@ int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata, enum nl80211_iftype type); void ieee80211_if_remove(struct ieee80211_sub_if_data *sdata); void ieee80211_remove_interfaces(struct ieee80211_local *local); +u32 __ieee80211_recalc_idle(struct ieee80211_local *local); void ieee80211_recalc_idle(struct ieee80211_local *local); void ieee80211_adjust_monitor_flags(struct ieee80211_sub_if_data *sdata, const int offset); @@ -1480,16 +1481,6 @@ u8 *ieee80211_ie_build_ht_oper(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap, struct ieee80211_channel *channel, enum nl80211_channel_type channel_type, u16 prot_mode); -u8 *ieee80211_ie_build_vht_cap(u8 *pos, struct ieee80211_sta_vht_cap *vht_cap, - u32 cap); -int ieee80211_add_srates_ie(struct ieee80211_sub_if_data *sdata, - struct sk_buff *skb, bool need_basic); -int ieee80211_add_ext_srates_ie(struct ieee80211_sub_if_data *sdata, - struct sk_buff *skb, bool need_basic); - -/* virtual monitor */ -int ieee80211_add_virtual_monitor(struct ieee80211_local *local); -void ieee80211_del_virtual_monitor(struct ieee80211_local *local); /* channel management */ enum ieee80211_chan_mode { diff --git a/trunk/net/mac80211/iface.c b/trunk/net/mac80211/iface.c index fbef7a1ada7a..58c2ab3d483a 100644 --- a/trunk/net/mac80211/iface.c +++ b/trunk/net/mac80211/iface.c @@ -43,127 +43,6 @@ */ -static u32 ieee80211_idle_off(struct ieee80211_local *local, - const char *reason) -{ - if (!(local->hw.conf.flags & IEEE80211_CONF_IDLE)) - return 0; - - local->hw.conf.flags &= ~IEEE80211_CONF_IDLE; - return IEEE80211_CONF_CHANGE_IDLE; -} - -static u32 ieee80211_idle_on(struct ieee80211_local *local) -{ - if (local->hw.conf.flags & IEEE80211_CONF_IDLE) - return 0; - - drv_flush(local, false); - - local->hw.conf.flags |= IEEE80211_CONF_IDLE; - return IEEE80211_CONF_CHANGE_IDLE; -} - -static u32 __ieee80211_recalc_idle(struct ieee80211_local *local) -{ - struct ieee80211_sub_if_data *sdata; - int count = 0; - bool working = false, scanning = false; - unsigned int led_trig_start = 0, led_trig_stop = 0; - struct ieee80211_roc_work *roc; - -#ifdef CONFIG_PROVE_LOCKING - WARN_ON(debug_locks && !lockdep_rtnl_is_held() && - !lockdep_is_held(&local->iflist_mtx)); -#endif - lockdep_assert_held(&local->mtx); - - list_for_each_entry(sdata, &local->interfaces, list) { - if (!ieee80211_sdata_running(sdata)) { - sdata->vif.bss_conf.idle = true; - continue; - } - - sdata->old_idle = sdata->vif.bss_conf.idle; - - /* do not count disabled managed interfaces */ - if (sdata->vif.type == NL80211_IFTYPE_STATION && - !sdata->u.mgd.associated && - !sdata->u.mgd.auth_data && - !sdata->u.mgd.assoc_data) { - sdata->vif.bss_conf.idle = true; - continue; - } - /* do not count unused IBSS interfaces */ - if (sdata->vif.type == NL80211_IFTYPE_ADHOC && - !sdata->u.ibss.ssid_len) { - sdata->vif.bss_conf.idle = true; - continue; - } - /* count everything else */ - sdata->vif.bss_conf.idle = false; - count++; - } - - if (!local->ops->remain_on_channel) { - list_for_each_entry(roc, &local->roc_list, list) { - working = true; - roc->sdata->vif.bss_conf.idle = false; - } - } - - if (local->scan_sdata && - !(local->hw.flags & IEEE80211_HW_SCAN_WHILE_IDLE)) { - scanning = true; - local->scan_sdata->vif.bss_conf.idle = false; - } - - list_for_each_entry(sdata, &local->interfaces, list) { - if (sdata->vif.type == NL80211_IFTYPE_MONITOR || - sdata->vif.type == NL80211_IFTYPE_AP_VLAN) - continue; - if (sdata->old_idle == sdata->vif.bss_conf.idle) - continue; - if (!ieee80211_sdata_running(sdata)) - continue; - ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_IDLE); - } - - if (working || scanning) - led_trig_start |= IEEE80211_TPT_LEDTRIG_FL_WORK; - else - led_trig_stop |= IEEE80211_TPT_LEDTRIG_FL_WORK; - - if (count) - led_trig_start |= IEEE80211_TPT_LEDTRIG_FL_CONNECTED; - else - led_trig_stop |= IEEE80211_TPT_LEDTRIG_FL_CONNECTED; - - ieee80211_mod_tpt_led_trig(local, led_trig_start, led_trig_stop); - - if (working) - return ieee80211_idle_off(local, "working"); - if (scanning) - return ieee80211_idle_off(local, "scanning"); - if (!count) - return ieee80211_idle_on(local); - else - return ieee80211_idle_off(local, "in use"); - - return 0; -} - -void ieee80211_recalc_idle(struct ieee80211_local *local) -{ - u32 chg; - - mutex_lock(&local->iflist_mtx); - chg = __ieee80211_recalc_idle(local); - mutex_unlock(&local->iflist_mtx); - if (chg) - ieee80211_hw_config(local, chg); -} - static int ieee80211_change_mtu(struct net_device *dev, int new_mtu) { int meshhdrlen; @@ -330,7 +209,7 @@ static void ieee80211_set_default_queues(struct ieee80211_sub_if_data *sdata) sdata->vif.cab_queue = IEEE80211_INVAL_HW_QUEUE; } -int ieee80211_add_virtual_monitor(struct ieee80211_local *local) +static int ieee80211_add_virtual_monitor(struct ieee80211_local *local) { struct ieee80211_sub_if_data *sdata; int ret; @@ -371,7 +250,7 @@ int ieee80211_add_virtual_monitor(struct ieee80211_local *local) return 0; } -void ieee80211_del_virtual_monitor(struct ieee80211_local *local) +static void ieee80211_del_virtual_monitor(struct ieee80211_local *local) { struct ieee80211_sub_if_data *sdata; @@ -487,6 +366,12 @@ static int ieee80211_do_open(struct net_device *dev, bool coming_up) break; } + if (local->monitors == 0 && local->open_count == 0) { + res = ieee80211_add_virtual_monitor(local); + if (res) + goto err_stop; + } + /* must be before the call to ieee80211_configure_filter */ local->monitors++; if (local->monitors == 1) { @@ -501,6 +386,8 @@ static int ieee80211_do_open(struct net_device *dev, bool coming_up) break; default: if (coming_up) { + ieee80211_del_virtual_monitor(local); + res = drv_add_interface(local, sdata); if (res) goto err_stop; @@ -735,6 +622,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, if (local->monitors == 0) { local->hw.conf.flags &= ~IEEE80211_CONF_MONITOR; hw_reconf_flags |= IEEE80211_CONF_CHANGE_MONITOR; + ieee80211_del_virtual_monitor(local); } ieee80211_adjust_monitor_flags(sdata, -1); @@ -808,6 +696,9 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, } } spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); + + if (local->monitors == local->open_count && local->monitors > 0) + ieee80211_add_virtual_monitor(local); } static int ieee80211_stop(struct net_device *dev) @@ -1512,6 +1403,127 @@ void ieee80211_remove_interfaces(struct ieee80211_local *local) list_del(&unreg_list); } +static u32 ieee80211_idle_off(struct ieee80211_local *local, + const char *reason) +{ + if (!(local->hw.conf.flags & IEEE80211_CONF_IDLE)) + return 0; + + local->hw.conf.flags &= ~IEEE80211_CONF_IDLE; + return IEEE80211_CONF_CHANGE_IDLE; +} + +static u32 ieee80211_idle_on(struct ieee80211_local *local) +{ + if (local->hw.conf.flags & IEEE80211_CONF_IDLE) + return 0; + + drv_flush(local, false); + + local->hw.conf.flags |= IEEE80211_CONF_IDLE; + return IEEE80211_CONF_CHANGE_IDLE; +} + +u32 __ieee80211_recalc_idle(struct ieee80211_local *local) +{ + struct ieee80211_sub_if_data *sdata; + int count = 0; + bool working = false, scanning = false; + unsigned int led_trig_start = 0, led_trig_stop = 0; + struct ieee80211_roc_work *roc; + +#ifdef CONFIG_PROVE_LOCKING + WARN_ON(debug_locks && !lockdep_rtnl_is_held() && + !lockdep_is_held(&local->iflist_mtx)); +#endif + lockdep_assert_held(&local->mtx); + + list_for_each_entry(sdata, &local->interfaces, list) { + if (!ieee80211_sdata_running(sdata)) { + sdata->vif.bss_conf.idle = true; + continue; + } + + sdata->old_idle = sdata->vif.bss_conf.idle; + + /* do not count disabled managed interfaces */ + if (sdata->vif.type == NL80211_IFTYPE_STATION && + !sdata->u.mgd.associated && + !sdata->u.mgd.auth_data && + !sdata->u.mgd.assoc_data) { + sdata->vif.bss_conf.idle = true; + continue; + } + /* do not count unused IBSS interfaces */ + if (sdata->vif.type == NL80211_IFTYPE_ADHOC && + !sdata->u.ibss.ssid_len) { + sdata->vif.bss_conf.idle = true; + continue; + } + /* count everything else */ + sdata->vif.bss_conf.idle = false; + count++; + } + + if (!local->ops->remain_on_channel) { + list_for_each_entry(roc, &local->roc_list, list) { + working = true; + roc->sdata->vif.bss_conf.idle = false; + } + } + + if (local->scan_sdata && + !(local->hw.flags & IEEE80211_HW_SCAN_WHILE_IDLE)) { + scanning = true; + local->scan_sdata->vif.bss_conf.idle = false; + } + + list_for_each_entry(sdata, &local->interfaces, list) { + if (sdata->vif.type == NL80211_IFTYPE_MONITOR || + sdata->vif.type == NL80211_IFTYPE_AP_VLAN) + continue; + if (sdata->old_idle == sdata->vif.bss_conf.idle) + continue; + if (!ieee80211_sdata_running(sdata)) + continue; + ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_IDLE); + } + + if (working || scanning) + led_trig_start |= IEEE80211_TPT_LEDTRIG_FL_WORK; + else + led_trig_stop |= IEEE80211_TPT_LEDTRIG_FL_WORK; + + if (count) + led_trig_start |= IEEE80211_TPT_LEDTRIG_FL_CONNECTED; + else + led_trig_stop |= IEEE80211_TPT_LEDTRIG_FL_CONNECTED; + + ieee80211_mod_tpt_led_trig(local, led_trig_start, led_trig_stop); + + if (working) + return ieee80211_idle_off(local, "working"); + if (scanning) + return ieee80211_idle_off(local, "scanning"); + if (!count) + return ieee80211_idle_on(local); + else + return ieee80211_idle_off(local, "in use"); + + return 0; +} + +void ieee80211_recalc_idle(struct ieee80211_local *local) +{ + u32 chg; + + mutex_lock(&local->iflist_mtx); + chg = __ieee80211_recalc_idle(local); + mutex_unlock(&local->iflist_mtx); + if (chg) + ieee80211_hw_config(local, chg); +} + static int netdev_notify(struct notifier_block *nb, unsigned long state, void *ndev) diff --git a/trunk/net/mac80211/main.c b/trunk/net/mac80211/main.c index c794101f8987..0b040fb73673 100644 --- a/trunk/net/mac80211/main.c +++ b/trunk/net/mac80211/main.c @@ -587,7 +587,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, local->hw.priv = (char *)local + ALIGN(sizeof(*local), NETDEV_ALIGN); - BUG_ON(!ops->tx); + BUG_ON(!ops->tx && !ops->tx_frags); BUG_ON(!ops->start); BUG_ON(!ops->stop); BUG_ON(!ops->config); @@ -688,7 +688,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) int result, i; enum ieee80211_band band; int channels, max_bitrates; - bool supp_ht, supp_vht; + bool supp_ht; netdev_features_t feature_whitelist; static const u32 cipher_suites[] = { /* keep WEP first, it may be removed below */ @@ -706,11 +706,12 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) local->hw.offchannel_tx_hw_queue >= local->hw.queues)) return -EINVAL; + if ((hw->wiphy->wowlan.flags || hw->wiphy->wowlan.n_patterns) #ifdef CONFIG_PM - if ((hw->wiphy->wowlan.flags || hw->wiphy->wowlan.n_patterns) && - (!local->ops->suspend || !local->ops->resume)) - return -EINVAL; + && (!local->ops->suspend || !local->ops->resume) #endif + ) + return -EINVAL; if ((hw->flags & IEEE80211_HW_SCAN_WHILE_IDLE) && !local->ops->hw_scan) return -EINVAL; @@ -732,7 +733,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) channels = 0; max_bitrates = 0; supp_ht = false; - supp_vht = false; for (band = 0; band < IEEE80211_NUM_BANDS; band++) { struct ieee80211_supported_band *sband; @@ -750,7 +750,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) if (max_bitrates < sband->n_bitrates) max_bitrates = sband->n_bitrates; supp_ht = supp_ht || sband->ht_cap.ht_supported; - supp_vht = supp_vht || sband->vht_cap.vht_supported; } local->int_scan_req = kzalloc(sizeof(*local->int_scan_req) + @@ -826,10 +825,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) if (supp_ht) local->scan_ies_len += 2 + sizeof(struct ieee80211_ht_cap); - if (supp_vht) - local->scan_ies_len += - 2 + sizeof(struct ieee80211_vht_capabilities); - if (!local->ops->hw_scan) { /* For hw_scan, driver needs to set these up. */ local->hw.wiphy->max_scan_ssids = 4; diff --git a/trunk/net/mac80211/mesh.c b/trunk/net/mac80211/mesh.c index 6fac18c0423f..764593d65fc3 100644 --- a/trunk/net/mac80211/mesh.c +++ b/trunk/net/mac80211/mesh.c @@ -133,7 +133,7 @@ bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie) } /** - * mesh_accept_plinks_update - update accepting_plink in local mesh beacons + * mesh_accept_plinks_update: update accepting_plink in local mesh beacons * * @sdata: mesh interface in which mesh beacons are going to be updated */ diff --git a/trunk/net/mac80211/mesh_hwmp.c b/trunk/net/mac80211/mesh_hwmp.c index 494bc39f61a4..fb7b6a11d0ba 100644 --- a/trunk/net/mac80211/mesh_hwmp.c +++ b/trunk/net/mac80211/mesh_hwmp.c @@ -1054,15 +1054,12 @@ void mesh_path_start_discovery(struct ieee80211_sub_if_data *sdata) kfree(preq_node); } -/** - * mesh_nexthop_resolve - lookup next hop; conditionally start path discovery +/* mesh_nexthop_resolve - lookup next hop for given skb and start path + * discovery if no forwarding information is found. * * @skb: 802.11 frame to be sent * @sdata: network subif the frame will be sent through * - * Lookup next hop for given skb and start path discovery if no - * forwarding information is found. - * * Returns: 0 if the next hop was found and -ENOENT if the frame was queued. * skb is freeed here if no mpath could be allocated. */ diff --git a/trunk/net/mac80211/mesh_pathtbl.c b/trunk/net/mac80211/mesh_pathtbl.c index 075bc535c601..c9ae931dd693 100644 --- a/trunk/net/mac80211/mesh_pathtbl.c +++ b/trunk/net/mac80211/mesh_pathtbl.c @@ -778,7 +778,7 @@ static void __mesh_path_del(struct mesh_table *tbl, struct mpath_node *node) /** * mesh_path_flush_by_nexthop - Deletes mesh paths if their next hop matches * - * @sta: mesh peer to match + * @sta - mesh peer to match * * RCU notes: this function is called when a mesh plink transitions from * PLINK_ESTAB to any other state, since PLINK_ESTAB state is the only one that @@ -833,7 +833,7 @@ static void table_flush_by_iface(struct mesh_table *tbl, * * This function deletes both mesh paths as well as mesh portal paths. * - * @sdata: interface data to match + * @sdata - interface data to match * */ void mesh_path_flush_by_iface(struct ieee80211_sub_if_data *sdata) diff --git a/trunk/net/mac80211/mesh_plink.c b/trunk/net/mac80211/mesh_plink.c index af671b984df3..a1dbd1540276 100644 --- a/trunk/net/mac80211/mesh_plink.c +++ b/trunk/net/mac80211/mesh_plink.c @@ -99,7 +99,7 @@ static struct sta_info *mesh_plink_alloc(struct ieee80211_sub_if_data *sdata, return sta; } -/** +/* * mesh_set_ht_prot_mode - set correct HT protection mode * * Section 9.23.3.5 of IEEE 80211-2012 describes the protection rules for HT @@ -258,8 +258,8 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, pos = skb_put(skb, 2); memcpy(pos + 2, &plid, 2); } - if (ieee80211_add_srates_ie(sdata, skb, true) || - ieee80211_add_ext_srates_ie(sdata, skb, true) || + if (ieee80211_add_srates_ie(&sdata->vif, skb, true) || + ieee80211_add_ext_srates_ie(&sdata->vif, skb, true) || mesh_add_rsn_ie(skb, sdata) || mesh_add_meshid_ie(skb, sdata) || mesh_add_meshconf_ie(skb, sdata)) @@ -320,8 +320,7 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, return 0; } -/** - * mesh_peer_init - initialize new mesh peer and return resulting sta_info +/* mesh_peer_init - initialize new mesh peer and return resulting sta_info * * @sdata: local meshif * @addr: peer's address diff --git a/trunk/net/mac80211/mlme.c b/trunk/net/mac80211/mlme.c index f49f14f8ba82..e6fe84a08443 100644 --- a/trunk/net/mac80211/mlme.c +++ b/trunk/net/mac80211/mlme.c @@ -541,8 +541,6 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) memcpy(pos, assoc_data->ie + offset, noffset - offset); } - drv_mgd_prepare_tx(local, sdata); - IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; ieee80211_tx_skb(sdata, skb); } @@ -582,9 +580,6 @@ static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata, if (!(ifmgd->flags & IEEE80211_STA_MFP_ENABLED)) IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; - - drv_mgd_prepare_tx(local, sdata); - ieee80211_tx_skb(sdata, skb); } } @@ -907,6 +902,9 @@ static bool ieee80211_powersave_allowed(struct ieee80211_sub_if_data *sdata) if (!mgd->associated) return false; + if (!mgd->associated->beacon_ies) + return false; + if (mgd->flags & (IEEE80211_STA_BEACON_POLL | IEEE80211_STA_CONNECTION_POLL)) return false; @@ -1364,10 +1362,6 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, } mutex_unlock(&local->sta_mtx); - /* flush out any pending frame (e.g. DELBA) before deauth/disassoc */ - if (tx) - drv_flush(local, false); - /* deauthenticate/disassociate now */ if (tx || frame_buf) ieee80211_send_deauth_disassoc(sdata, ifmgd->bssid, stype, @@ -1616,7 +1610,6 @@ struct sk_buff *ieee80211_ap_probereq_get(struct ieee80211_hw *hw, { struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; - struct cfg80211_bss *cbss; struct sk_buff *skb; const u8 *ssid; int ssid_len; @@ -1626,22 +1619,16 @@ struct sk_buff *ieee80211_ap_probereq_get(struct ieee80211_hw *hw, ASSERT_MGD_MTX(ifmgd); - if (ifmgd->associated) - cbss = ifmgd->associated; - else if (ifmgd->auth_data) - cbss = ifmgd->auth_data->bss; - else if (ifmgd->assoc_data) - cbss = ifmgd->assoc_data->bss; - else + if (!ifmgd->associated) return NULL; - ssid = ieee80211_bss_get_ie(cbss, WLAN_EID_SSID); + ssid = ieee80211_bss_get_ie(ifmgd->associated, WLAN_EID_SSID); if (WARN_ON_ONCE(ssid == NULL)) ssid_len = 0; else ssid_len = ssid[1]; - skb = ieee80211_build_probe_req(sdata, cbss->bssid, + skb = ieee80211_build_probe_req(sdata, ifmgd->associated->bssid, (u32) -1, ssid + 2, ssid_len, NULL, 0, true); @@ -1760,7 +1747,6 @@ static void ieee80211_auth_challenge(struct ieee80211_sub_if_data *sdata, if (!elems.challenge) return; auth_data->expected_transaction = 4; - drv_mgd_prepare_tx(sdata->local, sdata); ieee80211_send_auth(sdata, 3, auth_data->algorithm, elems.challenge - 2, elems.challenge_len + 2, auth_data->bss->bssid, auth_data->bss->bssid, @@ -2166,13 +2152,15 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, mgmt->sa, status_code); ieee80211_destroy_assoc_data(sdata, false); } else { + sdata_info(sdata, "associated\n"); + if (!ieee80211_assoc_success(sdata, *bss, mgmt, len)) { /* oops -- internal error -- send timeout for now */ - ieee80211_destroy_assoc_data(sdata, false); + ieee80211_destroy_assoc_data(sdata, true); + sta_info_destroy_addr(sdata, mgmt->bssid); cfg80211_put_bss(*bss); return RX_MGMT_CFG80211_ASSOC_TIMEOUT; } - sdata_info(sdata, "associated\n"); /* * destroy assoc_data afterwards, as otherwise an idle @@ -2644,8 +2632,6 @@ static int ieee80211_probe_auth(struct ieee80211_sub_if_data *sdata) return -ETIMEDOUT; } - drv_mgd_prepare_tx(local, sdata); - if (auth_data->bss->proberesp_ies) { sdata_info(sdata, "send auth to %pM (try %d/%d)\n", auth_data->bss->bssid, auth_data->tries, diff --git a/trunk/net/mac80211/rc80211_minstrel_ht.c b/trunk/net/mac80211/rc80211_minstrel_ht.c index f9e51ef8dfa2..2d1acc6c5445 100644 --- a/trunk/net/mac80211/rc80211_minstrel_ht.c +++ b/trunk/net/mac80211/rc80211_minstrel_ht.c @@ -809,7 +809,7 @@ minstrel_ht_alloc_sta(void *priv, struct ieee80211_sta *sta, gfp_t gfp) max_rates = sband->n_bitrates; } - msp = kzalloc(sizeof(*msp), gfp); + msp = kzalloc(sizeof(struct minstrel_ht_sta), gfp); if (!msp) return NULL; diff --git a/trunk/net/mac80211/rx.c b/trunk/net/mac80211/rx.c index 67edd69e8421..839cac8fab57 100644 --- a/trunk/net/mac80211/rx.c +++ b/trunk/net/mac80211/rx.c @@ -94,7 +94,7 @@ ieee80211_rx_radiotap_len(struct ieee80211_local *local, return len; } -/** +/* * ieee80211_add_rx_radiotap_header - add radiotap header * * add a radiotap header containing all the fields which the hardware provided. diff --git a/trunk/net/mac80211/trace.h b/trunk/net/mac80211/trace.h index e1e9d10ec2e7..2e60f4acd027 100644 --- a/trunk/net/mac80211/trace.h +++ b/trunk/net/mac80211/trace.h @@ -1244,13 +1244,6 @@ TRACE_EVENT(drv_get_rssi, ) ); -DEFINE_EVENT(local_sdata_evt, drv_mgd_prepare_tx, - TP_PROTO(struct ieee80211_local *local, - struct ieee80211_sub_if_data *sdata), - - TP_ARGS(local, sdata) -); - /* * Tracing for API calls that drivers call. */ diff --git a/trunk/net/mac80211/tx.c b/trunk/net/mac80211/tx.c index c9d2175d15c1..ec8f53467374 100644 --- a/trunk/net/mac80211/tx.c +++ b/trunk/net/mac80211/tx.c @@ -140,8 +140,6 @@ static __le16 ieee80211_duration(struct ieee80211_tx_data *tx, if (r->flags & IEEE80211_RATE_MANDATORY_A) mrate = r->bitrate; break; - case IEEE80211_BAND_60GHZ: - /* TODO, for now fall through */ case IEEE80211_NUM_BANDS: WARN_ON(1); break; @@ -959,7 +957,8 @@ ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx) info->control.rates[1].idx = -1; info->control.rates[2].idx = -1; info->control.rates[3].idx = -1; - BUILD_BUG_ON(IEEE80211_TX_MAX_RATES != 4); + info->control.rates[4].idx = -1; + BUILD_BUG_ON(IEEE80211_TX_MAX_RATES != 5); info->flags &= ~IEEE80211_TX_CTL_RATE_CTRL_PROBE; } else { hdr->frame_control &= ~morefrags; @@ -1294,8 +1293,11 @@ static bool __ieee80211_tx(struct ieee80211_local *local, break; } - result = ieee80211_tx_frags(local, vif, pubsta, skbs, - txpending); + if (local->ops->tx_frags) + drv_tx_frags(local, vif, pubsta, skbs); + else + result = ieee80211_tx_frags(local, vif, pubsta, skbs, + txpending); ieee80211_tpt_led_trig_tx(local, fc, led_len); ieee80211_led_tx(local, 1); @@ -2418,9 +2420,9 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, *pos++ = WLAN_EID_SSID; *pos++ = 0x0; - if (ieee80211_add_srates_ie(sdata, skb, true) || + if (ieee80211_add_srates_ie(&sdata->vif, skb, true) || mesh_add_ds_params_ie(skb, sdata) || - ieee80211_add_ext_srates_ie(sdata, skb, true) || + ieee80211_add_ext_srates_ie(&sdata->vif, skb, true) || mesh_add_rsn_ie(skb, sdata) || mesh_add_ht_cap_ie(skb, sdata) || mesh_add_ht_oper_ie(skb, sdata) || diff --git a/trunk/net/mac80211/util.c b/trunk/net/mac80211/util.c index 64493a7bef1a..242ecde381f6 100644 --- a/trunk/net/mac80211/util.c +++ b/trunk/net/mac80211/util.c @@ -268,10 +268,6 @@ EXPORT_SYMBOL(ieee80211_ctstoself_duration); void ieee80211_propagate_queue_wake(struct ieee80211_local *local, int queue) { struct ieee80211_sub_if_data *sdata; - int n_acs = IEEE80211_NUM_ACS; - - if (local->hw.queues < IEEE80211_NUM_ACS) - n_acs = 1; list_for_each_entry_rcu(sdata, &local->interfaces, list) { int ac; @@ -283,7 +279,7 @@ void ieee80211_propagate_queue_wake(struct ieee80211_local *local, int queue) local->queue_stop_reasons[sdata->vif.cab_queue] != 0) continue; - for (ac = 0; ac < n_acs; ac++) { + for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { int ac_queue = sdata->vif.hw_queue[ac]; if (ac_queue == queue || @@ -345,7 +341,6 @@ static void __ieee80211_stop_queue(struct ieee80211_hw *hw, int queue, { struct ieee80211_local *local = hw_to_local(hw); struct ieee80211_sub_if_data *sdata; - int n_acs = IEEE80211_NUM_ACS; trace_stop_queue(local, queue, reason); @@ -357,14 +352,11 @@ static void __ieee80211_stop_queue(struct ieee80211_hw *hw, int queue, __set_bit(reason, &local->queue_stop_reasons[queue]); - if (local->hw.queues < IEEE80211_NUM_ACS) - n_acs = 1; - rcu_read_lock(); list_for_each_entry_rcu(sdata, &local->interfaces, list) { int ac; - for (ac = 0; ac < n_acs; ac++) { + for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { if (sdata->vif.hw_queue[ac] == queue || sdata->vif.cab_queue == queue) netif_stop_subqueue(sdata->dev, ac); @@ -1080,10 +1072,6 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, pos += noffset - offset; } - if (sband->vht_cap.vht_supported) - pos = ieee80211_ie_build_vht_cap(pos, &sband->vht_cap, - sband->vht_cap.cap); - return pos - buffer; } @@ -1423,10 +1411,10 @@ int ieee80211_reconfig(struct ieee80211_local *local) if (ieee80211_sdata_running(sdata)) ieee80211_enable_keys(sdata); - wake_up: local->in_reconfig = false; barrier(); + wake_up: /* * Clear the WLAN_STA_BLOCK_BA flag so new aggregation * sessions can be established after a resume. @@ -1711,27 +1699,6 @@ u8 *ieee80211_ie_build_ht_cap(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap, return pos; } -u8 *ieee80211_ie_build_vht_cap(u8 *pos, struct ieee80211_sta_vht_cap *vht_cap, - u32 cap) -{ - __le32 tmp; - - *pos++ = WLAN_EID_VHT_CAPABILITY; - *pos++ = sizeof(struct ieee80211_vht_capabilities); - memset(pos, 0, sizeof(struct ieee80211_vht_capabilities)); - - /* capability flags */ - tmp = cpu_to_le32(cap); - memcpy(pos, &tmp, sizeof(u32)); - pos += sizeof(u32); - - /* VHT MCS set */ - memcpy(pos, &vht_cap->vht_mcs, sizeof(vht_cap->vht_mcs)); - pos += sizeof(vht_cap->vht_mcs); - - return pos; -} - u8 *ieee80211_ie_build_ht_oper(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap, struct ieee80211_channel *channel, enum nl80211_channel_type channel_type, @@ -1797,14 +1764,15 @@ ieee80211_ht_oper_to_channel_type(struct ieee80211_ht_operation *ht_oper) return channel_type; } -int ieee80211_add_srates_ie(struct ieee80211_sub_if_data *sdata, +int ieee80211_add_srates_ie(struct ieee80211_vif *vif, struct sk_buff *skb, bool need_basic) { + struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); struct ieee80211_local *local = sdata->local; struct ieee80211_supported_band *sband; int rate; u8 i, rates, *pos; - u32 basic_rates = sdata->vif.bss_conf.basic_rates; + u32 basic_rates = vif->bss_conf.basic_rates; sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; rates = sband->n_bitrates; @@ -1828,14 +1796,15 @@ int ieee80211_add_srates_ie(struct ieee80211_sub_if_data *sdata, return 0; } -int ieee80211_add_ext_srates_ie(struct ieee80211_sub_if_data *sdata, +int ieee80211_add_ext_srates_ie(struct ieee80211_vif *vif, struct sk_buff *skb, bool need_basic) { + struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); struct ieee80211_local *local = sdata->local; struct ieee80211_supported_band *sband; int rate; u8 i, exrates, *pos; - u32 basic_rates = sdata->vif.bss_conf.basic_rates; + u32 basic_rates = vif->bss_conf.basic_rates; sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; exrates = sband->n_bitrates; diff --git a/trunk/net/mac802154/mac802154.h b/trunk/net/mac802154/mac802154.h index a4dcaf1dd4b6..69678644a5c2 100644 --- a/trunk/net/mac802154/mac802154.h +++ b/trunk/net/mac802154/mac802154.h @@ -109,7 +109,6 @@ netdev_tx_t mac802154_tx(struct mac802154_priv *priv, struct sk_buff *skb, /* MIB callbacks */ void mac802154_dev_set_short_addr(struct net_device *dev, u16 val); -u16 mac802154_dev_get_short_addr(const struct net_device *dev); void mac802154_dev_set_ieee_addr(struct net_device *dev); u16 mac802154_dev_get_pan_id(const struct net_device *dev); void mac802154_dev_set_pan_id(struct net_device *dev, u16 val); diff --git a/trunk/net/mac802154/mac_cmd.c b/trunk/net/mac802154/mac_cmd.c index d8d277006089..7f5403e5ea91 100644 --- a/trunk/net/mac802154/mac_cmd.c +++ b/trunk/net/mac802154/mac_cmd.c @@ -55,7 +55,7 @@ static int mac802154_mlme_start_req(struct net_device *dev, return 0; } -static struct wpan_phy *mac802154_get_phy(const struct net_device *dev) +struct wpan_phy *mac802154_get_phy(const struct net_device *dev) { struct mac802154_sub_if_data *priv = netdev_priv(dev); @@ -71,6 +71,4 @@ struct ieee802154_reduced_mlme_ops mac802154_mlme_reduced = { struct ieee802154_mlme_ops mac802154_mlme_wpan = { .get_phy = mac802154_get_phy, .start_req = mac802154_mlme_start_req, - .get_pan_id = mac802154_dev_get_pan_id, - .get_short_addr = mac802154_dev_get_short_addr, }; diff --git a/trunk/net/mac802154/mib.c b/trunk/net/mac802154/mib.c index f47781ab0ccc..380829d84600 100644 --- a/trunk/net/mac802154/mib.c +++ b/trunk/net/mac802154/mib.c @@ -39,7 +39,7 @@ struct hw_addr_filt_notify_work { unsigned long changed; }; -static struct mac802154_priv *mac802154_slave_get_priv(struct net_device *dev) +struct mac802154_priv *mac802154_slave_get_priv(struct net_device *dev) { struct mac802154_sub_if_data *priv = netdev_priv(dev); @@ -100,20 +100,6 @@ void mac802154_dev_set_short_addr(struct net_device *dev, u16 val) } } -u16 mac802154_dev_get_short_addr(const struct net_device *dev) -{ - struct mac802154_sub_if_data *priv = netdev_priv(dev); - u16 ret; - - BUG_ON(dev->type != ARPHRD_IEEE802154); - - spin_lock_bh(&priv->mib_lock); - ret = priv->short_addr; - spin_unlock_bh(&priv->mib_lock); - - return ret; -} - void mac802154_dev_set_ieee_addr(struct net_device *dev) { struct mac802154_sub_if_data *priv = netdev_priv(dev); diff --git a/trunk/net/netfilter/ipvs/ip_vs_xmit.c b/trunk/net/netfilter/ipvs/ip_vs_xmit.c index 65b616ae1716..71d6ecb65926 100644 --- a/trunk/net/netfilter/ipvs/ip_vs_xmit.c +++ b/trunk/net/netfilter/ipvs/ip_vs_xmit.c @@ -797,7 +797,7 @@ ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, goto tx_error_put; } if (skb_dst(skb)) - skb_dst(skb)->ops->update_pmtu(skb_dst(skb), NULL, skb, mtu); + skb_dst(skb)->ops->update_pmtu(skb_dst(skb), mtu); df |= (old_iph->frag_off & htons(IP_DF)); @@ -913,7 +913,7 @@ ip_vs_tunnel_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, goto tx_error_put; } if (skb_dst(skb)) - skb_dst(skb)->ops->update_pmtu(skb_dst(skb), NULL, skb, mtu); + skb_dst(skb)->ops->update_pmtu(skb_dst(skb), mtu); if (mtu < ntohs(old_iph->payload_len) + sizeof(struct ipv6hdr) && !skb_is_gso(skb)) { diff --git a/trunk/net/netfilter/nf_conntrack_netlink.c b/trunk/net/netfilter/nf_conntrack_netlink.c index 14f67a2cbcb5..b9b8f4ac7a36 100644 --- a/trunk/net/netfilter/nf_conntrack_netlink.c +++ b/trunk/net/netfilter/nf_conntrack_netlink.c @@ -4,7 +4,7 @@ * (C) 2001 by Jay Schulist * (C) 2002-2006 by Harald Welte * (C) 2003 by Patrick Mchardy - * (C) 2005-2012 by Pablo Neira Ayuso + * (C) 2005-2011 by Pablo Neira Ayuso * * Initial connection tracking via netlink development funded and * generally made possible by Network Robots, Inc. (www.networkrobots.com) @@ -1627,155 +1627,6 @@ ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb, return err; } -static int -ctnetlink_ct_stat_cpu_fill_info(struct sk_buff *skb, u32 pid, u32 seq, - __u16 cpu, const struct ip_conntrack_stat *st) -{ - struct nlmsghdr *nlh; - struct nfgenmsg *nfmsg; - unsigned int flags = pid ? NLM_F_MULTI : 0, event; - - event = (NFNL_SUBSYS_CTNETLINK << 8 | IPCTNL_MSG_CT_GET_STATS_CPU); - nlh = nlmsg_put(skb, pid, seq, event, sizeof(*nfmsg), flags); - if (nlh == NULL) - goto nlmsg_failure; - - nfmsg = nlmsg_data(nlh); - nfmsg->nfgen_family = AF_UNSPEC; - nfmsg->version = NFNETLINK_V0; - nfmsg->res_id = htons(cpu); - - if (nla_put_be32(skb, CTA_STATS_SEARCHED, htonl(st->searched)) || - nla_put_be32(skb, CTA_STATS_FOUND, htonl(st->found)) || - nla_put_be32(skb, CTA_STATS_NEW, htonl(st->new)) || - nla_put_be32(skb, CTA_STATS_INVALID, htonl(st->invalid)) || - nla_put_be32(skb, CTA_STATS_IGNORE, htonl(st->ignore)) || - nla_put_be32(skb, CTA_STATS_DELETE, htonl(st->delete)) || - nla_put_be32(skb, CTA_STATS_DELETE_LIST, htonl(st->delete_list)) || - nla_put_be32(skb, CTA_STATS_INSERT, htonl(st->insert)) || - nla_put_be32(skb, CTA_STATS_INSERT_FAILED, - htonl(st->insert_failed)) || - nla_put_be32(skb, CTA_STATS_DROP, htonl(st->drop)) || - nla_put_be32(skb, CTA_STATS_EARLY_DROP, htonl(st->early_drop)) || - nla_put_be32(skb, CTA_STATS_ERROR, htonl(st->error)) || - nla_put_be32(skb, CTA_STATS_SEARCH_RESTART, - htonl(st->search_restart))) - goto nla_put_failure; - - nlmsg_end(skb, nlh); - return skb->len; - -nla_put_failure: -nlmsg_failure: - nlmsg_cancel(skb, nlh); - return -1; -} - -static int -ctnetlink_ct_stat_cpu_dump(struct sk_buff *skb, struct netlink_callback *cb) -{ - int cpu; - struct net *net = sock_net(skb->sk); - - if (cb->args[0] == nr_cpu_ids) - return 0; - - for (cpu = cb->args[0]; cpu < nr_cpu_ids; cpu++) { - const struct ip_conntrack_stat *st; - - if (!cpu_possible(cpu)) - continue; - - st = per_cpu_ptr(net->ct.stat, cpu); - if (ctnetlink_ct_stat_cpu_fill_info(skb, - NETLINK_CB(cb->skb).pid, - cb->nlh->nlmsg_seq, - cpu, st) < 0) - break; - } - cb->args[0] = cpu; - - return skb->len; -} - -static int -ctnetlink_stat_ct_cpu(struct sock *ctnl, struct sk_buff *skb, - const struct nlmsghdr *nlh, - const struct nlattr * const cda[]) -{ - if (nlh->nlmsg_flags & NLM_F_DUMP) { - struct netlink_dump_control c = { - .dump = ctnetlink_ct_stat_cpu_dump, - }; - return netlink_dump_start(ctnl, skb, nlh, &c); - } - - return 0; -} - -static int -ctnetlink_stat_ct_fill_info(struct sk_buff *skb, u32 pid, u32 seq, u32 type, - struct net *net) -{ - struct nlmsghdr *nlh; - struct nfgenmsg *nfmsg; - unsigned int flags = pid ? NLM_F_MULTI : 0, event; - unsigned int nr_conntracks = atomic_read(&net->ct.count); - - event = (NFNL_SUBSYS_CTNETLINK << 8 | IPCTNL_MSG_CT_GET_STATS); - nlh = nlmsg_put(skb, pid, seq, event, sizeof(*nfmsg), flags); - if (nlh == NULL) - goto nlmsg_failure; - - nfmsg = nlmsg_data(nlh); - nfmsg->nfgen_family = AF_UNSPEC; - nfmsg->version = NFNETLINK_V0; - nfmsg->res_id = 0; - - if (nla_put_be32(skb, CTA_STATS_GLOBAL_ENTRIES, htonl(nr_conntracks))) - goto nla_put_failure; - - nlmsg_end(skb, nlh); - return skb->len; - -nla_put_failure: -nlmsg_failure: - nlmsg_cancel(skb, nlh); - return -1; -} - -static int -ctnetlink_stat_ct(struct sock *ctnl, struct sk_buff *skb, - const struct nlmsghdr *nlh, - const struct nlattr * const cda[]) -{ - struct sk_buff *skb2; - int err; - - skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); - if (skb2 == NULL) - return -ENOMEM; - - err = ctnetlink_stat_ct_fill_info(skb2, NETLINK_CB(skb).pid, - nlh->nlmsg_seq, - NFNL_MSG_TYPE(nlh->nlmsg_type), - sock_net(skb->sk)); - if (err <= 0) - goto free; - - err = netlink_unicast(ctnl, skb2, NETLINK_CB(skb).pid, MSG_DONTWAIT); - if (err < 0) - goto out; - - return 0; - -free: - kfree_skb(skb2); -out: - /* this avoids a loop in nfnetlink. */ - return err == -EAGAIN ? -ENOBUFS : err; -} - #ifdef CONFIG_NETFILTER_NETLINK_QUEUE_CT static size_t ctnetlink_nfqueue_build_size(const struct nf_conn *ct) @@ -2589,79 +2440,6 @@ ctnetlink_new_expect(struct sock *ctnl, struct sk_buff *skb, return err; } -static int -ctnetlink_exp_stat_fill_info(struct sk_buff *skb, u32 pid, u32 seq, int cpu, - const struct ip_conntrack_stat *st) -{ - struct nlmsghdr *nlh; - struct nfgenmsg *nfmsg; - unsigned int flags = pid ? NLM_F_MULTI : 0, event; - - event = (NFNL_SUBSYS_CTNETLINK << 8 | IPCTNL_MSG_EXP_GET_STATS_CPU); - nlh = nlmsg_put(skb, pid, seq, event, sizeof(*nfmsg), flags); - if (nlh == NULL) - goto nlmsg_failure; - - nfmsg = nlmsg_data(nlh); - nfmsg->nfgen_family = AF_UNSPEC; - nfmsg->version = NFNETLINK_V0; - nfmsg->res_id = htons(cpu); - - if (nla_put_be32(skb, CTA_STATS_EXP_NEW, htonl(st->expect_new)) || - nla_put_be32(skb, CTA_STATS_EXP_CREATE, htonl(st->expect_create)) || - nla_put_be32(skb, CTA_STATS_EXP_DELETE, htonl(st->expect_delete))) - goto nla_put_failure; - - nlmsg_end(skb, nlh); - return skb->len; - -nla_put_failure: -nlmsg_failure: - nlmsg_cancel(skb, nlh); - return -1; -} - -static int -ctnetlink_exp_stat_cpu_dump(struct sk_buff *skb, struct netlink_callback *cb) -{ - int cpu; - struct net *net = sock_net(skb->sk); - - if (cb->args[0] == nr_cpu_ids) - return 0; - - for (cpu = cb->args[0]; cpu < nr_cpu_ids; cpu++) { - const struct ip_conntrack_stat *st; - - if (!cpu_possible(cpu)) - continue; - - st = per_cpu_ptr(net->ct.stat, cpu); - if (ctnetlink_exp_stat_fill_info(skb, NETLINK_CB(cb->skb).pid, - cb->nlh->nlmsg_seq, - cpu, st) < 0) - break; - } - cb->args[0] = cpu; - - return skb->len; -} - -static int -ctnetlink_stat_exp_cpu(struct sock *ctnl, struct sk_buff *skb, - const struct nlmsghdr *nlh, - const struct nlattr * const cda[]) -{ - if (nlh->nlmsg_flags & NLM_F_DUMP) { - struct netlink_dump_control c = { - .dump = ctnetlink_exp_stat_cpu_dump, - }; - return netlink_dump_start(ctnl, skb, nlh, &c); - } - - return 0; -} - #ifdef CONFIG_NF_CONNTRACK_EVENTS static struct nf_ct_event_notifier ctnl_notifier = { .fcn = ctnetlink_conntrack_event, @@ -2685,8 +2463,6 @@ static const struct nfnl_callback ctnl_cb[IPCTNL_MSG_MAX] = { [IPCTNL_MSG_CT_GET_CTRZERO] = { .call = ctnetlink_get_conntrack, .attr_count = CTA_MAX, .policy = ct_nla_policy }, - [IPCTNL_MSG_CT_GET_STATS_CPU] = { .call = ctnetlink_stat_ct_cpu }, - [IPCTNL_MSG_CT_GET_STATS] = { .call = ctnetlink_stat_ct }, }; static const struct nfnl_callback ctnl_exp_cb[IPCTNL_MSG_EXP_MAX] = { @@ -2699,7 +2475,6 @@ static const struct nfnl_callback ctnl_exp_cb[IPCTNL_MSG_EXP_MAX] = { [IPCTNL_MSG_EXP_DELETE] = { .call = ctnetlink_del_expect, .attr_count = CTA_EXPECT_MAX, .policy = exp_nla_policy }, - [IPCTNL_MSG_EXP_GET_STATS_CPU] = { .call = ctnetlink_stat_exp_cpu }, }; static const struct nfnetlink_subsystem ctnl_subsys = { diff --git a/trunk/net/netfilter/nf_conntrack_proto.c b/trunk/net/netfilter/nf_conntrack_proto.c index 0dc63854390f..1ea919450fc3 100644 --- a/trunk/net/netfilter/nf_conntrack_proto.c +++ b/trunk/net/netfilter/nf_conntrack_proto.c @@ -39,13 +39,16 @@ static int nf_ct_register_sysctl(struct net *net, struct ctl_table_header **header, const char *path, - struct ctl_table *table) + struct ctl_table *table, + unsigned int *users) { if (*header == NULL) { *header = register_net_sysctl(net, path, table); if (*header == NULL) return -ENOMEM; } + if (users != NULL) + (*users)++; return 0; } @@ -53,9 +56,9 @@ nf_ct_register_sysctl(struct net *net, static void nf_ct_unregister_sysctl(struct ctl_table_header **header, struct ctl_table **table, - unsigned int users) + unsigned int *users) { - if (users > 0) + if (users != NULL && --*users > 0) return; unregister_net_sysctl_table(*header); @@ -188,7 +191,8 @@ static int nf_ct_l3proto_register_sysctl(struct net *net, err = nf_ct_register_sysctl(net, &in->ctl_table_header, l3proto->ctl_table_path, - in->ctl_table); + in->ctl_table, + NULL); if (err < 0) { kfree(in->ctl_table); in->ctl_table = NULL; @@ -209,7 +213,7 @@ static void nf_ct_l3proto_unregister_sysctl(struct net *net, if (in->ctl_table_header != NULL) nf_ct_unregister_sysctl(&in->ctl_table_header, &in->ctl_table, - 0); + NULL); #endif } @@ -249,23 +253,18 @@ int nf_conntrack_l3proto_register(struct net *net, { int ret = 0; - if (proto->init_net) { - ret = proto->init_net(net); - if (ret < 0) - return ret; - } + if (net == &init_net) + ret = nf_conntrack_l3proto_register_net(proto); - ret = nf_ct_l3proto_register_sysctl(net, proto); if (ret < 0) return ret; - if (net == &init_net) { - ret = nf_conntrack_l3proto_register_net(proto); + if (proto->init_net) { + ret = proto->init_net(net); if (ret < 0) - nf_ct_l3proto_unregister_sysctl(net, proto); + return ret; } - - return ret; + return nf_ct_l3proto_register_sysctl(net, proto); } EXPORT_SYMBOL_GPL(nf_conntrack_l3proto_register); @@ -303,77 +302,93 @@ EXPORT_SYMBOL_GPL(nf_conntrack_l3proto_unregister); static struct nf_proto_net *nf_ct_l4proto_net(struct net *net, struct nf_conntrack_l4proto *l4proto) { - if (l4proto->get_net_proto) { - /* statically built-in protocols use static per-net */ - return l4proto->get_net_proto(net); - } else if (l4proto->net_id) { - /* ... and loadable protocols use dynamic per-net */ - return net_generic(net, *l4proto->net_id); + switch (l4proto->l4proto) { + case IPPROTO_TCP: + return (struct nf_proto_net *)&net->ct.nf_ct_proto.tcp; + case IPPROTO_UDP: + return (struct nf_proto_net *)&net->ct.nf_ct_proto.udp; + case IPPROTO_ICMP: + return (struct nf_proto_net *)&net->ct.nf_ct_proto.icmp; + case IPPROTO_ICMPV6: + return (struct nf_proto_net *)&net->ct.nf_ct_proto.icmpv6; + case 255: /* l4proto_generic */ + return (struct nf_proto_net *)&net->ct.nf_ct_proto.generic; + default: + if (l4proto->net_id) + return net_generic(net, *l4proto->net_id); + else + return NULL; } return NULL; } static int nf_ct_l4proto_register_sysctl(struct net *net, - struct nf_proto_net *pn, struct nf_conntrack_l4proto *l4proto) { int err = 0; + struct nf_proto_net *pn = nf_ct_l4proto_net(net, l4proto); + if (pn == NULL) + return 0; #ifdef CONFIG_SYSCTL if (pn->ctl_table != NULL) { err = nf_ct_register_sysctl(net, &pn->ctl_table_header, "net/netfilter", - pn->ctl_table); + pn->ctl_table, + &pn->users); if (err < 0) { if (!pn->users) { kfree(pn->ctl_table); pn->ctl_table = NULL; } + goto out; } } #ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT if (l4proto->l3proto != AF_INET6 && pn->ctl_compat_table != NULL) { - if (err < 0) { - nf_ct_kfree_compat_sysctl_table(pn); - goto out; - } err = nf_ct_register_sysctl(net, &pn->ctl_compat_header, "net/ipv4/netfilter", - pn->ctl_compat_table); + pn->ctl_compat_table, + NULL); if (err == 0) goto out; - nf_ct_kfree_compat_sysctl_table(pn); + kfree(pn->ctl_compat_table); + pn->ctl_compat_table = NULL; nf_ct_unregister_sysctl(&pn->ctl_table_header, &pn->ctl_table, - pn->users); + &pn->users); } -out: #endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */ +out: #endif /* CONFIG_SYSCTL */ return err; } static void nf_ct_l4proto_unregister_sysctl(struct net *net, - struct nf_proto_net *pn, struct nf_conntrack_l4proto *l4proto) { + struct nf_proto_net *pn = nf_ct_l4proto_net(net, l4proto); + if (pn == NULL) + return; #ifdef CONFIG_SYSCTL if (pn->ctl_table_header != NULL) nf_ct_unregister_sysctl(&pn->ctl_table_header, &pn->ctl_table, - pn->users); + &pn->users); #ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT if (l4proto->l3proto != AF_INET6 && pn->ctl_compat_header != NULL) nf_ct_unregister_sysctl(&pn->ctl_compat_header, &pn->ctl_compat_table, - 0); + NULL); #endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */ +#else + pn->users--; #endif /* CONFIG_SYSCTL */ } @@ -439,33 +454,19 @@ int nf_conntrack_l4proto_register(struct net *net, struct nf_conntrack_l4proto *l4proto) { int ret = 0; - struct nf_proto_net *pn = NULL; + if (net == &init_net) + ret = nf_conntrack_l4proto_register_net(l4proto); - if (l4proto->init_net) { - ret = l4proto->init_net(net, l4proto->l3proto); - if (ret < 0) - goto out; - } + if (ret < 0) + return ret; - pn = nf_ct_l4proto_net(net, l4proto); - if (pn == NULL) - goto out; + if (l4proto->init_net) + ret = l4proto->init_net(net); - ret = nf_ct_l4proto_register_sysctl(net, pn, l4proto); if (ret < 0) - goto out; - - if (net == &init_net) { - ret = nf_conntrack_l4proto_register_net(l4proto); - if (ret < 0) { - nf_ct_l4proto_unregister_sysctl(net, pn, l4proto); - goto out; - } - } + return ret; - pn->users++; -out: - return ret; + return nf_ct_l4proto_register_sysctl(net, l4proto); } EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_register); @@ -489,18 +490,10 @@ nf_conntrack_l4proto_unregister_net(struct nf_conntrack_l4proto *l4proto) void nf_conntrack_l4proto_unregister(struct net *net, struct nf_conntrack_l4proto *l4proto) { - struct nf_proto_net *pn = NULL; - if (net == &init_net) nf_conntrack_l4proto_unregister_net(l4proto); - pn = nf_ct_l4proto_net(net, l4proto); - if (pn == NULL) - return; - - pn->users--; - nf_ct_l4proto_unregister_sysctl(net, pn, l4proto); - + nf_ct_l4proto_unregister_sysctl(net, l4proto); /* Remove all contrack entries for this protocol */ rtnl_lock(); nf_ct_iterate_cleanup(net, kill_l4proto, l4proto); @@ -512,15 +505,10 @@ int nf_conntrack_proto_init(struct net *net) { unsigned int i; int err; - struct nf_proto_net *pn = nf_ct_l4proto_net(net, - &nf_conntrack_l4proto_generic); - - err = nf_conntrack_l4proto_generic.init_net(net, - nf_conntrack_l4proto_generic.l3proto); + err = nf_conntrack_l4proto_generic.init_net(net); if (err < 0) return err; err = nf_ct_l4proto_register_sysctl(net, - pn, &nf_conntrack_l4proto_generic); if (err < 0) return err; @@ -530,20 +518,13 @@ int nf_conntrack_proto_init(struct net *net) rcu_assign_pointer(nf_ct_l3protos[i], &nf_conntrack_l3proto_generic); } - - pn->users++; return 0; } void nf_conntrack_proto_fini(struct net *net) { unsigned int i; - struct nf_proto_net *pn = nf_ct_l4proto_net(net, - &nf_conntrack_l4proto_generic); - - pn->users--; nf_ct_l4proto_unregister_sysctl(net, - pn, &nf_conntrack_l4proto_generic); if (net == &init_net) { /* free l3proto protocol tables */ diff --git a/trunk/net/netfilter/nf_conntrack_proto_dccp.c b/trunk/net/netfilter/nf_conntrack_proto_dccp.c index 6535326cf07c..c33f76af913f 100644 --- a/trunk/net/netfilter/nf_conntrack_proto_dccp.c +++ b/trunk/net/netfilter/nf_conntrack_proto_dccp.c @@ -387,7 +387,7 @@ dccp_state_table[CT_DCCP_ROLE_MAX + 1][DCCP_PKT_SYNCACK + 1][CT_DCCP_MAX + 1] = /* this module per-net specifics */ static int dccp_net_id __read_mostly; struct dccp_net { - struct nf_proto_net pn; + struct nf_proto_net np; int dccp_loose; unsigned int dccp_timeout[CT_DCCP_MAX + 1]; }; @@ -815,37 +815,16 @@ static struct ctl_table dccp_sysctl_table[] = { }; #endif /* CONFIG_SYSCTL */ -static int dccp_kmemdup_sysctl_table(struct nf_proto_net *pn, - struct dccp_net *dn) -{ -#ifdef CONFIG_SYSCTL - if (pn->ctl_table) - return 0; - - pn->ctl_table = kmemdup(dccp_sysctl_table, - sizeof(dccp_sysctl_table), - GFP_KERNEL); - if (!pn->ctl_table) - return -ENOMEM; - - pn->ctl_table[0].data = &dn->dccp_timeout[CT_DCCP_REQUEST]; - pn->ctl_table[1].data = &dn->dccp_timeout[CT_DCCP_RESPOND]; - pn->ctl_table[2].data = &dn->dccp_timeout[CT_DCCP_PARTOPEN]; - pn->ctl_table[3].data = &dn->dccp_timeout[CT_DCCP_OPEN]; - pn->ctl_table[4].data = &dn->dccp_timeout[CT_DCCP_CLOSEREQ]; - pn->ctl_table[5].data = &dn->dccp_timeout[CT_DCCP_CLOSING]; - pn->ctl_table[6].data = &dn->dccp_timeout[CT_DCCP_TIMEWAIT]; - pn->ctl_table[7].data = &dn->dccp_loose; -#endif - return 0; -} - -static int dccp_init_net(struct net *net, u_int16_t proto) +static int dccp_init_net(struct net *net) { struct dccp_net *dn = dccp_pernet(net); - struct nf_proto_net *pn = &dn->pn; + struct nf_proto_net *pn = (struct nf_proto_net *)dn; - if (!pn->users) { +#ifdef CONFIG_SYSCTL + if (!pn->ctl_table) { +#else + if (!pn->users++) { +#endif /* default values */ dn->dccp_loose = 1; dn->dccp_timeout[CT_DCCP_REQUEST] = 2 * DCCP_MSL; @@ -855,9 +834,24 @@ static int dccp_init_net(struct net *net, u_int16_t proto) dn->dccp_timeout[CT_DCCP_CLOSEREQ] = 64 * HZ; dn->dccp_timeout[CT_DCCP_CLOSING] = 64 * HZ; dn->dccp_timeout[CT_DCCP_TIMEWAIT] = 2 * DCCP_MSL; +#ifdef CONFIG_SYSCTL + pn->ctl_table = kmemdup(dccp_sysctl_table, + sizeof(dccp_sysctl_table), + GFP_KERNEL); + if (!pn->ctl_table) + return -ENOMEM; + + pn->ctl_table[0].data = &dn->dccp_timeout[CT_DCCP_REQUEST]; + pn->ctl_table[1].data = &dn->dccp_timeout[CT_DCCP_RESPOND]; + pn->ctl_table[2].data = &dn->dccp_timeout[CT_DCCP_PARTOPEN]; + pn->ctl_table[3].data = &dn->dccp_timeout[CT_DCCP_OPEN]; + pn->ctl_table[4].data = &dn->dccp_timeout[CT_DCCP_CLOSEREQ]; + pn->ctl_table[5].data = &dn->dccp_timeout[CT_DCCP_CLOSING]; + pn->ctl_table[6].data = &dn->dccp_timeout[CT_DCCP_TIMEWAIT]; + pn->ctl_table[7].data = &dn->dccp_loose; +#endif } - - return dccp_kmemdup_sysctl_table(pn, dn); + return 0; } static struct nf_conntrack_l4proto dccp_proto4 __read_mostly = { diff --git a/trunk/net/netfilter/nf_conntrack_proto_generic.c b/trunk/net/netfilter/nf_conntrack_proto_generic.c index d25f29377648..bb0e74fe0fae 100644 --- a/trunk/net/netfilter/nf_conntrack_proto_generic.c +++ b/trunk/net/netfilter/nf_conntrack_proto_generic.c @@ -135,62 +135,34 @@ static struct ctl_table generic_compat_sysctl_table[] = { #endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */ #endif /* CONFIG_SYSCTL */ -static int generic_kmemdup_sysctl_table(struct nf_proto_net *pn, - struct nf_generic_net *gn) +static int generic_init_net(struct net *net) { + struct nf_generic_net *gn = generic_pernet(net); + struct nf_proto_net *pn = (struct nf_proto_net *)gn; + gn->timeout = nf_ct_generic_timeout; #ifdef CONFIG_SYSCTL pn->ctl_table = kmemdup(generic_sysctl_table, sizeof(generic_sysctl_table), GFP_KERNEL); if (!pn->ctl_table) return -ENOMEM; - pn->ctl_table[0].data = &gn->timeout; -#endif - return 0; -} -static int generic_kmemdup_compat_sysctl_table(struct nf_proto_net *pn, - struct nf_generic_net *gn) -{ -#ifdef CONFIG_SYSCTL #ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT pn->ctl_compat_table = kmemdup(generic_compat_sysctl_table, sizeof(generic_compat_sysctl_table), GFP_KERNEL); - if (!pn->ctl_compat_table) + if (!pn->ctl_compat_table) { + kfree(pn->ctl_table); + pn->ctl_table = NULL; return -ENOMEM; - + } pn->ctl_compat_table[0].data = &gn->timeout; #endif #endif return 0; } -static int generic_init_net(struct net *net, u_int16_t proto) -{ - int ret; - struct nf_generic_net *gn = generic_pernet(net); - struct nf_proto_net *pn = &gn->pn; - - gn->timeout = nf_ct_generic_timeout; - - ret = generic_kmemdup_compat_sysctl_table(pn, gn); - if (ret < 0) - return ret; - - ret = generic_kmemdup_sysctl_table(pn, gn); - if (ret < 0) - nf_ct_kfree_compat_sysctl_table(pn); - - return ret; -} - -static struct nf_proto_net *generic_get_net_proto(struct net *net) -{ - return &net->ct.nf_ct_proto.generic.pn; -} - struct nf_conntrack_l4proto nf_conntrack_l4proto_generic __read_mostly = { .l3proto = PF_UNSPEC, @@ -212,5 +184,4 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_generic __read_mostly = }, #endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */ .init_net = generic_init_net, - .get_net_proto = generic_get_net_proto, }; diff --git a/trunk/net/netfilter/nf_conntrack_proto_gre.c b/trunk/net/netfilter/nf_conntrack_proto_gre.c index b09b7af7f6f8..5cac41c2fa09 100644 --- a/trunk/net/netfilter/nf_conntrack_proto_gre.c +++ b/trunk/net/netfilter/nf_conntrack_proto_gre.c @@ -348,7 +348,7 @@ gre_timeout_nla_policy[CTA_TIMEOUT_GRE_MAX+1] = { }; #endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */ -static int gre_init_net(struct net *net, u_int16_t proto) +static int gre_init_net(struct net *net) { struct netns_proto_gre *net_gre = gre_pernet(net); int i; diff --git a/trunk/net/netfilter/nf_conntrack_proto_sctp.c b/trunk/net/netfilter/nf_conntrack_proto_sctp.c index c746d61f83ed..8fb0582ad397 100644 --- a/trunk/net/netfilter/nf_conntrack_proto_sctp.c +++ b/trunk/net/netfilter/nf_conntrack_proto_sctp.c @@ -707,10 +707,23 @@ static struct ctl_table sctp_compat_sysctl_table[] = { #endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */ #endif -static int sctp_kmemdup_sysctl_table(struct nf_proto_net *pn, - struct sctp_net *sn) +static void sctp_init_net_data(struct sctp_net *sn) +{ + int i; +#ifdef CONFIG_SYSCTL + if (!sn->pn.ctl_table) { +#else + if (!sn->pn.users++) { +#endif + for (i = 0; i < SCTP_CONNTRACK_MAX; i++) + sn->timeouts[i] = sctp_timeouts[i]; + } +} + +static int sctp_kmemdup_sysctl_table(struct nf_proto_net *pn) { #ifdef CONFIG_SYSCTL + struct sctp_net *sn = (struct sctp_net *)pn; if (pn->ctl_table) return 0; @@ -731,11 +744,11 @@ static int sctp_kmemdup_sysctl_table(struct nf_proto_net *pn, return 0; } -static int sctp_kmemdup_compat_sysctl_table(struct nf_proto_net *pn, - struct sctp_net *sn) +static int sctp_kmemdup_compat_sysctl_table(struct nf_proto_net *pn) { #ifdef CONFIG_SYSCTL #ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT + struct sctp_net *sn = (struct sctp_net *)pn; pn->ctl_compat_table = kmemdup(sctp_compat_sysctl_table, sizeof(sctp_compat_sysctl_table), GFP_KERNEL); @@ -754,33 +767,41 @@ static int sctp_kmemdup_compat_sysctl_table(struct nf_proto_net *pn, return 0; } -static int sctp_init_net(struct net *net, u_int16_t proto) +static int sctpv4_init_net(struct net *net) { int ret; struct sctp_net *sn = sctp_pernet(net); - struct nf_proto_net *pn = &sn->pn; + struct nf_proto_net *pn = (struct nf_proto_net *)sn; - if (!pn->users) { - int i; + sctp_init_net_data(sn); - for (i = 0; i < SCTP_CONNTRACK_MAX; i++) - sn->timeouts[i] = sctp_timeouts[i]; - } + ret = sctp_kmemdup_compat_sysctl_table(pn); + if (ret < 0) + return ret; - if (proto == AF_INET) { - ret = sctp_kmemdup_compat_sysctl_table(pn, sn); - if (ret < 0) - return ret; + ret = sctp_kmemdup_sysctl_table(pn); - ret = sctp_kmemdup_sysctl_table(pn, sn); - if (ret < 0) - nf_ct_kfree_compat_sysctl_table(pn); - } else - ret = sctp_kmemdup_sysctl_table(pn, sn); +#ifdef CONFIG_SYSCTL +#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT + if (ret < 0) { + kfree(pn->ctl_compat_table); + pn->ctl_compat_table = NULL; + } +#endif +#endif return ret; } +static int sctpv6_init_net(struct net *net) +{ + struct sctp_net *sn = sctp_pernet(net); + struct nf_proto_net *pn = (struct nf_proto_net *)sn; + + sctp_init_net_data(sn); + return sctp_kmemdup_sysctl_table(pn); +} + static struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp4 __read_mostly = { .l3proto = PF_INET, .l4proto = IPPROTO_SCTP, @@ -812,7 +833,7 @@ static struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp4 __read_mostly = { }, #endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */ .net_id = &sctp_net_id, - .init_net = sctp_init_net, + .init_net = sctpv4_init_net, }; static struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp6 __read_mostly = { @@ -846,7 +867,7 @@ static struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp6 __read_mostly = { #endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */ #endif .net_id = &sctp_net_id, - .init_net = sctp_init_net, + .init_net = sctpv6_init_net, }; static int sctp_net_init(struct net *net) diff --git a/trunk/net/netfilter/nf_conntrack_proto_tcp.c b/trunk/net/netfilter/nf_conntrack_proto_tcp.c index a5ac11ebef33..99caa1304477 100644 --- a/trunk/net/netfilter/nf_conntrack_proto_tcp.c +++ b/trunk/net/netfilter/nf_conntrack_proto_tcp.c @@ -821,7 +821,7 @@ static int tcp_error(struct net *net, struct nf_conn *tmpl, static unsigned int *tcp_get_timeouts(struct net *net) { - return tcp_pernet(net)->timeouts; + return tcp_timeouts; } /* Returns verdict for packet, or -1 for invalid. */ @@ -1533,10 +1533,11 @@ static struct ctl_table tcp_compat_sysctl_table[] = { #endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */ #endif /* CONFIG_SYSCTL */ -static int tcp_kmemdup_sysctl_table(struct nf_proto_net *pn, - struct nf_tcp_net *tn) +static int tcp_kmemdup_sysctl_table(struct nf_proto_net *pn) { #ifdef CONFIG_SYSCTL + struct nf_tcp_net *tn = (struct nf_tcp_net *)pn; + if (pn->ctl_table) return 0; @@ -1563,11 +1564,11 @@ static int tcp_kmemdup_sysctl_table(struct nf_proto_net *pn, return 0; } -static int tcp_kmemdup_compat_sysctl_table(struct nf_proto_net *pn, - struct nf_tcp_net *tn) +static int tcp_kmemdup_compat_sysctl_table(struct nf_proto_net *pn) { #ifdef CONFIG_SYSCTL #ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT + struct nf_tcp_net *tn = (struct nf_tcp_net *)pn; pn->ctl_compat_table = kmemdup(tcp_compat_sysctl_table, sizeof(tcp_compat_sysctl_table), GFP_KERNEL); @@ -1592,15 +1593,18 @@ static int tcp_kmemdup_compat_sysctl_table(struct nf_proto_net *pn, return 0; } -static int tcp_init_net(struct net *net, u_int16_t proto) +static int tcpv4_init_net(struct net *net) { - int ret; + int i; + int ret = 0; struct nf_tcp_net *tn = tcp_pernet(net); - struct nf_proto_net *pn = &tn->pn; - - if (!pn->users) { - int i; + struct nf_proto_net *pn = (struct nf_proto_net *)tn; +#ifdef CONFIG_SYSCTL + if (!pn->ctl_table) { +#else + if (!pn->users++) { +#endif for (i = 0; i < TCP_CONNTRACK_TIMEOUT_MAX; i++) tn->timeouts[i] = tcp_timeouts[i]; @@ -1609,23 +1613,43 @@ static int tcp_init_net(struct net *net, u_int16_t proto) tn->tcp_max_retrans = nf_ct_tcp_max_retrans; } - if (proto == AF_INET) { - ret = tcp_kmemdup_compat_sysctl_table(pn, tn); - if (ret < 0) - return ret; + ret = tcp_kmemdup_compat_sysctl_table(pn); + + if (ret < 0) + return ret; - ret = tcp_kmemdup_sysctl_table(pn, tn); - if (ret < 0) - nf_ct_kfree_compat_sysctl_table(pn); - } else - ret = tcp_kmemdup_sysctl_table(pn, tn); + ret = tcp_kmemdup_sysctl_table(pn); +#ifdef CONFIG_SYSCTL +#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT + if (ret < 0) { + kfree(pn->ctl_compat_table); + pn->ctl_compat_table = NULL; + } +#endif +#endif return ret; } -static struct nf_proto_net *tcp_get_net_proto(struct net *net) +static int tcpv6_init_net(struct net *net) { - return &net->ct.nf_ct_proto.tcp.pn; + int i; + struct nf_tcp_net *tn = tcp_pernet(net); + struct nf_proto_net *pn = (struct nf_proto_net *)tn; + +#ifdef CONFIG_SYSCTL + if (!pn->ctl_table) { +#else + if (!pn->users++) { +#endif + for (i = 0; i < TCP_CONNTRACK_TIMEOUT_MAX; i++) + tn->timeouts[i] = tcp_timeouts[i]; + tn->tcp_loose = nf_ct_tcp_loose; + tn->tcp_be_liberal = nf_ct_tcp_be_liberal; + tn->tcp_max_retrans = nf_ct_tcp_max_retrans; + } + + return tcp_kmemdup_sysctl_table(pn); } struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp4 __read_mostly = @@ -1660,8 +1684,7 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp4 __read_mostly = .nla_policy = tcp_timeout_nla_policy, }, #endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */ - .init_net = tcp_init_net, - .get_net_proto = tcp_get_net_proto, + .init_net = tcpv4_init_net, }; EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_tcp4); @@ -1697,7 +1720,6 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp6 __read_mostly = .nla_policy = tcp_timeout_nla_policy, }, #endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */ - .init_net = tcp_init_net, - .get_net_proto = tcp_get_net_proto, + .init_net = tcpv6_init_net, }; EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_tcp6); diff --git a/trunk/net/netfilter/nf_conntrack_proto_udp.c b/trunk/net/netfilter/nf_conntrack_proto_udp.c index 59623cc56e8d..a83cf93545cd 100644 --- a/trunk/net/netfilter/nf_conntrack_proto_udp.c +++ b/trunk/net/netfilter/nf_conntrack_proto_udp.c @@ -235,10 +235,10 @@ static struct ctl_table udp_compat_sysctl_table[] = { #endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */ #endif /* CONFIG_SYSCTL */ -static int udp_kmemdup_sysctl_table(struct nf_proto_net *pn, - struct nf_udp_net *un) +static int udp_kmemdup_sysctl_table(struct nf_proto_net *pn) { #ifdef CONFIG_SYSCTL + struct nf_udp_net *un = (struct nf_udp_net *)pn; if (pn->ctl_table) return 0; pn->ctl_table = kmemdup(udp_sysctl_table, @@ -252,11 +252,11 @@ static int udp_kmemdup_sysctl_table(struct nf_proto_net *pn, return 0; } -static int udp_kmemdup_compat_sysctl_table(struct nf_proto_net *pn, - struct nf_udp_net *un) +static int udp_kmemdup_compat_sysctl_table(struct nf_proto_net *pn) { #ifdef CONFIG_SYSCTL #ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT + struct nf_udp_net *un = (struct nf_udp_net *)pn; pn->ctl_compat_table = kmemdup(udp_compat_sysctl_table, sizeof(udp_compat_sysctl_table), GFP_KERNEL); @@ -270,36 +270,50 @@ static int udp_kmemdup_compat_sysctl_table(struct nf_proto_net *pn, return 0; } -static int udp_init_net(struct net *net, u_int16_t proto) +static void udp_init_net_data(struct nf_udp_net *un) { - int ret; - struct nf_udp_net *un = udp_pernet(net); - struct nf_proto_net *pn = &un->pn; - - if (!pn->users) { - int i; - + int i; +#ifdef CONFIG_SYSCTL + if (!un->pn.ctl_table) { +#else + if (!un->pn.users++) { +#endif for (i = 0; i < UDP_CT_MAX; i++) un->timeouts[i] = udp_timeouts[i]; } +} + +static int udpv4_init_net(struct net *net) +{ + int ret; + struct nf_udp_net *un = udp_pernet(net); + struct nf_proto_net *pn = (struct nf_proto_net *)un; - if (proto == AF_INET) { - ret = udp_kmemdup_compat_sysctl_table(pn, un); - if (ret < 0) - return ret; + udp_init_net_data(un); - ret = udp_kmemdup_sysctl_table(pn, un); - if (ret < 0) - nf_ct_kfree_compat_sysctl_table(pn); - } else - ret = udp_kmemdup_sysctl_table(pn, un); + ret = udp_kmemdup_compat_sysctl_table(pn); + if (ret < 0) + return ret; + ret = udp_kmemdup_sysctl_table(pn); +#ifdef CONFIG_SYSCTL +#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT + if (ret < 0) { + kfree(pn->ctl_compat_table); + pn->ctl_compat_table = NULL; + } +#endif +#endif return ret; } -static struct nf_proto_net *udp_get_net_proto(struct net *net) +static int udpv6_init_net(struct net *net) { - return &net->ct.nf_ct_proto.udp.pn; + struct nf_udp_net *un = udp_pernet(net); + struct nf_proto_net *pn = (struct nf_proto_net *)un; + + udp_init_net_data(un); + return udp_kmemdup_sysctl_table(pn); } struct nf_conntrack_l4proto nf_conntrack_l4proto_udp4 __read_mostly = @@ -329,8 +343,7 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_udp4 __read_mostly = .nla_policy = udp_timeout_nla_policy, }, #endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */ - .init_net = udp_init_net, - .get_net_proto = udp_get_net_proto, + .init_net = udpv4_init_net, }; EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_udp4); @@ -361,7 +374,6 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_udp6 __read_mostly = .nla_policy = udp_timeout_nla_policy, }, #endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */ - .init_net = udp_init_net, - .get_net_proto = udp_get_net_proto, + .init_net = udpv6_init_net, }; EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_udp6); diff --git a/trunk/net/netfilter/nf_conntrack_proto_udplite.c b/trunk/net/netfilter/nf_conntrack_proto_udplite.c index 4b66df209286..b32e700f8dde 100644 --- a/trunk/net/netfilter/nf_conntrack_proto_udplite.c +++ b/trunk/net/netfilter/nf_conntrack_proto_udplite.c @@ -234,38 +234,29 @@ static struct ctl_table udplite_sysctl_table[] = { }; #endif /* CONFIG_SYSCTL */ -static int udplite_kmemdup_sysctl_table(struct nf_proto_net *pn, - struct udplite_net *un) +static int udplite_init_net(struct net *net) { + int i; + struct udplite_net *un = udplite_pernet(net); + struct nf_proto_net *pn = (struct nf_proto_net *)un; #ifdef CONFIG_SYSCTL - if (pn->ctl_table) - return 0; - - pn->ctl_table = kmemdup(udplite_sysctl_table, - sizeof(udplite_sysctl_table), - GFP_KERNEL); - if (!pn->ctl_table) - return -ENOMEM; - - pn->ctl_table[0].data = &un->timeouts[UDPLITE_CT_UNREPLIED]; - pn->ctl_table[1].data = &un->timeouts[UDPLITE_CT_REPLIED]; + if (!pn->ctl_table) { +#else + if (!pn->users++) { #endif - return 0; -} - -static int udplite_init_net(struct net *net, u_int16_t proto) -{ - struct udplite_net *un = udplite_pernet(net); - struct nf_proto_net *pn = &un->pn; - - if (!pn->users) { - int i; - for (i = 0 ; i < UDPLITE_CT_MAX; i++) un->timeouts[i] = udplite_timeouts[i]; +#ifdef CONFIG_SYSCTL + pn->ctl_table = kmemdup(udplite_sysctl_table, + sizeof(udplite_sysctl_table), + GFP_KERNEL); + if (!pn->ctl_table) + return -ENOMEM; + pn->ctl_table[0].data = &un->timeouts[UDPLITE_CT_UNREPLIED]; + pn->ctl_table[1].data = &un->timeouts[UDPLITE_CT_REPLIED]; +#endif } - - return udplite_kmemdup_sysctl_table(pn, un); + return 0; } static struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite4 __read_mostly = diff --git a/trunk/net/netfilter/nfnetlink.c b/trunk/net/netfilter/nfnetlink.c index a26503342e71..465539d43a0a 100644 --- a/trunk/net/netfilter/nfnetlink.c +++ b/trunk/net/netfilter/nfnetlink.c @@ -195,11 +195,9 @@ static int nfnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) lockdep_is_held(&nfnl_mutex)) != ss || nfnetlink_find_client(type, ss) != nc) err = -EAGAIN; - else if (nc->call) + else err = nc->call(net->nfnl, skb, nlh, (const struct nlattr **)cda); - else - err = -EINVAL; nfnl_unlock(); } if (err == -EAGAIN) diff --git a/trunk/net/netfilter/nfnetlink_queue_core.c b/trunk/net/netfilter/nfnetlink_queue_core.c index c0496a55ad0c..a0b64920039d 100644 --- a/trunk/net/netfilter/nfnetlink_queue_core.c +++ b/trunk/net/netfilter/nfnetlink_queue_core.c @@ -910,11 +910,6 @@ nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb, flags = ntohl(nla_get_be32(nfqa[NFQA_CFG_FLAGS])); mask = ntohl(nla_get_be32(nfqa[NFQA_CFG_MASK])); - if (flags >= NFQA_CFG_F_MAX) { - ret = -EOPNOTSUPP; - goto err_out_unlock; - } - spin_lock_bh(&queue->lock); queue->flags &= ~mask; queue->flags |= flags & mask; diff --git a/trunk/net/netfilter/xt_TPROXY.c b/trunk/net/netfilter/xt_TPROXY.c index d7f195388f66..146033a86de8 100644 --- a/trunk/net/netfilter/xt_TPROXY.c +++ b/trunk/net/netfilter/xt_TPROXY.c @@ -69,7 +69,7 @@ tproxy_laddr4(struct sk_buff *skb, __be32 user_laddr, __be32 daddr) } /** - * tproxy_handle_time_wait4 - handle IPv4 TCP TIME_WAIT reopen redirections + * tproxy_handle_time_wait4() - handle IPv4 TCP TIME_WAIT reopen redirections * @skb: The skb being processed. * @laddr: IPv4 address to redirect to or zero. * @lport: TCP port to redirect to or zero. @@ -220,7 +220,7 @@ tproxy_laddr6(struct sk_buff *skb, const struct in6_addr *user_laddr, } /** - * tproxy_handle_time_wait6 - handle IPv6 TCP TIME_WAIT reopen redirections + * tproxy_handle_time_wait6() - handle IPv6 TCP TIME_WAIT reopen redirections * @skb: The skb being processed. * @tproto: Transport protocol. * @thoff: Transport protocol header offset. diff --git a/trunk/net/netfilter/xt_set.c b/trunk/net/netfilter/xt_set.c index c6f7db720d84..035960ec5cb9 100644 --- a/trunk/net/netfilter/xt_set.c +++ b/trunk/net/netfilter/xt_set.c @@ -16,7 +16,6 @@ #include #include -#include MODULE_LICENSE("GPL"); MODULE_AUTHOR("Jozsef Kadlecsik "); @@ -311,8 +310,7 @@ set_target_v2(struct sk_buff *skb, const struct xt_action_param *par) info->del_set.flags, 0, UINT_MAX); /* Normalize to fit into jiffies */ - if (add_opt.timeout != IPSET_NO_TIMEOUT && - add_opt.timeout > UINT_MAX/MSEC_PER_SEC) + if (add_opt.timeout > UINT_MAX/MSEC_PER_SEC) add_opt.timeout = UINT_MAX/MSEC_PER_SEC; if (info->add_set.index != IPSET_INVALID_ID) ip_set_add(info->add_set.index, skb, par, &add_opt); diff --git a/trunk/net/netlink/genetlink.c b/trunk/net/netlink/genetlink.c index 62ebe3c6291c..32761b53015e 100644 --- a/trunk/net/netlink/genetlink.c +++ b/trunk/net/netlink/genetlink.c @@ -504,7 +504,7 @@ EXPORT_SYMBOL(genl_unregister_family); * @pid: netlink pid the message is addressed to * @seq: sequence number (usually the one of the sender) * @family: generic netlink family - * @flags: netlink message flags + * @flags netlink message flags * @cmd: generic netlink command * * Returns pointer to user specific header diff --git a/trunk/net/nfc/core.c b/trunk/net/nfc/core.c index ff749794bc5b..4177bb5104b9 100644 --- a/trunk/net/nfc/core.c +++ b/trunk/net/nfc/core.c @@ -29,8 +29,6 @@ #include #include -#include - #include "nfc.h" #define VERSION "0.1" @@ -562,8 +560,6 @@ EXPORT_SYMBOL(nfc_alloc_recv_skb); * The device driver must call this function when one or many nfc targets * are found. After calling this function, the device driver must stop * polling for targets. - * NOTE: This function can be called with targets=NULL and n_targets=0 to - * notify a driver error, meaning that the polling operation cannot complete. * IMPORTANT: this function must not be called from an atomic context. * In addition, it must also not be called from a context that would prevent * the NFC Core to call other nfc ops entry point concurrently. @@ -575,33 +571,23 @@ int nfc_targets_found(struct nfc_dev *dev, pr_debug("dev_name=%s n_targets=%d\n", dev_name(&dev->dev), n_targets); + dev->polling = false; + for (i = 0; i < n_targets; i++) targets[i].idx = dev->target_next_idx++; device_lock(&dev->dev); - if (dev->polling == false) { - device_unlock(&dev->dev); - return 0; - } - - dev->polling = false; - dev->targets_generation++; kfree(dev->targets); - dev->targets = NULL; + dev->targets = kmemdup(targets, n_targets * sizeof(struct nfc_target), + GFP_ATOMIC); - if (targets) { - dev->targets = kmemdup(targets, - n_targets * sizeof(struct nfc_target), - GFP_ATOMIC); - - if (!dev->targets) { - dev->n_targets = 0; - device_unlock(&dev->dev); - return -ENOMEM; - } + if (!dev->targets) { + dev->n_targets = 0; + device_unlock(&dev->dev); + return -ENOMEM; } dev->n_targets = n_targets; @@ -665,12 +651,6 @@ int nfc_target_lost(struct nfc_dev *dev, u32 target_idx) } EXPORT_SYMBOL(nfc_target_lost); -inline void nfc_driver_failure(struct nfc_dev *dev, int err) -{ - nfc_targets_found(dev, NULL, 0); -} -EXPORT_SYMBOL(nfc_driver_failure); - static void nfc_release(struct device *d) { struct nfc_dev *dev = to_nfc_dev(d); @@ -926,5 +906,3 @@ MODULE_AUTHOR("Lauro Ramos Venancio "); MODULE_DESCRIPTION("NFC Core ver " VERSION); MODULE_VERSION(VERSION); MODULE_LICENSE("GPL"); -MODULE_ALIAS_NETPROTO(PF_NFC); -MODULE_ALIAS_GENL_FAMILY(NFC_GENL_NAME); diff --git a/trunk/net/nfc/hci/command.c b/trunk/net/nfc/hci/command.c index 46362ef979db..8729abf5f18b 100644 --- a/trunk/net/nfc/hci/command.c +++ b/trunk/net/nfc/hci/command.c @@ -28,14 +28,26 @@ #include "hci.h" -static void nfc_hci_execute_cb(struct nfc_hci_dev *hdev, int err, +static int nfc_hci_result_to_errno(u8 result) +{ + switch (result) { + case NFC_HCI_ANY_OK: + return 0; + case NFC_HCI_ANY_E_TIMEOUT: + return -ETIMEDOUT; + default: + return -1; + } +} + +static void nfc_hci_execute_cb(struct nfc_hci_dev *hdev, u8 result, struct sk_buff *skb, void *cb_data) { struct hcp_exec_waiter *hcp_ew = (struct hcp_exec_waiter *)cb_data; - pr_debug("HCI Cmd completed with result=%d\n", err); + pr_debug("HCI Cmd completed with HCI result=%d\n", result); - hcp_ew->exec_result = err; + hcp_ew->exec_result = nfc_hci_result_to_errno(result); if (hcp_ew->exec_result == 0) hcp_ew->result_skb = skb; else @@ -299,9 +311,9 @@ int nfc_hci_disconnect_all_gates(struct nfc_hci_dev *hdev) } EXPORT_SYMBOL(nfc_hci_disconnect_all_gates); -int nfc_hci_connect_gate(struct nfc_hci_dev *hdev, u8 dest_host, u8 dest_gate, - u8 pipe) +int nfc_hci_connect_gate(struct nfc_hci_dev *hdev, u8 dest_host, u8 dest_gate) { + u8 pipe = NFC_HCI_INVALID_PIPE; bool pipe_created = false; int r; @@ -310,9 +322,6 @@ int nfc_hci_connect_gate(struct nfc_hci_dev *hdev, u8 dest_host, u8 dest_gate, if (hdev->gate2pipe[dest_gate] != NFC_HCI_INVALID_PIPE) return -EADDRINUSE; - if (pipe != NFC_HCI_INVALID_PIPE) - goto pipe_is_open; - switch (dest_gate) { case NFC_HCI_LINK_MGMT_GATE: pipe = NFC_HCI_LINK_MGMT_PIPE; @@ -338,7 +347,6 @@ int nfc_hci_connect_gate(struct nfc_hci_dev *hdev, u8 dest_host, u8 dest_gate, return r; } -pipe_is_open: hdev->gate2pipe[dest_gate] = pipe; return 0; diff --git a/trunk/net/nfc/hci/core.c b/trunk/net/nfc/hci/core.c index 36717cebfbb6..a8b0b71e8f86 100644 --- a/trunk/net/nfc/hci/core.c +++ b/trunk/net/nfc/hci/core.c @@ -32,18 +32,6 @@ /* Largest headroom needed for outgoing HCI commands */ #define HCI_CMDS_HEADROOM 1 -static int nfc_hci_result_to_errno(u8 result) -{ - switch (result) { - case NFC_HCI_ANY_OK: - return 0; - case NFC_HCI_ANY_E_TIMEOUT: - return -ETIME; - default: - return -1; - } -} - static void nfc_hci_msg_tx_work(struct work_struct *work) { struct nfc_hci_dev *hdev = container_of(work, struct nfc_hci_dev, @@ -58,7 +46,7 @@ static void nfc_hci_msg_tx_work(struct work_struct *work) if (timer_pending(&hdev->cmd_timer) == 0) { if (hdev->cmd_pending_msg->cb) hdev->cmd_pending_msg->cb(hdev, - -ETIME, + NFC_HCI_ANY_E_TIMEOUT, NULL, hdev-> cmd_pending_msg-> @@ -83,7 +71,8 @@ static void nfc_hci_msg_tx_work(struct work_struct *work) kfree_skb(skb); skb_queue_purge(&msg->msg_frags); if (msg->cb) - msg->cb(hdev, r, NULL, msg->cb_context); + msg->cb(hdev, NFC_HCI_ANY_E_NOK, NULL, + msg->cb_context); kfree(msg); break; } @@ -127,13 +116,20 @@ static void nfc_hci_msg_rx_work(struct work_struct *work) } } -static void __nfc_hci_cmd_completion(struct nfc_hci_dev *hdev, int err, - struct sk_buff *skb) +void nfc_hci_resp_received(struct nfc_hci_dev *hdev, u8 result, + struct sk_buff *skb) { + mutex_lock(&hdev->msg_tx_mutex); + + if (hdev->cmd_pending_msg == NULL) { + kfree_skb(skb); + goto exit; + } + del_timer_sync(&hdev->cmd_timer); if (hdev->cmd_pending_msg->cb) - hdev->cmd_pending_msg->cb(hdev, err, skb, + hdev->cmd_pending_msg->cb(hdev, result, skb, hdev->cmd_pending_msg->cb_context); else kfree_skb(skb); @@ -142,19 +138,6 @@ static void __nfc_hci_cmd_completion(struct nfc_hci_dev *hdev, int err, hdev->cmd_pending_msg = NULL; queue_work(hdev->msg_tx_wq, &hdev->msg_tx_work); -} - -void nfc_hci_resp_received(struct nfc_hci_dev *hdev, u8 result, - struct sk_buff *skb) -{ - mutex_lock(&hdev->msg_tx_mutex); - - if (hdev->cmd_pending_msg == NULL) { - kfree_skb(skb); - goto exit; - } - - __nfc_hci_cmd_completion(hdev, nfc_hci_result_to_errno(result), skb); exit: mutex_unlock(&hdev->msg_tx_mutex); @@ -230,7 +213,7 @@ static int nfc_hci_target_discovered(struct nfc_hci_dev *hdev, u8 gate) } break; case NFC_HCI_RF_READER_B_GATE: - targets->supported_protocols = NFC_PROTO_ISO14443_B_MASK; + targets->supported_protocols = NFC_PROTO_ISO14443_MASK; break; default: if (hdev->ops->target_from_gate) @@ -315,15 +298,15 @@ static void nfc_hci_cmd_timeout(unsigned long data) } static int hci_dev_connect_gates(struct nfc_hci_dev *hdev, u8 gate_count, - struct nfc_hci_gate *gates) + u8 gates[]) { int r; + u8 *p = gates; while (gate_count--) { - r = nfc_hci_connect_gate(hdev, NFC_HCI_HOST_CONTROLLER_ID, - gates->gate, gates->pipe); + r = nfc_hci_connect_gate(hdev, NFC_HCI_HOST_CONTROLLER_ID, *p); if (r < 0) return r; - gates++; + p++; } return 0; @@ -333,13 +316,14 @@ static int hci_dev_session_init(struct nfc_hci_dev *hdev) { struct sk_buff *skb = NULL; int r; - - if (hdev->init_data.gates[0].gate != NFC_HCI_ADMIN_GATE) - return -EPROTO; + u8 hci_gates[] = { /* NFC_HCI_ADMIN_GATE MUST be first */ + NFC_HCI_ADMIN_GATE, NFC_HCI_LOOPBACK_GATE, + NFC_HCI_ID_MGMT_GATE, NFC_HCI_LINK_MGMT_GATE, + NFC_HCI_RF_READER_B_GATE, NFC_HCI_RF_READER_A_GATE + }; r = nfc_hci_connect_gate(hdev, NFC_HCI_HOST_CONTROLLER_ID, - hdev->init_data.gates[0].gate, - hdev->init_data.gates[0].pipe); + NFC_HCI_ADMIN_GATE); if (r < 0) goto exit; @@ -367,6 +351,10 @@ static int hci_dev_session_init(struct nfc_hci_dev *hdev) if (r < 0) goto exit; + r = hci_dev_connect_gates(hdev, sizeof(hci_gates), hci_gates); + if (r < 0) + goto disconnect_all; + r = hci_dev_connect_gates(hdev, hdev->init_data.gate_count, hdev->init_data.gates); if (r < 0) @@ -729,27 +717,6 @@ 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 nfc_hci_recv_frame(struct nfc_hci_dev *hdev, struct sk_buff *skb) { struct hcp_packet *packet; @@ -760,6 +727,16 @@ void nfc_hci_recv_frame(struct nfc_hci_dev *hdev, struct sk_buff *skb) struct sk_buff *frag_skb; int msg_len; + if (skb == NULL) { + /* TODO ELa: lower layer had permanent failure, need to + * propagate that up + */ + + skb_queue_purge(&hdev->rx_hcp_frags); + + return; + } + packet = (struct hcp_packet *)skb->data; if ((packet->header & ~NFC_HCI_FRAGMENT) == 0) { skb_queue_tail(&hdev->rx_hcp_frags, skb); @@ -780,8 +757,9 @@ void nfc_hci_recv_frame(struct nfc_hci_dev *hdev, struct sk_buff *skb) 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; + /* TODO ELa: cannot deliver HCP message. How to + * propagate error up? + */ } *skb_put(hcp_skb, NFC_HCI_HCP_PACKET_HEADER_LEN) = pipe; diff --git a/trunk/net/nfc/hci/hci.h b/trunk/net/nfc/hci/hci.h index fa9a21e92239..45f2fe4fd486 100644 --- a/trunk/net/nfc/hci/hci.h +++ b/trunk/net/nfc/hci/hci.h @@ -37,11 +37,10 @@ struct hcp_packet { /* * 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 + * result will be one of the HCI response codes. + * skb contains the response data and must be disposed. */ -typedef void (*hci_cmd_cb_t) (struct nfc_hci_dev *hdev, int result, +typedef void (*hci_cmd_cb_t) (struct nfc_hci_dev *hdev, u8 result, struct sk_buff *skb, void *cb_data); struct hcp_exec_waiter { @@ -132,4 +131,9 @@ void nfc_hci_hcp_message_rx(struct nfc_hci_dev *hdev, u8 pipe, u8 type, #define NFC_HCI_ANY_E_REG_ACCESS_DENIED 0x0a #define NFC_HCI_ANY_E_PIPE_ACCESS_DENIED 0x0b +/* Pipes */ +#define NFC_HCI_INVALID_PIPE 0x80 +#define NFC_HCI_LINK_MGMT_PIPE 0x00 +#define NFC_HCI_ADMIN_PIPE 0x01 + #endif /* __LOCAL_HCI_H */ diff --git a/trunk/net/nfc/hci/shdlc.c b/trunk/net/nfc/hci/shdlc.c index 6f840c18c892..6b836e6242b7 100644 --- a/trunk/net/nfc/hci/shdlc.c +++ b/trunk/net/nfc/hci/shdlc.c @@ -340,6 +340,15 @@ static void nfc_shdlc_connect_complete(struct nfc_shdlc *shdlc, int r) shdlc->state = SHDLC_CONNECTED; } else { shdlc->state = SHDLC_DISCONNECTED; + + /* + * TODO: Could it be possible that there are pending + * executing commands that are waiting for connect to complete + * before they can be carried? As connect is a blocking + * operation, it would require that the userspace process can + * send commands on the same device from a second thread before + * the device is up. I don't think that is possible, is it? + */ } shdlc->connect_result = r; @@ -404,12 +413,12 @@ static void nfc_shdlc_rcv_u_frame(struct nfc_shdlc *shdlc, r = nfc_shdlc_connect_send_ua(shdlc); nfc_shdlc_connect_complete(shdlc, r); } - } else if (shdlc->state == SHDLC_CONNECTED) { + } else if (shdlc->state > SHDLC_NEGOCIATING) { /* - * Chip wants to reset link. This is unexpected and - * unsupported. + * TODO: Chip wants to reset link + * send ua, empty skb lists, reset counters + * propagate info to HCI layer */ - shdlc->hard_fault = -ECONNRESET; } break; case U_FRAME_UA: @@ -514,6 +523,10 @@ static void nfc_shdlc_handle_send_queue(struct nfc_shdlc *shdlc) r = shdlc->ops->xmit(shdlc, skb); if (r < 0) { + /* + * TODO: Cannot send, shdlc machine is dead, we + * must propagate the information up to HCI. + */ shdlc->hard_fault = r; break; } @@ -577,11 +590,6 @@ static void nfc_shdlc_sm_work(struct work_struct *work) skb_queue_purge(&shdlc->ack_pending_q); break; case SHDLC_CONNECTING: - if (shdlc->hard_fault) { - nfc_shdlc_connect_complete(shdlc, shdlc->hard_fault); - break; - } - if (shdlc->connect_tries++ < 5) r = nfc_shdlc_connect_initiate(shdlc); else @@ -602,11 +610,6 @@ static void nfc_shdlc_sm_work(struct work_struct *work) } nfc_shdlc_handle_rcv_queue(shdlc); - - if (shdlc->hard_fault) { - nfc_shdlc_connect_complete(shdlc, shdlc->hard_fault); - break; - } break; case SHDLC_CONNECTED: nfc_shdlc_handle_rcv_queue(shdlc); @@ -634,7 +637,10 @@ static void nfc_shdlc_sm_work(struct work_struct *work) } if (shdlc->hard_fault) { - nfc_hci_driver_failure(shdlc->hdev, shdlc->hard_fault); + /* + * TODO: Handle hard_fault that occured during + * this invocation of the shdlc worker + */ } break; default: @@ -917,6 +923,8 @@ void nfc_shdlc_free(struct nfc_shdlc *shdlc) { pr_debug("\n"); + /* TODO: Check that this cannot be called while still in use */ + nfc_hci_unregister_device(shdlc->hdev); nfc_hci_free_device(shdlc->hdev); diff --git a/trunk/net/nfc/llcp/llcp.c b/trunk/net/nfc/llcp/llcp.c index 82f0f7588b46..5d503eeb15a1 100644 --- a/trunk/net/nfc/llcp/llcp.c +++ b/trunk/net/nfc/llcp/llcp.c @@ -45,7 +45,7 @@ void nfc_llcp_sock_unlink(struct llcp_sock_list *l, struct sock *sk) write_unlock(&l->lock); } -static void nfc_llcp_socket_release(struct nfc_llcp_local *local, bool listen) +static void nfc_llcp_socket_release(struct nfc_llcp_local *local) { struct sock *sk; struct hlist_node *node, *tmp; @@ -78,11 +78,6 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local, bool listen) sock_orphan(accept_sk); } - - if (listen == true) { - release_sock(sk); - continue; - } } sk->sk_state = LLCP_CLOSED; @@ -111,7 +106,7 @@ static void local_release(struct kref *ref) local = container_of(ref, struct nfc_llcp_local, ref); list_del(&local->list); - nfc_llcp_socket_release(local, false); + nfc_llcp_socket_release(local); del_timer_sync(&local->link_timer); skb_queue_purge(&local->tx_queue); destroy_workqueue(local->tx_wq); @@ -123,48 +118,23 @@ static void local_release(struct kref *ref) int nfc_llcp_local_put(struct nfc_llcp_local *local) { + WARN_ON(local == NULL); + if (local == NULL) return 0; return kref_put(&local->ref, local_release); } -static struct nfc_llcp_sock *nfc_llcp_sock_get(struct nfc_llcp_local *local, - u8 ssap, u8 dsap) +static void nfc_llcp_clear_sdp(struct nfc_llcp_local *local) { - struct sock *sk; - struct hlist_node *node; - struct nfc_llcp_sock *llcp_sock; - - pr_debug("ssap dsap %d %d\n", ssap, dsap); - - if (ssap == 0 && dsap == 0) - return NULL; - - read_lock(&local->sockets.lock); - - llcp_sock = NULL; - - sk_for_each(sk, node, &local->sockets.head) { - llcp_sock = nfc_llcp_sock(sk); - - if (llcp_sock->ssap == ssap && llcp_sock->dsap == dsap) - break; - } - - read_unlock(&local->sockets.lock); - - if (llcp_sock == NULL) - return NULL; - - sock_hold(&llcp_sock->sk); + mutex_lock(&local->sdp_lock); - return llcp_sock; -} + local->local_wks = 0; + local->local_sdp = 0; + local->local_sap = 0; -static void nfc_llcp_sock_put(struct nfc_llcp_sock *sock) -{ - sock_put(&sock->sk); + mutex_unlock(&local->sdp_lock); } static void nfc_llcp_timeout_work(struct work_struct *work) @@ -227,51 +197,6 @@ static int nfc_llcp_wks_sap(char *service_name, size_t service_name_len) return -EINVAL; } -static -struct nfc_llcp_sock *nfc_llcp_sock_from_sn(struct nfc_llcp_local *local, - u8 *sn, size_t sn_len) -{ - struct sock *sk; - struct hlist_node *node; - struct nfc_llcp_sock *llcp_sock, *tmp_sock; - - pr_debug("sn %zd %p\n", sn_len, sn); - - if (sn == NULL || sn_len == 0) - return NULL; - - read_lock(&local->sockets.lock); - - llcp_sock = NULL; - - sk_for_each(sk, node, &local->sockets.head) { - tmp_sock = nfc_llcp_sock(sk); - - pr_debug("llcp sock %p\n", tmp_sock); - - if (tmp_sock->sk.sk_state != LLCP_LISTEN) - continue; - - if (tmp_sock->service_name == NULL || - tmp_sock->service_name_len == 0) - continue; - - if (tmp_sock->service_name_len != sn_len) - continue; - - if (memcmp(sn, tmp_sock->service_name, sn_len) == 0) { - llcp_sock = tmp_sock; - break; - } - } - - read_unlock(&local->sockets.lock); - - pr_debug("Found llcp sock %p\n", llcp_sock); - - return llcp_sock; -} - u8 nfc_llcp_get_sdp_ssap(struct nfc_llcp_local *local, struct nfc_llcp_sock *sock) { @@ -298,26 +223,41 @@ u8 nfc_llcp_get_sdp_ssap(struct nfc_llcp_local *local, } /* - * Check if there already is a non WKS socket bound - * to this service name. + * This is not a well known service, + * we should try to find a local SDP free spot */ - if (nfc_llcp_sock_from_sn(local, sock->service_name, - sock->service_name_len) != NULL) { + ssap = find_first_zero_bit(&local->local_sdp, LLCP_SDP_NUM_SAP); + if (ssap == LLCP_SDP_NUM_SAP) { mutex_unlock(&local->sdp_lock); return LLCP_SAP_MAX; } + pr_debug("SDP ssap %d\n", LLCP_WKS_NUM_SAP + ssap); + + set_bit(ssap, &local->local_sdp); mutex_unlock(&local->sdp_lock); - return LLCP_SDP_UNBOUND; + return LLCP_WKS_NUM_SAP + ssap; - } else if (sock->ssap != 0 && sock->ssap < LLCP_WKS_NUM_SAP) { - if (!test_bit(sock->ssap, &local->local_wks)) { - set_bit(sock->ssap, &local->local_wks); - mutex_unlock(&local->sdp_lock); + } else if (sock->ssap != 0) { + if (sock->ssap < LLCP_WKS_NUM_SAP) { + if (!test_bit(sock->ssap, &local->local_wks)) { + set_bit(sock->ssap, &local->local_wks); + mutex_unlock(&local->sdp_lock); - return sock->ssap; + return sock->ssap; + } + + } else if (sock->ssap < LLCP_SDP_NUM_SAP) { + if (!test_bit(sock->ssap - LLCP_WKS_NUM_SAP, + &local->local_sdp)) { + set_bit(sock->ssap - LLCP_WKS_NUM_SAP, + &local->local_sdp); + mutex_unlock(&local->sdp_lock); + + return sock->ssap; + } } } @@ -354,34 +294,8 @@ void nfc_llcp_put_ssap(struct nfc_llcp_local *local, u8 ssap) local_ssap = ssap; sdp = &local->local_wks; } else if (ssap < LLCP_LOCAL_NUM_SAP) { - atomic_t *client_cnt; - local_ssap = ssap - LLCP_WKS_NUM_SAP; sdp = &local->local_sdp; - client_cnt = &local->local_sdp_cnt[local_ssap]; - - pr_debug("%d clients\n", atomic_read(client_cnt)); - - mutex_lock(&local->sdp_lock); - - if (atomic_dec_and_test(client_cnt)) { - struct nfc_llcp_sock *l_sock; - - pr_debug("No more clients for SAP %d\n", ssap); - - clear_bit(local_ssap, sdp); - - /* Find the listening sock and set it back to UNBOUND */ - l_sock = nfc_llcp_sock_get(local, ssap, LLCP_SAP_SDP); - if (l_sock) { - l_sock->ssap = LLCP_SDP_UNBOUND; - nfc_llcp_sock_put(l_sock); - } - } - - mutex_unlock(&local->sdp_lock); - - return; } else if (ssap < LLCP_MAX_SAP) { local_ssap = ssap - LLCP_LOCAL_NUM_SAP; sdp = &local->local_sap; @@ -396,26 +310,19 @@ void nfc_llcp_put_ssap(struct nfc_llcp_local *local, u8 ssap) mutex_unlock(&local->sdp_lock); } -static u8 nfc_llcp_reserve_sdp_ssap(struct nfc_llcp_local *local) +u8 *nfc_llcp_general_bytes(struct nfc_dev *dev, size_t *general_bytes_len) { - u8 ssap; - - mutex_lock(&local->sdp_lock); - - ssap = find_first_zero_bit(&local->local_sdp, LLCP_SDP_NUM_SAP); - if (ssap == LLCP_SDP_NUM_SAP) { - mutex_unlock(&local->sdp_lock); + struct nfc_llcp_local *local; - return LLCP_SAP_MAX; + local = nfc_llcp_find_local(dev); + if (local == NULL) { + *general_bytes_len = 0; + return NULL; } - pr_debug("SDP ssap %d\n", LLCP_WKS_NUM_SAP + ssap); - - set_bit(ssap, &local->local_sdp); - - mutex_unlock(&local->sdp_lock); + *general_bytes_len = local->gb_len; - return LLCP_WKS_NUM_SAP + ssap; + return local->gb; } static int nfc_llcp_build_gb(struct nfc_llcp_local *local) @@ -479,23 +386,6 @@ static int nfc_llcp_build_gb(struct nfc_llcp_local *local) return 0; } -u8 *nfc_llcp_general_bytes(struct nfc_dev *dev, size_t *general_bytes_len) -{ - struct nfc_llcp_local *local; - - local = nfc_llcp_find_local(dev); - if (local == NULL) { - *general_bytes_len = 0; - return NULL; - } - - nfc_llcp_build_gb(local); - - *general_bytes_len = local->gb_len; - - return local->gb; -} - int nfc_llcp_set_remote_gb(struct nfc_dev *dev, u8 *gb, u8 gb_len) { struct nfc_llcp_local *local = nfc_llcp_find_local(dev); @@ -619,12 +509,74 @@ static struct nfc_llcp_sock *nfc_llcp_connecting_sock_get(struct nfc_llcp_local return llcp_sock; } +static struct nfc_llcp_sock *nfc_llcp_sock_get(struct nfc_llcp_local *local, + u8 ssap, u8 dsap) +{ + struct sock *sk; + struct hlist_node *node; + struct nfc_llcp_sock *llcp_sock; + + pr_debug("ssap dsap %d %d\n", ssap, dsap); + + if (ssap == 0 && dsap == 0) + return NULL; + + read_lock(&local->sockets.lock); + + llcp_sock = NULL; + + sk_for_each(sk, node, &local->sockets.head) { + llcp_sock = nfc_llcp_sock(sk); + + if (llcp_sock->ssap == ssap && + llcp_sock->dsap == dsap) + break; + } + + read_unlock(&local->sockets.lock); + + if (llcp_sock == NULL) + return NULL; + + sock_hold(&llcp_sock->sk); + + return llcp_sock; +} + static struct nfc_llcp_sock *nfc_llcp_sock_get_sn(struct nfc_llcp_local *local, u8 *sn, size_t sn_len) { + struct sock *sk; + struct hlist_node *node; struct nfc_llcp_sock *llcp_sock; - llcp_sock = nfc_llcp_sock_from_sn(local, sn, sn_len); + pr_debug("sn %zd\n", sn_len); + + if (sn == NULL || sn_len == 0) + return NULL; + + read_lock(&local->sockets.lock); + + llcp_sock = NULL; + + sk_for_each(sk, node, &local->sockets.head) { + llcp_sock = nfc_llcp_sock(sk); + + if (llcp_sock->sk.sk_state != LLCP_LISTEN) + continue; + + if (llcp_sock->service_name == NULL || + llcp_sock->service_name_len == 0) + continue; + + if (llcp_sock->service_name_len != sn_len) + continue; + + if (memcmp(sn, llcp_sock->service_name, sn_len) == 0) + break; + } + + read_unlock(&local->sockets.lock); if (llcp_sock == NULL) return NULL; @@ -634,6 +586,11 @@ static struct nfc_llcp_sock *nfc_llcp_sock_get_sn(struct nfc_llcp_local *local, return llcp_sock; } +static void nfc_llcp_sock_put(struct nfc_llcp_sock *sock) +{ + sock_put(&sock->sk); +} + static u8 *nfc_llcp_connect_sn(struct sk_buff *skb, size_t *sn_len) { u8 *tlv = &skb->data[2], type, length; @@ -705,21 +662,6 @@ static void nfc_llcp_recv_connect(struct nfc_llcp_local *local, goto fail; } - if (sock->ssap == LLCP_SDP_UNBOUND) { - u8 ssap = nfc_llcp_reserve_sdp_ssap(local); - - pr_debug("First client, reserving %d\n", ssap); - - if (ssap == LLCP_SAP_MAX) { - reason = LLCP_DM_REJ; - release_sock(&sock->sk); - sock_put(&sock->sk); - goto fail; - } - - sock->ssap = ssap; - } - new_sk = nfc_llcp_sock_alloc(NULL, parent->sk_type, GFP_ATOMIC); if (new_sk == NULL) { reason = LLCP_DM_REJ; @@ -733,21 +675,9 @@ static void nfc_llcp_recv_connect(struct nfc_llcp_local *local, new_sock->local = nfc_llcp_local_get(local); new_sock->miu = local->remote_miu; new_sock->nfc_protocol = sock->nfc_protocol; + new_sock->ssap = sock->ssap; new_sock->dsap = ssap; - new_sock->target_idx = local->target_idx; new_sock->parent = parent; - new_sock->ssap = sock->ssap; - if (sock->ssap < LLCP_LOCAL_NUM_SAP && sock->ssap >= LLCP_WKS_NUM_SAP) { - atomic_t *client_count; - - pr_debug("reserved_ssap %d for %p\n", sock->ssap, new_sock); - - client_count = - &local->local_sdp_cnt[sock->ssap - LLCP_WKS_NUM_SAP]; - - atomic_inc(client_count); - new_sock->reserved_ssap = sock->ssap; - } nfc_llcp_parse_connection_tlv(new_sock, &skb->data[LLCP_HEADER_SIZE], skb->len - LLCP_HEADER_SIZE); @@ -956,45 +886,6 @@ static void nfc_llcp_recv_cc(struct nfc_llcp_local *local, struct sk_buff *skb) nfc_llcp_sock_put(llcp_sock); } -static void nfc_llcp_recv_dm(struct nfc_llcp_local *local, struct sk_buff *skb) -{ - struct nfc_llcp_sock *llcp_sock; - struct sock *sk; - u8 dsap, ssap, reason; - - dsap = nfc_llcp_dsap(skb); - ssap = nfc_llcp_ssap(skb); - reason = skb->data[2]; - - pr_debug("%d %d reason %d\n", ssap, dsap, reason); - - switch (reason) { - case LLCP_DM_NOBOUND: - case LLCP_DM_REJ: - llcp_sock = nfc_llcp_connecting_sock_get(local, dsap); - break; - - default: - llcp_sock = nfc_llcp_sock_get(local, dsap, ssap); - break; - } - - if (llcp_sock == NULL) { - pr_err("Invalid DM\n"); - return; - } - - sk = &llcp_sock->sk; - - sk->sk_err = ENXIO; - sk->sk_state = LLCP_CLOSED; - sk->sk_state_change(sk); - - nfc_llcp_sock_put(llcp_sock); - - return; -} - static void nfc_llcp_rx_work(struct work_struct *work) { struct nfc_llcp_local *local = container_of(work, struct nfc_llcp_local, @@ -1038,11 +929,6 @@ static void nfc_llcp_rx_work(struct work_struct *work) nfc_llcp_recv_cc(local, skb); break; - case LLCP_PDU_DM: - pr_debug("DM\n"); - nfc_llcp_recv_dm(local, skb); - break; - case LLCP_PDU_I: case LLCP_PDU_RR: case LLCP_PDU_RNR: @@ -1099,8 +985,10 @@ void nfc_llcp_mac_is_down(struct nfc_dev *dev) if (local == NULL) return; + nfc_llcp_clear_sdp(local); + /* Close and purge all existing sockets */ - nfc_llcp_socket_release(local, true); + nfc_llcp_socket_release(local); } void nfc_llcp_mac_is_up(struct nfc_dev *dev, u32 target_idx, diff --git a/trunk/net/nfc/llcp/llcp.h b/trunk/net/nfc/llcp/llcp.h index 83b8bba5a280..7286c86982ff 100644 --- a/trunk/net/nfc/llcp/llcp.h +++ b/trunk/net/nfc/llcp/llcp.h @@ -37,7 +37,6 @@ enum llcp_state { #define LLCP_LOCAL_NUM_SAP 32 #define LLCP_LOCAL_SAP_OFFSET (LLCP_WKS_NUM_SAP + LLCP_SDP_NUM_SAP) #define LLCP_MAX_SAP (LLCP_WKS_NUM_SAP + LLCP_SDP_NUM_SAP + LLCP_LOCAL_NUM_SAP) -#define LLCP_SDP_UNBOUND (LLCP_MAX_SAP + 1) struct nfc_llcp_sock; @@ -70,7 +69,6 @@ struct nfc_llcp_local { unsigned long local_wks; /* Well known services */ unsigned long local_sdp; /* Local services */ unsigned long local_sap; /* Local SAPs, not available for discovery */ - atomic_t local_sdp_cnt[LLCP_SDP_NUM_SAP]; /* local */ u8 gb[NFC_MAX_GT_LEN]; @@ -115,9 +113,6 @@ struct nfc_llcp_sock { /* Is the remote peer ready to receive */ u8 remote_ready; - /* Reserved source SAP */ - u8 reserved_ssap; - struct sk_buff_head tx_queue; struct sk_buff_head tx_pending_queue; struct sk_buff_head tx_backlog_queue; diff --git a/trunk/net/nfc/llcp/sock.c b/trunk/net/nfc/llcp/sock.c index ddeb9aa398f0..2c0b317344b7 100644 --- a/trunk/net/nfc/llcp/sock.c +++ b/trunk/net/nfc/llcp/sock.c @@ -78,11 +78,11 @@ static int llcp_sock_bind(struct socket *sock, struct sockaddr *addr, int alen) struct sockaddr_nfc_llcp llcp_addr; int len, ret = 0; + pr_debug("sk %p addr %p family %d\n", sk, addr, addr->sa_family); + 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); @@ -121,12 +121,8 @@ static int llcp_sock_bind(struct socket *sock, struct sockaddr *addr, int alen) GFP_KERNEL); llcp_sock->ssap = nfc_llcp_get_sdp_ssap(local, llcp_sock); - if (llcp_sock->ssap == LLCP_SAP_MAX) { - ret = -EADDRINUSE; + if (llcp_sock->ssap == LLCP_MAX_SAP) goto put_dev; - } - - llcp_sock->reserved_ssap = llcp_sock->ssap; nfc_llcp_sock_link(&local->sockets, sk); @@ -287,28 +283,22 @@ static int llcp_sock_accept(struct socket *sock, struct socket *newsock, return ret; } -static int llcp_sock_getname(struct socket *sock, struct sockaddr *uaddr, +static int llcp_sock_getname(struct socket *sock, struct sockaddr *addr, int *len, int peer) { + struct sockaddr_nfc_llcp *llcp_addr = (struct sockaddr_nfc_llcp *)addr; struct sock *sk = sock->sk; struct nfc_llcp_sock *llcp_sock = nfc_llcp_sock(sk); - DECLARE_SOCKADDR(struct sockaddr_nfc_llcp *, llcp_addr, uaddr); - if (llcp_sock == NULL || llcp_sock->dev == NULL) - return -EBADFD; - - pr_debug("%p %d %d %d\n", sk, llcp_sock->target_idx, - llcp_sock->dsap, llcp_sock->ssap); + pr_debug("%p\n", sk); - if (llcp_sock == NULL || llcp_sock->dev == NULL) + if (llcp_sock == NULL) return -EBADFD; - uaddr->sa_family = AF_NFC; - + addr->sa_family = AF_NFC; *len = sizeof(struct sockaddr_nfc_llcp); llcp_addr->dev_idx = llcp_sock->dev->idx; - llcp_addr->target_idx = llcp_sock->target_idx; llcp_addr->dsap = llcp_sock->dsap; llcp_addr->ssap = llcp_sock->ssap; llcp_addr->service_name_len = llcp_sock->service_name_len; @@ -416,8 +406,7 @@ static int llcp_sock_release(struct socket *sock) } } - if (llcp_sock->reserved_ssap < LLCP_SAP_MAX) - nfc_llcp_put_ssap(llcp_sock->local, llcp_sock->ssap); + nfc_llcp_put_ssap(llcp_sock->local, llcp_sock->ssap); release_sock(sk); @@ -497,9 +486,6 @@ static int llcp_sock_connect(struct socket *sock, struct sockaddr *_addr, ret = -ENOMEM; goto put_dev; } - - llcp_sock->reserved_ssap = llcp_sock->ssap; - if (addr->service_name_len == 0) llcp_sock->dsap = addr->dsap; else @@ -701,7 +687,6 @@ struct sock *nfc_llcp_sock_alloc(struct socket *sock, int type, gfp_t gfp) llcp_sock->send_n = llcp_sock->send_ack_n = 0; llcp_sock->recv_n = llcp_sock->recv_ack_n = 0; llcp_sock->remote_ready = 1; - llcp_sock->reserved_ssap = LLCP_SAP_MAX; skb_queue_head_init(&llcp_sock->tx_queue); skb_queue_head_init(&llcp_sock->tx_pending_queue); skb_queue_head_init(&llcp_sock->tx_backlog_queue); diff --git a/trunk/net/nfc/nci/core.c b/trunk/net/nfc/nci/core.c index 5bb4da680427..766a02b1dfa1 100644 --- a/trunk/net/nfc/nci/core.c +++ b/trunk/net/nfc/nci/core.c @@ -194,7 +194,7 @@ static void nci_rf_discover_req(struct nci_dev *ndev, unsigned long opt) } if ((cmd.num_disc_configs < NCI_MAX_NUM_RF_CONFIGS) && - (protocols & NFC_PROTO_ISO14443_B_MASK)) { + (protocols & NFC_PROTO_ISO14443_MASK)) { cmd.disc_configs[cmd.num_disc_configs].rf_tech_and_mode = NCI_NFC_B_PASSIVE_POLL_MODE; cmd.disc_configs[cmd.num_disc_configs].frequency = 1; @@ -486,8 +486,7 @@ static int nci_activate_target(struct nfc_dev *nfc_dev, param.rf_protocol = NCI_RF_PROTOCOL_T2T; else if (protocol == NFC_PROTO_FELICA) param.rf_protocol = NCI_RF_PROTOCOL_T3T; - else if (protocol == NFC_PROTO_ISO14443 || - protocol == NFC_PROTO_ISO14443_B) + else if (protocol == NFC_PROTO_ISO14443) param.rf_protocol = NCI_RF_PROTOCOL_ISO_DEP; else param.rf_protocol = NCI_RF_PROTOCOL_NFC_DEP; diff --git a/trunk/net/nfc/nci/ntf.c b/trunk/net/nfc/nci/ntf.c index af7a93b04393..2ab196a9f228 100644 --- a/trunk/net/nfc/nci/ntf.c +++ b/trunk/net/nfc/nci/ntf.c @@ -170,10 +170,7 @@ static int nci_add_new_protocol(struct nci_dev *ndev, if (rf_protocol == NCI_RF_PROTOCOL_T2T) protocol = NFC_PROTO_MIFARE_MASK; else if (rf_protocol == NCI_RF_PROTOCOL_ISO_DEP) - if (rf_tech_and_mode == NCI_NFC_A_PASSIVE_POLL_MODE) - protocol = NFC_PROTO_ISO14443_MASK; - else - protocol = NFC_PROTO_ISO14443_B_MASK; + protocol = NFC_PROTO_ISO14443_MASK; else if (rf_protocol == NCI_RF_PROTOCOL_T3T) protocol = NFC_PROTO_FELICA_MASK; else diff --git a/trunk/net/nfc/netlink.c b/trunk/net/nfc/netlink.c index 4c51714ee741..f4f07f9b61c0 100644 --- a/trunk/net/nfc/netlink.c +++ b/trunk/net/nfc/netlink.c @@ -634,15 +634,6 @@ static int nfc_genl_stop_poll(struct sk_buff *skb, struct genl_info *info) if (!dev) return -ENODEV; - device_lock(&dev->dev); - - if (!dev->polling) { - device_unlock(&dev->dev); - return -EINVAL; - } - - device_unlock(&dev->dev); - mutex_lock(&dev->genl_data.genl_data_mutex); if (dev->genl_data.poll_req_pid != info->snd_pid) { diff --git a/trunk/net/rds/page.c b/trunk/net/rds/page.c index 9005a2c920ee..2499cd108421 100644 --- a/trunk/net/rds/page.c +++ b/trunk/net/rds/page.c @@ -74,12 +74,11 @@ int rds_page_copy_user(struct page *page, unsigned long offset, } EXPORT_SYMBOL_GPL(rds_page_copy_user); -/** - * rds_page_remainder_alloc - build up regions of a message. +/* + * Message allocation uses this to build up regions of a message. * - * @scat: Scatter list for message - * @bytes: the number of bytes needed. - * @gfp: the waiting behaviour of the allocation + * @bytes - the number of bytes needed. + * @gfp - the waiting behaviour of the allocation * * @gfp is always ored with __GFP_HIGHMEM. Callers must be prepared to * kmap the pages, etc. diff --git a/trunk/net/rxrpc/ar-output.c b/trunk/net/rxrpc/ar-output.c index e1ac183d50bb..16ae88762d00 100644 --- a/trunk/net/rxrpc/ar-output.c +++ b/trunk/net/rxrpc/ar-output.c @@ -242,7 +242,7 @@ int rxrpc_kernel_send_data(struct rxrpc_call *call, struct msghdr *msg, EXPORT_SYMBOL(rxrpc_kernel_send_data); -/** +/* * rxrpc_kernel_abort_call - Allow a kernel service to abort a call * @call: The call to be aborted * @abort_code: The abort code to stick into the ABORT packet diff --git a/trunk/net/rxrpc/ar-peer.c b/trunk/net/rxrpc/ar-peer.c index bebaa43484bc..2754f098d436 100644 --- a/trunk/net/rxrpc/ar-peer.c +++ b/trunk/net/rxrpc/ar-peer.c @@ -229,7 +229,7 @@ struct rxrpc_peer *rxrpc_find_peer(struct rxrpc_local *local, return peer; new_UDP_peer: - _net("Rx UDP DGRAM from NEW peer"); + _net("Rx UDP DGRAM from NEW peer %d", peer->debug_id); read_unlock_bh(&rxrpc_peer_lock); _leave(" = -EBUSY [new]"); return ERR_PTR(-EBUSY); diff --git a/trunk/net/sched/Kconfig b/trunk/net/sched/Kconfig index 62fb51face8a..e7a8976bf25c 100644 --- a/trunk/net/sched/Kconfig +++ b/trunk/net/sched/Kconfig @@ -507,26 +507,6 @@ config NET_EMATCH_TEXT To compile this code as a module, choose M here: the module will be called em_text. -config NET_EMATCH_CANID - tristate "CAN Identifier" - depends on NET_EMATCH && CAN - ---help--- - Say Y here if you want to be able to classify CAN frames based - on CAN Identifier. - - To compile this code as a module, choose M here: the - module will be called em_canid. - -config NET_EMATCH_IPSET - tristate "IPset" - depends on NET_EMATCH && IP_SET - ---help--- - Say Y here if you want to be able to classify packets based on - ipset membership. - - To compile this code as a module, choose M here: the - module will be called em_ipset. - config NET_CLS_ACT bool "Actions" ---help--- diff --git a/trunk/net/sched/Makefile b/trunk/net/sched/Makefile index 978cbf004e80..5940a1992f0d 100644 --- a/trunk/net/sched/Makefile +++ b/trunk/net/sched/Makefile @@ -55,5 +55,3 @@ obj-$(CONFIG_NET_EMATCH_NBYTE) += em_nbyte.o obj-$(CONFIG_NET_EMATCH_U32) += em_u32.o obj-$(CONFIG_NET_EMATCH_META) += em_meta.o obj-$(CONFIG_NET_EMATCH_TEXT) += em_text.o -obj-$(CONFIG_NET_EMATCH_CANID) += em_canid.o -obj-$(CONFIG_NET_EMATCH_IPSET) += em_ipset.o diff --git a/trunk/net/sched/em_canid.c b/trunk/net/sched/em_canid.c deleted file mode 100644 index bfd34e4c1afc..000000000000 --- a/trunk/net/sched/em_canid.c +++ /dev/null @@ -1,240 +0,0 @@ -/* - * em_canid.c Ematch rule to match CAN frames according to their CAN IDs - * - * This program is free software; you can distribute 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. - * - * Idea: Oliver Hartkopp - * Copyright: (c) 2011 Czech Technical University in Prague - * (c) 2011 Volkswagen Group Research - * Authors: Michal Sojka - * Pavel Pisa - * Rostislav Lisovy - * Funded by: Volkswagen Group Research - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#define EM_CAN_RULES_MAX 500 - -struct canid_match { - /* For each SFF CAN ID (11 bit) there is one record in this bitfield */ - DECLARE_BITMAP(match_sff, (1 << CAN_SFF_ID_BITS)); - - int rules_count; - int sff_rules_count; - int eff_rules_count; - - /* - * Raw rules copied from netlink message; Used for sending - * information to userspace (when 'tc filter show' is invoked) - * AND when matching EFF frames - */ - struct can_filter rules_raw[]; -}; - -/** - * em_canid_get_id() - Extracts Can ID out of the sk_buff structure. - */ -static canid_t em_canid_get_id(struct sk_buff *skb) -{ - /* CAN ID is stored within the data field */ - struct can_frame *cf = (struct can_frame *)skb->data; - - return cf->can_id; -} - -static void em_canid_sff_match_add(struct canid_match *cm, u32 can_id, - u32 can_mask) -{ - int i; - - /* - * Limit can_mask and can_id to SFF range to - * protect against write after end of array - */ - can_mask &= CAN_SFF_MASK; - can_id &= can_mask; - - /* Single frame */ - if (can_mask == CAN_SFF_MASK) { - set_bit(can_id, cm->match_sff); - return; - } - - /* All frames */ - if (can_mask == 0) { - bitmap_fill(cm->match_sff, (1 << CAN_SFF_ID_BITS)); - return; - } - - /* - * Individual frame filter. - * Add record (set bit to 1) for each ID that - * conforms particular rule - */ - for (i = 0; i < (1 << CAN_SFF_ID_BITS); i++) { - if ((i & can_mask) == can_id) - set_bit(i, cm->match_sff); - } -} - -static inline struct canid_match *em_canid_priv(struct tcf_ematch *m) -{ - return (struct canid_match *)m->data; -} - -static int em_canid_match(struct sk_buff *skb, struct tcf_ematch *m, - struct tcf_pkt_info *info) -{ - struct canid_match *cm = em_canid_priv(m); - canid_t can_id; - int match = 0; - int i; - const struct can_filter *lp; - - can_id = em_canid_get_id(skb); - - if (can_id & CAN_EFF_FLAG) { - for (i = 0, lp = cm->rules_raw; - i < cm->eff_rules_count; i++, lp++) { - if (!(((lp->can_id ^ can_id) & lp->can_mask))) { - match = 1; - break; - } - } - } else { /* SFF */ - can_id &= CAN_SFF_MASK; - match = (test_bit(can_id, cm->match_sff) ? 1 : 0); - } - - return match; -} - -static int em_canid_change(struct tcf_proto *tp, void *data, int len, - struct tcf_ematch *m) -{ - struct can_filter *conf = data; /* Array with rules */ - struct canid_match *cm; - struct canid_match *cm_old = (struct canid_match *)m->data; - int i; - - if (!len) - return -EINVAL; - - if (len % sizeof(struct can_filter)) - return -EINVAL; - - if (len > sizeof(struct can_filter) * EM_CAN_RULES_MAX) - return -EINVAL; - - cm = kzalloc(sizeof(struct canid_match) + len, GFP_KERNEL); - if (!cm) - return -ENOMEM; - - cm->rules_count = len / sizeof(struct can_filter); - - /* - * We need two for() loops for copying rules into two contiguous - * areas in rules_raw to process all eff rules with a simple loop. - * NB: The configuration interface supports sff and eff rules. - * We do not support filters here that match for the same can_id - * provided in a SFF and EFF frame (e.g. 0x123 / 0x80000123). - * For this (unusual case) two filters have to be specified. The - * SFF/EFF separation is done with the CAN_EFF_FLAG in the can_id. - */ - - /* Fill rules_raw with EFF rules first */ - for (i = 0; i < cm->rules_count; i++) { - if (conf[i].can_id & CAN_EFF_FLAG) { - memcpy(cm->rules_raw + cm->eff_rules_count, - &conf[i], - sizeof(struct can_filter)); - - cm->eff_rules_count++; - } - } - - /* append SFF frame rules */ - for (i = 0; i < cm->rules_count; i++) { - if (!(conf[i].can_id & CAN_EFF_FLAG)) { - memcpy(cm->rules_raw - + cm->eff_rules_count - + cm->sff_rules_count, - &conf[i], sizeof(struct can_filter)); - - cm->sff_rules_count++; - - em_canid_sff_match_add(cm, - conf[i].can_id, conf[i].can_mask); - } - } - - m->datalen = sizeof(struct canid_match) + len; - m->data = (unsigned long)cm; - - if (cm_old != NULL) { - pr_err("canid: Configuring an existing ematch!\n"); - kfree(cm_old); - } - - return 0; -} - -static void em_canid_destroy(struct tcf_proto *tp, struct tcf_ematch *m) -{ - struct canid_match *cm = em_canid_priv(m); - - kfree(cm); -} - -static int em_canid_dump(struct sk_buff *skb, struct tcf_ematch *m) -{ - struct canid_match *cm = em_canid_priv(m); - - /* - * When configuring this ematch 'rules_count' is set not to exceed - * 'rules_raw' array size - */ - if (nla_put_nohdr(skb, sizeof(struct can_filter) * cm->rules_count, - &cm->rules_raw) < 0) - return -EMSGSIZE; - - return 0; -} - -static struct tcf_ematch_ops em_canid_ops = { - .kind = TCF_EM_CANID, - .change = em_canid_change, - .match = em_canid_match, - .destroy = em_canid_destroy, - .dump = em_canid_dump, - .owner = THIS_MODULE, - .link = LIST_HEAD_INIT(em_canid_ops.link) -}; - -static int __init init_em_canid(void) -{ - return tcf_em_register(&em_canid_ops); -} - -static void __exit exit_em_canid(void) -{ - tcf_em_unregister(&em_canid_ops); -} - -MODULE_LICENSE("GPL"); - -module_init(init_em_canid); -module_exit(exit_em_canid); - -MODULE_ALIAS_TCF_EMATCH(TCF_EM_CANID); diff --git a/trunk/net/sched/em_ipset.c b/trunk/net/sched/em_ipset.c deleted file mode 100644 index 3130320997e2..000000000000 --- a/trunk/net/sched/em_ipset.c +++ /dev/null @@ -1,135 +0,0 @@ -/* - * net/sched/em_ipset.c ipset ematch - * - * Copyright (c) 2012 Florian Westphal - * - * 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 int em_ipset_change(struct tcf_proto *tp, void *data, int data_len, - struct tcf_ematch *em) -{ - struct xt_set_info *set = data; - ip_set_id_t index; - - if (data_len != sizeof(*set)) - return -EINVAL; - - index = ip_set_nfnl_get_byindex(set->index); - if (index == IPSET_INVALID_ID) - return -ENOENT; - - em->datalen = sizeof(*set); - em->data = (unsigned long)kmemdup(data, em->datalen, GFP_KERNEL); - if (em->data) - return 0; - - ip_set_nfnl_put(index); - return -ENOMEM; -} - -static void em_ipset_destroy(struct tcf_proto *p, struct tcf_ematch *em) -{ - const struct xt_set_info *set = (const void *) em->data; - if (set) { - ip_set_nfnl_put(set->index); - kfree((void *) em->data); - } -} - -static int em_ipset_match(struct sk_buff *skb, struct tcf_ematch *em, - struct tcf_pkt_info *info) -{ - struct ip_set_adt_opt opt; - struct xt_action_param acpar; - const struct xt_set_info *set = (const void *) em->data; - struct net_device *dev, *indev = NULL; - int ret, network_offset; - - switch (skb->protocol) { - case htons(ETH_P_IP): - acpar.family = NFPROTO_IPV4; - if (!pskb_network_may_pull(skb, sizeof(struct iphdr))) - return 0; - acpar.thoff = ip_hdrlen(skb); - break; - case htons(ETH_P_IPV6): - acpar.family = NFPROTO_IPV6; - if (!pskb_network_may_pull(skb, sizeof(struct ipv6hdr))) - return 0; - /* doesn't call ipv6_find_hdr() because ipset doesn't use thoff, yet */ - acpar.thoff = sizeof(struct ipv6hdr); - break; - default: - return 0; - } - - acpar.hooknum = 0; - - opt.family = acpar.family; - opt.dim = set->dim; - opt.flags = set->flags; - opt.cmdflags = 0; - opt.timeout = ~0u; - - network_offset = skb_network_offset(skb); - skb_pull(skb, network_offset); - - dev = skb->dev; - - rcu_read_lock(); - - if (dev && skb->skb_iif) - indev = dev_get_by_index_rcu(dev_net(dev), skb->skb_iif); - - acpar.in = indev ? indev : dev; - acpar.out = dev; - - ret = ip_set_test(set->index, skb, &acpar, &opt); - - rcu_read_unlock(); - - skb_push(skb, network_offset); - return ret; -} - -static struct tcf_ematch_ops em_ipset_ops = { - .kind = TCF_EM_IPSET, - .change = em_ipset_change, - .destroy = em_ipset_destroy, - .match = em_ipset_match, - .owner = THIS_MODULE, - .link = LIST_HEAD_INIT(em_ipset_ops.link) -}; - -static int __init init_em_ipset(void) -{ - return tcf_em_register(&em_ipset_ops); -} - -static void __exit exit_em_ipset(void) -{ - tcf_em_unregister(&em_ipset_ops); -} - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Florian Westphal "); -MODULE_DESCRIPTION("TC extended match for IP sets"); - -module_init(init_em_ipset); -module_exit(exit_em_ipset); - -MODULE_ALIAS_TCF_EMATCH(TCF_EM_IPSET); diff --git a/trunk/net/sched/sch_netem.c b/trunk/net/sched/sch_netem.c index 298c0ddfb57e..a2a95aabf9c2 100644 --- a/trunk/net/sched/sch_netem.c +++ b/trunk/net/sched/sch_netem.c @@ -331,22 +331,29 @@ static psched_time_t packet_len_2_sched_time(unsigned int len, struct netem_sche return PSCHED_NS2TICKS(ticks); } -static void tfifo_enqueue(struct sk_buff *nskb, struct Qdisc *sch) +static int tfifo_enqueue(struct sk_buff *nskb, struct Qdisc *sch) { struct sk_buff_head *list = &sch->q; psched_time_t tnext = netem_skb_cb(nskb)->time_to_send; - struct sk_buff *skb = skb_peek_tail(list); + struct sk_buff *skb; - /* Optimize for add at tail */ - if (likely(!skb || tnext >= netem_skb_cb(skb)->time_to_send)) - return __skb_queue_tail(list, nskb); + if (likely(skb_queue_len(list) < sch->limit)) { + skb = skb_peek_tail(list); + /* Optimize for add at tail */ + if (likely(!skb || tnext >= netem_skb_cb(skb)->time_to_send)) + return qdisc_enqueue_tail(nskb, sch); - skb_queue_reverse_walk(list, skb) { - if (tnext >= netem_skb_cb(skb)->time_to_send) - break; + skb_queue_reverse_walk(list, skb) { + if (tnext >= netem_skb_cb(skb)->time_to_send) + break; + } + + __skb_queue_after(list, skb, nskb); + sch->qstats.backlog += qdisc_pkt_len(nskb); + return NET_XMIT_SUCCESS; } - __skb_queue_after(list, skb, nskb); + return qdisc_reshape_fail(nskb, sch); } /* @@ -361,6 +368,7 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch) /* We don't fill cb now as skb_unshare() may invalidate it */ struct netem_skb_cb *cb; struct sk_buff *skb2; + int ret; int count = 1; /* Random duplication */ @@ -380,14 +388,7 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch) return NET_XMIT_SUCCESS | __NET_XMIT_BYPASS; } - /* If a delay is expected, orphan the skb. (orphaning usually takes - * place at TX completion time, so _before_ the link transit delay) - * Ideally, this orphaning should be done after the rate limiting - * module, because this breaks TCP Small Queue, and other mechanisms - * based on socket sk_wmem_alloc. - */ - if (q->latency || q->jitter) - skb_orphan(skb); + skb_orphan(skb); /* * If we need to duplicate packet, then re-insert at top of the @@ -418,11 +419,6 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch) skb->data[net_random() % skb_headlen(skb)] ^= 1<<(net_random() % 8); } - if (unlikely(skb_queue_len(&sch->q) >= sch->limit)) - return qdisc_reshape_fail(skb, sch); - - sch->qstats.backlog += qdisc_pkt_len(skb); - cb = netem_skb_cb(skb); if (q->gap == 0 || /* not doing reordering */ q->counter < q->gap - 1 || /* inside last reordering gap */ @@ -454,7 +450,7 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch) cb->time_to_send = now + delay; ++q->counter; - tfifo_enqueue(skb, sch); + ret = tfifo_enqueue(skb, sch); } else { /* * Do re-ordering by putting one out of N packets at the front @@ -464,7 +460,16 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch) q->counter = 0; __skb_queue_head(&sch->q, skb); + sch->qstats.backlog += qdisc_pkt_len(skb); sch->qstats.requeues++; + ret = NET_XMIT_SUCCESS; + } + + if (ret != NET_XMIT_SUCCESS) { + if (net_xmit_drop_count(ret)) { + sch->qstats.drops++; + return ret; + } } return NET_XMIT_SUCCESS; diff --git a/trunk/net/sctp/associola.c b/trunk/net/sctp/associola.c index 8cf348e62e74..b16517ee1aaf 100644 --- a/trunk/net/sctp/associola.c +++ b/trunk/net/sctp/associola.c @@ -1360,7 +1360,7 @@ struct sctp_transport *sctp_assoc_choose_alter_transport( /* Update the association's pmtu and frag_point by going through all the * transports. This routine is called when a transport's PMTU has changed. */ -void sctp_assoc_sync_pmtu(struct sock *sk, struct sctp_association *asoc) +void sctp_assoc_sync_pmtu(struct sctp_association *asoc) { struct sctp_transport *t; __u32 pmtu = 0; @@ -1372,7 +1372,7 @@ void sctp_assoc_sync_pmtu(struct sock *sk, struct sctp_association *asoc) list_for_each_entry(t, &asoc->peer.transport_addr_list, transports) { if (t->pmtu_pending && t->dst) { - sctp_transport_update_pmtu(sk, t, dst_mtu(t->dst)); + sctp_transport_update_pmtu(t, dst_mtu(t->dst)); t->pmtu_pending = 0; } if (!pmtu || (t->pathmtu < pmtu)) diff --git a/trunk/net/sctp/input.c b/trunk/net/sctp/input.c index c201b26879a1..80564fe03024 100644 --- a/trunk/net/sctp/input.c +++ b/trunk/net/sctp/input.c @@ -408,10 +408,10 @@ void sctp_icmp_frag_needed(struct sock *sk, struct sctp_association *asoc, if (t->param_flags & SPP_PMTUD_ENABLE) { /* Update transports view of the MTU */ - sctp_transport_update_pmtu(sk, t, pmtu); + sctp_transport_update_pmtu(t, pmtu); /* Update association pmtu. */ - sctp_assoc_sync_pmtu(sk, asoc); + sctp_assoc_sync_pmtu(asoc); } /* Retransmit with the new pmtu setting. @@ -423,18 +423,6 @@ void sctp_icmp_frag_needed(struct sock *sk, struct sctp_association *asoc, sctp_retransmit(&asoc->outqueue, t, SCTP_RTXR_PMTUD); } -void sctp_icmp_redirect(struct sock *sk, struct sctp_transport *t, - struct sk_buff *skb) -{ - struct dst_entry *dst; - - if (!t) - return; - dst = sctp_transport_dst_check(t); - if (dst) - dst->ops->redirect(dst, sk, skb); -} - /* * SCTP Implementer's Guide, 2.37 ICMP handling procedures * @@ -640,10 +628,6 @@ void sctp_v4_err(struct sk_buff *skb, __u32 info) err = EHOSTUNREACH; break; - case ICMP_REDIRECT: - sctp_icmp_redirect(sk, transport, skb); - err = 0; - break; default: goto out_unlock; } diff --git a/trunk/net/sctp/ipv6.c b/trunk/net/sctp/ipv6.c index ed7139ea7978..91f479121c55 100644 --- a/trunk/net/sctp/ipv6.c +++ b/trunk/net/sctp/ipv6.c @@ -185,9 +185,6 @@ SCTP_STATIC void sctp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, goto out_unlock; } break; - case NDISC_REDIRECT: - sctp_icmp_redirect(sk, transport, skb); - break; default: break; } diff --git a/trunk/net/sctp/output.c b/trunk/net/sctp/output.c index 838e18b4d7ea..6ae47acaaec6 100644 --- a/trunk/net/sctp/output.c +++ b/trunk/net/sctp/output.c @@ -64,8 +64,6 @@ #include /* Forward declarations for private helpers. */ -static sctp_xmit_t __sctp_packet_append_chunk(struct sctp_packet *packet, - struct sctp_chunk *chunk); static sctp_xmit_t sctp_packet_can_append_data(struct sctp_packet *packet, struct sctp_chunk *chunk); static void sctp_packet_append_data(struct sctp_packet *packet, @@ -226,10 +224,7 @@ static sctp_xmit_t sctp_packet_bundle_auth(struct sctp_packet *pkt, if (!auth) return retval; - retval = __sctp_packet_append_chunk(pkt, auth); - - if (retval != SCTP_XMIT_OK) - sctp_chunk_free(auth); + retval = sctp_packet_append_chunk(pkt, auth); return retval; } @@ -261,31 +256,48 @@ static sctp_xmit_t sctp_packet_bundle_sack(struct sctp_packet *pkt, asoc->a_rwnd = asoc->rwnd; sack = sctp_make_sack(asoc); if (sack) { - retval = __sctp_packet_append_chunk(pkt, sack); - if (retval != SCTP_XMIT_OK) { - sctp_chunk_free(sack); - goto out; - } + retval = sctp_packet_append_chunk(pkt, sack); asoc->peer.sack_needed = 0; if (del_timer(timer)) sctp_association_put(asoc); } } } -out: return retval; } - /* Append a chunk to the offered packet reporting back any inability to do * so. */ -static sctp_xmit_t __sctp_packet_append_chunk(struct sctp_packet *packet, - struct sctp_chunk *chunk) +sctp_xmit_t sctp_packet_append_chunk(struct sctp_packet *packet, + struct sctp_chunk *chunk) { sctp_xmit_t retval = SCTP_XMIT_OK; __u16 chunk_len = WORD_ROUND(ntohs(chunk->chunk_hdr->length)); + SCTP_DEBUG_PRINTK("%s: packet:%p chunk:%p\n", __func__, packet, + chunk); + + /* Data chunks are special. Before seeing what else we can + * bundle into this packet, check to see if we are allowed to + * send this DATA. + */ + if (sctp_chunk_is_data(chunk)) { + retval = sctp_packet_can_append_data(packet, chunk); + if (retval != SCTP_XMIT_OK) + goto finish; + } + + /* Try to bundle AUTH chunk */ + retval = sctp_packet_bundle_auth(packet, chunk); + if (retval != SCTP_XMIT_OK) + goto finish; + + /* Try to bundle SACK chunk */ + retval = sctp_packet_bundle_sack(packet, chunk); + if (retval != SCTP_XMIT_OK) + goto finish; + /* Check to see if this chunk will fit into the packet */ retval = sctp_packet_will_fit(packet, chunk, chunk_len); if (retval != SCTP_XMIT_OK) @@ -327,43 +339,6 @@ static sctp_xmit_t __sctp_packet_append_chunk(struct sctp_packet *packet, return retval; } -/* Append a chunk to the offered packet reporting back any inability to do - * so. - */ -sctp_xmit_t sctp_packet_append_chunk(struct sctp_packet *packet, - struct sctp_chunk *chunk) -{ - sctp_xmit_t retval = SCTP_XMIT_OK; - - SCTP_DEBUG_PRINTK("%s: packet:%p chunk:%p\n", __func__, packet, - chunk); - - /* Data chunks are special. Before seeing what else we can - * bundle into this packet, check to see if we are allowed to - * send this DATA. - */ - if (sctp_chunk_is_data(chunk)) { - retval = sctp_packet_can_append_data(packet, chunk); - if (retval != SCTP_XMIT_OK) - goto finish; - } - - /* Try to bundle AUTH chunk */ - retval = sctp_packet_bundle_auth(packet, chunk); - if (retval != SCTP_XMIT_OK) - goto finish; - - /* Try to bundle SACK chunk */ - retval = sctp_packet_bundle_sack(packet, chunk); - if (retval != SCTP_XMIT_OK) - goto finish; - - retval = __sctp_packet_append_chunk(packet, chunk); - -finish: - return retval; -} - /* All packets are sent to the network through this function from * sctp_outq_tail(). * @@ -410,7 +385,7 @@ int sctp_packet_transmit(struct sctp_packet *packet) if (!sctp_transport_dst_check(tp)) { sctp_transport_route(tp, NULL, sctp_sk(sk)); if (asoc && (asoc->param_flags & SPP_PMTUD_ENABLE)) { - sctp_assoc_sync_pmtu(sk, asoc); + sctp_assoc_sync_pmtu(asoc); } } dst = dst_clone(tp->dst); diff --git a/trunk/net/sctp/sm_make_chunk.c b/trunk/net/sctp/sm_make_chunk.c index 479a70ef6ff8..b6de71efb140 100644 --- a/trunk/net/sctp/sm_make_chunk.c +++ b/trunk/net/sctp/sm_make_chunk.c @@ -132,7 +132,7 @@ void sctp_init_cause(struct sctp_chunk *chunk, __be16 cause_code, * abort chunk. Differs from sctp_init_cause in that it won't oops * if there isn't enough space in the op error chunk */ -static int sctp_init_cause_fixed(struct sctp_chunk *chunk, __be16 cause_code, +int sctp_init_cause_fixed(struct sctp_chunk *chunk, __be16 cause_code, size_t paylen) { sctp_errhdr_t err; diff --git a/trunk/net/sctp/socket.c b/trunk/net/sctp/socket.c index 74bd3c47350a..b3b8a8d813eb 100644 --- a/trunk/net/sctp/socket.c +++ b/trunk/net/sctp/socket.c @@ -1853,7 +1853,7 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, } if (asoc->pmtu_pending) - sctp_assoc_pending_pmtu(sk, asoc); + sctp_assoc_pending_pmtu(asoc); /* If fragmentation is disabled and the message length exceeds the * association fragmentation point, return EMSGSIZE. The I-D @@ -2365,7 +2365,7 @@ static int sctp_apply_peer_addr_params(struct sctp_paddrparams *params, if ((params->spp_flags & SPP_PMTUD_DISABLE) && params->spp_pathmtu) { if (trans) { trans->pathmtu = params->spp_pathmtu; - sctp_assoc_sync_pmtu(sctp_opt2sk(sp), asoc); + sctp_assoc_sync_pmtu(asoc); } else if (asoc) { asoc->pathmtu = params->spp_pathmtu; sctp_frag_point(asoc, params->spp_pathmtu); @@ -2382,7 +2382,7 @@ static int sctp_apply_peer_addr_params(struct sctp_paddrparams *params, (trans->param_flags & ~SPP_PMTUD) | pmtud_change; if (update) { sctp_transport_pmtu(trans, sctp_opt2sk(sp)); - sctp_assoc_sync_pmtu(sctp_opt2sk(sp), asoc); + sctp_assoc_sync_pmtu(asoc); } } else if (asoc) { asoc->param_flags = diff --git a/trunk/net/sctp/transport.c b/trunk/net/sctp/transport.c index a6b7ee9ce28a..1dcceb6e0ce6 100644 --- a/trunk/net/sctp/transport.c +++ b/trunk/net/sctp/transport.c @@ -228,7 +228,7 @@ void sctp_transport_pmtu(struct sctp_transport *transport, struct sock *sk) transport->pathmtu = SCTP_DEFAULT_MAXSEGMENT; } -void sctp_transport_update_pmtu(struct sock *sk, struct sctp_transport *t, u32 pmtu) +void sctp_transport_update_pmtu(struct sctp_transport *t, u32 pmtu) { struct dst_entry *dst; @@ -245,16 +245,8 @@ void sctp_transport_update_pmtu(struct sock *sk, struct sctp_transport *t, u32 p } dst = sctp_transport_dst_check(t); - if (!dst) - t->af_specific->get_dst(t, &t->saddr, &t->fl, sk); - - if (dst) { - dst->ops->update_pmtu(dst, sk, NULL, pmtu); - - dst = sctp_transport_dst_check(t); - if (!dst) - t->af_specific->get_dst(t, &t->saddr, &t->fl, sk); - } + if (dst) + dst->ops->update_pmtu(dst, pmtu); } /* Caches the dst entry and source address for a transport's destination diff --git a/trunk/net/sunrpc/backchannel_rqst.c b/trunk/net/sunrpc/backchannel_rqst.c index 5a3d675d2f2f..31def68a0f6e 100644 --- a/trunk/net/sunrpc/backchannel_rqst.c +++ b/trunk/net/sunrpc/backchannel_rqst.c @@ -176,14 +176,13 @@ int xprt_setup_backchannel(struct rpc_xprt *xprt, unsigned int min_reqs) } EXPORT_SYMBOL_GPL(xprt_setup_backchannel); -/** - * xprt_destroy_backchannel - Destroys the backchannel preallocated structures. - * @xprt: the transport holding the preallocated strucures - * @max_reqs the maximum number of preallocated structures to destroy - * +/* + * Destroys the backchannel preallocated structures. * Since these structures may have been allocated by multiple calls * to xprt_setup_backchannel, we only destroy up to the maximum number * of reqs specified by the caller. + * @xprt: the transport holding the preallocated strucures + * @max_reqs the maximum number of preallocated structures to destroy */ void xprt_destroy_backchannel(struct rpc_xprt *xprt, unsigned int max_reqs) { diff --git a/trunk/net/sunrpc/clnt.c b/trunk/net/sunrpc/clnt.c index 00eb859b7de5..f56f045778ae 100644 --- a/trunk/net/sunrpc/clnt.c +++ b/trunk/net/sunrpc/clnt.c @@ -385,7 +385,7 @@ static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, stru return ERR_PTR(err); } -/** +/* * rpc_create - create an RPC client and transport with one call * @args: rpc_clnt create argument structure * diff --git a/trunk/net/sunrpc/xdr.c b/trunk/net/sunrpc/xdr.c index 0cf165580d8d..fddcccfcdf76 100644 --- a/trunk/net/sunrpc/xdr.c +++ b/trunk/net/sunrpc/xdr.c @@ -180,9 +180,7 @@ EXPORT_SYMBOL_GPL(xdr_inline_pages); /* * Helper routines for doing 'memmove' like operations on a struct xdr_buf - */ - -/** + * * _shift_data_right_pages * @pages: vector of pages containing both the source and dest memory area. * @pgto_base: page vector address of destination @@ -244,7 +242,7 @@ _shift_data_right_pages(struct page **pages, size_t pgto_base, } while ((len -= copy) != 0); } -/** +/* * _copy_to_pages * @pages: array of pages * @pgbase: page vector address of destination @@ -288,7 +286,7 @@ _copy_to_pages(struct page **pages, size_t pgbase, const char *p, size_t len) flush_dcache_page(*pgto); } -/** +/* * _copy_from_pages * @p: pointer to destination * @pages: array of pages @@ -328,7 +326,7 @@ _copy_from_pages(char *p, struct page **pages, size_t pgbase, size_t len) } EXPORT_SYMBOL_GPL(_copy_from_pages); -/** +/* * xdr_shrink_bufhead * @buf: xdr_buf * @len: bytes to remove from buf->head[0] @@ -401,7 +399,7 @@ xdr_shrink_bufhead(struct xdr_buf *buf, size_t len) buf->len = buf->buflen; } -/** +/* * xdr_shrink_pagelen * @buf: xdr_buf * @len: bytes to remove from buf->pages diff --git a/trunk/net/sunrpc/xprt.c b/trunk/net/sunrpc/xprt.c index a5a402a7d21f..3c83035cdaa9 100644 --- a/trunk/net/sunrpc/xprt.c +++ b/trunk/net/sunrpc/xprt.c @@ -531,7 +531,7 @@ void xprt_set_retrans_timeout_def(struct rpc_task *task) } EXPORT_SYMBOL_GPL(xprt_set_retrans_timeout_def); -/** +/* * xprt_set_retrans_timeout_rtt - set a request's retransmit timeout * @task: task whose timeout is to be set * diff --git a/trunk/net/tipc/Kconfig b/trunk/net/tipc/Kconfig index 585460180ffb..2c5954b85933 100644 --- a/trunk/net/tipc/Kconfig +++ b/trunk/net/tipc/Kconfig @@ -41,4 +41,29 @@ config TIPC_PORTS Setting this to a smaller value saves some memory, setting it to higher allows for more ports. +config TIPC_LOG + int "Size of log buffer" + depends on TIPC_ADVANCED + range 0 32768 + default "0" + help + Size (in bytes) of TIPC's internal log buffer, which records the + occurrence of significant events. Can range from 0 to 32768 bytes; + default is 0. + + There is no need to enable the log buffer unless the node will be + managed remotely via TIPC. + +config TIPC_DEBUG + bool "Enable debugging support" + default n + help + Saying Y here enables TIPC debugging capabilities used by developers. + Most users do not need to bother; if unsure, just say N. + + Enabling debugging support causes TIPC to display data about its + internal state when certain abnormal conditions occur. It also + makes it easy for developers to capture additional information of + interest using the dbg() or msg_dbg() macros. + endif # TIPC diff --git a/trunk/net/tipc/bcast.c b/trunk/net/tipc/bcast.c index e4e6d8cd47e6..2625f5ebe3e8 100644 --- a/trunk/net/tipc/bcast.c +++ b/trunk/net/tipc/bcast.c @@ -162,7 +162,7 @@ static void bclink_update_last_sent(struct tipc_node *node, u32 seqno) } -/** +/* * tipc_bclink_retransmit_to - get most recent node to request retransmission * * Called with bc_lock locked @@ -270,7 +270,7 @@ void tipc_bclink_acknowledge(struct tipc_node *n_ptr, u32 acked) spin_unlock_bh(&bc_lock); } -/** +/* * tipc_bclink_update_link_state - update broadcast link state * * tipc_net_lock and node lock set @@ -330,7 +330,7 @@ void tipc_bclink_update_link_state(struct tipc_node *n_ptr, u32 last_sent) } } -/** +/* * bclink_peek_nack - monitor retransmission requests sent by other nodes * * Delay any upcoming NACK by this node if another node has already @@ -381,7 +381,7 @@ int tipc_bclink_send_msg(struct sk_buff *buf) return res; } -/** +/* * bclink_accept_pkt - accept an incoming, in-sequence broadcast packet * * Called with both sending node's lock and bc_lock taken. @@ -406,7 +406,7 @@ static void bclink_accept_pkt(struct tipc_node *node, u32 seqno) } } -/** +/* * tipc_bclink_recv_pkt - receive a broadcast packet, and deliver upwards * * tipc_net_lock is read_locked, no other locks set @@ -701,43 +701,48 @@ void tipc_bcbearer_sort(void) int tipc_bclink_stats(char *buf, const u32 buf_size) { - int ret; - struct tipc_stats *s; + struct print_buf pb; if (!bcl) return 0; + tipc_printbuf_init(&pb, buf, buf_size); + spin_lock_bh(&bc_lock); - s = &bcl->stats; - - ret = tipc_snprintf(buf, buf_size, "Link <%s>\n" - " Window:%u packets\n", - bcl->name, bcl->queue_limit[0]); - ret += tipc_snprintf(buf + ret, buf_size - ret, - " RX packets:%u fragments:%u/%u bundles:%u/%u\n", - s->recv_info, s->recv_fragments, - s->recv_fragmented, s->recv_bundles, - s->recv_bundled); - ret += tipc_snprintf(buf + ret, buf_size - ret, - " TX packets:%u fragments:%u/%u bundles:%u/%u\n", - s->sent_info, s->sent_fragments, - s->sent_fragmented, s->sent_bundles, - s->sent_bundled); - ret += tipc_snprintf(buf + ret, buf_size - ret, - " RX naks:%u defs:%u dups:%u\n", - s->recv_nacks, s->deferred_recv, s->duplicates); - ret += tipc_snprintf(buf + ret, buf_size - ret, - " TX naks:%u acks:%u dups:%u\n", - s->sent_nacks, s->sent_acks, s->retransmitted); - ret += tipc_snprintf(buf + ret, buf_size - ret, - " Congestion bearer:%u link:%u Send queue max:%u avg:%u\n", - s->bearer_congs, s->link_congs, s->max_queue_sz, - s->queue_sz_counts ? - (s->accu_queue_sz / s->queue_sz_counts) : 0); + tipc_printf(&pb, "Link <%s>\n" + " Window:%u packets\n", + bcl->name, bcl->queue_limit[0]); + tipc_printf(&pb, " RX packets:%u fragments:%u/%u bundles:%u/%u\n", + bcl->stats.recv_info, + bcl->stats.recv_fragments, + bcl->stats.recv_fragmented, + bcl->stats.recv_bundles, + bcl->stats.recv_bundled); + tipc_printf(&pb, " TX packets:%u fragments:%u/%u bundles:%u/%u\n", + bcl->stats.sent_info, + bcl->stats.sent_fragments, + bcl->stats.sent_fragmented, + bcl->stats.sent_bundles, + bcl->stats.sent_bundled); + tipc_printf(&pb, " RX naks:%u defs:%u dups:%u\n", + bcl->stats.recv_nacks, + bcl->stats.deferred_recv, + bcl->stats.duplicates); + tipc_printf(&pb, " TX naks:%u acks:%u dups:%u\n", + bcl->stats.sent_nacks, + bcl->stats.sent_acks, + bcl->stats.retransmitted); + tipc_printf(&pb, " Congestion bearer:%u link:%u Send queue max:%u avg:%u\n", + bcl->stats.bearer_congs, + bcl->stats.link_congs, + bcl->stats.max_queue_sz, + bcl->stats.queue_sz_counts + ? (bcl->stats.accu_queue_sz / bcl->stats.queue_sz_counts) + : 0); spin_unlock_bh(&bc_lock); - return ret; + return tipc_printbuf_validate(&pb); } int tipc_bclink_reset_stats(void) @@ -875,7 +880,7 @@ void tipc_port_list_add(struct tipc_port_list *pl_ptr, u32 port) if (!item->next) { item->next = kmalloc(sizeof(*item), GFP_ATOMIC); if (!item->next) { - pr_warn("Incomplete multicast delivery, no memory\n"); + warn("Incomplete multicast delivery, no memory\n"); return; } item->next->next = NULL; diff --git a/trunk/net/tipc/bearer.c b/trunk/net/tipc/bearer.c index 09e71241265d..a297e3a2e3e7 100644 --- a/trunk/net/tipc/bearer.c +++ b/trunk/net/tipc/bearer.c @@ -123,30 +123,28 @@ int tipc_register_media(struct tipc_media *m_ptr) exit: write_unlock_bh(&tipc_net_lock); if (res) - pr_warn("Media <%s> registration error\n", m_ptr->name); + warn("Media <%s> registration error\n", m_ptr->name); return res; } /** * tipc_media_addr_printf - record media address in print buffer */ -void tipc_media_addr_printf(char *buf, int len, struct tipc_media_addr *a) +void tipc_media_addr_printf(struct print_buf *pb, struct tipc_media_addr *a) { char addr_str[MAX_ADDR_STR]; struct tipc_media *m_ptr; - int ret; m_ptr = media_find_id(a->media_id); if (m_ptr && !m_ptr->addr2str(a, addr_str, sizeof(addr_str))) - ret = tipc_snprintf(buf, len, "%s(%s)", m_ptr->name, addr_str); + tipc_printf(pb, "%s(%s)", m_ptr->name, addr_str); else { u32 i; - ret = tipc_snprintf(buf, len, "UNKNOWN(%u)", a->media_id); + tipc_printf(pb, "UNKNOWN(%u)", a->media_id); for (i = 0; i < sizeof(a->value); i++) - ret += tipc_snprintf(buf - ret, len + ret, - "-%02x", a->value[i]); + tipc_printf(pb, "-%02x", a->value[i]); } } @@ -174,8 +172,8 @@ struct sk_buff *tipc_media_get_names(void) /** * bearer_name_validate - validate & (optionally) deconstruct bearer name - * @name: ptr to bearer name string - * @name_parts: ptr to area for bearer name components (or NULL if not needed) + * @name - ptr to bearer name string + * @name_parts - ptr to area for bearer name components (or NULL if not needed) * * Returns 1 if bearer name is valid, otherwise 0. */ @@ -420,12 +418,12 @@ int tipc_enable_bearer(const char *name, u32 disc_domain, u32 priority) int res = -EINVAL; if (!tipc_own_addr) { - pr_warn("Bearer <%s> rejected, not supported in standalone mode\n", - name); + warn("Bearer <%s> rejected, not supported in standalone mode\n", + name); return -ENOPROTOOPT; } if (!bearer_name_validate(name, &b_names)) { - pr_warn("Bearer <%s> rejected, illegal name\n", name); + warn("Bearer <%s> rejected, illegal name\n", name); return -EINVAL; } if (tipc_addr_domain_valid(disc_domain) && @@ -437,13 +435,12 @@ int tipc_enable_bearer(const char *name, u32 disc_domain, u32 priority) res = 0; /* accept specified node in own cluster */ } if (res) { - pr_warn("Bearer <%s> rejected, illegal discovery domain\n", - name); + warn("Bearer <%s> rejected, illegal discovery domain\n", name); return -EINVAL; } if ((priority > TIPC_MAX_LINK_PRI) && (priority != TIPC_MEDIA_LINK_PRI)) { - pr_warn("Bearer <%s> rejected, illegal priority\n", name); + warn("Bearer <%s> rejected, illegal priority\n", name); return -EINVAL; } @@ -451,8 +448,8 @@ int tipc_enable_bearer(const char *name, u32 disc_domain, u32 priority) m_ptr = tipc_media_find(b_names.media_name); if (!m_ptr) { - pr_warn("Bearer <%s> rejected, media <%s> not registered\n", - name, b_names.media_name); + warn("Bearer <%s> rejected, media <%s> not registered\n", name, + b_names.media_name); goto exit; } @@ -468,25 +465,24 @@ int tipc_enable_bearer(const char *name, u32 disc_domain, u32 priority) continue; } if (!strcmp(name, tipc_bearers[i].name)) { - pr_warn("Bearer <%s> rejected, already enabled\n", - name); + warn("Bearer <%s> rejected, already enabled\n", name); goto exit; } if ((tipc_bearers[i].priority == priority) && (++with_this_prio > 2)) { if (priority-- == 0) { - pr_warn("Bearer <%s> rejected, duplicate priority\n", - name); + warn("Bearer <%s> rejected, duplicate priority\n", + name); goto exit; } - pr_warn("Bearer <%s> priority adjustment required %u->%u\n", - name, priority + 1, priority); + warn("Bearer <%s> priority adjustment required %u->%u\n", + name, priority + 1, priority); goto restart; } } if (bearer_id >= MAX_BEARERS) { - pr_warn("Bearer <%s> rejected, bearer limit reached (%u)\n", - name, MAX_BEARERS); + warn("Bearer <%s> rejected, bearer limit reached (%u)\n", + name, MAX_BEARERS); goto exit; } @@ -494,8 +490,7 @@ int tipc_enable_bearer(const char *name, u32 disc_domain, u32 priority) strcpy(b_ptr->name, name); res = m_ptr->enable_bearer(b_ptr); if (res) { - pr_warn("Bearer <%s> rejected, enable failure (%d)\n", - name, -res); + warn("Bearer <%s> rejected, enable failure (%d)\n", name, -res); goto exit; } @@ -513,20 +508,20 @@ int tipc_enable_bearer(const char *name, u32 disc_domain, u32 priority) res = tipc_disc_create(b_ptr, &m_ptr->bcast_addr, disc_domain); if (res) { bearer_disable(b_ptr); - pr_warn("Bearer <%s> rejected, discovery object creation failed\n", - name); + warn("Bearer <%s> rejected, discovery object creation failed\n", + name); goto exit; } - pr_info("Enabled bearer <%s>, discovery domain %s, priority %u\n", - name, - tipc_addr_string_fill(addr_string, disc_domain), priority); + info("Enabled bearer <%s>, discovery domain %s, priority %u\n", + name, tipc_addr_string_fill(addr_string, disc_domain), priority); exit: write_unlock_bh(&tipc_net_lock); return res; } /** - * tipc_block_bearer - Block the bearer with the given name, and reset all its links + * tipc_block_bearer(): Block the bearer with the given name, + * and reset all its links */ int tipc_block_bearer(const char *name) { @@ -537,12 +532,12 @@ int tipc_block_bearer(const char *name) read_lock_bh(&tipc_net_lock); b_ptr = tipc_bearer_find(name); if (!b_ptr) { - pr_warn("Attempt to block unknown bearer <%s>\n", name); + warn("Attempt to block unknown bearer <%s>\n", name); read_unlock_bh(&tipc_net_lock); return -EINVAL; } - pr_info("Blocking bearer <%s>\n", name); + info("Blocking bearer <%s>\n", name); spin_lock_bh(&b_ptr->lock); b_ptr->blocked = 1; list_splice_init(&b_ptr->cong_links, &b_ptr->links); @@ -568,7 +563,7 @@ static void bearer_disable(struct tipc_bearer *b_ptr) struct tipc_link *l_ptr; struct tipc_link *temp_l_ptr; - pr_info("Disabling bearer <%s>\n", b_ptr->name); + info("Disabling bearer <%s>\n", b_ptr->name); spin_lock_bh(&b_ptr->lock); b_ptr->blocked = 1; b_ptr->media->disable_bearer(b_ptr); @@ -590,7 +585,7 @@ int tipc_disable_bearer(const char *name) write_lock_bh(&tipc_net_lock); b_ptr = tipc_bearer_find(name); if (b_ptr == NULL) { - pr_warn("Attempt to disable unknown bearer <%s>\n", name); + warn("Attempt to disable unknown bearer <%s>\n", name); res = -EINVAL; } else { bearer_disable(b_ptr); diff --git a/trunk/net/tipc/bearer.h b/trunk/net/tipc/bearer.h index dd4c2abf08e7..e3b2be37fb31 100644 --- a/trunk/net/tipc/bearer.h +++ b/trunk/net/tipc/bearer.h @@ -57,7 +57,7 @@ */ #define TIPC_MEDIA_TYPE_ETH 1 -/** +/* * struct tipc_media_addr - destination address used by TIPC bearers * @value: address info (format defined by media) * @media_id: TIPC media type identifier @@ -179,7 +179,7 @@ void tipc_eth_media_stop(void); int tipc_media_set_priority(const char *name, u32 new_value); int tipc_media_set_window(const char *name, u32 new_value); -void tipc_media_addr_printf(char *buf, int len, struct tipc_media_addr *a); +void tipc_media_addr_printf(struct print_buf *pb, struct tipc_media_addr *a); struct sk_buff *tipc_media_get_names(void); struct sk_buff *tipc_bearer_get_names(void); diff --git a/trunk/net/tipc/config.c b/trunk/net/tipc/config.c index a056a3852f71..c5712a343810 100644 --- a/trunk/net/tipc/config.c +++ b/trunk/net/tipc/config.c @@ -39,8 +39,6 @@ #include "name_table.h" #include "config.h" -#define REPLY_TRUNCATED "\n" - static u32 config_port_ref; static DEFINE_SPINLOCK(config_lock); @@ -106,12 +104,13 @@ struct sk_buff *tipc_cfg_reply_string_type(u16 tlv_type, char *string) return buf; } +#define MAX_STATS_INFO 2000 + static struct sk_buff *tipc_show_stats(void) { struct sk_buff *buf; struct tlv_desc *rep_tlv; - char *pb; - int pb_len; + struct print_buf pb; int str_len; u32 value; @@ -122,16 +121,17 @@ static struct sk_buff *tipc_show_stats(void) if (value != 0) return tipc_cfg_reply_error_string("unsupported argument"); - buf = tipc_cfg_reply_alloc(TLV_SPACE(ULTRA_STRING_MAX_LEN)); + buf = tipc_cfg_reply_alloc(TLV_SPACE(MAX_STATS_INFO)); if (buf == NULL) return NULL; rep_tlv = (struct tlv_desc *)buf->data; - pb = TLV_DATA(rep_tlv); - pb_len = ULTRA_STRING_MAX_LEN; + tipc_printbuf_init(&pb, (char *)TLV_DATA(rep_tlv), MAX_STATS_INFO); + + tipc_printf(&pb, "TIPC version " TIPC_MOD_VER "\n"); - str_len = tipc_snprintf(pb, pb_len, "TIPC version " TIPC_MOD_VER "\n"); - str_len += 1; /* for "\0" */ + /* Use additional tipc_printf()'s to return more info ... */ + str_len = tipc_printbuf_validate(&pb); skb_put(buf, TLV_SPACE(str_len)); TLV_SET(rep_tlv, TIPC_TLV_ULTRA_STRING, NULL, str_len); @@ -334,6 +334,12 @@ struct sk_buff *tipc_cfg_do_cmd(u32 orig_node, u16 cmd, const void *request_area case TIPC_CMD_SHOW_PORTS: rep_tlv_buf = tipc_port_get_ports(); break; + case TIPC_CMD_SET_LOG_SIZE: + rep_tlv_buf = tipc_log_resize_cmd(req_tlv_area, req_tlv_space); + break; + case TIPC_CMD_DUMP_LOG: + rep_tlv_buf = tipc_log_dump(); + break; case TIPC_CMD_SHOW_STATS: rep_tlv_buf = tipc_show_stats(); break; @@ -393,8 +399,6 @@ struct sk_buff *tipc_cfg_do_cmd(u32 orig_node, u16 cmd, const void *request_area case TIPC_CMD_GET_MAX_CLUSTERS: case TIPC_CMD_SET_MAX_NODES: case TIPC_CMD_GET_MAX_NODES: - case TIPC_CMD_SET_LOG_SIZE: - case TIPC_CMD_DUMP_LOG: rep_tlv_buf = tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED " (obsolete command)"); break; @@ -404,15 +408,6 @@ struct sk_buff *tipc_cfg_do_cmd(u32 orig_node, u16 cmd, const void *request_area break; } - WARN_ON(rep_tlv_buf->len > TLV_SPACE(ULTRA_STRING_MAX_LEN)); - - /* Append an error message if we cannot return all requested data */ - if (rep_tlv_buf->len == TLV_SPACE(ULTRA_STRING_MAX_LEN)) { - if (*(rep_tlv_buf->data + ULTRA_STRING_MAX_LEN) != '\0') - sprintf(rep_tlv_buf->data + rep_tlv_buf->len - - sizeof(REPLY_TRUNCATED) - 1, REPLY_TRUNCATED); - } - /* Return reply buffer */ exit: spin_unlock_bh(&config_lock); @@ -437,7 +432,7 @@ static void cfg_named_msg_event(void *userdata, if ((size < sizeof(*req_hdr)) || (size != TCM_ALIGN(ntohl(req_hdr->tcm_len))) || (ntohs(req_hdr->tcm_flags) != TCM_F_REQUEST)) { - pr_warn("Invalid configuration message discarded\n"); + warn("Invalid configuration message discarded\n"); return; } @@ -483,7 +478,7 @@ int tipc_cfg_init(void) return 0; failed: - pr_err("Unable to create configuration service\n"); + err("Unable to create configuration service\n"); return res; } @@ -499,7 +494,7 @@ void tipc_cfg_reinit(void) seq.lower = seq.upper = tipc_own_addr; res = tipc_publish(config_port_ref, TIPC_ZONE_SCOPE, &seq); if (res) - pr_err("Unable to reinitialize configuration service\n"); + err("Unable to reinitialize configuration service\n"); } void tipc_cfg_stop(void) diff --git a/trunk/net/tipc/core.c b/trunk/net/tipc/core.c index 6586eac6a50e..f7b95239ebda 100644 --- a/trunk/net/tipc/core.c +++ b/trunk/net/tipc/core.c @@ -34,18 +34,22 @@ * POSSIBILITY OF SUCH DAMAGE. */ +#include + #include "core.h" #include "ref.h" #include "name_table.h" #include "subscr.h" #include "config.h" -#include #ifndef CONFIG_TIPC_PORTS #define CONFIG_TIPC_PORTS 8191 #endif +#ifndef CONFIG_TIPC_LOG +#define CONFIG_TIPC_LOG 0 +#endif /* global variables used by multiple sub-systems within TIPC */ int tipc_random; @@ -121,6 +125,7 @@ static void tipc_core_stop(void) tipc_nametbl_stop(); tipc_ref_table_stop(); tipc_socket_stop(); + tipc_log_resize(0); } /** @@ -156,7 +161,10 @@ static int __init tipc_init(void) { int res; - pr_info("Activated (version " TIPC_MOD_VER ")\n"); + if (tipc_log_resize(CONFIG_TIPC_LOG) != 0) + warn("Unable to create log buffer\n"); + + info("Activated (version " TIPC_MOD_VER ")\n"); tipc_own_addr = 0; tipc_remote_management = 1; @@ -167,9 +175,9 @@ static int __init tipc_init(void) res = tipc_core_start(); if (res) - pr_err("Unable to start in single node mode\n"); + err("Unable to start in single node mode\n"); else - pr_info("Started in single node mode\n"); + info("Started in single node mode\n"); return res; } @@ -177,7 +185,7 @@ static void __exit tipc_exit(void) { tipc_core_stop_net(); tipc_core_stop(); - pr_info("Deactivated\n"); + info("Deactivated\n"); } module_init(tipc_init); diff --git a/trunk/net/tipc/core.h b/trunk/net/tipc/core.h index fd42e106c185..2a9bb99537b3 100644 --- a/trunk/net/tipc/core.h +++ b/trunk/net/tipc/core.h @@ -37,8 +37,6 @@ #ifndef _TIPC_CORE_H #define _TIPC_CORE_H -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - #include #include #include @@ -60,11 +58,68 @@ #define TIPC_MOD_VER "2.0.0" -#define ULTRA_STRING_MAX_LEN 32768 - struct tipc_msg; /* msg.h */ +struct print_buf; /* log.h */ + +/* + * TIPC system monitoring code + */ + +/* + * TIPC's print buffer subsystem supports the following print buffers: + * + * TIPC_NULL : null buffer (i.e. print nowhere) + * TIPC_CONS : system console + * TIPC_LOG : TIPC log buffer + * &buf : user-defined buffer (struct print_buf *) + * + * Note: TIPC_LOG is configured to echo its output to the system console; + * user-defined buffers can be configured to do the same thing. + */ +extern struct print_buf *const TIPC_NULL; +extern struct print_buf *const TIPC_CONS; +extern struct print_buf *const TIPC_LOG; + +void tipc_printf(struct print_buf *, const char *fmt, ...); + +/* + * TIPC_OUTPUT is the destination print buffer for system messages. + */ +#ifndef TIPC_OUTPUT +#define TIPC_OUTPUT TIPC_LOG +#endif + +#define err(fmt, arg...) tipc_printf(TIPC_OUTPUT, \ + KERN_ERR "TIPC: " fmt, ## arg) +#define warn(fmt, arg...) tipc_printf(TIPC_OUTPUT, \ + KERN_WARNING "TIPC: " fmt, ## arg) +#define info(fmt, arg...) tipc_printf(TIPC_OUTPUT, \ + KERN_NOTICE "TIPC: " fmt, ## arg) + +#ifdef CONFIG_TIPC_DEBUG + +/* + * DBG_OUTPUT is the destination print buffer for debug messages. + */ +#ifndef DBG_OUTPUT +#define DBG_OUTPUT TIPC_LOG +#endif + +#define dbg(fmt, arg...) tipc_printf(DBG_OUTPUT, KERN_DEBUG fmt, ## arg); + +#define msg_dbg(msg, txt) tipc_msg_dbg(DBG_OUTPUT, msg, txt); + +void tipc_msg_dbg(struct print_buf *, struct tipc_msg *, const char *); + +#else + +#define dbg(fmt, arg...) do {} while (0) +#define msg_dbg(msg, txt) do {} while (0) + +#define tipc_msg_dbg(buf, msg, txt) do {} while (0) + +#endif -int tipc_snprintf(char *buf, int len, const char *fmt, ...); /* * TIPC-specific error codes diff --git a/trunk/net/tipc/discover.c b/trunk/net/tipc/discover.c index 50eaa403eb6e..ae054cfe179f 100644 --- a/trunk/net/tipc/discover.c +++ b/trunk/net/tipc/discover.c @@ -100,12 +100,14 @@ static void disc_dupl_alert(struct tipc_bearer *b_ptr, u32 node_addr, { char node_addr_str[16]; char media_addr_str[64]; + struct print_buf pb; tipc_addr_string_fill(node_addr_str, node_addr); - tipc_media_addr_printf(media_addr_str, sizeof(media_addr_str), - media_addr); - pr_warn("Duplicate %s using %s seen on <%s>\n", node_addr_str, - media_addr_str, b_ptr->name); + tipc_printbuf_init(&pb, media_addr_str, sizeof(media_addr_str)); + tipc_media_addr_printf(&pb, media_addr); + tipc_printbuf_validate(&pb); + warn("Duplicate %s using %s seen on <%s>\n", + node_addr_str, media_addr_str, b_ptr->name); } /** diff --git a/trunk/net/tipc/handler.c b/trunk/net/tipc/handler.c index 7a52d3922f3c..9c6f22ff1c6d 100644 --- a/trunk/net/tipc/handler.c +++ b/trunk/net/tipc/handler.c @@ -57,14 +57,14 @@ unsigned int tipc_k_signal(Handler routine, unsigned long argument) struct queue_item *item; if (!handler_enabled) { - pr_err("Signal request ignored by handler\n"); + err("Signal request ignored by handler\n"); return -ENOPROTOOPT; } spin_lock_bh(&qitem_lock); item = kmem_cache_alloc(tipc_queue_item_cache, GFP_ATOMIC); if (!item) { - pr_err("Signal queue out of memory\n"); + err("Signal queue out of memory\n"); spin_unlock_bh(&qitem_lock); return -ENOMEM; } diff --git a/trunk/net/tipc/link.c b/trunk/net/tipc/link.c index 1c1e6151875e..7a614f43549d 100644 --- a/trunk/net/tipc/link.c +++ b/trunk/net/tipc/link.c @@ -41,12 +41,6 @@ #include "discover.h" #include "config.h" -/* - * Error message prefixes - */ -static const char *link_co_err = "Link changeover error, "; -static const char *link_rst_msg = "Resetting link "; -static const char *link_unk_evt = "Unknown link event "; /* * Out-of-range value for link session numbers @@ -159,8 +153,8 @@ int tipc_link_is_active(struct tipc_link *l_ptr) /** * link_name_validate - validate & (optionally) deconstruct tipc_link name - * @name: ptr to link name string - * @name_parts: ptr to area for link name components (or NULL if not needed) + * @name - ptr to link name string + * @name_parts - ptr to area for link name components (or NULL if not needed) * * Returns 1 if link name is valid, otherwise 0. */ @@ -306,20 +300,20 @@ struct tipc_link *tipc_link_create(struct tipc_node *n_ptr, if (n_ptr->link_cnt >= 2) { tipc_addr_string_fill(addr_string, n_ptr->addr); - pr_err("Attempt to establish third link to %s\n", addr_string); + err("Attempt to establish third link to %s\n", addr_string); return NULL; } if (n_ptr->links[b_ptr->identity]) { tipc_addr_string_fill(addr_string, n_ptr->addr); - pr_err("Attempt to establish second link on <%s> to %s\n", - b_ptr->name, addr_string); + err("Attempt to establish second link on <%s> to %s\n", + b_ptr->name, addr_string); return NULL; } l_ptr = kzalloc(sizeof(*l_ptr), GFP_ATOMIC); if (!l_ptr) { - pr_warn("Link creation failed, no memory\n"); + warn("Link creation failed, no memory\n"); return NULL; } @@ -377,7 +371,7 @@ struct tipc_link *tipc_link_create(struct tipc_node *n_ptr, void tipc_link_delete(struct tipc_link *l_ptr) { if (!l_ptr) { - pr_err("Attempt to delete non-existent link\n"); + err("Attempt to delete non-existent link\n"); return; } @@ -638,8 +632,8 @@ static void link_state_event(struct tipc_link *l_ptr, unsigned int event) link_set_timer(l_ptr, cont_intv / 4); break; case RESET_MSG: - pr_info("%s<%s>, requested by peer\n", link_rst_msg, - l_ptr->name); + info("Resetting link <%s>, requested by peer\n", + l_ptr->name); tipc_link_reset(l_ptr); l_ptr->state = RESET_RESET; l_ptr->fsm_msg_cnt = 0; @@ -648,7 +642,7 @@ static void link_state_event(struct tipc_link *l_ptr, unsigned int event) link_set_timer(l_ptr, cont_intv); break; default: - pr_err("%s%u in WW state\n", link_unk_evt, event); + err("Unknown link event %u in WW state\n", event); } break; case WORKING_UNKNOWN: @@ -660,8 +654,8 @@ static void link_state_event(struct tipc_link *l_ptr, unsigned int event) link_set_timer(l_ptr, cont_intv); break; case RESET_MSG: - pr_info("%s<%s>, requested by peer while probing\n", - link_rst_msg, l_ptr->name); + info("Resetting link <%s>, requested by peer " + "while probing\n", l_ptr->name); tipc_link_reset(l_ptr); l_ptr->state = RESET_RESET; l_ptr->fsm_msg_cnt = 0; @@ -686,8 +680,8 @@ static void link_state_event(struct tipc_link *l_ptr, unsigned int event) l_ptr->fsm_msg_cnt++; link_set_timer(l_ptr, cont_intv / 4); } else { /* Link has failed */ - pr_warn("%s<%s>, peer not responding\n", - link_rst_msg, l_ptr->name); + warn("Resetting link <%s>, peer not responding\n", + l_ptr->name); tipc_link_reset(l_ptr); l_ptr->state = RESET_UNKNOWN; l_ptr->fsm_msg_cnt = 0; @@ -698,7 +692,7 @@ static void link_state_event(struct tipc_link *l_ptr, unsigned int event) } break; default: - pr_err("%s%u in WU state\n", link_unk_evt, event); + err("Unknown link event %u in WU state\n", event); } break; case RESET_UNKNOWN: @@ -732,7 +726,7 @@ static void link_state_event(struct tipc_link *l_ptr, unsigned int event) link_set_timer(l_ptr, cont_intv); break; default: - pr_err("%s%u in RU state\n", link_unk_evt, event); + err("Unknown link event %u in RU state\n", event); } break; case RESET_RESET: @@ -757,11 +751,11 @@ static void link_state_event(struct tipc_link *l_ptr, unsigned int event) link_set_timer(l_ptr, cont_intv); break; default: - pr_err("%s%u in RR state\n", link_unk_evt, event); + err("Unknown link event %u in RR state\n", event); } break; default: - pr_err("Unknown link state %u/%u\n", l_ptr->state, event); + err("Unknown link state %u/%u\n", l_ptr->state, event); } } @@ -862,8 +856,7 @@ int tipc_link_send_buf(struct tipc_link *l_ptr, struct sk_buff *buf) } kfree_skb(buf); if (imp > CONN_MANAGER) { - pr_warn("%s<%s>, send queue full", link_rst_msg, - l_ptr->name); + warn("Resetting link <%s>, send queue full", l_ptr->name); tipc_link_reset(l_ptr); } return dsz; @@ -951,7 +944,7 @@ int tipc_link_send(struct sk_buff *buf, u32 dest, u32 selector) return res; } -/** +/* * tipc_link_send_names - send name table entries to new neighbor * * Send routine for bulk delivery of name table messages when contact @@ -1416,8 +1409,8 @@ static void link_reset_all(unsigned long addr) tipc_node_lock(n_ptr); - pr_warn("Resetting all links to %s\n", - tipc_addr_string_fill(addr_string, n_ptr->addr)); + warn("Resetting all links to %s\n", + tipc_addr_string_fill(addr_string, n_ptr->addr)); for (i = 0; i < MAX_BEARERS; i++) { if (n_ptr->links[i]) { @@ -1435,7 +1428,7 @@ static void link_retransmit_failure(struct tipc_link *l_ptr, { struct tipc_msg *msg = buf_msg(buf); - pr_warn("Retransmission failure on link <%s>\n", l_ptr->name); + warn("Retransmission failure on link <%s>\n", l_ptr->name); if (l_ptr->addr) { /* Handle failure on standard link */ @@ -1447,23 +1440,21 @@ static void link_retransmit_failure(struct tipc_link *l_ptr, struct tipc_node *n_ptr; char addr_string[16]; - pr_info("Msg seq number: %u, ", msg_seqno(msg)); - pr_cont("Outstanding acks: %lu\n", - (unsigned long) TIPC_SKB_CB(buf)->handle); + info("Msg seq number: %u, ", msg_seqno(msg)); + info("Outstanding acks: %lu\n", + (unsigned long) TIPC_SKB_CB(buf)->handle); n_ptr = tipc_bclink_retransmit_to(); tipc_node_lock(n_ptr); tipc_addr_string_fill(addr_string, n_ptr->addr); - pr_info("Broadcast link info for %s\n", addr_string); - pr_info("Supportable: %d, Supported: %d, Acked: %u\n", - n_ptr->bclink.supportable, - n_ptr->bclink.supported, - n_ptr->bclink.acked); - pr_info("Last in: %u, Oos state: %u, Last sent: %u\n", - n_ptr->bclink.last_in, - n_ptr->bclink.oos_state, - n_ptr->bclink.last_sent); + info("Broadcast link info for %s\n", addr_string); + info("Supportable: %d, ", n_ptr->bclink.supportable); + info("Supported: %d, ", n_ptr->bclink.supported); + info("Acked: %u\n", n_ptr->bclink.acked); + info("Last in: %u, ", n_ptr->bclink.last_in); + info("Oos state: %u, ", n_ptr->bclink.oos_state); + info("Last sent: %u\n", n_ptr->bclink.last_sent); tipc_k_signal((Handler)link_reset_all, (unsigned long)n_ptr->addr); @@ -1488,8 +1479,8 @@ void tipc_link_retransmit(struct tipc_link *l_ptr, struct sk_buff *buf, l_ptr->retransm_queue_head = msg_seqno(msg); l_ptr->retransm_queue_size = retransmits; } else { - pr_err("Unexpected retransmit on link %s (qsize=%d)\n", - l_ptr->name, l_ptr->retransm_queue_size); + err("Unexpected retransmit on link %s (qsize=%d)\n", + l_ptr->name, l_ptr->retransm_queue_size); } return; } else { @@ -1796,7 +1787,7 @@ void tipc_recv_msg(struct sk_buff *head, struct tipc_bearer *b_ptr) read_unlock_bh(&tipc_net_lock); } -/** +/* * tipc_link_defer_pkt - Add out-of-sequence message to deferred reception queue * * Returns increase in queue length (i.e. 0 or 1) @@ -2083,9 +2074,8 @@ static void link_recv_proto_msg(struct tipc_link *l_ptr, struct sk_buff *buf) if (msg_linkprio(msg) && (msg_linkprio(msg) != l_ptr->priority)) { - pr_warn("%s<%s>, priority change %u->%u\n", - link_rst_msg, l_ptr->name, l_ptr->priority, - msg_linkprio(msg)); + warn("Resetting link <%s>, priority change %u->%u\n", + l_ptr->name, l_ptr->priority, msg_linkprio(msg)); l_ptr->priority = msg_linkprio(msg); tipc_link_reset(l_ptr); /* Enforce change to take effect */ break; @@ -2149,13 +2139,15 @@ static void tipc_link_tunnel(struct tipc_link *l_ptr, tunnel = l_ptr->owner->active_links[selector & 1]; if (!tipc_link_is_up(tunnel)) { - pr_warn("%stunnel link no longer available\n", link_co_err); + warn("Link changeover error, " + "tunnel link no longer available\n"); return; } msg_set_size(tunnel_hdr, length + INT_H_SIZE); buf = tipc_buf_acquire(length + INT_H_SIZE); if (!buf) { - pr_warn("%sunable to send tunnel msg\n", link_co_err); + warn("Link changeover error, " + "unable to send tunnel msg\n"); return; } skb_copy_to_linear_data(buf, tunnel_hdr, INT_H_SIZE); @@ -2181,7 +2173,8 @@ void tipc_link_changeover(struct tipc_link *l_ptr) return; if (!l_ptr->owner->permit_changeover) { - pr_warn("%speer did not permit changeover\n", link_co_err); + warn("Link changeover error, " + "peer did not permit changeover\n"); return; } @@ -2199,8 +2192,8 @@ void tipc_link_changeover(struct tipc_link *l_ptr) msg_set_size(&tunnel_hdr, INT_H_SIZE); tipc_link_send_buf(tunnel, buf); } else { - pr_warn("%sunable to send changeover msg\n", - link_co_err); + warn("Link changeover error, " + "unable to send changeover msg\n"); } return; } @@ -2253,8 +2246,8 @@ void tipc_link_send_duplicate(struct tipc_link *l_ptr, struct tipc_link *tunnel) msg_set_size(&tunnel_hdr, length + INT_H_SIZE); outbuf = tipc_buf_acquire(length + INT_H_SIZE); if (outbuf == NULL) { - pr_warn("%sunable to send duplicate msg\n", - link_co_err); + warn("Link changeover error, " + "unable to send duplicate msg\n"); return; } skb_copy_to_linear_data(outbuf, &tunnel_hdr, INT_H_SIZE); @@ -2305,8 +2298,8 @@ static int link_recv_changeover_msg(struct tipc_link **l_ptr, if (!dest_link) goto exit; if (dest_link == *l_ptr) { - pr_err("Unexpected changeover message on link <%s>\n", - (*l_ptr)->name); + err("Unexpected changeover message on link <%s>\n", + (*l_ptr)->name); goto exit; } *l_ptr = dest_link; @@ -2317,7 +2310,7 @@ static int link_recv_changeover_msg(struct tipc_link **l_ptr, goto exit; *buf = buf_extract(tunnel_buf, INT_H_SIZE); if (*buf == NULL) { - pr_warn("%sduplicate msg dropped\n", link_co_err); + warn("Link changeover error, duplicate msg dropped\n"); goto exit; } kfree_skb(tunnel_buf); @@ -2326,8 +2319,8 @@ static int link_recv_changeover_msg(struct tipc_link **l_ptr, /* First original message ?: */ if (tipc_link_is_up(dest_link)) { - pr_info("%s<%s>, changeover initiated by peer\n", link_rst_msg, - dest_link->name); + info("Resetting link <%s>, changeover initiated by peer\n", + dest_link->name); tipc_link_reset(dest_link); dest_link->exp_msg_count = msg_count; if (!msg_count) @@ -2340,7 +2333,8 @@ static int link_recv_changeover_msg(struct tipc_link **l_ptr, /* Receive original message */ if (dest_link->exp_msg_count == 0) { - pr_warn("%sgot too many tunnelled messages\n", link_co_err); + warn("Link switchover error, " + "got too many tunnelled messages\n"); goto exit; } dest_link->exp_msg_count--; @@ -2352,7 +2346,7 @@ static int link_recv_changeover_msg(struct tipc_link **l_ptr, kfree_skb(tunnel_buf); return 1; } else { - pr_warn("%soriginal msg dropped\n", link_co_err); + warn("Link changeover error, original msg dropped\n"); } } exit: @@ -2373,7 +2367,7 @@ void tipc_link_recv_bundle(struct sk_buff *buf) while (msgcount--) { obuf = buf_extract(buf, pos); if (obuf == NULL) { - pr_warn("Link unable to unbundle message(s)\n"); + warn("Link unable to unbundle message(s)\n"); break; } pos += align(msg_size(buf_msg(obuf))); @@ -2544,7 +2538,7 @@ int tipc_link_recv_fragment(struct sk_buff **pending, struct sk_buff **fb, set_fragm_size(pbuf, fragm_sz); set_expected_frags(pbuf, exp_fragm_cnt - 1); } else { - pr_debug("Link unable to reassemble fragmented message\n"); + dbg("Link unable to reassemble fragmented message\n"); kfree_skb(fbuf); return -1; } @@ -2641,8 +2635,8 @@ void tipc_link_set_queue_limits(struct tipc_link *l_ptr, u32 window) /** * link_find_link - locate link by name - * @name: ptr to link name string - * @node: ptr to area to be filled with ptr to associated node + * @name - ptr to link name string + * @node - ptr to area to be filled with ptr to associated node * * Caller must hold 'tipc_net_lock' to ensure node and bearer are not deleted; * this also prevents link deletion. @@ -2677,8 +2671,8 @@ static struct tipc_link *link_find_link(const char *name, /** * link_value_is_valid -- validate proposed link tolerance/priority/window * - * @cmd: value type (TIPC_CMD_SET_LINK_*) - * @new_value: the new value + * @cmd - value type (TIPC_CMD_SET_LINK_*) + * @new_value - the new value * * Returns 1 if value is within range, 0 if not. */ @@ -2699,9 +2693,9 @@ static int link_value_is_valid(u16 cmd, u32 new_value) /** * link_cmd_set_value - change priority/tolerance/window for link/bearer/media - * @name: ptr to link, bearer, or media name - * @new_value: new value of link, bearer, or media setting - * @cmd: which link, bearer, or media attribute to set (TIPC_CMD_SET_LINK_*) + * @name - ptr to link, bearer, or media name + * @new_value - new value of link, bearer, or media setting + * @cmd - which link, bearer, or media attribute to set (TIPC_CMD_SET_LINK_*) * * Caller must hold 'tipc_net_lock' to ensure link/bearer/media is not deleted. * @@ -2866,114 +2860,112 @@ static u32 percent(u32 count, u32 total) */ static int tipc_link_stats(const char *name, char *buf, const u32 buf_size) { - struct tipc_link *l; - struct tipc_stats *s; + struct print_buf pb; + struct tipc_link *l_ptr; struct tipc_node *node; char *status; u32 profile_total = 0; - int ret; if (!strcmp(name, tipc_bclink_name)) return tipc_bclink_stats(buf, buf_size); + tipc_printbuf_init(&pb, buf, buf_size); + read_lock_bh(&tipc_net_lock); - l = link_find_link(name, &node); - if (!l) { + l_ptr = link_find_link(name, &node); + if (!l_ptr) { read_unlock_bh(&tipc_net_lock); return 0; } tipc_node_lock(node); - s = &l->stats; - if (tipc_link_is_active(l)) + if (tipc_link_is_active(l_ptr)) status = "ACTIVE"; - else if (tipc_link_is_up(l)) + else if (tipc_link_is_up(l_ptr)) status = "STANDBY"; else status = "DEFUNCT"; - - ret = tipc_snprintf(buf, buf_size, "Link <%s>\n" - " %s MTU:%u Priority:%u Tolerance:%u ms" - " Window:%u packets\n", - l->name, status, l->max_pkt, l->priority, - l->tolerance, l->queue_limit[0]); - - ret += tipc_snprintf(buf + ret, buf_size - ret, - " RX packets:%u fragments:%u/%u bundles:%u/%u\n", - l->next_in_no - s->recv_info, s->recv_fragments, - s->recv_fragmented, s->recv_bundles, - s->recv_bundled); - - ret += tipc_snprintf(buf + ret, buf_size - ret, - " TX packets:%u fragments:%u/%u bundles:%u/%u\n", - l->next_out_no - s->sent_info, s->sent_fragments, - s->sent_fragmented, s->sent_bundles, - s->sent_bundled); - - profile_total = s->msg_length_counts; + tipc_printf(&pb, "Link <%s>\n" + " %s MTU:%u Priority:%u Tolerance:%u ms" + " Window:%u packets\n", + l_ptr->name, status, l_ptr->max_pkt, + l_ptr->priority, l_ptr->tolerance, l_ptr->queue_limit[0]); + tipc_printf(&pb, " RX packets:%u fragments:%u/%u bundles:%u/%u\n", + l_ptr->next_in_no - l_ptr->stats.recv_info, + l_ptr->stats.recv_fragments, + l_ptr->stats.recv_fragmented, + l_ptr->stats.recv_bundles, + l_ptr->stats.recv_bundled); + tipc_printf(&pb, " TX packets:%u fragments:%u/%u bundles:%u/%u\n", + l_ptr->next_out_no - l_ptr->stats.sent_info, + l_ptr->stats.sent_fragments, + l_ptr->stats.sent_fragmented, + l_ptr->stats.sent_bundles, + l_ptr->stats.sent_bundled); + profile_total = l_ptr->stats.msg_length_counts; if (!profile_total) profile_total = 1; - - ret += tipc_snprintf(buf + ret, buf_size - ret, - " TX profile sample:%u packets average:%u octets\n" - " 0-64:%u%% -256:%u%% -1024:%u%% -4096:%u%% " - "-16384:%u%% -32768:%u%% -66000:%u%%\n", - s->msg_length_counts, - s->msg_lengths_total / profile_total, - percent(s->msg_length_profile[0], profile_total), - percent(s->msg_length_profile[1], profile_total), - percent(s->msg_length_profile[2], profile_total), - percent(s->msg_length_profile[3], profile_total), - percent(s->msg_length_profile[4], profile_total), - percent(s->msg_length_profile[5], profile_total), - percent(s->msg_length_profile[6], profile_total)); - - ret += tipc_snprintf(buf + ret, buf_size - ret, - " RX states:%u probes:%u naks:%u defs:%u" - " dups:%u\n", s->recv_states, s->recv_probes, - s->recv_nacks, s->deferred_recv, s->duplicates); - - ret += tipc_snprintf(buf + ret, buf_size - ret, - " TX states:%u probes:%u naks:%u acks:%u" - " dups:%u\n", s->sent_states, s->sent_probes, - s->sent_nacks, s->sent_acks, s->retransmitted); - - ret += tipc_snprintf(buf + ret, buf_size - ret, - " Congestion bearer:%u link:%u Send queue" - " max:%u avg:%u\n", s->bearer_congs, s->link_congs, - s->max_queue_sz, s->queue_sz_counts ? - (s->accu_queue_sz / s->queue_sz_counts) : 0); + tipc_printf(&pb, " TX profile sample:%u packets average:%u octets\n" + " 0-64:%u%% -256:%u%% -1024:%u%% -4096:%u%% " + "-16384:%u%% -32768:%u%% -66000:%u%%\n", + l_ptr->stats.msg_length_counts, + l_ptr->stats.msg_lengths_total / profile_total, + percent(l_ptr->stats.msg_length_profile[0], profile_total), + percent(l_ptr->stats.msg_length_profile[1], profile_total), + percent(l_ptr->stats.msg_length_profile[2], profile_total), + percent(l_ptr->stats.msg_length_profile[3], profile_total), + percent(l_ptr->stats.msg_length_profile[4], profile_total), + percent(l_ptr->stats.msg_length_profile[5], profile_total), + percent(l_ptr->stats.msg_length_profile[6], profile_total)); + tipc_printf(&pb, " RX states:%u probes:%u naks:%u defs:%u dups:%u\n", + l_ptr->stats.recv_states, + l_ptr->stats.recv_probes, + l_ptr->stats.recv_nacks, + l_ptr->stats.deferred_recv, + l_ptr->stats.duplicates); + tipc_printf(&pb, " TX states:%u probes:%u naks:%u acks:%u dups:%u\n", + l_ptr->stats.sent_states, + l_ptr->stats.sent_probes, + l_ptr->stats.sent_nacks, + l_ptr->stats.sent_acks, + l_ptr->stats.retransmitted); + tipc_printf(&pb, " Congestion bearer:%u link:%u Send queue max:%u avg:%u\n", + l_ptr->stats.bearer_congs, + l_ptr->stats.link_congs, + l_ptr->stats.max_queue_sz, + l_ptr->stats.queue_sz_counts + ? (l_ptr->stats.accu_queue_sz / l_ptr->stats.queue_sz_counts) + : 0); tipc_node_unlock(node); read_unlock_bh(&tipc_net_lock); - return ret; + return tipc_printbuf_validate(&pb); } +#define MAX_LINK_STATS_INFO 2000 + struct sk_buff *tipc_link_cmd_show_stats(const void *req_tlv_area, int req_tlv_space) { struct sk_buff *buf; struct tlv_desc *rep_tlv; int str_len; - int pb_len; - char *pb; if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_LINK_NAME)) return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); - buf = tipc_cfg_reply_alloc(TLV_SPACE(ULTRA_STRING_MAX_LEN)); + buf = tipc_cfg_reply_alloc(TLV_SPACE(MAX_LINK_STATS_INFO)); if (!buf) return NULL; rep_tlv = (struct tlv_desc *)buf->data; - pb = TLV_DATA(rep_tlv); - pb_len = ULTRA_STRING_MAX_LEN; + str_len = tipc_link_stats((char *)TLV_DATA(req_tlv_area), - pb, pb_len); + (char *)TLV_DATA(rep_tlv), MAX_LINK_STATS_INFO); if (!str_len) { kfree_skb(buf); return tipc_cfg_reply_error_string("link not found"); } - str_len += 1; /* for "\0" */ + skb_put(buf, TLV_SPACE(str_len)); TLV_SET(rep_tlv, TIPC_TLV_ULTRA_STRING, NULL, str_len); @@ -3011,16 +3003,62 @@ u32 tipc_link_get_max_pkt(u32 dest, u32 selector) static void link_print(struct tipc_link *l_ptr, const char *str) { - pr_info("%s Link %x<%s>:", str, l_ptr->addr, l_ptr->b_ptr->name); + char print_area[256]; + struct print_buf pb; + struct print_buf *buf = &pb; + + tipc_printbuf_init(buf, print_area, sizeof(print_area)); + + tipc_printf(buf, str); + tipc_printf(buf, "Link %x<%s>:", + l_ptr->addr, l_ptr->b_ptr->name); + +#ifdef CONFIG_TIPC_DEBUG + if (link_reset_reset(l_ptr) || link_reset_unknown(l_ptr)) + goto print_state; + + tipc_printf(buf, ": NXO(%u):", mod(l_ptr->next_out_no)); + tipc_printf(buf, "NXI(%u):", mod(l_ptr->next_in_no)); + tipc_printf(buf, "SQUE"); + if (l_ptr->first_out) { + tipc_printf(buf, "[%u..", buf_seqno(l_ptr->first_out)); + if (l_ptr->next_out) + tipc_printf(buf, "%u..", buf_seqno(l_ptr->next_out)); + tipc_printf(buf, "%u]", buf_seqno(l_ptr->last_out)); + if ((mod(buf_seqno(l_ptr->last_out) - + buf_seqno(l_ptr->first_out)) + != (l_ptr->out_queue_size - 1)) || + (l_ptr->last_out->next != NULL)) { + tipc_printf(buf, "\nSend queue inconsistency\n"); + tipc_printf(buf, "first_out= %p ", l_ptr->first_out); + tipc_printf(buf, "next_out= %p ", l_ptr->next_out); + tipc_printf(buf, "last_out= %p ", l_ptr->last_out); + } + } else + tipc_printf(buf, "[]"); + tipc_printf(buf, "SQSIZ(%u)", l_ptr->out_queue_size); + if (l_ptr->oldest_deferred_in) { + u32 o = buf_seqno(l_ptr->oldest_deferred_in); + u32 n = buf_seqno(l_ptr->newest_deferred_in); + tipc_printf(buf, ":RQUE[%u..%u]", o, n); + if (l_ptr->deferred_inqueue_sz != mod((n + 1) - o)) { + tipc_printf(buf, ":RQSIZ(%u)", + l_ptr->deferred_inqueue_sz); + } + } +print_state: +#endif if (link_working_unknown(l_ptr)) - pr_cont(":WU\n"); + tipc_printf(buf, ":WU"); else if (link_reset_reset(l_ptr)) - pr_cont(":RR\n"); + tipc_printf(buf, ":RR"); else if (link_reset_unknown(l_ptr)) - pr_cont(":RU\n"); + tipc_printf(buf, ":RU"); else if (link_working_working(l_ptr)) - pr_cont(":WW\n"); - else - pr_cont("\n"); + tipc_printf(buf, ":WW"); + tipc_printf(buf, "\n"); + + tipc_printbuf_validate(buf); + info("%s", print_area); } diff --git a/trunk/net/tipc/link.h b/trunk/net/tipc/link.h index 6e921121be06..d6a60a963ce6 100644 --- a/trunk/net/tipc/link.h +++ b/trunk/net/tipc/link.h @@ -37,6 +37,7 @@ #ifndef _TIPC_LINK_H #define _TIPC_LINK_H +#include "log.h" #include "msg.h" #include "node.h" @@ -62,37 +63,6 @@ */ #define MAX_PKT_DEFAULT 1500 -struct tipc_stats { - u32 sent_info; /* used in counting # sent packets */ - u32 recv_info; /* used in counting # recv'd packets */ - u32 sent_states; - u32 recv_states; - u32 sent_probes; - u32 recv_probes; - u32 sent_nacks; - u32 recv_nacks; - u32 sent_acks; - u32 sent_bundled; - u32 sent_bundles; - u32 recv_bundled; - u32 recv_bundles; - u32 retransmitted; - u32 sent_fragmented; - u32 sent_fragments; - u32 recv_fragmented; - u32 recv_fragments; - u32 link_congs; /* # port sends blocked by congestion */ - u32 bearer_congs; - u32 deferred_recv; - u32 duplicates; - u32 max_queue_sz; /* send queue size high water mark */ - u32 accu_queue_sz; /* used for send queue size profiling */ - u32 queue_sz_counts; /* used for send queue size profiling */ - u32 msg_length_counts; /* used for message length profiling */ - u32 msg_lengths_total; /* used for message length profiling */ - u32 msg_length_profile[7]; /* used for msg. length profiling */ -}; - /** * struct tipc_link - TIPC link data structure * @addr: network address of link's peer node @@ -205,7 +175,36 @@ struct tipc_link { struct sk_buff *defragm_buf; /* Statistics */ - struct tipc_stats stats; + struct { + u32 sent_info; /* used in counting # sent packets */ + u32 recv_info; /* used in counting # recv'd packets */ + u32 sent_states; + u32 recv_states; + u32 sent_probes; + u32 recv_probes; + u32 sent_nacks; + u32 recv_nacks; + u32 sent_acks; + u32 sent_bundled; + u32 sent_bundles; + u32 recv_bundled; + u32 recv_bundles; + u32 retransmitted; + u32 sent_fragmented; + u32 sent_fragments; + u32 recv_fragmented; + u32 recv_fragments; + u32 link_congs; /* # port sends blocked by congestion */ + u32 bearer_congs; + u32 deferred_recv; + u32 duplicates; + u32 max_queue_sz; /* send queue size high water mark */ + u32 accu_queue_sz; /* used for send queue size profiling */ + u32 queue_sz_counts; /* used for send queue size profiling */ + u32 msg_length_counts; /* used for message length profiling */ + u32 msg_lengths_total; /* used for message length profiling */ + u32 msg_length_profile[7]; /* used for msg. length profiling */ + } stats; }; struct tipc_port; diff --git a/trunk/net/tipc/log.c b/trunk/net/tipc/log.c index abef644f27d8..026733f24919 100644 --- a/trunk/net/tipc/log.c +++ b/trunk/net/tipc/log.c @@ -36,20 +36,302 @@ #include "core.h" #include "config.h" +#include "log.h" + +/* + * TIPC pre-defines the following print buffers: + * + * TIPC_NULL : null buffer (i.e. print nowhere) + * TIPC_CONS : system console + * TIPC_LOG : TIPC log buffer + * + * Additional user-defined print buffers are also permitted. + */ +static struct print_buf null_buf = { NULL, 0, NULL, 0 }; +struct print_buf *const TIPC_NULL = &null_buf; + +static struct print_buf cons_buf = { NULL, 0, NULL, 1 }; +struct print_buf *const TIPC_CONS = &cons_buf; + +static struct print_buf log_buf = { NULL, 0, NULL, 1 }; +struct print_buf *const TIPC_LOG = &log_buf; + +/* + * Locking policy when using print buffers. + * + * 1) tipc_printf() uses 'print_lock' to protect against concurrent access to + * 'print_string' when writing to a print buffer. This also protects against + * concurrent writes to the print buffer being written to. + * + * 2) tipc_log_XXX() leverages the aforementioned use of 'print_lock' to + * protect against all types of concurrent operations on their associated + * print buffer (not just write operations). + * + * Note: All routines of the form tipc_printbuf_XXX() are lock-free, and rely + * on the caller to prevent simultaneous use of the print buffer(s) being + * manipulated. + */ +static char print_string[TIPC_PB_MAX_STR]; +static DEFINE_SPINLOCK(print_lock); + +static void tipc_printbuf_move(struct print_buf *pb_to, + struct print_buf *pb_from); + +#define FORMAT(PTR, LEN, FMT) \ +{\ + va_list args;\ + va_start(args, FMT);\ + LEN = vsprintf(PTR, FMT, args);\ + va_end(args);\ + *(PTR + LEN) = '\0';\ +} + +/** + * tipc_printbuf_init - initialize print buffer to empty + * @pb: pointer to print buffer structure + * @raw: pointer to character array used by print buffer + * @size: size of character array + * + * Note: If the character array is too small (or absent), the print buffer + * becomes a null device that discards anything written to it. + */ +void tipc_printbuf_init(struct print_buf *pb, char *raw, u32 size) +{ + pb->buf = raw; + pb->crs = raw; + pb->size = size; + pb->echo = 0; + + if (size < TIPC_PB_MIN_SIZE) { + pb->buf = NULL; + } else if (raw) { + pb->buf[0] = 0; + pb->buf[size - 1] = ~0; + } +} + +/** + * tipc_printbuf_reset - reinitialize print buffer to empty state + * @pb: pointer to print buffer structure + */ +static void tipc_printbuf_reset(struct print_buf *pb) +{ + if (pb->buf) { + pb->crs = pb->buf; + pb->buf[0] = 0; + pb->buf[pb->size - 1] = ~0; + } +} + +/** + * tipc_printbuf_empty - test if print buffer is in empty state + * @pb: pointer to print buffer structure + * + * Returns non-zero if print buffer is empty. + */ +static int tipc_printbuf_empty(struct print_buf *pb) +{ + return !pb->buf || (pb->crs == pb->buf); +} + +/** + * tipc_printbuf_validate - check for print buffer overflow + * @pb: pointer to print buffer structure + * + * Verifies that a print buffer has captured all data written to it. + * If data has been lost, linearize buffer and prepend an error message + * + * Returns length of print buffer data string (including trailing NUL) + */ +int tipc_printbuf_validate(struct print_buf *pb) +{ + char *err = "\n\n*** PRINT BUFFER OVERFLOW ***\n\n"; + char *cp_buf; + struct print_buf cb; + + if (!pb->buf) + return 0; + + if (pb->buf[pb->size - 1] == 0) { + cp_buf = kmalloc(pb->size, GFP_ATOMIC); + if (cp_buf) { + tipc_printbuf_init(&cb, cp_buf, pb->size); + tipc_printbuf_move(&cb, pb); + tipc_printbuf_move(pb, &cb); + kfree(cp_buf); + memcpy(pb->buf, err, strlen(err)); + } else { + tipc_printbuf_reset(pb); + tipc_printf(pb, err); + } + } + return pb->crs - pb->buf + 1; +} + +/** + * tipc_printbuf_move - move print buffer contents to another print buffer + * @pb_to: pointer to destination print buffer structure + * @pb_from: pointer to source print buffer structure + * + * Current contents of destination print buffer (if any) are discarded. + * Source print buffer becomes empty if a successful move occurs. + */ +static void tipc_printbuf_move(struct print_buf *pb_to, + struct print_buf *pb_from) +{ + int len; + + /* Handle the cases where contents can't be moved */ + if (!pb_to->buf) + return; + + if (!pb_from->buf) { + tipc_printbuf_reset(pb_to); + return; + } + + if (pb_to->size < pb_from->size) { + strcpy(pb_to->buf, "*** PRINT BUFFER MOVE ERROR ***"); + pb_to->buf[pb_to->size - 1] = ~0; + pb_to->crs = strchr(pb_to->buf, 0); + return; + } + + /* Copy data from char after cursor to end (if used) */ + len = pb_from->buf + pb_from->size - pb_from->crs - 2; + if ((pb_from->buf[pb_from->size - 1] == 0) && (len > 0)) { + strcpy(pb_to->buf, pb_from->crs + 1); + pb_to->crs = pb_to->buf + len; + } else + pb_to->crs = pb_to->buf; + + /* Copy data from start to cursor (always) */ + len = pb_from->crs - pb_from->buf; + strcpy(pb_to->crs, pb_from->buf); + pb_to->crs += len; + + tipc_printbuf_reset(pb_from); +} /** - * tipc_snprintf - append formatted output to print buffer - * @buf: pointer to print buffer - * @len: buffer length + * tipc_printf - append formatted output to print buffer + * @pb: pointer to print buffer * @fmt: formatted info to be printed */ -int tipc_snprintf(char *buf, int len, const char *fmt, ...) +void tipc_printf(struct print_buf *pb, const char *fmt, ...) +{ + int chars_to_add; + int chars_left; + char save_char; + + spin_lock_bh(&print_lock); + + FORMAT(print_string, chars_to_add, fmt); + if (chars_to_add >= TIPC_PB_MAX_STR) + strcpy(print_string, "*** PRINT BUFFER STRING TOO LONG ***"); + + if (pb->buf) { + chars_left = pb->buf + pb->size - pb->crs - 1; + if (chars_to_add <= chars_left) { + strcpy(pb->crs, print_string); + pb->crs += chars_to_add; + } else if (chars_to_add >= (pb->size - 1)) { + strcpy(pb->buf, print_string + chars_to_add + 1 + - pb->size); + pb->crs = pb->buf + pb->size - 1; + } else { + strcpy(pb->buf, print_string + chars_left); + save_char = print_string[chars_left]; + print_string[chars_left] = 0; + strcpy(pb->crs, print_string); + print_string[chars_left] = save_char; + pb->crs = pb->buf + chars_to_add - chars_left; + } + } + + if (pb->echo) + printk("%s", print_string); + + spin_unlock_bh(&print_lock); +} + +/** + * tipc_log_resize - change the size of the TIPC log buffer + * @log_size: print buffer size to use + */ +int tipc_log_resize(int log_size) +{ + int res = 0; + + spin_lock_bh(&print_lock); + kfree(TIPC_LOG->buf); + TIPC_LOG->buf = NULL; + if (log_size) { + if (log_size < TIPC_PB_MIN_SIZE) + log_size = TIPC_PB_MIN_SIZE; + res = TIPC_LOG->echo; + tipc_printbuf_init(TIPC_LOG, kmalloc(log_size, GFP_ATOMIC), + log_size); + TIPC_LOG->echo = res; + res = !TIPC_LOG->buf; + } + spin_unlock_bh(&print_lock); + + return res; +} + +/** + * tipc_log_resize_cmd - reconfigure size of TIPC log buffer + */ +struct sk_buff *tipc_log_resize_cmd(const void *req_tlv_area, int req_tlv_space) +{ + u32 value; + + if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) + return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); + + value = ntohl(*(__be32 *)TLV_DATA(req_tlv_area)); + if (value > 32768) + return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE + " (log size must be 0-32768)"); + if (tipc_log_resize(value)) + return tipc_cfg_reply_error_string( + "unable to create specified log (log size is now 0)"); + return tipc_cfg_reply_none(); +} + +/** + * tipc_log_dump - capture TIPC log buffer contents in configuration message + */ +struct sk_buff *tipc_log_dump(void) { - int i; - va_list args; + struct sk_buff *reply; + + spin_lock_bh(&print_lock); + if (!TIPC_LOG->buf) { + spin_unlock_bh(&print_lock); + reply = tipc_cfg_reply_ultra_string("log not activated\n"); + } else if (tipc_printbuf_empty(TIPC_LOG)) { + spin_unlock_bh(&print_lock); + reply = tipc_cfg_reply_ultra_string("log is empty\n"); + } else { + struct tlv_desc *rep_tlv; + struct print_buf pb; + int str_len; - va_start(args, fmt); - i = vscnprintf(buf, len, fmt, args); - va_end(args); - return i; + str_len = min(TIPC_LOG->size, 32768u); + spin_unlock_bh(&print_lock); + reply = tipc_cfg_reply_alloc(TLV_SPACE(str_len)); + if (reply) { + rep_tlv = (struct tlv_desc *)reply->data; + tipc_printbuf_init(&pb, TLV_DATA(rep_tlv), str_len); + spin_lock_bh(&print_lock); + tipc_printbuf_move(&pb, TIPC_LOG); + spin_unlock_bh(&print_lock); + str_len = strlen(TLV_DATA(rep_tlv)) + 1; + skb_put(reply, TLV_SPACE(str_len)); + TLV_SET(rep_tlv, TIPC_TLV_ULTRA_STRING, NULL, str_len); + } + } + return reply; } diff --git a/trunk/net/tipc/log.h b/trunk/net/tipc/log.h new file mode 100644 index 000000000000..d1f5eb967fd8 --- /dev/null +++ b/trunk/net/tipc/log.h @@ -0,0 +1,66 @@ +/* + * net/tipc/log.h: Include file for TIPC print buffer routines + * + * Copyright (c) 1997-2006, Ericsson AB + * Copyright (c) 2005-2007, Wind River Systems + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _TIPC_LOG_H +#define _TIPC_LOG_H + +/** + * struct print_buf - TIPC print buffer structure + * @buf: pointer to character array containing print buffer contents + * @size: size of character array + * @crs: pointer to first unused space in character array (i.e. final NUL) + * @echo: echo output to system console if non-zero + */ +struct print_buf { + char *buf; + u32 size; + char *crs; + int echo; +}; + +#define TIPC_PB_MIN_SIZE 64 /* minimum size for a print buffer's array */ +#define TIPC_PB_MAX_STR 512 /* max printable string (with trailing NUL) */ + +void tipc_printbuf_init(struct print_buf *pb, char *buf, u32 size); +int tipc_printbuf_validate(struct print_buf *pb); + +int tipc_log_resize(int log_size); + +struct sk_buff *tipc_log_resize_cmd(const void *req_tlv_area, + int req_tlv_space); +struct sk_buff *tipc_log_dump(void); + +#endif diff --git a/trunk/net/tipc/msg.c b/trunk/net/tipc/msg.c index f2db8a87d9c5..deea0d232dca 100644 --- a/trunk/net/tipc/msg.c +++ b/trunk/net/tipc/msg.c @@ -109,3 +109,245 @@ int tipc_msg_build(struct tipc_msg *hdr, struct iovec const *msg_sect, *buf = NULL; return -EFAULT; } + +#ifdef CONFIG_TIPC_DEBUG +void tipc_msg_dbg(struct print_buf *buf, struct tipc_msg *msg, const char *str) +{ + u32 usr = msg_user(msg); + tipc_printf(buf, KERN_DEBUG); + tipc_printf(buf, str); + + switch (usr) { + case MSG_BUNDLER: + tipc_printf(buf, "BNDL::"); + tipc_printf(buf, "MSGS(%u):", msg_msgcnt(msg)); + break; + case BCAST_PROTOCOL: + tipc_printf(buf, "BCASTP::"); + break; + case MSG_FRAGMENTER: + tipc_printf(buf, "FRAGM::"); + switch (msg_type(msg)) { + case FIRST_FRAGMENT: + tipc_printf(buf, "FIRST:"); + break; + case FRAGMENT: + tipc_printf(buf, "BODY:"); + break; + case LAST_FRAGMENT: + tipc_printf(buf, "LAST:"); + break; + default: + tipc_printf(buf, "UNKNOWN:%x", msg_type(msg)); + + } + tipc_printf(buf, "NO(%u/%u):", msg_long_msgno(msg), + msg_fragm_no(msg)); + break; + case TIPC_LOW_IMPORTANCE: + case TIPC_MEDIUM_IMPORTANCE: + case TIPC_HIGH_IMPORTANCE: + case TIPC_CRITICAL_IMPORTANCE: + tipc_printf(buf, "DAT%u:", msg_user(msg)); + if (msg_short(msg)) { + tipc_printf(buf, "CON:"); + break; + } + switch (msg_type(msg)) { + case TIPC_CONN_MSG: + tipc_printf(buf, "CON:"); + break; + case TIPC_MCAST_MSG: + tipc_printf(buf, "MCST:"); + break; + case TIPC_NAMED_MSG: + tipc_printf(buf, "NAM:"); + break; + case TIPC_DIRECT_MSG: + tipc_printf(buf, "DIR:"); + break; + default: + tipc_printf(buf, "UNKNOWN TYPE %u", msg_type(msg)); + } + if (msg_reroute_cnt(msg)) + tipc_printf(buf, "REROUTED(%u):", + msg_reroute_cnt(msg)); + break; + case NAME_DISTRIBUTOR: + tipc_printf(buf, "NMD::"); + switch (msg_type(msg)) { + case PUBLICATION: + tipc_printf(buf, "PUBL(%u):", (msg_size(msg) - msg_hdr_sz(msg)) / 20); /* Items */ + break; + case WITHDRAWAL: + tipc_printf(buf, "WDRW:"); + break; + default: + tipc_printf(buf, "UNKNOWN:%x", msg_type(msg)); + } + if (msg_reroute_cnt(msg)) + tipc_printf(buf, "REROUTED(%u):", + msg_reroute_cnt(msg)); + break; + case CONN_MANAGER: + tipc_printf(buf, "CONN_MNG:"); + switch (msg_type(msg)) { + case CONN_PROBE: + tipc_printf(buf, "PROBE:"); + break; + case CONN_PROBE_REPLY: + tipc_printf(buf, "PROBE_REPLY:"); + break; + case CONN_ACK: + tipc_printf(buf, "CONN_ACK:"); + tipc_printf(buf, "ACK(%u):", msg_msgcnt(msg)); + break; + default: + tipc_printf(buf, "UNKNOWN TYPE:%x", msg_type(msg)); + } + if (msg_reroute_cnt(msg)) + tipc_printf(buf, "REROUTED(%u):", msg_reroute_cnt(msg)); + break; + case LINK_PROTOCOL: + switch (msg_type(msg)) { + case STATE_MSG: + tipc_printf(buf, "STATE:"); + tipc_printf(buf, "%s:", msg_probe(msg) ? "PRB" : ""); + tipc_printf(buf, "NXS(%u):", msg_next_sent(msg)); + tipc_printf(buf, "GAP(%u):", msg_seq_gap(msg)); + tipc_printf(buf, "LSTBC(%u):", msg_last_bcast(msg)); + break; + case RESET_MSG: + tipc_printf(buf, "RESET:"); + if (msg_size(msg) != msg_hdr_sz(msg)) + tipc_printf(buf, "BEAR:%s:", msg_data(msg)); + break; + case ACTIVATE_MSG: + tipc_printf(buf, "ACTIVATE:"); + break; + default: + tipc_printf(buf, "UNKNOWN TYPE:%x", msg_type(msg)); + } + tipc_printf(buf, "PLANE(%c):", msg_net_plane(msg)); + tipc_printf(buf, "SESS(%u):", msg_session(msg)); + break; + case CHANGEOVER_PROTOCOL: + tipc_printf(buf, "TUNL:"); + switch (msg_type(msg)) { + case DUPLICATE_MSG: + tipc_printf(buf, "DUPL:"); + break; + case ORIGINAL_MSG: + tipc_printf(buf, "ORIG:"); + tipc_printf(buf, "EXP(%u)", msg_msgcnt(msg)); + break; + default: + tipc_printf(buf, "UNKNOWN TYPE:%x", msg_type(msg)); + } + break; + case LINK_CONFIG: + tipc_printf(buf, "CFG:"); + switch (msg_type(msg)) { + case DSC_REQ_MSG: + tipc_printf(buf, "DSC_REQ:"); + break; + case DSC_RESP_MSG: + tipc_printf(buf, "DSC_RESP:"); + break; + default: + tipc_printf(buf, "UNKNOWN TYPE:%x:", msg_type(msg)); + break; + } + break; + default: + tipc_printf(buf, "UNKNOWN USER:"); + } + + switch (usr) { + case CONN_MANAGER: + case TIPC_LOW_IMPORTANCE: + case TIPC_MEDIUM_IMPORTANCE: + case TIPC_HIGH_IMPORTANCE: + case TIPC_CRITICAL_IMPORTANCE: + switch (msg_errcode(msg)) { + case TIPC_OK: + break; + case TIPC_ERR_NO_NAME: + tipc_printf(buf, "NO_NAME:"); + break; + case TIPC_ERR_NO_PORT: + tipc_printf(buf, "NO_PORT:"); + break; + case TIPC_ERR_NO_NODE: + tipc_printf(buf, "NO_PROC:"); + break; + case TIPC_ERR_OVERLOAD: + tipc_printf(buf, "OVERLOAD:"); + break; + case TIPC_CONN_SHUTDOWN: + tipc_printf(buf, "SHUTDOWN:"); + break; + default: + tipc_printf(buf, "UNKNOWN ERROR(%x):", + msg_errcode(msg)); + } + default: + break; + } + + tipc_printf(buf, "HZ(%u):", msg_hdr_sz(msg)); + tipc_printf(buf, "SZ(%u):", msg_size(msg)); + tipc_printf(buf, "SQNO(%u):", msg_seqno(msg)); + + if (msg_non_seq(msg)) + tipc_printf(buf, "NOSEQ:"); + else + tipc_printf(buf, "ACK(%u):", msg_ack(msg)); + tipc_printf(buf, "BACK(%u):", msg_bcast_ack(msg)); + tipc_printf(buf, "PRND(%x)", msg_prevnode(msg)); + + if (msg_isdata(msg)) { + if (msg_named(msg)) { + tipc_printf(buf, "NTYP(%u):", msg_nametype(msg)); + tipc_printf(buf, "NINST(%u)", msg_nameinst(msg)); + } + } + + if ((usr != LINK_PROTOCOL) && (usr != LINK_CONFIG) && + (usr != MSG_BUNDLER)) { + if (!msg_short(msg)) { + tipc_printf(buf, ":ORIG(%x:%u):", + msg_orignode(msg), msg_origport(msg)); + tipc_printf(buf, ":DEST(%x:%u):", + msg_destnode(msg), msg_destport(msg)); + } else { + tipc_printf(buf, ":OPRT(%u):", msg_origport(msg)); + tipc_printf(buf, ":DPRT(%u):", msg_destport(msg)); + } + } + if (msg_user(msg) == NAME_DISTRIBUTOR) { + tipc_printf(buf, ":ONOD(%x):", msg_orignode(msg)); + tipc_printf(buf, ":DNOD(%x):", msg_destnode(msg)); + } + + if (msg_user(msg) == LINK_CONFIG) { + struct tipc_media_addr orig; + + tipc_printf(buf, ":DDOM(%x):", msg_dest_domain(msg)); + tipc_printf(buf, ":NETID(%u):", msg_bc_netid(msg)); + memcpy(orig.value, msg_media_addr(msg), sizeof(orig.value)); + orig.media_id = 0; + orig.broadcast = 0; + tipc_media_addr_printf(buf, &orig); + } + if (msg_user(msg) == BCAST_PROTOCOL) { + tipc_printf(buf, "BCNACK:AFTER(%u):", msg_bcgap_after(msg)); + tipc_printf(buf, "TO(%u):", msg_bcgap_to(msg)); + } + tipc_printf(buf, "\n"); + if ((usr == CHANGEOVER_PROTOCOL) && (msg_msgcnt(msg))) + tipc_msg_dbg(buf, msg_get_wrapped(msg), " /"); + if ((usr == MSG_FRAGMENTER) && (msg_type(msg) == FIRST_FRAGMENT)) + tipc_msg_dbg(buf, msg_get_wrapped(msg), " /"); +} +#endif diff --git a/trunk/net/tipc/name_distr.c b/trunk/net/tipc/name_distr.c index 55d3928dfd67..158318e67b08 100644 --- a/trunk/net/tipc/name_distr.c +++ b/trunk/net/tipc/name_distr.c @@ -161,7 +161,7 @@ void tipc_named_publish(struct publication *publ) buf = named_prepare_buf(PUBLICATION, ITEM_SIZE, 0); if (!buf) { - pr_warn("Publication distribution failure\n"); + warn("Publication distribution failure\n"); return; } @@ -186,7 +186,7 @@ void tipc_named_withdraw(struct publication *publ) buf = named_prepare_buf(WITHDRAWAL, ITEM_SIZE, 0); if (!buf) { - pr_warn("Withdrawal distribution failure\n"); + warn("Withdrawal distribution failure\n"); return; } @@ -213,7 +213,7 @@ static void named_distribute(struct list_head *message_list, u32 node, rest -= left; buf = named_prepare_buf(PUBLICATION, left, node); if (!buf) { - pr_warn("Bulk publication failure\n"); + warn("Bulk publication failure\n"); return; } item = (struct distr_item *)msg_data(buf_msg(buf)); @@ -283,10 +283,9 @@ static void named_purge_publ(struct publication *publ) write_unlock_bh(&tipc_nametbl_lock); if (p != publ) { - pr_err("Unable to remove publication from failed node\n" - " (type=%u, lower=%u, node=0x%x, ref=%u, key=%u)\n", - publ->type, publ->lower, publ->node, publ->ref, - publ->key); + err("Unable to remove publication from failed node\n" + "(type=%u, lower=%u, node=0x%x, ref=%u, key=%u)\n", + publ->type, publ->lower, publ->node, publ->ref, publ->key); } kfree(p); @@ -330,14 +329,14 @@ void tipc_named_recv(struct sk_buff *buf) tipc_nodesub_unsubscribe(&publ->subscr); kfree(publ); } else { - pr_err("Unable to remove publication by node 0x%x\n" - " (type=%u, lower=%u, ref=%u, key=%u)\n", - msg_orignode(msg), ntohl(item->type), - ntohl(item->lower), ntohl(item->ref), - ntohl(item->key)); + err("Unable to remove publication by node 0x%x\n" + "(type=%u, lower=%u, ref=%u, key=%u)\n", + msg_orignode(msg), + ntohl(item->type), ntohl(item->lower), + ntohl(item->ref), ntohl(item->key)); } } else { - pr_warn("Unrecognized name table message received\n"); + warn("Unrecognized name table message received\n"); } item++; } diff --git a/trunk/net/tipc/name_table.c b/trunk/net/tipc/name_table.c index 360c478b0b53..010f24a59da2 100644 --- a/trunk/net/tipc/name_table.c +++ b/trunk/net/tipc/name_table.c @@ -126,7 +126,7 @@ static struct publication *publ_create(u32 type, u32 lower, u32 upper, { struct publication *publ = kzalloc(sizeof(*publ), GFP_ATOMIC); if (publ == NULL) { - pr_warn("Publication creation failure, no memory\n"); + warn("Publication creation failure, no memory\n"); return NULL; } @@ -163,7 +163,7 @@ static struct name_seq *tipc_nameseq_create(u32 type, struct hlist_head *seq_hea struct sub_seq *sseq = tipc_subseq_alloc(1); if (!nseq || !sseq) { - pr_warn("Name sequence creation failed, no memory\n"); + warn("Name sequence creation failed, no memory\n"); kfree(nseq); kfree(sseq); return NULL; @@ -191,7 +191,7 @@ static void nameseq_delete_empty(struct name_seq *seq) } } -/** +/* * nameseq_find_subseq - find sub-sequence (if any) matching a name instance * * Very time-critical, so binary searches through sub-sequence array. @@ -263,8 +263,8 @@ static struct publication *tipc_nameseq_insert_publ(struct name_seq *nseq, /* Lower end overlaps existing entry => need an exact match */ if ((sseq->lower != lower) || (sseq->upper != upper)) { - pr_warn("Cannot publish {%u,%u,%u}, overlap error\n", - type, lower, upper); + warn("Cannot publish {%u,%u,%u}, overlap error\n", + type, lower, upper); return NULL; } @@ -286,8 +286,8 @@ static struct publication *tipc_nameseq_insert_publ(struct name_seq *nseq, /* Fail if upper end overlaps into an existing entry */ if ((inspos < nseq->first_free) && (upper >= nseq->sseqs[inspos].lower)) { - pr_warn("Cannot publish {%u,%u,%u}, overlap error\n", - type, lower, upper); + warn("Cannot publish {%u,%u,%u}, overlap error\n", + type, lower, upper); return NULL; } @@ -296,8 +296,8 @@ static struct publication *tipc_nameseq_insert_publ(struct name_seq *nseq, struct sub_seq *sseqs = tipc_subseq_alloc(nseq->alloc * 2); if (!sseqs) { - pr_warn("Cannot publish {%u,%u,%u}, no memory\n", - type, lower, upper); + warn("Cannot publish {%u,%u,%u}, no memory\n", + type, lower, upper); return NULL; } memcpy(sseqs, nseq->sseqs, @@ -309,8 +309,8 @@ static struct publication *tipc_nameseq_insert_publ(struct name_seq *nseq, info = kzalloc(sizeof(*info), GFP_ATOMIC); if (!info) { - pr_warn("Cannot publish {%u,%u,%u}, no memory\n", - type, lower, upper); + warn("Cannot publish {%u,%u,%u}, no memory\n", + type, lower, upper); return NULL; } @@ -435,7 +435,7 @@ static struct publication *tipc_nameseq_remove_publ(struct name_seq *nseq, u32 i } /** - * tipc_nameseq_subscribe - attach a subscription, and issue + * tipc_nameseq_subscribe: attach a subscription, and issue * the prescribed number of events if there is any sub- * sequence overlapping with the requested sequence */ @@ -492,8 +492,8 @@ struct publication *tipc_nametbl_insert_publ(u32 type, u32 lower, u32 upper, if ((scope < TIPC_ZONE_SCOPE) || (scope > TIPC_NODE_SCOPE) || (lower > upper)) { - pr_debug("Failed to publish illegal {%u,%u,%u} with scope %u\n", - type, lower, upper, scope); + dbg("Failed to publish illegal {%u,%u,%u} with scope %u\n", + type, lower, upper, scope); return NULL; } @@ -520,7 +520,7 @@ struct publication *tipc_nametbl_remove_publ(u32 type, u32 lower, return publ; } -/** +/* * tipc_nametbl_translate - perform name translation * * On entry, 'destnode' is the search domain used during translation. @@ -668,8 +668,8 @@ struct publication *tipc_nametbl_publish(u32 type, u32 lower, u32 upper, struct publication *publ; if (table.local_publ_count >= tipc_max_publications) { - pr_warn("Publication failed, local publication limit reached (%u)\n", - tipc_max_publications); + warn("Publication failed, local publication limit reached (%u)\n", + tipc_max_publications); return NULL; } @@ -702,9 +702,9 @@ int tipc_nametbl_withdraw(u32 type, u32 lower, u32 ref, u32 key) return 1; } write_unlock_bh(&tipc_nametbl_lock); - pr_err("Unable to remove local publication\n" - "(type=%u, lower=%u, ref=%u, key=%u)\n", - type, lower, ref, key); + err("Unable to remove local publication\n" + "(type=%u, lower=%u, ref=%u, key=%u)\n", + type, lower, ref, key); return 0; } @@ -725,8 +725,8 @@ void tipc_nametbl_subscribe(struct tipc_subscription *s) tipc_nameseq_subscribe(seq, s); spin_unlock_bh(&seq->lock); } else { - pr_warn("Failed to create subscription for {%u,%u,%u}\n", - s->seq.type, s->seq.lower, s->seq.upper); + warn("Failed to create subscription for {%u,%u,%u}\n", + s->seq.type, s->seq.lower, s->seq.upper); } write_unlock_bh(&tipc_nametbl_lock); } @@ -751,22 +751,21 @@ void tipc_nametbl_unsubscribe(struct tipc_subscription *s) /** - * subseq_list - print specified sub-sequence contents into the given buffer + * subseq_list: print specified sub-sequence contents into the given buffer */ -static int subseq_list(struct sub_seq *sseq, char *buf, int len, u32 depth, +static void subseq_list(struct sub_seq *sseq, struct print_buf *buf, u32 depth, u32 index) { char portIdStr[27]; const char *scope_str[] = {"", " zone", " cluster", " node"}; struct publication *publ; struct name_info *info; - int ret; - ret = tipc_snprintf(buf, len, "%-10u %-10u ", sseq->lower, sseq->upper); + tipc_printf(buf, "%-10u %-10u ", sseq->lower, sseq->upper); if (depth == 2) { - ret += tipc_snprintf(buf - ret, len + ret, "\n"); - return ret; + tipc_printf(buf, "\n"); + return; } info = sseq->info; @@ -775,58 +774,52 @@ static int subseq_list(struct sub_seq *sseq, char *buf, int len, u32 depth, sprintf(portIdStr, "<%u.%u.%u:%u>", tipc_zone(publ->node), tipc_cluster(publ->node), tipc_node(publ->node), publ->ref); - ret += tipc_snprintf(buf + ret, len - ret, "%-26s ", portIdStr); + tipc_printf(buf, "%-26s ", portIdStr); if (depth > 3) { - ret += tipc_snprintf(buf + ret, len - ret, "%-10u %s", - publ->key, scope_str[publ->scope]); + tipc_printf(buf, "%-10u %s", publ->key, + scope_str[publ->scope]); } if (!list_is_last(&publ->zone_list, &info->zone_list)) - ret += tipc_snprintf(buf + ret, len - ret, - "\n%33s", " "); + tipc_printf(buf, "\n%33s", " "); }; - ret += tipc_snprintf(buf + ret, len - ret, "\n"); - return ret; + tipc_printf(buf, "\n"); } /** - * nameseq_list - print specified name sequence contents into the given buffer + * nameseq_list: print specified name sequence contents into the given buffer */ -static int nameseq_list(struct name_seq *seq, char *buf, int len, u32 depth, +static void nameseq_list(struct name_seq *seq, struct print_buf *buf, u32 depth, u32 type, u32 lowbound, u32 upbound, u32 index) { struct sub_seq *sseq; char typearea[11]; - int ret = 0; if (seq->first_free == 0) - return 0; + return; sprintf(typearea, "%-10u", seq->type); if (depth == 1) { - ret += tipc_snprintf(buf, len, "%s\n", typearea); - return ret; + tipc_printf(buf, "%s\n", typearea); + return; } for (sseq = seq->sseqs; sseq != &seq->sseqs[seq->first_free]; sseq++) { if ((lowbound <= sseq->upper) && (upbound >= sseq->lower)) { - ret += tipc_snprintf(buf + ret, len - ret, "%s ", - typearea); + tipc_printf(buf, "%s ", typearea); spin_lock_bh(&seq->lock); - ret += subseq_list(sseq, buf + ret, len - ret, - depth, index); + subseq_list(sseq, buf, depth, index); spin_unlock_bh(&seq->lock); sprintf(typearea, "%10s", " "); } } - return ret; } /** * nametbl_header - print name table header into the given buffer */ -static int nametbl_header(char *buf, int len, u32 depth) +static void nametbl_header(struct print_buf *buf, u32 depth) { const char *header[] = { "Type ", @@ -836,27 +829,24 @@ static int nametbl_header(char *buf, int len, u32 depth) }; int i; - int ret = 0; if (depth > 4) depth = 4; for (i = 0; i < depth; i++) - ret += tipc_snprintf(buf + ret, len - ret, header[i]); - ret += tipc_snprintf(buf + ret, len - ret, "\n"); - return ret; + tipc_printf(buf, header[i]); + tipc_printf(buf, "\n"); } /** * nametbl_list - print specified name table contents into the given buffer */ -static int nametbl_list(char *buf, int len, u32 depth_info, +static void nametbl_list(struct print_buf *buf, u32 depth_info, u32 type, u32 lowbound, u32 upbound) { struct hlist_head *seq_head; struct hlist_node *seq_node; struct name_seq *seq; int all_types; - int ret = 0; u32 depth; u32 i; @@ -864,69 +854,65 @@ static int nametbl_list(char *buf, int len, u32 depth_info, depth = (depth_info & ~TIPC_NTQ_ALLTYPES); if (depth == 0) - return 0; + return; if (all_types) { /* display all entries in name table to specified depth */ - ret += nametbl_header(buf, len, depth); + nametbl_header(buf, depth); lowbound = 0; upbound = ~0; for (i = 0; i < tipc_nametbl_size; i++) { seq_head = &table.types[i]; hlist_for_each_entry(seq, seq_node, seq_head, ns_list) { - ret += nameseq_list(seq, buf + ret, len - ret, - depth, seq->type, - lowbound, upbound, i); + nameseq_list(seq, buf, depth, seq->type, + lowbound, upbound, i); } } } else { /* display only the sequence that matches the specified type */ if (upbound < lowbound) { - ret += tipc_snprintf(buf + ret, len - ret, - "invalid name sequence specified\n"); - return ret; + tipc_printf(buf, "invalid name sequence specified\n"); + return; } - ret += nametbl_header(buf + ret, len - ret, depth); + nametbl_header(buf, depth); i = hash(type); seq_head = &table.types[i]; hlist_for_each_entry(seq, seq_node, seq_head, ns_list) { if (seq->type == type) { - ret += nameseq_list(seq, buf + ret, len - ret, - depth, type, - lowbound, upbound, i); + nameseq_list(seq, buf, depth, type, + lowbound, upbound, i); break; } } } - return ret; } +#define MAX_NAME_TBL_QUERY 32768 + struct sk_buff *tipc_nametbl_get(const void *req_tlv_area, int req_tlv_space) { struct sk_buff *buf; struct tipc_name_table_query *argv; struct tlv_desc *rep_tlv; - char *pb; - int pb_len; + struct print_buf b; int str_len; if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NAME_TBL_QUERY)) return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); - buf = tipc_cfg_reply_alloc(TLV_SPACE(ULTRA_STRING_MAX_LEN)); + buf = tipc_cfg_reply_alloc(TLV_SPACE(MAX_NAME_TBL_QUERY)); if (!buf) return NULL; rep_tlv = (struct tlv_desc *)buf->data; - pb = TLV_DATA(rep_tlv); - pb_len = ULTRA_STRING_MAX_LEN; + tipc_printbuf_init(&b, TLV_DATA(rep_tlv), MAX_NAME_TBL_QUERY); argv = (struct tipc_name_table_query *)TLV_DATA(req_tlv_area); read_lock_bh(&tipc_nametbl_lock); - str_len = nametbl_list(pb, pb_len, ntohl(argv->depth), - ntohl(argv->type), - ntohl(argv->lowbound), ntohl(argv->upbound)); + nametbl_list(&b, ntohl(argv->depth), ntohl(argv->type), + ntohl(argv->lowbound), ntohl(argv->upbound)); read_unlock_bh(&tipc_nametbl_lock); - str_len += 1; /* for "\0" */ + str_len = tipc_printbuf_validate(&b); + skb_put(buf, TLV_SPACE(str_len)); TLV_SET(rep_tlv, TIPC_TLV_ULTRA_STRING, NULL, str_len); @@ -954,10 +940,8 @@ void tipc_nametbl_stop(void) /* Verify name table is empty, then release it */ write_lock_bh(&tipc_nametbl_lock); for (i = 0; i < tipc_nametbl_size; i++) { - if (hlist_empty(&table.types[i])) - continue; - pr_err("nametbl_stop(): orphaned hash chain detected\n"); - break; + if (!hlist_empty(&table.types[i])) + err("tipc_nametbl_stop(): hash chain %u is non-null\n", i); } kfree(table.types); table.types = NULL; diff --git a/trunk/net/tipc/net.c b/trunk/net/tipc/net.c index 5b5cea259caf..7c236c89cf5e 100644 --- a/trunk/net/tipc/net.c +++ b/trunk/net/tipc/net.c @@ -184,9 +184,9 @@ int tipc_net_start(u32 addr) tipc_cfg_reinit(); - pr_info("Started in network mode\n"); - pr_info("Own node address %s, network identity %u\n", - tipc_addr_string_fill(addr_string, tipc_own_addr), tipc_net_id); + info("Started in network mode\n"); + info("Own node address %s, network identity %u\n", + tipc_addr_string_fill(addr_string, tipc_own_addr), tipc_net_id); return 0; } @@ -202,5 +202,5 @@ void tipc_net_stop(void) list_for_each_entry_safe(node, t_node, &tipc_node_list, list) tipc_node_delete(node); write_unlock_bh(&tipc_net_lock); - pr_info("Left network mode\n"); + info("Left network mode\n"); } diff --git a/trunk/net/tipc/netlink.c b/trunk/net/tipc/netlink.c index 47a839df27dc..7bda8e3d1398 100644 --- a/trunk/net/tipc/netlink.c +++ b/trunk/net/tipc/netlink.c @@ -90,7 +90,7 @@ int tipc_netlink_start(void) res = genl_register_family_with_ops(&tipc_genl_family, &tipc_genl_ops, 1); if (res) { - pr_err("Failed to register netlink interface\n"); + err("Failed to register netlink interface\n"); return res; } diff --git a/trunk/net/tipc/node.c b/trunk/net/tipc/node.c index d21db204e25a..d4fd341e6e0d 100644 --- a/trunk/net/tipc/node.c +++ b/trunk/net/tipc/node.c @@ -105,7 +105,7 @@ struct tipc_node *tipc_node_create(u32 addr) n_ptr = kzalloc(sizeof(*n_ptr), GFP_ATOMIC); if (!n_ptr) { spin_unlock_bh(&node_create_lock); - pr_warn("Node creation failed, no memory\n"); + warn("Node creation failed, no memory\n"); return NULL; } @@ -151,8 +151,8 @@ void tipc_node_link_up(struct tipc_node *n_ptr, struct tipc_link *l_ptr) n_ptr->working_links++; - pr_info("Established link <%s> on network plane %c\n", - l_ptr->name, l_ptr->b_ptr->net_plane); + info("Established link <%s> on network plane %c\n", + l_ptr->name, l_ptr->b_ptr->net_plane); if (!active[0]) { active[0] = active[1] = l_ptr; @@ -160,7 +160,7 @@ void tipc_node_link_up(struct tipc_node *n_ptr, struct tipc_link *l_ptr) return; } if (l_ptr->priority < active[0]->priority) { - pr_info("New link <%s> becomes standby\n", l_ptr->name); + info("New link <%s> becomes standby\n", l_ptr->name); return; } tipc_link_send_duplicate(active[0], l_ptr); @@ -168,9 +168,9 @@ void tipc_node_link_up(struct tipc_node *n_ptr, struct tipc_link *l_ptr) active[0] = l_ptr; return; } - pr_info("Old link <%s> becomes standby\n", active[0]->name); + info("Old link <%s> becomes standby\n", active[0]->name); if (active[1] != active[0]) - pr_info("Old link <%s> becomes standby\n", active[1]->name); + info("Old link <%s> becomes standby\n", active[1]->name); active[0] = active[1] = l_ptr; } @@ -211,11 +211,11 @@ void tipc_node_link_down(struct tipc_node *n_ptr, struct tipc_link *l_ptr) n_ptr->working_links--; if (!tipc_link_is_active(l_ptr)) { - pr_info("Lost standby link <%s> on network plane %c\n", - l_ptr->name, l_ptr->b_ptr->net_plane); + info("Lost standby link <%s> on network plane %c\n", + l_ptr->name, l_ptr->b_ptr->net_plane); return; } - pr_info("Lost link <%s> on network plane %c\n", + info("Lost link <%s> on network plane %c\n", l_ptr->name, l_ptr->b_ptr->net_plane); active = &n_ptr->active_links[0]; @@ -290,8 +290,8 @@ static void node_lost_contact(struct tipc_node *n_ptr) char addr_string[16]; u32 i; - pr_info("Lost contact with %s\n", - tipc_addr_string_fill(addr_string, n_ptr->addr)); + info("Lost contact with %s\n", + tipc_addr_string_fill(addr_string, n_ptr->addr)); /* Flush broadcast link info associated with lost node */ if (n_ptr->bclink.supported) { diff --git a/trunk/net/tipc/node_subscr.c b/trunk/net/tipc/node_subscr.c index 5e34b015da45..7a27344108fe 100644 --- a/trunk/net/tipc/node_subscr.c +++ b/trunk/net/tipc/node_subscr.c @@ -51,8 +51,7 @@ void tipc_nodesub_subscribe(struct tipc_node_subscr *node_sub, u32 addr, node_sub->node = tipc_node_find(addr); if (!node_sub->node) { - pr_warn("Node subscription rejected, unknown node 0x%x\n", - addr); + warn("Node subscription rejected, unknown node 0x%x\n", addr); return; } node_sub->handle_node_down = handle_down; diff --git a/trunk/net/tipc/port.c b/trunk/net/tipc/port.c index 07c42fba672b..a1e828989d7a 100644 --- a/trunk/net/tipc/port.c +++ b/trunk/net/tipc/port.c @@ -69,7 +69,7 @@ static u32 port_peerport(struct tipc_port *p_ptr) return msg_destport(&p_ptr->phdr); } -/** +/* * tipc_port_peer_msg - verify message was sent by connected port's peer * * Handles cases where the node's network address has changed from @@ -191,7 +191,7 @@ void tipc_port_recv_mcast(struct sk_buff *buf, struct tipc_port_list *dp) struct sk_buff *b = skb_clone(buf, GFP_ATOMIC); if (b == NULL) { - pr_warn("Unable to deliver multicast message(s)\n"); + warn("Unable to deliver multicast message(s)\n"); goto exit; } if ((index == 0) && (cnt != 0)) @@ -221,12 +221,12 @@ struct tipc_port *tipc_createport_raw(void *usr_handle, p_ptr = kzalloc(sizeof(*p_ptr), GFP_ATOMIC); if (!p_ptr) { - pr_warn("Port creation failed, no memory\n"); + warn("Port creation failed, no memory\n"); return NULL; } ref = tipc_ref_acquire(p_ptr, &p_ptr->lock); if (!ref) { - pr_warn("Port creation failed, ref. table exhausted\n"); + warn("Port creation failed, reference table exhausted\n"); kfree(p_ptr); return NULL; } @@ -581,73 +581,67 @@ void tipc_port_recv_proto_msg(struct sk_buff *buf) kfree_skb(buf); } -static int port_print(struct tipc_port *p_ptr, char *buf, int len, int full_id) +static void port_print(struct tipc_port *p_ptr, struct print_buf *buf, int full_id) { struct publication *publ; - int ret; if (full_id) - ret = tipc_snprintf(buf, len, "<%u.%u.%u:%u>:", - tipc_zone(tipc_own_addr), - tipc_cluster(tipc_own_addr), - tipc_node(tipc_own_addr), p_ptr->ref); + tipc_printf(buf, "<%u.%u.%u:%u>:", + tipc_zone(tipc_own_addr), tipc_cluster(tipc_own_addr), + tipc_node(tipc_own_addr), p_ptr->ref); else - ret = tipc_snprintf(buf, len, "%-10u:", p_ptr->ref); + tipc_printf(buf, "%-10u:", p_ptr->ref); if (p_ptr->connected) { u32 dport = port_peerport(p_ptr); u32 destnode = port_peernode(p_ptr); - ret += tipc_snprintf(buf + ret, len - ret, - " connected to <%u.%u.%u:%u>", - tipc_zone(destnode), - tipc_cluster(destnode), - tipc_node(destnode), dport); + tipc_printf(buf, " connected to <%u.%u.%u:%u>", + tipc_zone(destnode), tipc_cluster(destnode), + tipc_node(destnode), dport); if (p_ptr->conn_type != 0) - ret += tipc_snprintf(buf + ret, len - ret, - " via {%u,%u}", p_ptr->conn_type, - p_ptr->conn_instance); + tipc_printf(buf, " via {%u,%u}", + p_ptr->conn_type, + p_ptr->conn_instance); } else if (p_ptr->published) { - ret += tipc_snprintf(buf + ret, len - ret, " bound to"); + tipc_printf(buf, " bound to"); list_for_each_entry(publ, &p_ptr->publications, pport_list) { if (publ->lower == publ->upper) - ret += tipc_snprintf(buf + ret, len - ret, - " {%u,%u}", publ->type, - publ->lower); + tipc_printf(buf, " {%u,%u}", publ->type, + publ->lower); else - ret += tipc_snprintf(buf + ret, len - ret, - " {%u,%u,%u}", publ->type, - publ->lower, publ->upper); + tipc_printf(buf, " {%u,%u,%u}", publ->type, + publ->lower, publ->upper); } } - ret += tipc_snprintf(buf + ret, len - ret, "\n"); - return ret; + tipc_printf(buf, "\n"); } +#define MAX_PORT_QUERY 32768 + struct sk_buff *tipc_port_get_ports(void) { struct sk_buff *buf; struct tlv_desc *rep_tlv; - char *pb; - int pb_len; + struct print_buf pb; struct tipc_port *p_ptr; - int str_len = 0; + int str_len; - buf = tipc_cfg_reply_alloc(TLV_SPACE(ULTRA_STRING_MAX_LEN)); + buf = tipc_cfg_reply_alloc(TLV_SPACE(MAX_PORT_QUERY)); if (!buf) return NULL; rep_tlv = (struct tlv_desc *)buf->data; - pb = TLV_DATA(rep_tlv); - pb_len = ULTRA_STRING_MAX_LEN; + tipc_printbuf_init(&pb, TLV_DATA(rep_tlv), MAX_PORT_QUERY); spin_lock_bh(&tipc_port_list_lock); list_for_each_entry(p_ptr, &ports, port_list) { spin_lock_bh(p_ptr->lock); - str_len += port_print(p_ptr, pb, pb_len, 0); + port_print(p_ptr, &pb, 0); spin_unlock_bh(p_ptr->lock); } spin_unlock_bh(&tipc_port_list_lock); - str_len += 1; /* for "\0" */ + str_len = tipc_printbuf_validate(&pb); + skb_put(buf, TLV_SPACE(str_len)); TLV_SET(rep_tlv, TIPC_TLV_ULTRA_STRING, NULL, str_len); @@ -912,7 +906,7 @@ int tipc_createport(void *usr_handle, up_ptr = kmalloc(sizeof(*up_ptr), GFP_ATOMIC); if (!up_ptr) { - pr_warn("Port creation failed, no memory\n"); + warn("Port creation failed, no memory\n"); return -ENOMEM; } p_ptr = tipc_createport_raw(NULL, port_dispatcher, port_wakeup, diff --git a/trunk/net/tipc/port.h b/trunk/net/tipc/port.h index 4660e3065790..98cbec9c4532 100644 --- a/trunk/net/tipc/port.h +++ b/trunk/net/tipc/port.h @@ -79,7 +79,6 @@ typedef void (*tipc_continue_event) (void *usr_handle, u32 portref); * struct user_port - TIPC user port (used with native API) * @usr_handle: user-specified field * @ref: object reference to associated TIPC port - * * */ struct user_port { diff --git a/trunk/net/tipc/ref.c b/trunk/net/tipc/ref.c index 2a2a938dc22c..5cada0e38e03 100644 --- a/trunk/net/tipc/ref.c +++ b/trunk/net/tipc/ref.c @@ -153,11 +153,11 @@ u32 tipc_ref_acquire(void *object, spinlock_t **lock) struct reference *entry = NULL; if (!object) { - pr_err("Attempt to acquire ref. to non-existent obj\n"); + err("Attempt to acquire reference to non-existent object\n"); return 0; } if (!tipc_ref_table.entries) { - pr_err("Ref. table not found in acquisition attempt\n"); + err("Reference table not found during acquisition attempt\n"); return 0; } @@ -211,7 +211,7 @@ void tipc_ref_discard(u32 ref) u32 index_mask; if (!tipc_ref_table.entries) { - pr_err("Ref. table not found during discard attempt\n"); + err("Reference table not found during discard attempt\n"); return; } @@ -222,11 +222,11 @@ void tipc_ref_discard(u32 ref) write_lock_bh(&ref_table_lock); if (!entry->object) { - pr_err("Attempt to discard ref. to non-existent obj\n"); + err("Attempt to discard reference to non-existent object\n"); goto exit; } if (entry->ref != ref) { - pr_err("Attempt to discard non-existent reference\n"); + err("Attempt to discard non-existent reference\n"); goto exit; } diff --git a/trunk/net/tipc/socket.c b/trunk/net/tipc/socket.c index 09dc5b97e079..11a863d81421 100644 --- a/trunk/net/tipc/socket.c +++ b/trunk/net/tipc/socket.c @@ -34,12 +34,12 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include "core.h" -#include "port.h" - #include #include +#include "core.h" +#include "port.h" + #define SS_LISTENING -1 /* socket is listening */ #define SS_READY -2 /* socket is connectionless */ @@ -1699,8 +1699,9 @@ static int getsockopt(struct socket *sock, return put_user(sizeof(value), ol); } -/* Protocol switches for the various types of TIPC sockets */ - +/** + * Protocol switches for the various types of TIPC sockets + */ static const struct proto_ops msg_ops = { .owner = THIS_MODULE, .family = AF_TIPC, @@ -1787,13 +1788,13 @@ int tipc_socket_init(void) res = proto_register(&tipc_proto, 1); if (res) { - pr_err("Failed to register TIPC protocol type\n"); + err("Failed to register TIPC protocol type\n"); goto out; } res = sock_register(&tipc_family_ops); if (res) { - pr_err("Failed to register TIPC socket type\n"); + err("Failed to register TIPC socket type\n"); proto_unregister(&tipc_proto); goto out; } diff --git a/trunk/net/tipc/subscr.c b/trunk/net/tipc/subscr.c index 5ed5965eb0be..f976e9cd6a72 100644 --- a/trunk/net/tipc/subscr.c +++ b/trunk/net/tipc/subscr.c @@ -305,8 +305,8 @@ static struct tipc_subscription *subscr_subscribe(struct tipc_subscr *s, /* Refuse subscription if global limit exceeded */ if (atomic_read(&topsrv.subscription_count) >= tipc_max_subscriptions) { - pr_warn("Subscription rejected, limit reached (%u)\n", - tipc_max_subscriptions); + warn("Subscription rejected, subscription limit reached (%u)\n", + tipc_max_subscriptions); subscr_terminate(subscriber); return NULL; } @@ -314,7 +314,7 @@ static struct tipc_subscription *subscr_subscribe(struct tipc_subscr *s, /* Allocate subscription object */ sub = kmalloc(sizeof(*sub), GFP_ATOMIC); if (!sub) { - pr_warn("Subscription rejected, no memory\n"); + warn("Subscription rejected, no memory\n"); subscr_terminate(subscriber); return NULL; } @@ -328,7 +328,7 @@ static struct tipc_subscription *subscr_subscribe(struct tipc_subscr *s, if ((!(sub->filter & TIPC_SUB_PORTS) == !(sub->filter & TIPC_SUB_SERVICE)) || (sub->seq.lower > sub->seq.upper)) { - pr_warn("Subscription rejected, illegal request\n"); + warn("Subscription rejected, illegal request\n"); kfree(sub); subscr_terminate(subscriber); return NULL; @@ -440,7 +440,7 @@ static void subscr_named_msg_event(void *usr_handle, /* Create subscriber object */ subscriber = kzalloc(sizeof(struct tipc_subscriber), GFP_ATOMIC); if (subscriber == NULL) { - pr_warn("Subscriber rejected, no memory\n"); + warn("Subscriber rejected, no memory\n"); return; } INIT_LIST_HEAD(&subscriber->subscription_list); @@ -458,7 +458,7 @@ static void subscr_named_msg_event(void *usr_handle, NULL, &subscriber->port_ref); if (subscriber->port_ref == 0) { - pr_warn("Subscriber rejected, unable to create port\n"); + warn("Subscriber rejected, unable to create port\n"); kfree(subscriber); return; } @@ -517,7 +517,7 @@ int tipc_subscr_start(void) return 0; failed: - pr_err("Failed to create subscription service\n"); + err("Failed to create subscription service\n"); return res; } diff --git a/trunk/net/unix/diag.c b/trunk/net/unix/diag.c index 750b13408449..a74864eedfcd 100644 --- a/trunk/net/unix/diag.c +++ b/trunk/net/unix/diag.c @@ -177,7 +177,6 @@ static int unix_diag_dump(struct sk_buff *skb, struct netlink_callback *cb) { struct unix_diag_req *req; int num, s_num, slot, s_slot; - struct net *net = sock_net(skb->sk); req = nlmsg_data(cb->nlh); @@ -193,8 +192,6 @@ static int unix_diag_dump(struct sk_buff *skb, struct netlink_callback *cb) num = 0; sk_for_each(sk, node, &unix_socket_table[slot]) { - if (!net_eq(sock_net(sk), net)) - continue; if (num < s_num) goto next; if (!(req->udiag_states & (1 << sk->sk_state))) @@ -246,7 +243,6 @@ static int unix_diag_get_exact(struct sk_buff *in_skb, struct sock *sk; struct sk_buff *rep; unsigned int extra_len; - struct net *net = sock_net(in_skb->sk); if (req->udiag_ino == 0) goto out_nosk; @@ -277,7 +273,7 @@ static int unix_diag_get_exact(struct sk_buff *in_skb, goto again; } - err = netlink_unicast(net->diag_nlsk, rep, NETLINK_CB(in_skb).pid, + err = netlink_unicast(sock_diag_nlsk, rep, NETLINK_CB(in_skb).pid, MSG_DONTWAIT); if (err > 0) err = 0; @@ -291,7 +287,6 @@ static int unix_diag_get_exact(struct sk_buff *in_skb, static int unix_diag_handler_dump(struct sk_buff *skb, struct nlmsghdr *h) { int hdrlen = sizeof(struct unix_diag_req); - struct net *net = sock_net(skb->sk); if (nlmsg_len(h) < hdrlen) return -EINVAL; @@ -300,7 +295,7 @@ static int unix_diag_handler_dump(struct sk_buff *skb, struct nlmsghdr *h) struct netlink_dump_control c = { .dump = unix_diag_dump, }; - return netlink_dump_start(net->diag_nlsk, skb, h, &c); + return netlink_dump_start(sock_diag_nlsk, skb, h, &c); } else return unix_diag_get_exact(skb, h, nlmsg_data(h)); } diff --git a/trunk/net/wireless/Makefile b/trunk/net/wireless/Makefile index 0f7e0d621ab0..55a28ab21db9 100644 --- a/trunk/net/wireless/Makefile +++ b/trunk/net/wireless/Makefile @@ -10,7 +10,7 @@ obj-$(CONFIG_WEXT_SPY) += wext-spy.o obj-$(CONFIG_WEXT_PRIV) += wext-priv.o cfg80211-y += core.o sysfs.o radiotap.o util.o reg.o scan.o nl80211.o -cfg80211-y += mlme.o ibss.o sme.o chan.o ethtool.o mesh.o ap.o +cfg80211-y += mlme.o ibss.o sme.o chan.o ethtool.o mesh.o cfg80211-$(CONFIG_CFG80211_DEBUGFS) += debugfs.o cfg80211-$(CONFIG_CFG80211_WEXT) += wext-compat.o wext-sme.o cfg80211-$(CONFIG_CFG80211_INTERNAL_REGDB) += regdb.o diff --git a/trunk/net/wireless/ap.c b/trunk/net/wireless/ap.c deleted file mode 100644 index fcc60d8dbefa..000000000000 --- a/trunk/net/wireless/ap.c +++ /dev/null @@ -1,46 +0,0 @@ -#include -#include -#include -#include "nl80211.h" -#include "core.h" - - -static int __cfg80211_stop_ap(struct cfg80211_registered_device *rdev, - struct net_device *dev) -{ - struct wireless_dev *wdev = dev->ieee80211_ptr; - int err; - - ASSERT_WDEV_LOCK(wdev); - - if (!rdev->ops->stop_ap) - return -EOPNOTSUPP; - - if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && - dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) - return -EOPNOTSUPP; - - if (!wdev->beacon_interval) - return -ENOENT; - - err = rdev->ops->stop_ap(&rdev->wiphy, dev); - if (!err) { - wdev->beacon_interval = 0; - wdev->channel = NULL; - } - - return err; -} - -int cfg80211_stop_ap(struct cfg80211_registered_device *rdev, - struct net_device *dev) -{ - struct wireless_dev *wdev = dev->ieee80211_ptr; - int err; - - wdev_lock(wdev); - err = __cfg80211_stop_ap(rdev, dev); - wdev_unlock(wdev); - - return err; -} diff --git a/trunk/net/wireless/chan.c b/trunk/net/wireless/chan.c index 434c56b92c3c..c1999e45a07c 100644 --- a/trunk/net/wireless/chan.c +++ b/trunk/net/wireless/chan.c @@ -82,73 +82,13 @@ int cfg80211_set_monitor_channel(struct cfg80211_registered_device *rdev, int freq, enum nl80211_channel_type chantype) { struct ieee80211_channel *chan; - int err; if (!rdev->ops->set_monitor_channel) return -EOPNOTSUPP; - if (!cfg80211_has_monitors_only(rdev)) - return -EBUSY; chan = rdev_freq_to_chan(rdev, freq, chantype); if (!chan) return -EINVAL; - err = rdev->ops->set_monitor_channel(&rdev->wiphy, chan, chantype); - if (!err) { - rdev->monitor_channel = chan; - rdev->monitor_channel_type = chantype; - } - - return err; -} - -void -cfg80211_get_chan_state(struct cfg80211_registered_device *rdev, - struct wireless_dev *wdev, - struct ieee80211_channel **chan, - enum cfg80211_chan_mode *chanmode) -{ - *chan = NULL; - *chanmode = CHAN_MODE_UNDEFINED; - - ASSERT_RDEV_LOCK(rdev); - ASSERT_WDEV_LOCK(wdev); - - if (!netif_running(wdev->netdev)) - return; - - switch (wdev->iftype) { - case NL80211_IFTYPE_ADHOC: - if (wdev->current_bss) { - *chan = wdev->current_bss->pub.channel; - *chanmode = wdev->ibss_fixed - ? CHAN_MODE_SHARED - : CHAN_MODE_EXCLUSIVE; - return; - } - case NL80211_IFTYPE_STATION: - case NL80211_IFTYPE_P2P_CLIENT: - if (wdev->current_bss) { - *chan = wdev->current_bss->pub.channel; - *chanmode = CHAN_MODE_SHARED; - return; - } - break; - case NL80211_IFTYPE_AP: - case NL80211_IFTYPE_P2P_GO: - case NL80211_IFTYPE_MESH_POINT: - *chan = wdev->channel; - *chanmode = CHAN_MODE_SHARED; - return; - case NL80211_IFTYPE_MONITOR: - case NL80211_IFTYPE_AP_VLAN: - case NL80211_IFTYPE_WDS: - /* these interface types don't really have a channel */ - return; - case NL80211_IFTYPE_UNSPECIFIED: - case NUM_NL80211_IFTYPES: - WARN_ON(1); - } - - return; + return rdev->ops->set_monitor_channel(&rdev->wiphy, chan, chantype); } diff --git a/trunk/net/wireless/core.c b/trunk/net/wireless/core.c index eb60410ae588..907f62c80e28 100644 --- a/trunk/net/wireless/core.c +++ b/trunk/net/wireless/core.c @@ -373,14 +373,6 @@ static int wiphy_verify_combinations(struct wiphy *wiphy) if (WARN_ON(!c->num_different_channels)) return -EINVAL; - /* - * Put a sane limit on maximum number of different - * channels to simplify channel accounting code. - */ - if (WARN_ON(c->num_different_channels > - CFG80211_MAX_NUM_DIFFERENT_CHANNELS)) - return -EINVAL; - if (WARN_ON(!c->n_limits)) return -EINVAL; @@ -429,11 +421,9 @@ int wiphy_register(struct wiphy *wiphy) int i; u16 ifmodes = wiphy->interface_modes; -#ifdef CONFIG_PM if (WARN_ON((wiphy->wowlan.flags & WIPHY_WOWLAN_GTK_REKEY_FAILURE) && !(wiphy->wowlan.flags & WIPHY_WOWLAN_SUPPORTS_GTK_REKEY))) return -EINVAL; -#endif if (WARN_ON(wiphy->ap_sme_capa && !(wiphy->flags & WIPHY_FLAG_HAVE_AP_SME))) @@ -468,14 +458,8 @@ int wiphy_register(struct wiphy *wiphy) continue; sband->band = band; - if (WARN_ON(!sband->n_channels)) - return -EINVAL; - /* - * on 60gHz band, there are no legacy rates, so - * n_bitrates is 0 - */ - if (WARN_ON(band != IEEE80211_BAND_60GHZ && - !sband->n_bitrates)) + + if (WARN_ON(!sband->n_channels || !sband->n_bitrates)) return -EINVAL; /* @@ -516,14 +500,12 @@ int wiphy_register(struct wiphy *wiphy) return -EINVAL; } -#ifdef CONFIG_PM if (rdev->wiphy.wowlan.n_patterns) { if (WARN_ON(!rdev->wiphy.wowlan.pattern_min_len || rdev->wiphy.wowlan.pattern_min_len > rdev->wiphy.wowlan.pattern_max_len)) return -EINVAL; } -#endif /* check and set up bitrates */ ieee80211_set_bitrate_flags(wiphy); @@ -731,61 +713,6 @@ static struct device_type wiphy_type = { .name = "wlan", }; -static struct ieee80211_channel * -cfg80211_get_any_chan(struct cfg80211_registered_device *rdev) -{ - struct ieee80211_supported_band *sband; - int i; - - for (i = 0; i < IEEE80211_NUM_BANDS; i++) { - sband = rdev->wiphy.bands[i]; - if (sband && sband->n_channels > 0) - return &sband->channels[0]; - } - - return NULL; -} - -static void cfg80211_init_mon_chan(struct cfg80211_registered_device *rdev) -{ - struct ieee80211_channel *chan; - - chan = cfg80211_get_any_chan(rdev); - if (WARN_ON(!chan)) - return; - - mutex_lock(&rdev->devlist_mtx); - WARN_ON(cfg80211_set_monitor_channel(rdev, chan->center_freq, - NL80211_CHAN_NO_HT)); - mutex_unlock(&rdev->devlist_mtx); -} - -void cfg80211_update_iface_num(struct cfg80211_registered_device *rdev, - enum nl80211_iftype iftype, int num) -{ - bool has_monitors_only_old = cfg80211_has_monitors_only(rdev); - bool has_monitors_only_new; - - ASSERT_RTNL(); - - rdev->num_running_ifaces += num; - if (iftype == NL80211_IFTYPE_MONITOR) - rdev->num_running_monitor_ifaces += num; - - has_monitors_only_new = cfg80211_has_monitors_only(rdev); - if (has_monitors_only_new != has_monitors_only_old) { - rdev->ops->set_monitor_enabled(&rdev->wiphy, - has_monitors_only_new); - - if (!has_monitors_only_new) { - rdev->monitor_channel = NULL; - rdev->monitor_channel_type = NL80211_CHAN_NO_HT; - } else { - cfg80211_init_mon_chan(rdev); - } - } -} - static int cfg80211_netdev_notifier_call(struct notifier_block *nb, unsigned long state, void *ndev) @@ -879,16 +806,12 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb, case NL80211_IFTYPE_MESH_POINT: cfg80211_leave_mesh(rdev, dev); break; - case NL80211_IFTYPE_AP: - cfg80211_stop_ap(rdev, dev); - break; default: break; } wdev->beacon_interval = 0; break; case NETDEV_DOWN: - cfg80211_update_iface_num(rdev, wdev->iftype, -1); dev_hold(dev); queue_work(cfg80211_wq, &wdev->cleanup_work); break; @@ -994,12 +917,9 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb, return notifier_from_errno(-EOPNOTSUPP); if (rfkill_blocked(rdev->rfkill)) return notifier_from_errno(-ERFKILL); - mutex_lock(&rdev->devlist_mtx); ret = cfg80211_can_add_interface(rdev, wdev->iftype); - mutex_unlock(&rdev->devlist_mtx); if (ret) return notifier_from_errno(ret); - cfg80211_update_iface_num(rdev, wdev->iftype, 1); break; } diff --git a/trunk/net/wireless/core.h b/trunk/net/wireless/core.h index 377dc394f48c..609a579255ac 100644 --- a/trunk/net/wireless/core.h +++ b/trunk/net/wireless/core.h @@ -13,7 +13,6 @@ #include #include #include -#include #include #include #include "reg.h" @@ -57,13 +56,6 @@ struct cfg80211_registered_device { u32 ap_beacons_nlpid; - /* protected by RTNL only */ - int num_running_ifaces; - int num_running_monitor_ifaces; - - struct ieee80211_channel *monitor_channel; - enum nl80211_channel_type monitor_channel_type; - /* BSSes/scanning */ spinlock_t bss_lock; struct list_head bss_list; @@ -205,14 +197,6 @@ static inline void wdev_unlock(struct wireless_dev *wdev) #define ASSERT_RDEV_LOCK(rdev) lockdep_assert_held(&(rdev)->mtx) #define ASSERT_WDEV_LOCK(wdev) lockdep_assert_held(&(wdev)->mtx) -static inline bool cfg80211_has_monitors_only(struct cfg80211_registered_device *rdev) -{ - ASSERT_RTNL(); - - return rdev->num_running_ifaces == rdev->num_running_monitor_ifaces && - rdev->num_running_ifaces > 0; -} - enum cfg80211_event_type { EVENT_CONNECT_RESULT, EVENT_ROAMED, @@ -257,12 +241,6 @@ struct cfg80211_cached_keys { int def, defmgmt; }; -enum cfg80211_chan_mode { - CHAN_MODE_UNDEFINED, - CHAN_MODE_SHARED, - CHAN_MODE_EXCLUSIVE, -}; - /* free object */ extern void cfg80211_dev_free(struct cfg80211_registered_device *rdev); @@ -311,10 +289,6 @@ int cfg80211_set_mesh_freq(struct cfg80211_registered_device *rdev, struct wireless_dev *wdev, int freq, enum nl80211_channel_type channel_type); -/* AP */ -int cfg80211_stop_ap(struct cfg80211_registered_device *rdev, - struct net_device *dev); - /* MLME */ int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, struct net_device *dev, @@ -430,20 +404,9 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev, u32 *flags, struct vif_params *params); void cfg80211_process_rdev_events(struct cfg80211_registered_device *rdev); -int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev, - struct wireless_dev *wdev, - enum nl80211_iftype iftype, - struct ieee80211_channel *chan, - enum cfg80211_chan_mode chanmode); - -static inline int -cfg80211_can_change_interface(struct cfg80211_registered_device *rdev, - struct wireless_dev *wdev, - enum nl80211_iftype iftype) -{ - return cfg80211_can_use_iftype_chan(rdev, wdev, iftype, NULL, - CHAN_MODE_UNDEFINED); -} +int cfg80211_can_change_interface(struct cfg80211_registered_device *rdev, + struct wireless_dev *wdev, + enum nl80211_iftype iftype); static inline int cfg80211_can_add_interface(struct cfg80211_registered_device *rdev, @@ -452,22 +415,6 @@ cfg80211_can_add_interface(struct cfg80211_registered_device *rdev, return cfg80211_can_change_interface(rdev, NULL, iftype); } -static inline int -cfg80211_can_use_chan(struct cfg80211_registered_device *rdev, - struct wireless_dev *wdev, - struct ieee80211_channel *chan, - enum cfg80211_chan_mode chanmode) -{ - return cfg80211_can_use_iftype_chan(rdev, wdev, wdev->iftype, - chan, chanmode); -} - -void -cfg80211_get_chan_state(struct cfg80211_registered_device *rdev, - struct wireless_dev *wdev, - struct ieee80211_channel **chan, - enum cfg80211_chan_mode *chanmode); - struct ieee80211_channel * rdev_freq_to_chan(struct cfg80211_registered_device *rdev, int freq, enum nl80211_channel_type channel_type); @@ -481,11 +428,6 @@ int ieee80211_get_ratemask(struct ieee80211_supported_band *sband, int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev, u32 beacon_int); -void cfg80211_update_iface_num(struct cfg80211_registered_device *rdev, - enum nl80211_iftype iftype, int num); - -#define CFG80211_MAX_NUM_DIFFERENT_CHANNELS 10 - #ifdef CONFIG_CFG80211_DEVELOPER_WARNINGS #define CFG80211_DEV_WARN_ON(cond) WARN_ON(cond) #else diff --git a/trunk/net/wireless/ibss.c b/trunk/net/wireless/ibss.c index ca5672f6ee2f..89baa3328411 100644 --- a/trunk/net/wireless/ibss.c +++ b/trunk/net/wireless/ibss.c @@ -113,21 +113,10 @@ int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev, kfree(wdev->connect_keys); wdev->connect_keys = connkeys; - wdev->ibss_fixed = params->channel_fixed; #ifdef CONFIG_CFG80211_WEXT wdev->wext.ibss.channel = params->channel; #endif wdev->sme_state = CFG80211_SME_CONNECTING; - - err = cfg80211_can_use_chan(rdev, wdev, params->channel, - params->channel_fixed - ? CHAN_MODE_SHARED - : CHAN_MODE_EXCLUSIVE); - if (err) { - wdev->connect_keys = NULL; - return err; - } - err = rdev->ops->join_ibss(&rdev->wiphy, dev, params); if (err) { wdev->connect_keys = NULL; diff --git a/trunk/net/wireless/mesh.c b/trunk/net/wireless/mesh.c index c384e77ff77a..3b73b07486cf 100644 --- a/trunk/net/wireless/mesh.c +++ b/trunk/net/wireless/mesh.c @@ -155,16 +155,10 @@ int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev, setup->channel_type)) return -EINVAL; - err = cfg80211_can_use_chan(rdev, wdev, setup->channel, - CHAN_MODE_SHARED); - if (err) - return err; - err = rdev->ops->join_mesh(&rdev->wiphy, dev, conf, setup); if (!err) { memcpy(wdev->ssid, setup->mesh_id, setup->mesh_id_len); wdev->mesh_id_len = setup->mesh_id_len; - wdev->channel = setup->channel; } return err; @@ -178,11 +172,9 @@ int cfg80211_join_mesh(struct cfg80211_registered_device *rdev, struct wireless_dev *wdev = dev->ieee80211_ptr; int err; - mutex_lock(&rdev->devlist_mtx); wdev_lock(wdev); err = __cfg80211_join_mesh(rdev, dev, setup, conf); wdev_unlock(wdev); - mutex_unlock(&rdev->devlist_mtx); return err; } @@ -192,7 +184,6 @@ int cfg80211_set_mesh_freq(struct cfg80211_registered_device *rdev, enum nl80211_channel_type channel_type) { struct ieee80211_channel *channel; - int err; channel = rdev_freq_to_chan(rdev, freq, channel_type); if (!channel || !cfg80211_can_beacon_sec_chan(&rdev->wiphy, @@ -214,19 +205,9 @@ int cfg80211_set_mesh_freq(struct cfg80211_registered_device *rdev, if (!netif_running(wdev->netdev)) return -ENETDOWN; - - err = cfg80211_can_use_chan(rdev, wdev, channel, - CHAN_MODE_SHARED); - if (err) - return err; - - err = rdev->ops->libertas_set_mesh_channel(&rdev->wiphy, - wdev->netdev, - channel); - if (!err) - wdev->channel = channel; - - return err; + return rdev->ops->libertas_set_mesh_channel(&rdev->wiphy, + wdev->netdev, + channel); } if (wdev->mesh_id_len) @@ -268,11 +249,8 @@ static int __cfg80211_leave_mesh(struct cfg80211_registered_device *rdev, return -ENOTCONN; err = rdev->ops->leave_mesh(&rdev->wiphy, dev); - if (!err) { + if (!err) wdev->mesh_id_len = 0; - wdev->channel = NULL; - } - return err; } diff --git a/trunk/net/wireless/mlme.c b/trunk/net/wireless/mlme.c index d4fece3bb18a..da4406f11929 100644 --- a/trunk/net/wireless/mlme.c +++ b/trunk/net/wireless/mlme.c @@ -302,14 +302,8 @@ int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, if (!req.bss) return -ENOENT; - err = cfg80211_can_use_chan(rdev, wdev, req.bss->channel, - CHAN_MODE_SHARED); - if (err) - goto out; - err = rdev->ops->auth(&rdev->wiphy, dev, &req); -out: cfg80211_put_bss(req.bss); return err; } @@ -323,13 +317,11 @@ int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, { int err; - mutex_lock(&rdev->devlist_mtx); wdev_lock(dev->ieee80211_ptr); err = __cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid, ssid, ssid_len, ie, ie_len, key, key_len, key_idx); wdev_unlock(dev->ieee80211_ptr); - mutex_unlock(&rdev->devlist_mtx); return err; } @@ -405,14 +397,8 @@ int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, return -ENOENT; } - err = cfg80211_can_use_chan(rdev, wdev, req.bss->channel, - CHAN_MODE_SHARED); - if (err) - goto out; - err = rdev->ops->assoc(&rdev->wiphy, dev, &req); -out: if (err) { if (was_connected) wdev->sme_state = CFG80211_SME_CONNECTED; @@ -435,13 +421,11 @@ int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, struct wireless_dev *wdev = dev->ieee80211_ptr; int err; - mutex_lock(&rdev->devlist_mtx); wdev_lock(wdev); err = __cfg80211_mlme_assoc(rdev, dev, chan, bssid, prev_bssid, ssid, ssid_len, ie, ie_len, use_mfp, crypt, assoc_flags, ht_capa, ht_capa_mask); wdev_unlock(wdev); - mutex_unlock(&rdev->devlist_mtx); return err; } @@ -963,7 +947,6 @@ void cfg80211_ch_switch_notify(struct net_device *dev, int freq, if (WARN_ON(!chan)) goto out; - wdev->channel = chan; nl80211_ch_switch_notify(rdev, dev, freq, type, GFP_KERNEL); out: wdev_unlock(wdev); diff --git a/trunk/net/wireless/nl80211.c b/trunk/net/wireless/nl80211.c index 0249cea53852..3b508eaf2d07 100644 --- a/trunk/net/wireless/nl80211.c +++ b/trunk/net/wireless/nl80211.c @@ -921,15 +921,6 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, dev->wiphy.bands[band]->ht_cap.ampdu_density))) goto nla_put_failure; - /* add VHT info */ - if (dev->wiphy.bands[band]->vht_cap.vht_supported && - (nla_put(msg, NL80211_BAND_ATTR_VHT_MCS_SET, - sizeof(dev->wiphy.bands[band]->vht_cap.vht_mcs), - &dev->wiphy.bands[band]->vht_cap.vht_mcs) || - nla_put_u32(msg, NL80211_BAND_ATTR_VHT_CAPA, - dev->wiphy.bands[band]->vht_cap.cap))) - goto nla_put_failure; - /* add frequencies */ nl_freqs = nla_nest_start(msg, NL80211_BAND_ATTR_FREQS); if (!nl_freqs) @@ -1121,7 +1112,6 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, nla_nest_end(msg, nl_ifs); } -#ifdef CONFIG_PM if (dev->wiphy.wowlan.flags || dev->wiphy.wowlan.n_patterns) { struct nlattr *nl_wowlan; @@ -1162,7 +1152,6 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, nla_nest_end(msg, nl_wowlan); } -#endif if (nl80211_put_iftypes(msg, NL80211_ATTR_SOFTWARE_IFTYPES, dev->wiphy.software_iftypes)) @@ -1689,11 +1678,16 @@ static int nl80211_send_iface(struct sk_buff *msg, u32 pid, u32 seq, int flags, (cfg80211_rdev_list_generation << 2))) goto nla_put_failure; - if (rdev->monitor_channel) { - if (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, - rdev->monitor_channel->center_freq) || - nla_put_u32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE, - rdev->monitor_channel_type)) + if (rdev->ops->get_channel) { + struct ieee80211_channel *chan; + enum nl80211_channel_type channel_type; + + chan = rdev->ops->get_channel(&rdev->wiphy, &channel_type); + if (chan && + (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, + chan->center_freq) || + nla_put_u32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE, + channel_type))) goto nla_put_failure; } @@ -2478,20 +2472,11 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info) params.channel_type)) return -EINVAL; - mutex_lock(&rdev->devlist_mtx); - err = cfg80211_can_use_chan(rdev, wdev, params.channel, - CHAN_MODE_SHARED); - mutex_unlock(&rdev->devlist_mtx); - - if (err) - return err; - err = rdev->ops->start_ap(&rdev->wiphy, dev, ¶ms); if (!err) { wdev->preset_chan = params.channel; wdev->preset_chantype = params.channel_type; wdev->beacon_interval = params.beacon_interval; - wdev->channel = params.channel; } return err; } @@ -2525,8 +2510,23 @@ static int nl80211_stop_ap(struct sk_buff *skb, struct genl_info *info) { struct cfg80211_registered_device *rdev = info->user_ptr[0]; struct net_device *dev = info->user_ptr[1]; + struct wireless_dev *wdev = dev->ieee80211_ptr; + int err; - return cfg80211_stop_ap(rdev, dev); + if (!rdev->ops->stop_ap) + return -EOPNOTSUPP; + + if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && + dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) + return -EOPNOTSUPP; + + if (!wdev->beacon_interval) + return -ENOENT; + + err = rdev->ops->stop_ap(&rdev->wiphy, dev); + if (!err) + wdev->beacon_interval = 0; + return err; } static const struct nla_policy sta_flags_policy[NL80211_STA_FLAG_MAX + 1] = { @@ -2618,8 +2618,7 @@ static bool nl80211_put_sta_rate(struct sk_buff *msg, struct rate_info *info, int attr) { struct nlattr *rate; - u32 bitrate; - u16 bitrate_compat; + u16 bitrate; rate = nla_nest_start(msg, attr); if (!rate) @@ -2627,12 +2626,8 @@ static bool nl80211_put_sta_rate(struct sk_buff *msg, struct rate_info *info, /* cfg80211_calculate_bitrate will return 0 for mcs >= 32 */ bitrate = cfg80211_calculate_bitrate(info); - /* report 16-bit bitrate only if we can */ - bitrate_compat = bitrate < (1UL << 16) ? bitrate : 0; if ((bitrate > 0 && - nla_put_u32(msg, NL80211_RATE_INFO_BITRATE32, bitrate)) || - (bitrate_compat > 0 && - nla_put_u16(msg, NL80211_RATE_INFO_BITRATE, bitrate_compat)) || + nla_put_u16(msg, NL80211_RATE_INFO_BITRATE, bitrate)) || ((info->flags & RATE_INFO_FLAGS_MCS) && nla_put_u8(msg, NL80211_RATE_INFO_MCS, info->mcs)) || ((info->flags & RATE_INFO_FLAGS_40_MHZ_WIDTH) && @@ -6281,7 +6276,6 @@ static int nl80211_leave_mesh(struct sk_buff *skb, struct genl_info *info) return cfg80211_leave_mesh(rdev, dev); } -#ifdef CONFIG_PM static int nl80211_get_wowlan(struct sk_buff *skb, struct genl_info *info) { struct cfg80211_registered_device *rdev = info->user_ptr[0]; @@ -6510,7 +6504,6 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info) kfree(new_triggers.patterns); return err; } -#endif static int nl80211_set_rekey_data(struct sk_buff *skb, struct genl_info *info) { @@ -7165,7 +7158,6 @@ static struct genl_ops nl80211_ops[] = { .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | NL80211_FLAG_NEED_RTNL, }, -#ifdef CONFIG_PM { .cmd = NL80211_CMD_GET_WOWLAN, .doit = nl80211_get_wowlan, @@ -7182,7 +7174,6 @@ static struct genl_ops nl80211_ops[] = { .internal_flags = NL80211_FLAG_NEED_WIPHY | NL80211_FLAG_NEED_RTNL, }, -#endif { .cmd = NL80211_CMD_SET_REKEY_OFFLOAD, .doit = nl80211_set_rekey_data, diff --git a/trunk/net/wireless/reg.c b/trunk/net/wireless/reg.c index b2b32229b607..baf5704740ee 100644 --- a/trunk/net/wireless/reg.c +++ b/trunk/net/wireless/reg.c @@ -129,7 +129,7 @@ static DECLARE_DELAYED_WORK(reg_timeout, reg_timeout_work); /* We keep a static world regulatory domain in case of the absence of CRDA */ static const struct ieee80211_regdomain world_regdom = { - .n_reg_rules = 6, + .n_reg_rules = 5, .alpha2 = "00", .reg_rules = { /* IEEE 802.11b/g, channels 1..11 */ @@ -156,9 +156,6 @@ static const struct ieee80211_regdomain world_regdom = { REG_RULE(5745-10, 5825+10, 40, 6, 20, NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS), - - /* IEEE 802.11ad (60gHz), channels 1..3 */ - REG_RULE(56160+2160*1-1080, 56160+2160*3+1080, 2160, 0, 0, 0), } }; diff --git a/trunk/net/wireless/util.c b/trunk/net/wireless/util.c index e31f1dba79ec..316cfd00914f 100644 --- a/trunk/net/wireless/util.c +++ b/trunk/net/wireless/util.c @@ -35,29 +35,19 @@ int ieee80211_channel_to_frequency(int chan, enum ieee80211_band band) { /* see 802.11 17.3.8.3.2 and Annex J * there are overlapping channel numbers in 5GHz and 2GHz bands */ - if (chan <= 0) - return 0; /* not supported */ - switch (band) { - case IEEE80211_BAND_2GHZ: + if (band == IEEE80211_BAND_5GHZ) { + if (chan >= 182 && chan <= 196) + return 4000 + chan * 5; + else + return 5000 + chan * 5; + } else { /* IEEE80211_BAND_2GHZ */ if (chan == 14) return 2484; else if (chan < 14) return 2407 + chan * 5; - break; - case IEEE80211_BAND_5GHZ: - if (chan >= 182 && chan <= 196) - return 4000 + chan * 5; else - return 5000 + chan * 5; - break; - case IEEE80211_BAND_60GHZ: - if (chan < 5) - return 56160 + chan * 2160; - break; - default: - ; + return 0; /* not supported */ } - return 0; /* not supported */ } EXPORT_SYMBOL(ieee80211_channel_to_frequency); @@ -70,12 +60,8 @@ int ieee80211_frequency_to_channel(int freq) return (freq - 2407) / 5; else if (freq >= 4910 && freq <= 4980) return (freq - 4000) / 5; - else if (freq <= 45000) /* DMG band lower limit */ - return (freq - 5000) / 5; - else if (freq >= 58320 && freq <= 64800) - return (freq - 56160) / 2160; else - return 0; + return (freq - 5000) / 5; } EXPORT_SYMBOL(ieee80211_frequency_to_channel); @@ -151,11 +137,6 @@ static void set_mandatory_flags_band(struct ieee80211_supported_band *sband, } WARN_ON(want != 0 && want != 3 && want != 6); break; - case IEEE80211_BAND_60GHZ: - /* check for mandatory HT MCS 1..4 */ - WARN_ON(!sband->ht_cap.ht_supported); - WARN_ON((sband->ht_cap.mcs.rx_mask[0] & 0x1e) != 0x1e); - break; case IEEE80211_NUM_BANDS: WARN_ON(1); break; @@ -824,10 +805,8 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev, return -EBUSY; if (ntype != otype && netif_running(dev)) { - mutex_lock(&rdev->devlist_mtx); err = cfg80211_can_change_interface(rdev, dev->ieee80211_ptr, ntype); - mutex_unlock(&rdev->devlist_mtx); if (err) return err; @@ -835,9 +814,6 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev, dev->ieee80211_ptr->mesh_id_up_len = 0; switch (otype) { - case NL80211_IFTYPE_AP: - cfg80211_stop_ap(rdev, dev); - break; case NL80211_IFTYPE_ADHOC: cfg80211_leave_ibss(rdev, dev, false); break; @@ -892,69 +868,15 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev, } } - if (!err && ntype != otype && netif_running(dev)) { - cfg80211_update_iface_num(rdev, ntype, 1); - cfg80211_update_iface_num(rdev, otype, -1); - } - return err; } -static u32 cfg80211_calculate_bitrate_60g(struct rate_info *rate) -{ - static const u32 __mcs2bitrate[] = { - /* control PHY */ - [0] = 275, - /* SC PHY */ - [1] = 3850, - [2] = 7700, - [3] = 9625, - [4] = 11550, - [5] = 12512, /* 1251.25 mbps */ - [6] = 15400, - [7] = 19250, - [8] = 23100, - [9] = 25025, - [10] = 30800, - [11] = 38500, - [12] = 46200, - /* OFDM PHY */ - [13] = 6930, - [14] = 8662, /* 866.25 mbps */ - [15] = 13860, - [16] = 17325, - [17] = 20790, - [18] = 27720, - [19] = 34650, - [20] = 41580, - [21] = 45045, - [22] = 51975, - [23] = 62370, - [24] = 67568, /* 6756.75 mbps */ - /* LP-SC PHY */ - [25] = 6260, - [26] = 8340, - [27] = 11120, - [28] = 12510, - [29] = 16680, - [30] = 22240, - [31] = 25030, - }; - - if (WARN_ON_ONCE(rate->mcs >= ARRAY_SIZE(__mcs2bitrate))) - return 0; - - return __mcs2bitrate[rate->mcs]; -} - -u32 cfg80211_calculate_bitrate(struct rate_info *rate) +u16 cfg80211_calculate_bitrate(struct rate_info *rate) { int modulation, streams, bitrate; if (!(rate->flags & RATE_INFO_FLAGS_MCS)) return rate->legacy; - if (rate->flags & RATE_INFO_FLAGS_60G) - return cfg80211_calculate_bitrate_60g(rate); /* the formula below does only work for MCS values smaller than 32 */ if (WARN_ON_ONCE(rate->mcs >= 32)) @@ -1008,48 +930,27 @@ int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev, return res; } -int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev, - struct wireless_dev *wdev, - enum nl80211_iftype iftype, - struct ieee80211_channel *chan, - enum cfg80211_chan_mode chanmode) +int cfg80211_can_change_interface(struct cfg80211_registered_device *rdev, + struct wireless_dev *wdev, + enum nl80211_iftype iftype) { struct wireless_dev *wdev_iter; u32 used_iftypes = BIT(iftype); int num[NUM_NL80211_IFTYPES]; - struct ieee80211_channel - *used_channels[CFG80211_MAX_NUM_DIFFERENT_CHANNELS]; - struct ieee80211_channel *ch; - enum cfg80211_chan_mode chmode; - int num_different_channels = 0; int total = 1; int i, j; ASSERT_RTNL(); - lockdep_assert_held(&rdev->devlist_mtx); /* Always allow software iftypes */ if (rdev->wiphy.software_iftypes & BIT(iftype)) return 0; memset(num, 0, sizeof(num)); - memset(used_channels, 0, sizeof(used_channels)); num[iftype] = 1; - switch (chanmode) { - case CHAN_MODE_UNDEFINED: - break; - case CHAN_MODE_SHARED: - WARN_ON(!chan); - used_channels[0] = chan; - num_different_channels++; - break; - case CHAN_MODE_EXCLUSIVE: - num_different_channels++; - break; - } - + mutex_lock(&rdev->devlist_mtx); list_for_each_entry(wdev_iter, &rdev->netdev_list, list) { if (wdev_iter == wdev) continue; @@ -1059,33 +960,11 @@ int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev, if (rdev->wiphy.software_iftypes & BIT(wdev_iter->iftype)) continue; - cfg80211_get_chan_state(rdev, wdev_iter, &ch, &chmode); - - switch (chmode) { - case CHAN_MODE_UNDEFINED: - break; - case CHAN_MODE_SHARED: - for (i = 0; i < CFG80211_MAX_NUM_DIFFERENT_CHANNELS; i++) - if (!used_channels[i] || used_channels[i] == ch) - break; - - if (i == CFG80211_MAX_NUM_DIFFERENT_CHANNELS) - return -EBUSY; - - if (used_channels[i] == NULL) { - used_channels[i] = ch; - num_different_channels++; - } - break; - case CHAN_MODE_EXCLUSIVE: - num_different_channels++; - break; - } - num[wdev_iter->iftype]++; total++; used_iftypes |= BIT(wdev_iter->iftype); } + mutex_unlock(&rdev->devlist_mtx); if (total == 1) return 0; @@ -1097,15 +976,12 @@ int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev, c = &rdev->wiphy.iface_combinations[i]; - if (total > c->max_interfaces) - continue; - if (num_different_channels > c->num_different_channels) - continue; - limits = kmemdup(c->limits, sizeof(limits[0]) * c->n_limits, GFP_KERNEL); if (!limits) return -ENOMEM; + if (total > c->max_interfaces) + goto cont; for (iftype = 0; iftype < NUM_NL80211_IFTYPES; iftype++) { if (rdev->wiphy.software_iftypes & BIT(iftype)) diff --git a/trunk/net/wireless/wext-compat.c b/trunk/net/wireless/wext-compat.c index 7df42f541873..bc879833b21f 100644 --- a/trunk/net/wireless/wext-compat.c +++ b/trunk/net/wireless/wext-compat.c @@ -827,6 +827,8 @@ static int cfg80211_wext_giwfreq(struct net_device *dev, { struct wireless_dev *wdev = dev->ieee80211_ptr; struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); + struct ieee80211_channel *chan; + enum nl80211_channel_type channel_type; switch (wdev->iftype) { case NL80211_IFTYPE_STATION: @@ -834,10 +836,13 @@ static int cfg80211_wext_giwfreq(struct net_device *dev, case NL80211_IFTYPE_ADHOC: return cfg80211_ibss_wext_giwfreq(dev, info, freq, extra); case NL80211_IFTYPE_MONITOR: - if (!rdev->monitor_channel) + if (!rdev->ops->get_channel) return -EINVAL; - freq->m = rdev->monitor_channel->center_freq; + chan = rdev->ops->get_channel(wdev->wiphy, &channel_type); + if (!chan) + return -EINVAL; + freq->m = chan->center_freq; freq->e = 6; return 0; default: diff --git a/trunk/net/x25/x25_route.c b/trunk/net/x25/x25_route.c index 277c8d2448d6..cf6366270054 100644 --- a/trunk/net/x25/x25_route.c +++ b/trunk/net/x25/x25_route.c @@ -66,7 +66,7 @@ static int x25_add_route(struct x25_address *address, unsigned int sigdigits, /** * __x25_remove_route - remove route from x25_route_list - * @rt: route to remove + * @rt - route to remove * * Remove route from x25_route_list. If it was there. * Caller must hold x25_route_list_lock. diff --git a/trunk/net/xfrm/xfrm_policy.c b/trunk/net/xfrm/xfrm_policy.c index 65bd1ca51517..6e97855b5842 100644 --- a/trunk/net/xfrm/xfrm_policy.c +++ b/trunk/net/xfrm/xfrm_policy.c @@ -1353,9 +1353,8 @@ static inline struct xfrm_dst *xfrm_alloc_dst(struct net *net, int family) xdst = dst_alloc(dst_ops, NULL, 0, 0, 0); if (likely(xdst)) { - struct dst_entry *dst = &xdst->u.dst; - - memset(dst + 1, 0, sizeof(*xdst) - sizeof(*dst)); + memset(&xdst->u.rt6.rt6i_table, 0, + sizeof(*xdst) - sizeof(struct dst_entry)); xdst->flo.ops = &xfrm_bundle_fc_ops; } else xdst = ERR_PTR(-ENOBUFS);