Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt
index d3d653a..e3df119 100644
--- a/Documentation/networking/ip-sysctl.txt
+++ b/Documentation/networking/ip-sysctl.txt
@@ -106,16 +106,6 @@
when the number of entries in the pool is very small).
Measured in seconds.
-inet_peer_gc_mintime - INTEGER
- Minimum interval between garbage collection passes. This interval is
- in effect under high memory pressure on the pool.
- Measured in seconds.
-
-inet_peer_gc_maxtime - INTEGER
- Minimum interval between garbage collection passes. This interval is
- in effect under low (or absent) memory pressure on the pool.
- Measured in seconds.
-
TCP variables:
somaxconn - INTEGER
@@ -394,7 +384,7 @@
min: Minimal size of receive buffer used by TCP sockets.
It is guaranteed to each TCP socket, even under moderate memory
pressure.
- Default: 8K
+ Default: 1 page
default: initial size of receive buffer used by TCP sockets.
This value overrides net.core.rmem_default used by other protocols.
@@ -483,7 +473,7 @@
tcp_wmem - vector of 3 INTEGERs: min, default, max
min: Amount of memory reserved for send buffers for TCP sockets.
Each TCP socket has rights to use it due to fact of its birth.
- Default: 4K
+ Default: 1 page
default: initial size of send buffer used by TCP sockets. This
value overrides net.core.wmem_default used by other protocols.
@@ -553,13 +543,13 @@
Minimal size of receive buffer used by UDP sockets in moderation.
Each UDP socket is able to use the size for receiving data, even if
total pages of UDP sockets exceed udp_mem pressure. The unit is byte.
- Default: 4096
+ Default: 1 page
udp_wmem_min - INTEGER
Minimal size of send buffer used by UDP sockets in moderation.
Each UDP socket is able to use the size for sending data, even if
total pages of UDP sockets exceed udp_mem pressure. The unit is byte.
- Default: 4096
+ Default: 1 page
CIPSOv4 Variables:
@@ -1465,10 +1455,17 @@
Default is calculated at boot time from amount of available memory.
sctp_rmem - vector of 3 INTEGERs: min, default, max
- See tcp_rmem for a description.
+ Only the first value ("min") is used, "default" and "max" are
+ ignored.
+
+ min: Minimal size of receive buffer used by SCTP socket.
+ It is guaranteed to each SCTP socket (but not association) even
+ under moderate memory pressure.
+
+ Default: 1 page
sctp_wmem - vector of 3 INTEGERs: min, default, max
- See tcp_wmem for a description.
+ Currently this tunable has no effect.
addr_scope_policy - INTEGER
Control IPv4 address scoping - draft-stewart-tsvwg-sctp-ipv4-00
diff --git a/MAINTAINERS b/MAINTAINERS
index ae563fa..573cfa3 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -4279,8 +4279,8 @@
F: drivers/usb/musb/
MYRICOM MYRI-10G 10GbE DRIVER (MYRI10GE)
+M: Jon Mason <mason@myri.com>
M: Andrew Gallatin <gallatin@myri.com>
-M: Brice Goglin <brice@myri.com>
L: netdev@vger.kernel.org
W: http://www.myri.com/scs/download-Myri10GE.html
S: Supported
diff --git a/arch/arm/mach-davinci/board-mityomapl138.c b/arch/arm/mach-davinci/board-mityomapl138.c
index 606a6f2..5f5d783 100644
--- a/arch/arm/mach-davinci/board-mityomapl138.c
+++ b/arch/arm/mach-davinci/board-mityomapl138.c
@@ -20,6 +20,7 @@
#include <linux/spi/spi.h>
#include <linux/spi/flash.h>
+#include <asm/io.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <mach/common.h>
diff --git a/arch/arm/mach-davinci/dm646x.c b/arch/arm/mach-davinci/dm646x.c
index 1e0f809..e00d61e 100644
--- a/arch/arm/mach-davinci/dm646x.c
+++ b/arch/arm/mach-davinci/dm646x.c
@@ -8,6 +8,7 @@
* is licensed "as is" without any warranty of any kind, whether express
* or implied.
*/
+#include <linux/dma-mapping.h>
#include <linux/init.h>
#include <linux/clk.h>
#include <linux/serial_8250.h>
diff --git a/arch/arm/mach-davinci/pm.c b/arch/arm/mach-davinci/pm.c
index 1bd73a04..04c49f7 100644
--- a/arch/arm/mach-davinci/pm.c
+++ b/arch/arm/mach-davinci/pm.c
@@ -17,6 +17,7 @@
#include <asm/cacheflush.h>
#include <asm/delay.h>
+#include <asm/io.h>
#include <mach/da8xx.h>
#include <mach/sram.h>
diff --git a/arch/arm/mach-imx/dma-v1.c b/arch/arm/mach-imx/dma-v1.c
index 236f149..f8aa5be 100644
--- a/arch/arm/mach-imx/dma-v1.c
+++ b/arch/arm/mach-imx/dma-v1.c
@@ -26,6 +26,7 @@
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/interrupt.h>
+#include <linux/err.h>
#include <linux/errno.h>
#include <linux/clk.h>
#include <linux/scatterlist.h>
diff --git a/arch/arm/mach-imx/mach-mx31_3ds.c b/arch/arm/mach-imx/mach-mx31_3ds.c
index 9b98244..b5ecc26 100644
--- a/arch/arm/mach-imx/mach-mx31_3ds.c
+++ b/arch/arm/mach-imx/mach-mx31_3ds.c
@@ -13,6 +13,7 @@
*/
#include <linux/delay.h>
+#include <linux/dma-mapping.h>
#include <linux/types.h>
#include <linux/init.h>
#include <linux/clk.h>
diff --git a/arch/arm/mach-iop13xx/setup.c b/arch/arm/mach-iop13xx/setup.c
index 5c147fb..a5b9897 100644
--- a/arch/arm/mach-iop13xx/setup.c
+++ b/arch/arm/mach-iop13xx/setup.c
@@ -17,6 +17,7 @@
*
*/
+#include <linux/dma-mapping.h>
#include <linux/serial_8250.h>
#include <linux/io.h>
#ifdef CONFIG_MTD_PHYSMAP
diff --git a/arch/arm/mach-mxs/devices/platform-auart.c b/arch/arm/mach-mxs/devices/platform-auart.c
index 796606c..27608f5 100644
--- a/arch/arm/mach-mxs/devices/platform-auart.c
+++ b/arch/arm/mach-mxs/devices/platform-auart.c
@@ -6,6 +6,7 @@
* the terms of the GNU General Public License version 2 as published by the
* Free Software Foundation.
*/
+#include <linux/dma-mapping.h>
#include <asm/sizes.h>
#include <mach/mx23.h>
#include <mach/mx28.h>
diff --git a/arch/arm/mach-mxs/devices/platform-dma.c b/arch/arm/mach-mxs/devices/platform-dma.c
index 295c442..6a0202b1 100644
--- a/arch/arm/mach-mxs/devices/platform-dma.c
+++ b/arch/arm/mach-mxs/devices/platform-dma.c
@@ -6,6 +6,7 @@
* Free Software Foundation.
*/
#include <linux/compiler.h>
+#include <linux/dma-mapping.h>
#include <linux/err.h>
#include <linux/init.h>
diff --git a/arch/arm/mach-mxs/devices/platform-fec.c b/arch/arm/mach-mxs/devices/platform-fec.c
index 9859cf28..ae96a4f 100644
--- a/arch/arm/mach-mxs/devices/platform-fec.c
+++ b/arch/arm/mach-mxs/devices/platform-fec.c
@@ -6,6 +6,7 @@
* the terms of the GNU General Public License version 2 as published by the
* Free Software Foundation.
*/
+#include <linux/dma-mapping.h>
#include <asm/sizes.h>
#include <mach/mx28.h>
#include <mach/devices-common.h>
diff --git a/arch/arm/plat-mxc/devices/platform-fec.c b/arch/arm/plat-mxc/devices/platform-fec.c
index ccc789e..4fc6ffc 100644
--- a/arch/arm/plat-mxc/devices/platform-fec.c
+++ b/arch/arm/plat-mxc/devices/platform-fec.c
@@ -6,6 +6,7 @@
* the terms of the GNU General Public License version 2 as published by the
* Free Software Foundation.
*/
+#include <linux/dma-mapping.h>
#include <asm/sizes.h>
#include <mach/hardware.h>
#include <mach/devices-common.h>
diff --git a/arch/arm/plat-mxc/devices/platform-fsl-usb2-udc.c b/arch/arm/plat-mxc/devices/platform-fsl-usb2-udc.c
index 59c33f6..23ce08e 100644
--- a/arch/arm/plat-mxc/devices/platform-fsl-usb2-udc.c
+++ b/arch/arm/plat-mxc/devices/platform-fsl-usb2-udc.c
@@ -6,6 +6,7 @@
* the terms of the GNU General Public License version 2 as published by the
* Free Software Foundation.
*/
+#include <linux/dma-mapping.h>
#include <mach/hardware.h>
#include <mach/devices-common.h>
diff --git a/arch/arm/plat-mxc/devices/platform-imx-fb.c b/arch/arm/plat-mxc/devices/platform-imx-fb.c
index 79a1cb1..2b0b5e0 100644
--- a/arch/arm/plat-mxc/devices/platform-imx-fb.c
+++ b/arch/arm/plat-mxc/devices/platform-imx-fb.c
@@ -6,6 +6,7 @@
* the terms of the GNU General Public License version 2 as published by the
* Free Software Foundation.
*/
+#include <linux/dma-mapping.h>
#include <mach/hardware.h>
#include <mach/devices-common.h>
diff --git a/arch/arm/plat-mxc/devices/platform-ipu-core.c b/arch/arm/plat-mxc/devices/platform-ipu-core.c
index edf6503..79d340a 100644
--- a/arch/arm/plat-mxc/devices/platform-ipu-core.c
+++ b/arch/arm/plat-mxc/devices/platform-ipu-core.c
@@ -6,6 +6,7 @@
* the terms of the GNU General Public License version 2 as published by the
* Free Software Foundation.
*/
+#include <linux/dma-mapping.h>
#include <mach/hardware.h>
#include <mach/devices-common.h>
diff --git a/arch/arm/plat-mxc/devices/platform-mxc-ehci.c b/arch/arm/plat-mxc/devices/platform-mxc-ehci.c
index cc488f4..e1763e0 100644
--- a/arch/arm/plat-mxc/devices/platform-mxc-ehci.c
+++ b/arch/arm/plat-mxc/devices/platform-mxc-ehci.c
@@ -6,6 +6,7 @@
* the terms of the GNU General Public License version 2 as published by the
* Free Software Foundation.
*/
+#include <linux/dma-mapping.h>
#include <mach/hardware.h>
#include <mach/devices-common.h>
diff --git a/arch/arm/plat-mxc/devices/platform-mxc-mmc.c b/arch/arm/plat-mxc/devices/platform-mxc-mmc.c
index 90d762f..540d3a7 100644
--- a/arch/arm/plat-mxc/devices/platform-mxc-mmc.c
+++ b/arch/arm/plat-mxc/devices/platform-mxc-mmc.c
@@ -6,6 +6,7 @@
* the terms of the GNU General Public License version 2 as published by the
* Free Software Foundation.
*/
+#include <linux/dma-mapping.h>
#include <mach/hardware.h>
#include <mach/devices-common.h>
diff --git a/arch/arm/plat-nomadik/include/plat/ste_dma40.h b/arch/arm/plat-nomadik/include/plat/ste_dma40.h
index c448860..685c787 100644
--- a/arch/arm/plat-nomadik/include/plat/ste_dma40.h
+++ b/arch/arm/plat-nomadik/include/plat/ste_dma40.h
@@ -10,6 +10,7 @@
#define STE_DMA40_H
#include <linux/dmaengine.h>
+#include <linux/scatterlist.h>
#include <linux/workqueue.h>
#include <linux/interrupt.h>
diff --git a/arch/m68k/emu/nfeth.c b/arch/m68k/emu/nfeth.c
index 8b6e201..3c55312 100644
--- a/arch/m68k/emu/nfeth.c
+++ b/arch/m68k/emu/nfeth.c
@@ -16,6 +16,7 @@
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
+#include <linux/interrupt.h>
#include <linux/module.h>
#include <asm/natfeat.h>
#include <asm/virtconvert.h>
diff --git a/arch/x86/kernel/tboot.c b/arch/x86/kernel/tboot.c
index 30ac65d..e07a2fc 100644
--- a/arch/x86/kernel/tboot.c
+++ b/arch/x86/kernel/tboot.c
@@ -36,6 +36,7 @@
#include <asm/bootparam.h>
#include <asm/pgtable.h>
#include <asm/pgalloc.h>
+#include <asm/swiotlb.h>
#include <asm/fixmap.h>
#include <asm/proto.h>
#include <asm/setup.h>
diff --git a/crypto/async_tx/raid6test.c b/crypto/async_tx/raid6test.c
index c132193..c88ff9e 100644
--- a/crypto/async_tx/raid6test.c
+++ b/crypto/async_tx/raid6test.c
@@ -21,6 +21,7 @@
*/
#include <linux/async_tx.h>
#include <linux/gfp.h>
+#include <linux/mm.h>
#include <linux/random.h>
#undef pr
diff --git a/drivers/atm/eni.h b/drivers/atm/eni.h
index e4c9525..493a693 100644
--- a/drivers/atm/eni.h
+++ b/drivers/atm/eni.h
@@ -8,6 +8,7 @@
#include <linux/atm.h>
#include <linux/atmdev.h>
+#include <linux/interrupt.h>
#include <linux/sonet.h>
#include <linux/skbuff.h>
#include <linux/time.h>
diff --git a/drivers/atm/firestream.c b/drivers/atm/firestream.c
index ef7a658..7c7b571 100644
--- a/drivers/atm/firestream.c
+++ b/drivers/atm/firestream.c
@@ -44,6 +44,7 @@
#include <linux/ioport.h> /* for request_region */
#include <linux/uio.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/capability.h>
#include <linux/bitops.h>
#include <linux/slab.h>
diff --git a/drivers/atm/horizon.c b/drivers/atm/horizon.c
index d58e3fc..2875061 100644
--- a/drivers/atm/horizon.c
+++ b/drivers/atm/horizon.c
@@ -38,6 +38,7 @@
#include <linux/delay.h>
#include <linux/uio.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/wait.h>
#include <linux/slab.h>
diff --git a/drivers/atm/idt77252.c b/drivers/atm/idt77252.c
index 1f8d724..be0dbfe 100644
--- a/drivers/atm/idt77252.c
+++ b/drivers/atm/idt77252.c
@@ -37,6 +37,7 @@
#include <linux/atm.h>
#include <linux/delay.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/bitops.h>
#include <linux/wait.h>
#include <linux/jiffies.h>
diff --git a/drivers/atm/iphase.c b/drivers/atm/iphase.c
index dee4f01..957106f 100644
--- a/drivers/atm/iphase.c
+++ b/drivers/atm/iphase.c
@@ -53,6 +53,7 @@
#include <linux/delay.h>
#include <linux/uio.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/wait.h>
#include <linux/slab.h>
#include <asm/system.h>
diff --git a/drivers/atm/zatm.c b/drivers/atm/zatm.c
index 6249179..7f8c513 100644
--- a/drivers/atm/zatm.c
+++ b/drivers/atm/zatm.c
@@ -16,6 +16,7 @@
#include <linux/delay.h>
#include <linux/uio.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/dma-mapping.h>
#include <linux/atm_zatm.h>
#include <linux/capability.h>
diff --git a/drivers/bcma/Kconfig b/drivers/bcma/Kconfig
index 353781b..83e9adf 100644
--- a/drivers/bcma/Kconfig
+++ b/drivers/bcma/Kconfig
@@ -13,6 +13,11 @@
Bus driver for Broadcom specific Advanced Microcontroller Bus
Architecture.
+# Support for Block-I/O. SELECT this from the driver that needs it.
+config BCMA_BLOCKIO
+ bool
+ depends on BCMA
+
config BCMA_HOST_PCI_POSSIBLE
bool
depends on BCMA && PCI = y
diff --git a/drivers/bcma/Makefile b/drivers/bcma/Makefile
index 0d56245..cde0182 100644
--- a/drivers/bcma/Makefile
+++ b/drivers/bcma/Makefile
@@ -1,4 +1,4 @@
-bcma-y += main.o scan.o core.o
+bcma-y += main.o scan.o core.o sprom.o
bcma-y += driver_chipcommon.o driver_chipcommon_pmu.o
bcma-y += driver_pci.o
bcma-$(CONFIG_BCMA_HOST_PCI) += host_pci.o
diff --git a/drivers/bcma/bcma_private.h b/drivers/bcma/bcma_private.h
index 2f72e9c..4228736 100644
--- a/drivers/bcma/bcma_private.h
+++ b/drivers/bcma/bcma_private.h
@@ -13,12 +13,15 @@
struct bcma_bus;
/* main.c */
-extern int bcma_bus_register(struct bcma_bus *bus);
-extern void bcma_bus_unregister(struct bcma_bus *bus);
+int bcma_bus_register(struct bcma_bus *bus);
+void bcma_bus_unregister(struct bcma_bus *bus);
/* scan.c */
int bcma_bus_scan(struct bcma_bus *bus);
+/* sprom.c */
+int bcma_sprom_get(struct bcma_bus *bus);
+
#ifdef CONFIG_BCMA_HOST_PCI
/* host_pci.c */
extern int __init bcma_host_pci_init(void);
diff --git a/drivers/bcma/core.c b/drivers/bcma/core.c
index ced379f..1ec7d45 100644
--- a/drivers/bcma/core.c
+++ b/drivers/bcma/core.c
@@ -19,7 +19,7 @@
}
EXPORT_SYMBOL_GPL(bcma_core_is_enabled);
-static void bcma_core_disable(struct bcma_device *core, u32 flags)
+void bcma_core_disable(struct bcma_device *core, u32 flags)
{
if (bcma_aread32(core, BCMA_RESET_CTL) & BCMA_RESET_CTL_RESET)
return;
@@ -31,6 +31,7 @@
bcma_awrite32(core, BCMA_RESET_CTL, BCMA_RESET_CTL_RESET);
udelay(1);
}
+EXPORT_SYMBOL_GPL(bcma_core_disable);
int bcma_core_enable(struct bcma_device *core, u32 flags)
{
diff --git a/drivers/bcma/driver_chipcommon_pmu.c b/drivers/bcma/driver_chipcommon_pmu.c
index f44177a..dd5846b 100644
--- a/drivers/bcma/driver_chipcommon_pmu.c
+++ b/drivers/bcma/driver_chipcommon_pmu.c
@@ -53,6 +53,7 @@
max_msk = 0xFFFF;
break;
case 43224:
+ case 43225:
break;
default:
pr_err("PMU resource config unknown for device 0x%04X\n",
@@ -74,6 +75,7 @@
case 0x4313:
case 0x4331:
case 43224:
+ case 43225:
break;
default:
pr_err("PMU switch/regulators init unknown for device "
@@ -96,11 +98,13 @@
if (bus->chipinfo.rev == 0) {
pr_err("Workarounds for 43224 rev 0 not fully "
"implemented\n");
- bcma_chipco_chipctl_maskset(cc, 0, ~0, 0xF0);
+ bcma_chipco_chipctl_maskset(cc, 0, ~0, 0x00F000F0);
} else {
bcma_chipco_chipctl_maskset(cc, 0, ~0, 0xF0);
}
break;
+ case 43225:
+ break;
default:
pr_err("Workarounds unknown for device 0x%04X\n",
bus->chipinfo.id);
diff --git a/drivers/bcma/driver_pci.c b/drivers/bcma/driver_pci.c
index e757e4e..b0c19ed 100644
--- a/drivers/bcma/driver_pci.c
+++ b/drivers/bcma/driver_pci.c
@@ -161,3 +161,27 @@
{
bcma_pcicore_serdes_workaround(pc);
}
+
+int bcma_core_pci_irq_ctl(struct bcma_drv_pci *pc, struct bcma_device *core,
+ bool enable)
+{
+ struct pci_dev *pdev = pc->core->bus->host_pci;
+ u32 coremask, tmp;
+ int err;
+
+ err = pci_read_config_dword(pdev, BCMA_PCI_IRQMASK, &tmp);
+ if (err)
+ goto out;
+
+ coremask = BIT(core->core_index) << 8;
+ if (enable)
+ tmp |= coremask;
+ else
+ tmp &= ~coremask;
+
+ err = pci_write_config_dword(pdev, BCMA_PCI_IRQMASK, tmp);
+
+out:
+ return err;
+}
+EXPORT_SYMBOL_GPL(bcma_core_pci_irq_ctl);
diff --git a/drivers/bcma/host_pci.c b/drivers/bcma/host_pci.c
index 471a040..ac4bc62 100644
--- a/drivers/bcma/host_pci.c
+++ b/drivers/bcma/host_pci.c
@@ -65,6 +65,54 @@
iowrite32(value, core->bus->mmio + offset);
}
+#ifdef CONFIG_BCMA_BLOCKIO
+void bcma_host_pci_block_read(struct bcma_device *core, void *buffer,
+ size_t count, u16 offset, u8 reg_width)
+{
+ void __iomem *addr = core->bus->mmio + offset;
+ if (core->bus->mapped_core != core)
+ bcma_host_pci_switch_core(core);
+ switch (reg_width) {
+ case sizeof(u8):
+ ioread8_rep(addr, buffer, count);
+ break;
+ case sizeof(u16):
+ WARN_ON(count & 1);
+ ioread16_rep(addr, buffer, count >> 1);
+ break;
+ case sizeof(u32):
+ WARN_ON(count & 3);
+ ioread32_rep(addr, buffer, count >> 2);
+ break;
+ default:
+ WARN_ON(1);
+ }
+}
+
+void bcma_host_pci_block_write(struct bcma_device *core, const void *buffer,
+ size_t count, u16 offset, u8 reg_width)
+{
+ void __iomem *addr = core->bus->mmio + offset;
+ if (core->bus->mapped_core != core)
+ bcma_host_pci_switch_core(core);
+ switch (reg_width) {
+ case sizeof(u8):
+ iowrite8_rep(addr, buffer, count);
+ break;
+ case sizeof(u16):
+ WARN_ON(count & 1);
+ iowrite16_rep(addr, buffer, count >> 1);
+ break;
+ case sizeof(u32):
+ WARN_ON(count & 3);
+ iowrite32_rep(addr, buffer, count >> 2);
+ break;
+ default:
+ WARN_ON(1);
+ }
+}
+#endif
+
static u32 bcma_host_pci_aread32(struct bcma_device *core, u16 offset)
{
if (core->bus->mapped_core != core)
@@ -87,6 +135,10 @@
.write8 = bcma_host_pci_write8,
.write16 = bcma_host_pci_write16,
.write32 = bcma_host_pci_write32,
+#ifdef CONFIG_BCMA_BLOCKIO
+ .block_read = bcma_host_pci_block_read,
+ .block_write = bcma_host_pci_block_write,
+#endif
.aread32 = bcma_host_pci_aread32,
.awrite32 = bcma_host_pci_awrite32,
};
@@ -175,6 +227,7 @@
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x0576) },
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4331) },
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4353) },
+ { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4357) },
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4727) },
{ 0, },
};
diff --git a/drivers/bcma/main.c b/drivers/bcma/main.c
index be52344..08a14a3 100644
--- a/drivers/bcma/main.c
+++ b/drivers/bcma/main.c
@@ -7,6 +7,7 @@
#include "bcma_private.h"
#include <linux/bcma/bcma.h>
+#include <linux/slab.h>
MODULE_DESCRIPTION("Broadcom's specific AMBA driver");
MODULE_LICENSE("GPL");
@@ -89,6 +90,8 @@
switch (bus->hosttype) {
case BCMA_HOSTTYPE_PCI:
core->dev.parent = &bus->host_pci->dev;
+ core->dma_dev = &bus->host_pci->dev;
+ core->irq = bus->host_pci->irq;
break;
case BCMA_HOSTTYPE_NONE:
case BCMA_HOSTTYPE_SDIO:
@@ -144,6 +147,13 @@
bcma_core_pci_init(&bus->drv_pci);
}
+ /* Try to get SPROM */
+ err = bcma_sprom_get(bus);
+ if (err) {
+ pr_err("Failed to get SPROM: %d\n", err);
+ return -ENOENT;
+ }
+
/* Register found cores */
bcma_register_cores(bus);
@@ -151,13 +161,11 @@
return 0;
}
-EXPORT_SYMBOL_GPL(bcma_bus_register);
void bcma_bus_unregister(struct bcma_bus *bus)
{
bcma_unregister_cores(bus);
}
-EXPORT_SYMBOL_GPL(bcma_bus_unregister);
int __bcma_driver_register(struct bcma_driver *drv, struct module *owner)
{
diff --git a/drivers/bcma/sprom.c b/drivers/bcma/sprom.c
new file mode 100644
index 0000000..ffbb0e3
--- /dev/null
+++ b/drivers/bcma/sprom.c
@@ -0,0 +1,162 @@
+/*
+ * Broadcom specific AMBA
+ * SPROM reading
+ *
+ * Licensed under the GNU/GPL. See COPYING for details.
+ */
+
+#include "bcma_private.h"
+
+#include <linux/bcma/bcma.h>
+#include <linux/bcma/bcma_regs.h>
+#include <linux/pci.h>
+#include <linux/io.h>
+#include <linux/dma-mapping.h>
+#include <linux/slab.h>
+
+#define SPOFF(offset) ((offset) / sizeof(u16))
+
+/**************************************************
+ * R/W ops.
+ **************************************************/
+
+static void bcma_sprom_read(struct bcma_bus *bus, u16 *sprom)
+{
+ int i;
+ for (i = 0; i < SSB_SPROMSIZE_WORDS_R4; i++)
+ sprom[i] = bcma_read16(bus->drv_cc.core,
+ BCMA_CC_SPROM + (i * 2));
+}
+
+/**************************************************
+ * Validation.
+ **************************************************/
+
+static inline u8 bcma_crc8(u8 crc, u8 data)
+{
+ /* Polynomial: x^8 + x^7 + x^6 + x^4 + x^2 + 1 */
+ static const u8 t[] = {
+ 0x00, 0xF7, 0xB9, 0x4E, 0x25, 0xD2, 0x9C, 0x6B,
+ 0x4A, 0xBD, 0xF3, 0x04, 0x6F, 0x98, 0xD6, 0x21,
+ 0x94, 0x63, 0x2D, 0xDA, 0xB1, 0x46, 0x08, 0xFF,
+ 0xDE, 0x29, 0x67, 0x90, 0xFB, 0x0C, 0x42, 0xB5,
+ 0x7F, 0x88, 0xC6, 0x31, 0x5A, 0xAD, 0xE3, 0x14,
+ 0x35, 0xC2, 0x8C, 0x7B, 0x10, 0xE7, 0xA9, 0x5E,
+ 0xEB, 0x1C, 0x52, 0xA5, 0xCE, 0x39, 0x77, 0x80,
+ 0xA1, 0x56, 0x18, 0xEF, 0x84, 0x73, 0x3D, 0xCA,
+ 0xFE, 0x09, 0x47, 0xB0, 0xDB, 0x2C, 0x62, 0x95,
+ 0xB4, 0x43, 0x0D, 0xFA, 0x91, 0x66, 0x28, 0xDF,
+ 0x6A, 0x9D, 0xD3, 0x24, 0x4F, 0xB8, 0xF6, 0x01,
+ 0x20, 0xD7, 0x99, 0x6E, 0x05, 0xF2, 0xBC, 0x4B,
+ 0x81, 0x76, 0x38, 0xCF, 0xA4, 0x53, 0x1D, 0xEA,
+ 0xCB, 0x3C, 0x72, 0x85, 0xEE, 0x19, 0x57, 0xA0,
+ 0x15, 0xE2, 0xAC, 0x5B, 0x30, 0xC7, 0x89, 0x7E,
+ 0x5F, 0xA8, 0xE6, 0x11, 0x7A, 0x8D, 0xC3, 0x34,
+ 0xAB, 0x5C, 0x12, 0xE5, 0x8E, 0x79, 0x37, 0xC0,
+ 0xE1, 0x16, 0x58, 0xAF, 0xC4, 0x33, 0x7D, 0x8A,
+ 0x3F, 0xC8, 0x86, 0x71, 0x1A, 0xED, 0xA3, 0x54,
+ 0x75, 0x82, 0xCC, 0x3B, 0x50, 0xA7, 0xE9, 0x1E,
+ 0xD4, 0x23, 0x6D, 0x9A, 0xF1, 0x06, 0x48, 0xBF,
+ 0x9E, 0x69, 0x27, 0xD0, 0xBB, 0x4C, 0x02, 0xF5,
+ 0x40, 0xB7, 0xF9, 0x0E, 0x65, 0x92, 0xDC, 0x2B,
+ 0x0A, 0xFD, 0xB3, 0x44, 0x2F, 0xD8, 0x96, 0x61,
+ 0x55, 0xA2, 0xEC, 0x1B, 0x70, 0x87, 0xC9, 0x3E,
+ 0x1F, 0xE8, 0xA6, 0x51, 0x3A, 0xCD, 0x83, 0x74,
+ 0xC1, 0x36, 0x78, 0x8F, 0xE4, 0x13, 0x5D, 0xAA,
+ 0x8B, 0x7C, 0x32, 0xC5, 0xAE, 0x59, 0x17, 0xE0,
+ 0x2A, 0xDD, 0x93, 0x64, 0x0F, 0xF8, 0xB6, 0x41,
+ 0x60, 0x97, 0xD9, 0x2E, 0x45, 0xB2, 0xFC, 0x0B,
+ 0xBE, 0x49, 0x07, 0xF0, 0x9B, 0x6C, 0x22, 0xD5,
+ 0xF4, 0x03, 0x4D, 0xBA, 0xD1, 0x26, 0x68, 0x9F,
+ };
+ return t[crc ^ data];
+}
+
+static u8 bcma_sprom_crc(const u16 *sprom)
+{
+ int word;
+ u8 crc = 0xFF;
+
+ for (word = 0; word < SSB_SPROMSIZE_WORDS_R4 - 1; word++) {
+ crc = bcma_crc8(crc, sprom[word] & 0x00FF);
+ crc = bcma_crc8(crc, (sprom[word] & 0xFF00) >> 8);
+ }
+ crc = bcma_crc8(crc, sprom[SSB_SPROMSIZE_WORDS_R4 - 1] & 0x00FF);
+ crc ^= 0xFF;
+
+ return crc;
+}
+
+static int bcma_sprom_check_crc(const u16 *sprom)
+{
+ u8 crc;
+ u8 expected_crc;
+ u16 tmp;
+
+ crc = bcma_sprom_crc(sprom);
+ tmp = sprom[SSB_SPROMSIZE_WORDS_R4 - 1] & SSB_SPROM_REVISION_CRC;
+ expected_crc = tmp >> SSB_SPROM_REVISION_CRC_SHIFT;
+ if (crc != expected_crc)
+ return -EPROTO;
+
+ return 0;
+}
+
+static int bcma_sprom_valid(const u16 *sprom)
+{
+ u16 revision;
+ int err;
+
+ err = bcma_sprom_check_crc(sprom);
+ if (err)
+ return err;
+
+ revision = sprom[SSB_SPROMSIZE_WORDS_R4 - 1] & SSB_SPROM_REVISION_REV;
+ if (revision != 8) {
+ pr_err("Unsupported SPROM revision: %d\n", revision);
+ return -ENOENT;
+ }
+
+ return 0;
+}
+
+/**************************************************
+ * SPROM extraction.
+ **************************************************/
+
+static void bcma_sprom_extract_r8(struct bcma_bus *bus, const u16 *sprom)
+{
+ u16 v;
+ int i;
+
+ for (i = 0; i < 3; i++) {
+ v = sprom[SPOFF(SSB_SPROM8_IL0MAC) + i];
+ *(((__be16 *)bus->sprom.il0mac) + i) = cpu_to_be16(v);
+ }
+}
+
+int bcma_sprom_get(struct bcma_bus *bus)
+{
+ u16 *sprom;
+ int err = 0;
+
+ if (!bus->drv_cc.core)
+ return -EOPNOTSUPP;
+
+ sprom = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16),
+ GFP_KERNEL);
+ if (!sprom)
+ return -ENOMEM;
+
+ bcma_sprom_read(bus, sprom);
+
+ err = bcma_sprom_valid(sprom);
+ if (err)
+ goto out;
+
+ bcma_sprom_extract_r8(bus, sprom);
+
+out:
+ kfree(sprom);
+ return err;
+}
diff --git a/drivers/dma/coh901318.c b/drivers/dma/coh901318.c
index af8c0b5..a92d95e 100644
--- a/drivers/dma/coh901318.c
+++ b/drivers/dma/coh901318.c
@@ -11,6 +11,7 @@
#include <linux/module.h>
#include <linux/kernel.h> /* printk() */
#include <linux/fs.h> /* everything... */
+#include <linux/scatterlist.h>
#include <linux/slab.h> /* kmalloc() */
#include <linux/dmaengine.h>
#include <linux/platform_device.h>
diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c
index 8bcb15f..48694c3 100644
--- a/drivers/dma/dmaengine.c
+++ b/drivers/dma/dmaengine.c
@@ -45,6 +45,7 @@
* See Documentation/dmaengine.txt for more details
*/
+#include <linux/dma-mapping.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/mm.h>
diff --git a/drivers/dma/dmatest.c b/drivers/dma/dmatest.c
index b4f5c32..765f5ff 100644
--- a/drivers/dma/dmatest.c
+++ b/drivers/dma/dmatest.c
@@ -8,6 +8,7 @@
* published by the Free Software Foundation.
*/
#include <linux/delay.h>
+#include <linux/dma-mapping.h>
#include <linux/dmaengine.h>
#include <linux/init.h>
#include <linux/kthread.h>
diff --git a/drivers/dma/ipu/ipu_idmac.c b/drivers/dma/ipu/ipu_idmac.c
index c1a125e7..fd7d2b3 100644
--- a/drivers/dma/ipu/ipu_idmac.c
+++ b/drivers/dma/ipu/ipu_idmac.c
@@ -9,6 +9,7 @@
* published by the Free Software Foundation.
*/
+#include <linux/dma-mapping.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/err.h>
diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c
index 8f222d4..29d1add 100644
--- a/drivers/dma/ste_dma40.c
+++ b/drivers/dma/ste_dma40.c
@@ -6,6 +6,7 @@
* License terms: GNU General Public License (GPL) version 2
*/
+#include <linux/dma-mapping.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/dmaengine.h>
diff --git a/drivers/ieee802154/Makefile b/drivers/ieee802154/Makefile
index 6899913..800a389 100644
--- a/drivers/ieee802154/Makefile
+++ b/drivers/ieee802154/Makefile
@@ -1,3 +1 @@
obj-$(CONFIG_IEEE802154_FAKEHARD) += fakehard.o
-
-ccflags-y := -DDEBUG -DCONFIG_FFD
diff --git a/drivers/ieee802154/fakehard.c b/drivers/ieee802154/fakehard.c
index a5a49a1..eb0e2cc 100644
--- a/drivers/ieee802154/fakehard.c
+++ b/drivers/ieee802154/fakehard.c
@@ -370,8 +370,6 @@
return -ENOMEM;
}
- phy->dev.platform_data = dev;
-
memcpy(dev->dev_addr, "\xba\xbe\xca\xfe\xde\xad\xbe\xef",
dev->addr_len);
memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
diff --git a/drivers/infiniband/core/netlink.c b/drivers/infiniband/core/netlink.c
index 4a5abaf..9227f4a 100644
--- a/drivers/infiniband/core/netlink.c
+++ b/drivers/infiniband/core/netlink.c
@@ -148,7 +148,7 @@
return -EINVAL;
return netlink_dump_start(nls, skb, nlh,
client->cb_table[op].dump,
- NULL);
+ NULL, 0);
}
}
diff --git a/drivers/infiniband/hw/amso1100/c2.c b/drivers/infiniband/hw/amso1100/c2.c
index 0cfc455..444470a 100644
--- a/drivers/infiniband/hw/amso1100/c2.c
+++ b/drivers/infiniband/hw/amso1100/c2.c
@@ -36,6 +36,7 @@
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/inetdevice.h>
+#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/ethtool.h>
#include <linux/mii.h>
diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.h b/drivers/infiniband/ulp/iser/iscsi_iser.h
index 2f02ab0..342cbc1 100644
--- a/drivers/infiniband/ulp/iser/iscsi_iser.h
+++ b/drivers/infiniband/ulp/iser/iscsi_iser.h
@@ -45,6 +45,7 @@
#include <scsi/libiscsi.h>
#include <scsi/scsi_transport_iscsi.h>
+#include <linux/interrupt.h>
#include <linux/wait.h>
#include <linux/sched.h>
#include <linux/list.h>
diff --git a/drivers/isdn/hardware/mISDN/avmfritz.c b/drivers/isdn/hardware/mISDN/avmfritz.c
index 472a2af..861b651 100644
--- a/drivers/isdn/hardware/mISDN/avmfritz.c
+++ b/drivers/isdn/hardware/mISDN/avmfritz.c
@@ -20,6 +20,7 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
+#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/delay.h>
diff --git a/drivers/isdn/hardware/mISDN/hfcmulti.c b/drivers/isdn/hardware/mISDN/hfcmulti.c
index f6f3c87..a440d7f 100644
--- a/drivers/isdn/hardware/mISDN/hfcmulti.c
+++ b/drivers/isdn/hardware/mISDN/hfcmulti.c
@@ -152,6 +152,7 @@
#define HFC_MULTI_VERSION "2.03"
+#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/pci.h>
diff --git a/drivers/isdn/hardware/mISDN/hfcpci.c b/drivers/isdn/hardware/mISDN/hfcpci.c
index b01a7be..3261de1 100644
--- a/drivers/isdn/hardware/mISDN/hfcpci.c
+++ b/drivers/isdn/hardware/mISDN/hfcpci.c
@@ -44,6 +44,7 @@
*
*/
+#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/delay.h>
diff --git a/drivers/isdn/hardware/mISDN/mISDNinfineon.c b/drivers/isdn/hardware/mISDN/mISDNinfineon.c
index bc0529a..6218775 100644
--- a/drivers/isdn/hardware/mISDN/mISDNinfineon.c
+++ b/drivers/isdn/hardware/mISDN/mISDNinfineon.c
@@ -38,6 +38,7 @@
*
*/
+#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/delay.h>
diff --git a/drivers/isdn/hardware/mISDN/mISDNipac.c b/drivers/isdn/hardware/mISDN/mISDNipac.c
index 64ecc6f..d2ffb1d 100644
--- a/drivers/isdn/hardware/mISDN/mISDNipac.c
+++ b/drivers/isdn/hardware/mISDN/mISDNipac.c
@@ -20,6 +20,7 @@
*
*/
+#include <linux/irqreturn.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/mISDNhw.h>
diff --git a/drivers/isdn/hardware/mISDN/netjet.c b/drivers/isdn/hardware/mISDN/netjet.c
index db25b6b..5ef9f11 100644
--- a/drivers/isdn/hardware/mISDN/netjet.c
+++ b/drivers/isdn/hardware/mISDN/netjet.c
@@ -20,6 +20,7 @@
*
*/
+#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/delay.h>
diff --git a/drivers/isdn/hardware/mISDN/speedfax.c b/drivers/isdn/hardware/mISDN/speedfax.c
index 9e07246..4d0d41e 100644
--- a/drivers/isdn/hardware/mISDN/speedfax.c
+++ b/drivers/isdn/hardware/mISDN/speedfax.c
@@ -22,6 +22,7 @@
*
*/
+#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/pci.h>
diff --git a/drivers/isdn/hardware/mISDN/w6692.c b/drivers/isdn/hardware/mISDN/w6692.c
index 9e84870..e10e028 100644
--- a/drivers/isdn/hardware/mISDN/w6692.c
+++ b/drivers/isdn/hardware/mISDN/w6692.c
@@ -21,6 +21,7 @@
*
*/
+#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/delay.h>
diff --git a/drivers/isdn/hisax/hisax.h b/drivers/isdn/hisax/hisax.h
index de1c669..0a5c42a 100644
--- a/drivers/isdn/hisax/hisax.h
+++ b/drivers/isdn/hisax/hisax.h
@@ -16,6 +16,7 @@
#include <linux/slab.h>
#include <linux/mm.h>
#include <linux/mman.h>
+#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/timer.h>
#include <linux/wait.h>
diff --git a/drivers/isdn/hisax/hisax_fcpcipnp.c b/drivers/isdn/hisax/hisax_fcpcipnp.c
index 8b0a7d8..478ebab 100644
--- a/drivers/isdn/hisax/hisax_fcpcipnp.c
+++ b/drivers/isdn/hisax/hisax_fcpcipnp.c
@@ -25,6 +25,7 @@
#include <linux/module.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/pci.h>
#include <linux/isapnp.h>
#include <linux/kmod.h>
diff --git a/drivers/media/dvb/b2c2/flexcop-common.h b/drivers/media/dvb/b2c2/flexcop-common.h
index 9e2148a..437912e 100644
--- a/drivers/media/dvb/b2c2/flexcop-common.h
+++ b/drivers/media/dvb/b2c2/flexcop-common.h
@@ -6,6 +6,7 @@
#ifndef __FLEXCOP_COMMON_H__
#define __FLEXCOP_COMMON_H__
+#include <linux/interrupt.h>
#include <linux/pci.h>
#include <linux/mutex.h>
diff --git a/drivers/media/dvb/dm1105/dm1105.c b/drivers/media/dvb/dm1105/dm1105.c
index b2b0c45..55e6533 100644
--- a/drivers/media/dvb/dm1105/dm1105.c
+++ b/drivers/media/dvb/dm1105/dm1105.c
@@ -22,6 +22,7 @@
#include <linux/i2c.h>
#include <linux/i2c-algo-bit.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/proc_fs.h>
diff --git a/drivers/media/dvb/mantis/mantis_ca.c b/drivers/media/dvb/mantis/mantis_ca.c
index 330216f..3d70469 100644
--- a/drivers/media/dvb/mantis/mantis_ca.c
+++ b/drivers/media/dvb/mantis/mantis_ca.c
@@ -22,6 +22,7 @@
#include <linux/slab.h>
#include <linux/sched.h>
#include <linux/interrupt.h>
+#include <asm/io.h>
#include "dmxdev.h"
#include "dvbdev.h"
diff --git a/drivers/media/dvb/mantis/mantis_common.h b/drivers/media/dvb/mantis/mantis_common.h
index bd400d2..49dbca1 100644
--- a/drivers/media/dvb/mantis/mantis_common.h
+++ b/drivers/media/dvb/mantis/mantis_common.h
@@ -21,6 +21,7 @@
#ifndef __MANTIS_COMMON_H
#define __MANTIS_COMMON_H
+#include <linux/interrupt.h>
#include <linux/mutex.h>
#include <linux/workqueue.h>
diff --git a/drivers/media/dvb/mantis/mantis_evm.c b/drivers/media/dvb/mantis/mantis_evm.c
index 9f73c2c..36f2256 100644
--- a/drivers/media/dvb/mantis/mantis_evm.c
+++ b/drivers/media/dvb/mantis/mantis_evm.c
@@ -23,6 +23,7 @@
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/interrupt.h>
+#include <asm/io.h>
#include "dmxdev.h"
#include "dvbdev.h"
diff --git a/drivers/media/dvb/mantis/mantis_hif.c b/drivers/media/dvb/mantis/mantis_hif.c
index 5772ebb..672cf4d 100644
--- a/drivers/media/dvb/mantis/mantis_hif.c
+++ b/drivers/media/dvb/mantis/mantis_hif.c
@@ -23,6 +23,7 @@
#include <linux/sched.h>
#include <linux/interrupt.h>
+#include <asm/io.h>
#include "dmxdev.h"
#include "dvbdev.h"
diff --git a/drivers/media/dvb/mantis/mantis_ioc.c b/drivers/media/dvb/mantis/mantis_ioc.c
index 479086d..24fcdc6 100644
--- a/drivers/media/dvb/mantis/mantis_ioc.c
+++ b/drivers/media/dvb/mantis/mantis_ioc.c
@@ -24,6 +24,7 @@
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/interrupt.h>
+#include <asm/io.h>
#include "dmxdev.h"
#include "dvbdev.h"
diff --git a/drivers/media/dvb/mantis/mantis_pcmcia.c b/drivers/media/dvb/mantis/mantis_pcmcia.c
index 5cb545b..2f188c0 100644
--- a/drivers/media/dvb/mantis/mantis_pcmcia.c
+++ b/drivers/media/dvb/mantis/mantis_pcmcia.c
@@ -23,6 +23,7 @@
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/interrupt.h>
+#include <asm/io.h>
#include "dmxdev.h"
#include "dvbdev.h"
diff --git a/drivers/media/dvb/mantis/mantis_uart.c b/drivers/media/dvb/mantis/mantis_uart.c
index f807c8b..18340da 100644
--- a/drivers/media/dvb/mantis/mantis_uart.c
+++ b/drivers/media/dvb/mantis/mantis_uart.c
@@ -20,6 +20,7 @@
#include <linux/kernel.h>
#include <linux/spinlock.h>
+#include <asm/io.h>
#include <linux/signal.h>
#include <linux/sched.h>
diff --git a/drivers/media/dvb/mantis/mantis_vp1034.c b/drivers/media/dvb/mantis/mantis_vp1034.c
index 26bc0cb..430ae84 100644
--- a/drivers/media/dvb/mantis/mantis_vp1034.c
+++ b/drivers/media/dvb/mantis/mantis_vp1034.c
@@ -21,6 +21,7 @@
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/interrupt.h>
+#include <asm/io.h>
#include "dmxdev.h"
#include "dvbdev.h"
diff --git a/drivers/media/dvb/pluto2/pluto2.c b/drivers/media/dvb/pluto2/pluto2.c
index 7cb79ec..80fb510 100644
--- a/drivers/media/dvb/pluto2/pluto2.c
+++ b/drivers/media/dvb/pluto2/pluto2.c
@@ -26,6 +26,7 @@
#include <linux/i2c.h>
#include <linux/i2c-algo-bit.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/pci.h>
diff --git a/drivers/mmc/host/tmio_mmc_dma.c b/drivers/mmc/host/tmio_mmc_dma.c
index 25f1ad6..bf12513 100644
--- a/drivers/mmc/host/tmio_mmc_dma.c
+++ b/drivers/mmc/host/tmio_mmc_dma.c
@@ -11,6 +11,7 @@
*/
#include <linux/device.h>
+#include <linux/dma-mapping.h>
#include <linux/dmaengine.h>
#include <linux/mfd/tmio.h>
#include <linux/mmc/host.h>
diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c
index b300705..1b90fd5 100644
--- a/drivers/mtd/nand/atmel_nand.c
+++ b/drivers/mtd/nand/atmel_nand.c
@@ -22,6 +22,7 @@
*
*/
+#include <linux/dma-mapping.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
diff --git a/drivers/net/3c503.c b/drivers/net/3c503.c
index 5b73298..84e68f1 100644
--- a/drivers/net/3c503.c
+++ b/drivers/net/3c503.c
@@ -49,6 +49,7 @@
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/ethtool.h>
#include <asm/uaccess.h>
diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c
index 10c4505..73b10b0 100644
--- a/drivers/net/8139cp.c
+++ b/drivers/net/8139cp.c
@@ -60,6 +60,7 @@
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/pci.h>
#include <linux/dma-mapping.h>
#include <linux/delay.h>
diff --git a/drivers/net/8139too.c b/drivers/net/8139too.c
index e3bad82..c2672c6 100644
--- a/drivers/net/8139too.c
+++ b/drivers/net/8139too.c
@@ -100,6 +100,7 @@
#include <linux/compiler.h>
#include <linux/pci.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/rtnetlink.h>
diff --git a/drivers/net/8390.h b/drivers/net/8390.h
index 3d9e8fb..58a12e4 100644
--- a/drivers/net/8390.h
+++ b/drivers/net/8390.h
@@ -9,6 +9,7 @@
#include <linux/if_ether.h>
#include <linux/ioport.h>
+#include <linux/irqreturn.h>
#include <linux/skbuff.h>
#define TX_PAGES 12 /* Two Tx slots */
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 93359fa..4d68a26 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -2115,7 +2115,6 @@
config E1000E
tristate "Intel(R) PRO/1000 PCI-Express Gigabit Ethernet support"
- select CRC32
depends on PCI && (!SPARC32 || BROKEN)
select CRC32
---help---
@@ -2197,15 +2196,6 @@
source "drivers/net/ixp2000/Kconfig"
-config MYRI_SBUS
- tristate "MyriCOM Gigabit Ethernet support"
- depends on SBUS
- help
- This driver supports MyriCOM Sbus gigabit Ethernet cards.
-
- To compile this driver as a module, choose M here: the module
- will be called myri_sbus. This is recommended.
-
config NS83820
tristate "National Semiconductor DP83820 support"
depends on PCI
@@ -2561,6 +2551,15 @@
ML7223 is companion chip for Intel Atom E6xx series.
ML7223 is completely compatible for Intel EG20T PCH.
+config FTGMAC100
+ tristate "Faraday FTGMAC100 Gigabit Ethernet support"
+ depends on ARM
+ select PHYLIB
+ help
+ This driver supports the FTGMAC100 Gigabit Ethernet controller
+ from Faraday. It is used on Faraday A369, Andes AG102 and some
+ other ARM/NDS32 SoC's.
+
endif # NETDEV_1000
#
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 776a478..86f6c8d 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -59,7 +59,6 @@
obj-$(CONFIG_SUNLANCE) += sunlance.o
obj-$(CONFIG_SUNQE) += sunqe.o
obj-$(CONFIG_SUNBMAC) += sunbmac.o
-obj-$(CONFIG_MYRI_SBUS) += myri_sbus.o
obj-$(CONFIG_SUNGEM) += sungem.o sungem_phy.o
obj-$(CONFIG_CASSINI) += cassini.o
obj-$(CONFIG_SUNVNET) += sunvnet.o
@@ -148,6 +147,7 @@
obj-$(CONFIG_NE_H8300) += ne-h8300.o
obj-$(CONFIG_AX88796) += ax88796.o
obj-$(CONFIG_BCM63XX_ENET) += bcm63xx_enet.o
+obj-$(CONFIG_FTGMAC100) += ftgmac100.o
obj-$(CONFIG_FTMAC100) += ftmac100.o
obj-$(CONFIG_TSI108_ETH) += tsi108_eth.o
diff --git a/drivers/net/a2065.c b/drivers/net/a2065.c
index deaa8bc..7d9a1a6 100644
--- a/drivers/net/a2065.c
+++ b/drivers/net/a2065.c
@@ -37,6 +37,11 @@
* both 10BASE-2 (thin coax) and AUI (DB-15) connectors
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+/*#define DEBUG*/
+/*#define TEST_HITS*/
+
#include <linux/errno.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
@@ -58,29 +63,22 @@
#include "a2065.h"
-
- /*
- * Transmit/Receive Ring Definitions
- */
+/* Transmit/Receive Ring Definitions */
#define LANCE_LOG_TX_BUFFERS (2)
#define LANCE_LOG_RX_BUFFERS (4)
-#define TX_RING_SIZE (1<<LANCE_LOG_TX_BUFFERS)
-#define RX_RING_SIZE (1<<LANCE_LOG_RX_BUFFERS)
+#define TX_RING_SIZE (1 << LANCE_LOG_TX_BUFFERS)
+#define RX_RING_SIZE (1 << LANCE_LOG_RX_BUFFERS)
-#define TX_RING_MOD_MASK (TX_RING_SIZE-1)
-#define RX_RING_MOD_MASK (RX_RING_SIZE-1)
+#define TX_RING_MOD_MASK (TX_RING_SIZE - 1)
+#define RX_RING_MOD_MASK (RX_RING_SIZE - 1)
#define PKT_BUF_SIZE (1544)
#define RX_BUFF_SIZE PKT_BUF_SIZE
#define TX_BUFF_SIZE PKT_BUF_SIZE
-
- /*
- * Layout of the Lance's RAM Buffer
- */
-
+/* Layout of the Lance's RAM Buffer */
struct lance_init_block {
unsigned short mode; /* Pre-set mode (reg. 15) */
@@ -97,14 +95,11 @@
struct lance_rx_desc brx_ring[RX_RING_SIZE];
struct lance_tx_desc btx_ring[TX_RING_SIZE];
- char rx_buf [RX_RING_SIZE][RX_BUFF_SIZE];
- char tx_buf [TX_RING_SIZE][TX_BUFF_SIZE];
+ char rx_buf[RX_RING_SIZE][RX_BUFF_SIZE];
+ char tx_buf[TX_RING_SIZE][TX_BUFF_SIZE];
};
-
- /*
- * Private Device Data
- */
+/* Private Device Data */
struct lance_private {
char *name;
@@ -129,21 +124,14 @@
struct timer_list multicast_timer;
};
-#define TX_BUFFS_AVAIL ((lp->tx_old<=lp->tx_new)?\
- lp->tx_old+lp->tx_ring_mod_mask-lp->tx_new:\
- lp->tx_old - lp->tx_new-1)
-
-
#define LANCE_ADDR(x) ((int)(x) & ~0xff000000)
/* Load the CSR registers */
-static void load_csrs (struct lance_private *lp)
+static void load_csrs(struct lance_private *lp)
{
volatile struct lance_regs *ll = lp->ll;
volatile struct lance_init_block *aib = lp->lance_init_block;
- int leptr;
-
- leptr = LANCE_ADDR (aib);
+ int leptr = LANCE_ADDR(aib);
ll->rap = LE_CSR1;
ll->rdp = (leptr & 0xFFFF);
@@ -156,19 +144,16 @@
ll->rap = LE_CSR0;
}
-#define ZERO 0
-
/* Setup the Lance Rx and Tx rings */
-static void lance_init_ring (struct net_device *dev)
+static void lance_init_ring(struct net_device *dev)
{
struct lance_private *lp = netdev_priv(dev);
volatile struct lance_init_block *ib = lp->init_block;
- volatile struct lance_init_block *aib; /* for LANCE_ADDR computations */
+ volatile struct lance_init_block *aib = lp->lance_init_block;
+ /* for LANCE_ADDR computations */
int leptr;
int i;
- aib = lp->lance_init_block;
-
/* Lock out other processes while setting up hardware */
netif_stop_queue(dev);
lp->rx_new = lp->tx_new = 0;
@@ -179,41 +164,38 @@
/* Copy the ethernet address to the lance init block
* Note that on the sparc you need to swap the ethernet address.
*/
- ib->phys_addr [0] = dev->dev_addr [1];
- ib->phys_addr [1] = dev->dev_addr [0];
- ib->phys_addr [2] = dev->dev_addr [3];
- ib->phys_addr [3] = dev->dev_addr [2];
- ib->phys_addr [4] = dev->dev_addr [5];
- ib->phys_addr [5] = dev->dev_addr [4];
-
- if (ZERO)
- printk(KERN_DEBUG "TX rings:\n");
+ ib->phys_addr[0] = dev->dev_addr[1];
+ ib->phys_addr[1] = dev->dev_addr[0];
+ ib->phys_addr[2] = dev->dev_addr[3];
+ ib->phys_addr[3] = dev->dev_addr[2];
+ ib->phys_addr[4] = dev->dev_addr[5];
+ ib->phys_addr[5] = dev->dev_addr[4];
/* Setup the Tx ring entries */
- for (i = 0; i <= (1<<lp->lance_log_tx_bufs); i++) {
+ netdev_dbg(dev, "TX rings:\n");
+ for (i = 0; i <= 1 << lp->lance_log_tx_bufs; i++) {
leptr = LANCE_ADDR(&aib->tx_buf[i][0]);
- ib->btx_ring [i].tmd0 = leptr;
- ib->btx_ring [i].tmd1_hadr = leptr >> 16;
- ib->btx_ring [i].tmd1_bits = 0;
- ib->btx_ring [i].length = 0xf000; /* The ones required by tmd2 */
- ib->btx_ring [i].misc = 0;
- if (i < 3 && ZERO)
- printk(KERN_DEBUG "%d: 0x%8.8x\n", i, leptr);
+ ib->btx_ring[i].tmd0 = leptr;
+ ib->btx_ring[i].tmd1_hadr = leptr >> 16;
+ ib->btx_ring[i].tmd1_bits = 0;
+ ib->btx_ring[i].length = 0xf000; /* The ones required by tmd2 */
+ ib->btx_ring[i].misc = 0;
+ if (i < 3)
+ netdev_dbg(dev, "%d: 0x%08x\n", i, leptr);
}
/* Setup the Rx ring entries */
- if (ZERO)
- printk(KERN_DEBUG "RX rings:\n");
- for (i = 0; i < (1<<lp->lance_log_rx_bufs); i++) {
+ netdev_dbg(dev, "RX rings:\n");
+ for (i = 0; i < 1 << lp->lance_log_rx_bufs; i++) {
leptr = LANCE_ADDR(&aib->rx_buf[i][0]);
- ib->brx_ring [i].rmd0 = leptr;
- ib->brx_ring [i].rmd1_hadr = leptr >> 16;
- ib->brx_ring [i].rmd1_bits = LE_R1_OWN;
- ib->brx_ring [i].length = -RX_BUFF_SIZE | 0xf000;
- ib->brx_ring [i].mblength = 0;
- if (i < 3 && ZERO)
- printk(KERN_DEBUG "%d: 0x%8.8x\n", i, leptr);
+ ib->brx_ring[i].rmd0 = leptr;
+ ib->brx_ring[i].rmd1_hadr = leptr >> 16;
+ ib->brx_ring[i].rmd1_bits = LE_R1_OWN;
+ ib->brx_ring[i].length = -RX_BUFF_SIZE | 0xf000;
+ ib->brx_ring[i].mblength = 0;
+ if (i < 3)
+ netdev_dbg(dev, "%d: 0x%08x\n", i, leptr);
}
/* Setup the initialization block */
@@ -222,22 +204,20 @@
leptr = LANCE_ADDR(&aib->brx_ring);
ib->rx_len = (lp->lance_log_rx_bufs << 13) | (leptr >> 16);
ib->rx_ptr = leptr;
- if (ZERO)
- printk(KERN_DEBUG "RX ptr: %8.8x\n", leptr);
+ netdev_dbg(dev, "RX ptr: %08x\n", leptr);
/* Setup tx descriptor pointer */
leptr = LANCE_ADDR(&aib->btx_ring);
ib->tx_len = (lp->lance_log_tx_bufs << 13) | (leptr >> 16);
ib->tx_ptr = leptr;
- if (ZERO)
- printk(KERN_DEBUG "TX ptr: %8.8x\n", leptr);
+ netdev_dbg(dev, "TX ptr: %08x\n", leptr);
/* Clear the multicast filter */
- ib->filter [0] = 0;
- ib->filter [1] = 0;
+ ib->filter[0] = 0;
+ ib->filter[1] = 0;
}
-static int init_restart_lance (struct lance_private *lp)
+static int init_restart_lance(struct lance_private *lp)
{
volatile struct lance_regs *ll = lp->ll;
int i;
@@ -249,8 +229,7 @@
for (i = 0; (i < 100) && !(ll->rdp & (LE_C0_ERR | LE_C0_IDON)); i++)
barrier();
if ((i == 100) || (ll->rdp & LE_C0_ERR)) {
- printk(KERN_ERR "LANCE unopened after %d ticks, csr0=%4.4x.\n",
- i, ll->rdp);
+ pr_err("unopened after %d ticks, csr0=%04x\n", i, ll->rdp);
return -EIO;
}
@@ -261,7 +240,7 @@
return 0;
}
-static int lance_rx (struct net_device *dev)
+static int lance_rx(struct net_device *dev)
{
struct lance_private *lp = netdev_priv(dev);
volatile struct lance_init_block *ib = lp->init_block;
@@ -271,22 +250,24 @@
#ifdef TEST_HITS
int i;
- printk(KERN_DEBUG "[");
+ char buf[RX_RING_SIZE + 1];
+
for (i = 0; i < RX_RING_SIZE; i++) {
+ char r1_own = ib->brx_ring[i].rmd1_bits & LE_R1_OWN;
if (i == lp->rx_new)
- printk ("%s",
- ib->brx_ring [i].rmd1_bits & LE_R1_OWN ? "_" : "X");
+ buf[i] = r1_own ? '_' : 'X';
else
- printk ("%s",
- ib->brx_ring [i].rmd1_bits & LE_R1_OWN ? "." : "1");
+ buf[i] = r1_own ? '.' : '1';
}
- printk ("]\n");
+ buf[RX_RING_SIZE] = 0;
+
+ pr_debug("RxRing TestHits: [%s]\n", buf);
#endif
- ll->rdp = LE_C0_RINT|LE_C0_INEA;
- for (rd = &ib->brx_ring [lp->rx_new];
+ ll->rdp = LE_C0_RINT | LE_C0_INEA;
+ for (rd = &ib->brx_ring[lp->rx_new];
!((bits = rd->rmd1_bits) & LE_R1_OWN);
- rd = &ib->brx_ring [lp->rx_new]) {
+ rd = &ib->brx_ring[lp->rx_new]) {
/* We got an incomplete frame? */
if ((bits & LE_R1_POK) != LE_R1_POK) {
@@ -297,18 +278,22 @@
/* Count only the end frame as a rx error,
* not the beginning
*/
- if (bits & LE_R1_BUF) dev->stats.rx_fifo_errors++;
- if (bits & LE_R1_CRC) dev->stats.rx_crc_errors++;
- if (bits & LE_R1_OFL) dev->stats.rx_over_errors++;
- if (bits & LE_R1_FRA) dev->stats.rx_frame_errors++;
- if (bits & LE_R1_EOP) dev->stats.rx_errors++;
+ if (bits & LE_R1_BUF)
+ dev->stats.rx_fifo_errors++;
+ if (bits & LE_R1_CRC)
+ dev->stats.rx_crc_errors++;
+ if (bits & LE_R1_OFL)
+ dev->stats.rx_over_errors++;
+ if (bits & LE_R1_FRA)
+ dev->stats.rx_frame_errors++;
+ if (bits & LE_R1_EOP)
+ dev->stats.rx_errors++;
} else {
int len = (rd->mblength & 0xfff) - 4;
- struct sk_buff *skb = dev_alloc_skb (len+2);
+ struct sk_buff *skb = dev_alloc_skb(len + 2);
if (!skb) {
- printk(KERN_WARNING "%s: Memory squeeze, "
- "deferring packet.\n", dev->name);
+ netdev_warn(dev, "Memory squeeze, deferring packet\n");
dev->stats.rx_dropped++;
rd->mblength = 0;
rd->rmd1_bits = LE_R1_OWN;
@@ -316,13 +301,13 @@
return 0;
}
- skb_reserve (skb, 2); /* 16 byte align */
- skb_put (skb, len); /* make room */
+ skb_reserve(skb, 2); /* 16 byte align */
+ skb_put(skb, len); /* make room */
skb_copy_to_linear_data(skb,
- (unsigned char *)&(ib->rx_buf [lp->rx_new][0]),
- len);
- skb->protocol = eth_type_trans (skb, dev);
- netif_rx (skb);
+ (unsigned char *)&ib->rx_buf[lp->rx_new][0],
+ len);
+ skb->protocol = eth_type_trans(skb, dev);
+ netif_rx(skb);
dev->stats.rx_packets++;
dev->stats.rx_bytes += len;
}
@@ -335,7 +320,7 @@
return 0;
}
-static int lance_tx (struct net_device *dev)
+static int lance_tx(struct net_device *dev)
{
struct lance_private *lp = netdev_priv(dev);
volatile struct lance_init_block *ib = lp->init_block;
@@ -350,7 +335,7 @@
j = lp->tx_old;
for (i = j; i != lp->tx_new; i = j) {
- td = &ib->btx_ring [i];
+ td = &ib->btx_ring[i];
/* If we hit a packet not owned by us, stop */
if (td->tmd1_bits & LE_T1_OWN)
@@ -360,45 +345,44 @@
status = td->misc;
dev->stats.tx_errors++;
- if (status & LE_T3_RTY) dev->stats.tx_aborted_errors++;
- if (status & LE_T3_LCOL) dev->stats.tx_window_errors++;
+ if (status & LE_T3_RTY)
+ dev->stats.tx_aborted_errors++;
+ if (status & LE_T3_LCOL)
+ dev->stats.tx_window_errors++;
if (status & LE_T3_CLOS) {
dev->stats.tx_carrier_errors++;
if (lp->auto_select) {
lp->tpe = 1 - lp->tpe;
- printk(KERN_ERR "%s: Carrier Lost, "
- "trying %s\n", dev->name,
- lp->tpe?"TPE":"AUI");
+ netdev_err(dev, "Carrier Lost, trying %s\n",
+ lp->tpe ? "TPE" : "AUI");
/* Stop the lance */
ll->rap = LE_CSR0;
ll->rdp = LE_C0_STOP;
- lance_init_ring (dev);
- load_csrs (lp);
- init_restart_lance (lp);
+ lance_init_ring(dev);
+ load_csrs(lp);
+ init_restart_lance(lp);
return 0;
}
}
- /* buffer errors and underflows turn off the transmitter */
- /* Restart the adapter */
- if (status & (LE_T3_BUF|LE_T3_UFL)) {
+ /* buffer errors and underflows turn off
+ * the transmitter, so restart the adapter
+ */
+ if (status & (LE_T3_BUF | LE_T3_UFL)) {
dev->stats.tx_fifo_errors++;
- printk(KERN_ERR "%s: Tx: ERR_BUF|ERR_UFL, "
- "restarting\n", dev->name);
+ netdev_err(dev, "Tx: ERR_BUF|ERR_UFL, restarting\n");
/* Stop the lance */
ll->rap = LE_CSR0;
ll->rdp = LE_C0_STOP;
- lance_init_ring (dev);
- load_csrs (lp);
- init_restart_lance (lp);
+ lance_init_ring(dev);
+ load_csrs(lp);
+ init_restart_lance(lp);
return 0;
}
} else if ((td->tmd1_bits & LE_T1_POK) == LE_T1_POK) {
- /*
- * So we don't count the packet more than once.
- */
+ /* So we don't count the packet more than once. */
td->tmd1_bits &= ~(LE_T1_POK);
/* One collision before packet was sent. */
@@ -419,18 +403,20 @@
return 0;
}
-static irqreturn_t lance_interrupt (int irq, void *dev_id)
+static int lance_tx_buffs_avail(struct lance_private *lp)
{
- struct net_device *dev;
- struct lance_private *lp;
- volatile struct lance_regs *ll;
+ if (lp->tx_old <= lp->tx_new)
+ return lp->tx_old + lp->tx_ring_mod_mask - lp->tx_new;
+ return lp->tx_old - lp->tx_new - 1;
+}
+
+static irqreturn_t lance_interrupt(int irq, void *dev_id)
+{
+ struct net_device *dev = dev_id;
+ struct lance_private *lp = netdev_priv(dev);
+ volatile struct lance_regs *ll = lp->ll;
int csr0;
- dev = (struct net_device *) dev_id;
-
- lp = netdev_priv(dev);
- ll = lp->ll;
-
ll->rap = LE_CSR0; /* LANCE Controller Status */
csr0 = ll->rdp;
@@ -438,19 +424,19 @@
return IRQ_NONE; /* been generated by the Lance. */
/* Acknowledge all the interrupt sources ASAP */
- ll->rdp = csr0 & ~(LE_C0_INEA|LE_C0_TDMD|LE_C0_STOP|LE_C0_STRT|
+ ll->rdp = csr0 & ~(LE_C0_INEA | LE_C0_TDMD | LE_C0_STOP | LE_C0_STRT |
LE_C0_INIT);
- if ((csr0 & LE_C0_ERR)) {
+ if (csr0 & LE_C0_ERR) {
/* Clear the error condition */
- ll->rdp = LE_C0_BABL|LE_C0_ERR|LE_C0_MISS|LE_C0_INEA;
+ ll->rdp = LE_C0_BABL | LE_C0_ERR | LE_C0_MISS | LE_C0_INEA;
}
if (csr0 & LE_C0_RINT)
- lance_rx (dev);
+ lance_rx(dev);
if (csr0 & LE_C0_TINT)
- lance_tx (dev);
+ lance_tx(dev);
/* Log misc errors. */
if (csr0 & LE_C0_BABL)
@@ -458,22 +444,22 @@
if (csr0 & LE_C0_MISS)
dev->stats.rx_errors++; /* Missed a Rx frame. */
if (csr0 & LE_C0_MERR) {
- printk(KERN_ERR "%s: Bus master arbitration failure, status "
- "%4.4x.\n", dev->name, csr0);
+ netdev_err(dev, "Bus master arbitration failure, status %04x\n",
+ csr0);
/* Restart the chip. */
ll->rdp = LE_C0_STRT;
}
- if (netif_queue_stopped(dev) && TX_BUFFS_AVAIL > 0)
+ if (netif_queue_stopped(dev) && lance_tx_buffs_avail(lp) > 0)
netif_wake_queue(dev);
ll->rap = LE_CSR0;
- ll->rdp = LE_C0_BABL|LE_C0_CERR|LE_C0_MISS|LE_C0_MERR|
- LE_C0_IDON|LE_C0_INEA;
+ ll->rdp = (LE_C0_BABL | LE_C0_CERR | LE_C0_MISS | LE_C0_MERR |
+ LE_C0_IDON | LE_C0_INEA);
return IRQ_HANDLED;
}
-static int lance_open (struct net_device *dev)
+static int lance_open(struct net_device *dev)
{
struct lance_private *lp = netdev_priv(dev);
volatile struct lance_regs *ll = lp->ll;
@@ -486,17 +472,18 @@
/* Install the Interrupt handler */
ret = request_irq(IRQ_AMIGA_PORTS, lance_interrupt, IRQF_SHARED,
dev->name, dev);
- if (ret) return ret;
+ if (ret)
+ return ret;
- load_csrs (lp);
- lance_init_ring (dev);
+ load_csrs(lp);
+ lance_init_ring(dev);
netif_start_queue(dev);
- return init_restart_lance (lp);
+ return init_restart_lance(lp);
}
-static int lance_close (struct net_device *dev)
+static int lance_close(struct net_device *dev)
{
struct lance_private *lp = netdev_priv(dev);
volatile struct lance_regs *ll = lp->ll;
@@ -512,7 +499,7 @@
return 0;
}
-static inline int lance_reset (struct net_device *dev)
+static inline int lance_reset(struct net_device *dev)
{
struct lance_private *lp = netdev_priv(dev);
volatile struct lance_regs *ll = lp->ll;
@@ -522,16 +509,15 @@
ll->rap = LE_CSR0;
ll->rdp = LE_C0_STOP;
- load_csrs (lp);
+ load_csrs(lp);
- lance_init_ring (dev);
+ lance_init_ring(dev);
dev->trans_start = jiffies; /* prevent tx timeout */
netif_start_queue(dev);
- status = init_restart_lance (lp);
-#ifdef DEBUG_DRIVER
- printk(KERN_DEBUG "Lance restart=%d\n", status);
-#endif
+ status = init_restart_lance(lp);
+ netdev_dbg(dev, "Lance restart=%d\n", status);
+
return status;
}
@@ -540,14 +526,13 @@
struct lance_private *lp = netdev_priv(dev);
volatile struct lance_regs *ll = lp->ll;
- printk(KERN_ERR "%s: transmit timed out, status %04x, reset\n",
- dev->name, ll->rdp);
+ netdev_err(dev, "transmit timed out, status %04x, reset\n", ll->rdp);
lance_reset(dev);
netif_wake_queue(dev);
}
-static netdev_tx_t lance_start_xmit (struct sk_buff *skb,
- struct net_device *dev)
+static netdev_tx_t lance_start_xmit(struct sk_buff *skb,
+ struct net_device *dev)
{
struct lance_private *lp = netdev_priv(dev);
volatile struct lance_regs *ll = lp->ll;
@@ -562,33 +547,33 @@
local_irq_save(flags);
- if (!TX_BUFFS_AVAIL){
+ if (!lance_tx_buffs_avail(lp)) {
local_irq_restore(flags);
return NETDEV_TX_LOCKED;
}
-#ifdef DEBUG_DRIVER
+#ifdef DEBUG
/* dump the packet */
print_hex_dump(KERN_DEBUG, "skb->data: ", DUMP_PREFIX_NONE,
16, 1, skb->data, 64, true);
#endif
entry = lp->tx_new & lp->tx_ring_mod_mask;
- ib->btx_ring [entry].length = (-skblen) | 0xf000;
- ib->btx_ring [entry].misc = 0;
+ ib->btx_ring[entry].length = (-skblen) | 0xf000;
+ ib->btx_ring[entry].misc = 0;
- skb_copy_from_linear_data(skb, (void *)&ib->tx_buf [entry][0], skblen);
+ skb_copy_from_linear_data(skb, (void *)&ib->tx_buf[entry][0], skblen);
/* Now, give the packet to the lance */
- ib->btx_ring [entry].tmd1_bits = (LE_T1_POK|LE_T1_OWN);
+ ib->btx_ring[entry].tmd1_bits = (LE_T1_POK | LE_T1_OWN);
lp->tx_new = (lp->tx_new+1) & lp->tx_ring_mod_mask;
dev->stats.tx_bytes += skblen;
- if (TX_BUFFS_AVAIL <= 0)
+ if (lance_tx_buffs_avail(lp) <= 0)
netif_stop_queue(dev);
/* Kick the lance: transmit now */
ll->rdp = LE_C0_INEA | LE_C0_TDMD;
- dev_kfree_skb (skb);
+ dev_kfree_skb(skb);
local_irq_restore(flags);
@@ -596,7 +581,7 @@
}
/* taken from the depca driver */
-static void lance_load_multicast (struct net_device *dev)
+static void lance_load_multicast(struct net_device *dev)
{
struct lance_private *lp = netdev_priv(dev);
volatile struct lance_init_block *ib = lp->init_block;
@@ -606,14 +591,14 @@
u32 crc;
/* set all multicast bits */
- if (dev->flags & IFF_ALLMULTI){
- ib->filter [0] = 0xffffffff;
- ib->filter [1] = 0xffffffff;
+ if (dev->flags & IFF_ALLMULTI) {
+ ib->filter[0] = 0xffffffff;
+ ib->filter[1] = 0xffffffff;
return;
}
/* clear the multicast filter */
- ib->filter [0] = 0;
- ib->filter [1] = 0;
+ ib->filter[0] = 0;
+ ib->filter[1] = 0;
/* Add addresses */
netdev_for_each_mc_addr(ha, dev) {
@@ -625,11 +610,11 @@
crc = ether_crc_le(6, addrs);
crc = crc >> 26;
- mcast_table [crc >> 4] |= 1 << (crc & 0xf);
+ mcast_table[crc >> 4] |= 1 << (crc & 0xf);
}
}
-static void lance_set_multicast (struct net_device *dev)
+static void lance_set_multicast(struct net_device *dev)
{
struct lance_private *lp = netdev_priv(dev);
volatile struct lance_init_block *ib = lp->init_block;
@@ -648,16 +633,16 @@
ll->rap = LE_CSR0;
ll->rdp = LE_C0_STOP;
- lance_init_ring (dev);
+ lance_init_ring(dev);
if (dev->flags & IFF_PROMISC) {
ib->mode |= LE_MO_PROM;
} else {
ib->mode &= ~LE_MO_PROM;
- lance_load_multicast (dev);
+ lance_load_multicast(dev);
}
- load_csrs (lp);
- init_restart_lance (lp);
+ load_csrs(lp);
+ init_restart_lance(lp);
netif_wake_queue(dev);
}
@@ -697,14 +682,12 @@
{
struct net_device *dev;
struct lance_private *priv;
- unsigned long board, base_addr, mem_start;
+ unsigned long board = z->resource.start;
+ unsigned long base_addr = board + A2065_LANCE;
+ unsigned long mem_start = board + A2065_RAM;
struct resource *r1, *r2;
int err;
- board = z->resource.start;
- base_addr = board+A2065_LANCE;
- mem_start = board+A2065_RAM;
-
r1 = request_mem_region(base_addr, sizeof(struct lance_regs),
"Am7990");
if (!r1)
@@ -735,12 +718,12 @@
dev->dev_addr[1] = 0x00;
dev->dev_addr[2] = 0x9f;
}
- dev->dev_addr[3] = (z->rom.er_SerialNumber>>16) & 0xff;
- dev->dev_addr[4] = (z->rom.er_SerialNumber>>8) & 0xff;
+ dev->dev_addr[3] = (z->rom.er_SerialNumber >> 16) & 0xff;
+ dev->dev_addr[4] = (z->rom.er_SerialNumber >> 8) & 0xff;
dev->dev_addr[5] = z->rom.er_SerialNumber & 0xff;
dev->base_addr = ZTWO_VADDR(base_addr);
dev->mem_start = ZTWO_VADDR(mem_start);
- dev->mem_end = dev->mem_start+A2065_RAM_SIZE;
+ dev->mem_end = dev->mem_start + A2065_RAM_SIZE;
priv->ll = (volatile struct lance_regs *)dev->base_addr;
priv->init_block = (struct lance_init_block *)dev->mem_start;
@@ -760,7 +743,7 @@
init_timer(&priv->multicast_timer);
priv->multicast_timer.data = (unsigned long) dev;
priv->multicast_timer.function =
- (void (*)(unsigned long)) &lance_set_multicast;
+ (void (*)(unsigned long))lance_set_multicast;
err = register_netdev(dev);
if (err) {
@@ -771,8 +754,8 @@
}
zorro_set_drvdata(z, dev);
- printk(KERN_INFO "%s: A2065 at 0x%08lx, Ethernet Address "
- "%pM\n", dev->name, board, dev->dev_addr);
+ netdev_info(dev, "A2065 at 0x%08lx, Ethernet Address %pM\n",
+ board, dev->dev_addr);
return 0;
}
diff --git a/drivers/net/ac3200.c b/drivers/net/ac3200.c
index 5181e93..f07b2e9 100644
--- a/drivers/net/ac3200.c
+++ b/drivers/net/ac3200.c
@@ -32,6 +32,7 @@
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <asm/system.h>
#include <asm/io.h>
diff --git a/drivers/net/acenic.h b/drivers/net/acenic.h
index 0681da7..fd25a3b 100644
--- a/drivers/net/acenic.h
+++ b/drivers/net/acenic.h
@@ -1,5 +1,6 @@
#ifndef _ACENIC_H_
#define _ACENIC_H_
+#include <linux/interrupt.h>
/*
diff --git a/drivers/net/amd8111e.c b/drivers/net/amd8111e.c
index 241b185..db6d2da 100644
--- a/drivers/net/amd8111e.c
+++ b/drivers/net/amd8111e.c
@@ -75,6 +75,7 @@
#include <linux/compiler.h>
#include <linux/delay.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/pci.h>
#include <linux/netdevice.h>
@@ -1958,7 +1959,7 @@
IPG_CONVERGE_JIFFIES;
lp->ipg_data.ipg = DEFAULT_IPG;
lp->ipg_data.ipg_state = CSTATE;
- };
+ }
/* display driver and device information */
diff --git a/drivers/net/apne.c b/drivers/net/apne.c
index 2fe60f1..5477373 100644
--- a/drivers/net/apne.c
+++ b/drivers/net/apne.c
@@ -36,6 +36,7 @@
#include <linux/delay.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
+#include <linux/interrupt.h>
#include <linux/jiffies.h>
#include <asm/system.h>
diff --git a/drivers/net/appletalk/ltpc.c b/drivers/net/appletalk/ltpc.c
index e69eead..34ffb54 100644
--- a/drivers/net/appletalk/ltpc.c
+++ b/drivers/net/appletalk/ltpc.c
@@ -652,9 +652,9 @@
int ret;
if(i) {
- qels[i].cbuf = (unsigned char *) cbuf;
+ qels[i].cbuf = cbuf;
qels[i].cbuflen = cbuflen;
- qels[i].dbuf = (unsigned char *) dbuf;
+ qels[i].dbuf = dbuf;
qels[i].dbuflen = dbuflen;
qels[i].QWrite = 1;
qels[i].mailbox = i; /* this should be initted rather */
@@ -676,9 +676,9 @@
int ret;
if(i) {
- qels[i].cbuf = (unsigned char *) cbuf;
+ qels[i].cbuf = cbuf;
qels[i].cbuflen = cbuflen;
- qels[i].dbuf = (unsigned char *) dbuf;
+ qels[i].dbuf = dbuf;
qels[i].dbuflen = dbuflen;
qels[i].QWrite = 0;
qels[i].mailbox = i; /* this should be initted rather */
diff --git a/drivers/net/arcnet/arc-rimi.c b/drivers/net/arcnet/arc-rimi.c
index 9efbbba..25197b6 100644
--- a/drivers/net/arcnet/arc-rimi.c
+++ b/drivers/net/arcnet/arc-rimi.c
@@ -32,6 +32,7 @@
#include <linux/netdevice.h>
#include <linux/bootmem.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <asm/io.h>
#include <linux/arcdevice.h>
diff --git a/drivers/net/arcnet/com20020-isa.c b/drivers/net/arcnet/com20020-isa.c
index 3727282..45c61a2 100644
--- a/drivers/net/arcnet/com20020-isa.c
+++ b/drivers/net/arcnet/com20020-isa.c
@@ -34,6 +34,7 @@
#include <linux/delay.h>
#include <linux/netdevice.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/bootmem.h>
#include <linux/arcdevice.h>
#include <linux/com20020.h>
diff --git a/drivers/net/arcnet/com20020-pci.c b/drivers/net/arcnet/com20020-pci.c
index 48a1dbf..d427493 100644
--- a/drivers/net/arcnet/com20020-pci.c
+++ b/drivers/net/arcnet/com20020-pci.c
@@ -34,6 +34,7 @@
#include <linux/errno.h>
#include <linux/netdevice.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/pci.h>
#include <linux/arcdevice.h>
#include <linux/com20020.h>
diff --git a/drivers/net/arcnet/com20020.c b/drivers/net/arcnet/com20020.c
index c9e4594..7bfb91f 100644
--- a/drivers/net/arcnet/com20020.c
+++ b/drivers/net/arcnet/com20020.c
@@ -33,6 +33,7 @@
#include <linux/delay.h>
#include <linux/netdevice.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/arcdevice.h>
#include <linux/com20020.h>
diff --git a/drivers/net/arcnet/com90io.c b/drivers/net/arcnet/com90io.c
index eb27976..487d780 100644
--- a/drivers/net/arcnet/com90io.c
+++ b/drivers/net/arcnet/com90io.c
@@ -33,6 +33,7 @@
#include <linux/netdevice.h>
#include <linux/bootmem.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <asm/io.h>
#include <linux/arcdevice.h>
diff --git a/drivers/net/arcnet/com90xx.c b/drivers/net/arcnet/com90xx.c
index f3b46f7..b80fbe4 100644
--- a/drivers/net/arcnet/com90xx.c
+++ b/drivers/net/arcnet/com90xx.c
@@ -27,6 +27,7 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/delay.h>
#include <linux/netdevice.h>
diff --git a/drivers/net/ariadne.c b/drivers/net/ariadne.c
index b7f45cd..7ed78f4 100644
--- a/drivers/net/ariadne.c
+++ b/drivers/net/ariadne.c
@@ -34,6 +34,9 @@
* - an MC68230 Parallel Interface/Timer configured as 2 parallel ports
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+/*#define DEBUG*/
+
#include <linux/module.h>
#include <linux/stddef.h>
#include <linux/kernel.h>
@@ -54,106 +57,647 @@
#include "ariadne.h"
-
#ifdef ARIADNE_DEBUG
int ariadne_debug = ARIADNE_DEBUG;
#else
int ariadne_debug = 1;
#endif
+/* Macros to Fix Endianness problems */
- /*
- * Macros to Fix Endianness problems
- */
+/* Swap the Bytes in a WORD */
+#define swapw(x) (((x >> 8) & 0x00ff) | ((x << 8) & 0xff00))
+/* Get the Low BYTE in a WORD */
+#define lowb(x) (x & 0xff)
+/* Get the Swapped High WORD in a LONG */
+#define swhighw(x) ((((x) >> 8) & 0xff00) | (((x) >> 24) & 0x00ff))
+/* Get the Swapped Low WORD in a LONG */
+#define swloww(x) ((((x) << 8) & 0xff00) | (((x) >> 8) & 0x00ff))
- /* Swap the Bytes in a WORD */
-#define swapw(x) (((x>>8)&0x00ff)|((x<<8)&0xff00))
- /* Get the Low BYTE in a WORD */
-#define lowb(x) (x&0xff)
- /* Get the Swapped High WORD in a LONG */
-#define swhighw(x) ((((x)>>8)&0xff00)|(((x)>>24)&0x00ff))
- /* Get the Swapped Low WORD in a LONG */
-#define swloww(x) ((((x)<<8)&0xff00)|(((x)>>8)&0x00ff))
-
-
- /*
- * Transmit/Receive Ring Definitions
- */
+/* Transmit/Receive Ring Definitions */
#define TX_RING_SIZE 5
#define RX_RING_SIZE 16
#define PKT_BUF_SIZE 1520
-
- /*
- * Private Device Data
- */
+/* Private Device Data */
struct ariadne_private {
- volatile struct TDRE *tx_ring[TX_RING_SIZE];
- volatile struct RDRE *rx_ring[RX_RING_SIZE];
- volatile u_short *tx_buff[TX_RING_SIZE];
- volatile u_short *rx_buff[RX_RING_SIZE];
- int cur_tx, cur_rx; /* The next free ring entry */
- int dirty_tx; /* The ring entries to be free()ed. */
- char tx_full;
+ volatile struct TDRE *tx_ring[TX_RING_SIZE];
+ volatile struct RDRE *rx_ring[RX_RING_SIZE];
+ volatile u_short *tx_buff[TX_RING_SIZE];
+ volatile u_short *rx_buff[RX_RING_SIZE];
+ int cur_tx, cur_rx; /* The next free ring entry */
+ int dirty_tx; /* The ring entries to be free()ed */
+ char tx_full;
};
-
- /*
- * Structure Created in the Ariadne's RAM Buffer
- */
+/* Structure Created in the Ariadne's RAM Buffer */
struct lancedata {
- struct TDRE tx_ring[TX_RING_SIZE];
- struct RDRE rx_ring[RX_RING_SIZE];
- u_short tx_buff[TX_RING_SIZE][PKT_BUF_SIZE/sizeof(u_short)];
- u_short rx_buff[RX_RING_SIZE][PKT_BUF_SIZE/sizeof(u_short)];
+ struct TDRE tx_ring[TX_RING_SIZE];
+ struct RDRE rx_ring[RX_RING_SIZE];
+ u_short tx_buff[TX_RING_SIZE][PKT_BUF_SIZE / sizeof(u_short)];
+ u_short rx_buff[RX_RING_SIZE][PKT_BUF_SIZE / sizeof(u_short)];
};
-static int ariadne_open(struct net_device *dev);
-static void ariadne_init_ring(struct net_device *dev);
-static netdev_tx_t ariadne_start_xmit(struct sk_buff *skb,
- struct net_device *dev);
-static void ariadne_tx_timeout(struct net_device *dev);
-static int ariadne_rx(struct net_device *dev);
-static void ariadne_reset(struct net_device *dev);
-static irqreturn_t ariadne_interrupt(int irq, void *data);
-static int ariadne_close(struct net_device *dev);
-static struct net_device_stats *ariadne_get_stats(struct net_device *dev);
-static void set_multicast_list(struct net_device *dev);
-
-
static void memcpyw(volatile u_short *dest, u_short *src, int len)
{
- while (len >= 2) {
- *(dest++) = *(src++);
- len -= 2;
- }
- if (len == 1)
- *dest = (*(u_char *)src)<<8;
+ while (len >= 2) {
+ *(dest++) = *(src++);
+ len -= 2;
+ }
+ if (len == 1)
+ *dest = (*(u_char *)src) << 8;
+}
+
+static void ariadne_init_ring(struct net_device *dev)
+{
+ struct ariadne_private *priv = netdev_priv(dev);
+ volatile struct lancedata *lancedata = (struct lancedata *)dev->mem_start;
+ int i;
+
+ netif_stop_queue(dev);
+
+ priv->tx_full = 0;
+ priv->cur_rx = priv->cur_tx = 0;
+ priv->dirty_tx = 0;
+
+ /* Set up TX Ring */
+ for (i = 0; i < TX_RING_SIZE; i++) {
+ volatile struct TDRE *t = &lancedata->tx_ring[i];
+ t->TMD0 = swloww(ARIADNE_RAM +
+ offsetof(struct lancedata, tx_buff[i]));
+ t->TMD1 = swhighw(ARIADNE_RAM +
+ offsetof(struct lancedata, tx_buff[i])) |
+ TF_STP | TF_ENP;
+ t->TMD2 = swapw((u_short)-PKT_BUF_SIZE);
+ t->TMD3 = 0;
+ priv->tx_ring[i] = &lancedata->tx_ring[i];
+ priv->tx_buff[i] = lancedata->tx_buff[i];
+ netdev_dbg(dev, "TX Entry %2d at %p, Buf at %p\n",
+ i, &lancedata->tx_ring[i], lancedata->tx_buff[i]);
+ }
+
+ /* Set up RX Ring */
+ for (i = 0; i < RX_RING_SIZE; i++) {
+ volatile struct RDRE *r = &lancedata->rx_ring[i];
+ r->RMD0 = swloww(ARIADNE_RAM +
+ offsetof(struct lancedata, rx_buff[i]));
+ r->RMD1 = swhighw(ARIADNE_RAM +
+ offsetof(struct lancedata, rx_buff[i])) |
+ RF_OWN;
+ r->RMD2 = swapw((u_short)-PKT_BUF_SIZE);
+ r->RMD3 = 0x0000;
+ priv->rx_ring[i] = &lancedata->rx_ring[i];
+ priv->rx_buff[i] = lancedata->rx_buff[i];
+ netdev_dbg(dev, "RX Entry %2d at %p, Buf at %p\n",
+ i, &lancedata->rx_ring[i], lancedata->rx_buff[i]);
+ }
+}
+
+static int ariadne_rx(struct net_device *dev)
+{
+ struct ariadne_private *priv = netdev_priv(dev);
+ int entry = priv->cur_rx % RX_RING_SIZE;
+ int i;
+
+ /* If we own the next entry, it's a new packet. Send it up */
+ while (!(lowb(priv->rx_ring[entry]->RMD1) & RF_OWN)) {
+ int status = lowb(priv->rx_ring[entry]->RMD1);
+
+ if (status != (RF_STP | RF_ENP)) { /* There was an error */
+ /* There is a tricky error noted by
+ * John Murphy <murf@perftech.com> to Russ Nelson:
+ * Even with full-sized buffers it's possible for a
+ * jabber packet to use two buffers, with only the
+ * last correctly noting the error
+ */
+ /* Only count a general error at the end of a packet */
+ if (status & RF_ENP)
+ dev->stats.rx_errors++;
+ if (status & RF_FRAM)
+ dev->stats.rx_frame_errors++;
+ if (status & RF_OFLO)
+ dev->stats.rx_over_errors++;
+ if (status & RF_CRC)
+ dev->stats.rx_crc_errors++;
+ if (status & RF_BUFF)
+ dev->stats.rx_fifo_errors++;
+ priv->rx_ring[entry]->RMD1 &= 0xff00 | RF_STP | RF_ENP;
+ } else {
+ /* Malloc up new buffer, compatible with net-3 */
+ short pkt_len = swapw(priv->rx_ring[entry]->RMD3);
+ struct sk_buff *skb;
+
+ skb = dev_alloc_skb(pkt_len + 2);
+ if (skb == NULL) {
+ netdev_warn(dev, "Memory squeeze, deferring packet\n");
+ for (i = 0; i < RX_RING_SIZE; i++)
+ if (lowb(priv->rx_ring[(entry + i) % RX_RING_SIZE]->RMD1) & RF_OWN)
+ break;
+
+ if (i > RX_RING_SIZE - 2) {
+ dev->stats.rx_dropped++;
+ priv->rx_ring[entry]->RMD1 |= RF_OWN;
+ priv->cur_rx++;
+ }
+ break;
+ }
+
+
+ skb_reserve(skb, 2); /* 16 byte align */
+ skb_put(skb, pkt_len); /* Make room */
+ skb_copy_to_linear_data(skb,
+ (const void *)priv->rx_buff[entry],
+ pkt_len);
+ skb->protocol = eth_type_trans(skb, dev);
+ netdev_dbg(dev, "RX pkt type 0x%04x from %pM to %pM data 0x%08x len %d\n",
+ ((u_short *)skb->data)[6],
+ skb->data + 6, skb->data,
+ (int)skb->data, (int)skb->len);
+
+ netif_rx(skb);
+ dev->stats.rx_packets++;
+ dev->stats.rx_bytes += pkt_len;
+ }
+
+ priv->rx_ring[entry]->RMD1 |= RF_OWN;
+ entry = (++priv->cur_rx) % RX_RING_SIZE;
+ }
+
+ priv->cur_rx = priv->cur_rx % RX_RING_SIZE;
+
+ /* We should check that at least two ring entries are free.
+ * If not, we should free one and mark stats->rx_dropped++
+ */
+
+ return 0;
+}
+
+static irqreturn_t ariadne_interrupt(int irq, void *data)
+{
+ struct net_device *dev = (struct net_device *)data;
+ volatile struct Am79C960 *lance = (struct Am79C960 *)dev->base_addr;
+ struct ariadne_private *priv;
+ int csr0, boguscnt;
+ int handled = 0;
+
+ lance->RAP = CSR0; /* PCnet-ISA Controller Status */
+
+ if (!(lance->RDP & INTR)) /* Check if any interrupt has been */
+ return IRQ_NONE; /* generated by the board */
+
+ priv = netdev_priv(dev);
+
+ boguscnt = 10;
+ while ((csr0 = lance->RDP) & (ERR | RINT | TINT) && --boguscnt >= 0) {
+ /* Acknowledge all of the current interrupt sources ASAP */
+ lance->RDP = csr0 & ~(INEA | TDMD | STOP | STRT | INIT);
+
+#ifdef DEBUG
+ if (ariadne_debug > 5) {
+ netdev_dbg(dev, "interrupt csr0=%#02x new csr=%#02x [",
+ csr0, lance->RDP);
+ if (csr0 & INTR)
+ pr_cont(" INTR");
+ if (csr0 & INEA)
+ pr_cont(" INEA");
+ if (csr0 & RXON)
+ pr_cont(" RXON");
+ if (csr0 & TXON)
+ pr_cont(" TXON");
+ if (csr0 & TDMD)
+ pr_cont(" TDMD");
+ if (csr0 & STOP)
+ pr_cont(" STOP");
+ if (csr0 & STRT)
+ pr_cont(" STRT");
+ if (csr0 & INIT)
+ pr_cont(" INIT");
+ if (csr0 & ERR)
+ pr_cont(" ERR");
+ if (csr0 & BABL)
+ pr_cont(" BABL");
+ if (csr0 & CERR)
+ pr_cont(" CERR");
+ if (csr0 & MISS)
+ pr_cont(" MISS");
+ if (csr0 & MERR)
+ pr_cont(" MERR");
+ if (csr0 & RINT)
+ pr_cont(" RINT");
+ if (csr0 & TINT)
+ pr_cont(" TINT");
+ if (csr0 & IDON)
+ pr_cont(" IDON");
+ pr_cont(" ]\n");
+ }
+#endif
+
+ if (csr0 & RINT) { /* Rx interrupt */
+ handled = 1;
+ ariadne_rx(dev);
+ }
+
+ if (csr0 & TINT) { /* Tx-done interrupt */
+ int dirty_tx = priv->dirty_tx;
+
+ handled = 1;
+ while (dirty_tx < priv->cur_tx) {
+ int entry = dirty_tx % TX_RING_SIZE;
+ int status = lowb(priv->tx_ring[entry]->TMD1);
+
+ if (status & TF_OWN)
+ break; /* It still hasn't been Txed */
+
+ priv->tx_ring[entry]->TMD1 &= 0xff00;
+
+ if (status & TF_ERR) {
+ /* There was an major error, log it */
+ int err_status = priv->tx_ring[entry]->TMD3;
+ dev->stats.tx_errors++;
+ if (err_status & EF_RTRY)
+ dev->stats.tx_aborted_errors++;
+ if (err_status & EF_LCAR)
+ dev->stats.tx_carrier_errors++;
+ if (err_status & EF_LCOL)
+ dev->stats.tx_window_errors++;
+ if (err_status & EF_UFLO) {
+ /* Ackk! On FIFO errors the Tx unit is turned off! */
+ dev->stats.tx_fifo_errors++;
+ /* Remove this verbosity later! */
+ netdev_err(dev, "Tx FIFO error! Status %04x\n",
+ csr0);
+ /* Restart the chip */
+ lance->RDP = STRT;
+ }
+ } else {
+ if (status & (TF_MORE | TF_ONE))
+ dev->stats.collisions++;
+ dev->stats.tx_packets++;
+ }
+ dirty_tx++;
+ }
+
+#ifndef final_version
+ if (priv->cur_tx - dirty_tx >= TX_RING_SIZE) {
+ netdev_err(dev, "out-of-sync dirty pointer, %d vs. %d, full=%d\n",
+ dirty_tx, priv->cur_tx,
+ priv->tx_full);
+ dirty_tx += TX_RING_SIZE;
+ }
+#endif
+
+ if (priv->tx_full && netif_queue_stopped(dev) &&
+ dirty_tx > priv->cur_tx - TX_RING_SIZE + 2) {
+ /* The ring is no longer full */
+ priv->tx_full = 0;
+ netif_wake_queue(dev);
+ }
+
+ priv->dirty_tx = dirty_tx;
+ }
+
+ /* Log misc errors */
+ if (csr0 & BABL) {
+ handled = 1;
+ dev->stats.tx_errors++; /* Tx babble */
+ }
+ if (csr0 & MISS) {
+ handled = 1;
+ dev->stats.rx_errors++; /* Missed a Rx frame */
+ }
+ if (csr0 & MERR) {
+ handled = 1;
+ netdev_err(dev, "Bus master arbitration failure, status %04x\n",
+ csr0);
+ /* Restart the chip */
+ lance->RDP = STRT;
+ }
+ }
+
+ /* Clear any other interrupt, and set interrupt enable */
+ lance->RAP = CSR0; /* PCnet-ISA Controller Status */
+ lance->RDP = INEA | BABL | CERR | MISS | MERR | IDON;
+
+ if (ariadne_debug > 4)
+ netdev_dbg(dev, "exiting interrupt, csr%d=%#04x\n",
+ lance->RAP, lance->RDP);
+
+ return IRQ_RETVAL(handled);
+}
+
+static int ariadne_open(struct net_device *dev)
+{
+ volatile struct Am79C960 *lance = (struct Am79C960 *)dev->base_addr;
+ u_short in;
+ u_long version;
+ int i;
+
+ /* Reset the LANCE */
+ in = lance->Reset;
+
+ /* Stop the LANCE */
+ lance->RAP = CSR0; /* PCnet-ISA Controller Status */
+ lance->RDP = STOP;
+
+ /* Check the LANCE version */
+ lance->RAP = CSR88; /* Chip ID */
+ version = swapw(lance->RDP);
+ lance->RAP = CSR89; /* Chip ID */
+ version |= swapw(lance->RDP) << 16;
+ if ((version & 0x00000fff) != 0x00000003) {
+ pr_warn("Couldn't find AMD Ethernet Chip\n");
+ return -EAGAIN;
+ }
+ if ((version & 0x0ffff000) != 0x00003000) {
+ pr_warn("Couldn't find Am79C960 (Wrong part number = %ld)\n",
+ (version & 0x0ffff000) >> 12);
+ return -EAGAIN;
+ }
+
+ netdev_dbg(dev, "Am79C960 (PCnet-ISA) Revision %ld\n",
+ (version & 0xf0000000) >> 28);
+
+ ariadne_init_ring(dev);
+
+ /* Miscellaneous Stuff */
+ lance->RAP = CSR3; /* Interrupt Masks and Deferral Control */
+ lance->RDP = 0x0000;
+ lance->RAP = CSR4; /* Test and Features Control */
+ lance->RDP = DPOLL | APAD_XMT | MFCOM | RCVCCOM | TXSTRTM | JABM;
+
+ /* Set the Multicast Table */
+ lance->RAP = CSR8; /* Logical Address Filter, LADRF[15:0] */
+ lance->RDP = 0x0000;
+ lance->RAP = CSR9; /* Logical Address Filter, LADRF[31:16] */
+ lance->RDP = 0x0000;
+ lance->RAP = CSR10; /* Logical Address Filter, LADRF[47:32] */
+ lance->RDP = 0x0000;
+ lance->RAP = CSR11; /* Logical Address Filter, LADRF[63:48] */
+ lance->RDP = 0x0000;
+
+ /* Set the Ethernet Hardware Address */
+ lance->RAP = CSR12; /* Physical Address Register, PADR[15:0] */
+ lance->RDP = ((u_short *)&dev->dev_addr[0])[0];
+ lance->RAP = CSR13; /* Physical Address Register, PADR[31:16] */
+ lance->RDP = ((u_short *)&dev->dev_addr[0])[1];
+ lance->RAP = CSR14; /* Physical Address Register, PADR[47:32] */
+ lance->RDP = ((u_short *)&dev->dev_addr[0])[2];
+
+ /* Set the Init Block Mode */
+ lance->RAP = CSR15; /* Mode Register */
+ lance->RDP = 0x0000;
+
+ /* Set the Transmit Descriptor Ring Pointer */
+ lance->RAP = CSR30; /* Base Address of Transmit Ring */
+ lance->RDP = swloww(ARIADNE_RAM + offsetof(struct lancedata, tx_ring));
+ lance->RAP = CSR31; /* Base Address of transmit Ring */
+ lance->RDP = swhighw(ARIADNE_RAM + offsetof(struct lancedata, tx_ring));
+
+ /* Set the Receive Descriptor Ring Pointer */
+ lance->RAP = CSR24; /* Base Address of Receive Ring */
+ lance->RDP = swloww(ARIADNE_RAM + offsetof(struct lancedata, rx_ring));
+ lance->RAP = CSR25; /* Base Address of Receive Ring */
+ lance->RDP = swhighw(ARIADNE_RAM + offsetof(struct lancedata, rx_ring));
+
+ /* Set the Number of RX and TX Ring Entries */
+ lance->RAP = CSR76; /* Receive Ring Length */
+ lance->RDP = swapw(((u_short)-RX_RING_SIZE));
+ lance->RAP = CSR78; /* Transmit Ring Length */
+ lance->RDP = swapw(((u_short)-TX_RING_SIZE));
+
+ /* Enable Media Interface Port Auto Select (10BASE-2/10BASE-T) */
+ lance->RAP = ISACSR2; /* Miscellaneous Configuration */
+ lance->IDP = ASEL;
+
+ /* LED Control */
+ lance->RAP = ISACSR5; /* LED1 Status */
+ lance->IDP = PSE|XMTE;
+ lance->RAP = ISACSR6; /* LED2 Status */
+ lance->IDP = PSE|COLE;
+ lance->RAP = ISACSR7; /* LED3 Status */
+ lance->IDP = PSE|RCVE;
+
+ netif_start_queue(dev);
+
+ i = request_irq(IRQ_AMIGA_PORTS, ariadne_interrupt, IRQF_SHARED,
+ dev->name, dev);
+ if (i)
+ return i;
+
+ lance->RAP = CSR0; /* PCnet-ISA Controller Status */
+ lance->RDP = INEA | STRT;
+
+ return 0;
+}
+
+static int ariadne_close(struct net_device *dev)
+{
+ volatile struct Am79C960 *lance = (struct Am79C960 *)dev->base_addr;
+
+ netif_stop_queue(dev);
+
+ lance->RAP = CSR112; /* Missed Frame Count */
+ dev->stats.rx_missed_errors = swapw(lance->RDP);
+ lance->RAP = CSR0; /* PCnet-ISA Controller Status */
+
+ if (ariadne_debug > 1) {
+ netdev_dbg(dev, "Shutting down ethercard, status was %02x\n",
+ lance->RDP);
+ netdev_dbg(dev, "%lu packets missed\n",
+ dev->stats.rx_missed_errors);
+ }
+
+ /* We stop the LANCE here -- it occasionally polls memory if we don't */
+ lance->RDP = STOP;
+
+ free_irq(IRQ_AMIGA_PORTS, dev);
+
+ return 0;
+}
+
+static inline void ariadne_reset(struct net_device *dev)
+{
+ volatile struct Am79C960 *lance = (struct Am79C960 *)dev->base_addr;
+
+ lance->RAP = CSR0; /* PCnet-ISA Controller Status */
+ lance->RDP = STOP;
+ ariadne_init_ring(dev);
+ lance->RDP = INEA | STRT;
+ netif_start_queue(dev);
+}
+
+static void ariadne_tx_timeout(struct net_device *dev)
+{
+ volatile struct Am79C960 *lance = (struct Am79C960 *)dev->base_addr;
+
+ netdev_err(dev, "transmit timed out, status %04x, resetting\n",
+ lance->RDP);
+ ariadne_reset(dev);
+ netif_wake_queue(dev);
+}
+
+static netdev_tx_t ariadne_start_xmit(struct sk_buff *skb,
+ struct net_device *dev)
+{
+ struct ariadne_private *priv = netdev_priv(dev);
+ volatile struct Am79C960 *lance = (struct Am79C960 *)dev->base_addr;
+ int entry;
+ unsigned long flags;
+ int len = skb->len;
+
+#if 0
+ if (ariadne_debug > 3) {
+ lance->RAP = CSR0; /* PCnet-ISA Controller Status */
+ netdev_dbg(dev, "%s: csr0 %04x\n", __func__, lance->RDP);
+ lance->RDP = 0x0000;
+ }
+#endif
+
+ /* FIXME: is the 79C960 new enough to do its own padding right ? */
+ if (skb->len < ETH_ZLEN) {
+ if (skb_padto(skb, ETH_ZLEN))
+ return NETDEV_TX_OK;
+ len = ETH_ZLEN;
+ }
+
+ /* Fill in a Tx ring entry */
+
+ netdev_dbg(dev, "TX pkt type 0x%04x from %pM to %pM data 0x%08x len %d\n",
+ ((u_short *)skb->data)[6],
+ skb->data + 6, skb->data,
+ (int)skb->data, (int)skb->len);
+
+ local_irq_save(flags);
+
+ entry = priv->cur_tx % TX_RING_SIZE;
+
+ /* Caution: the write order is important here, set the base address with
+ the "ownership" bits last */
+
+ priv->tx_ring[entry]->TMD2 = swapw((u_short)-skb->len);
+ priv->tx_ring[entry]->TMD3 = 0x0000;
+ memcpyw(priv->tx_buff[entry], (u_short *)skb->data, len);
+
+#ifdef DEBUG
+ print_hex_dump(KERN_DEBUG, "tx_buff: ", DUMP_PREFIX_OFFSET, 16, 1,
+ (void *)priv->tx_buff[entry],
+ skb->len > 64 ? 64 : skb->len, true);
+#endif
+
+ priv->tx_ring[entry]->TMD1 = (priv->tx_ring[entry]->TMD1 & 0xff00)
+ | TF_OWN | TF_STP | TF_ENP;
+
+ dev_kfree_skb(skb);
+
+ priv->cur_tx++;
+ if ((priv->cur_tx >= TX_RING_SIZE) &&
+ (priv->dirty_tx >= TX_RING_SIZE)) {
+
+ netdev_dbg(dev, "*** Subtracting TX_RING_SIZE from cur_tx (%d) and dirty_tx (%d)\n",
+ priv->cur_tx, priv->dirty_tx);
+
+ priv->cur_tx -= TX_RING_SIZE;
+ priv->dirty_tx -= TX_RING_SIZE;
+ }
+ dev->stats.tx_bytes += len;
+
+ /* Trigger an immediate send poll */
+ lance->RAP = CSR0; /* PCnet-ISA Controller Status */
+ lance->RDP = INEA | TDMD;
+
+ if (lowb(priv->tx_ring[(entry + 1) % TX_RING_SIZE]->TMD1) != 0) {
+ netif_stop_queue(dev);
+ priv->tx_full = 1;
+ }
+ local_irq_restore(flags);
+
+ return NETDEV_TX_OK;
+}
+
+static struct net_device_stats *ariadne_get_stats(struct net_device *dev)
+{
+ volatile struct Am79C960 *lance = (struct Am79C960 *)dev->base_addr;
+ short saved_addr;
+ unsigned long flags;
+
+ local_irq_save(flags);
+ saved_addr = lance->RAP;
+ lance->RAP = CSR112; /* Missed Frame Count */
+ dev->stats.rx_missed_errors = swapw(lance->RDP);
+ lance->RAP = saved_addr;
+ local_irq_restore(flags);
+
+ return &dev->stats;
+}
+
+/* Set or clear the multicast filter for this adaptor.
+ * num_addrs == -1 Promiscuous mode, receive all packets
+ * num_addrs == 0 Normal mode, clear multicast list
+ * num_addrs > 0 Multicast mode, receive normal and MC packets,
+ * and do best-effort filtering.
+ */
+static void set_multicast_list(struct net_device *dev)
+{
+ volatile struct Am79C960 *lance = (struct Am79C960 *)dev->base_addr;
+
+ if (!netif_running(dev))
+ return;
+
+ netif_stop_queue(dev);
+
+ /* We take the simple way out and always enable promiscuous mode */
+ lance->RAP = CSR0; /* PCnet-ISA Controller Status */
+ lance->RDP = STOP; /* Temporarily stop the lance */
+ ariadne_init_ring(dev);
+
+ if (dev->flags & IFF_PROMISC) {
+ lance->RAP = CSR15; /* Mode Register */
+ lance->RDP = PROM; /* Set promiscuous mode */
+ } else {
+ short multicast_table[4];
+ int num_addrs = netdev_mc_count(dev);
+ int i;
+ /* We don't use the multicast table,
+ * but rely on upper-layer filtering
+ */
+ memset(multicast_table, (num_addrs == 0) ? 0 : -1,
+ sizeof(multicast_table));
+ for (i = 0; i < 4; i++) {
+ lance->RAP = CSR8 + (i << 8);
+ /* Logical Address Filter */
+ lance->RDP = swapw(multicast_table[i]);
+ }
+ lance->RAP = CSR15; /* Mode Register */
+ lance->RDP = 0x0000; /* Unset promiscuous mode */
+ }
+
+ lance->RAP = CSR0; /* PCnet-ISA Controller Status */
+ lance->RDP = INEA | STRT | IDON;/* Resume normal operation */
+
+ netif_wake_queue(dev);
}
-static int __devinit ariadne_init_one(struct zorro_dev *z,
- const struct zorro_device_id *ent);
-static void __devexit ariadne_remove_one(struct zorro_dev *z);
+static void __devexit ariadne_remove_one(struct zorro_dev *z)
+{
+ struct net_device *dev = zorro_get_drvdata(z);
+ unregister_netdev(dev);
+ release_mem_region(ZTWO_PADDR(dev->base_addr), sizeof(struct Am79C960));
+ release_mem_region(ZTWO_PADDR(dev->mem_start), ARIADNE_RAM_SIZE);
+ free_netdev(dev);
+}
static struct zorro_device_id ariadne_zorro_tbl[] __devinitdata = {
- { ZORRO_PROD_VILLAGE_TRONIC_ARIADNE },
- { 0 }
+ { ZORRO_PROD_VILLAGE_TRONIC_ARIADNE },
+ { 0 }
};
MODULE_DEVICE_TABLE(zorro, ariadne_zorro_tbl);
-static struct zorro_driver ariadne_driver = {
- .name = "ariadne",
- .id_table = ariadne_zorro_tbl,
- .probe = ariadne_init_one,
- .remove = __devexit_p(ariadne_remove_one),
-};
-
static const struct net_device_ops ariadne_netdev_ops = {
.ndo_open = ariadne_open,
.ndo_stop = ariadne_close,
@@ -169,687 +713,78 @@
static int __devinit ariadne_init_one(struct zorro_dev *z,
const struct zorro_device_id *ent)
{
- unsigned long board = z->resource.start;
- unsigned long base_addr = board+ARIADNE_LANCE;
- unsigned long mem_start = board+ARIADNE_RAM;
- struct resource *r1, *r2;
- struct net_device *dev;
- struct ariadne_private *priv;
- int err;
+ unsigned long board = z->resource.start;
+ unsigned long base_addr = board + ARIADNE_LANCE;
+ unsigned long mem_start = board + ARIADNE_RAM;
+ struct resource *r1, *r2;
+ struct net_device *dev;
+ struct ariadne_private *priv;
+ int err;
- r1 = request_mem_region(base_addr, sizeof(struct Am79C960), "Am79C960");
- if (!r1)
- return -EBUSY;
- r2 = request_mem_region(mem_start, ARIADNE_RAM_SIZE, "RAM");
- if (!r2) {
- release_mem_region(base_addr, sizeof(struct Am79C960));
- return -EBUSY;
- }
-
- dev = alloc_etherdev(sizeof(struct ariadne_private));
- if (dev == NULL) {
- release_mem_region(base_addr, sizeof(struct Am79C960));
- release_mem_region(mem_start, ARIADNE_RAM_SIZE);
- return -ENOMEM;
- }
-
- priv = netdev_priv(dev);
-
- r1->name = dev->name;
- r2->name = dev->name;
-
- dev->dev_addr[0] = 0x00;
- dev->dev_addr[1] = 0x60;
- dev->dev_addr[2] = 0x30;
- dev->dev_addr[3] = (z->rom.er_SerialNumber>>16) & 0xff;
- dev->dev_addr[4] = (z->rom.er_SerialNumber>>8) & 0xff;
- dev->dev_addr[5] = z->rom.er_SerialNumber & 0xff;
- dev->base_addr = ZTWO_VADDR(base_addr);
- dev->mem_start = ZTWO_VADDR(mem_start);
- dev->mem_end = dev->mem_start+ARIADNE_RAM_SIZE;
-
- dev->netdev_ops = &ariadne_netdev_ops;
- dev->watchdog_timeo = 5*HZ;
-
- err = register_netdev(dev);
- if (err) {
- release_mem_region(base_addr, sizeof(struct Am79C960));
- release_mem_region(mem_start, ARIADNE_RAM_SIZE);
- free_netdev(dev);
- return err;
- }
- zorro_set_drvdata(z, dev);
-
- printk(KERN_INFO "%s: Ariadne at 0x%08lx, Ethernet Address %pM\n",
- dev->name, board, dev->dev_addr);
-
- return 0;
-}
-
-
-static int ariadne_open(struct net_device *dev)
-{
- volatile struct Am79C960 *lance = (struct Am79C960*)dev->base_addr;
- u_short in;
- u_long version;
- int i;
-
- /* Reset the LANCE */
- in = lance->Reset;
-
- /* Stop the LANCE */
- lance->RAP = CSR0; /* PCnet-ISA Controller Status */
- lance->RDP = STOP;
-
- /* Check the LANCE version */
- lance->RAP = CSR88; /* Chip ID */
- version = swapw(lance->RDP);
- lance->RAP = CSR89; /* Chip ID */
- version |= swapw(lance->RDP)<<16;
- if ((version & 0x00000fff) != 0x00000003) {
- printk(KERN_WARNING "ariadne_open: Couldn't find AMD Ethernet Chip\n");
- return -EAGAIN;
- }
- if ((version & 0x0ffff000) != 0x00003000) {
- printk(KERN_WARNING "ariadne_open: Couldn't find Am79C960 (Wrong part "
- "number = %ld)\n", (version & 0x0ffff000)>>12);
- return -EAGAIN;
- }
-#if 0
- printk(KERN_DEBUG "ariadne_open: Am79C960 (PCnet-ISA) Revision %ld\n",
- (version & 0xf0000000)>>28);
-#endif
-
- ariadne_init_ring(dev);
-
- /* Miscellaneous Stuff */
- lance->RAP = CSR3; /* Interrupt Masks and Deferral Control */
- lance->RDP = 0x0000;
- lance->RAP = CSR4; /* Test and Features Control */
- lance->RDP = DPOLL|APAD_XMT|MFCOM|RCVCCOM|TXSTRTM|JABM;
-
- /* Set the Multicast Table */
- lance->RAP = CSR8; /* Logical Address Filter, LADRF[15:0] */
- lance->RDP = 0x0000;
- lance->RAP = CSR9; /* Logical Address Filter, LADRF[31:16] */
- lance->RDP = 0x0000;
- lance->RAP = CSR10; /* Logical Address Filter, LADRF[47:32] */
- lance->RDP = 0x0000;
- lance->RAP = CSR11; /* Logical Address Filter, LADRF[63:48] */
- lance->RDP = 0x0000;
-
- /* Set the Ethernet Hardware Address */
- lance->RAP = CSR12; /* Physical Address Register, PADR[15:0] */
- lance->RDP = ((u_short *)&dev->dev_addr[0])[0];
- lance->RAP = CSR13; /* Physical Address Register, PADR[31:16] */
- lance->RDP = ((u_short *)&dev->dev_addr[0])[1];
- lance->RAP = CSR14; /* Physical Address Register, PADR[47:32] */
- lance->RDP = ((u_short *)&dev->dev_addr[0])[2];
-
- /* Set the Init Block Mode */
- lance->RAP = CSR15; /* Mode Register */
- lance->RDP = 0x0000;
-
- /* Set the Transmit Descriptor Ring Pointer */
- lance->RAP = CSR30; /* Base Address of Transmit Ring */
- lance->RDP = swloww(ARIADNE_RAM+offsetof(struct lancedata, tx_ring));
- lance->RAP = CSR31; /* Base Address of transmit Ring */
- lance->RDP = swhighw(ARIADNE_RAM+offsetof(struct lancedata, tx_ring));
-
- /* Set the Receive Descriptor Ring Pointer */
- lance->RAP = CSR24; /* Base Address of Receive Ring */
- lance->RDP = swloww(ARIADNE_RAM+offsetof(struct lancedata, rx_ring));
- lance->RAP = CSR25; /* Base Address of Receive Ring */
- lance->RDP = swhighw(ARIADNE_RAM+offsetof(struct lancedata, rx_ring));
-
- /* Set the Number of RX and TX Ring Entries */
- lance->RAP = CSR76; /* Receive Ring Length */
- lance->RDP = swapw(((u_short)-RX_RING_SIZE));
- lance->RAP = CSR78; /* Transmit Ring Length */
- lance->RDP = swapw(((u_short)-TX_RING_SIZE));
-
- /* Enable Media Interface Port Auto Select (10BASE-2/10BASE-T) */
- lance->RAP = ISACSR2; /* Miscellaneous Configuration */
- lance->IDP = ASEL;
-
- /* LED Control */
- lance->RAP = ISACSR5; /* LED1 Status */
- lance->IDP = PSE|XMTE;
- lance->RAP = ISACSR6; /* LED2 Status */
- lance->IDP = PSE|COLE;
- lance->RAP = ISACSR7; /* LED3 Status */
- lance->IDP = PSE|RCVE;
-
- netif_start_queue(dev);
-
- i = request_irq(IRQ_AMIGA_PORTS, ariadne_interrupt, IRQF_SHARED,
- dev->name, dev);
- if (i) return i;
-
- lance->RAP = CSR0; /* PCnet-ISA Controller Status */
- lance->RDP = INEA|STRT;
-
- return 0;
-}
-
-
-static void ariadne_init_ring(struct net_device *dev)
-{
- struct ariadne_private *priv = netdev_priv(dev);
- volatile struct lancedata *lancedata = (struct lancedata *)dev->mem_start;
- int i;
-
- netif_stop_queue(dev);
-
- priv->tx_full = 0;
- priv->cur_rx = priv->cur_tx = 0;
- priv->dirty_tx = 0;
-
- /* Set up TX Ring */
- for (i = 0; i < TX_RING_SIZE; i++) {
- volatile struct TDRE *t = &lancedata->tx_ring[i];
- t->TMD0 = swloww(ARIADNE_RAM+offsetof(struct lancedata, tx_buff[i]));
- t->TMD1 = swhighw(ARIADNE_RAM+offsetof(struct lancedata, tx_buff[i])) |
- TF_STP | TF_ENP;
- t->TMD2 = swapw((u_short)-PKT_BUF_SIZE);
- t->TMD3 = 0;
- priv->tx_ring[i] = &lancedata->tx_ring[i];
- priv->tx_buff[i] = lancedata->tx_buff[i];
-#if 0
- printk(KERN_DEBUG "TX Entry %2d at %p, Buf at %p\n", i,
- &lancedata->tx_ring[i], lancedata->tx_buff[i]);
-#endif
- }
-
- /* Set up RX Ring */
- for (i = 0; i < RX_RING_SIZE; i++) {
- volatile struct RDRE *r = &lancedata->rx_ring[i];
- r->RMD0 = swloww(ARIADNE_RAM+offsetof(struct lancedata, rx_buff[i]));
- r->RMD1 = swhighw(ARIADNE_RAM+offsetof(struct lancedata, rx_buff[i])) |
- RF_OWN;
- r->RMD2 = swapw((u_short)-PKT_BUF_SIZE);
- r->RMD3 = 0x0000;
- priv->rx_ring[i] = &lancedata->rx_ring[i];
- priv->rx_buff[i] = lancedata->rx_buff[i];
-#if 0
- printk(KERN_DEBUG "RX Entry %2d at %p, Buf at %p\n", i,
- &lancedata->rx_ring[i], lancedata->rx_buff[i]);
-#endif
- }
-}
-
-
-static int ariadne_close(struct net_device *dev)
-{
- volatile struct Am79C960 *lance = (struct Am79C960*)dev->base_addr;
-
- netif_stop_queue(dev);
-
- lance->RAP = CSR112; /* Missed Frame Count */
- dev->stats.rx_missed_errors = swapw(lance->RDP);
- lance->RAP = CSR0; /* PCnet-ISA Controller Status */
-
- if (ariadne_debug > 1) {
- printk(KERN_DEBUG "%s: Shutting down ethercard, status was %2.2x.\n",
- dev->name, lance->RDP);
- printk(KERN_DEBUG "%s: %lu packets missed\n", dev->name,
- dev->stats.rx_missed_errors);
- }
-
- /* We stop the LANCE here -- it occasionally polls memory if we don't. */
- lance->RDP = STOP;
-
- free_irq(IRQ_AMIGA_PORTS, dev);
-
- return 0;
-}
-
-
-static inline void ariadne_reset(struct net_device *dev)
-{
- volatile struct Am79C960 *lance = (struct Am79C960*)dev->base_addr;
-
- lance->RAP = CSR0; /* PCnet-ISA Controller Status */
- lance->RDP = STOP;
- ariadne_init_ring(dev);
- lance->RDP = INEA|STRT;
- netif_start_queue(dev);
-}
-
-
-static irqreturn_t ariadne_interrupt(int irq, void *data)
-{
- struct net_device *dev = (struct net_device *)data;
- volatile struct Am79C960 *lance = (struct Am79C960*)dev->base_addr;
- struct ariadne_private *priv;
- int csr0, boguscnt;
- int handled = 0;
-
- lance->RAP = CSR0; /* PCnet-ISA Controller Status */
-
- if (!(lance->RDP & INTR)) /* Check if any interrupt has been */
- return IRQ_NONE; /* generated by the board. */
-
- priv = netdev_priv(dev);
-
- boguscnt = 10;
- while ((csr0 = lance->RDP) & (ERR|RINT|TINT) && --boguscnt >= 0) {
- /* Acknowledge all of the current interrupt sources ASAP. */
- lance->RDP = csr0 & ~(INEA|TDMD|STOP|STRT|INIT);
-
-#if 0
- if (ariadne_debug > 5) {
- printk(KERN_DEBUG "%s: interrupt csr0=%#2.2x new csr=%#2.2x.",
- dev->name, csr0, lance->RDP);
- printk("[");
- if (csr0 & INTR)
- printk(" INTR");
- if (csr0 & INEA)
- printk(" INEA");
- if (csr0 & RXON)
- printk(" RXON");
- if (csr0 & TXON)
- printk(" TXON");
- if (csr0 & TDMD)
- printk(" TDMD");
- if (csr0 & STOP)
- printk(" STOP");
- if (csr0 & STRT)
- printk(" STRT");
- if (csr0 & INIT)
- printk(" INIT");
- if (csr0 & ERR)
- printk(" ERR");
- if (csr0 & BABL)
- printk(" BABL");
- if (csr0 & CERR)
- printk(" CERR");
- if (csr0 & MISS)
- printk(" MISS");
- if (csr0 & MERR)
- printk(" MERR");
- if (csr0 & RINT)
- printk(" RINT");
- if (csr0 & TINT)
- printk(" TINT");
- if (csr0 & IDON)
- printk(" IDON");
- printk(" ]\n");
- }
-#endif
-
- if (csr0 & RINT) { /* Rx interrupt */
- handled = 1;
- ariadne_rx(dev);
+ r1 = request_mem_region(base_addr, sizeof(struct Am79C960), "Am79C960");
+ if (!r1)
+ return -EBUSY;
+ r2 = request_mem_region(mem_start, ARIADNE_RAM_SIZE, "RAM");
+ if (!r2) {
+ release_mem_region(base_addr, sizeof(struct Am79C960));
+ return -EBUSY;
}
- if (csr0 & TINT) { /* Tx-done interrupt */
- int dirty_tx = priv->dirty_tx;
-
- handled = 1;
- while (dirty_tx < priv->cur_tx) {
- int entry = dirty_tx % TX_RING_SIZE;
- int status = lowb(priv->tx_ring[entry]->TMD1);
-
- if (status & TF_OWN)
- break; /* It still hasn't been Txed */
-
- priv->tx_ring[entry]->TMD1 &= 0xff00;
-
- if (status & TF_ERR) {
- /* There was an major error, log it. */
- int err_status = priv->tx_ring[entry]->TMD3;
- dev->stats.tx_errors++;
- if (err_status & EF_RTRY)
- dev->stats.tx_aborted_errors++;
- if (err_status & EF_LCAR)
- dev->stats.tx_carrier_errors++;
- if (err_status & EF_LCOL)
- dev->stats.tx_window_errors++;
- if (err_status & EF_UFLO) {
- /* Ackk! On FIFO errors the Tx unit is turned off! */
- dev->stats.tx_fifo_errors++;
- /* Remove this verbosity later! */
- printk(KERN_ERR "%s: Tx FIFO error! Status %4.4x.\n",
- dev->name, csr0);
- /* Restart the chip. */
- lance->RDP = STRT;
- }
- } else {
- if (status & (TF_MORE|TF_ONE))
- dev->stats.collisions++;
- dev->stats.tx_packets++;
- }
- dirty_tx++;
- }
-
-#ifndef final_version
- if (priv->cur_tx - dirty_tx >= TX_RING_SIZE) {
- printk(KERN_ERR "out-of-sync dirty pointer, %d vs. %d, "
- "full=%d.\n", dirty_tx, priv->cur_tx, priv->tx_full);
- dirty_tx += TX_RING_SIZE;
- }
-#endif
-
- if (priv->tx_full && netif_queue_stopped(dev) &&
- dirty_tx > priv->cur_tx - TX_RING_SIZE + 2) {
- /* The ring is no longer full. */
- priv->tx_full = 0;
- netif_wake_queue(dev);
- }
-
- priv->dirty_tx = dirty_tx;
+ dev = alloc_etherdev(sizeof(struct ariadne_private));
+ if (dev == NULL) {
+ release_mem_region(base_addr, sizeof(struct Am79C960));
+ release_mem_region(mem_start, ARIADNE_RAM_SIZE);
+ return -ENOMEM;
}
- /* Log misc errors. */
- if (csr0 & BABL) {
- handled = 1;
- dev->stats.tx_errors++; /* Tx babble. */
+ priv = netdev_priv(dev);
+
+ r1->name = dev->name;
+ r2->name = dev->name;
+
+ dev->dev_addr[0] = 0x00;
+ dev->dev_addr[1] = 0x60;
+ dev->dev_addr[2] = 0x30;
+ dev->dev_addr[3] = (z->rom.er_SerialNumber >> 16) & 0xff;
+ dev->dev_addr[4] = (z->rom.er_SerialNumber >> 8) & 0xff;
+ dev->dev_addr[5] = z->rom.er_SerialNumber & 0xff;
+ dev->base_addr = ZTWO_VADDR(base_addr);
+ dev->mem_start = ZTWO_VADDR(mem_start);
+ dev->mem_end = dev->mem_start + ARIADNE_RAM_SIZE;
+
+ dev->netdev_ops = &ariadne_netdev_ops;
+ dev->watchdog_timeo = 5 * HZ;
+
+ err = register_netdev(dev);
+ if (err) {
+ release_mem_region(base_addr, sizeof(struct Am79C960));
+ release_mem_region(mem_start, ARIADNE_RAM_SIZE);
+ free_netdev(dev);
+ return err;
}
- if (csr0 & MISS) {
- handled = 1;
- dev->stats.rx_errors++; /* Missed a Rx frame. */
- }
- if (csr0 & MERR) {
- handled = 1;
- printk(KERN_ERR "%s: Bus master arbitration failure, status "
- "%4.4x.\n", dev->name, csr0);
- /* Restart the chip. */
- lance->RDP = STRT;
- }
- }
+ zorro_set_drvdata(z, dev);
- /* Clear any other interrupt, and set interrupt enable. */
- lance->RAP = CSR0; /* PCnet-ISA Controller Status */
- lance->RDP = INEA|BABL|CERR|MISS|MERR|IDON;
+ netdev_info(dev, "Ariadne at 0x%08lx, Ethernet Address %pM\n",
+ board, dev->dev_addr);
-#if 0
- if (ariadne_debug > 4)
- printk(KERN_DEBUG "%s: exiting interrupt, csr%d=%#4.4x.\n", dev->name,
- lance->RAP, lance->RDP);
-#endif
- return IRQ_RETVAL(handled);
+ return 0;
}
-
-static void ariadne_tx_timeout(struct net_device *dev)
-{
- volatile struct Am79C960 *lance = (struct Am79C960*)dev->base_addr;
-
- printk(KERN_ERR "%s: transmit timed out, status %4.4x, resetting.\n",
- dev->name, lance->RDP);
- ariadne_reset(dev);
- netif_wake_queue(dev);
-}
-
-
-static netdev_tx_t ariadne_start_xmit(struct sk_buff *skb,
- struct net_device *dev)
-{
- struct ariadne_private *priv = netdev_priv(dev);
- volatile struct Am79C960 *lance = (struct Am79C960*)dev->base_addr;
- int entry;
- unsigned long flags;
- int len = skb->len;
-
-#if 0
- if (ariadne_debug > 3) {
- lance->RAP = CSR0; /* PCnet-ISA Controller Status */
- printk(KERN_DEBUG "%s: ariadne_start_xmit() called, csr0 %4.4x.\n",
- dev->name, lance->RDP);
- lance->RDP = 0x0000;
- }
-#endif
-
- /* FIXME: is the 79C960 new enough to do its own padding right ? */
- if (skb->len < ETH_ZLEN)
- {
- if (skb_padto(skb, ETH_ZLEN))
- return NETDEV_TX_OK;
- len = ETH_ZLEN;
- }
-
- /* Fill in a Tx ring entry */
-
-#if 0
-{
- printk(KERN_DEBUG "TX pkt type 0x%04x from %pM to %pM "
- " data 0x%08x len %d\n",
- ((u_short *)skb->data)[6],
- skb->data + 6, skb->data,
- (int)skb->data, (int)skb->len);
-}
-#endif
-
- local_irq_save(flags);
-
- entry = priv->cur_tx % TX_RING_SIZE;
-
- /* Caution: the write order is important here, set the base address with
- the "ownership" bits last. */
-
- priv->tx_ring[entry]->TMD2 = swapw((u_short)-skb->len);
- priv->tx_ring[entry]->TMD3 = 0x0000;
- memcpyw(priv->tx_buff[entry], (u_short *)skb->data, len);
-
-#if 0
- {
- int i, len;
-
- len = skb->len > 64 ? 64 : skb->len;
- len >>= 1;
- for (i = 0; i < len; i += 8) {
- int j;
- printk(KERN_DEBUG "%04x:", i);
- for (j = 0; (j < 8) && ((i+j) < len); j++) {
- if (!(j & 1))
- printk(" ");
- printk("%04x", priv->tx_buff[entry][i+j]);
- }
- printk("\n");
- }
- }
-#endif
-
- priv->tx_ring[entry]->TMD1 = (priv->tx_ring[entry]->TMD1&0xff00)|TF_OWN|TF_STP|TF_ENP;
-
- dev_kfree_skb(skb);
-
- priv->cur_tx++;
- if ((priv->cur_tx >= TX_RING_SIZE) && (priv->dirty_tx >= TX_RING_SIZE)) {
-
-#if 0
- printk(KERN_DEBUG "*** Subtracting TX_RING_SIZE from cur_tx (%d) and "
- "dirty_tx (%d)\n", priv->cur_tx, priv->dirty_tx);
-#endif
-
- priv->cur_tx -= TX_RING_SIZE;
- priv->dirty_tx -= TX_RING_SIZE;
- }
- dev->stats.tx_bytes += len;
-
- /* Trigger an immediate send poll. */
- lance->RAP = CSR0; /* PCnet-ISA Controller Status */
- lance->RDP = INEA|TDMD;
-
- if (lowb(priv->tx_ring[(entry+1) % TX_RING_SIZE]->TMD1) != 0) {
- netif_stop_queue(dev);
- priv->tx_full = 1;
- }
- local_irq_restore(flags);
-
- return NETDEV_TX_OK;
-}
-
-
-static int ariadne_rx(struct net_device *dev)
-{
- struct ariadne_private *priv = netdev_priv(dev);
- int entry = priv->cur_rx % RX_RING_SIZE;
- int i;
-
- /* If we own the next entry, it's a new packet. Send it up. */
- while (!(lowb(priv->rx_ring[entry]->RMD1) & RF_OWN)) {
- int status = lowb(priv->rx_ring[entry]->RMD1);
-
- if (status != (RF_STP|RF_ENP)) { /* There was an error. */
- /* There is a tricky error noted by John Murphy,
- <murf@perftech.com> to Russ Nelson: Even with full-sized
- buffers it's possible for a jabber packet to use two
- buffers, with only the last correctly noting the error. */
- if (status & RF_ENP)
- /* Only count a general error at the end of a packet.*/
- dev->stats.rx_errors++;
- if (status & RF_FRAM)
- dev->stats.rx_frame_errors++;
- if (status & RF_OFLO)
- dev->stats.rx_over_errors++;
- if (status & RF_CRC)
- dev->stats.rx_crc_errors++;
- if (status & RF_BUFF)
- dev->stats.rx_fifo_errors++;
- priv->rx_ring[entry]->RMD1 &= 0xff00|RF_STP|RF_ENP;
- } else {
- /* Malloc up new buffer, compatible with net-3. */
- short pkt_len = swapw(priv->rx_ring[entry]->RMD3);
- struct sk_buff *skb;
-
- skb = dev_alloc_skb(pkt_len+2);
- if (skb == NULL) {
- printk(KERN_WARNING "%s: Memory squeeze, deferring packet.\n",
- dev->name);
- for (i = 0; i < RX_RING_SIZE; i++)
- if (lowb(priv->rx_ring[(entry+i) % RX_RING_SIZE]->RMD1) & RF_OWN)
- break;
-
- if (i > RX_RING_SIZE-2) {
- dev->stats.rx_dropped++;
- priv->rx_ring[entry]->RMD1 |= RF_OWN;
- priv->cur_rx++;
- }
- break;
- }
-
-
- skb_reserve(skb,2); /* 16 byte align */
- skb_put(skb,pkt_len); /* Make room */
- skb_copy_to_linear_data(skb, (char *)priv->rx_buff[entry], pkt_len);
- skb->protocol=eth_type_trans(skb,dev);
-#if 0
-{
- printk(KERN_DEBUG "RX pkt type 0x%04x from ",
- ((u_short *)skb->data)[6]);
- {
- u_char *ptr = &((u_char *)skb->data)[6];
- printk("%pM", ptr);
- }
- printk(" to ");
- {
- u_char *ptr = (u_char *)skb->data;
- printk("%pM", ptr);
- }
- printk(" data 0x%08x len %d\n", (int)skb->data, (int)skb->len);
-}
-#endif
-
- netif_rx(skb);
- dev->stats.rx_packets++;
- dev->stats.rx_bytes += pkt_len;
- }
-
- priv->rx_ring[entry]->RMD1 |= RF_OWN;
- entry = (++priv->cur_rx) % RX_RING_SIZE;
- }
-
- priv->cur_rx = priv->cur_rx % RX_RING_SIZE;
-
- /* We should check that at least two ring entries are free. If not,
- we should free one and mark stats->rx_dropped++. */
-
- return 0;
-}
-
-
-static struct net_device_stats *ariadne_get_stats(struct net_device *dev)
-{
- volatile struct Am79C960 *lance = (struct Am79C960*)dev->base_addr;
- short saved_addr;
- unsigned long flags;
-
- local_irq_save(flags);
- saved_addr = lance->RAP;
- lance->RAP = CSR112; /* Missed Frame Count */
- dev->stats.rx_missed_errors = swapw(lance->RDP);
- lance->RAP = saved_addr;
- local_irq_restore(flags);
-
- return &dev->stats;
-}
-
-
-/* Set or clear the multicast filter for this adaptor.
- num_addrs == -1 Promiscuous mode, receive all packets
- num_addrs == 0 Normal mode, clear multicast list
- num_addrs > 0 Multicast mode, receive normal and MC packets, and do
- best-effort filtering.
- */
-static void set_multicast_list(struct net_device *dev)
-{
- volatile struct Am79C960 *lance = (struct Am79C960*)dev->base_addr;
-
- if (!netif_running(dev))
- return;
-
- netif_stop_queue(dev);
-
- /* We take the simple way out and always enable promiscuous mode. */
- lance->RAP = CSR0; /* PCnet-ISA Controller Status */
- lance->RDP = STOP; /* Temporarily stop the lance. */
- ariadne_init_ring(dev);
-
- if (dev->flags & IFF_PROMISC) {
- lance->RAP = CSR15; /* Mode Register */
- lance->RDP = PROM; /* Set promiscuous mode */
- } else {
- short multicast_table[4];
- int num_addrs = netdev_mc_count(dev);
- int i;
- /* We don't use the multicast table, but rely on upper-layer filtering. */
- memset(multicast_table, (num_addrs == 0) ? 0 : -1,
- sizeof(multicast_table));
- for (i = 0; i < 4; i++) {
- lance->RAP = CSR8+(i<<8); /* Logical Address Filter */
- lance->RDP = swapw(multicast_table[i]);
- }
- lance->RAP = CSR15; /* Mode Register */
- lance->RDP = 0x0000; /* Unset promiscuous mode */
- }
-
- lance->RAP = CSR0; /* PCnet-ISA Controller Status */
- lance->RDP = INEA|STRT|IDON; /* Resume normal operation. */
-
- netif_wake_queue(dev);
-}
-
-
-static void __devexit ariadne_remove_one(struct zorro_dev *z)
-{
- struct net_device *dev = zorro_get_drvdata(z);
-
- unregister_netdev(dev);
- release_mem_region(ZTWO_PADDR(dev->base_addr), sizeof(struct Am79C960));
- release_mem_region(ZTWO_PADDR(dev->mem_start), ARIADNE_RAM_SIZE);
- free_netdev(dev);
-}
+static struct zorro_driver ariadne_driver = {
+ .name = "ariadne",
+ .id_table = ariadne_zorro_tbl,
+ .probe = ariadne_init_one,
+ .remove = __devexit_p(ariadne_remove_one),
+};
static int __init ariadne_init_module(void)
{
- return zorro_register_driver(&ariadne_driver);
+ return zorro_register_driver(&ariadne_driver);
}
static void __exit ariadne_cleanup_module(void)
{
- zorro_unregister_driver(&ariadne_driver);
+ zorro_unregister_driver(&ariadne_driver);
}
module_init(ariadne_init_module);
diff --git a/drivers/net/arm/am79c961a.c b/drivers/net/arm/am79c961a.c
index 7b3e23f..52fe21e 100644
--- a/drivers/net/arm/am79c961a.c
+++ b/drivers/net/arm/am79c961a.c
@@ -199,17 +199,15 @@
static void am79c961_mc_hash(char *addr, u16 *hash)
{
- if (addr[0] & 0x01) {
- int idx, bit;
- u32 crc;
+ int idx, bit;
+ u32 crc;
- crc = ether_crc_le(ETH_ALEN, addr);
+ crc = ether_crc_le(ETH_ALEN, addr);
- idx = crc >> 30;
- bit = (crc >> 26) & 15;
+ idx = crc >> 30;
+ bit = (crc >> 26) & 15;
- hash[idx] |= 1 << bit;
- }
+ hash[idx] |= 1 << bit;
}
static unsigned int am79c961_get_rx_mode(struct net_device *dev, u16 *hash)
diff --git a/drivers/net/arm/at91_ether.c b/drivers/net/arm/at91_ether.c
index e07b314..29dc435 100644
--- a/drivers/net/arm/at91_ether.c
+++ b/drivers/net/arm/at91_ether.c
@@ -19,6 +19,7 @@
#include <linux/module.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/mii.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
diff --git a/drivers/net/arm/ep93xx_eth.c b/drivers/net/arm/ep93xx_eth.c
index 0b46b8e..4317af8 100644
--- a/drivers/net/arm/ep93xx_eth.c
+++ b/drivers/net/arm/ep93xx_eth.c
@@ -19,6 +19,7 @@
#include <linux/etherdevice.h>
#include <linux/ethtool.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/moduleparam.h>
#include <linux/platform_device.h>
#include <linux/delay.h>
diff --git a/drivers/net/arm/ks8695net.c b/drivers/net/arm/ks8695net.c
index a7b0caa..c827a60 100644
--- a/drivers/net/arm/ks8695net.c
+++ b/drivers/net/arm/ks8695net.c
@@ -16,11 +16,13 @@
* Vincent Sanders <vince@simtec.co.uk>
*/
+#include <linux/dma-mapping.h>
#include <linux/module.h>
#include <linux/ioport.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/skbuff.h>
#include <linux/spinlock.h>
#include <linux/crc32.h>
diff --git a/drivers/net/atl1c/atl1c.h b/drivers/net/atl1c/atl1c.h
index 925929d..0f481b9 100644
--- a/drivers/net/atl1c/atl1c.h
+++ b/drivers/net/atl1c/atl1c.h
@@ -22,8 +22,8 @@
#ifndef _ATL1C_H_
#define _ATL1C_H_
-#include <linux/version.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/module.h>
diff --git a/drivers/net/atl1e/atl1e.h b/drivers/net/atl1e/atl1e.h
index 490d3b3..8c8181b 100644
--- a/drivers/net/atl1e/atl1e.h
+++ b/drivers/net/atl1e/atl1e.h
@@ -23,8 +23,8 @@
#ifndef _ATL1E_H_
#define _ATL1E_H_
-#include <linux/version.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/module.h>
diff --git a/drivers/net/atl1e/atl1e_main.c b/drivers/net/atl1e/atl1e_main.c
index 86a9122..c3c5db1 100644
--- a/drivers/net/atl1e/atl1e_main.c
+++ b/drivers/net/atl1e/atl1e_main.c
@@ -800,8 +800,7 @@
/* Init TPD Ring */
tx_ring->dma = roundup(adapter->ring_dma, 8);
offset = tx_ring->dma - adapter->ring_dma;
- tx_ring->desc = (struct atl1e_tpd_desc *)
- (adapter->ring_vir_addr + offset);
+ tx_ring->desc = adapter->ring_vir_addr + offset;
size = sizeof(struct atl1e_tx_buffer) * (tx_ring->count);
tx_ring->tx_buffer = kzalloc(size, GFP_KERNEL);
if (tx_ring->tx_buffer == NULL) {
@@ -827,7 +826,7 @@
/* Init CMB dma address */
tx_ring->cmb_dma = adapter->ring_dma + offset;
- tx_ring->cmb = (u32 *)(adapter->ring_vir_addr + offset);
+ tx_ring->cmb = adapter->ring_vir_addr + offset;
offset += sizeof(u32);
for (i = 0; i < adapter->num_rx_queues; i++) {
diff --git a/drivers/net/atlx/atl2.c b/drivers/net/atlx/atl2.c
index 16249e9..24e1592 100644
--- a/drivers/net/atlx/atl2.c
+++ b/drivers/net/atlx/atl2.c
@@ -311,8 +311,7 @@
adapter->txd_dma = adapter->ring_dma ;
offset = (adapter->txd_dma & 0x7) ? (8 - (adapter->txd_dma & 0x7)) : 0;
adapter->txd_dma += offset;
- adapter->txd_ring = (struct tx_pkt_header *) (adapter->ring_vir_addr +
- offset);
+ adapter->txd_ring = adapter->ring_vir_addr + offset;
/* Init TXS Ring */
adapter->txs_dma = adapter->txd_dma + adapter->txd_ring_size;
diff --git a/drivers/net/b44.c b/drivers/net/b44.c
index a69331e..6c4ef96 100644
--- a/drivers/net/b44.c
+++ b/drivers/net/b44.c
@@ -25,6 +25,7 @@
#include <linux/pci.h>
#include <linux/delay.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/dma-mapping.h>
#include <linux/ssb/ssb.h>
#include <linux/slab.h>
@@ -38,6 +39,7 @@
#define DRV_MODULE_NAME "b44"
#define DRV_MODULE_VERSION "2.0"
+#define DRV_DESCRIPTION "Broadcom 44xx/47xx 10/100 PCI ethernet driver"
#define B44_DEF_MSG_ENABLE \
(NETIF_MSG_DRV | \
@@ -90,11 +92,8 @@
#define B44_ETHIPV6UDP_HLEN 62
#define B44_ETHIPV4UDP_HLEN 42
-static char version[] __devinitdata =
- DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION "\n";
-
MODULE_AUTHOR("Felix Fietkau, Florian Schirmer, Pekka Pietikainen, David S. Miller");
-MODULE_DESCRIPTION("Broadcom 44xx/47xx 10/100 PCI ethernet driver");
+MODULE_DESCRIPTION(DRV_DESCRIPTION);
MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_MODULE_VERSION);
@@ -609,7 +608,7 @@
skb->len,
DMA_TO_DEVICE);
rp->skb = NULL;
- dev_kfree_skb_irq(skb);
+ dev_kfree_skb(skb);
}
bp->tx_cons = cons;
@@ -2129,16 +2128,13 @@
static int __devinit b44_init_one(struct ssb_device *sdev,
const struct ssb_device_id *ent)
{
- static int b44_version_printed = 0;
struct net_device *dev;
struct b44 *bp;
int err;
instance++;
- if (b44_version_printed++ == 0)
- pr_info("%s", version);
-
+ pr_info_once("%s version %s\n", DRV_DESCRIPTION, DRV_MODULE_VERSION);
dev = alloc_etherdev(sizeof(*bp));
if (!dev) {
@@ -2224,8 +2220,7 @@
if (b44_phy_reset(bp) < 0)
bp->phy_addr = B44_PHY_ADDR_NO_PHY;
- netdev_info(dev, "Broadcom 44xx/47xx 10/100BaseT Ethernet %pM\n",
- dev->dev_addr);
+ netdev_info(dev, "%s %pM\n", DRV_DESCRIPTION, dev->dev_addr);
return 0;
@@ -2335,7 +2330,7 @@
.resume = b44_resume,
};
-static inline int b44_pci_init(void)
+static inline int __init b44_pci_init(void)
{
int err = 0;
#ifdef CONFIG_B44_PCI
@@ -2344,7 +2339,7 @@
return err;
}
-static inline void b44_pci_exit(void)
+static inline void __exit b44_pci_exit(void)
{
#ifdef CONFIG_B44_PCI
ssb_pcihost_unregister(&b44_pci_driver);
diff --git a/drivers/net/bcm63xx_enet.c b/drivers/net/bcm63xx_enet.c
index f1573d4..4753bb9 100644
--- a/drivers/net/bcm63xx_enet.c
+++ b/drivers/net/bcm63xx_enet.c
@@ -18,6 +18,7 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/clk.h>
#include <linux/etherdevice.h>
diff --git a/drivers/net/benet/be.h b/drivers/net/benet/be.h
index a7db870..9aa1534 100644
--- a/drivers/net/benet/be.h
+++ b/drivers/net/benet/be.h
@@ -20,7 +20,6 @@
#include <linux/pci.h>
#include <linux/etherdevice.h>
-#include <linux/version.h>
#include <linux/delay.h>
#include <net/tcp.h>
#include <net/ip.h>
@@ -87,6 +86,7 @@
#define MAX_RSS_QS 4 /* BE limit is 4 queues/port */
#define MAX_RX_QS (MAX_RSS_QS + 1) /* RSS qs + 1 def Rx */
+#define MAX_TX_QS 8
#define BE_MAX_MSIX_VECTORS (MAX_RX_QS + 1)/* RX + TX */
#define BE_NAPI_WEIGHT 64
#define MAX_RX_POST BE_NAPI_WEIGHT /* Frags posted at a time */
@@ -170,7 +170,6 @@
u32 be_tx_reqs; /* number of TX requests initiated */
u32 be_tx_stops; /* number of times TX Q was stopped */
u32 be_tx_wrbs; /* number of tx WRBs used */
- u32 be_tx_events; /* number of tx completion events */
u32 be_tx_compl; /* number of tx completion entries processed */
ulong be_tx_jiffies;
u64 be_tx_bytes;
@@ -184,6 +183,7 @@
struct be_queue_info cq;
/* Remember the skbs that were transmitted */
struct sk_buff *sent_skb_list[TX_Q_LEN];
+ struct be_tx_stats stats;
};
/* Struct to remember the pages posted for rx frags */
@@ -319,8 +319,8 @@
/* TX Rings */
struct be_eq_obj tx_eq;
- struct be_tx_obj tx_obj;
- struct be_tx_stats tx_stats;
+ struct be_tx_obj tx_obj[MAX_TX_QS];
+ u8 num_tx_qs;
u32 cache_line_break[8];
@@ -391,7 +391,7 @@
extern const struct ethtool_ops be_ethtool_ops;
#define msix_enabled(adapter) (adapter->num_msix_vec > 0)
-#define tx_stats(adapter) (&adapter->tx_stats)
+#define tx_stats(txo) (&txo->stats)
#define rx_stats(rxo) (&rxo->stats)
#define BE_SET_NETDEV_OPS(netdev, ops) (netdev->netdev_ops = ops)
@@ -405,6 +405,10 @@
for (i = 0, rxo = &adapter->rx_obj[i+1]; i < (adapter->num_rx_qs - 1);\
i++, rxo++)
+#define for_all_tx_queues(adapter, txo, i) \
+ for (i = 0, txo = &adapter->tx_obj[i]; i < adapter->num_tx_qs; \
+ i++, txo++)
+
#define PAGE_SHIFT_4K 12
#define PAGE_SIZE_4K (1 << PAGE_SHIFT_4K)
diff --git a/drivers/net/benet/be_cmds.c b/drivers/net/benet/be_cmds.c
index 81654ae..f520a5c 100644
--- a/drivers/net/benet/be_cmds.c
+++ b/drivers/net/benet/be_cmds.c
@@ -106,14 +106,24 @@
netdev_stats_update(adapter);
adapter->stats_cmd_sent = false;
}
- } else if ((compl_status != MCC_STATUS_NOT_SUPPORTED) &&
- (compl->tag0 != OPCODE_COMMON_NTWK_MAC_QUERY)) {
- extd_status = (compl->status >> CQE_STATUS_EXTD_SHIFT) &
- CQE_STATUS_EXTD_MASK;
- dev_warn(&adapter->pdev->dev,
- "Error in cmd completion - opcode %d, compl %d, extd %d\n",
- compl->tag0, compl_status, extd_status);
+ } else {
+ if (compl_status == MCC_STATUS_NOT_SUPPORTED ||
+ compl_status == MCC_STATUS_ILLEGAL_REQUEST)
+ goto done;
+
+ if (compl_status == MCC_STATUS_UNAUTHORIZED_REQUEST) {
+ dev_warn(&adapter->pdev->dev, "This domain(VM) is not "
+ "permitted to execute this cmd (opcode %d)\n",
+ compl->tag0);
+ } else {
+ extd_status = (compl->status >> CQE_STATUS_EXTD_SHIFT) &
+ CQE_STATUS_EXTD_MASK;
+ dev_err(&adapter->pdev->dev, "Cmd (opcode %d) failed:"
+ "status %d, extd-status %d\n",
+ compl->tag0, compl_status, extd_status);
+ }
}
+done:
return compl_status;
}
@@ -799,12 +809,12 @@
return len_encoded;
}
-int be_cmd_mccq_create(struct be_adapter *adapter,
+int be_cmd_mccq_ext_create(struct be_adapter *adapter,
struct be_queue_info *mccq,
struct be_queue_info *cq)
{
struct be_mcc_wrb *wrb;
- struct be_cmd_req_mcc_create *req;
+ struct be_cmd_req_mcc_ext_create *req;
struct be_dma_mem *q_mem = &mccq->dma_mem;
void *ctxt;
int status;
@@ -859,6 +869,67 @@
return status;
}
+int be_cmd_mccq_org_create(struct be_adapter *adapter,
+ struct be_queue_info *mccq,
+ struct be_queue_info *cq)
+{
+ struct be_mcc_wrb *wrb;
+ struct be_cmd_req_mcc_create *req;
+ struct be_dma_mem *q_mem = &mccq->dma_mem;
+ void *ctxt;
+ int status;
+
+ if (mutex_lock_interruptible(&adapter->mbox_lock))
+ return -1;
+
+ wrb = wrb_from_mbox(adapter);
+ req = embedded_payload(wrb);
+ ctxt = &req->context;
+
+ be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0,
+ OPCODE_COMMON_MCC_CREATE);
+
+ be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+ OPCODE_COMMON_MCC_CREATE, sizeof(*req));
+
+ req->num_pages = cpu_to_le16(PAGES_4K_SPANNED(q_mem->va, q_mem->size));
+
+ AMAP_SET_BITS(struct amap_mcc_context_be, valid, ctxt, 1);
+ AMAP_SET_BITS(struct amap_mcc_context_be, ring_size, ctxt,
+ be_encoded_q_len(mccq->len));
+ AMAP_SET_BITS(struct amap_mcc_context_be, cq_id, ctxt, cq->id);
+
+ be_dws_cpu_to_le(ctxt, sizeof(req->context));
+
+ be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem);
+
+ status = be_mbox_notify_wait(adapter);
+ if (!status) {
+ struct be_cmd_resp_mcc_create *resp = embedded_payload(wrb);
+ mccq->id = le16_to_cpu(resp->id);
+ mccq->created = true;
+ }
+
+ mutex_unlock(&adapter->mbox_lock);
+ return status;
+}
+
+int be_cmd_mccq_create(struct be_adapter *adapter,
+ struct be_queue_info *mccq,
+ struct be_queue_info *cq)
+{
+ int status;
+
+ status = be_cmd_mccq_ext_create(adapter, mccq, cq);
+ if (status && !lancer_chip(adapter)) {
+ dev_warn(&adapter->pdev->dev, "Upgrade to F/W ver 2.102.235.0 "
+ "or newer to avoid conflicting priorities between NIC "
+ "and FCoE traffic");
+ status = be_cmd_mccq_org_create(adapter, mccq, cq);
+ }
+ return status;
+}
+
int be_cmd_txq_create(struct be_adapter *adapter,
struct be_queue_info *txq,
struct be_queue_info *cq)
@@ -913,7 +984,7 @@
return status;
}
-/* Uses mbox */
+/* Uses MCC */
int be_cmd_rxq_create(struct be_adapter *adapter,
struct be_queue_info *rxq, u16 cq_id, u16 frag_size,
u16 max_frame_size, u32 if_id, u32 rss, u8 *rss_id)
@@ -923,10 +994,13 @@
struct be_dma_mem *q_mem = &rxq->dma_mem;
int status;
- if (mutex_lock_interruptible(&adapter->mbox_lock))
- return -1;
+ spin_lock_bh(&adapter->mcc_lock);
- wrb = wrb_from_mbox(adapter);
+ wrb = wrb_from_mccq(adapter);
+ if (!wrb) {
+ status = -EBUSY;
+ goto err;
+ }
req = embedded_payload(wrb);
be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0,
@@ -943,7 +1017,7 @@
req->max_frame_size = cpu_to_le16(max_frame_size);
req->rss_queue = cpu_to_le32(rss);
- status = be_mbox_notify_wait(adapter);
+ status = be_mcc_notify_wait(adapter);
if (!status) {
struct be_cmd_resp_eth_rx_create *resp = embedded_payload(wrb);
rxq->id = le16_to_cpu(resp->id);
@@ -951,8 +1025,8 @@
*rss_id = resp->rss_id;
}
- mutex_unlock(&adapter->mbox_lock);
-
+err:
+ spin_unlock_bh(&adapter->mcc_lock);
return status;
}
@@ -1007,9 +1081,40 @@
req->id = cpu_to_le16(q->id);
status = be_mbox_notify_wait(adapter);
+ if (!status)
+ q->created = false;
mutex_unlock(&adapter->mbox_lock);
+ return status;
+}
+/* Uses MCC */
+int be_cmd_rxq_destroy(struct be_adapter *adapter, struct be_queue_info *q)
+{
+ struct be_mcc_wrb *wrb;
+ struct be_cmd_req_q_destroy *req;
+ int status;
+
+ spin_lock_bh(&adapter->mcc_lock);
+
+ wrb = wrb_from_mccq(adapter);
+ if (!wrb) {
+ status = -EBUSY;
+ goto err;
+ }
+ req = embedded_payload(wrb);
+
+ be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0, OPCODE_ETH_RX_DESTROY);
+ be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH, OPCODE_ETH_RX_DESTROY,
+ sizeof(*req));
+ req->id = cpu_to_le16(q->id);
+
+ status = be_mcc_notify_wait(adapter);
+ if (!status)
+ q->created = false;
+
+err:
+ spin_unlock_bh(&adapter->mcc_lock);
return status;
}
@@ -2273,8 +2378,7 @@
status = be_mbox_notify_wait(adapter);
if (!status) {
- attribs = (struct mgmt_controller_attrib *)( attribs_cmd.va +
- sizeof(struct be_cmd_resp_hdr));
+ attribs = attribs_cmd.va + sizeof(struct be_cmd_resp_hdr);
adapter->hba_port_num = attribs->hba_attribs.phy_port;
}
diff --git a/drivers/net/benet/be_cmds.h b/drivers/net/benet/be_cmds.h
index 8148cc6..1151df6 100644
--- a/drivers/net/benet/be_cmds.h
+++ b/drivers/net/benet/be_cmds.h
@@ -51,17 +51,12 @@
/* Completion Status */
enum {
- MCC_STATUS_SUCCESS = 0x0,
-/* The client does not have sufficient privileges to execute the command */
- MCC_STATUS_INSUFFICIENT_PRIVILEGES = 0x1,
-/* A parameter in the command was invalid. */
- MCC_STATUS_INVALID_PARAMETER = 0x2,
-/* There are insufficient chip resources to execute the command */
- MCC_STATUS_INSUFFICIENT_RESOURCES = 0x3,
-/* The command is completing because the queue was getting flushed */
- MCC_STATUS_QUEUE_FLUSHING = 0x4,
-/* The command is completing with a DMA error */
- MCC_STATUS_DMA_FAILED = 0x5,
+ MCC_STATUS_SUCCESS = 0,
+ MCC_STATUS_FAILED = 1,
+ MCC_STATUS_ILLEGAL_REQUEST = 2,
+ MCC_STATUS_ILLEGAL_FIELD = 3,
+ MCC_STATUS_INSUFFICIENT_BUFFER = 4,
+ MCC_STATUS_UNAUTHORIZED_REQUEST = 5,
MCC_STATUS_NOT_SUPPORTED = 66
};
@@ -434,6 +429,14 @@
struct be_cmd_req_hdr hdr;
u16 num_pages;
u16 cq_id;
+ u8 context[sizeof(struct amap_mcc_context_be) / 8];
+ struct phys_addr pages[8];
+} __packed;
+
+struct be_cmd_req_mcc_ext_create {
+ struct be_cmd_req_hdr hdr;
+ u16 num_pages;
+ u16 cq_id;
u32 async_event_bitmap[1];
u8 context[sizeof(struct amap_mcc_context_be) / 8];
struct phys_addr pages[8];
@@ -1479,6 +1482,8 @@
u32 rss, u8 *rss_id);
extern int be_cmd_q_destroy(struct be_adapter *adapter, struct be_queue_info *q,
int type);
+extern int be_cmd_rxq_destroy(struct be_adapter *adapter,
+ struct be_queue_info *q);
extern int be_cmd_link_status_query(struct be_adapter *adapter,
bool *link_up, u8 *mac_speed, u16 *link_speed, u32 dom);
extern int be_cmd_reset(struct be_adapter *adapter);
diff --git a/drivers/net/benet/be_ethtool.c b/drivers/net/benet/be_ethtool.c
index facfe3c..30c1386 100644
--- a/drivers/net/benet/be_ethtool.c
+++ b/drivers/net/benet/be_ethtool.c
@@ -52,12 +52,7 @@
{NETSTAT_INFO(tx_errors)},
{NETSTAT_INFO(rx_dropped)},
{NETSTAT_INFO(tx_dropped)},
- {DRVSTAT_TX_INFO(be_tx_rate)},
- {DRVSTAT_TX_INFO(be_tx_reqs)},
- {DRVSTAT_TX_INFO(be_tx_wrbs)},
- {DRVSTAT_TX_INFO(be_tx_stops)},
- {DRVSTAT_TX_INFO(be_tx_events)},
- {DRVSTAT_TX_INFO(be_tx_compl)},
+ {DRVSTAT_INFO(be_tx_events)},
{DRVSTAT_INFO(rx_crc_errors)},
{DRVSTAT_INFO(rx_alignment_symbol_errors)},
{DRVSTAT_INFO(rx_pause_frames)},
@@ -111,6 +106,16 @@
};
#define ETHTOOL_RXSTATS_NUM (ARRAY_SIZE(et_rx_stats))
+/* Stats related to multi TX queues */
+static const struct be_ethtool_stat et_tx_stats[] = {
+ {DRVSTAT_TX_INFO(be_tx_rate)},
+ {DRVSTAT_TX_INFO(be_tx_reqs)},
+ {DRVSTAT_TX_INFO(be_tx_wrbs)},
+ {DRVSTAT_TX_INFO(be_tx_stops)},
+ {DRVSTAT_TX_INFO(be_tx_compl)}
+};
+#define ETHTOOL_TXSTATS_NUM (ARRAY_SIZE(et_tx_stats))
+
static const char et_self_tests[][ETH_GSTRING_LEN] = {
"MAC Loopback test",
"PHY Loopback test",
@@ -253,17 +258,15 @@
{
struct be_adapter *adapter = netdev_priv(netdev);
struct be_rx_obj *rxo;
+ struct be_tx_obj *txo;
void *p = NULL;
- int i, j;
+ int i, j, base;
for (i = 0; i < ETHTOOL_STATS_NUM; i++) {
switch (et_stats[i].type) {
case NETSTAT:
p = &netdev->stats;
break;
- case DRVSTAT_TX:
- p = &adapter->tx_stats;
- break;
case DRVSTAT:
p = &adapter->drv_stats;
break;
@@ -274,6 +277,7 @@
*(u64 *)p: *(u32 *)p;
}
+ base = ETHTOOL_STATS_NUM;
for_all_rx_queues(adapter, rxo, j) {
for (i = 0; i < ETHTOOL_RXSTATS_NUM; i++) {
switch (et_rx_stats[i].type) {
@@ -285,11 +289,21 @@
rxo->q.id;
break;
}
- data[ETHTOOL_STATS_NUM + j * ETHTOOL_RXSTATS_NUM + i] =
+ data[base + j * ETHTOOL_RXSTATS_NUM + i] =
(et_rx_stats[i].size == sizeof(u64)) ?
*(u64 *)p: *(u32 *)p;
}
}
+
+ base = ETHTOOL_STATS_NUM + adapter->num_rx_qs * ETHTOOL_RXSTATS_NUM;
+ for_all_tx_queues(adapter, txo, j) {
+ for (i = 0; i < ETHTOOL_TXSTATS_NUM; i++) {
+ p = (u8 *)&txo->stats + et_tx_stats[i].offset;
+ data[base + j * ETHTOOL_TXSTATS_NUM + i] =
+ (et_tx_stats[i].size == sizeof(u64)) ?
+ *(u64 *)p: *(u32 *)p;
+ }
+ }
}
static void
@@ -312,6 +326,13 @@
data += ETH_GSTRING_LEN;
}
}
+ for (i = 0; i < adapter->num_tx_qs; i++) {
+ for (j = 0; j < ETHTOOL_TXSTATS_NUM; j++) {
+ sprintf(data, "txq%d: %s", i,
+ et_tx_stats[j].desc);
+ data += ETH_GSTRING_LEN;
+ }
+ }
break;
case ETH_SS_TEST:
for (i = 0; i < ETHTOOL_TESTS_NUM; i++) {
@@ -331,7 +352,8 @@
return ETHTOOL_TESTS_NUM;
case ETH_SS_STATS:
return ETHTOOL_STATS_NUM +
- adapter->num_rx_qs * ETHTOOL_RXSTATS_NUM;
+ adapter->num_rx_qs * ETHTOOL_RXSTATS_NUM +
+ adapter->num_tx_qs * ETHTOOL_TXSTATS_NUM;
default:
return -EINVAL;
}
@@ -386,7 +408,7 @@
}
status = be_cmd_get_phy_info(adapter, &phy_cmd);
if (!status) {
- resp = (struct be_cmd_resp_get_phy_info *) phy_cmd.va;
+ resp = phy_cmd.va;
intf_type = le16_to_cpu(resp->interface_type);
switch (intf_type) {
@@ -457,10 +479,10 @@
struct be_adapter *adapter = netdev_priv(netdev);
ring->rx_max_pending = adapter->rx_obj[0].q.len;
- ring->tx_max_pending = adapter->tx_obj.q.len;
+ ring->tx_max_pending = adapter->tx_obj[0].q.len;
ring->rx_pending = atomic_read(&adapter->rx_obj[0].q.used);
- ring->tx_pending = atomic_read(&adapter->tx_obj.q.used);
+ ring->tx_pending = atomic_read(&adapter->tx_obj[0].q.used);
}
static void
@@ -690,7 +712,7 @@
status = be_cmd_get_seeprom_data(adapter, &eeprom_cmd);
if (!status) {
- resp = (struct be_cmd_resp_seeprom_read *) eeprom_cmd.va;
+ resp = eeprom_cmd.va;
memcpy(data, resp->seeprom_data + eeprom->offset, eeprom->len);
}
dma_free_coherent(&adapter->pdev->dev, eeprom_cmd.size, eeprom_cmd.va,
diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c
index a485f7f..696f634 100644
--- a/drivers/net/benet/be_main.c
+++ b/drivers/net/benet/be_main.c
@@ -33,10 +33,6 @@
MODULE_PARM_DESC(rx_frag_size, "Size of a fragment that holds rcvd data.");
MODULE_PARM_DESC(num_vfs, "Number of PCI VFs to initialize");
-static bool multi_rxq = true;
-module_param(multi_rxq, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(multi_rxq, "Multi Rx Queue support. Enabled by default");
-
static DEFINE_PCI_DEVICE_TABLE(be_dev_ids) = {
{ PCI_DEVICE(BE_VENDOR_ID, BE_DEVICE_ID1) },
{ PCI_DEVICE(BE_VENDOR_ID, BE_DEVICE_ID2) },
@@ -362,8 +358,8 @@
drvs->rx_priority_pause_frames = 0;
drvs->pmem_fifo_overflow_drop = 0;
drvs->rx_pause_frames =
- make_64bit_val(pport_stats->rx_pause_frames_lo,
- pport_stats->rx_pause_frames_hi);
+ make_64bit_val(pport_stats->rx_pause_frames_hi,
+ pport_stats->rx_pause_frames_lo);
drvs->rx_crc_errors = make_64bit_val(pport_stats->rx_crc_errors_hi,
pport_stats->rx_crc_errors_lo);
drvs->rx_control_frames =
@@ -427,31 +423,39 @@
struct be_drv_stats *drvs = &adapter->drv_stats;
struct net_device_stats *dev_stats = &adapter->netdev->stats;
struct be_rx_obj *rxo;
+ struct be_tx_obj *txo;
+ unsigned long pkts = 0, bytes = 0, mcast = 0, drops = 0;
int i;
- memset(dev_stats, 0, sizeof(*dev_stats));
for_all_rx_queues(adapter, rxo, i) {
- dev_stats->rx_packets += rx_stats(rxo)->rx_pkts;
- dev_stats->rx_bytes += rx_stats(rxo)->rx_bytes;
- dev_stats->multicast += rx_stats(rxo)->rx_mcast_pkts;
+ pkts += rx_stats(rxo)->rx_pkts;
+ bytes += rx_stats(rxo)->rx_bytes;
+ mcast += rx_stats(rxo)->rx_mcast_pkts;
/* no space in linux buffers: best possible approximation */
if (adapter->generation == BE_GEN3) {
if (!(lancer_chip(adapter))) {
- struct be_erx_stats_v1 *erx_stats =
+ struct be_erx_stats_v1 *erx =
be_erx_stats_from_cmd(adapter);
- dev_stats->rx_dropped +=
- erx_stats->rx_drops_no_fragments[rxo->q.id];
+ drops += erx->rx_drops_no_fragments[rxo->q.id];
}
} else {
- struct be_erx_stats_v0 *erx_stats =
+ struct be_erx_stats_v0 *erx =
be_erx_stats_from_cmd(adapter);
- dev_stats->rx_dropped +=
- erx_stats->rx_drops_no_fragments[rxo->q.id];
+ drops += erx->rx_drops_no_fragments[rxo->q.id];
}
}
+ dev_stats->rx_packets = pkts;
+ dev_stats->rx_bytes = bytes;
+ dev_stats->multicast = mcast;
+ dev_stats->rx_dropped = drops;
- dev_stats->tx_packets = tx_stats(adapter)->be_tx_pkts;
- dev_stats->tx_bytes = tx_stats(adapter)->be_tx_bytes;
+ pkts = bytes = 0;
+ for_all_tx_queues(adapter, txo, i) {
+ pkts += tx_stats(txo)->be_tx_pkts;
+ bytes += tx_stats(txo)->be_tx_bytes;
+ }
+ dev_stats->tx_packets = pkts;
+ dev_stats->tx_bytes = bytes;
/* bad pkts received */
dev_stats->rx_errors = drvs->rx_crc_errors +
@@ -554,9 +558,9 @@
return rate;
}
-static void be_tx_rate_update(struct be_adapter *adapter)
+static void be_tx_rate_update(struct be_tx_obj *txo)
{
- struct be_tx_stats *stats = tx_stats(adapter);
+ struct be_tx_stats *stats = tx_stats(txo);
ulong now = jiffies;
/* Wrapped around? */
@@ -575,10 +579,11 @@
}
}
-static void be_tx_stats_update(struct be_adapter *adapter,
+static void be_tx_stats_update(struct be_tx_obj *txo,
u32 wrb_cnt, u32 copied, u32 gso_segs, bool stopped)
{
- struct be_tx_stats *stats = tx_stats(adapter);
+ struct be_tx_stats *stats = tx_stats(txo);
+
stats->be_tx_reqs++;
stats->be_tx_wrbs += wrb_cnt;
stats->be_tx_bytes += copied;
@@ -682,14 +687,13 @@
}
}
-static int make_tx_wrbs(struct be_adapter *adapter,
+static int make_tx_wrbs(struct be_adapter *adapter, struct be_queue_info *txq,
struct sk_buff *skb, u32 wrb_cnt, bool dummy_wrb)
{
dma_addr_t busaddr;
int i, copied = 0;
struct device *dev = &adapter->pdev->dev;
struct sk_buff *first_skb = skb;
- struct be_queue_info *txq = &adapter->tx_obj.q;
struct be_eth_wrb *wrb;
struct be_eth_hdr_wrb *hdr;
bool map_single = false;
@@ -753,19 +757,19 @@
struct net_device *netdev)
{
struct be_adapter *adapter = netdev_priv(netdev);
- struct be_tx_obj *tx_obj = &adapter->tx_obj;
- struct be_queue_info *txq = &tx_obj->q;
+ struct be_tx_obj *txo = &adapter->tx_obj[skb_get_queue_mapping(skb)];
+ struct be_queue_info *txq = &txo->q;
u32 wrb_cnt = 0, copied = 0;
u32 start = txq->head;
bool dummy_wrb, stopped = false;
wrb_cnt = wrb_cnt_for_skb(adapter, skb, &dummy_wrb);
- copied = make_tx_wrbs(adapter, skb, wrb_cnt, dummy_wrb);
+ copied = make_tx_wrbs(adapter, txq, skb, wrb_cnt, dummy_wrb);
if (copied) {
/* record the sent skb in the sent_skb table */
- BUG_ON(tx_obj->sent_skb_list[start]);
- tx_obj->sent_skb_list[start] = skb;
+ BUG_ON(txo->sent_skb_list[start]);
+ txo->sent_skb_list[start] = skb;
/* Ensure txq has space for the next skb; Else stop the queue
* *BEFORE* ringing the tx doorbell, so that we serialze the
@@ -774,13 +778,13 @@
atomic_add(wrb_cnt, &txq->used);
if ((BE_MAX_TX_FRAG_COUNT + atomic_read(&txq->used)) >=
txq->len) {
- netif_stop_queue(netdev);
+ netif_stop_subqueue(netdev, skb_get_queue_mapping(skb));
stopped = true;
}
be_txq_notify(adapter, txq->id, wrb_cnt);
- be_tx_stats_update(adapter, wrb_cnt, copied,
+ be_tx_stats_update(txo, wrb_cnt, copied,
skb_shinfo(skb)->gso_segs, stopped);
} else {
txq->head = start;
@@ -1459,11 +1463,12 @@
return txcp;
}
-static u16 be_tx_compl_process(struct be_adapter *adapter, u16 last_index)
+static u16 be_tx_compl_process(struct be_adapter *adapter,
+ struct be_tx_obj *txo, u16 last_index)
{
- struct be_queue_info *txq = &adapter->tx_obj.q;
+ struct be_queue_info *txq = &txo->q;
struct be_eth_wrb *wrb;
- struct sk_buff **sent_skbs = adapter->tx_obj.sent_skb_list;
+ struct sk_buff **sent_skbs = txo->sent_skb_list;
struct sk_buff *sent_skb;
u16 cur_index, num_wrbs = 1; /* account for hdr wrb */
bool unmap_skb_hdr = true;
@@ -1504,7 +1509,8 @@
}
static int event_handle(struct be_adapter *adapter,
- struct be_eq_obj *eq_obj)
+ struct be_eq_obj *eq_obj,
+ bool rearm)
{
struct be_eq_entry *eqe;
u16 num = 0;
@@ -1517,7 +1523,10 @@
/* Deal with any spurious interrupts that come
* without events
*/
- be_eq_notify(adapter, eq_obj->q.id, true, true, num);
+ if (!num)
+ rearm = true;
+
+ be_eq_notify(adapter, eq_obj->q.id, rearm, true, num);
if (num)
napi_schedule(&eq_obj->napi);
@@ -1563,15 +1572,17 @@
memset(page_info, 0, sizeof(*page_info));
}
BUG_ON(atomic_read(&rxq->used));
+ rxq->tail = rxq->head = 0;
}
-static void be_tx_compl_clean(struct be_adapter *adapter)
+static void be_tx_compl_clean(struct be_adapter *adapter,
+ struct be_tx_obj *txo)
{
- struct be_queue_info *tx_cq = &adapter->tx_obj.cq;
- struct be_queue_info *txq = &adapter->tx_obj.q;
+ struct be_queue_info *tx_cq = &txo->cq;
+ struct be_queue_info *txq = &txo->q;
struct be_eth_tx_compl *txcp;
u16 end_idx, cmpl = 0, timeo = 0, num_wrbs = 0;
- struct sk_buff **sent_skbs = adapter->tx_obj.sent_skb_list;
+ struct sk_buff **sent_skbs = txo->sent_skb_list;
struct sk_buff *sent_skb;
bool dummy_wrb;
@@ -1580,7 +1591,7 @@
while ((txcp = be_tx_compl_get(tx_cq))) {
end_idx = AMAP_GET_BITS(struct amap_eth_tx_compl,
wrb_index, txcp);
- num_wrbs += be_tx_compl_process(adapter, end_idx);
+ num_wrbs += be_tx_compl_process(adapter, txo, end_idx);
cmpl++;
}
if (cmpl) {
@@ -1607,7 +1618,7 @@
index_adv(&end_idx,
wrb_cnt_for_skb(adapter, sent_skb, &dummy_wrb) - 1,
txq->len);
- num_wrbs = be_tx_compl_process(adapter, end_idx);
+ num_wrbs = be_tx_compl_process(adapter, txo, end_idx);
atomic_sub(num_wrbs, &txq->used);
}
}
@@ -1666,16 +1677,20 @@
static void be_tx_queues_destroy(struct be_adapter *adapter)
{
struct be_queue_info *q;
+ struct be_tx_obj *txo;
+ u8 i;
- q = &adapter->tx_obj.q;
- if (q->created)
- be_cmd_q_destroy(adapter, q, QTYPE_TXQ);
- be_queue_free(adapter, q);
+ for_all_tx_queues(adapter, txo, i) {
+ q = &txo->q;
+ if (q->created)
+ be_cmd_q_destroy(adapter, q, QTYPE_TXQ);
+ be_queue_free(adapter, q);
- q = &adapter->tx_obj.cq;
- if (q->created)
- be_cmd_q_destroy(adapter, q, QTYPE_CQ);
- be_queue_free(adapter, q);
+ q = &txo->cq;
+ if (q->created)
+ be_cmd_q_destroy(adapter, q, QTYPE_CQ);
+ be_queue_free(adapter, q);
+ }
/* Clear any residual events */
be_eq_clean(adapter, &adapter->tx_eq);
@@ -1686,56 +1701,48 @@
be_queue_free(adapter, q);
}
+/* One TX event queue is shared by all TX compl qs */
static int be_tx_queues_create(struct be_adapter *adapter)
{
struct be_queue_info *eq, *q, *cq;
+ struct be_tx_obj *txo;
+ u8 i;
adapter->tx_eq.max_eqd = 0;
adapter->tx_eq.min_eqd = 0;
adapter->tx_eq.cur_eqd = 96;
adapter->tx_eq.enable_aic = false;
- /* Alloc Tx Event queue */
+
eq = &adapter->tx_eq.q;
- if (be_queue_alloc(adapter, eq, EVNT_Q_LEN, sizeof(struct be_eq_entry)))
+ if (be_queue_alloc(adapter, eq, EVNT_Q_LEN,
+ sizeof(struct be_eq_entry)))
return -1;
- /* Ask BE to create Tx Event queue */
if (be_cmd_eq_create(adapter, eq, adapter->tx_eq.cur_eqd))
- goto tx_eq_free;
-
+ goto err;
adapter->tx_eq.eq_idx = adapter->eq_next_idx++;
-
- /* Alloc TX eth compl queue */
- cq = &adapter->tx_obj.cq;
- if (be_queue_alloc(adapter, cq, TX_CQ_LEN,
+ for_all_tx_queues(adapter, txo, i) {
+ cq = &txo->cq;
+ if (be_queue_alloc(adapter, cq, TX_CQ_LEN,
sizeof(struct be_eth_tx_compl)))
- goto tx_eq_destroy;
+ goto err;
- /* Ask BE to create Tx eth compl queue */
- if (be_cmd_cq_create(adapter, cq, eq, false, false, 3))
- goto tx_cq_free;
+ if (be_cmd_cq_create(adapter, cq, eq, false, false, 3))
+ goto err;
- /* Alloc TX eth queue */
- q = &adapter->tx_obj.q;
- if (be_queue_alloc(adapter, q, TX_Q_LEN, sizeof(struct be_eth_wrb)))
- goto tx_cq_destroy;
+ q = &txo->q;
+ if (be_queue_alloc(adapter, q, TX_Q_LEN,
+ sizeof(struct be_eth_wrb)))
+ goto err;
- /* Ask BE to create Tx eth queue */
- if (be_cmd_txq_create(adapter, q, cq))
- goto tx_q_free;
+ if (be_cmd_txq_create(adapter, q, cq))
+ goto err;
+ }
return 0;
-tx_q_free:
- be_queue_free(adapter, q);
-tx_cq_destroy:
- be_cmd_q_destroy(adapter, cq, QTYPE_CQ);
-tx_cq_free:
- be_queue_free(adapter, cq);
-tx_eq_destroy:
- be_cmd_q_destroy(adapter, eq, QTYPE_EQ);
-tx_eq_free:
- be_queue_free(adapter, eq);
+err:
+ be_tx_queues_destroy(adapter);
return -1;
}
@@ -1746,36 +1753,23 @@
int i;
for_all_rx_queues(adapter, rxo, i) {
- q = &rxo->q;
- if (q->created) {
- be_cmd_q_destroy(adapter, q, QTYPE_RXQ);
- /* After the rxq is invalidated, wait for a grace time
- * of 1ms for all dma to end and the flush compl to
- * arrive
- */
- mdelay(1);
- be_rx_q_clean(adapter, rxo);
- }
- be_queue_free(adapter, q);
+ be_queue_free(adapter, &rxo->q);
q = &rxo->cq;
if (q->created)
be_cmd_q_destroy(adapter, q, QTYPE_CQ);
be_queue_free(adapter, q);
- /* Clear any residual events */
q = &rxo->rx_eq.q;
- if (q->created) {
- be_eq_clean(adapter, &rxo->rx_eq);
+ if (q->created)
be_cmd_q_destroy(adapter, q, QTYPE_EQ);
- }
be_queue_free(adapter, q);
}
}
static u32 be_num_rxqs_want(struct be_adapter *adapter)
{
- if (multi_rxq && (adapter->function_caps & BE_FUNCTION_CAPS_RSS) &&
+ if ((adapter->function_caps & BE_FUNCTION_CAPS_RSS) &&
!adapter->sriov_enabled && !(adapter->function_mode & 0x400)) {
return 1 + MAX_RSS_QS; /* one default non-RSS queue */
} else {
@@ -1827,30 +1821,14 @@
rc = be_cmd_cq_create(adapter, cq, eq, false, false, 3);
if (rc)
goto err;
- /* Rx Q */
+
+ /* Rx Q - will be created in be_open() */
q = &rxo->q;
rc = be_queue_alloc(adapter, q, RX_Q_LEN,
sizeof(struct be_eth_rx_d));
if (rc)
goto err;
- rc = be_cmd_rxq_create(adapter, q, cq->id, rx_frag_size,
- BE_MAX_JUMBO_FRAME_SIZE, adapter->if_handle,
- (i > 0) ? 1 : 0/* rss enable */, &rxo->rss_id);
- if (rc)
- goto err;
- }
-
- if (be_multi_rxq(adapter)) {
- u8 rsstable[MAX_RSS_QS];
-
- for_all_rss_queues(adapter, rxo, i)
- rsstable[i] = rxo->rss_id;
-
- rc = be_cmd_rss_config(adapter, rsstable,
- adapter->num_rx_qs - 1);
- if (rc)
- goto err;
}
return 0;
@@ -1876,10 +1854,10 @@
if (lancer_chip(adapter)) {
if (event_peek(&adapter->tx_eq))
- tx = event_handle(adapter, &adapter->tx_eq);
+ tx = event_handle(adapter, &adapter->tx_eq, false);
for_all_rx_queues(adapter, rxo, i) {
if (event_peek(&rxo->rx_eq))
- rx |= event_handle(adapter, &rxo->rx_eq);
+ rx |= event_handle(adapter, &rxo->rx_eq, true);
}
if (!(tx || rx))
@@ -1892,11 +1870,11 @@
return IRQ_NONE;
if ((1 << adapter->tx_eq.eq_idx & isr))
- event_handle(adapter, &adapter->tx_eq);
+ event_handle(adapter, &adapter->tx_eq, false);
for_all_rx_queues(adapter, rxo, i) {
if ((1 << rxo->rx_eq.eq_idx & isr))
- event_handle(adapter, &rxo->rx_eq);
+ event_handle(adapter, &rxo->rx_eq, true);
}
}
@@ -1908,7 +1886,7 @@
struct be_rx_obj *rxo = dev;
struct be_adapter *adapter = rxo->adapter;
- event_handle(adapter, &rxo->rx_eq);
+ event_handle(adapter, &rxo->rx_eq, true);
return IRQ_HANDLED;
}
@@ -1917,7 +1895,7 @@
{
struct be_adapter *adapter = dev;
- event_handle(adapter, &adapter->tx_eq);
+ event_handle(adapter, &adapter->tx_eq, false);
return IRQ_HANDLED;
}
@@ -1978,45 +1956,48 @@
struct be_eq_obj *tx_eq = container_of(napi, struct be_eq_obj, napi);
struct be_adapter *adapter =
container_of(tx_eq, struct be_adapter, tx_eq);
- struct be_queue_info *txq = &adapter->tx_obj.q;
- struct be_queue_info *tx_cq = &adapter->tx_obj.cq;
+ struct be_tx_obj *txo;
struct be_eth_tx_compl *txcp;
- int tx_compl = 0, mcc_compl, status = 0;
- u16 end_idx, num_wrbs = 0;
+ int tx_compl, mcc_compl, status = 0;
+ u8 i;
+ u16 num_wrbs;
- while ((txcp = be_tx_compl_get(tx_cq))) {
- end_idx = AMAP_GET_BITS(struct amap_eth_tx_compl,
- wrb_index, txcp);
- num_wrbs += be_tx_compl_process(adapter, end_idx);
- tx_compl++;
+ for_all_tx_queues(adapter, txo, i) {
+ tx_compl = 0;
+ num_wrbs = 0;
+ while ((txcp = be_tx_compl_get(&txo->cq))) {
+ num_wrbs += be_tx_compl_process(adapter, txo,
+ AMAP_GET_BITS(struct amap_eth_tx_compl,
+ wrb_index, txcp));
+ tx_compl++;
+ }
+ if (tx_compl) {
+ be_cq_notify(adapter, txo->cq.id, true, tx_compl);
+
+ atomic_sub(num_wrbs, &txo->q.used);
+
+ /* As Tx wrbs have been freed up, wake up netdev queue
+ * if it was stopped due to lack of tx wrbs. */
+ if (__netif_subqueue_stopped(adapter->netdev, i) &&
+ atomic_read(&txo->q.used) < txo->q.len / 2) {
+ netif_wake_subqueue(adapter->netdev, i);
+ }
+
+ adapter->drv_stats.be_tx_events++;
+ txo->stats.be_tx_compl += tx_compl;
+ }
}
mcc_compl = be_process_mcc(adapter, &status);
- napi_complete(napi);
-
if (mcc_compl) {
struct be_mcc_obj *mcc_obj = &adapter->mcc_obj;
be_cq_notify(adapter, mcc_obj->cq.id, true, mcc_compl);
}
- if (tx_compl) {
- be_cq_notify(adapter, adapter->tx_obj.cq.id, true, tx_compl);
+ napi_complete(napi);
- atomic_sub(num_wrbs, &txq->used);
-
- /* As Tx wrbs have been freed up, wake up netdev queue if
- * it was stopped due to lack of tx wrbs.
- */
- if (netif_queue_stopped(adapter->netdev) &&
- atomic_read(&txq->used) < txq->len / 2) {
- netif_wake_queue(adapter->netdev);
- }
-
- tx_stats(adapter)->be_tx_events++;
- tx_stats(adapter)->be_tx_compl += tx_compl;
- }
-
+ be_eq_notify(adapter, tx_eq->q.id, true, false, 0);
return 1;
}
@@ -2065,6 +2046,7 @@
struct be_adapter *adapter =
container_of(work, struct be_adapter, work.work);
struct be_rx_obj *rxo;
+ struct be_tx_obj *txo;
int i;
if (!adapter->ue_detected && !lancer_chip(adapter))
@@ -2092,7 +2074,9 @@
else
be_cmd_get_stats(adapter, &adapter->stats_cmd);
}
- be_tx_rate_update(adapter);
+
+ for_all_tx_queues(adapter, txo, i)
+ be_tx_rate_update(txo);
for_all_rx_queues(adapter, rxo, i) {
be_rx_rate_update(rxo);
@@ -2290,10 +2274,36 @@
adapter->isr_registered = false;
}
+static void be_rx_queues_clear(struct be_adapter *adapter)
+{
+ struct be_queue_info *q;
+ struct be_rx_obj *rxo;
+ int i;
+
+ for_all_rx_queues(adapter, rxo, i) {
+ q = &rxo->q;
+ if (q->created) {
+ be_cmd_rxq_destroy(adapter, q);
+ /* After the rxq is invalidated, wait for a grace time
+ * of 1ms for all dma to end and the flush compl to
+ * arrive
+ */
+ mdelay(1);
+ be_rx_q_clean(adapter, rxo);
+ }
+
+ /* Clear any residual events */
+ q = &rxo->rx_eq.q;
+ if (q->created)
+ be_eq_clean(adapter, &rxo->rx_eq);
+ }
+}
+
static int be_close(struct net_device *netdev)
{
struct be_adapter *adapter = netdev_priv(netdev);
struct be_rx_obj *rxo;
+ struct be_tx_obj *txo;
struct be_eq_obj *tx_eq = &adapter->tx_eq;
int vec, i;
@@ -2311,10 +2321,11 @@
napi_disable(&tx_eq->napi);
if (lancer_chip(adapter)) {
- be_cq_notify(adapter, adapter->tx_obj.cq.id, false, 0);
be_cq_notify(adapter, adapter->mcc_obj.cq.id, false, 0);
for_all_rx_queues(adapter, rxo, i)
be_cq_notify(adapter, rxo->cq.id, false, 0);
+ for_all_tx_queues(adapter, txo, i)
+ be_cq_notify(adapter, txo->cq.id, false, 0);
}
if (msix_enabled(adapter)) {
@@ -2333,8 +2344,43 @@
/* Wait for all pending tx completions to arrive so that
* all tx skbs are freed.
*/
- be_tx_compl_clean(adapter);
+ for_all_tx_queues(adapter, txo, i)
+ be_tx_compl_clean(adapter, txo);
+ be_rx_queues_clear(adapter);
+ return 0;
+}
+
+static int be_rx_queues_setup(struct be_adapter *adapter)
+{
+ struct be_rx_obj *rxo;
+ int rc, i;
+ u8 rsstable[MAX_RSS_QS];
+
+ for_all_rx_queues(adapter, rxo, i) {
+ rc = be_cmd_rxq_create(adapter, &rxo->q, rxo->cq.id,
+ rx_frag_size, BE_MAX_JUMBO_FRAME_SIZE,
+ adapter->if_handle,
+ (i > 0) ? 1 : 0/* rss enable */, &rxo->rss_id);
+ if (rc)
+ return rc;
+ }
+
+ if (be_multi_rxq(adapter)) {
+ for_all_rss_queues(adapter, rxo, i)
+ rsstable[i] = rxo->rss_id;
+
+ rc = be_cmd_rss_config(adapter, rsstable,
+ adapter->num_rx_qs - 1);
+ if (rc)
+ return rc;
+ }
+
+ /* First time posting */
+ for_all_rx_queues(adapter, rxo, i) {
+ be_post_rx_frags(rxo, GFP_KERNEL);
+ napi_enable(&rxo->rx_eq.napi);
+ }
return 0;
}
@@ -2348,10 +2394,10 @@
u8 mac_speed;
u16 link_speed;
- for_all_rx_queues(adapter, rxo, i) {
- be_post_rx_frags(rxo, GFP_KERNEL);
- napi_enable(&rxo->rx_eq.napi);
- }
+ status = be_rx_queues_setup(adapter);
+ if (status)
+ goto err;
+
napi_enable(&tx_eq->napi);
be_irq_register(adapter);
@@ -2539,6 +2585,9 @@
if (status != 0)
goto tx_qs_destroy;
+ /* Allow all priorities by default. A GRP5 evt may modify this */
+ adapter->vlan_prio_bmap = 0xff;
+
status = be_mcc_queues_create(adapter);
if (status != 0)
goto rx_qs_destroy;
@@ -2925,12 +2974,9 @@
netdev->features |= netdev->hw_features |
NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_FILTER;
- netdev->vlan_features |= NETIF_F_SG | NETIF_F_TSO |
+ netdev->vlan_features |= NETIF_F_SG | NETIF_F_TSO | NETIF_F_TSO6 |
NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
- if (lancer_chip(adapter))
- netdev->vlan_features |= NETIF_F_TSO6;
-
netdev->flags |= IFF_MULTICAST;
/* Default settings for Rx and Tx flow control */
@@ -3186,6 +3232,17 @@
return status;
be_cmd_check_native_mode(adapter);
+
+ if ((num_vfs && adapter->sriov_enabled) ||
+ (adapter->function_mode & 0x400) ||
+ lancer_chip(adapter) || !be_physfn(adapter)) {
+ adapter->num_tx_qs = 1;
+ netif_set_real_num_tx_queues(adapter->netdev,
+ adapter->num_tx_qs);
+ } else {
+ adapter->num_tx_qs = MAX_TX_QS;
+ }
+
return 0;
}
@@ -3288,7 +3345,7 @@
goto disable_dev;
pci_set_master(pdev);
- netdev = alloc_etherdev(sizeof(struct be_adapter));
+ netdev = alloc_etherdev_mq(sizeof(struct be_adapter), MAX_TX_QS);
if (netdev == NULL) {
status = -ENOMEM;
goto rel_reg;
@@ -3360,6 +3417,12 @@
if (status)
goto stats_clean;
+ /* The INTR bit may be set in the card when probed by a kdump kernel
+ * after a crash.
+ */
+ if (!lancer_chip(adapter))
+ be_intr_set(adapter, false);
+
be_msix_enable(adapter);
INIT_DELAYED_WORK(&adapter->work, be_worker);
@@ -3396,6 +3459,7 @@
}
dev_info(&pdev->dev, "%s port %d\n", nic_name(pdev), adapter->port_num);
+
schedule_delayed_work(&adapter->work, msecs_to_jiffies(100));
return 0;
diff --git a/drivers/net/bmac.c b/drivers/net/bmac.c
index a1b8c8b..d2e58e2 100644
--- a/drivers/net/bmac.c
+++ b/drivers/net/bmac.c
@@ -7,6 +7,7 @@
* May 1999, Al Viro: proper release of /proc/net/bmac entry, switched to
* dynamic procfs inode.
*/
+#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/netdevice.h>
diff --git a/drivers/net/bna/bfa_cee.c b/drivers/net/bna/bfa_cee.c
index f7b789a..dcfbf08 100644
--- a/drivers/net/bna/bfa_cee.c
+++ b/drivers/net/bna/bfa_cee.c
@@ -236,7 +236,7 @@
bfa_cee_hbfail(void *arg)
{
struct bfa_cee *cee;
- cee = (struct bfa_cee *) arg;
+ cee = arg;
if (cee->get_attr_pending == true) {
cee->get_attr_status = BFA_STATUS_FAILED;
diff --git a/drivers/net/bna/cna.h b/drivers/net/bna/cna.h
index bbd39dc..01b4af7 100644
--- a/drivers/net/bna/cna.h
+++ b/drivers/net/bna/cna.h
@@ -19,7 +19,6 @@
#ifndef __CNA_H__
#define __CNA_H__
-#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/pci.h>
@@ -74,7 +73,7 @@
bfa_q_next(_q) = bfa_q_next(*((struct list_head **) _qe)); \
bfa_q_qe_init(*((struct list_head **) _qe)); \
} else { \
- *((struct list_head **) (_qe)) = (struct list_head *) NULL; \
+ *((struct list_head **)(_qe)) = NULL; \
} \
}
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index 57d3293..7915d14 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -416,6 +416,9 @@
struct bnx2 *bp = netdev_priv(dev);
struct cnic_eth_dev *cp = &bp->cnic_eth_dev;
+ if (!cp->max_iscsi_conn)
+ return NULL;
+
cp->drv_owner = THIS_MODULE;
cp->chip_id = bp->chip_id;
cp->pdev = bp->pdev;
@@ -7908,9 +7911,8 @@
bp->chip_id = REG_RD(bp, BNX2_MISC_ID);
if (CHIP_NUM(bp) == CHIP_NUM_5709) {
- if (pci_find_capability(pdev, PCI_CAP_ID_EXP) == 0) {
- dev_err(&pdev->dev,
- "Cannot find PCIE capability, aborting\n");
+ if (!pci_is_pcie(pdev)) {
+ dev_err(&pdev->dev, "Not PCIE, aborting\n");
rc = -EIO;
goto err_out_unmap;
}
@@ -8177,6 +8179,10 @@
bp->timer.data = (unsigned long) bp;
bp->timer.function = bnx2_timer;
+#ifdef BCM_CNIC
+ bp->cnic_eth_dev.max_iscsi_conn =
+ bnx2_reg_rd_ind(bp, BNX2_FW_MAX_ISCSI_CONN);
+#endif
pci_save_state(pdev);
return 0;
diff --git a/drivers/net/bnx2x/Makefile b/drivers/net/bnx2x/Makefile
index bb83a29..48fbdd4 100644
--- a/drivers/net/bnx2x/Makefile
+++ b/drivers/net/bnx2x/Makefile
@@ -4,4 +4,4 @@
obj-$(CONFIG_BNX2X) += bnx2x.o
-bnx2x-objs := bnx2x_main.o bnx2x_link.o bnx2x_cmn.o bnx2x_ethtool.o bnx2x_stats.o bnx2x_dcb.o
+bnx2x-objs := bnx2x_main.o bnx2x_link.o bnx2x_cmn.o bnx2x_ethtool.o bnx2x_stats.o bnx2x_dcb.o bnx2x_sp.o
diff --git a/drivers/net/bnx2x/bnx2x.h b/drivers/net/bnx2x/bnx2x.h
index 668a578..0d4b981 100644
--- a/drivers/net/bnx2x/bnx2x.h
+++ b/drivers/net/bnx2x/bnx2x.h
@@ -14,6 +14,7 @@
#ifndef BNX2X_H
#define BNX2X_H
#include <linux/netdevice.h>
+#include <linux/dma-mapping.h>
#include <linux/types.h>
/* compilation time flags */
@@ -22,14 +23,10 @@
* (you will need to reboot afterwards) */
/* #define BNX2X_STOP_ON_ERROR */
-#define DRV_MODULE_VERSION "1.62.12-0"
-#define DRV_MODULE_RELDATE "2011/03/20"
+#define DRV_MODULE_VERSION "1.70.00-0"
+#define DRV_MODULE_RELDATE "2011/06/13"
#define BNX2X_BC_VER 0x040200
-#define BNX2X_MULTI_QUEUE
-
-#define BNX2X_NEW_NAPI
-
#if defined(CONFIG_DCB)
#define BCM_DCBNL
#endif
@@ -47,11 +44,12 @@
#endif
#include <linux/mdio.h>
-#include <linux/pci.h>
+
#include "bnx2x_reg.h"
#include "bnx2x_fw_defs.h"
#include "bnx2x_hsi.h"
#include "bnx2x_link.h"
+#include "bnx2x_sp.h"
#include "bnx2x_dcb.h"
#include "bnx2x_stats.h"
@@ -80,6 +78,12 @@
##__args); \
} while (0)
+#define DP_CONT(__mask, __fmt, __args...) \
+do { \
+ if (bp->msg_enable & (__mask)) \
+ pr_cont(__fmt, ##__args); \
+} while (0)
+
/* errors debug print */
#define BNX2X_DBG_ERR(__fmt, __args...) \
do { \
@@ -111,7 +115,9 @@
dev_info(&bp->pdev->dev, __fmt, ##__args); \
} while (0)
-void bnx2x_panic_dump(struct bnx2x *bp);
+#define BNX2X_MAC_FMT "%pM"
+#define BNX2X_MAC_PRN_LIST(mac) (mac)
+
#ifdef BNX2X_STOP_ON_ERROR
#define bnx2x_panic() do { \
@@ -233,11 +239,11 @@
*
*/
/* iSCSI L2 */
-#define BNX2X_ISCSI_ETH_CL_ID 17
+#define BNX2X_ISCSI_ETH_CL_ID_IDX 1
#define BNX2X_ISCSI_ETH_CID 17
/* FCoE L2 */
-#define BNX2X_FCOE_ETH_CL_ID 18
+#define BNX2X_FCOE_ETH_CL_ID_IDX 2
#define BNX2X_FCOE_ETH_CID 18
/** Additional rings budgeting */
@@ -283,44 +289,73 @@
/* MC hsi */
-#define BCM_PAGE_SHIFT 12
-#define BCM_PAGE_SIZE (1 << BCM_PAGE_SHIFT)
-#define BCM_PAGE_MASK (~(BCM_PAGE_SIZE - 1))
+#define BCM_PAGE_SHIFT 12
+#define BCM_PAGE_SIZE (1 << BCM_PAGE_SHIFT)
+#define BCM_PAGE_MASK (~(BCM_PAGE_SIZE - 1))
#define BCM_PAGE_ALIGN(addr) (((addr) + BCM_PAGE_SIZE - 1) & BCM_PAGE_MASK)
-#define PAGES_PER_SGE_SHIFT 0
-#define PAGES_PER_SGE (1 << PAGES_PER_SGE_SHIFT)
-#define SGE_PAGE_SIZE PAGE_SIZE
-#define SGE_PAGE_SHIFT PAGE_SHIFT
-#define SGE_PAGE_ALIGN(addr) PAGE_ALIGN((typeof(PAGE_SIZE))(addr))
+#define PAGES_PER_SGE_SHIFT 0
+#define PAGES_PER_SGE (1 << PAGES_PER_SGE_SHIFT)
+#define SGE_PAGE_SIZE PAGE_SIZE
+#define SGE_PAGE_SHIFT PAGE_SHIFT
+#define SGE_PAGE_ALIGN(addr) PAGE_ALIGN((typeof(PAGE_SIZE))(addr))
/* SGE ring related macros */
-#define NUM_RX_SGE_PAGES 2
+#define NUM_RX_SGE_PAGES 2
#define RX_SGE_CNT (BCM_PAGE_SIZE / sizeof(struct eth_rx_sge))
-#define MAX_RX_SGE_CNT (RX_SGE_CNT - 2)
+#define MAX_RX_SGE_CNT (RX_SGE_CNT - 2)
/* RX_SGE_CNT is promised to be a power of 2 */
-#define RX_SGE_MASK (RX_SGE_CNT - 1)
-#define NUM_RX_SGE (RX_SGE_CNT * NUM_RX_SGE_PAGES)
-#define MAX_RX_SGE (NUM_RX_SGE - 1)
+#define RX_SGE_MASK (RX_SGE_CNT - 1)
+#define NUM_RX_SGE (RX_SGE_CNT * NUM_RX_SGE_PAGES)
+#define MAX_RX_SGE (NUM_RX_SGE - 1)
#define NEXT_SGE_IDX(x) ((((x) & RX_SGE_MASK) == \
(MAX_RX_SGE_CNT - 1)) ? (x) + 3 : (x) + 1)
-#define RX_SGE(x) ((x) & MAX_RX_SGE)
+#define RX_SGE(x) ((x) & MAX_RX_SGE)
-/* SGE producer mask related macros */
+/* Manipulate a bit vector defined as an array of u64 */
+
/* Number of bits in one sge_mask array element */
-#define RX_SGE_MASK_ELEM_SZ 64
-#define RX_SGE_MASK_ELEM_SHIFT 6
-#define RX_SGE_MASK_ELEM_MASK ((u64)RX_SGE_MASK_ELEM_SZ - 1)
+#define BIT_VEC64_ELEM_SZ 64
+#define BIT_VEC64_ELEM_SHIFT 6
+#define BIT_VEC64_ELEM_MASK ((u64)BIT_VEC64_ELEM_SZ - 1)
+
+
+#define __BIT_VEC64_SET_BIT(el, bit) \
+ do { \
+ el = ((el) | ((u64)0x1 << (bit))); \
+ } while (0)
+
+#define __BIT_VEC64_CLEAR_BIT(el, bit) \
+ do { \
+ el = ((el) & (~((u64)0x1 << (bit)))); \
+ } while (0)
+
+
+#define BIT_VEC64_SET_BIT(vec64, idx) \
+ __BIT_VEC64_SET_BIT((vec64)[(idx) >> BIT_VEC64_ELEM_SHIFT], \
+ (idx) & BIT_VEC64_ELEM_MASK)
+
+#define BIT_VEC64_CLEAR_BIT(vec64, idx) \
+ __BIT_VEC64_CLEAR_BIT((vec64)[(idx) >> BIT_VEC64_ELEM_SHIFT], \
+ (idx) & BIT_VEC64_ELEM_MASK)
+
+#define BIT_VEC64_TEST_BIT(vec64, idx) \
+ (((vec64)[(idx) >> BIT_VEC64_ELEM_SHIFT] >> \
+ ((idx) & BIT_VEC64_ELEM_MASK)) & 0x1)
/* Creates a bitmask of all ones in less significant bits.
idx - index of the most significant bit in the created mask */
-#define RX_SGE_ONES_MASK(idx) \
- (((u64)0x1 << (((idx) & RX_SGE_MASK_ELEM_MASK) + 1)) - 1)
-#define RX_SGE_MASK_ELEM_ONE_MASK ((u64)(~0))
+#define BIT_VEC64_ONES_MASK(idx) \
+ (((u64)0x1 << (((idx) & BIT_VEC64_ELEM_MASK) + 1)) - 1)
+#define BIT_VEC64_ELEM_ONE_MASK ((u64)(~0))
+
+/*******************************************************/
+
+
/* Number of u64 elements in SGE mask array */
#define RX_SGE_MASK_LEN ((NUM_RX_SGE_PAGES * RX_SGE_CNT) / \
- RX_SGE_MASK_ELEM_SZ)
+ BIT_VEC64_ELEM_SZ)
#define RX_SGE_MASK_LEN_MASK (RX_SGE_MASK_LEN - 1)
#define NEXT_SGE_MASK_ELEM(el) (((el) + 1) & RX_SGE_MASK_LEN_MASK)
@@ -331,7 +366,30 @@
struct host_hc_status_block_e2 *e2_sb;
};
+struct bnx2x_agg_info {
+ /*
+ * First aggregation buffer is an skb, the following - are pages.
+ * We will preallocate the skbs for each aggregation when
+ * we open the interface and will replace the BD at the consumer
+ * with this one when we receive the TPA_START CQE in order to
+ * keep the Rx BD ring consistent.
+ */
+ struct sw_rx_bd first_buf;
+ u8 tpa_state;
+#define BNX2X_TPA_START 1
+#define BNX2X_TPA_STOP 2
+#define BNX2X_TPA_ERROR 3
+ u8 placement_offset;
+ u16 parsing_flags;
+ u16 vlan_tag;
+ u16 len_on_bd;
+};
+
+#define Q_STATS_OFFSET32(stat_name) \
+ (offsetof(struct bnx2x_eth_q_stats, stat_name) / 4)
+
struct bnx2x_fastpath {
+ struct bnx2x *bp; /* parent */
#define BNX2X_NAPI_WEIGHT 128
struct napi_struct napi;
@@ -366,23 +424,13 @@
u64 sge_mask[RX_SGE_MASK_LEN];
- int state;
-#define BNX2X_FP_STATE_CLOSED 0
-#define BNX2X_FP_STATE_IRQ 0x80000
-#define BNX2X_FP_STATE_OPENING 0x90000
-#define BNX2X_FP_STATE_OPEN 0xa0000
-#define BNX2X_FP_STATE_HALTING 0xb0000
-#define BNX2X_FP_STATE_HALTED 0xc0000
-#define BNX2X_FP_STATE_TERMINATING 0xd0000
-#define BNX2X_FP_STATE_TERMINATED 0xe0000
+ u32 cid;
u8 index; /* number in fp array */
u8 cl_id; /* eth client id */
u8 cl_qzone_id;
u8 fw_sb_id; /* status block number in FW */
u8 igu_sb_id; /* status block number in HW */
- u32 cid;
-
union db_prod tx_db;
u16 tx_pkt_prod;
@@ -401,24 +449,20 @@
/* The last maximal completed SGE */
u16 last_max_sge;
__le16 *rx_cons_sb;
-
unsigned long tx_pkt,
rx_pkt,
rx_calls;
/* TPA related */
- struct sw_rx_bd tpa_pool[ETH_MAX_AGGREGATION_QUEUES_E1H];
- u8 tpa_state[ETH_MAX_AGGREGATION_QUEUES_E1H];
-#define BNX2X_TPA_START 1
-#define BNX2X_TPA_STOP 2
+ struct bnx2x_agg_info tpa_info[ETH_MAX_AGGREGATION_QUEUES_E1H_E2];
u8 disable_tpa;
#ifdef BNX2X_STOP_ON_ERROR
u64 tpa_queue_used;
#endif
- struct tstorm_per_client_stats old_tclient;
- struct ustorm_per_client_stats old_uclient;
- struct xstorm_per_client_stats old_xclient;
+ struct tstorm_per_queue_stats old_tclient;
+ struct ustorm_per_queue_stats old_uclient;
+ struct xstorm_per_queue_stats old_xclient;
struct bnx2x_eth_q_stats eth_q_stats;
/* The size is calculated using the following:
@@ -427,7 +471,13 @@
4 (for the digits and to make it DWORD aligned) */
#define FP_NAME_SIZE (sizeof(((struct net_device *)0)->name) + 8)
char name[FP_NAME_SIZE];
- struct bnx2x *bp; /* parent */
+
+ /* MACs object */
+ struct bnx2x_vlan_mac_obj mac_obj;
+
+ /* Queue State object */
+ struct bnx2x_queue_sp_obj q_obj;
+
};
#define bnx2x_fp(bp, nr, var) (bp->fp[nr].var)
@@ -435,11 +485,13 @@
/* Use 2500 as a mini-jumbo MTU for FCoE */
#define BNX2X_FCOE_MINI_JUMBO_MTU 2500
-#ifdef BCM_CNIC
-/* FCoE L2 `fastpath' is right after the eth entries */
+/* FCoE L2 `fastpath' entry is right after the eth entries */
#define FCOE_IDX BNX2X_NUM_ETH_QUEUES(bp)
#define bnx2x_fcoe_fp(bp) (&bp->fp[FCOE_IDX])
#define bnx2x_fcoe(bp, var) (bnx2x_fcoe_fp(bp)->var)
+
+
+#ifdef BCM_CNIC
#define IS_FCOE_FP(fp) (fp->index == FCOE_IDX)
#define IS_FCOE_IDX(idx) ((idx) == FCOE_IDX)
#else
@@ -449,77 +501,68 @@
/* MC hsi */
-#define MAX_FETCH_BD 13 /* HW max BDs per packet */
-#define RX_COPY_THRESH 92
+#define MAX_FETCH_BD 13 /* HW max BDs per packet */
+#define RX_COPY_THRESH 92
-#define NUM_TX_RINGS 16
+#define NUM_TX_RINGS 16
#define TX_DESC_CNT (BCM_PAGE_SIZE / sizeof(union eth_tx_bd_types))
-#define MAX_TX_DESC_CNT (TX_DESC_CNT - 1)
-#define NUM_TX_BD (TX_DESC_CNT * NUM_TX_RINGS)
-#define MAX_TX_BD (NUM_TX_BD - 1)
-#define MAX_TX_AVAIL (MAX_TX_DESC_CNT * NUM_TX_RINGS - 2)
-#define INIT_JUMBO_TX_RING_SIZE MAX_TX_AVAIL
-#define INIT_TX_RING_SIZE MAX_TX_AVAIL
+#define MAX_TX_DESC_CNT (TX_DESC_CNT - 1)
+#define NUM_TX_BD (TX_DESC_CNT * NUM_TX_RINGS)
+#define MAX_TX_BD (NUM_TX_BD - 1)
+#define MAX_TX_AVAIL (MAX_TX_DESC_CNT * NUM_TX_RINGS - 2)
#define NEXT_TX_IDX(x) ((((x) & MAX_TX_DESC_CNT) == \
(MAX_TX_DESC_CNT - 1)) ? (x) + 2 : (x) + 1)
-#define TX_BD(x) ((x) & MAX_TX_BD)
-#define TX_BD_POFF(x) ((x) & MAX_TX_DESC_CNT)
+#define TX_BD(x) ((x) & MAX_TX_BD)
+#define TX_BD_POFF(x) ((x) & MAX_TX_DESC_CNT)
/* The RX BD ring is special, each bd is 8 bytes but the last one is 16 */
-#define NUM_RX_RINGS 8
+#define NUM_RX_RINGS 8
#define RX_DESC_CNT (BCM_PAGE_SIZE / sizeof(struct eth_rx_bd))
-#define MAX_RX_DESC_CNT (RX_DESC_CNT - 2)
-#define RX_DESC_MASK (RX_DESC_CNT - 1)
-#define NUM_RX_BD (RX_DESC_CNT * NUM_RX_RINGS)
-#define MAX_RX_BD (NUM_RX_BD - 1)
-#define MAX_RX_AVAIL (MAX_RX_DESC_CNT * NUM_RX_RINGS - 2)
-#define MIN_RX_SIZE_TPA 72
-#define MIN_RX_SIZE_NONTPA 10
-#define INIT_JUMBO_RX_RING_SIZE MAX_RX_AVAIL
-#define INIT_RX_RING_SIZE MAX_RX_AVAIL
+#define MAX_RX_DESC_CNT (RX_DESC_CNT - 2)
+#define RX_DESC_MASK (RX_DESC_CNT - 1)
+#define NUM_RX_BD (RX_DESC_CNT * NUM_RX_RINGS)
+#define MAX_RX_BD (NUM_RX_BD - 1)
+#define MAX_RX_AVAIL (MAX_RX_DESC_CNT * NUM_RX_RINGS - 2)
+#define MIN_RX_AVAIL 128
+
+#define MIN_RX_SIZE_TPA_HW (CHIP_IS_E1(bp) ? \
+ ETH_MIN_RX_CQES_WITH_TPA_E1 : \
+ ETH_MIN_RX_CQES_WITH_TPA_E1H_E2)
+#define MIN_RX_SIZE_NONTPA_HW ETH_MIN_RX_CQES_WITHOUT_TPA
+#define MIN_RX_SIZE_TPA (max_t(u32, MIN_RX_SIZE_TPA_HW, MIN_RX_AVAIL))
+#define MIN_RX_SIZE_NONTPA (max_t(u32, MIN_RX_SIZE_NONTPA_HW,\
+ MIN_RX_AVAIL))
+
#define NEXT_RX_IDX(x) ((((x) & RX_DESC_MASK) == \
(MAX_RX_DESC_CNT - 1)) ? (x) + 3 : (x) + 1)
-#define RX_BD(x) ((x) & MAX_RX_BD)
+#define RX_BD(x) ((x) & MAX_RX_BD)
-/* As long as CQE is 4 times bigger than BD entry we have to allocate
- 4 times more pages for CQ ring in order to keep it balanced with
- BD ring */
-#define NUM_RCQ_RINGS (NUM_RX_RINGS * 4)
+/*
+ * As long as CQE is X times bigger than BD entry we have to allocate X times
+ * more pages for CQ ring in order to keep it balanced with BD ring
+ */
+#define CQE_BD_REL (sizeof(union eth_rx_cqe) / sizeof(struct eth_rx_bd))
+#define NUM_RCQ_RINGS (NUM_RX_RINGS * CQE_BD_REL)
#define RCQ_DESC_CNT (BCM_PAGE_SIZE / sizeof(union eth_rx_cqe))
-#define MAX_RCQ_DESC_CNT (RCQ_DESC_CNT - 1)
-#define NUM_RCQ_BD (RCQ_DESC_CNT * NUM_RCQ_RINGS)
-#define MAX_RCQ_BD (NUM_RCQ_BD - 1)
-#define MAX_RCQ_AVAIL (MAX_RCQ_DESC_CNT * NUM_RCQ_RINGS - 2)
+#define MAX_RCQ_DESC_CNT (RCQ_DESC_CNT - 1)
+#define NUM_RCQ_BD (RCQ_DESC_CNT * NUM_RCQ_RINGS)
+#define MAX_RCQ_BD (NUM_RCQ_BD - 1)
+#define MAX_RCQ_AVAIL (MAX_RCQ_DESC_CNT * NUM_RCQ_RINGS - 2)
#define NEXT_RCQ_IDX(x) ((((x) & MAX_RCQ_DESC_CNT) == \
(MAX_RCQ_DESC_CNT - 1)) ? (x) + 2 : (x) + 1)
-#define RCQ_BD(x) ((x) & MAX_RCQ_BD)
+#define RCQ_BD(x) ((x) & MAX_RCQ_BD)
/* This is needed for determining of last_max */
-#define SUB_S16(a, b) (s16)((s16)(a) - (s16)(b))
+#define SUB_S16(a, b) (s16)((s16)(a) - (s16)(b))
+#define SUB_S32(a, b) (s32)((s32)(a) - (s32)(b))
-#define __SGE_MASK_SET_BIT(el, bit) \
- do { \
- el = ((el) | ((u64)0x1 << (bit))); \
- } while (0)
-#define __SGE_MASK_CLEAR_BIT(el, bit) \
- do { \
- el = ((el) & (~((u64)0x1 << (bit)))); \
- } while (0)
-
-#define SGE_MASK_SET_BIT(fp, idx) \
- __SGE_MASK_SET_BIT(fp->sge_mask[(idx) >> RX_SGE_MASK_ELEM_SHIFT], \
- ((idx) & RX_SGE_MASK_ELEM_MASK))
-
-#define SGE_MASK_CLEAR_BIT(fp, idx) \
- __SGE_MASK_CLEAR_BIT(fp->sge_mask[(idx) >> RX_SGE_MASK_ELEM_SHIFT], \
- ((idx) & RX_SGE_MASK_ELEM_MASK))
-
+#define BNX2X_SWCID_SHIFT 17
+#define BNX2X_SWCID_MASK ((0x1 << BNX2X_SWCID_SHIFT) - 1)
/* used on a CID received from the HW */
-#define SW_CID(x) (le32_to_cpu(x) & \
- (COMMON_RAMROD_ETH_RX_CQE_CID >> 7))
+#define SW_CID(x) (le32_to_cpu(x) & BNX2X_SWCID_MASK)
#define CQE_CMD(x) (le32_to_cpu(x) >> \
COMMON_RAMROD_ETH_RX_CQE_CMD_ID_SHIFT)
@@ -529,6 +572,9 @@
#define BNX2X_DB_MIN_SHIFT 3 /* 8 bytes */
#define BNX2X_DB_SHIFT 7 /* 128 bytes*/
+#if (BNX2X_DB_SHIFT < BNX2X_DB_MIN_SHIFT)
+#error "Min DB doorbell stride is 8"
+#endif
#define DPM_TRIGER_TYPE 0x40
#define DOORBELL(bp, cid, val) \
do { \
@@ -557,13 +603,11 @@
/* stuff added to make the code fit 80Col */
-
-#define CQE_TYPE(cqe_fp_flags) ((cqe_fp_flags) & ETH_FAST_PATH_RX_CQE_TYPE)
-
-#define TPA_TYPE_START ETH_FAST_PATH_RX_CQE_START_FLG
-#define TPA_TYPE_END ETH_FAST_PATH_RX_CQE_END_FLG
-#define TPA_TYPE(cqe_fp_flags) ((cqe_fp_flags) & \
- (TPA_TYPE_START | TPA_TYPE_END))
+#define CQE_TYPE(cqe_fp_flags) ((cqe_fp_flags) & ETH_FAST_PATH_RX_CQE_TYPE)
+#define CQE_TYPE_START(cqe_type) ((cqe_type) == RX_ETH_CQE_TYPE_ETH_START_AGG)
+#define CQE_TYPE_STOP(cqe_type) ((cqe_type) == RX_ETH_CQE_TYPE_ETH_STOP_AGG)
+#define CQE_TYPE_SLOW(cqe_type) ((cqe_type) == RX_ETH_CQE_TYPE_ETH_RAMROD)
+#define CQE_TYPE_FAST(cqe_type) ((cqe_type) == RX_ETH_CQE_TYPE_ETH_FASTPATH)
#define ETH_RX_ERROR_FALGS ETH_FAST_PATH_RX_CQE_PHY_DECODE_ERR_FLG
@@ -590,12 +634,30 @@
#define BNX2X_RX_SUM_FIX(cqe) \
BNX2X_PRS_FLAG_OVERETH_IPV4(cqe->fast_path_cqe.pars_flags.flags)
-#define U_SB_ETH_RX_CQ_INDEX 1
-#define U_SB_ETH_RX_BD_INDEX 2
-#define C_SB_ETH_TX_CQ_INDEX 5
+
+#define FP_USB_FUNC_OFF \
+ offsetof(struct cstorm_status_block_u, func)
+#define FP_CSB_FUNC_OFF \
+ offsetof(struct cstorm_status_block_c, func)
+
+#define HC_INDEX_TOE_RX_CQ_CONS 0 /* Formerly Ustorm TOE CQ index */
+ /* (HC_INDEX_U_TOE_RX_CQ_CONS) */
+#define HC_INDEX_ETH_RX_CQ_CONS 1 /* Formerly Ustorm ETH CQ index */
+ /* (HC_INDEX_U_ETH_RX_CQ_CONS) */
+#define HC_INDEX_ETH_RX_BD_CONS 2 /* Formerly Ustorm ETH BD index */
+ /* (HC_INDEX_U_ETH_RX_BD_CONS) */
+
+#define HC_INDEX_TOE_TX_CQ_CONS 4 /* Formerly Cstorm TOE CQ index */
+ /* (HC_INDEX_C_TOE_TX_CQ_CONS) */
+#define HC_INDEX_ETH_TX_CQ_CONS 5 /* Formerly Cstorm ETH CQ index */
+ /* (HC_INDEX_C_ETH_TX_CQ_CONS) */
+
+#define U_SB_ETH_RX_CQ_INDEX HC_INDEX_ETH_RX_CQ_CONS
+#define U_SB_ETH_RX_BD_INDEX HC_INDEX_ETH_RX_BD_CONS
+#define C_SB_ETH_TX_CQ_INDEX HC_INDEX_ETH_TX_CQ_CONS
#define BNX2X_RX_SB_INDEX \
- (&fp->sb_index_values[U_SB_ETH_RX_CQ_INDEX])
+ (&fp->sb_index_values[HC_INDEX_ETH_RX_CQ_CONS])
#define BNX2X_TX_SB_INDEX \
(&fp->sb_index_values[C_SB_ETH_TX_CQ_INDEX])
@@ -615,41 +677,74 @@
#define CHIP_NUM_57711 0x164f
#define CHIP_NUM_57711E 0x1650
#define CHIP_NUM_57712 0x1662
-#define CHIP_NUM_57712E 0x1663
+#define CHIP_NUM_57712_MF 0x1663
+#define CHIP_NUM_57713 0x1651
+#define CHIP_NUM_57713E 0x1652
+#define CHIP_NUM_57800 0x168a
+#define CHIP_NUM_57800_MF 0x16a5
+#define CHIP_NUM_57810 0x168e
+#define CHIP_NUM_57810_MF 0x16ae
+#define CHIP_NUM_57840 0x168d
+#define CHIP_NUM_57840_MF 0x16ab
#define CHIP_IS_E1(bp) (CHIP_NUM(bp) == CHIP_NUM_57710)
#define CHIP_IS_57711(bp) (CHIP_NUM(bp) == CHIP_NUM_57711)
#define CHIP_IS_57711E(bp) (CHIP_NUM(bp) == CHIP_NUM_57711E)
#define CHIP_IS_57712(bp) (CHIP_NUM(bp) == CHIP_NUM_57712)
-#define CHIP_IS_57712E(bp) (CHIP_NUM(bp) == CHIP_NUM_57712E)
+#define CHIP_IS_57712_MF(bp) (CHIP_NUM(bp) == CHIP_NUM_57712_MF)
+#define CHIP_IS_57800(bp) (CHIP_NUM(bp) == CHIP_NUM_57800)
+#define CHIP_IS_57800_MF(bp) (CHIP_NUM(bp) == CHIP_NUM_57800_MF)
+#define CHIP_IS_57810(bp) (CHIP_NUM(bp) == CHIP_NUM_57810)
+#define CHIP_IS_57810_MF(bp) (CHIP_NUM(bp) == CHIP_NUM_57810_MF)
+#define CHIP_IS_57840(bp) (CHIP_NUM(bp) == CHIP_NUM_57840)
+#define CHIP_IS_57840_MF(bp) (CHIP_NUM(bp) == CHIP_NUM_57840_MF)
#define CHIP_IS_E1H(bp) (CHIP_IS_57711(bp) || \
CHIP_IS_57711E(bp))
#define CHIP_IS_E2(bp) (CHIP_IS_57712(bp) || \
- CHIP_IS_57712E(bp))
+ CHIP_IS_57712_MF(bp))
+#define CHIP_IS_E3(bp) (CHIP_IS_57800(bp) || \
+ CHIP_IS_57800_MF(bp) || \
+ CHIP_IS_57810(bp) || \
+ CHIP_IS_57810_MF(bp) || \
+ CHIP_IS_57840(bp) || \
+ CHIP_IS_57840_MF(bp))
#define CHIP_IS_E1x(bp) (CHIP_IS_E1((bp)) || CHIP_IS_E1H((bp)))
-#define IS_E1H_OFFSET (CHIP_IS_E1H(bp) || CHIP_IS_E2(bp))
+#define USES_WARPCORE(bp) (CHIP_IS_E3(bp))
+#define IS_E1H_OFFSET (!CHIP_IS_E1(bp))
-#define CHIP_REV(bp) (bp->common.chip_id & 0x0000f000)
-#define CHIP_REV_Ax 0x00000000
+#define CHIP_REV_SHIFT 12
+#define CHIP_REV_MASK (0xF << CHIP_REV_SHIFT)
+#define CHIP_REV_VAL(bp) (bp->common.chip_id & CHIP_REV_MASK)
+#define CHIP_REV_Ax (0x0 << CHIP_REV_SHIFT)
+#define CHIP_REV_Bx (0x1 << CHIP_REV_SHIFT)
/* assume maximum 5 revisions */
-#define CHIP_REV_IS_SLOW(bp) (CHIP_REV(bp) > 0x00005000)
+#define CHIP_REV_IS_SLOW(bp) (CHIP_REV_VAL(bp) > 0x00005000)
/* Emul versions are A=>0xe, B=>0xc, C=>0xa, D=>8, E=>6 */
#define CHIP_REV_IS_EMUL(bp) ((CHIP_REV_IS_SLOW(bp)) && \
- !(CHIP_REV(bp) & 0x00001000))
+ !(CHIP_REV_VAL(bp) & 0x00001000))
/* FPGA versions are A=>0xf, B=>0xd, C=>0xb, D=>9, E=>7 */
#define CHIP_REV_IS_FPGA(bp) ((CHIP_REV_IS_SLOW(bp)) && \
- (CHIP_REV(bp) & 0x00001000))
+ (CHIP_REV_VAL(bp) & 0x00001000))
#define CHIP_TIME(bp) ((CHIP_REV_IS_EMUL(bp)) ? 2000 : \
((CHIP_REV_IS_FPGA(bp)) ? 200 : 1))
#define CHIP_METAL(bp) (bp->common.chip_id & 0x00000ff0)
#define CHIP_BOND_ID(bp) (bp->common.chip_id & 0x0000000f)
-#define CHIP_PARITY_ENABLED(bp) (CHIP_IS_E1(bp) || CHIP_IS_E1H(bp))
+#define CHIP_REV_SIM(bp) (((CHIP_REV_MASK - CHIP_REV_VAL(bp)) >>\
+ (CHIP_REV_SHIFT + 1)) \
+ << CHIP_REV_SHIFT)
+#define CHIP_REV(bp) (CHIP_REV_IS_SLOW(bp) ? \
+ CHIP_REV_SIM(bp) :\
+ CHIP_REV_VAL(bp))
+#define CHIP_IS_E3B0(bp) (CHIP_IS_E3(bp) && \
+ (CHIP_REV(bp) == CHIP_REV_Bx))
+#define CHIP_IS_E3A0(bp) (CHIP_IS_E3(bp) && \
+ (CHIP_REV(bp) == CHIP_REV_Ax))
int flash_size;
-#define NVRAM_1MB_SIZE 0x20000 /* 1M bit in bytes */
-#define NVRAM_TIMEOUT_COUNT 30000
-#define NVRAM_PAGE_SIZE 256
+#define BNX2X_NVRAM_1MB_SIZE 0x20000 /* 1M bit in bytes */
+#define BNX2X_NVRAM_TIMEOUT_COUNT 30000
+#define BNX2X_NVRAM_PAGE_SIZE 256
u32 shmem_base;
u32 shmem2_base;
@@ -666,7 +761,7 @@
#define INT_BLOCK_MODE_NORMAL 0
#define INT_BLOCK_MODE_BW_COMP 2
#define CHIP_INT_MODE_IS_NBC(bp) \
- (CHIP_IS_E2(bp) && \
+ (!CHIP_IS_E1x(bp) && \
!((bp)->common.int_block & INT_BLOCK_MODE_BW_COMP))
#define CHIP_INT_MODE_IS_BC(bp) (!CHIP_INT_MODE_IS_NBC(bp))
@@ -712,19 +807,15 @@
/* end of port */
-/* e1h Classification CAM line allocations */
-enum {
- CAM_ETH_LINE = 0,
- CAM_ISCSI_ETH_LINE,
- CAM_FIP_ETH_LINE,
- CAM_FIP_MCAST_LINE,
- CAM_MAX_PF_LINE = CAM_FIP_MCAST_LINE
-};
-/* number of MACs per function in NIG memory - used for SI mode */
-#define NIG_LLH_FUNC_MEM_SIZE 16
-/* number of entries in NIG_REG_LLHX_FUNC_MEM */
-#define NIG_LLH_FUNC_MEM_MAX_OFFSET 8
+#define STATS_OFFSET32(stat_name) \
+ (offsetof(struct bnx2x_eth_stats, stat_name) / 4)
+/* slow path */
+
+/* slow path work-queue */
+extern struct workqueue_struct *bnx2x_wq;
+
+#define BNX2X_MAX_NUM_OF_VFS 64
#define BNX2X_VF_ID_INVALID 0xFF
/*
@@ -749,8 +840,10 @@
* L2 queue is supported. the cid for the FCoE L2 queue is always X.
*/
-#define FP_SB_MAX_E1x 16 /* fast-path interrupt contexts E1x */
-#define FP_SB_MAX_E2 16 /* fast-path interrupt contexts E2 */
+/* fast-path interrupt contexts E1x */
+#define FP_SB_MAX_E1x 16
+/* fast-path interrupt contexts E2 */
+#define FP_SB_MAX_E2 HC_SB_MAX_SB_E2
/*
* cid_cnt paramter below refers to the value returned by
@@ -761,13 +854,13 @@
* The number of FP context allocated by the driver == max number of regular
* L2 queues + 1 for the FCoE L2 queue
*/
-#define L2_FP_COUNT(cid_cnt) ((cid_cnt) - CNIC_CONTEXT_USE)
+#define L2_FP_COUNT(cid_cnt) ((cid_cnt) - FCOE_CONTEXT_USE)
/*
* The number of FP-SB allocated by the driver == max number of regular L2
* queues + 1 for the CNIC which also consumes an FP-SB
*/
-#define FP_SB_COUNT(cid_cnt) ((cid_cnt) - FCOE_CONTEXT_USE)
+#define FP_SB_COUNT(cid_cnt) ((cid_cnt) - CNIC_CONTEXT_USE)
#define NUM_IGU_SB_REQUIRED(cid_cnt) \
(FP_SB_COUNT(cid_cnt) - NONE_ETH_CONTEXT_USE)
@@ -788,38 +881,61 @@
#define CNIC_ILT_LINES DIV_ROUND_UP(CNIC_CID_MAX, ILT_PAGE_CIDS)
#endif
-#define QM_ILT_PAGE_SZ_HW 3
-#define QM_ILT_PAGE_SZ (4096 << QM_ILT_PAGE_SZ_HW) /* 32K */
+#define QM_ILT_PAGE_SZ_HW 0
+#define QM_ILT_PAGE_SZ (4096 << QM_ILT_PAGE_SZ_HW) /* 4K */
#define QM_CID_ROUND 1024
#ifdef BCM_CNIC
/* TM (timers) host DB constants */
-#define TM_ILT_PAGE_SZ_HW 2
-#define TM_ILT_PAGE_SZ (4096 << TM_ILT_PAGE_SZ_HW) /* 16K */
+#define TM_ILT_PAGE_SZ_HW 0
+#define TM_ILT_PAGE_SZ (4096 << TM_ILT_PAGE_SZ_HW) /* 4K */
/* #define TM_CONN_NUM (CNIC_STARTING_CID+CNIC_ISCSI_CXT_MAX) */
#define TM_CONN_NUM 1024
#define TM_ILT_SZ (8 * TM_CONN_NUM)
#define TM_ILT_LINES DIV_ROUND_UP(TM_ILT_SZ, TM_ILT_PAGE_SZ)
/* SRC (Searcher) host DB constants */
-#define SRC_ILT_PAGE_SZ_HW 3
-#define SRC_ILT_PAGE_SZ (4096 << SRC_ILT_PAGE_SZ_HW) /* 32K */
+#define SRC_ILT_PAGE_SZ_HW 0
+#define SRC_ILT_PAGE_SZ (4096 << SRC_ILT_PAGE_SZ_HW) /* 4K */
#define SRC_HASH_BITS 10
#define SRC_CONN_NUM (1 << SRC_HASH_BITS) /* 1024 */
#define SRC_ILT_SZ (sizeof(struct src_ent) * SRC_CONN_NUM)
#define SRC_T2_SZ SRC_ILT_SZ
#define SRC_ILT_LINES DIV_ROUND_UP(SRC_ILT_SZ, SRC_ILT_PAGE_SZ)
+
#endif
-#define MAX_DMAE_C 8
+#define MAX_DMAE_C 8
/* DMA memory not used in fastpath */
struct bnx2x_slowpath {
- struct eth_stats_query fw_stats;
- struct mac_configuration_cmd mac_config;
- struct mac_configuration_cmd mcast_config;
- struct mac_configuration_cmd uc_mac_config;
- struct client_init_ramrod_data client_init_data;
+ union {
+ struct mac_configuration_cmd e1x;
+ struct eth_classify_rules_ramrod_data e2;
+ } mac_rdata;
+
+
+ union {
+ struct tstorm_eth_mac_filter_config e1x;
+ struct eth_filter_rules_ramrod_data e2;
+ } rx_mode_rdata;
+
+ union {
+ struct mac_configuration_cmd e1;
+ struct eth_multicast_rules_ramrod_data e2;
+ } mcast_rdata;
+
+ struct eth_rss_update_ramrod_data rss_rdata;
+
+ /* Queue State related ramrods are always sent under rtnl_lock */
+ union {
+ struct client_init_ramrod_data init_data;
+ struct client_update_ramrod_data update_data;
+ } q_rdata;
+
+ union {
+ struct function_start_data func_start;
+ } func_rdata;
/* used by dmae command executer */
struct dmae_command dmae[MAX_DMAE_C];
@@ -846,7 +962,7 @@
#define MAX_DYNAMIC_ATTN_GRPS 8
struct attn_route {
- u32 sig[5];
+ u32 sig[5];
};
struct iro {
@@ -866,13 +982,15 @@
/* forward */
struct bnx2x_ilt;
-typedef enum {
+
+enum bnx2x_recovery_state {
BNX2X_RECOVERY_DONE,
BNX2X_RECOVERY_INIT,
BNX2X_RECOVERY_WAIT,
-} bnx2x_recovery_state_t;
+ BNX2X_RECOVERY_FAILED
+};
-/**
+/*
* Event queue (EQ or event ring) MC hsi
* NUM_EQ_PAGES and EQ_DESC_CNT_PAGE must be power of 2
*/
@@ -910,6 +1028,24 @@
BNX2X_LINK_REPORT_TX_FC_ON,
};
+enum {
+ BNX2X_PORT_QUERY_IDX,
+ BNX2X_PF_QUERY_IDX,
+ BNX2X_FIRST_QUEUE_QUERY_IDX,
+};
+
+struct bnx2x_fw_stats_req {
+ struct stats_query_header hdr;
+ struct stats_query_entry query[STATS_QUERY_CMD_COUNT];
+};
+
+struct bnx2x_fw_stats_data {
+ struct stats_counter storm_counters;
+ struct per_port_stats port;
+ struct per_pf_stats pf;
+ struct per_queue_stats queue_stats[1];
+};
+
struct bnx2x {
/* Fields used in the tx and intr/napi performance paths
* are grouped together in the beginning of the structure
@@ -919,19 +1055,28 @@
void __iomem *doorbells;
u16 db_size;
+ u8 pf_num; /* absolute PF number */
+ u8 pfid; /* per-path PF number */
+ int base_fw_ndsb; /**/
+#define BP_PATH(bp) (CHIP_IS_E1x(bp) ? 0 : (bp->pf_num & 1))
+#define BP_PORT(bp) (bp->pfid & 1)
+#define BP_FUNC(bp) (bp->pfid)
+#define BP_ABS_FUNC(bp) (bp->pf_num)
+#define BP_E1HVN(bp) (bp->pfid >> 1)
+#define BP_VN(bp) (BP_E1HVN(bp)) /*remove when approved*/
+#define BP_L_ID(bp) (BP_E1HVN(bp) << 2)
+#define BP_FW_MB_IDX(bp) (BP_PORT(bp) +\
+ BP_VN(bp) * (CHIP_IS_E1x(bp) ? 2 : 1))
+
struct net_device *dev;
struct pci_dev *pdev;
- struct iro *iro_arr;
+ const struct iro *iro_arr;
#define IRO (bp->iro_arr)
- atomic_t intr_sem;
-
- bnx2x_recovery_state_t recovery_state;
+ enum bnx2x_recovery_state recovery_state;
int is_leader;
struct msix_entry *msix_table;
-#define INT_MODE_INTx 1
-#define INT_MODE_MSI 2
int tx_ring_size;
@@ -944,7 +1089,8 @@
/* Max supported alignment is 256 (8 shift) */
#define BNX2X_RX_ALIGN_SHIFT ((L1_CACHE_SHIFT < 8) ? \
L1_CACHE_SHIFT : 8)
-#define BNX2X_RX_ALIGN (1 << BNX2X_RX_ALIGN_SHIFT)
+ /* FW use 2 Cache lines Alignment for start packet and size */
+#define BNX2X_FW_RX_ALIGN (2 << BNX2X_RX_ALIGN_SHIFT)
#define BNX2X_PXP_DRAM_ALIGN (BNX2X_RX_ALIGN_SHIFT - 5)
struct host_sp_status_block *def_status_blk;
@@ -974,10 +1120,12 @@
__le16 *eq_cons_sb;
atomic_t eq_spq_left; /* COMMON_XXX ramrods credit */
- /* Flags for marking that there is a STAT_QUERY or
- SET_MAC ramrod pending */
- int stats_pending;
- int set_mac_pending;
+
+
+ /* Counter for marking that there is a STAT_QUERY ramrod pending */
+ u16 stats_pending;
+ /* Counter for completed statistics ramrods */
+ u16 stats_comp;
/* End of fields used in the performance code paths */
@@ -985,54 +1133,35 @@
int msg_enable;
u32 flags;
-#define PCIX_FLAG 1
-#define PCI_32BIT_FLAG 2
-#define ONE_PORT_FLAG 4
-#define NO_WOL_FLAG 8
-#define USING_DAC_FLAG 0x10
-#define USING_MSIX_FLAG 0x20
-#define USING_MSI_FLAG 0x40
+#define PCIX_FLAG (1 << 0)
+#define PCI_32BIT_FLAG (1 << 1)
+#define ONE_PORT_FLAG (1 << 2)
+#define NO_WOL_FLAG (1 << 3)
+#define USING_DAC_FLAG (1 << 4)
+#define USING_MSIX_FLAG (1 << 5)
+#define USING_MSI_FLAG (1 << 6)
+#define DISABLE_MSI_FLAG (1 << 7)
+#define TPA_ENABLE_FLAG (1 << 8)
+#define NO_MCP_FLAG (1 << 9)
-#define TPA_ENABLE_FLAG 0x80
-#define NO_MCP_FLAG 0x100
-#define DISABLE_MSI_FLAG 0x200
#define BP_NOMCP(bp) (bp->flags & NO_MCP_FLAG)
-#define MF_FUNC_DIS 0x1000
-#define FCOE_MACS_SET 0x2000
-#define NO_FCOE_FLAG 0x4000
-#define NO_ISCSI_OOO_FLAG 0x8000
-#define NO_ISCSI_FLAG 0x10000
+#define MF_FUNC_DIS (1 << 11)
+#define OWN_CNIC_IRQ (1 << 12)
+#define NO_ISCSI_OOO_FLAG (1 << 13)
+#define NO_ISCSI_FLAG (1 << 14)
+#define NO_FCOE_FLAG (1 << 15)
-#define NO_FCOE(bp) ((bp)->flags & NO_FCOE_FLAG)
#define NO_ISCSI(bp) ((bp)->flags & NO_ISCSI_FLAG)
#define NO_ISCSI_OOO(bp) ((bp)->flags & NO_ISCSI_OOO_FLAG)
-
- int pf_num; /* absolute PF number */
- int pfid; /* per-path PF number */
- int base_fw_ndsb;
-#define BP_PATH(bp) (!CHIP_IS_E2(bp) ? \
- 0 : (bp->pf_num & 1))
-#define BP_PORT(bp) (bp->pfid & 1)
-#define BP_FUNC(bp) (bp->pfid)
-#define BP_ABS_FUNC(bp) (bp->pf_num)
-#define BP_E1HVN(bp) (bp->pfid >> 1)
-#define BP_VN(bp) (CHIP_MODE_IS_4_PORT(bp) ? \
- 0 : BP_E1HVN(bp))
-#define BP_L_ID(bp) (BP_E1HVN(bp) << 2)
-#define BP_FW_MB_IDX(bp) (BP_PORT(bp) +\
- BP_VN(bp) * (CHIP_IS_E1x(bp) ? 2 : 1))
-
-#ifdef BCM_CNIC
-#define BCM_CNIC_CID_START 16
-#define BCM_ISCSI_ETH_CL_ID 17
-#endif
+#define NO_FCOE(bp) ((bp)->flags & NO_FCOE_FLAG)
int pm_cap;
- int pcie_cap;
int mrrs;
struct delayed_work sp_task;
struct delayed_work reset_task;
+
+ struct delayed_work period_task;
struct timer_list timer;
int current_interval;
@@ -1052,9 +1181,9 @@
struct cmng_struct_per_port cmng;
u32 vn_weight_sum;
-
u32 mf_config[E1HVN_MAX];
u32 mf2_config[E2_FUNC_MAX];
+ u32 path_has_ovlan; /* E3 */
u16 mf_ov;
u8 mf_mode;
#define IS_MF(bp) (bp->mf_mode != 0)
@@ -1079,33 +1208,20 @@
u32 lin_cnt;
- int state;
+ u16 state;
#define BNX2X_STATE_CLOSED 0
#define BNX2X_STATE_OPENING_WAIT4_LOAD 0x1000
#define BNX2X_STATE_OPENING_WAIT4_PORT 0x2000
#define BNX2X_STATE_OPEN 0x3000
#define BNX2X_STATE_CLOSING_WAIT4_HALT 0x4000
#define BNX2X_STATE_CLOSING_WAIT4_DELETE 0x5000
-#define BNX2X_STATE_CLOSING_WAIT4_UNLOAD 0x6000
-#define BNX2X_STATE_FUNC_STARTED 0x7000
+
#define BNX2X_STATE_DIAG 0xe000
#define BNX2X_STATE_ERROR 0xf000
int multi_mode;
int num_queues;
int disable_tpa;
- int int_mode;
- u32 *rx_indir_table;
-
- struct tstorm_eth_mac_filter_config mac_filters;
-#define BNX2X_ACCEPT_NONE 0x0000
-#define BNX2X_ACCEPT_UNICAST 0x0001
-#define BNX2X_ACCEPT_MULTICAST 0x0002
-#define BNX2X_ACCEPT_ALL_UNICAST 0x0004
-#define BNX2X_ACCEPT_ALL_MULTICAST 0x0008
-#define BNX2X_ACCEPT_BROADCAST 0x0010
-#define BNX2X_ACCEPT_UNMATCHED_UCAST 0x0020
-#define BNX2X_PROMISCUOUS_MODE 0x10000
u32 rx_mode;
#define BNX2X_RX_MODE_NONE 0
@@ -1113,7 +1229,6 @@
#define BNX2X_RX_MODE_ALLMULTI 2
#define BNX2X_RX_MODE_PROMISC 3
#define BNX2X_MAX_MULTICAST 64
-#define BNX2X_MAX_EMUL_MULTI 16
u8 igu_dsb_id;
u8 igu_base_sb;
@@ -1122,11 +1237,38 @@
struct bnx2x_slowpath *slowpath;
dma_addr_t slowpath_mapping;
+
+ /* Total number of FW statistics requests */
+ u8 fw_stats_num;
+
+ /*
+ * This is a memory buffer that will contain both statistics
+ * ramrod request and data.
+ */
+ void *fw_stats;
+ dma_addr_t fw_stats_mapping;
+
+ /*
+ * FW statistics request shortcut (points at the
+ * beginning of fw_stats buffer).
+ */
+ struct bnx2x_fw_stats_req *fw_stats_req;
+ dma_addr_t fw_stats_req_mapping;
+ int fw_stats_req_sz;
+
+ /*
+ * FW statistics data shortcut (points at the begining of
+ * fw_stats buffer + fw_stats_req_sz).
+ */
+ struct bnx2x_fw_stats_data *fw_stats_data;
+ dma_addr_t fw_stats_data_mapping;
+ int fw_stats_data_sz;
+
struct hw_context context;
struct bnx2x_ilt *ilt;
#define BP_ILT(bp) ((bp)->ilt)
-#define ILT_MAX_LINES 128
+#define ILT_MAX_LINES 256
int l2_cid_count;
#define L2_ILT_LINES(bp) (DIV_ROUND_UP((bp)->l2_cid_count, \
@@ -1148,16 +1290,18 @@
struct cnic_eth_dev cnic_eth_dev;
union host_hc_status_block cnic_sb;
dma_addr_t cnic_sb_mapping;
-#define CNIC_SB_ID(bp) ((bp)->base_fw_ndsb + BP_L_ID(bp))
-#define CNIC_IGU_SB_ID(bp) ((bp)->igu_base_sb)
struct eth_spe *cnic_kwq;
struct eth_spe *cnic_kwq_prod;
struct eth_spe *cnic_kwq_cons;
struct eth_spe *cnic_kwq_last;
u16 cnic_kwq_pending;
u16 cnic_spq_pending;
- struct mutex cnic_mutex;
u8 fip_mac[ETH_ALEN];
+ struct mutex cnic_mutex;
+ struct bnx2x_vlan_mac_obj iscsi_l2_mac_obj;
+
+ /* Start index of the "special" (CNIC related) L2 cleints */
+ u8 cnic_base_cl_id;
#endif
int dmae_ready;
@@ -1194,6 +1338,8 @@
u16 *init_ops_offsets;
/* Data blob - has 32 bit granularity */
u32 *init_data;
+ u32 init_mode_flags;
+#define INIT_MODE_FLAGS(bp) (bp->init_mode_flags)
/* Zipped PRAM blobs - raw data */
const u8 *tsem_int_table_data;
const u8 *tsem_pram_data;
@@ -1215,8 +1361,10 @@
#define INIT_CSEM_INT_TABLE_DATA(bp) (bp->csem_int_table_data)
#define INIT_CSEM_PRAM_DATA(bp) (bp->csem_pram_data)
+#define PHY_FW_VER_LEN 20
char fw_ver[32];
const struct firmware *firmware;
+
/* LLDP params */
struct bnx2x_config_lldp_params lldp_config_params;
@@ -1235,13 +1383,30 @@
bool dcbx_mode_uset;
struct bnx2x_config_dcbx_params dcbx_config_params;
-
struct bnx2x_dcbx_port_params dcbx_port_params;
int dcb_version;
- /* DCBX Negotiation results */
+ /* CAM credit pools */
+ struct bnx2x_credit_pool_obj macs_pool;
+
+ /* RX_MODE object */
+ struct bnx2x_rx_mode_obj rx_mode_obj;
+
+ /* MCAST object */
+ struct bnx2x_mcast_obj mcast_obj;
+
+ /* RSS configuration object */
+ struct bnx2x_rss_config_obj rss_conf_obj;
+
+ /* Function State controlling object */
+ struct bnx2x_func_sp_obj func_obj;
+
+ unsigned long sp_state;
+
+ /* DCBX Negotation results */
struct dcbx_features dcbx_local_feat;
u32 dcbx_error;
+
#ifdef BCM_DCBNL
struct dcbx_features dcbx_remote_feat;
u32 dcbx_remote_flags;
@@ -1249,42 +1414,11 @@
u32 pending_max;
};
-/**
- * Init queue/func interface
- */
-/* queue init flags */
-#define QUEUE_FLG_TPA 0x0001
-#define QUEUE_FLG_CACHE_ALIGN 0x0002
-#define QUEUE_FLG_STATS 0x0004
-#define QUEUE_FLG_OV 0x0008
-#define QUEUE_FLG_VLAN 0x0010
-#define QUEUE_FLG_COS 0x0020
-#define QUEUE_FLG_HC 0x0040
-#define QUEUE_FLG_DHC 0x0080
-#define QUEUE_FLG_OOO 0x0100
-
-#define QUEUE_DROP_IP_CS_ERR TSTORM_ETH_CLIENT_CONFIG_DROP_IP_CS_ERR
-#define QUEUE_DROP_TCP_CS_ERR TSTORM_ETH_CLIENT_CONFIG_DROP_TCP_CS_ERR
-#define QUEUE_DROP_TTL0 TSTORM_ETH_CLIENT_CONFIG_DROP_TTL0
-#define QUEUE_DROP_UDP_CS_ERR TSTORM_ETH_CLIENT_CONFIG_DROP_UDP_CS_ERR
-
-
-
-/* rss capabilities */
-#define RSS_IPV4_CAP 0x0001
-#define RSS_IPV4_TCP_CAP 0x0002
-#define RSS_IPV6_CAP 0x0004
-#define RSS_IPV6_TCP_CAP 0x0008
-
+/* Tx queues may be less or equal to Rx queues */
+extern int num_queues;
#define BNX2X_NUM_QUEUES(bp) (bp->num_queues)
#define BNX2X_NUM_ETH_QUEUES(bp) (BNX2X_NUM_QUEUES(bp) - NONE_ETH_CONTEXT_USE)
-/* ethtool statistics are displayed for all regular ethernet queues and the
- * fcoe L2 queue if not disabled
- */
-#define BNX2X_NUM_STAT_QUEUES(bp) (NO_FCOE(bp) ? BNX2X_NUM_ETH_QUEUES(bp) : \
- (BNX2X_NUM_ETH_QUEUES(bp) + FCOE_CONTEXT_USE))
-
#define is_multi(bp) (BNX2X_NUM_QUEUES(bp) > 1)
#define BNX2X_MAX_QUEUES(bp) (bp->igu_sb_cnt - CNIC_CONTEXT_USE)
@@ -1302,107 +1436,15 @@
TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV6_TCP_CAPABILITY
/* func init flags */
-#define FUNC_FLG_STATS 0x0001
-#define FUNC_FLG_TPA 0x0002
-#define FUNC_FLG_SPQ 0x0004
-#define FUNC_FLG_LEADING 0x0008 /* PF only */
+#define FUNC_FLG_RSS 0x0001
+#define FUNC_FLG_STATS 0x0002
+/* removed FUNC_FLG_UNMATCHED 0x0004 */
+#define FUNC_FLG_TPA 0x0008
+#define FUNC_FLG_SPQ 0x0010
+#define FUNC_FLG_LEADING 0x0020 /* PF only */
-struct rxq_pause_params {
- u16 bd_th_lo;
- u16 bd_th_hi;
- u16 rcq_th_lo;
- u16 rcq_th_hi;
- u16 sge_th_lo; /* valid iff QUEUE_FLG_TPA */
- u16 sge_th_hi; /* valid iff QUEUE_FLG_TPA */
- u16 pri_map;
-};
-
-struct bnx2x_rxq_init_params {
- /* cxt*/
- struct eth_context *cxt;
-
- /* dma */
- dma_addr_t dscr_map;
- dma_addr_t sge_map;
- dma_addr_t rcq_map;
- dma_addr_t rcq_np_map;
-
- u16 flags;
- u16 drop_flags;
- u16 mtu;
- u16 buf_sz;
- u16 fw_sb_id;
- u16 cl_id;
- u16 spcl_id;
- u16 cl_qzone_id;
-
- /* valid iff QUEUE_FLG_STATS */
- u16 stat_id;
-
- /* valid iff QUEUE_FLG_TPA */
- u16 tpa_agg_sz;
- u16 sge_buf_sz;
- u16 max_sges_pkt;
-
- /* valid iff QUEUE_FLG_CACHE_ALIGN */
- u8 cache_line_log;
-
- u8 sb_cq_index;
- u32 cid;
-
- /* desired interrupts per sec. valid iff QUEUE_FLG_HC */
- u32 hc_rate;
-};
-
-struct bnx2x_txq_init_params {
- /* cxt*/
- struct eth_context *cxt;
-
- /* dma */
- dma_addr_t dscr_map;
-
- u16 flags;
- u16 fw_sb_id;
- u8 sb_cq_index;
- u8 cos; /* valid iff QUEUE_FLG_COS */
- u16 stat_id; /* valid iff QUEUE_FLG_STATS */
- u16 traffic_type;
- u32 cid;
- u16 hc_rate; /* desired interrupts per sec.*/
- /* valid iff QUEUE_FLG_HC */
-
-};
-
-struct bnx2x_client_ramrod_params {
- int *pstate;
- int state;
- u16 index;
- u16 cl_id;
- u32 cid;
- u8 poll;
-#define CLIENT_IS_FCOE 0x01
-#define CLIENT_IS_LEADING_RSS 0x02
- u8 flags;
-};
-
-struct bnx2x_client_init_params {
- struct rxq_pause_params pause;
- struct bnx2x_rxq_init_params rxq_params;
- struct bnx2x_txq_init_params txq_params;
- struct bnx2x_client_ramrod_params ramrod_params;
-};
-
-struct bnx2x_rss_params {
- int mode;
- u16 cap;
- u16 result_mask;
-};
struct bnx2x_func_init_params {
-
- /* rss */
- struct bnx2x_rss_params *rss; /* valid iff FUNC_FLG_RSS */
-
/* dma */
dma_addr_t fw_stat_map; /* valid iff FUNC_FLG_STATS */
dma_addr_t spq_map; /* valid iff FUNC_FLG_SPQ */
@@ -1414,17 +1456,10 @@
};
#define for_each_eth_queue(bp, var) \
- for (var = 0; var < BNX2X_NUM_ETH_QUEUES(bp); var++)
+ for (var = 0; var < BNX2X_NUM_ETH_QUEUES(bp); var++)
#define for_each_nondefault_eth_queue(bp, var) \
- for (var = 1; var < BNX2X_NUM_ETH_QUEUES(bp); var++)
-
-#define for_each_napi_queue(bp, var) \
- for (var = 0; \
- var < BNX2X_NUM_ETH_QUEUES(bp) + FCOE_CONTEXT_USE; var++) \
- if (skip_queue(bp, var)) \
- continue; \
- else
+ for (var = 1; var < BNX2X_NUM_ETH_QUEUES(bp); var++)
#define for_each_queue(bp, var) \
for (var = 0; var < BNX2X_NUM_QUEUES(bp); var++) \
@@ -1462,11 +1497,66 @@
#define skip_queue(bp, idx) (NO_FCOE(bp) && IS_FCOE_IDX(idx))
-#define WAIT_RAMROD_POLL 0x01
-#define WAIT_RAMROD_COMMON 0x02
+
+
+/**
+ * bnx2x_set_mac_one - configure a single MAC address
+ *
+ * @bp: driver handle
+ * @mac: MAC to configure
+ * @obj: MAC object handle
+ * @set: if 'true' add a new MAC, otherwise - delete
+ * @mac_type: the type of the MAC to configure (e.g. ETH, UC list)
+ * @ramrod_flags: RAMROD_XXX flags (e.g. RAMROD_CONT, RAMROD_COMP_WAIT)
+ *
+ * Configures one MAC according to provided parameters or continues the
+ * execution of previously scheduled commands if RAMROD_CONT is set in
+ * ramrod_flags.
+ *
+ * Returns zero if operation has successfully completed, a positive value if the
+ * operation has been successfully scheduled and a negative - if a requested
+ * operations has failed.
+ */
+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
+ *
+ * @bp: driver handle
+ * @mac_obj: MAC object handle
+ * @mac_type: type of the MACs to clear (BNX2X_XXX_MAC)
+ * @wait_for_comp: if 'true' block until completion
+ *
+ * Deletes all MACs of the specific type (e.g. ETH, UC list).
+ *
+ * Returns zero if operation has successfully completed, a positive value if the
+ * operation has been successfully scheduled and a negative - if a requested
+ * operations has failed.
+ */
+int bnx2x_del_all_macs(struct bnx2x *bp,
+ struct bnx2x_vlan_mac_obj *mac_obj,
+ int mac_type, bool wait_for_comp);
+
+/* Init Function API */
+void bnx2x_func_init(struct bnx2x *bp, struct bnx2x_func_init_params *p);
+int bnx2x_get_gpio(struct bnx2x *bp, int gpio_num, u8 port);
+int bnx2x_set_gpio(struct bnx2x *bp, int gpio_num, u32 mode, u8 port);
+int bnx2x_set_mult_gpio(struct bnx2x *bp, u8 pins, u32 mode);
+int bnx2x_set_gpio_int(struct bnx2x *bp, int gpio_num, u32 mode, u8 port);
void bnx2x_read_mf_cfg(struct bnx2x *bp);
+
/* dmae */
void bnx2x_read_dmae(struct bnx2x *bp, u32 src_addr, u32 len32);
void bnx2x_write_dmae(struct bnx2x *bp, dma_addr_t dma_addr, u32 dst_addr,
@@ -1477,22 +1567,12 @@
u32 bnx2x_dmae_opcode(struct bnx2x *bp, u8 src_type, u8 dst_type,
bool with_comp, u8 comp_type);
-int bnx2x_get_gpio(struct bnx2x *bp, int gpio_num, u8 port);
-int bnx2x_set_gpio(struct bnx2x *bp, int gpio_num, u32 mode, u8 port);
-int bnx2x_set_gpio_int(struct bnx2x *bp, int gpio_num, u32 mode, u8 port);
-u32 bnx2x_fw_command(struct bnx2x *bp, u32 command, u32 param);
void bnx2x_calc_fc_adv(struct bnx2x *bp);
int bnx2x_sp_post(struct bnx2x *bp, int command, int cid,
- u32 data_hi, u32 data_lo, int common);
-
-/* Clears multicast and unicast list configuration in the chip. */
-void bnx2x_invalidate_e1_mc_list(struct bnx2x *bp);
-void bnx2x_invalidate_e1h_mc_list(struct bnx2x *bp);
-void bnx2x_invalidate_uc_list(struct bnx2x *bp);
-
+ u32 data_hi, u32 data_lo, int cmd_type);
void bnx2x_update_coalesce(struct bnx2x *bp);
-int bnx2x_get_link_cfg_idx(struct bnx2x *bp);
+int bnx2x_get_cur_phy_idx(struct bnx2x *bp);
static inline u32 reg_poll(struct bnx2x *bp, u32 reg, u32 expected, int ms,
int wait)
@@ -1648,7 +1728,8 @@
/* must be used on a CID before placing it on a HW ring */
#define HW_CID(bp, x) ((BP_PORT(bp) << 23) | \
- (BP_E1HVN(bp) << 17) | (x))
+ (BP_E1HVN(bp) << BNX2X_SWCID_SHIFT) | \
+ (x))
#define SP_DESC_CNT (BCM_PAGE_SIZE / sizeof(struct eth_spe))
#define MAX_SP_DESC_CNT (SP_DESC_CNT - 1)
@@ -1718,12 +1799,14 @@
(AEU_INPUTS_ATTN_BITS_TSDM_HW_INTERRUPT | \
AEU_INPUTS_ATTN_BITS_TCM_HW_INTERRUPT | \
AEU_INPUTS_ATTN_BITS_TSEMI_HW_INTERRUPT | \
- AEU_INPUTS_ATTN_BITS_PBF_HW_INTERRUPT)
+ AEU_INPUTS_ATTN_BITS_PBCLIENT_HW_INTERRUPT)
#define HW_PRTY_ASSERT_SET_0 (AEU_INPUTS_ATTN_BITS_BRB_PARITY_ERROR | \
AEU_INPUTS_ATTN_BITS_PARSER_PARITY_ERROR | \
AEU_INPUTS_ATTN_BITS_TSDM_PARITY_ERROR | \
AEU_INPUTS_ATTN_BITS_SEARCHER_PARITY_ERROR |\
- AEU_INPUTS_ATTN_BITS_TSEMI_PARITY_ERROR)
+ AEU_INPUTS_ATTN_BITS_TSEMI_PARITY_ERROR |\
+ AEU_INPUTS_ATTN_BITS_TCM_PARITY_ERROR |\
+ AEU_INPUTS_ATTN_BITS_PBCLIENT_PARITY_ERROR)
#define HW_INTERRUT_ASSERT_SET_1 \
(AEU_INPUTS_ATTN_BITS_QM_HW_INTERRUPT | \
AEU_INPUTS_ATTN_BITS_TIMERS_HW_INTERRUPT | \
@@ -1736,17 +1819,22 @@
AEU_INPUTS_ATTN_BITS_UPB_HW_INTERRUPT | \
AEU_INPUTS_ATTN_BITS_CSDM_HW_INTERRUPT | \
AEU_INPUTS_ATTN_BITS_CCM_HW_INTERRUPT)
-#define HW_PRTY_ASSERT_SET_1 (AEU_INPUTS_ATTN_BITS_PBCLIENT_PARITY_ERROR |\
+#define HW_PRTY_ASSERT_SET_1 (AEU_INPUTS_ATTN_BITS_PBF_PARITY_ERROR |\
AEU_INPUTS_ATTN_BITS_QM_PARITY_ERROR | \
+ AEU_INPUTS_ATTN_BITS_TIMERS_PARITY_ERROR |\
AEU_INPUTS_ATTN_BITS_XSDM_PARITY_ERROR | \
+ AEU_INPUTS_ATTN_BITS_XCM_PARITY_ERROR |\
AEU_INPUTS_ATTN_BITS_XSEMI_PARITY_ERROR | \
AEU_INPUTS_ATTN_BITS_DOORBELLQ_PARITY_ERROR |\
+ AEU_INPUTS_ATTN_BITS_NIG_PARITY_ERROR |\
AEU_INPUTS_ATTN_BITS_VAUX_PCI_CORE_PARITY_ERROR |\
AEU_INPUTS_ATTN_BITS_DEBUG_PARITY_ERROR | \
AEU_INPUTS_ATTN_BITS_USDM_PARITY_ERROR | \
+ AEU_INPUTS_ATTN_BITS_UCM_PARITY_ERROR |\
AEU_INPUTS_ATTN_BITS_USEMI_PARITY_ERROR | \
AEU_INPUTS_ATTN_BITS_UPB_PARITY_ERROR | \
- AEU_INPUTS_ATTN_BITS_CSDM_PARITY_ERROR)
+ AEU_INPUTS_ATTN_BITS_CSDM_PARITY_ERROR |\
+ AEU_INPUTS_ATTN_BITS_CCM_PARITY_ERROR)
#define HW_INTERRUT_ASSERT_SET_2 \
(AEU_INPUTS_ATTN_BITS_CSEMI_HW_INTERRUPT | \
AEU_INPUTS_ATTN_BITS_CDU_HW_INTERRUPT | \
@@ -1758,6 +1846,7 @@
AEU_INPUTS_ATTN_BITS_PXPPCICLOCKCLIENT_PARITY_ERROR |\
AEU_INPUTS_ATTN_BITS_CFC_PARITY_ERROR | \
AEU_INPUTS_ATTN_BITS_CDU_PARITY_ERROR | \
+ AEU_INPUTS_ATTN_BITS_DMAE_PARITY_ERROR |\
AEU_INPUTS_ATTN_BITS_IGU_PARITY_ERROR | \
AEU_INPUTS_ATTN_BITS_MISC_PARITY_ERROR)
@@ -1775,6 +1864,30 @@
TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_MODE_SHIFT))
#define MULTI_MASK 0x7f
+
+#define DEF_USB_FUNC_OFF offsetof(struct cstorm_def_status_block_u, func)
+#define DEF_CSB_FUNC_OFF offsetof(struct cstorm_def_status_block_c, func)
+#define DEF_XSB_FUNC_OFF offsetof(struct xstorm_def_status_block, func)
+#define DEF_TSB_FUNC_OFF offsetof(struct tstorm_def_status_block, func)
+
+#define DEF_USB_IGU_INDEX_OFF \
+ offsetof(struct cstorm_def_status_block_u, igu_index)
+#define DEF_CSB_IGU_INDEX_OFF \
+ offsetof(struct cstorm_def_status_block_c, igu_index)
+#define DEF_XSB_IGU_INDEX_OFF \
+ offsetof(struct xstorm_def_status_block, igu_index)
+#define DEF_TSB_IGU_INDEX_OFF \
+ offsetof(struct tstorm_def_status_block, igu_index)
+
+#define DEF_USB_SEGMENT_OFF \
+ offsetof(struct cstorm_def_status_block_u, segment)
+#define DEF_CSB_SEGMENT_OFF \
+ offsetof(struct cstorm_def_status_block_c, segment)
+#define DEF_XSB_SEGMENT_OFF \
+ offsetof(struct xstorm_def_status_block, segment)
+#define DEF_TSB_SEGMENT_OFF \
+ offsetof(struct tstorm_def_status_block, segment)
+
#define BNX2X_SP_DSB_INDEX \
(&bp->def_status_blk->sp_sb.\
index_values[HC_SP_INDEX_ETH_DEF_CONS])
@@ -1786,7 +1899,7 @@
} while (0)
#define GET_FLAG(value, mask) \
- (((value) &= (mask)) >> (mask##_SHIFT))
+ (((value) & (mask)) >> (mask##_SHIFT))
#define GET_FIELD(value, fname) \
(((value) & (fname##_MASK)) >> (fname##_SHIFT))
@@ -1821,15 +1934,13 @@
#define HC_SEG_ACCESS_ATTN 4
#define HC_SEG_ACCESS_NORM 0 /*Driver decision 0-1*/
-#ifdef BNX2X_MAIN
-#define BNX2X_EXTERN
-#else
-#define BNX2X_EXTERN extern
-#endif
+static const u32 dmae_reg_go_c[] = {
+ DMAE_REG_GO_C0, DMAE_REG_GO_C1, DMAE_REG_GO_C2, DMAE_REG_GO_C3,
+ DMAE_REG_GO_C4, DMAE_REG_GO_C5, DMAE_REG_GO_C6, DMAE_REG_GO_C7,
+ DMAE_REG_GO_C8, DMAE_REG_GO_C9, DMAE_REG_GO_C10, DMAE_REG_GO_C11,
+ DMAE_REG_GO_C12, DMAE_REG_GO_C13, DMAE_REG_GO_C14, DMAE_REG_GO_C15
+};
-BNX2X_EXTERN int load_count[2][3]; /* per path: 0-common, 1-port0, 2-port1 */
-
-extern void bnx2x_set_ethtool_ops(struct net_device *netdev);
-void bnx2x_push_indir_table(struct bnx2x *bp);
-
+void bnx2x_set_ethtool_ops(struct net_device *netdev);
+void bnx2x_notify_link_changed(struct bnx2x *bp);
#endif /* bnx2x.h */
diff --git a/drivers/net/bnx2x/bnx2x_cmn.c b/drivers/net/bnx2x/bnx2x_cmn.c
index 2890443..bb75560 100644
--- a/drivers/net/bnx2x/bnx2x_cmn.c
+++ b/drivers/net/bnx2x/bnx2x_cmn.c
@@ -17,16 +17,17 @@
#include <linux/etherdevice.h>
#include <linux/if_vlan.h>
+#include <linux/interrupt.h>
#include <linux/ip.h>
#include <net/ipv6.h>
#include <net/ip6_checksum.h>
#include <linux/firmware.h>
#include <linux/prefetch.h>
#include "bnx2x_cmn.h"
-
#include "bnx2x_init.h"
+#include "bnx2x_sp.h"
-static int bnx2x_setup_irqs(struct bnx2x *bp);
+
/**
* bnx2x_bz_fp - zero content of the fastpath structure.
@@ -71,6 +72,8 @@
to_fp->napi = orig_napi;
}
+int load_count[2][3] = { {0} }; /* per-path: 0-common, 1-port0, 2-port1 */
+
/* free skb in the packet ring at pos idx
* return idx of last bd freed
*/
@@ -87,8 +90,8 @@
/* prefetch skb end pointer to speedup dev_kfree_skb() */
prefetch(&skb->end);
- DP(BNX2X_MSG_OFF, "pkt_idx %d buff @(%p)->skb %p\n",
- idx, tx_buf, skb);
+ DP(BNX2X_MSG_FP, "fp[%d]: pkt_idx %d buff @(%p)->skb %p\n",
+ fp->index, idx, tx_buf, skb);
/* unmap first bd */
DP(BNX2X_MSG_OFF, "free bd_idx %d\n", bd_idx);
@@ -96,6 +99,7 @@
dma_unmap_single(&bp->pdev->dev, BD_UNMAP_ADDR(tx_start_bd),
BD_UNMAP_LEN(tx_start_bd), DMA_TO_DEVICE);
+
nbd = le16_to_cpu(tx_start_bd->nbd) - 1;
#ifdef BNX2X_STOP_ON_ERROR
if ((nbd - 1) > (MAX_SKB_FRAGS + 2)) {
@@ -174,6 +178,9 @@
* memory barrier, there is a small possibility that
* start_xmit() will miss it and cause the queue to be stopped
* forever.
+ * On the other hand we need an rmb() here to ensure the proper
+ * ordering of bit testing in the following
+ * netif_tx_queue_stopped(txq) call.
*/
smp_mb();
@@ -225,7 +232,7 @@
/* First mark all used pages */
for (i = 0; i < sge_len; i++)
- SGE_MASK_CLEAR_BIT(fp,
+ BIT_VEC64_CLEAR_BIT(fp->sge_mask,
RX_SGE(le16_to_cpu(fp_cqe->sgl_or_raw_data.sgl[i])));
DP(NETIF_MSG_RX_STATUS, "fp_cqe->sgl[%d] = %d\n",
@@ -237,8 +244,8 @@
le16_to_cpu(fp_cqe->sgl_or_raw_data.sgl[sge_len - 1]));
last_max = RX_SGE(fp->last_max_sge);
- last_elem = last_max >> RX_SGE_MASK_ELEM_SHIFT;
- first_elem = RX_SGE(fp->rx_sge_prod) >> RX_SGE_MASK_ELEM_SHIFT;
+ last_elem = last_max >> BIT_VEC64_ELEM_SHIFT;
+ first_elem = RX_SGE(fp->rx_sge_prod) >> BIT_VEC64_ELEM_SHIFT;
/* If ring is not full */
if (last_elem + 1 != first_elem)
@@ -249,8 +256,8 @@
if (likely(fp->sge_mask[i]))
break;
- fp->sge_mask[i] = RX_SGE_MASK_ELEM_ONE_MASK;
- delta += RX_SGE_MASK_ELEM_SZ;
+ fp->sge_mask[i] = BIT_VEC64_ELEM_ONE_MASK;
+ delta += BIT_VEC64_ELEM_SZ;
}
if (delta > 0) {
@@ -265,33 +272,56 @@
}
static void bnx2x_tpa_start(struct bnx2x_fastpath *fp, u16 queue,
- struct sk_buff *skb, u16 cons, u16 prod)
+ struct sk_buff *skb, u16 cons, u16 prod,
+ struct eth_fast_path_rx_cqe *cqe)
{
struct bnx2x *bp = fp->bp;
struct sw_rx_bd *cons_rx_buf = &fp->rx_buf_ring[cons];
struct sw_rx_bd *prod_rx_buf = &fp->rx_buf_ring[prod];
struct eth_rx_bd *prod_bd = &fp->rx_desc_ring[prod];
dma_addr_t mapping;
+ struct bnx2x_agg_info *tpa_info = &fp->tpa_info[queue];
+ struct sw_rx_bd *first_buf = &tpa_info->first_buf;
- /* move empty skb from pool to prod and map it */
- prod_rx_buf->skb = fp->tpa_pool[queue].skb;
- mapping = dma_map_single(&bp->pdev->dev, fp->tpa_pool[queue].skb->data,
- fp->rx_buf_size, DMA_FROM_DEVICE);
- dma_unmap_addr_set(prod_rx_buf, mapping, mapping);
-
- /* move partial skb from cons to pool (don't unmap yet) */
- fp->tpa_pool[queue] = *cons_rx_buf;
-
- /* mark bin state as start - print error if current state != stop */
- if (fp->tpa_state[queue] != BNX2X_TPA_STOP)
+ /* print error if current state != stop */
+ if (tpa_info->tpa_state != BNX2X_TPA_STOP)
BNX2X_ERR("start of bin not in stop [%d]\n", queue);
- fp->tpa_state[queue] = BNX2X_TPA_START;
+ /* Try to map an empty skb from the aggregation info */
+ mapping = dma_map_single(&bp->pdev->dev,
+ first_buf->skb->data,
+ fp->rx_buf_size, DMA_FROM_DEVICE);
+ /*
+ * ...if it fails - move the skb from the consumer to the producer
+ * and set the current aggregation state as ERROR to drop it
+ * when TPA_STOP arrives.
+ */
+ if (unlikely(dma_mapping_error(&bp->pdev->dev, mapping))) {
+ /* Move the BD from the consumer to the producer */
+ bnx2x_reuse_rx_skb(fp, cons, prod);
+ tpa_info->tpa_state = BNX2X_TPA_ERROR;
+ return;
+ }
+
+ /* move empty skb from pool to prod */
+ prod_rx_buf->skb = first_buf->skb;
+ dma_unmap_addr_set(prod_rx_buf, mapping, mapping);
/* point prod_bd to new skb */
prod_bd->addr_hi = cpu_to_le32(U64_HI(mapping));
prod_bd->addr_lo = cpu_to_le32(U64_LO(mapping));
+ /* move partial skb from cons to pool (don't unmap yet) */
+ *first_buf = *cons_rx_buf;
+
+ /* mark bin state as START */
+ tpa_info->parsing_flags =
+ le16_to_cpu(cqe->pars_flags.flags);
+ tpa_info->vlan_tag = le16_to_cpu(cqe->vlan_tag);
+ 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;
+
#ifdef BNX2X_STOP_ON_ERROR
fp->tpa_queue_used |= (1 << queue);
#ifdef _ASM_GENERIC_INT_L64_H
@@ -322,10 +352,17 @@
static inline u16 bnx2x_set_lro_mss(struct bnx2x *bp, u16 parsing_flags,
u16 len_on_bd)
{
- /* TPA arrgregation won't have an IP options and TCP options
- * other than timestamp.
+ /*
+ * TPA arrgregation won't have either IP options or TCP options
+ * other than timestamp or IPv6 extension headers.
*/
- u16 hdrs_len = ETH_HLEN + sizeof(struct iphdr) + sizeof(struct tcphdr);
+ u16 hdrs_len = ETH_HLEN + sizeof(struct tcphdr);
+
+ if (GET_FLAG(parsing_flags, PARSING_FLAGS_OVER_ETHERNET_PROTOCOL) ==
+ PRS_FLAG_OVERETH_IPV6)
+ hdrs_len += sizeof(struct ipv6hdr);
+ else /* IPv4 */
+ hdrs_len += sizeof(struct iphdr);
/* Check if there was a TCP timestamp, if there is it's will
@@ -340,30 +377,30 @@
}
static int bnx2x_fill_frag_skb(struct bnx2x *bp, struct bnx2x_fastpath *fp,
- struct sk_buff *skb,
- struct eth_fast_path_rx_cqe *fp_cqe,
- u16 cqe_idx, u16 parsing_flags)
+ u16 queue, struct sk_buff *skb,
+ struct eth_end_agg_rx_cqe *cqe,
+ u16 cqe_idx)
{
struct sw_rx_page *rx_pg, old_rx_pg;
- u16 len_on_bd = le16_to_cpu(fp_cqe->len_on_bd);
u32 i, frag_len, frag_size, pages;
int err;
int j;
+ struct bnx2x_agg_info *tpa_info = &fp->tpa_info[queue];
+ u16 len_on_bd = tpa_info->len_on_bd;
- frag_size = le16_to_cpu(fp_cqe->pkt_len) - len_on_bd;
+ frag_size = le16_to_cpu(cqe->pkt_len) - len_on_bd;
pages = SGE_PAGE_ALIGN(frag_size) >> SGE_PAGE_SHIFT;
/* This is needed in order to enable forwarding support */
if (frag_size)
- skb_shinfo(skb)->gso_size = bnx2x_set_lro_mss(bp, parsing_flags,
- len_on_bd);
+ skb_shinfo(skb)->gso_size = bnx2x_set_lro_mss(bp,
+ tpa_info->parsing_flags, len_on_bd);
#ifdef BNX2X_STOP_ON_ERROR
if (pages > min_t(u32, 8, MAX_SKB_FRAGS)*SGE_PAGE_SIZE*PAGES_PER_SGE) {
BNX2X_ERR("SGL length is too long: %d. CQE index is %d\n",
pages, cqe_idx);
- BNX2X_ERR("fp_cqe->pkt_len = %d fp_cqe->len_on_bd = %d\n",
- fp_cqe->pkt_len, len_on_bd);
+ BNX2X_ERR("cqe->pkt_len = %d\n", cqe->pkt_len);
bnx2x_panic();
return -EINVAL;
}
@@ -371,8 +408,7 @@
/* Run through the SGL and compose the fragmented skb */
for (i = 0, j = 0; i < pages; i += PAGES_PER_SGE, j++) {
- u16 sge_idx =
- RX_SGE(le16_to_cpu(fp_cqe->sgl_or_raw_data.sgl[j]));
+ u16 sge_idx = RX_SGE(le16_to_cpu(cqe->sgl_or_raw_data.sgl[j]));
/* FW gives the indices of the SGE as if the ring is an array
(meaning that "next" element will consume 2 indices) */
@@ -407,13 +443,28 @@
}
static void bnx2x_tpa_stop(struct bnx2x *bp, struct bnx2x_fastpath *fp,
- u16 queue, int pad, int len, union eth_rx_cqe *cqe,
+ u16 queue, struct eth_end_agg_rx_cqe *cqe,
u16 cqe_idx)
{
- struct sw_rx_bd *rx_buf = &fp->tpa_pool[queue];
+ struct bnx2x_agg_info *tpa_info = &fp->tpa_info[queue];
+ struct sw_rx_bd *rx_buf = &tpa_info->first_buf;
+ u8 pad = tpa_info->placement_offset;
+ u16 len = tpa_info->len_on_bd;
struct sk_buff *skb = rx_buf->skb;
/* alloc new skb */
- struct sk_buff *new_skb = netdev_alloc_skb(bp->dev, fp->rx_buf_size);
+ struct sk_buff *new_skb;
+ u8 old_tpa_state = tpa_info->tpa_state;
+
+ tpa_info->tpa_state = BNX2X_TPA_STOP;
+
+ /* If we there was an error during the handling of the TPA_START -
+ * drop this aggregation.
+ */
+ if (old_tpa_state == BNX2X_TPA_ERROR)
+ goto drop;
+
+ /* Try to allocate the new skb */
+ new_skb = netdev_alloc_skb(bp->dev, fp->rx_buf_size);
/* Unmap skb in the pool anyway, as we are going to change
pool entry status to BNX2X_TPA_STOP even if new skb allocation
@@ -422,11 +473,6 @@
fp->rx_buf_size, DMA_FROM_DEVICE);
if (likely(new_skb)) {
- /* fix ip xsum and give it to the stack */
- /* (no need to map the new skb) */
- u16 parsing_flags =
- le16_to_cpu(cqe->fast_path_cqe.pars_flags.flags);
-
prefetch(skb);
prefetch(((char *)(skb)) + L1_CACHE_BYTES);
@@ -446,21 +492,9 @@
skb->protocol = eth_type_trans(skb, bp->dev);
skb->ip_summed = CHECKSUM_UNNECESSARY;
- {
- struct iphdr *iph;
-
- iph = (struct iphdr *)skb->data;
- iph->check = 0;
- iph->check = ip_fast_csum((u8 *)iph, iph->ihl);
- }
-
- if (!bnx2x_fill_frag_skb(bp, fp, skb,
- &cqe->fast_path_cqe, cqe_idx,
- parsing_flags)) {
- if (parsing_flags & PARSING_FLAGS_VLAN)
- __vlan_hwaccel_put_tag(skb,
- le16_to_cpu(cqe->fast_path_cqe.
- vlan_tag));
+ if (!bnx2x_fill_frag_skb(bp, fp, queue, skb, cqe, cqe_idx)) {
+ if (tpa_info->parsing_flags & PARSING_FLAGS_VLAN)
+ __vlan_hwaccel_put_tag(skb, tpa_info->vlan_tag);
napi_gro_receive(&fp->napi, skb);
} else {
DP(NETIF_MSG_RX_STATUS, "Failed to allocate new pages"
@@ -470,16 +504,16 @@
/* put new skb in bin */
- fp->tpa_pool[queue].skb = new_skb;
+ rx_buf->skb = new_skb;
- } else {
- /* else drop the packet and keep the buffer in the bin */
- DP(NETIF_MSG_RX_STATUS,
- "Failed to allocate new skb - dropping packet!\n");
- fp->eth_q_stats.rx_skb_alloc_failed++;
+ return;
}
- fp->tpa_state[queue] = BNX2X_TPA_STOP;
+drop:
+ /* drop the packet and keep the buffer in the bin */
+ DP(NETIF_MSG_RX_STATUS,
+ "Failed to allocate or map a new skb - dropping packet!\n");
+ fp->eth_q_stats.rx_skb_alloc_failed++;
}
/* Set Toeplitz hash value in the skb using the value from the
@@ -533,9 +567,16 @@
struct sw_rx_bd *rx_buf = NULL;
struct sk_buff *skb;
union eth_rx_cqe *cqe;
+ struct eth_fast_path_rx_cqe *cqe_fp;
u8 cqe_fp_flags;
+ enum eth_rx_cqe_type cqe_fp_type;
u16 len, pad;
+#ifdef BNX2X_STOP_ON_ERROR
+ if (unlikely(bp->panic))
+ return 0;
+#endif
+
comp_ring_cons = RCQ_BD(sw_comp_cons);
bd_prod = RX_BD(bd_prod);
bd_cons = RX_BD(bd_cons);
@@ -548,17 +589,18 @@
PAGE_SIZE + 1));
cqe = &fp->rx_comp_ring[comp_ring_cons];
- cqe_fp_flags = cqe->fast_path_cqe.type_error_flags;
+ cqe_fp = &cqe->fast_path_cqe;
+ cqe_fp_flags = cqe_fp->type_error_flags;
+ cqe_fp_type = cqe_fp_flags & ETH_FAST_PATH_RX_CQE_TYPE;
DP(NETIF_MSG_RX_STATUS, "CQE type %x err %x status %x"
" queue %x vlan %x len %u\n", CQE_TYPE(cqe_fp_flags),
- cqe_fp_flags, cqe->fast_path_cqe.status_flags,
- le32_to_cpu(cqe->fast_path_cqe.rss_hash_result),
- le16_to_cpu(cqe->fast_path_cqe.vlan_tag),
- le16_to_cpu(cqe->fast_path_cqe.pkt_len));
+ cqe_fp_flags, cqe_fp->status_flags,
+ le32_to_cpu(cqe_fp->rss_hash_result),
+ le16_to_cpu(cqe_fp->vlan_tag), le16_to_cpu(cqe_fp->pkt_len));
/* is this a slowpath msg? */
- if (unlikely(CQE_TYPE(cqe_fp_flags))) {
+ if (unlikely(CQE_TYPE_SLOW(cqe_fp_type))) {
bnx2x_sp_event(fp, cqe);
goto next_cqe;
@@ -567,61 +609,59 @@
rx_buf = &fp->rx_buf_ring[bd_cons];
skb = rx_buf->skb;
prefetch(skb);
- len = le16_to_cpu(cqe->fast_path_cqe.pkt_len);
- pad = cqe->fast_path_cqe.placement_offset;
- /* - If CQE is marked both TPA_START and TPA_END it is
- * a non-TPA CQE.
- * - FP CQE will always have either TPA_START or/and
- * TPA_STOP flags set.
- */
- if ((!fp->disable_tpa) &&
- (TPA_TYPE(cqe_fp_flags) !=
- (TPA_TYPE_START | TPA_TYPE_END))) {
- u16 queue = cqe->fast_path_cqe.queue_index;
+ if (!CQE_TYPE_FAST(cqe_fp_type)) {
+#ifdef BNX2X_STOP_ON_ERROR
+ /* sanity check */
+ if (fp->disable_tpa &&
+ (CQE_TYPE_START(cqe_fp_type) ||
+ CQE_TYPE_STOP(cqe_fp_type)))
+ BNX2X_ERR("START/STOP packet while "
+ "disable_tpa type %x\n",
+ CQE_TYPE(cqe_fp_type));
+#endif
- if (TPA_TYPE(cqe_fp_flags) == TPA_TYPE_START) {
+ if (CQE_TYPE_START(cqe_fp_type)) {
+ u16 queue = cqe_fp->queue_index;
DP(NETIF_MSG_RX_STATUS,
"calling tpa_start on queue %d\n",
queue);
bnx2x_tpa_start(fp, queue, skb,
- bd_cons, bd_prod);
+ bd_cons, bd_prod,
+ cqe_fp);
- /* Set Toeplitz hash for an LRO skb */
+ /* Set Toeplitz hash for LRO skb */
bnx2x_set_skb_rxhash(bp, cqe, skb);
goto next_rx;
- } else { /* TPA_STOP */
+
+ } else {
+ u16 queue =
+ cqe->end_agg_cqe.queue_index;
DP(NETIF_MSG_RX_STATUS,
"calling tpa_stop on queue %d\n",
queue);
- if (!BNX2X_RX_SUM_FIX(cqe))
- BNX2X_ERR("STOP on none TCP "
- "data\n");
-
- /* This is a size of the linear data
- on this skb */
- len = le16_to_cpu(cqe->fast_path_cqe.
- len_on_bd);
- bnx2x_tpa_stop(bp, fp, queue, pad,
- len, cqe, comp_ring_cons);
+ bnx2x_tpa_stop(bp, fp, queue,
+ &cqe->end_agg_cqe,
+ comp_ring_cons);
#ifdef BNX2X_STOP_ON_ERROR
if (bp->panic)
return 0;
#endif
- bnx2x_update_sge_prod(fp,
- &cqe->fast_path_cqe);
+ bnx2x_update_sge_prod(fp, cqe_fp);
goto next_cqe;
}
}
-
+ /* non TPA */
+ len = le16_to_cpu(cqe_fp->pkt_len);
+ pad = cqe_fp->placement_offset;
dma_sync_single_for_device(&bp->pdev->dev,
dma_unmap_addr(rx_buf, mapping),
- pad + RX_COPY_THRESH,
- DMA_FROM_DEVICE);
+ pad + RX_COPY_THRESH,
+ DMA_FROM_DEVICE);
prefetch(((char *)(skb)) + L1_CACHE_BYTES);
/* is this an error packet? */
@@ -640,8 +680,7 @@
(len <= RX_COPY_THRESH)) {
struct sk_buff *new_skb;
- new_skb = netdev_alloc_skb(bp->dev,
- len + pad);
+ new_skb = netdev_alloc_skb(bp->dev, len + pad);
if (new_skb == NULL) {
DP(NETIF_MSG_RX_ERR,
"ERROR packet dropped "
@@ -687,6 +726,7 @@
skb_checksum_none_assert(skb);
if (bp->dev->features & NETIF_F_RXCSUM) {
+
if (likely(BNX2X_RX_CSUM_OK(cqe)))
skb->ip_summed = CHECKSUM_UNNECESSARY;
else
@@ -696,10 +736,10 @@
skb_record_rx_queue(skb, fp->index);
- if (le16_to_cpu(cqe->fast_path_cqe.pars_flags.flags) &
- PARSING_FLAGS_VLAN)
+ if (le16_to_cpu(cqe_fp->pars_flags.flags) &
+ PARSING_FLAGS_VLAN)
__vlan_hwaccel_put_tag(skb,
- le16_to_cpu(cqe->fast_path_cqe.vlan_tag));
+ le16_to_cpu(cqe_fp->vlan_tag));
napi_gro_receive(&fp->napi, skb);
@@ -738,12 +778,6 @@
struct bnx2x_fastpath *fp = fp_cookie;
struct bnx2x *bp = fp->bp;
- /* Return here if interrupt is disabled */
- if (unlikely(atomic_read(&bp->intr_sem) != 0)) {
- DP(NETIF_MSG_INTR, "called but intr_sem not 0, returning\n");
- return IRQ_HANDLED;
- }
-
DP(BNX2X_MSG_FP, "got an MSI-X interrupt on IDX:SB "
"[fp %d fw_sd %d igusb %d]\n",
fp->index, fp->fw_sb_id, fp->igu_sb_id);
@@ -931,7 +965,7 @@
{
int func = BP_FUNC(bp);
int max_agg_queues = CHIP_IS_E1(bp) ? ETH_MAX_AGGREGATION_QUEUES_E1 :
- ETH_MAX_AGGREGATION_QUEUES_E1H;
+ ETH_MAX_AGGREGATION_QUEUES_E1H_E2;
u16 ring_prod;
int i, j;
@@ -943,11 +977,16 @@
"mtu %d rx_buf_size %d\n", bp->dev->mtu, fp->rx_buf_size);
if (!fp->disable_tpa) {
- /* Fill the per-aggregation pool */
+ /* Fill the per-aggregtion pool */
for (i = 0; i < max_agg_queues; i++) {
- fp->tpa_pool[i].skb =
- netdev_alloc_skb(bp->dev, fp->rx_buf_size);
- if (!fp->tpa_pool[i].skb) {
+ struct bnx2x_agg_info *tpa_info =
+ &fp->tpa_info[i];
+ struct sw_rx_bd *first_buf =
+ &tpa_info->first_buf;
+
+ first_buf->skb = netdev_alloc_skb(bp->dev,
+ fp->rx_buf_size);
+ if (!first_buf->skb) {
BNX2X_ERR("Failed to allocate TPA "
"skb pool for queue[%d] - "
"disabling TPA on this "
@@ -956,10 +995,8 @@
fp->disable_tpa = 1;
break;
}
- dma_unmap_addr_set((struct sw_rx_bd *)
- &bp->fp->tpa_pool[i],
- mapping, 0);
- fp->tpa_state[i] = BNX2X_TPA_STOP;
+ dma_unmap_addr_set(first_buf, mapping, 0);
+ tpa_info->tpa_state = BNX2X_TPA_STOP;
}
/* "next page" elements initialization */
@@ -975,13 +1012,13 @@
if (bnx2x_alloc_rx_sge(bp, fp, ring_prod) < 0) {
BNX2X_ERR("was only able to allocate "
"%d rx sges\n", i);
- BNX2X_ERR("disabling TPA for"
- " queue[%d]\n", j);
+ BNX2X_ERR("disabling TPA for "
+ "queue[%d]\n", j);
/* Cleanup already allocated elements */
- bnx2x_free_rx_sge_range(bp,
- fp, ring_prod);
- bnx2x_free_tpa_pool(bp,
- fp, max_agg_queues);
+ bnx2x_free_rx_sge_range(bp, fp,
+ ring_prod);
+ bnx2x_free_tpa_pool(bp, fp,
+ max_agg_queues);
fp->disable_tpa = 1;
ring_prod = 0;
break;
@@ -1009,7 +1046,7 @@
if (j != 0)
continue;
- if (!CHIP_IS_E2(bp)) {
+ if (CHIP_IS_E1(bp)) {
REG_WR(bp, BAR_USTRORM_INTMEM +
USTORM_MEM_WORKAROUND_ADDRESS_OFFSET(func),
U64_LO(fp->rx_comp_mapping));
@@ -1053,7 +1090,6 @@
if (skb == NULL)
continue;
-
dma_unmap_single(&bp->pdev->dev,
dma_unmap_addr(rx_buf, mapping),
fp->rx_buf_size, DMA_FROM_DEVICE);
@@ -1075,7 +1111,7 @@
if (!fp->disable_tpa)
bnx2x_free_tpa_pool(bp, fp, CHIP_IS_E1(bp) ?
ETH_MAX_AGGREGATION_QUEUES_E1 :
- ETH_MAX_AGGREGATION_QUEUES_E1H);
+ ETH_MAX_AGGREGATION_QUEUES_E1H_E2);
}
}
@@ -1102,30 +1138,43 @@
}
}
-static void bnx2x_free_msix_irqs(struct bnx2x *bp)
+/**
+ * bnx2x_free_msix_irqs - free previously requested MSI-X IRQ vectors
+ *
+ * @bp: driver handle
+ * @nvecs: number of vectors to be released
+ */
+static void bnx2x_free_msix_irqs(struct bnx2x *bp, int nvecs)
{
- int i, offset = 1;
+ int i, offset = 0;
- free_irq(bp->msix_table[0].vector, bp->dev);
+ if (nvecs == offset)
+ return;
+ free_irq(bp->msix_table[offset].vector, bp->dev);
DP(NETIF_MSG_IFDOWN, "released sp irq (%d)\n",
- bp->msix_table[0].vector);
-
+ bp->msix_table[offset].vector);
+ offset++;
#ifdef BCM_CNIC
+ if (nvecs == offset)
+ return;
offset++;
#endif
- for_each_eth_queue(bp, i) {
- DP(NETIF_MSG_IFDOWN, "about to release fp #%d->%d irq "
- "state %x\n", i, bp->msix_table[i + offset].vector,
- bnx2x_fp(bp, i, state));
- free_irq(bp->msix_table[i + offset].vector, &bp->fp[i]);
+ for_each_eth_queue(bp, i) {
+ if (nvecs == offset)
+ return;
+ DP(NETIF_MSG_IFDOWN, "about to release fp #%d->%d "
+ "irq\n", i, bp->msix_table[offset].vector);
+
+ free_irq(bp->msix_table[offset++].vector, &bp->fp[i]);
}
}
void bnx2x_free_irq(struct bnx2x *bp)
{
if (bp->flags & USING_MSIX_FLAG)
- bnx2x_free_msix_irqs(bp);
+ bnx2x_free_msix_irqs(bp, BNX2X_NUM_ETH_QUEUES(bp) +
+ CNIC_CONTEXT_USE + 1);
else if (bp->flags & USING_MSI_FLAG)
free_irq(bp->pdev->irq, bp->dev);
else
@@ -1198,9 +1247,10 @@
static int bnx2x_req_msix_irqs(struct bnx2x *bp)
{
- int i, rc, offset = 1;
+ int i, rc, offset = 0;
- rc = request_irq(bp->msix_table[0].vector, bnx2x_msix_sp_int, 0,
+ rc = request_irq(bp->msix_table[offset++].vector,
+ bnx2x_msix_sp_int, 0,
bp->dev->name, bp->dev);
if (rc) {
BNX2X_ERR("request sp irq failed\n");
@@ -1218,13 +1268,13 @@
rc = request_irq(bp->msix_table[offset].vector,
bnx2x_msix_fp_int, 0, fp->name, fp);
if (rc) {
- BNX2X_ERR("request fp #%d irq failed rc %d\n", i, rc);
- bnx2x_free_msix_irqs(bp);
+ BNX2X_ERR("request fp #%d irq (%d) failed rc %d\n", i,
+ bp->msix_table[offset].vector, rc);
+ bnx2x_free_msix_irqs(bp, offset);
return -EBUSY;
}
offset++;
- fp->state = BNX2X_FP_STATE_IRQ;
}
i = BNX2X_NUM_ETH_QUEUES(bp);
@@ -1264,42 +1314,56 @@
rc = request_irq(bp->pdev->irq, bnx2x_interrupt, flags,
bp->dev->name, bp->dev);
- if (!rc)
- bnx2x_fp(bp, 0, state) = BNX2X_FP_STATE_IRQ;
-
return rc;
}
-static void bnx2x_napi_enable(struct bnx2x *bp)
+static inline int bnx2x_setup_irqs(struct bnx2x *bp)
+{
+ int rc = 0;
+ if (bp->flags & USING_MSIX_FLAG) {
+ rc = bnx2x_req_msix_irqs(bp);
+ if (rc)
+ return rc;
+ } else {
+ bnx2x_ack_int(bp);
+ rc = bnx2x_req_irq(bp);
+ if (rc) {
+ BNX2X_ERR("IRQ request failed rc %d, aborting\n", rc);
+ return rc;
+ }
+ if (bp->flags & USING_MSI_FLAG) {
+ bp->dev->irq = bp->pdev->irq;
+ netdev_info(bp->dev, "using MSI IRQ %d\n",
+ bp->pdev->irq);
+ }
+ }
+
+ return 0;
+}
+
+static inline void bnx2x_napi_enable(struct bnx2x *bp)
{
int i;
- for_each_napi_queue(bp, i)
+ for_each_rx_queue(bp, i)
napi_enable(&bnx2x_fp(bp, i, napi));
}
-static void bnx2x_napi_disable(struct bnx2x *bp)
+static inline void bnx2x_napi_disable(struct bnx2x *bp)
{
int i;
- for_each_napi_queue(bp, i)
+ for_each_rx_queue(bp, i)
napi_disable(&bnx2x_fp(bp, i, napi));
}
void bnx2x_netif_start(struct bnx2x *bp)
{
- int intr_sem;
-
- intr_sem = atomic_dec_and_test(&bp->intr_sem);
- smp_wmb(); /* Ensure that bp->intr_sem update is SMP-safe */
-
- if (intr_sem) {
- if (netif_running(bp->dev)) {
- bnx2x_napi_enable(bp);
- bnx2x_int_enable(bp);
- if (bp->state == BNX2X_STATE_OPEN)
- netif_tx_wake_all_queues(bp->dev);
- }
+ if (netif_running(bp->dev)) {
+ bnx2x_napi_enable(bp);
+ bnx2x_int_enable(bp);
+ if (bp->state == BNX2X_STATE_OPEN)
+ netif_tx_wake_all_queues(bp->dev);
}
}
@@ -1307,7 +1371,6 @@
{
bnx2x_int_disable_sync(bp, disable_hw);
bnx2x_napi_disable(bp);
- netif_tx_disable(bp->dev);
}
u16 bnx2x_select_queue(struct net_device *dev, struct sk_buff *skb)
@@ -1358,26 +1421,6 @@
bp->num_queues += NONE_ETH_CONTEXT_USE;
}
-#ifdef BCM_CNIC
-static inline void bnx2x_set_fcoe_eth_macs(struct bnx2x *bp)
-{
- if (!NO_FCOE(bp)) {
- if (!IS_MF_SD(bp))
- bnx2x_set_fip_eth_mac_addr(bp, 1);
- bnx2x_set_all_enode_macs(bp, 1);
- bp->flags |= FCOE_MACS_SET;
- }
-}
-#endif
-
-static void bnx2x_release_firmware(struct bnx2x *bp)
-{
- kfree(bp->init_ops_offsets);
- kfree(bp->init_ops);
- kfree(bp->init_data);
- release_firmware(bp->firmware);
-}
-
static inline int bnx2x_set_real_num_queues(struct bnx2x *bp)
{
int rc, num = bp->num_queues;
@@ -1409,27 +1452,198 @@
*/
fp->rx_buf_size =
BNX2X_FCOE_MINI_JUMBO_MTU + ETH_OVREHEAD +
- BNX2X_RX_ALIGN + IP_HEADER_ALIGNMENT_PADDING;
+ BNX2X_FW_RX_ALIGN + IP_HEADER_ALIGNMENT_PADDING;
else
fp->rx_buf_size =
- bp->dev->mtu + ETH_OVREHEAD + BNX2X_RX_ALIGN +
- IP_HEADER_ALIGNMENT_PADDING;
+ bp->dev->mtu + ETH_OVREHEAD +
+ BNX2X_FW_RX_ALIGN + IP_HEADER_ALIGNMENT_PADDING;
}
}
+static inline int bnx2x_init_rss_pf(struct bnx2x *bp)
+{
+ int i;
+ u8 ind_table[T_ETH_INDIRECTION_TABLE_SIZE] = {0};
+ u8 num_eth_queues = BNX2X_NUM_ETH_QUEUES(bp);
+
+ /*
+ * Prepare the inital contents fo the indirection table if RSS is
+ * enabled
+ */
+ if (bp->multi_mode != ETH_RSS_MODE_DISABLED) {
+ for (i = 0; i < sizeof(ind_table); i++)
+ ind_table[i] =
+ bp->fp->cl_id + (i % num_eth_queues);
+ }
+
+ /*
+ * For 57710 and 57711 SEARCHER configuration (rss_keys) is
+ * per-port, so if explicit configuration is needed , do it only
+ * for a PMF.
+ *
+ * For 57712 and newer on the other hand it's a per-function
+ * configuration.
+ */
+ return bnx2x_config_rss_pf(bp, ind_table,
+ bp->port.pmf || !CHIP_IS_E1x(bp));
+}
+
+int bnx2x_config_rss_pf(struct bnx2x *bp, u8 *ind_table, bool config_hash)
+{
+ struct bnx2x_config_rss_params params = {0};
+ int i;
+
+ /* Although RSS is meaningless when there is a single HW queue we
+ * still need it enabled in order to have HW Rx hash generated.
+ *
+ * if (!is_eth_multi(bp))
+ * bp->multi_mode = ETH_RSS_MODE_DISABLED;
+ */
+
+ params.rss_obj = &bp->rss_conf_obj;
+
+ __set_bit(RAMROD_COMP_WAIT, ¶ms.ramrod_flags);
+
+ /* RSS mode */
+ switch (bp->multi_mode) {
+ case ETH_RSS_MODE_DISABLED:
+ __set_bit(BNX2X_RSS_MODE_DISABLED, ¶ms.rss_flags);
+ break;
+ case ETH_RSS_MODE_REGULAR:
+ __set_bit(BNX2X_RSS_MODE_REGULAR, ¶ms.rss_flags);
+ break;
+ case ETH_RSS_MODE_VLAN_PRI:
+ __set_bit(BNX2X_RSS_MODE_VLAN_PRI, ¶ms.rss_flags);
+ break;
+ case ETH_RSS_MODE_E1HOV_PRI:
+ __set_bit(BNX2X_RSS_MODE_E1HOV_PRI, ¶ms.rss_flags);
+ break;
+ case ETH_RSS_MODE_IP_DSCP:
+ __set_bit(BNX2X_RSS_MODE_IP_DSCP, ¶ms.rss_flags);
+ break;
+ default:
+ BNX2X_ERR("Unknown multi_mode: %d\n", bp->multi_mode);
+ return -EINVAL;
+ }
+
+ /* If RSS is enabled */
+ if (bp->multi_mode != ETH_RSS_MODE_DISABLED) {
+ /* RSS configuration */
+ __set_bit(BNX2X_RSS_IPV4, ¶ms.rss_flags);
+ __set_bit(BNX2X_RSS_IPV4_TCP, ¶ms.rss_flags);
+ __set_bit(BNX2X_RSS_IPV6, ¶ms.rss_flags);
+ __set_bit(BNX2X_RSS_IPV6_TCP, ¶ms.rss_flags);
+
+ /* Hash bits */
+ params.rss_result_mask = MULTI_MASK;
+
+ memcpy(params.ind_table, ind_table, sizeof(params.ind_table));
+
+ if (config_hash) {
+ /* RSS keys */
+ for (i = 0; i < sizeof(params.rss_key) / 4; i++)
+ params.rss_key[i] = random32();
+
+ __set_bit(BNX2X_RSS_SET_SRCH, ¶ms.rss_flags);
+ }
+ }
+
+ return bnx2x_config_rss(bp, ¶ms);
+}
+
+static inline int bnx2x_init_hw(struct bnx2x *bp, u32 load_code)
+{
+ struct bnx2x_func_state_params func_params = {0};
+
+ /* Prepare parameters for function state transitions */
+ __set_bit(RAMROD_COMP_WAIT, &func_params.ramrod_flags);
+
+ func_params.f_obj = &bp->func_obj;
+ func_params.cmd = BNX2X_F_CMD_HW_INIT;
+
+ func_params.params.hw_init.load_phase = load_code;
+
+ return bnx2x_func_state_change(bp, &func_params);
+}
+
+/*
+ * Cleans the object that have internal lists without sending
+ * ramrods. Should be run when interrutps are disabled.
+ */
+static void bnx2x_squeeze_objects(struct bnx2x *bp)
+{
+ int rc;
+ unsigned long ramrod_flags = 0, vlan_mac_flags = 0;
+ struct bnx2x_mcast_ramrod_params rparam = {0};
+ struct bnx2x_vlan_mac_obj *mac_obj = &bp->fp->mac_obj;
+
+ /***************** Cleanup MACs' object first *************************/
+
+ /* Wait for completion of requested */
+ __set_bit(RAMROD_COMP_WAIT, &ramrod_flags);
+ /* Perform a dry cleanup */
+ __set_bit(RAMROD_DRV_CLR_ONLY, &ramrod_flags);
+
+ /* Clean ETH primary MAC */
+ __set_bit(BNX2X_ETH_MAC, &vlan_mac_flags);
+ rc = mac_obj->delete_all(bp, &bp->fp->mac_obj, &vlan_mac_flags,
+ &ramrod_flags);
+ if (rc != 0)
+ BNX2X_ERR("Failed to clean ETH MACs: %d\n", rc);
+
+ /* Cleanup UC list */
+ vlan_mac_flags = 0;
+ __set_bit(BNX2X_UC_LIST_MAC, &vlan_mac_flags);
+ rc = mac_obj->delete_all(bp, mac_obj, &vlan_mac_flags,
+ &ramrod_flags);
+ if (rc != 0)
+ BNX2X_ERR("Failed to clean UC list MACs: %d\n", rc);
+
+ /***************** Now clean mcast object *****************************/
+ rparam.mcast_obj = &bp->mcast_obj;
+ __set_bit(RAMROD_DRV_CLR_ONLY, &rparam.ramrod_flags);
+
+ /* Add a DEL command... */
+ rc = bnx2x_config_mcast(bp, &rparam, BNX2X_MCAST_CMD_DEL);
+ if (rc < 0)
+ BNX2X_ERR("Failed to add a new DEL command to a multi-cast "
+ "object: %d\n", rc);
+
+ /* ...and wait until all pending commands are cleared */
+ rc = bnx2x_config_mcast(bp, &rparam, BNX2X_MCAST_CMD_CONT);
+ while (rc != 0) {
+ if (rc < 0) {
+ BNX2X_ERR("Failed to clean multi-cast object: %d\n",
+ rc);
+ return;
+ }
+
+ rc = bnx2x_config_mcast(bp, &rparam, BNX2X_MCAST_CMD_CONT);
+ }
+}
+
+#ifndef BNX2X_STOP_ON_ERROR
+#define LOAD_ERROR_EXIT(bp, label) \
+ do { \
+ (bp)->state = BNX2X_STATE_ERROR; \
+ goto label; \
+ } while (0)
+#else
+#define LOAD_ERROR_EXIT(bp, label) \
+ do { \
+ (bp)->state = BNX2X_STATE_ERROR; \
+ (bp)->panic = 1; \
+ return -EBUSY; \
+ } while (0)
+#endif
+
/* must be called with rtnl_lock */
int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
{
+ int port = BP_PORT(bp);
u32 load_code;
int i, rc;
- /* Set init arrays */
- rc = bnx2x_init_firmware(bp);
- if (rc) {
- BNX2X_ERR("Error loading firmware\n");
- return rc;
- }
-
#ifdef BNX2X_STOP_ON_ERROR
if (unlikely(bp->panic))
return -EPERM;
@@ -1456,6 +1670,10 @@
/* Set the receive queues buffer size */
bnx2x_set_rx_buf_size(bp);
+ /*
+ * set the tpa flag for each queue. The tpa flag determines the queue
+ * minimal size so it must be set prior to queue memory allocation
+ */
for_each_queue(bp, i)
bnx2x_fp(bp, i, disable_tpa) =
((bp->flags & TPA_ENABLE_FLAG) == 0);
@@ -1475,31 +1693,30 @@
rc = bnx2x_set_real_num_queues(bp);
if (rc) {
BNX2X_ERR("Unable to set real_num_queues\n");
- goto load_error0;
+ LOAD_ERROR_EXIT(bp, load_error0);
}
bnx2x_napi_enable(bp);
/* Send LOAD_REQUEST command to MCP
- Returns the type of LOAD command:
- if it is the first port to be initialized
- common blocks should be initialized, otherwise - not
- */
+ * Returns the type of LOAD command:
+ * if it is the first port to be initialized
+ * common blocks should be initialized, otherwise - not
+ */
if (!BP_NOMCP(bp)) {
load_code = bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_REQ, 0);
if (!load_code) {
BNX2X_ERR("MCP response failure, aborting\n");
rc = -EBUSY;
- goto load_error1;
+ LOAD_ERROR_EXIT(bp, load_error1);
}
if (load_code == FW_MSG_CODE_DRV_LOAD_REFUSED) {
rc = -EBUSY; /* other port in diagnostic mode */
- goto load_error1;
+ LOAD_ERROR_EXIT(bp, load_error1);
}
} else {
int path = BP_PATH(bp);
- int port = BP_PORT(bp);
DP(NETIF_MSG_IFUP, "NO MCP - load counts[%d] %d, %d, %d\n",
path, load_count[path][0], load_count[path][1],
@@ -1519,36 +1736,58 @@
if ((load_code == FW_MSG_CODE_DRV_LOAD_COMMON) ||
(load_code == FW_MSG_CODE_DRV_LOAD_COMMON_CHIP) ||
- (load_code == FW_MSG_CODE_DRV_LOAD_PORT))
+ (load_code == FW_MSG_CODE_DRV_LOAD_PORT)) {
bp->port.pmf = 1;
- else
+ /*
+ * We need the barrier to ensure the ordering between the
+ * writing to bp->port.pmf here and reading it from the
+ * bnx2x_periodic_task().
+ */
+ smp_mb();
+ queue_delayed_work(bnx2x_wq, &bp->period_task, 0);
+ } else
bp->port.pmf = 0;
DP(NETIF_MSG_LINK, "pmf %d\n", bp->port.pmf);
+ /* Init Function state controlling object */
+ bnx2x__init_func_obj(bp);
+
/* Initialize HW */
rc = bnx2x_init_hw(bp, load_code);
if (rc) {
BNX2X_ERR("HW init failed, aborting\n");
bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_DONE, 0);
- goto load_error2;
+ LOAD_ERROR_EXIT(bp, load_error2);
}
/* Connect to IRQs */
rc = bnx2x_setup_irqs(bp);
if (rc) {
bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_DONE, 0);
- goto load_error2;
+ LOAD_ERROR_EXIT(bp, load_error2);
}
/* Setup NIC internals and enable interrupts */
bnx2x_nic_init(bp, load_code);
+ /* Init per-function objects */
+ bnx2x_init_bp_objs(bp);
+
if (((load_code == FW_MSG_CODE_DRV_LOAD_COMMON) ||
(load_code == FW_MSG_CODE_DRV_LOAD_COMMON_CHIP)) &&
- (bp->common.shmem2_base))
- SHMEM2_WR(bp, dcc_support,
- (SHMEM_DCC_SUPPORT_DISABLE_ENABLE_PF_TLV |
- SHMEM_DCC_SUPPORT_BANDWIDTH_ALLOCATION_TLV));
+ (bp->common.shmem2_base)) {
+ if (SHMEM2_HAS(bp, dcc_support))
+ SHMEM2_WR(bp, dcc_support,
+ (SHMEM_DCC_SUPPORT_DISABLE_ENABLE_PF_TLV |
+ SHMEM_DCC_SUPPORT_BANDWIDTH_ALLOCATION_TLV));
+ }
+
+ bp->state = BNX2X_STATE_OPENING_WAIT4_PORT;
+ rc = bnx2x_func_start(bp);
+ if (rc) {
+ BNX2X_ERR("Function start failed!\n");
+ LOAD_ERROR_EXIT(bp, load_error3);
+ }
/* Send LOAD_DONE command to MCP */
if (!BP_NOMCP(bp)) {
@@ -1556,74 +1795,38 @@
if (!load_code) {
BNX2X_ERR("MCP response failure, aborting\n");
rc = -EBUSY;
- goto load_error3;
+ LOAD_ERROR_EXIT(bp, load_error3);
}
}
- bnx2x_dcbx_init(bp);
-
- bp->state = BNX2X_STATE_OPENING_WAIT4_PORT;
-
- rc = bnx2x_func_start(bp);
- if (rc) {
- BNX2X_ERR("Function start failed!\n");
-#ifndef BNX2X_STOP_ON_ERROR
- goto load_error3;
-#else
- bp->panic = 1;
- return -EBUSY;
-#endif
- }
-
- rc = bnx2x_setup_client(bp, &bp->fp[0], 1 /* Leading */);
+ rc = bnx2x_setup_leading(bp);
if (rc) {
BNX2X_ERR("Setup leading failed!\n");
-#ifndef BNX2X_STOP_ON_ERROR
- goto load_error3;
-#else
- bp->panic = 1;
- return -EBUSY;
-#endif
- }
-
- if (!CHIP_IS_E1(bp) &&
- (bp->mf_config[BP_VN(bp)] & FUNC_MF_CFG_FUNC_DISABLED)) {
- DP(NETIF_MSG_IFUP, "mf_cfg function disabled\n");
- bp->flags |= MF_FUNC_DIS;
+ LOAD_ERROR_EXIT(bp, load_error3);
}
#ifdef BCM_CNIC
/* Enable Timer scan */
- REG_WR(bp, TM_REG_EN_LINEAR0_TIMER + BP_PORT(bp)*4, 1);
+ REG_WR(bp, TM_REG_EN_LINEAR0_TIMER + port*4, 1);
#endif
for_each_nondefault_queue(bp, i) {
- rc = bnx2x_setup_client(bp, &bp->fp[i], 0);
+ rc = bnx2x_setup_queue(bp, &bp->fp[i], 0);
if (rc)
-#ifdef BCM_CNIC
- goto load_error4;
-#else
- goto load_error3;
-#endif
+ LOAD_ERROR_EXIT(bp, load_error4);
}
+ rc = bnx2x_init_rss_pf(bp);
+ if (rc)
+ LOAD_ERROR_EXIT(bp, load_error4);
+
/* Now when Clients are configured we are ready to work */
bp->state = BNX2X_STATE_OPEN;
-#ifdef BCM_CNIC
- bnx2x_set_fcoe_eth_macs(bp);
-#endif
-
- bnx2x_set_eth_mac(bp, 1);
-
- /* Clear MC configuration */
- if (CHIP_IS_E1(bp))
- bnx2x_invalidate_e1_mc_list(bp);
- else
- bnx2x_invalidate_e1h_mc_list(bp);
-
- /* Clear UC lists configuration */
- bnx2x_invalidate_uc_list(bp);
+ /* Configure a ucast MAC */
+ rc = bnx2x_set_eth_mac(bp, true);
+ if (rc)
+ LOAD_ERROR_EXIT(bp, load_error4);
if (bp->pending_max) {
bnx2x_update_max_mf_config(bp, bp->pending_max);
@@ -1633,15 +1836,18 @@
if (bp->port.pmf)
bnx2x_initial_phy_init(bp, load_mode);
- /* Initialize Rx filtering */
- bnx2x_set_rx_mode(bp->dev);
-
/* Start fast path */
+
+ /* Initialize Rx filter. */
+ netif_addr_lock_bh(bp->dev);
+ bnx2x_set_rx_mode(bp->dev);
+ netif_addr_unlock_bh(bp->dev);
+
+ /* Start the Tx */
switch (load_mode) {
case LOAD_NORMAL:
/* Tx queue should be only reenabled */
netif_tx_wake_all_queues(bp->dev);
- /* Initialize the receive filter. */
break;
case LOAD_OPEN:
@@ -1670,18 +1876,28 @@
#endif
bnx2x_inc_load_cnt(bp);
- bnx2x_release_firmware(bp);
+ /* Wait for all pending SP commands to complete */
+ if (!bnx2x_wait_sp_comp(bp, ~0x0UL)) {
+ BNX2X_ERR("Timeout waiting for SP elements to complete\n");
+ bnx2x_nic_unload(bp, UNLOAD_CLOSE);
+ return -EBUSY;
+ }
+ bnx2x_dcbx_init(bp);
return 0;
-#ifdef BCM_CNIC
+#ifndef BNX2X_STOP_ON_ERROR
load_error4:
+#ifdef BCM_CNIC
/* Disable Timer scan */
- REG_WR(bp, TM_REG_EN_LINEAR0_TIMER + BP_PORT(bp)*4, 0);
+ REG_WR(bp, TM_REG_EN_LINEAR0_TIMER + port*4, 0);
#endif
load_error3:
bnx2x_int_disable_sync(bp, 1);
+ /* Clean queueable objects */
+ bnx2x_squeeze_objects(bp);
+
/* Free SKBs, SGEs, TPA pool and driver internals */
bnx2x_free_skbs(bp);
for_each_rx_queue(bp, i)
@@ -1701,22 +1917,31 @@
load_error0:
bnx2x_free_mem(bp);
- bnx2x_release_firmware(bp);
-
return rc;
+#endif /* ! BNX2X_STOP_ON_ERROR */
}
/* must be called with rtnl_lock */
int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode)
{
int i;
+ bool global = false;
- if (bp->state == BNX2X_STATE_CLOSED) {
- /* Interface has been removed - nothing to recover */
+ if ((bp->state == BNX2X_STATE_CLOSED) ||
+ (bp->state == BNX2X_STATE_ERROR)) {
+ /* We can get here if the driver has been unloaded
+ * during parity error recovery and is either waiting for a
+ * leader to complete or for other functions to unload and
+ * then ifdown has been issued. In this case we want to
+ * unload and let other functions to complete a recovery
+ * process.
+ */
bp->recovery_state = BNX2X_RECOVERY_DONE;
bp->is_leader = 0;
- bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_RESERVED_08);
- smp_wmb();
+ bnx2x_release_leader_lock(bp);
+ smp_mb();
+
+ DP(NETIF_MSG_HW, "Releasing a leadership...\n");
return -EINVAL;
}
@@ -1725,18 +1950,19 @@
bnx2x_cnic_notify(bp, CNIC_CTL_STOP_CMD);
#endif
bp->state = BNX2X_STATE_CLOSING_WAIT4_HALT;
+ smp_mb();
- /* Set "drop all" */
bp->rx_mode = BNX2X_RX_MODE_NONE;
- bnx2x_set_storm_rx_mode(bp);
/* Stop Tx */
bnx2x_tx_disable(bp);
del_timer_sync(&bp->timer);
- SHMEM_WR(bp, func_mb[BP_FW_MB_IDX(bp)].drv_pulse_mb,
- (DRV_PULSE_ALWAYS_ALIVE | bp->fw_drv_pulse_wr_seq));
+ /* Set ALWAYS_ALIVE bit in shmem */
+ bp->fw_drv_pulse_wr_seq |= DRV_PULSE_ALWAYS_ALIVE;
+
+ bnx2x_drv_pulse(bp);
bnx2x_stats_handle(bp, STATS_EVENT_STOP);
@@ -1744,13 +1970,35 @@
if (unload_mode != UNLOAD_RECOVERY)
bnx2x_chip_cleanup(bp, unload_mode);
else {
- /* Disable HW interrupts, NAPI and Tx */
+ /* Send the UNLOAD_REQUEST to the MCP */
+ bnx2x_send_unload_req(bp, unload_mode);
+
+ /*
+ * Prevent transactions to host from the functions on the
+ * engine that doesn't reset global blocks in case of global
+ * attention once gloabl blocks are reset and gates are opened
+ * (the engine which leader will perform the recovery
+ * last).
+ */
+ if (!CHIP_IS_E1x(bp))
+ bnx2x_pf_disable(bp);
+
+ /* Disable HW interrupts, NAPI */
bnx2x_netif_stop(bp, 1);
/* Release IRQs */
bnx2x_free_irq(bp);
+
+ /* Report UNLOAD_DONE to MCP */
+ bnx2x_send_unload_done(bp);
}
+ /*
+ * At this stage no more interrupts will arrive so we may safly clean
+ * the queueable objects here in case they failed to get cleaned so far.
+ */
+ bnx2x_squeeze_objects(bp);
+
bp->port.pmf = 0;
/* Free SKBs, SGEs, TPA pool and driver internals */
@@ -1762,17 +2010,24 @@
bp->state = BNX2X_STATE_CLOSED;
+ /* Check if there are pending parity attentions. If there are - set
+ * RECOVERY_IN_PROGRESS.
+ */
+ if (bnx2x_chk_parity_attn(bp, &global, false)) {
+ bnx2x_set_reset_in_progress(bp);
+
+ /* Set RESET_IS_GLOBAL if needed */
+ if (global)
+ bnx2x_set_reset_global(bp);
+ }
+
+
/* The last driver must disable a "close the gate" if there is no
* parity attention or "process kill" pending.
*/
- if ((!bnx2x_dec_load_cnt(bp)) && (!bnx2x_chk_parity_attn(bp)) &&
- bnx2x_reset_is_done(bp))
+ if (!bnx2x_dec_load_cnt(bp) && bnx2x_reset_is_done(bp, BP_PATH(bp)))
bnx2x_disable_close_the_gate(bp);
- /* Reset MCP mail box sequence if there is on going recovery */
- if (unload_mode == UNLOAD_RECOVERY)
- bp->fw_seq = 0;
-
return 0;
}
@@ -2148,6 +2403,22 @@
sizeof(struct udphdr) - skb->data;
}
+static inline void bnx2x_set_sbd_csum(struct bnx2x *bp, struct sk_buff *skb,
+ struct eth_tx_start_bd *tx_start_bd, u32 xmit_type)
+{
+ tx_start_bd->bd_flags.as_bitfield |= ETH_TX_BD_FLAGS_L4_CSUM;
+
+ if (xmit_type & XMIT_CSUM_V4)
+ tx_start_bd->bd_flags.as_bitfield |=
+ ETH_TX_BD_FLAGS_IP_CSUM;
+ else
+ tx_start_bd->bd_flags.as_bitfield |=
+ ETH_TX_BD_FLAGS_IPV6;
+
+ if (!(xmit_type & XMIT_CSUM_TCP))
+ tx_start_bd->bd_flags.as_bitfield |= ETH_TX_BD_FLAGS_IS_UDP;
+}
+
/**
* bnx2x_set_pbd_csum - update PBD with checksum and return header length
*
@@ -2213,7 +2484,7 @@
struct bnx2x_fastpath *fp;
struct netdev_queue *txq;
struct sw_tx_bd *tx_buf;
- struct eth_tx_start_bd *tx_start_bd;
+ struct eth_tx_start_bd *tx_start_bd, *first_bd;
struct eth_tx_bd *tx_data_bd, *total_pkt_bd = NULL;
struct eth_tx_parse_bd_e1x *pbd_e1x = NULL;
struct eth_tx_parse_bd_e2 *pbd_e2 = NULL;
@@ -2275,7 +2546,15 @@
}
}
#endif
-
+ /* Map skb linear data for DMA */
+ mapping = dma_map_single(&bp->pdev->dev, skb->data,
+ skb_headlen(skb), DMA_TO_DEVICE);
+ if (unlikely(dma_mapping_error(&bp->pdev->dev, mapping))) {
+ DP(NETIF_MSG_TX_QUEUED, "SKB mapping failed - "
+ "silently dropping this SKB\n");
+ dev_kfree_skb_any(skb);
+ return NETDEV_TX_OK;
+ }
/*
Please read carefully. First we use one BD which we mark as start,
then we have a parsing info BD (used for TSO or xsum),
@@ -2285,12 +2564,19 @@
And above all, all pdb sizes are in words - NOT DWORDS!
*/
- pkt_prod = fp->tx_pkt_prod++;
+ /* get current pkt produced now - advance it just before sending packet
+ * since mapping of pages may fail and cause packet to be dropped
+ */
+ pkt_prod = fp->tx_pkt_prod;
bd_prod = TX_BD(fp->tx_bd_prod);
- /* get a tx_buf and first BD */
+ /* get a tx_buf and first BD
+ * tx_start_bd may be changed during SPLIT,
+ * but first_bd will always stay first
+ */
tx_buf = &fp->tx_buf_ring[TX_BD(pkt_prod)];
tx_start_bd = &fp->tx_desc_ring[bd_prod].start_bd;
+ first_bd = tx_start_bd;
tx_start_bd->bd_flags.as_bitfield = ETH_TX_BD_FLAGS_START_BD;
SET_FLAG(tx_start_bd->general_data, ETH_TX_START_BD_ETH_ADDR_TYPE,
@@ -2319,22 +2605,10 @@
/* turn on parsing and get a BD */
bd_prod = TX_BD(NEXT_TX_IDX(bd_prod));
- if (xmit_type & XMIT_CSUM) {
- tx_start_bd->bd_flags.as_bitfield |= ETH_TX_BD_FLAGS_L4_CSUM;
+ if (xmit_type & XMIT_CSUM)
+ bnx2x_set_sbd_csum(bp, skb, tx_start_bd, xmit_type);
- if (xmit_type & XMIT_CSUM_V4)
- tx_start_bd->bd_flags.as_bitfield |=
- ETH_TX_BD_FLAGS_IP_CSUM;
- else
- tx_start_bd->bd_flags.as_bitfield |=
- ETH_TX_BD_FLAGS_IPV6;
-
- if (!(xmit_type & XMIT_CSUM_TCP))
- tx_start_bd->bd_flags.as_bitfield |=
- ETH_TX_BD_FLAGS_IS_UDP;
- }
-
- if (CHIP_IS_E2(bp)) {
+ if (!CHIP_IS_E1x(bp)) {
pbd_e2 = &fp->tx_desc_ring[bd_prod].parse_bd_e2;
memset(pbd_e2, 0, sizeof(struct eth_tx_parse_bd_e2));
/* Set PBD in checksum offload case */
@@ -2342,6 +2616,20 @@
hlen = bnx2x_set_pbd_csum_e2(bp, skb,
&pbd_e2_parsing_data,
xmit_type);
+ if (IS_MF_SI(bp)) {
+ /*
+ * fill in the MAC addresses in the PBD - for local
+ * switching
+ */
+ bnx2x_set_fw_mac_addr(&pbd_e2->src_mac_addr_hi,
+ &pbd_e2->src_mac_addr_mid,
+ &pbd_e2->src_mac_addr_lo,
+ eth->h_source);
+ bnx2x_set_fw_mac_addr(&pbd_e2->dst_mac_addr_hi,
+ &pbd_e2->dst_mac_addr_mid,
+ &pbd_e2->dst_mac_addr_lo,
+ eth->h_dest);
+ }
} else {
pbd_e1x = &fp->tx_desc_ring[bd_prod].parse_bd_e1x;
memset(pbd_e1x, 0, sizeof(struct eth_tx_parse_bd_e1x));
@@ -2351,15 +2639,10 @@
}
- /* Map skb linear data for DMA */
- mapping = dma_map_single(&bp->pdev->dev, skb->data,
- skb_headlen(skb), DMA_TO_DEVICE);
-
/* Setup the data pointer of the first BD of the packet */
tx_start_bd->addr_hi = cpu_to_le32(U64_HI(mapping));
tx_start_bd->addr_lo = cpu_to_le32(U64_LO(mapping));
- nbd = skb_shinfo(skb)->nr_frags + 2; /* start_bd + pbd + frags */
- tx_start_bd->nbd = cpu_to_le16(nbd);
+ nbd = 2; /* start_bd + pbd + frags (updated when pages are mapped) */
tx_start_bd->nbytes = cpu_to_le16(skb_headlen(skb));
pkt_size = tx_start_bd->nbytes;
@@ -2382,7 +2665,7 @@
if (unlikely(skb_headlen(skb) > hlen))
bd_prod = bnx2x_tx_split(bp, fp, tx_buf, &tx_start_bd,
hlen, bd_prod, ++nbd);
- if (CHIP_IS_E2(bp))
+ if (!CHIP_IS_E1x(bp))
bnx2x_set_pbd_gso_e2(skb, &pbd_e2_parsing_data,
xmit_type);
else
@@ -2401,19 +2684,34 @@
for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+ mapping = dma_map_page(&bp->pdev->dev, frag->page,
+ frag->page_offset, frag->size,
+ DMA_TO_DEVICE);
+ if (unlikely(dma_mapping_error(&bp->pdev->dev, mapping))) {
+
+ DP(NETIF_MSG_TX_QUEUED, "Unable to map page - "
+ "dropping packet...\n");
+
+ /* we need unmap all buffers already mapped
+ * for this SKB;
+ * first_bd->nbd need to be properly updated
+ * before call to bnx2x_free_tx_pkt
+ */
+ first_bd->nbd = cpu_to_le16(nbd);
+ bnx2x_free_tx_pkt(bp, fp, TX_BD(fp->tx_pkt_prod));
+ return NETDEV_TX_OK;
+ }
+
bd_prod = TX_BD(NEXT_TX_IDX(bd_prod));
tx_data_bd = &fp->tx_desc_ring[bd_prod].reg_bd;
if (total_pkt_bd == NULL)
total_pkt_bd = &fp->tx_desc_ring[bd_prod].reg_bd;
- mapping = dma_map_page(&bp->pdev->dev, frag->page,
- frag->page_offset,
- frag->size, DMA_TO_DEVICE);
-
tx_data_bd->addr_hi = cpu_to_le32(U64_HI(mapping));
tx_data_bd->addr_lo = cpu_to_le32(U64_LO(mapping));
tx_data_bd->nbytes = cpu_to_le16(frag->size);
le16_add_cpu(&pkt_size, frag->size);
+ nbd++;
DP(NETIF_MSG_TX_QUEUED,
"frag %d bd @%p addr (%x:%x) nbytes %d\n",
@@ -2423,6 +2721,9 @@
DP(NETIF_MSG_TX_QUEUED, "last bd @%p\n", tx_data_bd);
+ /* update with actual num BDs */
+ first_bd->nbd = cpu_to_le16(nbd);
+
bd_prod = TX_BD(NEXT_TX_IDX(bd_prod));
/* now send a tx doorbell, counting the next BD
@@ -2431,6 +2732,13 @@
if (TX_BD_POFF(bd_prod) < nbd)
nbd++;
+ /* total_pkt_bytes should be set on the first data BD if
+ * it's not an LSO packet and there is more than one
+ * data BD. In this case pkt_size is limited by an MTU value.
+ * However we prefer to set it for an LSO packet (while we don't
+ * have to) in order to save some CPU cycles in a none-LSO
+ * case, when we much more care about them.
+ */
if (total_pkt_bd != NULL)
total_pkt_bd->total_pkt_bytes = pkt_size;
@@ -2451,6 +2759,7 @@
pbd_e2->parsing_data);
DP(NETIF_MSG_TX_QUEUED, "doorbell: nbd %d bd %u\n", nbd, bd_prod);
+ fp->tx_pkt_prod++;
/*
* Make sure that the BD data is updated before updating the producer
* since FW might read the BD right after the producer is updated.
@@ -2491,15 +2800,23 @@
{
struct sockaddr *addr = p;
struct bnx2x *bp = netdev_priv(dev);
+ int rc = 0;
if (!is_valid_ether_addr((u8 *)(addr->sa_data)))
return -EINVAL;
- memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
- if (netif_running(dev))
- bnx2x_set_eth_mac(bp, 1);
+ if (netif_running(dev)) {
+ rc = bnx2x_set_eth_mac(bp, false);
+ if (rc)
+ return rc;
+ }
- return 0;
+ memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
+
+ if (netif_running(dev))
+ rc = bnx2x_set_eth_mac(bp, true);
+
+ return rc;
}
static void bnx2x_free_fp_mem_at(struct bnx2x *bp, int fp_index)
@@ -2516,7 +2833,7 @@
} else {
#endif
/* status blocks */
- if (CHIP_IS_E2(bp))
+ if (!CHIP_IS_E1x(bp))
BNX2X_PCI_FREE(sb->e2_sb,
bnx2x_fp(bp, fp_index,
status_blk_mapping),
@@ -2572,7 +2889,7 @@
static inline void set_sb_shortcuts(struct bnx2x *bp, int index)
{
union host_hc_status_block status_blk = bnx2x_fp(bp, index, status_blk);
- if (CHIP_IS_E2(bp)) {
+ if (!CHIP_IS_E1x(bp)) {
bnx2x_fp(bp, index, sb_index_values) =
(__le16 *)status_blk.e2_sb->sb.index_values;
bnx2x_fp(bp, index, sb_running_index) =
@@ -2609,7 +2926,7 @@
if (!IS_FCOE_IDX(index)) {
#endif
/* status blocks */
- if (CHIP_IS_E2(bp))
+ if (!CHIP_IS_E1x(bp))
BNX2X_PCI_ALLOC(sb->e2_sb,
&bnx2x_fp(bp, index, status_blk_mapping),
sizeof(struct host_hc_status_block_e2));
@@ -2620,7 +2937,12 @@
#ifdef BCM_CNIC
}
#endif
- set_sb_shortcuts(bp, index);
+
+ /* FCoE Queue uses Default SB and doesn't ACK the SB, thus no need to
+ * set shortcuts for it.
+ */
+ if (!IS_FCOE_IDX(index))
+ set_sb_shortcuts(bp, index);
/* Tx */
if (!skip_tx_queue(bp, index)) {
@@ -2697,9 +3019,13 @@
if (bnx2x_alloc_fp_mem_at(bp, 0))
return -ENOMEM;
#ifdef BCM_CNIC
- /* FCoE */
- if (bnx2x_alloc_fp_mem_at(bp, FCOE_IDX))
- return -ENOMEM;
+ if (!NO_FCOE(bp))
+ /* FCoE */
+ if (bnx2x_alloc_fp_mem_at(bp, FCOE_IDX))
+ /* we will fail load process instead of mark
+ * NO_FCOE_FLAG
+ */
+ return -ENOMEM;
#endif
/* RSS */
for_each_nondefault_eth_queue(bp, i)
@@ -2729,30 +3055,6 @@
return 0;
}
-static int bnx2x_setup_irqs(struct bnx2x *bp)
-{
- int rc = 0;
- if (bp->flags & USING_MSIX_FLAG) {
- rc = bnx2x_req_msix_irqs(bp);
- if (rc)
- return rc;
- } else {
- bnx2x_ack_int(bp);
- rc = bnx2x_req_irq(bp);
- if (rc) {
- BNX2X_ERR("IRQ request failed rc %d, aborting\n", rc);
- return rc;
- }
- if (bp->flags & USING_MSI_FLAG) {
- bp->dev->irq = bp->pdev->irq;
- netdev_info(bp->dev, "using MSI IRQ %d\n",
- bp->pdev->irq);
- }
- }
-
- return 0;
-}
-
void bnx2x_free_mem_bp(struct bnx2x *bp)
{
kfree(bp->fp);
@@ -2792,7 +3094,7 @@
}
-static int bnx2x_reload_if_running(struct net_device *dev)
+int bnx2x_reload_if_running(struct net_device *dev)
{
struct bnx2x *bp = netdev_priv(dev);
@@ -2803,6 +3105,55 @@
return bnx2x_nic_load(bp, LOAD_NORMAL);
}
+int bnx2x_get_cur_phy_idx(struct bnx2x *bp)
+{
+ u32 sel_phy_idx = 0;
+ if (bp->link_params.num_phys <= 1)
+ return INT_PHY;
+
+ if (bp->link_vars.link_up) {
+ sel_phy_idx = EXT_PHY1;
+ /* In case link is SERDES, check if the EXT_PHY2 is the one */
+ if ((bp->link_vars.link_status & LINK_STATUS_SERDES_LINK) &&
+ (bp->link_params.phy[EXT_PHY2].supported & SUPPORTED_FIBRE))
+ sel_phy_idx = EXT_PHY2;
+ } else {
+
+ switch (bnx2x_phy_selection(&bp->link_params)) {
+ case PORT_HW_CFG_PHY_SELECTION_HARDWARE_DEFAULT:
+ case PORT_HW_CFG_PHY_SELECTION_FIRST_PHY:
+ case PORT_HW_CFG_PHY_SELECTION_FIRST_PHY_PRIORITY:
+ sel_phy_idx = EXT_PHY1;
+ break;
+ case PORT_HW_CFG_PHY_SELECTION_SECOND_PHY:
+ case PORT_HW_CFG_PHY_SELECTION_SECOND_PHY_PRIORITY:
+ sel_phy_idx = EXT_PHY2;
+ break;
+ }
+ }
+
+ return sel_phy_idx;
+
+}
+int bnx2x_get_link_cfg_idx(struct bnx2x *bp)
+{
+ u32 sel_phy_idx = bnx2x_get_cur_phy_idx(bp);
+ /*
+ * The selected actived PHY is always after swapping (in case PHY
+ * swapping is enabled). So when swapping is enabled, we need to reverse
+ * the configuration
+ */
+
+ if (bp->link_params.multi_phy_config &
+ PORT_HW_CFG_PHY_SWAPPED_ENABLED) {
+ if (sel_phy_idx == EXT_PHY1)
+ sel_phy_idx = EXT_PHY2;
+ else if (sel_phy_idx == EXT_PHY2)
+ sel_phy_idx = EXT_PHY1;
+ }
+ return LINK_CONFIG_IDX(sel_phy_idx);
+}
+
/* called with rtnl_lock */
int bnx2x_change_mtu(struct net_device *dev, int new_mtu)
{
@@ -2954,3 +3305,57 @@
return rc;
}
+
+
+void bnx2x_set_ctx_validation(struct bnx2x *bp, struct eth_context *cxt,
+ u32 cid)
+{
+ /* ustorm cxt validation */
+ cxt->ustorm_ag_context.cdu_usage =
+ CDU_RSRVD_VALUE_TYPE_A(HW_CID(bp, cid),
+ CDU_REGION_NUMBER_UCM_AG, ETH_CONNECTION_TYPE);
+ /* xcontext validation */
+ cxt->xstorm_ag_context.cdu_reserved =
+ CDU_RSRVD_VALUE_TYPE_A(HW_CID(bp, cid),
+ CDU_REGION_NUMBER_XCM_AG, ETH_CONNECTION_TYPE);
+}
+
+static inline void storm_memset_hc_timeout(struct bnx2x *bp, u8 port,
+ u8 fw_sb_id, u8 sb_index,
+ u8 ticks)
+{
+
+ u32 addr = BAR_CSTRORM_INTMEM +
+ CSTORM_STATUS_BLOCK_DATA_TIMEOUT_OFFSET(fw_sb_id, sb_index);
+ REG_WR8(bp, addr, ticks);
+ DP(NETIF_MSG_HW, "port %x fw_sb_id %d sb_index %d ticks %d\n",
+ port, fw_sb_id, sb_index, ticks);
+}
+
+static inline void storm_memset_hc_disable(struct bnx2x *bp, u8 port,
+ u16 fw_sb_id, u8 sb_index,
+ u8 disable)
+{
+ u32 enable_flag = disable ? 0 : (1 << HC_INDEX_DATA_HC_ENABLED_SHIFT);
+ u32 addr = BAR_CSTRORM_INTMEM +
+ CSTORM_STATUS_BLOCK_DATA_FLAGS_OFFSET(fw_sb_id, sb_index);
+ u16 flags = REG_RD16(bp, addr);
+ /* clear and set */
+ flags &= ~HC_INDEX_DATA_HC_ENABLED;
+ flags |= enable_flag;
+ REG_WR16(bp, addr, flags);
+ DP(NETIF_MSG_HW, "port %x fw_sb_id %d sb_index %d disable %d\n",
+ port, fw_sb_id, sb_index, disable);
+}
+
+void bnx2x_update_coalesce_sb_index(struct bnx2x *bp, u8 fw_sb_id,
+ u8 sb_index, u8 disable, u16 usec)
+{
+ int port = BP_PORT(bp);
+ u8 ticks = usec / BNX2X_BTR;
+
+ storm_memset_hc_timeout(bp, port, fw_sb_id, sb_index, ticks);
+
+ disable = disable ? 1 : (usec ? 0 : 1);
+ storm_memset_hc_disable(bp, port, fw_sb_id, sb_index, disable);
+}
diff --git a/drivers/net/bnx2x/bnx2x_cmn.h b/drivers/net/bnx2x/bnx2x_cmn.h
index 1a3545b..c016e20 100644
--- a/drivers/net/bnx2x/bnx2x_cmn.h
+++ b/drivers/net/bnx2x/bnx2x_cmn.h
@@ -18,11 +18,15 @@
#define BNX2X_CMN_H
#include <linux/types.h>
+#include <linux/pci.h>
#include <linux/netdevice.h>
#include "bnx2x.h"
+/* This is used as a replacement for an MCP if it's not present */
+extern int load_count[2][3]; /* per-path: 0-common, 1-port0, 2-port1 */
+
extern int num_queues;
/************************ Macros ********************************/
@@ -61,6 +65,73 @@
/*********************** Interfaces ****************************
* Functions that need to be implemented by each driver version
*/
+/* Init */
+
+/**
+ * bnx2x_send_unload_req - request unload mode from the MCP.
+ *
+ * @bp: driver handle
+ * @unload_mode: requested function's unload mode
+ *
+ * Return unload mode returned by the MCP: COMMON, PORT or FUNC.
+ */
+u32 bnx2x_send_unload_req(struct bnx2x *bp, int unload_mode);
+
+/**
+ * bnx2x_send_unload_done - send UNLOAD_DONE command to the MCP.
+ *
+ * @bp: driver handle
+ */
+void bnx2x_send_unload_done(struct bnx2x *bp);
+
+/**
+ * bnx2x_config_rss_pf - configure RSS parameters.
+ *
+ * @bp: driver handle
+ * @ind_table: indirection table to configure
+ * @config_hash: re-configure RSS hash keys configuration
+ */
+int bnx2x_config_rss_pf(struct bnx2x *bp, u8 *ind_table, bool config_hash);
+
+/**
+ * bnx2x__init_func_obj - init function object
+ *
+ * @bp: driver handle
+ *
+ * Initializes the Function Object with the appropriate
+ * parameters which include a function slow path driver
+ * interface.
+ */
+void bnx2x__init_func_obj(struct bnx2x *bp);
+
+/**
+ * bnx2x_setup_queue - setup eth queue.
+ *
+ * @bp: driver handle
+ * @fp: pointer to the fastpath structure
+ * @leading: boolean
+ *
+ */
+int bnx2x_setup_queue(struct bnx2x *bp, struct bnx2x_fastpath *fp,
+ bool leading);
+
+/**
+ * bnx2x_setup_leading - bring up a leading eth queue.
+ *
+ * @bp: driver handle
+ */
+int bnx2x_setup_leading(struct bnx2x *bp);
+
+/**
+ * bnx2x_fw_command - send the MCP a request
+ *
+ * @bp: driver handle
+ * @command: request
+ * @param: request's parameter
+ *
+ * block until there is a reply
+ */
+u32 bnx2x_fw_command(struct bnx2x *bp, u32 command, u32 param);
/**
* bnx2x_initial_phy_init - initialize link parameters structure variables.
@@ -88,6 +159,32 @@
u8 bnx2x_link_test(struct bnx2x *bp, u8 is_serdes);
/**
+ * bnx2x_drv_pulse - write driver pulse to shmem
+ *
+ * @bp: driver handle
+ *
+ * writes the value in bp->fw_drv_pulse_wr_seq to drv_pulse mbox
+ * in the shmem.
+ */
+void bnx2x_drv_pulse(struct bnx2x *bp);
+
+/**
+ * bnx2x_igu_ack_sb - update IGU with current SB value
+ *
+ * @bp: driver handle
+ * @igu_sb_id: SB id
+ * @segment: SB segment
+ * @index: SB index
+ * @op: SB operation
+ * @update: is HW update required
+ */
+void bnx2x_igu_ack_sb(struct bnx2x *bp, u8 igu_sb_id, u8 segment,
+ u16 index, u8 op, u8 update);
+
+/* Disable transactions from chip to host */
+void bnx2x_pf_disable(struct bnx2x *bp);
+
+/**
* bnx2x__link_status_update - handles link status change.
*
* @bp: driver handle
@@ -165,21 +262,6 @@
void bnx2x_int_disable_sync(struct bnx2x *bp, int disable_hw);
/**
- * bnx2x_init_firmware - loads device firmware
- *
- * @bp: driver handle
- */
-int bnx2x_init_firmware(struct bnx2x *bp);
-
-/**
- * bnx2x_init_hw - init HW blocks according to current initialization stage.
- *
- * @bp: driver handle
- * @load_code: COMMON, PORT or FUNCTION
- */
-int bnx2x_init_hw(struct bnx2x *bp, u32 load_code);
-
-/**
* bnx2x_nic_init - init driver internals.
*
* @bp: driver handle
@@ -207,16 +289,6 @@
void bnx2x_free_mem(struct bnx2x *bp);
/**
- * bnx2x_setup_client - setup eth client.
- *
- * @bp: driver handle
- * @fp: pointer to fastpath structure
- * @is_leading: boolean
- */
-int bnx2x_setup_client(struct bnx2x *bp, struct bnx2x_fastpath *fp,
- int is_leading);
-
-/**
* bnx2x_set_num_queues - set number of queues according to mode.
*
* @bp: driver handle
@@ -252,6 +324,13 @@
int bnx2x_release_hw_lock(struct bnx2x *bp, u32 resource);
/**
+ * bnx2x_release_leader_lock - release recovery leader lock
+ *
+ * @bp: driver handle
+ */
+int bnx2x_release_leader_lock(struct bnx2x *bp);
+
+/**
* bnx2x_set_eth_mac - configure eth MAC address in the HW
*
* @bp: driver handle
@@ -259,29 +338,7 @@
*
* Configures according to the value in netdev->dev_addr.
*/
-void bnx2x_set_eth_mac(struct bnx2x *bp, int set);
-
-#ifdef BCM_CNIC
-/**
- * bnx2x_set_fip_eth_mac_addr - Set/Clear FIP MAC(s)
- *
- * @bp: driver handle
- * @set: set or clear the CAM entry
- *
- * Used next enties in the CAM after the ETH MAC(s).
- * This function will wait until the ramdord completion returns.
- * Return 0 if cussess, -ENODEV if ramrod doesn't return.
- */
-int bnx2x_set_fip_eth_mac_addr(struct bnx2x *bp, int set);
-
-/**
- * bnx2x_set_all_enode_macs - Set/Clear ALL_ENODE mcast MAC.
- *
- * @bp: driver handle
- * @set: set or clear
- */
-int bnx2x_set_all_enode_macs(struct bnx2x *bp, int set);
-#endif
+int bnx2x_set_eth_mac(struct bnx2x *bp, bool set);
/**
* bnx2x_set_rx_mode - set MAC filtering configurations.
@@ -289,6 +346,8 @@
* @dev: netdevice
*
* called with netif_tx_lock from dev_mcast.c
+ * If bp->state is OPEN, should be called with
+ * netif_addr_lock_bh()
*/
void bnx2x_set_rx_mode(struct net_device *dev);
@@ -296,25 +355,38 @@
* bnx2x_set_storm_rx_mode - configure MAC filtering rules in a FW.
*
* @bp: driver handle
+ *
+ * If bp->state is OPEN, should be called with
+ * netif_addr_lock_bh().
*/
void bnx2x_set_storm_rx_mode(struct bnx2x *bp);
+/**
+ * bnx2x_set_q_rx_mode - configures rx_mode for a single queue.
+ *
+ * @bp: driver handle
+ * @cl_id: client id
+ * @rx_mode_flags: rx mode configuration
+ * @rx_accept_flags: rx accept configuration
+ * @tx_accept_flags: tx accept configuration (tx switch)
+ * @ramrod_flags: ramrod configuration
+ */
+void bnx2x_set_q_rx_mode(struct bnx2x *bp, u8 cl_id,
+ unsigned long rx_mode_flags,
+ unsigned long rx_accept_flags,
+ unsigned long tx_accept_flags,
+ unsigned long ramrod_flags);
+
/* Parity errors related */
void bnx2x_inc_load_cnt(struct bnx2x *bp);
u32 bnx2x_dec_load_cnt(struct bnx2x *bp);
-bool bnx2x_chk_parity_attn(struct bnx2x *bp);
-bool bnx2x_reset_is_done(struct bnx2x *bp);
+bool bnx2x_chk_parity_attn(struct bnx2x *bp, bool *global, bool print);
+bool bnx2x_reset_is_done(struct bnx2x *bp, int engine);
+void bnx2x_set_reset_in_progress(struct bnx2x *bp);
+void bnx2x_set_reset_global(struct bnx2x *bp);
void bnx2x_disable_close_the_gate(struct bnx2x *bp);
/**
- * bnx2x_stats_handle - perform statistics handling according to event.
- *
- * @bp: driver handle
- * @event: bnx2x_stats_event
- */
-void bnx2x_stats_handle(struct bnx2x *bp, enum bnx2x_stats_event event);
-
-/**
* bnx2x_sp_event - handle ramrods completion.
*
* @fp: fastpath handle for the event
@@ -323,15 +395,6 @@
void bnx2x_sp_event(struct bnx2x_fastpath *fp, union eth_rx_cqe *rr_cqe);
/**
- * bnx2x_func_start - init function
- *
- * @bp: driver handle
- *
- * Must be called before sending CLIENT_SETUP for the first client.
- */
-int bnx2x_func_start(struct bnx2x *bp);
-
-/**
* bnx2x_ilt_set_info - prepare ILT configurations.
*
* @bp: driver handle
@@ -362,6 +425,10 @@
* @value: new value
*/
void bnx2x_update_max_mf_config(struct bnx2x *bp, u32 value);
+/* Error handling */
+void bnx2x_panic_dump(struct bnx2x *bp);
+
+void bnx2x_fw_dump_lvl(struct bnx2x *bp, const char *lvl);
/* dev_close main block */
int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode);
@@ -375,11 +442,17 @@
/* select_queue callback */
u16 bnx2x_select_queue(struct net_device *dev, struct sk_buff *skb);
+/* reload helper */
+int bnx2x_reload_if_running(struct net_device *dev);
+
int bnx2x_change_mac_addr(struct net_device *dev, void *p);
/* NAPI poll Rx part */
int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget);
+void bnx2x_update_rx_prod(struct bnx2x *bp, struct bnx2x_fastpath *fp,
+ u16 bd_prod, u16 rx_comp_prod, u16 rx_sge_prod);
+
/* NAPI poll Tx part */
int bnx2x_tx_int(struct bnx2x_fastpath *fp);
@@ -392,7 +465,6 @@
void bnx2x_free_fp_mem(struct bnx2x *bp);
int bnx2x_alloc_fp_mem(struct bnx2x *bp);
-
void bnx2x_init_rx_rings(struct bnx2x *bp);
void bnx2x_free_skbs(struct bnx2x *bp);
void bnx2x_netif_stop(struct bnx2x *bp, int disable_hw);
@@ -457,19 +529,20 @@
*/
void bnx2x_tx_timeout(struct net_device *dev);
+/*********************** Inlines **********************************/
+/*********************** Fast path ********************************/
static inline void bnx2x_update_fpsb_idx(struct bnx2x_fastpath *fp)
{
barrier(); /* status block is written to by the chip */
fp->fp_hc_idx = fp->sb_running_index[SM_RX_ID];
}
-static inline void bnx2x_update_rx_prod(struct bnx2x *bp,
- struct bnx2x_fastpath *fp,
- u16 bd_prod, u16 rx_comp_prod,
- u16 rx_sge_prod)
+static inline void bnx2x_update_rx_prod_gen(struct bnx2x *bp,
+ struct bnx2x_fastpath *fp, u16 bd_prod,
+ u16 rx_comp_prod, u16 rx_sge_prod, u32 start)
{
struct ustorm_eth_rx_producers rx_prods = {0};
- int i;
+ u32 i;
/* Update producers */
rx_prods.bd_prod = bd_prod;
@@ -486,10 +559,8 @@
*/
wmb();
- for (i = 0; i < sizeof(struct ustorm_eth_rx_producers)/4; i++)
- REG_WR(bp,
- BAR_USTRORM_INTMEM + fp->ustorm_rx_prods_offset + i*4,
- ((u32 *)&rx_prods)[i]);
+ for (i = 0; i < sizeof(rx_prods)/4; i++)
+ REG_WR(bp, start + i*4, ((u32 *)&rx_prods)[i]);
mmiowb(); /* keep prod updates ordered */
@@ -519,7 +590,7 @@
barrier();
}
-static inline void bnx2x_igu_clear_sb_gen(struct bnx2x *bp,
+static inline void bnx2x_igu_clear_sb_gen(struct bnx2x *bp, u8 func,
u8 idu_sb_id, bool is_Pf)
{
u32 data, ctl, cnt = 100;
@@ -527,7 +598,7 @@
u32 igu_addr_ctl = IGU_REG_COMMAND_REG_CTRL;
u32 igu_addr_ack = IGU_REG_CSTORM_TYPE_0_SB_CLEANUP + (idu_sb_id/32)*4;
u32 sb_bit = 1 << (idu_sb_id%32);
- u32 func_encode = BP_FUNC(bp) |
+ u32 func_encode = func |
((is_Pf == true ? 1 : 0) << IGU_FID_ENCODE_IS_PF_SHIFT);
u32 addr_encode = IGU_CMD_E2_PROD_UPD_BASE + idu_sb_id;
@@ -590,15 +661,6 @@
barrier();
}
-static inline void bnx2x_igu_ack_sb(struct bnx2x *bp, u8 igu_sb_id, u8 segment,
- u16 index, u8 op, u8 update)
-{
- u32 igu_addr = BAR_IGU_INTMEM + (IGU_CMD_INT_ACK_BASE + igu_sb_id)*8;
-
- bnx2x_igu_ack_sb_gen(bp, igu_sb_id, segment, index, op, update,
- igu_addr);
-}
-
static inline void bnx2x_ack_sb(struct bnx2x *bp, u8 igu_sb_id, u8 storm,
u16 index, u8 op, u8 update)
{
@@ -705,7 +767,7 @@
}
/**
- * disables tx from stack point of view
+ * bnx2x_tx_disable - disables tx from stack point of view
*
* @bp: driver handle
*/
@@ -740,7 +802,7 @@
int i;
/* Add NAPI objects */
- for_each_napi_queue(bp, i)
+ for_each_rx_queue(bp, i)
netif_napi_add(bp->dev, &bnx2x_fp(bp, i, napi),
bnx2x_poll, BNX2X_NAPI_WEIGHT);
}
@@ -749,7 +811,7 @@
{
int i;
- for_each_napi_queue(bp, i)
+ for_each_rx_queue(bp, i)
netif_napi_del(&bnx2x_fp(bp, i, napi));
}
@@ -779,7 +841,7 @@
int idx = RX_SGE_CNT * i - 1;
for (j = 0; j < 2; j++) {
- SGE_MASK_CLEAR_BIT(fp, idx);
+ BIT_VEC64_CLEAR_BIT(fp->sge_mask, idx);
idx--;
}
}
@@ -789,7 +851,7 @@
{
/* Set the mask to all 1-s: it's faster to compare to 0 than to 0xf-s */
memset(fp->sge_mask, 0xff,
- (NUM_RX_SGE >> RX_SGE_MASK_ELEM_SHIFT)*sizeof(u64));
+ (NUM_RX_SGE >> BIT_VEC64_ELEM_SHIFT)*sizeof(u64));
/* Clear the two last indices in the page to 1:
these are the indices that correspond to the "next" element,
@@ -871,12 +933,61 @@
dma_unmap_addr(cons_rx_buf, mapping),
RX_COPY_THRESH, DMA_FROM_DEVICE);
- prod_rx_buf->skb = cons_rx_buf->skb;
dma_unmap_addr_set(prod_rx_buf, mapping,
dma_unmap_addr(cons_rx_buf, mapping));
+ prod_rx_buf->skb = cons_rx_buf->skb;
*prod_bd = *cons_bd;
}
+/************************* Init ******************************************/
+
+/**
+ * bnx2x_func_start - init function
+ *
+ * @bp: driver handle
+ *
+ * Must be called before sending CLIENT_SETUP for the first client.
+ */
+static inline int bnx2x_func_start(struct bnx2x *bp)
+{
+ struct bnx2x_func_state_params func_params = {0};
+ struct bnx2x_func_start_params *start_params =
+ &func_params.params.start;
+
+ /* Prepare parameters for function state transitions */
+ __set_bit(RAMROD_COMP_WAIT, &func_params.ramrod_flags);
+
+ func_params.f_obj = &bp->func_obj;
+ func_params.cmd = BNX2X_F_CMD_START;
+
+ /* Function parameters */
+ start_params->mf_mode = bp->mf_mode;
+ start_params->sd_vlan_tag = bp->mf_ov;
+ start_params->network_cos_mode = OVERRIDE_COS;
+
+ return bnx2x_func_state_change(bp, &func_params);
+}
+
+
+/**
+ * bnx2x_set_fw_mac_addr - fill in a MAC address in FW format
+ *
+ * @fw_hi: pointer to upper part
+ * @fw_mid: pointer to middle part
+ * @fw_lo: pointer to lower part
+ * @mac: pointer to MAC address
+ */
+static inline void bnx2x_set_fw_mac_addr(u16 *fw_hi, u16 *fw_mid, u16 *fw_lo,
+ u8 *mac)
+{
+ ((u8 *)fw_hi)[0] = mac[1];
+ ((u8 *)fw_hi)[1] = mac[0];
+ ((u8 *)fw_mid)[0] = mac[3];
+ ((u8 *)fw_mid)[1] = mac[2];
+ ((u8 *)fw_lo)[0] = mac[5];
+ ((u8 *)fw_lo)[1] = mac[4];
+}
+
static inline void bnx2x_free_rx_sge_range(struct bnx2x *bp,
struct bnx2x_fastpath *fp, int last)
{
@@ -895,21 +1006,20 @@
int i;
for (i = 0; i < last; i++) {
- struct sw_rx_bd *rx_buf = &(fp->tpa_pool[i]);
- struct sk_buff *skb = rx_buf->skb;
+ struct bnx2x_agg_info *tpa_info = &fp->tpa_info[i];
+ struct sw_rx_bd *first_buf = &tpa_info->first_buf;
+ struct sk_buff *skb = first_buf->skb;
if (skb == NULL) {
DP(NETIF_MSG_IFDOWN, "tpa bin %d empty on free\n", i);
continue;
}
-
- if (fp->tpa_state[i] == BNX2X_TPA_START)
+ if (tpa_info->tpa_state == BNX2X_TPA_START)
dma_unmap_single(&bp->pdev->dev,
- dma_unmap_addr(rx_buf, mapping),
+ dma_unmap_addr(first_buf, mapping),
fp->rx_buf_size, DMA_FROM_DEVICE);
-
dev_kfree_skb(skb);
- rx_buf->skb = NULL;
+ first_buf->skb = NULL;
}
}
@@ -1038,31 +1148,201 @@
return i - fp->eth_q_stats.rx_skb_alloc_failed;
}
+/* Statistics ID are global per chip/path, while Client IDs for E1x are per
+ * port.
+ */
+static inline u8 bnx2x_stats_id(struct bnx2x_fastpath *fp)
+{
+ if (!CHIP_IS_E1x(fp->bp))
+ return fp->cl_id;
+ else
+ return fp->cl_id + BP_PORT(fp->bp) * FP_SB_MAX_E1x;
+}
+
+static inline void bnx2x_init_vlan_mac_fp_objs(struct bnx2x_fastpath *fp,
+ bnx2x_obj_type obj_type)
+{
+ struct bnx2x *bp = fp->bp;
+
+ /* Configure classification DBs */
+ bnx2x_init_mac_obj(bp, &fp->mac_obj, fp->cl_id, fp->cid,
+ BP_FUNC(bp), bnx2x_sp(bp, mac_rdata),
+ bnx2x_sp_mapping(bp, mac_rdata),
+ BNX2X_FILTER_MAC_PENDING,
+ &bp->sp_state, obj_type,
+ &bp->macs_pool);
+}
+
+/**
+ * bnx2x_get_path_func_num - get number of active functions
+ *
+ * @bp: driver handle
+ *
+ * Calculates the number of active (not hidden) functions on the
+ * current path.
+ */
+static inline u8 bnx2x_get_path_func_num(struct bnx2x *bp)
+{
+ u8 func_num = 0, i;
+
+ /* 57710 has only one function per-port */
+ if (CHIP_IS_E1(bp))
+ return 1;
+
+ /* Calculate a number of functions enabled on the current
+ * PATH/PORT.
+ */
+ if (CHIP_REV_IS_SLOW(bp)) {
+ if (IS_MF(bp))
+ func_num = 4;
+ else
+ func_num = 2;
+ } else {
+ for (i = 0; i < E1H_FUNC_MAX / 2; i++) {
+ u32 func_config =
+ MF_CFG_RD(bp,
+ func_mf_config[BP_PORT(bp) + 2 * i].
+ config);
+ func_num +=
+ ((func_config & FUNC_MF_CFG_FUNC_HIDE) ? 0 : 1);
+ }
+ }
+
+ WARN_ON(!func_num);
+
+ return func_num;
+}
+
+static inline void bnx2x_init_bp_objs(struct bnx2x *bp)
+{
+ /* RX_MODE controlling object */
+ bnx2x_init_rx_mode_obj(bp, &bp->rx_mode_obj);
+
+ /* multicast configuration controlling object */
+ bnx2x_init_mcast_obj(bp, &bp->mcast_obj, bp->fp->cl_id, bp->fp->cid,
+ BP_FUNC(bp), BP_FUNC(bp),
+ bnx2x_sp(bp, mcast_rdata),
+ bnx2x_sp_mapping(bp, mcast_rdata),
+ BNX2X_FILTER_MCAST_PENDING, &bp->sp_state,
+ BNX2X_OBJ_TYPE_RX);
+
+ /* Setup CAM credit pools */
+ bnx2x_init_mac_credit_pool(bp, &bp->macs_pool, BP_FUNC(bp),
+ bnx2x_get_path_func_num(bp));
+
+ /* RSS configuration object */
+ bnx2x_init_rss_config_obj(bp, &bp->rss_conf_obj, bp->fp->cl_id,
+ bp->fp->cid, BP_FUNC(bp), BP_FUNC(bp),
+ bnx2x_sp(bp, rss_rdata),
+ bnx2x_sp_mapping(bp, rss_rdata),
+ BNX2X_FILTER_RSS_CONF_PENDING, &bp->sp_state,
+ BNX2X_OBJ_TYPE_RX);
+}
+
+static inline u8 bnx2x_fp_qzone_id(struct bnx2x_fastpath *fp)
+{
+ if (CHIP_IS_E1x(fp->bp))
+ return fp->cl_id + BP_PORT(fp->bp) * ETH_MAX_RX_CLIENTS_E1H;
+ else
+ return fp->cl_id;
+}
+
+static inline u32 bnx2x_rx_ustorm_prods_offset(struct bnx2x_fastpath *fp)
+{
+ struct bnx2x *bp = fp->bp;
+
+ if (!CHIP_IS_E1x(bp))
+ return USTORM_RX_PRODS_E2_OFFSET(fp->cl_qzone_id);
+ else
+ return USTORM_RX_PRODS_E1X_OFFSET(BP_PORT(bp), fp->cl_id);
+}
+
+
#ifdef BCM_CNIC
+static inline u8 bnx2x_cnic_eth_cl_id(struct bnx2x *bp, u8 cl_idx)
+{
+ return bp->cnic_base_cl_id + cl_idx +
+ (bp->pf_num >> 1) * NONE_ETH_CONTEXT_USE;
+}
+
+static inline u8 bnx2x_cnic_fw_sb_id(struct bnx2x *bp)
+{
+
+ /* the 'first' id is allocated for the cnic */
+ return bp->base_fw_ndsb;
+}
+
+static inline u8 bnx2x_cnic_igu_sb_id(struct bnx2x *bp)
+{
+ return bp->igu_base_sb;
+}
+
+
static inline void bnx2x_init_fcoe_fp(struct bnx2x *bp)
{
- bnx2x_fcoe(bp, cl_id) = BNX2X_FCOE_ETH_CL_ID +
- BP_E1HVN(bp) * NONE_ETH_CONTEXT_USE;
+ struct bnx2x_fastpath *fp = bnx2x_fcoe_fp(bp);
+ unsigned long q_type = 0;
+
+ bnx2x_fcoe(bp, cl_id) = bnx2x_cnic_eth_cl_id(bp,
+ BNX2X_FCOE_ETH_CL_ID_IDX);
+ /** Current BNX2X_FCOE_ETH_CID deffinition implies not more than
+ * 16 ETH clients per function when CNIC is enabled!
+ *
+ * Fix it ASAP!!!
+ */
bnx2x_fcoe(bp, cid) = BNX2X_FCOE_ETH_CID;
bnx2x_fcoe(bp, fw_sb_id) = DEF_SB_ID;
bnx2x_fcoe(bp, igu_sb_id) = bp->igu_dsb_id;
bnx2x_fcoe(bp, bp) = bp;
- bnx2x_fcoe(bp, state) = BNX2X_FP_STATE_CLOSED;
bnx2x_fcoe(bp, index) = FCOE_IDX;
bnx2x_fcoe(bp, rx_cons_sb) = BNX2X_FCOE_L2_RX_INDEX;
bnx2x_fcoe(bp, tx_cons_sb) = BNX2X_FCOE_L2_TX_INDEX;
/* qZone id equals to FW (per path) client id */
- bnx2x_fcoe(bp, cl_qzone_id) = bnx2x_fcoe(bp, cl_id) +
- BP_PORT(bp)*(CHIP_IS_E2(bp) ? ETH_MAX_RX_CLIENTS_E2 :
- ETH_MAX_RX_CLIENTS_E1H);
+ bnx2x_fcoe(bp, cl_qzone_id) = bnx2x_fp_qzone_id(fp);
/* init shortcut */
- bnx2x_fcoe(bp, ustorm_rx_prods_offset) = CHIP_IS_E2(bp) ?
- USTORM_RX_PRODS_E2_OFFSET(bnx2x_fcoe(bp, cl_qzone_id)) :
- USTORM_RX_PRODS_E1X_OFFSET(BP_PORT(bp), bnx2x_fcoe_fp(bp)->cl_id);
+ bnx2x_fcoe(bp, ustorm_rx_prods_offset) =
+ bnx2x_rx_ustorm_prods_offset(fp);
+ /* Configure Queue State object */
+ __set_bit(BNX2X_Q_TYPE_HAS_RX, &q_type);
+ __set_bit(BNX2X_Q_TYPE_HAS_TX, &q_type);
+ bnx2x_init_queue_obj(bp, &fp->q_obj, fp->cl_id, fp->cid, BP_FUNC(bp),
+ bnx2x_sp(bp, q_rdata), bnx2x_sp_mapping(bp, q_rdata),
+ q_type);
+
+ DP(NETIF_MSG_IFUP, "queue[%d]: bnx2x_init_sb(%p,%p) cl_id %d fw_sb %d "
+ "igu_sb %d\n",
+ fp->index, bp, fp->status_blk.e2_sb, fp->cl_id, fp->fw_sb_id,
+ fp->igu_sb_id);
}
#endif
+static inline int bnx2x_clean_tx_queue(struct bnx2x *bp,
+ struct bnx2x_fastpath *fp)
+{
+ int cnt = 1000;
+
+ while (bnx2x_has_tx_work_unload(fp)) {
+ if (!cnt) {
+ BNX2X_ERR("timeout waiting for queue[%d]: "
+ "fp->tx_pkt_prod(%d) != fp->tx_pkt_cons(%d)\n",
+ fp->index, fp->tx_pkt_prod, fp->tx_pkt_cons);
+#ifdef BNX2X_STOP_ON_ERROR
+ bnx2x_panic();
+ return -EBUSY;
+#else
+ break;
+#endif
+ }
+ cnt--;
+ usleep_range(1000, 1000);
+ }
+
+ return 0;
+}
+
+int bnx2x_get_link_cfg_idx(struct bnx2x *bp);
+
static inline void __storm_memset_struct(struct bnx2x *bp,
u32 addr, size_t size, u32 *data)
{
@@ -1071,42 +1351,78 @@
REG_WR(bp, addr + (i * 4), data[i]);
}
-static inline void storm_memset_mac_filters(struct bnx2x *bp,
- struct tstorm_eth_mac_filter_config *mac_filters,
- u16 abs_fid)
+static inline void storm_memset_func_cfg(struct bnx2x *bp,
+ struct tstorm_eth_function_common_config *tcfg,
+ u16 abs_fid)
{
- size_t size = sizeof(struct tstorm_eth_mac_filter_config);
+ size_t size = sizeof(struct tstorm_eth_function_common_config);
u32 addr = BAR_TSTRORM_INTMEM +
- TSTORM_MAC_FILTER_CONFIG_OFFSET(abs_fid);
+ TSTORM_FUNCTION_COMMON_CONFIG_OFFSET(abs_fid);
- __storm_memset_struct(bp, addr, size, (u32 *)mac_filters);
+ __storm_memset_struct(bp, addr, size, (u32 *)tcfg);
}
static inline void storm_memset_cmng(struct bnx2x *bp,
struct cmng_struct_per_port *cmng,
u8 port)
{
- size_t size =
- sizeof(struct rate_shaping_vars_per_port) +
- sizeof(struct fairness_vars_per_port) +
- sizeof(struct safc_struct_per_port) +
- sizeof(struct pfc_struct_per_port);
+ size_t size = sizeof(struct cmng_struct_per_port);
u32 addr = BAR_XSTRORM_INTMEM +
XSTORM_CMNG_PER_PORT_VARS_OFFSET(port);
__storm_memset_struct(bp, addr, size, (u32 *)cmng);
-
- addr += size + 4 /* SKIP DCB+LLFC */;
- size = sizeof(struct cmng_struct_per_port) -
- size /* written */ - 4 /*skipped*/;
-
- __storm_memset_struct(bp, addr, size,
- (u32 *)(cmng->traffic_type_to_priority_cos));
}
-/* HW Lock for shared dual port PHYs */
+/**
+ * bnx2x_wait_sp_comp - wait for the outstanding SP commands.
+ *
+ * @bp: driver handle
+ * @mask: bits that need to be cleared
+ */
+static inline bool bnx2x_wait_sp_comp(struct bnx2x *bp, unsigned long mask)
+{
+ int tout = 5000; /* Wait for 5 secs tops */
+
+ while (tout--) {
+ smp_mb();
+ netif_addr_lock_bh(bp->dev);
+ if (!(bp->sp_state & mask)) {
+ netif_addr_unlock_bh(bp->dev);
+ return true;
+ }
+ netif_addr_unlock_bh(bp->dev);
+
+ usleep_range(1000, 1000);
+ }
+
+ smp_mb();
+
+ netif_addr_lock_bh(bp->dev);
+ if (bp->sp_state & mask) {
+ BNX2X_ERR("Filtering completion timed out. sp_state 0x%lx, "
+ "mask 0x%lx\n", bp->sp_state, mask);
+ netif_addr_unlock_bh(bp->dev);
+ return false;
+ }
+ netif_addr_unlock_bh(bp->dev);
+
+ return true;
+}
+
+/**
+ * bnx2x_set_ctx_validation - set CDU context validation values
+ *
+ * @bp: driver handle
+ * @cxt: context of the connection on the host memory
+ * @cid: SW CID of the connection to be configured
+ */
+void bnx2x_set_ctx_validation(struct bnx2x *bp, struct eth_context *cxt,
+ u32 cid);
+
+void bnx2x_update_coalesce_sb_index(struct bnx2x *bp, u8 fw_sb_id,
+ u8 sb_index, u8 disable, u16 usec);
void bnx2x_acquire_phy_lock(struct bnx2x *bp);
void bnx2x_release_phy_lock(struct bnx2x *bp);
diff --git a/drivers/net/bnx2x/bnx2x_dcb.c b/drivers/net/bnx2x/bnx2x_dcb.c
index 410a49e..b51a759 100644
--- a/drivers/net/bnx2x/bnx2x_dcb.c
+++ b/drivers/net/bnx2x/bnx2x_dcb.c
@@ -47,34 +47,39 @@
struct cos_help_data *cos_data,
u32 *pg_pri_orginal_spread,
struct dcbx_ets_feature *ets);
-static void bnx2x_pfc_fw_struct_e2(struct bnx2x *bp);
+static void bnx2x_dcbx_fw_struct(struct bnx2x *bp);
static void bnx2x_pfc_set(struct bnx2x *bp)
{
struct bnx2x_nig_brb_pfc_port_params pfc_params = {0};
u32 pri_bit, val = 0;
- u8 pri;
+ int i;
+
+ pfc_params.num_of_rx_cos_priority_mask =
+ bp->dcbx_port_params.ets.num_of_cos;
/* Tx COS configuration */
- if (bp->dcbx_port_params.ets.cos_params[0].pauseable)
- pfc_params.rx_cos0_priority_mask =
- bp->dcbx_port_params.ets.cos_params[0].pri_bitmask;
- if (bp->dcbx_port_params.ets.cos_params[1].pauseable)
- pfc_params.rx_cos1_priority_mask =
- bp->dcbx_port_params.ets.cos_params[1].pri_bitmask;
+ for (i = 0; i < bp->dcbx_port_params.ets.num_of_cos; i++)
+ /*
+ * We configure only the pauseable bits (non pauseable aren't
+ * configured at all) it's done to avoid false pauses from
+ * network
+ */
+ pfc_params.rx_cos_priority_mask[i] =
+ bp->dcbx_port_params.ets.cos_params[i].pri_bitmask
+ & DCBX_PFC_PRI_PAUSE_MASK(bp);
-
- /**
+ /*
* Rx COS configuration
* Changing PFC RX configuration .
* In RX COS0 will always be configured to lossy and COS1 to lossless
*/
- for (pri = 0 ; pri < MAX_PFC_PRIORITIES ; pri++) {
- pri_bit = 1 << pri;
+ for (i = 0 ; i < MAX_PFC_PRIORITIES ; i++) {
+ pri_bit = 1 << i;
if (pri_bit & DCBX_PFC_PRI_PAUSE_MASK(bp))
- val |= 1 << (pri * 4);
+ val |= 1 << (i * 4);
}
pfc_params.pkt_priority_to_cos = val;
@@ -253,12 +258,11 @@
/* Clean up old settings of ets on COS */
- for (i = 0; i < E2_NUM_OF_COS ; i++) {
-
+ for (i = 0; i < ARRAY_SIZE(bp->dcbx_port_params.ets.cos_params) ; i++) {
cos_params[i].pauseable = false;
- cos_params[i].strict = BNX2X_DCBX_COS_NOT_STRICT;
+ cos_params[i].strict = BNX2X_DCBX_STRICT_INVALID;
cos_params[i].bw_tbl = DCBX_INVALID_COS_BW;
- cos_params[i].pri_bitmask = DCBX_PFC_PRI_GET_NON_PAUSE(bp, 0);
+ cos_params[i].pri_bitmask = 0;
}
if (bp->dcbx_port_params.app.enabled &&
@@ -378,25 +382,19 @@
static void bnx2x_pfc_set_pfc(struct bnx2x *bp)
{
- if (CHIP_IS_E2(bp)) {
- if (BP_PORT(bp)) {
- BNX2X_ERR("4 port mode is not supported");
- return;
- }
-
- if (bp->dcbx_port_params.pfc.enabled)
-
- /* 1. Fills up common PFC structures if required.*/
- /* 2. Configure NIG, MAC and BRB via the elink:
- * elink must first check if BMAC is not in reset
- * and only then configures the BMAC
- * Or, configure EMAC.
- */
- bnx2x_pfc_set(bp);
-
- else
- bnx2x_pfc_clear(bp);
+ if (BP_PORT(bp)) {
+ BNX2X_ERR("4 port mode is not supported");
+ return;
}
+
+ if (bp->dcbx_port_params.pfc.enabled)
+ /*
+ * 1. Fills up common PFC structures if required
+ * 2. Configure NIG, MAC and BRB via the elink
+ */
+ bnx2x_pfc_set(bp);
+ else
+ bnx2x_pfc_clear(bp);
}
static void bnx2x_dcbx_stop_hw_tx(struct bnx2x *bp)
@@ -406,32 +404,27 @@
0 /* connectionless */,
0 /* dataHi is zero */,
0 /* dataLo is zero */,
- 1 /* common */);
+ NONE_CONNECTION_TYPE);
}
static void bnx2x_dcbx_resume_hw_tx(struct bnx2x *bp)
{
- bnx2x_pfc_fw_struct_e2(bp);
+ bnx2x_dcbx_fw_struct(bp);
DP(NETIF_MSG_LINK, "sending START TRAFFIC\n");
bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_START_TRAFFIC,
0, /* connectionless */
U64_HI(bnx2x_sp_mapping(bp, pfc_config)),
U64_LO(bnx2x_sp_mapping(bp, pfc_config)),
- 1 /* commmon */);
+ NONE_CONNECTION_TYPE);
}
-static void bnx2x_dcbx_update_ets_params(struct bnx2x *bp)
+static void bnx2x_dcbx_2cos_limit_update_ets_config(struct bnx2x *bp)
{
struct bnx2x_dcbx_pg_params *ets = &(bp->dcbx_port_params.ets);
- u8 status = 0;
+ int rc = 0;
- bnx2x_ets_disabled(&bp->link_params);
-
- if (!ets->enabled)
- return;
-
- if ((ets->num_of_cos == 0) || (ets->num_of_cos > E2_NUM_OF_COS)) {
- BNX2X_ERR("illegal num of cos= %x", ets->num_of_cos);
+ if (ets->num_of_cos == 0 || ets->num_of_cos > DCBX_COS_MAX_NUM_E2) {
+ BNX2X_ERR("Illegal number of COSes %d\n", ets->num_of_cos);
return;
}
@@ -440,9 +433,9 @@
return;
/* sanity */
- if (((BNX2X_DCBX_COS_NOT_STRICT == ets->cos_params[0].strict) &&
+ if (((BNX2X_DCBX_STRICT_INVALID == ets->cos_params[0].strict) &&
(DCBX_INVALID_COS_BW == ets->cos_params[0].bw_tbl)) ||
- ((BNX2X_DCBX_COS_NOT_STRICT == ets->cos_params[1].strict) &&
+ ((BNX2X_DCBX_STRICT_INVALID == ets->cos_params[1].strict) &&
(DCBX_INVALID_COS_BW == ets->cos_params[1].bw_tbl))) {
BNX2X_ERR("all COS should have at least bw_limit or strict"
"ets->cos_params[0].strict= %x"
@@ -474,17 +467,70 @@
bnx2x_ets_bw_limit(&bp->link_params, bw_tbl_0, bw_tbl_1);
} else {
- if (ets->cos_params[0].strict == BNX2X_DCBX_COS_HIGH_STRICT)
- status = bnx2x_ets_strict(&bp->link_params, 0);
+ if (ets->cos_params[0].strict == BNX2X_DCBX_STRICT_COS_HIGHEST)
+ rc = bnx2x_ets_strict(&bp->link_params, 0);
else if (ets->cos_params[1].strict
- == BNX2X_DCBX_COS_HIGH_STRICT)
- status = bnx2x_ets_strict(&bp->link_params, 1);
-
- if (status)
+ == BNX2X_DCBX_STRICT_COS_HIGHEST)
+ rc = bnx2x_ets_strict(&bp->link_params, 1);
+ if (rc)
BNX2X_ERR("update_ets_params failed\n");
}
}
+/*
+ * In E3B0 the configuration may have more than 2 COS.
+ */
+void bnx2x_dcbx_update_ets_config(struct bnx2x *bp)
+{
+ struct bnx2x_dcbx_pg_params *ets = &(bp->dcbx_port_params.ets);
+ struct bnx2x_ets_params ets_params = { 0 };
+ u8 i;
+
+ ets_params.num_of_cos = ets->num_of_cos;
+
+ for (i = 0; i < ets->num_of_cos; i++) {
+ /* COS is SP */
+ if (ets->cos_params[i].strict != BNX2X_DCBX_STRICT_INVALID) {
+ if (ets->cos_params[i].bw_tbl != DCBX_INVALID_COS_BW) {
+ BNX2X_ERR("COS can't be not BW and not SP\n");
+ return;
+ }
+
+ ets_params.cos[i].state = bnx2x_cos_state_strict;
+ ets_params.cos[i].params.sp_params.pri =
+ ets->cos_params[i].strict;
+ } else { /* COS is BW */
+ if (ets->cos_params[i].bw_tbl == DCBX_INVALID_COS_BW) {
+ BNX2X_ERR("COS can't be not BW and not SP\n");
+ return;
+ }
+ ets_params.cos[i].state = bnx2x_cos_state_bw;
+ ets_params.cos[i].params.bw_params.bw =
+ (u8)ets->cos_params[i].bw_tbl;
+ }
+ }
+
+ /* Configure the ETS in HW */
+ if (bnx2x_ets_e3b0_config(&bp->link_params, &bp->link_vars,
+ &ets_params)) {
+ BNX2X_ERR("bnx2x_ets_e3b0_config failed\n");
+ bnx2x_ets_disabled(&bp->link_params, &bp->link_vars);
+ }
+}
+
+static void bnx2x_dcbx_update_ets_params(struct bnx2x *bp)
+{
+ bnx2x_ets_disabled(&bp->link_params, &bp->link_vars);
+
+ if (!bp->dcbx_port_params.ets.enabled)
+ return;
+
+ if (CHIP_IS_E3B0(bp))
+ bnx2x_dcbx_update_ets_config(bp);
+ else
+ bnx2x_dcbx_2cos_limit_update_ets_config(bp);
+}
+
#ifdef BCM_DCBNL
static int bnx2x_dcbx_read_shmem_remote_mib(struct bnx2x *bp)
{
@@ -527,6 +573,7 @@
BNX2X_ERR("FW doesn't support dcbx_neg_res_offset\n");
return -EINVAL;
}
+
rc = bnx2x_dcbx_read_mib(bp, (u32 *)&local_mib, dcbx_neg_res_offset,
DCBX_READ_LOCAL_MIB);
@@ -563,15 +610,6 @@
DCB_APP_IDTYPE_ETHTYPE;
}
-static inline
-void bnx2x_dcbx_invalidate_local_apps(struct bnx2x *bp)
-{
- int i;
- for (i = 0; i < DCBX_MAX_APP_PROTOCOL; i++)
- bp->dcbx_local_feat.app.app_pri_tbl[i].appBitfield &=
- ~DCBX_APP_ENTRY_VALID;
-}
-
int bnx2x_dcbnl_update_applist(struct bnx2x *bp, bool delall)
{
int i, err = 0;
@@ -597,32 +635,28 @@
}
#endif
+static inline void bnx2x_update_drv_flags(struct bnx2x *bp, u32 flags, u32 set)
+{
+ if (SHMEM2_HAS(bp, drv_flags)) {
+ u32 drv_flags;
+ bnx2x_acquire_hw_lock(bp, HW_LOCK_DRV_FLAGS);
+ drv_flags = SHMEM2_RD(bp, drv_flags);
+
+ if (set)
+ SET_FLAGS(drv_flags, flags);
+ else
+ RESET_FLAGS(drv_flags, flags);
+
+ SHMEM2_WR(bp, drv_flags, drv_flags);
+ DP(NETIF_MSG_HW, "drv_flags 0x%08x\n", drv_flags);
+ bnx2x_release_hw_lock(bp, HW_LOCK_DRV_FLAGS);
+ }
+}
+
void bnx2x_dcbx_set_params(struct bnx2x *bp, u32 state)
{
switch (state) {
case BNX2X_DCBX_STATE_NEG_RECEIVED:
-#ifdef BCM_CNIC
- if (bp->state != BNX2X_STATE_OPENING_WAIT4_LOAD) {
- struct cnic_ops *c_ops;
- struct cnic_eth_dev *cp = &bp->cnic_eth_dev;
- bp->flags |= NO_ISCSI_OOO_FLAG | NO_ISCSI_FLAG;
- cp->drv_state |= CNIC_DRV_STATE_NO_ISCSI_OOO;
- cp->drv_state |= CNIC_DRV_STATE_NO_ISCSI;
-
- rcu_read_lock();
- c_ops = rcu_dereference(bp->cnic_ops);
- if (c_ops) {
- bnx2x_cnic_notify(bp, CNIC_CTL_STOP_ISCSI_CMD);
- rcu_read_unlock();
- return;
- }
- rcu_read_unlock();
- }
-
- /* fall through if no CNIC initialized */
- case BNX2X_DCBX_STATE_ISCSI_STOPPED:
-#endif
-
{
DP(NETIF_MSG_LINK, "BNX2X_DCBX_STATE_NEG_RECEIVED\n");
#ifdef BCM_DCBNL
@@ -646,41 +680,28 @@
bnx2x_get_dcbx_drv_param(bp, &bp->dcbx_local_feat,
bp->dcbx_error);
- if (bp->state != BNX2X_STATE_OPENING_WAIT4_LOAD) {
-#ifdef BCM_DCBNL
- /**
- * Add new app tlvs to dcbnl
- */
- bnx2x_dcbnl_update_applist(bp, false);
-#endif
- bnx2x_dcbx_stop_hw_tx(bp);
- return;
- }
- /* fall through */
+ /* mark DCBX result for PMF migration */
+ bnx2x_update_drv_flags(bp, DRV_FLAGS_DCB_CONFIGURED, 1);
#ifdef BCM_DCBNL
/**
- * Invalidate the local app tlvs if they are not added
- * to the dcbnl app list to avoid deleting them from
- * the list later on
+ * Add new app tlvs to dcbnl
*/
- bnx2x_dcbx_invalidate_local_apps(bp);
+ bnx2x_dcbnl_update_applist(bp, false);
#endif
+ bnx2x_dcbx_stop_hw_tx(bp);
+
+ return;
}
case BNX2X_DCBX_STATE_TX_PAUSED:
DP(NETIF_MSG_LINK, "BNX2X_DCBX_STATE_TX_PAUSED\n");
bnx2x_pfc_set_pfc(bp);
bnx2x_dcbx_update_ets_params(bp);
- if (bp->state != BNX2X_STATE_OPENING_WAIT4_LOAD) {
- bnx2x_dcbx_resume_hw_tx(bp);
- return;
- }
- /* fall through */
+ bnx2x_dcbx_resume_hw_tx(bp);
+ return;
case BNX2X_DCBX_STATE_TX_RELEASED:
DP(NETIF_MSG_LINK, "BNX2X_DCBX_STATE_TX_RELEASED\n");
- if (bp->state != BNX2X_STATE_OPENING_WAIT4_LOAD)
- bnx2x_fw_command(bp, DRV_MSG_CODE_DCBX_PMF_DRV_OK, 0);
-
+ bnx2x_fw_command(bp, DRV_MSG_CODE_DCBX_PMF_DRV_OK, 0);
return;
default:
BNX2X_ERR("Unknown DCBX_STATE\n");
@@ -868,7 +889,7 @@
void bnx2x_dcbx_set_state(struct bnx2x *bp, bool dcb_on, u32 dcbx_enabled)
{
- if (CHIP_IS_E2(bp) && !CHIP_MODE_IS_4_PORT(bp)) {
+ if (!CHIP_IS_E1x(bp) && !CHIP_MODE_IS_4_PORT(bp)) {
bp->dcb_state = dcb_on;
bp->dcbx_enabled = dcbx_enabled;
} else {
@@ -966,7 +987,7 @@
DP(NETIF_MSG_LINK, "dcb_state %d bp->port.pmf %d\n",
bp->dcb_state, bp->port.pmf);
- if (bp->dcb_state == BNX2X_DCB_STATE_ON && bp->port.pmf &&
+ if (bp->dcb_state == BNX2X_DCB_STATE_ON && bp->port.pmf &&
SHMEM2_HAS(bp, dcbx_lldp_params_offset)) {
dcbx_lldp_params_offset =
SHMEM2_RD(bp, dcbx_lldp_params_offset);
@@ -974,6 +995,8 @@
DP(NETIF_MSG_LINK, "dcbx_lldp_params_offset 0x%x\n",
dcbx_lldp_params_offset);
+ bnx2x_update_drv_flags(bp, DRV_FLAGS_DCB_CONFIGURED, 0);
+
if (SHMEM_LLDP_DCBX_PARAMS_NONE != dcbx_lldp_params_offset) {
bnx2x_dcbx_lldp_updated_params(bp,
dcbx_lldp_params_offset);
@@ -981,46 +1004,12 @@
bnx2x_dcbx_admin_mib_updated_params(bp,
dcbx_lldp_params_offset);
- /* set default configuration BC has */
- bnx2x_dcbx_set_params(bp,
- BNX2X_DCBX_STATE_NEG_RECEIVED);
-
+ /* Let HW start negotiation */
bnx2x_fw_command(bp,
DRV_MSG_CODE_DCBX_ADMIN_PMF_MSG, 0);
}
}
}
-
-void bnx2x_dcb_init_intmem_pfc(struct bnx2x *bp)
-{
- struct priority_cos pricos[MAX_PFC_TRAFFIC_TYPES];
- u32 i = 0, addr;
- memset(pricos, 0, sizeof(pricos));
- /* Default initialization */
- for (i = 0; i < MAX_PFC_TRAFFIC_TYPES; i++)
- pricos[i].priority = LLFC_TRAFFIC_TYPE_TO_PRIORITY_UNMAPPED;
-
- /* Store per port struct to internal memory */
- addr = BAR_XSTRORM_INTMEM +
- XSTORM_CMNG_PER_PORT_VARS_OFFSET(BP_PORT(bp)) +
- offsetof(struct cmng_struct_per_port,
- traffic_type_to_priority_cos);
- __storm_memset_struct(bp, addr, sizeof(pricos), (u32 *)pricos);
-
-
- /* LLFC disabled.*/
- REG_WR8(bp , BAR_XSTRORM_INTMEM +
- XSTORM_CMNG_PER_PORT_VARS_OFFSET(BP_PORT(bp)) +
- offsetof(struct cmng_struct_per_port, llfc_mode),
- LLFC_MODE_NONE);
-
- /* DCBX disabled.*/
- REG_WR8(bp , BAR_XSTRORM_INTMEM +
- XSTORM_CMNG_PER_PORT_VARS_OFFSET(BP_PORT(bp)) +
- offsetof(struct cmng_struct_per_port, dcb_enabled),
- DCB_DISABLED);
-}
-
static void
bnx2x_dcbx_print_cos_params(struct bnx2x *bp,
struct flow_control_configuration *pfc_fw_cfg)
@@ -1171,7 +1160,7 @@
/* If we join a group and one is strict
* than the bw rulls */
cos_data->data[entry].strict =
- BNX2X_DCBX_COS_HIGH_STRICT;
+ BNX2X_DCBX_STRICT_COS_HIGHEST;
}
if ((0 == cos_data->data[0].pri_join_mask) &&
(0 == cos_data->data[1].pri_join_mask))
@@ -1183,7 +1172,7 @@
#define POWER_OF_2(x) ((0 != x) && (0 == (x & (x-1))))
#endif
-static void bxn2x_dcbx_single_pg_to_cos_params(struct bnx2x *bp,
+static void bnx2x_dcbx_2cos_limit_cee_single_pg_to_cos_params(struct bnx2x *bp,
struct pg_help_data *pg_help_data,
struct cos_help_data *cos_data,
u32 pri_join_mask,
@@ -1263,14 +1252,16 @@
if (DCBX_PFC_PRI_GET_PAUSE(bp, pri_join_mask) >
DCBX_PFC_PRI_GET_NON_PAUSE(bp, pri_join_mask)) {
cos_data->data[0].strict =
- BNX2X_DCBX_COS_HIGH_STRICT;
+ BNX2X_DCBX_STRICT_COS_HIGHEST;
cos_data->data[1].strict =
- BNX2X_DCBX_COS_LOW_STRICT;
+ BNX2X_DCBX_STRICT_COS_NEXT_LOWER_PRI(
+ BNX2X_DCBX_STRICT_COS_HIGHEST);
} else {
cos_data->data[0].strict =
- BNX2X_DCBX_COS_LOW_STRICT;
+ BNX2X_DCBX_STRICT_COS_NEXT_LOWER_PRI(
+ BNX2X_DCBX_STRICT_COS_HIGHEST);
cos_data->data[1].strict =
- BNX2X_DCBX_COS_HIGH_STRICT;
+ BNX2X_DCBX_STRICT_COS_HIGHEST;
}
/* Pauseable */
cos_data->data[0].pausable = true;
@@ -1306,13 +1297,16 @@
* and that with the highest priority
* gets the highest strict priority in the arbiter.
*/
- cos_data->data[0].strict = BNX2X_DCBX_COS_LOW_STRICT;
- cos_data->data[1].strict = BNX2X_DCBX_COS_HIGH_STRICT;
+ cos_data->data[0].strict =
+ BNX2X_DCBX_STRICT_COS_NEXT_LOWER_PRI(
+ BNX2X_DCBX_STRICT_COS_HIGHEST);
+ cos_data->data[1].strict =
+ BNX2X_DCBX_STRICT_COS_HIGHEST;
}
}
}
-static void bnx2x_dcbx_two_pg_to_cos_params(
+static void bnx2x_dcbx_2cos_limit_cee_two_pg_to_cos_params(
struct bnx2x *bp,
struct pg_help_data *pg_help_data,
struct dcbx_ets_feature *ets,
@@ -1322,7 +1316,7 @@
u8 num_of_dif_pri)
{
u8 i = 0;
- u8 pg[E2_NUM_OF_COS] = {0};
+ u8 pg[DCBX_COS_MAX_NUM_E2] = { 0 };
/* If there are both pauseable and non-pauseable priorities,
* the pauseable priorities go to the first queue and
@@ -1378,16 +1372,68 @@
}
/* There can be only one strict pg */
- for (i = 0 ; i < E2_NUM_OF_COS; i++) {
+ for (i = 0 ; i < ARRAY_SIZE(pg); i++) {
if (pg[i] < DCBX_MAX_NUM_PG_BW_ENTRIES)
cos_data->data[i].cos_bw =
DCBX_PG_BW_GET(ets->pg_bw_tbl, pg[i]);
else
- cos_data->data[i].strict = BNX2X_DCBX_COS_HIGH_STRICT;
+ cos_data->data[i].strict =
+ BNX2X_DCBX_STRICT_COS_HIGHEST;
}
}
-static void bnx2x_dcbx_three_pg_to_cos_params(
+static int bnx2x_dcbx_join_pgs(
+ struct bnx2x *bp,
+ struct dcbx_ets_feature *ets,
+ struct pg_help_data *pg_help_data,
+ u8 required_num_of_pg)
+{
+ u8 entry_joined = pg_help_data->num_of_pg - 1;
+ u8 entry_removed = entry_joined + 1;
+ u8 pg_joined = 0;
+
+ if (required_num_of_pg == 0 || ARRAY_SIZE(pg_help_data->data)
+ <= pg_help_data->num_of_pg) {
+
+ BNX2X_ERR("required_num_of_pg can't be zero\n");
+ return -EINVAL;
+ }
+
+ while (required_num_of_pg < pg_help_data->num_of_pg) {
+ entry_joined = pg_help_data->num_of_pg - 2;
+ entry_removed = entry_joined + 1;
+ /* protect index */
+ entry_removed %= ARRAY_SIZE(pg_help_data->data);
+
+ pg_help_data->data[entry_joined].pg_priority |=
+ pg_help_data->data[entry_removed].pg_priority;
+
+ pg_help_data->data[entry_joined].num_of_dif_pri +=
+ pg_help_data->data[entry_removed].num_of_dif_pri;
+
+ if (pg_help_data->data[entry_joined].pg == DCBX_STRICT_PRI_PG ||
+ pg_help_data->data[entry_removed].pg == DCBX_STRICT_PRI_PG)
+ /* Entries joined strict priority rules */
+ pg_help_data->data[entry_joined].pg =
+ DCBX_STRICT_PRI_PG;
+ else {
+ /* Entries can be joined join BW */
+ pg_joined = DCBX_PG_BW_GET(ets->pg_bw_tbl,
+ pg_help_data->data[entry_joined].pg) +
+ DCBX_PG_BW_GET(ets->pg_bw_tbl,
+ pg_help_data->data[entry_removed].pg);
+
+ DCBX_PG_BW_SET(ets->pg_bw_tbl,
+ pg_help_data->data[entry_joined].pg, pg_joined);
+ }
+ /* Joined the entries */
+ pg_help_data->num_of_pg--;
+ }
+
+ return 0;
+}
+
+static void bnx2x_dcbx_2cos_limit_cee_three_pg_to_cos_params(
struct bnx2x *bp,
struct pg_help_data *pg_help_data,
struct dcbx_ets_feature *ets,
@@ -1459,24 +1505,203 @@
/* If we join a group and one is strict
* than the bw rulls */
cos_data->data[1].strict =
- BNX2X_DCBX_COS_HIGH_STRICT;
+ BNX2X_DCBX_STRICT_COS_HIGHEST;
}
}
}
}
+static void bnx2x_dcbx_2cos_limit_cee_fill_cos_params(struct bnx2x *bp,
+ struct pg_help_data *help_data,
+ struct dcbx_ets_feature *ets,
+ struct cos_help_data *cos_data,
+ u32 *pg_pri_orginal_spread,
+ u32 pri_join_mask,
+ u8 num_of_dif_pri)
+{
+
+ /* default E2 settings */
+ cos_data->num_of_cos = DCBX_COS_MAX_NUM_E2;
+
+ switch (help_data->num_of_pg) {
+ case 1:
+ bnx2x_dcbx_2cos_limit_cee_single_pg_to_cos_params(
+ bp,
+ help_data,
+ cos_data,
+ pri_join_mask,
+ num_of_dif_pri);
+ break;
+ case 2:
+ bnx2x_dcbx_2cos_limit_cee_two_pg_to_cos_params(
+ bp,
+ help_data,
+ ets,
+ cos_data,
+ pg_pri_orginal_spread,
+ pri_join_mask,
+ num_of_dif_pri);
+ break;
+
+ case 3:
+ bnx2x_dcbx_2cos_limit_cee_three_pg_to_cos_params(
+ bp,
+ help_data,
+ ets,
+ cos_data,
+ pg_pri_orginal_spread,
+ pri_join_mask,
+ num_of_dif_pri);
+ break;
+ default:
+ BNX2X_ERR("Wrong pg_help_data.num_of_pg\n");
+ bnx2x_dcbx_ets_disabled_entry_data(bp,
+ cos_data, pri_join_mask);
+ }
+}
+
+static int bnx2x_dcbx_spread_strict_pri(struct bnx2x *bp,
+ struct cos_help_data *cos_data,
+ u8 entry,
+ u8 num_spread_of_entries,
+ u8 strict_app_pris)
+{
+ u8 strict_pri = BNX2X_DCBX_STRICT_COS_HIGHEST;
+ u8 num_of_app_pri = MAX_PFC_PRIORITIES;
+ u8 app_pri_bit = 0;
+
+ while (num_spread_of_entries && num_of_app_pri > 0) {
+ app_pri_bit = 1 << (num_of_app_pri - 1);
+ if (app_pri_bit & strict_app_pris) {
+ struct cos_entry_help_data *data = &cos_data->
+ data[entry];
+ num_spread_of_entries--;
+ if (num_spread_of_entries == 0) {
+ /* last entry needed put all the entries left */
+ data->cos_bw = DCBX_INVALID_COS_BW;
+ data->strict = strict_pri;
+ data->pri_join_mask = strict_app_pris;
+ data->pausable = DCBX_IS_PFC_PRI_SOME_PAUSE(bp,
+ data->pri_join_mask);
+ } else {
+ strict_app_pris &= ~app_pri_bit;
+
+ data->cos_bw = DCBX_INVALID_COS_BW;
+ data->strict = strict_pri;
+ data->pri_join_mask = app_pri_bit;
+ data->pausable = DCBX_IS_PFC_PRI_SOME_PAUSE(bp,
+ data->pri_join_mask);
+ }
+
+ strict_pri =
+ BNX2X_DCBX_STRICT_COS_NEXT_LOWER_PRI(strict_pri);
+ entry++;
+ }
+
+ num_of_app_pri--;
+ }
+
+ if (num_spread_of_entries)
+ return -EINVAL;
+
+ return 0;
+}
+
+static u8 bnx2x_dcbx_cee_fill_strict_pri(struct bnx2x *bp,
+ struct cos_help_data *cos_data,
+ u8 entry,
+ u8 num_spread_of_entries,
+ u8 strict_app_pris)
+{
+
+ if (bnx2x_dcbx_spread_strict_pri(bp, cos_data, entry,
+ num_spread_of_entries,
+ strict_app_pris)) {
+ struct cos_entry_help_data *data = &cos_data->
+ data[entry];
+ /* Fill BW entry */
+ data->cos_bw = DCBX_INVALID_COS_BW;
+ data->strict = BNX2X_DCBX_STRICT_COS_HIGHEST;
+ data->pri_join_mask = strict_app_pris;
+ data->pausable = DCBX_IS_PFC_PRI_SOME_PAUSE(bp,
+ data->pri_join_mask);
+ return 1;
+ }
+
+ return num_spread_of_entries;
+}
+
+static void bnx2x_dcbx_cee_fill_cos_params(struct bnx2x *bp,
+ struct pg_help_data *help_data,
+ struct dcbx_ets_feature *ets,
+ struct cos_help_data *cos_data,
+ u32 pri_join_mask)
+
+{
+ u8 need_num_of_entries = 0;
+ u8 i = 0;
+ u8 entry = 0;
+
+ /*
+ * if the number of requested PG-s in CEE is greater than 3
+ * then the results are not determined since this is a violation
+ * of the standard.
+ */
+ if (help_data->num_of_pg > DCBX_COS_MAX_NUM_E3B0) {
+ if (bnx2x_dcbx_join_pgs(bp, ets, help_data,
+ DCBX_COS_MAX_NUM_E3B0)) {
+ BNX2X_ERR("Unable to reduce the number of PGs -"
+ "we will disables ETS\n");
+ bnx2x_dcbx_ets_disabled_entry_data(bp, cos_data,
+ pri_join_mask);
+ return;
+ }
+ }
+
+ for (i = 0 ; i < help_data->num_of_pg; i++) {
+ struct pg_entry_help_data *pg = &help_data->data[i];
+ if (pg->pg < DCBX_MAX_NUM_PG_BW_ENTRIES) {
+ struct cos_entry_help_data *data = &cos_data->
+ data[entry];
+ /* Fill BW entry */
+ data->cos_bw = DCBX_PG_BW_GET(ets->pg_bw_tbl, pg->pg);
+ data->strict = BNX2X_DCBX_STRICT_INVALID;
+ data->pri_join_mask = pg->pg_priority;
+ data->pausable = DCBX_IS_PFC_PRI_SOME_PAUSE(bp,
+ data->pri_join_mask);
+
+ entry++;
+ } else {
+ need_num_of_entries = min_t(u8,
+ (u8)pg->num_of_dif_pri,
+ (u8)DCBX_COS_MAX_NUM_E3B0 -
+ help_data->num_of_pg + 1);
+ /*
+ * If there are still VOQ-s which have no associated PG,
+ * then associate these VOQ-s to PG15. These PG-s will
+ * be used for SP between priorities on PG15.
+ */
+ entry += bnx2x_dcbx_cee_fill_strict_pri(bp, cos_data,
+ entry, need_num_of_entries, pg->pg_priority);
+ }
+ }
+
+ /* the entry will represent the number of COSes used */
+ cos_data->num_of_cos = entry;
+}
static void bnx2x_dcbx_fill_cos_params(struct bnx2x *bp,
struct pg_help_data *help_data,
struct dcbx_ets_feature *ets,
u32 *pg_pri_orginal_spread)
{
- struct cos_help_data cos_data ;
+ struct cos_help_data cos_data;
u8 i = 0;
u32 pri_join_mask = 0;
u8 num_of_dif_pri = 0;
memset(&cos_data, 0, sizeof(cos_data));
+
/* Validate the pg value */
for (i = 0; i < help_data->num_of_pg ; i++) {
if (DCBX_STRICT_PRIORITY != help_data->data[i].pg &&
@@ -1487,74 +1712,65 @@
num_of_dif_pri += help_data->data[i].num_of_dif_pri;
}
- /* default settings */
- cos_data.num_of_cos = 2;
- for (i = 0; i < E2_NUM_OF_COS ; i++) {
- cos_data.data[i].pri_join_mask = pri_join_mask;
- cos_data.data[i].pausable = false;
- cos_data.data[i].strict = BNX2X_DCBX_COS_NOT_STRICT;
- cos_data.data[i].cos_bw = DCBX_INVALID_COS_BW;
+ /* defaults */
+ cos_data.num_of_cos = 1;
+ for (i = 0; i < ARRAY_SIZE(cos_data.data); i++) {
+ cos_data.data[i].pri_join_mask = 0;
+ cos_data.data[i].pausable = false;
+ cos_data.data[i].strict = BNX2X_DCBX_STRICT_INVALID;
+ cos_data.data[i].cos_bw = DCBX_INVALID_COS_BW;
}
- switch (help_data->num_of_pg) {
- case 1:
+ if (CHIP_IS_E3B0(bp))
+ bnx2x_dcbx_cee_fill_cos_params(bp, help_data, ets,
+ &cos_data, pri_join_mask);
+ else /* E2 + E3A0 */
+ bnx2x_dcbx_2cos_limit_cee_fill_cos_params(bp,
+ help_data, ets,
+ &cos_data,
+ pg_pri_orginal_spread,
+ pri_join_mask,
+ num_of_dif_pri);
- bxn2x_dcbx_single_pg_to_cos_params(
- bp,
- help_data,
- &cos_data,
- pri_join_mask,
- num_of_dif_pri);
- break;
- case 2:
- bnx2x_dcbx_two_pg_to_cos_params(
- bp,
- help_data,
- ets,
- &cos_data,
- pg_pri_orginal_spread,
- pri_join_mask,
- num_of_dif_pri);
- break;
-
- case 3:
- bnx2x_dcbx_three_pg_to_cos_params(
- bp,
- help_data,
- ets,
- &cos_data,
- pg_pri_orginal_spread,
- pri_join_mask,
- num_of_dif_pri);
-
- break;
- default:
- BNX2X_ERR("Wrong pg_help_data.num_of_pg\n");
- bnx2x_dcbx_ets_disabled_entry_data(bp,
- &cos_data, pri_join_mask);
- }
for (i = 0; i < cos_data.num_of_cos ; i++) {
- struct bnx2x_dcbx_cos_params *params =
+ struct bnx2x_dcbx_cos_params *p =
&bp->dcbx_port_params.ets.cos_params[i];
- params->pauseable = cos_data.data[i].pausable;
- params->strict = cos_data.data[i].strict;
- params->bw_tbl = cos_data.data[i].cos_bw;
- if (params->pauseable) {
- params->pri_bitmask =
- DCBX_PFC_PRI_GET_PAUSE(bp,
- cos_data.data[i].pri_join_mask);
+ p->strict = cos_data.data[i].strict;
+ p->bw_tbl = cos_data.data[i].cos_bw;
+ p->pri_bitmask = cos_data.data[i].pri_join_mask;
+ p->pauseable = cos_data.data[i].pausable;
+
+ /* sanity */
+ if (p->bw_tbl != DCBX_INVALID_COS_BW ||
+ p->strict != BNX2X_DCBX_STRICT_INVALID) {
+ if (p->pri_bitmask == 0)
+ BNX2X_ERR("Invalid pri_bitmask for %d\n", i);
+
+ if (CHIP_IS_E2(bp) || CHIP_IS_E3A0(bp)) {
+
+ if (p->pauseable &&
+ DCBX_PFC_PRI_GET_NON_PAUSE(bp,
+ p->pri_bitmask) != 0)
+ BNX2X_ERR("Inconsistent config for "
+ "pausable COS %d\n", i);
+
+ if (!p->pauseable &&
+ DCBX_PFC_PRI_GET_PAUSE(bp,
+ p->pri_bitmask) != 0)
+ BNX2X_ERR("Inconsistent config for "
+ "nonpausable COS %d\n", i);
+ }
+ }
+
+ if (p->pauseable)
DP(NETIF_MSG_LINK, "COS %d PAUSABLE prijoinmask 0x%x\n",
i, cos_data.data[i].pri_join_mask);
- } else {
- params->pri_bitmask =
- DCBX_PFC_PRI_GET_NON_PAUSE(bp,
- cos_data.data[i].pri_join_mask);
+ else
DP(NETIF_MSG_LINK, "COS %d NONPAUSABLE prijoinmask "
"0x%x\n",
i, cos_data.data[i].pri_join_mask);
- }
}
bp->dcbx_port_params.ets.num_of_cos = cos_data.num_of_cos ;
@@ -1574,7 +1790,7 @@
}
}
-static void bnx2x_pfc_fw_struct_e2(struct bnx2x *bp)
+static void bnx2x_dcbx_fw_struct(struct bnx2x *bp)
{
struct flow_control_configuration *pfc_fw_cfg = NULL;
u16 pri_bit = 0;
@@ -1591,13 +1807,7 @@
/* Fw version should be incremented each update */
pfc_fw_cfg->dcb_version = ++bp->dcb_version;
- pfc_fw_cfg->dcb_enabled = DCB_ENABLED;
-
- /* Default initialization */
- for (pri = 0; pri < MAX_PFC_TRAFFIC_TYPES ; pri++) {
- tt2cos[pri].priority = LLFC_TRAFFIC_TYPE_TO_PRIORITY_UNMAPPED;
- tt2cos[pri].cos = 0;
- }
+ pfc_fw_cfg->dcb_enabled = 1;
/* Fill priority parameters */
for (pri = 0; pri < LLFC_DRIVER_TRAFFIC_TYPE_MAX; pri++) {
@@ -1605,14 +1815,37 @@
pri_bit = 1 << tt2cos[pri].priority;
/* Fill COS parameters based on COS calculated to
- * make it more generally for future use */
+ * make it more general for future use */
for (cos = 0; cos < bp->dcbx_port_params.ets.num_of_cos; cos++)
if (bp->dcbx_port_params.ets.cos_params[cos].
pri_bitmask & pri_bit)
tt2cos[pri].cos = cos;
}
+
+ /* we never want the FW to add a 0 vlan tag */
+ pfc_fw_cfg->dont_add_pri_0_en = 1;
+
bnx2x_dcbx_print_cos_params(bp, pfc_fw_cfg);
}
+
+void bnx2x_dcbx_pmf_update(struct bnx2x *bp)
+{
+ /* if we need to syncronize DCBX result from prev PMF
+ * read it from shmem and update bp accordingly
+ */
+ if (SHMEM2_HAS(bp, drv_flags) &&
+ GET_FLAGS(SHMEM2_RD(bp, drv_flags), DRV_FLAGS_DCB_CONFIGURED)) {
+ /* Read neg results if dcbx is in the FW */
+ if (bnx2x_dcbx_read_shmem_neg_results(bp))
+ return;
+
+ bnx2x_dump_dcbx_drv_param(bp, &bp->dcbx_local_feat,
+ bp->dcbx_error);
+ bnx2x_get_dcbx_drv_param(bp, &bp->dcbx_local_feat,
+ bp->dcbx_error);
+ }
+}
+
/* DCB netlink */
#ifdef BCM_DCBNL
@@ -1879,10 +2112,12 @@
if (bp->dcb_state) {
switch (tcid) {
case DCB_NUMTCS_ATTR_PG:
- *num = E2_NUM_OF_COS;
+ *num = CHIP_IS_E3B0(bp) ? DCBX_COS_MAX_NUM_E3B0 :
+ DCBX_COS_MAX_NUM_E2;
break;
case DCB_NUMTCS_ATTR_PFC:
- *num = E2_NUM_OF_COS;
+ *num = CHIP_IS_E3B0(bp) ? DCBX_COS_MAX_NUM_E3B0 :
+ DCBX_COS_MAX_NUM_E2;
break;
default:
rval = -EINVAL;
diff --git a/drivers/net/bnx2x/bnx2x_dcb.h b/drivers/net/bnx2x/bnx2x_dcb.h
index bed369d..2c6a3bc 100644
--- a/drivers/net/bnx2x/bnx2x_dcb.h
+++ b/drivers/net/bnx2x/bnx2x_dcb.h
@@ -27,22 +27,30 @@
u32 traffic_type_priority[LLFC_DRIVER_TRAFFIC_TYPE_MAX];
};
-#define E2_NUM_OF_COS 2
-#define BNX2X_DCBX_COS_NOT_STRICT 0
-#define BNX2X_DCBX_COS_LOW_STRICT 1
-#define BNX2X_DCBX_COS_HIGH_STRICT 2
+#define DCBX_COS_MAX_NUM_E2 DCBX_E2E3_MAX_NUM_COS
+/* bnx2x currently limits numbers of supported COSes to 3 to be extended to 6 */
+#define BNX2X_MAX_COS_SUPPORT 3
+#define DCBX_COS_MAX_NUM_E3B0 BNX2X_MAX_COS_SUPPORT
+#define DCBX_COS_MAX_NUM BNX2X_MAX_COS_SUPPORT
struct bnx2x_dcbx_cos_params {
u32 bw_tbl;
u32 pri_bitmask;
+ /*
+ * strict priority: valid values are 0..5; 0 is highest priority.
+ * There can't be two COSes with the same priority.
+ */
u8 strict;
+#define BNX2X_DCBX_STRICT_INVALID DCBX_COS_MAX_NUM
+#define BNX2X_DCBX_STRICT_COS_HIGHEST 0
+#define BNX2X_DCBX_STRICT_COS_NEXT_LOWER_PRI(sp) ((sp) + 1)
u8 pauseable;
};
struct bnx2x_dcbx_pg_params {
u32 enabled;
u8 num_of_cos; /* valid COS entries */
- struct bnx2x_dcbx_cos_params cos_params[E2_NUM_OF_COS];
+ struct bnx2x_dcbx_cos_params cos_params[DCBX_COS_MAX_NUM];
};
struct bnx2x_dcbx_pfc_params {
@@ -60,6 +68,8 @@
#define BNX2X_DCBX_OVERWRITE_SETTINGS_DISABLE 0
#define BNX2X_DCBX_OVERWRITE_SETTINGS_ENABLE 1
#define BNX2X_DCBX_OVERWRITE_SETTINGS_INVALID (BNX2X_DCBX_CONFIG_INV_VALUE)
+#define BNX2X_IS_ETS_ENABLED(bp) ((bp)->dcb_state == BNX2X_DCB_STATE_ON &&\
+ (bp)->dcbx_port_params.ets.enabled)
struct bnx2x_config_lldp_params {
u32 overwrite_settings;
@@ -132,7 +142,7 @@
};
struct cos_help_data {
- struct cos_entry_help_data data[E2_NUM_OF_COS];
+ struct cos_entry_help_data data[DCBX_COS_MAX_NUM];
u8 num_of_cos;
};
@@ -148,6 +158,8 @@
((pg_pri) & (DCBX_PFC_PRI_PAUSE_MASK(bp)))
#define DCBX_PFC_PRI_GET_NON_PAUSE(bp, pg_pri) \
(DCBX_PFC_PRI_NON_PAUSE_MASK(bp) & (pg_pri))
+#define DCBX_IS_PFC_PRI_SOME_PAUSE(bp, pg_pri) \
+ (0 != DCBX_PFC_PRI_GET_PAUSE(bp, pg_pri))
#define IS_DCBX_PFC_PRI_ONLY_PAUSE(bp, pg_pri) \
(pg_pri == DCBX_PFC_PRI_GET_PAUSE((bp), (pg_pri)))
#define IS_DCBX_PFC_PRI_ONLY_NON_PAUSE(bp, pg_pri)\
@@ -170,22 +182,18 @@
/* forward DCB/PFC related declarations */
struct bnx2x;
-void bnx2x_dcb_init_intmem_pfc(struct bnx2x *bp);
void bnx2x_dcbx_update(struct work_struct *work);
void bnx2x_dcbx_init_params(struct bnx2x *bp);
void bnx2x_dcbx_set_state(struct bnx2x *bp, bool dcb_on, u32 dcbx_enabled);
enum {
BNX2X_DCBX_STATE_NEG_RECEIVED = 0x1,
-#ifdef BCM_CNIC
- BNX2X_DCBX_STATE_ISCSI_STOPPED,
-#endif
BNX2X_DCBX_STATE_TX_PAUSED,
BNX2X_DCBX_STATE_TX_RELEASED
};
void bnx2x_dcbx_set_params(struct bnx2x *bp, u32 state);
-
+void bnx2x_dcbx_pmf_update(struct bnx2x *bp);
/* DCB netlink */
#ifdef BCM_DCBNL
extern const struct dcbnl_rtnl_ops bnx2x_dcbnl_ops;
diff --git a/drivers/net/bnx2x/bnx2x_dump.h b/drivers/net/bnx2x/bnx2x_dump.h
index fb3ff7c..407531a 100644
--- a/drivers/net/bnx2x/bnx2x_dump.h
+++ b/drivers/net/bnx2x/bnx2x_dump.h
@@ -25,34 +25,55 @@
/*definitions */
-#define XSTORM_WAITP_ADDR 0x2b8a80
-#define TSTORM_WAITP_ADDR 0x1b8a80
-#define USTORM_WAITP_ADDR 0x338a80
-#define CSTORM_WAITP_ADDR 0x238a80
-#define TSTORM_CAM_MODE 0x1B1440
+#define XSTORM_WAITP_ADDR 0x2b8a80
+#define TSTORM_WAITP_ADDR 0x1b8a80
+#define USTORM_WAITP_ADDR 0x338a80
+#define CSTORM_WAITP_ADDR 0x238a80
+#define TSTORM_CAM_MODE 0x1B1440
-#define MAX_TIMER_PENDING 200
-#define TIMER_SCAN_DONT_CARE 0xFF
-#define RI_E1 0x1
-#define RI_E1H 0x2
-#define RI_E2 0x4
-#define RI_ONLINE 0x100
-#define RI_PATH0_DUMP 0x200
-#define RI_PATH1_DUMP 0x400
-#define RI_E1_OFFLINE (RI_E1)
-#define RI_E1_ONLINE (RI_E1 | RI_ONLINE)
-#define RI_E1H_OFFLINE (RI_E1H)
-#define RI_E1H_ONLINE (RI_E1H | RI_ONLINE)
-#define RI_E2_OFFLINE (RI_E2)
-#define RI_E2_ONLINE (RI_E2 | RI_ONLINE)
-#define RI_E1E1H_OFFLINE (RI_E1 | RI_E1H)
-#define RI_E1E1H_ONLINE (RI_E1 | RI_E1H | RI_ONLINE)
-#define RI_E1HE2_OFFLINE (RI_E2 | RI_E1H)
-#define RI_E1HE2_ONLINE (RI_E2 | RI_E1H | RI_ONLINE)
-#define RI_E1E2_OFFLINE (RI_E2 | RI_E1)
-#define RI_E1E2_ONLINE (RI_E2 | RI_E1 | RI_ONLINE)
-#define RI_ALL_OFFLINE (RI_E1 | RI_E1H | RI_E2)
-#define RI_ALL_ONLINE (RI_E1 | RI_E1H | RI_E2 | RI_ONLINE)
+#define MAX_TIMER_PENDING 200
+#define TIMER_SCAN_DONT_CARE 0xFF
+#define RI_E1 0x1
+#define RI_E1H 0x2
+#define RI_E2 0x4
+#define RI_E3 0x8
+#define RI_ONLINE 0x100
+#define RI_PATH0_DUMP 0x200
+#define RI_PATH1_DUMP 0x400
+#define RI_E1_OFFLINE (RI_E1)
+#define RI_E1_ONLINE (RI_E1 | RI_ONLINE)
+#define RI_E1H_OFFLINE (RI_E1H)
+#define RI_E1H_ONLINE (RI_E1H | RI_ONLINE)
+#define RI_E2_OFFLINE (RI_E2)
+#define RI_E2_ONLINE (RI_E2 | RI_ONLINE)
+#define RI_E3_OFFLINE (RI_E3)
+#define RI_E3_ONLINE (RI_E3 | RI_ONLINE)
+#define RI_E1E1H_OFFLINE (RI_E1 | RI_E1H)
+#define RI_E1E1H_ONLINE (RI_E1 | RI_E1H | RI_ONLINE)
+#define RI_E1E1HE2_OFFLINE (RI_E1 | RI_E1H | RI_E2)
+#define RI_E1E1HE2_ONLINE (RI_E1 | RI_E1H | RI_E2 | RI_ONLINE)
+#define RI_E1HE2_OFFLINE (RI_E2 | RI_E1H)
+#define RI_E1HE2_ONLINE (RI_E2 | RI_E1H | RI_ONLINE)
+#define RI_E1E2_OFFLINE (RI_E2 | RI_E1)
+#define RI_E1E2_ONLINE (RI_E2 | RI_E1 | RI_ONLINE)
+#define RI_E1E3_OFFLINE (RI_E1 | RI_E3)
+#define RI_E1E3_ONLINE (RI_E1 | RI_E3 | RI_ONLINE)
+#define RI_E1HE3_OFFLINE (RI_E1H | RI_E3)
+#define RI_E1HE3_ONLINE (RI_E1H | RI_E3 | RI_ONLINE)
+#define RI_E2E3_OFFLINE (RI_E2 | RI_E3)
+#define RI_E2E3_ONLINE (RI_E2 | RI_E3 | RI_ONLINE)
+#define RI_E1E1HE3_OFFLINE (RI_E1 | RI_E1H | RI_E3)
+#define RI_E1E1HE3_ONLINE (RI_E1 | RI_E1H | RI_E3 | RI_ONLINE)
+#define RI_E1HE2E3_OFFLINE (RI_E2 | RI_E1H | RI_E3)
+#define RI_E1HE2E3_ONLINE (RI_E2 | RI_E1H | RI_E3 | RI_ONLINE)
+#define RI_E1E2E3_OFFLINE (RI_E2 | RI_E1 | RI_E3)
+#define RI_E1E2E3_ONLINE (RI_E2 | RI_E1 | RI_E3 | RI_ONLINE)
+#define RI_ALL_OFFLINE (RI_E1 | RI_E1H | RI_E2 | RI_E3)
+#define RI_ALL_ONLINE (RI_E1 | RI_E1H | RI_E2 | RI_E3 | RI_ONLINE)
+
+#define DBG_DMP_TRACE_BUFFER_SIZE 0x800
+#define DBG_DMP_TRACE_BUFFER_OFFSET(shmem0_offset) \
+ ((shmem0_offset) - DBG_DMP_TRACE_BUFFER_SIZE)
struct dump_sign {
u32 time_stamp;
@@ -86,185 +107,255 @@
u16 info;
};
-#define REGS_COUNT 834
-static const struct reg_addr reg_addrs[REGS_COUNT] = {
+static const struct reg_addr reg_addrs[] = {
{ 0x2000, 341, RI_ALL_ONLINE }, { 0x2800, 103, RI_ALL_ONLINE },
{ 0x3000, 287, RI_ALL_ONLINE }, { 0x3800, 331, RI_ALL_ONLINE },
- { 0x8800, 6, RI_ALL_ONLINE }, { 0x8818, 1, RI_E1HE2_ONLINE },
- { 0x9000, 164, RI_E2_ONLINE }, { 0x9400, 33, RI_E2_ONLINE },
- { 0xa000, 27, RI_ALL_ONLINE }, { 0xa06c, 1, RI_E1E1H_ONLINE },
- { 0xa070, 71, RI_ALL_ONLINE }, { 0xa18c, 4, RI_E1E1H_ONLINE },
- { 0xa19c, 62, RI_ALL_ONLINE }, { 0xa294, 2, RI_E1E1H_ONLINE },
- { 0xa29c, 56, RI_ALL_ONLINE }, { 0xa39c, 7, RI_E1HE2_ONLINE },
- { 0xa3c0, 3, RI_E1HE2_ONLINE }, { 0xa3d0, 1, RI_E1HE2_ONLINE },
- { 0xa3d8, 1, RI_E1HE2_ONLINE }, { 0xa3e0, 1, RI_E1HE2_ONLINE },
- { 0xa3e8, 1, RI_E1HE2_ONLINE }, { 0xa3f0, 1, RI_E1HE2_ONLINE },
- { 0xa3f8, 1, RI_E1HE2_ONLINE }, { 0xa400, 43, RI_ALL_ONLINE },
- { 0xa4ac, 2, RI_E1E1H_ONLINE }, { 0xa4b4, 1, RI_ALL_ONLINE },
+ { 0x8800, 6, RI_ALL_ONLINE }, { 0x8818, 1, RI_E1HE2E3_ONLINE },
+ { 0x9000, 147, RI_E2E3_ONLINE }, { 0x924c, 1, RI_E2_ONLINE },
+ { 0x9250, 16, RI_E2E3_ONLINE }, { 0x9400, 33, RI_E2E3_ONLINE },
+ { 0x9484, 5, RI_E3_ONLINE }, { 0xa000, 27, RI_ALL_ONLINE },
+ { 0xa06c, 1, RI_E1E1H_ONLINE }, { 0xa070, 71, RI_ALL_ONLINE },
+ { 0xa18c, 4, RI_E1E1H_ONLINE }, { 0xa19c, 62, RI_ALL_ONLINE },
+ { 0xa294, 2, RI_E1E1H_ONLINE }, { 0xa29c, 2, RI_ALL_ONLINE },
+ { 0xa2a4, 2, RI_E1E1HE2_ONLINE }, { 0xa2ac, 52, RI_ALL_ONLINE },
+ { 0xa39c, 7, RI_E1HE2E3_ONLINE }, { 0xa3b8, 2, RI_E3_ONLINE },
+ { 0xa3c0, 3, RI_E1HE2E3_ONLINE }, { 0xa3d0, 1, RI_E1HE2E3_ONLINE },
+ { 0xa3d8, 1, RI_E1HE2E3_ONLINE }, { 0xa3e0, 1, RI_E1HE2E3_ONLINE },
+ { 0xa3e8, 1, RI_E1HE2E3_ONLINE }, { 0xa3f0, 1, RI_E1HE2E3_ONLINE },
+ { 0xa3f8, 1, RI_E1HE2E3_ONLINE }, { 0xa400, 40, RI_ALL_ONLINE },
+ { 0xa4a0, 1, RI_E1E1HE2_ONLINE }, { 0xa4a4, 2, RI_ALL_ONLINE },
+ { 0xa4ac, 2, RI_E1E1H_ONLINE }, { 0xa4b4, 1, RI_E1E1HE2_ONLINE },
{ 0xa4b8, 2, RI_E1E1H_ONLINE }, { 0xa4c0, 3, RI_ALL_ONLINE },
- { 0xa4cc, 5, RI_E1E1H_ONLINE }, { 0xa4e0, 9, RI_ALL_ONLINE },
- { 0xa504, 1, RI_E1E1H_ONLINE }, { 0xa508, 3, RI_ALL_ONLINE },
- { 0xa518, 1, RI_ALL_ONLINE }, { 0xa520, 1, RI_ALL_ONLINE },
- { 0xa528, 1, RI_ALL_ONLINE }, { 0xa530, 1, RI_ALL_ONLINE },
- { 0xa538, 1, RI_ALL_ONLINE }, { 0xa540, 1, RI_ALL_ONLINE },
- { 0xa548, 1, RI_E1E1H_ONLINE }, { 0xa550, 1, RI_E1E1H_ONLINE },
- { 0xa558, 1, RI_E1E1H_ONLINE }, { 0xa560, 1, RI_E1E1H_ONLINE },
- { 0xa568, 1, RI_E1E1H_ONLINE }, { 0xa570, 1, RI_ALL_ONLINE },
- { 0xa580, 1, RI_ALL_ONLINE }, { 0xa590, 1, RI_ALL_ONLINE },
- { 0xa5a0, 1, RI_ALL_ONLINE }, { 0xa5c0, 1, RI_ALL_ONLINE },
- { 0xa5e0, 1, RI_E1HE2_ONLINE }, { 0xa5e8, 1, RI_E1HE2_ONLINE },
- { 0xa5f0, 1, RI_E1HE2_ONLINE }, { 0xa5f8, 10, RI_E1HE2_ONLINE },
- { 0xa620, 111, RI_E2_ONLINE }, { 0xa800, 51, RI_E2_ONLINE },
- { 0xa8d4, 4, RI_E2_ONLINE }, { 0xa8e8, 1, RI_E2_ONLINE },
- { 0xa8f0, 1, RI_E2_ONLINE }, { 0x10000, 236, RI_ALL_ONLINE },
- { 0x10400, 57, RI_ALL_ONLINE }, { 0x104e8, 2, RI_ALL_ONLINE },
+ { 0xa4cc, 5, RI_E1E1H_ONLINE }, { 0xa4e0, 3, RI_ALL_ONLINE },
+ { 0xa4fc, 2, RI_ALL_ONLINE }, { 0xa504, 1, RI_E1E1H_ONLINE },
+ { 0xa508, 3, RI_ALL_ONLINE }, { 0xa518, 1, RI_ALL_ONLINE },
+ { 0xa520, 1, RI_ALL_ONLINE }, { 0xa528, 1, RI_ALL_ONLINE },
+ { 0xa530, 1, RI_ALL_ONLINE }, { 0xa538, 1, RI_ALL_ONLINE },
+ { 0xa540, 1, RI_ALL_ONLINE }, { 0xa548, 1, RI_E1E1H_ONLINE },
+ { 0xa550, 1, RI_E1E1H_ONLINE }, { 0xa558, 1, RI_E1E1H_ONLINE },
+ { 0xa560, 1, RI_E1E1H_ONLINE }, { 0xa568, 1, RI_E1E1H_ONLINE },
+ { 0xa570, 1, RI_ALL_ONLINE }, { 0xa580, 1, RI_ALL_ONLINE },
+ { 0xa590, 1, RI_ALL_ONLINE }, { 0xa5a0, 1, RI_E1E1HE2_ONLINE },
+ { 0xa5c0, 1, RI_ALL_ONLINE }, { 0xa5e0, 1, RI_E1HE2E3_ONLINE },
+ { 0xa5e8, 1, RI_E1HE2E3_ONLINE }, { 0xa5f0, 1, RI_E1HE2E3_ONLINE },
+ { 0xa5f8, 1, RI_E1HE2_ONLINE }, { 0xa5fc, 9, RI_E1HE2E3_ONLINE },
+ { 0xa620, 6, RI_E2E3_ONLINE }, { 0xa638, 20, RI_E2_ONLINE },
+ { 0xa688, 42, RI_E2E3_ONLINE }, { 0xa730, 1, RI_E2_ONLINE },
+ { 0xa734, 2, RI_E2E3_ONLINE }, { 0xa73c, 4, RI_E2_ONLINE },
+ { 0xa74c, 5, RI_E2E3_ONLINE }, { 0xa760, 5, RI_E2_ONLINE },
+ { 0xa774, 7, RI_E2E3_ONLINE }, { 0xa790, 15, RI_E2_ONLINE },
+ { 0xa7cc, 4, RI_E2E3_ONLINE }, { 0xa7e0, 6, RI_E3_ONLINE },
+ { 0xa800, 18, RI_E2_ONLINE }, { 0xa848, 33, RI_E2E3_ONLINE },
+ { 0xa8cc, 2, RI_E3_ONLINE }, { 0xa8d4, 4, RI_E2E3_ONLINE },
+ { 0xa8e4, 1, RI_E3_ONLINE }, { 0xa8e8, 1, RI_E2E3_ONLINE },
+ { 0xa8f0, 1, RI_E2E3_ONLINE }, { 0xa8f8, 30, RI_E3_ONLINE },
+ { 0xa974, 73, RI_E3_ONLINE }, { 0xac30, 1, RI_E3_ONLINE },
+ { 0xac40, 1, RI_E3_ONLINE }, { 0xac50, 1, RI_E3_ONLINE },
+ { 0x10000, 9, RI_ALL_ONLINE }, { 0x10024, 1, RI_E1E1HE2_ONLINE },
+ { 0x10028, 5, RI_ALL_ONLINE }, { 0x1003c, 6, RI_E1E1HE2_ONLINE },
+ { 0x10054, 20, RI_ALL_ONLINE }, { 0x100a4, 4, RI_E1E1HE2_ONLINE },
+ { 0x100b4, 11, RI_ALL_ONLINE }, { 0x100e0, 4, RI_E1E1HE2_ONLINE },
+ { 0x100f0, 8, RI_ALL_ONLINE }, { 0x10110, 6, RI_E1E1HE2_ONLINE },
+ { 0x10128, 110, RI_ALL_ONLINE }, { 0x102e0, 4, RI_E1E1HE2_ONLINE },
+ { 0x102f0, 18, RI_ALL_ONLINE }, { 0x10338, 20, RI_E1E1HE2_ONLINE },
+ { 0x10388, 10, RI_ALL_ONLINE }, { 0x10400, 6, RI_E1E1HE2_ONLINE },
+ { 0x10418, 6, RI_ALL_ONLINE }, { 0x10430, 10, RI_E1E1HE2_ONLINE },
+ { 0x10458, 22, RI_ALL_ONLINE }, { 0x104b0, 12, RI_E1E1HE2_ONLINE },
+ { 0x104e0, 1, RI_ALL_ONLINE }, { 0x104e8, 2, RI_ALL_ONLINE },
{ 0x104f4, 2, RI_ALL_ONLINE }, { 0x10500, 146, RI_ALL_ONLINE },
- { 0x10750, 2, RI_ALL_ONLINE }, { 0x10760, 2, RI_ALL_ONLINE },
- { 0x10770, 2, RI_ALL_ONLINE }, { 0x10780, 2, RI_ALL_ONLINE },
- { 0x10790, 2, RI_ALL_ONLINE }, { 0x107a0, 2, RI_ALL_ONLINE },
- { 0x107b0, 2, RI_ALL_ONLINE }, { 0x107c0, 2, RI_ALL_ONLINE },
- { 0x107d0, 2, RI_ALL_ONLINE }, { 0x107e0, 2, RI_ALL_ONLINE },
+ { 0x10750, 2, RI_E1E1HE2_ONLINE }, { 0x10760, 2, RI_E1E1HE2_ONLINE },
+ { 0x10770, 2, RI_E1E1HE2_ONLINE }, { 0x10780, 2, RI_E1E1HE2_ONLINE },
+ { 0x10790, 2, RI_ALL_ONLINE }, { 0x107a0, 2, RI_E1E1HE2_ONLINE },
+ { 0x107b0, 2, RI_E1E1HE2_ONLINE }, { 0x107c0, 2, RI_E1E1HE2_ONLINE },
+ { 0x107d0, 2, RI_E1E1HE2_ONLINE }, { 0x107e0, 2, RI_ALL_ONLINE },
{ 0x10880, 2, RI_ALL_ONLINE }, { 0x10900, 2, RI_ALL_ONLINE },
- { 0x16000, 26, RI_E1HE2_ONLINE }, { 0x16070, 18, RI_E1HE2_ONLINE },
- { 0x160c0, 27, RI_E1HE2_ONLINE }, { 0x16140, 1, RI_E1HE2_ONLINE },
- { 0x16160, 1, RI_E1HE2_ONLINE }, { 0x16180, 2, RI_E1HE2_ONLINE },
- { 0x161c0, 2, RI_E1HE2_ONLINE }, { 0x16204, 5, RI_E1HE2_ONLINE },
- { 0x18000, 1, RI_E1HE2_ONLINE }, { 0x18008, 1, RI_E1HE2_ONLINE },
- { 0x18010, 35, RI_E2_ONLINE }, { 0x180a4, 2, RI_E2_ONLINE },
- { 0x180c0, 191, RI_E2_ONLINE }, { 0x18440, 1, RI_E2_ONLINE },
- { 0x18460, 1, RI_E2_ONLINE }, { 0x18480, 2, RI_E2_ONLINE },
- { 0x184c0, 2, RI_E2_ONLINE }, { 0x18500, 15, RI_E2_ONLINE },
- { 0x20000, 24, RI_ALL_ONLINE }, { 0x20060, 8, RI_ALL_ONLINE },
- { 0x20080, 94, RI_ALL_ONLINE }, { 0x201f8, 1, RI_E1E1H_ONLINE },
- { 0x201fc, 1, RI_ALL_ONLINE }, { 0x20200, 1, RI_E1E1H_ONLINE },
- { 0x20204, 1, RI_ALL_ONLINE }, { 0x20208, 1, RI_E1E1H_ONLINE },
- { 0x2020c, 39, RI_ALL_ONLINE }, { 0x202c8, 1, RI_E2_ONLINE },
- { 0x202d8, 4, RI_E2_ONLINE }, { 0x20400, 2, RI_ALL_ONLINE },
- { 0x2040c, 8, RI_ALL_ONLINE }, { 0x2042c, 18, RI_E1HE2_ONLINE },
- { 0x20480, 1, RI_ALL_ONLINE }, { 0x20500, 1, RI_ALL_ONLINE },
- { 0x20600, 1, RI_ALL_ONLINE }, { 0x28000, 1, RI_ALL_ONLINE },
- { 0x28004, 8191, RI_ALL_OFFLINE }, { 0x30000, 1, RI_ALL_ONLINE },
- { 0x30004, 16383, RI_ALL_OFFLINE }, { 0x40000, 98, RI_ALL_ONLINE },
- { 0x401a8, 8, RI_E1HE2_ONLINE }, { 0x401c8, 1, RI_E1H_ONLINE },
- { 0x401cc, 2, RI_E1HE2_ONLINE }, { 0x401d4, 2, RI_E2_ONLINE },
- { 0x40200, 4, RI_ALL_ONLINE }, { 0x40220, 18, RI_E2_ONLINE },
- { 0x40400, 43, RI_ALL_ONLINE }, { 0x404cc, 3, RI_E1HE2_ONLINE },
- { 0x404e0, 1, RI_E2_ONLINE }, { 0x40500, 2, RI_ALL_ONLINE },
+ { 0x16000, 1, RI_E1HE2_ONLINE }, { 0x16004, 25, RI_E1HE2E3_ONLINE },
+ { 0x16070, 18, RI_E1HE2E3_ONLINE }, { 0x160c0, 7, RI_E1HE2E3_ONLINE },
+ { 0x160dc, 2, RI_E1HE2_ONLINE }, { 0x160e4, 10, RI_E1HE2E3_ONLINE },
+ { 0x1610c, 2, RI_E1HE2_ONLINE }, { 0x16114, 6, RI_E1HE2E3_ONLINE },
+ { 0x16140, 48, RI_E1HE2E3_ONLINE }, { 0x16204, 5, RI_E1HE2E3_ONLINE },
+ { 0x18000, 1, RI_E1HE2E3_ONLINE }, { 0x18008, 1, RI_E1HE2E3_ONLINE },
+ { 0x18010, 35, RI_E2E3_ONLINE }, { 0x180a4, 2, RI_E2E3_ONLINE },
+ { 0x180c0, 109, RI_E2E3_ONLINE }, { 0x18274, 1, RI_E2_ONLINE },
+ { 0x18278, 81, RI_E2E3_ONLINE }, { 0x18440, 63, RI_E2E3_ONLINE },
+ { 0x18570, 42, RI_E3_ONLINE }, { 0x20000, 24, RI_ALL_ONLINE },
+ { 0x20060, 8, RI_ALL_ONLINE }, { 0x20080, 94, RI_ALL_ONLINE },
+ { 0x201f8, 1, RI_E1E1H_ONLINE }, { 0x201fc, 1, RI_ALL_ONLINE },
+ { 0x20200, 1, RI_E1E1H_ONLINE }, { 0x20204, 1, RI_ALL_ONLINE },
+ { 0x20208, 1, RI_E1E1H_ONLINE }, { 0x2020c, 39, RI_ALL_ONLINE },
+ { 0x202c8, 1, RI_E2E3_ONLINE }, { 0x202d8, 4, RI_E2E3_ONLINE },
+ { 0x20400, 2, RI_ALL_ONLINE }, { 0x2040c, 8, RI_ALL_ONLINE },
+ { 0x2042c, 18, RI_E1HE2E3_ONLINE }, { 0x20480, 1, RI_ALL_ONLINE },
+ { 0x20500, 1, RI_ALL_ONLINE }, { 0x20600, 1, RI_ALL_ONLINE },
+ { 0x28000, 1, RI_ALL_ONLINE }, { 0x28004, 8191, RI_ALL_OFFLINE },
+ { 0x30000, 1, RI_ALL_ONLINE }, { 0x30004, 16383, RI_ALL_OFFLINE },
+ { 0x40000, 98, RI_ALL_ONLINE }, { 0x401a8, 8, RI_E1HE2E3_ONLINE },
+ { 0x401c8, 1, RI_E1H_ONLINE }, { 0x401cc, 2, RI_E1HE2E3_ONLINE },
+ { 0x401d4, 2, RI_E2E3_ONLINE }, { 0x40200, 4, RI_ALL_ONLINE },
+ { 0x40220, 18, RI_E2E3_ONLINE }, { 0x40268, 2, RI_E3_ONLINE },
+ { 0x40400, 43, RI_ALL_ONLINE }, { 0x404cc, 3, RI_E1HE2E3_ONLINE },
+ { 0x404e0, 1, RI_E2E3_ONLINE }, { 0x40500, 2, RI_ALL_ONLINE },
{ 0x40510, 2, RI_ALL_ONLINE }, { 0x40520, 2, RI_ALL_ONLINE },
{ 0x40530, 2, RI_ALL_ONLINE }, { 0x40540, 2, RI_ALL_ONLINE },
- { 0x40550, 10, RI_E2_ONLINE }, { 0x40610, 2, RI_E2_ONLINE },
- { 0x42000, 164, RI_ALL_ONLINE }, { 0x422c0, 4, RI_E2_ONLINE },
- { 0x422d4, 5, RI_E1HE2_ONLINE }, { 0x422e8, 1, RI_E2_ONLINE },
+ { 0x40550, 10, RI_E2E3_ONLINE }, { 0x40610, 2, RI_E2E3_ONLINE },
+ { 0x42000, 164, RI_ALL_ONLINE }, { 0x422c0, 4, RI_E2E3_ONLINE },
+ { 0x422d4, 5, RI_E1HE2E3_ONLINE }, { 0x422e8, 1, RI_E2E3_ONLINE },
{ 0x42400, 49, RI_ALL_ONLINE }, { 0x424c8, 38, RI_ALL_ONLINE },
- { 0x42568, 2, RI_ALL_ONLINE }, { 0x42640, 5, RI_E2_ONLINE },
+ { 0x42568, 2, RI_ALL_ONLINE }, { 0x42640, 5, RI_E2E3_ONLINE },
{ 0x42800, 1, RI_ALL_ONLINE }, { 0x50000, 1, RI_ALL_ONLINE },
{ 0x50004, 19, RI_ALL_ONLINE }, { 0x50050, 8, RI_ALL_ONLINE },
- { 0x50070, 88, RI_ALL_ONLINE }, { 0x501f0, 4, RI_E1HE2_ONLINE },
+ { 0x50070, 88, RI_ALL_ONLINE }, { 0x501f0, 4, RI_E1HE2E3_ONLINE },
{ 0x50200, 2, RI_ALL_ONLINE }, { 0x5020c, 7, RI_ALL_ONLINE },
- { 0x50228, 6, RI_E1HE2_ONLINE }, { 0x50240, 1, RI_ALL_ONLINE },
- { 0x50280, 1, RI_ALL_ONLINE }, { 0x50300, 1, RI_E2_ONLINE },
- { 0x5030c, 1, RI_E2_ONLINE }, { 0x50318, 1, RI_E2_ONLINE },
- { 0x5031c, 1, RI_E2_ONLINE }, { 0x50320, 2, RI_E2_ONLINE },
+ { 0x50228, 6, RI_E1HE2E3_ONLINE }, { 0x50240, 1, RI_ALL_ONLINE },
+ { 0x50280, 1, RI_ALL_ONLINE }, { 0x50300, 1, RI_E2E3_ONLINE },
+ { 0x5030c, 1, RI_E2E3_ONLINE }, { 0x50318, 1, RI_E2E3_ONLINE },
+ { 0x5031c, 1, RI_E2E3_ONLINE }, { 0x50320, 2, RI_E2E3_ONLINE },
{ 0x52000, 1, RI_ALL_ONLINE }, { 0x54000, 1, RI_ALL_ONLINE },
{ 0x54004, 3327, RI_ALL_OFFLINE }, { 0x58000, 1, RI_ALL_ONLINE },
{ 0x58004, 8191, RI_E1E1H_OFFLINE }, { 0x60000, 26, RI_ALL_ONLINE },
{ 0x60068, 8, RI_E1E1H_ONLINE }, { 0x60088, 12, RI_ALL_ONLINE },
{ 0x600b8, 9, RI_E1E1H_ONLINE }, { 0x600dc, 1, RI_ALL_ONLINE },
- { 0x600e0, 5, RI_E1E1H_ONLINE }, { 0x600f4, 1, RI_ALL_ONLINE },
+ { 0x600e0, 5, RI_E1E1H_ONLINE }, { 0x600f4, 1, RI_E1E1HE2_ONLINE },
{ 0x600f8, 1, RI_E1E1H_ONLINE }, { 0x600fc, 8, RI_ALL_ONLINE },
- { 0x6013c, 24, RI_E1H_ONLINE }, { 0x6019c, 2, RI_E2_ONLINE },
- { 0x601ac, 18, RI_E2_ONLINE }, { 0x60200, 1, RI_ALL_ONLINE },
- { 0x60204, 2, RI_ALL_OFFLINE }, { 0x60210, 13, RI_E2_ONLINE },
+ { 0x6013c, 24, RI_E1H_ONLINE }, { 0x6019c, 2, RI_E2E3_ONLINE },
+ { 0x601ac, 18, RI_E2E3_ONLINE }, { 0x60200, 1, RI_ALL_ONLINE },
+ { 0x60204, 2, RI_ALL_OFFLINE }, { 0x60210, 13, RI_E2E3_ONLINE },
{ 0x61000, 1, RI_ALL_ONLINE }, { 0x61004, 511, RI_ALL_OFFLINE },
- { 0x70000, 8, RI_ALL_ONLINE }, { 0x70020, 8184, RI_ALL_OFFLINE },
+ { 0x61800, 512, RI_E3_OFFLINE }, { 0x70000, 8, RI_ALL_ONLINE },
+ { 0x70020, 8184, RI_ALL_OFFLINE }, { 0x78000, 8192, RI_E3_OFFLINE },
{ 0x85000, 3, RI_ALL_ONLINE }, { 0x8501c, 7, RI_ALL_ONLINE },
{ 0x85048, 1, RI_ALL_ONLINE }, { 0x85200, 32, RI_ALL_ONLINE },
- { 0xc1000, 7, RI_ALL_ONLINE }, { 0xc103c, 2, RI_E2_ONLINE },
+ { 0xb0000, 16384, RI_E1H_ONLINE },
+ { 0xc1000, 7, RI_ALL_ONLINE }, { 0xc103c, 2, RI_E2E3_ONLINE },
{ 0xc1800, 2, RI_ALL_ONLINE }, { 0xc2000, 164, RI_ALL_ONLINE },
- { 0xc22c0, 5, RI_E2_ONLINE }, { 0xc22d8, 4, RI_E2_ONLINE },
+ { 0xc22c0, 5, RI_E2E3_ONLINE }, { 0xc22d8, 4, RI_E2E3_ONLINE },
{ 0xc2400, 49, RI_ALL_ONLINE }, { 0xc24c8, 38, RI_ALL_ONLINE },
{ 0xc2568, 2, RI_ALL_ONLINE }, { 0xc2600, 1, RI_ALL_ONLINE },
- { 0xc4000, 165, RI_ALL_ONLINE }, { 0xc42d8, 2, RI_E2_ONLINE },
- { 0xc42e0, 7, RI_E1HE2_ONLINE }, { 0xc42fc, 1, RI_E2_ONLINE },
+ { 0xc4000, 165, RI_ALL_ONLINE }, { 0xc42d8, 2, RI_E2E3_ONLINE },
+ { 0xc42e0, 7, RI_E1HE2E3_ONLINE }, { 0xc42fc, 1, RI_E2E3_ONLINE },
{ 0xc4400, 51, RI_ALL_ONLINE }, { 0xc44d0, 38, RI_ALL_ONLINE },
- { 0xc4570, 2, RI_ALL_ONLINE }, { 0xc4578, 5, RI_E2_ONLINE },
+ { 0xc4570, 2, RI_ALL_ONLINE }, { 0xc4578, 5, RI_E2E3_ONLINE },
{ 0xc4600, 1, RI_ALL_ONLINE }, { 0xd0000, 19, RI_ALL_ONLINE },
{ 0xd004c, 8, RI_ALL_ONLINE }, { 0xd006c, 91, RI_ALL_ONLINE },
- { 0xd01fc, 1, RI_E2_ONLINE }, { 0xd0200, 2, RI_ALL_ONLINE },
- { 0xd020c, 7, RI_ALL_ONLINE }, { 0xd0228, 18, RI_E1HE2_ONLINE },
+ { 0xd01fc, 1, RI_E2E3_ONLINE }, { 0xd0200, 2, RI_ALL_ONLINE },
+ { 0xd020c, 7, RI_ALL_ONLINE }, { 0xd0228, 18, RI_E1HE2E3_ONLINE },
{ 0xd0280, 1, RI_ALL_ONLINE }, { 0xd0300, 1, RI_ALL_ONLINE },
{ 0xd0400, 1, RI_ALL_ONLINE }, { 0xd4000, 1, RI_ALL_ONLINE },
{ 0xd4004, 2559, RI_ALL_OFFLINE }, { 0xd8000, 1, RI_ALL_ONLINE },
{ 0xd8004, 8191, RI_ALL_OFFLINE }, { 0xe0000, 21, RI_ALL_ONLINE },
{ 0xe0054, 8, RI_ALL_ONLINE }, { 0xe0074, 49, RI_ALL_ONLINE },
{ 0xe0138, 1, RI_E1E1H_ONLINE }, { 0xe013c, 35, RI_ALL_ONLINE },
- { 0xe01f4, 2, RI_E2_ONLINE }, { 0xe0200, 2, RI_ALL_ONLINE },
- { 0xe020c, 8, RI_ALL_ONLINE }, { 0xe022c, 18, RI_E1HE2_ONLINE },
- { 0xe0280, 1, RI_ALL_ONLINE }, { 0xe0300, 1, RI_ALL_ONLINE },
- { 0xe1000, 1, RI_ALL_ONLINE }, { 0xe2000, 1, RI_ALL_ONLINE },
- { 0xe2004, 2047, RI_ALL_OFFLINE }, { 0xf0000, 1, RI_ALL_ONLINE },
- { 0xf0004, 16383, RI_ALL_OFFLINE }, { 0x101000, 12, RI_ALL_ONLINE },
- { 0x101050, 1, RI_E1HE2_ONLINE }, { 0x101054, 3, RI_E2_ONLINE },
- { 0x101100, 1, RI_ALL_ONLINE }, { 0x101800, 8, RI_ALL_ONLINE },
- { 0x102000, 18, RI_ALL_ONLINE }, { 0x102068, 6, RI_E2_ONLINE },
- { 0x102080, 17, RI_ALL_ONLINE }, { 0x1020c8, 8, RI_E1H_ONLINE },
- { 0x1020e8, 9, RI_E2_ONLINE }, { 0x102400, 1, RI_ALL_ONLINE },
- { 0x103000, 26, RI_ALL_ONLINE }, { 0x103098, 5, RI_E1HE2_ONLINE },
- { 0x1030ac, 10, RI_E2_ONLINE }, { 0x1030d8, 8, RI_E2_ONLINE },
- { 0x103400, 1, RI_E2_ONLINE }, { 0x103404, 135, RI_E2_OFFLINE },
- { 0x103800, 8, RI_ALL_ONLINE }, { 0x104000, 63, RI_ALL_ONLINE },
- { 0x10411c, 16, RI_E2_ONLINE }, { 0x104200, 17, RI_ALL_ONLINE },
- { 0x104400, 64, RI_ALL_ONLINE }, { 0x104500, 192, RI_ALL_OFFLINE },
- { 0x104800, 64, RI_ALL_ONLINE }, { 0x104900, 192, RI_ALL_OFFLINE },
- { 0x105000, 256, RI_ALL_ONLINE }, { 0x105400, 768, RI_ALL_OFFLINE },
- { 0x107000, 7, RI_E2_ONLINE }, { 0x108000, 33, RI_E1E1H_ONLINE },
+ { 0xe01f4, 1, RI_E2_ONLINE }, { 0xe01f8, 1, RI_E2E3_ONLINE },
+ { 0xe0200, 2, RI_ALL_ONLINE }, { 0xe020c, 8, RI_ALL_ONLINE },
+ { 0xe022c, 18, RI_E1HE2E3_ONLINE }, { 0xe0280, 1, RI_ALL_ONLINE },
+ { 0xe0300, 1, RI_ALL_ONLINE }, { 0xe1000, 1, RI_ALL_ONLINE },
+ { 0xe2000, 1, RI_ALL_ONLINE }, { 0xe2004, 2047, RI_ALL_OFFLINE },
+ { 0xf0000, 1, RI_ALL_ONLINE }, { 0xf0004, 16383, RI_ALL_OFFLINE },
+ { 0x101000, 12, RI_ALL_ONLINE }, { 0x101050, 1, RI_E1HE2E3_ONLINE },
+ { 0x101054, 3, RI_E2E3_ONLINE }, { 0x101100, 1, RI_ALL_ONLINE },
+ { 0x101800, 8, RI_ALL_ONLINE }, { 0x102000, 18, RI_ALL_ONLINE },
+ { 0x102068, 6, RI_E2E3_ONLINE }, { 0x102080, 17, RI_ALL_ONLINE },
+ { 0x1020c8, 8, RI_E1H_ONLINE }, { 0x1020e8, 9, RI_E2E3_ONLINE },
+ { 0x102400, 1, RI_ALL_ONLINE }, { 0x103000, 26, RI_ALL_ONLINE },
+ { 0x103098, 5, RI_E1HE2E3_ONLINE }, { 0x1030ac, 2, RI_E2E3_ONLINE },
+ { 0x1030b4, 1, RI_E2_ONLINE }, { 0x1030b8, 7, RI_E2E3_ONLINE },
+ { 0x1030d8, 8, RI_E2E3_ONLINE }, { 0x103400, 1, RI_E2E3_ONLINE },
+ { 0x103404, 135, RI_E2E3_OFFLINE }, { 0x103800, 8, RI_ALL_ONLINE },
+ { 0x104000, 63, RI_ALL_ONLINE }, { 0x10411c, 16, RI_E2E3_ONLINE },
+ { 0x104200, 17, RI_ALL_ONLINE }, { 0x104400, 64, RI_ALL_ONLINE },
+ { 0x104500, 192, RI_ALL_OFFLINE }, { 0x104800, 64, RI_ALL_ONLINE },
+ { 0x104900, 192, RI_ALL_OFFLINE }, { 0x105000, 256, RI_ALL_ONLINE },
+ { 0x105400, 768, RI_ALL_OFFLINE }, { 0x107000, 7, RI_E2E3_ONLINE },
+ { 0x10701c, 1, RI_E3_ONLINE }, { 0x108000, 33, RI_E1E1H_ONLINE },
{ 0x1080ac, 5, RI_E1H_ONLINE }, { 0x108100, 5, RI_E1E1H_ONLINE },
{ 0x108120, 5, RI_E1E1H_ONLINE }, { 0x108200, 74, RI_E1E1H_ONLINE },
{ 0x108400, 74, RI_E1E1H_ONLINE }, { 0x108800, 152, RI_E1E1H_ONLINE },
- { 0x110000, 111, RI_E2_ONLINE }, { 0x110200, 4, RI_E2_ONLINE },
- { 0x120000, 2, RI_ALL_ONLINE }, { 0x120008, 4, RI_ALL_ONLINE },
- { 0x120018, 3, RI_ALL_ONLINE }, { 0x120024, 4, RI_ALL_ONLINE },
- { 0x120034, 3, RI_ALL_ONLINE }, { 0x120040, 4, RI_ALL_ONLINE },
- { 0x120050, 3, RI_ALL_ONLINE }, { 0x12005c, 4, RI_ALL_ONLINE },
- { 0x12006c, 3, RI_ALL_ONLINE }, { 0x120078, 4, RI_ALL_ONLINE },
- { 0x120088, 3, RI_ALL_ONLINE }, { 0x120094, 4, RI_ALL_ONLINE },
- { 0x1200a4, 3, RI_ALL_ONLINE }, { 0x1200b0, 4, RI_ALL_ONLINE },
- { 0x1200c0, 3, RI_ALL_ONLINE }, { 0x1200cc, 4, RI_ALL_ONLINE },
- { 0x1200dc, 3, RI_ALL_ONLINE }, { 0x1200e8, 4, RI_ALL_ONLINE },
- { 0x1200f8, 3, RI_ALL_ONLINE }, { 0x120104, 4, RI_ALL_ONLINE },
- { 0x120114, 1, RI_ALL_ONLINE }, { 0x120118, 22, RI_ALL_ONLINE },
- { 0x120170, 2, RI_E1E1H_ONLINE }, { 0x120178, 243, RI_ALL_ONLINE },
- { 0x120544, 4, RI_E1E1H_ONLINE }, { 0x120554, 7, RI_ALL_ONLINE },
- { 0x12059c, 6, RI_E1HE2_ONLINE }, { 0x1205b4, 1, RI_E1HE2_ONLINE },
- { 0x1205b8, 16, RI_E1HE2_ONLINE }, { 0x1205f8, 4, RI_E2_ONLINE },
- { 0x120618, 1, RI_E2_ONLINE }, { 0x12061c, 20, RI_E1HE2_ONLINE },
- { 0x12066c, 11, RI_E1HE2_ONLINE }, { 0x120698, 5, RI_E2_ONLINE },
- { 0x1206b0, 76, RI_E2_ONLINE }, { 0x1207fc, 1, RI_E2_ONLINE },
- { 0x120808, 66, RI_ALL_ONLINE }, { 0x120910, 7, RI_E2_ONLINE },
- { 0x120930, 9, RI_E2_ONLINE }, { 0x120a00, 2, RI_ALL_ONLINE },
- { 0x122000, 2, RI_ALL_ONLINE }, { 0x122008, 2046, RI_E1_OFFLINE },
- { 0x128000, 2, RI_E1HE2_ONLINE }, { 0x128008, 6142, RI_E1HE2_OFFLINE },
- { 0x130000, 35, RI_E2_ONLINE }, { 0x130100, 29, RI_E2_ONLINE },
- { 0x130180, 1, RI_E2_ONLINE }, { 0x130200, 1, RI_E2_ONLINE },
- { 0x130280, 1, RI_E2_ONLINE }, { 0x130300, 5, RI_E2_ONLINE },
- { 0x130380, 1, RI_E2_ONLINE }, { 0x130400, 1, RI_E2_ONLINE },
- { 0x130480, 5, RI_E2_ONLINE }, { 0x130800, 72, RI_E2_ONLINE },
- { 0x131000, 136, RI_E2_ONLINE }, { 0x132000, 148, RI_E2_ONLINE },
- { 0x134000, 544, RI_E2_ONLINE }, { 0x140000, 64, RI_ALL_ONLINE },
- { 0x140100, 5, RI_E1E1H_ONLINE }, { 0x140114, 45, RI_ALL_ONLINE },
- { 0x140200, 6, RI_ALL_ONLINE }, { 0x140220, 4, RI_E2_ONLINE },
- { 0x140240, 4, RI_E2_ONLINE }, { 0x140260, 4, RI_E2_ONLINE },
- { 0x140280, 4, RI_E2_ONLINE }, { 0x1402a0, 4, RI_E2_ONLINE },
- { 0x1402c0, 4, RI_E2_ONLINE }, { 0x1402e0, 13, RI_E2_ONLINE },
- { 0x144000, 4, RI_E1E1H_ONLINE }, { 0x148000, 4, RI_E1E1H_ONLINE },
- { 0x14c000, 4, RI_E1E1H_ONLINE }, { 0x150000, 4, RI_E1E1H_ONLINE },
- { 0x154000, 4, RI_E1E1H_ONLINE }, { 0x158000, 4, RI_E1E1H_ONLINE },
- { 0x15c000, 2, RI_E1HE2_ONLINE }, { 0x15c008, 5, RI_E1H_ONLINE },
- { 0x15c020, 27, RI_E2_ONLINE }, { 0x15c090, 13, RI_E2_ONLINE },
- { 0x15c0c8, 34, RI_E2_ONLINE }, { 0x161000, 7, RI_ALL_ONLINE },
- { 0x16103c, 2, RI_E2_ONLINE }, { 0x161800, 2, RI_ALL_ONLINE },
- { 0x164000, 60, RI_ALL_ONLINE }, { 0x164110, 2, RI_E1HE2_ONLINE },
- { 0x164118, 15, RI_E2_ONLINE }, { 0x164200, 1, RI_ALL_ONLINE },
+ { 0x110000, 111, RI_E2E3_ONLINE }, { 0x1101dc, 1, RI_E3_ONLINE },
+ { 0x110200, 4, RI_E2E3_ONLINE }, { 0x120000, 2, RI_ALL_ONLINE },
+ { 0x120008, 4, RI_ALL_ONLINE }, { 0x120018, 3, RI_ALL_ONLINE },
+ { 0x120024, 4, RI_ALL_ONLINE }, { 0x120034, 3, RI_ALL_ONLINE },
+ { 0x120040, 4, RI_ALL_ONLINE }, { 0x120050, 3, RI_ALL_ONLINE },
+ { 0x12005c, 4, RI_ALL_ONLINE }, { 0x12006c, 3, RI_ALL_ONLINE },
+ { 0x120078, 4, RI_ALL_ONLINE }, { 0x120088, 3, RI_ALL_ONLINE },
+ { 0x120094, 4, RI_ALL_ONLINE }, { 0x1200a4, 3, RI_ALL_ONLINE },
+ { 0x1200b0, 4, RI_ALL_ONLINE }, { 0x1200c0, 3, RI_ALL_ONLINE },
+ { 0x1200cc, 4, RI_ALL_ONLINE }, { 0x1200dc, 3, RI_ALL_ONLINE },
+ { 0x1200e8, 4, RI_ALL_ONLINE }, { 0x1200f8, 3, RI_ALL_ONLINE },
+ { 0x120104, 4, RI_ALL_ONLINE }, { 0x120114, 1, RI_ALL_ONLINE },
+ { 0x120118, 22, RI_ALL_ONLINE }, { 0x120170, 2, RI_E1E1H_ONLINE },
+ { 0x120178, 243, RI_ALL_ONLINE }, { 0x120544, 4, RI_E1E1H_ONLINE },
+ { 0x120554, 6, RI_ALL_ONLINE }, { 0x12059c, 6, RI_E1HE2E3_ONLINE },
+ { 0x1205b4, 1, RI_E1HE2E3_ONLINE }, { 0x1205b8, 15, RI_E1HE2E3_ONLINE },
+ { 0x1205f4, 1, RI_E1HE2_ONLINE }, { 0x1205f8, 4, RI_E2E3_ONLINE },
+ { 0x120618, 1, RI_E2E3_ONLINE }, { 0x12061c, 20, RI_E1HE2E3_ONLINE },
+ { 0x12066c, 11, RI_E1HE2E3_ONLINE }, { 0x120698, 3, RI_E2E3_ONLINE },
+ { 0x1206a4, 1, RI_E2_ONLINE }, { 0x1206a8, 1, RI_E2E3_ONLINE },
+ { 0x1206b0, 75, RI_E2E3_ONLINE }, { 0x1207dc, 1, RI_E2_ONLINE },
+ { 0x1207fc, 1, RI_E2E3_ONLINE }, { 0x12080c, 65, RI_ALL_ONLINE },
+ { 0x120910, 7, RI_E2E3_ONLINE }, { 0x120930, 9, RI_E2E3_ONLINE },
+ { 0x12095c, 37, RI_E3_ONLINE }, { 0x120a00, 2, RI_E1E1HE2_ONLINE },
+ { 0x120b00, 1, RI_E3_ONLINE }, { 0x122000, 2, RI_ALL_ONLINE },
+ { 0x122008, 2046, RI_E1_OFFLINE }, { 0x128000, 2, RI_E1HE2E3_ONLINE },
+ { 0x128008, 6142, RI_E1HE2E3_OFFLINE },
+ { 0x130000, 35, RI_E2E3_ONLINE },
+ { 0x130100, 29, RI_E2E3_ONLINE }, { 0x130180, 1, RI_E2E3_ONLINE },
+ { 0x130200, 1, RI_E2E3_ONLINE }, { 0x130280, 1, RI_E2E3_ONLINE },
+ { 0x130300, 5, RI_E2E3_ONLINE }, { 0x130380, 1, RI_E2E3_ONLINE },
+ { 0x130400, 1, RI_E2E3_ONLINE }, { 0x130480, 5, RI_E2E3_ONLINE },
+ { 0x130800, 72, RI_E2E3_ONLINE }, { 0x131000, 136, RI_E2E3_ONLINE },
+ { 0x132000, 148, RI_E2E3_ONLINE }, { 0x134000, 544, RI_E2E3_ONLINE },
+ { 0x140000, 64, RI_ALL_ONLINE }, { 0x140100, 5, RI_E1E1H_ONLINE },
+ { 0x140114, 45, RI_ALL_ONLINE }, { 0x140200, 6, RI_ALL_ONLINE },
+ { 0x140220, 4, RI_E2E3_ONLINE }, { 0x140240, 4, RI_E2E3_ONLINE },
+ { 0x140260, 4, RI_E2E3_ONLINE }, { 0x140280, 4, RI_E2E3_ONLINE },
+ { 0x1402a0, 4, RI_E2E3_ONLINE }, { 0x1402c0, 4, RI_E2E3_ONLINE },
+ { 0x1402e0, 13, RI_E2E3_ONLINE }, { 0x144000, 4, RI_E1E1H_ONLINE },
+ { 0x148000, 4, RI_E1E1H_ONLINE }, { 0x14c000, 4, RI_E1E1H_ONLINE },
+ { 0x150000, 4, RI_E1E1H_ONLINE }, { 0x154000, 4, RI_E1E1H_ONLINE },
+ { 0x158000, 4, RI_E1E1H_ONLINE }, { 0x15c000, 2, RI_E1HE2E3_ONLINE },
+ { 0x15c008, 5, RI_E1H_ONLINE }, { 0x15c020, 27, RI_E2E3_ONLINE },
+ { 0x15c090, 13, RI_E2E3_ONLINE }, { 0x15c0c8, 34, RI_E2E3_ONLINE },
+ { 0x15c150, 4, RI_E3_ONLINE }, { 0x160004, 6, RI_E3_ONLINE },
+ { 0x160040, 6, RI_E3_ONLINE }, { 0x16005c, 6, RI_E3_ONLINE },
+ { 0x160078, 2, RI_E3_ONLINE }, { 0x160300, 8, RI_E3_ONLINE },
+ { 0x160330, 6, RI_E3_ONLINE }, { 0x160404, 6, RI_E3_ONLINE },
+ { 0x160440, 6, RI_E3_ONLINE }, { 0x16045c, 6, RI_E3_ONLINE },
+ { 0x160478, 2, RI_E3_ONLINE }, { 0x160700, 8, RI_E3_ONLINE },
+ { 0x160730, 6, RI_E3_ONLINE }, { 0x161000, 7, RI_ALL_ONLINE },
+ { 0x16103c, 2, RI_E2E3_ONLINE }, { 0x161800, 2, RI_ALL_ONLINE },
+ { 0x162000, 54, RI_E3_ONLINE }, { 0x162200, 60, RI_E3_ONLINE },
+ { 0x162400, 54, RI_E3_ONLINE }, { 0x162600, 60, RI_E3_ONLINE },
+ { 0x162800, 54, RI_E3_ONLINE }, { 0x162a00, 60, RI_E3_ONLINE },
+ { 0x162c00, 54, RI_E3_ONLINE }, { 0x162e00, 60, RI_E3_ONLINE },
+ { 0x163000, 1, RI_E3_ONLINE }, { 0x163008, 1, RI_E3_ONLINE },
+ { 0x163010, 1, RI_E3_ONLINE }, { 0x163018, 1, RI_E3_ONLINE },
+ { 0x163020, 5, RI_E3_ONLINE }, { 0x163038, 3, RI_E3_ONLINE },
+ { 0x163048, 3, RI_E3_ONLINE }, { 0x163058, 1, RI_E3_ONLINE },
+ { 0x163060, 1, RI_E3_ONLINE }, { 0x163068, 1, RI_E3_ONLINE },
+ { 0x163070, 3, RI_E3_ONLINE }, { 0x163080, 1, RI_E3_ONLINE },
+ { 0x163088, 3, RI_E3_ONLINE }, { 0x163098, 1, RI_E3_ONLINE },
+ { 0x1630a0, 1, RI_E3_ONLINE }, { 0x1630a8, 1, RI_E3_ONLINE },
+ { 0x1630c0, 1, RI_E3_ONLINE }, { 0x1630c8, 1, RI_E3_ONLINE },
+ { 0x1630d0, 1, RI_E3_ONLINE }, { 0x1630d8, 1, RI_E3_ONLINE },
+ { 0x1630e0, 2, RI_E3_ONLINE }, { 0x163110, 1, RI_E3_ONLINE },
+ { 0x163120, 2, RI_E3_ONLINE }, { 0x163420, 4, RI_E3_ONLINE },
+ { 0x163438, 2, RI_E3_ONLINE }, { 0x163488, 2, RI_E3_ONLINE },
+ { 0x163520, 2, RI_E3_ONLINE }, { 0x163800, 1, RI_E3_ONLINE },
+ { 0x163808, 1, RI_E3_ONLINE }, { 0x163810, 1, RI_E3_ONLINE },
+ { 0x163818, 1, RI_E3_ONLINE }, { 0x163820, 5, RI_E3_ONLINE },
+ { 0x163838, 3, RI_E3_ONLINE }, { 0x163848, 3, RI_E3_ONLINE },
+ { 0x163858, 1, RI_E3_ONLINE }, { 0x163860, 1, RI_E3_ONLINE },
+ { 0x163868, 1, RI_E3_ONLINE }, { 0x163870, 3, RI_E3_ONLINE },
+ { 0x163880, 1, RI_E3_ONLINE }, { 0x163888, 3, RI_E3_ONLINE },
+ { 0x163898, 1, RI_E3_ONLINE }, { 0x1638a0, 1, RI_E3_ONLINE },
+ { 0x1638a8, 1, RI_E3_ONLINE }, { 0x1638c0, 1, RI_E3_ONLINE },
+ { 0x1638c8, 1, RI_E3_ONLINE }, { 0x1638d0, 1, RI_E3_ONLINE },
+ { 0x1638d8, 1, RI_E3_ONLINE }, { 0x1638e0, 2, RI_E3_ONLINE },
+ { 0x163910, 1, RI_E3_ONLINE }, { 0x163920, 2, RI_E3_ONLINE },
+ { 0x163c20, 4, RI_E3_ONLINE }, { 0x163c38, 2, RI_E3_ONLINE },
+ { 0x163c88, 2, RI_E3_ONLINE }, { 0x163d20, 2, RI_E3_ONLINE },
+ { 0x164000, 60, RI_ALL_ONLINE }, { 0x164110, 2, RI_E1HE2E3_ONLINE },
+ { 0x164118, 15, RI_E2E3_ONLINE }, { 0x164200, 1, RI_ALL_ONLINE },
{ 0x164208, 1, RI_ALL_ONLINE }, { 0x164210, 1, RI_ALL_ONLINE },
{ 0x164218, 1, RI_ALL_ONLINE }, { 0x164220, 1, RI_ALL_ONLINE },
{ 0x164228, 1, RI_ALL_ONLINE }, { 0x164230, 1, RI_ALL_ONLINE },
@@ -273,9 +364,9 @@
{ 0x164258, 1, RI_ALL_ONLINE }, { 0x164260, 1, RI_ALL_ONLINE },
{ 0x164270, 2, RI_ALL_ONLINE }, { 0x164280, 2, RI_ALL_ONLINE },
{ 0x164800, 2, RI_ALL_ONLINE }, { 0x165000, 2, RI_ALL_ONLINE },
- { 0x166000, 164, RI_ALL_ONLINE }, { 0x1662cc, 7, RI_E2_ONLINE },
+ { 0x166000, 164, RI_ALL_ONLINE }, { 0x1662cc, 7, RI_E2E3_ONLINE },
{ 0x166400, 49, RI_ALL_ONLINE }, { 0x1664c8, 38, RI_ALL_ONLINE },
- { 0x166568, 2, RI_ALL_ONLINE }, { 0x166570, 5, RI_E2_ONLINE },
+ { 0x166568, 2, RI_ALL_ONLINE }, { 0x166570, 5, RI_E2E3_ONLINE },
{ 0x166800, 1, RI_ALL_ONLINE }, { 0x168000, 137, RI_ALL_ONLINE },
{ 0x168224, 2, RI_E1E1H_ONLINE }, { 0x16822c, 29, RI_ALL_ONLINE },
{ 0x1682a0, 12, RI_E1E1H_ONLINE }, { 0x1682d0, 12, RI_ALL_ONLINE },
@@ -285,89 +376,94 @@
{ 0x168a00, 128, RI_ALL_ONLINE }, { 0x16a000, 1, RI_ALL_ONLINE },
{ 0x16a004, 1535, RI_ALL_OFFLINE }, { 0x16c000, 1, RI_ALL_ONLINE },
{ 0x16c004, 1535, RI_ALL_OFFLINE }, { 0x16e000, 16, RI_E1H_ONLINE },
- { 0x16e040, 8, RI_E2_ONLINE }, { 0x16e100, 1, RI_E1H_ONLINE },
+ { 0x16e040, 8, RI_E2E3_ONLINE }, { 0x16e100, 1, RI_E1H_ONLINE },
{ 0x16e200, 2, RI_E1H_ONLINE }, { 0x16e400, 161, RI_E1H_ONLINE },
- { 0x16e684, 2, RI_E1HE2_ONLINE }, { 0x16e68c, 12, RI_E1H_ONLINE },
- { 0x16e6bc, 4, RI_E1HE2_ONLINE }, { 0x16e6cc, 4, RI_E1H_ONLINE },
- { 0x16e6e0, 12, RI_E2_ONLINE }, { 0x16e768, 17, RI_E2_ONLINE },
+ { 0x16e684, 2, RI_E1HE2E3_ONLINE }, { 0x16e68c, 12, RI_E1H_ONLINE },
+ { 0x16e6bc, 4, RI_E1HE2E3_ONLINE }, { 0x16e6cc, 4, RI_E1H_ONLINE },
+ { 0x16e6e0, 12, RI_E2E3_ONLINE }, { 0x16e768, 17, RI_E2E3_ONLINE },
{ 0x170000, 24, RI_ALL_ONLINE }, { 0x170060, 4, RI_E1E1H_ONLINE },
- { 0x170070, 65, RI_ALL_ONLINE }, { 0x170194, 11, RI_E2_ONLINE },
- { 0x1701c4, 1, RI_E2_ONLINE }, { 0x1701cc, 7, RI_E2_ONLINE },
- { 0x1701ec, 1, RI_E2_ONLINE }, { 0x1701f4, 1, RI_E2_ONLINE },
- { 0x170200, 4, RI_ALL_ONLINE }, { 0x170214, 1, RI_ALL_ONLINE },
- { 0x170218, 77, RI_E2_ONLINE }, { 0x170400, 64, RI_E2_ONLINE },
- { 0x178000, 1, RI_ALL_ONLINE }, { 0x180000, 61, RI_ALL_ONLINE },
- { 0x18013c, 2, RI_E1HE2_ONLINE }, { 0x180200, 58, RI_ALL_ONLINE },
- { 0x180340, 4, RI_ALL_ONLINE }, { 0x180380, 1, RI_E2_ONLINE },
- { 0x180388, 1, RI_E2_ONLINE }, { 0x180390, 1, RI_E2_ONLINE },
- { 0x180398, 1, RI_E2_ONLINE }, { 0x1803a0, 5, RI_E2_ONLINE },
+ { 0x170070, 65, RI_ALL_ONLINE }, { 0x170194, 11, RI_E2E3_ONLINE },
+ { 0x1701c4, 1, RI_E2E3_ONLINE }, { 0x1701cc, 7, RI_E2E3_ONLINE },
+ { 0x1701e8, 1, RI_E3_ONLINE }, { 0x1701ec, 1, RI_E2E3_ONLINE },
+ { 0x1701f4, 1, RI_E2E3_ONLINE }, { 0x170200, 4, RI_ALL_ONLINE },
+ { 0x170214, 1, RI_ALL_ONLINE }, { 0x170218, 77, RI_E2E3_ONLINE },
+ { 0x170400, 64, RI_E2E3_ONLINE }, { 0x178000, 1, RI_ALL_ONLINE },
+ { 0x180000, 61, RI_ALL_ONLINE }, { 0x18013c, 2, RI_E1HE2E3_ONLINE },
+ { 0x180200, 58, RI_ALL_ONLINE }, { 0x180340, 4, RI_ALL_ONLINE },
+ { 0x180380, 1, RI_E2E3_ONLINE }, { 0x180388, 1, RI_E2E3_ONLINE },
+ { 0x180390, 1, RI_E2E3_ONLINE }, { 0x180398, 1, RI_E2E3_ONLINE },
+ { 0x1803a0, 5, RI_E2E3_ONLINE }, { 0x1803b4, 2, RI_E3_ONLINE },
{ 0x180400, 1, RI_ALL_ONLINE }, { 0x180404, 255, RI_E1E1H_OFFLINE },
{ 0x181000, 4, RI_ALL_ONLINE }, { 0x181010, 1020, RI_ALL_OFFLINE },
- { 0x1a0000, 1, RI_ALL_ONLINE }, { 0x1a0004, 5631, RI_ALL_OFFLINE },
- { 0x1a5800, 2560, RI_E1HE2_OFFLINE }, { 0x1a8000, 1, RI_ALL_ONLINE },
- { 0x1a8004, 8191, RI_E1HE2_OFFLINE }, { 0x1b0000, 1, RI_ALL_ONLINE },
- { 0x1b0004, 15, RI_E1H_OFFLINE }, { 0x1b0040, 1, RI_E1HE2_ONLINE },
- { 0x1b0044, 239, RI_E1H_OFFLINE }, { 0x1b0400, 1, RI_ALL_ONLINE },
- { 0x1b0404, 255, RI_E1H_OFFLINE }, { 0x1b0800, 1, RI_ALL_ONLINE },
- { 0x1b0840, 1, RI_E1HE2_ONLINE }, { 0x1b0c00, 1, RI_ALL_ONLINE },
- { 0x1b1000, 1, RI_ALL_ONLINE }, { 0x1b1040, 1, RI_E1HE2_ONLINE },
- { 0x1b1400, 1, RI_ALL_ONLINE }, { 0x1b1440, 1, RI_E1HE2_ONLINE },
- { 0x1b1480, 1, RI_E1HE2_ONLINE }, { 0x1b14c0, 1, RI_E1HE2_ONLINE },
- { 0x1b1800, 128, RI_ALL_OFFLINE }, { 0x1b1c00, 128, RI_ALL_OFFLINE },
- { 0x1b2000, 1, RI_ALL_ONLINE }, { 0x1b2400, 1, RI_E1HE2_ONLINE },
- { 0x1b2404, 5631, RI_E2_OFFLINE }, { 0x1b8000, 1, RI_ALL_ONLINE },
- { 0x1b8040, 1, RI_ALL_ONLINE }, { 0x1b8080, 1, RI_ALL_ONLINE },
- { 0x1b80c0, 1, RI_ALL_ONLINE }, { 0x1b8100, 1, RI_ALL_ONLINE },
- { 0x1b8140, 1, RI_ALL_ONLINE }, { 0x1b8180, 1, RI_ALL_ONLINE },
- { 0x1b81c0, 1, RI_ALL_ONLINE }, { 0x1b8200, 1, RI_ALL_ONLINE },
- { 0x1b8240, 1, RI_ALL_ONLINE }, { 0x1b8280, 1, RI_ALL_ONLINE },
- { 0x1b82c0, 1, RI_ALL_ONLINE }, { 0x1b8300, 1, RI_ALL_ONLINE },
- { 0x1b8340, 1, RI_ALL_ONLINE }, { 0x1b8380, 1, RI_ALL_ONLINE },
- { 0x1b83c0, 1, RI_ALL_ONLINE }, { 0x1b8400, 1, RI_ALL_ONLINE },
- { 0x1b8440, 1, RI_ALL_ONLINE }, { 0x1b8480, 1, RI_ALL_ONLINE },
- { 0x1b84c0, 1, RI_ALL_ONLINE }, { 0x1b8500, 1, RI_ALL_ONLINE },
- { 0x1b8540, 1, RI_ALL_ONLINE }, { 0x1b8580, 1, RI_ALL_ONLINE },
- { 0x1b85c0, 19, RI_E2_ONLINE }, { 0x1b8800, 1, RI_ALL_ONLINE },
- { 0x1b8840, 1, RI_ALL_ONLINE }, { 0x1b8880, 1, RI_ALL_ONLINE },
- { 0x1b88c0, 1, RI_ALL_ONLINE }, { 0x1b8900, 1, RI_ALL_ONLINE },
- { 0x1b8940, 1, RI_ALL_ONLINE }, { 0x1b8980, 1, RI_ALL_ONLINE },
- { 0x1b89c0, 1, RI_ALL_ONLINE }, { 0x1b8a00, 1, RI_ALL_ONLINE },
- { 0x1b8a40, 1, RI_ALL_ONLINE }, { 0x1b8a80, 1, RI_ALL_ONLINE },
- { 0x1b8ac0, 1, RI_ALL_ONLINE }, { 0x1b8b00, 1, RI_ALL_ONLINE },
- { 0x1b8b40, 1, RI_ALL_ONLINE }, { 0x1b8b80, 1, RI_ALL_ONLINE },
- { 0x1b8bc0, 1, RI_ALL_ONLINE }, { 0x1b8c00, 1, RI_ALL_ONLINE },
- { 0x1b8c40, 1, RI_ALL_ONLINE }, { 0x1b8c80, 1, RI_ALL_ONLINE },
- { 0x1b8cc0, 1, RI_ALL_ONLINE }, { 0x1b8cc4, 1, RI_E2_ONLINE },
- { 0x1b8d00, 1, RI_ALL_ONLINE }, { 0x1b8d40, 1, RI_ALL_ONLINE },
- { 0x1b8d80, 1, RI_ALL_ONLINE }, { 0x1b8dc0, 1, RI_ALL_ONLINE },
- { 0x1b8e00, 1, RI_ALL_ONLINE }, { 0x1b8e40, 1, RI_ALL_ONLINE },
- { 0x1b8e80, 1, RI_ALL_ONLINE }, { 0x1b8e84, 1, RI_E2_ONLINE },
- { 0x1b8ec0, 1, RI_E1HE2_ONLINE }, { 0x1b8f00, 1, RI_E1HE2_ONLINE },
- { 0x1b8f40, 1, RI_E1HE2_ONLINE }, { 0x1b8f80, 1, RI_E1HE2_ONLINE },
- { 0x1b8fc0, 1, RI_E1HE2_ONLINE }, { 0x1b8fc4, 2, RI_E2_ONLINE },
- { 0x1b8fd0, 6, RI_E2_ONLINE }, { 0x1b9000, 1, RI_E2_ONLINE },
- { 0x1b9040, 3, RI_E2_ONLINE }, { 0x1b9400, 14, RI_E2_ONLINE },
- { 0x1b943c, 19, RI_E2_ONLINE }, { 0x1b9490, 10, RI_E2_ONLINE },
- { 0x1c0000, 2, RI_ALL_ONLINE }, { 0x200000, 65, RI_ALL_ONLINE },
- { 0x20014c, 2, RI_E1HE2_ONLINE }, { 0x200200, 58, RI_ALL_ONLINE },
- { 0x200340, 4, RI_ALL_ONLINE }, { 0x200380, 1, RI_E2_ONLINE },
- { 0x200388, 1, RI_E2_ONLINE }, { 0x200390, 1, RI_E2_ONLINE },
- { 0x200398, 1, RI_E2_ONLINE }, { 0x2003a0, 1, RI_E2_ONLINE },
- { 0x2003a8, 2, RI_E2_ONLINE }, { 0x200400, 1, RI_ALL_ONLINE },
- { 0x200404, 255, RI_E1E1H_OFFLINE }, { 0x202000, 4, RI_ALL_ONLINE },
- { 0x202010, 2044, RI_ALL_OFFLINE }, { 0x220000, 1, RI_ALL_ONLINE },
- { 0x220004, 5631, RI_ALL_OFFLINE }, { 0x225800, 2560, RI_E1HE2_OFFLINE},
- { 0x228000, 1, RI_ALL_ONLINE }, { 0x228004, 8191, RI_E1HE2_OFFLINE },
+ { 0x182000, 4, RI_E3_ONLINE }, { 0x1a0000, 1, RI_ALL_ONLINE },
+ { 0x1a0004, 5631, RI_ALL_OFFLINE },
+ { 0x1a5800, 2560, RI_E1HE2E3_OFFLINE },
+ { 0x1a8000, 1, RI_ALL_ONLINE }, { 0x1a8004, 8191, RI_E1HE2E3_OFFLINE },
+ { 0x1b0000, 1, RI_ALL_ONLINE }, { 0x1b0004, 15, RI_E1H_OFFLINE },
+ { 0x1b0040, 1, RI_E1HE2E3_ONLINE }, { 0x1b0044, 239, RI_E1H_OFFLINE },
+ { 0x1b0400, 1, RI_ALL_ONLINE }, { 0x1b0404, 255, RI_E1H_OFFLINE },
+ { 0x1b0800, 1, RI_ALL_ONLINE }, { 0x1b0840, 1, RI_E1HE2E3_ONLINE },
+ { 0x1b0c00, 1, RI_ALL_ONLINE }, { 0x1b1000, 1, RI_ALL_ONLINE },
+ { 0x1b1040, 1, RI_E1HE2E3_ONLINE }, { 0x1b1400, 1, RI_ALL_ONLINE },
+ { 0x1b1440, 1, RI_E1HE2E3_ONLINE }, { 0x1b1480, 1, RI_E1HE2E3_ONLINE },
+ { 0x1b14c0, 1, RI_E1HE2E3_ONLINE }, { 0x1b1800, 128, RI_ALL_OFFLINE },
+ { 0x1b1c00, 128, RI_ALL_OFFLINE }, { 0x1b2000, 1, RI_ALL_ONLINE },
+ { 0x1b2400, 1, RI_E1HE2E3_ONLINE }, { 0x1b2404, 5631, RI_E2E3_OFFLINE },
+ { 0x1b8000, 1, RI_ALL_ONLINE }, { 0x1b8040, 1, RI_ALL_ONLINE },
+ { 0x1b8080, 1, RI_ALL_ONLINE }, { 0x1b80c0, 1, RI_ALL_ONLINE },
+ { 0x1b8100, 1, RI_ALL_ONLINE }, { 0x1b8140, 1, RI_ALL_ONLINE },
+ { 0x1b8180, 1, RI_ALL_ONLINE }, { 0x1b81c0, 1, RI_ALL_ONLINE },
+ { 0x1b8200, 1, RI_ALL_ONLINE }, { 0x1b8240, 1, RI_ALL_ONLINE },
+ { 0x1b8280, 1, RI_ALL_ONLINE }, { 0x1b82c0, 1, RI_ALL_ONLINE },
+ { 0x1b8300, 1, RI_ALL_ONLINE }, { 0x1b8340, 1, RI_ALL_ONLINE },
+ { 0x1b8380, 1, RI_ALL_ONLINE }, { 0x1b83c0, 1, RI_ALL_ONLINE },
+ { 0x1b8400, 1, RI_ALL_ONLINE }, { 0x1b8440, 1, RI_ALL_ONLINE },
+ { 0x1b8480, 1, RI_ALL_ONLINE }, { 0x1b84c0, 1, RI_ALL_ONLINE },
+ { 0x1b8500, 1, RI_ALL_ONLINE }, { 0x1b8540, 1, RI_ALL_ONLINE },
+ { 0x1b8580, 1, RI_ALL_ONLINE }, { 0x1b85c0, 19, RI_E2E3_ONLINE },
+ { 0x1b8800, 1, RI_ALL_ONLINE }, { 0x1b8840, 1, RI_ALL_ONLINE },
+ { 0x1b8880, 1, RI_ALL_ONLINE }, { 0x1b88c0, 1, RI_ALL_ONLINE },
+ { 0x1b8900, 1, RI_ALL_ONLINE }, { 0x1b8940, 1, RI_ALL_ONLINE },
+ { 0x1b8980, 1, RI_ALL_ONLINE }, { 0x1b89c0, 1, RI_ALL_ONLINE },
+ { 0x1b8a00, 1, RI_ALL_ONLINE }, { 0x1b8a40, 1, RI_ALL_ONLINE },
+ { 0x1b8a80, 1, RI_ALL_ONLINE }, { 0x1b8ac0, 1, RI_ALL_ONLINE },
+ { 0x1b8b00, 1, RI_ALL_ONLINE }, { 0x1b8b40, 1, RI_ALL_ONLINE },
+ { 0x1b8b80, 1, RI_ALL_ONLINE }, { 0x1b8bc0, 1, RI_ALL_ONLINE },
+ { 0x1b8c00, 1, RI_ALL_ONLINE }, { 0x1b8c40, 1, RI_ALL_ONLINE },
+ { 0x1b8c80, 1, RI_ALL_ONLINE }, { 0x1b8cc0, 1, RI_ALL_ONLINE },
+ { 0x1b8cc4, 1, RI_E2E3_ONLINE }, { 0x1b8d00, 1, RI_ALL_ONLINE },
+ { 0x1b8d40, 1, RI_ALL_ONLINE }, { 0x1b8d80, 1, RI_ALL_ONLINE },
+ { 0x1b8dc0, 1, RI_ALL_ONLINE }, { 0x1b8e00, 1, RI_ALL_ONLINE },
+ { 0x1b8e40, 1, RI_ALL_ONLINE }, { 0x1b8e80, 1, RI_ALL_ONLINE },
+ { 0x1b8e84, 1, RI_E2E3_ONLINE }, { 0x1b8ec0, 1, RI_E1HE2E3_ONLINE },
+ { 0x1b8f00, 1, RI_E1HE2E3_ONLINE }, { 0x1b8f40, 1, RI_E1HE2E3_ONLINE },
+ { 0x1b8f80, 1, RI_E1HE2E3_ONLINE }, { 0x1b8fc0, 1, RI_E1HE2E3_ONLINE },
+ { 0x1b8fc4, 2, RI_E2E3_ONLINE }, { 0x1b8fd0, 6, RI_E2E3_ONLINE },
+ { 0x1b8fe8, 2, RI_E3_ONLINE }, { 0x1b9000, 1, RI_E2E3_ONLINE },
+ { 0x1b9040, 3, RI_E2E3_ONLINE }, { 0x1b905c, 1, RI_E3_ONLINE },
+ { 0x1b9400, 14, RI_E2E3_ONLINE }, { 0x1b943c, 19, RI_E2E3_ONLINE },
+ { 0x1b9490, 10, RI_E2E3_ONLINE }, { 0x1c0000, 2, RI_ALL_ONLINE },
+ { 0x200000, 65, RI_ALL_ONLINE }, { 0x20014c, 2, RI_E1HE2E3_ONLINE },
+ { 0x200200, 58, RI_ALL_ONLINE }, { 0x200340, 4, RI_ALL_ONLINE },
+ { 0x200380, 1, RI_E2E3_ONLINE }, { 0x200388, 1, RI_E2E3_ONLINE },
+ { 0x200390, 1, RI_E2E3_ONLINE }, { 0x200398, 1, RI_E2E3_ONLINE },
+ { 0x2003a0, 1, RI_E2E3_ONLINE }, { 0x2003a8, 2, RI_E2E3_ONLINE },
+ { 0x200400, 1, RI_ALL_ONLINE }, { 0x200404, 255, RI_E1E1H_OFFLINE },
+ { 0x202000, 4, RI_ALL_ONLINE }, { 0x202010, 2044, RI_ALL_OFFLINE },
+ { 0x204000, 4, RI_E3_ONLINE }, { 0x220000, 1, RI_ALL_ONLINE },
+ { 0x220004, 5631, RI_ALL_OFFLINE },
+ { 0x225800, 2560, RI_E1HE2E3_OFFLINE },
+ { 0x228000, 1, RI_ALL_ONLINE }, { 0x228004, 8191, RI_E1HE2E3_OFFLINE },
{ 0x230000, 1, RI_ALL_ONLINE }, { 0x230004, 15, RI_E1H_OFFLINE },
- { 0x230040, 1, RI_E1HE2_ONLINE }, { 0x230044, 239, RI_E1H_OFFLINE },
+ { 0x230040, 1, RI_E1HE2E3_ONLINE }, { 0x230044, 239, RI_E1H_OFFLINE },
{ 0x230400, 1, RI_ALL_ONLINE }, { 0x230404, 255, RI_E1H_OFFLINE },
- { 0x230800, 1, RI_ALL_ONLINE }, { 0x230840, 1, RI_E1HE2_ONLINE },
+ { 0x230800, 1, RI_ALL_ONLINE }, { 0x230840, 1, RI_E1HE2E3_ONLINE },
{ 0x230c00, 1, RI_ALL_ONLINE }, { 0x231000, 1, RI_ALL_ONLINE },
- { 0x231040, 1, RI_E1HE2_ONLINE }, { 0x231400, 1, RI_ALL_ONLINE },
- { 0x231440, 1, RI_E1HE2_ONLINE }, { 0x231480, 1, RI_E1HE2_ONLINE },
- { 0x2314c0, 1, RI_E1HE2_ONLINE }, { 0x231800, 128, RI_ALL_OFFLINE },
+ { 0x231040, 1, RI_E1HE2E3_ONLINE }, { 0x231400, 1, RI_ALL_ONLINE },
+ { 0x231440, 1, RI_E1HE2E3_ONLINE }, { 0x231480, 1, RI_E1HE2E3_ONLINE },
+ { 0x2314c0, 1, RI_E1HE2E3_ONLINE }, { 0x231800, 128, RI_ALL_OFFLINE },
{ 0x231c00, 128, RI_ALL_OFFLINE }, { 0x232000, 1, RI_ALL_ONLINE },
- { 0x232400, 1, RI_E1HE2_ONLINE }, { 0x232404, 5631, RI_E2_OFFLINE },
+ { 0x232400, 1, RI_E1HE2E3_ONLINE }, { 0x232404, 5631, RI_E2E3_OFFLINE },
{ 0x238000, 1, RI_ALL_ONLINE }, { 0x238040, 1, RI_ALL_ONLINE },
{ 0x238080, 1, RI_ALL_ONLINE }, { 0x2380c0, 1, RI_ALL_ONLINE },
{ 0x238100, 1, RI_ALL_ONLINE }, { 0x238140, 1, RI_ALL_ONLINE },
@@ -379,7 +475,7 @@
{ 0x238400, 1, RI_ALL_ONLINE }, { 0x238440, 1, RI_ALL_ONLINE },
{ 0x238480, 1, RI_ALL_ONLINE }, { 0x2384c0, 1, RI_ALL_ONLINE },
{ 0x238500, 1, RI_ALL_ONLINE }, { 0x238540, 1, RI_ALL_ONLINE },
- { 0x238580, 1, RI_ALL_ONLINE }, { 0x2385c0, 19, RI_E2_ONLINE },
+ { 0x238580, 1, RI_ALL_ONLINE }, { 0x2385c0, 19, RI_E2E3_ONLINE },
{ 0x238800, 1, RI_ALL_ONLINE }, { 0x238840, 1, RI_ALL_ONLINE },
{ 0x238880, 1, RI_ALL_ONLINE }, { 0x2388c0, 1, RI_ALL_ONLINE },
{ 0x238900, 1, RI_ALL_ONLINE }, { 0x238940, 1, RI_ALL_ONLINE },
@@ -390,88 +486,91 @@
{ 0x238b80, 1, RI_ALL_ONLINE }, { 0x238bc0, 1, RI_ALL_ONLINE },
{ 0x238c00, 1, RI_ALL_ONLINE }, { 0x238c40, 1, RI_ALL_ONLINE },
{ 0x238c80, 1, RI_ALL_ONLINE }, { 0x238cc0, 1, RI_ALL_ONLINE },
- { 0x238cc4, 1, RI_E2_ONLINE }, { 0x238d00, 1, RI_ALL_ONLINE },
+ { 0x238cc4, 1, RI_E2E3_ONLINE }, { 0x238d00, 1, RI_ALL_ONLINE },
{ 0x238d40, 1, RI_ALL_ONLINE }, { 0x238d80, 1, RI_ALL_ONLINE },
{ 0x238dc0, 1, RI_ALL_ONLINE }, { 0x238e00, 1, RI_ALL_ONLINE },
{ 0x238e40, 1, RI_ALL_ONLINE }, { 0x238e80, 1, RI_ALL_ONLINE },
- { 0x238e84, 1, RI_E2_ONLINE }, { 0x238ec0, 1, RI_E1HE2_ONLINE },
- { 0x238f00, 1, RI_E1HE2_ONLINE }, { 0x238f40, 1, RI_E1HE2_ONLINE },
- { 0x238f80, 1, RI_E1HE2_ONLINE }, { 0x238fc0, 1, RI_E1HE2_ONLINE },
- { 0x238fc4, 2, RI_E2_ONLINE }, { 0x238fd0, 6, RI_E2_ONLINE },
- { 0x239000, 1, RI_E2_ONLINE }, { 0x239040, 3, RI_E2_ONLINE },
+ { 0x238e84, 1, RI_E2E3_ONLINE }, { 0x238ec0, 1, RI_E1HE2E3_ONLINE },
+ { 0x238f00, 1, RI_E1HE2E3_ONLINE }, { 0x238f40, 1, RI_E1HE2E3_ONLINE },
+ { 0x238f80, 1, RI_E1HE2E3_ONLINE }, { 0x238fc0, 1, RI_E1HE2E3_ONLINE },
+ { 0x238fc4, 2, RI_E2E3_ONLINE }, { 0x238fd0, 6, RI_E2E3_ONLINE },
+ { 0x238fe8, 2, RI_E3_ONLINE }, { 0x239000, 1, RI_E2E3_ONLINE },
+ { 0x239040, 3, RI_E2E3_ONLINE }, { 0x23905c, 1, RI_E3_ONLINE },
{ 0x240000, 2, RI_ALL_ONLINE }, { 0x280000, 65, RI_ALL_ONLINE },
- { 0x28014c, 2, RI_E1HE2_ONLINE }, { 0x280200, 58, RI_ALL_ONLINE },
- { 0x280340, 4, RI_ALL_ONLINE }, { 0x280380, 1, RI_E2_ONLINE },
- { 0x280388, 1, RI_E2_ONLINE }, { 0x280390, 1, RI_E2_ONLINE },
- { 0x280398, 1, RI_E2_ONLINE }, { 0x2803a0, 1, RI_E2_ONLINE },
- { 0x2803a8, 2, RI_E2_ONLINE }, { 0x280400, 1, RI_ALL_ONLINE },
+ { 0x28014c, 2, RI_E1HE2E3_ONLINE }, { 0x280200, 58, RI_ALL_ONLINE },
+ { 0x280340, 4, RI_ALL_ONLINE }, { 0x280380, 1, RI_E2E3_ONLINE },
+ { 0x280388, 1, RI_E2E3_ONLINE }, { 0x280390, 1, RI_E2E3_ONLINE },
+ { 0x280398, 1, RI_E2E3_ONLINE }, { 0x2803a0, 1, RI_E2E3_ONLINE },
+ { 0x2803a8, 2, RI_E2E3_ONLINE }, { 0x280400, 1, RI_ALL_ONLINE },
{ 0x280404, 255, RI_E1E1H_OFFLINE }, { 0x282000, 4, RI_ALL_ONLINE },
- { 0x282010, 2044, RI_ALL_OFFLINE }, { 0x2a0000, 1, RI_ALL_ONLINE },
- { 0x2a0004, 5631, RI_ALL_OFFLINE }, { 0x2a5800, 2560, RI_E1HE2_OFFLINE},
- { 0x2a8000, 1, RI_ALL_ONLINE }, { 0x2a8004, 8191, RI_E1HE2_OFFLINE },
- { 0x2b0000, 1, RI_ALL_ONLINE }, { 0x2b0004, 15, RI_E1H_OFFLINE },
- { 0x2b0040, 1, RI_E1HE2_ONLINE }, { 0x2b0044, 239, RI_E1H_OFFLINE },
- { 0x2b0400, 1, RI_ALL_ONLINE }, { 0x2b0404, 255, RI_E1H_OFFLINE },
- { 0x2b0800, 1, RI_ALL_ONLINE }, { 0x2b0840, 1, RI_E1HE2_ONLINE },
- { 0x2b0c00, 1, RI_ALL_ONLINE }, { 0x2b1000, 1, RI_ALL_ONLINE },
- { 0x2b1040, 1, RI_E1HE2_ONLINE }, { 0x2b1400, 1, RI_ALL_ONLINE },
- { 0x2b1440, 1, RI_E1HE2_ONLINE }, { 0x2b1480, 1, RI_E1HE2_ONLINE },
- { 0x2b14c0, 1, RI_E1HE2_ONLINE }, { 0x2b1800, 128, RI_ALL_OFFLINE },
- { 0x2b1c00, 128, RI_ALL_OFFLINE }, { 0x2b2000, 1, RI_ALL_ONLINE },
- { 0x2b2400, 1, RI_E1HE2_ONLINE }, { 0x2b2404, 5631, RI_E2_OFFLINE },
- { 0x2b8000, 1, RI_ALL_ONLINE }, { 0x2b8040, 1, RI_ALL_ONLINE },
- { 0x2b8080, 1, RI_ALL_ONLINE }, { 0x2b80c0, 1, RI_ALL_ONLINE },
- { 0x2b8100, 1, RI_ALL_ONLINE }, { 0x2b8140, 1, RI_ALL_ONLINE },
- { 0x2b8180, 1, RI_ALL_ONLINE }, { 0x2b81c0, 1, RI_ALL_ONLINE },
- { 0x2b8200, 1, RI_ALL_ONLINE }, { 0x2b8240, 1, RI_ALL_ONLINE },
- { 0x2b8280, 1, RI_ALL_ONLINE }, { 0x2b82c0, 1, RI_ALL_ONLINE },
- { 0x2b8300, 1, RI_ALL_ONLINE }, { 0x2b8340, 1, RI_ALL_ONLINE },
- { 0x2b8380, 1, RI_ALL_ONLINE }, { 0x2b83c0, 1, RI_ALL_ONLINE },
- { 0x2b8400, 1, RI_ALL_ONLINE }, { 0x2b8440, 1, RI_ALL_ONLINE },
- { 0x2b8480, 1, RI_ALL_ONLINE }, { 0x2b84c0, 1, RI_ALL_ONLINE },
- { 0x2b8500, 1, RI_ALL_ONLINE }, { 0x2b8540, 1, RI_ALL_ONLINE },
- { 0x2b8580, 1, RI_ALL_ONLINE }, { 0x2b85c0, 19, RI_E2_ONLINE },
- { 0x2b8800, 1, RI_ALL_ONLINE }, { 0x2b8840, 1, RI_ALL_ONLINE },
- { 0x2b8880, 1, RI_ALL_ONLINE }, { 0x2b88c0, 1, RI_ALL_ONLINE },
- { 0x2b8900, 1, RI_ALL_ONLINE }, { 0x2b8940, 1, RI_ALL_ONLINE },
- { 0x2b8980, 1, RI_ALL_ONLINE }, { 0x2b89c0, 1, RI_ALL_ONLINE },
- { 0x2b8a00, 1, RI_ALL_ONLINE }, { 0x2b8a40, 1, RI_ALL_ONLINE },
- { 0x2b8a80, 1, RI_ALL_ONLINE }, { 0x2b8ac0, 1, RI_ALL_ONLINE },
- { 0x2b8b00, 1, RI_ALL_ONLINE }, { 0x2b8b40, 1, RI_ALL_ONLINE },
- { 0x2b8b80, 1, RI_ALL_ONLINE }, { 0x2b8bc0, 1, RI_ALL_ONLINE },
- { 0x2b8c00, 1, RI_ALL_ONLINE }, { 0x2b8c40, 1, RI_ALL_ONLINE },
- { 0x2b8c80, 1, RI_ALL_ONLINE }, { 0x2b8cc0, 1, RI_ALL_ONLINE },
- { 0x2b8cc4, 1, RI_E2_ONLINE }, { 0x2b8d00, 1, RI_ALL_ONLINE },
- { 0x2b8d40, 1, RI_ALL_ONLINE }, { 0x2b8d80, 1, RI_ALL_ONLINE },
- { 0x2b8dc0, 1, RI_ALL_ONLINE }, { 0x2b8e00, 1, RI_ALL_ONLINE },
- { 0x2b8e40, 1, RI_ALL_ONLINE }, { 0x2b8e80, 1, RI_ALL_ONLINE },
- { 0x2b8e84, 1, RI_E2_ONLINE }, { 0x2b8ec0, 1, RI_E1HE2_ONLINE },
- { 0x2b8f00, 1, RI_E1HE2_ONLINE }, { 0x2b8f40, 1, RI_E1HE2_ONLINE },
- { 0x2b8f80, 1, RI_E1HE2_ONLINE }, { 0x2b8fc0, 1, RI_E1HE2_ONLINE },
- { 0x2b8fc4, 2, RI_E2_ONLINE }, { 0x2b8fd0, 6, RI_E2_ONLINE },
- { 0x2b9000, 1, RI_E2_ONLINE }, { 0x2b9040, 3, RI_E2_ONLINE },
- { 0x2b9400, 14, RI_E2_ONLINE }, { 0x2b943c, 19, RI_E2_ONLINE },
- { 0x2b9490, 10, RI_E2_ONLINE }, { 0x2c0000, 2, RI_ALL_ONLINE },
- { 0x300000, 65, RI_ALL_ONLINE }, { 0x30014c, 2, RI_E1HE2_ONLINE },
- { 0x300200, 58, RI_ALL_ONLINE }, { 0x300340, 4, RI_ALL_ONLINE },
- { 0x300380, 1, RI_E2_ONLINE }, { 0x300388, 1, RI_E2_ONLINE },
- { 0x300390, 1, RI_E2_ONLINE }, { 0x300398, 1, RI_E2_ONLINE },
- { 0x3003a0, 1, RI_E2_ONLINE }, { 0x3003a8, 2, RI_E2_ONLINE },
- { 0x300400, 1, RI_ALL_ONLINE }, { 0x300404, 255, RI_E1E1H_OFFLINE },
- { 0x302000, 4, RI_ALL_ONLINE }, { 0x302010, 2044, RI_ALL_OFFLINE },
+ { 0x282010, 2044, RI_ALL_OFFLINE }, { 0x284000, 4, RI_E3_ONLINE },
+ { 0x2a0000, 1, RI_ALL_ONLINE }, { 0x2a0004, 5631, RI_ALL_OFFLINE },
+ { 0x2a5800, 2560, RI_E1HE2E3_OFFLINE }, { 0x2a8000, 1, RI_ALL_ONLINE },
+ { 0x2a8004, 8191, RI_E1HE2E3_OFFLINE }, { 0x2b0000, 1, RI_ALL_ONLINE },
+ { 0x2b0004, 15, RI_E1H_OFFLINE }, { 0x2b0040, 1, RI_E1HE2E3_ONLINE },
+ { 0x2b0044, 239, RI_E1H_OFFLINE }, { 0x2b0400, 1, RI_ALL_ONLINE },
+ { 0x2b0404, 255, RI_E1H_OFFLINE }, { 0x2b0800, 1, RI_ALL_ONLINE },
+ { 0x2b0840, 1, RI_E1HE2E3_ONLINE }, { 0x2b0c00, 1, RI_ALL_ONLINE },
+ { 0x2b1000, 1, RI_ALL_ONLINE }, { 0x2b1040, 1, RI_E1HE2E3_ONLINE },
+ { 0x2b1400, 1, RI_ALL_ONLINE }, { 0x2b1440, 1, RI_E1HE2E3_ONLINE },
+ { 0x2b1480, 1, RI_E1HE2E3_ONLINE }, { 0x2b14c0, 1, RI_E1HE2E3_ONLINE },
+ { 0x2b1800, 128, RI_ALL_OFFLINE }, { 0x2b1c00, 128, RI_ALL_OFFLINE },
+ { 0x2b2000, 1, RI_ALL_ONLINE }, { 0x2b2400, 1, RI_E1HE2E3_ONLINE },
+ { 0x2b2404, 5631, RI_E2E3_OFFLINE }, { 0x2b8000, 1, RI_ALL_ONLINE },
+ { 0x2b8040, 1, RI_ALL_ONLINE }, { 0x2b8080, 1, RI_ALL_ONLINE },
+ { 0x2b80c0, 1, RI_ALL_ONLINE }, { 0x2b8100, 1, RI_ALL_ONLINE },
+ { 0x2b8140, 1, RI_ALL_ONLINE }, { 0x2b8180, 1, RI_ALL_ONLINE },
+ { 0x2b81c0, 1, RI_ALL_ONLINE }, { 0x2b8200, 1, RI_ALL_ONLINE },
+ { 0x2b8240, 1, RI_ALL_ONLINE }, { 0x2b8280, 1, RI_ALL_ONLINE },
+ { 0x2b82c0, 1, RI_ALL_ONLINE }, { 0x2b8300, 1, RI_ALL_ONLINE },
+ { 0x2b8340, 1, RI_ALL_ONLINE }, { 0x2b8380, 1, RI_ALL_ONLINE },
+ { 0x2b83c0, 1, RI_ALL_ONLINE }, { 0x2b8400, 1, RI_ALL_ONLINE },
+ { 0x2b8440, 1, RI_ALL_ONLINE }, { 0x2b8480, 1, RI_ALL_ONLINE },
+ { 0x2b84c0, 1, RI_ALL_ONLINE }, { 0x2b8500, 1, RI_ALL_ONLINE },
+ { 0x2b8540, 1, RI_ALL_ONLINE }, { 0x2b8580, 1, RI_ALL_ONLINE },
+ { 0x2b85c0, 19, RI_E2E3_ONLINE }, { 0x2b8800, 1, RI_ALL_ONLINE },
+ { 0x2b8840, 1, RI_ALL_ONLINE }, { 0x2b8880, 1, RI_ALL_ONLINE },
+ { 0x2b88c0, 1, RI_ALL_ONLINE }, { 0x2b8900, 1, RI_ALL_ONLINE },
+ { 0x2b8940, 1, RI_ALL_ONLINE }, { 0x2b8980, 1, RI_ALL_ONLINE },
+ { 0x2b89c0, 1, RI_ALL_ONLINE }, { 0x2b8a00, 1, RI_ALL_ONLINE },
+ { 0x2b8a40, 1, RI_ALL_ONLINE }, { 0x2b8a80, 1, RI_ALL_ONLINE },
+ { 0x2b8ac0, 1, RI_ALL_ONLINE }, { 0x2b8b00, 1, RI_ALL_ONLINE },
+ { 0x2b8b40, 1, RI_ALL_ONLINE }, { 0x2b8b80, 1, RI_ALL_ONLINE },
+ { 0x2b8bc0, 1, RI_ALL_ONLINE }, { 0x2b8c00, 1, RI_ALL_ONLINE },
+ { 0x2b8c40, 1, RI_ALL_ONLINE }, { 0x2b8c80, 1, RI_ALL_ONLINE },
+ { 0x2b8cc0, 1, RI_ALL_ONLINE }, { 0x2b8cc4, 1, RI_E2E3_ONLINE },
+ { 0x2b8d00, 1, RI_ALL_ONLINE }, { 0x2b8d40, 1, RI_ALL_ONLINE },
+ { 0x2b8d80, 1, RI_ALL_ONLINE }, { 0x2b8dc0, 1, RI_ALL_ONLINE },
+ { 0x2b8e00, 1, RI_ALL_ONLINE }, { 0x2b8e40, 1, RI_ALL_ONLINE },
+ { 0x2b8e80, 1, RI_ALL_ONLINE }, { 0x2b8e84, 1, RI_E2E3_ONLINE },
+ { 0x2b8ec0, 1, RI_E1HE2E3_ONLINE }, { 0x2b8f00, 1, RI_E1HE2E3_ONLINE },
+ { 0x2b8f40, 1, RI_E1HE2E3_ONLINE }, { 0x2b8f80, 1, RI_E1HE2E3_ONLINE },
+ { 0x2b8fc0, 1, RI_E1HE2E3_ONLINE }, { 0x2b8fc4, 2, RI_E2E3_ONLINE },
+ { 0x2b8fd0, 6, RI_E2E3_ONLINE }, { 0x2b8fe8, 2, RI_E3_ONLINE },
+ { 0x2b9000, 1, RI_E2E3_ONLINE }, { 0x2b9040, 3, RI_E2E3_ONLINE },
+ { 0x2b905c, 1, RI_E3_ONLINE }, { 0x2b9400, 14, RI_E2E3_ONLINE },
+ { 0x2b943c, 19, RI_E2E3_ONLINE }, { 0x2b9490, 10, RI_E2E3_ONLINE },
+ { 0x2c0000, 2, RI_ALL_ONLINE }, { 0x300000, 65, RI_ALL_ONLINE },
+ { 0x30014c, 2, RI_E1HE2E3_ONLINE }, { 0x300200, 58, RI_ALL_ONLINE },
+ { 0x300340, 4, RI_ALL_ONLINE }, { 0x300380, 1, RI_E2E3_ONLINE },
+ { 0x300388, 1, RI_E2E3_ONLINE }, { 0x300390, 1, RI_E2E3_ONLINE },
+ { 0x300398, 1, RI_E2E3_ONLINE }, { 0x3003a0, 1, RI_E2E3_ONLINE },
+ { 0x3003a8, 2, RI_E2E3_ONLINE }, { 0x300400, 1, RI_ALL_ONLINE },
+ { 0x300404, 255, RI_E1E1H_OFFLINE }, { 0x302000, 4, RI_ALL_ONLINE },
+ { 0x302010, 2044, RI_ALL_OFFLINE }, { 0x304000, 4, RI_E3_ONLINE },
{ 0x320000, 1, RI_ALL_ONLINE }, { 0x320004, 5631, RI_ALL_OFFLINE },
- { 0x325800, 2560, RI_E1HE2_OFFLINE }, { 0x328000, 1, RI_ALL_ONLINE },
- { 0x328004, 8191, RI_E1HE2_OFFLINE }, { 0x330000, 1, RI_ALL_ONLINE },
- { 0x330004, 15, RI_E1H_OFFLINE }, { 0x330040, 1, RI_E1HE2_ONLINE },
+ { 0x325800, 2560, RI_E1HE2E3_OFFLINE }, { 0x328000, 1, RI_ALL_ONLINE },
+ { 0x328004, 8191, RI_E1HE2E3_OFFLINE }, { 0x330000, 1, RI_ALL_ONLINE },
+ { 0x330004, 15, RI_E1H_OFFLINE }, { 0x330040, 1, RI_E1HE2E3_ONLINE },
{ 0x330044, 239, RI_E1H_OFFLINE }, { 0x330400, 1, RI_ALL_ONLINE },
{ 0x330404, 255, RI_E1H_OFFLINE }, { 0x330800, 1, RI_ALL_ONLINE },
- { 0x330840, 1, RI_E1HE2_ONLINE }, { 0x330c00, 1, RI_ALL_ONLINE },
- { 0x331000, 1, RI_ALL_ONLINE }, { 0x331040, 1, RI_E1HE2_ONLINE },
- { 0x331400, 1, RI_ALL_ONLINE }, { 0x331440, 1, RI_E1HE2_ONLINE },
- { 0x331480, 1, RI_E1HE2_ONLINE }, { 0x3314c0, 1, RI_E1HE2_ONLINE },
+ { 0x330840, 1, RI_E1HE2E3_ONLINE }, { 0x330c00, 1, RI_ALL_ONLINE },
+ { 0x331000, 1, RI_ALL_ONLINE }, { 0x331040, 1, RI_E1HE2E3_ONLINE },
+ { 0x331400, 1, RI_ALL_ONLINE }, { 0x331440, 1, RI_E1HE2E3_ONLINE },
+ { 0x331480, 1, RI_E1HE2E3_ONLINE }, { 0x3314c0, 1, RI_E1HE2E3_ONLINE },
{ 0x331800, 128, RI_ALL_OFFLINE }, { 0x331c00, 128, RI_ALL_OFFLINE },
- { 0x332000, 1, RI_ALL_ONLINE }, { 0x332400, 1, RI_E1HE2_ONLINE },
- { 0x332404, 5631, RI_E2_OFFLINE }, { 0x338000, 1, RI_ALL_ONLINE },
+ { 0x332000, 1, RI_ALL_ONLINE }, { 0x332400, 1, RI_E1HE2E3_ONLINE },
+ { 0x332404, 5631, RI_E2E3_OFFLINE }, { 0x338000, 1, RI_ALL_ONLINE },
{ 0x338040, 1, RI_ALL_ONLINE }, { 0x338080, 1, RI_ALL_ONLINE },
{ 0x3380c0, 1, RI_ALL_ONLINE }, { 0x338100, 1, RI_ALL_ONLINE },
{ 0x338140, 1, RI_ALL_ONLINE }, { 0x338180, 1, RI_ALL_ONLINE },
@@ -483,7 +582,7 @@
{ 0x338440, 1, RI_ALL_ONLINE }, { 0x338480, 1, RI_ALL_ONLINE },
{ 0x3384c0, 1, RI_ALL_ONLINE }, { 0x338500, 1, RI_ALL_ONLINE },
{ 0x338540, 1, RI_ALL_ONLINE }, { 0x338580, 1, RI_ALL_ONLINE },
- { 0x3385c0, 19, RI_E2_ONLINE }, { 0x338800, 1, RI_ALL_ONLINE },
+ { 0x3385c0, 19, RI_E2E3_ONLINE }, { 0x338800, 1, RI_ALL_ONLINE },
{ 0x338840, 1, RI_ALL_ONLINE }, { 0x338880, 1, RI_ALL_ONLINE },
{ 0x3388c0, 1, RI_ALL_ONLINE }, { 0x338900, 1, RI_ALL_ONLINE },
{ 0x338940, 1, RI_ALL_ONLINE }, { 0x338980, 1, RI_ALL_ONLINE },
@@ -493,35 +592,48 @@
{ 0x338b40, 1, RI_ALL_ONLINE }, { 0x338b80, 1, RI_ALL_ONLINE },
{ 0x338bc0, 1, RI_ALL_ONLINE }, { 0x338c00, 1, RI_ALL_ONLINE },
{ 0x338c40, 1, RI_ALL_ONLINE }, { 0x338c80, 1, RI_ALL_ONLINE },
- { 0x338cc0, 1, RI_ALL_ONLINE }, { 0x338cc4, 1, RI_E2_ONLINE },
+ { 0x338cc0, 1, RI_ALL_ONLINE }, { 0x338cc4, 1, RI_E2E3_ONLINE },
{ 0x338d00, 1, RI_ALL_ONLINE }, { 0x338d40, 1, RI_ALL_ONLINE },
{ 0x338d80, 1, RI_ALL_ONLINE }, { 0x338dc0, 1, RI_ALL_ONLINE },
{ 0x338e00, 1, RI_ALL_ONLINE }, { 0x338e40, 1, RI_ALL_ONLINE },
- { 0x338e80, 1, RI_ALL_ONLINE }, { 0x338e84, 1, RI_E2_ONLINE },
- { 0x338ec0, 1, RI_E1HE2_ONLINE }, { 0x338f00, 1, RI_E1HE2_ONLINE },
- { 0x338f40, 1, RI_E1HE2_ONLINE }, { 0x338f80, 1, RI_E1HE2_ONLINE },
- { 0x338fc0, 1, RI_E1HE2_ONLINE }, { 0x338fc4, 2, RI_E2_ONLINE },
- { 0x338fd0, 6, RI_E2_ONLINE }, { 0x339000, 1, RI_E2_ONLINE },
- { 0x339040, 3, RI_E2_ONLINE }, { 0x340000, 2, RI_ALL_ONLINE },
+ { 0x338e80, 1, RI_ALL_ONLINE }, { 0x338e84, 1, RI_E2E3_ONLINE },
+ { 0x338ec0, 1, RI_E1HE2E3_ONLINE }, { 0x338f00, 1, RI_E1HE2E3_ONLINE },
+ { 0x338f40, 1, RI_E1HE2E3_ONLINE }, { 0x338f80, 1, RI_E1HE2E3_ONLINE },
+ { 0x338fc0, 1, RI_E1HE2E3_ONLINE }, { 0x338fc4, 2, RI_E2E3_ONLINE },
+ { 0x338fd0, 6, RI_E2E3_ONLINE }, { 0x338fe8, 2, RI_E3_ONLINE },
+ { 0x339000, 1, RI_E2E3_ONLINE }, { 0x339040, 3, RI_E2E3_ONLINE },
+ { 0x33905c, 1, RI_E3_ONLINE }, { 0x340000, 2, RI_ALL_ONLINE },
};
+#define REGS_COUNT ARRAY_SIZE(reg_addrs)
-#define IDLE_REGS_COUNT 237
-static const struct reg_addr idle_addrs[IDLE_REGS_COUNT] = {
+static const struct reg_addr idle_addrs[] = {
{ 0x2104, 1, RI_ALL_ONLINE }, { 0x2110, 2, RI_ALL_ONLINE },
{ 0x211c, 8, RI_ALL_ONLINE }, { 0x2814, 1, RI_ALL_ONLINE },
{ 0x281c, 2, RI_ALL_ONLINE }, { 0x2854, 1, RI_ALL_ONLINE },
- { 0x285c, 1, RI_ALL_ONLINE }, { 0x9010, 7, RI_E2_ONLINE },
- { 0x9030, 1, RI_E2_ONLINE }, { 0x9068, 16, RI_E2_ONLINE },
- { 0x9230, 2, RI_E2_ONLINE }, { 0x9244, 1, RI_E2_ONLINE },
- { 0x9298, 1, RI_E2_ONLINE }, { 0x92a8, 1, RI_E2_ONLINE },
- { 0xa38c, 1, RI_ALL_ONLINE }, { 0xa3c4, 1, RI_E1HE2_ONLINE },
- { 0xa408, 1, RI_ALL_ONLINE }, { 0xa42c, 12, RI_ALL_ONLINE },
- { 0xa600, 5, RI_E1HE2_ONLINE }, { 0xa618, 1, RI_E1HE2_ONLINE },
- { 0xa714, 1, RI_E2_ONLINE }, { 0xa720, 1, RI_E2_ONLINE },
- { 0xa750, 1, RI_E2_ONLINE }, { 0xc09c, 1, RI_E1E1H_ONLINE },
- { 0x103b0, 1, RI_ALL_ONLINE }, { 0x103c0, 1, RI_ALL_ONLINE },
- { 0x103d0, 1, RI_E1H_ONLINE }, { 0x183bc, 1, RI_E2_ONLINE },
- { 0x183cc, 1, RI_E2_ONLINE }, { 0x2021c, 11, RI_ALL_ONLINE },
+ { 0x285c, 1, RI_ALL_ONLINE }, { 0x3040, 1, RI_ALL_ONLINE },
+ { 0x9010, 7, RI_E2E3_ONLINE }, { 0x9030, 1, RI_E2E3_ONLINE },
+ { 0x9068, 16, RI_E2E3_ONLINE }, { 0x9230, 2, RI_E2E3_ONLINE },
+ { 0x9244, 1, RI_E2E3_ONLINE }, { 0x9298, 1, RI_E2E3_ONLINE },
+ { 0x92a8, 1, RI_E2E3_ONLINE }, { 0xa38c, 1, RI_ALL_ONLINE },
+ { 0xa3c4, 1, RI_E1HE2E3_ONLINE }, { 0xa404, 3, RI_ALL_ONLINE },
+ { 0xa42c, 12, RI_ALL_ONLINE }, { 0xa600, 5, RI_E1HE2E3_ONLINE },
+ { 0xa618, 1, RI_E1HE2E3_ONLINE }, { 0xa714, 1, RI_E2E3_ONLINE },
+ { 0xa720, 1, RI_E2E3_ONLINE }, { 0xa750, 1, RI_E2E3_ONLINE },
+ { 0xc09c, 1, RI_E1E1H_ONLINE }, { 0x103b0, 1, RI_ALL_ONLINE },
+ { 0x103c0, 1, RI_ALL_ONLINE }, { 0x103d0, 1, RI_E1H_ONLINE },
+ { 0x10418, 1, RI_ALL_ONLINE }, { 0x10420, 1, RI_ALL_ONLINE },
+ { 0x10428, 1, RI_ALL_ONLINE }, { 0x10460, 1, RI_ALL_ONLINE },
+ { 0x10474, 1, RI_ALL_ONLINE }, { 0x104e0, 1, RI_ALL_ONLINE },
+ { 0x104ec, 1, RI_ALL_ONLINE }, { 0x104f8, 1, RI_ALL_ONLINE },
+ { 0x10508, 1, RI_ALL_ONLINE }, { 0x10530, 1, RI_ALL_ONLINE },
+ { 0x10538, 1, RI_ALL_ONLINE }, { 0x10548, 1, RI_ALL_ONLINE },
+ { 0x10558, 1, RI_ALL_ONLINE }, { 0x182a8, 1, RI_E2E3_ONLINE },
+ { 0x182b8, 1, RI_E2E3_ONLINE }, { 0x18308, 1, RI_E2E3_ONLINE },
+ { 0x18318, 1, RI_E2E3_ONLINE }, { 0x18338, 1, RI_E2E3_ONLINE },
+ { 0x18348, 1, RI_E2E3_ONLINE }, { 0x183bc, 1, RI_E2E3_ONLINE },
+ { 0x183cc, 1, RI_E2E3_ONLINE }, { 0x18570, 1, RI_E3_ONLINE },
+ { 0x18578, 1, RI_E3_ONLINE }, { 0x1858c, 1, RI_E3_ONLINE },
+ { 0x18594, 1, RI_E3_ONLINE }, { 0x2021c, 11, RI_ALL_ONLINE },
{ 0x202a8, 1, RI_ALL_ONLINE }, { 0x202b8, 1, RI_ALL_ONLINE },
{ 0x20404, 1, RI_ALL_ONLINE }, { 0x2040c, 2, RI_ALL_ONLINE },
{ 0x2041c, 2, RI_ALL_ONLINE }, { 0x40154, 14, RI_ALL_ONLINE },
@@ -551,8 +663,8 @@
{ 0x102058, 1, RI_ALL_ONLINE }, { 0x102080, 16, RI_ALL_ONLINE },
{ 0x103004, 2, RI_ALL_ONLINE }, { 0x103068, 1, RI_ALL_ONLINE },
{ 0x103078, 1, RI_ALL_ONLINE }, { 0x103088, 1, RI_ALL_ONLINE },
- { 0x10309c, 2, RI_E1HE2_ONLINE }, { 0x1030b8, 2, RI_E2_ONLINE },
- { 0x1030cc, 1, RI_E2_ONLINE }, { 0x1030e0, 1, RI_E2_ONLINE },
+ { 0x10309c, 2, RI_E1HE2E3_ONLINE }, { 0x1030b8, 2, RI_E2E3_ONLINE },
+ { 0x1030cc, 1, RI_E2E3_ONLINE }, { 0x1030e0, 1, RI_E2E3_ONLINE },
{ 0x104004, 1, RI_ALL_ONLINE }, { 0x104018, 1, RI_ALL_ONLINE },
{ 0x104020, 1, RI_ALL_ONLINE }, { 0x10403c, 1, RI_ALL_ONLINE },
{ 0x1040fc, 1, RI_ALL_ONLINE }, { 0x10410c, 1, RI_ALL_ONLINE },
@@ -563,28 +675,27 @@
{ 0x120414, 15, RI_ALL_ONLINE }, { 0x120478, 2, RI_ALL_ONLINE },
{ 0x12052c, 1, RI_ALL_ONLINE }, { 0x120564, 3, RI_ALL_ONLINE },
{ 0x12057c, 1, RI_ALL_ONLINE }, { 0x12058c, 1, RI_ALL_ONLINE },
- { 0x120608, 1, RI_E1HE2_ONLINE }, { 0x120738, 1, RI_E2_ONLINE },
- { 0x120778, 2, RI_E2_ONLINE }, { 0x120808, 3, RI_ALL_ONLINE },
- { 0x120818, 1, RI_ALL_ONLINE }, { 0x120820, 1, RI_ALL_ONLINE },
- { 0x120828, 1, RI_ALL_ONLINE }, { 0x120830, 1, RI_ALL_ONLINE },
- { 0x120838, 1, RI_ALL_ONLINE }, { 0x120840, 1, RI_ALL_ONLINE },
- { 0x120848, 1, RI_ALL_ONLINE }, { 0x120850, 1, RI_ALL_ONLINE },
- { 0x120858, 1, RI_ALL_ONLINE }, { 0x120860, 1, RI_ALL_ONLINE },
- { 0x120868, 1, RI_ALL_ONLINE }, { 0x120870, 1, RI_ALL_ONLINE },
- { 0x120878, 1, RI_ALL_ONLINE }, { 0x120880, 1, RI_ALL_ONLINE },
- { 0x120888, 1, RI_ALL_ONLINE }, { 0x120890, 1, RI_ALL_ONLINE },
- { 0x120898, 1, RI_ALL_ONLINE }, { 0x1208a0, 1, RI_ALL_ONLINE },
- { 0x1208a8, 1, RI_ALL_ONLINE }, { 0x1208b0, 1, RI_ALL_ONLINE },
- { 0x1208b8, 1, RI_ALL_ONLINE }, { 0x1208c0, 1, RI_ALL_ONLINE },
- { 0x1208c8, 1, RI_ALL_ONLINE }, { 0x1208d0, 1, RI_ALL_ONLINE },
- { 0x1208d8, 1, RI_ALL_ONLINE }, { 0x1208e0, 1, RI_ALL_ONLINE },
- { 0x1208e8, 1, RI_ALL_ONLINE }, { 0x1208f0, 1, RI_ALL_ONLINE },
- { 0x1208f8, 1, RI_ALL_ONLINE }, { 0x120900, 1, RI_ALL_ONLINE },
- { 0x120908, 1, RI_ALL_ONLINE }, { 0x120940, 5, RI_E2_ONLINE },
- { 0x130030, 1, RI_E2_ONLINE }, { 0x13004c, 3, RI_E2_ONLINE },
- { 0x130064, 2, RI_E2_ONLINE }, { 0x13009c, 1, RI_E2_ONLINE },
- { 0x130130, 1, RI_E2_ONLINE }, { 0x13016c, 1, RI_E2_ONLINE },
- { 0x130300, 1, RI_E2_ONLINE }, { 0x130480, 1, RI_E2_ONLINE },
+ { 0x120608, 1, RI_E1HE2E3_ONLINE }, { 0x120778, 2, RI_E2E3_ONLINE },
+ { 0x120808, 3, RI_ALL_ONLINE }, { 0x120818, 1, RI_ALL_ONLINE },
+ { 0x120820, 1, RI_ALL_ONLINE }, { 0x120828, 1, RI_ALL_ONLINE },
+ { 0x120830, 1, RI_ALL_ONLINE }, { 0x120838, 1, RI_ALL_ONLINE },
+ { 0x120840, 1, RI_ALL_ONLINE }, { 0x120848, 1, RI_ALL_ONLINE },
+ { 0x120850, 1, RI_ALL_ONLINE }, { 0x120858, 1, RI_ALL_ONLINE },
+ { 0x120860, 1, RI_ALL_ONLINE }, { 0x120868, 1, RI_ALL_ONLINE },
+ { 0x120870, 1, RI_ALL_ONLINE }, { 0x120878, 1, RI_ALL_ONLINE },
+ { 0x120880, 1, RI_ALL_ONLINE }, { 0x120888, 1, RI_ALL_ONLINE },
+ { 0x120890, 1, RI_ALL_ONLINE }, { 0x120898, 1, RI_ALL_ONLINE },
+ { 0x1208a0, 1, RI_ALL_ONLINE }, { 0x1208a8, 1, RI_ALL_ONLINE },
+ { 0x1208b0, 1, RI_ALL_ONLINE }, { 0x1208b8, 1, RI_ALL_ONLINE },
+ { 0x1208c0, 1, RI_ALL_ONLINE }, { 0x1208c8, 1, RI_ALL_ONLINE },
+ { 0x1208d0, 1, RI_ALL_ONLINE }, { 0x1208d8, 1, RI_ALL_ONLINE },
+ { 0x1208e0, 1, RI_ALL_ONLINE }, { 0x1208e8, 1, RI_ALL_ONLINE },
+ { 0x1208f0, 1, RI_ALL_ONLINE }, { 0x1208f8, 1, RI_ALL_ONLINE },
+ { 0x120900, 1, RI_ALL_ONLINE }, { 0x120908, 1, RI_ALL_ONLINE },
+ { 0x130030, 1, RI_E2E3_ONLINE }, { 0x13004c, 3, RI_E2E3_ONLINE },
+ { 0x130064, 2, RI_E2E3_ONLINE }, { 0x13009c, 1, RI_E2E3_ONLINE },
+ { 0x130130, 1, RI_E2E3_ONLINE }, { 0x13016c, 1, RI_E2E3_ONLINE },
+ { 0x130300, 1, RI_E2E3_ONLINE }, { 0x130480, 1, RI_E2E3_ONLINE },
{ 0x14005c, 2, RI_ALL_ONLINE }, { 0x1400d0, 2, RI_ALL_ONLINE },
{ 0x1400e0, 1, RI_ALL_ONLINE }, { 0x1401c8, 1, RI_ALL_ONLINE },
{ 0x140200, 6, RI_ALL_ONLINE }, { 0x16101c, 1, RI_ALL_ONLINE },
@@ -602,8 +713,8 @@
{ 0x168438, 1, RI_ALL_ONLINE }, { 0x168448, 1, RI_ALL_ONLINE },
{ 0x168a00, 128, RI_ALL_ONLINE }, { 0x16e200, 128, RI_E1H_ONLINE },
{ 0x16e404, 2, RI_E1H_ONLINE }, { 0x16e584, 64, RI_E1H_ONLINE },
- { 0x16e684, 2, RI_E1HE2_ONLINE }, { 0x16e68c, 4, RI_E1H_ONLINE },
- { 0x16e6fc, 4, RI_E2_ONLINE }, { 0x1700a4, 1, RI_ALL_ONLINE },
+ { 0x16e684, 2, RI_E1HE2E3_ONLINE }, { 0x16e68c, 4, RI_E1H_ONLINE },
+ { 0x16e6fc, 4, RI_E2E3_ONLINE }, { 0x1700a4, 1, RI_ALL_ONLINE },
{ 0x1700ac, 2, RI_ALL_ONLINE }, { 0x1700c0, 1, RI_ALL_ONLINE },
{ 0x170174, 1, RI_ALL_ONLINE }, { 0x170184, 1, RI_ALL_ONLINE },
{ 0x1800f4, 1, RI_ALL_ONLINE }, { 0x180104, 1, RI_ALL_ONLINE },
@@ -627,51 +738,61 @@
{ 0x338040, 1, RI_ALL_ONLINE }, { 0x338080, 1, RI_ALL_ONLINE },
{ 0x3380c0, 1, RI_ALL_ONLINE }
};
+#define IDLE_REGS_COUNT ARRAY_SIZE(idle_addrs)
-#define WREGS_COUNT_E1 1
static const u32 read_reg_e1_0[] = { 0x1b1000 };
+#define WREGS_COUNT_E1 ARRAY_SIZE(read_reg_e1_0)
static const struct wreg_addr wreg_addrs_e1[WREGS_COUNT_E1] = {
{ 0x1b0c00, 192, 1, read_reg_e1_0, RI_E1_OFFLINE }
};
-#define WREGS_COUNT_E1H 1
static const u32 read_reg_e1h_0[] = { 0x1b1040, 0x1b1000 };
+#define WREGS_COUNT_E1H ARRAY_SIZE(read_reg_e1h_0)
static const struct wreg_addr wreg_addrs_e1h[WREGS_COUNT_E1H] = {
{ 0x1b0c00, 256, 2, read_reg_e1h_0, RI_E1H_OFFLINE }
};
-#define WREGS_COUNT_E2 1
static const u32 read_reg_e2_0[] = { 0x1b1040, 0x1b1000 };
+#define WREGS_COUNT_E2 ARRAY_SIZE(read_reg_e2_0)
static const struct wreg_addr wreg_addrs_e2[WREGS_COUNT_E2] = {
{ 0x1b0c00, 128, 2, read_reg_e2_0, RI_E2_OFFLINE }
};
-static const struct dump_sign dump_sign_all = { 0x4d18b0a4, 0x60010, 0x3a };
+static const u32 read_reg_e3_0[] = { 0x1b1040, 0x1b1000 };
+#define WREGS_COUNT_E3 ARRAY_SIZE(read_reg_e3_0)
-#define TIMER_REGS_COUNT_E1 2
+static const struct wreg_addr wreg_addrs_e3[WREGS_COUNT_E3] = {
+ { 0x1b0c00, 128, 2, read_reg_e3_0, RI_E3_OFFLINE } };
-static const u32 timer_status_regs_e1[TIMER_REGS_COUNT_E1] = {
- 0x164014, 0x164018 };
+static const struct dump_sign dump_sign_all = { 0x4dbe9fca, 0x60011, 0x3a };
+
+static const u32 timer_status_regs_e1[] = { 0x164014, 0x164018 };
+#define TIMER_REGS_COUNT_E1 ARRAY_SIZE(timer_status_regs_e1)
+
static const u32 timer_scan_regs_e1[TIMER_REGS_COUNT_E1] = {
0x1640d0, 0x1640d4 };
-#define TIMER_REGS_COUNT_E1H 2
+static const u32 timer_status_regs_e1h[] = { 0x164014, 0x164018 };
+#define TIMER_REGS_COUNT_E1H ARRAY_SIZE(timer_status_regs_e1h)
-static const u32 timer_status_regs_e1h[TIMER_REGS_COUNT_E1H] = {
- 0x164014, 0x164018 };
static const u32 timer_scan_regs_e1h[TIMER_REGS_COUNT_E1H] = {
0x1640d0, 0x1640d4 };
-#define TIMER_REGS_COUNT_E2 2
+static const u32 timer_status_regs_e2[] = { 0x164014, 0x164018 };
+#define TIMER_REGS_COUNT_E2 ARRAY_SIZE(timer_status_regs_e2)
-static const u32 timer_status_regs_e2[TIMER_REGS_COUNT_E2] = {
- 0x164014, 0x164018 };
static const u32 timer_scan_regs_e2[TIMER_REGS_COUNT_E2] = {
0x1640d0, 0x1640d4 };
+static const u32 timer_status_regs_e3[] = { 0x164014, 0x164018 };
+#define TIMER_REGS_COUNT_E3 ARRAY_SIZE(timer_status_regs_e3)
+
+static const u32 timer_scan_regs_e3[TIMER_REGS_COUNT_E3] = {
+ 0x1640d0, 0x1640d4 };
+
#define PAGE_MODE_VALUES_E1 0
#define PAGE_READ_REGS_E1 0
@@ -682,7 +803,8 @@
static const u32 page_write_regs_e1[] = { 0 };
-static const struct reg_addr page_read_regs_e1[] = { { 0x0, 0, RI_E1_ONLINE } };
+static const struct reg_addr page_read_regs_e1[] = {
+ { 0x0, 0, RI_E1_ONLINE } };
#define PAGE_MODE_VALUES_E1H 0
@@ -697,17 +819,24 @@
static const struct reg_addr page_read_regs_e1h[] = {
{ 0x0, 0, RI_E1H_ONLINE } };
-#define PAGE_MODE_VALUES_E2 2
+static const u32 page_vals_e2[] = { 0, 128 };
+#define PAGE_MODE_VALUES_E2 ARRAY_SIZE(page_vals_e2)
-#define PAGE_READ_REGS_E2 1
+static const u32 page_write_regs_e2[] = { 328476 };
+#define PAGE_WRITE_REGS_E2 ARRAY_SIZE(page_write_regs_e2)
-#define PAGE_WRITE_REGS_E2 1
-
-static const u32 page_vals_e2[PAGE_MODE_VALUES_E2] = { 0, 128 };
-
-static const u32 page_write_regs_e2[PAGE_WRITE_REGS_E2] = { 328476 };
-
-static const struct reg_addr page_read_regs_e2[PAGE_READ_REGS_E2] = {
+static const struct reg_addr page_read_regs_e2[] = {
{ 0x58000, 4608, RI_E2_ONLINE } };
+#define PAGE_READ_REGS_E2 ARRAY_SIZE(page_read_regs_e2)
+
+static const u32 page_vals_e3[] = { 0, 128 };
+#define PAGE_MODE_VALUES_E3 ARRAY_SIZE(page_vals_e3)
+
+static const u32 page_write_regs_e3[] = { 328476 };
+#define PAGE_WRITE_REGS_E3 ARRAY_SIZE(page_write_regs_e3)
+
+static const struct reg_addr page_read_regs_e3[] = {
+ { 0x58000, 4608, RI_E3_ONLINE } };
+#define PAGE_READ_REGS_E3 ARRAY_SIZE(page_read_regs_e3)
#endif /* BNX2X_DUMP_H */
diff --git a/drivers/net/bnx2x/bnx2x_ethtool.c b/drivers/net/bnx2x/bnx2x_ethtool.c
index 727fe89..1a3ed41 100644
--- a/drivers/net/bnx2x/bnx2x_ethtool.c
+++ b/drivers/net/bnx2x/bnx2x_ethtool.c
@@ -25,6 +25,7 @@
#include "bnx2x_cmn.h"
#include "bnx2x_dump.h"
#include "bnx2x_init.h"
+#include "bnx2x_sp.h"
/* Note: in the format strings below %s is replaced by the queue-name which is
* either its index or 'fcoe' for the fcoe queue. Make sure the format string
@@ -37,8 +38,6 @@
char string[ETH_GSTRING_LEN];
} bnx2x_q_stats_arr[] = {
/* 1 */ { Q_STATS_OFFSET32(total_bytes_received_hi), 8, "[%s]: rx_bytes" },
- { Q_STATS_OFFSET32(error_bytes_received_hi),
- 8, "[%s]: rx_error_bytes" },
{ Q_STATS_OFFSET32(total_unicast_packets_received_hi),
8, "[%s]: rx_ucast_packets" },
{ Q_STATS_OFFSET32(total_multicast_packets_received_hi),
@@ -52,13 +51,18 @@
4, "[%s]: rx_skb_alloc_discard" },
{ Q_STATS_OFFSET32(hw_csum_err), 4, "[%s]: rx_csum_offload_errors" },
-/* 10 */{ Q_STATS_OFFSET32(total_bytes_transmitted_hi), 8, "[%s]: tx_bytes" },
- { Q_STATS_OFFSET32(total_unicast_packets_transmitted_hi),
+ { Q_STATS_OFFSET32(total_bytes_transmitted_hi), 8, "[%s]: tx_bytes" },
+/* 10 */{ Q_STATS_OFFSET32(total_unicast_packets_transmitted_hi),
8, "[%s]: tx_ucast_packets" },
{ Q_STATS_OFFSET32(total_multicast_packets_transmitted_hi),
8, "[%s]: tx_mcast_packets" },
{ Q_STATS_OFFSET32(total_broadcast_packets_transmitted_hi),
- 8, "[%s]: tx_bcast_packets" }
+ 8, "[%s]: tx_bcast_packets" },
+ { Q_STATS_OFFSET32(total_tpa_aggregations_hi),
+ 8, "[%s]: tpa_aggregations" },
+ { Q_STATS_OFFSET32(total_tpa_aggregated_frames_hi),
+ 8, "[%s]: tpa_aggregated_frames"},
+ { Q_STATS_OFFSET32(total_tpa_bytes_hi), 8, "[%s]: tpa_bytes"}
};
#define BNX2X_NUM_Q_STATS ARRAY_SIZE(bnx2x_q_stats_arr)
@@ -98,8 +102,8 @@
8, STATS_FLAGS_BOTH, "rx_discards" },
{ STATS_OFFSET32(mac_filter_discard),
4, STATS_FLAGS_PORT, "rx_filtered_packets" },
- { STATS_OFFSET32(xxoverflow_discard),
- 4, STATS_FLAGS_PORT, "rx_fw_discards" },
+ { STATS_OFFSET32(mf_tag_discard),
+ 4, STATS_FLAGS_PORT, "rx_mf_tag_discard" },
{ STATS_OFFSET32(brb_drop_hi),
8, STATS_FLAGS_PORT, "rx_brb_discard" },
{ STATS_OFFSET32(brb_truncate_hi),
@@ -158,10 +162,43 @@
{ STATS_OFFSET32(etherstatspktsover1522octets_hi),
8, STATS_FLAGS_PORT, "tx_1523_to_9022_byte_packets" },
{ STATS_OFFSET32(pause_frames_sent_hi),
- 8, STATS_FLAGS_PORT, "tx_pause_frames" }
+ 8, STATS_FLAGS_PORT, "tx_pause_frames" },
+ { STATS_OFFSET32(total_tpa_aggregations_hi),
+ 8, STATS_FLAGS_FUNC, "tpa_aggregations" },
+ { STATS_OFFSET32(total_tpa_aggregated_frames_hi),
+ 8, STATS_FLAGS_FUNC, "tpa_aggregated_frames"},
+ { STATS_OFFSET32(total_tpa_bytes_hi),
+ 8, STATS_FLAGS_FUNC, "tpa_bytes"}
};
#define BNX2X_NUM_STATS ARRAY_SIZE(bnx2x_stats_arr)
+static int bnx2x_get_port_type(struct bnx2x *bp)
+{
+ int port_type;
+ u32 phy_idx = bnx2x_get_cur_phy_idx(bp);
+ switch (bp->link_params.phy[phy_idx].media_type) {
+ case ETH_PHY_SFP_FIBER:
+ case ETH_PHY_XFP_FIBER:
+ case ETH_PHY_KR:
+ case ETH_PHY_CX4:
+ port_type = PORT_FIBRE;
+ break;
+ case ETH_PHY_DA_TWINAX:
+ port_type = PORT_DA;
+ break;
+ case ETH_PHY_BASE_T:
+ port_type = PORT_TP;
+ break;
+ case ETH_PHY_NOT_PRESENT:
+ port_type = PORT_NONE;
+ break;
+ case ETH_PHY_UNSPECIFIED:
+ default:
+ port_type = PORT_OTHER;
+ break;
+ }
+ return port_type;
+}
static int bnx2x_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{
@@ -188,12 +225,7 @@
if (IS_MF(bp))
ethtool_cmd_speed_set(cmd, bnx2x_get_mf_speed(bp));
- if (bp->port.supported[cfg_idx] & SUPPORTED_TP)
- cmd->port = PORT_TP;
- else if (bp->port.supported[cfg_idx] & SUPPORTED_FIBRE)
- cmd->port = PORT_FIBRE;
- else
- BNX2X_ERR("XGXS PHY Failure detected\n");
+ cmd->port = bnx2x_get_port_type(bp);
cmd->phy_address = bp->mdio.prtad;
cmd->transceiver = XCVR_INTERNAL;
@@ -494,7 +526,7 @@
if (IS_E1H_ONLINE(wreg_addrs_e1h[i].info))
regdump_len += wreg_addrs_e1h[i].size *
(1 + wreg_addrs_e1h[i].read_regs_count);
- } else if (CHIP_IS_E2(bp)) {
+ } else if (!CHIP_IS_E1x(bp)) {
for (i = 0; i < REGS_COUNT; i++)
if (IS_E2_ONLINE(reg_addrs[i].info))
regdump_len += reg_addrs[i].size;
@@ -566,7 +598,7 @@
dump_hdr.info = RI_E1_ONLINE;
else if (CHIP_IS_E1H(bp))
dump_hdr.info = RI_E1H_ONLINE;
- else if (CHIP_IS_E2(bp))
+ else if (!CHIP_IS_E1x(bp))
dump_hdr.info = RI_E2_ONLINE |
(BP_PATH(bp) ? RI_PATH1_DUMP : RI_PATH0_DUMP);
@@ -587,23 +619,24 @@
*p++ = REG_RD(bp,
reg_addrs[i].addr + j*4);
- } else if (CHIP_IS_E2(bp)) {
+ } else if (!CHIP_IS_E1x(bp)) {
for (i = 0; i < REGS_COUNT; i++)
if (IS_E2_ONLINE(reg_addrs[i].info))
for (j = 0; j < reg_addrs[i].size; j++)
*p++ = REG_RD(bp,
reg_addrs[i].addr + j*4);
- bnx2x_read_pages_regs_e2(bp, p);
+ if (CHIP_IS_E2(bp))
+ bnx2x_read_pages_regs_e2(bp, p);
+ else
+ /* E3 paged registers read is unimplemented yet */
+ WARN_ON(1);
}
/* Re-enable parity attentions */
bnx2x_clear_blocks_parity(bp);
- if (CHIP_PARITY_ENABLED(bp))
- bnx2x_enable_blocks_parity(bp);
+ bnx2x_enable_blocks_parity(bp);
}
-#define PHY_FW_VER_LEN 20
-
static void bnx2x_get_drvinfo(struct net_device *dev,
struct ethtool_drvinfo *info)
{
@@ -682,8 +715,12 @@
{
struct bnx2x *bp = netdev_priv(dev);
- if (capable(CAP_NET_ADMIN))
+ if (capable(CAP_NET_ADMIN)) {
+ /* dump MCP trace */
+ if (level & BNX2X_MSG_MCP)
+ bnx2x_fw_dump_lvl(bp, KERN_INFO);
bp->msg_enable = level;
+ }
}
static int bnx2x_nway_reset(struct net_device *dev)
@@ -725,7 +762,7 @@
u32 val = 0;
/* adjust timeout for emulation/FPGA */
- count = NVRAM_TIMEOUT_COUNT;
+ count = BNX2X_NVRAM_TIMEOUT_COUNT;
if (CHIP_REV_IS_SLOW(bp))
count *= 100;
@@ -756,7 +793,7 @@
u32 val = 0;
/* adjust timeout for emulation/FPGA */
- count = NVRAM_TIMEOUT_COUNT;
+ count = BNX2X_NVRAM_TIMEOUT_COUNT;
if (CHIP_REV_IS_SLOW(bp))
count *= 100;
@@ -824,7 +861,7 @@
REG_WR(bp, MCP_REG_MCPR_NVM_COMMAND, cmd_flags);
/* adjust timeout for emulation/FPGA */
- count = NVRAM_TIMEOUT_COUNT;
+ count = BNX2X_NVRAM_TIMEOUT_COUNT;
if (CHIP_REV_IS_SLOW(bp))
count *= 100;
@@ -947,7 +984,7 @@
REG_WR(bp, MCP_REG_MCPR_NVM_COMMAND, cmd_flags);
/* adjust timeout for emulation/FPGA */
- count = NVRAM_TIMEOUT_COUNT;
+ count = BNX2X_NVRAM_TIMEOUT_COUNT;
if (CHIP_REV_IS_SLOW(bp))
count *= 100;
@@ -1051,9 +1088,9 @@
while ((written_so_far < buf_size) && (rc == 0)) {
if (written_so_far == (buf_size - sizeof(u32)))
cmd_flags |= MCPR_NVM_COMMAND_LAST;
- else if (((offset + 4) % NVRAM_PAGE_SIZE) == 0)
+ else if (((offset + 4) % BNX2X_NVRAM_PAGE_SIZE) == 0)
cmd_flags |= MCPR_NVM_COMMAND_LAST;
- else if ((offset % NVRAM_PAGE_SIZE) == 0)
+ else if ((offset % BNX2X_NVRAM_PAGE_SIZE) == 0)
cmd_flags |= MCPR_NVM_COMMAND_FIRST;
memcpy(&val, data_buf, 4);
@@ -1212,7 +1249,6 @@
struct ethtool_ringparam *ering)
{
struct bnx2x *bp = netdev_priv(dev);
- int rc = 0;
if (bp->recovery_state != BNX2X_RECOVERY_DONE) {
printk(KERN_ERR "Handling parity error recovery. Try again later\n");
@@ -1229,12 +1265,7 @@
bp->rx_ring_size = ering->rx_pending;
bp->tx_ring_size = ering->tx_pending;
- if (netif_running(dev)) {
- bnx2x_nic_unload(bp, UNLOAD_NORMAL);
- rc = bnx2x_nic_load(bp, LOAD_NORMAL);
- }
-
- return rc;
+ return bnx2x_reload_if_running(dev);
}
static void bnx2x_get_pauseparam(struct net_device *dev,
@@ -1313,60 +1344,129 @@
{ "idle check (online)" }
};
+enum {
+ BNX2X_CHIP_E1_OFST = 0,
+ BNX2X_CHIP_E1H_OFST,
+ BNX2X_CHIP_E2_OFST,
+ BNX2X_CHIP_E3_OFST,
+ BNX2X_CHIP_E3B0_OFST,
+ BNX2X_CHIP_MAX_OFST
+};
+
+#define BNX2X_CHIP_MASK_E1 (1 << BNX2X_CHIP_E1_OFST)
+#define BNX2X_CHIP_MASK_E1H (1 << BNX2X_CHIP_E1H_OFST)
+#define BNX2X_CHIP_MASK_E2 (1 << BNX2X_CHIP_E2_OFST)
+#define BNX2X_CHIP_MASK_E3 (1 << BNX2X_CHIP_E3_OFST)
+#define BNX2X_CHIP_MASK_E3B0 (1 << BNX2X_CHIP_E3B0_OFST)
+
+#define BNX2X_CHIP_MASK_ALL ((1 << BNX2X_CHIP_MAX_OFST) - 1)
+#define BNX2X_CHIP_MASK_E1X (BNX2X_CHIP_MASK_E1 | BNX2X_CHIP_MASK_E1H)
+
static int bnx2x_test_registers(struct bnx2x *bp)
{
int idx, i, rc = -ENODEV;
- u32 wr_val = 0;
+ u32 wr_val = 0, hw;
int port = BP_PORT(bp);
static const struct {
+ u32 hw;
u32 offset0;
u32 offset1;
u32 mask;
} reg_tbl[] = {
-/* 0 */ { BRB1_REG_PAUSE_LOW_THRESHOLD_0, 4, 0x000003ff },
- { DORQ_REG_DB_ADDR0, 4, 0xffffffff },
- { HC_REG_AGG_INT_0, 4, 0x000003ff },
- { PBF_REG_MAC_IF0_ENABLE, 4, 0x00000001 },
- { PBF_REG_P0_INIT_CRD, 4, 0x000007ff },
- { PRS_REG_CID_PORT_0, 4, 0x00ffffff },
- { PXP2_REG_PSWRQ_CDU0_L2P, 4, 0x000fffff },
- { PXP2_REG_RQ_CDU0_EFIRST_MEM_ADDR, 8, 0x0003ffff },
- { PXP2_REG_PSWRQ_TM0_L2P, 4, 0x000fffff },
- { PXP2_REG_RQ_USDM0_EFIRST_MEM_ADDR, 8, 0x0003ffff },
-/* 10 */ { PXP2_REG_PSWRQ_TSDM0_L2P, 4, 0x000fffff },
- { QM_REG_CONNNUM_0, 4, 0x000fffff },
- { TM_REG_LIN0_MAX_ACTIVE_CID, 4, 0x0003ffff },
- { SRC_REG_KEYRSS0_0, 40, 0xffffffff },
- { SRC_REG_KEYRSS0_7, 40, 0xffffffff },
- { XCM_REG_WU_DA_SET_TMR_CNT_FLG_CMD00, 4, 0x00000001 },
- { XCM_REG_WU_DA_CNT_CMD00, 4, 0x00000003 },
- { XCM_REG_GLB_DEL_ACK_MAX_CNT_0, 4, 0x000000ff },
- { NIG_REG_LLH0_T_BIT, 4, 0x00000001 },
- { NIG_REG_EMAC0_IN_EN, 4, 0x00000001 },
-/* 20 */ { NIG_REG_BMAC0_IN_EN, 4, 0x00000001 },
- { NIG_REG_XCM0_OUT_EN, 4, 0x00000001 },
- { NIG_REG_BRB0_OUT_EN, 4, 0x00000001 },
- { NIG_REG_LLH0_XCM_MASK, 4, 0x00000007 },
- { NIG_REG_LLH0_ACPI_PAT_6_LEN, 68, 0x000000ff },
- { NIG_REG_LLH0_ACPI_PAT_0_CRC, 68, 0xffffffff },
- { NIG_REG_LLH0_DEST_MAC_0_0, 160, 0xffffffff },
- { NIG_REG_LLH0_DEST_IP_0_1, 160, 0xffffffff },
- { NIG_REG_LLH0_IPV4_IPV6_0, 160, 0x00000001 },
- { NIG_REG_LLH0_DEST_UDP_0, 160, 0x0000ffff },
-/* 30 */ { NIG_REG_LLH0_DEST_TCP_0, 160, 0x0000ffff },
- { NIG_REG_LLH0_VLAN_ID_0, 160, 0x00000fff },
- { NIG_REG_XGXS_SERDES0_MODE_SEL, 4, 0x00000001 },
- { NIG_REG_LED_CONTROL_OVERRIDE_TRAFFIC_P0, 4, 0x00000001 },
- { NIG_REG_STATUS_INTERRUPT_PORT0, 4, 0x07ffffff },
- { NIG_REG_XGXS0_CTRL_EXTREMOTEMDIOST, 24, 0x00000001 },
- { NIG_REG_SERDES0_CTRL_PHY_ADDR, 16, 0x0000001f },
+/* 0 */ { BNX2X_CHIP_MASK_ALL,
+ BRB1_REG_PAUSE_LOW_THRESHOLD_0, 4, 0x000003ff },
+ { BNX2X_CHIP_MASK_ALL,
+ DORQ_REG_DB_ADDR0, 4, 0xffffffff },
+ { BNX2X_CHIP_MASK_E1X,
+ HC_REG_AGG_INT_0, 4, 0x000003ff },
+ { BNX2X_CHIP_MASK_ALL,
+ PBF_REG_MAC_IF0_ENABLE, 4, 0x00000001 },
+ { BNX2X_CHIP_MASK_E1X | BNX2X_CHIP_MASK_E2 | BNX2X_CHIP_MASK_E3,
+ PBF_REG_P0_INIT_CRD, 4, 0x000007ff },
+ { BNX2X_CHIP_MASK_E3B0,
+ PBF_REG_INIT_CRD_Q0, 4, 0x000007ff },
+ { BNX2X_CHIP_MASK_ALL,
+ PRS_REG_CID_PORT_0, 4, 0x00ffffff },
+ { BNX2X_CHIP_MASK_ALL,
+ PXP2_REG_PSWRQ_CDU0_L2P, 4, 0x000fffff },
+ { BNX2X_CHIP_MASK_ALL,
+ PXP2_REG_RQ_CDU0_EFIRST_MEM_ADDR, 8, 0x0003ffff },
+ { BNX2X_CHIP_MASK_ALL,
+ PXP2_REG_PSWRQ_TM0_L2P, 4, 0x000fffff },
+/* 10 */ { BNX2X_CHIP_MASK_ALL,
+ PXP2_REG_RQ_USDM0_EFIRST_MEM_ADDR, 8, 0x0003ffff },
+ { BNX2X_CHIP_MASK_ALL,
+ PXP2_REG_PSWRQ_TSDM0_L2P, 4, 0x000fffff },
+ { BNX2X_CHIP_MASK_ALL,
+ QM_REG_CONNNUM_0, 4, 0x000fffff },
+ { BNX2X_CHIP_MASK_ALL,
+ TM_REG_LIN0_MAX_ACTIVE_CID, 4, 0x0003ffff },
+ { BNX2X_CHIP_MASK_ALL,
+ SRC_REG_KEYRSS0_0, 40, 0xffffffff },
+ { BNX2X_CHIP_MASK_ALL,
+ SRC_REG_KEYRSS0_7, 40, 0xffffffff },
+ { BNX2X_CHIP_MASK_ALL,
+ XCM_REG_WU_DA_SET_TMR_CNT_FLG_CMD00, 4, 0x00000001 },
+ { BNX2X_CHIP_MASK_ALL,
+ XCM_REG_WU_DA_CNT_CMD00, 4, 0x00000003 },
+ { BNX2X_CHIP_MASK_ALL,
+ XCM_REG_GLB_DEL_ACK_MAX_CNT_0, 4, 0x000000ff },
+ { BNX2X_CHIP_MASK_ALL,
+ NIG_REG_LLH0_T_BIT, 4, 0x00000001 },
+/* 20 */ { BNX2X_CHIP_MASK_E1X | BNX2X_CHIP_MASK_E2,
+ NIG_REG_EMAC0_IN_EN, 4, 0x00000001 },
+ { BNX2X_CHIP_MASK_E1X | BNX2X_CHIP_MASK_E2,
+ NIG_REG_BMAC0_IN_EN, 4, 0x00000001 },
+ { BNX2X_CHIP_MASK_ALL,
+ NIG_REG_XCM0_OUT_EN, 4, 0x00000001 },
+ { BNX2X_CHIP_MASK_ALL,
+ NIG_REG_BRB0_OUT_EN, 4, 0x00000001 },
+ { BNX2X_CHIP_MASK_ALL,
+ NIG_REG_LLH0_XCM_MASK, 4, 0x00000007 },
+ { BNX2X_CHIP_MASK_ALL,
+ NIG_REG_LLH0_ACPI_PAT_6_LEN, 68, 0x000000ff },
+ { BNX2X_CHIP_MASK_ALL,
+ NIG_REG_LLH0_ACPI_PAT_0_CRC, 68, 0xffffffff },
+ { BNX2X_CHIP_MASK_ALL,
+ NIG_REG_LLH0_DEST_MAC_0_0, 160, 0xffffffff },
+ { BNX2X_CHIP_MASK_ALL,
+ NIG_REG_LLH0_DEST_IP_0_1, 160, 0xffffffff },
+ { BNX2X_CHIP_MASK_ALL,
+ NIG_REG_LLH0_IPV4_IPV6_0, 160, 0x00000001 },
+/* 30 */ { BNX2X_CHIP_MASK_ALL,
+ NIG_REG_LLH0_DEST_UDP_0, 160, 0x0000ffff },
+ { BNX2X_CHIP_MASK_ALL,
+ NIG_REG_LLH0_DEST_TCP_0, 160, 0x0000ffff },
+ { BNX2X_CHIP_MASK_ALL,
+ NIG_REG_LLH0_VLAN_ID_0, 160, 0x00000fff },
+ { BNX2X_CHIP_MASK_E1X | BNX2X_CHIP_MASK_E2,
+ NIG_REG_XGXS_SERDES0_MODE_SEL, 4, 0x00000001 },
+ { BNX2X_CHIP_MASK_ALL,
+ NIG_REG_LED_CONTROL_OVERRIDE_TRAFFIC_P0, 4, 0x00000001},
+ { BNX2X_CHIP_MASK_ALL,
+ NIG_REG_STATUS_INTERRUPT_PORT0, 4, 0x07ffffff },
+ { BNX2X_CHIP_MASK_E1X | BNX2X_CHIP_MASK_E2,
+ NIG_REG_XGXS0_CTRL_EXTREMOTEMDIOST, 24, 0x00000001 },
+ { BNX2X_CHIP_MASK_E1X | BNX2X_CHIP_MASK_E2,
+ NIG_REG_SERDES0_CTRL_PHY_ADDR, 16, 0x0000001f },
- { 0xffffffff, 0, 0x00000000 }
+ { BNX2X_CHIP_MASK_ALL, 0xffffffff, 0, 0x00000000 }
};
if (!netif_running(bp->dev))
return rc;
+ if (CHIP_IS_E1(bp))
+ hw = BNX2X_CHIP_MASK_E1;
+ else if (CHIP_IS_E1H(bp))
+ hw = BNX2X_CHIP_MASK_E1H;
+ else if (CHIP_IS_E2(bp))
+ hw = BNX2X_CHIP_MASK_E2;
+ else if (CHIP_IS_E3B0(bp))
+ hw = BNX2X_CHIP_MASK_E3B0;
+ else /* e3 A0 */
+ hw = BNX2X_CHIP_MASK_E3;
+
/* Repeat the test twice:
First by writing 0x00000000, second by writing 0xffffffff */
for (idx = 0; idx < 2; idx++) {
@@ -1382,8 +1482,7 @@
for (i = 0; reg_tbl[i].offset0 != 0xffffffff; i++) {
u32 offset, mask, save_val, val;
- if (CHIP_IS_E2(bp) &&
- reg_tbl[i].offset0 == HC_REG_AGG_INT_0)
+ if (!(hw & reg_tbl[i].hw))
continue;
offset = reg_tbl[i].offset0 + port*reg_tbl[i].offset1;
@@ -1400,7 +1499,7 @@
/* verify value is as expected */
if ((val & mask) != (wr_val & mask)) {
- DP(NETIF_MSG_PROBE,
+ DP(NETIF_MSG_HW,
"offset 0x%x: val 0x%x != 0x%x mask 0x%x\n",
offset, val, wr_val, mask);
goto test_reg_exit;
@@ -1417,7 +1516,7 @@
static int bnx2x_test_memory(struct bnx2x *bp)
{
int i, j, rc = -ENODEV;
- u32 val;
+ u32 val, index;
static const struct {
u32 offset;
int size;
@@ -1432,32 +1531,44 @@
{ 0xffffffff, 0 }
};
+
static const struct {
char *name;
u32 offset;
- u32 e1_mask;
- u32 e1h_mask;
- u32 e2_mask;
+ u32 hw_mask[BNX2X_CHIP_MAX_OFST];
} prty_tbl[] = {
- { "CCM_PRTY_STS", CCM_REG_CCM_PRTY_STS, 0x3ffc0, 0, 0 },
- { "CFC_PRTY_STS", CFC_REG_CFC_PRTY_STS, 0x2, 0x2, 0 },
- { "DMAE_PRTY_STS", DMAE_REG_DMAE_PRTY_STS, 0, 0, 0 },
- { "TCM_PRTY_STS", TCM_REG_TCM_PRTY_STS, 0x3ffc0, 0, 0 },
- { "UCM_PRTY_STS", UCM_REG_UCM_PRTY_STS, 0x3ffc0, 0, 0 },
- { "XCM_PRTY_STS", XCM_REG_XCM_PRTY_STS, 0x3ffc1, 0, 0 },
+ { "CCM_PRTY_STS", CCM_REG_CCM_PRTY_STS,
+ {0x3ffc0, 0, 0, 0} },
+ { "CFC_PRTY_STS", CFC_REG_CFC_PRTY_STS,
+ {0x2, 0x2, 0, 0} },
+ { "DMAE_PRTY_STS", DMAE_REG_DMAE_PRTY_STS,
+ {0, 0, 0, 0} },
+ { "TCM_PRTY_STS", TCM_REG_TCM_PRTY_STS,
+ {0x3ffc0, 0, 0, 0} },
+ { "UCM_PRTY_STS", UCM_REG_UCM_PRTY_STS,
+ {0x3ffc0, 0, 0, 0} },
+ { "XCM_PRTY_STS", XCM_REG_XCM_PRTY_STS,
+ {0x3ffc1, 0, 0, 0} },
- { NULL, 0xffffffff, 0, 0, 0 }
+ { NULL, 0xffffffff, {0, 0, 0, 0} }
};
if (!netif_running(bp->dev))
return rc;
+ if (CHIP_IS_E1(bp))
+ index = BNX2X_CHIP_E1_OFST;
+ else if (CHIP_IS_E1H(bp))
+ index = BNX2X_CHIP_E1H_OFST;
+ else if (CHIP_IS_E2(bp))
+ index = BNX2X_CHIP_E2_OFST;
+ else /* e3 */
+ index = BNX2X_CHIP_E3_OFST;
+
/* pre-Check the parity status */
for (i = 0; prty_tbl[i].offset != 0xffffffff; i++) {
val = REG_RD(bp, prty_tbl[i].offset);
- if ((CHIP_IS_E1(bp) && (val & ~(prty_tbl[i].e1_mask))) ||
- (CHIP_IS_E1H(bp) && (val & ~(prty_tbl[i].e1h_mask))) ||
- (CHIP_IS_E2(bp) && (val & ~(prty_tbl[i].e2_mask)))) {
+ if (val & ~(prty_tbl[i].hw_mask[index])) {
DP(NETIF_MSG_HW,
"%s is 0x%x\n", prty_tbl[i].name, val);
goto test_mem_exit;
@@ -1472,9 +1583,7 @@
/* Check the parity status */
for (i = 0; prty_tbl[i].offset != 0xffffffff; i++) {
val = REG_RD(bp, prty_tbl[i].offset);
- if ((CHIP_IS_E1(bp) && (val & ~(prty_tbl[i].e1_mask))) ||
- (CHIP_IS_E1H(bp) && (val & ~(prty_tbl[i].e1h_mask))) ||
- (CHIP_IS_E2(bp) && (val & ~(prty_tbl[i].e2_mask)))) {
+ if (val & ~(prty_tbl[i].hw_mask[index])) {
DP(NETIF_MSG_HW,
"%s is 0x%x\n", prty_tbl[i].name, val);
goto test_mem_exit;
@@ -1491,12 +1600,16 @@
{
int cnt = 1400;
- if (link_up)
+ if (link_up) {
while (bnx2x_link_test(bp, is_serdes) && cnt--)
- msleep(10);
+ msleep(20);
+
+ if (cnt <= 0 && bnx2x_link_test(bp, is_serdes))
+ DP(NETIF_MSG_LINK, "Timeout waiting for link up\n");
+ }
}
-static int bnx2x_run_loopback(struct bnx2x *bp, int loopback_mode, u8 link_up)
+static int bnx2x_run_loopback(struct bnx2x *bp, int loopback_mode)
{
unsigned int pkt_size, num_pkts, i;
struct sk_buff *skb;
@@ -1505,14 +1618,14 @@
struct bnx2x_fastpath *fp_tx = &bp->fp[0];
u16 tx_start_idx, tx_idx;
u16 rx_start_idx, rx_idx;
- u16 pkt_prod, bd_prod;
+ u16 pkt_prod, bd_prod, rx_comp_cons;
struct sw_tx_bd *tx_buf;
struct eth_tx_start_bd *tx_start_bd;
struct eth_tx_parse_bd_e1x *pbd_e1x = NULL;
struct eth_tx_parse_bd_e2 *pbd_e2 = NULL;
dma_addr_t mapping;
union eth_rx_cqe *cqe;
- u8 cqe_fp_flags;
+ u8 cqe_fp_flags, cqe_fp_type;
struct sw_rx_bd *rx_buf;
u16 len;
int rc = -ENODEV;
@@ -1524,7 +1637,8 @@
return -EINVAL;
break;
case BNX2X_MAC_LOOPBACK:
- bp->link_params.loopback_mode = LOOPBACK_BMAC;
+ bp->link_params.loopback_mode = CHIP_IS_E3(bp) ?
+ LOOPBACK_XMAC : LOOPBACK_BMAC;
bnx2x_phy_init(&bp->link_params, &bp->link_vars);
break;
default:
@@ -1545,6 +1659,14 @@
memset(packet + 2*ETH_ALEN, 0x77, (ETH_HLEN - 2*ETH_ALEN));
for (i = ETH_HLEN; i < pkt_size; i++)
packet[i] = (unsigned char) (i & 0xff);
+ mapping = dma_map_single(&bp->pdev->dev, skb->data,
+ skb_headlen(skb), DMA_TO_DEVICE);
+ if (unlikely(dma_mapping_error(&bp->pdev->dev, mapping))) {
+ rc = -ENOMEM;
+ dev_kfree_skb(skb);
+ BNX2X_ERR("Unable to map SKB\n");
+ goto test_loopback_exit;
+ }
/* send the loopback packet */
num_pkts = 0;
@@ -1559,8 +1681,6 @@
bd_prod = TX_BD(fp_tx->tx_bd_prod);
tx_start_bd = &fp_tx->tx_desc_ring[bd_prod].start_bd;
- mapping = dma_map_single(&bp->pdev->dev, skb->data,
- skb_headlen(skb), DMA_TO_DEVICE);
tx_start_bd->addr_hi = cpu_to_le32(U64_HI(mapping));
tx_start_bd->addr_lo = cpu_to_le32(U64_LO(mapping));
tx_start_bd->nbd = cpu_to_le16(2); /* start + pbd */
@@ -1590,6 +1710,7 @@
DOORBELL(bp, fp_tx->index, fp_tx->tx_db.raw);
mmiowb();
+ barrier();
num_pkts++;
fp_tx->tx_bd_prod += 2; /* start + pbd */
@@ -1618,9 +1739,11 @@
if (rx_idx != rx_start_idx + num_pkts)
goto test_loopback_exit;
- cqe = &fp_rx->rx_comp_ring[RCQ_BD(fp_rx->rx_comp_cons)];
+ rx_comp_cons = le16_to_cpu(fp_rx->rx_comp_cons);
+ cqe = &fp_rx->rx_comp_ring[RCQ_BD(rx_comp_cons)];
cqe_fp_flags = cqe->fast_path_cqe.type_error_flags;
- if (CQE_TYPE(cqe_fp_flags) || (cqe_fp_flags & ETH_RX_ERROR_FALGS))
+ cqe_fp_type = cqe_fp_flags & ETH_FAST_PATH_RX_CQE_TYPE;
+ if (!CQE_TYPE_FAST(cqe_fp_type) || (cqe_fp_flags & ETH_RX_ERROR_FALGS))
goto test_loopback_rx_exit;
len = le16_to_cpu(cqe->fast_path_cqe.pkt_len);
@@ -1628,6 +1751,9 @@
goto test_loopback_rx_exit;
rx_buf = &fp_rx->rx_buf_ring[RX_BD(fp_rx->rx_bd_cons)];
+ dma_sync_single_for_device(&bp->pdev->dev,
+ dma_unmap_addr(rx_buf, mapping),
+ fp_rx->rx_buf_size, DMA_FROM_DEVICE);
skb = rx_buf->skb;
skb_reserve(skb, cqe->fast_path_cqe.placement_offset);
for (i = ETH_HLEN; i < pkt_size; i++)
@@ -1653,7 +1779,7 @@
return rc;
}
-static int bnx2x_test_loopback(struct bnx2x *bp, u8 link_up)
+static int bnx2x_test_loopback(struct bnx2x *bp)
{
int rc = 0, res;
@@ -1666,13 +1792,13 @@
bnx2x_netif_stop(bp, 1);
bnx2x_acquire_phy_lock(bp);
- res = bnx2x_run_loopback(bp, BNX2X_PHY_LOOPBACK, link_up);
+ res = bnx2x_run_loopback(bp, BNX2X_PHY_LOOPBACK);
if (res) {
DP(NETIF_MSG_PROBE, " PHY loopback failed (res %d)\n", res);
rc |= BNX2X_PHY_LOOPBACK_FAILED;
}
- res = bnx2x_run_loopback(bp, BNX2X_MAC_LOOPBACK, link_up);
+ res = bnx2x_run_loopback(bp, BNX2X_MAC_LOOPBACK);
if (res) {
DP(NETIF_MSG_PROBE, " MAC loopback failed (res %d)\n", res);
rc |= BNX2X_MAC_LOOPBACK_FAILED;
@@ -1744,39 +1870,20 @@
return rc;
}
+/* Send an EMPTY ramrod on the first queue */
static int bnx2x_test_intr(struct bnx2x *bp)
{
- struct mac_configuration_cmd *config = bnx2x_sp(bp, mac_config);
- int i, rc;
+ struct bnx2x_queue_state_params params = {0};
if (!netif_running(bp->dev))
return -ENODEV;
- config->hdr.length = 0;
- if (CHIP_IS_E1(bp))
- config->hdr.offset = (BP_PORT(bp) ? 32 : 0);
- else
- config->hdr.offset = BP_FUNC(bp);
- config->hdr.client_id = bp->fp->cl_id;
- config->hdr.reserved1 = 0;
+ params.q_obj = &bp->fp->q_obj;
+ params.cmd = BNX2X_Q_CMD_EMPTY;
- bp->set_mac_pending = 1;
- smp_wmb();
- rc = bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_SET_MAC, 0,
- U64_HI(bnx2x_sp_mapping(bp, mac_config)),
- U64_LO(bnx2x_sp_mapping(bp, mac_config)), 1);
- if (rc == 0) {
- for (i = 0; i < 10; i++) {
- if (!bp->set_mac_pending)
- break;
- smp_rmb();
- msleep_interruptible(10);
- }
- if (i == 10)
- rc = -ENODEV;
- }
+ __set_bit(RAMROD_COMP_WAIT, ¶ms.ramrod_flags);
- return rc;
+ return bnx2x_queue_state_change(bp, ¶ms);
}
static void bnx2x_self_test(struct net_device *dev,
@@ -1815,7 +1922,7 @@
bnx2x_nic_unload(bp, UNLOAD_NORMAL);
bnx2x_nic_load(bp, LOAD_DIAG);
/* wait until link state is restored */
- bnx2x_wait_for_link(bp, link_up, is_serdes);
+ bnx2x_wait_for_link(bp, 1, is_serdes);
if (bnx2x_test_registers(bp) != 0) {
buf[0] = 1;
@@ -1826,7 +1933,7 @@
etest->flags |= ETH_TEST_FL_FAILED;
}
- buf[2] = bnx2x_test_loopback(bp, link_up);
+ buf[2] = bnx2x_test_loopback(bp);
if (buf[2] != 0)
etest->flags |= ETH_TEST_FL_FAILED;
@@ -1864,6 +1971,14 @@
#define IS_MF_MODE_STAT(bp) \
(IS_MF(bp) && !(bp->msg_enable & BNX2X_MSG_STATS))
+/* ethtool statistics are displayed for all regular ethernet queues and the
+ * fcoe L2 queue if not disabled
+ */
+static inline int bnx2x_num_stat_queues(struct bnx2x *bp)
+{
+ return BNX2X_NUM_ETH_QUEUES(bp);
+}
+
static int bnx2x_get_sset_count(struct net_device *dev, int stringset)
{
struct bnx2x *bp = netdev_priv(dev);
@@ -1872,7 +1987,7 @@
switch (stringset) {
case ETH_SS_STATS:
if (is_multi(bp)) {
- num_stats = BNX2X_NUM_STAT_QUEUES(bp) *
+ num_stats = bnx2x_num_stat_queues(bp) *
BNX2X_NUM_Q_STATS;
if (!IS_MF_MODE_STAT(bp))
num_stats += BNX2X_NUM_STATS;
@@ -1905,14 +2020,9 @@
case ETH_SS_STATS:
if (is_multi(bp)) {
k = 0;
- for_each_napi_queue(bp, i) {
+ for_each_eth_queue(bp, i) {
memset(queue_name, 0, sizeof(queue_name));
-
- if (IS_FCOE_IDX(i))
- sprintf(queue_name, "fcoe");
- else
- sprintf(queue_name, "%d", i);
-
+ sprintf(queue_name, "%d", i);
for (j = 0; j < BNX2X_NUM_Q_STATS; j++)
snprintf(buf + (k + j)*ETH_GSTRING_LEN,
ETH_GSTRING_LEN,
@@ -1951,7 +2061,7 @@
if (is_multi(bp)) {
k = 0;
- for_each_napi_queue(bp, i) {
+ for_each_eth_queue(bp, i) {
hw_stats = (u32 *)&bp->fp[i].eth_q_stats;
for (j = 0; j < BNX2X_NUM_Q_STATS; j++) {
if (bnx2x_q_stats_arr[j].size == 0) {
@@ -2069,14 +2179,30 @@
{
struct bnx2x *bp = netdev_priv(dev);
size_t copy_size =
- min_t(size_t, indir->size, TSTORM_INDIRECTION_TABLE_SIZE);
+ min_t(size_t, indir->size, T_ETH_INDIRECTION_TABLE_SIZE);
+ u8 ind_table[T_ETH_INDIRECTION_TABLE_SIZE] = {0};
+ size_t i;
if (bp->multi_mode == ETH_RSS_MODE_DISABLED)
return -EOPNOTSUPP;
- indir->size = TSTORM_INDIRECTION_TABLE_SIZE;
- memcpy(indir->ring_index, bp->rx_indir_table,
- copy_size * sizeof(bp->rx_indir_table[0]));
+ /* Get the current configuration of the RSS indirection table */
+ bnx2x_get_rss_ind_table(&bp->rss_conf_obj, ind_table);
+
+ /*
+ * We can't use a memcpy() as an internal storage of an
+ * indirection table is a u8 array while indir->ring_index
+ * points to an array of u32.
+ *
+ * Indirection table contains the FW Client IDs, so we need to
+ * align the returned table to the Client ID of the leading RSS
+ * queue.
+ */
+ for (i = 0; i < copy_size; i++)
+ indir->ring_index[i] = ind_table[i] - bp->fp->cl_id;
+
+ indir->size = T_ETH_INDIRECTION_TABLE_SIZE;
+
return 0;
}
@@ -2085,21 +2211,33 @@
{
struct bnx2x *bp = netdev_priv(dev);
size_t i;
+ u8 ind_table[T_ETH_INDIRECTION_TABLE_SIZE] = {0};
+ u32 num_eth_queues = BNX2X_NUM_ETH_QUEUES(bp);
if (bp->multi_mode == ETH_RSS_MODE_DISABLED)
return -EOPNOTSUPP;
- /* Validate size and indices */
- if (indir->size != TSTORM_INDIRECTION_TABLE_SIZE)
+ /* validate the size */
+ if (indir->size != T_ETH_INDIRECTION_TABLE_SIZE)
return -EINVAL;
- for (i = 0; i < TSTORM_INDIRECTION_TABLE_SIZE; i++)
- if (indir->ring_index[i] >= BNX2X_NUM_ETH_QUEUES(bp))
- return -EINVAL;
- memcpy(bp->rx_indir_table, indir->ring_index,
- indir->size * sizeof(bp->rx_indir_table[0]));
- bnx2x_push_indir_table(bp);
- return 0;
+ for (i = 0; i < T_ETH_INDIRECTION_TABLE_SIZE; i++) {
+ /* validate the indices */
+ if (indir->ring_index[i] >= num_eth_queues)
+ return -EINVAL;
+ /*
+ * The same as in bnx2x_get_rxfh_indir: we can't use a memcpy()
+ * as an internal storage of an indirection table is a u8 array
+ * while indir->ring_index points to an array of u32.
+ *
+ * Indirection table contains the FW Client IDs, so we need to
+ * align the received table to the Client ID of the leading RSS
+ * queue
+ */
+ ind_table[i] = indir->ring_index[i] + bp->fp->cl_id;
+ }
+
+ return bnx2x_config_rss_pf(bp, ind_table, false);
}
static const struct ethtool_ops bnx2x_ethtool_ops = {
diff --git a/drivers/net/bnx2x/bnx2x_fw_defs.h b/drivers/net/bnx2x/bnx2x_fw_defs.h
index 9fe3678..998652a 100644
--- a/drivers/net/bnx2x/bnx2x_fw_defs.h
+++ b/drivers/net/bnx2x/bnx2x_fw_defs.h
@@ -10,249 +10,221 @@
#ifndef BNX2X_FW_DEFS_H
#define BNX2X_FW_DEFS_H
-#define CSTORM_ASSERT_LIST_INDEX_OFFSET (IRO[142].base)
+#define CSTORM_ASSERT_LIST_INDEX_OFFSET (IRO[148].base)
#define CSTORM_ASSERT_LIST_OFFSET(assertListEntry) \
- (IRO[141].base + ((assertListEntry) * IRO[141].m1))
-#define CSTORM_ETH_STATS_QUERY_ADDR_OFFSET(pfId) \
- (IRO[144].base + ((pfId) * IRO[144].m1))
+ (IRO[147].base + ((assertListEntry) * IRO[147].m1))
#define CSTORM_EVENT_RING_DATA_OFFSET(pfId) \
- (IRO[149].base + (((pfId)>>1) * IRO[149].m1) + (((pfId)&1) * \
- IRO[149].m2))
+ (IRO[153].base + (((pfId)>>1) * IRO[153].m1) + (((pfId)&1) * \
+ IRO[153].m2))
#define CSTORM_EVENT_RING_PROD_OFFSET(pfId) \
- (IRO[150].base + (((pfId)>>1) * IRO[150].m1) + (((pfId)&1) * \
- IRO[150].m2))
+ (IRO[154].base + (((pfId)>>1) * IRO[154].m1) + (((pfId)&1) * \
+ IRO[154].m2))
#define CSTORM_FINAL_CLEANUP_COMPLETE_OFFSET(funcId) \
- (IRO[156].base + ((funcId) * IRO[156].m1))
+ (IRO[159].base + ((funcId) * IRO[159].m1))
#define CSTORM_FUNC_EN_OFFSET(funcId) \
- (IRO[146].base + ((funcId) * IRO[146].m1))
-#define CSTORM_FUNCTION_MODE_OFFSET (IRO[153].base)
-#define CSTORM_IGU_MODE_OFFSET (IRO[154].base)
+ (IRO[149].base + ((funcId) * IRO[149].m1))
+#define CSTORM_IGU_MODE_OFFSET (IRO[157].base)
#define CSTORM_ISCSI_CQ_SIZE_OFFSET(pfId) \
- (IRO[311].base + ((pfId) * IRO[311].m1))
+ (IRO[315].base + ((pfId) * IRO[315].m1))
#define CSTORM_ISCSI_CQ_SQN_SIZE_OFFSET(pfId) \
- (IRO[312].base + ((pfId) * IRO[312].m1))
- #define CSTORM_ISCSI_EQ_CONS_OFFSET(pfId, iscsiEqId) \
- (IRO[304].base + ((pfId) * IRO[304].m1) + ((iscsiEqId) * \
- IRO[304].m2))
- #define CSTORM_ISCSI_EQ_NEXT_EQE_ADDR_OFFSET(pfId, iscsiEqId) \
- (IRO[306].base + ((pfId) * IRO[306].m1) + ((iscsiEqId) * \
- IRO[306].m2))
- #define CSTORM_ISCSI_EQ_NEXT_PAGE_ADDR_OFFSET(pfId, iscsiEqId) \
- (IRO[305].base + ((pfId) * IRO[305].m1) + ((iscsiEqId) * \
- IRO[305].m2))
- #define \
- CSTORM_ISCSI_EQ_NEXT_PAGE_ADDR_VALID_OFFSET(pfId, iscsiEqId) \
- (IRO[307].base + ((pfId) * IRO[307].m1) + ((iscsiEqId) * \
- IRO[307].m2))
- #define CSTORM_ISCSI_EQ_PROD_OFFSET(pfId, iscsiEqId) \
- (IRO[303].base + ((pfId) * IRO[303].m1) + ((iscsiEqId) * \
- IRO[303].m2))
- #define CSTORM_ISCSI_EQ_SB_INDEX_OFFSET(pfId, iscsiEqId) \
- (IRO[309].base + ((pfId) * IRO[309].m1) + ((iscsiEqId) * \
- IRO[309].m2))
- #define CSTORM_ISCSI_EQ_SB_NUM_OFFSET(pfId, iscsiEqId) \
- (IRO[308].base + ((pfId) * IRO[308].m1) + ((iscsiEqId) * \
- IRO[308].m2))
+ (IRO[316].base + ((pfId) * IRO[316].m1))
+#define CSTORM_ISCSI_EQ_CONS_OFFSET(pfId, iscsiEqId) \
+ (IRO[308].base + ((pfId) * IRO[308].m1) + ((iscsiEqId) * IRO[308].m2))
+#define CSTORM_ISCSI_EQ_NEXT_EQE_ADDR_OFFSET(pfId, iscsiEqId) \
+ (IRO[310].base + ((pfId) * IRO[310].m1) + ((iscsiEqId) * IRO[310].m2))
+#define CSTORM_ISCSI_EQ_NEXT_PAGE_ADDR_OFFSET(pfId, iscsiEqId) \
+ (IRO[309].base + ((pfId) * IRO[309].m1) + ((iscsiEqId) * IRO[309].m2))
+#define CSTORM_ISCSI_EQ_NEXT_PAGE_ADDR_VALID_OFFSET(pfId, iscsiEqId) \
+ (IRO[311].base + ((pfId) * IRO[311].m1) + ((iscsiEqId) * IRO[311].m2))
+#define CSTORM_ISCSI_EQ_PROD_OFFSET(pfId, iscsiEqId) \
+ (IRO[307].base + ((pfId) * IRO[307].m1) + ((iscsiEqId) * IRO[307].m2))
+#define CSTORM_ISCSI_EQ_SB_INDEX_OFFSET(pfId, iscsiEqId) \
+ (IRO[313].base + ((pfId) * IRO[313].m1) + ((iscsiEqId) * IRO[313].m2))
+#define CSTORM_ISCSI_EQ_SB_NUM_OFFSET(pfId, iscsiEqId) \
+ (IRO[312].base + ((pfId) * IRO[312].m1) + ((iscsiEqId) * IRO[312].m2))
#define CSTORM_ISCSI_HQ_SIZE_OFFSET(pfId) \
- (IRO[310].base + ((pfId) * IRO[310].m1))
+ (IRO[314].base + ((pfId) * IRO[314].m1))
#define CSTORM_ISCSI_NUM_OF_TASKS_OFFSET(pfId) \
- (IRO[302].base + ((pfId) * IRO[302].m1))
+ (IRO[306].base + ((pfId) * IRO[306].m1))
#define CSTORM_ISCSI_PAGE_SIZE_LOG_OFFSET(pfId) \
- (IRO[301].base + ((pfId) * IRO[301].m1))
+ (IRO[305].base + ((pfId) * IRO[305].m1))
#define CSTORM_ISCSI_PAGE_SIZE_OFFSET(pfId) \
- (IRO[300].base + ((pfId) * IRO[300].m1))
-#define CSTORM_PATH_ID_OFFSET (IRO[159].base)
+ (IRO[304].base + ((pfId) * IRO[304].m1))
+#define CSTORM_RECORD_SLOW_PATH_OFFSET(funcId) \
+ (IRO[151].base + ((funcId) * IRO[151].m1))
#define CSTORM_SP_STATUS_BLOCK_DATA_OFFSET(pfId) \
- (IRO[137].base + ((pfId) * IRO[137].m1))
-#define CSTORM_SP_STATUS_BLOCK_OFFSET(pfId) \
- (IRO[136].base + ((pfId) * IRO[136].m1))
-#define CSTORM_SP_STATUS_BLOCK_SIZE (IRO[136].size)
-#define CSTORM_SP_SYNC_BLOCK_OFFSET(pfId) \
- (IRO[138].base + ((pfId) * IRO[138].m1))
-#define CSTORM_SP_SYNC_BLOCK_SIZE (IRO[138].size)
-#define CSTORM_STATS_FLAGS_OFFSET(pfId) \
+ (IRO[142].base + ((pfId) * IRO[142].m1))
+#define CSTORM_SP_STATUS_BLOCK_DATA_STATE_OFFSET(pfId) \
(IRO[143].base + ((pfId) * IRO[143].m1))
+#define CSTORM_SP_STATUS_BLOCK_OFFSET(pfId) \
+ (IRO[141].base + ((pfId) * IRO[141].m1))
+#define CSTORM_SP_STATUS_BLOCK_SIZE (IRO[141].size)
+#define CSTORM_SP_SYNC_BLOCK_OFFSET(pfId) \
+ (IRO[144].base + ((pfId) * IRO[144].m1))
+#define CSTORM_SP_SYNC_BLOCK_SIZE (IRO[144].size)
+#define CSTORM_STATUS_BLOCK_DATA_FLAGS_OFFSET(sbId, hcIndex) \
+ (IRO[136].base + ((sbId) * IRO[136].m1) + ((hcIndex) * IRO[136].m2))
#define CSTORM_STATUS_BLOCK_DATA_OFFSET(sbId) \
- (IRO[129].base + ((sbId) * IRO[129].m1))
+ (IRO[133].base + ((sbId) * IRO[133].m1))
+#define CSTORM_STATUS_BLOCK_DATA_STATE_OFFSET(sbId) \
+ (IRO[134].base + ((sbId) * IRO[134].m1))
+#define CSTORM_STATUS_BLOCK_DATA_TIMEOUT_OFFSET(sbId, hcIndex) \
+ (IRO[135].base + ((sbId) * IRO[135].m1) + ((hcIndex) * IRO[135].m2))
#define CSTORM_STATUS_BLOCK_OFFSET(sbId) \
- (IRO[128].base + ((sbId) * IRO[128].m1))
-#define CSTORM_STATUS_BLOCK_SIZE (IRO[128].size)
-#define CSTORM_SYNC_BLOCK_OFFSET(sbId) \
(IRO[132].base + ((sbId) * IRO[132].m1))
-#define CSTORM_SYNC_BLOCK_SIZE (IRO[132].size)
+#define CSTORM_STATUS_BLOCK_SIZE (IRO[132].size)
+#define CSTORM_SYNC_BLOCK_OFFSET(sbId) \
+ (IRO[137].base + ((sbId) * IRO[137].m1))
+#define CSTORM_SYNC_BLOCK_SIZE (IRO[137].size)
#define CSTORM_VF_PF_CHANNEL_STATE_OFFSET(vfId) \
- (IRO[151].base + ((vfId) * IRO[151].m1))
+ (IRO[155].base + ((vfId) * IRO[155].m1))
#define CSTORM_VF_PF_CHANNEL_VALID_OFFSET(vfId) \
- (IRO[152].base + ((vfId) * IRO[152].m1))
+ (IRO[156].base + ((vfId) * IRO[156].m1))
#define CSTORM_VF_TO_PF_OFFSET(funcId) \
- (IRO[147].base + ((funcId) * IRO[147].m1))
-#define TSTORM_ACCEPT_CLASSIFY_FAILED_OFFSET (IRO[199].base)
+ (IRO[150].base + ((funcId) * IRO[150].m1))
+#define TSTORM_ACCEPT_CLASSIFY_FAILED_OFFSET (IRO[204].base)
#define TSTORM_APPROXIMATE_MATCH_MULTICAST_FILTERING_OFFSET(pfId) \
- (IRO[198].base + ((pfId) * IRO[198].m1))
-#define TSTORM_ASSERT_LIST_INDEX_OFFSET (IRO[99].base)
+ (IRO[203].base + ((pfId) * IRO[203].m1))
+#define TSTORM_ASSERT_LIST_INDEX_OFFSET (IRO[102].base)
#define TSTORM_ASSERT_LIST_OFFSET(assertListEntry) \
- (IRO[98].base + ((assertListEntry) * IRO[98].m1))
- #define TSTORM_CLIENT_CONFIG_OFFSET(portId, clientId) \
- (IRO[197].base + ((portId) * IRO[197].m1) + ((clientId) * \
- IRO[197].m2))
-#define TSTORM_COMMON_SAFC_WORKAROUND_ENABLE_OFFSET (IRO[104].base)
+ (IRO[101].base + ((assertListEntry) * IRO[101].m1))
+#define TSTORM_COMMON_SAFC_WORKAROUND_ENABLE_OFFSET (IRO[107].base)
#define TSTORM_COMMON_SAFC_WORKAROUND_TIMEOUT_10USEC_OFFSET \
- (IRO[105].base)
-#define TSTORM_ETH_STATS_QUERY_ADDR_OFFSET(pfId) \
- (IRO[96].base + ((pfId) * IRO[96].m1))
-#define TSTORM_FUNC_EN_OFFSET(funcId) \
- (IRO[101].base + ((funcId) * IRO[101].m1))
+ (IRO[108].base)
#define TSTORM_FUNCTION_COMMON_CONFIG_OFFSET(pfId) \
- (IRO[195].base + ((pfId) * IRO[195].m1))
-#define TSTORM_FUNCTION_MODE_OFFSET (IRO[103].base)
-#define TSTORM_INDIRECTION_TABLE_OFFSET(pfId) \
- (IRO[91].base + ((pfId) * IRO[91].m1))
-#define TSTORM_INDIRECTION_TABLE_SIZE (IRO[91].size)
- #define \
- TSTORM_ISCSI_CONN_BUF_PBL_OFFSET(pfId, iscsiConBufPblEntry) \
- (IRO[260].base + ((pfId) * IRO[260].m1) + ((iscsiConBufPblEntry) \
- * IRO[260].m2))
+ (IRO[201].base + ((pfId) * IRO[201].m1))
+#define TSTORM_FUNC_EN_OFFSET(funcId) \
+ (IRO[103].base + ((funcId) * IRO[103].m1))
#define TSTORM_ISCSI_ERROR_BITMAP_OFFSET(pfId) \
- (IRO[264].base + ((pfId) * IRO[264].m1))
+ (IRO[271].base + ((pfId) * IRO[271].m1))
#define TSTORM_ISCSI_L2_ISCSI_OOO_CID_TABLE_OFFSET(pfId) \
- (IRO[265].base + ((pfId) * IRO[265].m1))
+ (IRO[272].base + ((pfId) * IRO[272].m1))
#define TSTORM_ISCSI_L2_ISCSI_OOO_CLIENT_ID_TABLE_OFFSET(pfId) \
- (IRO[266].base + ((pfId) * IRO[266].m1))
-#define TSTORM_ISCSI_L2_ISCSI_OOO_PROD_OFFSET(pfId) \
- (IRO[267].base + ((pfId) * IRO[267].m1))
-#define TSTORM_ISCSI_NUM_OF_TASKS_OFFSET(pfId) \
- (IRO[263].base + ((pfId) * IRO[263].m1))
-#define TSTORM_ISCSI_PAGE_SIZE_LOG_OFFSET(pfId) \
- (IRO[262].base + ((pfId) * IRO[262].m1))
-#define TSTORM_ISCSI_PAGE_SIZE_OFFSET(pfId) \
- (IRO[261].base + ((pfId) * IRO[261].m1))
-#define TSTORM_ISCSI_RQ_SIZE_OFFSET(pfId) \
- (IRO[259].base + ((pfId) * IRO[259].m1))
-#define TSTORM_ISCSI_TCP_LOCAL_ADV_WND_OFFSET(pfId) \
- (IRO[269].base + ((pfId) * IRO[269].m1))
-#define TSTORM_ISCSI_TCP_VARS_FLAGS_OFFSET(pfId) \
- (IRO[256].base + ((pfId) * IRO[256].m1))
-#define TSTORM_ISCSI_TCP_VARS_LSB_LOCAL_MAC_ADDR_OFFSET(pfId) \
- (IRO[257].base + ((pfId) * IRO[257].m1))
-#define TSTORM_ISCSI_TCP_VARS_MSB_LOCAL_MAC_ADDR_OFFSET(pfId) \
- (IRO[258].base + ((pfId) * IRO[258].m1))
-#define TSTORM_MAC_FILTER_CONFIG_OFFSET(pfId) \
- (IRO[196].base + ((pfId) * IRO[196].m1))
- #define TSTORM_PER_COUNTER_ID_STATS_OFFSET(portId, tStatCntId) \
- (IRO[100].base + ((portId) * IRO[100].m1) + ((tStatCntId) * \
- IRO[100].m2))
-#define TSTORM_STATS_FLAGS_OFFSET(pfId) \
- (IRO[95].base + ((pfId) * IRO[95].m1))
-#define TSTORM_TCP_MAX_CWND_OFFSET(pfId) \
- (IRO[211].base + ((pfId) * IRO[211].m1))
-#define TSTORM_VF_TO_PF_OFFSET(funcId) \
- (IRO[102].base + ((funcId) * IRO[102].m1))
-#define USTORM_AGG_DATA_OFFSET (IRO[201].base)
-#define USTORM_AGG_DATA_SIZE (IRO[201].size)
-#define USTORM_ASSERT_LIST_INDEX_OFFSET (IRO[170].base)
-#define USTORM_ASSERT_LIST_OFFSET(assertListEntry) \
- (IRO[169].base + ((assertListEntry) * IRO[169].m1))
-#define USTORM_ETH_PAUSE_ENABLED_OFFSET(portId) \
- (IRO[178].base + ((portId) * IRO[178].m1))
-#define USTORM_ETH_STATS_QUERY_ADDR_OFFSET(pfId) \
- (IRO[172].base + ((pfId) * IRO[172].m1))
-#define USTORM_FCOE_EQ_PROD_OFFSET(pfId) \
- (IRO[313].base + ((pfId) * IRO[313].m1))
-#define USTORM_FUNC_EN_OFFSET(funcId) \
- (IRO[174].base + ((funcId) * IRO[174].m1))
-#define USTORM_FUNCTION_MODE_OFFSET (IRO[177].base)
-#define USTORM_ISCSI_CQ_SIZE_OFFSET(pfId) \
- (IRO[277].base + ((pfId) * IRO[277].m1))
-#define USTORM_ISCSI_CQ_SQN_SIZE_OFFSET(pfId) \
- (IRO[278].base + ((pfId) * IRO[278].m1))
-#define USTORM_ISCSI_ERROR_BITMAP_OFFSET(pfId) \
- (IRO[282].base + ((pfId) * IRO[282].m1))
-#define USTORM_ISCSI_GLOBAL_BUF_PHYS_ADDR_OFFSET(pfId) \
- (IRO[279].base + ((pfId) * IRO[279].m1))
-#define USTORM_ISCSI_NUM_OF_TASKS_OFFSET(pfId) \
- (IRO[275].base + ((pfId) * IRO[275].m1))
-#define USTORM_ISCSI_PAGE_SIZE_LOG_OFFSET(pfId) \
- (IRO[274].base + ((pfId) * IRO[274].m1))
-#define USTORM_ISCSI_PAGE_SIZE_OFFSET(pfId) \
(IRO[273].base + ((pfId) * IRO[273].m1))
-#define USTORM_ISCSI_R2TQ_SIZE_OFFSET(pfId) \
+#define TSTORM_ISCSI_L2_ISCSI_OOO_PROD_OFFSET(pfId) \
+ (IRO[274].base + ((pfId) * IRO[274].m1))
+#define TSTORM_ISCSI_NUM_OF_TASKS_OFFSET(pfId) \
+ (IRO[270].base + ((pfId) * IRO[270].m1))
+#define TSTORM_ISCSI_PAGE_SIZE_LOG_OFFSET(pfId) \
+ (IRO[269].base + ((pfId) * IRO[269].m1))
+#define TSTORM_ISCSI_PAGE_SIZE_OFFSET(pfId) \
+ (IRO[268].base + ((pfId) * IRO[268].m1))
+#define TSTORM_ISCSI_RQ_SIZE_OFFSET(pfId) \
+ (IRO[267].base + ((pfId) * IRO[267].m1))
+#define TSTORM_ISCSI_TCP_LOCAL_ADV_WND_OFFSET(pfId) \
(IRO[276].base + ((pfId) * IRO[276].m1))
-#define USTORM_ISCSI_RQ_BUFFER_SIZE_OFFSET(pfId) \
- (IRO[280].base + ((pfId) * IRO[280].m1))
-#define USTORM_ISCSI_RQ_SIZE_OFFSET(pfId) \
+#define TSTORM_ISCSI_TCP_VARS_FLAGS_OFFSET(pfId) \
+ (IRO[263].base + ((pfId) * IRO[263].m1))
+#define TSTORM_ISCSI_TCP_VARS_LSB_LOCAL_MAC_ADDR_OFFSET(pfId) \
+ (IRO[264].base + ((pfId) * IRO[264].m1))
+#define TSTORM_ISCSI_TCP_VARS_MID_LOCAL_MAC_ADDR_OFFSET(pfId) \
+ (IRO[265].base + ((pfId) * IRO[265].m1))
+#define TSTORM_ISCSI_TCP_VARS_MSB_LOCAL_MAC_ADDR_OFFSET(pfId) \
+ (IRO[266].base + ((pfId) * IRO[266].m1))
+#define TSTORM_MAC_FILTER_CONFIG_OFFSET(pfId) \
+ (IRO[202].base + ((pfId) * IRO[202].m1))
+#define TSTORM_RECORD_SLOW_PATH_OFFSET(funcId) \
+ (IRO[105].base + ((funcId) * IRO[105].m1))
+#define TSTORM_TCP_MAX_CWND_OFFSET(pfId) \
+ (IRO[216].base + ((pfId) * IRO[216].m1))
+#define TSTORM_VF_TO_PF_OFFSET(funcId) \
+ (IRO[104].base + ((funcId) * IRO[104].m1))
+#define USTORM_AGG_DATA_OFFSET (IRO[206].base)
+#define USTORM_AGG_DATA_SIZE (IRO[206].size)
+#define USTORM_ASSERT_LIST_INDEX_OFFSET (IRO[177].base)
+#define USTORM_ASSERT_LIST_OFFSET(assertListEntry) \
+ (IRO[176].base + ((assertListEntry) * IRO[176].m1))
+#define USTORM_CQE_PAGE_NEXT_OFFSET(portId, clientId) \
+ (IRO[205].base + ((portId) * IRO[205].m1) + ((clientId) * \
+ IRO[205].m2))
+#define USTORM_ETH_PAUSE_ENABLED_OFFSET(portId) \
+ (IRO[183].base + ((portId) * IRO[183].m1))
+#define USTORM_FCOE_EQ_PROD_OFFSET(pfId) \
+ (IRO[317].base + ((pfId) * IRO[317].m1))
+#define USTORM_FUNC_EN_OFFSET(funcId) \
+ (IRO[178].base + ((funcId) * IRO[178].m1))
+#define USTORM_ISCSI_CQ_SIZE_OFFSET(pfId) \
(IRO[281].base + ((pfId) * IRO[281].m1))
-#define USTORM_MEM_WORKAROUND_ADDRESS_OFFSET(pfId) \
- (IRO[176].base + ((pfId) * IRO[176].m1))
- #define USTORM_PER_COUNTER_ID_STATS_OFFSET(portId, uStatCntId) \
- (IRO[173].base + ((portId) * IRO[173].m1) + ((uStatCntId) * \
- IRO[173].m2))
- #define USTORM_RX_PRODS_E1X_OFFSET(portId, clientId) \
- (IRO[204].base + ((portId) * IRO[204].m1) + ((clientId) * \
- IRO[204].m2))
-#define USTORM_RX_PRODS_E2_OFFSET(qzoneId) \
- (IRO[205].base + ((qzoneId) * IRO[205].m1))
-#define USTORM_STATS_FLAGS_OFFSET(pfId) \
- (IRO[171].base + ((pfId) * IRO[171].m1))
-#define USTORM_TPA_BTR_OFFSET (IRO[202].base)
-#define USTORM_TPA_BTR_SIZE (IRO[202].size)
-#define USTORM_VF_TO_PF_OFFSET(funcId) \
- (IRO[175].base + ((funcId) * IRO[175].m1))
-#define XSTORM_AGG_INT_FINAL_CLEANUP_COMP_TYPE (IRO[59].base)
-#define XSTORM_AGG_INT_FINAL_CLEANUP_INDEX (IRO[58].base)
-#define XSTORM_ASSERT_LIST_INDEX_OFFSET (IRO[54].base)
-#define XSTORM_ASSERT_LIST_OFFSET(assertListEntry) \
- (IRO[53].base + ((assertListEntry) * IRO[53].m1))
-#define XSTORM_CMNG_PER_PORT_VARS_OFFSET(portId) \
- (IRO[47].base + ((portId) * IRO[47].m1))
-#define XSTORM_E1HOV_OFFSET(pfId) \
- (IRO[55].base + ((pfId) * IRO[55].m1))
-#define XSTORM_ETH_STATS_QUERY_ADDR_OFFSET(pfId) \
- (IRO[45].base + ((pfId) * IRO[45].m1))
-#define XSTORM_FAIRNESS_PER_VN_VARS_OFFSET(pfId) \
- (IRO[49].base + ((pfId) * IRO[49].m1))
-#define XSTORM_FUNC_EN_OFFSET(funcId) \
- (IRO[51].base + ((funcId) * IRO[51].m1))
-#define XSTORM_FUNCTION_MODE_OFFSET (IRO[56].base)
-#define XSTORM_ISCSI_HQ_SIZE_OFFSET(pfId) \
- (IRO[290].base + ((pfId) * IRO[290].m1))
-#define XSTORM_ISCSI_LOCAL_MAC_ADDR0_OFFSET(pfId) \
- (IRO[293].base + ((pfId) * IRO[293].m1))
-#define XSTORM_ISCSI_LOCAL_MAC_ADDR1_OFFSET(pfId) \
- (IRO[294].base + ((pfId) * IRO[294].m1))
-#define XSTORM_ISCSI_LOCAL_MAC_ADDR2_OFFSET(pfId) \
- (IRO[295].base + ((pfId) * IRO[295].m1))
-#define XSTORM_ISCSI_LOCAL_MAC_ADDR3_OFFSET(pfId) \
- (IRO[296].base + ((pfId) * IRO[296].m1))
-#define XSTORM_ISCSI_LOCAL_MAC_ADDR4_OFFSET(pfId) \
- (IRO[297].base + ((pfId) * IRO[297].m1))
-#define XSTORM_ISCSI_LOCAL_MAC_ADDR5_OFFSET(pfId) \
- (IRO[298].base + ((pfId) * IRO[298].m1))
-#define XSTORM_ISCSI_LOCAL_VLAN_OFFSET(pfId) \
- (IRO[299].base + ((pfId) * IRO[299].m1))
-#define XSTORM_ISCSI_NUM_OF_TASKS_OFFSET(pfId) \
- (IRO[289].base + ((pfId) * IRO[289].m1))
-#define XSTORM_ISCSI_PAGE_SIZE_LOG_OFFSET(pfId) \
- (IRO[288].base + ((pfId) * IRO[288].m1))
-#define XSTORM_ISCSI_PAGE_SIZE_OFFSET(pfId) \
- (IRO[287].base + ((pfId) * IRO[287].m1))
-#define XSTORM_ISCSI_R2TQ_SIZE_OFFSET(pfId) \
- (IRO[292].base + ((pfId) * IRO[292].m1))
-#define XSTORM_ISCSI_SQ_SIZE_OFFSET(pfId) \
- (IRO[291].base + ((pfId) * IRO[291].m1))
-#define XSTORM_ISCSI_TCP_VARS_ADV_WND_SCL_OFFSET(pfId) \
+#define USTORM_ISCSI_CQ_SQN_SIZE_OFFSET(pfId) \
+ (IRO[282].base + ((pfId) * IRO[282].m1))
+#define USTORM_ISCSI_ERROR_BITMAP_OFFSET(pfId) \
(IRO[286].base + ((pfId) * IRO[286].m1))
-#define XSTORM_ISCSI_TCP_VARS_FLAGS_OFFSET(pfId) \
- (IRO[285].base + ((pfId) * IRO[285].m1))
-#define XSTORM_ISCSI_TCP_VARS_TOS_OFFSET(pfId) \
- (IRO[284].base + ((pfId) * IRO[284].m1))
-#define XSTORM_ISCSI_TCP_VARS_TTL_OFFSET(pfId) \
+#define USTORM_ISCSI_GLOBAL_BUF_PHYS_ADDR_OFFSET(pfId) \
(IRO[283].base + ((pfId) * IRO[283].m1))
-#define XSTORM_PATH_ID_OFFSET (IRO[65].base)
- #define XSTORM_PER_COUNTER_ID_STATS_OFFSET(portId, xStatCntId) \
- (IRO[50].base + ((portId) * IRO[50].m1) + ((xStatCntId) * \
- IRO[50].m2))
+#define USTORM_ISCSI_NUM_OF_TASKS_OFFSET(pfId) \
+ (IRO[279].base + ((pfId) * IRO[279].m1))
+#define USTORM_ISCSI_PAGE_SIZE_LOG_OFFSET(pfId) \
+ (IRO[278].base + ((pfId) * IRO[278].m1))
+#define USTORM_ISCSI_PAGE_SIZE_OFFSET(pfId) \
+ (IRO[277].base + ((pfId) * IRO[277].m1))
+#define USTORM_ISCSI_R2TQ_SIZE_OFFSET(pfId) \
+ (IRO[280].base + ((pfId) * IRO[280].m1))
+#define USTORM_ISCSI_RQ_BUFFER_SIZE_OFFSET(pfId) \
+ (IRO[284].base + ((pfId) * IRO[284].m1))
+#define USTORM_ISCSI_RQ_SIZE_OFFSET(pfId) \
+ (IRO[285].base + ((pfId) * IRO[285].m1))
+#define USTORM_MEM_WORKAROUND_ADDRESS_OFFSET(pfId) \
+ (IRO[182].base + ((pfId) * IRO[182].m1))
+#define USTORM_RECORD_SLOW_PATH_OFFSET(funcId) \
+ (IRO[180].base + ((funcId) * IRO[180].m1))
+#define USTORM_RX_PRODS_E1X_OFFSET(portId, clientId) \
+ (IRO[209].base + ((portId) * IRO[209].m1) + ((clientId) * \
+ IRO[209].m2))
+#define USTORM_RX_PRODS_E2_OFFSET(qzoneId) \
+ (IRO[210].base + ((qzoneId) * IRO[210].m1))
+#define USTORM_TPA_BTR_OFFSET (IRO[207].base)
+#define USTORM_TPA_BTR_SIZE (IRO[207].size)
+#define USTORM_VF_TO_PF_OFFSET(funcId) \
+ (IRO[179].base + ((funcId) * IRO[179].m1))
+#define XSTORM_AGG_INT_FINAL_CLEANUP_COMP_TYPE (IRO[67].base)
+#define XSTORM_AGG_INT_FINAL_CLEANUP_INDEX (IRO[66].base)
+#define XSTORM_ASSERT_LIST_INDEX_OFFSET (IRO[51].base)
+#define XSTORM_ASSERT_LIST_OFFSET(assertListEntry) \
+ (IRO[50].base + ((assertListEntry) * IRO[50].m1))
+#define XSTORM_CMNG_PER_PORT_VARS_OFFSET(portId) \
+ (IRO[43].base + ((portId) * IRO[43].m1))
+#define XSTORM_FAIRNESS_PER_VN_VARS_OFFSET(pfId) \
+ (IRO[45].base + ((pfId) * IRO[45].m1))
+#define XSTORM_FUNC_EN_OFFSET(funcId) \
+ (IRO[47].base + ((funcId) * IRO[47].m1))
+#define XSTORM_ISCSI_HQ_SIZE_OFFSET(pfId) \
+ (IRO[294].base + ((pfId) * IRO[294].m1))
+#define XSTORM_ISCSI_LOCAL_MAC_ADDR0_OFFSET(pfId) \
+ (IRO[297].base + ((pfId) * IRO[297].m1))
+#define XSTORM_ISCSI_LOCAL_MAC_ADDR1_OFFSET(pfId) \
+ (IRO[298].base + ((pfId) * IRO[298].m1))
+#define XSTORM_ISCSI_LOCAL_MAC_ADDR2_OFFSET(pfId) \
+ (IRO[299].base + ((pfId) * IRO[299].m1))
+#define XSTORM_ISCSI_LOCAL_MAC_ADDR3_OFFSET(pfId) \
+ (IRO[300].base + ((pfId) * IRO[300].m1))
+#define XSTORM_ISCSI_LOCAL_MAC_ADDR4_OFFSET(pfId) \
+ (IRO[301].base + ((pfId) * IRO[301].m1))
+#define XSTORM_ISCSI_LOCAL_MAC_ADDR5_OFFSET(pfId) \
+ (IRO[302].base + ((pfId) * IRO[302].m1))
+#define XSTORM_ISCSI_LOCAL_VLAN_OFFSET(pfId) \
+ (IRO[303].base + ((pfId) * IRO[303].m1))
+#define XSTORM_ISCSI_NUM_OF_TASKS_OFFSET(pfId) \
+ (IRO[293].base + ((pfId) * IRO[293].m1))
+#define XSTORM_ISCSI_PAGE_SIZE_LOG_OFFSET(pfId) \
+ (IRO[292].base + ((pfId) * IRO[292].m1))
+#define XSTORM_ISCSI_PAGE_SIZE_OFFSET(pfId) \
+ (IRO[291].base + ((pfId) * IRO[291].m1))
+#define XSTORM_ISCSI_R2TQ_SIZE_OFFSET(pfId) \
+ (IRO[296].base + ((pfId) * IRO[296].m1))
+#define XSTORM_ISCSI_SQ_SIZE_OFFSET(pfId) \
+ (IRO[295].base + ((pfId) * IRO[295].m1))
+#define XSTORM_ISCSI_TCP_VARS_ADV_WND_SCL_OFFSET(pfId) \
+ (IRO[290].base + ((pfId) * IRO[290].m1))
+#define XSTORM_ISCSI_TCP_VARS_FLAGS_OFFSET(pfId) \
+ (IRO[289].base + ((pfId) * IRO[289].m1))
+#define XSTORM_ISCSI_TCP_VARS_TOS_OFFSET(pfId) \
+ (IRO[288].base + ((pfId) * IRO[288].m1))
+#define XSTORM_ISCSI_TCP_VARS_TTL_OFFSET(pfId) \
+ (IRO[287].base + ((pfId) * IRO[287].m1))
#define XSTORM_RATE_SHAPING_PER_VN_VARS_OFFSET(pfId) \
- (IRO[48].base + ((pfId) * IRO[48].m1))
+ (IRO[44].base + ((pfId) * IRO[44].m1))
+#define XSTORM_RECORD_SLOW_PATH_OFFSET(funcId) \
+ (IRO[49].base + ((funcId) * IRO[49].m1))
#define XSTORM_SPQ_DATA_OFFSET(funcId) \
(IRO[32].base + ((funcId) * IRO[32].m1))
#define XSTORM_SPQ_DATA_SIZE (IRO[32].size)
@@ -260,42 +232,37 @@
(IRO[30].base + ((funcId) * IRO[30].m1))
#define XSTORM_SPQ_PROD_OFFSET(funcId) \
(IRO[31].base + ((funcId) * IRO[31].m1))
-#define XSTORM_STATS_FLAGS_OFFSET(pfId) \
- (IRO[43].base + ((pfId) * IRO[43].m1))
#define XSTORM_TCP_GLOBAL_DEL_ACK_COUNTER_ENABLED_OFFSET(portId) \
- (IRO[206].base + ((portId) * IRO[206].m1))
+ (IRO[211].base + ((portId) * IRO[211].m1))
#define XSTORM_TCP_GLOBAL_DEL_ACK_COUNTER_MAX_COUNT_OFFSET(portId) \
- (IRO[207].base + ((portId) * IRO[207].m1))
+ (IRO[212].base + ((portId) * IRO[212].m1))
#define XSTORM_TCP_TX_SWS_TIMER_VAL_OFFSET(pfId) \
- (IRO[209].base + (((pfId)>>1) * IRO[209].m1) + (((pfId)&1) * \
- IRO[209].m2))
+ (IRO[214].base + (((pfId)>>1) * IRO[214].m1) + (((pfId)&1) * \
+ IRO[214].m2))
#define XSTORM_VF_TO_PF_OFFSET(funcId) \
- (IRO[52].base + ((funcId) * IRO[52].m1))
+ (IRO[48].base + ((funcId) * IRO[48].m1))
#define COMMON_ASM_INVALID_ASSERT_OPCODE 0x0
-/* RSS hash types */
-#define DEFAULT_HASH_TYPE 0
-#define IPV4_HASH_TYPE 1
-#define TCP_IPV4_HASH_TYPE 2
-#define IPV6_HASH_TYPE 3
-#define TCP_IPV6_HASH_TYPE 4
-#define VLAN_PRI_HASH_TYPE 5
-#define E1HOV_PRI_HASH_TYPE 6
-#define DSCP_HASH_TYPE 7
+/**
+* This file defines HSI constants for the ETH flow
+*/
+#ifdef _EVEREST_MICROCODE
+#include "Microcode\Generated\DataTypes\eth_rx_bd.h"
+#include "Microcode\Generated\DataTypes\eth_tx_bd.h"
+#include "Microcode\Generated\DataTypes\eth_rx_cqe.h"
+#include "Microcode\Generated\DataTypes\eth_rx_sge.h"
+#include "Microcode\Generated\DataTypes\eth_rx_cqe_next_page.h"
+#endif
/* Ethernet Ring parameters */
#define X_ETH_LOCAL_RING_SIZE 13
-#define FIRST_BD_IN_PKT 0
+#define FIRST_BD_IN_PKT 0
#define PARSE_BD_INDEX 1
#define NUM_OF_ETH_BDS_IN_PAGE ((PAGE_SIZE)/(STRUCT_SIZE(eth_tx_bd)/8))
#define U_ETH_NUM_OF_SGES_TO_FETCH 8
#define U_ETH_MAX_SGES_FOR_PACKET 3
-/*Tx params*/
-#define X_ETH_NO_VLAN 0
-#define X_ETH_OUTBAND_VLAN 1
-#define X_ETH_INBAND_VLAN 2
/* Rx ring params */
#define U_ETH_LOCAL_BD_RING_SIZE 8
#define U_ETH_LOCAL_SGE_RING_SIZE 10
@@ -311,79 +278,64 @@
#define U_ETH_BDS_PER_PAGE (PAGE_SIZE/(STRUCT_SIZE(eth_rx_bd)/8))
#define U_ETH_SGES_PER_PAGE (PAGE_SIZE/(STRUCT_SIZE(eth_rx_sge)/8))
-#define U_ETH_BDS_PER_PAGE_MASK (U_ETH_BDS_PER_PAGE-1)
-#define U_ETH_CQE_PER_PAGE_MASK (TU_ETH_CQES_PER_PAGE-1)
+#define U_ETH_BDS_PER_PAGE_MASK (U_ETH_BDS_PER_PAGE-1)
+#define U_ETH_CQE_PER_PAGE_MASK (TU_ETH_CQES_PER_PAGE-1)
#define U_ETH_SGES_PER_PAGE_MASK (U_ETH_SGES_PER_PAGE-1)
#define U_ETH_UNDEFINED_Q 0xFF
-/* values of command IDs in the ramrod message */
-#define RAMROD_CMD_ID_ETH_UNUSED 0
-#define RAMROD_CMD_ID_ETH_CLIENT_SETUP 1
-#define RAMROD_CMD_ID_ETH_UPDATE 2
-#define RAMROD_CMD_ID_ETH_HALT 3
-#define RAMROD_CMD_ID_ETH_FORWARD_SETUP 4
-#define RAMROD_CMD_ID_ETH_ACTIVATE 5
-#define RAMROD_CMD_ID_ETH_DEACTIVATE 6
-#define RAMROD_CMD_ID_ETH_EMPTY 7
-#define RAMROD_CMD_ID_ETH_TERMINATE 8
-
-/* command values for set mac command */
-#define T_ETH_MAC_COMMAND_SET 0
-#define T_ETH_MAC_COMMAND_INVALIDATE 1
-
#define T_ETH_INDIRECTION_TABLE_SIZE 128
+#define T_ETH_RSS_KEY 10
+#define ETH_NUM_OF_RSS_ENGINES_E2 72
+
+#define FILTER_RULES_COUNT 16
+#define MULTICAST_RULES_COUNT 16
+#define CLASSIFY_RULES_COUNT 16
/*The CRC32 seed, that is used for the hash(reduction) multicast address */
-#define T_ETH_CRC32_HASH_SEED 0x00000000
+#define ETH_CRC32_HASH_SEED 0x00000000
+
+#define ETH_CRC32_HASH_BIT_SIZE (8)
+#define ETH_CRC32_HASH_MASK EVAL((1<<ETH_CRC32_HASH_BIT_SIZE)-1)
/* Maximal L2 clients supported */
#define ETH_MAX_RX_CLIENTS_E1 18
#define ETH_MAX_RX_CLIENTS_E1H 28
+#define ETH_MAX_RX_CLIENTS_E2 152
-#define MAX_STAT_COUNTER_ID ETH_MAX_RX_CLIENTS_E1H
+/* Maximal statistics client Ids */
+#define MAX_STAT_COUNTER_ID_E1 36
+#define MAX_STAT_COUNTER_ID_E1H 56
+#define MAX_STAT_COUNTER_ID_E2 140
+
+#define MAX_MAC_CREDIT_E1 192 /* Per Chip */
+#define MAX_MAC_CREDIT_E1H 256 /* Per Chip */
+#define MAX_MAC_CREDIT_E2 272 /* Per Path */
+#define MAX_VLAN_CREDIT_E1 0 /* Per Chip */
+#define MAX_VLAN_CREDIT_E1H 0 /* Per Chip */
+#define MAX_VLAN_CREDIT_E2 272 /* Per Path */
+
/* Maximal aggregation queues supported */
#define ETH_MAX_AGGREGATION_QUEUES_E1 32
-#define ETH_MAX_AGGREGATION_QUEUES_E1H 64
-
-/* ETH RSS modes */
-#define ETH_RSS_MODE_DISABLED 0
-#define ETH_RSS_MODE_REGULAR 1
-#define ETH_RSS_MODE_VLAN_PRI 2
-#define ETH_RSS_MODE_E1HOV_PRI 3
-#define ETH_RSS_MODE_IP_DSCP 4
-#define ETH_RSS_MODE_E2_INTEG 5
+#define ETH_MAX_AGGREGATION_QUEUES_E1H_E2 64
-/* ETH vlan filtering modes */
-#define ETH_VLAN_FILTER_ANY_VLAN 0 /* Don't filter by vlan */
-#define ETH_VLAN_FILTER_SPECIFIC_VLAN \
- 1 /* Only the vlan_id is allowed */
-#define ETH_VLAN_FILTER_CLASSIFY \
- 2 /* vlan will be added to CAM for classification */
+#define ETH_NUM_OF_MCAST_BINS 256
+#define ETH_NUM_OF_MCAST_ENGINES_E2 72
-/* Fast path CQE selection */
-#define ETH_FP_CQE_REGULAR 0
-#define ETH_FP_CQE_SGL 1
-#define ETH_FP_CQE_RAW 2
+#define ETH_MIN_RX_CQES_WITHOUT_TPA (MAX_RAMRODS_PER_PORT + 3)
+#define ETH_MIN_RX_CQES_WITH_TPA_E1 \
+ (ETH_MAX_AGGREGATION_QUEUES_E1 + ETH_MIN_RX_CQES_WITHOUT_TPA)
+#define ETH_MIN_RX_CQES_WITH_TPA_E1H_E2 \
+ (ETH_MAX_AGGREGATION_QUEUES_E1H_E2 + ETH_MIN_RX_CQES_WITHOUT_TPA)
+
+#define DISABLE_STATISTIC_COUNTER_ID_VALUE 0
/**
-* This file defines HSI constants common to all microcode flows
-*/
-
-/* Connection types */
-#define ETH_CONNECTION_TYPE 0
-#define TOE_CONNECTION_TYPE 1
-#define RDMA_CONNECTION_TYPE 2
-#define ISCSI_CONNECTION_TYPE 3
-#define FCOE_CONNECTION_TYPE 4
-#define RESERVED_CONNECTION_TYPE_0 5
-#define RESERVED_CONNECTION_TYPE_1 6
-#define RESERVED_CONNECTION_TYPE_2 7
-#define NONE_CONNECTION_TYPE 8
-
+ * This file defines HSI constants common to all microcode flows
+ */
#define PROTOCOL_STATE_BIT_OFFSET 6
@@ -391,25 +343,9 @@
#define TOE_STATE (TOE_CONNECTION_TYPE << PROTOCOL_STATE_BIT_OFFSET)
#define RDMA_STATE (RDMA_CONNECTION_TYPE << PROTOCOL_STATE_BIT_OFFSET)
-/* values of command IDs in the ramrod message */
-#define RAMROD_CMD_ID_COMMON_FUNCTION_START 1
-#define RAMROD_CMD_ID_COMMON_FUNCTION_STOP 2
-#define RAMROD_CMD_ID_COMMON_CFC_DEL 3
-#define RAMROD_CMD_ID_COMMON_CFC_DEL_WB 4
-#define RAMROD_CMD_ID_COMMON_SET_MAC 5
-#define RAMROD_CMD_ID_COMMON_STAT_QUERY 6
-#define RAMROD_CMD_ID_COMMON_STOP_TRAFFIC 7
-#define RAMROD_CMD_ID_COMMON_START_TRAFFIC 8
-
/* microcode fixed page page size 4K (chains and ring segments) */
#define MC_PAGE_SIZE 4096
-
-/* Host coalescing constants */
-#define HC_IGU_BC_MODE 0
-#define HC_IGU_NBC_MODE 1
-/* Host coalescing constants. E1 includes E1H as well */
-
/* Number of indices per slow-path SB */
#define HC_SP_SB_MAX_INDICES 16
@@ -418,30 +354,17 @@
#define HC_SB_MAX_INDICES_E2 8
#define HC_SB_MAX_SB_E1X 32
-#define HC_SB_MAX_SB_E2 136
+#define HC_SB_MAX_SB_E2 136
#define HC_SP_SB_ID 0xde
-#define HC_REGULAR_SEGMENT 0
-#define HC_DEFAULT_SEGMENT 1
#define HC_SB_MAX_SM 2
#define HC_SB_MAX_DYNAMIC_INDICES 4
-#define HC_FUNCTION_DISABLED 0xff
-/* used by the driver to get the SB offset */
-#define USTORM_ID 0
-#define CSTORM_ID 1
-#define XSTORM_ID 2
-#define TSTORM_ID 3
-#define ATTENTION_ID 4
/* max number of slow path commands per port */
#define MAX_RAMRODS_PER_PORT 8
-/* values for RX ETH CQE type field */
-#define RX_ETH_CQE_TYPE_ETH_FASTPATH 0
-#define RX_ETH_CQE_TYPE_ETH_RAMROD 1
-
/**** DEFINES FOR TIMERS/CLOCKS RESOLUTIONS ****/
@@ -451,7 +374,7 @@
#define XSEMI_CLK1_RESUL_CHIP (1e-3)
-#define SDM_TIMER_TICK_RESUL_CHIP (4*(1e-6))
+#define SDM_TIMER_TICK_RESUL_CHIP (4 * (1e-6))
/**** END DEFINES FOR TIMERS/CLOCKS RESOLUTIONS ****/
@@ -460,72 +383,28 @@
#define FW_LOG_LIST_SIZE 50
-#define NUM_OF_PROTOCOLS 4
#define NUM_OF_SAFC_BITS 16
#define MAX_COS_NUMBER 4
-
-#define FAIRNESS_COS_WRR_MODE 0
-#define FAIRNESS_COS_ETS_MODE 1
-
-
-/* Priority Flow Control (PFC) */
+#define MAX_TRAFFIC_TYPES 8
#define MAX_PFC_PRIORITIES 8
-#define MAX_PFC_TRAFFIC_TYPES 8
-
-/* Available Traffic Types for Link Layer Flow Control */
-#define LLFC_TRAFFIC_TYPE_NW 0
-#define LLFC_TRAFFIC_TYPE_FCOE 1
-#define LLFC_TRAFFIC_TYPE_ISCSI 2
- /***************** START OF E2 INTEGRATION \
- CODE***************************************/
-#define LLFC_TRAFFIC_TYPE_NW_COS1_E2INTEG 3
- /***************** END OF E2 INTEGRATION \
- CODE***************************************/
-#define LLFC_TRAFFIC_TYPE_MAX 4
/* used by array traffic_type_to_priority[] to mark traffic type \
that is not mapped to priority*/
#define LLFC_TRAFFIC_TYPE_TO_PRIORITY_UNMAPPED 0xFF
-#define LLFC_MODE_NONE 0
-#define LLFC_MODE_PFC 1
-#define LLFC_MODE_SAFC 2
-
-#define DCB_DISABLED 0
-#define DCB_ENABLED 1
-
-#define UNKNOWN_ADDRESS 0
-#define UNICAST_ADDRESS 1
-#define MULTICAST_ADDRESS 2
-#define BROADCAST_ADDRESS 3
-
-#define SINGLE_FUNCTION 0
-#define MULTI_FUNCTION_SD 1
-#define MULTI_FUNCTION_SI 2
-
-#define IP_V4 0
-#define IP_V6 1
-
#define C_ERES_PER_PAGE \
(PAGE_SIZE / BITS_TO_BYTES(STRUCT_SIZE(event_ring_elem)))
#define C_ERE_PER_PAGE_MASK (C_ERES_PER_PAGE - 1)
-#define EVENT_RING_OPCODE_VF_PF_CHANNEL 0
-#define EVENT_RING_OPCODE_FUNCTION_START 1
-#define EVENT_RING_OPCODE_FUNCTION_STOP 2
-#define EVENT_RING_OPCODE_CFC_DEL 3
-#define EVENT_RING_OPCODE_CFC_DEL_WB 4
-#define EVENT_RING_OPCODE_SET_MAC 5
-#define EVENT_RING_OPCODE_STAT_QUERY 6
-#define EVENT_RING_OPCODE_STOP_TRAFFIC 7
-#define EVENT_RING_OPCODE_START_TRAFFIC 8
-#define EVENT_RING_OPCODE_FORWARD_SETUP 9
+#define STATS_QUERY_CMD_COUNT 16
-#define VF_PF_CHANNEL_STATE_READY 0
-#define VF_PF_CHANNEL_STATE_WAITING_FOR_ACK 1
+#define NIV_LIST_TABLE_SIZE 4096
-#define VF_PF_CHANNEL_STATE_MAX_NUMBER 2
+#define INVALID_VNIC_ID 0xFF
+
+
+#define UNDEF_IRO 0x80000000
#endif /* BNX2X_FW_DEFS_H */
diff --git a/drivers/net/bnx2x/bnx2x_hsi.h b/drivers/net/bnx2x/bnx2x_hsi.h
index cdf19fe..0692d75 100644
--- a/drivers/net/bnx2x/bnx2x_hsi.h
+++ b/drivers/net/bnx2x/bnx2x_hsi.h
@@ -11,7 +11,7 @@
#include "bnx2x_fw_defs.h"
-#define FW_ENCODE_32BIT_PATTERN 0x1e1e1e1e
+#define FW_ENCODE_32BIT_PATTERN 0x1e1e1e1e
struct license_key {
u32 reserved[6];
@@ -33,201 +33,366 @@
u32 reserved_b[4];
};
-#define PORT_0 0
-#define PORT_1 1
-#define PORT_MAX 2
+
+#define PORT_0 0
+#define PORT_1 1
+#define PORT_MAX 2
/****************************************************************************
- * Shared HW configuration *
+ * Shared HW configuration *
****************************************************************************/
-struct shared_hw_cfg { /* NVRAM Offset */
+#define PIN_CFG_NA 0x00000000
+#define PIN_CFG_GPIO0_P0 0x00000001
+#define PIN_CFG_GPIO1_P0 0x00000002
+#define PIN_CFG_GPIO2_P0 0x00000003
+#define PIN_CFG_GPIO3_P0 0x00000004
+#define PIN_CFG_GPIO0_P1 0x00000005
+#define PIN_CFG_GPIO1_P1 0x00000006
+#define PIN_CFG_GPIO2_P1 0x00000007
+#define PIN_CFG_GPIO3_P1 0x00000008
+#define PIN_CFG_EPIO0 0x00000009
+#define PIN_CFG_EPIO1 0x0000000a
+#define PIN_CFG_EPIO2 0x0000000b
+#define PIN_CFG_EPIO3 0x0000000c
+#define PIN_CFG_EPIO4 0x0000000d
+#define PIN_CFG_EPIO5 0x0000000e
+#define PIN_CFG_EPIO6 0x0000000f
+#define PIN_CFG_EPIO7 0x00000010
+#define PIN_CFG_EPIO8 0x00000011
+#define PIN_CFG_EPIO9 0x00000012
+#define PIN_CFG_EPIO10 0x00000013
+#define PIN_CFG_EPIO11 0x00000014
+#define PIN_CFG_EPIO12 0x00000015
+#define PIN_CFG_EPIO13 0x00000016
+#define PIN_CFG_EPIO14 0x00000017
+#define PIN_CFG_EPIO15 0x00000018
+#define PIN_CFG_EPIO16 0x00000019
+#define PIN_CFG_EPIO17 0x0000001a
+#define PIN_CFG_EPIO18 0x0000001b
+#define PIN_CFG_EPIO19 0x0000001c
+#define PIN_CFG_EPIO20 0x0000001d
+#define PIN_CFG_EPIO21 0x0000001e
+#define PIN_CFG_EPIO22 0x0000001f
+#define PIN_CFG_EPIO23 0x00000020
+#define PIN_CFG_EPIO24 0x00000021
+#define PIN_CFG_EPIO25 0x00000022
+#define PIN_CFG_EPIO26 0x00000023
+#define PIN_CFG_EPIO27 0x00000024
+#define PIN_CFG_EPIO28 0x00000025
+#define PIN_CFG_EPIO29 0x00000026
+#define PIN_CFG_EPIO30 0x00000027
+#define PIN_CFG_EPIO31 0x00000028
+
+/* EPIO definition */
+#define EPIO_CFG_NA 0x00000000
+#define EPIO_CFG_EPIO0 0x00000001
+#define EPIO_CFG_EPIO1 0x00000002
+#define EPIO_CFG_EPIO2 0x00000003
+#define EPIO_CFG_EPIO3 0x00000004
+#define EPIO_CFG_EPIO4 0x00000005
+#define EPIO_CFG_EPIO5 0x00000006
+#define EPIO_CFG_EPIO6 0x00000007
+#define EPIO_CFG_EPIO7 0x00000008
+#define EPIO_CFG_EPIO8 0x00000009
+#define EPIO_CFG_EPIO9 0x0000000a
+#define EPIO_CFG_EPIO10 0x0000000b
+#define EPIO_CFG_EPIO11 0x0000000c
+#define EPIO_CFG_EPIO12 0x0000000d
+#define EPIO_CFG_EPIO13 0x0000000e
+#define EPIO_CFG_EPIO14 0x0000000f
+#define EPIO_CFG_EPIO15 0x00000010
+#define EPIO_CFG_EPIO16 0x00000011
+#define EPIO_CFG_EPIO17 0x00000012
+#define EPIO_CFG_EPIO18 0x00000013
+#define EPIO_CFG_EPIO19 0x00000014
+#define EPIO_CFG_EPIO20 0x00000015
+#define EPIO_CFG_EPIO21 0x00000016
+#define EPIO_CFG_EPIO22 0x00000017
+#define EPIO_CFG_EPIO23 0x00000018
+#define EPIO_CFG_EPIO24 0x00000019
+#define EPIO_CFG_EPIO25 0x0000001a
+#define EPIO_CFG_EPIO26 0x0000001b
+#define EPIO_CFG_EPIO27 0x0000001c
+#define EPIO_CFG_EPIO28 0x0000001d
+#define EPIO_CFG_EPIO29 0x0000001e
+#define EPIO_CFG_EPIO30 0x0000001f
+#define EPIO_CFG_EPIO31 0x00000020
+
+
+struct shared_hw_cfg { /* NVRAM Offset */
/* Up to 16 bytes of NULL-terminated string */
- u8 part_num[16]; /* 0x104 */
+ u8 part_num[16]; /* 0x104 */
- u32 config; /* 0x114 */
-#define SHARED_HW_CFG_MDIO_VOLTAGE_MASK 0x00000001
-#define SHARED_HW_CFG_MDIO_VOLTAGE_SHIFT 0
-#define SHARED_HW_CFG_MDIO_VOLTAGE_1_2V 0x00000000
-#define SHARED_HW_CFG_MDIO_VOLTAGE_2_5V 0x00000001
-#define SHARED_HW_CFG_MCP_RST_ON_CORE_RST_EN 0x00000002
+ u32 config; /* 0x114 */
+ #define SHARED_HW_CFG_MDIO_VOLTAGE_MASK 0x00000001
+ #define SHARED_HW_CFG_MDIO_VOLTAGE_SHIFT 0
+ #define SHARED_HW_CFG_MDIO_VOLTAGE_1_2V 0x00000000
+ #define SHARED_HW_CFG_MDIO_VOLTAGE_2_5V 0x00000001
+ #define SHARED_HW_CFG_MCP_RST_ON_CORE_RST_EN 0x00000002
-#define SHARED_HW_CFG_PORT_SWAP 0x00000004
+ #define SHARED_HW_CFG_PORT_SWAP 0x00000004
-#define SHARED_HW_CFG_BEACON_WOL_EN 0x00000008
+ #define SHARED_HW_CFG_BEACON_WOL_EN 0x00000008
-#define SHARED_HW_CFG_MFW_SELECT_MASK 0x00000700
-#define SHARED_HW_CFG_MFW_SELECT_SHIFT 8
+ #define SHARED_HW_CFG_PCIE_GEN3_DISABLED 0x00000000
+ #define SHARED_HW_CFG_PCIE_GEN3_ENABLED 0x00000010
+
+ #define SHARED_HW_CFG_MFW_SELECT_MASK 0x00000700
+ #define SHARED_HW_CFG_MFW_SELECT_SHIFT 8
/* Whatever MFW found in NVM
(if multiple found, priority order is: NC-SI, UMP, IPMI) */
-#define SHARED_HW_CFG_MFW_SELECT_DEFAULT 0x00000000
-#define SHARED_HW_CFG_MFW_SELECT_NC_SI 0x00000100
-#define SHARED_HW_CFG_MFW_SELECT_UMP 0x00000200
-#define SHARED_HW_CFG_MFW_SELECT_IPMI 0x00000300
+ #define SHARED_HW_CFG_MFW_SELECT_DEFAULT 0x00000000
+ #define SHARED_HW_CFG_MFW_SELECT_NC_SI 0x00000100
+ #define SHARED_HW_CFG_MFW_SELECT_UMP 0x00000200
+ #define SHARED_HW_CFG_MFW_SELECT_IPMI 0x00000300
/* Use SPIO4 as an arbiter between: 0-NC_SI, 1-IPMI
(can only be used when an add-in board, not BMC, pulls-down SPIO4) */
-#define SHARED_HW_CFG_MFW_SELECT_SPIO4_NC_SI_IPMI 0x00000400
+ #define SHARED_HW_CFG_MFW_SELECT_SPIO4_NC_SI_IPMI 0x00000400
/* Use SPIO4 as an arbiter between: 0-UMP, 1-IPMI
(can only be used when an add-in board, not BMC, pulls-down SPIO4) */
-#define SHARED_HW_CFG_MFW_SELECT_SPIO4_UMP_IPMI 0x00000500
+ #define SHARED_HW_CFG_MFW_SELECT_SPIO4_UMP_IPMI 0x00000500
/* Use SPIO4 as an arbiter between: 0-NC-SI, 1-UMP
(can only be used when an add-in board, not BMC, pulls-down SPIO4) */
-#define SHARED_HW_CFG_MFW_SELECT_SPIO4_NC_SI_UMP 0x00000600
+ #define SHARED_HW_CFG_MFW_SELECT_SPIO4_NC_SI_UMP 0x00000600
-#define SHARED_HW_CFG_LED_MODE_MASK 0x000f0000
-#define SHARED_HW_CFG_LED_MODE_SHIFT 16
-#define SHARED_HW_CFG_LED_MAC1 0x00000000
-#define SHARED_HW_CFG_LED_PHY1 0x00010000
-#define SHARED_HW_CFG_LED_PHY2 0x00020000
-#define SHARED_HW_CFG_LED_PHY3 0x00030000
-#define SHARED_HW_CFG_LED_MAC2 0x00040000
-#define SHARED_HW_CFG_LED_PHY4 0x00050000
-#define SHARED_HW_CFG_LED_PHY5 0x00060000
-#define SHARED_HW_CFG_LED_PHY6 0x00070000
-#define SHARED_HW_CFG_LED_MAC3 0x00080000
-#define SHARED_HW_CFG_LED_PHY7 0x00090000
-#define SHARED_HW_CFG_LED_PHY9 0x000a0000
-#define SHARED_HW_CFG_LED_PHY11 0x000b0000
-#define SHARED_HW_CFG_LED_MAC4 0x000c0000
-#define SHARED_HW_CFG_LED_PHY8 0x000d0000
-#define SHARED_HW_CFG_LED_EXTPHY1 0x000e0000
+ #define SHARED_HW_CFG_LED_MODE_MASK 0x000f0000
+ #define SHARED_HW_CFG_LED_MODE_SHIFT 16
+ #define SHARED_HW_CFG_LED_MAC1 0x00000000
+ #define SHARED_HW_CFG_LED_PHY1 0x00010000
+ #define SHARED_HW_CFG_LED_PHY2 0x00020000
+ #define SHARED_HW_CFG_LED_PHY3 0x00030000
+ #define SHARED_HW_CFG_LED_MAC2 0x00040000
+ #define SHARED_HW_CFG_LED_PHY4 0x00050000
+ #define SHARED_HW_CFG_LED_PHY5 0x00060000
+ #define SHARED_HW_CFG_LED_PHY6 0x00070000
+ #define SHARED_HW_CFG_LED_MAC3 0x00080000
+ #define SHARED_HW_CFG_LED_PHY7 0x00090000
+ #define SHARED_HW_CFG_LED_PHY9 0x000a0000
+ #define SHARED_HW_CFG_LED_PHY11 0x000b0000
+ #define SHARED_HW_CFG_LED_MAC4 0x000c0000
+ #define SHARED_HW_CFG_LED_PHY8 0x000d0000
+ #define SHARED_HW_CFG_LED_EXTPHY1 0x000e0000
-#define SHARED_HW_CFG_AN_ENABLE_MASK 0x3f000000
-#define SHARED_HW_CFG_AN_ENABLE_SHIFT 24
-#define SHARED_HW_CFG_AN_ENABLE_CL37 0x01000000
-#define SHARED_HW_CFG_AN_ENABLE_CL73 0x02000000
-#define SHARED_HW_CFG_AN_ENABLE_BAM 0x04000000
-#define SHARED_HW_CFG_AN_ENABLE_PARALLEL_DETECTION 0x08000000
-#define SHARED_HW_CFG_AN_EN_SGMII_FIBER_AUTO_DETECT 0x10000000
-#define SHARED_HW_CFG_AN_ENABLE_REMOTE_PHY 0x20000000
+ #define SHARED_HW_CFG_AN_ENABLE_MASK 0x3f000000
+ #define SHARED_HW_CFG_AN_ENABLE_SHIFT 24
+ #define SHARED_HW_CFG_AN_ENABLE_CL37 0x01000000
+ #define SHARED_HW_CFG_AN_ENABLE_CL73 0x02000000
+ #define SHARED_HW_CFG_AN_ENABLE_BAM 0x04000000
+ #define SHARED_HW_CFG_AN_ENABLE_PARALLEL_DETECTION 0x08000000
+ #define SHARED_HW_CFG_AN_EN_SGMII_FIBER_AUTO_DETECT 0x10000000
+ #define SHARED_HW_CFG_AN_ENABLE_REMOTE_PHY 0x20000000
- u32 config2; /* 0x118 */
+ #define SHARED_HW_CFG_SRIOV_MASK 0x40000000
+ #define SHARED_HW_CFG_SRIOV_DISABLED 0x00000000
+ #define SHARED_HW_CFG_SRIOV_ENABLED 0x40000000
+
+ #define SHARED_HW_CFG_ATC_MASK 0x80000000
+ #define SHARED_HW_CFG_ATC_DISABLED 0x00000000
+ #define SHARED_HW_CFG_ATC_ENABLED 0x80000000
+
+ u32 config2; /* 0x118 */
/* one time auto detect grace period (in sec) */
-#define SHARED_HW_CFG_GRACE_PERIOD_MASK 0x000000ff
-#define SHARED_HW_CFG_GRACE_PERIOD_SHIFT 0
+ #define SHARED_HW_CFG_GRACE_PERIOD_MASK 0x000000ff
+ #define SHARED_HW_CFG_GRACE_PERIOD_SHIFT 0
-#define SHARED_HW_CFG_PCIE_GEN2_ENABLED 0x00000100
+ #define SHARED_HW_CFG_PCIE_GEN2_ENABLED 0x00000100
+ #define SHARED_HW_CFG_PCIE_GEN2_DISABLED 0x00000000
/* The default value for the core clock is 250MHz and it is
achieved by setting the clock change to 4 */
-#define SHARED_HW_CFG_CLOCK_CHANGE_MASK 0x00000e00
-#define SHARED_HW_CFG_CLOCK_CHANGE_SHIFT 9
+ #define SHARED_HW_CFG_CLOCK_CHANGE_MASK 0x00000e00
+ #define SHARED_HW_CFG_CLOCK_CHANGE_SHIFT 9
-#define SHARED_HW_CFG_SMBUS_TIMING_100KHZ 0x00000000
-#define SHARED_HW_CFG_SMBUS_TIMING_400KHZ 0x00001000
+ #define SHARED_HW_CFG_SMBUS_TIMING_MASK 0x00001000
+ #define SHARED_HW_CFG_SMBUS_TIMING_100KHZ 0x00000000
+ #define SHARED_HW_CFG_SMBUS_TIMING_400KHZ 0x00001000
-#define SHARED_HW_CFG_HIDE_PORT1 0x00002000
+ #define SHARED_HW_CFG_HIDE_PORT1 0x00002000
+
+ #define SHARED_HW_CFG_WOL_CAPABLE_MASK 0x00004000
+ #define SHARED_HW_CFG_WOL_CAPABLE_DISABLED 0x00000000
+ #define SHARED_HW_CFG_WOL_CAPABLE_ENABLED 0x00004000
+
+ /* Output low when PERST is asserted */
+ #define SHARED_HW_CFG_SPIO4_FOLLOW_PERST_MASK 0x00008000
+ #define SHARED_HW_CFG_SPIO4_FOLLOW_PERST_DISABLED 0x00000000
+ #define SHARED_HW_CFG_SPIO4_FOLLOW_PERST_ENABLED 0x00008000
+
+ #define SHARED_HW_CFG_PCIE_GEN2_PREEMPHASIS_MASK 0x00070000
+ #define SHARED_HW_CFG_PCIE_GEN2_PREEMPHASIS_SHIFT 16
+ #define SHARED_HW_CFG_PCIE_GEN2_PREEMPHASIS_HW 0x00000000
+ #define SHARED_HW_CFG_PCIE_GEN2_PREEMPHASIS_0DB 0x00010000
+ #define SHARED_HW_CFG_PCIE_GEN2_PREEMPHASIS_3_5DB 0x00020000
+ #define SHARED_HW_CFG_PCIE_GEN2_PREEMPHASIS_6_0DB 0x00030000
/* The fan failure mechanism is usually related to the PHY type
- since the power consumption of the board is determined by the PHY.
- Currently, fan is required for most designs with SFX7101, BCM8727
- and BCM8481. If a fan is not required for a board which uses one
- of those PHYs, this field should be set to "Disabled". If a fan is
- required for a different PHY type, this option should be set to
- "Enabled".
- The fan failure indication is expected on
- SPIO5 */
-#define SHARED_HW_CFG_FAN_FAILURE_MASK 0x00180000
-#define SHARED_HW_CFG_FAN_FAILURE_SHIFT 19
-#define SHARED_HW_CFG_FAN_FAILURE_PHY_TYPE 0x00000000
-#define SHARED_HW_CFG_FAN_FAILURE_DISABLED 0x00080000
-#define SHARED_HW_CFG_FAN_FAILURE_ENABLED 0x00100000
+ since the power consumption of the board is determined by the PHY.
+ Currently, fan is required for most designs with SFX7101, BCM8727
+ and BCM8481. If a fan is not required for a board which uses one
+ of those PHYs, this field should be set to "Disabled". If a fan is
+ required for a different PHY type, this option should be set to
+ "Enabled". The fan failure indication is expected on SPIO5 */
+ #define SHARED_HW_CFG_FAN_FAILURE_MASK 0x00180000
+ #define SHARED_HW_CFG_FAN_FAILURE_SHIFT 19
+ #define SHARED_HW_CFG_FAN_FAILURE_PHY_TYPE 0x00000000
+ #define SHARED_HW_CFG_FAN_FAILURE_DISABLED 0x00080000
+ #define SHARED_HW_CFG_FAN_FAILURE_ENABLED 0x00100000
- /* Set the MDC/MDIO access for the first external phy */
-#define SHARED_HW_CFG_MDC_MDIO_ACCESS1_MASK 0x1C000000
-#define SHARED_HW_CFG_MDC_MDIO_ACCESS1_SHIFT 26
-#define SHARED_HW_CFG_MDC_MDIO_ACCESS1_PHY_TYPE 0x00000000
-#define SHARED_HW_CFG_MDC_MDIO_ACCESS1_EMAC0 0x04000000
-#define SHARED_HW_CFG_MDC_MDIO_ACCESS1_EMAC1 0x08000000
-#define SHARED_HW_CFG_MDC_MDIO_ACCESS1_BOTH 0x0c000000
-#define SHARED_HW_CFG_MDC_MDIO_ACCESS1_SWAPPED 0x10000000
+ /* ASPM Power Management support */
+ #define SHARED_HW_CFG_ASPM_SUPPORT_MASK 0x00600000
+ #define SHARED_HW_CFG_ASPM_SUPPORT_SHIFT 21
+ #define SHARED_HW_CFG_ASPM_SUPPORT_L0S_L1_ENABLED 0x00000000
+ #define SHARED_HW_CFG_ASPM_SUPPORT_L0S_DISABLED 0x00200000
+ #define SHARED_HW_CFG_ASPM_SUPPORT_L1_DISABLED 0x00400000
+ #define SHARED_HW_CFG_ASPM_SUPPORT_L0S_L1_DISABLED 0x00600000
- /* Set the MDC/MDIO access for the second external phy */
-#define SHARED_HW_CFG_MDC_MDIO_ACCESS2_MASK 0xE0000000
-#define SHARED_HW_CFG_MDC_MDIO_ACCESS2_SHIFT 29
-#define SHARED_HW_CFG_MDC_MDIO_ACCESS2_PHY_TYPE 0x00000000
-#define SHARED_HW_CFG_MDC_MDIO_ACCESS2_EMAC0 0x20000000
-#define SHARED_HW_CFG_MDC_MDIO_ACCESS2_EMAC1 0x40000000
-#define SHARED_HW_CFG_MDC_MDIO_ACCESS2_BOTH 0x60000000
-#define SHARED_HW_CFG_MDC_MDIO_ACCESS2_SWAPPED 0x80000000
- u32 power_dissipated; /* 0x11c */
-#define SHARED_HW_CFG_POWER_DIS_CMN_MASK 0xff000000
-#define SHARED_HW_CFG_POWER_DIS_CMN_SHIFT 24
+ /* The value of PM_TL_IGNORE_REQS (bit0) in PCI register
+ tl_control_0 (register 0x2800) */
+ #define SHARED_HW_CFG_PREVENT_L1_ENTRY_MASK 0x00800000
+ #define SHARED_HW_CFG_PREVENT_L1_ENTRY_DISABLED 0x00000000
+ #define SHARED_HW_CFG_PREVENT_L1_ENTRY_ENABLED 0x00800000
-#define SHARED_HW_CFG_POWER_MGNT_SCALE_MASK 0x00ff0000
-#define SHARED_HW_CFG_POWER_MGNT_SCALE_SHIFT 16
-#define SHARED_HW_CFG_POWER_MGNT_UNKNOWN_SCALE 0x00000000
-#define SHARED_HW_CFG_POWER_MGNT_DOT_1_WATT 0x00010000
-#define SHARED_HW_CFG_POWER_MGNT_DOT_01_WATT 0x00020000
-#define SHARED_HW_CFG_POWER_MGNT_DOT_001_WATT 0x00030000
+ #define SHARED_HW_CFG_PORT_MODE_MASK 0x01000000
+ #define SHARED_HW_CFG_PORT_MODE_2 0x00000000
+ #define SHARED_HW_CFG_PORT_MODE_4 0x01000000
- u32 ump_nc_si_config; /* 0x120 */
-#define SHARED_HW_CFG_UMP_NC_SI_MII_MODE_MASK 0x00000003
-#define SHARED_HW_CFG_UMP_NC_SI_MII_MODE_SHIFT 0
-#define SHARED_HW_CFG_UMP_NC_SI_MII_MODE_MAC 0x00000000
-#define SHARED_HW_CFG_UMP_NC_SI_MII_MODE_PHY 0x00000001
-#define SHARED_HW_CFG_UMP_NC_SI_MII_MODE_MII 0x00000000
-#define SHARED_HW_CFG_UMP_NC_SI_MII_MODE_RMII 0x00000002
+ #define SHARED_HW_CFG_PATH_SWAP_MASK 0x02000000
+ #define SHARED_HW_CFG_PATH_SWAP_DISABLED 0x00000000
+ #define SHARED_HW_CFG_PATH_SWAP_ENABLED 0x02000000
-#define SHARED_HW_CFG_UMP_NC_SI_NUM_DEVS_MASK 0x00000f00
-#define SHARED_HW_CFG_UMP_NC_SI_NUM_DEVS_SHIFT 8
+ /* Set the MDC/MDIO access for the first external phy */
+ #define SHARED_HW_CFG_MDC_MDIO_ACCESS1_MASK 0x1C000000
+ #define SHARED_HW_CFG_MDC_MDIO_ACCESS1_SHIFT 26
+ #define SHARED_HW_CFG_MDC_MDIO_ACCESS1_PHY_TYPE 0x00000000
+ #define SHARED_HW_CFG_MDC_MDIO_ACCESS1_EMAC0 0x04000000
+ #define SHARED_HW_CFG_MDC_MDIO_ACCESS1_EMAC1 0x08000000
+ #define SHARED_HW_CFG_MDC_MDIO_ACCESS1_BOTH 0x0c000000
+ #define SHARED_HW_CFG_MDC_MDIO_ACCESS1_SWAPPED 0x10000000
-#define SHARED_HW_CFG_UMP_NC_SI_EXT_PHY_TYPE_MASK 0x00ff0000
-#define SHARED_HW_CFG_UMP_NC_SI_EXT_PHY_TYPE_SHIFT 16
-#define SHARED_HW_CFG_UMP_NC_SI_EXT_PHY_TYPE_NONE 0x00000000
-#define SHARED_HW_CFG_UMP_NC_SI_EXT_PHY_TYPE_BCM5221 0x00010000
+ /* Set the MDC/MDIO access for the second external phy */
+ #define SHARED_HW_CFG_MDC_MDIO_ACCESS2_MASK 0xE0000000
+ #define SHARED_HW_CFG_MDC_MDIO_ACCESS2_SHIFT 29
+ #define SHARED_HW_CFG_MDC_MDIO_ACCESS2_PHY_TYPE 0x00000000
+ #define SHARED_HW_CFG_MDC_MDIO_ACCESS2_EMAC0 0x20000000
+ #define SHARED_HW_CFG_MDC_MDIO_ACCESS2_EMAC1 0x40000000
+ #define SHARED_HW_CFG_MDC_MDIO_ACCESS2_BOTH 0x60000000
+ #define SHARED_HW_CFG_MDC_MDIO_ACCESS2_SWAPPED 0x80000000
- u32 board; /* 0x124 */
-#define SHARED_HW_CFG_BOARD_REV_MASK 0x00FF0000
-#define SHARED_HW_CFG_BOARD_REV_SHIFT 16
-#define SHARED_HW_CFG_BOARD_MAJOR_VER_MASK 0x0F000000
-#define SHARED_HW_CFG_BOARD_MAJOR_VER_SHIFT 24
+ u32 power_dissipated; /* 0x11c */
+ #define SHARED_HW_CFG_POWER_MGNT_SCALE_MASK 0x00ff0000
+ #define SHARED_HW_CFG_POWER_MGNT_SCALE_SHIFT 16
+ #define SHARED_HW_CFG_POWER_MGNT_UNKNOWN_SCALE 0x00000000
+ #define SHARED_HW_CFG_POWER_MGNT_DOT_1_WATT 0x00010000
+ #define SHARED_HW_CFG_POWER_MGNT_DOT_01_WATT 0x00020000
+ #define SHARED_HW_CFG_POWER_MGNT_DOT_001_WATT 0x00030000
-#define SHARED_HW_CFG_BOARD_MINOR_VER_MASK 0xF0000000
-#define SHARED_HW_CFG_BOARD_MINOR_VER_SHIFT 28
+ #define SHARED_HW_CFG_POWER_DIS_CMN_MASK 0xff000000
+ #define SHARED_HW_CFG_POWER_DIS_CMN_SHIFT 24
- u32 reserved; /* 0x128 */
+ u32 ump_nc_si_config; /* 0x120 */
+ #define SHARED_HW_CFG_UMP_NC_SI_MII_MODE_MASK 0x00000003
+ #define SHARED_HW_CFG_UMP_NC_SI_MII_MODE_SHIFT 0
+ #define SHARED_HW_CFG_UMP_NC_SI_MII_MODE_MAC 0x00000000
+ #define SHARED_HW_CFG_UMP_NC_SI_MII_MODE_PHY 0x00000001
+ #define SHARED_HW_CFG_UMP_NC_SI_MII_MODE_MII 0x00000000
+ #define SHARED_HW_CFG_UMP_NC_SI_MII_MODE_RMII 0x00000002
+ #define SHARED_HW_CFG_UMP_NC_SI_NUM_DEVS_MASK 0x00000f00
+ #define SHARED_HW_CFG_UMP_NC_SI_NUM_DEVS_SHIFT 8
+
+ #define SHARED_HW_CFG_UMP_NC_SI_EXT_PHY_TYPE_MASK 0x00ff0000
+ #define SHARED_HW_CFG_UMP_NC_SI_EXT_PHY_TYPE_SHIFT 16
+ #define SHARED_HW_CFG_UMP_NC_SI_EXT_PHY_TYPE_NONE 0x00000000
+ #define SHARED_HW_CFG_UMP_NC_SI_EXT_PHY_TYPE_BCM5221 0x00010000
+
+ u32 board; /* 0x124 */
+ #define SHARED_HW_CFG_E3_I2C_MUX0_MASK 0x0000003F
+ #define SHARED_HW_CFG_E3_I2C_MUX0_SHIFT 0
+ #define SHARED_HW_CFG_E3_I2C_MUX1_MASK 0x00000FC0
+ #define SHARED_HW_CFG_E3_I2C_MUX1_SHIFT 6
+ /* Use the PIN_CFG_XXX defines on top */
+ #define SHARED_HW_CFG_BOARD_REV_MASK 0x00ff0000
+ #define SHARED_HW_CFG_BOARD_REV_SHIFT 16
+
+ #define SHARED_HW_CFG_BOARD_MAJOR_VER_MASK 0x0f000000
+ #define SHARED_HW_CFG_BOARD_MAJOR_VER_SHIFT 24
+
+ #define SHARED_HW_CFG_BOARD_MINOR_VER_MASK 0xf0000000
+ #define SHARED_HW_CFG_BOARD_MINOR_VER_SHIFT 28
+
+ u32 wc_lane_config; /* 0x128 */
+ #define SHARED_HW_CFG_LANE_SWAP_CFG_MASK 0x0000FFFF
+ #define SHARED_HW_CFG_LANE_SWAP_CFG_SHIFT 0
+ #define SHARED_HW_CFG_LANE_SWAP_CFG_32103210 0x00001b1b
+ #define SHARED_HW_CFG_LANE_SWAP_CFG_32100123 0x00001be4
+ #define SHARED_HW_CFG_LANE_SWAP_CFG_01233210 0x0000e41b
+ #define SHARED_HW_CFG_LANE_SWAP_CFG_01230123 0x0000e4e4
+ #define SHARED_HW_CFG_LANE_SWAP_CFG_TX_MASK 0x000000FF
+ #define SHARED_HW_CFG_LANE_SWAP_CFG_TX_SHIFT 0
+ #define SHARED_HW_CFG_LANE_SWAP_CFG_RX_MASK 0x0000FF00
+ #define SHARED_HW_CFG_LANE_SWAP_CFG_RX_SHIFT 8
+
+ /* TX lane Polarity swap */
+ #define SHARED_HW_CFG_TX_LANE0_POL_FLIP_ENABLED 0x00010000
+ #define SHARED_HW_CFG_TX_LANE1_POL_FLIP_ENABLED 0x00020000
+ #define SHARED_HW_CFG_TX_LANE2_POL_FLIP_ENABLED 0x00040000
+ #define SHARED_HW_CFG_TX_LANE3_POL_FLIP_ENABLED 0x00080000
+ /* TX lane Polarity swap */
+ #define SHARED_HW_CFG_RX_LANE0_POL_FLIP_ENABLED 0x00100000
+ #define SHARED_HW_CFG_RX_LANE1_POL_FLIP_ENABLED 0x00200000
+ #define SHARED_HW_CFG_RX_LANE2_POL_FLIP_ENABLED 0x00400000
+ #define SHARED_HW_CFG_RX_LANE3_POL_FLIP_ENABLED 0x00800000
+
+ /* Selects the port layout of the board */
+ #define SHARED_HW_CFG_E3_PORT_LAYOUT_MASK 0x0F000000
+ #define SHARED_HW_CFG_E3_PORT_LAYOUT_SHIFT 24
+ #define SHARED_HW_CFG_E3_PORT_LAYOUT_2P_01 0x00000000
+ #define SHARED_HW_CFG_E3_PORT_LAYOUT_2P_10 0x01000000
+ #define SHARED_HW_CFG_E3_PORT_LAYOUT_4P_0123 0x02000000
+ #define SHARED_HW_CFG_E3_PORT_LAYOUT_4P_1032 0x03000000
+ #define SHARED_HW_CFG_E3_PORT_LAYOUT_4P_2301 0x04000000
+ #define SHARED_HW_CFG_E3_PORT_LAYOUT_4P_3210 0x05000000
};
/****************************************************************************
- * Port HW configuration *
+ * Port HW configuration *
****************************************************************************/
-struct port_hw_cfg { /* port 0: 0x12c port 1: 0x2bc */
+struct port_hw_cfg { /* port 0: 0x12c port 1: 0x2bc */
u32 pci_id;
-#define PORT_HW_CFG_PCI_VENDOR_ID_MASK 0xffff0000
-#define PORT_HW_CFG_PCI_DEVICE_ID_MASK 0x0000ffff
+ #define PORT_HW_CFG_PCI_VENDOR_ID_MASK 0xffff0000
+ #define PORT_HW_CFG_PCI_DEVICE_ID_MASK 0x0000ffff
u32 pci_sub_id;
-#define PORT_HW_CFG_PCI_SUBSYS_DEVICE_ID_MASK 0xffff0000
-#define PORT_HW_CFG_PCI_SUBSYS_VENDOR_ID_MASK 0x0000ffff
+ #define PORT_HW_CFG_PCI_SUBSYS_DEVICE_ID_MASK 0xffff0000
+ #define PORT_HW_CFG_PCI_SUBSYS_VENDOR_ID_MASK 0x0000ffff
u32 power_dissipated;
-#define PORT_HW_CFG_POWER_DIS_D3_MASK 0xff000000
-#define PORT_HW_CFG_POWER_DIS_D3_SHIFT 24
-#define PORT_HW_CFG_POWER_DIS_D2_MASK 0x00ff0000
-#define PORT_HW_CFG_POWER_DIS_D2_SHIFT 16
-#define PORT_HW_CFG_POWER_DIS_D1_MASK 0x0000ff00
-#define PORT_HW_CFG_POWER_DIS_D1_SHIFT 8
-#define PORT_HW_CFG_POWER_DIS_D0_MASK 0x000000ff
-#define PORT_HW_CFG_POWER_DIS_D0_SHIFT 0
+ #define PORT_HW_CFG_POWER_DIS_D0_MASK 0x000000ff
+ #define PORT_HW_CFG_POWER_DIS_D0_SHIFT 0
+ #define PORT_HW_CFG_POWER_DIS_D1_MASK 0x0000ff00
+ #define PORT_HW_CFG_POWER_DIS_D1_SHIFT 8
+ #define PORT_HW_CFG_POWER_DIS_D2_MASK 0x00ff0000
+ #define PORT_HW_CFG_POWER_DIS_D2_SHIFT 16
+ #define PORT_HW_CFG_POWER_DIS_D3_MASK 0xff000000
+ #define PORT_HW_CFG_POWER_DIS_D3_SHIFT 24
u32 power_consumed;
-#define PORT_HW_CFG_POWER_CONS_D3_MASK 0xff000000
-#define PORT_HW_CFG_POWER_CONS_D3_SHIFT 24
-#define PORT_HW_CFG_POWER_CONS_D2_MASK 0x00ff0000
-#define PORT_HW_CFG_POWER_CONS_D2_SHIFT 16
-#define PORT_HW_CFG_POWER_CONS_D1_MASK 0x0000ff00
-#define PORT_HW_CFG_POWER_CONS_D1_SHIFT 8
-#define PORT_HW_CFG_POWER_CONS_D0_MASK 0x000000ff
-#define PORT_HW_CFG_POWER_CONS_D0_SHIFT 0
+ #define PORT_HW_CFG_POWER_CONS_D0_MASK 0x000000ff
+ #define PORT_HW_CFG_POWER_CONS_D0_SHIFT 0
+ #define PORT_HW_CFG_POWER_CONS_D1_MASK 0x0000ff00
+ #define PORT_HW_CFG_POWER_CONS_D1_SHIFT 8
+ #define PORT_HW_CFG_POWER_CONS_D2_MASK 0x00ff0000
+ #define PORT_HW_CFG_POWER_CONS_D2_SHIFT 16
+ #define PORT_HW_CFG_POWER_CONS_D3_MASK 0xff000000
+ #define PORT_HW_CFG_POWER_CONS_D3_SHIFT 24
u32 mac_upper;
-#define PORT_HW_CFG_UPPERMAC_MASK 0x0000ffff
-#define PORT_HW_CFG_UPPERMAC_SHIFT 0
+ #define PORT_HW_CFG_UPPERMAC_MASK 0x0000ffff
+ #define PORT_HW_CFG_UPPERMAC_SHIFT 0
u32 mac_lower;
u32 iscsi_mac_upper; /* Upper 16 bits are always zeroes */
@@ -237,642 +402,807 @@
u32 rdma_mac_lower;
u32 serdes_config;
-#define PORT_HW_CFG_SERDES_TX_DRV_PRE_EMPHASIS_MASK 0x0000FFFF
-#define PORT_HW_CFG_SERDES_TX_DRV_PRE_EMPHASIS_SHIFT 0
+ #define PORT_HW_CFG_SERDES_TX_DRV_PRE_EMPHASIS_MASK 0x0000ffff
+ #define PORT_HW_CFG_SERDES_TX_DRV_PRE_EMPHASIS_SHIFT 0
-#define PORT_HW_CFG_SERDES_RX_DRV_EQUALIZER_MASK 0xFFFF0000
-#define PORT_HW_CFG_SERDES_RX_DRV_EQUALIZER_SHIFT 16
+ #define PORT_HW_CFG_SERDES_RX_DRV_EQUALIZER_MASK 0xffff0000
+ #define PORT_HW_CFG_SERDES_RX_DRV_EQUALIZER_SHIFT 16
- u32 Reserved0[3]; /* 0x158 */
- /* Controls the TX laser of the SFP+ module */
- u32 sfp_ctrl; /* 0x164 */
-#define PORT_HW_CFG_TX_LASER_MASK 0x000000FF
-#define PORT_HW_CFG_TX_LASER_SHIFT 0
-#define PORT_HW_CFG_TX_LASER_MDIO 0x00000000
-#define PORT_HW_CFG_TX_LASER_GPIO0 0x00000001
-#define PORT_HW_CFG_TX_LASER_GPIO1 0x00000002
-#define PORT_HW_CFG_TX_LASER_GPIO2 0x00000003
-#define PORT_HW_CFG_TX_LASER_GPIO3 0x00000004
+ /* Default values: 2P-64, 4P-32 */
+ u32 pf_config; /* 0x158 */
+ #define PORT_HW_CFG_PF_NUM_VF_MASK 0x0000007F
+ #define PORT_HW_CFG_PF_NUM_VF_SHIFT 0
- /* Controls the fault module LED of the SFP+ */
-#define PORT_HW_CFG_FAULT_MODULE_LED_MASK 0x0000FF00
-#define PORT_HW_CFG_FAULT_MODULE_LED_SHIFT 8
-#define PORT_HW_CFG_FAULT_MODULE_LED_GPIO0 0x00000000
-#define PORT_HW_CFG_FAULT_MODULE_LED_GPIO1 0x00000100
-#define PORT_HW_CFG_FAULT_MODULE_LED_GPIO2 0x00000200
-#define PORT_HW_CFG_FAULT_MODULE_LED_GPIO3 0x00000300
-#define PORT_HW_CFG_FAULT_MODULE_LED_DISABLED 0x00000400
- u32 Reserved01[12]; /* 0x158 */
- /* for external PHY, or forced mode or during AN */
- u16 xgxs_config_rx[4]; /* 0x198 */
+ /* Default values: 17 */
+ #define PORT_HW_CFG_PF_NUM_MSIX_VECTORS_MASK 0x00007F00
+ #define PORT_HW_CFG_PF_NUM_MSIX_VECTORS_SHIFT 8
- u16 xgxs_config_tx[4]; /* 0x1A0 */
+ #define PORT_HW_CFG_ENABLE_FLR_MASK 0x00010000
+ #define PORT_HW_CFG_FLR_ENABLED 0x00010000
- u32 Reserved1[56]; /* 0x1A8 */
- u32 default_cfg; /* 0x288 */
-#define PORT_HW_CFG_GPIO0_CONFIG_MASK 0x00000003
-#define PORT_HW_CFG_GPIO0_CONFIG_SHIFT 0
-#define PORT_HW_CFG_GPIO0_CONFIG_NA 0x00000000
-#define PORT_HW_CFG_GPIO0_CONFIG_LOW 0x00000001
-#define PORT_HW_CFG_GPIO0_CONFIG_HIGH 0x00000002
-#define PORT_HW_CFG_GPIO0_CONFIG_INPUT 0x00000003
+ u32 vf_config; /* 0x15C */
+ #define PORT_HW_CFG_VF_NUM_MSIX_VECTORS_MASK 0x0000007F
+ #define PORT_HW_CFG_VF_NUM_MSIX_VECTORS_SHIFT 0
-#define PORT_HW_CFG_GPIO1_CONFIG_MASK 0x0000000C
-#define PORT_HW_CFG_GPIO1_CONFIG_SHIFT 2
-#define PORT_HW_CFG_GPIO1_CONFIG_NA 0x00000000
-#define PORT_HW_CFG_GPIO1_CONFIG_LOW 0x00000004
-#define PORT_HW_CFG_GPIO1_CONFIG_HIGH 0x00000008
-#define PORT_HW_CFG_GPIO1_CONFIG_INPUT 0x0000000c
+ #define PORT_HW_CFG_VF_PCI_DEVICE_ID_MASK 0xFFFF0000
+ #define PORT_HW_CFG_VF_PCI_DEVICE_ID_SHIFT 16
-#define PORT_HW_CFG_GPIO2_CONFIG_MASK 0x00000030
-#define PORT_HW_CFG_GPIO2_CONFIG_SHIFT 4
-#define PORT_HW_CFG_GPIO2_CONFIG_NA 0x00000000
-#define PORT_HW_CFG_GPIO2_CONFIG_LOW 0x00000010
-#define PORT_HW_CFG_GPIO2_CONFIG_HIGH 0x00000020
-#define PORT_HW_CFG_GPIO2_CONFIG_INPUT 0x00000030
+ u32 mf_pci_id; /* 0x160 */
+ #define PORT_HW_CFG_MF_PCI_DEVICE_ID_MASK 0x0000FFFF
+ #define PORT_HW_CFG_MF_PCI_DEVICE_ID_SHIFT 0
-#define PORT_HW_CFG_GPIO3_CONFIG_MASK 0x000000C0
-#define PORT_HW_CFG_GPIO3_CONFIG_SHIFT 6
-#define PORT_HW_CFG_GPIO3_CONFIG_NA 0x00000000
-#define PORT_HW_CFG_GPIO3_CONFIG_LOW 0x00000040
-#define PORT_HW_CFG_GPIO3_CONFIG_HIGH 0x00000080
-#define PORT_HW_CFG_GPIO3_CONFIG_INPUT 0x000000c0
+ /* Controls the TX laser of the SFP+ module */
+ u32 sfp_ctrl; /* 0x164 */
+ #define PORT_HW_CFG_TX_LASER_MASK 0x000000FF
+ #define PORT_HW_CFG_TX_LASER_SHIFT 0
+ #define PORT_HW_CFG_TX_LASER_MDIO 0x00000000
+ #define PORT_HW_CFG_TX_LASER_GPIO0 0x00000001
+ #define PORT_HW_CFG_TX_LASER_GPIO1 0x00000002
+ #define PORT_HW_CFG_TX_LASER_GPIO2 0x00000003
+ #define PORT_HW_CFG_TX_LASER_GPIO3 0x00000004
+
+ /* Controls the fault module LED of the SFP+ */
+ #define PORT_HW_CFG_FAULT_MODULE_LED_MASK 0x0000FF00
+ #define PORT_HW_CFG_FAULT_MODULE_LED_SHIFT 8
+ #define PORT_HW_CFG_FAULT_MODULE_LED_GPIO0 0x00000000
+ #define PORT_HW_CFG_FAULT_MODULE_LED_GPIO1 0x00000100
+ #define PORT_HW_CFG_FAULT_MODULE_LED_GPIO2 0x00000200
+ #define PORT_HW_CFG_FAULT_MODULE_LED_GPIO3 0x00000300
+ #define PORT_HW_CFG_FAULT_MODULE_LED_DISABLED 0x00000400
+
+ /* The output pin TX_DIS that controls the TX laser of the SFP+
+ module. Use the PIN_CFG_XXX defines on top */
+ u32 e3_sfp_ctrl; /* 0x168 */
+ #define PORT_HW_CFG_E3_TX_LASER_MASK 0x000000FF
+ #define PORT_HW_CFG_E3_TX_LASER_SHIFT 0
+
+ /* The output pin for SFPP_TYPE which turns on the Fault module LED */
+ #define PORT_HW_CFG_E3_FAULT_MDL_LED_MASK 0x0000FF00
+ #define PORT_HW_CFG_E3_FAULT_MDL_LED_SHIFT 8
+
+ /* The input pin MOD_ABS that indicates whether SFP+ module is
+ present or not. Use the PIN_CFG_XXX defines on top */
+ #define PORT_HW_CFG_E3_MOD_ABS_MASK 0x00FF0000
+ #define PORT_HW_CFG_E3_MOD_ABS_SHIFT 16
+
+ /* The output pin PWRDIS_SFP_X which disable the power of the SFP+
+ module. Use the PIN_CFG_XXX defines on top */
+ #define PORT_HW_CFG_E3_PWR_DIS_MASK 0xFF000000
+ #define PORT_HW_CFG_E3_PWR_DIS_SHIFT 24
/*
- * When KR link is required to be set to force which is not
- * KR-compliant, this parameter determine what is the trigger for it.
- * When GPIO is selected, low input will force the speed. Currently
- * default speed is 1G. In the future, it may be widen to select the
- * forced speed in with another parameter. Note when force-1G is
- * enabled, it override option 56: Link Speed option.
+ * The input pin which signals module transmit fault. Use the
+ * PIN_CFG_XXX defines on top
*/
-#define PORT_HW_CFG_FORCE_KR_ENABLER_MASK 0x00000F00
-#define PORT_HW_CFG_FORCE_KR_ENABLER_SHIFT 8
-#define PORT_HW_CFG_FORCE_KR_ENABLER_NOT_FORCED 0x00000000
-#define PORT_HW_CFG_FORCE_KR_ENABLER_GPIO0_P0 0x00000100
-#define PORT_HW_CFG_FORCE_KR_ENABLER_GPIO1_P0 0x00000200
-#define PORT_HW_CFG_FORCE_KR_ENABLER_GPIO2_P0 0x00000300
-#define PORT_HW_CFG_FORCE_KR_ENABLER_GPIO3_P0 0x00000400
-#define PORT_HW_CFG_FORCE_KR_ENABLER_GPIO0_P1 0x00000500
-#define PORT_HW_CFG_FORCE_KR_ENABLER_GPIO1_P1 0x00000600
-#define PORT_HW_CFG_FORCE_KR_ENABLER_GPIO2_P1 0x00000700
-#define PORT_HW_CFG_FORCE_KR_ENABLER_GPIO3_P1 0x00000800
-#define PORT_HW_CFG_FORCE_KR_ENABLER_FORCED 0x00000900
- /* Enable to determine with which GPIO to reset the external phy */
-#define PORT_HW_CFG_EXT_PHY_GPIO_RST_MASK 0x000F0000
-#define PORT_HW_CFG_EXT_PHY_GPIO_RST_SHIFT 16
-#define PORT_HW_CFG_EXT_PHY_GPIO_RST_PHY_TYPE 0x00000000
-#define PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO0_P0 0x00010000
-#define PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO1_P0 0x00020000
-#define PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO2_P0 0x00030000
-#define PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO3_P0 0x00040000
-#define PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO0_P1 0x00050000
-#define PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO1_P1 0x00060000
-#define PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO2_P1 0x00070000
-#define PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO3_P1 0x00080000
+ u32 e3_cmn_pin_cfg; /* 0x16C */
+ #define PORT_HW_CFG_E3_TX_FAULT_MASK 0x000000FF
+ #define PORT_HW_CFG_E3_TX_FAULT_SHIFT 0
+
+ /* The output pin which reset the PHY. Use the PIN_CFG_XXX defines on
+ top */
+ #define PORT_HW_CFG_E3_PHY_RESET_MASK 0x0000FF00
+ #define PORT_HW_CFG_E3_PHY_RESET_SHIFT 8
+
+ /*
+ * The output pin which powers down the PHY. Use the PIN_CFG_XXX
+ * defines on top
+ */
+ #define PORT_HW_CFG_E3_PWR_DOWN_MASK 0x00FF0000
+ #define PORT_HW_CFG_E3_PWR_DOWN_SHIFT 16
+
+ /* The output pin values BSC_SEL which selects the I2C for this port
+ in the I2C Mux */
+ #define PORT_HW_CFG_E3_I2C_MUX0_MASK 0x01000000
+ #define PORT_HW_CFG_E3_I2C_MUX1_MASK 0x02000000
+
+
+ /*
+ * The input pin I_FAULT which indicate over-current has occurred.
+ * Use the PIN_CFG_XXX defines on top
+ */
+ u32 e3_cmn_pin_cfg1; /* 0x170 */
+ #define PORT_HW_CFG_E3_OVER_CURRENT_MASK 0x000000FF
+ #define PORT_HW_CFG_E3_OVER_CURRENT_SHIFT 0
+ u32 reserved0[7]; /* 0x174 */
+
+ u32 aeu_int_mask; /* 0x190 */
+
+ u32 media_type; /* 0x194 */
+ #define PORT_HW_CFG_MEDIA_TYPE_PHY0_MASK 0x000000FF
+ #define PORT_HW_CFG_MEDIA_TYPE_PHY0_SHIFT 0
+
+ #define PORT_HW_CFG_MEDIA_TYPE_PHY1_MASK 0x0000FF00
+ #define PORT_HW_CFG_MEDIA_TYPE_PHY1_SHIFT 8
+
+ #define PORT_HW_CFG_MEDIA_TYPE_PHY2_MASK 0x00FF0000
+ #define PORT_HW_CFG_MEDIA_TYPE_PHY2_SHIFT 16
+
+ /* 4 times 16 bits for all 4 lanes. In case external PHY is present
+ (not direct mode), those values will not take effect on the 4 XGXS
+ lanes. For some external PHYs (such as 8706 and 8726) the values
+ will be used to configure the external PHY in those cases, not
+ all 4 values are needed. */
+ u16 xgxs_config_rx[4]; /* 0x198 */
+ u16 xgxs_config_tx[4]; /* 0x1A0 */
+
+ /* For storing FCOE mac on shared memory */
+ u32 fcoe_fip_mac_upper;
+ #define PORT_HW_CFG_FCOE_UPPERMAC_MASK 0x0000ffff
+ #define PORT_HW_CFG_FCOE_UPPERMAC_SHIFT 0
+ u32 fcoe_fip_mac_lower;
+
+ u32 fcoe_wwn_port_name_upper;
+ u32 fcoe_wwn_port_name_lower;
+
+ u32 fcoe_wwn_node_name_upper;
+ u32 fcoe_wwn_node_name_lower;
+
+ u32 Reserved1[49]; /* 0x1C0 */
+
+ /* Enable RJ45 magjack pair swapping on 10GBase-T PHY (0=default),
+ 84833 only */
+ u32 xgbt_phy_cfg; /* 0x284 */
+ #define PORT_HW_CFG_RJ45_PAIR_SWAP_MASK 0x000000FF
+ #define PORT_HW_CFG_RJ45_PAIR_SWAP_SHIFT 0
+
+ u32 default_cfg; /* 0x288 */
+ #define PORT_HW_CFG_GPIO0_CONFIG_MASK 0x00000003
+ #define PORT_HW_CFG_GPIO0_CONFIG_SHIFT 0
+ #define PORT_HW_CFG_GPIO0_CONFIG_NA 0x00000000
+ #define PORT_HW_CFG_GPIO0_CONFIG_LOW 0x00000001
+ #define PORT_HW_CFG_GPIO0_CONFIG_HIGH 0x00000002
+ #define PORT_HW_CFG_GPIO0_CONFIG_INPUT 0x00000003
+
+ #define PORT_HW_CFG_GPIO1_CONFIG_MASK 0x0000000C
+ #define PORT_HW_CFG_GPIO1_CONFIG_SHIFT 2
+ #define PORT_HW_CFG_GPIO1_CONFIG_NA 0x00000000
+ #define PORT_HW_CFG_GPIO1_CONFIG_LOW 0x00000004
+ #define PORT_HW_CFG_GPIO1_CONFIG_HIGH 0x00000008
+ #define PORT_HW_CFG_GPIO1_CONFIG_INPUT 0x0000000c
+
+ #define PORT_HW_CFG_GPIO2_CONFIG_MASK 0x00000030
+ #define PORT_HW_CFG_GPIO2_CONFIG_SHIFT 4
+ #define PORT_HW_CFG_GPIO2_CONFIG_NA 0x00000000
+ #define PORT_HW_CFG_GPIO2_CONFIG_LOW 0x00000010
+ #define PORT_HW_CFG_GPIO2_CONFIG_HIGH 0x00000020
+ #define PORT_HW_CFG_GPIO2_CONFIG_INPUT 0x00000030
+
+ #define PORT_HW_CFG_GPIO3_CONFIG_MASK 0x000000C0
+ #define PORT_HW_CFG_GPIO3_CONFIG_SHIFT 6
+ #define PORT_HW_CFG_GPIO3_CONFIG_NA 0x00000000
+ #define PORT_HW_CFG_GPIO3_CONFIG_LOW 0x00000040
+ #define PORT_HW_CFG_GPIO3_CONFIG_HIGH 0x00000080
+ #define PORT_HW_CFG_GPIO3_CONFIG_INPUT 0x000000c0
+
+ /* When KR link is required to be set to force which is not
+ KR-compliant, this parameter determine what is the trigger for it.
+ When GPIO is selected, low input will force the speed. Currently
+ default speed is 1G. In the future, it may be widen to select the
+ forced speed in with another parameter. Note when force-1G is
+ enabled, it override option 56: Link Speed option. */
+ #define PORT_HW_CFG_FORCE_KR_ENABLER_MASK 0x00000F00
+ #define PORT_HW_CFG_FORCE_KR_ENABLER_SHIFT 8
+ #define PORT_HW_CFG_FORCE_KR_ENABLER_NOT_FORCED 0x00000000
+ #define PORT_HW_CFG_FORCE_KR_ENABLER_GPIO0_P0 0x00000100
+ #define PORT_HW_CFG_FORCE_KR_ENABLER_GPIO1_P0 0x00000200
+ #define PORT_HW_CFG_FORCE_KR_ENABLER_GPIO2_P0 0x00000300
+ #define PORT_HW_CFG_FORCE_KR_ENABLER_GPIO3_P0 0x00000400
+ #define PORT_HW_CFG_FORCE_KR_ENABLER_GPIO0_P1 0x00000500
+ #define PORT_HW_CFG_FORCE_KR_ENABLER_GPIO1_P1 0x00000600
+ #define PORT_HW_CFG_FORCE_KR_ENABLER_GPIO2_P1 0x00000700
+ #define PORT_HW_CFG_FORCE_KR_ENABLER_GPIO3_P1 0x00000800
+ #define PORT_HW_CFG_FORCE_KR_ENABLER_FORCED 0x00000900
+ /* Enable to determine with which GPIO to reset the external phy */
+ #define PORT_HW_CFG_EXT_PHY_GPIO_RST_MASK 0x000F0000
+ #define PORT_HW_CFG_EXT_PHY_GPIO_RST_SHIFT 16
+ #define PORT_HW_CFG_EXT_PHY_GPIO_RST_PHY_TYPE 0x00000000
+ #define PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO0_P0 0x00010000
+ #define PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO1_P0 0x00020000
+ #define PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO2_P0 0x00030000
+ #define PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO3_P0 0x00040000
+ #define PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO0_P1 0x00050000
+ #define PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO1_P1 0x00060000
+ #define PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO2_P1 0x00070000
+ #define PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO3_P1 0x00080000
+
/* Enable BAM on KR */
-#define PORT_HW_CFG_ENABLE_BAM_ON_KR_MASK 0x00100000
-#define PORT_HW_CFG_ENABLE_BAM_ON_KR_SHIFT 20
-#define PORT_HW_CFG_ENABLE_BAM_ON_KR_DISABLED 0x00000000
-#define PORT_HW_CFG_ENABLE_BAM_ON_KR_ENABLED 0x00100000
+ #define PORT_HW_CFG_ENABLE_BAM_ON_KR_MASK 0x00100000
+ #define PORT_HW_CFG_ENABLE_BAM_ON_KR_SHIFT 20
+ #define PORT_HW_CFG_ENABLE_BAM_ON_KR_DISABLED 0x00000000
+ #define PORT_HW_CFG_ENABLE_BAM_ON_KR_ENABLED 0x00100000
/* Enable Common Mode Sense */
-#define PORT_HW_CFG_ENABLE_CMS_MASK 0x00200000
-#define PORT_HW_CFG_ENABLE_CMS_SHIFT 21
-#define PORT_HW_CFG_ENABLE_CMS_DISABLED 0x00000000
-#define PORT_HW_CFG_ENABLE_CMS_ENABLED 0x00200000
+ #define PORT_HW_CFG_ENABLE_CMS_MASK 0x00200000
+ #define PORT_HW_CFG_ENABLE_CMS_SHIFT 21
+ #define PORT_HW_CFG_ENABLE_CMS_DISABLED 0x00000000
+ #define PORT_HW_CFG_ENABLE_CMS_ENABLED 0x00200000
+
+ /* Enable RJ45 magjack pair swapping on 10GBase-T PHY, 84833 only */
+ #define PORT_HW_CFG_RJ45_PR_SWP_MASK 0x00400000
+ #define PORT_HW_CFG_RJ45_PR_SWP_SHIFT 22
+ #define PORT_HW_CFG_RJ45_PR_SWP_DISABLED 0x00000000
+ #define PORT_HW_CFG_RJ45_PR_SWP_ENABLED 0x00400000
+
+ /* Determine the Serdes electrical interface */
+ #define PORT_HW_CFG_NET_SERDES_IF_MASK 0x0F000000
+ #define PORT_HW_CFG_NET_SERDES_IF_SHIFT 24
+ #define PORT_HW_CFG_NET_SERDES_IF_SGMII 0x00000000
+ #define PORT_HW_CFG_NET_SERDES_IF_XFI 0x01000000
+ #define PORT_HW_CFG_NET_SERDES_IF_SFI 0x02000000
+ #define PORT_HW_CFG_NET_SERDES_IF_KR 0x03000000
+ #define PORT_HW_CFG_NET_SERDES_IF_DXGXS 0x04000000
+ #define PORT_HW_CFG_NET_SERDES_IF_KR2 0x05000000
+
u32 speed_capability_mask2; /* 0x28C */
-#define PORT_HW_CFG_SPEED_CAPABILITY2_D3_MASK 0x0000FFFF
-#define PORT_HW_CFG_SPEED_CAPABILITY2_D3_SHIFT 0
-#define PORT_HW_CFG_SPEED_CAPABILITY2_D3_10M_FULL 0x00000001
-#define PORT_HW_CFG_SPEED_CAPABILITY2_D3__ 0x00000002
-#define PORT_HW_CFG_SPEED_CAPABILITY2_D3___ 0x00000004
-#define PORT_HW_CFG_SPEED_CAPABILITY2_D3_100M_FULL 0x00000008
-#define PORT_HW_CFG_SPEED_CAPABILITY2_D3_1G 0x00000010
-#define PORT_HW_CFG_SPEED_CAPABILITY2_D3_2_DOT_5G 0x00000020
-#define PORT_HW_CFG_SPEED_CAPABILITY2_D3_10G 0x00000040
-#define PORT_HW_CFG_SPEED_CAPABILITY2_D3_12G 0x00000080
-#define PORT_HW_CFG_SPEED_CAPABILITY2_D3_12_DOT_5G 0x00000100
-#define PORT_HW_CFG_SPEED_CAPABILITY2_D3_13G 0x00000200
-#define PORT_HW_CFG_SPEED_CAPABILITY2_D3_15G 0x00000400
-#define PORT_HW_CFG_SPEED_CAPABILITY2_D3_16G 0x00000800
+ #define PORT_HW_CFG_SPEED_CAPABILITY2_D3_MASK 0x0000FFFF
+ #define PORT_HW_CFG_SPEED_CAPABILITY2_D3_SHIFT 0
+ #define PORT_HW_CFG_SPEED_CAPABILITY2_D3_10M_FULL 0x00000001
+ #define PORT_HW_CFG_SPEED_CAPABILITY2_D3__ 0x00000002
+ #define PORT_HW_CFG_SPEED_CAPABILITY2_D3___ 0x00000004
+ #define PORT_HW_CFG_SPEED_CAPABILITY2_D3_100M_FULL 0x00000008
+ #define PORT_HW_CFG_SPEED_CAPABILITY2_D3_1G 0x00000010
+ #define PORT_HW_CFG_SPEED_CAPABILITY2_D3_2_DOT_5G 0x00000020
+ #define PORT_HW_CFG_SPEED_CAPABILITY2_D3_10G 0x00000040
+ #define PORT_HW_CFG_SPEED_CAPABILITY2_D3_20G 0x00000080
-#define PORT_HW_CFG_SPEED_CAPABILITY2_D0_MASK 0xFFFF0000
-#define PORT_HW_CFG_SPEED_CAPABILITY2_D0_SHIFT 16
-#define PORT_HW_CFG_SPEED_CAPABILITY2_D0_10M_FULL 0x00010000
-#define PORT_HW_CFG_SPEED_CAPABILITY2_D0__ 0x00020000
-#define PORT_HW_CFG_SPEED_CAPABILITY2_D0___ 0x00040000
-#define PORT_HW_CFG_SPEED_CAPABILITY2_D0_100M_FULL 0x00080000
-#define PORT_HW_CFG_SPEED_CAPABILITY2_D0_1G 0x00100000
-#define PORT_HW_CFG_SPEED_CAPABILITY2_D0_2_DOT_5G 0x00200000
-#define PORT_HW_CFG_SPEED_CAPABILITY2_D0_10G 0x00400000
-#define PORT_HW_CFG_SPEED_CAPABILITY2_D0_12G 0x00800000
-#define PORT_HW_CFG_SPEED_CAPABILITY2_D0_12_DOT_5G 0x01000000
-#define PORT_HW_CFG_SPEED_CAPABILITY2_D0_13G 0x02000000
-#define PORT_HW_CFG_SPEED_CAPABILITY2_D0_15G 0x04000000
-#define PORT_HW_CFG_SPEED_CAPABILITY2_D0_16G 0x08000000
-
- /* In the case where two media types (e.g. copper and fiber) are
- present and electrically active at the same time, PHY Selection
- will determine which of the two PHYs will be designated as the
- Active PHY and used for a connection to the network. */
- u32 multi_phy_config; /* 0x290 */
-#define PORT_HW_CFG_PHY_SELECTION_MASK 0x00000007
-#define PORT_HW_CFG_PHY_SELECTION_SHIFT 0
-#define PORT_HW_CFG_PHY_SELECTION_HARDWARE_DEFAULT 0x00000000
-#define PORT_HW_CFG_PHY_SELECTION_FIRST_PHY 0x00000001
-#define PORT_HW_CFG_PHY_SELECTION_SECOND_PHY 0x00000002
-#define PORT_HW_CFG_PHY_SELECTION_FIRST_PHY_PRIORITY 0x00000003
-#define PORT_HW_CFG_PHY_SELECTION_SECOND_PHY_PRIORITY 0x00000004
-
- /* When enabled, all second phy nvram parameters will be swapped
- with the first phy parameters */
-#define PORT_HW_CFG_PHY_SWAPPED_MASK 0x00000008
-#define PORT_HW_CFG_PHY_SWAPPED_SHIFT 3
-#define PORT_HW_CFG_PHY_SWAPPED_DISABLED 0x00000000
-#define PORT_HW_CFG_PHY_SWAPPED_ENABLED 0x00000008
+ #define PORT_HW_CFG_SPEED_CAPABILITY2_D0_MASK 0xFFFF0000
+ #define PORT_HW_CFG_SPEED_CAPABILITY2_D0_SHIFT 16
+ #define PORT_HW_CFG_SPEED_CAPABILITY2_D0_10M_FULL 0x00010000
+ #define PORT_HW_CFG_SPEED_CAPABILITY2_D0__ 0x00020000
+ #define PORT_HW_CFG_SPEED_CAPABILITY2_D0___ 0x00040000
+ #define PORT_HW_CFG_SPEED_CAPABILITY2_D0_100M_FULL 0x00080000
+ #define PORT_HW_CFG_SPEED_CAPABILITY2_D0_1G 0x00100000
+ #define PORT_HW_CFG_SPEED_CAPABILITY2_D0_2_DOT_5G 0x00200000
+ #define PORT_HW_CFG_SPEED_CAPABILITY2_D0_10G 0x00400000
+ #define PORT_HW_CFG_SPEED_CAPABILITY2_D0_20G 0x00800000
- /* Address of the second external phy */
- u32 external_phy_config2; /* 0x294 */
-#define PORT_HW_CFG_XGXS_EXT_PHY2_ADDR_MASK 0x000000FF
-#define PORT_HW_CFG_XGXS_EXT_PHY2_ADDR_SHIFT 0
+ /* In the case where two media types (e.g. copper and fiber) are
+ present and electrically active at the same time, PHY Selection
+ will determine which of the two PHYs will be designated as the
+ Active PHY and used for a connection to the network. */
+ u32 multi_phy_config; /* 0x290 */
+ #define PORT_HW_CFG_PHY_SELECTION_MASK 0x00000007
+ #define PORT_HW_CFG_PHY_SELECTION_SHIFT 0
+ #define PORT_HW_CFG_PHY_SELECTION_HARDWARE_DEFAULT 0x00000000
+ #define PORT_HW_CFG_PHY_SELECTION_FIRST_PHY 0x00000001
+ #define PORT_HW_CFG_PHY_SELECTION_SECOND_PHY 0x00000002
+ #define PORT_HW_CFG_PHY_SELECTION_FIRST_PHY_PRIORITY 0x00000003
+ #define PORT_HW_CFG_PHY_SELECTION_SECOND_PHY_PRIORITY 0x00000004
- /* The second XGXS external PHY type */
-#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_MASK 0x0000FF00
-#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_SHIFT 8
-#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_DIRECT 0x00000000
-#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8071 0x00000100
-#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8072 0x00000200
-#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8073 0x00000300
-#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8705 0x00000400
-#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8706 0x00000500
-#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8726 0x00000600
-#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8481 0x00000700
-#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_SFX7101 0x00000800
-#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8727 0x00000900
-#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8727_NOC 0x00000a00
-#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM84823 0x00000b00
-#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM54640 0x00000c00
-#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM84833 0x00000d00
-#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_FAILURE 0x0000fd00
-#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_NOT_CONN 0x0000ff00
+ /* When enabled, all second phy nvram parameters will be swapped
+ with the first phy parameters */
+ #define PORT_HW_CFG_PHY_SWAPPED_MASK 0x00000008
+ #define PORT_HW_CFG_PHY_SWAPPED_SHIFT 3
+ #define PORT_HW_CFG_PHY_SWAPPED_DISABLED 0x00000000
+ #define PORT_HW_CFG_PHY_SWAPPED_ENABLED 0x00000008
- /* 4 times 16 bits for all 4 lanes. For some external PHYs (such as
- 8706, 8726 and 8727) not all 4 values are needed. */
- u16 xgxs_config2_rx[4]; /* 0x296 */
- u16 xgxs_config2_tx[4]; /* 0x2A0 */
+
+ /* Address of the second external phy */
+ u32 external_phy_config2; /* 0x294 */
+ #define PORT_HW_CFG_XGXS_EXT_PHY2_ADDR_MASK 0x000000FF
+ #define PORT_HW_CFG_XGXS_EXT_PHY2_ADDR_SHIFT 0
+
+ /* The second XGXS external PHY type */
+ #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_MASK 0x0000FF00
+ #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_SHIFT 8
+ #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_DIRECT 0x00000000
+ #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8071 0x00000100
+ #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8072 0x00000200
+ #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8073 0x00000300
+ #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8705 0x00000400
+ #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8706 0x00000500
+ #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8726 0x00000600
+ #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8481 0x00000700
+ #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_SFX7101 0x00000800
+ #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8727 0x00000900
+ #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8727_NOC 0x00000a00
+ #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM84823 0x00000b00
+ #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM54640 0x00000c00
+ #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM84833 0x00000d00
+ #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM54618SE 0x00000e00
+ #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8722 0x00000f00
+ #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_FAILURE 0x0000fd00
+ #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_NOT_CONN 0x0000ff00
+
+
+ /* 4 times 16 bits for all 4 lanes. For some external PHYs (such as
+ 8706, 8726 and 8727) not all 4 values are needed. */
+ u16 xgxs_config2_rx[4]; /* 0x296 */
+ u16 xgxs_config2_tx[4]; /* 0x2A0 */
u32 lane_config;
-#define PORT_HW_CFG_LANE_SWAP_CFG_MASK 0x0000ffff
-#define PORT_HW_CFG_LANE_SWAP_CFG_SHIFT 0
+ #define PORT_HW_CFG_LANE_SWAP_CFG_MASK 0x0000ffff
+ #define PORT_HW_CFG_LANE_SWAP_CFG_SHIFT 0
+ /* AN and forced */
+ #define PORT_HW_CFG_LANE_SWAP_CFG_01230123 0x00001b1b
+ /* forced only */
+ #define PORT_HW_CFG_LANE_SWAP_CFG_01233210 0x00001be4
+ /* forced only */
+ #define PORT_HW_CFG_LANE_SWAP_CFG_31203120 0x0000d8d8
+ /* forced only */
+ #define PORT_HW_CFG_LANE_SWAP_CFG_32103210 0x0000e4e4
+ #define PORT_HW_CFG_LANE_SWAP_CFG_TX_MASK 0x000000ff
+ #define PORT_HW_CFG_LANE_SWAP_CFG_TX_SHIFT 0
+ #define PORT_HW_CFG_LANE_SWAP_CFG_RX_MASK 0x0000ff00
+ #define PORT_HW_CFG_LANE_SWAP_CFG_RX_SHIFT 8
+ #define PORT_HW_CFG_LANE_SWAP_CFG_MASTER_MASK 0x0000c000
+ #define PORT_HW_CFG_LANE_SWAP_CFG_MASTER_SHIFT 14
-#define PORT_HW_CFG_LANE_SWAP_CFG_TX_MASK 0x000000ff
-#define PORT_HW_CFG_LANE_SWAP_CFG_TX_SHIFT 0
-#define PORT_HW_CFG_LANE_SWAP_CFG_RX_MASK 0x0000ff00
-#define PORT_HW_CFG_LANE_SWAP_CFG_RX_SHIFT 8
-#define PORT_HW_CFG_LANE_SWAP_CFG_MASTER_MASK 0x0000c000
-#define PORT_HW_CFG_LANE_SWAP_CFG_MASTER_SHIFT 14
- /* AN and forced */
-#define PORT_HW_CFG_LANE_SWAP_CFG_01230123 0x00001b1b
- /* forced only */
-#define PORT_HW_CFG_LANE_SWAP_CFG_01233210 0x00001be4
- /* forced only */
-#define PORT_HW_CFG_LANE_SWAP_CFG_31203120 0x0000d8d8
- /* forced only */
-#define PORT_HW_CFG_LANE_SWAP_CFG_32103210 0x0000e4e4
- /* Indicate whether to swap the external phy polarity */
-#define PORT_HW_CFG_SWAP_PHY_POLARITY_MASK 0x00010000
-#define PORT_HW_CFG_SWAP_PHY_POLARITY_DISABLED 0x00000000
-#define PORT_HW_CFG_SWAP_PHY_POLARITY_ENABLED 0x00010000
+ /* Indicate whether to swap the external phy polarity */
+ #define PORT_HW_CFG_SWAP_PHY_POLARITY_MASK 0x00010000
+ #define PORT_HW_CFG_SWAP_PHY_POLARITY_DISABLED 0x00000000
+ #define PORT_HW_CFG_SWAP_PHY_POLARITY_ENABLED 0x00010000
+
u32 external_phy_config;
-#define PORT_HW_CFG_SERDES_EXT_PHY_TYPE_MASK 0xff000000
-#define PORT_HW_CFG_SERDES_EXT_PHY_TYPE_SHIFT 24
-#define PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT 0x00000000
-#define PORT_HW_CFG_SERDES_EXT_PHY_TYPE_BCM5482 0x01000000
-#define PORT_HW_CFG_SERDES_EXT_PHY_TYPE_NOT_CONN 0xff000000
+ #define PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK 0x000000ff
+ #define PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT 0
-#define PORT_HW_CFG_SERDES_EXT_PHY_ADDR_MASK 0x00ff0000
-#define PORT_HW_CFG_SERDES_EXT_PHY_ADDR_SHIFT 16
+ #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_MASK 0x0000ff00
+ #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SHIFT 8
+ #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT 0x00000000
+ #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8071 0x00000100
+ #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072 0x00000200
+ #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073 0x00000300
+ #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705 0x00000400
+ #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706 0x00000500
+ #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726 0x00000600
+ #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481 0x00000700
+ #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101 0x00000800
+ #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727 0x00000900
+ #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727_NOC 0x00000a00
+ #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823 0x00000b00
+ #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM54640 0x00000c00
+ #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833 0x00000d00
+ #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM54618SE 0x00000e00
+ #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8722 0x00000f00
+ #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT_WC 0x0000fc00
+ #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE 0x0000fd00
+ #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN 0x0000ff00
-#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_MASK 0x0000ff00
-#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SHIFT 8
-#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT 0x00000000
-#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8071 0x00000100
-#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072 0x00000200
-#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073 0x00000300
-#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705 0x00000400
-#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706 0x00000500
-#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726 0x00000600
-#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481 0x00000700
-#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101 0x00000800
-#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727 0x00000900
-#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727_NOC 0x00000a00
-#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823 0x00000b00
-#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833 0x00000d00
-#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE 0x0000fd00
-#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN 0x0000ff00
+ #define PORT_HW_CFG_SERDES_EXT_PHY_ADDR_MASK 0x00ff0000
+ #define PORT_HW_CFG_SERDES_EXT_PHY_ADDR_SHIFT 16
-#define PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK 0x000000ff
-#define PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT 0
+ #define PORT_HW_CFG_SERDES_EXT_PHY_TYPE_MASK 0xff000000
+ #define PORT_HW_CFG_SERDES_EXT_PHY_TYPE_SHIFT 24
+ #define PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT 0x00000000
+ #define PORT_HW_CFG_SERDES_EXT_PHY_TYPE_BCM5482 0x01000000
+ #define PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT_SD 0x02000000
+ #define PORT_HW_CFG_SERDES_EXT_PHY_TYPE_NOT_CONN 0xff000000
u32 speed_capability_mask;
-#define PORT_HW_CFG_SPEED_CAPABILITY_D0_MASK 0xffff0000
-#define PORT_HW_CFG_SPEED_CAPABILITY_D0_SHIFT 16
-#define PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_FULL 0x00010000
-#define PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_HALF 0x00020000
-#define PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_HALF 0x00040000
-#define PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_FULL 0x00080000
-#define PORT_HW_CFG_SPEED_CAPABILITY_D0_1G 0x00100000
-#define PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G 0x00200000
-#define PORT_HW_CFG_SPEED_CAPABILITY_D0_10G 0x00400000
-#define PORT_HW_CFG_SPEED_CAPABILITY_D0_12G 0x00800000
-#define PORT_HW_CFG_SPEED_CAPABILITY_D0_12_5G 0x01000000
-#define PORT_HW_CFG_SPEED_CAPABILITY_D0_13G 0x02000000
-#define PORT_HW_CFG_SPEED_CAPABILITY_D0_15G 0x04000000
-#define PORT_HW_CFG_SPEED_CAPABILITY_D0_16G 0x08000000
-#define PORT_HW_CFG_SPEED_CAPABILITY_D0_RESERVED 0xf0000000
+ #define PORT_HW_CFG_SPEED_CAPABILITY_D3_MASK 0x0000ffff
+ #define PORT_HW_CFG_SPEED_CAPABILITY_D3_SHIFT 0
+ #define PORT_HW_CFG_SPEED_CAPABILITY_D3_10M_FULL 0x00000001
+ #define PORT_HW_CFG_SPEED_CAPABILITY_D3_10M_HALF 0x00000002
+ #define PORT_HW_CFG_SPEED_CAPABILITY_D3_100M_HALF 0x00000004
+ #define PORT_HW_CFG_SPEED_CAPABILITY_D3_100M_FULL 0x00000008
+ #define PORT_HW_CFG_SPEED_CAPABILITY_D3_1G 0x00000010
+ #define PORT_HW_CFG_SPEED_CAPABILITY_D3_2_5G 0x00000020
+ #define PORT_HW_CFG_SPEED_CAPABILITY_D3_10G 0x00000040
+ #define PORT_HW_CFG_SPEED_CAPABILITY_D3_20G 0x00000080
+ #define PORT_HW_CFG_SPEED_CAPABILITY_D3_RESERVED 0x0000f000
-#define PORT_HW_CFG_SPEED_CAPABILITY_D3_MASK 0x0000ffff
-#define PORT_HW_CFG_SPEED_CAPABILITY_D3_SHIFT 0
-#define PORT_HW_CFG_SPEED_CAPABILITY_D3_10M_FULL 0x00000001
-#define PORT_HW_CFG_SPEED_CAPABILITY_D3_10M_HALF 0x00000002
-#define PORT_HW_CFG_SPEED_CAPABILITY_D3_100M_HALF 0x00000004
-#define PORT_HW_CFG_SPEED_CAPABILITY_D3_100M_FULL 0x00000008
-#define PORT_HW_CFG_SPEED_CAPABILITY_D3_1G 0x00000010
-#define PORT_HW_CFG_SPEED_CAPABILITY_D3_2_5G 0x00000020
-#define PORT_HW_CFG_SPEED_CAPABILITY_D3_10G 0x00000040
-#define PORT_HW_CFG_SPEED_CAPABILITY_D3_12G 0x00000080
-#define PORT_HW_CFG_SPEED_CAPABILITY_D3_12_5G 0x00000100
-#define PORT_HW_CFG_SPEED_CAPABILITY_D3_13G 0x00000200
-#define PORT_HW_CFG_SPEED_CAPABILITY_D3_15G 0x00000400
-#define PORT_HW_CFG_SPEED_CAPABILITY_D3_16G 0x00000800
-#define PORT_HW_CFG_SPEED_CAPABILITY_D3_RESERVED 0x0000f000
+ #define PORT_HW_CFG_SPEED_CAPABILITY_D0_MASK 0xffff0000
+ #define PORT_HW_CFG_SPEED_CAPABILITY_D0_SHIFT 16
+ #define PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_FULL 0x00010000
+ #define PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_HALF 0x00020000
+ #define PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_HALF 0x00040000
+ #define PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_FULL 0x00080000
+ #define PORT_HW_CFG_SPEED_CAPABILITY_D0_1G 0x00100000
+ #define PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G 0x00200000
+ #define PORT_HW_CFG_SPEED_CAPABILITY_D0_10G 0x00400000
+ #define PORT_HW_CFG_SPEED_CAPABILITY_D0_20G 0x00800000
+ #define PORT_HW_CFG_SPEED_CAPABILITY_D0_RESERVED 0xf0000000
- u32 reserved[2];
+ /* A place to hold the original MAC address as a backup */
+ u32 backup_mac_upper; /* 0x2B4 */
+ u32 backup_mac_lower; /* 0x2B8 */
};
/****************************************************************************
- * Shared Feature configuration *
+ * Shared Feature configuration *
****************************************************************************/
-struct shared_feat_cfg { /* NVRAM Offset */
+struct shared_feat_cfg { /* NVRAM Offset */
- u32 config; /* 0x450 */
-#define SHARED_FEATURE_BMC_ECHO_MODE_EN 0x00000001
+ u32 config; /* 0x450 */
+ #define SHARED_FEATURE_BMC_ECHO_MODE_EN 0x00000001
- /* Use the values from options 47 and 48 instead of the HW default
- values */
-#define SHARED_FEAT_CFG_OVERRIDE_PREEMPHASIS_CFG_DISABLED 0x00000000
-#define SHARED_FEAT_CFG_OVERRIDE_PREEMPHASIS_CFG_ENABLED 0x00000002
+ /* Use NVRAM values instead of HW default values */
+ #define SHARED_FEAT_CFG_OVERRIDE_PREEMPHASIS_CFG_MASK \
+ 0x00000002
+ #define SHARED_FEAT_CFG_OVERRIDE_PREEMPHASIS_CFG_DISABLED \
+ 0x00000000
+ #define SHARED_FEAT_CFG_OVERRIDE_PREEMPHASIS_CFG_ENABLED \
+ 0x00000002
-#define SHARED_FEAT_CFG_FORCE_SF_MODE_MASK 0x00000700
-#define SHARED_FEAT_CFG_FORCE_SF_MODE_SHIFT 8
-#define SHARED_FEAT_CFG_FORCE_SF_MODE_MF_ALLOWED 0x00000000
-#define SHARED_FEAT_CFG_FORCE_SF_MODE_FORCED_SF 0x00000100
-#define SHARED_FEAT_CFG_FORCE_SF_MODE_SPIO4 0x00000200
-#define SHARED_FEAT_CFG_FORCE_SF_MODE_SWITCH_INDEPT 0x00000300
+ #define SHARED_FEAT_CFG_NCSI_ID_METHOD_MASK 0x00000008
+ #define SHARED_FEAT_CFG_NCSI_ID_METHOD_SPIO 0x00000000
+ #define SHARED_FEAT_CFG_NCSI_ID_METHOD_NVRAM 0x00000008
+
+ #define SHARED_FEAT_CFG_NCSI_ID_MASK 0x00000030
+ #define SHARED_FEAT_CFG_NCSI_ID_SHIFT 4
+
+ /* Override the OTP back to single function mode. When using GPIO,
+ high means only SF, 0 is according to CLP configuration */
+ #define SHARED_FEAT_CFG_FORCE_SF_MODE_MASK 0x00000700
+ #define SHARED_FEAT_CFG_FORCE_SF_MODE_SHIFT 8
+ #define SHARED_FEAT_CFG_FORCE_SF_MODE_MF_ALLOWED 0x00000000
+ #define SHARED_FEAT_CFG_FORCE_SF_MODE_FORCED_SF 0x00000100
+ #define SHARED_FEAT_CFG_FORCE_SF_MODE_SPIO4 0x00000200
+ #define SHARED_FEAT_CFG_FORCE_SF_MODE_SWITCH_INDEPT 0x00000300
+
+ /* The interval in seconds between sending LLDP packets. Set to zero
+ to disable the feature */
+ #define SHARED_FEAT_CFG_LLDP_XMIT_INTERVAL_MASK 0x00ff0000
+ #define SHARED_FEAT_CFG_LLDP_XMIT_INTERVAL_SHIFT 16
+
+ /* The assigned device type ID for LLDP usage */
+ #define SHARED_FEAT_CFG_LLDP_DEVICE_TYPE_ID_MASK 0xff000000
+ #define SHARED_FEAT_CFG_LLDP_DEVICE_TYPE_ID_SHIFT 24
};
/****************************************************************************
- * Port Feature configuration *
+ * Port Feature configuration *
****************************************************************************/
-struct port_feat_cfg { /* port 0: 0x454 port 1: 0x4c8 */
+struct port_feat_cfg { /* port 0: 0x454 port 1: 0x4c8 */
u32 config;
-#define PORT_FEATURE_BAR1_SIZE_MASK 0x0000000f
-#define PORT_FEATURE_BAR1_SIZE_SHIFT 0
-#define PORT_FEATURE_BAR1_SIZE_DISABLED 0x00000000
-#define PORT_FEATURE_BAR1_SIZE_64K 0x00000001
-#define PORT_FEATURE_BAR1_SIZE_128K 0x00000002
-#define PORT_FEATURE_BAR1_SIZE_256K 0x00000003
-#define PORT_FEATURE_BAR1_SIZE_512K 0x00000004
-#define PORT_FEATURE_BAR1_SIZE_1M 0x00000005
-#define PORT_FEATURE_BAR1_SIZE_2M 0x00000006
-#define PORT_FEATURE_BAR1_SIZE_4M 0x00000007
-#define PORT_FEATURE_BAR1_SIZE_8M 0x00000008
-#define PORT_FEATURE_BAR1_SIZE_16M 0x00000009
-#define PORT_FEATURE_BAR1_SIZE_32M 0x0000000a
-#define PORT_FEATURE_BAR1_SIZE_64M 0x0000000b
-#define PORT_FEATURE_BAR1_SIZE_128M 0x0000000c
-#define PORT_FEATURE_BAR1_SIZE_256M 0x0000000d
-#define PORT_FEATURE_BAR1_SIZE_512M 0x0000000e
-#define PORT_FEATURE_BAR1_SIZE_1G 0x0000000f
-#define PORT_FEATURE_BAR2_SIZE_MASK 0x000000f0
-#define PORT_FEATURE_BAR2_SIZE_SHIFT 4
-#define PORT_FEATURE_BAR2_SIZE_DISABLED 0x00000000
-#define PORT_FEATURE_BAR2_SIZE_64K 0x00000010
-#define PORT_FEATURE_BAR2_SIZE_128K 0x00000020
-#define PORT_FEATURE_BAR2_SIZE_256K 0x00000030
-#define PORT_FEATURE_BAR2_SIZE_512K 0x00000040
-#define PORT_FEATURE_BAR2_SIZE_1M 0x00000050
-#define PORT_FEATURE_BAR2_SIZE_2M 0x00000060
-#define PORT_FEATURE_BAR2_SIZE_4M 0x00000070
-#define PORT_FEATURE_BAR2_SIZE_8M 0x00000080
-#define PORT_FEATURE_BAR2_SIZE_16M 0x00000090
-#define PORT_FEATURE_BAR2_SIZE_32M 0x000000a0
-#define PORT_FEATURE_BAR2_SIZE_64M 0x000000b0
-#define PORT_FEATURE_BAR2_SIZE_128M 0x000000c0
-#define PORT_FEATURE_BAR2_SIZE_256M 0x000000d0
-#define PORT_FEATURE_BAR2_SIZE_512M 0x000000e0
-#define PORT_FEATURE_BAR2_SIZE_1G 0x000000f0
-#define PORT_FEATURE_EN_SIZE_MASK 0x07000000
-#define PORT_FEATURE_EN_SIZE_SHIFT 24
-#define PORT_FEATURE_WOL_ENABLED 0x01000000
-#define PORT_FEATURE_MBA_ENABLED 0x02000000
-#define PORT_FEATURE_MFW_ENABLED 0x04000000
+ #define PORT_FEATURE_BAR1_SIZE_MASK 0x0000000f
+ #define PORT_FEATURE_BAR1_SIZE_SHIFT 0
+ #define PORT_FEATURE_BAR1_SIZE_DISABLED 0x00000000
+ #define PORT_FEATURE_BAR1_SIZE_64K 0x00000001
+ #define PORT_FEATURE_BAR1_SIZE_128K 0x00000002
+ #define PORT_FEATURE_BAR1_SIZE_256K 0x00000003
+ #define PORT_FEATURE_BAR1_SIZE_512K 0x00000004
+ #define PORT_FEATURE_BAR1_SIZE_1M 0x00000005
+ #define PORT_FEATURE_BAR1_SIZE_2M 0x00000006
+ #define PORT_FEATURE_BAR1_SIZE_4M 0x00000007
+ #define PORT_FEATURE_BAR1_SIZE_8M 0x00000008
+ #define PORT_FEATURE_BAR1_SIZE_16M 0x00000009
+ #define PORT_FEATURE_BAR1_SIZE_32M 0x0000000a
+ #define PORT_FEATURE_BAR1_SIZE_64M 0x0000000b
+ #define PORT_FEATURE_BAR1_SIZE_128M 0x0000000c
+ #define PORT_FEATURE_BAR1_SIZE_256M 0x0000000d
+ #define PORT_FEATURE_BAR1_SIZE_512M 0x0000000e
+ #define PORT_FEATURE_BAR1_SIZE_1G 0x0000000f
+ #define PORT_FEATURE_BAR2_SIZE_MASK 0x000000f0
+ #define PORT_FEATURE_BAR2_SIZE_SHIFT 4
+ #define PORT_FEATURE_BAR2_SIZE_DISABLED 0x00000000
+ #define PORT_FEATURE_BAR2_SIZE_64K 0x00000010
+ #define PORT_FEATURE_BAR2_SIZE_128K 0x00000020
+ #define PORT_FEATURE_BAR2_SIZE_256K 0x00000030
+ #define PORT_FEATURE_BAR2_SIZE_512K 0x00000040
+ #define PORT_FEATURE_BAR2_SIZE_1M 0x00000050
+ #define PORT_FEATURE_BAR2_SIZE_2M 0x00000060
+ #define PORT_FEATURE_BAR2_SIZE_4M 0x00000070
+ #define PORT_FEATURE_BAR2_SIZE_8M 0x00000080
+ #define PORT_FEATURE_BAR2_SIZE_16M 0x00000090
+ #define PORT_FEATURE_BAR2_SIZE_32M 0x000000a0
+ #define PORT_FEATURE_BAR2_SIZE_64M 0x000000b0
+ #define PORT_FEATURE_BAR2_SIZE_128M 0x000000c0
+ #define PORT_FEATURE_BAR2_SIZE_256M 0x000000d0
+ #define PORT_FEATURE_BAR2_SIZE_512M 0x000000e0
+ #define PORT_FEATURE_BAR2_SIZE_1G 0x000000f0
- /* Reserved bits: 28-29 */
- /* Check the optic vendor via i2c against a list of approved modules
- in a separate nvram image */
-#define PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK 0xE0000000
-#define PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_SHIFT 29
-#define PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_NO_ENFORCEMENT 0x00000000
-#define PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_DISABLE_TX_LASER 0x20000000
-#define PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_WARNING_MSG 0x40000000
-#define PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_POWER_DOWN 0x60000000
+ #define PORT_FEAT_CFG_DCBX_MASK 0x00000100
+ #define PORT_FEAT_CFG_DCBX_DISABLED 0x00000000
+ #define PORT_FEAT_CFG_DCBX_ENABLED 0x00000100
+ #define PORT_FEAT_CFG_AUTOGREEN_MASK 0x00000200
+ #define PORT_FEAT_CFG_AUTOGREEN_SHIFT 9
+ #define PORT_FEAT_CFG_AUTOGREEN_DISABLED 0x00000000
+ #define PORT_FEAT_CFG_AUTOGREEN_ENABLED 0x00000200
+
+ #define PORT_FEATURE_EN_SIZE_MASK 0x0f000000
+ #define PORT_FEATURE_EN_SIZE_SHIFT 24
+ #define PORT_FEATURE_WOL_ENABLED 0x01000000
+ #define PORT_FEATURE_MBA_ENABLED 0x02000000
+ #define PORT_FEATURE_MFW_ENABLED 0x04000000
+
+ /* Advertise expansion ROM even if MBA is disabled */
+ #define PORT_FEAT_CFG_FORCE_EXP_ROM_ADV_MASK 0x08000000
+ #define PORT_FEAT_CFG_FORCE_EXP_ROM_ADV_DISABLED 0x00000000
+ #define PORT_FEAT_CFG_FORCE_EXP_ROM_ADV_ENABLED 0x08000000
+
+ /* Check the optic vendor via i2c against a list of approved modules
+ in a separate nvram image */
+ #define PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK 0xe0000000
+ #define PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_SHIFT 29
+ #define PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_NO_ENFORCEMENT \
+ 0x00000000
+ #define PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_DISABLE_TX_LASER \
+ 0x20000000
+ #define PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_WARNING_MSG 0x40000000
+ #define PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_POWER_DOWN 0x60000000
u32 wol_config;
/* Default is used when driver sets to "auto" mode */
-#define PORT_FEATURE_WOL_DEFAULT_MASK 0x00000003
-#define PORT_FEATURE_WOL_DEFAULT_SHIFT 0
-#define PORT_FEATURE_WOL_DEFAULT_DISABLE 0x00000000
-#define PORT_FEATURE_WOL_DEFAULT_MAGIC 0x00000001
-#define PORT_FEATURE_WOL_DEFAULT_ACPI 0x00000002
-#define PORT_FEATURE_WOL_DEFAULT_MAGIC_AND_ACPI 0x00000003
-#define PORT_FEATURE_WOL_RES_PAUSE_CAP 0x00000004
-#define PORT_FEATURE_WOL_RES_ASYM_PAUSE_CAP 0x00000008
-#define PORT_FEATURE_WOL_ACPI_UPON_MGMT 0x00000010
+ #define PORT_FEATURE_WOL_DEFAULT_MASK 0x00000003
+ #define PORT_FEATURE_WOL_DEFAULT_SHIFT 0
+ #define PORT_FEATURE_WOL_DEFAULT_DISABLE 0x00000000
+ #define PORT_FEATURE_WOL_DEFAULT_MAGIC 0x00000001
+ #define PORT_FEATURE_WOL_DEFAULT_ACPI 0x00000002
+ #define PORT_FEATURE_WOL_DEFAULT_MAGIC_AND_ACPI 0x00000003
+ #define PORT_FEATURE_WOL_RES_PAUSE_CAP 0x00000004
+ #define PORT_FEATURE_WOL_RES_ASYM_PAUSE_CAP 0x00000008
+ #define PORT_FEATURE_WOL_ACPI_UPON_MGMT 0x00000010
u32 mba_config;
-#define PORT_FEATURE_MBA_BOOT_AGENT_TYPE_MASK 0x00000003
-#define PORT_FEATURE_MBA_BOOT_AGENT_TYPE_SHIFT 0
-#define PORT_FEATURE_MBA_BOOT_AGENT_TYPE_PXE 0x00000000
-#define PORT_FEATURE_MBA_BOOT_AGENT_TYPE_RPL 0x00000001
-#define PORT_FEATURE_MBA_BOOT_AGENT_TYPE_BOOTP 0x00000002
-#define PORT_FEATURE_MBA_BOOT_AGENT_TYPE_ISCSIB 0x00000003
-#define PORT_FEATURE_MBA_RES_PAUSE_CAP 0x00000100
-#define PORT_FEATURE_MBA_RES_ASYM_PAUSE_CAP 0x00000200
-#define PORT_FEATURE_MBA_SETUP_PROMPT_ENABLE 0x00000400
-#define PORT_FEATURE_MBA_HOTKEY_CTRL_S 0x00000000
-#define PORT_FEATURE_MBA_HOTKEY_CTRL_B 0x00000800
-#define PORT_FEATURE_MBA_EXP_ROM_SIZE_MASK 0x000ff000
-#define PORT_FEATURE_MBA_EXP_ROM_SIZE_SHIFT 12
-#define PORT_FEATURE_MBA_EXP_ROM_SIZE_DISABLED 0x00000000
-#define PORT_FEATURE_MBA_EXP_ROM_SIZE_2K 0x00001000
-#define PORT_FEATURE_MBA_EXP_ROM_SIZE_4K 0x00002000
-#define PORT_FEATURE_MBA_EXP_ROM_SIZE_8K 0x00003000
-#define PORT_FEATURE_MBA_EXP_ROM_SIZE_16K 0x00004000
-#define PORT_FEATURE_MBA_EXP_ROM_SIZE_32K 0x00005000
-#define PORT_FEATURE_MBA_EXP_ROM_SIZE_64K 0x00006000
-#define PORT_FEATURE_MBA_EXP_ROM_SIZE_128K 0x00007000
-#define PORT_FEATURE_MBA_EXP_ROM_SIZE_256K 0x00008000
-#define PORT_FEATURE_MBA_EXP_ROM_SIZE_512K 0x00009000
-#define PORT_FEATURE_MBA_EXP_ROM_SIZE_1M 0x0000a000
-#define PORT_FEATURE_MBA_EXP_ROM_SIZE_2M 0x0000b000
-#define PORT_FEATURE_MBA_EXP_ROM_SIZE_4M 0x0000c000
-#define PORT_FEATURE_MBA_EXP_ROM_SIZE_8M 0x0000d000
-#define PORT_FEATURE_MBA_EXP_ROM_SIZE_16M 0x0000e000
-#define PORT_FEATURE_MBA_EXP_ROM_SIZE_32M 0x0000f000
-#define PORT_FEATURE_MBA_MSG_TIMEOUT_MASK 0x00f00000
-#define PORT_FEATURE_MBA_MSG_TIMEOUT_SHIFT 20
-#define PORT_FEATURE_MBA_BIOS_BOOTSTRAP_MASK 0x03000000
-#define PORT_FEATURE_MBA_BIOS_BOOTSTRAP_SHIFT 24
-#define PORT_FEATURE_MBA_BIOS_BOOTSTRAP_AUTO 0x00000000
-#define PORT_FEATURE_MBA_BIOS_BOOTSTRAP_BBS 0x01000000
-#define PORT_FEATURE_MBA_BIOS_BOOTSTRAP_INT18H 0x02000000
-#define PORT_FEATURE_MBA_BIOS_BOOTSTRAP_INT19H 0x03000000
-#define PORT_FEATURE_MBA_LINK_SPEED_MASK 0x3c000000
-#define PORT_FEATURE_MBA_LINK_SPEED_SHIFT 26
-#define PORT_FEATURE_MBA_LINK_SPEED_AUTO 0x00000000
-#define PORT_FEATURE_MBA_LINK_SPEED_10HD 0x04000000
-#define PORT_FEATURE_MBA_LINK_SPEED_10FD 0x08000000
-#define PORT_FEATURE_MBA_LINK_SPEED_100HD 0x0c000000
-#define PORT_FEATURE_MBA_LINK_SPEED_100FD 0x10000000
-#define PORT_FEATURE_MBA_LINK_SPEED_1GBPS 0x14000000
-#define PORT_FEATURE_MBA_LINK_SPEED_2_5GBPS 0x18000000
-#define PORT_FEATURE_MBA_LINK_SPEED_10GBPS_CX4 0x1c000000
-#define PORT_FEATURE_MBA_LINK_SPEED_10GBPS_KX4 0x20000000
-#define PORT_FEATURE_MBA_LINK_SPEED_10GBPS_KR 0x24000000
-#define PORT_FEATURE_MBA_LINK_SPEED_12GBPS 0x28000000
-#define PORT_FEATURE_MBA_LINK_SPEED_12_5GBPS 0x2c000000
-#define PORT_FEATURE_MBA_LINK_SPEED_13GBPS 0x30000000
-#define PORT_FEATURE_MBA_LINK_SPEED_15GBPS 0x34000000
-#define PORT_FEATURE_MBA_LINK_SPEED_16GBPS 0x38000000
+ #define PORT_FEATURE_MBA_BOOT_AGENT_TYPE_MASK 0x00000007
+ #define PORT_FEATURE_MBA_BOOT_AGENT_TYPE_SHIFT 0
+ #define PORT_FEATURE_MBA_BOOT_AGENT_TYPE_PXE 0x00000000
+ #define PORT_FEATURE_MBA_BOOT_AGENT_TYPE_RPL 0x00000001
+ #define PORT_FEATURE_MBA_BOOT_AGENT_TYPE_BOOTP 0x00000002
+ #define PORT_FEATURE_MBA_BOOT_AGENT_TYPE_ISCSIB 0x00000003
+ #define PORT_FEATURE_MBA_BOOT_AGENT_TYPE_FCOE_BOOT 0x00000004
+ #define PORT_FEATURE_MBA_BOOT_AGENT_TYPE_NONE 0x00000007
+ #define PORT_FEATURE_MBA_BOOT_RETRY_MASK 0x00000038
+ #define PORT_FEATURE_MBA_BOOT_RETRY_SHIFT 3
+
+ #define PORT_FEATURE_MBA_RES_PAUSE_CAP 0x00000100
+ #define PORT_FEATURE_MBA_RES_ASYM_PAUSE_CAP 0x00000200
+ #define PORT_FEATURE_MBA_SETUP_PROMPT_ENABLE 0x00000400
+ #define PORT_FEATURE_MBA_HOTKEY_MASK 0x00000800
+ #define PORT_FEATURE_MBA_HOTKEY_CTRL_S 0x00000000
+ #define PORT_FEATURE_MBA_HOTKEY_CTRL_B 0x00000800
+ #define PORT_FEATURE_MBA_EXP_ROM_SIZE_MASK 0x000ff000
+ #define PORT_FEATURE_MBA_EXP_ROM_SIZE_SHIFT 12
+ #define PORT_FEATURE_MBA_EXP_ROM_SIZE_DISABLED 0x00000000
+ #define PORT_FEATURE_MBA_EXP_ROM_SIZE_2K 0x00001000
+ #define PORT_FEATURE_MBA_EXP_ROM_SIZE_4K 0x00002000
+ #define PORT_FEATURE_MBA_EXP_ROM_SIZE_8K 0x00003000
+ #define PORT_FEATURE_MBA_EXP_ROM_SIZE_16K 0x00004000
+ #define PORT_FEATURE_MBA_EXP_ROM_SIZE_32K 0x00005000
+ #define PORT_FEATURE_MBA_EXP_ROM_SIZE_64K 0x00006000
+ #define PORT_FEATURE_MBA_EXP_ROM_SIZE_128K 0x00007000
+ #define PORT_FEATURE_MBA_EXP_ROM_SIZE_256K 0x00008000
+ #define PORT_FEATURE_MBA_EXP_ROM_SIZE_512K 0x00009000
+ #define PORT_FEATURE_MBA_EXP_ROM_SIZE_1M 0x0000a000
+ #define PORT_FEATURE_MBA_EXP_ROM_SIZE_2M 0x0000b000
+ #define PORT_FEATURE_MBA_EXP_ROM_SIZE_4M 0x0000c000
+ #define PORT_FEATURE_MBA_EXP_ROM_SIZE_8M 0x0000d000
+ #define PORT_FEATURE_MBA_EXP_ROM_SIZE_16M 0x0000e000
+ #define PORT_FEATURE_MBA_EXP_ROM_SIZE_32M 0x0000f000
+ #define PORT_FEATURE_MBA_MSG_TIMEOUT_MASK 0x00f00000
+ #define PORT_FEATURE_MBA_MSG_TIMEOUT_SHIFT 20
+ #define PORT_FEATURE_MBA_BIOS_BOOTSTRAP_MASK 0x03000000
+ #define PORT_FEATURE_MBA_BIOS_BOOTSTRAP_SHIFT 24
+ #define PORT_FEATURE_MBA_BIOS_BOOTSTRAP_AUTO 0x00000000
+ #define PORT_FEATURE_MBA_BIOS_BOOTSTRAP_BBS 0x01000000
+ #define PORT_FEATURE_MBA_BIOS_BOOTSTRAP_INT18H 0x02000000
+ #define PORT_FEATURE_MBA_BIOS_BOOTSTRAP_INT19H 0x03000000
+ #define PORT_FEATURE_MBA_LINK_SPEED_MASK 0x3c000000
+ #define PORT_FEATURE_MBA_LINK_SPEED_SHIFT 26
+ #define PORT_FEATURE_MBA_LINK_SPEED_AUTO 0x00000000
+ #define PORT_FEATURE_MBA_LINK_SPEED_10HD 0x04000000
+ #define PORT_FEATURE_MBA_LINK_SPEED_10FD 0x08000000
+ #define PORT_FEATURE_MBA_LINK_SPEED_100HD 0x0c000000
+ #define PORT_FEATURE_MBA_LINK_SPEED_100FD 0x10000000
+ #define PORT_FEATURE_MBA_LINK_SPEED_1GBPS 0x14000000
+ #define PORT_FEATURE_MBA_LINK_SPEED_2_5GBPS 0x18000000
+ #define PORT_FEATURE_MBA_LINK_SPEED_10GBPS_CX4 0x1c000000
+ #define PORT_FEATURE_MBA_LINK_SPEED_20GBPS 0x20000000
u32 bmc_config;
-#define PORT_FEATURE_BMC_LINK_OVERRIDE_DEFAULT 0x00000000
-#define PORT_FEATURE_BMC_LINK_OVERRIDE_EN 0x00000001
+ #define PORT_FEATURE_BMC_LINK_OVERRIDE_MASK 0x00000001
+ #define PORT_FEATURE_BMC_LINK_OVERRIDE_DEFAULT 0x00000000
+ #define PORT_FEATURE_BMC_LINK_OVERRIDE_EN 0x00000001
u32 mba_vlan_cfg;
-#define PORT_FEATURE_MBA_VLAN_TAG_MASK 0x0000ffff
-#define PORT_FEATURE_MBA_VLAN_TAG_SHIFT 0
-#define PORT_FEATURE_MBA_VLAN_EN 0x00010000
+ #define PORT_FEATURE_MBA_VLAN_TAG_MASK 0x0000ffff
+ #define PORT_FEATURE_MBA_VLAN_TAG_SHIFT 0
+ #define PORT_FEATURE_MBA_VLAN_EN 0x00010000
u32 resource_cfg;
-#define PORT_FEATURE_RESOURCE_CFG_VALID 0x00000001
-#define PORT_FEATURE_RESOURCE_CFG_DIAG 0x00000002
-#define PORT_FEATURE_RESOURCE_CFG_L2 0x00000004
-#define PORT_FEATURE_RESOURCE_CFG_ISCSI 0x00000008
-#define PORT_FEATURE_RESOURCE_CFG_RDMA 0x00000010
+ #define PORT_FEATURE_RESOURCE_CFG_VALID 0x00000001
+ #define PORT_FEATURE_RESOURCE_CFG_DIAG 0x00000002
+ #define PORT_FEATURE_RESOURCE_CFG_L2 0x00000004
+ #define PORT_FEATURE_RESOURCE_CFG_ISCSI 0x00000008
+ #define PORT_FEATURE_RESOURCE_CFG_RDMA 0x00000010
u32 smbus_config;
- /* Obsolete */
-#define PORT_FEATURE_SMBUS_EN 0x00000001
-#define PORT_FEATURE_SMBUS_ADDR_MASK 0x000000fe
-#define PORT_FEATURE_SMBUS_ADDR_SHIFT 1
+ #define PORT_FEATURE_SMBUS_ADDR_MASK 0x000000fe
+ #define PORT_FEATURE_SMBUS_ADDR_SHIFT 1
- u32 reserved1;
+ u32 vf_config;
+ #define PORT_FEAT_CFG_VF_BAR2_SIZE_MASK 0x0000000f
+ #define PORT_FEAT_CFG_VF_BAR2_SIZE_SHIFT 0
+ #define PORT_FEAT_CFG_VF_BAR2_SIZE_DISABLED 0x00000000
+ #define PORT_FEAT_CFG_VF_BAR2_SIZE_4K 0x00000001
+ #define PORT_FEAT_CFG_VF_BAR2_SIZE_8K 0x00000002
+ #define PORT_FEAT_CFG_VF_BAR2_SIZE_16K 0x00000003
+ #define PORT_FEAT_CFG_VF_BAR2_SIZE_32K 0x00000004
+ #define PORT_FEAT_CFG_VF_BAR2_SIZE_64K 0x00000005
+ #define PORT_FEAT_CFG_VF_BAR2_SIZE_128K 0x00000006
+ #define PORT_FEAT_CFG_VF_BAR2_SIZE_256K 0x00000007
+ #define PORT_FEAT_CFG_VF_BAR2_SIZE_512K 0x00000008
+ #define PORT_FEAT_CFG_VF_BAR2_SIZE_1M 0x00000009
+ #define PORT_FEAT_CFG_VF_BAR2_SIZE_2M 0x0000000a
+ #define PORT_FEAT_CFG_VF_BAR2_SIZE_4M 0x0000000b
+ #define PORT_FEAT_CFG_VF_BAR2_SIZE_8M 0x0000000c
+ #define PORT_FEAT_CFG_VF_BAR2_SIZE_16M 0x0000000d
+ #define PORT_FEAT_CFG_VF_BAR2_SIZE_32M 0x0000000e
+ #define PORT_FEAT_CFG_VF_BAR2_SIZE_64M 0x0000000f
u32 link_config; /* Used as HW defaults for the driver */
-#define PORT_FEATURE_CONNECTED_SWITCH_MASK 0x03000000
-#define PORT_FEATURE_CONNECTED_SWITCH_SHIFT 24
- /* (forced) low speed switch (< 10G) */
-#define PORT_FEATURE_CON_SWITCH_1G_SWITCH 0x00000000
- /* (forced) high speed switch (>= 10G) */
-#define PORT_FEATURE_CON_SWITCH_10G_SWITCH 0x01000000
-#define PORT_FEATURE_CON_SWITCH_AUTO_DETECT 0x02000000
-#define PORT_FEATURE_CON_SWITCH_ONE_TIME_DETECT 0x03000000
+ #define PORT_FEATURE_CONNECTED_SWITCH_MASK 0x03000000
+ #define PORT_FEATURE_CONNECTED_SWITCH_SHIFT 24
+ /* (forced) low speed switch (< 10G) */
+ #define PORT_FEATURE_CON_SWITCH_1G_SWITCH 0x00000000
+ /* (forced) high speed switch (>= 10G) */
+ #define PORT_FEATURE_CON_SWITCH_10G_SWITCH 0x01000000
+ #define PORT_FEATURE_CON_SWITCH_AUTO_DETECT 0x02000000
+ #define PORT_FEATURE_CON_SWITCH_ONE_TIME_DETECT 0x03000000
-#define PORT_FEATURE_LINK_SPEED_MASK 0x000f0000
-#define PORT_FEATURE_LINK_SPEED_SHIFT 16
-#define PORT_FEATURE_LINK_SPEED_AUTO 0x00000000
-#define PORT_FEATURE_LINK_SPEED_10M_FULL 0x00010000
-#define PORT_FEATURE_LINK_SPEED_10M_HALF 0x00020000
-#define PORT_FEATURE_LINK_SPEED_100M_HALF 0x00030000
-#define PORT_FEATURE_LINK_SPEED_100M_FULL 0x00040000
-#define PORT_FEATURE_LINK_SPEED_1G 0x00050000
-#define PORT_FEATURE_LINK_SPEED_2_5G 0x00060000
-#define PORT_FEATURE_LINK_SPEED_10G_CX4 0x00070000
-#define PORT_FEATURE_LINK_SPEED_10G_KX4 0x00080000
-#define PORT_FEATURE_LINK_SPEED_10G_KR 0x00090000
-#define PORT_FEATURE_LINK_SPEED_12G 0x000a0000
-#define PORT_FEATURE_LINK_SPEED_12_5G 0x000b0000
-#define PORT_FEATURE_LINK_SPEED_13G 0x000c0000
-#define PORT_FEATURE_LINK_SPEED_15G 0x000d0000
-#define PORT_FEATURE_LINK_SPEED_16G 0x000e0000
+ #define PORT_FEATURE_LINK_SPEED_MASK 0x000f0000
+ #define PORT_FEATURE_LINK_SPEED_SHIFT 16
+ #define PORT_FEATURE_LINK_SPEED_AUTO 0x00000000
+ #define PORT_FEATURE_LINK_SPEED_10M_FULL 0x00010000
+ #define PORT_FEATURE_LINK_SPEED_10M_HALF 0x00020000
+ #define PORT_FEATURE_LINK_SPEED_100M_HALF 0x00030000
+ #define PORT_FEATURE_LINK_SPEED_100M_FULL 0x00040000
+ #define PORT_FEATURE_LINK_SPEED_1G 0x00050000
+ #define PORT_FEATURE_LINK_SPEED_2_5G 0x00060000
+ #define PORT_FEATURE_LINK_SPEED_10G_CX4 0x00070000
+ #define PORT_FEATURE_LINK_SPEED_20G 0x00080000
-#define PORT_FEATURE_FLOW_CONTROL_MASK 0x00000700
-#define PORT_FEATURE_FLOW_CONTROL_SHIFT 8
-#define PORT_FEATURE_FLOW_CONTROL_AUTO 0x00000000
-#define PORT_FEATURE_FLOW_CONTROL_TX 0x00000100
-#define PORT_FEATURE_FLOW_CONTROL_RX 0x00000200
-#define PORT_FEATURE_FLOW_CONTROL_BOTH 0x00000300
-#define PORT_FEATURE_FLOW_CONTROL_NONE 0x00000400
+ #define PORT_FEATURE_FLOW_CONTROL_MASK 0x00000700
+ #define PORT_FEATURE_FLOW_CONTROL_SHIFT 8
+ #define PORT_FEATURE_FLOW_CONTROL_AUTO 0x00000000
+ #define PORT_FEATURE_FLOW_CONTROL_TX 0x00000100
+ #define PORT_FEATURE_FLOW_CONTROL_RX 0x00000200
+ #define PORT_FEATURE_FLOW_CONTROL_BOTH 0x00000300
+ #define PORT_FEATURE_FLOW_CONTROL_NONE 0x00000400
/* The default for MCP link configuration,
- uses the same defines as link_config */
+ uses the same defines as link_config */
u32 mfw_wol_link_cfg;
+
/* The default for the driver of the second external phy,
- uses the same defines as link_config */
- u32 link_config2; /* 0x47C */
+ uses the same defines as link_config */
+ u32 link_config2; /* 0x47C */
/* The default for MCP of the second external phy,
- uses the same defines as link_config */
- u32 mfw_wol_link_cfg2; /* 0x480 */
+ uses the same defines as link_config */
+ u32 mfw_wol_link_cfg2; /* 0x480 */
- u32 Reserved2[17]; /* 0x484 */
+ u32 Reserved2[17]; /* 0x484 */
};
/****************************************************************************
- * Device Information *
+ * Device Information *
****************************************************************************/
-struct shm_dev_info { /* size */
+struct shm_dev_info { /* size */
u32 bc_rev; /* 8 bits each: major, minor, build */ /* 4 */
- struct shared_hw_cfg shared_hw_config; /* 40 */
+ struct shared_hw_cfg shared_hw_config; /* 40 */
- struct port_hw_cfg port_hw_config[PORT_MAX]; /* 400*2=800 */
+ struct port_hw_cfg port_hw_config[PORT_MAX]; /* 400*2=800 */
- struct shared_feat_cfg shared_feature_config; /* 4 */
+ struct shared_feat_cfg shared_feature_config; /* 4 */
- struct port_feat_cfg port_feature_config[PORT_MAX];/* 116*2=232 */
+ struct port_feat_cfg port_feature_config[PORT_MAX];/* 116*2=232 */
};
-#define FUNC_0 0
-#define FUNC_1 1
-#define FUNC_2 2
-#define FUNC_3 3
-#define FUNC_4 4
-#define FUNC_5 5
-#define FUNC_6 6
-#define FUNC_7 7
-#define E1_FUNC_MAX 2
-#define E1H_FUNC_MAX 8
-#define E2_FUNC_MAX 4 /* per path */
+#if !defined(__LITTLE_ENDIAN) && !defined(__BIG_ENDIAN)
+ #error "Missing either LITTLE_ENDIAN or BIG_ENDIAN definition."
+#endif
-#define VN_0 0
-#define VN_1 1
-#define VN_2 2
-#define VN_3 3
-#define E1VN_MAX 1
-#define E1HVN_MAX 4
+#define FUNC_0 0
+#define FUNC_1 1
+#define FUNC_2 2
+#define FUNC_3 3
+#define FUNC_4 4
+#define FUNC_5 5
+#define FUNC_6 6
+#define FUNC_7 7
+#define E1_FUNC_MAX 2
+#define E1H_FUNC_MAX 8
+#define E2_FUNC_MAX 4 /* per path */
-#define E2_VF_MAX 64
+#define VN_0 0
+#define VN_1 1
+#define VN_2 2
+#define VN_3 3
+#define E1VN_MAX 1
+#define E1HVN_MAX 4
+
+#define E2_VF_MAX 64 /* HC_REG_VF_CONFIGURATION_SIZE */
/* This value (in milliseconds) determines the frequency of the driver
* issuing the PULSE message code. The firmware monitors this periodic
* pulse to determine when to switch to an OS-absent mode. */
-#define DRV_PULSE_PERIOD_MS 250
+#define DRV_PULSE_PERIOD_MS 250
/* This value (in milliseconds) determines how long the driver should
* wait for an acknowledgement from the firmware before timing out. Once
* the firmware has timed out, the driver will assume there is no firmware
* running and there won't be any firmware-driver synchronization during a
* driver reset. */
-#define FW_ACK_TIME_OUT_MS 5000
+#define FW_ACK_TIME_OUT_MS 5000
-#define FW_ACK_POLL_TIME_MS 1
+#define FW_ACK_POLL_TIME_MS 1
-#define FW_ACK_NUM_OF_POLL (FW_ACK_TIME_OUT_MS/FW_ACK_POLL_TIME_MS)
+#define FW_ACK_NUM_OF_POLL (FW_ACK_TIME_OUT_MS/FW_ACK_POLL_TIME_MS)
/* LED Blink rate that will achieve ~15.9Hz */
-#define LED_BLINK_RATE_VAL 480
+#define LED_BLINK_RATE_VAL 480
/****************************************************************************
- * Driver <-> FW Mailbox *
+ * Driver <-> FW Mailbox *
****************************************************************************/
struct drv_port_mb {
u32 link_status;
/* Driver should update this field on any link change event */
-#define LINK_STATUS_LINK_FLAG_MASK 0x00000001
-#define LINK_STATUS_LINK_UP 0x00000001
-#define LINK_STATUS_SPEED_AND_DUPLEX_MASK 0x0000001E
-#define LINK_STATUS_SPEED_AND_DUPLEX_AN_NOT_COMPLETE (0<<1)
-#define LINK_STATUS_SPEED_AND_DUPLEX_10THD (1<<1)
-#define LINK_STATUS_SPEED_AND_DUPLEX_10TFD (2<<1)
-#define LINK_STATUS_SPEED_AND_DUPLEX_100TXHD (3<<1)
-#define LINK_STATUS_SPEED_AND_DUPLEX_100T4 (4<<1)
-#define LINK_STATUS_SPEED_AND_DUPLEX_100TXFD (5<<1)
-#define LINK_STATUS_SPEED_AND_DUPLEX_1000THD (6<<1)
-#define LINK_STATUS_SPEED_AND_DUPLEX_1000TFD (7<<1)
-#define LINK_STATUS_SPEED_AND_DUPLEX_1000XFD (7<<1)
-#define LINK_STATUS_SPEED_AND_DUPLEX_2500THD (8<<1)
-#define LINK_STATUS_SPEED_AND_DUPLEX_2500TFD (9<<1)
-#define LINK_STATUS_SPEED_AND_DUPLEX_2500XFD (9<<1)
-#define LINK_STATUS_SPEED_AND_DUPLEX_10GTFD (10<<1)
-#define LINK_STATUS_SPEED_AND_DUPLEX_10GXFD (10<<1)
-#define LINK_STATUS_SPEED_AND_DUPLEX_12GTFD (11<<1)
-#define LINK_STATUS_SPEED_AND_DUPLEX_12GXFD (11<<1)
-#define LINK_STATUS_SPEED_AND_DUPLEX_12_5GTFD (12<<1)
-#define LINK_STATUS_SPEED_AND_DUPLEX_12_5GXFD (12<<1)
-#define LINK_STATUS_SPEED_AND_DUPLEX_13GTFD (13<<1)
-#define LINK_STATUS_SPEED_AND_DUPLEX_13GXFD (13<<1)
-#define LINK_STATUS_SPEED_AND_DUPLEX_15GTFD (14<<1)
-#define LINK_STATUS_SPEED_AND_DUPLEX_15GXFD (14<<1)
-#define LINK_STATUS_SPEED_AND_DUPLEX_16GTFD (15<<1)
-#define LINK_STATUS_SPEED_AND_DUPLEX_16GXFD (15<<1)
+ #define LINK_STATUS_LINK_FLAG_MASK 0x00000001
+ #define LINK_STATUS_LINK_UP 0x00000001
+ #define LINK_STATUS_SPEED_AND_DUPLEX_MASK 0x0000001E
+ #define LINK_STATUS_SPEED_AND_DUPLEX_AN_NOT_COMPLETE (0<<1)
+ #define LINK_STATUS_SPEED_AND_DUPLEX_10THD (1<<1)
+ #define LINK_STATUS_SPEED_AND_DUPLEX_10TFD (2<<1)
+ #define LINK_STATUS_SPEED_AND_DUPLEX_100TXHD (3<<1)
+ #define LINK_STATUS_SPEED_AND_DUPLEX_100T4 (4<<1)
+ #define LINK_STATUS_SPEED_AND_DUPLEX_100TXFD (5<<1)
+ #define LINK_STATUS_SPEED_AND_DUPLEX_1000THD (6<<1)
+ #define LINK_STATUS_SPEED_AND_DUPLEX_1000TFD (7<<1)
+ #define LINK_STATUS_SPEED_AND_DUPLEX_1000XFD (7<<1)
+ #define LINK_STATUS_SPEED_AND_DUPLEX_2500THD (8<<1)
+ #define LINK_STATUS_SPEED_AND_DUPLEX_2500TFD (9<<1)
+ #define LINK_STATUS_SPEED_AND_DUPLEX_2500XFD (9<<1)
+ #define LINK_STATUS_SPEED_AND_DUPLEX_10GTFD (10<<1)
+ #define LINK_STATUS_SPEED_AND_DUPLEX_10GXFD (10<<1)
+ #define LINK_STATUS_SPEED_AND_DUPLEX_20GTFD (11<<1)
+ #define LINK_STATUS_SPEED_AND_DUPLEX_20GXFD (11<<1)
-#define LINK_STATUS_AUTO_NEGOTIATE_FLAG_MASK 0x00000020
-#define LINK_STATUS_AUTO_NEGOTIATE_ENABLED 0x00000020
+ #define LINK_STATUS_AUTO_NEGOTIATE_FLAG_MASK 0x00000020
+ #define LINK_STATUS_AUTO_NEGOTIATE_ENABLED 0x00000020
-#define LINK_STATUS_AUTO_NEGOTIATE_COMPLETE 0x00000040
-#define LINK_STATUS_PARALLEL_DETECTION_FLAG_MASK 0x00000080
-#define LINK_STATUS_PARALLEL_DETECTION_USED 0x00000080
+ #define LINK_STATUS_AUTO_NEGOTIATE_COMPLETE 0x00000040
+ #define LINK_STATUS_PARALLEL_DETECTION_FLAG_MASK 0x00000080
+ #define LINK_STATUS_PARALLEL_DETECTION_USED 0x00000080
-#define LINK_STATUS_LINK_PARTNER_1000TFD_CAPABLE 0x00000200
-#define LINK_STATUS_LINK_PARTNER_1000THD_CAPABLE 0x00000400
-#define LINK_STATUS_LINK_PARTNER_100T4_CAPABLE 0x00000800
-#define LINK_STATUS_LINK_PARTNER_100TXFD_CAPABLE 0x00001000
-#define LINK_STATUS_LINK_PARTNER_100TXHD_CAPABLE 0x00002000
-#define LINK_STATUS_LINK_PARTNER_10TFD_CAPABLE 0x00004000
-#define LINK_STATUS_LINK_PARTNER_10THD_CAPABLE 0x00008000
+ #define LINK_STATUS_LINK_PARTNER_1000TFD_CAPABLE 0x00000200
+ #define LINK_STATUS_LINK_PARTNER_1000THD_CAPABLE 0x00000400
+ #define LINK_STATUS_LINK_PARTNER_100T4_CAPABLE 0x00000800
+ #define LINK_STATUS_LINK_PARTNER_100TXFD_CAPABLE 0x00001000
+ #define LINK_STATUS_LINK_PARTNER_100TXHD_CAPABLE 0x00002000
+ #define LINK_STATUS_LINK_PARTNER_10TFD_CAPABLE 0x00004000
+ #define LINK_STATUS_LINK_PARTNER_10THD_CAPABLE 0x00008000
-#define LINK_STATUS_TX_FLOW_CONTROL_FLAG_MASK 0x00010000
-#define LINK_STATUS_TX_FLOW_CONTROL_ENABLED 0x00010000
+ #define LINK_STATUS_TX_FLOW_CONTROL_FLAG_MASK 0x00010000
+ #define LINK_STATUS_TX_FLOW_CONTROL_ENABLED 0x00010000
-#define LINK_STATUS_RX_FLOW_CONTROL_FLAG_MASK 0x00020000
-#define LINK_STATUS_RX_FLOW_CONTROL_ENABLED 0x00020000
+ #define LINK_STATUS_RX_FLOW_CONTROL_FLAG_MASK 0x00020000
+ #define LINK_STATUS_RX_FLOW_CONTROL_ENABLED 0x00020000
-#define LINK_STATUS_LINK_PARTNER_FLOW_CONTROL_MASK 0x000C0000
-#define LINK_STATUS_LINK_PARTNER_NOT_PAUSE_CAPABLE (0<<18)
-#define LINK_STATUS_LINK_PARTNER_SYMMETRIC_PAUSE (1<<18)
-#define LINK_STATUS_LINK_PARTNER_ASYMMETRIC_PAUSE (2<<18)
-#define LINK_STATUS_LINK_PARTNER_BOTH_PAUSE (3<<18)
+ #define LINK_STATUS_LINK_PARTNER_FLOW_CONTROL_MASK 0x000C0000
+ #define LINK_STATUS_LINK_PARTNER_NOT_PAUSE_CAPABLE (0<<18)
+ #define LINK_STATUS_LINK_PARTNER_SYMMETRIC_PAUSE (1<<18)
+ #define LINK_STATUS_LINK_PARTNER_ASYMMETRIC_PAUSE (2<<18)
+ #define LINK_STATUS_LINK_PARTNER_BOTH_PAUSE (3<<18)
-#define LINK_STATUS_SERDES_LINK 0x00100000
+ #define LINK_STATUS_SERDES_LINK 0x00100000
-#define LINK_STATUS_LINK_PARTNER_2500XFD_CAPABLE 0x00200000
-#define LINK_STATUS_LINK_PARTNER_2500XHD_CAPABLE 0x00400000
-#define LINK_STATUS_LINK_PARTNER_10GXFD_CAPABLE 0x00800000
-#define LINK_STATUS_LINK_PARTNER_12GXFD_CAPABLE 0x01000000
-#define LINK_STATUS_LINK_PARTNER_12_5GXFD_CAPABLE 0x02000000
-#define LINK_STATUS_LINK_PARTNER_13GXFD_CAPABLE 0x04000000
-#define LINK_STATUS_LINK_PARTNER_15GXFD_CAPABLE 0x08000000
-#define LINK_STATUS_LINK_PARTNER_16GXFD_CAPABLE 0x10000000
+ #define LINK_STATUS_LINK_PARTNER_2500XFD_CAPABLE 0x00200000
+ #define LINK_STATUS_LINK_PARTNER_2500XHD_CAPABLE 0x00400000
+ #define LINK_STATUS_LINK_PARTNER_10GXFD_CAPABLE 0x00800000
+ #define LINK_STATUS_LINK_PARTNER_20GXFD_CAPABLE 0x10000000
+
+ #define LINK_STATUS_PFC_ENABLED 0x20000000
u32 port_stx;
@@ -887,138 +1217,159 @@
struct drv_func_mb {
u32 drv_mb_header;
-#define DRV_MSG_CODE_MASK 0xffff0000
-#define DRV_MSG_CODE_LOAD_REQ 0x10000000
-#define DRV_MSG_CODE_LOAD_DONE 0x11000000
-#define DRV_MSG_CODE_UNLOAD_REQ_WOL_EN 0x20000000
-#define DRV_MSG_CODE_UNLOAD_REQ_WOL_DIS 0x20010000
-#define DRV_MSG_CODE_UNLOAD_REQ_WOL_MCP 0x20020000
-#define DRV_MSG_CODE_UNLOAD_DONE 0x21000000
-#define DRV_MSG_CODE_DCC_OK 0x30000000
-#define DRV_MSG_CODE_DCC_FAILURE 0x31000000
-#define DRV_MSG_CODE_DIAG_ENTER_REQ 0x50000000
-#define DRV_MSG_CODE_DIAG_EXIT_REQ 0x60000000
-#define DRV_MSG_CODE_VALIDATE_KEY 0x70000000
-#define DRV_MSG_CODE_GET_CURR_KEY 0x80000000
-#define DRV_MSG_CODE_GET_UPGRADE_KEY 0x81000000
-#define DRV_MSG_CODE_GET_MANUF_KEY 0x82000000
-#define DRV_MSG_CODE_LOAD_L2B_PRAM 0x90000000
+ #define DRV_MSG_CODE_MASK 0xffff0000
+ #define DRV_MSG_CODE_LOAD_REQ 0x10000000
+ #define DRV_MSG_CODE_LOAD_DONE 0x11000000
+ #define DRV_MSG_CODE_UNLOAD_REQ_WOL_EN 0x20000000
+ #define DRV_MSG_CODE_UNLOAD_REQ_WOL_DIS 0x20010000
+ #define DRV_MSG_CODE_UNLOAD_REQ_WOL_MCP 0x20020000
+ #define DRV_MSG_CODE_UNLOAD_DONE 0x21000000
+ #define DRV_MSG_CODE_DCC_OK 0x30000000
+ #define DRV_MSG_CODE_DCC_FAILURE 0x31000000
+ #define DRV_MSG_CODE_DIAG_ENTER_REQ 0x50000000
+ #define DRV_MSG_CODE_DIAG_EXIT_REQ 0x60000000
+ #define DRV_MSG_CODE_VALIDATE_KEY 0x70000000
+ #define DRV_MSG_CODE_GET_CURR_KEY 0x80000000
+ #define DRV_MSG_CODE_GET_UPGRADE_KEY 0x81000000
+ #define DRV_MSG_CODE_GET_MANUF_KEY 0x82000000
+ #define DRV_MSG_CODE_LOAD_L2B_PRAM 0x90000000
/*
- * The optic module verification commands require bootcode
- * v5.0.6 or later
+ * The optic module verification command requires bootcode
+ * v5.0.6 or later, te specific optic module verification command
+ * requires bootcode v5.2.12 or later
*/
-#define DRV_MSG_CODE_VRFY_FIRST_PHY_OPT_MDL 0xa0000000
-#define REQ_BC_VER_4_VRFY_FIRST_PHY_OPT_MDL 0x00050006
- /*
- * The specific optic module verification command requires bootcode
- * v5.2.12 or later
- */
-#define DRV_MSG_CODE_VRFY_SPECIFIC_PHY_OPT_MDL 0xa1000000
-#define REQ_BC_VER_4_VRFY_SPECIFIC_PHY_OPT_MDL 0x00050234
+ #define DRV_MSG_CODE_VRFY_FIRST_PHY_OPT_MDL 0xa0000000
+ #define REQ_BC_VER_4_VRFY_FIRST_PHY_OPT_MDL 0x00050006
+ #define DRV_MSG_CODE_VRFY_SPECIFIC_PHY_OPT_MDL 0xa1000000
+ #define REQ_BC_VER_4_VRFY_SPECIFIC_PHY_OPT_MDL 0x00050234
+ #define REQ_BC_VER_4_SFP_TX_DISABLE_SUPPORTED 0x00070014
-#define DRV_MSG_CODE_DCBX_ADMIN_PMF_MSG 0xb0000000
-#define DRV_MSG_CODE_DCBX_PMF_DRV_OK 0xb2000000
-#define DRV_MSG_CODE_SET_MF_BW 0xe0000000
-#define REQ_BC_VER_4_SET_MF_BW 0x00060202
-#define DRV_MSG_CODE_SET_MF_BW_ACK 0xe1000000
-#define BIOS_MSG_CODE_LIC_CHALLENGE 0xff010000
-#define BIOS_MSG_CODE_LIC_RESPONSE 0xff020000
-#define BIOS_MSG_CODE_VIRT_MAC_PRIM 0xff030000
-#define BIOS_MSG_CODE_VIRT_MAC_ISCSI 0xff040000
+ #define DRV_MSG_CODE_DCBX_ADMIN_PMF_MSG 0xb0000000
+ #define DRV_MSG_CODE_DCBX_PMF_DRV_OK 0xb2000000
-#define DRV_MSG_SEQ_NUMBER_MASK 0x0000ffff
+ #define DRV_MSG_CODE_VF_DISABLED_DONE 0xc0000000
+
+ #define DRV_MSG_CODE_SET_MF_BW 0xe0000000
+ #define REQ_BC_VER_4_SET_MF_BW 0x00060202
+ #define DRV_MSG_CODE_SET_MF_BW_ACK 0xe1000000
+
+ #define DRV_MSG_CODE_LINK_STATUS_CHANGED 0x01000000
+
+ #define BIOS_MSG_CODE_LIC_CHALLENGE 0xff010000
+ #define BIOS_MSG_CODE_LIC_RESPONSE 0xff020000
+ #define BIOS_MSG_CODE_VIRT_MAC_PRIM 0xff030000
+ #define BIOS_MSG_CODE_VIRT_MAC_ISCSI 0xff040000
+
+ #define DRV_MSG_SEQ_NUMBER_MASK 0x0000ffff
u32 drv_mb_param;
+ #define DRV_MSG_CODE_SET_MF_BW_MIN_MASK 0x00ff0000
+ #define DRV_MSG_CODE_SET_MF_BW_MAX_MASK 0xff000000
u32 fw_mb_header;
-#define FW_MSG_CODE_MASK 0xffff0000
-#define FW_MSG_CODE_DRV_LOAD_COMMON 0x10100000
-#define FW_MSG_CODE_DRV_LOAD_PORT 0x10110000
-#define FW_MSG_CODE_DRV_LOAD_FUNCTION 0x10120000
- /* Load common chip is supported from bc 6.0.0 */
-#define REQ_BC_VER_4_DRV_LOAD_COMMON_CHIP 0x00060000
-#define FW_MSG_CODE_DRV_LOAD_COMMON_CHIP 0x10130000
-#define FW_MSG_CODE_DRV_LOAD_REFUSED 0x10200000
-#define FW_MSG_CODE_DRV_LOAD_DONE 0x11100000
-#define FW_MSG_CODE_DRV_UNLOAD_COMMON 0x20100000
-#define FW_MSG_CODE_DRV_UNLOAD_PORT 0x20110000
-#define FW_MSG_CODE_DRV_UNLOAD_FUNCTION 0x20120000
-#define FW_MSG_CODE_DRV_UNLOAD_DONE 0x21100000
-#define FW_MSG_CODE_DCC_DONE 0x30100000
-#define FW_MSG_CODE_DIAG_ENTER_DONE 0x50100000
-#define FW_MSG_CODE_DIAG_REFUSE 0x50200000
-#define FW_MSG_CODE_DIAG_EXIT_DONE 0x60100000
-#define FW_MSG_CODE_VALIDATE_KEY_SUCCESS 0x70100000
-#define FW_MSG_CODE_VALIDATE_KEY_FAILURE 0x70200000
-#define FW_MSG_CODE_GET_KEY_DONE 0x80100000
-#define FW_MSG_CODE_NO_KEY 0x80f00000
-#define FW_MSG_CODE_LIC_INFO_NOT_READY 0x80f80000
-#define FW_MSG_CODE_L2B_PRAM_LOADED 0x90100000
-#define FW_MSG_CODE_L2B_PRAM_T_LOAD_FAILURE 0x90210000
-#define FW_MSG_CODE_L2B_PRAM_C_LOAD_FAILURE 0x90220000
-#define FW_MSG_CODE_L2B_PRAM_X_LOAD_FAILURE 0x90230000
-#define FW_MSG_CODE_L2B_PRAM_U_LOAD_FAILURE 0x90240000
-#define FW_MSG_CODE_VRFY_OPT_MDL_SUCCESS 0xa0100000
-#define FW_MSG_CODE_VRFY_OPT_MDL_INVLD_IMG 0xa0200000
-#define FW_MSG_CODE_VRFY_OPT_MDL_UNAPPROVED 0xa0300000
+ #define FW_MSG_CODE_MASK 0xffff0000
+ #define FW_MSG_CODE_DRV_LOAD_COMMON 0x10100000
+ #define FW_MSG_CODE_DRV_LOAD_PORT 0x10110000
+ #define FW_MSG_CODE_DRV_LOAD_FUNCTION 0x10120000
+ /* Load common chip is supported from bc 6.0.0 */
+ #define REQ_BC_VER_4_DRV_LOAD_COMMON_CHIP 0x00060000
+ #define FW_MSG_CODE_DRV_LOAD_COMMON_CHIP 0x10130000
-#define FW_MSG_CODE_LIC_CHALLENGE 0xff010000
-#define FW_MSG_CODE_LIC_RESPONSE 0xff020000
-#define FW_MSG_CODE_VIRT_MAC_PRIM 0xff030000
-#define FW_MSG_CODE_VIRT_MAC_ISCSI 0xff040000
+ #define FW_MSG_CODE_DRV_LOAD_REFUSED 0x10200000
+ #define FW_MSG_CODE_DRV_LOAD_DONE 0x11100000
+ #define FW_MSG_CODE_DRV_UNLOAD_COMMON 0x20100000
+ #define FW_MSG_CODE_DRV_UNLOAD_PORT 0x20110000
+ #define FW_MSG_CODE_DRV_UNLOAD_FUNCTION 0x20120000
+ #define FW_MSG_CODE_DRV_UNLOAD_DONE 0x21100000
+ #define FW_MSG_CODE_DCC_DONE 0x30100000
+ #define FW_MSG_CODE_LLDP_DONE 0x40100000
+ #define FW_MSG_CODE_DIAG_ENTER_DONE 0x50100000
+ #define FW_MSG_CODE_DIAG_REFUSE 0x50200000
+ #define FW_MSG_CODE_DIAG_EXIT_DONE 0x60100000
+ #define FW_MSG_CODE_VALIDATE_KEY_SUCCESS 0x70100000
+ #define FW_MSG_CODE_VALIDATE_KEY_FAILURE 0x70200000
+ #define FW_MSG_CODE_GET_KEY_DONE 0x80100000
+ #define FW_MSG_CODE_NO_KEY 0x80f00000
+ #define FW_MSG_CODE_LIC_INFO_NOT_READY 0x80f80000
+ #define FW_MSG_CODE_L2B_PRAM_LOADED 0x90100000
+ #define FW_MSG_CODE_L2B_PRAM_T_LOAD_FAILURE 0x90210000
+ #define FW_MSG_CODE_L2B_PRAM_C_LOAD_FAILURE 0x90220000
+ #define FW_MSG_CODE_L2B_PRAM_X_LOAD_FAILURE 0x90230000
+ #define FW_MSG_CODE_L2B_PRAM_U_LOAD_FAILURE 0x90240000
+ #define FW_MSG_CODE_VRFY_OPT_MDL_SUCCESS 0xa0100000
+ #define FW_MSG_CODE_VRFY_OPT_MDL_INVLD_IMG 0xa0200000
+ #define FW_MSG_CODE_VRFY_OPT_MDL_UNAPPROVED 0xa0300000
+ #define FW_MSG_CODE_VF_DISABLED_DONE 0xb0000000
-#define FW_MSG_SEQ_NUMBER_MASK 0x0000ffff
+ #define FW_MSG_CODE_SET_MF_BW_SENT 0xe0000000
+ #define FW_MSG_CODE_SET_MF_BW_DONE 0xe1000000
+
+ #define FW_MSG_CODE_LINK_CHANGED_ACK 0x01100000
+
+ #define FW_MSG_CODE_LIC_CHALLENGE 0xff010000
+ #define FW_MSG_CODE_LIC_RESPONSE 0xff020000
+ #define FW_MSG_CODE_VIRT_MAC_PRIM 0xff030000
+ #define FW_MSG_CODE_VIRT_MAC_ISCSI 0xff040000
+
+ #define FW_MSG_SEQ_NUMBER_MASK 0x0000ffff
u32 fw_mb_param;
u32 drv_pulse_mb;
-#define DRV_PULSE_SEQ_MASK 0x00007fff
-#define DRV_PULSE_SYSTEM_TIME_MASK 0xffff0000
- /* The system time is in the format of
- * (year-2001)*12*32 + month*32 + day. */
-#define DRV_PULSE_ALWAYS_ALIVE 0x00008000
- /* Indicate to the firmware not to go into the
+ #define DRV_PULSE_SEQ_MASK 0x00007fff
+ #define DRV_PULSE_SYSTEM_TIME_MASK 0xffff0000
+ /*
+ * The system time is in the format of
+ * (year-2001)*12*32 + month*32 + day.
+ */
+ #define DRV_PULSE_ALWAYS_ALIVE 0x00008000
+ /*
+ * Indicate to the firmware not to go into the
* OS-absent when it is not getting driver pulse.
- * This is used for debugging as well for PXE(MBA). */
+ * This is used for debugging as well for PXE(MBA).
+ */
u32 mcp_pulse_mb;
-#define MCP_PULSE_SEQ_MASK 0x00007fff
-#define MCP_PULSE_ALWAYS_ALIVE 0x00008000
+ #define MCP_PULSE_SEQ_MASK 0x00007fff
+ #define MCP_PULSE_ALWAYS_ALIVE 0x00008000
/* Indicates to the driver not to assert due to lack
* of MCP response */
-#define MCP_EVENT_MASK 0xffff0000
-#define MCP_EVENT_OTHER_DRIVER_RESET_REQ 0x00010000
+ #define MCP_EVENT_MASK 0xffff0000
+ #define MCP_EVENT_OTHER_DRIVER_RESET_REQ 0x00010000
u32 iscsi_boot_signature;
u32 iscsi_boot_block_offset;
u32 drv_status;
-#define DRV_STATUS_PMF 0x00000001
-#define DRV_STATUS_SET_MF_BW 0x00000004
+ #define DRV_STATUS_PMF 0x00000001
+ #define DRV_STATUS_VF_DISABLED 0x00000002
+ #define DRV_STATUS_SET_MF_BW 0x00000004
+ #define DRV_STATUS_LINK_EVENT 0x00000008
-#define DRV_STATUS_DCC_EVENT_MASK 0x0000ff00
-#define DRV_STATUS_DCC_DISABLE_ENABLE_PF 0x00000100
-#define DRV_STATUS_DCC_BANDWIDTH_ALLOCATION 0x00000200
-#define DRV_STATUS_DCC_CHANGE_MAC_ADDRESS 0x00000400
-#define DRV_STATUS_DCC_RESERVED1 0x00000800
-#define DRV_STATUS_DCC_SET_PROTOCOL 0x00001000
-#define DRV_STATUS_DCC_SET_PRIORITY 0x00002000
-#define DRV_STATUS_DCBX_EVENT_MASK 0x000f0000
-#define DRV_STATUS_DCBX_NEGOTIATION_RESULTS 0x00010000
+ #define DRV_STATUS_DCC_EVENT_MASK 0x0000ff00
+ #define DRV_STATUS_DCC_DISABLE_ENABLE_PF 0x00000100
+ #define DRV_STATUS_DCC_BANDWIDTH_ALLOCATION 0x00000200
+ #define DRV_STATUS_DCC_CHANGE_MAC_ADDRESS 0x00000400
+ #define DRV_STATUS_DCC_RESERVED1 0x00000800
+ #define DRV_STATUS_DCC_SET_PROTOCOL 0x00001000
+ #define DRV_STATUS_DCC_SET_PRIORITY 0x00002000
+
+ #define DRV_STATUS_DCBX_EVENT_MASK 0x000f0000
+ #define DRV_STATUS_DCBX_NEGOTIATION_RESULTS 0x00010000
u32 virt_mac_upper;
-#define VIRT_MAC_SIGN_MASK 0xffff0000
-#define VIRT_MAC_SIGNATURE 0x564d0000
+ #define VIRT_MAC_SIGN_MASK 0xffff0000
+ #define VIRT_MAC_SIGNATURE 0x564d0000
u32 virt_mac_lower;
};
/****************************************************************************
- * Management firmware state *
+ * Management firmware state *
****************************************************************************/
/* Allocate 440 bytes for management firmware */
-#define MGMTFW_STATE_WORD_SIZE 110
+#define MGMTFW_STATE_WORD_SIZE 110
struct mgmtfw_state {
u32 opaque[MGMTFW_STATE_WORD_SIZE];
@@ -1026,25 +1377,25 @@
/****************************************************************************
- * Multi-Function configuration *
+ * Multi-Function configuration *
****************************************************************************/
struct shared_mf_cfg {
u32 clp_mb;
-#define SHARED_MF_CLP_SET_DEFAULT 0x00000000
+ #define SHARED_MF_CLP_SET_DEFAULT 0x00000000
/* set by CLP */
-#define SHARED_MF_CLP_EXIT 0x00000001
+ #define SHARED_MF_CLP_EXIT 0x00000001
/* set by MCP */
-#define SHARED_MF_CLP_EXIT_DONE 0x00010000
+ #define SHARED_MF_CLP_EXIT_DONE 0x00010000
};
struct port_mf_cfg {
- u32 dynamic_cfg; /* device control channel */
-#define PORT_MF_CFG_E1HOV_TAG_MASK 0x0000ffff
-#define PORT_MF_CFG_E1HOV_TAG_SHIFT 0
-#define PORT_MF_CFG_E1HOV_TAG_DEFAULT PORT_MF_CFG_E1HOV_TAG_MASK
+ u32 dynamic_cfg; /* device control channel */
+ #define PORT_MF_CFG_E1HOV_TAG_MASK 0x0000ffff
+ #define PORT_MF_CFG_E1HOV_TAG_SHIFT 0
+ #define PORT_MF_CFG_E1HOV_TAG_DEFAULT PORT_MF_CFG_E1HOV_TAG_MASK
u32 reserved[3];
@@ -1055,57 +1406,58 @@
u32 config;
/* E/R/I/D */
/* function 0 of each port cannot be hidden */
-#define FUNC_MF_CFG_FUNC_HIDE 0x00000001
+ #define FUNC_MF_CFG_FUNC_HIDE 0x00000001
-#define FUNC_MF_CFG_PROTOCOL_MASK 0x00000007
-#define FUNC_MF_CFG_PROTOCOL_ETHERNET 0x00000002
-#define FUNC_MF_CFG_PROTOCOL_ETHERNET_WITH_RDMA 0x00000004
-#define FUNC_MF_CFG_PROTOCOL_ISCSI 0x00000006
-#define FUNC_MF_CFG_PROTOCOL_DEFAULT\
- FUNC_MF_CFG_PROTOCOL_ETHERNET_WITH_RDMA
+ #define FUNC_MF_CFG_PROTOCOL_MASK 0x00000006
+ #define FUNC_MF_CFG_PROTOCOL_FCOE 0x00000000
+ #define FUNC_MF_CFG_PROTOCOL_ETHERNET 0x00000002
+ #define FUNC_MF_CFG_PROTOCOL_ETHERNET_WITH_RDMA 0x00000004
+ #define FUNC_MF_CFG_PROTOCOL_ISCSI 0x00000006
+ #define FUNC_MF_CFG_PROTOCOL_DEFAULT \
+ FUNC_MF_CFG_PROTOCOL_ETHERNET_WITH_RDMA
-#define FUNC_MF_CFG_FUNC_DISABLED 0x00000008
+ #define FUNC_MF_CFG_FUNC_DISABLED 0x00000008
+ #define FUNC_MF_CFG_FUNC_DELETED 0x00000010
/* PRI */
/* 0 - low priority, 3 - high priority */
-#define FUNC_MF_CFG_TRANSMIT_PRIORITY_MASK 0x00000300
-#define FUNC_MF_CFG_TRANSMIT_PRIORITY_SHIFT 8
-#define FUNC_MF_CFG_TRANSMIT_PRIORITY_DEFAULT 0x00000000
+ #define FUNC_MF_CFG_TRANSMIT_PRIORITY_MASK 0x00000300
+ #define FUNC_MF_CFG_TRANSMIT_PRIORITY_SHIFT 8
+ #define FUNC_MF_CFG_TRANSMIT_PRIORITY_DEFAULT 0x00000000
/* MINBW, MAXBW */
/* value range - 0..100, increments in 100Mbps */
-#define FUNC_MF_CFG_MIN_BW_MASK 0x00ff0000
-#define FUNC_MF_CFG_MIN_BW_SHIFT 16
-#define FUNC_MF_CFG_MIN_BW_DEFAULT 0x00000000
-#define FUNC_MF_CFG_MAX_BW_MASK 0xff000000
-#define FUNC_MF_CFG_MAX_BW_SHIFT 24
-#define FUNC_MF_CFG_MAX_BW_DEFAULT 0x64000000
+ #define FUNC_MF_CFG_MIN_BW_MASK 0x00ff0000
+ #define FUNC_MF_CFG_MIN_BW_SHIFT 16
+ #define FUNC_MF_CFG_MIN_BW_DEFAULT 0x00000000
+ #define FUNC_MF_CFG_MAX_BW_MASK 0xff000000
+ #define FUNC_MF_CFG_MAX_BW_SHIFT 24
+ #define FUNC_MF_CFG_MAX_BW_DEFAULT 0x64000000
- u32 mac_upper; /* MAC */
-#define FUNC_MF_CFG_UPPERMAC_MASK 0x0000ffff
-#define FUNC_MF_CFG_UPPERMAC_SHIFT 0
-#define FUNC_MF_CFG_UPPERMAC_DEFAULT FUNC_MF_CFG_UPPERMAC_MASK
+ u32 mac_upper; /* MAC */
+ #define FUNC_MF_CFG_UPPERMAC_MASK 0x0000ffff
+ #define FUNC_MF_CFG_UPPERMAC_SHIFT 0
+ #define FUNC_MF_CFG_UPPERMAC_DEFAULT FUNC_MF_CFG_UPPERMAC_MASK
u32 mac_lower;
-#define FUNC_MF_CFG_LOWERMAC_DEFAULT 0xffffffff
+ #define FUNC_MF_CFG_LOWERMAC_DEFAULT 0xffffffff
u32 e1hov_tag; /* VNI */
-#define FUNC_MF_CFG_E1HOV_TAG_MASK 0x0000ffff
-#define FUNC_MF_CFG_E1HOV_TAG_SHIFT 0
-#define FUNC_MF_CFG_E1HOV_TAG_DEFAULT FUNC_MF_CFG_E1HOV_TAG_MASK
+ #define FUNC_MF_CFG_E1HOV_TAG_MASK 0x0000ffff
+ #define FUNC_MF_CFG_E1HOV_TAG_SHIFT 0
+ #define FUNC_MF_CFG_E1HOV_TAG_DEFAULT FUNC_MF_CFG_E1HOV_TAG_MASK
u32 reserved[2];
-
};
/* This structure is not applicable and should not be accessed on 57711 */
struct func_ext_cfg {
u32 func_cfg;
-#define MACP_FUNC_CFG_FLAGS_MASK 0x000000FF
-#define MACP_FUNC_CFG_FLAGS_SHIFT 0
-#define MACP_FUNC_CFG_FLAGS_ENABLED 0x00000001
-#define MACP_FUNC_CFG_FLAGS_ETHERNET 0x00000002
-#define MACP_FUNC_CFG_FLAGS_ISCSI_OFFLOAD 0x00000004
-#define MACP_FUNC_CFG_FLAGS_FCOE_OFFLOAD 0x00000008
+ #define MACP_FUNC_CFG_FLAGS_MASK 0x000000FF
+ #define MACP_FUNC_CFG_FLAGS_SHIFT 0
+ #define MACP_FUNC_CFG_FLAGS_ENABLED 0x00000001
+ #define MACP_FUNC_CFG_FLAGS_ETHERNET 0x00000002
+ #define MACP_FUNC_CFG_FLAGS_ISCSI_OFFLOAD 0x00000004
+ #define MACP_FUNC_CFG_FLAGS_FCOE_OFFLOAD 0x00000008
u32 iscsi_mac_addr_upper;
u32 iscsi_mac_addr_lower;
@@ -1120,73 +1472,99 @@
u32 fcoe_wwn_node_name_lower;
u32 preserve_data;
-#define MF_FUNC_CFG_PRESERVE_L2_MAC (1<<0)
-#define MF_FUNC_CFG_PRESERVE_ISCSI_MAC (1<<1)
-#define MF_FUNC_CFG_PRESERVE_FCOE_MAC (1<<2)
-#define MF_FUNC_CFG_PRESERVE_FCOE_WWN_P (1<<3)
-#define MF_FUNC_CFG_PRESERVE_FCOE_WWN_N (1<<4)
+ #define MF_FUNC_CFG_PRESERVE_L2_MAC (1<<0)
+ #define MF_FUNC_CFG_PRESERVE_ISCSI_MAC (1<<1)
+ #define MF_FUNC_CFG_PRESERVE_FCOE_MAC (1<<2)
+ #define MF_FUNC_CFG_PRESERVE_FCOE_WWN_P (1<<3)
+ #define MF_FUNC_CFG_PRESERVE_FCOE_WWN_N (1<<4)
+ #define MF_FUNC_CFG_PRESERVE_TX_BW (1<<5)
};
struct mf_cfg {
- struct shared_mf_cfg shared_mf_config;
- struct port_mf_cfg port_mf_config[PORT_MAX];
- struct func_mf_cfg func_mf_config[E1H_FUNC_MAX];
-
- struct func_ext_cfg func_ext_config[E1H_FUNC_MAX];
-};
-
+ struct shared_mf_cfg shared_mf_config; /* 0x4 */
+ struct port_mf_cfg port_mf_config[PORT_MAX]; /* 0x10 * 2 = 0x20 */
+ /* for all chips, there are 8 mf functions */
+ struct func_mf_cfg func_mf_config[E1H_FUNC_MAX]; /* 0x18 * 8 = 0xc0 */
+ /*
+ * Extended configuration per function - this array does not exist and
+ * should not be accessed on 57711
+ */
+ struct func_ext_cfg func_ext_config[E1H_FUNC_MAX]; /* 0x28 * 8 = 0x140*/
+}; /* 0x224 */
/****************************************************************************
- * Shared Memory Region *
+ * Shared Memory Region *
****************************************************************************/
-struct shmem_region { /* SharedMem Offset (size) */
+struct shmem_region { /* SharedMem Offset (size) */
- u32 validity_map[PORT_MAX]; /* 0x0 (4*2 = 0x8) */
-#define SHR_MEM_FORMAT_REV_ID ('A'<<24)
-#define SHR_MEM_FORMAT_REV_MASK 0xff000000
+ u32 validity_map[PORT_MAX]; /* 0x0 (4*2 = 0x8) */
+ #define SHR_MEM_FORMAT_REV_MASK 0xff000000
+ #define SHR_MEM_FORMAT_REV_ID ('A'<<24)
/* validity bits */
-#define SHR_MEM_VALIDITY_PCI_CFG 0x00100000
-#define SHR_MEM_VALIDITY_MB 0x00200000
-#define SHR_MEM_VALIDITY_DEV_INFO 0x00400000
-#define SHR_MEM_VALIDITY_RESERVED 0x00000007
+ #define SHR_MEM_VALIDITY_PCI_CFG 0x00100000
+ #define SHR_MEM_VALIDITY_MB 0x00200000
+ #define SHR_MEM_VALIDITY_DEV_INFO 0x00400000
+ #define SHR_MEM_VALIDITY_RESERVED 0x00000007
/* One licensing bit should be set */
-#define SHR_MEM_VALIDITY_LIC_KEY_IN_EFFECT_MASK 0x00000038
-#define SHR_MEM_VALIDITY_LIC_MANUF_KEY_IN_EFFECT 0x00000008
-#define SHR_MEM_VALIDITY_LIC_UPGRADE_KEY_IN_EFFECT 0x00000010
-#define SHR_MEM_VALIDITY_LIC_NO_KEY_IN_EFFECT 0x00000020
+ #define SHR_MEM_VALIDITY_LIC_KEY_IN_EFFECT_MASK 0x00000038
+ #define SHR_MEM_VALIDITY_LIC_MANUF_KEY_IN_EFFECT 0x00000008
+ #define SHR_MEM_VALIDITY_LIC_UPGRADE_KEY_IN_EFFECT 0x00000010
+ #define SHR_MEM_VALIDITY_LIC_NO_KEY_IN_EFFECT 0x00000020
/* Active MFW */
-#define SHR_MEM_VALIDITY_ACTIVE_MFW_UNKNOWN 0x00000000
-#define SHR_MEM_VALIDITY_ACTIVE_MFW_IPMI 0x00000040
-#define SHR_MEM_VALIDITY_ACTIVE_MFW_UMP 0x00000080
-#define SHR_MEM_VALIDITY_ACTIVE_MFW_NCSI 0x000000c0
-#define SHR_MEM_VALIDITY_ACTIVE_MFW_NONE 0x000001c0
-#define SHR_MEM_VALIDITY_ACTIVE_MFW_MASK 0x000001c0
+ #define SHR_MEM_VALIDITY_ACTIVE_MFW_UNKNOWN 0x00000000
+ #define SHR_MEM_VALIDITY_ACTIVE_MFW_MASK 0x000001c0
+ #define SHR_MEM_VALIDITY_ACTIVE_MFW_IPMI 0x00000040
+ #define SHR_MEM_VALIDITY_ACTIVE_MFW_UMP 0x00000080
+ #define SHR_MEM_VALIDITY_ACTIVE_MFW_NCSI 0x000000c0
+ #define SHR_MEM_VALIDITY_ACTIVE_MFW_NONE 0x000001c0
- struct shm_dev_info dev_info; /* 0x8 (0x438) */
+ struct shm_dev_info dev_info; /* 0x8 (0x438) */
- struct license_key drv_lic_key[PORT_MAX]; /* 0x440 (52*2=0x68) */
+ struct license_key drv_lic_key[PORT_MAX]; /* 0x440 (52*2=0x68) */
/* FW information (for internal FW use) */
- u32 fw_info_fio_offset; /* 0x4a8 (0x4) */
- struct mgmtfw_state mgmtfw_state; /* 0x4ac (0x1b8) */
+ u32 fw_info_fio_offset; /* 0x4a8 (0x4) */
+ struct mgmtfw_state mgmtfw_state; /* 0x4ac (0x1b8) */
- struct drv_port_mb port_mb[PORT_MAX]; /* 0x664 (16*2=0x20) */
- struct drv_func_mb func_mb[]; /* 0x684
- (44*2/4/8=0x58/0xb0/0x160) */
+ struct drv_port_mb port_mb[PORT_MAX]; /* 0x664 (16*2=0x20) */
+
+#ifdef BMAPI
+ /* This is a variable length array */
+ /* the number of function depends on the chip type */
+ struct drv_func_mb func_mb[1]; /* 0x684 (44*2/4/8=0x58/0xb0/0x160) */
+#else
+ /* the number of function depends on the chip type */
+ struct drv_func_mb func_mb[]; /* 0x684 (44*2/4/8=0x58/0xb0/0x160) */
+#endif /* BMAPI */
}; /* 57710 = 0x6dc | 57711 = 0x7E4 | 57712 = 0x734 */
+/****************************************************************************
+ * Shared Memory 2 Region *
+ ****************************************************************************/
+/* The fw_flr_ack is actually built in the following way: */
+/* 8 bit: PF ack */
+/* 64 bit: VF ack */
+/* 8 bit: ios_dis_ack */
+/* In order to maintain endianity in the mailbox hsi, we want to keep using */
+/* u32. The fw must have the VF right after the PF since this is how it */
+/* access arrays(it expects always the VF to reside after the PF, and that */
+/* makes the calculation much easier for it. ) */
+/* In order to answer both limitations, and keep the struct small, the code */
+/* will abuse the structure defined here to achieve the actual partition */
+/* above */
+/****************************************************************************/
struct fw_flr_ack {
- u32 pf_ack;
- u32 vf_ack[1];
- u32 iov_dis_ack;
+ u32 pf_ack;
+ u32 vf_ack[1];
+ u32 iov_dis_ack;
};
struct fw_flr_mb {
- u32 aggint;
- u32 opgen_addr;
- struct fw_flr_ack ack;
+ u32 aggint;
+ u32 opgen_addr;
+ struct fw_flr_ack ack;
};
/**** SUPPORT FOR SHMEM ARRRAYS ***
@@ -1210,36 +1588,36 @@
*
* SHMEM_ARRAY_BITPOS(i, 4, 4) defines the stadard ordering:
*
- * | | | |
- * 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
- * | | | |
+ * | | | |
+ * 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
+ * | | | |
*
* SHMEM_ARRAY_BITPOS(i, 4, 8) defines a flip ordering per byte:
*
- * | | | |
- * 1 | 0 | 3 | 2 | 5 | 4 | 7 | 6 |
- * | | | |
+ * | | | |
+ * 1 | 0 | 3 | 2 | 5 | 4 | 7 | 6 |
+ * | | | |
*
* SHMEM_ARRAY_BITPOS(i, 4, 16) defines a flip ordering per word:
*
- * | | | |
- * 3 | 2 | 1 | 0 | 7 | 6 | 5 | 4 |
- * | | | |
+ * | | | |
+ * 3 | 2 | 1 | 0 | 7 | 6 | 5 | 4 |
+ * | | | |
*/
#define SHMEM_ARRAY_BITPOS(i, eb, fb) \
((((32/(fb)) - 1 - ((i)/((fb)/(eb))) % (32/(fb))) * (fb)) + \
(((i)%((fb)/(eb))) * (eb)))
-#define SHMEM_ARRAY_GET(a, i, eb, fb) \
+#define SHMEM_ARRAY_GET(a, i, eb, fb) \
((a[SHMEM_ARRAY_ENTRY(i, eb)] >> SHMEM_ARRAY_BITPOS(i, eb, fb)) & \
SHMEM_ARRAY_MASK(eb))
-#define SHMEM_ARRAY_SET(a, i, eb, fb, val) \
+#define SHMEM_ARRAY_SET(a, i, eb, fb, val) \
do { \
a[SHMEM_ARRAY_ENTRY(i, eb)] &= ~(SHMEM_ARRAY_MASK(eb) << \
- SHMEM_ARRAY_BITPOS(i, eb, fb)); \
+ SHMEM_ARRAY_BITPOS(i, eb, fb)); \
a[SHMEM_ARRAY_ENTRY(i, eb)] |= (((val) & SHMEM_ARRAY_MASK(eb)) << \
- SHMEM_ARRAY_BITPOS(i, eb, fb)); \
+ SHMEM_ARRAY_BITPOS(i, eb, fb)); \
} while (0)
@@ -1263,23 +1641,30 @@
#define ISCSI_APP_IDX 1
#define PREDEFINED_APP_IDX_MAX 2
+
+/* Big/Little endian have the same representation. */
struct dcbx_ets_feature {
+ /*
+ * For Admin MIB - is this feature supported by the
+ * driver | For Local MIB - should this feature be enabled.
+ */
u32 enabled;
u32 pg_bw_tbl[2];
u32 pri_pg_tbl[1];
};
+/* Driver structure in LE */
struct dcbx_pfc_feature {
#ifdef __BIG_ENDIAN
u8 pri_en_bitmap;
-#define DCBX_PFC_PRI_0 0x01
-#define DCBX_PFC_PRI_1 0x02
-#define DCBX_PFC_PRI_2 0x04
-#define DCBX_PFC_PRI_3 0x08
-#define DCBX_PFC_PRI_4 0x10
-#define DCBX_PFC_PRI_5 0x20
-#define DCBX_PFC_PRI_6 0x40
-#define DCBX_PFC_PRI_7 0x80
+ #define DCBX_PFC_PRI_0 0x01
+ #define DCBX_PFC_PRI_1 0x02
+ #define DCBX_PFC_PRI_2 0x04
+ #define DCBX_PFC_PRI_3 0x08
+ #define DCBX_PFC_PRI_4 0x10
+ #define DCBX_PFC_PRI_5 0x20
+ #define DCBX_PFC_PRI_6 0x40
+ #define DCBX_PFC_PRI_7 0x80
u8 pfc_caps;
u8 reserved;
u8 enabled;
@@ -1288,39 +1673,41 @@
u8 reserved;
u8 pfc_caps;
u8 pri_en_bitmap;
-#define DCBX_PFC_PRI_0 0x01
-#define DCBX_PFC_PRI_1 0x02
-#define DCBX_PFC_PRI_2 0x04
-#define DCBX_PFC_PRI_3 0x08
-#define DCBX_PFC_PRI_4 0x10
-#define DCBX_PFC_PRI_5 0x20
-#define DCBX_PFC_PRI_6 0x40
-#define DCBX_PFC_PRI_7 0x80
+ #define DCBX_PFC_PRI_0 0x01
+ #define DCBX_PFC_PRI_1 0x02
+ #define DCBX_PFC_PRI_2 0x04
+ #define DCBX_PFC_PRI_3 0x08
+ #define DCBX_PFC_PRI_4 0x10
+ #define DCBX_PFC_PRI_5 0x20
+ #define DCBX_PFC_PRI_6 0x40
+ #define DCBX_PFC_PRI_7 0x80
#endif
};
struct dcbx_app_priority_entry {
#ifdef __BIG_ENDIAN
- u16 app_id;
- u8 pri_bitmap;
- u8 appBitfield;
-#define DCBX_APP_ENTRY_VALID 0x01
-#define DCBX_APP_ENTRY_SF_MASK 0x30
-#define DCBX_APP_ENTRY_SF_SHIFT 4
-#define DCBX_APP_SF_ETH_TYPE 0x10
-#define DCBX_APP_SF_PORT 0x20
+ u16 app_id;
+ u8 pri_bitmap;
+ u8 appBitfield;
+ #define DCBX_APP_ENTRY_VALID 0x01
+ #define DCBX_APP_ENTRY_SF_MASK 0x30
+ #define DCBX_APP_ENTRY_SF_SHIFT 4
+ #define DCBX_APP_SF_ETH_TYPE 0x10
+ #define DCBX_APP_SF_PORT 0x20
#elif defined(__LITTLE_ENDIAN)
u8 appBitfield;
-#define DCBX_APP_ENTRY_VALID 0x01
-#define DCBX_APP_ENTRY_SF_MASK 0x30
-#define DCBX_APP_ENTRY_SF_SHIFT 4
-#define DCBX_APP_SF_ETH_TYPE 0x10
-#define DCBX_APP_SF_PORT 0x20
- u8 pri_bitmap;
- u16 app_id;
+ #define DCBX_APP_ENTRY_VALID 0x01
+ #define DCBX_APP_ENTRY_SF_MASK 0x30
+ #define DCBX_APP_ENTRY_SF_SHIFT 4
+ #define DCBX_APP_SF_ETH_TYPE 0x10
+ #define DCBX_APP_SF_PORT 0x20
+ u8 pri_bitmap;
+ u16 app_id;
#endif
};
+
+/* FW structure in BE */
struct dcbx_app_priority_feature {
#ifdef __BIG_ENDIAN
u8 reserved;
@@ -1336,302 +1723,402 @@
struct dcbx_app_priority_entry app_pri_tbl[DCBX_MAX_APP_PROTOCOL];
};
+/* FW structure in BE */
struct dcbx_features {
+ /* PG feature */
struct dcbx_ets_feature ets;
+ /* PFC feature */
struct dcbx_pfc_feature pfc;
+ /* APP feature */
struct dcbx_app_priority_feature app;
};
+/* LLDP protocol parameters */
+/* FW structure in BE */
struct lldp_params {
#ifdef __BIG_ENDIAN
- u8 msg_fast_tx_interval;
- u8 msg_tx_hold;
- u8 msg_tx_interval;
- u8 admin_status;
-#define LLDP_TX_ONLY 0x01
-#define LLDP_RX_ONLY 0x02
-#define LLDP_TX_RX 0x03
-#define LLDP_DISABLED 0x04
- u8 reserved1;
- u8 tx_fast;
- u8 tx_crd_max;
- u8 tx_crd;
+ u8 msg_fast_tx_interval;
+ u8 msg_tx_hold;
+ u8 msg_tx_interval;
+ u8 admin_status;
+ #define LLDP_TX_ONLY 0x01
+ #define LLDP_RX_ONLY 0x02
+ #define LLDP_TX_RX 0x03
+ #define LLDP_DISABLED 0x04
+ u8 reserved1;
+ u8 tx_fast;
+ u8 tx_crd_max;
+ u8 tx_crd;
#elif defined(__LITTLE_ENDIAN)
- u8 admin_status;
-#define LLDP_TX_ONLY 0x01
-#define LLDP_RX_ONLY 0x02
-#define LLDP_TX_RX 0x03
-#define LLDP_DISABLED 0x04
- u8 msg_tx_interval;
- u8 msg_tx_hold;
- u8 msg_fast_tx_interval;
- u8 tx_crd;
- u8 tx_crd_max;
- u8 tx_fast;
- u8 reserved1;
+ u8 admin_status;
+ #define LLDP_TX_ONLY 0x01
+ #define LLDP_RX_ONLY 0x02
+ #define LLDP_TX_RX 0x03
+ #define LLDP_DISABLED 0x04
+ u8 msg_tx_interval;
+ u8 msg_tx_hold;
+ u8 msg_fast_tx_interval;
+ u8 tx_crd;
+ u8 tx_crd_max;
+ u8 tx_fast;
+ u8 reserved1;
#endif
-#define REM_CHASSIS_ID_STAT_LEN 4
-#define REM_PORT_ID_STAT_LEN 4
+ #define REM_CHASSIS_ID_STAT_LEN 4
+ #define REM_PORT_ID_STAT_LEN 4
+ /* Holds remote Chassis ID TLV header, subtype and 9B of payload. */
u32 peer_chassis_id[REM_CHASSIS_ID_STAT_LEN];
+ /* Holds remote Port ID TLV header, subtype and 9B of payload. */
u32 peer_port_id[REM_PORT_ID_STAT_LEN];
};
struct lldp_dcbx_stat {
-#define LOCAL_CHASSIS_ID_STAT_LEN 2
-#define LOCAL_PORT_ID_STAT_LEN 2
+ #define LOCAL_CHASSIS_ID_STAT_LEN 2
+ #define LOCAL_PORT_ID_STAT_LEN 2
+ /* Holds local Chassis ID 8B payload of constant subtype 4. */
u32 local_chassis_id[LOCAL_CHASSIS_ID_STAT_LEN];
+ /* Holds local Port ID 8B payload of constant subtype 3. */
u32 local_port_id[LOCAL_PORT_ID_STAT_LEN];
+ /* Number of DCBX frames transmitted. */
u32 num_tx_dcbx_pkts;
+ /* Number of DCBX frames received. */
u32 num_rx_dcbx_pkts;
};
+/* ADMIN MIB - DCBX local machine default configuration. */
struct lldp_admin_mib {
- u32 ver_cfg_flags;
-#define DCBX_ETS_CONFIG_TX_ENABLED 0x00000001
-#define DCBX_PFC_CONFIG_TX_ENABLED 0x00000002
-#define DCBX_APP_CONFIG_TX_ENABLED 0x00000004
-#define DCBX_ETS_RECO_TX_ENABLED 0x00000008
-#define DCBX_ETS_RECO_VALID 0x00000010
-#define DCBX_ETS_WILLING 0x00000020
-#define DCBX_PFC_WILLING 0x00000040
-#define DCBX_APP_WILLING 0x00000080
-#define DCBX_VERSION_CEE 0x00000100
-#define DCBX_VERSION_IEEE 0x00000200
-#define DCBX_DCBX_ENABLED 0x00000400
-#define DCBX_CEE_VERSION_MASK 0x0000f000
-#define DCBX_CEE_VERSION_SHIFT 12
-#define DCBX_CEE_MAX_VERSION_MASK 0x000f0000
-#define DCBX_CEE_MAX_VERSION_SHIFT 16
- struct dcbx_features features;
+ u32 ver_cfg_flags;
+ #define DCBX_ETS_CONFIG_TX_ENABLED 0x00000001
+ #define DCBX_PFC_CONFIG_TX_ENABLED 0x00000002
+ #define DCBX_APP_CONFIG_TX_ENABLED 0x00000004
+ #define DCBX_ETS_RECO_TX_ENABLED 0x00000008
+ #define DCBX_ETS_RECO_VALID 0x00000010
+ #define DCBX_ETS_WILLING 0x00000020
+ #define DCBX_PFC_WILLING 0x00000040
+ #define DCBX_APP_WILLING 0x00000080
+ #define DCBX_VERSION_CEE 0x00000100
+ #define DCBX_VERSION_IEEE 0x00000200
+ #define DCBX_DCBX_ENABLED 0x00000400
+ #define DCBX_CEE_VERSION_MASK 0x0000f000
+ #define DCBX_CEE_VERSION_SHIFT 12
+ #define DCBX_CEE_MAX_VERSION_MASK 0x000f0000
+ #define DCBX_CEE_MAX_VERSION_SHIFT 16
+ struct dcbx_features features;
};
+/* REMOTE MIB - remote machine DCBX configuration. */
struct lldp_remote_mib {
u32 prefix_seq_num;
u32 flags;
-#define DCBX_ETS_TLV_RX 0x00000001
-#define DCBX_PFC_TLV_RX 0x00000002
-#define DCBX_APP_TLV_RX 0x00000004
-#define DCBX_ETS_RX_ERROR 0x00000010
-#define DCBX_PFC_RX_ERROR 0x00000020
-#define DCBX_APP_RX_ERROR 0x00000040
-#define DCBX_ETS_REM_WILLING 0x00000100
-#define DCBX_PFC_REM_WILLING 0x00000200
-#define DCBX_APP_REM_WILLING 0x00000400
-#define DCBX_REMOTE_ETS_RECO_VALID 0x00001000
+ #define DCBX_ETS_TLV_RX 0x00000001
+ #define DCBX_PFC_TLV_RX 0x00000002
+ #define DCBX_APP_TLV_RX 0x00000004
+ #define DCBX_ETS_RX_ERROR 0x00000010
+ #define DCBX_PFC_RX_ERROR 0x00000020
+ #define DCBX_APP_RX_ERROR 0x00000040
+ #define DCBX_ETS_REM_WILLING 0x00000100
+ #define DCBX_PFC_REM_WILLING 0x00000200
+ #define DCBX_APP_REM_WILLING 0x00000400
+ #define DCBX_REMOTE_ETS_RECO_VALID 0x00001000
+ #define DCBX_REMOTE_MIB_VALID 0x00002000
struct dcbx_features features;
u32 suffix_seq_num;
};
+/* LOCAL MIB - operational DCBX configuration - transmitted on Tx LLDPDU. */
struct lldp_local_mib {
u32 prefix_seq_num;
+ /* Indicates if there is mismatch with negotiation results. */
u32 error;
-#define DCBX_LOCAL_ETS_ERROR 0x00000001
-#define DCBX_LOCAL_PFC_ERROR 0x00000002
-#define DCBX_LOCAL_APP_ERROR 0x00000004
-#define DCBX_LOCAL_PFC_MISMATCH 0x00000010
-#define DCBX_LOCAL_APP_MISMATCH 0x00000020
+ #define DCBX_LOCAL_ETS_ERROR 0x00000001
+ #define DCBX_LOCAL_PFC_ERROR 0x00000002
+ #define DCBX_LOCAL_APP_ERROR 0x00000004
+ #define DCBX_LOCAL_PFC_MISMATCH 0x00000010
+ #define DCBX_LOCAL_APP_MISMATCH 0x00000020
struct dcbx_features features;
u32 suffix_seq_num;
};
/***END OF DCBX STRUCTURES DECLARATIONS***/
+struct ncsi_oem_fcoe_features {
+ u32 fcoe_features1;
+ #define FCOE_FEATURES1_IOS_PER_CONNECTION_MASK 0x0000FFFF
+ #define FCOE_FEATURES1_IOS_PER_CONNECTION_OFFSET 0
+
+ #define FCOE_FEATURES1_LOGINS_PER_PORT_MASK 0xFFFF0000
+ #define FCOE_FEATURES1_LOGINS_PER_PORT_OFFSET 16
+
+ u32 fcoe_features2;
+ #define FCOE_FEATURES2_EXCHANGES_MASK 0x0000FFFF
+ #define FCOE_FEATURES2_EXCHANGES_OFFSET 0
+
+ #define FCOE_FEATURES2_NPIV_WWN_PER_PORT_MASK 0xFFFF0000
+ #define FCOE_FEATURES2_NPIV_WWN_PER_PORT_OFFSET 16
+
+ u32 fcoe_features3;
+ #define FCOE_FEATURES3_TARGETS_SUPPORTED_MASK 0x0000FFFF
+ #define FCOE_FEATURES3_TARGETS_SUPPORTED_OFFSET 0
+
+ #define FCOE_FEATURES3_OUTSTANDING_COMMANDS_MASK 0xFFFF0000
+ #define FCOE_FEATURES3_OUTSTANDING_COMMANDS_OFFSET 16
+
+ u32 fcoe_features4;
+ #define FCOE_FEATURES4_FEATURE_SETTINGS_MASK 0x0000000F
+ #define FCOE_FEATURES4_FEATURE_SETTINGS_OFFSET 0
+};
+
+struct ncsi_oem_data {
+ u32 driver_version[4];
+ struct ncsi_oem_fcoe_features ncsi_oem_fcoe_features;
+};
+
struct shmem2_region {
- u32 size;
+ u32 size; /* 0x0000 */
- u32 dcc_support;
-#define SHMEM_DCC_SUPPORT_NONE 0x00000000
-#define SHMEM_DCC_SUPPORT_DISABLE_ENABLE_PF_TLV 0x00000001
-#define SHMEM_DCC_SUPPORT_BANDWIDTH_ALLOCATION_TLV 0x00000004
-#define SHMEM_DCC_SUPPORT_CHANGE_MAC_ADDRESS_TLV 0x00000008
-#define SHMEM_DCC_SUPPORT_SET_PROTOCOL_TLV 0x00000040
-#define SHMEM_DCC_SUPPORT_SET_PRIORITY_TLV 0x00000080
-#define SHMEM_DCC_SUPPORT_DEFAULT SHMEM_DCC_SUPPORT_NONE
- u32 ext_phy_fw_version2[PORT_MAX];
+ u32 dcc_support; /* 0x0004 */
+ #define SHMEM_DCC_SUPPORT_NONE 0x00000000
+ #define SHMEM_DCC_SUPPORT_DISABLE_ENABLE_PF_TLV 0x00000001
+ #define SHMEM_DCC_SUPPORT_BANDWIDTH_ALLOCATION_TLV 0x00000004
+ #define SHMEM_DCC_SUPPORT_CHANGE_MAC_ADDRESS_TLV 0x00000008
+ #define SHMEM_DCC_SUPPORT_SET_PROTOCOL_TLV 0x00000040
+ #define SHMEM_DCC_SUPPORT_SET_PRIORITY_TLV 0x00000080
+
+ u32 ext_phy_fw_version2[PORT_MAX]; /* 0x0008 */
/*
* For backwards compatibility, if the mf_cfg_addr does not exist
* (the size filed is smaller than 0xc) the mf_cfg resides at the
* end of struct shmem_region
- */
- u32 mf_cfg_addr;
-#define SHMEM_MF_CFG_ADDR_NONE 0x00000000
+ */
+ u32 mf_cfg_addr; /* 0x0010 */
+ #define SHMEM_MF_CFG_ADDR_NONE 0x00000000
- struct fw_flr_mb flr_mb;
- u32 dcbx_lldp_params_offset;
-#define SHMEM_LLDP_DCBX_PARAMS_NONE 0x00000000
- u32 dcbx_neg_res_offset;
-#define SHMEM_DCBX_NEG_RES_NONE 0x00000000
- u32 dcbx_remote_mib_offset;
-#define SHMEM_DCBX_REMOTE_MIB_NONE 0x00000000
+ struct fw_flr_mb flr_mb; /* 0x0014 */
+ u32 dcbx_lldp_params_offset; /* 0x0028 */
+ #define SHMEM_LLDP_DCBX_PARAMS_NONE 0x00000000
+ u32 dcbx_neg_res_offset; /* 0x002c */
+ #define SHMEM_DCBX_NEG_RES_NONE 0x00000000
+ u32 dcbx_remote_mib_offset; /* 0x0030 */
+ #define SHMEM_DCBX_REMOTE_MIB_NONE 0x00000000
/*
* The other shmemX_base_addr holds the other path's shmem address
* required for example in case of common phy init, or for path1 to know
* the address of mcp debug trace which is located in offset from shmem
* of path0
*/
- u32 other_shmem_base_addr;
- u32 other_shmem2_base_addr;
- u32 reserved1[E2_VF_MAX / 32];
- u32 reserved2[E2_FUNC_MAX][E2_VF_MAX / 32];
- u32 dcbx_lldp_dcbx_stat_offset;
-#define SHMEM_LLDP_DCBX_STAT_NONE 0x00000000
+ u32 other_shmem_base_addr; /* 0x0034 */
+ u32 other_shmem2_base_addr; /* 0x0038 */
+ /*
+ * mcp_vf_disabled is set by the MCP to indicate the driver about VFs
+ * which were disabled/flred
+ */
+ u32 mcp_vf_disabled[E2_VF_MAX / 32]; /* 0x003c */
+
+ /*
+ * drv_ack_vf_disabled is set by the PF driver to ack handled disabled
+ * VFs
+ */
+ u32 drv_ack_vf_disabled[E2_FUNC_MAX][E2_VF_MAX / 32]; /* 0x0044 */
+
+ u32 dcbx_lldp_dcbx_stat_offset; /* 0x0064 */
+ #define SHMEM_LLDP_DCBX_STAT_NONE 0x00000000
+
+ /*
+ * edebug_driver_if field is used to transfer messages between edebug
+ * app to the driver through shmem2.
+ *
+ * message format:
+ * bits 0-2 - function number / instance of driver to perform request
+ * bits 3-5 - op code / is_ack?
+ * bits 6-63 - data
+ */
+ u32 edebug_driver_if[2]; /* 0x0068 */
+ #define EDEBUG_DRIVER_IF_OP_CODE_GET_PHYS_ADDR 1
+ #define EDEBUG_DRIVER_IF_OP_CODE_GET_BUS_ADDR 2
+ #define EDEBUG_DRIVER_IF_OP_CODE_DISABLE_STAT 3
+
+ u32 nvm_retain_bitmap_addr; /* 0x0070 */
+
+ u32 reserved1; /* 0x0074 */
+
+ u32 reserved2[E2_FUNC_MAX];
+
+ u32 reserved3[E2_FUNC_MAX];/* 0x0088 */
+ u32 reserved4[E2_FUNC_MAX];/* 0x0098 */
+
+ u32 swim_base_addr; /* 0x0108 */
+ u32 swim_funcs;
+ u32 swim_main_cb;
+
+ u32 reserved5[2];
+
+ /* generic flags controlled by the driver */
+ u32 drv_flags;
+ #define DRV_FLAGS_DCB_CONFIGURED 0x1
+
+ /* pointer to extended dev_info shared data copied from nvm image */
+ u32 extended_dev_info_shared_addr;
+ u32 ncsi_oem_data_addr;
+
+ u32 ocsd_host_addr;
+ u32 ocbb_host_addr;
+ u32 ocsd_req_update_interval;
};
struct emac_stats {
- u32 rx_stat_ifhcinoctets;
- u32 rx_stat_ifhcinbadoctets;
- u32 rx_stat_etherstatsfragments;
- u32 rx_stat_ifhcinucastpkts;
- u32 rx_stat_ifhcinmulticastpkts;
- u32 rx_stat_ifhcinbroadcastpkts;
- u32 rx_stat_dot3statsfcserrors;
- u32 rx_stat_dot3statsalignmenterrors;
- u32 rx_stat_dot3statscarriersenseerrors;
- u32 rx_stat_xonpauseframesreceived;
- u32 rx_stat_xoffpauseframesreceived;
- u32 rx_stat_maccontrolframesreceived;
- u32 rx_stat_xoffstateentered;
- u32 rx_stat_dot3statsframestoolong;
- u32 rx_stat_etherstatsjabbers;
- u32 rx_stat_etherstatsundersizepkts;
- u32 rx_stat_etherstatspkts64octets;
- u32 rx_stat_etherstatspkts65octetsto127octets;
- u32 rx_stat_etherstatspkts128octetsto255octets;
- u32 rx_stat_etherstatspkts256octetsto511octets;
- u32 rx_stat_etherstatspkts512octetsto1023octets;
- u32 rx_stat_etherstatspkts1024octetsto1522octets;
- u32 rx_stat_etherstatspktsover1522octets;
+ u32 rx_stat_ifhcinoctets;
+ u32 rx_stat_ifhcinbadoctets;
+ u32 rx_stat_etherstatsfragments;
+ u32 rx_stat_ifhcinucastpkts;
+ u32 rx_stat_ifhcinmulticastpkts;
+ u32 rx_stat_ifhcinbroadcastpkts;
+ u32 rx_stat_dot3statsfcserrors;
+ u32 rx_stat_dot3statsalignmenterrors;
+ u32 rx_stat_dot3statscarriersenseerrors;
+ u32 rx_stat_xonpauseframesreceived;
+ u32 rx_stat_xoffpauseframesreceived;
+ u32 rx_stat_maccontrolframesreceived;
+ u32 rx_stat_xoffstateentered;
+ u32 rx_stat_dot3statsframestoolong;
+ u32 rx_stat_etherstatsjabbers;
+ u32 rx_stat_etherstatsundersizepkts;
+ u32 rx_stat_etherstatspkts64octets;
+ u32 rx_stat_etherstatspkts65octetsto127octets;
+ u32 rx_stat_etherstatspkts128octetsto255octets;
+ u32 rx_stat_etherstatspkts256octetsto511octets;
+ u32 rx_stat_etherstatspkts512octetsto1023octets;
+ u32 rx_stat_etherstatspkts1024octetsto1522octets;
+ u32 rx_stat_etherstatspktsover1522octets;
- u32 rx_stat_falsecarriererrors;
+ u32 rx_stat_falsecarriererrors;
- u32 tx_stat_ifhcoutoctets;
- u32 tx_stat_ifhcoutbadoctets;
- u32 tx_stat_etherstatscollisions;
- u32 tx_stat_outxonsent;
- u32 tx_stat_outxoffsent;
- u32 tx_stat_flowcontroldone;
- u32 tx_stat_dot3statssinglecollisionframes;
- u32 tx_stat_dot3statsmultiplecollisionframes;
- u32 tx_stat_dot3statsdeferredtransmissions;
- u32 tx_stat_dot3statsexcessivecollisions;
- u32 tx_stat_dot3statslatecollisions;
- u32 tx_stat_ifhcoutucastpkts;
- u32 tx_stat_ifhcoutmulticastpkts;
- u32 tx_stat_ifhcoutbroadcastpkts;
- u32 tx_stat_etherstatspkts64octets;
- u32 tx_stat_etherstatspkts65octetsto127octets;
- u32 tx_stat_etherstatspkts128octetsto255octets;
- u32 tx_stat_etherstatspkts256octetsto511octets;
- u32 tx_stat_etherstatspkts512octetsto1023octets;
- u32 tx_stat_etherstatspkts1024octetsto1522octets;
- u32 tx_stat_etherstatspktsover1522octets;
- u32 tx_stat_dot3statsinternalmactransmiterrors;
+ u32 tx_stat_ifhcoutoctets;
+ u32 tx_stat_ifhcoutbadoctets;
+ u32 tx_stat_etherstatscollisions;
+ u32 tx_stat_outxonsent;
+ u32 tx_stat_outxoffsent;
+ u32 tx_stat_flowcontroldone;
+ u32 tx_stat_dot3statssinglecollisionframes;
+ u32 tx_stat_dot3statsmultiplecollisionframes;
+ u32 tx_stat_dot3statsdeferredtransmissions;
+ u32 tx_stat_dot3statsexcessivecollisions;
+ u32 tx_stat_dot3statslatecollisions;
+ u32 tx_stat_ifhcoutucastpkts;
+ u32 tx_stat_ifhcoutmulticastpkts;
+ u32 tx_stat_ifhcoutbroadcastpkts;
+ u32 tx_stat_etherstatspkts64octets;
+ u32 tx_stat_etherstatspkts65octetsto127octets;
+ u32 tx_stat_etherstatspkts128octetsto255octets;
+ u32 tx_stat_etherstatspkts256octetsto511octets;
+ u32 tx_stat_etherstatspkts512octetsto1023octets;
+ u32 tx_stat_etherstatspkts1024octetsto1522octets;
+ u32 tx_stat_etherstatspktsover1522octets;
+ u32 tx_stat_dot3statsinternalmactransmiterrors;
};
struct bmac1_stats {
- u32 tx_stat_gtpkt_lo;
- u32 tx_stat_gtpkt_hi;
- u32 tx_stat_gtxpf_lo;
- u32 tx_stat_gtxpf_hi;
- u32 tx_stat_gtfcs_lo;
- u32 tx_stat_gtfcs_hi;
- u32 tx_stat_gtmca_lo;
- u32 tx_stat_gtmca_hi;
- u32 tx_stat_gtbca_lo;
- u32 tx_stat_gtbca_hi;
- u32 tx_stat_gtfrg_lo;
- u32 tx_stat_gtfrg_hi;
- u32 tx_stat_gtovr_lo;
- u32 tx_stat_gtovr_hi;
- u32 tx_stat_gt64_lo;
- u32 tx_stat_gt64_hi;
- u32 tx_stat_gt127_lo;
- u32 tx_stat_gt127_hi;
- u32 tx_stat_gt255_lo;
- u32 tx_stat_gt255_hi;
- u32 tx_stat_gt511_lo;
- u32 tx_stat_gt511_hi;
- u32 tx_stat_gt1023_lo;
- u32 tx_stat_gt1023_hi;
- u32 tx_stat_gt1518_lo;
- u32 tx_stat_gt1518_hi;
- u32 tx_stat_gt2047_lo;
- u32 tx_stat_gt2047_hi;
- u32 tx_stat_gt4095_lo;
- u32 tx_stat_gt4095_hi;
- u32 tx_stat_gt9216_lo;
- u32 tx_stat_gt9216_hi;
- u32 tx_stat_gt16383_lo;
- u32 tx_stat_gt16383_hi;
- u32 tx_stat_gtmax_lo;
- u32 tx_stat_gtmax_hi;
- u32 tx_stat_gtufl_lo;
- u32 tx_stat_gtufl_hi;
- u32 tx_stat_gterr_lo;
- u32 tx_stat_gterr_hi;
- u32 tx_stat_gtbyt_lo;
- u32 tx_stat_gtbyt_hi;
+ u32 tx_stat_gtpkt_lo;
+ u32 tx_stat_gtpkt_hi;
+ u32 tx_stat_gtxpf_lo;
+ u32 tx_stat_gtxpf_hi;
+ u32 tx_stat_gtfcs_lo;
+ u32 tx_stat_gtfcs_hi;
+ u32 tx_stat_gtmca_lo;
+ u32 tx_stat_gtmca_hi;
+ u32 tx_stat_gtbca_lo;
+ u32 tx_stat_gtbca_hi;
+ u32 tx_stat_gtfrg_lo;
+ u32 tx_stat_gtfrg_hi;
+ u32 tx_stat_gtovr_lo;
+ u32 tx_stat_gtovr_hi;
+ u32 tx_stat_gt64_lo;
+ u32 tx_stat_gt64_hi;
+ u32 tx_stat_gt127_lo;
+ u32 tx_stat_gt127_hi;
+ u32 tx_stat_gt255_lo;
+ u32 tx_stat_gt255_hi;
+ u32 tx_stat_gt511_lo;
+ u32 tx_stat_gt511_hi;
+ u32 tx_stat_gt1023_lo;
+ u32 tx_stat_gt1023_hi;
+ u32 tx_stat_gt1518_lo;
+ u32 tx_stat_gt1518_hi;
+ u32 tx_stat_gt2047_lo;
+ u32 tx_stat_gt2047_hi;
+ u32 tx_stat_gt4095_lo;
+ u32 tx_stat_gt4095_hi;
+ u32 tx_stat_gt9216_lo;
+ u32 tx_stat_gt9216_hi;
+ u32 tx_stat_gt16383_lo;
+ u32 tx_stat_gt16383_hi;
+ u32 tx_stat_gtmax_lo;
+ u32 tx_stat_gtmax_hi;
+ u32 tx_stat_gtufl_lo;
+ u32 tx_stat_gtufl_hi;
+ u32 tx_stat_gterr_lo;
+ u32 tx_stat_gterr_hi;
+ u32 tx_stat_gtbyt_lo;
+ u32 tx_stat_gtbyt_hi;
- u32 rx_stat_gr64_lo;
- u32 rx_stat_gr64_hi;
- u32 rx_stat_gr127_lo;
- u32 rx_stat_gr127_hi;
- u32 rx_stat_gr255_lo;
- u32 rx_stat_gr255_hi;
- u32 rx_stat_gr511_lo;
- u32 rx_stat_gr511_hi;
- u32 rx_stat_gr1023_lo;
- u32 rx_stat_gr1023_hi;
- u32 rx_stat_gr1518_lo;
- u32 rx_stat_gr1518_hi;
- u32 rx_stat_gr2047_lo;
- u32 rx_stat_gr2047_hi;
- u32 rx_stat_gr4095_lo;
- u32 rx_stat_gr4095_hi;
- u32 rx_stat_gr9216_lo;
- u32 rx_stat_gr9216_hi;
- u32 rx_stat_gr16383_lo;
- u32 rx_stat_gr16383_hi;
- u32 rx_stat_grmax_lo;
- u32 rx_stat_grmax_hi;
- u32 rx_stat_grpkt_lo;
- u32 rx_stat_grpkt_hi;
- u32 rx_stat_grfcs_lo;
- u32 rx_stat_grfcs_hi;
- u32 rx_stat_grmca_lo;
- u32 rx_stat_grmca_hi;
- u32 rx_stat_grbca_lo;
- u32 rx_stat_grbca_hi;
- u32 rx_stat_grxcf_lo;
- u32 rx_stat_grxcf_hi;
- u32 rx_stat_grxpf_lo;
- u32 rx_stat_grxpf_hi;
- u32 rx_stat_grxuo_lo;
- u32 rx_stat_grxuo_hi;
- u32 rx_stat_grjbr_lo;
- u32 rx_stat_grjbr_hi;
- u32 rx_stat_grovr_lo;
- u32 rx_stat_grovr_hi;
- u32 rx_stat_grflr_lo;
- u32 rx_stat_grflr_hi;
- u32 rx_stat_grmeg_lo;
- u32 rx_stat_grmeg_hi;
- u32 rx_stat_grmeb_lo;
- u32 rx_stat_grmeb_hi;
- u32 rx_stat_grbyt_lo;
- u32 rx_stat_grbyt_hi;
- u32 rx_stat_grund_lo;
- u32 rx_stat_grund_hi;
- u32 rx_stat_grfrg_lo;
- u32 rx_stat_grfrg_hi;
- u32 rx_stat_grerb_lo;
- u32 rx_stat_grerb_hi;
- u32 rx_stat_grfre_lo;
- u32 rx_stat_grfre_hi;
- u32 rx_stat_gripj_lo;
- u32 rx_stat_gripj_hi;
+ u32 rx_stat_gr64_lo;
+ u32 rx_stat_gr64_hi;
+ u32 rx_stat_gr127_lo;
+ u32 rx_stat_gr127_hi;
+ u32 rx_stat_gr255_lo;
+ u32 rx_stat_gr255_hi;
+ u32 rx_stat_gr511_lo;
+ u32 rx_stat_gr511_hi;
+ u32 rx_stat_gr1023_lo;
+ u32 rx_stat_gr1023_hi;
+ u32 rx_stat_gr1518_lo;
+ u32 rx_stat_gr1518_hi;
+ u32 rx_stat_gr2047_lo;
+ u32 rx_stat_gr2047_hi;
+ u32 rx_stat_gr4095_lo;
+ u32 rx_stat_gr4095_hi;
+ u32 rx_stat_gr9216_lo;
+ u32 rx_stat_gr9216_hi;
+ u32 rx_stat_gr16383_lo;
+ u32 rx_stat_gr16383_hi;
+ u32 rx_stat_grmax_lo;
+ u32 rx_stat_grmax_hi;
+ u32 rx_stat_grpkt_lo;
+ u32 rx_stat_grpkt_hi;
+ u32 rx_stat_grfcs_lo;
+ u32 rx_stat_grfcs_hi;
+ u32 rx_stat_grmca_lo;
+ u32 rx_stat_grmca_hi;
+ u32 rx_stat_grbca_lo;
+ u32 rx_stat_grbca_hi;
+ u32 rx_stat_grxcf_lo;
+ u32 rx_stat_grxcf_hi;
+ u32 rx_stat_grxpf_lo;
+ u32 rx_stat_grxpf_hi;
+ u32 rx_stat_grxuo_lo;
+ u32 rx_stat_grxuo_hi;
+ u32 rx_stat_grjbr_lo;
+ u32 rx_stat_grjbr_hi;
+ u32 rx_stat_grovr_lo;
+ u32 rx_stat_grovr_hi;
+ u32 rx_stat_grflr_lo;
+ u32 rx_stat_grflr_hi;
+ u32 rx_stat_grmeg_lo;
+ u32 rx_stat_grmeg_hi;
+ u32 rx_stat_grmeb_lo;
+ u32 rx_stat_grmeb_hi;
+ u32 rx_stat_grbyt_lo;
+ u32 rx_stat_grbyt_hi;
+ u32 rx_stat_grund_lo;
+ u32 rx_stat_grund_hi;
+ u32 rx_stat_grfrg_lo;
+ u32 rx_stat_grfrg_hi;
+ u32 rx_stat_grerb_lo;
+ u32 rx_stat_grerb_hi;
+ u32 rx_stat_grfre_lo;
+ u32 rx_stat_grfre_hi;
+ u32 rx_stat_gripj_lo;
+ u32 rx_stat_gripj_hi;
};
struct bmac2_stats {
@@ -1750,187 +2237,316 @@
u32 rx_stat_gripj_hi;
};
+struct mstat_stats {
+ struct {
+ /* OTE MSTAT on E3 has a bug where this register's contents are
+ * actually tx_gtxpok + tx_gtxpf + (possibly)tx_gtxpp
+ */
+ u32 tx_gtxpok_lo;
+ u32 tx_gtxpok_hi;
+ u32 tx_gtxpf_lo;
+ u32 tx_gtxpf_hi;
+ u32 tx_gtxpp_lo;
+ u32 tx_gtxpp_hi;
+ u32 tx_gtfcs_lo;
+ u32 tx_gtfcs_hi;
+ u32 tx_gtuca_lo;
+ u32 tx_gtuca_hi;
+ u32 tx_gtmca_lo;
+ u32 tx_gtmca_hi;
+ u32 tx_gtgca_lo;
+ u32 tx_gtgca_hi;
+ u32 tx_gtpkt_lo;
+ u32 tx_gtpkt_hi;
+ u32 tx_gt64_lo;
+ u32 tx_gt64_hi;
+ u32 tx_gt127_lo;
+ u32 tx_gt127_hi;
+ u32 tx_gt255_lo;
+ u32 tx_gt255_hi;
+ u32 tx_gt511_lo;
+ u32 tx_gt511_hi;
+ u32 tx_gt1023_lo;
+ u32 tx_gt1023_hi;
+ u32 tx_gt1518_lo;
+ u32 tx_gt1518_hi;
+ u32 tx_gt2047_lo;
+ u32 tx_gt2047_hi;
+ u32 tx_gt4095_lo;
+ u32 tx_gt4095_hi;
+ u32 tx_gt9216_lo;
+ u32 tx_gt9216_hi;
+ u32 tx_gt16383_lo;
+ u32 tx_gt16383_hi;
+ u32 tx_gtufl_lo;
+ u32 tx_gtufl_hi;
+ u32 tx_gterr_lo;
+ u32 tx_gterr_hi;
+ u32 tx_gtbyt_lo;
+ u32 tx_gtbyt_hi;
+ u32 tx_collisions_lo;
+ u32 tx_collisions_hi;
+ u32 tx_singlecollision_lo;
+ u32 tx_singlecollision_hi;
+ u32 tx_multiplecollisions_lo;
+ u32 tx_multiplecollisions_hi;
+ u32 tx_deferred_lo;
+ u32 tx_deferred_hi;
+ u32 tx_excessivecollisions_lo;
+ u32 tx_excessivecollisions_hi;
+ u32 tx_latecollisions_lo;
+ u32 tx_latecollisions_hi;
+ } stats_tx;
+
+ struct {
+ u32 rx_gr64_lo;
+ u32 rx_gr64_hi;
+ u32 rx_gr127_lo;
+ u32 rx_gr127_hi;
+ u32 rx_gr255_lo;
+ u32 rx_gr255_hi;
+ u32 rx_gr511_lo;
+ u32 rx_gr511_hi;
+ u32 rx_gr1023_lo;
+ u32 rx_gr1023_hi;
+ u32 rx_gr1518_lo;
+ u32 rx_gr1518_hi;
+ u32 rx_gr2047_lo;
+ u32 rx_gr2047_hi;
+ u32 rx_gr4095_lo;
+ u32 rx_gr4095_hi;
+ u32 rx_gr9216_lo;
+ u32 rx_gr9216_hi;
+ u32 rx_gr16383_lo;
+ u32 rx_gr16383_hi;
+ u32 rx_grpkt_lo;
+ u32 rx_grpkt_hi;
+ u32 rx_grfcs_lo;
+ u32 rx_grfcs_hi;
+ u32 rx_gruca_lo;
+ u32 rx_gruca_hi;
+ u32 rx_grmca_lo;
+ u32 rx_grmca_hi;
+ u32 rx_grbca_lo;
+ u32 rx_grbca_hi;
+ u32 rx_grxpf_lo;
+ u32 rx_grxpf_hi;
+ u32 rx_grxpp_lo;
+ u32 rx_grxpp_hi;
+ u32 rx_grxuo_lo;
+ u32 rx_grxuo_hi;
+ u32 rx_grovr_lo;
+ u32 rx_grovr_hi;
+ u32 rx_grxcf_lo;
+ u32 rx_grxcf_hi;
+ u32 rx_grflr_lo;
+ u32 rx_grflr_hi;
+ u32 rx_grpok_lo;
+ u32 rx_grpok_hi;
+ u32 rx_grbyt_lo;
+ u32 rx_grbyt_hi;
+ u32 rx_grund_lo;
+ u32 rx_grund_hi;
+ u32 rx_grfrg_lo;
+ u32 rx_grfrg_hi;
+ u32 rx_grerb_lo;
+ u32 rx_grerb_hi;
+ u32 rx_grfre_lo;
+ u32 rx_grfre_hi;
+
+ u32 rx_alignmenterrors_lo;
+ u32 rx_alignmenterrors_hi;
+ u32 rx_falsecarrier_lo;
+ u32 rx_falsecarrier_hi;
+ u32 rx_llfcmsgcnt_lo;
+ u32 rx_llfcmsgcnt_hi;
+ } stats_rx;
+};
+
union mac_stats {
- struct emac_stats emac_stats;
- struct bmac1_stats bmac1_stats;
- struct bmac2_stats bmac2_stats;
+ struct emac_stats emac_stats;
+ struct bmac1_stats bmac1_stats;
+ struct bmac2_stats bmac2_stats;
+ struct mstat_stats mstat_stats;
};
struct mac_stx {
- /* in_bad_octets */
- u32 rx_stat_ifhcinbadoctets_hi;
- u32 rx_stat_ifhcinbadoctets_lo;
+ /* in_bad_octets */
+ u32 rx_stat_ifhcinbadoctets_hi;
+ u32 rx_stat_ifhcinbadoctets_lo;
- /* out_bad_octets */
- u32 tx_stat_ifhcoutbadoctets_hi;
- u32 tx_stat_ifhcoutbadoctets_lo;
+ /* out_bad_octets */
+ u32 tx_stat_ifhcoutbadoctets_hi;
+ u32 tx_stat_ifhcoutbadoctets_lo;
- /* crc_receive_errors */
- u32 rx_stat_dot3statsfcserrors_hi;
- u32 rx_stat_dot3statsfcserrors_lo;
- /* alignment_errors */
- u32 rx_stat_dot3statsalignmenterrors_hi;
- u32 rx_stat_dot3statsalignmenterrors_lo;
- /* carrier_sense_errors */
- u32 rx_stat_dot3statscarriersenseerrors_hi;
- u32 rx_stat_dot3statscarriersenseerrors_lo;
- /* false_carrier_detections */
- u32 rx_stat_falsecarriererrors_hi;
- u32 rx_stat_falsecarriererrors_lo;
+ /* crc_receive_errors */
+ u32 rx_stat_dot3statsfcserrors_hi;
+ u32 rx_stat_dot3statsfcserrors_lo;
+ /* alignment_errors */
+ u32 rx_stat_dot3statsalignmenterrors_hi;
+ u32 rx_stat_dot3statsalignmenterrors_lo;
+ /* carrier_sense_errors */
+ u32 rx_stat_dot3statscarriersenseerrors_hi;
+ u32 rx_stat_dot3statscarriersenseerrors_lo;
+ /* false_carrier_detections */
+ u32 rx_stat_falsecarriererrors_hi;
+ u32 rx_stat_falsecarriererrors_lo;
- /* runt_packets_received */
- u32 rx_stat_etherstatsundersizepkts_hi;
- u32 rx_stat_etherstatsundersizepkts_lo;
- /* jabber_packets_received */
- u32 rx_stat_dot3statsframestoolong_hi;
- u32 rx_stat_dot3statsframestoolong_lo;
+ /* runt_packets_received */
+ u32 rx_stat_etherstatsundersizepkts_hi;
+ u32 rx_stat_etherstatsundersizepkts_lo;
+ /* jabber_packets_received */
+ u32 rx_stat_dot3statsframestoolong_hi;
+ u32 rx_stat_dot3statsframestoolong_lo;
- /* error_runt_packets_received */
- u32 rx_stat_etherstatsfragments_hi;
- u32 rx_stat_etherstatsfragments_lo;
- /* error_jabber_packets_received */
- u32 rx_stat_etherstatsjabbers_hi;
- u32 rx_stat_etherstatsjabbers_lo;
+ /* error_runt_packets_received */
+ u32 rx_stat_etherstatsfragments_hi;
+ u32 rx_stat_etherstatsfragments_lo;
+ /* error_jabber_packets_received */
+ u32 rx_stat_etherstatsjabbers_hi;
+ u32 rx_stat_etherstatsjabbers_lo;
- /* control_frames_received */
- u32 rx_stat_maccontrolframesreceived_hi;
- u32 rx_stat_maccontrolframesreceived_lo;
- u32 rx_stat_bmac_xpf_hi;
- u32 rx_stat_bmac_xpf_lo;
- u32 rx_stat_bmac_xcf_hi;
- u32 rx_stat_bmac_xcf_lo;
+ /* control_frames_received */
+ u32 rx_stat_maccontrolframesreceived_hi;
+ u32 rx_stat_maccontrolframesreceived_lo;
+ u32 rx_stat_mac_xpf_hi;
+ u32 rx_stat_mac_xpf_lo;
+ u32 rx_stat_mac_xcf_hi;
+ u32 rx_stat_mac_xcf_lo;
- /* xoff_state_entered */
- u32 rx_stat_xoffstateentered_hi;
- u32 rx_stat_xoffstateentered_lo;
- /* pause_xon_frames_received */
- u32 rx_stat_xonpauseframesreceived_hi;
- u32 rx_stat_xonpauseframesreceived_lo;
- /* pause_xoff_frames_received */
- u32 rx_stat_xoffpauseframesreceived_hi;
- u32 rx_stat_xoffpauseframesreceived_lo;
- /* pause_xon_frames_transmitted */
- u32 tx_stat_outxonsent_hi;
- u32 tx_stat_outxonsent_lo;
- /* pause_xoff_frames_transmitted */
- u32 tx_stat_outxoffsent_hi;
- u32 tx_stat_outxoffsent_lo;
- /* flow_control_done */
- u32 tx_stat_flowcontroldone_hi;
- u32 tx_stat_flowcontroldone_lo;
+ /* xoff_state_entered */
+ u32 rx_stat_xoffstateentered_hi;
+ u32 rx_stat_xoffstateentered_lo;
+ /* pause_xon_frames_received */
+ u32 rx_stat_xonpauseframesreceived_hi;
+ u32 rx_stat_xonpauseframesreceived_lo;
+ /* pause_xoff_frames_received */
+ u32 rx_stat_xoffpauseframesreceived_hi;
+ u32 rx_stat_xoffpauseframesreceived_lo;
+ /* pause_xon_frames_transmitted */
+ u32 tx_stat_outxonsent_hi;
+ u32 tx_stat_outxonsent_lo;
+ /* pause_xoff_frames_transmitted */
+ u32 tx_stat_outxoffsent_hi;
+ u32 tx_stat_outxoffsent_lo;
+ /* flow_control_done */
+ u32 tx_stat_flowcontroldone_hi;
+ u32 tx_stat_flowcontroldone_lo;
- /* ether_stats_collisions */
- u32 tx_stat_etherstatscollisions_hi;
- u32 tx_stat_etherstatscollisions_lo;
- /* single_collision_transmit_frames */
- u32 tx_stat_dot3statssinglecollisionframes_hi;
- u32 tx_stat_dot3statssinglecollisionframes_lo;
- /* multiple_collision_transmit_frames */
- u32 tx_stat_dot3statsmultiplecollisionframes_hi;
- u32 tx_stat_dot3statsmultiplecollisionframes_lo;
- /* deferred_transmissions */
- u32 tx_stat_dot3statsdeferredtransmissions_hi;
- u32 tx_stat_dot3statsdeferredtransmissions_lo;
- /* excessive_collision_frames */
- u32 tx_stat_dot3statsexcessivecollisions_hi;
- u32 tx_stat_dot3statsexcessivecollisions_lo;
- /* late_collision_frames */
- u32 tx_stat_dot3statslatecollisions_hi;
- u32 tx_stat_dot3statslatecollisions_lo;
+ /* ether_stats_collisions */
+ u32 tx_stat_etherstatscollisions_hi;
+ u32 tx_stat_etherstatscollisions_lo;
+ /* single_collision_transmit_frames */
+ u32 tx_stat_dot3statssinglecollisionframes_hi;
+ u32 tx_stat_dot3statssinglecollisionframes_lo;
+ /* multiple_collision_transmit_frames */
+ u32 tx_stat_dot3statsmultiplecollisionframes_hi;
+ u32 tx_stat_dot3statsmultiplecollisionframes_lo;
+ /* deferred_transmissions */
+ u32 tx_stat_dot3statsdeferredtransmissions_hi;
+ u32 tx_stat_dot3statsdeferredtransmissions_lo;
+ /* excessive_collision_frames */
+ u32 tx_stat_dot3statsexcessivecollisions_hi;
+ u32 tx_stat_dot3statsexcessivecollisions_lo;
+ /* late_collision_frames */
+ u32 tx_stat_dot3statslatecollisions_hi;
+ u32 tx_stat_dot3statslatecollisions_lo;
- /* frames_transmitted_64_bytes */
- u32 tx_stat_etherstatspkts64octets_hi;
- u32 tx_stat_etherstatspkts64octets_lo;
- /* frames_transmitted_65_127_bytes */
- u32 tx_stat_etherstatspkts65octetsto127octets_hi;
- u32 tx_stat_etherstatspkts65octetsto127octets_lo;
- /* frames_transmitted_128_255_bytes */
- u32 tx_stat_etherstatspkts128octetsto255octets_hi;
- u32 tx_stat_etherstatspkts128octetsto255octets_lo;
- /* frames_transmitted_256_511_bytes */
- u32 tx_stat_etherstatspkts256octetsto511octets_hi;
- u32 tx_stat_etherstatspkts256octetsto511octets_lo;
- /* frames_transmitted_512_1023_bytes */
- u32 tx_stat_etherstatspkts512octetsto1023octets_hi;
- u32 tx_stat_etherstatspkts512octetsto1023octets_lo;
- /* frames_transmitted_1024_1522_bytes */
- u32 tx_stat_etherstatspkts1024octetsto1522octets_hi;
- u32 tx_stat_etherstatspkts1024octetsto1522octets_lo;
- /* frames_transmitted_1523_9022_bytes */
- u32 tx_stat_etherstatspktsover1522octets_hi;
- u32 tx_stat_etherstatspktsover1522octets_lo;
- u32 tx_stat_bmac_2047_hi;
- u32 tx_stat_bmac_2047_lo;
- u32 tx_stat_bmac_4095_hi;
- u32 tx_stat_bmac_4095_lo;
- u32 tx_stat_bmac_9216_hi;
- u32 tx_stat_bmac_9216_lo;
- u32 tx_stat_bmac_16383_hi;
- u32 tx_stat_bmac_16383_lo;
+ /* frames_transmitted_64_bytes */
+ u32 tx_stat_etherstatspkts64octets_hi;
+ u32 tx_stat_etherstatspkts64octets_lo;
+ /* frames_transmitted_65_127_bytes */
+ u32 tx_stat_etherstatspkts65octetsto127octets_hi;
+ u32 tx_stat_etherstatspkts65octetsto127octets_lo;
+ /* frames_transmitted_128_255_bytes */
+ u32 tx_stat_etherstatspkts128octetsto255octets_hi;
+ u32 tx_stat_etherstatspkts128octetsto255octets_lo;
+ /* frames_transmitted_256_511_bytes */
+ u32 tx_stat_etherstatspkts256octetsto511octets_hi;
+ u32 tx_stat_etherstatspkts256octetsto511octets_lo;
+ /* frames_transmitted_512_1023_bytes */
+ u32 tx_stat_etherstatspkts512octetsto1023octets_hi;
+ u32 tx_stat_etherstatspkts512octetsto1023octets_lo;
+ /* frames_transmitted_1024_1522_bytes */
+ u32 tx_stat_etherstatspkts1024octetsto1522octets_hi;
+ u32 tx_stat_etherstatspkts1024octetsto1522octets_lo;
+ /* frames_transmitted_1523_9022_bytes */
+ u32 tx_stat_etherstatspktsover1522octets_hi;
+ u32 tx_stat_etherstatspktsover1522octets_lo;
+ u32 tx_stat_mac_2047_hi;
+ u32 tx_stat_mac_2047_lo;
+ u32 tx_stat_mac_4095_hi;
+ u32 tx_stat_mac_4095_lo;
+ u32 tx_stat_mac_9216_hi;
+ u32 tx_stat_mac_9216_lo;
+ u32 tx_stat_mac_16383_hi;
+ u32 tx_stat_mac_16383_lo;
- /* internal_mac_transmit_errors */
- u32 tx_stat_dot3statsinternalmactransmiterrors_hi;
- u32 tx_stat_dot3statsinternalmactransmiterrors_lo;
+ /* internal_mac_transmit_errors */
+ u32 tx_stat_dot3statsinternalmactransmiterrors_hi;
+ u32 tx_stat_dot3statsinternalmactransmiterrors_lo;
- /* if_out_discards */
- u32 tx_stat_bmac_ufl_hi;
- u32 tx_stat_bmac_ufl_lo;
+ /* if_out_discards */
+ u32 tx_stat_mac_ufl_hi;
+ u32 tx_stat_mac_ufl_lo;
};
-#define MAC_STX_IDX_MAX 2
+#define MAC_STX_IDX_MAX 2
struct host_port_stats {
- u32 host_port_stats_start;
+ u32 host_port_stats_start;
- struct mac_stx mac_stx[MAC_STX_IDX_MAX];
+ struct mac_stx mac_stx[MAC_STX_IDX_MAX];
- u32 brb_drop_hi;
- u32 brb_drop_lo;
+ u32 brb_drop_hi;
+ u32 brb_drop_lo;
- u32 host_port_stats_end;
+ u32 host_port_stats_end;
};
struct host_func_stats {
- u32 host_func_stats_start;
+ u32 host_func_stats_start;
- u32 total_bytes_received_hi;
- u32 total_bytes_received_lo;
+ u32 total_bytes_received_hi;
+ u32 total_bytes_received_lo;
- u32 total_bytes_transmitted_hi;
- u32 total_bytes_transmitted_lo;
+ u32 total_bytes_transmitted_hi;
+ u32 total_bytes_transmitted_lo;
- u32 total_unicast_packets_received_hi;
- u32 total_unicast_packets_received_lo;
+ u32 total_unicast_packets_received_hi;
+ u32 total_unicast_packets_received_lo;
- u32 total_multicast_packets_received_hi;
- u32 total_multicast_packets_received_lo;
+ u32 total_multicast_packets_received_hi;
+ u32 total_multicast_packets_received_lo;
- u32 total_broadcast_packets_received_hi;
- u32 total_broadcast_packets_received_lo;
+ u32 total_broadcast_packets_received_hi;
+ u32 total_broadcast_packets_received_lo;
- u32 total_unicast_packets_transmitted_hi;
- u32 total_unicast_packets_transmitted_lo;
+ u32 total_unicast_packets_transmitted_hi;
+ u32 total_unicast_packets_transmitted_lo;
- u32 total_multicast_packets_transmitted_hi;
- u32 total_multicast_packets_transmitted_lo;
+ u32 total_multicast_packets_transmitted_hi;
+ u32 total_multicast_packets_transmitted_lo;
- u32 total_broadcast_packets_transmitted_hi;
- u32 total_broadcast_packets_transmitted_lo;
+ u32 total_broadcast_packets_transmitted_hi;
+ u32 total_broadcast_packets_transmitted_lo;
- u32 valid_bytes_received_hi;
- u32 valid_bytes_received_lo;
+ u32 valid_bytes_received_hi;
+ u32 valid_bytes_received_lo;
- u32 host_func_stats_end;
+ u32 host_func_stats_end;
};
+/* VIC definitions */
+#define VICSTATST_UIF_INDEX 2
-#define BCM_5710_FW_MAJOR_VERSION 6
-#define BCM_5710_FW_MINOR_VERSION 2
-#define BCM_5710_FW_REVISION_VERSION 9
-#define BCM_5710_FW_ENGINEERING_VERSION 0
+#define BCM_5710_FW_MAJOR_VERSION 7
+#define BCM_5710_FW_MINOR_VERSION 0
+#define BCM_5710_FW_REVISION_VERSION 20
+#define BCM_5710_FW_ENGINEERING_VERSION 0
#define BCM_5710_FW_COMPILE_FLAGS 1
@@ -1948,6 +2564,115 @@
/*
+ * The eth aggregative context of Cstorm
+ */
+struct cstorm_eth_ag_context {
+ u32 __reserved0[10];
+};
+
+
+/*
+ * dmae command structure
+ */
+struct dmae_command {
+ u32 opcode;
+#define DMAE_COMMAND_SRC (0x1<<0)
+#define DMAE_COMMAND_SRC_SHIFT 0
+#define DMAE_COMMAND_DST (0x3<<1)
+#define DMAE_COMMAND_DST_SHIFT 1
+#define DMAE_COMMAND_C_DST (0x1<<3)
+#define DMAE_COMMAND_C_DST_SHIFT 3
+#define DMAE_COMMAND_C_TYPE_ENABLE (0x1<<4)
+#define DMAE_COMMAND_C_TYPE_ENABLE_SHIFT 4
+#define DMAE_COMMAND_C_TYPE_CRC_ENABLE (0x1<<5)
+#define DMAE_COMMAND_C_TYPE_CRC_ENABLE_SHIFT 5
+#define DMAE_COMMAND_C_TYPE_CRC_OFFSET (0x7<<6)
+#define DMAE_COMMAND_C_TYPE_CRC_OFFSET_SHIFT 6
+#define DMAE_COMMAND_ENDIANITY (0x3<<9)
+#define DMAE_COMMAND_ENDIANITY_SHIFT 9
+#define DMAE_COMMAND_PORT (0x1<<11)
+#define DMAE_COMMAND_PORT_SHIFT 11
+#define DMAE_COMMAND_CRC_RESET (0x1<<12)
+#define DMAE_COMMAND_CRC_RESET_SHIFT 12
+#define DMAE_COMMAND_SRC_RESET (0x1<<13)
+#define DMAE_COMMAND_SRC_RESET_SHIFT 13
+#define DMAE_COMMAND_DST_RESET (0x1<<14)
+#define DMAE_COMMAND_DST_RESET_SHIFT 14
+#define DMAE_COMMAND_E1HVN (0x3<<15)
+#define DMAE_COMMAND_E1HVN_SHIFT 15
+#define DMAE_COMMAND_DST_VN (0x3<<17)
+#define DMAE_COMMAND_DST_VN_SHIFT 17
+#define DMAE_COMMAND_C_FUNC (0x1<<19)
+#define DMAE_COMMAND_C_FUNC_SHIFT 19
+#define DMAE_COMMAND_ERR_POLICY (0x3<<20)
+#define DMAE_COMMAND_ERR_POLICY_SHIFT 20
+#define DMAE_COMMAND_RESERVED0 (0x3FF<<22)
+#define DMAE_COMMAND_RESERVED0_SHIFT 22
+ u32 src_addr_lo;
+ u32 src_addr_hi;
+ u32 dst_addr_lo;
+ u32 dst_addr_hi;
+#if defined(__BIG_ENDIAN)
+ u16 opcode_iov;
+#define DMAE_COMMAND_SRC_VFID (0x3F<<0)
+#define DMAE_COMMAND_SRC_VFID_SHIFT 0
+#define DMAE_COMMAND_SRC_VFPF (0x1<<6)
+#define DMAE_COMMAND_SRC_VFPF_SHIFT 6
+#define DMAE_COMMAND_RESERVED1 (0x1<<7)
+#define DMAE_COMMAND_RESERVED1_SHIFT 7
+#define DMAE_COMMAND_DST_VFID (0x3F<<8)
+#define DMAE_COMMAND_DST_VFID_SHIFT 8
+#define DMAE_COMMAND_DST_VFPF (0x1<<14)
+#define DMAE_COMMAND_DST_VFPF_SHIFT 14
+#define DMAE_COMMAND_RESERVED2 (0x1<<15)
+#define DMAE_COMMAND_RESERVED2_SHIFT 15
+ u16 len;
+#elif defined(__LITTLE_ENDIAN)
+ u16 len;
+ u16 opcode_iov;
+#define DMAE_COMMAND_SRC_VFID (0x3F<<0)
+#define DMAE_COMMAND_SRC_VFID_SHIFT 0
+#define DMAE_COMMAND_SRC_VFPF (0x1<<6)
+#define DMAE_COMMAND_SRC_VFPF_SHIFT 6
+#define DMAE_COMMAND_RESERVED1 (0x1<<7)
+#define DMAE_COMMAND_RESERVED1_SHIFT 7
+#define DMAE_COMMAND_DST_VFID (0x3F<<8)
+#define DMAE_COMMAND_DST_VFID_SHIFT 8
+#define DMAE_COMMAND_DST_VFPF (0x1<<14)
+#define DMAE_COMMAND_DST_VFPF_SHIFT 14
+#define DMAE_COMMAND_RESERVED2 (0x1<<15)
+#define DMAE_COMMAND_RESERVED2_SHIFT 15
+#endif
+ u32 comp_addr_lo;
+ u32 comp_addr_hi;
+ u32 comp_val;
+ u32 crc32;
+ u32 crc32_c;
+#if defined(__BIG_ENDIAN)
+ u16 crc16_c;
+ u16 crc16;
+#elif defined(__LITTLE_ENDIAN)
+ u16 crc16;
+ u16 crc16_c;
+#endif
+#if defined(__BIG_ENDIAN)
+ u16 reserved3;
+ u16 crc_t10;
+#elif defined(__LITTLE_ENDIAN)
+ u16 crc_t10;
+ u16 reserved3;
+#endif
+#if defined(__BIG_ENDIAN)
+ u16 xsum8;
+ u16 xsum16;
+#elif defined(__LITTLE_ENDIAN)
+ u16 xsum16;
+ u16 xsum8;
+#endif
+};
+
+
+/*
* common data for all protocols
*/
struct doorbell_hdr {
@@ -1963,33 +2688,29 @@
};
/*
- * doorbell message sent to the chip
+ * Ethernet doorbell
*/
-struct doorbell {
+struct eth_tx_doorbell {
#if defined(__BIG_ENDIAN)
- u16 zero_fill2;
- u8 zero_fill1;
- struct doorbell_hdr header;
+ u16 npackets;
+ u8 params;
+#define ETH_TX_DOORBELL_NUM_BDS (0x3F<<0)
+#define ETH_TX_DOORBELL_NUM_BDS_SHIFT 0
+#define ETH_TX_DOORBELL_RESERVED_TX_FIN_FLAG (0x1<<6)
+#define ETH_TX_DOORBELL_RESERVED_TX_FIN_FLAG_SHIFT 6
+#define ETH_TX_DOORBELL_SPARE (0x1<<7)
+#define ETH_TX_DOORBELL_SPARE_SHIFT 7
+ struct doorbell_hdr hdr;
#elif defined(__LITTLE_ENDIAN)
- struct doorbell_hdr header;
- u8 zero_fill1;
- u16 zero_fill2;
-#endif
-};
-
-
-/*
- * doorbell message sent to the chip
- */
-struct doorbell_set_prod {
-#if defined(__BIG_ENDIAN)
- u16 prod;
- u8 zero_fill1;
- struct doorbell_hdr header;
-#elif defined(__LITTLE_ENDIAN)
- struct doorbell_hdr header;
- u8 zero_fill1;
- u16 prod;
+ struct doorbell_hdr hdr;
+ u8 params;
+#define ETH_TX_DOORBELL_NUM_BDS (0x3F<<0)
+#define ETH_TX_DOORBELL_NUM_BDS_SHIFT 0
+#define ETH_TX_DOORBELL_RESERVED_TX_FIN_FLAG (0x1<<6)
+#define ETH_TX_DOORBELL_RESERVED_TX_FIN_FLAG_SHIFT 6
+#define ETH_TX_DOORBELL_SPARE (0x1<<7)
+#define ETH_TX_DOORBELL_SPARE_SHIFT 7
+ u16 npackets;
#endif
};
@@ -2000,7 +2721,7 @@
struct hc_status_block_e1x {
__le16 index_values[HC_SB_MAX_INDICES_E1X];
__le16 running_index[HC_SB_MAX_SM];
- u32 rsrv;
+ __le32 rsrv[11];
};
/*
@@ -2017,7 +2738,7 @@
struct hc_status_block_e2 {
__le16 index_values[HC_SB_MAX_INDICES_E2];
__le16 running_index[HC_SB_MAX_SM];
- u32 reserved;
+ __le32 reserved[11];
};
/*
@@ -2138,6 +2859,16 @@
/*
+ * Igu control commands
+ */
+enum igu_ctrl_cmd {
+ IGU_CTRL_CMD_TYPE_RD,
+ IGU_CTRL_CMD_TYPE_WR,
+ MAX_IGU_CTRL_CMD
+};
+
+
+/*
* Control register for the IGU command register
*/
struct igu_ctrl_reg {
@@ -2156,6 +2887,29 @@
/*
+ * Igu interrupt command
+ */
+enum igu_int_cmd {
+ IGU_INT_ENABLE,
+ IGU_INT_DISABLE,
+ IGU_INT_NOP,
+ IGU_INT_NOP2,
+ MAX_IGU_INT_CMD
+};
+
+
+/*
+ * Igu segments
+ */
+enum igu_seg_access {
+ IGU_SEG_ACCESS_NORM,
+ IGU_SEG_ACCESS_DEF,
+ IGU_SEG_ACCESS_ATTN,
+ MAX_IGU_SEG_ACCESS
+};
+
+
+/*
* Parser parsing flags field
*/
struct parsing_flags {
@@ -2189,94 +2943,46 @@
};
-struct regpair {
- __le32 lo;
- __le32 hi;
+/*
+ * Parsing flags for TCP ACK type
+ */
+enum prs_flags_ack_type {
+ PRS_FLAG_PUREACK_PIGGY,
+ PRS_FLAG_PUREACK_PURE,
+ MAX_PRS_FLAGS_ACK_TYPE
};
/*
- * dmae command structure
+ * Parsing flags for Ethernet address type
*/
-struct dmae_command {
- u32 opcode;
-#define DMAE_COMMAND_SRC (0x1<<0)
-#define DMAE_COMMAND_SRC_SHIFT 0
-#define DMAE_COMMAND_DST (0x3<<1)
-#define DMAE_COMMAND_DST_SHIFT 1
-#define DMAE_COMMAND_C_DST (0x1<<3)
-#define DMAE_COMMAND_C_DST_SHIFT 3
-#define DMAE_COMMAND_C_TYPE_ENABLE (0x1<<4)
-#define DMAE_COMMAND_C_TYPE_ENABLE_SHIFT 4
-#define DMAE_COMMAND_C_TYPE_CRC_ENABLE (0x1<<5)
-#define DMAE_COMMAND_C_TYPE_CRC_ENABLE_SHIFT 5
-#define DMAE_COMMAND_C_TYPE_CRC_OFFSET (0x7<<6)
-#define DMAE_COMMAND_C_TYPE_CRC_OFFSET_SHIFT 6
-#define DMAE_COMMAND_ENDIANITY (0x3<<9)
-#define DMAE_COMMAND_ENDIANITY_SHIFT 9
-#define DMAE_COMMAND_PORT (0x1<<11)
-#define DMAE_COMMAND_PORT_SHIFT 11
-#define DMAE_COMMAND_CRC_RESET (0x1<<12)
-#define DMAE_COMMAND_CRC_RESET_SHIFT 12
-#define DMAE_COMMAND_SRC_RESET (0x1<<13)
-#define DMAE_COMMAND_SRC_RESET_SHIFT 13
-#define DMAE_COMMAND_DST_RESET (0x1<<14)
-#define DMAE_COMMAND_DST_RESET_SHIFT 14
-#define DMAE_COMMAND_E1HVN (0x3<<15)
-#define DMAE_COMMAND_E1HVN_SHIFT 15
-#define DMAE_COMMAND_DST_VN (0x3<<17)
-#define DMAE_COMMAND_DST_VN_SHIFT 17
-#define DMAE_COMMAND_C_FUNC (0x1<<19)
-#define DMAE_COMMAND_C_FUNC_SHIFT 19
-#define DMAE_COMMAND_ERR_POLICY (0x3<<20)
-#define DMAE_COMMAND_ERR_POLICY_SHIFT 20
-#define DMAE_COMMAND_RESERVED0 (0x3FF<<22)
-#define DMAE_COMMAND_RESERVED0_SHIFT 22
- u32 src_addr_lo;
- u32 src_addr_hi;
- u32 dst_addr_lo;
- u32 dst_addr_hi;
-#if defined(__BIG_ENDIAN)
- u16 reserved1;
- u16 len;
-#elif defined(__LITTLE_ENDIAN)
- u16 len;
- u16 reserved1;
-#endif
- u32 comp_addr_lo;
- u32 comp_addr_hi;
- u32 comp_val;
- u32 crc32;
- u32 crc32_c;
-#if defined(__BIG_ENDIAN)
- u16 crc16_c;
- u16 crc16;
-#elif defined(__LITTLE_ENDIAN)
- u16 crc16;
- u16 crc16_c;
-#endif
-#if defined(__BIG_ENDIAN)
- u16 reserved3;
- u16 crc_t10;
-#elif defined(__LITTLE_ENDIAN)
- u16 crc_t10;
- u16 reserved3;
-#endif
-#if defined(__BIG_ENDIAN)
- u16 xsum8;
- u16 xsum16;
-#elif defined(__LITTLE_ENDIAN)
- u16 xsum16;
- u16 xsum8;
-#endif
+enum prs_flags_eth_addr_type {
+ PRS_FLAG_ETHTYPE_NON_UNICAST,
+ PRS_FLAG_ETHTYPE_UNICAST,
+ MAX_PRS_FLAGS_ETH_ADDR_TYPE
};
-struct double_regpair {
- u32 regpair0_lo;
- u32 regpair0_hi;
- u32 regpair1_lo;
- u32 regpair1_hi;
+/*
+ * Parsing flags for over-ethernet protocol
+ */
+enum prs_flags_over_eth {
+ PRS_FLAG_OVERETH_UNKNOWN,
+ PRS_FLAG_OVERETH_IPV4,
+ PRS_FLAG_OVERETH_IPV6,
+ PRS_FLAG_OVERETH_LLCSNAP_UNKNOWN,
+ MAX_PRS_FLAGS_OVER_ETH
+};
+
+
+/*
+ * Parsing flags for over-IP protocol
+ */
+enum prs_flags_over_ip {
+ PRS_FLAG_OVERIP_UNKNOWN,
+ PRS_FLAG_OVERIP_TCP,
+ PRS_FLAG_OVERIP_UDP,
+ MAX_PRS_FLAGS_OVER_IP
};
@@ -2297,55 +3003,24 @@
#define SDM_OP_GEN_RESERVED_SHIFT 17
};
-/*
- * The eth Rx Buffer Descriptor
- */
-struct eth_rx_bd {
- __le32 addr_lo;
- __le32 addr_hi;
-};
/*
- * The eth Rx SGE Descriptor
+ * Timers connection context
*/
-struct eth_rx_sge {
- __le32 addr_lo;
- __le32 addr_hi;
+struct timers_block_context {
+ u32 __reserved_0;
+ u32 __reserved_1;
+ u32 __reserved_2;
+ u32 flags;
+#define __TIMERS_BLOCK_CONTEXT_NUM_OF_ACTIVE_TIMERS (0x3<<0)
+#define __TIMERS_BLOCK_CONTEXT_NUM_OF_ACTIVE_TIMERS_SHIFT 0
+#define TIMERS_BLOCK_CONTEXT_CONN_VALID_FLG (0x1<<2)
+#define TIMERS_BLOCK_CONTEXT_CONN_VALID_FLG_SHIFT 2
+#define __TIMERS_BLOCK_CONTEXT_RESERVED0 (0x1FFFFFFF<<3)
+#define __TIMERS_BLOCK_CONTEXT_RESERVED0_SHIFT 3
};
-
-/*
- * The eth storm context of Ustorm
- */
-struct ustorm_eth_st_context {
- u32 reserved0[48];
-};
-
-/*
- * The eth storm context of Tstorm
- */
-struct tstorm_eth_st_context {
- u32 __reserved0[28];
-};
-
-/*
- * The eth aggregative context of Xstorm
- */
-struct xstorm_eth_ag_context {
- u32 reserved0;
-#if defined(__BIG_ENDIAN)
- u8 cdu_reserved;
- u8 reserved2;
- u16 reserved1;
-#elif defined(__LITTLE_ENDIAN)
- u16 reserved1;
- u8 reserved2;
- u8 cdu_reserved;
-#endif
- u32 reserved3[30];
-};
-
/*
* The eth aggregative context of Tstorm
*/
@@ -2355,14 +3030,6 @@
/*
- * The eth aggregative context of Cstorm
- */
-struct cstorm_eth_ag_context {
- u32 __reserved0[10];
-};
-
-
-/*
* The eth aggregative context of Ustorm
*/
struct ustorm_eth_ag_context {
@@ -2379,22 +3046,808 @@
u32 __reserved3[6];
};
+
/*
- * Timers connection context
+ * The eth aggregative context of Xstorm
*/
-struct timers_block_context {
- u32 __reserved_0;
- u32 __reserved_1;
- u32 __reserved_2;
- u32 flags;
-#define __TIMERS_BLOCK_CONTEXT_NUM_OF_ACTIVE_TIMERS (0x3<<0)
-#define __TIMERS_BLOCK_CONTEXT_NUM_OF_ACTIVE_TIMERS_SHIFT 0
-#define TIMERS_BLOCK_CONTEXT_CONN_VALID_FLG (0x1<<2)
-#define TIMERS_BLOCK_CONTEXT_CONN_VALID_FLG_SHIFT 2
-#define __TIMERS_BLOCK_CONTEXT_RESERVED0 (0x1FFFFFFF<<3)
-#define __TIMERS_BLOCK_CONTEXT_RESERVED0_SHIFT 3
+struct xstorm_eth_ag_context {
+ u32 reserved0;
+#if defined(__BIG_ENDIAN)
+ u8 cdu_reserved;
+ u8 reserved2;
+ u16 reserved1;
+#elif defined(__LITTLE_ENDIAN)
+ u16 reserved1;
+ u8 reserved2;
+ u8 cdu_reserved;
+#endif
+ u32 reserved3[30];
};
+
+/*
+ * doorbell message sent to the chip
+ */
+struct doorbell {
+#if defined(__BIG_ENDIAN)
+ u16 zero_fill2;
+ u8 zero_fill1;
+ struct doorbell_hdr header;
+#elif defined(__LITTLE_ENDIAN)
+ struct doorbell_hdr header;
+ u8 zero_fill1;
+ u16 zero_fill2;
+#endif
+};
+
+
+/*
+ * doorbell message sent to the chip
+ */
+struct doorbell_set_prod {
+#if defined(__BIG_ENDIAN)
+ u16 prod;
+ u8 zero_fill1;
+ struct doorbell_hdr header;
+#elif defined(__LITTLE_ENDIAN)
+ struct doorbell_hdr header;
+ u8 zero_fill1;
+ u16 prod;
+#endif
+};
+
+
+struct regpair {
+ __le32 lo;
+ __le32 hi;
+};
+
+
+/*
+ * Classify rule opcodes in E2/E3
+ */
+enum classify_rule {
+ CLASSIFY_RULE_OPCODE_MAC,
+ CLASSIFY_RULE_OPCODE_VLAN,
+ CLASSIFY_RULE_OPCODE_PAIR,
+ MAX_CLASSIFY_RULE
+};
+
+
+/*
+ * Classify rule types in E2/E3
+ */
+enum classify_rule_action_type {
+ CLASSIFY_RULE_REMOVE,
+ CLASSIFY_RULE_ADD,
+ MAX_CLASSIFY_RULE_ACTION_TYPE
+};
+
+
+/*
+ * client init ramrod data
+ */
+struct client_init_general_data {
+ u8 client_id;
+ u8 statistics_counter_id;
+ u8 statistics_en_flg;
+ u8 is_fcoe_flg;
+ u8 activate_flg;
+ u8 sp_client_id;
+ __le16 mtu;
+ u8 statistics_zero_flg;
+ u8 func_id;
+ u8 cos;
+ u8 traffic_type;
+ u32 reserved0;
+};
+
+
+/*
+ * client init rx data
+ */
+struct client_init_rx_data {
+ u8 tpa_en;
+#define CLIENT_INIT_RX_DATA_TPA_EN_IPV4 (0x1<<0)
+#define CLIENT_INIT_RX_DATA_TPA_EN_IPV4_SHIFT 0
+#define CLIENT_INIT_RX_DATA_TPA_EN_IPV6 (0x1<<1)
+#define CLIENT_INIT_RX_DATA_TPA_EN_IPV6_SHIFT 1
+#define CLIENT_INIT_RX_DATA_RESERVED5 (0x3F<<2)
+#define CLIENT_INIT_RX_DATA_RESERVED5_SHIFT 2
+ u8 vmqueue_mode_en_flg;
+ u8 extra_data_over_sgl_en_flg;
+ u8 cache_line_alignment_log_size;
+ u8 enable_dynamic_hc;
+ u8 max_sges_for_packet;
+ u8 client_qzone_id;
+ u8 drop_ip_cs_err_flg;
+ u8 drop_tcp_cs_err_flg;
+ u8 drop_ttl0_flg;
+ u8 drop_udp_cs_err_flg;
+ u8 inner_vlan_removal_enable_flg;
+ u8 outer_vlan_removal_enable_flg;
+ u8 status_block_id;
+ u8 rx_sb_index_number;
+ u8 reserved0;
+ u8 max_tpa_queues;
+ u8 silent_vlan_removal_flg;
+ __le16 max_bytes_on_bd;
+ __le16 sge_buff_size;
+ u8 approx_mcast_engine_id;
+ u8 rss_engine_id;
+ struct regpair bd_page_base;
+ struct regpair sge_page_base;
+ struct regpair cqe_page_base;
+ u8 is_leading_rss;
+ u8 is_approx_mcast;
+ __le16 max_agg_size;
+ __le16 state;
+#define CLIENT_INIT_RX_DATA_UCAST_DROP_ALL (0x1<<0)
+#define CLIENT_INIT_RX_DATA_UCAST_DROP_ALL_SHIFT 0
+#define CLIENT_INIT_RX_DATA_UCAST_ACCEPT_ALL (0x1<<1)
+#define CLIENT_INIT_RX_DATA_UCAST_ACCEPT_ALL_SHIFT 1
+#define CLIENT_INIT_RX_DATA_UCAST_ACCEPT_UNMATCHED (0x1<<2)
+#define CLIENT_INIT_RX_DATA_UCAST_ACCEPT_UNMATCHED_SHIFT 2
+#define CLIENT_INIT_RX_DATA_MCAST_DROP_ALL (0x1<<3)
+#define CLIENT_INIT_RX_DATA_MCAST_DROP_ALL_SHIFT 3
+#define CLIENT_INIT_RX_DATA_MCAST_ACCEPT_ALL (0x1<<4)
+#define CLIENT_INIT_RX_DATA_MCAST_ACCEPT_ALL_SHIFT 4
+#define CLIENT_INIT_RX_DATA_BCAST_ACCEPT_ALL (0x1<<5)
+#define CLIENT_INIT_RX_DATA_BCAST_ACCEPT_ALL_SHIFT 5
+#define CLIENT_INIT_RX_DATA_ACCEPT_ANY_VLAN (0x1<<6)
+#define CLIENT_INIT_RX_DATA_ACCEPT_ANY_VLAN_SHIFT 6
+#define CLIENT_INIT_RX_DATA_RESERVED2 (0x1FF<<7)
+#define CLIENT_INIT_RX_DATA_RESERVED2_SHIFT 7
+ __le16 cqe_pause_thr_low;
+ __le16 cqe_pause_thr_high;
+ __le16 bd_pause_thr_low;
+ __le16 bd_pause_thr_high;
+ __le16 sge_pause_thr_low;
+ __le16 sge_pause_thr_high;
+ __le16 rx_cos_mask;
+ __le16 silent_vlan_value;
+ __le16 silent_vlan_mask;
+ __le32 reserved6[2];
+};
+
+/*
+ * client init tx data
+ */
+struct client_init_tx_data {
+ u8 enforce_security_flg;
+ u8 tx_status_block_id;
+ u8 tx_sb_index_number;
+ u8 tss_leading_client_id;
+ u8 tx_switching_flg;
+ u8 anti_spoofing_flg;
+ __le16 default_vlan;
+ struct regpair tx_bd_page_base;
+ __le16 state;
+#define CLIENT_INIT_TX_DATA_UCAST_ACCEPT_ALL (0x1<<0)
+#define CLIENT_INIT_TX_DATA_UCAST_ACCEPT_ALL_SHIFT 0
+#define CLIENT_INIT_TX_DATA_MCAST_ACCEPT_ALL (0x1<<1)
+#define CLIENT_INIT_TX_DATA_MCAST_ACCEPT_ALL_SHIFT 1
+#define CLIENT_INIT_TX_DATA_BCAST_ACCEPT_ALL (0x1<<2)
+#define CLIENT_INIT_TX_DATA_BCAST_ACCEPT_ALL_SHIFT 2
+#define CLIENT_INIT_TX_DATA_ACCEPT_ANY_VLAN (0x1<<3)
+#define CLIENT_INIT_TX_DATA_ACCEPT_ANY_VLAN_SHIFT 3
+#define CLIENT_INIT_TX_DATA_RESERVED1 (0xFFF<<4)
+#define CLIENT_INIT_TX_DATA_RESERVED1_SHIFT 4
+ u8 default_vlan_flg;
+ u8 reserved2;
+ __le32 reserved3;
+};
+
+/*
+ * client init ramrod data
+ */
+struct client_init_ramrod_data {
+ struct client_init_general_data general;
+ struct client_init_rx_data rx;
+ struct client_init_tx_data tx;
+};
+
+
+/*
+ * client update ramrod data
+ */
+struct client_update_ramrod_data {
+ u8 client_id;
+ u8 func_id;
+ u8 inner_vlan_removal_enable_flg;
+ u8 inner_vlan_removal_change_flg;
+ u8 outer_vlan_removal_enable_flg;
+ u8 outer_vlan_removal_change_flg;
+ u8 anti_spoofing_enable_flg;
+ u8 anti_spoofing_change_flg;
+ u8 activate_flg;
+ u8 activate_change_flg;
+ __le16 default_vlan;
+ u8 default_vlan_enable_flg;
+ u8 default_vlan_change_flg;
+ __le16 silent_vlan_value;
+ __le16 silent_vlan_mask;
+ u8 silent_vlan_removal_flg;
+ u8 silent_vlan_change_flg;
+ __le32 echo;
+};
+
+
+/*
+ * The eth storm context of Cstorm
+ */
+struct cstorm_eth_st_context {
+ u32 __reserved0[4];
+};
+
+
+struct double_regpair {
+ u32 regpair0_lo;
+ u32 regpair0_hi;
+ u32 regpair1_lo;
+ u32 regpair1_hi;
+};
+
+
+/*
+ * Ethernet address typesm used in ethernet tx BDs
+ */
+enum eth_addr_type {
+ UNKNOWN_ADDRESS,
+ UNICAST_ADDRESS,
+ MULTICAST_ADDRESS,
+ BROADCAST_ADDRESS,
+ MAX_ETH_ADDR_TYPE
+};
+
+
+/*
+ *
+ */
+struct eth_classify_cmd_header {
+ u8 cmd_general_data;
+#define ETH_CLASSIFY_CMD_HEADER_RX_CMD (0x1<<0)
+#define ETH_CLASSIFY_CMD_HEADER_RX_CMD_SHIFT 0
+#define ETH_CLASSIFY_CMD_HEADER_TX_CMD (0x1<<1)
+#define ETH_CLASSIFY_CMD_HEADER_TX_CMD_SHIFT 1
+#define ETH_CLASSIFY_CMD_HEADER_OPCODE (0x3<<2)
+#define ETH_CLASSIFY_CMD_HEADER_OPCODE_SHIFT 2
+#define ETH_CLASSIFY_CMD_HEADER_IS_ADD (0x1<<4)
+#define ETH_CLASSIFY_CMD_HEADER_IS_ADD_SHIFT 4
+#define ETH_CLASSIFY_CMD_HEADER_RESERVED0 (0x7<<5)
+#define ETH_CLASSIFY_CMD_HEADER_RESERVED0_SHIFT 5
+ u8 func_id;
+ u8 client_id;
+ u8 reserved1;
+};
+
+
+/*
+ * header for eth classification config ramrod
+ */
+struct eth_classify_header {
+ u8 rule_cnt;
+ u8 reserved0;
+ __le16 reserved1;
+ __le32 echo;
+};
+
+
+/*
+ * Command for adding/removing a MAC classification rule
+ */
+struct eth_classify_mac_cmd {
+ struct eth_classify_cmd_header header;
+ __le32 reserved0;
+ __le16 mac_lsb;
+ __le16 mac_mid;
+ __le16 mac_msb;
+ __le16 reserved1;
+};
+
+
+/*
+ * Command for adding/removing a MAC-VLAN pair classification rule
+ */
+struct eth_classify_pair_cmd {
+ struct eth_classify_cmd_header header;
+ __le32 reserved0;
+ __le16 mac_lsb;
+ __le16 mac_mid;
+ __le16 mac_msb;
+ __le16 vlan;
+};
+
+
+/*
+ * Command for adding/removing a VLAN classification rule
+ */
+struct eth_classify_vlan_cmd {
+ struct eth_classify_cmd_header header;
+ __le32 reserved0;
+ __le32 reserved1;
+ __le16 reserved2;
+ __le16 vlan;
+};
+
+/*
+ * union for eth classification rule
+ */
+union eth_classify_rule_cmd {
+ struct eth_classify_mac_cmd mac;
+ struct eth_classify_vlan_cmd vlan;
+ struct eth_classify_pair_cmd pair;
+};
+
+/*
+ * parameters for eth classification configuration ramrod
+ */
+struct eth_classify_rules_ramrod_data {
+ struct eth_classify_header header;
+ union eth_classify_rule_cmd rules[CLASSIFY_RULES_COUNT];
+};
+
+
+/*
+ * The data contain client ID need to the ramrod
+ */
+struct eth_common_ramrod_data {
+ __le32 client_id;
+ __le32 reserved1;
+};
+
+
+/*
+ * The eth storm context of Ustorm
+ */
+struct ustorm_eth_st_context {
+ u32 reserved0[52];
+};
+
+/*
+ * The eth storm context of Tstorm
+ */
+struct tstorm_eth_st_context {
+ u32 __reserved0[28];
+};
+
+/*
+ * The eth storm context of Xstorm
+ */
+struct xstorm_eth_st_context {
+ u32 reserved0[60];
+};
+
+/*
+ * Ethernet connection context
+ */
+struct eth_context {
+ struct ustorm_eth_st_context ustorm_st_context;
+ struct tstorm_eth_st_context tstorm_st_context;
+ struct xstorm_eth_ag_context xstorm_ag_context;
+ struct tstorm_eth_ag_context tstorm_ag_context;
+ struct cstorm_eth_ag_context cstorm_ag_context;
+ struct ustorm_eth_ag_context ustorm_ag_context;
+ struct timers_block_context timers_context;
+ struct xstorm_eth_st_context xstorm_st_context;
+ struct cstorm_eth_st_context cstorm_st_context;
+};
+
+
+/*
+ * union for sgl and raw data.
+ */
+union eth_sgl_or_raw_data {
+ __le16 sgl[8];
+ u32 raw_data[4];
+};
+
+/*
+ * eth FP end aggregation CQE parameters struct
+ */
+struct eth_end_agg_rx_cqe {
+ u8 type_error_flags;
+#define ETH_END_AGG_RX_CQE_TYPE (0x3<<0)
+#define ETH_END_AGG_RX_CQE_TYPE_SHIFT 0
+#define ETH_END_AGG_RX_CQE_SGL_RAW_SEL (0x1<<2)
+#define ETH_END_AGG_RX_CQE_SGL_RAW_SEL_SHIFT 2
+#define ETH_END_AGG_RX_CQE_RESERVED0 (0x1F<<3)
+#define ETH_END_AGG_RX_CQE_RESERVED0_SHIFT 3
+ u8 reserved1;
+ u8 queue_index;
+ u8 reserved2;
+ __le32 timestamp_delta;
+ __le16 num_of_coalesced_segs;
+ __le16 pkt_len;
+ u8 pure_ack_count;
+ u8 reserved3;
+ __le16 reserved4;
+ union eth_sgl_or_raw_data sgl_or_raw_data;
+ __le32 reserved5[8];
+};
+
+
+/*
+ * regular eth FP CQE parameters struct
+ */
+struct eth_fast_path_rx_cqe {
+ u8 type_error_flags;
+#define ETH_FAST_PATH_RX_CQE_TYPE (0x3<<0)
+#define ETH_FAST_PATH_RX_CQE_TYPE_SHIFT 0
+#define ETH_FAST_PATH_RX_CQE_SGL_RAW_SEL (0x1<<2)
+#define ETH_FAST_PATH_RX_CQE_SGL_RAW_SEL_SHIFT 2
+#define ETH_FAST_PATH_RX_CQE_PHY_DECODE_ERR_FLG (0x1<<3)
+#define ETH_FAST_PATH_RX_CQE_PHY_DECODE_ERR_FLG_SHIFT 3
+#define ETH_FAST_PATH_RX_CQE_IP_BAD_XSUM_FLG (0x1<<4)
+#define ETH_FAST_PATH_RX_CQE_IP_BAD_XSUM_FLG_SHIFT 4
+#define ETH_FAST_PATH_RX_CQE_L4_BAD_XSUM_FLG (0x1<<5)
+#define ETH_FAST_PATH_RX_CQE_L4_BAD_XSUM_FLG_SHIFT 5
+#define ETH_FAST_PATH_RX_CQE_RESERVED0 (0x3<<6)
+#define ETH_FAST_PATH_RX_CQE_RESERVED0_SHIFT 6
+ u8 status_flags;
+#define ETH_FAST_PATH_RX_CQE_RSS_HASH_TYPE (0x7<<0)
+#define ETH_FAST_PATH_RX_CQE_RSS_HASH_TYPE_SHIFT 0
+#define ETH_FAST_PATH_RX_CQE_RSS_HASH_FLG (0x1<<3)
+#define ETH_FAST_PATH_RX_CQE_RSS_HASH_FLG_SHIFT 3
+#define ETH_FAST_PATH_RX_CQE_BROADCAST_FLG (0x1<<4)
+#define ETH_FAST_PATH_RX_CQE_BROADCAST_FLG_SHIFT 4
+#define ETH_FAST_PATH_RX_CQE_MAC_MATCH_FLG (0x1<<5)
+#define ETH_FAST_PATH_RX_CQE_MAC_MATCH_FLG_SHIFT 5
+#define ETH_FAST_PATH_RX_CQE_IP_XSUM_NO_VALIDATION_FLG (0x1<<6)
+#define ETH_FAST_PATH_RX_CQE_IP_XSUM_NO_VALIDATION_FLG_SHIFT 6
+#define ETH_FAST_PATH_RX_CQE_L4_XSUM_NO_VALIDATION_FLG (0x1<<7)
+#define ETH_FAST_PATH_RX_CQE_L4_XSUM_NO_VALIDATION_FLG_SHIFT 7
+ u8 queue_index;
+ u8 placement_offset;
+ __le32 rss_hash_result;
+ __le16 vlan_tag;
+ __le16 pkt_len;
+ __le16 len_on_bd;
+ struct parsing_flags pars_flags;
+ union eth_sgl_or_raw_data sgl_or_raw_data;
+ __le32 reserved1[8];
+};
+
+
+/*
+ * Command for setting classification flags for a client
+ */
+struct eth_filter_rules_cmd {
+ u8 cmd_general_data;
+#define ETH_FILTER_RULES_CMD_RX_CMD (0x1<<0)
+#define ETH_FILTER_RULES_CMD_RX_CMD_SHIFT 0
+#define ETH_FILTER_RULES_CMD_TX_CMD (0x1<<1)
+#define ETH_FILTER_RULES_CMD_TX_CMD_SHIFT 1
+#define ETH_FILTER_RULES_CMD_RESERVED0 (0x3F<<2)
+#define ETH_FILTER_RULES_CMD_RESERVED0_SHIFT 2
+ u8 func_id;
+ u8 client_id;
+ u8 reserved1;
+ __le16 state;
+#define ETH_FILTER_RULES_CMD_UCAST_DROP_ALL (0x1<<0)
+#define ETH_FILTER_RULES_CMD_UCAST_DROP_ALL_SHIFT 0
+#define ETH_FILTER_RULES_CMD_UCAST_ACCEPT_ALL (0x1<<1)
+#define ETH_FILTER_RULES_CMD_UCAST_ACCEPT_ALL_SHIFT 1
+#define ETH_FILTER_RULES_CMD_UCAST_ACCEPT_UNMATCHED (0x1<<2)
+#define ETH_FILTER_RULES_CMD_UCAST_ACCEPT_UNMATCHED_SHIFT 2
+#define ETH_FILTER_RULES_CMD_MCAST_DROP_ALL (0x1<<3)
+#define ETH_FILTER_RULES_CMD_MCAST_DROP_ALL_SHIFT 3
+#define ETH_FILTER_RULES_CMD_MCAST_ACCEPT_ALL (0x1<<4)
+#define ETH_FILTER_RULES_CMD_MCAST_ACCEPT_ALL_SHIFT 4
+#define ETH_FILTER_RULES_CMD_BCAST_ACCEPT_ALL (0x1<<5)
+#define ETH_FILTER_RULES_CMD_BCAST_ACCEPT_ALL_SHIFT 5
+#define ETH_FILTER_RULES_CMD_ACCEPT_ANY_VLAN (0x1<<6)
+#define ETH_FILTER_RULES_CMD_ACCEPT_ANY_VLAN_SHIFT 6
+#define ETH_FILTER_RULES_CMD_RESERVED2 (0x1FF<<7)
+#define ETH_FILTER_RULES_CMD_RESERVED2_SHIFT 7
+ __le16 reserved3;
+ struct regpair reserved4;
+};
+
+
+/*
+ * parameters for eth classification filters ramrod
+ */
+struct eth_filter_rules_ramrod_data {
+ struct eth_classify_header header;
+ struct eth_filter_rules_cmd rules[FILTER_RULES_COUNT];
+};
+
+
+/*
+ * parameters for eth classification configuration ramrod
+ */
+struct eth_general_rules_ramrod_data {
+ struct eth_classify_header header;
+ union eth_classify_rule_cmd rules[CLASSIFY_RULES_COUNT];
+};
+
+
+/*
+ * The data for Halt ramrod
+ */
+struct eth_halt_ramrod_data {
+ __le32 client_id;
+ __le32 reserved0;
+};
+
+
+/*
+ * Command for setting multicast classification for a client
+ */
+struct eth_multicast_rules_cmd {
+ u8 cmd_general_data;
+#define ETH_MULTICAST_RULES_CMD_RX_CMD (0x1<<0)
+#define ETH_MULTICAST_RULES_CMD_RX_CMD_SHIFT 0
+#define ETH_MULTICAST_RULES_CMD_TX_CMD (0x1<<1)
+#define ETH_MULTICAST_RULES_CMD_TX_CMD_SHIFT 1
+#define ETH_MULTICAST_RULES_CMD_IS_ADD (0x1<<2)
+#define ETH_MULTICAST_RULES_CMD_IS_ADD_SHIFT 2
+#define ETH_MULTICAST_RULES_CMD_RESERVED0 (0x1F<<3)
+#define ETH_MULTICAST_RULES_CMD_RESERVED0_SHIFT 3
+ u8 func_id;
+ u8 bin_id;
+ u8 engine_id;
+ __le32 reserved2;
+ struct regpair reserved3;
+};
+
+
+/*
+ * parameters for multicast classification ramrod
+ */
+struct eth_multicast_rules_ramrod_data {
+ struct eth_classify_header header;
+ struct eth_multicast_rules_cmd rules[MULTICAST_RULES_COUNT];
+};
+
+
+/*
+ * Place holder for ramrods protocol specific data
+ */
+struct ramrod_data {
+ __le32 data_lo;
+ __le32 data_hi;
+};
+
+/*
+ * union for ramrod data for Ethernet protocol (CQE) (force size of 16 bits)
+ */
+union eth_ramrod_data {
+ struct ramrod_data general;
+};
+
+
+/*
+ * RSS toeplitz hash type, as reported in CQE
+ */
+enum eth_rss_hash_type {
+ DEFAULT_HASH_TYPE,
+ IPV4_HASH_TYPE,
+ TCP_IPV4_HASH_TYPE,
+ IPV6_HASH_TYPE,
+ TCP_IPV6_HASH_TYPE,
+ VLAN_PRI_HASH_TYPE,
+ E1HOV_PRI_HASH_TYPE,
+ DSCP_HASH_TYPE,
+ MAX_ETH_RSS_HASH_TYPE
+};
+
+
+/*
+ * Ethernet RSS mode
+ */
+enum eth_rss_mode {
+ ETH_RSS_MODE_DISABLED,
+ ETH_RSS_MODE_REGULAR,
+ ETH_RSS_MODE_VLAN_PRI,
+ ETH_RSS_MODE_E1HOV_PRI,
+ ETH_RSS_MODE_IP_DSCP,
+ MAX_ETH_RSS_MODE
+};
+
+
+/*
+ * parameters for RSS update ramrod (E2)
+ */
+struct eth_rss_update_ramrod_data {
+ u8 rss_engine_id;
+ u8 capabilities;
+#define ETH_RSS_UPDATE_RAMROD_DATA_IPV4_CAPABILITY (0x1<<0)
+#define ETH_RSS_UPDATE_RAMROD_DATA_IPV4_CAPABILITY_SHIFT 0
+#define ETH_RSS_UPDATE_RAMROD_DATA_IPV4_TCP_CAPABILITY (0x1<<1)
+#define ETH_RSS_UPDATE_RAMROD_DATA_IPV4_TCP_CAPABILITY_SHIFT 1
+#define ETH_RSS_UPDATE_RAMROD_DATA_IPV4_UDP_CAPABILITY (0x1<<2)
+#define ETH_RSS_UPDATE_RAMROD_DATA_IPV4_UDP_CAPABILITY_SHIFT 2
+#define ETH_RSS_UPDATE_RAMROD_DATA_IPV6_CAPABILITY (0x1<<3)
+#define ETH_RSS_UPDATE_RAMROD_DATA_IPV6_CAPABILITY_SHIFT 3
+#define ETH_RSS_UPDATE_RAMROD_DATA_IPV6_TCP_CAPABILITY (0x1<<4)
+#define ETH_RSS_UPDATE_RAMROD_DATA_IPV6_TCP_CAPABILITY_SHIFT 4
+#define ETH_RSS_UPDATE_RAMROD_DATA_IPV6_UDP_CAPABILITY (0x1<<5)
+#define ETH_RSS_UPDATE_RAMROD_DATA_IPV6_UDP_CAPABILITY_SHIFT 5
+#define ETH_RSS_UPDATE_RAMROD_DATA_UPDATE_RSS_KEY (0x1<<6)
+#define ETH_RSS_UPDATE_RAMROD_DATA_UPDATE_RSS_KEY_SHIFT 6
+#define __ETH_RSS_UPDATE_RAMROD_DATA_RESERVED0 (0x1<<7)
+#define __ETH_RSS_UPDATE_RAMROD_DATA_RESERVED0_SHIFT 7
+ u8 rss_result_mask;
+ u8 rss_mode;
+ __le32 __reserved2;
+ u8 indirection_table[T_ETH_INDIRECTION_TABLE_SIZE];
+ __le32 rss_key[T_ETH_RSS_KEY];
+ __le32 echo;
+ __le32 reserved3;
+};
+
+
+/*
+ * The eth Rx Buffer Descriptor
+ */
+struct eth_rx_bd {
+ __le32 addr_lo;
+ __le32 addr_hi;
+};
+
+
+/*
+ * Eth Rx Cqe structure- general structure for ramrods
+ */
+struct common_ramrod_eth_rx_cqe {
+ u8 ramrod_type;
+#define COMMON_RAMROD_ETH_RX_CQE_TYPE (0x3<<0)
+#define COMMON_RAMROD_ETH_RX_CQE_TYPE_SHIFT 0
+#define COMMON_RAMROD_ETH_RX_CQE_ERROR (0x1<<2)
+#define COMMON_RAMROD_ETH_RX_CQE_ERROR_SHIFT 2
+#define COMMON_RAMROD_ETH_RX_CQE_RESERVED0 (0x1F<<3)
+#define COMMON_RAMROD_ETH_RX_CQE_RESERVED0_SHIFT 3
+ u8 conn_type;
+ __le16 reserved1;
+ __le32 conn_and_cmd_data;
+#define COMMON_RAMROD_ETH_RX_CQE_CID (0xFFFFFF<<0)
+#define COMMON_RAMROD_ETH_RX_CQE_CID_SHIFT 0
+#define COMMON_RAMROD_ETH_RX_CQE_CMD_ID (0xFF<<24)
+#define COMMON_RAMROD_ETH_RX_CQE_CMD_ID_SHIFT 24
+ struct ramrod_data protocol_data;
+ __le32 echo;
+ __le32 reserved2[11];
+};
+
+/*
+ * Rx Last CQE in page (in ETH)
+ */
+struct eth_rx_cqe_next_page {
+ __le32 addr_lo;
+ __le32 addr_hi;
+ __le32 reserved[14];
+};
+
+/*
+ * union for all eth rx cqe types (fix their sizes)
+ */
+union eth_rx_cqe {
+ struct eth_fast_path_rx_cqe fast_path_cqe;
+ struct common_ramrod_eth_rx_cqe ramrod_cqe;
+ struct eth_rx_cqe_next_page next_page_cqe;
+ struct eth_end_agg_rx_cqe end_agg_cqe;
+};
+
+
+/*
+ * Values for RX ETH CQE type field
+ */
+enum eth_rx_cqe_type {
+ RX_ETH_CQE_TYPE_ETH_FASTPATH,
+ RX_ETH_CQE_TYPE_ETH_RAMROD,
+ RX_ETH_CQE_TYPE_ETH_START_AGG,
+ RX_ETH_CQE_TYPE_ETH_STOP_AGG,
+ MAX_ETH_RX_CQE_TYPE
+};
+
+
+/*
+ * Type of SGL/Raw field in ETH RX fast path CQE
+ */
+enum eth_rx_fp_sel {
+ ETH_FP_CQE_REGULAR,
+ ETH_FP_CQE_RAW,
+ MAX_ETH_RX_FP_SEL
+};
+
+
+/*
+ * The eth Rx SGE Descriptor
+ */
+struct eth_rx_sge {
+ __le32 addr_lo;
+ __le32 addr_hi;
+};
+
+
+/*
+ * common data for all protocols
+ */
+struct spe_hdr {
+ __le32 conn_and_cmd_data;
+#define SPE_HDR_CID (0xFFFFFF<<0)
+#define SPE_HDR_CID_SHIFT 0
+#define SPE_HDR_CMD_ID (0xFF<<24)
+#define SPE_HDR_CMD_ID_SHIFT 24
+ __le16 type;
+#define SPE_HDR_CONN_TYPE (0xFF<<0)
+#define SPE_HDR_CONN_TYPE_SHIFT 0
+#define SPE_HDR_FUNCTION_ID (0xFF<<8)
+#define SPE_HDR_FUNCTION_ID_SHIFT 8
+ __le16 reserved1;
+};
+
+/*
+ * specific data for ethernet slow path element
+ */
+union eth_specific_data {
+ u8 protocol_data[8];
+ struct regpair client_update_ramrod_data;
+ struct regpair client_init_ramrod_init_data;
+ struct eth_halt_ramrod_data halt_ramrod_data;
+ struct regpair update_data_addr;
+ struct eth_common_ramrod_data common_ramrod_data;
+ struct regpair classify_cfg_addr;
+ struct regpair filter_cfg_addr;
+ struct regpair mcast_cfg_addr;
+};
+
+/*
+ * Ethernet slow path element
+ */
+struct eth_spe {
+ struct spe_hdr hdr;
+ union eth_specific_data data;
+};
+
+
+/*
+ * Ethernet command ID for slow path elements
+ */
+enum eth_spqe_cmd_id {
+ RAMROD_CMD_ID_ETH_UNUSED,
+ RAMROD_CMD_ID_ETH_CLIENT_SETUP,
+ RAMROD_CMD_ID_ETH_HALT,
+ RAMROD_CMD_ID_ETH_FORWARD_SETUP,
+ RAMROD_CMD_ID_ETH_TX_QUEUE_SETUP,
+ RAMROD_CMD_ID_ETH_CLIENT_UPDATE,
+ RAMROD_CMD_ID_ETH_EMPTY,
+ RAMROD_CMD_ID_ETH_TERMINATE,
+ RAMROD_CMD_ID_ETH_TPA_UPDATE,
+ RAMROD_CMD_ID_ETH_CLASSIFICATION_RULES,
+ RAMROD_CMD_ID_ETH_FILTER_RULES,
+ RAMROD_CMD_ID_ETH_MULTICAST_RULES,
+ RAMROD_CMD_ID_ETH_RSS_UPDATE,
+ RAMROD_CMD_ID_ETH_SET_MAC,
+ MAX_ETH_SPQE_CMD_ID
+};
+
+
+/*
+ * eth tpa update command
+ */
+enum eth_tpa_update_command {
+ TPA_UPDATE_NONE_COMMAND,
+ TPA_UPDATE_ENABLE_COMMAND,
+ TPA_UPDATE_DISABLE_COMMAND,
+ MAX_ETH_TPA_UPDATE_COMMAND
+};
+
+
+/*
+ * Tx regular BD structure
+ */
+struct eth_tx_bd {
+ __le32 addr_lo;
+ __le32 addr_hi;
+ __le16 total_pkt_bytes;
+ __le16 nbytes;
+ u8 reserved[4];
+};
+
+
/*
* structure for easy accessibility to assembler
*/
@@ -2427,24 +3880,17 @@
__le16 vlan_or_ethertype;
struct eth_tx_bd_flags bd_flags;
u8 general_data;
-#define ETH_TX_START_BD_HDR_NBDS (0x3F<<0)
+#define ETH_TX_START_BD_HDR_NBDS (0xF<<0)
#define ETH_TX_START_BD_HDR_NBDS_SHIFT 0
+#define ETH_TX_START_BD_FORCE_VLAN_MODE (0x1<<4)
+#define ETH_TX_START_BD_FORCE_VLAN_MODE_SHIFT 4
+#define ETH_TX_START_BD_RESREVED (0x1<<5)
+#define ETH_TX_START_BD_RESREVED_SHIFT 5
#define ETH_TX_START_BD_ETH_ADDR_TYPE (0x3<<6)
#define ETH_TX_START_BD_ETH_ADDR_TYPE_SHIFT 6
};
/*
- * Tx regular BD structure
- */
-struct eth_tx_bd {
- __le32 addr_lo;
- __le32 addr_hi;
- __le16 total_pkt_bytes;
- __le16 nbytes;
- u8 reserved[4];
-};
-
-/*
* Tx parsing BD structure for ETH E1/E1h
*/
struct eth_tx_parse_bd_e1x {
@@ -2526,336 +3972,6 @@
struct eth_tx_next_bd next_bd;
};
-
-/*
- * The eth storm context of Xstorm
- */
-struct xstorm_eth_st_context {
- u32 reserved0[60];
-};
-
-/*
- * The eth storm context of Cstorm
- */
-struct cstorm_eth_st_context {
- u32 __reserved0[4];
-};
-
-/*
- * Ethernet connection context
- */
-struct eth_context {
- struct ustorm_eth_st_context ustorm_st_context;
- struct tstorm_eth_st_context tstorm_st_context;
- struct xstorm_eth_ag_context xstorm_ag_context;
- struct tstorm_eth_ag_context tstorm_ag_context;
- struct cstorm_eth_ag_context cstorm_ag_context;
- struct ustorm_eth_ag_context ustorm_ag_context;
- struct timers_block_context timers_context;
- struct xstorm_eth_st_context xstorm_st_context;
- struct cstorm_eth_st_context cstorm_st_context;
-};
-
-
-/*
- * Ethernet doorbell
- */
-struct eth_tx_doorbell {
-#if defined(__BIG_ENDIAN)
- u16 npackets;
- u8 params;
-#define ETH_TX_DOORBELL_NUM_BDS (0x3F<<0)
-#define ETH_TX_DOORBELL_NUM_BDS_SHIFT 0
-#define ETH_TX_DOORBELL_RESERVED_TX_FIN_FLAG (0x1<<6)
-#define ETH_TX_DOORBELL_RESERVED_TX_FIN_FLAG_SHIFT 6
-#define ETH_TX_DOORBELL_SPARE (0x1<<7)
-#define ETH_TX_DOORBELL_SPARE_SHIFT 7
- struct doorbell_hdr hdr;
-#elif defined(__LITTLE_ENDIAN)
- struct doorbell_hdr hdr;
- u8 params;
-#define ETH_TX_DOORBELL_NUM_BDS (0x3F<<0)
-#define ETH_TX_DOORBELL_NUM_BDS_SHIFT 0
-#define ETH_TX_DOORBELL_RESERVED_TX_FIN_FLAG (0x1<<6)
-#define ETH_TX_DOORBELL_RESERVED_TX_FIN_FLAG_SHIFT 6
-#define ETH_TX_DOORBELL_SPARE (0x1<<7)
-#define ETH_TX_DOORBELL_SPARE_SHIFT 7
- u16 npackets;
-#endif
-};
-
-
-/*
- * client init fc data
- */
-struct client_init_fc_data {
- __le16 cqe_pause_thr_low;
- __le16 cqe_pause_thr_high;
- __le16 bd_pause_thr_low;
- __le16 bd_pause_thr_high;
- __le16 sge_pause_thr_low;
- __le16 sge_pause_thr_high;
- __le16 rx_cos_mask;
- u8 safc_group_num;
- u8 safc_group_en_flg;
- u8 traffic_type;
- u8 reserved0;
- __le16 reserved1;
- __le32 reserved2;
-};
-
-
-/*
- * client init ramrod data
- */
-struct client_init_general_data {
- u8 client_id;
- u8 statistics_counter_id;
- u8 statistics_en_flg;
- u8 is_fcoe_flg;
- u8 activate_flg;
- u8 sp_client_id;
- __le16 reserved0;
- __le32 reserved1[2];
-};
-
-
-/*
- * client init rx data
- */
-struct client_init_rx_data {
- u8 tpa_en_flg;
- u8 vmqueue_mode_en_flg;
- u8 extra_data_over_sgl_en_flg;
- u8 cache_line_alignment_log_size;
- u8 enable_dynamic_hc;
- u8 max_sges_for_packet;
- u8 client_qzone_id;
- u8 drop_ip_cs_err_flg;
- u8 drop_tcp_cs_err_flg;
- u8 drop_ttl0_flg;
- u8 drop_udp_cs_err_flg;
- u8 inner_vlan_removal_enable_flg;
- u8 outer_vlan_removal_enable_flg;
- u8 status_block_id;
- u8 rx_sb_index_number;
- u8 reserved0[3];
- __le16 bd_buff_size;
- __le16 sge_buff_size;
- __le16 mtu;
- struct regpair bd_page_base;
- struct regpair sge_page_base;
- struct regpair cqe_page_base;
- u8 is_leading_rss;
- u8 is_approx_mcast;
- __le16 max_agg_size;
- __le32 reserved2[3];
-};
-
-/*
- * client init tx data
- */
-struct client_init_tx_data {
- u8 enforce_security_flg;
- u8 tx_status_block_id;
- u8 tx_sb_index_number;
- u8 reserved0;
- __le16 mtu;
- __le16 reserved1;
- struct regpair tx_bd_page_base;
- __le32 reserved2[2];
-};
-
-/*
- * client init ramrod data
- */
-struct client_init_ramrod_data {
- struct client_init_general_data general;
- struct client_init_rx_data rx;
- struct client_init_tx_data tx;
- struct client_init_fc_data fc;
-};
-
-
-/*
- * The data contain client ID need to the ramrod
- */
-struct eth_common_ramrod_data {
- u32 client_id;
- u32 reserved1;
-};
-
-
-/*
- * union for sgl and raw data.
- */
-union eth_sgl_or_raw_data {
- __le16 sgl[8];
- u32 raw_data[4];
-};
-
-/*
- * regular eth FP CQE parameters struct
- */
-struct eth_fast_path_rx_cqe {
- u8 type_error_flags;
-#define ETH_FAST_PATH_RX_CQE_TYPE (0x1<<0)
-#define ETH_FAST_PATH_RX_CQE_TYPE_SHIFT 0
-#define ETH_FAST_PATH_RX_CQE_PHY_DECODE_ERR_FLG (0x1<<1)
-#define ETH_FAST_PATH_RX_CQE_PHY_DECODE_ERR_FLG_SHIFT 1
-#define ETH_FAST_PATH_RX_CQE_IP_BAD_XSUM_FLG (0x1<<2)
-#define ETH_FAST_PATH_RX_CQE_IP_BAD_XSUM_FLG_SHIFT 2
-#define ETH_FAST_PATH_RX_CQE_L4_BAD_XSUM_FLG (0x1<<3)
-#define ETH_FAST_PATH_RX_CQE_L4_BAD_XSUM_FLG_SHIFT 3
-#define ETH_FAST_PATH_RX_CQE_START_FLG (0x1<<4)
-#define ETH_FAST_PATH_RX_CQE_START_FLG_SHIFT 4
-#define ETH_FAST_PATH_RX_CQE_END_FLG (0x1<<5)
-#define ETH_FAST_PATH_RX_CQE_END_FLG_SHIFT 5
-#define ETH_FAST_PATH_RX_CQE_SGL_RAW_SEL (0x3<<6)
-#define ETH_FAST_PATH_RX_CQE_SGL_RAW_SEL_SHIFT 6
- u8 status_flags;
-#define ETH_FAST_PATH_RX_CQE_RSS_HASH_TYPE (0x7<<0)
-#define ETH_FAST_PATH_RX_CQE_RSS_HASH_TYPE_SHIFT 0
-#define ETH_FAST_PATH_RX_CQE_RSS_HASH_FLG (0x1<<3)
-#define ETH_FAST_PATH_RX_CQE_RSS_HASH_FLG_SHIFT 3
-#define ETH_FAST_PATH_RX_CQE_BROADCAST_FLG (0x1<<4)
-#define ETH_FAST_PATH_RX_CQE_BROADCAST_FLG_SHIFT 4
-#define ETH_FAST_PATH_RX_CQE_MAC_MATCH_FLG (0x1<<5)
-#define ETH_FAST_PATH_RX_CQE_MAC_MATCH_FLG_SHIFT 5
-#define ETH_FAST_PATH_RX_CQE_IP_XSUM_NO_VALIDATION_FLG (0x1<<6)
-#define ETH_FAST_PATH_RX_CQE_IP_XSUM_NO_VALIDATION_FLG_SHIFT 6
-#define ETH_FAST_PATH_RX_CQE_L4_XSUM_NO_VALIDATION_FLG (0x1<<7)
-#define ETH_FAST_PATH_RX_CQE_L4_XSUM_NO_VALIDATION_FLG_SHIFT 7
- u8 placement_offset;
- u8 queue_index;
- __le32 rss_hash_result;
- __le16 vlan_tag;
- __le16 pkt_len;
- __le16 len_on_bd;
- struct parsing_flags pars_flags;
- union eth_sgl_or_raw_data sgl_or_raw_data;
-};
-
-
-/*
- * The data for RSS setup ramrod
- */
-struct eth_halt_ramrod_data {
- u32 client_id;
- u32 reserved0;
-};
-
-/*
- * The data for statistics query ramrod
- */
-struct common_query_ramrod_data {
-#if defined(__BIG_ENDIAN)
- u8 reserved0;
- u8 collect_port;
- u16 drv_counter;
-#elif defined(__LITTLE_ENDIAN)
- u16 drv_counter;
- u8 collect_port;
- u8 reserved0;
-#endif
- u32 ctr_id_vector;
-};
-
-
-/*
- * Place holder for ramrods protocol specific data
- */
-struct ramrod_data {
- __le32 data_lo;
- __le32 data_hi;
-};
-
-/*
- * union for ramrod data for Ethernet protocol (CQE) (force size of 16 bits)
- */
-union eth_ramrod_data {
- struct ramrod_data general;
-};
-
-
-/*
- * Eth Rx Cqe structure- general structure for ramrods
- */
-struct common_ramrod_eth_rx_cqe {
- u8 ramrod_type;
-#define COMMON_RAMROD_ETH_RX_CQE_TYPE (0x1<<0)
-#define COMMON_RAMROD_ETH_RX_CQE_TYPE_SHIFT 0
-#define COMMON_RAMROD_ETH_RX_CQE_ERROR (0x1<<1)
-#define COMMON_RAMROD_ETH_RX_CQE_ERROR_SHIFT 1
-#define COMMON_RAMROD_ETH_RX_CQE_RESERVED0 (0x3F<<2)
-#define COMMON_RAMROD_ETH_RX_CQE_RESERVED0_SHIFT 2
- u8 conn_type;
- __le16 reserved1;
- __le32 conn_and_cmd_data;
-#define COMMON_RAMROD_ETH_RX_CQE_CID (0xFFFFFF<<0)
-#define COMMON_RAMROD_ETH_RX_CQE_CID_SHIFT 0
-#define COMMON_RAMROD_ETH_RX_CQE_CMD_ID (0xFF<<24)
-#define COMMON_RAMROD_ETH_RX_CQE_CMD_ID_SHIFT 24
- struct ramrod_data protocol_data;
- __le32 reserved2[4];
-};
-
-/*
- * Rx Last CQE in page (in ETH)
- */
-struct eth_rx_cqe_next_page {
- __le32 addr_lo;
- __le32 addr_hi;
- __le32 reserved[6];
-};
-
-/*
- * union for all eth rx cqe types (fix their sizes)
- */
-union eth_rx_cqe {
- struct eth_fast_path_rx_cqe fast_path_cqe;
- struct common_ramrod_eth_rx_cqe ramrod_cqe;
- struct eth_rx_cqe_next_page next_page_cqe;
-};
-
-
-/*
- * common data for all protocols
- */
-struct spe_hdr {
- __le32 conn_and_cmd_data;
-#define SPE_HDR_CID (0xFFFFFF<<0)
-#define SPE_HDR_CID_SHIFT 0
-#define SPE_HDR_CMD_ID (0xFF<<24)
-#define SPE_HDR_CMD_ID_SHIFT 24
- __le16 type;
-#define SPE_HDR_CONN_TYPE (0xFF<<0)
-#define SPE_HDR_CONN_TYPE_SHIFT 0
-#define SPE_HDR_FUNCTION_ID (0xFF<<8)
-#define SPE_HDR_FUNCTION_ID_SHIFT 8
- __le16 reserved1;
-};
-
-/*
- * Ethernet slow path element
- */
-union eth_specific_data {
- u8 protocol_data[8];
- struct regpair client_init_ramrod_init_data;
- struct eth_halt_ramrod_data halt_ramrod_data;
- struct regpair update_data_addr;
- struct eth_common_ramrod_data common_ramrod_data;
-};
-
-/*
- * Ethernet slow path element
- */
-struct eth_spe {
- struct spe_hdr hdr;
- union eth_specific_data data;
-};
-
-
/*
* array of 13 bds as appears in the eth xstorm context
*/
@@ -2865,86 +3981,25 @@
/*
- * Common configuration parameters per function in Tstorm
+ * VLAN mode on TX BDs
*/
-struct tstorm_eth_function_common_config {
-#if defined(__BIG_ENDIAN)
- u8 reserved1;
- u8 rss_result_mask;
- u16 config_flags;
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV4_CAPABILITY (0x1<<0)
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV4_CAPABILITY_SHIFT 0
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV4_TCP_CAPABILITY (0x1<<1)
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV4_TCP_CAPABILITY_SHIFT 1
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV6_CAPABILITY (0x1<<2)
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV6_CAPABILITY_SHIFT 2
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV6_TCP_CAPABILITY (0x1<<3)
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV6_TCP_CAPABILITY_SHIFT 3
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_MODE (0x7<<4)
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_MODE_SHIFT 4
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_ENABLE_TPA (0x1<<7)
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_ENABLE_TPA_SHIFT 7
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_VLAN_FILTERING_ENABLE (0x1<<8)
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_VLAN_FILTERING_ENABLE_SHIFT 8
-#define __TSTORM_ETH_FUNCTION_COMMON_CONFIG_RESERVED0 (0x7F<<9)
-#define __TSTORM_ETH_FUNCTION_COMMON_CONFIG_RESERVED0_SHIFT 9
-#elif defined(__LITTLE_ENDIAN)
- u16 config_flags;
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV4_CAPABILITY (0x1<<0)
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV4_CAPABILITY_SHIFT 0
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV4_TCP_CAPABILITY (0x1<<1)
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV4_TCP_CAPABILITY_SHIFT 1
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV6_CAPABILITY (0x1<<2)
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV6_CAPABILITY_SHIFT 2
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV6_TCP_CAPABILITY (0x1<<3)
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV6_TCP_CAPABILITY_SHIFT 3
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_MODE (0x7<<4)
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_MODE_SHIFT 4
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_ENABLE_TPA (0x1<<7)
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_ENABLE_TPA_SHIFT 7
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_VLAN_FILTERING_ENABLE (0x1<<8)
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_VLAN_FILTERING_ENABLE_SHIFT 8
-#define __TSTORM_ETH_FUNCTION_COMMON_CONFIG_RESERVED0 (0x7F<<9)
-#define __TSTORM_ETH_FUNCTION_COMMON_CONFIG_RESERVED0_SHIFT 9
- u8 rss_result_mask;
- u8 reserved1;
-#endif
- u16 vlan_id[2];
+enum eth_tx_vlan_type {
+ X_ETH_NO_VLAN,
+ X_ETH_OUTBAND_VLAN,
+ X_ETH_INBAND_VLAN,
+ X_ETH_FW_ADDED_VLAN,
+ MAX_ETH_TX_VLAN_TYPE
};
-/*
- * RSS idirection table update configuration
- */
-struct rss_update_config {
-#if defined(__BIG_ENDIAN)
- u16 toe_rss_bitmap;
- u16 flags;
-#define RSS_UPDATE_CONFIG_ETH_UPDATE_ENABLE (0x1<<0)
-#define RSS_UPDATE_CONFIG_ETH_UPDATE_ENABLE_SHIFT 0
-#define RSS_UPDATE_CONFIG_TOE_UPDATE_ENABLE (0x1<<1)
-#define RSS_UPDATE_CONFIG_TOE_UPDATE_ENABLE_SHIFT 1
-#define __RSS_UPDATE_CONFIG_RESERVED0 (0x3FFF<<2)
-#define __RSS_UPDATE_CONFIG_RESERVED0_SHIFT 2
-#elif defined(__LITTLE_ENDIAN)
- u16 flags;
-#define RSS_UPDATE_CONFIG_ETH_UPDATE_ENABLE (0x1<<0)
-#define RSS_UPDATE_CONFIG_ETH_UPDATE_ENABLE_SHIFT 0
-#define RSS_UPDATE_CONFIG_TOE_UPDATE_ENABLE (0x1<<1)
-#define RSS_UPDATE_CONFIG_TOE_UPDATE_ENABLE_SHIFT 1
-#define __RSS_UPDATE_CONFIG_RESERVED0 (0x3FFF<<2)
-#define __RSS_UPDATE_CONFIG_RESERVED0_SHIFT 2
- u16 toe_rss_bitmap;
-#endif
- u32 reserved1;
-};
/*
- * parameters for eth update ramrod
+ * Ethernet VLAN filtering mode in E1x
*/
-struct eth_update_ramrod_data {
- struct tstorm_eth_function_common_config func_config;
- u8 indirectionTable[128];
- struct rss_update_config rss_config;
+enum eth_vlan_filter_mode {
+ ETH_VLAN_FILTER_ANY_VLAN,
+ ETH_VLAN_FILTER_SPECIFIC_VLAN,
+ ETH_VLAN_FILTER_CLASSIFY,
+ MAX_ETH_VLAN_FILTER_MODE
};
@@ -2954,9 +4009,8 @@
struct mac_configuration_hdr {
u8 length;
u8 offset;
- u16 client_id;
- u16 echo;
- u16 reserved1;
+ __le16 client_id;
+ __le32 echo;
};
/*
@@ -2981,8 +4035,8 @@
#define MAC_CONFIGURATION_ENTRY_BROADCAST_SHIFT 5
#define MAC_CONFIGURATION_ENTRY_RESERVED1 (0x3<<6)
#define MAC_CONFIGURATION_ENTRY_RESERVED1_SHIFT 6
- u16 reserved0;
- u32 clients_bit_vector;
+ __le16 reserved0;
+ __le32 clients_bit_vector;
};
/*
@@ -2995,6 +4049,36 @@
/*
+ * Set-MAC command type (in E1x)
+ */
+enum set_mac_action_type {
+ T_ETH_MAC_COMMAND_INVALIDATE,
+ T_ETH_MAC_COMMAND_SET,
+ MAX_SET_MAC_ACTION_TYPE
+};
+
+
+/*
+ * tpa update ramrod data
+ */
+struct tpa_update_ramrod_data {
+ u8 update_ipv4;
+ u8 update_ipv6;
+ u8 client_id;
+ u8 max_tpa_queues;
+ u8 max_sges_for_packet;
+ u8 complete_on_both_clients;
+ __le16 reserved1;
+ __le16 sge_buff_size;
+ __le16 max_agg_size;
+ __le32 sge_page_base_lo;
+ __le32 sge_page_base_hi;
+ __le16 sge_pause_thr_low;
+ __le16 sge_pause_thr_high;
+};
+
+
+/*
* approximate-match multicast filtering for E1H per function in Tstorm
*/
struct tstorm_eth_approximate_match_multicast_filtering {
@@ -3003,35 +4087,50 @@
/*
- * MAC filtering configuration parameters per port in Tstorm
+ * Common configuration parameters per function in Tstorm
*/
-struct tstorm_eth_mac_filter_config {
- u32 ucast_drop_all;
- u32 ucast_accept_all;
- u32 mcast_drop_all;
- u32 mcast_accept_all;
- u32 bcast_drop_all;
- u32 bcast_accept_all;
- u32 vlan_filter[2];
- u32 unmatched_unicast;
- u32 reserved;
+struct tstorm_eth_function_common_config {
+ __le16 config_flags;
+#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV4_CAPABILITY (0x1<<0)
+#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV4_CAPABILITY_SHIFT 0
+#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV4_TCP_CAPABILITY (0x1<<1)
+#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV4_TCP_CAPABILITY_SHIFT 1
+#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV6_CAPABILITY (0x1<<2)
+#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV6_CAPABILITY_SHIFT 2
+#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV6_TCP_CAPABILITY (0x1<<3)
+#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV6_TCP_CAPABILITY_SHIFT 3
+#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_MODE (0x7<<4)
+#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_MODE_SHIFT 4
+#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_VLAN_FILTERING_ENABLE (0x1<<7)
+#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_VLAN_FILTERING_ENABLE_SHIFT 7
+#define __TSTORM_ETH_FUNCTION_COMMON_CONFIG_RESERVED0 (0xFF<<8)
+#define __TSTORM_ETH_FUNCTION_COMMON_CONFIG_RESERVED0_SHIFT 8
+ u8 rss_result_mask;
+ u8 reserved1;
+ __le16 vlan_id[2];
};
/*
- * common flag to indicate existence of TPA.
+ * MAC filtering configuration parameters per port in Tstorm
*/
-struct tstorm_eth_tpa_exist {
-#if defined(__BIG_ENDIAN)
- u16 reserved1;
- u8 reserved0;
- u8 tpa_exist;
-#elif defined(__LITTLE_ENDIAN)
- u8 tpa_exist;
- u8 reserved0;
- u16 reserved1;
-#endif
- u32 reserved2;
+struct tstorm_eth_mac_filter_config {
+ __le32 ucast_drop_all;
+ __le32 ucast_accept_all;
+ __le32 mcast_drop_all;
+ __le32 mcast_accept_all;
+ __le32 bcast_accept_all;
+ __le32 vlan_filter[2];
+ __le32 unmatched_unicast;
+};
+
+
+/*
+ * tx only queue init ramrod data
+ */
+struct tx_queue_init_ramrod_data {
+ struct client_init_general_data general;
+ struct client_init_tx_data tx;
};
@@ -3061,10 +4160,8 @@
*/
struct cfc_del_event_data {
u32 cid;
- u8 error;
- u8 reserved0;
- u16 reserved1;
- u32 reserved2;
+ u32 reserved0;
+ u32 reserved1;
};
@@ -3072,22 +4169,18 @@
* per-port SAFC demo variables
*/
struct cmng_flags_per_port {
- u8 con_number[NUM_OF_PROTOCOLS];
u32 cmng_enables;
#define CMNG_FLAGS_PER_PORT_FAIRNESS_VN (0x1<<0)
#define CMNG_FLAGS_PER_PORT_FAIRNESS_VN_SHIFT 0
#define CMNG_FLAGS_PER_PORT_RATE_SHAPING_VN (0x1<<1)
#define CMNG_FLAGS_PER_PORT_RATE_SHAPING_VN_SHIFT 1
-#define CMNG_FLAGS_PER_PORT_FAIRNESS_PROTOCOL (0x1<<2)
-#define CMNG_FLAGS_PER_PORT_FAIRNESS_PROTOCOL_SHIFT 2
-#define CMNG_FLAGS_PER_PORT_RATE_SHAPING_PROTOCOL (0x1<<3)
-#define CMNG_FLAGS_PER_PORT_RATE_SHAPING_PROTOCOL_SHIFT 3
-#define CMNG_FLAGS_PER_PORT_FAIRNESS_COS (0x1<<4)
-#define CMNG_FLAGS_PER_PORT_FAIRNESS_COS_SHIFT 4
-#define CMNG_FLAGS_PER_PORT_FAIRNESS_COS_MODE (0x1<<5)
-#define CMNG_FLAGS_PER_PORT_FAIRNESS_COS_MODE_SHIFT 5
-#define __CMNG_FLAGS_PER_PORT_RESERVED0 (0x3FFFFFF<<6)
-#define __CMNG_FLAGS_PER_PORT_RESERVED0_SHIFT 6
+#define CMNG_FLAGS_PER_PORT_FAIRNESS_COS (0x1<<2)
+#define CMNG_FLAGS_PER_PORT_FAIRNESS_COS_SHIFT 2
+#define CMNG_FLAGS_PER_PORT_FAIRNESS_COS_MODE (0x1<<3)
+#define CMNG_FLAGS_PER_PORT_FAIRNESS_COS_MODE_SHIFT 3
+#define __CMNG_FLAGS_PER_PORT_RESERVED0 (0xFFFFFFF<<4)
+#define __CMNG_FLAGS_PER_PORT_RESERVED0_SHIFT 4
+ u32 __reserved1;
};
@@ -3106,6 +4199,7 @@
u32 upper_bound;
u32 fair_threshold;
u32 fairness_timeout;
+ u32 reserved0;
};
/*
@@ -3122,65 +4216,65 @@
u16 __reserved1;
#endif
u8 cos_to_traffic_types[MAX_COS_NUMBER];
- u32 __reserved2;
u16 cos_to_pause_mask[NUM_OF_SAFC_BITS];
};
/*
- * per-port PFC variables
- */
-struct pfc_struct_per_port {
- u8 priority_to_traffic_types[MAX_PFC_PRIORITIES];
-#if defined(__BIG_ENDIAN)
- u16 pfc_pause_quanta_in_nanosec;
- u8 __reserved0;
- u8 priority_non_pausable_mask;
-#elif defined(__LITTLE_ENDIAN)
- u8 priority_non_pausable_mask;
- u8 __reserved0;
- u16 pfc_pause_quanta_in_nanosec;
-#endif
-};
-
-/*
- * Priority and cos
- */
-struct priority_cos {
-#if defined(__BIG_ENDIAN)
- u16 reserved1;
- u8 cos;
- u8 priority;
-#elif defined(__LITTLE_ENDIAN)
- u8 priority;
- u8 cos;
- u16 reserved1;
-#endif
- u32 reserved2;
-};
-
-/*
* Per-port congestion management variables
*/
struct cmng_struct_per_port {
struct rate_shaping_vars_per_port rs_vars;
struct fairness_vars_per_port fair_vars;
struct safc_struct_per_port safc_vars;
- struct pfc_struct_per_port pfc_vars;
-#if defined(__BIG_ENDIAN)
- u16 __reserved1;
- u8 dcb_enabled;
- u8 llfc_mode;
-#elif defined(__LITTLE_ENDIAN)
- u8 llfc_mode;
- u8 dcb_enabled;
- u16 __reserved1;
-#endif
- struct priority_cos
- traffic_type_to_priority_cos[MAX_PFC_TRAFFIC_TYPES];
struct cmng_flags_per_port flags;
};
+/*
+ * Protocol-common command ID for slow path elements
+ */
+enum common_spqe_cmd_id {
+ RAMROD_CMD_ID_COMMON_UNUSED,
+ RAMROD_CMD_ID_COMMON_FUNCTION_START,
+ RAMROD_CMD_ID_COMMON_FUNCTION_STOP,
+ RAMROD_CMD_ID_COMMON_CFC_DEL,
+ RAMROD_CMD_ID_COMMON_CFC_DEL_WB,
+ RAMROD_CMD_ID_COMMON_STAT_QUERY,
+ RAMROD_CMD_ID_COMMON_STOP_TRAFFIC,
+ RAMROD_CMD_ID_COMMON_START_TRAFFIC,
+ RAMROD_CMD_ID_COMMON_RESERVED1,
+ RAMROD_CMD_ID_COMMON_RESERVED2,
+ MAX_COMMON_SPQE_CMD_ID
+};
+
+
+/*
+ * Per-protocol connection types
+ */
+enum connection_type {
+ ETH_CONNECTION_TYPE,
+ TOE_CONNECTION_TYPE,
+ RDMA_CONNECTION_TYPE,
+ ISCSI_CONNECTION_TYPE,
+ FCOE_CONNECTION_TYPE,
+ RESERVED_CONNECTION_TYPE_0,
+ RESERVED_CONNECTION_TYPE_1,
+ RESERVED_CONNECTION_TYPE_2,
+ NONE_CONNECTION_TYPE,
+ MAX_CONNECTION_TYPE
+};
+
+
+/*
+ * Cos modes
+ */
+enum cos_mode {
+ OVERRIDE_COS,
+ STATIC_COS,
+ FW_WRR,
+ MAX_COS_MODE
+};
+
/*
* Dynamic HC counters set by the driver
@@ -3197,10 +4291,58 @@
struct regpair reserved[2];
};
+
/*
- * Dynamic host coalescing init parameters
+ * Vf-PF channel data in cstorm ram (non-triggered zone)
*/
-struct dynamic_hc_config {
+struct vf_pf_channel_zone_data {
+ u32 msg_addr_lo;
+ u32 msg_addr_hi;
+};
+
+/*
+ * zone for VF non-triggered data
+ */
+struct non_trigger_vf_zone {
+ struct vf_pf_channel_zone_data vf_pf_channel;
+};
+
+/*
+ * Vf-PF channel trigger zone in cstorm ram
+ */
+struct vf_pf_channel_zone_trigger {
+ u8 addr_valid;
+};
+
+/*
+ * zone that triggers the in-bound interrupt
+ */
+struct trigger_vf_zone {
+#if defined(__BIG_ENDIAN)
+ u16 reserved1;
+ u8 reserved0;
+ struct vf_pf_channel_zone_trigger vf_pf_channel;
+#elif defined(__LITTLE_ENDIAN)
+ struct vf_pf_channel_zone_trigger vf_pf_channel;
+ u8 reserved0;
+ u16 reserved1;
+#endif
+ u32 reserved2;
+};
+
+/*
+ * zone B per-VF data
+ */
+struct cstorm_vf_zone_data {
+ struct non_trigger_vf_zone non_trigger;
+ struct trigger_vf_zone trigger;
+};
+
+
+/*
+ * Dynamic host coalescing init parameters, per state machine
+ */
+struct dynamic_hc_sm_config {
u32 threshold[3];
u8 shift_per_protocol[HC_SB_MAX_DYNAMIC_INDICES];
u8 hc_timeout0[HC_SB_MAX_DYNAMIC_INDICES];
@@ -3209,114 +4351,114 @@
u8 hc_timeout3[HC_SB_MAX_DYNAMIC_INDICES];
};
-
/*
- * Protocol-common statistics collected by the Xstorm (per client)
+ * Dynamic host coalescing init parameters
*/
-struct xstorm_per_client_stats {
- __le32 reserved0;
- __le32 unicast_pkts_sent;
- struct regpair unicast_bytes_sent;
- struct regpair multicast_bytes_sent;
- __le32 multicast_pkts_sent;
- __le32 broadcast_pkts_sent;
- struct regpair broadcast_bytes_sent;
- __le16 stats_counter;
- __le16 reserved1;
- __le32 reserved2;
+struct dynamic_hc_config {
+ struct dynamic_hc_sm_config sm_config[HC_SB_MAX_SM];
};
-/*
- * Common statistics collected by the Xstorm (per port)
- */
-struct xstorm_common_stats {
- struct xstorm_per_client_stats client_statistics[MAX_STAT_COUNTER_ID];
-};
-/*
- * Protocol-common statistics collected by the Tstorm (per port)
- */
-struct tstorm_per_port_stats {
- __le32 mac_filter_discard;
- __le32 xxoverflow_discard;
- __le32 brb_truncate_discard;
- __le32 mac_discard;
-};
-
-/*
- * Protocol-common statistics collected by the Tstorm (per client)
- */
-struct tstorm_per_client_stats {
- struct regpair rcv_unicast_bytes;
- struct regpair rcv_broadcast_bytes;
- struct regpair rcv_multicast_bytes;
- struct regpair rcv_error_bytes;
- __le32 checksum_discard;
- __le32 packets_too_big_discard;
- __le32 rcv_unicast_pkts;
- __le32 rcv_broadcast_pkts;
- __le32 rcv_multicast_pkts;
- __le32 no_buff_discard;
- __le32 ttl0_discard;
- __le16 stats_counter;
- __le16 reserved0;
-};
-
-/*
- * Protocol-common statistics collected by the Tstorm
- */
-struct tstorm_common_stats {
- struct tstorm_per_port_stats port_statistics;
- struct tstorm_per_client_stats client_statistics[MAX_STAT_COUNTER_ID];
-};
-
-/*
- * Protocol-common statistics collected by the Ustorm (per client)
- */
-struct ustorm_per_client_stats {
- struct regpair ucast_no_buff_bytes;
- struct regpair mcast_no_buff_bytes;
- struct regpair bcast_no_buff_bytes;
- __le32 ucast_no_buff_pkts;
- __le32 mcast_no_buff_pkts;
- __le32 bcast_no_buff_pkts;
- __le16 stats_counter;
- __le16 reserved0;
-};
-
-/*
- * Protocol-common statistics collected by the Ustorm
- */
-struct ustorm_common_stats {
- struct ustorm_per_client_stats client_statistics[MAX_STAT_COUNTER_ID];
-};
-
-/*
- * Eth statistics query structure for the eth_stats_query ramrod
- */
-struct eth_stats_query {
- struct xstorm_common_stats xstorm_common;
- struct tstorm_common_stats tstorm_common;
- struct ustorm_common_stats ustorm_common;
+struct e2_integ_data {
+#if defined(__BIG_ENDIAN)
+ u8 flags;
+#define E2_INTEG_DATA_TESTING_EN (0x1<<0)
+#define E2_INTEG_DATA_TESTING_EN_SHIFT 0
+#define E2_INTEG_DATA_LB_TX (0x1<<1)
+#define E2_INTEG_DATA_LB_TX_SHIFT 1
+#define E2_INTEG_DATA_COS_TX (0x1<<2)
+#define E2_INTEG_DATA_COS_TX_SHIFT 2
+#define E2_INTEG_DATA_OPPORTUNISTICQM (0x1<<3)
+#define E2_INTEG_DATA_OPPORTUNISTICQM_SHIFT 3
+#define E2_INTEG_DATA_DPMTESTRELEASEDQ (0x1<<4)
+#define E2_INTEG_DATA_DPMTESTRELEASEDQ_SHIFT 4
+#define E2_INTEG_DATA_RESERVED (0x7<<5)
+#define E2_INTEG_DATA_RESERVED_SHIFT 5
+ u8 cos;
+ u8 voq;
+ u8 pbf_queue;
+#elif defined(__LITTLE_ENDIAN)
+ u8 pbf_queue;
+ u8 voq;
+ u8 cos;
+ u8 flags;
+#define E2_INTEG_DATA_TESTING_EN (0x1<<0)
+#define E2_INTEG_DATA_TESTING_EN_SHIFT 0
+#define E2_INTEG_DATA_LB_TX (0x1<<1)
+#define E2_INTEG_DATA_LB_TX_SHIFT 1
+#define E2_INTEG_DATA_COS_TX (0x1<<2)
+#define E2_INTEG_DATA_COS_TX_SHIFT 2
+#define E2_INTEG_DATA_OPPORTUNISTICQM (0x1<<3)
+#define E2_INTEG_DATA_OPPORTUNISTICQM_SHIFT 3
+#define E2_INTEG_DATA_DPMTESTRELEASEDQ (0x1<<4)
+#define E2_INTEG_DATA_DPMTESTRELEASEDQ_SHIFT 4
+#define E2_INTEG_DATA_RESERVED (0x7<<5)
+#define E2_INTEG_DATA_RESERVED_SHIFT 5
+#endif
+#if defined(__BIG_ENDIAN)
+ u16 reserved3;
+ u8 reserved2;
+ u8 ramEn;
+#elif defined(__LITTLE_ENDIAN)
+ u8 ramEn;
+ u8 reserved2;
+ u16 reserved3;
+#endif
};
/*
* set mac event data
*/
-struct set_mac_event_data {
- u16 echo;
- u16 reserved0;
+struct eth_event_data {
+ u32 echo;
+ u32 reserved0;
u32 reserved1;
+};
+
+
+/*
+ * pf-vf event data
+ */
+struct vf_pf_event_data {
+ u8 vf_id;
+ u8 reserved0;
+ u16 reserved1;
+ u32 msg_addr_lo;
+ u32 msg_addr_hi;
+};
+
+/*
+ * VF FLR event data
+ */
+struct vf_flr_event_data {
+ u8 vf_id;
+ u8 reserved0;
+ u16 reserved1;
u32 reserved2;
+ u32 reserved3;
+};
+
+/*
+ * malicious VF event data
+ */
+struct malicious_vf_event_data {
+ u8 vf_id;
+ u8 reserved0;
+ u16 reserved1;
+ u32 reserved2;
+ u32 reserved3;
};
/*
* union for all event ring message types
*/
union event_data {
- struct set_mac_event_data set_mac_event;
+ struct vf_pf_event_data vf_pf_event;
+ struct eth_event_data eth_event;
struct cfc_del_event_data cfc_del_event;
+ struct vf_flr_event_data vf_flr_event;
+ struct malicious_vf_event_data malicious_vf_event;
};
@@ -3343,7 +4485,7 @@
*/
struct event_ring_msg {
u8 opcode;
- u8 reserved0;
+ u8 error;
u16 reserved1;
union event_data data;
};
@@ -3366,32 +4508,82 @@
/*
+ * Common event ring opcodes
+ */
+enum event_ring_opcode {
+ EVENT_RING_OPCODE_VF_PF_CHANNEL,
+ EVENT_RING_OPCODE_FUNCTION_START,
+ EVENT_RING_OPCODE_FUNCTION_STOP,
+ EVENT_RING_OPCODE_CFC_DEL,
+ EVENT_RING_OPCODE_CFC_DEL_WB,
+ EVENT_RING_OPCODE_STAT_QUERY,
+ EVENT_RING_OPCODE_STOP_TRAFFIC,
+ EVENT_RING_OPCODE_START_TRAFFIC,
+ EVENT_RING_OPCODE_VF_FLR,
+ EVENT_RING_OPCODE_MALICIOUS_VF,
+ EVENT_RING_OPCODE_FORWARD_SETUP,
+ EVENT_RING_OPCODE_RSS_UPDATE_RULES,
+ EVENT_RING_OPCODE_RESERVED1,
+ EVENT_RING_OPCODE_RESERVED2,
+ EVENT_RING_OPCODE_SET_MAC,
+ EVENT_RING_OPCODE_CLASSIFICATION_RULES,
+ EVENT_RING_OPCODE_FILTERS_RULES,
+ EVENT_RING_OPCODE_MULTICAST_RULES,
+ MAX_EVENT_RING_OPCODE
+};
+
+
+/*
+ * Modes for fairness algorithm
+ */
+enum fairness_mode {
+ FAIRNESS_COS_WRR_MODE,
+ FAIRNESS_COS_ETS_MODE,
+ MAX_FAIRNESS_MODE
+};
+
+
+/*
* per-vnic fairness variables
*/
struct fairness_vars_per_vn {
u32 cos_credit_delta[MAX_COS_NUMBER];
- u32 protocol_credit_delta[NUM_OF_PROTOCOLS];
u32 vn_credit_delta;
u32 __reserved0;
};
/*
+ * Priority and cos
+ */
+struct priority_cos {
+ u8 priority;
+ u8 cos;
+ __le16 reserved1;
+};
+
+/*
* The data for flow control configuration
*/
struct flow_control_configuration {
- struct priority_cos
- traffic_type_to_priority_cos[MAX_PFC_TRAFFIC_TYPES];
-#if defined(__BIG_ENDIAN)
- u16 reserved1;
- u8 dcb_version;
- u8 dcb_enabled;
-#elif defined(__LITTLE_ENDIAN)
+ struct priority_cos traffic_type_to_priority_cos[MAX_TRAFFIC_TYPES];
u8 dcb_enabled;
u8 dcb_version;
- u16 reserved1;
-#endif
- u32 reserved2;
+ u8 dont_add_pri_0_en;
+ u8 reserved1;
+ __le32 reserved2;
+};
+
+
+/*
+ *
+ */
+struct function_start_data {
+ __le16 function_mode;
+ __le16 sd_vlan_tag;
+ u16 reserved;
+ u8 path_id;
+ u8 network_cos_mode;
};
@@ -3504,13 +4696,13 @@
struct pci_entity p_func;
#if defined(__BIG_ENDIAN)
u8 rsrv0;
+ u8 state;
u8 dhc_qzone_id;
- u8 __dynamic_hc_level;
u8 same_igu_sb_1b;
#elif defined(__LITTLE_ENDIAN)
u8 same_igu_sb_1b;
- u8 __dynamic_hc_level;
u8 dhc_qzone_id;
+ u8 state;
u8 rsrv0;
#endif
struct regpair rsrv1[2];
@@ -3518,18 +4710,30 @@
/*
+ * Segment types for host coaslescing
+ */
+enum hc_segment {
+ HC_REGULAR_SEGMENT,
+ HC_DEFAULT_SEGMENT,
+ MAX_HC_SEGMENT
+};
+
+
+/*
* The fast-path status block meta-data
*/
struct hc_sp_status_block_data {
struct regpair host_sb_addr;
#if defined(__BIG_ENDIAN)
- u16 rsrv;
+ u8 rsrv1;
+ u8 state;
u8 igu_seg_id;
u8 igu_sb_id;
#elif defined(__LITTLE_ENDIAN)
u8 igu_sb_id;
u8 igu_seg_id;
- u16 rsrv;
+ u8 state;
+ u8 rsrv1;
#endif
struct pci_entity p_func;
};
@@ -3554,6 +4758,129 @@
/*
+ * IGU block operartion modes (in Everest2)
+ */
+enum igu_mode {
+ HC_IGU_BC_MODE,
+ HC_IGU_NBC_MODE,
+ MAX_IGU_MODE
+};
+
+
+/*
+ * IP versions
+ */
+enum ip_ver {
+ IP_V4,
+ IP_V6,
+ MAX_IP_VER
+};
+
+
+/*
+ * Multi-function modes
+ */
+enum mf_mode {
+ SINGLE_FUNCTION,
+ MULTI_FUNCTION_SD,
+ MULTI_FUNCTION_SI,
+ MULTI_FUNCTION_RESERVED,
+ MAX_MF_MODE
+};
+
+/*
+ * Protocol-common statistics collected by the Tstorm (per pf)
+ */
+struct tstorm_per_pf_stats {
+ struct regpair rcv_error_bytes;
+};
+
+/*
+ *
+ */
+struct per_pf_stats {
+ struct tstorm_per_pf_stats tstorm_pf_statistics;
+};
+
+
+/*
+ * Protocol-common statistics collected by the Tstorm (per port)
+ */
+struct tstorm_per_port_stats {
+ __le32 mac_discard;
+ __le32 mac_filter_discard;
+ __le32 brb_truncate_discard;
+ __le32 mf_tag_discard;
+ __le32 packet_drop;
+ __le32 reserved;
+};
+
+/*
+ *
+ */
+struct per_port_stats {
+ struct tstorm_per_port_stats tstorm_port_statistics;
+};
+
+
+/*
+ * Protocol-common statistics collected by the Tstorm (per client)
+ */
+struct tstorm_per_queue_stats {
+ struct regpair rcv_ucast_bytes;
+ __le32 rcv_ucast_pkts;
+ __le32 checksum_discard;
+ struct regpair rcv_bcast_bytes;
+ __le32 rcv_bcast_pkts;
+ __le32 pkts_too_big_discard;
+ struct regpair rcv_mcast_bytes;
+ __le32 rcv_mcast_pkts;
+ __le32 ttl0_discard;
+ __le16 no_buff_discard;
+ __le16 reserved0;
+ __le32 reserved1;
+};
+
+/*
+ * Protocol-common statistics collected by the Ustorm (per client)
+ */
+struct ustorm_per_queue_stats {
+ struct regpair ucast_no_buff_bytes;
+ struct regpair mcast_no_buff_bytes;
+ struct regpair bcast_no_buff_bytes;
+ __le32 ucast_no_buff_pkts;
+ __le32 mcast_no_buff_pkts;
+ __le32 bcast_no_buff_pkts;
+ __le32 coalesced_pkts;
+ struct regpair coalesced_bytes;
+ __le32 coalesced_events;
+ __le32 coalesced_aborts;
+};
+
+/*
+ * Protocol-common statistics collected by the Xstorm (per client)
+ */
+struct xstorm_per_queue_stats {
+ struct regpair ucast_bytes_sent;
+ struct regpair mcast_bytes_sent;
+ struct regpair bcast_bytes_sent;
+ __le32 ucast_pkts_sent;
+ __le32 mcast_pkts_sent;
+ __le32 bcast_pkts_sent;
+ __le32 error_drop_pkts;
+};
+
+/*
+ *
+ */
+struct per_queue_stats {
+ struct tstorm_per_queue_stats tstorm_queue_statistics;
+ struct ustorm_per_queue_stats ustorm_queue_statistics;
+ struct xstorm_per_queue_stats xstorm_queue_statistics;
+};
+
+
+/*
* FW version stored in first line of pram
*/
struct pram_fw_version {
@@ -3582,7 +4909,6 @@
u8 protocol_data[8];
struct regpair phy_address;
struct regpair mac_config_addr;
- struct common_query_ramrod_data query_ramrod_data;
};
/*
@@ -3613,7 +4939,6 @@
* per-vnic rate shaping variables
*/
struct rate_shaping_vars_per_vn {
- struct rate_shaping_counter protocol_counters[NUM_OF_PROTOCOLS];
struct rate_shaping_counter vn_counter;
};
@@ -3628,39 +4953,100 @@
/*
- * eth/toe flags that indicate if to query
+ * Protocol-common statistics counter
*/
-struct stats_indication_flags {
- u32 collect_eth;
- u32 collect_toe;
+struct stats_counter {
+ __le16 xstats_counter;
+ __le16 reserved0;
+ __le32 reserved1;
+ __le16 tstats_counter;
+ __le16 reserved2;
+ __le32 reserved3;
+ __le16 ustats_counter;
+ __le16 reserved4;
+ __le32 reserved5;
+ __le16 cstats_counter;
+ __le16 reserved6;
+ __le32 reserved7;
};
/*
- * per-port PFC variables
+ *
*/
-struct storm_pfc_struct_per_port {
-#if defined(__BIG_ENDIAN)
- u16 mid_mac_addr;
- u16 msb_mac_addr;
-#elif defined(__LITTLE_ENDIAN)
- u16 msb_mac_addr;
- u16 mid_mac_addr;
-#endif
-#if defined(__BIG_ENDIAN)
- u16 pfc_pause_quanta_in_nanosec;
- u16 lsb_mac_addr;
-#elif defined(__LITTLE_ENDIAN)
- u16 lsb_mac_addr;
- u16 pfc_pause_quanta_in_nanosec;
-#endif
+struct stats_query_entry {
+ u8 kind;
+ u8 index;
+ __le16 funcID;
+ __le32 reserved;
+ struct regpair address;
};
/*
- * Per-port congestion management variables
+ * statistic command
*/
-struct storm_cmng_struct_per_port {
- struct storm_pfc_struct_per_port pfc_vars;
+struct stats_query_cmd_group {
+ struct stats_query_entry query[STATS_QUERY_CMD_COUNT];
+};
+
+
+/*
+ * statistic command header
+ */
+struct stats_query_header {
+ u8 cmd_num;
+ u8 reserved0;
+ __le16 drv_stats_counter;
+ __le32 reserved1;
+ struct regpair stats_counters_addrs;
+};
+
+
+/*
+ * Types of statistcis query entry
+ */
+enum stats_query_type {
+ STATS_TYPE_QUEUE,
+ STATS_TYPE_PORT,
+ STATS_TYPE_PF,
+ STATS_TYPE_TOE,
+ STATS_TYPE_FCOE,
+ MAX_STATS_QUERY_TYPE
+};
+
+
+/*
+ * Indicate of the function status block state
+ */
+enum status_block_state {
+ SB_DISABLED,
+ SB_ENABLED,
+ SB_CLEANED,
+ MAX_STATUS_BLOCK_STATE
+};
+
+
+/*
+ * Storm IDs (including attentions for IGU related enums)
+ */
+enum storm_id {
+ USTORM_ID,
+ CSTORM_ID,
+ XSTORM_ID,
+ TSTORM_ID,
+ ATTENTION_ID,
+ MAX_STORM_ID
+};
+
+
+/*
+ * Taffic types used in ETS and flow control algorithms
+ */
+enum traffic_type {
+ LLFC_TRAFFIC_TYPE_NW,
+ LLFC_TRAFFIC_TYPE_FCOE,
+ LLFC_TRAFFIC_TYPE_ISCSI,
+ MAX_TRAFFIC_TYPE
};
@@ -3715,6 +5101,16 @@
/*
+ * State of VF-PF channel
+ */
+enum vf_pf_channel_state {
+ VF_PF_CHANNEL_STATE_READY,
+ VF_PF_CHANNEL_STATE_WAITING_FOR_ACK,
+ MAX_VF_PF_CHANNEL_STATE
+};
+
+
+/*
* zone A per-queue data
*/
struct xstorm_queue_zone_data {
diff --git a/drivers/net/bnx2x/bnx2x_init.h b/drivers/net/bnx2x/bnx2x_init.h
index d539920..df9f196 100644
--- a/drivers/net/bnx2x/bnx2x_init.h
+++ b/drivers/net/bnx2x/bnx2x_init.h
@@ -15,98 +15,34 @@
#ifndef BNX2X_INIT_H
#define BNX2X_INIT_H
-/* RAM0 size in bytes */
-#define STORM_INTMEM_SIZE_E1 0x5800
-#define STORM_INTMEM_SIZE_E1H 0x10000
-#define STORM_INTMEM_SIZE(bp) ((CHIP_IS_E1(bp) ? STORM_INTMEM_SIZE_E1 : \
- STORM_INTMEM_SIZE_E1H) / 4)
-
-
/* Init operation types and structures */
-/* Common for both E1 and E1H */
-#define OP_RD 0x1 /* read single register */
-#define OP_WR 0x2 /* write single register */
-#define OP_IW 0x3 /* write single register using mailbox */
-#define OP_SW 0x4 /* copy a string to the device */
-#define OP_SI 0x5 /* copy a string using mailbox */
-#define OP_ZR 0x6 /* clear memory */
-#define OP_ZP 0x7 /* unzip then copy with DMAE */
-#define OP_WR_64 0x8 /* write 64 bit pattern */
-#define OP_WB 0x9 /* copy a string using DMAE */
+enum {
+ OP_RD = 0x1, /* read a single register */
+ OP_WR, /* write a single register */
+ OP_SW, /* copy a string to the device */
+ OP_ZR, /* clear memory */
+ OP_ZP, /* unzip then copy with DMAE */
+ OP_WR_64, /* write 64 bit pattern */
+ OP_WB, /* copy a string using DMAE */
+ OP_WB_ZR, /* Clear a string using DMAE or indirect-wr */
+ /* Skip the following ops if all of the init modes don't match */
+ OP_IF_MODE_OR,
+ /* Skip the following ops if any of the init modes don't match */
+ OP_IF_MODE_AND,
+ OP_MAX
+};
-/* FPGA and EMUL specific operations */
-#define OP_WR_EMUL 0xa /* write single register on Emulation */
-#define OP_WR_FPGA 0xb /* write single register on FPGA */
-#define OP_WR_ASIC 0xc /* write single register on ASIC */
-
-/* Init stages */
-/* Never reorder stages !!! */
-#define COMMON_STAGE 0
-#define PORT0_STAGE 1
-#define PORT1_STAGE 2
-#define FUNC0_STAGE 3
-#define FUNC1_STAGE 4
-#define FUNC2_STAGE 5
-#define FUNC3_STAGE 6
-#define FUNC4_STAGE 7
-#define FUNC5_STAGE 8
-#define FUNC6_STAGE 9
-#define FUNC7_STAGE 10
-#define STAGE_IDX_MAX 11
-
-#define STAGE_START 0
-#define STAGE_END 1
-
-
-/* Indices of blocks */
-#define PRS_BLOCK 0
-#define SRCH_BLOCK 1
-#define TSDM_BLOCK 2
-#define TCM_BLOCK 3
-#define BRB1_BLOCK 4
-#define TSEM_BLOCK 5
-#define PXPCS_BLOCK 6
-#define EMAC0_BLOCK 7
-#define EMAC1_BLOCK 8
-#define DBU_BLOCK 9
-#define MISC_BLOCK 10
-#define DBG_BLOCK 11
-#define NIG_BLOCK 12
-#define MCP_BLOCK 13
-#define UPB_BLOCK 14
-#define CSDM_BLOCK 15
-#define USDM_BLOCK 16
-#define CCM_BLOCK 17
-#define UCM_BLOCK 18
-#define USEM_BLOCK 19
-#define CSEM_BLOCK 20
-#define XPB_BLOCK 21
-#define DQ_BLOCK 22
-#define TIMERS_BLOCK 23
-#define XSDM_BLOCK 24
-#define QM_BLOCK 25
-#define PBF_BLOCK 26
-#define XCM_BLOCK 27
-#define XSEM_BLOCK 28
-#define CDU_BLOCK 29
-#define DMAE_BLOCK 30
-#define PXP_BLOCK 31
-#define CFC_BLOCK 32
-#define HC_BLOCK 33
-#define PXP2_BLOCK 34
-#define MISC_AEU_BLOCK 35
-#define PGLUE_B_BLOCK 36
-#define IGU_BLOCK 37
-#define ATC_BLOCK 38
-#define QM_4PORT_BLOCK 39
-#define XSEM_4PORT_BLOCK 40
-
+enum {
+ STAGE_START,
+ STAGE_END,
+};
/* Returns the index of start or end of a specific block stage in ops array*/
#define BLOCK_OPS_IDX(block, stage, end) \
- (2*(((block)*STAGE_IDX_MAX) + (stage)) + (end))
+ (2*(((block)*NUM_OF_INIT_PHASES) + (stage)) + (end))
+/* structs for the various opcodes */
struct raw_op {
u32 op:8;
u32 offset:24;
@@ -116,7 +52,7 @@
struct op_read {
u32 op:8;
u32 offset:24;
- u32 pad;
+ u32 val;
};
struct op_write {
@@ -125,15 +61,15 @@
u32 val;
};
-struct op_string_write {
+struct op_arr_write {
u32 op:8;
u32 offset:24;
-#ifdef __LITTLE_ENDIAN
- u16 data_off;
- u16 data_len;
-#else /* __BIG_ENDIAN */
+#ifdef __BIG_ENDIAN
u16 data_len;
u16 data_off;
+#else /* __LITTLE_ENDIAN */
+ u16 data_off;
+ u16 data_len;
#endif
};
@@ -143,14 +79,210 @@
u32 len;
};
+struct op_if_mode {
+ u32 op:8;
+ u32 cmd_offset:24;
+ u32 mode_bit_map;
+};
+
+
union init_op {
struct op_read read;
struct op_write write;
- struct op_string_write str_wr;
+ struct op_arr_write arr_wr;
struct op_zero zero;
struct raw_op raw;
+ struct op_if_mode if_mode;
};
+
+/* Init Phases */
+enum {
+ PHASE_COMMON,
+ PHASE_PORT0,
+ PHASE_PORT1,
+ PHASE_PF0,
+ PHASE_PF1,
+ PHASE_PF2,
+ PHASE_PF3,
+ PHASE_PF4,
+ PHASE_PF5,
+ PHASE_PF6,
+ PHASE_PF7,
+ NUM_OF_INIT_PHASES
+};
+
+/* Init Modes */
+enum {
+ MODE_ASIC = 0x00000001,
+ MODE_FPGA = 0x00000002,
+ MODE_EMUL = 0x00000004,
+ MODE_E2 = 0x00000008,
+ MODE_E3 = 0x00000010,
+ MODE_PORT2 = 0x00000020,
+ MODE_PORT4 = 0x00000040,
+ MODE_SF = 0x00000080,
+ MODE_MF = 0x00000100,
+ MODE_MF_SD = 0x00000200,
+ MODE_MF_SI = 0x00000400,
+ MODE_MF_NIV = 0x00000800,
+ MODE_E3_A0 = 0x00001000,
+ MODE_E3_B0 = 0x00002000,
+ MODE_COS_BC = 0x00004000,
+ MODE_COS3 = 0x00008000,
+ MODE_COS6 = 0x00010000,
+ MODE_LITTLE_ENDIAN = 0x00020000,
+ MODE_BIG_ENDIAN = 0x00040000,
+};
+
+/* Init Blocks */
+enum {
+ BLOCK_ATC,
+ BLOCK_BRB1,
+ BLOCK_CCM,
+ BLOCK_CDU,
+ BLOCK_CFC,
+ BLOCK_CSDM,
+ BLOCK_CSEM,
+ BLOCK_DBG,
+ BLOCK_DMAE,
+ BLOCK_DORQ,
+ BLOCK_HC,
+ BLOCK_IGU,
+ BLOCK_MISC,
+ BLOCK_NIG,
+ BLOCK_PBF,
+ BLOCK_PGLUE_B,
+ BLOCK_PRS,
+ BLOCK_PXP2,
+ BLOCK_PXP,
+ BLOCK_QM,
+ BLOCK_SRC,
+ BLOCK_TCM,
+ BLOCK_TM,
+ BLOCK_TSDM,
+ BLOCK_TSEM,
+ BLOCK_UCM,
+ BLOCK_UPB,
+ BLOCK_USDM,
+ BLOCK_USEM,
+ BLOCK_XCM,
+ BLOCK_XPB,
+ BLOCK_XSDM,
+ BLOCK_XSEM,
+ BLOCK_MISC_AEU,
+ NUM_OF_INIT_BLOCKS
+};
+
+/* QM queue numbers */
+#define BNX2X_ETH_Q 0
+#define BNX2X_TOE_Q 3
+#define BNX2X_TOE_ACK_Q 6
+#define BNX2X_ISCSI_Q 9
+#define BNX2X_ISCSI_ACK_Q 8
+#define BNX2X_FCOE_Q 10
+
+/* Vnics per mode */
+#define BNX2X_PORT2_MODE_NUM_VNICS 4
+#define BNX2X_PORT4_MODE_NUM_VNICS 2
+
+/* COS offset for port1 in E3 B0 4port mode */
+#define BNX2X_E3B0_PORT1_COS_OFFSET 3
+
+/* QM Register addresses */
+#define BNX2X_Q_VOQ_REG_ADDR(pf_q_num)\
+ (QM_REG_QVOQIDX_0 + 4 * (pf_q_num))
+#define BNX2X_VOQ_Q_REG_ADDR(cos, pf_q_num)\
+ (QM_REG_VOQQMASK_0_LSB + 4 * ((cos) * 2 + ((pf_q_num) >> 5)))
+#define BNX2X_Q_CMDQ_REG_ADDR(pf_q_num)\
+ (QM_REG_BYTECRDCMDQ_0 + 4 * ((pf_q_num) >> 4))
+
+/* extracts the QM queue number for the specified port and vnic */
+#define BNX2X_PF_Q_NUM(q_num, port, vnic)\
+ ((((port) << 1) | (vnic)) * 16 + (q_num))
+
+
+/* Maps the specified queue to the specified COS */
+static inline void bnx2x_map_q_cos(struct bnx2x *bp, u32 q_num, u32 new_cos)
+{
+ /* find current COS mapping */
+ u32 curr_cos = REG_RD(bp, QM_REG_QVOQIDX_0 + q_num * 4);
+
+ /* check if queue->COS mapping has changed */
+ if (curr_cos != new_cos) {
+ u32 num_vnics = BNX2X_PORT2_MODE_NUM_VNICS;
+ u32 reg_addr, reg_bit_map, vnic;
+
+ /* update parameters for 4port mode */
+ if (INIT_MODE_FLAGS(bp) & MODE_PORT4) {
+ num_vnics = BNX2X_PORT4_MODE_NUM_VNICS;
+ if (BP_PORT(bp)) {
+ curr_cos += BNX2X_E3B0_PORT1_COS_OFFSET;
+ new_cos += BNX2X_E3B0_PORT1_COS_OFFSET;
+ }
+ }
+
+ /* change queue mapping for each VNIC */
+ for (vnic = 0; vnic < num_vnics; vnic++) {
+ u32 pf_q_num =
+ BNX2X_PF_Q_NUM(q_num, BP_PORT(bp), vnic);
+ u32 q_bit_map = 1 << (pf_q_num & 0x1f);
+
+ /* overwrite queue->VOQ mapping */
+ REG_WR(bp, BNX2X_Q_VOQ_REG_ADDR(pf_q_num), new_cos);
+
+ /* clear queue bit from current COS bit map */
+ reg_addr = BNX2X_VOQ_Q_REG_ADDR(curr_cos, pf_q_num);
+ reg_bit_map = REG_RD(bp, reg_addr);
+ REG_WR(bp, reg_addr, reg_bit_map & (~q_bit_map));
+
+ /* set queue bit in new COS bit map */
+ reg_addr = BNX2X_VOQ_Q_REG_ADDR(new_cos, pf_q_num);
+ reg_bit_map = REG_RD(bp, reg_addr);
+ REG_WR(bp, reg_addr, reg_bit_map | q_bit_map);
+
+ /* set/clear queue bit in command-queue bit map
+ (E2/E3A0 only, valid COS values are 0/1) */
+ if (!(INIT_MODE_FLAGS(bp) & MODE_E3_B0)) {
+ reg_addr = BNX2X_Q_CMDQ_REG_ADDR(pf_q_num);
+ reg_bit_map = REG_RD(bp, reg_addr);
+ q_bit_map = 1 << (2 * (pf_q_num & 0xf));
+ reg_bit_map = new_cos ?
+ (reg_bit_map | q_bit_map) :
+ (reg_bit_map & (~q_bit_map));
+ REG_WR(bp, reg_addr, reg_bit_map);
+ }
+ }
+ }
+}
+
+/* Configures the QM according to the specified per-traffic-type COSes */
+static inline void bnx2x_dcb_config_qm(struct bnx2x *bp,
+ struct priority_cos *traffic_cos)
+{
+ bnx2x_map_q_cos(bp, BNX2X_FCOE_Q,
+ traffic_cos[LLFC_TRAFFIC_TYPE_FCOE].cos);
+ bnx2x_map_q_cos(bp, BNX2X_ISCSI_Q,
+ traffic_cos[LLFC_TRAFFIC_TYPE_ISCSI].cos);
+ if (INIT_MODE_FLAGS(bp) & MODE_COS_BC) {
+ /* required only in backward compatible COS mode */
+ bnx2x_map_q_cos(bp, BNX2X_ETH_Q,
+ traffic_cos[LLFC_TRAFFIC_TYPE_NW].cos);
+ bnx2x_map_q_cos(bp, BNX2X_TOE_Q,
+ traffic_cos[LLFC_TRAFFIC_TYPE_NW].cos);
+ bnx2x_map_q_cos(bp, BNX2X_TOE_ACK_Q,
+ traffic_cos[LLFC_TRAFFIC_TYPE_NW].cos);
+ bnx2x_map_q_cos(bp, BNX2X_ISCSI_ACK_Q,
+ traffic_cos[LLFC_TRAFFIC_TYPE_ISCSI].cos);
+ }
+}
+
+
+/* Returns the index of start or end of a specific block stage in ops array*/
+#define BLOCK_OPS_IDX(block, stage, end) \
+ (2*(((block)*NUM_OF_INIT_PHASES) + (stage)) + (end))
+
+
#define INITOP_SET 0 /* set the HW directly */
#define INITOP_CLEAR 1 /* clear the HW directly */
#define INITOP_INIT 2 /* set the init-value array */
@@ -245,12 +377,15 @@
BLOCK_PRTY_INFO_0(PXP2, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff),
BLOCK_PRTY_INFO_1(PXP2, 0x7ff, 0x7f, 0x7f, 0x7ff),
BLOCK_PRTY_INFO(HC, 0x7, 0x7, 0x7, 0),
+ BLOCK_PRTY_INFO(NIG, 0xffffffff, 0x3fffffff, 0xffffffff, 0),
+ BLOCK_PRTY_INFO_0(NIG, 0xffffffff, 0, 0, 0xffffffff),
+ BLOCK_PRTY_INFO_1(NIG, 0xffff, 0, 0, 0xffff),
BLOCK_PRTY_INFO(IGU, 0x7ff, 0, 0, 0x7ff),
BLOCK_PRTY_INFO(MISC, 0x1, 0x1, 0x1, 0x1),
BLOCK_PRTY_INFO(QM, 0, 0x1ff, 0xfff, 0xfff),
BLOCK_PRTY_INFO(DORQ, 0, 0x3, 0x3, 0x3),
{GRCBASE_UPB + PB_REG_PB_PRTY_MASK,
- GRCBASE_UPB + PB_REG_PB_PRTY_STS_CLR, 0,
+ GRCBASE_UPB + PB_REG_PB_PRTY_STS_CLR, 0xf,
{0xf, 0xf, 0xf}, "UPB"},
{GRCBASE_XPB + PB_REG_PB_PRTY_MASK,
GRCBASE_XPB + PB_REG_PB_PRTY_STS_CLR, 0,
@@ -262,10 +397,16 @@
BLOCK_PRTY_INFO(DMAE, 0, 0xf, 0xf, 0xf),
BLOCK_PRTY_INFO(BRB1, 0, 0xf, 0xf, 0xf),
BLOCK_PRTY_INFO(PRS, (1<<6), 0xff, 0xff, 0xff),
+ BLOCK_PRTY_INFO(PBF, 0, 0, 0x3ffff, 0xfffffff),
+ BLOCK_PRTY_INFO(TM, 0, 0, 0x7f, 0x7f),
BLOCK_PRTY_INFO(TSDM, 0x18, 0x7ff, 0x7ff, 0x7ff),
BLOCK_PRTY_INFO(CSDM, 0x8, 0x7ff, 0x7ff, 0x7ff),
BLOCK_PRTY_INFO(USDM, 0x38, 0x7ff, 0x7ff, 0x7ff),
BLOCK_PRTY_INFO(XSDM, 0x8, 0x7ff, 0x7ff, 0x7ff),
+ BLOCK_PRTY_INFO(TCM, 0, 0, 0x7ffffff, 0x7ffffff),
+ BLOCK_PRTY_INFO(CCM, 0, 0, 0x7ffffff, 0x7ffffff),
+ BLOCK_PRTY_INFO(UCM, 0, 0, 0x7ffffff, 0x7ffffff),
+ BLOCK_PRTY_INFO(XCM, 0, 0, 0x3fffffff, 0x3fffffff),
BLOCK_PRTY_INFO_0(TSEM, 0, 0xffffffff, 0xffffffff, 0xffffffff),
BLOCK_PRTY_INFO_1(TSEM, 0, 0x3, 0x1f, 0x3f),
BLOCK_PRTY_INFO_0(USEM, 0, 0xffffffff, 0xffffffff, 0xffffffff),
diff --git a/drivers/net/bnx2x/bnx2x_init_ops.h b/drivers/net/bnx2x/bnx2x_init_ops.h
index aafd023..7ec1724 100644
--- a/drivers/net/bnx2x/bnx2x_init_ops.h
+++ b/drivers/net/bnx2x/bnx2x_init_ops.h
@@ -15,13 +15,39 @@
#ifndef BNX2X_INIT_OPS_H
#define BNX2X_INIT_OPS_H
+
+#ifndef BP_ILT
+#define BP_ILT(bp) NULL
+#endif
+
+#ifndef BP_FUNC
+#define BP_FUNC(bp) 0
+#endif
+
+#ifndef BP_PORT
+#define BP_PORT(bp) 0
+#endif
+
+#ifndef BNX2X_ILT_FREE
+#define BNX2X_ILT_FREE(x, y, sz)
+#endif
+
+#ifndef BNX2X_ILT_ZALLOC
+#define BNX2X_ILT_ZALLOC(x, y, sz)
+#endif
+
+#ifndef ILOG2
+#define ILOG2(x) x
+#endif
+
static int bnx2x_gunzip(struct bnx2x *bp, const u8 *zbuf, int len);
static void bnx2x_reg_wr_ind(struct bnx2x *bp, u32 addr, u32 val);
-static void bnx2x_write_dmae_phys_len(struct bnx2x *bp, dma_addr_t phys_addr,
- u32 addr, u32 len);
+static void bnx2x_write_dmae_phys_len(struct bnx2x *bp,
+ dma_addr_t phys_addr, u32 addr,
+ u32 len);
-static void bnx2x_init_str_wr(struct bnx2x *bp, u32 addr, const u32 *data,
- u32 len)
+static void bnx2x_init_str_wr(struct bnx2x *bp, u32 addr,
+ const u32 *data, u32 len)
{
u32 i;
@@ -29,24 +55,32 @@
REG_WR(bp, addr + i*4, data[i]);
}
-static void bnx2x_init_ind_wr(struct bnx2x *bp, u32 addr, const u32 *data,
- u32 len)
+static void bnx2x_init_ind_wr(struct bnx2x *bp, u32 addr,
+ const u32 *data, u32 len)
{
u32 i;
for (i = 0; i < len; i++)
- REG_WR_IND(bp, addr + i*4, data[i]);
+ bnx2x_reg_wr_ind(bp, addr + i*4, data[i]);
}
-static void bnx2x_write_big_buf(struct bnx2x *bp, u32 addr, u32 len)
+static void bnx2x_write_big_buf(struct bnx2x *bp, u32 addr, u32 len,
+ u8 wb)
{
if (bp->dmae_ready)
bnx2x_write_dmae_phys_len(bp, GUNZIP_PHYS(bp), addr, len);
+ else if (wb)
+ /*
+ * Wide bus registers with no dmae need to be written
+ * using indirect write.
+ */
+ bnx2x_init_ind_wr(bp, addr, GUNZIP_BUF(bp), len);
else
bnx2x_init_str_wr(bp, addr, GUNZIP_BUF(bp), len);
}
-static void bnx2x_init_fill(struct bnx2x *bp, u32 addr, int fill, u32 len)
+static void bnx2x_init_fill(struct bnx2x *bp, u32 addr, int fill,
+ u32 len, u8 wb)
{
u32 buf_len = (((len*4) > FW_BUF_SIZE) ? FW_BUF_SIZE : (len*4));
u32 buf_len32 = buf_len/4;
@@ -57,12 +91,20 @@
for (i = 0; i < len; i += buf_len32) {
u32 cur_len = min(buf_len32, len - i);
- bnx2x_write_big_buf(bp, addr + i*4, cur_len);
+ bnx2x_write_big_buf(bp, addr + i*4, cur_len, wb);
}
}
-static void bnx2x_init_wr_64(struct bnx2x *bp, u32 addr, const u32 *data,
- u32 len64)
+static void bnx2x_write_big_buf_wb(struct bnx2x *bp, u32 addr, u32 len)
+{
+ if (bp->dmae_ready)
+ bnx2x_write_dmae_phys_len(bp, GUNZIP_PHYS(bp), addr, len);
+ else
+ bnx2x_init_ind_wr(bp, addr, GUNZIP_BUF(bp), len);
+}
+
+static void bnx2x_init_wr_64(struct bnx2x *bp, u32 addr,
+ const u32 *data, u32 len64)
{
u32 buf_len32 = FW_BUF_SIZE/4;
u32 len = len64*2;
@@ -82,7 +124,7 @@
for (i = 0; i < len; i += buf_len32) {
u32 cur_len = min(buf_len32, len - i);
- bnx2x_write_big_buf(bp, addr + i*4, cur_len);
+ bnx2x_write_big_buf_wb(bp, addr + i*4, cur_len);
}
}
@@ -100,7 +142,8 @@
#define IF_IS_PRAM_ADDR(base, addr) \
if (((base) <= (addr)) && ((base) + 0x40000 >= (addr)))
-static const u8 *bnx2x_sel_blob(struct bnx2x *bp, u32 addr, const u8 *data)
+static const u8 *bnx2x_sel_blob(struct bnx2x *bp, u32 addr,
+ const u8 *data)
{
IF_IS_INT_TABLE_ADDR(TSEM_REG_INT_TABLE, addr)
data = INIT_TSEM_INT_TABLE_DATA(bp);
@@ -129,31 +172,17 @@
return data;
}
-static void bnx2x_write_big_buf_wb(struct bnx2x *bp, u32 addr, u32 len)
+static void bnx2x_init_wr_wb(struct bnx2x *bp, u32 addr,
+ const u32 *data, u32 len)
{
if (bp->dmae_ready)
- bnx2x_write_dmae_phys_len(bp, GUNZIP_PHYS(bp), addr, len);
+ VIRT_WR_DMAE_LEN(bp, data, addr, len, 0);
else
- bnx2x_init_ind_wr(bp, addr, GUNZIP_BUF(bp), len);
-}
-
-static void bnx2x_init_wr_wb(struct bnx2x *bp, u32 addr, const u32 *data,
- u32 len)
-{
- const u32 *old_data = data;
-
- data = (const u32 *)bnx2x_sel_blob(bp, addr, (const u8 *)data);
-
- if (bp->dmae_ready) {
- if (old_data != data)
- VIRT_WR_DMAE_LEN(bp, data, addr, len, 1);
- else
- VIRT_WR_DMAE_LEN(bp, data, addr, len, 0);
- } else
bnx2x_init_ind_wr(bp, addr, data, len);
}
-static void bnx2x_wr_64(struct bnx2x *bp, u32 reg, u32 val_lo, u32 val_hi)
+static void bnx2x_wr_64(struct bnx2x *bp, u32 reg, u32 val_lo,
+ u32 val_hi)
{
u32 wb_write[2];
@@ -161,8 +190,8 @@
wb_write[1] = val_hi;
REG_WR_DMAE_LEN(bp, reg, wb_write, 2);
}
-
-static void bnx2x_init_wr_zp(struct bnx2x *bp, u32 addr, u32 len, u32 blob_off)
+static void bnx2x_init_wr_zp(struct bnx2x *bp, u32 addr, u32 len,
+ u32 blob_off)
{
const u8 *data = NULL;
int rc;
@@ -186,39 +215,33 @@
static void bnx2x_init_block(struct bnx2x *bp, u32 block, u32 stage)
{
u16 op_start =
- INIT_OPS_OFFSETS(bp)[BLOCK_OPS_IDX(block, stage, STAGE_START)];
+ INIT_OPS_OFFSETS(bp)[BLOCK_OPS_IDX(block, stage,
+ STAGE_START)];
u16 op_end =
- INIT_OPS_OFFSETS(bp)[BLOCK_OPS_IDX(block, stage, STAGE_END)];
+ INIT_OPS_OFFSETS(bp)[BLOCK_OPS_IDX(block, stage,
+ STAGE_END)];
union init_op *op;
- int hw_wr;
- u32 i, op_type, addr, len;
+ u32 op_idx, op_type, addr, len;
const u32 *data, *data_base;
/* If empty block */
if (op_start == op_end)
return;
- if (CHIP_REV_IS_FPGA(bp))
- hw_wr = OP_WR_FPGA;
- else if (CHIP_REV_IS_EMUL(bp))
- hw_wr = OP_WR_EMUL;
- else
- hw_wr = OP_WR_ASIC;
-
data_base = INIT_DATA(bp);
- for (i = op_start; i < op_end; i++) {
+ for (op_idx = op_start; op_idx < op_end; op_idx++) {
- op = (union init_op *)&(INIT_OPS(bp)[i]);
-
- op_type = op->str_wr.op;
- addr = op->str_wr.offset;
- len = op->str_wr.data_len;
- data = data_base + op->str_wr.data_off;
-
- /* HW/EMUL specific */
- if ((op_type > OP_WB) && (op_type == hw_wr))
- op_type = OP_WR;
+ op = (union init_op *)&(INIT_OPS(bp)[op_idx]);
+ /* Get generic data */
+ op_type = op->raw.op;
+ addr = op->raw.offset;
+ /* Get data that's used for OP_SW, OP_WB, OP_FW, OP_ZP and
+ * OP_WR64 (we assume that op_arr_write and op_write have the
+ * same structure).
+ */
+ len = op->arr_wr.data_len;
+ data = data_base + op->arr_wr.data_off;
switch (op_type) {
case OP_RD:
@@ -233,21 +256,39 @@
case OP_WB:
bnx2x_init_wr_wb(bp, addr, data, len);
break;
- case OP_SI:
- bnx2x_init_ind_wr(bp, addr, data, len);
- break;
case OP_ZR:
- bnx2x_init_fill(bp, addr, 0, op->zero.len);
+ bnx2x_init_fill(bp, addr, 0, op->zero.len, 0);
+ break;
+ case OP_WB_ZR:
+ bnx2x_init_fill(bp, addr, 0, op->zero.len, 1);
break;
case OP_ZP:
bnx2x_init_wr_zp(bp, addr, len,
- op->str_wr.data_off);
+ op->arr_wr.data_off);
break;
case OP_WR_64:
bnx2x_init_wr_64(bp, addr, data, len);
break;
+ case OP_IF_MODE_AND:
+ /* if any of the flags doesn't match, skip the
+ * conditional block.
+ */
+ if ((INIT_MODE_FLAGS(bp) &
+ op->if_mode.mode_bit_map) !=
+ op->if_mode.mode_bit_map)
+ op_idx += op->if_mode.cmd_offset;
+ break;
+ case OP_IF_MODE_OR:
+ /* if all the flags don't match, skip the conditional
+ * block.
+ */
+ if ((INIT_MODE_FLAGS(bp) &
+ op->if_mode.mode_bit_map) == 0)
+ op_idx += op->if_mode.cmd_offset;
+ break;
default:
- /* happens whenever an op is of a diff HW */
+ /* Should never get here! */
+
break;
}
}
@@ -417,7 +458,8 @@
PXP2_REG_RQ_BW_WR_UBOUND30}
};
-static void bnx2x_init_pxp_arb(struct bnx2x *bp, int r_order, int w_order)
+static void bnx2x_init_pxp_arb(struct bnx2x *bp, int r_order,
+ int w_order)
{
u32 val, i;
@@ -491,19 +533,21 @@
if ((CHIP_IS_E1(bp) || CHIP_IS_E1H(bp)) && (r_order == MAX_RD_ORD))
REG_WR(bp, PXP2_REG_RQ_PDR_LIMIT, 0xe00);
- if (CHIP_IS_E2(bp))
+ if (CHIP_IS_E3(bp))
+ REG_WR(bp, PXP2_REG_WR_USDMDP_TH, (0x4 << w_order));
+ else if (CHIP_IS_E2(bp))
REG_WR(bp, PXP2_REG_WR_USDMDP_TH, (0x8 << w_order));
else
REG_WR(bp, PXP2_REG_WR_USDMDP_TH, (0x18 << w_order));
- if (CHIP_IS_E1H(bp) || CHIP_IS_E2(bp)) {
+ if (!CHIP_IS_E1(bp)) {
/* MPS w_order optimal TH presently TH
* 128 0 0 2
* 256 1 1 3
* >=512 2 2 3
*/
/* DMAE is special */
- if (CHIP_IS_E2(bp)) {
+ if (!CHIP_IS_E1H(bp)) {
/* E2 can use optimal TH */
val = w_order;
REG_WR(bp, PXP2_REG_WR_DMAE_MPS, val);
@@ -557,8 +601,8 @@
#define ILT_ADDR2(x) ((u32)((1 << 20) | ((u64)x >> 44)))
#define ILT_RANGE(f, l) (((l) << 10) | f)
-static int bnx2x_ilt_line_mem_op(struct bnx2x *bp, struct ilt_line *line,
- u32 size, u8 memop)
+static int bnx2x_ilt_line_mem_op(struct bnx2x *bp,
+ struct ilt_line *line, u32 size, u8 memop)
{
if (memop == ILT_MEMOP_FREE) {
BNX2X_ILT_FREE(line->page, line->page_mapping, line->size);
@@ -572,7 +616,8 @@
}
-static int bnx2x_ilt_client_mem_op(struct bnx2x *bp, int cli_num, u8 memop)
+static int bnx2x_ilt_client_mem_op(struct bnx2x *bp, int cli_num,
+ u8 memop)
{
int i, rc;
struct bnx2x_ilt *ilt = BP_ILT(bp);
@@ -617,8 +662,8 @@
bnx2x_wr_64(bp, reg, ILT_ADDR1(page_mapping), ILT_ADDR2(page_mapping));
}
-static void bnx2x_ilt_line_init_op(struct bnx2x *bp, struct bnx2x_ilt *ilt,
- int idx, u8 initop)
+static void bnx2x_ilt_line_init_op(struct bnx2x *bp,
+ struct bnx2x_ilt *ilt, int idx, u8 initop)
{
dma_addr_t null_mapping;
int abs_idx = ilt->start_line + idx;
@@ -733,7 +778,7 @@
}
static void bnx2x_ilt_init_client_psz(struct bnx2x *bp, int cli_num,
- u32 psz_reg, u8 initop)
+ u32 psz_reg, u8 initop)
{
struct bnx2x_ilt *ilt = BP_ILT(bp);
struct ilt_client_info *ilt_cli = &ilt->clients[cli_num];
@@ -848,7 +893,8 @@
/* Initialize T2 */
for (i = 0; i < src_cid_count-1; i++)
- t2[i].next = (u64)(t2_mapping + (i+1)*sizeof(struct src_ent));
+ t2[i].next = (u64)(t2_mapping +
+ (i+1)*sizeof(struct src_ent));
/* tell the searcher where the T2 table is */
REG_WR(bp, SRC_REG_COUNTFREE0 + port*4, src_cid_count);
diff --git a/drivers/net/bnx2x/bnx2x_link.c b/drivers/net/bnx2x/bnx2x_link.c
index 076e11f..bcd8f00 100644
--- a/drivers/net/bnx2x/bnx2x_link.c
+++ b/drivers/net/bnx2x/bnx2x_link.c
@@ -25,6 +25,8 @@
#include <linux/mutex.h>
#include "bnx2x.h"
+#include "bnx2x_cmn.h"
+
/********************************************************/
#define ETH_HLEN 14
@@ -35,6 +37,13 @@
#define ETH_MAX_JUMBO_PACKET_SIZE 9600
#define MDIO_ACCESS_TIMEOUT 1000
#define BMAC_CONTROL_RX_ENABLE 2
+#define WC_LANE_MAX 4
+#define I2C_SWITCH_WIDTH 2
+#define I2C_BSC0 0
+#define I2C_BSC1 1
+#define I2C_WA_RETRY_CNT 3
+#define MCPR_IMC_COMMAND_READ_OP 1
+#define MCPR_IMC_COMMAND_WRITE_OP 2
/***********************************************************/
/* Shortcut definitions */
@@ -103,16 +112,13 @@
MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_HIG
#define GP_STATUS_10G_CX4 \
MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_CX4
-#define GP_STATUS_12G_HIG \
- MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_12G_HIG
-#define GP_STATUS_12_5G MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_12_5G
-#define GP_STATUS_13G MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_13G
-#define GP_STATUS_15G MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_15G
-#define GP_STATUS_16G MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_16G
#define GP_STATUS_1G_KX MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_1G_KX
#define GP_STATUS_10G_KX4 \
MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_KX4
-
+#define GP_STATUS_10G_KR MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_KR
+#define GP_STATUS_10G_XFI MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_XFI
+#define GP_STATUS_20G_DXGXS MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_20G_DXGXS
+#define GP_STATUS_10G_SFI MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_SFI
#define LINK_10THD LINK_STATUS_SPEED_AND_DUPLEX_10THD
#define LINK_10TFD LINK_STATUS_SPEED_AND_DUPLEX_10TFD
#define LINK_100TXHD LINK_STATUS_SPEED_AND_DUPLEX_100TXHD
@@ -126,20 +132,10 @@
#define LINK_2500XFD LINK_STATUS_SPEED_AND_DUPLEX_2500XFD
#define LINK_10GTFD LINK_STATUS_SPEED_AND_DUPLEX_10GTFD
#define LINK_10GXFD LINK_STATUS_SPEED_AND_DUPLEX_10GXFD
-#define LINK_12GTFD LINK_STATUS_SPEED_AND_DUPLEX_12GTFD
-#define LINK_12GXFD LINK_STATUS_SPEED_AND_DUPLEX_12GXFD
-#define LINK_12_5GTFD LINK_STATUS_SPEED_AND_DUPLEX_12_5GTFD
-#define LINK_12_5GXFD LINK_STATUS_SPEED_AND_DUPLEX_12_5GXFD
-#define LINK_13GTFD LINK_STATUS_SPEED_AND_DUPLEX_13GTFD
-#define LINK_13GXFD LINK_STATUS_SPEED_AND_DUPLEX_13GXFD
-#define LINK_15GTFD LINK_STATUS_SPEED_AND_DUPLEX_15GTFD
-#define LINK_15GXFD LINK_STATUS_SPEED_AND_DUPLEX_15GXFD
-#define LINK_16GTFD LINK_STATUS_SPEED_AND_DUPLEX_16GTFD
-#define LINK_16GXFD LINK_STATUS_SPEED_AND_DUPLEX_16GXFD
+#define LINK_20GTFD LINK_STATUS_SPEED_AND_DUPLEX_20GTFD
+#define LINK_20GXFD LINK_STATUS_SPEED_AND_DUPLEX_20GXFD
-#define PHY_XGXS_FLAG 0x1
-#define PHY_SGMII_FLAG 0x2
-#define PHY_SERDES_FLAG 0x4
+
/* */
#define SFP_EEPROM_CON_TYPE_ADDR 0x2
@@ -165,8 +161,104 @@
#define EDC_MODE_PASSIVE_DAC 0x0055
+/* BRB thresholds for E2*/
+#define PFC_E2_BRB_MAC_PAUSE_XOFF_THR_PAUSE 170
+#define PFC_E2_BRB_MAC_PAUSE_XOFF_THR_NON_PAUSE 0
+
+#define PFC_E2_BRB_MAC_PAUSE_XON_THR_PAUSE 250
+#define PFC_E2_BRB_MAC_PAUSE_XON_THR_NON_PAUSE 0
+
+#define PFC_E2_BRB_MAC_FULL_XOFF_THR_PAUSE 10
+#define PFC_E2_BRB_MAC_FULL_XOFF_THR_NON_PAUSE 90
+
+#define PFC_E2_BRB_MAC_FULL_XON_THR_PAUSE 50
+#define PFC_E2_BRB_MAC_FULL_XON_THR_NON_PAUSE 250
+
+/* BRB thresholds for E3A0 */
+#define PFC_E3A0_BRB_MAC_PAUSE_XOFF_THR_PAUSE 290
+#define PFC_E3A0_BRB_MAC_PAUSE_XOFF_THR_NON_PAUSE 0
+
+#define PFC_E3A0_BRB_MAC_PAUSE_XON_THR_PAUSE 410
+#define PFC_E3A0_BRB_MAC_PAUSE_XON_THR_NON_PAUSE 0
+
+#define PFC_E3A0_BRB_MAC_FULL_XOFF_THR_PAUSE 10
+#define PFC_E3A0_BRB_MAC_FULL_XOFF_THR_NON_PAUSE 170
+
+#define PFC_E3A0_BRB_MAC_FULL_XON_THR_PAUSE 50
+#define PFC_E3A0_BRB_MAC_FULL_XON_THR_NON_PAUSE 410
+
+
+/* BRB thresholds for E3B0 2 port mode*/
+#define PFC_E3B0_2P_BRB_MAC_PAUSE_XOFF_THR_PAUSE 1025
+#define PFC_E3B0_2P_BRB_MAC_PAUSE_XOFF_THR_NON_PAUSE 0
+
+#define PFC_E3B0_2P_BRB_MAC_PAUSE_XON_THR_PAUSE 1025
+#define PFC_E3B0_2P_BRB_MAC_PAUSE_XON_THR_NON_PAUSE 0
+
+#define PFC_E3B0_2P_BRB_MAC_FULL_XOFF_THR_PAUSE 10
+#define PFC_E3B0_2P_BRB_MAC_FULL_XOFF_THR_NON_PAUSE 1025
+
+#define PFC_E3B0_2P_BRB_MAC_FULL_XON_THR_PAUSE 50
+#define PFC_E3B0_2P_BRB_MAC_FULL_XON_THR_NON_PAUSE 1025
+
+/* only for E3B0*/
+#define PFC_E3B0_2P_BRB_FULL_LB_XOFF_THR 1025
+#define PFC_E3B0_2P_BRB_FULL_LB_XON_THR 1025
+
+/* Lossy +Lossless GUARANTIED == GUART */
+#define PFC_E3B0_2P_MIX_PAUSE_LB_GUART 284
+/* Lossless +Lossless*/
+#define PFC_E3B0_2P_PAUSE_LB_GUART 236
+/* Lossy +Lossy*/
+#define PFC_E3B0_2P_NON_PAUSE_LB_GUART 342
+
+/* Lossy +Lossless*/
+#define PFC_E3B0_2P_MIX_PAUSE_MAC_0_CLASS_T_GUART 284
+/* Lossless +Lossless*/
+#define PFC_E3B0_2P_PAUSE_MAC_0_CLASS_T_GUART 236
+/* Lossy +Lossy*/
+#define PFC_E3B0_2P_NON_PAUSE_MAC_0_CLASS_T_GUART 336
+#define PFC_E3B0_2P_BRB_MAC_0_CLASS_T_GUART_HYST 80
+
+#define PFC_E3B0_2P_BRB_MAC_1_CLASS_T_GUART 0
+#define PFC_E3B0_2P_BRB_MAC_1_CLASS_T_GUART_HYST 0
+
+/* BRB thresholds for E3B0 4 port mode */
+#define PFC_E3B0_4P_BRB_MAC_PAUSE_XOFF_THR_PAUSE 304
+#define PFC_E3B0_4P_BRB_MAC_PAUSE_XOFF_THR_NON_PAUSE 0
+
+#define PFC_E3B0_4P_BRB_MAC_PAUSE_XON_THR_PAUSE 384
+#define PFC_E3B0_4P_BRB_MAC_PAUSE_XON_THR_NON_PAUSE 0
+
+#define PFC_E3B0_4P_BRB_MAC_FULL_XOFF_THR_PAUSE 10
+#define PFC_E3B0_4P_BRB_MAC_FULL_XOFF_THR_NON_PAUSE 304
+
+#define PFC_E3B0_4P_BRB_MAC_FULL_XON_THR_PAUSE 50
+#define PFC_E3B0_4P_BRB_MAC_FULL_XON_THR_NON_PAUSE 384
+
+
+/* only for E3B0*/
+#define PFC_E3B0_4P_BRB_FULL_LB_XOFF_THR 304
+#define PFC_E3B0_4P_BRB_FULL_LB_XON_THR 384
+#define PFC_E3B0_4P_LB_GUART 120
+
+#define PFC_E3B0_4P_BRB_MAC_0_CLASS_T_GUART 120
+#define PFC_E3B0_4P_BRB_MAC_0_CLASS_T_GUART_HYST 80
+
+#define PFC_E3B0_4P_BRB_MAC_1_CLASS_T_GUART 80
+#define PFC_E3B0_4P_BRB_MAC_1_CLASS_T_GUART_HYST 120
+
+#define DCBX_INVALID_COS (0xFF)
+
#define ETS_BW_LIMIT_CREDIT_UPPER_BOUND (0x5000)
#define ETS_BW_LIMIT_CREDIT_WEIGHT (0x5000)
+#define ETS_E3B0_NIG_MIN_W_VAL_UP_TO_10GBPS (1360)
+#define ETS_E3B0_NIG_MIN_W_VAL_20GBPS (2720)
+#define ETS_E3B0_PBF_MIN_W_VAL (10000)
+
+#define MAX_PACKET_SIZE (9700)
+#define WC_UC_TIMEOUT 100
+
/**********************************************************/
/* INTERFACE */
/**********************************************************/
@@ -202,14 +294,86 @@
}
/******************************************************************/
+/* EPIO/GPIO section */
+/******************************************************************/
+static void bnx2x_get_epio(struct bnx2x *bp, u32 epio_pin, u32 *en)
+{
+ u32 epio_mask, gp_oenable;
+ *en = 0;
+ /* Sanity check */
+ if (epio_pin > 31) {
+ DP(NETIF_MSG_LINK, "Invalid EPIO pin %d to get\n", epio_pin);
+ return;
+ }
+
+ epio_mask = 1 << epio_pin;
+ /* Set this EPIO to output */
+ gp_oenable = REG_RD(bp, MCP_REG_MCPR_GP_OENABLE);
+ REG_WR(bp, MCP_REG_MCPR_GP_OENABLE, gp_oenable & ~epio_mask);
+
+ *en = (REG_RD(bp, MCP_REG_MCPR_GP_INPUTS) & epio_mask) >> epio_pin;
+}
+static void bnx2x_set_epio(struct bnx2x *bp, u32 epio_pin, u32 en)
+{
+ u32 epio_mask, gp_output, gp_oenable;
+
+ /* Sanity check */
+ if (epio_pin > 31) {
+ DP(NETIF_MSG_LINK, "Invalid EPIO pin %d to set\n", epio_pin);
+ return;
+ }
+ DP(NETIF_MSG_LINK, "Setting EPIO pin %d to %d\n", epio_pin, en);
+ epio_mask = 1 << epio_pin;
+ /* Set this EPIO to output */
+ gp_output = REG_RD(bp, MCP_REG_MCPR_GP_OUTPUTS);
+ if (en)
+ gp_output |= epio_mask;
+ else
+ gp_output &= ~epio_mask;
+
+ REG_WR(bp, MCP_REG_MCPR_GP_OUTPUTS, gp_output);
+
+ /* Set the value for this EPIO */
+ gp_oenable = REG_RD(bp, MCP_REG_MCPR_GP_OENABLE);
+ REG_WR(bp, MCP_REG_MCPR_GP_OENABLE, gp_oenable | epio_mask);
+}
+
+static void bnx2x_set_cfg_pin(struct bnx2x *bp, u32 pin_cfg, u32 val)
+{
+ if (pin_cfg == PIN_CFG_NA)
+ return;
+ if (pin_cfg >= PIN_CFG_EPIO0) {
+ bnx2x_set_epio(bp, pin_cfg - PIN_CFG_EPIO0, val);
+ } else {
+ u8 gpio_num = (pin_cfg - PIN_CFG_GPIO0_P0) & 0x3;
+ u8 gpio_port = (pin_cfg - PIN_CFG_GPIO0_P0) >> 2;
+ bnx2x_set_gpio(bp, gpio_num, (u8)val, gpio_port);
+ }
+}
+
+static u32 bnx2x_get_cfg_pin(struct bnx2x *bp, u32 pin_cfg, u32 *val)
+{
+ if (pin_cfg == PIN_CFG_NA)
+ return -EINVAL;
+ if (pin_cfg >= PIN_CFG_EPIO0) {
+ bnx2x_get_epio(bp, pin_cfg - PIN_CFG_EPIO0, val);
+ } else {
+ u8 gpio_num = (pin_cfg - PIN_CFG_GPIO0_P0) & 0x3;
+ u8 gpio_port = (pin_cfg - PIN_CFG_GPIO0_P0) >> 2;
+ *val = bnx2x_get_gpio(bp, gpio_num, gpio_port);
+ }
+ return 0;
+
+}
+/******************************************************************/
/* ETS section */
/******************************************************************/
-void bnx2x_ets_disabled(struct link_params *params)
+static void bnx2x_ets_e2e3a0_disabled(struct link_params *params)
{
/* ETS disabled configuration*/
struct bnx2x *bp = params->bp;
- DP(NETIF_MSG_LINK, "ETS disabled configuration\n");
+ DP(NETIF_MSG_LINK, "ETS E2E3 disabled configuration\n");
/*
* mapping between entry priority to client number (0,1,2 -debug and
@@ -262,7 +426,756 @@
/* Defines the number of consecutive slots for the strict priority */
REG_WR(bp, PBF_REG_NUM_STRICT_ARB_SLOTS, 0);
}
+/******************************************************************************
+* Description:
+* Getting min_w_val will be set according to line speed .
+*.
+******************************************************************************/
+static u32 bnx2x_ets_get_min_w_val_nig(const struct link_vars *vars)
+{
+ u32 min_w_val = 0;
+ /* Calculate min_w_val.*/
+ if (vars->link_up) {
+ if (SPEED_20000 == vars->line_speed)
+ min_w_val = ETS_E3B0_NIG_MIN_W_VAL_20GBPS;
+ else
+ min_w_val = ETS_E3B0_NIG_MIN_W_VAL_UP_TO_10GBPS;
+ } else
+ min_w_val = ETS_E3B0_NIG_MIN_W_VAL_20GBPS;
+ /**
+ * If the link isn't up (static configuration for example ) The
+ * link will be according to 20GBPS.
+ */
+ return min_w_val;
+}
+/******************************************************************************
+* Description:
+* Getting credit upper bound form min_w_val.
+*.
+******************************************************************************/
+static u32 bnx2x_ets_get_credit_upper_bound(const u32 min_w_val)
+{
+ const u32 credit_upper_bound = (u32)MAXVAL((150 * min_w_val),
+ MAX_PACKET_SIZE);
+ return credit_upper_bound;
+}
+/******************************************************************************
+* Description:
+* Set credit upper bound for NIG.
+*.
+******************************************************************************/
+static void bnx2x_ets_e3b0_set_credit_upper_bound_nig(
+ const struct link_params *params,
+ const u32 min_w_val)
+{
+ struct bnx2x *bp = params->bp;
+ const u8 port = params->port;
+ const u32 credit_upper_bound =
+ bnx2x_ets_get_credit_upper_bound(min_w_val);
+ REG_WR(bp, (port) ? NIG_REG_P1_TX_ARB_CREDIT_UPPER_BOUND_0 :
+ NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_0, credit_upper_bound);
+ REG_WR(bp, (port) ? NIG_REG_P1_TX_ARB_CREDIT_UPPER_BOUND_1 :
+ NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_1, credit_upper_bound);
+ REG_WR(bp, (port) ? NIG_REG_P1_TX_ARB_CREDIT_UPPER_BOUND_2 :
+ NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_2, credit_upper_bound);
+ REG_WR(bp, (port) ? NIG_REG_P1_TX_ARB_CREDIT_UPPER_BOUND_3 :
+ NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_3, credit_upper_bound);
+ REG_WR(bp, (port) ? NIG_REG_P1_TX_ARB_CREDIT_UPPER_BOUND_4 :
+ NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_4, credit_upper_bound);
+ REG_WR(bp, (port) ? NIG_REG_P1_TX_ARB_CREDIT_UPPER_BOUND_5 :
+ NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_5, credit_upper_bound);
+
+ if (0 == port) {
+ REG_WR(bp, NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_6,
+ credit_upper_bound);
+ REG_WR(bp, NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_7,
+ credit_upper_bound);
+ REG_WR(bp, NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_8,
+ credit_upper_bound);
+ }
+}
+/******************************************************************************
+* Description:
+* Will return the NIG ETS registers to init values.Except
+* credit_upper_bound.
+* That isn't used in this configuration (No WFQ is enabled) and will be
+* configured acording to spec
+*.
+******************************************************************************/
+static void bnx2x_ets_e3b0_nig_disabled(const struct link_params *params,
+ const struct link_vars *vars)
+{
+ struct bnx2x *bp = params->bp;
+ const u8 port = params->port;
+ const u32 min_w_val = bnx2x_ets_get_min_w_val_nig(vars);
+ /**
+ * mapping between entry priority to client number (0,1,2 -debug and
+ * management clients, 3 - COS0 client, 4 - COS1, ... 8 -
+ * COS5)(HIGHEST) 4bits client num.TODO_ETS - Should be done by
+ * reset value or init tool
+ */
+ if (port) {
+ REG_WR(bp, NIG_REG_P1_TX_ARB_PRIORITY_CLIENT2_LSB, 0x543210);
+ REG_WR(bp, NIG_REG_P1_TX_ARB_PRIORITY_CLIENT2_MSB, 0x0);
+ } else {
+ REG_WR(bp, NIG_REG_P0_TX_ARB_PRIORITY_CLIENT2_LSB, 0x76543210);
+ REG_WR(bp, NIG_REG_P0_TX_ARB_PRIORITY_CLIENT2_MSB, 0x8);
+ }
+ /**
+ * For strict priority entries defines the number of consecutive
+ * slots for the highest priority.
+ */
+ /* TODO_ETS - Should be done by reset value or init tool */
+ REG_WR(bp, (port) ? NIG_REG_P1_TX_ARB_NUM_STRICT_ARB_SLOTS :
+ NIG_REG_P1_TX_ARB_NUM_STRICT_ARB_SLOTS, 0x100);
+ /**
+ * mapping between the CREDIT_WEIGHT registers and actual client
+ * numbers
+ */
+ /* TODO_ETS - Should be done by reset value or init tool */
+ if (port) {
+ /*Port 1 has 6 COS*/
+ REG_WR(bp, NIG_REG_P1_TX_ARB_CLIENT_CREDIT_MAP2_LSB, 0x210543);
+ REG_WR(bp, NIG_REG_P1_TX_ARB_CLIENT_CREDIT_MAP2_MSB, 0x0);
+ } else {
+ /*Port 0 has 9 COS*/
+ REG_WR(bp, NIG_REG_P0_TX_ARB_CLIENT_CREDIT_MAP2_LSB,
+ 0x43210876);
+ REG_WR(bp, NIG_REG_P0_TX_ARB_CLIENT_CREDIT_MAP2_MSB, 0x5);
+ }
+
+ /**
+ * Bitmap of 5bits length. Each bit specifies whether the entry behaves
+ * as strict. Bits 0,1,2 - debug and management entries, 3 -
+ * COS0 entry, 4 - COS1 entry.
+ * COS1 | COS0 | DEBUG1 | DEBUG0 | MGMT
+ * bit4 bit3 bit2 bit1 bit0
+ * MCP and debug are strict
+ */
+ if (port)
+ REG_WR(bp, NIG_REG_P1_TX_ARB_CLIENT_IS_STRICT, 0x3f);
+ else
+ REG_WR(bp, NIG_REG_P0_TX_ARB_CLIENT_IS_STRICT, 0x1ff);
+ /* defines which entries (clients) are subjected to WFQ arbitration */
+ REG_WR(bp, (port) ? NIG_REG_P1_TX_ARB_CLIENT_IS_SUBJECT2WFQ :
+ NIG_REG_P0_TX_ARB_CLIENT_IS_SUBJECT2WFQ, 0);
+
+ /**
+ * Please notice the register address are note continuous and a
+ * for here is note appropriate.In 2 port mode port0 only COS0-5
+ * can be used. DEBUG1,DEBUG1,MGMT are never used for WFQ* In 4
+ * port mode port1 only COS0-2 can be used. DEBUG1,DEBUG1,MGMT
+ * are never used for WFQ
+ */
+ REG_WR(bp, (port) ? NIG_REG_P1_TX_ARB_CREDIT_WEIGHT_0 :
+ NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_0, 0x0);
+ REG_WR(bp, (port) ? NIG_REG_P1_TX_ARB_CREDIT_WEIGHT_1 :
+ NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_1, 0x0);
+ REG_WR(bp, (port) ? NIG_REG_P1_TX_ARB_CREDIT_WEIGHT_2 :
+ NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_2, 0x0);
+ REG_WR(bp, (port) ? NIG_REG_P1_TX_ARB_CREDIT_WEIGHT_3 :
+ NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_3, 0x0);
+ REG_WR(bp, (port) ? NIG_REG_P1_TX_ARB_CREDIT_WEIGHT_4 :
+ NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_4, 0x0);
+ REG_WR(bp, (port) ? NIG_REG_P1_TX_ARB_CREDIT_WEIGHT_5 :
+ NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_5, 0x0);
+ if (0 == port) {
+ REG_WR(bp, NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_6, 0x0);
+ REG_WR(bp, NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_7, 0x0);
+ REG_WR(bp, NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_8, 0x0);
+ }
+
+ bnx2x_ets_e3b0_set_credit_upper_bound_nig(params, min_w_val);
+}
+/******************************************************************************
+* Description:
+* Set credit upper bound for PBF.
+*.
+******************************************************************************/
+static void bnx2x_ets_e3b0_set_credit_upper_bound_pbf(
+ const struct link_params *params,
+ const u32 min_w_val)
+{
+ struct bnx2x *bp = params->bp;
+ const u32 credit_upper_bound =
+ bnx2x_ets_get_credit_upper_bound(min_w_val);
+ const u8 port = params->port;
+ u32 base_upper_bound = 0;
+ u8 max_cos = 0;
+ u8 i = 0;
+ /**
+ * In 2 port mode port0 has COS0-5 that can be used for WFQ.In 4
+ * port mode port1 has COS0-2 that can be used for WFQ.
+ */
+ if (0 == port) {
+ base_upper_bound = PBF_REG_COS0_UPPER_BOUND_P0;
+ max_cos = DCBX_E3B0_MAX_NUM_COS_PORT0;
+ } else {
+ base_upper_bound = PBF_REG_COS0_UPPER_BOUND_P1;
+ max_cos = DCBX_E3B0_MAX_NUM_COS_PORT1;
+ }
+
+ for (i = 0; i < max_cos; i++)
+ REG_WR(bp, base_upper_bound + (i << 2), credit_upper_bound);
+}
+
+/******************************************************************************
+* Description:
+* Will return the PBF ETS registers to init values.Except
+* credit_upper_bound.
+* That isn't used in this configuration (No WFQ is enabled) and will be
+* configured acording to spec
+*.
+******************************************************************************/
+static void bnx2x_ets_e3b0_pbf_disabled(const struct link_params *params)
+{
+ struct bnx2x *bp = params->bp;
+ const u8 port = params->port;
+ const u32 min_w_val_pbf = ETS_E3B0_PBF_MIN_W_VAL;
+ u8 i = 0;
+ u32 base_weight = 0;
+ u8 max_cos = 0;
+
+ /**
+ * mapping between entry priority to client number 0 - COS0
+ * client, 2 - COS1, ... 5 - COS5)(HIGHEST) 4bits client num.
+ * TODO_ETS - Should be done by reset value or init tool
+ */
+ if (port)
+ /* 0x688 (|011|0 10|00 1|000) */
+ REG_WR(bp, PBF_REG_ETS_ARB_PRIORITY_CLIENT_P1 , 0x688);
+ else
+ /* (10 1|100 |011|0 10|00 1|000) */
+ REG_WR(bp, PBF_REG_ETS_ARB_PRIORITY_CLIENT_P0 , 0x2C688);
+
+ /* TODO_ETS - Should be done by reset value or init tool */
+ if (port)
+ /* 0x688 (|011|0 10|00 1|000)*/
+ REG_WR(bp, PBF_REG_ETS_ARB_CLIENT_CREDIT_MAP_P1, 0x688);
+ else
+ /* 0x2C688 (10 1|100 |011|0 10|00 1|000) */
+ REG_WR(bp, PBF_REG_ETS_ARB_CLIENT_CREDIT_MAP_P0, 0x2C688);
+
+ REG_WR(bp, (port) ? PBF_REG_ETS_ARB_NUM_STRICT_ARB_SLOTS_P1 :
+ PBF_REG_ETS_ARB_NUM_STRICT_ARB_SLOTS_P0 , 0x100);
+
+
+ REG_WR(bp, (port) ? PBF_REG_ETS_ARB_CLIENT_IS_STRICT_P1 :
+ PBF_REG_ETS_ARB_CLIENT_IS_STRICT_P0 , 0);
+
+ REG_WR(bp, (port) ? PBF_REG_ETS_ARB_CLIENT_IS_SUBJECT2WFQ_P1 :
+ PBF_REG_ETS_ARB_CLIENT_IS_SUBJECT2WFQ_P0 , 0);
+ /**
+ * In 2 port mode port0 has COS0-5 that can be used for WFQ.
+ * In 4 port mode port1 has COS0-2 that can be used for WFQ.
+ */
+ if (0 == port) {
+ base_weight = PBF_REG_COS0_WEIGHT_P0;
+ max_cos = DCBX_E3B0_MAX_NUM_COS_PORT0;
+ } else {
+ base_weight = PBF_REG_COS0_WEIGHT_P1;
+ max_cos = DCBX_E3B0_MAX_NUM_COS_PORT1;
+ }
+
+ for (i = 0; i < max_cos; i++)
+ REG_WR(bp, base_weight + (0x4 * i), 0);
+
+ bnx2x_ets_e3b0_set_credit_upper_bound_pbf(params, min_w_val_pbf);
+}
+/******************************************************************************
+* Description:
+* E3B0 disable will return basicly the values to init values.
+*.
+******************************************************************************/
+static int bnx2x_ets_e3b0_disabled(const struct link_params *params,
+ const struct link_vars *vars)
+{
+ struct bnx2x *bp = params->bp;
+
+ if (!CHIP_IS_E3B0(bp)) {
+ DP(NETIF_MSG_LINK, "bnx2x_ets_e3b0_disabled the chip isn't E3B0"
+ "\n");
+ return -EINVAL;
+ }
+
+ bnx2x_ets_e3b0_nig_disabled(params, vars);
+
+ bnx2x_ets_e3b0_pbf_disabled(params);
+
+ return 0;
+}
+
+/******************************************************************************
+* Description:
+* Disable will return basicly the values to init values.
+*.
+******************************************************************************/
+int bnx2x_ets_disabled(struct link_params *params,
+ struct link_vars *vars)
+{
+ struct bnx2x *bp = params->bp;
+ int bnx2x_status = 0;
+
+ if ((CHIP_IS_E2(bp)) || (CHIP_IS_E3A0(bp)))
+ bnx2x_ets_e2e3a0_disabled(params);
+ else if (CHIP_IS_E3B0(bp))
+ bnx2x_status = bnx2x_ets_e3b0_disabled(params, vars);
+ else {
+ DP(NETIF_MSG_LINK, "bnx2x_ets_disabled - chip not supported\n");
+ return -EINVAL;
+ }
+
+ return bnx2x_status;
+}
+
+/******************************************************************************
+* Description
+* Set the COS mappimg to SP and BW until this point all the COS are not
+* set as SP or BW.
+******************************************************************************/
+static int bnx2x_ets_e3b0_cli_map(const struct link_params *params,
+ const struct bnx2x_ets_params *ets_params,
+ const u8 cos_sp_bitmap,
+ const u8 cos_bw_bitmap)
+{
+ struct bnx2x *bp = params->bp;
+ const u8 port = params->port;
+ const u8 nig_cli_sp_bitmap = 0x7 | (cos_sp_bitmap << 3);
+ const u8 pbf_cli_sp_bitmap = cos_sp_bitmap;
+ const u8 nig_cli_subject2wfq_bitmap = cos_bw_bitmap << 3;
+ const u8 pbf_cli_subject2wfq_bitmap = cos_bw_bitmap;
+
+ REG_WR(bp, (port) ? NIG_REG_P1_TX_ARB_CLIENT_IS_STRICT :
+ NIG_REG_P0_TX_ARB_CLIENT_IS_STRICT, nig_cli_sp_bitmap);
+
+ REG_WR(bp, (port) ? PBF_REG_ETS_ARB_CLIENT_IS_STRICT_P1 :
+ PBF_REG_ETS_ARB_CLIENT_IS_STRICT_P0 , pbf_cli_sp_bitmap);
+
+ REG_WR(bp, (port) ? NIG_REG_P1_TX_ARB_CLIENT_IS_SUBJECT2WFQ :
+ NIG_REG_P0_TX_ARB_CLIENT_IS_SUBJECT2WFQ,
+ nig_cli_subject2wfq_bitmap);
+
+ REG_WR(bp, (port) ? PBF_REG_ETS_ARB_CLIENT_IS_SUBJECT2WFQ_P1 :
+ PBF_REG_ETS_ARB_CLIENT_IS_SUBJECT2WFQ_P0,
+ pbf_cli_subject2wfq_bitmap);
+
+ return 0;
+}
+
+/******************************************************************************
+* Description:
+* This function is needed because NIG ARB_CREDIT_WEIGHT_X are
+* not continues and ARB_CREDIT_WEIGHT_0 + offset is suitable.
+******************************************************************************/
+static int bnx2x_ets_e3b0_set_cos_bw(struct bnx2x *bp,
+ const u8 cos_entry,
+ const u32 min_w_val_nig,
+ const u32 min_w_val_pbf,
+ const u16 total_bw,
+ const u8 bw,
+ const u8 port)
+{
+ u32 nig_reg_adress_crd_weight = 0;
+ u32 pbf_reg_adress_crd_weight = 0;
+ /* Calculate and set BW for this COS*/
+ const u32 cos_bw_nig = (bw * min_w_val_nig) / total_bw;
+ const u32 cos_bw_pbf = (bw * min_w_val_pbf) / total_bw;
+
+ switch (cos_entry) {
+ case 0:
+ nig_reg_adress_crd_weight =
+ (port) ? NIG_REG_P1_TX_ARB_CREDIT_WEIGHT_0 :
+ NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_0;
+ pbf_reg_adress_crd_weight = (port) ?
+ PBF_REG_COS0_WEIGHT_P1 : PBF_REG_COS0_WEIGHT_P0;
+ break;
+ case 1:
+ nig_reg_adress_crd_weight = (port) ?
+ NIG_REG_P1_TX_ARB_CREDIT_WEIGHT_1 :
+ NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_1;
+ pbf_reg_adress_crd_weight = (port) ?
+ PBF_REG_COS1_WEIGHT_P1 : PBF_REG_COS1_WEIGHT_P0;
+ break;
+ case 2:
+ nig_reg_adress_crd_weight = (port) ?
+ NIG_REG_P1_TX_ARB_CREDIT_WEIGHT_2 :
+ NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_2;
+
+ pbf_reg_adress_crd_weight = (port) ?
+ PBF_REG_COS2_WEIGHT_P1 : PBF_REG_COS2_WEIGHT_P0;
+ break;
+ case 3:
+ if (port)
+ return -EINVAL;
+ nig_reg_adress_crd_weight =
+ NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_3;
+ pbf_reg_adress_crd_weight =
+ PBF_REG_COS3_WEIGHT_P0;
+ break;
+ case 4:
+ if (port)
+ return -EINVAL;
+ nig_reg_adress_crd_weight =
+ NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_4;
+ pbf_reg_adress_crd_weight = PBF_REG_COS4_WEIGHT_P0;
+ break;
+ case 5:
+ if (port)
+ return -EINVAL;
+ nig_reg_adress_crd_weight =
+ NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_5;
+ pbf_reg_adress_crd_weight = PBF_REG_COS5_WEIGHT_P0;
+ break;
+ }
+
+ REG_WR(bp, nig_reg_adress_crd_weight, cos_bw_nig);
+
+ REG_WR(bp, pbf_reg_adress_crd_weight, cos_bw_pbf);
+
+ return 0;
+}
+/******************************************************************************
+* Description:
+* Calculate the total BW.A value of 0 isn't legal.
+*.
+******************************************************************************/
+static int bnx2x_ets_e3b0_get_total_bw(
+ const struct link_params *params,
+ const struct bnx2x_ets_params *ets_params,
+ u16 *total_bw)
+{
+ struct bnx2x *bp = params->bp;
+ u8 cos_idx = 0;
+
+ *total_bw = 0 ;
+ /* Calculate total BW requested */
+ for (cos_idx = 0; cos_idx < ets_params->num_of_cos; cos_idx++) {
+ if (bnx2x_cos_state_bw == ets_params->cos[cos_idx].state) {
+
+ if (0 == ets_params->cos[cos_idx].params.bw_params.bw) {
+ DP(NETIF_MSG_LINK, "bnx2x_ets_E3B0_config BW"
+ "was set to 0\n");
+ return -EINVAL;
+ }
+ *total_bw +=
+ ets_params->cos[cos_idx].params.bw_params.bw;
+ }
+ }
+
+ /*Check taotl BW is valid */
+ if ((100 != *total_bw) || (0 == *total_bw)) {
+ if (0 == *total_bw) {
+ DP(NETIF_MSG_LINK, "bnx2x_ets_E3B0_config toatl BW"
+ "shouldn't be 0\n");
+ return -EINVAL;
+ }
+ DP(NETIF_MSG_LINK, "bnx2x_ets_E3B0_config toatl BW should be"
+ "100\n");
+ /**
+ * We can handle a case whre the BW isn't 100 this can happen
+ * if the TC are joined.
+ */
+ }
+ return 0;
+}
+
+/******************************************************************************
+* Description:
+* Invalidate all the sp_pri_to_cos.
+*.
+******************************************************************************/
+static void bnx2x_ets_e3b0_sp_pri_to_cos_init(u8 *sp_pri_to_cos)
+{
+ u8 pri = 0;
+ for (pri = 0; pri < DCBX_MAX_NUM_COS; pri++)
+ sp_pri_to_cos[pri] = DCBX_INVALID_COS;
+}
+/******************************************************************************
+* Description:
+* Calculate and set the SP (ARB_PRIORITY_CLIENT) NIG and PBF registers
+* according to sp_pri_to_cos.
+*.
+******************************************************************************/
+static int bnx2x_ets_e3b0_sp_pri_to_cos_set(const struct link_params *params,
+ u8 *sp_pri_to_cos, const u8 pri,
+ const u8 cos_entry)
+{
+ struct bnx2x *bp = params->bp;
+ const u8 port = params->port;
+ const u8 max_num_of_cos = (port) ? DCBX_E3B0_MAX_NUM_COS_PORT1 :
+ DCBX_E3B0_MAX_NUM_COS_PORT0;
+
+ if (DCBX_INVALID_COS != sp_pri_to_cos[pri]) {
+ DP(NETIF_MSG_LINK, "bnx2x_ets_e3b0_sp_pri_to_cos_set invalid "
+ "parameter There can't be two COS's with"
+ "the same strict pri\n");
+ return -EINVAL;
+ }
+
+ if (pri > max_num_of_cos) {
+ DP(NETIF_MSG_LINK, "bnx2x_ets_e3b0_sp_pri_to_cos_set invalid"
+ "parameter Illegal strict priority\n");
+ return -EINVAL;
+ }
+
+ sp_pri_to_cos[pri] = cos_entry;
+ return 0;
+
+}
+
+/******************************************************************************
+* Description:
+* Returns the correct value according to COS and priority in
+* the sp_pri_cli register.
+*.
+******************************************************************************/
+static u64 bnx2x_e3b0_sp_get_pri_cli_reg(const u8 cos, const u8 cos_offset,
+ const u8 pri_set,
+ const u8 pri_offset,
+ const u8 entry_size)
+{
+ u64 pri_cli_nig = 0;
+ pri_cli_nig = ((u64)(cos + cos_offset)) << (entry_size *
+ (pri_set + pri_offset));
+
+ return pri_cli_nig;
+}
+/******************************************************************************
+* Description:
+* Returns the correct value according to COS and priority in the
+* sp_pri_cli register for NIG.
+*.
+******************************************************************************/
+static u64 bnx2x_e3b0_sp_get_pri_cli_reg_nig(const u8 cos, const u8 pri_set)
+{
+ /* MCP Dbg0 and dbg1 are always with higher strict pri*/
+ const u8 nig_cos_offset = 3;
+ const u8 nig_pri_offset = 3;
+
+ return bnx2x_e3b0_sp_get_pri_cli_reg(cos, nig_cos_offset, pri_set,
+ nig_pri_offset, 4);
+
+}
+/******************************************************************************
+* Description:
+* Returns the correct value according to COS and priority in the
+* sp_pri_cli register for PBF.
+*.
+******************************************************************************/
+static u64 bnx2x_e3b0_sp_get_pri_cli_reg_pbf(const u8 cos, const u8 pri_set)
+{
+ const u8 pbf_cos_offset = 0;
+ const u8 pbf_pri_offset = 0;
+
+ return bnx2x_e3b0_sp_get_pri_cli_reg(cos, pbf_cos_offset, pri_set,
+ pbf_pri_offset, 3);
+
+}
+
+/******************************************************************************
+* Description:
+* Calculate and set the SP (ARB_PRIORITY_CLIENT) NIG and PBF registers
+* according to sp_pri_to_cos.(which COS has higher priority)
+*.
+******************************************************************************/
+static int bnx2x_ets_e3b0_sp_set_pri_cli_reg(const struct link_params *params,
+ u8 *sp_pri_to_cos)
+{
+ struct bnx2x *bp = params->bp;
+ u8 i = 0;
+ const u8 port = params->port;
+ /* MCP Dbg0 and dbg1 are always with higher strict pri*/
+ u64 pri_cli_nig = 0x210;
+ u32 pri_cli_pbf = 0x0;
+ u8 pri_set = 0;
+ u8 pri_bitmask = 0;
+ const u8 max_num_of_cos = (port) ? DCBX_E3B0_MAX_NUM_COS_PORT1 :
+ DCBX_E3B0_MAX_NUM_COS_PORT0;
+
+ u8 cos_bit_to_set = (1 << max_num_of_cos) - 1;
+
+ /* Set all the strict priority first */
+ for (i = 0; i < max_num_of_cos; i++) {
+ if (DCBX_INVALID_COS != sp_pri_to_cos[i]) {
+ if (DCBX_MAX_NUM_COS <= sp_pri_to_cos[i]) {
+ DP(NETIF_MSG_LINK,
+ "bnx2x_ets_e3b0_sp_set_pri_cli_reg "
+ "invalid cos entry\n");
+ return -EINVAL;
+ }
+
+ pri_cli_nig |= bnx2x_e3b0_sp_get_pri_cli_reg_nig(
+ sp_pri_to_cos[i], pri_set);
+
+ pri_cli_pbf |= bnx2x_e3b0_sp_get_pri_cli_reg_pbf(
+ sp_pri_to_cos[i], pri_set);
+ pri_bitmask = 1 << sp_pri_to_cos[i];
+ /* COS is used remove it from bitmap.*/
+ if (0 == (pri_bitmask & cos_bit_to_set)) {
+ DP(NETIF_MSG_LINK,
+ "bnx2x_ets_e3b0_sp_set_pri_cli_reg "
+ "invalid There can't be two COS's with"
+ " the same strict pri\n");
+ return -EINVAL;
+ }
+ cos_bit_to_set &= ~pri_bitmask;
+ pri_set++;
+ }
+ }
+
+ /* Set all the Non strict priority i= COS*/
+ for (i = 0; i < max_num_of_cos; i++) {
+ pri_bitmask = 1 << i;
+ /* Check if COS was already used for SP */
+ if (pri_bitmask & cos_bit_to_set) {
+ /* COS wasn't used for SP */
+ pri_cli_nig |= bnx2x_e3b0_sp_get_pri_cli_reg_nig(
+ i, pri_set);
+
+ pri_cli_pbf |= bnx2x_e3b0_sp_get_pri_cli_reg_pbf(
+ i, pri_set);
+ /* COS is used remove it from bitmap.*/
+ cos_bit_to_set &= ~pri_bitmask;
+ pri_set++;
+ }
+ }
+
+ if (pri_set != max_num_of_cos) {
+ DP(NETIF_MSG_LINK, "bnx2x_ets_e3b0_sp_set_pri_cli_reg not all "
+ "entries were set\n");
+ return -EINVAL;
+ }
+
+ if (port) {
+ /* Only 6 usable clients*/
+ REG_WR(bp, NIG_REG_P1_TX_ARB_PRIORITY_CLIENT2_LSB,
+ (u32)pri_cli_nig);
+
+ REG_WR(bp, PBF_REG_ETS_ARB_PRIORITY_CLIENT_P1 , pri_cli_pbf);
+ } else {
+ /* Only 9 usable clients*/
+ const u32 pri_cli_nig_lsb = (u32) (pri_cli_nig);
+ const u32 pri_cli_nig_msb = (u32) ((pri_cli_nig >> 32) & 0xF);
+
+ REG_WR(bp, NIG_REG_P0_TX_ARB_PRIORITY_CLIENT2_LSB,
+ pri_cli_nig_lsb);
+ REG_WR(bp, NIG_REG_P0_TX_ARB_PRIORITY_CLIENT2_MSB,
+ pri_cli_nig_msb);
+
+ REG_WR(bp, PBF_REG_ETS_ARB_PRIORITY_CLIENT_P0 , pri_cli_pbf);
+ }
+ return 0;
+}
+
+/******************************************************************************
+* Description:
+* Configure the COS to ETS according to BW and SP settings.
+******************************************************************************/
+int bnx2x_ets_e3b0_config(const struct link_params *params,
+ const struct link_vars *vars,
+ const struct bnx2x_ets_params *ets_params)
+{
+ struct bnx2x *bp = params->bp;
+ int bnx2x_status = 0;
+ const u8 port = params->port;
+ u16 total_bw = 0;
+ const u32 min_w_val_nig = bnx2x_ets_get_min_w_val_nig(vars);
+ const u32 min_w_val_pbf = ETS_E3B0_PBF_MIN_W_VAL;
+ u8 cos_bw_bitmap = 0;
+ u8 cos_sp_bitmap = 0;
+ u8 sp_pri_to_cos[DCBX_MAX_NUM_COS] = {0};
+ const u8 max_num_of_cos = (port) ? DCBX_E3B0_MAX_NUM_COS_PORT1 :
+ DCBX_E3B0_MAX_NUM_COS_PORT0;
+ u8 cos_entry = 0;
+
+ if (!CHIP_IS_E3B0(bp)) {
+ DP(NETIF_MSG_LINK, "bnx2x_ets_e3b0_disabled the chip isn't E3B0"
+ "\n");
+ return -EINVAL;
+ }
+
+ if ((ets_params->num_of_cos > max_num_of_cos)) {
+ DP(NETIF_MSG_LINK, "bnx2x_ets_E3B0_config the number of COS "
+ "isn't supported\n");
+ return -EINVAL;
+ }
+
+ /* Prepare sp strict priority parameters*/
+ bnx2x_ets_e3b0_sp_pri_to_cos_init(sp_pri_to_cos);
+
+ /* Prepare BW parameters*/
+ bnx2x_status = bnx2x_ets_e3b0_get_total_bw(params, ets_params,
+ &total_bw);
+ if (0 != bnx2x_status) {
+ DP(NETIF_MSG_LINK, "bnx2x_ets_E3B0_config get_total_bw failed "
+ "\n");
+ return -EINVAL;
+ }
+
+ /**
+ * Upper bound is set according to current link speed (min_w_val
+ * should be the same for upper bound and COS credit val).
+ */
+ bnx2x_ets_e3b0_set_credit_upper_bound_nig(params, min_w_val_nig);
+ bnx2x_ets_e3b0_set_credit_upper_bound_pbf(params, min_w_val_pbf);
+
+
+ for (cos_entry = 0; cos_entry < ets_params->num_of_cos; cos_entry++) {
+ if (bnx2x_cos_state_bw == ets_params->cos[cos_entry].state) {
+ cos_bw_bitmap |= (1 << cos_entry);
+ /**
+ * The function also sets the BW in HW(not the mappin
+ * yet)
+ */
+ bnx2x_status = bnx2x_ets_e3b0_set_cos_bw(
+ bp, cos_entry, min_w_val_nig, min_w_val_pbf,
+ total_bw,
+ ets_params->cos[cos_entry].params.bw_params.bw,
+ port);
+ } else if (bnx2x_cos_state_strict ==
+ ets_params->cos[cos_entry].state){
+ cos_sp_bitmap |= (1 << cos_entry);
+
+ bnx2x_status = bnx2x_ets_e3b0_sp_pri_to_cos_set(
+ params,
+ sp_pri_to_cos,
+ ets_params->cos[cos_entry].params.sp_params.pri,
+ cos_entry);
+
+ } else {
+ DP(NETIF_MSG_LINK, "bnx2x_ets_e3b0_config cos state not"
+ " valid\n");
+ return -EINVAL;
+ }
+ if (0 != bnx2x_status) {
+ DP(NETIF_MSG_LINK, "bnx2x_ets_e3b0_config set cos bw "
+ "failed\n");
+ return bnx2x_status;
+ }
+ }
+
+ /* Set SP register (which COS has higher priority) */
+ bnx2x_status = bnx2x_ets_e3b0_sp_set_pri_cli_reg(params,
+ sp_pri_to_cos);
+
+ if (0 != bnx2x_status) {
+ DP(NETIF_MSG_LINK, "bnx2x_ets_E3B0_config set_pri_cli_reg "
+ "failed\n");
+ return bnx2x_status;
+ }
+
+ /* Set client mapping of BW and strict */
+ bnx2x_status = bnx2x_ets_e3b0_cli_map(params, ets_params,
+ cos_sp_bitmap,
+ cos_bw_bitmap);
+
+ if (0 != bnx2x_status) {
+ DP(NETIF_MSG_LINK, "bnx2x_ets_E3B0_config SP failed\n");
+ return bnx2x_status;
+ }
+ return 0;
+}
static void bnx2x_ets_bw_limit_common(const struct link_params *params)
{
/* ETS disabled configuration */
@@ -342,7 +1255,7 @@
REG_WR(bp, PBF_REG_COS1_WEIGHT, cos1_credit_weight);
}
-u8 bnx2x_ets_strict(const struct link_params *params, const u8 strict_cos)
+int bnx2x_ets_strict(const struct link_params *params, const u8 strict_cos)
{
/* ETS disabled configuration*/
struct bnx2x *bp = params->bp;
@@ -388,24 +1301,64 @@
/* PFC section */
/******************************************************************/
-static void bnx2x_bmac2_get_pfc_stat(struct link_params *params,
- u32 pfc_frames_sent[2],
- u32 pfc_frames_received[2])
+static void bnx2x_update_pfc_xmac(struct link_params *params,
+ struct link_vars *vars,
+ u8 is_lb)
{
- /* Read pfc statistic */
struct bnx2x *bp = params->bp;
- u32 bmac_addr = params->port ? NIG_REG_INGRESS_BMAC1_MEM :
- NIG_REG_INGRESS_BMAC0_MEM;
+ u32 xmac_base;
+ u32 pause_val, pfc0_val, pfc1_val;
- DP(NETIF_MSG_LINK, "pfc statistic read from BMAC\n");
+ /* XMAC base adrr */
+ xmac_base = (params->port) ? GRCBASE_XMAC1 : GRCBASE_XMAC0;
- REG_RD_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_TX_STAT_GTPP,
- pfc_frames_sent, 2);
+ /* Initialize pause and pfc registers */
+ pause_val = 0x18000;
+ pfc0_val = 0xFFFF8000;
+ pfc1_val = 0x2;
- REG_RD_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_RX_STAT_GRPP,
- pfc_frames_received, 2);
+ /* No PFC support */
+ if (!(params->feature_config_flags &
+ FEATURE_CONFIG_PFC_ENABLED)) {
+ /*
+ * RX flow control - Process pause frame in receive direction
+ */
+ if (vars->flow_ctrl & BNX2X_FLOW_CTRL_RX)
+ pause_val |= XMAC_PAUSE_CTRL_REG_RX_PAUSE_EN;
+
+ /*
+ * TX flow control - Send pause packet when buffer is full
+ */
+ if (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX)
+ pause_val |= XMAC_PAUSE_CTRL_REG_TX_PAUSE_EN;
+ } else {/* PFC support */
+ pfc1_val |= XMAC_PFC_CTRL_HI_REG_PFC_REFRESH_EN |
+ XMAC_PFC_CTRL_HI_REG_PFC_STATS_EN |
+ XMAC_PFC_CTRL_HI_REG_RX_PFC_EN |
+ XMAC_PFC_CTRL_HI_REG_TX_PFC_EN;
+ }
+
+ /* Write pause and PFC registers */
+ REG_WR(bp, xmac_base + XMAC_REG_PAUSE_CTRL, pause_val);
+ REG_WR(bp, xmac_base + XMAC_REG_PFC_CTRL, pfc0_val);
+ REG_WR(bp, xmac_base + XMAC_REG_PFC_CTRL_HI, pfc1_val);
+
+
+ /* Set MAC address for source TX Pause/PFC frames */
+ REG_WR(bp, xmac_base + XMAC_REG_CTRL_SA_LO,
+ ((params->mac_addr[2] << 24) |
+ (params->mac_addr[3] << 16) |
+ (params->mac_addr[4] << 8) |
+ (params->mac_addr[5])));
+ REG_WR(bp, xmac_base + XMAC_REG_CTRL_SA_HI,
+ ((params->mac_addr[0] << 8) |
+ (params->mac_addr[1])));
+
+ udelay(30);
}
+
+
static void bnx2x_emac_get_pfc_stat(struct link_params *params,
u32 pfc_frames_sent[2],
u32 pfc_frames_received[2])
@@ -437,33 +1390,54 @@
pfc_frames_sent[0] = val_xon + val_xoff;
}
+/* Read pfc statistic*/
void bnx2x_pfc_statistic(struct link_params *params, struct link_vars *vars,
u32 pfc_frames_sent[2],
u32 pfc_frames_received[2])
{
/* Read pfc statistic */
struct bnx2x *bp = params->bp;
- u32 val = 0;
+
DP(NETIF_MSG_LINK, "pfc statistic\n");
if (!vars->link_up)
return;
- val = REG_RD(bp, MISC_REG_RESET_REG_2);
- if ((val & (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << params->port))
- == 0) {
- DP(NETIF_MSG_LINK, "About to read stats from EMAC\n");
+ if (MAC_TYPE_EMAC == vars->mac_type) {
+ DP(NETIF_MSG_LINK, "About to read PFC stats from EMAC\n");
bnx2x_emac_get_pfc_stat(params, pfc_frames_sent,
pfc_frames_received);
- } else {
- DP(NETIF_MSG_LINK, "About to read stats from BMAC\n");
- bnx2x_bmac2_get_pfc_stat(params, pfc_frames_sent,
- pfc_frames_received);
}
}
/******************************************************************/
/* MAC/PBF section */
/******************************************************************/
+static void bnx2x_set_mdio_clk(struct bnx2x *bp, u32 chip_id, u8 port)
+{
+ u32 mode, emac_base;
+ /**
+ * Set clause 45 mode, slow down the MDIO clock to 2.5MHz
+ * (a value of 49==0x31) and make sure that the AUTO poll is off
+ */
+
+ if (CHIP_IS_E2(bp))
+ emac_base = GRCBASE_EMAC0;
+ else
+ emac_base = (port) ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
+ mode = REG_RD(bp, emac_base + EMAC_REG_EMAC_MDIO_MODE);
+ mode &= ~(EMAC_MDIO_MODE_AUTO_POLL |
+ EMAC_MDIO_MODE_CLOCK_CNT);
+ if (USES_WARPCORE(bp))
+ mode |= (74L << EMAC_MDIO_MODE_CLOCK_CNT_BITSHIFT);
+ else
+ mode |= (49L << EMAC_MDIO_MODE_CLOCK_CNT_BITSHIFT);
+
+ mode |= (EMAC_MDIO_MODE_CLAUSE_45);
+ REG_WR(bp, emac_base + EMAC_REG_EMAC_MDIO_MODE, mode);
+
+ udelay(40);
+}
+
static void bnx2x_emac_init(struct link_params *params,
struct link_vars *vars)
{
@@ -495,7 +1469,7 @@
}
timeout--;
} while (val & EMAC_MODE_RESET);
-
+ bnx2x_set_mdio_clk(bp, params->chip_id, port);
/* Set mac address */
val = ((params->mac_addr[0] << 8) |
params->mac_addr[1]);
@@ -508,9 +1482,246 @@
EMAC_WR(bp, EMAC_REG_EMAC_MAC_MATCH + 4, val);
}
-static u8 bnx2x_emac_enable(struct link_params *params,
+static void bnx2x_set_xumac_nig(struct link_params *params,
+ u16 tx_pause_en,
+ u8 enable)
+{
+ struct bnx2x *bp = params->bp;
+
+ REG_WR(bp, params->port ? NIG_REG_P1_MAC_IN_EN : NIG_REG_P0_MAC_IN_EN,
+ enable);
+ REG_WR(bp, params->port ? NIG_REG_P1_MAC_OUT_EN : NIG_REG_P0_MAC_OUT_EN,
+ enable);
+ REG_WR(bp, params->port ? NIG_REG_P1_MAC_PAUSE_OUT_EN :
+ NIG_REG_P0_MAC_PAUSE_OUT_EN, tx_pause_en);
+}
+
+static void bnx2x_umac_enable(struct link_params *params,
struct link_vars *vars, u8 lb)
{
+ u32 val;
+ u32 umac_base = params->port ? GRCBASE_UMAC1 : GRCBASE_UMAC0;
+ struct bnx2x *bp = params->bp;
+ /* Reset UMAC */
+ REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR,
+ (MISC_REGISTERS_RESET_REG_2_UMAC0 << params->port));
+ usleep_range(1000, 1000);
+
+ REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET,
+ (MISC_REGISTERS_RESET_REG_2_UMAC0 << params->port));
+
+ DP(NETIF_MSG_LINK, "enabling UMAC\n");
+
+ /**
+ * This register determines on which events the MAC will assert
+ * error on the i/f to the NIG along w/ EOP.
+ */
+
+ /**
+ * BD REG_WR(bp, NIG_REG_P0_MAC_RSV_ERR_MASK +
+ * params->port*0x14, 0xfffff.
+ */
+ /* This register opens the gate for the UMAC despite its name */
+ REG_WR(bp, NIG_REG_EGRESS_EMAC0_PORT + params->port*4, 1);
+
+ val = UMAC_COMMAND_CONFIG_REG_PROMIS_EN |
+ UMAC_COMMAND_CONFIG_REG_PAD_EN |
+ UMAC_COMMAND_CONFIG_REG_SW_RESET |
+ UMAC_COMMAND_CONFIG_REG_NO_LGTH_CHECK;
+ switch (vars->line_speed) {
+ case SPEED_10:
+ val |= (0<<2);
+ break;
+ case SPEED_100:
+ val |= (1<<2);
+ break;
+ case SPEED_1000:
+ val |= (2<<2);
+ break;
+ case SPEED_2500:
+ val |= (3<<2);
+ break;
+ default:
+ DP(NETIF_MSG_LINK, "Invalid speed for UMAC %d\n",
+ vars->line_speed);
+ break;
+ }
+ REG_WR(bp, umac_base + UMAC_REG_COMMAND_CONFIG, val);
+ udelay(50);
+
+ /* Set MAC address for source TX Pause/PFC frames (under SW reset) */
+ REG_WR(bp, umac_base + UMAC_REG_MAC_ADDR0,
+ ((params->mac_addr[2] << 24) |
+ (params->mac_addr[3] << 16) |
+ (params->mac_addr[4] << 8) |
+ (params->mac_addr[5])));
+ REG_WR(bp, umac_base + UMAC_REG_MAC_ADDR1,
+ ((params->mac_addr[0] << 8) |
+ (params->mac_addr[1])));
+
+ /* Enable RX and TX */
+ val &= ~UMAC_COMMAND_CONFIG_REG_PAD_EN;
+ val |= UMAC_COMMAND_CONFIG_REG_TX_ENA |
+ UMAC_COMMAND_CONFIG_REG_RX_ENA;
+ REG_WR(bp, umac_base + UMAC_REG_COMMAND_CONFIG, val);
+ udelay(50);
+
+ /* Remove SW Reset */
+ val &= ~UMAC_COMMAND_CONFIG_REG_SW_RESET;
+
+ /* Check loopback mode */
+ if (lb)
+ val |= UMAC_COMMAND_CONFIG_REG_LOOP_ENA;
+ REG_WR(bp, umac_base + UMAC_REG_COMMAND_CONFIG, val);
+
+ /*
+ * Maximum Frame Length (RW). Defines a 14-Bit maximum frame
+ * length used by the MAC receive logic to check frames.
+ */
+ REG_WR(bp, umac_base + UMAC_REG_MAXFR, 0x2710);
+ bnx2x_set_xumac_nig(params,
+ ((vars->flow_ctrl & BNX2X_FLOW_CTRL_TX) != 0), 1);
+ vars->mac_type = MAC_TYPE_UMAC;
+
+}
+
+static u8 bnx2x_is_4_port_mode(struct bnx2x *bp)
+{
+ u32 port4mode_ovwr_val;
+ /* Check 4-port override enabled */
+ port4mode_ovwr_val = REG_RD(bp, MISC_REG_PORT4MODE_EN_OVWR);
+ if (port4mode_ovwr_val & (1<<0)) {
+ /* Return 4-port mode override value */
+ return ((port4mode_ovwr_val & (1<<1)) == (1<<1));
+ }
+ /* Return 4-port mode from input pin */
+ return (u8)REG_RD(bp, MISC_REG_PORT4MODE_EN);
+}
+
+/* Define the XMAC mode */
+static void bnx2x_xmac_init(struct bnx2x *bp, u32 max_speed)
+{
+ u32 is_port4mode = bnx2x_is_4_port_mode(bp);
+
+ /**
+ * In 4-port mode, need to set the mode only once, so if XMAC is
+ * already out of reset, it means the mode has already been set,
+ * and it must not* reset the XMAC again, since it controls both
+ * ports of the path
+ **/
+
+ if (is_port4mode && (REG_RD(bp, MISC_REG_RESET_REG_2) &
+ MISC_REGISTERS_RESET_REG_2_XMAC)) {
+ DP(NETIF_MSG_LINK, "XMAC already out of reset"
+ " in 4-port mode\n");
+ return;
+ }
+
+ /* Hard reset */
+ REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR,
+ MISC_REGISTERS_RESET_REG_2_XMAC);
+ usleep_range(1000, 1000);
+
+ REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET,
+ MISC_REGISTERS_RESET_REG_2_XMAC);
+ if (is_port4mode) {
+ DP(NETIF_MSG_LINK, "Init XMAC to 2 ports x 10G per path\n");
+
+ /* Set the number of ports on the system side to up to 2 */
+ REG_WR(bp, MISC_REG_XMAC_CORE_PORT_MODE, 1);
+
+ /* Set the number of ports on the Warp Core to 10G */
+ REG_WR(bp, MISC_REG_XMAC_PHY_PORT_MODE, 3);
+ } else {
+ /* Set the number of ports on the system side to 1 */
+ REG_WR(bp, MISC_REG_XMAC_CORE_PORT_MODE, 0);
+ if (max_speed == SPEED_10000) {
+ DP(NETIF_MSG_LINK, "Init XMAC to 10G x 1"
+ " port per path\n");
+ /* Set the number of ports on the Warp Core to 10G */
+ REG_WR(bp, MISC_REG_XMAC_PHY_PORT_MODE, 3);
+ } else {
+ DP(NETIF_MSG_LINK, "Init XMAC to 20G x 2 ports"
+ " per path\n");
+ /* Set the number of ports on the Warp Core to 20G */
+ REG_WR(bp, MISC_REG_XMAC_PHY_PORT_MODE, 1);
+ }
+ }
+ /* Soft reset */
+ REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR,
+ MISC_REGISTERS_RESET_REG_2_XMAC_SOFT);
+ usleep_range(1000, 1000);
+
+ REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET,
+ MISC_REGISTERS_RESET_REG_2_XMAC_SOFT);
+
+}
+
+static void bnx2x_xmac_disable(struct link_params *params)
+{
+ u8 port = params->port;
+ struct bnx2x *bp = params->bp;
+ u32 xmac_base = (port) ? GRCBASE_XMAC1 : GRCBASE_XMAC0;
+
+ if (REG_RD(bp, MISC_REG_RESET_REG_2) &
+ MISC_REGISTERS_RESET_REG_2_XMAC) {
+ DP(NETIF_MSG_LINK, "Disable XMAC on port %x\n", port);
+ REG_WR(bp, xmac_base + XMAC_REG_CTRL, 0);
+ usleep_range(1000, 1000);
+ bnx2x_set_xumac_nig(params, 0, 0);
+ REG_WR(bp, xmac_base + XMAC_REG_CTRL,
+ XMAC_CTRL_REG_SOFT_RESET);
+ }
+}
+
+static int bnx2x_xmac_enable(struct link_params *params,
+ struct link_vars *vars, u8 lb)
+{
+ u32 val, xmac_base;
+ struct bnx2x *bp = params->bp;
+ DP(NETIF_MSG_LINK, "enabling XMAC\n");
+
+ xmac_base = (params->port) ? GRCBASE_XMAC1 : GRCBASE_XMAC0;
+
+ bnx2x_xmac_init(bp, vars->line_speed);
+
+ /*
+ * This register determines on which events the MAC will assert
+ * error on the i/f to the NIG along w/ EOP.
+ */
+
+ /*
+ * This register tells the NIG whether to send traffic to UMAC
+ * or XMAC
+ */
+ REG_WR(bp, NIG_REG_EGRESS_EMAC0_PORT + params->port*4, 0);
+
+ /* Set Max packet size */
+ REG_WR(bp, xmac_base + XMAC_REG_RX_MAX_SIZE, 0x2710);
+
+ /* CRC append for Tx packets */
+ REG_WR(bp, xmac_base + XMAC_REG_TX_CTRL, 0xC800);
+
+ /* update PFC */
+ bnx2x_update_pfc_xmac(params, vars, 0);
+
+ /* Enable TX and RX */
+ val = XMAC_CTRL_REG_TX_EN | XMAC_CTRL_REG_RX_EN;
+
+ /* Check loopback mode */
+ if (lb)
+ val |= XMAC_CTRL_REG_CORE_LOCAL_LPBK;
+ REG_WR(bp, xmac_base + XMAC_REG_CTRL, val);
+ bnx2x_set_xumac_nig(params,
+ ((vars->flow_ctrl & BNX2X_FLOW_CTRL_TX) != 0), 1);
+
+ vars->mac_type = MAC_TYPE_XMAC;
+
+ return 0;
+}
+static int bnx2x_emac_enable(struct link_params *params,
+ struct link_vars *vars, u8 lb)
+{
struct bnx2x *bp = params->bp;
u8 port = params->port;
u32 emac_base = port ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
@@ -760,95 +1971,398 @@
REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_BMAC_CONTROL, wb_data, 2);
}
-static void bnx2x_update_pfc_brb(struct link_params *params,
- struct link_vars *vars,
- struct bnx2x_nig_brb_pfc_port_params *pfc_params)
+
+/* PFC BRB internal port configuration params */
+struct bnx2x_pfc_brb_threshold_val {
+ u32 pause_xoff;
+ u32 pause_xon;
+ u32 full_xoff;
+ u32 full_xon;
+};
+
+struct bnx2x_pfc_brb_e3b0_val {
+ u32 full_lb_xoff_th;
+ u32 full_lb_xon_threshold;
+ u32 lb_guarantied;
+ u32 mac_0_class_t_guarantied;
+ u32 mac_0_class_t_guarantied_hyst;
+ u32 mac_1_class_t_guarantied;
+ u32 mac_1_class_t_guarantied_hyst;
+};
+
+struct bnx2x_pfc_brb_th_val {
+ struct bnx2x_pfc_brb_threshold_val pauseable_th;
+ struct bnx2x_pfc_brb_threshold_val non_pauseable_th;
+};
+static int bnx2x_pfc_brb_get_config_params(
+ struct link_params *params,
+ struct bnx2x_pfc_brb_th_val *config_val)
{
struct bnx2x *bp = params->bp;
+ DP(NETIF_MSG_LINK, "Setting PFC BRB configuration\n");
+ if (CHIP_IS_E2(bp)) {
+ config_val->pauseable_th.pause_xoff =
+ PFC_E2_BRB_MAC_PAUSE_XOFF_THR_PAUSE;
+ config_val->pauseable_th.pause_xon =
+ PFC_E2_BRB_MAC_PAUSE_XON_THR_PAUSE;
+ config_val->pauseable_th.full_xoff =
+ PFC_E2_BRB_MAC_FULL_XOFF_THR_PAUSE;
+ config_val->pauseable_th.full_xon =
+ PFC_E2_BRB_MAC_FULL_XON_THR_PAUSE;
+ /* non pause able*/
+ config_val->non_pauseable_th.pause_xoff =
+ PFC_E2_BRB_MAC_PAUSE_XOFF_THR_NON_PAUSE;
+ config_val->non_pauseable_th.pause_xon =
+ PFC_E2_BRB_MAC_PAUSE_XON_THR_NON_PAUSE;
+ config_val->non_pauseable_th.full_xoff =
+ PFC_E2_BRB_MAC_FULL_XOFF_THR_NON_PAUSE;
+ config_val->non_pauseable_th.full_xon =
+ PFC_E2_BRB_MAC_FULL_XON_THR_NON_PAUSE;
+ } else if (CHIP_IS_E3A0(bp)) {
+ config_val->pauseable_th.pause_xoff =
+ PFC_E3A0_BRB_MAC_PAUSE_XOFF_THR_PAUSE;
+ config_val->pauseable_th.pause_xon =
+ PFC_E3A0_BRB_MAC_PAUSE_XON_THR_PAUSE;
+ config_val->pauseable_th.full_xoff =
+ PFC_E3A0_BRB_MAC_FULL_XOFF_THR_PAUSE;
+ config_val->pauseable_th.full_xon =
+ PFC_E3A0_BRB_MAC_FULL_XON_THR_PAUSE;
+ /* non pause able*/
+ config_val->non_pauseable_th.pause_xoff =
+ PFC_E3A0_BRB_MAC_PAUSE_XOFF_THR_NON_PAUSE;
+ config_val->non_pauseable_th.pause_xon =
+ PFC_E3A0_BRB_MAC_PAUSE_XON_THR_NON_PAUSE;
+ config_val->non_pauseable_th.full_xoff =
+ PFC_E3A0_BRB_MAC_FULL_XOFF_THR_NON_PAUSE;
+ config_val->non_pauseable_th.full_xon =
+ PFC_E3A0_BRB_MAC_FULL_XON_THR_NON_PAUSE;
+ } else if (CHIP_IS_E3B0(bp)) {
+ if (params->phy[INT_PHY].flags &
+ FLAGS_4_PORT_MODE) {
+ config_val->pauseable_th.pause_xoff =
+ PFC_E3B0_4P_BRB_MAC_PAUSE_XOFF_THR_PAUSE;
+ config_val->pauseable_th.pause_xon =
+ PFC_E3B0_4P_BRB_MAC_PAUSE_XON_THR_PAUSE;
+ config_val->pauseable_th.full_xoff =
+ PFC_E3B0_4P_BRB_MAC_FULL_XOFF_THR_PAUSE;
+ config_val->pauseable_th.full_xon =
+ PFC_E3B0_4P_BRB_MAC_FULL_XON_THR_PAUSE;
+ /* non pause able*/
+ config_val->non_pauseable_th.pause_xoff =
+ PFC_E3B0_4P_BRB_MAC_PAUSE_XOFF_THR_NON_PAUSE;
+ config_val->non_pauseable_th.pause_xon =
+ PFC_E3B0_4P_BRB_MAC_PAUSE_XON_THR_NON_PAUSE;
+ config_val->non_pauseable_th.full_xoff =
+ PFC_E3B0_4P_BRB_MAC_FULL_XOFF_THR_NON_PAUSE;
+ config_val->non_pauseable_th.full_xon =
+ PFC_E3B0_4P_BRB_MAC_FULL_XON_THR_NON_PAUSE;
+ } else {
+ config_val->pauseable_th.pause_xoff =
+ PFC_E3B0_2P_BRB_MAC_PAUSE_XOFF_THR_PAUSE;
+ config_val->pauseable_th.pause_xon =
+ PFC_E3B0_2P_BRB_MAC_PAUSE_XON_THR_PAUSE;
+ config_val->pauseable_th.full_xoff =
+ PFC_E3B0_2P_BRB_MAC_FULL_XOFF_THR_PAUSE;
+ config_val->pauseable_th.full_xon =
+ PFC_E3B0_2P_BRB_MAC_FULL_XON_THR_PAUSE;
+ /* non pause able*/
+ config_val->non_pauseable_th.pause_xoff =
+ PFC_E3B0_2P_BRB_MAC_PAUSE_XOFF_THR_NON_PAUSE;
+ config_val->non_pauseable_th.pause_xon =
+ PFC_E3B0_2P_BRB_MAC_PAUSE_XON_THR_NON_PAUSE;
+ config_val->non_pauseable_th.full_xoff =
+ PFC_E3B0_2P_BRB_MAC_FULL_XOFF_THR_NON_PAUSE;
+ config_val->non_pauseable_th.full_xon =
+ PFC_E3B0_2P_BRB_MAC_FULL_XON_THR_NON_PAUSE;
+ }
+ } else
+ return -EINVAL;
+
+ return 0;
+}
+
+
+static void bnx2x_pfc_brb_get_e3b0_config_params(struct link_params *params,
+ struct bnx2x_pfc_brb_e3b0_val
+ *e3b0_val,
+ u32 cos0_pauseable,
+ u32 cos1_pauseable)
+{
+ if (params->phy[INT_PHY].flags & FLAGS_4_PORT_MODE) {
+ e3b0_val->full_lb_xoff_th =
+ PFC_E3B0_4P_BRB_FULL_LB_XOFF_THR;
+ e3b0_val->full_lb_xon_threshold =
+ PFC_E3B0_4P_BRB_FULL_LB_XON_THR;
+ e3b0_val->lb_guarantied =
+ PFC_E3B0_4P_LB_GUART;
+ e3b0_val->mac_0_class_t_guarantied =
+ PFC_E3B0_4P_BRB_MAC_0_CLASS_T_GUART;
+ e3b0_val->mac_0_class_t_guarantied_hyst =
+ PFC_E3B0_4P_BRB_MAC_0_CLASS_T_GUART_HYST;
+ e3b0_val->mac_1_class_t_guarantied =
+ PFC_E3B0_4P_BRB_MAC_1_CLASS_T_GUART;
+ e3b0_val->mac_1_class_t_guarantied_hyst =
+ PFC_E3B0_4P_BRB_MAC_1_CLASS_T_GUART_HYST;
+ } else {
+ e3b0_val->full_lb_xoff_th =
+ PFC_E3B0_2P_BRB_FULL_LB_XOFF_THR;
+ e3b0_val->full_lb_xon_threshold =
+ PFC_E3B0_2P_BRB_FULL_LB_XON_THR;
+ e3b0_val->mac_0_class_t_guarantied_hyst =
+ PFC_E3B0_2P_BRB_MAC_0_CLASS_T_GUART_HYST;
+ e3b0_val->mac_1_class_t_guarantied =
+ PFC_E3B0_2P_BRB_MAC_1_CLASS_T_GUART;
+ e3b0_val->mac_1_class_t_guarantied_hyst =
+ PFC_E3B0_2P_BRB_MAC_1_CLASS_T_GUART_HYST;
+
+ if (cos0_pauseable != cos1_pauseable) {
+ /* nonpauseable= Lossy + pauseable = Lossless*/
+ e3b0_val->lb_guarantied =
+ PFC_E3B0_2P_MIX_PAUSE_LB_GUART;
+ e3b0_val->mac_0_class_t_guarantied =
+ PFC_E3B0_2P_MIX_PAUSE_MAC_0_CLASS_T_GUART;
+ } else if (cos0_pauseable) {
+ /* Lossless +Lossless*/
+ e3b0_val->lb_guarantied =
+ PFC_E3B0_2P_PAUSE_LB_GUART;
+ e3b0_val->mac_0_class_t_guarantied =
+ PFC_E3B0_2P_PAUSE_MAC_0_CLASS_T_GUART;
+ } else {
+ /* Lossy +Lossy*/
+ e3b0_val->lb_guarantied =
+ PFC_E3B0_2P_NON_PAUSE_LB_GUART;
+ e3b0_val->mac_0_class_t_guarantied =
+ PFC_E3B0_2P_NON_PAUSE_MAC_0_CLASS_T_GUART;
+ }
+ }
+}
+static int bnx2x_update_pfc_brb(struct link_params *params,
+ struct link_vars *vars,
+ struct bnx2x_nig_brb_pfc_port_params
+ *pfc_params)
+{
+ struct bnx2x *bp = params->bp;
+ struct bnx2x_pfc_brb_th_val config_val = { {0} };
+ struct bnx2x_pfc_brb_threshold_val *reg_th_config =
+ &config_val.pauseable_th;
+ struct bnx2x_pfc_brb_e3b0_val e3b0_val = {0};
int set_pfc = params->feature_config_flags &
FEATURE_CONFIG_PFC_ENABLED;
+ int bnx2x_status = 0;
+ u8 port = params->port;
/* default - pause configuration */
- u32 pause_xoff_th = PFC_BRB_MAC_PAUSE_XOFF_THRESHOLD_PAUSEABLE;
- u32 pause_xon_th = PFC_BRB_MAC_PAUSE_XON_THRESHOLD_PAUSEABLE;
- u32 full_xoff_th = PFC_BRB_MAC_FULL_XOFF_THRESHOLD_PAUSEABLE;
- u32 full_xon_th = PFC_BRB_MAC_FULL_XON_THRESHOLD_PAUSEABLE;
+ reg_th_config = &config_val.pauseable_th;
+ bnx2x_status = bnx2x_pfc_brb_get_config_params(params, &config_val);
+ if (0 != bnx2x_status)
+ return bnx2x_status;
if (set_pfc && pfc_params)
/* First COS */
- if (!pfc_params->cos0_pauseable) {
- pause_xoff_th =
- PFC_BRB_MAC_PAUSE_XOFF_THRESHOLD_NON_PAUSEABLE;
- pause_xon_th =
- PFC_BRB_MAC_PAUSE_XON_THRESHOLD_NON_PAUSEABLE;
- full_xoff_th =
- PFC_BRB_MAC_FULL_XOFF_THRESHOLD_NON_PAUSEABLE;
- full_xon_th =
- PFC_BRB_MAC_FULL_XON_THRESHOLD_NON_PAUSEABLE;
- }
+ if (!pfc_params->cos0_pauseable)
+ reg_th_config = &config_val.non_pauseable_th;
/*
* The number of free blocks below which the pause signal to class 0
* of MAC #n is asserted. n=0,1
*/
- REG_WR(bp, BRB1_REG_PAUSE_0_XOFF_THRESHOLD_0 , pause_xoff_th);
+ REG_WR(bp, (port) ? BRB1_REG_PAUSE_0_XOFF_THRESHOLD_1 :
+ BRB1_REG_PAUSE_0_XOFF_THRESHOLD_0 ,
+ reg_th_config->pause_xoff);
/*
* The number of free blocks above which the pause signal to class 0
* of MAC #n is de-asserted. n=0,1
*/
- REG_WR(bp, BRB1_REG_PAUSE_0_XON_THRESHOLD_0 , pause_xon_th);
+ REG_WR(bp, (port) ? BRB1_REG_PAUSE_0_XON_THRESHOLD_1 :
+ BRB1_REG_PAUSE_0_XON_THRESHOLD_0 , reg_th_config->pause_xon);
/*
* The number of free blocks below which the full signal to class 0
* of MAC #n is asserted. n=0,1
*/
- REG_WR(bp, BRB1_REG_FULL_0_XOFF_THRESHOLD_0 , full_xoff_th);
+ REG_WR(bp, (port) ? BRB1_REG_FULL_0_XOFF_THRESHOLD_1 :
+ BRB1_REG_FULL_0_XOFF_THRESHOLD_0 , reg_th_config->full_xoff);
/*
* The number of free blocks above which the full signal to class 0
* of MAC #n is de-asserted. n=0,1
*/
- REG_WR(bp, BRB1_REG_FULL_0_XON_THRESHOLD_0 , full_xon_th);
+ REG_WR(bp, (port) ? BRB1_REG_FULL_0_XON_THRESHOLD_1 :
+ BRB1_REG_FULL_0_XON_THRESHOLD_0 , reg_th_config->full_xon);
if (set_pfc && pfc_params) {
/* Second COS */
- if (pfc_params->cos1_pauseable) {
- pause_xoff_th =
- PFC_BRB_MAC_PAUSE_XOFF_THRESHOLD_PAUSEABLE;
- pause_xon_th =
- PFC_BRB_MAC_PAUSE_XON_THRESHOLD_PAUSEABLE;
- full_xoff_th =
- PFC_BRB_MAC_FULL_XOFF_THRESHOLD_PAUSEABLE;
- full_xon_th =
- PFC_BRB_MAC_FULL_XON_THRESHOLD_PAUSEABLE;
- } else {
- pause_xoff_th =
- PFC_BRB_MAC_PAUSE_XOFF_THRESHOLD_NON_PAUSEABLE;
- pause_xon_th =
- PFC_BRB_MAC_PAUSE_XON_THRESHOLD_NON_PAUSEABLE;
- full_xoff_th =
- PFC_BRB_MAC_FULL_XOFF_THRESHOLD_NON_PAUSEABLE;
- full_xon_th =
- PFC_BRB_MAC_FULL_XON_THRESHOLD_NON_PAUSEABLE;
- }
+ if (pfc_params->cos1_pauseable)
+ reg_th_config = &config_val.pauseable_th;
+ else
+ reg_th_config = &config_val.non_pauseable_th;
/*
* The number of free blocks below which the pause signal to
* class 1 of MAC #n is asserted. n=0,1
- */
- REG_WR(bp, BRB1_REG_PAUSE_1_XOFF_THRESHOLD_0, pause_xoff_th);
+ **/
+ REG_WR(bp, (port) ? BRB1_REG_PAUSE_1_XOFF_THRESHOLD_1 :
+ BRB1_REG_PAUSE_1_XOFF_THRESHOLD_0,
+ reg_th_config->pause_xoff);
/*
* The number of free blocks above which the pause signal to
* class 1 of MAC #n is de-asserted. n=0,1
*/
- REG_WR(bp, BRB1_REG_PAUSE_1_XON_THRESHOLD_0, pause_xon_th);
+ REG_WR(bp, (port) ? BRB1_REG_PAUSE_1_XON_THRESHOLD_1 :
+ BRB1_REG_PAUSE_1_XON_THRESHOLD_0,
+ reg_th_config->pause_xon);
/*
* The number of free blocks below which the full signal to
* class 1 of MAC #n is asserted. n=0,1
*/
- REG_WR(bp, BRB1_REG_FULL_1_XOFF_THRESHOLD_0, full_xoff_th);
+ REG_WR(bp, (port) ? BRB1_REG_FULL_1_XOFF_THRESHOLD_1 :
+ BRB1_REG_FULL_1_XOFF_THRESHOLD_0,
+ reg_th_config->full_xoff);
/*
* The number of free blocks above which the full signal to
* class 1 of MAC #n is de-asserted. n=0,1
*/
- REG_WR(bp, BRB1_REG_FULL_1_XON_THRESHOLD_0, full_xon_th);
+ REG_WR(bp, (port) ? BRB1_REG_FULL_1_XON_THRESHOLD_1 :
+ BRB1_REG_FULL_1_XON_THRESHOLD_0,
+ reg_th_config->full_xon);
+
+
+ if (CHIP_IS_E3B0(bp)) {
+ /*Should be done by init tool */
+ /*
+ * BRB_empty_for_dup = BRB1_REG_BRB_EMPTY_THRESHOLD
+ * reset value
+ * 944
+ */
+
+ /**
+ * The hysteresis on the guarantied buffer space for the Lb port
+ * before signaling XON.
+ **/
+ REG_WR(bp, BRB1_REG_LB_GUARANTIED_HYST, 80);
+
+ bnx2x_pfc_brb_get_e3b0_config_params(
+ params,
+ &e3b0_val,
+ pfc_params->cos0_pauseable,
+ pfc_params->cos1_pauseable);
+ /**
+ * The number of free blocks below which the full signal to the
+ * LB port is asserted.
+ */
+ REG_WR(bp, BRB1_REG_FULL_LB_XOFF_THRESHOLD,
+ e3b0_val.full_lb_xoff_th);
+ /**
+ * The number of free blocks above which the full signal to the
+ * LB port is de-asserted.
+ */
+ REG_WR(bp, BRB1_REG_FULL_LB_XON_THRESHOLD,
+ e3b0_val.full_lb_xon_threshold);
+ /**
+ * The number of blocks guarantied for the MAC #n port. n=0,1
+ */
+
+ /*The number of blocks guarantied for the LB port.*/
+ REG_WR(bp, BRB1_REG_LB_GUARANTIED,
+ e3b0_val.lb_guarantied);
+
+ /**
+ * The number of blocks guarantied for the MAC #n port.
+ */
+ REG_WR(bp, BRB1_REG_MAC_GUARANTIED_0,
+ 2 * e3b0_val.mac_0_class_t_guarantied);
+ REG_WR(bp, BRB1_REG_MAC_GUARANTIED_1,
+ 2 * e3b0_val.mac_1_class_t_guarantied);
+ /**
+ * The number of blocks guarantied for class #t in MAC0. t=0,1
+ */
+ REG_WR(bp, BRB1_REG_MAC_0_CLASS_0_GUARANTIED,
+ e3b0_val.mac_0_class_t_guarantied);
+ REG_WR(bp, BRB1_REG_MAC_0_CLASS_1_GUARANTIED,
+ e3b0_val.mac_0_class_t_guarantied);
+ /**
+ * The hysteresis on the guarantied buffer space for class in
+ * MAC0. t=0,1
+ */
+ REG_WR(bp, BRB1_REG_MAC_0_CLASS_0_GUARANTIED_HYST,
+ e3b0_val.mac_0_class_t_guarantied_hyst);
+ REG_WR(bp, BRB1_REG_MAC_0_CLASS_1_GUARANTIED_HYST,
+ e3b0_val.mac_0_class_t_guarantied_hyst);
+
+ /**
+ * The number of blocks guarantied for class #t in MAC1.t=0,1
+ */
+ REG_WR(bp, BRB1_REG_MAC_1_CLASS_0_GUARANTIED,
+ e3b0_val.mac_1_class_t_guarantied);
+ REG_WR(bp, BRB1_REG_MAC_1_CLASS_1_GUARANTIED,
+ e3b0_val.mac_1_class_t_guarantied);
+ /**
+ * The hysteresis on the guarantied buffer space for class #t
+ * in MAC1. t=0,1
+ */
+ REG_WR(bp, BRB1_REG_MAC_1_CLASS_0_GUARANTIED_HYST,
+ e3b0_val.mac_1_class_t_guarantied_hyst);
+ REG_WR(bp, BRB1_REG_MAC_1_CLASS_1_GUARANTIED_HYST,
+ e3b0_val.mac_1_class_t_guarantied_hyst);
+
+ }
+
}
+
+ return bnx2x_status;
+}
+
+/******************************************************************************
+* Description:
+* This function is needed because NIG ARB_CREDIT_WEIGHT_X are
+* not continues and ARB_CREDIT_WEIGHT_0 + offset is suitable.
+******************************************************************************/
+int bnx2x_pfc_nig_rx_priority_mask(struct bnx2x *bp,
+ u8 cos_entry,
+ u32 priority_mask, u8 port)
+{
+ u32 nig_reg_rx_priority_mask_add = 0;
+
+ switch (cos_entry) {
+ case 0:
+ nig_reg_rx_priority_mask_add = (port) ?
+ NIG_REG_P1_RX_COS0_PRIORITY_MASK :
+ NIG_REG_P0_RX_COS0_PRIORITY_MASK;
+ break;
+ case 1:
+ nig_reg_rx_priority_mask_add = (port) ?
+ NIG_REG_P1_RX_COS1_PRIORITY_MASK :
+ NIG_REG_P0_RX_COS1_PRIORITY_MASK;
+ break;
+ case 2:
+ nig_reg_rx_priority_mask_add = (port) ?
+ NIG_REG_P1_RX_COS2_PRIORITY_MASK :
+ NIG_REG_P0_RX_COS2_PRIORITY_MASK;
+ break;
+ case 3:
+ if (port)
+ return -EINVAL;
+ nig_reg_rx_priority_mask_add = NIG_REG_P0_RX_COS3_PRIORITY_MASK;
+ break;
+ case 4:
+ if (port)
+ return -EINVAL;
+ nig_reg_rx_priority_mask_add = NIG_REG_P0_RX_COS4_PRIORITY_MASK;
+ break;
+ case 5:
+ if (port)
+ return -EINVAL;
+ nig_reg_rx_priority_mask_add = NIG_REG_P0_RX_COS5_PRIORITY_MASK;
+ break;
+ }
+
+ REG_WR(bp, nig_reg_rx_priority_mask_add, priority_mask);
+
+ return 0;
+}
+static void bnx2x_update_mng(struct link_params *params, u32 link_status)
+{
+ struct bnx2x *bp = params->bp;
+
+ REG_WR(bp, params->shmem_base +
+ offsetof(struct shmem_region,
+ port_mb[params->port].link_status), link_status);
}
static void bnx2x_update_pfc_nig(struct link_params *params,
@@ -858,9 +2372,9 @@
u32 xcm_mask = 0, ppp_enable = 0, pause_enable = 0, llfc_out_en = 0;
u32 llfc_enable = 0, xcm0_out_en = 0, p0_hwpfc_enable = 0;
u32 pkt_priority_to_cos = 0;
- u32 val;
struct bnx2x *bp = params->bp;
- int port = params->port;
+ u8 port = params->port;
+
int set_pfc = params->feature_config_flags &
FEATURE_CONFIG_PFC_ENABLED;
DP(NETIF_MSG_LINK, "updating pfc nig parameters\n");
@@ -881,6 +2395,9 @@
pause_enable = 0;
llfc_out_en = 0;
llfc_enable = 0;
+ if (CHIP_IS_E3(bp))
+ ppp_enable = 0;
+ else
ppp_enable = 1;
xcm_mask &= ~(port ? NIG_LLH1_XCM_MASK_REG_LLH1_XCM_MASK_BCN :
NIG_LLH0_XCM_MASK_REG_LLH0_XCM_MASK_BCN);
@@ -899,6 +2416,9 @@
xcm0_out_en = 1;
}
+ if (CHIP_IS_E3(bp))
+ REG_WR(bp, port ? NIG_REG_BRB1_PAUSE_IN_EN :
+ NIG_REG_BRB0_PAUSE_IN_EN, pause_enable);
REG_WR(bp, port ? NIG_REG_LLFC_OUT_EN_1 :
NIG_REG_LLFC_OUT_EN_0, llfc_out_en);
REG_WR(bp, port ? NIG_REG_LLFC_ENABLE_1 :
@@ -920,30 +2440,13 @@
/* HW PFC TX enable */
REG_WR(bp, NIG_REG_P0_HWPFC_ENABLE, p0_hwpfc_enable);
- /* 0x2 = BMAC, 0x1= EMAC */
- switch (vars->mac_type) {
- case MAC_TYPE_EMAC:
- val = 1;
- break;
- case MAC_TYPE_BMAC:
- val = 0;
- break;
- default:
- val = 0;
- break;
- }
- REG_WR(bp, NIG_REG_EGRESS_EMAC0_PORT, val);
-
if (nig_params) {
+ u8 i = 0;
pkt_priority_to_cos = nig_params->pkt_priority_to_cos;
- REG_WR(bp, port ? NIG_REG_P1_RX_COS0_PRIORITY_MASK :
- NIG_REG_P0_RX_COS0_PRIORITY_MASK,
- nig_params->rx_cos0_priority_mask);
-
- REG_WR(bp, port ? NIG_REG_P1_RX_COS1_PRIORITY_MASK :
- NIG_REG_P0_RX_COS1_PRIORITY_MASK,
- nig_params->rx_cos1_priority_mask);
+ for (i = 0; i < nig_params->num_of_rx_cos_priority_mask; i++)
+ bnx2x_pfc_nig_rx_priority_mask(bp, i,
+ nig_params->rx_cos_priority_mask[i], port);
REG_WR(bp, port ? NIG_REG_LLFC_HIGH_PRIORITY_CLASSES_1 :
NIG_REG_LLFC_HIGH_PRIORITY_CLASSES_0,
@@ -958,8 +2461,7 @@
pkt_priority_to_cos);
}
-
-void bnx2x_update_pfc(struct link_params *params,
+int bnx2x_update_pfc(struct link_params *params,
struct link_vars *vars,
struct bnx2x_nig_brb_pfc_port_params *pfc_params)
{
@@ -970,41 +2472,59 @@
*/
u32 val;
struct bnx2x *bp = params->bp;
+ int bnx2x_status = 0;
+ u8 bmac_loopback = (params->loopback_mode == LOOPBACK_BMAC);
+
+ if (params->feature_config_flags & FEATURE_CONFIG_PFC_ENABLED)
+ vars->link_status |= LINK_STATUS_PFC_ENABLED;
+ else
+ vars->link_status &= ~LINK_STATUS_PFC_ENABLED;
+
+ bnx2x_update_mng(params, vars->link_status);
/* update NIG params */
bnx2x_update_pfc_nig(params, vars, pfc_params);
/* update BRB params */
- bnx2x_update_pfc_brb(params, vars, pfc_params);
+ bnx2x_status = bnx2x_update_pfc_brb(params, vars, pfc_params);
+ if (0 != bnx2x_status)
+ return bnx2x_status;
if (!vars->link_up)
- return;
-
- val = REG_RD(bp, MISC_REG_RESET_REG_2);
- if ((val & (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << params->port))
- == 0) {
- DP(NETIF_MSG_LINK, "About to update PFC in EMAC\n");
- bnx2x_emac_enable(params, vars, 0);
- return;
- }
+ return bnx2x_status;
DP(NETIF_MSG_LINK, "About to update PFC in BMAC\n");
- if (CHIP_IS_E2(bp))
- bnx2x_update_pfc_bmac2(params, vars, 0);
- else
- bnx2x_update_pfc_bmac1(params, vars);
+ if (CHIP_IS_E3(bp))
+ bnx2x_update_pfc_xmac(params, vars, 0);
+ else {
+ val = REG_RD(bp, MISC_REG_RESET_REG_2);
+ if ((val &
+ (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << params->port))
+ == 0) {
+ DP(NETIF_MSG_LINK, "About to update PFC in EMAC\n");
+ bnx2x_emac_enable(params, vars, 0);
+ return bnx2x_status;
+ }
- val = 0;
- if ((params->feature_config_flags &
- FEATURE_CONFIG_PFC_ENABLED) ||
- (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX))
- val = 1;
- REG_WR(bp, NIG_REG_BMAC0_PAUSE_OUT_EN + params->port*4, val);
+ if (CHIP_IS_E2(bp))
+ bnx2x_update_pfc_bmac2(params, vars, bmac_loopback);
+ else
+ bnx2x_update_pfc_bmac1(params, vars);
+
+ val = 0;
+ if ((params->feature_config_flags &
+ FEATURE_CONFIG_PFC_ENABLED) ||
+ (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX))
+ val = 1;
+ REG_WR(bp, NIG_REG_BMAC0_PAUSE_OUT_EN + params->port*4, val);
+ }
+ return bnx2x_status;
}
-static u8 bnx2x_bmac1_enable(struct link_params *params,
- struct link_vars *vars,
- u8 is_lb)
+
+static int bnx2x_bmac1_enable(struct link_params *params,
+ struct link_vars *vars,
+ u8 is_lb)
{
struct bnx2x *bp = params->bp;
u8 port = params->port;
@@ -1063,12 +2583,18 @@
REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_RX_LLFC_MSG_FLDS,
wb_data, 2);
+ if (vars->phy_flags & PHY_TX_ERROR_CHECK_FLAG) {
+ REG_RD_DMAE(bp, bmac_addr + BIGMAC_REGISTER_RX_LSS_STATUS,
+ wb_data, 2);
+ if (wb_data[0] > 0)
+ return -ESRCH;
+ }
return 0;
}
-static u8 bnx2x_bmac2_enable(struct link_params *params,
- struct link_vars *vars,
- u8 is_lb)
+static int bnx2x_bmac2_enable(struct link_params *params,
+ struct link_vars *vars,
+ u8 is_lb)
{
struct bnx2x *bp = params->bp;
u8 port = params->port;
@@ -1128,14 +2654,25 @@
udelay(30);
bnx2x_update_pfc_bmac2(params, vars, is_lb);
+ if (vars->phy_flags & PHY_TX_ERROR_CHECK_FLAG) {
+ REG_RD_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_RX_LSS_STAT,
+ wb_data, 2);
+ if (wb_data[0] > 0) {
+ DP(NETIF_MSG_LINK, "Got bad LSS status 0x%x\n",
+ wb_data[0]);
+ return -ESRCH;
+ }
+ }
+
return 0;
}
-static u8 bnx2x_bmac_enable(struct link_params *params,
- struct link_vars *vars,
- u8 is_lb)
+static int bnx2x_bmac_enable(struct link_params *params,
+ struct link_vars *vars,
+ u8 is_lb)
{
- u8 rc, port = params->port;
+ int rc = 0;
+ u8 port = params->port;
struct bnx2x *bp = params->bp;
u32 val;
/* reset and unreset the BigMac */
@@ -1173,16 +2710,6 @@
return rc;
}
-
-static void bnx2x_update_mng(struct link_params *params, u32 link_status)
-{
- struct bnx2x *bp = params->bp;
-
- REG_WR(bp, params->shmem_base +
- offsetof(struct shmem_region,
- port_mb[params->port].link_status), link_status);
-}
-
static void bnx2x_bmac_rx_disable(struct bnx2x *bp, u8 port)
{
u32 bmac_addr = port ? NIG_REG_INGRESS_BMAC1_MEM :
@@ -1218,8 +2745,8 @@
}
}
-static u8 bnx2x_pbf_update(struct link_params *params, u32 flow_ctrl,
- u32 line_speed)
+static int bnx2x_pbf_update(struct link_params *params, u32 flow_ctrl,
+ u32 line_speed)
{
struct bnx2x *bp = params->bp;
u8 port = params->port;
@@ -1269,18 +2796,6 @@
case SPEED_10000:
init_crd = thresh + 553 - 22;
break;
-
- case SPEED_12000:
- init_crd = thresh + 664 - 22;
- break;
-
- case SPEED_13000:
- init_crd = thresh + 742 - 22;
- break;
-
- case SPEED_16000:
- init_crd = thresh + 778 - 22;
- break;
default:
DP(NETIF_MSG_LINK, "Invalid line_speed 0x%x\n",
line_speed);
@@ -1349,31 +2864,23 @@
}
/******************************************************************/
-/* CL45 access functions */
+/* CL22 access functions */
/******************************************************************/
-static u8 bnx2x_cl45_write(struct bnx2x *bp, struct bnx2x_phy *phy,
- u8 devad, u16 reg, u16 val)
+static int bnx2x_cl22_write(struct bnx2x *bp,
+ struct bnx2x_phy *phy,
+ u16 reg, u16 val)
{
- u32 tmp, saved_mode;
- u8 i, rc = 0;
- /*
- * Set clause 45 mode, slow down the MDIO clock to 2.5MHz
- * (a value of 49==0x31) and make sure that the AUTO poll is off
- */
-
- saved_mode = REG_RD(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE);
- tmp = saved_mode & ~(EMAC_MDIO_MODE_AUTO_POLL |
- EMAC_MDIO_MODE_CLOCK_CNT);
- tmp |= (EMAC_MDIO_MODE_CLAUSE_45 |
- (49 << EMAC_MDIO_MODE_CLOCK_CNT_BITSHIFT));
- REG_WR(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE, tmp);
- REG_RD(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE);
- udelay(40);
+ u32 tmp, mode;
+ u8 i;
+ int rc = 0;
+ /* Switch to CL22 */
+ mode = REG_RD(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE);
+ REG_WR(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE,
+ mode & ~EMAC_MDIO_MODE_CLAUSE_45);
/* address */
-
- tmp = ((phy->addr << 21) | (devad << 16) | reg |
- EMAC_MDIO_COMM_COMMAND_ADDRESS |
+ tmp = ((phy->addr << 21) | (reg << 16) | val |
+ EMAC_MDIO_COMM_COMMAND_WRITE_22 |
EMAC_MDIO_COMM_START_BUSY);
REG_WR(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, tmp);
@@ -1388,57 +2895,60 @@
}
if (tmp & EMAC_MDIO_COMM_START_BUSY) {
DP(NETIF_MSG_LINK, "write phy register failed\n");
- netdev_err(bp->dev, "MDC/MDIO access timeout\n");
rc = -EFAULT;
- } else {
- /* data */
- tmp = ((phy->addr << 21) | (devad << 16) | val |
- EMAC_MDIO_COMM_COMMAND_WRITE_45 |
- EMAC_MDIO_COMM_START_BUSY);
- REG_WR(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, tmp);
-
- for (i = 0; i < 50; i++) {
- udelay(10);
-
- tmp = REG_RD(bp, phy->mdio_ctrl +
- EMAC_REG_EMAC_MDIO_COMM);
- if (!(tmp & EMAC_MDIO_COMM_START_BUSY)) {
- udelay(5);
- break;
- }
- }
- if (tmp & EMAC_MDIO_COMM_START_BUSY) {
- DP(NETIF_MSG_LINK, "write phy register failed\n");
- netdev_err(bp->dev, "MDC/MDIO access timeout\n");
- rc = -EFAULT;
- }
}
-
- /* Restore the saved mode */
- REG_WR(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE, saved_mode);
-
+ REG_WR(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE, mode);
return rc;
}
-static u8 bnx2x_cl45_read(struct bnx2x *bp, struct bnx2x_phy *phy,
- u8 devad, u16 reg, u16 *ret_val)
+static int bnx2x_cl22_read(struct bnx2x *bp,
+ struct bnx2x_phy *phy,
+ u16 reg, u16 *ret_val)
{
- u32 val, saved_mode;
+ u32 val, mode;
u16 i;
- u8 rc = 0;
- /*
- * Set clause 45 mode, slow down the MDIO clock to 2.5MHz
- * (a value of 49==0x31) and make sure that the AUTO poll is off
- */
+ int rc = 0;
- saved_mode = REG_RD(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE);
- val = saved_mode & ~((EMAC_MDIO_MODE_AUTO_POLL |
- EMAC_MDIO_MODE_CLOCK_CNT));
- val |= (EMAC_MDIO_MODE_CLAUSE_45 |
- (49L << EMAC_MDIO_MODE_CLOCK_CNT_BITSHIFT));
- REG_WR(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE, val);
- REG_RD(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE);
- udelay(40);
+ /* Switch to CL22 */
+ mode = REG_RD(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE);
+ REG_WR(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE,
+ mode & ~EMAC_MDIO_MODE_CLAUSE_45);
+
+ /* address */
+ val = ((phy->addr << 21) | (reg << 16) |
+ EMAC_MDIO_COMM_COMMAND_READ_22 |
+ EMAC_MDIO_COMM_START_BUSY);
+ REG_WR(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, val);
+
+ for (i = 0; i < 50; i++) {
+ udelay(10);
+
+ val = REG_RD(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM);
+ if (!(val & EMAC_MDIO_COMM_START_BUSY)) {
+ *ret_val = (u16)(val & EMAC_MDIO_COMM_DATA);
+ udelay(5);
+ break;
+ }
+ }
+ if (val & EMAC_MDIO_COMM_START_BUSY) {
+ DP(NETIF_MSG_LINK, "read phy register failed\n");
+
+ *ret_val = 0;
+ rc = -EFAULT;
+ }
+ REG_WR(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE, mode);
+ return rc;
+}
+
+/******************************************************************/
+/* CL45 access functions */
+/******************************************************************/
+static int bnx2x_cl45_read(struct bnx2x *bp, struct bnx2x_phy *phy,
+ u8 devad, u16 reg, u16 *ret_val)
+{
+ u32 val;
+ u16 i;
+ int rc = 0;
/* address */
val = ((phy->addr << 21) | (devad << 16) | reg |
@@ -1460,7 +2970,6 @@
netdev_err(bp->dev, "MDC/MDIO access timeout\n");
*ret_val = 0;
rc = -EFAULT;
-
} else {
/* data */
val = ((phy->addr << 21) | (devad << 16) |
@@ -1485,15 +2994,214 @@
rc = -EFAULT;
}
}
-
- /* Restore the saved mode */
- REG_WR(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE, saved_mode);
+ /* Work around for E3 A0 */
+ if (phy->flags & FLAGS_MDC_MDIO_WA) {
+ phy->flags ^= FLAGS_DUMMY_READ;
+ if (phy->flags & FLAGS_DUMMY_READ) {
+ u16 temp_val;
+ bnx2x_cl45_read(bp, phy, devad, 0xf, &temp_val);
+ }
+ }
return rc;
}
-u8 bnx2x_phy_read(struct link_params *params, u8 phy_addr,
- u8 devad, u16 reg, u16 *ret_val)
+static int bnx2x_cl45_write(struct bnx2x *bp, struct bnx2x_phy *phy,
+ u8 devad, u16 reg, u16 val)
+{
+ u32 tmp;
+ u8 i;
+ int rc = 0;
+
+ /* address */
+
+ tmp = ((phy->addr << 21) | (devad << 16) | reg |
+ EMAC_MDIO_COMM_COMMAND_ADDRESS |
+ EMAC_MDIO_COMM_START_BUSY);
+ REG_WR(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, tmp);
+
+ for (i = 0; i < 50; i++) {
+ udelay(10);
+
+ tmp = REG_RD(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM);
+ if (!(tmp & EMAC_MDIO_COMM_START_BUSY)) {
+ udelay(5);
+ break;
+ }
+ }
+ if (tmp & EMAC_MDIO_COMM_START_BUSY) {
+ DP(NETIF_MSG_LINK, "write phy register failed\n");
+ netdev_err(bp->dev, "MDC/MDIO access timeout\n");
+ rc = -EFAULT;
+
+ } else {
+ /* data */
+ tmp = ((phy->addr << 21) | (devad << 16) | val |
+ EMAC_MDIO_COMM_COMMAND_WRITE_45 |
+ EMAC_MDIO_COMM_START_BUSY);
+ REG_WR(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, tmp);
+
+ for (i = 0; i < 50; i++) {
+ udelay(10);
+
+ tmp = REG_RD(bp, phy->mdio_ctrl +
+ EMAC_REG_EMAC_MDIO_COMM);
+ if (!(tmp & EMAC_MDIO_COMM_START_BUSY)) {
+ udelay(5);
+ break;
+ }
+ }
+ if (tmp & EMAC_MDIO_COMM_START_BUSY) {
+ DP(NETIF_MSG_LINK, "write phy register failed\n");
+ netdev_err(bp->dev, "MDC/MDIO access timeout\n");
+ rc = -EFAULT;
+ }
+ }
+ /* Work around for E3 A0 */
+ if (phy->flags & FLAGS_MDC_MDIO_WA) {
+ phy->flags ^= FLAGS_DUMMY_READ;
+ if (phy->flags & FLAGS_DUMMY_READ) {
+ u16 temp_val;
+ bnx2x_cl45_read(bp, phy, devad, 0xf, &temp_val);
+ }
+ }
+
+ return rc;
+}
+
+
+/******************************************************************/
+/* BSC access functions from E3 */
+/******************************************************************/
+static void bnx2x_bsc_module_sel(struct link_params *params)
+{
+ int idx;
+ u32 board_cfg, sfp_ctrl;
+ u32 i2c_pins[I2C_SWITCH_WIDTH], i2c_val[I2C_SWITCH_WIDTH];
+ struct bnx2x *bp = params->bp;
+ u8 port = params->port;
+ /* Read I2C output PINs */
+ board_cfg = REG_RD(bp, params->shmem_base +
+ offsetof(struct shmem_region,
+ dev_info.shared_hw_config.board));
+ i2c_pins[I2C_BSC0] = board_cfg & SHARED_HW_CFG_E3_I2C_MUX0_MASK;
+ i2c_pins[I2C_BSC1] = (board_cfg & SHARED_HW_CFG_E3_I2C_MUX1_MASK) >>
+ SHARED_HW_CFG_E3_I2C_MUX1_SHIFT;
+
+ /* Read I2C output value */
+ sfp_ctrl = REG_RD(bp, params->shmem_base +
+ offsetof(struct shmem_region,
+ dev_info.port_hw_config[port].e3_cmn_pin_cfg));
+ i2c_val[I2C_BSC0] = (sfp_ctrl & PORT_HW_CFG_E3_I2C_MUX0_MASK) > 0;
+ i2c_val[I2C_BSC1] = (sfp_ctrl & PORT_HW_CFG_E3_I2C_MUX1_MASK) > 0;
+ DP(NETIF_MSG_LINK, "Setting BSC switch\n");
+ for (idx = 0; idx < I2C_SWITCH_WIDTH; idx++)
+ bnx2x_set_cfg_pin(bp, i2c_pins[idx], i2c_val[idx]);
+}
+
+static int bnx2x_bsc_read(struct link_params *params,
+ struct bnx2x_phy *phy,
+ u8 sl_devid,
+ u16 sl_addr,
+ u8 lc_addr,
+ u8 xfer_cnt,
+ u32 *data_array)
+{
+ u32 val, i;
+ int rc = 0;
+ struct bnx2x *bp = params->bp;
+
+ if ((sl_devid != 0xa0) && (sl_devid != 0xa2)) {
+ DP(NETIF_MSG_LINK, "invalid sl_devid 0x%x\n", sl_devid);
+ return -EINVAL;
+ }
+
+ if (xfer_cnt > 16) {
+ DP(NETIF_MSG_LINK, "invalid xfer_cnt %d. Max is 16 bytes\n",
+ xfer_cnt);
+ return -EINVAL;
+ }
+ bnx2x_bsc_module_sel(params);
+
+ xfer_cnt = 16 - lc_addr;
+
+ /* enable the engine */
+ val = REG_RD(bp, MCP_REG_MCPR_IMC_COMMAND);
+ val |= MCPR_IMC_COMMAND_ENABLE;
+ REG_WR(bp, MCP_REG_MCPR_IMC_COMMAND, val);
+
+ /* program slave device ID */
+ val = (sl_devid << 16) | sl_addr;
+ REG_WR(bp, MCP_REG_MCPR_IMC_SLAVE_CONTROL, val);
+
+ /* start xfer with 0 byte to update the address pointer ???*/
+ val = (MCPR_IMC_COMMAND_ENABLE) |
+ (MCPR_IMC_COMMAND_WRITE_OP <<
+ MCPR_IMC_COMMAND_OPERATION_BITSHIFT) |
+ (lc_addr << MCPR_IMC_COMMAND_TRANSFER_ADDRESS_BITSHIFT) | (0);
+ REG_WR(bp, MCP_REG_MCPR_IMC_COMMAND, val);
+
+ /* poll for completion */
+ i = 0;
+ val = REG_RD(bp, MCP_REG_MCPR_IMC_COMMAND);
+ while (((val >> MCPR_IMC_COMMAND_IMC_STATUS_BITSHIFT) & 0x3) != 1) {
+ udelay(10);
+ val = REG_RD(bp, MCP_REG_MCPR_IMC_COMMAND);
+ if (i++ > 1000) {
+ DP(NETIF_MSG_LINK, "wr 0 byte timed out after %d try\n",
+ i);
+ rc = -EFAULT;
+ break;
+ }
+ }
+ if (rc == -EFAULT)
+ return rc;
+
+ /* start xfer with read op */
+ val = (MCPR_IMC_COMMAND_ENABLE) |
+ (MCPR_IMC_COMMAND_READ_OP <<
+ MCPR_IMC_COMMAND_OPERATION_BITSHIFT) |
+ (lc_addr << MCPR_IMC_COMMAND_TRANSFER_ADDRESS_BITSHIFT) |
+ (xfer_cnt);
+ REG_WR(bp, MCP_REG_MCPR_IMC_COMMAND, val);
+
+ /* poll for completion */
+ i = 0;
+ val = REG_RD(bp, MCP_REG_MCPR_IMC_COMMAND);
+ while (((val >> MCPR_IMC_COMMAND_IMC_STATUS_BITSHIFT) & 0x3) != 1) {
+ udelay(10);
+ val = REG_RD(bp, MCP_REG_MCPR_IMC_COMMAND);
+ if (i++ > 1000) {
+ DP(NETIF_MSG_LINK, "rd op timed out after %d try\n", i);
+ rc = -EFAULT;
+ break;
+ }
+ }
+ if (rc == -EFAULT)
+ return rc;
+
+ for (i = (lc_addr >> 2); i < 4; i++) {
+ data_array[i] = REG_RD(bp, (MCP_REG_MCPR_IMC_DATAREG0 + i*4));
+#ifdef __BIG_ENDIAN
+ data_array[i] = ((data_array[i] & 0x000000ff) << 24) |
+ ((data_array[i] & 0x0000ff00) << 8) |
+ ((data_array[i] & 0x00ff0000) >> 8) |
+ ((data_array[i] & 0xff000000) >> 24);
+#endif
+ }
+ return rc;
+}
+
+static void bnx2x_cl45_read_or_write(struct bnx2x *bp, struct bnx2x_phy *phy,
+ u8 devad, u16 reg, u16 or_val)
+{
+ u16 val;
+ bnx2x_cl45_read(bp, phy, devad, reg, &val);
+ bnx2x_cl45_write(bp, phy, devad, reg, val | or_val);
+}
+
+int bnx2x_phy_read(struct link_params *params, u8 phy_addr,
+ u8 devad, u16 reg, u16 *ret_val)
{
u8 phy_index;
/*
@@ -1510,8 +3218,8 @@
return -EINVAL;
}
-u8 bnx2x_phy_write(struct link_params *params, u8 phy_addr,
- u8 devad, u16 reg, u16 val)
+int bnx2x_phy_write(struct link_params *params, u8 phy_addr,
+ u8 devad, u16 reg, u16 val)
{
u8 phy_index;
/*
@@ -1527,9 +3235,62 @@
}
return -EINVAL;
}
+static u8 bnx2x_get_warpcore_lane(struct bnx2x_phy *phy,
+ struct link_params *params)
+{
+ u8 lane = 0;
+ struct bnx2x *bp = params->bp;
+ u32 path_swap, path_swap_ovr;
+ u8 path, port;
-static void bnx2x_set_aer_mmd_xgxs(struct link_params *params,
- struct bnx2x_phy *phy)
+ path = BP_PATH(bp);
+ port = params->port;
+
+ if (bnx2x_is_4_port_mode(bp)) {
+ u32 port_swap, port_swap_ovr;
+
+ /*figure out path swap value */
+ path_swap_ovr = REG_RD(bp, MISC_REG_FOUR_PORT_PATH_SWAP_OVWR);
+ if (path_swap_ovr & 0x1)
+ path_swap = (path_swap_ovr & 0x2);
+ else
+ path_swap = REG_RD(bp, MISC_REG_FOUR_PORT_PATH_SWAP);
+
+ if (path_swap)
+ path = path ^ 1;
+
+ /*figure out port swap value */
+ port_swap_ovr = REG_RD(bp, MISC_REG_FOUR_PORT_PORT_SWAP_OVWR);
+ if (port_swap_ovr & 0x1)
+ port_swap = (port_swap_ovr & 0x2);
+ else
+ port_swap = REG_RD(bp, MISC_REG_FOUR_PORT_PORT_SWAP);
+
+ if (port_swap)
+ port = port ^ 1;
+
+ lane = (port<<1) + path;
+ } else { /* two port mode - no port swap */
+
+ /*figure out path swap value */
+ path_swap_ovr =
+ REG_RD(bp, MISC_REG_TWO_PORT_PATH_SWAP_OVWR);
+ if (path_swap_ovr & 0x1) {
+ path_swap = (path_swap_ovr & 0x2);
+ } else {
+ path_swap =
+ REG_RD(bp, MISC_REG_TWO_PORT_PATH_SWAP);
+ }
+ if (path_swap)
+ path = path ^ 1;
+
+ lane = path << 1 ;
+ }
+ return lane;
+}
+
+static void bnx2x_set_aer_mmd(struct link_params *params,
+ struct bnx2x_phy *phy)
{
u32 ser_lane;
u16 offset, aer_val;
@@ -1538,20 +3299,28 @@
PORT_HW_CFG_LANE_SWAP_CFG_MASTER_MASK) >>
PORT_HW_CFG_LANE_SWAP_CFG_MASTER_SHIFT);
- offset = phy->addr + ser_lane;
- if (CHIP_IS_E2(bp))
+ offset = (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) ?
+ (phy->addr + ser_lane) : 0;
+
+ if (USES_WARPCORE(bp)) {
+ aer_val = bnx2x_get_warpcore_lane(phy, params);
+ /*
+ * In Dual-lane mode, two lanes are joined together,
+ * so in order to configure them, the AER broadcast method is
+ * used here.
+ * 0x200 is the broadcast address for lanes 0,1
+ * 0x201 is the broadcast address for lanes 2,3
+ */
+ if (phy->flags & FLAGS_WC_DUAL_MODE)
+ aer_val = (aer_val >> 1) | 0x200;
+ } else if (CHIP_IS_E2(bp))
aer_val = 0x3800 + offset - 1;
else
aer_val = 0x3800 + offset;
+ DP(NETIF_MSG_LINK, "Set AER to 0x%x\n", aer_val);
CL22_WR_OVER_CL45(bp, phy, MDIO_REG_BANK_AER_BLOCK,
MDIO_AER_BLOCK_AER_REG, aer_val);
-}
-static void bnx2x_set_aer_mmd_serdes(struct bnx2x *bp,
- struct bnx2x_phy *phy)
-{
- CL22_WR_OVER_CL45(bp, phy,
- MDIO_REG_BANK_AER_BLOCK,
- MDIO_AER_BLOCK_AER_REG, 0x3800);
+
}
/******************************************************************/
@@ -1611,20 +3380,979 @@
params->phy[INT_PHY].def_md_devad);
}
+static void bnx2x_calc_ieee_aneg_adv(struct bnx2x_phy *phy,
+ struct link_params *params, u16 *ieee_fc)
+{
+ struct bnx2x *bp = params->bp;
+ *ieee_fc = MDIO_COMBO_IEEE0_AUTO_NEG_ADV_FULL_DUPLEX;
+ /**
+ * resolve pause mode and advertisement Please refer to Table
+ * 28B-3 of the 802.3ab-1999 spec
+ */
+
+ switch (phy->req_flow_ctrl) {
+ case BNX2X_FLOW_CTRL_AUTO:
+ if (params->req_fc_auto_adv == BNX2X_FLOW_CTRL_BOTH)
+ *ieee_fc |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH;
+ else
+ *ieee_fc |=
+ MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC;
+ break;
+
+ case BNX2X_FLOW_CTRL_TX:
+ *ieee_fc |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC;
+ break;
+
+ case BNX2X_FLOW_CTRL_RX:
+ case BNX2X_FLOW_CTRL_BOTH:
+ *ieee_fc |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH;
+ break;
+
+ case BNX2X_FLOW_CTRL_NONE:
+ default:
+ *ieee_fc |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_NONE;
+ break;
+ }
+ DP(NETIF_MSG_LINK, "ieee_fc = 0x%x\n", *ieee_fc);
+}
+
+static void set_phy_vars(struct link_params *params,
+ struct link_vars *vars)
+{
+ struct bnx2x *bp = params->bp;
+ u8 actual_phy_idx, phy_index, link_cfg_idx;
+ u8 phy_config_swapped = params->multi_phy_config &
+ PORT_HW_CFG_PHY_SWAPPED_ENABLED;
+ for (phy_index = INT_PHY; phy_index < params->num_phys;
+ phy_index++) {
+ link_cfg_idx = LINK_CONFIG_IDX(phy_index);
+ actual_phy_idx = phy_index;
+ if (phy_config_swapped) {
+ if (phy_index == EXT_PHY1)
+ actual_phy_idx = EXT_PHY2;
+ else if (phy_index == EXT_PHY2)
+ actual_phy_idx = EXT_PHY1;
+ }
+ params->phy[actual_phy_idx].req_flow_ctrl =
+ params->req_flow_ctrl[link_cfg_idx];
+
+ params->phy[actual_phy_idx].req_line_speed =
+ params->req_line_speed[link_cfg_idx];
+
+ params->phy[actual_phy_idx].speed_cap_mask =
+ params->speed_cap_mask[link_cfg_idx];
+
+ params->phy[actual_phy_idx].req_duplex =
+ params->req_duplex[link_cfg_idx];
+
+ if (params->req_line_speed[link_cfg_idx] ==
+ SPEED_AUTO_NEG)
+ vars->link_status |= LINK_STATUS_AUTO_NEGOTIATE_ENABLED;
+
+ DP(NETIF_MSG_LINK, "req_flow_ctrl %x, req_line_speed %x,"
+ " speed_cap_mask %x\n",
+ params->phy[actual_phy_idx].req_flow_ctrl,
+ params->phy[actual_phy_idx].req_line_speed,
+ params->phy[actual_phy_idx].speed_cap_mask);
+ }
+}
+
+static void bnx2x_ext_phy_set_pause(struct link_params *params,
+ struct bnx2x_phy *phy,
+ struct link_vars *vars)
+{
+ u16 val;
+ struct bnx2x *bp = params->bp;
+ /* read modify write pause advertizing */
+ bnx2x_cl45_read(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_ADV_PAUSE, &val);
+
+ val &= ~MDIO_AN_REG_ADV_PAUSE_BOTH;
+
+ /* Please refer to Table 28B-3 of 802.3ab-1999 spec. */
+ bnx2x_calc_ieee_aneg_adv(phy, params, &vars->ieee_fc);
+ if ((vars->ieee_fc &
+ MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) ==
+ MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) {
+ val |= MDIO_AN_REG_ADV_PAUSE_ASYMMETRIC;
+ }
+ if ((vars->ieee_fc &
+ MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) ==
+ MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) {
+ val |= MDIO_AN_REG_ADV_PAUSE_PAUSE;
+ }
+ DP(NETIF_MSG_LINK, "Ext phy AN advertize 0x%x\n", val);
+ bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_ADV_PAUSE, val);
+}
+
+static void bnx2x_pause_resolve(struct link_vars *vars, u32 pause_result)
+{ /* LD LP */
+ switch (pause_result) { /* ASYM P ASYM P */
+ case 0xb: /* 1 0 1 1 */
+ vars->flow_ctrl = BNX2X_FLOW_CTRL_TX;
+ break;
+
+ case 0xe: /* 1 1 1 0 */
+ vars->flow_ctrl = BNX2X_FLOW_CTRL_RX;
+ break;
+
+ case 0x5: /* 0 1 0 1 */
+ case 0x7: /* 0 1 1 1 */
+ case 0xd: /* 1 1 0 1 */
+ case 0xf: /* 1 1 1 1 */
+ vars->flow_ctrl = BNX2X_FLOW_CTRL_BOTH;
+ break;
+
+ default:
+ break;
+ }
+ if (pause_result & (1<<0))
+ vars->link_status |= LINK_STATUS_LINK_PARTNER_SYMMETRIC_PAUSE;
+ if (pause_result & (1<<1))
+ vars->link_status |= LINK_STATUS_LINK_PARTNER_ASYMMETRIC_PAUSE;
+}
+
+static u8 bnx2x_ext_phy_resolve_fc(struct bnx2x_phy *phy,
+ struct link_params *params,
+ struct link_vars *vars)
+{
+ struct bnx2x *bp = params->bp;
+ u16 ld_pause; /* local */
+ u16 lp_pause; /* link partner */
+ u16 pause_result;
+ u8 ret = 0;
+ /* read twice */
+
+ vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
+
+ if (phy->req_flow_ctrl != BNX2X_FLOW_CTRL_AUTO)
+ vars->flow_ctrl = phy->req_flow_ctrl;
+ else if (phy->req_line_speed != SPEED_AUTO_NEG)
+ vars->flow_ctrl = params->req_fc_auto_adv;
+ else if (vars->link_status & LINK_STATUS_AUTO_NEGOTIATE_COMPLETE) {
+ ret = 1;
+ if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM54618SE) {
+ bnx2x_cl22_read(bp, phy,
+ 0x4, &ld_pause);
+ bnx2x_cl22_read(bp, phy,
+ 0x5, &lp_pause);
+ } else {
+ bnx2x_cl45_read(bp, phy,
+ MDIO_AN_DEVAD,
+ MDIO_AN_REG_ADV_PAUSE, &ld_pause);
+ bnx2x_cl45_read(bp, phy,
+ MDIO_AN_DEVAD,
+ MDIO_AN_REG_LP_AUTO_NEG, &lp_pause);
+ }
+ pause_result = (ld_pause &
+ MDIO_AN_REG_ADV_PAUSE_MASK) >> 8;
+ pause_result |= (lp_pause &
+ MDIO_AN_REG_ADV_PAUSE_MASK) >> 10;
+ DP(NETIF_MSG_LINK, "Ext PHY pause result 0x%x\n",
+ pause_result);
+ bnx2x_pause_resolve(vars, pause_result);
+ }
+ return ret;
+}
+/******************************************************************/
+/* Warpcore section */
+/******************************************************************/
+/* The init_internal_warpcore should mirror the xgxs,
+ * i.e. reset the lane (if needed), set aer for the
+ * init configuration, and set/clear SGMII flag. Internal
+ * phy init is done purely in phy_init stage.
+ */
+static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy,
+ struct link_params *params,
+ struct link_vars *vars) {
+ u16 val16 = 0, lane, bam37 = 0;
+ struct bnx2x *bp = params->bp;
+ DP(NETIF_MSG_LINK, "Enable Auto Negotiation for KR\n");
+ /* Check adding advertisement for 1G KX */
+ if (((vars->line_speed == SPEED_AUTO_NEG) &&
+ (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)) ||
+ (vars->line_speed == SPEED_1000)) {
+ u16 sd_digital;
+ val16 |= (1<<5);
+
+ /* Enable CL37 1G Parallel Detect */
+ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2, &sd_digital);
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2,
+ (sd_digital | 0x1));
+
+ DP(NETIF_MSG_LINK, "Advertize 1G\n");
+ }
+ if (((vars->line_speed == SPEED_AUTO_NEG) &&
+ (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)) ||
+ (vars->line_speed == SPEED_10000)) {
+ /* Check adding advertisement for 10G KR */
+ val16 |= (1<<7);
+ /* Enable 10G Parallel Detect */
+ bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD,
+ MDIO_WC_REG_PAR_DET_10G_CTRL, 1);
+
+ DP(NETIF_MSG_LINK, "Advertize 10G\n");
+ }
+
+ /* Set Transmit PMD settings */
+ lane = bnx2x_get_warpcore_lane(phy, params);
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_TX0_TX_DRIVER + 0x10*lane,
+ ((0x02 << MDIO_WC_REG_TX0_TX_DRIVER_POST2_COEFF_OFFSET) |
+ (0x06 << MDIO_WC_REG_TX0_TX_DRIVER_IDRIVER_OFFSET) |
+ (0x09 << MDIO_WC_REG_TX0_TX_DRIVER_IPRE_DRIVER_OFFSET)));
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_CL72_USERB0_CL72_OS_DEF_CTRL,
+ 0x03f0);
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_CL72_USERB0_CL72_2P5_DEF_CTRL,
+ 0x03f0);
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL,
+ 0x383f);
+
+ /* Advertised speeds */
+ bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD,
+ MDIO_WC_REG_AN_IEEE1BLK_AN_ADVERTISEMENT1, val16);
+
+ /* Enable CL37 BAM */
+ if (REG_RD(bp, params->shmem_base +
+ offsetof(struct shmem_region, dev_info.
+ port_hw_config[params->port].default_cfg)) &
+ PORT_HW_CFG_ENABLE_BAM_ON_KR_ENABLED) {
+ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_DIGITAL6_MP5_NEXTPAGECTRL, &bam37);
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_DIGITAL6_MP5_NEXTPAGECTRL, bam37 | 1);
+ DP(NETIF_MSG_LINK, "Enable CL37 BAM on KR\n");
+ }
+
+ /* Advertise pause */
+ bnx2x_ext_phy_set_pause(params, phy, vars);
+
+ /* Enable Autoneg */
+ bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD,
+ MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x1000);
+
+ /* Over 1G - AN local device user page 1 */
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_DIGITAL3_UP1, 0x1f);
+
+ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_DIGITAL5_MISC7, &val16);
+
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_DIGITAL5_MISC7, val16 | 0x100);
+}
+
+static void bnx2x_warpcore_set_10G_KR(struct bnx2x_phy *phy,
+ struct link_params *params,
+ struct link_vars *vars)
+{
+ struct bnx2x *bp = params->bp;
+ u16 val;
+
+ /* Disable Autoneg */
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2, 0x7);
+
+ bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD,
+ MDIO_WC_REG_PAR_DET_10G_CTRL, 0);
+
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL, 0x3f00);
+
+ bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD,
+ MDIO_WC_REG_AN_IEEE1BLK_AN_ADVERTISEMENT1, 0);
+
+ bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD,
+ MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x0);
+
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_DIGITAL3_UP1, 0x1);
+
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_DIGITAL5_MISC7, 0xa);
+
+ /* Disable CL36 PCS Tx */
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_XGXSBLK1_LANECTRL0, 0x0);
+
+ /* Double Wide Single Data Rate @ pll rate */
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_XGXSBLK1_LANECTRL1, 0xFFFF);
+
+ /* Leave cl72 training enable, needed for KR */
+ bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD,
+ MDIO_WC_REG_PMD_IEEE9BLK_TENGBASE_KR_PMD_CONTROL_REGISTER_150,
+ 0x2);
+
+ /* Leave CL72 enabled */
+ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL,
+ &val);
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL,
+ val | 0x3800);
+
+ /* Set speed via PMA/PMD register */
+ bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD,
+ MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x2040);
+
+ bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD,
+ MDIO_WC_REG_IEEE0BLK_AUTONEGNP, 0xB);
+
+ /*Enable encoded forced speed */
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_SERDESDIGITAL_MISC2, 0x30);
+
+ /* Turn TX scramble payload only the 64/66 scrambler */
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_TX66_CONTROL, 0x9);
+
+ /* Turn RX scramble payload only the 64/66 scrambler */
+ bnx2x_cl45_read_or_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_RX66_CONTROL, 0xF9);
+
+ /* set and clear loopback to cause a reset to 64/66 decoder */
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x4000);
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x0);
+
+}
+
+static void bnx2x_warpcore_set_10G_XFI(struct bnx2x_phy *phy,
+ struct link_params *params,
+ u8 is_xfi)
+{
+ struct bnx2x *bp = params->bp;
+ u16 misc1_val, tap_val, tx_driver_val, lane, val;
+ /* Hold rxSeqStart */
+ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_DSC2B0_DSC_MISC_CTRL0, &val);
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_DSC2B0_DSC_MISC_CTRL0, (val | 0x8000));
+
+ /* Hold tx_fifo_reset */
+ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X3, &val);
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X3, (val | 0x1));
+
+ /* Disable CL73 AN */
+ bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_CTRL, 0);
+
+ /* Disable 100FX Enable and Auto-Detect */
+ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_FX100_CTRL1, &val);
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_FX100_CTRL1, (val & 0xFFFA));
+
+ /* Disable 100FX Idle detect */
+ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_FX100_CTRL3, &val);
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_FX100_CTRL3, (val | 0x0080));
+
+ /* Set Block address to Remote PHY & Clear forced_speed[5] */
+ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_DIGITAL4_MISC3, &val);
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_DIGITAL4_MISC3, (val & 0xFF7F));
+
+ /* Turn off auto-detect & fiber mode */
+ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X1, &val);
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X1,
+ (val & 0xFFEE));
+
+ /* Set filter_force_link, disable_false_link and parallel_detect */
+ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2, &val);
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2,
+ ((val | 0x0006) & 0xFFFE));
+
+ /* Set XFI / SFI */
+ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_SERDESDIGITAL_MISC1, &misc1_val);
+
+ misc1_val &= ~(0x1f);
+
+ if (is_xfi) {
+ misc1_val |= 0x5;
+ tap_val = ((0x08 << MDIO_WC_REG_TX_FIR_TAP_POST_TAP_OFFSET) |
+ (0x37 << MDIO_WC_REG_TX_FIR_TAP_MAIN_TAP_OFFSET) |
+ (0x00 << MDIO_WC_REG_TX_FIR_TAP_PRE_TAP_OFFSET));
+ tx_driver_val =
+ ((0x00 << MDIO_WC_REG_TX0_TX_DRIVER_POST2_COEFF_OFFSET) |
+ (0x02 << MDIO_WC_REG_TX0_TX_DRIVER_IDRIVER_OFFSET) |
+ (0x03 << MDIO_WC_REG_TX0_TX_DRIVER_IPRE_DRIVER_OFFSET));
+
+ } else {
+ misc1_val |= 0x9;
+ tap_val = ((0x12 << MDIO_WC_REG_TX_FIR_TAP_POST_TAP_OFFSET) |
+ (0x2d << MDIO_WC_REG_TX_FIR_TAP_MAIN_TAP_OFFSET) |
+ (0x00 << MDIO_WC_REG_TX_FIR_TAP_PRE_TAP_OFFSET));
+ tx_driver_val =
+ ((0x02 << MDIO_WC_REG_TX0_TX_DRIVER_POST2_COEFF_OFFSET) |
+ (0x02 << MDIO_WC_REG_TX0_TX_DRIVER_IDRIVER_OFFSET) |
+ (0x02 << MDIO_WC_REG_TX0_TX_DRIVER_IPRE_DRIVER_OFFSET));
+ }
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_SERDESDIGITAL_MISC1, misc1_val);
+
+ /* Set Transmit PMD settings */
+ lane = bnx2x_get_warpcore_lane(phy, params);
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_TX_FIR_TAP,
+ tap_val | MDIO_WC_REG_TX_FIR_TAP_ENABLE);
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_TX0_TX_DRIVER + 0x10*lane,
+ tx_driver_val);
+
+ /* Enable fiber mode, enable and invert sig_det */
+ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X1, &val);
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X1, val | 0xd);
+
+ /* Set Block address to Remote PHY & Set forced_speed[5], 40bit mode */
+ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_DIGITAL4_MISC3, &val);
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_DIGITAL4_MISC3, val | 0x8080);
+
+ /* 10G XFI Full Duplex */
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x100);
+
+ /* Release tx_fifo_reset */
+ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X3, &val);
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X3, val & 0xFFFE);
+
+ /* Release rxSeqStart */
+ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_DSC2B0_DSC_MISC_CTRL0, &val);
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_DSC2B0_DSC_MISC_CTRL0, (val & 0x7FFF));
+}
+
+static void bnx2x_warpcore_set_20G_KR2(struct bnx2x *bp,
+ struct bnx2x_phy *phy)
+{
+ DP(NETIF_MSG_LINK, "KR2 still not supported !!!\n");
+}
+
+static void bnx2x_warpcore_set_20G_DXGXS(struct bnx2x *bp,
+ struct bnx2x_phy *phy,
+ u16 lane)
+{
+ /* Rx0 anaRxControl1G */
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_RX0_ANARXCONTROL1G, 0x90);
+
+ /* Rx2 anaRxControl1G */
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_RX2_ANARXCONTROL1G, 0x90);
+
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_RX66_SCW0, 0xE070);
+
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_RX66_SCW1, 0xC0D0);
+
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_RX66_SCW2, 0xA0B0);
+
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_RX66_SCW3, 0x8090);
+
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_RX66_SCW0_MASK, 0xF0F0);
+
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_RX66_SCW1_MASK, 0xF0F0);
+
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_RX66_SCW2_MASK, 0xF0F0);
+
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_RX66_SCW3_MASK, 0xF0F0);
+
+ /* Serdes Digital Misc1 */
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_SERDESDIGITAL_MISC1, 0x6008);
+
+ /* Serdes Digital4 Misc3 */
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_DIGITAL4_MISC3, 0x8088);
+
+ /* Set Transmit PMD settings */
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_TX_FIR_TAP,
+ ((0x12 << MDIO_WC_REG_TX_FIR_TAP_POST_TAP_OFFSET) |
+ (0x2d << MDIO_WC_REG_TX_FIR_TAP_MAIN_TAP_OFFSET) |
+ (0x00 << MDIO_WC_REG_TX_FIR_TAP_PRE_TAP_OFFSET) |
+ MDIO_WC_REG_TX_FIR_TAP_ENABLE));
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_TX0_TX_DRIVER + 0x10*lane,
+ ((0x02 << MDIO_WC_REG_TX0_TX_DRIVER_POST2_COEFF_OFFSET) |
+ (0x02 << MDIO_WC_REG_TX0_TX_DRIVER_IDRIVER_OFFSET) |
+ (0x02 << MDIO_WC_REG_TX0_TX_DRIVER_IPRE_DRIVER_OFFSET)));
+}
+
+static void bnx2x_warpcore_set_sgmii_speed(struct bnx2x_phy *phy,
+ struct link_params *params,
+ u8 fiber_mode)
+{
+ struct bnx2x *bp = params->bp;
+ u16 val16, digctrl_kx1, digctrl_kx2;
+ u8 lane;
+
+ lane = bnx2x_get_warpcore_lane(phy, params);
+
+ /* Clear XFI clock comp in non-10G single lane mode. */
+ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_RX66_CONTROL, &val16);
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_RX66_CONTROL, val16 & ~(3<<13));
+
+ if (phy->req_line_speed == SPEED_AUTO_NEG) {
+ /* SGMII Autoneg */
+ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_COMBO_IEEE0_MIICTRL, &val16);
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_COMBO_IEEE0_MIICTRL,
+ val16 | 0x1000);
+ DP(NETIF_MSG_LINK, "set SGMII AUTONEG\n");
+ } else {
+ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_COMBO_IEEE0_MIICTRL, &val16);
+ val16 &= 0xcfbf;
+ switch (phy->req_line_speed) {
+ case SPEED_10:
+ break;
+ case SPEED_100:
+ val16 |= 0x2000;
+ break;
+ case SPEED_1000:
+ val16 |= 0x0040;
+ break;
+ default:
+ DP(NETIF_MSG_LINK, "Speed not supported: 0x%x"
+ "\n", phy->req_line_speed);
+ return;
+ }
+
+ if (phy->req_duplex == DUPLEX_FULL)
+ val16 |= 0x0100;
+
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_COMBO_IEEE0_MIICTRL, val16);
+
+ DP(NETIF_MSG_LINK, "set SGMII force speed %d\n",
+ phy->req_line_speed);
+ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_COMBO_IEEE0_MIICTRL, &val16);
+ DP(NETIF_MSG_LINK, " (readback) %x\n", val16);
+ }
+
+ /* SGMII Slave mode and disable signal detect */
+ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X1, &digctrl_kx1);
+ if (fiber_mode)
+ digctrl_kx1 = 1;
+ else
+ digctrl_kx1 &= 0xff4a;
+
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X1,
+ digctrl_kx1);
+
+ /* Turn off parallel detect */
+ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2, &digctrl_kx2);
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2,
+ (digctrl_kx2 & ~(1<<2)));
+
+ /* Re-enable parallel detect */
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2,
+ (digctrl_kx2 | (1<<2)));
+
+ /* Enable autodet */
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X1,
+ (digctrl_kx1 | 0x10));
+}
+
+static void bnx2x_warpcore_reset_lane(struct bnx2x *bp,
+ struct bnx2x_phy *phy,
+ u8 reset)
+{
+ u16 val;
+ /* Take lane out of reset after configuration is finished */
+ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_DIGITAL5_MISC6, &val);
+ if (reset)
+ val |= 0xC000;
+ else
+ val &= 0x3FFF;
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_DIGITAL5_MISC6, val);
+ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_DIGITAL5_MISC6, &val);
+}
+
+
+ /* Clear SFI/XFI link settings registers */
+static void bnx2x_warpcore_clear_regs(struct bnx2x_phy *phy,
+ struct link_params *params,
+ u16 lane)
+{
+ struct bnx2x *bp = params->bp;
+ u16 val16;
+
+ /* Set XFI clock comp as default. */
+ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_RX66_CONTROL, &val16);
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_RX66_CONTROL, val16 | (3<<13));
+
+ bnx2x_warpcore_reset_lane(bp, phy, 1);
+ bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_CTRL, 0);
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_FX100_CTRL1, 0x014a);
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_FX100_CTRL3, 0x0800);
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_DIGITAL4_MISC3, 0x8008);
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X1, 0x0195);
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2, 0x0007);
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X3, 0x0002);
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_SERDESDIGITAL_MISC1, 0x6000);
+ lane = bnx2x_get_warpcore_lane(phy, params);
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_TX_FIR_TAP, 0x0000);
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_TX0_TX_DRIVER + 0x10*lane, 0x0990);
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x2040);
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_COMBO_IEEE0_MIICTRL, 0x0140);
+ bnx2x_warpcore_reset_lane(bp, phy, 0);
+}
+
+static int bnx2x_get_mod_abs_int_cfg(struct bnx2x *bp,
+ u32 chip_id,
+ u32 shmem_base, u8 port,
+ u8 *gpio_num, u8 *gpio_port)
+{
+ u32 cfg_pin;
+ *gpio_num = 0;
+ *gpio_port = 0;
+ if (CHIP_IS_E3(bp)) {
+ cfg_pin = (REG_RD(bp, shmem_base +
+ offsetof(struct shmem_region,
+ dev_info.port_hw_config[port].e3_sfp_ctrl)) &
+ PORT_HW_CFG_E3_MOD_ABS_MASK) >>
+ PORT_HW_CFG_E3_MOD_ABS_SHIFT;
+
+ /*
+ * Should not happen. This function called upon interrupt
+ * triggered by GPIO ( since EPIO can only generate interrupts
+ * to MCP).
+ * So if this function was called and none of the GPIOs was set,
+ * it means the shit hit the fan.
+ */
+ if ((cfg_pin < PIN_CFG_GPIO0_P0) ||
+ (cfg_pin > PIN_CFG_GPIO3_P1)) {
+ DP(NETIF_MSG_LINK, "ERROR: Invalid cfg pin %x for "
+ "module detect indication\n",
+ cfg_pin);
+ return -EINVAL;
+ }
+
+ *gpio_num = (cfg_pin - PIN_CFG_GPIO0_P0) & 0x3;
+ *gpio_port = (cfg_pin - PIN_CFG_GPIO0_P0) >> 2;
+ } else {
+ *gpio_num = MISC_REGISTERS_GPIO_3;
+ *gpio_port = port;
+ }
+ DP(NETIF_MSG_LINK, "MOD_ABS int GPIO%d_P%d\n", *gpio_num, *gpio_port);
+ return 0;
+}
+
+static int bnx2x_is_sfp_module_plugged(struct bnx2x_phy *phy,
+ struct link_params *params)
+{
+ struct bnx2x *bp = params->bp;
+ u8 gpio_num, gpio_port;
+ u32 gpio_val;
+ if (bnx2x_get_mod_abs_int_cfg(bp, params->chip_id,
+ params->shmem_base, params->port,
+ &gpio_num, &gpio_port) != 0)
+ return 0;
+ gpio_val = bnx2x_get_gpio(bp, gpio_num, gpio_port);
+
+ /* Call the handling function in case module is detected */
+ if (gpio_val == 0)
+ return 1;
+ else
+ return 0;
+}
+
+static void bnx2x_warpcore_config_init(struct bnx2x_phy *phy,
+ struct link_params *params,
+ struct link_vars *vars)
+{
+ struct bnx2x *bp = params->bp;
+ u32 serdes_net_if;
+ u8 fiber_mode;
+ u16 lane = bnx2x_get_warpcore_lane(phy, params);
+ serdes_net_if = (REG_RD(bp, params->shmem_base +
+ offsetof(struct shmem_region, dev_info.
+ port_hw_config[params->port].default_cfg)) &
+ PORT_HW_CFG_NET_SERDES_IF_MASK);
+ DP(NETIF_MSG_LINK, "Begin Warpcore init, link_speed %d, "
+ "serdes_net_if = 0x%x\n",
+ vars->line_speed, serdes_net_if);
+ bnx2x_set_aer_mmd(params, phy);
+
+ vars->phy_flags |= PHY_XGXS_FLAG;
+ if ((serdes_net_if == PORT_HW_CFG_NET_SERDES_IF_SGMII) ||
+ (phy->req_line_speed &&
+ ((phy->req_line_speed == SPEED_100) ||
+ (phy->req_line_speed == SPEED_10)))) {
+ vars->phy_flags |= PHY_SGMII_FLAG;
+ DP(NETIF_MSG_LINK, "Setting SGMII mode\n");
+ bnx2x_warpcore_clear_regs(phy, params, lane);
+ bnx2x_warpcore_set_sgmii_speed(phy, params, 0);
+ } else {
+ switch (serdes_net_if) {
+ case PORT_HW_CFG_NET_SERDES_IF_KR:
+ /* Enable KR Auto Neg */
+ if (params->loopback_mode == LOOPBACK_NONE)
+ bnx2x_warpcore_enable_AN_KR(phy, params, vars);
+ else {
+ DP(NETIF_MSG_LINK, "Setting KR 10G-Force\n");
+ bnx2x_warpcore_set_10G_KR(phy, params, vars);
+ }
+ break;
+
+ case PORT_HW_CFG_NET_SERDES_IF_XFI:
+ bnx2x_warpcore_clear_regs(phy, params, lane);
+ if (vars->line_speed == SPEED_10000) {
+ DP(NETIF_MSG_LINK, "Setting 10G XFI\n");
+ bnx2x_warpcore_set_10G_XFI(phy, params, 1);
+ } else {
+ if (SINGLE_MEDIA_DIRECT(params)) {
+ DP(NETIF_MSG_LINK, "1G Fiber\n");
+ fiber_mode = 1;
+ } else {
+ DP(NETIF_MSG_LINK, "10/100/1G SGMII\n");
+ fiber_mode = 0;
+ }
+ bnx2x_warpcore_set_sgmii_speed(phy,
+ params,
+ fiber_mode);
+ }
+
+ break;
+
+ case PORT_HW_CFG_NET_SERDES_IF_SFI:
+
+ bnx2x_warpcore_clear_regs(phy, params, lane);
+ if (vars->line_speed == SPEED_10000) {
+ DP(NETIF_MSG_LINK, "Setting 10G SFI\n");
+ bnx2x_warpcore_set_10G_XFI(phy, params, 0);
+ } else if (vars->line_speed == SPEED_1000) {
+ DP(NETIF_MSG_LINK, "Setting 1G Fiber\n");
+ bnx2x_warpcore_set_sgmii_speed(phy, params, 1);
+ }
+ /* Issue Module detection */
+ if (bnx2x_is_sfp_module_plugged(phy, params))
+ bnx2x_sfp_module_detection(phy, params);
+ break;
+
+ case PORT_HW_CFG_NET_SERDES_IF_DXGXS:
+ if (vars->line_speed != SPEED_20000) {
+ DP(NETIF_MSG_LINK, "Speed not supported yet\n");
+ return;
+ }
+ DP(NETIF_MSG_LINK, "Setting 20G DXGXS\n");
+ bnx2x_warpcore_set_20G_DXGXS(bp, phy, lane);
+ /* Issue Module detection */
+
+ bnx2x_sfp_module_detection(phy, params);
+ break;
+
+ case PORT_HW_CFG_NET_SERDES_IF_KR2:
+ if (vars->line_speed != SPEED_20000) {
+ DP(NETIF_MSG_LINK, "Speed not supported yet\n");
+ return;
+ }
+ DP(NETIF_MSG_LINK, "Setting 20G KR2\n");
+ bnx2x_warpcore_set_20G_KR2(bp, phy);
+ break;
+
+ default:
+ DP(NETIF_MSG_LINK, "Unsupported Serdes Net Interface "
+ "0x%x\n", serdes_net_if);
+ return;
+ }
+ }
+
+ /* Take lane out of reset after configuration is finished */
+ bnx2x_warpcore_reset_lane(bp, phy, 0);
+ DP(NETIF_MSG_LINK, "Exit config init\n");
+}
+
+static void bnx2x_sfp_e3_set_transmitter(struct link_params *params,
+ struct bnx2x_phy *phy,
+ u8 tx_en)
+{
+ struct bnx2x *bp = params->bp;
+ u32 cfg_pin;
+ u8 port = params->port;
+
+ cfg_pin = REG_RD(bp, params->shmem_base +
+ offsetof(struct shmem_region,
+ dev_info.port_hw_config[port].e3_sfp_ctrl)) &
+ PORT_HW_CFG_TX_LASER_MASK;
+ /* Set the !tx_en since this pin is DISABLE_TX_LASER */
+ DP(NETIF_MSG_LINK, "Setting WC TX to %d\n", tx_en);
+ /* For 20G, the expected pin to be used is 3 pins after the current */
+
+ bnx2x_set_cfg_pin(bp, cfg_pin, tx_en ^ 1);
+ if (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_20G)
+ bnx2x_set_cfg_pin(bp, cfg_pin + 3, tx_en ^ 1);
+}
+
+static void bnx2x_warpcore_link_reset(struct bnx2x_phy *phy,
+ struct link_params *params)
+{
+ struct bnx2x *bp = params->bp;
+ u16 val16;
+ bnx2x_sfp_e3_set_transmitter(params, phy, 0);
+ bnx2x_set_mdio_clk(bp, params->chip_id, params->port);
+ bnx2x_set_aer_mmd(params, phy);
+ /* Global register */
+ bnx2x_warpcore_reset_lane(bp, phy, 1);
+
+ /* Clear loopback settings (if any) */
+ /* 10G & 20G */
+ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_COMBO_IEEE0_MIICTRL, &val16);
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_COMBO_IEEE0_MIICTRL, val16 &
+ 0xBFFF);
+
+ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_IEEE0BLK_MIICNTL, &val16);
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_IEEE0BLK_MIICNTL, val16 & 0xfffe);
+
+ /* Update those 1-copy registers */
+ CL22_WR_OVER_CL45(bp, phy, MDIO_REG_BANK_AER_BLOCK,
+ MDIO_AER_BLOCK_AER_REG, 0);
+ /* Enable 1G MDIO (1-copy) */
+ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_XGXSBLK0_XGXSCONTROL,
+ &val16);
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_XGXSBLK0_XGXSCONTROL,
+ val16 & ~0x10);
+
+ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_XGXSBLK1_LANECTRL2, &val16);
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_XGXSBLK1_LANECTRL2,
+ val16 & 0xff00);
+
+}
+
+static void bnx2x_set_warpcore_loopback(struct bnx2x_phy *phy,
+ struct link_params *params)
+{
+ struct bnx2x *bp = params->bp;
+ u16 val16;
+ u32 lane;
+ DP(NETIF_MSG_LINK, "Setting Warpcore loopback type %x, speed %d\n",
+ params->loopback_mode, phy->req_line_speed);
+
+ if (phy->req_line_speed < SPEED_10000) {
+ /* 10/100/1000 */
+
+ /* Update those 1-copy registers */
+ CL22_WR_OVER_CL45(bp, phy, MDIO_REG_BANK_AER_BLOCK,
+ MDIO_AER_BLOCK_AER_REG, 0);
+ /* Enable 1G MDIO (1-copy) */
+ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_XGXSBLK0_XGXSCONTROL,
+ &val16);
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_XGXSBLK0_XGXSCONTROL,
+ val16 | 0x10);
+ /* Set 1G loopback based on lane (1-copy) */
+ lane = bnx2x_get_warpcore_lane(phy, params);
+ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_XGXSBLK1_LANECTRL2, &val16);
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_XGXSBLK1_LANECTRL2,
+ val16 | (1<<lane));
+
+ /* Switch back to 4-copy registers */
+ bnx2x_set_aer_mmd(params, phy);
+ /* Global loopback, not recommended. */
+ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_COMBO_IEEE0_MIICTRL, &val16);
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_COMBO_IEEE0_MIICTRL, val16 |
+ 0x4000);
+ } else {
+ /* 10G & 20G */
+ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_COMBO_IEEE0_MIICTRL, &val16);
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_COMBO_IEEE0_MIICTRL, val16 |
+ 0x4000);
+
+ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_IEEE0BLK_MIICNTL, &val16);
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_IEEE0BLK_MIICNTL, val16 | 0x1);
+ }
+}
+
void bnx2x_link_status_update(struct link_params *params,
struct link_vars *vars)
{
struct bnx2x *bp = params->bp;
- u8 link_10g;
+ u8 link_10g_plus;
u8 port = params->port;
+ u32 sync_offset, media_types;
+ /* Update PHY configuration */
+ set_phy_vars(params, vars);
vars->link_status = REG_RD(bp, params->shmem_base +
offsetof(struct shmem_region,
port_mb[port].link_status));
vars->link_up = (vars->link_status & LINK_STATUS_LINK_UP);
-
+ vars->phy_flags = PHY_XGXS_FLAG;
if (vars->link_up) {
DP(NETIF_MSG_LINK, "phy link up\n");
@@ -1664,27 +4392,9 @@
case LINK_10GTFD:
vars->line_speed = SPEED_10000;
break;
-
- case LINK_12GTFD:
- vars->line_speed = SPEED_12000;
+ case LINK_20GTFD:
+ vars->line_speed = SPEED_20000;
break;
-
- case LINK_12_5GTFD:
- vars->line_speed = SPEED_12500;
- break;
-
- case LINK_13GTFD:
- vars->line_speed = SPEED_13000;
- break;
-
- case LINK_15GTFD:
- vars->line_speed = SPEED_15000;
- break;
-
- case LINK_16GTFD:
- vars->line_speed = SPEED_16000;
- break;
-
default:
break;
}
@@ -1705,19 +4415,24 @@
} else {
vars->phy_flags &= ~PHY_SGMII_FLAG;
}
-
+ if (vars->line_speed &&
+ USES_WARPCORE(bp) &&
+ (vars->line_speed == SPEED_1000))
+ vars->phy_flags |= PHY_SGMII_FLAG;
/* anything 10 and over uses the bmac */
- link_10g = ((vars->line_speed == SPEED_10000) ||
- (vars->line_speed == SPEED_12000) ||
- (vars->line_speed == SPEED_12500) ||
- (vars->line_speed == SPEED_13000) ||
- (vars->line_speed == SPEED_15000) ||
- (vars->line_speed == SPEED_16000));
- if (link_10g)
- vars->mac_type = MAC_TYPE_BMAC;
- else
- vars->mac_type = MAC_TYPE_EMAC;
+ link_10g_plus = (vars->line_speed >= SPEED_10000);
+ if (link_10g_plus) {
+ if (USES_WARPCORE(bp))
+ vars->mac_type = MAC_TYPE_XMAC;
+ else
+ vars->mac_type = MAC_TYPE_BMAC;
+ } else {
+ if (USES_WARPCORE(bp))
+ vars->mac_type = MAC_TYPE_UMAC;
+ else
+ vars->mac_type = MAC_TYPE_EMAC;
+ }
} else { /* link down */
DP(NETIF_MSG_LINK, "phy link down\n");
@@ -1731,8 +4446,40 @@
vars->mac_type = MAC_TYPE_NONE;
}
- DP(NETIF_MSG_LINK, "link_status 0x%x phy_link_up %x\n",
- vars->link_status, vars->phy_link_up);
+ /* Sync media type */
+ sync_offset = params->shmem_base +
+ offsetof(struct shmem_region,
+ dev_info.port_hw_config[port].media_type);
+ media_types = REG_RD(bp, sync_offset);
+
+ params->phy[INT_PHY].media_type =
+ (media_types & PORT_HW_CFG_MEDIA_TYPE_PHY0_MASK) >>
+ PORT_HW_CFG_MEDIA_TYPE_PHY0_SHIFT;
+ params->phy[EXT_PHY1].media_type =
+ (media_types & PORT_HW_CFG_MEDIA_TYPE_PHY1_MASK) >>
+ PORT_HW_CFG_MEDIA_TYPE_PHY1_SHIFT;
+ params->phy[EXT_PHY2].media_type =
+ (media_types & PORT_HW_CFG_MEDIA_TYPE_PHY2_MASK) >>
+ PORT_HW_CFG_MEDIA_TYPE_PHY2_SHIFT;
+ DP(NETIF_MSG_LINK, "media_types = 0x%x\n", media_types);
+
+ /* Sync AEU offset */
+ sync_offset = params->shmem_base +
+ offsetof(struct shmem_region,
+ dev_info.port_hw_config[port].aeu_int_mask);
+
+ vars->aeu_int_mask = REG_RD(bp, sync_offset);
+
+ /* Sync PFC status */
+ if (vars->link_status & LINK_STATUS_PFC_ENABLED)
+ params->feature_config_flags |=
+ FEATURE_CONFIG_PFC_ENABLED;
+ else
+ params->feature_config_flags &=
+ ~FEATURE_CONFIG_PFC_ENABLED;
+
+ DP(NETIF_MSG_LINK, "link_status 0x%x phy_link_up %x int_mask 0x%x\n",
+ vars->link_status, vars->phy_link_up, vars->aeu_int_mask);
DP(NETIF_MSG_LINK, "line_speed %x duplex %x flow_ctrl 0x%x\n",
vars->line_speed, vars->duplex, vars->flow_ctrl);
}
@@ -1759,9 +4506,9 @@
(new_master_ln | ser_lane));
}
-static u8 bnx2x_reset_unicore(struct link_params *params,
- struct bnx2x_phy *phy,
- u8 set_serdes)
+static int bnx2x_reset_unicore(struct link_params *params,
+ struct bnx2x_phy *phy,
+ u8 set_serdes)
{
struct bnx2x *bp = params->bp;
u16 mii_control;
@@ -2048,9 +4795,6 @@
if (vars->line_speed == SPEED_10000)
reg_val |=
MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_10G_CX4;
- if (vars->line_speed == SPEED_13000)
- reg_val |=
- MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_13G;
}
CL22_WR_OVER_CL45(bp, phy,
@@ -2059,8 +4803,8 @@
}
-static void bnx2x_set_brcm_cl37_advertisment(struct bnx2x_phy *phy,
- struct link_params *params)
+static void bnx2x_set_brcm_cl37_advertisement(struct bnx2x_phy *phy,
+ struct link_params *params)
{
struct bnx2x *bp = params->bp;
u16 val = 0;
@@ -2081,44 +4825,9 @@
MDIO_OVER_1G_UP3, 0x400);
}
-static void bnx2x_calc_ieee_aneg_adv(struct bnx2x_phy *phy,
- struct link_params *params, u16 *ieee_fc)
-{
- struct bnx2x *bp = params->bp;
- *ieee_fc = MDIO_COMBO_IEEE0_AUTO_NEG_ADV_FULL_DUPLEX;
- /*
- * Resolve pause mode and advertisement.
- * Please refer to Table 28B-3 of the 802.3ab-1999 spec
- */
-
- switch (phy->req_flow_ctrl) {
- case BNX2X_FLOW_CTRL_AUTO:
- if (params->req_fc_auto_adv == BNX2X_FLOW_CTRL_BOTH)
- *ieee_fc |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH;
- else
- *ieee_fc |=
- MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC;
- break;
- case BNX2X_FLOW_CTRL_TX:
- *ieee_fc |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC;
- break;
-
- case BNX2X_FLOW_CTRL_RX:
- case BNX2X_FLOW_CTRL_BOTH:
- *ieee_fc |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH;
- break;
-
- case BNX2X_FLOW_CTRL_NONE:
- default:
- *ieee_fc |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_NONE;
- break;
- }
- DP(NETIF_MSG_LINK, "ieee_fc = 0x%x\n", *ieee_fc);
-}
-
-static void bnx2x_set_ieee_aneg_advertisment(struct bnx2x_phy *phy,
- struct link_params *params,
- u16 ieee_fc)
+static void bnx2x_set_ieee_aneg_advertisement(struct bnx2x_phy *phy,
+ struct link_params *params,
+ u16 ieee_fc)
{
struct bnx2x *bp = params->bp;
u16 val;
@@ -2252,35 +4961,8 @@
* link management
*/
-static void bnx2x_pause_resolve(struct link_vars *vars, u32 pause_result)
-{ /* LD LP */
- switch (pause_result) { /* ASYM P ASYM P */
- case 0xb: /* 1 0 1 1 */
- vars->flow_ctrl = BNX2X_FLOW_CTRL_TX;
- break;
-
- case 0xe: /* 1 1 1 0 */
- vars->flow_ctrl = BNX2X_FLOW_CTRL_RX;
- break;
-
- case 0x5: /* 0 1 0 1 */
- case 0x7: /* 0 1 1 1 */
- case 0xd: /* 1 1 0 1 */
- case 0xf: /* 1 1 1 1 */
- vars->flow_ctrl = BNX2X_FLOW_CTRL_BOTH;
- break;
-
- default:
- break;
- }
- if (pause_result & (1<<0))
- vars->link_status |= LINK_STATUS_LINK_PARTNER_SYMMETRIC_PAUSE;
- if (pause_result & (1<<1))
- vars->link_status |= LINK_STATUS_LINK_PARTNER_ASYMMETRIC_PAUSE;
-}
-
-static u8 bnx2x_direct_parallel_detect_used(struct bnx2x_phy *phy,
- struct link_params *params)
+static int bnx2x_direct_parallel_detect_used(struct bnx2x_phy *phy,
+ struct link_params *params)
{
struct bnx2x *bp = params->bp;
u16 pd_10g, status2_1000x;
@@ -2383,7 +5065,7 @@
struct link_params *params)
{
struct bnx2x *bp = params->bp;
- u16 rx_status, ustat_val, cl37_fsm_recieved;
+ u16 rx_status, ustat_val, cl37_fsm_received;
DP(NETIF_MSG_LINK, "bnx2x_check_fallback_to_cl37\n");
/* Step 1: Make sure signal is detected */
CL22_RD_OVER_CL45(bp, phy,
@@ -2421,15 +5103,15 @@
CL22_RD_OVER_CL45(bp, phy,
MDIO_REG_BANK_REMOTE_PHY,
MDIO_REMOTE_PHY_MISC_RX_STATUS,
- &cl37_fsm_recieved);
- if ((cl37_fsm_recieved &
+ &cl37_fsm_received);
+ if ((cl37_fsm_received &
(MDIO_REMOTE_PHY_MISC_RX_STATUS_CL37_FSM_RECEIVED_OVER1G_MSG |
MDIO_REMOTE_PHY_MISC_RX_STATUS_CL37_FSM_RECEIVED_BRCM_OUI_MSG)) !=
(MDIO_REMOTE_PHY_MISC_RX_STATUS_CL37_FSM_RECEIVED_OVER1G_MSG |
MDIO_REMOTE_PHY_MISC_RX_STATUS_CL37_FSM_RECEIVED_BRCM_OUI_MSG)) {
DP(NETIF_MSG_LINK, "No CL37 FSM were received. "
"misc_rx_status(0x8330) = 0x%x\n",
- cl37_fsm_recieved);
+ cl37_fsm_received);
return;
}
/*
@@ -2462,45 +5144,25 @@
vars->link_status |=
LINK_STATUS_PARALLEL_DETECTION_USED;
}
-
-static u8 bnx2x_link_settings_status(struct bnx2x_phy *phy,
+static int bnx2x_get_link_speed_duplex(struct bnx2x_phy *phy,
struct link_params *params,
- struct link_vars *vars)
+ struct link_vars *vars,
+ u16 is_link_up,
+ u16 speed_mask,
+ u16 is_duplex)
{
struct bnx2x *bp = params->bp;
- u16 new_line_speed, gp_status;
- u8 rc = 0;
-
- /* Read gp_status */
- CL22_RD_OVER_CL45(bp, phy,
- MDIO_REG_BANK_GP_STATUS,
- MDIO_GP_STATUS_TOP_AN_STATUS1,
- &gp_status);
-
if (phy->req_line_speed == SPEED_AUTO_NEG)
vars->link_status |= LINK_STATUS_AUTO_NEGOTIATE_ENABLED;
- if (gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_LINK_STATUS) {
- DP(NETIF_MSG_LINK, "phy link up gp_status=0x%x\n",
- gp_status);
+ if (is_link_up) {
+ DP(NETIF_MSG_LINK, "phy link up\n");
vars->phy_link_up = 1;
vars->link_status |= LINK_STATUS_LINK_UP;
- if (gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_DUPLEX_STATUS)
- vars->duplex = DUPLEX_FULL;
- else
- vars->duplex = DUPLEX_HALF;
-
- if (SINGLE_MEDIA_DIRECT(params)) {
- bnx2x_flow_ctrl_resolve(phy, params, vars, gp_status);
- if (phy->req_line_speed == SPEED_AUTO_NEG)
- bnx2x_xgxs_an_resolve(phy, params, vars,
- gp_status);
- }
-
- switch (gp_status & GP_STATUS_SPEED_MASK) {
+ switch (speed_mask) {
case GP_STATUS_10M:
- new_line_speed = SPEED_10;
+ vars->line_speed = SPEED_10;
if (vars->duplex == DUPLEX_FULL)
vars->link_status |= LINK_10TFD;
else
@@ -2508,7 +5170,7 @@
break;
case GP_STATUS_100M:
- new_line_speed = SPEED_100;
+ vars->line_speed = SPEED_100;
if (vars->duplex == DUPLEX_FULL)
vars->link_status |= LINK_100TXFD;
else
@@ -2517,7 +5179,7 @@
case GP_STATUS_1G:
case GP_STATUS_1G_KX:
- new_line_speed = SPEED_1000;
+ vars->line_speed = SPEED_1000;
if (vars->duplex == DUPLEX_FULL)
vars->link_status |= LINK_1000TFD;
else
@@ -2525,7 +5187,7 @@
break;
case GP_STATUS_2_5G:
- new_line_speed = SPEED_2500;
+ vars->line_speed = SPEED_2500;
if (vars->duplex == DUPLEX_FULL)
vars->link_status |= LINK_2500TFD;
else
@@ -2536,50 +5198,28 @@
case GP_STATUS_6G:
DP(NETIF_MSG_LINK,
"link speed unsupported gp_status 0x%x\n",
- gp_status);
+ speed_mask);
return -EINVAL;
case GP_STATUS_10G_KX4:
case GP_STATUS_10G_HIG:
case GP_STATUS_10G_CX4:
- new_line_speed = SPEED_10000;
+ case GP_STATUS_10G_KR:
+ case GP_STATUS_10G_SFI:
+ case GP_STATUS_10G_XFI:
+ vars->line_speed = SPEED_10000;
vars->link_status |= LINK_10GTFD;
break;
-
- case GP_STATUS_12G_HIG:
- new_line_speed = SPEED_12000;
- vars->link_status |= LINK_12GTFD;
+ case GP_STATUS_20G_DXGXS:
+ vars->line_speed = SPEED_20000;
+ vars->link_status |= LINK_20GTFD;
break;
-
- case GP_STATUS_12_5G:
- new_line_speed = SPEED_12500;
- vars->link_status |= LINK_12_5GTFD;
- break;
-
- case GP_STATUS_13G:
- new_line_speed = SPEED_13000;
- vars->link_status |= LINK_13GTFD;
- break;
-
- case GP_STATUS_15G:
- new_line_speed = SPEED_15000;
- vars->link_status |= LINK_15GTFD;
- break;
-
- case GP_STATUS_16G:
- new_line_speed = SPEED_16000;
- vars->link_status |= LINK_16GTFD;
- break;
-
default:
DP(NETIF_MSG_LINK,
"link speed unsupported gp_status 0x%x\n",
- gp_status);
+ speed_mask);
return -EINVAL;
}
-
- vars->line_speed = new_line_speed;
-
} else { /* link_down */
DP(NETIF_MSG_LINK, "phy link down\n");
@@ -2588,7 +5228,47 @@
vars->duplex = DUPLEX_FULL;
vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
vars->mac_type = MAC_TYPE_NONE;
+ }
+ DP(NETIF_MSG_LINK, " phy_link_up %x line_speed %d\n",
+ vars->phy_link_up, vars->line_speed);
+ return 0;
+}
+static int bnx2x_link_settings_status(struct bnx2x_phy *phy,
+ struct link_params *params,
+ struct link_vars *vars)
+{
+
+ struct bnx2x *bp = params->bp;
+
+ u16 gp_status, duplex = DUPLEX_HALF, link_up = 0, speed_mask;
+ int rc = 0;
+
+ /* Read gp_status */
+ CL22_RD_OVER_CL45(bp, phy,
+ MDIO_REG_BANK_GP_STATUS,
+ MDIO_GP_STATUS_TOP_AN_STATUS1,
+ &gp_status);
+ if (gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_DUPLEX_STATUS)
+ duplex = DUPLEX_FULL;
+ if (gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_LINK_STATUS)
+ link_up = 1;
+ speed_mask = gp_status & GP_STATUS_SPEED_MASK;
+ DP(NETIF_MSG_LINK, "gp_status 0x%x, is_link_up %d, speed_mask 0x%x\n",
+ gp_status, link_up, speed_mask);
+ rc = bnx2x_get_link_speed_duplex(phy, params, vars, link_up, speed_mask,
+ duplex);
+ if (rc == -EINVAL)
+ return rc;
+
+ if (gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_LINK_STATUS) {
+ if (SINGLE_MEDIA_DIRECT(params)) {
+ bnx2x_flow_ctrl_resolve(phy, params, vars, gp_status);
+ if (phy->req_line_speed == SPEED_AUTO_NEG)
+ bnx2x_xgxs_an_resolve(phy, params, vars,
+ gp_status);
+ }
+ } else { /* link_down */
if ((phy->req_line_speed == SPEED_AUTO_NEG) &&
SINGLE_MEDIA_DIRECT(params)) {
/* Check signal is detected */
@@ -2596,13 +5276,86 @@
}
}
- DP(NETIF_MSG_LINK, "gp_status 0x%x phy_link_up %x line_speed %x\n",
- gp_status, vars->phy_link_up, vars->line_speed);
DP(NETIF_MSG_LINK, "duplex %x flow_ctrl 0x%x link_status 0x%x\n",
vars->duplex, vars->flow_ctrl, vars->link_status);
return rc;
}
+static int bnx2x_warpcore_read_status(struct bnx2x_phy *phy,
+ struct link_params *params,
+ struct link_vars *vars)
+{
+
+ struct bnx2x *bp = params->bp;
+
+ u8 lane;
+ u16 gp_status1, gp_speed, link_up, duplex = DUPLEX_FULL;
+ int rc = 0;
+ lane = bnx2x_get_warpcore_lane(phy, params);
+ /* Read gp_status */
+ if (phy->req_line_speed > SPEED_10000) {
+ u16 temp_link_up;
+ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+ 1, &temp_link_up);
+ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+ 1, &link_up);
+ DP(NETIF_MSG_LINK, "PCS RX link status = 0x%x-->0x%x\n",
+ temp_link_up, link_up);
+ link_up &= (1<<2);
+ if (link_up)
+ bnx2x_ext_phy_resolve_fc(phy, params, vars);
+ } else {
+ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_GP2_STATUS_GP_2_1, &gp_status1);
+ DP(NETIF_MSG_LINK, "0x81d1 = 0x%x\n", gp_status1);
+ /* Check for either KR or generic link up. */
+ gp_status1 = ((gp_status1 >> 8) & 0xf) |
+ ((gp_status1 >> 12) & 0xf);
+ link_up = gp_status1 & (1 << lane);
+ if (link_up && SINGLE_MEDIA_DIRECT(params)) {
+ u16 pd, gp_status4;
+ if (phy->req_line_speed == SPEED_AUTO_NEG) {
+ /* Check Autoneg complete */
+ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_GP2_STATUS_GP_2_4,
+ &gp_status4);
+ if (gp_status4 & ((1<<12)<<lane))
+ vars->link_status |=
+ LINK_STATUS_AUTO_NEGOTIATE_COMPLETE;
+
+ /* Check parallel detect used */
+ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_PAR_DET_10G_STATUS,
+ &pd);
+ if (pd & (1<<15))
+ vars->link_status |=
+ LINK_STATUS_PARALLEL_DETECTION_USED;
+ }
+ bnx2x_ext_phy_resolve_fc(phy, params, vars);
+ }
+ }
+
+ if (lane < 2) {
+ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_GP2_STATUS_GP_2_2, &gp_speed);
+ } else {
+ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_GP2_STATUS_GP_2_3, &gp_speed);
+ }
+ DP(NETIF_MSG_LINK, "lane %d gp_speed 0x%x\n", lane, gp_speed);
+
+ if ((lane & 1) == 0)
+ gp_speed <<= 8;
+ gp_speed &= 0x3f00;
+
+
+ rc = bnx2x_get_link_speed_duplex(phy, params, vars, link_up, gp_speed,
+ duplex);
+
+ DP(NETIF_MSG_LINK, "duplex %x flow_ctrl 0x%x link_status 0x%x\n",
+ vars->duplex, vars->flow_ctrl, vars->link_status);
+ return rc;
+}
static void bnx2x_set_gmii_tx_driver(struct link_params *params)
{
struct bnx2x *bp = params->bp;
@@ -2642,8 +5395,8 @@
}
}
-static u8 bnx2x_emac_program(struct link_params *params,
- struct link_vars *vars)
+static int bnx2x_emac_program(struct link_params *params,
+ struct link_vars *vars)
{
struct bnx2x *bp = params->bp;
u8 port = params->port;
@@ -2713,9 +5466,9 @@
}
}
-static void bnx2x_init_internal_phy(struct bnx2x_phy *phy,
- struct link_params *params,
- struct link_vars *vars)
+static void bnx2x_xgxs_config_init(struct bnx2x_phy *phy,
+ struct link_params *params,
+ struct link_vars *vars)
{
struct bnx2x *bp = params->bp;
u8 enable_cl73 = (SINGLE_MEDIA_DIRECT(params) ||
@@ -2742,11 +5495,11 @@
DP(NETIF_MSG_LINK, "not SGMII, AN\n");
/* AN enabled */
- bnx2x_set_brcm_cl37_advertisment(phy, params);
+ bnx2x_set_brcm_cl37_advertisement(phy, params);
/* program duplex & pause advertisement (for aneg) */
- bnx2x_set_ieee_aneg_advertisment(phy, params,
- vars->ieee_fc);
+ bnx2x_set_ieee_aneg_advertisement(phy, params,
+ vars->ieee_fc);
/* enable autoneg */
bnx2x_set_autoneg(phy, params, vars, enable_cl73);
@@ -2762,29 +5515,12 @@
}
}
-static u8 bnx2x_init_serdes(struct bnx2x_phy *phy,
- struct link_params *params,
- struct link_vars *vars)
-{
- u8 rc;
- vars->phy_flags |= PHY_SGMII_FLAG;
- bnx2x_calc_ieee_aneg_adv(phy, params, &vars->ieee_fc);
- bnx2x_set_aer_mmd_serdes(params->bp, phy);
- rc = bnx2x_reset_unicore(params, phy, 1);
- /* reset the SerDes and wait for reset bit return low */
- if (rc != 0)
- return rc;
- bnx2x_set_aer_mmd_serdes(params->bp, phy);
-
- return rc;
-}
-
-static u8 bnx2x_init_xgxs(struct bnx2x_phy *phy,
+static int bnx2x_prepare_xgxs(struct bnx2x_phy *phy,
struct link_params *params,
struct link_vars *vars)
{
- u8 rc;
- vars->phy_flags = PHY_XGXS_FLAG;
+ int rc;
+ vars->phy_flags |= PHY_XGXS_FLAG;
if ((phy->req_line_speed &&
((phy->req_line_speed == SPEED_100) ||
(phy->req_line_speed == SPEED_10))) ||
@@ -2792,26 +5528,28 @@
(phy->speed_cap_mask >=
PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_FULL) &&
(phy->speed_cap_mask <
- PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)
- ))
+ PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)) ||
+ (phy->type == PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT_SD))
vars->phy_flags |= PHY_SGMII_FLAG;
else
vars->phy_flags &= ~PHY_SGMII_FLAG;
bnx2x_calc_ieee_aneg_adv(phy, params, &vars->ieee_fc);
- bnx2x_set_aer_mmd_xgxs(params, phy);
- bnx2x_set_master_ln(params, phy);
+ bnx2x_set_aer_mmd(params, phy);
+ if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT)
+ bnx2x_set_master_ln(params, phy);
rc = bnx2x_reset_unicore(params, phy, 0);
/* reset the SerDes and wait for reset bit return low */
if (rc != 0)
return rc;
- bnx2x_set_aer_mmd_xgxs(params, phy);
-
+ bnx2x_set_aer_mmd(params, phy);
/* setting the masterLn_def again after the reset */
- bnx2x_set_master_ln(params, phy);
- bnx2x_set_swap_lanes(params, phy);
+ if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) {
+ bnx2x_set_master_ln(params, phy);
+ bnx2x_set_swap_lanes(params, phy);
+ }
return rc;
}
@@ -2823,8 +5561,13 @@
u16 cnt, ctrl;
/* Wait for soft reset to get cleared up to 1 sec */
for (cnt = 0; cnt < 1000; cnt++) {
- bnx2x_cl45_read(bp, phy,
- MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, &ctrl);
+ if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM54618SE)
+ bnx2x_cl22_read(bp, phy,
+ MDIO_PMA_REG_CTRL, &ctrl);
+ else
+ bnx2x_cl45_read(bp, phy,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_CTRL, &ctrl);
if (!(ctrl & (1<<15)))
break;
msleep(1);
@@ -2845,7 +5588,11 @@
struct bnx2x *bp = params->bp;
/* Setting the status to report on link up for either XGXS or SerDes */
- if (params->switch_cfg == SWITCH_CFG_10G) {
+ if (CHIP_IS_E3(bp)) {
+ mask = NIG_MASK_XGXS0_LINK_STATUS;
+ if (!(SINGLE_MEDIA_DIRECT(params)))
+ mask |= NIG_MASK_MI_INT;
+ } else if (params->switch_cfg == SWITCH_CFG_10G) {
mask = (NIG_MASK_XGXS0_LINK10G |
NIG_MASK_XGXS0_LINK_STATUS);
DP(NETIF_MSG_LINK, "enabled XGXS interrupt\n");
@@ -2918,11 +5665,11 @@
}
static void bnx2x_link_int_ack(struct link_params *params,
- struct link_vars *vars, u8 is_10g)
+ struct link_vars *vars, u8 is_10g_plus)
{
struct bnx2x *bp = params->bp;
u8 port = params->port;
-
+ u32 mask;
/*
* First reset all status we assume only one line will be
* change at a time
@@ -2932,47 +5679,34 @@
NIG_STATUS_XGXS0_LINK_STATUS |
NIG_STATUS_SERDES0_LINK_STATUS));
if (vars->phy_link_up) {
- if (is_10g) {
- /*
- * Disable the 10G link interrupt by writing 1 to the
- * status register
- */
- DP(NETIF_MSG_LINK, "10G XGXS phy link up\n");
- bnx2x_bits_en(bp,
- NIG_REG_STATUS_INTERRUPT_PORT0 + port*4,
- NIG_STATUS_XGXS0_LINK10G);
-
- } else if (params->switch_cfg == SWITCH_CFG_10G) {
- /*
- * Disable the link interrupt by writing 1 to the
- * relevant lane in the status register
- */
- u32 ser_lane = ((params->lane_config &
+ if (USES_WARPCORE(bp))
+ mask = NIG_STATUS_XGXS0_LINK_STATUS;
+ else {
+ if (is_10g_plus)
+ mask = NIG_STATUS_XGXS0_LINK10G;
+ else if (params->switch_cfg == SWITCH_CFG_10G) {
+ /*
+ * Disable the link interrupt by writing 1 to
+ * the relevant lane in the status register
+ */
+ u32 ser_lane =
+ ((params->lane_config &
PORT_HW_CFG_LANE_SWAP_CFG_MASTER_MASK) >>
PORT_HW_CFG_LANE_SWAP_CFG_MASTER_SHIFT);
-
- DP(NETIF_MSG_LINK, "%d speed XGXS phy link up\n",
- vars->line_speed);
- bnx2x_bits_en(bp,
- NIG_REG_STATUS_INTERRUPT_PORT0 + port*4,
- ((1 << ser_lane) <<
- NIG_STATUS_XGXS0_LINK_STATUS_SIZE));
-
- } else { /* SerDes */
- DP(NETIF_MSG_LINK, "SerDes phy link up\n");
- /*
- * Disable the link interrupt by writing 1 to the status
- * register
- */
- bnx2x_bits_en(bp,
- NIG_REG_STATUS_INTERRUPT_PORT0 + port*4,
- NIG_STATUS_SERDES0_LINK_STATUS);
+ mask = ((1 << ser_lane) <<
+ NIG_STATUS_XGXS0_LINK_STATUS_SIZE);
+ } else
+ mask = NIG_STATUS_SERDES0_LINK_STATUS;
}
-
+ DP(NETIF_MSG_LINK, "Ack link up interrupt with mask 0x%x\n",
+ mask);
+ bnx2x_bits_en(bp,
+ NIG_REG_STATUS_INTERRUPT_PORT0 + port*4,
+ mask);
}
}
-static u8 bnx2x_format_ver(u32 num, u8 *str, u16 *len)
+static int bnx2x_format_ver(u32 num, u8 *str, u16 *len)
{
u8 *str_ptr = str;
u32 mask = 0xf0000000;
@@ -3011,19 +5745,19 @@
}
-static u8 bnx2x_null_format_ver(u32 spirom_ver, u8 *str, u16 *len)
+static int bnx2x_null_format_ver(u32 spirom_ver, u8 *str, u16 *len)
{
str[0] = '\0';
(*len)--;
return 0;
}
-u8 bnx2x_get_ext_phy_fw_version(struct link_params *params, u8 driver_loaded,
- u8 *version, u16 len)
+int bnx2x_get_ext_phy_fw_version(struct link_params *params, u8 driver_loaded,
+ u8 *version, u16 len)
{
struct bnx2x *bp;
u32 spirom_ver = 0;
- u8 status = 0;
+ int status = 0;
u8 *ver_p = version;
u16 remain_len = len;
if (version == NULL || params == NULL)
@@ -3065,15 +5799,18 @@
struct bnx2x *bp = params->bp;
if (phy->req_line_speed != SPEED_1000) {
- u32 md_devad;
+ u32 md_devad = 0;
DP(NETIF_MSG_LINK, "XGXS 10G loopback enable\n");
- /* change the uni_phy_addr in the nig */
- md_devad = REG_RD(bp, (NIG_REG_XGXS0_CTRL_MD_DEVAD +
- port*0x18));
+ if (!CHIP_IS_E3(bp)) {
+ /* change the uni_phy_addr in the nig */
+ md_devad = REG_RD(bp, (NIG_REG_XGXS0_CTRL_MD_DEVAD +
+ port*0x18));
- REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_DEVAD + port*0x18, 0x5);
+ REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_DEVAD + port*0x18,
+ 0x5);
+ }
bnx2x_cl45_write(bp, phy,
5,
@@ -3088,10 +5825,13 @@
0x6041);
msleep(200);
/* set aer mmd back */
- bnx2x_set_aer_mmd_xgxs(params, phy);
+ bnx2x_set_aer_mmd(params, phy);
- /* and md_devad */
- REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_DEVAD + port*0x18, md_devad);
+ if (!CHIP_IS_E3(bp)) {
+ /* and md_devad */
+ REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_DEVAD + port*0x18,
+ md_devad);
+ }
} else {
u16 mii_ctrl;
DP(NETIF_MSG_LINK, "XGXS 1G loopback enable\n");
@@ -3107,12 +5847,13 @@
}
}
-u8 bnx2x_set_led(struct link_params *params,
- struct link_vars *vars, u8 mode, u32 speed)
+int bnx2x_set_led(struct link_params *params,
+ struct link_vars *vars, u8 mode, u32 speed)
{
u8 port = params->port;
u16 hw_led_mode = params->hw_led_mode;
- u8 rc = 0, phy_idx;
+ int rc = 0;
+ u8 phy_idx;
u32 tmp;
u32 emac_base = port ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
struct bnx2x *bp = params->bp;
@@ -3146,8 +5887,10 @@
if (!vars->link_up)
break;
case LED_MODE_ON:
- if (params->phy[EXT_PHY1].type ==
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727 &&
+ if (((params->phy[EXT_PHY1].type ==
+ PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727) ||
+ (params->phy[EXT_PHY1].type ==
+ PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8722)) &&
CHIP_IS_E2(bp) && params->num_phys == 2) {
/*
* This is a work-around for E2+8727 Configurations
@@ -3162,7 +5905,9 @@
(tmp | EMAC_LED_OVERRIDE));
return rc;
}
- } else if (SINGLE_MEDIA_DIRECT(params)) {
+ } else if (SINGLE_MEDIA_DIRECT(params) &&
+ (CHIP_IS_E1x(bp) ||
+ CHIP_IS_E2(bp))) {
/*
* This is a work-around for HW issue found when link
* is up in CL73
@@ -3214,21 +5959,49 @@
* This function comes to reflect the actual link state read DIRECTLY from the
* HW
*/
-u8 bnx2x_test_link(struct link_params *params, struct link_vars *vars,
- u8 is_serdes)
+int bnx2x_test_link(struct link_params *params, struct link_vars *vars,
+ u8 is_serdes)
{
struct bnx2x *bp = params->bp;
u16 gp_status = 0, phy_index = 0;
u8 ext_phy_link_up = 0, serdes_phy_type;
struct link_vars temp_vars;
+ struct bnx2x_phy *int_phy = ¶ms->phy[INT_PHY];
- CL22_RD_OVER_CL45(bp, ¶ms->phy[INT_PHY],
+ if (CHIP_IS_E3(bp)) {
+ u16 link_up;
+ if (params->req_line_speed[LINK_CONFIG_IDX(INT_PHY)]
+ > SPEED_10000) {
+ /* Check 20G link */
+ bnx2x_cl45_read(bp, int_phy, MDIO_WC_DEVAD,
+ 1, &link_up);
+ bnx2x_cl45_read(bp, int_phy, MDIO_WC_DEVAD,
+ 1, &link_up);
+ link_up &= (1<<2);
+ } else {
+ /* Check 10G link and below*/
+ u8 lane = bnx2x_get_warpcore_lane(int_phy, params);
+ bnx2x_cl45_read(bp, int_phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_GP2_STATUS_GP_2_1,
+ &gp_status);
+ gp_status = ((gp_status >> 8) & 0xf) |
+ ((gp_status >> 12) & 0xf);
+ link_up = gp_status & (1 << lane);
+ }
+ if (!link_up)
+ return -ESRCH;
+ } else {
+ CL22_RD_OVER_CL45(bp, int_phy,
MDIO_REG_BANK_GP_STATUS,
MDIO_GP_STATUS_TOP_AN_STATUS1,
&gp_status);
/* link is up only if both local phy and external phy are up */
if (!(gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_LINK_STATUS))
return -ESRCH;
+ }
+ /* In XGXS loopback mode, do not check external PHY */
+ if (params->loopback_mode == LOOPBACK_XGXS)
+ return 0;
switch (params->num_phys) {
case 1:
@@ -3245,7 +6018,9 @@
serdes_phy_type = ((params->phy[phy_index].media_type ==
ETH_PHY_SFP_FIBER) ||
(params->phy[phy_index].media_type ==
- ETH_PHY_XFP_FIBER));
+ ETH_PHY_XFP_FIBER) ||
+ (params->phy[phy_index].media_type ==
+ ETH_PHY_DA_TWINAX));
if (is_serdes != serdes_phy_type)
continue;
@@ -3263,10 +6038,10 @@
return -ESRCH;
}
-static u8 bnx2x_link_initialize(struct link_params *params,
- struct link_vars *vars)
+static int bnx2x_link_initialize(struct link_params *params,
+ struct link_vars *vars)
{
- u8 rc = 0;
+ int rc = 0;
u8 phy_index, non_ext_phy;
struct bnx2x *bp = params->bp;
/*
@@ -3282,12 +6057,8 @@
* (no external phys), or this board has external phy which requires
* to first.
*/
-
- if (params->phy[INT_PHY].config_init)
- params->phy[INT_PHY].config_init(
- ¶ms->phy[INT_PHY],
- params, vars);
-
+ if (!USES_WARPCORE(bp))
+ bnx2x_prepare_xgxs(¶ms->phy[INT_PHY], params, vars);
/* init ext phy and enable link state int */
non_ext_phy = (SINGLE_MEDIA_DIRECT(params) ||
(params->loopback_mode == LOOPBACK_XGXS));
@@ -3296,13 +6067,22 @@
(params->phy[EXT_PHY1].flags & FLAGS_INIT_XGXS_FIRST) ||
(params->loopback_mode == LOOPBACK_EXT_PHY)) {
struct bnx2x_phy *phy = ¶ms->phy[INT_PHY];
- if (vars->line_speed == SPEED_AUTO_NEG)
+ if (vars->line_speed == SPEED_AUTO_NEG &&
+ (CHIP_IS_E1x(bp) ||
+ CHIP_IS_E2(bp)))
bnx2x_set_parallel_detection(phy, params);
- bnx2x_init_internal_phy(phy, params, vars);
+ if (params->phy[INT_PHY].config_init)
+ params->phy[INT_PHY].config_init(phy,
+ params,
+ vars);
}
/* Init external phy*/
- if (!non_ext_phy)
+ if (non_ext_phy) {
+ if (params->phy[INT_PHY].supported &
+ SUPPORTED_FIBRE)
+ vars->link_status |= LINK_STATUS_SERDES_LINK;
+ } else {
for (phy_index = EXT_PHY1; phy_index < params->num_phys;
phy_index++) {
/*
@@ -3311,17 +6091,22 @@
* need to initialize the first phy, since they are
* connected.
*/
+ if (params->phy[phy_index].supported &
+ SUPPORTED_FIBRE)
+ vars->link_status |= LINK_STATUS_SERDES_LINK;
+
if (phy_index == EXT_PHY2 &&
(bnx2x_phy_selection(params) ==
PORT_HW_CFG_PHY_SELECTION_FIRST_PHY)) {
- DP(NETIF_MSG_LINK, "Ignoring second phy\n");
+ DP(NETIF_MSG_LINK, "Not initializing"
+ " second phy\n");
continue;
}
params->phy[phy_index].config_init(
¶ms->phy[phy_index],
params, vars);
}
-
+ }
/* Reset the interrupt indication after phy was initialized */
bnx2x_bits_dis(bp, NIG_REG_STATUS_INTERRUPT_PORT0 +
params->port*4,
@@ -3329,6 +6114,7 @@
NIG_STATUS_XGXS0_LINK_STATUS |
NIG_STATUS_SERDES0_LINK_STATUS |
NIG_MASK_MI_INT));
+ bnx2x_update_mng(params, vars->link_status);
return rc;
}
@@ -3359,20 +6145,25 @@
DP(NETIF_MSG_LINK, "reset external PHY\n");
}
-static u8 bnx2x_update_link_down(struct link_params *params,
- struct link_vars *vars)
+static int bnx2x_update_link_down(struct link_params *params,
+ struct link_vars *vars)
{
struct bnx2x *bp = params->bp;
u8 port = params->port;
DP(NETIF_MSG_LINK, "Port %x: Link is down\n", port);
bnx2x_set_led(params, vars, LED_MODE_OFF, 0);
-
+ vars->phy_flags &= ~PHY_PHYSICAL_LINK_FLAG;
/* indicate no mac active */
vars->mac_type = MAC_TYPE_NONE;
/* update shared memory */
- vars->link_status = 0;
+ vars->link_status &= ~(LINK_STATUS_SPEED_AND_DUPLEX_MASK |
+ LINK_STATUS_LINK_UP |
+ LINK_STATUS_AUTO_NEGOTIATE_COMPLETE |
+ LINK_STATUS_RX_FLOW_CONTROL_FLAG_MASK |
+ LINK_STATUS_TX_FLOW_CONTROL_FLAG_MASK |
+ LINK_STATUS_PARALLEL_DETECTION_FLAG_MASK);
vars->line_speed = 0;
bnx2x_update_mng(params, vars->link_status);
@@ -3380,26 +6171,34 @@
REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + port*4, 1);
/* disable emac */
- REG_WR(bp, NIG_REG_NIG_EMAC0_EN + port*4, 0);
+ if (!CHIP_IS_E3(bp))
+ REG_WR(bp, NIG_REG_NIG_EMAC0_EN + port*4, 0);
msleep(10);
-
- /* reset BigMac */
- bnx2x_bmac_rx_disable(bp, params->port);
- REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR,
+ /* reset BigMac/Xmac */
+ if (CHIP_IS_E1x(bp) ||
+ CHIP_IS_E2(bp)) {
+ bnx2x_bmac_rx_disable(bp, params->port);
+ REG_WR(bp, GRCBASE_MISC +
+ MISC_REGISTERS_RESET_REG_2_CLEAR,
(MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port));
+ }
+ if (CHIP_IS_E3(bp))
+ bnx2x_xmac_disable(params);
+
return 0;
}
-static u8 bnx2x_update_link_up(struct link_params *params,
- struct link_vars *vars,
- u8 link_10g)
+static int bnx2x_update_link_up(struct link_params *params,
+ struct link_vars *vars,
+ u8 link_10g)
{
struct bnx2x *bp = params->bp;
u8 port = params->port;
- u8 rc = 0;
+ int rc = 0;
vars->link_status |= LINK_STATUS_LINK_UP;
+ vars->phy_flags |= PHY_PHYSICAL_LINK_FLAG;
if (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX)
vars->link_status |=
@@ -3408,25 +6207,48 @@
if (vars->flow_ctrl & BNX2X_FLOW_CTRL_RX)
vars->link_status |=
LINK_STATUS_RX_FLOW_CONTROL_ENABLED;
-
- if (link_10g) {
- bnx2x_bmac_enable(params, vars, 0);
+ if (USES_WARPCORE(bp)) {
+ if (link_10g) {
+ if (bnx2x_xmac_enable(params, vars, 0) ==
+ -ESRCH) {
+ DP(NETIF_MSG_LINK, "Found errors on XMAC\n");
+ vars->link_up = 0;
+ vars->phy_flags |= PHY_HALF_OPEN_CONN_FLAG;
+ vars->link_status &= ~LINK_STATUS_LINK_UP;
+ }
+ } else
+ bnx2x_umac_enable(params, vars, 0);
bnx2x_set_led(params, vars,
- LED_MODE_OPER, SPEED_10000);
- } else {
- rc = bnx2x_emac_program(params, vars);
+ LED_MODE_OPER, vars->line_speed);
+ }
+ if ((CHIP_IS_E1x(bp) ||
+ CHIP_IS_E2(bp))) {
+ if (link_10g) {
+ if (bnx2x_bmac_enable(params, vars, 0) ==
+ -ESRCH) {
+ DP(NETIF_MSG_LINK, "Found errors on BMAC\n");
+ vars->link_up = 0;
+ vars->phy_flags |= PHY_HALF_OPEN_CONN_FLAG;
+ vars->link_status &= ~LINK_STATUS_LINK_UP;
+ }
- bnx2x_emac_enable(params, vars, 0);
+ bnx2x_set_led(params, vars,
+ LED_MODE_OPER, SPEED_10000);
+ } else {
+ rc = bnx2x_emac_program(params, vars);
+ bnx2x_emac_enable(params, vars, 0);
- /* AN complete? */
- if ((vars->link_status & LINK_STATUS_AUTO_NEGOTIATE_COMPLETE)
- && (!(vars->phy_flags & PHY_SGMII_FLAG)) &&
- SINGLE_MEDIA_DIRECT(params))
- bnx2x_set_gmii_tx_driver(params);
+ /* AN complete? */
+ if ((vars->link_status &
+ LINK_STATUS_AUTO_NEGOTIATE_COMPLETE)
+ && (!(vars->phy_flags & PHY_SGMII_FLAG)) &&
+ SINGLE_MEDIA_DIRECT(params))
+ bnx2x_set_gmii_tx_driver(params);
+ }
}
/* PBF - link up */
- if (!(CHIP_IS_E2(bp)))
+ if (CHIP_IS_E1x(bp))
rc |= bnx2x_pbf_update(params, vars->flow_ctrl,
vars->line_speed);
@@ -3451,17 +6273,18 @@
* external phy needs to be up, and at least one of the 2
* external phy link must be up.
*/
-u8 bnx2x_link_update(struct link_params *params, struct link_vars *vars)
+int bnx2x_link_update(struct link_params *params, struct link_vars *vars)
{
struct bnx2x *bp = params->bp;
struct link_vars phy_vars[MAX_PHYS];
u8 port = params->port;
- u8 link_10g, phy_index;
- u8 ext_phy_link_up = 0, cur_link_up, rc = 0;
+ u8 link_10g_plus, phy_index;
+ u8 ext_phy_link_up = 0, cur_link_up;
+ int rc = 0;
u8 is_mi_int = 0;
u16 ext_phy_line_speed = 0, prev_line_speed = vars->line_speed;
u8 active_external_phy = INT_PHY;
- vars->link_status = 0;
+ vars->phy_flags &= ~PHY_HALF_OPEN_CONN_FLAG;
for (phy_index = INT_PHY; phy_index < params->num_phys;
phy_index++) {
phy_vars[phy_index].flow_ctrl = 0;
@@ -3470,8 +6293,12 @@
phy_vars[phy_index].duplex = DUPLEX_FULL;
phy_vars[phy_index].phy_link_up = 0;
phy_vars[phy_index].link_up = 0;
+ phy_vars[phy_index].fault_detected = 0;
}
+ if (USES_WARPCORE(bp))
+ bnx2x_set_aer_mmd(params, ¶ms->phy[INT_PHY]);
+
DP(NETIF_MSG_LINK, "port %x, XGXS?%x, int_status 0x%x\n",
port, (vars->phy_flags & PHY_XGXS_FLAG),
REG_RD(bp, NIG_REG_STATUS_INTERRUPT_PORT0 + port*4));
@@ -3488,13 +6315,14 @@
REG_RD(bp, NIG_REG_XGXS0_STATUS_LINK_STATUS + port*0x68));
/* disable emac */
- REG_WR(bp, NIG_REG_NIG_EMAC0_EN + port*4, 0);
+ if (!CHIP_IS_E3(bp))
+ REG_WR(bp, NIG_REG_NIG_EMAC0_EN + port*4, 0);
/*
* Step 1:
* Check external link change only for external phys, and apply
* priority selection between them in case the link on both phys
- * is up. Note that the instead of the common vars, a temporary
+ * is up. Note that instead of the common vars, a temporary
* vars argument is used since each phy may have different link/
* speed/duplex result
*/
@@ -3601,6 +6429,8 @@
if (params->phy[active_external_phy].supported &
SUPPORTED_FIBRE)
vars->link_status |= LINK_STATUS_SERDES_LINK;
+ else
+ vars->link_status &= ~LINK_STATUS_SERDES_LINK;
DP(NETIF_MSG_LINK, "Active external phy selected: %x\n",
active_external_phy);
}
@@ -3640,14 +6470,9 @@
}
/* anything 10 and over uses the bmac */
- link_10g = ((vars->line_speed == SPEED_10000) ||
- (vars->line_speed == SPEED_12000) ||
- (vars->line_speed == SPEED_12500) ||
- (vars->line_speed == SPEED_13000) ||
- (vars->line_speed == SPEED_15000) ||
- (vars->line_speed == SPEED_16000));
+ link_10g_plus = (vars->line_speed >= SPEED_10000);
- bnx2x_link_int_ack(params, vars, link_10g);
+ bnx2x_link_int_ack(params, vars, link_10g_plus);
/*
* In case external phy link is up, and internal link is down
@@ -3671,21 +6496,24 @@
vars->phy_flags |= PHY_SGMII_FLAG;
else
vars->phy_flags &= ~PHY_SGMII_FLAG;
- bnx2x_init_internal_phy(¶ms->phy[INT_PHY],
- params,
+
+ if (params->phy[INT_PHY].config_init)
+ params->phy[INT_PHY].config_init(
+ ¶ms->phy[INT_PHY], params,
vars);
}
}
/*
* Link is up only if both local phy and external phy (in case of
- * non-direct board) are up
+ * non-direct board) are up and no fault detected on active PHY.
*/
vars->link_up = (vars->phy_link_up &&
(ext_phy_link_up ||
- SINGLE_MEDIA_DIRECT(params)));
+ SINGLE_MEDIA_DIRECT(params)) &&
+ (phy_vars[active_external_phy].fault_detected == 0));
if (vars->link_up)
- rc = bnx2x_update_link_up(params, vars, link_10g);
+ rc = bnx2x_update_link_up(params, vars, link_10g_plus);
else
rc = bnx2x_update_link_down(params, vars);
@@ -3729,69 +6557,6 @@
phy->ver_addr);
}
-static void bnx2x_ext_phy_set_pause(struct link_params *params,
- struct bnx2x_phy *phy,
- struct link_vars *vars)
-{
- u16 val;
- struct bnx2x *bp = params->bp;
- /* read modify write pause advertizing */
- bnx2x_cl45_read(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_ADV_PAUSE, &val);
-
- val &= ~MDIO_AN_REG_ADV_PAUSE_BOTH;
-
- /* Please refer to Table 28B-3 of 802.3ab-1999 spec. */
- bnx2x_calc_ieee_aneg_adv(phy, params, &vars->ieee_fc);
- if ((vars->ieee_fc &
- MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) ==
- MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) {
- val |= MDIO_AN_REG_ADV_PAUSE_ASYMMETRIC;
- }
- if ((vars->ieee_fc &
- MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) ==
- MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) {
- val |= MDIO_AN_REG_ADV_PAUSE_PAUSE;
- }
- DP(NETIF_MSG_LINK, "Ext phy AN advertize 0x%x\n", val);
- bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_ADV_PAUSE, val);
-}
-
-static u8 bnx2x_ext_phy_resolve_fc(struct bnx2x_phy *phy,
- struct link_params *params,
- struct link_vars *vars)
-{
- struct bnx2x *bp = params->bp;
- u16 ld_pause; /* local */
- u16 lp_pause; /* link partner */
- u16 pause_result;
- u8 ret = 0;
- /* read twice */
-
- vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
-
- if (phy->req_flow_ctrl != BNX2X_FLOW_CTRL_AUTO)
- vars->flow_ctrl = phy->req_flow_ctrl;
- else if (phy->req_line_speed != SPEED_AUTO_NEG)
- vars->flow_ctrl = params->req_fc_auto_adv;
- else if (vars->link_status & LINK_STATUS_AUTO_NEGOTIATE_COMPLETE) {
- ret = 1;
- bnx2x_cl45_read(bp, phy,
- MDIO_AN_DEVAD,
- MDIO_AN_REG_ADV_PAUSE, &ld_pause);
- bnx2x_cl45_read(bp, phy,
- MDIO_AN_DEVAD,
- MDIO_AN_REG_LP_AUTO_NEG, &lp_pause);
- pause_result = (ld_pause &
- MDIO_AN_REG_ADV_PAUSE_MASK) >> 8;
- pause_result |= (lp_pause &
- MDIO_AN_REG_ADV_PAUSE_MASK) >> 10;
- DP(NETIF_MSG_LINK, "Ext PHY pause result 0x%x\n",
- pause_result);
- bnx2x_pause_resolve(vars, pause_result);
- }
- return ret;
-}
-
static void bnx2x_ext_phy_10G_an_resolve(struct bnx2x *bp,
struct bnx2x_phy *phy,
struct link_vars *vars)
@@ -3845,13 +6610,13 @@
pause_result);
}
}
-static u8 bnx2x_8073_8727_external_rom_boot(struct bnx2x *bp,
- struct bnx2x_phy *phy,
- u8 port)
+static int bnx2x_8073_8727_external_rom_boot(struct bnx2x *bp,
+ struct bnx2x_phy *phy,
+ u8 port)
{
u32 count = 0;
u16 fw_ver1, fw_msgout;
- u8 rc = 0;
+ int rc = 0;
/* Boot port from external ROM */
/* EDC grst */
@@ -3926,7 +6691,7 @@
/******************************************************************/
/* BCM8073 PHY SECTION */
/******************************************************************/
-static u8 bnx2x_8073_is_snr_needed(struct bnx2x *bp, struct bnx2x_phy *phy)
+static int bnx2x_8073_is_snr_needed(struct bnx2x *bp, struct bnx2x_phy *phy)
{
/* This is only required for 8073A1, version 102 only */
u16 val;
@@ -3952,7 +6717,7 @@
return 1;
}
-static u8 bnx2x_8073_xaui_wa(struct bnx2x *bp, struct bnx2x_phy *phy)
+static int bnx2x_8073_xaui_wa(struct bnx2x *bp, struct bnx2x_phy *phy)
{
u16 val, cnt, cnt1 ;
@@ -4059,9 +6824,9 @@
msleep(500);
}
-static u8 bnx2x_8073_config_init(struct bnx2x_phy *phy,
- struct link_params *params,
- struct link_vars *vars)
+static int bnx2x_8073_config_init(struct bnx2x_phy *phy,
+ struct link_params *params,
+ struct link_vars *vars)
{
struct bnx2x *bp = params->bp;
u16 val = 0, tmp1;
@@ -4081,9 +6846,9 @@
/* enable LASI */
bnx2x_cl45_write(bp, phy,
- MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_ALARM_CTRL, (1<<2));
+ MDIO_PMA_DEVAD, MDIO_PMA_LASI_RXCTRL, (1<<2));
bnx2x_cl45_write(bp, phy,
- MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_CTRL, 0x0004);
+ MDIO_PMA_DEVAD, MDIO_PMA_LASI_CTRL, 0x0004);
bnx2x_8073_set_pause_cl37(params, phy, vars);
@@ -4091,7 +6856,7 @@
MDIO_PMA_DEVAD, MDIO_PMA_REG_M8051_MSGOUT_REG, &tmp1);
bnx2x_cl45_read(bp, phy,
- MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_ALARM, &tmp1);
+ MDIO_PMA_DEVAD, MDIO_PMA_LASI_RXSTAT, &tmp1);
DP(NETIF_MSG_LINK, "Before rom RX_ALARM(port1): 0x%x\n", tmp1);
@@ -4225,7 +6990,7 @@
u16 an1000_status = 0;
bnx2x_cl45_read(bp, phy,
- MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_STATUS, &val1);
+ MDIO_PMA_DEVAD, MDIO_PMA_LASI_STAT, &val1);
DP(NETIF_MSG_LINK, "8703 LASI status 0x%x\n", val1);
@@ -4241,7 +7006,7 @@
/* Check the LASI */
bnx2x_cl45_read(bp, phy,
- MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_ALARM, &val2);
+ MDIO_PMA_DEVAD, MDIO_PMA_LASI_RXSTAT, &val2);
DP(NETIF_MSG_LINK, "KR 0x9003 0x%x\n", val2);
@@ -4367,9 +7132,9 @@
/******************************************************************/
/* BCM8705 PHY SECTION */
/******************************************************************/
-static u8 bnx2x_8705_config_init(struct bnx2x_phy *phy,
- struct link_params *params,
- struct link_vars *vars)
+static int bnx2x_8705_config_init(struct bnx2x_phy *phy,
+ struct link_params *params,
+ struct link_vars *vars)
{
struct bnx2x *bp = params->bp;
DP(NETIF_MSG_LINK, "init 8705\n");
@@ -4430,6 +7195,30 @@
/******************************************************************/
/* SFP+ module Section */
/******************************************************************/
+static void bnx2x_set_disable_pmd_transmit(struct link_params *params,
+ struct bnx2x_phy *phy,
+ u8 pmd_dis)
+{
+ struct bnx2x *bp = params->bp;
+ /*
+ * Disable transmitter only for bootcodes which can enable it afterwards
+ * (for D3 link)
+ */
+ if (pmd_dis) {
+ if (params->feature_config_flags &
+ FEATURE_CONFIG_BC_SUPPORTS_SFP_TX_DISABLED)
+ DP(NETIF_MSG_LINK, "Disabling PMD transmitter\n");
+ else {
+ DP(NETIF_MSG_LINK, "NOT disabling PMD transmitter\n");
+ return;
+ }
+ } else
+ DP(NETIF_MSG_LINK, "Enabling PMD transmitter\n");
+ bnx2x_cl45_write(bp, phy,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_TX_DISABLE, pmd_dis);
+}
+
static u8 bnx2x_get_gpio_port(struct link_params *params)
{
u8 gpio_port;
@@ -4443,9 +7232,10 @@
swap_override = REG_RD(bp, NIG_REG_STRAP_OVERRIDE);
return gpio_port ^ (swap_val && swap_override);
}
-static void bnx2x_sfp_set_transmitter(struct link_params *params,
- struct bnx2x_phy *phy,
- u8 tx_en)
+
+static void bnx2x_sfp_e1e2_set_transmitter(struct link_params *params,
+ struct bnx2x_phy *phy,
+ u8 tx_en)
{
u16 val;
u8 port = params->port;
@@ -4500,9 +7290,21 @@
}
}
-static u8 bnx2x_8726_read_sfp_module_eeprom(struct bnx2x_phy *phy,
- struct link_params *params,
- u16 addr, u8 byte_cnt, u8 *o_buf)
+static void bnx2x_sfp_set_transmitter(struct link_params *params,
+ struct bnx2x_phy *phy,
+ u8 tx_en)
+{
+ struct bnx2x *bp = params->bp;
+ DP(NETIF_MSG_LINK, "Setting SFP+ transmitter to %d\n", tx_en);
+ if (CHIP_IS_E3(bp))
+ bnx2x_sfp_e3_set_transmitter(params, phy, tx_en);
+ else
+ bnx2x_sfp_e1e2_set_transmitter(params, phy, tx_en);
+}
+
+static int bnx2x_8726_read_sfp_module_eeprom(struct bnx2x_phy *phy,
+ struct link_params *params,
+ u16 addr, u8 byte_cnt, u8 *o_buf)
{
struct bnx2x *bp = params->bp;
u16 val = 0;
@@ -4566,9 +7368,45 @@
return -EINVAL;
}
-static u8 bnx2x_8727_read_sfp_module_eeprom(struct bnx2x_phy *phy,
- struct link_params *params,
- u16 addr, u8 byte_cnt, u8 *o_buf)
+static int bnx2x_warpcore_read_sfp_module_eeprom(struct bnx2x_phy *phy,
+ struct link_params *params,
+ u16 addr, u8 byte_cnt,
+ u8 *o_buf)
+{
+ int rc = 0;
+ u8 i, j = 0, cnt = 0;
+ u32 data_array[4];
+ u16 addr32;
+ struct bnx2x *bp = params->bp;
+ /*DP(NETIF_MSG_LINK, "bnx2x_direct_read_sfp_module_eeprom:"
+ " addr %d, cnt %d\n",
+ addr, byte_cnt);*/
+ if (byte_cnt > 16) {
+ DP(NETIF_MSG_LINK, "Reading from eeprom is"
+ " is limited to 16 bytes\n");
+ return -EINVAL;
+ }
+
+ /* 4 byte aligned address */
+ addr32 = addr & (~0x3);
+ do {
+ rc = bnx2x_bsc_read(params, phy, 0xa0, addr32, 0, byte_cnt,
+ data_array);
+ } while ((rc != 0) && (++cnt < I2C_WA_RETRY_CNT));
+
+ if (rc == 0) {
+ for (i = (addr - addr32); i < byte_cnt + (addr - addr32); i++) {
+ o_buf[j] = *((u8 *)data_array + i);
+ j++;
+ }
+ }
+
+ return rc;
+}
+
+static int bnx2x_8727_read_sfp_module_eeprom(struct bnx2x_phy *phy,
+ struct link_params *params,
+ u16 addr, u8 byte_cnt, u8 *o_buf)
{
struct bnx2x *bp = params->bp;
u16 val, i;
@@ -4653,27 +7491,39 @@
return -EINVAL;
}
-u8 bnx2x_read_sfp_module_eeprom(struct bnx2x_phy *phy,
- struct link_params *params, u16 addr,
- u8 byte_cnt, u8 *o_buf)
+int bnx2x_read_sfp_module_eeprom(struct bnx2x_phy *phy,
+ struct link_params *params, u16 addr,
+ u8 byte_cnt, u8 *o_buf)
{
- if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726)
- return bnx2x_8726_read_sfp_module_eeprom(phy, params, addr,
- byte_cnt, o_buf);
- else if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727)
- return bnx2x_8727_read_sfp_module_eeprom(phy, params, addr,
- byte_cnt, o_buf);
- return -EINVAL;
+ int rc = -EINVAL;
+ switch (phy->type) {
+ case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726:
+ rc = bnx2x_8726_read_sfp_module_eeprom(phy, params, addr,
+ byte_cnt, o_buf);
+ break;
+ case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
+ case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8722:
+ rc = bnx2x_8727_read_sfp_module_eeprom(phy, params, addr,
+ byte_cnt, o_buf);
+ break;
+ case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
+ rc = bnx2x_warpcore_read_sfp_module_eeprom(phy, params, addr,
+ byte_cnt, o_buf);
+ break;
+ }
+ return rc;
}
-static u8 bnx2x_get_edc_mode(struct bnx2x_phy *phy,
- struct link_params *params,
- u16 *edc_mode)
+static int bnx2x_get_edc_mode(struct bnx2x_phy *phy,
+ struct link_params *params,
+ u16 *edc_mode)
{
struct bnx2x *bp = params->bp;
+ u32 sync_offset = 0, phy_idx, media_types;
u8 val, check_limiting_mode = 0;
*edc_mode = EDC_MODE_LIMITING;
+ phy->media_type = ETH_PHY_UNSPECIFIED;
/* First check for copper cable */
if (bnx2x_read_sfp_module_eeprom(phy,
params,
@@ -4688,7 +7538,7 @@
case SFP_EEPROM_CON_TYPE_VAL_COPPER:
{
u8 copper_module_type;
-
+ phy->media_type = ETH_PHY_DA_TWINAX;
/*
* Check if its active cable (includes SFP+ module)
* of passive cable
@@ -4697,8 +7547,7 @@
params,
SFP_EEPROM_FC_TX_TECH_ADDR,
1,
- &copper_module_type) !=
- 0) {
+ &copper_module_type) != 0) {
DP(NETIF_MSG_LINK,
"Failed to read copper-cable-type"
" from SFP+ EEPROM\n");
@@ -4723,6 +7572,7 @@
break;
}
case SFP_EEPROM_CON_TYPE_VAL_LC:
+ phy->media_type = ETH_PHY_SFP_FIBER;
DP(NETIF_MSG_LINK, "Optic module detected\n");
check_limiting_mode = 1;
break;
@@ -4731,7 +7581,22 @@
val);
return -EINVAL;
}
-
+ sync_offset = params->shmem_base +
+ offsetof(struct shmem_region,
+ dev_info.port_hw_config[params->port].media_type);
+ media_types = REG_RD(bp, sync_offset);
+ /* Update media type for non-PMF sync */
+ for (phy_idx = INT_PHY; phy_idx < MAX_PHYS; phy_idx++) {
+ if (&(params->phy[phy_idx]) == phy) {
+ media_types &= ~(PORT_HW_CFG_MEDIA_TYPE_PHY0_MASK <<
+ (PORT_HW_CFG_MEDIA_TYPE_PHY1_SHIFT * phy_idx));
+ media_types |= ((phy->media_type &
+ PORT_HW_CFG_MEDIA_TYPE_PHY0_MASK) <<
+ (PORT_HW_CFG_MEDIA_TYPE_PHY1_SHIFT * phy_idx));
+ break;
+ }
+ }
+ REG_WR(bp, sync_offset, media_types);
if (check_limiting_mode) {
u8 options[SFP_EEPROM_OPTIONS_SIZE];
if (bnx2x_read_sfp_module_eeprom(phy,
@@ -4755,8 +7620,8 @@
* This function read the relevant field from the module (SFP+), and verify it
* is compliant with this board
*/
-static u8 bnx2x_verify_sfp_module(struct bnx2x_phy *phy,
- struct link_params *params)
+static int bnx2x_verify_sfp_module(struct bnx2x_phy *phy,
+ struct link_params *params)
{
struct bnx2x *bp = params->bp;
u32 val, cmd;
@@ -4825,8 +7690,8 @@
return -EINVAL;
}
-static u8 bnx2x_wait_for_sfp_module_initialized(struct bnx2x_phy *phy,
- struct link_params *params)
+static int bnx2x_wait_for_sfp_module_initialized(struct bnx2x_phy *phy,
+ struct link_params *params)
{
u8 val;
@@ -4858,8 +7723,8 @@
* In the GPIO register, bit 4 is use to determine if the GPIOs are
* operating as INPUT or as OUTPUT. Bit 1 is for input, and 0 for
* output
- * Bits 0-1 determine the gpios value for OUTPUT in case bit 4 val is 0
- * Bits 8-9 determine the gpios value for INPUT in case bit 4 val is 1
+ * Bits 0-1 determine the GPIOs value for OUTPUT in case bit 4 val is 0
+ * Bits 8-9 determine the GPIOs value for INPUT in case bit 4 val is 1
* where the 1st bit is the over-current(only input), and 2nd bit is
* for power( only output )
*
@@ -4868,15 +7733,14 @@
*/
if (phy->flags & FLAGS_NOC)
return;
- if (!(phy->flags &
- FLAGS_NOC) && is_power_up)
+ if (is_power_up)
val = (1<<4);
else
/*
* Set GPIO control to OUTPUT, and set the power bit
* to according to the is_power_up
*/
- val = ((!(is_power_up)) << 1);
+ val = (1<<1);
bnx2x_cl45_write(bp, phy,
MDIO_PMA_DEVAD,
@@ -4884,9 +7748,9 @@
val);
}
-static u8 bnx2x_8726_set_limiting_mode(struct bnx2x *bp,
- struct bnx2x_phy *phy,
- u16 edc_mode)
+static int bnx2x_8726_set_limiting_mode(struct bnx2x *bp,
+ struct bnx2x_phy *phy,
+ u16 edc_mode)
{
u16 cur_limiting_mode;
@@ -4934,9 +7798,9 @@
return 0;
}
-static u8 bnx2x_8727_set_limiting_mode(struct bnx2x *bp,
- struct bnx2x_phy *phy,
- u16 edc_mode)
+static int bnx2x_8727_set_limiting_mode(struct bnx2x *bp,
+ struct bnx2x_phy *phy,
+ u16 edc_mode)
{
u16 phy_identifier;
u16 rom_ver2_val;
@@ -4989,7 +7853,7 @@
}
}
-static void bnx2x_set_sfp_module_fault_led(struct link_params *params,
+static void bnx2x_set_e1e2_module_fault_led(struct link_params *params,
u8 gpio_mode)
{
struct bnx2x *bp = params->bp;
@@ -5021,12 +7885,146 @@
}
}
-static u8 bnx2x_sfp_module_detection(struct bnx2x_phy *phy,
- struct link_params *params)
+static void bnx2x_set_e3_module_fault_led(struct link_params *params,
+ u8 gpio_mode)
+{
+ u32 pin_cfg;
+ u8 port = params->port;
+ struct bnx2x *bp = params->bp;
+ pin_cfg = (REG_RD(bp, params->shmem_base +
+ offsetof(struct shmem_region,
+ dev_info.port_hw_config[port].e3_sfp_ctrl)) &
+ PORT_HW_CFG_E3_FAULT_MDL_LED_MASK) >>
+ PORT_HW_CFG_E3_FAULT_MDL_LED_SHIFT;
+ DP(NETIF_MSG_LINK, "Setting Fault LED to %d using pin cfg %d\n",
+ gpio_mode, pin_cfg);
+ bnx2x_set_cfg_pin(bp, pin_cfg, gpio_mode);
+}
+
+static void bnx2x_set_sfp_module_fault_led(struct link_params *params,
+ u8 gpio_mode)
+{
+ struct bnx2x *bp = params->bp;
+ DP(NETIF_MSG_LINK, "Setting SFP+ module fault LED to %d\n", gpio_mode);
+ if (CHIP_IS_E3(bp)) {
+ /*
+ * Low ==> if SFP+ module is supported otherwise
+ * High ==> if SFP+ module is not on the approved vendor list
+ */
+ bnx2x_set_e3_module_fault_led(params, gpio_mode);
+ } else
+ bnx2x_set_e1e2_module_fault_led(params, gpio_mode);
+}
+
+static void bnx2x_warpcore_power_module(struct link_params *params,
+ struct bnx2x_phy *phy,
+ u8 power)
+{
+ u32 pin_cfg;
+ struct bnx2x *bp = params->bp;
+
+ pin_cfg = (REG_RD(bp, params->shmem_base +
+ offsetof(struct shmem_region,
+ dev_info.port_hw_config[params->port].e3_sfp_ctrl)) &
+ PORT_HW_CFG_E3_PWR_DIS_MASK) >>
+ PORT_HW_CFG_E3_PWR_DIS_SHIFT;
+
+ if (pin_cfg == PIN_CFG_NA)
+ return;
+ DP(NETIF_MSG_LINK, "Setting SFP+ module power to %d using pin cfg %d\n",
+ power, pin_cfg);
+ /*
+ * Low ==> corresponding SFP+ module is powered
+ * high ==> the SFP+ module is powered down
+ */
+ bnx2x_set_cfg_pin(bp, pin_cfg, power ^ 1);
+}
+
+static void bnx2x_warpcore_hw_reset(struct bnx2x_phy *phy,
+ struct link_params *params)
+{
+ bnx2x_warpcore_power_module(params, phy, 0);
+}
+
+static void bnx2x_power_sfp_module(struct link_params *params,
+ struct bnx2x_phy *phy,
+ u8 power)
+{
+ struct bnx2x *bp = params->bp;
+ DP(NETIF_MSG_LINK, "Setting SFP+ power to %x\n", power);
+
+ switch (phy->type) {
+ case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
+ case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8722:
+ bnx2x_8727_power_module(params->bp, phy, power);
+ break;
+ case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
+ bnx2x_warpcore_power_module(params, phy, power);
+ break;
+ default:
+ break;
+ }
+}
+static void bnx2x_warpcore_set_limiting_mode(struct link_params *params,
+ struct bnx2x_phy *phy,
+ u16 edc_mode)
+{
+ u16 val = 0;
+ u16 mode = MDIO_WC_REG_UC_INFO_B1_FIRMWARE_MODE_DEFAULT;
+ struct bnx2x *bp = params->bp;
+
+ u8 lane = bnx2x_get_warpcore_lane(phy, params);
+ /* This is a global register which controls all lanes */
+ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_UC_INFO_B1_FIRMWARE_MODE, &val);
+ val &= ~(0xf << (lane << 2));
+
+ switch (edc_mode) {
+ case EDC_MODE_LINEAR:
+ case EDC_MODE_LIMITING:
+ mode = MDIO_WC_REG_UC_INFO_B1_FIRMWARE_MODE_DEFAULT;
+ break;
+ case EDC_MODE_PASSIVE_DAC:
+ mode = MDIO_WC_REG_UC_INFO_B1_FIRMWARE_MODE_SFP_DAC;
+ break;
+ default:
+ break;
+ }
+
+ val |= (mode << (lane << 2));
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_UC_INFO_B1_FIRMWARE_MODE, val);
+ /* A must read */
+ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_UC_INFO_B1_FIRMWARE_MODE, &val);
+
+
+}
+
+static void bnx2x_set_limiting_mode(struct link_params *params,
+ struct bnx2x_phy *phy,
+ u16 edc_mode)
+{
+ switch (phy->type) {
+ case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726:
+ bnx2x_8726_set_limiting_mode(params->bp, phy, edc_mode);
+ break;
+ case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
+ case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8722:
+ bnx2x_8727_set_limiting_mode(params->bp, phy, edc_mode);
+ break;
+ case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
+ bnx2x_warpcore_set_limiting_mode(params, phy, edc_mode);
+ break;
+ }
+}
+
+int bnx2x_sfp_module_detection(struct bnx2x_phy *phy,
+ struct link_params *params)
{
struct bnx2x *bp = params->bp;
u16 edc_mode;
- u8 rc = 0;
+ int rc = 0;
u32 val = REG_RD(bp, params->shmem_base +
offsetof(struct shmem_region, dev_info.
@@ -5034,7 +8032,8 @@
DP(NETIF_MSG_LINK, "SFP+ module plugged in/out detected on port %d\n",
params->port);
-
+ /* Power up module */
+ bnx2x_power_sfp_module(params, phy, 1);
if (bnx2x_get_edc_mode(phy, params, &edc_mode) != 0) {
DP(NETIF_MSG_LINK, "Failed to get valid module type\n");
return -EINVAL;
@@ -5046,12 +8045,11 @@
bnx2x_set_sfp_module_fault_led(params,
MISC_REGISTERS_GPIO_HIGH);
- if ((phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727) &&
- ((val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) ==
- PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_POWER_DOWN)) {
- /* Shutdown SFP+ module */
+ /* Check if need to power down the SFP+ module */
+ if ((val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) ==
+ PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_POWER_DOWN) {
DP(NETIF_MSG_LINK, "Shutdown SFP+ module!!\n");
- bnx2x_8727_power_module(bp, phy, 0);
+ bnx2x_power_sfp_module(params, phy, 0);
return rc;
}
} else {
@@ -5059,18 +8057,12 @@
bnx2x_set_sfp_module_fault_led(params, MISC_REGISTERS_GPIO_LOW);
}
- /* power up the SFP module */
- if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727)
- bnx2x_8727_power_module(bp, phy, 1);
-
/*
* Check and set limiting mode / LRM mode on 8726. On 8727 it
* is done automatically
*/
- if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726)
- bnx2x_8726_set_limiting_mode(bp, phy, edc_mode);
- else
- bnx2x_8727_set_limiting_mode(bp, phy, edc_mode);
+ bnx2x_set_limiting_mode(params, phy, edc_mode);
+
/*
* Enable transmit for this module if the module is approved, or
* if unapproved modules should also enable the Tx laser
@@ -5088,23 +8080,33 @@
void bnx2x_handle_module_detect_int(struct link_params *params)
{
struct bnx2x *bp = params->bp;
- struct bnx2x_phy *phy = ¶ms->phy[EXT_PHY1];
+ struct bnx2x_phy *phy;
u32 gpio_val;
- u8 port = params->port;
+ u8 gpio_num, gpio_port;
+ if (CHIP_IS_E3(bp))
+ phy = ¶ms->phy[INT_PHY];
+ else
+ phy = ¶ms->phy[EXT_PHY1];
+
+ if (bnx2x_get_mod_abs_int_cfg(bp, params->chip_id, params->shmem_base,
+ params->port, &gpio_num, &gpio_port) ==
+ -EINVAL) {
+ DP(NETIF_MSG_LINK, "Failed to get MOD_ABS interrupt config\n");
+ return;
+ }
/* Set valid module led off */
bnx2x_set_sfp_module_fault_led(params, MISC_REGISTERS_GPIO_HIGH);
/* Get current gpio val reflecting module plugged in / out*/
- gpio_val = bnx2x_get_gpio(bp, MISC_REGISTERS_GPIO_3, port);
+ gpio_val = bnx2x_get_gpio(bp, gpio_num, gpio_port);
/* Call the handling function in case module is detected */
if (gpio_val == 0) {
-
- bnx2x_set_gpio_int(bp, MISC_REGISTERS_GPIO_3,
+ bnx2x_power_sfp_module(params, phy, 1);
+ bnx2x_set_gpio_int(bp, gpio_num,
MISC_REGISTERS_GPIO_INT_OUTPUT_CLR,
- port);
-
+ gpio_port);
if (bnx2x_wait_for_sfp_module_initialized(phy, params) == 0)
bnx2x_sfp_module_detection(phy, params);
else
@@ -5115,13 +8117,14 @@
port_feature_config[params->port].
config));
- bnx2x_set_gpio_int(bp, MISC_REGISTERS_GPIO_3,
+ bnx2x_set_gpio_int(bp, gpio_num,
MISC_REGISTERS_GPIO_INT_OUTPUT_SET,
- port);
+ gpio_port);
/*
* Module was plugged out.
* Disable transmit for this module
*/
+ phy->media_type = ETH_PHY_NOT_PRESENT;
if ((val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) ==
PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_DISABLE_TX_LASER)
bnx2x_sfp_set_transmitter(params, phy, 0);
@@ -5129,6 +8132,29 @@
}
/******************************************************************/
+/* Used by 8706 and 8727 */
+/******************************************************************/
+static void bnx2x_sfp_mask_fault(struct bnx2x *bp,
+ struct bnx2x_phy *phy,
+ u16 alarm_status_offset,
+ u16 alarm_ctrl_offset)
+{
+ u16 alarm_status, val;
+ bnx2x_cl45_read(bp, phy,
+ MDIO_PMA_DEVAD, alarm_status_offset,
+ &alarm_status);
+ bnx2x_cl45_read(bp, phy,
+ MDIO_PMA_DEVAD, alarm_status_offset,
+ &alarm_status);
+ /* Mask or enable the fault event. */
+ bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, alarm_ctrl_offset, &val);
+ if (alarm_status & (1<<0))
+ val &= ~(1<<0);
+ else
+ val |= (1<<0);
+ bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, alarm_ctrl_offset, val);
+}
+/******************************************************************/
/* common BCM8706/BCM8726 PHY SECTION */
/******************************************************************/
static u8 bnx2x_8706_8726_read_status(struct bnx2x_phy *phy,
@@ -5141,12 +8167,16 @@
DP(NETIF_MSG_LINK, "XGXS 8706/8726\n");
/* Clear RX Alarm*/
bnx2x_cl45_read(bp, phy,
- MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_ALARM, &val2);
+ MDIO_PMA_DEVAD, MDIO_PMA_LASI_RXSTAT, &val2);
+
+ bnx2x_sfp_mask_fault(bp, phy, MDIO_PMA_LASI_TXSTAT,
+ MDIO_PMA_LASI_TXCTRL);
+
/* clear LASI indication*/
bnx2x_cl45_read(bp, phy,
- MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_STATUS, &val1);
+ MDIO_PMA_DEVAD, MDIO_PMA_LASI_STAT, &val1);
bnx2x_cl45_read(bp, phy,
- MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_STATUS, &val2);
+ MDIO_PMA_DEVAD, MDIO_PMA_LASI_STAT, &val2);
DP(NETIF_MSG_LINK, "8706/8726 LASI status 0x%x--> 0x%x\n", val1, val2);
bnx2x_cl45_read(bp, phy,
@@ -5173,6 +8203,17 @@
bnx2x_ext_phy_resolve_fc(phy, params, vars);
vars->duplex = DUPLEX_FULL;
}
+
+ /* Capture 10G link fault. Read twice to clear stale value. */
+ if (vars->line_speed == SPEED_10000) {
+ bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD,
+ MDIO_PMA_LASI_TXSTAT, &val1);
+ bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD,
+ MDIO_PMA_LASI_TXSTAT, &val1);
+ if (val1 & (1<<0))
+ vars->fault_detected = 1;
+ }
+
return link_up;
}
@@ -5186,6 +8227,10 @@
u32 tx_en_mode;
u16 cnt, val, tmp1;
struct bnx2x *bp = params->bp;
+
+ /* SPF+ PHY: Set flag to check for Tx error */
+ vars->phy_flags = PHY_TX_ERROR_CHECK_FLAG;
+
bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
MISC_REGISTERS_GPIO_OUTPUT_HIGH, params->port);
/* HW reset */
@@ -5228,7 +8273,11 @@
MDIO_PMA_DEVAD,
MDIO_PMA_REG_DIGITAL_CTRL, 0x400);
bnx2x_cl45_write(bp, phy,
- MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_CTRL, 1);
+ MDIO_PMA_DEVAD, MDIO_PMA_LASI_TXCTRL,
+ 0);
+ /* Arm LASI for link and Tx fault. */
+ bnx2x_cl45_write(bp, phy,
+ MDIO_PMA_DEVAD, MDIO_PMA_LASI_CTRL, 3);
} else {
/* Force 1Gbps using autoneg with 1G advertisement */
@@ -5251,10 +8300,10 @@
bnx2x_cl45_write(bp, phy,
MDIO_AN_DEVAD, MDIO_AN_REG_CTRL, 0x1200);
bnx2x_cl45_write(bp, phy,
- MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_ALARM_CTRL,
+ MDIO_PMA_DEVAD, MDIO_PMA_LASI_RXCTRL,
0x0400);
bnx2x_cl45_write(bp, phy,
- MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_CTRL,
+ MDIO_PMA_DEVAD, MDIO_PMA_LASI_CTRL,
0x0004);
}
bnx2x_save_bcm_spirom_ver(bp, phy, params->port);
@@ -5281,9 +8330,9 @@
return 0;
}
-static u8 bnx2x_8706_read_status(struct bnx2x_phy *phy,
- struct link_params *params,
- struct link_vars *vars)
+static int bnx2x_8706_read_status(struct bnx2x_phy *phy,
+ struct link_params *params,
+ struct link_vars *vars)
{
return bnx2x_8706_8726_read_status(phy, params, vars);
}
@@ -5358,15 +8407,16 @@
}
-static u8 bnx2x_8726_config_init(struct bnx2x_phy *phy,
- struct link_params *params,
- struct link_vars *vars)
+static int bnx2x_8726_config_init(struct bnx2x_phy *phy,
+ struct link_params *params,
+ struct link_vars *vars)
{
struct bnx2x *bp = params->bp;
- u32 val;
- u32 swap_val, swap_override, aeu_gpio_mask, offset;
DP(NETIF_MSG_LINK, "Initializing BCM8726\n");
+ /* SPF+ PHY: Set flag to check for Tx error */
+ vars->phy_flags = PHY_TX_ERROR_CHECK_FLAG;
+
bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 1<<15);
bnx2x_wait_reset_complete(bp, phy, params);
@@ -5387,9 +8437,9 @@
bnx2x_cl45_write(bp, phy,
MDIO_PMA_DEVAD, MDIO_PMA_REG_10G_CTRL2, 0xD);
bnx2x_cl45_write(bp, phy,
- MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_CTRL, 0x5);
+ MDIO_PMA_DEVAD, MDIO_PMA_LASI_CTRL, 0x5);
bnx2x_cl45_write(bp, phy,
- MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_ALARM_CTRL,
+ MDIO_PMA_DEVAD, MDIO_PMA_LASI_RXCTRL,
0x400);
} else if ((phy->req_line_speed == SPEED_AUTO_NEG) &&
(phy->speed_cap_mask &
@@ -5415,14 +8465,14 @@
* change
*/
bnx2x_cl45_write(bp, phy,
- MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_CTRL, 0x4);
+ MDIO_PMA_DEVAD, MDIO_PMA_LASI_CTRL, 0x4);
bnx2x_cl45_write(bp, phy,
- MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_ALARM_CTRL,
+ MDIO_PMA_DEVAD, MDIO_PMA_LASI_RXCTRL,
0x400);
} else { /* Default 10G. Set only LASI control */
bnx2x_cl45_write(bp, phy,
- MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_CTRL, 1);
+ MDIO_PMA_DEVAD, MDIO_PMA_LASI_CTRL, 1);
}
/* Set TX PreEmphasis if needed */
@@ -5443,30 +8493,6 @@
phy->tx_preemphasis[1]);
}
- /* Set GPIO3 to trigger SFP+ module insertion/removal */
- bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_3,
- MISC_REGISTERS_GPIO_INPUT_HI_Z, params->port);
-
- /* The GPIO should be swapped if the swap register is set and active */
- swap_val = REG_RD(bp, NIG_REG_PORT_SWAP);
- swap_override = REG_RD(bp, NIG_REG_STRAP_OVERRIDE);
-
- /* Select function upon port-swap configuration */
- if (params->port == 0) {
- offset = MISC_REG_AEU_ENABLE1_FUNC_0_OUT_0;
- aeu_gpio_mask = (swap_val && swap_override) ?
- AEU_INPUTS_ATTN_BITS_GPIO3_FUNCTION_1 :
- AEU_INPUTS_ATTN_BITS_GPIO3_FUNCTION_0;
- } else {
- offset = MISC_REG_AEU_ENABLE1_FUNC_1_OUT_0;
- aeu_gpio_mask = (swap_val && swap_override) ?
- AEU_INPUTS_ATTN_BITS_GPIO3_FUNCTION_0 :
- AEU_INPUTS_ATTN_BITS_GPIO3_FUNCTION_1;
- }
- val = REG_RD(bp, offset);
- /* add GPIO3 to group */
- val |= aeu_gpio_mask;
- REG_WR(bp, offset, val);
return 0;
}
@@ -5548,9 +8574,9 @@
MISC_REGISTERS_GPIO_OUTPUT_LOW, port);
}
-static u8 bnx2x_8727_config_init(struct bnx2x_phy *phy,
- struct link_params *params,
- struct link_vars *vars)
+static int bnx2x_8727_config_init(struct bnx2x_phy *phy,
+ struct link_params *params,
+ struct link_vars *vars)
{
u32 tx_en_mode;
u16 tmp1, val, mod_abs, tmp2;
@@ -5559,18 +8585,24 @@
struct bnx2x *bp = params->bp;
/* Enable PMD link, MOD_ABS_FLT, and 1G link alarm */
+ /* SPF+ PHY: Set flag to check for Tx error */
+ vars->phy_flags = PHY_TX_ERROR_CHECK_FLAG;
+
bnx2x_wait_reset_complete(bp, phy, params);
rx_alarm_ctrl_val = (1<<2) | (1<<5) ;
- lasi_ctrl_val = 0x0004;
+ /* Should be 0x6 to enable XS on Tx side. */
+ lasi_ctrl_val = 0x0006;
DP(NETIF_MSG_LINK, "Initializing BCM8727\n");
/* enable LASI */
bnx2x_cl45_write(bp, phy,
- MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_ALARM_CTRL,
+ MDIO_PMA_DEVAD, MDIO_PMA_LASI_RXCTRL,
rx_alarm_ctrl_val);
-
bnx2x_cl45_write(bp, phy,
- MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_CTRL, lasi_ctrl_val);
+ MDIO_PMA_DEVAD, MDIO_PMA_LASI_TXCTRL,
+ 0);
+ bnx2x_cl45_write(bp, phy,
+ MDIO_PMA_DEVAD, MDIO_PMA_LASI_CTRL, lasi_ctrl_val);
/*
* Initially configure MOD_ABS to interrupt when module is
@@ -5590,6 +8622,9 @@
MDIO_PMA_DEVAD, MDIO_PMA_REG_PHY_IDENTIFIER, mod_abs);
+ /* Enable/Disable PHY transmitter output */
+ bnx2x_set_disable_pmd_transmit(params, phy, 0);
+
/* Make MOD_ABS give interrupt on change */
bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_8727_PCS_OPT_CTRL,
&val);
@@ -5612,7 +8647,7 @@
MDIO_PMA_DEVAD, MDIO_PMA_REG_M8051_MSGOUT_REG, &tmp1);
bnx2x_cl45_read(bp, phy,
- MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_ALARM, &tmp1);
+ MDIO_PMA_DEVAD, MDIO_PMA_LASI_RXSTAT, &tmp1);
/* Set option 1G speed */
if (phy->req_line_speed == SPEED_1000) {
@@ -5730,7 +8765,7 @@
/* Module is absent */
DP(NETIF_MSG_LINK, "MOD_ABS indication "
"show module is absent\n");
-
+ phy->media_type = ETH_PHY_NOT_PRESENT;
/*
* 1. Set mod_abs to detect next module
* presence event
@@ -5752,7 +8787,7 @@
*/
bnx2x_cl45_read(bp, phy,
MDIO_PMA_DEVAD,
- MDIO_PMA_REG_RX_ALARM, &rx_alarm_status);
+ MDIO_PMA_LASI_RXSTAT, &rx_alarm_status);
} else {
/* Module is present */
@@ -5781,7 +8816,7 @@
*/
bnx2x_cl45_read(bp, phy,
MDIO_PMA_DEVAD,
- MDIO_PMA_REG_RX_ALARM, &rx_alarm_status);
+ MDIO_PMA_LASI_RXSTAT, &rx_alarm_status);
if ((val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) ==
@@ -5805,26 +8840,29 @@
{
struct bnx2x *bp = params->bp;
- u8 link_up = 0;
+ u8 link_up = 0, oc_port = params->port;
u16 link_status = 0;
u16 rx_alarm_status, lasi_ctrl, val1;
/* If PHY is not initialized, do not check link status */
bnx2x_cl45_read(bp, phy,
- MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_CTRL,
+ MDIO_PMA_DEVAD, MDIO_PMA_LASI_CTRL,
&lasi_ctrl);
if (!lasi_ctrl)
return 0;
- /* Check the LASI */
+ /* Check the LASI on Rx */
bnx2x_cl45_read(bp, phy,
- MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_ALARM,
+ MDIO_PMA_DEVAD, MDIO_PMA_LASI_RXSTAT,
&rx_alarm_status);
vars->line_speed = 0;
DP(NETIF_MSG_LINK, "8727 RX_ALARM_STATUS 0x%x\n", rx_alarm_status);
+ bnx2x_sfp_mask_fault(bp, phy, MDIO_PMA_LASI_TXSTAT,
+ MDIO_PMA_LASI_TXCTRL);
+
bnx2x_cl45_read(bp, phy,
- MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_STATUS, &val1);
+ MDIO_PMA_DEVAD, MDIO_PMA_LASI_STAT, &val1);
DP(NETIF_MSG_LINK, "8727 LASI status 0x%x\n", val1);
@@ -5843,8 +8881,10 @@
&val1);
if ((val1 & (1<<8)) == 0) {
+ if (!CHIP_IS_E1x(bp))
+ oc_port = BP_PATH(bp) + (params->port << 1);
DP(NETIF_MSG_LINK, "8727 Power fault has been detected"
- " on port %d\n", params->port);
+ " on port %d\n", oc_port);
netdev_err(bp->dev, "Error: Power fault on Port %d has"
" been detected and the power to "
"that SFP+ module has been removed"
@@ -5852,11 +8892,11 @@
" Please remove the SFP+ module and"
" restart the system to clear this"
" error.\n",
- params->port);
+ oc_port);
/* Disable all RX_ALARMs except for mod_abs */
bnx2x_cl45_write(bp, phy,
MDIO_PMA_DEVAD,
- MDIO_PMA_REG_RX_ALARM_CTRL, (1<<5));
+ MDIO_PMA_LASI_RXCTRL, (1<<5));
bnx2x_cl45_read(bp, phy,
MDIO_PMA_DEVAD,
@@ -5869,7 +8909,7 @@
/* Clear RX alarm */
bnx2x_cl45_read(bp, phy,
MDIO_PMA_DEVAD,
- MDIO_PMA_REG_RX_ALARM, &rx_alarm_status);
+ MDIO_PMA_LASI_RXSTAT, &rx_alarm_status);
return 0;
}
} /* Over current check */
@@ -5879,7 +8919,7 @@
bnx2x_8727_handle_mod_abs(phy, params);
/* Enable all mod_abs and link detection bits */
bnx2x_cl45_write(bp, phy,
- MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_ALARM_CTRL,
+ MDIO_PMA_DEVAD, MDIO_PMA_LASI_RXCTRL,
((1<<5) | (1<<2)));
}
DP(NETIF_MSG_LINK, "Enabling 8727 TX laser if SFP is approved\n");
@@ -5915,6 +8955,20 @@
DP(NETIF_MSG_LINK, "port %x: External link is down\n",
params->port);
}
+
+ /* Capture 10G link fault. */
+ if (vars->line_speed == SPEED_10000) {
+ bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD,
+ MDIO_PMA_LASI_TXSTAT, &val1);
+
+ bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD,
+ MDIO_PMA_LASI_TXSTAT, &val1);
+
+ if (val1 & (1<<0)) {
+ vars->fault_detected = 1;
+ }
+ }
+
if (link_up) {
bnx2x_ext_phy_resolve_fc(phy, params, vars);
vars->duplex = DUPLEX_FULL;
@@ -5945,10 +8999,14 @@
struct link_params *params)
{
struct bnx2x *bp = params->bp;
+
+ /* Enable/Disable PHY transmitter output */
+ bnx2x_set_disable_pmd_transmit(params, phy, 1);
+
/* Disable Transmitter */
bnx2x_sfp_set_transmitter(params, phy, 0);
/* Clear LASI */
- bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_CTRL, 0);
+ bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_LASI_CTRL, 0);
}
@@ -5958,111 +9016,106 @@
static void bnx2x_save_848xx_spirom_version(struct bnx2x_phy *phy,
struct link_params *params)
{
- u16 val, fw_ver1, fw_ver2, cnt, adj;
+ u16 val, fw_ver1, fw_ver2, cnt;
+ u8 port;
struct bnx2x *bp = params->bp;
- adj = 0;
- if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833)
- adj = -1;
+ port = params->port;
/* For the 32 bits registers in 848xx, access via MDIO2ARM interface.*/
/* (1) set register 0xc200_0014(SPI_BRIDGE_CTRL_2) to 0x03000000 */
- bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA819 + adj, 0x0014);
- bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA81A + adj, 0xc200);
- bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA81B + adj, 0x0000);
- bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA81C + adj, 0x0300);
- bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA817 + adj, 0x0009);
+ bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA819, 0x0014);
+ bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA81A, 0xc200);
+ bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA81B, 0x0000);
+ bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA81C, 0x0300);
+ bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA817, 0x0009);
for (cnt = 0; cnt < 100; cnt++) {
- bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, 0xA818 + adj, &val);
+ bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, 0xA818, &val);
if (val & 1)
break;
udelay(5);
}
if (cnt == 100) {
DP(NETIF_MSG_LINK, "Unable to read 848xx phy fw version(1)\n");
- bnx2x_save_spirom_version(bp, params->port, 0,
+ bnx2x_save_spirom_version(bp, port, 0,
phy->ver_addr);
return;
}
/* 2) read register 0xc200_0000 (SPI_FW_STATUS) */
- bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA819 + adj, 0x0000);
- bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA81A + adj, 0xc200);
- bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA817 + adj, 0x000A);
+ bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA819, 0x0000);
+ bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA81A, 0xc200);
+ bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA817, 0x000A);
for (cnt = 0; cnt < 100; cnt++) {
- bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, 0xA818 + adj, &val);
+ bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, 0xA818, &val);
if (val & 1)
break;
udelay(5);
}
if (cnt == 100) {
DP(NETIF_MSG_LINK, "Unable to read 848xx phy fw version(2)\n");
- bnx2x_save_spirom_version(bp, params->port, 0,
+ bnx2x_save_spirom_version(bp, port, 0,
phy->ver_addr);
return;
}
/* lower 16 bits of the register SPI_FW_STATUS */
- bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, 0xA81B + adj, &fw_ver1);
+ bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, 0xA81B, &fw_ver1);
/* upper 16 bits of register SPI_FW_STATUS */
- bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, 0xA81C + adj, &fw_ver2);
+ bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, 0xA81C, &fw_ver2);
- bnx2x_save_spirom_version(bp, params->port, (fw_ver2<<16) | fw_ver1,
+ bnx2x_save_spirom_version(bp, port, (fw_ver2<<16) | fw_ver1,
phy->ver_addr);
}
static void bnx2x_848xx_set_led(struct bnx2x *bp,
struct bnx2x_phy *phy)
{
- u16 val, adj;
-
- adj = 0;
- if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833)
- adj = -1;
+ u16 val;
/* PHYC_CTL_LED_CTL */
bnx2x_cl45_read(bp, phy,
MDIO_PMA_DEVAD,
- MDIO_PMA_REG_8481_LINK_SIGNAL + adj, &val);
+ MDIO_PMA_REG_8481_LINK_SIGNAL, &val);
val &= 0xFE00;
val |= 0x0092;
bnx2x_cl45_write(bp, phy,
MDIO_PMA_DEVAD,
- MDIO_PMA_REG_8481_LINK_SIGNAL + adj, val);
+ MDIO_PMA_REG_8481_LINK_SIGNAL, val);
bnx2x_cl45_write(bp, phy,
MDIO_PMA_DEVAD,
- MDIO_PMA_REG_8481_LED1_MASK + adj,
+ MDIO_PMA_REG_8481_LED1_MASK,
0x80);
bnx2x_cl45_write(bp, phy,
MDIO_PMA_DEVAD,
- MDIO_PMA_REG_8481_LED2_MASK + adj,
+ MDIO_PMA_REG_8481_LED2_MASK,
0x18);
/* Select activity source by Tx and Rx, as suggested by PHY AE */
bnx2x_cl45_write(bp, phy,
MDIO_PMA_DEVAD,
- MDIO_PMA_REG_8481_LED3_MASK + adj,
+ MDIO_PMA_REG_8481_LED3_MASK,
0x0006);
/* Select the closest activity blink rate to that in 10/100/1000 */
bnx2x_cl45_write(bp, phy,
MDIO_PMA_DEVAD,
- MDIO_PMA_REG_8481_LED3_BLINK + adj,
+ MDIO_PMA_REG_8481_LED3_BLINK,
0);
bnx2x_cl45_read(bp, phy,
MDIO_PMA_DEVAD,
- MDIO_PMA_REG_84823_CTL_LED_CTL_1 + adj, &val);
+ MDIO_PMA_REG_84823_CTL_LED_CTL_1, &val);
val |= MDIO_PMA_REG_84823_LED3_STRETCH_EN; /* stretch_en for LED3*/
bnx2x_cl45_write(bp, phy,
MDIO_PMA_DEVAD,
- MDIO_PMA_REG_84823_CTL_LED_CTL_1 + adj, val);
+ MDIO_PMA_REG_84823_CTL_LED_CTL_1, val);
/* 'Interrupt Mask' */
bnx2x_cl45_write(bp, phy,
@@ -6070,12 +9123,19 @@
0xFFFB, 0xFFFD);
}
-static u8 bnx2x_848xx_cmn_config_init(struct bnx2x_phy *phy,
- struct link_params *params,
- struct link_vars *vars)
+static int bnx2x_848xx_cmn_config_init(struct bnx2x_phy *phy,
+ struct link_params *params,
+ struct link_vars *vars)
{
struct bnx2x *bp = params->bp;
u16 autoneg_val, an_1000_val, an_10_100_val;
+ u16 tmp_req_line_speed;
+
+ tmp_req_line_speed = phy->req_line_speed;
+ if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833)
+ if (phy->req_line_speed == SPEED_10000)
+ phy->req_line_speed = SPEED_AUTO_NEG;
+
/*
* This phy uses the NIG latch mechanism since link indication
* arrives through its LED4 and not via its LASI signal, so we
@@ -6122,11 +9182,14 @@
MDIO_AN_DEVAD, MDIO_AN_REG_8481_1000T_CTRL,
an_1000_val);
- /* set 10 speed advertisement */
+ /* set 100 speed advertisement */
if (((phy->req_line_speed == SPEED_AUTO_NEG) &&
(phy->speed_cap_mask &
- (PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_FULL |
- PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_HALF)))) {
+ (PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_FULL |
+ PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_HALF)) &&
+ (phy->supported &
+ (SUPPORTED_100baseT_Half |
+ SUPPORTED_100baseT_Full)))) {
an_10_100_val |= (1<<7);
/* Enable autoneg and restart autoneg for legacy speeds */
autoneg_val |= (1<<9 | 1<<12);
@@ -6137,9 +9200,12 @@
}
/* set 10 speed advertisement */
if (((phy->req_line_speed == SPEED_AUTO_NEG) &&
- (phy->speed_cap_mask &
- (PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_FULL |
- PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_HALF)))) {
+ (phy->speed_cap_mask &
+ (PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_FULL |
+ PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_HALF)) &&
+ (phy->supported &
+ (SUPPORTED_10baseT_Half |
+ SUPPORTED_10baseT_Full)))) {
an_10_100_val |= (1<<5);
autoneg_val |= (1<<9 | 1<<12);
if (phy->req_duplex == DUPLEX_FULL)
@@ -6148,7 +9214,10 @@
}
/* Only 10/100 are allowed to work in FORCE mode */
- if (phy->req_line_speed == SPEED_100) {
+ if ((phy->req_line_speed == SPEED_100) &&
+ (phy->supported &
+ (SUPPORTED_100baseT_Half |
+ SUPPORTED_100baseT_Full))) {
autoneg_val |= (1<<13);
/* Enabled AUTO-MDIX when autoneg is disabled */
bnx2x_cl45_write(bp, phy,
@@ -6156,7 +9225,10 @@
(1<<15 | 1<<9 | 7<<0));
DP(NETIF_MSG_LINK, "Setting 100M force\n");
}
- if (phy->req_line_speed == SPEED_10) {
+ if ((phy->req_line_speed == SPEED_10) &&
+ (phy->supported &
+ (SUPPORTED_10baseT_Half |
+ SUPPORTED_10baseT_Full))) {
/* Enabled AUTO-MDIX when autoneg is disabled */
bnx2x_cl45_write(bp, phy,
MDIO_AN_DEVAD, MDIO_AN_REG_8481_AUX_CTRL,
@@ -6179,10 +9251,10 @@
(phy->speed_cap_mask &
PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)) ||
(phy->req_line_speed == SPEED_10000)) {
- DP(NETIF_MSG_LINK, "Advertising 10G\n");
- /* Restart autoneg for 10G*/
+ DP(NETIF_MSG_LINK, "Advertising 10G\n");
+ /* Restart autoneg for 10G*/
- bnx2x_cl45_write(bp, phy,
+ bnx2x_cl45_write(bp, phy,
MDIO_AN_DEVAD, MDIO_AN_REG_CTRL,
0x3200);
} else if (phy->req_line_speed != SPEED_10 &&
@@ -6195,12 +9267,14 @@
/* Save spirom version */
bnx2x_save_848xx_spirom_version(phy, params);
+ phy->req_line_speed = tmp_req_line_speed;
+
return 0;
}
-static u8 bnx2x_8481_config_init(struct bnx2x_phy *phy,
- struct link_params *params,
- struct link_vars *vars)
+static int bnx2x_8481_config_init(struct bnx2x_phy *phy,
+ struct link_params *params,
+ struct link_vars *vars)
{
struct bnx2x *bp = params->bp;
/* Restore normal power mode*/
@@ -6215,33 +9289,200 @@
return bnx2x_848xx_cmn_config_init(phy, params, vars);
}
-static u8 bnx2x_848x3_config_init(struct bnx2x_phy *phy,
- struct link_params *params,
- struct link_vars *vars)
+
+#define PHY84833_HDSHK_WAIT 300
+static int bnx2x_84833_pair_swap_cfg(struct bnx2x_phy *phy,
+ struct link_params *params,
+ struct link_vars *vars)
+{
+ u32 idx;
+ u32 pair_swap;
+ u16 val;
+ u16 data;
+ struct bnx2x *bp = params->bp;
+ /* Do pair swap */
+
+ /* Check for configuration. */
+ pair_swap = REG_RD(bp, params->shmem_base +
+ offsetof(struct shmem_region,
+ dev_info.port_hw_config[params->port].xgbt_phy_cfg)) &
+ PORT_HW_CFG_RJ45_PAIR_SWAP_MASK;
+
+ if (pair_swap == 0)
+ return 0;
+
+ data = (u16)pair_swap;
+
+ /* Write CMD_OPEN_OVERRIDE to STATUS reg */
+ bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
+ MDIO_84833_TOP_CFG_SCRATCH_REG2,
+ PHY84833_CMD_OPEN_OVERRIDE);
+ for (idx = 0; idx < PHY84833_HDSHK_WAIT; idx++) {
+ bnx2x_cl45_read(bp, phy, MDIO_CTL_DEVAD,
+ MDIO_84833_TOP_CFG_SCRATCH_REG2, &val);
+ if (val == PHY84833_CMD_OPEN_FOR_CMDS)
+ break;
+ msleep(1);
+ }
+ if (idx >= PHY84833_HDSHK_WAIT) {
+ DP(NETIF_MSG_LINK, "Pairswap: FW not ready.\n");
+ return -EINVAL;
+ }
+
+ bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
+ MDIO_84833_TOP_CFG_SCRATCH_REG4,
+ data);
+ /* Issue pair swap command */
+ bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
+ MDIO_84833_TOP_CFG_SCRATCH_REG0,
+ PHY84833_DIAG_CMD_PAIR_SWAP_CHANGE);
+ for (idx = 0; idx < PHY84833_HDSHK_WAIT; idx++) {
+ bnx2x_cl45_read(bp, phy, MDIO_CTL_DEVAD,
+ MDIO_84833_TOP_CFG_SCRATCH_REG2, &val);
+ if ((val == PHY84833_CMD_COMPLETE_PASS) ||
+ (val == PHY84833_CMD_COMPLETE_ERROR))
+ break;
+ msleep(1);
+ }
+ if ((idx >= PHY84833_HDSHK_WAIT) ||
+ (val == PHY84833_CMD_COMPLETE_ERROR)) {
+ DP(NETIF_MSG_LINK, "Pairswap: override failed.\n");
+ return -EINVAL;
+ }
+ bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
+ MDIO_84833_TOP_CFG_SCRATCH_REG2,
+ PHY84833_CMD_CLEAR_COMPLETE);
+ DP(NETIF_MSG_LINK, "Pairswap OK, val=0x%x\n", data);
+ return 0;
+}
+
+
+static u8 bnx2x_84833_get_reset_gpios(struct bnx2x *bp,
+ u32 shmem_base_path[],
+ u32 chip_id)
+{
+ u32 reset_pin[2];
+ u32 idx;
+ u8 reset_gpios;
+ if (CHIP_IS_E3(bp)) {
+ /* Assume that these will be GPIOs, not EPIOs. */
+ for (idx = 0; idx < 2; idx++) {
+ /* Map config param to register bit. */
+ reset_pin[idx] = REG_RD(bp, shmem_base_path[idx] +
+ offsetof(struct shmem_region,
+ dev_info.port_hw_config[0].e3_cmn_pin_cfg));
+ reset_pin[idx] = (reset_pin[idx] &
+ PORT_HW_CFG_E3_PHY_RESET_MASK) >>
+ PORT_HW_CFG_E3_PHY_RESET_SHIFT;
+ reset_pin[idx] -= PIN_CFG_GPIO0_P0;
+ reset_pin[idx] = (1 << reset_pin[idx]);
+ }
+ reset_gpios = (u8)(reset_pin[0] | reset_pin[1]);
+ } else {
+ /* E2, look from diff place of shmem. */
+ for (idx = 0; idx < 2; idx++) {
+ reset_pin[idx] = REG_RD(bp, shmem_base_path[idx] +
+ offsetof(struct shmem_region,
+ dev_info.port_hw_config[0].default_cfg));
+ reset_pin[idx] &= PORT_HW_CFG_EXT_PHY_GPIO_RST_MASK;
+ reset_pin[idx] -= PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO0_P0;
+ reset_pin[idx] >>= PORT_HW_CFG_EXT_PHY_GPIO_RST_SHIFT;
+ reset_pin[idx] = (1 << reset_pin[idx]);
+ }
+ reset_gpios = (u8)(reset_pin[0] | reset_pin[1]);
+ }
+
+ return reset_gpios;
+}
+
+static int bnx2x_84833_hw_reset_phy(struct bnx2x_phy *phy,
+ struct link_params *params)
+{
+ struct bnx2x *bp = params->bp;
+ u8 reset_gpios;
+ u32 other_shmem_base_addr = REG_RD(bp, params->shmem2_base +
+ offsetof(struct shmem2_region,
+ other_shmem_base_addr));
+
+ u32 shmem_base_path[2];
+ shmem_base_path[0] = params->shmem_base;
+ shmem_base_path[1] = other_shmem_base_addr;
+
+ reset_gpios = bnx2x_84833_get_reset_gpios(bp, shmem_base_path,
+ params->chip_id);
+
+ bnx2x_set_mult_gpio(bp, reset_gpios, MISC_REGISTERS_GPIO_OUTPUT_LOW);
+ udelay(10);
+ DP(NETIF_MSG_LINK, "84833 hw reset on pin values 0x%x\n",
+ reset_gpios);
+
+ return 0;
+}
+
+static int bnx2x_84833_common_init_phy(struct bnx2x *bp,
+ u32 shmem_base_path[],
+ u32 chip_id)
+{
+ u8 reset_gpios;
+
+ reset_gpios = bnx2x_84833_get_reset_gpios(bp, shmem_base_path, chip_id);
+
+ bnx2x_set_mult_gpio(bp, reset_gpios, MISC_REGISTERS_GPIO_OUTPUT_LOW);
+ udelay(10);
+ bnx2x_set_mult_gpio(bp, reset_gpios, MISC_REGISTERS_GPIO_OUTPUT_HIGH);
+ msleep(800);
+ DP(NETIF_MSG_LINK, "84833 reset pulse on pin values 0x%x\n",
+ reset_gpios);
+
+ return 0;
+}
+
+#define PHY84833_CONSTANT_LATENCY 1193
+static int bnx2x_848x3_config_init(struct bnx2x_phy *phy,
+ struct link_params *params,
+ struct link_vars *vars)
{
struct bnx2x *bp = params->bp;
u8 port, initialize = 1;
- u16 val, adj;
+ u16 val;
u16 temp;
- u32 actual_phy_selection, cms_enable;
- u8 rc = 0;
-
- /* This is just for MDIO_CTL_REG_84823_MEDIA register. */
- adj = 0;
- if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833)
- adj = 3;
+ u32 actual_phy_selection, cms_enable, idx;
+ int rc = 0;
msleep(1);
- if (CHIP_IS_E2(bp))
+
+ if (!(CHIP_IS_E1(bp)))
port = BP_PATH(bp);
else
port = params->port;
- bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_3,
- MISC_REGISTERS_GPIO_OUTPUT_HIGH,
- port);
+
+ if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823) {
+ bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_3,
+ MISC_REGISTERS_GPIO_OUTPUT_HIGH,
+ port);
+ } else {
+ /* MDIO reset */
+ bnx2x_cl45_write(bp, phy,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_CTRL, 0x8000);
+ /* Bring PHY out of super isolate mode */
+ bnx2x_cl45_read(bp, phy,
+ MDIO_CTL_DEVAD,
+ MDIO_84833_TOP_CFG_XGPHY_STRAP1, &val);
+ val &= ~MDIO_84833_SUPER_ISOLATE;
+ bnx2x_cl45_write(bp, phy,
+ MDIO_CTL_DEVAD,
+ MDIO_84833_TOP_CFG_XGPHY_STRAP1, val);
+ }
+
bnx2x_wait_reset_complete(bp, phy, params);
+
/* Wait for GPHY to come out of reset */
msleep(50);
+
+ if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833)
+ bnx2x_84833_pair_swap_cfg(phy, params, vars);
+
/*
* BCM84823 requires that XGXS links up first @ 10G for normal behavior
*/
@@ -6254,14 +9495,20 @@
/* Set dual-media configuration according to configuration */
bnx2x_cl45_read(bp, phy, MDIO_CTL_DEVAD,
- MDIO_CTL_REG_84823_MEDIA + adj, &val);
+ MDIO_CTL_REG_84823_MEDIA, &val);
val &= ~(MDIO_CTL_REG_84823_MEDIA_MAC_MASK |
MDIO_CTL_REG_84823_MEDIA_LINE_MASK |
MDIO_CTL_REG_84823_MEDIA_COPPER_CORE_DOWN |
MDIO_CTL_REG_84823_MEDIA_PRIORITY_MASK |
MDIO_CTL_REG_84823_MEDIA_FIBER_1G);
- val |= MDIO_CTL_REG_84823_CTRL_MAC_XFI |
- MDIO_CTL_REG_84823_MEDIA_LINE_XAUI_L;
+
+ if (CHIP_IS_E3(bp)) {
+ val &= ~(MDIO_CTL_REG_84823_MEDIA_MAC_MASK |
+ MDIO_CTL_REG_84823_MEDIA_LINE_MASK);
+ } else {
+ val |= (MDIO_CTL_REG_84823_CTRL_MAC_XFI |
+ MDIO_CTL_REG_84823_MEDIA_LINE_XAUI_L);
+ }
actual_phy_selection = bnx2x_phy_selection(params);
@@ -6287,28 +9534,90 @@
val |= MDIO_CTL_REG_84823_MEDIA_FIBER_1G;
bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
- MDIO_CTL_REG_84823_MEDIA + adj, val);
+ MDIO_CTL_REG_84823_MEDIA, val);
DP(NETIF_MSG_LINK, "Multi_phy config = 0x%x, Media control = 0x%x\n",
params->multi_phy_config, val);
+ /* AutogrEEEn */
+ if (params->feature_config_flags &
+ FEATURE_CONFIG_AUTOGREEEN_ENABLED) {
+ /* Ensure that f/w is ready */
+ for (idx = 0; idx < PHY84833_HDSHK_WAIT; idx++) {
+ bnx2x_cl45_read(bp, phy, MDIO_CTL_DEVAD,
+ MDIO_84833_TOP_CFG_SCRATCH_REG2, &val);
+ if (val == PHY84833_CMD_OPEN_FOR_CMDS)
+ break;
+ usleep_range(1000, 1000);
+ }
+ if (idx >= PHY84833_HDSHK_WAIT) {
+ DP(NETIF_MSG_LINK, "AutogrEEEn: FW not ready.\n");
+ return -EINVAL;
+ }
+
+ /* Select EEE mode */
+ bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
+ MDIO_84833_TOP_CFG_SCRATCH_REG3,
+ 0x2);
+
+ /* Set Idle and Latency */
+ bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
+ MDIO_84833_TOP_CFG_SCRATCH_REG4,
+ PHY84833_CONSTANT_LATENCY + 1);
+
+ bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
+ MDIO_84833_TOP_CFG_DATA3_REG,
+ PHY84833_CONSTANT_LATENCY + 1);
+
+ bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
+ MDIO_84833_TOP_CFG_DATA4_REG,
+ PHY84833_CONSTANT_LATENCY);
+
+ /* Send EEE instruction to command register */
+ bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
+ MDIO_84833_TOP_CFG_SCRATCH_REG0,
+ PHY84833_DIAG_CMD_SET_EEE_MODE);
+
+ /* Ensure that the command has completed */
+ for (idx = 0; idx < PHY84833_HDSHK_WAIT; idx++) {
+ bnx2x_cl45_read(bp, phy, MDIO_CTL_DEVAD,
+ MDIO_84833_TOP_CFG_SCRATCH_REG2, &val);
+ if ((val == PHY84833_CMD_COMPLETE_PASS) ||
+ (val == PHY84833_CMD_COMPLETE_ERROR))
+ break;
+ usleep_range(1000, 1000);
+ }
+ if ((idx >= PHY84833_HDSHK_WAIT) ||
+ (val == PHY84833_CMD_COMPLETE_ERROR)) {
+ DP(NETIF_MSG_LINK, "AutogrEEEn: command failed.\n");
+ return -EINVAL;
+ }
+
+ /* Reset command handler */
+ bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
+ MDIO_84833_TOP_CFG_SCRATCH_REG2,
+ PHY84833_CMD_CLEAR_COMPLETE);
+ }
+
if (initialize)
rc = bnx2x_848xx_cmn_config_init(phy, params, vars);
else
bnx2x_save_848xx_spirom_version(phy, params);
- cms_enable = REG_RD(bp, params->shmem_base +
+ /* 84833 PHY has a better feature and doesn't need to support this. */
+ if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823) {
+ cms_enable = REG_RD(bp, params->shmem_base +
offsetof(struct shmem_region,
dev_info.port_hw_config[params->port].default_cfg)) &
PORT_HW_CFG_ENABLE_CMS_MASK;
- bnx2x_cl45_read(bp, phy, MDIO_CTL_DEVAD,
- MDIO_CTL_REG_84823_USER_CTRL_REG, &val);
- if (cms_enable)
- val |= MDIO_CTL_REG_84823_USER_CTRL_CMS;
- else
- val &= ~MDIO_CTL_REG_84823_USER_CTRL_CMS;
- bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
- MDIO_CTL_REG_84823_USER_CTRL_REG, val);
-
+ bnx2x_cl45_read(bp, phy, MDIO_CTL_DEVAD,
+ MDIO_CTL_REG_84823_USER_CTRL_REG, &val);
+ if (cms_enable)
+ val |= MDIO_CTL_REG_84823_USER_CTRL_CMS;
+ else
+ val &= ~MDIO_CTL_REG_84823_USER_CTRL_CMS;
+ bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
+ MDIO_CTL_REG_84823_USER_CTRL_REG, val);
+ }
return rc;
}
@@ -6318,20 +9627,16 @@
struct link_vars *vars)
{
struct bnx2x *bp = params->bp;
- u16 val, val1, val2, adj;
+ u16 val, val1, val2;
u8 link_up = 0;
- /* Reg offset adjustment for 84833 */
- adj = 0;
- if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833)
- adj = -1;
/* Check 10G-BaseT link status */
/* Check PMD signal ok */
bnx2x_cl45_read(bp, phy,
MDIO_AN_DEVAD, 0xFFFA, &val1);
bnx2x_cl45_read(bp, phy,
- MDIO_PMA_DEVAD, MDIO_PMA_REG_8481_PMD_SIGNAL + adj,
+ MDIO_PMA_DEVAD, MDIO_PMA_REG_8481_PMD_SIGNAL,
&val2);
DP(NETIF_MSG_LINK, "BCM848xx: PMD_SIGNAL 1.a811 = 0x%x\n", val2);
@@ -6403,9 +9708,10 @@
return link_up;
}
-static u8 bnx2x_848xx_format_ver(u32 raw_ver, u8 *str, u16 *len)
+
+static int bnx2x_848xx_format_ver(u32 raw_ver, u8 *str, u16 *len)
{
- u8 status = 0;
+ int status = 0;
u32 spirom_ver;
spirom_ver = ((raw_ver & 0xF80) >> 7) << 16 | (raw_ver & 0x7F);
status = bnx2x_format_ver(spirom_ver, str, len);
@@ -6435,13 +9741,27 @@
{
struct bnx2x *bp = params->bp;
u8 port;
- if (CHIP_IS_E2(bp))
+ u16 val16;
+
+ if (!(CHIP_IS_E1(bp)))
port = BP_PATH(bp);
else
port = params->port;
- bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_3,
- MISC_REGISTERS_GPIO_OUTPUT_LOW,
- port);
+
+ if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823) {
+ bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_3,
+ MISC_REGISTERS_GPIO_OUTPUT_LOW,
+ port);
+ } else {
+ bnx2x_cl45_read(bp, phy,
+ MDIO_CTL_DEVAD,
+ 0x400f, &val16);
+ /* Put to low power mode on newer FW */
+ if ((val16 & 0x303f) > 0x1009)
+ bnx2x_cl45_write(bp, phy,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_CTRL, 0x800);
+ }
}
static void bnx2x_848xx_set_link_led(struct bnx2x_phy *phy,
@@ -6449,11 +9769,17 @@
{
struct bnx2x *bp = params->bp;
u16 val;
+ u8 port;
+
+ if (!(CHIP_IS_E1(bp)))
+ port = BP_PATH(bp);
+ else
+ port = params->port;
switch (mode) {
case LED_MODE_OFF:
- DP(NETIF_MSG_LINK, "Port 0x%x: LED MODE OFF\n", params->port);
+ DP(NETIF_MSG_LINK, "Port 0x%x: LED MODE OFF\n", port);
if ((params->hw_led_mode << SHARED_HW_CFG_LED_MODE_SHIFT) ==
SHARED_HW_CFG_LED_EXTPHY1) {
@@ -6489,7 +9815,7 @@
case LED_MODE_FRONT_PANEL_OFF:
DP(NETIF_MSG_LINK, "Port 0x%x: LED MODE FRONT PANEL OFF\n",
- params->port);
+ port);
if ((params->hw_led_mode << SHARED_HW_CFG_LED_MODE_SHIFT) ==
SHARED_HW_CFG_LED_EXTPHY1) {
@@ -6524,7 +9850,7 @@
break;
case LED_MODE_ON:
- DP(NETIF_MSG_LINK, "Port 0x%x: LED MODE ON\n", params->port);
+ DP(NETIF_MSG_LINK, "Port 0x%x: LED MODE ON\n", port);
if ((params->hw_led_mode << SHARED_HW_CFG_LED_MODE_SHIFT) ==
SHARED_HW_CFG_LED_EXTPHY1) {
@@ -6571,7 +9897,7 @@
case LED_MODE_OPER:
- DP(NETIF_MSG_LINK, "Port 0x%x: LED MODE OPER\n", params->port);
+ DP(NETIF_MSG_LINK, "Port 0x%x: LED MODE OPER\n", port);
if ((params->hw_led_mode << SHARED_HW_CFG_LED_MODE_SHIFT) ==
SHARED_HW_CFG_LED_EXTPHY1) {
@@ -6633,7 +9959,388 @@
}
break;
}
+
+ /*
+ * This is a workaround for E3+84833 until autoneg
+ * restart is fixed in f/w
+ */
+ if (CHIP_IS_E3(bp)) {
+ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_GP2_STATUS_GP_2_1, &val);
+ }
}
+
+/******************************************************************/
+/* 54618SE PHY SECTION */
+/******************************************************************/
+static int bnx2x_54618se_config_init(struct bnx2x_phy *phy,
+ struct link_params *params,
+ struct link_vars *vars)
+{
+ struct bnx2x *bp = params->bp;
+ u8 port;
+ u16 autoneg_val, an_1000_val, an_10_100_val, fc_val, temp;
+ u32 cfg_pin;
+
+ DP(NETIF_MSG_LINK, "54618SE cfg init\n");
+ usleep_range(1000, 1000);
+
+ /* This works with E3 only, no need to check the chip
+ before determining the port. */
+ port = params->port;
+
+ cfg_pin = (REG_RD(bp, params->shmem_base +
+ offsetof(struct shmem_region,
+ dev_info.port_hw_config[port].e3_cmn_pin_cfg)) &
+ PORT_HW_CFG_E3_PHY_RESET_MASK) >>
+ PORT_HW_CFG_E3_PHY_RESET_SHIFT;
+
+ /* Drive pin high to bring the GPHY out of reset. */
+ bnx2x_set_cfg_pin(bp, cfg_pin, 1);
+
+ /* wait for GPHY to reset */
+ msleep(50);
+
+ /* reset phy */
+ bnx2x_cl22_write(bp, phy,
+ MDIO_PMA_REG_CTRL, 0x8000);
+ bnx2x_wait_reset_complete(bp, phy, params);
+
+ /*wait for GPHY to reset */
+ msleep(50);
+
+ /* Configure LED4: set to INTR (0x6). */
+ /* Accessing shadow register 0xe. */
+ bnx2x_cl22_write(bp, phy,
+ MDIO_REG_GPHY_SHADOW,
+ MDIO_REG_GPHY_SHADOW_LED_SEL2);
+ bnx2x_cl22_read(bp, phy,
+ MDIO_REG_GPHY_SHADOW,
+ &temp);
+ temp &= ~(0xf << 4);
+ temp |= (0x6 << 4);
+ bnx2x_cl22_write(bp, phy,
+ MDIO_REG_GPHY_SHADOW,
+ MDIO_REG_GPHY_SHADOW_WR_ENA | temp);
+ /* Configure INTR based on link status change. */
+ bnx2x_cl22_write(bp, phy,
+ MDIO_REG_INTR_MASK,
+ ~MDIO_REG_INTR_MASK_LINK_STATUS);
+
+ /* Flip the signal detect polarity (set 0x1c.0x1e[8]). */
+ bnx2x_cl22_write(bp, phy,
+ MDIO_REG_GPHY_SHADOW,
+ MDIO_REG_GPHY_SHADOW_AUTO_DET_MED);
+ bnx2x_cl22_read(bp, phy,
+ MDIO_REG_GPHY_SHADOW,
+ &temp);
+ temp |= MDIO_REG_GPHY_SHADOW_INVERT_FIB_SD;
+ bnx2x_cl22_write(bp, phy,
+ MDIO_REG_GPHY_SHADOW,
+ MDIO_REG_GPHY_SHADOW_WR_ENA | temp);
+
+ /* Set up fc */
+ /* Please refer to Table 28B-3 of 802.3ab-1999 spec. */
+ bnx2x_calc_ieee_aneg_adv(phy, params, &vars->ieee_fc);
+ fc_val = 0;
+ if ((vars->ieee_fc & MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) ==
+ MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC)
+ fc_val |= MDIO_AN_REG_ADV_PAUSE_ASYMMETRIC;
+
+ if ((vars->ieee_fc & MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) ==
+ MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH)
+ fc_val |= MDIO_AN_REG_ADV_PAUSE_PAUSE;
+
+ /* read all advertisement */
+ bnx2x_cl22_read(bp, phy,
+ 0x09,
+ &an_1000_val);
+
+ bnx2x_cl22_read(bp, phy,
+ 0x04,
+ &an_10_100_val);
+
+ bnx2x_cl22_read(bp, phy,
+ MDIO_PMA_REG_CTRL,
+ &autoneg_val);
+
+ /* Disable forced speed */
+ autoneg_val &= ~((1<<6) | (1<<8) | (1<<9) | (1<<12) | (1<<13));
+ an_10_100_val &= ~((1<<5) | (1<<6) | (1<<7) | (1<<8) | (1<<10) |
+ (1<<11));
+
+ if (((phy->req_line_speed == SPEED_AUTO_NEG) &&
+ (phy->speed_cap_mask &
+ PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)) ||
+ (phy->req_line_speed == SPEED_1000)) {
+ an_1000_val |= (1<<8);
+ autoneg_val |= (1<<9 | 1<<12);
+ if (phy->req_duplex == DUPLEX_FULL)
+ an_1000_val |= (1<<9);
+ DP(NETIF_MSG_LINK, "Advertising 1G\n");
+ } else
+ an_1000_val &= ~((1<<8) | (1<<9));
+
+ bnx2x_cl22_write(bp, phy,
+ 0x09,
+ an_1000_val);
+ bnx2x_cl22_read(bp, phy,
+ 0x09,
+ &an_1000_val);
+
+ /* set 100 speed advertisement */
+ if (((phy->req_line_speed == SPEED_AUTO_NEG) &&
+ (phy->speed_cap_mask &
+ (PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_FULL |
+ PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_HALF)))) {
+ an_10_100_val |= (1<<7);
+ /* Enable autoneg and restart autoneg for legacy speeds */
+ autoneg_val |= (1<<9 | 1<<12);
+
+ if (phy->req_duplex == DUPLEX_FULL)
+ an_10_100_val |= (1<<8);
+ DP(NETIF_MSG_LINK, "Advertising 100M\n");
+ }
+
+ /* set 10 speed advertisement */
+ if (((phy->req_line_speed == SPEED_AUTO_NEG) &&
+ (phy->speed_cap_mask &
+ (PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_FULL |
+ PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_HALF)))) {
+ an_10_100_val |= (1<<5);
+ autoneg_val |= (1<<9 | 1<<12);
+ if (phy->req_duplex == DUPLEX_FULL)
+ an_10_100_val |= (1<<6);
+ DP(NETIF_MSG_LINK, "Advertising 10M\n");
+ }
+
+ /* Only 10/100 are allowed to work in FORCE mode */
+ if (phy->req_line_speed == SPEED_100) {
+ autoneg_val |= (1<<13);
+ /* Enabled AUTO-MDIX when autoneg is disabled */
+ bnx2x_cl22_write(bp, phy,
+ 0x18,
+ (1<<15 | 1<<9 | 7<<0));
+ DP(NETIF_MSG_LINK, "Setting 100M force\n");
+ }
+ if (phy->req_line_speed == SPEED_10) {
+ /* Enabled AUTO-MDIX when autoneg is disabled */
+ bnx2x_cl22_write(bp, phy,
+ 0x18,
+ (1<<15 | 1<<9 | 7<<0));
+ DP(NETIF_MSG_LINK, "Setting 10M force\n");
+ }
+
+ /* Check if we should turn on Auto-GrEEEn */
+ bnx2x_cl22_read(bp, phy, MDIO_REG_GPHY_PHYID_LSB, &temp);
+ if (temp == MDIO_REG_GPHY_ID_54618SE) {
+ if (params->feature_config_flags &
+ FEATURE_CONFIG_AUTOGREEEN_ENABLED) {
+ temp = 6;
+ DP(NETIF_MSG_LINK, "Enabling Auto-GrEEEn\n");
+ } else {
+ temp = 0;
+ DP(NETIF_MSG_LINK, "Disabling Auto-GrEEEn\n");
+ }
+ bnx2x_cl22_write(bp, phy,
+ MDIO_REG_GPHY_CL45_ADDR_REG, MDIO_AN_DEVAD);
+ bnx2x_cl22_write(bp, phy,
+ MDIO_REG_GPHY_CL45_DATA_REG,
+ MDIO_REG_GPHY_EEE_ADV);
+ bnx2x_cl22_write(bp, phy,
+ MDIO_REG_GPHY_CL45_ADDR_REG,
+ (0x1 << 14) | MDIO_AN_DEVAD);
+ bnx2x_cl22_write(bp, phy,
+ MDIO_REG_GPHY_CL45_DATA_REG,
+ temp);
+ }
+
+ bnx2x_cl22_write(bp, phy,
+ 0x04,
+ an_10_100_val | fc_val);
+
+ if (phy->req_duplex == DUPLEX_FULL)
+ autoneg_val |= (1<<8);
+
+ bnx2x_cl22_write(bp, phy,
+ MDIO_PMA_REG_CTRL, autoneg_val);
+
+ return 0;
+}
+
+static void bnx2x_54618se_set_link_led(struct bnx2x_phy *phy,
+ struct link_params *params, u8 mode)
+{
+ struct bnx2x *bp = params->bp;
+ DP(NETIF_MSG_LINK, "54618SE set link led (mode=%x)\n", mode);
+ switch (mode) {
+ case LED_MODE_FRONT_PANEL_OFF:
+ case LED_MODE_OFF:
+ case LED_MODE_OPER:
+ case LED_MODE_ON:
+ default:
+ break;
+ }
+ return;
+}
+
+static void bnx2x_54618se_link_reset(struct bnx2x_phy *phy,
+ struct link_params *params)
+{
+ struct bnx2x *bp = params->bp;
+ u32 cfg_pin;
+ u8 port;
+
+ /* This works with E3 only, no need to check the chip
+ before determining the port. */
+ port = params->port;
+ cfg_pin = (REG_RD(bp, params->shmem_base +
+ offsetof(struct shmem_region,
+ dev_info.port_hw_config[port].e3_cmn_pin_cfg)) &
+ PORT_HW_CFG_E3_PHY_RESET_MASK) >>
+ PORT_HW_CFG_E3_PHY_RESET_SHIFT;
+
+ /* Drive pin low to put GPHY in reset. */
+ bnx2x_set_cfg_pin(bp, cfg_pin, 0);
+}
+
+static u8 bnx2x_54618se_read_status(struct bnx2x_phy *phy,
+ struct link_params *params,
+ struct link_vars *vars)
+{
+ struct bnx2x *bp = params->bp;
+ u16 val;
+ u8 link_up = 0;
+ u16 legacy_status, legacy_speed;
+
+ /* Get speed operation status */
+ bnx2x_cl22_read(bp, phy,
+ 0x19,
+ &legacy_status);
+ DP(NETIF_MSG_LINK, "54618SE read_status: 0x%x\n", legacy_status);
+
+ /* Read status to clear the PHY interrupt. */
+ bnx2x_cl22_read(bp, phy,
+ MDIO_REG_INTR_STATUS,
+ &val);
+
+ link_up = ((legacy_status & (1<<2)) == (1<<2));
+
+ if (link_up) {
+ legacy_speed = (legacy_status & (7<<8));
+ if (legacy_speed == (7<<8)) {
+ vars->line_speed = SPEED_1000;
+ vars->duplex = DUPLEX_FULL;
+ } else if (legacy_speed == (6<<8)) {
+ vars->line_speed = SPEED_1000;
+ vars->duplex = DUPLEX_HALF;
+ } else if (legacy_speed == (5<<8)) {
+ vars->line_speed = SPEED_100;
+ vars->duplex = DUPLEX_FULL;
+ }
+ /* Omitting 100Base-T4 for now */
+ else if (legacy_speed == (3<<8)) {
+ vars->line_speed = SPEED_100;
+ vars->duplex = DUPLEX_HALF;
+ } else if (legacy_speed == (2<<8)) {
+ vars->line_speed = SPEED_10;
+ vars->duplex = DUPLEX_FULL;
+ } else if (legacy_speed == (1<<8)) {
+ vars->line_speed = SPEED_10;
+ vars->duplex = DUPLEX_HALF;
+ } else /* Should not happen */
+ vars->line_speed = 0;
+
+ DP(NETIF_MSG_LINK, "Link is up in %dMbps,"
+ " is_duplex_full= %d\n", vars->line_speed,
+ (vars->duplex == DUPLEX_FULL));
+
+ /* Check legacy speed AN resolution */
+ bnx2x_cl22_read(bp, phy,
+ 0x01,
+ &val);
+ if (val & (1<<5))
+ vars->link_status |=
+ LINK_STATUS_AUTO_NEGOTIATE_COMPLETE;
+ bnx2x_cl22_read(bp, phy,
+ 0x06,
+ &val);
+ if ((val & (1<<0)) == 0)
+ vars->link_status |=
+ LINK_STATUS_PARALLEL_DETECTION_USED;
+
+ DP(NETIF_MSG_LINK, "BCM54618SE: link speed is %d\n",
+ vars->line_speed);
+
+ /* Report whether EEE is resolved. */
+ bnx2x_cl22_read(bp, phy, MDIO_REG_GPHY_PHYID_LSB, &val);
+ if (val == MDIO_REG_GPHY_ID_54618SE) {
+ if (vars->link_status &
+ LINK_STATUS_AUTO_NEGOTIATE_COMPLETE)
+ val = 0;
+ else {
+ bnx2x_cl22_write(bp, phy,
+ MDIO_REG_GPHY_CL45_ADDR_REG,
+ MDIO_AN_DEVAD);
+ bnx2x_cl22_write(bp, phy,
+ MDIO_REG_GPHY_CL45_DATA_REG,
+ MDIO_REG_GPHY_EEE_RESOLVED);
+ bnx2x_cl22_write(bp, phy,
+ MDIO_REG_GPHY_CL45_ADDR_REG,
+ (0x1 << 14) | MDIO_AN_DEVAD);
+ bnx2x_cl22_read(bp, phy,
+ MDIO_REG_GPHY_CL45_DATA_REG,
+ &val);
+ }
+ DP(NETIF_MSG_LINK, "EEE resolution: 0x%x\n", val);
+ }
+
+ bnx2x_ext_phy_resolve_fc(phy, params, vars);
+ }
+ return link_up;
+}
+
+static void bnx2x_54618se_config_loopback(struct bnx2x_phy *phy,
+ struct link_params *params)
+{
+ struct bnx2x *bp = params->bp;
+ u16 val;
+ u32 umac_base = params->port ? GRCBASE_UMAC1 : GRCBASE_UMAC0;
+
+ DP(NETIF_MSG_LINK, "2PMA/PMD ext_phy_loopback: 54618se\n");
+
+ /* Enable master/slave manual mmode and set to master */
+ /* mii write 9 [bits set 11 12] */
+ bnx2x_cl22_write(bp, phy, 0x09, 3<<11);
+
+ /* forced 1G and disable autoneg */
+ /* set val [mii read 0] */
+ /* set val [expr $val & [bits clear 6 12 13]] */
+ /* set val [expr $val | [bits set 6 8]] */
+ /* mii write 0 $val */
+ bnx2x_cl22_read(bp, phy, 0x00, &val);
+ val &= ~((1<<6) | (1<<12) | (1<<13));
+ val |= (1<<6) | (1<<8);
+ bnx2x_cl22_write(bp, phy, 0x00, val);
+
+ /* Set external loopback and Tx using 6dB coding */
+ /* mii write 0x18 7 */
+ /* set val [mii read 0x18] */
+ /* mii write 0x18 [expr $val | [bits set 10 15]] */
+ bnx2x_cl22_write(bp, phy, 0x18, 7);
+ bnx2x_cl22_read(bp, phy, 0x18, &val);
+ bnx2x_cl22_write(bp, phy, 0x18, val | (1<<10) | (1<<15));
+
+ /* This register opens the gate for the UMAC despite its name */
+ REG_WR(bp, NIG_REG_EGRESS_EMAC0_PORT + params->port*4, 1);
+
+ /*
+ * Maximum Frame Length (RW). Defines a 14-Bit maximum frame
+ * length used by the MAC receive logic to check frames.
+ */
+ REG_WR(bp, umac_base + UMAC_REG_MAXFR, 0x2710);
+}
+
/******************************************************************/
/* SFX7101 PHY SECTION */
/******************************************************************/
@@ -6646,9 +10353,9 @@
MDIO_XS_DEVAD, MDIO_XS_SFX7101_XGXS_TEST1, 0x100);
}
-static u8 bnx2x_7101_config_init(struct bnx2x_phy *phy,
- struct link_params *params,
- struct link_vars *vars)
+static int bnx2x_7101_config_init(struct bnx2x_phy *phy,
+ struct link_params *params,
+ struct link_vars *vars)
{
u16 fw_ver1, fw_ver2, val;
struct bnx2x *bp = params->bp;
@@ -6662,7 +10369,7 @@
bnx2x_wait_reset_complete(bp, phy, params);
bnx2x_cl45_write(bp, phy,
- MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_CTRL, 0x1);
+ MDIO_PMA_DEVAD, MDIO_PMA_LASI_CTRL, 0x1);
DP(NETIF_MSG_LINK, "Setting the SFX7101 LED to blink on traffic\n");
bnx2x_cl45_write(bp, phy,
MDIO_PMA_DEVAD, MDIO_PMA_REG_7107_LED_CNTL, (1<<3));
@@ -6694,9 +10401,9 @@
u8 link_up;
u16 val1, val2;
bnx2x_cl45_read(bp, phy,
- MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_STATUS, &val2);
+ MDIO_PMA_DEVAD, MDIO_PMA_LASI_STAT, &val2);
bnx2x_cl45_read(bp, phy,
- MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_STATUS, &val1);
+ MDIO_PMA_DEVAD, MDIO_PMA_LASI_STAT, &val1);
DP(NETIF_MSG_LINK, "10G-base-T LASI status 0x%x->0x%x\n",
val2, val1);
bnx2x_cl45_read(bp, phy,
@@ -6721,8 +10428,7 @@
return link_up;
}
-
-static u8 bnx2x_7101_format_ver(u32 spirom_ver, u8 *str, u16 *len)
+static int bnx2x_7101_format_ver(u32 spirom_ver, u8 *str, u16 *len)
{
if (*len < 5)
return -EINVAL;
@@ -6800,9 +10506,8 @@
static struct bnx2x_phy phy_null = {
.type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN,
.addr = 0,
- .flags = FLAGS_INIT_XGXS_FIRST,
.def_md_devad = 0,
- .reserved = 0,
+ .flags = FLAGS_INIT_XGXS_FIRST,
.rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
.tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
.mdio_ctrl = 0,
@@ -6827,9 +10532,8 @@
static struct bnx2x_phy phy_serdes = {
.type = PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT,
.addr = 0xff,
- .flags = 0,
.def_md_devad = 0,
- .reserved = 0,
+ .flags = 0,
.rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
.tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
.mdio_ctrl = 0,
@@ -6843,14 +10547,14 @@
SUPPORTED_Autoneg |
SUPPORTED_Pause |
SUPPORTED_Asym_Pause),
- .media_type = ETH_PHY_UNSPECIFIED,
+ .media_type = ETH_PHY_BASE_T,
.ver_addr = 0,
.req_flow_ctrl = 0,
.req_line_speed = 0,
.speed_cap_mask = 0,
.req_duplex = 0,
.rsrv = 0,
- .config_init = (config_init_t)bnx2x_init_serdes,
+ .config_init = (config_init_t)bnx2x_xgxs_config_init,
.read_status = (read_status_t)bnx2x_link_settings_status,
.link_reset = (link_reset_t)bnx2x_int_link_reset,
.config_loopback = (config_loopback_t)NULL,
@@ -6863,9 +10567,8 @@
static struct bnx2x_phy phy_xgxs = {
.type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT,
.addr = 0xff,
- .flags = 0,
.def_md_devad = 0,
- .reserved = 0,
+ .flags = 0,
.rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
.tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
.mdio_ctrl = 0,
@@ -6880,14 +10583,14 @@
SUPPORTED_Autoneg |
SUPPORTED_Pause |
SUPPORTED_Asym_Pause),
- .media_type = ETH_PHY_UNSPECIFIED,
+ .media_type = ETH_PHY_CX4,
.ver_addr = 0,
.req_flow_ctrl = 0,
.req_line_speed = 0,
.speed_cap_mask = 0,
.req_duplex = 0,
.rsrv = 0,
- .config_init = (config_init_t)bnx2x_init_xgxs,
+ .config_init = (config_init_t)bnx2x_xgxs_config_init,
.read_status = (read_status_t)bnx2x_link_settings_status,
.link_reset = (link_reset_t)bnx2x_int_link_reset,
.config_loopback = (config_loopback_t)bnx2x_set_xgxs_loopback,
@@ -6896,13 +10599,49 @@
.set_link_led = (set_link_led_t)NULL,
.phy_specific_func = (phy_specific_func_t)NULL
};
+static struct bnx2x_phy phy_warpcore = {
+ .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT,
+ .addr = 0xff,
+ .def_md_devad = 0,
+ .flags = FLAGS_HW_LOCK_REQUIRED,
+ .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
+ .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
+ .mdio_ctrl = 0,
+ .supported = (SUPPORTED_10baseT_Half |
+ SUPPORTED_10baseT_Full |
+ SUPPORTED_100baseT_Half |
+ SUPPORTED_100baseT_Full |
+ SUPPORTED_1000baseT_Full |
+ SUPPORTED_10000baseT_Full |
+ SUPPORTED_20000baseKR2_Full |
+ SUPPORTED_20000baseMLD2_Full |
+ SUPPORTED_FIBRE |
+ SUPPORTED_Autoneg |
+ SUPPORTED_Pause |
+ SUPPORTED_Asym_Pause),
+ .media_type = ETH_PHY_UNSPECIFIED,
+ .ver_addr = 0,
+ .req_flow_ctrl = 0,
+ .req_line_speed = 0,
+ .speed_cap_mask = 0,
+ /* req_duplex = */0,
+ /* rsrv = */0,
+ .config_init = (config_init_t)bnx2x_warpcore_config_init,
+ .read_status = (read_status_t)bnx2x_warpcore_read_status,
+ .link_reset = (link_reset_t)bnx2x_warpcore_link_reset,
+ .config_loopback = (config_loopback_t)bnx2x_set_warpcore_loopback,
+ .format_fw_ver = (format_fw_ver_t)NULL,
+ .hw_reset = (hw_reset_t)bnx2x_warpcore_hw_reset,
+ .set_link_led = (set_link_led_t)NULL,
+ .phy_specific_func = (phy_specific_func_t)NULL
+};
+
static struct bnx2x_phy phy_7101 = {
.type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
.addr = 0xff,
- .flags = FLAGS_FAN_FAILURE_DET_REQ,
.def_md_devad = 0,
- .reserved = 0,
+ .flags = FLAGS_FAN_FAILURE_DET_REQ,
.rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
.tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
.mdio_ctrl = 0,
@@ -6930,9 +10669,8 @@
static struct bnx2x_phy phy_8073 = {
.type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
.addr = 0xff,
- .flags = FLAGS_HW_LOCK_REQUIRED,
.def_md_devad = 0,
- .reserved = 0,
+ .flags = FLAGS_HW_LOCK_REQUIRED,
.rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
.tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
.mdio_ctrl = 0,
@@ -6943,7 +10681,7 @@
SUPPORTED_Autoneg |
SUPPORTED_Pause |
SUPPORTED_Asym_Pause),
- .media_type = ETH_PHY_UNSPECIFIED,
+ .media_type = ETH_PHY_KR,
.ver_addr = 0,
.req_flow_ctrl = 0,
.req_line_speed = 0,
@@ -6962,9 +10700,8 @@
static struct bnx2x_phy phy_8705 = {
.type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705,
.addr = 0xff,
- .flags = FLAGS_INIT_XGXS_FIRST,
.def_md_devad = 0,
- .reserved = 0,
+ .flags = FLAGS_INIT_XGXS_FIRST,
.rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
.tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
.mdio_ctrl = 0,
@@ -6991,9 +10728,8 @@
static struct bnx2x_phy phy_8706 = {
.type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706,
.addr = 0xff,
- .flags = FLAGS_INIT_XGXS_FIRST,
.def_md_devad = 0,
- .reserved = 0,
+ .flags = FLAGS_INIT_XGXS_FIRST,
.rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
.tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
.mdio_ctrl = 0,
@@ -7022,10 +10758,9 @@
static struct bnx2x_phy phy_8726 = {
.type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726,
.addr = 0xff,
+ .def_md_devad = 0,
.flags = (FLAGS_HW_LOCK_REQUIRED |
FLAGS_INIT_XGXS_FIRST),
- .def_md_devad = 0,
- .reserved = 0,
.rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
.tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
.mdio_ctrl = 0,
@@ -7035,7 +10770,7 @@
SUPPORTED_FIBRE |
SUPPORTED_Pause |
SUPPORTED_Asym_Pause),
- .media_type = ETH_PHY_SFP_FIBER,
+ .media_type = ETH_PHY_NOT_PRESENT,
.ver_addr = 0,
.req_flow_ctrl = 0,
.req_line_speed = 0,
@@ -7055,9 +10790,8 @@
static struct bnx2x_phy phy_8727 = {
.type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727,
.addr = 0xff,
- .flags = FLAGS_FAN_FAILURE_DET_REQ,
.def_md_devad = 0,
- .reserved = 0,
+ .flags = FLAGS_FAN_FAILURE_DET_REQ,
.rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
.tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
.mdio_ctrl = 0,
@@ -7066,7 +10800,7 @@
SUPPORTED_FIBRE |
SUPPORTED_Pause |
SUPPORTED_Asym_Pause),
- .media_type = ETH_PHY_SFP_FIBER,
+ .media_type = ETH_PHY_NOT_PRESENT,
.ver_addr = 0,
.req_flow_ctrl = 0,
.req_line_speed = 0,
@@ -7085,10 +10819,9 @@
static struct bnx2x_phy phy_8481 = {
.type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481,
.addr = 0xff,
+ .def_md_devad = 0,
.flags = FLAGS_FAN_FAILURE_DET_REQ |
FLAGS_REARM_LATCH_SIGNAL,
- .def_md_devad = 0,
- .reserved = 0,
.rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
.tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
.mdio_ctrl = 0,
@@ -7122,10 +10855,9 @@
static struct bnx2x_phy phy_84823 = {
.type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823,
.addr = 0xff,
+ .def_md_devad = 0,
.flags = FLAGS_FAN_FAILURE_DET_REQ |
FLAGS_REARM_LATCH_SIGNAL,
- .def_md_devad = 0,
- .reserved = 0,
.rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
.tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
.mdio_ctrl = 0,
@@ -7159,16 +10891,13 @@
static struct bnx2x_phy phy_84833 = {
.type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833,
.addr = 0xff,
+ .def_md_devad = 0,
.flags = FLAGS_FAN_FAILURE_DET_REQ |
FLAGS_REARM_LATCH_SIGNAL,
- .def_md_devad = 0,
- .reserved = 0,
.rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
.tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
.mdio_ctrl = 0,
- .supported = (SUPPORTED_10baseT_Half |
- SUPPORTED_10baseT_Full |
- SUPPORTED_100baseT_Half |
+ .supported = (SUPPORTED_100baseT_Half |
SUPPORTED_100baseT_Full |
SUPPORTED_1000baseT_Full |
SUPPORTED_10000baseT_Full |
@@ -7188,11 +10917,44 @@
.link_reset = (link_reset_t)bnx2x_848x3_link_reset,
.config_loopback = (config_loopback_t)NULL,
.format_fw_ver = (format_fw_ver_t)bnx2x_848xx_format_ver,
- .hw_reset = (hw_reset_t)NULL,
+ .hw_reset = (hw_reset_t)bnx2x_84833_hw_reset_phy,
.set_link_led = (set_link_led_t)bnx2x_848xx_set_link_led,
.phy_specific_func = (phy_specific_func_t)NULL
};
+static struct bnx2x_phy phy_54618se = {
+ .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM54618SE,
+ .addr = 0xff,
+ .def_md_devad = 0,
+ .flags = FLAGS_INIT_XGXS_FIRST,
+ .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
+ .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
+ .mdio_ctrl = 0,
+ .supported = (SUPPORTED_10baseT_Half |
+ SUPPORTED_10baseT_Full |
+ SUPPORTED_100baseT_Half |
+ SUPPORTED_100baseT_Full |
+ SUPPORTED_1000baseT_Full |
+ SUPPORTED_TP |
+ SUPPORTED_Autoneg |
+ SUPPORTED_Pause |
+ SUPPORTED_Asym_Pause),
+ .media_type = ETH_PHY_BASE_T,
+ .ver_addr = 0,
+ .req_flow_ctrl = 0,
+ .req_line_speed = 0,
+ .speed_cap_mask = 0,
+ /* req_duplex = */0,
+ /* rsrv = */0,
+ .config_init = (config_init_t)bnx2x_54618se_config_init,
+ .read_status = (read_status_t)bnx2x_54618se_read_status,
+ .link_reset = (link_reset_t)bnx2x_54618se_link_reset,
+ .config_loopback = (config_loopback_t)bnx2x_54618se_config_loopback,
+ .format_fw_ver = (format_fw_ver_t)NULL,
+ .hw_reset = (hw_reset_t)NULL,
+ .set_link_led = (set_link_led_t)bnx2x_54618se_set_link_led,
+ .phy_specific_func = (phy_specific_func_t)NULL
+};
/*****************************************************************/
/* */
/* Populate the phy according. Main function: bnx2x_populate_phy */
@@ -7259,8 +11021,8 @@
return ext_phy_config;
}
-static u8 bnx2x_populate_int_phy(struct bnx2x *bp, u32 shmem_base, u8 port,
- struct bnx2x_phy *phy)
+static int bnx2x_populate_int_phy(struct bnx2x *bp, u32 shmem_base, u8 port,
+ struct bnx2x_phy *phy)
{
u32 phy_addr;
u32 chip_id;
@@ -7269,22 +11031,105 @@
dev_info.port_feature_config[port].link_config)) &
PORT_FEATURE_CONNECTED_SWITCH_MASK);
chip_id = REG_RD(bp, MISC_REG_CHIP_NUM) << 16;
- switch (switch_cfg) {
- case SWITCH_CFG_1G:
+ DP(NETIF_MSG_LINK, ":chip_id = 0x%x\n", chip_id);
+ if (USES_WARPCORE(bp)) {
+ u32 serdes_net_if;
phy_addr = REG_RD(bp,
- NIG_REG_SERDES0_CTRL_PHY_ADDR +
- port * 0x10);
- *phy = phy_serdes;
- break;
- case SWITCH_CFG_10G:
- phy_addr = REG_RD(bp,
- NIG_REG_XGXS0_CTRL_PHY_ADDR +
- port * 0x18);
- *phy = phy_xgxs;
- break;
- default:
- DP(NETIF_MSG_LINK, "Invalid switch_cfg\n");
- return -EINVAL;
+ MISC_REG_WC0_CTRL_PHY_ADDR);
+ *phy = phy_warpcore;
+ if (REG_RD(bp, MISC_REG_PORT4MODE_EN_OVWR) == 0x3)
+ phy->flags |= FLAGS_4_PORT_MODE;
+ else
+ phy->flags &= ~FLAGS_4_PORT_MODE;
+ /* Check Dual mode */
+ serdes_net_if = (REG_RD(bp, shmem_base +
+ offsetof(struct shmem_region, dev_info.
+ port_hw_config[port].default_cfg)) &
+ PORT_HW_CFG_NET_SERDES_IF_MASK);
+ /*
+ * Set the appropriate supported and flags indications per
+ * interface type of the chip
+ */
+ switch (serdes_net_if) {
+ case PORT_HW_CFG_NET_SERDES_IF_SGMII:
+ phy->supported &= (SUPPORTED_10baseT_Half |
+ SUPPORTED_10baseT_Full |
+ SUPPORTED_100baseT_Half |
+ SUPPORTED_100baseT_Full |
+ SUPPORTED_1000baseT_Full |
+ SUPPORTED_FIBRE |
+ SUPPORTED_Autoneg |
+ SUPPORTED_Pause |
+ SUPPORTED_Asym_Pause);
+ phy->media_type = ETH_PHY_BASE_T;
+ break;
+ case PORT_HW_CFG_NET_SERDES_IF_XFI:
+ phy->media_type = ETH_PHY_XFP_FIBER;
+ break;
+ case PORT_HW_CFG_NET_SERDES_IF_SFI:
+ phy->supported &= (SUPPORTED_1000baseT_Full |
+ SUPPORTED_10000baseT_Full |
+ SUPPORTED_FIBRE |
+ SUPPORTED_Pause |
+ SUPPORTED_Asym_Pause);
+ phy->media_type = ETH_PHY_SFP_FIBER;
+ break;
+ case PORT_HW_CFG_NET_SERDES_IF_KR:
+ phy->media_type = ETH_PHY_KR;
+ phy->supported &= (SUPPORTED_1000baseT_Full |
+ SUPPORTED_10000baseT_Full |
+ SUPPORTED_FIBRE |
+ SUPPORTED_Autoneg |
+ SUPPORTED_Pause |
+ SUPPORTED_Asym_Pause);
+ break;
+ case PORT_HW_CFG_NET_SERDES_IF_DXGXS:
+ phy->media_type = ETH_PHY_KR;
+ phy->flags |= FLAGS_WC_DUAL_MODE;
+ phy->supported &= (SUPPORTED_20000baseMLD2_Full |
+ SUPPORTED_FIBRE |
+ SUPPORTED_Pause |
+ SUPPORTED_Asym_Pause);
+ break;
+ case PORT_HW_CFG_NET_SERDES_IF_KR2:
+ phy->media_type = ETH_PHY_KR;
+ phy->flags |= FLAGS_WC_DUAL_MODE;
+ phy->supported &= (SUPPORTED_20000baseKR2_Full |
+ SUPPORTED_FIBRE |
+ SUPPORTED_Pause |
+ SUPPORTED_Asym_Pause);
+ break;
+ default:
+ DP(NETIF_MSG_LINK, "Unknown WC interface type 0x%x\n",
+ serdes_net_if);
+ break;
+ }
+
+ /*
+ * Enable MDC/MDIO work-around for E3 A0 since free running MDC
+ * was not set as expected. For B0, ECO will be enabled so there
+ * won't be an issue there
+ */
+ if (CHIP_REV(bp) == CHIP_REV_Ax)
+ phy->flags |= FLAGS_MDC_MDIO_WA;
+ } else {
+ switch (switch_cfg) {
+ case SWITCH_CFG_1G:
+ phy_addr = REG_RD(bp,
+ NIG_REG_SERDES0_CTRL_PHY_ADDR +
+ port * 0x10);
+ *phy = phy_serdes;
+ break;
+ case SWITCH_CFG_10G:
+ phy_addr = REG_RD(bp,
+ NIG_REG_XGXS0_CTRL_PHY_ADDR +
+ port * 0x18);
+ *phy = phy_xgxs;
+ break;
+ default:
+ DP(NETIF_MSG_LINK, "Invalid switch_cfg\n");
+ return -EINVAL;
+ }
}
phy->addr = (u8)phy_addr;
phy->mdio_ctrl = bnx2x_get_emac_base(bp,
@@ -7302,12 +11147,12 @@
return 0;
}
-static u8 bnx2x_populate_ext_phy(struct bnx2x *bp,
- u8 phy_index,
- u32 shmem_base,
- u32 shmem2_base,
- u8 port,
- struct bnx2x_phy *phy)
+static int bnx2x_populate_ext_phy(struct bnx2x *bp,
+ u8 phy_index,
+ u32 shmem_base,
+ u32 shmem2_base,
+ u8 port,
+ struct bnx2x_phy *phy)
{
u32 ext_phy_config, phy_type, config2;
u32 mdc_mdio_access = SHARED_HW_CFG_MDC_MDIO_ACCESS1_BOTH;
@@ -7336,6 +11181,7 @@
*phy = phy_8727;
phy->flags |= FLAGS_NOC;
break;
+ case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8722:
case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
mdc_mdio_access = SHARED_HW_CFG_MDC_MDIO_ACCESS1_EMAC1;
*phy = phy_8727;
@@ -7349,6 +11195,9 @@
case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833:
*phy = phy_84833;
break;
+ case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM54618SE:
+ *phy = phy_54618se;
+ break;
case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
*phy = phy_7101;
break;
@@ -7410,10 +11259,10 @@
return 0;
}
-static u8 bnx2x_populate_phy(struct bnx2x *bp, u8 phy_index, u32 shmem_base,
- u32 shmem2_base, u8 port, struct bnx2x_phy *phy)
+static int bnx2x_populate_phy(struct bnx2x *bp, u8 phy_index, u32 shmem_base,
+ u32 shmem2_base, u8 port, struct bnx2x_phy *phy)
{
- u8 status = 0;
+ int status = 0;
phy->type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN;
if (phy_index == INT_PHY)
return bnx2x_populate_int_phy(bp, shmem_base, port, phy);
@@ -7527,10 +11376,10 @@
}
-u8 bnx2x_phy_probe(struct link_params *params)
+int bnx2x_phy_probe(struct link_params *params)
{
u8 phy_index, actual_phy_idx, link_cfg_idx;
- u32 phy_config_swapped;
+ u32 phy_config_swapped, sync_offset, media_types;
struct bnx2x *bp = params->bp;
struct bnx2x_phy *phy;
params->num_phys = 0;
@@ -7567,6 +11416,26 @@
if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN)
break;
+ sync_offset = params->shmem_base +
+ offsetof(struct shmem_region,
+ dev_info.port_hw_config[params->port].media_type);
+ media_types = REG_RD(bp, sync_offset);
+
+ /*
+ * Update media type for non-PMF sync only for the first time
+ * In case the media type changes afterwards, it will be updated
+ * using the update_status function
+ */
+ if ((media_types & (PORT_HW_CFG_MEDIA_TYPE_PHY0_MASK <<
+ (PORT_HW_CFG_MEDIA_TYPE_PHY1_SHIFT *
+ actual_phy_idx))) == 0) {
+ media_types |= ((phy->media_type &
+ PORT_HW_CFG_MEDIA_TYPE_PHY0_MASK) <<
+ (PORT_HW_CFG_MEDIA_TYPE_PHY1_SHIFT *
+ actual_phy_idx));
+ }
+ REG_WR(bp, sync_offset, media_types);
+
bnx2x_phy_def_cfg(params, phy, phy_index);
params->num_phys++;
}
@@ -7575,43 +11444,141 @@
return 0;
}
-static void set_phy_vars(struct link_params *params)
+void bnx2x_init_bmac_loopback(struct link_params *params,
+ struct link_vars *vars)
{
struct bnx2x *bp = params->bp;
- u8 actual_phy_idx, phy_index, link_cfg_idx;
- u8 phy_config_swapped = params->multi_phy_config &
- PORT_HW_CFG_PHY_SWAPPED_ENABLED;
- for (phy_index = INT_PHY; phy_index < params->num_phys;
- phy_index++) {
- link_cfg_idx = LINK_CONFIG_IDX(phy_index);
- actual_phy_idx = phy_index;
- if (phy_config_swapped) {
- if (phy_index == EXT_PHY1)
- actual_phy_idx = EXT_PHY2;
- else if (phy_index == EXT_PHY2)
- actual_phy_idx = EXT_PHY1;
- }
- params->phy[actual_phy_idx].req_flow_ctrl =
- params->req_flow_ctrl[link_cfg_idx];
+ vars->link_up = 1;
+ vars->line_speed = SPEED_10000;
+ vars->duplex = DUPLEX_FULL;
+ vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
+ vars->mac_type = MAC_TYPE_BMAC;
- params->phy[actual_phy_idx].req_line_speed =
- params->req_line_speed[link_cfg_idx];
+ vars->phy_flags = PHY_XGXS_FLAG;
- params->phy[actual_phy_idx].speed_cap_mask =
- params->speed_cap_mask[link_cfg_idx];
+ bnx2x_xgxs_deassert(params);
- params->phy[actual_phy_idx].req_duplex =
- params->req_duplex[link_cfg_idx];
+ /* set bmac loopback */
+ bnx2x_bmac_enable(params, vars, 1);
- DP(NETIF_MSG_LINK, "req_flow_ctrl %x, req_line_speed %x,"
- " speed_cap_mask %x\n",
- params->phy[actual_phy_idx].req_flow_ctrl,
- params->phy[actual_phy_idx].req_line_speed,
- params->phy[actual_phy_idx].speed_cap_mask);
- }
+ REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4, 0);
}
-u8 bnx2x_phy_init(struct link_params *params, struct link_vars *vars)
+void bnx2x_init_emac_loopback(struct link_params *params,
+ struct link_vars *vars)
+{
+ struct bnx2x *bp = params->bp;
+ vars->link_up = 1;
+ vars->line_speed = SPEED_1000;
+ vars->duplex = DUPLEX_FULL;
+ vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
+ vars->mac_type = MAC_TYPE_EMAC;
+
+ vars->phy_flags = PHY_XGXS_FLAG;
+
+ bnx2x_xgxs_deassert(params);
+ /* set bmac loopback */
+ bnx2x_emac_enable(params, vars, 1);
+ bnx2x_emac_program(params, vars);
+ REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4, 0);
+}
+
+void bnx2x_init_xmac_loopback(struct link_params *params,
+ struct link_vars *vars)
+{
+ struct bnx2x *bp = params->bp;
+ vars->link_up = 1;
+ if (!params->req_line_speed[0])
+ vars->line_speed = SPEED_10000;
+ else
+ vars->line_speed = params->req_line_speed[0];
+ vars->duplex = DUPLEX_FULL;
+ vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
+ vars->mac_type = MAC_TYPE_XMAC;
+ vars->phy_flags = PHY_XGXS_FLAG;
+ /*
+ * Set WC to loopback mode since link is required to provide clock
+ * to the XMAC in 20G mode
+ */
+ if (vars->line_speed == SPEED_20000) {
+ bnx2x_set_aer_mmd(params, ¶ms->phy[0]);
+ bnx2x_warpcore_reset_lane(bp, ¶ms->phy[0], 0);
+ params->phy[INT_PHY].config_loopback(
+ ¶ms->phy[INT_PHY],
+ params);
+ }
+ bnx2x_xmac_enable(params, vars, 1);
+ REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4, 0);
+}
+
+void bnx2x_init_umac_loopback(struct link_params *params,
+ struct link_vars *vars)
+{
+ struct bnx2x *bp = params->bp;
+ vars->link_up = 1;
+ vars->line_speed = SPEED_1000;
+ vars->duplex = DUPLEX_FULL;
+ vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
+ vars->mac_type = MAC_TYPE_UMAC;
+ vars->phy_flags = PHY_XGXS_FLAG;
+ bnx2x_umac_enable(params, vars, 1);
+
+ REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4, 0);
+}
+
+void bnx2x_init_xgxs_loopback(struct link_params *params,
+ struct link_vars *vars)
+{
+ struct bnx2x *bp = params->bp;
+ vars->link_up = 1;
+ vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
+ vars->duplex = DUPLEX_FULL;
+ if (params->req_line_speed[0] == SPEED_1000)
+ vars->line_speed = SPEED_1000;
+ else
+ vars->line_speed = SPEED_10000;
+
+ if (!USES_WARPCORE(bp))
+ bnx2x_xgxs_deassert(params);
+ bnx2x_link_initialize(params, vars);
+
+ if (params->req_line_speed[0] == SPEED_1000) {
+ if (USES_WARPCORE(bp))
+ bnx2x_umac_enable(params, vars, 0);
+ else {
+ bnx2x_emac_program(params, vars);
+ bnx2x_emac_enable(params, vars, 0);
+ }
+ } else {
+ if (USES_WARPCORE(bp))
+ bnx2x_xmac_enable(params, vars, 0);
+ else
+ bnx2x_bmac_enable(params, vars, 0);
+ }
+
+ if (params->loopback_mode == LOOPBACK_XGXS) {
+ /* set 10G XGXS loopback */
+ params->phy[INT_PHY].config_loopback(
+ ¶ms->phy[INT_PHY],
+ params);
+
+ } else {
+ /* set external phy loopback */
+ u8 phy_index;
+ for (phy_index = EXT_PHY1;
+ phy_index < params->num_phys; phy_index++) {
+ if (params->phy[phy_index].config_loopback)
+ params->phy[phy_index].config_loopback(
+ ¶ms->phy[phy_index],
+ params);
+ }
+ }
+ REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4, 0);
+
+ bnx2x_set_led(params, vars, LED_MODE_OPER, vars->line_speed);
+}
+
+int bnx2x_phy_init(struct link_params *params, struct link_vars *vars)
{
struct bnx2x *bp = params->bp;
DP(NETIF_MSG_LINK, "Phy Initialization started\n");
@@ -7641,101 +11608,43 @@
DP(NETIF_MSG_LINK, "No phy found for initialization !!\n");
return -EINVAL;
}
- set_phy_vars(params);
+ set_phy_vars(params, vars);
DP(NETIF_MSG_LINK, "Num of phys on board: %d\n", params->num_phys);
- if (params->loopback_mode == LOOPBACK_BMAC) {
-
- vars->link_up = 1;
- vars->line_speed = SPEED_10000;
- vars->duplex = DUPLEX_FULL;
- vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
- vars->mac_type = MAC_TYPE_BMAC;
-
- vars->phy_flags = PHY_XGXS_FLAG;
-
- bnx2x_xgxs_deassert(params);
-
- /* set bmac loopback */
- bnx2x_bmac_enable(params, vars, 1);
-
- REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4, 0);
-
- } else if (params->loopback_mode == LOOPBACK_EMAC) {
-
- vars->link_up = 1;
- vars->line_speed = SPEED_1000;
- vars->duplex = DUPLEX_FULL;
- vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
- vars->mac_type = MAC_TYPE_EMAC;
-
- vars->phy_flags = PHY_XGXS_FLAG;
-
- bnx2x_xgxs_deassert(params);
- /* set bmac loopback */
- bnx2x_emac_enable(params, vars, 1);
- bnx2x_emac_program(params, vars);
- REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4, 0);
-
- } else if ((params->loopback_mode == LOOPBACK_XGXS) ||
- (params->loopback_mode == LOOPBACK_EXT_PHY)) {
-
- vars->link_up = 1;
- vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
- vars->duplex = DUPLEX_FULL;
- if (params->req_line_speed[0] == SPEED_1000) {
- vars->line_speed = SPEED_1000;
- vars->mac_type = MAC_TYPE_EMAC;
- } else {
- vars->line_speed = SPEED_10000;
- vars->mac_type = MAC_TYPE_BMAC;
+ switch (params->loopback_mode) {
+ case LOOPBACK_BMAC:
+ bnx2x_init_bmac_loopback(params, vars);
+ break;
+ case LOOPBACK_EMAC:
+ bnx2x_init_emac_loopback(params, vars);
+ break;
+ case LOOPBACK_XMAC:
+ bnx2x_init_xmac_loopback(params, vars);
+ break;
+ case LOOPBACK_UMAC:
+ bnx2x_init_umac_loopback(params, vars);
+ break;
+ case LOOPBACK_XGXS:
+ case LOOPBACK_EXT_PHY:
+ bnx2x_init_xgxs_loopback(params, vars);
+ break;
+ default:
+ if (!CHIP_IS_E3(bp)) {
+ if (params->switch_cfg == SWITCH_CFG_10G)
+ bnx2x_xgxs_deassert(params);
+ else
+ bnx2x_serdes_deassert(bp, params->port);
}
-
- bnx2x_xgxs_deassert(params);
- bnx2x_link_initialize(params, vars);
-
- if (params->req_line_speed[0] == SPEED_1000) {
- bnx2x_emac_program(params, vars);
- bnx2x_emac_enable(params, vars, 0);
- } else
- bnx2x_bmac_enable(params, vars, 0);
- if (params->loopback_mode == LOOPBACK_XGXS) {
- /* set 10G XGXS loopback */
- params->phy[INT_PHY].config_loopback(
- ¶ms->phy[INT_PHY],
- params);
-
- } else {
- /* set external phy loopback */
- u8 phy_index;
- for (phy_index = EXT_PHY1;
- phy_index < params->num_phys; phy_index++) {
- if (params->phy[phy_index].config_loopback)
- params->phy[phy_index].config_loopback(
- ¶ms->phy[phy_index],
- params);
- }
- }
- REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4, 0);
-
- bnx2x_set_led(params, vars,
- LED_MODE_OPER, vars->line_speed);
- } else
- /* No loopback */
- {
- if (params->switch_cfg == SWITCH_CFG_10G)
- bnx2x_xgxs_deassert(params);
- else
- bnx2x_serdes_deassert(bp, params->port);
-
bnx2x_link_initialize(params, vars);
msleep(30);
bnx2x_link_int_enable(params);
+ break;
}
return 0;
}
-u8 bnx2x_link_reset(struct link_params *params, struct link_vars *vars,
- u8 reset_ext_phy)
+
+int bnx2x_link_reset(struct link_params *params, struct link_vars *vars,
+ u8 reset_ext_phy)
{
struct bnx2x *bp = params->bp;
u8 phy_index, port = params->port, clear_latch_ind = 0;
@@ -7753,14 +11662,19 @@
REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + port*4, 1);
/* disable nig egress interface */
- REG_WR(bp, NIG_REG_BMAC0_OUT_EN + port*4, 0);
- REG_WR(bp, NIG_REG_EGRESS_EMAC0_OUT_EN + port*4, 0);
+ if (!CHIP_IS_E3(bp)) {
+ REG_WR(bp, NIG_REG_BMAC0_OUT_EN + port*4, 0);
+ REG_WR(bp, NIG_REG_EGRESS_EMAC0_OUT_EN + port*4, 0);
+ }
/* Stop BigMac rx */
- bnx2x_bmac_rx_disable(bp, port);
-
+ if (!CHIP_IS_E3(bp))
+ bnx2x_bmac_rx_disable(bp, port);
+ else
+ bnx2x_xmac_disable(params);
/* disable emac */
- REG_WR(bp, NIG_REG_NIG_EMAC0_EN + port*4, 0);
+ if (!CHIP_IS_E3(bp))
+ REG_WR(bp, NIG_REG_NIG_EMAC0_EN + port*4, 0);
msleep(10);
/* The PHY reset is controlled by GPIO 1
@@ -7796,21 +11710,22 @@
(MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port));
/* disable nig ingress interface */
- REG_WR(bp, NIG_REG_BMAC0_IN_EN + port*4, 0);
- REG_WR(bp, NIG_REG_EMAC0_IN_EN + port*4, 0);
- REG_WR(bp, NIG_REG_BMAC0_OUT_EN + port*4, 0);
- REG_WR(bp, NIG_REG_EGRESS_EMAC0_OUT_EN + port*4, 0);
+ if (!CHIP_IS_E3(bp)) {
+ REG_WR(bp, NIG_REG_BMAC0_IN_EN + port*4, 0);
+ REG_WR(bp, NIG_REG_EMAC0_IN_EN + port*4, 0);
+ }
vars->link_up = 0;
+ vars->phy_flags = 0;
return 0;
}
/****************************************************************************/
/* Common function */
/****************************************************************************/
-static u8 bnx2x_8073_common_init_phy(struct bnx2x *bp,
- u32 shmem_base_path[],
- u32 shmem2_base_path[], u8 phy_index,
- u32 chip_id)
+static int bnx2x_8073_common_init_phy(struct bnx2x *bp,
+ u32 shmem_base_path[],
+ u32 shmem2_base_path[], u8 phy_index,
+ u32 chip_id)
{
struct bnx2x_phy phy[PORT_MAX];
struct bnx2x_phy *phy_blk[PORT_MAX];
@@ -7826,14 +11741,14 @@
for (port = PORT_MAX - 1; port >= PORT_0; port--) {
u32 shmem_base, shmem2_base;
/* In E2, same phy is using for port0 of the two paths */
- if (CHIP_IS_E2(bp)) {
- shmem_base = shmem_base_path[port];
- shmem2_base = shmem2_base_path[port];
- port_of_path = 0;
- } else {
+ if (CHIP_IS_E1x(bp)) {
shmem_base = shmem_base_path[0];
shmem2_base = shmem2_base_path[0];
port_of_path = port;
+ } else {
+ shmem_base = shmem_base_path[port];
+ shmem2_base = shmem2_base_path[port];
+ port_of_path = 0;
}
/* Extract the ext phy address for the port */
@@ -7877,10 +11792,10 @@
/* PART2 - Download firmware to both phys */
for (port = PORT_MAX - 1; port >= PORT_0; port--) {
- if (CHIP_IS_E2(bp))
- port_of_path = 0;
- else
+ if (CHIP_IS_E1x(bp))
port_of_path = port;
+ else
+ port_of_path = 0;
DP(NETIF_MSG_LINK, "Loading spirom for phy address 0x%x\n",
phy_blk[port]->addr);
@@ -7933,10 +11848,10 @@
}
return 0;
}
-static u8 bnx2x_8726_common_init_phy(struct bnx2x *bp,
- u32 shmem_base_path[],
- u32 shmem2_base_path[], u8 phy_index,
- u32 chip_id)
+static int bnx2x_8726_common_init_phy(struct bnx2x *bp,
+ u32 shmem_base_path[],
+ u32 shmem2_base_path[], u8 phy_index,
+ u32 chip_id)
{
u32 val;
s8 port;
@@ -7954,12 +11869,12 @@
u32 shmem_base, shmem2_base;
/* In E2, same phy is using for port0 of the two paths */
- if (CHIP_IS_E2(bp)) {
- shmem_base = shmem_base_path[port];
- shmem2_base = shmem2_base_path[port];
- } else {
+ if (CHIP_IS_E1x(bp)) {
shmem_base = shmem_base_path[0];
shmem2_base = shmem2_base_path[0];
+ } else {
+ shmem_base = shmem_base_path[port];
+ shmem2_base = shmem2_base_path[port];
}
/* Extract the ext phy address for the port */
if (bnx2x_populate_phy(bp, phy_index, shmem_base, shmem2_base,
@@ -8027,10 +11942,11 @@
break;
}
}
-static u8 bnx2x_8727_common_init_phy(struct bnx2x *bp,
- u32 shmem_base_path[],
- u32 shmem2_base_path[], u8 phy_index,
- u32 chip_id)
+
+static int bnx2x_8727_common_init_phy(struct bnx2x *bp,
+ u32 shmem_base_path[],
+ u32 shmem2_base_path[], u8 phy_index,
+ u32 chip_id)
{
s8 port, reset_gpio;
u32 swap_val, swap_override;
@@ -8067,14 +11983,14 @@
u32 shmem_base, shmem2_base;
/* In E2, same phy is using for port0 of the two paths */
- if (CHIP_IS_E2(bp)) {
- shmem_base = shmem_base_path[port];
- shmem2_base = shmem2_base_path[port];
- port_of_path = 0;
- } else {
+ if (CHIP_IS_E1x(bp)) {
shmem_base = shmem_base_path[0];
shmem2_base = shmem2_base_path[0];
port_of_path = port;
+ } else {
+ shmem_base = shmem_base_path[port];
+ shmem2_base = shmem2_base_path[port];
+ port_of_path = 0;
}
/* Extract the ext phy address for the port */
@@ -8109,25 +12025,29 @@
}
/* PART2 - Download firmware to both phys */
for (port = PORT_MAX - 1; port >= PORT_0; port--) {
- if (CHIP_IS_E2(bp))
- port_of_path = 0;
- else
+ if (CHIP_IS_E1x(bp))
port_of_path = port;
+ else
+ port_of_path = 0;
DP(NETIF_MSG_LINK, "Loading spirom for phy address 0x%x\n",
phy_blk[port]->addr);
if (bnx2x_8073_8727_external_rom_boot(bp, phy_blk[port],
port_of_path))
return -EINVAL;
+ /* Disable PHY transmitter output */
+ bnx2x_cl45_write(bp, phy_blk[port],
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_TX_DISABLE, 1);
}
return 0;
}
-static u8 bnx2x_ext_phy_common_init(struct bnx2x *bp, u32 shmem_base_path[],
- u32 shmem2_base_path[], u8 phy_index,
- u32 ext_phy_type, u32 chip_id)
+static int bnx2x_ext_phy_common_init(struct bnx2x *bp, u32 shmem_base_path[],
+ u32 shmem2_base_path[], u8 phy_index,
+ u32 ext_phy_type, u32 chip_id)
{
- u8 rc = 0;
+ int rc = 0;
switch (ext_phy_type) {
case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
@@ -8135,7 +12055,7 @@
shmem2_base_path,
phy_index, chip_id);
break;
-
+ case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8722:
case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727_NOC:
rc = bnx2x_8727_common_init_phy(bp, shmem_base_path,
@@ -8152,6 +12072,13 @@
shmem2_base_path,
phy_index, chip_id);
break;
+ case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833:
+ /*
+ * GPIO3's are linked, and so both need to be toggled
+ * to obtain required 2us pulse.
+ */
+ rc = bnx2x_84833_common_init_phy(bp, shmem_base_path, chip_id);
+ break;
case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE:
rc = -EINVAL;
break;
@@ -8169,15 +12096,21 @@
return rc;
}
-u8 bnx2x_common_init_phy(struct bnx2x *bp, u32 shmem_base_path[],
- u32 shmem2_base_path[], u32 chip_id)
+int bnx2x_common_init_phy(struct bnx2x *bp, u32 shmem_base_path[],
+ u32 shmem2_base_path[], u32 chip_id)
{
- u8 rc = 0;
- u32 phy_ver;
- u8 phy_index;
+ int rc = 0;
+ u32 phy_ver, val;
+ u8 phy_index = 0;
u32 ext_phy_type, ext_phy_config;
+ bnx2x_set_mdio_clk(bp, chip_id, PORT_0);
+ bnx2x_set_mdio_clk(bp, chip_id, PORT_1);
DP(NETIF_MSG_LINK, "Begin common phy init\n");
-
+ if (CHIP_IS_E3(bp)) {
+ /* Enable EPIO */
+ val = REG_RD(bp, MISC_REG_GEN_PURP_HWG);
+ REG_WR(bp, MISC_REG_GEN_PURP_HWG, val | 1);
+ }
/* Check if common init was already done */
phy_ver = REG_RD(bp, shmem_base_path[0] +
offsetof(struct shmem_region,
@@ -8203,6 +12136,135 @@
return rc;
}
+static void bnx2x_check_over_curr(struct link_params *params,
+ struct link_vars *vars)
+{
+ struct bnx2x *bp = params->bp;
+ u32 cfg_pin;
+ u8 port = params->port;
+ u32 pin_val;
+
+ cfg_pin = (REG_RD(bp, params->shmem_base +
+ offsetof(struct shmem_region,
+ dev_info.port_hw_config[port].e3_cmn_pin_cfg1)) &
+ PORT_HW_CFG_E3_OVER_CURRENT_MASK) >>
+ PORT_HW_CFG_E3_OVER_CURRENT_SHIFT;
+
+ /* Ignore check if no external input PIN available */
+ if (bnx2x_get_cfg_pin(bp, cfg_pin, &pin_val) != 0)
+ return;
+
+ if (!pin_val) {
+ if ((vars->phy_flags & PHY_OVER_CURRENT_FLAG) == 0) {
+ netdev_err(bp->dev, "Error: Power fault on Port %d has"
+ " been detected and the power to "
+ "that SFP+ module has been removed"
+ " to prevent failure of the card."
+ " Please remove the SFP+ module and"
+ " restart the system to clear this"
+ " error.\n",
+ params->port);
+ vars->phy_flags |= PHY_OVER_CURRENT_FLAG;
+ }
+ } else
+ vars->phy_flags &= ~PHY_OVER_CURRENT_FLAG;
+}
+
+static void bnx2x_analyze_link_error(struct link_params *params,
+ struct link_vars *vars, u32 lss_status)
+{
+ struct bnx2x *bp = params->bp;
+ /* Compare new value with previous value */
+ u8 led_mode;
+ u32 half_open_conn = (vars->phy_flags & PHY_HALF_OPEN_CONN_FLAG) > 0;
+
+ /*DP(NETIF_MSG_LINK, "CHECK LINK: %x half_open:%x-> lss:%x\n",
+ vars->link_up,
+ half_open_conn, lss_status);*/
+
+ if ((lss_status ^ half_open_conn) == 0)
+ return;
+
+ /* If values differ */
+ DP(NETIF_MSG_LINK, "Link changed:%x %x->%x\n", vars->link_up,
+ half_open_conn, lss_status);
+
+ /*
+ * a. Update shmem->link_status accordingly
+ * b. Update link_vars->link_up
+ */
+ if (lss_status) {
+ vars->link_status &= ~LINK_STATUS_LINK_UP;
+ vars->link_up = 0;
+ vars->phy_flags |= PHY_HALF_OPEN_CONN_FLAG;
+ /*
+ * Set LED mode to off since the PHY doesn't know about these
+ * errors
+ */
+ led_mode = LED_MODE_OFF;
+ } else {
+ vars->link_status |= LINK_STATUS_LINK_UP;
+ vars->link_up = 1;
+ vars->phy_flags &= ~PHY_HALF_OPEN_CONN_FLAG;
+ led_mode = LED_MODE_OPER;
+ }
+ /* Update the LED according to the link state */
+ bnx2x_set_led(params, vars, led_mode, SPEED_10000);
+
+ /* Update link status in the shared memory */
+ bnx2x_update_mng(params, vars->link_status);
+
+ /* C. Trigger General Attention */
+ vars->periodic_flags |= PERIODIC_FLAGS_LINK_EVENT;
+ bnx2x_notify_link_changed(bp);
+}
+
+static void bnx2x_check_half_open_conn(struct link_params *params,
+ struct link_vars *vars)
+{
+ struct bnx2x *bp = params->bp;
+ u32 lss_status = 0;
+ u32 mac_base;
+ /* In case link status is physically up @ 10G do */
+ if ((vars->phy_flags & PHY_PHYSICAL_LINK_FLAG) == 0)
+ return;
+
+ if (!CHIP_IS_E3(bp) &&
+ (REG_RD(bp, MISC_REG_RESET_REG_2) &
+ (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << params->port))) {
+ /* Check E1X / E2 BMAC */
+ u32 lss_status_reg;
+ u32 wb_data[2];
+ mac_base = params->port ? NIG_REG_INGRESS_BMAC1_MEM :
+ NIG_REG_INGRESS_BMAC0_MEM;
+ /* Read BIGMAC_REGISTER_RX_LSS_STATUS */
+ if (CHIP_IS_E2(bp))
+ lss_status_reg = BIGMAC2_REGISTER_RX_LSS_STAT;
+ else
+ lss_status_reg = BIGMAC_REGISTER_RX_LSS_STATUS;
+
+ REG_RD_DMAE(bp, mac_base + lss_status_reg, wb_data, 2);
+ lss_status = (wb_data[0] > 0);
+
+ bnx2x_analyze_link_error(params, vars, lss_status);
+ }
+}
+
+void bnx2x_period_func(struct link_params *params, struct link_vars *vars)
+{
+ struct bnx2x *bp = params->bp;
+ if (!params) {
+ DP(NETIF_MSG_LINK, "Ininitliazed params !\n");
+ return;
+ }
+ /* DP(NETIF_MSG_LINK, "Periodic called vars->phy_flags 0x%x speed 0x%x
+ RESET_REG_2 0x%x\n", vars->phy_flags, vars->line_speed,
+ REG_RD(bp, MISC_REG_RESET_REG_2)); */
+ bnx2x_check_half_open_conn(params, vars);
+ if (CHIP_IS_E3(bp))
+ bnx2x_check_over_curr(params, vars);
+}
+
u8 bnx2x_hw_lock_required(struct bnx2x *bp, u32 shmem_base, u32 shmem2_base)
{
u8 phy_index;
@@ -8245,7 +12307,15 @@
void bnx2x_hw_reset_phy(struct link_params *params)
{
u8 phy_index;
- for (phy_index = EXT_PHY1; phy_index < MAX_PHYS;
+ struct bnx2x *bp = params->bp;
+ bnx2x_update_mng(params, 0);
+ bnx2x_bits_dis(bp, NIG_REG_MASK_INTERRUPT_PORT0 + params->port*4,
+ (NIG_MASK_XGXS0_LINK_STATUS |
+ NIG_MASK_XGXS0_LINK10G |
+ NIG_MASK_SERDES0_LINK_STATUS |
+ NIG_MASK_MI_INT));
+
+ for (phy_index = INT_PHY; phy_index < MAX_PHYS;
phy_index++) {
if (params->phy[phy_index].hw_reset) {
params->phy[phy_index].hw_reset(
@@ -8255,3 +12325,72 @@
}
}
}
+
+void bnx2x_init_mod_abs_int(struct bnx2x *bp, struct link_vars *vars,
+ u32 chip_id, u32 shmem_base, u32 shmem2_base,
+ u8 port)
+{
+ u8 gpio_num = 0xff, gpio_port = 0xff, phy_index;
+ u32 val;
+ u32 offset, aeu_mask, swap_val, swap_override, sync_offset;
+ if (CHIP_IS_E3(bp)) {
+ if (bnx2x_get_mod_abs_int_cfg(bp, chip_id,
+ shmem_base,
+ port,
+ &gpio_num,
+ &gpio_port) != 0)
+ return;
+ } else {
+ struct bnx2x_phy phy;
+ for (phy_index = EXT_PHY1; phy_index < MAX_PHYS;
+ phy_index++) {
+ if (bnx2x_populate_phy(bp, phy_index, shmem_base,
+ shmem2_base, port, &phy)
+ != 0) {
+ DP(NETIF_MSG_LINK, "populate phy failed\n");
+ return;
+ }
+ if (phy.type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726) {
+ gpio_num = MISC_REGISTERS_GPIO_3;
+ gpio_port = port;
+ break;
+ }
+ }
+ }
+
+ if (gpio_num == 0xff)
+ return;
+
+ /* Set GPIO3 to trigger SFP+ module insertion/removal */
+ bnx2x_set_gpio(bp, gpio_num, MISC_REGISTERS_GPIO_INPUT_HI_Z, gpio_port);
+
+ swap_val = REG_RD(bp, NIG_REG_PORT_SWAP);
+ swap_override = REG_RD(bp, NIG_REG_STRAP_OVERRIDE);
+ gpio_port ^= (swap_val && swap_override);
+
+ vars->aeu_int_mask = AEU_INPUTS_ATTN_BITS_GPIO0_FUNCTION_0 <<
+ (gpio_num + (gpio_port << 2));
+
+ sync_offset = shmem_base +
+ offsetof(struct shmem_region,
+ dev_info.port_hw_config[port].aeu_int_mask);
+ REG_WR(bp, sync_offset, vars->aeu_int_mask);
+
+ DP(NETIF_MSG_LINK, "Setting MOD_ABS (GPIO%d_P%d) AEU to 0x%x\n",
+ gpio_num, gpio_port, vars->aeu_int_mask);
+
+ if (port == 0)
+ offset = MISC_REG_AEU_ENABLE1_FUNC_0_OUT_0;
+ else
+ offset = MISC_REG_AEU_ENABLE1_FUNC_1_OUT_0;
+
+ /* Open appropriate AEU for interrupts */
+ aeu_mask = REG_RD(bp, offset);
+ aeu_mask |= vars->aeu_int_mask;
+ REG_WR(bp, offset, aeu_mask);
+
+ /* Enable the GPIO to trigger interrupt */
+ val = REG_RD(bp, MISC_REG_GPIO_EVENT_EN);
+ val |= 1 << (gpio_num + (gpio_port << 2));
+ REG_WR(bp, MISC_REG_GPIO_EVENT_EN, val);
+}
diff --git a/drivers/net/bnx2x/bnx2x_link.h b/drivers/net/bnx2x/bnx2x_link.h
index 92f36b6..6a7708d 100644
--- a/drivers/net/bnx2x/bnx2x_link.h
+++ b/drivers/net/bnx2x/bnx2x_link.h
@@ -33,12 +33,13 @@
#define BNX2X_FLOW_CTRL_BOTH PORT_FEATURE_FLOW_CONTROL_BOTH
#define BNX2X_FLOW_CTRL_NONE PORT_FEATURE_FLOW_CONTROL_NONE
+#define NET_SERDES_IF_XFI 1
+#define NET_SERDES_IF_SFI 2
+#define NET_SERDES_IF_KR 3
+#define NET_SERDES_IF_DXGXS 4
+
#define SPEED_AUTO_NEG 0
-#define SPEED_12000 12000
-#define SPEED_12500 12500
-#define SPEED_13000 13000
-#define SPEED_15000 15000
-#define SPEED_16000 16000
+#define SPEED_20000 20000
#define SFP_EEPROM_VENDOR_NAME_ADDR 0x14
#define SFP_EEPROM_VENDOR_NAME_SIZE 16
@@ -46,6 +47,12 @@
#define SFP_EEPROM_VENDOR_OUI_SIZE 3
#define SFP_EEPROM_PART_NO_ADDR 0x28
#define SFP_EEPROM_PART_NO_SIZE 16
+#define SFP_EEPROM_REVISION_ADDR 0x38
+#define SFP_EEPROM_REVISION_SIZE 4
+#define SFP_EEPROM_SERIAL_ADDR 0x44
+#define SFP_EEPROM_SERIAL_SIZE 16
+#define SFP_EEPROM_DATE_ADDR 0x54 /* ASCII YYMMDD */
+#define SFP_EEPROM_DATE_SIZE 6
#define PWR_FLT_ERR_MSG_LEN 250
#define XGXS_EXT_PHY_TYPE(ext_phy_config) \
@@ -62,25 +69,26 @@
#define SINGLE_MEDIA(params) (params->num_phys == 2)
/* Dual Media board contains two external phy with different media */
#define DUAL_MEDIA(params) (params->num_phys == 3)
+
+#define FW_PARAM_PHY_ADDR_MASK 0x000000FF
+#define FW_PARAM_PHY_TYPE_MASK 0x0000FF00
+#define FW_PARAM_MDIO_CTRL_MASK 0xFFFF0000
#define FW_PARAM_MDIO_CTRL_OFFSET 16
+#define FW_PARAM_PHY_ADDR(fw_param) (fw_param & \
+ FW_PARAM_PHY_ADDR_MASK)
+#define FW_PARAM_PHY_TYPE(fw_param) (fw_param & \
+ FW_PARAM_PHY_TYPE_MASK)
+#define FW_PARAM_MDIO_CTRL(fw_param) ((fw_param & \
+ FW_PARAM_MDIO_CTRL_MASK) >> \
+ FW_PARAM_MDIO_CTRL_OFFSET)
#define FW_PARAM_SET(phy_addr, phy_type, mdio_access) \
(phy_addr | phy_type | mdio_access << FW_PARAM_MDIO_CTRL_OFFSET)
-#define PFC_BRB_MAC_PAUSE_XOFF_THRESHOLD_PAUSEABLE 170
-#define PFC_BRB_MAC_PAUSE_XOFF_THRESHOLD_NON_PAUSEABLE 0
-
-#define PFC_BRB_MAC_PAUSE_XON_THRESHOLD_PAUSEABLE 250
-#define PFC_BRB_MAC_PAUSE_XON_THRESHOLD_NON_PAUSEABLE 0
-
-#define PFC_BRB_MAC_FULL_XOFF_THRESHOLD_PAUSEABLE 10
-#define PFC_BRB_MAC_FULL_XOFF_THRESHOLD_NON_PAUSEABLE 90
-
-#define PFC_BRB_MAC_FULL_XON_THRESHOLD_PAUSEABLE 50
-#define PFC_BRB_MAC_FULL_XON_THRESHOLD_NON_PAUSEABLE 250
#define PFC_BRB_FULL_LB_XOFF_THRESHOLD 170
#define PFC_BRB_FULL_LB_XON_THRESHOLD 250
+#define MAXVAL(a, b) (((a) > (b)) ? (a) : (b))
/***********************************************************/
/* Structs */
/***********************************************************/
@@ -121,8 +129,8 @@
/* Loaded during init */
u8 addr;
-
- u8 flags;
+ u8 def_md_devad;
+ u16 flags;
/* Require HW lock */
#define FLAGS_HW_LOCK_REQUIRED (1<<0)
/* No Over-Current detection */
@@ -131,11 +139,13 @@
#define FLAGS_FAN_FAILURE_DET_REQ (1<<2)
/* Initialize first the XGXS and only then the phy itself */
#define FLAGS_INIT_XGXS_FIRST (1<<3)
+#define FLAGS_WC_DUAL_MODE (1<<4)
+#define FLAGS_4_PORT_MODE (1<<5)
#define FLAGS_REARM_LATCH_SIGNAL (1<<6)
#define FLAGS_SFP_NOT_APPROVED (1<<7)
+#define FLAGS_MDC_MDIO_WA (1<<8)
+#define FLAGS_DUMMY_READ (1<<9)
- u8 def_md_devad;
- u8 reserved;
/* preemphasis values for the rx side */
u16 rx_preemphasis[4];
@@ -153,6 +163,8 @@
#define ETH_PHY_XFP_FIBER 0x2
#define ETH_PHY_DA_TWINAX 0x3
#define ETH_PHY_BASE_T 0x4
+#define ETH_PHY_KR 0xf0
+#define ETH_PHY_CX4 0xf1
#define ETH_PHY_NOT_PRESENT 0xff
/* The address in which version is located*/
@@ -238,6 +250,8 @@
#define FEATURE_CONFIG_PFC_ENABLED (1<<1)
#define FEATURE_CONFIG_BC_SUPPORTS_OPT_MDL_VRFY (1<<2)
#define FEATURE_CONFIG_BC_SUPPORTS_DUAL_PHY_OPT_MDL_VRFY (1<<3)
+#define FEATURE_CONFIG_AUTOGREEEN_ENABLED (1<<9)
+#define FEATURE_CONFIG_BC_SUPPORTS_SFP_TX_DISABLED (1<<10)
/* Will be populated during common init */
struct bnx2x_phy phy[MAX_PHYS];
@@ -257,11 +271,19 @@
/* Output parameters */
struct link_vars {
u8 phy_flags;
+#define PHY_XGXS_FLAG (1<<0)
+#define PHY_SGMII_FLAG (1<<1)
+#define PHY_PHYSICAL_LINK_FLAG (1<<2)
+#define PHY_HALF_OPEN_CONN_FLAG (1<<3)
+#define PHY_OVER_CURRENT_FLAG (1<<4)
+#define PHY_TX_ERROR_CHECK_FLAG (1<<5)
u8 mac_type;
#define MAC_TYPE_NONE 0
#define MAC_TYPE_EMAC 1
#define MAC_TYPE_BMAC 2
+#define MAC_TYPE_UMAC 3
+#define MAC_TYPE_XMAC 4
u8 phy_link_up; /* internal phy link indication */
u8 link_up;
@@ -274,45 +296,52 @@
/* The same definitions as the shmem parameter */
u32 link_status;
+ u8 fault_detected;
+ u8 rsrv1;
+ u16 periodic_flags;
+#define PERIODIC_FLAGS_LINK_EVENT 0x0001
+
+ u32 aeu_int_mask;
};
/***********************************************************/
/* Functions */
/***********************************************************/
-u8 bnx2x_phy_init(struct link_params *input, struct link_vars *output);
+int bnx2x_phy_init(struct link_params *params, struct link_vars *vars);
/* Reset the link. Should be called when driver or interface goes down
Before calling phy firmware upgrade, the reset_ext_phy should be set
to 0 */
-u8 bnx2x_link_reset(struct link_params *params, struct link_vars *vars,
- u8 reset_ext_phy);
+int bnx2x_link_reset(struct link_params *params, struct link_vars *vars,
+ u8 reset_ext_phy);
/* bnx2x_link_update should be called upon link interrupt */
-u8 bnx2x_link_update(struct link_params *input, struct link_vars *output);
+int bnx2x_link_update(struct link_params *params, struct link_vars *vars);
/* use the following phy functions to read/write from external_phy
In order to use it to read/write internal phy registers, use
DEFAULT_PHY_DEV_ADDR as devad, and (_bank + (_addr & 0xf)) as
the register */
-u8 bnx2x_phy_read(struct link_params *params, u8 phy_addr,
- u8 devad, u16 reg, u16 *ret_val);
+int bnx2x_phy_read(struct link_params *params, u8 phy_addr,
+ u8 devad, u16 reg, u16 *ret_val);
-u8 bnx2x_phy_write(struct link_params *params, u8 phy_addr,
- u8 devad, u16 reg, u16 val);
+int bnx2x_phy_write(struct link_params *params, u8 phy_addr,
+ u8 devad, u16 reg, u16 val);
+
/* Reads the link_status from the shmem,
and update the link vars accordingly */
void bnx2x_link_status_update(struct link_params *input,
struct link_vars *output);
/* returns string representing the fw_version of the external phy */
-u8 bnx2x_get_ext_phy_fw_version(struct link_params *params, u8 driver_loaded,
- u8 *version, u16 len);
+int bnx2x_get_ext_phy_fw_version(struct link_params *params, u8 driver_loaded,
+ u8 *version, u16 len);
/* Set/Unset the led
Basically, the CLC takes care of the led for the link, but in case one needs
to set/unset the led unnaturally, set the "mode" to LED_MODE_OPER to
blink the led, and LED_MODE_OFF to set the led off.*/
-u8 bnx2x_set_led(struct link_params *params, struct link_vars *vars,
- u8 mode, u32 speed);
+int bnx2x_set_led(struct link_params *params,
+ struct link_vars *vars, u8 mode, u32 speed);
#define LED_MODE_OFF 0
#define LED_MODE_ON 1
#define LED_MODE_OPER 2
@@ -324,12 +353,12 @@
/* Get the actual link status. In case it returns 0, link is up,
otherwise link is down*/
-u8 bnx2x_test_link(struct link_params *input, struct link_vars *vars,
- u8 is_serdes);
+int bnx2x_test_link(struct link_params *params, struct link_vars *vars,
+ u8 is_serdes);
/* One-time initialization for external phy after power up */
-u8 bnx2x_common_init_phy(struct bnx2x *bp, u32 shmem_base_path[],
- u32 shmem2_base_path[], u32 chip_id);
+int bnx2x_common_init_phy(struct bnx2x *bp, u32 shmem_base_path[],
+ u32 shmem2_base_path[], u32 chip_id);
/* Reset the external PHY using GPIO */
void bnx2x_ext_phy_hw_reset(struct bnx2x *bp, u8 port);
@@ -338,9 +367,9 @@
void bnx2x_sfx7101_sp_sw_reset(struct bnx2x *bp, struct bnx2x_phy *phy);
/* Read "byte_cnt" bytes from address "addr" from the SFP+ EEPROM */
-u8 bnx2x_read_sfp_module_eeprom(struct bnx2x_phy *phy,
- struct link_params *params, u16 addr,
- u8 byte_cnt, u8 *o_buf);
+int bnx2x_read_sfp_module_eeprom(struct bnx2x_phy *phy,
+ struct link_params *params, u16 addr,
+ u8 byte_cnt, u8 *o_buf);
void bnx2x_hw_reset_phy(struct link_params *params);
@@ -352,11 +381,28 @@
u32 bnx2x_phy_selection(struct link_params *params);
/* Probe the phys on board, and populate them in "params" */
-u8 bnx2x_phy_probe(struct link_params *params);
+int bnx2x_phy_probe(struct link_params *params);
+
/* Checks if fan failure detection is required on one of the phys on board */
u8 bnx2x_fan_failure_det_req(struct bnx2x *bp, u32 shmem_base,
u32 shmem2_base, u8 port);
+
+
+/* DCBX structs */
+
+/* Number of maximum COS per chip */
+#define DCBX_E2E3_MAX_NUM_COS (2)
+#define DCBX_E3B0_MAX_NUM_COS_PORT0 (6)
+#define DCBX_E3B0_MAX_NUM_COS_PORT1 (3)
+#define DCBX_E3B0_MAX_NUM_COS ( \
+ MAXVAL(DCBX_E3B0_MAX_NUM_COS_PORT0, \
+ DCBX_E3B0_MAX_NUM_COS_PORT1))
+
+#define DCBX_MAX_NUM_COS ( \
+ MAXVAL(DCBX_E3B0_MAX_NUM_COS, \
+ DCBX_E2E3_MAX_NUM_COS))
+
/* PFC port configuration params */
struct bnx2x_nig_brb_pfc_port_params {
/* NIG */
@@ -364,8 +410,8 @@
u32 llfc_out_en;
u32 llfc_enable;
u32 pkt_priority_to_cos;
- u32 rx_cos0_priority_mask;
- u32 rx_cos1_priority_mask;
+ u8 num_of_rx_cos_priority_mask;
+ u32 rx_cos_priority_mask[DCBX_MAX_NUM_COS];
u32 llfc_high_priority_classes;
u32 llfc_low_priority_classes;
/* BRB */
@@ -373,27 +419,74 @@
u32 cos1_pauseable;
};
+
+/* ETS port configuration params */
+struct bnx2x_ets_bw_params {
+ u8 bw;
+};
+
+struct bnx2x_ets_sp_params {
+ /**
+ * valid values are 0 - 5. 0 is highest strict priority.
+ * There can't be two COS's with the same pri.
+ */
+ u8 pri;
+};
+
+enum bnx2x_cos_state {
+ bnx2x_cos_state_strict = 0,
+ bnx2x_cos_state_bw = 1,
+};
+
+struct bnx2x_ets_cos_params {
+ enum bnx2x_cos_state state ;
+ union {
+ struct bnx2x_ets_bw_params bw_params;
+ struct bnx2x_ets_sp_params sp_params;
+ } params;
+};
+
+struct bnx2x_ets_params {
+ u8 num_of_cos; /* Number of valid COS entries*/
+ struct bnx2x_ets_cos_params cos[DCBX_MAX_NUM_COS];
+};
+
/**
* Used to update the PFC attributes in EMAC, BMAC, NIG and BRB
* when link is already up
*/
-void bnx2x_update_pfc(struct link_params *params,
+int bnx2x_update_pfc(struct link_params *params,
struct link_vars *vars,
struct bnx2x_nig_brb_pfc_port_params *pfc_params);
/* Used to configure the ETS to disable */
-void bnx2x_ets_disabled(struct link_params *params);
+int bnx2x_ets_disabled(struct link_params *params,
+ struct link_vars *vars);
/* Used to configure the ETS to BW limited */
void bnx2x_ets_bw_limit(const struct link_params *params, const u32 cos0_bw,
const u32 cos1_bw);
/* Used to configure the ETS to strict */
-u8 bnx2x_ets_strict(const struct link_params *params, const u8 strict_cos);
+int bnx2x_ets_strict(const struct link_params *params, const u8 strict_cos);
+
+/* Configure the COS to ETS according to BW and SP settings.*/
+int bnx2x_ets_e3b0_config(const struct link_params *params,
+ const struct link_vars *vars,
+ const struct bnx2x_ets_params *ets_params);
/* Read pfc statistic*/
void bnx2x_pfc_statistic(struct link_params *params, struct link_vars *vars,
u32 pfc_frames_sent[2],
u32 pfc_frames_received[2]);
+void bnx2x_init_mod_abs_int(struct bnx2x *bp, struct link_vars *vars,
+ u32 chip_id, u32 shmem_base, u32 shmem2_base,
+ u8 port);
+
+int bnx2x_sfp_module_detection(struct bnx2x_phy *phy,
+ struct link_params *params);
+
+void bnx2x_period_func(struct link_params *params, struct link_vars *vars);
+
#endif /* BNX2X_LINK_H */
diff --git a/drivers/net/bnx2x/bnx2x_main.c b/drivers/net/bnx2x/bnx2x_main.c
index 74be989..5b4a8f3 100644
--- a/drivers/net/bnx2x/bnx2x_main.c
+++ b/drivers/net/bnx2x/bnx2x_main.c
@@ -39,6 +39,7 @@
#include <linux/mii.h>
#include <linux/if_vlan.h>
#include <net/ip.h>
+#include <net/ipv6.h>
#include <net/tcp.h>
#include <net/checksum.h>
#include <net/ip6_checksum.h>
@@ -51,12 +52,12 @@
#include <linux/stringify.h>
#include <linux/vmalloc.h>
-#define BNX2X_MAIN
#include "bnx2x.h"
#include "bnx2x_init.h"
#include "bnx2x_init_ops.h"
#include "bnx2x_cmn.h"
#include "bnx2x_dcb.h"
+#include "bnx2x_sp.h"
#include <linux/firmware.h>
#include "bnx2x_fw_file_hdr.h"
@@ -74,12 +75,14 @@
#define TX_TIMEOUT (5*HZ)
static char version[] __devinitdata =
- "Broadcom NetXtreme II 5771x 10Gigabit Ethernet Driver "
+ "Broadcom NetXtreme II 5771x/578xx 10/20-Gigabit Ethernet Driver "
DRV_MODULE_NAME " " DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
MODULE_AUTHOR("Eliezer Tamir");
MODULE_DESCRIPTION("Broadcom NetXtreme II "
- "BCM57710/57711/57711E/57712/57712E Driver");
+ "BCM57710/57711/57711E/"
+ "57712/57712_MF/57800/57800_MF/57810/57810_MF/"
+ "57840/57840_MF Driver");
MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_MODULE_VERSION);
MODULE_FIRMWARE(FW_FILE_NAME_E1);
@@ -100,9 +103,11 @@
module_param(disable_tpa, int, 0);
MODULE_PARM_DESC(disable_tpa, " Disable the TPA (LRO) feature");
+#define INT_MODE_INTx 1
+#define INT_MODE_MSI 2
static int int_mode;
module_param(int_mode, int, 0);
-MODULE_PARM_DESC(int_mode, " Force interrupt mode other then MSI-X "
+MODULE_PARM_DESC(int_mode, " Force interrupt mode other than MSI-X "
"(1 INT#x; 2 MSI)");
static int dropless_fc;
@@ -121,37 +126,87 @@
module_param(debug, int, 0);
MODULE_PARM_DESC(debug, " Default debug msglevel");
-static struct workqueue_struct *bnx2x_wq;
-#ifdef BCM_CNIC
-static u8 ALL_ENODE_MACS[] = {0x01, 0x10, 0x18, 0x01, 0x00, 0x01};
-#endif
+
+struct workqueue_struct *bnx2x_wq;
enum bnx2x_board_type {
BCM57710 = 0,
- BCM57711 = 1,
- BCM57711E = 2,
- BCM57712 = 3,
- BCM57712E = 4
+ BCM57711,
+ BCM57711E,
+ BCM57712,
+ BCM57712_MF,
+ BCM57800,
+ BCM57800_MF,
+ BCM57810,
+ BCM57810_MF,
+ BCM57840,
+ BCM57840_MF
};
/* indexed by board_type, above */
static struct {
char *name;
} board_info[] __devinitdata = {
- { "Broadcom NetXtreme II BCM57710 XGb" },
- { "Broadcom NetXtreme II BCM57711 XGb" },
- { "Broadcom NetXtreme II BCM57711E XGb" },
- { "Broadcom NetXtreme II BCM57712 XGb" },
- { "Broadcom NetXtreme II BCM57712E XGb" }
+ { "Broadcom NetXtreme II BCM57710 10 Gigabit PCIe [Everest]" },
+ { "Broadcom NetXtreme II BCM57711 10 Gigabit PCIe" },
+ { "Broadcom NetXtreme II BCM57711E 10 Gigabit PCIe" },
+ { "Broadcom NetXtreme II BCM57712 10 Gigabit Ethernet" },
+ { "Broadcom NetXtreme II BCM57712 10 Gigabit Ethernet Multi Function" },
+ { "Broadcom NetXtreme II BCM57800 10 Gigabit Ethernet" },
+ { "Broadcom NetXtreme II BCM57800 10 Gigabit Ethernet Multi Function" },
+ { "Broadcom NetXtreme II BCM57810 10 Gigabit Ethernet" },
+ { "Broadcom NetXtreme II BCM57810 10 Gigabit Ethernet Multi Function" },
+ { "Broadcom NetXtreme II BCM57840 10/20 Gigabit Ethernet" },
+ { "Broadcom NetXtreme II BCM57840 10/20 Gigabit "
+ "Ethernet Multi Function"}
};
+#ifndef PCI_DEVICE_ID_NX2_57710
+#define PCI_DEVICE_ID_NX2_57710 CHIP_NUM_57710
+#endif
+#ifndef PCI_DEVICE_ID_NX2_57711
+#define PCI_DEVICE_ID_NX2_57711 CHIP_NUM_57711
+#endif
+#ifndef PCI_DEVICE_ID_NX2_57711E
+#define PCI_DEVICE_ID_NX2_57711E CHIP_NUM_57711E
+#endif
+#ifndef PCI_DEVICE_ID_NX2_57712
+#define PCI_DEVICE_ID_NX2_57712 CHIP_NUM_57712
+#endif
+#ifndef PCI_DEVICE_ID_NX2_57712_MF
+#define PCI_DEVICE_ID_NX2_57712_MF CHIP_NUM_57712_MF
+#endif
+#ifndef PCI_DEVICE_ID_NX2_57800
+#define PCI_DEVICE_ID_NX2_57800 CHIP_NUM_57800
+#endif
+#ifndef PCI_DEVICE_ID_NX2_57800_MF
+#define PCI_DEVICE_ID_NX2_57800_MF CHIP_NUM_57800_MF
+#endif
+#ifndef PCI_DEVICE_ID_NX2_57810
+#define PCI_DEVICE_ID_NX2_57810 CHIP_NUM_57810
+#endif
+#ifndef PCI_DEVICE_ID_NX2_57810_MF
+#define PCI_DEVICE_ID_NX2_57810_MF CHIP_NUM_57810_MF
+#endif
+#ifndef PCI_DEVICE_ID_NX2_57840
+#define PCI_DEVICE_ID_NX2_57840 CHIP_NUM_57840
+#endif
+#ifndef PCI_DEVICE_ID_NX2_57840_MF
+#define PCI_DEVICE_ID_NX2_57840_MF CHIP_NUM_57840_MF
+#endif
static DEFINE_PCI_DEVICE_TABLE(bnx2x_pci_tbl) = {
{ PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57710), BCM57710 },
{ PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57711), BCM57711 },
{ PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57711E), BCM57711E },
{ PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57712), BCM57712 },
- { PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57712E), BCM57712E },
+ { PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57712_MF), BCM57712_MF },
+ { PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57800), BCM57800 },
+ { PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57800_MF), BCM57800_MF },
+ { PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57810), BCM57810 },
+ { PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57810_MF), BCM57810_MF },
+ { PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57840), BCM57840 },
+ { PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57840_MF), BCM57840_MF },
{ 0 }
};
@@ -168,48 +223,6 @@
REG_WR(bp, addr + 4, U64_HI(mapping));
}
-static inline void __storm_memset_fill(struct bnx2x *bp,
- u32 addr, size_t size, u32 val)
-{
- int i;
- for (i = 0; i < size/4; i++)
- REG_WR(bp, addr + (i * 4), val);
-}
-
-static inline void storm_memset_ustats_zero(struct bnx2x *bp,
- u8 port, u16 stat_id)
-{
- size_t size = sizeof(struct ustorm_per_client_stats);
-
- u32 addr = BAR_USTRORM_INTMEM +
- USTORM_PER_COUNTER_ID_STATS_OFFSET(port, stat_id);
-
- __storm_memset_fill(bp, addr, size, 0);
-}
-
-static inline void storm_memset_tstats_zero(struct bnx2x *bp,
- u8 port, u16 stat_id)
-{
- size_t size = sizeof(struct tstorm_per_client_stats);
-
- u32 addr = BAR_TSTRORM_INTMEM +
- TSTORM_PER_COUNTER_ID_STATS_OFFSET(port, stat_id);
-
- __storm_memset_fill(bp, addr, size, 0);
-}
-
-static inline void storm_memset_xstats_zero(struct bnx2x *bp,
- u8 port, u16 stat_id)
-{
- size_t size = sizeof(struct xstorm_per_client_stats);
-
- u32 addr = BAR_XSTRORM_INTMEM +
- XSTORM_PER_COUNTER_ID_STATS_OFFSET(port, stat_id);
-
- __storm_memset_fill(bp, addr, size, 0);
-}
-
-
static inline void storm_memset_spq_addr(struct bnx2x *bp,
dma_addr_t mapping, u16 abs_fid)
{
@@ -219,103 +232,6 @@
__storm_memset_dma_mapping(bp, addr, mapping);
}
-static inline void storm_memset_ov(struct bnx2x *bp, u16 ov, u16 abs_fid)
-{
- REG_WR16(bp, BAR_XSTRORM_INTMEM + XSTORM_E1HOV_OFFSET(abs_fid), ov);
-}
-
-static inline void storm_memset_func_cfg(struct bnx2x *bp,
- struct tstorm_eth_function_common_config *tcfg,
- u16 abs_fid)
-{
- size_t size = sizeof(struct tstorm_eth_function_common_config);
-
- u32 addr = BAR_TSTRORM_INTMEM +
- TSTORM_FUNCTION_COMMON_CONFIG_OFFSET(abs_fid);
-
- __storm_memset_struct(bp, addr, size, (u32 *)tcfg);
-}
-
-static inline void storm_memset_xstats_flags(struct bnx2x *bp,
- struct stats_indication_flags *flags,
- u16 abs_fid)
-{
- size_t size = sizeof(struct stats_indication_flags);
-
- u32 addr = BAR_XSTRORM_INTMEM + XSTORM_STATS_FLAGS_OFFSET(abs_fid);
-
- __storm_memset_struct(bp, addr, size, (u32 *)flags);
-}
-
-static inline void storm_memset_tstats_flags(struct bnx2x *bp,
- struct stats_indication_flags *flags,
- u16 abs_fid)
-{
- size_t size = sizeof(struct stats_indication_flags);
-
- u32 addr = BAR_TSTRORM_INTMEM + TSTORM_STATS_FLAGS_OFFSET(abs_fid);
-
- __storm_memset_struct(bp, addr, size, (u32 *)flags);
-}
-
-static inline void storm_memset_ustats_flags(struct bnx2x *bp,
- struct stats_indication_flags *flags,
- u16 abs_fid)
-{
- size_t size = sizeof(struct stats_indication_flags);
-
- u32 addr = BAR_USTRORM_INTMEM + USTORM_STATS_FLAGS_OFFSET(abs_fid);
-
- __storm_memset_struct(bp, addr, size, (u32 *)flags);
-}
-
-static inline void storm_memset_cstats_flags(struct bnx2x *bp,
- struct stats_indication_flags *flags,
- u16 abs_fid)
-{
- size_t size = sizeof(struct stats_indication_flags);
-
- u32 addr = BAR_CSTRORM_INTMEM + CSTORM_STATS_FLAGS_OFFSET(abs_fid);
-
- __storm_memset_struct(bp, addr, size, (u32 *)flags);
-}
-
-static inline void storm_memset_xstats_addr(struct bnx2x *bp,
- dma_addr_t mapping, u16 abs_fid)
-{
- u32 addr = BAR_XSTRORM_INTMEM +
- XSTORM_ETH_STATS_QUERY_ADDR_OFFSET(abs_fid);
-
- __storm_memset_dma_mapping(bp, addr, mapping);
-}
-
-static inline void storm_memset_tstats_addr(struct bnx2x *bp,
- dma_addr_t mapping, u16 abs_fid)
-{
- u32 addr = BAR_TSTRORM_INTMEM +
- TSTORM_ETH_STATS_QUERY_ADDR_OFFSET(abs_fid);
-
- __storm_memset_dma_mapping(bp, addr, mapping);
-}
-
-static inline void storm_memset_ustats_addr(struct bnx2x *bp,
- dma_addr_t mapping, u16 abs_fid)
-{
- u32 addr = BAR_USTRORM_INTMEM +
- USTORM_ETH_STATS_QUERY_ADDR_OFFSET(abs_fid);
-
- __storm_memset_dma_mapping(bp, addr, mapping);
-}
-
-static inline void storm_memset_cstats_addr(struct bnx2x *bp,
- dma_addr_t mapping, u16 abs_fid)
-{
- u32 addr = BAR_CSTRORM_INTMEM +
- CSTORM_ETH_STATS_QUERY_ADDR_OFFSET(abs_fid);
-
- __storm_memset_dma_mapping(bp, addr, mapping);
-}
-
static inline void storm_memset_vf_to_pf(struct bnx2x *bp, u16 abs_fid,
u16 pf_id)
{
@@ -360,45 +276,6 @@
REG_WR16(bp, addr, eq_prod);
}
-static inline void storm_memset_hc_timeout(struct bnx2x *bp, u8 port,
- u16 fw_sb_id, u8 sb_index,
- u8 ticks)
-{
-
- int index_offset = CHIP_IS_E2(bp) ?
- offsetof(struct hc_status_block_data_e2, index_data) :
- offsetof(struct hc_status_block_data_e1x, index_data);
- u32 addr = BAR_CSTRORM_INTMEM +
- CSTORM_STATUS_BLOCK_DATA_OFFSET(fw_sb_id) +
- index_offset +
- sizeof(struct hc_index_data)*sb_index +
- offsetof(struct hc_index_data, timeout);
- REG_WR8(bp, addr, ticks);
- DP(NETIF_MSG_HW, "port %x fw_sb_id %d sb_index %d ticks %d\n",
- port, fw_sb_id, sb_index, ticks);
-}
-static inline void storm_memset_hc_disable(struct bnx2x *bp, u8 port,
- u16 fw_sb_id, u8 sb_index,
- u8 disable)
-{
- u32 enable_flag = disable ? 0 : (1 << HC_INDEX_DATA_HC_ENABLED_SHIFT);
- int index_offset = CHIP_IS_E2(bp) ?
- offsetof(struct hc_status_block_data_e2, index_data) :
- offsetof(struct hc_status_block_data_e1x, index_data);
- u32 addr = BAR_CSTRORM_INTMEM +
- CSTORM_STATUS_BLOCK_DATA_OFFSET(fw_sb_id) +
- index_offset +
- sizeof(struct hc_index_data)*sb_index +
- offsetof(struct hc_index_data, flags);
- u16 flags = REG_RD16(bp, addr);
- /* clear and set */
- flags &= ~HC_INDEX_DATA_HC_ENABLED;
- flags |= enable_flag;
- REG_WR16(bp, addr, flags);
- DP(NETIF_MSG_HW, "port %x fw_sb_id %d sb_index %d disable %d\n",
- port, fw_sb_id, sb_index, disable);
-}
-
/* used only at init
* locking is done by mcp
*/
@@ -492,13 +369,6 @@
}
-const u32 dmae_reg_go_c[] = {
- DMAE_REG_GO_C0, DMAE_REG_GO_C1, DMAE_REG_GO_C2, DMAE_REG_GO_C3,
- DMAE_REG_GO_C4, DMAE_REG_GO_C5, DMAE_REG_GO_C6, DMAE_REG_GO_C7,
- DMAE_REG_GO_C8, DMAE_REG_GO_C9, DMAE_REG_GO_C10, DMAE_REG_GO_C11,
- DMAE_REG_GO_C12, DMAE_REG_GO_C13, DMAE_REG_GO_C14, DMAE_REG_GO_C15
-};
-
/* copy command into DMAE command memory and set DMAE command go */
void bnx2x_post_dmae(struct bnx2x *bp, struct dmae_command *dmae, int idx)
{
@@ -579,7 +449,11 @@
bp->slowpath->wb_data[0], bp->slowpath->wb_data[1],
bp->slowpath->wb_data[2], bp->slowpath->wb_data[3]);
- /* lock the dmae channel */
+ /*
+ * Lock the dmae channel. Disable BHs to prevent a dead-lock
+ * as long as this code is called both from syscall context and
+ * from ndo_set_rx_mode() flow that may be called from BH.
+ */
spin_lock_bh(&bp->dmae_lock);
/* reset completion */
@@ -834,9 +708,9 @@
return rc;
}
-static void bnx2x_fw_dump(struct bnx2x *bp)
+void bnx2x_fw_dump_lvl(struct bnx2x *bp, const char *lvl)
{
- u32 addr;
+ u32 addr, val;
u32 mark, offset;
__be32 data[9];
int word;
@@ -845,6 +719,14 @@
BNX2X_ERR("NO MCP - can not dump\n");
return;
}
+ netdev_printk(lvl, bp->dev, "bc %d.%d.%d\n",
+ (bp->common.bc_ver & 0xff0000) >> 16,
+ (bp->common.bc_ver & 0xff00) >> 8,
+ (bp->common.bc_ver & 0xff));
+
+ val = REG_RD(bp, MCP_REG_MCPR_CPU_PROGRAM_COUNTER);
+ if (val == REG_RD(bp, MCP_REG_MCPR_CPU_PROGRAM_COUNTER))
+ printk("%s" "MCP PC at 0x%x\n", lvl, val);
if (BP_PATH(bp) == 0)
trace_shmem_base = bp->common.shmem_base;
@@ -854,9 +736,9 @@
mark = REG_RD(bp, addr);
mark = (CHIP_IS_E1x(bp) ? MCP_REG_MCPR_SCRATCH : MCP_A_REG_MCPR_SCRATCH)
+ ((mark + 0x3) & ~0x3) - 0x08000000;
- pr_err("begin fw dump (mark 0x%x)\n", mark);
+ printk("%s" "begin fw dump (mark 0x%x)\n", lvl, mark);
- pr_err("");
+ printk("%s", lvl);
for (offset = mark; offset <= trace_shmem_base; offset += 0x8*4) {
for (word = 0; word < 8; word++)
data[word] = htonl(REG_RD(bp, offset + 4*word));
@@ -869,7 +751,12 @@
data[8] = 0x0;
pr_cont("%s", (char *)data);
}
- pr_err("end of fw dump\n");
+ printk("%s" "end of fw dump\n", lvl);
+}
+
+static inline void bnx2x_fw_dump(struct bnx2x *bp)
+{
+ bnx2x_fw_dump_lvl(bp, KERN_ERR);
}
void bnx2x_panic_dump(struct bnx2x *bp)
@@ -890,9 +777,9 @@
/* Indices */
/* Common */
BNX2X_ERR("def_idx(0x%x) def_att_idx(0x%x) attn_state(0x%x)"
- " spq_prod_idx(0x%x)\n",
- bp->def_idx, bp->def_att_idx,
- bp->attn_state, bp->spq_prod_idx);
+ " spq_prod_idx(0x%x) next_stats_cnt(0x%x)\n",
+ bp->def_idx, bp->def_att_idx, bp->attn_state,
+ bp->spq_prod_idx, bp->stats_counter);
BNX2X_ERR("DSB: attn bits(0x%x) ack(0x%x) id(0x%x) idx(0x%x)\n",
bp->def_status_blk->atten_status_block.attn_bits,
bp->def_status_blk->atten_status_block.attn_bits_ack,
@@ -909,15 +796,17 @@
CSTORM_SP_STATUS_BLOCK_DATA_OFFSET(func) +
i*sizeof(u32));
- pr_cont("igu_sb_id(0x%x) igu_seg_id (0x%x) "
+ pr_cont("igu_sb_id(0x%x) igu_seg_id(0x%x) "
"pf_id(0x%x) vnic_id(0x%x) "
- "vf_id(0x%x) vf_valid (0x%x)\n",
+ "vf_id(0x%x) vf_valid (0x%x) "
+ "state(0x%x)\n",
sp_sb_data.igu_sb_id,
sp_sb_data.igu_seg_id,
sp_sb_data.p_func.pf_id,
sp_sb_data.p_func.vnic_id,
sp_sb_data.p_func.vf_id,
- sp_sb_data.p_func.vf_valid);
+ sp_sb_data.p_func.vf_valid,
+ sp_sb_data.state);
for_each_eth_queue(bp, i) {
@@ -926,13 +815,13 @@
struct hc_status_block_data_e2 sb_data_e2;
struct hc_status_block_data_e1x sb_data_e1x;
struct hc_status_block_sm *hc_sm_p =
- CHIP_IS_E2(bp) ?
- sb_data_e2.common.state_machine :
- sb_data_e1x.common.state_machine;
+ CHIP_IS_E1x(bp) ?
+ sb_data_e1x.common.state_machine :
+ sb_data_e2.common.state_machine;
struct hc_index_data *hc_index_p =
- CHIP_IS_E2(bp) ?
- sb_data_e2.index_data :
- sb_data_e1x.index_data;
+ CHIP_IS_E1x(bp) ?
+ sb_data_e1x.index_data :
+ sb_data_e2.index_data;
int data_size;
u32 *sb_data_p;
@@ -955,8 +844,8 @@
i, fp->tx_pkt_prod, fp->tx_pkt_cons, fp->tx_bd_prod,
fp->tx_bd_cons, le16_to_cpu(*fp->tx_cons_sb));
- loop = CHIP_IS_E2(bp) ?
- HC_SB_MAX_INDICES_E2 : HC_SB_MAX_INDICES_E1X;
+ loop = CHIP_IS_E1x(bp) ?
+ HC_SB_MAX_INDICES_E1X : HC_SB_MAX_INDICES_E2;
/* host sb data */
@@ -976,35 +865,39 @@
fp->sb_index_values[j],
(j == loop - 1) ? ")" : " ");
/* fw sb data */
- data_size = CHIP_IS_E2(bp) ?
- sizeof(struct hc_status_block_data_e2) :
- sizeof(struct hc_status_block_data_e1x);
+ data_size = CHIP_IS_E1x(bp) ?
+ sizeof(struct hc_status_block_data_e1x) :
+ sizeof(struct hc_status_block_data_e2);
data_size /= sizeof(u32);
- sb_data_p = CHIP_IS_E2(bp) ?
- (u32 *)&sb_data_e2 :
- (u32 *)&sb_data_e1x;
+ sb_data_p = CHIP_IS_E1x(bp) ?
+ (u32 *)&sb_data_e1x :
+ (u32 *)&sb_data_e2;
/* copy sb data in here */
for (j = 0; j < data_size; j++)
*(sb_data_p + j) = REG_RD(bp, BAR_CSTRORM_INTMEM +
CSTORM_STATUS_BLOCK_DATA_OFFSET(fp->fw_sb_id) +
j * sizeof(u32));
- if (CHIP_IS_E2(bp)) {
- pr_cont("pf_id(0x%x) vf_id (0x%x) vf_valid(0x%x) "
- "vnic_id(0x%x) same_igu_sb_1b(0x%x)\n",
+ if (!CHIP_IS_E1x(bp)) {
+ pr_cont("pf_id(0x%x) vf_id(0x%x) vf_valid(0x%x) "
+ "vnic_id(0x%x) same_igu_sb_1b(0x%x) "
+ "state(0x%x)\n",
sb_data_e2.common.p_func.pf_id,
sb_data_e2.common.p_func.vf_id,
sb_data_e2.common.p_func.vf_valid,
sb_data_e2.common.p_func.vnic_id,
- sb_data_e2.common.same_igu_sb_1b);
+ sb_data_e2.common.same_igu_sb_1b,
+ sb_data_e2.common.state);
} else {
- pr_cont("pf_id(0x%x) vf_id (0x%x) vf_valid(0x%x) "
- "vnic_id(0x%x) same_igu_sb_1b(0x%x)\n",
+ pr_cont("pf_id(0x%x) vf_id(0x%x) vf_valid(0x%x) "
+ "vnic_id(0x%x) same_igu_sb_1b(0x%x) "
+ "state(0x%x)\n",
sb_data_e1x.common.p_func.pf_id,
sb_data_e1x.common.p_func.vf_id,
sb_data_e1x.common.p_func.vf_valid,
sb_data_e1x.common.p_func.vnic_id,
- sb_data_e1x.common.same_igu_sb_1b);
+ sb_data_e1x.common.same_igu_sb_1b,
+ sb_data_e1x.common.state);
}
/* SB_SMs data */
@@ -1093,6 +986,373 @@
BNX2X_ERR("end crash dump -----------------\n");
}
+/*
+ * FLR Support for E2
+ *
+ * bnx2x_pf_flr_clnup() is called during nic_load in the per function HW
+ * initialization.
+ */
+#define FLR_WAIT_USEC 10000 /* 10 miliseconds */
+#define FLR_WAIT_INTERAVAL 50 /* usec */
+#define FLR_POLL_CNT (FLR_WAIT_USEC/FLR_WAIT_INTERAVAL) /* 200 */
+
+struct pbf_pN_buf_regs {
+ int pN;
+ u32 init_crd;
+ u32 crd;
+ u32 crd_freed;
+};
+
+struct pbf_pN_cmd_regs {
+ int pN;
+ u32 lines_occup;
+ u32 lines_freed;
+};
+
+static void bnx2x_pbf_pN_buf_flushed(struct bnx2x *bp,
+ struct pbf_pN_buf_regs *regs,
+ u32 poll_count)
+{
+ u32 init_crd, crd, crd_start, crd_freed, crd_freed_start;
+ u32 cur_cnt = poll_count;
+
+ crd_freed = crd_freed_start = REG_RD(bp, regs->crd_freed);
+ crd = crd_start = REG_RD(bp, regs->crd);
+ init_crd = REG_RD(bp, regs->init_crd);
+
+ DP(BNX2X_MSG_SP, "INIT CREDIT[%d] : %x\n", regs->pN, init_crd);
+ DP(BNX2X_MSG_SP, "CREDIT[%d] : s:%x\n", regs->pN, crd);
+ DP(BNX2X_MSG_SP, "CREDIT_FREED[%d]: s:%x\n", regs->pN, crd_freed);
+
+ while ((crd != init_crd) && ((u32)SUB_S32(crd_freed, crd_freed_start) <
+ (init_crd - crd_start))) {
+ if (cur_cnt--) {
+ udelay(FLR_WAIT_INTERAVAL);
+ crd = REG_RD(bp, regs->crd);
+ crd_freed = REG_RD(bp, regs->crd_freed);
+ } else {
+ DP(BNX2X_MSG_SP, "PBF tx buffer[%d] timed out\n",
+ regs->pN);
+ DP(BNX2X_MSG_SP, "CREDIT[%d] : c:%x\n",
+ regs->pN, crd);
+ DP(BNX2X_MSG_SP, "CREDIT_FREED[%d]: c:%x\n",
+ regs->pN, crd_freed);
+ break;
+ }
+ }
+ DP(BNX2X_MSG_SP, "Waited %d*%d usec for PBF tx buffer[%d]\n",
+ poll_count-cur_cnt, FLR_WAIT_INTERAVAL, regs->pN);
+}
+
+static void bnx2x_pbf_pN_cmd_flushed(struct bnx2x *bp,
+ struct pbf_pN_cmd_regs *regs,
+ u32 poll_count)
+{
+ u32 occup, to_free, freed, freed_start;
+ u32 cur_cnt = poll_count;
+
+ occup = to_free = REG_RD(bp, regs->lines_occup);
+ freed = freed_start = REG_RD(bp, regs->lines_freed);
+
+ DP(BNX2X_MSG_SP, "OCCUPANCY[%d] : s:%x\n", regs->pN, occup);
+ DP(BNX2X_MSG_SP, "LINES_FREED[%d] : s:%x\n", regs->pN, freed);
+
+ while (occup && ((u32)SUB_S32(freed, freed_start) < to_free)) {
+ if (cur_cnt--) {
+ udelay(FLR_WAIT_INTERAVAL);
+ occup = REG_RD(bp, regs->lines_occup);
+ freed = REG_RD(bp, regs->lines_freed);
+ } else {
+ DP(BNX2X_MSG_SP, "PBF cmd queue[%d] timed out\n",
+ regs->pN);
+ DP(BNX2X_MSG_SP, "OCCUPANCY[%d] : s:%x\n",
+ regs->pN, occup);
+ DP(BNX2X_MSG_SP, "LINES_FREED[%d] : s:%x\n",
+ regs->pN, freed);
+ break;
+ }
+ }
+ DP(BNX2X_MSG_SP, "Waited %d*%d usec for PBF cmd queue[%d]\n",
+ poll_count-cur_cnt, FLR_WAIT_INTERAVAL, regs->pN);
+}
+
+static inline u32 bnx2x_flr_clnup_reg_poll(struct bnx2x *bp, u32 reg,
+ u32 expected, u32 poll_count)
+{
+ u32 cur_cnt = poll_count;
+ u32 val;
+
+ while ((val = REG_RD(bp, reg)) != expected && cur_cnt--)
+ udelay(FLR_WAIT_INTERAVAL);
+
+ return val;
+}
+
+static inline int bnx2x_flr_clnup_poll_hw_counter(struct bnx2x *bp, u32 reg,
+ char *msg, u32 poll_cnt)
+{
+ u32 val = bnx2x_flr_clnup_reg_poll(bp, reg, 0, poll_cnt);
+ if (val != 0) {
+ BNX2X_ERR("%s usage count=%d\n", msg, val);
+ return 1;
+ }
+ return 0;
+}
+
+static u32 bnx2x_flr_clnup_poll_count(struct bnx2x *bp)
+{
+ /* adjust polling timeout */
+ if (CHIP_REV_IS_EMUL(bp))
+ return FLR_POLL_CNT * 2000;
+
+ if (CHIP_REV_IS_FPGA(bp))
+ return FLR_POLL_CNT * 120;
+
+ return FLR_POLL_CNT;
+}
+
+static void bnx2x_tx_hw_flushed(struct bnx2x *bp, u32 poll_count)
+{
+ struct pbf_pN_cmd_regs cmd_regs[] = {
+ {0, (CHIP_IS_E3B0(bp)) ?
+ PBF_REG_TQ_OCCUPANCY_Q0 :
+ PBF_REG_P0_TQ_OCCUPANCY,
+ (CHIP_IS_E3B0(bp)) ?
+ PBF_REG_TQ_LINES_FREED_CNT_Q0 :
+ PBF_REG_P0_TQ_LINES_FREED_CNT},
+ {1, (CHIP_IS_E3B0(bp)) ?
+ PBF_REG_TQ_OCCUPANCY_Q1 :
+ PBF_REG_P1_TQ_OCCUPANCY,
+ (CHIP_IS_E3B0(bp)) ?
+ PBF_REG_TQ_LINES_FREED_CNT_Q1 :
+ PBF_REG_P1_TQ_LINES_FREED_CNT},
+ {4, (CHIP_IS_E3B0(bp)) ?
+ PBF_REG_TQ_OCCUPANCY_LB_Q :
+ PBF_REG_P4_TQ_OCCUPANCY,
+ (CHIP_IS_E3B0(bp)) ?
+ PBF_REG_TQ_LINES_FREED_CNT_LB_Q :
+ PBF_REG_P4_TQ_LINES_FREED_CNT}
+ };
+
+ struct pbf_pN_buf_regs buf_regs[] = {
+ {0, (CHIP_IS_E3B0(bp)) ?
+ PBF_REG_INIT_CRD_Q0 :
+ PBF_REG_P0_INIT_CRD ,
+ (CHIP_IS_E3B0(bp)) ?
+ PBF_REG_CREDIT_Q0 :
+ PBF_REG_P0_CREDIT,
+ (CHIP_IS_E3B0(bp)) ?
+ PBF_REG_INTERNAL_CRD_FREED_CNT_Q0 :
+ PBF_REG_P0_INTERNAL_CRD_FREED_CNT},
+ {1, (CHIP_IS_E3B0(bp)) ?
+ PBF_REG_INIT_CRD_Q1 :
+ PBF_REG_P1_INIT_CRD,
+ (CHIP_IS_E3B0(bp)) ?
+ PBF_REG_CREDIT_Q1 :
+ PBF_REG_P1_CREDIT,
+ (CHIP_IS_E3B0(bp)) ?
+ PBF_REG_INTERNAL_CRD_FREED_CNT_Q1 :
+ PBF_REG_P1_INTERNAL_CRD_FREED_CNT},
+ {4, (CHIP_IS_E3B0(bp)) ?
+ PBF_REG_INIT_CRD_LB_Q :
+ PBF_REG_P4_INIT_CRD,
+ (CHIP_IS_E3B0(bp)) ?
+ PBF_REG_CREDIT_LB_Q :
+ PBF_REG_P4_CREDIT,
+ (CHIP_IS_E3B0(bp)) ?
+ PBF_REG_INTERNAL_CRD_FREED_CNT_LB_Q :
+ PBF_REG_P4_INTERNAL_CRD_FREED_CNT},
+ };
+
+ int i;
+
+ /* Verify the command queues are flushed P0, P1, P4 */
+ for (i = 0; i < ARRAY_SIZE(cmd_regs); i++)
+ bnx2x_pbf_pN_cmd_flushed(bp, &cmd_regs[i], poll_count);
+
+
+ /* Verify the transmission buffers are flushed P0, P1, P4 */
+ for (i = 0; i < ARRAY_SIZE(buf_regs); i++)
+ bnx2x_pbf_pN_buf_flushed(bp, &buf_regs[i], poll_count);
+}
+
+#define OP_GEN_PARAM(param) \
+ (((param) << SDM_OP_GEN_COMP_PARAM_SHIFT) & SDM_OP_GEN_COMP_PARAM)
+
+#define OP_GEN_TYPE(type) \
+ (((type) << SDM_OP_GEN_COMP_TYPE_SHIFT) & SDM_OP_GEN_COMP_TYPE)
+
+#define OP_GEN_AGG_VECT(index) \
+ (((index) << SDM_OP_GEN_AGG_VECT_IDX_SHIFT) & SDM_OP_GEN_AGG_VECT_IDX)
+
+
+static inline int bnx2x_send_final_clnup(struct bnx2x *bp, u8 clnup_func,
+ u32 poll_cnt)
+{
+ struct sdm_op_gen op_gen = {0};
+
+ u32 comp_addr = BAR_CSTRORM_INTMEM +
+ CSTORM_FINAL_CLEANUP_COMPLETE_OFFSET(clnup_func);
+ int ret = 0;
+
+ if (REG_RD(bp, comp_addr)) {
+ BNX2X_ERR("Cleanup complete is not 0\n");
+ return 1;
+ }
+
+ op_gen.command |= OP_GEN_PARAM(XSTORM_AGG_INT_FINAL_CLEANUP_INDEX);
+ op_gen.command |= OP_GEN_TYPE(XSTORM_AGG_INT_FINAL_CLEANUP_COMP_TYPE);
+ op_gen.command |= OP_GEN_AGG_VECT(clnup_func);
+ op_gen.command |= 1 << SDM_OP_GEN_AGG_VECT_IDX_VALID_SHIFT;
+
+ DP(BNX2X_MSG_SP, "FW Final cleanup\n");
+ REG_WR(bp, XSDM_REG_OPERATION_GEN, op_gen.command);
+
+ if (bnx2x_flr_clnup_reg_poll(bp, comp_addr, 1, poll_cnt) != 1) {
+ BNX2X_ERR("FW final cleanup did not succeed\n");
+ ret = 1;
+ }
+ /* Zero completion for nxt FLR */
+ REG_WR(bp, comp_addr, 0);
+
+ return ret;
+}
+
+static inline u8 bnx2x_is_pcie_pending(struct pci_dev *dev)
+{
+ int pos;
+ u16 status;
+
+ pos = pci_pcie_cap(dev);
+ if (!pos)
+ return false;
+
+ pci_read_config_word(dev, pos + PCI_EXP_DEVSTA, &status);
+ return status & PCI_EXP_DEVSTA_TRPND;
+}
+
+/* PF FLR specific routines
+*/
+static int bnx2x_poll_hw_usage_counters(struct bnx2x *bp, u32 poll_cnt)
+{
+
+ /* wait for CFC PF usage-counter to zero (includes all the VFs) */
+ if (bnx2x_flr_clnup_poll_hw_counter(bp,
+ CFC_REG_NUM_LCIDS_INSIDE_PF,
+ "CFC PF usage counter timed out",
+ poll_cnt))
+ return 1;
+
+
+ /* Wait for DQ PF usage-counter to zero (until DQ cleanup) */
+ if (bnx2x_flr_clnup_poll_hw_counter(bp,
+ DORQ_REG_PF_USAGE_CNT,
+ "DQ PF usage counter timed out",
+ poll_cnt))
+ return 1;
+
+ /* Wait for QM PF usage-counter to zero (until DQ cleanup) */
+ if (bnx2x_flr_clnup_poll_hw_counter(bp,
+ QM_REG_PF_USG_CNT_0 + 4*BP_FUNC(bp),
+ "QM PF usage counter timed out",
+ poll_cnt))
+ return 1;
+
+ /* Wait for Timer PF usage-counters to zero (until DQ cleanup) */
+ if (bnx2x_flr_clnup_poll_hw_counter(bp,
+ TM_REG_LIN0_VNIC_UC + 4*BP_PORT(bp),
+ "Timers VNIC usage counter timed out",
+ poll_cnt))
+ return 1;
+ if (bnx2x_flr_clnup_poll_hw_counter(bp,
+ TM_REG_LIN0_NUM_SCANS + 4*BP_PORT(bp),
+ "Timers NUM_SCANS usage counter timed out",
+ poll_cnt))
+ return 1;
+
+ /* Wait DMAE PF usage counter to zero */
+ if (bnx2x_flr_clnup_poll_hw_counter(bp,
+ dmae_reg_go_c[INIT_DMAE_C(bp)],
+ "DMAE dommand register timed out",
+ poll_cnt))
+ return 1;
+
+ return 0;
+}
+
+static void bnx2x_hw_enable_status(struct bnx2x *bp)
+{
+ u32 val;
+
+ val = REG_RD(bp, CFC_REG_WEAK_ENABLE_PF);
+ DP(BNX2X_MSG_SP, "CFC_REG_WEAK_ENABLE_PF is 0x%x\n", val);
+
+ val = REG_RD(bp, PBF_REG_DISABLE_PF);
+ DP(BNX2X_MSG_SP, "PBF_REG_DISABLE_PF is 0x%x\n", val);
+
+ val = REG_RD(bp, IGU_REG_PCI_PF_MSI_EN);
+ DP(BNX2X_MSG_SP, "IGU_REG_PCI_PF_MSI_EN is 0x%x\n", val);
+
+ val = REG_RD(bp, IGU_REG_PCI_PF_MSIX_EN);
+ DP(BNX2X_MSG_SP, "IGU_REG_PCI_PF_MSIX_EN is 0x%x\n", val);
+
+ val = REG_RD(bp, IGU_REG_PCI_PF_MSIX_FUNC_MASK);
+ DP(BNX2X_MSG_SP, "IGU_REG_PCI_PF_MSIX_FUNC_MASK is 0x%x\n", val);
+
+ val = REG_RD(bp, PGLUE_B_REG_SHADOW_BME_PF_7_0_CLR);
+ DP(BNX2X_MSG_SP, "PGLUE_B_REG_SHADOW_BME_PF_7_0_CLR is 0x%x\n", val);
+
+ val = REG_RD(bp, PGLUE_B_REG_FLR_REQUEST_PF_7_0_CLR);
+ DP(BNX2X_MSG_SP, "PGLUE_B_REG_FLR_REQUEST_PF_7_0_CLR is 0x%x\n", val);
+
+ val = REG_RD(bp, PGLUE_B_REG_INTERNAL_PFID_ENABLE_MASTER);
+ DP(BNX2X_MSG_SP, "PGLUE_B_REG_INTERNAL_PFID_ENABLE_MASTER is 0x%x\n",
+ val);
+}
+
+static int bnx2x_pf_flr_clnup(struct bnx2x *bp)
+{
+ u32 poll_cnt = bnx2x_flr_clnup_poll_count(bp);
+
+ DP(BNX2X_MSG_SP, "Cleanup after FLR PF[%d]\n", BP_ABS_FUNC(bp));
+
+ /* Re-enable PF target read access */
+ REG_WR(bp, PGLUE_B_REG_INTERNAL_PFID_ENABLE_TARGET_READ, 1);
+
+ /* Poll HW usage counters */
+ if (bnx2x_poll_hw_usage_counters(bp, poll_cnt))
+ return -EBUSY;
+
+ /* Zero the igu 'trailing edge' and 'leading edge' */
+
+ /* Send the FW cleanup command */
+ if (bnx2x_send_final_clnup(bp, (u8)BP_FUNC(bp), poll_cnt))
+ return -EBUSY;
+
+ /* ATC cleanup */
+
+ /* Verify TX hw is flushed */
+ bnx2x_tx_hw_flushed(bp, poll_cnt);
+
+ /* Wait 100ms (not adjusted according to platform) */
+ msleep(100);
+
+ /* Verify no pending pci transactions */
+ if (bnx2x_is_pcie_pending(bp->pdev))
+ BNX2X_ERR("PCIE Transactions still pending\n");
+
+ /* Debug */
+ bnx2x_hw_enable_status(bp);
+
+ /*
+ * Master enable - Due to WB DMAE writes performed before this
+ * register is re-initialized as part of the regular function init
+ */
+ REG_WR(bp, PGLUE_B_REG_INTERNAL_PFID_ENABLE_MASTER, 1);
+
+ return 0;
+}
+
static void bnx2x_hc_int_enable(struct bnx2x *bp)
{
int port = BP_PORT(bp);
@@ -1286,10 +1546,6 @@
int msix = (bp->flags & USING_MSIX_FLAG) ? 1 : 0;
int i, offset;
- /* disable interrupt handling */
- atomic_inc(&bp->intr_sem);
- smp_wmb(); /* Ensure that bp->intr_sem update is SMP-safe */
-
if (disable_hw)
/* prevent the HW from sending interrupts */
bnx2x_int_disable(bp);
@@ -1302,12 +1558,13 @@
offset++;
#endif
for_each_eth_queue(bp, i)
- synchronize_irq(bp->msix_table[i + offset].vector);
+ synchronize_irq(bp->msix_table[offset++].vector);
} else
synchronize_irq(bp->pdev->irq);
/* make sure sp_task is not running */
cancel_delayed_work(&bp->sp_task);
+ cancel_delayed_work(&bp->period_task);
flush_workqueue(bnx2x_wq);
}
@@ -1351,53 +1608,114 @@
return false;
}
+/**
+ * bnx2x_get_leader_lock_resource - get the recovery leader resource id
+ *
+ * @bp: driver handle
+ *
+ * Returns the recovery leader resource id according to the engine this function
+ * belongs to. Currently only only 2 engines is supported.
+ */
+static inline int bnx2x_get_leader_lock_resource(struct bnx2x *bp)
+{
+ if (BP_PATH(bp))
+ return HW_LOCK_RESOURCE_RECOVERY_LEADER_1;
+ else
+ return HW_LOCK_RESOURCE_RECOVERY_LEADER_0;
+}
+
+/**
+ * bnx2x_trylock_leader_lock- try to aquire a leader lock.
+ *
+ * @bp: driver handle
+ *
+ * Tries to aquire a leader lock for cuurent engine.
+ */
+static inline bool bnx2x_trylock_leader_lock(struct bnx2x *bp)
+{
+ return bnx2x_trylock_hw_lock(bp, bnx2x_get_leader_lock_resource(bp));
+}
+
#ifdef BCM_CNIC
-static void bnx2x_cnic_cfc_comp(struct bnx2x *bp, int cid);
+static void bnx2x_cnic_cfc_comp(struct bnx2x *bp, int cid, u8 err);
#endif
-void bnx2x_sp_event(struct bnx2x_fastpath *fp,
- union eth_rx_cqe *rr_cqe)
+void bnx2x_sp_event(struct bnx2x_fastpath *fp, union eth_rx_cqe *rr_cqe)
{
struct bnx2x *bp = fp->bp;
int cid = SW_CID(rr_cqe->ramrod_cqe.conn_and_cmd_data);
int command = CQE_CMD(rr_cqe->ramrod_cqe.conn_and_cmd_data);
+ enum bnx2x_queue_cmd drv_cmd = BNX2X_Q_CMD_MAX;
+ struct bnx2x_queue_sp_obj *q_obj = &fp->q_obj;
DP(BNX2X_MSG_SP,
"fp %d cid %d got ramrod #%d state is %x type is %d\n",
fp->index, cid, command, bp->state,
rr_cqe->ramrod_cqe.ramrod_type);
- switch (command | fp->state) {
- case (RAMROD_CMD_ID_ETH_CLIENT_SETUP | BNX2X_FP_STATE_OPENING):
+ switch (command) {
+ case (RAMROD_CMD_ID_ETH_CLIENT_UPDATE):
+ DP(NETIF_MSG_IFUP, "got UPDATE ramrod. CID %d\n", cid);
+ drv_cmd = BNX2X_Q_CMD_UPDATE;
+ break;
+ case (RAMROD_CMD_ID_ETH_CLIENT_SETUP):
DP(NETIF_MSG_IFUP, "got MULTI[%d] setup ramrod\n", cid);
- fp->state = BNX2X_FP_STATE_OPEN;
+ drv_cmd = BNX2X_Q_CMD_SETUP;
break;
- case (RAMROD_CMD_ID_ETH_HALT | BNX2X_FP_STATE_HALTING):
+ case (RAMROD_CMD_ID_ETH_HALT):
DP(NETIF_MSG_IFDOWN, "got MULTI[%d] halt ramrod\n", cid);
- fp->state = BNX2X_FP_STATE_HALTED;
+ drv_cmd = BNX2X_Q_CMD_HALT;
break;
- case (RAMROD_CMD_ID_ETH_TERMINATE | BNX2X_FP_STATE_TERMINATING):
+ case (RAMROD_CMD_ID_ETH_TERMINATE):
DP(NETIF_MSG_IFDOWN, "got MULTI[%d] teminate ramrod\n", cid);
- fp->state = BNX2X_FP_STATE_TERMINATED;
+ drv_cmd = BNX2X_Q_CMD_TERMINATE;
+ break;
+
+ case (RAMROD_CMD_ID_ETH_EMPTY):
+ DP(NETIF_MSG_IFDOWN, "got MULTI[%d] empty ramrod\n", cid);
+ drv_cmd = BNX2X_Q_CMD_EMPTY;
break;
default:
- BNX2X_ERR("unexpected MC reply (%d) "
- "fp[%d] state is %x\n",
- command, fp->index, fp->state);
- break;
+ BNX2X_ERR("unexpected MC reply (%d) on fp[%d]\n",
+ command, fp->index);
+ return;
}
+ if ((drv_cmd != BNX2X_Q_CMD_MAX) &&
+ q_obj->complete_cmd(bp, q_obj, drv_cmd))
+ /* q_obj->complete_cmd() failure means that this was
+ * an unexpected completion.
+ *
+ * In this case we don't want to increase the bp->spq_left
+ * because apparently we haven't sent this command the first
+ * place.
+ */
+#ifdef BNX2X_STOP_ON_ERROR
+ bnx2x_panic();
+#else
+ return;
+#endif
+
smp_mb__before_atomic_inc();
atomic_inc(&bp->cq_spq_left);
- /* push the change in fp->state and towards the memory */
- smp_wmb();
+ /* push the change in bp->spq_left and towards the memory */
+ smp_mb__after_atomic_inc();
return;
}
+void bnx2x_update_rx_prod(struct bnx2x *bp, struct bnx2x_fastpath *fp,
+ u16 bd_prod, u16 rx_comp_prod, u16 rx_sge_prod)
+{
+ u32 start = BAR_USTRORM_INTMEM + fp->ustorm_rx_prods_offset;
+
+ bnx2x_update_rx_prod_gen(bp, fp, bd_prod, rx_comp_prod, rx_sge_prod,
+ start);
+}
+
irqreturn_t bnx2x_interrupt(int irq, void *dev_instance)
{
struct bnx2x *bp = netdev_priv(dev_instance);
@@ -1412,12 +1730,6 @@
}
DP(NETIF_MSG_INTR, "got an interrupt status 0x%x\n", status);
- /* Return here if interrupt is disabled */
- if (unlikely(atomic_read(&bp->intr_sem) != 0)) {
- DP(NETIF_MSG_INTR, "called but intr_sem not 0, returning\n");
- return IRQ_HANDLED;
- }
-
#ifdef BNX2X_STOP_ON_ERROR
if (unlikely(bp->panic))
return IRQ_HANDLED;
@@ -1428,7 +1740,7 @@
mask = 0x2 << (fp->index + CNIC_CONTEXT_USE);
if (status & mask) {
- /* Handle Rx and Tx according to SB id */
+ /* Handle Rx or Tx according to SB id */
prefetch(fp->rx_cons_sb);
prefetch(fp->tx_cons_sb);
prefetch(&fp->sb_running_index[SM_RX_ID]);
@@ -1442,11 +1754,13 @@
if (status & (mask | 0x1)) {
struct cnic_ops *c_ops = NULL;
- rcu_read_lock();
- c_ops = rcu_dereference(bp->cnic_ops);
- if (c_ops)
- c_ops->cnic_handler(bp->cnic_data, NULL);
- rcu_read_unlock();
+ if (likely(bp->state == BNX2X_STATE_OPEN)) {
+ rcu_read_lock();
+ c_ops = rcu_dereference(bp->cnic_ops);
+ if (c_ops)
+ c_ops->cnic_handler(bp->cnic_data, NULL);
+ rcu_read_unlock();
+ }
status &= ~mask;
}
@@ -1467,9 +1781,6 @@
return IRQ_HANDLED;
}
-/* end of fast path */
-
-
/* Link */
/*
@@ -1521,6 +1832,11 @@
return -EAGAIN;
}
+int bnx2x_release_leader_lock(struct bnx2x *bp)
+{
+ return bnx2x_release_hw_lock(bp, bnx2x_get_leader_lock_resource(bp));
+}
+
int bnx2x_release_hw_lock(struct bnx2x *bp, u32 resource)
{
u32 lock_status;
@@ -1641,6 +1957,53 @@
return 0;
}
+int bnx2x_set_mult_gpio(struct bnx2x *bp, u8 pins, u32 mode)
+{
+ u32 gpio_reg = 0;
+ int rc = 0;
+
+ /* Any port swapping should be handled by caller. */
+
+ bnx2x_acquire_hw_lock(bp, HW_LOCK_RESOURCE_GPIO);
+ /* read GPIO and mask except the float bits */
+ gpio_reg = REG_RD(bp, MISC_REG_GPIO);
+ gpio_reg &= ~(pins << MISC_REGISTERS_GPIO_FLOAT_POS);
+ gpio_reg &= ~(pins << MISC_REGISTERS_GPIO_CLR_POS);
+ gpio_reg &= ~(pins << MISC_REGISTERS_GPIO_SET_POS);
+
+ switch (mode) {
+ case MISC_REGISTERS_GPIO_OUTPUT_LOW:
+ DP(NETIF_MSG_LINK, "Set GPIO 0x%x -> output low\n", pins);
+ /* set CLR */
+ gpio_reg |= (pins << MISC_REGISTERS_GPIO_CLR_POS);
+ break;
+
+ case MISC_REGISTERS_GPIO_OUTPUT_HIGH:
+ DP(NETIF_MSG_LINK, "Set GPIO 0x%x -> output high\n", pins);
+ /* set SET */
+ gpio_reg |= (pins << MISC_REGISTERS_GPIO_SET_POS);
+ break;
+
+ case MISC_REGISTERS_GPIO_INPUT_HI_Z:
+ DP(NETIF_MSG_LINK, "Set GPIO 0x%x -> input\n", pins);
+ /* set FLOAT */
+ gpio_reg |= (pins << MISC_REGISTERS_GPIO_FLOAT_POS);
+ break;
+
+ default:
+ BNX2X_ERR("Invalid GPIO mode assignment %d\n", mode);
+ rc = -EINVAL;
+ break;
+ }
+
+ if (rc == 0)
+ REG_WR(bp, MISC_REG_GPIO, gpio_reg);
+
+ bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_GPIO);
+
+ return rc;
+}
+
int bnx2x_set_gpio_int(struct bnx2x *bp, int gpio_num, u32 mode, u8 port)
{
/* The GPIO should be swapped if swap register is set and active */
@@ -1733,45 +2096,6 @@
return 0;
}
-int bnx2x_get_link_cfg_idx(struct bnx2x *bp)
-{
- u32 sel_phy_idx = 0;
- if (bp->link_vars.link_up) {
- sel_phy_idx = EXT_PHY1;
- /* In case link is SERDES, check if the EXT_PHY2 is the one */
- if ((bp->link_vars.link_status & LINK_STATUS_SERDES_LINK) &&
- (bp->link_params.phy[EXT_PHY2].supported & SUPPORTED_FIBRE))
- sel_phy_idx = EXT_PHY2;
- } else {
-
- switch (bnx2x_phy_selection(&bp->link_params)) {
- case PORT_HW_CFG_PHY_SELECTION_HARDWARE_DEFAULT:
- case PORT_HW_CFG_PHY_SELECTION_FIRST_PHY:
- case PORT_HW_CFG_PHY_SELECTION_FIRST_PHY_PRIORITY:
- sel_phy_idx = EXT_PHY1;
- break;
- case PORT_HW_CFG_PHY_SELECTION_SECOND_PHY:
- case PORT_HW_CFG_PHY_SELECTION_SECOND_PHY_PRIORITY:
- sel_phy_idx = EXT_PHY2;
- break;
- }
- }
- /*
- * The selected actived PHY is always after swapping (in case PHY
- * swapping is enabled). So when swapping is enabled, we need to reverse
- * the configuration
- */
-
- if (bp->link_params.multi_phy_config &
- PORT_HW_CFG_PHY_SWAPPED_ENABLED) {
- if (sel_phy_idx == EXT_PHY1)
- sel_phy_idx = EXT_PHY2;
- else if (sel_phy_idx == EXT_PHY2)
- sel_phy_idx = EXT_PHY1;
- }
- return LINK_CONFIG_IDX(sel_phy_idx);
-}
-
void bnx2x_calc_fc_adv(struct bnx2x *bp)
{
u8 cfg_idx = bnx2x_get_link_cfg_idx(bp);
@@ -1828,7 +2152,8 @@
if (CHIP_REV_IS_SLOW(bp) && bp->link_vars.link_up) {
bnx2x_stats_handle(bp, STATS_EVENT_LINK_UP);
bnx2x_link_report(bp);
- }
+ } else
+ queue_delayed_work(bnx2x_wq, &bp->period_task, 0);
bp->link_params.req_line_speed[cfx_idx] = req_line_speed;
return rc;
}
@@ -1942,8 +2267,12 @@
bp->vn_weight_sum += vn_min_rate;
}
- /* ... only if all min rates are zeros - disable fairness */
- if (all_zero) {
+ /* if ETS or all min rates are zeros - disable fairness */
+ if (BNX2X_IS_ETS_ENABLED(bp)) {
+ bp->cmng.flags.cmng_enables &=
+ ~CMNG_FLAGS_PER_PORT_FAIRNESS_VN;
+ DP(NETIF_MSG_IFUP, "Fairness will be disabled due to ETS\n");
+ } else if (all_zero) {
bp->cmng.flags.cmng_enables &=
~CMNG_FLAGS_PER_PORT_FAIRNESS_VN;
DP(NETIF_MSG_IFUP, "All MIN values are zeroes"
@@ -2144,11 +2473,11 @@
pause_enabled);
}
- if (bp->link_vars.mac_type == MAC_TYPE_BMAC) {
+ if (bp->link_vars.mac_type != MAC_TYPE_EMAC) {
struct host_port_stats *pstats;
pstats = bnx2x_sp(bp, port_stats);
- /* reset old bmac stats */
+ /* reset old mac stats */
memset(&(pstats->mac_stx[0]), 0,
sizeof(struct mac_stx));
}
@@ -2198,12 +2527,23 @@
bp->port.pmf = 1;
DP(NETIF_MSG_LINK, "pmf %d\n", bp->port.pmf);
+ /*
+ * We need the mb() to ensure the ordering between the writing to
+ * bp->port.pmf here and reading it from the bnx2x_periodic_task().
+ */
+ smp_mb();
+
+ /* queue a periodic task */
+ queue_delayed_work(bnx2x_wq, &bp->period_task, 0);
+
+ bnx2x_dcbx_pmf_update(bp);
+
/* enable nig attention */
val = (0xff0f | (1 << (BP_E1HVN(bp) + 4)));
if (bp->common.int_block == INT_BLOCK_HC) {
REG_WR(bp, HC_REG_TRAILING_EDGE_0 + port*8, val);
REG_WR(bp, HC_REG_LEADING_EDGE_0 + port*8, val);
- } else if (CHIP_IS_E2(bp)) {
+ } else if (!CHIP_IS_E1x(bp)) {
REG_WR(bp, IGU_REG_TRAILING_EDGE_LATCH, val);
REG_WR(bp, IGU_REG_LEADING_EDGE_LATCH, val);
}
@@ -2233,7 +2573,8 @@
SHMEM_WR(bp, func_mb[mb_idx].drv_mb_param, param);
SHMEM_WR(bp, func_mb[mb_idx].drv_mb_header, (command | seq));
- DP(BNX2X_MSG_MCP, "wrote command (%x) to FW MB\n", (command | seq));
+ DP(BNX2X_MSG_MCP, "wrote command (%x) to FW MB param 0x%08x\n",
+ (command | seq), param);
do {
/* let the FW do it's magic ... */
@@ -2264,141 +2605,25 @@
static u8 stat_counter_valid(struct bnx2x *bp, struct bnx2x_fastpath *fp)
{
#ifdef BCM_CNIC
- if (IS_FCOE_FP(fp) && IS_MF(bp))
+ /* Statistics are not supported for CNIC Clients at the moment */
+ if (IS_FCOE_FP(fp))
return false;
#endif
return true;
}
-/* must be called under rtnl_lock */
-static void bnx2x_rxq_set_mac_filters(struct bnx2x *bp, u16 cl_id, u32 filters)
+void bnx2x_func_init(struct bnx2x *bp, struct bnx2x_func_init_params *p)
{
- u32 mask = (1 << cl_id);
+ if (CHIP_IS_E1x(bp)) {
+ struct tstorm_eth_function_common_config tcfg = {0};
- /* initial seeting is BNX2X_ACCEPT_NONE */
- u8 drop_all_ucast = 1, drop_all_bcast = 1, drop_all_mcast = 1;
- u8 accp_all_ucast = 0, accp_all_bcast = 0, accp_all_mcast = 0;
- u8 unmatched_unicast = 0;
-
- if (filters & BNX2X_ACCEPT_UNMATCHED_UCAST)
- unmatched_unicast = 1;
-
- if (filters & BNX2X_PROMISCUOUS_MODE) {
- /* promiscious - accept all, drop none */
- drop_all_ucast = drop_all_bcast = drop_all_mcast = 0;
- accp_all_ucast = accp_all_bcast = accp_all_mcast = 1;
- if (IS_MF_SI(bp)) {
- /*
- * SI mode defines to accept in promiscuos mode
- * only unmatched packets
- */
- unmatched_unicast = 1;
- accp_all_ucast = 0;
- }
+ storm_memset_func_cfg(bp, &tcfg, p->func_id);
}
- if (filters & BNX2X_ACCEPT_UNICAST) {
- /* accept matched ucast */
- drop_all_ucast = 0;
- }
- if (filters & BNX2X_ACCEPT_MULTICAST)
- /* accept matched mcast */
- drop_all_mcast = 0;
-
- if (filters & BNX2X_ACCEPT_ALL_UNICAST) {
- /* accept all mcast */
- drop_all_ucast = 0;
- accp_all_ucast = 1;
- }
- if (filters & BNX2X_ACCEPT_ALL_MULTICAST) {
- /* accept all mcast */
- drop_all_mcast = 0;
- accp_all_mcast = 1;
- }
- if (filters & BNX2X_ACCEPT_BROADCAST) {
- /* accept (all) bcast */
- drop_all_bcast = 0;
- accp_all_bcast = 1;
- }
-
- bp->mac_filters.ucast_drop_all = drop_all_ucast ?
- bp->mac_filters.ucast_drop_all | mask :
- bp->mac_filters.ucast_drop_all & ~mask;
-
- bp->mac_filters.mcast_drop_all = drop_all_mcast ?
- bp->mac_filters.mcast_drop_all | mask :
- bp->mac_filters.mcast_drop_all & ~mask;
-
- bp->mac_filters.bcast_drop_all = drop_all_bcast ?
- bp->mac_filters.bcast_drop_all | mask :
- bp->mac_filters.bcast_drop_all & ~mask;
-
- bp->mac_filters.ucast_accept_all = accp_all_ucast ?
- bp->mac_filters.ucast_accept_all | mask :
- bp->mac_filters.ucast_accept_all & ~mask;
-
- bp->mac_filters.mcast_accept_all = accp_all_mcast ?
- bp->mac_filters.mcast_accept_all | mask :
- bp->mac_filters.mcast_accept_all & ~mask;
-
- bp->mac_filters.bcast_accept_all = accp_all_bcast ?
- bp->mac_filters.bcast_accept_all | mask :
- bp->mac_filters.bcast_accept_all & ~mask;
-
- bp->mac_filters.unmatched_unicast = unmatched_unicast ?
- bp->mac_filters.unmatched_unicast | mask :
- bp->mac_filters.unmatched_unicast & ~mask;
-}
-
-static void bnx2x_func_init(struct bnx2x *bp, struct bnx2x_func_init_params *p)
-{
- struct tstorm_eth_function_common_config tcfg = {0};
- u16 rss_flgs;
-
- /* tpa */
- if (p->func_flgs & FUNC_FLG_TPA)
- tcfg.config_flags |=
- TSTORM_ETH_FUNCTION_COMMON_CONFIG_ENABLE_TPA;
-
- /* set rss flags */
- rss_flgs = (p->rss->mode <<
- TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_MODE_SHIFT);
-
- if (p->rss->cap & RSS_IPV4_CAP)
- rss_flgs |= RSS_IPV4_CAP_MASK;
- if (p->rss->cap & RSS_IPV4_TCP_CAP)
- rss_flgs |= RSS_IPV4_TCP_CAP_MASK;
- if (p->rss->cap & RSS_IPV6_CAP)
- rss_flgs |= RSS_IPV6_CAP_MASK;
- if (p->rss->cap & RSS_IPV6_TCP_CAP)
- rss_flgs |= RSS_IPV6_TCP_CAP_MASK;
-
- tcfg.config_flags |= rss_flgs;
- tcfg.rss_result_mask = p->rss->result_mask;
-
- storm_memset_func_cfg(bp, &tcfg, p->func_id);
/* Enable the function in the FW */
storm_memset_vf_to_pf(bp, p->func_id, p->pf_id);
storm_memset_func_en(bp, p->func_id, 1);
- /* statistics */
- if (p->func_flgs & FUNC_FLG_STATS) {
- struct stats_indication_flags stats_flags = {0};
- stats_flags.collect_eth = 1;
-
- storm_memset_xstats_flags(bp, &stats_flags, p->func_id);
- storm_memset_xstats_addr(bp, p->fw_stat_map, p->func_id);
-
- storm_memset_tstats_flags(bp, &stats_flags, p->func_id);
- storm_memset_tstats_addr(bp, p->fw_stat_map, p->func_id);
-
- storm_memset_ustats_flags(bp, &stats_flags, p->func_id);
- storm_memset_ustats_addr(bp, p->fw_stat_map, p->func_id);
-
- storm_memset_cstats_flags(bp, &stats_flags, p->func_id);
- storm_memset_cstats_addr(bp, p->fw_stat_map, p->func_id);
- }
-
/* spq */
if (p->func_flgs & FUNC_FLG_SPQ) {
storm_memset_spq_addr(bp, p->spq_map, p->func_id);
@@ -2407,39 +2632,62 @@
}
}
-static inline u16 bnx2x_get_cl_flags(struct bnx2x *bp,
- struct bnx2x_fastpath *fp)
+static inline unsigned long bnx2x_get_q_flags(struct bnx2x *bp,
+ struct bnx2x_fastpath *fp,
+ bool leading)
{
- u16 flags = 0;
+ unsigned long flags = 0;
- /* calculate queue flags */
- flags |= QUEUE_FLG_CACHE_ALIGN;
- flags |= QUEUE_FLG_HC;
- flags |= IS_MF_SD(bp) ? QUEUE_FLG_OV : 0;
+ /* PF driver will always initialize the Queue to an ACTIVE state */
+ __set_bit(BNX2X_Q_FLG_ACTIVE, &flags);
- flags |= QUEUE_FLG_VLAN;
- DP(NETIF_MSG_IFUP, "vlan removal enabled\n");
+ /* calculate other queue flags */
+ if (IS_MF_SD(bp))
+ __set_bit(BNX2X_Q_FLG_OV, &flags);
+
+ if (IS_FCOE_FP(fp))
+ __set_bit(BNX2X_Q_FLG_FCOE, &flags);
if (!fp->disable_tpa)
- flags |= QUEUE_FLG_TPA;
+ __set_bit(BNX2X_Q_FLG_TPA, &flags);
- flags = stat_counter_valid(bp, fp) ?
- (flags | QUEUE_FLG_STATS) : (flags & ~QUEUE_FLG_STATS);
+ if (stat_counter_valid(bp, fp)) {
+ __set_bit(BNX2X_Q_FLG_STATS, &flags);
+ __set_bit(BNX2X_Q_FLG_ZERO_STATS, &flags);
+ }
+
+ if (leading) {
+ __set_bit(BNX2X_Q_FLG_LEADING_RSS, &flags);
+ __set_bit(BNX2X_Q_FLG_MCAST, &flags);
+ }
+
+ /* Always set HW VLAN stripping */
+ __set_bit(BNX2X_Q_FLG_VLAN, &flags);
return flags;
}
-static void bnx2x_pf_rx_cl_prep(struct bnx2x *bp,
- struct bnx2x_fastpath *fp, struct rxq_pause_params *pause,
- struct bnx2x_rxq_init_params *rxq_init)
+static void bnx2x_pf_q_prep_general(struct bnx2x *bp,
+ struct bnx2x_fastpath *fp, struct bnx2x_general_setup_params *gen_init)
{
- u16 max_sge = 0;
+ gen_init->stat_id = bnx2x_stats_id(fp);
+ gen_init->spcl_id = fp->cl_id;
+
+ /* Always use mini-jumbo MTU for FCoE L2 ring */
+ if (IS_FCOE_FP(fp))
+ gen_init->mtu = BNX2X_FCOE_MINI_JUMBO_MTU;
+ else
+ gen_init->mtu = bp->dev->mtu;
+}
+
+static void bnx2x_pf_rx_q_prep(struct bnx2x *bp,
+ struct bnx2x_fastpath *fp, struct rxq_pause_params *pause,
+ struct bnx2x_rxq_setup_params *rxq_init)
+{
+ u8 max_sge = 0;
u16 sge_sz = 0;
u16 tpa_agg_size = 0;
- /* calculate queue flags */
- u16 flags = bnx2x_get_cl_flags(bp, fp);
-
if (!fp->disable_tpa) {
pause->sge_th_hi = 250;
pause->sge_th_lo = 150;
@@ -2460,33 +2708,37 @@
pause->bd_th_lo = 250;
pause->rcq_th_hi = 350;
pause->rcq_th_lo = 250;
- pause->sge_th_hi = 0;
- pause->sge_th_lo = 0;
+
pause->pri_map = 1;
}
/* rxq setup */
- rxq_init->flags = flags;
- rxq_init->cxt = &bp->context.vcxt[fp->cid].eth;
rxq_init->dscr_map = fp->rx_desc_mapping;
rxq_init->sge_map = fp->rx_sge_mapping;
rxq_init->rcq_map = fp->rx_comp_mapping;
rxq_init->rcq_np_map = fp->rx_comp_mapping + BCM_PAGE_SIZE;
- /* Always use mini-jumbo MTU for FCoE L2 ring */
- if (IS_FCOE_FP(fp))
- rxq_init->mtu = BNX2X_FCOE_MINI_JUMBO_MTU;
- else
- rxq_init->mtu = bp->dev->mtu;
+ /* This should be a maximum number of data bytes that may be
+ * placed on the BD (not including paddings).
+ */
+ rxq_init->buf_sz = fp->rx_buf_size - BNX2X_FW_RX_ALIGN -
+ IP_HEADER_ALIGNMENT_PADDING;
- rxq_init->buf_sz = fp->rx_buf_size;
rxq_init->cl_qzone_id = fp->cl_qzone_id;
- rxq_init->cl_id = fp->cl_id;
- rxq_init->spcl_id = fp->cl_id;
- rxq_init->stat_id = fp->cl_id;
rxq_init->tpa_agg_sz = tpa_agg_size;
rxq_init->sge_buf_sz = sge_sz;
rxq_init->max_sges_pkt = max_sge;
+ rxq_init->rss_engine_id = BP_FUNC(bp);
+
+ /* Maximum number or simultaneous TPA aggregation for this Queue.
+ *
+ * For PF Clients it should be the maximum avaliable number.
+ * VF driver(s) may want to define it to a smaller value.
+ */
+ rxq_init->max_tpa_queues =
+ (CHIP_IS_E1(bp) ? ETH_MAX_AGGREGATION_QUEUES_E1 :
+ ETH_MAX_AGGREGATION_QUEUES_E1H_E2);
+
rxq_init->cache_line_log = BNX2X_RX_ALIGN_SHIFT;
rxq_init->fw_sb_id = fp->fw_sb_id;
@@ -2494,46 +2746,35 @@
rxq_init->sb_cq_index = HC_SP_INDEX_ETH_FCOE_RX_CQ_CONS;
else
rxq_init->sb_cq_index = U_SB_ETH_RX_CQ_INDEX;
-
- rxq_init->cid = HW_CID(bp, fp->cid);
-
- rxq_init->hc_rate = bp->rx_ticks ? (1000000 / bp->rx_ticks) : 0;
}
-static void bnx2x_pf_tx_cl_prep(struct bnx2x *bp,
- struct bnx2x_fastpath *fp, struct bnx2x_txq_init_params *txq_init)
+static void bnx2x_pf_tx_q_prep(struct bnx2x *bp,
+ struct bnx2x_fastpath *fp, struct bnx2x_txq_setup_params *txq_init)
{
- u16 flags = bnx2x_get_cl_flags(bp, fp);
-
- txq_init->flags = flags;
- txq_init->cxt = &bp->context.vcxt[fp->cid].eth;
txq_init->dscr_map = fp->tx_desc_mapping;
- txq_init->stat_id = fp->cl_id;
- txq_init->cid = HW_CID(bp, fp->cid);
txq_init->sb_cq_index = C_SB_ETH_TX_CQ_INDEX;
txq_init->traffic_type = LLFC_TRAFFIC_TYPE_NW;
txq_init->fw_sb_id = fp->fw_sb_id;
+ /*
+ * set the tss leading client id for TX classfication ==
+ * leading RSS client id
+ */
+ txq_init->tss_leading_cl_id = bnx2x_fp(bp, 0, cl_id);
+
if (IS_FCOE_FP(fp)) {
txq_init->sb_cq_index = HC_SP_INDEX_ETH_FCOE_TX_CQ_CONS;
txq_init->traffic_type = LLFC_TRAFFIC_TYPE_FCOE;
}
-
- txq_init->hc_rate = bp->tx_ticks ? (1000000 / bp->tx_ticks) : 0;
}
static void bnx2x_pf_init(struct bnx2x *bp)
{
struct bnx2x_func_init_params func_init = {0};
- struct bnx2x_rss_params rss = {0};
struct event_ring_data eq_data = { {0} };
u16 flags;
- /* pf specific setups */
- if (!CHIP_IS_E1(bp))
- storm_memset_ov(bp, bp->mf_ov, BP_FUNC(bp));
-
- if (CHIP_IS_E2(bp)) {
+ if (!CHIP_IS_E1x(bp)) {
/* reset IGU PF statistics: MSIX + ATTN */
/* PF */
REG_WR(bp, IGU_REG_STATISTIC_NUM_MESSAGE_SENT +
@@ -2551,27 +2792,14 @@
/* function setup flags */
flags = (FUNC_FLG_STATS | FUNC_FLG_LEADING | FUNC_FLG_SPQ);
- if (CHIP_IS_E1x(bp))
- flags |= (bp->flags & TPA_ENABLE_FLAG) ? FUNC_FLG_TPA : 0;
- else
- flags |= FUNC_FLG_TPA;
-
- /* function setup */
-
- /**
- * Although RSS is meaningless when there is a single HW queue we
- * still need it enabled in order to have HW Rx hash generated.
+ /* This flag is relevant for E1x only.
+ * E2 doesn't have a TPA configuration in a function level.
*/
- rss.cap = (RSS_IPV4_CAP | RSS_IPV4_TCP_CAP |
- RSS_IPV6_CAP | RSS_IPV6_TCP_CAP);
- rss.mode = bp->multi_mode;
- rss.result_mask = MULTI_MASK;
- func_init.rss = &rss;
+ flags |= (bp->flags & TPA_ENABLE_FLAG) ? FUNC_FLG_TPA : 0;
func_init.func_flgs = flags;
func_init.pf_id = BP_FUNC(bp);
func_init.func_id = BP_FUNC(bp);
- func_init.fw_stat_map = bnx2x_sp_mapping(bp, fw_stats);
func_init.spq_map = bp->spq_mapping;
func_init.spq_prod = bp->spq_prod_idx;
@@ -2580,11 +2808,11 @@
memset(&(bp->cmng), 0, sizeof(struct cmng_struct_per_port));
/*
- Congestion management values depend on the link rate
- There is no active link so initial link rate is set to 10 Gbps.
- When the link comes up The congestion management values are
- re-calculated according to the actual link rate.
- */
+ * Congestion management values depend on the link rate
+ * There is no active link so initial link rate is set to 10 Gbps.
+ * When the link comes up The congestion management values are
+ * re-calculated according to the actual link rate.
+ */
bp->link_vars.line_speed = SPEED_10000;
bnx2x_cmng_fns_init(bp, true, bnx2x_get_cmng_fns_mode(bp));
@@ -2592,10 +2820,6 @@
if (bp->port.pmf)
storm_memset_cmng(bp, &bp->cmng, BP_PORT(bp));
- /* no rx until link is up */
- bp->rx_mode = BNX2X_RX_MODE_NONE;
- bnx2x_set_storm_rx_mode(bp);
-
/* init Event Queue */
eq_data.base_addr.hi = U64_HI(bp->eq_mapping);
eq_data.base_addr.lo = U64_LO(bp->eq_mapping);
@@ -2610,11 +2834,9 @@
{
int port = BP_PORT(bp);
- netif_tx_disable(bp->dev);
+ bnx2x_tx_disable(bp);
REG_WR(bp, NIG_REG_LLH0_FUNC_EN + port*8, 0);
-
- netif_carrier_off(bp->dev);
}
static void bnx2x_e1h_enable(struct bnx2x *bp)
@@ -2717,12 +2939,47 @@
mmiowb();
}
-/* the slow path queue is odd since completions arrive on the fastpath ring */
+/**
+ * bnx2x_is_contextless_ramrod - check if the current command ends on EQ
+ *
+ * @cmd: command to check
+ * @cmd_type: command type
+ */
+static inline bool bnx2x_is_contextless_ramrod(int cmd, int cmd_type)
+{
+ if ((cmd_type == NONE_CONNECTION_TYPE) ||
+ (cmd == RAMROD_CMD_ID_ETH_CLASSIFICATION_RULES) ||
+ (cmd == RAMROD_CMD_ID_ETH_FILTER_RULES) ||
+ (cmd == RAMROD_CMD_ID_ETH_MULTICAST_RULES) ||
+ (cmd == RAMROD_CMD_ID_ETH_SET_MAC) ||
+ (cmd == RAMROD_CMD_ID_ETH_RSS_UPDATE))
+ return true;
+ else
+ return false;
+
+}
+
+
+/**
+ * bnx2x_sp_post - place a single command on an SP ring
+ *
+ * @bp: driver handle
+ * @command: command to place (e.g. SETUP, FILTER_RULES, etc.)
+ * @cid: SW CID the command is related to
+ * @data_hi: command private data address (high 32 bits)
+ * @data_lo: command private data address (low 32 bits)
+ * @cmd_type: command type (e.g. NONE, ETH)
+ *
+ * SP data is handled as if it's always an address pair, thus data fields are
+ * not swapped to little endian in upper functions. Instead this function swaps
+ * data as if it's two u32 fields.
+ */
int bnx2x_sp_post(struct bnx2x *bp, int command, int cid,
- u32 data_hi, u32 data_lo, int common)
+ u32 data_hi, u32 data_lo, int cmd_type)
{
struct eth_spe *spe;
u16 type;
+ bool common = bnx2x_is_contextless_ramrod(command, cmd_type);
#ifdef BNX2X_STOP_ON_ERROR
if (unlikely(bp->panic))
@@ -2752,17 +3009,7 @@
cpu_to_le32((command << SPE_HDR_CMD_ID_SHIFT) |
HW_CID(bp, cid));
- if (common)
- /* Common ramrods:
- * FUNC_START, FUNC_STOP, CFC_DEL, STATS, SET_MAC
- * TRAFFIC_STOP, TRAFFIC_START
- */
- type = (NONE_CONNECTION_TYPE << SPE_HDR_CONN_TYPE_SHIFT)
- & SPE_HDR_CONN_TYPE;
- else
- /* ETH ramrods: SETUP, HALT */
- type = (ETH_CONNECTION_TYPE << SPE_HDR_CONN_TYPE_SHIFT)
- & SPE_HDR_CONN_TYPE;
+ type = (cmd_type << SPE_HDR_CONN_TYPE_SHIFT) & SPE_HDR_CONN_TYPE;
type |= ((BP_FUNC(bp) << SPE_HDR_FUNCTION_ID_SHIFT) &
SPE_HDR_FUNCTION_ID);
@@ -2774,7 +3021,8 @@
/* stats ramrod has it's own slot on the spq */
if (command != RAMROD_CMD_ID_COMMON_STAT_QUERY) {
- /* It's ok if the actual decrement is issued towards the memory
+ /*
+ * It's ok if the actual decrement is issued towards the memory
* somewhere between the spin_lock and spin_unlock. Thus no
* more explict memory barrier is needed.
*/
@@ -2893,9 +3141,15 @@
/* save nig interrupt mask */
nig_mask = REG_RD(bp, nig_int_mask_addr);
- REG_WR(bp, nig_int_mask_addr, 0);
- bnx2x_link_attn(bp);
+ /* If nig_mask is not set, no need to call the update
+ * function.
+ */
+ if (nig_mask) {
+ REG_WR(bp, nig_int_mask_addr, 0);
+
+ bnx2x_link_attn(bp);
+ }
/* handle unicore attn? */
}
@@ -3000,8 +3254,7 @@
bnx2x_fan_failure(bp);
}
- if (attn & (AEU_INPUTS_ATTN_BITS_GPIO3_FUNCTION_0 |
- AEU_INPUTS_ATTN_BITS_GPIO3_FUNCTION_1)) {
+ if ((attn & bp->link_vars.aeu_int_mask) && bp->port.pmf) {
bnx2x_acquire_phy_lock(bp);
bnx2x_handle_module_detect_int(&bp->link_params);
bnx2x_release_phy_lock(bp);
@@ -3064,13 +3317,13 @@
}
if (attn & AEU_INPUTS_ATTN_BITS_PXP_HW_INTERRUPT) {
-
val = REG_RD(bp, PXP_REG_PXP_INT_STS_CLR_0);
- BNX2X_ERR("PXP hw attention 0x%x\n", val);
+ BNX2X_ERR("PXP hw attention-0 0x%x\n", val);
/* RQ_USDMDP_FIFO_OVERFLOW */
if (val & 0x18000)
BNX2X_ERR("FATAL error from PXP\n");
- if (CHIP_IS_E2(bp)) {
+
+ if (!CHIP_IS_E1x(bp)) {
val = REG_RD(bp, PXP_REG_PXP_INT_STS_CLR_1);
BNX2X_ERR("PXP hw attention-1 0x%x\n", val);
}
@@ -3118,17 +3371,27 @@
if ((bp->port.pmf == 0) && (val & DRV_STATUS_PMF))
bnx2x_pmf_update(bp);
- /* Always call it here: bnx2x_link_report() will
- * prevent the link indication duplication.
- */
- bnx2x__link_status_update(bp);
-
if (bp->port.pmf &&
(val & DRV_STATUS_DCBX_NEGOTIATION_RESULTS) &&
bp->dcbx_enabled > 0)
/* start dcbx state machine */
bnx2x_dcbx_set_params(bp,
BNX2X_DCBX_STATE_NEG_RECEIVED);
+ if (bp->link_vars.periodic_flags &
+ PERIODIC_FLAGS_LINK_EVENT) {
+ /* sync with link */
+ bnx2x_acquire_phy_lock(bp);
+ bp->link_vars.periodic_flags &=
+ ~PERIODIC_FLAGS_LINK_EVENT;
+ bnx2x_release_phy_lock(bp);
+ if (IS_MF(bp))
+ bnx2x_link_sync_notify(bp);
+ bnx2x_link_report(bp);
+ }
+ /* Always call it here: bnx2x_link_report() will
+ * prevent the link indication duplication.
+ */
+ bnx2x__link_status_update(bp);
} else if (attn & BNX2X_MC_ASSERT_BITS) {
BNX2X_ERR("MC assert!\n");
@@ -3164,72 +3427,185 @@
}
}
-#define BNX2X_MISC_GEN_REG MISC_REG_GENERIC_POR_1
-#define LOAD_COUNTER_BITS 16 /* Number of bits for load counter */
-#define LOAD_COUNTER_MASK (((u32)0x1 << LOAD_COUNTER_BITS) - 1)
-#define RESET_DONE_FLAG_MASK (~LOAD_COUNTER_MASK)
-#define RESET_DONE_FLAG_SHIFT LOAD_COUNTER_BITS
+/*
+ * Bits map:
+ * 0-7 - Engine0 load counter.
+ * 8-15 - Engine1 load counter.
+ * 16 - Engine0 RESET_IN_PROGRESS bit.
+ * 17 - Engine1 RESET_IN_PROGRESS bit.
+ * 18 - Engine0 ONE_IS_LOADED. Set when there is at least one active function
+ * on the engine
+ * 19 - Engine1 ONE_IS_LOADED.
+ * 20 - Chip reset flow bit. When set none-leader must wait for both engines
+ * leader to complete (check for both RESET_IN_PROGRESS bits and not for
+ * just the one belonging to its engine).
+ *
+ */
+#define BNX2X_RECOVERY_GLOB_REG MISC_REG_GENERIC_POR_1
+
+#define BNX2X_PATH0_LOAD_CNT_MASK 0x000000ff
+#define BNX2X_PATH0_LOAD_CNT_SHIFT 0
+#define BNX2X_PATH1_LOAD_CNT_MASK 0x0000ff00
+#define BNX2X_PATH1_LOAD_CNT_SHIFT 8
+#define BNX2X_PATH0_RST_IN_PROG_BIT 0x00010000
+#define BNX2X_PATH1_RST_IN_PROG_BIT 0x00020000
+#define BNX2X_GLOBAL_RESET_BIT 0x00040000
/*
+ * Set the GLOBAL_RESET bit.
+ *
+ * Should be run under rtnl lock
+ */
+void bnx2x_set_reset_global(struct bnx2x *bp)
+{
+ u32 val = REG_RD(bp, BNX2X_RECOVERY_GLOB_REG);
+
+ REG_WR(bp, BNX2X_RECOVERY_GLOB_REG, val | BNX2X_GLOBAL_RESET_BIT);
+ barrier();
+ mmiowb();
+}
+
+/*
+ * Clear the GLOBAL_RESET bit.
+ *
+ * Should be run under rtnl lock
+ */
+static inline void bnx2x_clear_reset_global(struct bnx2x *bp)
+{
+ u32 val = REG_RD(bp, BNX2X_RECOVERY_GLOB_REG);
+
+ REG_WR(bp, BNX2X_RECOVERY_GLOB_REG, val & (~BNX2X_GLOBAL_RESET_BIT));
+ barrier();
+ mmiowb();
+}
+
+/*
+ * Checks the GLOBAL_RESET bit.
+ *
* should be run under rtnl lock
*/
+static inline bool bnx2x_reset_is_global(struct bnx2x *bp)
+{
+ u32 val = REG_RD(bp, BNX2X_RECOVERY_GLOB_REG);
+
+ DP(NETIF_MSG_HW, "GEN_REG_VAL=0x%08x\n", val);
+ return (val & BNX2X_GLOBAL_RESET_BIT) ? true : false;
+}
+
+/*
+ * Clear RESET_IN_PROGRESS bit for the current engine.
+ *
+ * Should be run under rtnl lock
+ */
static inline void bnx2x_set_reset_done(struct bnx2x *bp)
{
- u32 val = REG_RD(bp, BNX2X_MISC_GEN_REG);
- val &= ~(1 << RESET_DONE_FLAG_SHIFT);
- REG_WR(bp, BNX2X_MISC_GEN_REG, val);
+ u32 val = REG_RD(bp, BNX2X_RECOVERY_GLOB_REG);
+ u32 bit = BP_PATH(bp) ?
+ BNX2X_PATH1_RST_IN_PROG_BIT : BNX2X_PATH0_RST_IN_PROG_BIT;
+
+ /* Clear the bit */
+ val &= ~bit;
+ REG_WR(bp, BNX2X_RECOVERY_GLOB_REG, val);
barrier();
mmiowb();
}
/*
+ * Set RESET_IN_PROGRESS for the current engine.
+ *
* should be run under rtnl lock
*/
-static inline void bnx2x_set_reset_in_progress(struct bnx2x *bp)
+void bnx2x_set_reset_in_progress(struct bnx2x *bp)
{
- u32 val = REG_RD(bp, BNX2X_MISC_GEN_REG);
- val |= (1 << 16);
- REG_WR(bp, BNX2X_MISC_GEN_REG, val);
+ u32 val = REG_RD(bp, BNX2X_RECOVERY_GLOB_REG);
+ u32 bit = BP_PATH(bp) ?
+ BNX2X_PATH1_RST_IN_PROG_BIT : BNX2X_PATH0_RST_IN_PROG_BIT;
+
+ /* Set the bit */
+ val |= bit;
+ REG_WR(bp, BNX2X_RECOVERY_GLOB_REG, val);
barrier();
mmiowb();
}
/*
+ * Checks the RESET_IN_PROGRESS bit for the given engine.
* should be run under rtnl lock
*/
-bool bnx2x_reset_is_done(struct bnx2x *bp)
+bool bnx2x_reset_is_done(struct bnx2x *bp, int engine)
{
- u32 val = REG_RD(bp, BNX2X_MISC_GEN_REG);
- DP(NETIF_MSG_HW, "GEN_REG_VAL=0x%08x\n", val);
- return (val & RESET_DONE_FLAG_MASK) ? false : true;
+ u32 val = REG_RD(bp, BNX2X_RECOVERY_GLOB_REG);
+ u32 bit = engine ?
+ BNX2X_PATH1_RST_IN_PROG_BIT : BNX2X_PATH0_RST_IN_PROG_BIT;
+
+ /* return false if bit is set */
+ return (val & bit) ? false : true;
}
/*
+ * Increment the load counter for the current engine.
+ *
* should be run under rtnl lock
*/
-inline void bnx2x_inc_load_cnt(struct bnx2x *bp)
+void bnx2x_inc_load_cnt(struct bnx2x *bp)
{
- u32 val1, val = REG_RD(bp, BNX2X_MISC_GEN_REG);
+ u32 val1, val = REG_RD(bp, BNX2X_RECOVERY_GLOB_REG);
+ u32 mask = BP_PATH(bp) ? BNX2X_PATH1_LOAD_CNT_MASK :
+ BNX2X_PATH0_LOAD_CNT_MASK;
+ u32 shift = BP_PATH(bp) ? BNX2X_PATH1_LOAD_CNT_SHIFT :
+ BNX2X_PATH0_LOAD_CNT_SHIFT;
DP(NETIF_MSG_HW, "Old GEN_REG_VAL=0x%08x\n", val);
- val1 = ((val & LOAD_COUNTER_MASK) + 1) & LOAD_COUNTER_MASK;
- REG_WR(bp, BNX2X_MISC_GEN_REG, (val & RESET_DONE_FLAG_MASK) | val1);
+ /* get the current counter value */
+ val1 = (val & mask) >> shift;
+
+ /* increment... */
+ val1++;
+
+ /* clear the old value */
+ val &= ~mask;
+
+ /* set the new one */
+ val |= ((val1 << shift) & mask);
+
+ REG_WR(bp, BNX2X_RECOVERY_GLOB_REG, val);
barrier();
mmiowb();
}
-/*
- * should be run under rtnl lock
+/**
+ * bnx2x_dec_load_cnt - decrement the load counter
+ *
+ * @bp: driver handle
+ *
+ * Should be run under rtnl lock.
+ * Decrements the load counter for the current engine. Returns
+ * the new counter value.
*/
u32 bnx2x_dec_load_cnt(struct bnx2x *bp)
{
- u32 val1, val = REG_RD(bp, BNX2X_MISC_GEN_REG);
+ u32 val1, val = REG_RD(bp, BNX2X_RECOVERY_GLOB_REG);
+ u32 mask = BP_PATH(bp) ? BNX2X_PATH1_LOAD_CNT_MASK :
+ BNX2X_PATH0_LOAD_CNT_MASK;
+ u32 shift = BP_PATH(bp) ? BNX2X_PATH1_LOAD_CNT_SHIFT :
+ BNX2X_PATH0_LOAD_CNT_SHIFT;
DP(NETIF_MSG_HW, "Old GEN_REG_VAL=0x%08x\n", val);
- val1 = ((val & LOAD_COUNTER_MASK) - 1) & LOAD_COUNTER_MASK;
- REG_WR(bp, BNX2X_MISC_GEN_REG, (val & RESET_DONE_FLAG_MASK) | val1);
+ /* get the current counter value */
+ val1 = (val & mask) >> shift;
+
+ /* decrement... */
+ val1--;
+
+ /* clear the old value */
+ val &= ~mask;
+
+ /* set the new one */
+ val |= ((val1 << shift) & mask);
+
+ REG_WR(bp, BNX2X_RECOVERY_GLOB_REG, val);
barrier();
mmiowb();
@@ -3237,17 +3613,39 @@
}
/*
+ * Read the load counter for the current engine.
+ *
* should be run under rtnl lock
*/
-static inline u32 bnx2x_get_load_cnt(struct bnx2x *bp)
+static inline u32 bnx2x_get_load_cnt(struct bnx2x *bp, int engine)
{
- return REG_RD(bp, BNX2X_MISC_GEN_REG) & LOAD_COUNTER_MASK;
+ u32 mask = (engine ? BNX2X_PATH1_LOAD_CNT_MASK :
+ BNX2X_PATH0_LOAD_CNT_MASK);
+ u32 shift = (engine ? BNX2X_PATH1_LOAD_CNT_SHIFT :
+ BNX2X_PATH0_LOAD_CNT_SHIFT);
+ u32 val = REG_RD(bp, BNX2X_RECOVERY_GLOB_REG);
+
+ DP(NETIF_MSG_HW, "GLOB_REG=0x%08x\n", val);
+
+ val = (val & mask) >> shift;
+
+ DP(NETIF_MSG_HW, "load_cnt for engine %d = %d\n", engine, val);
+
+ return val;
}
+/*
+ * Reset the load counter for the current engine.
+ *
+ * should be run under rtnl lock
+ */
static inline void bnx2x_clear_load_cnt(struct bnx2x *bp)
{
- u32 val = REG_RD(bp, BNX2X_MISC_GEN_REG);
- REG_WR(bp, BNX2X_MISC_GEN_REG, val & (~LOAD_COUNTER_MASK));
+ u32 val = REG_RD(bp, BNX2X_RECOVERY_GLOB_REG);
+ u32 mask = (BP_PATH(bp) ? BNX2X_PATH1_LOAD_CNT_MASK :
+ BNX2X_PATH0_LOAD_CNT_MASK);
+
+ REG_WR(bp, BNX2X_RECOVERY_GLOB_REG, val & (~mask));
}
static inline void _print_next_block(int idx, const char *blk)
@@ -3257,7 +3655,8 @@
pr_cont("%s", blk);
}
-static inline int bnx2x_print_blocks_with_parity0(u32 sig, int par_num)
+static inline int bnx2x_check_blocks_with_parity0(u32 sig, int par_num,
+ bool print)
{
int i = 0;
u32 cur_bit = 0;
@@ -3266,19 +3665,33 @@
if (sig & cur_bit) {
switch (cur_bit) {
case AEU_INPUTS_ATTN_BITS_BRB_PARITY_ERROR:
- _print_next_block(par_num++, "BRB");
+ if (print)
+ _print_next_block(par_num++, "BRB");
break;
case AEU_INPUTS_ATTN_BITS_PARSER_PARITY_ERROR:
- _print_next_block(par_num++, "PARSER");
+ if (print)
+ _print_next_block(par_num++, "PARSER");
break;
case AEU_INPUTS_ATTN_BITS_TSDM_PARITY_ERROR:
- _print_next_block(par_num++, "TSDM");
+ if (print)
+ _print_next_block(par_num++, "TSDM");
break;
case AEU_INPUTS_ATTN_BITS_SEARCHER_PARITY_ERROR:
- _print_next_block(par_num++, "SEARCHER");
+ if (print)
+ _print_next_block(par_num++,
+ "SEARCHER");
+ break;
+ case AEU_INPUTS_ATTN_BITS_TCM_PARITY_ERROR:
+ if (print)
+ _print_next_block(par_num++, "TCM");
break;
case AEU_INPUTS_ATTN_BITS_TSEMI_PARITY_ERROR:
- _print_next_block(par_num++, "TSEMI");
+ if (print)
+ _print_next_block(par_num++, "TSEMI");
+ break;
+ case AEU_INPUTS_ATTN_BITS_PBCLIENT_PARITY_ERROR:
+ if (print)
+ _print_next_block(par_num++, "XPB");
break;
}
@@ -3290,7 +3703,8 @@
return par_num;
}
-static inline int bnx2x_print_blocks_with_parity1(u32 sig, int par_num)
+static inline int bnx2x_check_blocks_with_parity1(u32 sig, int par_num,
+ bool *global, bool print)
{
int i = 0;
u32 cur_bit = 0;
@@ -3298,38 +3712,64 @@
cur_bit = ((u32)0x1 << i);
if (sig & cur_bit) {
switch (cur_bit) {
- case AEU_INPUTS_ATTN_BITS_PBCLIENT_PARITY_ERROR:
- _print_next_block(par_num++, "PBCLIENT");
+ case AEU_INPUTS_ATTN_BITS_PBF_PARITY_ERROR:
+ if (print)
+ _print_next_block(par_num++, "PBF");
break;
case AEU_INPUTS_ATTN_BITS_QM_PARITY_ERROR:
- _print_next_block(par_num++, "QM");
+ if (print)
+ _print_next_block(par_num++, "QM");
+ break;
+ case AEU_INPUTS_ATTN_BITS_TIMERS_PARITY_ERROR:
+ if (print)
+ _print_next_block(par_num++, "TM");
break;
case AEU_INPUTS_ATTN_BITS_XSDM_PARITY_ERROR:
- _print_next_block(par_num++, "XSDM");
+ if (print)
+ _print_next_block(par_num++, "XSDM");
+ break;
+ case AEU_INPUTS_ATTN_BITS_XCM_PARITY_ERROR:
+ if (print)
+ _print_next_block(par_num++, "XCM");
break;
case AEU_INPUTS_ATTN_BITS_XSEMI_PARITY_ERROR:
- _print_next_block(par_num++, "XSEMI");
+ if (print)
+ _print_next_block(par_num++, "XSEMI");
break;
case AEU_INPUTS_ATTN_BITS_DOORBELLQ_PARITY_ERROR:
- _print_next_block(par_num++, "DOORBELLQ");
+ if (print)
+ _print_next_block(par_num++,
+ "DOORBELLQ");
+ break;
+ case AEU_INPUTS_ATTN_BITS_NIG_PARITY_ERROR:
+ if (print)
+ _print_next_block(par_num++, "NIG");
break;
case AEU_INPUTS_ATTN_BITS_VAUX_PCI_CORE_PARITY_ERROR:
- _print_next_block(par_num++, "VAUX PCI CORE");
+ if (print)
+ _print_next_block(par_num++,
+ "VAUX PCI CORE");
+ *global = true;
break;
case AEU_INPUTS_ATTN_BITS_DEBUG_PARITY_ERROR:
- _print_next_block(par_num++, "DEBUG");
+ if (print)
+ _print_next_block(par_num++, "DEBUG");
break;
case AEU_INPUTS_ATTN_BITS_USDM_PARITY_ERROR:
- _print_next_block(par_num++, "USDM");
+ if (print)
+ _print_next_block(par_num++, "USDM");
break;
case AEU_INPUTS_ATTN_BITS_USEMI_PARITY_ERROR:
- _print_next_block(par_num++, "USEMI");
+ if (print)
+ _print_next_block(par_num++, "USEMI");
break;
case AEU_INPUTS_ATTN_BITS_UPB_PARITY_ERROR:
- _print_next_block(par_num++, "UPB");
+ if (print)
+ _print_next_block(par_num++, "UPB");
break;
case AEU_INPUTS_ATTN_BITS_CSDM_PARITY_ERROR:
- _print_next_block(par_num++, "CSDM");
+ if (print)
+ _print_next_block(par_num++, "CSDM");
break;
}
@@ -3341,7 +3781,8 @@
return par_num;
}
-static inline int bnx2x_print_blocks_with_parity2(u32 sig, int par_num)
+static inline int bnx2x_check_blocks_with_parity2(u32 sig, int par_num,
+ bool print)
{
int i = 0;
u32 cur_bit = 0;
@@ -3350,26 +3791,37 @@
if (sig & cur_bit) {
switch (cur_bit) {
case AEU_INPUTS_ATTN_BITS_CSEMI_PARITY_ERROR:
- _print_next_block(par_num++, "CSEMI");
+ if (print)
+ _print_next_block(par_num++, "CSEMI");
break;
case AEU_INPUTS_ATTN_BITS_PXP_PARITY_ERROR:
- _print_next_block(par_num++, "PXP");
+ if (print)
+ _print_next_block(par_num++, "PXP");
break;
case AEU_IN_ATTN_BITS_PXPPCICLOCKCLIENT_PARITY_ERROR:
- _print_next_block(par_num++,
+ if (print)
+ _print_next_block(par_num++,
"PXPPCICLOCKCLIENT");
break;
case AEU_INPUTS_ATTN_BITS_CFC_PARITY_ERROR:
- _print_next_block(par_num++, "CFC");
+ if (print)
+ _print_next_block(par_num++, "CFC");
break;
case AEU_INPUTS_ATTN_BITS_CDU_PARITY_ERROR:
- _print_next_block(par_num++, "CDU");
+ if (print)
+ _print_next_block(par_num++, "CDU");
+ break;
+ case AEU_INPUTS_ATTN_BITS_DMAE_PARITY_ERROR:
+ if (print)
+ _print_next_block(par_num++, "DMAE");
break;
case AEU_INPUTS_ATTN_BITS_IGU_PARITY_ERROR:
- _print_next_block(par_num++, "IGU");
+ if (print)
+ _print_next_block(par_num++, "IGU");
break;
case AEU_INPUTS_ATTN_BITS_MISC_PARITY_ERROR:
- _print_next_block(par_num++, "MISC");
+ if (print)
+ _print_next_block(par_num++, "MISC");
break;
}
@@ -3381,7 +3833,8 @@
return par_num;
}
-static inline int bnx2x_print_blocks_with_parity3(u32 sig, int par_num)
+static inline int bnx2x_check_blocks_with_parity3(u32 sig, int par_num,
+ bool *global, bool print)
{
int i = 0;
u32 cur_bit = 0;
@@ -3390,16 +3843,27 @@
if (sig & cur_bit) {
switch (cur_bit) {
case AEU_INPUTS_ATTN_BITS_MCP_LATCHED_ROM_PARITY:
- _print_next_block(par_num++, "MCP ROM");
+ if (print)
+ _print_next_block(par_num++, "MCP ROM");
+ *global = true;
break;
case AEU_INPUTS_ATTN_BITS_MCP_LATCHED_UMP_RX_PARITY:
- _print_next_block(par_num++, "MCP UMP RX");
+ if (print)
+ _print_next_block(par_num++,
+ "MCP UMP RX");
+ *global = true;
break;
case AEU_INPUTS_ATTN_BITS_MCP_LATCHED_UMP_TX_PARITY:
- _print_next_block(par_num++, "MCP UMP TX");
+ if (print)
+ _print_next_block(par_num++,
+ "MCP UMP TX");
+ *global = true;
break;
case AEU_INPUTS_ATTN_BITS_MCP_LATCHED_SCPAD_PARITY:
- _print_next_block(par_num++, "MCP SCPAD");
+ if (print)
+ _print_next_block(par_num++,
+ "MCP SCPAD");
+ *global = true;
break;
}
@@ -3411,8 +3875,8 @@
return par_num;
}
-static inline bool bnx2x_parity_attn(struct bnx2x *bp, u32 sig0, u32 sig1,
- u32 sig2, u32 sig3)
+static inline bool bnx2x_parity_attn(struct bnx2x *bp, bool *global, bool print,
+ u32 sig0, u32 sig1, u32 sig2, u32 sig3)
{
if ((sig0 & HW_PRTY_ASSERT_SET_0) || (sig1 & HW_PRTY_ASSERT_SET_1) ||
(sig2 & HW_PRTY_ASSERT_SET_2) || (sig3 & HW_PRTY_ASSERT_SET_3)) {
@@ -3424,23 +3888,32 @@
sig1 & HW_PRTY_ASSERT_SET_1,
sig2 & HW_PRTY_ASSERT_SET_2,
sig3 & HW_PRTY_ASSERT_SET_3);
- printk(KERN_ERR"%s: Parity errors detected in blocks: ",
- bp->dev->name);
- par_num = bnx2x_print_blocks_with_parity0(
- sig0 & HW_PRTY_ASSERT_SET_0, par_num);
- par_num = bnx2x_print_blocks_with_parity1(
- sig1 & HW_PRTY_ASSERT_SET_1, par_num);
- par_num = bnx2x_print_blocks_with_parity2(
- sig2 & HW_PRTY_ASSERT_SET_2, par_num);
- par_num = bnx2x_print_blocks_with_parity3(
- sig3 & HW_PRTY_ASSERT_SET_3, par_num);
- printk("\n");
+ if (print)
+ netdev_err(bp->dev,
+ "Parity errors detected in blocks: ");
+ par_num = bnx2x_check_blocks_with_parity0(
+ sig0 & HW_PRTY_ASSERT_SET_0, par_num, print);
+ par_num = bnx2x_check_blocks_with_parity1(
+ sig1 & HW_PRTY_ASSERT_SET_1, par_num, global, print);
+ par_num = bnx2x_check_blocks_with_parity2(
+ sig2 & HW_PRTY_ASSERT_SET_2, par_num, print);
+ par_num = bnx2x_check_blocks_with_parity3(
+ sig3 & HW_PRTY_ASSERT_SET_3, par_num, global, print);
+ if (print)
+ pr_cont("\n");
return true;
} else
return false;
}
-bool bnx2x_chk_parity_attn(struct bnx2x *bp)
+/**
+ * bnx2x_chk_parity_attn - checks for parity attentions.
+ *
+ * @bp: driver handle
+ * @global: true if there was a global attention
+ * @print: show parity attention in syslog
+ */
+bool bnx2x_chk_parity_attn(struct bnx2x *bp, bool *global, bool print)
{
struct attn_route attn;
int port = BP_PORT(bp);
@@ -3458,8 +3931,8 @@
MISC_REG_AEU_AFTER_INVERT_4_FUNC_0 +
port*4);
- return bnx2x_parity_attn(bp, attn.sig[0], attn.sig[1], attn.sig[2],
- attn.sig[3]);
+ return bnx2x_parity_attn(bp, global, print, attn.sig[0], attn.sig[1],
+ attn.sig[2], attn.sig[3]);
}
@@ -3538,21 +4011,25 @@
u32 reg_addr;
u32 val;
u32 aeu_mask;
+ bool global = false;
/* need to take HW lock because MCP or other port might also
try to handle this event */
bnx2x_acquire_alr(bp);
- if (CHIP_PARITY_ENABLED(bp) && bnx2x_chk_parity_attn(bp)) {
+ if (bnx2x_chk_parity_attn(bp, &global, true)) {
+#ifndef BNX2X_STOP_ON_ERROR
bp->recovery_state = BNX2X_RECOVERY_INIT;
- bnx2x_set_reset_in_progress(bp);
schedule_delayed_work(&bp->reset_task, 0);
/* Disable HW interrupts */
bnx2x_int_disable(bp);
- bnx2x_release_alr(bp);
/* In case of parity errors don't handle attentions so that
* other function would "see" parity errors.
*/
+#else
+ bnx2x_panic();
+#endif
+ bnx2x_release_alr(bp);
return;
}
@@ -3560,7 +4037,7 @@
attn.sig[1] = REG_RD(bp, MISC_REG_AEU_AFTER_INVERT_2_FUNC_0 + port*4);
attn.sig[2] = REG_RD(bp, MISC_REG_AEU_AFTER_INVERT_3_FUNC_0 + port*4);
attn.sig[3] = REG_RD(bp, MISC_REG_AEU_AFTER_INVERT_4_FUNC_0 + port*4);
- if (CHIP_IS_E2(bp))
+ if (!CHIP_IS_E1x(bp))
attn.sig[4] =
REG_RD(bp, MISC_REG_AEU_AFTER_INVERT_5_FUNC_0 + port*4);
else
@@ -3656,6 +4133,15 @@
bnx2x_attn_int_deasserted(bp, deasserted);
}
+void bnx2x_igu_ack_sb(struct bnx2x *bp, u8 igu_sb_id, u8 segment,
+ u16 index, u8 op, u8 update)
+{
+ u32 igu_addr = BAR_IGU_INTMEM + (IGU_CMD_INT_ACK_BASE + igu_sb_id)*8;
+
+ bnx2x_igu_ack_sb_gen(bp, igu_sb_id, segment, index, op, update,
+ igu_addr);
+}
+
static inline void bnx2x_update_eq_prod(struct bnx2x *bp, u16 prod)
{
/* No memory barriers */
@@ -3667,6 +4153,8 @@
static int bnx2x_cnic_handle_cfc_del(struct bnx2x *bp, u32 cid,
union event_ring_elem *elem)
{
+ u8 err = elem->message.error;
+
if (!bp->cnic_eth_dev.starting_cid ||
(cid < bp->cnic_eth_dev.starting_cid &&
cid != bp->cnic_eth_dev.iscsi_l2_cid))
@@ -3674,16 +4162,122 @@
DP(BNX2X_MSG_SP, "got delete ramrod for CNIC CID %d\n", cid);
- if (unlikely(elem->message.data.cfc_del_event.error)) {
+ if (unlikely(err)) {
+
BNX2X_ERR("got delete ramrod for CNIC CID %d with error!\n",
cid);
bnx2x_panic_dump(bp);
}
- bnx2x_cnic_cfc_comp(bp, cid);
+ bnx2x_cnic_cfc_comp(bp, cid, err);
return 0;
}
#endif
+static inline void bnx2x_handle_mcast_eqe(struct bnx2x *bp)
+{
+ struct bnx2x_mcast_ramrod_params rparam;
+ int rc;
+
+ memset(&rparam, 0, sizeof(rparam));
+
+ rparam.mcast_obj = &bp->mcast_obj;
+
+ netif_addr_lock_bh(bp->dev);
+
+ /* Clear pending state for the last command */
+ bp->mcast_obj.raw.clear_pending(&bp->mcast_obj.raw);
+
+ /* If there are pending mcast commands - send them */
+ if (bp->mcast_obj.check_pending(&bp->mcast_obj)) {
+ rc = bnx2x_config_mcast(bp, &rparam, BNX2X_MCAST_CMD_CONT);
+ if (rc < 0)
+ BNX2X_ERR("Failed to send pending mcast commands: %d\n",
+ rc);
+ }
+
+ netif_addr_unlock_bh(bp->dev);
+}
+
+static inline void bnx2x_handle_classification_eqe(struct bnx2x *bp,
+ union event_ring_elem *elem)
+{
+ unsigned long ramrod_flags = 0;
+ int rc = 0;
+ u32 cid = elem->message.data.eth_event.echo & BNX2X_SWCID_MASK;
+ struct bnx2x_vlan_mac_obj *vlan_mac_obj;
+
+ /* Always push next commands out, don't wait here */
+ __set_bit(RAMROD_CONT, &ramrod_flags);
+
+ switch (elem->message.data.eth_event.echo >> BNX2X_SWCID_SHIFT) {
+ case BNX2X_FILTER_MAC_PENDING:
+#ifdef BCM_CNIC
+ if (cid == BNX2X_ISCSI_ETH_CID)
+ vlan_mac_obj = &bp->iscsi_l2_mac_obj;
+ else
+#endif
+ vlan_mac_obj = &bp->fp[cid].mac_obj;
+
+ break;
+ vlan_mac_obj = &bp->fp[cid].mac_obj;
+
+ case BNX2X_FILTER_MCAST_PENDING:
+ /* This is only relevant for 57710 where multicast MACs are
+ * configured as unicast MACs using the same ramrod.
+ */
+ bnx2x_handle_mcast_eqe(bp);
+ return;
+ default:
+ BNX2X_ERR("Unsupported classification command: %d\n",
+ elem->message.data.eth_event.echo);
+ return;
+ }
+
+ rc = vlan_mac_obj->complete(bp, vlan_mac_obj, elem, &ramrod_flags);
+
+ if (rc < 0)
+ BNX2X_ERR("Failed to schedule new commands: %d\n", rc);
+ else if (rc > 0)
+ DP(BNX2X_MSG_SP, "Scheduled next pending commands...\n");
+
+}
+
+#ifdef BCM_CNIC
+static void bnx2x_set_iscsi_eth_rx_mode(struct bnx2x *bp, bool start);
+#endif
+
+static inline void bnx2x_handle_rx_mode_eqe(struct bnx2x *bp)
+{
+ netif_addr_lock_bh(bp->dev);
+
+ clear_bit(BNX2X_FILTER_RX_MODE_PENDING, &bp->sp_state);
+
+ /* Send rx_mode command again if was requested */
+ if (test_and_clear_bit(BNX2X_FILTER_RX_MODE_SCHED, &bp->sp_state))
+ bnx2x_set_storm_rx_mode(bp);
+#ifdef BCM_CNIC
+ else if (test_and_clear_bit(BNX2X_FILTER_ISCSI_ETH_START_SCHED,
+ &bp->sp_state))
+ bnx2x_set_iscsi_eth_rx_mode(bp, true);
+ else if (test_and_clear_bit(BNX2X_FILTER_ISCSI_ETH_STOP_SCHED,
+ &bp->sp_state))
+ bnx2x_set_iscsi_eth_rx_mode(bp, false);
+#endif
+
+ netif_addr_unlock_bh(bp->dev);
+}
+
+static inline struct bnx2x_queue_sp_obj *bnx2x_cid_to_q_obj(
+ struct bnx2x *bp, u32 cid)
+{
+#ifdef BCM_CNIC
+ if (cid == BNX2X_FCOE_ETH_CID)
+ return &bnx2x_fcoe(bp, q_obj);
+ else
+#endif
+ return &bnx2x_fp(bp, cid, q_obj);
+}
+
static void bnx2x_eq_int(struct bnx2x *bp)
{
u16 hw_cons, sw_cons, sw_prod;
@@ -3691,6 +4285,9 @@
u32 cid;
u8 opcode;
int spqe_cnt = 0;
+ struct bnx2x_queue_sp_obj *q_obj;
+ struct bnx2x_func_sp_obj *f_obj = &bp->func_obj;
+ struct bnx2x_raw_obj *rss_raw = &bp->rss_conf_obj.raw;
hw_cons = le16_to_cpu(*bp->eq_cons_sb);
@@ -3725,7 +4322,8 @@
/* handle eq element */
switch (opcode) {
case EVENT_RING_OPCODE_STAT_QUERY:
- DP(NETIF_MSG_TIMER, "got statistics comp event\n");
+ DP(NETIF_MSG_TIMER, "got statistics comp event %d\n",
+ bp->stats_comp++);
/* nothing to do with stats comp */
continue;
@@ -3740,12 +4338,13 @@
#ifdef BCM_CNIC
if (!bnx2x_cnic_handle_cfc_del(bp, cid, elem))
goto next_spqe;
- if (cid == BNX2X_FCOE_ETH_CID)
- bnx2x_fcoe(bp, state) = BNX2X_FP_STATE_CLOSED;
- else
#endif
- bnx2x_fp(bp, cid, state) =
- BNX2X_FP_STATE_CLOSED;
+ q_obj = bnx2x_cid_to_q_obj(bp, cid);
+
+ if (q_obj->complete_cmd(bp, q_obj, BNX2X_Q_CMD_CFC_DEL))
+ break;
+
+
goto next_spqe;
@@ -3753,42 +4352,75 @@
DP(NETIF_MSG_IFUP, "got STOP TRAFFIC\n");
bnx2x_dcbx_set_params(bp, BNX2X_DCBX_STATE_TX_PAUSED);
goto next_spqe;
+
case EVENT_RING_OPCODE_START_TRAFFIC:
DP(NETIF_MSG_IFUP, "got START TRAFFIC\n");
bnx2x_dcbx_set_params(bp, BNX2X_DCBX_STATE_TX_RELEASED);
goto next_spqe;
+ case EVENT_RING_OPCODE_FUNCTION_START:
+ DP(NETIF_MSG_IFUP, "got FUNC_START ramrod\n");
+ if (f_obj->complete_cmd(bp, f_obj, BNX2X_F_CMD_START))
+ break;
+
+ goto next_spqe;
+
+ case EVENT_RING_OPCODE_FUNCTION_STOP:
+ DP(NETIF_MSG_IFDOWN, "got FUNC_STOP ramrod\n");
+ if (f_obj->complete_cmd(bp, f_obj, BNX2X_F_CMD_STOP))
+ break;
+
+ goto next_spqe;
}
switch (opcode | bp->state) {
- case (EVENT_RING_OPCODE_FUNCTION_START |
+ case (EVENT_RING_OPCODE_RSS_UPDATE_RULES |
+ BNX2X_STATE_OPEN):
+ case (EVENT_RING_OPCODE_RSS_UPDATE_RULES |
BNX2X_STATE_OPENING_WAIT4_PORT):
- DP(NETIF_MSG_IFUP, "got setup ramrod\n");
- bp->state = BNX2X_STATE_FUNC_STARTED;
- break;
-
- case (EVENT_RING_OPCODE_FUNCTION_STOP |
- BNX2X_STATE_CLOSING_WAIT4_HALT):
- DP(NETIF_MSG_IFDOWN, "got halt ramrod\n");
- bp->state = BNX2X_STATE_CLOSING_WAIT4_UNLOAD;
+ cid = elem->message.data.eth_event.echo &
+ BNX2X_SWCID_MASK;
+ DP(NETIF_MSG_IFUP, "got RSS_UPDATE ramrod. CID %d\n",
+ cid);
+ rss_raw->clear_pending(rss_raw);
break;
case (EVENT_RING_OPCODE_SET_MAC | BNX2X_STATE_OPEN):
case (EVENT_RING_OPCODE_SET_MAC | BNX2X_STATE_DIAG):
- DP(NETIF_MSG_IFUP, "got set mac ramrod\n");
- if (elem->message.data.set_mac_event.echo)
- bp->set_mac_pending = 0;
- break;
-
case (EVENT_RING_OPCODE_SET_MAC |
BNX2X_STATE_CLOSING_WAIT4_HALT):
- DP(NETIF_MSG_IFDOWN, "got (un)set mac ramrod\n");
- if (elem->message.data.set_mac_event.echo)
- bp->set_mac_pending = 0;
+ case (EVENT_RING_OPCODE_CLASSIFICATION_RULES |
+ BNX2X_STATE_OPEN):
+ case (EVENT_RING_OPCODE_CLASSIFICATION_RULES |
+ BNX2X_STATE_DIAG):
+ case (EVENT_RING_OPCODE_CLASSIFICATION_RULES |
+ BNX2X_STATE_CLOSING_WAIT4_HALT):
+ DP(NETIF_MSG_IFUP, "got (un)set mac ramrod\n");
+ bnx2x_handle_classification_eqe(bp, elem);
+ break;
+
+ case (EVENT_RING_OPCODE_MULTICAST_RULES |
+ BNX2X_STATE_OPEN):
+ case (EVENT_RING_OPCODE_MULTICAST_RULES |
+ BNX2X_STATE_DIAG):
+ case (EVENT_RING_OPCODE_MULTICAST_RULES |
+ BNX2X_STATE_CLOSING_WAIT4_HALT):
+ DP(NETIF_MSG_IFUP, "got mcast ramrod\n");
+ bnx2x_handle_mcast_eqe(bp);
+ break;
+
+ case (EVENT_RING_OPCODE_FILTERS_RULES |
+ BNX2X_STATE_OPEN):
+ case (EVENT_RING_OPCODE_FILTERS_RULES |
+ BNX2X_STATE_DIAG):
+ case (EVENT_RING_OPCODE_FILTERS_RULES |
+ BNX2X_STATE_CLOSING_WAIT4_HALT):
+ DP(NETIF_MSG_IFUP, "got rx_mode ramrod\n");
+ bnx2x_handle_rx_mode_eqe(bp);
break;
default:
/* unknown event log error and continue */
- BNX2X_ERR("Unknown EQ event %d\n",
- elem->message.opcode);
+ BNX2X_ERR("Unknown EQ event %d, bp->state 0x%x\n",
+ elem->message.opcode, bp->state);
}
next_spqe:
spqe_cnt++;
@@ -3811,12 +4443,6 @@
struct bnx2x *bp = container_of(work, struct bnx2x, sp_task.work);
u16 status;
- /* Return here if interrupt is disabled */
- if (unlikely(atomic_read(&bp->intr_sem) != 0)) {
- DP(NETIF_MSG_INTR, "called but intr_sem not 0, returning\n");
- return;
- }
-
status = bnx2x_update_dsb_idx(bp);
/* if (status == 0) */
/* BNX2X_ERR("spurious slowpath interrupt!\n"); */
@@ -3860,12 +4486,6 @@
struct net_device *dev = dev_instance;
struct bnx2x *bp = netdev_priv(dev);
- /* Return here if interrupt is disabled */
- if (unlikely(atomic_read(&bp->intr_sem) != 0)) {
- DP(NETIF_MSG_INTR, "called but intr_sem not 0, returning\n");
- return IRQ_HANDLED;
- }
-
bnx2x_ack_sb(bp, bp->igu_dsb_id, USTORM_ID, 0,
IGU_INT_DISABLE, 0);
@@ -3892,6 +4512,14 @@
/* end of slow path */
+
+void bnx2x_drv_pulse(struct bnx2x *bp)
+{
+ SHMEM_WR(bp, func_mb[BP_FW_MB_IDX(bp)].drv_pulse_mb,
+ bp->fw_drv_pulse_wr_seq);
+}
+
+
static void bnx2x_timer(unsigned long data)
{
struct bnx2x *bp = (struct bnx2x *) data;
@@ -3899,9 +4527,6 @@
if (!netif_running(bp->dev))
return;
- if (atomic_read(&bp->intr_sem) != 0)
- goto timer_restart;
-
if (poll) {
struct bnx2x_fastpath *fp = &bp->fp[0];
@@ -3918,7 +4543,7 @@
bp->fw_drv_pulse_wr_seq &= DRV_PULSE_SEQ_MASK;
/* TBD - add SYSTEM_TIME */
drv_pulse = bp->fw_drv_pulse_wr_seq;
- SHMEM_WR(bp, func_mb[mb_idx].drv_pulse_mb, drv_pulse);
+ bnx2x_drv_pulse(bp);
mcp_pulse = (SHMEM_RD(bp, func_mb[mb_idx].mcp_pulse_mb) &
MCP_PULSE_SEQ_MASK);
@@ -3936,7 +4561,6 @@
if (bp->state == BNX2X_STATE_OPEN)
bnx2x_stats_handle(bp, STATS_EVENT_UPDATE);
-timer_restart:
mod_timer(&bp->timer, jiffies + bp->current_interval);
}
@@ -3982,18 +4606,16 @@
struct hc_status_block_data_e1x sb_data_e1x;
/* disable the function first */
- if (CHIP_IS_E2(bp)) {
+ if (!CHIP_IS_E1x(bp)) {
memset(&sb_data_e2, 0, sizeof(struct hc_status_block_data_e2));
- sb_data_e2.common.p_func.pf_id = HC_FUNCTION_DISABLED;
- sb_data_e2.common.p_func.vf_id = HC_FUNCTION_DISABLED;
+ sb_data_e2.common.state = SB_DISABLED;
sb_data_e2.common.p_func.vf_valid = false;
sb_data_p = (u32 *)&sb_data_e2;
data_size = sizeof(struct hc_status_block_data_e2)/sizeof(u32);
} else {
memset(&sb_data_e1x, 0,
sizeof(struct hc_status_block_data_e1x));
- sb_data_e1x.common.p_func.pf_id = HC_FUNCTION_DISABLED;
- sb_data_e1x.common.p_func.vf_id = HC_FUNCTION_DISABLED;
+ sb_data_e1x.common.state = SB_DISABLED;
sb_data_e1x.common.p_func.vf_valid = false;
sb_data_p = (u32 *)&sb_data_e1x;
data_size = sizeof(struct hc_status_block_data_e1x)/sizeof(u32);
@@ -4027,8 +4649,7 @@
struct hc_sp_status_block_data sp_sb_data;
memset(&sp_sb_data, 0, sizeof(struct hc_sp_status_block_data));
- sp_sb_data.p_func.pf_id = HC_FUNCTION_DISABLED;
- sp_sb_data.p_func.vf_id = HC_FUNCTION_DISABLED;
+ sp_sb_data.state = SB_DISABLED;
sp_sb_data.p_func.vf_valid = false;
bnx2x_wr_sp_sb_data(bp, &sp_sb_data);
@@ -4071,8 +4692,9 @@
bnx2x_zero_fp_sb(bp, fw_sb_id);
- if (CHIP_IS_E2(bp)) {
+ if (!CHIP_IS_E1x(bp)) {
memset(&sb_data_e2, 0, sizeof(struct hc_status_block_data_e2));
+ sb_data_e2.common.state = SB_ENABLED;
sb_data_e2.common.p_func.pf_id = BP_FUNC(bp);
sb_data_e2.common.p_func.vf_id = vfid;
sb_data_e2.common.p_func.vf_valid = vf_valid;
@@ -4086,6 +4708,7 @@
} else {
memset(&sb_data_e1x, 0,
sizeof(struct hc_status_block_data_e1x));
+ sb_data_e1x.common.state = SB_ENABLED;
sb_data_e1x.common.p_func.pf_id = BP_FUNC(bp);
sb_data_e1x.common.p_func.vf_id = 0xff;
sb_data_e1x.common.p_func.vf_valid = false;
@@ -4109,19 +4732,7 @@
bnx2x_wr_fp_sb_data(bp, fw_sb_id, sb_data_p, data_size);
}
-static void bnx2x_update_coalesce_sb_index(struct bnx2x *bp, u16 fw_sb_id,
- u8 sb_index, u8 disable, u16 usec)
-{
- int port = BP_PORT(bp);
- u8 ticks = usec / BNX2X_BTR;
-
- storm_memset_hc_timeout(bp, port, fw_sb_id, sb_index, ticks);
-
- disable = disable ? 1 : (usec ? 0 : 1);
- storm_memset_hc_disable(bp, port, fw_sb_id, sb_index, disable);
-}
-
-static void bnx2x_update_coalesce_sb(struct bnx2x *bp, u16 fw_sb_id,
+static void bnx2x_update_coalesce_sb(struct bnx2x *bp, u8 fw_sb_id,
u16 tx_usec, u16 rx_usec)
{
bnx2x_update_coalesce_sb_index(bp, fw_sb_id, U_SB_ETH_RX_CQ_INDEX,
@@ -4168,7 +4779,7 @@
bp->attn_group[index].sig[sindex] =
REG_RD(bp, reg_offset + sindex*0x4 + 0x10*index);
- if (CHIP_IS_E2(bp))
+ if (!CHIP_IS_E1x(bp))
/*
* enable5 is separate from the rest of the registers,
* and therefore the address skip is 4
@@ -4186,7 +4797,7 @@
REG_WR(bp, reg_offset, U64_LO(section));
REG_WR(bp, reg_offset + 4, U64_HI(section));
- } else if (CHIP_IS_E2(bp)) {
+ } else if (!CHIP_IS_E1x(bp)) {
REG_WR(bp, IGU_REG_ATTN_MSG_ADDR_L, U64_LO(section));
REG_WR(bp, IGU_REG_ATTN_MSG_ADDR_H, U64_HI(section));
}
@@ -4196,6 +4807,7 @@
bnx2x_zero_sp_sb(bp);
+ sp_sb_data.state = SB_ENABLED;
sp_sb_data.host_sb_addr.lo = U64_LO(section);
sp_sb_data.host_sb_addr.hi = U64_HI(section);
sp_sb_data.igu_sb_id = igu_sp_sb_index;
@@ -4206,9 +4818,6 @@
bnx2x_wr_sp_sb_data(bp, &sp_sb_data);
- bp->stats_pending = 0;
- bp->set_mac_pending = 0;
-
bnx2x_ack_sb(bp, bp->igu_dsb_id, USTORM_ID, 0, IGU_INT_ENABLE, 0);
}
@@ -4254,146 +4863,129 @@
min_t(int, MAX_SP_DESC_CNT - MAX_SPQ_PENDING, NUM_EQ_DESC) - 1);
}
-void bnx2x_push_indir_table(struct bnx2x *bp)
-{
- int func = BP_FUNC(bp);
- int i;
- if (bp->multi_mode == ETH_RSS_MODE_DISABLED)
+/* called with netif_addr_lock_bh() */
+void bnx2x_set_q_rx_mode(struct bnx2x *bp, u8 cl_id,
+ unsigned long rx_mode_flags,
+ unsigned long rx_accept_flags,
+ unsigned long tx_accept_flags,
+ unsigned long ramrod_flags)
+{
+ struct bnx2x_rx_mode_ramrod_params ramrod_param;
+ int rc;
+
+ memset(&ramrod_param, 0, sizeof(ramrod_param));
+
+ /* Prepare ramrod parameters */
+ ramrod_param.cid = 0;
+ ramrod_param.cl_id = cl_id;
+ ramrod_param.rx_mode_obj = &bp->rx_mode_obj;
+ ramrod_param.func_id = BP_FUNC(bp);
+
+ ramrod_param.pstate = &bp->sp_state;
+ ramrod_param.state = BNX2X_FILTER_RX_MODE_PENDING;
+
+ ramrod_param.rdata = bnx2x_sp(bp, rx_mode_rdata);
+ ramrod_param.rdata_mapping = bnx2x_sp_mapping(bp, rx_mode_rdata);
+
+ set_bit(BNX2X_FILTER_RX_MODE_PENDING, &bp->sp_state);
+
+ ramrod_param.ramrod_flags = ramrod_flags;
+ ramrod_param.rx_mode_flags = rx_mode_flags;
+
+ ramrod_param.rx_accept_flags = rx_accept_flags;
+ ramrod_param.tx_accept_flags = tx_accept_flags;
+
+ rc = bnx2x_config_rx_mode(bp, &ramrod_param);
+ if (rc < 0) {
+ BNX2X_ERR("Set rx_mode %d failed\n", bp->rx_mode);
return;
-
- for (i = 0; i < TSTORM_INDIRECTION_TABLE_SIZE; i++)
- REG_WR8(bp, BAR_TSTRORM_INTMEM +
- TSTORM_INDIRECTION_TABLE_OFFSET(func) + i,
- bp->fp->cl_id + bp->rx_indir_table[i]);
+ }
}
-static void bnx2x_init_ind_table(struct bnx2x *bp)
-{
- int i;
-
- for (i = 0; i < TSTORM_INDIRECTION_TABLE_SIZE; i++)
- bp->rx_indir_table[i] = i % BNX2X_NUM_ETH_QUEUES(bp);
-
- bnx2x_push_indir_table(bp);
-}
-
+/* called with netif_addr_lock_bh() */
void bnx2x_set_storm_rx_mode(struct bnx2x *bp)
{
- int mode = bp->rx_mode;
- int port = BP_PORT(bp);
- u16 cl_id;
- u32 def_q_filters = 0;
+ unsigned long rx_mode_flags = 0, ramrod_flags = 0;
+ unsigned long rx_accept_flags = 0, tx_accept_flags = 0;
- /* All but management unicast packets should pass to the host as well */
- u32 llh_mask =
- NIG_LLH0_BRB1_DRV_MASK_REG_LLH0_BRB1_DRV_MASK_BRCST |
- NIG_LLH0_BRB1_DRV_MASK_REG_LLH0_BRB1_DRV_MASK_MLCST |
- NIG_LLH0_BRB1_DRV_MASK_REG_LLH0_BRB1_DRV_MASK_VLAN |
- NIG_LLH0_BRB1_DRV_MASK_REG_LLH0_BRB1_DRV_MASK_NO_VLAN;
-
- switch (mode) {
- case BNX2X_RX_MODE_NONE: /* no Rx */
- def_q_filters = BNX2X_ACCEPT_NONE;
#ifdef BCM_CNIC
- if (!NO_FCOE(bp)) {
- cl_id = bnx2x_fcoe(bp, cl_id);
- bnx2x_rxq_set_mac_filters(bp, cl_id, BNX2X_ACCEPT_NONE);
- }
-#endif
- break;
+ if (!NO_FCOE(bp))
+ /* Configure rx_mode of FCoE Queue */
+ __set_bit(BNX2X_RX_MODE_FCOE_ETH, &rx_mode_flags);
+#endif
+
+ switch (bp->rx_mode) {
+ case BNX2X_RX_MODE_NONE:
+ /*
+ * 'drop all' supersedes any accept flags that may have been
+ * passed to the function.
+ */
+ break;
case BNX2X_RX_MODE_NORMAL:
- def_q_filters |= BNX2X_ACCEPT_UNICAST | BNX2X_ACCEPT_BROADCAST |
- BNX2X_ACCEPT_MULTICAST;
-#ifdef BCM_CNIC
- if (!NO_FCOE(bp)) {
- cl_id = bnx2x_fcoe(bp, cl_id);
- bnx2x_rxq_set_mac_filters(bp, cl_id,
- BNX2X_ACCEPT_UNICAST |
- BNX2X_ACCEPT_MULTICAST);
- }
-#endif
- break;
+ __set_bit(BNX2X_ACCEPT_UNICAST, &rx_accept_flags);
+ __set_bit(BNX2X_ACCEPT_MULTICAST, &rx_accept_flags);
+ __set_bit(BNX2X_ACCEPT_BROADCAST, &rx_accept_flags);
+ /* internal switching mode */
+ __set_bit(BNX2X_ACCEPT_UNICAST, &tx_accept_flags);
+ __set_bit(BNX2X_ACCEPT_MULTICAST, &tx_accept_flags);
+ __set_bit(BNX2X_ACCEPT_BROADCAST, &tx_accept_flags);
+
+ break;
case BNX2X_RX_MODE_ALLMULTI:
- def_q_filters |= BNX2X_ACCEPT_UNICAST | BNX2X_ACCEPT_BROADCAST |
- BNX2X_ACCEPT_ALL_MULTICAST;
-#ifdef BCM_CNIC
- /*
- * Prevent duplication of multicast packets by configuring FCoE
- * L2 Client to receive only matched unicast frames.
- */
- if (!NO_FCOE(bp)) {
- cl_id = bnx2x_fcoe(bp, cl_id);
- bnx2x_rxq_set_mac_filters(bp, cl_id,
- BNX2X_ACCEPT_UNICAST);
- }
-#endif
- break;
+ __set_bit(BNX2X_ACCEPT_UNICAST, &rx_accept_flags);
+ __set_bit(BNX2X_ACCEPT_ALL_MULTICAST, &rx_accept_flags);
+ __set_bit(BNX2X_ACCEPT_BROADCAST, &rx_accept_flags);
+ /* internal switching mode */
+ __set_bit(BNX2X_ACCEPT_UNICAST, &tx_accept_flags);
+ __set_bit(BNX2X_ACCEPT_ALL_MULTICAST, &tx_accept_flags);
+ __set_bit(BNX2X_ACCEPT_BROADCAST, &tx_accept_flags);
+
+ break;
case BNX2X_RX_MODE_PROMISC:
- def_q_filters |= BNX2X_PROMISCUOUS_MODE;
-#ifdef BCM_CNIC
- /*
- * Prevent packets duplication by configuring DROP_ALL for FCoE
- * L2 Client.
+ /* According to deffinition of SI mode, iface in promisc mode
+ * should receive matched and unmatched (in resolution of port)
+ * unicast packets.
*/
- if (!NO_FCOE(bp)) {
- cl_id = bnx2x_fcoe(bp, cl_id);
- bnx2x_rxq_set_mac_filters(bp, cl_id, BNX2X_ACCEPT_NONE);
- }
-#endif
- /* pass management unicast packets as well */
- llh_mask |= NIG_LLH0_BRB1_DRV_MASK_REG_LLH0_BRB1_DRV_MASK_UNCST;
- break;
+ __set_bit(BNX2X_ACCEPT_UNMATCHED, &rx_accept_flags);
+ __set_bit(BNX2X_ACCEPT_UNICAST, &rx_accept_flags);
+ __set_bit(BNX2X_ACCEPT_ALL_MULTICAST, &rx_accept_flags);
+ __set_bit(BNX2X_ACCEPT_BROADCAST, &rx_accept_flags);
- default:
- BNX2X_ERR("BAD rx mode (%d)\n", mode);
+ /* internal switching mode */
+ __set_bit(BNX2X_ACCEPT_ALL_MULTICAST, &tx_accept_flags);
+ __set_bit(BNX2X_ACCEPT_BROADCAST, &tx_accept_flags);
+
+ if (IS_MF_SI(bp))
+ __set_bit(BNX2X_ACCEPT_ALL_UNICAST, &tx_accept_flags);
+ else
+ __set_bit(BNX2X_ACCEPT_UNICAST, &tx_accept_flags);
+
break;
+ default:
+ BNX2X_ERR("Unknown rx_mode: %d\n", bp->rx_mode);
+ return;
}
- cl_id = BP_L_ID(bp);
- bnx2x_rxq_set_mac_filters(bp, cl_id, def_q_filters);
+ if (bp->rx_mode != BNX2X_RX_MODE_NONE) {
+ __set_bit(BNX2X_ACCEPT_ANY_VLAN, &rx_accept_flags);
+ __set_bit(BNX2X_ACCEPT_ANY_VLAN, &tx_accept_flags);
+ }
- REG_WR(bp,
- (port ? NIG_REG_LLH1_BRB1_DRV_MASK :
- NIG_REG_LLH0_BRB1_DRV_MASK), llh_mask);
+ __set_bit(RAMROD_RX, &ramrod_flags);
+ __set_bit(RAMROD_TX, &ramrod_flags);
- DP(NETIF_MSG_IFUP, "rx mode %d\n"
- "drop_ucast 0x%x\ndrop_mcast 0x%x\ndrop_bcast 0x%x\n"
- "accp_ucast 0x%x\naccp_mcast 0x%x\naccp_bcast 0x%x\n"
- "unmatched_ucast 0x%x\n", mode,
- bp->mac_filters.ucast_drop_all,
- bp->mac_filters.mcast_drop_all,
- bp->mac_filters.bcast_drop_all,
- bp->mac_filters.ucast_accept_all,
- bp->mac_filters.mcast_accept_all,
- bp->mac_filters.bcast_accept_all,
- bp->mac_filters.unmatched_unicast
- );
-
- storm_memset_mac_filters(bp, &bp->mac_filters, BP_FUNC(bp));
+ bnx2x_set_q_rx_mode(bp, bp->fp->cl_id, rx_mode_flags, rx_accept_flags,
+ tx_accept_flags, ramrod_flags);
}
static void bnx2x_init_internal_common(struct bnx2x *bp)
{
int i;
- if (!CHIP_IS_E1(bp)) {
-
- /* xstorm needs to know whether to add ovlan to packets or not,
- * in switch-independent we'll write 0 to here... */
- REG_WR8(bp, BAR_XSTRORM_INTMEM + XSTORM_FUNCTION_MODE_OFFSET,
- bp->mf_mode);
- REG_WR8(bp, BAR_TSTRORM_INTMEM + TSTORM_FUNCTION_MODE_OFFSET,
- bp->mf_mode);
- REG_WR8(bp, BAR_CSTRORM_INTMEM + CSTORM_FUNCTION_MODE_OFFSET,
- bp->mf_mode);
- REG_WR8(bp, BAR_USTRORM_INTMEM + USTORM_FUNCTION_MODE_OFFSET,
- bp->mf_mode);
- }
-
if (IS_MF_SI(bp))
/*
* In switch independent mode, the TSTORM needs to accept
@@ -4402,25 +4994,22 @@
*/
REG_WR8(bp, BAR_TSTRORM_INTMEM +
TSTORM_ACCEPT_CLASSIFY_FAILED_OFFSET, 2);
+ else if (!CHIP_IS_E1(bp)) /* 57710 doesn't support MF */
+ REG_WR8(bp, BAR_TSTRORM_INTMEM +
+ TSTORM_ACCEPT_CLASSIFY_FAILED_OFFSET, 0);
/* Zero this manually as its initialization is
currently missing in the initTool */
for (i = 0; i < (USTORM_AGG_DATA_SIZE >> 2); i++)
REG_WR(bp, BAR_USTRORM_INTMEM +
USTORM_AGG_DATA_OFFSET + i * 4, 0);
- if (CHIP_IS_E2(bp)) {
+ if (!CHIP_IS_E1x(bp)) {
REG_WR8(bp, BAR_CSTRORM_INTMEM + CSTORM_IGU_MODE_OFFSET,
CHIP_INT_MODE_IS_BC(bp) ?
HC_IGU_BC_MODE : HC_IGU_NBC_MODE);
}
}
-static void bnx2x_init_internal_port(struct bnx2x *bp)
-{
- /* port */
- bnx2x_dcb_init_intmem_pfc(bp);
-}
-
static void bnx2x_init_internal(struct bnx2x *bp, u32 load_code)
{
switch (load_code) {
@@ -4430,7 +5019,7 @@
/* no break */
case FW_MSG_CODE_DRV_LOAD_PORT:
- bnx2x_init_internal_port(bp);
+ /* nothing to do */
/* no break */
case FW_MSG_CODE_DRV_LOAD_FUNCTION:
@@ -4444,31 +5033,57 @@
}
}
-static void bnx2x_init_fp_sb(struct bnx2x *bp, int fp_idx)
+static inline u8 bnx2x_fp_igu_sb_id(struct bnx2x_fastpath *fp)
+{
+ return fp->bp->igu_base_sb + fp->index + CNIC_CONTEXT_USE;
+}
+
+static inline u8 bnx2x_fp_fw_sb_id(struct bnx2x_fastpath *fp)
+{
+ return fp->bp->base_fw_ndsb + fp->index + CNIC_CONTEXT_USE;
+}
+
+static inline u8 bnx2x_fp_cl_id(struct bnx2x_fastpath *fp)
+{
+ if (CHIP_IS_E1x(fp->bp))
+ return BP_L_ID(fp->bp) + fp->index;
+ else /* We want Client ID to be the same as IGU SB ID for 57712 */
+ return bnx2x_fp_igu_sb_id(fp);
+}
+
+static void bnx2x_init_fp(struct bnx2x *bp, int fp_idx)
{
struct bnx2x_fastpath *fp = &bp->fp[fp_idx];
-
- fp->state = BNX2X_FP_STATE_CLOSED;
+ unsigned long q_type = 0;
fp->cid = fp_idx;
- fp->cl_id = BP_L_ID(bp) + fp_idx;
- fp->fw_sb_id = bp->base_fw_ndsb + fp->cl_id + CNIC_CONTEXT_USE;
- fp->igu_sb_id = bp->igu_base_sb + fp_idx + CNIC_CONTEXT_USE;
+ fp->cl_id = bnx2x_fp_cl_id(fp);
+ fp->fw_sb_id = bnx2x_fp_fw_sb_id(fp);
+ fp->igu_sb_id = bnx2x_fp_igu_sb_id(fp);
/* qZone id equals to FW (per path) client id */
- fp->cl_qzone_id = fp->cl_id +
- BP_PORT(bp)*(CHIP_IS_E2(bp) ? ETH_MAX_RX_CLIENTS_E2 :
- ETH_MAX_RX_CLIENTS_E1H);
+ fp->cl_qzone_id = bnx2x_fp_qzone_id(fp);
+
/* init shortcut */
- fp->ustorm_rx_prods_offset = CHIP_IS_E2(bp) ?
- USTORM_RX_PRODS_E2_OFFSET(fp->cl_qzone_id) :
- USTORM_RX_PRODS_E1X_OFFSET(BP_PORT(bp), fp->cl_id);
+ fp->ustorm_rx_prods_offset = bnx2x_rx_ustorm_prods_offset(fp);
/* Setup SB indicies */
fp->rx_cons_sb = BNX2X_RX_SB_INDEX;
fp->tx_cons_sb = BNX2X_TX_SB_INDEX;
+ /* Configure Queue State object */
+ __set_bit(BNX2X_Q_TYPE_HAS_RX, &q_type);
+ __set_bit(BNX2X_Q_TYPE_HAS_TX, &q_type);
+ bnx2x_init_queue_obj(bp, &fp->q_obj, fp->cl_id, fp->cid, BP_FUNC(bp),
+ bnx2x_sp(bp, q_rdata), bnx2x_sp_mapping(bp, q_rdata),
+ q_type);
+
+ /**
+ * Configure classification DBs: Always enable Tx switching
+ */
+ bnx2x_init_vlan_mac_fp_objs(fp, BNX2X_OBJ_TYPE_RX_TX);
+
DP(NETIF_MSG_IFUP, "queue[%d]: bnx2x_init_sb(%p,%p) "
"cl_id %d fw_sb %d igu_sb %d\n",
- fp_idx, bp, fp->status_blk.e1x_sb, fp->cl_id, fp->fw_sb_id,
+ fp_idx, bp, fp->status_blk.e2_sb, fp->cl_id, fp->fw_sb_id,
fp->igu_sb_id);
bnx2x_init_sb(bp, fp->status_blk_mapping, BNX2X_VF_ID_INVALID, false,
fp->fw_sb_id, fp->igu_sb_id);
@@ -4481,17 +5096,21 @@
int i;
for_each_eth_queue(bp, i)
- bnx2x_init_fp_sb(bp, i);
+ bnx2x_init_fp(bp, i);
#ifdef BCM_CNIC
if (!NO_FCOE(bp))
bnx2x_init_fcoe_fp(bp);
bnx2x_init_sb(bp, bp->cnic_sb_mapping,
BNX2X_VF_ID_INVALID, false,
- CNIC_SB_ID(bp), CNIC_IGU_SB_ID(bp));
+ bnx2x_cnic_fw_sb_id(bp), bnx2x_cnic_igu_sb_id(bp));
#endif
+ /* Initialize MOD_ABS interrupts */
+ bnx2x_init_mod_abs_int(bp, &bp->link_vars, bp->common.chip_id,
+ bp->common.shmem_base, bp->common.shmem2_base,
+ BP_PORT(bp));
/* ensure status block indices were read */
rmb();
@@ -4503,12 +5122,8 @@
bnx2x_init_eq_ring(bp);
bnx2x_init_internal(bp, load_code);
bnx2x_pf_init(bp);
- bnx2x_init_ind_table(bp);
bnx2x_stats_init(bp);
- /* At this point, we are ready for interrupts */
- atomic_set(&bp->intr_sem, 0);
-
/* flush all before enabling interrupts */
mb();
mmiowb();
@@ -4711,8 +5326,8 @@
msleep(50);
REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_SET, 0x03);
msleep(50);
- bnx2x_init_block(bp, BRB1_BLOCK, COMMON_STAGE);
- bnx2x_init_block(bp, PRS_BLOCK, COMMON_STAGE);
+ bnx2x_init_block(bp, BLOCK_BRB1, PHASE_COMMON);
+ bnx2x_init_block(bp, BLOCK_PRS, PHASE_COMMON);
DP(NETIF_MSG_HW, "part2\n");
@@ -4776,8 +5391,8 @@
msleep(50);
REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_SET, 0x03);
msleep(50);
- bnx2x_init_block(bp, BRB1_BLOCK, COMMON_STAGE);
- bnx2x_init_block(bp, PRS_BLOCK, COMMON_STAGE);
+ bnx2x_init_block(bp, BLOCK_BRB1, PHASE_COMMON);
+ bnx2x_init_block(bp, BLOCK_PRS, PHASE_COMMON);
#ifndef BCM_CNIC
/* set NIC mode */
REG_WR(bp, PRS_REG_NIC_MODE, 1);
@@ -4797,7 +5412,7 @@
static void bnx2x_enable_blocks_attention(struct bnx2x *bp)
{
REG_WR(bp, PXP_REG_PXP_INT_MASK_0, 0);
- if (CHIP_IS_E2(bp))
+ if (!CHIP_IS_E1x(bp))
REG_WR(bp, PXP_REG_PXP_INT_MASK_1, 0x40);
else
REG_WR(bp, PXP_REG_PXP_INT_MASK_1, 0);
@@ -4831,7 +5446,7 @@
if (CHIP_REV_IS_FPGA(bp))
REG_WR(bp, PXP2_REG_PXP2_INT_MASK_0, 0x580000);
- else if (CHIP_IS_E2(bp))
+ else if (!CHIP_IS_E1x(bp))
REG_WR(bp, PXP2_REG_PXP2_INT_MASK_0,
(PXP2_PXP2_INT_MASK_0_REG_PGL_CPL_OF
| PXP2_PXP2_INT_MASK_0_REG_PGL_CPL_AFT
@@ -4844,7 +5459,11 @@
REG_WR(bp, TSDM_REG_TSDM_INT_MASK_1, 0);
REG_WR(bp, TCM_REG_TCM_INT_MASK, 0);
/* REG_WR(bp, TSEM_REG_TSEM_INT_MASK_0, 0); */
-/* REG_WR(bp, TSEM_REG_TSEM_INT_MASK_1, 0); */
+
+ if (!CHIP_IS_E1x(bp))
+ /* enable VFC attentions: bits 11 and 12, bits 31:13 reserved */
+ REG_WR(bp, TSEM_REG_TSEM_INT_MASK_1, 0x07ff);
+
REG_WR(bp, CDU_REG_CDU_INT_MASK, 0);
REG_WR(bp, DMAE_REG_DMAE_INT_MASK, 0);
/* REG_WR(bp, MISC_REG_MISC_INT_MASK, 0); */
@@ -4853,10 +5472,24 @@
static void bnx2x_reset_common(struct bnx2x *bp)
{
+ u32 val = 0x1400;
+
/* reset_common */
REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_CLEAR,
0xd3ffff7f);
- REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR, 0x1403);
+
+ if (CHIP_IS_E3(bp)) {
+ val |= MISC_REGISTERS_RESET_REG_2_MSTAT0;
+ val |= MISC_REGISTERS_RESET_REG_2_MSTAT1;
+ }
+
+ REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR, val);
+}
+
+static void bnx2x_setup_dmae(struct bnx2x *bp)
+{
+ bp->dmae_ready = 0;
+ spin_lock_init(&bp->dmae_lock);
}
static void bnx2x_init_pxp(struct bnx2x *bp)
@@ -4865,7 +5498,7 @@
int r_order, w_order;
pci_read_config_word(bp->pdev,
- bp->pcie_cap + PCI_EXP_DEVCTL, &devctl);
+ bp->pdev->pcie_cap + PCI_EXP_DEVCTL, &devctl);
DP(NETIF_MSG_HW, "read 0x%x from devctl\n", devctl);
w_order = ((devctl & PCI_EXP_DEVCTL_PAYLOAD) >> 5);
if (bp->mrrs == -1)
@@ -4973,7 +5606,7 @@
DP(NETIF_MSG_HW, "Pretending to func %d\n", pretend_func_num);
}
-static void bnx2x_pf_disable(struct bnx2x *bp)
+void bnx2x_pf_disable(struct bnx2x *bp)
{
u32 val = REG_RD(bp, IGU_REG_PF_CONFIGURATION);
val &= ~IGU_PF_CONF_FUNC_EN;
@@ -4983,22 +5616,48 @@
REG_WR(bp, CFC_REG_WEAK_ENABLE_PF, 0);
}
-static int bnx2x_init_hw_common(struct bnx2x *bp, u32 load_code)
+static inline void bnx2x__common_init_phy(struct bnx2x *bp)
{
- u32 val, i;
+ u32 shmem_base[2], shmem2_base[2];
+ shmem_base[0] = bp->common.shmem_base;
+ shmem2_base[0] = bp->common.shmem2_base;
+ if (!CHIP_IS_E1x(bp)) {
+ shmem_base[1] =
+ SHMEM2_RD(bp, other_shmem_base_addr);
+ shmem2_base[1] =
+ SHMEM2_RD(bp, other_shmem2_base_addr);
+ }
+ bnx2x_acquire_phy_lock(bp);
+ bnx2x_common_init_phy(bp, shmem_base, shmem2_base,
+ bp->common.chip_id);
+ bnx2x_release_phy_lock(bp);
+}
+
+/**
+ * bnx2x_init_hw_common - initialize the HW at the COMMON phase.
+ *
+ * @bp: driver handle
+ */
+static int bnx2x_init_hw_common(struct bnx2x *bp)
+{
+ u32 val;
DP(BNX2X_MSG_MCP, "starting common init func %d\n", BP_ABS_FUNC(bp));
bnx2x_reset_common(bp);
REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_SET, 0xffffffff);
- REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET, 0xfffc);
- bnx2x_init_block(bp, MISC_BLOCK, COMMON_STAGE);
- if (!CHIP_IS_E1(bp))
- REG_WR(bp, MISC_REG_E1HMF_MODE, IS_MF(bp));
+ val = 0xfffc;
+ if (CHIP_IS_E3(bp)) {
+ val |= MISC_REGISTERS_RESET_REG_2_MSTAT0;
+ val |= MISC_REGISTERS_RESET_REG_2_MSTAT1;
+ }
+ REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET, val);
- if (CHIP_IS_E2(bp)) {
- u8 fid;
+ bnx2x_init_block(bp, BLOCK_MISC, PHASE_COMMON);
+
+ if (!CHIP_IS_E1x(bp)) {
+ u8 abs_func_id;
/**
* 4-port mode or 2-port mode we need to turn of master-enable
@@ -5007,29 +5666,30 @@
* for all functions on the given path, this means 0,2,4,6 for
* path 0 and 1,3,5,7 for path 1
*/
- for (fid = BP_PATH(bp); fid < E2_FUNC_MAX*2; fid += 2) {
- if (fid == BP_ABS_FUNC(bp)) {
+ for (abs_func_id = BP_PATH(bp);
+ abs_func_id < E2_FUNC_MAX*2; abs_func_id += 2) {
+ if (abs_func_id == BP_ABS_FUNC(bp)) {
REG_WR(bp,
PGLUE_B_REG_INTERNAL_PFID_ENABLE_MASTER,
1);
continue;
}
- bnx2x_pretend_func(bp, fid);
+ bnx2x_pretend_func(bp, abs_func_id);
/* clear pf enable */
bnx2x_pf_disable(bp);
bnx2x_pretend_func(bp, BP_ABS_FUNC(bp));
}
}
- bnx2x_init_block(bp, PXP_BLOCK, COMMON_STAGE);
+ bnx2x_init_block(bp, BLOCK_PXP, PHASE_COMMON);
if (CHIP_IS_E1(bp)) {
/* enable HW interrupt from PXP on USDM overflow
bit 16 on INT_MASK_0 */
REG_WR(bp, PXP_REG_PXP_INT_MASK_0, 0);
}
- bnx2x_init_block(bp, PXP2_BLOCK, COMMON_STAGE);
+ bnx2x_init_block(bp, BLOCK_PXP2, PHASE_COMMON);
bnx2x_init_pxp(bp);
#ifdef __BIG_ENDIAN
@@ -5072,7 +5732,69 @@
* This needs to be done by the first PF that is loaded in a path
* (i.e. common phase)
*/
- if (CHIP_IS_E2(bp)) {
+ if (!CHIP_IS_E1x(bp)) {
+/* In E2 there is a bug in the timers block that can cause function 6 / 7
+ * (i.e. vnic3) to start even if it is marked as "scan-off".
+ * This occurs when a different function (func2,3) is being marked
+ * as "scan-off". Real-life scenario for example: if a driver is being
+ * load-unloaded while func6,7 are down. This will cause the timer to access
+ * the ilt, translate to a logical address and send a request to read/write.
+ * Since the ilt for the function that is down is not valid, this will cause
+ * a translation error which is unrecoverable.
+ * The Workaround is intended to make sure that when this happens nothing fatal
+ * will occur. The workaround:
+ * 1. First PF driver which loads on a path will:
+ * a. After taking the chip out of reset, by using pretend,
+ * it will write "0" to the following registers of
+ * the other vnics.
+ * REG_WR(pdev, PGLUE_B_REG_INTERNAL_PFID_ENABLE_MASTER, 0);
+ * REG_WR(pdev, CFC_REG_WEAK_ENABLE_PF,0);
+ * REG_WR(pdev, CFC_REG_STRONG_ENABLE_PF,0);
+ * And for itself it will write '1' to
+ * PGLUE_B_REG_INTERNAL_PFID_ENABLE_MASTER to enable
+ * dmae-operations (writing to pram for example.)
+ * note: can be done for only function 6,7 but cleaner this
+ * way.
+ * b. Write zero+valid to the entire ILT.
+ * c. Init the first_timers_ilt_entry, last_timers_ilt_entry of
+ * VNIC3 (of that port). The range allocated will be the
+ * entire ILT. This is needed to prevent ILT range error.
+ * 2. Any PF driver load flow:
+ * a. ILT update with the physical addresses of the allocated
+ * logical pages.
+ * b. Wait 20msec. - note that this timeout is needed to make
+ * sure there are no requests in one of the PXP internal
+ * queues with "old" ILT addresses.
+ * c. PF enable in the PGLC.
+ * d. Clear the was_error of the PF in the PGLC. (could have
+ * occured while driver was down)
+ * e. PF enable in the CFC (WEAK + STRONG)
+ * f. Timers scan enable
+ * 3. PF driver unload flow:
+ * a. Clear the Timers scan_en.
+ * b. Polling for scan_on=0 for that PF.
+ * c. Clear the PF enable bit in the PXP.
+ * d. Clear the PF enable in the CFC (WEAK + STRONG)
+ * e. Write zero+valid to all ILT entries (The valid bit must
+ * stay set)
+ * f. If this is VNIC 3 of a port then also init
+ * first_timers_ilt_entry to zero and last_timers_ilt_entry
+ * to the last enrty in the ILT.
+ *
+ * Notes:
+ * Currently the PF error in the PGLC is non recoverable.
+ * In the future the there will be a recovery routine for this error.
+ * Currently attention is masked.
+ * Having an MCP lock on the load/unload process does not guarantee that
+ * there is no Timer disable during Func6/7 enable. This is because the
+ * Timers scan is currently being cleared by the MCP on FLR.
+ * Step 2.d can be done only for PF6/7 and the driver can also check if
+ * there is error before clearing it. But the flow above is simpler and
+ * more general.
+ * All ILT entries are written by zero+valid and not just PF6/7
+ * ILT entries since in the future the ILT entries allocation for
+ * PF-s might be dynamic.
+ */
struct ilt_client_info ilt_cli;
struct bnx2x_ilt ilt;
memset(&ilt_cli, 0, sizeof(struct ilt_client_info));
@@ -5086,7 +5808,7 @@
/* Step 1: set zeroes to all ilt page entries with valid bit on
* Step 2: set the timers first/last ilt entry to point
* to the entire range to prevent ILT range error for 3rd/4th
- * vnic (this code assumes existence of the vnic)
+ * vnic (this code assumes existance of the vnic)
*
* both steps performed by call to bnx2x_ilt_client_init_op()
* with dummy TM client
@@ -5107,12 +5829,12 @@
REG_WR(bp, PXP2_REG_RQ_DISABLE_INPUTS, 0);
REG_WR(bp, PXP2_REG_RD_DISABLE_INPUTS, 0);
- if (CHIP_IS_E2(bp)) {
+ if (!CHIP_IS_E1x(bp)) {
int factor = CHIP_REV_IS_EMUL(bp) ? 1000 :
(CHIP_REV_IS_FPGA(bp) ? 400 : 0);
- bnx2x_init_block(bp, PGLUE_B_BLOCK, COMMON_STAGE);
+ bnx2x_init_block(bp, BLOCK_PGLUE_B, PHASE_COMMON);
- bnx2x_init_block(bp, ATC_BLOCK, COMMON_STAGE);
+ bnx2x_init_block(bp, BLOCK_ATC, PHASE_COMMON);
/* let the HW do it's magic ... */
do {
@@ -5126,26 +5848,27 @@
}
}
- bnx2x_init_block(bp, DMAE_BLOCK, COMMON_STAGE);
+ bnx2x_init_block(bp, BLOCK_DMAE, PHASE_COMMON);
/* clean the DMAE memory */
bp->dmae_ready = 1;
- bnx2x_init_fill(bp, TSEM_REG_PRAM, 0, 8);
+ bnx2x_init_fill(bp, TSEM_REG_PRAM, 0, 8, 1);
- bnx2x_init_block(bp, TCM_BLOCK, COMMON_STAGE);
- bnx2x_init_block(bp, UCM_BLOCK, COMMON_STAGE);
- bnx2x_init_block(bp, CCM_BLOCK, COMMON_STAGE);
- bnx2x_init_block(bp, XCM_BLOCK, COMMON_STAGE);
+ bnx2x_init_block(bp, BLOCK_TCM, PHASE_COMMON);
+
+ bnx2x_init_block(bp, BLOCK_UCM, PHASE_COMMON);
+
+ bnx2x_init_block(bp, BLOCK_CCM, PHASE_COMMON);
+
+ bnx2x_init_block(bp, BLOCK_XCM, PHASE_COMMON);
bnx2x_read_dmae(bp, XSEM_REG_PASSIVE_BUFFER, 3);
bnx2x_read_dmae(bp, CSEM_REG_PASSIVE_BUFFER, 3);
bnx2x_read_dmae(bp, TSEM_REG_PASSIVE_BUFFER, 3);
bnx2x_read_dmae(bp, USEM_REG_PASSIVE_BUFFER, 3);
- bnx2x_init_block(bp, QM_BLOCK, COMMON_STAGE);
+ bnx2x_init_block(bp, BLOCK_QM, PHASE_COMMON);
- if (CHIP_MODE_IS_4_PORT(bp))
- bnx2x_init_block(bp, QM_4PORT_BLOCK, COMMON_STAGE);
/* QM queues pointers table */
bnx2x_qm_init_ptr_table(bp, bp->qm_cid_count, INITOP_SET);
@@ -5155,57 +5878,51 @@
REG_WR(bp, QM_REG_SOFT_RESET, 0);
#ifdef BCM_CNIC
- bnx2x_init_block(bp, TIMERS_BLOCK, COMMON_STAGE);
+ bnx2x_init_block(bp, BLOCK_TM, PHASE_COMMON);
#endif
- bnx2x_init_block(bp, DQ_BLOCK, COMMON_STAGE);
+ bnx2x_init_block(bp, BLOCK_DORQ, PHASE_COMMON);
REG_WR(bp, DORQ_REG_DPM_CID_OFST, BNX2X_DB_SHIFT);
-
- if (!CHIP_REV_IS_SLOW(bp)) {
+ if (!CHIP_REV_IS_SLOW(bp))
/* enable hw interrupt from doorbell Q */
REG_WR(bp, DORQ_REG_DORQ_INT_MASK, 0);
- }
- bnx2x_init_block(bp, BRB1_BLOCK, COMMON_STAGE);
- if (CHIP_MODE_IS_4_PORT(bp)) {
- REG_WR(bp, BRB1_REG_FULL_LB_XOFF_THRESHOLD, 248);
- REG_WR(bp, BRB1_REG_FULL_LB_XON_THRESHOLD, 328);
- }
+ bnx2x_init_block(bp, BLOCK_BRB1, PHASE_COMMON);
- bnx2x_init_block(bp, PRS_BLOCK, COMMON_STAGE);
+ bnx2x_init_block(bp, BLOCK_PRS, PHASE_COMMON);
REG_WR(bp, PRS_REG_A_PRSU_20, 0xf);
-#ifndef BCM_CNIC
- /* set NIC mode */
- REG_WR(bp, PRS_REG_NIC_MODE, 1);
-#endif
- if (!CHIP_IS_E1(bp))
- REG_WR(bp, PRS_REG_E1HOV_MODE, IS_MF_SD(bp));
- if (CHIP_IS_E2(bp)) {
- /* Bit-map indicating which L2 hdrs may appear after the
- basic Ethernet header */
- int has_ovlan = IS_MF_SD(bp);
- REG_WR(bp, PRS_REG_HDRS_AFTER_BASIC, (has_ovlan ? 7 : 6));
- REG_WR(bp, PRS_REG_MUST_HAVE_HDRS, (has_ovlan ? 1 : 0));
+ if (!CHIP_IS_E1(bp))
+ REG_WR(bp, PRS_REG_E1HOV_MODE, bp->path_has_ovlan);
+
+ if (!CHIP_IS_E1x(bp) && !CHIP_IS_E3B0(bp))
+ /* Bit-map indicating which L2 hdrs may appear
+ * after the basic Ethernet header
+ */
+ REG_WR(bp, PRS_REG_HDRS_AFTER_BASIC,
+ bp->path_has_ovlan ? 7 : 6);
+
+ bnx2x_init_block(bp, BLOCK_TSDM, PHASE_COMMON);
+ bnx2x_init_block(bp, BLOCK_CSDM, PHASE_COMMON);
+ bnx2x_init_block(bp, BLOCK_USDM, PHASE_COMMON);
+ bnx2x_init_block(bp, BLOCK_XSDM, PHASE_COMMON);
+
+ if (!CHIP_IS_E1x(bp)) {
+ /* reset VFC memories */
+ REG_WR(bp, TSEM_REG_FAST_MEMORY + VFC_REG_MEMORIES_RST,
+ VFC_MEMORIES_RST_REG_CAM_RST |
+ VFC_MEMORIES_RST_REG_RAM_RST);
+ REG_WR(bp, XSEM_REG_FAST_MEMORY + VFC_REG_MEMORIES_RST,
+ VFC_MEMORIES_RST_REG_CAM_RST |
+ VFC_MEMORIES_RST_REG_RAM_RST);
+
+ msleep(20);
}
- bnx2x_init_block(bp, TSDM_BLOCK, COMMON_STAGE);
- bnx2x_init_block(bp, CSDM_BLOCK, COMMON_STAGE);
- bnx2x_init_block(bp, USDM_BLOCK, COMMON_STAGE);
- bnx2x_init_block(bp, XSDM_BLOCK, COMMON_STAGE);
-
- bnx2x_init_fill(bp, TSEM_REG_FAST_MEMORY, 0, STORM_INTMEM_SIZE(bp));
- bnx2x_init_fill(bp, USEM_REG_FAST_MEMORY, 0, STORM_INTMEM_SIZE(bp));
- bnx2x_init_fill(bp, CSEM_REG_FAST_MEMORY, 0, STORM_INTMEM_SIZE(bp));
- bnx2x_init_fill(bp, XSEM_REG_FAST_MEMORY, 0, STORM_INTMEM_SIZE(bp));
-
- bnx2x_init_block(bp, TSEM_BLOCK, COMMON_STAGE);
- bnx2x_init_block(bp, USEM_BLOCK, COMMON_STAGE);
- bnx2x_init_block(bp, CSEM_BLOCK, COMMON_STAGE);
- bnx2x_init_block(bp, XSEM_BLOCK, COMMON_STAGE);
-
- if (CHIP_MODE_IS_4_PORT(bp))
- bnx2x_init_block(bp, XSEM_4PORT_BLOCK, COMMON_STAGE);
+ bnx2x_init_block(bp, BLOCK_TSEM, PHASE_COMMON);
+ bnx2x_init_block(bp, BLOCK_USEM, PHASE_COMMON);
+ bnx2x_init_block(bp, BLOCK_CSEM, PHASE_COMMON);
+ bnx2x_init_block(bp, BLOCK_XSEM, PHASE_COMMON);
/* sync semi rtc */
REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_CLEAR,
@@ -5213,21 +5930,18 @@
REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_SET,
0x80000000);
- bnx2x_init_block(bp, UPB_BLOCK, COMMON_STAGE);
- bnx2x_init_block(bp, XPB_BLOCK, COMMON_STAGE);
- bnx2x_init_block(bp, PBF_BLOCK, COMMON_STAGE);
+ bnx2x_init_block(bp, BLOCK_UPB, PHASE_COMMON);
+ bnx2x_init_block(bp, BLOCK_XPB, PHASE_COMMON);
+ bnx2x_init_block(bp, BLOCK_PBF, PHASE_COMMON);
- if (CHIP_IS_E2(bp)) {
- int has_ovlan = IS_MF_SD(bp);
- REG_WR(bp, PBF_REG_HDRS_AFTER_BASIC, (has_ovlan ? 7 : 6));
- REG_WR(bp, PBF_REG_MUST_HAVE_HDRS, (has_ovlan ? 1 : 0));
- }
+ if (!CHIP_IS_E1x(bp))
+ REG_WR(bp, PBF_REG_HDRS_AFTER_BASIC,
+ bp->path_has_ovlan ? 7 : 6);
REG_WR(bp, SRC_REG_SOFT_RST, 1);
- for (i = SRC_REG_KEYRSS0_0; i <= SRC_REG_KEYRSS1_9; i += 4)
- REG_WR(bp, i, random32());
- bnx2x_init_block(bp, SRCH_BLOCK, COMMON_STAGE);
+ bnx2x_init_block(bp, BLOCK_SRC, PHASE_COMMON);
+
#ifdef BCM_CNIC
REG_WR(bp, SRC_REG_KEYSEARCH_0, 0x63285672);
REG_WR(bp, SRC_REG_KEYSEARCH_1, 0x24b8f2cc);
@@ -5248,11 +5962,11 @@
"of cdu_context(%ld)\n",
(long)sizeof(union cdu_context));
- bnx2x_init_block(bp, CDU_BLOCK, COMMON_STAGE);
+ bnx2x_init_block(bp, BLOCK_CDU, PHASE_COMMON);
val = (4 << 24) + (0 << 12) + 1024;
REG_WR(bp, CDU_REG_CDU_GLOBAL_PARAMS, val);
- bnx2x_init_block(bp, CFC_BLOCK, COMMON_STAGE);
+ bnx2x_init_block(bp, BLOCK_CFC, PHASE_COMMON);
REG_WR(bp, CFC_REG_INIT_REG, 0x7FF);
/* enable context validation interrupt from CFC */
REG_WR(bp, CFC_REG_CFC_INT_MASK, 0);
@@ -5260,20 +5974,19 @@
/* set the thresholds to prevent CFC/CDU race */
REG_WR(bp, CFC_REG_DEBUG0, 0x20020000);
- bnx2x_init_block(bp, HC_BLOCK, COMMON_STAGE);
+ bnx2x_init_block(bp, BLOCK_HC, PHASE_COMMON);
- if (CHIP_IS_E2(bp) && BP_NOMCP(bp))
+ if (!CHIP_IS_E1x(bp) && BP_NOMCP(bp))
REG_WR(bp, IGU_REG_RESET_MEMORIES, 0x36);
- bnx2x_init_block(bp, IGU_BLOCK, COMMON_STAGE);
- bnx2x_init_block(bp, MISC_AEU_BLOCK, COMMON_STAGE);
+ bnx2x_init_block(bp, BLOCK_IGU, PHASE_COMMON);
+ bnx2x_init_block(bp, BLOCK_MISC_AEU, PHASE_COMMON);
- bnx2x_init_block(bp, PXPCS_BLOCK, COMMON_STAGE);
/* Reset PCIE errors for debug */
REG_WR(bp, 0x2814, 0xffffffff);
REG_WR(bp, 0x3820, 0xffffffff);
- if (CHIP_IS_E2(bp)) {
+ if (!CHIP_IS_E1x(bp)) {
REG_WR(bp, PCICFG_OFFSET + PXPCS_TL_CONTROL_5,
(PXPCS_TL_CONTROL_5_ERR_UNSPPORT1 |
PXPCS_TL_CONTROL_5_ERR_UNSPPORT));
@@ -5287,21 +6000,15 @@
PXPCS_TL_FUNC678_STAT_ERR_UNSPPORT5));
}
- bnx2x_init_block(bp, EMAC0_BLOCK, COMMON_STAGE);
- bnx2x_init_block(bp, EMAC1_BLOCK, COMMON_STAGE);
- bnx2x_init_block(bp, DBU_BLOCK, COMMON_STAGE);
- bnx2x_init_block(bp, DBG_BLOCK, COMMON_STAGE);
-
- bnx2x_init_block(bp, NIG_BLOCK, COMMON_STAGE);
+ bnx2x_init_block(bp, BLOCK_NIG, PHASE_COMMON);
if (!CHIP_IS_E1(bp)) {
- REG_WR(bp, NIG_REG_LLH_MF_MODE, IS_MF(bp));
+ /* in E3 this done in per-port section */
+ if (!CHIP_IS_E3(bp))
+ REG_WR(bp, NIG_REG_LLH_MF_MODE, IS_MF(bp));
+ }
+ if (CHIP_IS_E1H(bp))
+ /* not applicable for E2 (and above ...) */
REG_WR(bp, NIG_REG_LLH_E1HOV_MODE, IS_MF_SD(bp));
- }
- if (CHIP_IS_E2(bp)) {
- /* Bit-map indicating which L2 hdrs may appear after the
- basic Ethernet header */
- REG_WR(bp, NIG_REG_P0_HDRS_AFTER_BASIC, (IS_MF_SD(bp) ? 7 : 6));
- }
if (CHIP_REV_IS_SLOW(bp))
msleep(200);
@@ -5343,127 +6050,136 @@
REG_RD(bp, PXP2_REG_PXP2_INT_STS_CLR_0);
bnx2x_enable_blocks_attention(bp);
- if (CHIP_PARITY_ENABLED(bp))
- bnx2x_enable_blocks_parity(bp);
+ bnx2x_enable_blocks_parity(bp);
if (!BP_NOMCP(bp)) {
- /* In E2 2-PORT mode, same ext phy is used for the two paths */
- if ((load_code == FW_MSG_CODE_DRV_LOAD_COMMON_CHIP) ||
- CHIP_IS_E1x(bp)) {
- u32 shmem_base[2], shmem2_base[2];
- shmem_base[0] = bp->common.shmem_base;
- shmem2_base[0] = bp->common.shmem2_base;
- if (CHIP_IS_E2(bp)) {
- shmem_base[1] =
- SHMEM2_RD(bp, other_shmem_base_addr);
- shmem2_base[1] =
- SHMEM2_RD(bp, other_shmem2_base_addr);
- }
- bnx2x_acquire_phy_lock(bp);
- bnx2x_common_init_phy(bp, shmem_base, shmem2_base,
- bp->common.chip_id);
- bnx2x_release_phy_lock(bp);
- }
+ if (CHIP_IS_E1x(bp))
+ bnx2x__common_init_phy(bp);
} else
BNX2X_ERR("Bootcode is missing - can not initialize link\n");
return 0;
}
+/**
+ * bnx2x_init_hw_common_chip - init HW at the COMMON_CHIP phase.
+ *
+ * @bp: driver handle
+ */
+static int bnx2x_init_hw_common_chip(struct bnx2x *bp)
+{
+ int rc = bnx2x_init_hw_common(bp);
+
+ if (rc)
+ return rc;
+
+ /* In E2 2-PORT mode, same ext phy is used for the two paths */
+ if (!BP_NOMCP(bp))
+ bnx2x__common_init_phy(bp);
+
+ return 0;
+}
+
static int bnx2x_init_hw_port(struct bnx2x *bp)
{
int port = BP_PORT(bp);
- int init_stage = port ? PORT1_STAGE : PORT0_STAGE;
+ int init_phase = port ? PHASE_PORT1 : PHASE_PORT0;
u32 low, high;
u32 val;
+ bnx2x__link_reset(bp);
+
DP(BNX2X_MSG_MCP, "starting port init port %d\n", port);
REG_WR(bp, NIG_REG_MASK_INTERRUPT_PORT0 + port*4, 0);
- bnx2x_init_block(bp, PXP_BLOCK, init_stage);
- bnx2x_init_block(bp, PXP2_BLOCK, init_stage);
+ bnx2x_init_block(bp, BLOCK_MISC, init_phase);
+ bnx2x_init_block(bp, BLOCK_PXP, init_phase);
+ bnx2x_init_block(bp, BLOCK_PXP2, init_phase);
/* Timers bug workaround: disables the pf_master bit in pglue at
* common phase, we need to enable it here before any dmae access are
* attempted. Therefore we manually added the enable-master to the
* port phase (it also happens in the function phase)
*/
- if (CHIP_IS_E2(bp))
+ if (!CHIP_IS_E1x(bp))
REG_WR(bp, PGLUE_B_REG_INTERNAL_PFID_ENABLE_MASTER, 1);
- bnx2x_init_block(bp, TCM_BLOCK, init_stage);
- bnx2x_init_block(bp, UCM_BLOCK, init_stage);
- bnx2x_init_block(bp, CCM_BLOCK, init_stage);
- bnx2x_init_block(bp, XCM_BLOCK, init_stage);
+ bnx2x_init_block(bp, BLOCK_ATC, init_phase);
+ bnx2x_init_block(bp, BLOCK_DMAE, init_phase);
+ bnx2x_init_block(bp, BLOCK_PGLUE_B, init_phase);
+ bnx2x_init_block(bp, BLOCK_QM, init_phase);
+
+ bnx2x_init_block(bp, BLOCK_TCM, init_phase);
+ bnx2x_init_block(bp, BLOCK_UCM, init_phase);
+ bnx2x_init_block(bp, BLOCK_CCM, init_phase);
+ bnx2x_init_block(bp, BLOCK_XCM, init_phase);
/* QM cid (connection) count */
bnx2x_qm_init_cid_count(bp, bp->qm_cid_count, INITOP_SET);
#ifdef BCM_CNIC
- bnx2x_init_block(bp, TIMERS_BLOCK, init_stage);
+ bnx2x_init_block(bp, BLOCK_TM, init_phase);
REG_WR(bp, TM_REG_LIN0_SCAN_TIME + port*4, 20);
REG_WR(bp, TM_REG_LIN0_MAX_ACTIVE_CID + port*4, 31);
#endif
- bnx2x_init_block(bp, DQ_BLOCK, init_stage);
-
- if (CHIP_MODE_IS_4_PORT(bp))
- bnx2x_init_block(bp, QM_4PORT_BLOCK, init_stage);
+ bnx2x_init_block(bp, BLOCK_DORQ, init_phase);
if (CHIP_IS_E1(bp) || CHIP_IS_E1H(bp)) {
- bnx2x_init_block(bp, BRB1_BLOCK, init_stage);
- if (CHIP_REV_IS_SLOW(bp) && CHIP_IS_E1(bp)) {
- /* no pause for emulation and FPGA */
- low = 0;
- high = 513;
- } else {
- if (IS_MF(bp))
- low = ((bp->flags & ONE_PORT_FLAG) ? 160 : 246);
- else if (bp->dev->mtu > 4096) {
- if (bp->flags & ONE_PORT_FLAG)
- low = 160;
- else {
- val = bp->dev->mtu;
- /* (24*1024 + val*4)/256 */
- low = 96 + (val/64) +
- ((val % 64) ? 1 : 0);
- }
- } else
- low = ((bp->flags & ONE_PORT_FLAG) ? 80 : 160);
- high = low + 56; /* 14*1024/256 */
- }
+ bnx2x_init_block(bp, BLOCK_BRB1, init_phase);
+
+ if (IS_MF(bp))
+ low = ((bp->flags & ONE_PORT_FLAG) ? 160 : 246);
+ else if (bp->dev->mtu > 4096) {
+ if (bp->flags & ONE_PORT_FLAG)
+ low = 160;
+ else {
+ val = bp->dev->mtu;
+ /* (24*1024 + val*4)/256 */
+ low = 96 + (val/64) +
+ ((val % 64) ? 1 : 0);
+ }
+ } else
+ low = ((bp->flags & ONE_PORT_FLAG) ? 80 : 160);
+ high = low + 56; /* 14*1024/256 */
REG_WR(bp, BRB1_REG_PAUSE_LOW_THRESHOLD_0 + port*4, low);
REG_WR(bp, BRB1_REG_PAUSE_HIGH_THRESHOLD_0 + port*4, high);
}
- if (CHIP_MODE_IS_4_PORT(bp)) {
- REG_WR(bp, BRB1_REG_PAUSE_0_XOFF_THRESHOLD_0 + port*8, 248);
- REG_WR(bp, BRB1_REG_PAUSE_0_XON_THRESHOLD_0 + port*8, 328);
- REG_WR(bp, (BP_PORT(bp) ? BRB1_REG_MAC_GUARANTIED_1 :
- BRB1_REG_MAC_GUARANTIED_0), 40);
- }
-
- bnx2x_init_block(bp, PRS_BLOCK, init_stage);
-
- bnx2x_init_block(bp, TSDM_BLOCK, init_stage);
- bnx2x_init_block(bp, CSDM_BLOCK, init_stage);
- bnx2x_init_block(bp, USDM_BLOCK, init_stage);
- bnx2x_init_block(bp, XSDM_BLOCK, init_stage);
-
- bnx2x_init_block(bp, TSEM_BLOCK, init_stage);
- bnx2x_init_block(bp, USEM_BLOCK, init_stage);
- bnx2x_init_block(bp, CSEM_BLOCK, init_stage);
- bnx2x_init_block(bp, XSEM_BLOCK, init_stage);
if (CHIP_MODE_IS_4_PORT(bp))
- bnx2x_init_block(bp, XSEM_4PORT_BLOCK, init_stage);
+ REG_WR(bp, (BP_PORT(bp) ?
+ BRB1_REG_MAC_GUARANTIED_1 :
+ BRB1_REG_MAC_GUARANTIED_0), 40);
- bnx2x_init_block(bp, UPB_BLOCK, init_stage);
- bnx2x_init_block(bp, XPB_BLOCK, init_stage);
- bnx2x_init_block(bp, PBF_BLOCK, init_stage);
+ bnx2x_init_block(bp, BLOCK_PRS, init_phase);
+ if (CHIP_IS_E3B0(bp))
+ /* Ovlan exists only if we are in multi-function +
+ * switch-dependent mode, in switch-independent there
+ * is no ovlan headers
+ */
+ REG_WR(bp, BP_PORT(bp) ?
+ PRS_REG_HDRS_AFTER_BASIC_PORT_1 :
+ PRS_REG_HDRS_AFTER_BASIC_PORT_0,
+ (bp->path_has_ovlan ? 7 : 6));
- if (!CHIP_IS_E2(bp)) {
+ bnx2x_init_block(bp, BLOCK_TSDM, init_phase);
+ bnx2x_init_block(bp, BLOCK_CSDM, init_phase);
+ bnx2x_init_block(bp, BLOCK_USDM, init_phase);
+ bnx2x_init_block(bp, BLOCK_XSDM, init_phase);
+
+ bnx2x_init_block(bp, BLOCK_TSEM, init_phase);
+ bnx2x_init_block(bp, BLOCK_USEM, init_phase);
+ bnx2x_init_block(bp, BLOCK_CSEM, init_phase);
+ bnx2x_init_block(bp, BLOCK_XSEM, init_phase);
+
+ bnx2x_init_block(bp, BLOCK_UPB, init_phase);
+ bnx2x_init_block(bp, BLOCK_XPB, init_phase);
+
+ bnx2x_init_block(bp, BLOCK_PBF, init_phase);
+
+ if (CHIP_IS_E1x(bp)) {
/* configure PBF to work without PAUSE mtu 9000 */
REG_WR(bp, PBF_REG_P0_PAUSE_ENABLE + port*4, 0);
@@ -5479,20 +6195,20 @@
}
#ifdef BCM_CNIC
- bnx2x_init_block(bp, SRCH_BLOCK, init_stage);
+ bnx2x_init_block(bp, BLOCK_SRC, init_phase);
#endif
- bnx2x_init_block(bp, CDU_BLOCK, init_stage);
- bnx2x_init_block(bp, CFC_BLOCK, init_stage);
+ bnx2x_init_block(bp, BLOCK_CDU, init_phase);
+ bnx2x_init_block(bp, BLOCK_CFC, init_phase);
if (CHIP_IS_E1(bp)) {
REG_WR(bp, HC_REG_LEADING_EDGE_0 + port*8, 0);
REG_WR(bp, HC_REG_TRAILING_EDGE_0 + port*8, 0);
}
- bnx2x_init_block(bp, HC_BLOCK, init_stage);
+ bnx2x_init_block(bp, BLOCK_HC, init_phase);
- bnx2x_init_block(bp, IGU_BLOCK, init_stage);
+ bnx2x_init_block(bp, BLOCK_IGU, init_phase);
- bnx2x_init_block(bp, MISC_AEU_BLOCK, init_stage);
+ bnx2x_init_block(bp, BLOCK_MISC_AEU, init_phase);
/* init aeu_mask_attn_func_0/1:
* - SF mode: bits 3-7 are masked. only bits 0-2 are in use
* - MF mode: bit 3 is masked. bits 0-2 are in use as in SF
@@ -5502,22 +6218,31 @@
val |= CHIP_IS_E1(bp) ? 0 : 0x10;
REG_WR(bp, MISC_REG_AEU_MASK_ATTN_FUNC_0 + port*4, val);
- bnx2x_init_block(bp, PXPCS_BLOCK, init_stage);
- bnx2x_init_block(bp, EMAC0_BLOCK, init_stage);
- bnx2x_init_block(bp, EMAC1_BLOCK, init_stage);
- bnx2x_init_block(bp, DBU_BLOCK, init_stage);
- bnx2x_init_block(bp, DBG_BLOCK, init_stage);
+ bnx2x_init_block(bp, BLOCK_NIG, init_phase);
- bnx2x_init_block(bp, NIG_BLOCK, init_stage);
+ if (!CHIP_IS_E1x(bp)) {
+ /* Bit-map indicating which L2 hdrs may appear after the
+ * basic Ethernet header
+ */
+ REG_WR(bp, BP_PORT(bp) ?
+ NIG_REG_P1_HDRS_AFTER_BASIC :
+ NIG_REG_P0_HDRS_AFTER_BASIC,
+ IS_MF_SD(bp) ? 7 : 6);
- REG_WR(bp, NIG_REG_XGXS_SERDES0_MODE_SEL + port*4, 1);
+ if (CHIP_IS_E3(bp))
+ REG_WR(bp, BP_PORT(bp) ?
+ NIG_REG_LLH1_MF_MODE :
+ NIG_REG_LLH_MF_MODE, IS_MF(bp));
+ }
+ if (!CHIP_IS_E3(bp))
+ REG_WR(bp, NIG_REG_XGXS_SERDES0_MODE_SEL + port*4, 1);
if (!CHIP_IS_E1(bp)) {
/* 0x2 disable mf_ov, 0x1 enable */
REG_WR(bp, NIG_REG_LLH0_BRB1_DRV_MASK_MF + port*4,
(IS_MF_SD(bp) ? 0x1 : 0x2));
- if (CHIP_IS_E2(bp)) {
+ if (!CHIP_IS_E1x(bp)) {
val = 0;
switch (bp->mf_mode) {
case MULTI_FUNCTION_SD:
@@ -5538,17 +6263,16 @@
}
}
- bnx2x_init_block(bp, MCP_BLOCK, init_stage);
- bnx2x_init_block(bp, DMAE_BLOCK, init_stage);
- if (bnx2x_fan_failure_det_req(bp, bp->common.shmem_base,
- bp->common.shmem2_base, port)) {
+
+ /* If SPIO5 is set to generate interrupts, enable it for this port */
+ val = REG_RD(bp, MISC_REG_SPIO_EVENT_EN);
+ if (val & (1 << MISC_REGISTERS_SPIO_5)) {
u32 reg_addr = (port ? MISC_REG_AEU_ENABLE1_FUNC_1_OUT_0 :
MISC_REG_AEU_ENABLE1_FUNC_0_OUT_0);
val = REG_RD(bp, reg_addr);
val |= AEU_INPUTS_ATTN_BITS_SPIO5;
REG_WR(bp, reg_addr, val);
}
- bnx2x__link_reset(bp);
return 0;
}
@@ -5567,7 +6291,7 @@
static inline void bnx2x_igu_clear_sb(struct bnx2x *bp, u8 idu_sb_id)
{
- bnx2x_igu_clear_sb_gen(bp, idu_sb_id, true /*PF*/);
+ bnx2x_igu_clear_sb_gen(bp, BP_FUNC(bp), idu_sb_id, true /*PF*/);
}
static inline void bnx2x_clear_func_ilt(struct bnx2x *bp, u32 func)
@@ -5581,6 +6305,7 @@
{
int port = BP_PORT(bp);
int func = BP_FUNC(bp);
+ int init_phase = PHASE_PF0 + func;
struct bnx2x_ilt *ilt = BP_ILT(bp);
u16 cdu_ilt_start;
u32 addr, val;
@@ -5589,6 +6314,10 @@
DP(BNX2X_MSG_MCP, "starting func init func %d\n", func);
+ /* FLR cleanup - hmmm */
+ if (!CHIP_IS_E1x(bp))
+ bnx2x_pf_flr_clnup(bp);
+
/* set MSI reconfigure capability */
if (bp->common.int_block == INT_BLOCK_HC) {
addr = (port ? HC_REG_CONFIG_1 : HC_REG_CONFIG_0);
@@ -5597,6 +6326,9 @@
REG_WR(bp, addr, val);
}
+ bnx2x_init_block(bp, BLOCK_PXP, init_phase);
+ bnx2x_init_block(bp, BLOCK_PXP2, init_phase);
+
ilt = BP_ILT(bp);
cdu_ilt_start = ilt->clients[ILT_CLIENT_CDU].start;
@@ -5622,7 +6354,7 @@
REG_WR(bp, PRS_REG_NIC_MODE, 1);
#endif /* BCM_CNIC */
- if (CHIP_IS_E2(bp)) {
+ if (!CHIP_IS_E1x(bp)) {
u32 pf_conf = IGU_PF_CONF_FUNC_EN;
/* Turn on a single ISR mode in IGU if driver is going to use
@@ -5649,58 +6381,55 @@
bp->dmae_ready = 1;
- bnx2x_init_block(bp, PGLUE_B_BLOCK, FUNC0_STAGE + func);
+ bnx2x_init_block(bp, BLOCK_PGLUE_B, init_phase);
- if (CHIP_IS_E2(bp))
+ if (!CHIP_IS_E1x(bp))
REG_WR(bp, PGLUE_B_REG_WAS_ERROR_PF_7_0_CLR, func);
- bnx2x_init_block(bp, MISC_BLOCK, FUNC0_STAGE + func);
- bnx2x_init_block(bp, TCM_BLOCK, FUNC0_STAGE + func);
- bnx2x_init_block(bp, UCM_BLOCK, FUNC0_STAGE + func);
- bnx2x_init_block(bp, CCM_BLOCK, FUNC0_STAGE + func);
- bnx2x_init_block(bp, XCM_BLOCK, FUNC0_STAGE + func);
- bnx2x_init_block(bp, TSEM_BLOCK, FUNC0_STAGE + func);
- bnx2x_init_block(bp, USEM_BLOCK, FUNC0_STAGE + func);
- bnx2x_init_block(bp, CSEM_BLOCK, FUNC0_STAGE + func);
- bnx2x_init_block(bp, XSEM_BLOCK, FUNC0_STAGE + func);
+ bnx2x_init_block(bp, BLOCK_ATC, init_phase);
+ bnx2x_init_block(bp, BLOCK_DMAE, init_phase);
+ bnx2x_init_block(bp, BLOCK_NIG, init_phase);
+ bnx2x_init_block(bp, BLOCK_SRC, init_phase);
+ bnx2x_init_block(bp, BLOCK_MISC, init_phase);
+ bnx2x_init_block(bp, BLOCK_TCM, init_phase);
+ bnx2x_init_block(bp, BLOCK_UCM, init_phase);
+ bnx2x_init_block(bp, BLOCK_CCM, init_phase);
+ bnx2x_init_block(bp, BLOCK_XCM, init_phase);
+ bnx2x_init_block(bp, BLOCK_TSEM, init_phase);
+ bnx2x_init_block(bp, BLOCK_USEM, init_phase);
+ bnx2x_init_block(bp, BLOCK_CSEM, init_phase);
+ bnx2x_init_block(bp, BLOCK_XSEM, init_phase);
- if (CHIP_IS_E2(bp)) {
- REG_WR(bp, BAR_XSTRORM_INTMEM + XSTORM_PATH_ID_OFFSET,
- BP_PATH(bp));
- REG_WR(bp, BAR_CSTRORM_INTMEM + CSTORM_PATH_ID_OFFSET,
- BP_PATH(bp));
- }
-
- if (CHIP_MODE_IS_4_PORT(bp))
- bnx2x_init_block(bp, XSEM_4PORT_BLOCK, FUNC0_STAGE + func);
-
- if (CHIP_IS_E2(bp))
+ if (!CHIP_IS_E1x(bp))
REG_WR(bp, QM_REG_PF_EN, 1);
- bnx2x_init_block(bp, QM_BLOCK, FUNC0_STAGE + func);
+ if (!CHIP_IS_E1x(bp)) {
+ REG_WR(bp, TSEM_REG_VFPF_ERR_NUM, BNX2X_MAX_NUM_OF_VFS + func);
+ REG_WR(bp, USEM_REG_VFPF_ERR_NUM, BNX2X_MAX_NUM_OF_VFS + func);
+ REG_WR(bp, CSEM_REG_VFPF_ERR_NUM, BNX2X_MAX_NUM_OF_VFS + func);
+ REG_WR(bp, XSEM_REG_VFPF_ERR_NUM, BNX2X_MAX_NUM_OF_VFS + func);
+ }
+ bnx2x_init_block(bp, BLOCK_QM, init_phase);
- if (CHIP_MODE_IS_4_PORT(bp))
- bnx2x_init_block(bp, QM_4PORT_BLOCK, FUNC0_STAGE + func);
-
- bnx2x_init_block(bp, TIMERS_BLOCK, FUNC0_STAGE + func);
- bnx2x_init_block(bp, DQ_BLOCK, FUNC0_STAGE + func);
- bnx2x_init_block(bp, BRB1_BLOCK, FUNC0_STAGE + func);
- bnx2x_init_block(bp, PRS_BLOCK, FUNC0_STAGE + func);
- bnx2x_init_block(bp, TSDM_BLOCK, FUNC0_STAGE + func);
- bnx2x_init_block(bp, CSDM_BLOCK, FUNC0_STAGE + func);
- bnx2x_init_block(bp, USDM_BLOCK, FUNC0_STAGE + func);
- bnx2x_init_block(bp, XSDM_BLOCK, FUNC0_STAGE + func);
- bnx2x_init_block(bp, UPB_BLOCK, FUNC0_STAGE + func);
- bnx2x_init_block(bp, XPB_BLOCK, FUNC0_STAGE + func);
- bnx2x_init_block(bp, PBF_BLOCK, FUNC0_STAGE + func);
- if (CHIP_IS_E2(bp))
+ bnx2x_init_block(bp, BLOCK_TM, init_phase);
+ bnx2x_init_block(bp, BLOCK_DORQ, init_phase);
+ bnx2x_init_block(bp, BLOCK_BRB1, init_phase);
+ bnx2x_init_block(bp, BLOCK_PRS, init_phase);
+ bnx2x_init_block(bp, BLOCK_TSDM, init_phase);
+ bnx2x_init_block(bp, BLOCK_CSDM, init_phase);
+ bnx2x_init_block(bp, BLOCK_USDM, init_phase);
+ bnx2x_init_block(bp, BLOCK_XSDM, init_phase);
+ bnx2x_init_block(bp, BLOCK_UPB, init_phase);
+ bnx2x_init_block(bp, BLOCK_XPB, init_phase);
+ bnx2x_init_block(bp, BLOCK_PBF, init_phase);
+ if (!CHIP_IS_E1x(bp))
REG_WR(bp, PBF_REG_DISABLE_PF, 0);
- bnx2x_init_block(bp, CDU_BLOCK, FUNC0_STAGE + func);
+ bnx2x_init_block(bp, BLOCK_CDU, init_phase);
- bnx2x_init_block(bp, CFC_BLOCK, FUNC0_STAGE + func);
+ bnx2x_init_block(bp, BLOCK_CFC, init_phase);
- if (CHIP_IS_E2(bp))
+ if (!CHIP_IS_E1x(bp))
REG_WR(bp, CFC_REG_WEAK_ENABLE_PF, 1);
if (IS_MF(bp)) {
@@ -5708,7 +6437,7 @@
REG_WR(bp, NIG_REG_LLH0_FUNC_VLAN_ID + port*8, bp->mf_ov);
}
- bnx2x_init_block(bp, MISC_AEU_BLOCK, FUNC0_STAGE + func);
+ bnx2x_init_block(bp, BLOCK_MISC_AEU, init_phase);
/* HC init per function */
if (bp->common.int_block == INT_BLOCK_HC) {
@@ -5718,21 +6447,21 @@
REG_WR(bp, HC_REG_LEADING_EDGE_0 + port*8, 0);
REG_WR(bp, HC_REG_TRAILING_EDGE_0 + port*8, 0);
}
- bnx2x_init_block(bp, HC_BLOCK, FUNC0_STAGE + func);
+ bnx2x_init_block(bp, BLOCK_HC, init_phase);
} else {
int num_segs, sb_idx, prod_offset;
REG_WR(bp, MISC_REG_AEU_GENERAL_ATTN_12 + func*4, 0);
- if (CHIP_IS_E2(bp)) {
+ if (!CHIP_IS_E1x(bp)) {
REG_WR(bp, IGU_REG_LEADING_EDGE_LATCH, 0);
REG_WR(bp, IGU_REG_TRAILING_EDGE_LATCH, 0);
}
- bnx2x_init_block(bp, IGU_BLOCK, FUNC0_STAGE + func);
+ bnx2x_init_block(bp, BLOCK_IGU, init_phase);
- if (CHIP_IS_E2(bp)) {
+ if (!CHIP_IS_E1x(bp)) {
int dsb_idx = 0;
/**
* Producer memory:
@@ -5827,13 +6556,6 @@
REG_WR(bp, 0x2114, 0xffffffff);
REG_WR(bp, 0x2120, 0xffffffff);
- bnx2x_init_block(bp, EMAC0_BLOCK, FUNC0_STAGE + func);
- bnx2x_init_block(bp, EMAC1_BLOCK, FUNC0_STAGE + func);
- bnx2x_init_block(bp, DBU_BLOCK, FUNC0_STAGE + func);
- bnx2x_init_block(bp, DBG_BLOCK, FUNC0_STAGE + func);
- bnx2x_init_block(bp, MCP_BLOCK, FUNC0_STAGE + func);
- bnx2x_init_block(bp, DMAE_BLOCK, FUNC0_STAGE + func);
-
if (CHIP_IS_E1x(bp)) {
main_mem_size = HC_REG_MAIN_MEMORY_SIZE / 2; /*dwords*/
main_mem_base = HC_REG_MAIN_MEMORY +
@@ -5859,65 +6581,26 @@
REG_RD(bp, main_mem_prty_clr);
}
+#ifdef BNX2X_STOP_ON_ERROR
+ /* Enable STORMs SP logging */
+ REG_WR8(bp, BAR_USTRORM_INTMEM +
+ USTORM_RECORD_SLOW_PATH_OFFSET(BP_FUNC(bp)), 1);
+ REG_WR8(bp, BAR_TSTRORM_INTMEM +
+ TSTORM_RECORD_SLOW_PATH_OFFSET(BP_FUNC(bp)), 1);
+ REG_WR8(bp, BAR_CSTRORM_INTMEM +
+ CSTORM_RECORD_SLOW_PATH_OFFSET(BP_FUNC(bp)), 1);
+ REG_WR8(bp, BAR_XSTRORM_INTMEM +
+ XSTORM_RECORD_SLOW_PATH_OFFSET(BP_FUNC(bp)), 1);
+#endif
+
bnx2x_phy_probe(&bp->link_params);
return 0;
}
-int bnx2x_init_hw(struct bnx2x *bp, u32 load_code)
-{
- int rc = 0;
-
- DP(BNX2X_MSG_MCP, "function %d load_code %x\n",
- BP_ABS_FUNC(bp), load_code);
-
- bp->dmae_ready = 0;
- spin_lock_init(&bp->dmae_lock);
-
- switch (load_code) {
- case FW_MSG_CODE_DRV_LOAD_COMMON:
- case FW_MSG_CODE_DRV_LOAD_COMMON_CHIP:
- rc = bnx2x_init_hw_common(bp, load_code);
- if (rc)
- goto init_hw_err;
- /* no break */
-
- case FW_MSG_CODE_DRV_LOAD_PORT:
- rc = bnx2x_init_hw_port(bp);
- if (rc)
- goto init_hw_err;
- /* no break */
-
- case FW_MSG_CODE_DRV_LOAD_FUNCTION:
- rc = bnx2x_init_hw_func(bp);
- if (rc)
- goto init_hw_err;
- break;
-
- default:
- BNX2X_ERR("Unknown load_code (0x%x) from MCP\n", load_code);
- break;
- }
-
- if (!BP_NOMCP(bp)) {
- int mb_idx = BP_FW_MB_IDX(bp);
-
- bp->fw_drv_pulse_wr_seq =
- (SHMEM_RD(bp, func_mb[mb_idx].drv_pulse_mb) &
- DRV_PULSE_SEQ_MASK);
- DP(BNX2X_MSG_MCP, "drv_pulse 0x%x\n", bp->fw_drv_pulse_wr_seq);
- }
-
-init_hw_err:
- bnx2x_gunzip_end(bp);
-
- return rc;
-}
void bnx2x_free_mem(struct bnx2x *bp)
{
- bnx2x_gunzip_end(bp);
-
/* fastpath */
bnx2x_free_fp_mem(bp);
/* end of fastpath */
@@ -5925,6 +6608,9 @@
BNX2X_PCI_FREE(bp->def_status_blk, bp->def_status_blk_mapping,
sizeof(struct host_sp_status_block));
+ BNX2X_PCI_FREE(bp->fw_stats, bp->fw_stats_mapping,
+ bp->fw_stats_data_sz + bp->fw_stats_req_sz);
+
BNX2X_PCI_FREE(bp->slowpath, bp->slowpath_mapping,
sizeof(struct bnx2x_slowpath));
@@ -5936,7 +6622,7 @@
BNX2X_FREE(bp->ilt->lines);
#ifdef BCM_CNIC
- if (CHIP_IS_E2(bp))
+ if (!CHIP_IS_E1x(bp))
BNX2X_PCI_FREE(bp->cnic_sb.e2_sb, bp->cnic_sb_mapping,
sizeof(struct host_hc_status_block_e2));
else
@@ -5950,18 +6636,67 @@
BNX2X_PCI_FREE(bp->eq_ring, bp->eq_mapping,
BCM_PAGE_SIZE * NUM_EQ_PAGES);
+}
- BNX2X_FREE(bp->rx_indir_table);
+static inline int bnx2x_alloc_fw_stats_mem(struct bnx2x *bp)
+{
+ int num_groups;
+
+ /* number of eth_queues */
+ u8 num_queue_stats = BNX2X_NUM_ETH_QUEUES(bp);
+
+ /* Total number of FW statistics requests =
+ * 1 for port stats + 1 for PF stats + num_eth_queues */
+ bp->fw_stats_num = 2 + num_queue_stats;
+
+
+ /* Request is built from stats_query_header and an array of
+ * stats_query_cmd_group each of which contains
+ * STATS_QUERY_CMD_COUNT rules. The real number or requests is
+ * configured in the stats_query_header.
+ */
+ num_groups = (2 + num_queue_stats) / STATS_QUERY_CMD_COUNT +
+ (((2 + num_queue_stats) % STATS_QUERY_CMD_COUNT) ? 1 : 0);
+
+ bp->fw_stats_req_sz = sizeof(struct stats_query_header) +
+ num_groups * sizeof(struct stats_query_cmd_group);
+
+ /* Data for statistics requests + stats_conter
+ *
+ * stats_counter holds per-STORM counters that are incremented
+ * when STORM has finished with the current request.
+ */
+ bp->fw_stats_data_sz = sizeof(struct per_port_stats) +
+ sizeof(struct per_pf_stats) +
+ sizeof(struct per_queue_stats) * num_queue_stats +
+ sizeof(struct stats_counter);
+
+ BNX2X_PCI_ALLOC(bp->fw_stats, &bp->fw_stats_mapping,
+ bp->fw_stats_data_sz + bp->fw_stats_req_sz);
+
+ /* Set shortcuts */
+ bp->fw_stats_req = (struct bnx2x_fw_stats_req *)bp->fw_stats;
+ bp->fw_stats_req_mapping = bp->fw_stats_mapping;
+
+ bp->fw_stats_data = (struct bnx2x_fw_stats_data *)
+ ((u8 *)bp->fw_stats + bp->fw_stats_req_sz);
+
+ bp->fw_stats_data_mapping = bp->fw_stats_mapping +
+ bp->fw_stats_req_sz;
+ return 0;
+
+alloc_mem_err:
+ BNX2X_PCI_FREE(bp->fw_stats, bp->fw_stats_mapping,
+ bp->fw_stats_data_sz + bp->fw_stats_req_sz);
+ return -ENOMEM;
}
int bnx2x_alloc_mem(struct bnx2x *bp)
{
- if (bnx2x_gunzip_init(bp))
- return -ENOMEM;
-
#ifdef BCM_CNIC
- if (CHIP_IS_E2(bp))
+ if (!CHIP_IS_E1x(bp))
+ /* size = the status block + ramrod buffers */
BNX2X_PCI_ALLOC(bp->cnic_sb.e2_sb, &bp->cnic_sb_mapping,
sizeof(struct host_hc_status_block_e2));
else
@@ -5979,6 +6714,10 @@
BNX2X_PCI_ALLOC(bp->slowpath, &bp->slowpath_mapping,
sizeof(struct bnx2x_slowpath));
+ /* Allocated memory for FW statistics */
+ if (bnx2x_alloc_fw_stats_mem(bp))
+ goto alloc_mem_err;
+
bp->context.size = sizeof(union cdu_context) * bp->l2_cid_count;
BNX2X_PCI_ALLOC(bp->context.vcxt, &bp->context.cxt_mapping,
@@ -5996,8 +6735,6 @@
BNX2X_PCI_ALLOC(bp->eq_ring, &bp->eq_mapping,
BCM_PAGE_SIZE * NUM_EQ_PAGES);
- BNX2X_ALLOC(bp->rx_indir_table, sizeof(bp->rx_indir_table[0]) *
- TSTORM_INDIRECTION_TABLE_SIZE);
/* fastpath */
/* need to be done at the end, since it's self adjusting to amount
@@ -6015,631 +6752,77 @@
/*
* Init service functions
*/
-static int bnx2x_wait_ramrod(struct bnx2x *bp, int state, int idx,
- int *state_p, int flags);
-int bnx2x_func_start(struct bnx2x *bp)
+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)
{
- bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_FUNCTION_START, 0, 0, 0, 1);
+ int rc;
+ struct bnx2x_vlan_mac_ramrod_params ramrod_param;
- /* Wait for completion */
- return bnx2x_wait_ramrod(bp, BNX2X_STATE_FUNC_STARTED, 0, &(bp->state),
- WAIT_RAMROD_COMMON);
-}
+ memset(&ramrod_param, 0, sizeof(ramrod_param));
-static int bnx2x_func_stop(struct bnx2x *bp)
-{
- bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_FUNCTION_STOP, 0, 0, 0, 1);
+ /* Fill general parameters */
+ ramrod_param.vlan_mac_obj = obj;
+ ramrod_param.ramrod_flags = *ramrod_flags;
- /* Wait for completion */
- return bnx2x_wait_ramrod(bp, BNX2X_STATE_CLOSING_WAIT4_UNLOAD,
- 0, &(bp->state), WAIT_RAMROD_COMMON);
-}
+ /* Fill a user request section if needed */
+ if (!test_bit(RAMROD_CONT, ramrod_flags)) {
+ memcpy(ramrod_param.user_req.u.mac.mac, mac, ETH_ALEN);
-/**
- * bnx2x_set_mac_addr_gen - set a MAC in a CAM for a few L2 Clients for E1x chips
- *
- * @bp: driver handle
- * @set: set or clear an entry (1 or 0)
- * @mac: pointer to a buffer containing a MAC
- * @cl_bit_vec: bit vector of clients to register a MAC for
- * @cam_offset: offset in a CAM to use
- * @is_bcast: is the set MAC a broadcast address (for E1 only)
- */
-static void bnx2x_set_mac_addr_gen(struct bnx2x *bp, int set, const u8 *mac,
- u32 cl_bit_vec, u8 cam_offset,
- u8 is_bcast)
-{
- struct mac_configuration_cmd *config =
- (struct mac_configuration_cmd *)bnx2x_sp(bp, mac_config);
- int ramrod_flags = WAIT_RAMROD_COMMON;
+ __set_bit(mac_type, &ramrod_param.user_req.vlan_mac_flags);
- bp->set_mac_pending = 1;
-
- config->hdr.length = 1;
- config->hdr.offset = cam_offset;
- config->hdr.client_id = 0xff;
- /* Mark the single MAC configuration ramrod as opposed to a
- * UC/MC list configuration).
- */
- config->hdr.echo = 1;
-
- /* primary MAC */
- config->config_table[0].msb_mac_addr =
- swab16(*(u16 *)&mac[0]);
- config->config_table[0].middle_mac_addr =
- swab16(*(u16 *)&mac[2]);
- config->config_table[0].lsb_mac_addr =
- swab16(*(u16 *)&mac[4]);
- config->config_table[0].clients_bit_vector =
- cpu_to_le32(cl_bit_vec);
- config->config_table[0].vlan_id = 0;
- config->config_table[0].pf_id = BP_FUNC(bp);
- if (set)
- SET_FLAG(config->config_table[0].flags,
- MAC_CONFIGURATION_ENTRY_ACTION_TYPE,
- T_ETH_MAC_COMMAND_SET);
- else
- SET_FLAG(config->config_table[0].flags,
- MAC_CONFIGURATION_ENTRY_ACTION_TYPE,
- T_ETH_MAC_COMMAND_INVALIDATE);
-
- if (is_bcast)
- SET_FLAG(config->config_table[0].flags,
- MAC_CONFIGURATION_ENTRY_BROADCAST, 1);
-
- DP(NETIF_MSG_IFUP, "%s MAC (%04x:%04x:%04x) PF_ID %d CLID mask %d\n",
- (set ? "setting" : "clearing"),
- config->config_table[0].msb_mac_addr,
- config->config_table[0].middle_mac_addr,
- config->config_table[0].lsb_mac_addr, BP_FUNC(bp), cl_bit_vec);
-
- mb();
-
- bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_SET_MAC, 0,
- U64_HI(bnx2x_sp_mapping(bp, mac_config)),
- U64_LO(bnx2x_sp_mapping(bp, mac_config)), 1);
-
- /* Wait for a completion */
- bnx2x_wait_ramrod(bp, 0, 0, &bp->set_mac_pending, ramrod_flags);
-}
-
-static int bnx2x_wait_ramrod(struct bnx2x *bp, int state, int idx,
- int *state_p, int flags)
-{
- /* can take a while if any port is running */
- int cnt = 5000;
- u8 poll = flags & WAIT_RAMROD_POLL;
- u8 common = flags & WAIT_RAMROD_COMMON;
-
- DP(NETIF_MSG_IFUP, "%s for state to become %x on IDX [%d]\n",
- poll ? "polling" : "waiting", state, idx);
-
- might_sleep();
- while (cnt--) {
- if (poll) {
- if (common)
- bnx2x_eq_int(bp);
- else {
- bnx2x_rx_int(bp->fp, 10);
- /* if index is different from 0
- * the reply for some commands will
- * be on the non default queue
- */
- if (idx)
- bnx2x_rx_int(&bp->fp[idx], 10);
- }
- }
-
- mb(); /* state is changed by bnx2x_sp_event() */
- if (*state_p == state) {
-#ifdef BNX2X_STOP_ON_ERROR
- DP(NETIF_MSG_IFUP, "exit (cnt %d)\n", 5000 - cnt);
-#endif
- return 0;
- }
-
- msleep(1);
-
- if (bp->panic)
- return -EIO;
+ /* Set the command: ADD or DEL */
+ if (set)
+ ramrod_param.user_req.cmd = BNX2X_VLAN_MAC_ADD;
+ else
+ ramrod_param.user_req.cmd = BNX2X_VLAN_MAC_DEL;
}
- /* timeout! */
- BNX2X_ERR("timeout %s for state %x on IDX [%d]\n",
- poll ? "polling" : "waiting", state, idx);
-#ifdef BNX2X_STOP_ON_ERROR
- bnx2x_panic();
-#endif
-
- return -EBUSY;
-}
-
-static u8 bnx2x_e1h_cam_offset(struct bnx2x *bp, u8 rel_offset)
-{
- if (CHIP_IS_E1H(bp))
- return E1H_FUNC_MAX * rel_offset + BP_FUNC(bp);
- else if (CHIP_MODE_IS_4_PORT(bp))
- return E2_FUNC_MAX * rel_offset + BP_FUNC(bp);
- else
- return E2_FUNC_MAX * rel_offset + BP_VN(bp);
-}
-
-/**
- * LLH CAM line allocations: currently only iSCSI and ETH macs are
- * relevant. In addition, current implementation is tuned for a
- * single ETH MAC.
- */
-enum {
- LLH_CAM_ISCSI_ETH_LINE = 0,
- LLH_CAM_ETH_LINE,
- LLH_CAM_MAX_PF_LINE = NIG_REG_LLH1_FUNC_MEM_SIZE
-};
-
-static void bnx2x_set_mac_in_nig(struct bnx2x *bp,
- int set,
- unsigned char *dev_addr,
- int index)
-{
- u32 wb_data[2];
- u32 mem_offset, ena_offset, mem_index;
- /**
- * indexes mapping:
- * 0..7 - goes to MEM
- * 8..15 - goes to MEM2
- */
-
- if (!IS_MF_SI(bp) || index > LLH_CAM_MAX_PF_LINE)
- return;
-
- /* calculate memory start offset according to the mapping
- * and index in the memory */
- if (index < NIG_LLH_FUNC_MEM_MAX_OFFSET) {
- mem_offset = BP_PORT(bp) ? NIG_REG_LLH1_FUNC_MEM :
- NIG_REG_LLH0_FUNC_MEM;
- ena_offset = BP_PORT(bp) ? NIG_REG_LLH1_FUNC_MEM_ENABLE :
- NIG_REG_LLH0_FUNC_MEM_ENABLE;
- mem_index = index;
- } else {
- mem_offset = BP_PORT(bp) ? NIG_REG_P1_LLH_FUNC_MEM2 :
- NIG_REG_P0_LLH_FUNC_MEM2;
- ena_offset = BP_PORT(bp) ? NIG_REG_P1_LLH_FUNC_MEM2_ENABLE :
- NIG_REG_P0_LLH_FUNC_MEM2_ENABLE;
- mem_index = index - NIG_LLH_FUNC_MEM_MAX_OFFSET;
- }
-
- if (set) {
- /* LLH_FUNC_MEM is a u64 WB register */
- mem_offset += 8*mem_index;
-
- wb_data[0] = ((dev_addr[2] << 24) | (dev_addr[3] << 16) |
- (dev_addr[4] << 8) | dev_addr[5]);
- wb_data[1] = ((dev_addr[0] << 8) | dev_addr[1]);
-
- REG_WR_DMAE(bp, mem_offset, wb_data, 2);
- }
-
- /* enable/disable the entry */
- REG_WR(bp, ena_offset + 4*mem_index, set);
-
-}
-
-void bnx2x_set_eth_mac(struct bnx2x *bp, int set)
-{
- u8 cam_offset = (CHIP_IS_E1(bp) ? (BP_PORT(bp) ? 32 : 0) :
- bnx2x_e1h_cam_offset(bp, CAM_ETH_LINE));
-
- /* networking MAC */
- bnx2x_set_mac_addr_gen(bp, set, bp->dev->dev_addr,
- (1 << bp->fp->cl_id), cam_offset , 0);
-
- bnx2x_set_mac_in_nig(bp, set, bp->dev->dev_addr, LLH_CAM_ETH_LINE);
-
- if (CHIP_IS_E1(bp)) {
- /* broadcast MAC */
- static const u8 bcast[ETH_ALEN] = {
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
- };
- bnx2x_set_mac_addr_gen(bp, set, bcast, 0, cam_offset + 1, 1);
- }
-}
-
-static inline u8 bnx2x_e1_cam_mc_offset(struct bnx2x *bp)
-{
- return CHIP_REV_IS_SLOW(bp) ?
- (BNX2X_MAX_EMUL_MULTI * (1 + BP_PORT(bp))) :
- (BNX2X_MAX_MULTICAST * (1 + BP_PORT(bp)));
-}
-
-/* set mc list, do not wait as wait implies sleep and
- * set_rx_mode can be invoked from non-sleepable context.
- *
- * Instead we use the same ramrod data buffer each time we need
- * to configure a list of addresses, and use the fact that the
- * list of MACs is changed in an incremental way and that the
- * function is called under the netif_addr_lock. A temporary
- * inconsistent CAM configuration (possible in case of a very fast
- * sequence of add/del/add on the host side) will shortly be
- * restored by the handler of the last ramrod.
- */
-static int bnx2x_set_e1_mc_list(struct bnx2x *bp)
-{
- int i = 0, old;
- struct net_device *dev = bp->dev;
- u8 offset = bnx2x_e1_cam_mc_offset(bp);
- struct netdev_hw_addr *ha;
- struct mac_configuration_cmd *config_cmd = bnx2x_sp(bp, mcast_config);
- dma_addr_t config_cmd_map = bnx2x_sp_mapping(bp, mcast_config);
-
- if (netdev_mc_count(dev) > BNX2X_MAX_MULTICAST)
- return -EINVAL;
-
- netdev_for_each_mc_addr(ha, dev) {
- /* copy mac */
- config_cmd->config_table[i].msb_mac_addr =
- swab16(*(u16 *)&bnx2x_mc_addr(ha)[0]);
- config_cmd->config_table[i].middle_mac_addr =
- swab16(*(u16 *)&bnx2x_mc_addr(ha)[2]);
- config_cmd->config_table[i].lsb_mac_addr =
- swab16(*(u16 *)&bnx2x_mc_addr(ha)[4]);
-
- config_cmd->config_table[i].vlan_id = 0;
- config_cmd->config_table[i].pf_id = BP_FUNC(bp);
- config_cmd->config_table[i].clients_bit_vector =
- cpu_to_le32(1 << BP_L_ID(bp));
-
- SET_FLAG(config_cmd->config_table[i].flags,
- MAC_CONFIGURATION_ENTRY_ACTION_TYPE,
- T_ETH_MAC_COMMAND_SET);
-
- DP(NETIF_MSG_IFUP,
- "setting MCAST[%d] (%04x:%04x:%04x)\n", i,
- config_cmd->config_table[i].msb_mac_addr,
- config_cmd->config_table[i].middle_mac_addr,
- config_cmd->config_table[i].lsb_mac_addr);
- i++;
- }
- old = config_cmd->hdr.length;
- if (old > i) {
- for (; i < old; i++) {
- if (CAM_IS_INVALID(config_cmd->
- config_table[i])) {
- /* already invalidated */
- break;
- }
- /* invalidate */
- SET_FLAG(config_cmd->config_table[i].flags,
- MAC_CONFIGURATION_ENTRY_ACTION_TYPE,
- T_ETH_MAC_COMMAND_INVALIDATE);
- }
- }
-
- wmb();
-
- config_cmd->hdr.length = i;
- config_cmd->hdr.offset = offset;
- config_cmd->hdr.client_id = 0xff;
- /* Mark that this ramrod doesn't use bp->set_mac_pending for
- * synchronization.
- */
- config_cmd->hdr.echo = 0;
-
- mb();
-
- return bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_SET_MAC, 0,
- U64_HI(config_cmd_map), U64_LO(config_cmd_map), 1);
-}
-
-void bnx2x_invalidate_e1_mc_list(struct bnx2x *bp)
-{
- int i;
- struct mac_configuration_cmd *config_cmd = bnx2x_sp(bp, mcast_config);
- dma_addr_t config_cmd_map = bnx2x_sp_mapping(bp, mcast_config);
- int ramrod_flags = WAIT_RAMROD_COMMON;
- u8 offset = bnx2x_e1_cam_mc_offset(bp);
-
- for (i = 0; i < BNX2X_MAX_MULTICAST; i++)
- SET_FLAG(config_cmd->config_table[i].flags,
- MAC_CONFIGURATION_ENTRY_ACTION_TYPE,
- T_ETH_MAC_COMMAND_INVALIDATE);
-
- wmb();
-
- config_cmd->hdr.length = BNX2X_MAX_MULTICAST;
- config_cmd->hdr.offset = offset;
- config_cmd->hdr.client_id = 0xff;
- /* We'll wait for a completion this time... */
- config_cmd->hdr.echo = 1;
-
- bp->set_mac_pending = 1;
-
- mb();
-
- bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_SET_MAC, 0,
- U64_HI(config_cmd_map), U64_LO(config_cmd_map), 1);
-
- /* Wait for a completion */
- bnx2x_wait_ramrod(bp, 0, 0, &bp->set_mac_pending,
- ramrod_flags);
-
-}
-
-/* Accept one or more multicasts */
-static int bnx2x_set_e1h_mc_list(struct bnx2x *bp)
-{
- struct net_device *dev = bp->dev;
- struct netdev_hw_addr *ha;
- u32 mc_filter[MC_HASH_SIZE];
- u32 crc, bit, regidx;
- int i;
-
- memset(mc_filter, 0, 4 * MC_HASH_SIZE);
-
- netdev_for_each_mc_addr(ha, dev) {
- DP(NETIF_MSG_IFUP, "Adding mcast MAC: %pM\n",
- bnx2x_mc_addr(ha));
-
- crc = crc32c_le(0, bnx2x_mc_addr(ha),
- ETH_ALEN);
- bit = (crc >> 24) & 0xff;
- regidx = bit >> 5;
- bit &= 0x1f;
- mc_filter[regidx] |= (1 << bit);
- }
-
- for (i = 0; i < MC_HASH_SIZE; i++)
- REG_WR(bp, MC_HASH_OFFSET(bp, i),
- mc_filter[i]);
-
- return 0;
-}
-
-void bnx2x_invalidate_e1h_mc_list(struct bnx2x *bp)
-{
- int i;
-
- for (i = 0; i < MC_HASH_SIZE; i++)
- REG_WR(bp, MC_HASH_OFFSET(bp, i), 0);
-}
-
-#ifdef BCM_CNIC
-/**
- * bnx2x_set_iscsi_eth_mac_addr - set iSCSI MAC(s).
- *
- * @bp: driver handle
- * @set: set or clear the CAM entry
- *
- * This function will wait until the ramdord completion returns.
- * Return 0 if success, -ENODEV if ramrod doesn't return.
- */
-static int bnx2x_set_iscsi_eth_mac_addr(struct bnx2x *bp, int set)
-{
- u8 cam_offset = (CHIP_IS_E1(bp) ? ((BP_PORT(bp) ? 32 : 0) + 2) :
- bnx2x_e1h_cam_offset(bp, CAM_ISCSI_ETH_LINE));
- u32 iscsi_l2_cl_id = BNX2X_ISCSI_ETH_CL_ID +
- BP_E1HVN(bp) * NONE_ETH_CONTEXT_USE;
- u32 cl_bit_vec = (1 << iscsi_l2_cl_id);
- u8 *iscsi_mac = bp->cnic_eth_dev.iscsi_mac;
-
- /* Send a SET_MAC ramrod */
- bnx2x_set_mac_addr_gen(bp, set, iscsi_mac, cl_bit_vec,
- cam_offset, 0);
-
- bnx2x_set_mac_in_nig(bp, set, iscsi_mac, LLH_CAM_ISCSI_ETH_LINE);
-
- return 0;
-}
-
-/**
- * bnx2x_set_fip_eth_mac_addr - set FCoE L2 MAC(s)
- *
- * @bp: driver handle
- * @set: set or clear the CAM entry
- *
- * This function will wait until the ramrod completion returns.
- * Returns 0 if success, -ENODEV if ramrod doesn't return.
- */
-int bnx2x_set_fip_eth_mac_addr(struct bnx2x *bp, int set)
-{
- u32 cl_bit_vec = (1 << bnx2x_fcoe(bp, cl_id));
- /**
- * CAM allocation for E1H
- * eth unicasts: by func number
- * iscsi: by func number
- * fip unicast: by func number
- * fip multicast: by func number
- */
- bnx2x_set_mac_addr_gen(bp, set, bp->fip_mac,
- cl_bit_vec, bnx2x_e1h_cam_offset(bp, CAM_FIP_ETH_LINE), 0);
-
- return 0;
-}
-
-int bnx2x_set_all_enode_macs(struct bnx2x *bp, int set)
-{
- u32 cl_bit_vec = (1 << bnx2x_fcoe(bp, cl_id));
-
- /**
- * CAM allocation for E1H
- * eth unicasts: by func number
- * iscsi: by func number
- * fip unicast: by func number
- * fip multicast: by func number
- */
- bnx2x_set_mac_addr_gen(bp, set, ALL_ENODE_MACS, cl_bit_vec,
- bnx2x_e1h_cam_offset(bp, CAM_FIP_MCAST_LINE), 0);
-
- return 0;
-}
-#endif
-
-static void bnx2x_fill_cl_init_data(struct bnx2x *bp,
- struct bnx2x_client_init_params *params,
- u8 activate,
- struct client_init_ramrod_data *data)
-{
- /* Clear the buffer */
- memset(data, 0, sizeof(*data));
-
- /* general */
- data->general.client_id = params->rxq_params.cl_id;
- data->general.statistics_counter_id = params->rxq_params.stat_id;
- data->general.statistics_en_flg =
- (params->rxq_params.flags & QUEUE_FLG_STATS) ? 1 : 0;
- data->general.is_fcoe_flg =
- (params->ramrod_params.flags & CLIENT_IS_FCOE) ? 1 : 0;
- data->general.activate_flg = activate;
- data->general.sp_client_id = params->rxq_params.spcl_id;
-
- /* Rx data */
- data->rx.tpa_en_flg =
- (params->rxq_params.flags & QUEUE_FLG_TPA) ? 1 : 0;
- data->rx.vmqueue_mode_en_flg = 0;
- data->rx.cache_line_alignment_log_size =
- params->rxq_params.cache_line_log;
- data->rx.enable_dynamic_hc =
- (params->rxq_params.flags & QUEUE_FLG_DHC) ? 1 : 0;
- data->rx.max_sges_for_packet = params->rxq_params.max_sges_pkt;
- data->rx.client_qzone_id = params->rxq_params.cl_qzone_id;
- data->rx.max_agg_size = params->rxq_params.tpa_agg_sz;
-
- /* We don't set drop flags */
- data->rx.drop_ip_cs_err_flg = 0;
- data->rx.drop_tcp_cs_err_flg = 0;
- data->rx.drop_ttl0_flg = 0;
- data->rx.drop_udp_cs_err_flg = 0;
-
- data->rx.inner_vlan_removal_enable_flg =
- (params->rxq_params.flags & QUEUE_FLG_VLAN) ? 1 : 0;
- data->rx.outer_vlan_removal_enable_flg =
- (params->rxq_params.flags & QUEUE_FLG_OV) ? 1 : 0;
- data->rx.status_block_id = params->rxq_params.fw_sb_id;
- data->rx.rx_sb_index_number = params->rxq_params.sb_cq_index;
- data->rx.bd_buff_size = cpu_to_le16(params->rxq_params.buf_sz);
- data->rx.sge_buff_size = cpu_to_le16(params->rxq_params.sge_buf_sz);
- data->rx.mtu = cpu_to_le16(params->rxq_params.mtu);
- data->rx.bd_page_base.lo =
- cpu_to_le32(U64_LO(params->rxq_params.dscr_map));
- data->rx.bd_page_base.hi =
- cpu_to_le32(U64_HI(params->rxq_params.dscr_map));
- data->rx.sge_page_base.lo =
- cpu_to_le32(U64_LO(params->rxq_params.sge_map));
- data->rx.sge_page_base.hi =
- cpu_to_le32(U64_HI(params->rxq_params.sge_map));
- data->rx.cqe_page_base.lo =
- cpu_to_le32(U64_LO(params->rxq_params.rcq_map));
- data->rx.cqe_page_base.hi =
- cpu_to_le32(U64_HI(params->rxq_params.rcq_map));
- data->rx.is_leading_rss =
- (params->ramrod_params.flags & CLIENT_IS_LEADING_RSS) ? 1 : 0;
- data->rx.is_approx_mcast = data->rx.is_leading_rss;
-
- /* Tx data */
- data->tx.enforce_security_flg = 0; /* VF specific */
- data->tx.tx_status_block_id = params->txq_params.fw_sb_id;
- data->tx.tx_sb_index_number = params->txq_params.sb_cq_index;
- data->tx.mtu = 0; /* VF specific */
- data->tx.tx_bd_page_base.lo =
- cpu_to_le32(U64_LO(params->txq_params.dscr_map));
- data->tx.tx_bd_page_base.hi =
- cpu_to_le32(U64_HI(params->txq_params.dscr_map));
-
- /* flow control data */
- data->fc.cqe_pause_thr_low = cpu_to_le16(params->pause.rcq_th_lo);
- data->fc.cqe_pause_thr_high = cpu_to_le16(params->pause.rcq_th_hi);
- data->fc.bd_pause_thr_low = cpu_to_le16(params->pause.bd_th_lo);
- data->fc.bd_pause_thr_high = cpu_to_le16(params->pause.bd_th_hi);
- data->fc.sge_pause_thr_low = cpu_to_le16(params->pause.sge_th_lo);
- data->fc.sge_pause_thr_high = cpu_to_le16(params->pause.sge_th_hi);
- data->fc.rx_cos_mask = cpu_to_le16(params->pause.pri_map);
-
- data->fc.safc_group_num = params->txq_params.cos;
- data->fc.safc_group_en_flg =
- (params->txq_params.flags & QUEUE_FLG_COS) ? 1 : 0;
- data->fc.traffic_type =
- (params->ramrod_params.flags & CLIENT_IS_FCOE) ?
- LLFC_TRAFFIC_TYPE_FCOE : LLFC_TRAFFIC_TYPE_NW;
-}
-
-static inline void bnx2x_set_ctx_validation(struct eth_context *cxt, u32 cid)
-{
- /* ustorm cxt validation */
- cxt->ustorm_ag_context.cdu_usage =
- CDU_RSRVD_VALUE_TYPE_A(cid, CDU_REGION_NUMBER_UCM_AG,
- ETH_CONNECTION_TYPE);
- /* xcontext validation */
- cxt->xstorm_ag_context.cdu_reserved =
- CDU_RSRVD_VALUE_TYPE_A(cid, CDU_REGION_NUMBER_XCM_AG,
- ETH_CONNECTION_TYPE);
-}
-
-static int bnx2x_setup_fw_client(struct bnx2x *bp,
- struct bnx2x_client_init_params *params,
- u8 activate,
- struct client_init_ramrod_data *data,
- dma_addr_t data_mapping)
-{
- u16 hc_usec;
- int ramrod = RAMROD_CMD_ID_ETH_CLIENT_SETUP;
- int ramrod_flags = 0, rc;
-
- /* HC and context validation values */
- hc_usec = params->txq_params.hc_rate ?
- 1000000 / params->txq_params.hc_rate : 0;
- bnx2x_update_coalesce_sb_index(bp,
- params->txq_params.fw_sb_id,
- params->txq_params.sb_cq_index,
- !(params->txq_params.flags & QUEUE_FLG_HC),
- hc_usec);
-
- *(params->ramrod_params.pstate) = BNX2X_FP_STATE_OPENING;
-
- hc_usec = params->rxq_params.hc_rate ?
- 1000000 / params->rxq_params.hc_rate : 0;
- bnx2x_update_coalesce_sb_index(bp,
- params->rxq_params.fw_sb_id,
- params->rxq_params.sb_cq_index,
- !(params->rxq_params.flags & QUEUE_FLG_HC),
- hc_usec);
-
- bnx2x_set_ctx_validation(params->rxq_params.cxt,
- params->rxq_params.cid);
-
- /* zero stats */
- if (params->txq_params.flags & QUEUE_FLG_STATS)
- storm_memset_xstats_zero(bp, BP_PORT(bp),
- params->txq_params.stat_id);
-
- if (params->rxq_params.flags & QUEUE_FLG_STATS) {
- storm_memset_ustats_zero(bp, BP_PORT(bp),
- params->rxq_params.stat_id);
- storm_memset_tstats_zero(bp, BP_PORT(bp),
- params->rxq_params.stat_id);
- }
-
- /* Fill the ramrod data */
- bnx2x_fill_cl_init_data(bp, params, activate, data);
-
- /* SETUP ramrod.
- *
- * bnx2x_sp_post() takes a spin_lock thus no other explict memory
- * barrier except from mmiowb() is needed to impose a
- * proper ordering of memory operations.
- */
- mmiowb();
-
-
- bnx2x_sp_post(bp, ramrod, params->ramrod_params.cid,
- U64_HI(data_mapping), U64_LO(data_mapping), 0);
-
- /* Wait for completion */
- rc = bnx2x_wait_ramrod(bp, params->ramrod_params.state,
- params->ramrod_params.index,
- params->ramrod_params.pstate,
- ramrod_flags);
+ rc = bnx2x_config_vlan_mac(bp, &ramrod_param);
+ if (rc < 0)
+ BNX2X_ERR("%s MAC failed\n", (set ? "Set" : "Del"));
return rc;
}
+int bnx2x_del_all_macs(struct bnx2x *bp,
+ struct bnx2x_vlan_mac_obj *mac_obj,
+ int mac_type, bool wait_for_comp)
+{
+ int rc;
+ unsigned long ramrod_flags = 0, vlan_mac_flags = 0;
+
+ /* Wait for completion of requested */
+ if (wait_for_comp)
+ __set_bit(RAMROD_COMP_WAIT, &ramrod_flags);
+
+ /* Set the mac type of addresses we want to clear */
+ __set_bit(mac_type, &vlan_mac_flags);
+
+ rc = mac_obj->delete_all(bp, mac_obj, &vlan_mac_flags, &ramrod_flags);
+ if (rc < 0)
+ BNX2X_ERR("Failed to delete MACs: %d\n", rc);
+
+ return rc;
+}
+
+int bnx2x_set_eth_mac(struct bnx2x *bp, bool set)
+{
+ unsigned long ramrod_flags = 0;
+
+ DP(NETIF_MSG_IFUP, "Adding Eth MAC\n");
+
+ __set_bit(RAMROD_COMP_WAIT, &ramrod_flags);
+ /* Eth MAC is set on RSS leading client (fp[0]) */
+ return bnx2x_set_mac_one(bp, bp->dev->dev_addr, &bp->fp->mac_obj, set,
+ BNX2X_ETH_MAC, &ramrod_flags);
+}
+
+int bnx2x_setup_leading(struct bnx2x *bp)
+{
+ return bnx2x_setup_queue(bp, &bp->fp[0], 1);
+}
+
/**
* bnx2x_set_int_mode - configure interrupt mode
*
@@ -6647,11 +6830,9 @@
*
* In case of MSI-X it will also try to enable MSI-X.
*/
-static int __devinit bnx2x_set_int_mode(struct bnx2x *bp)
+static void __devinit bnx2x_set_int_mode(struct bnx2x *bp)
{
- int rc = 0;
-
- switch (bp->int_mode) {
+ switch (int_mode) {
case INT_MODE_MSI:
bnx2x_enable_msi(bp);
/* falling through... */
@@ -6670,8 +6851,7 @@
* so try to enable MSI-X with the requested number of fp's
* and fallback to MSI or legacy INTx with one fp
*/
- rc = bnx2x_enable_msix(bp);
- if (rc) {
+ if (bnx2x_enable_msix(bp)) {
/* failed to enable MSI-X */
if (bp->multi_mode)
DP(NETIF_MSG_IFUP,
@@ -6682,14 +6862,12 @@
1 + NONE_ETH_CONTEXT_USE);
bp->num_queues = 1 + NONE_ETH_CONTEXT_USE;
+ /* Try to enable MSI */
if (!(bp->flags & DISABLE_MSI_FLAG))
bnx2x_enable_msi(bp);
}
-
break;
}
-
- return rc;
}
/* must be called prioir to any HW initializations */
@@ -6713,7 +6891,7 @@
ilt_client->page_size = CDU_ILT_PAGE_SZ;
ilt_client->flags = ILT_CLIENT_SKIP_MEM;
ilt_client->start = line;
- line += L2_ILT_LINES(bp);
+ line += bnx2x_cid_ilt_lines(bp);
#ifdef BCM_CNIC
line += CNIC_ILT_LINES;
#endif
@@ -6793,12 +6971,72 @@
#else
ilt_client->flags = (ILT_CLIENT_SKIP_INIT | ILT_CLIENT_SKIP_MEM);
#endif
+ BUG_ON(line > ILT_MAX_LINES);
}
-int bnx2x_setup_client(struct bnx2x *bp, struct bnx2x_fastpath *fp,
- int is_leading)
+/**
+ * bnx2x_pf_q_prep_init - prepare INIT transition parameters
+ *
+ * @bp: driver handle
+ * @fp: pointer to fastpath
+ * @init_params: pointer to parameters structure
+ *
+ * parameters configured:
+ * - HC configuration
+ * - Queue's CDU context
+ */
+static inline void bnx2x_pf_q_prep_init(struct bnx2x *bp,
+ struct bnx2x_fastpath *fp, struct bnx2x_queue_init_params *init_params)
{
- struct bnx2x_client_init_params params = { {0} };
+ /* FCoE Queue uses Default SB, thus has no HC capabilities */
+ if (!IS_FCOE_FP(fp)) {
+ __set_bit(BNX2X_Q_FLG_HC, &init_params->rx.flags);
+ __set_bit(BNX2X_Q_FLG_HC, &init_params->tx.flags);
+
+ /* If HC is supporterd, enable host coalescing in the transition
+ * to INIT state.
+ */
+ __set_bit(BNX2X_Q_FLG_HC_EN, &init_params->rx.flags);
+ __set_bit(BNX2X_Q_FLG_HC_EN, &init_params->tx.flags);
+
+ /* HC rate */
+ init_params->rx.hc_rate = bp->rx_ticks ?
+ (1000000 / bp->rx_ticks) : 0;
+ init_params->tx.hc_rate = bp->tx_ticks ?
+ (1000000 / bp->tx_ticks) : 0;
+
+ /* FW SB ID */
+ init_params->rx.fw_sb_id = init_params->tx.fw_sb_id =
+ fp->fw_sb_id;
+
+ /*
+ * CQ index among the SB indices: FCoE clients uses the default
+ * SB, therefore it's different.
+ */
+ init_params->rx.sb_cq_index = U_SB_ETH_RX_CQ_INDEX;
+ init_params->tx.sb_cq_index = C_SB_ETH_TX_CQ_INDEX;
+ }
+
+ init_params->cxt = &bp->context.vcxt[fp->cid].eth;
+}
+
+/**
+ * bnx2x_setup_queue - setup queue
+ *
+ * @bp: driver handle
+ * @fp: pointer to fastpath
+ * @leading: is leading
+ *
+ * This function performs 2 steps in a Queue state machine
+ * actually: 1) RESET->INIT 2) INIT->SETUP
+ */
+
+int bnx2x_setup_queue(struct bnx2x *bp, struct bnx2x_fastpath *fp,
+ bool leading)
+{
+ struct bnx2x_queue_state_params q_params = {0};
+ struct bnx2x_queue_setup_params *setup_params =
+ &q_params.params.setup;
int rc;
/* reset IGU state skip FCoE L2 queue */
@@ -6806,79 +7044,73 @@
bnx2x_ack_sb(bp, fp->igu_sb_id, USTORM_ID, 0,
IGU_INT_ENABLE, 0);
- params.ramrod_params.pstate = &fp->state;
- params.ramrod_params.state = BNX2X_FP_STATE_OPEN;
- params.ramrod_params.index = fp->index;
- params.ramrod_params.cid = fp->cid;
+ q_params.q_obj = &fp->q_obj;
+ /* We want to wait for completion in this context */
+ __set_bit(RAMROD_COMP_WAIT, &q_params.ramrod_flags);
-#ifdef BCM_CNIC
- if (IS_FCOE_FP(fp))
- params.ramrod_params.flags |= CLIENT_IS_FCOE;
+ /* Prepare the INIT parameters */
+ bnx2x_pf_q_prep_init(bp, fp, &q_params.params.init);
-#endif
+ /* Set the command */
+ q_params.cmd = BNX2X_Q_CMD_INIT;
- if (is_leading)
- params.ramrod_params.flags |= CLIENT_IS_LEADING_RSS;
+ /* Change the state to INIT */
+ rc = bnx2x_queue_state_change(bp, &q_params);
+ if (rc) {
+ BNX2X_ERR("Queue INIT failed\n");
+ return rc;
+ }
- bnx2x_pf_rx_cl_prep(bp, fp, ¶ms.pause, ¶ms.rxq_params);
+ /* Now move the Queue to the SETUP state... */
+ memset(setup_params, 0, sizeof(*setup_params));
- bnx2x_pf_tx_cl_prep(bp, fp, ¶ms.txq_params);
+ /* Set QUEUE flags */
+ setup_params->flags = bnx2x_get_q_flags(bp, fp, leading);
- rc = bnx2x_setup_fw_client(bp, ¶ms, 1,
- bnx2x_sp(bp, client_init_data),
- bnx2x_sp_mapping(bp, client_init_data));
+ /* Set general SETUP parameters */
+ bnx2x_pf_q_prep_general(bp, fp, &setup_params->gen_params);
+
+ bnx2x_pf_rx_q_prep(bp, fp, &setup_params->pause,
+ &setup_params->rxq_params);
+
+ bnx2x_pf_tx_q_prep(bp, fp, &setup_params->txq_params);
+
+ /* Set the command */
+ q_params.cmd = BNX2X_Q_CMD_SETUP;
+
+ /* Change the state to SETUP */
+ rc = bnx2x_queue_state_change(bp, &q_params);
+ if (rc)
+ BNX2X_ERR("Queue SETUP failed\n");
+
return rc;
}
-static int bnx2x_stop_fw_client(struct bnx2x *bp,
- struct bnx2x_client_ramrod_params *p)
+static int bnx2x_stop_queue(struct bnx2x *bp, int index)
{
+ struct bnx2x_fastpath *fp = &bp->fp[index];
+ struct bnx2x_queue_state_params q_params = {0};
int rc;
- int poll_flag = p->poll ? WAIT_RAMROD_POLL : 0;
+ q_params.q_obj = &fp->q_obj;
+ /* We want to wait for completion in this context */
+ __set_bit(RAMROD_COMP_WAIT, &q_params.ramrod_flags);
/* halt the connection */
- *p->pstate = BNX2X_FP_STATE_HALTING;
- bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_HALT, p->cid, 0,
- p->cl_id, 0);
-
- /* Wait for completion */
- rc = bnx2x_wait_ramrod(bp, BNX2X_FP_STATE_HALTED, p->index,
- p->pstate, poll_flag);
- if (rc) /* timeout */
+ q_params.cmd = BNX2X_Q_CMD_HALT;
+ rc = bnx2x_queue_state_change(bp, &q_params);
+ if (rc)
return rc;
- *p->pstate = BNX2X_FP_STATE_TERMINATING;
- bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_TERMINATE, p->cid, 0,
- p->cl_id, 0);
- /* Wait for completion */
- rc = bnx2x_wait_ramrod(bp, BNX2X_FP_STATE_TERMINATED, p->index,
- p->pstate, poll_flag);
- if (rc) /* timeout */
+ /* terminate the connection */
+ q_params.cmd = BNX2X_Q_CMD_TERMINATE;
+ rc = bnx2x_queue_state_change(bp, &q_params);
+ if (rc)
return rc;
-
/* delete cfc entry */
- bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_CFC_DEL, p->cid, 0, 0, 1);
-
- /* Wait for completion */
- rc = bnx2x_wait_ramrod(bp, BNX2X_FP_STATE_CLOSED, p->index,
- p->pstate, WAIT_RAMROD_COMMON);
- return rc;
-}
-
-static int bnx2x_stop_client(struct bnx2x *bp, int index)
-{
- struct bnx2x_client_ramrod_params client_stop = {0};
- struct bnx2x_fastpath *fp = &bp->fp[index];
-
- client_stop.index = index;
- client_stop.cid = fp->cid;
- client_stop.cl_id = fp->cl_id;
- client_stop.pstate = &(fp->state);
- client_stop.poll = 0;
-
- return bnx2x_stop_fw_client(bp, &client_stop);
+ q_params.cmd = BNX2X_Q_CMD_CFC_DEL;
+ return bnx2x_queue_state_change(bp, &q_params);
}
@@ -6887,12 +7119,6 @@
int port = BP_PORT(bp);
int func = BP_FUNC(bp);
int i;
- int pfunc_offset_fp = offsetof(struct hc_sb_data, p_func) +
- (CHIP_IS_E2(bp) ?
- offsetof(struct hc_status_block_data_e2, common) :
- offsetof(struct hc_status_block_data_e1x, common));
- int pfunc_offset_sp = offsetof(struct hc_sp_status_block_data, p_func);
- int pfid_offset = offsetof(struct pci_entity, pf_id);
/* Disable the function in the FW */
REG_WR8(bp, BAR_XSTRORM_INTMEM + XSTORM_FUNC_EN_OFFSET(func), 0);
@@ -6903,20 +7129,21 @@
/* FP SBs */
for_each_eth_queue(bp, i) {
struct bnx2x_fastpath *fp = &bp->fp[i];
- REG_WR8(bp,
- BAR_CSTRORM_INTMEM +
- CSTORM_STATUS_BLOCK_DATA_OFFSET(fp->fw_sb_id)
- + pfunc_offset_fp + pfid_offset,
- HC_FUNCTION_DISABLED);
+ REG_WR8(bp, BAR_CSTRORM_INTMEM +
+ CSTORM_STATUS_BLOCK_DATA_STATE_OFFSET(fp->fw_sb_id),
+ SB_DISABLED);
}
+#ifdef BCM_CNIC
+ /* CNIC SB */
+ REG_WR8(bp, BAR_CSTRORM_INTMEM +
+ CSTORM_STATUS_BLOCK_DATA_STATE_OFFSET(bnx2x_cnic_fw_sb_id(bp)),
+ SB_DISABLED);
+#endif
/* SP SB */
- REG_WR8(bp,
- BAR_CSTRORM_INTMEM +
- CSTORM_SP_STATUS_BLOCK_DATA_OFFSET(func) +
- pfunc_offset_sp + pfid_offset,
- HC_FUNCTION_DISABLED);
-
+ REG_WR8(bp, BAR_CSTRORM_INTMEM +
+ CSTORM_SP_STATUS_BLOCK_DATA_STATE_OFFSET(func),
+ SB_DISABLED);
for (i = 0; i < XSTORM_SPQ_DATA_SIZE / 4; i++)
REG_WR(bp, BAR_XSTRORM_INTMEM + XSTORM_SPQ_DATA_OFFSET(func),
@@ -6950,7 +7177,7 @@
/* Timers workaround bug for E2: if this is vnic-3,
* we need to set the entire ilt range for this timers.
*/
- if (CHIP_IS_E2(bp) && BP_VN(bp) == 3) {
+ if (!CHIP_IS_E1x(bp) && BP_VN(bp) == 3) {
struct ilt_client_info ilt_cli;
/* use dummy TM client */
memset(&ilt_cli, 0, sizeof(struct ilt_client_info));
@@ -6962,7 +7189,7 @@
}
/* this assumes that reset_port() called before reset_func()*/
- if (CHIP_IS_E2(bp))
+ if (!CHIP_IS_E1x(bp))
bnx2x_pf_disable(bp);
bp->dmae_ready = 0;
@@ -6973,6 +7200,9 @@
int port = BP_PORT(bp);
u32 val;
+ /* Reset physical Link */
+ bnx2x__link_reset(bp);
+
REG_WR(bp, NIG_REG_MASK_INTERRUPT_PORT0 + port*4, 0);
/* Do not rcv packets to BRB */
@@ -6994,92 +7224,66 @@
/* TODO: Close Doorbell port? */
}
-static void bnx2x_reset_chip(struct bnx2x *bp, u32 reset_code)
+static inline int bnx2x_reset_hw(struct bnx2x *bp, u32 load_code)
{
- DP(BNX2X_MSG_MCP, "function %d reset_code %x\n",
- BP_ABS_FUNC(bp), reset_code);
+ struct bnx2x_func_state_params func_params = {0};
- switch (reset_code) {
- case FW_MSG_CODE_DRV_UNLOAD_COMMON:
- bnx2x_reset_port(bp);
- bnx2x_reset_func(bp);
- bnx2x_reset_common(bp);
- break;
+ /* Prepare parameters for function state transitions */
+ __set_bit(RAMROD_COMP_WAIT, &func_params.ramrod_flags);
- case FW_MSG_CODE_DRV_UNLOAD_PORT:
- bnx2x_reset_port(bp);
- bnx2x_reset_func(bp);
- break;
+ func_params.f_obj = &bp->func_obj;
+ func_params.cmd = BNX2X_F_CMD_HW_RESET;
- case FW_MSG_CODE_DRV_UNLOAD_FUNCTION:
- bnx2x_reset_func(bp);
- break;
+ func_params.params.hw_init.load_phase = load_code;
- default:
- BNX2X_ERR("Unknown reset_code (0x%x) from MCP\n", reset_code);
- break;
- }
+ return bnx2x_func_state_change(bp, &func_params);
}
-#ifdef BCM_CNIC
-static inline void bnx2x_del_fcoe_eth_macs(struct bnx2x *bp)
+static inline int bnx2x_func_stop(struct bnx2x *bp)
{
- if (bp->flags & FCOE_MACS_SET) {
- if (!IS_MF_SD(bp))
- bnx2x_set_fip_eth_mac_addr(bp, 0);
+ struct bnx2x_func_state_params func_params = {0};
+ int rc;
- bnx2x_set_all_enode_macs(bp, 0);
+ /* Prepare parameters for function state transitions */
+ __set_bit(RAMROD_COMP_WAIT, &func_params.ramrod_flags);
+ func_params.f_obj = &bp->func_obj;
+ func_params.cmd = BNX2X_F_CMD_STOP;
- bp->flags &= ~FCOE_MACS_SET;
- }
-}
-#endif
-
-void bnx2x_chip_cleanup(struct bnx2x *bp, int unload_mode)
-{
- int port = BP_PORT(bp);
- u32 reset_code = 0;
- int i, cnt, rc;
-
- /* Wait until tx fastpath tasks complete */
- for_each_tx_queue(bp, i) {
- struct bnx2x_fastpath *fp = &bp->fp[i];
-
- cnt = 1000;
- while (bnx2x_has_tx_work_unload(fp)) {
-
- if (!cnt) {
- BNX2X_ERR("timeout waiting for queue[%d]\n",
- i);
+ /*
+ * Try to stop the function the 'good way'. If fails (in case
+ * of a parity error during bnx2x_chip_cleanup()) and we are
+ * not in a debug mode, perform a state transaction in order to
+ * enable further HW_RESET transaction.
+ */
+ rc = bnx2x_func_state_change(bp, &func_params);
+ if (rc) {
#ifdef BNX2X_STOP_ON_ERROR
- bnx2x_panic();
- return -EBUSY;
+ return rc;
#else
- break;
+ BNX2X_ERR("FUNC_STOP ramrod failed. Running a dry "
+ "transaction\n");
+ __set_bit(RAMROD_DRV_CLR_ONLY, &func_params.ramrod_flags);
+ return bnx2x_func_state_change(bp, &func_params);
#endif
- }
- cnt--;
- msleep(1);
- }
- }
- /* Give HW time to discard old tx messages */
- msleep(1);
-
- bnx2x_set_eth_mac(bp, 0);
-
- bnx2x_invalidate_uc_list(bp);
-
- if (CHIP_IS_E1(bp))
- bnx2x_invalidate_e1_mc_list(bp);
- else {
- bnx2x_invalidate_e1h_mc_list(bp);
- REG_WR(bp, NIG_REG_LLH0_FUNC_EN + port*8, 0);
}
-#ifdef BCM_CNIC
- bnx2x_del_fcoe_eth_macs(bp);
-#endif
+ return 0;
+}
+/**
+ * bnx2x_send_unload_req - request unload mode from the MCP.
+ *
+ * @bp: driver handle
+ * @unload_mode: requested function's unload mode
+ *
+ * Return unload mode returned by the MCP: COMMON, PORT or FUNC.
+ */
+u32 bnx2x_send_unload_req(struct bnx2x *bp, int unload_mode)
+{
+ u32 reset_code = 0;
+ int port = BP_PORT(bp);
+
+ /* Select the UNLOAD request mode */
if (unload_mode == UNLOAD_NORMAL)
reset_code = DRV_MSG_CODE_UNLOAD_REQ_WOL_DIS;
@@ -7106,54 +7310,135 @@
} else
reset_code = DRV_MSG_CODE_UNLOAD_REQ_WOL_DIS;
- /* Close multi and leading connections
- Completions for ramrods are collected in a synchronous way */
- for_each_queue(bp, i)
-
- if (bnx2x_stop_client(bp, i))
-#ifdef BNX2X_STOP_ON_ERROR
- return;
-#else
- goto unload_error;
-#endif
-
- rc = bnx2x_func_stop(bp);
- if (rc) {
- BNX2X_ERR("Function stop failed!\n");
-#ifdef BNX2X_STOP_ON_ERROR
- return;
-#else
- goto unload_error;
-#endif
- }
-#ifndef BNX2X_STOP_ON_ERROR
-unload_error:
-#endif
+ /* Send the request to the MCP */
if (!BP_NOMCP(bp))
reset_code = bnx2x_fw_command(bp, reset_code, 0);
else {
+ int path = BP_PATH(bp);
+
DP(NETIF_MSG_IFDOWN, "NO MCP - load counts[%d] "
- "%d, %d, %d\n", BP_PATH(bp),
- load_count[BP_PATH(bp)][0],
- load_count[BP_PATH(bp)][1],
- load_count[BP_PATH(bp)][2]);
- load_count[BP_PATH(bp)][0]--;
- load_count[BP_PATH(bp)][1 + port]--;
+ "%d, %d, %d\n",
+ path, load_count[path][0], load_count[path][1],
+ load_count[path][2]);
+ load_count[path][0]--;
+ load_count[path][1 + port]--;
DP(NETIF_MSG_IFDOWN, "NO MCP - new load counts[%d] "
- "%d, %d, %d\n", BP_PATH(bp),
- load_count[BP_PATH(bp)][0], load_count[BP_PATH(bp)][1],
- load_count[BP_PATH(bp)][2]);
- if (load_count[BP_PATH(bp)][0] == 0)
+ "%d, %d, %d\n",
+ path, load_count[path][0], load_count[path][1],
+ load_count[path][2]);
+ if (load_count[path][0] == 0)
reset_code = FW_MSG_CODE_DRV_UNLOAD_COMMON;
- else if (load_count[BP_PATH(bp)][1 + port] == 0)
+ else if (load_count[path][1 + port] == 0)
reset_code = FW_MSG_CODE_DRV_UNLOAD_PORT;
else
reset_code = FW_MSG_CODE_DRV_UNLOAD_FUNCTION;
}
- if ((reset_code == FW_MSG_CODE_DRV_UNLOAD_COMMON) ||
- (reset_code == FW_MSG_CODE_DRV_UNLOAD_PORT))
- bnx2x__link_reset(bp);
+ return reset_code;
+}
+
+/**
+ * bnx2x_send_unload_done - send UNLOAD_DONE command to the MCP.
+ *
+ * @bp: driver handle
+ */
+void bnx2x_send_unload_done(struct bnx2x *bp)
+{
+ /* Report UNLOAD_DONE to MCP */
+ if (!BP_NOMCP(bp))
+ bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_DONE, 0);
+}
+
+void bnx2x_chip_cleanup(struct bnx2x *bp, int unload_mode)
+{
+ int port = BP_PORT(bp);
+ int i, rc;
+ struct bnx2x_mcast_ramrod_params rparam = {0};
+ u32 reset_code;
+
+ /* Wait until tx fastpath tasks complete */
+ for_each_tx_queue(bp, i) {
+ struct bnx2x_fastpath *fp = &bp->fp[i];
+
+ rc = bnx2x_clean_tx_queue(bp, fp);
+#ifdef BNX2X_STOP_ON_ERROR
+ if (rc)
+ return;
+#endif
+ }
+
+ /* Give HW time to discard old tx messages */
+ usleep_range(1000, 1000);
+
+ /* Clean all ETH MACs */
+ rc = bnx2x_del_all_macs(bp, &bp->fp[0].mac_obj, BNX2X_ETH_MAC, false);
+ if (rc < 0)
+ BNX2X_ERR("Failed to delete all ETH macs: %d\n", rc);
+
+ /* Clean up UC list */
+ rc = bnx2x_del_all_macs(bp, &bp->fp[0].mac_obj, BNX2X_UC_LIST_MAC,
+ true);
+ if (rc < 0)
+ BNX2X_ERR("Failed to schedule DEL commands for UC MACs list: "
+ "%d\n", rc);
+
+ /* Disable LLH */
+ if (!CHIP_IS_E1(bp))
+ REG_WR(bp, NIG_REG_LLH0_FUNC_EN + port*8, 0);
+
+ /* Set "drop all" (stop Rx).
+ * We need to take a netif_addr_lock() here in order to prevent
+ * a race between the completion code and this code.
+ */
+ netif_addr_lock_bh(bp->dev);
+ /* Schedule the rx_mode command */
+ if (test_bit(BNX2X_FILTER_RX_MODE_PENDING, &bp->sp_state))
+ set_bit(BNX2X_FILTER_RX_MODE_SCHED, &bp->sp_state);
+ else
+ bnx2x_set_storm_rx_mode(bp);
+
+ /* Cleanup multicast configuration */
+ rparam.mcast_obj = &bp->mcast_obj;
+ rc = bnx2x_config_mcast(bp, &rparam, BNX2X_MCAST_CMD_DEL);
+ if (rc < 0)
+ BNX2X_ERR("Failed to send DEL multicast command: %d\n", rc);
+
+ netif_addr_unlock_bh(bp->dev);
+
+
+ /* Close multi and leading connections
+ * Completions for ramrods are collected in a synchronous way
+ */
+ for_each_queue(bp, i)
+ if (bnx2x_stop_queue(bp, i))
+#ifdef BNX2X_STOP_ON_ERROR
+ return;
+#else
+ goto unload_error;
+#endif
+ /* If SP settings didn't get completed so far - something
+ * very wrong has happen.
+ */
+ if (!bnx2x_wait_sp_comp(bp, ~0x0UL))
+ BNX2X_ERR("Hmmm... Common slow path ramrods got stuck!\n");
+
+#ifndef BNX2X_STOP_ON_ERROR
+unload_error:
+#endif
+ rc = bnx2x_func_stop(bp);
+ if (rc) {
+ BNX2X_ERR("Function stop failed!\n");
+#ifdef BNX2X_STOP_ON_ERROR
+ return;
+#endif
+ }
+
+ /*
+ * Send the UNLOAD_REQUEST to the MCP. This will return if
+ * this function should perform FUNC, PORT or COMMON HW
+ * reset.
+ */
+ reset_code = bnx2x_send_unload_req(bp, unload_mode);
/* Disable HW interrupts, NAPI */
bnx2x_netif_stop(bp, 1);
@@ -7162,12 +7447,13 @@
bnx2x_free_irq(bp);
/* Reset the chip */
- bnx2x_reset_chip(bp, reset_code);
+ rc = bnx2x_reset_hw(bp, reset_code);
+ if (rc)
+ BNX2X_ERR("HW_RESET failed\n");
+
/* Report UNLOAD_DONE to MCP */
- if (!BP_NOMCP(bp))
- bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_DONE, 0);
-
+ bnx2x_send_unload_done(bp);
}
void bnx2x_disable_close_the_gate(struct bnx2x *bp)
@@ -7184,7 +7470,7 @@
val = REG_RD(bp, addr);
val &= ~(0x300);
REG_WR(bp, addr, val);
- } else if (CHIP_IS_E1H(bp)) {
+ } else {
val = REG_RD(bp, MISC_REG_AEU_GENERAL_MASK);
val &= ~(MISC_AEU_GENERAL_MASK_REG_AEU_PXP_CLOSE_MASK |
MISC_AEU_GENERAL_MASK_REG_AEU_NIG_CLOSE_MASK);
@@ -7195,24 +7481,37 @@
/* Close gates #2, #3 and #4: */
static void bnx2x_set_234_gates(struct bnx2x *bp, bool close)
{
- u32 val, addr;
+ u32 val;
/* Gates #2 and #4a are closed/opened for "not E1" only */
if (!CHIP_IS_E1(bp)) {
/* #4 */
- val = REG_RD(bp, PXP_REG_HST_DISCARD_DOORBELLS);
- REG_WR(bp, PXP_REG_HST_DISCARD_DOORBELLS,
- close ? (val | 0x1) : (val & (~(u32)1)));
+ REG_WR(bp, PXP_REG_HST_DISCARD_DOORBELLS, !!close);
/* #2 */
- val = REG_RD(bp, PXP_REG_HST_DISCARD_INTERNAL_WRITES);
- REG_WR(bp, PXP_REG_HST_DISCARD_INTERNAL_WRITES,
- close ? (val | 0x1) : (val & (~(u32)1)));
+ REG_WR(bp, PXP_REG_HST_DISCARD_INTERNAL_WRITES, !!close);
}
/* #3 */
- addr = BP_PORT(bp) ? HC_REG_CONFIG_1 : HC_REG_CONFIG_0;
- val = REG_RD(bp, addr);
- REG_WR(bp, addr, (!close) ? (val | 0x1) : (val & (~(u32)1)));
+ if (CHIP_IS_E1x(bp)) {
+ /* Prevent interrupts from HC on both ports */
+ val = REG_RD(bp, HC_REG_CONFIG_1);
+ REG_WR(bp, HC_REG_CONFIG_1,
+ (!close) ? (val | HC_CONFIG_1_REG_BLOCK_DISABLE_1) :
+ (val & ~(u32)HC_CONFIG_1_REG_BLOCK_DISABLE_1));
+
+ val = REG_RD(bp, HC_REG_CONFIG_0);
+ REG_WR(bp, HC_REG_CONFIG_0,
+ (!close) ? (val | HC_CONFIG_0_REG_BLOCK_DISABLE_0) :
+ (val & ~(u32)HC_CONFIG_0_REG_BLOCK_DISABLE_0));
+ } else {
+ /* Prevent incomming interrupts in IGU */
+ val = REG_RD(bp, IGU_REG_BLOCK_CONFIGURATION);
+
+ REG_WR(bp, IGU_REG_BLOCK_CONFIGURATION,
+ (!close) ?
+ (val | IGU_BLOCK_CONFIGURATION_REG_BLOCK_ENABLE) :
+ (val & ~(u32)IGU_BLOCK_CONFIGURATION_REG_BLOCK_ENABLE));
+ }
DP(NETIF_MSG_HW, "%s gates #2, #3 and #4\n",
close ? "closing" : "opening");
@@ -7330,7 +7629,6 @@
if (!CHIP_IS_E1(bp)) {
REG_WR(bp, PXP2_REG_RD_START_INIT, 0);
REG_WR(bp, PXP2_REG_RQ_RBC_DONE, 0);
- REG_WR(bp, PXP2_REG_RQ_CFG_DONE, 0);
mmiowb();
}
}
@@ -7345,9 +7643,18 @@
* - GRC
* - RBCN, RBCP
*/
-static void bnx2x_process_kill_chip_reset(struct bnx2x *bp)
+static void bnx2x_process_kill_chip_reset(struct bnx2x *bp, bool global)
{
u32 not_reset_mask1, reset_mask1, not_reset_mask2, reset_mask2;
+ u32 global_bits2;
+
+ /*
+ * Bits that have to be set in reset_mask2 if we want to reset 'global'
+ * (per chip) blocks.
+ */
+ global_bits2 =
+ MISC_REGISTERS_RESET_REG_2_RST_MCP_N_RESET_CMN_CPU |
+ MISC_REGISTERS_RESET_REG_2_RST_MCP_N_RESET_CMN_CORE;
not_reset_mask1 =
MISC_REGISTERS_RESET_REG_1_RST_HC |
@@ -7355,7 +7662,7 @@
MISC_REGISTERS_RESET_REG_1_RST_PXP;
not_reset_mask2 =
- MISC_REGISTERS_RESET_REG_2_RST_MDIO |
+ MISC_REGISTERS_RESET_REG_2_RST_PCI_MDIO |
MISC_REGISTERS_RESET_REG_2_RST_EMAC0_HARD_CORE |
MISC_REGISTERS_RESET_REG_2_RST_EMAC1_HARD_CORE |
MISC_REGISTERS_RESET_REG_2_RST_MISC_CORE |
@@ -7371,20 +7678,76 @@
else
reset_mask2 = 0x1ffff;
- REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_CLEAR,
- reset_mask1 & (~not_reset_mask1));
+ if (CHIP_IS_E3(bp)) {
+ reset_mask2 |= MISC_REGISTERS_RESET_REG_2_MSTAT0;
+ reset_mask2 |= MISC_REGISTERS_RESET_REG_2_MSTAT1;
+ }
+
+ /* Don't reset global blocks unless we need to */
+ if (!global)
+ reset_mask2 &= ~global_bits2;
+
+ /*
+ * In case of attention in the QM, we need to reset PXP
+ * (MISC_REGISTERS_RESET_REG_2_RST_PXP_RQ_RD_WR) before QM
+ * because otherwise QM reset would release 'close the gates' shortly
+ * before resetting the PXP, then the PSWRQ would send a write
+ * request to PGLUE. Then when PXP is reset, PGLUE would try to
+ * read the payload data from PSWWR, but PSWWR would not
+ * respond. The write queue in PGLUE would stuck, dmae commands
+ * would not return. Therefore it's important to reset the second
+ * reset register (containing the
+ * MISC_REGISTERS_RESET_REG_2_RST_PXP_RQ_RD_WR bit) before the
+ * first one (containing the MISC_REGISTERS_RESET_REG_1_RST_QM
+ * bit).
+ */
REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR,
reset_mask2 & (~not_reset_mask2));
+ REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_CLEAR,
+ reset_mask1 & (~not_reset_mask1));
+
barrier();
mmiowb();
- REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_SET, reset_mask1);
REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET, reset_mask2);
+ REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_SET, reset_mask1);
mmiowb();
}
-static int bnx2x_process_kill(struct bnx2x *bp)
+/**
+ * bnx2x_er_poll_igu_vq - poll for pending writes bit.
+ * It should get cleared in no more than 1s.
+ *
+ * @bp: driver handle
+ *
+ * It should get cleared in no more than 1s. Returns 0 if
+ * pending writes bit gets cleared.
+ */
+static int bnx2x_er_poll_igu_vq(struct bnx2x *bp)
+{
+ u32 cnt = 1000;
+ u32 pend_bits = 0;
+
+ do {
+ pend_bits = REG_RD(bp, IGU_REG_PENDING_BITS_STATUS);
+
+ if (pend_bits == 0)
+ break;
+
+ usleep_range(1000, 1000);
+ } while (cnt-- > 0);
+
+ if (cnt <= 0) {
+ BNX2X_ERR("Still pending IGU requests pend_bits=%x!\n",
+ pend_bits);
+ return -EBUSY;
+ }
+
+ return 0;
+}
+
+static int bnx2x_process_kill(struct bnx2x *bp, bool global)
{
int cnt = 1000;
u32 val = 0;
@@ -7403,7 +7766,7 @@
((port_is_idle_1 & 0x1) == 0x1) &&
(pgl_exp_rom2 == 0xffffffff))
break;
- msleep(1);
+ usleep_range(1000, 1000);
} while (cnt-- > 0);
if (cnt <= 0) {
@@ -7423,6 +7786,11 @@
/* Close gates #2, #3 and #4 */
bnx2x_set_234_gates(bp, true);
+ /* Poll for IGU VQs for 57712 and newer chips */
+ if (!CHIP_IS_E1x(bp) && bnx2x_er_poll_igu_vq(bp))
+ return -EAGAIN;
+
+
/* TBD: Indicate that "process kill" is in progress to MCP */
/* Clear "unprepared" bit */
@@ -7435,25 +7803,28 @@
/* Wait for 1ms to empty GLUE and PCI-E core queues,
* PSWHST, GRC and PSWRD Tetris buffer.
*/
- msleep(1);
+ usleep_range(1000, 1000);
/* Prepare to chip reset: */
/* MCP */
- bnx2x_reset_mcp_prep(bp, &val);
+ if (global)
+ bnx2x_reset_mcp_prep(bp, &val);
/* PXP */
bnx2x_pxp_prep(bp);
barrier();
/* reset the chip */
- bnx2x_process_kill_chip_reset(bp);
+ bnx2x_process_kill_chip_reset(bp, global);
barrier();
/* Recover after reset: */
/* MCP */
- if (bnx2x_reset_mcp_comp(bp, val))
+ if (global && bnx2x_reset_mcp_comp(bp, val))
return -EAGAIN;
+ /* TBD: Add resetting the NO_MCP mode DB here */
+
/* PXP */
bnx2x_pxp_prep(bp);
@@ -7466,43 +7837,85 @@
return 0;
}
-static int bnx2x_leader_reset(struct bnx2x *bp)
+int bnx2x_leader_reset(struct bnx2x *bp)
{
int rc = 0;
+ bool global = bnx2x_reset_is_global(bp);
+
/* Try to recover after the failure */
- if (bnx2x_process_kill(bp)) {
- printk(KERN_ERR "%s: Something bad had happen! Aii!\n",
- bp->dev->name);
+ if (bnx2x_process_kill(bp, global)) {
+ netdev_err(bp->dev, "Something bad had happen on engine %d! "
+ "Aii!\n", BP_PATH(bp));
rc = -EAGAIN;
goto exit_leader_reset;
}
- /* Clear "reset is in progress" bit and update the driver state */
+ /*
+ * Clear RESET_IN_PROGRES and RESET_GLOBAL bits and update the driver
+ * state.
+ */
bnx2x_set_reset_done(bp);
- bp->recovery_state = BNX2X_RECOVERY_DONE;
+ if (global)
+ bnx2x_clear_reset_global(bp);
exit_leader_reset:
bp->is_leader = 0;
- bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_RESERVED_08);
- smp_wmb();
+ bnx2x_release_leader_lock(bp);
+ smp_mb();
return rc;
}
-/* Assumption: runs under rtnl lock. This together with the fact
+static inline void bnx2x_recovery_failed(struct bnx2x *bp)
+{
+ netdev_err(bp->dev, "Recovery has failed. Power cycle is needed.\n");
+
+ /* Disconnect this device */
+ netif_device_detach(bp->dev);
+
+ /*
+ * Block ifup for all function on this engine until "process kill"
+ * or power cycle.
+ */
+ bnx2x_set_reset_in_progress(bp);
+
+ /* Shut down the power */
+ bnx2x_set_power_state(bp, PCI_D3hot);
+
+ bp->recovery_state = BNX2X_RECOVERY_FAILED;
+
+ smp_mb();
+}
+
+/*
+ * Assumption: runs under rtnl lock. This together with the fact
* that it's called only from bnx2x_reset_task() ensure that it
* will never be called when netif_running(bp->dev) is false.
*/
static void bnx2x_parity_recover(struct bnx2x *bp)
{
+ bool global = false;
+
DP(NETIF_MSG_HW, "Handling parity\n");
while (1) {
switch (bp->recovery_state) {
case BNX2X_RECOVERY_INIT:
DP(NETIF_MSG_HW, "State is BNX2X_RECOVERY_INIT\n");
+ bnx2x_chk_parity_attn(bp, &global, false);
+
/* Try to get a LEADER_LOCK HW lock */
- if (bnx2x_trylock_hw_lock(bp,
- HW_LOCK_RESOURCE_RESERVED_08))
+ if (bnx2x_trylock_leader_lock(bp)) {
+ bnx2x_set_reset_in_progress(bp);
+ /*
+ * Check if there is a global attention and if
+ * there was a global attention, set the global
+ * reset bit.
+ */
+
+ if (global)
+ bnx2x_set_reset_global(bp);
+
bp->is_leader = 1;
+ }
/* Stop the driver */
/* If interface has been removed - break */
@@ -7510,17 +7923,43 @@
return;
bp->recovery_state = BNX2X_RECOVERY_WAIT;
- /* Ensure "is_leader" and "recovery_state"
- * update values are seen on other CPUs
+
+ /*
+ * Reset MCP command sequence number and MCP mail box
+ * sequence as we are going to reset the MCP.
*/
- smp_wmb();
+ if (global) {
+ bp->fw_seq = 0;
+ bp->fw_drv_pulse_wr_seq = 0;
+ }
+
+ /* Ensure "is_leader", MCP command sequence and
+ * "recovery_state" update values are seen on other
+ * CPUs.
+ */
+ smp_mb();
break;
case BNX2X_RECOVERY_WAIT:
DP(NETIF_MSG_HW, "State is BNX2X_RECOVERY_WAIT\n");
if (bp->is_leader) {
- u32 load_counter = bnx2x_get_load_cnt(bp);
- if (load_counter) {
+ int other_engine = BP_PATH(bp) ? 0 : 1;
+ u32 other_load_counter =
+ bnx2x_get_load_cnt(bp, other_engine);
+ u32 load_counter =
+ bnx2x_get_load_cnt(bp, BP_PATH(bp));
+ global = bnx2x_reset_is_global(bp);
+
+ /*
+ * In case of a parity in a global block, let
+ * the first leader that performs a
+ * leader_reset() reset the global blocks in
+ * order to clear global attentions. Otherwise
+ * the the gates will remain closed for that
+ * engine.
+ */
+ if (load_counter ||
+ (global && other_load_counter)) {
/* Wait until all other functions get
* down.
*/
@@ -7533,37 +7972,27 @@
* normal. In any case it's an exit
* point for a leader.
*/
- if (bnx2x_leader_reset(bp) ||
- bnx2x_nic_load(bp, LOAD_NORMAL)) {
- printk(KERN_ERR"%s: Recovery "
- "has failed. Power cycle is "
- "needed.\n", bp->dev->name);
- /* Disconnect this device */
- netif_device_detach(bp->dev);
- /* Block ifup for all function
- * of this ASIC until
- * "process kill" or power
- * cycle.
- */
- bnx2x_set_reset_in_progress(bp);
- /* Shut down the power */
- bnx2x_set_power_state(bp,
- PCI_D3hot);
+ if (bnx2x_leader_reset(bp)) {
+ bnx2x_recovery_failed(bp);
return;
}
- return;
+ /* If we are here, means that the
+ * leader has succeeded and doesn't
+ * want to be a leader any more. Try
+ * to continue as a none-leader.
+ */
+ break;
}
} else { /* non-leader */
- if (!bnx2x_reset_is_done(bp)) {
+ if (!bnx2x_reset_is_done(bp, BP_PATH(bp))) {
/* Try to get a LEADER_LOCK HW lock as
* long as a former leader may have
* been unloaded by the user or
* released a leadership by another
* reason.
*/
- if (bnx2x_trylock_hw_lock(bp,
- HW_LOCK_RESOURCE_RESERVED_08)) {
+ if (bnx2x_trylock_leader_lock(bp)) {
/* I'm a leader now! Restart a
* switch case.
*/
@@ -7575,14 +8004,25 @@
HZ/10);
return;
- } else { /* A leader has completed
- * the "process kill". It's an exit
- * point for a non-leader.
- */
- bnx2x_nic_load(bp, LOAD_NORMAL);
- bp->recovery_state =
- BNX2X_RECOVERY_DONE;
- smp_wmb();
+ } else {
+ /*
+ * If there was a global attention, wait
+ * for it to be cleared.
+ */
+ if (bnx2x_reset_is_global(bp)) {
+ schedule_delayed_work(
+ &bp->reset_task, HZ/10);
+ return;
+ }
+
+ if (bnx2x_nic_load(bp, LOAD_NORMAL))
+ bnx2x_recovery_failed(bp);
+ else {
+ bp->recovery_state =
+ BNX2X_RECOVERY_DONE;
+ smp_mb();
+ }
+
return;
}
}
@@ -7624,6 +8064,37 @@
/* end of nic load/unload */
+static void bnx2x_period_task(struct work_struct *work)
+{
+ struct bnx2x *bp = container_of(work, struct bnx2x, period_task.work);
+
+ if (!netif_running(bp->dev))
+ goto period_task_exit;
+
+ if (CHIP_REV_IS_SLOW(bp)) {
+ BNX2X_ERR("period task called on emulation, ignoring\n");
+ goto period_task_exit;
+ }
+
+ bnx2x_acquire_phy_lock(bp);
+ /*
+ * The barrier is needed to ensure the ordering between the writing to
+ * the bp->port.pmf in the bnx2x_nic_load() or bnx2x_pmf_update() and
+ * the reading here.
+ */
+ smp_mb();
+ if (bp->port.pmf) {
+ bnx2x_period_func(&bp->link_params, &bp->link_vars);
+
+ /* Re-queue task in 1 sec */
+ queue_delayed_work(bnx2x_wq, &bp->period_task, 1*HZ);
+ }
+
+ bnx2x_release_phy_lock(bp);
+period_task_exit:
+ return;
+}
+
/*
* Init service functions
*/
@@ -7681,8 +8152,8 @@
u32 reset_code = DRV_MSG_CODE_UNLOAD_REQ_WOL_DIS;
/* save our pf_num */
int orig_pf_num = bp->pf_num;
- u32 swap_en;
- u32 swap_val;
+ int port;
+ u32 swap_en, swap_val, value;
/* clear the UNDI indication */
REG_WR(bp, DORQ_REG_NORM_CID_OFST, 0);
@@ -7717,21 +8188,19 @@
bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_UNDI);
bnx2x_undi_int_disable(bp);
+ port = BP_PORT(bp);
/* close input traffic and wait for it */
/* Do not rcv packets to BRB */
- REG_WR(bp,
- (BP_PORT(bp) ? NIG_REG_LLH1_BRB1_DRV_MASK :
- NIG_REG_LLH0_BRB1_DRV_MASK), 0x0);
+ REG_WR(bp, (port ? NIG_REG_LLH1_BRB1_DRV_MASK :
+ NIG_REG_LLH0_BRB1_DRV_MASK), 0x0);
/* Do not direct rcv packets that are not for MCP to
* the BRB */
- REG_WR(bp,
- (BP_PORT(bp) ? NIG_REG_LLH1_BRB1_NOT_MCP :
- NIG_REG_LLH0_BRB1_NOT_MCP), 0x0);
+ REG_WR(bp, (port ? NIG_REG_LLH1_BRB1_NOT_MCP :
+ NIG_REG_LLH0_BRB1_NOT_MCP), 0x0);
/* clear AEU */
- REG_WR(bp,
- (BP_PORT(bp) ? MISC_REG_AEU_MASK_ATTN_FUNC_1 :
- MISC_REG_AEU_MASK_ATTN_FUNC_0), 0);
+ REG_WR(bp, (port ? MISC_REG_AEU_MASK_ATTN_FUNC_1 :
+ MISC_REG_AEU_MASK_ATTN_FUNC_0), 0);
msleep(10);
/* save NIG port swap info */
@@ -7741,9 +8210,17 @@
REG_WR(bp,
GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_CLEAR,
0xd3ffffff);
+
+ value = 0x1400;
+ if (CHIP_IS_E3(bp)) {
+ value |= MISC_REGISTERS_RESET_REG_2_MSTAT0;
+ value |= MISC_REGISTERS_RESET_REG_2_MSTAT1;
+ }
+
REG_WR(bp,
GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR,
- 0x1403);
+ value);
+
/* take the NIG out of reset and restore swap values */
REG_WR(bp,
GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_SET,
@@ -7784,7 +8261,7 @@
/* Set doorbell size */
bp->db_size = (1 << BNX2X_DB_SHIFT);
- if (CHIP_IS_E2(bp)) {
+ if (!CHIP_IS_E1x(bp)) {
val = REG_RD(bp, MISC_REG_PORT4MODE_EN_OVWR);
if ((val & 1) == 0)
val = REG_RD(bp, MISC_REG_PORT4MODE_EN);
@@ -7804,16 +8281,6 @@
bp->pfid = bp->pf_num; /* 0..7 */
}
- /*
- * set base FW non-default (fast path) status block id, this value is
- * used to initialize the fw_sb_id saved on the fp/queue structure to
- * determine the id used by the FW.
- */
- if (CHIP_IS_E1x(bp))
- bp->base_fw_ndsb = BP_PORT(bp) * FP_SB_MAX_E1x;
- else /* E2 */
- bp->base_fw_ndsb = BP_PORT(bp) * FP_SB_MAX_E2;
-
bp->link_params.chip_id = bp->common.chip_id;
BNX2X_DEV_INFO("chip ID is 0x%x\n", id);
@@ -7825,13 +8292,15 @@
}
val = REG_RD(bp, MCP_REG_MCPR_NVM_CFG4);
- bp->common.flash_size = (NVRAM_1MB_SIZE <<
+ bp->common.flash_size = (BNX2X_NVRAM_1MB_SIZE <<
(val & MCPR_NVM_CFG4_FLASH_SIZE));
BNX2X_DEV_INFO("flash_size 0x%x (%d)\n",
bp->common.flash_size, bp->common.flash_size);
bnx2x_init_shmem(bp);
+
+
bp->common.shmem2_base = REG_RD(bp, (BP_PATH(bp) ?
MISC_REG_GENERIC_CR_1 :
MISC_REG_GENERIC_CR_0));
@@ -7880,6 +8349,10 @@
(val >= REQ_BC_VER_4_VRFY_SPECIFIC_PHY_OPT_MDL) ?
FEATURE_CONFIG_BC_SUPPORTS_DUAL_PHY_OPT_MDL_VRFY : 0;
+ bp->link_params.feature_config_flags |=
+ (val >= REQ_BC_VER_4_SFP_TX_DISABLE_SUPPORTED) ?
+ FEATURE_CONFIG_BC_SUPPORTS_SFP_TX_DISABLED : 0;
+
pci_read_config_word(bp->pdev, bp->pm_cap + PCI_PM_PMC, &pmc);
bp->flags |= (pmc & PCI_PM_CAP_PME_D3cold) ? 0 : NO_WOL_FLAG;
@@ -7941,8 +8414,14 @@
}
}
}
- bp->igu_sb_cnt = min_t(u8, bp->igu_sb_cnt,
- NUM_IGU_SB_REQUIRED(bp->l2_cid_count));
+
+ /* It's expected that number of CAM entries for this
+ * functions is equal to the MSI-X table size (which was a
+ * used during bp->l2_cid_count value calculation.
+ * We want a harsh warning if these values are different!
+ */
+ WARN_ON(bp->igu_sb_cnt != NUM_IGU_SB_REQUIRED(bp->l2_cid_count));
+
if (bp->igu_sb_cnt == 0)
BNX2X_ERR("CAM configuration error\n");
}
@@ -7991,24 +8470,25 @@
return;
}
- switch (switch_cfg) {
- case SWITCH_CFG_1G:
- bp->port.phy_addr = REG_RD(bp, NIG_REG_SERDES0_CTRL_PHY_ADDR +
- port*0x10);
- BNX2X_DEV_INFO("phy_addr 0x%x\n", bp->port.phy_addr);
- break;
-
- case SWITCH_CFG_10G:
- bp->port.phy_addr = REG_RD(bp, NIG_REG_XGXS0_CTRL_PHY_ADDR +
- port*0x18);
- BNX2X_DEV_INFO("phy_addr 0x%x\n", bp->port.phy_addr);
- break;
-
- default:
- BNX2X_ERR("BAD switch_cfg link_config 0x%x\n",
- bp->port.link_config[0]);
- return;
+ if (CHIP_IS_E3(bp))
+ bp->port.phy_addr = REG_RD(bp, MISC_REG_WC0_CTRL_PHY_ADDR);
+ else {
+ switch (switch_cfg) {
+ case SWITCH_CFG_1G:
+ bp->port.phy_addr = REG_RD(
+ bp, NIG_REG_SERDES0_CTRL_PHY_ADDR + port*0x10);
+ break;
+ case SWITCH_CFG_10G:
+ bp->port.phy_addr = REG_RD(
+ bp, NIG_REG_XGXS0_CTRL_PHY_ADDR + port*0x18);
+ break;
+ default:
+ BNX2X_ERR("BAD switch_cfg link_config 0x%x\n",
+ bp->port.link_config[0]);
+ return;
+ }
}
+ BNX2X_DEV_INFO("phy_addr 0x%x\n", bp->port.phy_addr);
/* mask what we support according to speed_cap_mask per configuration */
for (idx = 0; idx < cfg_size; idx++) {
if (!(bp->link_params.speed_cap_mask[idx] &
@@ -8089,7 +8569,7 @@
(ADVERTISED_10baseT_Full |
ADVERTISED_TP);
} else {
- BNX2X_ERROR("NVRAM config error. "
+ BNX2X_ERR("NVRAM config error. "
"Invalid link_config 0x%x"
" speed_cap_mask 0x%x\n",
link_config,
@@ -8108,7 +8588,7 @@
(ADVERTISED_10baseT_Half |
ADVERTISED_TP);
} else {
- BNX2X_ERROR("NVRAM config error. "
+ BNX2X_ERR("NVRAM config error. "
"Invalid link_config 0x%x"
" speed_cap_mask 0x%x\n",
link_config,
@@ -8126,7 +8606,7 @@
(ADVERTISED_100baseT_Full |
ADVERTISED_TP);
} else {
- BNX2X_ERROR("NVRAM config error. "
+ BNX2X_ERR("NVRAM config error. "
"Invalid link_config 0x%x"
" speed_cap_mask 0x%x\n",
link_config,
@@ -8146,7 +8626,7 @@
(ADVERTISED_100baseT_Half |
ADVERTISED_TP);
} else {
- BNX2X_ERROR("NVRAM config error. "
+ BNX2X_ERR("NVRAM config error. "
"Invalid link_config 0x%x"
" speed_cap_mask 0x%x\n",
link_config,
@@ -8164,7 +8644,7 @@
(ADVERTISED_1000baseT_Full |
ADVERTISED_TP);
} else {
- BNX2X_ERROR("NVRAM config error. "
+ BNX2X_ERR("NVRAM config error. "
"Invalid link_config 0x%x"
" speed_cap_mask 0x%x\n",
link_config,
@@ -8182,7 +8662,7 @@
(ADVERTISED_2500baseX_Full |
ADVERTISED_TP);
} else {
- BNX2X_ERROR("NVRAM config error. "
+ BNX2X_ERR("NVRAM config error. "
"Invalid link_config 0x%x"
" speed_cap_mask 0x%x\n",
link_config,
@@ -8192,8 +8672,6 @@
break;
case PORT_FEATURE_LINK_SPEED_10G_CX4:
- case PORT_FEATURE_LINK_SPEED_10G_KX4:
- case PORT_FEATURE_LINK_SPEED_10G_KR:
if (bp->port.supported[idx] &
SUPPORTED_10000baseT_Full) {
bp->link_params.req_line_speed[idx] =
@@ -8202,7 +8680,7 @@
(ADVERTISED_10000baseT_Full |
ADVERTISED_FIBRE);
} else {
- BNX2X_ERROR("NVRAM config error. "
+ BNX2X_ERR("NVRAM config error. "
"Invalid link_config 0x%x"
" speed_cap_mask 0x%x\n",
link_config,
@@ -8210,11 +8688,14 @@
return;
}
break;
+ case PORT_FEATURE_LINK_SPEED_20G:
+ bp->link_params.req_line_speed[idx] = SPEED_20000;
+ break;
default:
- BNX2X_ERROR("NVRAM config error. "
- "BAD link speed link_config 0x%x\n",
- link_config);
+ BNX2X_ERR("NVRAM config error. "
+ "BAD link speed link_config 0x%x\n",
+ link_config);
bp->link_params.req_line_speed[idx] =
SPEED_AUTO_NEG;
bp->port.advertising[idx] =
@@ -8364,6 +8845,9 @@
u8 *fip_mac = bp->fip_mac;
#endif
+ /* Zero primary MAC configuration */
+ memset(bp->dev->dev_addr, 0, ETH_ALEN);
+
if (BP_NOMCP(bp)) {
BNX2X_ERROR("warning: random MAC workaround active\n");
random_ether_addr(bp->dev->dev_addr);
@@ -8385,9 +8869,10 @@
iscsi_mac_addr_upper);
val = MF_CFG_RD(bp, func_ext_config[func].
iscsi_mac_addr_lower);
- BNX2X_DEV_INFO("Read iSCSI MAC: "
- "0x%x:0x%04x\n", val2, val);
bnx2x_set_mac_buf(iscsi_mac, val, val2);
+ BNX2X_DEV_INFO("Read iSCSI MAC: "
+ BNX2X_MAC_FMT"\n",
+ BNX2X_MAC_PRN_LIST(iscsi_mac));
} else
bp->flags |= NO_ISCSI_OOO_FLAG | NO_ISCSI_FLAG;
@@ -8396,9 +8881,10 @@
fcoe_mac_addr_upper);
val = MF_CFG_RD(bp, func_ext_config[func].
fcoe_mac_addr_lower);
- BNX2X_DEV_INFO("Read FCoE MAC to "
- "0x%x:0x%04x\n", val2, val);
bnx2x_set_mac_buf(fip_mac, val, val2);
+ BNX2X_DEV_INFO("Read FCoE L2 MAC to "
+ BNX2X_MAC_FMT"\n",
+ BNX2X_MAC_PRN_LIST(fip_mac));
} else
bp->flags |= NO_FCOE_FLAG;
@@ -8447,6 +8933,13 @@
memset(bp->fip_mac, 0, ETH_ALEN);
}
#endif
+
+ if (!is_valid_ether_addr(bp->dev->dev_addr))
+ dev_err(&bp->pdev->dev,
+ "bad Ethernet MAC address configuration: "
+ BNX2X_MAC_FMT", change it manually before bringing up "
+ "the appropriate network interface\n",
+ BNX2X_MAC_PRN_LIST(bp->dev->dev_addr));
}
static int __devinit bnx2x_get_hwinfo(struct bnx2x *bp)
@@ -8468,17 +8961,55 @@
} else {
bp->common.int_block = INT_BLOCK_IGU;
val = REG_RD(bp, IGU_REG_BLOCK_CONFIGURATION);
+
if (val & IGU_BLOCK_CONFIGURATION_REG_BACKWARD_COMP_EN) {
- DP(NETIF_MSG_PROBE, "IGU Backward Compatible Mode\n");
+ int tout = 5000;
+
+ BNX2X_DEV_INFO("FORCING Normal Mode\n");
+
+ val &= ~(IGU_BLOCK_CONFIGURATION_REG_BACKWARD_COMP_EN);
+ REG_WR(bp, IGU_REG_BLOCK_CONFIGURATION, val);
+ REG_WR(bp, IGU_REG_RESET_MEMORIES, 0x7f);
+
+ while (tout && REG_RD(bp, IGU_REG_RESET_MEMORIES)) {
+ tout--;
+ usleep_range(1000, 1000);
+ }
+
+ if (REG_RD(bp, IGU_REG_RESET_MEMORIES)) {
+ dev_err(&bp->pdev->dev,
+ "FORCING Normal Mode failed!!!\n");
+ return -EPERM;
+ }
+ }
+
+ if (val & IGU_BLOCK_CONFIGURATION_REG_BACKWARD_COMP_EN) {
+ BNX2X_DEV_INFO("IGU Backward Compatible Mode\n");
bp->common.int_block |= INT_BLOCK_MODE_BW_COMP;
} else
- DP(NETIF_MSG_PROBE, "IGU Normal Mode\n");
+ BNX2X_DEV_INFO("IGU Normal Mode\n");
bnx2x_get_igu_cam_info(bp);
}
- DP(NETIF_MSG_PROBE, "igu_dsb_id %d igu_base_sb %d igu_sb_cnt %d\n",
- bp->igu_dsb_id, bp->igu_base_sb, bp->igu_sb_cnt);
+
+ /*
+ * set base FW non-default (fast path) status block id, this value is
+ * used to initialize the fw_sb_id saved on the fp/queue structure to
+ * determine the id used by the FW.
+ */
+ if (CHIP_IS_E1x(bp))
+ bp->base_fw_ndsb = BP_PORT(bp) * FP_SB_MAX_E1x + BP_L_ID(bp);
+ else /*
+ * 57712 - we currently use one FW SB per IGU SB (Rx and Tx of
+ * the same queue are indicated on the same IGU SB). So we prefer
+ * FW and IGU SBs to be the same value.
+ */
+ bp->base_fw_ndsb = bp->igu_base_sb;
+
+ BNX2X_DEV_INFO("igu_dsb_id %d igu_base_sb %d igu_sb_cnt %d\n"
+ "base_fw_ndsb %d\n", bp->igu_dsb_id, bp->igu_base_sb,
+ bp->igu_sb_cnt, bp->base_fw_ndsb);
/*
* Initialize MF configuration
@@ -8489,10 +9020,10 @@
vn = BP_E1HVN(bp);
if (!CHIP_IS_E1(bp) && !BP_NOMCP(bp)) {
- DP(NETIF_MSG_PROBE,
- "shmem2base 0x%x, size %d, mfcfg offset %d\n",
- bp->common.shmem2_base, SHMEM2_RD(bp, size),
- (u32)offsetof(struct shmem2_region, mf_cfg_addr));
+ BNX2X_DEV_INFO("shmem2base 0x%x, size %d, mfcfg offset %d\n",
+ bp->common.shmem2_base, SHMEM2_RD(bp, size),
+ (u32)offsetof(struct shmem2_region, mf_cfg_addr));
+
if (SHMEM2_HAS(bp, mf_cfg_addr))
bp->common.mf_cfg_base = SHMEM2_RD(bp, mf_cfg_addr);
else
@@ -8523,8 +9054,8 @@
bp->mf_config[vn] = MF_CFG_RD(bp,
func_mf_config[func].config);
} else
- DP(NETIF_MSG_PROBE, "illegal MAC "
- "address for SI\n");
+ BNX2X_DEV_INFO("illegal MAC address "
+ "for SI\n");
break;
case SHARED_FEAT_CFG_FORCE_SF_MODE_MF_ALLOWED:
/* get OV configuration */
@@ -8537,14 +9068,12 @@
bp->mf_config[vn] = MF_CFG_RD(bp,
func_mf_config[func].config);
} else
- DP(NETIF_MSG_PROBE, "illegal OV for "
- "SD\n");
+ BNX2X_DEV_INFO("illegal OV for SD\n");
break;
default:
/* Unknown configuration: reset mf_config */
bp->mf_config[vn] = 0;
- DP(NETIF_MSG_PROBE, "Unknown MF mode 0x%x\n",
- val);
+ BNX2X_DEV_INFO("unkown MF mode 0x%x\n", val);
}
}
@@ -8557,13 +9086,16 @@
FUNC_MF_CFG_E1HOV_TAG_MASK;
if (val != FUNC_MF_CFG_E1HOV_TAG_DEFAULT) {
bp->mf_ov = val;
- BNX2X_DEV_INFO("MF OV for func %d is %d"
- " (0x%04x)\n", func,
- bp->mf_ov, bp->mf_ov);
+ bp->path_has_ovlan = true;
+
+ BNX2X_DEV_INFO("MF OV for func %d is %d "
+ "(0x%04x)\n", func, bp->mf_ov,
+ bp->mf_ov);
} else {
- BNX2X_ERR("No valid MF OV for func %d,"
- " aborting\n", func);
- rc = -EPERM;
+ dev_err(&bp->pdev->dev,
+ "No valid MF OV for func %d, "
+ "aborting\n", func);
+ return -EPERM;
}
break;
case MULTI_FUNCTION_SI:
@@ -8572,31 +9104,40 @@
break;
default:
if (vn) {
- BNX2X_ERR("VN %d in single function mode,"
- " aborting\n", vn);
- rc = -EPERM;
+ dev_err(&bp->pdev->dev,
+ "VN %d is in a single function mode, "
+ "aborting\n", vn);
+ return -EPERM;
}
break;
}
+ /* check if other port on the path needs ovlan:
+ * Since MF configuration is shared between ports
+ * Possible mixed modes are only
+ * {SF, SI} {SF, SD} {SD, SF} {SI, SF}
+ */
+ if (CHIP_MODE_IS_4_PORT(bp) &&
+ !bp->path_has_ovlan &&
+ !IS_MF(bp) &&
+ bp->common.mf_cfg_base != SHMEM_MF_CFG_ADDR_NONE) {
+ u8 other_port = !BP_PORT(bp);
+ u8 other_func = BP_PATH(bp) + 2*other_port;
+ val = MF_CFG_RD(bp,
+ func_mf_config[other_func].e1hov_tag);
+ if (val != FUNC_MF_CFG_E1HOV_TAG_DEFAULT)
+ bp->path_has_ovlan = true;
+ }
}
/* adjust igu_sb_cnt to MF for E1x */
if (CHIP_IS_E1x(bp) && IS_MF(bp))
bp->igu_sb_cnt /= E1HVN_MAX;
- /*
- * adjust E2 sb count: to be removed when FW will support
- * more then 16 L2 clients
- */
-#define MAX_L2_CLIENTS 16
- if (CHIP_IS_E2(bp))
- bp->igu_sb_cnt = min_t(u8, bp->igu_sb_cnt,
- MAX_L2_CLIENTS / (IS_MF(bp) ? 4 : 1));
+ /* port info */
+ bnx2x_get_port_hwinfo(bp);
if (!BP_NOMCP(bp)) {
- bnx2x_get_port_hwinfo(bp);
-
bp->fw_seq =
(SHMEM_RD(bp, func_mb[BP_FW_MB_IDX(bp)].drv_mb_header) &
DRV_MSG_SEQ_NUMBER_MASK);
@@ -8610,6 +9151,16 @@
bnx2x_get_cnic_info(bp);
#endif
+ /* Get current FW pulse sequence */
+ if (!BP_NOMCP(bp)) {
+ int mb_idx = BP_FW_MB_IDX(bp);
+
+ bp->fw_drv_pulse_wr_seq =
+ (SHMEM_RD(bp, func_mb[mb_idx].drv_pulse_mb) &
+ DRV_PULSE_SEQ_MASK);
+ BNX2X_DEV_INFO("drv_pulse 0x%x\n", bp->fw_drv_pulse_wr_seq);
+ }
+
return rc;
}
@@ -8677,16 +9228,61 @@
return;
}
+static void __devinit bnx2x_set_modes_bitmap(struct bnx2x *bp)
+{
+ u32 flags = 0;
+
+ if (CHIP_REV_IS_FPGA(bp))
+ SET_FLAGS(flags, MODE_FPGA);
+ else if (CHIP_REV_IS_EMUL(bp))
+ SET_FLAGS(flags, MODE_EMUL);
+ else
+ SET_FLAGS(flags, MODE_ASIC);
+
+ if (CHIP_MODE_IS_4_PORT(bp))
+ SET_FLAGS(flags, MODE_PORT4);
+ else
+ SET_FLAGS(flags, MODE_PORT2);
+
+ if (CHIP_IS_E2(bp))
+ SET_FLAGS(flags, MODE_E2);
+ else if (CHIP_IS_E3(bp)) {
+ SET_FLAGS(flags, MODE_E3);
+ if (CHIP_REV(bp) == CHIP_REV_Ax)
+ SET_FLAGS(flags, MODE_E3_A0);
+ else {/*if (CHIP_REV(bp) == CHIP_REV_Bx)*/
+ SET_FLAGS(flags, MODE_E3_B0);
+ SET_FLAGS(flags, MODE_COS_BC);
+ }
+ }
+
+ if (IS_MF(bp)) {
+ SET_FLAGS(flags, MODE_MF);
+ switch (bp->mf_mode) {
+ case MULTI_FUNCTION_SD:
+ SET_FLAGS(flags, MODE_MF_SD);
+ break;
+ case MULTI_FUNCTION_SI:
+ SET_FLAGS(flags, MODE_MF_SI);
+ break;
+ }
+ } else
+ SET_FLAGS(flags, MODE_SF);
+
+#if defined(__LITTLE_ENDIAN)
+ SET_FLAGS(flags, MODE_LITTLE_ENDIAN);
+#else /*(__BIG_ENDIAN)*/
+ SET_FLAGS(flags, MODE_BIG_ENDIAN);
+#endif
+ INIT_MODE_FLAGS(bp) = flags;
+}
+
static int __devinit bnx2x_init_bp(struct bnx2x *bp)
{
int func;
int timer_interval;
int rc;
- /* Disable interrupt handling until HW is initialized */
- atomic_set(&bp->intr_sem, 1);
- smp_wmb(); /* Ensure that bp->intr_sem update is SMP-safe */
-
mutex_init(&bp->port.phy_mutex);
mutex_init(&bp->fw_mb_mutex);
spin_lock_init(&bp->stats_lock);
@@ -8696,11 +9292,16 @@
INIT_DELAYED_WORK(&bp->sp_task, bnx2x_sp_task);
INIT_DELAYED_WORK(&bp->reset_task, bnx2x_reset_task);
-
+ INIT_DELAYED_WORK(&bp->period_task, bnx2x_period_task);
rc = bnx2x_get_hwinfo(bp);
+ if (rc)
+ return rc;
- if (!rc)
- rc = bnx2x_alloc_mem_bp(bp);
+ bnx2x_set_modes_bitmap(bp);
+
+ rc = bnx2x_alloc_mem_bp(bp);
+ if (rc)
+ return rc;
bnx2x_read_fwinfo(bp);
@@ -8718,7 +9319,6 @@
"must load devices in order!\n");
bp->multi_mode = multi_mode;
- bp->int_mode = int_mode;
/* Set TPA flags */
if (disable_tpa) {
@@ -8754,6 +9354,13 @@
bnx2x_dcbx_set_state(bp, true, BNX2X_DCBX_ENABLED_ON_NEG_ON);
bnx2x_dcbx_init_params(bp);
+#ifdef BCM_CNIC
+ if (CHIP_IS_E1x(bp))
+ bp->cnic_base_cl_id = FP_SB_MAX_E1x;
+ else
+ bp->cnic_base_cl_id = FP_SB_MAX_E2;
+#endif
+
return rc;
}
@@ -8762,49 +9369,70 @@
* General service functions
****************************************************************************/
+/*
+ * net_device service functions
+ */
+
/* called with rtnl_lock */
static int bnx2x_open(struct net_device *dev)
{
struct bnx2x *bp = netdev_priv(dev);
+ bool global = false;
+ int other_engine = BP_PATH(bp) ? 0 : 1;
+ u32 other_load_counter, load_counter;
netif_carrier_off(dev);
bnx2x_set_power_state(bp, PCI_D0);
- if (!bnx2x_reset_is_done(bp)) {
- do {
- /* Reset MCP mail box sequence if there is on going
- * recovery
- */
- bp->fw_seq = 0;
+ other_load_counter = bnx2x_get_load_cnt(bp, other_engine);
+ load_counter = bnx2x_get_load_cnt(bp, BP_PATH(bp));
- /* If it's the first function to load and reset done
- * is still not cleared it may mean that. We don't
- * check the attention state here because it may have
- * already been cleared by a "common" reset but we
- * shell proceed with "process kill" anyway.
+ /*
+ * If parity had happen during the unload, then attentions
+ * and/or RECOVERY_IN_PROGRES may still be set. In this case we
+ * want the first function loaded on the current engine to
+ * complete the recovery.
+ */
+ if (!bnx2x_reset_is_done(bp, BP_PATH(bp)) ||
+ bnx2x_chk_parity_attn(bp, &global, true))
+ do {
+ /*
+ * If there are attentions and they are in a global
+ * blocks, set the GLOBAL_RESET bit regardless whether
+ * it will be this function that will complete the
+ * recovery or not.
*/
- if ((bnx2x_get_load_cnt(bp) == 0) &&
- bnx2x_trylock_hw_lock(bp,
- HW_LOCK_RESOURCE_RESERVED_08) &&
- (!bnx2x_leader_reset(bp))) {
- DP(NETIF_MSG_HW, "Recovered in open\n");
+ if (global)
+ bnx2x_set_reset_global(bp);
+
+ /*
+ * Only the first function on the current engine should
+ * try to recover in open. In case of attentions in
+ * global blocks only the first in the chip should try
+ * to recover.
+ */
+ if ((!load_counter &&
+ (!global || !other_load_counter)) &&
+ bnx2x_trylock_leader_lock(bp) &&
+ !bnx2x_leader_reset(bp)) {
+ netdev_info(bp->dev, "Recovered in open\n");
break;
}
+ /* recovery has failed... */
bnx2x_set_power_state(bp, PCI_D3hot);
+ bp->recovery_state = BNX2X_RECOVERY_FAILED;
- printk(KERN_ERR"%s: Recovery flow hasn't been properly"
+ netdev_err(bp->dev, "Recovery flow hasn't been properly"
" completed yet. Try again later. If u still see this"
" message after a few retries then power cycle is"
- " required.\n", bp->dev->name);
+ " required.\n");
return -EAGAIN;
} while (0);
- }
bp->recovery_state = BNX2X_RECOVERY_DONE;
-
return bnx2x_nic_load(bp, LOAD_OPEN);
}
@@ -8815,198 +9443,126 @@
/* Unload the driver, release IRQs */
bnx2x_nic_unload(bp, UNLOAD_CLOSE);
+
+ /* Power off */
bnx2x_set_power_state(bp, PCI_D3hot);
return 0;
}
-#define E1_MAX_UC_LIST 29
-#define E1H_MAX_UC_LIST 30
-#define E2_MAX_UC_LIST 14
-static inline u8 bnx2x_max_uc_list(struct bnx2x *bp)
+static inline int bnx2x_init_mcast_macs_list(struct bnx2x *bp,
+ struct bnx2x_mcast_ramrod_params *p)
{
- if (CHIP_IS_E1(bp))
- return E1_MAX_UC_LIST;
- else if (CHIP_IS_E1H(bp))
- return E1H_MAX_UC_LIST;
- else
- return E2_MAX_UC_LIST;
-}
-
-
-static inline u8 bnx2x_uc_list_cam_offset(struct bnx2x *bp)
-{
- if (CHIP_IS_E1(bp))
- /* CAM Entries for Port0:
- * 0 - prim ETH MAC
- * 1 - BCAST MAC
- * 2 - iSCSI L2 ring ETH MAC
- * 3-31 - UC MACs
- *
- * Port1 entries are allocated the same way starting from
- * entry 32.
- */
- return 3 + 32 * BP_PORT(bp);
- else if (CHIP_IS_E1H(bp)) {
- /* CAM Entries:
- * 0-7 - prim ETH MAC for each function
- * 8-15 - iSCSI L2 ring ETH MAC for each function
- * 16 till 255 UC MAC lists for each function
- *
- * Remark: There is no FCoE support for E1H, thus FCoE related
- * MACs are not considered.
- */
- return E1H_FUNC_MAX * (CAM_ISCSI_ETH_LINE + 1) +
- bnx2x_max_uc_list(bp) * BP_FUNC(bp);
- } else {
- /* CAM Entries (there is a separate CAM per engine):
- * 0-4 - prim ETH MAC for each function
- * 4-7 - iSCSI L2 ring ETH MAC for each function
- * 8-11 - FIP ucast L2 MAC for each function
- * 12-15 - ALL_ENODE_MACS mcast MAC for each function
- * 16 till 71 UC MAC lists for each function
- */
- u8 func_idx =
- (CHIP_MODE_IS_4_PORT(bp) ? BP_FUNC(bp) : BP_VN(bp));
-
- return E2_FUNC_MAX * (CAM_MAX_PF_LINE + 1) +
- bnx2x_max_uc_list(bp) * func_idx;
- }
-}
-
-/* set uc list, do not wait as wait implies sleep and
- * set_rx_mode can be invoked from non-sleepable context.
- *
- * Instead we use the same ramrod data buffer each time we need
- * to configure a list of addresses, and use the fact that the
- * list of MACs is changed in an incremental way and that the
- * function is called under the netif_addr_lock. A temporary
- * inconsistent CAM configuration (possible in case of very fast
- * sequence of add/del/add on the host side) will shortly be
- * restored by the handler of the last ramrod.
- */
-static int bnx2x_set_uc_list(struct bnx2x *bp)
-{
- int i = 0, old;
- struct net_device *dev = bp->dev;
- u8 offset = bnx2x_uc_list_cam_offset(bp);
+ int mc_count = netdev_mc_count(bp->dev);
+ struct bnx2x_mcast_list_elem *mc_mac =
+ kzalloc(sizeof(*mc_mac) * mc_count, GFP_ATOMIC);
struct netdev_hw_addr *ha;
- struct mac_configuration_cmd *config_cmd = bnx2x_sp(bp, uc_mac_config);
- dma_addr_t config_cmd_map = bnx2x_sp_mapping(bp, uc_mac_config);
- if (netdev_uc_count(dev) > bnx2x_max_uc_list(bp))
- return -EINVAL;
+ if (!mc_mac)
+ return -ENOMEM;
+
+ INIT_LIST_HEAD(&p->mcast_list);
+
+ netdev_for_each_mc_addr(ha, bp->dev) {
+ mc_mac->mac = bnx2x_mc_addr(ha);
+ list_add_tail(&mc_mac->link, &p->mcast_list);
+ mc_mac++;
+ }
+
+ p->mcast_list_len = mc_count;
+
+ return 0;
+}
+
+static inline void bnx2x_free_mcast_macs_list(
+ struct bnx2x_mcast_ramrod_params *p)
+{
+ struct bnx2x_mcast_list_elem *mc_mac =
+ list_first_entry(&p->mcast_list, struct bnx2x_mcast_list_elem,
+ link);
+
+ WARN_ON(!mc_mac);
+ kfree(mc_mac);
+}
+
+/**
+ * bnx2x_set_uc_list - configure a new unicast MACs list.
+ *
+ * @bp: driver handle
+ *
+ * We will use zero (0) as a MAC type for these MACs.
+ */
+static inline int bnx2x_set_uc_list(struct bnx2x *bp)
+{
+ int rc;
+ struct net_device *dev = bp->dev;
+ struct netdev_hw_addr *ha;
+ struct bnx2x_vlan_mac_obj *mac_obj = &bp->fp->mac_obj;
+ unsigned long ramrod_flags = 0;
+
+ /* First schedule a cleanup up of old configuration */
+ rc = bnx2x_del_all_macs(bp, mac_obj, BNX2X_UC_LIST_MAC, false);
+ if (rc < 0) {
+ BNX2X_ERR("Failed to schedule DELETE operations: %d\n", rc);
+ return rc;
+ }
netdev_for_each_uc_addr(ha, dev) {
- /* copy mac */
- config_cmd->config_table[i].msb_mac_addr =
- swab16(*(u16 *)&bnx2x_uc_addr(ha)[0]);
- config_cmd->config_table[i].middle_mac_addr =
- swab16(*(u16 *)&bnx2x_uc_addr(ha)[2]);
- config_cmd->config_table[i].lsb_mac_addr =
- swab16(*(u16 *)&bnx2x_uc_addr(ha)[4]);
-
- config_cmd->config_table[i].vlan_id = 0;
- config_cmd->config_table[i].pf_id = BP_FUNC(bp);
- config_cmd->config_table[i].clients_bit_vector =
- cpu_to_le32(1 << BP_L_ID(bp));
-
- SET_FLAG(config_cmd->config_table[i].flags,
- MAC_CONFIGURATION_ENTRY_ACTION_TYPE,
- T_ETH_MAC_COMMAND_SET);
-
- DP(NETIF_MSG_IFUP,
- "setting UCAST[%d] (%04x:%04x:%04x)\n", i,
- config_cmd->config_table[i].msb_mac_addr,
- config_cmd->config_table[i].middle_mac_addr,
- config_cmd->config_table[i].lsb_mac_addr);
-
- i++;
-
- /* Set uc MAC in NIG */
- bnx2x_set_mac_in_nig(bp, 1, bnx2x_uc_addr(ha),
- LLH_CAM_ETH_LINE + i);
- }
- old = config_cmd->hdr.length;
- if (old > i) {
- for (; i < old; i++) {
- if (CAM_IS_INVALID(config_cmd->
- config_table[i])) {
- /* already invalidated */
- break;
- }
- /* invalidate */
- SET_FLAG(config_cmd->config_table[i].flags,
- MAC_CONFIGURATION_ENTRY_ACTION_TYPE,
- T_ETH_MAC_COMMAND_INVALIDATE);
+ rc = bnx2x_set_mac_one(bp, bnx2x_uc_addr(ha), mac_obj, true,
+ BNX2X_UC_LIST_MAC, &ramrod_flags);
+ if (rc < 0) {
+ BNX2X_ERR("Failed to schedule ADD operations: %d\n",
+ rc);
+ return rc;
}
}
- wmb();
-
- config_cmd->hdr.length = i;
- config_cmd->hdr.offset = offset;
- config_cmd->hdr.client_id = 0xff;
- /* Mark that this ramrod doesn't use bp->set_mac_pending for
- * synchronization.
- */
- config_cmd->hdr.echo = 0;
-
- mb();
-
- return bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_SET_MAC, 0,
- U64_HI(config_cmd_map), U64_LO(config_cmd_map), 1);
-
-}
-
-void bnx2x_invalidate_uc_list(struct bnx2x *bp)
-{
- int i;
- struct mac_configuration_cmd *config_cmd = bnx2x_sp(bp, uc_mac_config);
- dma_addr_t config_cmd_map = bnx2x_sp_mapping(bp, uc_mac_config);
- int ramrod_flags = WAIT_RAMROD_COMMON;
- u8 offset = bnx2x_uc_list_cam_offset(bp);
- u8 max_list_size = bnx2x_max_uc_list(bp);
-
- for (i = 0; i < max_list_size; i++) {
- SET_FLAG(config_cmd->config_table[i].flags,
- MAC_CONFIGURATION_ENTRY_ACTION_TYPE,
- T_ETH_MAC_COMMAND_INVALIDATE);
- bnx2x_set_mac_in_nig(bp, 0, NULL, LLH_CAM_ETH_LINE + 1 + i);
- }
-
- wmb();
-
- config_cmd->hdr.length = max_list_size;
- config_cmd->hdr.offset = offset;
- config_cmd->hdr.client_id = 0xff;
- /* We'll wait for a completion this time... */
- config_cmd->hdr.echo = 1;
-
- bp->set_mac_pending = 1;
-
- mb();
-
- bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_SET_MAC, 0,
- U64_HI(config_cmd_map), U64_LO(config_cmd_map), 1);
-
- /* Wait for a completion */
- bnx2x_wait_ramrod(bp, 0, 0, &bp->set_mac_pending,
- ramrod_flags);
-
+ /* Execute the pending commands */
+ __set_bit(RAMROD_CONT, &ramrod_flags);
+ return bnx2x_set_mac_one(bp, NULL, mac_obj, false /* don't care */,
+ BNX2X_UC_LIST_MAC, &ramrod_flags);
}
static inline int bnx2x_set_mc_list(struct bnx2x *bp)
{
- /* some multicasts */
- if (CHIP_IS_E1(bp)) {
- return bnx2x_set_e1_mc_list(bp);
- } else { /* E1H and newer */
- return bnx2x_set_e1h_mc_list(bp);
+ struct net_device *dev = bp->dev;
+ struct bnx2x_mcast_ramrod_params rparam = {0};
+ int rc = 0;
+
+ rparam.mcast_obj = &bp->mcast_obj;
+
+ /* first, clear all configured multicast MACs */
+ rc = bnx2x_config_mcast(bp, &rparam, BNX2X_MCAST_CMD_DEL);
+ if (rc < 0) {
+ BNX2X_ERR("Failed to clear multicast "
+ "configuration: %d\n", rc);
+ return rc;
}
+
+ /* then, configure a new MACs list */
+ if (netdev_mc_count(dev)) {
+ rc = bnx2x_init_mcast_macs_list(bp, &rparam);
+ if (rc) {
+ BNX2X_ERR("Failed to create multicast MACs "
+ "list: %d\n", rc);
+ return rc;
+ }
+
+ /* Now add the new MACs */
+ rc = bnx2x_config_mcast(bp, &rparam,
+ BNX2X_MCAST_CMD_ADD);
+ if (rc < 0)
+ BNX2X_ERR("Failed to set a new multicast "
+ "configuration: %d\n", rc);
+
+ bnx2x_free_mcast_macs_list(&rparam);
+ }
+
+ return rc;
}
-/* called with netif_tx_lock from dev_mcast.c */
+
+/* If bp->state is OPEN, should be called with netif_addr_lock_bh() */
void bnx2x_set_rx_mode(struct net_device *dev)
{
struct bnx2x *bp = netdev_priv(dev);
@@ -9017,23 +9573,31 @@
return;
}
- DP(NETIF_MSG_IFUP, "dev->flags = %x\n", dev->flags);
+ DP(NETIF_MSG_IFUP, "dev->flags = %x\n", bp->dev->flags);
if (dev->flags & IFF_PROMISC)
rx_mode = BNX2X_RX_MODE_PROMISC;
- else if (dev->flags & IFF_ALLMULTI)
+ else if ((dev->flags & IFF_ALLMULTI) ||
+ ((netdev_mc_count(dev) > BNX2X_MAX_MULTICAST) &&
+ CHIP_IS_E1(bp)))
rx_mode = BNX2X_RX_MODE_ALLMULTI;
else {
/* some multicasts */
- if (bnx2x_set_mc_list(bp))
+ if (bnx2x_set_mc_list(bp) < 0)
rx_mode = BNX2X_RX_MODE_ALLMULTI;
- /* some unicasts */
- if (bnx2x_set_uc_list(bp))
+ if (bnx2x_set_uc_list(bp) < 0)
rx_mode = BNX2X_RX_MODE_PROMISC;
}
bp->rx_mode = rx_mode;
+
+ /* Schedule the rx_mode command */
+ if (test_bit(BNX2X_FILTER_RX_MODE_PENDING, &bp->sp_state)) {
+ set_bit(BNX2X_FILTER_RX_MODE_SCHED, &bp->sp_state);
+ return;
+ }
+
bnx2x_set_storm_rx_mode(bp);
}
@@ -9124,8 +9688,28 @@
#endif
};
+static inline int bnx2x_set_coherency_mask(struct bnx2x *bp)
+{
+ struct device *dev = &bp->pdev->dev;
+
+ if (dma_set_mask(dev, DMA_BIT_MASK(64)) == 0) {
+ bp->flags |= USING_DAC_FLAG;
+ if (dma_set_coherent_mask(dev, DMA_BIT_MASK(64)) != 0) {
+ dev_err(dev, "dma_set_coherent_mask failed, "
+ "aborting\n");
+ return -EIO;
+ }
+ } else if (dma_set_mask(dev, DMA_BIT_MASK(32)) != 0) {
+ dev_err(dev, "System does not support DMA, aborting\n");
+ return -EIO;
+ }
+
+ return 0;
+}
+
static int __devinit bnx2x_init_dev(struct pci_dev *pdev,
- struct net_device *dev)
+ struct net_device *dev,
+ unsigned long board_type)
{
struct bnx2x *bp;
int rc;
@@ -9179,29 +9763,15 @@
goto err_out_release;
}
- bp->pcie_cap = pci_find_capability(pdev, PCI_CAP_ID_EXP);
- if (bp->pcie_cap == 0) {
- dev_err(&bp->pdev->dev,
- "Cannot find PCI Express capability, aborting\n");
+ if (!pci_is_pcie(pdev)) {
+ dev_err(&bp->pdev->dev, "Not PCI Express, aborting\n");
rc = -EIO;
goto err_out_release;
}
- if (dma_set_mask(&pdev->dev, DMA_BIT_MASK(64)) == 0) {
- bp->flags |= USING_DAC_FLAG;
- if (dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(64)) != 0) {
- dev_err(&bp->pdev->dev, "dma_set_coherent_mask"
- " failed, aborting\n");
- rc = -EIO;
- goto err_out_release;
- }
-
- } else if (dma_set_mask(&pdev->dev, DMA_BIT_MASK(32)) != 0) {
- dev_err(&bp->pdev->dev,
- "System does not support DMA, aborting\n");
- rc = -EIO;
+ rc = bnx2x_set_coherency_mask(bp);
+ if (rc)
goto err_out_release;
- }
dev->mem_start = pci_resource_start(pdev, 0);
dev->base_addr = dev->mem_start;
@@ -9237,6 +9807,12 @@
REG_WR(bp, PXP2_REG_PGL_ADDR_90_F0 + BP_PORT(bp)*16, 0);
REG_WR(bp, PXP2_REG_PGL_ADDR_94_F0 + BP_PORT(bp)*16, 0);
+ /**
+ * Enable internal target-read (in case we are probed after PF FLR).
+ * Must be done prior to any BAR read access
+ */
+ REG_WR(bp, PGLUE_B_REG_INTERNAL_PFID_ENABLE_TARGET_READ, 1);
+
/* Reset the load counter */
bnx2x_clear_load_cnt(bp);
@@ -9451,7 +10027,7 @@
fw_file_name = FW_FILE_NAME_E1;
else if (CHIP_IS_E1H(bp))
fw_file_name = FW_FILE_NAME_E1H;
- else if (CHIP_IS_E2(bp))
+ else if (!CHIP_IS_E1x(bp))
fw_file_name = FW_FILE_NAME_E2;
else {
BNX2X_ERR("Unsupported chip revision\n");
@@ -9519,6 +10095,44 @@
return rc;
}
+static void bnx2x_release_firmware(struct bnx2x *bp)
+{
+ kfree(bp->init_ops_offsets);
+ kfree(bp->init_ops);
+ kfree(bp->init_data);
+ release_firmware(bp->firmware);
+}
+
+
+static struct bnx2x_func_sp_drv_ops bnx2x_func_sp_drv = {
+ .init_hw_cmn_chip = bnx2x_init_hw_common_chip,
+ .init_hw_cmn = bnx2x_init_hw_common,
+ .init_hw_port = bnx2x_init_hw_port,
+ .init_hw_func = bnx2x_init_hw_func,
+
+ .reset_hw_cmn = bnx2x_reset_common,
+ .reset_hw_port = bnx2x_reset_port,
+ .reset_hw_func = bnx2x_reset_func,
+
+ .gunzip_init = bnx2x_gunzip_init,
+ .gunzip_end = bnx2x_gunzip_end,
+
+ .init_fw = bnx2x_init_firmware,
+ .release_fw = bnx2x_release_firmware,
+};
+
+void bnx2x__init_func_obj(struct bnx2x *bp)
+{
+ /* Prepare DMAE related driver resources */
+ bnx2x_setup_dmae(bp);
+
+ bnx2x_init_func_obj(bp, &bp->func_obj,
+ bnx2x_sp(bp, func_rdata),
+ bnx2x_sp_mapping(bp, func_rdata),
+ &bnx2x_func_sp_drv);
+}
+
+/* must be called after sriov-enable */
static inline int bnx2x_set_qm_cid_count(struct bnx2x *bp, int l2_cid_count)
{
int cid_count = L2_FP_COUNT(l2_cid_count);
@@ -9529,6 +10143,25 @@
return roundup(cid_count, QM_CID_ROUND);
}
+/**
+ * bnx2x_pci_msix_table_size - get the size of the MSI-X table.
+ *
+ * @dev: pci device
+ *
+ */
+static inline int bnx2x_pci_msix_table_size(struct pci_dev *pdev)
+{
+ int pos;
+ u16 control;
+
+ pos = pci_find_capability(pdev, PCI_CAP_ID_MSIX);
+ if (!pos)
+ return 0;
+
+ pci_read_config_word(pdev, pos + PCI_MSI_FLAGS, &control);
+ return (control & PCI_MSIX_FLAGS_QSIZE) + 1;
+}
+
static int __devinit bnx2x_init_one(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
@@ -9541,12 +10174,28 @@
case BCM57710:
case BCM57711:
case BCM57711E:
- cid_count = FP_SB_MAX_E1x;
- break;
-
case BCM57712:
- case BCM57712E:
- cid_count = FP_SB_MAX_E2;
+ case BCM57712_MF:
+ case BCM57800:
+ case BCM57800_MF:
+ case BCM57810:
+ case BCM57810_MF:
+ case BCM57840:
+ case BCM57840_MF:
+ /* The size requested for the MSI-X table corresponds to the
+ * actual amount of avaliable IGU/HC status blocks. It includes
+ * the default SB vector but we want cid_count to contain the
+ * amount of only non-default SBs, that's what '-1' stands for.
+ */
+ cid_count = bnx2x_pci_msix_table_size(pdev) - 1;
+
+ /* do not allow initial cid_count grow above 16
+ * since Special CIDs starts from this number
+ * use old FP_SB_MAX_E1x define for this matter
+ */
+ cid_count = min_t(int, FP_SB_MAX_E1x, cid_count);
+
+ WARN_ON(!cid_count);
break;
default:
@@ -9555,7 +10204,7 @@
return -ENODEV;
}
- cid_count += NONE_ETH_CONTEXT_USE + CNIC_CONTEXT_USE;
+ cid_count += FCOE_CONTEXT_USE;
/* dev zeroed in init_etherdev */
dev = alloc_etherdev_mq(sizeof(*bp), cid_count);
@@ -9564,6 +10213,11 @@
return -ENOMEM;
}
+ /* We don't need a Tx queue for a CNIC and an OOO Rx-only ring,
+ * so update a cid_count after a netdev allocation.
+ */
+ cid_count += CNIC_CONTEXT_USE;
+
bp = netdev_priv(dev);
bp->msg_enable = debug;
@@ -9571,12 +10225,14 @@
bp->l2_cid_count = cid_count;
- rc = bnx2x_init_dev(pdev, dev);
+ rc = bnx2x_init_dev(pdev, dev, ent->driver_data);
if (rc < 0) {
free_netdev(dev);
return rc;
}
+ BNX2X_DEV_INFO("cid_count=%d\n", cid_count);
+
rc = bnx2x_init_bp(bp);
if (rc)
goto init_one_exit;
@@ -9713,12 +10369,17 @@
bp->rx_mode = BNX2X_RX_MODE_NONE;
+#ifdef BCM_CNIC
+ bnx2x_cnic_notify(bp, CNIC_CTL_STOP_CMD);
+#endif
+ /* Stop Tx */
+ bnx2x_tx_disable(bp);
+
bnx2x_netif_stop(bp, 0);
- netif_carrier_off(bp->dev);
del_timer_sync(&bp->timer);
- bp->stats_state = STATS_STATE_DISABLED;
- DP(BNX2X_MSG_STATS, "stats_state - DISABLED\n");
+
+ bnx2x_stats_handle(bp, STATS_EVENT_STOP);
/* Release IRQs */
bnx2x_free_irq(bp);
@@ -9733,6 +10394,8 @@
bp->state = BNX2X_STATE_CLOSED;
+ netif_carrier_off(bp->dev);
+
return 0;
}
@@ -9845,8 +10508,8 @@
struct bnx2x *bp = netdev_priv(dev);
if (bp->recovery_state != BNX2X_RECOVERY_DONE) {
- printk(KERN_ERR "Handling parity error recovery. "
- "Try again later\n");
+ netdev_err(bp->dev, "Handling parity error recovery. "
+ "Try again later\n");
return;
}
@@ -9905,10 +10568,33 @@
destroy_workqueue(bnx2x_wq);
}
+void bnx2x_notify_link_changed(struct bnx2x *bp)
+{
+ REG_WR(bp, MISC_REG_AEU_GENERAL_ATTN_12 + BP_FUNC(bp)*sizeof(u32), 1);
+}
+
module_init(bnx2x_init);
module_exit(bnx2x_cleanup);
#ifdef BCM_CNIC
+/**
+ * bnx2x_set_iscsi_eth_mac_addr - set iSCSI MAC(s).
+ *
+ * @bp: driver handle
+ * @set: set or clear the CAM entry
+ *
+ * This function will wait until the ramdord completion returns.
+ * Return 0 if success, -ENODEV if ramrod doesn't return.
+ */
+static inline int bnx2x_set_iscsi_eth_mac_addr(struct bnx2x *bp)
+{
+ unsigned long ramrod_flags = 0;
+
+ __set_bit(RAMROD_COMP_WAIT, &ramrod_flags);
+ return bnx2x_set_mac_one(bp, bp->cnic_eth_dev.iscsi_mac,
+ &bp->iscsi_l2_mac_obj, true,
+ BNX2X_ISCSI_ETH_MAC, &ramrod_flags);
+}
/* count denotes the number of new completions we have seen */
static void bnx2x_cnic_sp_post(struct bnx2x *bp, int count)
@@ -9929,23 +10615,22 @@
u16 type = (le16_to_cpu(bp->cnic_kwq_cons->hdr.type)
& SPE_HDR_CONN_TYPE) >>
SPE_HDR_CONN_TYPE_SHIFT;
+ u8 cmd = (le32_to_cpu(bp->cnic_kwq_cons->hdr.conn_and_cmd_data)
+ >> SPE_HDR_CMD_ID_SHIFT) & 0xff;
/* Set validation for iSCSI L2 client before sending SETUP
* ramrod
*/
if (type == ETH_CONNECTION_TYPE) {
- u8 cmd = (le32_to_cpu(bp->cnic_kwq_cons->
- hdr.conn_and_cmd_data) >>
- SPE_HDR_CMD_ID_SHIFT) & 0xff;
-
if (cmd == RAMROD_CMD_ID_ETH_CLIENT_SETUP)
- bnx2x_set_ctx_validation(&bp->context.
- vcxt[BNX2X_ISCSI_ETH_CID].eth,
- HW_CID(bp, BNX2X_ISCSI_ETH_CID));
+ bnx2x_set_ctx_validation(bp, &bp->context.
+ vcxt[BNX2X_ISCSI_ETH_CID].eth,
+ BNX2X_ISCSI_ETH_CID);
}
- /* There may be not more than 8 L2 and not more than 8 L5 SPEs
- * We also check that the number of outstanding
+ /*
+ * There may be not more than 8 L2, not more than 8 L5 SPEs
+ * and in the air. We also check that number of outstanding
* COMMON ramrods is not more than the EQ and SPQ can
* accommodate.
*/
@@ -10071,18 +10756,61 @@
return bnx2x_cnic_ctl_send(bp, &ctl);
}
-static void bnx2x_cnic_cfc_comp(struct bnx2x *bp, int cid)
+static void bnx2x_cnic_cfc_comp(struct bnx2x *bp, int cid, u8 err)
{
- struct cnic_ctl_info ctl;
+ struct cnic_ctl_info ctl = {0};
/* first we tell CNIC and only then we count this as a completion */
ctl.cmd = CNIC_CTL_COMPLETION_CMD;
ctl.data.comp.cid = cid;
+ ctl.data.comp.error = err;
bnx2x_cnic_ctl_send_bh(bp, &ctl);
bnx2x_cnic_sp_post(bp, 0);
}
+
+/* Called with netif_addr_lock_bh() taken.
+ * Sets an rx_mode config for an iSCSI ETH client.
+ * Doesn't block.
+ * Completion should be checked outside.
+ */
+static void bnx2x_set_iscsi_eth_rx_mode(struct bnx2x *bp, bool start)
+{
+ unsigned long accept_flags = 0, ramrod_flags = 0;
+ u8 cl_id = bnx2x_cnic_eth_cl_id(bp, BNX2X_ISCSI_ETH_CL_ID_IDX);
+ int sched_state = BNX2X_FILTER_ISCSI_ETH_STOP_SCHED;
+
+ if (start) {
+ /* Start accepting on iSCSI L2 ring. Accept all multicasts
+ * because it's the only way for UIO Queue to accept
+ * multicasts (in non-promiscuous mode only one Queue per
+ * function will receive multicast packets (leading in our
+ * case).
+ */
+ __set_bit(BNX2X_ACCEPT_UNICAST, &accept_flags);
+ __set_bit(BNX2X_ACCEPT_ALL_MULTICAST, &accept_flags);
+ __set_bit(BNX2X_ACCEPT_BROADCAST, &accept_flags);
+ __set_bit(BNX2X_ACCEPT_ANY_VLAN, &accept_flags);
+
+ /* Clear STOP_PENDING bit if START is requested */
+ clear_bit(BNX2X_FILTER_ISCSI_ETH_STOP_SCHED, &bp->sp_state);
+
+ sched_state = BNX2X_FILTER_ISCSI_ETH_START_SCHED;
+ } else
+ /* Clear START_PENDING bit if STOP is requested */
+ clear_bit(BNX2X_FILTER_ISCSI_ETH_START_SCHED, &bp->sp_state);
+
+ if (test_bit(BNX2X_FILTER_RX_MODE_PENDING, &bp->sp_state))
+ set_bit(sched_state, &bp->sp_state);
+ else {
+ __set_bit(RAMROD_RX, &ramrod_flags);
+ bnx2x_set_q_rx_mode(bp, cl_id, 0, accept_flags, 0,
+ ramrod_flags);
+ }
+}
+
+
static int bnx2x_drv_ctl(struct net_device *dev, struct drv_ctl_info *ctl)
{
struct bnx2x *bp = netdev_priv(dev);
@@ -10106,45 +10834,65 @@
/* rtnl_lock is held. */
case DRV_CTL_START_L2_CMD: {
- u32 cli = ctl->data.ring.client_id;
+ struct cnic_eth_dev *cp = &bp->cnic_eth_dev;
+ unsigned long sp_bits = 0;
- /* Clear FCoE FIP and ALL ENODE MACs addresses first */
- bnx2x_del_fcoe_eth_macs(bp);
+ /* Configure the iSCSI classification object */
+ bnx2x_init_mac_obj(bp, &bp->iscsi_l2_mac_obj,
+ cp->iscsi_l2_client_id,
+ cp->iscsi_l2_cid, BP_FUNC(bp),
+ bnx2x_sp(bp, mac_rdata),
+ bnx2x_sp_mapping(bp, mac_rdata),
+ BNX2X_FILTER_MAC_PENDING,
+ &bp->sp_state, BNX2X_OBJ_TYPE_RX,
+ &bp->macs_pool);
/* Set iSCSI MAC address */
- bnx2x_set_iscsi_eth_mac_addr(bp, 1);
+ rc = bnx2x_set_iscsi_eth_mac_addr(bp);
+ if (rc)
+ break;
mmiowb();
barrier();
- /* Start accepting on iSCSI L2 ring. Accept all multicasts
- * because it's the only way for UIO Client to accept
- * multicasts (in non-promiscuous mode only one Client per
- * function will receive multicast packets (leading in our
- * case).
- */
- bnx2x_rxq_set_mac_filters(bp, cli,
- BNX2X_ACCEPT_UNICAST |
- BNX2X_ACCEPT_BROADCAST |
- BNX2X_ACCEPT_ALL_MULTICAST);
- storm_memset_mac_filters(bp, &bp->mac_filters, BP_FUNC(bp));
+ /* Start accepting on iSCSI L2 ring */
+
+ netif_addr_lock_bh(dev);
+ bnx2x_set_iscsi_eth_rx_mode(bp, true);
+ netif_addr_unlock_bh(dev);
+
+ /* bits to wait on */
+ __set_bit(BNX2X_FILTER_RX_MODE_PENDING, &sp_bits);
+ __set_bit(BNX2X_FILTER_ISCSI_ETH_START_SCHED, &sp_bits);
+
+ if (!bnx2x_wait_sp_comp(bp, sp_bits))
+ BNX2X_ERR("rx_mode completion timed out!\n");
break;
}
/* rtnl_lock is held. */
case DRV_CTL_STOP_L2_CMD: {
- u32 cli = ctl->data.ring.client_id;
+ unsigned long sp_bits = 0;
/* Stop accepting on iSCSI L2 ring */
- bnx2x_rxq_set_mac_filters(bp, cli, BNX2X_ACCEPT_NONE);
- storm_memset_mac_filters(bp, &bp->mac_filters, BP_FUNC(bp));
+ netif_addr_lock_bh(dev);
+ bnx2x_set_iscsi_eth_rx_mode(bp, false);
+ netif_addr_unlock_bh(dev);
+
+ /* bits to wait on */
+ __set_bit(BNX2X_FILTER_RX_MODE_PENDING, &sp_bits);
+ __set_bit(BNX2X_FILTER_ISCSI_ETH_STOP_SCHED, &sp_bits);
+
+ if (!bnx2x_wait_sp_comp(bp, sp_bits))
+ BNX2X_ERR("rx_mode completion timed out!\n");
mmiowb();
barrier();
/* Unset iSCSI L2 MAC */
- bnx2x_set_iscsi_eth_mac_addr(bp, 0);
+ rc = bnx2x_del_all_macs(bp, &bp->iscsi_l2_mac_obj,
+ BNX2X_ISCSI_ETH_MAC, true);
break;
}
case DRV_CTL_RET_L2_SPQ_CREDIT_CMD: {
@@ -10156,11 +10904,6 @@
break;
}
- case DRV_CTL_ISCSI_STOPPED_CMD: {
- bnx2x_dcbx_set_params(bp, BNX2X_DCBX_STATE_ISCSI_STOPPED);
- break;
- }
-
default:
BNX2X_ERR("unknown command %x\n", ctl->cmd);
rc = -EINVAL;
@@ -10181,13 +10924,13 @@
cp->drv_state &= ~CNIC_DRV_STATE_USING_MSIX;
cp->irq_arr[0].irq_flags &= ~CNIC_IRQ_FL_MSIX;
}
- if (CHIP_IS_E2(bp))
+ if (!CHIP_IS_E1x(bp))
cp->irq_arr[0].status_blk = (void *)bp->cnic_sb.e2_sb;
else
cp->irq_arr[0].status_blk = (void *)bp->cnic_sb.e1x_sb;
- cp->irq_arr[0].status_blk_num = CNIC_SB_ID(bp);
- cp->irq_arr[0].status_blk_num2 = CNIC_IGU_SB_ID(bp);
+ cp->irq_arr[0].status_blk_num = bnx2x_cnic_fw_sb_id(bp);
+ cp->irq_arr[0].status_blk_num2 = bnx2x_cnic_igu_sb_id(bp);
cp->irq_arr[1].status_blk = bp->def_status_blk;
cp->irq_arr[1].status_blk_num = DEF_SB_ID;
cp->irq_arr[1].status_blk_num2 = DEF_SB_IGU_ID;
@@ -10204,9 +10947,6 @@
if (ops == NULL)
return -EINVAL;
- if (atomic_read(&bp->intr_sem) != 0)
- return -EBUSY;
-
bp->cnic_kwq = kzalloc(PAGE_SIZE, GFP_KERNEL);
if (!bp->cnic_kwq)
return -ENOMEM;
@@ -10221,7 +10961,7 @@
bp->cnic_data = data;
cp->num_irq = 0;
- cp->drv_state = CNIC_DRV_STATE_REGD;
+ cp->drv_state |= CNIC_DRV_STATE_REGD;
cp->iro_arr = bp->iro_arr;
bnx2x_setup_cnic_irq_info(bp);
@@ -10275,8 +11015,8 @@
cp->drv_register_cnic = bnx2x_register_cnic;
cp->drv_unregister_cnic = bnx2x_unregister_cnic;
cp->fcoe_init_cid = BNX2X_FCOE_ETH_CID;
- cp->iscsi_l2_client_id = BNX2X_ISCSI_ETH_CL_ID +
- BP_E1HVN(bp) * NONE_ETH_CONTEXT_USE;
+ cp->iscsi_l2_client_id =
+ bnx2x_cnic_eth_cl_id(bp, BNX2X_ISCSI_ETH_CL_ID_IDX);
cp->iscsi_l2_cid = BNX2X_ISCSI_ETH_CID;
if (NO_ISCSI_OOO(bp))
diff --git a/drivers/net/bnx2x/bnx2x_reg.h b/drivers/net/bnx2x/bnx2x_reg.h
index 86bba25..005c05a 100644
--- a/drivers/net/bnx2x/bnx2x_reg.h
+++ b/drivers/net/bnx2x/bnx2x_reg.h
@@ -54,16 +54,20 @@
/* [RW 10] The number of free blocks below which the full signal to class 0
* is asserted */
#define BRB1_REG_FULL_0_XOFF_THRESHOLD_0 0x601d0
-/* [RW 10] The number of free blocks above which the full signal to class 0
+#define BRB1_REG_FULL_0_XOFF_THRESHOLD_1 0x60230
+/* [RW 11] The number of free blocks above which the full signal to class 0
* is de-asserted */
#define BRB1_REG_FULL_0_XON_THRESHOLD_0 0x601d4
-/* [RW 10] The number of free blocks below which the full signal to class 1
+#define BRB1_REG_FULL_0_XON_THRESHOLD_1 0x60234
+/* [RW 11] The number of free blocks below which the full signal to class 1
* is asserted */
#define BRB1_REG_FULL_1_XOFF_THRESHOLD_0 0x601d8
-/* [RW 10] The number of free blocks above which the full signal to class 1
+#define BRB1_REG_FULL_1_XOFF_THRESHOLD_1 0x60238
+/* [RW 11] The number of free blocks above which the full signal to class 1
* is de-asserted */
#define BRB1_REG_FULL_1_XON_THRESHOLD_0 0x601dc
-/* [RW 10] The number of free blocks below which the full signal to the LB
+#define BRB1_REG_FULL_1_XON_THRESHOLD_1 0x6023c
+/* [RW 11] The number of free blocks below which the full signal to the LB
* port is asserted */
#define BRB1_REG_FULL_LB_XOFF_THRESHOLD 0x601e0
/* [RW 10] The number of free blocks above which the full signal to the LB
@@ -75,15 +79,49 @@
/* [RW 10] The number of free blocks below which the High_llfc signal to
interface #n is asserted. */
#define BRB1_REG_HIGH_LLFC_LOW_THRESHOLD_0 0x6013c
-/* [RW 23] LL RAM data. */
-#define BRB1_REG_LL_RAM 0x61000
+/* [RW 11] The number of blocks guarantied for the LB port */
+#define BRB1_REG_LB_GUARANTIED 0x601ec
+/* [RW 11] The hysteresis on the guarantied buffer space for the Lb port
+ * before signaling XON. */
+#define BRB1_REG_LB_GUARANTIED_HYST 0x60264
+/* [RW 24] LL RAM data. */
+#define BRB1_REG_LL_RAM 0x61000
/* [RW 10] The number of free blocks above which the Low_llfc signal to
interface #n is de-asserted. */
#define BRB1_REG_LOW_LLFC_HIGH_THRESHOLD_0 0x6016c
/* [RW 10] The number of free blocks below which the Low_llfc signal to
interface #n is asserted. */
#define BRB1_REG_LOW_LLFC_LOW_THRESHOLD_0 0x6015c
-/* [RW 10] The number of blocks guarantied for the MAC port */
+/* [RW 11] The number of blocks guarantied for class 0 in MAC 0. The
+ * register is applicable only when per_class_guaranty_mode is set. */
+#define BRB1_REG_MAC_0_CLASS_0_GUARANTIED 0x60244
+/* [RW 11] The hysteresis on the guarantied buffer space for class 0 in MAC
+ * 1 before signaling XON. The register is applicable only when
+ * per_class_guaranty_mode is set. */
+#define BRB1_REG_MAC_0_CLASS_0_GUARANTIED_HYST 0x60254
+/* [RW 11] The number of blocks guarantied for class 1 in MAC 0. The
+ * register is applicable only when per_class_guaranty_mode is set. */
+#define BRB1_REG_MAC_0_CLASS_1_GUARANTIED 0x60248
+/* [RW 11] The hysteresis on the guarantied buffer space for class 1in MAC 0
+ * before signaling XON. The register is applicable only when
+ * per_class_guaranty_mode is set. */
+#define BRB1_REG_MAC_0_CLASS_1_GUARANTIED_HYST 0x60258
+/* [RW 11] The number of blocks guarantied for class 0in MAC1.The register
+ * is applicable only when per_class_guaranty_mode is set. */
+#define BRB1_REG_MAC_1_CLASS_0_GUARANTIED 0x6024c
+/* [RW 11] The hysteresis on the guarantied buffer space for class 0 in MAC
+ * 1 before signaling XON. The register is applicable only when
+ * per_class_guaranty_mode is set. */
+#define BRB1_REG_MAC_1_CLASS_0_GUARANTIED_HYST 0x6025c
+/* [RW 11] The number of blocks guarantied for class 1 in MAC 1. The
+ * register is applicable only when per_class_guaranty_mode is set. */
+#define BRB1_REG_MAC_1_CLASS_1_GUARANTIED 0x60250
+/* [RW 11] The hysteresis on the guarantied buffer space for class 1 in MAC
+ * 1 before signaling XON. The register is applicable only when
+ * per_class_guaranty_mode is set. */
+#define BRB1_REG_MAC_1_CLASS_1_GUARANTIED_HYST 0x60260
+/* [RW 11] The number of blocks guarantied for the MAC port. The register is
+ * applicable only when per_class_guaranty_mode is reset. */
#define BRB1_REG_MAC_GUARANTIED_0 0x601e8
#define BRB1_REG_MAC_GUARANTIED_1 0x60240
/* [R 24] The number of full blocks. */
@@ -100,15 +138,19 @@
/* [RW 10] The number of free blocks below which the pause signal to class 0
* is asserted */
#define BRB1_REG_PAUSE_0_XOFF_THRESHOLD_0 0x601c0
-/* [RW 10] The number of free blocks above which the pause signal to class 0
+#define BRB1_REG_PAUSE_0_XOFF_THRESHOLD_1 0x60220
+/* [RW 11] The number of free blocks above which the pause signal to class 0
* is de-asserted */
#define BRB1_REG_PAUSE_0_XON_THRESHOLD_0 0x601c4
-/* [RW 10] The number of free blocks below which the pause signal to class 1
+#define BRB1_REG_PAUSE_0_XON_THRESHOLD_1 0x60224
+/* [RW 11] The number of free blocks below which the pause signal to class 1
* is asserted */
#define BRB1_REG_PAUSE_1_XOFF_THRESHOLD_0 0x601c8
-/* [RW 10] The number of free blocks above which the pause signal to class 1
+#define BRB1_REG_PAUSE_1_XOFF_THRESHOLD_1 0x60228
+/* [RW 11] The number of free blocks above which the pause signal to class 1
* is de-asserted */
#define BRB1_REG_PAUSE_1_XON_THRESHOLD_0 0x601cc
+#define BRB1_REG_PAUSE_1_XON_THRESHOLD_1 0x6022c
/* [RW 10] Write client 0: De-assert pause threshold. Not Functional */
#define BRB1_REG_PAUSE_HIGH_THRESHOLD_0 0x60078
#define BRB1_REG_PAUSE_HIGH_THRESHOLD_1 0x6007c
@@ -422,6 +464,7 @@
#define CFC_REG_NUM_LCIDS_ALLOC 0x104020
/* [R 9] Number of Arriving LCIDs in Link List Block */
#define CFC_REG_NUM_LCIDS_ARRIVING 0x104004
+#define CFC_REG_NUM_LCIDS_INSIDE_PF 0x104120
/* [R 9] Number of Leaving LCIDs in Link List Block */
#define CFC_REG_NUM_LCIDS_LEAVING 0x104018
#define CFC_REG_WEAK_ENABLE_PF 0x104124
@@ -783,6 +826,7 @@
/* [RW 3] The number of simultaneous outstanding requests to Context Fetch
Interface. */
#define DORQ_REG_OUTST_REQ 0x17003c
+#define DORQ_REG_PF_USAGE_CNT 0x1701d0
#define DORQ_REG_REGN 0x170038
/* [R 4] Current value of response A counter credit. Initial credit is
configured through write to ~dorq_registers_rsp_init_crd.rsp_init_crd
@@ -802,10 +846,12 @@
/* [RW 28] TCM Header when both ULP and TCP context is loaded. */
#define DORQ_REG_SHRT_CMHEAD 0x170054
#define HC_CONFIG_0_REG_ATTN_BIT_EN_0 (0x1<<4)
+#define HC_CONFIG_0_REG_BLOCK_DISABLE_0 (0x1<<0)
#define HC_CONFIG_0_REG_INT_LINE_EN_0 (0x1<<3)
#define HC_CONFIG_0_REG_MSI_ATTN_EN_0 (0x1<<7)
#define HC_CONFIG_0_REG_MSI_MSIX_INT_EN_0 (0x1<<2)
-#define HC_CONFIG_0_REG_SINGLE_ISR_EN_0 (0x1<<1)
+#define HC_CONFIG_0_REG_SINGLE_ISR_EN_0 (0x1<<1)
+#define HC_CONFIG_1_REG_BLOCK_DISABLE_1 (0x1<<0)
#define HC_REG_AGG_INT_0 0x108050
#define HC_REG_AGG_INT_1 0x108054
#define HC_REG_ATTN_BIT 0x108120
@@ -844,6 +890,7 @@
#define HC_REG_VQID_0 0x108008
#define HC_REG_VQID_1 0x10800c
#define IGU_BLOCK_CONFIGURATION_REG_BACKWARD_COMP_EN (0x1<<1)
+#define IGU_BLOCK_CONFIGURATION_REG_BLOCK_ENABLE (0x1<<0)
#define IGU_REG_ATTENTION_ACK_BITS 0x130108
/* [R 4] Debug: attn_fsm */
#define IGU_REG_ATTN_FSM 0x130054
@@ -933,6 +980,14 @@
* clear; 1 = set. Data valid only in addresses 0-4. all the rest are zero. */
#define IGU_REG_WRITE_DONE_PENDING 0x130480
#define MCP_A_REG_MCPR_SCRATCH 0x3a0000
+#define MCP_REG_MCPR_CPU_PROGRAM_COUNTER 0x8501c
+#define MCP_REG_MCPR_GP_INPUTS 0x800c0
+#define MCP_REG_MCPR_GP_OENABLE 0x800c8
+#define MCP_REG_MCPR_GP_OUTPUTS 0x800c4
+#define MCP_REG_MCPR_IMC_COMMAND 0x85900
+#define MCP_REG_MCPR_IMC_DATAREG0 0x85920
+#define MCP_REG_MCPR_IMC_SLAVE_CONTROL 0x85904
+#define MCP_REG_MCPR_CPU_PROGRAM_COUNTER 0x8501c
#define MCP_REG_MCPR_NVM_ACCESS_ENABLE 0x86424
#define MCP_REG_MCPR_NVM_ADDR 0x8640c
#define MCP_REG_MCPR_NVM_CFG4 0x8642c
@@ -1429,11 +1484,37 @@
/* [RW 1] e1hmf for WOL. If clr WOL signal o the PXP will be send on bit 0
only. */
#define MISC_REG_E1HMF_MODE 0xa5f8
+/* [R 1] Status of four port mode path swap input pin. */
+#define MISC_REG_FOUR_PORT_PATH_SWAP 0xa75c
+/* [RW 2] 4 port path swap overwrite.[0] - Overwrite control; if it is 0 -
+ the path_swap output is equal to 4 port mode path swap input pin; if it
+ is 1 - the path_swap output is equal to bit[1] of this register; [1] -
+ Overwrite value. If bit[0] of this register is 1 this is the value that
+ receives the path_swap output. Reset on Hard reset. */
+#define MISC_REG_FOUR_PORT_PATH_SWAP_OVWR 0xa738
+/* [R 1] Status of 4 port mode port swap input pin. */
+#define MISC_REG_FOUR_PORT_PORT_SWAP 0xa754
+/* [RW 2] 4 port port swap overwrite.[0] - Overwrite control; if it is 0 -
+ the port_swap output is equal to 4 port mode port swap input pin; if it
+ is 1 - the port_swap output is equal to bit[1] of this register; [1] -
+ Overwrite value. If bit[0] of this register is 1 this is the value that
+ receives the port_swap output. Reset on Hard reset. */
+#define MISC_REG_FOUR_PORT_PORT_SWAP_OVWR 0xa734
/* [RW 32] Debug only: spare RW register reset by core reset */
#define MISC_REG_GENERIC_CR_0 0xa460
#define MISC_REG_GENERIC_CR_1 0xa464
/* [RW 32] Debug only: spare RW register reset by por reset */
#define MISC_REG_GENERIC_POR_1 0xa474
+/* [RW 32] Bit[0]: EPIO MODE SEL: Setting this bit to 1 will allow SW/FW to
+ use all of the 32 Extended GPIO pins. Without setting this bit; an EPIO
+ can not be configured as an output. Each output has its output enable in
+ the MCP register space; but this bit needs to be set to make use of that.
+ Bit[3:1] spare. Bit[4]: WCVTMON_PWRDN: Powerdown for Warpcore VTMON. When
+ set to 1 - Powerdown. Bit[5]: WCVTMON_RESETB: Reset for Warpcore VTMON.
+ When set to 0 - vTMON is in reset. Bit[6]: setting this bit will change
+ the i/o to an output and will drive the TimeSync output. Bit[31:7]:
+ spare. Global register. Reset by hard reset. */
+#define MISC_REG_GEN_PURP_HWG 0xa9a0
/* [RW 32] GPIO. [31-28] FLOAT port 0; [27-24] FLOAT port 0; When any of
these bits is written as a '1'; the corresponding SPIO bit will turn off
it's drivers and become an input. This is the reset state of all GPIO
@@ -1636,6 +1717,14 @@
in this register. address 0 - timer 1; address 1 - timer 2, ... address 7 -
timer 8 */
#define MISC_REG_SW_TIMER_VAL 0xa5c0
+/* [R 1] Status of two port mode path swap input pin. */
+#define MISC_REG_TWO_PORT_PATH_SWAP 0xa758
+/* [RW 2] 2 port swap overwrite.[0] - Overwrite control; if it is 0 - the
+ path_swap output is equal to 2 port mode path swap input pin; if it is 1
+ - the path_swap output is equal to bit[1] of this register; [1] -
+ Overwrite value. If bit[0] of this register is 1 this is the value that
+ receives the path_swap output. Reset on Hard reset. */
+#define MISC_REG_TWO_PORT_PATH_SWAP_OVWR 0xa72c
/* [RW 1] Set by the MCP to remember if one or more of the drivers is/are
loaded; 0-prepare; -unprepare */
#define MISC_REG_UNPREPARED 0xa424
@@ -1644,6 +1733,36 @@
#define NIG_LLH0_BRB1_DRV_MASK_REG_LLH0_BRB1_DRV_MASK_NO_VLAN (0x1<<4)
#define NIG_LLH0_BRB1_DRV_MASK_REG_LLH0_BRB1_DRV_MASK_UNCST (0x1<<2)
#define NIG_LLH0_BRB1_DRV_MASK_REG_LLH0_BRB1_DRV_MASK_VLAN (0x1<<3)
+/* [RW 5] MDIO PHY Address. The WC uses this address to determine whether or
+ * not it is the recipient of the message on the MDIO interface. The value
+ * is compared to the value on ctrl_md_devad. Drives output
+ * misc_xgxs0_phy_addr. Global register. */
+#define MISC_REG_WC0_CTRL_PHY_ADDR 0xa9cc
+/* [RW 2] XMAC Core port mode. Indicates the number of ports on the system
+ side. This should be less than or equal to phy_port_mode; if some of the
+ ports are not used. This enables reduction of frequency on the core side.
+ This is a strap input for the XMAC_MP core. 00 - Single Port Mode; 01 -
+ Dual Port Mode; 10 - Tri Port Mode; 11 - Quad Port Mode. This is a strap
+ input for the XMAC_MP core; and should be changed only while reset is
+ held low. Reset on Hard reset. */
+#define MISC_REG_XMAC_CORE_PORT_MODE 0xa964
+/* [RW 2] XMAC PHY port mode. Indicates the number of ports on the Warp
+ Core. This is a strap input for the XMAC_MP core. 00 - Single Port Mode;
+ 01 - Dual Port Mode; 1x - Quad Port Mode; This is a strap input for the
+ XMAC_MP core; and should be changed only while reset is held low. Reset
+ on Hard reset. */
+#define MISC_REG_XMAC_PHY_PORT_MODE 0xa960
+/* [RW 32] 1 [47] Packet Size = 64 Write to this register write bits 31:0.
+ * Reads from this register will clear bits 31:0. */
+#define MSTAT_REG_RX_STAT_GR64_LO 0x200
+/* [RW 32] 1 [00] Tx Good Packet Count Write to this register write bits
+ * 31:0. Reads from this register will clear bits 31:0. */
+#define MSTAT_REG_TX_STAT_GTXPOK_LO 0
+#define NIG_LLH0_BRB1_DRV_MASK_REG_LLH0_BRB1_DRV_MASK_BRCST (0x1<<0)
+#define NIG_LLH0_BRB1_DRV_MASK_REG_LLH0_BRB1_DRV_MASK_MLCST (0x1<<1)
+#define NIG_LLH0_BRB1_DRV_MASK_REG_LLH0_BRB1_DRV_MASK_NO_VLAN (0x1<<4)
+#define NIG_LLH0_BRB1_DRV_MASK_REG_LLH0_BRB1_DRV_MASK_UNCST (0x1<<2)
+#define NIG_LLH0_BRB1_DRV_MASK_REG_LLH0_BRB1_DRV_MASK_VLAN (0x1<<3)
#define NIG_LLH0_XCM_MASK_REG_LLH0_XCM_MASK_BCN (0x1<<0)
#define NIG_LLH1_XCM_MASK_REG_LLH1_XCM_MASK_BCN (0x1<<0)
#define NIG_MASK_INTERRUPT_PORT0_REG_MASK_EMAC0_MISC_MI_INT (0x1<<0)
@@ -1837,6 +1956,10 @@
#define NIG_REG_LLH1_FUNC_MEM 0x161c0
#define NIG_REG_LLH1_FUNC_MEM_ENABLE 0x16160
#define NIG_REG_LLH1_FUNC_MEM_SIZE 16
+/* [RW 1] When this bit is set; the LLH will classify the packet before
+ * sending it to the BRB or calculating WoL on it. This bit controls port 1
+ * only. The legacy llh_multi_function_mode bit controls port 0. */
+#define NIG_REG_LLH1_MF_MODE 0x18614
/* [RW 8] init credit counter for port1 in LLH */
#define NIG_REG_LLH1_XCM_INIT_CREDIT 0x10564
#define NIG_REG_LLH1_XCM_MASK 0x10134
@@ -1858,11 +1981,25 @@
/* [R 32] Interrupt register #0 read */
#define NIG_REG_NIG_INT_STS_0 0x103b0
#define NIG_REG_NIG_INT_STS_1 0x103c0
+/* [R 32] Legacy E1 and E1H location for parity error mask register. */
+#define NIG_REG_NIG_PRTY_MASK 0x103dc
+/* [RW 32] Parity mask register #0 read/write */
+#define NIG_REG_NIG_PRTY_MASK_0 0x183c8
+#define NIG_REG_NIG_PRTY_MASK_1 0x183d8
/* [R 32] Legacy E1 and E1H location for parity error status register. */
#define NIG_REG_NIG_PRTY_STS 0x103d0
/* [R 32] Parity register #0 read */
#define NIG_REG_NIG_PRTY_STS_0 0x183bc
#define NIG_REG_NIG_PRTY_STS_1 0x183cc
+/* [R 32] Legacy E1 and E1H location for parity error status clear register. */
+#define NIG_REG_NIG_PRTY_STS_CLR 0x103d4
+/* [RC 32] Parity register #0 read clear */
+#define NIG_REG_NIG_PRTY_STS_CLR_0 0x183c0
+#define NIG_REG_NIG_PRTY_STS_CLR_1 0x183d0
+#define MCPR_IMC_COMMAND_ENABLE (1L<<31)
+#define MCPR_IMC_COMMAND_IMC_STATUS_BITSHIFT 16
+#define MCPR_IMC_COMMAND_OPERATION_BITSHIFT 28
+#define MCPR_IMC_COMMAND_TRANSFER_ADDRESS_BITSHIFT 8
/* [RW 6] Bit-map indicating which L2 hdrs may appear after the basic
* Ethernet header. */
#define NIG_REG_P0_HDRS_AFTER_BASIC 0x18038
@@ -1872,6 +2009,12 @@
#define NIG_REG_P0_HWPFC_ENABLE 0x18078
#define NIG_REG_P0_LLH_FUNC_MEM2 0x18480
#define NIG_REG_P0_LLH_FUNC_MEM2_ENABLE 0x18440
+/* [RW 1] Input enable for RX MAC interface. */
+#define NIG_REG_P0_MAC_IN_EN 0x185ac
+/* [RW 1] Output enable for TX MAC interface */
+#define NIG_REG_P0_MAC_OUT_EN 0x185b0
+/* [RW 1] Output enable for TX PAUSE signal to the MAC. */
+#define NIG_REG_P0_MAC_PAUSE_OUT_EN 0x185b4
/* [RW 32] Eight 4-bit configurations for specifying which COS (0-15 for
* future expansion) each priorty is to be mapped to. Bits 3:0 specify the
* COS for priority 0. Bits 31:28 specify the COS for priority 7. The 3-bit
@@ -1888,11 +2031,52 @@
* than one bit may be set; allowing multiple priorities to be mapped to one
* COS. */
#define NIG_REG_P0_RX_COS1_PRIORITY_MASK 0x1805c
+/* [RW 16] Bit-map indicating which SAFC/PFC priorities to map to COS 2. A
+ * priority is mapped to COS 2 when the corresponding mask bit is 1. More
+ * than one bit may be set; allowing multiple priorities to be mapped to one
+ * COS. */
+#define NIG_REG_P0_RX_COS2_PRIORITY_MASK 0x186b0
+/* [RW 16] Bit-map indicating which SAFC/PFC priorities to map to COS 3. A
+ * priority is mapped to COS 3 when the corresponding mask bit is 1. More
+ * than one bit may be set; allowing multiple priorities to be mapped to one
+ * COS. */
+#define NIG_REG_P0_RX_COS3_PRIORITY_MASK 0x186b4
+/* [RW 16] Bit-map indicating which SAFC/PFC priorities to map to COS 4. A
+ * priority is mapped to COS 4 when the corresponding mask bit is 1. More
+ * than one bit may be set; allowing multiple priorities to be mapped to one
+ * COS. */
+#define NIG_REG_P0_RX_COS4_PRIORITY_MASK 0x186b8
+/* [RW 16] Bit-map indicating which SAFC/PFC priorities to map to COS 5. A
+ * priority is mapped to COS 5 when the corresponding mask bit is 1. More
+ * than one bit may be set; allowing multiple priorities to be mapped to one
+ * COS. */
+#define NIG_REG_P0_RX_COS5_PRIORITY_MASK 0x186bc
+/* [R 1] RX FIFO for receiving data from MAC is empty. */
/* [RW 15] Specify which of the credit registers the client is to be mapped
* to. Bits[2:0] are for client 0; bits [14:12] are for client 4. For
* clients that are not subject to WFQ credit blocking - their
* specifications here are not used. */
#define NIG_REG_P0_TX_ARB_CLIENT_CREDIT_MAP 0x180f0
+/* [RW 32] Specify which of the credit registers the client is to be mapped
+ * to. This register specifies bits 31:0 of the 36-bit value. Bits[3:0] are
+ * for client 0; bits [35:32] are for client 8. For clients that are not
+ * subject to WFQ credit blocking - their specifications here are not used.
+ * This is a new register (with 2_) added in E3 B0 to accommodate the 9
+ * input clients to ETS arbiter. The reset default is set for management and
+ * debug to use credit registers 6, 7, and 8, respectively, and COSes 0-5 to
+ * use credit registers 0-5 respectively (0x543210876). Note that credit
+ * registers can not be shared between clients. */
+#define NIG_REG_P0_TX_ARB_CLIENT_CREDIT_MAP2_LSB 0x18688
+/* [RW 4] Specify which of the credit registers the client is to be mapped
+ * to. This register specifies bits 35:32 of the 36-bit value. Bits[3:0] are
+ * for client 0; bits [35:32] are for client 8. For clients that are not
+ * subject to WFQ credit blocking - their specifications here are not used.
+ * This is a new register (with 2_) added in E3 B0 to accommodate the 9
+ * input clients to ETS arbiter. The reset default is set for management and
+ * debug to use credit registers 6, 7, and 8, respectively, and COSes 0-5 to
+ * use credit registers 0-5 respectively (0x543210876). Note that credit
+ * registers can not be shared between clients. */
+#define NIG_REG_P0_TX_ARB_CLIENT_CREDIT_MAP2_MSB 0x1868c
/* [RW 5] Specify whether the client competes directly in the strict
* priority arbiter. The bits are mapped according to client ID (client IDs
* are defined in tx_arb_priority_client). Default value is set to enable
@@ -1907,10 +2091,24 @@
* reach. */
#define NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_0 0x1810c
#define NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_1 0x18110
+#define NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_2 0x18114
+#define NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_3 0x18118
+#define NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_4 0x1811c
+#define NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_5 0x186a0
+#define NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_6 0x186a4
+#define NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_7 0x186a8
+#define NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_8 0x186ac
/* [RW 32] Specify the weight (in bytes) to be added to credit register 0
* when it is time to increment. */
#define NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_0 0x180f8
#define NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_1 0x180fc
+#define NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_2 0x18100
+#define NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_3 0x18104
+#define NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_4 0x18108
+#define NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_5 0x18690
+#define NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_6 0x18694
+#define NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_7 0x18698
+#define NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_8 0x1869c
/* [RW 12] Specify the number of strict priority arbitration slots between
* two round-robin arbitration slots to avoid starvation. A value of 0 means
* no strict priority cycles - the strict priority with anti-starvation
@@ -1925,8 +2123,36 @@
* for management at priority 0; debug traffic at priorities 1 and 2; COS0
* traffic at priority 3; and COS1 traffic at priority 4. */
#define NIG_REG_P0_TX_ARB_PRIORITY_CLIENT 0x180e4
+/* [RW 6] Bit-map indicating which L2 hdrs may appear after the basic
+ * Ethernet header. */
+#define NIG_REG_P1_HDRS_AFTER_BASIC 0x1818c
#define NIG_REG_P1_LLH_FUNC_MEM2 0x184c0
#define NIG_REG_P1_LLH_FUNC_MEM2_ENABLE 0x18460
+/* [RW 32] Specify the client number to be assigned to each priority of the
+ * strict priority arbiter. This register specifies bits 31:0 of the 36-bit
+ * value. Priority 0 is the highest priority. Bits [3:0] are for priority 0
+ * client; bits [35-32] are for priority 8 client. The clients are assigned
+ * the following IDs: 0-management; 1-debug traffic from this port; 2-debug
+ * traffic from other port; 3-COS0 traffic; 4-COS1 traffic; 5-COS2 traffic;
+ * 6-COS3 traffic; 7-COS4 traffic; 8-COS5 traffic. The reset value[35:0] is
+ * set to 0x345678021. This is a new register (with 2_) added in E3 B0 to
+ * accommodate the 9 input clients to ETS arbiter. */
+#define NIG_REG_P0_TX_ARB_PRIORITY_CLIENT2_LSB 0x18680
+/* [RW 4] Specify the client number to be assigned to each priority of the
+ * strict priority arbiter. This register specifies bits 35:32 of the 36-bit
+ * value. Priority 0 is the highest priority. Bits [3:0] are for priority 0
+ * client; bits [35-32] are for priority 8 client. The clients are assigned
+ * the following IDs: 0-management; 1-debug traffic from this port; 2-debug
+ * traffic from other port; 3-COS0 traffic; 4-COS1 traffic; 5-COS2 traffic;
+ * 6-COS3 traffic; 7-COS4 traffic; 8-COS5 traffic. The reset value[35:0] is
+ * set to 0x345678021. This is a new register (with 2_) added in E3 B0 to
+ * accommodate the 9 input clients to ETS arbiter. */
+#define NIG_REG_P0_TX_ARB_PRIORITY_CLIENT2_MSB 0x18684
+#define NIG_REG_P1_MAC_IN_EN 0x185c0
+/* [RW 1] Output enable for TX MAC interface */
+#define NIG_REG_P1_MAC_OUT_EN 0x185c4
+/* [RW 1] Output enable for TX PAUSE signal to the MAC. */
+#define NIG_REG_P1_MAC_PAUSE_OUT_EN 0x185c8
/* [RW 32] Eight 4-bit configurations for specifying which COS (0-15 for
* future expansion) each priorty is to be mapped to. Bits 3:0 specify the
* COS for priority 0. Bits 31:28 specify the COS for priority 7. The 3-bit
@@ -1943,6 +2169,105 @@
* than one bit may be set; allowing multiple priorities to be mapped to one
* COS. */
#define NIG_REG_P1_RX_COS1_PRIORITY_MASK 0x181b0
+/* [RW 16] Bit-map indicating which SAFC/PFC priorities to map to COS 2. A
+ * priority is mapped to COS 2 when the corresponding mask bit is 1. More
+ * than one bit may be set; allowing multiple priorities to be mapped to one
+ * COS. */
+#define NIG_REG_P1_RX_COS2_PRIORITY_MASK 0x186f8
+/* [R 1] RX FIFO for receiving data from MAC is empty. */
+#define NIG_REG_P1_RX_MACFIFO_EMPTY 0x1858c
+/* [R 1] TLLH FIFO is empty. */
+#define NIG_REG_P1_TLLH_FIFO_EMPTY 0x18338
+/* [RW 32] Specify which of the credit registers the client is to be mapped
+ * to. This register specifies bits 31:0 of the 36-bit value. Bits[3:0] are
+ * for client 0; bits [35:32] are for client 8. For clients that are not
+ * subject to WFQ credit blocking - their specifications here are not used.
+ * This is a new register (with 2_) added in E3 B0 to accommodate the 9
+ * input clients to ETS arbiter. The reset default is set for management and
+ * debug to use credit registers 6, 7, and 8, respectively, and COSes 0-5 to
+ * use credit registers 0-5 respectively (0x543210876). Note that credit
+ * registers can not be shared between clients. Note also that there are
+ * only COS0-2 in port 1- there is a total of 6 clients in port 1. Only
+ * credit registers 0-5 are valid. This register should be configured
+ * appropriately before enabling WFQ. */
+#define NIG_REG_P1_TX_ARB_CLIENT_CREDIT_MAP2_LSB 0x186e8
+/* [RW 4] Specify which of the credit registers the client is to be mapped
+ * to. This register specifies bits 35:32 of the 36-bit value. Bits[3:0] are
+ * for client 0; bits [35:32] are for client 8. For clients that are not
+ * subject to WFQ credit blocking - their specifications here are not used.
+ * This is a new register (with 2_) added in E3 B0 to accommodate the 9
+ * input clients to ETS arbiter. The reset default is set for management and
+ * debug to use credit registers 6, 7, and 8, respectively, and COSes 0-5 to
+ * use credit registers 0-5 respectively (0x543210876). Note that credit
+ * registers can not be shared between clients. Note also that there are
+ * only COS0-2 in port 1- there is a total of 6 clients in port 1. Only
+ * credit registers 0-5 are valid. This register should be configured
+ * appropriately before enabling WFQ. */
+#define NIG_REG_P1_TX_ARB_CLIENT_CREDIT_MAP2_MSB 0x186ec
+/* [RW 9] Specify whether the client competes directly in the strict
+ * priority arbiter. The bits are mapped according to client ID (client IDs
+ * are defined in tx_arb_priority_client2): 0-management; 1-debug traffic
+ * from this port; 2-debug traffic from other port; 3-COS0 traffic; 4-COS1
+ * traffic; 5-COS2 traffic; 6-COS3 traffic; 7-COS4 traffic; 8-COS5 traffic.
+ * Default value is set to enable strict priorities for all clients. */
+#define NIG_REG_P1_TX_ARB_CLIENT_IS_STRICT 0x18234
+/* [RW 9] Specify whether the client is subject to WFQ credit blocking. The
+ * bits are mapped according to client ID (client IDs are defined in
+ * tx_arb_priority_client2): 0-management; 1-debug traffic from this port;
+ * 2-debug traffic from other port; 3-COS0 traffic; 4-COS1 traffic; 5-COS2
+ * traffic; 6-COS3 traffic; 7-COS4 traffic; 8-COS5 traffic. Default value is
+ * 0 for not using WFQ credit blocking. */
+#define NIG_REG_P1_TX_ARB_CLIENT_IS_SUBJECT2WFQ 0x18238
+#define NIG_REG_P1_TX_ARB_CREDIT_UPPER_BOUND_0 0x18258
+#define NIG_REG_P1_TX_ARB_CREDIT_UPPER_BOUND_1 0x1825c
+#define NIG_REG_P1_TX_ARB_CREDIT_UPPER_BOUND_2 0x18260
+#define NIG_REG_P1_TX_ARB_CREDIT_UPPER_BOUND_3 0x18264
+#define NIG_REG_P1_TX_ARB_CREDIT_UPPER_BOUND_4 0x18268
+#define NIG_REG_P1_TX_ARB_CREDIT_UPPER_BOUND_5 0x186f4
+/* [RW 32] Specify the weight (in bytes) to be added to credit register 0
+ * when it is time to increment. */
+#define NIG_REG_P1_TX_ARB_CREDIT_WEIGHT_0 0x18244
+#define NIG_REG_P1_TX_ARB_CREDIT_WEIGHT_1 0x18248
+#define NIG_REG_P1_TX_ARB_CREDIT_WEIGHT_2 0x1824c
+#define NIG_REG_P1_TX_ARB_CREDIT_WEIGHT_3 0x18250
+#define NIG_REG_P1_TX_ARB_CREDIT_WEIGHT_4 0x18254
+#define NIG_REG_P1_TX_ARB_CREDIT_WEIGHT_5 0x186f0
+/* [RW 12] Specify the number of strict priority arbitration slots between
+ two round-robin arbitration slots to avoid starvation. A value of 0 means
+ no strict priority cycles - the strict priority with anti-starvation
+ arbiter becomes a round-robin arbiter. */
+#define NIG_REG_P1_TX_ARB_NUM_STRICT_ARB_SLOTS 0x18240
+/* [RW 32] Specify the client number to be assigned to each priority of the
+ strict priority arbiter. This register specifies bits 31:0 of the 36-bit
+ value. Priority 0 is the highest priority. Bits [3:0] are for priority 0
+ client; bits [35-32] are for priority 8 client. The clients are assigned
+ the following IDs: 0-management; 1-debug traffic from this port; 2-debug
+ traffic from other port; 3-COS0 traffic; 4-COS1 traffic; 5-COS2 traffic;
+ 6-COS3 traffic; 7-COS4 traffic; 8-COS5 traffic. The reset value[35:0] is
+ set to 0x345678021. This is a new register (with 2_) added in E3 B0 to
+ accommodate the 9 input clients to ETS arbiter. Note that this register
+ is the same as the one for port 0, except that port 1 only has COS 0-2
+ traffic. There is no traffic for COS 3-5 of port 1. */
+#define NIG_REG_P1_TX_ARB_PRIORITY_CLIENT2_LSB 0x186e0
+/* [RW 4] Specify the client number to be assigned to each priority of the
+ strict priority arbiter. This register specifies bits 35:32 of the 36-bit
+ value. Priority 0 is the highest priority. Bits [3:0] are for priority 0
+ client; bits [35-32] are for priority 8 client. The clients are assigned
+ the following IDs: 0-management; 1-debug traffic from this port; 2-debug
+ traffic from other port; 3-COS0 traffic; 4-COS1 traffic; 5-COS2 traffic;
+ 6-COS3 traffic; 7-COS4 traffic; 8-COS5 traffic. The reset value[35:0] is
+ set to 0x345678021. This is a new register (with 2_) added in E3 B0 to
+ accommodate the 9 input clients to ETS arbiter. Note that this register
+ is the same as the one for port 0, except that port 1 only has COS 0-2
+ traffic. There is no traffic for COS 3-5 of port 1. */
+#define NIG_REG_P1_TX_ARB_PRIORITY_CLIENT2_MSB 0x186e4
+/* [R 1] TX FIFO for transmitting data to MAC is empty. */
+#define NIG_REG_P1_TX_MACFIFO_EMPTY 0x18594
+/* [R 1] FIFO empty status of the MCP TX FIFO used for storing MCP packets
+ forwarded to the host. */
+#define NIG_REG_P1_TX_MNG_HOST_FIFO_EMPTY 0x182b8
+/* [RW 32] Specify the upper bound that credit register 0 is allowed to
+ * reach. */
/* [RW 1] Pause enable for port0. This register may get 1 only when
~safc_enable.safc_enable = 0 and ppp_enable.ppp_enable =0 for the same
port */
@@ -2026,12 +2351,45 @@
#define NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_XGXS0_LINK_STATUS_SIZE 18
/* [RW 31] The upper bound of the weight of COS0 in the ETS command arbiter. */
#define PBF_REG_COS0_UPPER_BOUND 0x15c05c
+/* [RW 31] The upper bound of the weight of COS0 in the ETS command arbiter
+ * of port 0. */
+#define PBF_REG_COS0_UPPER_BOUND_P0 0x15c2cc
+/* [RW 31] The upper bound of the weight of COS0 in the ETS command arbiter
+ * of port 1. */
+#define PBF_REG_COS0_UPPER_BOUND_P1 0x15c2e4
/* [RW 31] The weight of COS0 in the ETS command arbiter. */
#define PBF_REG_COS0_WEIGHT 0x15c054
+/* [RW 31] The weight of COS0 in port 0 ETS command arbiter. */
+#define PBF_REG_COS0_WEIGHT_P0 0x15c2a8
+/* [RW 31] The weight of COS0 in port 1 ETS command arbiter. */
+#define PBF_REG_COS0_WEIGHT_P1 0x15c2c0
/* [RW 31] The upper bound of the weight of COS1 in the ETS command arbiter. */
#define PBF_REG_COS1_UPPER_BOUND 0x15c060
/* [RW 31] The weight of COS1 in the ETS command arbiter. */
#define PBF_REG_COS1_WEIGHT 0x15c058
+/* [RW 31] The weight of COS1 in port 0 ETS command arbiter. */
+#define PBF_REG_COS1_WEIGHT_P0 0x15c2ac
+/* [RW 31] The weight of COS1 in port 1 ETS command arbiter. */
+#define PBF_REG_COS1_WEIGHT_P1 0x15c2c4
+/* [RW 31] The weight of COS2 in port 0 ETS command arbiter. */
+#define PBF_REG_COS2_WEIGHT_P0 0x15c2b0
+/* [RW 31] The weight of COS2 in port 1 ETS command arbiter. */
+#define PBF_REG_COS2_WEIGHT_P1 0x15c2c8
+/* [RW 31] The weight of COS3 in port 0 ETS command arbiter. */
+#define PBF_REG_COS3_WEIGHT_P0 0x15c2b4
+/* [RW 31] The weight of COS4 in port 0 ETS command arbiter. */
+#define PBF_REG_COS4_WEIGHT_P0 0x15c2b8
+/* [RW 31] The weight of COS5 in port 0 ETS command arbiter. */
+#define PBF_REG_COS5_WEIGHT_P0 0x15c2bc
+/* [R 11] Current credit for the LB queue in the tx port buffers in 16 byte
+ * lines. */
+#define PBF_REG_CREDIT_LB_Q 0x140338
+/* [R 11] Current credit for queue 0 in the tx port buffers in 16 byte
+ * lines. */
+#define PBF_REG_CREDIT_Q0 0x14033c
+/* [R 11] Current credit for queue 1 in the tx port buffers in 16 byte
+ * lines. */
+#define PBF_REG_CREDIT_Q1 0x140340
/* [RW 1] Disable processing further tasks from port 0 (after ending the
current task in process). */
#define PBF_REG_DISABLE_NEW_TASK_PROC_P0 0x14005c
@@ -2042,6 +2400,52 @@
current task in process). */
#define PBF_REG_DISABLE_NEW_TASK_PROC_P4 0x14006c
#define PBF_REG_DISABLE_PF 0x1402e8
+/* [RW 18] For port 0: For each client that is subject to WFQ (the
+ * corresponding bit is 1); indicates to which of the credit registers this
+ * client is mapped. For clients which are not credit blocked; their mapping
+ * is dont care. */
+#define PBF_REG_ETS_ARB_CLIENT_CREDIT_MAP_P0 0x15c288
+/* [RW 9] For port 1: For each client that is subject to WFQ (the
+ * corresponding bit is 1); indicates to which of the credit registers this
+ * client is mapped. For clients which are not credit blocked; their mapping
+ * is dont care. */
+#define PBF_REG_ETS_ARB_CLIENT_CREDIT_MAP_P1 0x15c28c
+/* [RW 6] For port 0: Bit per client to indicate if the client competes in
+ * the strict priority arbiter directly (corresponding bit = 1); or first
+ * goes to the RR arbiter (corresponding bit = 0); and then competes in the
+ * lowest priority in the strict-priority arbiter. */
+#define PBF_REG_ETS_ARB_CLIENT_IS_STRICT_P0 0x15c278
+/* [RW 3] For port 1: Bit per client to indicate if the client competes in
+ * the strict priority arbiter directly (corresponding bit = 1); or first
+ * goes to the RR arbiter (corresponding bit = 0); and then competes in the
+ * lowest priority in the strict-priority arbiter. */
+#define PBF_REG_ETS_ARB_CLIENT_IS_STRICT_P1 0x15c27c
+/* [RW 6] For port 0: Bit per client to indicate if the client is subject to
+ * WFQ credit blocking (corresponding bit = 1). */
+#define PBF_REG_ETS_ARB_CLIENT_IS_SUBJECT2WFQ_P0 0x15c280
+/* [RW 3] For port 0: Bit per client to indicate if the client is subject to
+ * WFQ credit blocking (corresponding bit = 1). */
+#define PBF_REG_ETS_ARB_CLIENT_IS_SUBJECT2WFQ_P1 0x15c284
+/* [RW 16] For port 0: The number of strict priority arbitration slots
+ * between 2 RR arbitration slots. A value of 0 means no strict priority
+ * cycles; i.e. the strict-priority w/ anti-starvation arbiter is a RR
+ * arbiter. */
+#define PBF_REG_ETS_ARB_NUM_STRICT_ARB_SLOTS_P0 0x15c2a0
+/* [RW 16] For port 1: The number of strict priority arbitration slots
+ * between 2 RR arbitration slots. A value of 0 means no strict priority
+ * cycles; i.e. the strict-priority w/ anti-starvation arbiter is a RR
+ * arbiter. */
+#define PBF_REG_ETS_ARB_NUM_STRICT_ARB_SLOTS_P1 0x15c2a4
+/* [RW 18] For port 0: Indicates which client is connected to each priority
+ * in the strict-priority arbiter. Priority 0 is the highest priority, and
+ * priority 5 is the lowest; to which the RR output is connected to (this is
+ * not configurable). */
+#define PBF_REG_ETS_ARB_PRIORITY_CLIENT_P0 0x15c270
+/* [RW 9] For port 1: Indicates which client is connected to each priority
+ * in the strict-priority arbiter. Priority 0 is the highest priority, and
+ * priority 5 is the lowest; to which the RR output is connected to (this is
+ * not configurable). */
+#define PBF_REG_ETS_ARB_PRIORITY_CLIENT_P1 0x15c274
/* [RW 1] Indicates that ETS is performed between the COSes in the command
* arbiter. If reset strict priority w/ anti-starvation will be performed
* w/o WFQ. */
@@ -2049,14 +2453,25 @@
/* [RW 6] Bit-map indicating which L2 hdrs may appear after the basic
* Ethernet header. */
#define PBF_REG_HDRS_AFTER_BASIC 0x15c0a8
-/* [RW 1] Indicates which COS is conncted to the highest priority in the
- * command arbiter. */
+/* [RW 6] Bit-map indicating which L2 hdrs may appear after L2 tag 0 */
+#define PBF_REG_HDRS_AFTER_TAG_0 0x15c0b8
+/* [R 1] Removed for E3 B0 - Indicates which COS is conncted to the highest
+ * priority in the command arbiter. */
#define PBF_REG_HIGH_PRIORITY_COS_NUM 0x15c04c
#define PBF_REG_IF_ENABLE_REG 0x140044
/* [RW 1] Init bit. When set the initial credits are copied to the credit
registers (except the port credits). Should be set and then reset after
the configuration of the block has ended. */
#define PBF_REG_INIT 0x140000
+/* [RW 11] Initial credit for the LB queue in the tx port buffers in 16 byte
+ * lines. */
+#define PBF_REG_INIT_CRD_LB_Q 0x15c248
+/* [RW 11] Initial credit for queue 0 in the tx port buffers in 16 byte
+ * lines. */
+#define PBF_REG_INIT_CRD_Q0 0x15c230
+/* [RW 11] Initial credit for queue 1 in the tx port buffers in 16 byte
+ * lines. */
+#define PBF_REG_INIT_CRD_Q1 0x15c234
/* [RW 1] Init bit for port 0. When set the initial credit of port 0 is
copied to the credit register. Should be set and then reset after the
configuration of the port has ended. */
@@ -2069,6 +2484,15 @@
copied to the credit register. Should be set and then reset after the
configuration of the port has ended. */
#define PBF_REG_INIT_P4 0x14000c
+/* [R 32] Cyclic counter for the amount credits in 16 bytes lines added for
+ * the LB queue. Reset upon init. */
+#define PBF_REG_INTERNAL_CRD_FREED_CNT_LB_Q 0x140354
+/* [R 32] Cyclic counter for the amount credits in 16 bytes lines added for
+ * queue 0. Reset upon init. */
+#define PBF_REG_INTERNAL_CRD_FREED_CNT_Q0 0x140358
+/* [R 32] Cyclic counter for the amount credits in 16 bytes lines added for
+ * queue 1. Reset upon init. */
+#define PBF_REG_INTERNAL_CRD_FREED_CNT_Q1 0x14035c
/* [RW 1] Enable for mac interface 0. */
#define PBF_REG_MAC_IF0_ENABLE 0x140030
/* [RW 1] Enable for mac interface 1. */
@@ -2089,24 +2513,49 @@
/* [RW 11] Initial credit for port 0 in the tx port buffers in 16 byte
lines. */
#define PBF_REG_P0_INIT_CRD 0x1400d0
-/* [RW 1] Indication that pause is enabled for port 0. */
-#define PBF_REG_P0_PAUSE_ENABLE 0x140014
-/* [R 8] Number of tasks in port 0 task queue. */
+/* [R 32] Cyclic counter for the amount credits in 16 bytes lines added for
+ * port 0. Reset upon init. */
+#define PBF_REG_P0_INTERNAL_CRD_FREED_CNT 0x140308
+/* [R 1] Removed for E3 B0 - Indication that pause is enabled for port 0. */
+#define PBF_REG_P0_PAUSE_ENABLE 0x140014
+/* [R 8] Removed for E3 B0 - Number of tasks in port 0 task queue. */
#define PBF_REG_P0_TASK_CNT 0x140204
-/* [R 11] Current credit for port 1 in the tx port buffers in 16 byte lines. */
+/* [R 32] Removed for E3 B0 - Cyclic counter for number of 8 byte lines
+ * freed from the task queue of port 0. Reset upon init. */
+#define PBF_REG_P0_TQ_LINES_FREED_CNT 0x1402f0
+/* [R 12] Number of 8 bytes lines occupied in the task queue of port 0. */
+#define PBF_REG_P0_TQ_OCCUPANCY 0x1402fc
+/* [R 11] Removed for E3 B0 - Current credit for port 1 in the tx port
+ * buffers in 16 byte lines. */
#define PBF_REG_P1_CREDIT 0x140208
-/* [RW 11] Initial credit for port 1 in the tx port buffers in 16 byte
- lines. */
+/* [R 11] Removed for E3 B0 - Initial credit for port 0 in the tx port
+ * buffers in 16 byte lines. */
#define PBF_REG_P1_INIT_CRD 0x1400d4
-/* [R 8] Number of tasks in port 1 task queue. */
+/* [R 32] Cyclic counter for the amount credits in 16 bytes lines added for
+ * port 1. Reset upon init. */
+#define PBF_REG_P1_INTERNAL_CRD_FREED_CNT 0x14030c
+/* [R 8] Removed for E3 B0 - Number of tasks in port 1 task queue. */
#define PBF_REG_P1_TASK_CNT 0x14020c
+/* [R 32] Removed for E3 B0 - Cyclic counter for number of 8 byte lines
+ * freed from the task queue of port 1. Reset upon init. */
+#define PBF_REG_P1_TQ_LINES_FREED_CNT 0x1402f4
+/* [R 12] Number of 8 bytes lines occupied in the task queue of port 1. */
+#define PBF_REG_P1_TQ_OCCUPANCY 0x140300
/* [R 11] Current credit for port 4 in the tx port buffers in 16 byte lines. */
#define PBF_REG_P4_CREDIT 0x140210
/* [RW 11] Initial credit for port 4 in the tx port buffers in 16 byte
lines. */
#define PBF_REG_P4_INIT_CRD 0x1400e0
-/* [R 8] Number of tasks in port 4 task queue. */
+/* [R 32] Cyclic counter for the amount credits in 16 bytes lines added for
+ * port 4. Reset upon init. */
+#define PBF_REG_P4_INTERNAL_CRD_FREED_CNT 0x140310
+/* [R 8] Removed for E3 B0 - Number of tasks in port 4 task queue. */
#define PBF_REG_P4_TASK_CNT 0x140214
+/* [R 32] Removed for E3 B0 - Cyclic counter for number of 8 byte lines
+ * freed from the task queue of port 4. Reset upon init. */
+#define PBF_REG_P4_TQ_LINES_FREED_CNT 0x1402f8
+/* [R 12] Number of 8 bytes lines occupied in the task queue of port 4. */
+#define PBF_REG_P4_TQ_OCCUPANCY 0x140304
/* [RW 5] Interrupt mask register #0 read/write */
#define PBF_REG_PBF_INT_MASK 0x1401d4
/* [R 5] Interrupt register #0 read */
@@ -2115,6 +2564,27 @@
#define PBF_REG_PBF_PRTY_MASK 0x1401e4
/* [RC 20] Parity register #0 read clear */
#define PBF_REG_PBF_PRTY_STS_CLR 0x1401dc
+/* [RW 16] The Ethernet type value for L2 tag 0 */
+#define PBF_REG_TAG_ETHERTYPE_0 0x15c090
+/* [RW 4] The length of the info field for L2 tag 0. The length is between
+ * 2B and 14B; in 2B granularity */
+#define PBF_REG_TAG_LEN_0 0x15c09c
+/* [R 32] Cyclic counter for number of 8 byte lines freed from the LB task
+ * queue. Reset upon init. */
+#define PBF_REG_TQ_LINES_FREED_CNT_LB_Q 0x14038c
+/* [R 32] Cyclic counter for number of 8 byte lines freed from the task
+ * queue 0. Reset upon init. */
+#define PBF_REG_TQ_LINES_FREED_CNT_Q0 0x140390
+/* [R 32] Cyclic counter for number of 8 byte lines freed from task queue 1.
+ * Reset upon init. */
+#define PBF_REG_TQ_LINES_FREED_CNT_Q1 0x140394
+/* [R 13] Number of 8 bytes lines occupied in the task queue of the LB
+ * queue. */
+#define PBF_REG_TQ_OCCUPANCY_LB_Q 0x1403a8
+/* [R 13] Number of 8 bytes lines occupied in the task queue of queue 0. */
+#define PBF_REG_TQ_OCCUPANCY_Q0 0x1403ac
+/* [R 13] Number of 8 bytes lines occupied in the task queue of queue 1. */
+#define PBF_REG_TQ_OCCUPANCY_Q1 0x1403b0
#define PB_REG_CONTROL 0
/* [RW 2] Interrupt mask register #0 read/write */
#define PB_REG_PB_INT_MASK 0x28
@@ -2444,10 +2914,24 @@
/* [RW 6] Bit-map indicating which L2 hdrs may appear after the basic
* Ethernet header. */
#define PRS_REG_HDRS_AFTER_BASIC 0x40238
+/* [RW 6] Bit-map indicating which L2 hdrs may appear after the basic
+ * Ethernet header for port 0 packets. */
+#define PRS_REG_HDRS_AFTER_BASIC_PORT_0 0x40270
+#define PRS_REG_HDRS_AFTER_BASIC_PORT_1 0x40290
+/* [R 6] Bit-map indicating which L2 hdrs may appear after L2 tag 0 */
+#define PRS_REG_HDRS_AFTER_TAG_0 0x40248
+/* [RW 6] Bit-map indicating which L2 hdrs may appear after L2 tag 0 for
+ * port 0 packets */
+#define PRS_REG_HDRS_AFTER_TAG_0_PORT_0 0x40280
+#define PRS_REG_HDRS_AFTER_TAG_0_PORT_1 0x402a0
/* [RW 4] The increment value to send in the CFC load request message */
#define PRS_REG_INC_VALUE 0x40048
/* [RW 6] Bit-map indicating which headers must appear in the packet */
#define PRS_REG_MUST_HAVE_HDRS 0x40254
+/* [RW 6] Bit-map indicating which headers must appear in the packet for
+ * port 0 packets */
+#define PRS_REG_MUST_HAVE_HDRS_PORT_0 0x4028c
+#define PRS_REG_MUST_HAVE_HDRS_PORT_1 0x402ac
#define PRS_REG_NIC_MODE 0x40138
/* [RW 8] The 8-bit event ID for cases where there is no match on the
connection. Used in packet start message to TCM. */
@@ -2496,6 +2980,11 @@
#define PRS_REG_SERIAL_NUM_STATUS_MSB 0x40158
/* [R 4] debug only: SRC current credit. Transaction based. */
#define PRS_REG_SRC_CURRENT_CREDIT 0x4016c
+/* [RW 16] The Ethernet type value for L2 tag 0 */
+#define PRS_REG_TAG_ETHERTYPE_0 0x401d4
+/* [RW 4] The length of the info field for L2 tag 0. The length is between
+ * 2B and 14B; in 2B granularity */
+#define PRS_REG_TAG_LEN_0 0x4022c
/* [R 8] debug only: TCM current credit. Cycle based. */
#define PRS_REG_TCM_CURRENT_CREDIT 0x40160
/* [R 8] debug only: TSDM current credit. Transaction based. */
@@ -3080,6 +3569,7 @@
#define QM_REG_BYTECREDITAFULLTHR 0x168094
/* [RW 4] The initial credit for interface */
#define QM_REG_CMINITCRD_0 0x1680cc
+#define QM_REG_BYTECRDCMDQ_0 0x16e6e8
#define QM_REG_CMINITCRD_1 0x1680d0
#define QM_REG_CMINITCRD_2 0x1680d4
#define QM_REG_CMINITCRD_3 0x1680d8
@@ -3170,7 +3660,10 @@
/* [RW 2] The PCI attributes field used in the PCI request. */
#define QM_REG_PCIREQAT 0x168054
#define QM_REG_PF_EN 0x16e70c
-/* [R 16] The byte credit of port 0 */
+/* [R 24] The number of tasks stored in the QM for the PF. only even
+ * functions are valid in E2 (odd I registers will be hard wired to 0) */
+#define QM_REG_PF_USG_CNT_0 0x16e040
+/* [R 16] NOT USED */
#define QM_REG_PORT0BYTECRD 0x168300
/* [R 16] The byte credit of port 1 */
#define QM_REG_PORT1BYTECRD 0x168304
@@ -3782,6 +4275,8 @@
#define TM_REG_LIN0_LOGIC_ADDR 0x164240
/* [RW 18] Linear0 Max active cid (in banks of 32 entries). */
#define TM_REG_LIN0_MAX_ACTIVE_CID 0x164048
+/* [ST 16] Linear0 Number of scans counter. */
+#define TM_REG_LIN0_NUM_SCANS 0x1640a0
/* [WB 64] Linear0 phy address. */
#define TM_REG_LIN0_PHY_ADDR 0x164270
/* [RW 1] Linear0 physical address valid. */
@@ -3789,6 +4284,7 @@
#define TM_REG_LIN0_SCAN_ON 0x1640d0
/* [RW 24] Linear0 array scan timeout. */
#define TM_REG_LIN0_SCAN_TIME 0x16403c
+#define TM_REG_LIN0_VNIC_UC 0x164128
/* [RW 32] Linear1 logic address. */
#define TM_REG_LIN1_LOGIC_ADDR 0x164250
/* [WB 64] Linear1 phy address. */
@@ -4175,6 +4671,8 @@
#define UCM_REG_UCM_INT_MASK 0xe01d4
/* [R 11] Interrupt register #0 read */
#define UCM_REG_UCM_INT_STS 0xe01c8
+/* [RW 27] Parity mask register #0 read/write */
+#define UCM_REG_UCM_PRTY_MASK 0xe01e4
/* [R 27] Parity register #0 read */
#define UCM_REG_UCM_PRTY_STS 0xe01d8
/* [RC 27] Parity register #0 read clear */
@@ -4265,6 +4763,23 @@
The fields are: [4:0] - tail pointer; 10:5] - Link List size; 15:11] -
header pointer. */
#define UCM_REG_XX_TABLE 0xe0300
+#define UMAC_COMMAND_CONFIG_REG_LOOP_ENA (0x1<<15)
+#define UMAC_COMMAND_CONFIG_REG_NO_LGTH_CHECK (0x1<<24)
+#define UMAC_COMMAND_CONFIG_REG_PAD_EN (0x1<<5)
+#define UMAC_COMMAND_CONFIG_REG_PROMIS_EN (0x1<<4)
+#define UMAC_COMMAND_CONFIG_REG_RX_ENA (0x1<<1)
+#define UMAC_COMMAND_CONFIG_REG_SW_RESET (0x1<<13)
+#define UMAC_COMMAND_CONFIG_REG_TX_ENA (0x1<<0)
+#define UMAC_REG_COMMAND_CONFIG 0x8
+/* [RW 32] Register Bit 0 refers to Bit 16 of the MAC address; Bit 1 refers
+ * to bit 17 of the MAC address etc. */
+#define UMAC_REG_MAC_ADDR0 0xc
+/* [RW 16] Register Bit 0 refers to Bit 0 of the MAC address; Register Bit 1
+ * refers to Bit 1 of the MAC address etc. Bits 16 to 31 are reserved. */
+#define UMAC_REG_MAC_ADDR1 0x10
+/* [RW 14] Defines a 14-Bit maximum frame length used by the MAC receive
+ * logic to check frames. */
+#define UMAC_REG_MAXFR 0x14
/* [RW 8] The event id for aggregated interrupt 0 */
#define USDM_REG_AGG_INT_EVENT_0 0xc4038
#define USDM_REG_AGG_INT_EVENT_1 0xc403c
@@ -4696,8 +5211,13 @@
#define XCM_REG_XCM_INT_MASK 0x202b4
/* [R 14] Interrupt register #0 read */
#define XCM_REG_XCM_INT_STS 0x202a8
+/* [RW 30] Parity mask register #0 read/write */
+#define XCM_REG_XCM_PRTY_MASK 0x202c4
/* [R 30] Parity register #0 read */
#define XCM_REG_XCM_PRTY_STS 0x202b8
+/* [RC 30] Parity register #0 read clear */
+#define XCM_REG_XCM_PRTY_STS_CLR 0x202bc
+
/* [RW 4] The size of AG context region 0 in REG-pairs. Designates the MS
REG-pair number (e.g. if region 0 is 6 REG-pairs; the value should be 5).
Is used to determine the number of the AG context REG-pairs written back;
@@ -4772,6 +5292,34 @@
#define XCM_REG_XX_MSG_NUM 0x20428
/* [RW 8] The Event ID; sent to the STORM in case of XX overflow. */
#define XCM_REG_XX_OVFL_EVNT_ID 0x20058
+#define XMAC_CLEAR_RX_LSS_STATUS_REG_CLEAR_LOCAL_FAULT_STATUS (0x1<<0)
+#define XMAC_CLEAR_RX_LSS_STATUS_REG_CLEAR_REMOTE_FAULT_STATUS (0x1<<1)
+#define XMAC_CTRL_REG_CORE_LOCAL_LPBK (0x1<<3)
+#define XMAC_CTRL_REG_RX_EN (0x1<<1)
+#define XMAC_CTRL_REG_SOFT_RESET (0x1<<6)
+#define XMAC_CTRL_REG_TX_EN (0x1<<0)
+#define XMAC_PAUSE_CTRL_REG_RX_PAUSE_EN (0x1<<18)
+#define XMAC_PAUSE_CTRL_REG_TX_PAUSE_EN (0x1<<17)
+#define XMAC_PFC_CTRL_HI_REG_PFC_REFRESH_EN (0x1<<0)
+#define XMAC_PFC_CTRL_HI_REG_PFC_STATS_EN (0x1<<3)
+#define XMAC_PFC_CTRL_HI_REG_RX_PFC_EN (0x1<<4)
+#define XMAC_PFC_CTRL_HI_REG_TX_PFC_EN (0x1<<5)
+#define XMAC_REG_CLEAR_RX_LSS_STATUS 0x60
+#define XMAC_REG_CTRL 0
+/* [RW 16] Upper 48 bits of ctrl_sa register. Used as the SA in PAUSE/PFC
+ * packets transmitted by the MAC */
+#define XMAC_REG_CTRL_SA_HI 0x2c
+/* [RW 32] Lower 48 bits of ctrl_sa register. Used as the SA in PAUSE/PFC
+ * packets transmitted by the MAC */
+#define XMAC_REG_CTRL_SA_LO 0x28
+#define XMAC_REG_PAUSE_CTRL 0x68
+#define XMAC_REG_PFC_CTRL 0x70
+#define XMAC_REG_PFC_CTRL_HI 0x74
+#define XMAC_REG_RX_LSS_STATUS 0x58
+/* [RW 14] Maximum packet size in receive direction; exclusive of preamble &
+ * CRC in strip mode */
+#define XMAC_REG_RX_MAX_SIZE 0x40
+#define XMAC_REG_TX_CTRL 0x20
/* [RW 16] Indirect access to the XX table of the XX protection mechanism.
The fields are:[4:0] - tail pointer; 9:5] - Link List size; 14:10] -
header pointer. */
@@ -4846,6 +5394,10 @@
#define XSDM_REG_NUM_OF_Q9_CMD 0x166268
/* [RW 13] The start address in the internal RAM for queue counters */
#define XSDM_REG_Q_COUNTER_START_ADDR 0x166010
+/* [W 17] Generate an operation after completion; bit-16 is
+ * AggVectIdx_valid; bits 15:8 are AggVectIdx; bits 7:5 are the TRIG and
+ * bits 4:0 are the T124Param[4:0] */
+#define XSDM_REG_OPERATION_GEN 0x1664c4
/* [R 1] pxp_ctrl rd_data fifo empty in sdm_dma_rsp block */
#define XSDM_REG_RSP_PXP_CTRL_RDATA_EMPTY 0x166548
/* [R 1] parser fifo empty in sdm_sync block */
@@ -5019,6 +5571,7 @@
#define BIGMAC_REGISTER_CNT_MAX_SIZE (0x05<<3)
#define BIGMAC_REGISTER_RX_CONTROL (0x21<<3)
#define BIGMAC_REGISTER_RX_LLFC_MSG_FLDS (0x46<<3)
+#define BIGMAC_REGISTER_RX_LSS_STATUS (0x43<<3)
#define BIGMAC_REGISTER_RX_MAX_SIZE (0x23<<3)
#define BIGMAC_REGISTER_RX_STAT_GR64 (0x26<<3)
#define BIGMAC_REGISTER_RX_STAT_GRIPJ (0x42<<3)
@@ -5034,6 +5587,7 @@
#define BIGMAC2_REGISTER_PFC_CONTROL (0x06<<3)
#define BIGMAC2_REGISTER_RX_CONTROL (0x3A<<3)
#define BIGMAC2_REGISTER_RX_LLFC_MSG_FLDS (0x62<<3)
+#define BIGMAC2_REGISTER_RX_LSS_STAT (0x3E<<3)
#define BIGMAC2_REGISTER_RX_MAX_SIZE (0x3C<<3)
#define BIGMAC2_REGISTER_RX_STAT_GR64 (0x40<<3)
#define BIGMAC2_REGISTER_RX_STAT_GRIPJ (0x5f<<3)
@@ -5052,7 +5606,9 @@
#define EMAC_LED_OVERRIDE (1L<<0)
#define EMAC_LED_TRAFFIC (1L<<6)
#define EMAC_MDIO_COMM_COMMAND_ADDRESS (0L<<26)
+#define EMAC_MDIO_COMM_COMMAND_READ_22 (2L<<26)
#define EMAC_MDIO_COMM_COMMAND_READ_45 (3L<<26)
+#define EMAC_MDIO_COMM_COMMAND_WRITE_22 (1L<<26)
#define EMAC_MDIO_COMM_COMMAND_WRITE_45 (1L<<26)
#define EMAC_MDIO_COMM_DATA (0xffffL<<0)
#define EMAC_MDIO_COMM_START_BUSY (1L<<29)
@@ -5128,16 +5684,24 @@
#define MISC_REGISTERS_RESET_REG_1_RST_PXPV (0x1<<27)
#define MISC_REGISTERS_RESET_REG_1_SET 0x584
#define MISC_REGISTERS_RESET_REG_2_CLEAR 0x598
+#define MISC_REGISTERS_RESET_REG_2_MSTAT0 (0x1<<24)
+#define MISC_REGISTERS_RESET_REG_2_MSTAT1 (0x1<<25)
#define MISC_REGISTERS_RESET_REG_2_RST_BMAC0 (0x1<<0)
#define MISC_REGISTERS_RESET_REG_2_RST_EMAC0_HARD_CORE (0x1<<14)
#define MISC_REGISTERS_RESET_REG_2_RST_EMAC1_HARD_CORE (0x1<<15)
#define MISC_REGISTERS_RESET_REG_2_RST_GRC (0x1<<4)
#define MISC_REGISTERS_RESET_REG_2_RST_MCP_N_HARD_CORE_RST_B (0x1<<6)
+#define MISC_REGISTERS_RESET_REG_2_RST_MCP_N_RESET_CMN_CORE (0x1<<8)
+#define MISC_REGISTERS_RESET_REG_2_RST_MCP_N_RESET_CMN_CPU (0x1<<7)
#define MISC_REGISTERS_RESET_REG_2_RST_MCP_N_RESET_REG_HARD_CORE (0x1<<5)
#define MISC_REGISTERS_RESET_REG_2_RST_MDIO (0x1<<13)
#define MISC_REGISTERS_RESET_REG_2_RST_MISC_CORE (0x1<<11)
+#define MISC_REGISTERS_RESET_REG_2_RST_PCI_MDIO (0x1<<13)
#define MISC_REGISTERS_RESET_REG_2_RST_RBCN (0x1<<9)
#define MISC_REGISTERS_RESET_REG_2_SET 0x594
+#define MISC_REGISTERS_RESET_REG_2_UMAC0 (0x1<<20)
+#define MISC_REGISTERS_RESET_REG_2_XMAC (0x1<<22)
+#define MISC_REGISTERS_RESET_REG_2_XMAC_SOFT (0x1<<23)
#define MISC_REGISTERS_RESET_REG_3_CLEAR 0x5a8
#define MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_SERDES0_IDDQ (0x1<<1)
#define MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_SERDES0_PWRDWN (0x1<<2)
@@ -5160,74 +5724,86 @@
#define MISC_REGISTERS_SPIO_OUTPUT_HIGH 1
#define MISC_REGISTERS_SPIO_OUTPUT_LOW 0
#define MISC_REGISTERS_SPIO_SET_POS 8
+#define HW_LOCK_DRV_FLAGS 10
#define HW_LOCK_MAX_RESOURCE_VALUE 31
#define HW_LOCK_RESOURCE_GPIO 1
#define HW_LOCK_RESOURCE_MDIO 0
-#define HW_LOCK_RESOURCE_PORT0_ATT_MASK 3
-#define HW_LOCK_RESOURCE_RESERVED_08 8
+#define HW_LOCK_RESOURCE_PORT0_ATT_MASK 3
+#define HW_LOCK_RESOURCE_RECOVERY_LEADER_0 8
+#define HW_LOCK_RESOURCE_RECOVERY_LEADER_1 9
#define HW_LOCK_RESOURCE_SPIO 2
#define HW_LOCK_RESOURCE_UNDI 5
-#define PRS_FLAG_OVERETH_IPV4 1
-#define AEU_INPUTS_ATTN_BITS_ATC_HW_INTERRUPT (0x1<<4)
-#define AEU_INPUTS_ATTN_BITS_ATC_PARITY_ERROR (0x1<<5)
-#define AEU_INPUTS_ATTN_BITS_BRB_PARITY_ERROR (1<<18)
-#define AEU_INPUTS_ATTN_BITS_CCM_HW_INTERRUPT (1<<31)
-#define AEU_INPUTS_ATTN_BITS_CDU_HW_INTERRUPT (1<<9)
-#define AEU_INPUTS_ATTN_BITS_CDU_PARITY_ERROR (1<<8)
-#define AEU_INPUTS_ATTN_BITS_CFC_HW_INTERRUPT (1<<7)
-#define AEU_INPUTS_ATTN_BITS_CFC_PARITY_ERROR (1<<6)
-#define AEU_INPUTS_ATTN_BITS_CSDM_HW_INTERRUPT (1<<29)
-#define AEU_INPUTS_ATTN_BITS_CSDM_PARITY_ERROR (1<<28)
-#define AEU_INPUTS_ATTN_BITS_CSEMI_HW_INTERRUPT (1<<1)
-#define AEU_INPUTS_ATTN_BITS_CSEMI_PARITY_ERROR (1<<0)
-#define AEU_INPUTS_ATTN_BITS_DEBUG_PARITY_ERROR (1<<18)
-#define AEU_INPUTS_ATTN_BITS_DMAE_HW_INTERRUPT (1<<11)
-#define AEU_INPUTS_ATTN_BITS_DOORBELLQ_HW_INTERRUPT (1<<13)
-#define AEU_INPUTS_ATTN_BITS_DOORBELLQ_PARITY_ERROR (1<<12)
-#define AEU_INPUTS_ATTN_BITS_GPIO3_FUNCTION_0 (1<<5)
-#define AEU_INPUTS_ATTN_BITS_GPIO3_FUNCTION_1 (1<<9)
-#define AEU_INPUTS_ATTN_BITS_IGU_PARITY_ERROR (1<<12)
-#define AEU_INPUTS_ATTN_BITS_MCP_LATCHED_ROM_PARITY (1<<28)
-#define AEU_INPUTS_ATTN_BITS_MCP_LATCHED_SCPAD_PARITY (1<<31)
-#define AEU_INPUTS_ATTN_BITS_MCP_LATCHED_UMP_RX_PARITY (1<<29)
-#define AEU_INPUTS_ATTN_BITS_MCP_LATCHED_UMP_TX_PARITY (1<<30)
-#define AEU_INPUTS_ATTN_BITS_MISC_HW_INTERRUPT (1<<15)
-#define AEU_INPUTS_ATTN_BITS_MISC_PARITY_ERROR (1<<14)
-#define AEU_INPUTS_ATTN_BITS_PARSER_PARITY_ERROR (1<<20)
-#define AEU_INPUTS_ATTN_BITS_PBCLIENT_PARITY_ERROR (1<<0)
-#define AEU_INPUTS_ATTN_BITS_PBF_HW_INTERRUPT (1<<31)
-#define AEU_INPUTS_ATTN_BITS_PGLUE_HW_INTERRUPT (0x1<<2)
-#define AEU_INPUTS_ATTN_BITS_PGLUE_PARITY_ERROR (0x1<<3)
-#define AEU_INPUTS_ATTN_BITS_PXP_HW_INTERRUPT (1<<3)
-#define AEU_INPUTS_ATTN_BITS_PXP_PARITY_ERROR (1<<2)
-#define AEU_INPUTS_ATTN_BITS_PXPPCICLOCKCLIENT_HW_INTERRUPT (1<<5)
-#define AEU_INPUTS_ATTN_BITS_PXPPCICLOCKCLIENT_PARITY_ERROR (1<<4)
-#define AEU_INPUTS_ATTN_BITS_QM_HW_INTERRUPT (1<<3)
-#define AEU_INPUTS_ATTN_BITS_QM_PARITY_ERROR (1<<2)
-#define AEU_INPUTS_ATTN_BITS_SEARCHER_PARITY_ERROR (1<<22)
-#define AEU_INPUTS_ATTN_BITS_SPIO5 (1<<15)
-#define AEU_INPUTS_ATTN_BITS_TCM_HW_INTERRUPT (1<<27)
-#define AEU_INPUTS_ATTN_BITS_TIMERS_HW_INTERRUPT (1<<5)
-#define AEU_INPUTS_ATTN_BITS_TSDM_HW_INTERRUPT (1<<25)
-#define AEU_INPUTS_ATTN_BITS_TSDM_PARITY_ERROR (1<<24)
-#define AEU_INPUTS_ATTN_BITS_TSEMI_HW_INTERRUPT (1<<29)
-#define AEU_INPUTS_ATTN_BITS_TSEMI_PARITY_ERROR (1<<28)
-#define AEU_INPUTS_ATTN_BITS_UCM_HW_INTERRUPT (1<<23)
-#define AEU_INPUTS_ATTN_BITS_UPB_HW_INTERRUPT (1<<27)
-#define AEU_INPUTS_ATTN_BITS_UPB_PARITY_ERROR (1<<26)
-#define AEU_INPUTS_ATTN_BITS_USDM_HW_INTERRUPT (1<<21)
-#define AEU_INPUTS_ATTN_BITS_USDM_PARITY_ERROR (1<<20)
-#define AEU_INPUTS_ATTN_BITS_USEMI_HW_INTERRUPT (1<<25)
-#define AEU_INPUTS_ATTN_BITS_USEMI_PARITY_ERROR (1<<24)
-#define AEU_INPUTS_ATTN_BITS_VAUX_PCI_CORE_PARITY_ERROR (1<<16)
-#define AEU_INPUTS_ATTN_BITS_XCM_HW_INTERRUPT (1<<9)
-#define AEU_INPUTS_ATTN_BITS_XSDM_HW_INTERRUPT (1<<7)
-#define AEU_INPUTS_ATTN_BITS_XSDM_PARITY_ERROR (1<<6)
-#define AEU_INPUTS_ATTN_BITS_XSEMI_HW_INTERRUPT (1<<11)
-#define AEU_INPUTS_ATTN_BITS_XSEMI_PARITY_ERROR (1<<10)
+#define AEU_INPUTS_ATTN_BITS_ATC_HW_INTERRUPT (0x1<<4)
+#define AEU_INPUTS_ATTN_BITS_ATC_PARITY_ERROR (0x1<<5)
+#define AEU_INPUTS_ATTN_BITS_BRB_PARITY_ERROR (0x1<<18)
+#define AEU_INPUTS_ATTN_BITS_CCM_HW_INTERRUPT (0x1<<31)
+#define AEU_INPUTS_ATTN_BITS_CCM_PARITY_ERROR (0x1<<30)
+#define AEU_INPUTS_ATTN_BITS_CDU_HW_INTERRUPT (0x1<<9)
+#define AEU_INPUTS_ATTN_BITS_CDU_PARITY_ERROR (0x1<<8)
+#define AEU_INPUTS_ATTN_BITS_CFC_HW_INTERRUPT (0x1<<7)
+#define AEU_INPUTS_ATTN_BITS_CFC_PARITY_ERROR (0x1<<6)
+#define AEU_INPUTS_ATTN_BITS_CSDM_HW_INTERRUPT (0x1<<29)
+#define AEU_INPUTS_ATTN_BITS_CSDM_PARITY_ERROR (0x1<<28)
+#define AEU_INPUTS_ATTN_BITS_CSEMI_HW_INTERRUPT (0x1<<1)
+#define AEU_INPUTS_ATTN_BITS_CSEMI_PARITY_ERROR (0x1<<0)
+#define AEU_INPUTS_ATTN_BITS_DEBUG_PARITY_ERROR (0x1<<18)
+#define AEU_INPUTS_ATTN_BITS_DMAE_HW_INTERRUPT (0x1<<11)
+#define AEU_INPUTS_ATTN_BITS_DMAE_PARITY_ERROR (0x1<<10)
+#define AEU_INPUTS_ATTN_BITS_DOORBELLQ_HW_INTERRUPT (0x1<<13)
+#define AEU_INPUTS_ATTN_BITS_DOORBELLQ_PARITY_ERROR (0x1<<12)
+#define AEU_INPUTS_ATTN_BITS_GPIO0_FUNCTION_0 (0x1<<2)
+#define AEU_INPUTS_ATTN_BITS_IGU_PARITY_ERROR (0x1<<12)
+#define AEU_INPUTS_ATTN_BITS_MCP_LATCHED_ROM_PARITY (0x1<<28)
+#define AEU_INPUTS_ATTN_BITS_MCP_LATCHED_SCPAD_PARITY (0x1<<31)
+#define AEU_INPUTS_ATTN_BITS_MCP_LATCHED_UMP_RX_PARITY (0x1<<29)
+#define AEU_INPUTS_ATTN_BITS_MCP_LATCHED_UMP_TX_PARITY (0x1<<30)
+#define AEU_INPUTS_ATTN_BITS_MISC_HW_INTERRUPT (0x1<<15)
+#define AEU_INPUTS_ATTN_BITS_MISC_PARITY_ERROR (0x1<<14)
+#define AEU_INPUTS_ATTN_BITS_NIG_PARITY_ERROR (0x1<<14)
+#define AEU_INPUTS_ATTN_BITS_PARSER_PARITY_ERROR (0x1<<20)
+#define AEU_INPUTS_ATTN_BITS_PBCLIENT_HW_INTERRUPT (0x1<<31)
+#define AEU_INPUTS_ATTN_BITS_PBCLIENT_PARITY_ERROR (0x1<<30)
+#define AEU_INPUTS_ATTN_BITS_PBF_PARITY_ERROR (0x1<<0)
+#define AEU_INPUTS_ATTN_BITS_PGLUE_HW_INTERRUPT (0x1<<2)
+#define AEU_INPUTS_ATTN_BITS_PGLUE_PARITY_ERROR (0x1<<3)
+#define AEU_INPUTS_ATTN_BITS_PXPPCICLOCKCLIENT_HW_INTERRUPT (0x1<<5)
+#define AEU_INPUTS_ATTN_BITS_PXPPCICLOCKCLIENT_PARITY_ERROR (0x1<<4)
+#define AEU_INPUTS_ATTN_BITS_PXP_HW_INTERRUPT (0x1<<3)
+#define AEU_INPUTS_ATTN_BITS_PXP_PARITY_ERROR (0x1<<2)
+#define AEU_INPUTS_ATTN_BITS_QM_HW_INTERRUPT (0x1<<3)
+#define AEU_INPUTS_ATTN_BITS_QM_PARITY_ERROR (0x1<<2)
+#define AEU_INPUTS_ATTN_BITS_SEARCHER_PARITY_ERROR (0x1<<22)
+#define AEU_INPUTS_ATTN_BITS_SPIO5 (0x1<<15)
+#define AEU_INPUTS_ATTN_BITS_TCM_HW_INTERRUPT (0x1<<27)
+#define AEU_INPUTS_ATTN_BITS_TCM_PARITY_ERROR (0x1<<26)
+#define AEU_INPUTS_ATTN_BITS_TIMERS_HW_INTERRUPT (0x1<<5)
+#define AEU_INPUTS_ATTN_BITS_TIMERS_PARITY_ERROR (0x1<<4)
+#define AEU_INPUTS_ATTN_BITS_TSDM_HW_INTERRUPT (0x1<<25)
+#define AEU_INPUTS_ATTN_BITS_TSDM_PARITY_ERROR (0x1<<24)
+#define AEU_INPUTS_ATTN_BITS_TSEMI_HW_INTERRUPT (0x1<<29)
+#define AEU_INPUTS_ATTN_BITS_TSEMI_PARITY_ERROR (0x1<<28)
+#define AEU_INPUTS_ATTN_BITS_UCM_HW_INTERRUPT (0x1<<23)
+#define AEU_INPUTS_ATTN_BITS_UCM_PARITY_ERROR (0x1<<22)
+#define AEU_INPUTS_ATTN_BITS_UPB_HW_INTERRUPT (0x1<<27)
+#define AEU_INPUTS_ATTN_BITS_UPB_PARITY_ERROR (0x1<<26)
+#define AEU_INPUTS_ATTN_BITS_USDM_HW_INTERRUPT (0x1<<21)
+#define AEU_INPUTS_ATTN_BITS_USDM_PARITY_ERROR (0x1<<20)
+#define AEU_INPUTS_ATTN_BITS_USEMI_HW_INTERRUPT (0x1<<25)
+#define AEU_INPUTS_ATTN_BITS_USEMI_PARITY_ERROR (0x1<<24)
+#define AEU_INPUTS_ATTN_BITS_VAUX_PCI_CORE_PARITY_ERROR (0x1<<16)
+#define AEU_INPUTS_ATTN_BITS_XCM_HW_INTERRUPT (0x1<<9)
+#define AEU_INPUTS_ATTN_BITS_XCM_PARITY_ERROR (0x1<<8)
+#define AEU_INPUTS_ATTN_BITS_XSDM_HW_INTERRUPT (0x1<<7)
+#define AEU_INPUTS_ATTN_BITS_XSDM_PARITY_ERROR (0x1<<6)
+#define AEU_INPUTS_ATTN_BITS_XSEMI_HW_INTERRUPT (0x1<<11)
+#define AEU_INPUTS_ATTN_BITS_XSEMI_PARITY_ERROR (0x1<<10)
+
+#define AEU_INPUTS_ATTN_BITS_GPIO3_FUNCTION_0 (0x1<<5)
+#define AEU_INPUTS_ATTN_BITS_GPIO3_FUNCTION_1 (0x1<<9)
+
#define RESERVED_GENERAL_ATTENTION_BIT_0 0
-#define EVEREST_GEN_ATTN_IN_USE_MASK 0x3ffe0
+#define EVEREST_GEN_ATTN_IN_USE_MASK 0x7ffe0
#define EVEREST_LATCHED_ATTN_IN_USE_MASK 0xffe00000
#define RESERVED_GENERAL_ATTENTION_BIT_6 6
@@ -5317,7 +5893,13 @@
#define GRCBASE_HC 0x108000
#define GRCBASE_PXP2 0x120000
#define GRCBASE_PBF 0x140000
+#define GRCBASE_UMAC0 0x160000
+#define GRCBASE_UMAC1 0x160400
#define GRCBASE_XPB 0x161000
+#define GRCBASE_MSTAT0 0x162000
+#define GRCBASE_MSTAT1 0x162800
+#define GRCBASE_XMAC0 0x163000
+#define GRCBASE_XMAC1 0x163800
#define GRCBASE_TIMERS 0x164000
#define GRCBASE_XSDM 0x166000
#define GRCBASE_QM 0x168000
@@ -5883,6 +6465,10 @@
#define MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_16G 0x0C00
#define MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_1G_KX 0x0D00
#define MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_KX4 0x0E00
+#define MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_KR 0x0F00
+#define MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_XFI 0x1B00
+#define MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_20G_DXGXS 0x1E00
+#define MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_SFI 0x1F00
#define MDIO_REG_BANK_10G_PARALLEL_DETECT 0x8130
@@ -6032,15 +6618,11 @@
#define MDIO_PMA_REG_CTRL 0x0
#define MDIO_PMA_REG_STATUS 0x1
#define MDIO_PMA_REG_10G_CTRL2 0x7
+#define MDIO_PMA_REG_TX_DISABLE 0x0009
#define MDIO_PMA_REG_RX_SD 0xa
/*bcm*/
#define MDIO_PMA_REG_BCM_CTRL 0x0096
#define MDIO_PMA_REG_FEC_CTRL 0x00ab
-#define MDIO_PMA_REG_RX_ALARM_CTRL 0x9000
-#define MDIO_PMA_REG_LASI_CTRL 0x9002
-#define MDIO_PMA_REG_RX_ALARM 0x9003
-#define MDIO_PMA_REG_TX_ALARM 0x9004
-#define MDIO_PMA_REG_LASI_STATUS 0x9005
#define MDIO_PMA_REG_PHY_IDENTIFIER 0xc800
#define MDIO_PMA_REG_DIGITAL_CTRL 0xc808
#define MDIO_PMA_REG_DIGITAL_STATUS 0xc809
@@ -6201,6 +6783,169 @@
#define MDIO_PMA_REG_84823_CTL_LED_CTL_1 0xa8e3
#define MDIO_PMA_REG_84823_LED3_STRETCH_EN 0x0080
+/* BCM84833 only */
+#define MDIO_84833_TOP_CFG_XGPHY_STRAP1 0x401a
+#define MDIO_84833_SUPER_ISOLATE 0x8000
+/* These are mailbox register set used by 84833. */
+#define MDIO_84833_TOP_CFG_SCRATCH_REG0 0x4005
+#define MDIO_84833_TOP_CFG_SCRATCH_REG1 0x4006
+#define MDIO_84833_TOP_CFG_SCRATCH_REG2 0x4007
+#define MDIO_84833_TOP_CFG_SCRATCH_REG3 0x4008
+#define MDIO_84833_TOP_CFG_SCRATCH_REG4 0x4009
+#define MDIO_84833_TOP_CFG_DATA3_REG 0x4011
+#define MDIO_84833_TOP_CFG_DATA4_REG 0x4012
+
+/* Mailbox command set used by 84833. */
+#define PHY84833_DIAG_CMD_PAIR_SWAP_CHANGE 0x2
+/* Mailbox status set used by 84833. */
+#define PHY84833_CMD_RECEIVED 0x0001
+#define PHY84833_CMD_IN_PROGRESS 0x0002
+#define PHY84833_CMD_COMPLETE_PASS 0x0004
+#define PHY84833_CMD_COMPLETE_ERROR 0x0008
+#define PHY84833_CMD_OPEN_FOR_CMDS 0x0010
+#define PHY84833_CMD_SYSTEM_BOOT 0x0020
+#define PHY84833_CMD_NOT_OPEN_FOR_CMDS 0x0040
+#define PHY84833_CMD_CLEAR_COMPLETE 0x0080
+#define PHY84833_CMD_OPEN_OVERRIDE 0xa5a5
+
+
+/* 84833 F/W Feature Commands */
+#define PHY84833_DIAG_CMD_GET_EEE_MODE 0x27
+#define PHY84833_DIAG_CMD_SET_EEE_MODE 0x28
+
+/* Warpcore clause 45 addressing */
+#define MDIO_WC_DEVAD 0x3
+#define MDIO_WC_REG_IEEE0BLK_MIICNTL 0x0
+#define MDIO_WC_REG_IEEE0BLK_AUTONEGNP 0x7
+#define MDIO_WC_REG_AN_IEEE1BLK_AN_ADVERTISEMENT0 0x10
+#define MDIO_WC_REG_AN_IEEE1BLK_AN_ADVERTISEMENT1 0x11
+#define MDIO_WC_REG_PMD_IEEE9BLK_TENGBASE_KR_PMD_CONTROL_REGISTER_150 0x96
+#define MDIO_WC_REG_XGXSBLK0_XGXSCONTROL 0x8000
+#define MDIO_WC_REG_XGXSBLK0_MISCCONTROL1 0x800e
+#define MDIO_WC_REG_XGXSBLK1_DESKEW 0x8010
+#define MDIO_WC_REG_XGXSBLK1_LANECTRL0 0x8015
+#define MDIO_WC_REG_XGXSBLK1_LANECTRL1 0x8016
+#define MDIO_WC_REG_XGXSBLK1_LANECTRL2 0x8017
+#define MDIO_WC_REG_TX0_ANA_CTRL0 0x8061
+#define MDIO_WC_REG_TX1_ANA_CTRL0 0x8071
+#define MDIO_WC_REG_TX2_ANA_CTRL0 0x8081
+#define MDIO_WC_REG_TX3_ANA_CTRL0 0x8091
+#define MDIO_WC_REG_TX0_TX_DRIVER 0x8067
+#define MDIO_WC_REG_TX0_TX_DRIVER_IPRE_DRIVER_OFFSET 0x04
+#define MDIO_WC_REG_TX0_TX_DRIVER_IPRE_DRIVER_MASK 0x00f0
+#define MDIO_WC_REG_TX0_TX_DRIVER_IDRIVER_OFFSET 0x08
+#define MDIO_WC_REG_TX0_TX_DRIVER_IDRIVER_MASK 0x0f00
+#define MDIO_WC_REG_TX0_TX_DRIVER_POST2_COEFF_OFFSET 0x0c
+#define MDIO_WC_REG_TX0_TX_DRIVER_POST2_COEFF_MASK 0x7000
+#define MDIO_WC_REG_TX1_TX_DRIVER 0x8077
+#define MDIO_WC_REG_TX2_TX_DRIVER 0x8087
+#define MDIO_WC_REG_TX3_TX_DRIVER 0x8097
+#define MDIO_WC_REG_RX0_ANARXCONTROL1G 0x80b9
+#define MDIO_WC_REG_RX2_ANARXCONTROL1G 0x80d9
+#define MDIO_WC_REG_RX0_PCI_CTRL 0x80ba
+#define MDIO_WC_REG_RX1_PCI_CTRL 0x80ca
+#define MDIO_WC_REG_RX2_PCI_CTRL 0x80da
+#define MDIO_WC_REG_RX3_PCI_CTRL 0x80ea
+#define MDIO_WC_REG_XGXSBLK2_UNICORE_MODE_10G 0x8104
+#define MDIO_WC_REG_XGXS_STATUS3 0x8129
+#define MDIO_WC_REG_PAR_DET_10G_STATUS 0x8130
+#define MDIO_WC_REG_PAR_DET_10G_CTRL 0x8131
+#define MDIO_WC_REG_XGXS_X2_CONTROL2 0x8141
+#define MDIO_WC_REG_XGXS_RX_LN_SWAP1 0x816B
+#define MDIO_WC_REG_XGXS_TX_LN_SWAP1 0x8169
+#define MDIO_WC_REG_GP2_STATUS_GP_2_0 0x81d0
+#define MDIO_WC_REG_GP2_STATUS_GP_2_1 0x81d1
+#define MDIO_WC_REG_GP2_STATUS_GP_2_2 0x81d2
+#define MDIO_WC_REG_GP2_STATUS_GP_2_3 0x81d3
+#define MDIO_WC_REG_GP2_STATUS_GP_2_4 0x81d4
+#define MDIO_WC_REG_UC_INFO_B0_DEAD_TRAP 0x81EE
+#define MDIO_WC_REG_UC_INFO_B1_VERSION 0x81F0
+#define MDIO_WC_REG_UC_INFO_B1_FIRMWARE_MODE 0x81F2
+#define MDIO_WC_REG_UC_INFO_B1_FIRMWARE_LANE0_OFFSET 0x0
+#define MDIO_WC_REG_UC_INFO_B1_FIRMWARE_MODE_DEFAULT 0x0
+#define MDIO_WC_REG_UC_INFO_B1_FIRMWARE_MODE_SFP_OPT_LR 0x1
+#define MDIO_WC_REG_UC_INFO_B1_FIRMWARE_MODE_SFP_DAC 0x2
+#define MDIO_WC_REG_UC_INFO_B1_FIRMWARE_MODE_SFP_XLAUI 0x3
+#define MDIO_WC_REG_UC_INFO_B1_FIRMWARE_MODE_LONG_CH_6G 0x4
+#define MDIO_WC_REG_UC_INFO_B1_FIRMWARE_LANE1_OFFSET 0x4
+#define MDIO_WC_REG_UC_INFO_B1_FIRMWARE_LANE2_OFFSET 0x8
+#define MDIO_WC_REG_UC_INFO_B1_FIRMWARE_LANE3_OFFSET 0xc
+#define MDIO_WC_REG_UC_INFO_B1_CRC 0x81FE
+#define MDIO_WC_REG_DSC_SMC 0x8213
+#define MDIO_WC_REG_DSC2B0_DSC_MISC_CTRL0 0x821e
+#define MDIO_WC_REG_TX_FIR_TAP 0x82e2
+#define MDIO_WC_REG_TX_FIR_TAP_PRE_TAP_OFFSET 0x00
+#define MDIO_WC_REG_TX_FIR_TAP_PRE_TAP_MASK 0x000f
+#define MDIO_WC_REG_TX_FIR_TAP_MAIN_TAP_OFFSET 0x04
+#define MDIO_WC_REG_TX_FIR_TAP_MAIN_TAP_MASK 0x03f0
+#define MDIO_WC_REG_TX_FIR_TAP_POST_TAP_OFFSET 0x0a
+#define MDIO_WC_REG_TX_FIR_TAP_POST_TAP_MASK 0x7c00
+#define MDIO_WC_REG_TX_FIR_TAP_ENABLE 0x8000
+#define MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL 0x82e3
+#define MDIO_WC_REG_CL72_USERB0_CL72_OS_DEF_CTRL 0x82e6
+#define MDIO_WC_REG_CL72_USERB0_CL72_BR_DEF_CTRL 0x82e7
+#define MDIO_WC_REG_CL72_USERB0_CL72_2P5_DEF_CTRL 0x82e8
+#define MDIO_WC_REG_CL72_USERB0_CL72_MISC4_CONTROL 0x82ec
+#define MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X1 0x8300
+#define MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2 0x8301
+#define MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X3 0x8302
+#define MDIO_WC_REG_SERDESDIGITAL_STATUS1000X1 0x8304
+#define MDIO_WC_REG_SERDESDIGITAL_MISC1 0x8308
+#define MDIO_WC_REG_SERDESDIGITAL_MISC2 0x8309
+#define MDIO_WC_REG_DIGITAL3_UP1 0x8329
+#define MDIO_WC_REG_DIGITAL4_MISC3 0x833c
+#define MDIO_WC_REG_DIGITAL5_MISC6 0x8345
+#define MDIO_WC_REG_DIGITAL5_MISC7 0x8349
+#define MDIO_WC_REG_DIGITAL5_ACTUAL_SPEED 0x834e
+#define MDIO_WC_REG_DIGITAL6_MP5_NEXTPAGECTRL 0x8350
+#define MDIO_WC_REG_CL49_USERB0_CTRL 0x8368
+#define MDIO_WC_REG_TX66_CONTROL 0x83b0
+#define MDIO_WC_REG_RX66_CONTROL 0x83c0
+#define MDIO_WC_REG_RX66_SCW0 0x83c2
+#define MDIO_WC_REG_RX66_SCW1 0x83c3
+#define MDIO_WC_REG_RX66_SCW2 0x83c4
+#define MDIO_WC_REG_RX66_SCW3 0x83c5
+#define MDIO_WC_REG_RX66_SCW0_MASK 0x83c6
+#define MDIO_WC_REG_RX66_SCW1_MASK 0x83c7
+#define MDIO_WC_REG_RX66_SCW2_MASK 0x83c8
+#define MDIO_WC_REG_RX66_SCW3_MASK 0x83c9
+#define MDIO_WC_REG_FX100_CTRL1 0x8400
+#define MDIO_WC_REG_FX100_CTRL3 0x8402
+
+#define MDIO_WC_REG_MICROBLK_CMD 0xffc2
+#define MDIO_WC_REG_MICROBLK_DL_STATUS 0xffc5
+#define MDIO_WC_REG_MICROBLK_CMD3 0xffcc
+
+#define MDIO_WC_REG_AERBLK_AER 0xffde
+#define MDIO_WC_REG_COMBO_IEEE0_MIICTRL 0xffe0
+#define MDIO_WC_REG_COMBO_IEEE0_MIIISTAT 0xffe1
+
+#define MDIO_WC0_XGXS_BLK2_LANE_RESET 0x810A
+#define MDIO_WC0_XGXS_BLK2_LANE_RESET_RX_BITSHIFT 0
+#define MDIO_WC0_XGXS_BLK2_LANE_RESET_TX_BITSHIFT 4
+
+#define MDIO_WC0_XGXS_BLK6_XGXS_X2_CONTROL2 0x8141
+
+#define DIGITAL5_ACTUAL_SPEED_TX_MASK 0x003f
+
+/* 54618se */
+#define MDIO_REG_GPHY_PHYID_LSB 0x3
+#define MDIO_REG_GPHY_ID_54618SE 0x5cd5
+#define MDIO_REG_GPHY_CL45_ADDR_REG 0xd
+#define MDIO_REG_GPHY_CL45_DATA_REG 0xe
+#define MDIO_REG_GPHY_EEE_ADV 0x3c
+#define MDIO_REG_GPHY_EEE_1G (0x1 << 2)
+#define MDIO_REG_GPHY_EEE_100 (0x1 << 1)
+#define MDIO_REG_GPHY_EEE_RESOLVED 0x803e
+#define MDIO_REG_INTR_STATUS 0x1a
+#define MDIO_REG_INTR_MASK 0x1b
+#define MDIO_REG_INTR_MASK_LINK_STATUS (0x1 << 1)
+#define MDIO_REG_GPHY_SHADOW 0x1c
+#define MDIO_REG_GPHY_SHADOW_LED_SEL2 (0x0e << 10)
+#define MDIO_REG_GPHY_SHADOW_WR_ENA (0x1 << 15)
+#define MDIO_REG_GPHY_SHADOW_AUTO_DET_MED (0x1e << 10)
+#define MDIO_REG_GPHY_SHADOW_INVERT_FIB_SD (0x1 << 8)
+
#define IGU_FUNC_BASE 0x0400
#define IGU_ADDR_MSIX 0x0000
@@ -6217,11 +6962,6 @@
#define IGU_ADDR_MSI_ADDR_HI 0x0212
#define IGU_ADDR_MSI_DATA 0x0213
-#define IGU_INT_ENABLE 0
-#define IGU_INT_DISABLE 1
-#define IGU_INT_NOP 2
-#define IGU_INT_NOP2 3
-
#define IGU_USE_REGISTER_ustorm_type_0_sb_cleanup 0
#define IGU_USE_REGISTER_ustorm_type_1_sb_cleanup 1
#define IGU_USE_REGISTER_cstorm_type_0_sb_cleanup 2
@@ -6292,15 +7032,6 @@
#define IGU_BC_BASE_DSB_PROD 128
#define IGU_NORM_BASE_DSB_PROD 136
-#define IGU_CTRL_CMD_TYPE_WR\
- 1
-#define IGU_CTRL_CMD_TYPE_RD\
- 0
-
-#define IGU_SEG_ACCESS_NORM 0
-#define IGU_SEG_ACCESS_DEF 1
-#define IGU_SEG_ACCESS_ATTN 2
-
/* FID (if VF - [6] = 0; [5:0] = VF number; if PF - [6] = 1; \
[5:2] = 0; [1:0] = PF number) */
#define IGU_FID_ENCODE_IS_PF (0x1<<6)
diff --git a/drivers/net/bnx2x/bnx2x_sp.c b/drivers/net/bnx2x/bnx2x_sp.c
new file mode 100644
index 0000000..5bdf094
--- /dev/null
+++ b/drivers/net/bnx2x/bnx2x_sp.c
@@ -0,0 +1,5333 @@
+/* bnx2x_sp.c: Broadcom Everest network driver.
+ *
+ * Copyright 2011 Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2, available
+ * at http://www.gnu.org/licenses/old-licenses/gpl-2.0.html (the "GPL").
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a
+ * license other than the GPL, without Broadcom's express prior written
+ * consent.
+ *
+ * Maintained by: Eilon Greenstein <eilong@broadcom.com>
+ * Written by: Vladislav Zolotarov
+ *
+ */
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/crc32.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/crc32c.h>
+#include "bnx2x.h"
+#include "bnx2x_cmn.h"
+#include "bnx2x_sp.h"
+
+#define BNX2X_MAX_EMUL_MULTI 16
+
+/**** Exe Queue interfaces ****/
+
+/**
+ * bnx2x_exe_queue_init - init the Exe Queue object
+ *
+ * @o: poiter to the object
+ * @exe_len: length
+ * @owner: poiter to the owner
+ * @validate: validate function pointer
+ * @optimize: optimize function pointer
+ * @exec: execute function pointer
+ * @get: get function pointer
+ */
+static inline void bnx2x_exe_queue_init(struct bnx2x *bp,
+ struct bnx2x_exe_queue_obj *o,
+ int exe_len,
+ union bnx2x_qable_obj *owner,
+ exe_q_validate validate,
+ exe_q_optimize optimize,
+ exe_q_execute exec,
+ exe_q_get get)
+{
+ memset(o, 0, sizeof(*o));
+
+ INIT_LIST_HEAD(&o->exe_queue);
+ INIT_LIST_HEAD(&o->pending_comp);
+
+ spin_lock_init(&o->lock);
+
+ o->exe_chunk_len = exe_len;
+ o->owner = owner;
+
+ /* Owner specific callbacks */
+ o->validate = validate;
+ o->optimize = optimize;
+ o->execute = exec;
+ o->get = get;
+
+ DP(BNX2X_MSG_SP, "Setup the execution queue with the chunk "
+ "length of %d\n", exe_len);
+}
+
+static inline void bnx2x_exe_queue_free_elem(struct bnx2x *bp,
+ struct bnx2x_exeq_elem *elem)
+{
+ DP(BNX2X_MSG_SP, "Deleting an exe_queue element\n");
+ kfree(elem);
+}
+
+static inline int bnx2x_exe_queue_length(struct bnx2x_exe_queue_obj *o)
+{
+ struct bnx2x_exeq_elem *elem;
+ int cnt = 0;
+
+ spin_lock_bh(&o->lock);
+
+ list_for_each_entry(elem, &o->exe_queue, link)
+ cnt++;
+
+ spin_unlock_bh(&o->lock);
+
+ return cnt;
+}
+
+/**
+ * bnx2x_exe_queue_add - add a new element to the execution queue
+ *
+ * @bp: driver handle
+ * @o: queue
+ * @cmd: new command to add
+ * @restore: true - do not optimize the command
+ *
+ * If the element is optimized or is illegal, frees it.
+ */
+static inline int bnx2x_exe_queue_add(struct bnx2x *bp,
+ struct bnx2x_exe_queue_obj *o,
+ struct bnx2x_exeq_elem *elem,
+ bool restore)
+{
+ int rc;
+
+ spin_lock_bh(&o->lock);
+
+ if (!restore) {
+ /* Try to cancel this element queue */
+ rc = o->optimize(bp, o->owner, elem);
+ if (rc)
+ goto free_and_exit;
+
+ /* Check if this request is ok */
+ rc = o->validate(bp, o->owner, elem);
+ if (rc) {
+ BNX2X_ERR("Preamble failed: %d\n", rc);
+ goto free_and_exit;
+ }
+ }
+
+ /* If so, add it to the execution queue */
+ list_add_tail(&elem->link, &o->exe_queue);
+
+ spin_unlock_bh(&o->lock);
+
+ return 0;
+
+free_and_exit:
+ bnx2x_exe_queue_free_elem(bp, elem);
+
+ spin_unlock_bh(&o->lock);
+
+ return rc;
+
+}
+
+static inline void __bnx2x_exe_queue_reset_pending(
+ struct bnx2x *bp,
+ struct bnx2x_exe_queue_obj *o)
+{
+ struct bnx2x_exeq_elem *elem;
+
+ while (!list_empty(&o->pending_comp)) {
+ elem = list_first_entry(&o->pending_comp,
+ struct bnx2x_exeq_elem, link);
+
+ list_del(&elem->link);
+ bnx2x_exe_queue_free_elem(bp, elem);
+ }
+}
+
+static inline void bnx2x_exe_queue_reset_pending(struct bnx2x *bp,
+ struct bnx2x_exe_queue_obj *o)
+{
+
+ spin_lock_bh(&o->lock);
+
+ __bnx2x_exe_queue_reset_pending(bp, o);
+
+ spin_unlock_bh(&o->lock);
+
+}
+
+/**
+ * bnx2x_exe_queue_step - execute one execution chunk atomically
+ *
+ * @bp: driver handle
+ * @o: queue
+ * @ramrod_flags: flags
+ *
+ * (Atomicy is ensured using the exe_queue->lock).
+ */
+static inline int bnx2x_exe_queue_step(struct bnx2x *bp,
+ struct bnx2x_exe_queue_obj *o,
+ unsigned long *ramrod_flags)
+{
+ struct bnx2x_exeq_elem *elem, spacer;
+ int cur_len = 0, rc;
+
+ memset(&spacer, 0, sizeof(spacer));
+
+ spin_lock_bh(&o->lock);
+
+ /*
+ * Next step should not be performed until the current is finished,
+ * unless a DRV_CLEAR_ONLY bit is set. In this case we just want to
+ * properly clear object internals without sending any command to the FW
+ * which also implies there won't be any completion to clear the
+ * 'pending' list.
+ */
+ if (!list_empty(&o->pending_comp)) {
+ if (test_bit(RAMROD_DRV_CLR_ONLY, ramrod_flags)) {
+ DP(BNX2X_MSG_SP, "RAMROD_DRV_CLR_ONLY requested: "
+ "resetting pending_comp\n");
+ __bnx2x_exe_queue_reset_pending(bp, o);
+ } else {
+ spin_unlock_bh(&o->lock);
+ return 1;
+ }
+ }
+
+ /*
+ * Run through the pending commands list and create a next
+ * execution chunk.
+ */
+ while (!list_empty(&o->exe_queue)) {
+ elem = list_first_entry(&o->exe_queue, struct bnx2x_exeq_elem,
+ link);
+ WARN_ON(!elem->cmd_len);
+
+ if (cur_len + elem->cmd_len <= o->exe_chunk_len) {
+ cur_len += elem->cmd_len;
+ /*
+ * Prevent from both lists being empty when moving an
+ * element. This will allow the call of
+ * bnx2x_exe_queue_empty() without locking.
+ */
+ list_add_tail(&spacer.link, &o->pending_comp);
+ mb();
+ list_del(&elem->link);
+ list_add_tail(&elem->link, &o->pending_comp);
+ list_del(&spacer.link);
+ } else
+ break;
+ }
+
+ /* Sanity check */
+ if (!cur_len) {
+ spin_unlock_bh(&o->lock);
+ return 0;
+ }
+
+ rc = o->execute(bp, o->owner, &o->pending_comp, ramrod_flags);
+ if (rc < 0)
+ /*
+ * In case of an error return the commands back to the queue
+ * and reset the pending_comp.
+ */
+ list_splice_init(&o->pending_comp, &o->exe_queue);
+ else if (!rc)
+ /*
+ * If zero is returned, means there are no outstanding pending
+ * completions and we may dismiss the pending list.
+ */
+ __bnx2x_exe_queue_reset_pending(bp, o);
+
+ spin_unlock_bh(&o->lock);
+ return rc;
+}
+
+static inline bool bnx2x_exe_queue_empty(struct bnx2x_exe_queue_obj *o)
+{
+ bool empty = list_empty(&o->exe_queue);
+
+ /* Don't reorder!!! */
+ mb();
+
+ return empty && list_empty(&o->pending_comp);
+}
+
+static inline struct bnx2x_exeq_elem *bnx2x_exe_queue_alloc_elem(
+ struct bnx2x *bp)
+{
+ DP(BNX2X_MSG_SP, "Allocating a new exe_queue element\n");
+ return kzalloc(sizeof(struct bnx2x_exeq_elem), GFP_ATOMIC);
+}
+
+/************************ raw_obj functions ***********************************/
+static bool bnx2x_raw_check_pending(struct bnx2x_raw_obj *o)
+{
+ return !!test_bit(o->state, o->pstate);
+}
+
+static void bnx2x_raw_clear_pending(struct bnx2x_raw_obj *o)
+{
+ smp_mb__before_clear_bit();
+ clear_bit(o->state, o->pstate);
+ smp_mb__after_clear_bit();
+}
+
+static void bnx2x_raw_set_pending(struct bnx2x_raw_obj *o)
+{
+ smp_mb__before_clear_bit();
+ set_bit(o->state, o->pstate);
+ smp_mb__after_clear_bit();
+}
+
+/**
+ * bnx2x_state_wait - wait until the given bit(state) is cleared
+ *
+ * @bp: device handle
+ * @state: state which is to be cleared
+ * @state_p: state buffer
+ *
+ */
+static inline int bnx2x_state_wait(struct bnx2x *bp, int state,
+ unsigned long *pstate)
+{
+ /* can take a while if any port is running */
+ int cnt = 5000;
+
+
+ if (CHIP_REV_IS_EMUL(bp))
+ cnt *= 20;
+
+ DP(BNX2X_MSG_SP, "waiting for state to become %d\n", state);
+
+ might_sleep();
+ while (cnt--) {
+ if (!test_bit(state, pstate)) {
+#ifdef BNX2X_STOP_ON_ERROR
+ DP(BNX2X_MSG_SP, "exit (cnt %d)\n", 5000 - cnt);
+#endif
+ return 0;
+ }
+
+ usleep_range(1000, 1000);
+
+ if (bp->panic)
+ return -EIO;
+ }
+
+ /* timeout! */
+ BNX2X_ERR("timeout waiting for state %d\n", state);
+#ifdef BNX2X_STOP_ON_ERROR
+ bnx2x_panic();
+#endif
+
+ return -EBUSY;
+}
+
+static int bnx2x_raw_wait(struct bnx2x *bp, struct bnx2x_raw_obj *raw)
+{
+ return bnx2x_state_wait(bp, raw->state, raw->pstate);
+}
+
+/***************** Classification verbs: Set/Del MAC/VLAN/VLAN-MAC ************/
+/* credit handling callbacks */
+static bool bnx2x_get_cam_offset_mac(struct bnx2x_vlan_mac_obj *o, int *offset)
+{
+ struct bnx2x_credit_pool_obj *mp = o->macs_pool;
+
+ WARN_ON(!mp);
+
+ return mp->get_entry(mp, offset);
+}
+
+static bool bnx2x_get_credit_mac(struct bnx2x_vlan_mac_obj *o)
+{
+ struct bnx2x_credit_pool_obj *mp = o->macs_pool;
+
+ WARN_ON(!mp);
+
+ return mp->get(mp, 1);
+}
+
+static bool bnx2x_get_cam_offset_vlan(struct bnx2x_vlan_mac_obj *o, int *offset)
+{
+ struct bnx2x_credit_pool_obj *vp = o->vlans_pool;
+
+ WARN_ON(!vp);
+
+ return vp->get_entry(vp, offset);
+}
+
+static bool bnx2x_get_credit_vlan(struct bnx2x_vlan_mac_obj *o)
+{
+ struct bnx2x_credit_pool_obj *vp = o->vlans_pool;
+
+ WARN_ON(!vp);
+
+ return vp->get(vp, 1);
+}
+
+static bool bnx2x_get_credit_vlan_mac(struct bnx2x_vlan_mac_obj *o)
+{
+ struct bnx2x_credit_pool_obj *mp = o->macs_pool;
+ struct bnx2x_credit_pool_obj *vp = o->vlans_pool;
+
+ if (!mp->get(mp, 1))
+ return false;
+
+ if (!vp->get(vp, 1)) {
+ mp->put(mp, 1);
+ return false;
+ }
+
+ return true;
+}
+
+static bool bnx2x_put_cam_offset_mac(struct bnx2x_vlan_mac_obj *o, int offset)
+{
+ struct bnx2x_credit_pool_obj *mp = o->macs_pool;
+
+ return mp->put_entry(mp, offset);
+}
+
+static bool bnx2x_put_credit_mac(struct bnx2x_vlan_mac_obj *o)
+{
+ struct bnx2x_credit_pool_obj *mp = o->macs_pool;
+
+ return mp->put(mp, 1);
+}
+
+static bool bnx2x_put_cam_offset_vlan(struct bnx2x_vlan_mac_obj *o, int offset)
+{
+ struct bnx2x_credit_pool_obj *vp = o->vlans_pool;
+
+ return vp->put_entry(vp, offset);
+}
+
+static bool bnx2x_put_credit_vlan(struct bnx2x_vlan_mac_obj *o)
+{
+ struct bnx2x_credit_pool_obj *vp = o->vlans_pool;
+
+ return vp->put(vp, 1);
+}
+
+static bool bnx2x_put_credit_vlan_mac(struct bnx2x_vlan_mac_obj *o)
+{
+ struct bnx2x_credit_pool_obj *mp = o->macs_pool;
+ struct bnx2x_credit_pool_obj *vp = o->vlans_pool;
+
+ if (!mp->put(mp, 1))
+ return false;
+
+ if (!vp->put(vp, 1)) {
+ mp->get(mp, 1);
+ return false;
+ }
+
+ return true;
+}
+
+/* check_add() callbacks */
+static int bnx2x_check_mac_add(struct bnx2x_vlan_mac_obj *o,
+ union bnx2x_classification_ramrod_data *data)
+{
+ struct bnx2x_vlan_mac_registry_elem *pos;
+
+ if (!is_valid_ether_addr(data->mac.mac))
+ return -EINVAL;
+
+ /* Check if a requested MAC already exists */
+ list_for_each_entry(pos, &o->head, link)
+ if (!memcmp(data->mac.mac, pos->u.mac.mac, ETH_ALEN))
+ return -EEXIST;
+
+ return 0;
+}
+
+static int bnx2x_check_vlan_add(struct bnx2x_vlan_mac_obj *o,
+ union bnx2x_classification_ramrod_data *data)
+{
+ struct bnx2x_vlan_mac_registry_elem *pos;
+
+ list_for_each_entry(pos, &o->head, link)
+ if (data->vlan.vlan == pos->u.vlan.vlan)
+ return -EEXIST;
+
+ return 0;
+}
+
+static int bnx2x_check_vlan_mac_add(struct bnx2x_vlan_mac_obj *o,
+ union bnx2x_classification_ramrod_data *data)
+{
+ struct bnx2x_vlan_mac_registry_elem *pos;
+
+ list_for_each_entry(pos, &o->head, link)
+ if ((data->vlan_mac.vlan == pos->u.vlan_mac.vlan) &&
+ (!memcmp(data->vlan_mac.mac, pos->u.vlan_mac.mac,
+ ETH_ALEN)))
+ return -EEXIST;
+
+ return 0;
+}
+
+
+/* check_del() callbacks */
+static struct bnx2x_vlan_mac_registry_elem *
+ bnx2x_check_mac_del(struct bnx2x_vlan_mac_obj *o,
+ union bnx2x_classification_ramrod_data *data)
+{
+ struct bnx2x_vlan_mac_registry_elem *pos;
+
+ list_for_each_entry(pos, &o->head, link)
+ if (!memcmp(data->mac.mac, pos->u.mac.mac, ETH_ALEN))
+ return pos;
+
+ return NULL;
+}
+
+static struct bnx2x_vlan_mac_registry_elem *
+ bnx2x_check_vlan_del(struct bnx2x_vlan_mac_obj *o,
+ union bnx2x_classification_ramrod_data *data)
+{
+ struct bnx2x_vlan_mac_registry_elem *pos;
+
+ list_for_each_entry(pos, &o->head, link)
+ if (data->vlan.vlan == pos->u.vlan.vlan)
+ return pos;
+
+ return NULL;
+}
+
+static struct bnx2x_vlan_mac_registry_elem *
+ bnx2x_check_vlan_mac_del(struct bnx2x_vlan_mac_obj *o,
+ union bnx2x_classification_ramrod_data *data)
+{
+ struct bnx2x_vlan_mac_registry_elem *pos;
+
+ list_for_each_entry(pos, &o->head, link)
+ if ((data->vlan_mac.vlan == pos->u.vlan_mac.vlan) &&
+ (!memcmp(data->vlan_mac.mac, pos->u.vlan_mac.mac,
+ ETH_ALEN)))
+ return pos;
+
+ return NULL;
+}
+
+/* check_move() callback */
+static bool bnx2x_check_move(struct bnx2x_vlan_mac_obj *src_o,
+ struct bnx2x_vlan_mac_obj *dst_o,
+ union bnx2x_classification_ramrod_data *data)
+{
+ struct bnx2x_vlan_mac_registry_elem *pos;
+ int rc;
+
+ /* Check if we can delete the requested configuration from the first
+ * object.
+ */
+ pos = src_o->check_del(src_o, data);
+
+ /* check if configuration can be added */
+ rc = dst_o->check_add(dst_o, data);
+
+ /* If this classification can not be added (is already set)
+ * or can't be deleted - return an error.
+ */
+ if (rc || !pos)
+ return false;
+
+ return true;
+}
+
+static bool bnx2x_check_move_always_err(
+ struct bnx2x_vlan_mac_obj *src_o,
+ struct bnx2x_vlan_mac_obj *dst_o,
+ union bnx2x_classification_ramrod_data *data)
+{
+ return false;
+}
+
+
+static inline u8 bnx2x_vlan_mac_get_rx_tx_flag(struct bnx2x_vlan_mac_obj *o)
+{
+ struct bnx2x_raw_obj *raw = &o->raw;
+ u8 rx_tx_flag = 0;
+
+ if ((raw->obj_type == BNX2X_OBJ_TYPE_TX) ||
+ (raw->obj_type == BNX2X_OBJ_TYPE_RX_TX))
+ rx_tx_flag |= ETH_CLASSIFY_CMD_HEADER_TX_CMD;
+
+ if ((raw->obj_type == BNX2X_OBJ_TYPE_RX) ||
+ (raw->obj_type == BNX2X_OBJ_TYPE_RX_TX))
+ rx_tx_flag |= ETH_CLASSIFY_CMD_HEADER_RX_CMD;
+
+ return rx_tx_flag;
+}
+
+/* LLH CAM line allocations */
+enum {
+ LLH_CAM_ISCSI_ETH_LINE = 0,
+ LLH_CAM_ETH_LINE,
+ LLH_CAM_MAX_PF_LINE = NIG_REG_LLH1_FUNC_MEM_SIZE / 2
+};
+
+static inline void bnx2x_set_mac_in_nig(struct bnx2x *bp,
+ bool add, unsigned char *dev_addr, int index)
+{
+ u32 wb_data[2];
+ u32 reg_offset = BP_PORT(bp) ? NIG_REG_LLH1_FUNC_MEM :
+ NIG_REG_LLH0_FUNC_MEM;
+
+ if (!IS_MF_SI(bp) || index > LLH_CAM_MAX_PF_LINE)
+ return;
+
+ DP(BNX2X_MSG_SP, "Going to %s LLH configuration at entry %d\n",
+ (add ? "ADD" : "DELETE"), index);
+
+ if (add) {
+ /* LLH_FUNC_MEM is a u64 WB register */
+ reg_offset += 8*index;
+
+ wb_data[0] = ((dev_addr[2] << 24) | (dev_addr[3] << 16) |
+ (dev_addr[4] << 8) | dev_addr[5]);
+ wb_data[1] = ((dev_addr[0] << 8) | dev_addr[1]);
+
+ REG_WR_DMAE(bp, reg_offset, wb_data, 2);
+ }
+
+ REG_WR(bp, (BP_PORT(bp) ? NIG_REG_LLH1_FUNC_MEM_ENABLE :
+ NIG_REG_LLH0_FUNC_MEM_ENABLE) + 4*index, add);
+}
+
+/**
+ * bnx2x_vlan_mac_set_cmd_hdr_e2 - set a header in a single classify ramrod
+ *
+ * @bp: device handle
+ * @o: queue for which we want to configure this rule
+ * @add: if true the command is an ADD command, DEL otherwise
+ * @opcode: CLASSIFY_RULE_OPCODE_XXX
+ * @hdr: pointer to a header to setup
+ *
+ */
+static inline void bnx2x_vlan_mac_set_cmd_hdr_e2(struct bnx2x *bp,
+ struct bnx2x_vlan_mac_obj *o, bool add, int opcode,
+ struct eth_classify_cmd_header *hdr)
+{
+ struct bnx2x_raw_obj *raw = &o->raw;
+
+ hdr->client_id = raw->cl_id;
+ hdr->func_id = raw->func_id;
+
+ /* Rx or/and Tx (internal switching) configuration ? */
+ hdr->cmd_general_data |=
+ bnx2x_vlan_mac_get_rx_tx_flag(o);
+
+ if (add)
+ hdr->cmd_general_data |= ETH_CLASSIFY_CMD_HEADER_IS_ADD;
+
+ hdr->cmd_general_data |=
+ (opcode << ETH_CLASSIFY_CMD_HEADER_OPCODE_SHIFT);
+}
+
+/**
+ * bnx2x_vlan_mac_set_rdata_hdr_e2 - set the classify ramrod data header
+ *
+ * @cid: connection id
+ * @type: BNX2X_FILTER_XXX_PENDING
+ * @hdr: poiter to header to setup
+ * @rule_cnt:
+ *
+ * currently we always configure one rule and echo field to contain a CID and an
+ * opcode type.
+ */
+static inline void bnx2x_vlan_mac_set_rdata_hdr_e2(u32 cid, int type,
+ struct eth_classify_header *hdr, int rule_cnt)
+{
+ hdr->echo = (cid & BNX2X_SWCID_MASK) | (type << BNX2X_SWCID_SHIFT);
+ hdr->rule_cnt = (u8)rule_cnt;
+}
+
+
+/* hw_config() callbacks */
+static void bnx2x_set_one_mac_e2(struct bnx2x *bp,
+ struct bnx2x_vlan_mac_obj *o,
+ struct bnx2x_exeq_elem *elem, int rule_idx,
+ int cam_offset)
+{
+ struct bnx2x_raw_obj *raw = &o->raw;
+ struct eth_classify_rules_ramrod_data *data =
+ (struct eth_classify_rules_ramrod_data *)(raw->rdata);
+ int rule_cnt = rule_idx + 1, cmd = elem->cmd_data.vlan_mac.cmd;
+ union eth_classify_rule_cmd *rule_entry = &data->rules[rule_idx];
+ bool add = (cmd == BNX2X_VLAN_MAC_ADD) ? true : false;
+ unsigned long *vlan_mac_flags = &elem->cmd_data.vlan_mac.vlan_mac_flags;
+ u8 *mac = elem->cmd_data.vlan_mac.u.mac.mac;
+
+ /*
+ * Set LLH CAM entry: currently only iSCSI and ETH macs are
+ * relevant. In addition, current implementation is tuned for a
+ * single ETH MAC.
+ *
+ * When multiple unicast ETH MACs PF configuration in switch
+ * independent mode is required (NetQ, multiple netdev MACs,
+ * etc.), consider better utilisation of 8 per function MAC
+ * entries in the LLH register. There is also
+ * NIG_REG_P[01]_LLH_FUNC_MEM2 registers that complete the
+ * total number of CAM entries to 16.
+ *
+ * Currently we won't configure NIG for MACs other than a primary ETH
+ * MAC and iSCSI L2 MAC.
+ *
+ * If this MAC is moving from one Queue to another, no need to change
+ * NIG configuration.
+ */
+ if (cmd != BNX2X_VLAN_MAC_MOVE) {
+ if (test_bit(BNX2X_ISCSI_ETH_MAC, vlan_mac_flags))
+ bnx2x_set_mac_in_nig(bp, add, mac,
+ LLH_CAM_ISCSI_ETH_LINE);
+ else if (test_bit(BNX2X_ETH_MAC, vlan_mac_flags))
+ bnx2x_set_mac_in_nig(bp, add, mac, LLH_CAM_ETH_LINE);
+ }
+
+ /* Reset the ramrod data buffer for the first rule */
+ if (rule_idx == 0)
+ memset(data, 0, sizeof(*data));
+
+ /* Setup a command header */
+ bnx2x_vlan_mac_set_cmd_hdr_e2(bp, o, add, CLASSIFY_RULE_OPCODE_MAC,
+ &rule_entry->mac.header);
+
+ DP(BNX2X_MSG_SP, "About to %s MAC "BNX2X_MAC_FMT" for "
+ "Queue %d\n", (add ? "add" : "delete"),
+ BNX2X_MAC_PRN_LIST(mac), raw->cl_id);
+
+ /* Set a MAC itself */
+ bnx2x_set_fw_mac_addr(&rule_entry->mac.mac_msb,
+ &rule_entry->mac.mac_mid,
+ &rule_entry->mac.mac_lsb, mac);
+
+ /* MOVE: Add a rule that will add this MAC to the target Queue */
+ if (cmd == BNX2X_VLAN_MAC_MOVE) {
+ rule_entry++;
+ rule_cnt++;
+
+ /* Setup ramrod data */
+ bnx2x_vlan_mac_set_cmd_hdr_e2(bp,
+ elem->cmd_data.vlan_mac.target_obj,
+ true, CLASSIFY_RULE_OPCODE_MAC,
+ &rule_entry->mac.header);
+
+ /* Set a MAC itself */
+ bnx2x_set_fw_mac_addr(&rule_entry->mac.mac_msb,
+ &rule_entry->mac.mac_mid,
+ &rule_entry->mac.mac_lsb, mac);
+ }
+
+ /* Set the ramrod data header */
+ /* TODO: take this to the higher level in order to prevent multiple
+ writing */
+ bnx2x_vlan_mac_set_rdata_hdr_e2(raw->cid, raw->state, &data->header,
+ rule_cnt);
+}
+
+/**
+ * bnx2x_vlan_mac_set_rdata_hdr_e1x - set a header in a single classify ramrod
+ *
+ * @bp: device handle
+ * @o: queue
+ * @type:
+ * @cam_offset: offset in cam memory
+ * @hdr: pointer to a header to setup
+ *
+ * E1/E1H
+ */
+static inline void bnx2x_vlan_mac_set_rdata_hdr_e1x(struct bnx2x *bp,
+ struct bnx2x_vlan_mac_obj *o, int type, int cam_offset,
+ struct mac_configuration_hdr *hdr)
+{
+ struct bnx2x_raw_obj *r = &o->raw;
+
+ hdr->length = 1;
+ hdr->offset = (u8)cam_offset;
+ hdr->client_id = 0xff;
+ hdr->echo = ((r->cid & BNX2X_SWCID_MASK) | (type << BNX2X_SWCID_SHIFT));
+}
+
+static inline void bnx2x_vlan_mac_set_cfg_entry_e1x(struct bnx2x *bp,
+ struct bnx2x_vlan_mac_obj *o, bool add, int opcode, u8 *mac,
+ u16 vlan_id, struct mac_configuration_entry *cfg_entry)
+{
+ struct bnx2x_raw_obj *r = &o->raw;
+ u32 cl_bit_vec = (1 << r->cl_id);
+
+ cfg_entry->clients_bit_vector = cpu_to_le32(cl_bit_vec);
+ cfg_entry->pf_id = r->func_id;
+ cfg_entry->vlan_id = cpu_to_le16(vlan_id);
+
+ if (add) {
+ SET_FLAG(cfg_entry->flags, MAC_CONFIGURATION_ENTRY_ACTION_TYPE,
+ T_ETH_MAC_COMMAND_SET);
+ SET_FLAG(cfg_entry->flags,
+ MAC_CONFIGURATION_ENTRY_VLAN_FILTERING_MODE, opcode);
+
+ /* Set a MAC in a ramrod data */
+ bnx2x_set_fw_mac_addr(&cfg_entry->msb_mac_addr,
+ &cfg_entry->middle_mac_addr,
+ &cfg_entry->lsb_mac_addr, mac);
+ } else
+ SET_FLAG(cfg_entry->flags, MAC_CONFIGURATION_ENTRY_ACTION_TYPE,
+ T_ETH_MAC_COMMAND_INVALIDATE);
+}
+
+static inline void bnx2x_vlan_mac_set_rdata_e1x(struct bnx2x *bp,
+ struct bnx2x_vlan_mac_obj *o, int type, int cam_offset, bool add,
+ u8 *mac, u16 vlan_id, int opcode, struct mac_configuration_cmd *config)
+{
+ struct mac_configuration_entry *cfg_entry = &config->config_table[0];
+ struct bnx2x_raw_obj *raw = &o->raw;
+
+ bnx2x_vlan_mac_set_rdata_hdr_e1x(bp, o, type, cam_offset,
+ &config->hdr);
+ bnx2x_vlan_mac_set_cfg_entry_e1x(bp, o, add, opcode, mac, vlan_id,
+ cfg_entry);
+
+ DP(BNX2X_MSG_SP, "%s MAC "BNX2X_MAC_FMT" CLID %d CAM offset %d\n",
+ (add ? "setting" : "clearing"),
+ BNX2X_MAC_PRN_LIST(mac), raw->cl_id, cam_offset);
+}
+
+/**
+ * bnx2x_set_one_mac_e1x - fill a single MAC rule ramrod data
+ *
+ * @bp: device handle
+ * @o: bnx2x_vlan_mac_obj
+ * @elem: bnx2x_exeq_elem
+ * @rule_idx: rule_idx
+ * @cam_offset: cam_offset
+ */
+static void bnx2x_set_one_mac_e1x(struct bnx2x *bp,
+ struct bnx2x_vlan_mac_obj *o,
+ struct bnx2x_exeq_elem *elem, int rule_idx,
+ int cam_offset)
+{
+ struct bnx2x_raw_obj *raw = &o->raw;
+ struct mac_configuration_cmd *config =
+ (struct mac_configuration_cmd *)(raw->rdata);
+ /*
+ * 57710 and 57711 do not support MOVE command,
+ * so it's either ADD or DEL
+ */
+ bool add = (elem->cmd_data.vlan_mac.cmd == BNX2X_VLAN_MAC_ADD) ?
+ true : false;
+
+ /* Reset the ramrod data buffer */
+ memset(config, 0, sizeof(*config));
+
+ bnx2x_vlan_mac_set_rdata_e1x(bp, o, BNX2X_FILTER_MAC_PENDING,
+ cam_offset, add,
+ elem->cmd_data.vlan_mac.u.mac.mac, 0,
+ ETH_VLAN_FILTER_ANY_VLAN, config);
+}
+
+static void bnx2x_set_one_vlan_e2(struct bnx2x *bp,
+ struct bnx2x_vlan_mac_obj *o,
+ struct bnx2x_exeq_elem *elem, int rule_idx,
+ int cam_offset)
+{
+ struct bnx2x_raw_obj *raw = &o->raw;
+ struct eth_classify_rules_ramrod_data *data =
+ (struct eth_classify_rules_ramrod_data *)(raw->rdata);
+ int rule_cnt = rule_idx + 1;
+ union eth_classify_rule_cmd *rule_entry = &data->rules[rule_idx];
+ int cmd = elem->cmd_data.vlan_mac.cmd;
+ bool add = (cmd == BNX2X_VLAN_MAC_ADD) ? true : false;
+ u16 vlan = elem->cmd_data.vlan_mac.u.vlan.vlan;
+
+ /* Reset the ramrod data buffer for the first rule */
+ if (rule_idx == 0)
+ memset(data, 0, sizeof(*data));
+
+ /* Set a rule header */
+ bnx2x_vlan_mac_set_cmd_hdr_e2(bp, o, add, CLASSIFY_RULE_OPCODE_VLAN,
+ &rule_entry->vlan.header);
+
+ DP(BNX2X_MSG_SP, "About to %s VLAN %d\n", (add ? "add" : "delete"),
+ vlan);
+
+ /* Set a VLAN itself */
+ rule_entry->vlan.vlan = cpu_to_le16(vlan);
+
+ /* MOVE: Add a rule that will add this MAC to the target Queue */
+ if (cmd == BNX2X_VLAN_MAC_MOVE) {
+ rule_entry++;
+ rule_cnt++;
+
+ /* Setup ramrod data */
+ bnx2x_vlan_mac_set_cmd_hdr_e2(bp,
+ elem->cmd_data.vlan_mac.target_obj,
+ true, CLASSIFY_RULE_OPCODE_VLAN,
+ &rule_entry->vlan.header);
+
+ /* Set a VLAN itself */
+ rule_entry->vlan.vlan = cpu_to_le16(vlan);
+ }
+
+ /* Set the ramrod data header */
+ /* TODO: take this to the higher level in order to prevent multiple
+ writing */
+ bnx2x_vlan_mac_set_rdata_hdr_e2(raw->cid, raw->state, &data->header,
+ rule_cnt);
+}
+
+static void bnx2x_set_one_vlan_mac_e2(struct bnx2x *bp,
+ struct bnx2x_vlan_mac_obj *o,
+ struct bnx2x_exeq_elem *elem,
+ int rule_idx, int cam_offset)
+{
+ struct bnx2x_raw_obj *raw = &o->raw;
+ struct eth_classify_rules_ramrod_data *data =
+ (struct eth_classify_rules_ramrod_data *)(raw->rdata);
+ int rule_cnt = rule_idx + 1;
+ union eth_classify_rule_cmd *rule_entry = &data->rules[rule_idx];
+ int cmd = elem->cmd_data.vlan_mac.cmd;
+ bool add = (cmd == BNX2X_VLAN_MAC_ADD) ? true : false;
+ u16 vlan = elem->cmd_data.vlan_mac.u.vlan_mac.vlan;
+ u8 *mac = elem->cmd_data.vlan_mac.u.vlan_mac.mac;
+
+
+ /* Reset the ramrod data buffer for the first rule */
+ if (rule_idx == 0)
+ memset(data, 0, sizeof(*data));
+
+ /* Set a rule header */
+ bnx2x_vlan_mac_set_cmd_hdr_e2(bp, o, add, CLASSIFY_RULE_OPCODE_PAIR,
+ &rule_entry->pair.header);
+
+ /* Set VLAN and MAC themselvs */
+ rule_entry->pair.vlan = cpu_to_le16(vlan);
+ bnx2x_set_fw_mac_addr(&rule_entry->pair.mac_msb,
+ &rule_entry->pair.mac_mid,
+ &rule_entry->pair.mac_lsb, mac);
+
+ /* MOVE: Add a rule that will add this MAC to the target Queue */
+ if (cmd == BNX2X_VLAN_MAC_MOVE) {
+ rule_entry++;
+ rule_cnt++;
+
+ /* Setup ramrod data */
+ bnx2x_vlan_mac_set_cmd_hdr_e2(bp,
+ elem->cmd_data.vlan_mac.target_obj,
+ true, CLASSIFY_RULE_OPCODE_PAIR,
+ &rule_entry->pair.header);
+
+ /* Set a VLAN itself */
+ rule_entry->pair.vlan = cpu_to_le16(vlan);
+ bnx2x_set_fw_mac_addr(&rule_entry->pair.mac_msb,
+ &rule_entry->pair.mac_mid,
+ &rule_entry->pair.mac_lsb, mac);
+ }
+
+ /* Set the ramrod data header */
+ /* TODO: take this to the higher level in order to prevent multiple
+ writing */
+ bnx2x_vlan_mac_set_rdata_hdr_e2(raw->cid, raw->state, &data->header,
+ rule_cnt);
+}
+
+/**
+ * bnx2x_set_one_vlan_mac_e1h -
+ *
+ * @bp: device handle
+ * @o: bnx2x_vlan_mac_obj
+ * @elem: bnx2x_exeq_elem
+ * @rule_idx: rule_idx
+ * @cam_offset: cam_offset
+ */
+static void bnx2x_set_one_vlan_mac_e1h(struct bnx2x *bp,
+ struct bnx2x_vlan_mac_obj *o,
+ struct bnx2x_exeq_elem *elem,
+ int rule_idx, int cam_offset)
+{
+ struct bnx2x_raw_obj *raw = &o->raw;
+ struct mac_configuration_cmd *config =
+ (struct mac_configuration_cmd *)(raw->rdata);
+ /*
+ * 57710 and 57711 do not support MOVE command,
+ * so it's either ADD or DEL
+ */
+ bool add = (elem->cmd_data.vlan_mac.cmd == BNX2X_VLAN_MAC_ADD) ?
+ true : false;
+
+ /* Reset the ramrod data buffer */
+ memset(config, 0, sizeof(*config));
+
+ bnx2x_vlan_mac_set_rdata_e1x(bp, o, BNX2X_FILTER_VLAN_MAC_PENDING,
+ cam_offset, add,
+ elem->cmd_data.vlan_mac.u.vlan_mac.mac,
+ elem->cmd_data.vlan_mac.u.vlan_mac.vlan,
+ ETH_VLAN_FILTER_CLASSIFY, config);
+}
+
+#define list_next_entry(pos, member) \
+ list_entry((pos)->member.next, typeof(*(pos)), member)
+
+/**
+ * bnx2x_vlan_mac_restore - reconfigure next MAC/VLAN/VLAN-MAC element
+ *
+ * @bp: device handle
+ * @p: command parameters
+ * @ppos: pointer to the cooky
+ *
+ * reconfigure next MAC/VLAN/VLAN-MAC element from the
+ * previously configured elements list.
+ *
+ * from command parameters only RAMROD_COMP_WAIT bit in ramrod_flags is taken
+ * into an account
+ *
+ * pointer to the cooky - that should be given back in the next call to make
+ * function handle the next element. If *ppos is set to NULL it will restart the
+ * iterator. If returned *ppos == NULL this means that the last element has been
+ * handled.
+ *
+ */
+static int bnx2x_vlan_mac_restore(struct bnx2x *bp,
+ struct bnx2x_vlan_mac_ramrod_params *p,
+ struct bnx2x_vlan_mac_registry_elem **ppos)
+{
+ struct bnx2x_vlan_mac_registry_elem *pos;
+ struct bnx2x_vlan_mac_obj *o = p->vlan_mac_obj;
+
+ /* If list is empty - there is nothing to do here */
+ if (list_empty(&o->head)) {
+ *ppos = NULL;
+ return 0;
+ }
+
+ /* make a step... */
+ if (*ppos == NULL)
+ *ppos = list_first_entry(&o->head,
+ struct bnx2x_vlan_mac_registry_elem,
+ link);
+ else
+ *ppos = list_next_entry(*ppos, link);
+
+ pos = *ppos;
+
+ /* If it's the last step - return NULL */
+ if (list_is_last(&pos->link, &o->head))
+ *ppos = NULL;
+
+ /* Prepare a 'user_req' */
+ memcpy(&p->user_req.u, &pos->u, sizeof(pos->u));
+
+ /* Set the command */
+ p->user_req.cmd = BNX2X_VLAN_MAC_ADD;
+
+ /* Set vlan_mac_flags */
+ p->user_req.vlan_mac_flags = pos->vlan_mac_flags;
+
+ /* Set a restore bit */
+ __set_bit(RAMROD_RESTORE, &p->ramrod_flags);
+
+ return bnx2x_config_vlan_mac(bp, p);
+}
+
+/*
+ * bnx2x_exeq_get_mac/bnx2x_exeq_get_vlan/bnx2x_exeq_get_vlan_mac return a
+ * pointer to an element with a specific criteria and NULL if such an element
+ * hasn't been found.
+ */
+static struct bnx2x_exeq_elem *bnx2x_exeq_get_mac(
+ struct bnx2x_exe_queue_obj *o,
+ struct bnx2x_exeq_elem *elem)
+{
+ struct bnx2x_exeq_elem *pos;
+ struct bnx2x_mac_ramrod_data *data = &elem->cmd_data.vlan_mac.u.mac;
+
+ /* Check pending for execution commands */
+ list_for_each_entry(pos, &o->exe_queue, link)
+ if (!memcmp(&pos->cmd_data.vlan_mac.u.mac, data,
+ sizeof(*data)) &&
+ (pos->cmd_data.vlan_mac.cmd == elem->cmd_data.vlan_mac.cmd))
+ return pos;
+
+ return NULL;
+}
+
+static struct bnx2x_exeq_elem *bnx2x_exeq_get_vlan(
+ struct bnx2x_exe_queue_obj *o,
+ struct bnx2x_exeq_elem *elem)
+{
+ struct bnx2x_exeq_elem *pos;
+ struct bnx2x_vlan_ramrod_data *data = &elem->cmd_data.vlan_mac.u.vlan;
+
+ /* Check pending for execution commands */
+ list_for_each_entry(pos, &o->exe_queue, link)
+ if (!memcmp(&pos->cmd_data.vlan_mac.u.vlan, data,
+ sizeof(*data)) &&
+ (pos->cmd_data.vlan_mac.cmd == elem->cmd_data.vlan_mac.cmd))
+ return pos;
+
+ return NULL;
+}
+
+static struct bnx2x_exeq_elem *bnx2x_exeq_get_vlan_mac(
+ struct bnx2x_exe_queue_obj *o,
+ struct bnx2x_exeq_elem *elem)
+{
+ struct bnx2x_exeq_elem *pos;
+ struct bnx2x_vlan_mac_ramrod_data *data =
+ &elem->cmd_data.vlan_mac.u.vlan_mac;
+
+ /* Check pending for execution commands */
+ list_for_each_entry(pos, &o->exe_queue, link)
+ if (!memcmp(&pos->cmd_data.vlan_mac.u.vlan_mac, data,
+ sizeof(*data)) &&
+ (pos->cmd_data.vlan_mac.cmd == elem->cmd_data.vlan_mac.cmd))
+ return pos;
+
+ return NULL;
+}
+
+/**
+ * bnx2x_validate_vlan_mac_add - check if an ADD command can be executed
+ *
+ * @bp: device handle
+ * @qo: bnx2x_qable_obj
+ * @elem: bnx2x_exeq_elem
+ *
+ * Checks that the requested configuration can be added. If yes and if
+ * requested, consume CAM credit.
+ *
+ * The 'validate' is run after the 'optimize'.
+ *
+ */
+static inline int bnx2x_validate_vlan_mac_add(struct bnx2x *bp,
+ union bnx2x_qable_obj *qo,
+ struct bnx2x_exeq_elem *elem)
+{
+ struct bnx2x_vlan_mac_obj *o = &qo->vlan_mac;
+ struct bnx2x_exe_queue_obj *exeq = &o->exe_queue;
+ int rc;
+
+ /* Check the registry */
+ rc = o->check_add(o, &elem->cmd_data.vlan_mac.u);
+ if (rc) {
+ DP(BNX2X_MSG_SP, "ADD command is not allowed considering "
+ "current registry state\n");
+ return rc;
+ }
+
+ /*
+ * Check if there is a pending ADD command for this
+ * MAC/VLAN/VLAN-MAC. Return an error if there is.
+ */
+ if (exeq->get(exeq, elem)) {
+ DP(BNX2X_MSG_SP, "There is a pending ADD command already\n");
+ return -EEXIST;
+ }
+
+ /*
+ * TODO: Check the pending MOVE from other objects where this
+ * object is a destination object.
+ */
+
+ /* Consume the credit if not requested not to */
+ if (!(test_bit(BNX2X_DONT_CONSUME_CAM_CREDIT,
+ &elem->cmd_data.vlan_mac.vlan_mac_flags) ||
+ o->get_credit(o)))
+ return -EINVAL;
+
+ return 0;
+}
+
+/**
+ * bnx2x_validate_vlan_mac_del - check if the DEL command can be executed
+ *
+ * @bp: device handle
+ * @qo: quable object to check
+ * @elem: element that needs to be deleted
+ *
+ * Checks that the requested configuration can be deleted. If yes and if
+ * requested, returns a CAM credit.
+ *
+ * The 'validate' is run after the 'optimize'.
+ */
+static inline int bnx2x_validate_vlan_mac_del(struct bnx2x *bp,
+ union bnx2x_qable_obj *qo,
+ struct bnx2x_exeq_elem *elem)
+{
+ struct bnx2x_vlan_mac_obj *o = &qo->vlan_mac;
+ struct bnx2x_vlan_mac_registry_elem *pos;
+ struct bnx2x_exe_queue_obj *exeq = &o->exe_queue;
+ struct bnx2x_exeq_elem query_elem;
+
+ /* If this classification can not be deleted (doesn't exist)
+ * - return a BNX2X_EXIST.
+ */
+ pos = o->check_del(o, &elem->cmd_data.vlan_mac.u);
+ if (!pos) {
+ DP(BNX2X_MSG_SP, "DEL command is not allowed considering "
+ "current registry state\n");
+ return -EEXIST;
+ }
+
+ /*
+ * Check if there are pending DEL or MOVE commands for this
+ * MAC/VLAN/VLAN-MAC. Return an error if so.
+ */
+ memcpy(&query_elem, elem, sizeof(query_elem));
+
+ /* Check for MOVE commands */
+ query_elem.cmd_data.vlan_mac.cmd = BNX2X_VLAN_MAC_MOVE;
+ if (exeq->get(exeq, &query_elem)) {
+ BNX2X_ERR("There is a pending MOVE command already\n");
+ return -EINVAL;
+ }
+
+ /* Check for DEL commands */
+ if (exeq->get(exeq, elem)) {
+ DP(BNX2X_MSG_SP, "There is a pending DEL command already\n");
+ return -EEXIST;
+ }
+
+ /* Return the credit to the credit pool if not requested not to */
+ if (!(test_bit(BNX2X_DONT_CONSUME_CAM_CREDIT,
+ &elem->cmd_data.vlan_mac.vlan_mac_flags) ||
+ o->put_credit(o))) {
+ BNX2X_ERR("Failed to return a credit\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/**
+ * bnx2x_validate_vlan_mac_move - check if the MOVE command can be executed
+ *
+ * @bp: device handle
+ * @qo: quable object to check (source)
+ * @elem: element that needs to be moved
+ *
+ * Checks that the requested configuration can be moved. If yes and if
+ * requested, returns a CAM credit.
+ *
+ * The 'validate' is run after the 'optimize'.
+ */
+static inline int bnx2x_validate_vlan_mac_move(struct bnx2x *bp,
+ union bnx2x_qable_obj *qo,
+ struct bnx2x_exeq_elem *elem)
+{
+ struct bnx2x_vlan_mac_obj *src_o = &qo->vlan_mac;
+ struct bnx2x_vlan_mac_obj *dest_o = elem->cmd_data.vlan_mac.target_obj;
+ struct bnx2x_exeq_elem query_elem;
+ struct bnx2x_exe_queue_obj *src_exeq = &src_o->exe_queue;
+ struct bnx2x_exe_queue_obj *dest_exeq = &dest_o->exe_queue;
+
+ /*
+ * Check if we can perform this operation based on the current registry
+ * state.
+ */
+ if (!src_o->check_move(src_o, dest_o, &elem->cmd_data.vlan_mac.u)) {
+ DP(BNX2X_MSG_SP, "MOVE command is not allowed considering "
+ "current registry state\n");
+ return -EINVAL;
+ }
+
+ /*
+ * Check if there is an already pending DEL or MOVE command for the
+ * source object or ADD command for a destination object. Return an
+ * error if so.
+ */
+ memcpy(&query_elem, elem, sizeof(query_elem));
+
+ /* Check DEL on source */
+ query_elem.cmd_data.vlan_mac.cmd = BNX2X_VLAN_MAC_DEL;
+ if (src_exeq->get(src_exeq, &query_elem)) {
+ BNX2X_ERR("There is a pending DEL command on the source "
+ "queue already\n");
+ return -EINVAL;
+ }
+
+ /* Check MOVE on source */
+ if (src_exeq->get(src_exeq, elem)) {
+ DP(BNX2X_MSG_SP, "There is a pending MOVE command already\n");
+ return -EEXIST;
+ }
+
+ /* Check ADD on destination */
+ query_elem.cmd_data.vlan_mac.cmd = BNX2X_VLAN_MAC_ADD;
+ if (dest_exeq->get(dest_exeq, &query_elem)) {
+ BNX2X_ERR("There is a pending ADD command on the "
+ "destination queue already\n");
+ return -EINVAL;
+ }
+
+ /* Consume the credit if not requested not to */
+ if (!(test_bit(BNX2X_DONT_CONSUME_CAM_CREDIT_DEST,
+ &elem->cmd_data.vlan_mac.vlan_mac_flags) ||
+ dest_o->get_credit(dest_o)))
+ return -EINVAL;
+
+ if (!(test_bit(BNX2X_DONT_CONSUME_CAM_CREDIT,
+ &elem->cmd_data.vlan_mac.vlan_mac_flags) ||
+ src_o->put_credit(src_o))) {
+ /* return the credit taken from dest... */
+ dest_o->put_credit(dest_o);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int bnx2x_validate_vlan_mac(struct bnx2x *bp,
+ union bnx2x_qable_obj *qo,
+ struct bnx2x_exeq_elem *elem)
+{
+ switch (elem->cmd_data.vlan_mac.cmd) {
+ case BNX2X_VLAN_MAC_ADD:
+ return bnx2x_validate_vlan_mac_add(bp, qo, elem);
+ case BNX2X_VLAN_MAC_DEL:
+ return bnx2x_validate_vlan_mac_del(bp, qo, elem);
+ case BNX2X_VLAN_MAC_MOVE:
+ return bnx2x_validate_vlan_mac_move(bp, qo, elem);
+ default:
+ return -EINVAL;
+ }
+}
+
+/**
+ * bnx2x_wait_vlan_mac - passivly wait for 5 seconds until all work completes.
+ *
+ * @bp: device handle
+ * @o: bnx2x_vlan_mac_obj
+ *
+ */
+static int bnx2x_wait_vlan_mac(struct bnx2x *bp,
+ struct bnx2x_vlan_mac_obj *o)
+{
+ int cnt = 5000, rc;
+ struct bnx2x_exe_queue_obj *exeq = &o->exe_queue;
+ struct bnx2x_raw_obj *raw = &o->raw;
+
+ while (cnt--) {
+ /* Wait for the current command to complete */
+ rc = raw->wait_comp(bp, raw);
+ if (rc)
+ return rc;
+
+ /* Wait until there are no pending commands */
+ if (!bnx2x_exe_queue_empty(exeq))
+ usleep_range(1000, 1000);
+ else
+ return 0;
+ }
+
+ return -EBUSY;
+}
+
+/**
+ * bnx2x_complete_vlan_mac - complete one VLAN-MAC ramrod
+ *
+ * @bp: device handle
+ * @o: bnx2x_vlan_mac_obj
+ * @cqe:
+ * @cont: if true schedule next execution chunk
+ *
+ */
+static int bnx2x_complete_vlan_mac(struct bnx2x *bp,
+ struct bnx2x_vlan_mac_obj *o,
+ union event_ring_elem *cqe,
+ unsigned long *ramrod_flags)
+{
+ struct bnx2x_raw_obj *r = &o->raw;
+ int rc;
+
+ /* Reset pending list */
+ bnx2x_exe_queue_reset_pending(bp, &o->exe_queue);
+
+ /* Clear pending */
+ r->clear_pending(r);
+
+ /* If ramrod failed this is most likely a SW bug */
+ if (cqe->message.error)
+ return -EINVAL;
+
+ /* Run the next bulk of pending commands if requeted */
+ if (test_bit(RAMROD_CONT, ramrod_flags)) {
+ rc = bnx2x_exe_queue_step(bp, &o->exe_queue, ramrod_flags);
+ if (rc < 0)
+ return rc;
+ }
+
+ /* If there is more work to do return PENDING */
+ if (!bnx2x_exe_queue_empty(&o->exe_queue))
+ return 1;
+
+ return 0;
+}
+
+/**
+ * bnx2x_optimize_vlan_mac - optimize ADD and DEL commands.
+ *
+ * @bp: device handle
+ * @o: bnx2x_qable_obj
+ * @elem: bnx2x_exeq_elem
+ */
+static int bnx2x_optimize_vlan_mac(struct bnx2x *bp,
+ union bnx2x_qable_obj *qo,
+ struct bnx2x_exeq_elem *elem)
+{
+ struct bnx2x_exeq_elem query, *pos;
+ struct bnx2x_vlan_mac_obj *o = &qo->vlan_mac;
+ struct bnx2x_exe_queue_obj *exeq = &o->exe_queue;
+
+ memcpy(&query, elem, sizeof(query));
+
+ switch (elem->cmd_data.vlan_mac.cmd) {
+ case BNX2X_VLAN_MAC_ADD:
+ query.cmd_data.vlan_mac.cmd = BNX2X_VLAN_MAC_DEL;
+ break;
+ case BNX2X_VLAN_MAC_DEL:
+ query.cmd_data.vlan_mac.cmd = BNX2X_VLAN_MAC_ADD;
+ break;
+ default:
+ /* Don't handle anything other than ADD or DEL */
+ return 0;
+ }
+
+ /* If we found the appropriate element - delete it */
+ pos = exeq->get(exeq, &query);
+ if (pos) {
+
+ /* Return the credit of the optimized command */
+ if (!test_bit(BNX2X_DONT_CONSUME_CAM_CREDIT,
+ &pos->cmd_data.vlan_mac.vlan_mac_flags)) {
+ if ((query.cmd_data.vlan_mac.cmd ==
+ BNX2X_VLAN_MAC_ADD) && !o->put_credit(o)) {
+ BNX2X_ERR("Failed to return the credit for the "
+ "optimized ADD command\n");
+ return -EINVAL;
+ } else if (!o->get_credit(o)) { /* VLAN_MAC_DEL */
+ BNX2X_ERR("Failed to recover the credit from "
+ "the optimized DEL command\n");
+ return -EINVAL;
+ }
+ }
+
+ DP(BNX2X_MSG_SP, "Optimizing %s command\n",
+ (elem->cmd_data.vlan_mac.cmd == BNX2X_VLAN_MAC_ADD) ?
+ "ADD" : "DEL");
+
+ list_del(&pos->link);
+ bnx2x_exe_queue_free_elem(bp, pos);
+ return 1;
+ }
+
+ return 0;
+}
+
+/**
+ * bnx2x_vlan_mac_get_registry_elem - prepare a registry element
+ *
+ * @bp: device handle
+ * @o:
+ * @elem:
+ * @restore:
+ * @re:
+ *
+ * prepare a registry element according to the current command request.
+ */
+static inline int bnx2x_vlan_mac_get_registry_elem(
+ struct bnx2x *bp,
+ struct bnx2x_vlan_mac_obj *o,
+ struct bnx2x_exeq_elem *elem,
+ bool restore,
+ struct bnx2x_vlan_mac_registry_elem **re)
+{
+ int cmd = elem->cmd_data.vlan_mac.cmd;
+ struct bnx2x_vlan_mac_registry_elem *reg_elem;
+
+ /* Allocate a new registry element if needed. */
+ if (!restore &&
+ ((cmd == BNX2X_VLAN_MAC_ADD) || (cmd == BNX2X_VLAN_MAC_MOVE))) {
+ reg_elem = kzalloc(sizeof(*reg_elem), GFP_ATOMIC);
+ if (!reg_elem)
+ return -ENOMEM;
+
+ /* Get a new CAM offset */
+ if (!o->get_cam_offset(o, ®_elem->cam_offset)) {
+ /*
+ * This shell never happen, because we have checked the
+ * CAM availiability in the 'validate'.
+ */
+ WARN_ON(1);
+ kfree(reg_elem);
+ return -EINVAL;
+ }
+
+ DP(BNX2X_MSG_SP, "Got cam offset %d\n", reg_elem->cam_offset);
+
+ /* Set a VLAN-MAC data */
+ memcpy(®_elem->u, &elem->cmd_data.vlan_mac.u,
+ sizeof(reg_elem->u));
+
+ /* Copy the flags (needed for DEL and RESTORE flows) */
+ reg_elem->vlan_mac_flags =
+ elem->cmd_data.vlan_mac.vlan_mac_flags;
+ } else /* DEL, RESTORE */
+ reg_elem = o->check_del(o, &elem->cmd_data.vlan_mac.u);
+
+ *re = reg_elem;
+ return 0;
+}
+
+/**
+ * bnx2x_execute_vlan_mac - execute vlan mac command
+ *
+ * @bp: device handle
+ * @qo:
+ * @exe_chunk:
+ * @ramrod_flags:
+ *
+ * go and send a ramrod!
+ */
+static int bnx2x_execute_vlan_mac(struct bnx2x *bp,
+ union bnx2x_qable_obj *qo,
+ struct list_head *exe_chunk,
+ unsigned long *ramrod_flags)
+{
+ struct bnx2x_exeq_elem *elem;
+ struct bnx2x_vlan_mac_obj *o = &qo->vlan_mac, *cam_obj;
+ struct bnx2x_raw_obj *r = &o->raw;
+ int rc, idx = 0;
+ bool restore = test_bit(RAMROD_RESTORE, ramrod_flags);
+ bool drv_only = test_bit(RAMROD_DRV_CLR_ONLY, ramrod_flags);
+ struct bnx2x_vlan_mac_registry_elem *reg_elem;
+ int cmd;
+
+ /*
+ * If DRIVER_ONLY execution is requested, cleanup a registry
+ * and exit. Otherwise send a ramrod to FW.
+ */
+ if (!drv_only) {
+ WARN_ON(r->check_pending(r));
+
+ /* Set pending */
+ r->set_pending(r);
+
+ /* Fill tha ramrod data */
+ list_for_each_entry(elem, exe_chunk, link) {
+ cmd = elem->cmd_data.vlan_mac.cmd;
+ /*
+ * We will add to the target object in MOVE command, so
+ * change the object for a CAM search.
+ */
+ if (cmd == BNX2X_VLAN_MAC_MOVE)
+ cam_obj = elem->cmd_data.vlan_mac.target_obj;
+ else
+ cam_obj = o;
+
+ rc = bnx2x_vlan_mac_get_registry_elem(bp, cam_obj,
+ elem, restore,
+ ®_elem);
+ if (rc)
+ goto error_exit;
+
+ WARN_ON(!reg_elem);
+
+ /* Push a new entry into the registry */
+ if (!restore &&
+ ((cmd == BNX2X_VLAN_MAC_ADD) ||
+ (cmd == BNX2X_VLAN_MAC_MOVE)))
+ list_add(®_elem->link, &cam_obj->head);
+
+ /* Configure a single command in a ramrod data buffer */
+ o->set_one_rule(bp, o, elem, idx,
+ reg_elem->cam_offset);
+
+ /* MOVE command consumes 2 entries in the ramrod data */
+ if (cmd == BNX2X_VLAN_MAC_MOVE)
+ idx += 2;
+ else
+ idx++;
+ }
+
+ /* Commit the data writes towards the memory */
+ mb();
+
+ rc = bnx2x_sp_post(bp, o->ramrod_cmd, r->cid,
+ U64_HI(r->rdata_mapping),
+ U64_LO(r->rdata_mapping),
+ ETH_CONNECTION_TYPE);
+ if (rc)
+ goto error_exit;
+ }
+
+ /* Now, when we are done with the ramrod - clean up the registry */
+ list_for_each_entry(elem, exe_chunk, link) {
+ cmd = elem->cmd_data.vlan_mac.cmd;
+ if ((cmd == BNX2X_VLAN_MAC_DEL) ||
+ (cmd == BNX2X_VLAN_MAC_MOVE)) {
+ reg_elem = o->check_del(o, &elem->cmd_data.vlan_mac.u);
+
+ WARN_ON(!reg_elem);
+
+ o->put_cam_offset(o, reg_elem->cam_offset);
+ list_del(®_elem->link);
+ kfree(reg_elem);
+ }
+ }
+
+ if (!drv_only)
+ return 1;
+ else
+ return 0;
+
+error_exit:
+ r->clear_pending(r);
+
+ /* Cleanup a registry in case of a failure */
+ list_for_each_entry(elem, exe_chunk, link) {
+ cmd = elem->cmd_data.vlan_mac.cmd;
+
+ if (cmd == BNX2X_VLAN_MAC_MOVE)
+ cam_obj = elem->cmd_data.vlan_mac.target_obj;
+ else
+ cam_obj = o;
+
+ /* Delete all newly added above entries */
+ if (!restore &&
+ ((cmd == BNX2X_VLAN_MAC_ADD) ||
+ (cmd == BNX2X_VLAN_MAC_MOVE))) {
+ reg_elem = o->check_del(cam_obj,
+ &elem->cmd_data.vlan_mac.u);
+ if (reg_elem) {
+ list_del(®_elem->link);
+ kfree(reg_elem);
+ }
+ }
+ }
+
+ return rc;
+}
+
+static inline int bnx2x_vlan_mac_push_new_cmd(
+ struct bnx2x *bp,
+ struct bnx2x_vlan_mac_ramrod_params *p)
+{
+ struct bnx2x_exeq_elem *elem;
+ struct bnx2x_vlan_mac_obj *o = p->vlan_mac_obj;
+ bool restore = test_bit(RAMROD_RESTORE, &p->ramrod_flags);
+
+ /* Allocate the execution queue element */
+ elem = bnx2x_exe_queue_alloc_elem(bp);
+ if (!elem)
+ return -ENOMEM;
+
+ /* Set the command 'length' */
+ switch (p->user_req.cmd) {
+ case BNX2X_VLAN_MAC_MOVE:
+ elem->cmd_len = 2;
+ break;
+ default:
+ elem->cmd_len = 1;
+ }
+
+ /* Fill the object specific info */
+ memcpy(&elem->cmd_data.vlan_mac, &p->user_req, sizeof(p->user_req));
+
+ /* Try to add a new command to the pending list */
+ return bnx2x_exe_queue_add(bp, &o->exe_queue, elem, restore);
+}
+
+/**
+ * bnx2x_config_vlan_mac - configure VLAN/MAC/VLAN_MAC filtering rules.
+ *
+ * @bp: device handle
+ * @p:
+ *
+ */
+int bnx2x_config_vlan_mac(
+ struct bnx2x *bp,
+ struct bnx2x_vlan_mac_ramrod_params *p)
+{
+ int rc = 0;
+ struct bnx2x_vlan_mac_obj *o = p->vlan_mac_obj;
+ unsigned long *ramrod_flags = &p->ramrod_flags;
+ bool cont = test_bit(RAMROD_CONT, ramrod_flags);
+ struct bnx2x_raw_obj *raw = &o->raw;
+
+ /*
+ * Add new elements to the execution list for commands that require it.
+ */
+ if (!cont) {
+ rc = bnx2x_vlan_mac_push_new_cmd(bp, p);
+ if (rc)
+ return rc;
+ }
+
+ /*
+ * If nothing will be executed further in this iteration we want to
+ * return PENDING if there are pending commands
+ */
+ if (!bnx2x_exe_queue_empty(&o->exe_queue))
+ rc = 1;
+
+ /* Execute commands if required */
+ if (cont || test_bit(RAMROD_EXEC, ramrod_flags) ||
+ test_bit(RAMROD_COMP_WAIT, ramrod_flags)) {
+ rc = bnx2x_exe_queue_step(bp, &o->exe_queue, ramrod_flags);
+ if (rc < 0)
+ return rc;
+ }
+
+ /*
+ * RAMROD_COMP_WAIT is a superset of RAMROD_EXEC. If it was set
+ * then user want to wait until the last command is done.
+ */
+ if (test_bit(RAMROD_COMP_WAIT, &p->ramrod_flags)) {
+ /*
+ * Wait maximum for the current exe_queue length iterations plus
+ * one (for the current pending command).
+ */
+ int max_iterations = bnx2x_exe_queue_length(&o->exe_queue) + 1;
+
+ while (!bnx2x_exe_queue_empty(&o->exe_queue) &&
+ max_iterations--) {
+
+ /* Wait for the current command to complete */
+ rc = raw->wait_comp(bp, raw);
+ if (rc)
+ return rc;
+
+ /* Make a next step */
+ rc = bnx2x_exe_queue_step(bp, &o->exe_queue,
+ ramrod_flags);
+ if (rc < 0)
+ return rc;
+ }
+
+ return 0;
+ }
+
+ return rc;
+}
+
+
+
+/**
+ * bnx2x_vlan_mac_del_all - delete elements with given vlan_mac_flags spec
+ *
+ * @bp: device handle
+ * @o:
+ * @vlan_mac_flags:
+ * @ramrod_flags: execution flags to be used for this deletion
+ *
+ * if the last operation has completed successfully and there are no
+ * moreelements left, positive value if the last operation has completed
+ * successfully and there are more previously configured elements, negative
+ * value is current operation has failed.
+ */
+static int bnx2x_vlan_mac_del_all(struct bnx2x *bp,
+ struct bnx2x_vlan_mac_obj *o,
+ unsigned long *vlan_mac_flags,
+ unsigned long *ramrod_flags)
+{
+ struct bnx2x_vlan_mac_registry_elem *pos = NULL;
+ int rc = 0;
+ struct bnx2x_vlan_mac_ramrod_params p;
+ struct bnx2x_exe_queue_obj *exeq = &o->exe_queue;
+ struct bnx2x_exeq_elem *exeq_pos, *exeq_pos_n;
+
+ /* Clear pending commands first */
+
+ spin_lock_bh(&exeq->lock);
+
+ list_for_each_entry_safe(exeq_pos, exeq_pos_n, &exeq->exe_queue, link) {
+ if (exeq_pos->cmd_data.vlan_mac.vlan_mac_flags ==
+ *vlan_mac_flags)
+ list_del(&exeq_pos->link);
+ }
+
+ spin_unlock_bh(&exeq->lock);
+
+ /* Prepare a command request */
+ memset(&p, 0, sizeof(p));
+ p.vlan_mac_obj = o;
+ p.ramrod_flags = *ramrod_flags;
+ p.user_req.cmd = BNX2X_VLAN_MAC_DEL;
+
+ /*
+ * Add all but the last VLAN-MAC to the execution queue without actually
+ * execution anything.
+ */
+ __clear_bit(RAMROD_COMP_WAIT, &p.ramrod_flags);
+ __clear_bit(RAMROD_EXEC, &p.ramrod_flags);
+ __clear_bit(RAMROD_CONT, &p.ramrod_flags);
+
+ list_for_each_entry(pos, &o->head, link) {
+ if (pos->vlan_mac_flags == *vlan_mac_flags) {
+ p.user_req.vlan_mac_flags = pos->vlan_mac_flags;
+ memcpy(&p.user_req.u, &pos->u, sizeof(pos->u));
+ rc = bnx2x_config_vlan_mac(bp, &p);
+ if (rc < 0) {
+ BNX2X_ERR("Failed to add a new DEL command\n");
+ return rc;
+ }
+ }
+ }
+
+ p.ramrod_flags = *ramrod_flags;
+ __set_bit(RAMROD_CONT, &p.ramrod_flags);
+
+ return bnx2x_config_vlan_mac(bp, &p);
+}
+
+static inline void bnx2x_init_raw_obj(struct bnx2x_raw_obj *raw, u8 cl_id,
+ u32 cid, u8 func_id, void *rdata, dma_addr_t rdata_mapping, int state,
+ unsigned long *pstate, bnx2x_obj_type type)
+{
+ raw->func_id = func_id;
+ raw->cid = cid;
+ raw->cl_id = cl_id;
+ raw->rdata = rdata;
+ raw->rdata_mapping = rdata_mapping;
+ raw->state = state;
+ raw->pstate = pstate;
+ raw->obj_type = type;
+ raw->check_pending = bnx2x_raw_check_pending;
+ raw->clear_pending = bnx2x_raw_clear_pending;
+ raw->set_pending = bnx2x_raw_set_pending;
+ raw->wait_comp = bnx2x_raw_wait;
+}
+
+static inline void bnx2x_init_vlan_mac_common(struct bnx2x_vlan_mac_obj *o,
+ u8 cl_id, u32 cid, u8 func_id, void *rdata, dma_addr_t rdata_mapping,
+ int state, unsigned long *pstate, bnx2x_obj_type type,
+ struct bnx2x_credit_pool_obj *macs_pool,
+ struct bnx2x_credit_pool_obj *vlans_pool)
+{
+ INIT_LIST_HEAD(&o->head);
+
+ o->macs_pool = macs_pool;
+ o->vlans_pool = vlans_pool;
+
+ o->delete_all = bnx2x_vlan_mac_del_all;
+ o->restore = bnx2x_vlan_mac_restore;
+ o->complete = bnx2x_complete_vlan_mac;
+ o->wait = bnx2x_wait_vlan_mac;
+
+ bnx2x_init_raw_obj(&o->raw, cl_id, cid, func_id, rdata, rdata_mapping,
+ state, pstate, type);
+}
+
+
+void bnx2x_init_mac_obj(struct bnx2x *bp,
+ struct bnx2x_vlan_mac_obj *mac_obj,
+ u8 cl_id, u32 cid, u8 func_id, void *rdata,
+ dma_addr_t rdata_mapping, int state,
+ unsigned long *pstate, bnx2x_obj_type type,
+ struct bnx2x_credit_pool_obj *macs_pool)
+{
+ union bnx2x_qable_obj *qable_obj = (union bnx2x_qable_obj *)mac_obj;
+
+ bnx2x_init_vlan_mac_common(mac_obj, cl_id, cid, func_id, rdata,
+ rdata_mapping, state, pstate, type,
+ macs_pool, NULL);
+
+ /* CAM credit pool handling */
+ mac_obj->get_credit = bnx2x_get_credit_mac;
+ mac_obj->put_credit = bnx2x_put_credit_mac;
+ mac_obj->get_cam_offset = bnx2x_get_cam_offset_mac;
+ mac_obj->put_cam_offset = bnx2x_put_cam_offset_mac;
+
+ if (CHIP_IS_E1x(bp)) {
+ mac_obj->set_one_rule = bnx2x_set_one_mac_e1x;
+ mac_obj->check_del = bnx2x_check_mac_del;
+ mac_obj->check_add = bnx2x_check_mac_add;
+ mac_obj->check_move = bnx2x_check_move_always_err;
+ mac_obj->ramrod_cmd = RAMROD_CMD_ID_ETH_SET_MAC;
+
+ /* Exe Queue */
+ bnx2x_exe_queue_init(bp,
+ &mac_obj->exe_queue, 1, qable_obj,
+ bnx2x_validate_vlan_mac,
+ bnx2x_optimize_vlan_mac,
+ bnx2x_execute_vlan_mac,
+ bnx2x_exeq_get_mac);
+ } else {
+ mac_obj->set_one_rule = bnx2x_set_one_mac_e2;
+ mac_obj->check_del = bnx2x_check_mac_del;
+ mac_obj->check_add = bnx2x_check_mac_add;
+ mac_obj->check_move = bnx2x_check_move;
+ mac_obj->ramrod_cmd =
+ RAMROD_CMD_ID_ETH_CLASSIFICATION_RULES;
+
+ /* Exe Queue */
+ bnx2x_exe_queue_init(bp,
+ &mac_obj->exe_queue, CLASSIFY_RULES_COUNT,
+ qable_obj, bnx2x_validate_vlan_mac,
+ bnx2x_optimize_vlan_mac,
+ bnx2x_execute_vlan_mac,
+ bnx2x_exeq_get_mac);
+ }
+}
+
+void bnx2x_init_vlan_obj(struct bnx2x *bp,
+ struct bnx2x_vlan_mac_obj *vlan_obj,
+ u8 cl_id, u32 cid, u8 func_id, void *rdata,
+ dma_addr_t rdata_mapping, int state,
+ unsigned long *pstate, bnx2x_obj_type type,
+ struct bnx2x_credit_pool_obj *vlans_pool)
+{
+ union bnx2x_qable_obj *qable_obj = (union bnx2x_qable_obj *)vlan_obj;
+
+ bnx2x_init_vlan_mac_common(vlan_obj, cl_id, cid, func_id, rdata,
+ rdata_mapping, state, pstate, type, NULL,
+ vlans_pool);
+
+ vlan_obj->get_credit = bnx2x_get_credit_vlan;
+ vlan_obj->put_credit = bnx2x_put_credit_vlan;
+ vlan_obj->get_cam_offset = bnx2x_get_cam_offset_vlan;
+ vlan_obj->put_cam_offset = bnx2x_put_cam_offset_vlan;
+
+ if (CHIP_IS_E1x(bp)) {
+ BNX2X_ERR("Do not support chips others than E2 and newer\n");
+ BUG();
+ } else {
+ vlan_obj->set_one_rule = bnx2x_set_one_vlan_e2;
+ vlan_obj->check_del = bnx2x_check_vlan_del;
+ vlan_obj->check_add = bnx2x_check_vlan_add;
+ vlan_obj->check_move = bnx2x_check_move;
+ vlan_obj->ramrod_cmd =
+ RAMROD_CMD_ID_ETH_CLASSIFICATION_RULES;
+
+ /* Exe Queue */
+ bnx2x_exe_queue_init(bp,
+ &vlan_obj->exe_queue, CLASSIFY_RULES_COUNT,
+ qable_obj, bnx2x_validate_vlan_mac,
+ bnx2x_optimize_vlan_mac,
+ bnx2x_execute_vlan_mac,
+ bnx2x_exeq_get_vlan);
+ }
+}
+
+void bnx2x_init_vlan_mac_obj(struct bnx2x *bp,
+ struct bnx2x_vlan_mac_obj *vlan_mac_obj,
+ u8 cl_id, u32 cid, u8 func_id, void *rdata,
+ dma_addr_t rdata_mapping, int state,
+ unsigned long *pstate, bnx2x_obj_type type,
+ struct bnx2x_credit_pool_obj *macs_pool,
+ struct bnx2x_credit_pool_obj *vlans_pool)
+{
+ union bnx2x_qable_obj *qable_obj =
+ (union bnx2x_qable_obj *)vlan_mac_obj;
+
+ bnx2x_init_vlan_mac_common(vlan_mac_obj, cl_id, cid, func_id, rdata,
+ rdata_mapping, state, pstate, type,
+ macs_pool, vlans_pool);
+
+ /* CAM pool handling */
+ vlan_mac_obj->get_credit = bnx2x_get_credit_vlan_mac;
+ vlan_mac_obj->put_credit = bnx2x_put_credit_vlan_mac;
+ /*
+ * CAM offset is relevant for 57710 and 57711 chips only which have a
+ * single CAM for both MACs and VLAN-MAC pairs. So the offset
+ * will be taken from MACs' pool object only.
+ */
+ vlan_mac_obj->get_cam_offset = bnx2x_get_cam_offset_mac;
+ vlan_mac_obj->put_cam_offset = bnx2x_put_cam_offset_mac;
+
+ if (CHIP_IS_E1(bp)) {
+ BNX2X_ERR("Do not support chips others than E2\n");
+ BUG();
+ } else if (CHIP_IS_E1H(bp)) {
+ vlan_mac_obj->set_one_rule = bnx2x_set_one_vlan_mac_e1h;
+ vlan_mac_obj->check_del = bnx2x_check_vlan_mac_del;
+ vlan_mac_obj->check_add = bnx2x_check_vlan_mac_add;
+ vlan_mac_obj->check_move = bnx2x_check_move_always_err;
+ vlan_mac_obj->ramrod_cmd = RAMROD_CMD_ID_ETH_SET_MAC;
+
+ /* Exe Queue */
+ bnx2x_exe_queue_init(bp,
+ &vlan_mac_obj->exe_queue, 1, qable_obj,
+ bnx2x_validate_vlan_mac,
+ bnx2x_optimize_vlan_mac,
+ bnx2x_execute_vlan_mac,
+ bnx2x_exeq_get_vlan_mac);
+ } else {
+ vlan_mac_obj->set_one_rule = bnx2x_set_one_vlan_mac_e2;
+ vlan_mac_obj->check_del = bnx2x_check_vlan_mac_del;
+ vlan_mac_obj->check_add = bnx2x_check_vlan_mac_add;
+ vlan_mac_obj->check_move = bnx2x_check_move;
+ vlan_mac_obj->ramrod_cmd =
+ RAMROD_CMD_ID_ETH_CLASSIFICATION_RULES;
+
+ /* Exe Queue */
+ bnx2x_exe_queue_init(bp,
+ &vlan_mac_obj->exe_queue,
+ CLASSIFY_RULES_COUNT,
+ qable_obj, bnx2x_validate_vlan_mac,
+ bnx2x_optimize_vlan_mac,
+ bnx2x_execute_vlan_mac,
+ bnx2x_exeq_get_vlan_mac);
+ }
+
+}
+
+/* RX_MODE verbs: DROP_ALL/ACCEPT_ALL/ACCEPT_ALL_MULTI/ACCEPT_ALL_VLAN/NORMAL */
+static inline void __storm_memset_mac_filters(struct bnx2x *bp,
+ struct tstorm_eth_mac_filter_config *mac_filters,
+ u16 pf_id)
+{
+ size_t size = sizeof(struct tstorm_eth_mac_filter_config);
+
+ u32 addr = BAR_TSTRORM_INTMEM +
+ TSTORM_MAC_FILTER_CONFIG_OFFSET(pf_id);
+
+ __storm_memset_struct(bp, addr, size, (u32 *)mac_filters);
+}
+
+static int bnx2x_set_rx_mode_e1x(struct bnx2x *bp,
+ struct bnx2x_rx_mode_ramrod_params *p)
+{
+ /* update the bp MAC filter structure */
+ u32 mask = (1 << p->cl_id);
+
+ struct tstorm_eth_mac_filter_config *mac_filters =
+ (struct tstorm_eth_mac_filter_config *)p->rdata;
+
+ /* initial seeting is drop-all */
+ u8 drop_all_ucast = 1, drop_all_mcast = 1;
+ u8 accp_all_ucast = 0, accp_all_bcast = 0, accp_all_mcast = 0;
+ u8 unmatched_unicast = 0;
+
+ /* In e1x there we only take into account rx acceot flag since tx switching
+ * isn't enabled. */
+ if (test_bit(BNX2X_ACCEPT_UNICAST, &p->rx_accept_flags))
+ /* accept matched ucast */
+ drop_all_ucast = 0;
+
+ if (test_bit(BNX2X_ACCEPT_MULTICAST, &p->rx_accept_flags))
+ /* accept matched mcast */
+ drop_all_mcast = 0;
+
+ if (test_bit(BNX2X_ACCEPT_ALL_UNICAST, &p->rx_accept_flags)) {
+ /* accept all mcast */
+ drop_all_ucast = 0;
+ accp_all_ucast = 1;
+ }
+ if (test_bit(BNX2X_ACCEPT_ALL_MULTICAST, &p->rx_accept_flags)) {
+ /* accept all mcast */
+ drop_all_mcast = 0;
+ accp_all_mcast = 1;
+ }
+ if (test_bit(BNX2X_ACCEPT_BROADCAST, &p->rx_accept_flags))
+ /* accept (all) bcast */
+ accp_all_bcast = 1;
+ if (test_bit(BNX2X_ACCEPT_UNMATCHED, &p->rx_accept_flags))
+ /* accept unmatched unicasts */
+ unmatched_unicast = 1;
+
+ mac_filters->ucast_drop_all = drop_all_ucast ?
+ mac_filters->ucast_drop_all | mask :
+ mac_filters->ucast_drop_all & ~mask;
+
+ mac_filters->mcast_drop_all = drop_all_mcast ?
+ mac_filters->mcast_drop_all | mask :
+ mac_filters->mcast_drop_all & ~mask;
+
+ mac_filters->ucast_accept_all = accp_all_ucast ?
+ mac_filters->ucast_accept_all | mask :
+ mac_filters->ucast_accept_all & ~mask;
+
+ mac_filters->mcast_accept_all = accp_all_mcast ?
+ mac_filters->mcast_accept_all | mask :
+ mac_filters->mcast_accept_all & ~mask;
+
+ mac_filters->bcast_accept_all = accp_all_bcast ?
+ mac_filters->bcast_accept_all | mask :
+ mac_filters->bcast_accept_all & ~mask;
+
+ mac_filters->unmatched_unicast = unmatched_unicast ?
+ mac_filters->unmatched_unicast | mask :
+ mac_filters->unmatched_unicast & ~mask;
+
+ DP(BNX2X_MSG_SP, "drop_ucast 0x%x\ndrop_mcast 0x%x\n accp_ucast 0x%x\n"
+ "accp_mcast 0x%x\naccp_bcast 0x%x\n",
+ mac_filters->ucast_drop_all,
+ mac_filters->mcast_drop_all,
+ mac_filters->ucast_accept_all,
+ mac_filters->mcast_accept_all,
+ mac_filters->bcast_accept_all);
+
+ /* write the MAC filter structure*/
+ __storm_memset_mac_filters(bp, mac_filters, p->func_id);
+
+ /* The operation is completed */
+ clear_bit(p->state, p->pstate);
+ smp_mb__after_clear_bit();
+
+ return 0;
+}
+
+/* Setup ramrod data */
+static inline void bnx2x_rx_mode_set_rdata_hdr_e2(u32 cid,
+ struct eth_classify_header *hdr,
+ u8 rule_cnt)
+{
+ hdr->echo = cid;
+ hdr->rule_cnt = rule_cnt;
+}
+
+static inline void bnx2x_rx_mode_set_cmd_state_e2(struct bnx2x *bp,
+ unsigned long accept_flags,
+ struct eth_filter_rules_cmd *cmd,
+ bool clear_accept_all)
+{
+ u16 state;
+
+ /* start with 'drop-all' */
+ state = ETH_FILTER_RULES_CMD_UCAST_DROP_ALL |
+ ETH_FILTER_RULES_CMD_MCAST_DROP_ALL;
+
+ if (accept_flags) {
+ if (test_bit(BNX2X_ACCEPT_UNICAST, &accept_flags))
+ state &= ~ETH_FILTER_RULES_CMD_UCAST_DROP_ALL;
+
+ if (test_bit(BNX2X_ACCEPT_MULTICAST, &accept_flags))
+ state &= ~ETH_FILTER_RULES_CMD_MCAST_DROP_ALL;
+
+ if (test_bit(BNX2X_ACCEPT_ALL_UNICAST, &accept_flags)) {
+ state &= ~ETH_FILTER_RULES_CMD_UCAST_DROP_ALL;
+ state |= ETH_FILTER_RULES_CMD_UCAST_ACCEPT_ALL;
+ }
+
+ if (test_bit(BNX2X_ACCEPT_ALL_MULTICAST, &accept_flags)) {
+ state |= ETH_FILTER_RULES_CMD_MCAST_ACCEPT_ALL;
+ state &= ~ETH_FILTER_RULES_CMD_MCAST_DROP_ALL;
+ }
+ if (test_bit(BNX2X_ACCEPT_BROADCAST, &accept_flags))
+ state |= ETH_FILTER_RULES_CMD_BCAST_ACCEPT_ALL;
+
+ if (test_bit(BNX2X_ACCEPT_UNMATCHED, &accept_flags)) {
+ state &= ~ETH_FILTER_RULES_CMD_UCAST_DROP_ALL;
+ state |= ETH_FILTER_RULES_CMD_UCAST_ACCEPT_UNMATCHED;
+ }
+ if (test_bit(BNX2X_ACCEPT_ANY_VLAN, &accept_flags))
+ state |= ETH_FILTER_RULES_CMD_ACCEPT_ANY_VLAN;
+ }
+
+ /* Clear ACCEPT_ALL_XXX flags for FCoE L2 Queue */
+ if (clear_accept_all) {
+ state &= ~ETH_FILTER_RULES_CMD_MCAST_ACCEPT_ALL;
+ state &= ~ETH_FILTER_RULES_CMD_BCAST_ACCEPT_ALL;
+ state &= ~ETH_FILTER_RULES_CMD_UCAST_ACCEPT_ALL;
+ state &= ~ETH_FILTER_RULES_CMD_UCAST_ACCEPT_UNMATCHED;
+ }
+
+ cmd->state = cpu_to_le16(state);
+
+}
+
+static int bnx2x_set_rx_mode_e2(struct bnx2x *bp,
+ struct bnx2x_rx_mode_ramrod_params *p)
+{
+ struct eth_filter_rules_ramrod_data *data = p->rdata;
+ int rc;
+ u8 rule_idx = 0;
+
+ /* Reset the ramrod data buffer */
+ memset(data, 0, sizeof(*data));
+
+ /* Setup ramrod data */
+
+ /* Tx (internal switching) */
+ if (test_bit(RAMROD_TX, &p->ramrod_flags)) {
+ data->rules[rule_idx].client_id = p->cl_id;
+ data->rules[rule_idx].func_id = p->func_id;
+
+ data->rules[rule_idx].cmd_general_data =
+ ETH_FILTER_RULES_CMD_TX_CMD;
+
+ bnx2x_rx_mode_set_cmd_state_e2(bp, p->tx_accept_flags,
+ &(data->rules[rule_idx++]), false);
+ }
+
+ /* Rx */
+ if (test_bit(RAMROD_RX, &p->ramrod_flags)) {
+ data->rules[rule_idx].client_id = p->cl_id;
+ data->rules[rule_idx].func_id = p->func_id;
+
+ data->rules[rule_idx].cmd_general_data =
+ ETH_FILTER_RULES_CMD_RX_CMD;
+
+ bnx2x_rx_mode_set_cmd_state_e2(bp, p->rx_accept_flags,
+ &(data->rules[rule_idx++]), false);
+ }
+
+
+ /*
+ * If FCoE Queue configuration has been requested configure the Rx and
+ * internal switching modes for this queue in separate rules.
+ *
+ * FCoE queue shell never be set to ACCEPT_ALL packets of any sort:
+ * MCAST_ALL, UCAST_ALL, BCAST_ALL and UNMATCHED.
+ */
+ if (test_bit(BNX2X_RX_MODE_FCOE_ETH, &p->rx_mode_flags)) {
+ /* Tx (internal switching) */
+ if (test_bit(RAMROD_TX, &p->ramrod_flags)) {
+ data->rules[rule_idx].client_id = bnx2x_fcoe(bp, cl_id);
+ data->rules[rule_idx].func_id = p->func_id;
+
+ data->rules[rule_idx].cmd_general_data =
+ ETH_FILTER_RULES_CMD_TX_CMD;
+
+ bnx2x_rx_mode_set_cmd_state_e2(bp, p->tx_accept_flags,
+ &(data->rules[rule_idx++]),
+ true);
+ }
+
+ /* Rx */
+ if (test_bit(RAMROD_RX, &p->ramrod_flags)) {
+ data->rules[rule_idx].client_id = bnx2x_fcoe(bp, cl_id);
+ data->rules[rule_idx].func_id = p->func_id;
+
+ data->rules[rule_idx].cmd_general_data =
+ ETH_FILTER_RULES_CMD_RX_CMD;
+
+ bnx2x_rx_mode_set_cmd_state_e2(bp, p->rx_accept_flags,
+ &(data->rules[rule_idx++]),
+ true);
+ }
+ }
+
+ /*
+ * Set the ramrod header (most importantly - number of rules to
+ * configure).
+ */
+ bnx2x_rx_mode_set_rdata_hdr_e2(p->cid, &data->header, rule_idx);
+
+ DP(BNX2X_MSG_SP, "About to configure %d rules, rx_accept_flags 0x%lx, "
+ "tx_accept_flags 0x%lx\n",
+ data->header.rule_cnt, p->rx_accept_flags,
+ p->tx_accept_flags);
+
+ /* Commit writes towards the memory before sending a ramrod */
+ mb();
+
+ /* Send a ramrod */
+ rc = bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_FILTER_RULES, p->cid,
+ U64_HI(p->rdata_mapping),
+ U64_LO(p->rdata_mapping),
+ ETH_CONNECTION_TYPE);
+ if (rc)
+ return rc;
+
+ /* Ramrod completion is pending */
+ return 1;
+}
+
+static int bnx2x_wait_rx_mode_comp_e2(struct bnx2x *bp,
+ struct bnx2x_rx_mode_ramrod_params *p)
+{
+ return bnx2x_state_wait(bp, p->state, p->pstate);
+}
+
+static int bnx2x_empty_rx_mode_wait(struct bnx2x *bp,
+ struct bnx2x_rx_mode_ramrod_params *p)
+{
+ /* Do nothing */
+ return 0;
+}
+
+int bnx2x_config_rx_mode(struct bnx2x *bp,
+ struct bnx2x_rx_mode_ramrod_params *p)
+{
+ int rc;
+
+ /* Configure the new classification in the chip */
+ rc = p->rx_mode_obj->config_rx_mode(bp, p);
+ if (rc < 0)
+ return rc;
+
+ /* Wait for a ramrod completion if was requested */
+ if (test_bit(RAMROD_COMP_WAIT, &p->ramrod_flags)) {
+ rc = p->rx_mode_obj->wait_comp(bp, p);
+ if (rc)
+ return rc;
+ }
+
+ return rc;
+}
+
+void bnx2x_init_rx_mode_obj(struct bnx2x *bp,
+ struct bnx2x_rx_mode_obj *o)
+{
+ if (CHIP_IS_E1x(bp)) {
+ o->wait_comp = bnx2x_empty_rx_mode_wait;
+ o->config_rx_mode = bnx2x_set_rx_mode_e1x;
+ } else {
+ o->wait_comp = bnx2x_wait_rx_mode_comp_e2;
+ o->config_rx_mode = bnx2x_set_rx_mode_e2;
+ }
+}
+
+/********************* Multicast verbs: SET, CLEAR ****************************/
+static inline u8 bnx2x_mcast_bin_from_mac(u8 *mac)
+{
+ return (crc32c_le(0, mac, ETH_ALEN) >> 24) & 0xff;
+}
+
+struct bnx2x_mcast_mac_elem {
+ struct list_head link;
+ u8 mac[ETH_ALEN];
+ u8 pad[2]; /* For a natural alignment of the following buffer */
+};
+
+struct bnx2x_pending_mcast_cmd {
+ struct list_head link;
+ int type; /* BNX2X_MCAST_CMD_X */
+ union {
+ struct list_head macs_head;
+ u32 macs_num; /* Needed for DEL command */
+ int next_bin; /* Needed for RESTORE flow with aprox match */
+ } data;
+
+ bool done; /* set to true, when the command has been handled,
+ * practically used in 57712 handling only, where one pending
+ * command may be handled in a few operations. As long as for
+ * other chips every operation handling is completed in a
+ * single ramrod, there is no need to utilize this field.
+ */
+};
+
+static int bnx2x_mcast_wait(struct bnx2x *bp,
+ struct bnx2x_mcast_obj *o)
+{
+ if (bnx2x_state_wait(bp, o->sched_state, o->raw.pstate) ||
+ o->raw.wait_comp(bp, &o->raw))
+ return -EBUSY;
+
+ return 0;
+}
+
+static int bnx2x_mcast_enqueue_cmd(struct bnx2x *bp,
+ struct bnx2x_mcast_obj *o,
+ struct bnx2x_mcast_ramrod_params *p,
+ int cmd)
+{
+ int total_sz;
+ struct bnx2x_pending_mcast_cmd *new_cmd;
+ struct bnx2x_mcast_mac_elem *cur_mac = NULL;
+ struct bnx2x_mcast_list_elem *pos;
+ int macs_list_len = ((cmd == BNX2X_MCAST_CMD_ADD) ?
+ p->mcast_list_len : 0);
+
+ /* If the command is empty ("handle pending commands only"), break */
+ if (!p->mcast_list_len)
+ return 0;
+
+ total_sz = sizeof(*new_cmd) +
+ macs_list_len * sizeof(struct bnx2x_mcast_mac_elem);
+
+ /* Add mcast is called under spin_lock, thus calling with GFP_ATOMIC */
+ new_cmd = kzalloc(total_sz, GFP_ATOMIC);
+
+ if (!new_cmd)
+ return -ENOMEM;
+
+ DP(BNX2X_MSG_SP, "About to enqueue a new %d command. "
+ "macs_list_len=%d\n", cmd, macs_list_len);
+
+ INIT_LIST_HEAD(&new_cmd->data.macs_head);
+
+ new_cmd->type = cmd;
+ new_cmd->done = false;
+
+ switch (cmd) {
+ case BNX2X_MCAST_CMD_ADD:
+ cur_mac = (struct bnx2x_mcast_mac_elem *)
+ ((u8 *)new_cmd + sizeof(*new_cmd));
+
+ /* Push the MACs of the current command into the pendig command
+ * MACs list: FIFO
+ */
+ list_for_each_entry(pos, &p->mcast_list, link) {
+ memcpy(cur_mac->mac, pos->mac, ETH_ALEN);
+ list_add_tail(&cur_mac->link, &new_cmd->data.macs_head);
+ cur_mac++;
+ }
+
+ break;
+
+ case BNX2X_MCAST_CMD_DEL:
+ new_cmd->data.macs_num = p->mcast_list_len;
+ break;
+
+ case BNX2X_MCAST_CMD_RESTORE:
+ new_cmd->data.next_bin = 0;
+ break;
+
+ default:
+ BNX2X_ERR("Unknown command: %d\n", cmd);
+ return -EINVAL;
+ }
+
+ /* Push the new pending command to the tail of the pending list: FIFO */
+ list_add_tail(&new_cmd->link, &o->pending_cmds_head);
+
+ o->set_sched(o);
+
+ return 1;
+}
+
+/**
+ * bnx2x_mcast_get_next_bin - get the next set bin (index)
+ *
+ * @o:
+ * @last: index to start looking from (including)
+ *
+ * returns the next found (set) bin or a negative value if none is found.
+ */
+static inline int bnx2x_mcast_get_next_bin(struct bnx2x_mcast_obj *o, int last)
+{
+ int i, j, inner_start = last % BIT_VEC64_ELEM_SZ;
+
+ for (i = last / BIT_VEC64_ELEM_SZ; i < BNX2X_MCAST_VEC_SZ; i++) {
+ if (o->registry.aprox_match.vec[i])
+ for (j = inner_start; j < BIT_VEC64_ELEM_SZ; j++) {
+ int cur_bit = j + BIT_VEC64_ELEM_SZ * i;
+ if (BIT_VEC64_TEST_BIT(o->registry.aprox_match.
+ vec, cur_bit)) {
+ return cur_bit;
+ }
+ }
+ inner_start = 0;
+ }
+
+ /* None found */
+ return -1;
+}
+
+/**
+ * bnx2x_mcast_clear_first_bin - find the first set bin and clear it
+ *
+ * @o:
+ *
+ * returns the index of the found bin or -1 if none is found
+ */
+static inline int bnx2x_mcast_clear_first_bin(struct bnx2x_mcast_obj *o)
+{
+ int cur_bit = bnx2x_mcast_get_next_bin(o, 0);
+
+ if (cur_bit >= 0)
+ BIT_VEC64_CLEAR_BIT(o->registry.aprox_match.vec, cur_bit);
+
+ return cur_bit;
+}
+
+static inline u8 bnx2x_mcast_get_rx_tx_flag(struct bnx2x_mcast_obj *o)
+{
+ struct bnx2x_raw_obj *raw = &o->raw;
+ u8 rx_tx_flag = 0;
+
+ if ((raw->obj_type == BNX2X_OBJ_TYPE_TX) ||
+ (raw->obj_type == BNX2X_OBJ_TYPE_RX_TX))
+ rx_tx_flag |= ETH_MULTICAST_RULES_CMD_TX_CMD;
+
+ if ((raw->obj_type == BNX2X_OBJ_TYPE_RX) ||
+ (raw->obj_type == BNX2X_OBJ_TYPE_RX_TX))
+ rx_tx_flag |= ETH_MULTICAST_RULES_CMD_RX_CMD;
+
+ return rx_tx_flag;
+}
+
+static void bnx2x_mcast_set_one_rule_e2(struct bnx2x *bp,
+ struct bnx2x_mcast_obj *o, int idx,
+ union bnx2x_mcast_config_data *cfg_data,
+ int cmd)
+{
+ struct bnx2x_raw_obj *r = &o->raw;
+ struct eth_multicast_rules_ramrod_data *data =
+ (struct eth_multicast_rules_ramrod_data *)(r->rdata);
+ u8 func_id = r->func_id;
+ u8 rx_tx_add_flag = bnx2x_mcast_get_rx_tx_flag(o);
+ int bin;
+
+ if ((cmd == BNX2X_MCAST_CMD_ADD) || (cmd == BNX2X_MCAST_CMD_RESTORE))
+ rx_tx_add_flag |= ETH_MULTICAST_RULES_CMD_IS_ADD;
+
+ data->rules[idx].cmd_general_data |= rx_tx_add_flag;
+
+ /* Get a bin and update a bins' vector */
+ switch (cmd) {
+ case BNX2X_MCAST_CMD_ADD:
+ bin = bnx2x_mcast_bin_from_mac(cfg_data->mac);
+ BIT_VEC64_SET_BIT(o->registry.aprox_match.vec, bin);
+ break;
+
+ case BNX2X_MCAST_CMD_DEL:
+ /* If there were no more bins to clear
+ * (bnx2x_mcast_clear_first_bin() returns -1) then we would
+ * clear any (0xff) bin.
+ * See bnx2x_mcast_validate_e2() for explanation when it may
+ * happen.
+ */
+ bin = bnx2x_mcast_clear_first_bin(o);
+ break;
+
+ case BNX2X_MCAST_CMD_RESTORE:
+ bin = cfg_data->bin;
+ break;
+
+ default:
+ BNX2X_ERR("Unknown command: %d\n", cmd);
+ return;
+ }
+
+ DP(BNX2X_MSG_SP, "%s bin %d\n",
+ ((rx_tx_add_flag & ETH_MULTICAST_RULES_CMD_IS_ADD) ?
+ "Setting" : "Clearing"), bin);
+
+ data->rules[idx].bin_id = (u8)bin;
+ data->rules[idx].func_id = func_id;
+ data->rules[idx].engine_id = o->engine_id;
+}
+
+/**
+ * bnx2x_mcast_handle_restore_cmd_e2 - restore configuration from the registry
+ *
+ * @bp: device handle
+ * @o:
+ * @start_bin: index in the registry to start from (including)
+ * @rdata_idx: index in the ramrod data to start from
+ *
+ * returns last handled bin index or -1 if all bins have been handled
+ */
+static inline int bnx2x_mcast_handle_restore_cmd_e2(
+ struct bnx2x *bp, struct bnx2x_mcast_obj *o , int start_bin,
+ int *rdata_idx)
+{
+ int cur_bin, cnt = *rdata_idx;
+ union bnx2x_mcast_config_data cfg_data = {0};
+
+ /* go through the registry and configure the bins from it */
+ for (cur_bin = bnx2x_mcast_get_next_bin(o, start_bin); cur_bin >= 0;
+ cur_bin = bnx2x_mcast_get_next_bin(o, cur_bin + 1)) {
+
+ cfg_data.bin = (u8)cur_bin;
+ o->set_one_rule(bp, o, cnt, &cfg_data,
+ BNX2X_MCAST_CMD_RESTORE);
+
+ cnt++;
+
+ DP(BNX2X_MSG_SP, "About to configure a bin %d\n", cur_bin);
+
+ /* Break if we reached the maximum number
+ * of rules.
+ */
+ if (cnt >= o->max_cmd_len)
+ break;
+ }
+
+ *rdata_idx = cnt;
+
+ return cur_bin;
+}
+
+static inline void bnx2x_mcast_hdl_pending_add_e2(struct bnx2x *bp,
+ struct bnx2x_mcast_obj *o, struct bnx2x_pending_mcast_cmd *cmd_pos,
+ int *line_idx)
+{
+ struct bnx2x_mcast_mac_elem *pmac_pos, *pmac_pos_n;
+ int cnt = *line_idx;
+ union bnx2x_mcast_config_data cfg_data = {0};
+
+ list_for_each_entry_safe(pmac_pos, pmac_pos_n, &cmd_pos->data.macs_head,
+ link) {
+
+ cfg_data.mac = &pmac_pos->mac[0];
+ o->set_one_rule(bp, o, cnt, &cfg_data, cmd_pos->type);
+
+ cnt++;
+
+ DP(BNX2X_MSG_SP, "About to configure "BNX2X_MAC_FMT
+ " mcast MAC\n",
+ BNX2X_MAC_PRN_LIST(pmac_pos->mac));
+
+ list_del(&pmac_pos->link);
+
+ /* Break if we reached the maximum number
+ * of rules.
+ */
+ if (cnt >= o->max_cmd_len)
+ break;
+ }
+
+ *line_idx = cnt;
+
+ /* if no more MACs to configure - we are done */
+ if (list_empty(&cmd_pos->data.macs_head))
+ cmd_pos->done = true;
+}
+
+static inline void bnx2x_mcast_hdl_pending_del_e2(struct bnx2x *bp,
+ struct bnx2x_mcast_obj *o, struct bnx2x_pending_mcast_cmd *cmd_pos,
+ int *line_idx)
+{
+ int cnt = *line_idx;
+
+ while (cmd_pos->data.macs_num) {
+ o->set_one_rule(bp, o, cnt, NULL, cmd_pos->type);
+
+ cnt++;
+
+ cmd_pos->data.macs_num--;
+
+ DP(BNX2X_MSG_SP, "Deleting MAC. %d left,cnt is %d\n",
+ cmd_pos->data.macs_num, cnt);
+
+ /* Break if we reached the maximum
+ * number of rules.
+ */
+ if (cnt >= o->max_cmd_len)
+ break;
+ }
+
+ *line_idx = cnt;
+
+ /* If we cleared all bins - we are done */
+ if (!cmd_pos->data.macs_num)
+ cmd_pos->done = true;
+}
+
+static inline void bnx2x_mcast_hdl_pending_restore_e2(struct bnx2x *bp,
+ struct bnx2x_mcast_obj *o, struct bnx2x_pending_mcast_cmd *cmd_pos,
+ int *line_idx)
+{
+ cmd_pos->data.next_bin = o->hdl_restore(bp, o, cmd_pos->data.next_bin,
+ line_idx);
+
+ if (cmd_pos->data.next_bin < 0)
+ /* If o->set_restore returned -1 we are done */
+ cmd_pos->done = true;
+ else
+ /* Start from the next bin next time */
+ cmd_pos->data.next_bin++;
+}
+
+static inline int bnx2x_mcast_handle_pending_cmds_e2(struct bnx2x *bp,
+ struct bnx2x_mcast_ramrod_params *p)
+{
+ struct bnx2x_pending_mcast_cmd *cmd_pos, *cmd_pos_n;
+ int cnt = 0;
+ struct bnx2x_mcast_obj *o = p->mcast_obj;
+
+ list_for_each_entry_safe(cmd_pos, cmd_pos_n, &o->pending_cmds_head,
+ link) {
+ switch (cmd_pos->type) {
+ case BNX2X_MCAST_CMD_ADD:
+ bnx2x_mcast_hdl_pending_add_e2(bp, o, cmd_pos, &cnt);
+ break;
+
+ case BNX2X_MCAST_CMD_DEL:
+ bnx2x_mcast_hdl_pending_del_e2(bp, o, cmd_pos, &cnt);
+ break;
+
+ case BNX2X_MCAST_CMD_RESTORE:
+ bnx2x_mcast_hdl_pending_restore_e2(bp, o, cmd_pos,
+ &cnt);
+ break;
+
+ default:
+ BNX2X_ERR("Unknown command: %d\n", cmd_pos->type);
+ return -EINVAL;
+ }
+
+ /* If the command has been completed - remove it from the list
+ * and free the memory
+ */
+ if (cmd_pos->done) {
+ list_del(&cmd_pos->link);
+ kfree(cmd_pos);
+ }
+
+ /* Break if we reached the maximum number of rules */
+ if (cnt >= o->max_cmd_len)
+ break;
+ }
+
+ return cnt;
+}
+
+static inline void bnx2x_mcast_hdl_add(struct bnx2x *bp,
+ struct bnx2x_mcast_obj *o, struct bnx2x_mcast_ramrod_params *p,
+ int *line_idx)
+{
+ struct bnx2x_mcast_list_elem *mlist_pos;
+ union bnx2x_mcast_config_data cfg_data = {0};
+ int cnt = *line_idx;
+
+ list_for_each_entry(mlist_pos, &p->mcast_list, link) {
+ cfg_data.mac = mlist_pos->mac;
+ o->set_one_rule(bp, o, cnt, &cfg_data, BNX2X_MCAST_CMD_ADD);
+
+ cnt++;
+
+ DP(BNX2X_MSG_SP, "About to configure "BNX2X_MAC_FMT
+ " mcast MAC\n",
+ BNX2X_MAC_PRN_LIST(mlist_pos->mac));
+ }
+
+ *line_idx = cnt;
+}
+
+static inline void bnx2x_mcast_hdl_del(struct bnx2x *bp,
+ struct bnx2x_mcast_obj *o, struct bnx2x_mcast_ramrod_params *p,
+ int *line_idx)
+{
+ int cnt = *line_idx, i;
+
+ for (i = 0; i < p->mcast_list_len; i++) {
+ o->set_one_rule(bp, o, cnt, NULL, BNX2X_MCAST_CMD_DEL);
+
+ cnt++;
+
+ DP(BNX2X_MSG_SP, "Deleting MAC. %d left\n",
+ p->mcast_list_len - i - 1);
+ }
+
+ *line_idx = cnt;
+}
+
+/**
+ * bnx2x_mcast_handle_current_cmd -
+ *
+ * @bp: device handle
+ * @p:
+ * @cmd:
+ * @start_cnt: first line in the ramrod data that may be used
+ *
+ * This function is called iff there is enough place for the current command in
+ * the ramrod data.
+ * Returns number of lines filled in the ramrod data in total.
+ */
+static inline int bnx2x_mcast_handle_current_cmd(struct bnx2x *bp,
+ struct bnx2x_mcast_ramrod_params *p, int cmd,
+ int start_cnt)
+{
+ struct bnx2x_mcast_obj *o = p->mcast_obj;
+ int cnt = start_cnt;
+
+ DP(BNX2X_MSG_SP, "p->mcast_list_len=%d\n", p->mcast_list_len);
+
+ switch (cmd) {
+ case BNX2X_MCAST_CMD_ADD:
+ bnx2x_mcast_hdl_add(bp, o, p, &cnt);
+ break;
+
+ case BNX2X_MCAST_CMD_DEL:
+ bnx2x_mcast_hdl_del(bp, o, p, &cnt);
+ break;
+
+ case BNX2X_MCAST_CMD_RESTORE:
+ o->hdl_restore(bp, o, 0, &cnt);
+ break;
+
+ default:
+ BNX2X_ERR("Unknown command: %d\n", cmd);
+ return -EINVAL;
+ }
+
+ /* The current command has been handled */
+ p->mcast_list_len = 0;
+
+ return cnt;
+}
+
+static int bnx2x_mcast_validate_e2(struct bnx2x *bp,
+ struct bnx2x_mcast_ramrod_params *p,
+ int cmd)
+{
+ struct bnx2x_mcast_obj *o = p->mcast_obj;
+ int reg_sz = o->get_registry_size(o);
+
+ switch (cmd) {
+ /* DEL command deletes all currently configured MACs */
+ case BNX2X_MCAST_CMD_DEL:
+ o->set_registry_size(o, 0);
+ /* Don't break */
+
+ /* RESTORE command will restore the entire multicast configuration */
+ case BNX2X_MCAST_CMD_RESTORE:
+ /* Here we set the approximate amount of work to do, which in
+ * fact may be only less as some MACs in postponed ADD
+ * command(s) scheduled before this command may fall into
+ * the same bin and the actual number of bins set in the
+ * registry would be less than we estimated here. See
+ * bnx2x_mcast_set_one_rule_e2() for further details.
+ */
+ p->mcast_list_len = reg_sz;
+ break;
+
+ case BNX2X_MCAST_CMD_ADD:
+ case BNX2X_MCAST_CMD_CONT:
+ /* Here we assume that all new MACs will fall into new bins.
+ * However we will correct the real registry size after we
+ * handle all pending commands.
+ */
+ o->set_registry_size(o, reg_sz + p->mcast_list_len);
+ break;
+
+ default:
+ BNX2X_ERR("Unknown command: %d\n", cmd);
+ return -EINVAL;
+
+ }
+
+ /* Increase the total number of MACs pending to be configured */
+ o->total_pending_num += p->mcast_list_len;
+
+ return 0;
+}
+
+static void bnx2x_mcast_revert_e2(struct bnx2x *bp,
+ struct bnx2x_mcast_ramrod_params *p,
+ int old_num_bins)
+{
+ struct bnx2x_mcast_obj *o = p->mcast_obj;
+
+ o->set_registry_size(o, old_num_bins);
+ o->total_pending_num -= p->mcast_list_len;
+}
+
+/**
+ * bnx2x_mcast_set_rdata_hdr_e2 - sets a header values
+ *
+ * @bp: device handle
+ * @p:
+ * @len: number of rules to handle
+ */
+static inline void bnx2x_mcast_set_rdata_hdr_e2(struct bnx2x *bp,
+ struct bnx2x_mcast_ramrod_params *p,
+ u8 len)
+{
+ struct bnx2x_raw_obj *r = &p->mcast_obj->raw;
+ struct eth_multicast_rules_ramrod_data *data =
+ (struct eth_multicast_rules_ramrod_data *)(r->rdata);
+
+ data->header.echo = ((r->cid & BNX2X_SWCID_MASK) |
+ (BNX2X_FILTER_MCAST_PENDING << BNX2X_SWCID_SHIFT));
+ data->header.rule_cnt = len;
+}
+
+/**
+ * bnx2x_mcast_refresh_registry_e2 - recalculate the actual number of set bins
+ *
+ * @bp: device handle
+ * @o:
+ *
+ * Recalculate the actual number of set bins in the registry using Brian
+ * Kernighan's algorithm: it's execution complexity is as a number of set bins.
+ *
+ * returns 0 for the compliance with bnx2x_mcast_refresh_registry_e1().
+ */
+static inline int bnx2x_mcast_refresh_registry_e2(struct bnx2x *bp,
+ struct bnx2x_mcast_obj *o)
+{
+ int i, cnt = 0;
+ u64 elem;
+
+ for (i = 0; i < BNX2X_MCAST_VEC_SZ; i++) {
+ elem = o->registry.aprox_match.vec[i];
+ for (; elem; cnt++)
+ elem &= elem - 1;
+ }
+
+ o->set_registry_size(o, cnt);
+
+ return 0;
+}
+
+static int bnx2x_mcast_setup_e2(struct bnx2x *bp,
+ struct bnx2x_mcast_ramrod_params *p,
+ int cmd)
+{
+ struct bnx2x_raw_obj *raw = &p->mcast_obj->raw;
+ struct bnx2x_mcast_obj *o = p->mcast_obj;
+ struct eth_multicast_rules_ramrod_data *data =
+ (struct eth_multicast_rules_ramrod_data *)(raw->rdata);
+ int cnt = 0, rc;
+
+ /* Reset the ramrod data buffer */
+ memset(data, 0, sizeof(*data));
+
+ cnt = bnx2x_mcast_handle_pending_cmds_e2(bp, p);
+
+ /* If there are no more pending commands - clear SCHEDULED state */
+ if (list_empty(&o->pending_cmds_head))
+ o->clear_sched(o);
+
+ /* The below may be true iff there was enough room in ramrod
+ * data for all pending commands and for the current
+ * command. Otherwise the current command would have been added
+ * to the pending commands and p->mcast_list_len would have been
+ * zeroed.
+ */
+ if (p->mcast_list_len > 0)
+ cnt = bnx2x_mcast_handle_current_cmd(bp, p, cmd, cnt);
+
+ /* We've pulled out some MACs - update the total number of
+ * outstanding.
+ */
+ o->total_pending_num -= cnt;
+
+ /* send a ramrod */
+ WARN_ON(o->total_pending_num < 0);
+ WARN_ON(cnt > o->max_cmd_len);
+
+ bnx2x_mcast_set_rdata_hdr_e2(bp, p, (u8)cnt);
+
+ /* Update a registry size if there are no more pending operations.
+ *
+ * We don't want to change the value of the registry size if there are
+ * pending operations because we want it to always be equal to the
+ * exact or the approximate number (see bnx2x_mcast_validate_e2()) of
+ * set bins after the last requested operation in order to properly
+ * evaluate the size of the next DEL/RESTORE operation.
+ *
+ * Note that we update the registry itself during command(s) handling
+ * - see bnx2x_mcast_set_one_rule_e2(). That's because for 57712 we
+ * aggregate multiple commands (ADD/DEL/RESTORE) into one ramrod but
+ * with a limited amount of update commands (per MAC/bin) and we don't
+ * know in this scope what the actual state of bins configuration is
+ * going to be after this ramrod.
+ */
+ if (!o->total_pending_num)
+ bnx2x_mcast_refresh_registry_e2(bp, o);
+
+ /* Commit writes towards the memory before sending a ramrod */
+ mb();
+
+ /* If CLEAR_ONLY was requested - don't send a ramrod and clear
+ * RAMROD_PENDING status immediately.
+ */
+ if (test_bit(RAMROD_DRV_CLR_ONLY, &p->ramrod_flags)) {
+ raw->clear_pending(raw);
+ return 0;
+ } else {
+ /* Send a ramrod */
+ rc = bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_MULTICAST_RULES,
+ raw->cid, U64_HI(raw->rdata_mapping),
+ U64_LO(raw->rdata_mapping),
+ ETH_CONNECTION_TYPE);
+ if (rc)
+ return rc;
+
+ /* Ramrod completion is pending */
+ return 1;
+ }
+}
+
+static int bnx2x_mcast_validate_e1h(struct bnx2x *bp,
+ struct bnx2x_mcast_ramrod_params *p,
+ int cmd)
+{
+ /* Mark, that there is a work to do */
+ if ((cmd == BNX2X_MCAST_CMD_DEL) || (cmd == BNX2X_MCAST_CMD_RESTORE))
+ p->mcast_list_len = 1;
+
+ return 0;
+}
+
+static void bnx2x_mcast_revert_e1h(struct bnx2x *bp,
+ struct bnx2x_mcast_ramrod_params *p,
+ int old_num_bins)
+{
+ /* Do nothing */
+}
+
+#define BNX2X_57711_SET_MC_FILTER(filter, bit) \
+do { \
+ (filter)[(bit) >> 5] |= (1 << ((bit) & 0x1f)); \
+} while (0)
+
+static inline void bnx2x_mcast_hdl_add_e1h(struct bnx2x *bp,
+ struct bnx2x_mcast_obj *o,
+ struct bnx2x_mcast_ramrod_params *p,
+ u32 *mc_filter)
+{
+ struct bnx2x_mcast_list_elem *mlist_pos;
+ int bit;
+
+ list_for_each_entry(mlist_pos, &p->mcast_list, link) {
+ bit = bnx2x_mcast_bin_from_mac(mlist_pos->mac);
+ BNX2X_57711_SET_MC_FILTER(mc_filter, bit);
+
+ DP(BNX2X_MSG_SP, "About to configure "
+ BNX2X_MAC_FMT" mcast MAC, bin %d\n",
+ BNX2X_MAC_PRN_LIST(mlist_pos->mac), bit);
+
+ /* bookkeeping... */
+ BIT_VEC64_SET_BIT(o->registry.aprox_match.vec,
+ bit);
+ }
+}
+
+static inline void bnx2x_mcast_hdl_restore_e1h(struct bnx2x *bp,
+ struct bnx2x_mcast_obj *o, struct bnx2x_mcast_ramrod_params *p,
+ u32 *mc_filter)
+{
+ int bit;
+
+ for (bit = bnx2x_mcast_get_next_bin(o, 0);
+ bit >= 0;
+ bit = bnx2x_mcast_get_next_bin(o, bit + 1)) {
+ BNX2X_57711_SET_MC_FILTER(mc_filter, bit);
+ DP(BNX2X_MSG_SP, "About to set bin %d\n", bit);
+ }
+}
+
+/* On 57711 we write the multicast MACs' aproximate match
+ * table by directly into the TSTORM's internal RAM. So we don't
+ * really need to handle any tricks to make it work.
+ */
+static int bnx2x_mcast_setup_e1h(struct bnx2x *bp,
+ struct bnx2x_mcast_ramrod_params *p,
+ int cmd)
+{
+ int i;
+ struct bnx2x_mcast_obj *o = p->mcast_obj;
+ struct bnx2x_raw_obj *r = &o->raw;
+
+ /* If CLEAR_ONLY has been requested - clear the registry
+ * and clear a pending bit.
+ */
+ if (!test_bit(RAMROD_DRV_CLR_ONLY, &p->ramrod_flags)) {
+ u32 mc_filter[MC_HASH_SIZE] = {0};
+
+ /* Set the multicast filter bits before writing it into
+ * the internal memory.
+ */
+ switch (cmd) {
+ case BNX2X_MCAST_CMD_ADD:
+ bnx2x_mcast_hdl_add_e1h(bp, o, p, mc_filter);
+ break;
+
+ case BNX2X_MCAST_CMD_DEL:
+ DP(BNX2X_MSG_SP, "Invalidating multicast "
+ "MACs configuration\n");
+
+ /* clear the registry */
+ memset(o->registry.aprox_match.vec, 0,
+ sizeof(o->registry.aprox_match.vec));
+ break;
+
+ case BNX2X_MCAST_CMD_RESTORE:
+ bnx2x_mcast_hdl_restore_e1h(bp, o, p, mc_filter);
+ break;
+
+ default:
+ BNX2X_ERR("Unknown command: %d\n", cmd);
+ return -EINVAL;
+ }
+
+ /* Set the mcast filter in the internal memory */
+ for (i = 0; i < MC_HASH_SIZE; i++)
+ REG_WR(bp, MC_HASH_OFFSET(bp, i), mc_filter[i]);
+ } else
+ /* clear the registry */
+ memset(o->registry.aprox_match.vec, 0,
+ sizeof(o->registry.aprox_match.vec));
+
+ /* We are done */
+ r->clear_pending(r);
+
+ return 0;
+}
+
+static int bnx2x_mcast_validate_e1(struct bnx2x *bp,
+ struct bnx2x_mcast_ramrod_params *p,
+ int cmd)
+{
+ struct bnx2x_mcast_obj *o = p->mcast_obj;
+ int reg_sz = o->get_registry_size(o);
+
+ switch (cmd) {
+ /* DEL command deletes all currently configured MACs */
+ case BNX2X_MCAST_CMD_DEL:
+ o->set_registry_size(o, 0);
+ /* Don't break */
+
+ /* RESTORE command will restore the entire multicast configuration */
+ case BNX2X_MCAST_CMD_RESTORE:
+ p->mcast_list_len = reg_sz;
+ DP(BNX2X_MSG_SP, "Command %d, p->mcast_list_len=%d\n",
+ cmd, p->mcast_list_len);
+ break;
+
+ case BNX2X_MCAST_CMD_ADD:
+ case BNX2X_MCAST_CMD_CONT:
+ /* Multicast MACs on 57710 are configured as unicast MACs and
+ * there is only a limited number of CAM entries for that
+ * matter.
+ */
+ if (p->mcast_list_len > o->max_cmd_len) {
+ BNX2X_ERR("Can't configure more than %d multicast MACs"
+ "on 57710\n", o->max_cmd_len);
+ return -EINVAL;
+ }
+ /* Every configured MAC should be cleared if DEL command is
+ * called. Only the last ADD command is relevant as long as
+ * every ADD commands overrides the previous configuration.
+ */
+ DP(BNX2X_MSG_SP, "p->mcast_list_len=%d\n", p->mcast_list_len);
+ if (p->mcast_list_len > 0)
+ o->set_registry_size(o, p->mcast_list_len);
+
+ break;
+
+ default:
+ BNX2X_ERR("Unknown command: %d\n", cmd);
+ return -EINVAL;
+
+ }
+
+ /* We want to ensure that commands are executed one by one for 57710.
+ * Therefore each none-empty command will consume o->max_cmd_len.
+ */
+ if (p->mcast_list_len)
+ o->total_pending_num += o->max_cmd_len;
+
+ return 0;
+}
+
+static void bnx2x_mcast_revert_e1(struct bnx2x *bp,
+ struct bnx2x_mcast_ramrod_params *p,
+ int old_num_macs)
+{
+ struct bnx2x_mcast_obj *o = p->mcast_obj;
+
+ o->set_registry_size(o, old_num_macs);
+
+ /* If current command hasn't been handled yet and we are
+ * here means that it's meant to be dropped and we have to
+ * update the number of outstandling MACs accordingly.
+ */
+ if (p->mcast_list_len)
+ o->total_pending_num -= o->max_cmd_len;
+}
+
+static void bnx2x_mcast_set_one_rule_e1(struct bnx2x *bp,
+ struct bnx2x_mcast_obj *o, int idx,
+ union bnx2x_mcast_config_data *cfg_data,
+ int cmd)
+{
+ struct bnx2x_raw_obj *r = &o->raw;
+ struct mac_configuration_cmd *data =
+ (struct mac_configuration_cmd *)(r->rdata);
+
+ /* copy mac */
+ if ((cmd == BNX2X_MCAST_CMD_ADD) || (cmd == BNX2X_MCAST_CMD_RESTORE)) {
+ bnx2x_set_fw_mac_addr(&data->config_table[idx].msb_mac_addr,
+ &data->config_table[idx].middle_mac_addr,
+ &data->config_table[idx].lsb_mac_addr,
+ cfg_data->mac);
+
+ data->config_table[idx].vlan_id = 0;
+ data->config_table[idx].pf_id = r->func_id;
+ data->config_table[idx].clients_bit_vector =
+ cpu_to_le32(1 << r->cl_id);
+
+ SET_FLAG(data->config_table[idx].flags,
+ MAC_CONFIGURATION_ENTRY_ACTION_TYPE,
+ T_ETH_MAC_COMMAND_SET);
+ }
+}
+
+/**
+ * bnx2x_mcast_set_rdata_hdr_e1 - set header values in mac_configuration_cmd
+ *
+ * @bp: device handle
+ * @p:
+ * @len: number of rules to handle
+ */
+static inline void bnx2x_mcast_set_rdata_hdr_e1(struct bnx2x *bp,
+ struct bnx2x_mcast_ramrod_params *p,
+ u8 len)
+{
+ struct bnx2x_raw_obj *r = &p->mcast_obj->raw;
+ struct mac_configuration_cmd *data =
+ (struct mac_configuration_cmd *)(r->rdata);
+
+ u8 offset = (CHIP_REV_IS_SLOW(bp) ?
+ BNX2X_MAX_EMUL_MULTI*(1 + r->func_id) :
+ BNX2X_MAX_MULTICAST*(1 + r->func_id));
+
+ data->hdr.offset = offset;
+ data->hdr.client_id = 0xff;
+ data->hdr.echo = ((r->cid & BNX2X_SWCID_MASK) |
+ (BNX2X_FILTER_MCAST_PENDING << BNX2X_SWCID_SHIFT));
+ data->hdr.length = len;
+}
+
+/**
+ * bnx2x_mcast_handle_restore_cmd_e1 - restore command for 57710
+ *
+ * @bp: device handle
+ * @o:
+ * @start_idx: index in the registry to start from
+ * @rdata_idx: index in the ramrod data to start from
+ *
+ * restore command for 57710 is like all other commands - always a stand alone
+ * command - start_idx and rdata_idx will always be 0. This function will always
+ * succeed.
+ * returns -1 to comply with 57712 variant.
+ */
+static inline int bnx2x_mcast_handle_restore_cmd_e1(
+ struct bnx2x *bp, struct bnx2x_mcast_obj *o , int start_idx,
+ int *rdata_idx)
+{
+ struct bnx2x_mcast_mac_elem *elem;
+ int i = 0;
+ union bnx2x_mcast_config_data cfg_data = {0};
+
+ /* go through the registry and configure the MACs from it. */
+ list_for_each_entry(elem, &o->registry.exact_match.macs, link) {
+ cfg_data.mac = &elem->mac[0];
+ o->set_one_rule(bp, o, i, &cfg_data, BNX2X_MCAST_CMD_RESTORE);
+
+ i++;
+
+ DP(BNX2X_MSG_SP, "About to configure "BNX2X_MAC_FMT
+ " mcast MAC\n",
+ BNX2X_MAC_PRN_LIST(cfg_data.mac));
+ }
+
+ *rdata_idx = i;
+
+ return -1;
+}
+
+
+static inline int bnx2x_mcast_handle_pending_cmds_e1(
+ struct bnx2x *bp, struct bnx2x_mcast_ramrod_params *p)
+{
+ struct bnx2x_pending_mcast_cmd *cmd_pos;
+ struct bnx2x_mcast_mac_elem *pmac_pos;
+ struct bnx2x_mcast_obj *o = p->mcast_obj;
+ union bnx2x_mcast_config_data cfg_data = {0};
+ int cnt = 0;
+
+
+ /* If nothing to be done - return */
+ if (list_empty(&o->pending_cmds_head))
+ return 0;
+
+ /* Handle the first command */
+ cmd_pos = list_first_entry(&o->pending_cmds_head,
+ struct bnx2x_pending_mcast_cmd, link);
+
+ switch (cmd_pos->type) {
+ case BNX2X_MCAST_CMD_ADD:
+ list_for_each_entry(pmac_pos, &cmd_pos->data.macs_head, link) {
+ cfg_data.mac = &pmac_pos->mac[0];
+ o->set_one_rule(bp, o, cnt, &cfg_data, cmd_pos->type);
+
+ cnt++;
+
+ DP(BNX2X_MSG_SP, "About to configure "BNX2X_MAC_FMT
+ " mcast MAC\n",
+ BNX2X_MAC_PRN_LIST(pmac_pos->mac));
+ }
+ break;
+
+ case BNX2X_MCAST_CMD_DEL:
+ cnt = cmd_pos->data.macs_num;
+ DP(BNX2X_MSG_SP, "About to delete %d multicast MACs\n", cnt);
+ break;
+
+ case BNX2X_MCAST_CMD_RESTORE:
+ o->hdl_restore(bp, o, 0, &cnt);
+ break;
+
+ default:
+ BNX2X_ERR("Unknown command: %d\n", cmd_pos->type);
+ return -EINVAL;
+ }
+
+ list_del(&cmd_pos->link);
+ kfree(cmd_pos);
+
+ return cnt;
+}
+
+/**
+ * bnx2x_get_fw_mac_addr - revert the bnx2x_set_fw_mac_addr().
+ *
+ * @fw_hi:
+ * @fw_mid:
+ * @fw_lo:
+ * @mac:
+ */
+static inline void bnx2x_get_fw_mac_addr(__le16 *fw_hi, __le16 *fw_mid,
+ __le16 *fw_lo, u8 *mac)
+{
+ mac[1] = ((u8 *)fw_hi)[0];
+ mac[0] = ((u8 *)fw_hi)[1];
+ mac[3] = ((u8 *)fw_mid)[0];
+ mac[2] = ((u8 *)fw_mid)[1];
+ mac[5] = ((u8 *)fw_lo)[0];
+ mac[4] = ((u8 *)fw_lo)[1];
+}
+
+/**
+ * bnx2x_mcast_refresh_registry_e1 -
+ *
+ * @bp: device handle
+ * @cnt:
+ *
+ * Check the ramrod data first entry flag to see if it's a DELETE or ADD command
+ * and update the registry correspondingly: if ADD - allocate a memory and add
+ * the entries to the registry (list), if DELETE - clear the registry and free
+ * the memory.
+ */
+static inline int bnx2x_mcast_refresh_registry_e1(struct bnx2x *bp,
+ struct bnx2x_mcast_obj *o)
+{
+ struct bnx2x_raw_obj *raw = &o->raw;
+ struct bnx2x_mcast_mac_elem *elem;
+ struct mac_configuration_cmd *data =
+ (struct mac_configuration_cmd *)(raw->rdata);
+
+ /* If first entry contains a SET bit - the command was ADD,
+ * otherwise - DEL_ALL
+ */
+ if (GET_FLAG(data->config_table[0].flags,
+ MAC_CONFIGURATION_ENTRY_ACTION_TYPE)) {
+ int i, len = data->hdr.length;
+
+ /* Break if it was a RESTORE command */
+ if (!list_empty(&o->registry.exact_match.macs))
+ return 0;
+
+ elem = kzalloc(sizeof(*elem)*len, GFP_ATOMIC);
+ if (!elem) {
+ BNX2X_ERR("Failed to allocate registry memory\n");
+ return -ENOMEM;
+ }
+
+ for (i = 0; i < len; i++, elem++) {
+ bnx2x_get_fw_mac_addr(
+ &data->config_table[i].msb_mac_addr,
+ &data->config_table[i].middle_mac_addr,
+ &data->config_table[i].lsb_mac_addr,
+ elem->mac);
+ DP(BNX2X_MSG_SP, "Adding registry entry for ["
+ BNX2X_MAC_FMT"]\n",
+ BNX2X_MAC_PRN_LIST(elem->mac));
+ list_add_tail(&elem->link,
+ &o->registry.exact_match.macs);
+ }
+ } else {
+ elem = list_first_entry(&o->registry.exact_match.macs,
+ struct bnx2x_mcast_mac_elem, link);
+ DP(BNX2X_MSG_SP, "Deleting a registry\n");
+ kfree(elem);
+ INIT_LIST_HEAD(&o->registry.exact_match.macs);
+ }
+
+ return 0;
+}
+
+static int bnx2x_mcast_setup_e1(struct bnx2x *bp,
+ struct bnx2x_mcast_ramrod_params *p,
+ int cmd)
+{
+ struct bnx2x_mcast_obj *o = p->mcast_obj;
+ struct bnx2x_raw_obj *raw = &o->raw;
+ struct mac_configuration_cmd *data =
+ (struct mac_configuration_cmd *)(raw->rdata);
+ int cnt = 0, i, rc;
+
+ /* Reset the ramrod data buffer */
+ memset(data, 0, sizeof(*data));
+
+ /* First set all entries as invalid */
+ for (i = 0; i < o->max_cmd_len ; i++)
+ SET_FLAG(data->config_table[i].flags,
+ MAC_CONFIGURATION_ENTRY_ACTION_TYPE,
+ T_ETH_MAC_COMMAND_INVALIDATE);
+
+ /* Handle pending commands first */
+ cnt = bnx2x_mcast_handle_pending_cmds_e1(bp, p);
+
+ /* If there are no more pending commands - clear SCHEDULED state */
+ if (list_empty(&o->pending_cmds_head))
+ o->clear_sched(o);
+
+ /* The below may be true iff there were no pending commands */
+ if (!cnt)
+ cnt = bnx2x_mcast_handle_current_cmd(bp, p, cmd, 0);
+
+ /* For 57710 every command has o->max_cmd_len length to ensure that
+ * commands are done one at a time.
+ */
+ o->total_pending_num -= o->max_cmd_len;
+
+ /* send a ramrod */
+
+ WARN_ON(cnt > o->max_cmd_len);
+
+ /* Set ramrod header (in particular, a number of entries to update) */
+ bnx2x_mcast_set_rdata_hdr_e1(bp, p, (u8)cnt);
+
+ /* update a registry: we need the registry contents to be always up
+ * to date in order to be able to execute a RESTORE opcode. Here
+ * we use the fact that for 57710 we sent one command at a time
+ * hence we may take the registry update out of the command handling
+ * and do it in a simpler way here.
+ */
+ rc = bnx2x_mcast_refresh_registry_e1(bp, o);
+ if (rc)
+ return rc;
+
+ /* Commit writes towards the memory before sending a ramrod */
+ mb();
+
+ /* If CLEAR_ONLY was requested - don't send a ramrod and clear
+ * RAMROD_PENDING status immediately.
+ */
+ if (test_bit(RAMROD_DRV_CLR_ONLY, &p->ramrod_flags)) {
+ raw->clear_pending(raw);
+ return 0;
+ } else {
+ /* Send a ramrod */
+ rc = bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_SET_MAC, raw->cid,
+ U64_HI(raw->rdata_mapping),
+ U64_LO(raw->rdata_mapping),
+ ETH_CONNECTION_TYPE);
+ if (rc)
+ return rc;
+
+ /* Ramrod completion is pending */
+ return 1;
+ }
+
+}
+
+static int bnx2x_mcast_get_registry_size_exact(struct bnx2x_mcast_obj *o)
+{
+ return o->registry.exact_match.num_macs_set;
+}
+
+static int bnx2x_mcast_get_registry_size_aprox(struct bnx2x_mcast_obj *o)
+{
+ return o->registry.aprox_match.num_bins_set;
+}
+
+static void bnx2x_mcast_set_registry_size_exact(struct bnx2x_mcast_obj *o,
+ int n)
+{
+ o->registry.exact_match.num_macs_set = n;
+}
+
+static void bnx2x_mcast_set_registry_size_aprox(struct bnx2x_mcast_obj *o,
+ int n)
+{
+ o->registry.aprox_match.num_bins_set = n;
+}
+
+int bnx2x_config_mcast(struct bnx2x *bp,
+ struct bnx2x_mcast_ramrod_params *p,
+ int cmd)
+{
+ struct bnx2x_mcast_obj *o = p->mcast_obj;
+ struct bnx2x_raw_obj *r = &o->raw;
+ int rc = 0, old_reg_size;
+
+ /* This is needed to recover number of currently configured mcast macs
+ * in case of failure.
+ */
+ old_reg_size = o->get_registry_size(o);
+
+ /* Do some calculations and checks */
+ rc = o->validate(bp, p, cmd);
+ if (rc)
+ return rc;
+
+ /* Return if there is no work to do */
+ if ((!p->mcast_list_len) && (!o->check_sched(o)))
+ return 0;
+
+ DP(BNX2X_MSG_SP, "o->total_pending_num=%d p->mcast_list_len=%d "
+ "o->max_cmd_len=%d\n", o->total_pending_num,
+ p->mcast_list_len, o->max_cmd_len);
+
+ /* Enqueue the current command to the pending list if we can't complete
+ * it in the current iteration
+ */
+ if (r->check_pending(r) ||
+ ((o->max_cmd_len > 0) && (o->total_pending_num > o->max_cmd_len))) {
+ rc = o->enqueue_cmd(bp, p->mcast_obj, p, cmd);
+ if (rc < 0)
+ goto error_exit1;
+
+ /* As long as the current command is in a command list we
+ * don't need to handle it separately.
+ */
+ p->mcast_list_len = 0;
+ }
+
+ if (!r->check_pending(r)) {
+
+ /* Set 'pending' state */
+ r->set_pending(r);
+
+ /* Configure the new classification in the chip */
+ rc = o->config_mcast(bp, p, cmd);
+ if (rc < 0)
+ goto error_exit2;
+
+ /* Wait for a ramrod completion if was requested */
+ if (test_bit(RAMROD_COMP_WAIT, &p->ramrod_flags))
+ rc = o->wait_comp(bp, o);
+ }
+
+ return rc;
+
+error_exit2:
+ r->clear_pending(r);
+
+error_exit1:
+ o->revert(bp, p, old_reg_size);
+
+ return rc;
+}
+
+static void bnx2x_mcast_clear_sched(struct bnx2x_mcast_obj *o)
+{
+ smp_mb__before_clear_bit();
+ clear_bit(o->sched_state, o->raw.pstate);
+ smp_mb__after_clear_bit();
+}
+
+static void bnx2x_mcast_set_sched(struct bnx2x_mcast_obj *o)
+{
+ smp_mb__before_clear_bit();
+ set_bit(o->sched_state, o->raw.pstate);
+ smp_mb__after_clear_bit();
+}
+
+static bool bnx2x_mcast_check_sched(struct bnx2x_mcast_obj *o)
+{
+ return !!test_bit(o->sched_state, o->raw.pstate);
+}
+
+static bool bnx2x_mcast_check_pending(struct bnx2x_mcast_obj *o)
+{
+ return o->raw.check_pending(&o->raw) || o->check_sched(o);
+}
+
+void bnx2x_init_mcast_obj(struct bnx2x *bp,
+ struct bnx2x_mcast_obj *mcast_obj,
+ u8 mcast_cl_id, u32 mcast_cid, u8 func_id,
+ u8 engine_id, void *rdata, dma_addr_t rdata_mapping,
+ int state, unsigned long *pstate, bnx2x_obj_type type)
+{
+ memset(mcast_obj, 0, sizeof(*mcast_obj));
+
+ bnx2x_init_raw_obj(&mcast_obj->raw, mcast_cl_id, mcast_cid, func_id,
+ rdata, rdata_mapping, state, pstate, type);
+
+ mcast_obj->engine_id = engine_id;
+
+ INIT_LIST_HEAD(&mcast_obj->pending_cmds_head);
+
+ mcast_obj->sched_state = BNX2X_FILTER_MCAST_SCHED;
+ mcast_obj->check_sched = bnx2x_mcast_check_sched;
+ mcast_obj->set_sched = bnx2x_mcast_set_sched;
+ mcast_obj->clear_sched = bnx2x_mcast_clear_sched;
+
+ if (CHIP_IS_E1(bp)) {
+ mcast_obj->config_mcast = bnx2x_mcast_setup_e1;
+ mcast_obj->enqueue_cmd = bnx2x_mcast_enqueue_cmd;
+ mcast_obj->hdl_restore =
+ bnx2x_mcast_handle_restore_cmd_e1;
+ mcast_obj->check_pending = bnx2x_mcast_check_pending;
+
+ if (CHIP_REV_IS_SLOW(bp))
+ mcast_obj->max_cmd_len = BNX2X_MAX_EMUL_MULTI;
+ else
+ mcast_obj->max_cmd_len = BNX2X_MAX_MULTICAST;
+
+ mcast_obj->wait_comp = bnx2x_mcast_wait;
+ mcast_obj->set_one_rule = bnx2x_mcast_set_one_rule_e1;
+ mcast_obj->validate = bnx2x_mcast_validate_e1;
+ mcast_obj->revert = bnx2x_mcast_revert_e1;
+ mcast_obj->get_registry_size =
+ bnx2x_mcast_get_registry_size_exact;
+ mcast_obj->set_registry_size =
+ bnx2x_mcast_set_registry_size_exact;
+
+ /* 57710 is the only chip that uses the exact match for mcast
+ * at the moment.
+ */
+ INIT_LIST_HEAD(&mcast_obj->registry.exact_match.macs);
+
+ } else if (CHIP_IS_E1H(bp)) {
+ mcast_obj->config_mcast = bnx2x_mcast_setup_e1h;
+ mcast_obj->enqueue_cmd = NULL;
+ mcast_obj->hdl_restore = NULL;
+ mcast_obj->check_pending = bnx2x_mcast_check_pending;
+
+ /* 57711 doesn't send a ramrod, so it has unlimited credit
+ * for one command.
+ */
+ mcast_obj->max_cmd_len = -1;
+ mcast_obj->wait_comp = bnx2x_mcast_wait;
+ mcast_obj->set_one_rule = NULL;
+ mcast_obj->validate = bnx2x_mcast_validate_e1h;
+ mcast_obj->revert = bnx2x_mcast_revert_e1h;
+ mcast_obj->get_registry_size =
+ bnx2x_mcast_get_registry_size_aprox;
+ mcast_obj->set_registry_size =
+ bnx2x_mcast_set_registry_size_aprox;
+ } else {
+ mcast_obj->config_mcast = bnx2x_mcast_setup_e2;
+ mcast_obj->enqueue_cmd = bnx2x_mcast_enqueue_cmd;
+ mcast_obj->hdl_restore =
+ bnx2x_mcast_handle_restore_cmd_e2;
+ mcast_obj->check_pending = bnx2x_mcast_check_pending;
+ /* TODO: There should be a proper HSI define for this number!!!
+ */
+ mcast_obj->max_cmd_len = 16;
+ mcast_obj->wait_comp = bnx2x_mcast_wait;
+ mcast_obj->set_one_rule = bnx2x_mcast_set_one_rule_e2;
+ mcast_obj->validate = bnx2x_mcast_validate_e2;
+ mcast_obj->revert = bnx2x_mcast_revert_e2;
+ mcast_obj->get_registry_size =
+ bnx2x_mcast_get_registry_size_aprox;
+ mcast_obj->set_registry_size =
+ bnx2x_mcast_set_registry_size_aprox;
+ }
+}
+
+/*************************** Credit handling **********************************/
+
+/**
+ * atomic_add_ifless - add if the result is less than a given value.
+ *
+ * @v: pointer of type atomic_t
+ * @a: the amount to add to v...
+ * @u: ...if (v + a) is less than u.
+ *
+ * returns true if (v + a) was less than u, and false otherwise.
+ *
+ */
+static inline bool __atomic_add_ifless(atomic_t *v, int a, int u)
+{
+ int c, old;
+
+ c = atomic_read(v);
+ for (;;) {
+ if (unlikely(c + a >= u))
+ return false;
+
+ old = atomic_cmpxchg((v), c, c + a);
+ if (likely(old == c))
+ break;
+ c = old;
+ }
+
+ return true;
+}
+
+/**
+ * atomic_dec_ifmoe - dec if the result is more or equal than a given value.
+ *
+ * @v: pointer of type atomic_t
+ * @a: the amount to dec from v...
+ * @u: ...if (v - a) is more or equal than u.
+ *
+ * returns true if (v - a) was more or equal than u, and false
+ * otherwise.
+ */
+static inline bool __atomic_dec_ifmoe(atomic_t *v, int a, int u)
+{
+ int c, old;
+
+ c = atomic_read(v);
+ for (;;) {
+ if (unlikely(c - a < u))
+ return false;
+
+ old = atomic_cmpxchg((v), c, c - a);
+ if (likely(old == c))
+ break;
+ c = old;
+ }
+
+ return true;
+}
+
+static bool bnx2x_credit_pool_get(struct bnx2x_credit_pool_obj *o, int cnt)
+{
+ bool rc;
+
+ smp_mb();
+ rc = __atomic_dec_ifmoe(&o->credit, cnt, 0);
+ smp_mb();
+
+ return rc;
+}
+
+static bool bnx2x_credit_pool_put(struct bnx2x_credit_pool_obj *o, int cnt)
+{
+ bool rc;
+
+ smp_mb();
+
+ /* Don't let to refill if credit + cnt > pool_sz */
+ rc = __atomic_add_ifless(&o->credit, cnt, o->pool_sz + 1);
+
+ smp_mb();
+
+ return rc;
+}
+
+static int bnx2x_credit_pool_check(struct bnx2x_credit_pool_obj *o)
+{
+ int cur_credit;
+
+ smp_mb();
+ cur_credit = atomic_read(&o->credit);
+
+ return cur_credit;
+}
+
+static bool bnx2x_credit_pool_always_true(struct bnx2x_credit_pool_obj *o,
+ int cnt)
+{
+ return true;
+}
+
+
+static bool bnx2x_credit_pool_get_entry(
+ struct bnx2x_credit_pool_obj *o,
+ int *offset)
+{
+ int idx, vec, i;
+
+ *offset = -1;
+
+ /* Find "internal cam-offset" then add to base for this object... */
+ for (vec = 0; vec < BNX2X_POOL_VEC_SIZE; vec++) {
+
+ /* Skip the current vector if there are no free entries in it */
+ if (!o->pool_mirror[vec])
+ continue;
+
+ /* If we've got here we are going to find a free entry */
+ for (idx = vec * BNX2X_POOL_VEC_SIZE, i = 0;
+ i < BIT_VEC64_ELEM_SZ; idx++, i++)
+
+ if (BIT_VEC64_TEST_BIT(o->pool_mirror, idx)) {
+ /* Got one!! */
+ BIT_VEC64_CLEAR_BIT(o->pool_mirror, idx);
+ *offset = o->base_pool_offset + idx;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+static bool bnx2x_credit_pool_put_entry(
+ struct bnx2x_credit_pool_obj *o,
+ int offset)
+{
+ if (offset < o->base_pool_offset)
+ return false;
+
+ offset -= o->base_pool_offset;
+
+ if (offset >= o->pool_sz)
+ return false;
+
+ /* Return the entry to the pool */
+ BIT_VEC64_SET_BIT(o->pool_mirror, offset);
+
+ return true;
+}
+
+static bool bnx2x_credit_pool_put_entry_always_true(
+ struct bnx2x_credit_pool_obj *o,
+ int offset)
+{
+ return true;
+}
+
+static bool bnx2x_credit_pool_get_entry_always_true(
+ struct bnx2x_credit_pool_obj *o,
+ int *offset)
+{
+ *offset = -1;
+ return true;
+}
+/**
+ * bnx2x_init_credit_pool - initialize credit pool internals.
+ *
+ * @p:
+ * @base: Base entry in the CAM to use.
+ * @credit: pool size.
+ *
+ * If base is negative no CAM entries handling will be performed.
+ * If credit is negative pool operations will always succeed (unlimited pool).
+ *
+ */
+static inline void bnx2x_init_credit_pool(struct bnx2x_credit_pool_obj *p,
+ int base, int credit)
+{
+ /* Zero the object first */
+ memset(p, 0, sizeof(*p));
+
+ /* Set the table to all 1s */
+ memset(&p->pool_mirror, 0xff, sizeof(p->pool_mirror));
+
+ /* Init a pool as full */
+ atomic_set(&p->credit, credit);
+
+ /* The total poll size */
+ p->pool_sz = credit;
+
+ p->base_pool_offset = base;
+
+ /* Commit the change */
+ smp_mb();
+
+ p->check = bnx2x_credit_pool_check;
+
+ /* if pool credit is negative - disable the checks */
+ if (credit >= 0) {
+ p->put = bnx2x_credit_pool_put;
+ p->get = bnx2x_credit_pool_get;
+ p->put_entry = bnx2x_credit_pool_put_entry;
+ p->get_entry = bnx2x_credit_pool_get_entry;
+ } else {
+ p->put = bnx2x_credit_pool_always_true;
+ p->get = bnx2x_credit_pool_always_true;
+ p->put_entry = bnx2x_credit_pool_put_entry_always_true;
+ p->get_entry = bnx2x_credit_pool_get_entry_always_true;
+ }
+
+ /* If base is negative - disable entries handling */
+ if (base < 0) {
+ p->put_entry = bnx2x_credit_pool_put_entry_always_true;
+ p->get_entry = bnx2x_credit_pool_get_entry_always_true;
+ }
+}
+
+void bnx2x_init_mac_credit_pool(struct bnx2x *bp,
+ struct bnx2x_credit_pool_obj *p, u8 func_id,
+ u8 func_num)
+{
+/* TODO: this will be defined in consts as well... */
+#define BNX2X_CAM_SIZE_EMUL 5
+
+ int cam_sz;
+
+ if (CHIP_IS_E1(bp)) {
+ /* In E1, Multicast is saved in cam... */
+ if (!CHIP_REV_IS_SLOW(bp))
+ cam_sz = (MAX_MAC_CREDIT_E1 / 2) - BNX2X_MAX_MULTICAST;
+ else
+ cam_sz = BNX2X_CAM_SIZE_EMUL - BNX2X_MAX_EMUL_MULTI;
+
+ bnx2x_init_credit_pool(p, func_id * cam_sz, cam_sz);
+
+ } else if (CHIP_IS_E1H(bp)) {
+ /* CAM credit is equaly divided between all active functions
+ * on the PORT!.
+ */
+ if ((func_num > 0)) {
+ if (!CHIP_REV_IS_SLOW(bp))
+ cam_sz = (MAX_MAC_CREDIT_E1H / (2*func_num));
+ else
+ cam_sz = BNX2X_CAM_SIZE_EMUL;
+ bnx2x_init_credit_pool(p, func_id * cam_sz, cam_sz);
+ } else {
+ /* this should never happen! Block MAC operations. */
+ bnx2x_init_credit_pool(p, 0, 0);
+ }
+
+ } else {
+
+ /*
+ * CAM credit is equaly divided between all active functions
+ * on the PATH.
+ */
+ if ((func_num > 0)) {
+ if (!CHIP_REV_IS_SLOW(bp))
+ cam_sz = (MAX_MAC_CREDIT_E2 / func_num);
+ else
+ cam_sz = BNX2X_CAM_SIZE_EMUL;
+
+ /*
+ * No need for CAM entries handling for 57712 and
+ * newer.
+ */
+ bnx2x_init_credit_pool(p, -1, cam_sz);
+ } else {
+ /* this should never happen! Block MAC operations. */
+ bnx2x_init_credit_pool(p, 0, 0);
+ }
+
+ }
+}
+
+void bnx2x_init_vlan_credit_pool(struct bnx2x *bp,
+ struct bnx2x_credit_pool_obj *p,
+ u8 func_id,
+ u8 func_num)
+{
+ if (CHIP_IS_E1x(bp)) {
+ /*
+ * There is no VLAN credit in HW on 57710 and 57711 only
+ * MAC / MAC-VLAN can be set
+ */
+ bnx2x_init_credit_pool(p, 0, -1);
+ } else {
+ /*
+ * CAM credit is equaly divided between all active functions
+ * on the PATH.
+ */
+ if (func_num > 0) {
+ int credit = MAX_VLAN_CREDIT_E2 / func_num;
+ bnx2x_init_credit_pool(p, func_id * credit, credit);
+ } else
+ /* this should never happen! Block VLAN operations. */
+ bnx2x_init_credit_pool(p, 0, 0);
+ }
+}
+
+/****************** RSS Configuration ******************/
+/**
+ * bnx2x_debug_print_ind_table - prints the indirection table configuration.
+ *
+ * @bp: driver hanlde
+ * @p: pointer to rss configuration
+ *
+ * Prints it when NETIF_MSG_IFUP debug level is configured.
+ */
+static inline void bnx2x_debug_print_ind_table(struct bnx2x *bp,
+ struct bnx2x_config_rss_params *p)
+{
+ int i;
+
+ DP(BNX2X_MSG_SP, "Setting indirection table to:\n");
+ DP(BNX2X_MSG_SP, "0x0000: ");
+ for (i = 0; i < T_ETH_INDIRECTION_TABLE_SIZE; i++) {
+ DP_CONT(BNX2X_MSG_SP, "0x%02x ", p->ind_table[i]);
+
+ /* Print 4 bytes in a line */
+ if ((i + 1 < T_ETH_INDIRECTION_TABLE_SIZE) &&
+ (((i + 1) & 0x3) == 0)) {
+ DP_CONT(BNX2X_MSG_SP, "\n");
+ DP(BNX2X_MSG_SP, "0x%04x: ", i + 1);
+ }
+ }
+
+ DP_CONT(BNX2X_MSG_SP, "\n");
+}
+
+/**
+ * bnx2x_setup_rss - configure RSS
+ *
+ * @bp: device handle
+ * @p: rss configuration
+ *
+ * sends on UPDATE ramrod for that matter.
+ */
+static int bnx2x_setup_rss(struct bnx2x *bp,
+ struct bnx2x_config_rss_params *p)
+{
+ struct bnx2x_rss_config_obj *o = p->rss_obj;
+ struct bnx2x_raw_obj *r = &o->raw;
+ struct eth_rss_update_ramrod_data *data =
+ (struct eth_rss_update_ramrod_data *)(r->rdata);
+ u8 rss_mode = 0;
+ int rc;
+
+ memset(data, 0, sizeof(*data));
+
+ DP(BNX2X_MSG_SP, "Configuring RSS\n");
+
+ /* Set an echo field */
+ data->echo = (r->cid & BNX2X_SWCID_MASK) |
+ (r->state << BNX2X_SWCID_SHIFT);
+
+ /* RSS mode */
+ if (test_bit(BNX2X_RSS_MODE_DISABLED, &p->rss_flags))
+ rss_mode = ETH_RSS_MODE_DISABLED;
+ else if (test_bit(BNX2X_RSS_MODE_REGULAR, &p->rss_flags))
+ rss_mode = ETH_RSS_MODE_REGULAR;
+ else if (test_bit(BNX2X_RSS_MODE_VLAN_PRI, &p->rss_flags))
+ rss_mode = ETH_RSS_MODE_VLAN_PRI;
+ else if (test_bit(BNX2X_RSS_MODE_E1HOV_PRI, &p->rss_flags))
+ rss_mode = ETH_RSS_MODE_E1HOV_PRI;
+ else if (test_bit(BNX2X_RSS_MODE_IP_DSCP, &p->rss_flags))
+ rss_mode = ETH_RSS_MODE_IP_DSCP;
+
+ data->rss_mode = rss_mode;
+
+ DP(BNX2X_MSG_SP, "rss_mode=%d\n", rss_mode);
+
+ /* RSS capabilities */
+ if (test_bit(BNX2X_RSS_IPV4, &p->rss_flags))
+ data->capabilities |=
+ ETH_RSS_UPDATE_RAMROD_DATA_IPV4_CAPABILITY;
+
+ if (test_bit(BNX2X_RSS_IPV4_TCP, &p->rss_flags))
+ data->capabilities |=
+ ETH_RSS_UPDATE_RAMROD_DATA_IPV4_TCP_CAPABILITY;
+
+ if (test_bit(BNX2X_RSS_IPV6, &p->rss_flags))
+ data->capabilities |=
+ ETH_RSS_UPDATE_RAMROD_DATA_IPV6_CAPABILITY;
+
+ if (test_bit(BNX2X_RSS_IPV6_TCP, &p->rss_flags))
+ data->capabilities |=
+ ETH_RSS_UPDATE_RAMROD_DATA_IPV6_TCP_CAPABILITY;
+
+ /* Hashing mask */
+ data->rss_result_mask = p->rss_result_mask;
+
+ /* RSS engine ID */
+ data->rss_engine_id = o->engine_id;
+
+ DP(BNX2X_MSG_SP, "rss_engine_id=%d\n", data->rss_engine_id);
+
+ /* Indirection table */
+ memcpy(data->indirection_table, p->ind_table,
+ T_ETH_INDIRECTION_TABLE_SIZE);
+
+ /* Remember the last configuration */
+ memcpy(o->ind_table, p->ind_table, T_ETH_INDIRECTION_TABLE_SIZE);
+
+ /* Print the indirection table */
+ if (netif_msg_ifup(bp))
+ bnx2x_debug_print_ind_table(bp, p);
+
+ /* RSS keys */
+ if (test_bit(BNX2X_RSS_SET_SRCH, &p->rss_flags)) {
+ memcpy(&data->rss_key[0], &p->rss_key[0],
+ sizeof(data->rss_key));
+ data->capabilities |= ETH_RSS_UPDATE_RAMROD_DATA_UPDATE_RSS_KEY;
+ }
+
+ /* Commit writes towards the memory before sending a ramrod */
+ mb();
+
+ /* Send a ramrod */
+ rc = bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_RSS_UPDATE, r->cid,
+ U64_HI(r->rdata_mapping),
+ U64_LO(r->rdata_mapping),
+ ETH_CONNECTION_TYPE);
+
+ if (rc < 0)
+ return rc;
+
+ return 1;
+}
+
+void bnx2x_get_rss_ind_table(struct bnx2x_rss_config_obj *rss_obj,
+ u8 *ind_table)
+{
+ memcpy(ind_table, rss_obj->ind_table, sizeof(rss_obj->ind_table));
+}
+
+int bnx2x_config_rss(struct bnx2x *bp,
+ struct bnx2x_config_rss_params *p)
+{
+ int rc;
+ struct bnx2x_rss_config_obj *o = p->rss_obj;
+ struct bnx2x_raw_obj *r = &o->raw;
+
+ /* Do nothing if only driver cleanup was requested */
+ if (test_bit(RAMROD_DRV_CLR_ONLY, &p->ramrod_flags))
+ return 0;
+
+ r->set_pending(r);
+
+ rc = o->config_rss(bp, p);
+ if (rc < 0) {
+ r->clear_pending(r);
+ return rc;
+ }
+
+ if (test_bit(RAMROD_COMP_WAIT, &p->ramrod_flags))
+ rc = r->wait_comp(bp, r);
+
+ return rc;
+}
+
+
+void bnx2x_init_rss_config_obj(struct bnx2x *bp,
+ struct bnx2x_rss_config_obj *rss_obj,
+ u8 cl_id, u32 cid, u8 func_id, u8 engine_id,
+ void *rdata, dma_addr_t rdata_mapping,
+ int state, unsigned long *pstate,
+ bnx2x_obj_type type)
+{
+ bnx2x_init_raw_obj(&rss_obj->raw, cl_id, cid, func_id, rdata,
+ rdata_mapping, state, pstate, type);
+
+ rss_obj->engine_id = engine_id;
+ rss_obj->config_rss = bnx2x_setup_rss;
+}
+
+/********************** Queue state object ***********************************/
+
+/**
+ * bnx2x_queue_state_change - perform Queue state change transition
+ *
+ * @bp: device handle
+ * @params: parameters to perform the transition
+ *
+ * returns 0 in case of successfully completed transition, negative error
+ * code in case of failure, positive (EBUSY) value if there is a completion
+ * to that is still pending (possible only if RAMROD_COMP_WAIT is
+ * not set in params->ramrod_flags for asynchronous commands).
+ *
+ */
+int bnx2x_queue_state_change(struct bnx2x *bp,
+ struct bnx2x_queue_state_params *params)
+{
+ struct bnx2x_queue_sp_obj *o = params->q_obj;
+ int rc, pending_bit;
+ unsigned long *pending = &o->pending;
+
+ /* Check that the requested transition is legal */
+ if (o->check_transition(bp, o, params))
+ return -EINVAL;
+
+ /* Set "pending" bit */
+ pending_bit = o->set_pending(o, params);
+
+ /* Don't send a command if only driver cleanup was requested */
+ if (test_bit(RAMROD_DRV_CLR_ONLY, ¶ms->ramrod_flags))
+ o->complete_cmd(bp, o, pending_bit);
+ else {
+ /* Send a ramrod */
+ rc = o->send_cmd(bp, params);
+ if (rc) {
+ o->next_state = BNX2X_Q_STATE_MAX;
+ clear_bit(pending_bit, pending);
+ smp_mb__after_clear_bit();
+ return rc;
+ }
+
+ if (test_bit(RAMROD_COMP_WAIT, ¶ms->ramrod_flags)) {
+ rc = o->wait_comp(bp, o, pending_bit);
+ if (rc)
+ return rc;
+
+ return 0;
+ }
+ }
+
+ return !!test_bit(pending_bit, pending);
+}
+
+
+static int bnx2x_queue_set_pending(struct bnx2x_queue_sp_obj *obj,
+ struct bnx2x_queue_state_params *params)
+{
+ enum bnx2x_queue_cmd cmd = params->cmd, bit;
+
+ /* ACTIVATE and DEACTIVATE commands are implemented on top of
+ * UPDATE command.
+ */
+ if ((cmd == BNX2X_Q_CMD_ACTIVATE) ||
+ (cmd == BNX2X_Q_CMD_DEACTIVATE))
+ bit = BNX2X_Q_CMD_UPDATE;
+ else
+ bit = cmd;
+
+ set_bit(bit, &obj->pending);
+ return bit;
+}
+
+static int bnx2x_queue_wait_comp(struct bnx2x *bp,
+ struct bnx2x_queue_sp_obj *o,
+ enum bnx2x_queue_cmd cmd)
+{
+ return bnx2x_state_wait(bp, cmd, &o->pending);
+}
+
+/**
+ * bnx2x_queue_comp_cmd - complete the state change command.
+ *
+ * @bp: device handle
+ * @o:
+ * @cmd:
+ *
+ * Checks that the arrived completion is expected.
+ */
+static int bnx2x_queue_comp_cmd(struct bnx2x *bp,
+ struct bnx2x_queue_sp_obj *o,
+ enum bnx2x_queue_cmd cmd)
+{
+ unsigned long cur_pending = o->pending;
+
+ if (!test_and_clear_bit(cmd, &cur_pending)) {
+ BNX2X_ERR("Bad MC reply %d for queue %d in state %d "
+ "pending 0x%lx, next_state %d\n", cmd, o->cid,
+ o->state, cur_pending, o->next_state);
+ return -EINVAL;
+ }
+
+ DP(BNX2X_MSG_SP, "Completing command %d for queue %d, "
+ "setting state to %d\n", cmd, o->cid, o->next_state);
+
+ o->state = o->next_state;
+ o->next_state = BNX2X_Q_STATE_MAX;
+
+ /* It's important that o->state and o->next_state are
+ * updated before o->pending.
+ */
+ wmb();
+
+ clear_bit(cmd, &o->pending);
+ smp_mb__after_clear_bit();
+
+ return 0;
+}
+
+static void bnx2x_q_fill_setup_data_e2(struct bnx2x *bp,
+ struct bnx2x_queue_state_params *cmd_params,
+ struct client_init_ramrod_data *data)
+{
+ struct bnx2x_queue_setup_params *params = &cmd_params->params.setup;
+
+ /* Rx data */
+
+ /* IPv6 TPA supported for E2 and above only */
+ data->rx.tpa_en |= test_bit(BNX2X_Q_FLG_TPA, ¶ms->flags) *
+ CLIENT_INIT_RX_DATA_TPA_EN_IPV6;
+}
+
+static void bnx2x_q_fill_setup_data_cmn(struct bnx2x *bp,
+ struct bnx2x_queue_state_params *cmd_params,
+ struct client_init_ramrod_data *data)
+{
+ struct bnx2x_queue_sp_obj *o = cmd_params->q_obj;
+ struct bnx2x_queue_setup_params *params = &cmd_params->params.setup;
+
+
+ /* general */
+ data->general.client_id = o->cl_id;
+
+ if (test_bit(BNX2X_Q_FLG_STATS, ¶ms->flags)) {
+ data->general.statistics_counter_id =
+ params->gen_params.stat_id;
+ data->general.statistics_en_flg = 1;
+ data->general.statistics_zero_flg =
+ test_bit(BNX2X_Q_FLG_ZERO_STATS, ¶ms->flags);
+ } else
+ data->general.statistics_counter_id =
+ DISABLE_STATISTIC_COUNTER_ID_VALUE;
+
+ data->general.is_fcoe_flg = test_bit(BNX2X_Q_FLG_FCOE, ¶ms->flags);
+ data->general.activate_flg = test_bit(BNX2X_Q_FLG_ACTIVE,
+ ¶ms->flags);
+ data->general.sp_client_id = params->gen_params.spcl_id;
+ data->general.mtu = cpu_to_le16(params->gen_params.mtu);
+ data->general.func_id = o->func_id;
+
+
+ data->general.cos = params->txq_params.cos;
+
+ data->general.traffic_type =
+ test_bit(BNX2X_Q_FLG_FCOE, ¶ms->flags) ?
+ LLFC_TRAFFIC_TYPE_FCOE : LLFC_TRAFFIC_TYPE_NW;
+
+ /* Rx data */
+ data->rx.tpa_en = test_bit(BNX2X_Q_FLG_TPA, ¶ms->flags) *
+ CLIENT_INIT_RX_DATA_TPA_EN_IPV4;
+ data->rx.vmqueue_mode_en_flg = 0;
+
+ data->rx.cache_line_alignment_log_size =
+ params->rxq_params.cache_line_log;
+ data->rx.enable_dynamic_hc =
+ test_bit(BNX2X_Q_FLG_DHC, ¶ms->flags);
+ data->rx.max_sges_for_packet = params->rxq_params.max_sges_pkt;
+ data->rx.client_qzone_id = params->rxq_params.cl_qzone_id;
+ data->rx.max_agg_size = cpu_to_le16(params->rxq_params.tpa_agg_sz);
+
+ /* Always start in DROP_ALL mode */
+ data->rx.state = cpu_to_le16(CLIENT_INIT_RX_DATA_UCAST_DROP_ALL |
+ CLIENT_INIT_RX_DATA_MCAST_DROP_ALL);
+
+ /* We don't set drop flags */
+ data->rx.drop_ip_cs_err_flg = 0;
+ data->rx.drop_tcp_cs_err_flg = 0;
+ data->rx.drop_ttl0_flg = 0;
+ data->rx.drop_udp_cs_err_flg = 0;
+ data->rx.inner_vlan_removal_enable_flg =
+ test_bit(BNX2X_Q_FLG_VLAN, ¶ms->flags);
+ data->rx.outer_vlan_removal_enable_flg =
+ test_bit(BNX2X_Q_FLG_OV, ¶ms->flags);
+ data->rx.status_block_id = params->rxq_params.fw_sb_id;
+ data->rx.rx_sb_index_number = params->rxq_params.sb_cq_index;
+ data->rx.max_tpa_queues = params->rxq_params.max_tpa_queues;
+ data->rx.max_bytes_on_bd = cpu_to_le16(params->rxq_params.buf_sz);
+ data->rx.sge_buff_size = cpu_to_le16(params->rxq_params.sge_buf_sz);
+ data->rx.bd_page_base.lo =
+ cpu_to_le32(U64_LO(params->rxq_params.dscr_map));
+ data->rx.bd_page_base.hi =
+ cpu_to_le32(U64_HI(params->rxq_params.dscr_map));
+ data->rx.sge_page_base.lo =
+ cpu_to_le32(U64_LO(params->rxq_params.sge_map));
+ data->rx.sge_page_base.hi =
+ cpu_to_le32(U64_HI(params->rxq_params.sge_map));
+ data->rx.cqe_page_base.lo =
+ cpu_to_le32(U64_LO(params->rxq_params.rcq_map));
+ data->rx.cqe_page_base.hi =
+ cpu_to_le32(U64_HI(params->rxq_params.rcq_map));
+ data->rx.is_leading_rss = test_bit(BNX2X_Q_FLG_LEADING_RSS,
+ ¶ms->flags);
+
+ if (test_bit(BNX2X_Q_FLG_MCAST, ¶ms->flags)) {
+ data->rx.approx_mcast_engine_id = o->func_id;
+ data->rx.is_approx_mcast = 1;
+ }
+
+ data->rx.rss_engine_id = params->rxq_params.rss_engine_id;
+
+ /* flow control data */
+ data->rx.cqe_pause_thr_low = cpu_to_le16(params->pause.rcq_th_lo);
+ data->rx.cqe_pause_thr_high = cpu_to_le16(params->pause.rcq_th_hi);
+ data->rx.bd_pause_thr_low = cpu_to_le16(params->pause.bd_th_lo);
+ data->rx.bd_pause_thr_high = cpu_to_le16(params->pause.bd_th_hi);
+ data->rx.sge_pause_thr_low = cpu_to_le16(params->pause.sge_th_lo);
+ data->rx.sge_pause_thr_high = cpu_to_le16(params->pause.sge_th_hi);
+ data->rx.rx_cos_mask = cpu_to_le16(params->pause.pri_map);
+
+ /* silent vlan removal */
+ data->rx.silent_vlan_removal_flg =
+ test_bit(BNX2X_Q_FLG_SILENT_VLAN_REM, ¶ms->flags);
+ data->rx.silent_vlan_value =
+ cpu_to_le16(params->rxq_params.silent_removal_value);
+ data->rx.silent_vlan_mask =
+ cpu_to_le16(params->rxq_params.silent_removal_mask);
+
+ /* Tx data */
+ data->tx.enforce_security_flg =
+ test_bit(BNX2X_Q_FLG_TX_SEC, ¶ms->flags);
+ data->tx.default_vlan =
+ cpu_to_le16(params->txq_params.default_vlan);
+ data->tx.default_vlan_flg =
+ test_bit(BNX2X_Q_FLG_DEF_VLAN, ¶ms->flags);
+ data->tx.tx_switching_flg =
+ test_bit(BNX2X_Q_FLG_TX_SWITCH, ¶ms->flags);
+ data->tx.anti_spoofing_flg =
+ test_bit(BNX2X_Q_FLG_ANTI_SPOOF, ¶ms->flags);
+ data->tx.tx_status_block_id = params->txq_params.fw_sb_id;
+ data->tx.tx_sb_index_number = params->txq_params.sb_cq_index;
+ data->tx.tss_leading_client_id = params->txq_params.tss_leading_cl_id;
+
+ data->tx.tx_bd_page_base.lo =
+ cpu_to_le32(U64_LO(params->txq_params.dscr_map));
+ data->tx.tx_bd_page_base.hi =
+ cpu_to_le32(U64_HI(params->txq_params.dscr_map));
+
+ /* Don't configure any Tx switching mode during queue SETUP */
+ data->tx.state = 0;
+}
+
+
+/**
+ * bnx2x_q_init - init HW/FW queue
+ *
+ * @bp: device handle
+ * @params:
+ *
+ * HW/FW initial Queue configuration:
+ * - HC: Rx and Tx
+ * - CDU context validation
+ *
+ */
+static inline int bnx2x_q_init(struct bnx2x *bp,
+ struct bnx2x_queue_state_params *params)
+{
+ struct bnx2x_queue_sp_obj *o = params->q_obj;
+ struct bnx2x_queue_init_params *init = ¶ms->params.init;
+ u16 hc_usec;
+
+ /* Tx HC configuration */
+ if (test_bit(BNX2X_Q_TYPE_HAS_TX, &o->type) &&
+ test_bit(BNX2X_Q_FLG_HC, &init->tx.flags)) {
+ hc_usec = init->tx.hc_rate ? 1000000 / init->tx.hc_rate : 0;
+
+ bnx2x_update_coalesce_sb_index(bp, init->tx.fw_sb_id,
+ init->tx.sb_cq_index,
+ !test_bit(BNX2X_Q_FLG_HC_EN, &init->tx.flags),
+ hc_usec);
+ }
+
+ /* Rx HC configuration */
+ if (test_bit(BNX2X_Q_TYPE_HAS_RX, &o->type) &&
+ test_bit(BNX2X_Q_FLG_HC, &init->rx.flags)) {
+ hc_usec = init->rx.hc_rate ? 1000000 / init->rx.hc_rate : 0;
+
+ bnx2x_update_coalesce_sb_index(bp, init->rx.fw_sb_id,
+ init->rx.sb_cq_index,
+ !test_bit(BNX2X_Q_FLG_HC_EN, &init->rx.flags),
+ hc_usec);
+ }
+
+ /* Set CDU context validation values */
+ bnx2x_set_ctx_validation(bp, init->cxt, o->cid);
+
+ /* As no ramrod is sent, complete the command immediately */
+ o->complete_cmd(bp, o, BNX2X_Q_CMD_INIT);
+
+ mmiowb();
+ smp_mb();
+
+ return 0;
+}
+
+static inline int bnx2x_q_send_setup_e1x(struct bnx2x *bp,
+ struct bnx2x_queue_state_params *params)
+{
+ struct bnx2x_queue_sp_obj *o = params->q_obj;
+ struct client_init_ramrod_data *rdata =
+ (struct client_init_ramrod_data *)o->rdata;
+ dma_addr_t data_mapping = o->rdata_mapping;
+ int ramrod = RAMROD_CMD_ID_ETH_CLIENT_SETUP;
+
+ /* Clear the ramrod data */
+ memset(rdata, 0, sizeof(*rdata));
+
+ /* Fill the ramrod data */
+ bnx2x_q_fill_setup_data_cmn(bp, params, rdata);
+
+ mb();
+
+ return bnx2x_sp_post(bp, ramrod, o->cid, U64_HI(data_mapping),
+ U64_LO(data_mapping), ETH_CONNECTION_TYPE);
+}
+
+static inline int bnx2x_q_send_setup_e2(struct bnx2x *bp,
+ struct bnx2x_queue_state_params *params)
+{
+ struct bnx2x_queue_sp_obj *o = params->q_obj;
+ struct client_init_ramrod_data *rdata =
+ (struct client_init_ramrod_data *)o->rdata;
+ dma_addr_t data_mapping = o->rdata_mapping;
+ int ramrod = RAMROD_CMD_ID_ETH_CLIENT_SETUP;
+
+ /* Clear the ramrod data */
+ memset(rdata, 0, sizeof(*rdata));
+
+ /* Fill the ramrod data */
+ bnx2x_q_fill_setup_data_cmn(bp, params, rdata);
+ bnx2x_q_fill_setup_data_e2(bp, params, rdata);
+
+ mb();
+
+ return bnx2x_sp_post(bp, ramrod, o->cid, U64_HI(data_mapping),
+ U64_LO(data_mapping), ETH_CONNECTION_TYPE);
+}
+
+static void bnx2x_q_fill_update_data(struct bnx2x *bp,
+ struct bnx2x_queue_sp_obj *obj,
+ struct bnx2x_queue_update_params *params,
+ struct client_update_ramrod_data *data)
+{
+ /* Client ID of the client to update */
+ data->client_id = obj->cl_id;
+
+ /* Function ID of the client to update */
+ data->func_id = obj->func_id;
+
+ /* Default VLAN value */
+ data->default_vlan = cpu_to_le16(params->def_vlan);
+
+ /* Inner VLAN stripping */
+ data->inner_vlan_removal_enable_flg =
+ test_bit(BNX2X_Q_UPDATE_IN_VLAN_REM, ¶ms->update_flags);
+ data->inner_vlan_removal_change_flg =
+ test_bit(BNX2X_Q_UPDATE_IN_VLAN_REM_CHNG,
+ ¶ms->update_flags);
+
+ /* Outer VLAN sripping */
+ data->outer_vlan_removal_enable_flg =
+ test_bit(BNX2X_Q_UPDATE_OUT_VLAN_REM, ¶ms->update_flags);
+ data->outer_vlan_removal_change_flg =
+ test_bit(BNX2X_Q_UPDATE_OUT_VLAN_REM_CHNG,
+ ¶ms->update_flags);
+
+ /* Drop packets that have source MAC that doesn't belong to this
+ * Queue.
+ */
+ data->anti_spoofing_enable_flg =
+ test_bit(BNX2X_Q_UPDATE_ANTI_SPOOF, ¶ms->update_flags);
+ data->anti_spoofing_change_flg =
+ test_bit(BNX2X_Q_UPDATE_ANTI_SPOOF_CHNG, ¶ms->update_flags);
+
+ /* Activate/Deactivate */
+ data->activate_flg =
+ test_bit(BNX2X_Q_UPDATE_ACTIVATE, ¶ms->update_flags);
+ data->activate_change_flg =
+ test_bit(BNX2X_Q_UPDATE_ACTIVATE_CHNG, ¶ms->update_flags);
+
+ /* Enable default VLAN */
+ data->default_vlan_enable_flg =
+ test_bit(BNX2X_Q_UPDATE_DEF_VLAN_EN, ¶ms->update_flags);
+ data->default_vlan_change_flg =
+ test_bit(BNX2X_Q_UPDATE_DEF_VLAN_EN_CHNG,
+ ¶ms->update_flags);
+
+ /* silent vlan removal */
+ data->silent_vlan_change_flg =
+ test_bit(BNX2X_Q_UPDATE_SILENT_VLAN_REM_CHNG,
+ ¶ms->update_flags);
+ data->silent_vlan_removal_flg =
+ test_bit(BNX2X_Q_UPDATE_SILENT_VLAN_REM, ¶ms->update_flags);
+ data->silent_vlan_value = cpu_to_le16(params->silent_removal_value);
+ data->silent_vlan_mask = cpu_to_le16(params->silent_removal_mask);
+}
+
+static inline int bnx2x_q_send_update(struct bnx2x *bp,
+ struct bnx2x_queue_state_params *params)
+{
+ struct bnx2x_queue_sp_obj *o = params->q_obj;
+ struct client_update_ramrod_data *rdata =
+ (struct client_update_ramrod_data *)o->rdata;
+ dma_addr_t data_mapping = o->rdata_mapping;
+
+ /* Clear the ramrod data */
+ memset(rdata, 0, sizeof(*rdata));
+
+ /* Fill the ramrod data */
+ bnx2x_q_fill_update_data(bp, o, ¶ms->params.update, rdata);
+
+ mb();
+
+ return bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_CLIENT_UPDATE, o->cid,
+ U64_HI(data_mapping),
+ U64_LO(data_mapping), ETH_CONNECTION_TYPE);
+}
+
+/**
+ * bnx2x_q_send_deactivate - send DEACTIVATE command
+ *
+ * @bp: device handle
+ * @params:
+ *
+ * implemented using the UPDATE command.
+ */
+static inline int bnx2x_q_send_deactivate(struct bnx2x *bp,
+ struct bnx2x_queue_state_params *params)
+{
+ struct bnx2x_queue_update_params *update = ¶ms->params.update;
+
+ memset(update, 0, sizeof(*update));
+
+ __set_bit(BNX2X_Q_UPDATE_ACTIVATE_CHNG, &update->update_flags);
+
+ return bnx2x_q_send_update(bp, params);
+}
+
+/**
+ * bnx2x_q_send_activate - send ACTIVATE command
+ *
+ * @bp: device handle
+ * @params:
+ *
+ * implemented using the UPDATE command.
+ */
+static inline int bnx2x_q_send_activate(struct bnx2x *bp,
+ struct bnx2x_queue_state_params *params)
+{
+ struct bnx2x_queue_update_params *update = ¶ms->params.update;
+
+ memset(update, 0, sizeof(*update));
+
+ __set_bit(BNX2X_Q_UPDATE_ACTIVATE, &update->update_flags);
+ __set_bit(BNX2X_Q_UPDATE_ACTIVATE_CHNG, &update->update_flags);
+
+ return bnx2x_q_send_update(bp, params);
+}
+
+static inline int bnx2x_q_send_update_tpa(struct bnx2x *bp,
+ struct bnx2x_queue_state_params *params)
+{
+ /* TODO: Not implemented yet. */
+ return -1;
+}
+
+static inline int bnx2x_q_send_halt(struct bnx2x *bp,
+ struct bnx2x_queue_state_params *params)
+{
+ struct bnx2x_queue_sp_obj *o = params->q_obj;
+
+ return bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_HALT, o->cid, 0, o->cl_id,
+ ETH_CONNECTION_TYPE);
+}
+
+static inline int bnx2x_q_send_cfc_del(struct bnx2x *bp,
+ struct bnx2x_queue_state_params *params)
+{
+ struct bnx2x_queue_sp_obj *o = params->q_obj;
+
+ return bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_CFC_DEL, o->cid, 0, 0,
+ NONE_CONNECTION_TYPE);
+}
+
+static inline int bnx2x_q_send_terminate(struct bnx2x *bp,
+ struct bnx2x_queue_state_params *params)
+{
+ struct bnx2x_queue_sp_obj *o = params->q_obj;
+
+ return bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_TERMINATE, o->cid, 0, 0,
+ ETH_CONNECTION_TYPE);
+}
+
+static inline int bnx2x_q_send_empty(struct bnx2x *bp,
+ struct bnx2x_queue_state_params *params)
+{
+ struct bnx2x_queue_sp_obj *o = params->q_obj;
+
+ return bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_EMPTY, o->cid, 0, 0,
+ ETH_CONNECTION_TYPE);
+}
+
+static inline int bnx2x_queue_send_cmd_cmn(struct bnx2x *bp,
+ struct bnx2x_queue_state_params *params)
+{
+ switch (params->cmd) {
+ case BNX2X_Q_CMD_INIT:
+ return bnx2x_q_init(bp, params);
+ case BNX2X_Q_CMD_DEACTIVATE:
+ return bnx2x_q_send_deactivate(bp, params);
+ case BNX2X_Q_CMD_ACTIVATE:
+ return bnx2x_q_send_activate(bp, params);
+ case BNX2X_Q_CMD_UPDATE:
+ return bnx2x_q_send_update(bp, params);
+ case BNX2X_Q_CMD_UPDATE_TPA:
+ return bnx2x_q_send_update_tpa(bp, params);
+ case BNX2X_Q_CMD_HALT:
+ return bnx2x_q_send_halt(bp, params);
+ case BNX2X_Q_CMD_CFC_DEL:
+ return bnx2x_q_send_cfc_del(bp, params);
+ case BNX2X_Q_CMD_TERMINATE:
+ return bnx2x_q_send_terminate(bp, params);
+ case BNX2X_Q_CMD_EMPTY:
+ return bnx2x_q_send_empty(bp, params);
+ default:
+ BNX2X_ERR("Unknown command: %d\n", params->cmd);
+ return -EINVAL;
+ }
+}
+
+static int bnx2x_queue_send_cmd_e1x(struct bnx2x *bp,
+ struct bnx2x_queue_state_params *params)
+{
+ switch (params->cmd) {
+ case BNX2X_Q_CMD_SETUP:
+ return bnx2x_q_send_setup_e1x(bp, params);
+ case BNX2X_Q_CMD_INIT:
+ case BNX2X_Q_CMD_DEACTIVATE:
+ case BNX2X_Q_CMD_ACTIVATE:
+ case BNX2X_Q_CMD_UPDATE:
+ case BNX2X_Q_CMD_UPDATE_TPA:
+ case BNX2X_Q_CMD_HALT:
+ case BNX2X_Q_CMD_CFC_DEL:
+ case BNX2X_Q_CMD_TERMINATE:
+ case BNX2X_Q_CMD_EMPTY:
+ return bnx2x_queue_send_cmd_cmn(bp, params);
+ default:
+ BNX2X_ERR("Unknown command: %d\n", params->cmd);
+ return -EINVAL;
+ }
+}
+
+static int bnx2x_queue_send_cmd_e2(struct bnx2x *bp,
+ struct bnx2x_queue_state_params *params)
+{
+ switch (params->cmd) {
+ case BNX2X_Q_CMD_SETUP:
+ return bnx2x_q_send_setup_e2(bp, params);
+ case BNX2X_Q_CMD_INIT:
+ case BNX2X_Q_CMD_DEACTIVATE:
+ case BNX2X_Q_CMD_ACTIVATE:
+ case BNX2X_Q_CMD_UPDATE:
+ case BNX2X_Q_CMD_UPDATE_TPA:
+ case BNX2X_Q_CMD_HALT:
+ case BNX2X_Q_CMD_CFC_DEL:
+ case BNX2X_Q_CMD_TERMINATE:
+ case BNX2X_Q_CMD_EMPTY:
+ return bnx2x_queue_send_cmd_cmn(bp, params);
+ default:
+ BNX2X_ERR("Unknown command: %d\n", params->cmd);
+ return -EINVAL;
+ }
+}
+
+/**
+ * bnx2x_queue_chk_transition - check state machine of a regular Queue
+ *
+ * @bp: device handle
+ * @o:
+ * @params:
+ *
+ * (not Forwarding)
+ * It both checks if the requested command is legal in a current
+ * state and, if it's legal, sets a `next_state' in the object
+ * that will be used in the completion flow to set the `state'
+ * of the object.
+ *
+ * returns 0 if a requested command is a legal transition,
+ * -EINVAL otherwise.
+ */
+static int bnx2x_queue_chk_transition(struct bnx2x *bp,
+ struct bnx2x_queue_sp_obj *o,
+ struct bnx2x_queue_state_params *params)
+{
+ enum bnx2x_q_state state = o->state, next_state = BNX2X_Q_STATE_MAX;
+ enum bnx2x_queue_cmd cmd = params->cmd;
+
+ switch (state) {
+ case BNX2X_Q_STATE_RESET:
+ if (cmd == BNX2X_Q_CMD_INIT)
+ next_state = BNX2X_Q_STATE_INITIALIZED;
+
+ break;
+ case BNX2X_Q_STATE_INITIALIZED:
+ if (cmd == BNX2X_Q_CMD_SETUP) {
+ if (test_bit(BNX2X_Q_FLG_ACTIVE,
+ ¶ms->params.setup.flags))
+ next_state = BNX2X_Q_STATE_ACTIVE;
+ else
+ next_state = BNX2X_Q_STATE_INACTIVE;
+ }
+
+ break;
+ case BNX2X_Q_STATE_ACTIVE:
+ if (cmd == BNX2X_Q_CMD_DEACTIVATE)
+ next_state = BNX2X_Q_STATE_INACTIVE;
+
+ else if ((cmd == BNX2X_Q_CMD_EMPTY) ||
+ (cmd == BNX2X_Q_CMD_UPDATE_TPA))
+ next_state = BNX2X_Q_STATE_ACTIVE;
+
+ else if (cmd == BNX2X_Q_CMD_HALT)
+ next_state = BNX2X_Q_STATE_STOPPED;
+
+ else if (cmd == BNX2X_Q_CMD_UPDATE) {
+ struct bnx2x_queue_update_params *update_params =
+ ¶ms->params.update;
+
+ /* If "active" state change is requested, update the
+ * state accordingly.
+ */
+ if (test_bit(BNX2X_Q_UPDATE_ACTIVATE_CHNG,
+ &update_params->update_flags) &&
+ !test_bit(BNX2X_Q_UPDATE_ACTIVATE,
+ &update_params->update_flags))
+ next_state = BNX2X_Q_STATE_INACTIVE;
+ else
+ next_state = BNX2X_Q_STATE_ACTIVE;
+ }
+
+ break;
+ case BNX2X_Q_STATE_INACTIVE:
+ if (cmd == BNX2X_Q_CMD_ACTIVATE)
+ next_state = BNX2X_Q_STATE_ACTIVE;
+
+ else if ((cmd == BNX2X_Q_CMD_EMPTY) ||
+ (cmd == BNX2X_Q_CMD_UPDATE_TPA))
+ next_state = BNX2X_Q_STATE_INACTIVE;
+
+ else if (cmd == BNX2X_Q_CMD_HALT)
+ next_state = BNX2X_Q_STATE_STOPPED;
+
+ else if (cmd == BNX2X_Q_CMD_UPDATE) {
+ struct bnx2x_queue_update_params *update_params =
+ ¶ms->params.update;
+
+ /* If "active" state change is requested, update the
+ * state accordingly.
+ */
+ if (test_bit(BNX2X_Q_UPDATE_ACTIVATE_CHNG,
+ &update_params->update_flags) &&
+ test_bit(BNX2X_Q_UPDATE_ACTIVATE,
+ &update_params->update_flags))
+ next_state = BNX2X_Q_STATE_ACTIVE;
+ else
+ next_state = BNX2X_Q_STATE_INACTIVE;
+ }
+
+ break;
+ case BNX2X_Q_STATE_STOPPED:
+ if (cmd == BNX2X_Q_CMD_TERMINATE)
+ next_state = BNX2X_Q_STATE_TERMINATED;
+
+ break;
+ case BNX2X_Q_STATE_TERMINATED:
+ if (cmd == BNX2X_Q_CMD_CFC_DEL)
+ next_state = BNX2X_Q_STATE_RESET;
+
+ break;
+ default:
+ BNX2X_ERR("Illegal state: %d\n", state);
+ }
+
+ /* Transition is assured */
+ if (next_state != BNX2X_Q_STATE_MAX) {
+ DP(BNX2X_MSG_SP, "Good state transition: %d(%d)->%d\n",
+ state, cmd, next_state);
+ o->next_state = next_state;
+ return 0;
+ }
+
+ DP(BNX2X_MSG_SP, "Bad state transition request: %d %d\n", state, cmd);
+
+ return -EINVAL;
+}
+
+void bnx2x_init_queue_obj(struct bnx2x *bp,
+ struct bnx2x_queue_sp_obj *obj,
+ u8 cl_id, u32 cid, u8 func_id, void *rdata,
+ dma_addr_t rdata_mapping, unsigned long type)
+{
+ memset(obj, 0, sizeof(*obj));
+
+ obj->cid = cid;
+ obj->cl_id = cl_id;
+ obj->func_id = func_id;
+ obj->rdata = rdata;
+ obj->rdata_mapping = rdata_mapping;
+ obj->type = type;
+ obj->next_state = BNX2X_Q_STATE_MAX;
+
+ if (CHIP_IS_E1x(bp))
+ obj->send_cmd = bnx2x_queue_send_cmd_e1x;
+ else
+ obj->send_cmd = bnx2x_queue_send_cmd_e2;
+
+ obj->check_transition = bnx2x_queue_chk_transition;
+
+ obj->complete_cmd = bnx2x_queue_comp_cmd;
+ obj->wait_comp = bnx2x_queue_wait_comp;
+ obj->set_pending = bnx2x_queue_set_pending;
+}
+
+/********************** Function state object *********************************/
+
+static int bnx2x_func_wait_comp(struct bnx2x *bp,
+ struct bnx2x_func_sp_obj *o,
+ enum bnx2x_func_cmd cmd)
+{
+ return bnx2x_state_wait(bp, cmd, &o->pending);
+}
+
+/**
+ * bnx2x_func_state_change_comp - complete the state machine transition
+ *
+ * @bp: device handle
+ * @o:
+ * @cmd:
+ *
+ * Called on state change transition. Completes the state
+ * machine transition only - no HW interaction.
+ */
+static inline int bnx2x_func_state_change_comp(struct bnx2x *bp,
+ struct bnx2x_func_sp_obj *o,
+ enum bnx2x_func_cmd cmd)
+{
+ unsigned long cur_pending = o->pending;
+
+ if (!test_and_clear_bit(cmd, &cur_pending)) {
+ BNX2X_ERR("Bad MC reply %d for func %d in state %d "
+ "pending 0x%lx, next_state %d\n", cmd, BP_FUNC(bp),
+ o->state, cur_pending, o->next_state);
+ return -EINVAL;
+ }
+
+ DP(BNX2X_MSG_SP, "Completing command %d for func %d, setting state to "
+ "%d\n", cmd, BP_FUNC(bp), o->next_state);
+
+ o->state = o->next_state;
+ o->next_state = BNX2X_F_STATE_MAX;
+
+ /* It's important that o->state and o->next_state are
+ * updated before o->pending.
+ */
+ wmb();
+
+ clear_bit(cmd, &o->pending);
+ smp_mb__after_clear_bit();
+
+ return 0;
+}
+
+/**
+ * bnx2x_func_comp_cmd - complete the state change command
+ *
+ * @bp: device handle
+ * @o:
+ * @cmd:
+ *
+ * Checks that the arrived completion is expected.
+ */
+static int bnx2x_func_comp_cmd(struct bnx2x *bp,
+ struct bnx2x_func_sp_obj *o,
+ enum bnx2x_func_cmd cmd)
+{
+ /* Complete the state machine part first, check if it's a
+ * legal completion.
+ */
+ int rc = bnx2x_func_state_change_comp(bp, o, cmd);
+ return rc;
+}
+
+/**
+ * bnx2x_func_chk_transition - perform function state machine transition
+ *
+ * @bp: device handle
+ * @o:
+ * @params:
+ *
+ * It both checks if the requested command is legal in a current
+ * state and, if it's legal, sets a `next_state' in the object
+ * that will be used in the completion flow to set the `state'
+ * of the object.
+ *
+ * returns 0 if a requested command is a legal transition,
+ * -EINVAL otherwise.
+ */
+static int bnx2x_func_chk_transition(struct bnx2x *bp,
+ struct bnx2x_func_sp_obj *o,
+ struct bnx2x_func_state_params *params)
+{
+ enum bnx2x_func_state state = o->state, next_state = BNX2X_F_STATE_MAX;
+ enum bnx2x_func_cmd cmd = params->cmd;
+
+ switch (state) {
+ case BNX2X_F_STATE_RESET:
+ if (cmd == BNX2X_F_CMD_HW_INIT)
+ next_state = BNX2X_F_STATE_INITIALIZED;
+
+ break;
+ case BNX2X_F_STATE_INITIALIZED:
+ if (cmd == BNX2X_F_CMD_START)
+ next_state = BNX2X_F_STATE_STARTED;
+
+ else if (cmd == BNX2X_F_CMD_HW_RESET)
+ next_state = BNX2X_F_STATE_RESET;
+
+ break;
+ case BNX2X_F_STATE_STARTED:
+ if (cmd == BNX2X_F_CMD_STOP)
+ next_state = BNX2X_F_STATE_INITIALIZED;
+
+ break;
+ default:
+ BNX2X_ERR("Unknown state: %d\n", state);
+ }
+
+ /* Transition is assured */
+ if (next_state != BNX2X_F_STATE_MAX) {
+ DP(BNX2X_MSG_SP, "Good function state transition: %d(%d)->%d\n",
+ state, cmd, next_state);
+ o->next_state = next_state;
+ return 0;
+ }
+
+ DP(BNX2X_MSG_SP, "Bad function state transition request: %d %d\n",
+ state, cmd);
+
+ return -EINVAL;
+}
+
+/**
+ * bnx2x_func_init_func - performs HW init at function stage
+ *
+ * @bp: device handle
+ * @drv:
+ *
+ * Init HW when the current phase is
+ * FW_MSG_CODE_DRV_LOAD_FUNCTION: initialize only FUNCTION-only
+ * HW blocks.
+ */
+static inline int bnx2x_func_init_func(struct bnx2x *bp,
+ const struct bnx2x_func_sp_drv_ops *drv)
+{
+ return drv->init_hw_func(bp);
+}
+
+/**
+ * bnx2x_func_init_port - performs HW init at port stage
+ *
+ * @bp: device handle
+ * @drv:
+ *
+ * Init HW when the current phase is
+ * FW_MSG_CODE_DRV_LOAD_PORT: initialize PORT-only and
+ * FUNCTION-only HW blocks.
+ *
+ */
+static inline int bnx2x_func_init_port(struct bnx2x *bp,
+ const struct bnx2x_func_sp_drv_ops *drv)
+{
+ int rc = drv->init_hw_port(bp);
+ if (rc)
+ return rc;
+
+ return bnx2x_func_init_func(bp, drv);
+}
+
+/**
+ * bnx2x_func_init_cmn_chip - performs HW init at chip-common stage
+ *
+ * @bp: device handle
+ * @drv:
+ *
+ * Init HW when the current phase is
+ * FW_MSG_CODE_DRV_LOAD_COMMON_CHIP: initialize COMMON_CHIP,
+ * PORT-only and FUNCTION-only HW blocks.
+ */
+static inline int bnx2x_func_init_cmn_chip(struct bnx2x *bp,
+ const struct bnx2x_func_sp_drv_ops *drv)
+{
+ int rc = drv->init_hw_cmn_chip(bp);
+ if (rc)
+ return rc;
+
+ return bnx2x_func_init_port(bp, drv);
+}
+
+/**
+ * bnx2x_func_init_cmn - performs HW init at common stage
+ *
+ * @bp: device handle
+ * @drv:
+ *
+ * Init HW when the current phase is
+ * FW_MSG_CODE_DRV_LOAD_COMMON_CHIP: initialize COMMON,
+ * PORT-only and FUNCTION-only HW blocks.
+ */
+static inline int bnx2x_func_init_cmn(struct bnx2x *bp,
+ const struct bnx2x_func_sp_drv_ops *drv)
+{
+ int rc = drv->init_hw_cmn(bp);
+ if (rc)
+ return rc;
+
+ return bnx2x_func_init_port(bp, drv);
+}
+
+static int bnx2x_func_hw_init(struct bnx2x *bp,
+ struct bnx2x_func_state_params *params)
+{
+ u32 load_code = params->params.hw_init.load_phase;
+ struct bnx2x_func_sp_obj *o = params->f_obj;
+ const struct bnx2x_func_sp_drv_ops *drv = o->drv;
+ int rc = 0;
+
+ DP(BNX2X_MSG_SP, "function %d load_code %x\n",
+ BP_ABS_FUNC(bp), load_code);
+
+ /* Prepare buffers for unzipping the FW */
+ rc = drv->gunzip_init(bp);
+ if (rc)
+ return rc;
+
+ /* Prepare FW */
+ rc = drv->init_fw(bp);
+ if (rc) {
+ BNX2X_ERR("Error loading firmware\n");
+ goto fw_init_err;
+ }
+
+ /* Handle the beginning of COMMON_XXX pases separatelly... */
+ switch (load_code) {
+ case FW_MSG_CODE_DRV_LOAD_COMMON_CHIP:
+ rc = bnx2x_func_init_cmn_chip(bp, drv);
+ if (rc)
+ goto init_hw_err;
+
+ break;
+ case FW_MSG_CODE_DRV_LOAD_COMMON:
+ rc = bnx2x_func_init_cmn(bp, drv);
+ if (rc)
+ goto init_hw_err;
+
+ break;
+ case FW_MSG_CODE_DRV_LOAD_PORT:
+ rc = bnx2x_func_init_port(bp, drv);
+ if (rc)
+ goto init_hw_err;
+
+ break;
+ case FW_MSG_CODE_DRV_LOAD_FUNCTION:
+ rc = bnx2x_func_init_func(bp, drv);
+ if (rc)
+ goto init_hw_err;
+
+ break;
+ default:
+ BNX2X_ERR("Unknown load_code (0x%x) from MCP\n", load_code);
+ rc = -EINVAL;
+ }
+
+init_hw_err:
+ drv->release_fw(bp);
+
+fw_init_err:
+ drv->gunzip_end(bp);
+
+ /* In case of success, complete the comand immediatelly: no ramrods
+ * have been sent.
+ */
+ if (!rc)
+ o->complete_cmd(bp, o, BNX2X_F_CMD_HW_INIT);
+
+ return rc;
+}
+
+/**
+ * bnx2x_func_reset_func - reset HW at function stage
+ *
+ * @bp: device handle
+ * @drv:
+ *
+ * Reset HW at FW_MSG_CODE_DRV_UNLOAD_FUNCTION stage: reset only
+ * FUNCTION-only HW blocks.
+ */
+static inline void bnx2x_func_reset_func(struct bnx2x *bp,
+ const struct bnx2x_func_sp_drv_ops *drv)
+{
+ drv->reset_hw_func(bp);
+}
+
+/**
+ * bnx2x_func_reset_port - reser HW at port stage
+ *
+ * @bp: device handle
+ * @drv:
+ *
+ * Reset HW at FW_MSG_CODE_DRV_UNLOAD_PORT stage: reset
+ * FUNCTION-only and PORT-only HW blocks.
+ *
+ * !!!IMPORTANT!!!
+ *
+ * It's important to call reset_port before reset_func() as the last thing
+ * reset_func does is pf_disable() thus disabling PGLUE_B, which
+ * makes impossible any DMAE transactions.
+ */
+static inline void bnx2x_func_reset_port(struct bnx2x *bp,
+ const struct bnx2x_func_sp_drv_ops *drv)
+{
+ drv->reset_hw_port(bp);
+ bnx2x_func_reset_func(bp, drv);
+}
+
+/**
+ * bnx2x_func_reset_cmn - reser HW at common stage
+ *
+ * @bp: device handle
+ * @drv:
+ *
+ * Reset HW at FW_MSG_CODE_DRV_UNLOAD_COMMON and
+ * FW_MSG_CODE_DRV_UNLOAD_COMMON_CHIP stages: reset COMMON,
+ * COMMON_CHIP, FUNCTION-only and PORT-only HW blocks.
+ */
+static inline void bnx2x_func_reset_cmn(struct bnx2x *bp,
+ const struct bnx2x_func_sp_drv_ops *drv)
+{
+ bnx2x_func_reset_port(bp, drv);
+ drv->reset_hw_cmn(bp);
+}
+
+
+static inline int bnx2x_func_hw_reset(struct bnx2x *bp,
+ struct bnx2x_func_state_params *params)
+{
+ u32 reset_phase = params->params.hw_reset.reset_phase;
+ struct bnx2x_func_sp_obj *o = params->f_obj;
+ const struct bnx2x_func_sp_drv_ops *drv = o->drv;
+
+ DP(BNX2X_MSG_SP, "function %d reset_phase %x\n", BP_ABS_FUNC(bp),
+ reset_phase);
+
+ switch (reset_phase) {
+ case FW_MSG_CODE_DRV_UNLOAD_COMMON:
+ bnx2x_func_reset_cmn(bp, drv);
+ break;
+ case FW_MSG_CODE_DRV_UNLOAD_PORT:
+ bnx2x_func_reset_port(bp, drv);
+ break;
+ case FW_MSG_CODE_DRV_UNLOAD_FUNCTION:
+ bnx2x_func_reset_func(bp, drv);
+ break;
+ default:
+ BNX2X_ERR("Unknown reset_phase (0x%x) from MCP\n",
+ reset_phase);
+ break;
+ }
+
+ /* Complete the comand immediatelly: no ramrods have been sent. */
+ o->complete_cmd(bp, o, BNX2X_F_CMD_HW_RESET);
+
+ return 0;
+}
+
+static inline int bnx2x_func_send_start(struct bnx2x *bp,
+ struct bnx2x_func_state_params *params)
+{
+ struct bnx2x_func_sp_obj *o = params->f_obj;
+ struct function_start_data *rdata =
+ (struct function_start_data *)o->rdata;
+ dma_addr_t data_mapping = o->rdata_mapping;
+ struct bnx2x_func_start_params *start_params = ¶ms->params.start;
+
+ memset(rdata, 0, sizeof(*rdata));
+
+ /* Fill the ramrod data with provided parameters */
+ rdata->function_mode = cpu_to_le16(start_params->mf_mode);
+ rdata->sd_vlan_tag = start_params->sd_vlan_tag;
+ rdata->path_id = BP_PATH(bp);
+ rdata->network_cos_mode = start_params->network_cos_mode;
+
+ mb();
+
+ return bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_FUNCTION_START, 0,
+ U64_HI(data_mapping),
+ U64_LO(data_mapping), NONE_CONNECTION_TYPE);
+}
+
+static inline int bnx2x_func_send_stop(struct bnx2x *bp,
+ struct bnx2x_func_state_params *params)
+{
+ return bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_FUNCTION_STOP, 0, 0, 0,
+ NONE_CONNECTION_TYPE);
+}
+
+static int bnx2x_func_send_cmd(struct bnx2x *bp,
+ struct bnx2x_func_state_params *params)
+{
+ switch (params->cmd) {
+ case BNX2X_F_CMD_HW_INIT:
+ return bnx2x_func_hw_init(bp, params);
+ case BNX2X_F_CMD_START:
+ return bnx2x_func_send_start(bp, params);
+ case BNX2X_F_CMD_STOP:
+ return bnx2x_func_send_stop(bp, params);
+ case BNX2X_F_CMD_HW_RESET:
+ return bnx2x_func_hw_reset(bp, params);
+ default:
+ BNX2X_ERR("Unknown command: %d\n", params->cmd);
+ return -EINVAL;
+ }
+}
+
+void bnx2x_init_func_obj(struct bnx2x *bp,
+ struct bnx2x_func_sp_obj *obj,
+ void *rdata, dma_addr_t rdata_mapping,
+ struct bnx2x_func_sp_drv_ops *drv_iface)
+{
+ memset(obj, 0, sizeof(*obj));
+
+ mutex_init(&obj->one_pending_mutex);
+
+ obj->rdata = rdata;
+ obj->rdata_mapping = rdata_mapping;
+
+ obj->send_cmd = bnx2x_func_send_cmd;
+ obj->check_transition = bnx2x_func_chk_transition;
+ obj->complete_cmd = bnx2x_func_comp_cmd;
+ obj->wait_comp = bnx2x_func_wait_comp;
+
+ obj->drv = drv_iface;
+}
+
+/**
+ * bnx2x_func_state_change - perform Function state change transition
+ *
+ * @bp: device handle
+ * @params: parameters to perform the transaction
+ *
+ * returns 0 in case of successfully completed transition,
+ * negative error code in case of failure, positive
+ * (EBUSY) value if there is a completion to that is
+ * still pending (possible only if RAMROD_COMP_WAIT is
+ * not set in params->ramrod_flags for asynchronous
+ * commands).
+ */
+int bnx2x_func_state_change(struct bnx2x *bp,
+ struct bnx2x_func_state_params *params)
+{
+ struct bnx2x_func_sp_obj *o = params->f_obj;
+ int rc;
+ enum bnx2x_func_cmd cmd = params->cmd;
+ unsigned long *pending = &o->pending;
+
+ mutex_lock(&o->one_pending_mutex);
+
+ /* Check that the requested transition is legal */
+ if (o->check_transition(bp, o, params)) {
+ mutex_unlock(&o->one_pending_mutex);
+ return -EINVAL;
+ }
+
+ /* Set "pending" bit */
+ set_bit(cmd, pending);
+
+ /* Don't send a command if only driver cleanup was requested */
+ if (test_bit(RAMROD_DRV_CLR_ONLY, ¶ms->ramrod_flags)) {
+ bnx2x_func_state_change_comp(bp, o, cmd);
+ mutex_unlock(&o->one_pending_mutex);
+ } else {
+ /* Send a ramrod */
+ rc = o->send_cmd(bp, params);
+
+ mutex_unlock(&o->one_pending_mutex);
+
+ if (rc) {
+ o->next_state = BNX2X_F_STATE_MAX;
+ clear_bit(cmd, pending);
+ smp_mb__after_clear_bit();
+ return rc;
+ }
+
+ if (test_bit(RAMROD_COMP_WAIT, ¶ms->ramrod_flags)) {
+ rc = o->wait_comp(bp, o, cmd);
+ if (rc)
+ return rc;
+
+ return 0;
+ }
+ }
+
+ return !!test_bit(cmd, pending);
+}
diff --git a/drivers/net/bnx2x/bnx2x_sp.h b/drivers/net/bnx2x/bnx2x_sp.h
new file mode 100644
index 0000000..86eaa807
--- /dev/null
+++ b/drivers/net/bnx2x/bnx2x_sp.h
@@ -0,0 +1,1235 @@
+/* bnx2x_sp.h: Broadcom Everest network driver.
+ *
+ * Copyright 2011 Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2, available
+ * at http://www.gnu.org/licenses/old-licenses/gpl-2.0.html (the "GPL").
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a
+ * license other than the GPL, without Broadcom's express prior written
+ * consent.
+ *
+ * Maintained by: Eilon Greenstein <eilong@broadcom.com>
+ * Written by: Vladislav Zolotarov
+ *
+ */
+#ifndef BNX2X_SP_VERBS
+#define BNX2X_SP_VERBS
+
+struct bnx2x;
+struct eth_context;
+
+/* Bits representing general command's configuration */
+enum {
+ RAMROD_TX,
+ RAMROD_RX,
+ /* Wait until all pending commands complete */
+ RAMROD_COMP_WAIT,
+ /* Don't send a ramrod, only update a registry */
+ RAMROD_DRV_CLR_ONLY,
+ /* Configure HW according to the current object state */
+ RAMROD_RESTORE,
+ /* Execute the next command now */
+ RAMROD_EXEC,
+ /*
+ * Don't add a new command and continue execution of posponed
+ * commands. If not set a new command will be added to the
+ * pending commands list.
+ */
+ RAMROD_CONT,
+};
+
+typedef enum {
+ BNX2X_OBJ_TYPE_RX,
+ BNX2X_OBJ_TYPE_TX,
+ BNX2X_OBJ_TYPE_RX_TX,
+} bnx2x_obj_type;
+
+/* Filtering states */
+enum {
+ BNX2X_FILTER_MAC_PENDING,
+ BNX2X_FILTER_VLAN_PENDING,
+ BNX2X_FILTER_VLAN_MAC_PENDING,
+ BNX2X_FILTER_RX_MODE_PENDING,
+ BNX2X_FILTER_RX_MODE_SCHED,
+ BNX2X_FILTER_ISCSI_ETH_START_SCHED,
+ BNX2X_FILTER_ISCSI_ETH_STOP_SCHED,
+ BNX2X_FILTER_FCOE_ETH_START_SCHED,
+ BNX2X_FILTER_FCOE_ETH_STOP_SCHED,
+ BNX2X_FILTER_MCAST_PENDING,
+ BNX2X_FILTER_MCAST_SCHED,
+ BNX2X_FILTER_RSS_CONF_PENDING,
+};
+
+struct bnx2x_raw_obj {
+ u8 func_id;
+
+ /* Queue params */
+ u8 cl_id;
+ u32 cid;
+
+ /* Ramrod data buffer params */
+ void *rdata;
+ dma_addr_t rdata_mapping;
+
+ /* Ramrod state params */
+ int state; /* "ramrod is pending" state bit */
+ unsigned long *pstate; /* pointer to state buffer */
+
+ bnx2x_obj_type obj_type;
+
+ int (*wait_comp)(struct bnx2x *bp,
+ struct bnx2x_raw_obj *o);
+
+ bool (*check_pending)(struct bnx2x_raw_obj *o);
+ void (*clear_pending)(struct bnx2x_raw_obj *o);
+ void (*set_pending)(struct bnx2x_raw_obj *o);
+};
+
+/************************* VLAN-MAC commands related parameters ***************/
+struct bnx2x_mac_ramrod_data {
+ u8 mac[ETH_ALEN];
+};
+
+struct bnx2x_vlan_ramrod_data {
+ u16 vlan;
+};
+
+struct bnx2x_vlan_mac_ramrod_data {
+ u8 mac[ETH_ALEN];
+ u16 vlan;
+};
+
+union bnx2x_classification_ramrod_data {
+ struct bnx2x_mac_ramrod_data mac;
+ struct bnx2x_vlan_ramrod_data vlan;
+ struct bnx2x_vlan_mac_ramrod_data vlan_mac;
+};
+
+/* VLAN_MAC commands */
+enum bnx2x_vlan_mac_cmd {
+ BNX2X_VLAN_MAC_ADD,
+ BNX2X_VLAN_MAC_DEL,
+ BNX2X_VLAN_MAC_MOVE,
+};
+
+struct bnx2x_vlan_mac_data {
+ /* Requested command: BNX2X_VLAN_MAC_XX */
+ enum bnx2x_vlan_mac_cmd cmd;
+ /*
+ * used to contain the data related vlan_mac_flags bits from
+ * ramrod parameters.
+ */
+ unsigned long vlan_mac_flags;
+
+ /* Needed for MOVE command */
+ struct bnx2x_vlan_mac_obj *target_obj;
+
+ union bnx2x_classification_ramrod_data u;
+};
+
+/*************************** Exe Queue obj ************************************/
+union bnx2x_exe_queue_cmd_data {
+ struct bnx2x_vlan_mac_data vlan_mac;
+
+ struct {
+ /* TODO */
+ } mcast;
+};
+
+struct bnx2x_exeq_elem {
+ struct list_head link;
+
+ /* Length of this element in the exe_chunk. */
+ int cmd_len;
+
+ union bnx2x_exe_queue_cmd_data cmd_data;
+};
+
+union bnx2x_qable_obj;
+
+union bnx2x_exeq_comp_elem {
+ union event_ring_elem *elem;
+};
+
+struct bnx2x_exe_queue_obj;
+
+typedef int (*exe_q_validate)(struct bnx2x *bp,
+ union bnx2x_qable_obj *o,
+ struct bnx2x_exeq_elem *elem);
+
+/**
+ * @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,
+ struct bnx2x_exeq_elem *elem);
+typedef int (*exe_q_execute)(struct bnx2x *bp,
+ union bnx2x_qable_obj *o,
+ struct list_head *exe_chunk,
+ unsigned long *ramrod_flags);
+typedef struct bnx2x_exeq_elem *
+ (*exe_q_get)(struct bnx2x_exe_queue_obj *o,
+ struct bnx2x_exeq_elem *elem);
+
+struct bnx2x_exe_queue_obj {
+ /*
+ * Commands pending for an execution.
+ */
+ struct list_head exe_queue;
+
+ /*
+ * Commands pending for an completion.
+ */
+ struct list_head pending_comp;
+
+ spinlock_t lock;
+
+ /* Maximum length of commands' list for one execution */
+ int exe_chunk_len;
+
+ union bnx2x_qable_obj *owner;
+
+ /****** Virtual functions ******/
+ /**
+ * Called before commands execution for commands that are really
+ * going to be executed (after 'optimize').
+ *
+ * Must run under exe_queue->lock
+ */
+ exe_q_validate validate;
+
+
+ /**
+ * This will try to cancel the current pending commands list
+ * considering the new command.
+ *
+ * Must run under exe_queue->lock
+ */
+ exe_q_optimize optimize;
+
+ /**
+ * Run the next commands chunk (owner specific).
+ */
+ exe_q_execute execute;
+
+ /**
+ * Return the exe_queue element containing the specific command
+ * if any. Otherwise return NULL.
+ */
+ exe_q_get get;
+};
+/***************** Classification verbs: Set/Del MAC/VLAN/VLAN-MAC ************/
+/*
+ * Element in the VLAN_MAC registry list having all currenty configured
+ * rules.
+ */
+struct bnx2x_vlan_mac_registry_elem {
+ struct list_head link;
+
+ /*
+ * Used to store the cam offset used for the mac/vlan/vlan-mac.
+ * Relevant for 57710 and 57711 only. VLANs and MACs share the
+ * same CAM for these chips.
+ */
+ int cam_offset;
+
+ /* Needed for DEL and RESTORE flows */
+ unsigned long vlan_mac_flags;
+
+ union bnx2x_classification_ramrod_data u;
+};
+
+/* Bits representing VLAN_MAC commands specific flags */
+enum {
+ BNX2X_UC_LIST_MAC,
+ BNX2X_ETH_MAC,
+ BNX2X_ISCSI_ETH_MAC,
+ BNX2X_NETQ_ETH_MAC,
+ BNX2X_DONT_CONSUME_CAM_CREDIT,
+ BNX2X_DONT_CONSUME_CAM_CREDIT_DEST,
+};
+
+struct bnx2x_vlan_mac_ramrod_params {
+ /* Object to run the command from */
+ struct bnx2x_vlan_mac_obj *vlan_mac_obj;
+
+ /* General command flags: COMP_WAIT, etc. */
+ unsigned long ramrod_flags;
+
+ /* Command specific configuration request */
+ struct bnx2x_vlan_mac_data user_req;
+};
+
+struct bnx2x_vlan_mac_obj {
+ struct bnx2x_raw_obj raw;
+
+ /* Bookkeeping list: will prevent the addition of already existing
+ * entries.
+ */
+ struct list_head head;
+
+ /* TODO: Add it's initialization in the init functions */
+ struct bnx2x_exe_queue_obj exe_queue;
+
+ /* MACs credit pool */
+ struct bnx2x_credit_pool_obj *macs_pool;
+
+ /* VLANs credit pool */
+ struct bnx2x_credit_pool_obj *vlans_pool;
+
+ /* RAMROD command to be used */
+ int ramrod_cmd;
+
+ /**
+ * Checks if ADD-ramrod with the given params may be performed.
+ *
+ * @return zero if the element may be added
+ */
+
+ int (*check_add)(struct bnx2x_vlan_mac_obj *o,
+ union bnx2x_classification_ramrod_data *data);
+
+ /**
+ * Checks if DEL-ramrod with the given params may be performed.
+ *
+ * @return true if the element may be deleted
+ */
+ struct bnx2x_vlan_mac_registry_elem *
+ (*check_del)(struct bnx2x_vlan_mac_obj *o,
+ union bnx2x_classification_ramrod_data *data);
+
+ /**
+ * Checks if DEL-ramrod with the given params may be performed.
+ *
+ * @return true if the element may be deleted
+ */
+ bool (*check_move)(struct bnx2x_vlan_mac_obj *src_o,
+ struct bnx2x_vlan_mac_obj *dst_o,
+ union bnx2x_classification_ramrod_data *data);
+
+ /**
+ * Update the relevant credit object(s) (consume/return
+ * correspondingly).
+ */
+ bool (*get_credit)(struct bnx2x_vlan_mac_obj *o);
+ bool (*put_credit)(struct bnx2x_vlan_mac_obj *o);
+ bool (*get_cam_offset)(struct bnx2x_vlan_mac_obj *o, int *offset);
+ bool (*put_cam_offset)(struct bnx2x_vlan_mac_obj *o, int offset);
+
+ /**
+ * Configures one rule in the ramrod data buffer.
+ */
+ void (*set_one_rule)(struct bnx2x *bp,
+ struct bnx2x_vlan_mac_obj *o,
+ struct bnx2x_exeq_elem *elem, int rule_idx,
+ int cam_offset);
+
+ /**
+ * Delete all configured elements having the given
+ * vlan_mac_flags specification. Assumes no pending for
+ * execution commands. Will schedule all all currently
+ * configured MACs/VLANs/VLAN-MACs matching the vlan_mac_flags
+ * specification for deletion and will use the given
+ * ramrod_flags for the last DEL operation.
+ *
+ * @param bp
+ * @param o
+ * @param ramrod_flags RAMROD_XX flags
+ *
+ * @return 0 if the last operation has completed successfully
+ * and there are no more elements left, positive value
+ * if there are pending for completion commands,
+ * negative value in case of failure.
+ */
+ int (*delete_all)(struct bnx2x *bp,
+ struct bnx2x_vlan_mac_obj *o,
+ unsigned long *vlan_mac_flags,
+ unsigned long *ramrod_flags);
+
+ /**
+ * Reconfigures the next MAC/VLAN/VLAN-MAC element from the previously
+ * configured elements list.
+ *
+ * @param bp
+ * @param p Command parameters (RAMROD_COMP_WAIT bit in
+ * ramrod_flags is only taken into an account)
+ * @param ppos a pointer to the cooky that should be given back in the
+ * next call to make function handle the next element. If
+ * *ppos is set to NULL it will restart the iterator.
+ * If returned *ppos == NULL this means that the last
+ * element has been handled.
+ *
+ * @return int
+ */
+ int (*restore)(struct bnx2x *bp,
+ struct bnx2x_vlan_mac_ramrod_params *p,
+ struct bnx2x_vlan_mac_registry_elem **ppos);
+
+ /**
+ * Should be called on a completion arival.
+ *
+ * @param bp
+ * @param o
+ * @param cqe Completion element we are handling
+ * @param ramrod_flags if RAMROD_CONT is set the next bulk of
+ * pending commands will be executed.
+ * RAMROD_DRV_CLR_ONLY and RAMROD_RESTORE
+ * may also be set if needed.
+ *
+ * @return 0 if there are neither pending nor waiting for
+ * completion commands. Positive value if there are
+ * pending for execution or for completion commands.
+ * Negative value in case of an error (including an
+ * error in the cqe).
+ */
+ int (*complete)(struct bnx2x *bp, struct bnx2x_vlan_mac_obj *o,
+ union event_ring_elem *cqe,
+ unsigned long *ramrod_flags);
+
+ /**
+ * Wait for completion of all commands. Don't schedule new ones,
+ * just wait. It assumes that the completion code will schedule
+ * for new commands.
+ */
+ int (*wait)(struct bnx2x *bp, struct bnx2x_vlan_mac_obj *o);
+};
+
+/** RX_MODE verbs:DROP_ALL/ACCEPT_ALL/ACCEPT_ALL_MULTI/ACCEPT_ALL_VLAN/NORMAL */
+
+/* RX_MODE ramrod spesial flags: set in rx_mode_flags field in
+ * a bnx2x_rx_mode_ramrod_params.
+ */
+enum {
+ BNX2X_RX_MODE_FCOE_ETH,
+ BNX2X_RX_MODE_ISCSI_ETH,
+};
+
+enum {
+ BNX2X_ACCEPT_UNICAST,
+ BNX2X_ACCEPT_MULTICAST,
+ BNX2X_ACCEPT_ALL_UNICAST,
+ BNX2X_ACCEPT_ALL_MULTICAST,
+ BNX2X_ACCEPT_BROADCAST,
+ BNX2X_ACCEPT_UNMATCHED,
+ BNX2X_ACCEPT_ANY_VLAN
+};
+
+struct bnx2x_rx_mode_ramrod_params {
+ struct bnx2x_rx_mode_obj *rx_mode_obj;
+ unsigned long *pstate;
+ int state;
+ u8 cl_id;
+ u32 cid;
+ u8 func_id;
+ unsigned long ramrod_flags;
+ unsigned long rx_mode_flags;
+
+ /*
+ * rdata is either a pointer to eth_filter_rules_ramrod_data(e2) or to
+ * a tstorm_eth_mac_filter_config (e1x).
+ */
+ void *rdata;
+ dma_addr_t rdata_mapping;
+
+ /* Rx mode settings */
+ unsigned long rx_accept_flags;
+
+ /* internal switching settings */
+ unsigned long tx_accept_flags;
+};
+
+struct bnx2x_rx_mode_obj {
+ int (*config_rx_mode)(struct bnx2x *bp,
+ struct bnx2x_rx_mode_ramrod_params *p);
+
+ int (*wait_comp)(struct bnx2x *bp,
+ struct bnx2x_rx_mode_ramrod_params *p);
+};
+
+/********************** Set multicast group ***********************************/
+
+struct bnx2x_mcast_list_elem {
+ struct list_head link;
+ u8 *mac;
+};
+
+union bnx2x_mcast_config_data {
+ u8 *mac;
+ u8 bin; /* used in a RESTORE flow */
+};
+
+struct bnx2x_mcast_ramrod_params {
+ struct bnx2x_mcast_obj *mcast_obj;
+
+ /* Relevant options are RAMROD_COMP_WAIT and RAMROD_DRV_CLR_ONLY */
+ unsigned long ramrod_flags;
+
+ struct list_head mcast_list; /* list of struct bnx2x_mcast_list_elem */
+ /** TODO:
+ * - rename it to macs_num.
+ * - Add a new command type for handling pending commands
+ * (remove "zero semantics").
+ *
+ * Length of mcast_list. If zero and ADD_CONT command - post
+ * pending commands.
+ */
+ int mcast_list_len;
+};
+
+enum {
+ BNX2X_MCAST_CMD_ADD,
+ BNX2X_MCAST_CMD_CONT,
+ BNX2X_MCAST_CMD_DEL,
+ BNX2X_MCAST_CMD_RESTORE,
+};
+
+struct bnx2x_mcast_obj {
+ struct bnx2x_raw_obj raw;
+
+ union {
+ struct {
+ #define BNX2X_MCAST_BINS_NUM 256
+ #define BNX2X_MCAST_VEC_SZ (BNX2X_MCAST_BINS_NUM / 64)
+ u64 vec[BNX2X_MCAST_VEC_SZ];
+
+ /** Number of BINs to clear. Should be updated
+ * immediately when a command arrives in order to
+ * properly create DEL commands.
+ */
+ int num_bins_set;
+ } aprox_match;
+
+ struct {
+ struct list_head macs;
+ int num_macs_set;
+ } exact_match;
+ } registry;
+
+ /* Pending commands */
+ struct list_head pending_cmds_head;
+
+ /* A state that is set in raw.pstate, when there are pending commands */
+ int sched_state;
+
+ /* Maximal number of mcast MACs configured in one command */
+ int max_cmd_len;
+
+ /* Total number of currently pending MACs to configure: both
+ * in the pending commands list and in the current command.
+ */
+ int total_pending_num;
+
+ u8 engine_id;
+
+ /**
+ * @param cmd command to execute (BNX2X_MCAST_CMD_X, see above)
+ */
+ int (*config_mcast)(struct bnx2x *bp,
+ struct bnx2x_mcast_ramrod_params *p, int cmd);
+
+ /**
+ * Fills the ramrod data during the RESTORE flow.
+ *
+ * @param bp
+ * @param o
+ * @param start_idx Registry index to start from
+ * @param rdata_idx Index in the ramrod data to start from
+ *
+ * @return -1 if we handled the whole registry or index of the last
+ * handled registry element.
+ */
+ int (*hdl_restore)(struct bnx2x *bp, struct bnx2x_mcast_obj *o,
+ int start_bin, int *rdata_idx);
+
+ int (*enqueue_cmd)(struct bnx2x *bp, struct bnx2x_mcast_obj *o,
+ struct bnx2x_mcast_ramrod_params *p, int cmd);
+
+ void (*set_one_rule)(struct bnx2x *bp,
+ struct bnx2x_mcast_obj *o, int idx,
+ union bnx2x_mcast_config_data *cfg_data, int cmd);
+
+ /** Checks if there are more mcast MACs to be set or a previous
+ * command is still pending.
+ */
+ bool (*check_pending)(struct bnx2x_mcast_obj *o);
+
+ /**
+ * Set/Clear/Check SCHEDULED state of the object
+ */
+ void (*set_sched)(struct bnx2x_mcast_obj *o);
+ void (*clear_sched)(struct bnx2x_mcast_obj *o);
+ bool (*check_sched)(struct bnx2x_mcast_obj *o);
+
+ /* Wait until all pending commands complete */
+ int (*wait_comp)(struct bnx2x *bp, struct bnx2x_mcast_obj *o);
+
+ /**
+ * Handle the internal object counters needed for proper
+ * commands handling. Checks that the provided parameters are
+ * feasible.
+ */
+ int (*validate)(struct bnx2x *bp,
+ struct bnx2x_mcast_ramrod_params *p, int cmd);
+
+ /**
+ * Restore the values of internal counters in case of a failure.
+ */
+ void (*revert)(struct bnx2x *bp,
+ struct bnx2x_mcast_ramrod_params *p,
+ int old_num_bins);
+
+ int (*get_registry_size)(struct bnx2x_mcast_obj *o);
+ void (*set_registry_size)(struct bnx2x_mcast_obj *o, int n);
+};
+
+/*************************** Credit handling **********************************/
+struct bnx2x_credit_pool_obj {
+
+ /* Current amount of credit in the pool */
+ atomic_t credit;
+
+ /* Maximum allowed credit. put() will check against it. */
+ int pool_sz;
+
+ /*
+ * Allocate a pool table statically.
+ *
+ * Currently the mamimum allowed size is MAX_MAC_CREDIT_E2(272)
+ *
+ * The set bit in the table will mean that the entry is available.
+ */
+#define BNX2X_POOL_VEC_SIZE (MAX_MAC_CREDIT_E2 / 64)
+ u64 pool_mirror[BNX2X_POOL_VEC_SIZE];
+
+ /* Base pool offset (initialized differently */
+ int base_pool_offset;
+
+ /**
+ * Get the next free pool entry.
+ *
+ * @return true if there was a free entry in the pool
+ */
+ bool (*get_entry)(struct bnx2x_credit_pool_obj *o, int *entry);
+
+ /**
+ * Return the entry back to the pool.
+ *
+ * @return true if entry is legal and has been successfully
+ * returned to the pool.
+ */
+ bool (*put_entry)(struct bnx2x_credit_pool_obj *o, int entry);
+
+ /**
+ * Get the requested amount of credit from the pool.
+ *
+ * @param cnt Amount of requested credit
+ * @return true if the operation is successful
+ */
+ bool (*get)(struct bnx2x_credit_pool_obj *o, int cnt);
+
+ /**
+ * Returns the credit to the pool.
+ *
+ * @param cnt Amount of credit to return
+ * @return true if the operation is successful
+ */
+ bool (*put)(struct bnx2x_credit_pool_obj *o, int cnt);
+
+ /**
+ * Reads the current amount of credit.
+ */
+ int (*check)(struct bnx2x_credit_pool_obj *o);
+};
+
+/*************************** RSS configuration ********************************/
+enum {
+ /* RSS_MODE bits are mutually exclusive */
+ BNX2X_RSS_MODE_DISABLED,
+ BNX2X_RSS_MODE_REGULAR,
+ BNX2X_RSS_MODE_VLAN_PRI,
+ BNX2X_RSS_MODE_E1HOV_PRI,
+ BNX2X_RSS_MODE_IP_DSCP,
+
+ BNX2X_RSS_SET_SRCH, /* Setup searcher, E1x specific flag */
+
+ BNX2X_RSS_IPV4,
+ BNX2X_RSS_IPV4_TCP,
+ BNX2X_RSS_IPV6,
+ BNX2X_RSS_IPV6_TCP,
+};
+
+struct bnx2x_config_rss_params {
+ struct bnx2x_rss_config_obj *rss_obj;
+
+ /* may have RAMROD_COMP_WAIT set only */
+ unsigned long ramrod_flags;
+
+ /* BNX2X_RSS_X bits */
+ unsigned long rss_flags;
+
+ /* Number hash bits to take into an account */
+ u8 rss_result_mask;
+
+ /* Indirection table */
+ u8 ind_table[T_ETH_INDIRECTION_TABLE_SIZE];
+
+ /* RSS hash values */
+ u32 rss_key[10];
+
+ /* valid only iff BNX2X_RSS_UPDATE_TOE is set */
+ u16 toe_rss_bitmap;
+};
+
+struct bnx2x_rss_config_obj {
+ struct bnx2x_raw_obj raw;
+
+ /* RSS engine to use */
+ u8 engine_id;
+
+ /* Last configured indirection table */
+ u8 ind_table[T_ETH_INDIRECTION_TABLE_SIZE];
+
+ int (*config_rss)(struct bnx2x *bp,
+ struct bnx2x_config_rss_params *p);
+};
+
+/*********************** Queue state update ***********************************/
+
+/* UPDATE command options */
+enum {
+ BNX2X_Q_UPDATE_IN_VLAN_REM,
+ BNX2X_Q_UPDATE_IN_VLAN_REM_CHNG,
+ BNX2X_Q_UPDATE_OUT_VLAN_REM,
+ BNX2X_Q_UPDATE_OUT_VLAN_REM_CHNG,
+ BNX2X_Q_UPDATE_ANTI_SPOOF,
+ BNX2X_Q_UPDATE_ANTI_SPOOF_CHNG,
+ BNX2X_Q_UPDATE_ACTIVATE,
+ BNX2X_Q_UPDATE_ACTIVATE_CHNG,
+ BNX2X_Q_UPDATE_DEF_VLAN_EN,
+ BNX2X_Q_UPDATE_DEF_VLAN_EN_CHNG,
+ BNX2X_Q_UPDATE_SILENT_VLAN_REM_CHNG,
+ BNX2X_Q_UPDATE_SILENT_VLAN_REM
+};
+
+/* Allowed Queue states */
+enum bnx2x_q_state {
+ BNX2X_Q_STATE_RESET,
+ BNX2X_Q_STATE_INITIALIZED,
+ BNX2X_Q_STATE_ACTIVE,
+ BNX2X_Q_STATE_INACTIVE,
+ BNX2X_Q_STATE_STOPPED,
+ BNX2X_Q_STATE_TERMINATED,
+ BNX2X_Q_STATE_FLRED,
+ BNX2X_Q_STATE_MAX,
+};
+
+/* Allowed commands */
+enum bnx2x_queue_cmd {
+ BNX2X_Q_CMD_INIT,
+ BNX2X_Q_CMD_SETUP,
+ BNX2X_Q_CMD_DEACTIVATE,
+ BNX2X_Q_CMD_ACTIVATE,
+ BNX2X_Q_CMD_UPDATE,
+ BNX2X_Q_CMD_UPDATE_TPA,
+ BNX2X_Q_CMD_HALT,
+ BNX2X_Q_CMD_CFC_DEL,
+ BNX2X_Q_CMD_TERMINATE,
+ BNX2X_Q_CMD_EMPTY,
+ BNX2X_Q_CMD_MAX,
+};
+
+/* queue SETUP + INIT flags */
+enum {
+ BNX2X_Q_FLG_TPA,
+ BNX2X_Q_FLG_STATS,
+ BNX2X_Q_FLG_ZERO_STATS,
+ BNX2X_Q_FLG_ACTIVE,
+ BNX2X_Q_FLG_OV,
+ BNX2X_Q_FLG_VLAN,
+ BNX2X_Q_FLG_COS,
+ BNX2X_Q_FLG_HC,
+ BNX2X_Q_FLG_HC_EN,
+ BNX2X_Q_FLG_DHC,
+ BNX2X_Q_FLG_FCOE,
+ BNX2X_Q_FLG_LEADING_RSS,
+ BNX2X_Q_FLG_MCAST,
+ BNX2X_Q_FLG_DEF_VLAN,
+ BNX2X_Q_FLG_TX_SWITCH,
+ BNX2X_Q_FLG_TX_SEC,
+ BNX2X_Q_FLG_ANTI_SPOOF,
+ BNX2X_Q_FLG_SILENT_VLAN_REM
+};
+
+/* Queue type options: queue type may be a compination of below. */
+enum bnx2x_q_type {
+ /** TODO: Consider moving both these flags into the init()
+ * ramrod params.
+ */
+ BNX2X_Q_TYPE_HAS_RX,
+ BNX2X_Q_TYPE_HAS_TX,
+};
+
+struct bnx2x_queue_init_params {
+ struct {
+ unsigned long flags;
+ u16 hc_rate;
+ u8 fw_sb_id;
+ u8 sb_cq_index;
+ } tx;
+
+ struct {
+ unsigned long flags;
+ u16 hc_rate;
+ u8 fw_sb_id;
+ u8 sb_cq_index;
+ } rx;
+
+ /* CID context in the host memory */
+ struct eth_context *cxt;
+};
+
+struct bnx2x_queue_update_params {
+ unsigned long update_flags; /* BNX2X_Q_UPDATE_XX bits */
+ u16 def_vlan;
+ u16 silent_removal_value;
+ u16 silent_removal_mask;
+};
+
+struct rxq_pause_params {
+ u16 bd_th_lo;
+ u16 bd_th_hi;
+ u16 rcq_th_lo;
+ u16 rcq_th_hi;
+ u16 sge_th_lo; /* valid iff BNX2X_Q_FLG_TPA */
+ u16 sge_th_hi; /* valid iff BNX2X_Q_FLG_TPA */
+ u16 pri_map;
+};
+
+/* general */
+struct bnx2x_general_setup_params {
+ /* valid iff BNX2X_Q_FLG_STATS */
+ u8 stat_id;
+
+ u8 spcl_id;
+ u16 mtu;
+};
+
+struct bnx2x_rxq_setup_params {
+ /* dma */
+ dma_addr_t dscr_map;
+ dma_addr_t sge_map;
+ dma_addr_t rcq_map;
+ dma_addr_t rcq_np_map;
+
+ u16 drop_flags;
+ u16 buf_sz;
+ u8 fw_sb_id;
+ u8 cl_qzone_id;
+
+ /* valid iff BNX2X_Q_FLG_TPA */
+ u16 tpa_agg_sz;
+ u16 sge_buf_sz;
+ u8 max_sges_pkt;
+ u8 max_tpa_queues;
+ u8 rss_engine_id;
+
+ u8 cache_line_log;
+
+ u8 sb_cq_index;
+
+ /* valid iff BXN2X_Q_FLG_SILENT_VLAN_REM */
+ u16 silent_removal_value;
+ u16 silent_removal_mask;
+};
+
+struct bnx2x_txq_setup_params {
+ /* dma */
+ dma_addr_t dscr_map;
+
+ u8 fw_sb_id;
+ u8 sb_cq_index;
+ u8 cos; /* valid iff BNX2X_Q_FLG_COS */
+ u16 traffic_type;
+ /* equals to the leading rss client id, used for TX classification*/
+ u8 tss_leading_cl_id;
+
+ /* valid iff BNX2X_Q_FLG_DEF_VLAN */
+ u16 default_vlan;
+};
+
+struct bnx2x_queue_setup_params {
+ struct rxq_pause_params pause;
+ struct bnx2x_general_setup_params gen_params;
+ struct bnx2x_rxq_setup_params rxq_params;
+ struct bnx2x_txq_setup_params txq_params;
+ unsigned long flags;
+};
+
+
+struct bnx2x_queue_state_params {
+ struct bnx2x_queue_sp_obj *q_obj;
+
+ /* Current command */
+ enum bnx2x_queue_cmd cmd;
+
+ /* may have RAMROD_COMP_WAIT set only */
+ unsigned long ramrod_flags;
+
+ /* Params according to the current command */
+ union {
+ struct bnx2x_queue_update_params update;
+ struct bnx2x_queue_setup_params setup;
+ struct bnx2x_queue_init_params init;
+ } params;
+};
+
+struct bnx2x_queue_sp_obj {
+ u32 cid;
+ u8 cl_id;
+ u8 func_id;
+
+ enum bnx2x_q_state state, next_state;
+
+ /* bits from enum bnx2x_q_type */
+ unsigned long type;
+
+ /* BNX2X_Q_CMD_XX bits. This object implements "one
+ * pending" paradigm but for debug and tracing purposes it's
+ * more convinient to have different bits for different
+ * commands.
+ */
+ unsigned long pending;
+
+ /* Buffer to use as a ramrod data and its mapping */
+ void *rdata;
+ dma_addr_t rdata_mapping;
+
+ /**
+ * Performs one state change according to the given parameters.
+ *
+ * @return 0 in case of success and negative value otherwise.
+ */
+ int (*send_cmd)(struct bnx2x *bp,
+ struct bnx2x_queue_state_params *params);
+
+ /**
+ * Sets the pending bit according to the requested transition.
+ */
+ int (*set_pending)(struct bnx2x_queue_sp_obj *o,
+ struct bnx2x_queue_state_params *params);
+
+ /**
+ * Checks that the requested state transition is legal.
+ */
+ int (*check_transition)(struct bnx2x *bp,
+ struct bnx2x_queue_sp_obj *o,
+ struct bnx2x_queue_state_params *params);
+
+ /**
+ * Completes the pending command.
+ */
+ int (*complete_cmd)(struct bnx2x *bp,
+ struct bnx2x_queue_sp_obj *o,
+ enum bnx2x_queue_cmd);
+
+ int (*wait_comp)(struct bnx2x *bp,
+ struct bnx2x_queue_sp_obj *o,
+ enum bnx2x_queue_cmd cmd);
+};
+
+/********************** Function state update *********************************/
+/* Allowed Function states */
+enum bnx2x_func_state {
+ BNX2X_F_STATE_RESET,
+ BNX2X_F_STATE_INITIALIZED,
+ BNX2X_F_STATE_STARTED,
+ BNX2X_F_STATE_MAX,
+};
+
+/* Allowed Function commands */
+enum bnx2x_func_cmd {
+ BNX2X_F_CMD_HW_INIT,
+ BNX2X_F_CMD_START,
+ BNX2X_F_CMD_STOP,
+ BNX2X_F_CMD_HW_RESET,
+ BNX2X_F_CMD_MAX,
+};
+
+struct bnx2x_func_hw_init_params {
+ /* A load phase returned by MCP.
+ *
+ * May be:
+ * FW_MSG_CODE_DRV_LOAD_COMMON_CHIP
+ * FW_MSG_CODE_DRV_LOAD_COMMON
+ * FW_MSG_CODE_DRV_LOAD_PORT
+ * FW_MSG_CODE_DRV_LOAD_FUNCTION
+ */
+ u32 load_phase;
+};
+
+struct bnx2x_func_hw_reset_params {
+ /* A load phase returned by MCP.
+ *
+ * May be:
+ * FW_MSG_CODE_DRV_LOAD_COMMON_CHIP
+ * FW_MSG_CODE_DRV_LOAD_COMMON
+ * FW_MSG_CODE_DRV_LOAD_PORT
+ * FW_MSG_CODE_DRV_LOAD_FUNCTION
+ */
+ u32 reset_phase;
+};
+
+struct bnx2x_func_start_params {
+ /* Multi Function mode:
+ * - Single Function
+ * - Switch Dependent
+ * - Switch Independent
+ */
+ u16 mf_mode;
+
+ /* Switch Dependent mode outer VLAN tag */
+ u16 sd_vlan_tag;
+
+ /* Function cos mode */
+ u8 network_cos_mode;
+};
+
+struct bnx2x_func_state_params {
+ struct bnx2x_func_sp_obj *f_obj;
+
+ /* Current command */
+ enum bnx2x_func_cmd cmd;
+
+ /* may have RAMROD_COMP_WAIT set only */
+ unsigned long ramrod_flags;
+
+ /* Params according to the current command */
+ union {
+ struct bnx2x_func_hw_init_params hw_init;
+ struct bnx2x_func_hw_reset_params hw_reset;
+ struct bnx2x_func_start_params start;
+ } params;
+};
+
+struct bnx2x_func_sp_drv_ops {
+ /* Init tool + runtime initialization:
+ * - Common Chip
+ * - Common (per Path)
+ * - Port
+ * - Function phases
+ */
+ int (*init_hw_cmn_chip)(struct bnx2x *bp);
+ int (*init_hw_cmn)(struct bnx2x *bp);
+ int (*init_hw_port)(struct bnx2x *bp);
+ int (*init_hw_func)(struct bnx2x *bp);
+
+ /* Reset Function HW: Common, Port, Function phases. */
+ void (*reset_hw_cmn)(struct bnx2x *bp);
+ void (*reset_hw_port)(struct bnx2x *bp);
+ void (*reset_hw_func)(struct bnx2x *bp);
+
+ /* Init/Free GUNZIP resources */
+ int (*gunzip_init)(struct bnx2x *bp);
+ void (*gunzip_end)(struct bnx2x *bp);
+
+ /* Prepare/Release FW resources */
+ int (*init_fw)(struct bnx2x *bp);
+ void (*release_fw)(struct bnx2x *bp);
+};
+
+struct bnx2x_func_sp_obj {
+ enum bnx2x_func_state state, next_state;
+
+ /* BNX2X_FUNC_CMD_XX bits. This object implements "one
+ * pending" paradigm but for debug and tracing purposes it's
+ * more convinient to have different bits for different
+ * commands.
+ */
+ unsigned long pending;
+
+ /* Buffer to use as a ramrod data and its mapping */
+ void *rdata;
+ dma_addr_t rdata_mapping;
+
+ /* this mutex validates that when pending flag is taken, the next
+ * ramrod to be sent will be the one set the pending bit
+ */
+ struct mutex one_pending_mutex;
+
+ /* Driver interface */
+ struct bnx2x_func_sp_drv_ops *drv;
+
+ /**
+ * Performs one state change according to the given parameters.
+ *
+ * @return 0 in case of success and negative value otherwise.
+ */
+ int (*send_cmd)(struct bnx2x *bp,
+ struct bnx2x_func_state_params *params);
+
+ /**
+ * Checks that the requested state transition is legal.
+ */
+ int (*check_transition)(struct bnx2x *bp,
+ struct bnx2x_func_sp_obj *o,
+ struct bnx2x_func_state_params *params);
+
+ /**
+ * Completes the pending command.
+ */
+ int (*complete_cmd)(struct bnx2x *bp,
+ struct bnx2x_func_sp_obj *o,
+ enum bnx2x_func_cmd cmd);
+
+ int (*wait_comp)(struct bnx2x *bp, struct bnx2x_func_sp_obj *o,
+ enum bnx2x_func_cmd cmd);
+};
+
+/********************** Interfaces ********************************************/
+/* Queueable objects set */
+union bnx2x_qable_obj {
+ struct bnx2x_vlan_mac_obj vlan_mac;
+};
+/************** Function state update *********/
+void bnx2x_init_func_obj(struct bnx2x *bp,
+ struct bnx2x_func_sp_obj *obj,
+ void *rdata, dma_addr_t rdata_mapping,
+ struct bnx2x_func_sp_drv_ops *drv_iface);
+
+int bnx2x_func_state_change(struct bnx2x *bp,
+ struct bnx2x_func_state_params *params);
+
+/******************* Queue State **************/
+void bnx2x_init_queue_obj(struct bnx2x *bp,
+ struct bnx2x_queue_sp_obj *obj, u8 cl_id, u32 cid,
+ u8 func_id, void *rdata, dma_addr_t rdata_mapping,
+ unsigned long type);
+
+int bnx2x_queue_state_change(struct bnx2x *bp,
+ struct bnx2x_queue_state_params *params);
+
+/********************* VLAN-MAC ****************/
+void bnx2x_init_mac_obj(struct bnx2x *bp,
+ struct bnx2x_vlan_mac_obj *mac_obj,
+ u8 cl_id, u32 cid, u8 func_id, void *rdata,
+ dma_addr_t rdata_mapping, int state,
+ unsigned long *pstate, bnx2x_obj_type type,
+ struct bnx2x_credit_pool_obj *macs_pool);
+
+void bnx2x_init_vlan_obj(struct bnx2x *bp,
+ struct bnx2x_vlan_mac_obj *vlan_obj,
+ u8 cl_id, u32 cid, u8 func_id, void *rdata,
+ dma_addr_t rdata_mapping, int state,
+ unsigned long *pstate, bnx2x_obj_type type,
+ struct bnx2x_credit_pool_obj *vlans_pool);
+
+void bnx2x_init_vlan_mac_obj(struct bnx2x *bp,
+ struct bnx2x_vlan_mac_obj *vlan_mac_obj,
+ u8 cl_id, u32 cid, u8 func_id, void *rdata,
+ dma_addr_t rdata_mapping, int state,
+ unsigned long *pstate, bnx2x_obj_type type,
+ struct bnx2x_credit_pool_obj *macs_pool,
+ struct bnx2x_credit_pool_obj *vlans_pool);
+
+int bnx2x_config_vlan_mac(struct bnx2x *bp,
+ struct bnx2x_vlan_mac_ramrod_params *p);
+
+int bnx2x_vlan_mac_move(struct bnx2x *bp,
+ struct bnx2x_vlan_mac_ramrod_params *p,
+ struct bnx2x_vlan_mac_obj *dest_o);
+
+/********************* RX MODE ****************/
+
+void bnx2x_init_rx_mode_obj(struct bnx2x *bp,
+ struct bnx2x_rx_mode_obj *o);
+
+/**
+ * Send and RX_MODE ramrod according to the provided parameters.
+ *
+ * @param bp
+ * @param p Command parameters
+ *
+ * @return 0 - if operation was successfull and there is no pending completions,
+ * positive number - if there are pending completions,
+ * negative - if there were errors
+ */
+int bnx2x_config_rx_mode(struct bnx2x *bp,
+ struct bnx2x_rx_mode_ramrod_params *p);
+
+/****************** MULTICASTS ****************/
+
+void bnx2x_init_mcast_obj(struct bnx2x *bp,
+ struct bnx2x_mcast_obj *mcast_obj,
+ u8 mcast_cl_id, u32 mcast_cid, u8 func_id,
+ u8 engine_id, void *rdata, dma_addr_t rdata_mapping,
+ int state, unsigned long *pstate,
+ bnx2x_obj_type type);
+
+/**
+ * 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
+ * (BNX2X_MCAST_CMD_CONT).
+ *
+ * If previous command is still pending or if number of MACs to
+ * configure is more that maximum number of MACs in one command,
+ * the current command will be enqueued to the tail of the
+ * pending commands list.
+ *
+ * @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.
+ */
+int bnx2x_config_mcast(struct bnx2x *bp,
+ struct bnx2x_mcast_ramrod_params *p, int cmd);
+
+/****************** CREDIT POOL ****************/
+void bnx2x_init_mac_credit_pool(struct bnx2x *bp,
+ struct bnx2x_credit_pool_obj *p, u8 func_id,
+ u8 func_num);
+void bnx2x_init_vlan_credit_pool(struct bnx2x *bp,
+ struct bnx2x_credit_pool_obj *p, u8 func_id,
+ u8 func_num);
+
+
+/****************** RSS CONFIGURATION ****************/
+void bnx2x_init_rss_config_obj(struct bnx2x *bp,
+ struct bnx2x_rss_config_obj *rss_obj,
+ u8 cl_id, u32 cid, u8 func_id, u8 engine_id,
+ void *rdata, dma_addr_t rdata_mapping,
+ int state, unsigned long *pstate,
+ bnx2x_obj_type type);
+
+/**
+ * Updates RSS configuration according to provided parameters.
+ *
+ * @param bp
+ * @param p
+ *
+ * @return 0 in case of success
+ */
+int bnx2x_config_rss(struct bnx2x *bp,
+ struct bnx2x_config_rss_params *p);
+
+/**
+ * Return the current ind_table configuration.
+ *
+ * @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.
+ */
+void bnx2x_get_rss_ind_table(struct bnx2x_rss_config_obj *rss_obj,
+ u8 *ind_table);
+
+#endif /* BNX2X_SP_VERBS */
diff --git a/drivers/net/bnx2x/bnx2x_stats.c b/drivers/net/bnx2x/bnx2x_stats.c
index e535bfa..54c07f5 100644
--- a/drivers/net/bnx2x/bnx2x_stats.c
+++ b/drivers/net/bnx2x/bnx2x_stats.c
@@ -14,121 +14,12 @@
* Statistics and Link management by Yitchak Gertner
*
*/
-#include "bnx2x_cmn.h"
#include "bnx2x_stats.h"
+#include "bnx2x_cmn.h"
+
/* Statistics */
-/****************************************************************************
-* Macros
-****************************************************************************/
-
-/* sum[hi:lo] += add[hi:lo] */
-#define ADD_64(s_hi, a_hi, s_lo, a_lo) \
- do { \
- s_lo += a_lo; \
- s_hi += a_hi + ((s_lo < a_lo) ? 1 : 0); \
- } while (0)
-
-/* difference = minuend - subtrahend */
-#define DIFF_64(d_hi, m_hi, s_hi, d_lo, m_lo, s_lo) \
- do { \
- if (m_lo < s_lo) { \
- /* underflow */ \
- d_hi = m_hi - s_hi; \
- if (d_hi > 0) { \
- /* we can 'loan' 1 */ \
- d_hi--; \
- d_lo = m_lo + (UINT_MAX - s_lo) + 1; \
- } else { \
- /* m_hi <= s_hi */ \
- d_hi = 0; \
- d_lo = 0; \
- } \
- } else { \
- /* m_lo >= s_lo */ \
- if (m_hi < s_hi) { \
- d_hi = 0; \
- d_lo = 0; \
- } else { \
- /* m_hi >= s_hi */ \
- d_hi = m_hi - s_hi; \
- d_lo = m_lo - s_lo; \
- } \
- } \
- } while (0)
-
-#define UPDATE_STAT64(s, t) \
- do { \
- DIFF_64(diff.hi, new->s##_hi, pstats->mac_stx[0].t##_hi, \
- diff.lo, new->s##_lo, pstats->mac_stx[0].t##_lo); \
- pstats->mac_stx[0].t##_hi = new->s##_hi; \
- pstats->mac_stx[0].t##_lo = new->s##_lo; \
- ADD_64(pstats->mac_stx[1].t##_hi, diff.hi, \
- pstats->mac_stx[1].t##_lo, diff.lo); \
- } while (0)
-
-#define UPDATE_STAT64_NIG(s, t) \
- do { \
- DIFF_64(diff.hi, new->s##_hi, old->s##_hi, \
- diff.lo, new->s##_lo, old->s##_lo); \
- ADD_64(estats->t##_hi, diff.hi, \
- estats->t##_lo, diff.lo); \
- } while (0)
-
-/* sum[hi:lo] += add */
-#define ADD_EXTEND_64(s_hi, s_lo, a) \
- do { \
- s_lo += a; \
- s_hi += (s_lo < a) ? 1 : 0; \
- } while (0)
-
-#define UPDATE_EXTEND_STAT(s) \
- do { \
- ADD_EXTEND_64(pstats->mac_stx[1].s##_hi, \
- pstats->mac_stx[1].s##_lo, \
- new->s); \
- } while (0)
-
-#define UPDATE_EXTEND_TSTAT(s, t) \
- do { \
- diff = le32_to_cpu(tclient->s) - le32_to_cpu(old_tclient->s); \
- old_tclient->s = tclient->s; \
- ADD_EXTEND_64(qstats->t##_hi, qstats->t##_lo, diff); \
- } while (0)
-
-#define UPDATE_EXTEND_USTAT(s, t) \
- do { \
- diff = le32_to_cpu(uclient->s) - le32_to_cpu(old_uclient->s); \
- old_uclient->s = uclient->s; \
- ADD_EXTEND_64(qstats->t##_hi, qstats->t##_lo, diff); \
- } while (0)
-
-#define UPDATE_EXTEND_XSTAT(s, t) \
- do { \
- diff = le32_to_cpu(xclient->s) - le32_to_cpu(old_xclient->s); \
- old_xclient->s = xclient->s; \
- ADD_EXTEND_64(qstats->t##_hi, qstats->t##_lo, diff); \
- } while (0)
-
-/* minuend -= subtrahend */
-#define SUB_64(m_hi, s_hi, m_lo, s_lo) \
- do { \
- DIFF_64(m_hi, m_hi, s_hi, m_lo, m_lo, s_lo); \
- } while (0)
-
-/* minuend[hi:lo] -= subtrahend */
-#define SUB_EXTEND_64(m_hi, m_lo, s) \
- do { \
- SUB_64(m_hi, 0, m_lo, s); \
- } while (0)
-
-#define SUB_EXTEND_USTAT(s, t) \
- do { \
- diff = le32_to_cpu(uclient->s) - le32_to_cpu(old_uclient->s); \
- SUB_EXTEND_64(qstats->t##_hi, qstats->t##_lo, diff); \
- } while (0)
-
/*
* General service functions
*/
@@ -149,12 +40,16 @@
* Init service functions
*/
-
+/* Post the next statistics ramrod. Protect it with the spin in
+ * order to ensure the strict order between statistics ramrods
+ * (each ramrod has a sequence number passed in a
+ * bp->fw_stats_req->hdr.drv_stats_counter and ramrods must be
+ * sent in order).
+ */
static void bnx2x_storm_stats_post(struct bnx2x *bp)
{
if (!bp->stats_pending) {
- struct common_query_ramrod_data ramrod_data = {0};
- int i, rc;
+ int rc;
spin_lock_bh(&bp->stats_lock);
@@ -163,14 +58,19 @@
return;
}
- ramrod_data.drv_counter = bp->stats_counter++;
- ramrod_data.collect_port = bp->port.pmf ? 1 : 0;
- for_each_eth_queue(bp, i)
- ramrod_data.ctr_id_vector |= (1 << bp->fp[i].cl_id);
+ bp->fw_stats_req->hdr.drv_stats_counter =
+ cpu_to_le16(bp->stats_counter++);
+ DP(NETIF_MSG_TIMER, "Sending statistics ramrod %d\n",
+ bp->fw_stats_req->hdr.drv_stats_counter);
+
+
+
+ /* send FW stats ramrod */
rc = bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_STAT_QUERY, 0,
- ((u32 *)&ramrod_data)[1],
- ((u32 *)&ramrod_data)[0], 1);
+ U64_HI(bp->fw_stats_req_mapping),
+ U64_LO(bp->fw_stats_req_mapping),
+ NONE_CONNECTION_TYPE);
if (rc == 0)
bp->stats_pending = 1;
@@ -230,7 +130,7 @@
break;
}
cnt--;
- msleep(1);
+ usleep_range(1000, 1000);
}
return 1;
}
@@ -338,69 +238,8 @@
opcode = bnx2x_dmae_opcode(bp, DMAE_SRC_GRC, DMAE_DST_PCI,
true, DMAE_COMP_GRC);
- if (bp->link_vars.mac_type == MAC_TYPE_BMAC) {
-
- mac_addr = (port ? NIG_REG_INGRESS_BMAC1_MEM :
- NIG_REG_INGRESS_BMAC0_MEM);
-
- /* BIGMAC_REGISTER_TX_STAT_GTPKT ..
- BIGMAC_REGISTER_TX_STAT_GTBYT */
- dmae = bnx2x_sp(bp, dmae[bp->executer_idx++]);
- dmae->opcode = opcode;
- if (CHIP_IS_E1x(bp)) {
- dmae->src_addr_lo = (mac_addr +
- BIGMAC_REGISTER_TX_STAT_GTPKT) >> 2;
- dmae->len = (8 + BIGMAC_REGISTER_TX_STAT_GTBYT -
- BIGMAC_REGISTER_TX_STAT_GTPKT) >> 2;
- } else {
- dmae->src_addr_lo = (mac_addr +
- BIGMAC2_REGISTER_TX_STAT_GTPOK) >> 2;
- dmae->len = (8 + BIGMAC2_REGISTER_TX_STAT_GTBYT -
- BIGMAC2_REGISTER_TX_STAT_GTPOK) >> 2;
- }
-
- dmae->src_addr_hi = 0;
- dmae->dst_addr_lo = U64_LO(bnx2x_sp_mapping(bp, mac_stats));
- dmae->dst_addr_hi = U64_HI(bnx2x_sp_mapping(bp, mac_stats));
- dmae->comp_addr_lo = dmae_reg_go_c[loader_idx] >> 2;
- dmae->comp_addr_hi = 0;
- dmae->comp_val = 1;
-
- /* BIGMAC_REGISTER_RX_STAT_GR64 ..
- BIGMAC_REGISTER_RX_STAT_GRIPJ */
- dmae = bnx2x_sp(bp, dmae[bp->executer_idx++]);
- dmae->opcode = opcode;
- dmae->src_addr_hi = 0;
- if (CHIP_IS_E1x(bp)) {
- dmae->src_addr_lo = (mac_addr +
- BIGMAC_REGISTER_RX_STAT_GR64) >> 2;
- dmae->dst_addr_lo =
- U64_LO(bnx2x_sp_mapping(bp, mac_stats) +
- offsetof(struct bmac1_stats, rx_stat_gr64_lo));
- dmae->dst_addr_hi =
- U64_HI(bnx2x_sp_mapping(bp, mac_stats) +
- offsetof(struct bmac1_stats, rx_stat_gr64_lo));
- dmae->len = (8 + BIGMAC_REGISTER_RX_STAT_GRIPJ -
- BIGMAC_REGISTER_RX_STAT_GR64) >> 2;
- } else {
- dmae->src_addr_lo =
- (mac_addr + BIGMAC2_REGISTER_RX_STAT_GR64) >> 2;
- dmae->dst_addr_lo =
- U64_LO(bnx2x_sp_mapping(bp, mac_stats) +
- offsetof(struct bmac2_stats, rx_stat_gr64_lo));
- dmae->dst_addr_hi =
- U64_HI(bnx2x_sp_mapping(bp, mac_stats) +
- offsetof(struct bmac2_stats, rx_stat_gr64_lo));
- dmae->len = (8 + BIGMAC2_REGISTER_RX_STAT_GRIPJ -
- BIGMAC2_REGISTER_RX_STAT_GR64) >> 2;
- }
-
- dmae->comp_addr_lo = dmae_reg_go_c[loader_idx] >> 2;
- dmae->comp_addr_hi = 0;
- dmae->comp_val = 1;
-
- } else if (bp->link_vars.mac_type == MAC_TYPE_EMAC) {
-
+ /* EMAC is special */
+ if (bp->link_vars.mac_type == MAC_TYPE_EMAC) {
mac_addr = (port ? GRCBASE_EMAC1 : GRCBASE_EMAC0);
/* EMAC_REG_EMAC_RX_STAT_AC (EMAC_REG_EMAC_RX_STAT_AC_COUNT)*/
@@ -445,46 +284,122 @@
dmae->comp_addr_lo = dmae_reg_go_c[loader_idx] >> 2;
dmae->comp_addr_hi = 0;
dmae->comp_val = 1;
+ } else {
+ u32 tx_src_addr_lo, rx_src_addr_lo;
+ u16 rx_len, tx_len;
+
+ /* configure the params according to MAC type */
+ switch (bp->link_vars.mac_type) {
+ case MAC_TYPE_BMAC:
+ mac_addr = (port ? NIG_REG_INGRESS_BMAC1_MEM :
+ NIG_REG_INGRESS_BMAC0_MEM);
+
+ /* BIGMAC_REGISTER_TX_STAT_GTPKT ..
+ BIGMAC_REGISTER_TX_STAT_GTBYT */
+ if (CHIP_IS_E1x(bp)) {
+ tx_src_addr_lo = (mac_addr +
+ BIGMAC_REGISTER_TX_STAT_GTPKT) >> 2;
+ tx_len = (8 + BIGMAC_REGISTER_TX_STAT_GTBYT -
+ BIGMAC_REGISTER_TX_STAT_GTPKT) >> 2;
+ rx_src_addr_lo = (mac_addr +
+ BIGMAC_REGISTER_RX_STAT_GR64) >> 2;
+ rx_len = (8 + BIGMAC_REGISTER_RX_STAT_GRIPJ -
+ BIGMAC_REGISTER_RX_STAT_GR64) >> 2;
+ } else {
+ tx_src_addr_lo = (mac_addr +
+ BIGMAC2_REGISTER_TX_STAT_GTPOK) >> 2;
+ tx_len = (8 + BIGMAC2_REGISTER_TX_STAT_GTBYT -
+ BIGMAC2_REGISTER_TX_STAT_GTPOK) >> 2;
+ rx_src_addr_lo = (mac_addr +
+ BIGMAC2_REGISTER_RX_STAT_GR64) >> 2;
+ rx_len = (8 + BIGMAC2_REGISTER_RX_STAT_GRIPJ -
+ BIGMAC2_REGISTER_RX_STAT_GR64) >> 2;
+ }
+ break;
+
+ case MAC_TYPE_UMAC: /* handled by MSTAT */
+ case MAC_TYPE_XMAC: /* handled by MSTAT */
+ default:
+ mac_addr = port ? GRCBASE_MSTAT1 : GRCBASE_MSTAT0;
+ tx_src_addr_lo = (mac_addr +
+ MSTAT_REG_TX_STAT_GTXPOK_LO) >> 2;
+ rx_src_addr_lo = (mac_addr +
+ MSTAT_REG_RX_STAT_GR64_LO) >> 2;
+ tx_len = sizeof(bp->slowpath->
+ mac_stats.mstat_stats.stats_tx) >> 2;
+ rx_len = sizeof(bp->slowpath->
+ mac_stats.mstat_stats.stats_rx) >> 2;
+ break;
+ }
+
+ /* TX stats */
+ dmae = bnx2x_sp(bp, dmae[bp->executer_idx++]);
+ dmae->opcode = opcode;
+ dmae->src_addr_lo = tx_src_addr_lo;
+ dmae->src_addr_hi = 0;
+ dmae->len = tx_len;
+ dmae->dst_addr_lo = U64_LO(bnx2x_sp_mapping(bp, mac_stats));
+ dmae->dst_addr_hi = U64_HI(bnx2x_sp_mapping(bp, mac_stats));
+ dmae->comp_addr_lo = dmae_reg_go_c[loader_idx] >> 2;
+ dmae->comp_addr_hi = 0;
+ dmae->comp_val = 1;
+
+ /* RX stats */
+ dmae = bnx2x_sp(bp, dmae[bp->executer_idx++]);
+ dmae->opcode = opcode;
+ dmae->src_addr_hi = 0;
+ dmae->src_addr_lo = rx_src_addr_lo;
+ dmae->dst_addr_lo =
+ U64_LO(bnx2x_sp_mapping(bp, mac_stats) + (tx_len << 2));
+ dmae->dst_addr_hi =
+ U64_HI(bnx2x_sp_mapping(bp, mac_stats) + (tx_len << 2));
+ dmae->len = rx_len;
+ dmae->comp_addr_lo = dmae_reg_go_c[loader_idx] >> 2;
+ dmae->comp_addr_hi = 0;
+ dmae->comp_val = 1;
}
/* NIG */
+ if (!CHIP_IS_E3(bp)) {
+ dmae = bnx2x_sp(bp, dmae[bp->executer_idx++]);
+ dmae->opcode = opcode;
+ dmae->src_addr_lo = (port ? NIG_REG_STAT1_EGRESS_MAC_PKT0 :
+ NIG_REG_STAT0_EGRESS_MAC_PKT0) >> 2;
+ dmae->src_addr_hi = 0;
+ dmae->dst_addr_lo = U64_LO(bnx2x_sp_mapping(bp, nig_stats) +
+ offsetof(struct nig_stats, egress_mac_pkt0_lo));
+ dmae->dst_addr_hi = U64_HI(bnx2x_sp_mapping(bp, nig_stats) +
+ offsetof(struct nig_stats, egress_mac_pkt0_lo));
+ dmae->len = (2*sizeof(u32)) >> 2;
+ dmae->comp_addr_lo = dmae_reg_go_c[loader_idx] >> 2;
+ dmae->comp_addr_hi = 0;
+ dmae->comp_val = 1;
+
+ dmae = bnx2x_sp(bp, dmae[bp->executer_idx++]);
+ dmae->opcode = opcode;
+ dmae->src_addr_lo = (port ? NIG_REG_STAT1_EGRESS_MAC_PKT1 :
+ NIG_REG_STAT0_EGRESS_MAC_PKT1) >> 2;
+ dmae->src_addr_hi = 0;
+ dmae->dst_addr_lo = U64_LO(bnx2x_sp_mapping(bp, nig_stats) +
+ offsetof(struct nig_stats, egress_mac_pkt1_lo));
+ dmae->dst_addr_hi = U64_HI(bnx2x_sp_mapping(bp, nig_stats) +
+ offsetof(struct nig_stats, egress_mac_pkt1_lo));
+ dmae->len = (2*sizeof(u32)) >> 2;
+ dmae->comp_addr_lo = dmae_reg_go_c[loader_idx] >> 2;
+ dmae->comp_addr_hi = 0;
+ dmae->comp_val = 1;
+ }
+
dmae = bnx2x_sp(bp, dmae[bp->executer_idx++]);
- dmae->opcode = opcode;
+ dmae->opcode = bnx2x_dmae_opcode(bp, DMAE_SRC_GRC, DMAE_DST_PCI,
+ true, DMAE_COMP_PCI);
dmae->src_addr_lo = (port ? NIG_REG_STAT1_BRB_DISCARD :
NIG_REG_STAT0_BRB_DISCARD) >> 2;
dmae->src_addr_hi = 0;
dmae->dst_addr_lo = U64_LO(bnx2x_sp_mapping(bp, nig_stats));
dmae->dst_addr_hi = U64_HI(bnx2x_sp_mapping(bp, nig_stats));
dmae->len = (sizeof(struct nig_stats) - 4*sizeof(u32)) >> 2;
- dmae->comp_addr_lo = dmae_reg_go_c[loader_idx] >> 2;
- dmae->comp_addr_hi = 0;
- dmae->comp_val = 1;
- dmae = bnx2x_sp(bp, dmae[bp->executer_idx++]);
- dmae->opcode = opcode;
- dmae->src_addr_lo = (port ? NIG_REG_STAT1_EGRESS_MAC_PKT0 :
- NIG_REG_STAT0_EGRESS_MAC_PKT0) >> 2;
- dmae->src_addr_hi = 0;
- dmae->dst_addr_lo = U64_LO(bnx2x_sp_mapping(bp, nig_stats) +
- offsetof(struct nig_stats, egress_mac_pkt0_lo));
- dmae->dst_addr_hi = U64_HI(bnx2x_sp_mapping(bp, nig_stats) +
- offsetof(struct nig_stats, egress_mac_pkt0_lo));
- dmae->len = (2*sizeof(u32)) >> 2;
- dmae->comp_addr_lo = dmae_reg_go_c[loader_idx] >> 2;
- dmae->comp_addr_hi = 0;
- dmae->comp_val = 1;
-
- dmae = bnx2x_sp(bp, dmae[bp->executer_idx++]);
- dmae->opcode = bnx2x_dmae_opcode(bp, DMAE_SRC_GRC, DMAE_DST_PCI,
- true, DMAE_COMP_PCI);
- dmae->src_addr_lo = (port ? NIG_REG_STAT1_EGRESS_MAC_PKT1 :
- NIG_REG_STAT0_EGRESS_MAC_PKT1) >> 2;
- dmae->src_addr_hi = 0;
- dmae->dst_addr_lo = U64_LO(bnx2x_sp_mapping(bp, nig_stats) +
- offsetof(struct nig_stats, egress_mac_pkt1_lo));
- dmae->dst_addr_hi = U64_HI(bnx2x_sp_mapping(bp, nig_stats) +
- offsetof(struct nig_stats, egress_mac_pkt1_lo));
- dmae->len = (2*sizeof(u32)) >> 2;
dmae->comp_addr_lo = U64_LO(bnx2x_sp_mapping(bp, stats_comp));
dmae->comp_addr_hi = U64_HI(bnx2x_sp_mapping(bp, stats_comp));
dmae->comp_val = DMAE_COMP_VAL;
@@ -566,7 +481,8 @@
UPDATE_STAT64(rx_stat_grjbr, rx_stat_etherstatsjabbers);
UPDATE_STAT64(rx_stat_grxcf, rx_stat_maccontrolframesreceived);
UPDATE_STAT64(rx_stat_grxpf, rx_stat_xoffstateentered);
- UPDATE_STAT64(rx_stat_grxpf, rx_stat_bmac_xpf);
+ UPDATE_STAT64(rx_stat_grxpf, rx_stat_mac_xpf);
+
UPDATE_STAT64(tx_stat_gtxpf, tx_stat_outxoffsent);
UPDATE_STAT64(tx_stat_gtxpf, tx_stat_flowcontroldone);
UPDATE_STAT64(tx_stat_gt64, tx_stat_etherstatspkts64octets);
@@ -580,13 +496,13 @@
tx_stat_etherstatspkts512octetsto1023octets);
UPDATE_STAT64(tx_stat_gt1518,
tx_stat_etherstatspkts1024octetsto1522octets);
- UPDATE_STAT64(tx_stat_gt2047, tx_stat_bmac_2047);
- UPDATE_STAT64(tx_stat_gt4095, tx_stat_bmac_4095);
- UPDATE_STAT64(tx_stat_gt9216, tx_stat_bmac_9216);
- UPDATE_STAT64(tx_stat_gt16383, tx_stat_bmac_16383);
+ UPDATE_STAT64(tx_stat_gt2047, tx_stat_mac_2047);
+ UPDATE_STAT64(tx_stat_gt4095, tx_stat_mac_4095);
+ UPDATE_STAT64(tx_stat_gt9216, tx_stat_mac_9216);
+ UPDATE_STAT64(tx_stat_gt16383, tx_stat_mac_16383);
UPDATE_STAT64(tx_stat_gterr,
tx_stat_dot3statsinternalmactransmiterrors);
- UPDATE_STAT64(tx_stat_gtufl, tx_stat_bmac_ufl);
+ UPDATE_STAT64(tx_stat_gtufl, tx_stat_mac_ufl);
} else {
struct bmac2_stats *new = bnx2x_sp(bp, mac_stats.bmac2_stats);
@@ -600,7 +516,7 @@
UPDATE_STAT64(rx_stat_grjbr, rx_stat_etherstatsjabbers);
UPDATE_STAT64(rx_stat_grxcf, rx_stat_maccontrolframesreceived);
UPDATE_STAT64(rx_stat_grxpf, rx_stat_xoffstateentered);
- UPDATE_STAT64(rx_stat_grxpf, rx_stat_bmac_xpf);
+ UPDATE_STAT64(rx_stat_grxpf, rx_stat_mac_xpf);
UPDATE_STAT64(tx_stat_gtxpf, tx_stat_outxoffsent);
UPDATE_STAT64(tx_stat_gtxpf, tx_stat_flowcontroldone);
UPDATE_STAT64(tx_stat_gt64, tx_stat_etherstatspkts64octets);
@@ -614,19 +530,96 @@
tx_stat_etherstatspkts512octetsto1023octets);
UPDATE_STAT64(tx_stat_gt1518,
tx_stat_etherstatspkts1024octetsto1522octets);
- UPDATE_STAT64(tx_stat_gt2047, tx_stat_bmac_2047);
- UPDATE_STAT64(tx_stat_gt4095, tx_stat_bmac_4095);
- UPDATE_STAT64(tx_stat_gt9216, tx_stat_bmac_9216);
- UPDATE_STAT64(tx_stat_gt16383, tx_stat_bmac_16383);
+ UPDATE_STAT64(tx_stat_gt2047, tx_stat_mac_2047);
+ UPDATE_STAT64(tx_stat_gt4095, tx_stat_mac_4095);
+ UPDATE_STAT64(tx_stat_gt9216, tx_stat_mac_9216);
+ UPDATE_STAT64(tx_stat_gt16383, tx_stat_mac_16383);
UPDATE_STAT64(tx_stat_gterr,
tx_stat_dot3statsinternalmactransmiterrors);
- UPDATE_STAT64(tx_stat_gtufl, tx_stat_bmac_ufl);
+ UPDATE_STAT64(tx_stat_gtufl, tx_stat_mac_ufl);
}
estats->pause_frames_received_hi =
- pstats->mac_stx[1].rx_stat_bmac_xpf_hi;
+ pstats->mac_stx[1].rx_stat_mac_xpf_hi;
estats->pause_frames_received_lo =
- pstats->mac_stx[1].rx_stat_bmac_xpf_lo;
+ pstats->mac_stx[1].rx_stat_mac_xpf_lo;
+
+ estats->pause_frames_sent_hi =
+ pstats->mac_stx[1].tx_stat_outxoffsent_hi;
+ estats->pause_frames_sent_lo =
+ pstats->mac_stx[1].tx_stat_outxoffsent_lo;
+}
+
+static void bnx2x_mstat_stats_update(struct bnx2x *bp)
+{
+ struct host_port_stats *pstats = bnx2x_sp(bp, port_stats);
+ struct bnx2x_eth_stats *estats = &bp->eth_stats;
+
+ struct mstat_stats *new = bnx2x_sp(bp, mac_stats.mstat_stats);
+
+ ADD_STAT64(stats_rx.rx_grerb, rx_stat_ifhcinbadoctets);
+ ADD_STAT64(stats_rx.rx_grfcs, rx_stat_dot3statsfcserrors);
+ ADD_STAT64(stats_rx.rx_grund, rx_stat_etherstatsundersizepkts);
+ ADD_STAT64(stats_rx.rx_grovr, rx_stat_dot3statsframestoolong);
+ ADD_STAT64(stats_rx.rx_grfrg, rx_stat_etherstatsfragments);
+ ADD_STAT64(stats_rx.rx_grxcf, rx_stat_maccontrolframesreceived);
+ ADD_STAT64(stats_rx.rx_grxpf, rx_stat_xoffstateentered);
+ ADD_STAT64(stats_rx.rx_grxpf, rx_stat_mac_xpf);
+ ADD_STAT64(stats_tx.tx_gtxpf, tx_stat_outxoffsent);
+ ADD_STAT64(stats_tx.tx_gtxpf, tx_stat_flowcontroldone);
+
+
+ ADD_STAT64(stats_tx.tx_gt64, tx_stat_etherstatspkts64octets);
+ ADD_STAT64(stats_tx.tx_gt127,
+ tx_stat_etherstatspkts65octetsto127octets);
+ ADD_STAT64(stats_tx.tx_gt255,
+ tx_stat_etherstatspkts128octetsto255octets);
+ ADD_STAT64(stats_tx.tx_gt511,
+ tx_stat_etherstatspkts256octetsto511octets);
+ ADD_STAT64(stats_tx.tx_gt1023,
+ tx_stat_etherstatspkts512octetsto1023octets);
+ ADD_STAT64(stats_tx.tx_gt1518,
+ tx_stat_etherstatspkts1024octetsto1522octets);
+ ADD_STAT64(stats_tx.tx_gt2047, tx_stat_mac_2047);
+
+ ADD_STAT64(stats_tx.tx_gt4095, tx_stat_mac_4095);
+ ADD_STAT64(stats_tx.tx_gt9216, tx_stat_mac_9216);
+ ADD_STAT64(stats_tx.tx_gt16383, tx_stat_mac_16383);
+
+ ADD_STAT64(stats_tx.tx_gterr,
+ tx_stat_dot3statsinternalmactransmiterrors);
+ ADD_STAT64(stats_tx.tx_gtufl, tx_stat_mac_ufl);
+
+ ADD_64(estats->etherstatspkts1024octetsto1522octets_hi,
+ new->stats_tx.tx_gt1518_hi,
+ estats->etherstatspkts1024octetsto1522octets_lo,
+ new->stats_tx.tx_gt1518_lo);
+
+ ADD_64(estats->etherstatspktsover1522octets_hi,
+ new->stats_tx.tx_gt2047_hi,
+ estats->etherstatspktsover1522octets_lo,
+ new->stats_tx.tx_gt2047_lo);
+
+ ADD_64(estats->etherstatspktsover1522octets_hi,
+ new->stats_tx.tx_gt4095_hi,
+ estats->etherstatspktsover1522octets_lo,
+ new->stats_tx.tx_gt4095_lo);
+
+ ADD_64(estats->etherstatspktsover1522octets_hi,
+ new->stats_tx.tx_gt9216_hi,
+ estats->etherstatspktsover1522octets_lo,
+ new->stats_tx.tx_gt9216_lo);
+
+
+ ADD_64(estats->etherstatspktsover1522octets_hi,
+ new->stats_tx.tx_gt16383_hi,
+ estats->etherstatspktsover1522octets_lo,
+ new->stats_tx.tx_gt16383_lo);
+
+ estats->pause_frames_received_hi =
+ pstats->mac_stx[1].rx_stat_mac_xpf_hi;
+ estats->pause_frames_received_lo =
+ pstats->mac_stx[1].rx_stat_mac_xpf_lo;
estats->pause_frames_sent_hi =
pstats->mac_stx[1].tx_stat_outxoffsent_hi;
@@ -702,15 +695,26 @@
u32 hi;
} diff;
- if (bp->link_vars.mac_type == MAC_TYPE_BMAC)
+ switch (bp->link_vars.mac_type) {
+ case MAC_TYPE_BMAC:
bnx2x_bmac_stats_update(bp);
+ break;
- else if (bp->link_vars.mac_type == MAC_TYPE_EMAC)
+ case MAC_TYPE_EMAC:
bnx2x_emac_stats_update(bp);
+ break;
- else { /* unreached */
+ case MAC_TYPE_UMAC:
+ case MAC_TYPE_XMAC:
+ bnx2x_mstat_stats_update(bp);
+ break;
+
+ case MAC_TYPE_NONE: /* unreached */
BNX2X_ERR("stats updated by DMAE but no MAC active\n");
return -1;
+
+ default: /* unreached */
+ BNX2X_ERR("Unknown MAC type\n");
}
ADD_EXTEND_64(pstats->brb_drop_hi, pstats->brb_drop_lo,
@@ -718,9 +722,12 @@
ADD_EXTEND_64(estats->brb_truncate_hi, estats->brb_truncate_lo,
new->brb_truncate - old->brb_truncate);
- UPDATE_STAT64_NIG(egress_mac_pkt0,
+ if (!CHIP_IS_E3(bp)) {
+ UPDATE_STAT64_NIG(egress_mac_pkt0,
etherstatspkts1024octetsto1522octets);
- UPDATE_STAT64_NIG(egress_mac_pkt1, etherstatspktsover1522octets);
+ UPDATE_STAT64_NIG(egress_mac_pkt1,
+ etherstatspktsover1522octets);
+ }
memcpy(old, new, sizeof(struct nig_stats));
@@ -746,11 +753,13 @@
static int bnx2x_storm_stats_update(struct bnx2x *bp)
{
- struct eth_stats_query *stats = bnx2x_sp(bp, fw_stats);
struct tstorm_per_port_stats *tport =
- &stats->tstorm_common.port_statistics;
+ &bp->fw_stats_data->port.tstorm_port_statistics;
+ struct tstorm_per_pf_stats *tfunc =
+ &bp->fw_stats_data->pf.tstorm_pf_statistics;
struct host_func_stats *fstats = bnx2x_sp(bp, func_stats);
struct bnx2x_eth_stats *estats = &bp->eth_stats;
+ struct stats_counter *counters = &bp->fw_stats_data->storm_counters;
int i;
u16 cur_stats_counter;
@@ -761,6 +770,35 @@
cur_stats_counter = bp->stats_counter - 1;
spin_unlock_bh(&bp->stats_lock);
+ /* are storm stats valid? */
+ if (le16_to_cpu(counters->xstats_counter) != cur_stats_counter) {
+ DP(BNX2X_MSG_STATS, "stats not updated by xstorm"
+ " xstorm counter (0x%x) != stats_counter (0x%x)\n",
+ le16_to_cpu(counters->xstats_counter), bp->stats_counter);
+ return -EAGAIN;
+ }
+
+ if (le16_to_cpu(counters->ustats_counter) != cur_stats_counter) {
+ DP(BNX2X_MSG_STATS, "stats not updated by ustorm"
+ " ustorm counter (0x%x) != stats_counter (0x%x)\n",
+ le16_to_cpu(counters->ustats_counter), bp->stats_counter);
+ return -EAGAIN;
+ }
+
+ if (le16_to_cpu(counters->cstats_counter) != cur_stats_counter) {
+ DP(BNX2X_MSG_STATS, "stats not updated by cstorm"
+ " cstorm counter (0x%x) != stats_counter (0x%x)\n",
+ le16_to_cpu(counters->cstats_counter), bp->stats_counter);
+ return -EAGAIN;
+ }
+
+ if (le16_to_cpu(counters->tstats_counter) != cur_stats_counter) {
+ DP(BNX2X_MSG_STATS, "stats not updated by tstorm"
+ " tstorm counter (0x%x) != stats_counter (0x%x)\n",
+ le16_to_cpu(counters->tstats_counter), bp->stats_counter);
+ return -EAGAIN;
+ }
+
memcpy(&(fstats->total_bytes_received_hi),
&(bnx2x_sp(bp, func_stats_base)->total_bytes_received_hi),
sizeof(struct host_func_stats) - 2*sizeof(u32));
@@ -770,94 +808,84 @@
estats->etherstatsoverrsizepkts_lo = 0;
estats->no_buff_discard_hi = 0;
estats->no_buff_discard_lo = 0;
+ estats->total_tpa_aggregations_hi = 0;
+ estats->total_tpa_aggregations_lo = 0;
+ estats->total_tpa_aggregated_frames_hi = 0;
+ estats->total_tpa_aggregated_frames_lo = 0;
+ estats->total_tpa_bytes_hi = 0;
+ estats->total_tpa_bytes_lo = 0;
for_each_eth_queue(bp, i) {
struct bnx2x_fastpath *fp = &bp->fp[i];
- int cl_id = fp->cl_id;
- struct tstorm_per_client_stats *tclient =
- &stats->tstorm_common.client_statistics[cl_id];
- struct tstorm_per_client_stats *old_tclient = &fp->old_tclient;
- struct ustorm_per_client_stats *uclient =
- &stats->ustorm_common.client_statistics[cl_id];
- struct ustorm_per_client_stats *old_uclient = &fp->old_uclient;
- struct xstorm_per_client_stats *xclient =
- &stats->xstorm_common.client_statistics[cl_id];
- struct xstorm_per_client_stats *old_xclient = &fp->old_xclient;
+ struct tstorm_per_queue_stats *tclient =
+ &bp->fw_stats_data->queue_stats[i].
+ tstorm_queue_statistics;
+ struct tstorm_per_queue_stats *old_tclient = &fp->old_tclient;
+ struct ustorm_per_queue_stats *uclient =
+ &bp->fw_stats_data->queue_stats[i].
+ ustorm_queue_statistics;
+ struct ustorm_per_queue_stats *old_uclient = &fp->old_uclient;
+ struct xstorm_per_queue_stats *xclient =
+ &bp->fw_stats_data->queue_stats[i].
+ xstorm_queue_statistics;
+ struct xstorm_per_queue_stats *old_xclient = &fp->old_xclient;
struct bnx2x_eth_q_stats *qstats = &fp->eth_q_stats;
u32 diff;
- /* are storm stats valid? */
- if (le16_to_cpu(xclient->stats_counter) != cur_stats_counter) {
- DP(BNX2X_MSG_STATS, "[%d] stats not updated by xstorm"
- " xstorm counter (0x%x) != stats_counter (0x%x)\n",
- i, xclient->stats_counter, cur_stats_counter + 1);
- return -1;
- }
- if (le16_to_cpu(tclient->stats_counter) != cur_stats_counter) {
- DP(BNX2X_MSG_STATS, "[%d] stats not updated by tstorm"
- " tstorm counter (0x%x) != stats_counter (0x%x)\n",
- i, tclient->stats_counter, cur_stats_counter + 1);
- return -2;
- }
- if (le16_to_cpu(uclient->stats_counter) != cur_stats_counter) {
- DP(BNX2X_MSG_STATS, "[%d] stats not updated by ustorm"
- " ustorm counter (0x%x) != stats_counter (0x%x)\n",
- i, uclient->stats_counter, cur_stats_counter + 1);
- return -4;
- }
+ DP(BNX2X_MSG_STATS, "queue[%d]: ucast_sent 0x%x, "
+ "bcast_sent 0x%x mcast_sent 0x%x\n",
+ i, xclient->ucast_pkts_sent,
+ xclient->bcast_pkts_sent, xclient->mcast_pkts_sent);
+ DP(BNX2X_MSG_STATS, "---------------\n");
+
+ qstats->total_broadcast_bytes_received_hi =
+ le32_to_cpu(tclient->rcv_bcast_bytes.hi);
+ qstats->total_broadcast_bytes_received_lo =
+ le32_to_cpu(tclient->rcv_bcast_bytes.lo);
+
+ qstats->total_multicast_bytes_received_hi =
+ le32_to_cpu(tclient->rcv_mcast_bytes.hi);
+ qstats->total_multicast_bytes_received_lo =
+ le32_to_cpu(tclient->rcv_mcast_bytes.lo);
+
+ qstats->total_unicast_bytes_received_hi =
+ le32_to_cpu(tclient->rcv_ucast_bytes.hi);
+ qstats->total_unicast_bytes_received_lo =
+ le32_to_cpu(tclient->rcv_ucast_bytes.lo);
+
+ /*
+ * sum to total_bytes_received all
+ * unicast/multicast/broadcast
+ */
qstats->total_bytes_received_hi =
- le32_to_cpu(tclient->rcv_broadcast_bytes.hi);
+ qstats->total_broadcast_bytes_received_hi;
qstats->total_bytes_received_lo =
- le32_to_cpu(tclient->rcv_broadcast_bytes.lo);
+ qstats->total_broadcast_bytes_received_lo;
ADD_64(qstats->total_bytes_received_hi,
- le32_to_cpu(tclient->rcv_multicast_bytes.hi),
+ qstats->total_multicast_bytes_received_hi,
qstats->total_bytes_received_lo,
- le32_to_cpu(tclient->rcv_multicast_bytes.lo));
+ qstats->total_multicast_bytes_received_lo);
ADD_64(qstats->total_bytes_received_hi,
- le32_to_cpu(tclient->rcv_unicast_bytes.hi),
+ qstats->total_unicast_bytes_received_hi,
qstats->total_bytes_received_lo,
- le32_to_cpu(tclient->rcv_unicast_bytes.lo));
-
- SUB_64(qstats->total_bytes_received_hi,
- le32_to_cpu(uclient->bcast_no_buff_bytes.hi),
- qstats->total_bytes_received_lo,
- le32_to_cpu(uclient->bcast_no_buff_bytes.lo));
-
- SUB_64(qstats->total_bytes_received_hi,
- le32_to_cpu(uclient->mcast_no_buff_bytes.hi),
- qstats->total_bytes_received_lo,
- le32_to_cpu(uclient->mcast_no_buff_bytes.lo));
-
- SUB_64(qstats->total_bytes_received_hi,
- le32_to_cpu(uclient->ucast_no_buff_bytes.hi),
- qstats->total_bytes_received_lo,
- le32_to_cpu(uclient->ucast_no_buff_bytes.lo));
+ qstats->total_unicast_bytes_received_lo);
qstats->valid_bytes_received_hi =
qstats->total_bytes_received_hi;
qstats->valid_bytes_received_lo =
qstats->total_bytes_received_lo;
- qstats->error_bytes_received_hi =
- le32_to_cpu(tclient->rcv_error_bytes.hi);
- qstats->error_bytes_received_lo =
- le32_to_cpu(tclient->rcv_error_bytes.lo);
- ADD_64(qstats->total_bytes_received_hi,
- qstats->error_bytes_received_hi,
- qstats->total_bytes_received_lo,
- qstats->error_bytes_received_lo);
-
- UPDATE_EXTEND_TSTAT(rcv_unicast_pkts,
+ UPDATE_EXTEND_TSTAT(rcv_ucast_pkts,
total_unicast_packets_received);
- UPDATE_EXTEND_TSTAT(rcv_multicast_pkts,
+ UPDATE_EXTEND_TSTAT(rcv_mcast_pkts,
total_multicast_packets_received);
- UPDATE_EXTEND_TSTAT(rcv_broadcast_pkts,
+ UPDATE_EXTEND_TSTAT(rcv_bcast_pkts,
total_broadcast_packets_received);
- UPDATE_EXTEND_TSTAT(packets_too_big_discard,
+ UPDATE_EXTEND_TSTAT(pkts_too_big_discard,
etherstatsoverrsizepkts);
UPDATE_EXTEND_TSTAT(no_buff_discard, no_buff_discard);
@@ -871,30 +899,78 @@
UPDATE_EXTEND_USTAT(mcast_no_buff_pkts, no_buff_discard);
UPDATE_EXTEND_USTAT(bcast_no_buff_pkts, no_buff_discard);
+ qstats->total_broadcast_bytes_transmitted_hi =
+ le32_to_cpu(xclient->bcast_bytes_sent.hi);
+ qstats->total_broadcast_bytes_transmitted_lo =
+ le32_to_cpu(xclient->bcast_bytes_sent.lo);
+
+ qstats->total_multicast_bytes_transmitted_hi =
+ le32_to_cpu(xclient->mcast_bytes_sent.hi);
+ qstats->total_multicast_bytes_transmitted_lo =
+ le32_to_cpu(xclient->mcast_bytes_sent.lo);
+
+ qstats->total_unicast_bytes_transmitted_hi =
+ le32_to_cpu(xclient->ucast_bytes_sent.hi);
+ qstats->total_unicast_bytes_transmitted_lo =
+ le32_to_cpu(xclient->ucast_bytes_sent.lo);
+ /*
+ * sum to total_bytes_transmitted all
+ * unicast/multicast/broadcast
+ */
qstats->total_bytes_transmitted_hi =
- le32_to_cpu(xclient->unicast_bytes_sent.hi);
+ qstats->total_unicast_bytes_transmitted_hi;
qstats->total_bytes_transmitted_lo =
- le32_to_cpu(xclient->unicast_bytes_sent.lo);
+ qstats->total_unicast_bytes_transmitted_lo;
ADD_64(qstats->total_bytes_transmitted_hi,
- le32_to_cpu(xclient->multicast_bytes_sent.hi),
+ qstats->total_broadcast_bytes_transmitted_hi,
qstats->total_bytes_transmitted_lo,
- le32_to_cpu(xclient->multicast_bytes_sent.lo));
+ qstats->total_broadcast_bytes_transmitted_lo);
ADD_64(qstats->total_bytes_transmitted_hi,
- le32_to_cpu(xclient->broadcast_bytes_sent.hi),
+ qstats->total_multicast_bytes_transmitted_hi,
qstats->total_bytes_transmitted_lo,
- le32_to_cpu(xclient->broadcast_bytes_sent.lo));
+ qstats->total_multicast_bytes_transmitted_lo);
- UPDATE_EXTEND_XSTAT(unicast_pkts_sent,
+ UPDATE_EXTEND_XSTAT(ucast_pkts_sent,
total_unicast_packets_transmitted);
- UPDATE_EXTEND_XSTAT(multicast_pkts_sent,
+ UPDATE_EXTEND_XSTAT(mcast_pkts_sent,
total_multicast_packets_transmitted);
- UPDATE_EXTEND_XSTAT(broadcast_pkts_sent,
+ UPDATE_EXTEND_XSTAT(bcast_pkts_sent,
total_broadcast_packets_transmitted);
- old_tclient->checksum_discard = tclient->checksum_discard;
- old_tclient->ttl0_discard = tclient->ttl0_discard;
+ UPDATE_EXTEND_TSTAT(checksum_discard,
+ total_packets_received_checksum_discarded);
+ UPDATE_EXTEND_TSTAT(ttl0_discard,
+ total_packets_received_ttl0_discarded);
+
+ UPDATE_EXTEND_XSTAT(error_drop_pkts,
+ total_transmitted_dropped_packets_error);
+
+ /* TPA aggregations completed */
+ UPDATE_EXTEND_USTAT(coalesced_events, total_tpa_aggregations);
+ /* Number of network frames aggregated by TPA */
+ UPDATE_EXTEND_USTAT(coalesced_pkts,
+ total_tpa_aggregated_frames);
+ /* Total number of bytes in completed TPA aggregations */
+ qstats->total_tpa_bytes_lo =
+ le32_to_cpu(uclient->coalesced_bytes.lo);
+ qstats->total_tpa_bytes_hi =
+ le32_to_cpu(uclient->coalesced_bytes.hi);
+
+ /* TPA stats per-function */
+ ADD_64(estats->total_tpa_aggregations_hi,
+ qstats->total_tpa_aggregations_hi,
+ estats->total_tpa_aggregations_lo,
+ qstats->total_tpa_aggregations_lo);
+ ADD_64(estats->total_tpa_aggregated_frames_hi,
+ qstats->total_tpa_aggregated_frames_hi,
+ estats->total_tpa_aggregated_frames_lo,
+ qstats->total_tpa_aggregated_frames_lo);
+ ADD_64(estats->total_tpa_bytes_hi,
+ qstats->total_tpa_bytes_hi,
+ estats->total_tpa_bytes_lo,
+ qstats->total_tpa_bytes_lo);
ADD_64(fstats->total_bytes_received_hi,
qstats->total_bytes_received_hi,
@@ -933,10 +1009,6 @@
fstats->valid_bytes_received_lo,
qstats->valid_bytes_received_lo);
- ADD_64(estats->error_bytes_received_hi,
- qstats->error_bytes_received_hi,
- estats->error_bytes_received_lo,
- qstats->error_bytes_received_lo);
ADD_64(estats->etherstatsoverrsizepkts_hi,
qstats->etherstatsoverrsizepkts_hi,
estats->etherstatsoverrsizepkts_lo,
@@ -950,9 +1022,19 @@
fstats->total_bytes_received_lo,
estats->rx_stat_ifhcinbadoctets_lo);
+ ADD_64(fstats->total_bytes_received_hi,
+ tfunc->rcv_error_bytes.hi,
+ fstats->total_bytes_received_lo,
+ tfunc->rcv_error_bytes.lo);
+
memcpy(estats, &(fstats->total_bytes_received_hi),
sizeof(struct host_func_stats) - 2*sizeof(u32));
+ ADD_64(estats->error_bytes_received_hi,
+ tfunc->rcv_error_bytes.hi,
+ estats->error_bytes_received_lo,
+ tfunc->rcv_error_bytes.lo);
+
ADD_64(estats->etherstatsoverrsizepkts_hi,
estats->rx_stat_dot3statsframestoolong_hi,
estats->etherstatsoverrsizepkts_lo,
@@ -965,8 +1047,8 @@
if (bp->port.pmf) {
estats->mac_filter_discard =
le32_to_cpu(tport->mac_filter_discard);
- estats->xxoverflow_discard =
- le32_to_cpu(tport->xxoverflow_discard);
+ estats->mf_tag_discard =
+ le32_to_cpu(tport->mf_tag_discard);
estats->brb_truncate_discard =
le32_to_cpu(tport->brb_truncate_discard);
estats->mac_discard = le32_to_cpu(tport->mac_discard);
@@ -1023,7 +1105,7 @@
nstats->rx_frame_errors =
bnx2x_hilo(&estats->rx_stat_dot3statsalignmenterrors_hi);
nstats->rx_fifo_errors = bnx2x_hilo(&estats->no_buff_discard_hi);
- nstats->rx_missed_errors = estats->xxoverflow_discard;
+ nstats->rx_missed_errors = 0;
nstats->rx_errors = nstats->rx_length_errors +
nstats->rx_over_errors +
@@ -1065,10 +1147,27 @@
}
}
+static bool bnx2x_edebug_stats_stopped(struct bnx2x *bp)
+{
+ u32 val;
+
+ if (SHMEM2_HAS(bp, edebug_driver_if[1])) {
+ val = SHMEM2_RD(bp, edebug_driver_if[1]);
+
+ if (val == EDEBUG_DRIVER_IF_OP_CODE_DISABLE_STAT)
+ return true;
+ }
+
+ return false;
+}
+
static void bnx2x_stats_update(struct bnx2x *bp)
{
u32 *stats_comp = bnx2x_sp(bp, stats_comp);
+ if (bnx2x_edebug_stats_stopped(bp))
+ return;
+
if (*stats_comp != DMAE_COMP_VAL)
return;
@@ -1088,8 +1187,7 @@
struct bnx2x_eth_stats *estats = &bp->eth_stats;
int i;
- printk(KERN_DEBUG "%s: brb drops %u brb truncate %u\n",
- bp->dev->name,
+ netdev_dbg(bp->dev, "brb drops %u brb truncate %u\n",
estats->brb_drop_lo, estats->brb_truncate_lo);
for_each_eth_queue(bp, i) {
@@ -1149,6 +1247,7 @@
else
dmae->opcode = bnx2x_dmae_opcode_add_comp(
opcode, DMAE_COMP_PCI);
+
dmae->src_addr_lo = U64_LO(bnx2x_sp_mapping(bp, port_stats));
dmae->src_addr_hi = U64_HI(bnx2x_sp_mapping(bp, port_stats));
dmae->dst_addr_lo = bp->port.port_stx >> 2;
@@ -1235,13 +1334,9 @@
void bnx2x_stats_handle(struct bnx2x *bp, enum bnx2x_stats_event event)
{
enum bnx2x_stats_state state;
-
if (unlikely(bp->panic))
return;
-
bnx2x_stats_stm[bp->stats_state][event].action(bp);
-
- /* Protect a state change flow */
spin_lock_bh(&bp->stats_lock);
state = bp->stats_state;
bp->stats_state = bnx2x_stats_stm[state][event].next_state;
@@ -1297,7 +1392,7 @@
func_stx = bp->func_stx;
for (vn = VN_0; vn < vn_max; vn++) {
- int mb_idx = !CHIP_IS_E2(bp) ? 2*vn + BP_PORT(bp) : vn;
+ int mb_idx = CHIP_IS_E1x(bp) ? 2*vn + BP_PORT(bp) : vn;
bp->func_stx = SHMEM_RD(bp, func_mb[mb_idx].fw_mb_param);
bnx2x_func_stats_init(bp);
@@ -1339,12 +1434,97 @@
bnx2x_stats_comp(bp);
}
+/**
+ * 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 inline void bnx2x_prep_fw_stats_req(struct bnx2x *bp)
+{
+ int i;
+ struct stats_query_header *stats_hdr = &bp->fw_stats_req->hdr;
+
+ dma_addr_t cur_data_offset;
+ struct stats_query_entry *cur_query_entry;
+
+ stats_hdr->cmd_num = bp->fw_stats_num;
+ stats_hdr->drv_stats_counter = 0;
+
+ /* storm_counters struct contains the counters of completed
+ * statistics requests per storm which are incremented by FW
+ * each time it completes hadning a statistics ramrod. We will
+ * check these counters in the timer handler and discard a
+ * (statistics) ramrod completion.
+ */
+ cur_data_offset = bp->fw_stats_data_mapping +
+ offsetof(struct bnx2x_fw_stats_data, storm_counters);
+
+ stats_hdr->stats_counters_addrs.hi =
+ cpu_to_le32(U64_HI(cur_data_offset));
+ stats_hdr->stats_counters_addrs.lo =
+ cpu_to_le32(U64_LO(cur_data_offset));
+
+ /* prepare to the first stats ramrod (will be completed with
+ * the counters equal to zero) - init counters to somethig different.
+ */
+ memset(&bp->fw_stats_data->storm_counters, 0xff,
+ sizeof(struct stats_counter));
+
+ /**** Port FW statistics data ****/
+ cur_data_offset = bp->fw_stats_data_mapping +
+ offsetof(struct bnx2x_fw_stats_data, port);
+
+ cur_query_entry = &bp->fw_stats_req->query[BNX2X_PORT_QUERY_IDX];
+
+ cur_query_entry->kind = STATS_TYPE_PORT;
+ /* For port query index is a DONT CARE */
+ cur_query_entry->index = BP_PORT(bp);
+ /* For port query funcID is a DONT CARE */
+ cur_query_entry->funcID = cpu_to_le16(BP_FUNC(bp));
+ cur_query_entry->address.hi = cpu_to_le32(U64_HI(cur_data_offset));
+ cur_query_entry->address.lo = cpu_to_le32(U64_LO(cur_data_offset));
+
+ /**** PF FW statistics data ****/
+ cur_data_offset = bp->fw_stats_data_mapping +
+ offsetof(struct bnx2x_fw_stats_data, pf);
+
+ cur_query_entry = &bp->fw_stats_req->query[BNX2X_PF_QUERY_IDX];
+
+ cur_query_entry->kind = STATS_TYPE_PF;
+ /* For PF query index is a DONT CARE */
+ cur_query_entry->index = BP_PORT(bp);
+ cur_query_entry->funcID = cpu_to_le16(BP_FUNC(bp));
+ cur_query_entry->address.hi = cpu_to_le32(U64_HI(cur_data_offset));
+ cur_query_entry->address.lo = cpu_to_le32(U64_LO(cur_data_offset));
+
+ /**** Clients' queries ****/
+ cur_data_offset = bp->fw_stats_data_mapping +
+ offsetof(struct bnx2x_fw_stats_data, queue_stats);
+
+ for_each_eth_queue(bp, i) {
+ cur_query_entry =
+ &bp->fw_stats_req->
+ query[BNX2X_FIRST_QUEUE_QUERY_IDX + i];
+
+ cur_query_entry->kind = STATS_TYPE_QUEUE;
+ cur_query_entry->index = bnx2x_stats_id(&bp->fp[i]);
+ cur_query_entry->funcID = cpu_to_le16(BP_FUNC(bp));
+ cur_query_entry->address.hi =
+ cpu_to_le32(U64_HI(cur_data_offset));
+ cur_query_entry->address.lo =
+ cpu_to_le32(U64_LO(cur_data_offset));
+
+ cur_data_offset += sizeof(struct per_queue_stats);
+ }
+}
+
void bnx2x_stats_init(struct bnx2x *bp)
{
- int port = BP_PORT(bp);
+ int /*abs*/port = BP_PORT(bp);
int mb_idx = BP_FW_MB_IDX(bp);
int i;
- struct eth_stats_query *stats = bnx2x_sp(bp, fw_stats);
bp->stats_pending = 0;
bp->executer_idx = 0;
@@ -1362,45 +1542,35 @@
DP(BNX2X_MSG_STATS, "port_stx 0x%x func_stx 0x%x\n",
bp->port.port_stx, bp->func_stx);
+ port = BP_PORT(bp);
/* port stats */
memset(&(bp->port.old_nig_stats), 0, sizeof(struct nig_stats));
bp->port.old_nig_stats.brb_discard =
REG_RD(bp, NIG_REG_STAT0_BRB_DISCARD + port*0x38);
bp->port.old_nig_stats.brb_truncate =
REG_RD(bp, NIG_REG_STAT0_BRB_TRUNCATE + port*0x38);
- REG_RD_DMAE(bp, NIG_REG_STAT0_EGRESS_MAC_PKT0 + port*0x50,
- &(bp->port.old_nig_stats.egress_mac_pkt0_lo), 2);
- REG_RD_DMAE(bp, NIG_REG_STAT0_EGRESS_MAC_PKT1 + port*0x50,
- &(bp->port.old_nig_stats.egress_mac_pkt1_lo), 2);
+ if (!CHIP_IS_E3(bp)) {
+ REG_RD_DMAE(bp, NIG_REG_STAT0_EGRESS_MAC_PKT0 + port*0x50,
+ &(bp->port.old_nig_stats.egress_mac_pkt0_lo), 2);
+ REG_RD_DMAE(bp, NIG_REG_STAT0_EGRESS_MAC_PKT1 + port*0x50,
+ &(bp->port.old_nig_stats.egress_mac_pkt1_lo), 2);
+ }
/* function stats */
for_each_queue(bp, i) {
struct bnx2x_fastpath *fp = &bp->fp[i];
- memset(&fp->old_tclient, 0,
- sizeof(struct tstorm_per_client_stats));
- memset(&fp->old_uclient, 0,
- sizeof(struct ustorm_per_client_stats));
- memset(&fp->old_xclient, 0,
- sizeof(struct xstorm_per_client_stats));
- memset(&fp->eth_q_stats, 0, sizeof(struct bnx2x_eth_q_stats));
+ memset(&fp->old_tclient, 0, sizeof(fp->old_tclient));
+ memset(&fp->old_uclient, 0, sizeof(fp->old_uclient));
+ memset(&fp->old_xclient, 0, sizeof(fp->old_xclient));
+ memset(&fp->eth_q_stats, 0, sizeof(fp->eth_q_stats));
}
- /* FW stats are currently collected for ETH clients only */
- for_each_eth_queue(bp, i) {
- /* Set initial stats counter in the stats ramrod data to -1 */
- int cl_id = bp->fp[i].cl_id;
+ /* Prepare statistics ramrod data */
+ bnx2x_prep_fw_stats_req(bp);
- stats->xstorm_common.client_statistics[cl_id].
- stats_counter = 0xffff;
- stats->ustorm_common.client_statistics[cl_id].
- stats_counter = 0xffff;
- stats->tstorm_common.client_statistics[cl_id].
- stats_counter = 0xffff;
- }
-
- memset(&bp->dev->stats, 0, sizeof(struct net_device_stats));
- memset(&bp->eth_stats, 0, sizeof(struct bnx2x_eth_stats));
+ memset(&bp->dev->stats, 0, sizeof(bp->dev->stats));
+ memset(&bp->eth_stats, 0, sizeof(bp->eth_stats));
bp->stats_state = STATS_STATE_DISABLED;
diff --git a/drivers/net/bnx2x/bnx2x_stats.h b/drivers/net/bnx2x/bnx2x_stats.h
index 45d14d8..5d8ce2f 100644
--- a/drivers/net/bnx2x/bnx2x_stats.h
+++ b/drivers/net/bnx2x/bnx2x_stats.h
@@ -14,48 +14,11 @@
* Statistics and Link management by Yitchak Gertner
*
*/
-
#ifndef BNX2X_STATS_H
#define BNX2X_STATS_H
#include <linux/types.h>
-struct bnx2x_eth_q_stats {
- u32 total_bytes_received_hi;
- u32 total_bytes_received_lo;
- u32 total_bytes_transmitted_hi;
- u32 total_bytes_transmitted_lo;
- u32 total_unicast_packets_received_hi;
- u32 total_unicast_packets_received_lo;
- u32 total_multicast_packets_received_hi;
- u32 total_multicast_packets_received_lo;
- u32 total_broadcast_packets_received_hi;
- u32 total_broadcast_packets_received_lo;
- u32 total_unicast_packets_transmitted_hi;
- u32 total_unicast_packets_transmitted_lo;
- u32 total_multicast_packets_transmitted_hi;
- u32 total_multicast_packets_transmitted_lo;
- u32 total_broadcast_packets_transmitted_hi;
- u32 total_broadcast_packets_transmitted_lo;
- u32 valid_bytes_received_hi;
- u32 valid_bytes_received_lo;
-
- u32 error_bytes_received_hi;
- u32 error_bytes_received_lo;
- u32 etherstatsoverrsizepkts_hi;
- u32 etherstatsoverrsizepkts_lo;
- u32 no_buff_discard_hi;
- u32 no_buff_discard_lo;
-
- u32 driver_xoff;
- u32 rx_err_discard_pkt;
- u32 rx_skb_alloc_failed;
- u32 hw_csum_err;
-};
-
-#define Q_STATS_OFFSET32(stat_name) \
- (offsetof(struct bnx2x_eth_q_stats, stat_name) / 4)
-
struct nig_stats {
u32 brb_discard;
u32 brb_packet;
@@ -212,7 +175,7 @@
u32 brb_truncate_lo;
u32 mac_filter_discard;
- u32 xxoverflow_discard;
+ u32 mf_tag_discard;
u32 brb_truncate_discard;
u32 mac_discard;
@@ -222,16 +185,197 @@
u32 hw_csum_err;
u32 nig_timer_max;
+
+ /* TPA */
+ u32 total_tpa_aggregations_hi;
+ u32 total_tpa_aggregations_lo;
+ u32 total_tpa_aggregated_frames_hi;
+ u32 total_tpa_aggregated_frames_lo;
+ u32 total_tpa_bytes_hi;
+ u32 total_tpa_bytes_lo;
};
-#define STATS_OFFSET32(stat_name) \
- (offsetof(struct bnx2x_eth_stats, stat_name) / 4)
-/* Forward declaration */
+struct bnx2x_eth_q_stats {
+ u32 total_unicast_bytes_received_hi;
+ u32 total_unicast_bytes_received_lo;
+ u32 total_broadcast_bytes_received_hi;
+ u32 total_broadcast_bytes_received_lo;
+ u32 total_multicast_bytes_received_hi;
+ u32 total_multicast_bytes_received_lo;
+ u32 total_bytes_received_hi;
+ u32 total_bytes_received_lo;
+ u32 total_unicast_bytes_transmitted_hi;
+ u32 total_unicast_bytes_transmitted_lo;
+ u32 total_broadcast_bytes_transmitted_hi;
+ u32 total_broadcast_bytes_transmitted_lo;
+ u32 total_multicast_bytes_transmitted_hi;
+ u32 total_multicast_bytes_transmitted_lo;
+ u32 total_bytes_transmitted_hi;
+ u32 total_bytes_transmitted_lo;
+ u32 total_unicast_packets_received_hi;
+ u32 total_unicast_packets_received_lo;
+ u32 total_multicast_packets_received_hi;
+ u32 total_multicast_packets_received_lo;
+ u32 total_broadcast_packets_received_hi;
+ u32 total_broadcast_packets_received_lo;
+ u32 total_unicast_packets_transmitted_hi;
+ u32 total_unicast_packets_transmitted_lo;
+ u32 total_multicast_packets_transmitted_hi;
+ u32 total_multicast_packets_transmitted_lo;
+ u32 total_broadcast_packets_transmitted_hi;
+ u32 total_broadcast_packets_transmitted_lo;
+ u32 valid_bytes_received_hi;
+ u32 valid_bytes_received_lo;
+
+ u32 etherstatsoverrsizepkts_hi;
+ u32 etherstatsoverrsizepkts_lo;
+ u32 no_buff_discard_hi;
+ u32 no_buff_discard_lo;
+
+ u32 driver_xoff;
+ u32 rx_err_discard_pkt;
+ u32 rx_skb_alloc_failed;
+ u32 hw_csum_err;
+
+ u32 total_packets_received_checksum_discarded_hi;
+ u32 total_packets_received_checksum_discarded_lo;
+ u32 total_packets_received_ttl0_discarded_hi;
+ u32 total_packets_received_ttl0_discarded_lo;
+ u32 total_transmitted_dropped_packets_error_hi;
+ u32 total_transmitted_dropped_packets_error_lo;
+
+ /* TPA */
+ u32 total_tpa_aggregations_hi;
+ u32 total_tpa_aggregations_lo;
+ u32 total_tpa_aggregated_frames_hi;
+ u32 total_tpa_aggregated_frames_lo;
+ u32 total_tpa_bytes_hi;
+ u32 total_tpa_bytes_lo;
+};
+
+/****************************************************************************
+* Macros
+****************************************************************************/
+
+/* sum[hi:lo] += add[hi:lo] */
+#define ADD_64(s_hi, a_hi, s_lo, a_lo) \
+ do { \
+ s_lo += a_lo; \
+ s_hi += a_hi + ((s_lo < a_lo) ? 1 : 0); \
+ } while (0)
+
+/* difference = minuend - subtrahend */
+#define DIFF_64(d_hi, m_hi, s_hi, d_lo, m_lo, s_lo) \
+ do { \
+ if (m_lo < s_lo) { \
+ /* underflow */ \
+ d_hi = m_hi - s_hi; \
+ if (d_hi > 0) { \
+ /* we can 'loan' 1 */ \
+ d_hi--; \
+ d_lo = m_lo + (UINT_MAX - s_lo) + 1; \
+ } else { \
+ /* m_hi <= s_hi */ \
+ d_hi = 0; \
+ d_lo = 0; \
+ } \
+ } else { \
+ /* m_lo >= s_lo */ \
+ if (m_hi < s_hi) { \
+ d_hi = 0; \
+ d_lo = 0; \
+ } else { \
+ /* m_hi >= s_hi */ \
+ d_hi = m_hi - s_hi; \
+ d_lo = m_lo - s_lo; \
+ } \
+ } \
+ } while (0)
+
+#define UPDATE_STAT64(s, t) \
+ do { \
+ DIFF_64(diff.hi, new->s##_hi, pstats->mac_stx[0].t##_hi, \
+ diff.lo, new->s##_lo, pstats->mac_stx[0].t##_lo); \
+ pstats->mac_stx[0].t##_hi = new->s##_hi; \
+ pstats->mac_stx[0].t##_lo = new->s##_lo; \
+ ADD_64(pstats->mac_stx[1].t##_hi, diff.hi, \
+ pstats->mac_stx[1].t##_lo, diff.lo); \
+ } while (0)
+
+#define UPDATE_STAT64_NIG(s, t) \
+ do { \
+ DIFF_64(diff.hi, new->s##_hi, old->s##_hi, \
+ diff.lo, new->s##_lo, old->s##_lo); \
+ ADD_64(estats->t##_hi, diff.hi, \
+ estats->t##_lo, diff.lo); \
+ } while (0)
+
+/* sum[hi:lo] += add */
+#define ADD_EXTEND_64(s_hi, s_lo, a) \
+ do { \
+ s_lo += a; \
+ s_hi += (s_lo < a) ? 1 : 0; \
+ } while (0)
+
+#define ADD_STAT64(diff, t) \
+ do { \
+ ADD_64(pstats->mac_stx[1].t##_hi, new->diff##_hi, \
+ pstats->mac_stx[1].t##_lo, new->diff##_lo); \
+ } while (0)
+
+#define UPDATE_EXTEND_STAT(s) \
+ do { \
+ ADD_EXTEND_64(pstats->mac_stx[1].s##_hi, \
+ pstats->mac_stx[1].s##_lo, \
+ new->s); \
+ } while (0)
+
+#define UPDATE_EXTEND_TSTAT(s, t) \
+ do { \
+ diff = le32_to_cpu(tclient->s) - le32_to_cpu(old_tclient->s); \
+ old_tclient->s = tclient->s; \
+ ADD_EXTEND_64(qstats->t##_hi, qstats->t##_lo, diff); \
+ } while (0)
+
+#define UPDATE_EXTEND_USTAT(s, t) \
+ do { \
+ diff = le32_to_cpu(uclient->s) - le32_to_cpu(old_uclient->s); \
+ old_uclient->s = uclient->s; \
+ ADD_EXTEND_64(qstats->t##_hi, qstats->t##_lo, diff); \
+ } while (0)
+
+#define UPDATE_EXTEND_XSTAT(s, t) \
+ do { \
+ diff = le32_to_cpu(xclient->s) - le32_to_cpu(old_xclient->s); \
+ old_xclient->s = xclient->s; \
+ ADD_EXTEND_64(qstats->t##_hi, qstats->t##_lo, diff); \
+ } while (0)
+
+/* minuend -= subtrahend */
+#define SUB_64(m_hi, s_hi, m_lo, s_lo) \
+ do { \
+ DIFF_64(m_hi, m_hi, s_hi, m_lo, m_lo, s_lo); \
+ } while (0)
+
+/* minuend[hi:lo] -= subtrahend */
+#define SUB_EXTEND_64(m_hi, m_lo, s) \
+ do { \
+ SUB_64(m_hi, 0, m_lo, s); \
+ } while (0)
+
+#define SUB_EXTEND_USTAT(s, t) \
+ do { \
+ diff = le32_to_cpu(uclient->s) - le32_to_cpu(old_uclient->s); \
+ SUB_EXTEND_64(qstats->t##_hi, qstats->t##_lo, diff); \
+ } while (0)
+
+
+/* forward */
struct bnx2x;
void bnx2x_stats_init(struct bnx2x *bp);
-extern const u32 dmae_reg_go_c[];
+void bnx2x_stats_handle(struct bnx2x *bp, enum bnx2x_stats_event event);
#endif /* BNX2X_STATS_H */
diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c
index c7537abc..a047eb9 100644
--- a/drivers/net/bonding/bond_3ad.c
+++ b/drivers/net/bonding/bond_3ad.c
@@ -262,7 +262,7 @@
if (bond == NULL)
return BOND_AD_STABLE;
- return BOND_AD_INFO(bond).agg_select_mode;
+ return bond->params.ad_select;
}
/**
@@ -1859,7 +1859,6 @@
void bond_3ad_initiate_agg_selection(struct bonding *bond, int timeout)
{
BOND_AD_INFO(bond).agg_select_timer = timeout;
- BOND_AD_INFO(bond).agg_select_mode = bond->params.ad_select;
}
static u16 aggregator_identifier;
@@ -1868,11 +1867,10 @@
* bond_3ad_initialize - initialize a bond's 802.3ad parameters and structures
* @bond: bonding struct to work on
* @tick_resolution: tick duration (millisecond resolution)
- * @lacp_fast: boolean. whether fast periodic should be used
*
* Can be called only after the mac address of the bond is set.
*/
-void bond_3ad_initialize(struct bonding *bond, u16 tick_resolution, int lacp_fast)
+void bond_3ad_initialize(struct bonding *bond, u16 tick_resolution)
{
// check that the bond is not initialized yet
if (MAC_ADDRESS_COMPARE(&(BOND_AD_INFO(bond).system.sys_mac_addr),
@@ -1880,7 +1878,6 @@
aggregator_identifier = 0;
- BOND_AD_INFO(bond).lacp_fast = lacp_fast;
BOND_AD_INFO(bond).system.sys_priority = 0xFFFF;
BOND_AD_INFO(bond).system.sys_mac_addr = *((struct mac_addr *)bond->dev->dev_addr);
@@ -1918,7 +1915,7 @@
// port initialization
port = &(SLAVE_AD_INFO(slave).port);
- ad_initialize_port(port, BOND_AD_INFO(bond).lacp_fast);
+ ad_initialize_port(port, bond->params.lacp_fast);
port->slave = slave;
port->actor_port_number = SLAVE_AD_INFO(slave).id;
@@ -2345,8 +2342,17 @@
*/
int bond_3ad_set_carrier(struct bonding *bond)
{
- if (__get_active_agg(&(SLAVE_AD_INFO(bond->first_slave).aggregator))) {
- if (!netif_carrier_ok(bond->dev)) {
+ struct aggregator *active;
+
+ active = __get_active_agg(&(SLAVE_AD_INFO(bond->first_slave).aggregator));
+ if (active) {
+ /* are enough slaves available to consider link up? */
+ if (active->num_of_ports < bond->params.min_links) {
+ if (netif_carrier_ok(bond->dev)) {
+ netif_carrier_off(bond->dev);
+ return 1;
+ }
+ } else if (!netif_carrier_ok(bond->dev)) {
netif_carrier_on(bond->dev);
return 1;
}
@@ -2473,3 +2479,34 @@
bond_3ad_rx_indication((struct lacpdu *) skb->data, slave, skb->len);
read_unlock(&bond->lock);
}
+
+/*
+ * When modify lacp_rate parameter via sysfs,
+ * update actor_oper_port_state of each port.
+ *
+ * Hold slave->state_machine_lock,
+ * so we can modify port->actor_oper_port_state,
+ * no matter bond is up or down.
+ */
+void bond_3ad_update_lacp_rate(struct bonding *bond)
+{
+ int i;
+ struct slave *slave;
+ struct port *port = NULL;
+ int lacp_fast;
+
+ read_lock(&bond->lock);
+ lacp_fast = bond->params.lacp_fast;
+
+ bond_for_each_slave(bond, slave, i) {
+ port = &(SLAVE_AD_INFO(slave).port);
+ __get_state_machine_lock(port);
+ if (lacp_fast)
+ port->actor_oper_port_state |= AD_STATE_LACP_TIMEOUT;
+ else
+ port->actor_oper_port_state &= ~AD_STATE_LACP_TIMEOUT;
+ __release_state_machine_lock(port);
+ }
+
+ read_unlock(&bond->lock);
+}
diff --git a/drivers/net/bonding/bond_3ad.h b/drivers/net/bonding/bond_3ad.h
index 0ee3f16..235b2cc 100644
--- a/drivers/net/bonding/bond_3ad.h
+++ b/drivers/net/bonding/bond_3ad.h
@@ -253,11 +253,6 @@
struct ad_bond_info {
struct ad_system system; /* 802.3ad system structure */
u32 agg_select_timer; // Timer to select aggregator after all adapter's hand shakes
- u32 agg_select_mode; // Mode of selection of active aggregator(bandwidth/count)
- int lacp_fast; /* whether fast periodic tx should be
- * requested
- */
- struct timer_list ad_timer;
};
struct ad_slave_info {
@@ -269,7 +264,7 @@
};
// ================= AD Exported functions to the main bonding code ==================
-void bond_3ad_initialize(struct bonding *bond, u16 tick_resolution, int lacp_fast);
+void bond_3ad_initialize(struct bonding *bond, u16 tick_resolution);
int bond_3ad_bind_slave(struct slave *slave);
void bond_3ad_unbind_slave(struct slave *slave);
void bond_3ad_state_machine_handler(struct work_struct *);
@@ -282,5 +277,6 @@
void bond_3ad_lacpdu_recv(struct sk_buff *skb, struct bonding *bond,
struct slave *slave);
int bond_3ad_set_carrier(struct bonding *bond);
+void bond_3ad_update_lacp_rate(struct bonding *bond);
#endif //__BOND_3AD_H__
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index eafe44a..61265f7 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -98,6 +98,7 @@
static char *primary;
static char *primary_reselect;
static char *lacp_rate;
+static int min_links;
static char *ad_select;
static char *xmit_hash_policy;
static int arp_interval = BOND_LINK_ARP_INTERV;
@@ -150,6 +151,9 @@
MODULE_PARM_DESC(ad_select, "803.ad aggregation selection logic; "
"0 for stable (default), 1 for bandwidth, "
"2 for count");
+module_param(min_links, int, 0);
+MODULE_PARM_DESC(min_links, "Minimum number of available links before turning on carrier");
+
module_param(xmit_hash_policy, charp, 0);
MODULE_PARM_DESC(xmit_hash_policy, "balance-xor and 802.3ad hashing method; "
"0 for layer 2 (default), 1 for layer 3+4, "
@@ -329,16 +333,6 @@
kfree(vlan);
- if (list_empty(&bond->vlan_list) &&
- (bond->slave_cnt == 0)) {
- /* Last VLAN removed and no slaves, so
- * restore block on adding VLANs. This will
- * be removed once new slaves that are not
- * VLAN challenged will be added.
- */
- bond->dev->features |= NETIF_F_VLAN_CHALLENGED;
- }
-
res = 0;
goto out;
}
@@ -634,15 +628,8 @@
return -1;
slave_speed = ethtool_cmd_speed(&etool);
- switch (slave_speed) {
- case SPEED_10:
- case SPEED_100:
- case SPEED_1000:
- case SPEED_10000:
- break;
- default:
+ if (slave_speed == 0 || slave_speed == ((__u32) -1))
return -1;
- }
switch (etool.duplex) {
case DUPLEX_FULL:
@@ -1856,8 +1843,7 @@
/* Initialize AD with the number of times that the AD timer is called in 1 second
* can be called only after the mac address of the bond is set
*/
- bond_3ad_initialize(bond, 1000/AD_TIMER_INTERVAL,
- bond->params.lacp_fast);
+ bond_3ad_initialize(bond, 1000/AD_TIMER_INTERVAL);
} else {
SLAVE_AD_INFO(new_slave).id =
SLAVE_AD_INFO(new_slave->prev).id + 1;
@@ -3456,7 +3442,7 @@
int layer4_xor = 0;
if (skb->protocol == htons(ETH_P_IP)) {
- if (!(iph->frag_off & htons(IP_MF|IP_OFFSET)) &&
+ if (!ip_is_fragment(iph) &&
(iph->protocol == IPPROTO_TCP ||
iph->protocol == IPPROTO_UDP)) {
layer4_xor = ntohs((*layer4hdr ^ *(layer4hdr + 1)));
@@ -4816,6 +4802,7 @@
params->tx_queues = tx_queues;
params->all_slaves_active = all_slaves_active;
params->resend_igmp = resend_igmp;
+ params->min_links = min_links;
if (primary) {
strncpy(params->primary, primary, IFNAMSIZ);
diff --git a/drivers/net/bonding/bond_procfs.c b/drivers/net/bonding/bond_procfs.c
index c97307d..95de93b 100644
--- a/drivers/net/bonding/bond_procfs.c
+++ b/drivers/net/bonding/bond_procfs.c
@@ -125,6 +125,7 @@
seq_puts(seq, "\n802.3ad info\n");
seq_printf(seq, "LACP rate: %s\n",
(bond->params.lacp_fast) ? "fast" : "slow");
+ seq_printf(seq, "Min links: %d\n", bond->params.min_links);
seq_printf(seq, "Aggregator selection policy (ad_select): %s\n",
ad_select_tbl[bond->params.ad_select].modename);
diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c
index 88fcb25..b60835f 100644
--- a/drivers/net/bonding/bond_sysfs.c
+++ b/drivers/net/bonding/bond_sysfs.c
@@ -804,6 +804,7 @@
if ((new_value == 1) || (new_value == 0)) {
bond->params.lacp_fast = new_value;
+ bond_3ad_update_lacp_rate(bond);
pr_info("%s: Setting LACP rate to %s (%d).\n",
bond->dev->name, bond_lacp_tbl[new_value].modename,
new_value);
@@ -818,6 +819,38 @@
static DEVICE_ATTR(lacp_rate, S_IRUGO | S_IWUSR,
bonding_show_lacp, bonding_store_lacp);
+static ssize_t bonding_show_min_links(struct device *d,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct bonding *bond = to_bond(d);
+
+ return sprintf(buf, "%d\n", bond->params.min_links);
+}
+
+static ssize_t bonding_store_min_links(struct device *d,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct bonding *bond = to_bond(d);
+ int ret;
+ unsigned int new_value;
+
+ ret = kstrtouint(buf, 0, &new_value);
+ if (ret < 0) {
+ pr_err("%s: Ignoring invalid min links value %s.\n",
+ bond->dev->name, buf);
+ return ret;
+ }
+
+ pr_info("%s: Setting min links value to %u\n",
+ bond->dev->name, new_value);
+ bond->params.min_links = new_value;
+ return count;
+}
+static DEVICE_ATTR(min_links, S_IRUGO | S_IWUSR,
+ bonding_show_min_links, bonding_store_min_links);
+
static ssize_t bonding_show_ad_select(struct device *d,
struct device_attribute *attr,
char *buf)
@@ -1600,6 +1633,7 @@
&dev_attr_queue_id.attr,
&dev_attr_all_slaves_active.attr,
&dev_attr_resend_igmp.attr,
+ &dev_attr_min_links.attr,
NULL,
};
diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h
index ea1d005..2936171 100644
--- a/drivers/net/bonding/bonding.h
+++ b/drivers/net/bonding/bonding.h
@@ -147,6 +147,7 @@
int updelay;
int downdelay;
int lacp_fast;
+ unsigned int min_links;
int ad_select;
char primary[IFNAMSIZ];
int primary_reselect;
@@ -240,7 +241,6 @@
struct bond_params params;
struct list_head vlan_list;
struct vlan_group *vlgrp;
- struct packet_type arp_mon_pt;
struct workqueue_struct *wq;
struct delayed_work mii_work;
struct delayed_work arp_work;
diff --git a/drivers/net/caif/Kconfig b/drivers/net/caif/Kconfig
index 09ed3f4..abf4d7a 100644
--- a/drivers/net/caif/Kconfig
+++ b/drivers/net/caif/Kconfig
@@ -38,3 +38,12 @@
default n
---help---
The CAIF shared memory protocol driver for the STE UX5500 platform.
+
+config CAIF_HSI
+ tristate "CAIF HSI transport driver"
+ depends on CAIF
+ default n
+ ---help---
+ The caif low level driver for CAIF over HSI.
+ Be aware that if you enable this then you also need to
+ enable a low-level HSI driver.
diff --git a/drivers/net/caif/Makefile b/drivers/net/caif/Makefile
index 9560b9d..91dff86 100644
--- a/drivers/net/caif/Makefile
+++ b/drivers/net/caif/Makefile
@@ -10,3 +10,6 @@
# Shared memory
caif_shm-objs := caif_shmcore.o caif_shm_u5500.o
obj-$(CONFIG_CAIF_SHM) += caif_shm.o
+
+# HSI interface
+obj-$(CONFIG_CAIF_HSI) += caif_hsi.o
diff --git a/drivers/net/caif/caif_hsi.c b/drivers/net/caif/caif_hsi.c
new file mode 100644
index 0000000..016108a
--- /dev/null
+++ b/drivers/net/caif/caif_hsi.c
@@ -0,0 +1,1220 @@
+/*
+ * Copyright (C) ST-Ericsson AB 2010
+ * Contact: Sjur Brendeland / sjur.brandeland@stericsson.com
+ * Author: Daniel Martensson / daniel.martensson@stericsson.com
+ * Dmitry.Tarnyagin / dmitry.tarnyagin@stericsson.com
+ * License terms: GNU General Public License (GPL) version 2.
+ */
+
+#include <linux/version.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/netdevice.h>
+#include <linux/string.h>
+#include <linux/list.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/if_arp.h>
+#include <linux/timer.h>
+#include <net/caif/caif_layer.h>
+#include <net/caif/caif_hsi.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Daniel Martensson<daniel.martensson@stericsson.com>");
+MODULE_DESCRIPTION("CAIF HSI driver");
+
+/* Returns the number of padding bytes for alignment. */
+#define PAD_POW2(x, pow) ((((x)&((pow)-1)) == 0) ? 0 :\
+ (((pow)-((x)&((pow)-1)))))
+
+/*
+ * HSI padding options.
+ * Warning: must be a base of 2 (& operation used) and can not be zero !
+ */
+static int hsi_head_align = 4;
+module_param(hsi_head_align, int, S_IRUGO);
+MODULE_PARM_DESC(hsi_head_align, "HSI head alignment.");
+
+static int hsi_tail_align = 4;
+module_param(hsi_tail_align, int, S_IRUGO);
+MODULE_PARM_DESC(hsi_tail_align, "HSI tail alignment.");
+
+/*
+ * HSI link layer flowcontrol thresholds.
+ * Warning: A high threshold value migth increase throughput but it will at
+ * the same time prevent channel prioritization and increase the risk of
+ * flooding the modem. The high threshold should be above the low.
+ */
+static int hsi_high_threshold = 100;
+module_param(hsi_high_threshold, int, S_IRUGO);
+MODULE_PARM_DESC(hsi_high_threshold, "HSI high threshold (FLOW OFF).");
+
+static int hsi_low_threshold = 50;
+module_param(hsi_low_threshold, int, S_IRUGO);
+MODULE_PARM_DESC(hsi_low_threshold, "HSI high threshold (FLOW ON).");
+
+#define ON 1
+#define OFF 0
+
+/*
+ * Threshold values for the HSI packet queue. Flowcontrol will be asserted
+ * when the number of packets exceeds HIGH_WATER_MARK. It will not be
+ * de-asserted before the number of packets drops below LOW_WATER_MARK.
+ */
+#define LOW_WATER_MARK hsi_low_threshold
+#define HIGH_WATER_MARK hsi_high_threshold
+
+static LIST_HEAD(cfhsi_list);
+static spinlock_t cfhsi_list_lock;
+
+static void cfhsi_inactivity_tout(unsigned long arg)
+{
+ struct cfhsi *cfhsi = (struct cfhsi *)arg;
+
+ dev_dbg(&cfhsi->ndev->dev, "%s.\n",
+ __func__);
+
+ /* Schedule power down work queue. */
+ if (!test_bit(CFHSI_SHUTDOWN, &cfhsi->bits))
+ queue_work(cfhsi->wq, &cfhsi->wake_down_work);
+}
+
+static void cfhsi_abort_tx(struct cfhsi *cfhsi)
+{
+ struct sk_buff *skb;
+
+ for (;;) {
+ spin_lock_bh(&cfhsi->lock);
+ skb = skb_dequeue(&cfhsi->qhead);
+ if (!skb)
+ break;
+
+ cfhsi->ndev->stats.tx_errors++;
+ cfhsi->ndev->stats.tx_dropped++;
+ spin_unlock_bh(&cfhsi->lock);
+ kfree_skb(skb);
+ }
+ cfhsi->tx_state = CFHSI_TX_STATE_IDLE;
+ if (!test_bit(CFHSI_SHUTDOWN, &cfhsi->bits))
+ mod_timer(&cfhsi->timer, jiffies + CFHSI_INACTIVITY_TOUT);
+ spin_unlock_bh(&cfhsi->lock);
+}
+
+static int cfhsi_flush_fifo(struct cfhsi *cfhsi)
+{
+ char buffer[32]; /* Any reasonable value */
+ size_t fifo_occupancy;
+ int ret;
+
+ dev_dbg(&cfhsi->ndev->dev, "%s.\n",
+ __func__);
+
+
+ ret = cfhsi->dev->cfhsi_wake_up(cfhsi->dev);
+ if (ret) {
+ dev_warn(&cfhsi->ndev->dev,
+ "%s: can't wake up HSI interface: %d.\n",
+ __func__, ret);
+ return ret;
+ }
+
+ do {
+ ret = cfhsi->dev->cfhsi_fifo_occupancy(cfhsi->dev,
+ &fifo_occupancy);
+ if (ret) {
+ dev_warn(&cfhsi->ndev->dev,
+ "%s: can't get FIFO occupancy: %d.\n",
+ __func__, ret);
+ break;
+ } else if (!fifo_occupancy)
+ /* No more data, exitting normally */
+ break;
+
+ fifo_occupancy = min(sizeof(buffer), fifo_occupancy);
+ set_bit(CFHSI_FLUSH_FIFO, &cfhsi->bits);
+ ret = cfhsi->dev->cfhsi_rx(buffer, fifo_occupancy,
+ cfhsi->dev);
+ if (ret) {
+ clear_bit(CFHSI_FLUSH_FIFO, &cfhsi->bits);
+ dev_warn(&cfhsi->ndev->dev,
+ "%s: can't read data: %d.\n",
+ __func__, ret);
+ break;
+ }
+
+ ret = 5 * HZ;
+ wait_event_interruptible_timeout(cfhsi->flush_fifo_wait,
+ !test_bit(CFHSI_FLUSH_FIFO, &cfhsi->bits), ret);
+
+ if (ret < 0) {
+ dev_warn(&cfhsi->ndev->dev,
+ "%s: can't wait for flush complete: %d.\n",
+ __func__, ret);
+ break;
+ } else if (!ret) {
+ ret = -ETIMEDOUT;
+ dev_warn(&cfhsi->ndev->dev,
+ "%s: timeout waiting for flush complete.\n",
+ __func__);
+ break;
+ }
+ } while (1);
+
+ cfhsi->dev->cfhsi_wake_down(cfhsi->dev);
+
+ return ret;
+}
+
+static int cfhsi_tx_frm(struct cfhsi_desc *desc, struct cfhsi *cfhsi)
+{
+ int nfrms = 0;
+ int pld_len = 0;
+ struct sk_buff *skb;
+ u8 *pfrm = desc->emb_frm + CFHSI_MAX_EMB_FRM_SZ;
+
+ skb = skb_dequeue(&cfhsi->qhead);
+ if (!skb)
+ return 0;
+
+ /* Check if we can embed a CAIF frame. */
+ if (skb->len < CFHSI_MAX_EMB_FRM_SZ) {
+ struct caif_payload_info *info;
+ int hpad = 0;
+ int tpad = 0;
+
+ /* Calculate needed head alignment and tail alignment. */
+ info = (struct caif_payload_info *)&skb->cb;
+
+ hpad = 1 + PAD_POW2((info->hdr_len + 1), hsi_head_align);
+ tpad = PAD_POW2((skb->len + hpad), hsi_tail_align);
+
+ /* Check if frame still fits with added alignment. */
+ if ((skb->len + hpad + tpad) <= CFHSI_MAX_EMB_FRM_SZ) {
+ u8 *pemb = desc->emb_frm;
+ desc->offset = CFHSI_DESC_SHORT_SZ;
+ *pemb = (u8)(hpad - 1);
+ pemb += hpad;
+
+ /* Update network statistics. */
+ cfhsi->ndev->stats.tx_packets++;
+ cfhsi->ndev->stats.tx_bytes += skb->len;
+
+ /* Copy in embedded CAIF frame. */
+ skb_copy_bits(skb, 0, pemb, skb->len);
+ consume_skb(skb);
+ skb = NULL;
+ }
+ } else
+ /* Clear offset. */
+ desc->offset = 0;
+
+ /* Create payload CAIF frames. */
+ pfrm = desc->emb_frm + CFHSI_MAX_EMB_FRM_SZ;
+ while (nfrms < CFHSI_MAX_PKTS) {
+ struct caif_payload_info *info;
+ int hpad = 0;
+ int tpad = 0;
+
+ if (!skb)
+ skb = skb_dequeue(&cfhsi->qhead);
+
+ if (!skb)
+ break;
+
+ /* Calculate needed head alignment and tail alignment. */
+ info = (struct caif_payload_info *)&skb->cb;
+
+ hpad = 1 + PAD_POW2((info->hdr_len + 1), hsi_head_align);
+ tpad = PAD_POW2((skb->len + hpad), hsi_tail_align);
+
+ /* Fill in CAIF frame length in descriptor. */
+ desc->cffrm_len[nfrms] = hpad + skb->len + tpad;
+
+ /* Fill head padding information. */
+ *pfrm = (u8)(hpad - 1);
+ pfrm += hpad;
+
+ /* Update network statistics. */
+ cfhsi->ndev->stats.tx_packets++;
+ cfhsi->ndev->stats.tx_bytes += skb->len;
+
+ /* Copy in CAIF frame. */
+ skb_copy_bits(skb, 0, pfrm, skb->len);
+
+ /* Update payload length. */
+ pld_len += desc->cffrm_len[nfrms];
+
+ /* Update frame pointer. */
+ pfrm += skb->len + tpad;
+ consume_skb(skb);
+ skb = NULL;
+
+ /* Update number of frames. */
+ nfrms++;
+ }
+
+ /* Unused length fields should be zero-filled (according to SPEC). */
+ while (nfrms < CFHSI_MAX_PKTS) {
+ desc->cffrm_len[nfrms] = 0x0000;
+ nfrms++;
+ }
+
+ /* Check if we can piggy-back another descriptor. */
+ skb = skb_peek(&cfhsi->qhead);
+ if (skb)
+ desc->header |= CFHSI_PIGGY_DESC;
+ else
+ desc->header &= ~CFHSI_PIGGY_DESC;
+
+ return CFHSI_DESC_SZ + pld_len;
+}
+
+static void cfhsi_tx_done_work(struct work_struct *work)
+{
+ struct cfhsi *cfhsi = NULL;
+ struct cfhsi_desc *desc = NULL;
+ int len = 0;
+ int res;
+
+ cfhsi = container_of(work, struct cfhsi, tx_done_work);
+ dev_dbg(&cfhsi->ndev->dev, "%s.\n",
+ __func__);
+
+ if (test_bit(CFHSI_SHUTDOWN, &cfhsi->bits))
+ return;
+
+ desc = (struct cfhsi_desc *)cfhsi->tx_buf;
+
+ do {
+ /*
+ * Send flow on if flow off has been previously signalled
+ * and number of packets is below low water mark.
+ */
+ spin_lock_bh(&cfhsi->lock);
+ if (cfhsi->flow_off_sent &&
+ cfhsi->qhead.qlen <= cfhsi->q_low_mark &&
+ cfhsi->cfdev.flowctrl) {
+
+ cfhsi->flow_off_sent = 0;
+ cfhsi->cfdev.flowctrl(cfhsi->ndev, ON);
+ }
+ spin_unlock_bh(&cfhsi->lock);
+
+ /* Create HSI frame. */
+ len = cfhsi_tx_frm(desc, cfhsi);
+ if (!len) {
+ cfhsi->tx_state = CFHSI_TX_STATE_IDLE;
+ /* Start inactivity timer. */
+ mod_timer(&cfhsi->timer,
+ jiffies + CFHSI_INACTIVITY_TOUT);
+ break;
+ }
+
+ /* Set up new transfer. */
+ res = cfhsi->dev->cfhsi_tx(cfhsi->tx_buf, len, cfhsi->dev);
+ if (WARN_ON(res < 0)) {
+ dev_err(&cfhsi->ndev->dev, "%s: TX error %d.\n",
+ __func__, res);
+ }
+ } while (res < 0);
+}
+
+static void cfhsi_tx_done_cb(struct cfhsi_drv *drv)
+{
+ struct cfhsi *cfhsi;
+
+ cfhsi = container_of(drv, struct cfhsi, drv);
+ dev_dbg(&cfhsi->ndev->dev, "%s.\n",
+ __func__);
+
+ if (test_bit(CFHSI_SHUTDOWN, &cfhsi->bits))
+ return;
+
+ queue_work(cfhsi->wq, &cfhsi->tx_done_work);
+}
+
+static int cfhsi_rx_desc(struct cfhsi_desc *desc, struct cfhsi *cfhsi)
+{
+ int xfer_sz = 0;
+ int nfrms = 0;
+ u16 *plen = NULL;
+ u8 *pfrm = NULL;
+
+ if ((desc->header & ~CFHSI_PIGGY_DESC) ||
+ (desc->offset > CFHSI_MAX_EMB_FRM_SZ)) {
+ dev_err(&cfhsi->ndev->dev, "%s: Invalid descriptor.\n",
+ __func__);
+ return 0;
+ }
+
+ /* Check for embedded CAIF frame. */
+ if (desc->offset) {
+ struct sk_buff *skb;
+ u8 *dst = NULL;
+ int len = 0, retries = 0;
+ pfrm = ((u8 *)desc) + desc->offset;
+
+ /* Remove offset padding. */
+ pfrm += *pfrm + 1;
+
+ /* Read length of CAIF frame (little endian). */
+ len = *pfrm;
+ len |= ((*(pfrm+1)) << 8) & 0xFF00;
+ len += 2; /* Add FCS fields. */
+
+
+ /* Allocate SKB (OK even in IRQ context). */
+ skb = alloc_skb(len + 1, GFP_KERNEL);
+ while (!skb) {
+ retries++;
+ schedule_timeout(1);
+ skb = alloc_skb(len + 1, GFP_KERNEL);
+ if (skb) {
+ printk(KERN_WARNING "%s: slept for %u "
+ "before getting memory\n",
+ __func__, retries);
+ break;
+ }
+ if (retries > HZ) {
+ printk(KERN_ERR "%s: slept for 1HZ and "
+ "did not get memory\n",
+ __func__);
+ cfhsi->ndev->stats.rx_dropped++;
+ goto drop_frame;
+ }
+ }
+ caif_assert(skb != NULL);
+
+ dst = skb_put(skb, len);
+ memcpy(dst, pfrm, len);
+
+ skb->protocol = htons(ETH_P_CAIF);
+ skb_reset_mac_header(skb);
+ skb->dev = cfhsi->ndev;
+
+ /*
+ * We are called from a arch specific platform device.
+ * Unfortunately we don't know what context we're
+ * running in.
+ */
+ if (in_interrupt())
+ netif_rx(skb);
+ else
+ netif_rx_ni(skb);
+
+ /* Update network statistics. */
+ cfhsi->ndev->stats.rx_packets++;
+ cfhsi->ndev->stats.rx_bytes += len;
+ }
+
+drop_frame:
+ /* Calculate transfer length. */
+ plen = desc->cffrm_len;
+ while (nfrms < CFHSI_MAX_PKTS && *plen) {
+ xfer_sz += *plen;
+ plen++;
+ nfrms++;
+ }
+
+ /* Check for piggy-backed descriptor. */
+ if (desc->header & CFHSI_PIGGY_DESC)
+ xfer_sz += CFHSI_DESC_SZ;
+
+ if (xfer_sz % 4) {
+ dev_err(&cfhsi->ndev->dev,
+ "%s: Invalid payload len: %d, ignored.\n",
+ __func__, xfer_sz);
+ xfer_sz = 0;
+ }
+
+ return xfer_sz;
+}
+
+static int cfhsi_rx_pld(struct cfhsi_desc *desc, struct cfhsi *cfhsi)
+{
+ int rx_sz = 0;
+ int nfrms = 0;
+ u16 *plen = NULL;
+ u8 *pfrm = NULL;
+
+ /* Sanity check header and offset. */
+ if (WARN_ON((desc->header & ~CFHSI_PIGGY_DESC) ||
+ (desc->offset > CFHSI_MAX_EMB_FRM_SZ))) {
+ dev_err(&cfhsi->ndev->dev, "%s: Invalid descriptor.\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ /* Set frame pointer to start of payload. */
+ pfrm = desc->emb_frm + CFHSI_MAX_EMB_FRM_SZ;
+ plen = desc->cffrm_len;
+ while (nfrms < CFHSI_MAX_PKTS && *plen) {
+ struct sk_buff *skb;
+ u8 *dst = NULL;
+ u8 *pcffrm = NULL;
+ int len = 0, retries = 0;
+
+ if (WARN_ON(desc->cffrm_len[nfrms] > CFHSI_MAX_PAYLOAD_SZ)) {
+ dev_err(&cfhsi->ndev->dev, "%s: Invalid payload.\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ /* CAIF frame starts after head padding. */
+ pcffrm = pfrm + *pfrm + 1;
+
+ /* Read length of CAIF frame (little endian). */
+ len = *pcffrm;
+ len |= ((*(pcffrm + 1)) << 8) & 0xFF00;
+ len += 2; /* Add FCS fields. */
+
+ /* Allocate SKB (OK even in IRQ context). */
+ skb = alloc_skb(len + 1, GFP_KERNEL);
+ while (!skb) {
+ retries++;
+ schedule_timeout(1);
+ skb = alloc_skb(len + 1, GFP_KERNEL);
+ if (skb) {
+ printk(KERN_WARNING "%s: slept for %u "
+ "before getting memory\n",
+ __func__, retries);
+ break;
+ }
+ if (retries > HZ) {
+ printk(KERN_ERR "%s: slept for 1HZ "
+ "and did not get memory\n",
+ __func__);
+ cfhsi->ndev->stats.rx_dropped++;
+ goto drop_frame;
+ }
+ }
+ caif_assert(skb != NULL);
+
+ dst = skb_put(skb, len);
+ memcpy(dst, pcffrm, len);
+
+ skb->protocol = htons(ETH_P_CAIF);
+ skb_reset_mac_header(skb);
+ skb->dev = cfhsi->ndev;
+
+ /*
+ * We're called from a platform device,
+ * and don't know the context we're running in.
+ */
+ if (in_interrupt())
+ netif_rx(skb);
+ else
+ netif_rx_ni(skb);
+
+ /* Update network statistics. */
+ cfhsi->ndev->stats.rx_packets++;
+ cfhsi->ndev->stats.rx_bytes += len;
+
+drop_frame:
+ pfrm += *plen;
+ rx_sz += *plen;
+ plen++;
+ nfrms++;
+ }
+
+ return rx_sz;
+}
+
+static void cfhsi_rx_done_work(struct work_struct *work)
+{
+ int res;
+ int desc_pld_len = 0;
+ struct cfhsi *cfhsi = NULL;
+ struct cfhsi_desc *desc = NULL;
+
+ cfhsi = container_of(work, struct cfhsi, rx_done_work);
+ desc = (struct cfhsi_desc *)cfhsi->rx_buf;
+
+ dev_dbg(&cfhsi->ndev->dev, "%s: Kick timer if pending.\n",
+ __func__);
+
+ if (test_bit(CFHSI_SHUTDOWN, &cfhsi->bits))
+ return;
+
+ /* Update inactivity timer if pending. */
+ mod_timer_pending(&cfhsi->timer, jiffies + CFHSI_INACTIVITY_TOUT);
+
+ if (cfhsi->rx_state == CFHSI_RX_STATE_DESC) {
+ desc_pld_len = cfhsi_rx_desc(desc, cfhsi);
+ } else {
+ int pld_len;
+
+ pld_len = cfhsi_rx_pld(desc, cfhsi);
+
+ if ((pld_len > 0) && (desc->header & CFHSI_PIGGY_DESC)) {
+ struct cfhsi_desc *piggy_desc;
+ piggy_desc = (struct cfhsi_desc *)
+ (desc->emb_frm + CFHSI_MAX_EMB_FRM_SZ +
+ pld_len);
+
+ /* Extract piggy-backed descriptor. */
+ desc_pld_len = cfhsi_rx_desc(piggy_desc, cfhsi);
+
+ /*
+ * Copy needed information from the piggy-backed
+ * descriptor to the descriptor in the start.
+ */
+ memcpy((u8 *)desc, (u8 *)piggy_desc,
+ CFHSI_DESC_SHORT_SZ);
+ }
+ }
+
+ if (desc_pld_len) {
+ cfhsi->rx_state = CFHSI_RX_STATE_PAYLOAD;
+ cfhsi->rx_ptr = cfhsi->rx_buf + CFHSI_DESC_SZ;
+ cfhsi->rx_len = desc_pld_len;
+ } else {
+ cfhsi->rx_state = CFHSI_RX_STATE_DESC;
+ cfhsi->rx_ptr = cfhsi->rx_buf;
+ cfhsi->rx_len = CFHSI_DESC_SZ;
+ }
+ clear_bit(CFHSI_PENDING_RX, &cfhsi->bits);
+
+ if (test_bit(CFHSI_AWAKE, &cfhsi->bits)) {
+ /* Set up new transfer. */
+ dev_dbg(&cfhsi->ndev->dev, "%s: Start RX.\n",
+ __func__);
+ res = cfhsi->dev->cfhsi_rx(cfhsi->rx_ptr, cfhsi->rx_len,
+ cfhsi->dev);
+ if (WARN_ON(res < 0)) {
+ dev_err(&cfhsi->ndev->dev, "%s: RX error %d.\n",
+ __func__, res);
+ cfhsi->ndev->stats.rx_errors++;
+ cfhsi->ndev->stats.rx_dropped++;
+ }
+ }
+}
+
+static void cfhsi_rx_done_cb(struct cfhsi_drv *drv)
+{
+ struct cfhsi *cfhsi;
+
+ cfhsi = container_of(drv, struct cfhsi, drv);
+ dev_dbg(&cfhsi->ndev->dev, "%s.\n",
+ __func__);
+
+ if (test_bit(CFHSI_SHUTDOWN, &cfhsi->bits))
+ return;
+
+ set_bit(CFHSI_PENDING_RX, &cfhsi->bits);
+
+ if (test_and_clear_bit(CFHSI_FLUSH_FIFO, &cfhsi->bits))
+ wake_up_interruptible(&cfhsi->flush_fifo_wait);
+ else
+ queue_work(cfhsi->wq, &cfhsi->rx_done_work);
+}
+
+static void cfhsi_wake_up(struct work_struct *work)
+{
+ struct cfhsi *cfhsi = NULL;
+ int res;
+ int len;
+ long ret;
+
+ cfhsi = container_of(work, struct cfhsi, wake_up_work);
+
+ if (test_bit(CFHSI_SHUTDOWN, &cfhsi->bits))
+ return;
+
+ if (unlikely(test_bit(CFHSI_AWAKE, &cfhsi->bits))) {
+ /* It happenes when wakeup is requested by
+ * both ends at the same time. */
+ clear_bit(CFHSI_WAKE_UP, &cfhsi->bits);
+ return;
+ }
+
+ /* Activate wake line. */
+ cfhsi->dev->cfhsi_wake_up(cfhsi->dev);
+
+ dev_dbg(&cfhsi->ndev->dev, "%s: Start waiting.\n",
+ __func__);
+
+ /* Wait for acknowledge. */
+ ret = CFHSI_WAKEUP_TOUT;
+ wait_event_interruptible_timeout(cfhsi->wake_up_wait,
+ test_bit(CFHSI_WAKE_UP_ACK,
+ &cfhsi->bits), ret);
+ if (unlikely(ret < 0)) {
+ /* Interrupted by signal. */
+ dev_info(&cfhsi->ndev->dev, "%s: Signalled: %ld.\n",
+ __func__, ret);
+ clear_bit(CFHSI_WAKE_UP, &cfhsi->bits);
+ cfhsi->dev->cfhsi_wake_down(cfhsi->dev);
+ return;
+ } else if (!ret) {
+ /* Wakeup timeout */
+ dev_err(&cfhsi->ndev->dev, "%s: Timeout.\n",
+ __func__);
+ clear_bit(CFHSI_WAKE_UP, &cfhsi->bits);
+ cfhsi->dev->cfhsi_wake_down(cfhsi->dev);
+ return;
+ }
+ dev_dbg(&cfhsi->ndev->dev, "%s: Woken.\n",
+ __func__);
+
+ /* Clear power up bit. */
+ set_bit(CFHSI_AWAKE, &cfhsi->bits);
+ clear_bit(CFHSI_WAKE_UP, &cfhsi->bits);
+
+ /* Resume read operation. */
+ if (!test_bit(CFHSI_PENDING_RX, &cfhsi->bits)) {
+ dev_dbg(&cfhsi->ndev->dev, "%s: Start RX.\n",
+ __func__);
+ res = cfhsi->dev->cfhsi_rx(cfhsi->rx_ptr,
+ cfhsi->rx_len, cfhsi->dev);
+ if (WARN_ON(res < 0)) {
+ dev_err(&cfhsi->ndev->dev, "%s: RX error %d.\n",
+ __func__, res);
+ }
+ }
+
+ /* Clear power up acknowledment. */
+ clear_bit(CFHSI_WAKE_UP_ACK, &cfhsi->bits);
+
+ spin_lock_bh(&cfhsi->lock);
+
+ /* Resume transmit if queue is not empty. */
+ if (!skb_peek(&cfhsi->qhead)) {
+ dev_dbg(&cfhsi->ndev->dev, "%s: Peer wake, start timer.\n",
+ __func__);
+ /* Start inactivity timer. */
+ mod_timer(&cfhsi->timer,
+ jiffies + CFHSI_INACTIVITY_TOUT);
+ spin_unlock_bh(&cfhsi->lock);
+ return;
+ }
+
+ dev_dbg(&cfhsi->ndev->dev, "%s: Host wake.\n",
+ __func__);
+
+ spin_unlock_bh(&cfhsi->lock);
+
+ /* Create HSI frame. */
+ len = cfhsi_tx_frm((struct cfhsi_desc *)cfhsi->tx_buf, cfhsi);
+
+ if (likely(len > 0)) {
+ /* Set up new transfer. */
+ res = cfhsi->dev->cfhsi_tx(cfhsi->tx_buf, len, cfhsi->dev);
+ if (WARN_ON(res < 0)) {
+ dev_err(&cfhsi->ndev->dev, "%s: TX error %d.\n",
+ __func__, res);
+ cfhsi_abort_tx(cfhsi);
+ }
+ } else {
+ dev_err(&cfhsi->ndev->dev,
+ "%s: Failed to create HSI frame: %d.\n",
+ __func__, len);
+ }
+
+}
+
+static void cfhsi_wake_down(struct work_struct *work)
+{
+ long ret;
+ struct cfhsi *cfhsi = NULL;
+ size_t fifo_occupancy;
+
+ cfhsi = container_of(work, struct cfhsi, wake_down_work);
+ dev_dbg(&cfhsi->ndev->dev, "%s.\n",
+ __func__);
+
+ if (test_bit(CFHSI_SHUTDOWN, &cfhsi->bits))
+ return;
+
+ /* Check if there is something in FIFO. */
+ if (WARN_ON(cfhsi->dev->cfhsi_fifo_occupancy(cfhsi->dev,
+ &fifo_occupancy)))
+ fifo_occupancy = 0;
+
+ if (fifo_occupancy) {
+ dev_dbg(&cfhsi->ndev->dev,
+ "%s: %u words in RX FIFO, restart timer.\n",
+ __func__, (unsigned) fifo_occupancy);
+ spin_lock_bh(&cfhsi->lock);
+ mod_timer(&cfhsi->timer,
+ jiffies + CFHSI_INACTIVITY_TOUT);
+ spin_unlock_bh(&cfhsi->lock);
+ return;
+ }
+
+ /* Cancel pending RX requests */
+ cfhsi->dev->cfhsi_rx_cancel(cfhsi->dev);
+
+ /* Deactivate wake line. */
+ cfhsi->dev->cfhsi_wake_down(cfhsi->dev);
+
+ /* Wait for acknowledge. */
+ ret = CFHSI_WAKEUP_TOUT;
+ ret = wait_event_interruptible_timeout(cfhsi->wake_down_wait,
+ test_bit(CFHSI_WAKE_DOWN_ACK,
+ &cfhsi->bits),
+ ret);
+ if (ret < 0) {
+ /* Interrupted by signal. */
+ dev_info(&cfhsi->ndev->dev, "%s: Signalled: %ld.\n",
+ __func__, ret);
+ return;
+ } else if (!ret) {
+ /* Timeout */
+ dev_err(&cfhsi->ndev->dev, "%s: Timeout.\n",
+ __func__);
+ }
+
+ /* Clear power down acknowledment. */
+ clear_bit(CFHSI_WAKE_DOWN_ACK, &cfhsi->bits);
+ clear_bit(CFHSI_AWAKE, &cfhsi->bits);
+
+ /* Check if there is something in FIFO. */
+ if (WARN_ON(cfhsi->dev->cfhsi_fifo_occupancy(cfhsi->dev,
+ &fifo_occupancy)))
+ fifo_occupancy = 0;
+
+ if (fifo_occupancy) {
+ dev_dbg(&cfhsi->ndev->dev,
+ "%s: %u words in RX FIFO, wakeup forced.\n",
+ __func__, (unsigned) fifo_occupancy);
+ if (!test_and_set_bit(CFHSI_WAKE_UP, &cfhsi->bits))
+ queue_work(cfhsi->wq, &cfhsi->wake_up_work);
+ } else
+ dev_dbg(&cfhsi->ndev->dev, "%s: Done.\n",
+ __func__);
+}
+
+static void cfhsi_wake_up_cb(struct cfhsi_drv *drv)
+{
+ struct cfhsi *cfhsi = NULL;
+
+ cfhsi = container_of(drv, struct cfhsi, drv);
+ dev_dbg(&cfhsi->ndev->dev, "%s.\n",
+ __func__);
+
+ set_bit(CFHSI_WAKE_UP_ACK, &cfhsi->bits);
+ wake_up_interruptible(&cfhsi->wake_up_wait);
+
+ if (test_bit(CFHSI_SHUTDOWN, &cfhsi->bits))
+ return;
+
+ /* Schedule wake up work queue if the peer initiates. */
+ if (!test_and_set_bit(CFHSI_WAKE_UP, &cfhsi->bits))
+ queue_work(cfhsi->wq, &cfhsi->wake_up_work);
+}
+
+static void cfhsi_wake_down_cb(struct cfhsi_drv *drv)
+{
+ struct cfhsi *cfhsi = NULL;
+
+ cfhsi = container_of(drv, struct cfhsi, drv);
+ dev_dbg(&cfhsi->ndev->dev, "%s.\n",
+ __func__);
+
+ /* Initiating low power is only permitted by the host (us). */
+ set_bit(CFHSI_WAKE_DOWN_ACK, &cfhsi->bits);
+ wake_up_interruptible(&cfhsi->wake_down_wait);
+}
+
+static int cfhsi_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ struct cfhsi *cfhsi = NULL;
+ int start_xfer = 0;
+ int timer_active;
+
+ if (!dev)
+ return -EINVAL;
+
+ cfhsi = netdev_priv(dev);
+
+ spin_lock_bh(&cfhsi->lock);
+
+ skb_queue_tail(&cfhsi->qhead, skb);
+
+ /* Sanity check; xmit should not be called after unregister_netdev */
+ if (WARN_ON(test_bit(CFHSI_SHUTDOWN, &cfhsi->bits))) {
+ spin_unlock_bh(&cfhsi->lock);
+ cfhsi_abort_tx(cfhsi);
+ return -EINVAL;
+ }
+
+ /* Send flow off if number of packets is above high water mark. */
+ if (!cfhsi->flow_off_sent &&
+ cfhsi->qhead.qlen > cfhsi->q_high_mark &&
+ cfhsi->cfdev.flowctrl) {
+ cfhsi->flow_off_sent = 1;
+ cfhsi->cfdev.flowctrl(cfhsi->ndev, OFF);
+ }
+
+ if (cfhsi->tx_state == CFHSI_TX_STATE_IDLE) {
+ cfhsi->tx_state = CFHSI_TX_STATE_XFER;
+ start_xfer = 1;
+ }
+
+ spin_unlock_bh(&cfhsi->lock);
+
+ if (!start_xfer)
+ return 0;
+
+ /* Delete inactivity timer if started. */
+#ifdef CONFIG_SMP
+ timer_active = del_timer_sync(&cfhsi->timer);
+#else
+ timer_active = del_timer(&cfhsi->timer);
+#endif /* CONFIG_SMP */
+
+ if (timer_active) {
+ struct cfhsi_desc *desc = (struct cfhsi_desc *)cfhsi->tx_buf;
+ int len;
+ int res;
+
+ /* Create HSI frame. */
+ len = cfhsi_tx_frm(desc, cfhsi);
+ BUG_ON(!len);
+
+ /* Set up new transfer. */
+ res = cfhsi->dev->cfhsi_tx(cfhsi->tx_buf, len, cfhsi->dev);
+ if (WARN_ON(res < 0)) {
+ dev_err(&cfhsi->ndev->dev, "%s: TX error %d.\n",
+ __func__, res);
+ cfhsi_abort_tx(cfhsi);
+ }
+ } else {
+ /* Schedule wake up work queue if the we initiate. */
+ if (!test_and_set_bit(CFHSI_WAKE_UP, &cfhsi->bits))
+ queue_work(cfhsi->wq, &cfhsi->wake_up_work);
+ }
+
+ return 0;
+}
+
+static int cfhsi_open(struct net_device *dev)
+{
+ netif_wake_queue(dev);
+
+ return 0;
+}
+
+static int cfhsi_close(struct net_device *dev)
+{
+ netif_stop_queue(dev);
+
+ return 0;
+}
+
+static const struct net_device_ops cfhsi_ops = {
+ .ndo_open = cfhsi_open,
+ .ndo_stop = cfhsi_close,
+ .ndo_start_xmit = cfhsi_xmit
+};
+
+static void cfhsi_setup(struct net_device *dev)
+{
+ struct cfhsi *cfhsi = netdev_priv(dev);
+ dev->features = 0;
+ dev->netdev_ops = &cfhsi_ops;
+ dev->type = ARPHRD_CAIF;
+ dev->flags = IFF_POINTOPOINT | IFF_NOARP;
+ dev->mtu = CFHSI_MAX_PAYLOAD_SZ;
+ dev->tx_queue_len = 0;
+ dev->destructor = free_netdev;
+ skb_queue_head_init(&cfhsi->qhead);
+ cfhsi->cfdev.link_select = CAIF_LINK_HIGH_BANDW;
+ cfhsi->cfdev.use_frag = false;
+ cfhsi->cfdev.use_stx = false;
+ cfhsi->cfdev.use_fcs = false;
+ cfhsi->ndev = dev;
+}
+
+int cfhsi_probe(struct platform_device *pdev)
+{
+ struct cfhsi *cfhsi = NULL;
+ struct net_device *ndev;
+ struct cfhsi_dev *dev;
+ int res;
+
+ ndev = alloc_netdev(sizeof(struct cfhsi), "cfhsi%d", cfhsi_setup);
+ if (!ndev) {
+ dev_err(&pdev->dev, "%s: alloc_netdev failed.\n",
+ __func__);
+ return -ENODEV;
+ }
+
+ cfhsi = netdev_priv(ndev);
+ cfhsi->ndev = ndev;
+ cfhsi->pdev = pdev;
+
+ /* Initialize state vaiables. */
+ cfhsi->tx_state = CFHSI_TX_STATE_IDLE;
+ cfhsi->rx_state = CFHSI_RX_STATE_DESC;
+
+ /* Set flow info */
+ cfhsi->flow_off_sent = 0;
+ cfhsi->q_low_mark = LOW_WATER_MARK;
+ cfhsi->q_high_mark = HIGH_WATER_MARK;
+
+ /* Assign the HSI device. */
+ dev = (struct cfhsi_dev *)pdev->dev.platform_data;
+ cfhsi->dev = dev;
+
+ /* Assign the driver to this HSI device. */
+ dev->drv = &cfhsi->drv;
+
+ /*
+ * Allocate a TX buffer with the size of a HSI packet descriptors
+ * and the necessary room for CAIF payload frames.
+ */
+ cfhsi->tx_buf = kzalloc(CFHSI_BUF_SZ_TX, GFP_KERNEL);
+ if (!cfhsi->tx_buf) {
+ dev_err(&ndev->dev, "%s: Failed to allocate TX buffer.\n",
+ __func__);
+ res = -ENODEV;
+ goto err_alloc_tx;
+ }
+
+ /*
+ * Allocate a RX buffer with the size of two HSI packet descriptors and
+ * the necessary room for CAIF payload frames.
+ */
+ cfhsi->rx_buf = kzalloc(CFHSI_BUF_SZ_RX, GFP_KERNEL);
+ if (!cfhsi->rx_buf) {
+ dev_err(&ndev->dev, "%s: Failed to allocate RX buffer.\n",
+ __func__);
+ res = -ENODEV;
+ goto err_alloc_rx;
+ }
+
+ /* Initialize receive variables. */
+ cfhsi->rx_ptr = cfhsi->rx_buf;
+ cfhsi->rx_len = CFHSI_DESC_SZ;
+
+ /* Initialize spin locks. */
+ spin_lock_init(&cfhsi->lock);
+
+ /* Set up the driver. */
+ cfhsi->drv.tx_done_cb = cfhsi_tx_done_cb;
+ cfhsi->drv.rx_done_cb = cfhsi_rx_done_cb;
+
+ /* Initialize the work queues. */
+ INIT_WORK(&cfhsi->wake_up_work, cfhsi_wake_up);
+ INIT_WORK(&cfhsi->wake_down_work, cfhsi_wake_down);
+ INIT_WORK(&cfhsi->rx_done_work, cfhsi_rx_done_work);
+ INIT_WORK(&cfhsi->tx_done_work, cfhsi_tx_done_work);
+
+ /* Clear all bit fields. */
+ clear_bit(CFHSI_WAKE_UP_ACK, &cfhsi->bits);
+ clear_bit(CFHSI_WAKE_DOWN_ACK, &cfhsi->bits);
+ clear_bit(CFHSI_WAKE_UP, &cfhsi->bits);
+ clear_bit(CFHSI_AWAKE, &cfhsi->bits);
+ clear_bit(CFHSI_PENDING_RX, &cfhsi->bits);
+
+ /* Create work thread. */
+ cfhsi->wq = create_singlethread_workqueue(pdev->name);
+ if (!cfhsi->wq) {
+ dev_err(&ndev->dev, "%s: Failed to create work queue.\n",
+ __func__);
+ res = -ENODEV;
+ goto err_create_wq;
+ }
+
+ /* Initialize wait queues. */
+ init_waitqueue_head(&cfhsi->wake_up_wait);
+ init_waitqueue_head(&cfhsi->wake_down_wait);
+ init_waitqueue_head(&cfhsi->flush_fifo_wait);
+
+ /* Setup the inactivity timer. */
+ init_timer(&cfhsi->timer);
+ cfhsi->timer.data = (unsigned long)cfhsi;
+ cfhsi->timer.function = cfhsi_inactivity_tout;
+
+ /* Add CAIF HSI device to list. */
+ spin_lock(&cfhsi_list_lock);
+ list_add_tail(&cfhsi->list, &cfhsi_list);
+ spin_unlock(&cfhsi_list_lock);
+
+ /* Activate HSI interface. */
+ res = cfhsi->dev->cfhsi_up(cfhsi->dev);
+ if (res) {
+ dev_err(&cfhsi->ndev->dev,
+ "%s: can't activate HSI interface: %d.\n",
+ __func__, res);
+ goto err_activate;
+ }
+
+ /* Flush FIFO */
+ res = cfhsi_flush_fifo(cfhsi);
+ if (res) {
+ dev_err(&ndev->dev, "%s: Can't flush FIFO: %d.\n",
+ __func__, res);
+ goto err_net_reg;
+ }
+
+ cfhsi->drv.wake_up_cb = cfhsi_wake_up_cb;
+ cfhsi->drv.wake_down_cb = cfhsi_wake_down_cb;
+
+ /* Register network device. */
+ res = register_netdev(ndev);
+ if (res) {
+ dev_err(&ndev->dev, "%s: Registration error: %d.\n",
+ __func__, res);
+ goto err_net_reg;
+ }
+
+ netif_stop_queue(ndev);
+
+ return res;
+
+ err_net_reg:
+ cfhsi->dev->cfhsi_down(cfhsi->dev);
+ err_activate:
+ destroy_workqueue(cfhsi->wq);
+ err_create_wq:
+ kfree(cfhsi->rx_buf);
+ err_alloc_rx:
+ kfree(cfhsi->tx_buf);
+ err_alloc_tx:
+ free_netdev(ndev);
+
+ return res;
+}
+
+static void cfhsi_shutdown(struct cfhsi *cfhsi, bool remove_platform_dev)
+{
+ u8 *tx_buf, *rx_buf;
+
+ /* Stop TXing */
+ netif_tx_stop_all_queues(cfhsi->ndev);
+
+ /* going to shutdown driver */
+ set_bit(CFHSI_SHUTDOWN, &cfhsi->bits);
+
+ if (remove_platform_dev) {
+ /* Flush workqueue */
+ flush_workqueue(cfhsi->wq);
+
+ /* Notify device. */
+ platform_device_unregister(cfhsi->pdev);
+ }
+
+ /* Flush workqueue */
+ flush_workqueue(cfhsi->wq);
+
+ /* Delete timer if pending */
+#ifdef CONFIG_SMP
+ del_timer_sync(&cfhsi->timer);
+#else
+ del_timer(&cfhsi->timer);
+#endif /* CONFIG_SMP */
+
+ /* Cancel pending RX request (if any) */
+ cfhsi->dev->cfhsi_rx_cancel(cfhsi->dev);
+
+ /* Flush again and destroy workqueue */
+ destroy_workqueue(cfhsi->wq);
+
+ /* Store bufferes: will be freed later. */
+ tx_buf = cfhsi->tx_buf;
+ rx_buf = cfhsi->rx_buf;
+
+ /* Flush transmit queues. */
+ cfhsi_abort_tx(cfhsi);
+
+ /* Deactivate interface */
+ cfhsi->dev->cfhsi_down(cfhsi->dev);
+
+ /* Finally unregister the network device. */
+ unregister_netdev(cfhsi->ndev);
+
+ /* Free buffers. */
+ kfree(tx_buf);
+ kfree(rx_buf);
+}
+
+int cfhsi_remove(struct platform_device *pdev)
+{
+ struct list_head *list_node;
+ struct list_head *n;
+ struct cfhsi *cfhsi = NULL;
+ struct cfhsi_dev *dev;
+
+ dev = (struct cfhsi_dev *)pdev->dev.platform_data;
+ spin_lock(&cfhsi_list_lock);
+ list_for_each_safe(list_node, n, &cfhsi_list) {
+ cfhsi = list_entry(list_node, struct cfhsi, list);
+ /* Find the corresponding device. */
+ if (cfhsi->dev == dev) {
+ /* Remove from list. */
+ list_del(list_node);
+ spin_unlock(&cfhsi_list_lock);
+
+ /* Shutdown driver. */
+ cfhsi_shutdown(cfhsi, false);
+
+ return 0;
+ }
+ }
+ spin_unlock(&cfhsi_list_lock);
+ return -ENODEV;
+}
+
+struct platform_driver cfhsi_plat_drv = {
+ .probe = cfhsi_probe,
+ .remove = cfhsi_remove,
+ .driver = {
+ .name = "cfhsi",
+ .owner = THIS_MODULE,
+ },
+};
+
+static void __exit cfhsi_exit_module(void)
+{
+ struct list_head *list_node;
+ struct list_head *n;
+ struct cfhsi *cfhsi = NULL;
+
+ spin_lock(&cfhsi_list_lock);
+ list_for_each_safe(list_node, n, &cfhsi_list) {
+ cfhsi = list_entry(list_node, struct cfhsi, list);
+
+ /* Remove from list. */
+ list_del(list_node);
+ spin_unlock(&cfhsi_list_lock);
+
+ /* Shutdown driver. */
+ cfhsi_shutdown(cfhsi, true);
+
+ spin_lock(&cfhsi_list_lock);
+ }
+ spin_unlock(&cfhsi_list_lock);
+
+ /* Unregister platform driver. */
+ platform_driver_unregister(&cfhsi_plat_drv);
+}
+
+static int __init cfhsi_init_module(void)
+{
+ int result;
+
+ /* Initialize spin lock. */
+ spin_lock_init(&cfhsi_list_lock);
+
+ /* Register platform driver. */
+ result = platform_driver_register(&cfhsi_plat_drv);
+ if (result) {
+ printk(KERN_ERR "Could not register platform HSI driver: %d.\n",
+ result);
+ goto err_dev_register;
+ }
+
+ return result;
+
+ err_dev_register:
+ return result;
+}
+
+module_init(cfhsi_init_module);
+module_exit(cfhsi_exit_module);
diff --git a/drivers/net/caif/caif_serial.c b/drivers/net/caif/caif_serial.c
index 3df0c0f..23406e6 100644
--- a/drivers/net/caif/caif_serial.c
+++ b/drivers/net/caif/caif_serial.c
@@ -4,8 +4,8 @@
* License terms: GNU General Public License (GPL) version 2
*/
+#include <linux/hardirq.h>
#include <linux/init.h>
-#include <linux/version.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/types.h>
diff --git a/drivers/net/caif/caif_shm_u5500.c b/drivers/net/caif/caif_shm_u5500.c
index 5f771ab..89d76b7 100644
--- a/drivers/net/caif/caif_shm_u5500.c
+++ b/drivers/net/caif/caif_shm_u5500.c
@@ -7,7 +7,6 @@
#define pr_fmt(fmt) KBUILD_MODNAME ":" fmt
-#include <linux/version.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/netdevice.h>
diff --git a/drivers/net/caif/caif_shmcore.c b/drivers/net/caif/caif_shmcore.c
index 731aa11..d4b26fb 100644
--- a/drivers/net/caif/caif_shmcore.c
+++ b/drivers/net/caif/caif_shmcore.c
@@ -134,7 +134,7 @@
u32 avail_emptybuff = 0;
unsigned long flags = 0;
- pshm_drv = (struct shmdrv_layer *)priv;
+ pshm_drv = priv;
/* Check for received buffers. */
if (mbx_msg & SHM_FULL_MASK) {
diff --git a/drivers/net/caif/caif_spi.c b/drivers/net/caif/caif_spi.c
index 57e6393..0f8defc 100644
--- a/drivers/net/caif/caif_spi.c
+++ b/drivers/net/caif/caif_spi.c
@@ -5,7 +5,6 @@
* License terms: GNU General Public License (GPL) version 2.
*/
-#include <linux/version.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/device.h>
diff --git a/drivers/net/caif/caif_spi_slave.c b/drivers/net/caif/caif_spi_slave.c
index b009e03..e139e13 100644
--- a/drivers/net/caif/caif_spi_slave.c
+++ b/drivers/net/caif/caif_spi_slave.c
@@ -4,7 +4,6 @@
* Author: Daniel Martensson / Daniel.Martensson@stericsson.com
* License terms: GNU General Public License (GPL) version 2.
*/
-#include <linux/version.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/device.h>
diff --git a/drivers/net/can/Kconfig b/drivers/net/can/Kconfig
index 754df5e..f6c98fb 100644
--- a/drivers/net/can/Kconfig
+++ b/drivers/net/can/Kconfig
@@ -4,7 +4,6 @@
config CAN_VCAN
tristate "Virtual Local CAN Interface (vcan)"
depends on CAN
- default N
---help---
Similar to the network loopback devices, vcan offers a
virtual local CAN interface.
@@ -15,7 +14,6 @@
config CAN_SLCAN
tristate "Serial / USB serial CAN Adaptors (slcan)"
depends on CAN
- default N
---help---
CAN driver for several 'low cost' CAN interfaces that are attached
via serial lines or via USB-to-serial adapters using the LAWICEL
@@ -58,9 +56,10 @@
config CAN_AT91
tristate "Atmel AT91 onchip CAN controller"
- depends on CAN_DEV && ARCH_AT91SAM9263
+ depends on CAN_DEV && (ARCH_AT91SAM9263 || ARCH_AT91SAM9X5)
---help---
- This is a driver for the SoC CAN controller in Atmel's AT91SAM9263.
+ This is a driver for the SoC CAN controller in Atmel's AT91SAM9263
+ and AT91SAM9X5 processors.
config CAN_TI_HECC
depends on CAN_DEV && ARCH_OMAP3
@@ -124,7 +123,6 @@
config CAN_DEBUG_DEVICES
bool "CAN devices debugging messages"
depends on CAN
- default N
---help---
Say Y here if you want the CAN device drivers to produce a bunch of
debug messages to the system log. Select this if you are having
diff --git a/drivers/net/can/at91_can.c b/drivers/net/can/at91_can.c
index 74efb5a..121ede6 100644
--- a/drivers/net/can/at91_can.c
+++ b/drivers/net/can/at91_can.c
@@ -41,32 +41,7 @@
#include <mach/board.h>
-#define AT91_NAPI_WEIGHT 11
-
-/*
- * RX/TX Mailbox split
- * don't dare to touch
- */
-#define AT91_MB_RX_NUM 11
-#define AT91_MB_TX_SHIFT 2
-
-#define AT91_MB_RX_FIRST 1
-#define AT91_MB_RX_LAST (AT91_MB_RX_FIRST + AT91_MB_RX_NUM - 1)
-
-#define AT91_MB_RX_MASK(i) ((1 << (i)) - 1)
-#define AT91_MB_RX_SPLIT 8
-#define AT91_MB_RX_LOW_LAST (AT91_MB_RX_SPLIT - 1)
-#define AT91_MB_RX_LOW_MASK (AT91_MB_RX_MASK(AT91_MB_RX_SPLIT) & \
- ~AT91_MB_RX_MASK(AT91_MB_RX_FIRST))
-
-#define AT91_MB_TX_NUM (1 << AT91_MB_TX_SHIFT)
-#define AT91_MB_TX_FIRST (AT91_MB_RX_LAST + 1)
-#define AT91_MB_TX_LAST (AT91_MB_TX_FIRST + AT91_MB_TX_NUM - 1)
-
-#define AT91_NEXT_PRIO_SHIFT (AT91_MB_TX_SHIFT)
-#define AT91_NEXT_PRIO_MASK (0xf << AT91_MB_TX_SHIFT)
-#define AT91_NEXT_MB_MASK (AT91_MB_TX_NUM - 1)
-#define AT91_NEXT_MASK ((AT91_MB_TX_NUM - 1) | AT91_NEXT_PRIO_MASK)
+#define AT91_MB_MASK(i) ((1 << (i)) - 1)
/* Common registers */
enum at91_reg {
@@ -128,12 +103,6 @@
};
/* Interrupt mask bits */
-#define AT91_IRQ_MB_RX ((1 << (AT91_MB_RX_LAST + 1)) \
- - (1 << AT91_MB_RX_FIRST))
-#define AT91_IRQ_MB_TX ((1 << (AT91_MB_TX_LAST + 1)) \
- - (1 << AT91_MB_TX_FIRST))
-#define AT91_IRQ_MB_ALL (AT91_IRQ_MB_RX | AT91_IRQ_MB_TX)
-
#define AT91_IRQ_ERRA (1 << 16)
#define AT91_IRQ_WARN (1 << 17)
#define AT91_IRQ_ERRP (1 << 18)
@@ -156,22 +125,51 @@
#define AT91_IRQ_ALL (0x1fffffff)
+enum at91_devtype {
+ AT91_DEVTYPE_SAM9263,
+ AT91_DEVTYPE_SAM9X5,
+};
+
+struct at91_devtype_data {
+ unsigned int rx_first;
+ unsigned int rx_split;
+ unsigned int rx_last;
+ unsigned int tx_shift;
+ enum at91_devtype type;
+};
+
struct at91_priv {
- struct can_priv can; /* must be the first member! */
- struct net_device *dev;
- struct napi_struct napi;
+ struct can_priv can; /* must be the first member! */
+ struct net_device *dev;
+ struct napi_struct napi;
- void __iomem *reg_base;
+ void __iomem *reg_base;
- u32 reg_sr;
- unsigned int tx_next;
- unsigned int tx_echo;
- unsigned int rx_next;
+ u32 reg_sr;
+ unsigned int tx_next;
+ unsigned int tx_echo;
+ unsigned int rx_next;
+ struct at91_devtype_data devtype_data;
- struct clk *clk;
- struct at91_can_data *pdata;
+ struct clk *clk;
+ struct at91_can_data *pdata;
- canid_t mb0_id;
+ canid_t mb0_id;
+};
+
+static const struct at91_devtype_data at91_devtype_data[] __devinitconst = {
+ [AT91_DEVTYPE_SAM9263] = {
+ .rx_first = 1,
+ .rx_split = 8,
+ .rx_last = 11,
+ .tx_shift = 2,
+ },
+ [AT91_DEVTYPE_SAM9X5] = {
+ .rx_first = 0,
+ .rx_split = 4,
+ .rx_last = 5,
+ .tx_shift = 1,
+ },
};
static struct can_bittiming_const at91_bittiming_const = {
@@ -186,19 +184,111 @@
.brp_inc = 1,
};
-static inline int get_tx_next_mb(const struct at91_priv *priv)
-{
- return (priv->tx_next & AT91_NEXT_MB_MASK) + AT91_MB_TX_FIRST;
+#define AT91_IS(_model) \
+static inline int at91_is_sam##_model(const struct at91_priv *priv) \
+{ \
+ return priv->devtype_data.type == AT91_DEVTYPE_SAM##_model; \
}
-static inline int get_tx_next_prio(const struct at91_priv *priv)
+AT91_IS(9263);
+AT91_IS(9X5);
+
+static inline unsigned int get_mb_rx_first(const struct at91_priv *priv)
{
- return (priv->tx_next >> AT91_NEXT_PRIO_SHIFT) & 0xf;
+ return priv->devtype_data.rx_first;
}
-static inline int get_tx_echo_mb(const struct at91_priv *priv)
+static inline unsigned int get_mb_rx_last(const struct at91_priv *priv)
{
- return (priv->tx_echo & AT91_NEXT_MB_MASK) + AT91_MB_TX_FIRST;
+ return priv->devtype_data.rx_last;
+}
+
+static inline unsigned int get_mb_rx_split(const struct at91_priv *priv)
+{
+ return priv->devtype_data.rx_split;
+}
+
+static inline unsigned int get_mb_rx_num(const struct at91_priv *priv)
+{
+ return get_mb_rx_last(priv) - get_mb_rx_first(priv) + 1;
+}
+
+static inline unsigned int get_mb_rx_low_last(const struct at91_priv *priv)
+{
+ return get_mb_rx_split(priv) - 1;
+}
+
+static inline unsigned int get_mb_rx_low_mask(const struct at91_priv *priv)
+{
+ return AT91_MB_MASK(get_mb_rx_split(priv)) &
+ ~AT91_MB_MASK(get_mb_rx_first(priv));
+}
+
+static inline unsigned int get_mb_tx_shift(const struct at91_priv *priv)
+{
+ return priv->devtype_data.tx_shift;
+}
+
+static inline unsigned int get_mb_tx_num(const struct at91_priv *priv)
+{
+ return 1 << get_mb_tx_shift(priv);
+}
+
+static inline unsigned int get_mb_tx_first(const struct at91_priv *priv)
+{
+ return get_mb_rx_last(priv) + 1;
+}
+
+static inline unsigned int get_mb_tx_last(const struct at91_priv *priv)
+{
+ return get_mb_tx_first(priv) + get_mb_tx_num(priv) - 1;
+}
+
+static inline unsigned int get_next_prio_shift(const struct at91_priv *priv)
+{
+ return get_mb_tx_shift(priv);
+}
+
+static inline unsigned int get_next_prio_mask(const struct at91_priv *priv)
+{
+ return 0xf << get_mb_tx_shift(priv);
+}
+
+static inline unsigned int get_next_mb_mask(const struct at91_priv *priv)
+{
+ return AT91_MB_MASK(get_mb_tx_shift(priv));
+}
+
+static inline unsigned int get_next_mask(const struct at91_priv *priv)
+{
+ return get_next_mb_mask(priv) | get_next_prio_mask(priv);
+}
+
+static inline unsigned int get_irq_mb_rx(const struct at91_priv *priv)
+{
+ return AT91_MB_MASK(get_mb_rx_last(priv) + 1) &
+ ~AT91_MB_MASK(get_mb_rx_first(priv));
+}
+
+static inline unsigned int get_irq_mb_tx(const struct at91_priv *priv)
+{
+ return AT91_MB_MASK(get_mb_tx_last(priv) + 1) &
+ ~AT91_MB_MASK(get_mb_tx_first(priv));
+}
+
+static inline unsigned int get_tx_next_mb(const struct at91_priv *priv)
+{
+ return (priv->tx_next & get_next_mb_mask(priv)) + get_mb_tx_first(priv);
+}
+
+static inline unsigned int get_tx_next_prio(const struct at91_priv *priv)
+{
+ return (priv->tx_next >> get_next_prio_shift(priv)) & 0xf;
+}
+
+static inline unsigned int get_tx_echo_mb(const struct at91_priv *priv)
+{
+ return (priv->tx_echo & get_next_mb_mask(priv)) + get_mb_tx_first(priv);
}
static inline u32 at91_read(const struct at91_priv *priv, enum at91_reg reg)
@@ -259,29 +349,29 @@
* overflow.
*/
reg_mid = at91_can_id_to_reg_mid(priv->mb0_id);
- for (i = 0; i < AT91_MB_RX_FIRST; i++) {
+ for (i = 0; i < get_mb_rx_first(priv); i++) {
set_mb_mode(priv, i, AT91_MB_MODE_DISABLED);
at91_write(priv, AT91_MID(i), reg_mid);
at91_write(priv, AT91_MCR(i), 0x0); /* clear dlc */
}
- for (i = AT91_MB_RX_FIRST; i < AT91_MB_RX_LAST; i++)
+ for (i = get_mb_rx_first(priv); i < get_mb_rx_last(priv); i++)
set_mb_mode(priv, i, AT91_MB_MODE_RX);
- set_mb_mode(priv, AT91_MB_RX_LAST, AT91_MB_MODE_RX_OVRWR);
+ set_mb_mode(priv, get_mb_rx_last(priv), AT91_MB_MODE_RX_OVRWR);
/* reset acceptance mask and id register */
- for (i = AT91_MB_RX_FIRST; i <= AT91_MB_RX_LAST; i++) {
- at91_write(priv, AT91_MAM(i), 0x0 );
+ for (i = get_mb_rx_first(priv); i <= get_mb_rx_last(priv); i++) {
+ at91_write(priv, AT91_MAM(i), 0x0);
at91_write(priv, AT91_MID(i), AT91_MID_MIDE);
}
/* The last 4 mailboxes are used for transmitting. */
- for (i = AT91_MB_TX_FIRST; i <= AT91_MB_TX_LAST; i++)
+ for (i = get_mb_tx_first(priv); i <= get_mb_tx_last(priv); i++)
set_mb_mode_prio(priv, i, AT91_MB_MODE_TX, 0);
/* Reset tx and rx helper pointers */
priv->tx_next = priv->tx_echo = 0;
- priv->rx_next = AT91_MB_RX_FIRST;
+ priv->rx_next = get_mb_rx_first(priv);
}
static int at91_set_bittiming(struct net_device *dev)
@@ -336,7 +426,7 @@
priv->can.state = CAN_STATE_ERROR_ACTIVE;
/* Enable interrupts */
- reg_ier = AT91_IRQ_MB_RX | AT91_IRQ_ERRP | AT91_IRQ_ERR_FRAME;
+ reg_ier = get_irq_mb_rx(priv) | AT91_IRQ_ERRP | AT91_IRQ_ERR_FRAME;
at91_write(priv, AT91_IDR, AT91_IRQ_ALL);
at91_write(priv, AT91_IER, reg_ier);
}
@@ -375,8 +465,8 @@
* mailbox, but without the offset AT91_MB_TX_FIRST. The lower bits
* encode the mailbox number, the upper 4 bits the mailbox priority:
*
- * priv->tx_next = (prio << AT91_NEXT_PRIO_SHIFT) ||
- * (mb - AT91_MB_TX_FIRST);
+ * priv->tx_next = (prio << get_next_prio_shift(priv)) |
+ * (mb - get_mb_tx_first(priv));
*
*/
static netdev_tx_t at91_start_xmit(struct sk_buff *skb, struct net_device *dev)
@@ -417,7 +507,7 @@
stats->tx_bytes += cf->can_dlc;
/* _NOTE_: subtract AT91_MB_TX_FIRST offset from mb! */
- can_put_echo_skb(skb, dev, mb - AT91_MB_TX_FIRST);
+ can_put_echo_skb(skb, dev, mb - get_mb_tx_first(priv));
/*
* we have to stop the queue and deliver all messages in case
@@ -430,7 +520,7 @@
priv->tx_next++;
if (!(at91_read(priv, AT91_MSR(get_tx_next_mb(priv))) &
AT91_MSR_MRDY) ||
- (priv->tx_next & AT91_NEXT_MASK) == 0)
+ (priv->tx_next & get_next_mask(priv)) == 0)
netif_stop_queue(dev);
/* Enable interrupt for this mailbox */
@@ -447,7 +537,7 @@
*/
static inline void at91_activate_rx_low(const struct at91_priv *priv)
{
- u32 mask = AT91_MB_RX_LOW_MASK;
+ u32 mask = get_mb_rx_low_mask(priv);
at91_write(priv, AT91_TCR, mask);
}
@@ -513,17 +603,19 @@
cf->can_id = (reg_mid >> 18) & CAN_SFF_MASK;
reg_msr = at91_read(priv, AT91_MSR(mb));
- if (reg_msr & AT91_MSR_MRTR)
- cf->can_id |= CAN_RTR_FLAG;
cf->can_dlc = get_can_dlc((reg_msr >> 16) & 0xf);
- *(u32 *)(cf->data + 0) = at91_read(priv, AT91_MDL(mb));
- *(u32 *)(cf->data + 4) = at91_read(priv, AT91_MDH(mb));
+ if (reg_msr & AT91_MSR_MRTR)
+ cf->can_id |= CAN_RTR_FLAG;
+ else {
+ *(u32 *)(cf->data + 0) = at91_read(priv, AT91_MDL(mb));
+ *(u32 *)(cf->data + 4) = at91_read(priv, AT91_MDH(mb));
+ }
/* allow RX of extended frames */
at91_write(priv, AT91_MID(mb), AT91_MID_MIDE);
- if (unlikely(mb == AT91_MB_RX_LAST && reg_msr & AT91_MSR_MMI))
+ if (unlikely(mb == get_mb_rx_last(priv) && reg_msr & AT91_MSR_MMI))
at91_rx_overflow_err(dev);
}
@@ -561,8 +653,9 @@
*
* Theory of Operation:
*
- * 11 of the 16 mailboxes on the chip are reserved for RX. we split
- * them into 2 groups. The lower group holds 7 and upper 4 mailboxes.
+ * About 3/4 of the mailboxes (get_mb_rx_first()...get_mb_rx_last())
+ * on the chip are reserved for RX. We split them into 2 groups. The
+ * lower group ranges from get_mb_rx_first() to get_mb_rx_low_last().
*
* Like it or not, but the chip always saves a received CAN message
* into the first free mailbox it finds (starting with the
@@ -610,23 +703,23 @@
unsigned int mb;
int received = 0;
- if (priv->rx_next > AT91_MB_RX_LOW_LAST &&
- reg_sr & AT91_MB_RX_LOW_MASK)
+ if (priv->rx_next > get_mb_rx_low_last(priv) &&
+ reg_sr & get_mb_rx_low_mask(priv))
netdev_info(dev,
"order of incoming frames cannot be guaranteed\n");
again:
- for (mb = find_next_bit(addr, AT91_MB_RX_LAST + 1, priv->rx_next);
- mb < AT91_MB_RX_LAST + 1 && quota > 0;
+ for (mb = find_next_bit(addr, get_mb_tx_first(priv), priv->rx_next);
+ mb < get_mb_tx_first(priv) && quota > 0;
reg_sr = at91_read(priv, AT91_SR),
- mb = find_next_bit(addr, AT91_MB_RX_LAST + 1, ++priv->rx_next)) {
+ mb = find_next_bit(addr, get_mb_tx_first(priv), ++priv->rx_next)) {
at91_read_msg(dev, mb);
/* reactivate mailboxes */
- if (mb == AT91_MB_RX_LOW_LAST)
+ if (mb == get_mb_rx_low_last(priv))
/* all lower mailboxed, if just finished it */
at91_activate_rx_low(priv);
- else if (mb > AT91_MB_RX_LOW_LAST)
+ else if (mb > get_mb_rx_low_last(priv))
/* only the mailbox we read */
at91_activate_rx_mb(priv, mb);
@@ -635,9 +728,9 @@
}
/* upper group completed, look again in lower */
- if (priv->rx_next > AT91_MB_RX_LOW_LAST &&
- quota > 0 && mb > AT91_MB_RX_LAST) {
- priv->rx_next = AT91_MB_RX_FIRST;
+ if (priv->rx_next > get_mb_rx_low_last(priv) &&
+ quota > 0 && mb > get_mb_rx_last(priv)) {
+ priv->rx_next = get_mb_rx_first(priv);
goto again;
}
@@ -720,7 +813,7 @@
u32 reg_sr = at91_read(priv, AT91_SR);
int work_done = 0;
- if (reg_sr & AT91_IRQ_MB_RX)
+ if (reg_sr & get_irq_mb_rx(priv))
work_done += at91_poll_rx(dev, quota - work_done);
/*
@@ -734,7 +827,7 @@
if (work_done < quota) {
/* enable IRQs for frame errors and all mailboxes >= rx_next */
u32 reg_ier = AT91_IRQ_ERR_FRAME;
- reg_ier |= AT91_IRQ_MB_RX & ~AT91_MB_RX_MASK(priv->rx_next);
+ reg_ier |= get_irq_mb_rx(priv) & ~AT91_MB_MASK(priv->rx_next);
napi_complete(napi);
at91_write(priv, AT91_IER, reg_ier);
@@ -783,7 +876,7 @@
if (likely(reg_msr & AT91_MSR_MRDY &&
~reg_msr & AT91_MSR_MABT)) {
/* _NOTE_: subtract AT91_MB_TX_FIRST offset from mb! */
- can_get_echo_skb(dev, mb - AT91_MB_TX_FIRST);
+ can_get_echo_skb(dev, mb - get_mb_tx_first(priv));
dev->stats.tx_packets++;
}
}
@@ -793,8 +886,8 @@
* we get a TX int for the last can frame directly before a
* wrap around.
*/
- if ((priv->tx_next & AT91_NEXT_MASK) != 0 ||
- (priv->tx_echo & AT91_NEXT_MASK) == 0)
+ if ((priv->tx_next & get_next_mask(priv)) != 0 ||
+ (priv->tx_echo & get_next_mask(priv)) == 0)
netif_wake_queue(dev);
}
@@ -906,6 +999,29 @@
at91_write(priv, AT91_IER, reg_ier);
}
+static int at91_get_state_by_bec(const struct net_device *dev,
+ enum can_state *state)
+{
+ struct can_berr_counter bec;
+ int err;
+
+ err = at91_get_berr_counter(dev, &bec);
+ if (err)
+ return err;
+
+ if (bec.txerr < 96 && bec.rxerr < 96)
+ *state = CAN_STATE_ERROR_ACTIVE;
+ else if (bec.txerr < 128 && bec.rxerr < 128)
+ *state = CAN_STATE_ERROR_WARNING;
+ else if (bec.txerr < 256 && bec.rxerr < 256)
+ *state = CAN_STATE_ERROR_PASSIVE;
+ else
+ *state = CAN_STATE_BUS_OFF;
+
+ return 0;
+}
+
+
static void at91_irq_err(struct net_device *dev)
{
struct at91_priv *priv = netdev_priv(dev);
@@ -913,21 +1029,28 @@
struct can_frame *cf;
enum can_state new_state;
u32 reg_sr;
+ int err;
- reg_sr = at91_read(priv, AT91_SR);
+ if (at91_is_sam9263(priv)) {
+ reg_sr = at91_read(priv, AT91_SR);
- /* we need to look at the unmasked reg_sr */
- if (unlikely(reg_sr & AT91_IRQ_BOFF))
- new_state = CAN_STATE_BUS_OFF;
- else if (unlikely(reg_sr & AT91_IRQ_ERRP))
- new_state = CAN_STATE_ERROR_PASSIVE;
- else if (unlikely(reg_sr & AT91_IRQ_WARN))
- new_state = CAN_STATE_ERROR_WARNING;
- else if (likely(reg_sr & AT91_IRQ_ERRA))
- new_state = CAN_STATE_ERROR_ACTIVE;
- else {
- netdev_err(dev, "BUG! hardware in undefined state\n");
- return;
+ /* we need to look at the unmasked reg_sr */
+ if (unlikely(reg_sr & AT91_IRQ_BOFF))
+ new_state = CAN_STATE_BUS_OFF;
+ else if (unlikely(reg_sr & AT91_IRQ_ERRP))
+ new_state = CAN_STATE_ERROR_PASSIVE;
+ else if (unlikely(reg_sr & AT91_IRQ_WARN))
+ new_state = CAN_STATE_ERROR_WARNING;
+ else if (likely(reg_sr & AT91_IRQ_ERRA))
+ new_state = CAN_STATE_ERROR_ACTIVE;
+ else {
+ netdev_err(dev, "BUG! hardware in undefined state\n");
+ return;
+ }
+ } else {
+ err = at91_get_state_by_bec(dev, &new_state);
+ if (err)
+ return;
}
/* state hasn't changed */
@@ -968,19 +1091,19 @@
handled = IRQ_HANDLED;
/* Receive or error interrupt? -> napi */
- if (reg_sr & (AT91_IRQ_MB_RX | AT91_IRQ_ERR_FRAME)) {
+ if (reg_sr & (get_irq_mb_rx(priv) | AT91_IRQ_ERR_FRAME)) {
/*
* The error bits are clear on read,
* save for later use.
*/
priv->reg_sr = reg_sr;
at91_write(priv, AT91_IDR,
- AT91_IRQ_MB_RX | AT91_IRQ_ERR_FRAME);
+ get_irq_mb_rx(priv) | AT91_IRQ_ERR_FRAME);
napi_schedule(&priv->napi);
}
/* Transmission complete interrupt */
- if (reg_sr & AT91_IRQ_MB_TX)
+ if (reg_sr & get_irq_mb_tx(priv))
at91_irq_tx(dev, reg_sr);
at91_irq_err(dev);
@@ -1123,6 +1246,8 @@
static int __devinit at91_can_probe(struct platform_device *pdev)
{
+ const struct at91_devtype_data *devtype_data;
+ enum at91_devtype devtype;
struct net_device *dev;
struct at91_priv *priv;
struct resource *res;
@@ -1130,6 +1255,9 @@
void __iomem *addr;
int err, irq;
+ devtype = pdev->id_entry->driver_data;
+ devtype_data = &at91_devtype_data[devtype];
+
clk = clk_get(&pdev->dev, "can_clk");
if (IS_ERR(clk)) {
dev_err(&pdev->dev, "no clock defined\n");
@@ -1157,7 +1285,8 @@
goto exit_release;
}
- dev = alloc_candev(sizeof(struct at91_priv), AT91_MB_TX_NUM);
+ dev = alloc_candev(sizeof(struct at91_priv),
+ 1 << devtype_data->tx_shift);
if (!dev) {
err = -ENOMEM;
goto exit_iounmap;
@@ -1166,7 +1295,6 @@
dev->netdev_ops = &at91_netdev_ops;
dev->irq = irq;
dev->flags |= IFF_ECHO;
- dev->sysfs_groups[0] = &at91_sysfs_attr_group;
priv = netdev_priv(dev);
priv->can.clock.freq = clk_get_rate(clk);
@@ -1174,13 +1302,18 @@
priv->can.do_set_mode = at91_set_mode;
priv->can.do_get_berr_counter = at91_get_berr_counter;
priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES;
- priv->reg_base = addr;
priv->dev = dev;
+ priv->reg_base = addr;
+ priv->devtype_data = *devtype_data;
+ priv->devtype_data.type = devtype;
priv->clk = clk;
priv->pdata = pdev->dev.platform_data;
priv->mb0_id = 0x7ff;
- netif_napi_add(dev, &priv->napi, at91_poll, AT91_NAPI_WEIGHT);
+ netif_napi_add(dev, &priv->napi, at91_poll, get_mb_rx_num(priv));
+
+ if (at91_is_sam9263(priv))
+ dev->sysfs_groups[0] = &at91_sysfs_attr_group;
dev_set_drvdata(&pdev->dev, dev);
SET_NETDEV_DEV(dev, &pdev->dev);
@@ -1230,13 +1363,26 @@
return 0;
}
+static const struct platform_device_id at91_can_id_table[] = {
+ {
+ .name = "at91_can",
+ .driver_data = AT91_DEVTYPE_SAM9263,
+ }, {
+ .name = "at91sam9x5_can",
+ .driver_data = AT91_DEVTYPE_SAM9X5,
+ }, {
+ /* sentinel */
+ }
+};
+
static struct platform_driver at91_can_driver = {
- .probe = at91_can_probe,
- .remove = __devexit_p(at91_can_remove),
- .driver = {
- .name = KBUILD_MODNAME,
- .owner = THIS_MODULE,
+ .probe = at91_can_probe,
+ .remove = __devexit_p(at91_can_remove),
+ .driver = {
+ .name = KBUILD_MODNAME,
+ .owner = THIS_MODULE,
},
+ .id_table = at91_can_id_table,
};
static int __init at91_can_module_init(void)
diff --git a/drivers/net/can/bfin_can.c b/drivers/net/can/bfin_can.c
index b6e890d..a1c5abc 100644
--- a/drivers/net/can/bfin_can.c
+++ b/drivers/net/can/bfin_can.c
@@ -79,8 +79,8 @@
if (priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES)
timing |= SAM;
- bfin_write16(®->clock, clk);
- bfin_write16(®->timing, timing);
+ bfin_write(®->clock, clk);
+ bfin_write(®->timing, timing);
dev_info(dev->dev.parent, "setting CLOCK=0x%04x TIMING=0x%04x\n",
clk, timing);
@@ -96,16 +96,16 @@
int i;
/* disable interrupts */
- bfin_write16(®->mbim1, 0);
- bfin_write16(®->mbim2, 0);
- bfin_write16(®->gim, 0);
+ bfin_write(®->mbim1, 0);
+ bfin_write(®->mbim2, 0);
+ bfin_write(®->gim, 0);
/* reset can and enter configuration mode */
- bfin_write16(®->control, SRS | CCR);
+ bfin_write(®->control, SRS | CCR);
SSYNC();
- bfin_write16(®->control, CCR);
+ bfin_write(®->control, CCR);
SSYNC();
- while (!(bfin_read16(®->control) & CCA)) {
+ while (!(bfin_read(®->control) & CCA)) {
udelay(10);
if (--timeout == 0) {
dev_err(dev->dev.parent,
@@ -119,33 +119,33 @@
* by writing to CAN Mailbox Configuration Registers 1 and 2
* For all bits: 0 - Mailbox disabled, 1 - Mailbox enabled
*/
- bfin_write16(®->mc1, 0);
- bfin_write16(®->mc2, 0);
+ bfin_write(®->mc1, 0);
+ bfin_write(®->mc2, 0);
/* Set Mailbox Direction */
- bfin_write16(®->md1, 0xFFFF); /* mailbox 1-16 are RX */
- bfin_write16(®->md2, 0); /* mailbox 17-32 are TX */
+ bfin_write(®->md1, 0xFFFF); /* mailbox 1-16 are RX */
+ bfin_write(®->md2, 0); /* mailbox 17-32 are TX */
/* RECEIVE_STD_CHL */
for (i = 0; i < 2; i++) {
- bfin_write16(®->chl[RECEIVE_STD_CHL + i].id0, 0);
- bfin_write16(®->chl[RECEIVE_STD_CHL + i].id1, AME);
- bfin_write16(®->chl[RECEIVE_STD_CHL + i].dlc, 0);
- bfin_write16(®->msk[RECEIVE_STD_CHL + i].amh, 0x1FFF);
- bfin_write16(®->msk[RECEIVE_STD_CHL + i].aml, 0xFFFF);
+ bfin_write(®->chl[RECEIVE_STD_CHL + i].id0, 0);
+ bfin_write(®->chl[RECEIVE_STD_CHL + i].id1, AME);
+ bfin_write(®->chl[RECEIVE_STD_CHL + i].dlc, 0);
+ bfin_write(®->msk[RECEIVE_STD_CHL + i].amh, 0x1FFF);
+ bfin_write(®->msk[RECEIVE_STD_CHL + i].aml, 0xFFFF);
}
/* RECEIVE_EXT_CHL */
for (i = 0; i < 2; i++) {
- bfin_write16(®->chl[RECEIVE_EXT_CHL + i].id0, 0);
- bfin_write16(®->chl[RECEIVE_EXT_CHL + i].id1, AME | IDE);
- bfin_write16(®->chl[RECEIVE_EXT_CHL + i].dlc, 0);
- bfin_write16(®->msk[RECEIVE_EXT_CHL + i].amh, 0x1FFF);
- bfin_write16(®->msk[RECEIVE_EXT_CHL + i].aml, 0xFFFF);
+ bfin_write(®->chl[RECEIVE_EXT_CHL + i].id0, 0);
+ bfin_write(®->chl[RECEIVE_EXT_CHL + i].id1, AME | IDE);
+ bfin_write(®->chl[RECEIVE_EXT_CHL + i].dlc, 0);
+ bfin_write(®->msk[RECEIVE_EXT_CHL + i].amh, 0x1FFF);
+ bfin_write(®->msk[RECEIVE_EXT_CHL + i].aml, 0xFFFF);
}
- bfin_write16(®->mc2, BIT(TRANSMIT_CHL - 16));
- bfin_write16(®->mc1, BIT(RECEIVE_STD_CHL) + BIT(RECEIVE_EXT_CHL));
+ bfin_write(®->mc2, BIT(TRANSMIT_CHL - 16));
+ bfin_write(®->mc1, BIT(RECEIVE_STD_CHL) + BIT(RECEIVE_EXT_CHL));
SSYNC();
priv->can.state = CAN_STATE_STOPPED;
@@ -160,9 +160,9 @@
/*
* leave configuration mode
*/
- bfin_write16(®->control, bfin_read16(®->control) & ~CCR);
+ bfin_write(®->control, bfin_read(®->control) & ~CCR);
- while (bfin_read16(®->status) & CCA) {
+ while (bfin_read(®->status) & CCA) {
udelay(10);
if (--timeout == 0) {
dev_err(dev->dev.parent,
@@ -174,25 +174,25 @@
/*
* clear _All_ tx and rx interrupts
*/
- bfin_write16(®->mbtif1, 0xFFFF);
- bfin_write16(®->mbtif2, 0xFFFF);
- bfin_write16(®->mbrif1, 0xFFFF);
- bfin_write16(®->mbrif2, 0xFFFF);
+ bfin_write(®->mbtif1, 0xFFFF);
+ bfin_write(®->mbtif2, 0xFFFF);
+ bfin_write(®->mbrif1, 0xFFFF);
+ bfin_write(®->mbrif2, 0xFFFF);
/*
* clear global interrupt status register
*/
- bfin_write16(®->gis, 0x7FF); /* overwrites with '1' */
+ bfin_write(®->gis, 0x7FF); /* overwrites with '1' */
/*
* Initialize Interrupts
* - set bits in the mailbox interrupt mask register
* - global interrupt mask
*/
- bfin_write16(®->mbim1, BIT(RECEIVE_STD_CHL) + BIT(RECEIVE_EXT_CHL));
- bfin_write16(®->mbim2, BIT(TRANSMIT_CHL - 16));
+ bfin_write(®->mbim1, BIT(RECEIVE_STD_CHL) + BIT(RECEIVE_EXT_CHL));
+ bfin_write(®->mbim2, BIT(TRANSMIT_CHL - 16));
- bfin_write16(®->gim, EPIM | BOIM | RMLIM);
+ bfin_write(®->gim, EPIM | BOIM | RMLIM);
SSYNC();
}
@@ -242,37 +242,28 @@
/* fill id */
if (id & CAN_EFF_FLAG) {
- bfin_write16(®->chl[TRANSMIT_CHL].id0, id);
- if (id & CAN_RTR_FLAG)
- writew(((id & 0x1FFF0000) >> 16) | IDE | AME | RTR,
- ®->chl[TRANSMIT_CHL].id1);
- else
- writew(((id & 0x1FFF0000) >> 16) | IDE | AME,
- ®->chl[TRANSMIT_CHL].id1);
-
- } else {
- if (id & CAN_RTR_FLAG)
- writew((id << 2) | AME | RTR,
- ®->chl[TRANSMIT_CHL].id1);
- else
- bfin_write16(®->chl[TRANSMIT_CHL].id1,
- (id << 2) | AME);
- }
+ bfin_write(®->chl[TRANSMIT_CHL].id0, id);
+ val = ((id & 0x1FFF0000) >> 16) | IDE;
+ } else
+ val = (id << 2);
+ if (id & CAN_RTR_FLAG)
+ val |= RTR;
+ bfin_write(®->chl[TRANSMIT_CHL].id1, val | AME);
/* fill payload */
for (i = 0; i < 8; i += 2) {
val = ((7 - i) < dlc ? (data[7 - i]) : 0) +
((6 - i) < dlc ? (data[6 - i] << 8) : 0);
- bfin_write16(®->chl[TRANSMIT_CHL].data[i], val);
+ bfin_write(®->chl[TRANSMIT_CHL].data[i], val);
}
/* fill data length code */
- bfin_write16(®->chl[TRANSMIT_CHL].dlc, dlc);
+ bfin_write(®->chl[TRANSMIT_CHL].dlc, dlc);
can_put_echo_skb(skb, dev, 0);
/* set transmit request */
- bfin_write16(®->trs2, BIT(TRANSMIT_CHL - 16));
+ bfin_write(®->trs2, BIT(TRANSMIT_CHL - 16));
return 0;
}
@@ -295,26 +286,26 @@
/* get id */
if (isrc & BIT(RECEIVE_EXT_CHL)) {
/* extended frame format (EFF) */
- cf->can_id = ((bfin_read16(®->chl[RECEIVE_EXT_CHL].id1)
+ cf->can_id = ((bfin_read(®->chl[RECEIVE_EXT_CHL].id1)
& 0x1FFF) << 16)
- + bfin_read16(®->chl[RECEIVE_EXT_CHL].id0);
+ + bfin_read(®->chl[RECEIVE_EXT_CHL].id0);
cf->can_id |= CAN_EFF_FLAG;
obj = RECEIVE_EXT_CHL;
} else {
/* standard frame format (SFF) */
- cf->can_id = (bfin_read16(®->chl[RECEIVE_STD_CHL].id1)
+ cf->can_id = (bfin_read(®->chl[RECEIVE_STD_CHL].id1)
& 0x1ffc) >> 2;
obj = RECEIVE_STD_CHL;
}
- if (bfin_read16(®->chl[obj].id1) & RTR)
+ if (bfin_read(®->chl[obj].id1) & RTR)
cf->can_id |= CAN_RTR_FLAG;
/* get data length code */
- cf->can_dlc = get_can_dlc(bfin_read16(®->chl[obj].dlc) & 0xF);
+ cf->can_dlc = get_can_dlc(bfin_read(®->chl[obj].dlc) & 0xF);
/* get payload */
for (i = 0; i < 8; i += 2) {
- val = bfin_read16(®->chl[obj].data[i]);
+ val = bfin_read(®->chl[obj].data[i]);
cf->data[7 - i] = (7 - i) < cf->can_dlc ? val : 0;
cf->data[6 - i] = (6 - i) < cf->can_dlc ? (val >> 8) : 0;
}
@@ -368,7 +359,7 @@
if (state != priv->can.state && (state == CAN_STATE_ERROR_WARNING ||
state == CAN_STATE_ERROR_PASSIVE)) {
- u16 cec = bfin_read16(®->cec);
+ u16 cec = bfin_read(®->cec);
u8 rxerr = cec;
u8 txerr = cec >> 8;
@@ -419,23 +410,23 @@
struct net_device_stats *stats = &dev->stats;
u16 status, isrc;
- if ((irq == priv->tx_irq) && bfin_read16(®->mbtif2)) {
+ if ((irq == priv->tx_irq) && bfin_read(®->mbtif2)) {
/* transmission complete interrupt */
- bfin_write16(®->mbtif2, 0xFFFF);
+ bfin_write(®->mbtif2, 0xFFFF);
stats->tx_packets++;
- stats->tx_bytes += bfin_read16(®->chl[TRANSMIT_CHL].dlc);
+ stats->tx_bytes += bfin_read(®->chl[TRANSMIT_CHL].dlc);
can_get_echo_skb(dev, 0);
netif_wake_queue(dev);
- } else if ((irq == priv->rx_irq) && bfin_read16(®->mbrif1)) {
+ } else if ((irq == priv->rx_irq) && bfin_read(®->mbrif1)) {
/* receive interrupt */
- isrc = bfin_read16(®->mbrif1);
- bfin_write16(®->mbrif1, 0xFFFF);
+ isrc = bfin_read(®->mbrif1);
+ bfin_write(®->mbrif1, 0xFFFF);
bfin_can_rx(dev, isrc);
- } else if ((irq == priv->err_irq) && bfin_read16(®->gis)) {
+ } else if ((irq == priv->err_irq) && bfin_read(®->gis)) {
/* error interrupt */
- isrc = bfin_read16(®->gis);
- status = bfin_read16(®->esr);
- bfin_write16(®->gis, 0x7FF);
+ isrc = bfin_read(®->gis);
+ status = bfin_read(®->esr);
+ bfin_write(®->gis, 0x7FF);
bfin_can_err(dev, isrc, status);
} else {
return IRQ_NONE;
@@ -640,9 +631,9 @@
if (netif_running(dev)) {
/* enter sleep mode */
- bfin_write16(®->control, bfin_read16(®->control) | SMR);
+ bfin_write(®->control, bfin_read(®->control) | SMR);
SSYNC();
- while (!(bfin_read16(®->intr) & SMACK)) {
+ while (!(bfin_read(®->intr) & SMACK)) {
udelay(10);
if (--timeout == 0) {
dev_err(dev->dev.parent,
@@ -663,7 +654,7 @@
if (netif_running(dev)) {
/* leave sleep mode */
- bfin_write16(®->intr, 0);
+ bfin_write(®->intr, 0);
SSYNC();
}
diff --git a/drivers/net/can/c_can/c_can.c b/drivers/net/can/c_can/c_can.c
index 7e5cc0b..80adc83 100644
--- a/drivers/net/can/c_can/c_can.c
+++ b/drivers/net/can/c_can/c_can.c
@@ -26,7 +26,6 @@
*/
#include <linux/kernel.h>
-#include <linux/version.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
diff --git a/drivers/net/can/c_can/c_can_platform.c b/drivers/net/can/c_can/c_can_platform.c
index cc90824..0e300cf 100644
--- a/drivers/net/can/c_can/c_can_platform.c
+++ b/drivers/net/can/c_can/c_can_platform.c
@@ -20,7 +20,6 @@
*/
#include <linux/kernel.h>
-#include <linux/version.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
diff --git a/drivers/net/can/janz-ican3.c b/drivers/net/can/janz-ican3.c
index f1942ca..32778d5 100644
--- a/drivers/net/can/janz-ican3.c
+++ b/drivers/net/can/janz-ican3.c
@@ -22,6 +22,7 @@
#include <linux/can/error.h>
#include <linux/mfd/janz.h>
+#include <asm/io.h>
/* the DPM has 64k of memory, organized into 256x 256 byte pages */
#define DPM_NUM_PAGES 256
diff --git a/drivers/net/can/sja1000/sja1000.h b/drivers/net/can/sja1000/sja1000.h
index de8e778..78bd4ec 100644
--- a/drivers/net/can/sja1000/sja1000.h
+++ b/drivers/net/can/sja1000/sja1000.h
@@ -47,6 +47,7 @@
#ifndef SJA1000_DEV_H
#define SJA1000_DEV_H
+#include <linux/irqreturn.h>
#include <linux/can/dev.h>
#include <linux/can/platform/sja1000.h>
diff --git a/drivers/net/can/sja1000/sja1000_of_platform.c b/drivers/net/can/sja1000/sja1000_of_platform.c
index 9793df6..cee6ba2 100644
--- a/drivers/net/can/sja1000/sja1000_of_platform.c
+++ b/drivers/net/can/sja1000/sja1000_of_platform.c
@@ -38,6 +38,7 @@
#include <linux/interrupt.h>
#include <linux/netdevice.h>
#include <linux/delay.h>
+#include <linux/io.h>
#include <linux/can/dev.h>
#include <linux/of_platform.h>
diff --git a/drivers/net/can/softing/softing_fw.c b/drivers/net/can/softing/softing_fw.c
index b520784..3105961 100644
--- a/drivers/net/can/softing/softing_fw.c
+++ b/drivers/net/can/softing/softing_fw.c
@@ -20,6 +20,7 @@
#include <linux/firmware.h>
#include <linux/sched.h>
#include <asm/div64.h>
+#include <asm/io.h>
#include "softing.h"
diff --git a/drivers/net/can/softing/softing_main.c b/drivers/net/can/softing/softing_main.c
index 60a49e5..a79925e 100644
--- a/drivers/net/can/softing/softing_main.c
+++ b/drivers/net/can/softing/softing_main.c
@@ -17,10 +17,10 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include <linux/version.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/interrupt.h>
+#include <asm/io.h>
#include "softing.h"
diff --git a/drivers/net/cassini.c b/drivers/net/cassini.c
index 22ce03e..b414f5a 100644
--- a/drivers/net/cassini.c
+++ b/drivers/net/cassini.c
@@ -75,6 +75,7 @@
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/vmalloc.h>
#include <linux/ioport.h>
#include <linux/pci.h>
diff --git a/drivers/net/cnic.c b/drivers/net/cnic.c
index 11a92af..5533b15 100644
--- a/drivers/net/cnic.c
+++ b/drivers/net/cnic.c
@@ -1,6 +1,6 @@
/* cnic.c: Broadcom CNIC core network driver.
*
- * Copyright (c) 2006-2010 Broadcom Corporation
+ * Copyright (c) 2006-2011 Broadcom Corporation
*
* 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
@@ -605,11 +605,12 @@
}
EXPORT_SYMBOL(cnic_unregister_driver);
-static int cnic_init_id_tbl(struct cnic_id_tbl *id_tbl, u32 size, u32 start_id)
+static int cnic_init_id_tbl(struct cnic_id_tbl *id_tbl, u32 size, u32 start_id,
+ u32 next)
{
id_tbl->start = start_id;
id_tbl->max = size;
- id_tbl->next = 0;
+ id_tbl->next = next;
spin_lock_init(&id_tbl->lock);
id_tbl->table = kzalloc(DIV_ROUND_UP(size, 32) * 4, GFP_KERNEL);
if (!id_tbl->table)
@@ -835,7 +836,6 @@
cp->ctx_blks = 0;
cnic_free_dma(dev, &cp->gbl_buf_info);
- cnic_free_dma(dev, &cp->conn_buf_info);
cnic_free_dma(dev, &cp->kwq_info);
cnic_free_dma(dev, &cp->kwq_16_data_info);
cnic_free_dma(dev, &cp->kcq2.dma);
@@ -899,24 +899,56 @@
return 0;
}
-static int cnic_alloc_kcq(struct cnic_dev *dev, struct kcq_info *info)
+static u16 cnic_bnx2_next_idx(u16 idx)
{
- int err, i, is_bnx2 = 0;
+ return idx + 1;
+}
+
+static u16 cnic_bnx2_hw_idx(u16 idx)
+{
+ return idx;
+}
+
+static u16 cnic_bnx2x_next_idx(u16 idx)
+{
+ idx++;
+ if ((idx & MAX_KCQE_CNT) == MAX_KCQE_CNT)
+ idx++;
+
+ return idx;
+}
+
+static u16 cnic_bnx2x_hw_idx(u16 idx)
+{
+ if ((idx & MAX_KCQE_CNT) == MAX_KCQE_CNT)
+ idx++;
+ return idx;
+}
+
+static int cnic_alloc_kcq(struct cnic_dev *dev, struct kcq_info *info,
+ bool use_pg_tbl)
+{
+ int err, i, use_page_tbl = 0;
struct kcqe **kcq;
- if (test_bit(CNIC_F_BNX2_CLASS, &dev->flags))
- is_bnx2 = 1;
+ if (use_pg_tbl)
+ use_page_tbl = 1;
- err = cnic_alloc_dma(dev, &info->dma, KCQ_PAGE_CNT, is_bnx2);
+ err = cnic_alloc_dma(dev, &info->dma, KCQ_PAGE_CNT, use_page_tbl);
if (err)
return err;
kcq = (struct kcqe **) info->dma.pg_arr;
info->kcq = kcq;
- if (is_bnx2)
+ info->next_idx = cnic_bnx2_next_idx;
+ info->hw_idx = cnic_bnx2_hw_idx;
+ if (use_pg_tbl)
return 0;
+ info->next_idx = cnic_bnx2x_next_idx;
+ info->hw_idx = cnic_bnx2x_hw_idx;
+
for (i = 0; i < KCQ_PAGE_CNT; i++) {
struct bnx2x_bd_chain_next *next =
(struct bnx2x_bd_chain_next *) &kcq[i][MAX_KCQE_CNT];
@@ -1059,7 +1091,7 @@
goto error;
cp->kwq = (struct kwqe **) cp->kwq_info.pg_arr;
- ret = cnic_alloc_kcq(dev, &cp->kcq1);
+ ret = cnic_alloc_kcq(dev, &cp->kcq1, true);
if (ret)
goto error;
@@ -1143,7 +1175,7 @@
cp->iscsi_start_cid = start_cid;
cp->fcoe_start_cid = start_cid + MAX_ISCSI_TBL_SZ;
- if (BNX2X_CHIP_IS_E2(cp->chip_id)) {
+ if (BNX2X_CHIP_IS_E2_PLUS(cp->chip_id)) {
cp->max_cid_space += BNX2X_FCOE_NUM_CONNECTIONS;
cp->fcoe_init_cid = ethdev->fcoe_init_cid;
if (!cp->fcoe_init_cid)
@@ -1195,22 +1227,16 @@
j++;
}
- ret = cnic_alloc_kcq(dev, &cp->kcq1);
+ ret = cnic_alloc_kcq(dev, &cp->kcq1, false);
if (ret)
goto error;
- if (BNX2X_CHIP_IS_E2(cp->chip_id)) {
- ret = cnic_alloc_kcq(dev, &cp->kcq2);
+ if (BNX2X_CHIP_IS_E2_PLUS(cp->chip_id)) {
+ ret = cnic_alloc_kcq(dev, &cp->kcq2, true);
if (ret)
goto error;
}
- pages = PAGE_ALIGN(BNX2X_ISCSI_NUM_CONNECTIONS *
- BNX2X_ISCSI_CONN_BUF_SIZE) / PAGE_SIZE;
- ret = cnic_alloc_dma(dev, &cp->conn_buf_info, pages, 1);
- if (ret)
- goto error;
-
pages = PAGE_ALIGN(BNX2X_ISCSI_GLB_BUF_SIZE) / PAGE_SIZE;
ret = cnic_alloc_dma(dev, &cp->gbl_buf_info, pages, 0);
if (ret)
@@ -1577,6 +1603,7 @@
struct iscsi_context *ictx;
struct regpair context_addr;
int i, j, n = 2, n_max;
+ u8 port = CNIC_PORT(cp);
ctx->ctx_flags = 0;
if (!req2->num_additional_wqes)
@@ -1628,6 +1655,17 @@
XSTORM_ISCSI_CONTEXT_FLAGS_B_IMMEDIATE_DATA;
ictx->xstorm_st_context.iscsi.flags.flags |=
XSTORM_ISCSI_CONTEXT_FLAGS_B_INITIAL_R2T;
+ ictx->xstorm_st_context.common.ethernet.reserved_vlan_type =
+ ETH_P_8021Q;
+ if (BNX2X_CHIP_IS_E2_PLUS(cp->chip_id) &&
+ cp->port_mode == CHIP_2_PORT_MODE) {
+
+ port = 0;
+ }
+ ictx->xstorm_st_context.common.flags =
+ 1 << XSTORM_COMMON_CONTEXT_SECTION_PHYSQ_INITIALIZED_SHIFT;
+ ictx->xstorm_st_context.common.flags =
+ port << XSTORM_COMMON_CONTEXT_SECTION_PBF_PORT_SHIFT;
ictx->tstorm_st_context.iscsi.hdr_bytes_2_fetch = ISCSI_HEADER_SIZE;
/* TSTORM requires the base address of RQ DB & not PTE */
@@ -1843,8 +1881,11 @@
ret = cnic_submit_kwqe_16(dev, RAMROD_CMD_ID_COMMON_CFC_DEL,
hw_cid, NONE_CONNECTION_TYPE, &l5_data);
- if (ret == 0)
+ if (ret == 0) {
wait_event(ctx->waitq, ctx->wait_cond);
+ if (unlikely(test_bit(CTX_FL_CID_ERROR, &ctx->ctx_flags)))
+ return -EBUSY;
+ }
return ret;
}
@@ -1879,8 +1920,10 @@
skip_cfc_delete:
cnic_free_bnx2x_conn_resc(dev, l5_cid);
- atomic_dec(&cp->iscsi_conn);
- clear_bit(CTX_FL_OFFLD_START, &ctx->ctx_flags);
+ if (!ret) {
+ atomic_dec(&cp->iscsi_conn);
+ clear_bit(CTX_FL_OFFLD_START, &ctx->ctx_flags);
+ }
destroy_reply:
memset(&kcqe, 0, sizeof(kcqe));
@@ -1939,8 +1982,6 @@
tstorm_buf->ka_interval = kwqe3->ka_interval;
tstorm_buf->ka_max_probe_count = kwqe3->ka_max_probe_count;
}
- tstorm_buf->rcv_buf = kwqe3->rcv_buf;
- tstorm_buf->snd_buf = kwqe3->snd_buf;
tstorm_buf->max_rt_time = 0xffffffff;
}
@@ -1969,15 +2010,14 @@
TSTORM_ISCSI_TCP_VARS_LSB_LOCAL_MAC_ADDR_OFFSET(pfid) + 1,
mac[4]);
CNIC_WR8(dev, BAR_TSTRORM_INTMEM +
- TSTORM_ISCSI_TCP_VARS_MSB_LOCAL_MAC_ADDR_OFFSET(pfid), mac[3]);
+ TSTORM_ISCSI_TCP_VARS_MID_LOCAL_MAC_ADDR_OFFSET(pfid), mac[3]);
CNIC_WR8(dev, BAR_TSTRORM_INTMEM +
- TSTORM_ISCSI_TCP_VARS_MSB_LOCAL_MAC_ADDR_OFFSET(pfid) + 1,
+ TSTORM_ISCSI_TCP_VARS_MID_LOCAL_MAC_ADDR_OFFSET(pfid) + 1,
mac[2]);
CNIC_WR8(dev, BAR_TSTRORM_INTMEM +
- TSTORM_ISCSI_TCP_VARS_MSB_LOCAL_MAC_ADDR_OFFSET(pfid) + 2,
- mac[1]);
+ TSTORM_ISCSI_TCP_VARS_MSB_LOCAL_MAC_ADDR_OFFSET(pfid), mac[1]);
CNIC_WR8(dev, BAR_TSTRORM_INTMEM +
- TSTORM_ISCSI_TCP_VARS_MSB_LOCAL_MAC_ADDR_OFFSET(pfid) + 3,
+ TSTORM_ISCSI_TCP_VARS_MSB_LOCAL_MAC_ADDR_OFFSET(pfid) + 1,
mac[0]);
}
@@ -2156,7 +2196,7 @@
memset(fcoe_stat, 0, sizeof(*fcoe_stat));
memcpy(&fcoe_stat->stat_kwqe, req, sizeof(*req));
- ret = cnic_submit_kwqe_16(dev, FCOE_RAMROD_CMD_ID_STAT, cid,
+ ret = cnic_submit_kwqe_16(dev, FCOE_RAMROD_CMD_ID_STAT_FUNC, cid,
FCOE_CONNECTION_TYPE, &l5_data);
return ret;
}
@@ -2201,12 +2241,9 @@
memcpy(&fcoe_init->init_kwqe1, req1, sizeof(*req1));
memcpy(&fcoe_init->init_kwqe2, req2, sizeof(*req2));
memcpy(&fcoe_init->init_kwqe3, req3, sizeof(*req3));
- fcoe_init->eq_addr.lo = cp->kcq2.dma.pg_map_arr[0] & 0xffffffff;
- fcoe_init->eq_addr.hi = (u64) cp->kcq2.dma.pg_map_arr[0] >> 32;
- fcoe_init->eq_next_page_addr.lo =
- cp->kcq2.dma.pg_map_arr[1] & 0xffffffff;
- fcoe_init->eq_next_page_addr.hi =
- (u64) cp->kcq2.dma.pg_map_arr[1] >> 32;
+ fcoe_init->eq_pbl_base.lo = cp->kcq2.dma.pgtbl_map & 0xffffffff;
+ fcoe_init->eq_pbl_base.hi = (u64) cp->kcq2.dma.pgtbl_map >> 32;
+ fcoe_init->eq_pbl_size = cp->kcq2.dma.num_pages;
fcoe_init->sb_num = cp->status_blk_num;
fcoe_init->eq_prod = MAX_KCQ_IDX;
@@ -2214,7 +2251,7 @@
cp->kcq2.sw_prod_idx = 0;
cid = BNX2X_HW_CID(cp, cp->fcoe_init_cid);
- ret = cnic_submit_kwqe_16(dev, FCOE_RAMROD_CMD_ID_INIT, cid,
+ ret = cnic_submit_kwqe_16(dev, FCOE_RAMROD_CMD_ID_INIT_FUNC, cid,
FCOE_CONNECTION_TYPE, &l5_data);
*work = 3;
return ret;
@@ -2430,7 +2467,7 @@
cid = BNX2X_HW_CID(cp, cp->fcoe_init_cid);
memset(&l5_data, 0, sizeof(l5_data));
- ret = cnic_submit_kwqe_16(dev, FCOE_RAMROD_CMD_ID_DESTROY, cid,
+ ret = cnic_submit_kwqe_16(dev, FCOE_RAMROD_CMD_ID_DESTROY_FUNC, cid,
FCOE_CONNECTION_TYPE, &l5_data);
return ret;
}
@@ -2511,7 +2548,7 @@
if (!test_bit(CNIC_F_CNIC_UP, &dev->flags))
return -EAGAIN; /* bnx2 is down */
- if (BNX2X_CHIP_NUM(cp->chip_id) == BNX2X_CHIP_NUM_57710)
+ if (!BNX2X_CHIP_IS_E2_PLUS(cp->chip_id))
return -EINVAL;
for (i = 0; i < num_wqes; ) {
@@ -2651,32 +2688,6 @@
cnic_spq_completion(dev, DRV_CTL_RET_L5_SPQ_CREDIT_CMD, comp);
}
-static u16 cnic_bnx2_next_idx(u16 idx)
-{
- return idx + 1;
-}
-
-static u16 cnic_bnx2_hw_idx(u16 idx)
-{
- return idx;
-}
-
-static u16 cnic_bnx2x_next_idx(u16 idx)
-{
- idx++;
- if ((idx & MAX_KCQE_CNT) == MAX_KCQE_CNT)
- idx++;
-
- return idx;
-}
-
-static u16 cnic_bnx2x_hw_idx(u16 idx)
-{
- if ((idx & MAX_KCQE_CNT) == MAX_KCQE_CNT)
- idx++;
- return idx;
-}
-
static int cnic_get_kcqes(struct cnic_dev *dev, struct kcq_info *info)
{
struct cnic_local *cp = dev->cnic_priv;
@@ -2687,12 +2698,12 @@
i = ri = last = info->sw_prod_idx;
ri &= MAX_KCQ_IDX;
hw_prod = *info->hw_prod_idx_ptr;
- hw_prod = cp->hw_idx(hw_prod);
+ hw_prod = info->hw_idx(hw_prod);
while ((i != hw_prod) && (kcqe_cnt < MAX_COMPLETED_KCQE)) {
kcqe = &info->kcq[KCQ_PG(ri)][KCQ_IDX(ri)];
cp->completed_kcq[kcqe_cnt++] = kcqe;
- i = cp->next_idx(i);
+ i = info->next_idx(i);
ri = i & MAX_KCQ_IDX;
if (likely(!(kcqe->kcqe_op_flag & KCQE_FLAGS_NEXT))) {
last_cnt = kcqe_cnt;
@@ -2778,13 +2789,10 @@
/* Tell compiler that status_blk fields can change. */
barrier();
- if (status_idx != *cp->kcq1.status_idx_ptr) {
- status_idx = (u16) *cp->kcq1.status_idx_ptr;
- /* status block index must be read first */
- rmb();
- cp->kwq_con_idx = *cp->kwq_con_idx_ptr;
- } else
- break;
+ status_idx = (u16) *cp->kcq1.status_idx_ptr;
+ /* status block index must be read first */
+ rmb();
+ cp->kwq_con_idx = *cp->kwq_con_idx_ptr;
}
CNIC_WR16(dev, cp->kcq1.io_addr, cp->kcq1.sw_prod_idx);
@@ -2908,8 +2916,6 @@
/* Tell compiler that sblk fields can change. */
barrier();
- if (last_status == *info->status_idx_ptr)
- break;
last_status = *info->status_idx_ptr;
/* status block index must be read before reading the KCQ */
@@ -2933,7 +2939,7 @@
CNIC_WR16(dev, cp->kcq1.io_addr,
cp->kcq1.sw_prod_idx + MAX_KCQ_IDX);
- if (!BNX2X_CHIP_IS_E2(cp->chip_id)) {
+ if (!BNX2X_CHIP_IS_E2_PLUS(cp->chip_id)) {
cnic_ack_bnx2x_int(dev, cp->bnx2x_igu_sb_id, USTORM_ID,
status_idx, IGU_INT_ENABLE, 1);
break;
@@ -3052,13 +3058,21 @@
break;
}
case CNIC_CTL_COMPLETION_CMD: {
- u32 cid = BNX2X_SW_CID(info->data.comp.cid);
+ struct cnic_ctl_completion *comp = &info->data.comp;
+ u32 cid = BNX2X_SW_CID(comp->cid);
u32 l5_cid;
struct cnic_local *cp = dev->cnic_priv;
if (cnic_get_l5_cid(cp, cid, &l5_cid) == 0) {
struct cnic_context *ctx = &cp->ctx_tbl[l5_cid];
+ if (unlikely(comp->error)) {
+ set_bit(CTX_FL_CID_ERROR, &ctx->ctx_flags);
+ netdev_err(dev->netdev,
+ "CID %x CFC delete comp error %x\n",
+ cid, comp->error);
+ }
+
ctx->wait_cond = 1;
wake_up(&ctx->waitq);
}
@@ -3772,7 +3786,13 @@
break;
case L4_KCQE_OPCODE_VALUE_CLOSE_RECEIVED:
- cnic_cm_upcall(cp, csk, opcode);
+ /* after we already sent CLOSE_REQ */
+ if (test_bit(CNIC_F_BNX2X_CLASS, &dev->flags) &&
+ !test_bit(SK_F_OFFLD_COMPLETE, &csk->flags) &&
+ csk->state == L4_KCQE_OPCODE_VALUE_CLOSE_COMP)
+ cp->close_conn(csk, L4_KCQE_OPCODE_VALUE_RESET_COMP);
+ else
+ cnic_cm_upcall(cp, csk, opcode);
break;
}
csk_put(csk);
@@ -3803,14 +3823,17 @@
static int cnic_cm_alloc_mem(struct cnic_dev *dev)
{
struct cnic_local *cp = dev->cnic_priv;
+ u32 port_id;
cp->csk_tbl = kzalloc(sizeof(struct cnic_sock) * MAX_CM_SK_TBL_SZ,
GFP_KERNEL);
if (!cp->csk_tbl)
return -ENOMEM;
+ get_random_bytes(&port_id, sizeof(port_id));
+ port_id %= CNIC_LOCAL_PORT_RANGE;
if (cnic_init_id_tbl(&cp->csk_port_tbl, CNIC_LOCAL_PORT_RANGE,
- CNIC_LOCAL_PORT_MIN)) {
+ CNIC_LOCAL_PORT_MIN, port_id)) {
cnic_cm_free_mem(dev);
return -ENOMEM;
}
@@ -3826,12 +3849,14 @@
}
/* 1. If event opcode matches the expected event in csk->state
- * 2. If the expected event is CLOSE_COMP, we accept any event
+ * 2. If the expected event is CLOSE_COMP or RESET_COMP, we accept any
+ * event
* 3. If the expected event is 0, meaning the connection was never
* never established, we accept the opcode from cm_abort.
*/
if (opcode == csk->state || csk->state == 0 ||
- csk->state == L4_KCQE_OPCODE_VALUE_CLOSE_COMP) {
+ csk->state == L4_KCQE_OPCODE_VALUE_CLOSE_COMP ||
+ csk->state == L4_KCQE_OPCODE_VALUE_RESET_COMP) {
if (!test_and_set_bit(SK_F_CLOSING, &csk->flags)) {
if (csk->state == 0)
csk->state = opcode;
@@ -3922,10 +3947,17 @@
for (i = 0; i < cp->max_cid_space; i++) {
struct cnic_context *ctx = &cp->ctx_tbl[i];
+ int j;
while (test_bit(CTX_FL_DELETE_WAIT, &ctx->ctx_flags))
msleep(10);
+ for (j = 0; j < 5; j++) {
+ if (!test_bit(CTX_FL_OFFLD_START, &ctx->ctx_flags))
+ break;
+ msleep(20);
+ }
+
if (test_bit(CTX_FL_OFFLD_START, &ctx->ctx_flags))
netdev_warn(dev->netdev, "CID %x not deleted\n",
ctx->cid);
@@ -3992,6 +4024,7 @@
for (i = 0; i < cp->max_cid_space; i++) {
struct cnic_context *ctx = &cp->ctx_tbl[i];
+ int err;
if (!test_bit(CTX_FL_OFFLD_START, &ctx->ctx_flags) ||
!test_bit(CTX_FL_DELETE_WAIT, &ctx->ctx_flags))
@@ -4005,13 +4038,15 @@
if (!test_and_clear_bit(CTX_FL_DELETE_WAIT, &ctx->ctx_flags))
continue;
- cnic_bnx2x_destroy_ramrod(dev, i);
+ err = cnic_bnx2x_destroy_ramrod(dev, i);
cnic_free_bnx2x_conn_resc(dev, i);
- if (ctx->ulp_proto_id == CNIC_ULP_ISCSI)
- atomic_dec(&cp->iscsi_conn);
+ if (!err) {
+ if (ctx->ulp_proto_id == CNIC_ULP_ISCSI)
+ atomic_dec(&cp->iscsi_conn);
- clear_bit(CTX_FL_OFFLD_START, &ctx->ctx_flags);
+ clear_bit(CTX_FL_OFFLD_START, &ctx->ctx_flags);
+ }
}
if (need_resched)
@@ -4218,14 +4253,6 @@
BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID | cp->last_status_idx);
}
-static void cnic_get_bnx2_iscsi_info(struct cnic_dev *dev)
-{
- u32 max_conn;
-
- max_conn = cnic_reg_rd_ind(dev, BNX2_FW_MAX_ISCSI_CONN);
- dev->max_iscsi_conn = max_conn;
-}
-
static void cnic_disable_bnx2_int_sync(struct cnic_dev *dev)
{
struct cnic_local *cp = dev->cnic_priv;
@@ -4291,7 +4318,7 @@
val = BNX2_L2CTX_CMD_TYPE_TYPE_L2 | (8 << 16);
cnic_ctx_wr(dev, cid_addr, offset1, val);
- txbd = (struct tx_bd *) udev->l2_ring;
+ txbd = udev->l2_ring;
buf_map = udev->l2_buf_map;
for (i = 0; i < MAX_TX_DESC_CNT; i++, txbd++) {
@@ -4350,7 +4377,7 @@
val = BNX2_L2CTX_L2_STATUSB_NUM(sb_id);
cnic_ctx_wr(dev, cid_addr, BNX2_L2CTX_HOST_BDIDX, val);
- rxbd = (struct rx_bd *) (udev->l2_ring + BCM_PAGE_SIZE);
+ rxbd = udev->l2_ring + BCM_PAGE_SIZE;
for (i = 0; i < MAX_RX_DESC_CNT; i++, rxbd++) {
dma_addr_t buf_map;
int n = (i % cp->l2_rx_ring_size) + 1;
@@ -4550,8 +4577,6 @@
return err;
}
- cnic_get_bnx2_iscsi_info(dev);
-
return 0;
}
@@ -4617,7 +4642,7 @@
CSTORM_STATUS_BLOCK_DATA_OFFSET(sb_id) +
offsetof(struct hc_status_block_data_e1x, index_data) +
sizeof(struct hc_index_data)*HC_INDEX_ISCSI_EQ_CONS +
- offsetof(struct hc_index_data, timeout), 64 / 12);
+ offsetof(struct hc_index_data, timeout), 64 / 4);
cnic_storm_memset_hc_disable(dev, sb_id, HC_INDEX_ISCSI_EQ_CONS, 0);
}
@@ -4633,7 +4658,6 @@
union eth_tx_bd_types *txbd = (union eth_tx_bd_types *) udev->l2_ring;
dma_addr_t buf_map, ring_map = udev->l2_ring_map;
struct host_sp_status_block *sb = cp->bnx2x_def_status_blk;
- int port = CNIC_PORT(cp);
int i;
u32 cli = cp->ethdev->iscsi_l2_client_id;
u32 val;
@@ -4674,10 +4698,9 @@
/* reset xstorm per client statistics */
if (cli < MAX_STAT_COUNTER_ID) {
- val = BAR_XSTRORM_INTMEM +
- XSTORM_PER_COUNTER_ID_STATS_OFFSET(port, cli);
- for (i = 0; i < sizeof(struct xstorm_per_client_stats) / 4; i++)
- CNIC_WR(dev, val + i * 4, 0);
+ data->general.statistics_zero_flg = 1;
+ data->general.statistics_en_flg = 1;
+ data->general.statistics_counter_id = cli;
}
cp->tx_cons_ptr =
@@ -4695,7 +4718,6 @@
(udev->l2_ring + (2 * BCM_PAGE_SIZE));
struct host_sp_status_block *sb = cp->bnx2x_def_status_blk;
int i;
- int port = CNIC_PORT(cp);
u32 cli = cp->ethdev->iscsi_l2_client_id;
int cl_qzone_id = BNX2X_CL_QZONE_ID(cp, cli);
u32 val;
@@ -4703,10 +4725,10 @@
/* General data */
data->general.client_id = cli;
- data->general.statistics_en_flg = 1;
- data->general.statistics_counter_id = cli;
data->general.activate_flg = 1;
data->general.sp_client_id = cli;
+ data->general.mtu = cpu_to_le16(cp->l2_single_buf_size - 14);
+ data->general.func_id = cp->pfid;
for (i = 0; i < BNX2X_MAX_RX_DESC_CNT; i++, rxbd++) {
dma_addr_t buf_map;
@@ -4740,23 +4762,12 @@
data->rx.status_block_id = BNX2X_DEF_SB_ID;
data->rx.cache_line_alignment_log_size = L1_CACHE_SHIFT;
- data->rx.bd_buff_size = cpu_to_le16(cp->l2_single_buf_size);
- data->rx.mtu = cpu_to_le16(cp->l2_single_buf_size - 14);
+ data->rx.max_bytes_on_bd = cpu_to_le16(cp->l2_single_buf_size);
data->rx.outer_vlan_removal_enable_flg = 1;
-
- /* reset tstorm and ustorm per client statistics */
- if (cli < MAX_STAT_COUNTER_ID) {
- val = BAR_TSTRORM_INTMEM +
- TSTORM_PER_COUNTER_ID_STATS_OFFSET(port, cli);
- for (i = 0; i < sizeof(struct tstorm_per_client_stats) / 4; i++)
- CNIC_WR(dev, val + i * 4, 0);
-
- val = BAR_USTRORM_INTMEM +
- USTORM_PER_COUNTER_ID_STATS_OFFSET(port, cli);
- for (i = 0; i < sizeof(struct ustorm_per_client_stats) / 4; i++)
- CNIC_WR(dev, val + i * 4, 0);
- }
+ data->rx.silent_vlan_removal_flg = 1;
+ data->rx.silent_vlan_value = 0;
+ data->rx.silent_vlan_mask = 0xffff;
cp->rx_cons_ptr =
&sb->sp_sb.index_values[HC_SP_INDEX_ETH_ISCSI_RX_CQ_CONS];
@@ -4772,7 +4783,7 @@
CSTORM_ISCSI_EQ_PROD_OFFSET(pfid, 0);
cp->kcq1.sw_prod_idx = 0;
- if (BNX2X_CHIP_IS_E2(cp->chip_id)) {
+ if (BNX2X_CHIP_IS_E2_PLUS(cp->chip_id)) {
struct host_hc_status_block_e2 *sb = cp->status_blk.gen;
cp->kcq1.hw_prod_idx_ptr =
@@ -4788,7 +4799,7 @@
&sb->sb.running_index[SM_RX_ID];
}
- if (BNX2X_CHIP_IS_E2(cp->chip_id)) {
+ if (BNX2X_CHIP_IS_E2_PLUS(cp->chip_id)) {
struct host_hc_status_block_e2 *sb = cp->status_blk.gen;
cp->kcq2.io_addr = BAR_USTRORM_INTMEM +
@@ -4805,10 +4816,12 @@
{
struct cnic_local *cp = dev->cnic_priv;
struct cnic_eth_dev *ethdev = cp->ethdev;
- int func = CNIC_FUNC(cp), ret, i;
+ int func = CNIC_FUNC(cp), ret;
u32 pfid;
- if (BNX2X_CHIP_IS_E2(cp->chip_id)) {
+ cp->port_mode = CHIP_PORT_MODE_NONE;
+
+ if (BNX2X_CHIP_IS_E2_PLUS(cp->chip_id)) {
u32 val = CNIC_RD(dev, MISC_REG_PORT4MODE_EN_OVWR);
if (!(val & 1))
@@ -4816,25 +4829,28 @@
else
val = (val >> 1) & 1;
- if (val)
+ if (val) {
+ cp->port_mode = CHIP_4_PORT_MODE;
cp->pfid = func >> 1;
- else
+ } else {
+ cp->port_mode = CHIP_4_PORT_MODE;
cp->pfid = func & 0x6;
+ }
} else {
cp->pfid = func;
}
pfid = cp->pfid;
ret = cnic_init_id_tbl(&cp->cid_tbl, MAX_ISCSI_TBL_SZ,
- cp->iscsi_start_cid);
+ cp->iscsi_start_cid, 0);
if (ret)
return -ENOMEM;
- if (BNX2X_CHIP_IS_E2(cp->chip_id)) {
+ if (BNX2X_CHIP_IS_E2_PLUS(cp->chip_id)) {
ret = cnic_init_id_tbl(&cp->fcoe_cid_tbl,
BNX2X_FCOE_NUM_CONNECTIONS,
- cp->fcoe_start_cid);
+ cp->fcoe_start_cid, 0);
if (ret)
return -ENOMEM;
@@ -4868,15 +4884,6 @@
CSTORM_ISCSI_EQ_SB_INDEX_OFFSET(pfid, 0),
HC_INDEX_ISCSI_EQ_CONS);
- for (i = 0; i < cp->conn_buf_info.num_pages; i++) {
- CNIC_WR(dev, BAR_TSTRORM_INTMEM +
- TSTORM_ISCSI_CONN_BUF_PBL_OFFSET(pfid, i),
- cp->conn_buf_info.pgtbl[2 * i]);
- CNIC_WR(dev, BAR_TSTRORM_INTMEM +
- TSTORM_ISCSI_CONN_BUF_PBL_OFFSET(pfid, i) + 4,
- cp->conn_buf_info.pgtbl[(2 * i) + 1]);
- }
-
CNIC_WR(dev, BAR_USTRORM_INTMEM +
USTORM_ISCSI_GLOBAL_BUF_PHYS_ADDR_OFFSET(pfid),
cp->gbl_buf_info.pg_map_arr[0] & 0xffffffff);
@@ -4924,7 +4931,7 @@
cl_qzone_id = BNX2X_CL_QZONE_ID(cp, cli);
off = BAR_USTRORM_INTMEM +
- (BNX2X_CHIP_IS_E2(cp->chip_id) ?
+ (BNX2X_CHIP_IS_E2_PLUS(cp->chip_id) ?
USTORM_RX_PRODS_E2_OFFSET(cl_qzone_id) :
USTORM_RX_PRODS_E1X_OFFSET(CNIC_PORT(cp), cli));
@@ -5217,6 +5224,8 @@
cdev->pcidev = pdev;
cp->chip_id = ethdev->chip_id;
+ cdev->max_iscsi_conn = ethdev->max_iscsi_conn;
+
cp->cnic_ops = &cnic_bnx2_ops;
cp->start_hw = cnic_start_bnx2_hw;
cp->stop_hw = cnic_stop_bnx2_hw;
@@ -5228,8 +5237,6 @@
cp->enable_int = cnic_enable_bnx2_int;
cp->disable_int_sync = cnic_disable_bnx2_int_sync;
cp->close_conn = cnic_close_bnx2_conn;
- cp->next_idx = cnic_bnx2_next_idx;
- cp->hw_idx = cnic_bnx2_hw_idx;
return cdev;
cnic_err:
@@ -5274,7 +5281,7 @@
if (!(ethdev->drv_state & CNIC_DRV_STATE_NO_ISCSI))
cdev->max_iscsi_conn = ethdev->max_iscsi_conn;
- if (BNX2X_CHIP_IS_E2(cp->chip_id) &&
+ if (BNX2X_CHIP_IS_E2_PLUS(cp->chip_id) &&
!(ethdev->drv_state & CNIC_DRV_STATE_NO_FCOE))
cdev->max_fcoe_conn = ethdev->max_fcoe_conn;
@@ -5290,13 +5297,11 @@
cp->stop_cm = cnic_cm_stop_bnx2x_hw;
cp->enable_int = cnic_enable_bnx2x_int;
cp->disable_int_sync = cnic_disable_bnx2x_int_sync;
- if (BNX2X_CHIP_IS_E2(cp->chip_id))
+ if (BNX2X_CHIP_IS_E2_PLUS(cp->chip_id))
cp->ack_int = cnic_ack_bnx2x_e2_msix;
else
cp->ack_int = cnic_ack_bnx2x_msix;
cp->close_conn = cnic_close_bnx2x_conn;
- cp->next_idx = cnic_bnx2x_next_idx;
- cp->hw_idx = cnic_bnx2x_hw_idx;
return cdev;
}
@@ -5335,7 +5340,7 @@
dev = cnic_from_netdev(netdev);
- if (!dev && (event == NETDEV_REGISTER || event == NETDEV_UP)) {
+ if (!dev && (event == NETDEV_REGISTER || netif_running(netdev))) {
/* Check for the hot-plug device */
dev = is_cnic_dev(netdev);
if (dev) {
@@ -5351,7 +5356,7 @@
else if (event == NETDEV_UNREGISTER)
cnic_ulp_exit(dev);
- if (event == NETDEV_UP) {
+ if (event == NETDEV_UP || (new_dev && netif_running(netdev))) {
if (cnic_register_netdev(dev) != 0) {
cnic_put(dev);
goto done;
diff --git a/drivers/net/cnic.h b/drivers/net/cnic.h
index 3367a6d3..7a2928f 100644
--- a/drivers/net/cnic.h
+++ b/drivers/net/cnic.h
@@ -1,6 +1,6 @@
/* cnic.h: Broadcom CNIC core network driver.
*
- * Copyright (c) 2006-2010 Broadcom Corporation
+ * Copyright (c) 2006-2011 Broadcom Corporation
*
* 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
@@ -68,11 +68,6 @@
#define BNX2_PG_CTX_MAP 0x1a0034
#define BNX2_ISCSI_CTX_MAP 0x1a0074
-struct cnic_redirect_entry {
- struct dst_entry *old_dst;
- struct dst_entry *new_dst;
-};
-
#define MAX_COMPLETED_KCQE 64
#define MAX_CNIC_L5_CONTEXT 256
@@ -171,6 +166,7 @@
unsigned long ctx_flags;
#define CTX_FL_OFFLD_START 0
#define CTX_FL_DELETE_WAIT 1
+#define CTX_FL_CID_ERROR 2
u8 ulp_proto_id;
union {
struct cnic_iscsi *iscsi;
@@ -185,6 +181,9 @@
u16 sw_prod_idx;
u16 *status_idx_ptr;
u32 io_addr;
+
+ u16 (*next_idx)(u16);
+ u16 (*hw_idx)(u16);
};
struct iro {
@@ -242,7 +241,7 @@
u16 rx_cons;
u16 tx_cons;
- struct iro *iro_arr;
+ const struct iro *iro_arr;
#define IRO (((struct cnic_local *) dev->cnic_priv)->iro_arr)
struct cnic_dma kwq_info;
@@ -283,7 +282,6 @@
struct cnic_sock *csk_tbl;
struct cnic_id_tbl csk_port_tbl;
- struct cnic_dma conn_buf_info;
struct cnic_dma gbl_buf_info;
struct cnic_iscsi *iscsi_tbl;
@@ -317,6 +315,11 @@
u32 chip_id;
int func;
u32 pfid;
+ u8 port_mode;
+#define CHIP_4_PORT_MODE 0
+#define CHIP_2_PORT_MODE 1
+#define CHIP_PORT_MODE_NONE 2
+
u32 shmem_base;
struct cnic_ops *cnic_ops;
@@ -332,8 +335,6 @@
void (*disable_int_sync)(struct cnic_dev *);
void (*ack_int)(struct cnic_dev *);
void (*close_conn)(struct cnic_sock *, u32 opcode);
- u16 (*next_idx)(u16);
- u16 (*hw_idx)(u16);
};
struct bnx2x_bd_chain_next {
@@ -368,7 +369,6 @@
#define BNX2X_ISCSI_MAX_PENDING_R2TS 4
#define BNX2X_ISCSI_R2TQE_SIZE 8
#define BNX2X_ISCSI_HQ_BD_SIZE 64
-#define BNX2X_ISCSI_CONN_BUF_SIZE 64
#define BNX2X_ISCSI_GLB_BUF_SIZE 64
#define BNX2X_ISCSI_PBL_NOT_CACHED 0xff
#define BNX2X_ISCSI_PDU_HEADER_NOT_CACHED 0xff
@@ -384,6 +384,9 @@
#define BNX2X_CHIP_NUM_57712E 0x1663
#define BNX2X_CHIP_NUM_57713 0x1651
#define BNX2X_CHIP_NUM_57713E 0x1652
+#define BNX2X_CHIP_NUM_57800 0x168a
+#define BNX2X_CHIP_NUM_57810 0x168e
+#define BNX2X_CHIP_NUM_57840 0x168d
#define BNX2X_CHIP_NUM(x) (x >> 16)
#define BNX2X_CHIP_IS_57710(x) \
@@ -402,9 +405,19 @@
(BNX2X_CHIP_NUM(x) == BNX2X_CHIP_NUM_57713)
#define BNX2X_CHIP_IS_57713E(x) \
(BNX2X_CHIP_NUM(x) == BNX2X_CHIP_NUM_57713E)
+#define BNX2X_CHIP_IS_57800(x) \
+ (BNX2X_CHIP_NUM(x) == BNX2X_CHIP_NUM_57800)
+#define BNX2X_CHIP_IS_57810(x) \
+ (BNX2X_CHIP_NUM(x) == BNX2X_CHIP_NUM_57810)
+#define BNX2X_CHIP_IS_57840(x) \
+ (BNX2X_CHIP_NUM(x) == BNX2X_CHIP_NUM_57840)
#define BNX2X_CHIP_IS_E2(x) \
(BNX2X_CHIP_IS_57712(x) || BNX2X_CHIP_IS_57712E(x) || \
BNX2X_CHIP_IS_57713(x) || BNX2X_CHIP_IS_57713E(x))
+#define BNX2X_CHIP_IS_E3(x) \
+ (BNX2X_CHIP_IS_57800(x) || BNX2X_CHIP_IS_57810(x) || \
+ BNX2X_CHIP_IS_57840(x))
+#define BNX2X_CHIP_IS_E2_PLUS(x) (BNX2X_CHIP_IS_E2(x) || BNX2X_CHIP_IS_E3(x))
#define IS_E1H_OFFSET BNX2X_CHIP_IS_E1H(cp->chip_id)
@@ -441,8 +454,8 @@
#define CNIC_PORT(cp) ((cp)->pfid & 1)
#define CNIC_FUNC(cp) ((cp)->func)
-#define CNIC_PATH(cp) (!BNX2X_CHIP_IS_E2(cp->chip_id) ? 0 :\
- (CNIC_FUNC(cp) & 1))
+#define CNIC_PATH(cp) (!BNX2X_CHIP_IS_E2_PLUS(cp->chip_id) ? \
+ 0 : (CNIC_FUNC(cp) & 1))
#define CNIC_E1HVN(cp) ((cp)->pfid >> 1)
#define BNX2X_HW_CID(cp, x) ((CNIC_PORT(cp) << 23) | \
@@ -451,10 +464,15 @@
#define BNX2X_SW_CID(x) (x & 0x1ffff)
#define BNX2X_CL_QZONE_ID(cp, cli) \
- (cli + (CNIC_PORT(cp) * (BNX2X_CHIP_IS_E2(cp->chip_id) ?\
- ETH_MAX_RX_CLIENTS_E2 : \
- ETH_MAX_RX_CLIENTS_E1H)))
+ (BNX2X_CHIP_IS_E2_PLUS(cp->chip_id) ? cli : \
+ cli + (CNIC_PORT(cp) * ETH_MAX_RX_CLIENTS_E1H))
-#define TCP_TSTORM_OOO_DROP_AND_PROC_ACK (0<<4)
+#ifndef MAX_STAT_COUNTER_ID
+#define MAX_STAT_COUNTER_ID \
+ (BNX2X_CHIP_IS_E1H((cp)->chip_id) ? MAX_STAT_COUNTER_ID_E1H : \
+ ((BNX2X_CHIP_IS_E2_PLUS((cp)->chip_id)) ? MAX_STAT_COUNTER_ID_E2 :\
+ MAX_STAT_COUNTER_ID_E1))
+#endif
+
#endif
diff --git a/drivers/net/cnic_defs.h b/drivers/net/cnic_defs.h
index fdbc004..e47d210 100644
--- a/drivers/net/cnic_defs.h
+++ b/drivers/net/cnic_defs.h
@@ -1,7 +1,7 @@
/* cnic.c: Broadcom CNIC core network driver.
*
- * Copyright (c) 2006-2010 Broadcom Corporation
+ * Copyright (c) 2006-2009 Broadcom Corporation
*
* 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
@@ -45,13 +45,13 @@
#define FCOE_KCQE_OPCODE_CQ_EVENT_NOTIFICATION (0x20)
#define FCOE_KCQE_OPCODE_FCOE_ERROR (0x21)
-#define FCOE_RAMROD_CMD_ID_INIT (FCOE_KCQE_OPCODE_INIT_FUNC)
-#define FCOE_RAMROD_CMD_ID_DESTROY (FCOE_KCQE_OPCODE_DESTROY_FUNC)
+#define FCOE_RAMROD_CMD_ID_INIT_FUNC (FCOE_KCQE_OPCODE_INIT_FUNC)
+#define FCOE_RAMROD_CMD_ID_DESTROY_FUNC (FCOE_KCQE_OPCODE_DESTROY_FUNC)
+#define FCOE_RAMROD_CMD_ID_STAT_FUNC (FCOE_KCQE_OPCODE_STAT_FUNC)
#define FCOE_RAMROD_CMD_ID_OFFLOAD_CONN (FCOE_KCQE_OPCODE_OFFLOAD_CONN)
#define FCOE_RAMROD_CMD_ID_ENABLE_CONN (FCOE_KCQE_OPCODE_ENABLE_CONN)
#define FCOE_RAMROD_CMD_ID_DISABLE_CONN (FCOE_KCQE_OPCODE_DISABLE_CONN)
#define FCOE_RAMROD_CMD_ID_DESTROY_CONN (FCOE_KCQE_OPCODE_DESTROY_CONN)
-#define FCOE_RAMROD_CMD_ID_STAT (FCOE_KCQE_OPCODE_STAT_FUNC)
#define FCOE_RAMROD_CMD_ID_TERMINATE_CONN (0x81)
#define FCOE_KWQE_OPCODE_INIT1 (0)
@@ -641,20 +641,20 @@
#define __CSTORM_ISCSI_AG_CONTEXT_RESERVED_ULP_RX_SE_CF_EN_SHIFT 12
#define __CSTORM_ISCSI_AG_CONTEXT_RESERVED_ULP_RX_INV_CF_EN (0x1<<13)
#define __CSTORM_ISCSI_AG_CONTEXT_RESERVED_ULP_RX_INV_CF_EN_SHIFT 13
-#define __CSTORM_ISCSI_AG_CONTEXT_PENDING_COMPLETION3_CF (0x3<<14)
-#define __CSTORM_ISCSI_AG_CONTEXT_PENDING_COMPLETION3_CF_SHIFT 14
+#define __CSTORM_ISCSI_AG_CONTEXT_AUX4_CF (0x3<<14)
+#define __CSTORM_ISCSI_AG_CONTEXT_AUX4_CF_SHIFT 14
#define __CSTORM_ISCSI_AG_CONTEXT_RESERVED66 (0x3<<16)
#define __CSTORM_ISCSI_AG_CONTEXT_RESERVED66_SHIFT 16
#define __CSTORM_ISCSI_AG_CONTEXT_FIN_RECEIVED_CF_EN (0x1<<18)
#define __CSTORM_ISCSI_AG_CONTEXT_FIN_RECEIVED_CF_EN_SHIFT 18
-#define __CSTORM_ISCSI_AG_CONTEXT_PENDING_COMPLETION0_CF_EN (0x1<<19)
-#define __CSTORM_ISCSI_AG_CONTEXT_PENDING_COMPLETION0_CF_EN_SHIFT 19
-#define __CSTORM_ISCSI_AG_CONTEXT_PENDING_COMPLETION1_CF_EN (0x1<<20)
-#define __CSTORM_ISCSI_AG_CONTEXT_PENDING_COMPLETION1_CF_EN_SHIFT 20
-#define __CSTORM_ISCSI_AG_CONTEXT_PENDING_COMPLETION2_CF_EN (0x1<<21)
-#define __CSTORM_ISCSI_AG_CONTEXT_PENDING_COMPLETION2_CF_EN_SHIFT 21
-#define __CSTORM_ISCSI_AG_CONTEXT_PENDING_COMPLETION3_CF_EN (0x1<<22)
-#define __CSTORM_ISCSI_AG_CONTEXT_PENDING_COMPLETION3_CF_EN_SHIFT 22
+#define __CSTORM_ISCSI_AG_CONTEXT_AUX1_CF_EN (0x1<<19)
+#define __CSTORM_ISCSI_AG_CONTEXT_AUX1_CF_EN_SHIFT 19
+#define __CSTORM_ISCSI_AG_CONTEXT_AUX2_CF_EN (0x1<<20)
+#define __CSTORM_ISCSI_AG_CONTEXT_AUX2_CF_EN_SHIFT 20
+#define __CSTORM_ISCSI_AG_CONTEXT_AUX3_CF_EN (0x1<<21)
+#define __CSTORM_ISCSI_AG_CONTEXT_AUX3_CF_EN_SHIFT 21
+#define __CSTORM_ISCSI_AG_CONTEXT_AUX4_CF_EN (0x1<<22)
+#define __CSTORM_ISCSI_AG_CONTEXT_AUX4_CF_EN_SHIFT 22
#define __CSTORM_ISCSI_AG_CONTEXT_REL_SEQ_RULE (0x7<<23)
#define __CSTORM_ISCSI_AG_CONTEXT_REL_SEQ_RULE_SHIFT 23
#define CSTORM_ISCSI_AG_CONTEXT_HQ_PROD_RULE (0x3<<26)
@@ -694,574 +694,668 @@
#endif
#if defined(__BIG_ENDIAN)
u16 __reserved64;
- u16 __cq_u_prod0;
+ u16 cq_u_prod;
#elif defined(__LITTLE_ENDIAN)
- u16 __cq_u_prod0;
+ u16 cq_u_prod;
u16 __reserved64;
#endif
u32 __cq_u_prod1;
#if defined(__BIG_ENDIAN)
u16 __agg_vars3;
- u16 __cq_u_prod2;
+ u16 cq_u_pend;
#elif defined(__LITTLE_ENDIAN)
- u16 __cq_u_prod2;
+ u16 cq_u_pend;
u16 __agg_vars3;
#endif
#if defined(__BIG_ENDIAN)
u16 __aux2_th;
- u16 __cq_u_prod3;
+ u16 aux2_val;
#elif defined(__LITTLE_ENDIAN)
- u16 __cq_u_prod3;
+ u16 aux2_val;
u16 __aux2_th;
#endif
};
/*
- * Parameters initialized during offloaded according to FLOGI/PLOGI/PRLI and used in FCoE context section
+ * The fcoe extra aggregative context section of Tstorm
*/
-struct ustorm_fcoe_params {
+struct tstorm_fcoe_extra_ag_context_section {
+ u32 __agg_val1;
#if defined(__BIG_ENDIAN)
- u16 fcoe_conn_id;
- u16 flags;
-#define USTORM_FCOE_PARAMS_B_MUL_N_PORT_IDS (0x1<<0)
-#define USTORM_FCOE_PARAMS_B_MUL_N_PORT_IDS_SHIFT 0
-#define USTORM_FCOE_PARAMS_B_E_D_TOV_RES (0x1<<1)
-#define USTORM_FCOE_PARAMS_B_E_D_TOV_RES_SHIFT 1
-#define USTORM_FCOE_PARAMS_B_CONT_INCR_SEQ_CNT (0x1<<2)
-#define USTORM_FCOE_PARAMS_B_CONT_INCR_SEQ_CNT_SHIFT 2
-#define USTORM_FCOE_PARAMS_B_CONF_REQ (0x1<<3)
-#define USTORM_FCOE_PARAMS_B_CONF_REQ_SHIFT 3
-#define USTORM_FCOE_PARAMS_B_REC_VALID (0x1<<4)
-#define USTORM_FCOE_PARAMS_B_REC_VALID_SHIFT 4
-#define USTORM_FCOE_PARAMS_B_CQ_TOGGLE_BIT (0x1<<5)
-#define USTORM_FCOE_PARAMS_B_CQ_TOGGLE_BIT_SHIFT 5
-#define USTORM_FCOE_PARAMS_B_XFRQ_TOGGLE_BIT (0x1<<6)
-#define USTORM_FCOE_PARAMS_B_XFRQ_TOGGLE_BIT_SHIFT 6
-#define USTORM_FCOE_PARAMS_B_C2_VALID (0x1<<7)
-#define USTORM_FCOE_PARAMS_B_C2_VALID_SHIFT 7
-#define USTORM_FCOE_PARAMS_B_ACK_0 (0x1<<8)
-#define USTORM_FCOE_PARAMS_B_ACK_0_SHIFT 8
-#define USTORM_FCOE_PARAMS_RSRV0 (0x7F<<9)
-#define USTORM_FCOE_PARAMS_RSRV0_SHIFT 9
+ u8 __tcp_agg_vars2;
+ u8 __agg_val3;
+ u16 __agg_val2;
#elif defined(__LITTLE_ENDIAN)
- u16 flags;
-#define USTORM_FCOE_PARAMS_B_MUL_N_PORT_IDS (0x1<<0)
-#define USTORM_FCOE_PARAMS_B_MUL_N_PORT_IDS_SHIFT 0
-#define USTORM_FCOE_PARAMS_B_E_D_TOV_RES (0x1<<1)
-#define USTORM_FCOE_PARAMS_B_E_D_TOV_RES_SHIFT 1
-#define USTORM_FCOE_PARAMS_B_CONT_INCR_SEQ_CNT (0x1<<2)
-#define USTORM_FCOE_PARAMS_B_CONT_INCR_SEQ_CNT_SHIFT 2
-#define USTORM_FCOE_PARAMS_B_CONF_REQ (0x1<<3)
-#define USTORM_FCOE_PARAMS_B_CONF_REQ_SHIFT 3
-#define USTORM_FCOE_PARAMS_B_REC_VALID (0x1<<4)
-#define USTORM_FCOE_PARAMS_B_REC_VALID_SHIFT 4
-#define USTORM_FCOE_PARAMS_B_CQ_TOGGLE_BIT (0x1<<5)
-#define USTORM_FCOE_PARAMS_B_CQ_TOGGLE_BIT_SHIFT 5
-#define USTORM_FCOE_PARAMS_B_XFRQ_TOGGLE_BIT (0x1<<6)
-#define USTORM_FCOE_PARAMS_B_XFRQ_TOGGLE_BIT_SHIFT 6
-#define USTORM_FCOE_PARAMS_B_C2_VALID (0x1<<7)
-#define USTORM_FCOE_PARAMS_B_C2_VALID_SHIFT 7
-#define USTORM_FCOE_PARAMS_B_ACK_0 (0x1<<8)
-#define USTORM_FCOE_PARAMS_B_ACK_0_SHIFT 8
-#define USTORM_FCOE_PARAMS_RSRV0 (0x7F<<9)
-#define USTORM_FCOE_PARAMS_RSRV0_SHIFT 9
- u16 fcoe_conn_id;
+ u16 __agg_val2;
+ u8 __agg_val3;
+ u8 __tcp_agg_vars2;
#endif
#if defined(__BIG_ENDIAN)
- u8 hc_csdm_byte_en;
- u8 func_id;
- u8 port_id;
- u8 vnic_id;
+ u16 __agg_val5;
+ u8 __agg_val6;
+ u8 __tcp_agg_vars3;
#elif defined(__LITTLE_ENDIAN)
- u8 vnic_id;
- u8 port_id;
- u8 func_id;
- u8 hc_csdm_byte_en;
+ u8 __tcp_agg_vars3;
+ u8 __agg_val6;
+ u16 __agg_val5;
#endif
-#if defined(__BIG_ENDIAN)
- u16 rx_total_conc_seqs;
- u16 rx_max_fc_pay_len;
-#elif defined(__LITTLE_ENDIAN)
- u16 rx_max_fc_pay_len;
- u16 rx_total_conc_seqs;
-#endif
-#if defined(__BIG_ENDIAN)
- u16 ox_id;
- u16 rx_max_conc_seqs;
-#elif defined(__LITTLE_ENDIAN)
- u16 rx_max_conc_seqs;
- u16 ox_id;
-#endif
+ u32 __lcq_prod;
+ u32 rtt_seq;
+ u32 rtt_time;
+ u32 __reserved66;
+ u32 wnd_right_edge;
+ u32 tcp_agg_vars1;
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_FIN_SENT_FLAG (0x1<<0)
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_FIN_SENT_FLAG_SHIFT 0
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_LAST_PACKET_FIN_FLAG (0x1<<1)
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_LAST_PACKET_FIN_FLAG_SHIFT 1
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_WND_UPD_CF (0x3<<2)
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_WND_UPD_CF_SHIFT 2
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_TIMEOUT_CF (0x3<<4)
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_TIMEOUT_CF_SHIFT 4
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_WND_UPD_CF_EN (0x1<<6)
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_WND_UPD_CF_EN_SHIFT 6
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_TIMEOUT_CF_EN (0x1<<7)
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_TIMEOUT_CF_EN_SHIFT 7
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RETRANSMIT_SEQ_EN (0x1<<8)
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RETRANSMIT_SEQ_EN_SHIFT 8
+#define __TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_LCQ_SND_EN (0x1<<9)
+#define __TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_LCQ_SND_EN_SHIFT 9
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX1_FLAG (0x1<<10)
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX1_FLAG_SHIFT 10
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX2_FLAG (0x1<<11)
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX2_FLAG_SHIFT 11
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX1_CF_EN (0x1<<12)
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX1_CF_EN_SHIFT 12
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX2_CF_EN (0x1<<13)
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX2_CF_EN_SHIFT 13
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX1_CF (0x3<<14)
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX1_CF_SHIFT 14
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX2_CF (0x3<<16)
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX2_CF_SHIFT 16
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_TX_BLOCKED (0x1<<18)
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_TX_BLOCKED_SHIFT 18
+#define __TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX10_CF_EN (0x1<<19)
+#define __TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX10_CF_EN_SHIFT 19
+#define __TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX11_CF_EN (0x1<<20)
+#define __TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX11_CF_EN_SHIFT 20
+#define __TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX12_CF_EN (0x1<<21)
+#define __TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX12_CF_EN_SHIFT 21
+#define __TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED1 (0x3<<22)
+#define __TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED1_SHIFT 22
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RETRANSMIT_PEND_SEQ (0xF<<24)
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RETRANSMIT_PEND_SEQ_SHIFT 24
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RETRANSMIT_DONE_SEQ (0xF<<28)
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RETRANSMIT_DONE_SEQ_SHIFT 28
+ u32 snd_max;
+ u32 __lcq_cons;
+ u32 __reserved2;
};
/*
- * FCoE 16-bits index structure
+ * The fcoe aggregative context of Tstorm
*/
-struct fcoe_idx16_fields {
- u16 fields;
-#define FCOE_IDX16_FIELDS_IDX (0x7FFF<<0)
-#define FCOE_IDX16_FIELDS_IDX_SHIFT 0
-#define FCOE_IDX16_FIELDS_MSB (0x1<<15)
-#define FCOE_IDX16_FIELDS_MSB_SHIFT 15
+struct tstorm_fcoe_ag_context {
+#if defined(__BIG_ENDIAN)
+ u16 ulp_credit;
+ u8 agg_vars1;
+#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM0 (0x1<<0)
+#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM0_SHIFT 0
+#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM1 (0x1<<1)
+#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM1_SHIFT 1
+#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM2 (0x1<<2)
+#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM2_SHIFT 2
+#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM3 (0x1<<3)
+#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM3_SHIFT 3
+#define __TSTORM_FCOE_AG_CONTEXT_QUEUE0_FLUSH_CF (0x3<<4)
+#define __TSTORM_FCOE_AG_CONTEXT_QUEUE0_FLUSH_CF_SHIFT 4
+#define __TSTORM_FCOE_AG_CONTEXT_AUX3_FLAG (0x1<<6)
+#define __TSTORM_FCOE_AG_CONTEXT_AUX3_FLAG_SHIFT 6
+#define __TSTORM_FCOE_AG_CONTEXT_AUX4_FLAG (0x1<<7)
+#define __TSTORM_FCOE_AG_CONTEXT_AUX4_FLAG_SHIFT 7
+ u8 state;
+#elif defined(__LITTLE_ENDIAN)
+ u8 state;
+ u8 agg_vars1;
+#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM0 (0x1<<0)
+#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM0_SHIFT 0
+#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM1 (0x1<<1)
+#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM1_SHIFT 1
+#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM2 (0x1<<2)
+#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM2_SHIFT 2
+#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM3 (0x1<<3)
+#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM3_SHIFT 3
+#define __TSTORM_FCOE_AG_CONTEXT_QUEUE0_FLUSH_CF (0x3<<4)
+#define __TSTORM_FCOE_AG_CONTEXT_QUEUE0_FLUSH_CF_SHIFT 4
+#define __TSTORM_FCOE_AG_CONTEXT_AUX3_FLAG (0x1<<6)
+#define __TSTORM_FCOE_AG_CONTEXT_AUX3_FLAG_SHIFT 6
+#define __TSTORM_FCOE_AG_CONTEXT_AUX4_FLAG (0x1<<7)
+#define __TSTORM_FCOE_AG_CONTEXT_AUX4_FLAG_SHIFT 7
+ u16 ulp_credit;
+#endif
+#if defined(__BIG_ENDIAN)
+ u16 __agg_val4;
+ u16 agg_vars2;
+#define __TSTORM_FCOE_AG_CONTEXT_AUX5_FLAG (0x1<<0)
+#define __TSTORM_FCOE_AG_CONTEXT_AUX5_FLAG_SHIFT 0
+#define __TSTORM_FCOE_AG_CONTEXT_AUX6_FLAG (0x1<<1)
+#define __TSTORM_FCOE_AG_CONTEXT_AUX6_FLAG_SHIFT 1
+#define __TSTORM_FCOE_AG_CONTEXT_AUX4_CF (0x3<<2)
+#define __TSTORM_FCOE_AG_CONTEXT_AUX4_CF_SHIFT 2
+#define __TSTORM_FCOE_AG_CONTEXT_AUX5_CF (0x3<<4)
+#define __TSTORM_FCOE_AG_CONTEXT_AUX5_CF_SHIFT 4
+#define __TSTORM_FCOE_AG_CONTEXT_AUX6_CF (0x3<<6)
+#define __TSTORM_FCOE_AG_CONTEXT_AUX6_CF_SHIFT 6
+#define __TSTORM_FCOE_AG_CONTEXT_AUX7_CF (0x3<<8)
+#define __TSTORM_FCOE_AG_CONTEXT_AUX7_CF_SHIFT 8
+#define __TSTORM_FCOE_AG_CONTEXT_AUX7_FLAG (0x1<<10)
+#define __TSTORM_FCOE_AG_CONTEXT_AUX7_FLAG_SHIFT 10
+#define __TSTORM_FCOE_AG_CONTEXT_QUEUE0_FLUSH_CF_EN (0x1<<11)
+#define __TSTORM_FCOE_AG_CONTEXT_QUEUE0_FLUSH_CF_EN_SHIFT 11
+#define TSTORM_FCOE_AG_CONTEXT_AUX4_CF_EN (0x1<<12)
+#define TSTORM_FCOE_AG_CONTEXT_AUX4_CF_EN_SHIFT 12
+#define TSTORM_FCOE_AG_CONTEXT_AUX5_CF_EN (0x1<<13)
+#define TSTORM_FCOE_AG_CONTEXT_AUX5_CF_EN_SHIFT 13
+#define TSTORM_FCOE_AG_CONTEXT_AUX6_CF_EN (0x1<<14)
+#define TSTORM_FCOE_AG_CONTEXT_AUX6_CF_EN_SHIFT 14
+#define TSTORM_FCOE_AG_CONTEXT_AUX7_CF_EN (0x1<<15)
+#define TSTORM_FCOE_AG_CONTEXT_AUX7_CF_EN_SHIFT 15
+#elif defined(__LITTLE_ENDIAN)
+ u16 agg_vars2;
+#define __TSTORM_FCOE_AG_CONTEXT_AUX5_FLAG (0x1<<0)
+#define __TSTORM_FCOE_AG_CONTEXT_AUX5_FLAG_SHIFT 0
+#define __TSTORM_FCOE_AG_CONTEXT_AUX6_FLAG (0x1<<1)
+#define __TSTORM_FCOE_AG_CONTEXT_AUX6_FLAG_SHIFT 1
+#define __TSTORM_FCOE_AG_CONTEXT_AUX4_CF (0x3<<2)
+#define __TSTORM_FCOE_AG_CONTEXT_AUX4_CF_SHIFT 2
+#define __TSTORM_FCOE_AG_CONTEXT_AUX5_CF (0x3<<4)
+#define __TSTORM_FCOE_AG_CONTEXT_AUX5_CF_SHIFT 4
+#define __TSTORM_FCOE_AG_CONTEXT_AUX6_CF (0x3<<6)
+#define __TSTORM_FCOE_AG_CONTEXT_AUX6_CF_SHIFT 6
+#define __TSTORM_FCOE_AG_CONTEXT_AUX7_CF (0x3<<8)
+#define __TSTORM_FCOE_AG_CONTEXT_AUX7_CF_SHIFT 8
+#define __TSTORM_FCOE_AG_CONTEXT_AUX7_FLAG (0x1<<10)
+#define __TSTORM_FCOE_AG_CONTEXT_AUX7_FLAG_SHIFT 10
+#define __TSTORM_FCOE_AG_CONTEXT_QUEUE0_FLUSH_CF_EN (0x1<<11)
+#define __TSTORM_FCOE_AG_CONTEXT_QUEUE0_FLUSH_CF_EN_SHIFT 11
+#define TSTORM_FCOE_AG_CONTEXT_AUX4_CF_EN (0x1<<12)
+#define TSTORM_FCOE_AG_CONTEXT_AUX4_CF_EN_SHIFT 12
+#define TSTORM_FCOE_AG_CONTEXT_AUX5_CF_EN (0x1<<13)
+#define TSTORM_FCOE_AG_CONTEXT_AUX5_CF_EN_SHIFT 13
+#define TSTORM_FCOE_AG_CONTEXT_AUX6_CF_EN (0x1<<14)
+#define TSTORM_FCOE_AG_CONTEXT_AUX6_CF_EN_SHIFT 14
+#define TSTORM_FCOE_AG_CONTEXT_AUX7_CF_EN (0x1<<15)
+#define TSTORM_FCOE_AG_CONTEXT_AUX7_CF_EN_SHIFT 15
+ u16 __agg_val4;
+#endif
+ struct tstorm_fcoe_extra_ag_context_section __extra_section;
+};
+
+
+
+/*
+ * The tcp aggregative context section of Tstorm
+ */
+struct tstorm_tcp_tcp_ag_context_section {
+ u32 __agg_val1;
+#if defined(__BIG_ENDIAN)
+ u8 __tcp_agg_vars2;
+ u8 __agg_val3;
+ u16 __agg_val2;
+#elif defined(__LITTLE_ENDIAN)
+ u16 __agg_val2;
+ u8 __agg_val3;
+ u8 __tcp_agg_vars2;
+#endif
+#if defined(__BIG_ENDIAN)
+ u16 __agg_val5;
+ u8 __agg_val6;
+ u8 __tcp_agg_vars3;
+#elif defined(__LITTLE_ENDIAN)
+ u8 __tcp_agg_vars3;
+ u8 __agg_val6;
+ u16 __agg_val5;
+#endif
+ u32 snd_nxt;
+ u32 rtt_seq;
+ u32 rtt_time;
+ u32 __reserved66;
+ u32 wnd_right_edge;
+ u32 tcp_agg_vars1;
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_FIN_SENT_FLAG (0x1<<0)
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_FIN_SENT_FLAG_SHIFT 0
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_LAST_PACKET_FIN_FLAG (0x1<<1)
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_LAST_PACKET_FIN_FLAG_SHIFT 1
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_WND_UPD_CF (0x3<<2)
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_WND_UPD_CF_SHIFT 2
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_TIMEOUT_CF (0x3<<4)
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_TIMEOUT_CF_SHIFT 4
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_WND_UPD_CF_EN (0x1<<6)
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_WND_UPD_CF_EN_SHIFT 6
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_TIMEOUT_CF_EN (0x1<<7)
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_TIMEOUT_CF_EN_SHIFT 7
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_RETRANSMIT_SEQ_EN (0x1<<8)
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_RETRANSMIT_SEQ_EN_SHIFT 8
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_SND_NXT_EN (0x1<<9)
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_SND_NXT_EN_SHIFT 9
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX1_FLAG (0x1<<10)
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX1_FLAG_SHIFT 10
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX2_FLAG (0x1<<11)
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX2_FLAG_SHIFT 11
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX1_CF_EN (0x1<<12)
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX1_CF_EN_SHIFT 12
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX2_CF_EN (0x1<<13)
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX2_CF_EN_SHIFT 13
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX1_CF (0x3<<14)
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX1_CF_SHIFT 14
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX2_CF (0x3<<16)
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX2_CF_SHIFT 16
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_BLOCKED (0x1<<18)
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_BLOCKED_SHIFT 18
+#define __TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX10_CF_EN (0x1<<19)
+#define __TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX10_CF_EN_SHIFT 19
+#define __TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX11_CF_EN (0x1<<20)
+#define __TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX11_CF_EN_SHIFT 20
+#define __TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX12_CF_EN (0x1<<21)
+#define __TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX12_CF_EN_SHIFT 21
+#define __TSTORM_TCP_TCP_AG_CONTEXT_SECTION_RESERVED1 (0x3<<22)
+#define __TSTORM_TCP_TCP_AG_CONTEXT_SECTION_RESERVED1_SHIFT 22
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_RETRANSMIT_PEND_SEQ (0xF<<24)
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_RETRANSMIT_PEND_SEQ_SHIFT 24
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_RETRANSMIT_DONE_SEQ (0xF<<28)
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_RETRANSMIT_DONE_SEQ_SHIFT 28
+ u32 snd_max;
+ u32 snd_una;
+ u32 __reserved2;
};
/*
- * FCoE 16-bits index union
+ * The iscsi aggregative context of Tstorm
*/
-union fcoe_idx16_field_union {
- struct fcoe_idx16_fields fields;
- u16 val;
+struct tstorm_iscsi_ag_context {
+#if defined(__BIG_ENDIAN)
+ u16 ulp_credit;
+ u8 agg_vars1;
+#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM0 (0x1<<0)
+#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM0_SHIFT 0
+#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM1 (0x1<<1)
+#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM1_SHIFT 1
+#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM2 (0x1<<2)
+#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM2_SHIFT 2
+#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM3 (0x1<<3)
+#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM3_SHIFT 3
+#define __TSTORM_ISCSI_AG_CONTEXT_QUEUES_FLUSH_Q0_CF (0x3<<4)
+#define __TSTORM_ISCSI_AG_CONTEXT_QUEUES_FLUSH_Q0_CF_SHIFT 4
+#define __TSTORM_ISCSI_AG_CONTEXT_AUX3_FLAG (0x1<<6)
+#define __TSTORM_ISCSI_AG_CONTEXT_AUX3_FLAG_SHIFT 6
+#define __TSTORM_ISCSI_AG_CONTEXT_ACK_ON_FIN_SENT_FLAG (0x1<<7)
+#define __TSTORM_ISCSI_AG_CONTEXT_ACK_ON_FIN_SENT_FLAG_SHIFT 7
+ u8 state;
+#elif defined(__LITTLE_ENDIAN)
+ u8 state;
+ u8 agg_vars1;
+#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM0 (0x1<<0)
+#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM0_SHIFT 0
+#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM1 (0x1<<1)
+#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM1_SHIFT 1
+#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM2 (0x1<<2)
+#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM2_SHIFT 2
+#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM3 (0x1<<3)
+#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM3_SHIFT 3
+#define __TSTORM_ISCSI_AG_CONTEXT_QUEUES_FLUSH_Q0_CF (0x3<<4)
+#define __TSTORM_ISCSI_AG_CONTEXT_QUEUES_FLUSH_Q0_CF_SHIFT 4
+#define __TSTORM_ISCSI_AG_CONTEXT_AUX3_FLAG (0x1<<6)
+#define __TSTORM_ISCSI_AG_CONTEXT_AUX3_FLAG_SHIFT 6
+#define __TSTORM_ISCSI_AG_CONTEXT_ACK_ON_FIN_SENT_FLAG (0x1<<7)
+#define __TSTORM_ISCSI_AG_CONTEXT_ACK_ON_FIN_SENT_FLAG_SHIFT 7
+ u16 ulp_credit;
+#endif
+#if defined(__BIG_ENDIAN)
+ u16 __agg_val4;
+ u16 agg_vars2;
+#define __TSTORM_ISCSI_AG_CONTEXT_MSL_TIMER_SET_FLAG (0x1<<0)
+#define __TSTORM_ISCSI_AG_CONTEXT_MSL_TIMER_SET_FLAG_SHIFT 0
+#define __TSTORM_ISCSI_AG_CONTEXT_FIN_SENT_FIRST_FLAG (0x1<<1)
+#define __TSTORM_ISCSI_AG_CONTEXT_FIN_SENT_FIRST_FLAG_SHIFT 1
+#define __TSTORM_ISCSI_AG_CONTEXT_RST_SENT_CF (0x3<<2)
+#define __TSTORM_ISCSI_AG_CONTEXT_RST_SENT_CF_SHIFT 2
+#define __TSTORM_ISCSI_AG_CONTEXT_WAKEUP_CALL_CF (0x3<<4)
+#define __TSTORM_ISCSI_AG_CONTEXT_WAKEUP_CALL_CF_SHIFT 4
+#define __TSTORM_ISCSI_AG_CONTEXT_AUX6_CF (0x3<<6)
+#define __TSTORM_ISCSI_AG_CONTEXT_AUX6_CF_SHIFT 6
+#define __TSTORM_ISCSI_AG_CONTEXT_AUX7_CF (0x3<<8)
+#define __TSTORM_ISCSI_AG_CONTEXT_AUX7_CF_SHIFT 8
+#define __TSTORM_ISCSI_AG_CONTEXT_AUX7_FLAG (0x1<<10)
+#define __TSTORM_ISCSI_AG_CONTEXT_AUX7_FLAG_SHIFT 10
+#define __TSTORM_ISCSI_AG_CONTEXT_QUEUES_FLUSH_Q0_CF_EN (0x1<<11)
+#define __TSTORM_ISCSI_AG_CONTEXT_QUEUES_FLUSH_Q0_CF_EN_SHIFT 11
+#define __TSTORM_ISCSI_AG_CONTEXT_RST_SENT_CF_EN (0x1<<12)
+#define __TSTORM_ISCSI_AG_CONTEXT_RST_SENT_CF_EN_SHIFT 12
+#define __TSTORM_ISCSI_AG_CONTEXT_WAKEUP_CALL_CF_EN (0x1<<13)
+#define __TSTORM_ISCSI_AG_CONTEXT_WAKEUP_CALL_CF_EN_SHIFT 13
+#define TSTORM_ISCSI_AG_CONTEXT_AUX6_CF_EN (0x1<<14)
+#define TSTORM_ISCSI_AG_CONTEXT_AUX6_CF_EN_SHIFT 14
+#define TSTORM_ISCSI_AG_CONTEXT_AUX7_CF_EN (0x1<<15)
+#define TSTORM_ISCSI_AG_CONTEXT_AUX7_CF_EN_SHIFT 15
+#elif defined(__LITTLE_ENDIAN)
+ u16 agg_vars2;
+#define __TSTORM_ISCSI_AG_CONTEXT_MSL_TIMER_SET_FLAG (0x1<<0)
+#define __TSTORM_ISCSI_AG_CONTEXT_MSL_TIMER_SET_FLAG_SHIFT 0
+#define __TSTORM_ISCSI_AG_CONTEXT_FIN_SENT_FIRST_FLAG (0x1<<1)
+#define __TSTORM_ISCSI_AG_CONTEXT_FIN_SENT_FIRST_FLAG_SHIFT 1
+#define __TSTORM_ISCSI_AG_CONTEXT_RST_SENT_CF (0x3<<2)
+#define __TSTORM_ISCSI_AG_CONTEXT_RST_SENT_CF_SHIFT 2
+#define __TSTORM_ISCSI_AG_CONTEXT_WAKEUP_CALL_CF (0x3<<4)
+#define __TSTORM_ISCSI_AG_CONTEXT_WAKEUP_CALL_CF_SHIFT 4
+#define __TSTORM_ISCSI_AG_CONTEXT_AUX6_CF (0x3<<6)
+#define __TSTORM_ISCSI_AG_CONTEXT_AUX6_CF_SHIFT 6
+#define __TSTORM_ISCSI_AG_CONTEXT_AUX7_CF (0x3<<8)
+#define __TSTORM_ISCSI_AG_CONTEXT_AUX7_CF_SHIFT 8
+#define __TSTORM_ISCSI_AG_CONTEXT_AUX7_FLAG (0x1<<10)
+#define __TSTORM_ISCSI_AG_CONTEXT_AUX7_FLAG_SHIFT 10
+#define __TSTORM_ISCSI_AG_CONTEXT_QUEUES_FLUSH_Q0_CF_EN (0x1<<11)
+#define __TSTORM_ISCSI_AG_CONTEXT_QUEUES_FLUSH_Q0_CF_EN_SHIFT 11
+#define __TSTORM_ISCSI_AG_CONTEXT_RST_SENT_CF_EN (0x1<<12)
+#define __TSTORM_ISCSI_AG_CONTEXT_RST_SENT_CF_EN_SHIFT 12
+#define __TSTORM_ISCSI_AG_CONTEXT_WAKEUP_CALL_CF_EN (0x1<<13)
+#define __TSTORM_ISCSI_AG_CONTEXT_WAKEUP_CALL_CF_EN_SHIFT 13
+#define TSTORM_ISCSI_AG_CONTEXT_AUX6_CF_EN (0x1<<14)
+#define TSTORM_ISCSI_AG_CONTEXT_AUX6_CF_EN_SHIFT 14
+#define TSTORM_ISCSI_AG_CONTEXT_AUX7_CF_EN (0x1<<15)
+#define TSTORM_ISCSI_AG_CONTEXT_AUX7_CF_EN_SHIFT 15
+ u16 __agg_val4;
+#endif
+ struct tstorm_tcp_tcp_ag_context_section tcp;
};
+
+
/*
- * 4 regs size
+ * The fcoe aggregative context of Ustorm
*/
-struct fcoe_bd_ctx {
- u32 buf_addr_hi;
- u32 buf_addr_lo;
+struct ustorm_fcoe_ag_context {
#if defined(__BIG_ENDIAN)
- u16 rsrv0;
- u16 buf_len;
+ u8 __aux_counter_flags;
+ u8 agg_vars2;
+#define USTORM_FCOE_AG_CONTEXT_TX_CF (0x3<<0)
+#define USTORM_FCOE_AG_CONTEXT_TX_CF_SHIFT 0
+#define __USTORM_FCOE_AG_CONTEXT_TIMER_CF (0x3<<2)
+#define __USTORM_FCOE_AG_CONTEXT_TIMER_CF_SHIFT 2
+#define USTORM_FCOE_AG_CONTEXT_AGG_MISC4_RULE (0x7<<4)
+#define USTORM_FCOE_AG_CONTEXT_AGG_MISC4_RULE_SHIFT 4
+#define __USTORM_FCOE_AG_CONTEXT_AGG_VAL2_MASK (0x1<<7)
+#define __USTORM_FCOE_AG_CONTEXT_AGG_VAL2_MASK_SHIFT 7
+ u8 agg_vars1;
+#define __USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM0 (0x1<<0)
+#define __USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM0_SHIFT 0
+#define USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM1 (0x1<<1)
+#define USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM1_SHIFT 1
+#define USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM2 (0x1<<2)
+#define USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM2_SHIFT 2
+#define USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM3 (0x1<<3)
+#define USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM3_SHIFT 3
+#define USTORM_FCOE_AG_CONTEXT_INV_CF (0x3<<4)
+#define USTORM_FCOE_AG_CONTEXT_INV_CF_SHIFT 4
+#define USTORM_FCOE_AG_CONTEXT_COMPLETION_CF (0x3<<6)
+#define USTORM_FCOE_AG_CONTEXT_COMPLETION_CF_SHIFT 6
+ u8 state;
#elif defined(__LITTLE_ENDIAN)
- u16 buf_len;
- u16 rsrv0;
+ u8 state;
+ u8 agg_vars1;
+#define __USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM0 (0x1<<0)
+#define __USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM0_SHIFT 0
+#define USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM1 (0x1<<1)
+#define USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM1_SHIFT 1
+#define USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM2 (0x1<<2)
+#define USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM2_SHIFT 2
+#define USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM3 (0x1<<3)
+#define USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM3_SHIFT 3
+#define USTORM_FCOE_AG_CONTEXT_INV_CF (0x3<<4)
+#define USTORM_FCOE_AG_CONTEXT_INV_CF_SHIFT 4
+#define USTORM_FCOE_AG_CONTEXT_COMPLETION_CF (0x3<<6)
+#define USTORM_FCOE_AG_CONTEXT_COMPLETION_CF_SHIFT 6
+ u8 agg_vars2;
+#define USTORM_FCOE_AG_CONTEXT_TX_CF (0x3<<0)
+#define USTORM_FCOE_AG_CONTEXT_TX_CF_SHIFT 0
+#define __USTORM_FCOE_AG_CONTEXT_TIMER_CF (0x3<<2)
+#define __USTORM_FCOE_AG_CONTEXT_TIMER_CF_SHIFT 2
+#define USTORM_FCOE_AG_CONTEXT_AGG_MISC4_RULE (0x7<<4)
+#define USTORM_FCOE_AG_CONTEXT_AGG_MISC4_RULE_SHIFT 4
+#define __USTORM_FCOE_AG_CONTEXT_AGG_VAL2_MASK (0x1<<7)
+#define __USTORM_FCOE_AG_CONTEXT_AGG_VAL2_MASK_SHIFT 7
+ u8 __aux_counter_flags;
#endif
#if defined(__BIG_ENDIAN)
- u16 rsrv1;
- u16 flags;
+ u8 cdu_usage;
+ u8 agg_misc2;
+ u16 pbf_tx_seq_ack;
#elif defined(__LITTLE_ENDIAN)
- u16 flags;
- u16 rsrv1;
+ u16 pbf_tx_seq_ack;
+ u8 agg_misc2;
+ u8 cdu_usage;
#endif
-};
-
-/*
- * Parameters required for placement according to SGL
- */
-struct ustorm_fcoe_data_place {
+ u32 agg_misc4;
#if defined(__BIG_ENDIAN)
- u16 cached_sge_off;
- u8 cached_num_sges;
- u8 cached_sge_idx;
+ u8 agg_val3_th;
+ u8 agg_val3;
+ u16 agg_misc3;
#elif defined(__LITTLE_ENDIAN)
- u8 cached_sge_idx;
- u8 cached_num_sges;
- u16 cached_sge_off;
+ u16 agg_misc3;
+ u8 agg_val3;
+ u8 agg_val3_th;
#endif
- struct fcoe_bd_ctx cached_sge[3];
-};
-
-struct fcoe_task_ctx_entry_txwr_rxrd {
+ u32 expired_task_id;
+ u32 agg_misc4_th;
#if defined(__BIG_ENDIAN)
- u16 verify_tx_seq;
- u8 init_flags;
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TASK_TYPE (0x7<<0)
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TASK_TYPE_SHIFT 0
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_DEV_TYPE (0x1<<3)
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_DEV_TYPE_SHIFT 3
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_CLASS_TYPE (0x1<<4)
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_CLASS_TYPE_SHIFT 4
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_SINGLE_SGE (0x1<<5)
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_SINGLE_SGE_SHIFT 5
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_RSRV5 (0x3<<6)
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_RSRV5_SHIFT 6
- u8 tx_flags;
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TX_STATE (0xF<<0)
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TX_STATE_SHIFT 0
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_RSRV4 (0xF<<4)
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_RSRV4_SHIFT 4
-#elif defined(__LITTLE_ENDIAN)
- u8 tx_flags;
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TX_STATE (0xF<<0)
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TX_STATE_SHIFT 0
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_RSRV4 (0xF<<4)
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_RSRV4_SHIFT 4
- u8 init_flags;
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TASK_TYPE (0x7<<0)
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TASK_TYPE_SHIFT 0
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_DEV_TYPE (0x1<<3)
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_DEV_TYPE_SHIFT 3
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_CLASS_TYPE (0x1<<4)
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_CLASS_TYPE_SHIFT 4
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_SINGLE_SGE (0x1<<5)
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_SINGLE_SGE_SHIFT 5
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_RSRV5 (0x3<<6)
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_RSRV5_SHIFT 6
- u16 verify_tx_seq;
-#endif
-};
-
-struct fcoe_fcp_cmd_payload {
- u32 opaque[8];
-};
-
-struct fcoe_fc_hdr {
-#if defined(__BIG_ENDIAN)
- u8 cs_ctl;
- u8 s_id[3];
-#elif defined(__LITTLE_ENDIAN)
- u8 s_id[3];
- u8 cs_ctl;
-#endif
-#if defined(__BIG_ENDIAN)
- u8 r_ctl;
- u8 d_id[3];
-#elif defined(__LITTLE_ENDIAN)
- u8 d_id[3];
- u8 r_ctl;
-#endif
-#if defined(__BIG_ENDIAN)
- u8 seq_id;
- u8 df_ctl;
- u16 seq_cnt;
-#elif defined(__LITTLE_ENDIAN)
- u16 seq_cnt;
- u8 df_ctl;
- u8 seq_id;
-#endif
-#if defined(__BIG_ENDIAN)
- u8 type;
- u8 f_ctl[3];
-#elif defined(__LITTLE_ENDIAN)
- u8 f_ctl[3];
- u8 type;
-#endif
- u32 parameters;
-#if defined(__BIG_ENDIAN)
- u16 ox_id;
- u16 rx_id;
-#elif defined(__LITTLE_ENDIAN)
- u16 rx_id;
- u16 ox_id;
-#endif
-};
-
-struct fcoe_fc_frame {
- struct fcoe_fc_hdr fc_hdr;
- u32 reserved0[2];
-};
-
-union fcoe_cmd_flow_info {
- struct fcoe_fcp_cmd_payload fcp_cmd_payload;
- struct fcoe_fc_frame mp_fc_frame;
-};
-
-struct fcoe_read_flow_info {
- struct fcoe_fc_hdr fc_data_in_hdr;
- u32 reserved[2];
-};
-
-struct fcoe_fcp_xfr_rdy_payload {
- u32 burst_len;
- u32 data_ro;
-};
-
-struct fcoe_write_flow_info {
- struct fcoe_fc_hdr fc_data_out_hdr;
- struct fcoe_fcp_xfr_rdy_payload fcp_xfr_payload;
-};
-
-struct fcoe_fcp_rsp_flags {
- u8 flags;
-#define FCOE_FCP_RSP_FLAGS_FCP_RSP_LEN_VALID (0x1<<0)
-#define FCOE_FCP_RSP_FLAGS_FCP_RSP_LEN_VALID_SHIFT 0
-#define FCOE_FCP_RSP_FLAGS_FCP_SNS_LEN_VALID (0x1<<1)
-#define FCOE_FCP_RSP_FLAGS_FCP_SNS_LEN_VALID_SHIFT 1
-#define FCOE_FCP_RSP_FLAGS_FCP_RESID_OVER (0x1<<2)
-#define FCOE_FCP_RSP_FLAGS_FCP_RESID_OVER_SHIFT 2
-#define FCOE_FCP_RSP_FLAGS_FCP_RESID_UNDER (0x1<<3)
-#define FCOE_FCP_RSP_FLAGS_FCP_RESID_UNDER_SHIFT 3
-#define FCOE_FCP_RSP_FLAGS_FCP_CONF_REQ (0x1<<4)
-#define FCOE_FCP_RSP_FLAGS_FCP_CONF_REQ_SHIFT 4
-#define FCOE_FCP_RSP_FLAGS_FCP_BIDI_FLAGS (0x7<<5)
-#define FCOE_FCP_RSP_FLAGS_FCP_BIDI_FLAGS_SHIFT 5
-};
-
-struct fcoe_fcp_rsp_payload {
- struct regpair reserved0;
- u32 fcp_resid;
-#if defined(__BIG_ENDIAN)
- u16 retry_delay_timer;
- struct fcoe_fcp_rsp_flags fcp_flags;
- u8 scsi_status_code;
-#elif defined(__LITTLE_ENDIAN)
- u8 scsi_status_code;
- struct fcoe_fcp_rsp_flags fcp_flags;
- u16 retry_delay_timer;
-#endif
- u32 fcp_rsp_len;
- u32 fcp_sns_len;
-};
-
-/*
- * Fixed size structure in order to plant it in Union structure
- */
-struct fcoe_fcp_rsp_union {
- struct fcoe_fcp_rsp_payload payload;
- struct regpair reserved0;
-};
-
-/*
- * Fixed size structure in order to plant it in Union structure
- */
-struct fcoe_abts_rsp_union {
- u32 r_ctl;
- u32 abts_rsp_payload[7];
-};
-
-union fcoe_rsp_flow_info {
- struct fcoe_fcp_rsp_union fcp_rsp;
- struct fcoe_abts_rsp_union abts_rsp;
-};
-
-struct fcoe_cleanup_flow_info {
-#if defined(__BIG_ENDIAN)
- u16 reserved1;
- u16 task_id;
-#elif defined(__LITTLE_ENDIAN)
- u16 task_id;
- u16 reserved1;
-#endif
- u32 reserved2[7];
-};
-
-/*
- * 32 bytes used for general purposes
- */
-union fcoe_general_task_ctx {
- union fcoe_cmd_flow_info cmd_info;
- struct fcoe_read_flow_info read_info;
- struct fcoe_write_flow_info write_info;
- union fcoe_rsp_flow_info rsp_info;
- struct fcoe_cleanup_flow_info cleanup_info;
- u32 comp_info[8];
-};
-
-struct fcoe_s_stat_ctx {
- u8 flags;
-#define FCOE_S_STAT_CTX_ACTIVE (0x1<<0)
-#define FCOE_S_STAT_CTX_ACTIVE_SHIFT 0
-#define FCOE_S_STAT_CTX_ACK_ABORT_SEQ_COND (0x1<<1)
-#define FCOE_S_STAT_CTX_ACK_ABORT_SEQ_COND_SHIFT 1
-#define FCOE_S_STAT_CTX_ABTS_PERFORMED (0x1<<2)
-#define FCOE_S_STAT_CTX_ABTS_PERFORMED_SHIFT 2
-#define FCOE_S_STAT_CTX_SEQ_TIMEOUT (0x1<<3)
-#define FCOE_S_STAT_CTX_SEQ_TIMEOUT_SHIFT 3
-#define FCOE_S_STAT_CTX_P_RJT (0x1<<4)
-#define FCOE_S_STAT_CTX_P_RJT_SHIFT 4
-#define FCOE_S_STAT_CTX_ACK_EOFT (0x1<<5)
-#define FCOE_S_STAT_CTX_ACK_EOFT_SHIFT 5
-#define FCOE_S_STAT_CTX_RSRV1 (0x3<<6)
-#define FCOE_S_STAT_CTX_RSRV1_SHIFT 6
-};
-
-/*
- * Common section. Both TX and RX processing might write and read from it in different flows
- */
-struct fcoe_task_ctx_entry_tx_rx_cmn {
- u32 data_2_trns;
- union fcoe_general_task_ctx general;
-#if defined(__BIG_ENDIAN)
- u16 tx_low_seq_cnt;
- struct fcoe_s_stat_ctx tx_s_stat;
- u8 tx_seq_id;
-#elif defined(__LITTLE_ENDIAN)
- u8 tx_seq_id;
- struct fcoe_s_stat_ctx tx_s_stat;
- u16 tx_low_seq_cnt;
-#endif
- u32 common_flags;
-#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_CID (0xFFFFFF<<0)
-#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_CID_SHIFT 0
-#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_VALID (0x1<<24)
-#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_VALID_SHIFT 24
-#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_SEQ_INIT (0x1<<25)
-#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_SEQ_INIT_SHIFT 25
-#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_PEND_XFER (0x1<<26)
-#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_PEND_XFER_SHIFT 26
-#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_PEND_CONF (0x1<<27)
-#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_PEND_CONF_SHIFT 27
-#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_EXP_FIRST_FRAME (0x1<<28)
-#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_EXP_FIRST_FRAME_SHIFT 28
-#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_RSRV (0x7<<29)
-#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_RSRV_SHIFT 29
-};
-
-struct fcoe_task_ctx_entry_rxwr_txrd {
-#if defined(__BIG_ENDIAN)
- u16 rx_id;
- u16 rx_flags;
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_RX_STATE (0xF<<0)
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_RX_STATE_SHIFT 0
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_NUM_RQ_WQE (0x7<<4)
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_NUM_RQ_WQE_SHIFT 4
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_CONF_REQ (0x1<<7)
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_CONF_REQ_SHIFT 7
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_MISS_FRAME (0x1<<8)
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_MISS_FRAME_SHIFT 8
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_RESERVED0 (0x7F<<9)
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_RESERVED0_SHIFT 9
-#elif defined(__LITTLE_ENDIAN)
- u16 rx_flags;
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_RX_STATE (0xF<<0)
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_RX_STATE_SHIFT 0
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_NUM_RQ_WQE (0x7<<4)
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_NUM_RQ_WQE_SHIFT 4
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_CONF_REQ (0x1<<7)
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_CONF_REQ_SHIFT 7
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_MISS_FRAME (0x1<<8)
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_MISS_FRAME_SHIFT 8
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_RESERVED0 (0x7F<<9)
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_RESERVED0_SHIFT 9
- u16 rx_id;
-#endif
-};
-
-struct fcoe_seq_ctx {
-#if defined(__BIG_ENDIAN)
- u16 low_seq_cnt;
- struct fcoe_s_stat_ctx s_stat;
- u8 seq_id;
-#elif defined(__LITTLE_ENDIAN)
- u8 seq_id;
- struct fcoe_s_stat_ctx s_stat;
- u16 low_seq_cnt;
-#endif
-#if defined(__BIG_ENDIAN)
- u16 err_seq_cnt;
- u16 high_seq_cnt;
-#elif defined(__LITTLE_ENDIAN)
- u16 high_seq_cnt;
- u16 err_seq_cnt;
-#endif
- u32 low_exp_ro;
- u32 high_exp_ro;
-};
-
-struct fcoe_single_sge_ctx {
- struct regpair cur_buf_addr;
-#if defined(__BIG_ENDIAN)
- u16 reserved0;
- u16 cur_buf_rem;
-#elif defined(__LITTLE_ENDIAN)
- u16 cur_buf_rem;
- u16 reserved0;
-#endif
-};
-
-struct fcoe_mul_sges_ctx {
- struct regpair cur_sge_addr;
-#if defined(__BIG_ENDIAN)
- u8 sgl_size;
- u8 cur_sge_idx;
- u16 cur_sge_off;
-#elif defined(__LITTLE_ENDIAN)
- u16 cur_sge_off;
- u8 cur_sge_idx;
- u8 sgl_size;
-#endif
-};
-
-union fcoe_sgl_ctx {
- struct fcoe_single_sge_ctx single_sge;
- struct fcoe_mul_sges_ctx mul_sges;
-};
-
-struct fcoe_task_ctx_entry_rx_only {
- struct fcoe_seq_ctx seq_ctx;
- struct fcoe_seq_ctx ooo_seq_ctx;
- u32 rsrv3;
- union fcoe_sgl_ctx sgl_ctx;
-};
-
-struct ustorm_fcoe_task_ctx_entry_rd {
- struct fcoe_task_ctx_entry_txwr_rxrd tx_wr_rx_rd;
- struct fcoe_task_ctx_entry_tx_rx_cmn cmn;
- struct fcoe_task_ctx_entry_rxwr_txrd rx_wr_tx_rd;
- struct fcoe_task_ctx_entry_rx_only rx_wr;
- u32 reserved;
-};
-
-/*
- * Ustorm FCoE Storm Context
- */
-struct ustorm_fcoe_st_context {
- struct ustorm_fcoe_params fcoe_params;
- struct regpair task_addr;
- struct regpair cq_base_addr;
- struct regpair rq_pbl_base;
- struct regpair rq_cur_page_addr;
- struct regpair confq_pbl_base_addr;
- struct regpair conn_db_base;
- struct regpair xfrq_base_addr;
- struct regpair lcq_base_addr;
-#if defined(__BIG_ENDIAN)
- union fcoe_idx16_field_union rq_cons;
- union fcoe_idx16_field_union rq_prod;
-#elif defined(__LITTLE_ENDIAN)
- union fcoe_idx16_field_union rq_prod;
- union fcoe_idx16_field_union rq_cons;
-#endif
-#if defined(__BIG_ENDIAN)
- u16 xfrq_prod;
+ u16 cq_prod;
u16 cq_cons;
#elif defined(__LITTLE_ENDIAN)
u16 cq_cons;
- u16 xfrq_prod;
+ u16 cq_prod;
#endif
#if defined(__BIG_ENDIAN)
- u16 lcq_cons;
- u16 hc_cram_address;
+ u16 __reserved2;
+ u8 decision_rules;
+#define USTORM_FCOE_AG_CONTEXT_CQ_DEC_RULE (0x7<<0)
+#define USTORM_FCOE_AG_CONTEXT_CQ_DEC_RULE_SHIFT 0
+#define __USTORM_FCOE_AG_CONTEXT_AGG_VAL3_RULE (0x7<<3)
+#define __USTORM_FCOE_AG_CONTEXT_AGG_VAL3_RULE_SHIFT 3
+#define USTORM_FCOE_AG_CONTEXT_CQ_ARM_N_FLAG (0x1<<6)
+#define USTORM_FCOE_AG_CONTEXT_CQ_ARM_N_FLAG_SHIFT 6
+#define __USTORM_FCOE_AG_CONTEXT_RESERVED1 (0x1<<7)
+#define __USTORM_FCOE_AG_CONTEXT_RESERVED1_SHIFT 7
+ u8 decision_rule_enable_bits;
+#define __USTORM_FCOE_AG_CONTEXT_RESERVED_INV_CF_EN (0x1<<0)
+#define __USTORM_FCOE_AG_CONTEXT_RESERVED_INV_CF_EN_SHIFT 0
+#define USTORM_FCOE_AG_CONTEXT_COMPLETION_CF_EN (0x1<<1)
+#define USTORM_FCOE_AG_CONTEXT_COMPLETION_CF_EN_SHIFT 1
+#define USTORM_FCOE_AG_CONTEXT_TX_CF_EN (0x1<<2)
+#define USTORM_FCOE_AG_CONTEXT_TX_CF_EN_SHIFT 2
+#define __USTORM_FCOE_AG_CONTEXT_TIMER_CF_EN (0x1<<3)
+#define __USTORM_FCOE_AG_CONTEXT_TIMER_CF_EN_SHIFT 3
+#define __USTORM_FCOE_AG_CONTEXT_AUX1_CF_EN (0x1<<4)
+#define __USTORM_FCOE_AG_CONTEXT_AUX1_CF_EN_SHIFT 4
+#define __USTORM_FCOE_AG_CONTEXT_QUEUE0_CF_EN (0x1<<5)
+#define __USTORM_FCOE_AG_CONTEXT_QUEUE0_CF_EN_SHIFT 5
+#define __USTORM_FCOE_AG_CONTEXT_AUX3_CF_EN (0x1<<6)
+#define __USTORM_FCOE_AG_CONTEXT_AUX3_CF_EN_SHIFT 6
+#define __USTORM_FCOE_AG_CONTEXT_DQ_CF_EN (0x1<<7)
+#define __USTORM_FCOE_AG_CONTEXT_DQ_CF_EN_SHIFT 7
#elif defined(__LITTLE_ENDIAN)
- u16 hc_cram_address;
- u16 lcq_cons;
+ u8 decision_rule_enable_bits;
+#define __USTORM_FCOE_AG_CONTEXT_RESERVED_INV_CF_EN (0x1<<0)
+#define __USTORM_FCOE_AG_CONTEXT_RESERVED_INV_CF_EN_SHIFT 0
+#define USTORM_FCOE_AG_CONTEXT_COMPLETION_CF_EN (0x1<<1)
+#define USTORM_FCOE_AG_CONTEXT_COMPLETION_CF_EN_SHIFT 1
+#define USTORM_FCOE_AG_CONTEXT_TX_CF_EN (0x1<<2)
+#define USTORM_FCOE_AG_CONTEXT_TX_CF_EN_SHIFT 2
+#define __USTORM_FCOE_AG_CONTEXT_TIMER_CF_EN (0x1<<3)
+#define __USTORM_FCOE_AG_CONTEXT_TIMER_CF_EN_SHIFT 3
+#define __USTORM_FCOE_AG_CONTEXT_AUX1_CF_EN (0x1<<4)
+#define __USTORM_FCOE_AG_CONTEXT_AUX1_CF_EN_SHIFT 4
+#define __USTORM_FCOE_AG_CONTEXT_QUEUE0_CF_EN (0x1<<5)
+#define __USTORM_FCOE_AG_CONTEXT_QUEUE0_CF_EN_SHIFT 5
+#define __USTORM_FCOE_AG_CONTEXT_AUX3_CF_EN (0x1<<6)
+#define __USTORM_FCOE_AG_CONTEXT_AUX3_CF_EN_SHIFT 6
+#define __USTORM_FCOE_AG_CONTEXT_DQ_CF_EN (0x1<<7)
+#define __USTORM_FCOE_AG_CONTEXT_DQ_CF_EN_SHIFT 7
+ u8 decision_rules;
+#define USTORM_FCOE_AG_CONTEXT_CQ_DEC_RULE (0x7<<0)
+#define USTORM_FCOE_AG_CONTEXT_CQ_DEC_RULE_SHIFT 0
+#define __USTORM_FCOE_AG_CONTEXT_AGG_VAL3_RULE (0x7<<3)
+#define __USTORM_FCOE_AG_CONTEXT_AGG_VAL3_RULE_SHIFT 3
+#define USTORM_FCOE_AG_CONTEXT_CQ_ARM_N_FLAG (0x1<<6)
+#define USTORM_FCOE_AG_CONTEXT_CQ_ARM_N_FLAG_SHIFT 6
+#define __USTORM_FCOE_AG_CONTEXT_RESERVED1 (0x1<<7)
+#define __USTORM_FCOE_AG_CONTEXT_RESERVED1_SHIFT 7
+ u16 __reserved2;
#endif
-#if defined(__BIG_ENDIAN)
- u16 sq_xfrq_lcq_confq_size;
- u16 confq_prod;
-#elif defined(__LITTLE_ENDIAN)
- u16 confq_prod;
- u16 sq_xfrq_lcq_confq_size;
-#endif
-#if defined(__BIG_ENDIAN)
- u8 hc_csdm_agg_int;
- u8 flags;
-#define USTORM_FCOE_ST_CONTEXT_MID_SEQ_PROC_FLAG (0x1<<0)
-#define USTORM_FCOE_ST_CONTEXT_MID_SEQ_PROC_FLAG_SHIFT 0
-#define USTORM_FCOE_ST_CONTEXT_CACHED_CONN_FLAG (0x1<<1)
-#define USTORM_FCOE_ST_CONTEXT_CACHED_CONN_FLAG_SHIFT 1
-#define USTORM_FCOE_ST_CONTEXT_CACHED_TCE_FLAG (0x1<<2)
-#define USTORM_FCOE_ST_CONTEXT_CACHED_TCE_FLAG_SHIFT 2
-#define USTORM_FCOE_ST_CONTEXT_RSRV1 (0x1F<<3)
-#define USTORM_FCOE_ST_CONTEXT_RSRV1_SHIFT 3
- u8 available_rqes;
- u8 sp_q_flush_cnt;
-#elif defined(__LITTLE_ENDIAN)
- u8 sp_q_flush_cnt;
- u8 available_rqes;
- u8 flags;
-#define USTORM_FCOE_ST_CONTEXT_MID_SEQ_PROC_FLAG (0x1<<0)
-#define USTORM_FCOE_ST_CONTEXT_MID_SEQ_PROC_FLAG_SHIFT 0
-#define USTORM_FCOE_ST_CONTEXT_CACHED_CONN_FLAG (0x1<<1)
-#define USTORM_FCOE_ST_CONTEXT_CACHED_CONN_FLAG_SHIFT 1
-#define USTORM_FCOE_ST_CONTEXT_CACHED_TCE_FLAG (0x1<<2)
-#define USTORM_FCOE_ST_CONTEXT_CACHED_TCE_FLAG_SHIFT 2
-#define USTORM_FCOE_ST_CONTEXT_RSRV1 (0x1F<<3)
-#define USTORM_FCOE_ST_CONTEXT_RSRV1_SHIFT 3
- u8 hc_csdm_agg_int;
-#endif
- struct ustorm_fcoe_data_place data_place;
- struct ustorm_fcoe_task_ctx_entry_rd tce;
};
+
/*
- * The FCoE non-aggregative context of Tstorm
+ * The iscsi aggregative context of Ustorm
*/
-struct tstorm_fcoe_st_context {
- struct regpair reserved0;
- struct regpair reserved1;
+struct ustorm_iscsi_ag_context {
+#if defined(__BIG_ENDIAN)
+ u8 __aux_counter_flags;
+ u8 agg_vars2;
+#define USTORM_ISCSI_AG_CONTEXT_TX_CF (0x3<<0)
+#define USTORM_ISCSI_AG_CONTEXT_TX_CF_SHIFT 0
+#define __USTORM_ISCSI_AG_CONTEXT_TIMER_CF (0x3<<2)
+#define __USTORM_ISCSI_AG_CONTEXT_TIMER_CF_SHIFT 2
+#define USTORM_ISCSI_AG_CONTEXT_AGG_MISC4_RULE (0x7<<4)
+#define USTORM_ISCSI_AG_CONTEXT_AGG_MISC4_RULE_SHIFT 4
+#define __USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_MASK (0x1<<7)
+#define __USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_MASK_SHIFT 7
+ u8 agg_vars1;
+#define __USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM0 (0x1<<0)
+#define __USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM0_SHIFT 0
+#define USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM1 (0x1<<1)
+#define USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM1_SHIFT 1
+#define USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM2 (0x1<<2)
+#define USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM2_SHIFT 2
+#define USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM3 (0x1<<3)
+#define USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM3_SHIFT 3
+#define USTORM_ISCSI_AG_CONTEXT_INV_CF (0x3<<4)
+#define USTORM_ISCSI_AG_CONTEXT_INV_CF_SHIFT 4
+#define USTORM_ISCSI_AG_CONTEXT_COMPLETION_CF (0x3<<6)
+#define USTORM_ISCSI_AG_CONTEXT_COMPLETION_CF_SHIFT 6
+ u8 state;
+#elif defined(__LITTLE_ENDIAN)
+ u8 state;
+ u8 agg_vars1;
+#define __USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM0 (0x1<<0)
+#define __USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM0_SHIFT 0
+#define USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM1 (0x1<<1)
+#define USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM1_SHIFT 1
+#define USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM2 (0x1<<2)
+#define USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM2_SHIFT 2
+#define USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM3 (0x1<<3)
+#define USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM3_SHIFT 3
+#define USTORM_ISCSI_AG_CONTEXT_INV_CF (0x3<<4)
+#define USTORM_ISCSI_AG_CONTEXT_INV_CF_SHIFT 4
+#define USTORM_ISCSI_AG_CONTEXT_COMPLETION_CF (0x3<<6)
+#define USTORM_ISCSI_AG_CONTEXT_COMPLETION_CF_SHIFT 6
+ u8 agg_vars2;
+#define USTORM_ISCSI_AG_CONTEXT_TX_CF (0x3<<0)
+#define USTORM_ISCSI_AG_CONTEXT_TX_CF_SHIFT 0
+#define __USTORM_ISCSI_AG_CONTEXT_TIMER_CF (0x3<<2)
+#define __USTORM_ISCSI_AG_CONTEXT_TIMER_CF_SHIFT 2
+#define USTORM_ISCSI_AG_CONTEXT_AGG_MISC4_RULE (0x7<<4)
+#define USTORM_ISCSI_AG_CONTEXT_AGG_MISC4_RULE_SHIFT 4
+#define __USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_MASK (0x1<<7)
+#define __USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_MASK_SHIFT 7
+ u8 __aux_counter_flags;
+#endif
+#if defined(__BIG_ENDIAN)
+ u8 cdu_usage;
+ u8 agg_misc2;
+ u16 __cq_local_comp_itt_val;
+#elif defined(__LITTLE_ENDIAN)
+ u16 __cq_local_comp_itt_val;
+ u8 agg_misc2;
+ u8 cdu_usage;
+#endif
+ u32 agg_misc4;
+#if defined(__BIG_ENDIAN)
+ u8 agg_val3_th;
+ u8 agg_val3;
+ u16 agg_misc3;
+#elif defined(__LITTLE_ENDIAN)
+ u16 agg_misc3;
+ u8 agg_val3;
+ u8 agg_val3_th;
+#endif
+ u32 agg_val1;
+ u32 agg_misc4_th;
+#if defined(__BIG_ENDIAN)
+ u16 agg_val2_th;
+ u16 agg_val2;
+#elif defined(__LITTLE_ENDIAN)
+ u16 agg_val2;
+ u16 agg_val2_th;
+#endif
+#if defined(__BIG_ENDIAN)
+ u16 __reserved2;
+ u8 decision_rules;
+#define USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_RULE (0x7<<0)
+#define USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_RULE_SHIFT 0
+#define __USTORM_ISCSI_AG_CONTEXT_AGG_VAL3_RULE (0x7<<3)
+#define __USTORM_ISCSI_AG_CONTEXT_AGG_VAL3_RULE_SHIFT 3
+#define USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_ARM_N_FLAG (0x1<<6)
+#define USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_ARM_N_FLAG_SHIFT 6
+#define __USTORM_ISCSI_AG_CONTEXT_RESERVED1 (0x1<<7)
+#define __USTORM_ISCSI_AG_CONTEXT_RESERVED1_SHIFT 7
+ u8 decision_rule_enable_bits;
+#define USTORM_ISCSI_AG_CONTEXT_INV_CF_EN (0x1<<0)
+#define USTORM_ISCSI_AG_CONTEXT_INV_CF_EN_SHIFT 0
+#define USTORM_ISCSI_AG_CONTEXT_COMPLETION_CF_EN (0x1<<1)
+#define USTORM_ISCSI_AG_CONTEXT_COMPLETION_CF_EN_SHIFT 1
+#define USTORM_ISCSI_AG_CONTEXT_TX_CF_EN (0x1<<2)
+#define USTORM_ISCSI_AG_CONTEXT_TX_CF_EN_SHIFT 2
+#define __USTORM_ISCSI_AG_CONTEXT_TIMER_CF_EN (0x1<<3)
+#define __USTORM_ISCSI_AG_CONTEXT_TIMER_CF_EN_SHIFT 3
+#define __USTORM_ISCSI_AG_CONTEXT_CQ_LOCAL_COMP_CF_EN (0x1<<4)
+#define __USTORM_ISCSI_AG_CONTEXT_CQ_LOCAL_COMP_CF_EN_SHIFT 4
+#define __USTORM_ISCSI_AG_CONTEXT_QUEUES_FLUSH_Q0_CF_EN (0x1<<5)
+#define __USTORM_ISCSI_AG_CONTEXT_QUEUES_FLUSH_Q0_CF_EN_SHIFT 5
+#define __USTORM_ISCSI_AG_CONTEXT_AUX3_CF_EN (0x1<<6)
+#define __USTORM_ISCSI_AG_CONTEXT_AUX3_CF_EN_SHIFT 6
+#define __USTORM_ISCSI_AG_CONTEXT_DQ_CF_EN (0x1<<7)
+#define __USTORM_ISCSI_AG_CONTEXT_DQ_CF_EN_SHIFT 7
+#elif defined(__LITTLE_ENDIAN)
+ u8 decision_rule_enable_bits;
+#define USTORM_ISCSI_AG_CONTEXT_INV_CF_EN (0x1<<0)
+#define USTORM_ISCSI_AG_CONTEXT_INV_CF_EN_SHIFT 0
+#define USTORM_ISCSI_AG_CONTEXT_COMPLETION_CF_EN (0x1<<1)
+#define USTORM_ISCSI_AG_CONTEXT_COMPLETION_CF_EN_SHIFT 1
+#define USTORM_ISCSI_AG_CONTEXT_TX_CF_EN (0x1<<2)
+#define USTORM_ISCSI_AG_CONTEXT_TX_CF_EN_SHIFT 2
+#define __USTORM_ISCSI_AG_CONTEXT_TIMER_CF_EN (0x1<<3)
+#define __USTORM_ISCSI_AG_CONTEXT_TIMER_CF_EN_SHIFT 3
+#define __USTORM_ISCSI_AG_CONTEXT_CQ_LOCAL_COMP_CF_EN (0x1<<4)
+#define __USTORM_ISCSI_AG_CONTEXT_CQ_LOCAL_COMP_CF_EN_SHIFT 4
+#define __USTORM_ISCSI_AG_CONTEXT_QUEUES_FLUSH_Q0_CF_EN (0x1<<5)
+#define __USTORM_ISCSI_AG_CONTEXT_QUEUES_FLUSH_Q0_CF_EN_SHIFT 5
+#define __USTORM_ISCSI_AG_CONTEXT_AUX3_CF_EN (0x1<<6)
+#define __USTORM_ISCSI_AG_CONTEXT_AUX3_CF_EN_SHIFT 6
+#define __USTORM_ISCSI_AG_CONTEXT_DQ_CF_EN (0x1<<7)
+#define __USTORM_ISCSI_AG_CONTEXT_DQ_CF_EN_SHIFT 7
+ u8 decision_rules;
+#define USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_RULE (0x7<<0)
+#define USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_RULE_SHIFT 0
+#define __USTORM_ISCSI_AG_CONTEXT_AGG_VAL3_RULE (0x7<<3)
+#define __USTORM_ISCSI_AG_CONTEXT_AGG_VAL3_RULE_SHIFT 3
+#define USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_ARM_N_FLAG (0x1<<6)
+#define USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_ARM_N_FLAG_SHIFT 6
+#define __USTORM_ISCSI_AG_CONTEXT_RESERVED1 (0x1<<7)
+#define __USTORM_ISCSI_AG_CONTEXT_RESERVED1_SHIFT 7
+ u16 __reserved2;
+#endif
};
+
/*
* The fcoe aggregative context section of Xstorm
*/
@@ -1272,8 +1366,8 @@
#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED51_SHIFT 0
#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_ACK_TO_FE_UPDATED (0x3<<2)
#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_ACK_TO_FE_UPDATED_SHIFT 2
-#define XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_PBF_TX_SEQ_ACK_CF (0x3<<4)
-#define XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_PBF_TX_SEQ_ACK_CF_SHIFT 4
+#define XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_SIDEBAND_SENT_CF (0x3<<4)
+#define XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_SIDEBAND_SENT_CF_SHIFT 4
#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED_CLEAR_DA_TIMER_EN (0x1<<6)
#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED_CLEAR_DA_TIMER_EN_SHIFT 6
#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED_DA_EXPIRATION_FLAG (0x1<<7)
@@ -1288,20 +1382,20 @@
#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED51_SHIFT 0
#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_ACK_TO_FE_UPDATED (0x3<<2)
#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_ACK_TO_FE_UPDATED_SHIFT 2
-#define XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_PBF_TX_SEQ_ACK_CF (0x3<<4)
-#define XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_PBF_TX_SEQ_ACK_CF_SHIFT 4
+#define XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_SIDEBAND_SENT_CF (0x3<<4)
+#define XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_SIDEBAND_SENT_CF_SHIFT 4
#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED_CLEAR_DA_TIMER_EN (0x1<<6)
#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED_CLEAR_DA_TIMER_EN_SHIFT 6
#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED_DA_EXPIRATION_FLAG (0x1<<7)
#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED_DA_EXPIRATION_FLAG_SHIFT 7
#endif
- u32 __task_addr_lo;
- u32 __task_addr_hi;
+ u32 snd_nxt;
+ u32 tx_wnd;
u32 __reserved55;
- u32 __tx_prods;
+ u32 local_adv_wnd;
#if defined(__BIG_ENDIAN)
u8 __agg_val8_th;
- u8 __agg_val8;
+ u8 __tx_dest;
u16 tcp_agg_vars2;
#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED57 (0x1<<0)
#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED57_SHIFT 0
@@ -1317,8 +1411,8 @@
#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED60_SHIFT 5
#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED_ACK_TO_FE_UPDATED_EN (0x1<<6)
#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED_ACK_TO_FE_UPDATED_EN_SHIFT 6
-#define XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_PBF_TX_SEQ_ACK_CF_EN (0x1<<7)
-#define XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_PBF_TX_SEQ_ACK_CF_EN_SHIFT 7
+#define XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_SIDEBAND_SENT_CF_EN (0x1<<7)
+#define XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_SIDEBAND_SENT_CF_EN_SHIFT 7
#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED_TX_FIN_FLAG_EN (0x1<<8)
#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED_TX_FIN_FLAG_EN_SHIFT 8
#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX1_FLAG (0x1<<9)
@@ -1327,8 +1421,8 @@
#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_SET_RTO_CF_SHIFT 10
#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_TS_TO_ECHO_UPDATED_CF (0x3<<12)
#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_TS_TO_ECHO_UPDATED_CF_SHIFT 12
-#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX8_CF (0x3<<14)
-#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX8_CF_SHIFT 14
+#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_TX_DEST_UPDATED_CF (0x3<<14)
+#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_TX_DEST_UPDATED_CF_SHIFT 14
#elif defined(__LITTLE_ENDIAN)
u16 tcp_agg_vars2;
#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED57 (0x1<<0)
@@ -1345,8 +1439,8 @@
#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED60_SHIFT 5
#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED_ACK_TO_FE_UPDATED_EN (0x1<<6)
#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED_ACK_TO_FE_UPDATED_EN_SHIFT 6
-#define XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_PBF_TX_SEQ_ACK_CF_EN (0x1<<7)
-#define XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_PBF_TX_SEQ_ACK_CF_EN_SHIFT 7
+#define XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_SIDEBAND_SENT_CF_EN (0x1<<7)
+#define XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_SIDEBAND_SENT_CF_EN_SHIFT 7
#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED_TX_FIN_FLAG_EN (0x1<<8)
#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED_TX_FIN_FLAG_EN_SHIFT 8
#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX1_FLAG (0x1<<9)
@@ -1355,9 +1449,9 @@
#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_SET_RTO_CF_SHIFT 10
#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_TS_TO_ECHO_UPDATED_CF (0x3<<12)
#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_TS_TO_ECHO_UPDATED_CF_SHIFT 12
-#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX8_CF (0x3<<14)
-#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX8_CF_SHIFT 14
- u8 __agg_val8;
+#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_TX_DEST_UPDATED_CF (0x3<<14)
+#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_TX_DEST_UPDATED_CF_SHIFT 14
+ u8 __tx_dest;
u8 __agg_val8_th;
#endif
u32 __sq_base_addr_lo;
@@ -1591,9 +1685,9 @@
#if defined(__BIG_ENDIAN)
u8 __reserved1;
u8 __agg_val6_th;
- u16 __confq_tx_prod;
+ u16 __agg_val9;
#elif defined(__LITTLE_ENDIAN)
- u16 __confq_tx_prod;
+ u16 __agg_val9;
u8 __agg_val6_th;
u8 __reserved1;
#endif
@@ -1605,16 +1699,16 @@
u16 confq_cons;
#endif
u32 agg_vars8;
-#define __XSTORM_FCOE_AG_CONTEXT_CACHE_WQE_IDX (0xFFFFFF<<0)
-#define __XSTORM_FCOE_AG_CONTEXT_CACHE_WQE_IDX_SHIFT 0
+#define XSTORM_FCOE_AG_CONTEXT_AGG_MISC2 (0xFFFFFF<<0)
+#define XSTORM_FCOE_AG_CONTEXT_AGG_MISC2_SHIFT 0
#define XSTORM_FCOE_AG_CONTEXT_AGG_MISC3 (0xFF<<24)
#define XSTORM_FCOE_AG_CONTEXT_AGG_MISC3_SHIFT 24
#if defined(__BIG_ENDIAN)
- u16 ox_id;
+ u16 agg_misc0;
u16 sq_prod;
#elif defined(__LITTLE_ENDIAN)
u16 sq_prod;
- u16 ox_id;
+ u16 agg_misc0;
#endif
#if defined(__BIG_ENDIAN)
u8 agg_val3;
@@ -1628,986 +1722,51 @@
u8 agg_val3;
#endif
#if defined(__BIG_ENDIAN)
- u16 __pbf_tx_seq_ack;
+ u16 __agg_misc1;
u16 agg_limit1;
#elif defined(__LITTLE_ENDIAN)
u16 agg_limit1;
- u16 __pbf_tx_seq_ack;
+ u16 __agg_misc1;
#endif
u32 completion_seq;
u32 confq_pbl_base_lo;
u32 confq_pbl_base_hi;
};
-/*
- * The fcoe extra aggregative context section of Tstorm
- */
-struct tstorm_fcoe_extra_ag_context_section {
- u32 __agg_val1;
-#if defined(__BIG_ENDIAN)
- u8 __tcp_agg_vars2;
- u8 __agg_val3;
- u16 __agg_val2;
-#elif defined(__LITTLE_ENDIAN)
- u16 __agg_val2;
- u8 __agg_val3;
- u8 __tcp_agg_vars2;
-#endif
-#if defined(__BIG_ENDIAN)
- u16 __agg_val5;
- u8 __agg_val6;
- u8 __tcp_agg_vars3;
-#elif defined(__LITTLE_ENDIAN)
- u8 __tcp_agg_vars3;
- u8 __agg_val6;
- u16 __agg_val5;
-#endif
- u32 __lcq_prod;
- u32 rtt_seq;
- u32 rtt_time;
- u32 __reserved66;
- u32 wnd_right_edge;
- u32 tcp_agg_vars1;
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_FIN_SENT_FLAG (0x1<<0)
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_FIN_SENT_FLAG_SHIFT 0
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_LAST_PACKET_FIN_FLAG (0x1<<1)
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_LAST_PACKET_FIN_FLAG_SHIFT 1
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_WND_UPD_CF (0x3<<2)
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_WND_UPD_CF_SHIFT 2
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_TIMEOUT_CF (0x3<<4)
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_TIMEOUT_CF_SHIFT 4
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_WND_UPD_CF_EN (0x1<<6)
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_WND_UPD_CF_EN_SHIFT 6
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_TIMEOUT_CF_EN (0x1<<7)
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_TIMEOUT_CF_EN_SHIFT 7
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RETRANSMIT_SEQ_EN (0x1<<8)
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RETRANSMIT_SEQ_EN_SHIFT 8
-#define __TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_LCQ_SND_EN (0x1<<9)
-#define __TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_LCQ_SND_EN_SHIFT 9
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX1_FLAG (0x1<<10)
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX1_FLAG_SHIFT 10
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX2_FLAG (0x1<<11)
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX2_FLAG_SHIFT 11
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX1_CF_EN (0x1<<12)
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX1_CF_EN_SHIFT 12
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX2_CF_EN (0x1<<13)
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX2_CF_EN_SHIFT 13
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX1_CF (0x3<<14)
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX1_CF_SHIFT 14
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX2_CF (0x3<<16)
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX2_CF_SHIFT 16
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_TX_BLOCKED (0x1<<18)
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_TX_BLOCKED_SHIFT 18
-#define __TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX10_CF_EN (0x1<<19)
-#define __TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX10_CF_EN_SHIFT 19
-#define __TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX11_CF_EN (0x1<<20)
-#define __TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX11_CF_EN_SHIFT 20
-#define __TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX12_CF_EN (0x1<<21)
-#define __TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX12_CF_EN_SHIFT 21
-#define __TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED1 (0x3<<22)
-#define __TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED1_SHIFT 22
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RETRANSMIT_PEND_SEQ (0xF<<24)
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RETRANSMIT_PEND_SEQ_SHIFT 24
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RETRANSMIT_DONE_SEQ (0xF<<28)
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RETRANSMIT_DONE_SEQ_SHIFT 28
- u32 snd_max;
- u32 __lcq_cons;
- u32 __reserved2;
-};
-/*
- * The fcoe aggregative context of Tstorm
- */
-struct tstorm_fcoe_ag_context {
-#if defined(__BIG_ENDIAN)
- u16 ulp_credit;
- u8 agg_vars1;
-#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM0 (0x1<<0)
-#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM0_SHIFT 0
-#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM1 (0x1<<1)
-#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM1_SHIFT 1
-#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM2 (0x1<<2)
-#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM2_SHIFT 2
-#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM3 (0x1<<3)
-#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM3_SHIFT 3
-#define __TSTORM_FCOE_AG_CONTEXT_QUEUE0_FLUSH_CF (0x3<<4)
-#define __TSTORM_FCOE_AG_CONTEXT_QUEUE0_FLUSH_CF_SHIFT 4
-#define __TSTORM_FCOE_AG_CONTEXT_AUX3_FLAG (0x1<<6)
-#define __TSTORM_FCOE_AG_CONTEXT_AUX3_FLAG_SHIFT 6
-#define __TSTORM_FCOE_AG_CONTEXT_AUX4_FLAG (0x1<<7)
-#define __TSTORM_FCOE_AG_CONTEXT_AUX4_FLAG_SHIFT 7
- u8 state;
-#elif defined(__LITTLE_ENDIAN)
- u8 state;
- u8 agg_vars1;
-#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM0 (0x1<<0)
-#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM0_SHIFT 0
-#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM1 (0x1<<1)
-#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM1_SHIFT 1
-#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM2 (0x1<<2)
-#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM2_SHIFT 2
-#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM3 (0x1<<3)
-#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM3_SHIFT 3
-#define __TSTORM_FCOE_AG_CONTEXT_QUEUE0_FLUSH_CF (0x3<<4)
-#define __TSTORM_FCOE_AG_CONTEXT_QUEUE0_FLUSH_CF_SHIFT 4
-#define __TSTORM_FCOE_AG_CONTEXT_AUX3_FLAG (0x1<<6)
-#define __TSTORM_FCOE_AG_CONTEXT_AUX3_FLAG_SHIFT 6
-#define __TSTORM_FCOE_AG_CONTEXT_AUX4_FLAG (0x1<<7)
-#define __TSTORM_FCOE_AG_CONTEXT_AUX4_FLAG_SHIFT 7
- u16 ulp_credit;
-#endif
-#if defined(__BIG_ENDIAN)
- u16 __agg_val4;
- u16 agg_vars2;
-#define __TSTORM_FCOE_AG_CONTEXT_AUX5_FLAG (0x1<<0)
-#define __TSTORM_FCOE_AG_CONTEXT_AUX5_FLAG_SHIFT 0
-#define __TSTORM_FCOE_AG_CONTEXT_AUX6_FLAG (0x1<<1)
-#define __TSTORM_FCOE_AG_CONTEXT_AUX6_FLAG_SHIFT 1
-#define __TSTORM_FCOE_AG_CONTEXT_AUX4_CF (0x3<<2)
-#define __TSTORM_FCOE_AG_CONTEXT_AUX4_CF_SHIFT 2
-#define __TSTORM_FCOE_AG_CONTEXT_AUX5_CF (0x3<<4)
-#define __TSTORM_FCOE_AG_CONTEXT_AUX5_CF_SHIFT 4
-#define __TSTORM_FCOE_AG_CONTEXT_AUX6_CF (0x3<<6)
-#define __TSTORM_FCOE_AG_CONTEXT_AUX6_CF_SHIFT 6
-#define __TSTORM_FCOE_AG_CONTEXT_AUX7_CF (0x3<<8)
-#define __TSTORM_FCOE_AG_CONTEXT_AUX7_CF_SHIFT 8
-#define __TSTORM_FCOE_AG_CONTEXT_AUX7_FLAG (0x1<<10)
-#define __TSTORM_FCOE_AG_CONTEXT_AUX7_FLAG_SHIFT 10
-#define __TSTORM_FCOE_AG_CONTEXT_QUEUE0_FLUSH_CF_EN (0x1<<11)
-#define __TSTORM_FCOE_AG_CONTEXT_QUEUE0_FLUSH_CF_EN_SHIFT 11
-#define TSTORM_FCOE_AG_CONTEXT_AUX4_CF_EN (0x1<<12)
-#define TSTORM_FCOE_AG_CONTEXT_AUX4_CF_EN_SHIFT 12
-#define TSTORM_FCOE_AG_CONTEXT_AUX5_CF_EN (0x1<<13)
-#define TSTORM_FCOE_AG_CONTEXT_AUX5_CF_EN_SHIFT 13
-#define TSTORM_FCOE_AG_CONTEXT_AUX6_CF_EN (0x1<<14)
-#define TSTORM_FCOE_AG_CONTEXT_AUX6_CF_EN_SHIFT 14
-#define TSTORM_FCOE_AG_CONTEXT_AUX7_CF_EN (0x1<<15)
-#define TSTORM_FCOE_AG_CONTEXT_AUX7_CF_EN_SHIFT 15
-#elif defined(__LITTLE_ENDIAN)
- u16 agg_vars2;
-#define __TSTORM_FCOE_AG_CONTEXT_AUX5_FLAG (0x1<<0)
-#define __TSTORM_FCOE_AG_CONTEXT_AUX5_FLAG_SHIFT 0
-#define __TSTORM_FCOE_AG_CONTEXT_AUX6_FLAG (0x1<<1)
-#define __TSTORM_FCOE_AG_CONTEXT_AUX6_FLAG_SHIFT 1
-#define __TSTORM_FCOE_AG_CONTEXT_AUX4_CF (0x3<<2)
-#define __TSTORM_FCOE_AG_CONTEXT_AUX4_CF_SHIFT 2
-#define __TSTORM_FCOE_AG_CONTEXT_AUX5_CF (0x3<<4)
-#define __TSTORM_FCOE_AG_CONTEXT_AUX5_CF_SHIFT 4
-#define __TSTORM_FCOE_AG_CONTEXT_AUX6_CF (0x3<<6)
-#define __TSTORM_FCOE_AG_CONTEXT_AUX6_CF_SHIFT 6
-#define __TSTORM_FCOE_AG_CONTEXT_AUX7_CF (0x3<<8)
-#define __TSTORM_FCOE_AG_CONTEXT_AUX7_CF_SHIFT 8
-#define __TSTORM_FCOE_AG_CONTEXT_AUX7_FLAG (0x1<<10)
-#define __TSTORM_FCOE_AG_CONTEXT_AUX7_FLAG_SHIFT 10
-#define __TSTORM_FCOE_AG_CONTEXT_QUEUE0_FLUSH_CF_EN (0x1<<11)
-#define __TSTORM_FCOE_AG_CONTEXT_QUEUE0_FLUSH_CF_EN_SHIFT 11
-#define TSTORM_FCOE_AG_CONTEXT_AUX4_CF_EN (0x1<<12)
-#define TSTORM_FCOE_AG_CONTEXT_AUX4_CF_EN_SHIFT 12
-#define TSTORM_FCOE_AG_CONTEXT_AUX5_CF_EN (0x1<<13)
-#define TSTORM_FCOE_AG_CONTEXT_AUX5_CF_EN_SHIFT 13
-#define TSTORM_FCOE_AG_CONTEXT_AUX6_CF_EN (0x1<<14)
-#define TSTORM_FCOE_AG_CONTEXT_AUX6_CF_EN_SHIFT 14
-#define TSTORM_FCOE_AG_CONTEXT_AUX7_CF_EN (0x1<<15)
-#define TSTORM_FCOE_AG_CONTEXT_AUX7_CF_EN_SHIFT 15
- u16 __agg_val4;
-#endif
- struct tstorm_fcoe_extra_ag_context_section __extra_section;
-};
-
-/*
- * The fcoe aggregative context of Ustorm
- */
-struct ustorm_fcoe_ag_context {
-#if defined(__BIG_ENDIAN)
- u8 __aux_counter_flags;
- u8 agg_vars2;
-#define USTORM_FCOE_AG_CONTEXT_TX_CF (0x3<<0)
-#define USTORM_FCOE_AG_CONTEXT_TX_CF_SHIFT 0
-#define __USTORM_FCOE_AG_CONTEXT_TIMER_CF (0x3<<2)
-#define __USTORM_FCOE_AG_CONTEXT_TIMER_CF_SHIFT 2
-#define USTORM_FCOE_AG_CONTEXT_AGG_MISC4_RULE (0x7<<4)
-#define USTORM_FCOE_AG_CONTEXT_AGG_MISC4_RULE_SHIFT 4
-#define __USTORM_FCOE_AG_CONTEXT_AGG_VAL2_MASK (0x1<<7)
-#define __USTORM_FCOE_AG_CONTEXT_AGG_VAL2_MASK_SHIFT 7
- u8 agg_vars1;
-#define __USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM0 (0x1<<0)
-#define __USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM0_SHIFT 0
-#define USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM1 (0x1<<1)
-#define USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM1_SHIFT 1
-#define USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM2 (0x1<<2)
-#define USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM2_SHIFT 2
-#define USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM3 (0x1<<3)
-#define USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM3_SHIFT 3
-#define USTORM_FCOE_AG_CONTEXT_INV_CF (0x3<<4)
-#define USTORM_FCOE_AG_CONTEXT_INV_CF_SHIFT 4
-#define USTORM_FCOE_AG_CONTEXT_COMPLETION_CF (0x3<<6)
-#define USTORM_FCOE_AG_CONTEXT_COMPLETION_CF_SHIFT 6
- u8 state;
-#elif defined(__LITTLE_ENDIAN)
- u8 state;
- u8 agg_vars1;
-#define __USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM0 (0x1<<0)
-#define __USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM0_SHIFT 0
-#define USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM1 (0x1<<1)
-#define USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM1_SHIFT 1
-#define USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM2 (0x1<<2)
-#define USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM2_SHIFT 2
-#define USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM3 (0x1<<3)
-#define USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM3_SHIFT 3
-#define USTORM_FCOE_AG_CONTEXT_INV_CF (0x3<<4)
-#define USTORM_FCOE_AG_CONTEXT_INV_CF_SHIFT 4
-#define USTORM_FCOE_AG_CONTEXT_COMPLETION_CF (0x3<<6)
-#define USTORM_FCOE_AG_CONTEXT_COMPLETION_CF_SHIFT 6
- u8 agg_vars2;
-#define USTORM_FCOE_AG_CONTEXT_TX_CF (0x3<<0)
-#define USTORM_FCOE_AG_CONTEXT_TX_CF_SHIFT 0
-#define __USTORM_FCOE_AG_CONTEXT_TIMER_CF (0x3<<2)
-#define __USTORM_FCOE_AG_CONTEXT_TIMER_CF_SHIFT 2
-#define USTORM_FCOE_AG_CONTEXT_AGG_MISC4_RULE (0x7<<4)
-#define USTORM_FCOE_AG_CONTEXT_AGG_MISC4_RULE_SHIFT 4
-#define __USTORM_FCOE_AG_CONTEXT_AGG_VAL2_MASK (0x1<<7)
-#define __USTORM_FCOE_AG_CONTEXT_AGG_VAL2_MASK_SHIFT 7
- u8 __aux_counter_flags;
-#endif
-#if defined(__BIG_ENDIAN)
- u8 cdu_usage;
- u8 agg_misc2;
- u16 pbf_tx_seq_ack;
-#elif defined(__LITTLE_ENDIAN)
- u16 pbf_tx_seq_ack;
- u8 agg_misc2;
- u8 cdu_usage;
-#endif
- u32 agg_misc4;
-#if defined(__BIG_ENDIAN)
- u8 agg_val3_th;
- u8 agg_val3;
- u16 agg_misc3;
-#elif defined(__LITTLE_ENDIAN)
- u16 agg_misc3;
- u8 agg_val3;
- u8 agg_val3_th;
-#endif
- u32 expired_task_id;
- u32 agg_misc4_th;
-#if defined(__BIG_ENDIAN)
- u16 cq_prod;
- u16 cq_cons;
-#elif defined(__LITTLE_ENDIAN)
- u16 cq_cons;
- u16 cq_prod;
-#endif
-#if defined(__BIG_ENDIAN)
- u16 __reserved2;
- u8 decision_rules;
-#define USTORM_FCOE_AG_CONTEXT_CQ_DEC_RULE (0x7<<0)
-#define USTORM_FCOE_AG_CONTEXT_CQ_DEC_RULE_SHIFT 0
-#define __USTORM_FCOE_AG_CONTEXT_AGG_VAL3_RULE (0x7<<3)
-#define __USTORM_FCOE_AG_CONTEXT_AGG_VAL3_RULE_SHIFT 3
-#define USTORM_FCOE_AG_CONTEXT_CQ_ARM_N_FLAG (0x1<<6)
-#define USTORM_FCOE_AG_CONTEXT_CQ_ARM_N_FLAG_SHIFT 6
-#define __USTORM_FCOE_AG_CONTEXT_RESERVED1 (0x1<<7)
-#define __USTORM_FCOE_AG_CONTEXT_RESERVED1_SHIFT 7
- u8 decision_rule_enable_bits;
-#define __USTORM_FCOE_AG_CONTEXT_RESERVED_INV_CF_EN (0x1<<0)
-#define __USTORM_FCOE_AG_CONTEXT_RESERVED_INV_CF_EN_SHIFT 0
-#define USTORM_FCOE_AG_CONTEXT_COMPLETION_CF_EN (0x1<<1)
-#define USTORM_FCOE_AG_CONTEXT_COMPLETION_CF_EN_SHIFT 1
-#define USTORM_FCOE_AG_CONTEXT_TX_CF_EN (0x1<<2)
-#define USTORM_FCOE_AG_CONTEXT_TX_CF_EN_SHIFT 2
-#define __USTORM_FCOE_AG_CONTEXT_TIMER_CF_EN (0x1<<3)
-#define __USTORM_FCOE_AG_CONTEXT_TIMER_CF_EN_SHIFT 3
-#define __USTORM_FCOE_AG_CONTEXT_AUX1_CF_EN (0x1<<4)
-#define __USTORM_FCOE_AG_CONTEXT_AUX1_CF_EN_SHIFT 4
-#define __USTORM_FCOE_AG_CONTEXT_QUEUE0_CF_EN (0x1<<5)
-#define __USTORM_FCOE_AG_CONTEXT_QUEUE0_CF_EN_SHIFT 5
-#define __USTORM_FCOE_AG_CONTEXT_AUX3_CF_EN (0x1<<6)
-#define __USTORM_FCOE_AG_CONTEXT_AUX3_CF_EN_SHIFT 6
-#define __USTORM_FCOE_AG_CONTEXT_DQ_CF_EN (0x1<<7)
-#define __USTORM_FCOE_AG_CONTEXT_DQ_CF_EN_SHIFT 7
-#elif defined(__LITTLE_ENDIAN)
- u8 decision_rule_enable_bits;
-#define __USTORM_FCOE_AG_CONTEXT_RESERVED_INV_CF_EN (0x1<<0)
-#define __USTORM_FCOE_AG_CONTEXT_RESERVED_INV_CF_EN_SHIFT 0
-#define USTORM_FCOE_AG_CONTEXT_COMPLETION_CF_EN (0x1<<1)
-#define USTORM_FCOE_AG_CONTEXT_COMPLETION_CF_EN_SHIFT 1
-#define USTORM_FCOE_AG_CONTEXT_TX_CF_EN (0x1<<2)
-#define USTORM_FCOE_AG_CONTEXT_TX_CF_EN_SHIFT 2
-#define __USTORM_FCOE_AG_CONTEXT_TIMER_CF_EN (0x1<<3)
-#define __USTORM_FCOE_AG_CONTEXT_TIMER_CF_EN_SHIFT 3
-#define __USTORM_FCOE_AG_CONTEXT_AUX1_CF_EN (0x1<<4)
-#define __USTORM_FCOE_AG_CONTEXT_AUX1_CF_EN_SHIFT 4
-#define __USTORM_FCOE_AG_CONTEXT_QUEUE0_CF_EN (0x1<<5)
-#define __USTORM_FCOE_AG_CONTEXT_QUEUE0_CF_EN_SHIFT 5
-#define __USTORM_FCOE_AG_CONTEXT_AUX3_CF_EN (0x1<<6)
-#define __USTORM_FCOE_AG_CONTEXT_AUX3_CF_EN_SHIFT 6
-#define __USTORM_FCOE_AG_CONTEXT_DQ_CF_EN (0x1<<7)
-#define __USTORM_FCOE_AG_CONTEXT_DQ_CF_EN_SHIFT 7
- u8 decision_rules;
-#define USTORM_FCOE_AG_CONTEXT_CQ_DEC_RULE (0x7<<0)
-#define USTORM_FCOE_AG_CONTEXT_CQ_DEC_RULE_SHIFT 0
-#define __USTORM_FCOE_AG_CONTEXT_AGG_VAL3_RULE (0x7<<3)
-#define __USTORM_FCOE_AG_CONTEXT_AGG_VAL3_RULE_SHIFT 3
-#define USTORM_FCOE_AG_CONTEXT_CQ_ARM_N_FLAG (0x1<<6)
-#define USTORM_FCOE_AG_CONTEXT_CQ_ARM_N_FLAG_SHIFT 6
-#define __USTORM_FCOE_AG_CONTEXT_RESERVED1 (0x1<<7)
-#define __USTORM_FCOE_AG_CONTEXT_RESERVED1_SHIFT 7
- u16 __reserved2;
-#endif
-};
-
-/*
- * Ethernet context section
- */
-struct xstorm_fcoe_eth_context_section {
-#if defined(__BIG_ENDIAN)
- u8 remote_addr_4;
- u8 remote_addr_5;
- u8 local_addr_0;
- u8 local_addr_1;
-#elif defined(__LITTLE_ENDIAN)
- u8 local_addr_1;
- u8 local_addr_0;
- u8 remote_addr_5;
- u8 remote_addr_4;
-#endif
-#if defined(__BIG_ENDIAN)
- u8 remote_addr_0;
- u8 remote_addr_1;
- u8 remote_addr_2;
- u8 remote_addr_3;
-#elif defined(__LITTLE_ENDIAN)
- u8 remote_addr_3;
- u8 remote_addr_2;
- u8 remote_addr_1;
- u8 remote_addr_0;
-#endif
-#if defined(__BIG_ENDIAN)
- u16 reserved_vlan_type;
- u16 params;
-#define XSTORM_FCOE_ETH_CONTEXT_SECTION_VLAN_ID (0xFFF<<0)
-#define XSTORM_FCOE_ETH_CONTEXT_SECTION_VLAN_ID_SHIFT 0
-#define XSTORM_FCOE_ETH_CONTEXT_SECTION_CFI (0x1<<12)
-#define XSTORM_FCOE_ETH_CONTEXT_SECTION_CFI_SHIFT 12
-#define XSTORM_FCOE_ETH_CONTEXT_SECTION_PRIORITY (0x7<<13)
-#define XSTORM_FCOE_ETH_CONTEXT_SECTION_PRIORITY_SHIFT 13
-#elif defined(__LITTLE_ENDIAN)
- u16 params;
-#define XSTORM_FCOE_ETH_CONTEXT_SECTION_VLAN_ID (0xFFF<<0)
-#define XSTORM_FCOE_ETH_CONTEXT_SECTION_VLAN_ID_SHIFT 0
-#define XSTORM_FCOE_ETH_CONTEXT_SECTION_CFI (0x1<<12)
-#define XSTORM_FCOE_ETH_CONTEXT_SECTION_CFI_SHIFT 12
-#define XSTORM_FCOE_ETH_CONTEXT_SECTION_PRIORITY (0x7<<13)
-#define XSTORM_FCOE_ETH_CONTEXT_SECTION_PRIORITY_SHIFT 13
- u16 reserved_vlan_type;
-#endif
-#if defined(__BIG_ENDIAN)
- u8 local_addr_2;
- u8 local_addr_3;
- u8 local_addr_4;
- u8 local_addr_5;
-#elif defined(__LITTLE_ENDIAN)
- u8 local_addr_5;
- u8 local_addr_4;
- u8 local_addr_3;
- u8 local_addr_2;
-#endif
-};
-
-/*
- * Flags used in FCoE context section - 1 byte
- */
-struct xstorm_fcoe_context_flags {
- u8 flags;
-#define XSTORM_FCOE_CONTEXT_FLAGS_B_PROC_Q (0x3<<0)
-#define XSTORM_FCOE_CONTEXT_FLAGS_B_PROC_Q_SHIFT 0
-#define XSTORM_FCOE_CONTEXT_FLAGS_B_MID_SEQ (0x1<<2)
-#define XSTORM_FCOE_CONTEXT_FLAGS_B_MID_SEQ_SHIFT 2
-#define XSTORM_FCOE_CONTEXT_FLAGS_B_EXCHANGE_CLEANUP_DEFFERED (0x1<<3)
-#define XSTORM_FCOE_CONTEXT_FLAGS_B_EXCHANGE_CLEANUP_DEFFERED_SHIFT 3
-#define XSTORM_FCOE_CONTEXT_FLAGS_B_REC_SUPPORT (0x1<<4)
-#define XSTORM_FCOE_CONTEXT_FLAGS_B_REC_SUPPORT_SHIFT 4
-#define XSTORM_FCOE_CONTEXT_FLAGS_B_SQ_TOGGLE (0x1<<5)
-#define XSTORM_FCOE_CONTEXT_FLAGS_B_SQ_TOGGLE_SHIFT 5
-#define XSTORM_FCOE_CONTEXT_FLAGS_B_XFRQ_TOGGLE (0x1<<6)
-#define XSTORM_FCOE_CONTEXT_FLAGS_B_XFRQ_TOGGLE_SHIFT 6
-#define XSTORM_FCOE_CONTEXT_FLAGS_B_ABTS_DEFFERED (0x1<<7)
-#define XSTORM_FCOE_CONTEXT_FLAGS_B_ABTS_DEFFERED_SHIFT 7
-};
-
-/*
- * FCoE SQ element
- */
-struct fcoe_sqe {
- u16 wqe;
-#define FCOE_SQE_TASK_ID (0x7FFF<<0)
-#define FCOE_SQE_TASK_ID_SHIFT 0
-#define FCOE_SQE_TOGGLE_BIT (0x1<<15)
-#define FCOE_SQE_TOGGLE_BIT_SHIFT 15
-};
-
-/*
- * FCoE XFRQ element
- */
-struct fcoe_xfrqe {
- u16 wqe;
-#define FCOE_XFRQE_TASK_ID (0x7FFF<<0)
-#define FCOE_XFRQE_TASK_ID_SHIFT 0
-#define FCOE_XFRQE_TOGGLE_BIT (0x1<<15)
-#define FCOE_XFRQE_TOGGLE_BIT_SHIFT 15
-};
-
-/*
- * FCoE SQ\XFRQ element
- */
-struct fcoe_cached_wqe {
-#if defined(__BIG_ENDIAN)
- struct fcoe_xfrqe xfrqe;
- struct fcoe_sqe sqe;
-#elif defined(__LITTLE_ENDIAN)
- struct fcoe_sqe sqe;
- struct fcoe_xfrqe xfrqe;
-#endif
-};
-
-struct fcoe_task_ctx_entry_tx_only {
- union fcoe_sgl_ctx sgl_ctx;
-};
-
-struct xstorm_fcoe_task_ctx_entry_rd {
- struct fcoe_task_ctx_entry_tx_only tx_wr;
- struct fcoe_task_ctx_entry_txwr_rxrd tx_wr_rx_rd;
- struct fcoe_task_ctx_entry_tx_rx_cmn cmn;
- struct fcoe_task_ctx_entry_rxwr_txrd rx_wr_tx_rd;
-};
-
-/*
- * Cached SGEs
- */
-struct common_fcoe_sgl {
- struct fcoe_bd_ctx sge[2];
-};
-
-/*
- * FCP_DATA parameters required for transmission
- */
-struct xstorm_fcoe_fcp_data {
- u32 io_rem;
-#if defined(__BIG_ENDIAN)
- u16 cached_sge_off;
- u8 cached_num_sges;
- u8 cached_sge_idx;
-#elif defined(__LITTLE_ENDIAN)
- u8 cached_sge_idx;
- u8 cached_num_sges;
- u16 cached_sge_off;
-#endif
- struct common_fcoe_sgl cached_sgl;
-};
-
-/*
- * FCoE context section
- */
-struct xstorm_fcoe_context_section {
-#if defined(__BIG_ENDIAN)
- u8 vlan_flag;
- u8 s_id[3];
-#elif defined(__LITTLE_ENDIAN)
- u8 s_id[3];
- u8 vlan_flag;
-#endif
-#if defined(__BIG_ENDIAN)
- u8 func_id;
- u8 d_id[3];
-#elif defined(__LITTLE_ENDIAN)
- u8 d_id[3];
- u8 func_id;
-#endif
-#if defined(__BIG_ENDIAN)
- u16 sq_xfrq_lcq_confq_size;
- u16 tx_max_fc_pay_len;
-#elif defined(__LITTLE_ENDIAN)
- u16 tx_max_fc_pay_len;
- u16 sq_xfrq_lcq_confq_size;
-#endif
- u32 lcq_prod;
-#if defined(__BIG_ENDIAN)
- u8 port_id;
- u8 tx_max_conc_seqs_c3;
- u8 seq_id;
- struct xstorm_fcoe_context_flags tx_flags;
-#elif defined(__LITTLE_ENDIAN)
- struct xstorm_fcoe_context_flags tx_flags;
- u8 seq_id;
- u8 tx_max_conc_seqs_c3;
- u8 port_id;
-#endif
-#if defined(__BIG_ENDIAN)
- u16 verify_tx_seq;
- u8 func_mode;
- u8 vnic_id;
-#elif defined(__LITTLE_ENDIAN)
- u8 vnic_id;
- u8 func_mode;
- u16 verify_tx_seq;
-#endif
- struct regpair confq_curr_page_addr;
- struct fcoe_cached_wqe cached_wqe[8];
- struct regpair lcq_base_addr;
- struct xstorm_fcoe_task_ctx_entry_rd tce;
- struct xstorm_fcoe_fcp_data fcp_data;
-#if defined(__BIG_ENDIAN)
- u16 fcoe_tx_stat_params_ram_addr;
- u16 cmng_port_ram_addr;
-#elif defined(__LITTLE_ENDIAN)
- u16 cmng_port_ram_addr;
- u16 fcoe_tx_stat_params_ram_addr;
-#endif
-#if defined(__BIG_ENDIAN)
- u8 fcp_cmd_pb_cmd_size;
- u8 eth_hdr_size;
- u16 pbf_addr;
-#elif defined(__LITTLE_ENDIAN)
- u16 pbf_addr;
- u8 eth_hdr_size;
- u8 fcp_cmd_pb_cmd_size;
-#endif
-#if defined(__BIG_ENDIAN)
- u8 reserved2[2];
- u8 cos;
- u8 dcb_version;
-#elif defined(__LITTLE_ENDIAN)
- u8 dcb_version;
- u8 cos;
- u8 reserved2[2];
-#endif
- u32 reserved3;
- struct regpair reserved4[2];
-};
-
-/*
- * Xstorm FCoE Storm Context
- */
-struct xstorm_fcoe_st_context {
- struct xstorm_fcoe_eth_context_section eth;
- struct xstorm_fcoe_context_section fcoe;
-};
-
-/*
- * Fcoe connection context
- */
-struct fcoe_context {
- struct ustorm_fcoe_st_context ustorm_st_context;
- struct tstorm_fcoe_st_context tstorm_st_context;
- struct xstorm_fcoe_ag_context xstorm_ag_context;
- struct tstorm_fcoe_ag_context tstorm_ag_context;
- struct ustorm_fcoe_ag_context ustorm_ag_context;
- struct timers_block_context timers_context;
- struct xstorm_fcoe_st_context xstorm_st_context;
-};
-
-/*
- * iSCSI context region, used only in iSCSI
- */
-struct ustorm_iscsi_rq_db {
- struct regpair pbl_base;
- struct regpair curr_pbe;
-};
-
-/*
- * iSCSI context region, used only in iSCSI
- */
-struct ustorm_iscsi_r2tq_db {
- struct regpair pbl_base;
- struct regpair curr_pbe;
-};
-
-/*
- * iSCSI context region, used only in iSCSI
- */
-struct ustorm_iscsi_cq_db {
-#if defined(__BIG_ENDIAN)
- u16 cq_sn;
- u16 prod;
-#elif defined(__LITTLE_ENDIAN)
- u16 prod;
- u16 cq_sn;
-#endif
- struct regpair curr_pbe;
-};
-
-/*
- * iSCSI context region, used only in iSCSI
- */
-struct rings_db {
- struct ustorm_iscsi_rq_db rq;
- struct ustorm_iscsi_r2tq_db r2tq;
- struct ustorm_iscsi_cq_db cq[8];
-#if defined(__BIG_ENDIAN)
- u16 rq_prod;
- u16 r2tq_prod;
-#elif defined(__LITTLE_ENDIAN)
- u16 r2tq_prod;
- u16 rq_prod;
-#endif
- struct regpair cq_pbl_base;
-};
-
-/*
- * iSCSI context region, used only in iSCSI
- */
-struct ustorm_iscsi_placement_db {
- u32 sgl_base_lo;
- u32 sgl_base_hi;
- u32 local_sge_0_address_hi;
- u32 local_sge_0_address_lo;
-#if defined(__BIG_ENDIAN)
- u16 curr_sge_offset;
- u16 local_sge_0_size;
-#elif defined(__LITTLE_ENDIAN)
- u16 local_sge_0_size;
- u16 curr_sge_offset;
-#endif
- u32 local_sge_1_address_hi;
- u32 local_sge_1_address_lo;
-#if defined(__BIG_ENDIAN)
- u16 reserved6;
- u16 local_sge_1_size;
-#elif defined(__LITTLE_ENDIAN)
- u16 local_sge_1_size;
- u16 reserved6;
-#endif
-#if defined(__BIG_ENDIAN)
- u8 sgl_size;
- u8 local_sge_index_2b;
- u16 reserved7;
-#elif defined(__LITTLE_ENDIAN)
- u16 reserved7;
- u8 local_sge_index_2b;
- u8 sgl_size;
-#endif
- u32 rem_pdu;
- u32 place_db_bitfield_1;
-#define USTORM_ISCSI_PLACEMENT_DB_REM_PDU_PAYLOAD (0xFFFFFF<<0)
-#define USTORM_ISCSI_PLACEMENT_DB_REM_PDU_PAYLOAD_SHIFT 0
-#define USTORM_ISCSI_PLACEMENT_DB_CQ_ID (0xFF<<24)
-#define USTORM_ISCSI_PLACEMENT_DB_CQ_ID_SHIFT 24
- u32 place_db_bitfield_2;
-#define USTORM_ISCSI_PLACEMENT_DB_BYTES_2_TRUNCATE (0xFFFFFF<<0)
-#define USTORM_ISCSI_PLACEMENT_DB_BYTES_2_TRUNCATE_SHIFT 0
-#define USTORM_ISCSI_PLACEMENT_DB_HOST_SGE_INDEX (0xFF<<24)
-#define USTORM_ISCSI_PLACEMENT_DB_HOST_SGE_INDEX_SHIFT 24
- u32 nal;
-#define USTORM_ISCSI_PLACEMENT_DB_REM_SGE_SIZE (0xFFFFFF<<0)
-#define USTORM_ISCSI_PLACEMENT_DB_REM_SGE_SIZE_SHIFT 0
-#define USTORM_ISCSI_PLACEMENT_DB_EXP_PADDING_2B (0x3<<24)
-#define USTORM_ISCSI_PLACEMENT_DB_EXP_PADDING_2B_SHIFT 24
-#define USTORM_ISCSI_PLACEMENT_DB_EXP_DIGEST_3B (0x7<<26)
-#define USTORM_ISCSI_PLACEMENT_DB_EXP_DIGEST_3B_SHIFT 26
-#define USTORM_ISCSI_PLACEMENT_DB_NAL_LEN_3B (0x7<<29)
-#define USTORM_ISCSI_PLACEMENT_DB_NAL_LEN_3B_SHIFT 29
-};
-
-/*
- * Ustorm iSCSI Storm Context
- */
-struct ustorm_iscsi_st_context {
- u32 exp_stat_sn;
- u32 exp_data_sn;
- struct rings_db ring;
- struct regpair task_pbl_base;
- struct regpair tce_phy_addr;
- struct ustorm_iscsi_placement_db place_db;
- u32 reserved8;
- u32 rem_rcv_len;
-#if defined(__BIG_ENDIAN)
- u16 hdr_itt;
- u16 iscsi_conn_id;
-#elif defined(__LITTLE_ENDIAN)
- u16 iscsi_conn_id;
- u16 hdr_itt;
-#endif
- u32 nal_bytes;
-#if defined(__BIG_ENDIAN)
- u8 hdr_second_byte_union;
- u8 bitfield_0;
-#define USTORM_ISCSI_ST_CONTEXT_BMIDDLEOFPDU (0x1<<0)
-#define USTORM_ISCSI_ST_CONTEXT_BMIDDLEOFPDU_SHIFT 0
-#define USTORM_ISCSI_ST_CONTEXT_BFENCECQE (0x1<<1)
-#define USTORM_ISCSI_ST_CONTEXT_BFENCECQE_SHIFT 1
-#define USTORM_ISCSI_ST_CONTEXT_BRESETCRC (0x1<<2)
-#define USTORM_ISCSI_ST_CONTEXT_BRESETCRC_SHIFT 2
-#define USTORM_ISCSI_ST_CONTEXT_RESERVED1 (0x1F<<3)
-#define USTORM_ISCSI_ST_CONTEXT_RESERVED1_SHIFT 3
- u8 task_pdu_cache_index;
- u8 task_pbe_cache_index;
-#elif defined(__LITTLE_ENDIAN)
- u8 task_pbe_cache_index;
- u8 task_pdu_cache_index;
- u8 bitfield_0;
-#define USTORM_ISCSI_ST_CONTEXT_BMIDDLEOFPDU (0x1<<0)
-#define USTORM_ISCSI_ST_CONTEXT_BMIDDLEOFPDU_SHIFT 0
-#define USTORM_ISCSI_ST_CONTEXT_BFENCECQE (0x1<<1)
-#define USTORM_ISCSI_ST_CONTEXT_BFENCECQE_SHIFT 1
-#define USTORM_ISCSI_ST_CONTEXT_BRESETCRC (0x1<<2)
-#define USTORM_ISCSI_ST_CONTEXT_BRESETCRC_SHIFT 2
-#define USTORM_ISCSI_ST_CONTEXT_RESERVED1 (0x1F<<3)
-#define USTORM_ISCSI_ST_CONTEXT_RESERVED1_SHIFT 3
- u8 hdr_second_byte_union;
-#endif
-#if defined(__BIG_ENDIAN)
- u16 reserved3;
- u8 reserved2;
- u8 acDecrement;
-#elif defined(__LITTLE_ENDIAN)
- u8 acDecrement;
- u8 reserved2;
- u16 reserved3;
-#endif
- u32 task_stat;
-#if defined(__BIG_ENDIAN)
- u8 hdr_opcode;
- u8 num_cqs;
- u16 reserved5;
-#elif defined(__LITTLE_ENDIAN)
- u16 reserved5;
- u8 num_cqs;
- u8 hdr_opcode;
-#endif
- u32 negotiated_rx;
-#define USTORM_ISCSI_ST_CONTEXT_MAX_RECV_PDU_LENGTH (0xFFFFFF<<0)
-#define USTORM_ISCSI_ST_CONTEXT_MAX_RECV_PDU_LENGTH_SHIFT 0
-#define USTORM_ISCSI_ST_CONTEXT_MAX_OUTSTANDING_R2TS (0xFF<<24)
-#define USTORM_ISCSI_ST_CONTEXT_MAX_OUTSTANDING_R2TS_SHIFT 24
- u32 negotiated_rx_and_flags;
-#define USTORM_ISCSI_ST_CONTEXT_MAX_BURST_LENGTH (0xFFFFFF<<0)
-#define USTORM_ISCSI_ST_CONTEXT_MAX_BURST_LENGTH_SHIFT 0
-#define USTORM_ISCSI_ST_CONTEXT_B_CQE_POSTED_OR_HEADER_CACHED (0x1<<24)
-#define USTORM_ISCSI_ST_CONTEXT_B_CQE_POSTED_OR_HEADER_CACHED_SHIFT 24
-#define USTORM_ISCSI_ST_CONTEXT_B_HDR_DIGEST_EN (0x1<<25)
-#define USTORM_ISCSI_ST_CONTEXT_B_HDR_DIGEST_EN_SHIFT 25
-#define USTORM_ISCSI_ST_CONTEXT_B_DATA_DIGEST_EN (0x1<<26)
-#define USTORM_ISCSI_ST_CONTEXT_B_DATA_DIGEST_EN_SHIFT 26
-#define USTORM_ISCSI_ST_CONTEXT_B_PROTOCOL_ERROR (0x1<<27)
-#define USTORM_ISCSI_ST_CONTEXT_B_PROTOCOL_ERROR_SHIFT 27
-#define USTORM_ISCSI_ST_CONTEXT_B_TASK_VALID (0x1<<28)
-#define USTORM_ISCSI_ST_CONTEXT_B_TASK_VALID_SHIFT 28
-#define USTORM_ISCSI_ST_CONTEXT_TASK_TYPE (0x3<<29)
-#define USTORM_ISCSI_ST_CONTEXT_TASK_TYPE_SHIFT 29
-#define USTORM_ISCSI_ST_CONTEXT_B_ALL_DATA_ACKED (0x1<<31)
-#define USTORM_ISCSI_ST_CONTEXT_B_ALL_DATA_ACKED_SHIFT 31
-};
-
-/*
- * TCP context region, shared in TOE, RDMA and ISCSI
- */
-struct tstorm_tcp_st_context_section {
- u32 flags1;
-#define TSTORM_TCP_ST_CONTEXT_SECTION_RTT_SRTT (0xFFFFFF<<0)
-#define TSTORM_TCP_ST_CONTEXT_SECTION_RTT_SRTT_SHIFT 0
-#define TSTORM_TCP_ST_CONTEXT_SECTION_PAWS_INVALID (0x1<<24)
-#define TSTORM_TCP_ST_CONTEXT_SECTION_PAWS_INVALID_SHIFT 24
-#define TSTORM_TCP_ST_CONTEXT_SECTION_TIMESTAMP_EXISTS (0x1<<25)
-#define TSTORM_TCP_ST_CONTEXT_SECTION_TIMESTAMP_EXISTS_SHIFT 25
-#define TSTORM_TCP_ST_CONTEXT_SECTION_RESERVED0 (0x1<<26)
-#define TSTORM_TCP_ST_CONTEXT_SECTION_RESERVED0_SHIFT 26
-#define TSTORM_TCP_ST_CONTEXT_SECTION_STOP_RX_PAYLOAD (0x1<<27)
-#define TSTORM_TCP_ST_CONTEXT_SECTION_STOP_RX_PAYLOAD_SHIFT 27
-#define TSTORM_TCP_ST_CONTEXT_SECTION_KA_ENABLED (0x1<<28)
-#define TSTORM_TCP_ST_CONTEXT_SECTION_KA_ENABLED_SHIFT 28
-#define TSTORM_TCP_ST_CONTEXT_SECTION_FIRST_RTO_ESTIMATE (0x1<<29)
-#define TSTORM_TCP_ST_CONTEXT_SECTION_FIRST_RTO_ESTIMATE_SHIFT 29
-#define TSTORM_TCP_ST_CONTEXT_SECTION_MAX_SEG_RETRANSMIT_EN (0x1<<30)
-#define TSTORM_TCP_ST_CONTEXT_SECTION_MAX_SEG_RETRANSMIT_EN_SHIFT 30
-#define TSTORM_TCP_ST_CONTEXT_SECTION_LAST_ISLE_HAS_FIN (0x1<<31)
-#define TSTORM_TCP_ST_CONTEXT_SECTION_LAST_ISLE_HAS_FIN_SHIFT 31
- u32 flags2;
-#define TSTORM_TCP_ST_CONTEXT_SECTION_RTT_VARIATION (0xFFFFFF<<0)
-#define TSTORM_TCP_ST_CONTEXT_SECTION_RTT_VARIATION_SHIFT 0
-#define TSTORM_TCP_ST_CONTEXT_SECTION_DA_EN (0x1<<24)
-#define TSTORM_TCP_ST_CONTEXT_SECTION_DA_EN_SHIFT 24
-#define TSTORM_TCP_ST_CONTEXT_SECTION_DA_COUNTER_EN (0x1<<25)
-#define TSTORM_TCP_ST_CONTEXT_SECTION_DA_COUNTER_EN_SHIFT 25
-#define __TSTORM_TCP_ST_CONTEXT_SECTION_KA_PROBE_SENT (0x1<<26)
-#define __TSTORM_TCP_ST_CONTEXT_SECTION_KA_PROBE_SENT_SHIFT 26
-#define __TSTORM_TCP_ST_CONTEXT_SECTION_PERSIST_PROBE_SENT (0x1<<27)
-#define __TSTORM_TCP_ST_CONTEXT_SECTION_PERSIST_PROBE_SENT_SHIFT 27
-#define TSTORM_TCP_ST_CONTEXT_SECTION_UPDATE_L2_STATSTICS (0x1<<28)
-#define TSTORM_TCP_ST_CONTEXT_SECTION_UPDATE_L2_STATSTICS_SHIFT 28
-#define TSTORM_TCP_ST_CONTEXT_SECTION_UPDATE_L4_STATSTICS (0x1<<29)
-#define TSTORM_TCP_ST_CONTEXT_SECTION_UPDATE_L4_STATSTICS_SHIFT 29
-#define __TSTORM_TCP_ST_CONTEXT_SECTION_IN_WINDOW_RST_ATTACK (0x1<<30)
-#define __TSTORM_TCP_ST_CONTEXT_SECTION_IN_WINDOW_RST_ATTACK_SHIFT 30
-#define __TSTORM_TCP_ST_CONTEXT_SECTION_IN_WINDOW_SYN_ATTACK (0x1<<31)
-#define __TSTORM_TCP_ST_CONTEXT_SECTION_IN_WINDOW_SYN_ATTACK_SHIFT 31
-#if defined(__BIG_ENDIAN)
- u16 mss;
- u8 tcp_sm_state;
- u8 rto_exp;
-#elif defined(__LITTLE_ENDIAN)
- u8 rto_exp;
- u8 tcp_sm_state;
- u16 mss;
-#endif
- u32 rcv_nxt;
- u32 timestamp_recent;
- u32 timestamp_recent_time;
- u32 cwnd;
- u32 ss_thresh;
- u32 cwnd_accum;
- u32 prev_seg_seq;
- u32 expected_rel_seq;
- u32 recover;
-#if defined(__BIG_ENDIAN)
- u8 retransmit_count;
- u8 ka_max_probe_count;
- u8 persist_probe_count;
- u8 ka_probe_count;
-#elif defined(__LITTLE_ENDIAN)
- u8 ka_probe_count;
- u8 persist_probe_count;
- u8 ka_max_probe_count;
- u8 retransmit_count;
-#endif
-#if defined(__BIG_ENDIAN)
- u8 statistics_counter_id;
- u8 ooo_support_mode;
- u8 snd_wnd_scale;
- u8 dup_ack_count;
-#elif defined(__LITTLE_ENDIAN)
- u8 dup_ack_count;
- u8 snd_wnd_scale;
- u8 ooo_support_mode;
- u8 statistics_counter_id;
-#endif
- u32 retransmit_start_time;
- u32 ka_timeout;
- u32 ka_interval;
- u32 isle_start_seq;
- u32 isle_end_seq;
-#if defined(__BIG_ENDIAN)
- u16 second_isle_address;
- u16 recent_seg_wnd;
-#elif defined(__LITTLE_ENDIAN)
- u16 recent_seg_wnd;
- u16 second_isle_address;
-#endif
-#if defined(__BIG_ENDIAN)
- u8 max_isles_ever_happened;
- u8 isles_number;
- u16 last_isle_address;
-#elif defined(__LITTLE_ENDIAN)
- u16 last_isle_address;
- u8 isles_number;
- u8 max_isles_ever_happened;
-#endif
- u32 max_rt_time;
-#if defined(__BIG_ENDIAN)
- u16 lsb_mac_address;
- u16 vlan_id;
-#elif defined(__LITTLE_ENDIAN)
- u16 vlan_id;
- u16 lsb_mac_address;
-#endif
- u32 msb_mac_address;
- u32 rightmost_received_seq;
-};
-
-/*
- * Termination variables
- */
-struct iscsi_term_vars {
- u8 BitMap;
-#define ISCSI_TERM_VARS_TCP_STATE (0xF<<0)
-#define ISCSI_TERM_VARS_TCP_STATE_SHIFT 0
-#define ISCSI_TERM_VARS_FIN_RECEIVED_SBIT (0x1<<4)
-#define ISCSI_TERM_VARS_FIN_RECEIVED_SBIT_SHIFT 4
-#define ISCSI_TERM_VARS_ACK_ON_FIN_RECEIVED_SBIT (0x1<<5)
-#define ISCSI_TERM_VARS_ACK_ON_FIN_RECEIVED_SBIT_SHIFT 5
-#define ISCSI_TERM_VARS_TERM_ON_CHIP (0x1<<6)
-#define ISCSI_TERM_VARS_TERM_ON_CHIP_SHIFT 6
-#define ISCSI_TERM_VARS_RSRV (0x1<<7)
-#define ISCSI_TERM_VARS_RSRV_SHIFT 7
-};
-
-/*
- * iSCSI context region, used only in iSCSI
- */
-struct tstorm_iscsi_st_context_section {
-#if defined(__BIG_ENDIAN)
- u16 rem_tcp_data_len;
- u16 brb_offset;
-#elif defined(__LITTLE_ENDIAN)
- u16 brb_offset;
- u16 rem_tcp_data_len;
-#endif
- u32 b2nh;
-#if defined(__BIG_ENDIAN)
- u16 rq_cons;
- u8 flags;
-#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_HDR_DIGEST_EN (0x1<<0)
-#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_HDR_DIGEST_EN_SHIFT 0
-#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_DATA_DIGEST_EN (0x1<<1)
-#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_DATA_DIGEST_EN_SHIFT 1
-#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_PARTIAL_HEADER (0x1<<2)
-#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_PARTIAL_HEADER_SHIFT 2
-#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_FULL_FEATURE (0x1<<3)
-#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_FULL_FEATURE_SHIFT 3
-#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_DROP_ALL_PDUS (0x1<<4)
-#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_DROP_ALL_PDUS_SHIFT 4
-#define TSTORM_ISCSI_ST_CONTEXT_SECTION_FLAGS_RSRV (0x7<<5)
-#define TSTORM_ISCSI_ST_CONTEXT_SECTION_FLAGS_RSRV_SHIFT 5
- u8 hdr_bytes_2_fetch;
-#elif defined(__LITTLE_ENDIAN)
- u8 hdr_bytes_2_fetch;
- u8 flags;
-#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_HDR_DIGEST_EN (0x1<<0)
-#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_HDR_DIGEST_EN_SHIFT 0
-#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_DATA_DIGEST_EN (0x1<<1)
-#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_DATA_DIGEST_EN_SHIFT 1
-#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_PARTIAL_HEADER (0x1<<2)
-#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_PARTIAL_HEADER_SHIFT 2
-#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_FULL_FEATURE (0x1<<3)
-#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_FULL_FEATURE_SHIFT 3
-#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_DROP_ALL_PDUS (0x1<<4)
-#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_DROP_ALL_PDUS_SHIFT 4
-#define TSTORM_ISCSI_ST_CONTEXT_SECTION_FLAGS_RSRV (0x7<<5)
-#define TSTORM_ISCSI_ST_CONTEXT_SECTION_FLAGS_RSRV_SHIFT 5
- u16 rq_cons;
-#endif
- struct regpair rq_db_phy_addr;
-#if defined(__BIG_ENDIAN)
- struct iscsi_term_vars term_vars;
- u8 scratchpad_idx;
- u16 iscsi_conn_id;
-#elif defined(__LITTLE_ENDIAN)
- u16 iscsi_conn_id;
- u8 scratchpad_idx;
- struct iscsi_term_vars term_vars;
-#endif
- u32 process_nxt;
-};
-
-/*
- * The iSCSI non-aggregative context of Tstorm
- */
-struct tstorm_iscsi_st_context {
- struct tstorm_tcp_st_context_section tcp;
- struct tstorm_iscsi_st_context_section iscsi;
-};
/*
* The tcp aggregative context section of Xstorm
*/
struct xstorm_tcp_tcp_ag_context_section {
#if defined(__BIG_ENDIAN)
- u8 __tcp_agg_vars1;
+ u8 tcp_agg_vars1;
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_SET_DA_TIMER_CF (0x3<<0)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_SET_DA_TIMER_CF_SHIFT 0
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_ACK_TO_FE_UPDATED (0x3<<2)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_ACK_TO_FE_UPDATED_SHIFT 2
+#define XSTORM_TCP_TCP_AG_CONTEXT_SECTION_SIDEBAND_SENT_CF (0x3<<4)
+#define XSTORM_TCP_TCP_AG_CONTEXT_SECTION_SIDEBAND_SENT_CF_SHIFT 4
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_CLEAR_DA_TIMER_EN (0x1<<6)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_CLEAR_DA_TIMER_EN_SHIFT 6
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_DA_EXPIRATION_FLAG (0x1<<7)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_DA_EXPIRATION_FLAG_SHIFT 7
u8 __da_cnt;
u16 mss;
#elif defined(__LITTLE_ENDIAN)
u16 mss;
u8 __da_cnt;
- u8 __tcp_agg_vars1;
+ u8 tcp_agg_vars1;
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_SET_DA_TIMER_CF (0x3<<0)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_SET_DA_TIMER_CF_SHIFT 0
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_ACK_TO_FE_UPDATED (0x3<<2)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_ACK_TO_FE_UPDATED_SHIFT 2
+#define XSTORM_TCP_TCP_AG_CONTEXT_SECTION_SIDEBAND_SENT_CF (0x3<<4)
+#define XSTORM_TCP_TCP_AG_CONTEXT_SECTION_SIDEBAND_SENT_CF_SHIFT 4
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_CLEAR_DA_TIMER_EN (0x1<<6)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_CLEAR_DA_TIMER_EN_SHIFT 6
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_DA_EXPIRATION_FLAG (0x1<<7)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_DA_EXPIRATION_FLAG_SHIFT 7
#endif
u32 snd_nxt;
u32 tx_wnd;
@@ -2615,7 +1774,7 @@
u32 local_adv_wnd;
#if defined(__BIG_ENDIAN)
u8 __agg_val8_th;
- u8 __agg_val8;
+ u8 __tx_dest;
u16 tcp_agg_vars2;
#define XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_FIN_FLAG (0x1<<0)
#define XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_FIN_FLAG_SHIFT 0
@@ -2631,8 +1790,8 @@
#define XSTORM_TCP_TCP_AG_CONTEXT_SECTION_DA_ENABLE_SHIFT 5
#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_ACK_TO_FE_UPDATED_EN (0x1<<6)
#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_ACK_TO_FE_UPDATED_EN_SHIFT 6
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX3_CF_EN (0x1<<7)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX3_CF_EN_SHIFT 7
+#define XSTORM_TCP_TCP_AG_CONTEXT_SECTION_SIDEBAND_SENT_CF_EN (0x1<<7)
+#define XSTORM_TCP_TCP_AG_CONTEXT_SECTION_SIDEBAND_SENT_CF_EN_SHIFT 7
#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_FIN_FLAG_EN (0x1<<8)
#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_FIN_FLAG_EN_SHIFT 8
#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX1_FLAG (0x1<<9)
@@ -2641,8 +1800,8 @@
#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_SET_RTO_CF_SHIFT 10
#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TS_TO_ECHO_UPDATED_CF (0x3<<12)
#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TS_TO_ECHO_UPDATED_CF_SHIFT 12
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX8_CF (0x3<<14)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX8_CF_SHIFT 14
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_DEST_UPDATED_CF (0x3<<14)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_DEST_UPDATED_CF_SHIFT 14
#elif defined(__LITTLE_ENDIAN)
u16 tcp_agg_vars2;
#define XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_FIN_FLAG (0x1<<0)
@@ -2659,8 +1818,8 @@
#define XSTORM_TCP_TCP_AG_CONTEXT_SECTION_DA_ENABLE_SHIFT 5
#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_ACK_TO_FE_UPDATED_EN (0x1<<6)
#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_ACK_TO_FE_UPDATED_EN_SHIFT 6
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX3_CF_EN (0x1<<7)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX3_CF_EN_SHIFT 7
+#define XSTORM_TCP_TCP_AG_CONTEXT_SECTION_SIDEBAND_SENT_CF_EN (0x1<<7)
+#define XSTORM_TCP_TCP_AG_CONTEXT_SECTION_SIDEBAND_SENT_CF_EN_SHIFT 7
#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_FIN_FLAG_EN (0x1<<8)
#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_FIN_FLAG_EN_SHIFT 8
#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX1_FLAG (0x1<<9)
@@ -2669,9 +1828,9 @@
#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_SET_RTO_CF_SHIFT 10
#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TS_TO_ECHO_UPDATED_CF (0x3<<12)
#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TS_TO_ECHO_UPDATED_CF_SHIFT 12
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX8_CF (0x3<<14)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX8_CF_SHIFT 14
- u8 __agg_val8;
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_DEST_UPDATED_CF (0x3<<14)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_DEST_UPDATED_CF_SHIFT 14
+ u8 __tx_dest;
u8 __agg_val8_th;
#endif
u32 ack_to_far_end;
@@ -2699,8 +1858,8 @@
u32 tcp_agg_vars6;
#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TS_TO_ECHO_CF_EN (0x1<<0)
#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TS_TO_ECHO_CF_EN_SHIFT 0
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX8_CF_EN (0x1<<1)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX8_CF_EN_SHIFT 1
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_DEST_UPDATED_CF_EN (0x1<<1)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_DEST_UPDATED_CF_EN_SHIFT 1
#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX9_CF_EN (0x1<<2)
#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX9_CF_EN_SHIFT 2
#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX10_CF_EN (0x1<<3)
@@ -2997,321 +2156,2116 @@
u32 rst_seq_num;
};
-/*
- * The tcp aggregative context section of Tstorm
- */
-struct tstorm_tcp_tcp_ag_context_section {
- u32 __agg_val1;
-#if defined(__BIG_ENDIAN)
- u8 __tcp_agg_vars2;
- u8 __agg_val3;
- u16 __agg_val2;
-#elif defined(__LITTLE_ENDIAN)
- u16 __agg_val2;
- u8 __agg_val3;
- u8 __tcp_agg_vars2;
-#endif
-#if defined(__BIG_ENDIAN)
- u16 __agg_val5;
- u8 __agg_val6;
- u8 __tcp_agg_vars3;
-#elif defined(__LITTLE_ENDIAN)
- u8 __tcp_agg_vars3;
- u8 __agg_val6;
- u16 __agg_val5;
-#endif
- u32 snd_nxt;
- u32 rtt_seq;
- u32 rtt_time;
- u32 __reserved66;
- u32 wnd_right_edge;
- u32 tcp_agg_vars1;
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_FIN_SENT_FLAG (0x1<<0)
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_FIN_SENT_FLAG_SHIFT 0
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_LAST_PACKET_FIN_FLAG (0x1<<1)
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_LAST_PACKET_FIN_FLAG_SHIFT 1
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_WND_UPD_CF (0x3<<2)
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_WND_UPD_CF_SHIFT 2
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_TIMEOUT_CF (0x3<<4)
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_TIMEOUT_CF_SHIFT 4
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_WND_UPD_CF_EN (0x1<<6)
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_WND_UPD_CF_EN_SHIFT 6
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_TIMEOUT_CF_EN (0x1<<7)
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_TIMEOUT_CF_EN_SHIFT 7
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_RETRANSMIT_SEQ_EN (0x1<<8)
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_RETRANSMIT_SEQ_EN_SHIFT 8
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_SND_NXT_EN (0x1<<9)
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_SND_NXT_EN_SHIFT 9
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX1_FLAG (0x1<<10)
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX1_FLAG_SHIFT 10
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX2_FLAG (0x1<<11)
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX2_FLAG_SHIFT 11
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX1_CF_EN (0x1<<12)
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX1_CF_EN_SHIFT 12
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX2_CF_EN (0x1<<13)
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX2_CF_EN_SHIFT 13
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX1_CF (0x3<<14)
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX1_CF_SHIFT 14
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX2_CF (0x3<<16)
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX2_CF_SHIFT 16
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_BLOCKED (0x1<<18)
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_BLOCKED_SHIFT 18
-#define __TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX10_CF_EN (0x1<<19)
-#define __TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX10_CF_EN_SHIFT 19
-#define __TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX11_CF_EN (0x1<<20)
-#define __TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX11_CF_EN_SHIFT 20
-#define __TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX12_CF_EN (0x1<<21)
-#define __TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX12_CF_EN_SHIFT 21
-#define __TSTORM_TCP_TCP_AG_CONTEXT_SECTION_RESERVED1 (0x3<<22)
-#define __TSTORM_TCP_TCP_AG_CONTEXT_SECTION_RESERVED1_SHIFT 22
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_RETRANSMIT_PEND_SEQ (0xF<<24)
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_RETRANSMIT_PEND_SEQ_SHIFT 24
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_RETRANSMIT_DONE_SEQ (0xF<<28)
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_RETRANSMIT_DONE_SEQ_SHIFT 28
- u32 snd_max;
- u32 snd_una;
- u32 __reserved2;
-};
/*
- * The iscsi aggregative context of Tstorm
+ * The L5cm aggregative context of XStorm
*/
-struct tstorm_iscsi_ag_context {
+struct xstorm_l5cm_ag_context {
#if defined(__BIG_ENDIAN)
- u16 ulp_credit;
+ u16 agg_val1;
u8 agg_vars1;
-#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM0 (0x1<<0)
-#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM0_SHIFT 0
-#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM1 (0x1<<1)
-#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM1_SHIFT 1
-#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM2 (0x1<<2)
-#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM2_SHIFT 2
-#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM3 (0x1<<3)
-#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM3_SHIFT 3
-#define __TSTORM_ISCSI_AG_CONTEXT_QUEUES_FLUSH_Q0_CF (0x3<<4)
-#define __TSTORM_ISCSI_AG_CONTEXT_QUEUES_FLUSH_Q0_CF_SHIFT 4
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX3_FLAG (0x1<<6)
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX3_FLAG_SHIFT 6
-#define __TSTORM_ISCSI_AG_CONTEXT_ACK_ON_FIN_SENT_FLAG (0x1<<7)
-#define __TSTORM_ISCSI_AG_CONTEXT_ACK_ON_FIN_SENT_FLAG_SHIFT 7
+#define __XSTORM_L5CM_AG_CONTEXT_EXISTS_IN_QM0 (0x1<<0)
+#define __XSTORM_L5CM_AG_CONTEXT_EXISTS_IN_QM0_SHIFT 0
+#define XSTORM_L5CM_AG_CONTEXT_EXISTS_IN_QM1 (0x1<<1)
+#define XSTORM_L5CM_AG_CONTEXT_EXISTS_IN_QM1_SHIFT 1
+#define XSTORM_L5CM_AG_CONTEXT_EXISTS_IN_QM2 (0x1<<2)
+#define XSTORM_L5CM_AG_CONTEXT_EXISTS_IN_QM2_SHIFT 2
+#define XSTORM_L5CM_AG_CONTEXT_EXISTS_IN_QM3 (0x1<<3)
+#define XSTORM_L5CM_AG_CONTEXT_EXISTS_IN_QM3_SHIFT 3
+#define __XSTORM_L5CM_AG_CONTEXT_MORE_TO_SEND_EN (0x1<<4)
+#define __XSTORM_L5CM_AG_CONTEXT_MORE_TO_SEND_EN_SHIFT 4
+#define XSTORM_L5CM_AG_CONTEXT_NAGLE_EN (0x1<<5)
+#define XSTORM_L5CM_AG_CONTEXT_NAGLE_EN_SHIFT 5
+#define __XSTORM_L5CM_AG_CONTEXT_DQ_SPARE_FLAG (0x1<<6)
+#define __XSTORM_L5CM_AG_CONTEXT_DQ_SPARE_FLAG_SHIFT 6
+#define __XSTORM_L5CM_AG_CONTEXT_UNA_GT_NXT_EN (0x1<<7)
+#define __XSTORM_L5CM_AG_CONTEXT_UNA_GT_NXT_EN_SHIFT 7
u8 state;
#elif defined(__LITTLE_ENDIAN)
u8 state;
u8 agg_vars1;
-#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM0 (0x1<<0)
-#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM0_SHIFT 0
-#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM1 (0x1<<1)
-#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM1_SHIFT 1
-#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM2 (0x1<<2)
-#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM2_SHIFT 2
-#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM3 (0x1<<3)
-#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM3_SHIFT 3
-#define __TSTORM_ISCSI_AG_CONTEXT_QUEUES_FLUSH_Q0_CF (0x3<<4)
-#define __TSTORM_ISCSI_AG_CONTEXT_QUEUES_FLUSH_Q0_CF_SHIFT 4
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX3_FLAG (0x1<<6)
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX3_FLAG_SHIFT 6
-#define __TSTORM_ISCSI_AG_CONTEXT_ACK_ON_FIN_SENT_FLAG (0x1<<7)
-#define __TSTORM_ISCSI_AG_CONTEXT_ACK_ON_FIN_SENT_FLAG_SHIFT 7
- u16 ulp_credit;
+#define __XSTORM_L5CM_AG_CONTEXT_EXISTS_IN_QM0 (0x1<<0)
+#define __XSTORM_L5CM_AG_CONTEXT_EXISTS_IN_QM0_SHIFT 0
+#define XSTORM_L5CM_AG_CONTEXT_EXISTS_IN_QM1 (0x1<<1)
+#define XSTORM_L5CM_AG_CONTEXT_EXISTS_IN_QM1_SHIFT 1
+#define XSTORM_L5CM_AG_CONTEXT_EXISTS_IN_QM2 (0x1<<2)
+#define XSTORM_L5CM_AG_CONTEXT_EXISTS_IN_QM2_SHIFT 2
+#define XSTORM_L5CM_AG_CONTEXT_EXISTS_IN_QM3 (0x1<<3)
+#define XSTORM_L5CM_AG_CONTEXT_EXISTS_IN_QM3_SHIFT 3
+#define __XSTORM_L5CM_AG_CONTEXT_MORE_TO_SEND_EN (0x1<<4)
+#define __XSTORM_L5CM_AG_CONTEXT_MORE_TO_SEND_EN_SHIFT 4
+#define XSTORM_L5CM_AG_CONTEXT_NAGLE_EN (0x1<<5)
+#define XSTORM_L5CM_AG_CONTEXT_NAGLE_EN_SHIFT 5
+#define __XSTORM_L5CM_AG_CONTEXT_DQ_SPARE_FLAG (0x1<<6)
+#define __XSTORM_L5CM_AG_CONTEXT_DQ_SPARE_FLAG_SHIFT 6
+#define __XSTORM_L5CM_AG_CONTEXT_UNA_GT_NXT_EN (0x1<<7)
+#define __XSTORM_L5CM_AG_CONTEXT_UNA_GT_NXT_EN_SHIFT 7
+ u16 agg_val1;
#endif
#if defined(__BIG_ENDIAN)
- u16 __agg_val4;
- u16 agg_vars2;
-#define __TSTORM_ISCSI_AG_CONTEXT_MSL_TIMER_SET_FLAG (0x1<<0)
-#define __TSTORM_ISCSI_AG_CONTEXT_MSL_TIMER_SET_FLAG_SHIFT 0
-#define __TSTORM_ISCSI_AG_CONTEXT_FIN_SENT_FIRST_FLAG (0x1<<1)
-#define __TSTORM_ISCSI_AG_CONTEXT_FIN_SENT_FIRST_FLAG_SHIFT 1
-#define __TSTORM_ISCSI_AG_CONTEXT_RST_SENT_CF (0x3<<2)
-#define __TSTORM_ISCSI_AG_CONTEXT_RST_SENT_CF_SHIFT 2
-#define __TSTORM_ISCSI_AG_CONTEXT_WAKEUP_CALL_CF (0x3<<4)
-#define __TSTORM_ISCSI_AG_CONTEXT_WAKEUP_CALL_CF_SHIFT 4
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX6_CF (0x3<<6)
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX6_CF_SHIFT 6
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX7_CF (0x3<<8)
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX7_CF_SHIFT 8
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX7_FLAG (0x1<<10)
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX7_FLAG_SHIFT 10
-#define __TSTORM_ISCSI_AG_CONTEXT_QUEUES_FLUSH_Q0_CF_EN (0x1<<11)
-#define __TSTORM_ISCSI_AG_CONTEXT_QUEUES_FLUSH_Q0_CF_EN_SHIFT 11
-#define __TSTORM_ISCSI_AG_CONTEXT_RST_SENT_CF_EN (0x1<<12)
-#define __TSTORM_ISCSI_AG_CONTEXT_RST_SENT_CF_EN_SHIFT 12
-#define __TSTORM_ISCSI_AG_CONTEXT_WAKEUP_CALL_CF_EN (0x1<<13)
-#define __TSTORM_ISCSI_AG_CONTEXT_WAKEUP_CALL_CF_EN_SHIFT 13
-#define TSTORM_ISCSI_AG_CONTEXT_AUX6_CF_EN (0x1<<14)
-#define TSTORM_ISCSI_AG_CONTEXT_AUX6_CF_EN_SHIFT 14
-#define TSTORM_ISCSI_AG_CONTEXT_AUX7_CF_EN (0x1<<15)
-#define TSTORM_ISCSI_AG_CONTEXT_AUX7_CF_EN_SHIFT 15
-#elif defined(__LITTLE_ENDIAN)
- u16 agg_vars2;
-#define __TSTORM_ISCSI_AG_CONTEXT_MSL_TIMER_SET_FLAG (0x1<<0)
-#define __TSTORM_ISCSI_AG_CONTEXT_MSL_TIMER_SET_FLAG_SHIFT 0
-#define __TSTORM_ISCSI_AG_CONTEXT_FIN_SENT_FIRST_FLAG (0x1<<1)
-#define __TSTORM_ISCSI_AG_CONTEXT_FIN_SENT_FIRST_FLAG_SHIFT 1
-#define __TSTORM_ISCSI_AG_CONTEXT_RST_SENT_CF (0x3<<2)
-#define __TSTORM_ISCSI_AG_CONTEXT_RST_SENT_CF_SHIFT 2
-#define __TSTORM_ISCSI_AG_CONTEXT_WAKEUP_CALL_CF (0x3<<4)
-#define __TSTORM_ISCSI_AG_CONTEXT_WAKEUP_CALL_CF_SHIFT 4
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX6_CF (0x3<<6)
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX6_CF_SHIFT 6
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX7_CF (0x3<<8)
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX7_CF_SHIFT 8
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX7_FLAG (0x1<<10)
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX7_FLAG_SHIFT 10
-#define __TSTORM_ISCSI_AG_CONTEXT_QUEUES_FLUSH_Q0_CF_EN (0x1<<11)
-#define __TSTORM_ISCSI_AG_CONTEXT_QUEUES_FLUSH_Q0_CF_EN_SHIFT 11
-#define __TSTORM_ISCSI_AG_CONTEXT_RST_SENT_CF_EN (0x1<<12)
-#define __TSTORM_ISCSI_AG_CONTEXT_RST_SENT_CF_EN_SHIFT 12
-#define __TSTORM_ISCSI_AG_CONTEXT_WAKEUP_CALL_CF_EN (0x1<<13)
-#define __TSTORM_ISCSI_AG_CONTEXT_WAKEUP_CALL_CF_EN_SHIFT 13
-#define TSTORM_ISCSI_AG_CONTEXT_AUX6_CF_EN (0x1<<14)
-#define TSTORM_ISCSI_AG_CONTEXT_AUX6_CF_EN_SHIFT 14
-#define TSTORM_ISCSI_AG_CONTEXT_AUX7_CF_EN (0x1<<15)
-#define TSTORM_ISCSI_AG_CONTEXT_AUX7_CF_EN_SHIFT 15
- u16 __agg_val4;
-#endif
- struct tstorm_tcp_tcp_ag_context_section tcp;
-};
-
-/*
- * The iscsi aggregative context of Ustorm
- */
-struct ustorm_iscsi_ag_context {
-#if defined(__BIG_ENDIAN)
- u8 __aux_counter_flags;
+ u8 cdu_reserved;
+ u8 __agg_vars4;
+ u8 agg_vars3;
+#define XSTORM_L5CM_AG_CONTEXT_PHYSICAL_QUEUE_NUM2 (0x3F<<0)
+#define XSTORM_L5CM_AG_CONTEXT_PHYSICAL_QUEUE_NUM2_SHIFT 0
+#define __XSTORM_L5CM_AG_CONTEXT_RX_TS_EN_CF (0x3<<6)
+#define __XSTORM_L5CM_AG_CONTEXT_RX_TS_EN_CF_SHIFT 6
u8 agg_vars2;
-#define USTORM_ISCSI_AG_CONTEXT_TX_CF (0x3<<0)
-#define USTORM_ISCSI_AG_CONTEXT_TX_CF_SHIFT 0
-#define __USTORM_ISCSI_AG_CONTEXT_TIMER_CF (0x3<<2)
-#define __USTORM_ISCSI_AG_CONTEXT_TIMER_CF_SHIFT 2
-#define USTORM_ISCSI_AG_CONTEXT_AGG_MISC4_RULE (0x7<<4)
-#define USTORM_ISCSI_AG_CONTEXT_AGG_MISC4_RULE_SHIFT 4
-#define __USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_MASK (0x1<<7)
-#define __USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_MASK_SHIFT 7
- u8 agg_vars1;
-#define __USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM0 (0x1<<0)
-#define __USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM0_SHIFT 0
-#define USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM1 (0x1<<1)
-#define USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM1_SHIFT 1
-#define USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM2 (0x1<<2)
-#define USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM2_SHIFT 2
-#define USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM3 (0x1<<3)
-#define USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM3_SHIFT 3
-#define USTORM_ISCSI_AG_CONTEXT_INV_CF (0x3<<4)
-#define USTORM_ISCSI_AG_CONTEXT_INV_CF_SHIFT 4
-#define USTORM_ISCSI_AG_CONTEXT_COMPLETION_CF (0x3<<6)
-#define USTORM_ISCSI_AG_CONTEXT_COMPLETION_CF_SHIFT 6
- u8 state;
+#define XSTORM_L5CM_AG_CONTEXT_AUX4_CF (0x3<<0)
+#define XSTORM_L5CM_AG_CONTEXT_AUX4_CF_SHIFT 0
+#define __XSTORM_L5CM_AG_CONTEXT_DQ_SPARE_FLAG_EN (0x1<<2)
+#define __XSTORM_L5CM_AG_CONTEXT_DQ_SPARE_FLAG_EN_SHIFT 2
+#define __XSTORM_L5CM_AG_CONTEXT_AUX8_FLAG (0x1<<3)
+#define __XSTORM_L5CM_AG_CONTEXT_AUX8_FLAG_SHIFT 3
+#define __XSTORM_L5CM_AG_CONTEXT_AUX9_FLAG (0x1<<4)
+#define __XSTORM_L5CM_AG_CONTEXT_AUX9_FLAG_SHIFT 4
+#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE1 (0x3<<5)
+#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE1_SHIFT 5
+#define XSTORM_L5CM_AG_CONTEXT_AUX4_CF_EN (0x1<<7)
+#define XSTORM_L5CM_AG_CONTEXT_AUX4_CF_EN_SHIFT 7
#elif defined(__LITTLE_ENDIAN)
- u8 state;
- u8 agg_vars1;
-#define __USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM0 (0x1<<0)
-#define __USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM0_SHIFT 0
-#define USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM1 (0x1<<1)
-#define USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM1_SHIFT 1
-#define USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM2 (0x1<<2)
-#define USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM2_SHIFT 2
-#define USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM3 (0x1<<3)
-#define USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM3_SHIFT 3
-#define USTORM_ISCSI_AG_CONTEXT_INV_CF (0x3<<4)
-#define USTORM_ISCSI_AG_CONTEXT_INV_CF_SHIFT 4
-#define USTORM_ISCSI_AG_CONTEXT_COMPLETION_CF (0x3<<6)
-#define USTORM_ISCSI_AG_CONTEXT_COMPLETION_CF_SHIFT 6
u8 agg_vars2;
-#define USTORM_ISCSI_AG_CONTEXT_TX_CF (0x3<<0)
-#define USTORM_ISCSI_AG_CONTEXT_TX_CF_SHIFT 0
-#define __USTORM_ISCSI_AG_CONTEXT_TIMER_CF (0x3<<2)
-#define __USTORM_ISCSI_AG_CONTEXT_TIMER_CF_SHIFT 2
-#define USTORM_ISCSI_AG_CONTEXT_AGG_MISC4_RULE (0x7<<4)
-#define USTORM_ISCSI_AG_CONTEXT_AGG_MISC4_RULE_SHIFT 4
-#define __USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_MASK (0x1<<7)
-#define __USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_MASK_SHIFT 7
- u8 __aux_counter_flags;
+#define XSTORM_L5CM_AG_CONTEXT_AUX4_CF (0x3<<0)
+#define XSTORM_L5CM_AG_CONTEXT_AUX4_CF_SHIFT 0
+#define __XSTORM_L5CM_AG_CONTEXT_DQ_SPARE_FLAG_EN (0x1<<2)
+#define __XSTORM_L5CM_AG_CONTEXT_DQ_SPARE_FLAG_EN_SHIFT 2
+#define __XSTORM_L5CM_AG_CONTEXT_AUX8_FLAG (0x1<<3)
+#define __XSTORM_L5CM_AG_CONTEXT_AUX8_FLAG_SHIFT 3
+#define __XSTORM_L5CM_AG_CONTEXT_AUX9_FLAG (0x1<<4)
+#define __XSTORM_L5CM_AG_CONTEXT_AUX9_FLAG_SHIFT 4
+#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE1 (0x3<<5)
+#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE1_SHIFT 5
+#define XSTORM_L5CM_AG_CONTEXT_AUX4_CF_EN (0x1<<7)
+#define XSTORM_L5CM_AG_CONTEXT_AUX4_CF_EN_SHIFT 7
+ u8 agg_vars3;
+#define XSTORM_L5CM_AG_CONTEXT_PHYSICAL_QUEUE_NUM2 (0x3F<<0)
+#define XSTORM_L5CM_AG_CONTEXT_PHYSICAL_QUEUE_NUM2_SHIFT 0
+#define __XSTORM_L5CM_AG_CONTEXT_RX_TS_EN_CF (0x3<<6)
+#define __XSTORM_L5CM_AG_CONTEXT_RX_TS_EN_CF_SHIFT 6
+ u8 __agg_vars4;
+ u8 cdu_reserved;
+#endif
+ u32 more_to_send;
+#if defined(__BIG_ENDIAN)
+ u16 agg_vars5;
+#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE5 (0x3<<0)
+#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE5_SHIFT 0
+#define XSTORM_L5CM_AG_CONTEXT_PHYSICAL_QUEUE_NUM0 (0x3F<<2)
+#define XSTORM_L5CM_AG_CONTEXT_PHYSICAL_QUEUE_NUM0_SHIFT 2
+#define XSTORM_L5CM_AG_CONTEXT_PHYSICAL_QUEUE_NUM1 (0x3F<<8)
+#define XSTORM_L5CM_AG_CONTEXT_PHYSICAL_QUEUE_NUM1_SHIFT 8
+#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE2 (0x3<<14)
+#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE2_SHIFT 14
+ u16 agg_val4_th;
+#elif defined(__LITTLE_ENDIAN)
+ u16 agg_val4_th;
+ u16 agg_vars5;
+#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE5 (0x3<<0)
+#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE5_SHIFT 0
+#define XSTORM_L5CM_AG_CONTEXT_PHYSICAL_QUEUE_NUM0 (0x3F<<2)
+#define XSTORM_L5CM_AG_CONTEXT_PHYSICAL_QUEUE_NUM0_SHIFT 2
+#define XSTORM_L5CM_AG_CONTEXT_PHYSICAL_QUEUE_NUM1 (0x3F<<8)
+#define XSTORM_L5CM_AG_CONTEXT_PHYSICAL_QUEUE_NUM1_SHIFT 8
+#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE2 (0x3<<14)
+#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE2_SHIFT 14
+#endif
+ struct xstorm_tcp_tcp_ag_context_section tcp;
+#if defined(__BIG_ENDIAN)
+ u16 agg_vars7;
+#define __XSTORM_L5CM_AG_CONTEXT_AGG_VAL11_DECISION_RULE (0x7<<0)
+#define __XSTORM_L5CM_AG_CONTEXT_AGG_VAL11_DECISION_RULE_SHIFT 0
+#define __XSTORM_L5CM_AG_CONTEXT_AUX13_FLAG (0x1<<3)
+#define __XSTORM_L5CM_AG_CONTEXT_AUX13_FLAG_SHIFT 3
+#define __XSTORM_L5CM_AG_CONTEXT_STORMS_SYNC_CF (0x3<<4)
+#define __XSTORM_L5CM_AG_CONTEXT_STORMS_SYNC_CF_SHIFT 4
+#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE3 (0x3<<6)
+#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE3_SHIFT 6
+#define XSTORM_L5CM_AG_CONTEXT_AUX1_CF (0x3<<8)
+#define XSTORM_L5CM_AG_CONTEXT_AUX1_CF_SHIFT 8
+#define __XSTORM_L5CM_AG_CONTEXT_COMPLETION_SEQ_DECISION_MASK (0x1<<10)
+#define __XSTORM_L5CM_AG_CONTEXT_COMPLETION_SEQ_DECISION_MASK_SHIFT 10
+#define __XSTORM_L5CM_AG_CONTEXT_AUX1_CF_EN (0x1<<11)
+#define __XSTORM_L5CM_AG_CONTEXT_AUX1_CF_EN_SHIFT 11
+#define __XSTORM_L5CM_AG_CONTEXT_AUX10_FLAG (0x1<<12)
+#define __XSTORM_L5CM_AG_CONTEXT_AUX10_FLAG_SHIFT 12
+#define __XSTORM_L5CM_AG_CONTEXT_AUX11_FLAG (0x1<<13)
+#define __XSTORM_L5CM_AG_CONTEXT_AUX11_FLAG_SHIFT 13
+#define __XSTORM_L5CM_AG_CONTEXT_AUX12_FLAG (0x1<<14)
+#define __XSTORM_L5CM_AG_CONTEXT_AUX12_FLAG_SHIFT 14
+#define __XSTORM_L5CM_AG_CONTEXT_RX_WND_SCL_EN (0x1<<15)
+#define __XSTORM_L5CM_AG_CONTEXT_RX_WND_SCL_EN_SHIFT 15
+ u8 agg_val3_th;
+ u8 agg_vars6;
+#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE6 (0x7<<0)
+#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE6_SHIFT 0
+#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE7 (0x7<<3)
+#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE7_SHIFT 3
+#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE4 (0x3<<6)
+#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE4_SHIFT 6
+#elif defined(__LITTLE_ENDIAN)
+ u8 agg_vars6;
+#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE6 (0x7<<0)
+#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE6_SHIFT 0
+#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE7 (0x7<<3)
+#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE7_SHIFT 3
+#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE4 (0x3<<6)
+#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE4_SHIFT 6
+ u8 agg_val3_th;
+ u16 agg_vars7;
+#define __XSTORM_L5CM_AG_CONTEXT_AGG_VAL11_DECISION_RULE (0x7<<0)
+#define __XSTORM_L5CM_AG_CONTEXT_AGG_VAL11_DECISION_RULE_SHIFT 0
+#define __XSTORM_L5CM_AG_CONTEXT_AUX13_FLAG (0x1<<3)
+#define __XSTORM_L5CM_AG_CONTEXT_AUX13_FLAG_SHIFT 3
+#define __XSTORM_L5CM_AG_CONTEXT_STORMS_SYNC_CF (0x3<<4)
+#define __XSTORM_L5CM_AG_CONTEXT_STORMS_SYNC_CF_SHIFT 4
+#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE3 (0x3<<6)
+#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE3_SHIFT 6
+#define XSTORM_L5CM_AG_CONTEXT_AUX1_CF (0x3<<8)
+#define XSTORM_L5CM_AG_CONTEXT_AUX1_CF_SHIFT 8
+#define __XSTORM_L5CM_AG_CONTEXT_COMPLETION_SEQ_DECISION_MASK (0x1<<10)
+#define __XSTORM_L5CM_AG_CONTEXT_COMPLETION_SEQ_DECISION_MASK_SHIFT 10
+#define __XSTORM_L5CM_AG_CONTEXT_AUX1_CF_EN (0x1<<11)
+#define __XSTORM_L5CM_AG_CONTEXT_AUX1_CF_EN_SHIFT 11
+#define __XSTORM_L5CM_AG_CONTEXT_AUX10_FLAG (0x1<<12)
+#define __XSTORM_L5CM_AG_CONTEXT_AUX10_FLAG_SHIFT 12
+#define __XSTORM_L5CM_AG_CONTEXT_AUX11_FLAG (0x1<<13)
+#define __XSTORM_L5CM_AG_CONTEXT_AUX11_FLAG_SHIFT 13
+#define __XSTORM_L5CM_AG_CONTEXT_AUX12_FLAG (0x1<<14)
+#define __XSTORM_L5CM_AG_CONTEXT_AUX12_FLAG_SHIFT 14
+#define __XSTORM_L5CM_AG_CONTEXT_RX_WND_SCL_EN (0x1<<15)
+#define __XSTORM_L5CM_AG_CONTEXT_RX_WND_SCL_EN_SHIFT 15
#endif
#if defined(__BIG_ENDIAN)
- u8 cdu_usage;
- u8 agg_misc2;
- u16 __cq_local_comp_itt_val;
+ u16 __agg_val11_th;
+ u16 __gen_data;
#elif defined(__LITTLE_ENDIAN)
- u16 __cq_local_comp_itt_val;
- u8 agg_misc2;
- u8 cdu_usage;
+ u16 __gen_data;
+ u16 __agg_val11_th;
#endif
+#if defined(__BIG_ENDIAN)
+ u8 __reserved1;
+ u8 __agg_val6_th;
+ u16 __agg_val9;
+#elif defined(__LITTLE_ENDIAN)
+ u16 __agg_val9;
+ u8 __agg_val6_th;
+ u8 __reserved1;
+#endif
+#if defined(__BIG_ENDIAN)
+ u16 agg_val2_th;
+ u16 agg_val2;
+#elif defined(__LITTLE_ENDIAN)
+ u16 agg_val2;
+ u16 agg_val2_th;
+#endif
+ u32 agg_vars8;
+#define XSTORM_L5CM_AG_CONTEXT_AGG_MISC2 (0xFFFFFF<<0)
+#define XSTORM_L5CM_AG_CONTEXT_AGG_MISC2_SHIFT 0
+#define XSTORM_L5CM_AG_CONTEXT_AGG_MISC3 (0xFF<<24)
+#define XSTORM_L5CM_AG_CONTEXT_AGG_MISC3_SHIFT 24
+#if defined(__BIG_ENDIAN)
+ u16 agg_misc0;
+ u16 agg_val4;
+#elif defined(__LITTLE_ENDIAN)
+ u16 agg_val4;
+ u16 agg_misc0;
+#endif
+#if defined(__BIG_ENDIAN)
+ u8 agg_val3;
+ u8 agg_val6;
+ u8 agg_val5_th;
+ u8 agg_val5;
+#elif defined(__LITTLE_ENDIAN)
+ u8 agg_val5;
+ u8 agg_val5_th;
+ u8 agg_val6;
+ u8 agg_val3;
+#endif
+#if defined(__BIG_ENDIAN)
+ u16 __agg_misc1;
+ u16 agg_limit1;
+#elif defined(__LITTLE_ENDIAN)
+ u16 agg_limit1;
+ u16 __agg_misc1;
+#endif
+ u32 completion_seq;
u32 agg_misc4;
+ u32 rst_seq_num;
+};
+
+/*
+ * ABTS info $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_abts_info {
+ __le16 aborted_task_id;
+ __le16 reserved0;
+ __le32 reserved1;
+};
+
+
+/*
+ * Fixed size structure in order to plant it in Union structure
+ * $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_abts_rsp_union {
+ u8 r_ctl;
+ u8 rsrv[3];
+ __le32 abts_rsp_payload[7];
+};
+
+
+/*
+ * 4 regs size $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_bd_ctx {
+ __le32 buf_addr_hi;
+ __le32 buf_addr_lo;
+ __le16 buf_len;
+ __le16 rsrv0;
+ __le16 flags;
+ __le16 rsrv1;
+};
+
+
+/*
+ * FCoE cached sges context $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_cached_sge_ctx {
+ struct regpair cur_buf_addr;
+ __le16 cur_buf_rem;
+ __le16 second_buf_rem;
+ struct regpair second_buf_addr;
+};
+
+
+/*
+ * Cleanup info $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_cleanup_info {
+ __le16 cleaned_task_id;
+ __le16 rolled_tx_seq_cnt;
+ __le32 rolled_tx_data_offset;
+};
+
+
+/*
+ * Fcp RSP flags $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_fcp_rsp_flags {
+ u8 flags;
+#define FCOE_FCP_RSP_FLAGS_FCP_RSP_LEN_VALID (0x1<<0)
+#define FCOE_FCP_RSP_FLAGS_FCP_RSP_LEN_VALID_SHIFT 0
+#define FCOE_FCP_RSP_FLAGS_FCP_SNS_LEN_VALID (0x1<<1)
+#define FCOE_FCP_RSP_FLAGS_FCP_SNS_LEN_VALID_SHIFT 1
+#define FCOE_FCP_RSP_FLAGS_FCP_RESID_OVER (0x1<<2)
+#define FCOE_FCP_RSP_FLAGS_FCP_RESID_OVER_SHIFT 2
+#define FCOE_FCP_RSP_FLAGS_FCP_RESID_UNDER (0x1<<3)
+#define FCOE_FCP_RSP_FLAGS_FCP_RESID_UNDER_SHIFT 3
+#define FCOE_FCP_RSP_FLAGS_FCP_CONF_REQ (0x1<<4)
+#define FCOE_FCP_RSP_FLAGS_FCP_CONF_REQ_SHIFT 4
+#define FCOE_FCP_RSP_FLAGS_FCP_BIDI_FLAGS (0x7<<5)
+#define FCOE_FCP_RSP_FLAGS_FCP_BIDI_FLAGS_SHIFT 5
+};
+
+/*
+ * Fcp RSP payload $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_fcp_rsp_payload {
+ struct regpair reserved0;
+ __le32 fcp_resid;
+ u8 scsi_status_code;
+ struct fcoe_fcp_rsp_flags fcp_flags;
+ __le16 retry_delay_timer;
+ __le32 fcp_rsp_len;
+ __le32 fcp_sns_len;
+};
+
+/*
+ * Fixed size structure in order to plant it in Union structure
+ * $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_fcp_rsp_union {
+ struct fcoe_fcp_rsp_payload payload;
+ struct regpair reserved0;
+};
+
+/*
+ * FC header $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_fc_hdr {
+ u8 s_id[3];
+ u8 cs_ctl;
+ u8 d_id[3];
+ u8 r_ctl;
+ __le16 seq_cnt;
+ u8 df_ctl;
+ u8 seq_id;
+ u8 f_ctl[3];
+ u8 type;
+ __le32 parameters;
+ __le16 rx_id;
+ __le16 ox_id;
+};
+
+/*
+ * FC header union $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_mp_rsp_union {
+ struct fcoe_fc_hdr fc_hdr;
+ __le32 mp_payload_len;
+ __le32 rsrv;
+};
+
+/*
+ * Completion information $$KEEP_ENDIANNESS$$
+ */
+union fcoe_comp_flow_info {
+ struct fcoe_fcp_rsp_union fcp_rsp;
+ struct fcoe_abts_rsp_union abts_rsp;
+ struct fcoe_mp_rsp_union mp_rsp;
+ __le32 opaque[8];
+};
+
+
+/*
+ * External ABTS info $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_ext_abts_info {
+ __le32 rsrv0[6];
+ struct fcoe_abts_info ctx;
+};
+
+
+/*
+ * External cleanup info $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_ext_cleanup_info {
+ __le32 rsrv0[6];
+ struct fcoe_cleanup_info ctx;
+};
+
+
+/*
+ * Fcoe FW Tx sequence context $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_fw_tx_seq_ctx {
+ __le32 data_offset;
+ __le16 seq_cnt;
+ __le16 rsrv0;
+};
+
+/*
+ * Fcoe external FW Tx sequence context $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_ext_fw_tx_seq_ctx {
+ __le32 rsrv0[6];
+ struct fcoe_fw_tx_seq_ctx ctx;
+};
+
+
+/*
+ * FCoE multiple sges context $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_mul_sges_ctx {
+ struct regpair cur_sge_addr;
+ __le16 cur_sge_off;
+ u8 cur_sge_idx;
+ u8 sgl_size;
+};
+
+/*
+ * FCoE external multiple sges context $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_ext_mul_sges_ctx {
+ struct fcoe_mul_sges_ctx mul_sgl;
+ struct regpair rsrv0;
+};
+
+
+/*
+ * FCP CMD payload $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_fcp_cmd_payload {
+ __le32 opaque[8];
+};
+
+
+
+
+
+/*
+ * Fcp xfr rdy payload $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_fcp_xfr_rdy_payload {
+ __le32 burst_len;
+ __le32 data_ro;
+};
+
+
+/*
+ * FC frame $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_fc_frame {
+ struct fcoe_fc_hdr fc_hdr;
+ __le32 reserved0[2];
+};
+
+
+
+
+/*
+ * FCoE KCQ CQE parameters $$KEEP_ENDIANNESS$$
+ */
+union fcoe_kcqe_params {
+ __le32 reserved0[4];
+};
+
+/*
+ * FCoE KCQ CQE $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_kcqe {
+ __le32 fcoe_conn_id;
+ __le32 completion_status;
+ __le32 fcoe_conn_context_id;
+ union fcoe_kcqe_params params;
+ __le16 qe_self_seq;
+ u8 op_code;
+ u8 flags;
+#define FCOE_KCQE_RESERVED0 (0x7<<0)
+#define FCOE_KCQE_RESERVED0_SHIFT 0
+#define FCOE_KCQE_RAMROD_COMPLETION (0x1<<3)
+#define FCOE_KCQE_RAMROD_COMPLETION_SHIFT 3
+#define FCOE_KCQE_LAYER_CODE (0x7<<4)
+#define FCOE_KCQE_LAYER_CODE_SHIFT 4
+#define FCOE_KCQE_LINKED_WITH_NEXT (0x1<<7)
+#define FCOE_KCQE_LINKED_WITH_NEXT_SHIFT 7
+};
+
+
+
+/*
+ * FCoE KWQE header $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_kwqe_header {
+ u8 op_code;
+ u8 flags;
+#define FCOE_KWQE_HEADER_RESERVED0 (0xF<<0)
+#define FCOE_KWQE_HEADER_RESERVED0_SHIFT 0
+#define FCOE_KWQE_HEADER_LAYER_CODE (0x7<<4)
+#define FCOE_KWQE_HEADER_LAYER_CODE_SHIFT 4
+#define FCOE_KWQE_HEADER_RESERVED1 (0x1<<7)
+#define FCOE_KWQE_HEADER_RESERVED1_SHIFT 7
+};
+
+/*
+ * FCoE firmware init request 1 $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_kwqe_init1 {
+ __le16 num_tasks;
+ struct fcoe_kwqe_header hdr;
+ __le32 task_list_pbl_addr_lo;
+ __le32 task_list_pbl_addr_hi;
+ __le32 dummy_buffer_addr_lo;
+ __le32 dummy_buffer_addr_hi;
+ __le16 sq_num_wqes;
+ __le16 rq_num_wqes;
+ __le16 rq_buffer_log_size;
+ __le16 cq_num_wqes;
+ __le16 mtu;
+ u8 num_sessions_log;
+ u8 flags;
+#define FCOE_KWQE_INIT1_LOG_PAGE_SIZE (0xF<<0)
+#define FCOE_KWQE_INIT1_LOG_PAGE_SIZE_SHIFT 0
+#define FCOE_KWQE_INIT1_LOG_CACHED_PBES_PER_FUNC (0x7<<4)
+#define FCOE_KWQE_INIT1_LOG_CACHED_PBES_PER_FUNC_SHIFT 4
+#define FCOE_KWQE_INIT1_RESERVED1 (0x1<<7)
+#define FCOE_KWQE_INIT1_RESERVED1_SHIFT 7
+};
+
+/*
+ * FCoE firmware init request 2 $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_kwqe_init2 {
+ u8 hsi_major_version;
+ u8 hsi_minor_version;
+ struct fcoe_kwqe_header hdr;
+ __le32 hash_tbl_pbl_addr_lo;
+ __le32 hash_tbl_pbl_addr_hi;
+ __le32 t2_hash_tbl_addr_lo;
+ __le32 t2_hash_tbl_addr_hi;
+ __le32 t2_ptr_hash_tbl_addr_lo;
+ __le32 t2_ptr_hash_tbl_addr_hi;
+ __le32 free_list_count;
+};
+
+/*
+ * FCoE firmware init request 3 $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_kwqe_init3 {
+ __le16 reserved0;
+ struct fcoe_kwqe_header hdr;
+ __le32 error_bit_map_lo;
+ __le32 error_bit_map_hi;
+ u8 perf_config;
+ u8 reserved21[3];
+ __le32 reserved2[4];
+};
+
+/*
+ * FCoE connection offload request 1 $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_kwqe_conn_offload1 {
+ __le16 fcoe_conn_id;
+ struct fcoe_kwqe_header hdr;
+ __le32 sq_addr_lo;
+ __le32 sq_addr_hi;
+ __le32 rq_pbl_addr_lo;
+ __le32 rq_pbl_addr_hi;
+ __le32 rq_first_pbe_addr_lo;
+ __le32 rq_first_pbe_addr_hi;
+ __le16 rq_prod;
+ __le16 reserved0;
+};
+
+/*
+ * FCoE connection offload request 2 $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_kwqe_conn_offload2 {
+ __le16 tx_max_fc_pay_len;
+ struct fcoe_kwqe_header hdr;
+ __le32 cq_addr_lo;
+ __le32 cq_addr_hi;
+ __le32 xferq_addr_lo;
+ __le32 xferq_addr_hi;
+ __le32 conn_db_addr_lo;
+ __le32 conn_db_addr_hi;
+ __le32 reserved1;
+};
+
+/*
+ * FCoE connection offload request 3 $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_kwqe_conn_offload3 {
+ __le16 vlan_tag;
+#define FCOE_KWQE_CONN_OFFLOAD3_VLAN_ID (0xFFF<<0)
+#define FCOE_KWQE_CONN_OFFLOAD3_VLAN_ID_SHIFT 0
+#define FCOE_KWQE_CONN_OFFLOAD3_CFI (0x1<<12)
+#define FCOE_KWQE_CONN_OFFLOAD3_CFI_SHIFT 12
+#define FCOE_KWQE_CONN_OFFLOAD3_PRIORITY (0x7<<13)
+#define FCOE_KWQE_CONN_OFFLOAD3_PRIORITY_SHIFT 13
+ struct fcoe_kwqe_header hdr;
+ u8 s_id[3];
+ u8 tx_max_conc_seqs_c3;
+ u8 d_id[3];
+ u8 flags;
+#define FCOE_KWQE_CONN_OFFLOAD3_B_MUL_N_PORT_IDS (0x1<<0)
+#define FCOE_KWQE_CONN_OFFLOAD3_B_MUL_N_PORT_IDS_SHIFT 0
+#define FCOE_KWQE_CONN_OFFLOAD3_B_E_D_TOV_RES (0x1<<1)
+#define FCOE_KWQE_CONN_OFFLOAD3_B_E_D_TOV_RES_SHIFT 1
+#define FCOE_KWQE_CONN_OFFLOAD3_B_CONT_INCR_SEQ_CNT (0x1<<2)
+#define FCOE_KWQE_CONN_OFFLOAD3_B_CONT_INCR_SEQ_CNT_SHIFT 2
+#define FCOE_KWQE_CONN_OFFLOAD3_B_CONF_REQ (0x1<<3)
+#define FCOE_KWQE_CONN_OFFLOAD3_B_CONF_REQ_SHIFT 3
+#define FCOE_KWQE_CONN_OFFLOAD3_B_REC_VALID (0x1<<4)
+#define FCOE_KWQE_CONN_OFFLOAD3_B_REC_VALID_SHIFT 4
+#define FCOE_KWQE_CONN_OFFLOAD3_B_C2_VALID (0x1<<5)
+#define FCOE_KWQE_CONN_OFFLOAD3_B_C2_VALID_SHIFT 5
+#define FCOE_KWQE_CONN_OFFLOAD3_B_ACK_0 (0x1<<6)
+#define FCOE_KWQE_CONN_OFFLOAD3_B_ACK_0_SHIFT 6
+#define FCOE_KWQE_CONN_OFFLOAD3_B_VLAN_FLAG (0x1<<7)
+#define FCOE_KWQE_CONN_OFFLOAD3_B_VLAN_FLAG_SHIFT 7
+ __le32 reserved;
+ __le32 confq_first_pbe_addr_lo;
+ __le32 confq_first_pbe_addr_hi;
+ __le16 tx_total_conc_seqs;
+ __le16 rx_max_fc_pay_len;
+ __le16 rx_total_conc_seqs;
+ u8 rx_max_conc_seqs_c3;
+ u8 rx_open_seqs_exch_c3;
+};
+
+/*
+ * FCoE connection offload request 4 $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_kwqe_conn_offload4 {
+ u8 e_d_tov_timer_val;
+ u8 reserved2;
+ struct fcoe_kwqe_header hdr;
+ u8 src_mac_addr_lo[2];
+ u8 src_mac_addr_mid[2];
+ u8 src_mac_addr_hi[2];
+ u8 dst_mac_addr_hi[2];
+ u8 dst_mac_addr_lo[2];
+ u8 dst_mac_addr_mid[2];
+ __le32 lcq_addr_lo;
+ __le32 lcq_addr_hi;
+ __le32 confq_pbl_base_addr_lo;
+ __le32 confq_pbl_base_addr_hi;
+};
+
+/*
+ * FCoE connection enable request $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_kwqe_conn_enable_disable {
+ __le16 reserved0;
+ struct fcoe_kwqe_header hdr;
+ u8 src_mac_addr_lo[2];
+ u8 src_mac_addr_mid[2];
+ u8 src_mac_addr_hi[2];
+ u16 vlan_tag;
+#define FCOE_KWQE_CONN_ENABLE_DISABLE_VLAN_ID (0xFFF<<0)
+#define FCOE_KWQE_CONN_ENABLE_DISABLE_VLAN_ID_SHIFT 0
+#define FCOE_KWQE_CONN_ENABLE_DISABLE_CFI (0x1<<12)
+#define FCOE_KWQE_CONN_ENABLE_DISABLE_CFI_SHIFT 12
+#define FCOE_KWQE_CONN_ENABLE_DISABLE_PRIORITY (0x7<<13)
+#define FCOE_KWQE_CONN_ENABLE_DISABLE_PRIORITY_SHIFT 13
+ u8 dst_mac_addr_lo[2];
+ u8 dst_mac_addr_mid[2];
+ u8 dst_mac_addr_hi[2];
+ __le16 reserved1;
+ u8 s_id[3];
+ u8 vlan_flag;
+ u8 d_id[3];
+ u8 reserved3;
+ __le32 context_id;
+ __le32 conn_id;
+ __le32 reserved4;
+};
+
+/*
+ * FCoE connection destroy request $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_kwqe_conn_destroy {
+ __le16 reserved0;
+ struct fcoe_kwqe_header hdr;
+ __le32 context_id;
+ __le32 conn_id;
+ __le32 reserved1[5];
+};
+
+/*
+ * FCoe destroy request $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_kwqe_destroy {
+ __le16 reserved0;
+ struct fcoe_kwqe_header hdr;
+ __le32 reserved1[7];
+};
+
+/*
+ * FCoe statistics request $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_kwqe_stat {
+ __le16 reserved0;
+ struct fcoe_kwqe_header hdr;
+ __le32 stat_params_addr_lo;
+ __le32 stat_params_addr_hi;
+ __le32 reserved1[5];
+};
+
+/*
+ * FCoE KWQ WQE $$KEEP_ENDIANNESS$$
+ */
+union fcoe_kwqe {
+ struct fcoe_kwqe_init1 init1;
+ struct fcoe_kwqe_init2 init2;
+ struct fcoe_kwqe_init3 init3;
+ struct fcoe_kwqe_conn_offload1 conn_offload1;
+ struct fcoe_kwqe_conn_offload2 conn_offload2;
+ struct fcoe_kwqe_conn_offload3 conn_offload3;
+ struct fcoe_kwqe_conn_offload4 conn_offload4;
+ struct fcoe_kwqe_conn_enable_disable conn_enable_disable;
+ struct fcoe_kwqe_conn_destroy conn_destroy;
+ struct fcoe_kwqe_destroy destroy;
+ struct fcoe_kwqe_stat statistics;
+};
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+/*
+ * TX SGL context $$KEEP_ENDIANNESS$$
+ */
+union fcoe_sgl_union_ctx {
+ struct fcoe_cached_sge_ctx cached_sge;
+ struct fcoe_ext_mul_sges_ctx sgl;
+ __le32 opaque[5];
+};
+
+/*
+ * Data-In/ELS/BLS information $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_read_flow_info {
+ union fcoe_sgl_union_ctx sgl_ctx;
+ __le32 rsrv0[3];
+};
+
+
+/*
+ * Fcoe stat context $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_s_stat_ctx {
+ u8 flags;
+#define FCOE_S_STAT_CTX_ACTIVE (0x1<<0)
+#define FCOE_S_STAT_CTX_ACTIVE_SHIFT 0
+#define FCOE_S_STAT_CTX_ACK_ABORT_SEQ_COND (0x1<<1)
+#define FCOE_S_STAT_CTX_ACK_ABORT_SEQ_COND_SHIFT 1
+#define FCOE_S_STAT_CTX_ABTS_PERFORMED (0x1<<2)
+#define FCOE_S_STAT_CTX_ABTS_PERFORMED_SHIFT 2
+#define FCOE_S_STAT_CTX_SEQ_TIMEOUT (0x1<<3)
+#define FCOE_S_STAT_CTX_SEQ_TIMEOUT_SHIFT 3
+#define FCOE_S_STAT_CTX_P_RJT (0x1<<4)
+#define FCOE_S_STAT_CTX_P_RJT_SHIFT 4
+#define FCOE_S_STAT_CTX_ACK_EOFT (0x1<<5)
+#define FCOE_S_STAT_CTX_ACK_EOFT_SHIFT 5
+#define FCOE_S_STAT_CTX_RSRV1 (0x3<<6)
+#define FCOE_S_STAT_CTX_RSRV1_SHIFT 6
+};
+
+/*
+ * Fcoe rx seq context $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_rx_seq_ctx {
+ u8 seq_id;
+ struct fcoe_s_stat_ctx s_stat;
+ __le16 seq_cnt;
+ __le32 low_exp_ro;
+ __le32 high_exp_ro;
+};
+
+
+/*
+ * Fcoe rx_wr union context $$KEEP_ENDIANNESS$$
+ */
+union fcoe_rx_wr_union_ctx {
+ struct fcoe_read_flow_info read_info;
+ union fcoe_comp_flow_info comp_info;
+ __le32 opaque[8];
+};
+
+
+
+/*
+ * FCoE SQ element $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_sqe {
+ __le16 wqe;
+#define FCOE_SQE_TASK_ID (0x7FFF<<0)
+#define FCOE_SQE_TASK_ID_SHIFT 0
+#define FCOE_SQE_TOGGLE_BIT (0x1<<15)
+#define FCOE_SQE_TOGGLE_BIT_SHIFT 15
+};
+
+
+
+/*
+ * 14 regs $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_tce_tx_only {
+ union fcoe_sgl_union_ctx sgl_ctx;
+ __le32 rsrv0;
+};
+
+/*
+ * 32 bytes (8 regs) used for TX only purposes $$KEEP_ENDIANNESS$$
+ */
+union fcoe_tx_wr_rx_rd_union_ctx {
+ struct fcoe_fc_frame tx_frame;
+ struct fcoe_fcp_cmd_payload fcp_cmd;
+ struct fcoe_ext_cleanup_info cleanup;
+ struct fcoe_ext_abts_info abts;
+ struct fcoe_ext_fw_tx_seq_ctx tx_seq;
+ __le32 opaque[8];
+};
+
+/*
+ * tce_tx_wr_rx_rd_const $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_tce_tx_wr_rx_rd_const {
+ u8 init_flags;
+#define FCOE_TCE_TX_WR_RX_RD_CONST_TASK_TYPE (0x7<<0)
+#define FCOE_TCE_TX_WR_RX_RD_CONST_TASK_TYPE_SHIFT 0
+#define FCOE_TCE_TX_WR_RX_RD_CONST_DEV_TYPE (0x1<<3)
+#define FCOE_TCE_TX_WR_RX_RD_CONST_DEV_TYPE_SHIFT 3
+#define FCOE_TCE_TX_WR_RX_RD_CONST_CLASS_TYPE (0x1<<4)
+#define FCOE_TCE_TX_WR_RX_RD_CONST_CLASS_TYPE_SHIFT 4
+#define FCOE_TCE_TX_WR_RX_RD_CONST_CACHED_SGE (0x3<<5)
+#define FCOE_TCE_TX_WR_RX_RD_CONST_CACHED_SGE_SHIFT 5
+#define FCOE_TCE_TX_WR_RX_RD_CONST_SUPPORT_REC_TOV (0x1<<7)
+#define FCOE_TCE_TX_WR_RX_RD_CONST_SUPPORT_REC_TOV_SHIFT 7
+ u8 tx_flags;
+#define FCOE_TCE_TX_WR_RX_RD_CONST_TX_VALID (0x1<<0)
+#define FCOE_TCE_TX_WR_RX_RD_CONST_TX_VALID_SHIFT 0
+#define FCOE_TCE_TX_WR_RX_RD_CONST_TX_STATE (0xF<<1)
+#define FCOE_TCE_TX_WR_RX_RD_CONST_TX_STATE_SHIFT 1
+#define FCOE_TCE_TX_WR_RX_RD_CONST_RSRV1 (0x1<<5)
+#define FCOE_TCE_TX_WR_RX_RD_CONST_RSRV1_SHIFT 5
+#define FCOE_TCE_TX_WR_RX_RD_CONST_TX_SEQ_INIT (0x1<<6)
+#define FCOE_TCE_TX_WR_RX_RD_CONST_TX_SEQ_INIT_SHIFT 6
+#define FCOE_TCE_TX_WR_RX_RD_CONST_RSRV2 (0x1<<7)
+#define FCOE_TCE_TX_WR_RX_RD_CONST_RSRV2_SHIFT 7
+ __le16 rsrv3;
+ __le32 verify_tx_seq;
+};
+
+/*
+ * tce_tx_wr_rx_rd $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_tce_tx_wr_rx_rd {
+ union fcoe_tx_wr_rx_rd_union_ctx union_ctx;
+ struct fcoe_tce_tx_wr_rx_rd_const const_ctx;
+};
+
+/*
+ * tce_rx_wr_tx_rd_const $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_tce_rx_wr_tx_rd_const {
+ __le32 data_2_trns;
+ __le32 init_flags;
+#define FCOE_TCE_RX_WR_TX_RD_CONST_CID (0xFFFFFF<<0)
+#define FCOE_TCE_RX_WR_TX_RD_CONST_CID_SHIFT 0
+#define FCOE_TCE_RX_WR_TX_RD_CONST_RSRV0 (0xFF<<24)
+#define FCOE_TCE_RX_WR_TX_RD_CONST_RSRV0_SHIFT 24
+};
+
+/*
+ * tce_rx_wr_tx_rd_var $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_tce_rx_wr_tx_rd_var {
+ __le16 rx_flags;
+#define FCOE_TCE_RX_WR_TX_RD_VAR_RSRV1 (0xF<<0)
+#define FCOE_TCE_RX_WR_TX_RD_VAR_RSRV1_SHIFT 0
+#define FCOE_TCE_RX_WR_TX_RD_VAR_NUM_RQ_WQE (0x7<<4)
+#define FCOE_TCE_RX_WR_TX_RD_VAR_NUM_RQ_WQE_SHIFT 4
+#define FCOE_TCE_RX_WR_TX_RD_VAR_CONF_REQ (0x1<<7)
+#define FCOE_TCE_RX_WR_TX_RD_VAR_CONF_REQ_SHIFT 7
+#define FCOE_TCE_RX_WR_TX_RD_VAR_RX_STATE (0xF<<8)
+#define FCOE_TCE_RX_WR_TX_RD_VAR_RX_STATE_SHIFT 8
+#define FCOE_TCE_RX_WR_TX_RD_VAR_EXP_FIRST_FRAME (0x1<<12)
+#define FCOE_TCE_RX_WR_TX_RD_VAR_EXP_FIRST_FRAME_SHIFT 12
+#define FCOE_TCE_RX_WR_TX_RD_VAR_RX_SEQ_INIT (0x1<<13)
+#define FCOE_TCE_RX_WR_TX_RD_VAR_RX_SEQ_INIT_SHIFT 13
+#define FCOE_TCE_RX_WR_TX_RD_VAR_RSRV2 (0x1<<14)
+#define FCOE_TCE_RX_WR_TX_RD_VAR_RSRV2_SHIFT 14
+#define FCOE_TCE_RX_WR_TX_RD_VAR_RX_VALID (0x1<<15)
+#define FCOE_TCE_RX_WR_TX_RD_VAR_RX_VALID_SHIFT 15
+ __le16 rx_id;
+ struct fcoe_fcp_xfr_rdy_payload fcp_xfr_rdy;
+};
+
+/*
+ * tce_rx_wr_tx_rd $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_tce_rx_wr_tx_rd {
+ struct fcoe_tce_rx_wr_tx_rd_const const_ctx;
+ struct fcoe_tce_rx_wr_tx_rd_var var_ctx;
+};
+
+/*
+ * tce_rx_only $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_tce_rx_only {
+ struct fcoe_rx_seq_ctx rx_seq_ctx;
+ union fcoe_rx_wr_union_ctx union_ctx;
+};
+
+/*
+ * task_ctx_entry $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_task_ctx_entry {
+ struct fcoe_tce_tx_only txwr_only;
+ struct fcoe_tce_tx_wr_rx_rd txwr_rxrd;
+ struct fcoe_tce_rx_wr_tx_rd rxwr_txrd;
+ struct fcoe_tce_rx_only rxwr_only;
+};
+
+
+
+
+
+
+
+
+
+
+/*
+ * FCoE XFRQ element $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_xfrqe {
+ __le16 wqe;
+#define FCOE_XFRQE_TASK_ID (0x7FFF<<0)
+#define FCOE_XFRQE_TASK_ID_SHIFT 0
+#define FCOE_XFRQE_TOGGLE_BIT (0x1<<15)
+#define FCOE_XFRQE_TOGGLE_BIT_SHIFT 15
+};
+
+
+/*
+ * Cached SGEs $$KEEP_ENDIANNESS$$
+ */
+struct common_fcoe_sgl {
+ struct fcoe_bd_ctx sge[3];
+};
+
+
+/*
+ * FCoE SQ\XFRQ element
+ */
+struct fcoe_cached_wqe {
+ struct fcoe_sqe sqe;
+ struct fcoe_xfrqe xfrqe;
+};
+
+
+/*
+ * FCoE connection enable\disable params passed by driver to FW in FCoE enable
+ * ramrod $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_conn_enable_disable_ramrod_params {
+ struct fcoe_kwqe_conn_enable_disable enable_disable_kwqe;
+};
+
+
+/*
+ * FCoE connection offload params passed by driver to FW in FCoE offload ramrod
+ * $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_conn_offload_ramrod_params {
+ struct fcoe_kwqe_conn_offload1 offload_kwqe1;
+ struct fcoe_kwqe_conn_offload2 offload_kwqe2;
+ struct fcoe_kwqe_conn_offload3 offload_kwqe3;
+ struct fcoe_kwqe_conn_offload4 offload_kwqe4;
+};
+
+
+struct ustorm_fcoe_mng_ctx {
#if defined(__BIG_ENDIAN)
- u8 agg_val3_th;
- u8 agg_val3;
- u16 agg_misc3;
+ u8 mid_seq_proc_flag;
+ u8 tce_in_cam_flag;
+ u8 tce_on_ior_flag;
+ u8 en_cached_tce_flag;
#elif defined(__LITTLE_ENDIAN)
- u16 agg_misc3;
- u8 agg_val3;
- u8 agg_val3_th;
-#endif
- u32 agg_val1;
- u32 agg_misc4_th;
-#if defined(__BIG_ENDIAN)
- u16 agg_val2_th;
- u16 agg_val2;
-#elif defined(__LITTLE_ENDIAN)
- u16 agg_val2;
- u16 agg_val2_th;
+ u8 en_cached_tce_flag;
+ u8 tce_on_ior_flag;
+ u8 tce_in_cam_flag;
+ u8 mid_seq_proc_flag;
#endif
#if defined(__BIG_ENDIAN)
- u16 __reserved2;
- u8 decision_rules;
-#define USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_RULE (0x7<<0)
-#define USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_RULE_SHIFT 0
-#define __USTORM_ISCSI_AG_CONTEXT_AGG_VAL3_RULE (0x7<<3)
-#define __USTORM_ISCSI_AG_CONTEXT_AGG_VAL3_RULE_SHIFT 3
-#define USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_ARM_N_FLAG (0x1<<6)
-#define USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_ARM_N_FLAG_SHIFT 6
-#define __USTORM_ISCSI_AG_CONTEXT_RESERVED1 (0x1<<7)
-#define __USTORM_ISCSI_AG_CONTEXT_RESERVED1_SHIFT 7
- u8 decision_rule_enable_bits;
-#define USTORM_ISCSI_AG_CONTEXT_INV_CF_EN (0x1<<0)
-#define USTORM_ISCSI_AG_CONTEXT_INV_CF_EN_SHIFT 0
-#define USTORM_ISCSI_AG_CONTEXT_COMPLETION_CF_EN (0x1<<1)
-#define USTORM_ISCSI_AG_CONTEXT_COMPLETION_CF_EN_SHIFT 1
-#define USTORM_ISCSI_AG_CONTEXT_TX_CF_EN (0x1<<2)
-#define USTORM_ISCSI_AG_CONTEXT_TX_CF_EN_SHIFT 2
-#define __USTORM_ISCSI_AG_CONTEXT_TIMER_CF_EN (0x1<<3)
-#define __USTORM_ISCSI_AG_CONTEXT_TIMER_CF_EN_SHIFT 3
-#define __USTORM_ISCSI_AG_CONTEXT_CQ_LOCAL_COMP_CF_EN (0x1<<4)
-#define __USTORM_ISCSI_AG_CONTEXT_CQ_LOCAL_COMP_CF_EN_SHIFT 4
-#define __USTORM_ISCSI_AG_CONTEXT_QUEUES_FLUSH_Q0_CF_EN (0x1<<5)
-#define __USTORM_ISCSI_AG_CONTEXT_QUEUES_FLUSH_Q0_CF_EN_SHIFT 5
-#define __USTORM_ISCSI_AG_CONTEXT_AUX3_CF_EN (0x1<<6)
-#define __USTORM_ISCSI_AG_CONTEXT_AUX3_CF_EN_SHIFT 6
-#define __USTORM_ISCSI_AG_CONTEXT_DQ_CF_EN (0x1<<7)
-#define __USTORM_ISCSI_AG_CONTEXT_DQ_CF_EN_SHIFT 7
+ u8 tce_cam_addr;
+ u8 cached_conn_flag;
+ u16 rsrv0;
#elif defined(__LITTLE_ENDIAN)
- u8 decision_rule_enable_bits;
-#define USTORM_ISCSI_AG_CONTEXT_INV_CF_EN (0x1<<0)
-#define USTORM_ISCSI_AG_CONTEXT_INV_CF_EN_SHIFT 0
-#define USTORM_ISCSI_AG_CONTEXT_COMPLETION_CF_EN (0x1<<1)
-#define USTORM_ISCSI_AG_CONTEXT_COMPLETION_CF_EN_SHIFT 1
-#define USTORM_ISCSI_AG_CONTEXT_TX_CF_EN (0x1<<2)
-#define USTORM_ISCSI_AG_CONTEXT_TX_CF_EN_SHIFT 2
-#define __USTORM_ISCSI_AG_CONTEXT_TIMER_CF_EN (0x1<<3)
-#define __USTORM_ISCSI_AG_CONTEXT_TIMER_CF_EN_SHIFT 3
-#define __USTORM_ISCSI_AG_CONTEXT_CQ_LOCAL_COMP_CF_EN (0x1<<4)
-#define __USTORM_ISCSI_AG_CONTEXT_CQ_LOCAL_COMP_CF_EN_SHIFT 4
-#define __USTORM_ISCSI_AG_CONTEXT_QUEUES_FLUSH_Q0_CF_EN (0x1<<5)
-#define __USTORM_ISCSI_AG_CONTEXT_QUEUES_FLUSH_Q0_CF_EN_SHIFT 5
-#define __USTORM_ISCSI_AG_CONTEXT_AUX3_CF_EN (0x1<<6)
-#define __USTORM_ISCSI_AG_CONTEXT_AUX3_CF_EN_SHIFT 6
-#define __USTORM_ISCSI_AG_CONTEXT_DQ_CF_EN (0x1<<7)
-#define __USTORM_ISCSI_AG_CONTEXT_DQ_CF_EN_SHIFT 7
- u8 decision_rules;
-#define USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_RULE (0x7<<0)
-#define USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_RULE_SHIFT 0
-#define __USTORM_ISCSI_AG_CONTEXT_AGG_VAL3_RULE (0x7<<3)
-#define __USTORM_ISCSI_AG_CONTEXT_AGG_VAL3_RULE_SHIFT 3
-#define USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_ARM_N_FLAG (0x1<<6)
-#define USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_ARM_N_FLAG_SHIFT 6
-#define __USTORM_ISCSI_AG_CONTEXT_RESERVED1 (0x1<<7)
-#define __USTORM_ISCSI_AG_CONTEXT_RESERVED1_SHIFT 7
- u16 __reserved2;
+ u16 rsrv0;
+ u8 cached_conn_flag;
+ u8 tce_cam_addr;
#endif
+#if defined(__BIG_ENDIAN)
+ u16 dma_tce_ram_addr;
+ u16 tce_ram_addr;
+#elif defined(__LITTLE_ENDIAN)
+ u16 tce_ram_addr;
+ u16 dma_tce_ram_addr;
+#endif
+#if defined(__BIG_ENDIAN)
+ u16 ox_id;
+ u16 wr_done_seq;
+#elif defined(__LITTLE_ENDIAN)
+ u16 wr_done_seq;
+ u16 ox_id;
+#endif
+ struct regpair task_addr;
+};
+
+/*
+ * Parameters initialized during offloaded according to FLOGI/PLOGI/PRLI and
+ * used in FCoE context section
+ */
+struct ustorm_fcoe_params {
+#if defined(__BIG_ENDIAN)
+ u16 fcoe_conn_id;
+ u16 flags;
+#define USTORM_FCOE_PARAMS_B_MUL_N_PORT_IDS (0x1<<0)
+#define USTORM_FCOE_PARAMS_B_MUL_N_PORT_IDS_SHIFT 0
+#define USTORM_FCOE_PARAMS_B_E_D_TOV_RES (0x1<<1)
+#define USTORM_FCOE_PARAMS_B_E_D_TOV_RES_SHIFT 1
+#define USTORM_FCOE_PARAMS_B_CONT_INCR_SEQ_CNT (0x1<<2)
+#define USTORM_FCOE_PARAMS_B_CONT_INCR_SEQ_CNT_SHIFT 2
+#define USTORM_FCOE_PARAMS_B_CONF_REQ (0x1<<3)
+#define USTORM_FCOE_PARAMS_B_CONF_REQ_SHIFT 3
+#define USTORM_FCOE_PARAMS_B_REC_VALID (0x1<<4)
+#define USTORM_FCOE_PARAMS_B_REC_VALID_SHIFT 4
+#define USTORM_FCOE_PARAMS_B_CQ_TOGGLE_BIT (0x1<<5)
+#define USTORM_FCOE_PARAMS_B_CQ_TOGGLE_BIT_SHIFT 5
+#define USTORM_FCOE_PARAMS_B_XFRQ_TOGGLE_BIT (0x1<<6)
+#define USTORM_FCOE_PARAMS_B_XFRQ_TOGGLE_BIT_SHIFT 6
+#define USTORM_FCOE_PARAMS_RSRV0 (0x1FF<<7)
+#define USTORM_FCOE_PARAMS_RSRV0_SHIFT 7
+#elif defined(__LITTLE_ENDIAN)
+ u16 flags;
+#define USTORM_FCOE_PARAMS_B_MUL_N_PORT_IDS (0x1<<0)
+#define USTORM_FCOE_PARAMS_B_MUL_N_PORT_IDS_SHIFT 0
+#define USTORM_FCOE_PARAMS_B_E_D_TOV_RES (0x1<<1)
+#define USTORM_FCOE_PARAMS_B_E_D_TOV_RES_SHIFT 1
+#define USTORM_FCOE_PARAMS_B_CONT_INCR_SEQ_CNT (0x1<<2)
+#define USTORM_FCOE_PARAMS_B_CONT_INCR_SEQ_CNT_SHIFT 2
+#define USTORM_FCOE_PARAMS_B_CONF_REQ (0x1<<3)
+#define USTORM_FCOE_PARAMS_B_CONF_REQ_SHIFT 3
+#define USTORM_FCOE_PARAMS_B_REC_VALID (0x1<<4)
+#define USTORM_FCOE_PARAMS_B_REC_VALID_SHIFT 4
+#define USTORM_FCOE_PARAMS_B_CQ_TOGGLE_BIT (0x1<<5)
+#define USTORM_FCOE_PARAMS_B_CQ_TOGGLE_BIT_SHIFT 5
+#define USTORM_FCOE_PARAMS_B_XFRQ_TOGGLE_BIT (0x1<<6)
+#define USTORM_FCOE_PARAMS_B_XFRQ_TOGGLE_BIT_SHIFT 6
+#define USTORM_FCOE_PARAMS_RSRV0 (0x1FF<<7)
+#define USTORM_FCOE_PARAMS_RSRV0_SHIFT 7
+ u16 fcoe_conn_id;
+#endif
+#if defined(__BIG_ENDIAN)
+ u8 hc_csdm_byte_en;
+ u8 func_id;
+ u8 port_id;
+ u8 vnic_id;
+#elif defined(__LITTLE_ENDIAN)
+ u8 vnic_id;
+ u8 port_id;
+ u8 func_id;
+ u8 hc_csdm_byte_en;
+#endif
+#if defined(__BIG_ENDIAN)
+ u16 rx_total_conc_seqs;
+ u16 rx_max_fc_pay_len;
+#elif defined(__LITTLE_ENDIAN)
+ u16 rx_max_fc_pay_len;
+ u16 rx_total_conc_seqs;
+#endif
+#if defined(__BIG_ENDIAN)
+ u8 task_pbe_idx_off;
+ u8 task_in_page_log_size;
+ u16 rx_max_conc_seqs;
+#elif defined(__LITTLE_ENDIAN)
+ u16 rx_max_conc_seqs;
+ u8 task_in_page_log_size;
+ u8 task_pbe_idx_off;
+#endif
+};
+
+/*
+ * FCoE 16-bits index structure
+ */
+struct fcoe_idx16_fields {
+ u16 fields;
+#define FCOE_IDX16_FIELDS_IDX (0x7FFF<<0)
+#define FCOE_IDX16_FIELDS_IDX_SHIFT 0
+#define FCOE_IDX16_FIELDS_MSB (0x1<<15)
+#define FCOE_IDX16_FIELDS_MSB_SHIFT 15
+};
+
+/*
+ * FCoE 16-bits index union
+ */
+union fcoe_idx16_field_union {
+ struct fcoe_idx16_fields fields;
+ u16 val;
+};
+
+/*
+ * Parameters required for placement according to SGL
+ */
+struct ustorm_fcoe_data_place_mng {
+#if defined(__BIG_ENDIAN)
+ u16 sge_off;
+ u8 num_sges;
+ u8 sge_idx;
+#elif defined(__LITTLE_ENDIAN)
+ u8 sge_idx;
+ u8 num_sges;
+ u16 sge_off;
+#endif
+};
+
+/*
+ * Parameters required for placement according to SGL
+ */
+struct ustorm_fcoe_data_place {
+ struct ustorm_fcoe_data_place_mng cached_mng;
+ struct fcoe_bd_ctx cached_sge[2];
+};
+
+/*
+ * TX processing shall write and RX processing shall read from this section
+ */
+union fcoe_u_tce_tx_wr_rx_rd_union {
+ struct fcoe_abts_info abts;
+ struct fcoe_cleanup_info cleanup;
+ struct fcoe_fw_tx_seq_ctx tx_seq_ctx;
+ u32 opaque[2];
+};
+
+/*
+ * TX processing shall write and RX processing shall read from this section
+ */
+struct fcoe_u_tce_tx_wr_rx_rd {
+ union fcoe_u_tce_tx_wr_rx_rd_union union_ctx;
+ struct fcoe_tce_tx_wr_rx_rd_const const_ctx;
+};
+
+struct ustorm_fcoe_tce {
+ struct fcoe_u_tce_tx_wr_rx_rd txwr_rxrd;
+ struct fcoe_tce_rx_wr_tx_rd rxwr_txrd;
+ struct fcoe_tce_rx_only rxwr;
+};
+
+struct ustorm_fcoe_cache_ctx {
+ u32 rsrv0;
+ struct ustorm_fcoe_data_place data_place;
+ struct ustorm_fcoe_tce tce;
+};
+
+/*
+ * Ustorm FCoE Storm Context
+ */
+struct ustorm_fcoe_st_context {
+ struct ustorm_fcoe_mng_ctx mng_ctx;
+ struct ustorm_fcoe_params fcoe_params;
+ struct regpair cq_base_addr;
+ struct regpair rq_pbl_base;
+ struct regpair rq_cur_page_addr;
+ struct regpair confq_pbl_base_addr;
+ struct regpair conn_db_base;
+ struct regpair xfrq_base_addr;
+ struct regpair lcq_base_addr;
+#if defined(__BIG_ENDIAN)
+ union fcoe_idx16_field_union rq_cons;
+ union fcoe_idx16_field_union rq_prod;
+#elif defined(__LITTLE_ENDIAN)
+ union fcoe_idx16_field_union rq_prod;
+ union fcoe_idx16_field_union rq_cons;
+#endif
+#if defined(__BIG_ENDIAN)
+ u16 xfrq_prod;
+ u16 cq_cons;
+#elif defined(__LITTLE_ENDIAN)
+ u16 cq_cons;
+ u16 xfrq_prod;
+#endif
+#if defined(__BIG_ENDIAN)
+ u16 lcq_cons;
+ u16 hc_cram_address;
+#elif defined(__LITTLE_ENDIAN)
+ u16 hc_cram_address;
+ u16 lcq_cons;
+#endif
+#if defined(__BIG_ENDIAN)
+ u16 sq_xfrq_lcq_confq_size;
+ u16 confq_prod;
+#elif defined(__LITTLE_ENDIAN)
+ u16 confq_prod;
+ u16 sq_xfrq_lcq_confq_size;
+#endif
+#if defined(__BIG_ENDIAN)
+ u8 hc_csdm_agg_int;
+ u8 rsrv2;
+ u8 available_rqes;
+ u8 sp_q_flush_cnt;
+#elif defined(__LITTLE_ENDIAN)
+ u8 sp_q_flush_cnt;
+ u8 available_rqes;
+ u8 rsrv2;
+ u8 hc_csdm_agg_int;
+#endif
+#if defined(__BIG_ENDIAN)
+ u16 num_pend_tasks;
+ u16 pbf_ack_ram_addr;
+#elif defined(__LITTLE_ENDIAN)
+ u16 pbf_ack_ram_addr;
+ u16 num_pend_tasks;
+#endif
+ struct ustorm_fcoe_cache_ctx cache_ctx;
+};
+
+/*
+ * The FCoE non-aggregative context of Tstorm
+ */
+struct tstorm_fcoe_st_context {
+ struct regpair reserved0;
+ struct regpair reserved1;
+};
+
+/*
+ * Ethernet context section
+ */
+struct xstorm_fcoe_eth_context_section {
+#if defined(__BIG_ENDIAN)
+ u8 remote_addr_4;
+ u8 remote_addr_5;
+ u8 local_addr_0;
+ u8 local_addr_1;
+#elif defined(__LITTLE_ENDIAN)
+ u8 local_addr_1;
+ u8 local_addr_0;
+ u8 remote_addr_5;
+ u8 remote_addr_4;
+#endif
+#if defined(__BIG_ENDIAN)
+ u8 remote_addr_0;
+ u8 remote_addr_1;
+ u8 remote_addr_2;
+ u8 remote_addr_3;
+#elif defined(__LITTLE_ENDIAN)
+ u8 remote_addr_3;
+ u8 remote_addr_2;
+ u8 remote_addr_1;
+ u8 remote_addr_0;
+#endif
+#if defined(__BIG_ENDIAN)
+ u16 reserved_vlan_type;
+ u16 params;
+#define XSTORM_FCOE_ETH_CONTEXT_SECTION_VLAN_ID (0xFFF<<0)
+#define XSTORM_FCOE_ETH_CONTEXT_SECTION_VLAN_ID_SHIFT 0
+#define XSTORM_FCOE_ETH_CONTEXT_SECTION_CFI (0x1<<12)
+#define XSTORM_FCOE_ETH_CONTEXT_SECTION_CFI_SHIFT 12
+#define XSTORM_FCOE_ETH_CONTEXT_SECTION_PRIORITY (0x7<<13)
+#define XSTORM_FCOE_ETH_CONTEXT_SECTION_PRIORITY_SHIFT 13
+#elif defined(__LITTLE_ENDIAN)
+ u16 params;
+#define XSTORM_FCOE_ETH_CONTEXT_SECTION_VLAN_ID (0xFFF<<0)
+#define XSTORM_FCOE_ETH_CONTEXT_SECTION_VLAN_ID_SHIFT 0
+#define XSTORM_FCOE_ETH_CONTEXT_SECTION_CFI (0x1<<12)
+#define XSTORM_FCOE_ETH_CONTEXT_SECTION_CFI_SHIFT 12
+#define XSTORM_FCOE_ETH_CONTEXT_SECTION_PRIORITY (0x7<<13)
+#define XSTORM_FCOE_ETH_CONTEXT_SECTION_PRIORITY_SHIFT 13
+ u16 reserved_vlan_type;
+#endif
+#if defined(__BIG_ENDIAN)
+ u8 local_addr_2;
+ u8 local_addr_3;
+ u8 local_addr_4;
+ u8 local_addr_5;
+#elif defined(__LITTLE_ENDIAN)
+ u8 local_addr_5;
+ u8 local_addr_4;
+ u8 local_addr_3;
+ u8 local_addr_2;
+#endif
+};
+
+/*
+ * Flags used in FCoE context section - 1 byte
+ */
+struct xstorm_fcoe_context_flags {
+ u8 flags;
+#define XSTORM_FCOE_CONTEXT_FLAGS_B_PROC_Q (0x3<<0)
+#define XSTORM_FCOE_CONTEXT_FLAGS_B_PROC_Q_SHIFT 0
+#define XSTORM_FCOE_CONTEXT_FLAGS_B_MID_SEQ (0x1<<2)
+#define XSTORM_FCOE_CONTEXT_FLAGS_B_MID_SEQ_SHIFT 2
+#define XSTORM_FCOE_CONTEXT_FLAGS_B_BLOCK_SQ (0x1<<3)
+#define XSTORM_FCOE_CONTEXT_FLAGS_B_BLOCK_SQ_SHIFT 3
+#define XSTORM_FCOE_CONTEXT_FLAGS_B_REC_SUPPORT (0x1<<4)
+#define XSTORM_FCOE_CONTEXT_FLAGS_B_REC_SUPPORT_SHIFT 4
+#define XSTORM_FCOE_CONTEXT_FLAGS_B_SQ_TOGGLE (0x1<<5)
+#define XSTORM_FCOE_CONTEXT_FLAGS_B_SQ_TOGGLE_SHIFT 5
+#define XSTORM_FCOE_CONTEXT_FLAGS_B_XFRQ_TOGGLE (0x1<<6)
+#define XSTORM_FCOE_CONTEXT_FLAGS_B_XFRQ_TOGGLE_SHIFT 6
+#define XSTORM_FCOE_CONTEXT_FLAGS_B_VNTAG_VLAN (0x1<<7)
+#define XSTORM_FCOE_CONTEXT_FLAGS_B_VNTAG_VLAN_SHIFT 7
+};
+
+struct xstorm_fcoe_tce {
+ struct fcoe_tce_tx_only txwr;
+ struct fcoe_tce_tx_wr_rx_rd txwr_rxrd;
+};
+
+/*
+ * FCP_DATA parameters required for transmission
+ */
+struct xstorm_fcoe_fcp_data {
+ u32 io_rem;
+#if defined(__BIG_ENDIAN)
+ u16 cached_sge_off;
+ u8 cached_num_sges;
+ u8 cached_sge_idx;
+#elif defined(__LITTLE_ENDIAN)
+ u8 cached_sge_idx;
+ u8 cached_num_sges;
+ u16 cached_sge_off;
+#endif
+ u32 buf_addr_hi_0;
+ u32 buf_addr_lo_0;
+#if defined(__BIG_ENDIAN)
+ u16 num_of_pending_tasks;
+ u16 buf_len_0;
+#elif defined(__LITTLE_ENDIAN)
+ u16 buf_len_0;
+ u16 num_of_pending_tasks;
+#endif
+ u32 buf_addr_hi_1;
+ u32 buf_addr_lo_1;
+#if defined(__BIG_ENDIAN)
+ u16 task_pbe_idx_off;
+ u16 buf_len_1;
+#elif defined(__LITTLE_ENDIAN)
+ u16 buf_len_1;
+ u16 task_pbe_idx_off;
+#endif
+ u32 buf_addr_hi_2;
+ u32 buf_addr_lo_2;
+#if defined(__BIG_ENDIAN)
+ u16 ox_id;
+ u16 buf_len_2;
+#elif defined(__LITTLE_ENDIAN)
+ u16 buf_len_2;
+ u16 ox_id;
+#endif
+};
+
+/*
+ * vlan configuration
+ */
+struct xstorm_fcoe_vlan_conf {
+ u8 vlan_conf;
+#define XSTORM_FCOE_VLAN_CONF_PRIORITY (0x7<<0)
+#define XSTORM_FCOE_VLAN_CONF_PRIORITY_SHIFT 0
+#define XSTORM_FCOE_VLAN_CONF_INNER_VLAN_FLAG (0x1<<3)
+#define XSTORM_FCOE_VLAN_CONF_INNER_VLAN_FLAG_SHIFT 3
+#define XSTORM_FCOE_VLAN_CONF_RESERVED (0xF<<4)
+#define XSTORM_FCOE_VLAN_CONF_RESERVED_SHIFT 4
+};
+
+/*
+ * FCoE 16-bits vlan structure
+ */
+struct fcoe_vlan_fields {
+ u16 fields;
+#define FCOE_VLAN_FIELDS_VID (0xFFF<<0)
+#define FCOE_VLAN_FIELDS_VID_SHIFT 0
+#define FCOE_VLAN_FIELDS_CLI (0x1<<12)
+#define FCOE_VLAN_FIELDS_CLI_SHIFT 12
+#define FCOE_VLAN_FIELDS_PRI (0x7<<13)
+#define FCOE_VLAN_FIELDS_PRI_SHIFT 13
+};
+
+/*
+ * FCoE 16-bits vlan union
+ */
+union fcoe_vlan_field_union {
+ struct fcoe_vlan_fields fields;
+ u16 val;
+};
+
+/*
+ * FCoE 16-bits vlan, vif union
+ */
+union fcoe_vlan_vif_field_union {
+ union fcoe_vlan_field_union vlan;
+ u16 vif;
+};
+
+/*
+ * FCoE context section
+ */
+struct xstorm_fcoe_context_section {
+#if defined(__BIG_ENDIAN)
+ u8 cs_ctl;
+ u8 s_id[3];
+#elif defined(__LITTLE_ENDIAN)
+ u8 s_id[3];
+ u8 cs_ctl;
+#endif
+#if defined(__BIG_ENDIAN)
+ u8 rctl;
+ u8 d_id[3];
+#elif defined(__LITTLE_ENDIAN)
+ u8 d_id[3];
+ u8 rctl;
+#endif
+#if defined(__BIG_ENDIAN)
+ u16 sq_xfrq_lcq_confq_size;
+ u16 tx_max_fc_pay_len;
+#elif defined(__LITTLE_ENDIAN)
+ u16 tx_max_fc_pay_len;
+ u16 sq_xfrq_lcq_confq_size;
+#endif
+ u32 lcq_prod;
+#if defined(__BIG_ENDIAN)
+ u8 port_id;
+ u8 func_id;
+ u8 seq_id;
+ struct xstorm_fcoe_context_flags tx_flags;
+#elif defined(__LITTLE_ENDIAN)
+ struct xstorm_fcoe_context_flags tx_flags;
+ u8 seq_id;
+ u8 func_id;
+ u8 port_id;
+#endif
+#if defined(__BIG_ENDIAN)
+ u16 mtu;
+ u8 func_mode;
+ u8 vnic_id;
+#elif defined(__LITTLE_ENDIAN)
+ u8 vnic_id;
+ u8 func_mode;
+ u16 mtu;
+#endif
+ struct regpair confq_curr_page_addr;
+ struct fcoe_cached_wqe cached_wqe[8];
+ struct regpair lcq_base_addr;
+ struct xstorm_fcoe_tce tce;
+ struct xstorm_fcoe_fcp_data fcp_data;
+#if defined(__BIG_ENDIAN)
+ u8 tx_max_conc_seqs_c3;
+ u8 vlan_flag;
+ u8 dcb_val;
+ u8 data_pb_cmd_size;
+#elif defined(__LITTLE_ENDIAN)
+ u8 data_pb_cmd_size;
+ u8 dcb_val;
+ u8 vlan_flag;
+ u8 tx_max_conc_seqs_c3;
+#endif
+#if defined(__BIG_ENDIAN)
+ u16 fcoe_tx_stat_params_ram_addr;
+ u16 fcoe_tx_fc_seq_ram_addr;
+#elif defined(__LITTLE_ENDIAN)
+ u16 fcoe_tx_fc_seq_ram_addr;
+ u16 fcoe_tx_stat_params_ram_addr;
+#endif
+#if defined(__BIG_ENDIAN)
+ u8 fcp_cmd_line_credit;
+ u8 eth_hdr_size;
+ u16 pbf_addr;
+#elif defined(__LITTLE_ENDIAN)
+ u16 pbf_addr;
+ u8 eth_hdr_size;
+ u8 fcp_cmd_line_credit;
+#endif
+#if defined(__BIG_ENDIAN)
+ union fcoe_vlan_vif_field_union multi_func_val;
+ u8 page_log_size;
+ struct xstorm_fcoe_vlan_conf orig_vlan_conf;
+#elif defined(__LITTLE_ENDIAN)
+ struct xstorm_fcoe_vlan_conf orig_vlan_conf;
+ u8 page_log_size;
+ union fcoe_vlan_vif_field_union multi_func_val;
+#endif
+#if defined(__BIG_ENDIAN)
+ u16 fcp_cmd_frame_size;
+ u16 pbf_addr_ff;
+#elif defined(__LITTLE_ENDIAN)
+ u16 pbf_addr_ff;
+ u16 fcp_cmd_frame_size;
+#endif
+#if defined(__BIG_ENDIAN)
+ u8 vlan_num;
+ u8 cos;
+ u8 cache_xfrq_cons;
+ u8 cache_sq_cons;
+#elif defined(__LITTLE_ENDIAN)
+ u8 cache_sq_cons;
+ u8 cache_xfrq_cons;
+ u8 cos;
+ u8 vlan_num;
+#endif
+ u32 verify_tx_seq;
+};
+
+/*
+ * Xstorm FCoE Storm Context
+ */
+struct xstorm_fcoe_st_context {
+ struct xstorm_fcoe_eth_context_section eth;
+ struct xstorm_fcoe_context_section fcoe;
+};
+
+/*
+ * Fcoe connection context
+ */
+struct fcoe_context {
+ struct ustorm_fcoe_st_context ustorm_st_context;
+ struct tstorm_fcoe_st_context tstorm_st_context;
+ struct xstorm_fcoe_ag_context xstorm_ag_context;
+ struct tstorm_fcoe_ag_context tstorm_ag_context;
+ struct ustorm_fcoe_ag_context ustorm_ag_context;
+ struct timers_block_context timers_context;
+ struct xstorm_fcoe_st_context xstorm_st_context;
+};
+
+/*
+ * FCoE init params passed by driver to FW in FCoE init ramrod
+ * $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_init_ramrod_params {
+ struct fcoe_kwqe_init1 init_kwqe1;
+ struct fcoe_kwqe_init2 init_kwqe2;
+ struct fcoe_kwqe_init3 init_kwqe3;
+ struct regpair eq_pbl_base;
+ __le32 eq_pbl_size;
+ __le32 reserved2;
+ __le16 eq_prod;
+ __le16 sb_num;
+ u8 sb_id;
+ u8 reserved0;
+ __le16 reserved1;
+};
+
+/*
+ * FCoE statistics params buffer passed by driver to FW in FCoE statistics
+ * ramrod $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_stat_ramrod_params {
+ struct fcoe_kwqe_stat stat_kwqe;
+};
+
+/*
+ * CQ DB CQ producer and pending completion counter
+ */
+struct iscsi_cq_db_prod_pnd_cmpltn_cnt {
+#if defined(__BIG_ENDIAN)
+ u16 cntr;
+ u16 prod;
+#elif defined(__LITTLE_ENDIAN)
+ u16 prod;
+ u16 cntr;
+#endif
+};
+
+/*
+ * CQ DB pending completion ITT array
+ */
+struct iscsi_cq_db_prod_pnd_cmpltn_cnt_arr {
+ struct iscsi_cq_db_prod_pnd_cmpltn_cnt prod_pend_comp[8];
+};
+
+/*
+ * Cstorm CQ sequence to notify array, updated by driver
+ */
+struct iscsi_cq_db_sqn_2_notify_arr {
+ u16 sqn[8];
+};
+
+/*
+ * Cstorm iSCSI Storm Context
+ */
+struct cstorm_iscsi_st_context {
+ struct iscsi_cq_db_prod_pnd_cmpltn_cnt_arr cq_c_prod_pend_comp_ctr_arr;
+ struct iscsi_cq_db_sqn_2_notify_arr cq_c_prod_sqn_arr;
+ struct iscsi_cq_db_sqn_2_notify_arr cq_c_sqn_2_notify_arr;
+ struct regpair hq_pbl_base;
+ struct regpair hq_curr_pbe;
+ struct regpair task_pbl_base;
+ struct regpair cq_db_base;
+#if defined(__BIG_ENDIAN)
+ u16 hq_bd_itt;
+ u16 iscsi_conn_id;
+#elif defined(__LITTLE_ENDIAN)
+ u16 iscsi_conn_id;
+ u16 hq_bd_itt;
+#endif
+ u32 hq_bd_data_segment_len;
+ u32 hq_bd_buffer_offset;
+#if defined(__BIG_ENDIAN)
+ u8 rsrv;
+ u8 cq_proc_en_bit_map;
+ u8 cq_pend_comp_itt_valid_bit_map;
+ u8 hq_bd_opcode;
+#elif defined(__LITTLE_ENDIAN)
+ u8 hq_bd_opcode;
+ u8 cq_pend_comp_itt_valid_bit_map;
+ u8 cq_proc_en_bit_map;
+ u8 rsrv;
+#endif
+ u32 hq_tcp_seq;
+#if defined(__BIG_ENDIAN)
+ u16 flags;
+#define CSTORM_ISCSI_ST_CONTEXT_DATA_DIGEST_EN (0x1<<0)
+#define CSTORM_ISCSI_ST_CONTEXT_DATA_DIGEST_EN_SHIFT 0
+#define CSTORM_ISCSI_ST_CONTEXT_HDR_DIGEST_EN (0x1<<1)
+#define CSTORM_ISCSI_ST_CONTEXT_HDR_DIGEST_EN_SHIFT 1
+#define CSTORM_ISCSI_ST_CONTEXT_HQ_BD_CTXT_VALID (0x1<<2)
+#define CSTORM_ISCSI_ST_CONTEXT_HQ_BD_CTXT_VALID_SHIFT 2
+#define CSTORM_ISCSI_ST_CONTEXT_HQ_BD_LCL_CMPLN_FLG (0x1<<3)
+#define CSTORM_ISCSI_ST_CONTEXT_HQ_BD_LCL_CMPLN_FLG_SHIFT 3
+#define CSTORM_ISCSI_ST_CONTEXT_HQ_BD_WRITE_TASK (0x1<<4)
+#define CSTORM_ISCSI_ST_CONTEXT_HQ_BD_WRITE_TASK_SHIFT 4
+#define CSTORM_ISCSI_ST_CONTEXT_CTRL_FLAGS_RSRV (0x7FF<<5)
+#define CSTORM_ISCSI_ST_CONTEXT_CTRL_FLAGS_RSRV_SHIFT 5
+ u16 hq_cons;
+#elif defined(__LITTLE_ENDIAN)
+ u16 hq_cons;
+ u16 flags;
+#define CSTORM_ISCSI_ST_CONTEXT_DATA_DIGEST_EN (0x1<<0)
+#define CSTORM_ISCSI_ST_CONTEXT_DATA_DIGEST_EN_SHIFT 0
+#define CSTORM_ISCSI_ST_CONTEXT_HDR_DIGEST_EN (0x1<<1)
+#define CSTORM_ISCSI_ST_CONTEXT_HDR_DIGEST_EN_SHIFT 1
+#define CSTORM_ISCSI_ST_CONTEXT_HQ_BD_CTXT_VALID (0x1<<2)
+#define CSTORM_ISCSI_ST_CONTEXT_HQ_BD_CTXT_VALID_SHIFT 2
+#define CSTORM_ISCSI_ST_CONTEXT_HQ_BD_LCL_CMPLN_FLG (0x1<<3)
+#define CSTORM_ISCSI_ST_CONTEXT_HQ_BD_LCL_CMPLN_FLG_SHIFT 3
+#define CSTORM_ISCSI_ST_CONTEXT_HQ_BD_WRITE_TASK (0x1<<4)
+#define CSTORM_ISCSI_ST_CONTEXT_HQ_BD_WRITE_TASK_SHIFT 4
+#define CSTORM_ISCSI_ST_CONTEXT_CTRL_FLAGS_RSRV (0x7FF<<5)
+#define CSTORM_ISCSI_ST_CONTEXT_CTRL_FLAGS_RSRV_SHIFT 5
+#endif
+ struct regpair rsrv1;
+};
+
+
+/*
+ * SCSI read/write SQ WQE
+ */
+struct iscsi_cmd_pdu_hdr_little_endian {
+#if defined(__BIG_ENDIAN)
+ u8 opcode;
+ u8 op_attr;
+#define ISCSI_CMD_PDU_HDR_LITTLE_ENDIAN_ATTRIBUTES (0x7<<0)
+#define ISCSI_CMD_PDU_HDR_LITTLE_ENDIAN_ATTRIBUTES_SHIFT 0
+#define ISCSI_CMD_PDU_HDR_LITTLE_ENDIAN_RSRV1 (0x3<<3)
+#define ISCSI_CMD_PDU_HDR_LITTLE_ENDIAN_RSRV1_SHIFT 3
+#define ISCSI_CMD_PDU_HDR_LITTLE_ENDIAN_WRITE_FLAG (0x1<<5)
+#define ISCSI_CMD_PDU_HDR_LITTLE_ENDIAN_WRITE_FLAG_SHIFT 5
+#define ISCSI_CMD_PDU_HDR_LITTLE_ENDIAN_READ_FLAG (0x1<<6)
+#define ISCSI_CMD_PDU_HDR_LITTLE_ENDIAN_READ_FLAG_SHIFT 6
+#define ISCSI_CMD_PDU_HDR_LITTLE_ENDIAN_FINAL_FLAG (0x1<<7)
+#define ISCSI_CMD_PDU_HDR_LITTLE_ENDIAN_FINAL_FLAG_SHIFT 7
+ u16 rsrv0;
+#elif defined(__LITTLE_ENDIAN)
+ u16 rsrv0;
+ u8 op_attr;
+#define ISCSI_CMD_PDU_HDR_LITTLE_ENDIAN_ATTRIBUTES (0x7<<0)
+#define ISCSI_CMD_PDU_HDR_LITTLE_ENDIAN_ATTRIBUTES_SHIFT 0
+#define ISCSI_CMD_PDU_HDR_LITTLE_ENDIAN_RSRV1 (0x3<<3)
+#define ISCSI_CMD_PDU_HDR_LITTLE_ENDIAN_RSRV1_SHIFT 3
+#define ISCSI_CMD_PDU_HDR_LITTLE_ENDIAN_WRITE_FLAG (0x1<<5)
+#define ISCSI_CMD_PDU_HDR_LITTLE_ENDIAN_WRITE_FLAG_SHIFT 5
+#define ISCSI_CMD_PDU_HDR_LITTLE_ENDIAN_READ_FLAG (0x1<<6)
+#define ISCSI_CMD_PDU_HDR_LITTLE_ENDIAN_READ_FLAG_SHIFT 6
+#define ISCSI_CMD_PDU_HDR_LITTLE_ENDIAN_FINAL_FLAG (0x1<<7)
+#define ISCSI_CMD_PDU_HDR_LITTLE_ENDIAN_FINAL_FLAG_SHIFT 7
+ u8 opcode;
+#endif
+ u32 data_fields;
+#define ISCSI_CMD_PDU_HDR_LITTLE_ENDIAN_DATA_SEGMENT_LENGTH (0xFFFFFF<<0)
+#define ISCSI_CMD_PDU_HDR_LITTLE_ENDIAN_DATA_SEGMENT_LENGTH_SHIFT 0
+#define ISCSI_CMD_PDU_HDR_LITTLE_ENDIAN_TOTAL_AHS_LENGTH (0xFF<<24)
+#define ISCSI_CMD_PDU_HDR_LITTLE_ENDIAN_TOTAL_AHS_LENGTH_SHIFT 24
+ struct regpair lun;
+ u32 itt;
+ u32 expected_data_transfer_length;
+ u32 cmd_sn;
+ u32 exp_stat_sn;
+ u32 scsi_command_block[4];
+};
+
+
+/*
+ * Buffer per connection, used in Tstorm
+ */
+struct iscsi_conn_buf {
+ struct regpair reserved[8];
+};
+
+
+/*
+ * iSCSI context region, used only in iSCSI
+ */
+struct ustorm_iscsi_rq_db {
+ struct regpair pbl_base;
+ struct regpair curr_pbe;
+};
+
+/*
+ * iSCSI context region, used only in iSCSI
+ */
+struct ustorm_iscsi_r2tq_db {
+ struct regpair pbl_base;
+ struct regpair curr_pbe;
+};
+
+/*
+ * iSCSI context region, used only in iSCSI
+ */
+struct ustorm_iscsi_cq_db {
+#if defined(__BIG_ENDIAN)
+ u16 cq_sn;
+ u16 prod;
+#elif defined(__LITTLE_ENDIAN)
+ u16 prod;
+ u16 cq_sn;
+#endif
+ struct regpair curr_pbe;
+};
+
+/*
+ * iSCSI context region, used only in iSCSI
+ */
+struct rings_db {
+ struct ustorm_iscsi_rq_db rq;
+ struct ustorm_iscsi_r2tq_db r2tq;
+ struct ustorm_iscsi_cq_db cq[8];
+#if defined(__BIG_ENDIAN)
+ u16 rq_prod;
+ u16 r2tq_prod;
+#elif defined(__LITTLE_ENDIAN)
+ u16 r2tq_prod;
+ u16 rq_prod;
+#endif
+ struct regpair cq_pbl_base;
+};
+
+/*
+ * iSCSI context region, used only in iSCSI
+ */
+struct ustorm_iscsi_placement_db {
+ u32 sgl_base_lo;
+ u32 sgl_base_hi;
+ u32 local_sge_0_address_hi;
+ u32 local_sge_0_address_lo;
+#if defined(__BIG_ENDIAN)
+ u16 curr_sge_offset;
+ u16 local_sge_0_size;
+#elif defined(__LITTLE_ENDIAN)
+ u16 local_sge_0_size;
+ u16 curr_sge_offset;
+#endif
+ u32 local_sge_1_address_hi;
+ u32 local_sge_1_address_lo;
+#if defined(__BIG_ENDIAN)
+ u8 exp_padding_2b;
+ u8 nal_len_3b;
+ u16 local_sge_1_size;
+#elif defined(__LITTLE_ENDIAN)
+ u16 local_sge_1_size;
+ u8 nal_len_3b;
+ u8 exp_padding_2b;
+#endif
+#if defined(__BIG_ENDIAN)
+ u8 sgl_size;
+ u8 local_sge_index_2b;
+ u16 reserved7;
+#elif defined(__LITTLE_ENDIAN)
+ u16 reserved7;
+ u8 local_sge_index_2b;
+ u8 sgl_size;
+#endif
+ u32 rem_pdu;
+ u32 place_db_bitfield_1;
+#define USTORM_ISCSI_PLACEMENT_DB_REM_PDU_PAYLOAD (0xFFFFFF<<0)
+#define USTORM_ISCSI_PLACEMENT_DB_REM_PDU_PAYLOAD_SHIFT 0
+#define USTORM_ISCSI_PLACEMENT_DB_CQ_ID (0xFF<<24)
+#define USTORM_ISCSI_PLACEMENT_DB_CQ_ID_SHIFT 24
+ u32 place_db_bitfield_2;
+#define USTORM_ISCSI_PLACEMENT_DB_BYTES_2_TRUNCATE (0xFFFFFF<<0)
+#define USTORM_ISCSI_PLACEMENT_DB_BYTES_2_TRUNCATE_SHIFT 0
+#define USTORM_ISCSI_PLACEMENT_DB_HOST_SGE_INDEX (0xFF<<24)
+#define USTORM_ISCSI_PLACEMENT_DB_HOST_SGE_INDEX_SHIFT 24
+ u32 nal;
+#define USTORM_ISCSI_PLACEMENT_DB_REM_SGE_SIZE (0xFFFFFF<<0)
+#define USTORM_ISCSI_PLACEMENT_DB_REM_SGE_SIZE_SHIFT 0
+#define USTORM_ISCSI_PLACEMENT_DB_EXP_DIGEST_3B (0xFF<<24)
+#define USTORM_ISCSI_PLACEMENT_DB_EXP_DIGEST_3B_SHIFT 24
+};
+
+/*
+ * Ustorm iSCSI Storm Context
+ */
+struct ustorm_iscsi_st_context {
+ u32 exp_stat_sn;
+ u32 exp_data_sn;
+ struct rings_db ring;
+ struct regpair task_pbl_base;
+ struct regpair tce_phy_addr;
+ struct ustorm_iscsi_placement_db place_db;
+ u32 reserved8;
+ u32 rem_rcv_len;
+#if defined(__BIG_ENDIAN)
+ u16 hdr_itt;
+ u16 iscsi_conn_id;
+#elif defined(__LITTLE_ENDIAN)
+ u16 iscsi_conn_id;
+ u16 hdr_itt;
+#endif
+ u32 nal_bytes;
+#if defined(__BIG_ENDIAN)
+ u8 hdr_second_byte_union;
+ u8 bitfield_0;
+#define USTORM_ISCSI_ST_CONTEXT_BMIDDLEOFPDU (0x1<<0)
+#define USTORM_ISCSI_ST_CONTEXT_BMIDDLEOFPDU_SHIFT 0
+#define USTORM_ISCSI_ST_CONTEXT_BFENCECQE (0x1<<1)
+#define USTORM_ISCSI_ST_CONTEXT_BFENCECQE_SHIFT 1
+#define USTORM_ISCSI_ST_CONTEXT_BRESETCRC (0x1<<2)
+#define USTORM_ISCSI_ST_CONTEXT_BRESETCRC_SHIFT 2
+#define USTORM_ISCSI_ST_CONTEXT_RESERVED1 (0x1F<<3)
+#define USTORM_ISCSI_ST_CONTEXT_RESERVED1_SHIFT 3
+ u8 task_pdu_cache_index;
+ u8 task_pbe_cache_index;
+#elif defined(__LITTLE_ENDIAN)
+ u8 task_pbe_cache_index;
+ u8 task_pdu_cache_index;
+ u8 bitfield_0;
+#define USTORM_ISCSI_ST_CONTEXT_BMIDDLEOFPDU (0x1<<0)
+#define USTORM_ISCSI_ST_CONTEXT_BMIDDLEOFPDU_SHIFT 0
+#define USTORM_ISCSI_ST_CONTEXT_BFENCECQE (0x1<<1)
+#define USTORM_ISCSI_ST_CONTEXT_BFENCECQE_SHIFT 1
+#define USTORM_ISCSI_ST_CONTEXT_BRESETCRC (0x1<<2)
+#define USTORM_ISCSI_ST_CONTEXT_BRESETCRC_SHIFT 2
+#define USTORM_ISCSI_ST_CONTEXT_RESERVED1 (0x1F<<3)
+#define USTORM_ISCSI_ST_CONTEXT_RESERVED1_SHIFT 3
+ u8 hdr_second_byte_union;
+#endif
+#if defined(__BIG_ENDIAN)
+ u16 reserved3;
+ u8 reserved2;
+ u8 acDecrement;
+#elif defined(__LITTLE_ENDIAN)
+ u8 acDecrement;
+ u8 reserved2;
+ u16 reserved3;
+#endif
+ u32 task_stat;
+#if defined(__BIG_ENDIAN)
+ u8 hdr_opcode;
+ u8 num_cqs;
+ u16 reserved5;
+#elif defined(__LITTLE_ENDIAN)
+ u16 reserved5;
+ u8 num_cqs;
+ u8 hdr_opcode;
+#endif
+ u32 negotiated_rx;
+#define USTORM_ISCSI_ST_CONTEXT_MAX_RECV_PDU_LENGTH (0xFFFFFF<<0)
+#define USTORM_ISCSI_ST_CONTEXT_MAX_RECV_PDU_LENGTH_SHIFT 0
+#define USTORM_ISCSI_ST_CONTEXT_MAX_OUTSTANDING_R2TS (0xFF<<24)
+#define USTORM_ISCSI_ST_CONTEXT_MAX_OUTSTANDING_R2TS_SHIFT 24
+ u32 negotiated_rx_and_flags;
+#define USTORM_ISCSI_ST_CONTEXT_MAX_BURST_LENGTH (0xFFFFFF<<0)
+#define USTORM_ISCSI_ST_CONTEXT_MAX_BURST_LENGTH_SHIFT 0
+#define USTORM_ISCSI_ST_CONTEXT_B_CQE_POSTED_OR_HEADER_CACHED (0x1<<24)
+#define USTORM_ISCSI_ST_CONTEXT_B_CQE_POSTED_OR_HEADER_CACHED_SHIFT 24
+#define USTORM_ISCSI_ST_CONTEXT_B_HDR_DIGEST_EN (0x1<<25)
+#define USTORM_ISCSI_ST_CONTEXT_B_HDR_DIGEST_EN_SHIFT 25
+#define USTORM_ISCSI_ST_CONTEXT_B_DATA_DIGEST_EN (0x1<<26)
+#define USTORM_ISCSI_ST_CONTEXT_B_DATA_DIGEST_EN_SHIFT 26
+#define USTORM_ISCSI_ST_CONTEXT_B_PROTOCOL_ERROR (0x1<<27)
+#define USTORM_ISCSI_ST_CONTEXT_B_PROTOCOL_ERROR_SHIFT 27
+#define USTORM_ISCSI_ST_CONTEXT_B_TASK_VALID (0x1<<28)
+#define USTORM_ISCSI_ST_CONTEXT_B_TASK_VALID_SHIFT 28
+#define USTORM_ISCSI_ST_CONTEXT_TASK_TYPE (0x3<<29)
+#define USTORM_ISCSI_ST_CONTEXT_TASK_TYPE_SHIFT 29
+#define USTORM_ISCSI_ST_CONTEXT_B_ALL_DATA_ACKED (0x1<<31)
+#define USTORM_ISCSI_ST_CONTEXT_B_ALL_DATA_ACKED_SHIFT 31
+};
+
+/*
+ * TCP context region, shared in TOE, RDMA and ISCSI
+ */
+struct tstorm_tcp_st_context_section {
+ u32 flags1;
+#define TSTORM_TCP_ST_CONTEXT_SECTION_RTT_SRTT (0xFFFFFF<<0)
+#define TSTORM_TCP_ST_CONTEXT_SECTION_RTT_SRTT_SHIFT 0
+#define TSTORM_TCP_ST_CONTEXT_SECTION_PAWS_INVALID (0x1<<24)
+#define TSTORM_TCP_ST_CONTEXT_SECTION_PAWS_INVALID_SHIFT 24
+#define TSTORM_TCP_ST_CONTEXT_SECTION_TIMESTAMP_EXISTS (0x1<<25)
+#define TSTORM_TCP_ST_CONTEXT_SECTION_TIMESTAMP_EXISTS_SHIFT 25
+#define TSTORM_TCP_ST_CONTEXT_SECTION_RESERVED0 (0x1<<26)
+#define TSTORM_TCP_ST_CONTEXT_SECTION_RESERVED0_SHIFT 26
+#define TSTORM_TCP_ST_CONTEXT_SECTION_STOP_RX_PAYLOAD (0x1<<27)
+#define TSTORM_TCP_ST_CONTEXT_SECTION_STOP_RX_PAYLOAD_SHIFT 27
+#define TSTORM_TCP_ST_CONTEXT_SECTION_KA_ENABLED (0x1<<28)
+#define TSTORM_TCP_ST_CONTEXT_SECTION_KA_ENABLED_SHIFT 28
+#define TSTORM_TCP_ST_CONTEXT_SECTION_FIRST_RTO_ESTIMATE (0x1<<29)
+#define TSTORM_TCP_ST_CONTEXT_SECTION_FIRST_RTO_ESTIMATE_SHIFT 29
+#define TSTORM_TCP_ST_CONTEXT_SECTION_MAX_SEG_RETRANSMIT_EN (0x1<<30)
+#define TSTORM_TCP_ST_CONTEXT_SECTION_MAX_SEG_RETRANSMIT_EN_SHIFT 30
+#define TSTORM_TCP_ST_CONTEXT_SECTION_LAST_ISLE_HAS_FIN (0x1<<31)
+#define TSTORM_TCP_ST_CONTEXT_SECTION_LAST_ISLE_HAS_FIN_SHIFT 31
+ u32 flags2;
+#define TSTORM_TCP_ST_CONTEXT_SECTION_RTT_VARIATION (0xFFFFFF<<0)
+#define TSTORM_TCP_ST_CONTEXT_SECTION_RTT_VARIATION_SHIFT 0
+#define TSTORM_TCP_ST_CONTEXT_SECTION_DA_EN (0x1<<24)
+#define TSTORM_TCP_ST_CONTEXT_SECTION_DA_EN_SHIFT 24
+#define TSTORM_TCP_ST_CONTEXT_SECTION_DA_COUNTER_EN (0x1<<25)
+#define TSTORM_TCP_ST_CONTEXT_SECTION_DA_COUNTER_EN_SHIFT 25
+#define __TSTORM_TCP_ST_CONTEXT_SECTION_KA_PROBE_SENT (0x1<<26)
+#define __TSTORM_TCP_ST_CONTEXT_SECTION_KA_PROBE_SENT_SHIFT 26
+#define __TSTORM_TCP_ST_CONTEXT_SECTION_PERSIST_PROBE_SENT (0x1<<27)
+#define __TSTORM_TCP_ST_CONTEXT_SECTION_PERSIST_PROBE_SENT_SHIFT 27
+#define TSTORM_TCP_ST_CONTEXT_SECTION_UPDATE_L2_STATSTICS (0x1<<28)
+#define TSTORM_TCP_ST_CONTEXT_SECTION_UPDATE_L2_STATSTICS_SHIFT 28
+#define TSTORM_TCP_ST_CONTEXT_SECTION_UPDATE_L4_STATSTICS (0x1<<29)
+#define TSTORM_TCP_ST_CONTEXT_SECTION_UPDATE_L4_STATSTICS_SHIFT 29
+#define __TSTORM_TCP_ST_CONTEXT_SECTION_IN_WINDOW_RST_ATTACK (0x1<<30)
+#define __TSTORM_TCP_ST_CONTEXT_SECTION_IN_WINDOW_RST_ATTACK_SHIFT 30
+#define __TSTORM_TCP_ST_CONTEXT_SECTION_IN_WINDOW_SYN_ATTACK (0x1<<31)
+#define __TSTORM_TCP_ST_CONTEXT_SECTION_IN_WINDOW_SYN_ATTACK_SHIFT 31
+#if defined(__BIG_ENDIAN)
+ u16 mss;
+ u8 tcp_sm_state;
+ u8 rto_exp;
+#elif defined(__LITTLE_ENDIAN)
+ u8 rto_exp;
+ u8 tcp_sm_state;
+ u16 mss;
+#endif
+ u32 rcv_nxt;
+ u32 timestamp_recent;
+ u32 timestamp_recent_time;
+ u32 cwnd;
+ u32 ss_thresh;
+ u32 cwnd_accum;
+ u32 prev_seg_seq;
+ u32 expected_rel_seq;
+ u32 recover;
+#if defined(__BIG_ENDIAN)
+ u8 retransmit_count;
+ u8 ka_max_probe_count;
+ u8 persist_probe_count;
+ u8 ka_probe_count;
+#elif defined(__LITTLE_ENDIAN)
+ u8 ka_probe_count;
+ u8 persist_probe_count;
+ u8 ka_max_probe_count;
+ u8 retransmit_count;
+#endif
+#if defined(__BIG_ENDIAN)
+ u8 statistics_counter_id;
+ u8 ooo_support_mode;
+ u8 snd_wnd_scale;
+ u8 dup_ack_count;
+#elif defined(__LITTLE_ENDIAN)
+ u8 dup_ack_count;
+ u8 snd_wnd_scale;
+ u8 ooo_support_mode;
+ u8 statistics_counter_id;
+#endif
+ u32 retransmit_start_time;
+ u32 ka_timeout;
+ u32 ka_interval;
+ u32 isle_start_seq;
+ u32 isle_end_seq;
+#if defined(__BIG_ENDIAN)
+ u16 second_isle_address;
+ u16 recent_seg_wnd;
+#elif defined(__LITTLE_ENDIAN)
+ u16 recent_seg_wnd;
+ u16 second_isle_address;
+#endif
+#if defined(__BIG_ENDIAN)
+ u8 max_isles_ever_happened;
+ u8 isles_number;
+ u16 last_isle_address;
+#elif defined(__LITTLE_ENDIAN)
+ u16 last_isle_address;
+ u8 isles_number;
+ u8 max_isles_ever_happened;
+#endif
+ u32 max_rt_time;
+#if defined(__BIG_ENDIAN)
+ u16 lsb_mac_address;
+ u16 vlan_id;
+#elif defined(__LITTLE_ENDIAN)
+ u16 vlan_id;
+ u16 lsb_mac_address;
+#endif
+#if defined(__BIG_ENDIAN)
+ u16 msb_mac_address;
+ u16 mid_mac_address;
+#elif defined(__LITTLE_ENDIAN)
+ u16 mid_mac_address;
+ u16 msb_mac_address;
+#endif
+ u32 rightmost_received_seq;
+};
+
+/*
+ * Termination variables
+ */
+struct iscsi_term_vars {
+ u8 BitMap;
+#define ISCSI_TERM_VARS_TCP_STATE (0xF<<0)
+#define ISCSI_TERM_VARS_TCP_STATE_SHIFT 0
+#define ISCSI_TERM_VARS_FIN_RECEIVED_SBIT (0x1<<4)
+#define ISCSI_TERM_VARS_FIN_RECEIVED_SBIT_SHIFT 4
+#define ISCSI_TERM_VARS_ACK_ON_FIN_RECEIVED_SBIT (0x1<<5)
+#define ISCSI_TERM_VARS_ACK_ON_FIN_RECEIVED_SBIT_SHIFT 5
+#define ISCSI_TERM_VARS_TERM_ON_CHIP (0x1<<6)
+#define ISCSI_TERM_VARS_TERM_ON_CHIP_SHIFT 6
+#define ISCSI_TERM_VARS_RSRV (0x1<<7)
+#define ISCSI_TERM_VARS_RSRV_SHIFT 7
+};
+
+/*
+ * iSCSI context region, used only in iSCSI
+ */
+struct tstorm_iscsi_st_context_section {
+ u32 nalPayload;
+ u32 b2nh;
+#if defined(__BIG_ENDIAN)
+ u16 rq_cons;
+ u8 flags;
+#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_HDR_DIGEST_EN (0x1<<0)
+#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_HDR_DIGEST_EN_SHIFT 0
+#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_DATA_DIGEST_EN (0x1<<1)
+#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_DATA_DIGEST_EN_SHIFT 1
+#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_PARTIAL_HEADER (0x1<<2)
+#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_PARTIAL_HEADER_SHIFT 2
+#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_FULL_FEATURE (0x1<<3)
+#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_FULL_FEATURE_SHIFT 3
+#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_DROP_ALL_PDUS (0x1<<4)
+#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_DROP_ALL_PDUS_SHIFT 4
+#define TSTORM_ISCSI_ST_CONTEXT_SECTION_NALLEN (0x3<<5)
+#define TSTORM_ISCSI_ST_CONTEXT_SECTION_NALLEN_SHIFT 5
+#define TSTORM_ISCSI_ST_CONTEXT_SECTION_RSRV0 (0x1<<7)
+#define TSTORM_ISCSI_ST_CONTEXT_SECTION_RSRV0_SHIFT 7
+ u8 hdr_bytes_2_fetch;
+#elif defined(__LITTLE_ENDIAN)
+ u8 hdr_bytes_2_fetch;
+ u8 flags;
+#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_HDR_DIGEST_EN (0x1<<0)
+#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_HDR_DIGEST_EN_SHIFT 0
+#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_DATA_DIGEST_EN (0x1<<1)
+#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_DATA_DIGEST_EN_SHIFT 1
+#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_PARTIAL_HEADER (0x1<<2)
+#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_PARTIAL_HEADER_SHIFT 2
+#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_FULL_FEATURE (0x1<<3)
+#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_FULL_FEATURE_SHIFT 3
+#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_DROP_ALL_PDUS (0x1<<4)
+#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_DROP_ALL_PDUS_SHIFT 4
+#define TSTORM_ISCSI_ST_CONTEXT_SECTION_NALLEN (0x3<<5)
+#define TSTORM_ISCSI_ST_CONTEXT_SECTION_NALLEN_SHIFT 5
+#define TSTORM_ISCSI_ST_CONTEXT_SECTION_RSRV0 (0x1<<7)
+#define TSTORM_ISCSI_ST_CONTEXT_SECTION_RSRV0_SHIFT 7
+ u16 rq_cons;
+#endif
+ struct regpair rq_db_phy_addr;
+#if defined(__BIG_ENDIAN)
+ struct iscsi_term_vars term_vars;
+ u8 rsrv1;
+ u16 iscsi_conn_id;
+#elif defined(__LITTLE_ENDIAN)
+ u16 iscsi_conn_id;
+ u8 rsrv1;
+ struct iscsi_term_vars term_vars;
+#endif
+ u32 process_nxt;
+};
+
+/*
+ * The iSCSI non-aggregative context of Tstorm
+ */
+struct tstorm_iscsi_st_context {
+ struct tstorm_tcp_st_context_section tcp;
+ struct tstorm_iscsi_st_context_section iscsi;
};
/*
@@ -3509,7 +4463,27 @@
u16 window_scaling_factor;
u16 pseudo_csum;
#endif
- u32 reserved2;
+#if defined(__BIG_ENDIAN)
+ u16 reserved2;
+ u8 statistics_counter_id;
+ u8 statistics_params;
+#define XSTORM_TCP_CONTEXT_SECTION_UPDATE_L2_STATSTICS (0x1<<0)
+#define XSTORM_TCP_CONTEXT_SECTION_UPDATE_L2_STATSTICS_SHIFT 0
+#define XSTORM_TCP_CONTEXT_SECTION_UPDATE_L4_STATSTICS (0x1<<1)
+#define XSTORM_TCP_CONTEXT_SECTION_UPDATE_L4_STATSTICS_SHIFT 1
+#define XSTORM_TCP_CONTEXT_SECTION_RESERVED (0x3F<<2)
+#define XSTORM_TCP_CONTEXT_SECTION_RESERVED_SHIFT 2
+#elif defined(__LITTLE_ENDIAN)
+ u8 statistics_params;
+#define XSTORM_TCP_CONTEXT_SECTION_UPDATE_L2_STATSTICS (0x1<<0)
+#define XSTORM_TCP_CONTEXT_SECTION_UPDATE_L2_STATSTICS_SHIFT 0
+#define XSTORM_TCP_CONTEXT_SECTION_UPDATE_L4_STATSTICS (0x1<<1)
+#define XSTORM_TCP_CONTEXT_SECTION_UPDATE_L4_STATSTICS_SHIFT 1
+#define XSTORM_TCP_CONTEXT_SECTION_RESERVED (0x3F<<2)
+#define XSTORM_TCP_CONTEXT_SECTION_RESERVED_SHIFT 2
+ u8 statistics_counter_id;
+ u16 reserved2;
+#endif
u32 ts_time_diff;
u32 __next_timer_expir;
};
@@ -3522,29 +4496,31 @@
union xstorm_ip_context_section_types ip_union;
struct xstorm_tcp_context_section tcp;
#if defined(__BIG_ENDIAN)
- u16 reserved;
- u8 statistics_params;
-#define XSTORM_COMMON_CONTEXT_SECTION_UPDATE_L2_STATSTICS (0x1<<0)
-#define XSTORM_COMMON_CONTEXT_SECTION_UPDATE_L2_STATSTICS_SHIFT 0
-#define XSTORM_COMMON_CONTEXT_SECTION_UPDATE_L4_STATSTICS (0x1<<1)
-#define XSTORM_COMMON_CONTEXT_SECTION_UPDATE_L4_STATSTICS_SHIFT 1
-#define XSTORM_COMMON_CONTEXT_SECTION_STATISTICS_COUNTER_ID (0x1F<<2)
-#define XSTORM_COMMON_CONTEXT_SECTION_STATISTICS_COUNTER_ID_SHIFT 2
-#define XSTORM_COMMON_CONTEXT_SECTION_DCB_EXISTS (0x1<<7)
-#define XSTORM_COMMON_CONTEXT_SECTION_DCB_EXISTS_SHIFT 7
+ u8 __dcb_val;
+ u8 flags;
+#define XSTORM_COMMON_CONTEXT_SECTION_PHYSQ_INITIALIZED (0x1<<0)
+#define XSTORM_COMMON_CONTEXT_SECTION_PHYSQ_INITIALIZED_SHIFT 0
+#define XSTORM_COMMON_CONTEXT_SECTION_PBF_PORT (0x7<<1)
+#define XSTORM_COMMON_CONTEXT_SECTION_PBF_PORT_SHIFT 1
+#define XSTORM_COMMON_CONTEXT_SECTION_VLAN_MODE (0x1<<4)
+#define XSTORM_COMMON_CONTEXT_SECTION_VLAN_MODE_SHIFT 4
+#define XSTORM_COMMON_CONTEXT_SECTION_ORIGINAL_PRIORITY (0x7<<5)
+#define XSTORM_COMMON_CONTEXT_SECTION_ORIGINAL_PRIORITY_SHIFT 5
+ u8 reserved;
u8 ip_version_1b;
#elif defined(__LITTLE_ENDIAN)
u8 ip_version_1b;
- u8 statistics_params;
-#define XSTORM_COMMON_CONTEXT_SECTION_UPDATE_L2_STATSTICS (0x1<<0)
-#define XSTORM_COMMON_CONTEXT_SECTION_UPDATE_L2_STATSTICS_SHIFT 0
-#define XSTORM_COMMON_CONTEXT_SECTION_UPDATE_L4_STATSTICS (0x1<<1)
-#define XSTORM_COMMON_CONTEXT_SECTION_UPDATE_L4_STATSTICS_SHIFT 1
-#define XSTORM_COMMON_CONTEXT_SECTION_STATISTICS_COUNTER_ID (0x1F<<2)
-#define XSTORM_COMMON_CONTEXT_SECTION_STATISTICS_COUNTER_ID_SHIFT 2
-#define XSTORM_COMMON_CONTEXT_SECTION_DCB_EXISTS (0x1<<7)
-#define XSTORM_COMMON_CONTEXT_SECTION_DCB_EXISTS_SHIFT 7
- u16 reserved;
+ u8 reserved;
+ u8 flags;
+#define XSTORM_COMMON_CONTEXT_SECTION_PHYSQ_INITIALIZED (0x1<<0)
+#define XSTORM_COMMON_CONTEXT_SECTION_PHYSQ_INITIALIZED_SHIFT 0
+#define XSTORM_COMMON_CONTEXT_SECTION_PBF_PORT (0x7<<1)
+#define XSTORM_COMMON_CONTEXT_SECTION_PBF_PORT_SHIFT 1
+#define XSTORM_COMMON_CONTEXT_SECTION_VLAN_MODE (0x1<<4)
+#define XSTORM_COMMON_CONTEXT_SECTION_VLAN_MODE_SHIFT 4
+#define XSTORM_COMMON_CONTEXT_SECTION_ORIGINAL_PRIORITY (0x7<<5)
+#define XSTORM_COMMON_CONTEXT_SECTION_ORIGINAL_PRIORITY_SHIFT 5
+ u8 __dcb_val;
#endif
};
@@ -3682,99 +4658,6 @@
};
/*
- * CQ DB CQ producer and pending completion counter
- */
-struct iscsi_cq_db_prod_pnd_cmpltn_cnt {
-#if defined(__BIG_ENDIAN)
- u16 cntr;
- u16 prod;
-#elif defined(__LITTLE_ENDIAN)
- u16 prod;
- u16 cntr;
-#endif
-};
-
-/*
- * CQ DB pending completion ITT array
- */
-struct iscsi_cq_db_prod_pnd_cmpltn_cnt_arr {
- struct iscsi_cq_db_prod_pnd_cmpltn_cnt prod_pend_comp[8];
-};
-
-/*
- * Cstorm CQ sequence to notify array, updated by driver
- */
-struct iscsi_cq_db_sqn_2_notify_arr {
- u16 sqn[8];
-};
-
-/*
- * Cstorm iSCSI Storm Context
- */
-struct cstorm_iscsi_st_context {
- struct iscsi_cq_db_prod_pnd_cmpltn_cnt_arr cq_c_prod_pend_comp_ctr_arr;
- struct iscsi_cq_db_sqn_2_notify_arr cq_c_prod_sqn_arr;
- struct iscsi_cq_db_sqn_2_notify_arr cq_c_sqn_2_notify_arr;
- struct regpair hq_pbl_base;
- struct regpair hq_curr_pbe;
- struct regpair task_pbl_base;
- struct regpair cq_db_base;
-#if defined(__BIG_ENDIAN)
- u16 hq_bd_itt;
- u16 iscsi_conn_id;
-#elif defined(__LITTLE_ENDIAN)
- u16 iscsi_conn_id;
- u16 hq_bd_itt;
-#endif
- u32 hq_bd_data_segment_len;
- u32 hq_bd_buffer_offset;
-#if defined(__BIG_ENDIAN)
- u8 timer_entry_idx;
- u8 cq_proc_en_bit_map;
- u8 cq_pend_comp_itt_valid_bit_map;
- u8 hq_bd_opcode;
-#elif defined(__LITTLE_ENDIAN)
- u8 hq_bd_opcode;
- u8 cq_pend_comp_itt_valid_bit_map;
- u8 cq_proc_en_bit_map;
- u8 timer_entry_idx;
-#endif
- u32 hq_tcp_seq;
-#if defined(__BIG_ENDIAN)
- u16 flags;
-#define CSTORM_ISCSI_ST_CONTEXT_DATA_DIGEST_EN (0x1<<0)
-#define CSTORM_ISCSI_ST_CONTEXT_DATA_DIGEST_EN_SHIFT 0
-#define CSTORM_ISCSI_ST_CONTEXT_HDR_DIGEST_EN (0x1<<1)
-#define CSTORM_ISCSI_ST_CONTEXT_HDR_DIGEST_EN_SHIFT 1
-#define CSTORM_ISCSI_ST_CONTEXT_HQ_BD_CTXT_VALID (0x1<<2)
-#define CSTORM_ISCSI_ST_CONTEXT_HQ_BD_CTXT_VALID_SHIFT 2
-#define CSTORM_ISCSI_ST_CONTEXT_HQ_BD_LCL_CMPLN_FLG (0x1<<3)
-#define CSTORM_ISCSI_ST_CONTEXT_HQ_BD_LCL_CMPLN_FLG_SHIFT 3
-#define CSTORM_ISCSI_ST_CONTEXT_HQ_BD_WRITE_TASK (0x1<<4)
-#define CSTORM_ISCSI_ST_CONTEXT_HQ_BD_WRITE_TASK_SHIFT 4
-#define CSTORM_ISCSI_ST_CONTEXT_CTRL_FLAGS_RSRV (0x7FF<<5)
-#define CSTORM_ISCSI_ST_CONTEXT_CTRL_FLAGS_RSRV_SHIFT 5
- u16 hq_cons;
-#elif defined(__LITTLE_ENDIAN)
- u16 hq_cons;
- u16 flags;
-#define CSTORM_ISCSI_ST_CONTEXT_DATA_DIGEST_EN (0x1<<0)
-#define CSTORM_ISCSI_ST_CONTEXT_DATA_DIGEST_EN_SHIFT 0
-#define CSTORM_ISCSI_ST_CONTEXT_HDR_DIGEST_EN (0x1<<1)
-#define CSTORM_ISCSI_ST_CONTEXT_HDR_DIGEST_EN_SHIFT 1
-#define CSTORM_ISCSI_ST_CONTEXT_HQ_BD_CTXT_VALID (0x1<<2)
-#define CSTORM_ISCSI_ST_CONTEXT_HQ_BD_CTXT_VALID_SHIFT 2
-#define CSTORM_ISCSI_ST_CONTEXT_HQ_BD_LCL_CMPLN_FLG (0x1<<3)
-#define CSTORM_ISCSI_ST_CONTEXT_HQ_BD_LCL_CMPLN_FLG_SHIFT 3
-#define CSTORM_ISCSI_ST_CONTEXT_HQ_BD_WRITE_TASK (0x1<<4)
-#define CSTORM_ISCSI_ST_CONTEXT_HQ_BD_WRITE_TASK_SHIFT 4
-#define CSTORM_ISCSI_ST_CONTEXT_CTRL_FLAGS_RSRV (0x7FF<<5)
-#define CSTORM_ISCSI_ST_CONTEXT_CTRL_FLAGS_RSRV_SHIFT 5
-#endif
- struct regpair rsrv1;
-};
-
-/*
* Iscsi connection context
*/
struct iscsi_context {
@@ -3791,584 +4674,389 @@
struct cstorm_iscsi_st_context cstorm_st_context;
};
+
/*
- * FCoE KCQ CQE parameters
+ * PDU header of an iSCSI DATA-OUT
*/
-union fcoe_kcqe_params {
- u32 reserved0[4];
+struct iscsi_data_pdu_hdr_little_endian {
+#if defined(__BIG_ENDIAN)
+ u8 opcode;
+ u8 op_attr;
+#define ISCSI_DATA_PDU_HDR_LITTLE_ENDIAN_RSRV1 (0x7F<<0)
+#define ISCSI_DATA_PDU_HDR_LITTLE_ENDIAN_RSRV1_SHIFT 0
+#define ISCSI_DATA_PDU_HDR_LITTLE_ENDIAN_FINAL_FLAG (0x1<<7)
+#define ISCSI_DATA_PDU_HDR_LITTLE_ENDIAN_FINAL_FLAG_SHIFT 7
+ u16 rsrv0;
+#elif defined(__LITTLE_ENDIAN)
+ u16 rsrv0;
+ u8 op_attr;
+#define ISCSI_DATA_PDU_HDR_LITTLE_ENDIAN_RSRV1 (0x7F<<0)
+#define ISCSI_DATA_PDU_HDR_LITTLE_ENDIAN_RSRV1_SHIFT 0
+#define ISCSI_DATA_PDU_HDR_LITTLE_ENDIAN_FINAL_FLAG (0x1<<7)
+#define ISCSI_DATA_PDU_HDR_LITTLE_ENDIAN_FINAL_FLAG_SHIFT 7
+ u8 opcode;
+#endif
+ u32 data_fields;
+#define ISCSI_DATA_PDU_HDR_LITTLE_ENDIAN_DATA_SEGMENT_LENGTH (0xFFFFFF<<0)
+#define ISCSI_DATA_PDU_HDR_LITTLE_ENDIAN_DATA_SEGMENT_LENGTH_SHIFT 0
+#define ISCSI_DATA_PDU_HDR_LITTLE_ENDIAN_TOTAL_AHS_LENGTH (0xFF<<24)
+#define ISCSI_DATA_PDU_HDR_LITTLE_ENDIAN_TOTAL_AHS_LENGTH_SHIFT 24
+ struct regpair lun;
+ u32 itt;
+ u32 ttt;
+ u32 rsrv2;
+ u32 exp_stat_sn;
+ u32 rsrv3;
+ u32 data_sn;
+ u32 buffer_offset;
+ u32 rsrv4;
+};
+
+
+/*
+ * PDU header of an iSCSI login request
+ */
+struct iscsi_login_req_hdr_little_endian {
+#if defined(__BIG_ENDIAN)
+ u8 opcode;
+ u8 op_attr;
+#define ISCSI_LOGIN_REQ_HDR_LITTLE_ENDIAN_NSG (0x3<<0)
+#define ISCSI_LOGIN_REQ_HDR_LITTLE_ENDIAN_NSG_SHIFT 0
+#define ISCSI_LOGIN_REQ_HDR_LITTLE_ENDIAN_CSG (0x3<<2)
+#define ISCSI_LOGIN_REQ_HDR_LITTLE_ENDIAN_CSG_SHIFT 2
+#define ISCSI_LOGIN_REQ_HDR_LITTLE_ENDIAN_RSRV0 (0x3<<4)
+#define ISCSI_LOGIN_REQ_HDR_LITTLE_ENDIAN_RSRV0_SHIFT 4
+#define ISCSI_LOGIN_REQ_HDR_LITTLE_ENDIAN_CONTINUE_FLG (0x1<<6)
+#define ISCSI_LOGIN_REQ_HDR_LITTLE_ENDIAN_CONTINUE_FLG_SHIFT 6
+#define ISCSI_LOGIN_REQ_HDR_LITTLE_ENDIAN_TRANSIT (0x1<<7)
+#define ISCSI_LOGIN_REQ_HDR_LITTLE_ENDIAN_TRANSIT_SHIFT 7
+ u8 version_max;
+ u8 version_min;
+#elif defined(__LITTLE_ENDIAN)
+ u8 version_min;
+ u8 version_max;
+ u8 op_attr;
+#define ISCSI_LOGIN_REQ_HDR_LITTLE_ENDIAN_NSG (0x3<<0)
+#define ISCSI_LOGIN_REQ_HDR_LITTLE_ENDIAN_NSG_SHIFT 0
+#define ISCSI_LOGIN_REQ_HDR_LITTLE_ENDIAN_CSG (0x3<<2)
+#define ISCSI_LOGIN_REQ_HDR_LITTLE_ENDIAN_CSG_SHIFT 2
+#define ISCSI_LOGIN_REQ_HDR_LITTLE_ENDIAN_RSRV0 (0x3<<4)
+#define ISCSI_LOGIN_REQ_HDR_LITTLE_ENDIAN_RSRV0_SHIFT 4
+#define ISCSI_LOGIN_REQ_HDR_LITTLE_ENDIAN_CONTINUE_FLG (0x1<<6)
+#define ISCSI_LOGIN_REQ_HDR_LITTLE_ENDIAN_CONTINUE_FLG_SHIFT 6
+#define ISCSI_LOGIN_REQ_HDR_LITTLE_ENDIAN_TRANSIT (0x1<<7)
+#define ISCSI_LOGIN_REQ_HDR_LITTLE_ENDIAN_TRANSIT_SHIFT 7
+ u8 opcode;
+#endif
+ u32 data_fields;
+#define ISCSI_LOGIN_REQ_HDR_LITTLE_ENDIAN_DATA_SEGMENT_LENGTH (0xFFFFFF<<0)
+#define ISCSI_LOGIN_REQ_HDR_LITTLE_ENDIAN_DATA_SEGMENT_LENGTH_SHIFT 0
+#define ISCSI_LOGIN_REQ_HDR_LITTLE_ENDIAN_TOTAL_AHS_LENGTH (0xFF<<24)
+#define ISCSI_LOGIN_REQ_HDR_LITTLE_ENDIAN_TOTAL_AHS_LENGTH_SHIFT 24
+ u32 isid_lo;
+#if defined(__BIG_ENDIAN)
+ u16 isid_hi;
+ u16 tsih;
+#elif defined(__LITTLE_ENDIAN)
+ u16 tsih;
+ u16 isid_hi;
+#endif
+ u32 itt;
+#if defined(__BIG_ENDIAN)
+ u16 cid;
+ u16 rsrv1;
+#elif defined(__LITTLE_ENDIAN)
+ u16 rsrv1;
+ u16 cid;
+#endif
+ u32 cmd_sn;
+ u32 exp_stat_sn;
+ u32 rsrv2[4];
};
/*
- * FCoE KCQ CQE
+ * PDU header of an iSCSI logout request
*/
-struct fcoe_kcqe {
- u32 fcoe_conn_id;
- u32 completion_status;
- u32 fcoe_conn_context_id;
- union fcoe_kcqe_params params;
+struct iscsi_logout_req_hdr_little_endian {
#if defined(__BIG_ENDIAN)
- u8 flags;
-#define FCOE_KCQE_RESERVED0 (0x7<<0)
-#define FCOE_KCQE_RESERVED0_SHIFT 0
-#define FCOE_KCQE_RAMROD_COMPLETION (0x1<<3)
-#define FCOE_KCQE_RAMROD_COMPLETION_SHIFT 3
-#define FCOE_KCQE_LAYER_CODE (0x7<<4)
-#define FCOE_KCQE_LAYER_CODE_SHIFT 4
-#define FCOE_KCQE_LINKED_WITH_NEXT (0x1<<7)
-#define FCOE_KCQE_LINKED_WITH_NEXT_SHIFT 7
- u8 op_code;
- u16 qe_self_seq;
+ u8 opcode;
+ u8 op_attr;
+#define ISCSI_LOGOUT_REQ_HDR_LITTLE_ENDIAN_REASON_CODE (0x7F<<0)
+#define ISCSI_LOGOUT_REQ_HDR_LITTLE_ENDIAN_REASON_CODE_SHIFT 0
+#define ISCSI_LOGOUT_REQ_HDR_LITTLE_ENDIAN_RSRV1_1 (0x1<<7)
+#define ISCSI_LOGOUT_REQ_HDR_LITTLE_ENDIAN_RSRV1_1_SHIFT 7
+ u16 rsrv0;
#elif defined(__LITTLE_ENDIAN)
- u16 qe_self_seq;
- u8 op_code;
- u8 flags;
-#define FCOE_KCQE_RESERVED0 (0x7<<0)
-#define FCOE_KCQE_RESERVED0_SHIFT 0
-#define FCOE_KCQE_RAMROD_COMPLETION (0x1<<3)
-#define FCOE_KCQE_RAMROD_COMPLETION_SHIFT 3
-#define FCOE_KCQE_LAYER_CODE (0x7<<4)
-#define FCOE_KCQE_LAYER_CODE_SHIFT 4
-#define FCOE_KCQE_LINKED_WITH_NEXT (0x1<<7)
-#define FCOE_KCQE_LINKED_WITH_NEXT_SHIFT 7
+ u16 rsrv0;
+ u8 op_attr;
+#define ISCSI_LOGOUT_REQ_HDR_LITTLE_ENDIAN_REASON_CODE (0x7F<<0)
+#define ISCSI_LOGOUT_REQ_HDR_LITTLE_ENDIAN_REASON_CODE_SHIFT 0
+#define ISCSI_LOGOUT_REQ_HDR_LITTLE_ENDIAN_RSRV1_1 (0x1<<7)
+#define ISCSI_LOGOUT_REQ_HDR_LITTLE_ENDIAN_RSRV1_1_SHIFT 7
+ u8 opcode;
#endif
+ u32 data_fields;
+#define ISCSI_LOGOUT_REQ_HDR_LITTLE_ENDIAN_DATA_SEGMENT_LENGTH (0xFFFFFF<<0)
+#define ISCSI_LOGOUT_REQ_HDR_LITTLE_ENDIAN_DATA_SEGMENT_LENGTH_SHIFT 0
+#define ISCSI_LOGOUT_REQ_HDR_LITTLE_ENDIAN_TOTAL_AHS_LENGTH (0xFF<<24)
+#define ISCSI_LOGOUT_REQ_HDR_LITTLE_ENDIAN_TOTAL_AHS_LENGTH_SHIFT 24
+ u32 rsrv2[2];
+ u32 itt;
+#if defined(__BIG_ENDIAN)
+ u16 cid;
+ u16 rsrv1;
+#elif defined(__LITTLE_ENDIAN)
+ u16 rsrv1;
+ u16 cid;
+#endif
+ u32 cmd_sn;
+ u32 exp_stat_sn;
+ u32 rsrv3[4];
};
/*
- * FCoE KWQE header
+ * PDU header of an iSCSI TMF request
*/
-struct fcoe_kwqe_header {
+struct iscsi_tmf_req_hdr_little_endian {
#if defined(__BIG_ENDIAN)
- u8 flags;
-#define FCOE_KWQE_HEADER_RESERVED0 (0xF<<0)
-#define FCOE_KWQE_HEADER_RESERVED0_SHIFT 0
-#define FCOE_KWQE_HEADER_LAYER_CODE (0x7<<4)
-#define FCOE_KWQE_HEADER_LAYER_CODE_SHIFT 4
-#define FCOE_KWQE_HEADER_RESERVED1 (0x1<<7)
-#define FCOE_KWQE_HEADER_RESERVED1_SHIFT 7
- u8 op_code;
+ u8 opcode;
+ u8 op_attr;
+#define ISCSI_TMF_REQ_HDR_LITTLE_ENDIAN_FUNCTION (0x7F<<0)
+#define ISCSI_TMF_REQ_HDR_LITTLE_ENDIAN_FUNCTION_SHIFT 0
+#define ISCSI_TMF_REQ_HDR_LITTLE_ENDIAN_RSRV1_1 (0x1<<7)
+#define ISCSI_TMF_REQ_HDR_LITTLE_ENDIAN_RSRV1_1_SHIFT 7
+ u16 rsrv0;
#elif defined(__LITTLE_ENDIAN)
- u8 op_code;
- u8 flags;
-#define FCOE_KWQE_HEADER_RESERVED0 (0xF<<0)
-#define FCOE_KWQE_HEADER_RESERVED0_SHIFT 0
-#define FCOE_KWQE_HEADER_LAYER_CODE (0x7<<4)
-#define FCOE_KWQE_HEADER_LAYER_CODE_SHIFT 4
-#define FCOE_KWQE_HEADER_RESERVED1 (0x1<<7)
-#define FCOE_KWQE_HEADER_RESERVED1_SHIFT 7
+ u16 rsrv0;
+ u8 op_attr;
+#define ISCSI_TMF_REQ_HDR_LITTLE_ENDIAN_FUNCTION (0x7F<<0)
+#define ISCSI_TMF_REQ_HDR_LITTLE_ENDIAN_FUNCTION_SHIFT 0
+#define ISCSI_TMF_REQ_HDR_LITTLE_ENDIAN_RSRV1_1 (0x1<<7)
+#define ISCSI_TMF_REQ_HDR_LITTLE_ENDIAN_RSRV1_1_SHIFT 7
+ u8 opcode;
#endif
+ u32 data_fields;
+#define ISCSI_TMF_REQ_HDR_LITTLE_ENDIAN_DATA_SEGMENT_LENGTH (0xFFFFFF<<0)
+#define ISCSI_TMF_REQ_HDR_LITTLE_ENDIAN_DATA_SEGMENT_LENGTH_SHIFT 0
+#define ISCSI_TMF_REQ_HDR_LITTLE_ENDIAN_TOTAL_AHS_LENGTH (0xFF<<24)
+#define ISCSI_TMF_REQ_HDR_LITTLE_ENDIAN_TOTAL_AHS_LENGTH_SHIFT 24
+ struct regpair lun;
+ u32 itt;
+ u32 referenced_task_tag;
+ u32 cmd_sn;
+ u32 exp_stat_sn;
+ u32 ref_cmd_sn;
+ u32 exp_data_sn;
+ u32 rsrv2[2];
};
/*
- * FCoE firmware init request 1
+ * PDU header of an iSCSI Text request
*/
-struct fcoe_kwqe_init1 {
+struct iscsi_text_req_hdr_little_endian {
#if defined(__BIG_ENDIAN)
- struct fcoe_kwqe_header hdr;
- u16 num_tasks;
+ u8 opcode;
+ u8 op_attr;
+#define ISCSI_TEXT_REQ_HDR_LITTLE_ENDIAN_RSRV1 (0x3F<<0)
+#define ISCSI_TEXT_REQ_HDR_LITTLE_ENDIAN_RSRV1_SHIFT 0
+#define ISCSI_TEXT_REQ_HDR_LITTLE_ENDIAN_CONTINUE_FLG (0x1<<6)
+#define ISCSI_TEXT_REQ_HDR_LITTLE_ENDIAN_CONTINUE_FLG_SHIFT 6
+#define ISCSI_TEXT_REQ_HDR_LITTLE_ENDIAN_FINAL (0x1<<7)
+#define ISCSI_TEXT_REQ_HDR_LITTLE_ENDIAN_FINAL_SHIFT 7
+ u16 rsrv0;
#elif defined(__LITTLE_ENDIAN)
- u16 num_tasks;
- struct fcoe_kwqe_header hdr;
+ u16 rsrv0;
+ u8 op_attr;
+#define ISCSI_TEXT_REQ_HDR_LITTLE_ENDIAN_RSRV1 (0x3F<<0)
+#define ISCSI_TEXT_REQ_HDR_LITTLE_ENDIAN_RSRV1_SHIFT 0
+#define ISCSI_TEXT_REQ_HDR_LITTLE_ENDIAN_CONTINUE_FLG (0x1<<6)
+#define ISCSI_TEXT_REQ_HDR_LITTLE_ENDIAN_CONTINUE_FLG_SHIFT 6
+#define ISCSI_TEXT_REQ_HDR_LITTLE_ENDIAN_FINAL (0x1<<7)
+#define ISCSI_TEXT_REQ_HDR_LITTLE_ENDIAN_FINAL_SHIFT 7
+ u8 opcode;
#endif
- u32 task_list_pbl_addr_lo;
- u32 task_list_pbl_addr_hi;
- u32 dummy_buffer_addr_lo;
- u32 dummy_buffer_addr_hi;
-#if defined(__BIG_ENDIAN)
- u16 rq_num_wqes;
- u16 sq_num_wqes;
-#elif defined(__LITTLE_ENDIAN)
- u16 sq_num_wqes;
- u16 rq_num_wqes;
-#endif
-#if defined(__BIG_ENDIAN)
- u16 cq_num_wqes;
- u16 rq_buffer_log_size;
-#elif defined(__LITTLE_ENDIAN)
- u16 rq_buffer_log_size;
- u16 cq_num_wqes;
-#endif
-#if defined(__BIG_ENDIAN)
- u8 flags;
-#define FCOE_KWQE_INIT1_LOG_PAGE_SIZE (0xF<<0)
-#define FCOE_KWQE_INIT1_LOG_PAGE_SIZE_SHIFT 0
-#define FCOE_KWQE_INIT1_LOG_CACHED_PBES_PER_FUNC (0x7<<4)
-#define FCOE_KWQE_INIT1_LOG_CACHED_PBES_PER_FUNC_SHIFT 4
-#define FCOE_KWQE_INIT1_RESERVED1 (0x1<<7)
-#define FCOE_KWQE_INIT1_RESERVED1_SHIFT 7
- u8 num_sessions_log;
- u16 mtu;
-#elif defined(__LITTLE_ENDIAN)
- u16 mtu;
- u8 num_sessions_log;
- u8 flags;
-#define FCOE_KWQE_INIT1_LOG_PAGE_SIZE (0xF<<0)
-#define FCOE_KWQE_INIT1_LOG_PAGE_SIZE_SHIFT 0
-#define FCOE_KWQE_INIT1_LOG_CACHED_PBES_PER_FUNC (0x7<<4)
-#define FCOE_KWQE_INIT1_LOG_CACHED_PBES_PER_FUNC_SHIFT 4
-#define FCOE_KWQE_INIT1_RESERVED1 (0x1<<7)
-#define FCOE_KWQE_INIT1_RESERVED1_SHIFT 7
-#endif
+ u32 data_fields;
+#define ISCSI_TEXT_REQ_HDR_LITTLE_ENDIAN_DATA_SEGMENT_LENGTH (0xFFFFFF<<0)
+#define ISCSI_TEXT_REQ_HDR_LITTLE_ENDIAN_DATA_SEGMENT_LENGTH_SHIFT 0
+#define ISCSI_TEXT_REQ_HDR_LITTLE_ENDIAN_TOTAL_AHS_LENGTH (0xFF<<24)
+#define ISCSI_TEXT_REQ_HDR_LITTLE_ENDIAN_TOTAL_AHS_LENGTH_SHIFT 24
+ struct regpair lun;
+ u32 itt;
+ u32 ttt;
+ u32 cmd_sn;
+ u32 exp_stat_sn;
+ u32 rsrv3[4];
};
/*
- * FCoE firmware init request 2
+ * PDU header of an iSCSI Nop-Out
*/
-struct fcoe_kwqe_init2 {
+struct iscsi_nop_out_hdr_little_endian {
#if defined(__BIG_ENDIAN)
- struct fcoe_kwqe_header hdr;
- u16 reserved0;
+ u8 opcode;
+ u8 op_attr;
+#define ISCSI_NOP_OUT_HDR_LITTLE_ENDIAN_RSRV1 (0x7F<<0)
+#define ISCSI_NOP_OUT_HDR_LITTLE_ENDIAN_RSRV1_SHIFT 0
+#define ISCSI_NOP_OUT_HDR_LITTLE_ENDIAN_RSRV2_1 (0x1<<7)
+#define ISCSI_NOP_OUT_HDR_LITTLE_ENDIAN_RSRV2_1_SHIFT 7
+ u16 rsrv0;
#elif defined(__LITTLE_ENDIAN)
- u16 reserved0;
- struct fcoe_kwqe_header hdr;
+ u16 rsrv0;
+ u8 op_attr;
+#define ISCSI_NOP_OUT_HDR_LITTLE_ENDIAN_RSRV1 (0x7F<<0)
+#define ISCSI_NOP_OUT_HDR_LITTLE_ENDIAN_RSRV1_SHIFT 0
+#define ISCSI_NOP_OUT_HDR_LITTLE_ENDIAN_RSRV2_1 (0x1<<7)
+#define ISCSI_NOP_OUT_HDR_LITTLE_ENDIAN_RSRV2_1_SHIFT 7
+ u8 opcode;
#endif
- u32 hash_tbl_pbl_addr_lo;
- u32 hash_tbl_pbl_addr_hi;
- u32 t2_hash_tbl_addr_lo;
- u32 t2_hash_tbl_addr_hi;
- u32 t2_ptr_hash_tbl_addr_lo;
- u32 t2_ptr_hash_tbl_addr_hi;
- u32 free_list_count;
+ u32 data_fields;
+#define ISCSI_NOP_OUT_HDR_LITTLE_ENDIAN_DATA_SEGMENT_LENGTH (0xFFFFFF<<0)
+#define ISCSI_NOP_OUT_HDR_LITTLE_ENDIAN_DATA_SEGMENT_LENGTH_SHIFT 0
+#define ISCSI_NOP_OUT_HDR_LITTLE_ENDIAN_TOTAL_AHS_LENGTH (0xFF<<24)
+#define ISCSI_NOP_OUT_HDR_LITTLE_ENDIAN_TOTAL_AHS_LENGTH_SHIFT 24
+ struct regpair lun;
+ u32 itt;
+ u32 ttt;
+ u32 cmd_sn;
+ u32 exp_stat_sn;
+ u32 rsrv3[4];
};
/*
- * FCoE firmware init request 3
+ * iscsi pdu headers in little endian form.
*/
-struct fcoe_kwqe_init3 {
-#if defined(__BIG_ENDIAN)
- struct fcoe_kwqe_header hdr;
- u16 reserved0;
-#elif defined(__LITTLE_ENDIAN)
- u16 reserved0;
- struct fcoe_kwqe_header hdr;
-#endif
- u32 error_bit_map_lo;
- u32 error_bit_map_hi;
-#if defined(__BIG_ENDIAN)
- u8 reserved21[3];
- u8 cached_session_enable;
-#elif defined(__LITTLE_ENDIAN)
- u8 cached_session_enable;
- u8 reserved21[3];
-#endif
- u32 reserved2[4];
+union iscsi_pdu_headers_little_endian {
+ u32 fullHeaderSize[12];
+ struct iscsi_cmd_pdu_hdr_little_endian command_pdu_hdr;
+ struct iscsi_data_pdu_hdr_little_endian data_out_pdu_hdr;
+ struct iscsi_login_req_hdr_little_endian login_req_pdu_hdr;
+ struct iscsi_logout_req_hdr_little_endian logout_req_pdu_hdr;
+ struct iscsi_tmf_req_hdr_little_endian tmf_req_pdu_hdr;
+ struct iscsi_text_req_hdr_little_endian text_req_pdu_hdr;
+ struct iscsi_nop_out_hdr_little_endian nop_out_pdu_hdr;
};
-/*
- * FCoE connection offload request 1
- */
-struct fcoe_kwqe_conn_offload1 {
-#if defined(__BIG_ENDIAN)
- struct fcoe_kwqe_header hdr;
- u16 fcoe_conn_id;
-#elif defined(__LITTLE_ENDIAN)
- u16 fcoe_conn_id;
- struct fcoe_kwqe_header hdr;
-#endif
- u32 sq_addr_lo;
- u32 sq_addr_hi;
- u32 rq_pbl_addr_lo;
- u32 rq_pbl_addr_hi;
- u32 rq_first_pbe_addr_lo;
- u32 rq_first_pbe_addr_hi;
-#if defined(__BIG_ENDIAN)
- u16 reserved0;
- u16 rq_prod;
-#elif defined(__LITTLE_ENDIAN)
- u16 rq_prod;
- u16 reserved0;
-#endif
-};
-
-/*
- * FCoE connection offload request 2
- */
-struct fcoe_kwqe_conn_offload2 {
-#if defined(__BIG_ENDIAN)
- struct fcoe_kwqe_header hdr;
- u16 tx_max_fc_pay_len;
-#elif defined(__LITTLE_ENDIAN)
- u16 tx_max_fc_pay_len;
- struct fcoe_kwqe_header hdr;
-#endif
- u32 cq_addr_lo;
- u32 cq_addr_hi;
- u32 xferq_addr_lo;
- u32 xferq_addr_hi;
- u32 conn_db_addr_lo;
- u32 conn_db_addr_hi;
- u32 reserved1;
-};
-
-/*
- * FCoE connection offload request 3
- */
-struct fcoe_kwqe_conn_offload3 {
-#if defined(__BIG_ENDIAN)
- struct fcoe_kwqe_header hdr;
- u16 vlan_tag;
-#define FCOE_KWQE_CONN_OFFLOAD3_VLAN_ID (0xFFF<<0)
-#define FCOE_KWQE_CONN_OFFLOAD3_VLAN_ID_SHIFT 0
-#define FCOE_KWQE_CONN_OFFLOAD3_CFI (0x1<<12)
-#define FCOE_KWQE_CONN_OFFLOAD3_CFI_SHIFT 12
-#define FCOE_KWQE_CONN_OFFLOAD3_PRIORITY (0x7<<13)
-#define FCOE_KWQE_CONN_OFFLOAD3_PRIORITY_SHIFT 13
-#elif defined(__LITTLE_ENDIAN)
- u16 vlan_tag;
-#define FCOE_KWQE_CONN_OFFLOAD3_VLAN_ID (0xFFF<<0)
-#define FCOE_KWQE_CONN_OFFLOAD3_VLAN_ID_SHIFT 0
-#define FCOE_KWQE_CONN_OFFLOAD3_CFI (0x1<<12)
-#define FCOE_KWQE_CONN_OFFLOAD3_CFI_SHIFT 12
-#define FCOE_KWQE_CONN_OFFLOAD3_PRIORITY (0x7<<13)
-#define FCOE_KWQE_CONN_OFFLOAD3_PRIORITY_SHIFT 13
- struct fcoe_kwqe_header hdr;
-#endif
-#if defined(__BIG_ENDIAN)
- u8 tx_max_conc_seqs_c3;
- u8 s_id[3];
-#elif defined(__LITTLE_ENDIAN)
- u8 s_id[3];
- u8 tx_max_conc_seqs_c3;
-#endif
-#if defined(__BIG_ENDIAN)
- u8 flags;
-#define FCOE_KWQE_CONN_OFFLOAD3_B_MUL_N_PORT_IDS (0x1<<0)
-#define FCOE_KWQE_CONN_OFFLOAD3_B_MUL_N_PORT_IDS_SHIFT 0
-#define FCOE_KWQE_CONN_OFFLOAD3_B_E_D_TOV_RES (0x1<<1)
-#define FCOE_KWQE_CONN_OFFLOAD3_B_E_D_TOV_RES_SHIFT 1
-#define FCOE_KWQE_CONN_OFFLOAD3_B_CONT_INCR_SEQ_CNT (0x1<<2)
-#define FCOE_KWQE_CONN_OFFLOAD3_B_CONT_INCR_SEQ_CNT_SHIFT 2
-#define FCOE_KWQE_CONN_OFFLOAD3_B_CONF_REQ (0x1<<3)
-#define FCOE_KWQE_CONN_OFFLOAD3_B_CONF_REQ_SHIFT 3
-#define FCOE_KWQE_CONN_OFFLOAD3_B_REC_VALID (0x1<<4)
-#define FCOE_KWQE_CONN_OFFLOAD3_B_REC_VALID_SHIFT 4
-#define FCOE_KWQE_CONN_OFFLOAD3_B_C2_VALID (0x1<<5)
-#define FCOE_KWQE_CONN_OFFLOAD3_B_C2_VALID_SHIFT 5
-#define FCOE_KWQE_CONN_OFFLOAD3_B_ACK_0 (0x1<<6)
-#define FCOE_KWQE_CONN_OFFLOAD3_B_ACK_0_SHIFT 6
-#define FCOE_KWQE_CONN_OFFLOAD3_B_VLAN_FLAG (0x1<<7)
-#define FCOE_KWQE_CONN_OFFLOAD3_B_VLAN_FLAG_SHIFT 7
- u8 d_id[3];
-#elif defined(__LITTLE_ENDIAN)
- u8 d_id[3];
- u8 flags;
-#define FCOE_KWQE_CONN_OFFLOAD3_B_MUL_N_PORT_IDS (0x1<<0)
-#define FCOE_KWQE_CONN_OFFLOAD3_B_MUL_N_PORT_IDS_SHIFT 0
-#define FCOE_KWQE_CONN_OFFLOAD3_B_E_D_TOV_RES (0x1<<1)
-#define FCOE_KWQE_CONN_OFFLOAD3_B_E_D_TOV_RES_SHIFT 1
-#define FCOE_KWQE_CONN_OFFLOAD3_B_CONT_INCR_SEQ_CNT (0x1<<2)
-#define FCOE_KWQE_CONN_OFFLOAD3_B_CONT_INCR_SEQ_CNT_SHIFT 2
-#define FCOE_KWQE_CONN_OFFLOAD3_B_CONF_REQ (0x1<<3)
-#define FCOE_KWQE_CONN_OFFLOAD3_B_CONF_REQ_SHIFT 3
-#define FCOE_KWQE_CONN_OFFLOAD3_B_REC_VALID (0x1<<4)
-#define FCOE_KWQE_CONN_OFFLOAD3_B_REC_VALID_SHIFT 4
-#define FCOE_KWQE_CONN_OFFLOAD3_B_C2_VALID (0x1<<5)
-#define FCOE_KWQE_CONN_OFFLOAD3_B_C2_VALID_SHIFT 5
-#define FCOE_KWQE_CONN_OFFLOAD3_B_ACK_0 (0x1<<6)
-#define FCOE_KWQE_CONN_OFFLOAD3_B_ACK_0_SHIFT 6
-#define FCOE_KWQE_CONN_OFFLOAD3_B_VLAN_FLAG (0x1<<7)
-#define FCOE_KWQE_CONN_OFFLOAD3_B_VLAN_FLAG_SHIFT 7
-#endif
- u32 reserved;
- u32 confq_first_pbe_addr_lo;
- u32 confq_first_pbe_addr_hi;
-#if defined(__BIG_ENDIAN)
- u16 rx_max_fc_pay_len;
- u16 tx_total_conc_seqs;
-#elif defined(__LITTLE_ENDIAN)
- u16 tx_total_conc_seqs;
- u16 rx_max_fc_pay_len;
-#endif
-#if defined(__BIG_ENDIAN)
- u8 rx_open_seqs_exch_c3;
- u8 rx_max_conc_seqs_c3;
- u16 rx_total_conc_seqs;
-#elif defined(__LITTLE_ENDIAN)
- u16 rx_total_conc_seqs;
- u8 rx_max_conc_seqs_c3;
- u8 rx_open_seqs_exch_c3;
-#endif
-};
-
-/*
- * FCoE connection offload request 4
- */
-struct fcoe_kwqe_conn_offload4 {
-#if defined(__BIG_ENDIAN)
- struct fcoe_kwqe_header hdr;
- u8 reserved2;
- u8 e_d_tov_timer_val;
-#elif defined(__LITTLE_ENDIAN)
- u8 e_d_tov_timer_val;
- u8 reserved2;
- struct fcoe_kwqe_header hdr;
-#endif
- u8 src_mac_addr_lo32[4];
-#if defined(__BIG_ENDIAN)
- u8 dst_mac_addr_hi16[2];
- u8 src_mac_addr_hi16[2];
-#elif defined(__LITTLE_ENDIAN)
- u8 src_mac_addr_hi16[2];
- u8 dst_mac_addr_hi16[2];
-#endif
- u8 dst_mac_addr_lo32[4];
- u32 lcq_addr_lo;
- u32 lcq_addr_hi;
- u32 confq_pbl_base_addr_lo;
- u32 confq_pbl_base_addr_hi;
-};
-
-/*
- * FCoE connection enable request
- */
-struct fcoe_kwqe_conn_enable_disable {
-#if defined(__BIG_ENDIAN)
- struct fcoe_kwqe_header hdr;
- u16 reserved0;
-#elif defined(__LITTLE_ENDIAN)
- u16 reserved0;
- struct fcoe_kwqe_header hdr;
-#endif
- u8 src_mac_addr_lo32[4];
-#if defined(__BIG_ENDIAN)
- u16 vlan_tag;
-#define FCOE_KWQE_CONN_ENABLE_DISABLE_VLAN_ID (0xFFF<<0)
-#define FCOE_KWQE_CONN_ENABLE_DISABLE_VLAN_ID_SHIFT 0
-#define FCOE_KWQE_CONN_ENABLE_DISABLE_CFI (0x1<<12)
-#define FCOE_KWQE_CONN_ENABLE_DISABLE_CFI_SHIFT 12
-#define FCOE_KWQE_CONN_ENABLE_DISABLE_PRIORITY (0x7<<13)
-#define FCOE_KWQE_CONN_ENABLE_DISABLE_PRIORITY_SHIFT 13
- u8 src_mac_addr_hi16[2];
-#elif defined(__LITTLE_ENDIAN)
- u8 src_mac_addr_hi16[2];
- u16 vlan_tag;
-#define FCOE_KWQE_CONN_ENABLE_DISABLE_VLAN_ID (0xFFF<<0)
-#define FCOE_KWQE_CONN_ENABLE_DISABLE_VLAN_ID_SHIFT 0
-#define FCOE_KWQE_CONN_ENABLE_DISABLE_CFI (0x1<<12)
-#define FCOE_KWQE_CONN_ENABLE_DISABLE_CFI_SHIFT 12
-#define FCOE_KWQE_CONN_ENABLE_DISABLE_PRIORITY (0x7<<13)
-#define FCOE_KWQE_CONN_ENABLE_DISABLE_PRIORITY_SHIFT 13
-#endif
- u8 dst_mac_addr_lo32[4];
+struct iscsi_hq_bd {
+ union iscsi_pdu_headers_little_endian pdu_header;
#if defined(__BIG_ENDIAN)
u16 reserved1;
- u8 dst_mac_addr_hi16[2];
+ u16 lcl_cmp_flg;
#elif defined(__LITTLE_ENDIAN)
- u8 dst_mac_addr_hi16[2];
+ u16 lcl_cmp_flg;
u16 reserved1;
#endif
+ u32 sgl_base_lo;
+ u32 sgl_base_hi;
#if defined(__BIG_ENDIAN)
- u8 vlan_flag;
- u8 s_id[3];
+ u8 sgl_size;
+ u8 sge_index;
+ u16 sge_offset;
#elif defined(__LITTLE_ENDIAN)
- u8 s_id[3];
- u8 vlan_flag;
-#endif
-#if defined(__BIG_ENDIAN)
- u8 reserved3;
- u8 d_id[3];
-#elif defined(__LITTLE_ENDIAN)
- u8 d_id[3];
- u8 reserved3;
-#endif
- u32 context_id;
- u32 conn_id;
- u32 reserved4;
-};
-
-/*
- * FCoE connection destroy request
- */
-struct fcoe_kwqe_conn_destroy {
-#if defined(__BIG_ENDIAN)
- struct fcoe_kwqe_header hdr;
- u16 reserved0;
-#elif defined(__LITTLE_ENDIAN)
- u16 reserved0;
- struct fcoe_kwqe_header hdr;
-#endif
- u32 context_id;
- u32 conn_id;
- u32 reserved1[5];
-};
-
-/*
- * FCoe destroy request
- */
-struct fcoe_kwqe_destroy {
-#if defined(__BIG_ENDIAN)
- struct fcoe_kwqe_header hdr;
- u16 reserved0;
-#elif defined(__LITTLE_ENDIAN)
- u16 reserved0;
- struct fcoe_kwqe_header hdr;
-#endif
- u32 reserved1[7];
-};
-
-/*
- * FCoe statistics request
- */
-struct fcoe_kwqe_stat {
-#if defined(__BIG_ENDIAN)
- struct fcoe_kwqe_header hdr;
- u16 reserved0;
-#elif defined(__LITTLE_ENDIAN)
- u16 reserved0;
- struct fcoe_kwqe_header hdr;
-#endif
- u32 stat_params_addr_lo;
- u32 stat_params_addr_hi;
- u32 reserved1[5];
-};
-
-/*
- * FCoE KWQ WQE
- */
-union fcoe_kwqe {
- struct fcoe_kwqe_init1 init1;
- struct fcoe_kwqe_init2 init2;
- struct fcoe_kwqe_init3 init3;
- struct fcoe_kwqe_conn_offload1 conn_offload1;
- struct fcoe_kwqe_conn_offload2 conn_offload2;
- struct fcoe_kwqe_conn_offload3 conn_offload3;
- struct fcoe_kwqe_conn_offload4 conn_offload4;
- struct fcoe_kwqe_conn_enable_disable conn_enable_disable;
- struct fcoe_kwqe_conn_destroy conn_destroy;
- struct fcoe_kwqe_destroy destroy;
- struct fcoe_kwqe_stat statistics;
-};
-
-struct fcoe_task_ctx_entry {
- struct fcoe_task_ctx_entry_tx_only tx_wr_only;
- struct fcoe_task_ctx_entry_txwr_rxrd tx_wr_rx_rd;
- struct fcoe_task_ctx_entry_tx_rx_cmn cmn;
- struct fcoe_task_ctx_entry_rxwr_txrd rx_wr_tx_rd;
- struct fcoe_task_ctx_entry_rx_only rx_wr_only;
- u32 reserved[4];
-};
-
-/*
- * FCoE connection enable\disable params passed by driver to FW in FCoE enable ramrod
- */
-struct fcoe_conn_enable_disable_ramrod_params {
- struct fcoe_kwqe_conn_enable_disable enable_disable_kwqe;
-};
-
-
-/*
- * FCoE connection offload params passed by driver to FW in FCoE offload ramrod
- */
-struct fcoe_conn_offload_ramrod_params {
- struct fcoe_kwqe_conn_offload1 offload_kwqe1;
- struct fcoe_kwqe_conn_offload2 offload_kwqe2;
- struct fcoe_kwqe_conn_offload3 offload_kwqe3;
- struct fcoe_kwqe_conn_offload4 offload_kwqe4;
-};
-
-/*
- * FCoE init params passed by driver to FW in FCoE init ramrod
- */
-struct fcoe_init_ramrod_params {
- struct fcoe_kwqe_init1 init_kwqe1;
- struct fcoe_kwqe_init2 init_kwqe2;
- struct fcoe_kwqe_init3 init_kwqe3;
- struct regpair eq_addr;
- struct regpair eq_next_page_addr;
-#if defined(__BIG_ENDIAN)
- u16 sb_num;
- u16 eq_prod;
-#elif defined(__LITTLE_ENDIAN)
- u16 eq_prod;
- u16 sb_num;
-#endif
-#if defined(__BIG_ENDIAN)
- u16 reserved1;
- u8 reserved0;
- u8 sb_id;
-#elif defined(__LITTLE_ENDIAN)
- u8 sb_id;
- u8 reserved0;
- u16 reserved1;
+ u16 sge_offset;
+ u8 sge_index;
+ u8 sgl_size;
#endif
};
/*
- * FCoE statistics params buffer passed by driver to FW in FCoE statistics ramrod
+ * CQE data for L2 OOO connection $$KEEP_ENDIANNESS$$
*/
-struct fcoe_stat_ramrod_params {
- struct fcoe_kwqe_stat stat_kwqe;
+struct iscsi_l2_ooo_data {
+ __le32 iscsi_cid;
+ u8 drop_isle;
+ u8 drop_size;
+ u8 ooo_opcode;
+ u8 ooo_isle;
+ u8 reserved[8];
};
-/*
- * FCoE 16-bits vlan structure
- */
-struct fcoe_vlan_fields {
- u16 fields;
-#define FCOE_VLAN_FIELDS_VID (0xFFF<<0)
-#define FCOE_VLAN_FIELDS_VID_SHIFT 0
-#define FCOE_VLAN_FIELDS_CLI (0x1<<12)
-#define FCOE_VLAN_FIELDS_CLI_SHIFT 12
-#define FCOE_VLAN_FIELDS_PRI (0x7<<13)
-#define FCOE_VLAN_FIELDS_PRI_SHIFT 13
+
+
+
+
+struct iscsi_task_context_entry_xuc_c_write_only {
+ u32 total_data_acked;
};
-
-/*
- * FCoE 16-bits vlan union
- */
-union fcoe_vlan_field_union {
- struct fcoe_vlan_fields fields;
- u16 val;
+struct iscsi_task_context_r2t_table_entry {
+ u32 ttt;
+ u32 desired_data_len;
};
-/*
- * Parameters used for Class 2 verifications
- */
-struct ustorm_fcoe_c2_params {
+struct iscsi_task_context_entry_xuc_u_write_only {
+ u32 exp_r2t_sn;
+ struct iscsi_task_context_r2t_table_entry r2t_table[4];
#if defined(__BIG_ENDIAN)
- u16 e2e_credit;
- u16 con_seq;
+ u16 data_in_count;
+ u8 cq_id;
+ u8 valid_1b;
#elif defined(__LITTLE_ENDIAN)
- u16 con_seq;
- u16 e2e_credit;
+ u8 valid_1b;
+ u8 cq_id;
+ u16 data_in_count;
#endif
-#if defined(__BIG_ENDIAN)
- u16 ackq_prod;
- u16 open_seq_per_exch;
-#elif defined(__LITTLE_ENDIAN)
- u16 open_seq_per_exch;
- u16 ackq_prod;
-#endif
- struct regpair ackq_pbl_base;
- struct regpair ackq_cur_seg;
};
-/*
- * Parameters used for Class 2 verifications
- */
-struct xstorm_fcoe_c2_params {
-#if defined(__BIG_ENDIAN)
- u16 reserved0;
- u8 ackq_x_prod;
- u8 max_conc_seqs_c2;
-#elif defined(__LITTLE_ENDIAN)
- u8 max_conc_seqs_c2;
- u8 ackq_x_prod;
- u16 reserved0;
-#endif
- struct regpair ackq_pbl_base;
- struct regpair ackq_cur_seg;
+struct iscsi_task_context_entry_xuc {
+ struct iscsi_task_context_entry_xuc_c_write_only write_c;
+ u32 exp_data_transfer_len;
+ struct iscsi_task_context_entry_xuc_x_write_only write_x;
+ u32 lun_lo;
+ struct iscsi_task_context_entry_xuc_xu_write_both write_xu;
+ u32 lun_hi;
+ struct iscsi_task_context_entry_xuc_u_write_only write_u;
};
-/*
- * Buffer per connection, used in Tstorm
- */
-struct iscsi_conn_buf {
- struct regpair reserved[8];
+struct iscsi_task_context_entry_u {
+ u32 exp_r2t_buff_offset;
+ u32 rem_rcv_len;
+ u32 exp_data_sn;
};
+struct iscsi_task_context_entry {
+ struct iscsi_task_context_entry_x tce_x;
+#if defined(__BIG_ENDIAN)
+ u16 data_out_count;
+ u16 rsrv0;
+#elif defined(__LITTLE_ENDIAN)
+ u16 rsrv0;
+ u16 data_out_count;
+#endif
+ struct iscsi_task_context_entry_xuc tce_xuc;
+ struct iscsi_task_context_entry_u tce_u;
+ u32 rsrv1[7];
+};
+
+
+
+
+
+
+
+
+struct iscsi_task_context_entry_xuc_x_init_only {
+ struct regpair lun;
+ u32 exp_data_transfer_len;
+};
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
* ipv6 structure
*/
@@ -4379,6 +5067,8 @@
u32 ip_addr_hi_hi;
};
+
+
/*
* l5cm- connection identification params
*/
@@ -4460,8 +5150,7 @@
* l5cm-tstorm connection buffer
*/
struct l5cm_tstorm_conn_buffer {
- u32 snd_buf;
- u32 rcv_buf;
+ u32 rsrv1[2];
#if defined(__BIG_ENDIAN)
u16 params;
#define L5CM_TSTORM_CONN_BUFFER_DELAYED_ACK_ENABLE (0x1<<0)
@@ -4493,6 +5182,72 @@
struct l5cm_tstorm_conn_buffer tstorm_conn_buffer;
};
+
+
+/*
+ * The l5cm opaque buffer passed in add new connection ramrod passive side
+ */
+struct l5cm_hash_input_string {
+ u32 __opaque1;
+#if defined(__BIG_ENDIAN)
+ u16 __opaque3;
+ u16 __opaque2;
+#elif defined(__LITTLE_ENDIAN)
+ u16 __opaque2;
+ u16 __opaque3;
+#endif
+ struct ip_v6_addr __opaque4;
+ struct ip_v6_addr __opaque5;
+ u32 __opaque6;
+ u32 __opaque7[5];
+};
+
+
+/*
+ * syn cookie component
+ */
+struct l5cm_syn_cookie_comp {
+ u32 __opaque;
+};
+
+/*
+ * data related to listeners of a TCP port
+ */
+struct l5cm_port_listener_data {
+ u8 params;
+#define L5CM_PORT_LISTENER_DATA_ENABLE (0x1<<0)
+#define L5CM_PORT_LISTENER_DATA_ENABLE_SHIFT 0
+#define L5CM_PORT_LISTENER_DATA_IP_INDEX (0xF<<1)
+#define L5CM_PORT_LISTENER_DATA_IP_INDEX_SHIFT 1
+#define L5CM_PORT_LISTENER_DATA_NET_FILTER (0x1<<5)
+#define L5CM_PORT_LISTENER_DATA_NET_FILTER_SHIFT 5
+#define L5CM_PORT_LISTENER_DATA_DEFFERED_MODE (0x1<<6)
+#define L5CM_PORT_LISTENER_DATA_DEFFERED_MODE_SHIFT 6
+#define L5CM_PORT_LISTENER_DATA_MPA_MODE (0x1<<7)
+#define L5CM_PORT_LISTENER_DATA_MPA_MODE_SHIFT 7
+};
+
+/*
+ * Opaque structure passed from U to X when final ack arrives
+ */
+struct l5cm_opaque_buf {
+ u32 __opaque1;
+ u32 __opaque2;
+ u32 __opaque3;
+ u32 __opaque4;
+ struct l5cm_syn_cookie_comp __opaque5;
+#if defined(__BIG_ENDIAN)
+ u16 rsrv2;
+ u8 rsrv;
+ struct l5cm_port_listener_data __opaque6;
+#elif defined(__LITTLE_ENDIAN)
+ struct l5cm_port_listener_data __opaque6;
+ u8 rsrv;
+ u16 rsrv2;
+#endif
+};
+
+
/*
* l5cm slow path element
*/
@@ -4501,6 +5256,109 @@
u32 rsrv;
};
+
+/*
+ * The final-ack union structure in PCS entry after final ack arrived
+ */
+struct l5cm_pcse_ack {
+ struct l5cm_xstorm_conn_buffer tx_socket_params;
+ struct l5cm_opaque_buf opaque_buf;
+ struct l5cm_tstorm_conn_buffer rx_socket_params;
+};
+
+
+/*
+ * The syn union structure in PCS entry after syn arrived
+ */
+struct l5cm_pcse_syn {
+ struct l5cm_opaque_buf opaque_buf;
+ u32 rsrv[12];
+};
+
+
+/*
+ * pcs entry data for passive connections
+ */
+struct l5cm_pcs_attributes {
+#if defined(__BIG_ENDIAN)
+ u16 pcs_id;
+ u8 status;
+ u8 flags;
+#define L5CM_PCS_ATTRIBUTES_NET_FILTER (0x1<<0)
+#define L5CM_PCS_ATTRIBUTES_NET_FILTER_SHIFT 0
+#define L5CM_PCS_ATTRIBUTES_CALCULATE_HASH (0x1<<1)
+#define L5CM_PCS_ATTRIBUTES_CALCULATE_HASH_SHIFT 1
+#define L5CM_PCS_ATTRIBUTES_COMPARE_HASH_RESULT (0x1<<2)
+#define L5CM_PCS_ATTRIBUTES_COMPARE_HASH_RESULT_SHIFT 2
+#define L5CM_PCS_ATTRIBUTES_QUERY_ULP_ACCEPT (0x1<<3)
+#define L5CM_PCS_ATTRIBUTES_QUERY_ULP_ACCEPT_SHIFT 3
+#define L5CM_PCS_ATTRIBUTES_FIND_DEST_MAC (0x1<<4)
+#define L5CM_PCS_ATTRIBUTES_FIND_DEST_MAC_SHIFT 4
+#define L5CM_PCS_ATTRIBUTES_L4_OFFLOAD (0x1<<5)
+#define L5CM_PCS_ATTRIBUTES_L4_OFFLOAD_SHIFT 5
+#define L5CM_PCS_ATTRIBUTES_FORWARD_PACKET (0x1<<6)
+#define L5CM_PCS_ATTRIBUTES_FORWARD_PACKET_SHIFT 6
+#define L5CM_PCS_ATTRIBUTES_RSRV (0x1<<7)
+#define L5CM_PCS_ATTRIBUTES_RSRV_SHIFT 7
+#elif defined(__LITTLE_ENDIAN)
+ u8 flags;
+#define L5CM_PCS_ATTRIBUTES_NET_FILTER (0x1<<0)
+#define L5CM_PCS_ATTRIBUTES_NET_FILTER_SHIFT 0
+#define L5CM_PCS_ATTRIBUTES_CALCULATE_HASH (0x1<<1)
+#define L5CM_PCS_ATTRIBUTES_CALCULATE_HASH_SHIFT 1
+#define L5CM_PCS_ATTRIBUTES_COMPARE_HASH_RESULT (0x1<<2)
+#define L5CM_PCS_ATTRIBUTES_COMPARE_HASH_RESULT_SHIFT 2
+#define L5CM_PCS_ATTRIBUTES_QUERY_ULP_ACCEPT (0x1<<3)
+#define L5CM_PCS_ATTRIBUTES_QUERY_ULP_ACCEPT_SHIFT 3
+#define L5CM_PCS_ATTRIBUTES_FIND_DEST_MAC (0x1<<4)
+#define L5CM_PCS_ATTRIBUTES_FIND_DEST_MAC_SHIFT 4
+#define L5CM_PCS_ATTRIBUTES_L4_OFFLOAD (0x1<<5)
+#define L5CM_PCS_ATTRIBUTES_L4_OFFLOAD_SHIFT 5
+#define L5CM_PCS_ATTRIBUTES_FORWARD_PACKET (0x1<<6)
+#define L5CM_PCS_ATTRIBUTES_FORWARD_PACKET_SHIFT 6
+#define L5CM_PCS_ATTRIBUTES_RSRV (0x1<<7)
+#define L5CM_PCS_ATTRIBUTES_RSRV_SHIFT 7
+ u8 status;
+ u16 pcs_id;
+#endif
+};
+
+
+union l5cm_seg_params {
+ struct l5cm_pcse_syn syn_seg_params;
+ struct l5cm_pcse_ack ack_seg_params;
+};
+
+/*
+ * pcs entry data for passive connections
+ */
+struct l5cm_pcs_hdr {
+ struct l5cm_hash_input_string hash_input_string;
+ struct l5cm_conn_addr_params conn_addr_buf;
+ u32 cid;
+ u32 hash_result;
+ union l5cm_seg_params seg_params;
+ struct l5cm_pcs_attributes att;
+#if defined(__BIG_ENDIAN)
+ u16 rsrv;
+ u16 rx_seg_size;
+#elif defined(__LITTLE_ENDIAN)
+ u16 rx_seg_size;
+ u16 rsrv;
+#endif
+};
+
+/*
+ * pcs entry for passive connections
+ */
+struct l5cm_pcs_entry {
+ struct l5cm_pcs_hdr hdr;
+ u8 rx_segment[1516];
+};
+
+
+
+
/*
* l5cm connection parameters
*/
@@ -4535,6 +5393,29 @@
union l5cm_specific_data data;
};
+
+
+
+/*
+ * Termination variables
+ */
+struct l5cm_term_vars {
+ u8 BitMap;
+#define L5CM_TERM_VARS_TCP_STATE (0xF<<0)
+#define L5CM_TERM_VARS_TCP_STATE_SHIFT 0
+#define L5CM_TERM_VARS_FIN_RECEIVED_SBIT (0x1<<4)
+#define L5CM_TERM_VARS_FIN_RECEIVED_SBIT_SHIFT 4
+#define L5CM_TERM_VARS_ACK_ON_FIN_RECEIVED_SBIT (0x1<<5)
+#define L5CM_TERM_VARS_ACK_ON_FIN_RECEIVED_SBIT_SHIFT 5
+#define L5CM_TERM_VARS_TERM_ON_CHIP (0x1<<6)
+#define L5CM_TERM_VARS_TERM_ON_CHIP_SHIFT 6
+#define L5CM_TERM_VARS_RSRV (0x1<<7)
+#define L5CM_TERM_VARS_RSRV_SHIFT 7
+};
+
+
+
+
/*
* Tstorm Tcp flags
*/
@@ -4550,6 +5431,7 @@
#define TSTORM_L5CM_TCP_FLAGS_RSRV1_SHIFT 14
};
+
/*
* Xstorm Tcp flags
*/
@@ -4565,4 +5447,38 @@
#define XSTORM_L5CM_TCP_FLAGS_RSRV_SHIFT 3
};
-#endif /* CNIC_DEFS_H */
+
+
+/*
+ * Out-of-order states
+ */
+enum tcp_ooo_event {
+ TCP_EVENT_ADD_PEN = 0,
+ TCP_EVENT_ADD_NEW_ISLE = 1,
+ TCP_EVENT_ADD_ISLE_RIGHT = 2,
+ TCP_EVENT_ADD_ISLE_LEFT = 3,
+ TCP_EVENT_JOIN = 4,
+ TCP_EVENT_NOP = 5,
+ MAX_TCP_OOO_EVENT
+};
+
+
+/*
+ * OOO support modes
+ */
+enum tcp_tstorm_ooo {
+ TCP_TSTORM_OOO_DROP_AND_PROC_ACK = 0,
+ TCP_TSTORM_OOO_SEND_PURE_ACK = 1,
+ TCP_TSTORM_OOO_SUPPORTED = 2,
+ MAX_TCP_TSTORM_OOO
+};
+
+
+
+
+
+
+
+
+
+#endif /* __5710_HSI_CNIC_LE__ */
diff --git a/drivers/net/cnic_if.h b/drivers/net/cnic_if.h
index fdd8e46..bc7000a 100644
--- a/drivers/net/cnic_if.h
+++ b/drivers/net/cnic_if.h
@@ -12,8 +12,8 @@
#ifndef CNIC_IF_H
#define CNIC_IF_H
-#define CNIC_MODULE_VERSION "2.2.14"
-#define CNIC_MODULE_RELDATE "Mar 30, 2011"
+#define CNIC_MODULE_VERSION "2.5.3"
+#define CNIC_MODULE_RELDATE "June 6, 2011"
#define CNIC_ULP_RDMA 0
#define CNIC_ULP_ISCSI 1
@@ -99,6 +99,8 @@
struct cnic_ctl_completion {
u32 cid;
+ u8 opcode;
+ u8 error;
};
struct cnic_ctl_info {
@@ -169,7 +171,7 @@
struct pci_dev *pdev;
void __iomem *io_base;
void __iomem *io_base2;
- void *iro_arr;
+ const void *iro_arr;
u32 ctx_tbl_offset;
u32 ctx_tbl_len;
diff --git a/drivers/net/cpmac.c b/drivers/net/cpmac.c
index fec939f..086ce04 100644
--- a/drivers/net/cpmac.c
+++ b/drivers/net/cpmac.c
@@ -18,6 +18,7 @@
#include <linux/module.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/moduleparam.h>
#include <linux/sched.h>
diff --git a/drivers/net/cxgb3/common.h b/drivers/net/cxgb3/common.h
index 056ee8c..df01b63 100644
--- a/drivers/net/cxgb3/common.h
+++ b/drivers/net/cxgb3/common.h
@@ -367,7 +367,6 @@
struct pci_params {
unsigned int vpd_cap_addr;
- unsigned int pcie_cap_addr;
unsigned short speed;
unsigned char width;
unsigned char variant;
diff --git a/drivers/net/cxgb3/cxgb3_offload.c b/drivers/net/cxgb3/cxgb3_offload.c
index 862804f..9db9068d 100644
--- a/drivers/net/cxgb3/cxgb3_offload.c
+++ b/drivers/net/cxgb3/cxgb3_offload.c
@@ -567,7 +567,7 @@
while (td->tid_release_list) {
struct t3c_tid_entry *p = td->tid_release_list;
- td->tid_release_list = (struct t3c_tid_entry *)p->ctx;
+ td->tid_release_list = p->ctx;
spin_unlock_bh(&td->tid_release_lock);
skb = alloc_skb(sizeof(struct cpl_tid_release),
diff --git a/drivers/net/cxgb3/t3_hw.c b/drivers/net/cxgb3/t3_hw.c
index c688421..44ac2f4 100644
--- a/drivers/net/cxgb3/t3_hw.c
+++ b/drivers/net/cxgb3/t3_hw.c
@@ -3290,22 +3290,20 @@
unsigned int fst_trn_rx, fst_trn_tx, acklat, rpllmt;
pci_read_config_word(adap->pdev,
- adap->params.pci.pcie_cap_addr + PCI_EXP_DEVCTL,
+ adap->pdev->pcie_cap + PCI_EXP_DEVCTL,
&val);
pldsize = (val & PCI_EXP_DEVCTL_PAYLOAD) >> 5;
pci_read_config_word(adap->pdev, 0x2, &devid);
if (devid == 0x37) {
pci_write_config_word(adap->pdev,
- adap->params.pci.pcie_cap_addr +
- PCI_EXP_DEVCTL,
+ adap->pdev->pcie_cap + PCI_EXP_DEVCTL,
val & ~PCI_EXP_DEVCTL_READRQ &
~PCI_EXP_DEVCTL_PAYLOAD);
pldsize = 0;
}
- pci_read_config_word(adap->pdev,
- adap->params.pci.pcie_cap_addr + PCI_EXP_LNKCTL,
+ pci_read_config_word(adap->pdev, adap->pdev->pcie_cap + PCI_EXP_LNKCTL,
&val);
fst_trn_tx = G_NUMFSTTRNSEQ(t3_read_reg(adap, A_PCIE_PEX_CTRL0));
@@ -3429,12 +3427,11 @@
static unsigned short speed_map[] = { 33, 66, 100, 133 };
u32 pci_mode, pcie_cap;
- pcie_cap = pci_find_capability(adapter->pdev, PCI_CAP_ID_EXP);
+ pcie_cap = pci_pcie_cap(adapter->pdev);
if (pcie_cap) {
u16 val;
p->variant = PCI_VARIANT_PCIE;
- p->pcie_cap_addr = pcie_cap;
pci_read_config_word(adapter->pdev, pcie_cap + PCI_EXP_LNKSTA,
&val);
p->width = (val >> 4) & 0x3f;
diff --git a/drivers/net/cxgb4/cxgb4_main.c b/drivers/net/cxgb4/cxgb4_main.c
index 7e3cfbe..c9957b7 100644
--- a/drivers/net/cxgb4/cxgb4_main.c
+++ b/drivers/net/cxgb4/cxgb4_main.c
@@ -3704,7 +3704,7 @@
if (err) {
dev_warn(&pdev->dev, "only %d net devices registered\n", i);
err = 0;
- };
+ }
if (cxgb4_debugfs_root) {
adapter->debugfs_root = debugfs_create_dir(pci_name(pdev),
diff --git a/drivers/net/cxgb4vf/adapter.h b/drivers/net/cxgb4vf/adapter.h
index 4fd821a..6e9a8d9 100644
--- a/drivers/net/cxgb4vf/adapter.h
+++ b/drivers/net/cxgb4vf/adapter.h
@@ -40,6 +40,7 @@
#ifndef __CXGB4VF_ADAPTER_H__
#define __CXGB4VF_ADAPTER_H__
+#include <linux/interrupt.h>
#include <linux/pci.h>
#include <linux/spinlock.h>
#include <linux/skbuff.h>
diff --git a/drivers/net/cxgb4vf/cxgb4vf_main.c b/drivers/net/cxgb4vf/cxgb4vf_main.c
index e71c08e..8a6f891 100644
--- a/drivers/net/cxgb4vf/cxgb4vf_main.c
+++ b/drivers/net/cxgb4vf/cxgb4vf_main.c
@@ -33,7 +33,6 @@
* SOFTWARE.
*/
-#include <linux/version.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
diff --git a/drivers/net/cxgb4vf/t4vf_hw.c b/drivers/net/cxgb4vf/t4vf_hw.c
index 192db22..fe3fd3d 100644
--- a/drivers/net/cxgb4vf/t4vf_hw.c
+++ b/drivers/net/cxgb4vf/t4vf_hw.c
@@ -33,7 +33,6 @@
* SOFTWARE.
*/
-#include <linux/version.h>
#include <linux/pci.h>
#include "t4vf_common.h"
diff --git a/drivers/net/davinci_cpdma.c b/drivers/net/davinci_cpdma.c
index ae47f23..dca9d33 100644
--- a/drivers/net/davinci_cpdma.c
+++ b/drivers/net/davinci_cpdma.c
@@ -167,7 +167,7 @@
} else {
pool->cpumap = dma_alloc_coherent(dev, size, &pool->phys,
GFP_KERNEL);
- pool->iomap = (void __force __iomem *)pool->cpumap;
+ pool->iomap = pool->cpumap;
pool->hw_addr = pool->phys;
}
diff --git a/drivers/net/davinci_emac.c b/drivers/net/davinci_emac.c
index dcc4a17..acef7e9 100644
--- a/drivers/net/davinci_emac.c
+++ b/drivers/net/davinci_emac.c
@@ -48,7 +48,6 @@
#include <linux/highmem.h>
#include <linux/proc_fs.h>
#include <linux/ctype.h>
-#include <linux/version.h>
#include <linux/spinlock.h>
#include <linux/dma-mapping.h>
#include <linux/clk.h>
@@ -1083,6 +1082,8 @@
goto fail_tx;
}
+ skb_tx_timestamp(skb);
+
ret_code = cpdma_chan_submit(priv->txchan, skb, skb->data, skb->len,
GFP_KERNEL);
if (unlikely(ret_code != 0)) {
@@ -1489,14 +1490,14 @@
*/
static int emac_devioctl(struct net_device *ndev, struct ifreq *ifrq, int cmd)
{
- dev_warn(&ndev->dev, "DaVinci EMAC: ioctl not supported\n");
+ struct emac_priv *priv = netdev_priv(ndev);
if (!(netif_running(ndev)))
return -EINVAL;
/* TODO: Add phy read and write and private statistics get feature */
- return -EOPNOTSUPP;
+ return phy_mii_ioctl(priv->phydev, ifrq, cmd);
}
static int match_first_device(struct device *dev, void *data)
diff --git a/drivers/net/declance.c b/drivers/net/declance.c
index 219eb5a..cabd3a5 100644
--- a/drivers/net/declance.c
+++ b/drivers/net/declance.c
@@ -326,15 +326,18 @@
*/
static void cp_to_buf(const int type, void *to, const void *from, int len)
{
- unsigned short *tp, *fp, clen;
- unsigned char *rtp, *rfp;
+ unsigned short *tp;
+ const unsigned short *fp;
+ unsigned short clen;
+ unsigned char *rtp;
+ const unsigned char *rfp;
if (type == PMAD_LANCE) {
memcpy(to, from, len);
} else if (type == PMAX_LANCE) {
clen = len >> 1;
- tp = (unsigned short *) to;
- fp = (unsigned short *) from;
+ tp = to;
+ fp = from;
while (clen--) {
*tp++ = *fp++;
@@ -342,8 +345,8 @@
}
clen = len & 1;
- rtp = (unsigned char *) tp;
- rfp = (unsigned char *) fp;
+ rtp = tp;
+ rfp = fp;
while (clen--) {
*rtp++ = *rfp++;
}
@@ -352,8 +355,8 @@
* copy 16 Byte chunks
*/
clen = len >> 4;
- tp = (unsigned short *) to;
- fp = (unsigned short *) from;
+ tp = to;
+ fp = from;
while (clen--) {
*tp++ = *fp++;
*tp++ = *fp++;
@@ -382,15 +385,18 @@
static void cp_from_buf(const int type, void *to, const void *from, int len)
{
- unsigned short *tp, *fp, clen;
- unsigned char *rtp, *rfp;
+ unsigned short *tp;
+ const unsigned short *fp;
+ unsigned short clen;
+ unsigned char *rtp;
+ const unsigned char *rfp;
if (type == PMAD_LANCE) {
memcpy(to, from, len);
} else if (type == PMAX_LANCE) {
clen = len >> 1;
- tp = (unsigned short *) to;
- fp = (unsigned short *) from;
+ tp = to;
+ fp = from;
while (clen--) {
*tp++ = *fp++;
fp++;
@@ -398,8 +404,8 @@
clen = len & 1;
- rtp = (unsigned char *) tp;
- rfp = (unsigned char *) fp;
+ rtp = tp;
+ rfp = fp;
while (clen--) {
*rtp++ = *rfp++;
@@ -410,8 +416,8 @@
* copy 16 Byte chunks
*/
clen = len >> 4;
- tp = (unsigned short *) to;
- fp = (unsigned short *) from;
+ tp = to;
+ fp = from;
while (clen--) {
*tp++ = *fp++;
*tp++ = *fp++;
diff --git a/drivers/net/depca.c b/drivers/net/depca.c
index 8b0084d..f2015a8 100644
--- a/drivers/net/depca.c
+++ b/drivers/net/depca.c
@@ -708,11 +708,11 @@
/* Tx & Rx descriptors (aligned to a quadword boundary) */
offset = (offset + DEPCA_ALIGN) & ~DEPCA_ALIGN;
- lp->rx_ring = (struct depca_rx_desc __iomem *) (lp->sh_mem + offset);
+ lp->rx_ring = lp->sh_mem + offset;
lp->rx_ring_offset = offset;
offset += (sizeof(struct depca_rx_desc) * NUM_RX_DESC);
- lp->tx_ring = (struct depca_tx_desc __iomem *) (lp->sh_mem + offset);
+ lp->tx_ring = lp->sh_mem + offset;
lp->tx_ring_offset = offset;
offset += (sizeof(struct depca_tx_desc) * NUM_TX_DESC);
@@ -1073,13 +1073,13 @@
i = DEPCA_PKT_STAT_SZ;
}
}
- if (buf[0] & 0x01) { /* Multicast/Broadcast */
- if ((*(s16 *) & buf[0] == -1) && (*(s16 *) & buf[2] == -1) && (*(s16 *) & buf[4] == -1)) {
+ if (is_multicast_ether_addr(buf)) {
+ if (is_broadcast_ether_addr(buf)) {
lp->pktStats.broadcast++;
} else {
lp->pktStats.multicast++;
}
- } else if ((*(s16 *) & buf[0] == *(s16 *) & dev->dev_addr[0]) && (*(s16 *) & buf[2] == *(s16 *) & dev->dev_addr[2]) && (*(s16 *) & buf[4] == *(s16 *) & dev->dev_addr[4])) {
+ } else if (compare_ether_addr(buf, dev->dev_addr) == 0) {
lp->pktStats.unicast++;
}
@@ -1270,7 +1270,6 @@
{
struct depca_private *lp = netdev_priv(dev);
struct netdev_hw_addr *ha;
- char *addrs;
int i, j, bit, byte;
u16 hashcode;
u32 crc;
@@ -1285,19 +1284,15 @@
}
/* Add multicast addresses */
netdev_for_each_mc_addr(ha, dev) {
- addrs = ha->addr;
- if ((*addrs & 0x01) == 1) { /* multicast address? */
- crc = ether_crc(ETH_ALEN, addrs);
- hashcode = (crc & 1); /* hashcode is 6 LSb of CRC ... */
- for (j = 0; j < 5; j++) { /* ... in reverse order. */
- hashcode = (hashcode << 1) | ((crc >>= 1) & 1);
- }
-
-
- byte = hashcode >> 3; /* bit[3-5] -> byte in filter */
- bit = 1 << (hashcode & 0x07); /* bit[0-2] -> bit in byte */
- lp->init_block.mcast_table[byte] |= bit;
+ crc = ether_crc(ETH_ALEN, ha->addr);
+ hashcode = (crc & 1); /* hashcode is 6 LSb of CRC ... */
+ for (j = 0; j < 5; j++) { /* ... in reverse order. */
+ hashcode = (hashcode << 1) | ((crc >>= 1) & 1);
}
+
+ byte = hashcode >> 3; /* bit[3-5] -> byte in filter */
+ bit = 1 << (hashcode & 0x07); /* bit[0-2] -> bit in byte */
+ lp->init_block.mcast_table[byte] |= bit;
}
}
}
diff --git a/drivers/net/dl2k.c b/drivers/net/dl2k.c
index 23179db..ed73e4a 100644
--- a/drivers/net/dl2k.c
+++ b/drivers/net/dl2k.c
@@ -221,13 +221,13 @@
ring_space = pci_alloc_consistent (pdev, TX_TOTAL_SIZE, &ring_dma);
if (!ring_space)
goto err_out_iounmap;
- np->tx_ring = (struct netdev_desc *) ring_space;
+ np->tx_ring = ring_space;
np->tx_ring_dma = ring_dma;
ring_space = pci_alloc_consistent (pdev, RX_TOTAL_SIZE, &ring_dma);
if (!ring_space)
goto err_out_unmap_tx;
- np->rx_ring = (struct netdev_desc *) ring_space;
+ np->rx_ring = ring_space;
np->rx_ring_dma = ring_dma;
/* Parse eeprom data */
diff --git a/drivers/net/dm9000.c b/drivers/net/dm9000.c
index ee597e6..8ef31dc 100644
--- a/drivers/net/dm9000.c
+++ b/drivers/net/dm9000.c
@@ -24,6 +24,7 @@
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/skbuff.h>
#include <linux/spinlock.h>
#include <linux/crc32.h>
@@ -534,21 +535,35 @@
board_info_t *dm = to_dm9000_board(dev);
int offset = ee->offset;
int len = ee->len;
- int i;
+ int done;
/* EEPROM access is aligned to two bytes */
- if ((len & 1) != 0 || (offset & 1) != 0)
- return -EINVAL;
-
if (dm->flags & DM9000_PLATF_NO_EEPROM)
return -ENOENT;
if (ee->magic != DM_EEPROM_MAGIC)
return -EINVAL;
- for (i = 0; i < len; i += 2)
- dm9000_write_eeprom(dm, (offset + i) / 2, data + i);
+ while (len > 0) {
+ if (len & 1 || offset & 1) {
+ int which = offset & 1;
+ u8 tmp[2];
+
+ dm9000_read_eeprom(dm, offset / 2, tmp);
+ tmp[which] = *data;
+ dm9000_write_eeprom(dm, offset / 2, tmp);
+
+ done = 1;
+ } else {
+ dm9000_write_eeprom(dm, offset / 2, data);
+ done = 2;
+ }
+
+ data += done;
+ offset += done;
+ len -= done;
+ }
return 0;
}
diff --git a/drivers/net/dnet.c b/drivers/net/dnet.c
index 8318ea0..c1063d1 100644
--- a/drivers/net/dnet.c
+++ b/drivers/net/dnet.c
@@ -16,6 +16,7 @@
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/dma-mapping.h>
@@ -587,6 +588,8 @@
dnet_writel(bp, irq_enable, INTR_ENB);
}
+ skb_tx_timestamp(skb);
+
/* free the buffer */
dev_kfree_skb(skb);
diff --git a/drivers/net/e100.c b/drivers/net/e100.c
index e336c79..c1352c6 100644
--- a/drivers/net/e100.c
+++ b/drivers/net/e100.c
@@ -149,6 +149,8 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#include <linux/hardirq.h>
+#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kernel.h>
diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c
index ec0fa42..c5f0f04 100644
--- a/drivers/net/e1000/e1000_ethtool.c
+++ b/drivers/net/e1000/e1000_ethtool.c
@@ -290,69 +290,6 @@
return retval;
}
-static u32 e1000_get_rx_csum(struct net_device *netdev)
-{
- struct e1000_adapter *adapter = netdev_priv(netdev);
- return adapter->rx_csum;
-}
-
-static int e1000_set_rx_csum(struct net_device *netdev, u32 data)
-{
- struct e1000_adapter *adapter = netdev_priv(netdev);
- adapter->rx_csum = data;
-
- if (netif_running(netdev))
- e1000_reinit_locked(adapter);
- else
- e1000_reset(adapter);
- return 0;
-}
-
-static u32 e1000_get_tx_csum(struct net_device *netdev)
-{
- return (netdev->features & NETIF_F_HW_CSUM) != 0;
-}
-
-static int e1000_set_tx_csum(struct net_device *netdev, u32 data)
-{
- struct e1000_adapter *adapter = netdev_priv(netdev);
- struct e1000_hw *hw = &adapter->hw;
-
- if (hw->mac_type < e1000_82543) {
- if (!data)
- return -EINVAL;
- return 0;
- }
-
- if (data)
- netdev->features |= NETIF_F_HW_CSUM;
- else
- netdev->features &= ~NETIF_F_HW_CSUM;
-
- return 0;
-}
-
-static int e1000_set_tso(struct net_device *netdev, u32 data)
-{
- struct e1000_adapter *adapter = netdev_priv(netdev);
- struct e1000_hw *hw = &adapter->hw;
-
- if ((hw->mac_type < e1000_82544) ||
- (hw->mac_type == e1000_82547))
- return data ? -EINVAL : 0;
-
- if (data)
- netdev->features |= NETIF_F_TSO;
- else
- netdev->features &= ~NETIF_F_TSO;
-
- netdev->features &= ~NETIF_F_TSO6;
-
- e_info(probe, "TSO is %s\n", data ? "Enabled" : "Disabled");
- adapter->tso_force = true;
- return 0;
-}
-
static u32 e1000_get_msglevel(struct net_device *netdev)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
@@ -1905,12 +1842,6 @@
.set_ringparam = e1000_set_ringparam,
.get_pauseparam = e1000_get_pauseparam,
.set_pauseparam = e1000_set_pauseparam,
- .get_rx_csum = e1000_get_rx_csum,
- .set_rx_csum = e1000_set_rx_csum,
- .get_tx_csum = e1000_get_tx_csum,
- .set_tx_csum = e1000_set_tx_csum,
- .set_sg = ethtool_op_set_sg,
- .set_tso = e1000_set_tso,
.self_test = e1000_diag_test,
.get_strings = e1000_get_strings,
.set_phys_id = e1000_set_phys_id,
diff --git a/drivers/net/e1000/e1000_hw.c b/drivers/net/e1000/e1000_hw.c
index 7501d97..1698622 100644
--- a/drivers/net/e1000/e1000_hw.c
+++ b/drivers/net/e1000/e1000_hw.c
@@ -3080,7 +3080,6 @@
{
u32 ctrl, ctrl_ext;
u32 led_ctrl;
- s32 ret_val;
e_dbg("e1000_phy_hw_reset");
@@ -3126,11 +3125,7 @@
}
/* Wait for FW to finish PHY configuration. */
- ret_val = e1000_get_phy_cfg_done(hw);
- if (ret_val != E1000_SUCCESS)
- return ret_val;
-
- return ret_val;
+ return e1000_get_phy_cfg_done(hw);
}
/**
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
index 76e8af0..188d99a 100644
--- a/drivers/net/e1000/e1000_main.c
+++ b/drivers/net/e1000/e1000_main.c
@@ -797,6 +797,24 @@
}
}
+static int e1000_set_features(struct net_device *netdev, u32 features)
+{
+ struct e1000_adapter *adapter = netdev_priv(netdev);
+ u32 changed = features ^ netdev->features;
+
+ if (!(changed & NETIF_F_RXCSUM))
+ return 0;
+
+ adapter->rx_csum = !!(features & NETIF_F_RXCSUM);
+
+ if (netif_running(netdev))
+ e1000_reinit_locked(adapter);
+ else
+ e1000_reset(adapter);
+
+ return 0;
+}
+
static const struct net_device_ops e1000_netdev_ops = {
.ndo_open = e1000_open,
.ndo_stop = e1000_close,
@@ -815,6 +833,7 @@
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = e1000_netpoll,
#endif
+ .ndo_set_features = e1000_set_features,
};
/**
@@ -1016,16 +1035,19 @@
}
if (hw->mac_type >= e1000_82543) {
- netdev->features = NETIF_F_SG |
- NETIF_F_HW_CSUM |
- NETIF_F_HW_VLAN_TX |
+ netdev->hw_features = NETIF_F_SG |
+ NETIF_F_HW_CSUM;
+ netdev->features = NETIF_F_HW_VLAN_TX |
NETIF_F_HW_VLAN_RX |
NETIF_F_HW_VLAN_FILTER;
}
if ((hw->mac_type >= e1000_82544) &&
(hw->mac_type != e1000_82547))
- netdev->features |= NETIF_F_TSO;
+ netdev->hw_features |= NETIF_F_TSO;
+
+ netdev->features |= netdev->hw_features;
+ netdev->hw_features |= NETIF_F_RXCSUM;
if (pci_using_dac) {
netdev->features |= NETIF_F_HIGHDMA;
diff --git a/drivers/net/e1000e/e1000.h b/drivers/net/e1000e/e1000.h
index 9549879..c1e7f94 100644
--- a/drivers/net/e1000e/e1000.h
+++ b/drivers/net/e1000e/e1000.h
@@ -104,6 +104,7 @@
(((reg) & ~MAX_PHY_REG_ADDRESS) << (PHY_UPPER_SHIFT - PHY_PAGE_SHIFT)))
/* PHY Wakeup Registers and defines */
+#define BM_PORT_GEN_CFG PHY_REG(BM_PORT_CTRL_PAGE, 17)
#define BM_RCTL PHY_REG(BM_WUC_PAGE, 0)
#define BM_WUC PHY_REG(BM_WUC_PAGE, 1)
#define BM_WUFC PHY_REG(BM_WUC_PAGE, 2)
@@ -122,20 +123,21 @@
#define BM_RCTL_PMCF 0x0040 /* Pass MAC Control Frames */
#define BM_RCTL_RFCE 0x0080 /* Rx Flow Control Enable */
-#define HV_SCC_UPPER PHY_REG(778, 16) /* Single Collision Count */
-#define HV_SCC_LOWER PHY_REG(778, 17)
-#define HV_ECOL_UPPER PHY_REG(778, 18) /* Excessive Collision Count */
-#define HV_ECOL_LOWER PHY_REG(778, 19)
-#define HV_MCC_UPPER PHY_REG(778, 20) /* Multiple Collision Count */
-#define HV_MCC_LOWER PHY_REG(778, 21)
-#define HV_LATECOL_UPPER PHY_REG(778, 23) /* Late Collision Count */
-#define HV_LATECOL_LOWER PHY_REG(778, 24)
-#define HV_COLC_UPPER PHY_REG(778, 25) /* Collision Count */
-#define HV_COLC_LOWER PHY_REG(778, 26)
-#define HV_DC_UPPER PHY_REG(778, 27) /* Defer Count */
-#define HV_DC_LOWER PHY_REG(778, 28)
-#define HV_TNCRS_UPPER PHY_REG(778, 29) /* Transmit with no CRS */
-#define HV_TNCRS_LOWER PHY_REG(778, 30)
+#define HV_STATS_PAGE 778
+#define HV_SCC_UPPER PHY_REG(HV_STATS_PAGE, 16) /* Single Collision Count */
+#define HV_SCC_LOWER PHY_REG(HV_STATS_PAGE, 17)
+#define HV_ECOL_UPPER PHY_REG(HV_STATS_PAGE, 18) /* Excessive Coll. Count */
+#define HV_ECOL_LOWER PHY_REG(HV_STATS_PAGE, 19)
+#define HV_MCC_UPPER PHY_REG(HV_STATS_PAGE, 20) /* Multiple Coll. Count */
+#define HV_MCC_LOWER PHY_REG(HV_STATS_PAGE, 21)
+#define HV_LATECOL_UPPER PHY_REG(HV_STATS_PAGE, 23) /* Late Collision Count */
+#define HV_LATECOL_LOWER PHY_REG(HV_STATS_PAGE, 24)
+#define HV_COLC_UPPER PHY_REG(HV_STATS_PAGE, 25) /* Collision Count */
+#define HV_COLC_LOWER PHY_REG(HV_STATS_PAGE, 26)
+#define HV_DC_UPPER PHY_REG(HV_STATS_PAGE, 27) /* Defer Count */
+#define HV_DC_LOWER PHY_REG(HV_STATS_PAGE, 28)
+#define HV_TNCRS_UPPER PHY_REG(HV_STATS_PAGE, 29) /* Transmit with no CRS */
+#define HV_TNCRS_LOWER PHY_REG(HV_STATS_PAGE, 30)
#define E1000_FCRTV_PCH 0x05F40 /* PCH Flow Control Refresh Timer Value */
@@ -533,7 +535,8 @@
bool state);
extern void e1000e_igp3_phy_powerdown_workaround_ich8lan(struct e1000_hw *hw);
extern void e1000e_gig_downshift_workaround_ich8lan(struct e1000_hw *hw);
-extern void e1000e_disable_gig_wol_ich8lan(struct e1000_hw *hw);
+extern void e1000_suspend_workarounds_ich8lan(struct e1000_hw *hw);
+extern void e1000_resume_workarounds_pchlan(struct e1000_hw *hw);
extern s32 e1000_configure_k1_ich8lan(struct e1000_hw *hw, bool k1_enable);
extern s32 e1000_lv_jumbo_workaround_ich8lan(struct e1000_hw *hw, bool enable);
extern void e1000_copy_rx_addrs_to_phy_ich8lan(struct e1000_hw *hw);
@@ -584,6 +587,7 @@
extern s32 e1000e_phy_force_speed_duplex_igp(struct e1000_hw *hw);
extern s32 e1000e_get_cable_length_igp_2(struct e1000_hw *hw);
extern s32 e1000e_get_phy_info_igp(struct e1000_hw *hw);
+extern s32 e1000_set_page_igp(struct e1000_hw *hw, u16 page);
extern s32 e1000e_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data);
extern s32 e1000e_read_phy_reg_igp_locked(struct e1000_hw *hw, u32 offset,
u16 *data);
@@ -604,6 +608,10 @@
extern s32 e1000e_determine_phy_address(struct e1000_hw *hw);
extern s32 e1000e_write_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 data);
extern s32 e1000e_read_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data);
+extern s32 e1000_enable_phy_wakeup_reg_access_bm(struct e1000_hw *hw,
+ u16 *phy_reg);
+extern s32 e1000_disable_phy_wakeup_reg_access_bm(struct e1000_hw *hw,
+ u16 *phy_reg);
extern s32 e1000e_read_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 *data);
extern s32 e1000e_write_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 data);
extern void e1000e_phy_force_speed_duplex_setup(struct e1000_hw *hw, u16 *phy_ctrl);
@@ -624,9 +632,13 @@
extern s32 e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data);
extern s32 e1000_read_phy_reg_hv_locked(struct e1000_hw *hw, u32 offset,
u16 *data);
+extern s32 e1000_read_phy_reg_page_hv(struct e1000_hw *hw, u32 offset,
+ u16 *data);
extern s32 e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data);
extern s32 e1000_write_phy_reg_hv_locked(struct e1000_hw *hw, u32 offset,
u16 data);
+extern s32 e1000_write_phy_reg_page_hv(struct e1000_hw *hw, u32 offset,
+ u16 data);
extern s32 e1000_link_stall_workaround_hv(struct e1000_hw *hw);
extern s32 e1000_copper_link_setup_82577(struct e1000_hw *hw);
extern s32 e1000_check_polarity_82577(struct e1000_hw *hw);
diff --git a/drivers/net/e1000e/es2lan.c b/drivers/net/e1000e/es2lan.c
index f4bbeb2..c0ecb2d 100644
--- a/drivers/net/e1000e/es2lan.c
+++ b/drivers/net/e1000e/es2lan.c
@@ -836,6 +836,7 @@
struct e1000_mac_info *mac = &hw->mac;
u32 reg_data;
s32 ret_val;
+ u16 kum_reg_data;
u16 i;
e1000_initialize_hw_bits_80003es2lan(hw);
@@ -861,6 +862,13 @@
/* Setup link and flow control */
ret_val = e1000e_setup_link(hw);
+ /* Disable IBIST slave mode (far-end loopback) */
+ e1000_read_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_INBAND_PARAM,
+ &kum_reg_data);
+ kum_reg_data |= E1000_KMRNCTRLSTA_IBIST_DISABLE;
+ e1000_write_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_INBAND_PARAM,
+ kum_reg_data);
+
/* Set the transmit descriptor write-back policy */
reg_data = er32(TXDCTL(0));
reg_data = (reg_data & ~E1000_TXDCTL_WTHRESH) |
diff --git a/drivers/net/e1000e/ethtool.c b/drivers/net/e1000e/ethtool.c
index 859d0d3..cb1a362 100644
--- a/drivers/net/e1000e/ethtool.c
+++ b/drivers/net/e1000e/ethtool.c
@@ -28,6 +28,7 @@
/* ethtool support for e1000 */
+#include <linux/interrupt.h>
#include <linux/netdevice.h>
#include <linux/ethtool.h>
#include <linux/pci.h>
diff --git a/drivers/net/e1000e/hw.h b/drivers/net/e1000e/hw.h
index 6c2fa83..2967039 100644
--- a/drivers/net/e1000e/hw.h
+++ b/drivers/net/e1000e/hw.h
@@ -246,6 +246,7 @@
#define BM_WUC_ENABLE_REG 17
#define BM_WUC_ENABLE_BIT (1 << 2)
#define BM_WUC_HOST_WU_BIT (1 << 4)
+#define BM_WUC_ME_WU_BIT (1 << 5)
#define BM_WUC PHY_REG(BM_WUC_PAGE, 1)
#define BM_WUFC PHY_REG(BM_WUC_PAGE, 2)
@@ -312,6 +313,7 @@
#define E1000_KMRNCTRLSTA_DIAG_OFFSET 0x3 /* Kumeran Diagnostic */
#define E1000_KMRNCTRLSTA_TIMEOUTS 0x4 /* Kumeran Timeouts */
#define E1000_KMRNCTRLSTA_INBAND_PARAM 0x9 /* Kumeran InBand Parameters */
+#define E1000_KMRNCTRLSTA_IBIST_DISABLE 0x0200 /* Kumeran IBIST Disable */
#define E1000_KMRNCTRLSTA_DIAG_NELPBK 0x1000 /* Nearend Loopback mode */
#define E1000_KMRNCTRLSTA_K1_CONFIG 0x7
#define E1000_KMRNCTRLSTA_K1_ENABLE 0x0002
@@ -777,7 +779,21 @@
s32 (*read_mac_addr)(struct e1000_hw *);
};
-/* Function pointers for the PHY. */
+/*
+ * When to use various PHY register access functions:
+ *
+ * Func Caller
+ * Function Does Does When to use
+ * ~~~~~~~~~~~~ ~~~~~ ~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ * X_reg L,P,A n/a for simple PHY reg accesses
+ * X_reg_locked P,A L for multiple accesses of different regs
+ * on different pages
+ * X_reg_page A L,P for multiple accesses of different regs
+ * on the same page
+ *
+ * Where X=[read|write], L=locking, P=sets page, A=register access
+ *
+ */
struct e1000_phy_operations {
s32 (*acquire)(struct e1000_hw *);
s32 (*cfg_on_link_up)(struct e1000_hw *);
@@ -788,14 +804,17 @@
s32 (*get_cfg_done)(struct e1000_hw *hw);
s32 (*get_cable_length)(struct e1000_hw *);
s32 (*get_info)(struct e1000_hw *);
+ s32 (*set_page)(struct e1000_hw *, u16);
s32 (*read_reg)(struct e1000_hw *, u32, u16 *);
s32 (*read_reg_locked)(struct e1000_hw *, u32, u16 *);
+ s32 (*read_reg_page)(struct e1000_hw *, u32, u16 *);
void (*release)(struct e1000_hw *);
s32 (*reset)(struct e1000_hw *);
s32 (*set_d0_lplu_state)(struct e1000_hw *, bool);
s32 (*set_d3_lplu_state)(struct e1000_hw *, bool);
s32 (*write_reg)(struct e1000_hw *, u32, u16);
s32 (*write_reg_locked)(struct e1000_hw *, u32, u16);
+ s32 (*write_reg_page)(struct e1000_hw *, u32, u16);
void (*power_up)(struct e1000_hw *);
void (*power_down)(struct e1000_hw *);
};
diff --git a/drivers/net/e1000e/ich8lan.c b/drivers/net/e1000e/ich8lan.c
index 3369d1f..c175212 100644
--- a/drivers/net/e1000e/ich8lan.c
+++ b/drivers/net/e1000e/ich8lan.c
@@ -275,6 +275,19 @@
#define ew16flash(reg,val) __ew16flash(hw, (reg), (val))
#define ew32flash(reg,val) __ew32flash(hw, (reg), (val))
+static void e1000_toggle_lanphypc_value_ich8lan(struct e1000_hw *hw)
+{
+ u32 ctrl;
+
+ ctrl = er32(CTRL);
+ ctrl |= E1000_CTRL_LANPHYPC_OVERRIDE;
+ ctrl &= ~E1000_CTRL_LANPHYPC_VALUE;
+ ew32(CTRL, ctrl);
+ udelay(10);
+ ctrl &= ~E1000_CTRL_LANPHYPC_OVERRIDE;
+ ew32(CTRL, ctrl);
+}
+
/**
* e1000_init_phy_params_pchlan - Initialize PHY function pointers
* @hw: pointer to the HW structure
@@ -284,18 +297,21 @@
static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw)
{
struct e1000_phy_info *phy = &hw->phy;
- u32 ctrl, fwsm;
+ u32 fwsm;
s32 ret_val = 0;
phy->addr = 1;
phy->reset_delay_us = 100;
+ phy->ops.set_page = e1000_set_page_igp;
phy->ops.read_reg = e1000_read_phy_reg_hv;
phy->ops.read_reg_locked = e1000_read_phy_reg_hv_locked;
+ phy->ops.read_reg_page = e1000_read_phy_reg_page_hv;
phy->ops.set_d0_lplu_state = e1000_set_lplu_state_pchlan;
phy->ops.set_d3_lplu_state = e1000_set_lplu_state_pchlan;
phy->ops.write_reg = e1000_write_phy_reg_hv;
phy->ops.write_reg_locked = e1000_write_phy_reg_hv_locked;
+ phy->ops.write_reg_page = e1000_write_phy_reg_page_hv;
phy->ops.power_up = e1000_power_up_phy_copper;
phy->ops.power_down = e1000_power_down_phy_copper_ich8lan;
phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT;
@@ -308,13 +324,7 @@
*/
fwsm = er32(FWSM);
if (!(fwsm & E1000_ICH_FWSM_FW_VALID) && !e1000_check_reset_block(hw)) {
- ctrl = er32(CTRL);
- ctrl |= E1000_CTRL_LANPHYPC_OVERRIDE;
- ctrl &= ~E1000_CTRL_LANPHYPC_VALUE;
- ew32(CTRL, ctrl);
- udelay(10);
- ctrl &= ~E1000_CTRL_LANPHYPC_OVERRIDE;
- ew32(CTRL, ctrl);
+ e1000_toggle_lanphypc_value_ich8lan(hw);
msleep(50);
/*
@@ -882,8 +892,13 @@
u32 extcnf_ctrl;
extcnf_ctrl = er32(EXTCNF_CTRL);
- extcnf_ctrl &= ~E1000_EXTCNF_CTRL_SWFLAG;
- ew32(EXTCNF_CTRL, extcnf_ctrl);
+
+ if (extcnf_ctrl & E1000_EXTCNF_CTRL_SWFLAG) {
+ extcnf_ctrl &= ~E1000_EXTCNF_CTRL_SWFLAG;
+ ew32(EXTCNF_CTRL, extcnf_ctrl);
+ } else {
+ e_dbg("Semaphore unexpectedly released by sw/fw/hw\n");
+ }
mutex_unlock(&swflag_mutex);
}
@@ -1376,14 +1391,11 @@
ret_val = hw->phy.ops.acquire(hw);
if (ret_val)
goto out;
- ret_val = hw->phy.ops.read_reg_locked(hw,
- PHY_REG(BM_PORT_CTRL_PAGE, 17),
- &phy_data);
+ ret_val = hw->phy.ops.read_reg_locked(hw, BM_PORT_GEN_CFG, &phy_data);
if (ret_val)
goto release;
- ret_val = hw->phy.ops.write_reg_locked(hw,
- PHY_REG(BM_PORT_CTRL_PAGE, 17),
- phy_data & 0x00FF);
+ ret_val = hw->phy.ops.write_reg_locked(hw, BM_PORT_GEN_CFG,
+ phy_data & 0x00FF);
release:
hw->phy.ops.release(hw);
out:
@@ -1397,17 +1409,36 @@
void e1000_copy_rx_addrs_to_phy_ich8lan(struct e1000_hw *hw)
{
u32 mac_reg;
- u16 i;
+ u16 i, phy_reg = 0;
+ s32 ret_val;
+
+ ret_val = hw->phy.ops.acquire(hw);
+ if (ret_val)
+ return;
+ ret_val = e1000_enable_phy_wakeup_reg_access_bm(hw, &phy_reg);
+ if (ret_val)
+ goto release;
/* Copy both RAL/H (rar_entry_count) and SHRAL/H (+4) to PHY */
for (i = 0; i < (hw->mac.rar_entry_count + 4); i++) {
mac_reg = er32(RAL(i));
- e1e_wphy(hw, BM_RAR_L(i), (u16)(mac_reg & 0xFFFF));
- e1e_wphy(hw, BM_RAR_M(i), (u16)((mac_reg >> 16) & 0xFFFF));
+ hw->phy.ops.write_reg_page(hw, BM_RAR_L(i),
+ (u16)(mac_reg & 0xFFFF));
+ hw->phy.ops.write_reg_page(hw, BM_RAR_M(i),
+ (u16)((mac_reg >> 16) & 0xFFFF));
+
mac_reg = er32(RAH(i));
- e1e_wphy(hw, BM_RAR_H(i), (u16)(mac_reg & 0xFFFF));
- e1e_wphy(hw, BM_RAR_CTRL(i), (u16)((mac_reg >> 16) & 0x8000));
+ hw->phy.ops.write_reg_page(hw, BM_RAR_H(i),
+ (u16)(mac_reg & 0xFFFF));
+ hw->phy.ops.write_reg_page(hw, BM_RAR_CTRL(i),
+ (u16)((mac_reg & E1000_RAH_AV)
+ >> 16));
}
+
+ e1000_disable_phy_wakeup_reg_access_bm(hw, &phy_reg);
+
+release:
+ hw->phy.ops.release(hw);
}
/**
@@ -1726,9 +1757,12 @@
break;
}
- /* Dummy read to clear the phy wakeup bit after lcd reset */
- if (hw->mac.type >= e1000_pchlan)
- e1e_rphy(hw, BM_WUC, ®);
+ /* Clear the host wakeup bit after lcd reset */
+ if (hw->mac.type >= e1000_pchlan) {
+ e1e_rphy(hw, BM_PORT_GEN_CFG, ®);
+ reg &= ~BM_WUC_HOST_WU_BIT;
+ e1e_wphy(hw, BM_PORT_GEN_CFG, reg);
+ }
/* Configure the LCD with the extended configuration region in NVM */
ret_val = e1000_sw_lcd_config_ich8lan(hw);
@@ -3059,7 +3093,7 @@
msleep(20);
if (!ret_val)
- e1000_release_swflag_ich8lan(hw);
+ mutex_unlock(&swflag_mutex);
if (ctrl & E1000_CTRL_PHY_RST) {
ret_val = hw->phy.ops.get_cfg_done(hw);
@@ -3127,11 +3161,13 @@
/*
* The 82578 Rx buffer will stall if wakeup is enabled in host and
- * the ME. Reading the BM_WUC register will clear the host wakeup bit.
+ * the ME. Disable wakeup by clearing the host wakeup bit.
* Reset the phy after disabling host wakeup to reset the Rx buffer.
*/
if (hw->phy.type == e1000_phy_82578) {
- e1e_rphy(hw, BM_WUC, &i);
+ e1e_rphy(hw, BM_PORT_GEN_CFG, &i);
+ i &= ~BM_WUC_HOST_WU_BIT;
+ e1e_wphy(hw, BM_PORT_GEN_CFG, i);
ret_val = e1000_phy_hw_reset_ich8lan(hw);
if (ret_val)
return ret_val;
@@ -3586,17 +3622,16 @@
}
/**
- * e1000e_disable_gig_wol_ich8lan - disable gig during WoL
+ * e1000_suspend_workarounds_ich8lan - workarounds needed during S0->Sx
* @hw: pointer to the HW structure
*
* During S0 to Sx transition, it is possible the link remains at gig
* instead of negotiating to a lower speed. Before going to Sx, set
* 'LPLU Enabled' and 'Gig Disable' to force link speed negotiation
- * to a lower speed.
- *
- * Should only be called for applicable parts.
+ * to a lower speed. For PCH and newer parts, the OEM bits PHY register
+ * (LED, GbE disable and LPLU configurations) also needs to be written.
**/
-void e1000e_disable_gig_wol_ich8lan(struct e1000_hw *hw)
+void e1000_suspend_workarounds_ich8lan(struct e1000_hw *hw)
{
u32 phy_ctrl;
s32 ret_val;
@@ -3616,6 +3651,60 @@
}
/**
+ * e1000_resume_workarounds_pchlan - workarounds needed during Sx->S0
+ * @hw: pointer to the HW structure
+ *
+ * During Sx to S0 transitions on non-managed devices or managed devices
+ * on which PHY resets are not blocked, if the PHY registers cannot be
+ * accessed properly by the s/w toggle the LANPHYPC value to power cycle
+ * the PHY.
+ **/
+void e1000_resume_workarounds_pchlan(struct e1000_hw *hw)
+{
+ u32 fwsm;
+
+ if (hw->mac.type != e1000_pch2lan)
+ return;
+
+ fwsm = er32(FWSM);
+ if (!(fwsm & E1000_ICH_FWSM_FW_VALID) || !e1000_check_reset_block(hw)) {
+ u16 phy_id1, phy_id2;
+ s32 ret_val;
+
+ ret_val = hw->phy.ops.acquire(hw);
+ if (ret_val) {
+ e_dbg("Failed to acquire PHY semaphore in resume\n");
+ return;
+ }
+
+ /* Test access to the PHY registers by reading the ID regs */
+ ret_val = hw->phy.ops.read_reg_locked(hw, PHY_ID1, &phy_id1);
+ if (ret_val)
+ goto release;
+ ret_val = hw->phy.ops.read_reg_locked(hw, PHY_ID2, &phy_id2);
+ if (ret_val)
+ goto release;
+
+ if (hw->phy.id == ((u32)(phy_id1 << 16) |
+ (u32)(phy_id2 & PHY_REVISION_MASK)))
+ goto release;
+
+ e1000_toggle_lanphypc_value_ich8lan(hw);
+
+ hw->phy.ops.release(hw);
+ msleep(50);
+ e1000_phy_hw_reset(hw);
+ msleep(50);
+ return;
+ }
+
+release:
+ hw->phy.ops.release(hw);
+
+ return;
+}
+
+/**
* e1000_cleanup_led_ich8lan - Restore the default LED operation
* @hw: pointer to the HW structure
*
@@ -3832,6 +3921,7 @@
static void e1000_clear_hw_cntrs_ich8lan(struct e1000_hw *hw)
{
u16 phy_data;
+ s32 ret_val;
e1000e_clear_hw_cntrs_base(hw);
@@ -3853,20 +3943,29 @@
if ((hw->phy.type == e1000_phy_82578) ||
(hw->phy.type == e1000_phy_82579) ||
(hw->phy.type == e1000_phy_82577)) {
- e1e_rphy(hw, HV_SCC_UPPER, &phy_data);
- e1e_rphy(hw, HV_SCC_LOWER, &phy_data);
- e1e_rphy(hw, HV_ECOL_UPPER, &phy_data);
- e1e_rphy(hw, HV_ECOL_LOWER, &phy_data);
- e1e_rphy(hw, HV_MCC_UPPER, &phy_data);
- e1e_rphy(hw, HV_MCC_LOWER, &phy_data);
- e1e_rphy(hw, HV_LATECOL_UPPER, &phy_data);
- e1e_rphy(hw, HV_LATECOL_LOWER, &phy_data);
- e1e_rphy(hw, HV_COLC_UPPER, &phy_data);
- e1e_rphy(hw, HV_COLC_LOWER, &phy_data);
- e1e_rphy(hw, HV_DC_UPPER, &phy_data);
- e1e_rphy(hw, HV_DC_LOWER, &phy_data);
- e1e_rphy(hw, HV_TNCRS_UPPER, &phy_data);
- e1e_rphy(hw, HV_TNCRS_LOWER, &phy_data);
+ ret_val = hw->phy.ops.acquire(hw);
+ if (ret_val)
+ return;
+ ret_val = hw->phy.ops.set_page(hw,
+ HV_STATS_PAGE << IGP_PAGE_SHIFT);
+ if (ret_val)
+ goto release;
+ hw->phy.ops.read_reg_page(hw, HV_SCC_UPPER, &phy_data);
+ hw->phy.ops.read_reg_page(hw, HV_SCC_LOWER, &phy_data);
+ hw->phy.ops.read_reg_page(hw, HV_ECOL_UPPER, &phy_data);
+ hw->phy.ops.read_reg_page(hw, HV_ECOL_LOWER, &phy_data);
+ hw->phy.ops.read_reg_page(hw, HV_MCC_UPPER, &phy_data);
+ hw->phy.ops.read_reg_page(hw, HV_MCC_LOWER, &phy_data);
+ hw->phy.ops.read_reg_page(hw, HV_LATECOL_UPPER, &phy_data);
+ hw->phy.ops.read_reg_page(hw, HV_LATECOL_LOWER, &phy_data);
+ hw->phy.ops.read_reg_page(hw, HV_COLC_UPPER, &phy_data);
+ hw->phy.ops.read_reg_page(hw, HV_COLC_LOWER, &phy_data);
+ hw->phy.ops.read_reg_page(hw, HV_DC_UPPER, &phy_data);
+ hw->phy.ops.read_reg_page(hw, HV_DC_LOWER, &phy_data);
+ hw->phy.ops.read_reg_page(hw, HV_TNCRS_UPPER, &phy_data);
+ hw->phy.ops.read_reg_page(hw, HV_TNCRS_LOWER, &phy_data);
+release:
+ hw->phy.ops.release(hw);
}
}
diff --git a/drivers/net/e1000e/lib.c b/drivers/net/e1000e/lib.c
index dd8ab05..65580b40 100644
--- a/drivers/net/e1000e/lib.c
+++ b/drivers/net/e1000e/lib.c
@@ -56,7 +56,7 @@
struct e1000_adapter *adapter = hw->adapter;
u16 pcie_link_status, cap_offset;
- cap_offset = pci_find_capability(adapter->pdev, PCI_CAP_ID_EXP);
+ cap_offset = adapter->pdev->pcie_cap;
if (!cap_offset) {
bus->width = e1000_bus_width_unknown;
} else {
@@ -220,7 +220,7 @@
}
/* if multicast bit is set, the alternate address will not be used */
- if (alt_mac_addr[0] & 0x01) {
+ if (is_multicast_ether_addr(alt_mac_addr)) {
e_dbg("Ignoring Alternate Mac Address with MC bit set\n");
goto out;
}
diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c
index 3310c3d..ed7a93d 100644
--- a/drivers/net/e1000e/netdev.c
+++ b/drivers/net/e1000e/netdev.c
@@ -31,6 +31,7 @@
#include <linux/module.h>
#include <linux/types.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/pci.h>
#include <linux/vmalloc.h>
#include <linux/pagemap.h>
@@ -53,9 +54,9 @@
#include "e1000.h"
-#define DRV_EXTRAVERSION "-k2"
+#define DRV_EXTRAVERSION "-k"
-#define DRV_VERSION "1.3.10" DRV_EXTRAVERSION
+#define DRV_VERSION "1.3.16" DRV_EXTRAVERSION
char e1000e_driver_name[] = "e1000e";
const char e1000e_driver_version[] = DRV_VERSION;
@@ -3346,7 +3347,7 @@
e1000_configure_msix(adapter);
e1000_irq_enable(adapter);
- netif_wake_queue(adapter->netdev);
+ netif_start_queue(adapter->netdev);
/* fire a link change interrupt to start the watchdog */
if (adapter->msix_entries)
@@ -3413,17 +3414,16 @@
e1000e_update_stats(adapter);
spin_unlock(&adapter->stats64_lock);
+ e1000e_flush_descriptors(adapter);
+ e1000_clean_tx_ring(adapter);
+ e1000_clean_rx_ring(adapter);
+
adapter->link_speed = 0;
adapter->link_duplex = 0;
if (!pci_channel_offline(adapter->pdev))
e1000e_reset(adapter);
- e1000e_flush_descriptors(adapter);
-
- e1000_clean_tx_ring(adapter);
- e1000_clean_rx_ring(adapter);
-
/*
* TODO: for power management, we could drop the link and
* pci_disable_device here.
@@ -3833,6 +3833,8 @@
/**
* e1000e_update_phy_stats - Update the PHY statistics counters
* @adapter: board private structure
+ *
+ * Read/clear the upper 16-bit PHY registers and read/accumulate lower
**/
static void e1000e_update_phy_stats(struct e1000_adapter *adapter)
{
@@ -3844,89 +3846,61 @@
if (ret_val)
return;
- hw->phy.addr = 1;
-
-#define HV_PHY_STATS_PAGE 778
/*
* A page set is expensive so check if already on desired page.
* If not, set to the page with the PHY status registers.
*/
+ hw->phy.addr = 1;
ret_val = e1000e_read_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT,
&phy_data);
if (ret_val)
goto release;
- if (phy_data != (HV_PHY_STATS_PAGE << IGP_PAGE_SHIFT)) {
- ret_val = e1000e_write_phy_reg_mdic(hw,
- IGP01E1000_PHY_PAGE_SELECT,
- (HV_PHY_STATS_PAGE <<
- IGP_PAGE_SHIFT));
+ if (phy_data != (HV_STATS_PAGE << IGP_PAGE_SHIFT)) {
+ ret_val = hw->phy.ops.set_page(hw,
+ HV_STATS_PAGE << IGP_PAGE_SHIFT);
if (ret_val)
goto release;
}
- /* Read/clear the upper 16-bit registers and read/accumulate lower */
-
/* Single Collision Count */
- e1000e_read_phy_reg_mdic(hw, HV_SCC_UPPER & MAX_PHY_REG_ADDRESS,
- &phy_data);
- ret_val = e1000e_read_phy_reg_mdic(hw,
- HV_SCC_LOWER & MAX_PHY_REG_ADDRESS,
- &phy_data);
+ hw->phy.ops.read_reg_page(hw, HV_SCC_UPPER, &phy_data);
+ ret_val = hw->phy.ops.read_reg_page(hw, HV_SCC_LOWER, &phy_data);
if (!ret_val)
adapter->stats.scc += phy_data;
/* Excessive Collision Count */
- e1000e_read_phy_reg_mdic(hw, HV_ECOL_UPPER & MAX_PHY_REG_ADDRESS,
- &phy_data);
- ret_val = e1000e_read_phy_reg_mdic(hw,
- HV_ECOL_LOWER & MAX_PHY_REG_ADDRESS,
- &phy_data);
+ hw->phy.ops.read_reg_page(hw, HV_ECOL_UPPER, &phy_data);
+ ret_val = hw->phy.ops.read_reg_page(hw, HV_ECOL_LOWER, &phy_data);
if (!ret_val)
adapter->stats.ecol += phy_data;
/* Multiple Collision Count */
- e1000e_read_phy_reg_mdic(hw, HV_MCC_UPPER & MAX_PHY_REG_ADDRESS,
- &phy_data);
- ret_val = e1000e_read_phy_reg_mdic(hw,
- HV_MCC_LOWER & MAX_PHY_REG_ADDRESS,
- &phy_data);
+ hw->phy.ops.read_reg_page(hw, HV_MCC_UPPER, &phy_data);
+ ret_val = hw->phy.ops.read_reg_page(hw, HV_MCC_LOWER, &phy_data);
if (!ret_val)
adapter->stats.mcc += phy_data;
/* Late Collision Count */
- e1000e_read_phy_reg_mdic(hw, HV_LATECOL_UPPER & MAX_PHY_REG_ADDRESS,
- &phy_data);
- ret_val = e1000e_read_phy_reg_mdic(hw,
- HV_LATECOL_LOWER &
- MAX_PHY_REG_ADDRESS,
- &phy_data);
+ hw->phy.ops.read_reg_page(hw, HV_LATECOL_UPPER, &phy_data);
+ ret_val = hw->phy.ops.read_reg_page(hw, HV_LATECOL_LOWER, &phy_data);
if (!ret_val)
adapter->stats.latecol += phy_data;
/* Collision Count - also used for adaptive IFS */
- e1000e_read_phy_reg_mdic(hw, HV_COLC_UPPER & MAX_PHY_REG_ADDRESS,
- &phy_data);
- ret_val = e1000e_read_phy_reg_mdic(hw,
- HV_COLC_LOWER & MAX_PHY_REG_ADDRESS,
- &phy_data);
+ hw->phy.ops.read_reg_page(hw, HV_COLC_UPPER, &phy_data);
+ ret_val = hw->phy.ops.read_reg_page(hw, HV_COLC_LOWER, &phy_data);
if (!ret_val)
hw->mac.collision_delta = phy_data;
/* Defer Count */
- e1000e_read_phy_reg_mdic(hw, HV_DC_UPPER & MAX_PHY_REG_ADDRESS,
- &phy_data);
- ret_val = e1000e_read_phy_reg_mdic(hw,
- HV_DC_LOWER & MAX_PHY_REG_ADDRESS,
- &phy_data);
+ hw->phy.ops.read_reg_page(hw, HV_DC_UPPER, &phy_data);
+ ret_val = hw->phy.ops.read_reg_page(hw, HV_DC_LOWER, &phy_data);
if (!ret_val)
adapter->stats.dc += phy_data;
/* Transmit with no CRS */
- e1000e_read_phy_reg_mdic(hw, HV_TNCRS_UPPER & MAX_PHY_REG_ADDRESS,
- &phy_data);
- ret_val = e1000e_read_phy_reg_mdic(hw,
- HV_TNCRS_LOWER & MAX_PHY_REG_ADDRESS,
- &phy_data);
+ hw->phy.ops.read_reg_page(hw, HV_TNCRS_UPPER, &phy_data);
+ ret_val = hw->phy.ops.read_reg_page(hw, HV_TNCRS_LOWER, &phy_data);
if (!ret_val)
adapter->stats.tncrs += phy_data;
@@ -5154,21 +5128,34 @@
{
struct e1000_hw *hw = &adapter->hw;
u32 i, mac_reg;
- u16 phy_reg;
+ u16 phy_reg, wuc_enable;
int retval = 0;
/* copy MAC RARs to PHY RARs */
e1000_copy_rx_addrs_to_phy_ich8lan(hw);
- /* copy MAC MTA to PHY MTA */
+ retval = hw->phy.ops.acquire(hw);
+ if (retval) {
+ e_err("Could not acquire PHY\n");
+ return retval;
+ }
+
+ /* Enable access to wakeup registers on and set page to BM_WUC_PAGE */
+ retval = e1000_enable_phy_wakeup_reg_access_bm(hw, &wuc_enable);
+ if (retval)
+ goto out;
+
+ /* copy MAC MTA to PHY MTA - only needed for pchlan */
for (i = 0; i < adapter->hw.mac.mta_reg_count; i++) {
mac_reg = E1000_READ_REG_ARRAY(hw, E1000_MTA, i);
- e1e_wphy(hw, BM_MTA(i), (u16)(mac_reg & 0xFFFF));
- e1e_wphy(hw, BM_MTA(i) + 1, (u16)((mac_reg >> 16) & 0xFFFF));
+ hw->phy.ops.write_reg_page(hw, BM_MTA(i),
+ (u16)(mac_reg & 0xFFFF));
+ hw->phy.ops.write_reg_page(hw, BM_MTA(i) + 1,
+ (u16)((mac_reg >> 16) & 0xFFFF));
}
/* configure PHY Rx Control register */
- e1e_rphy(&adapter->hw, BM_RCTL, &phy_reg);
+ hw->phy.ops.read_reg_page(&adapter->hw, BM_RCTL, &phy_reg);
mac_reg = er32(RCTL);
if (mac_reg & E1000_RCTL_UPE)
phy_reg |= BM_RCTL_UPE;
@@ -5185,31 +5172,19 @@
mac_reg = er32(CTRL);
if (mac_reg & E1000_CTRL_RFCE)
phy_reg |= BM_RCTL_RFCE;
- e1e_wphy(&adapter->hw, BM_RCTL, phy_reg);
+ hw->phy.ops.write_reg_page(&adapter->hw, BM_RCTL, phy_reg);
/* enable PHY wakeup in MAC register */
ew32(WUFC, wufc);
ew32(WUC, E1000_WUC_PHY_WAKE | E1000_WUC_PME_EN);
/* configure and enable PHY wakeup in PHY registers */
- e1e_wphy(&adapter->hw, BM_WUFC, wufc);
- e1e_wphy(&adapter->hw, BM_WUC, E1000_WUC_PME_EN);
+ hw->phy.ops.write_reg_page(&adapter->hw, BM_WUFC, wufc);
+ hw->phy.ops.write_reg_page(&adapter->hw, BM_WUC, E1000_WUC_PME_EN);
/* activate PHY wakeup */
- retval = hw->phy.ops.acquire(hw);
- if (retval) {
- e_err("Could not acquire PHY\n");
- return retval;
- }
- e1000e_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT,
- (BM_WUC_ENABLE_PAGE << IGP_PAGE_SHIFT));
- retval = e1000e_read_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, &phy_reg);
- if (retval) {
- e_err("Could not read PHY page 769\n");
- goto out;
- }
- phy_reg |= BM_WUC_ENABLE_BIT | BM_WUC_HOST_WU_BIT;
- retval = e1000e_write_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, phy_reg);
+ wuc_enable |= BM_WUC_ENABLE_BIT | BM_WUC_HOST_WU_BIT;
+ retval = e1000_disable_phy_wakeup_reg_access_bm(hw, &wuc_enable);
if (retval)
e_err("Could not set PHY Host Wakeup bit\n");
out:
@@ -5277,7 +5252,7 @@
}
if (adapter->flags & FLAG_IS_ICH)
- e1000e_disable_gig_wol_ich8lan(&adapter->hw);
+ e1000_suspend_workarounds_ich8lan(&adapter->hw);
/* Allow time for pending master requests to run */
e1000e_disable_pcie_master(&adapter->hw);
@@ -5343,7 +5318,7 @@
*/
if (adapter->flags & FLAG_IS_QUAD_PORT) {
struct pci_dev *us_dev = pdev->bus->self;
- int pos = pci_find_capability(us_dev, PCI_CAP_ID_EXP);
+ int pos = pci_pcie_cap(us_dev);
u16 devctl;
pci_read_config_word(us_dev, pos + PCI_EXP_DEVCTL, &devctl);
@@ -5428,6 +5403,9 @@
return err;
}
+ if (hw->mac.type == e1000_pch2lan)
+ e1000_resume_workarounds_pchlan(&adapter->hw);
+
e1000e_power_up_phy(adapter);
/* report the system wakeup cause from S3/S4 */
diff --git a/drivers/net/e1000e/phy.c b/drivers/net/e1000e/phy.c
index 484774c..2a6ee13 100644
--- a/drivers/net/e1000e/phy.c
+++ b/drivers/net/e1000e/phy.c
@@ -36,7 +36,7 @@
static s32 e1000_wait_autoneg(struct e1000_hw *hw);
static u32 e1000_get_phy_addr_for_bm_page(u32 page, u32 reg);
static s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset,
- u16 *data, bool read);
+ u16 *data, bool read, bool page_set);
static u32 e1000_get_phy_addr_for_hv_page(u32 page);
static s32 e1000_access_phy_debug_regs_hv(struct e1000_hw *hw, u32 offset,
u16 *data, bool read);
@@ -348,6 +348,24 @@
}
/**
+ * e1000_set_page_igp - Set page as on IGP-like PHY(s)
+ * @hw: pointer to the HW structure
+ * @page: page to set (shifted left when necessary)
+ *
+ * Sets PHY page required for PHY register access. Assumes semaphore is
+ * already acquired. Note, this function sets phy.addr to 1 so the caller
+ * must set it appropriately (if necessary) after this function returns.
+ **/
+s32 e1000_set_page_igp(struct e1000_hw *hw, u16 page)
+{
+ e_dbg("Setting page 0x%x\n", page);
+
+ hw->phy.addr = 1;
+
+ return e1000e_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, page);
+}
+
+/**
* __e1000e_read_phy_reg_igp - Read igp PHY register
* @hw: pointer to the HW structure
* @offset: register offset to be read
@@ -2418,7 +2436,7 @@
/* Page 800 works differently than the rest so it has its own func */
if (page == BM_WUC_PAGE) {
ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, &data,
- false);
+ false, false);
goto out;
}
@@ -2477,7 +2495,7 @@
/* Page 800 works differently than the rest so it has its own func */
if (page == BM_WUC_PAGE) {
ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, data,
- true);
+ true, false);
goto out;
}
@@ -2535,7 +2553,7 @@
/* Page 800 works differently than the rest so it has its own func */
if (page == BM_WUC_PAGE) {
ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, data,
- true);
+ true, false);
goto out;
}
@@ -2579,7 +2597,7 @@
/* Page 800 works differently than the rest so it has its own func */
if (page == BM_WUC_PAGE) {
ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, &data,
- false);
+ false, false);
goto out;
}
@@ -2603,104 +2621,163 @@
}
/**
- * e1000_access_phy_wakeup_reg_bm - Read BM PHY wakeup register
+ * e1000_enable_phy_wakeup_reg_access_bm - enable access to BM wakeup registers
+ * @hw: pointer to the HW structure
+ * @phy_reg: pointer to store original contents of BM_WUC_ENABLE_REG
+ *
+ * Assumes semaphore already acquired and phy_reg points to a valid memory
+ * address to store contents of the BM_WUC_ENABLE_REG register.
+ **/
+s32 e1000_enable_phy_wakeup_reg_access_bm(struct e1000_hw *hw, u16 *phy_reg)
+{
+ s32 ret_val;
+ u16 temp;
+
+ /* All page select, port ctrl and wakeup registers use phy address 1 */
+ hw->phy.addr = 1;
+
+ /* Select Port Control Registers page */
+ ret_val = e1000_set_page_igp(hw, (BM_PORT_CTRL_PAGE << IGP_PAGE_SHIFT));
+ if (ret_val) {
+ e_dbg("Could not set Port Control page\n");
+ goto out;
+ }
+
+ ret_val = e1000e_read_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, phy_reg);
+ if (ret_val) {
+ e_dbg("Could not read PHY register %d.%d\n",
+ BM_PORT_CTRL_PAGE, BM_WUC_ENABLE_REG);
+ goto out;
+ }
+
+ /*
+ * Enable both PHY wakeup mode and Wakeup register page writes.
+ * Prevent a power state change by disabling ME and Host PHY wakeup.
+ */
+ temp = *phy_reg;
+ temp |= BM_WUC_ENABLE_BIT;
+ temp &= ~(BM_WUC_ME_WU_BIT | BM_WUC_HOST_WU_BIT);
+
+ ret_val = e1000e_write_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, temp);
+ if (ret_val) {
+ e_dbg("Could not write PHY register %d.%d\n",
+ BM_PORT_CTRL_PAGE, BM_WUC_ENABLE_REG);
+ goto out;
+ }
+
+ /* Select Host Wakeup Registers page */
+ ret_val = e1000_set_page_igp(hw, (BM_WUC_PAGE << IGP_PAGE_SHIFT));
+
+ /* caller now able to write registers on the Wakeup registers page */
+out:
+ return ret_val;
+}
+
+/**
+ * e1000_disable_phy_wakeup_reg_access_bm - disable access to BM wakeup regs
+ * @hw: pointer to the HW structure
+ * @phy_reg: pointer to original contents of BM_WUC_ENABLE_REG
+ *
+ * Restore BM_WUC_ENABLE_REG to its original value.
+ *
+ * Assumes semaphore already acquired and *phy_reg is the contents of the
+ * BM_WUC_ENABLE_REG before register(s) on BM_WUC_PAGE were accessed by
+ * caller.
+ **/
+s32 e1000_disable_phy_wakeup_reg_access_bm(struct e1000_hw *hw, u16 *phy_reg)
+{
+ s32 ret_val = 0;
+
+ /* Select Port Control Registers page */
+ ret_val = e1000_set_page_igp(hw, (BM_PORT_CTRL_PAGE << IGP_PAGE_SHIFT));
+ if (ret_val) {
+ e_dbg("Could not set Port Control page\n");
+ goto out;
+ }
+
+ /* Restore 769.17 to its original value */
+ ret_val = e1000e_write_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, *phy_reg);
+ if (ret_val)
+ e_dbg("Could not restore PHY register %d.%d\n",
+ BM_PORT_CTRL_PAGE, BM_WUC_ENABLE_REG);
+out:
+ return ret_val;
+}
+
+/**
+ * e1000_access_phy_wakeup_reg_bm - Read/write BM PHY wakeup register
* @hw: pointer to the HW structure
* @offset: register offset to be read or written
* @data: pointer to the data to read or write
* @read: determines if operation is read or write
+ * @page_set: BM_WUC_PAGE already set and access enabled
*
- * Acquires semaphore, if necessary, then reads the PHY register at offset
- * and storing the retrieved information in data. Release any acquired
- * semaphores before exiting. Note that procedure to read the wakeup
- * registers are different. It works as such:
- * 1) Set page 769, register 17, bit 2 = 1
+ * Read the PHY register at offset and store the retrieved information in
+ * data, or write data to PHY register at offset. Note the procedure to
+ * access the PHY wakeup registers is different than reading the other PHY
+ * registers. It works as such:
+ * 1) Set 769.17.2 (page 769, register 17, bit 2) = 1
* 2) Set page to 800 for host (801 if we were manageability)
* 3) Write the address using the address opcode (0x11)
* 4) Read or write the data using the data opcode (0x12)
- * 5) Restore 769_17.2 to its original value
+ * 5) Restore 769.17.2 to its original value
*
- * Assumes semaphore already acquired.
+ * Steps 1 and 2 are done by e1000_enable_phy_wakeup_reg_access_bm() and
+ * step 5 is done by e1000_disable_phy_wakeup_reg_access_bm().
+ *
+ * Assumes semaphore is already acquired. When page_set==true, assumes
+ * the PHY page is set to BM_WUC_PAGE (i.e. a function in the call stack
+ * is responsible for calls to e1000_[enable|disable]_phy_wakeup_reg_bm()).
**/
static s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset,
- u16 *data, bool read)
+ u16 *data, bool read, bool page_set)
{
s32 ret_val;
u16 reg = BM_PHY_REG_NUM(offset);
+ u16 page = BM_PHY_REG_PAGE(offset);
u16 phy_reg = 0;
- /* Gig must be disabled for MDIO accesses to page 800 */
+ /* Gig must be disabled for MDIO accesses to Host Wakeup reg page */
if ((hw->mac.type == e1000_pchlan) &&
- (!(er32(PHY_CTRL) & E1000_PHY_CTRL_GBE_DISABLE)))
- e_dbg("Attempting to access page 800 while gig enabled.\n");
+ (!(er32(PHY_CTRL) & E1000_PHY_CTRL_GBE_DISABLE)))
+ e_dbg("Attempting to access page %d while gig enabled.\n",
+ page);
- /* All operations in this function are phy address 1 */
- hw->phy.addr = 1;
-
- /* Set page 769 */
- e1000e_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT,
- (BM_WUC_ENABLE_PAGE << IGP_PAGE_SHIFT));
-
- ret_val = e1000e_read_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, &phy_reg);
- if (ret_val) {
- e_dbg("Could not read PHY page 769\n");
- goto out;
+ if (!page_set) {
+ /* Enable access to PHY wakeup registers */
+ ret_val = e1000_enable_phy_wakeup_reg_access_bm(hw, &phy_reg);
+ if (ret_val) {
+ e_dbg("Could not enable PHY wakeup reg access\n");
+ goto out;
+ }
}
- /* First clear bit 4 to avoid a power state change */
- phy_reg &= ~(BM_WUC_HOST_WU_BIT);
- ret_val = e1000e_write_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, phy_reg);
- if (ret_val) {
- e_dbg("Could not clear PHY page 769 bit 4\n");
- goto out;
- }
+ e_dbg("Accessing PHY page %d reg 0x%x\n", page, reg);
- /* Write bit 2 = 1, and clear bit 4 to 769_17 */
- ret_val = e1000e_write_phy_reg_mdic(hw, BM_WUC_ENABLE_REG,
- phy_reg | BM_WUC_ENABLE_BIT);
- if (ret_val) {
- e_dbg("Could not write PHY page 769 bit 2\n");
- goto out;
- }
-
- /* Select page 800 */
- ret_val = e1000e_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT,
- (BM_WUC_PAGE << IGP_PAGE_SHIFT));
-
- /* Write the page 800 offset value using opcode 0x11 */
+ /* Write the Wakeup register page offset value using opcode 0x11 */
ret_val = e1000e_write_phy_reg_mdic(hw, BM_WUC_ADDRESS_OPCODE, reg);
if (ret_val) {
- e_dbg("Could not write address opcode to page 800\n");
+ e_dbg("Could not write address opcode to page %d\n", page);
goto out;
}
if (read) {
- /* Read the page 800 value using opcode 0x12 */
+ /* Read the Wakeup register page value using opcode 0x12 */
ret_val = e1000e_read_phy_reg_mdic(hw, BM_WUC_DATA_OPCODE,
data);
} else {
- /* Write the page 800 value using opcode 0x12 */
+ /* Write the Wakeup register page value using opcode 0x12 */
ret_val = e1000e_write_phy_reg_mdic(hw, BM_WUC_DATA_OPCODE,
*data);
}
if (ret_val) {
- e_dbg("Could not access data value from page 800\n");
+ e_dbg("Could not access PHY reg %d.%d\n", page, reg);
goto out;
}
- /*
- * Restore 769_17.2 to its original value
- * Set page 769
- */
- e1000e_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT,
- (BM_WUC_ENABLE_PAGE << IGP_PAGE_SHIFT));
-
- /* Clear 769_17.2 */
- ret_val = e1000e_write_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, phy_reg);
- if (ret_val) {
- e_dbg("Could not clear PHY page 769 bit 2\n");
- goto out;
- }
+ if (!page_set)
+ ret_val = e1000_disable_phy_wakeup_reg_access_bm(hw, &phy_reg);
out:
return ret_val;
@@ -2792,11 +2869,12 @@
* semaphore before exiting.
**/
static s32 __e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data,
- bool locked)
+ bool locked, bool page_set)
{
s32 ret_val;
u16 page = BM_PHY_REG_PAGE(offset);
u16 reg = BM_PHY_REG_NUM(offset);
+ u32 phy_addr = hw->phy.addr = e1000_get_phy_addr_for_hv_page(page);
if (!locked) {
ret_val = hw->phy.ops.acquire(hw);
@@ -2806,8 +2884,8 @@
/* Page 800 works differently than the rest so it has its own func */
if (page == BM_WUC_PAGE) {
- ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset,
- data, true);
+ ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, data,
+ true, page_set);
goto out;
}
@@ -2817,26 +2895,25 @@
goto out;
}
- hw->phy.addr = e1000_get_phy_addr_for_hv_page(page);
+ if (!page_set) {
+ if (page == HV_INTC_FC_PAGE_START)
+ page = 0;
- if (page == HV_INTC_FC_PAGE_START)
- page = 0;
+ if (reg > MAX_PHY_MULTI_PAGE_REG) {
+ /* Page is shifted left, PHY expects (page x 32) */
+ ret_val = e1000_set_page_igp(hw,
+ (page << IGP_PAGE_SHIFT));
- if (reg > MAX_PHY_MULTI_PAGE_REG) {
- u32 phy_addr = hw->phy.addr;
+ hw->phy.addr = phy_addr;
- hw->phy.addr = 1;
-
- /* Page is shifted left, PHY expects (page x 32) */
- ret_val = e1000e_write_phy_reg_mdic(hw,
- IGP01E1000_PHY_PAGE_SELECT,
- (page << IGP_PAGE_SHIFT));
- hw->phy.addr = phy_addr;
-
- if (ret_val)
- goto out;
+ if (ret_val)
+ goto out;
+ }
}
+ e_dbg("reading PHY page %d (or 0x%x shifted) reg 0x%x\n", page,
+ page << IGP_PAGE_SHIFT, reg);
+
ret_val = e1000e_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & reg,
data);
out:
@@ -2858,7 +2935,7 @@
**/
s32 e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data)
{
- return __e1000_read_phy_reg_hv(hw, offset, data, false);
+ return __e1000_read_phy_reg_hv(hw, offset, data, false, false);
}
/**
@@ -2872,7 +2949,21 @@
**/
s32 e1000_read_phy_reg_hv_locked(struct e1000_hw *hw, u32 offset, u16 *data)
{
- return __e1000_read_phy_reg_hv(hw, offset, data, true);
+ return __e1000_read_phy_reg_hv(hw, offset, data, true, false);
+}
+
+/**
+ * e1000_read_phy_reg_page_hv - Read HV PHY register
+ * @hw: pointer to the HW structure
+ * @offset: register offset to write to
+ * @data: data to write at register offset
+ *
+ * Reads the PHY register at offset and stores the retrieved information
+ * in data. Assumes semaphore already acquired and page already set.
+ **/
+s32 e1000_read_phy_reg_page_hv(struct e1000_hw *hw, u32 offset, u16 *data)
+{
+ return __e1000_read_phy_reg_hv(hw, offset, data, true, true);
}
/**
@@ -2886,11 +2977,12 @@
* at the offset. Release any acquired semaphores before exiting.
**/
static s32 __e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data,
- bool locked)
+ bool locked, bool page_set)
{
s32 ret_val;
u16 page = BM_PHY_REG_PAGE(offset);
u16 reg = BM_PHY_REG_NUM(offset);
+ u32 phy_addr = hw->phy.addr = e1000_get_phy_addr_for_hv_page(page);
if (!locked) {
ret_val = hw->phy.ops.acquire(hw);
@@ -2900,8 +2992,8 @@
/* Page 800 works differently than the rest so it has its own func */
if (page == BM_WUC_PAGE) {
- ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset,
- &data, false);
+ ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, &data,
+ false, page_set);
goto out;
}
@@ -2911,41 +3003,40 @@
goto out;
}
- hw->phy.addr = e1000_get_phy_addr_for_hv_page(page);
+ if (!page_set) {
+ if (page == HV_INTC_FC_PAGE_START)
+ page = 0;
- if (page == HV_INTC_FC_PAGE_START)
- page = 0;
+ /*
+ * Workaround MDIO accesses being disabled after entering IEEE
+ * Power Down (when bit 11 of the PHY Control register is set)
+ */
+ if ((hw->phy.type == e1000_phy_82578) &&
+ (hw->phy.revision >= 1) &&
+ (hw->phy.addr == 2) &&
+ ((MAX_PHY_REG_ADDRESS & reg) == 0) && (data & (1 << 11))) {
+ u16 data2 = 0x7EFF;
+ ret_val = e1000_access_phy_debug_regs_hv(hw,
+ (1 << 6) | 0x3,
+ &data2, false);
+ if (ret_val)
+ goto out;
+ }
- /*
- * Workaround MDIO accesses being disabled after entering IEEE Power
- * Down (whenever bit 11 of the PHY Control register is set)
- */
- if ((hw->phy.type == e1000_phy_82578) &&
- (hw->phy.revision >= 1) &&
- (hw->phy.addr == 2) &&
- ((MAX_PHY_REG_ADDRESS & reg) == 0) &&
- (data & (1 << 11))) {
- u16 data2 = 0x7EFF;
- ret_val = e1000_access_phy_debug_regs_hv(hw, (1 << 6) | 0x3,
- &data2, false);
- if (ret_val)
- goto out;
+ if (reg > MAX_PHY_MULTI_PAGE_REG) {
+ /* Page is shifted left, PHY expects (page x 32) */
+ ret_val = e1000_set_page_igp(hw,
+ (page << IGP_PAGE_SHIFT));
+
+ hw->phy.addr = phy_addr;
+
+ if (ret_val)
+ goto out;
+ }
}
- if (reg > MAX_PHY_MULTI_PAGE_REG) {
- u32 phy_addr = hw->phy.addr;
-
- hw->phy.addr = 1;
-
- /* Page is shifted left, PHY expects (page x 32) */
- ret_val = e1000e_write_phy_reg_mdic(hw,
- IGP01E1000_PHY_PAGE_SELECT,
- (page << IGP_PAGE_SHIFT));
- hw->phy.addr = phy_addr;
-
- if (ret_val)
- goto out;
- }
+ e_dbg("writing PHY page %d (or 0x%x shifted) reg 0x%x\n", page,
+ page << IGP_PAGE_SHIFT, reg);
ret_val = e1000e_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & reg,
data);
@@ -2968,7 +3059,7 @@
**/
s32 e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data)
{
- return __e1000_write_phy_reg_hv(hw, offset, data, false);
+ return __e1000_write_phy_reg_hv(hw, offset, data, false, false);
}
/**
@@ -2982,7 +3073,21 @@
**/
s32 e1000_write_phy_reg_hv_locked(struct e1000_hw *hw, u32 offset, u16 data)
{
- return __e1000_write_phy_reg_hv(hw, offset, data, true);
+ return __e1000_write_phy_reg_hv(hw, offset, data, true, false);
+}
+
+/**
+ * e1000_write_phy_reg_page_hv - Write HV PHY register
+ * @hw: pointer to the HW structure
+ * @offset: register offset to write to
+ * @data: data to write at register offset
+ *
+ * Writes the data to PHY register at the offset. Assumes semaphore
+ * already acquired and page already set.
+ **/
+s32 e1000_write_phy_reg_page_hv(struct e1000_hw *hw, u32 offset, u16 data)
+{
+ return __e1000_write_phy_reg_hv(hw, offset, data, true, true);
}
/**
@@ -3004,11 +3109,12 @@
* @hw: pointer to the HW structure
* @offset: register offset to be read or written
* @data: pointer to the data to be read or written
- * @read: determines if operation is read or written
+ * @read: determines if operation is read or write
*
* Reads the PHY register at offset and stores the retreived information
* in data. Assumes semaphore already acquired. Note that the procedure
- * to read these regs uses the address port and data port to read/write.
+ * to access these regs uses the address port and data port to read/write.
+ * These accesses done with PHY address 2 and without using pages.
**/
static s32 e1000_access_phy_debug_regs_hv(struct e1000_hw *hw, u32 offset,
u16 *data, bool read)
@@ -3028,7 +3134,7 @@
/* masking with 0x3F to remove the page from offset */
ret_val = e1000e_write_phy_reg_mdic(hw, addr_reg, (u16)offset & 0x3F);
if (ret_val) {
- e_dbg("Could not write PHY the HV address register\n");
+ e_dbg("Could not write the Address Offset port register\n");
goto out;
}
@@ -3039,7 +3145,7 @@
ret_val = e1000e_write_phy_reg_mdic(hw, data_reg, *data);
if (ret_val) {
- e_dbg("Could not read data value from HV data register\n");
+ e_dbg("Could not access the Data port register\n");
goto out;
}
diff --git a/drivers/net/e2100.c b/drivers/net/e2100.c
index 94ec973..d50a999 100644
--- a/drivers/net/e2100.c
+++ b/drivers/net/e2100.c
@@ -44,6 +44,7 @@
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/delay.h>
#include <asm/io.h>
diff --git a/drivers/net/ehea/ehea_qmr.c b/drivers/net/ehea/ehea_qmr.c
index cd44bb8..95b9f4f 100644
--- a/drivers/net/ehea/ehea_qmr.c
+++ b/drivers/net/ehea/ehea_qmr.c
@@ -331,7 +331,7 @@
unsigned long flags;
spin_lock_irqsave(&eq->spinlock, flags);
- eqe = (struct ehea_eqe *)hw_eqit_eq_get_inc_valid(&eq->hw_queue);
+ eqe = hw_eqit_eq_get_inc_valid(&eq->hw_queue);
spin_unlock_irqrestore(&eq->spinlock, flags);
return eqe;
diff --git a/drivers/net/enic/enic.h b/drivers/net/enic/enic.h
index 38b351c..f0b062b 100644
--- a/drivers/net/enic/enic.h
+++ b/drivers/net/enic/enic.h
@@ -32,7 +32,7 @@
#define DRV_NAME "enic"
#define DRV_DESCRIPTION "Cisco VIC Ethernet NIC Driver"
-#define DRV_VERSION "2.1.1.13"
+#define DRV_VERSION "2.1.1.24"
#define DRV_COPYRIGHT "Copyright 2008-2011 Cisco Systems, Inc"
#define ENIC_BARS_MAX 6
@@ -74,6 +74,7 @@
struct vnic_dev *vdev;
struct timer_list notify_timer;
struct work_struct reset;
+ struct work_struct change_mtu_work;
struct msix_entry msix_entry[ENIC_INTR_MAX];
struct enic_msix_entry msix[ENIC_INTR_MAX];
u32 msg_enable;
diff --git a/drivers/net/enic/enic_dev.c b/drivers/net/enic/enic_dev.c
index 90687b1..fd6247b 100644
--- a/drivers/net/enic/enic_dev.c
+++ b/drivers/net/enic/enic_dev.c
@@ -166,6 +166,17 @@
return err;
}
+int enic_dev_intr_coal_timer_info(struct enic *enic)
+{
+ int err;
+
+ spin_lock(&enic->devcmd_lock);
+ err = vnic_dev_intr_coal_timer_info(enic->vdev);
+ spin_unlock(&enic->devcmd_lock);
+
+ return err;
+}
+
int enic_vnic_dev_deinit(struct enic *enic)
{
int err;
diff --git a/drivers/net/enic/enic_dev.h b/drivers/net/enic/enic_dev.h
index d5f6813..ff8e87f 100644
--- a/drivers/net/enic/enic_dev.h
+++ b/drivers/net/enic/enic_dev.h
@@ -34,6 +34,7 @@
int enic_dev_set_ig_vlan_rewrite_mode(struct enic *enic);
int enic_dev_enable(struct enic *enic);
int enic_dev_disable(struct enic *enic);
+int enic_dev_intr_coal_timer_info(struct enic *enic);
int enic_vnic_dev_deinit(struct enic *enic);
int enic_dev_init_prov2(struct enic *enic, struct vic_provinfo *vp);
int enic_dev_deinit_done(struct enic *enic, int *status);
diff --git a/drivers/net/enic/enic_main.c b/drivers/net/enic/enic_main.c
index 2f433fb..e25800f 100644
--- a/drivers/net/enic/enic_main.c
+++ b/drivers/net/enic/enic_main.c
@@ -23,6 +23,7 @@
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/workqueue.h>
#include <linux/pci.h>
#include <linux/netdevice.h>
@@ -152,12 +153,12 @@
static inline unsigned int enic_msix_rq_intr(struct enic *enic, unsigned int rq)
{
- return rq;
+ return enic->cq[enic_cq_rq(enic, rq)].interrupt_offset;
}
static inline unsigned int enic_msix_wq_intr(struct enic *enic, unsigned int wq)
{
- return enic->rq_count + wq;
+ return enic->cq[enic_cq_wq(enic, wq)].interrupt_offset;
}
static inline unsigned int enic_msix_err_intr(struct enic *enic)
@@ -283,12 +284,10 @@
u32 rx_coalesce_usecs;
unsigned int i, intr;
- tx_coalesce_usecs = min_t(u32,
- INTR_COALESCE_HW_TO_USEC(VNIC_INTR_TIMER_MAX),
- ecmd->tx_coalesce_usecs);
- rx_coalesce_usecs = min_t(u32,
- INTR_COALESCE_HW_TO_USEC(VNIC_INTR_TIMER_MAX),
- ecmd->rx_coalesce_usecs);
+ tx_coalesce_usecs = min_t(u32, ecmd->tx_coalesce_usecs,
+ vnic_dev_get_intr_coal_timer_max(enic->vdev));
+ rx_coalesce_usecs = min_t(u32, ecmd->rx_coalesce_usecs,
+ vnic_dev_get_intr_coal_timer_max(enic->vdev));
switch (vnic_dev_get_intr_mode(enic->vdev)) {
case VNIC_DEV_INTR_MODE_INTX:
@@ -297,26 +296,26 @@
intr = enic_legacy_io_intr();
vnic_intr_coalescing_timer_set(&enic->intr[intr],
- INTR_COALESCE_USEC_TO_HW(tx_coalesce_usecs));
+ tx_coalesce_usecs);
break;
case VNIC_DEV_INTR_MODE_MSI:
if (tx_coalesce_usecs != rx_coalesce_usecs)
return -EINVAL;
vnic_intr_coalescing_timer_set(&enic->intr[0],
- INTR_COALESCE_USEC_TO_HW(tx_coalesce_usecs));
+ tx_coalesce_usecs);
break;
case VNIC_DEV_INTR_MODE_MSIX:
for (i = 0; i < enic->wq_count; i++) {
intr = enic_msix_wq_intr(enic, i);
vnic_intr_coalescing_timer_set(&enic->intr[intr],
- INTR_COALESCE_USEC_TO_HW(tx_coalesce_usecs));
+ tx_coalesce_usecs);
}
for (i = 0; i < enic->rq_count; i++) {
intr = enic_msix_rq_intr(enic, i);
vnic_intr_coalescing_timer_set(&enic->intr[intr],
- INTR_COALESCE_USEC_TO_HW(rx_coalesce_usecs));
+ rx_coalesce_usecs);
}
break;
@@ -423,11 +422,18 @@
if (mtu && mtu != enic->port_mtu) {
enic->port_mtu = mtu;
- if (mtu < netdev->mtu)
- netdev_warn(netdev,
- "interface MTU (%d) set higher "
- "than switch port MTU (%d)\n",
- netdev->mtu, mtu);
+ if (enic_is_dynamic(enic)) {
+ mtu = max_t(int, ENIC_MIN_MTU,
+ min_t(int, ENIC_MAX_MTU, mtu));
+ if (mtu != netdev->mtu)
+ schedule_work(&enic->change_mtu_work);
+ } else {
+ if (mtu < netdev->mtu)
+ netdev_warn(netdev,
+ "interface MTU (%d) set higher "
+ "than switch port MTU (%d)\n",
+ netdev->mtu, mtu);
+ }
}
}
@@ -793,10 +799,10 @@
}
/* dev_base_lock rwlock held, nominally process context */
-static struct net_device_stats *enic_get_stats(struct net_device *netdev)
+static struct rtnl_link_stats64 *enic_get_stats(struct net_device *netdev,
+ struct rtnl_link_stats64 *net_stats)
{
struct enic *enic = netdev_priv(netdev);
- struct net_device_stats *net_stats = &netdev->stats;
struct vnic_stats *stats;
enic_dev_stats_dump(enic, &stats);
@@ -1258,8 +1264,7 @@
skb->dev = netdev;
- if (enic->vlan_group && vlan_stripped &&
- (vlan_tci & CQ_ENET_RQ_DESC_VLAN_TCI_VLAN_MASK)) {
+ if (vlan_stripped) {
if (netdev->features & NETIF_F_GRO)
vlan_gro_receive(&enic->napi[q_number],
@@ -1560,7 +1565,7 @@
default:
/* Using intr for notification for INTx/MSI-X */
break;
- };
+ }
}
/* rtnl lock is held, process context */
@@ -1688,6 +1693,9 @@
if (new_mtu < ENIC_MIN_MTU || new_mtu > ENIC_MAX_MTU)
return -EINVAL;
+ if (enic_is_dynamic(enic))
+ return -EOPNOTSUPP;
+
if (running)
enic_stop(netdev);
@@ -1704,6 +1712,55 @@
return 0;
}
+static void enic_change_mtu_work(struct work_struct *work)
+{
+ struct enic *enic = container_of(work, struct enic, change_mtu_work);
+ struct net_device *netdev = enic->netdev;
+ int new_mtu = vnic_dev_mtu(enic->vdev);
+ int err;
+ unsigned int i;
+
+ new_mtu = max_t(int, ENIC_MIN_MTU, min_t(int, ENIC_MAX_MTU, new_mtu));
+
+ rtnl_lock();
+
+ /* Stop RQ */
+ del_timer_sync(&enic->notify_timer);
+
+ for (i = 0; i < enic->rq_count; i++)
+ napi_disable(&enic->napi[i]);
+
+ vnic_intr_mask(&enic->intr[0]);
+ enic_synchronize_irqs(enic);
+ err = vnic_rq_disable(&enic->rq[0]);
+ if (err) {
+ netdev_err(netdev, "Unable to disable RQ.\n");
+ return;
+ }
+ vnic_rq_clean(&enic->rq[0], enic_free_rq_buf);
+ vnic_cq_clean(&enic->cq[0]);
+ vnic_intr_clean(&enic->intr[0]);
+
+ /* Fill RQ with new_mtu-sized buffers */
+ netdev->mtu = new_mtu;
+ vnic_rq_fill(&enic->rq[0], enic_rq_alloc_buf);
+ /* Need at least one buffer on ring to get going */
+ if (vnic_rq_desc_used(&enic->rq[0]) == 0) {
+ netdev_err(netdev, "Unable to alloc receive buffers.\n");
+ return;
+ }
+
+ /* Start RQ */
+ vnic_rq_enable(&enic->rq[0]);
+ napi_enable(&enic->napi[0]);
+ vnic_intr_unmask(&enic->intr[0]);
+ enic_notify_timer_start(enic);
+
+ rtnl_unlock();
+
+ netdev_info(netdev, "interface MTU set as %d\n", netdev->mtu);
+}
+
#ifdef CONFIG_NET_POLL_CONTROLLER
static void enic_poll_controller(struct net_device *netdev)
{
@@ -1718,8 +1775,12 @@
enic_isr_msix_rq(enic->msix_entry[intr].vector,
&enic->napi[i]);
}
- intr = enic_msix_wq_intr(enic, i);
- enic_isr_msix_wq(enic->msix_entry[intr].vector, enic);
+
+ for (i = 0; i < enic->wq_count; i++) {
+ intr = enic_msix_wq_intr(enic, i);
+ enic_isr_msix_wq(enic->msix_entry[intr].vector, enic);
+ }
+
break;
case VNIC_DEV_INTR_MODE_MSI:
enic_isr_msi(enic->pdev->irq, enic);
@@ -2057,7 +2118,7 @@
.ndo_open = enic_open,
.ndo_stop = enic_stop,
.ndo_start_xmit = enic_hard_start_xmit,
- .ndo_get_stats = enic_get_stats,
+ .ndo_get_stats64 = enic_get_stats,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_rx_mode = enic_set_rx_mode,
.ndo_set_multicast_list = enic_set_rx_mode,
@@ -2079,7 +2140,7 @@
.ndo_open = enic_open,
.ndo_stop = enic_stop,
.ndo_start_xmit = enic_hard_start_xmit,
- .ndo_get_stats = enic_get_stats,
+ .ndo_get_stats64 = enic_get_stats,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = enic_set_mac_address,
.ndo_set_rx_mode = enic_set_rx_mode,
@@ -2112,6 +2173,14 @@
unsigned int i;
int err;
+ /* Get interrupt coalesce timer info */
+ err = enic_dev_intr_coal_timer_info(enic);
+ if (err) {
+ dev_warn(dev, "Using default conversion factor for "
+ "interrupt coalesce timer\n");
+ vnic_dev_intr_coal_timer_info_default(enic->vdev);
+ }
+
/* Get vNIC configuration
*/
@@ -2345,6 +2414,7 @@
enic->notify_timer.data = (unsigned long)enic;
INIT_WORK(&enic->reset, enic_reset);
+ INIT_WORK(&enic->change_mtu_work, enic_change_mtu_work);
for (i = 0; i < enic->wq_count; i++)
spin_lock_init(&enic->wq_lock[i]);
@@ -2427,6 +2497,7 @@
struct enic *enic = netdev_priv(netdev);
cancel_work_sync(&enic->reset);
+ cancel_work_sync(&enic->change_mtu_work);
unregister_netdev(netdev);
enic_dev_deinit(enic);
vnic_dev_close(enic->vdev);
diff --git a/drivers/net/enic/enic_res.c b/drivers/net/enic/enic_res.c
index 6e5c635..4a35367 100644
--- a/drivers/net/enic/enic_res.c
+++ b/drivers/net/enic/enic_res.c
@@ -90,18 +90,30 @@
max_t(u16, ENIC_MIN_MTU,
c->mtu));
- c->intr_timer_usec = min_t(u32,
- INTR_COALESCE_HW_TO_USEC(VNIC_INTR_TIMER_MAX),
- c->intr_timer_usec);
+ c->intr_timer_usec = min_t(u32, c->intr_timer_usec,
+ vnic_dev_get_intr_coal_timer_max(enic->vdev));
dev_info(enic_get_dev(enic),
"vNIC MAC addr %pM wq/rq %d/%d mtu %d\n",
enic->mac_addr, c->wq_desc_count, c->rq_desc_count, c->mtu);
- dev_info(enic_get_dev(enic), "vNIC csum tx/rx %d/%d "
- "tso %d intr timer %d usec rss %d\n",
- ENIC_SETTING(enic, TXCSUM), ENIC_SETTING(enic, RXCSUM),
- ENIC_SETTING(enic, TSO),
- c->intr_timer_usec, ENIC_SETTING(enic, RSS));
+
+ dev_info(enic_get_dev(enic), "vNIC csum tx/rx %s/%s "
+ "tso/lro %s/%s rss %s intr mode %s type %s timer %d usec "
+ "loopback tag 0x%04x\n",
+ ENIC_SETTING(enic, TXCSUM) ? "yes" : "no",
+ ENIC_SETTING(enic, RXCSUM) ? "yes" : "no",
+ ENIC_SETTING(enic, TSO) ? "yes" : "no",
+ ENIC_SETTING(enic, LRO) ? "yes" : "no",
+ ENIC_SETTING(enic, RSS) ? "yes" : "no",
+ c->intr_mode == VENET_INTR_MODE_INTX ? "INTx" :
+ c->intr_mode == VENET_INTR_MODE_MSI ? "MSI" :
+ c->intr_mode == VENET_INTR_MODE_ANY ? "any" :
+ "unknown",
+ c->intr_timer_type == VENET_INTR_TYPE_MIN ? "min" :
+ c->intr_timer_type == VENET_INTR_TYPE_IDLE ? "idle" :
+ "unknown",
+ c->intr_timer_usec,
+ c->loop_tag);
return 0;
}
@@ -290,7 +302,7 @@
for (i = 0; i < enic->intr_count; i++) {
vnic_intr_init(&enic->intr[i],
- INTR_COALESCE_USEC_TO_HW(enic->config.intr_timer_usec),
+ enic->config.intr_timer_usec,
enic->config.intr_timer_type,
mask_on_assertion);
}
diff --git a/drivers/net/enic/vnic_cq.c b/drivers/net/enic/vnic_cq.c
index b86d6ef..0daa1c7 100644
--- a/drivers/net/enic/vnic_cq.c
+++ b/drivers/net/enic/vnic_cq.c
@@ -74,6 +74,8 @@
iowrite32(cq_message_enable, &cq->ctrl->cq_message_enable);
iowrite32(interrupt_offset, &cq->ctrl->interrupt_offset);
writeq(cq_message_addr, &cq->ctrl->cq_message_addr);
+
+ cq->interrupt_offset = interrupt_offset;
}
void vnic_cq_clean(struct vnic_cq *cq)
diff --git a/drivers/net/enic/vnic_cq.h b/drivers/net/enic/vnic_cq.h
index 552d3da..579315c 100644
--- a/drivers/net/enic/vnic_cq.h
+++ b/drivers/net/enic/vnic_cq.h
@@ -57,6 +57,7 @@
struct vnic_dev_ring ring;
unsigned int to_clean;
unsigned int last_color;
+ unsigned int interrupt_offset;
};
static inline unsigned int vnic_cq_service(struct vnic_cq *cq,
diff --git a/drivers/net/enic/vnic_dev.c b/drivers/net/enic/vnic_dev.c
index 68f24ae..8c4c8cf 100644
--- a/drivers/net/enic/vnic_dev.c
+++ b/drivers/net/enic/vnic_dev.c
@@ -40,6 +40,12 @@
unsigned int count;
};
+struct vnic_intr_coal_timer_info {
+ u32 mul;
+ u32 div;
+ u32 max_usec;
+};
+
struct vnic_dev {
void *priv;
struct pci_dev *pdev;
@@ -58,6 +64,7 @@
enum vnic_proxy_type proxy;
u32 proxy_index;
u64 args[VNIC_DEVCMD_NARGS];
+ struct vnic_intr_coal_timer_info intr_coal_timer_info;
};
#define VNIC_MAX_RES_HDR_SIZE \
@@ -794,6 +801,42 @@
return vnic_dev_cmd(vdev, CMD_DEINIT, &a0, &a1, wait);
}
+void vnic_dev_intr_coal_timer_info_default(struct vnic_dev *vdev)
+{
+ /* Default: hardware intr coal timer is in units of 1.5 usecs */
+ vdev->intr_coal_timer_info.mul = 2;
+ vdev->intr_coal_timer_info.div = 3;
+ vdev->intr_coal_timer_info.max_usec =
+ vnic_dev_intr_coal_timer_hw_to_usec(vdev, 0xffff);
+}
+
+int vnic_dev_intr_coal_timer_info(struct vnic_dev *vdev)
+{
+ int wait = 1000;
+ int err;
+
+ memset(vdev->args, 0, sizeof(vdev->args));
+
+ err = _vnic_dev_cmd(vdev, CMD_INTR_COAL_CONVERT, wait);
+
+ /* Use defaults when firmware doesn't support the devcmd at all or
+ * supports it for only specific hardware
+ */
+ if ((err == ERR_ECMDUNKNOWN) ||
+ (!err && !(vdev->args[0] && vdev->args[1] && vdev->args[2]))) {
+ pr_warning("Using default conversion factor for "
+ "interrupt coalesce timer\n");
+ vnic_dev_intr_coal_timer_info_default(vdev);
+ return 0;
+ }
+
+ vdev->intr_coal_timer_info.mul = (u32) vdev->args[0];
+ vdev->intr_coal_timer_info.div = (u32) vdev->args[1];
+ vdev->intr_coal_timer_info.max_usec = (u32) vdev->args[2];
+
+ return err;
+}
+
int vnic_dev_link_status(struct vnic_dev *vdev)
{
if (!vnic_dev_notify_ready(vdev))
@@ -838,6 +881,23 @@
return vdev->intr_mode;
}
+u32 vnic_dev_intr_coal_timer_usec_to_hw(struct vnic_dev *vdev, u32 usec)
+{
+ return (usec * vdev->intr_coal_timer_info.mul) /
+ vdev->intr_coal_timer_info.div;
+}
+
+u32 vnic_dev_intr_coal_timer_hw_to_usec(struct vnic_dev *vdev, u32 hw_cycles)
+{
+ return (hw_cycles * vdev->intr_coal_timer_info.div) /
+ vdev->intr_coal_timer_info.mul;
+}
+
+u32 vnic_dev_get_intr_coal_timer_max(struct vnic_dev *vdev)
+{
+ return vdev->intr_coal_timer_info.max_usec;
+}
+
void vnic_dev_unregister(struct vnic_dev *vdev)
{
if (vdev) {
diff --git a/drivers/net/enic/vnic_dev.h b/drivers/net/enic/vnic_dev.h
index cf482a2..852b698 100644
--- a/drivers/net/enic/vnic_dev.h
+++ b/drivers/net/enic/vnic_dev.h
@@ -109,11 +109,16 @@
int vnic_dev_open_done(struct vnic_dev *vdev, int *done);
int vnic_dev_init(struct vnic_dev *vdev, int arg);
int vnic_dev_deinit(struct vnic_dev *vdev);
+void vnic_dev_intr_coal_timer_info_default(struct vnic_dev *vdev);
+int vnic_dev_intr_coal_timer_info(struct vnic_dev *vdev);
int vnic_dev_hang_reset(struct vnic_dev *vdev, int arg);
int vnic_dev_hang_reset_done(struct vnic_dev *vdev, int *done);
void vnic_dev_set_intr_mode(struct vnic_dev *vdev,
enum vnic_dev_intr_mode intr_mode);
enum vnic_dev_intr_mode vnic_dev_get_intr_mode(struct vnic_dev *vdev);
+u32 vnic_dev_intr_coal_timer_usec_to_hw(struct vnic_dev *vdev, u32 usec);
+u32 vnic_dev_intr_coal_timer_hw_to_usec(struct vnic_dev *vdev, u32 hw_cycles);
+u32 vnic_dev_get_intr_coal_timer_max(struct vnic_dev *vdev);
void vnic_dev_unregister(struct vnic_dev *vdev);
int vnic_dev_set_ig_vlan_rewrite_mode(struct vnic_dev *vdev,
u8 ig_vlan_rewrite_mode);
diff --git a/drivers/net/enic/vnic_devcmd.h b/drivers/net/enic/vnic_devcmd.h
index c5569bf..8025e88 100644
--- a/drivers/net/enic/vnic_devcmd.h
+++ b/drivers/net/enic/vnic_devcmd.h
@@ -318,6 +318,25 @@
* ERR_EINPROGRESS - command in a0 is still in progress
*/
CMD_STATUS = _CMDC(_CMD_DIR_RW, _CMD_VTYPE_ALL, 49),
+
+ /*
+ * Returns interrupt coalescing timer conversion factors.
+ * After calling this devcmd, ENIC driver can convert
+ * interrupt coalescing timer in usec into CPU cycles as follows:
+ *
+ * intr_timer_cycles = intr_timer_usec * multiplier / divisor
+ *
+ * Interrupt coalescing timer in usecs can be obtained from
+ * CPU cycles as follows:
+ *
+ * intr_timer_usec = intr_timer_cycles * divisor / multiplier
+ *
+ * in: none
+ * out: (u32)a0 = multiplier
+ * (u32)a1 = divisor
+ * (u32)a2 = maximum timer value in usec
+ */
+ CMD_INTR_COAL_CONVERT = _CMDC(_CMD_DIR_READ, _CMD_VTYPE_ALL, 50),
};
/* CMD_ENABLE2 flags */
diff --git a/drivers/net/enic/vnic_enet.h b/drivers/net/enic/vnic_enet.h
index e8740e3..6095428 100644
--- a/drivers/net/enic/vnic_enet.h
+++ b/drivers/net/enic/vnic_enet.h
@@ -20,10 +20,6 @@
#ifndef _VNIC_ENIC_H_
#define _VNIC_ENIC_H_
-/* Hardware intr coalesce timer is in units of 1.5us */
-#define INTR_COALESCE_USEC_TO_HW(usec) ((usec) * 2/3)
-#define INTR_COALESCE_HW_TO_USEC(usec) ((usec) * 3/2)
-
/* Device-specific region: enet configuration */
struct vnic_enet_config {
u32 flags;
@@ -51,4 +47,11 @@
#define VENETF_RSSHASH_TCPIPV6_EX 0x400 /* Hash on TCP + IPv6 ext. fields */
#define VENETF_LOOP 0x800 /* Loopback enabled */
+#define VENET_INTR_TYPE_MIN 0 /* Timer specs min interrupt spacing */
+#define VENET_INTR_TYPE_IDLE 1 /* Timer specs idle time before irq */
+
+#define VENET_INTR_MODE_ANY 0 /* Try MSI-X, then MSI, then INTx */
+#define VENET_INTR_MODE_MSI 1 /* Try MSI then INTx */
+#define VENET_INTR_MODE_INTX 2 /* Try INTx only */
+
#endif /* _VNIC_ENIC_H_ */
diff --git a/drivers/net/enic/vnic_intr.c b/drivers/net/enic/vnic_intr.c
index 3873771..0ca107f 100644
--- a/drivers/net/enic/vnic_intr.c
+++ b/drivers/net/enic/vnic_intr.c
@@ -46,7 +46,7 @@
return 0;
}
-void vnic_intr_init(struct vnic_intr *intr, unsigned int coalescing_timer,
+void vnic_intr_init(struct vnic_intr *intr, u32 coalescing_timer,
unsigned int coalescing_type, unsigned int mask_on_assertion)
{
vnic_intr_coalescing_timer_set(intr, coalescing_timer);
@@ -56,9 +56,10 @@
}
void vnic_intr_coalescing_timer_set(struct vnic_intr *intr,
- unsigned int coalescing_timer)
+ u32 coalescing_timer)
{
- iowrite32(coalescing_timer, &intr->ctrl->coalescing_timer);
+ iowrite32(vnic_dev_intr_coal_timer_usec_to_hw(intr->vdev,
+ coalescing_timer), &intr->ctrl->coalescing_timer);
}
void vnic_intr_clean(struct vnic_intr *intr)
diff --git a/drivers/net/enic/vnic_intr.h b/drivers/net/enic/vnic_intr.h
index 09dc0b7..2b16363 100644
--- a/drivers/net/enic/vnic_intr.h
+++ b/drivers/net/enic/vnic_intr.h
@@ -24,8 +24,6 @@
#include "vnic_dev.h"
-#define VNIC_INTR_TIMER_MAX 0xffff
-
#define VNIC_INTR_TIMER_TYPE_ABS 0
#define VNIC_INTR_TIMER_TYPE_QUIET 1
@@ -104,10 +102,10 @@
void vnic_intr_free(struct vnic_intr *intr);
int vnic_intr_alloc(struct vnic_dev *vdev, struct vnic_intr *intr,
unsigned int index);
-void vnic_intr_init(struct vnic_intr *intr, unsigned int coalescing_timer,
+void vnic_intr_init(struct vnic_intr *intr, u32 coalescing_timer,
unsigned int coalescing_type, unsigned int mask_on_assertion);
void vnic_intr_coalescing_timer_set(struct vnic_intr *intr,
- unsigned int coalescing_timer);
+ u32 coalescing_timer);
void vnic_intr_clean(struct vnic_intr *intr);
#endif /* _VNIC_INTR_H_ */
diff --git a/drivers/net/epic100.c b/drivers/net/epic100.c
index c353bf3..814c187 100644
--- a/drivers/net/epic100.c
+++ b/drivers/net/epic100.c
@@ -391,13 +391,13 @@
ring_space = pci_alloc_consistent(pdev, TX_TOTAL_SIZE, &ring_dma);
if (!ring_space)
goto err_out_iounmap;
- ep->tx_ring = (struct epic_tx_desc *)ring_space;
+ ep->tx_ring = ring_space;
ep->tx_ring_dma = ring_dma;
ring_space = pci_alloc_consistent(pdev, RX_TOTAL_SIZE, &ring_dma);
if (!ring_space)
goto err_out_unmap_tx;
- ep->rx_ring = (struct epic_rx_desc *)ring_space;
+ ep->rx_ring = ring_space;
ep->rx_ring_dma = ring_dma;
if (dev->mem_start) {
diff --git a/drivers/net/es3210.c b/drivers/net/es3210.c
index 0ba5e7b..7a09575 100644
--- a/drivers/net/es3210.c
+++ b/drivers/net/es3210.c
@@ -54,6 +54,7 @@
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
diff --git a/drivers/net/ethoc.c b/drivers/net/ethoc.c
index a83dd31..0da6295 100644
--- a/drivers/net/ethoc.c
+++ b/drivers/net/ethoc.c
@@ -11,8 +11,10 @@
* Written by Thierry Reding <thierry.reding@avionic-design.de>
*/
+#include <linux/dma-mapping.h>
#include <linux/etherdevice.h>
#include <linux/crc32.h>
+#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/mii.h>
#include <linux/phy.h>
@@ -874,6 +876,7 @@
}
spin_unlock_irq(&priv->lock);
+ skb_tx_timestamp(skb);
out:
dev_kfree_skb(skb);
return NETDEV_TX_OK;
diff --git a/drivers/net/ewrk3.c b/drivers/net/ewrk3.c
index b5f6173..d1e229f 100644
--- a/drivers/net/ewrk3.c
+++ b/drivers/net/ewrk3.c
@@ -1008,15 +1008,13 @@
}
}
p = skb->data; /* Look at the dest addr */
- if (p[0] & 0x01) { /* Multicast/Broadcast */
- if ((*(s16 *) & p[0] == -1) && (*(s16 *) & p[2] == -1) && (*(s16 *) & p[4] == -1)) {
+ if (is_multicast_ether_addr(p)) {
+ if (is_broadcast_ether_addr(p)) {
lp->pktStats.broadcast++;
} else {
lp->pktStats.multicast++;
}
- } else if ((*(s16 *) & p[0] == *(s16 *) & dev->dev_addr[0]) &&
- (*(s16 *) & p[2] == *(s16 *) & dev->dev_addr[2]) &&
- (*(s16 *) & p[4] == *(s16 *) & dev->dev_addr[4])) {
+ } else if (compare_ether_addr(p, dev->dev_addr) == 0) {
lp->pktStats.unicast++;
}
lp->pktStats.bins[0]++; /* Duplicates stats.rx_packets */
diff --git a/drivers/net/fealnx.c b/drivers/net/fealnx.c
index dd54abe..fa8677c 100644
--- a/drivers/net/fealnx.c
+++ b/drivers/net/fealnx.c
@@ -566,7 +566,7 @@
err = -ENOMEM;
goto err_out_free_dev;
}
- np->rx_ring = (struct fealnx_desc *)ring_space;
+ np->rx_ring = ring_space;
np->rx_ring_dma = ring_dma;
ring_space = pci_alloc_consistent(pdev, TX_TOTAL_SIZE, &ring_dma);
@@ -574,7 +574,7 @@
err = -ENOMEM;
goto err_out_free_rx;
}
- np->tx_ring = (struct fealnx_desc *)ring_space;
+ np->tx_ring = ring_space;
np->tx_ring_dma = ring_dma;
/* find the connected MII xcvrs */
diff --git a/drivers/net/fec.c b/drivers/net/fec.c
index 885d8ba..7ae3f28 100644
--- a/drivers/net/fec.c
+++ b/drivers/net/fec.c
@@ -324,6 +324,8 @@
fep->cur_tx = bdp;
+ skb_tx_timestamp(skb);
+
spin_unlock_irqrestore(&fep->hw_lock, flags);
return NETDEV_TX_OK;
@@ -650,7 +652,8 @@
skb_put(skb, pkt_len - 4); /* Make room */
skb_copy_to_linear_data(skb, data, pkt_len - 4);
skb->protocol = eth_type_trans(skb, ndev);
- netif_rx(skb);
+ if (!skb_defer_rx_timestamp(skb))
+ netif_rx(skb);
}
bdp->cbd_bufaddr = dma_map_single(&fep->pdev->dev, data,
diff --git a/drivers/net/fec_mpc52xx.c b/drivers/net/fec_mpc52xx.c
index 9f81b1a..381bdea 100644
--- a/drivers/net/fec_mpc52xx.c
+++ b/drivers/net/fec_mpc52xx.c
@@ -14,6 +14,7 @@
*
*/
+#include <linux/dma-mapping.h>
#include <linux/module.h>
#include <linux/kernel.h>
@@ -22,6 +23,7 @@
#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/crc32.h>
#include <linux/hardirq.h>
#include <linux/delay.h>
@@ -335,6 +337,7 @@
bd->skb_pa = dma_map_single(dev->dev.parent, skb->data, skb->len,
DMA_TO_DEVICE);
+ skb_tx_timestamp(skb);
bcom_submit_next_buffer(priv->tx_dmatsk, skb);
spin_unlock_irqrestore(&priv->lock, flags);
@@ -434,7 +437,8 @@
length = status & BCOM_FEC_RX_BD_LEN_MASK;
skb_put(rskb, length - 4); /* length without CRC32 */
rskb->protocol = eth_type_trans(rskb, dev);
- netif_rx(rskb);
+ if (!skb_defer_rx_timestamp(skb))
+ netif_rx(rskb);
spin_lock(&priv->lock);
}
diff --git a/drivers/net/fs_enet/fs_enet-main.c b/drivers/net/fs_enet/fs_enet-main.c
index 21abb5c..329ef23 100644
--- a/drivers/net/fs_enet/fs_enet-main.c
+++ b/drivers/net/fs_enet/fs_enet-main.c
@@ -697,6 +697,8 @@
sc |= BD_ENET_TX_PAD;
CBDS_SC(bdp, sc);
+ skb_tx_timestamp(skb);
+
(*fep->ops->tx_kickstart)(dev);
spin_unlock_irqrestore(&fep->tx_lock, flags);
diff --git a/drivers/net/ftgmac100.c b/drivers/net/ftgmac100.c
new file mode 100644
index 0000000..54709af
--- /dev/null
+++ b/drivers/net/ftgmac100.c
@@ -0,0 +1,1365 @@
+/*
+ * Faraday FTGMAC100 Gigabit Ethernet
+ *
+ * (C) Copyright 2009-2011 Faraday Technology
+ * Po-Yu Chuang <ratbert@faraday-tech.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/dma-mapping.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/phy.h>
+#include <linux/platform_device.h>
+#include <net/ip.h>
+
+#include "ftgmac100.h"
+
+#define DRV_NAME "ftgmac100"
+#define DRV_VERSION "0.7"
+
+#define RX_QUEUE_ENTRIES 256 /* must be power of 2 */
+#define TX_QUEUE_ENTRIES 512 /* must be power of 2 */
+
+#define MAX_PKT_SIZE 1518
+#define RX_BUF_SIZE PAGE_SIZE /* must be smaller than 0x3fff */
+
+/******************************************************************************
+ * private data
+ *****************************************************************************/
+struct ftgmac100_descs {
+ struct ftgmac100_rxdes rxdes[RX_QUEUE_ENTRIES];
+ struct ftgmac100_txdes txdes[TX_QUEUE_ENTRIES];
+};
+
+struct ftgmac100 {
+ struct resource *res;
+ void __iomem *base;
+ int irq;
+
+ struct ftgmac100_descs *descs;
+ dma_addr_t descs_dma_addr;
+
+ unsigned int rx_pointer;
+ unsigned int tx_clean_pointer;
+ unsigned int tx_pointer;
+ unsigned int tx_pending;
+
+ spinlock_t tx_lock;
+
+ struct net_device *netdev;
+ struct device *dev;
+ struct napi_struct napi;
+
+ struct mii_bus *mii_bus;
+ int phy_irq[PHY_MAX_ADDR];
+ struct phy_device *phydev;
+ int old_speed;
+};
+
+static int ftgmac100_alloc_rx_page(struct ftgmac100 *priv,
+ struct ftgmac100_rxdes *rxdes, gfp_t gfp);
+
+/******************************************************************************
+ * internal functions (hardware register access)
+ *****************************************************************************/
+#define INT_MASK_ALL_ENABLED (FTGMAC100_INT_RPKT_LOST | \
+ FTGMAC100_INT_XPKT_ETH | \
+ FTGMAC100_INT_XPKT_LOST | \
+ FTGMAC100_INT_AHB_ERR | \
+ FTGMAC100_INT_PHYSTS_CHG | \
+ FTGMAC100_INT_RPKT_BUF | \
+ FTGMAC100_INT_NO_RXBUF)
+
+static void ftgmac100_set_rx_ring_base(struct ftgmac100 *priv, dma_addr_t addr)
+{
+ iowrite32(addr, priv->base + FTGMAC100_OFFSET_RXR_BADR);
+}
+
+static void ftgmac100_set_rx_buffer_size(struct ftgmac100 *priv,
+ unsigned int size)
+{
+ size = FTGMAC100_RBSR_SIZE(size);
+ iowrite32(size, priv->base + FTGMAC100_OFFSET_RBSR);
+}
+
+static void ftgmac100_set_normal_prio_tx_ring_base(struct ftgmac100 *priv,
+ dma_addr_t addr)
+{
+ iowrite32(addr, priv->base + FTGMAC100_OFFSET_NPTXR_BADR);
+}
+
+static void ftgmac100_txdma_normal_prio_start_polling(struct ftgmac100 *priv)
+{
+ iowrite32(1, priv->base + FTGMAC100_OFFSET_NPTXPD);
+}
+
+static int ftgmac100_reset_hw(struct ftgmac100 *priv)
+{
+ struct net_device *netdev = priv->netdev;
+ int i;
+
+ /* NOTE: reset clears all registers */
+ iowrite32(FTGMAC100_MACCR_SW_RST, priv->base + FTGMAC100_OFFSET_MACCR);
+ for (i = 0; i < 5; i++) {
+ unsigned int maccr;
+
+ maccr = ioread32(priv->base + FTGMAC100_OFFSET_MACCR);
+ if (!(maccr & FTGMAC100_MACCR_SW_RST))
+ return 0;
+
+ udelay(1000);
+ }
+
+ netdev_err(netdev, "software reset failed\n");
+ return -EIO;
+}
+
+static void ftgmac100_set_mac(struct ftgmac100 *priv, const unsigned char *mac)
+{
+ unsigned int maddr = mac[0] << 8 | mac[1];
+ unsigned int laddr = mac[2] << 24 | mac[3] << 16 | mac[4] << 8 | mac[5];
+
+ iowrite32(maddr, priv->base + FTGMAC100_OFFSET_MAC_MADR);
+ iowrite32(laddr, priv->base + FTGMAC100_OFFSET_MAC_LADR);
+}
+
+static void ftgmac100_init_hw(struct ftgmac100 *priv)
+{
+ /* setup ring buffer base registers */
+ ftgmac100_set_rx_ring_base(priv,
+ priv->descs_dma_addr +
+ offsetof(struct ftgmac100_descs, rxdes));
+ ftgmac100_set_normal_prio_tx_ring_base(priv,
+ priv->descs_dma_addr +
+ offsetof(struct ftgmac100_descs, txdes));
+
+ ftgmac100_set_rx_buffer_size(priv, RX_BUF_SIZE);
+
+ iowrite32(FTGMAC100_APTC_RXPOLL_CNT(1), priv->base + FTGMAC100_OFFSET_APTC);
+
+ ftgmac100_set_mac(priv, priv->netdev->dev_addr);
+}
+
+#define MACCR_ENABLE_ALL (FTGMAC100_MACCR_TXDMA_EN | \
+ FTGMAC100_MACCR_RXDMA_EN | \
+ FTGMAC100_MACCR_TXMAC_EN | \
+ FTGMAC100_MACCR_RXMAC_EN | \
+ FTGMAC100_MACCR_FULLDUP | \
+ FTGMAC100_MACCR_CRC_APD | \
+ FTGMAC100_MACCR_RX_RUNT | \
+ FTGMAC100_MACCR_RX_BROADPKT)
+
+static void ftgmac100_start_hw(struct ftgmac100 *priv, int speed)
+{
+ int maccr = MACCR_ENABLE_ALL;
+
+ switch (speed) {
+ default:
+ case 10:
+ break;
+
+ case 100:
+ maccr |= FTGMAC100_MACCR_FAST_MODE;
+ break;
+
+ case 1000:
+ maccr |= FTGMAC100_MACCR_GIGA_MODE;
+ break;
+ }
+
+ iowrite32(maccr, priv->base + FTGMAC100_OFFSET_MACCR);
+}
+
+static void ftgmac100_stop_hw(struct ftgmac100 *priv)
+{
+ iowrite32(0, priv->base + FTGMAC100_OFFSET_MACCR);
+}
+
+/******************************************************************************
+ * internal functions (receive descriptor)
+ *****************************************************************************/
+static bool ftgmac100_rxdes_first_segment(struct ftgmac100_rxdes *rxdes)
+{
+ return rxdes->rxdes0 & cpu_to_le32(FTGMAC100_RXDES0_FRS);
+}
+
+static bool ftgmac100_rxdes_last_segment(struct ftgmac100_rxdes *rxdes)
+{
+ return rxdes->rxdes0 & cpu_to_le32(FTGMAC100_RXDES0_LRS);
+}
+
+static bool ftgmac100_rxdes_packet_ready(struct ftgmac100_rxdes *rxdes)
+{
+ return rxdes->rxdes0 & cpu_to_le32(FTGMAC100_RXDES0_RXPKT_RDY);
+}
+
+static void ftgmac100_rxdes_set_dma_own(struct ftgmac100_rxdes *rxdes)
+{
+ /* clear status bits */
+ rxdes->rxdes0 &= cpu_to_le32(FTGMAC100_RXDES0_EDORR);
+}
+
+static bool ftgmac100_rxdes_rx_error(struct ftgmac100_rxdes *rxdes)
+{
+ return rxdes->rxdes0 & cpu_to_le32(FTGMAC100_RXDES0_RX_ERR);
+}
+
+static bool ftgmac100_rxdes_crc_error(struct ftgmac100_rxdes *rxdes)
+{
+ return rxdes->rxdes0 & cpu_to_le32(FTGMAC100_RXDES0_CRC_ERR);
+}
+
+static bool ftgmac100_rxdes_frame_too_long(struct ftgmac100_rxdes *rxdes)
+{
+ return rxdes->rxdes0 & cpu_to_le32(FTGMAC100_RXDES0_FTL);
+}
+
+static bool ftgmac100_rxdes_runt(struct ftgmac100_rxdes *rxdes)
+{
+ return rxdes->rxdes0 & cpu_to_le32(FTGMAC100_RXDES0_RUNT);
+}
+
+static bool ftgmac100_rxdes_odd_nibble(struct ftgmac100_rxdes *rxdes)
+{
+ return rxdes->rxdes0 & cpu_to_le32(FTGMAC100_RXDES0_RX_ODD_NB);
+}
+
+static unsigned int ftgmac100_rxdes_data_length(struct ftgmac100_rxdes *rxdes)
+{
+ return le32_to_cpu(rxdes->rxdes0) & FTGMAC100_RXDES0_VDBC;
+}
+
+static bool ftgmac100_rxdes_multicast(struct ftgmac100_rxdes *rxdes)
+{
+ return rxdes->rxdes0 & cpu_to_le32(FTGMAC100_RXDES0_MULTICAST);
+}
+
+static void ftgmac100_rxdes_set_end_of_ring(struct ftgmac100_rxdes *rxdes)
+{
+ rxdes->rxdes0 |= cpu_to_le32(FTGMAC100_RXDES0_EDORR);
+}
+
+static void ftgmac100_rxdes_set_dma_addr(struct ftgmac100_rxdes *rxdes,
+ dma_addr_t addr)
+{
+ rxdes->rxdes3 = cpu_to_le32(addr);
+}
+
+static dma_addr_t ftgmac100_rxdes_get_dma_addr(struct ftgmac100_rxdes *rxdes)
+{
+ return le32_to_cpu(rxdes->rxdes3);
+}
+
+static bool ftgmac100_rxdes_is_tcp(struct ftgmac100_rxdes *rxdes)
+{
+ return (rxdes->rxdes1 & cpu_to_le32(FTGMAC100_RXDES1_PROT_MASK)) ==
+ cpu_to_le32(FTGMAC100_RXDES1_PROT_TCPIP);
+}
+
+static bool ftgmac100_rxdes_is_udp(struct ftgmac100_rxdes *rxdes)
+{
+ return (rxdes->rxdes1 & cpu_to_le32(FTGMAC100_RXDES1_PROT_MASK)) ==
+ cpu_to_le32(FTGMAC100_RXDES1_PROT_UDPIP);
+}
+
+static bool ftgmac100_rxdes_tcpcs_err(struct ftgmac100_rxdes *rxdes)
+{
+ return rxdes->rxdes1 & cpu_to_le32(FTGMAC100_RXDES1_TCP_CHKSUM_ERR);
+}
+
+static bool ftgmac100_rxdes_udpcs_err(struct ftgmac100_rxdes *rxdes)
+{
+ return rxdes->rxdes1 & cpu_to_le32(FTGMAC100_RXDES1_UDP_CHKSUM_ERR);
+}
+
+static bool ftgmac100_rxdes_ipcs_err(struct ftgmac100_rxdes *rxdes)
+{
+ return rxdes->rxdes1 & cpu_to_le32(FTGMAC100_RXDES1_IP_CHKSUM_ERR);
+}
+
+/*
+ * rxdes2 is not used by hardware. We use it to keep track of page.
+ * Since hardware does not touch it, we can skip cpu_to_le32()/le32_to_cpu().
+ */
+static void ftgmac100_rxdes_set_page(struct ftgmac100_rxdes *rxdes, struct page *page)
+{
+ rxdes->rxdes2 = (unsigned int)page;
+}
+
+static struct page *ftgmac100_rxdes_get_page(struct ftgmac100_rxdes *rxdes)
+{
+ return (struct page *)rxdes->rxdes2;
+}
+
+/******************************************************************************
+ * internal functions (receive)
+ *****************************************************************************/
+static int ftgmac100_next_rx_pointer(int pointer)
+{
+ return (pointer + 1) & (RX_QUEUE_ENTRIES - 1);
+}
+
+static void ftgmac100_rx_pointer_advance(struct ftgmac100 *priv)
+{
+ priv->rx_pointer = ftgmac100_next_rx_pointer(priv->rx_pointer);
+}
+
+static struct ftgmac100_rxdes *ftgmac100_current_rxdes(struct ftgmac100 *priv)
+{
+ return &priv->descs->rxdes[priv->rx_pointer];
+}
+
+static struct ftgmac100_rxdes *
+ftgmac100_rx_locate_first_segment(struct ftgmac100 *priv)
+{
+ struct ftgmac100_rxdes *rxdes = ftgmac100_current_rxdes(priv);
+
+ while (ftgmac100_rxdes_packet_ready(rxdes)) {
+ if (ftgmac100_rxdes_first_segment(rxdes))
+ return rxdes;
+
+ ftgmac100_rxdes_set_dma_own(rxdes);
+ ftgmac100_rx_pointer_advance(priv);
+ rxdes = ftgmac100_current_rxdes(priv);
+ }
+
+ return NULL;
+}
+
+static bool ftgmac100_rx_packet_error(struct ftgmac100 *priv,
+ struct ftgmac100_rxdes *rxdes)
+{
+ struct net_device *netdev = priv->netdev;
+ bool error = false;
+
+ if (unlikely(ftgmac100_rxdes_rx_error(rxdes))) {
+ if (net_ratelimit())
+ netdev_info(netdev, "rx err\n");
+
+ netdev->stats.rx_errors++;
+ error = true;
+ }
+
+ if (unlikely(ftgmac100_rxdes_crc_error(rxdes))) {
+ if (net_ratelimit())
+ netdev_info(netdev, "rx crc err\n");
+
+ netdev->stats.rx_crc_errors++;
+ error = true;
+ } else if (unlikely(ftgmac100_rxdes_ipcs_err(rxdes))) {
+ if (net_ratelimit())
+ netdev_info(netdev, "rx IP checksum err\n");
+
+ error = true;
+ }
+
+ if (unlikely(ftgmac100_rxdes_frame_too_long(rxdes))) {
+ if (net_ratelimit())
+ netdev_info(netdev, "rx frame too long\n");
+
+ netdev->stats.rx_length_errors++;
+ error = true;
+ } else if (unlikely(ftgmac100_rxdes_runt(rxdes))) {
+ if (net_ratelimit())
+ netdev_info(netdev, "rx runt\n");
+
+ netdev->stats.rx_length_errors++;
+ error = true;
+ } else if (unlikely(ftgmac100_rxdes_odd_nibble(rxdes))) {
+ if (net_ratelimit())
+ netdev_info(netdev, "rx odd nibble\n");
+
+ netdev->stats.rx_length_errors++;
+ error = true;
+ }
+
+ return error;
+}
+
+static void ftgmac100_rx_drop_packet(struct ftgmac100 *priv)
+{
+ struct net_device *netdev = priv->netdev;
+ struct ftgmac100_rxdes *rxdes = ftgmac100_current_rxdes(priv);
+ bool done = false;
+
+ if (net_ratelimit())
+ netdev_dbg(netdev, "drop packet %p\n", rxdes);
+
+ do {
+ if (ftgmac100_rxdes_last_segment(rxdes))
+ done = true;
+
+ ftgmac100_rxdes_set_dma_own(rxdes);
+ ftgmac100_rx_pointer_advance(priv);
+ rxdes = ftgmac100_current_rxdes(priv);
+ } while (!done && ftgmac100_rxdes_packet_ready(rxdes));
+
+ netdev->stats.rx_dropped++;
+}
+
+static bool ftgmac100_rx_packet(struct ftgmac100 *priv, int *processed)
+{
+ struct net_device *netdev = priv->netdev;
+ struct ftgmac100_rxdes *rxdes;
+ struct sk_buff *skb;
+ bool done = false;
+
+ rxdes = ftgmac100_rx_locate_first_segment(priv);
+ if (!rxdes)
+ return false;
+
+ if (unlikely(ftgmac100_rx_packet_error(priv, rxdes))) {
+ ftgmac100_rx_drop_packet(priv);
+ return true;
+ }
+
+ /* start processing */
+ skb = netdev_alloc_skb_ip_align(netdev, 128);
+ if (unlikely(!skb)) {
+ if (net_ratelimit())
+ netdev_err(netdev, "rx skb alloc failed\n");
+
+ ftgmac100_rx_drop_packet(priv);
+ return true;
+ }
+
+ if (unlikely(ftgmac100_rxdes_multicast(rxdes)))
+ netdev->stats.multicast++;
+
+ /*
+ * It seems that HW does checksum incorrectly with fragmented packets,
+ * so we are conservative here - if HW checksum error, let software do
+ * the checksum again.
+ */
+ if ((ftgmac100_rxdes_is_tcp(rxdes) && !ftgmac100_rxdes_tcpcs_err(rxdes)) ||
+ (ftgmac100_rxdes_is_udp(rxdes) && !ftgmac100_rxdes_udpcs_err(rxdes)))
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+
+ do {
+ dma_addr_t map = ftgmac100_rxdes_get_dma_addr(rxdes);
+ struct page *page = ftgmac100_rxdes_get_page(rxdes);
+ unsigned int size;
+
+ dma_unmap_page(priv->dev, map, RX_BUF_SIZE, DMA_FROM_DEVICE);
+
+ size = ftgmac100_rxdes_data_length(rxdes);
+ skb_fill_page_desc(skb, skb_shinfo(skb)->nr_frags, page, 0, size);
+
+ skb->len += size;
+ skb->data_len += size;
+ skb->truesize += size;
+
+ if (ftgmac100_rxdes_last_segment(rxdes))
+ done = true;
+
+ ftgmac100_alloc_rx_page(priv, rxdes, GFP_ATOMIC);
+
+ ftgmac100_rx_pointer_advance(priv);
+ rxdes = ftgmac100_current_rxdes(priv);
+ } while (!done);
+
+ __pskb_pull_tail(skb, min(skb->len, 64U));
+ skb->protocol = eth_type_trans(skb, netdev);
+
+ netdev->stats.rx_packets++;
+ netdev->stats.rx_bytes += skb->len;
+
+ /* push packet to protocol stack */
+ napi_gro_receive(&priv->napi, skb);
+
+ (*processed)++;
+ return true;
+}
+
+/******************************************************************************
+ * internal functions (transmit descriptor)
+ *****************************************************************************/
+static void ftgmac100_txdes_reset(struct ftgmac100_txdes *txdes)
+{
+ /* clear all except end of ring bit */
+ txdes->txdes0 &= cpu_to_le32(FTGMAC100_TXDES0_EDOTR);
+ txdes->txdes1 = 0;
+ txdes->txdes2 = 0;
+ txdes->txdes3 = 0;
+}
+
+static bool ftgmac100_txdes_owned_by_dma(struct ftgmac100_txdes *txdes)
+{
+ return txdes->txdes0 & cpu_to_le32(FTGMAC100_TXDES0_TXDMA_OWN);
+}
+
+static void ftgmac100_txdes_set_dma_own(struct ftgmac100_txdes *txdes)
+{
+ /*
+ * Make sure dma own bit will not be set before any other
+ * descriptor fields.
+ */
+ wmb();
+ txdes->txdes0 |= cpu_to_le32(FTGMAC100_TXDES0_TXDMA_OWN);
+}
+
+static void ftgmac100_txdes_set_end_of_ring(struct ftgmac100_txdes *txdes)
+{
+ txdes->txdes0 |= cpu_to_le32(FTGMAC100_TXDES0_EDOTR);
+}
+
+static void ftgmac100_txdes_set_first_segment(struct ftgmac100_txdes *txdes)
+{
+ txdes->txdes0 |= cpu_to_le32(FTGMAC100_TXDES0_FTS);
+}
+
+static void ftgmac100_txdes_set_last_segment(struct ftgmac100_txdes *txdes)
+{
+ txdes->txdes0 |= cpu_to_le32(FTGMAC100_TXDES0_LTS);
+}
+
+static void ftgmac100_txdes_set_buffer_size(struct ftgmac100_txdes *txdes,
+ unsigned int len)
+{
+ txdes->txdes0 |= cpu_to_le32(FTGMAC100_TXDES0_TXBUF_SIZE(len));
+}
+
+static void ftgmac100_txdes_set_txint(struct ftgmac100_txdes *txdes)
+{
+ txdes->txdes1 |= cpu_to_le32(FTGMAC100_TXDES1_TXIC);
+}
+
+static void ftgmac100_txdes_set_tcpcs(struct ftgmac100_txdes *txdes)
+{
+ txdes->txdes1 |= cpu_to_le32(FTGMAC100_TXDES1_TCP_CHKSUM);
+}
+
+static void ftgmac100_txdes_set_udpcs(struct ftgmac100_txdes *txdes)
+{
+ txdes->txdes1 |= cpu_to_le32(FTGMAC100_TXDES1_UDP_CHKSUM);
+}
+
+static void ftgmac100_txdes_set_ipcs(struct ftgmac100_txdes *txdes)
+{
+ txdes->txdes1 |= cpu_to_le32(FTGMAC100_TXDES1_IP_CHKSUM);
+}
+
+static void ftgmac100_txdes_set_dma_addr(struct ftgmac100_txdes *txdes,
+ dma_addr_t addr)
+{
+ txdes->txdes3 = cpu_to_le32(addr);
+}
+
+static dma_addr_t ftgmac100_txdes_get_dma_addr(struct ftgmac100_txdes *txdes)
+{
+ return le32_to_cpu(txdes->txdes3);
+}
+
+/*
+ * txdes2 is not used by hardware. We use it to keep track of socket buffer.
+ * Since hardware does not touch it, we can skip cpu_to_le32()/le32_to_cpu().
+ */
+static void ftgmac100_txdes_set_skb(struct ftgmac100_txdes *txdes,
+ struct sk_buff *skb)
+{
+ txdes->txdes2 = (unsigned int)skb;
+}
+
+static struct sk_buff *ftgmac100_txdes_get_skb(struct ftgmac100_txdes *txdes)
+{
+ return (struct sk_buff *)txdes->txdes2;
+}
+
+/******************************************************************************
+ * internal functions (transmit)
+ *****************************************************************************/
+static int ftgmac100_next_tx_pointer(int pointer)
+{
+ return (pointer + 1) & (TX_QUEUE_ENTRIES - 1);
+}
+
+static void ftgmac100_tx_pointer_advance(struct ftgmac100 *priv)
+{
+ priv->tx_pointer = ftgmac100_next_tx_pointer(priv->tx_pointer);
+}
+
+static void ftgmac100_tx_clean_pointer_advance(struct ftgmac100 *priv)
+{
+ priv->tx_clean_pointer = ftgmac100_next_tx_pointer(priv->tx_clean_pointer);
+}
+
+static struct ftgmac100_txdes *ftgmac100_current_txdes(struct ftgmac100 *priv)
+{
+ return &priv->descs->txdes[priv->tx_pointer];
+}
+
+static struct ftgmac100_txdes *
+ftgmac100_current_clean_txdes(struct ftgmac100 *priv)
+{
+ return &priv->descs->txdes[priv->tx_clean_pointer];
+}
+
+static bool ftgmac100_tx_complete_packet(struct ftgmac100 *priv)
+{
+ struct net_device *netdev = priv->netdev;
+ struct ftgmac100_txdes *txdes;
+ struct sk_buff *skb;
+ dma_addr_t map;
+
+ if (priv->tx_pending == 0)
+ return false;
+
+ txdes = ftgmac100_current_clean_txdes(priv);
+
+ if (ftgmac100_txdes_owned_by_dma(txdes))
+ return false;
+
+ skb = ftgmac100_txdes_get_skb(txdes);
+ map = ftgmac100_txdes_get_dma_addr(txdes);
+
+ netdev->stats.tx_packets++;
+ netdev->stats.tx_bytes += skb->len;
+
+ dma_unmap_single(priv->dev, map, skb_headlen(skb), DMA_TO_DEVICE);
+
+ dev_kfree_skb(skb);
+
+ ftgmac100_txdes_reset(txdes);
+
+ ftgmac100_tx_clean_pointer_advance(priv);
+
+ spin_lock(&priv->tx_lock);
+ priv->tx_pending--;
+ spin_unlock(&priv->tx_lock);
+ netif_wake_queue(netdev);
+
+ return true;
+}
+
+static void ftgmac100_tx_complete(struct ftgmac100 *priv)
+{
+ while (ftgmac100_tx_complete_packet(priv))
+ ;
+}
+
+static int ftgmac100_xmit(struct ftgmac100 *priv, struct sk_buff *skb,
+ dma_addr_t map)
+{
+ struct net_device *netdev = priv->netdev;
+ struct ftgmac100_txdes *txdes;
+ unsigned int len = (skb->len < ETH_ZLEN) ? ETH_ZLEN : skb->len;
+
+ txdes = ftgmac100_current_txdes(priv);
+ ftgmac100_tx_pointer_advance(priv);
+
+ /* setup TX descriptor */
+ ftgmac100_txdes_set_skb(txdes, skb);
+ ftgmac100_txdes_set_dma_addr(txdes, map);
+ ftgmac100_txdes_set_buffer_size(txdes, len);
+
+ ftgmac100_txdes_set_first_segment(txdes);
+ ftgmac100_txdes_set_last_segment(txdes);
+ ftgmac100_txdes_set_txint(txdes);
+ if (skb->ip_summed == CHECKSUM_PARTIAL) {
+ __be16 protocol = skb->protocol;
+
+ if (protocol == cpu_to_be16(ETH_P_IP)) {
+ u8 ip_proto = ip_hdr(skb)->protocol;
+
+ ftgmac100_txdes_set_ipcs(txdes);
+ if (ip_proto == IPPROTO_TCP)
+ ftgmac100_txdes_set_tcpcs(txdes);
+ else if (ip_proto == IPPROTO_UDP)
+ ftgmac100_txdes_set_udpcs(txdes);
+ }
+ }
+
+ spin_lock(&priv->tx_lock);
+ priv->tx_pending++;
+ if (priv->tx_pending == TX_QUEUE_ENTRIES)
+ netif_stop_queue(netdev);
+
+ /* start transmit */
+ ftgmac100_txdes_set_dma_own(txdes);
+ spin_unlock(&priv->tx_lock);
+
+ ftgmac100_txdma_normal_prio_start_polling(priv);
+
+ return NETDEV_TX_OK;
+}
+
+/******************************************************************************
+ * internal functions (buffer)
+ *****************************************************************************/
+static int ftgmac100_alloc_rx_page(struct ftgmac100 *priv,
+ struct ftgmac100_rxdes *rxdes, gfp_t gfp)
+{
+ struct net_device *netdev = priv->netdev;
+ struct page *page;
+ dma_addr_t map;
+
+ page = alloc_page(gfp);
+ if (!page) {
+ if (net_ratelimit())
+ netdev_err(netdev, "failed to allocate rx page\n");
+ return -ENOMEM;
+ }
+
+ map = dma_map_page(priv->dev, page, 0, RX_BUF_SIZE, DMA_FROM_DEVICE);
+ if (unlikely(dma_mapping_error(priv->dev, map))) {
+ if (net_ratelimit())
+ netdev_err(netdev, "failed to map rx page\n");
+ __free_page(page);
+ return -ENOMEM;
+ }
+
+ ftgmac100_rxdes_set_page(rxdes, page);
+ ftgmac100_rxdes_set_dma_addr(rxdes, map);
+ ftgmac100_rxdes_set_dma_own(rxdes);
+ return 0;
+}
+
+static void ftgmac100_free_buffers(struct ftgmac100 *priv)
+{
+ int i;
+
+ for (i = 0; i < RX_QUEUE_ENTRIES; i++) {
+ struct ftgmac100_rxdes *rxdes = &priv->descs->rxdes[i];
+ struct page *page = ftgmac100_rxdes_get_page(rxdes);
+ dma_addr_t map = ftgmac100_rxdes_get_dma_addr(rxdes);
+
+ if (!page)
+ continue;
+
+ dma_unmap_page(priv->dev, map, RX_BUF_SIZE, DMA_FROM_DEVICE);
+ __free_page(page);
+ }
+
+ for (i = 0; i < TX_QUEUE_ENTRIES; i++) {
+ struct ftgmac100_txdes *txdes = &priv->descs->txdes[i];
+ struct sk_buff *skb = ftgmac100_txdes_get_skb(txdes);
+ dma_addr_t map = ftgmac100_txdes_get_dma_addr(txdes);
+
+ if (!skb)
+ continue;
+
+ dma_unmap_single(priv->dev, map, skb_headlen(skb), DMA_TO_DEVICE);
+ dev_kfree_skb(skb);
+ }
+
+ dma_free_coherent(priv->dev, sizeof(struct ftgmac100_descs),
+ priv->descs, priv->descs_dma_addr);
+}
+
+static int ftgmac100_alloc_buffers(struct ftgmac100 *priv)
+{
+ int i;
+
+ priv->descs = dma_alloc_coherent(priv->dev,
+ sizeof(struct ftgmac100_descs),
+ &priv->descs_dma_addr, GFP_KERNEL);
+ if (!priv->descs)
+ return -ENOMEM;
+
+ memset(priv->descs, 0, sizeof(struct ftgmac100_descs));
+
+ /* initialize RX ring */
+ ftgmac100_rxdes_set_end_of_ring(&priv->descs->rxdes[RX_QUEUE_ENTRIES - 1]);
+
+ for (i = 0; i < RX_QUEUE_ENTRIES; i++) {
+ struct ftgmac100_rxdes *rxdes = &priv->descs->rxdes[i];
+
+ if (ftgmac100_alloc_rx_page(priv, rxdes, GFP_KERNEL))
+ goto err;
+ }
+
+ /* initialize TX ring */
+ ftgmac100_txdes_set_end_of_ring(&priv->descs->txdes[TX_QUEUE_ENTRIES - 1]);
+ return 0;
+
+err:
+ ftgmac100_free_buffers(priv);
+ return -ENOMEM;
+}
+
+/******************************************************************************
+ * internal functions (mdio)
+ *****************************************************************************/
+static void ftgmac100_adjust_link(struct net_device *netdev)
+{
+ struct ftgmac100 *priv = netdev_priv(netdev);
+ struct phy_device *phydev = priv->phydev;
+ int ier;
+
+ if (phydev->speed == priv->old_speed)
+ return;
+
+ priv->old_speed = phydev->speed;
+
+ ier = ioread32(priv->base + FTGMAC100_OFFSET_IER);
+
+ /* disable all interrupts */
+ iowrite32(0, priv->base + FTGMAC100_OFFSET_IER);
+
+ netif_stop_queue(netdev);
+ ftgmac100_stop_hw(priv);
+
+ netif_start_queue(netdev);
+ ftgmac100_init_hw(priv);
+ ftgmac100_start_hw(priv, phydev->speed);
+
+ /* re-enable interrupts */
+ iowrite32(ier, priv->base + FTGMAC100_OFFSET_IER);
+}
+
+static int ftgmac100_mii_probe(struct ftgmac100 *priv)
+{
+ struct net_device *netdev = priv->netdev;
+ struct phy_device *phydev = NULL;
+ int i;
+
+ /* search for connect PHY device */
+ for (i = 0; i < PHY_MAX_ADDR; i++) {
+ struct phy_device *tmp = priv->mii_bus->phy_map[i];
+
+ if (tmp) {
+ phydev = tmp;
+ break;
+ }
+ }
+
+ /* now we are supposed to have a proper phydev, to attach to... */
+ if (!phydev) {
+ netdev_info(netdev, "%s: no PHY found\n", netdev->name);
+ return -ENODEV;
+ }
+
+ phydev = phy_connect(netdev, dev_name(&phydev->dev),
+ &ftgmac100_adjust_link, 0,
+ PHY_INTERFACE_MODE_GMII);
+
+ if (IS_ERR(phydev)) {
+ netdev_err(netdev, "%s: Could not attach to PHY\n", netdev->name);
+ return PTR_ERR(phydev);
+ }
+
+ priv->phydev = phydev;
+ return 0;
+}
+
+/******************************************************************************
+ * struct mii_bus functions
+ *****************************************************************************/
+static int ftgmac100_mdiobus_read(struct mii_bus *bus, int phy_addr, int regnum)
+{
+ struct net_device *netdev = bus->priv;
+ struct ftgmac100 *priv = netdev_priv(netdev);
+ unsigned int phycr;
+ int i;
+
+ phycr = ioread32(priv->base + FTGMAC100_OFFSET_PHYCR);
+
+ /* preserve MDC cycle threshold */
+ phycr &= FTGMAC100_PHYCR_MDC_CYCTHR_MASK;
+
+ phycr |= FTGMAC100_PHYCR_PHYAD(phy_addr) |
+ FTGMAC100_PHYCR_REGAD(regnum) |
+ FTGMAC100_PHYCR_MIIRD;
+
+ iowrite32(phycr, priv->base + FTGMAC100_OFFSET_PHYCR);
+
+ for (i = 0; i < 10; i++) {
+ phycr = ioread32(priv->base + FTGMAC100_OFFSET_PHYCR);
+
+ if ((phycr & FTGMAC100_PHYCR_MIIRD) == 0) {
+ int data;
+
+ data = ioread32(priv->base + FTGMAC100_OFFSET_PHYDATA);
+ return FTGMAC100_PHYDATA_MIIRDATA(data);
+ }
+
+ udelay(100);
+ }
+
+ netdev_err(netdev, "mdio read timed out\n");
+ return -EIO;
+}
+
+static int ftgmac100_mdiobus_write(struct mii_bus *bus, int phy_addr,
+ int regnum, u16 value)
+{
+ struct net_device *netdev = bus->priv;
+ struct ftgmac100 *priv = netdev_priv(netdev);
+ unsigned int phycr;
+ int data;
+ int i;
+
+ phycr = ioread32(priv->base + FTGMAC100_OFFSET_PHYCR);
+
+ /* preserve MDC cycle threshold */
+ phycr &= FTGMAC100_PHYCR_MDC_CYCTHR_MASK;
+
+ phycr |= FTGMAC100_PHYCR_PHYAD(phy_addr) |
+ FTGMAC100_PHYCR_REGAD(regnum) |
+ FTGMAC100_PHYCR_MIIWR;
+
+ data = FTGMAC100_PHYDATA_MIIWDATA(value);
+
+ iowrite32(data, priv->base + FTGMAC100_OFFSET_PHYDATA);
+ iowrite32(phycr, priv->base + FTGMAC100_OFFSET_PHYCR);
+
+ for (i = 0; i < 10; i++) {
+ phycr = ioread32(priv->base + FTGMAC100_OFFSET_PHYCR);
+
+ if ((phycr & FTGMAC100_PHYCR_MIIWR) == 0)
+ return 0;
+
+ udelay(100);
+ }
+
+ netdev_err(netdev, "mdio write timed out\n");
+ return -EIO;
+}
+
+static int ftgmac100_mdiobus_reset(struct mii_bus *bus)
+{
+ return 0;
+}
+
+/******************************************************************************
+ * struct ethtool_ops functions
+ *****************************************************************************/
+static void ftgmac100_get_drvinfo(struct net_device *netdev,
+ struct ethtool_drvinfo *info)
+{
+ strcpy(info->driver, DRV_NAME);
+ strcpy(info->version, DRV_VERSION);
+ strcpy(info->bus_info, dev_name(&netdev->dev));
+}
+
+static int ftgmac100_get_settings(struct net_device *netdev,
+ struct ethtool_cmd *cmd)
+{
+ struct ftgmac100 *priv = netdev_priv(netdev);
+
+ return phy_ethtool_gset(priv->phydev, cmd);
+}
+
+static int ftgmac100_set_settings(struct net_device *netdev,
+ struct ethtool_cmd *cmd)
+{
+ struct ftgmac100 *priv = netdev_priv(netdev);
+
+ return phy_ethtool_sset(priv->phydev, cmd);
+}
+
+static const struct ethtool_ops ftgmac100_ethtool_ops = {
+ .set_settings = ftgmac100_set_settings,
+ .get_settings = ftgmac100_get_settings,
+ .get_drvinfo = ftgmac100_get_drvinfo,
+ .get_link = ethtool_op_get_link,
+};
+
+/******************************************************************************
+ * interrupt handler
+ *****************************************************************************/
+static irqreturn_t ftgmac100_interrupt(int irq, void *dev_id)
+{
+ struct net_device *netdev = dev_id;
+ struct ftgmac100 *priv = netdev_priv(netdev);
+
+ if (likely(netif_running(netdev))) {
+ /* Disable interrupts for polling */
+ iowrite32(0, priv->base + FTGMAC100_OFFSET_IER);
+ napi_schedule(&priv->napi);
+ }
+
+ return IRQ_HANDLED;
+}
+
+/******************************************************************************
+ * struct napi_struct functions
+ *****************************************************************************/
+static int ftgmac100_poll(struct napi_struct *napi, int budget)
+{
+ struct ftgmac100 *priv = container_of(napi, struct ftgmac100, napi);
+ struct net_device *netdev = priv->netdev;
+ unsigned int status;
+ bool completed = true;
+ int rx = 0;
+
+ status = ioread32(priv->base + FTGMAC100_OFFSET_ISR);
+ iowrite32(status, priv->base + FTGMAC100_OFFSET_ISR);
+
+ if (status & (FTGMAC100_INT_RPKT_BUF | FTGMAC100_INT_NO_RXBUF)) {
+ /*
+ * FTGMAC100_INT_RPKT_BUF:
+ * RX DMA has received packets into RX buffer successfully
+ *
+ * FTGMAC100_INT_NO_RXBUF:
+ * RX buffer unavailable
+ */
+ bool retry;
+
+ do {
+ retry = ftgmac100_rx_packet(priv, &rx);
+ } while (retry && rx < budget);
+
+ if (retry && rx == budget)
+ completed = false;
+ }
+
+ if (status & (FTGMAC100_INT_XPKT_ETH | FTGMAC100_INT_XPKT_LOST)) {
+ /*
+ * FTGMAC100_INT_XPKT_ETH:
+ * packet transmitted to ethernet successfully
+ *
+ * FTGMAC100_INT_XPKT_LOST:
+ * packet transmitted to ethernet lost due to late
+ * collision or excessive collision
+ */
+ ftgmac100_tx_complete(priv);
+ }
+
+ if (status & (FTGMAC100_INT_NO_RXBUF | FTGMAC100_INT_RPKT_LOST |
+ FTGMAC100_INT_AHB_ERR | FTGMAC100_INT_PHYSTS_CHG)) {
+ if (net_ratelimit())
+ netdev_info(netdev, "[ISR] = 0x%x: %s%s%s%s\n", status,
+ status & FTGMAC100_INT_NO_RXBUF ? "NO_RXBUF " : "",
+ status & FTGMAC100_INT_RPKT_LOST ? "RPKT_LOST " : "",
+ status & FTGMAC100_INT_AHB_ERR ? "AHB_ERR " : "",
+ status & FTGMAC100_INT_PHYSTS_CHG ? "PHYSTS_CHG" : "");
+
+ if (status & FTGMAC100_INT_NO_RXBUF) {
+ /* RX buffer unavailable */
+ netdev->stats.rx_over_errors++;
+ }
+
+ if (status & FTGMAC100_INT_RPKT_LOST) {
+ /* received packet lost due to RX FIFO full */
+ netdev->stats.rx_fifo_errors++;
+ }
+ }
+
+ if (completed) {
+ napi_complete(napi);
+
+ /* enable all interrupts */
+ iowrite32(INT_MASK_ALL_ENABLED, priv->base + FTGMAC100_OFFSET_IER);
+ }
+
+ return rx;
+}
+
+/******************************************************************************
+ * struct net_device_ops functions
+ *****************************************************************************/
+static int ftgmac100_open(struct net_device *netdev)
+{
+ struct ftgmac100 *priv = netdev_priv(netdev);
+ int err;
+
+ err = ftgmac100_alloc_buffers(priv);
+ if (err) {
+ netdev_err(netdev, "failed to allocate buffers\n");
+ goto err_alloc;
+ }
+
+ err = request_irq(priv->irq, ftgmac100_interrupt, 0, netdev->name, netdev);
+ if (err) {
+ netdev_err(netdev, "failed to request irq %d\n", priv->irq);
+ goto err_irq;
+ }
+
+ priv->rx_pointer = 0;
+ priv->tx_clean_pointer = 0;
+ priv->tx_pointer = 0;
+ priv->tx_pending = 0;
+
+ err = ftgmac100_reset_hw(priv);
+ if (err)
+ goto err_hw;
+
+ ftgmac100_init_hw(priv);
+ ftgmac100_start_hw(priv, 10);
+
+ phy_start(priv->phydev);
+
+ napi_enable(&priv->napi);
+ netif_start_queue(netdev);
+
+ /* enable all interrupts */
+ iowrite32(INT_MASK_ALL_ENABLED, priv->base + FTGMAC100_OFFSET_IER);
+ return 0;
+
+err_hw:
+ free_irq(priv->irq, netdev);
+err_irq:
+ ftgmac100_free_buffers(priv);
+err_alloc:
+ return err;
+}
+
+static int ftgmac100_stop(struct net_device *netdev)
+{
+ struct ftgmac100 *priv = netdev_priv(netdev);
+
+ /* disable all interrupts */
+ iowrite32(0, priv->base + FTGMAC100_OFFSET_IER);
+
+ netif_stop_queue(netdev);
+ napi_disable(&priv->napi);
+ phy_stop(priv->phydev);
+
+ ftgmac100_stop_hw(priv);
+ free_irq(priv->irq, netdev);
+ ftgmac100_free_buffers(priv);
+
+ return 0;
+}
+
+static int ftgmac100_hard_start_xmit(struct sk_buff *skb,
+ struct net_device *netdev)
+{
+ struct ftgmac100 *priv = netdev_priv(netdev);
+ dma_addr_t map;
+
+ if (unlikely(skb->len > MAX_PKT_SIZE)) {
+ if (net_ratelimit())
+ netdev_dbg(netdev, "tx packet too big\n");
+
+ netdev->stats.tx_dropped++;
+ dev_kfree_skb(skb);
+ return NETDEV_TX_OK;
+ }
+
+ map = dma_map_single(priv->dev, skb->data, skb_headlen(skb), DMA_TO_DEVICE);
+ if (unlikely(dma_mapping_error(priv->dev, map))) {
+ /* drop packet */
+ if (net_ratelimit())
+ netdev_err(netdev, "map socket buffer failed\n");
+
+ netdev->stats.tx_dropped++;
+ dev_kfree_skb(skb);
+ return NETDEV_TX_OK;
+ }
+
+ return ftgmac100_xmit(priv, skb, map);
+}
+
+/* optional */
+static int ftgmac100_do_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
+{
+ struct ftgmac100 *priv = netdev_priv(netdev);
+
+ return phy_mii_ioctl(priv->phydev, ifr, cmd);
+}
+
+static const struct net_device_ops ftgmac100_netdev_ops = {
+ .ndo_open = ftgmac100_open,
+ .ndo_stop = ftgmac100_stop,
+ .ndo_start_xmit = ftgmac100_hard_start_xmit,
+ .ndo_set_mac_address = eth_mac_addr,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_do_ioctl = ftgmac100_do_ioctl,
+};
+
+/******************************************************************************
+ * struct platform_driver functions
+ *****************************************************************************/
+static int ftgmac100_probe(struct platform_device *pdev)
+{
+ struct resource *res;
+ int irq;
+ struct net_device *netdev;
+ struct ftgmac100 *priv;
+ int err;
+ int i;
+
+ if (!pdev)
+ return -ENODEV;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res)
+ return -ENXIO;
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0)
+ return irq;
+
+ /* setup net_device */
+ netdev = alloc_etherdev(sizeof(*priv));
+ if (!netdev) {
+ err = -ENOMEM;
+ goto err_alloc_etherdev;
+ }
+
+ SET_NETDEV_DEV(netdev, &pdev->dev);
+
+ SET_ETHTOOL_OPS(netdev, &ftgmac100_ethtool_ops);
+ netdev->netdev_ops = &ftgmac100_netdev_ops;
+ netdev->features = NETIF_F_IP_CSUM | NETIF_F_GRO;
+
+ platform_set_drvdata(pdev, netdev);
+
+ /* setup private data */
+ priv = netdev_priv(netdev);
+ priv->netdev = netdev;
+ priv->dev = &pdev->dev;
+
+ spin_lock_init(&priv->tx_lock);
+
+ /* initialize NAPI */
+ netif_napi_add(netdev, &priv->napi, ftgmac100_poll, 64);
+
+ /* map io memory */
+ priv->res = request_mem_region(res->start, resource_size(res),
+ dev_name(&pdev->dev));
+ if (!priv->res) {
+ dev_err(&pdev->dev, "Could not reserve memory region\n");
+ err = -ENOMEM;
+ goto err_req_mem;
+ }
+
+ priv->base = ioremap(res->start, resource_size(res));
+ if (!priv->base) {
+ dev_err(&pdev->dev, "Failed to ioremap ethernet registers\n");
+ err = -EIO;
+ goto err_ioremap;
+ }
+
+ priv->irq = irq;
+
+ /* initialize mdio bus */
+ priv->mii_bus = mdiobus_alloc();
+ if (!priv->mii_bus) {
+ err = -EIO;
+ goto err_alloc_mdiobus;
+ }
+
+ priv->mii_bus->name = "ftgmac100_mdio";
+ snprintf(priv->mii_bus->id, MII_BUS_ID_SIZE, "ftgmac100_mii");
+
+ priv->mii_bus->priv = netdev;
+ priv->mii_bus->read = ftgmac100_mdiobus_read;
+ priv->mii_bus->write = ftgmac100_mdiobus_write;
+ priv->mii_bus->reset = ftgmac100_mdiobus_reset;
+ priv->mii_bus->irq = priv->phy_irq;
+
+ for (i = 0; i < PHY_MAX_ADDR; i++)
+ priv->mii_bus->irq[i] = PHY_POLL;
+
+ err = mdiobus_register(priv->mii_bus);
+ if (err) {
+ dev_err(&pdev->dev, "Cannot register MDIO bus!\n");
+ goto err_register_mdiobus;
+ }
+
+ err = ftgmac100_mii_probe(priv);
+ if (err) {
+ dev_err(&pdev->dev, "MII Probe failed!\n");
+ goto err_mii_probe;
+ }
+
+ /* register network device */
+ err = register_netdev(netdev);
+ if (err) {
+ dev_err(&pdev->dev, "Failed to register netdev\n");
+ goto err_register_netdev;
+ }
+
+ netdev_info(netdev, "irq %d, mapped at %p\n", priv->irq, priv->base);
+
+ if (!is_valid_ether_addr(netdev->dev_addr)) {
+ random_ether_addr(netdev->dev_addr);
+ netdev_info(netdev, "generated random MAC address %pM\n",
+ netdev->dev_addr);
+ }
+
+ return 0;
+
+err_register_netdev:
+ phy_disconnect(priv->phydev);
+err_mii_probe:
+ mdiobus_unregister(priv->mii_bus);
+err_register_mdiobus:
+ mdiobus_free(priv->mii_bus);
+err_alloc_mdiobus:
+ iounmap(priv->base);
+err_ioremap:
+ release_resource(priv->res);
+err_req_mem:
+ netif_napi_del(&priv->napi);
+ platform_set_drvdata(pdev, NULL);
+ free_netdev(netdev);
+err_alloc_etherdev:
+ return err;
+}
+
+static int __exit ftgmac100_remove(struct platform_device *pdev)
+{
+ struct net_device *netdev;
+ struct ftgmac100 *priv;
+
+ netdev = platform_get_drvdata(pdev);
+ priv = netdev_priv(netdev);
+
+ unregister_netdev(netdev);
+
+ phy_disconnect(priv->phydev);
+ mdiobus_unregister(priv->mii_bus);
+ mdiobus_free(priv->mii_bus);
+
+ iounmap(priv->base);
+ release_resource(priv->res);
+
+ netif_napi_del(&priv->napi);
+ platform_set_drvdata(pdev, NULL);
+ free_netdev(netdev);
+ return 0;
+}
+
+static struct platform_driver ftgmac100_driver = {
+ .probe = ftgmac100_probe,
+ .remove = __exit_p(ftgmac100_remove),
+ .driver = {
+ .name = DRV_NAME,
+ .owner = THIS_MODULE,
+ },
+};
+
+/******************************************************************************
+ * initialization / finalization
+ *****************************************************************************/
+static int __init ftgmac100_init(void)
+{
+ pr_info("Loading version " DRV_VERSION " ...\n");
+ return platform_driver_register(&ftgmac100_driver);
+}
+
+static void __exit ftgmac100_exit(void)
+{
+ platform_driver_unregister(&ftgmac100_driver);
+}
+
+module_init(ftgmac100_init);
+module_exit(ftgmac100_exit);
+
+MODULE_AUTHOR("Po-Yu Chuang <ratbert@faraday-tech.com>");
+MODULE_DESCRIPTION("FTGMAC100 driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/ftgmac100.h b/drivers/net/ftgmac100.h
new file mode 100644
index 0000000..13408d4
--- /dev/null
+++ b/drivers/net/ftgmac100.h
@@ -0,0 +1,246 @@
+/*
+ * Faraday FTGMAC100 Gigabit Ethernet
+ *
+ * (C) Copyright 2009-2011 Faraday Technology
+ * Po-Yu Chuang <ratbert@faraday-tech.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __FTGMAC100_H
+#define __FTGMAC100_H
+
+#define FTGMAC100_OFFSET_ISR 0x00
+#define FTGMAC100_OFFSET_IER 0x04
+#define FTGMAC100_OFFSET_MAC_MADR 0x08
+#define FTGMAC100_OFFSET_MAC_LADR 0x0c
+#define FTGMAC100_OFFSET_MAHT0 0x10
+#define FTGMAC100_OFFSET_MAHT1 0x14
+#define FTGMAC100_OFFSET_NPTXPD 0x18
+#define FTGMAC100_OFFSET_RXPD 0x1c
+#define FTGMAC100_OFFSET_NPTXR_BADR 0x20
+#define FTGMAC100_OFFSET_RXR_BADR 0x24
+#define FTGMAC100_OFFSET_HPTXPD 0x28
+#define FTGMAC100_OFFSET_HPTXR_BADR 0x2c
+#define FTGMAC100_OFFSET_ITC 0x30
+#define FTGMAC100_OFFSET_APTC 0x34
+#define FTGMAC100_OFFSET_DBLAC 0x38
+#define FTGMAC100_OFFSET_DMAFIFOS 0x3c
+#define FTGMAC100_OFFSET_REVR 0x40
+#define FTGMAC100_OFFSET_FEAR 0x44
+#define FTGMAC100_OFFSET_TPAFCR 0x48
+#define FTGMAC100_OFFSET_RBSR 0x4c
+#define FTGMAC100_OFFSET_MACCR 0x50
+#define FTGMAC100_OFFSET_MACSR 0x54
+#define FTGMAC100_OFFSET_TM 0x58
+#define FTGMAC100_OFFSET_PHYCR 0x60
+#define FTGMAC100_OFFSET_PHYDATA 0x64
+#define FTGMAC100_OFFSET_FCR 0x68
+#define FTGMAC100_OFFSET_BPR 0x6c
+#define FTGMAC100_OFFSET_WOLCR 0x70
+#define FTGMAC100_OFFSET_WOLSR 0x74
+#define FTGMAC100_OFFSET_WFCRC 0x78
+#define FTGMAC100_OFFSET_WFBM1 0x80
+#define FTGMAC100_OFFSET_WFBM2 0x84
+#define FTGMAC100_OFFSET_WFBM3 0x88
+#define FTGMAC100_OFFSET_WFBM4 0x8c
+#define FTGMAC100_OFFSET_NPTXR_PTR 0x90
+#define FTGMAC100_OFFSET_HPTXR_PTR 0x94
+#define FTGMAC100_OFFSET_RXR_PTR 0x98
+#define FTGMAC100_OFFSET_TX 0xa0
+#define FTGMAC100_OFFSET_TX_MCOL_SCOL 0xa4
+#define FTGMAC100_OFFSET_TX_ECOL_FAIL 0xa8
+#define FTGMAC100_OFFSET_TX_LCOL_UND 0xac
+#define FTGMAC100_OFFSET_RX 0xb0
+#define FTGMAC100_OFFSET_RX_BC 0xb4
+#define FTGMAC100_OFFSET_RX_MC 0xb8
+#define FTGMAC100_OFFSET_RX_PF_AEP 0xbc
+#define FTGMAC100_OFFSET_RX_RUNT 0xc0
+#define FTGMAC100_OFFSET_RX_CRCER_FTL 0xc4
+#define FTGMAC100_OFFSET_RX_COL_LOST 0xc8
+
+/*
+ * Interrupt status register & interrupt enable register
+ */
+#define FTGMAC100_INT_RPKT_BUF (1 << 0)
+#define FTGMAC100_INT_RPKT_FIFO (1 << 1)
+#define FTGMAC100_INT_NO_RXBUF (1 << 2)
+#define FTGMAC100_INT_RPKT_LOST (1 << 3)
+#define FTGMAC100_INT_XPKT_ETH (1 << 4)
+#define FTGMAC100_INT_XPKT_FIFO (1 << 5)
+#define FTGMAC100_INT_NO_NPTXBUF (1 << 6)
+#define FTGMAC100_INT_XPKT_LOST (1 << 7)
+#define FTGMAC100_INT_AHB_ERR (1 << 8)
+#define FTGMAC100_INT_PHYSTS_CHG (1 << 9)
+#define FTGMAC100_INT_NO_HPTXBUF (1 << 10)
+
+/*
+ * Interrupt timer control register
+ */
+#define FTGMAC100_ITC_RXINT_CNT(x) (((x) & 0xf) << 0)
+#define FTGMAC100_ITC_RXINT_THR(x) (((x) & 0x7) << 4)
+#define FTGMAC100_ITC_RXINT_TIME_SEL (1 << 7)
+#define FTGMAC100_ITC_TXINT_CNT(x) (((x) & 0xf) << 8)
+#define FTGMAC100_ITC_TXINT_THR(x) (((x) & 0x7) << 12)
+#define FTGMAC100_ITC_TXINT_TIME_SEL (1 << 15)
+
+/*
+ * Automatic polling timer control register
+ */
+#define FTGMAC100_APTC_RXPOLL_CNT(x) (((x) & 0xf) << 0)
+#define FTGMAC100_APTC_RXPOLL_TIME_SEL (1 << 4)
+#define FTGMAC100_APTC_TXPOLL_CNT(x) (((x) & 0xf) << 8)
+#define FTGMAC100_APTC_TXPOLL_TIME_SEL (1 << 12)
+
+/*
+ * DMA burst length and arbitration control register
+ */
+#define FTGMAC100_DBLAC_RXFIFO_LTHR(x) (((x) & 0x7) << 0)
+#define FTGMAC100_DBLAC_RXFIFO_HTHR(x) (((x) & 0x7) << 3)
+#define FTGMAC100_DBLAC_RX_THR_EN (1 << 6)
+#define FTGMAC100_DBLAC_RXBURST_SIZE(x) (((x) & 0x3) << 8)
+#define FTGMAC100_DBLAC_TXBURST_SIZE(x) (((x) & 0x3) << 10)
+#define FTGMAC100_DBLAC_RXDES_SIZE(x) (((x) & 0xf) << 12)
+#define FTGMAC100_DBLAC_TXDES_SIZE(x) (((x) & 0xf) << 16)
+#define FTGMAC100_DBLAC_IFG_CNT(x) (((x) & 0x7) << 20)
+#define FTGMAC100_DBLAC_IFG_INC (1 << 23)
+
+/*
+ * DMA FIFO status register
+ */
+#define FTGMAC100_DMAFIFOS_RXDMA1_SM(dmafifos) ((dmafifos) & 0xf)
+#define FTGMAC100_DMAFIFOS_RXDMA2_SM(dmafifos) (((dmafifos) >> 4) & 0xf)
+#define FTGMAC100_DMAFIFOS_RXDMA3_SM(dmafifos) (((dmafifos) >> 8) & 0x7)
+#define FTGMAC100_DMAFIFOS_TXDMA1_SM(dmafifos) (((dmafifos) >> 12) & 0xf)
+#define FTGMAC100_DMAFIFOS_TXDMA2_SM(dmafifos) (((dmafifos) >> 16) & 0x3)
+#define FTGMAC100_DMAFIFOS_TXDMA3_SM(dmafifos) (((dmafifos) >> 18) & 0xf)
+#define FTGMAC100_DMAFIFOS_RXFIFO_EMPTY (1 << 26)
+#define FTGMAC100_DMAFIFOS_TXFIFO_EMPTY (1 << 27)
+#define FTGMAC100_DMAFIFOS_RXDMA_GRANT (1 << 28)
+#define FTGMAC100_DMAFIFOS_TXDMA_GRANT (1 << 29)
+#define FTGMAC100_DMAFIFOS_RXDMA_REQ (1 << 30)
+#define FTGMAC100_DMAFIFOS_TXDMA_REQ (1 << 31)
+
+/*
+ * Receive buffer size register
+ */
+#define FTGMAC100_RBSR_SIZE(x) ((x) & 0x3fff)
+
+/*
+ * MAC control register
+ */
+#define FTGMAC100_MACCR_TXDMA_EN (1 << 0)
+#define FTGMAC100_MACCR_RXDMA_EN (1 << 1)
+#define FTGMAC100_MACCR_TXMAC_EN (1 << 2)
+#define FTGMAC100_MACCR_RXMAC_EN (1 << 3)
+#define FTGMAC100_MACCR_RM_VLAN (1 << 4)
+#define FTGMAC100_MACCR_HPTXR_EN (1 << 5)
+#define FTGMAC100_MACCR_LOOP_EN (1 << 6)
+#define FTGMAC100_MACCR_ENRX_IN_HALFTX (1 << 7)
+#define FTGMAC100_MACCR_FULLDUP (1 << 8)
+#define FTGMAC100_MACCR_GIGA_MODE (1 << 9)
+#define FTGMAC100_MACCR_CRC_APD (1 << 10)
+#define FTGMAC100_MACCR_RX_RUNT (1 << 12)
+#define FTGMAC100_MACCR_JUMBO_LF (1 << 13)
+#define FTGMAC100_MACCR_RX_ALL (1 << 14)
+#define FTGMAC100_MACCR_HT_MULTI_EN (1 << 15)
+#define FTGMAC100_MACCR_RX_MULTIPKT (1 << 16)
+#define FTGMAC100_MACCR_RX_BROADPKT (1 << 17)
+#define FTGMAC100_MACCR_DISCARD_CRCERR (1 << 18)
+#define FTGMAC100_MACCR_FAST_MODE (1 << 19)
+#define FTGMAC100_MACCR_SW_RST (1 << 31)
+
+/*
+ * PHY control register
+ */
+#define FTGMAC100_PHYCR_MDC_CYCTHR_MASK 0x3f
+#define FTGMAC100_PHYCR_MDC_CYCTHR(x) ((x) & 0x3f)
+#define FTGMAC100_PHYCR_PHYAD(x) (((x) & 0x1f) << 16)
+#define FTGMAC100_PHYCR_REGAD(x) (((x) & 0x1f) << 21)
+#define FTGMAC100_PHYCR_MIIRD (1 << 26)
+#define FTGMAC100_PHYCR_MIIWR (1 << 27)
+
+/*
+ * PHY data register
+ */
+#define FTGMAC100_PHYDATA_MIIWDATA(x) ((x) & 0xffff)
+#define FTGMAC100_PHYDATA_MIIRDATA(phydata) (((phydata) >> 16) & 0xffff)
+
+/*
+ * Transmit descriptor, aligned to 16 bytes
+ */
+struct ftgmac100_txdes {
+ unsigned int txdes0;
+ unsigned int txdes1;
+ unsigned int txdes2; /* not used by HW */
+ unsigned int txdes3; /* TXBUF_BADR */
+} __attribute__ ((aligned(16)));
+
+#define FTGMAC100_TXDES0_TXBUF_SIZE(x) ((x) & 0x3fff)
+#define FTGMAC100_TXDES0_EDOTR (1 << 15)
+#define FTGMAC100_TXDES0_CRC_ERR (1 << 19)
+#define FTGMAC100_TXDES0_LTS (1 << 28)
+#define FTGMAC100_TXDES0_FTS (1 << 29)
+#define FTGMAC100_TXDES0_TXDMA_OWN (1 << 31)
+
+#define FTGMAC100_TXDES1_VLANTAG_CI(x) ((x) & 0xffff)
+#define FTGMAC100_TXDES1_INS_VLANTAG (1 << 16)
+#define FTGMAC100_TXDES1_TCP_CHKSUM (1 << 17)
+#define FTGMAC100_TXDES1_UDP_CHKSUM (1 << 18)
+#define FTGMAC100_TXDES1_IP_CHKSUM (1 << 19)
+#define FTGMAC100_TXDES1_LLC (1 << 22)
+#define FTGMAC100_TXDES1_TX2FIC (1 << 30)
+#define FTGMAC100_TXDES1_TXIC (1 << 31)
+
+/*
+ * Receive descriptor, aligned to 16 bytes
+ */
+struct ftgmac100_rxdes {
+ unsigned int rxdes0;
+ unsigned int rxdes1;
+ unsigned int rxdes2; /* not used by HW */
+ unsigned int rxdes3; /* RXBUF_BADR */
+} __attribute__ ((aligned(16)));
+
+#define FTGMAC100_RXDES0_VDBC 0x3fff
+#define FTGMAC100_RXDES0_EDORR (1 << 15)
+#define FTGMAC100_RXDES0_MULTICAST (1 << 16)
+#define FTGMAC100_RXDES0_BROADCAST (1 << 17)
+#define FTGMAC100_RXDES0_RX_ERR (1 << 18)
+#define FTGMAC100_RXDES0_CRC_ERR (1 << 19)
+#define FTGMAC100_RXDES0_FTL (1 << 20)
+#define FTGMAC100_RXDES0_RUNT (1 << 21)
+#define FTGMAC100_RXDES0_RX_ODD_NB (1 << 22)
+#define FTGMAC100_RXDES0_FIFO_FULL (1 << 23)
+#define FTGMAC100_RXDES0_PAUSE_OPCODE (1 << 24)
+#define FTGMAC100_RXDES0_PAUSE_FRAME (1 << 25)
+#define FTGMAC100_RXDES0_LRS (1 << 28)
+#define FTGMAC100_RXDES0_FRS (1 << 29)
+#define FTGMAC100_RXDES0_RXPKT_RDY (1 << 31)
+
+#define FTGMAC100_RXDES1_VLANTAG_CI 0xffff
+#define FTGMAC100_RXDES1_PROT_MASK (0x3 << 20)
+#define FTGMAC100_RXDES1_PROT_NONIP (0x0 << 20)
+#define FTGMAC100_RXDES1_PROT_IP (0x1 << 20)
+#define FTGMAC100_RXDES1_PROT_TCPIP (0x2 << 20)
+#define FTGMAC100_RXDES1_PROT_UDPIP (0x3 << 20)
+#define FTGMAC100_RXDES1_LLC (1 << 22)
+#define FTGMAC100_RXDES1_DF (1 << 23)
+#define FTGMAC100_RXDES1_VLANTAG_AVAIL (1 << 24)
+#define FTGMAC100_RXDES1_TCP_CHKSUM_ERR (1 << 25)
+#define FTGMAC100_RXDES1_UDP_CHKSUM_ERR (1 << 26)
+#define FTGMAC100_RXDES1_IP_CHKSUM_ERR (1 << 27)
+
+#endif /* __FTGMAC100_H */
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c
index 2dfcc80..3321d71 100644
--- a/drivers/net/gianfar.c
+++ b/drivers/net/gianfar.c
@@ -62,6 +62,9 @@
* The driver then cleans up the buffer.
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#define DEBUG
+
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/errno.h>
@@ -213,8 +216,7 @@
} else {
skb = gfar_new_skb(ndev);
if (!skb) {
- pr_err("%s: Can't allocate RX buffers\n",
- ndev->name);
+ netdev_err(ndev, "Can't allocate RX buffers\n");
goto err_rxalloc_fail;
}
rx_queue->rx_skbuff[j] = skb;
@@ -258,15 +260,14 @@
sizeof(struct rxbd8) * priv->total_rx_ring_size,
&addr, GFP_KERNEL);
if (!vaddr) {
- if (netif_msg_ifup(priv))
- pr_err("%s: Could not allocate buffer descriptors!\n",
- ndev->name);
+ netif_err(priv, ifup, ndev,
+ "Could not allocate buffer descriptors!\n");
return -ENOMEM;
}
for (i = 0; i < priv->num_tx_queues; i++) {
tx_queue = priv->tx_queue[i];
- tx_queue->tx_bd_base = (struct txbd8 *) vaddr;
+ tx_queue->tx_bd_base = vaddr;
tx_queue->tx_bd_dma_base = addr;
tx_queue->dev = ndev;
/* enet DMA only understands physical addresses */
@@ -277,7 +278,7 @@
/* Start the rx descriptor ring where the tx ring leaves off */
for (i = 0; i < priv->num_rx_queues; i++) {
rx_queue = priv->rx_queue[i];
- rx_queue->rx_bd_base = (struct rxbd8 *) vaddr;
+ rx_queue->rx_bd_base = vaddr;
rx_queue->rx_bd_dma_base = addr;
rx_queue->dev = ndev;
addr += sizeof (struct rxbd8) * rx_queue->rx_ring_size;
@@ -290,9 +291,8 @@
tx_queue->tx_skbuff = kmalloc(sizeof(*tx_queue->tx_skbuff) *
tx_queue->tx_ring_size, GFP_KERNEL);
if (!tx_queue->tx_skbuff) {
- if (netif_msg_ifup(priv))
- pr_err("%s: Could not allocate tx_skbuff\n",
- ndev->name);
+ netif_err(priv, ifup, ndev,
+ "Could not allocate tx_skbuff\n");
goto cleanup;
}
@@ -306,9 +306,8 @@
rx_queue->rx_ring_size, GFP_KERNEL);
if (!rx_queue->rx_skbuff) {
- if (netif_msg_ifup(priv))
- pr_err("%s: Could not allocate rx_skbuff\n",
- ndev->name);
+ netif_err(priv, ifup, ndev,
+ "Could not allocate rx_skbuff\n");
goto cleanup;
}
@@ -625,9 +624,9 @@
num_tx_qs = tx_queues ? *tx_queues : 1;
if (num_tx_qs > MAX_TX_QS) {
- printk(KERN_ERR "num_tx_qs(=%d) greater than MAX_TX_QS(=%d)\n",
- num_tx_qs, MAX_TX_QS);
- printk(KERN_ERR "Cannot do alloc_etherdev, aborting\n");
+ pr_err("num_tx_qs(=%d) greater than MAX_TX_QS(=%d)\n",
+ num_tx_qs, MAX_TX_QS);
+ pr_err("Cannot do alloc_etherdev, aborting\n");
return -EINVAL;
}
@@ -635,9 +634,9 @@
num_rx_qs = rx_queues ? *rx_queues : 1;
if (num_rx_qs > MAX_RX_QS) {
- printk(KERN_ERR "num_rx_qs(=%d) greater than MAX_RX_QS(=%d)\n",
- num_tx_qs, MAX_TX_QS);
- printk(KERN_ERR "Cannot do alloc_etherdev, aborting\n");
+ pr_err("num_rx_qs(=%d) greater than MAX_RX_QS(=%d)\n",
+ num_rx_qs, MAX_RX_QS);
+ pr_err("Cannot do alloc_etherdev, aborting\n");
return -EINVAL;
}
@@ -655,6 +654,11 @@
priv->num_rx_queues = num_rx_qs;
priv->num_grps = 0x0;
+ /* Init Rx queue filer rule set linked list*/
+ INIT_LIST_HEAD(&priv->rx_list.list);
+ priv->rx_list.count = 0;
+ mutex_init(&priv->rx_queue_access);
+
model = of_get_property(np, "model", NULL);
for (i = 0; i < MAXGROUPS; i++)
@@ -1148,9 +1152,8 @@
priv->rx_queue[i]->rxic = DEFAULT_RXIC;
}
- /* enable filer if using multiple RX queues*/
- if(priv->num_rx_queues > 1)
- priv->rx_filer_enable = 1;
+ /* always enable rx filer*/
+ priv->rx_filer_enable = 1;
/* Enable most messages by default */
priv->msg_enable = (NETIF_MSG_IFUP << 1 ) - 1;
@@ -1160,8 +1163,7 @@
err = register_netdev(dev);
if (err) {
- printk(KERN_ERR "%s: Cannot register net device, aborting.\n",
- dev->name);
+ pr_err("%s: Cannot register net device, aborting\n", dev->name);
goto register_fail;
}
@@ -1212,17 +1214,17 @@
gfar_init_sysfs(dev);
/* Print out the device info */
- printk(KERN_INFO DEVICE_NAME "%pM\n", dev->name, dev->dev_addr);
+ netdev_info(dev, "mac: %pM\n", dev->dev_addr);
/* Even more device info helps when determining which kernel */
/* provided which set of benchmarks. */
- printk(KERN_INFO "%s: Running with NAPI enabled\n", dev->name);
+ netdev_info(dev, "Running with NAPI enabled\n");
for (i = 0; i < priv->num_rx_queues; i++)
- printk(KERN_INFO "%s: RX BD ring size for Q[%d]: %d\n",
- dev->name, i, priv->rx_queue[i]->rx_ring_size);
+ netdev_info(dev, "RX BD ring size for Q[%d]: %d\n",
+ i, priv->rx_queue[i]->rx_ring_size);
for(i = 0; i < priv->num_tx_queues; i++)
- printk(KERN_INFO "%s: TX BD ring size for Q[%d]: %d\n",
- dev->name, i, priv->tx_queue[i]->tx_ring_size);
+ netdev_info(dev, "TX BD ring size for Q[%d]: %d\n",
+ i, priv->tx_queue[i]->tx_ring_size);
return 0;
@@ -1855,34 +1857,30 @@
* Transmit, and Receive */
if ((err = request_irq(grp->interruptError, gfar_error, 0,
grp->int_name_er,grp)) < 0) {
- if (netif_msg_intr(priv))
- printk(KERN_ERR "%s: Can't get IRQ %d\n",
- dev->name, grp->interruptError);
+ netif_err(priv, intr, dev, "Can't get IRQ %d\n",
+ grp->interruptError);
goto err_irq_fail;
}
if ((err = request_irq(grp->interruptTransmit, gfar_transmit,
0, grp->int_name_tx, grp)) < 0) {
- if (netif_msg_intr(priv))
- printk(KERN_ERR "%s: Can't get IRQ %d\n",
- dev->name, grp->interruptTransmit);
+ netif_err(priv, intr, dev, "Can't get IRQ %d\n",
+ grp->interruptTransmit);
goto tx_irq_fail;
}
if ((err = request_irq(grp->interruptReceive, gfar_receive, 0,
grp->int_name_rx, grp)) < 0) {
- if (netif_msg_intr(priv))
- printk(KERN_ERR "%s: Can't get IRQ %d\n",
- dev->name, grp->interruptReceive);
+ netif_err(priv, intr, dev, "Can't get IRQ %d\n",
+ grp->interruptReceive);
goto rx_irq_fail;
}
} else {
if ((err = request_irq(grp->interruptTransmit, gfar_interrupt, 0,
grp->int_name_tx, grp)) < 0) {
- if (netif_msg_intr(priv))
- printk(KERN_ERR "%s: Can't get IRQ %d\n",
- dev->name, grp->interruptTransmit);
+ netif_err(priv, intr, dev, "Can't get IRQ %d\n",
+ grp->interruptTransmit);
goto err_irq_fail;
}
}
@@ -2351,9 +2349,7 @@
frame_size += VLAN_HLEN;
if ((frame_size < 64) || (frame_size > JUMBO_FRAME_SIZE)) {
- if (netif_msg_drv(priv))
- printk(KERN_ERR "%s: Invalid MTU setting\n",
- dev->name);
+ netif_err(priv, drv, dev, "Invalid MTU setting\n");
return -EINVAL;
}
@@ -2773,9 +2769,7 @@
gfar_process_frame(dev, skb, amount_pull);
} else {
- if (netif_msg_rx_err(priv))
- printk(KERN_WARNING
- "%s: Missing skb!\n", dev->name);
+ netif_warn(priv, rx_err, dev, "Missing skb!\n");
rx_queue->stats.rx_dropped++;
priv->extra_stats.rx_skbmissing++;
}
@@ -2978,10 +2972,9 @@
ecntrl &= ~(ECNTRL_R100);
break;
default:
- if (netif_msg_link(priv))
- printk(KERN_WARNING
- "%s: Ack! Speed (%d) is not 10/100/1000!\n",
- dev->name, phydev->speed);
+ netif_warn(priv, link, dev,
+ "Ack! Speed (%d) is not 10/100/1000!\n",
+ phydev->speed);
break;
}
@@ -3186,8 +3179,8 @@
/* Hmm... */
if (netif_msg_rx_err(priv) || netif_msg_tx_err(priv))
- printk(KERN_DEBUG "%s: error interrupt (ievent=0x%08x imask=0x%08x)\n",
- dev->name, events, gfar_read(®s->imask));
+ netdev_dbg(dev, "error interrupt (ievent=0x%08x imask=0x%08x)\n",
+ events, gfar_read(®s->imask));
/* Update the error counters */
if (events & IEVENT_TXE) {
@@ -3200,9 +3193,8 @@
if (events & IEVENT_XFUN) {
unsigned long flags;
- if (netif_msg_tx_err(priv))
- printk(KERN_DEBUG "%s: TX FIFO underrun, "
- "packet dropped.\n", dev->name);
+ netif_dbg(priv, tx_err, dev,
+ "TX FIFO underrun, packet dropped\n");
dev->stats.tx_dropped++;
priv->extra_stats.tx_underrun++;
@@ -3215,8 +3207,7 @@
unlock_tx_qs(priv);
local_irq_restore(flags);
}
- if (netif_msg_tx_err(priv))
- printk(KERN_DEBUG "%s: Transmit Error\n", dev->name);
+ netif_dbg(priv, tx_err, dev, "Transmit Error\n");
}
if (events & IEVENT_BSY) {
dev->stats.rx_errors++;
@@ -3224,29 +3215,25 @@
gfar_receive(irq, grp_id);
- if (netif_msg_rx_err(priv))
- printk(KERN_DEBUG "%s: busy error (rstat: %x)\n",
- dev->name, gfar_read(®s->rstat));
+ netif_dbg(priv, rx_err, dev, "busy error (rstat: %x)\n",
+ gfar_read(®s->rstat));
}
if (events & IEVENT_BABR) {
dev->stats.rx_errors++;
priv->extra_stats.rx_babr++;
- if (netif_msg_rx_err(priv))
- printk(KERN_DEBUG "%s: babbling RX error\n", dev->name);
+ netif_dbg(priv, rx_err, dev, "babbling RX error\n");
}
if (events & IEVENT_EBERR) {
priv->extra_stats.eberr++;
- if (netif_msg_rx_err(priv))
- printk(KERN_DEBUG "%s: bus error\n", dev->name);
+ netif_dbg(priv, rx_err, dev, "bus error\n");
}
- if ((events & IEVENT_RXC) && netif_msg_rx_status(priv))
- printk(KERN_DEBUG "%s: control frame\n", dev->name);
+ if (events & IEVENT_RXC)
+ netif_dbg(priv, rx_status, dev, "control frame\n");
if (events & IEVENT_BABT) {
priv->extra_stats.tx_babt++;
- if (netif_msg_tx_err(priv))
- printk(KERN_DEBUG "%s: babbling TX error\n", dev->name);
+ netif_dbg(priv, tx_err, dev, "babbling TX error\n");
}
return IRQ_HANDLED;
}
diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h
index ba36dc7..76f14d04 100644
--- a/drivers/net/gianfar.h
+++ b/drivers/net/gianfar.h
@@ -47,6 +47,16 @@
#include <linux/workqueue.h>
#include <linux/ethtool.h>
+struct ethtool_flow_spec_container {
+ struct ethtool_rx_flow_spec fs;
+ struct list_head list;
+};
+
+struct ethtool_rx_list {
+ struct list_head list;
+ unsigned int count;
+};
+
/* The maximum number of packets to be handled in one call of gfar_poll */
#define GFAR_DEV_WEIGHT 64
@@ -168,6 +178,7 @@
#define MACCFG2_LENGTHCHECK 0x00000010
#define MACCFG2_MPEN 0x00000008
+#define ECNTRL_FIFM 0x00008000
#define ECNTRL_INIT_SETTINGS 0x00001000
#define ECNTRL_TBI_MODE 0x00000020
#define ECNTRL_REDUCED_MODE 0x00000010
@@ -271,6 +282,7 @@
#define RCTRL_TUCSEN 0x00000100
#define RCTRL_PRSDEP_MASK 0x000000c0
#define RCTRL_PRSDEP_INIT 0x000000c0
+#define RCTRL_PRSFM 0x00000020
#define RCTRL_PROM 0x00000008
#define RCTRL_EMEN 0x00000002
#define RCTRL_REQ_PARSER (RCTRL_VLEX | RCTRL_IPCSEN | \
@@ -1066,6 +1078,9 @@
struct vlan_group *vlgrp;
+ /* RX queue filer rule set*/
+ struct ethtool_rx_list rx_list;
+ struct mutex rx_queue_access;
/* Hash registers and their width */
u32 __iomem *hash_regs[16];
@@ -1142,6 +1157,16 @@
gfar_write(®s->rqfpr, fpr);
}
+static inline void gfar_read_filer(struct gfar_private *priv,
+ unsigned int far, unsigned int *fcr, unsigned int *fpr)
+{
+ struct gfar __iomem *regs = priv->gfargrp[0].regs;
+
+ gfar_write(®s->rqfar, far);
+ *fcr = gfar_read(®s->rqfcr);
+ *fpr = gfar_read(®s->rqfpr);
+}
+
extern void lock_rx_qs(struct gfar_private *priv);
extern void lock_tx_qs(struct gfar_private *priv);
extern void unlock_rx_qs(struct gfar_private *priv);
@@ -1159,4 +1184,32 @@
extern const struct ethtool_ops gfar_ethtool_ops;
+#define MAX_FILER_CACHE_IDX (2*(MAX_FILER_IDX))
+
+#define RQFCR_PID_PRI_MASK 0xFFFFFFF8
+#define RQFCR_PID_L4P_MASK 0xFFFFFF00
+#define RQFCR_PID_VID_MASK 0xFFFFF000
+#define RQFCR_PID_PORT_MASK 0xFFFF0000
+#define RQFCR_PID_MAC_MASK 0xFF000000
+
+struct gfar_mask_entry {
+ unsigned int mask; /* The mask value which is valid form start to end */
+ unsigned int start;
+ unsigned int end;
+ unsigned int block; /* Same block values indicate depended entries */
+};
+
+/* Represents a receive filer table entry */
+struct gfar_filer_entry {
+ u32 ctrl;
+ u32 prop;
+};
+
+
+/* The 20 additional entries are a shadow for one extra element */
+struct filer_table {
+ u32 index;
+ struct gfar_filer_entry fe[MAX_FILER_CACHE_IDX + 20];
+};
+
#endif /* __GIANFAR_H */
diff --git a/drivers/net/gianfar_ethtool.c b/drivers/net/gianfar_ethtool.c
index 239e333..2ecdc9a 100644
--- a/drivers/net/gianfar_ethtool.c
+++ b/drivers/net/gianfar_ethtool.c
@@ -16,6 +16,8 @@
* by reference.
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/errno.h>
@@ -37,6 +39,7 @@
#include <linux/ethtool.h>
#include <linux/mii.h>
#include <linux/phy.h>
+#include <linux/sort.h>
#include "gianfar.h"
@@ -375,13 +378,13 @@
/* Check the bounds of the values */
if (cvals->rx_coalesce_usecs > GFAR_MAX_COAL_USECS) {
pr_info("Coalescing is limited to %d microseconds\n",
- GFAR_MAX_COAL_USECS);
+ GFAR_MAX_COAL_USECS);
return -EINVAL;
}
if (cvals->rx_max_coalesced_frames > GFAR_MAX_COAL_FRAMES) {
pr_info("Coalescing is limited to %d frames\n",
- GFAR_MAX_COAL_FRAMES);
+ GFAR_MAX_COAL_FRAMES);
return -EINVAL;
}
@@ -404,13 +407,13 @@
/* Check the bounds of the values */
if (cvals->tx_coalesce_usecs > GFAR_MAX_COAL_USECS) {
pr_info("Coalescing is limited to %d microseconds\n",
- GFAR_MAX_COAL_USECS);
+ GFAR_MAX_COAL_USECS);
return -EINVAL;
}
if (cvals->tx_max_coalesced_frames > GFAR_MAX_COAL_FRAMES) {
pr_info("Coalescing is limited to %d frames\n",
- GFAR_MAX_COAL_FRAMES);
+ GFAR_MAX_COAL_FRAMES);
return -EINVAL;
}
@@ -464,8 +467,7 @@
return -EINVAL;
if (!is_power_of_2(rvals->rx_pending)) {
- printk("%s: Ring sizes must be a power of 2\n",
- dev->name);
+ netdev_err(dev, "Ring sizes must be a power of 2\n");
return -EINVAL;
}
@@ -473,8 +475,7 @@
return -EINVAL;
if (!is_power_of_2(rvals->tx_pending)) {
- printk("%s: Ring sizes must be a power of 2\n",
- dev->name);
+ netdev_err(dev, "Ring sizes must be a power of 2\n");
return -EINVAL;
}
@@ -700,7 +701,7 @@
cmp_rqfpr = RQFPR_IPV6 |RQFPR_UDP;
break;
default:
- printk(KERN_ERR "Right now this class is not supported\n");
+ pr_err("Right now this class is not supported\n");
return 0;
}
@@ -715,8 +716,7 @@
}
if (i == MAX_FILER_IDX + 1) {
- printk(KERN_ERR "No parse rule found, ");
- printk(KERN_ERR "can't create hash rules\n");
+ pr_err("No parse rule found, can't create hash rules\n");
return 0;
}
@@ -773,19 +773,945 @@
return 0;
}
+static int gfar_check_filer_hardware(struct gfar_private *priv)
+{
+ struct gfar __iomem *regs = NULL;
+ u32 i;
+
+ regs = priv->gfargrp[0].regs;
+
+ /* Check if we are in FIFO mode */
+ i = gfar_read(®s->ecntrl);
+ i &= ECNTRL_FIFM;
+ if (i == ECNTRL_FIFM) {
+ netdev_notice(priv->ndev, "Interface in FIFO mode\n");
+ i = gfar_read(®s->rctrl);
+ i &= RCTRL_PRSDEP_MASK | RCTRL_PRSFM;
+ if (i == (RCTRL_PRSDEP_MASK | RCTRL_PRSFM)) {
+ netdev_info(priv->ndev,
+ "Receive Queue Filtering enabled\n");
+ } else {
+ netdev_warn(priv->ndev,
+ "Receive Queue Filtering disabled\n");
+ return -EOPNOTSUPP;
+ }
+ }
+ /* Or in standard mode */
+ else {
+ i = gfar_read(®s->rctrl);
+ i &= RCTRL_PRSDEP_MASK;
+ if (i == RCTRL_PRSDEP_MASK) {
+ netdev_info(priv->ndev,
+ "Receive Queue Filtering enabled\n");
+ } else {
+ netdev_warn(priv->ndev,
+ "Receive Queue Filtering disabled\n");
+ return -EOPNOTSUPP;
+ }
+ }
+
+ /* Sets the properties for arbitrary filer rule
+ * to the first 4 Layer 4 Bytes */
+ regs->rbifx = 0xC0C1C2C3;
+ return 0;
+}
+
+static int gfar_comp_asc(const void *a, const void *b)
+{
+ return memcmp(a, b, 4);
+}
+
+static int gfar_comp_desc(const void *a, const void *b)
+{
+ return -memcmp(a, b, 4);
+}
+
+static void gfar_swap(void *a, void *b, int size)
+{
+ u32 *_a = a;
+ u32 *_b = b;
+
+ swap(_a[0], _b[0]);
+ swap(_a[1], _b[1]);
+ swap(_a[2], _b[2]);
+ swap(_a[3], _b[3]);
+}
+
+/* Write a mask to filer cache */
+static void gfar_set_mask(u32 mask, struct filer_table *tab)
+{
+ tab->fe[tab->index].ctrl = RQFCR_AND | RQFCR_PID_MASK | RQFCR_CMP_EXACT;
+ tab->fe[tab->index].prop = mask;
+ tab->index++;
+}
+
+/* Sets parse bits (e.g. IP or TCP) */
+static void gfar_set_parse_bits(u32 value, u32 mask, struct filer_table *tab)
+{
+ gfar_set_mask(mask, tab);
+ tab->fe[tab->index].ctrl = RQFCR_CMP_EXACT | RQFCR_PID_PARSE
+ | RQFCR_AND;
+ tab->fe[tab->index].prop = value;
+ tab->index++;
+}
+
+static void gfar_set_general_attribute(u32 value, u32 mask, u32 flag,
+ struct filer_table *tab)
+{
+ gfar_set_mask(mask, tab);
+ tab->fe[tab->index].ctrl = RQFCR_CMP_EXACT | RQFCR_AND | flag;
+ tab->fe[tab->index].prop = value;
+ tab->index++;
+}
+
+/*
+ * For setting a tuple of value and mask of type flag
+ * Example:
+ * IP-Src = 10.0.0.0/255.0.0.0
+ * value: 0x0A000000 mask: FF000000 flag: RQFPR_IPV4
+ *
+ * Ethtool gives us a value=0 and mask=~0 for don't care a tuple
+ * For a don't care mask it gives us a 0
+ *
+ * The check if don't care and the mask adjustment if mask=0 is done for VLAN
+ * and MAC stuff on an upper level (due to missing information on this level).
+ * For these guys we can discard them if they are value=0 and mask=0.
+ *
+ * Further the all masks are one-padded for better hardware efficiency.
+ */
+static void gfar_set_attribute(u32 value, u32 mask, u32 flag,
+ struct filer_table *tab)
+{
+ switch (flag) {
+ /* 3bit */
+ case RQFCR_PID_PRI:
+ if (!(value | mask))
+ return;
+ mask |= RQFCR_PID_PRI_MASK;
+ break;
+ /* 8bit */
+ case RQFCR_PID_L4P:
+ case RQFCR_PID_TOS:
+ if (!~(mask | RQFCR_PID_L4P_MASK))
+ return;
+ if (!mask)
+ mask = ~0;
+ else
+ mask |= RQFCR_PID_L4P_MASK;
+ break;
+ /* 12bit */
+ case RQFCR_PID_VID:
+ if (!(value | mask))
+ return;
+ mask |= RQFCR_PID_VID_MASK;
+ break;
+ /* 16bit */
+ case RQFCR_PID_DPT:
+ case RQFCR_PID_SPT:
+ case RQFCR_PID_ETY:
+ if (!~(mask | RQFCR_PID_PORT_MASK))
+ return;
+ if (!mask)
+ mask = ~0;
+ else
+ mask |= RQFCR_PID_PORT_MASK;
+ break;
+ /* 24bit */
+ case RQFCR_PID_DAH:
+ case RQFCR_PID_DAL:
+ case RQFCR_PID_SAH:
+ case RQFCR_PID_SAL:
+ if (!(value | mask))
+ return;
+ mask |= RQFCR_PID_MAC_MASK;
+ break;
+ /* for all real 32bit masks */
+ default:
+ if (!~mask)
+ return;
+ if (!mask)
+ mask = ~0;
+ break;
+ }
+ gfar_set_general_attribute(value, mask, flag, tab);
+}
+
+/* Translates value and mask for UDP, TCP or SCTP */
+static void gfar_set_basic_ip(struct ethtool_tcpip4_spec *value,
+ struct ethtool_tcpip4_spec *mask, struct filer_table *tab)
+{
+ gfar_set_attribute(value->ip4src, mask->ip4src, RQFCR_PID_SIA, tab);
+ gfar_set_attribute(value->ip4dst, mask->ip4dst, RQFCR_PID_DIA, tab);
+ gfar_set_attribute(value->pdst, mask->pdst, RQFCR_PID_DPT, tab);
+ gfar_set_attribute(value->psrc, mask->psrc, RQFCR_PID_SPT, tab);
+ gfar_set_attribute(value->tos, mask->tos, RQFCR_PID_TOS, tab);
+}
+
+/* Translates value and mask for RAW-IP4 */
+static void gfar_set_user_ip(struct ethtool_usrip4_spec *value,
+ struct ethtool_usrip4_spec *mask, struct filer_table *tab)
+{
+ gfar_set_attribute(value->ip4src, mask->ip4src, RQFCR_PID_SIA, tab);
+ gfar_set_attribute(value->ip4dst, mask->ip4dst, RQFCR_PID_DIA, tab);
+ gfar_set_attribute(value->tos, mask->tos, RQFCR_PID_TOS, tab);
+ gfar_set_attribute(value->proto, mask->proto, RQFCR_PID_L4P, tab);
+ gfar_set_attribute(value->l4_4_bytes, mask->l4_4_bytes, RQFCR_PID_ARB,
+ tab);
+
+}
+
+/* Translates value and mask for ETHER spec */
+static void gfar_set_ether(struct ethhdr *value, struct ethhdr *mask,
+ struct filer_table *tab)
+{
+ u32 upper_temp_mask = 0;
+ u32 lower_temp_mask = 0;
+ /* Source address */
+ if (!is_broadcast_ether_addr(mask->h_source)) {
+
+ if (is_zero_ether_addr(mask->h_source)) {
+ upper_temp_mask = 0xFFFFFFFF;
+ lower_temp_mask = 0xFFFFFFFF;
+ } else {
+ upper_temp_mask = mask->h_source[0] << 16
+ | mask->h_source[1] << 8
+ | mask->h_source[2];
+ lower_temp_mask = mask->h_source[3] << 16
+ | mask->h_source[4] << 8
+ | mask->h_source[5];
+ }
+ /* Upper 24bit */
+ gfar_set_attribute(
+ value->h_source[0] << 16 | value->h_source[1]
+ << 8 | value->h_source[2],
+ upper_temp_mask, RQFCR_PID_SAH, tab);
+ /* And the same for the lower part */
+ gfar_set_attribute(
+ value->h_source[3] << 16 | value->h_source[4]
+ << 8 | value->h_source[5],
+ lower_temp_mask, RQFCR_PID_SAL, tab);
+ }
+ /* Destination address */
+ if (!is_broadcast_ether_addr(mask->h_dest)) {
+
+ /* Special for destination is limited broadcast */
+ if ((is_broadcast_ether_addr(value->h_dest)
+ && is_zero_ether_addr(mask->h_dest))) {
+ gfar_set_parse_bits(RQFPR_EBC, RQFPR_EBC, tab);
+ } else {
+
+ if (is_zero_ether_addr(mask->h_dest)) {
+ upper_temp_mask = 0xFFFFFFFF;
+ lower_temp_mask = 0xFFFFFFFF;
+ } else {
+ upper_temp_mask = mask->h_dest[0] << 16
+ | mask->h_dest[1] << 8
+ | mask->h_dest[2];
+ lower_temp_mask = mask->h_dest[3] << 16
+ | mask->h_dest[4] << 8
+ | mask->h_dest[5];
+ }
+
+ /* Upper 24bit */
+ gfar_set_attribute(
+ value->h_dest[0] << 16
+ | value->h_dest[1] << 8
+ | value->h_dest[2],
+ upper_temp_mask, RQFCR_PID_DAH, tab);
+ /* And the same for the lower part */
+ gfar_set_attribute(
+ value->h_dest[3] << 16
+ | value->h_dest[4] << 8
+ | value->h_dest[5],
+ lower_temp_mask, RQFCR_PID_DAL, tab);
+ }
+ }
+
+ gfar_set_attribute(value->h_proto, mask->h_proto, RQFCR_PID_ETY, tab);
+
+}
+
+/* Convert a rule to binary filter format of gianfar */
+static int gfar_convert_to_filer(struct ethtool_rx_flow_spec *rule,
+ struct filer_table *tab)
+{
+ u32 vlan = 0, vlan_mask = 0;
+ u32 id = 0, id_mask = 0;
+ u32 cfi = 0, cfi_mask = 0;
+ u32 prio = 0, prio_mask = 0;
+
+ u32 old_index = tab->index;
+
+ /* Check if vlan is wanted */
+ if ((rule->flow_type & FLOW_EXT) && (rule->m_ext.vlan_tci != 0xFFFF)) {
+ if (!rule->m_ext.vlan_tci)
+ rule->m_ext.vlan_tci = 0xFFFF;
+
+ vlan = RQFPR_VLN;
+ vlan_mask = RQFPR_VLN;
+
+ /* Separate the fields */
+ id = rule->h_ext.vlan_tci & 0xFFF;
+ id_mask = rule->m_ext.vlan_tci & 0xFFF;
+ cfi = (rule->h_ext.vlan_tci >> 12) & 1;
+ cfi_mask = (rule->m_ext.vlan_tci >> 12) & 1;
+ prio = (rule->h_ext.vlan_tci >> 13) & 0x7;
+ prio_mask = (rule->m_ext.vlan_tci >> 13) & 0x7;
+
+ if (cfi == 1 && cfi_mask == 1) {
+ vlan |= RQFPR_CFI;
+ vlan_mask |= RQFPR_CFI;
+ } else if (cfi == 0 && cfi_mask == 1) {
+ vlan_mask |= RQFPR_CFI;
+ }
+ }
+
+ switch (rule->flow_type & ~FLOW_EXT) {
+ case TCP_V4_FLOW:
+ gfar_set_parse_bits(RQFPR_IPV4 | RQFPR_TCP | vlan,
+ RQFPR_IPV4 | RQFPR_TCP | vlan_mask, tab);
+ gfar_set_basic_ip(&rule->h_u.tcp_ip4_spec,
+ &rule->m_u.tcp_ip4_spec, tab);
+ break;
+ case UDP_V4_FLOW:
+ gfar_set_parse_bits(RQFPR_IPV4 | RQFPR_UDP | vlan,
+ RQFPR_IPV4 | RQFPR_UDP | vlan_mask, tab);
+ gfar_set_basic_ip(&rule->h_u.udp_ip4_spec,
+ &rule->m_u.udp_ip4_spec, tab);
+ break;
+ case SCTP_V4_FLOW:
+ gfar_set_parse_bits(RQFPR_IPV4 | vlan, RQFPR_IPV4 | vlan_mask,
+ tab);
+ gfar_set_attribute(132, 0, RQFCR_PID_L4P, tab);
+ gfar_set_basic_ip((struct ethtool_tcpip4_spec *) &rule->h_u,
+ (struct ethtool_tcpip4_spec *) &rule->m_u, tab);
+ break;
+ case IP_USER_FLOW:
+ gfar_set_parse_bits(RQFPR_IPV4 | vlan, RQFPR_IPV4 | vlan_mask,
+ tab);
+ gfar_set_user_ip((struct ethtool_usrip4_spec *) &rule->h_u,
+ (struct ethtool_usrip4_spec *) &rule->m_u, tab);
+ break;
+ case ETHER_FLOW:
+ if (vlan)
+ gfar_set_parse_bits(vlan, vlan_mask, tab);
+ gfar_set_ether((struct ethhdr *) &rule->h_u,
+ (struct ethhdr *) &rule->m_u, tab);
+ break;
+ default:
+ return -1;
+ }
+
+ /* Set the vlan attributes in the end */
+ if (vlan) {
+ gfar_set_attribute(id, id_mask, RQFCR_PID_VID, tab);
+ gfar_set_attribute(prio, prio_mask, RQFCR_PID_PRI, tab);
+ }
+
+ /* If there has been nothing written till now, it must be a default */
+ if (tab->index == old_index) {
+ gfar_set_mask(0xFFFFFFFF, tab);
+ tab->fe[tab->index].ctrl = 0x20;
+ tab->fe[tab->index].prop = 0x0;
+ tab->index++;
+ }
+
+ /* Remove last AND */
+ tab->fe[tab->index - 1].ctrl &= (~RQFCR_AND);
+
+ /* Specify which queue to use or to drop */
+ if (rule->ring_cookie == RX_CLS_FLOW_DISC)
+ tab->fe[tab->index - 1].ctrl |= RQFCR_RJE;
+ else
+ tab->fe[tab->index - 1].ctrl |= (rule->ring_cookie << 10);
+
+ /* Only big enough entries can be clustered */
+ if (tab->index > (old_index + 2)) {
+ tab->fe[old_index + 1].ctrl |= RQFCR_CLE;
+ tab->fe[tab->index - 1].ctrl |= RQFCR_CLE;
+ }
+
+ /* In rare cases the cache can be full while there is free space in hw */
+ if (tab->index > MAX_FILER_CACHE_IDX - 1)
+ return -EBUSY;
+
+ return 0;
+}
+
+/* Copy size filer entries */
+static void gfar_copy_filer_entries(struct gfar_filer_entry dst[0],
+ struct gfar_filer_entry src[0], s32 size)
+{
+ while (size > 0) {
+ size--;
+ dst[size].ctrl = src[size].ctrl;
+ dst[size].prop = src[size].prop;
+ }
+}
+
+/* Delete the contents of the filer-table between start and end
+ * and collapse them */
+static int gfar_trim_filer_entries(u32 begin, u32 end, struct filer_table *tab)
+{
+ int length;
+ if (end > MAX_FILER_CACHE_IDX || end < begin)
+ return -EINVAL;
+
+ end++;
+ length = end - begin;
+
+ /* Copy */
+ while (end < tab->index) {
+ tab->fe[begin].ctrl = tab->fe[end].ctrl;
+ tab->fe[begin++].prop = tab->fe[end++].prop;
+
+ }
+ /* Fill up with don't cares */
+ while (begin < tab->index) {
+ tab->fe[begin].ctrl = 0x60;
+ tab->fe[begin].prop = 0xFFFFFFFF;
+ begin++;
+ }
+
+ tab->index -= length;
+ return 0;
+}
+
+/* Make space on the wanted location */
+static int gfar_expand_filer_entries(u32 begin, u32 length,
+ struct filer_table *tab)
+{
+ if (length == 0 || length + tab->index > MAX_FILER_CACHE_IDX || begin
+ > MAX_FILER_CACHE_IDX)
+ return -EINVAL;
+
+ gfar_copy_filer_entries(&(tab->fe[begin + length]), &(tab->fe[begin]),
+ tab->index - length + 1);
+
+ tab->index += length;
+ return 0;
+}
+
+static int gfar_get_next_cluster_start(int start, struct filer_table *tab)
+{
+ for (; (start < tab->index) && (start < MAX_FILER_CACHE_IDX - 1); start++) {
+ if ((tab->fe[start].ctrl & (RQFCR_AND | RQFCR_CLE))
+ == (RQFCR_AND | RQFCR_CLE))
+ return start;
+ }
+ return -1;
+}
+
+static int gfar_get_next_cluster_end(int start, struct filer_table *tab)
+{
+ for (; (start < tab->index) && (start < MAX_FILER_CACHE_IDX - 1); start++) {
+ if ((tab->fe[start].ctrl & (RQFCR_AND | RQFCR_CLE))
+ == (RQFCR_CLE))
+ return start;
+ }
+ return -1;
+}
+
+/*
+ * Uses hardwares clustering option to reduce
+ * the number of filer table entries
+ */
+static void gfar_cluster_filer(struct filer_table *tab)
+{
+ s32 i = -1, j, iend, jend;
+
+ while ((i = gfar_get_next_cluster_start(++i, tab)) != -1) {
+ j = i;
+ while ((j = gfar_get_next_cluster_start(++j, tab)) != -1) {
+ /*
+ * The cluster entries self and the previous one
+ * (a mask) must be identical!
+ */
+ if (tab->fe[i].ctrl != tab->fe[j].ctrl)
+ break;
+ if (tab->fe[i].prop != tab->fe[j].prop)
+ break;
+ if (tab->fe[i - 1].ctrl != tab->fe[j - 1].ctrl)
+ break;
+ if (tab->fe[i - 1].prop != tab->fe[j - 1].prop)
+ break;
+ iend = gfar_get_next_cluster_end(i, tab);
+ jend = gfar_get_next_cluster_end(j, tab);
+ if (jend == -1 || iend == -1)
+ break;
+ /*
+ * First we make some free space, where our cluster
+ * element should be. Then we copy it there and finally
+ * delete in from its old location.
+ */
+
+ if (gfar_expand_filer_entries(iend, (jend - j), tab)
+ == -EINVAL)
+ break;
+
+ gfar_copy_filer_entries(&(tab->fe[iend + 1]),
+ &(tab->fe[jend + 1]), jend - j);
+
+ if (gfar_trim_filer_entries(jend - 1,
+ jend + (jend - j), tab) == -EINVAL)
+ return;
+
+ /* Mask out cluster bit */
+ tab->fe[iend].ctrl &= ~(RQFCR_CLE);
+ }
+ }
+}
+
+/* Swaps the 0xFF80 masked bits of a1<>a2 and b1<>b2 */
+static void gfar_swap_ff80_bits(struct gfar_filer_entry *a1,
+ struct gfar_filer_entry *a2, struct gfar_filer_entry *b1,
+ struct gfar_filer_entry *b2)
+{
+ u32 temp[4];
+ temp[0] = a1->ctrl & 0xFF80;
+ temp[1] = a2->ctrl & 0xFF80;
+ temp[2] = b1->ctrl & 0xFF80;
+ temp[3] = b2->ctrl & 0xFF80;
+
+ a1->ctrl &= ~0xFF80;
+ a2->ctrl &= ~0xFF80;
+ b1->ctrl &= ~0xFF80;
+ b2->ctrl &= ~0xFF80;
+
+ a1->ctrl |= temp[1];
+ a2->ctrl |= temp[0];
+ b1->ctrl |= temp[3];
+ b2->ctrl |= temp[2];
+}
+
+/*
+ * Generate a list consisting of masks values with their start and
+ * end of validity and block as indicator for parts belonging
+ * together (glued by ANDs) in mask_table
+ */
+static u32 gfar_generate_mask_table(struct gfar_mask_entry *mask_table,
+ struct filer_table *tab)
+{
+ u32 i, and_index = 0, block_index = 1;
+
+ for (i = 0; i < tab->index; i++) {
+
+ /* LSByte of control = 0 sets a mask */
+ if (!(tab->fe[i].ctrl & 0xF)) {
+ mask_table[and_index].mask = tab->fe[i].prop;
+ mask_table[and_index].start = i;
+ mask_table[and_index].block = block_index;
+ if (and_index >= 1)
+ mask_table[and_index - 1].end = i - 1;
+ and_index++;
+ }
+ /* cluster starts will be separated because they should
+ * hold their position */
+ if (tab->fe[i].ctrl & RQFCR_CLE)
+ block_index++;
+ /* A not set AND indicates the end of a depended block */
+ if (!(tab->fe[i].ctrl & RQFCR_AND))
+ block_index++;
+
+ }
+
+ mask_table[and_index - 1].end = i - 1;
+
+ return and_index;
+}
+
+/*
+ * Sorts the entries of mask_table by the values of the masks.
+ * Important: The 0xFF80 flags of the first and last entry of a
+ * block must hold their position (which queue, CLusterEnable, ReJEct,
+ * AND)
+ */
+static void gfar_sort_mask_table(struct gfar_mask_entry *mask_table,
+ struct filer_table *temp_table, u32 and_index)
+{
+ /* Pointer to compare function (_asc or _desc) */
+ int (*gfar_comp)(const void *, const void *);
+
+ u32 i, size = 0, start = 0, prev = 1;
+ u32 old_first, old_last, new_first, new_last;
+
+ gfar_comp = &gfar_comp_desc;
+
+ for (i = 0; i < and_index; i++) {
+
+ if (prev != mask_table[i].block) {
+ old_first = mask_table[start].start + 1;
+ old_last = mask_table[i - 1].end;
+ sort(mask_table + start, size,
+ sizeof(struct gfar_mask_entry),
+ gfar_comp, &gfar_swap);
+
+ /* Toggle order for every block. This makes the
+ * thing more efficient! */
+ if (gfar_comp == gfar_comp_desc)
+ gfar_comp = &gfar_comp_asc;
+ else
+ gfar_comp = &gfar_comp_desc;
+
+ new_first = mask_table[start].start + 1;
+ new_last = mask_table[i - 1].end;
+
+ gfar_swap_ff80_bits(&temp_table->fe[new_first],
+ &temp_table->fe[old_first],
+ &temp_table->fe[new_last],
+ &temp_table->fe[old_last]);
+
+ start = i;
+ size = 0;
+ }
+ size++;
+ prev = mask_table[i].block;
+ }
+
+}
+
+/*
+ * Reduces the number of masks needed in the filer table to save entries
+ * This is done by sorting the masks of a depended block. A depended block is
+ * identified by gluing ANDs or CLE. The sorting order toggles after every
+ * block. Of course entries in scope of a mask must change their location with
+ * it.
+ */
+static int gfar_optimize_filer_masks(struct filer_table *tab)
+{
+ struct filer_table *temp_table;
+ struct gfar_mask_entry *mask_table;
+
+ u32 and_index = 0, previous_mask = 0, i = 0, j = 0, size = 0;
+ s32 ret = 0;
+
+ /* We need a copy of the filer table because
+ * we want to change its order */
+ temp_table = kmalloc(sizeof(*temp_table), GFP_KERNEL);
+ if (temp_table == NULL)
+ return -ENOMEM;
+ memcpy(temp_table, tab, sizeof(*temp_table));
+
+ mask_table = kcalloc(MAX_FILER_CACHE_IDX / 2 + 1,
+ sizeof(struct gfar_mask_entry), GFP_KERNEL);
+
+ if (mask_table == NULL) {
+ ret = -ENOMEM;
+ goto end;
+ }
+
+ and_index = gfar_generate_mask_table(mask_table, tab);
+
+ gfar_sort_mask_table(mask_table, temp_table, and_index);
+
+ /* Now we can copy the data from our duplicated filer table to
+ * the real one in the order the mask table says */
+ for (i = 0; i < and_index; i++) {
+ size = mask_table[i].end - mask_table[i].start + 1;
+ gfar_copy_filer_entries(&(tab->fe[j]),
+ &(temp_table->fe[mask_table[i].start]), size);
+ j += size;
+ }
+
+ /* And finally we just have to check for duplicated masks and drop the
+ * second ones */
+ for (i = 0; i < tab->index && i < MAX_FILER_CACHE_IDX; i++) {
+ if (tab->fe[i].ctrl == 0x80) {
+ previous_mask = i++;
+ break;
+ }
+ }
+ for (; i < tab->index && i < MAX_FILER_CACHE_IDX; i++) {
+ if (tab->fe[i].ctrl == 0x80) {
+ if (tab->fe[i].prop == tab->fe[previous_mask].prop) {
+ /* Two identical ones found!
+ * So drop the second one! */
+ gfar_trim_filer_entries(i, i, tab);
+ } else
+ /* Not identical! */
+ previous_mask = i;
+ }
+ }
+
+ kfree(mask_table);
+end: kfree(temp_table);
+ return ret;
+}
+
+/* Write the bit-pattern from software's buffer to hardware registers */
+static int gfar_write_filer_table(struct gfar_private *priv,
+ struct filer_table *tab)
+{
+ u32 i = 0;
+ if (tab->index > MAX_FILER_IDX - 1)
+ return -EBUSY;
+
+ /* Avoid inconsistent filer table to be processed */
+ lock_rx_qs(priv);
+
+ /* Fill regular entries */
+ for (; i < MAX_FILER_IDX - 1 && (tab->fe[i].ctrl | tab->fe[i].ctrl); i++)
+ gfar_write_filer(priv, i, tab->fe[i].ctrl, tab->fe[i].prop);
+ /* Fill the rest with fall-troughs */
+ for (; i < MAX_FILER_IDX - 1; i++)
+ gfar_write_filer(priv, i, 0x60, 0xFFFFFFFF);
+ /* Last entry must be default accept
+ * because that's what people expect */
+ gfar_write_filer(priv, i, 0x20, 0x0);
+
+ unlock_rx_qs(priv);
+
+ return 0;
+}
+
+static int gfar_check_capability(struct ethtool_rx_flow_spec *flow,
+ struct gfar_private *priv)
+{
+
+ if (flow->flow_type & FLOW_EXT) {
+ if (~flow->m_ext.data[0] || ~flow->m_ext.data[1])
+ netdev_warn(priv->ndev,
+ "User-specific data not supported!\n");
+ if (~flow->m_ext.vlan_etype)
+ netdev_warn(priv->ndev,
+ "VLAN-etype not supported!\n");
+ }
+ if (flow->flow_type == IP_USER_FLOW)
+ if (flow->h_u.usr_ip4_spec.ip_ver != ETH_RX_NFC_IP4)
+ netdev_warn(priv->ndev,
+ "IP-Version differing from IPv4 not supported!\n");
+
+ return 0;
+}
+
+static int gfar_process_filer_changes(struct gfar_private *priv)
+{
+ struct ethtool_flow_spec_container *j;
+ struct filer_table *tab;
+ s32 i = 0;
+ s32 ret = 0;
+
+ /* So index is set to zero, too! */
+ tab = kzalloc(sizeof(*tab), GFP_KERNEL);
+ if (tab == NULL)
+ return -ENOMEM;
+
+ /* Now convert the existing filer data from flow_spec into
+ * filer tables binary format */
+ list_for_each_entry(j, &priv->rx_list.list, list) {
+ ret = gfar_convert_to_filer(&j->fs, tab);
+ if (ret == -EBUSY) {
+ netdev_err(priv->ndev, "Rule not added: No free space!\n");
+ goto end;
+ }
+ if (ret == -1) {
+ netdev_err(priv->ndev, "Rule not added: Unsupported Flow-type!\n");
+ goto end;
+ }
+ }
+
+ i = tab->index;
+
+ /* Optimizations to save entries */
+ gfar_cluster_filer(tab);
+ gfar_optimize_filer_masks(tab);
+
+ pr_debug("\n\tSummary:\n"
+ "\tData on hardware: %d\n"
+ "\tCompression rate: %d%%\n",
+ tab->index, 100 - (100 * tab->index) / i);
+
+ /* Write everything to hardware */
+ ret = gfar_write_filer_table(priv, tab);
+ if (ret == -EBUSY) {
+ netdev_err(priv->ndev, "Rule not added: No free space!\n");
+ goto end;
+ }
+
+end: kfree(tab);
+ return ret;
+}
+
+static void gfar_invert_masks(struct ethtool_rx_flow_spec *flow)
+{
+ u32 i = 0;
+
+ for (i = 0; i < sizeof(flow->m_u); i++)
+ flow->m_u.hdata[i] ^= 0xFF;
+
+ flow->m_ext.vlan_etype ^= 0xFFFF;
+ flow->m_ext.vlan_tci ^= 0xFFFF;
+ flow->m_ext.data[0] ^= ~0;
+ flow->m_ext.data[1] ^= ~0;
+}
+
+static int gfar_add_cls(struct gfar_private *priv,
+ struct ethtool_rx_flow_spec *flow)
+{
+ struct ethtool_flow_spec_container *temp, *comp;
+ int ret = 0;
+
+ temp = kmalloc(sizeof(*temp), GFP_KERNEL);
+ if (temp == NULL)
+ return -ENOMEM;
+ memcpy(&temp->fs, flow, sizeof(temp->fs));
+
+ gfar_invert_masks(&temp->fs);
+ ret = gfar_check_capability(&temp->fs, priv);
+ if (ret)
+ goto clean_mem;
+ /* Link in the new element at the right @location */
+ if (list_empty(&priv->rx_list.list)) {
+ ret = gfar_check_filer_hardware(priv);
+ if (ret != 0)
+ goto clean_mem;
+ list_add(&temp->list, &priv->rx_list.list);
+ goto process;
+ } else {
+
+ list_for_each_entry(comp, &priv->rx_list.list, list) {
+ if (comp->fs.location > flow->location) {
+ list_add_tail(&temp->list, &comp->list);
+ goto process;
+ }
+ if (comp->fs.location == flow->location) {
+ netdev_err(priv->ndev,
+ "Rule not added: ID %d not free!\n",
+ flow->location);
+ ret = -EBUSY;
+ goto clean_mem;
+ }
+ }
+ list_add_tail(&temp->list, &priv->rx_list.list);
+ }
+
+process:
+ ret = gfar_process_filer_changes(priv);
+ if (ret)
+ goto clean_list;
+ priv->rx_list.count++;
+ return ret;
+
+clean_list:
+ list_del(&temp->list);
+clean_mem:
+ kfree(temp);
+ return ret;
+}
+
+static int gfar_del_cls(struct gfar_private *priv, u32 loc)
+{
+ struct ethtool_flow_spec_container *comp;
+ u32 ret = -EINVAL;
+
+ if (list_empty(&priv->rx_list.list))
+ return ret;
+
+ list_for_each_entry(comp, &priv->rx_list.list, list) {
+ if (comp->fs.location == loc) {
+ list_del(&comp->list);
+ kfree(comp);
+ priv->rx_list.count--;
+ gfar_process_filer_changes(priv);
+ ret = 0;
+ break;
+ }
+ }
+
+ return ret;
+
+}
+
+static int gfar_get_cls(struct gfar_private *priv, struct ethtool_rxnfc *cmd)
+{
+ struct ethtool_flow_spec_container *comp;
+ u32 ret = -EINVAL;
+
+ list_for_each_entry(comp, &priv->rx_list.list, list) {
+ if (comp->fs.location == cmd->fs.location) {
+ memcpy(&cmd->fs, &comp->fs, sizeof(cmd->fs));
+ gfar_invert_masks(&cmd->fs);
+ ret = 0;
+ break;
+ }
+ }
+
+ return ret;
+}
+
+static int gfar_get_cls_all(struct gfar_private *priv,
+ struct ethtool_rxnfc *cmd, u32 *rule_locs)
+{
+ struct ethtool_flow_spec_container *comp;
+ u32 i = 0;
+
+ list_for_each_entry(comp, &priv->rx_list.list, list) {
+ if (i <= cmd->rule_cnt) {
+ rule_locs[i] = comp->fs.location;
+ i++;
+ }
+ }
+
+ cmd->data = MAX_FILER_IDX;
+
+ return 0;
+}
+
static int gfar_set_nfc(struct net_device *dev, struct ethtool_rxnfc *cmd)
{
struct gfar_private *priv = netdev_priv(dev);
int ret = 0;
- switch(cmd->cmd) {
+ mutex_lock(&priv->rx_queue_access);
+
+ switch (cmd->cmd) {
case ETHTOOL_SRXFH:
ret = gfar_set_hash_opts(priv, cmd);
break;
+ case ETHTOOL_SRXCLSRLINS:
+ if (cmd->fs.ring_cookie != RX_CLS_FLOW_DISC &&
+ cmd->fs.ring_cookie >= priv->num_rx_queues) {
+ ret = -EINVAL;
+ break;
+ }
+ ret = gfar_add_cls(priv, &cmd->fs);
+ break;
+ case ETHTOOL_SRXCLSRLDEL:
+ ret = gfar_del_cls(priv, cmd->fs.location);
+ break;
default:
ret = -EINVAL;
}
+ mutex_unlock(&priv->rx_queue_access);
+
+ return ret;
+}
+
+static int gfar_get_nfc(struct net_device *dev, struct ethtool_rxnfc *cmd,
+ void *rule_locs)
+{
+ struct gfar_private *priv = netdev_priv(dev);
+ int ret = 0;
+
+ switch (cmd->cmd) {
+ case ETHTOOL_GRXRINGS:
+ cmd->data = priv->num_rx_queues;
+ break;
+ case ETHTOOL_GRXCLSRLCNT:
+ cmd->rule_cnt = priv->rx_list.count;
+ break;
+ case ETHTOOL_GRXCLSRULE:
+ ret = gfar_get_cls(priv, cmd);
+ break;
+ case ETHTOOL_GRXCLSRLALL:
+ ret = gfar_get_cls_all(priv, cmd, (u32 *) rule_locs);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
return ret;
}
@@ -810,4 +1736,5 @@
.set_wol = gfar_set_wol,
#endif
.set_rxnfc = gfar_set_nfc,
+ .get_rxnfc = gfar_get_nfc,
};
diff --git a/drivers/net/greth.c b/drivers/net/greth.c
index 672f096..16ce45c 100644
--- a/drivers/net/greth.c
+++ b/drivers/net/greth.c
@@ -22,9 +22,11 @@
* Marko Isomaki
*/
+#include <linux/dma-mapping.h>
#include <linux/module.h>
#include <linux/uaccess.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/ethtool.h>
diff --git a/drivers/net/hamachi.c b/drivers/net/hamachi.c
index a09041a..c274b3d 100644
--- a/drivers/net/hamachi.c
+++ b/drivers/net/hamachi.c
@@ -648,13 +648,13 @@
ring_space = pci_alloc_consistent(pdev, TX_TOTAL_SIZE, &ring_dma);
if (!ring_space)
goto err_out_cleardev;
- hmp->tx_ring = (struct hamachi_desc *)ring_space;
+ hmp->tx_ring = ring_space;
hmp->tx_ring_dma = ring_dma;
ring_space = pci_alloc_consistent(pdev, RX_TOTAL_SIZE, &ring_dma);
if (!ring_space)
goto err_out_unmap_tx;
- hmp->rx_ring = (struct hamachi_desc *)ring_space;
+ hmp->rx_ring = ring_space;
hmp->rx_ring_dma = ring_dma;
/* Check for options being passed in */
diff --git a/drivers/net/hamradio/baycom_ser_fdx.c b/drivers/net/hamradio/baycom_ser_fdx.c
index 99cdce3..a974727 100644
--- a/drivers/net/hamradio/baycom_ser_fdx.c
+++ b/drivers/net/hamradio/baycom_ser_fdx.c
@@ -76,6 +76,7 @@
#include <linux/ioport.h>
#include <linux/string.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/hdlcdrv.h>
#include <linux/baycom.h>
#include <linux/jiffies.h>
diff --git a/drivers/net/hamradio/baycom_ser_hdx.c b/drivers/net/hamradio/baycom_ser_hdx.c
index d92fe6c..e349d86 100644
--- a/drivers/net/hamradio/baycom_ser_hdx.c
+++ b/drivers/net/hamradio/baycom_ser_hdx.c
@@ -66,6 +66,7 @@
#include <linux/ioport.h>
#include <linux/string.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <linux/hdlcdrv.h>
diff --git a/drivers/net/hp-plus.c b/drivers/net/hp-plus.c
index 82bffc3..2991736 100644
--- a/drivers/net/hp-plus.c
+++ b/drivers/net/hp-plus.c
@@ -30,6 +30,7 @@
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/delay.h>
#include <asm/system.h>
diff --git a/drivers/net/hp.c b/drivers/net/hp.c
index ef20143..18564d4 100644
--- a/drivers/net/hp.c
+++ b/drivers/net/hp.c
@@ -30,6 +30,7 @@
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/delay.h>
#include <asm/system.h>
diff --git a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c
index b388d78..838c5b6 100644
--- a/drivers/net/ibmveth.c
+++ b/drivers/net/ibmveth.c
@@ -34,6 +34,7 @@
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/mm.h>
#include <linux/pm.h>
#include <linux/ethtool.h>
diff --git a/drivers/net/ifb.c b/drivers/net/ifb.c
index 4fecaed6..6e82dd3 100644
--- a/drivers/net/ifb.c
+++ b/drivers/net/ifb.c
@@ -32,6 +32,7 @@
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/moduleparam.h>
#include <net/pkt_sched.h>
#include <net/net_namespace.h>
@@ -40,8 +41,16 @@
struct ifb_private {
struct tasklet_struct ifb_tasklet;
int tasklet_pending;
+
+ struct u64_stats_sync rsync;
struct sk_buff_head rq;
+ u64 rx_packets;
+ u64 rx_bytes;
+
+ struct u64_stats_sync tsync;
struct sk_buff_head tq;
+ u64 tx_packets;
+ u64 tx_bytes;
};
static int numifbs = 2;
@@ -53,10 +62,8 @@
static void ri_tasklet(unsigned long dev)
{
-
struct net_device *_dev = (struct net_device *)dev;
struct ifb_private *dp = netdev_priv(_dev);
- struct net_device_stats *stats = &_dev->stats;
struct netdev_queue *txq;
struct sk_buff *skb;
@@ -76,15 +83,18 @@
skb->tc_verd = 0;
skb->tc_verd = SET_TC_NCLS(skb->tc_verd);
- stats->tx_packets++;
- stats->tx_bytes +=skb->len;
+
+ u64_stats_update_begin(&dp->tsync);
+ dp->tx_packets++;
+ dp->tx_bytes += skb->len;
+ u64_stats_update_end(&dp->tsync);
rcu_read_lock();
skb->dev = dev_get_by_index_rcu(&init_net, skb->skb_iif);
if (!skb->dev) {
rcu_read_unlock();
dev_kfree_skb(skb);
- stats->tx_dropped++;
+ _dev->stats.tx_dropped++;
if (skb_queue_len(&dp->tq) != 0)
goto resched;
break;
@@ -119,9 +129,37 @@
}
+static struct rtnl_link_stats64 *ifb_stats64(struct net_device *dev,
+ struct rtnl_link_stats64 *stats)
+{
+ struct ifb_private *dp = netdev_priv(dev);
+ unsigned int start;
+
+ do {
+ start = u64_stats_fetch_begin_bh(&dp->rsync);
+ stats->rx_packets = dp->rx_packets;
+ stats->rx_bytes = dp->rx_bytes;
+ } while (u64_stats_fetch_retry_bh(&dp->rsync, start));
+
+ do {
+ start = u64_stats_fetch_begin_bh(&dp->tsync);
+
+ stats->tx_packets = dp->tx_packets;
+ stats->tx_bytes = dp->tx_bytes;
+
+ } while (u64_stats_fetch_retry_bh(&dp->tsync, start));
+
+ stats->rx_dropped = dev->stats.rx_dropped;
+ stats->tx_dropped = dev->stats.tx_dropped;
+
+ return stats;
+}
+
+
static const struct net_device_ops ifb_netdev_ops = {
.ndo_open = ifb_open,
.ndo_stop = ifb_close,
+ .ndo_get_stats64 = ifb_stats64,
.ndo_start_xmit = ifb_xmit,
.ndo_validate_addr = eth_validate_addr,
};
@@ -152,15 +190,16 @@
static netdev_tx_t ifb_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct ifb_private *dp = netdev_priv(dev);
- struct net_device_stats *stats = &dev->stats;
u32 from = G_TC_FROM(skb->tc_verd);
- stats->rx_packets++;
- stats->rx_bytes+=skb->len;
+ u64_stats_update_begin(&dp->rsync);
+ dp->rx_packets++;
+ dp->rx_bytes += skb->len;
+ u64_stats_update_end(&dp->rsync);
if (!(from & (AT_INGRESS|AT_EGRESS)) || !skb->skb_iif) {
dev_kfree_skb(skb);
- stats->rx_dropped++;
+ dev->stats.rx_dropped++;
return NETDEV_TX_OK;
}
diff --git a/drivers/net/igb/e1000_mac.c b/drivers/net/igb/e1000_mac.c
index ce8255f..c822904 100644
--- a/drivers/net/igb/e1000_mac.c
+++ b/drivers/net/igb/e1000_mac.c
@@ -29,6 +29,7 @@
#include <linux/delay.h>
#include <linux/pci.h>
#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
#include "e1000_mac.h"
@@ -217,7 +218,7 @@
}
/* if multicast bit is set, the alternate address will not be used */
- if (alt_mac_addr[0] & 0x01) {
+ if (is_multicast_ether_addr(alt_mac_addr)) {
hw_dbg("Ignoring Alternate Mac Address with MC bit set\n");
goto out;
}
diff --git a/drivers/net/igb/igb_ethtool.c b/drivers/net/igb/igb_ethtool.c
index fdc895e..1862c97 100644
--- a/drivers/net/igb/igb_ethtool.c
+++ b/drivers/net/igb/igb_ethtool.c
@@ -318,65 +318,6 @@
return retval;
}
-static u32 igb_get_rx_csum(struct net_device *netdev)
-{
- struct igb_adapter *adapter = netdev_priv(netdev);
- return !!(adapter->rx_ring[0]->flags & IGB_RING_FLAG_RX_CSUM);
-}
-
-static int igb_set_rx_csum(struct net_device *netdev, u32 data)
-{
- struct igb_adapter *adapter = netdev_priv(netdev);
- int i;
-
- for (i = 0; i < adapter->num_rx_queues; i++) {
- if (data)
- adapter->rx_ring[i]->flags |= IGB_RING_FLAG_RX_CSUM;
- else
- adapter->rx_ring[i]->flags &= ~IGB_RING_FLAG_RX_CSUM;
- }
-
- return 0;
-}
-
-static u32 igb_get_tx_csum(struct net_device *netdev)
-{
- return (netdev->features & NETIF_F_IP_CSUM) != 0;
-}
-
-static int igb_set_tx_csum(struct net_device *netdev, u32 data)
-{
- struct igb_adapter *adapter = netdev_priv(netdev);
-
- if (data) {
- netdev->features |= (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM);
- if (adapter->hw.mac.type >= e1000_82576)
- netdev->features |= NETIF_F_SCTP_CSUM;
- } else {
- netdev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
- NETIF_F_SCTP_CSUM);
- }
-
- return 0;
-}
-
-static int igb_set_tso(struct net_device *netdev, u32 data)
-{
- struct igb_adapter *adapter = netdev_priv(netdev);
-
- if (data) {
- netdev->features |= NETIF_F_TSO;
- netdev->features |= NETIF_F_TSO6;
- } else {
- netdev->features &= ~NETIF_F_TSO;
- netdev->features &= ~NETIF_F_TSO6;
- }
-
- dev_info(&adapter->pdev->dev, "TSO is %s\n",
- data ? "Enabled" : "Disabled");
- return 0;
-}
-
static u32 igb_get_msglevel(struct net_device *netdev)
{
struct igb_adapter *adapter = netdev_priv(netdev);
@@ -2207,14 +2148,6 @@
.set_ringparam = igb_set_ringparam,
.get_pauseparam = igb_get_pauseparam,
.set_pauseparam = igb_set_pauseparam,
- .get_rx_csum = igb_get_rx_csum,
- .set_rx_csum = igb_set_rx_csum,
- .get_tx_csum = igb_get_tx_csum,
- .set_tx_csum = igb_set_tx_csum,
- .get_sg = ethtool_op_get_sg,
- .set_sg = ethtool_op_set_sg,
- .get_tso = ethtool_op_get_tso,
- .set_tso = igb_set_tso,
.self_test = igb_diag_test,
.get_strings = igb_get_strings,
.set_phys_id = igb_set_phys_id,
diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c
index 2c28621..d6c4bd8 100644
--- a/drivers/net/igb/igb_main.c
+++ b/drivers/net/igb/igb_main.c
@@ -54,9 +54,8 @@
#define MAJ 3
#define MIN 0
#define BUILD 6
-#define KFIX 2
#define DRV_VERSION __stringify(MAJ) "." __stringify(MIN) "." \
-__stringify(BUILD) "-k" __stringify(KFIX)
+__stringify(BUILD) "-k"
char igb_driver_name[] = "igb";
char igb_driver_version[] = DRV_VERSION;
static const char igb_driver_string[] =
@@ -1749,6 +1748,21 @@
igb_get_phy_info(hw);
}
+static int igb_set_features(struct net_device *netdev, u32 features)
+{
+ struct igb_adapter *adapter = netdev_priv(netdev);
+ int i;
+
+ for (i = 0; i < adapter->num_rx_queues; i++) {
+ if (features & NETIF_F_RXCSUM)
+ adapter->rx_ring[i]->flags |= IGB_RING_FLAG_RX_CSUM;
+ else
+ adapter->rx_ring[i]->flags &= ~IGB_RING_FLAG_RX_CSUM;
+ }
+
+ return 0;
+}
+
static const struct net_device_ops igb_netdev_ops = {
.ndo_open = igb_open,
.ndo_stop = igb_close,
@@ -1771,6 +1785,7 @@
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = igb_netpoll,
#endif
+ .ndo_set_features = igb_set_features,
};
/**
@@ -1910,17 +1925,18 @@
dev_info(&pdev->dev,
"PHY reset is blocked due to SOL/IDER session.\n");
- netdev->features = NETIF_F_SG |
+ netdev->hw_features = NETIF_F_SG |
NETIF_F_IP_CSUM |
+ NETIF_F_IPV6_CSUM |
+ NETIF_F_TSO |
+ NETIF_F_TSO6 |
+ NETIF_F_RXCSUM;
+
+ netdev->features = netdev->hw_features |
NETIF_F_HW_VLAN_TX |
NETIF_F_HW_VLAN_RX |
NETIF_F_HW_VLAN_FILTER;
- netdev->features |= NETIF_F_IPV6_CSUM;
- netdev->features |= NETIF_F_TSO;
- netdev->features |= NETIF_F_TSO6;
- netdev->features |= NETIF_F_GRO;
-
netdev->vlan_features |= NETIF_F_TSO;
netdev->vlan_features |= NETIF_F_TSO6;
netdev->vlan_features |= NETIF_F_IP_CSUM;
@@ -1932,8 +1948,10 @@
netdev->vlan_features |= NETIF_F_HIGHDMA;
}
- if (hw->mac.type >= e1000_82576)
+ if (hw->mac.type >= e1000_82576) {
+ netdev->hw_features |= NETIF_F_SCTP_CSUM;
netdev->features |= NETIF_F_SCTP_CSUM;
+ }
adapter->en_mng_pt = igb_enable_mng_pass_thru(hw);
@@ -6249,7 +6267,7 @@
struct igb_adapter *adapter = hw->back;
u16 cap_offset;
- cap_offset = pci_find_capability(adapter->pdev, PCI_CAP_ID_EXP);
+ cap_offset = adapter->pdev->pcie_cap;
if (!cap_offset)
return -E1000_ERR_CONFIG;
@@ -6263,7 +6281,7 @@
struct igb_adapter *adapter = hw->back;
u16 cap_offset;
- cap_offset = pci_find_capability(adapter->pdev, PCI_CAP_ID_EXP);
+ cap_offset = adapter->pdev->pcie_cap;
if (!cap_offset)
return -E1000_ERR_CONFIG;
diff --git a/drivers/net/igbvf/netdev.c b/drivers/net/igbvf/netdev.c
index 1c77fb3..64b47bf 100644
--- a/drivers/net/igbvf/netdev.c
+++ b/drivers/net/igbvf/netdev.c
@@ -45,7 +45,7 @@
#include "igbvf.h"
-#define DRV_VERSION "1.0.8-k0"
+#define DRV_VERSION "2.0.0-k"
char igbvf_driver_name[] = "igbvf";
const char igbvf_driver_version[] = DRV_VERSION;
static const char igbvf_driver_string[] =
diff --git a/drivers/net/ioc3-eth.c b/drivers/net/ioc3-eth.c
index 32f07f8..318a25a 100644
--- a/drivers/net/ioc3-eth.c
+++ b/drivers/net/ioc3-eth.c
@@ -532,7 +532,7 @@
return;
ih = (struct iphdr *) ((char *)eh + ETH_HLEN);
- if (ih->frag_off & htons(IP_MF | IP_OFFSET))
+ if (ip_is_fragment(ih))
return;
proto = ih->protocol;
diff --git a/drivers/net/ipg.c b/drivers/net/ipg.c
index 58cd320..d4aa40a 100644
--- a/drivers/net/ipg.c
+++ b/drivers/net/ipg.c
@@ -22,6 +22,7 @@
*/
#include <linux/crc32.h>
#include <linux/ethtool.h>
+#include <linux/interrupt.h>
#include <linux/gfp.h>
#include <linux/mii.h>
#include <linux/mutex.h>
diff --git a/drivers/net/irda/ali-ircc.c b/drivers/net/irda/ali-ircc.c
index d532dde..963067d 100644
--- a/drivers/net/irda/ali-ircc.c
+++ b/drivers/net/irda/ali-ircc.c
@@ -31,6 +31,7 @@
#include <linux/ioport.h>
#include <linux/delay.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/rtnetlink.h>
#include <linux/serial_reg.h>
#include <linux/dma-mapping.h>
diff --git a/drivers/net/irda/donauboe.c b/drivers/net/irda/donauboe.c
index 174cafa..b45b2cc 100644
--- a/drivers/net/irda/donauboe.c
+++ b/drivers/net/irda/donauboe.c
@@ -152,6 +152,7 @@
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/pci.h>
#include <linux/rtnetlink.h>
diff --git a/drivers/net/irda/nsc-ircc.c b/drivers/net/irda/nsc-ircc.c
index 7a963d4..b56636d 100644
--- a/drivers/net/irda/nsc-ircc.c
+++ b/drivers/net/irda/nsc-ircc.c
@@ -52,6 +52,7 @@
#include <linux/ioport.h>
#include <linux/delay.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/rtnetlink.h>
#include <linux/dma-mapping.h>
#include <linux/pnp.h>
diff --git a/drivers/net/irda/pxaficp_ir.c b/drivers/net/irda/pxaficp_ir.c
index 001ed0a..d0851df 100644
--- a/drivers/net/irda/pxaficp_ir.c
+++ b/drivers/net/irda/pxaficp_ir.c
@@ -12,6 +12,8 @@
* Infra-red driver (SIR/FIR) for the PXA2xx embedded microprocessor
*
*/
+#include <linux/dma-mapping.h>
+#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
diff --git a/drivers/net/irda/sir_dev.c b/drivers/net/irda/sir_dev.c
index efe05bb..5039f08 100644
--- a/drivers/net/irda/sir_dev.c
+++ b/drivers/net/irda/sir_dev.c
@@ -11,6 +11,7 @@
*
********************************************************************/
+#include <linux/hardirq.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/slab.h>
diff --git a/drivers/net/irda/smsc-ircc2.c b/drivers/net/irda/smsc-ircc2.c
index 8800e1f..954f6e93 100644
--- a/drivers/net/irda/smsc-ircc2.c
+++ b/drivers/net/irda/smsc-ircc2.c
@@ -49,6 +49,7 @@
#include <linux/ioport.h>
#include <linux/delay.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/rtnetlink.h>
#include <linux/serial_reg.h>
#include <linux/dma-mapping.h>
@@ -515,7 +516,7 @@
* Try to open driver instance
*
*/
-static int __init smsc_ircc_open(unsigned int fir_base, unsigned int sir_base, u8 dma, u8 irq)
+static int __devinit smsc_ircc_open(unsigned int fir_base, unsigned int sir_base, u8 dma, u8 irq)
{
struct smsc_ircc_cb *self;
struct net_device *dev;
diff --git a/drivers/net/irda/via-ircc.c b/drivers/net/irda/via-ircc.c
index f504b26..6d64790 100644
--- a/drivers/net/irda/via-ircc.c
+++ b/drivers/net/irda/via-ircc.c
@@ -46,6 +46,7 @@
#include <linux/ioport.h>
#include <linux/delay.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/rtnetlink.h>
#include <linux/pci.h>
#include <linux/dma-mapping.h>
diff --git a/drivers/net/irda/via-ircc.h b/drivers/net/irda/via-ircc.h
index c6f5848..f903a6a 100644
--- a/drivers/net/irda/via-ircc.h
+++ b/drivers/net/irda/via-ircc.h
@@ -210,7 +210,7 @@
break;
default:
break;
- }; //Switch
+ }
}
static unsigned char ReadLPCReg(int iRegNum)
diff --git a/drivers/net/irda/vlsi_ir.c b/drivers/net/irda/vlsi_ir.c
index c3d0738..9021d01 100644
--- a/drivers/net/irda/vlsi_ir.c
+++ b/drivers/net/irda/vlsi_ir.c
@@ -36,6 +36,7 @@
#include <linux/kernel.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/pci.h>
#include <linux/slab.h>
#include <linux/netdevice.h>
diff --git a/drivers/net/irda/w83977af_ir.c b/drivers/net/irda/w83977af_ir.c
index 1f9c3f08..c436660 100644
--- a/drivers/net/irda/w83977af_ir.c
+++ b/drivers/net/irda/w83977af_ir.c
@@ -47,6 +47,7 @@
#include <linux/ioport.h>
#include <linux/delay.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/rtnetlink.h>
#include <linux/dma-mapping.h>
#include <linux/gfp.h>
diff --git a/drivers/net/iseries_veth.c b/drivers/net/iseries_veth.c
index 9ece1fd..53dd39e 100644
--- a/drivers/net/iseries_veth.c
+++ b/drivers/net/iseries_veth.c
@@ -538,7 +538,7 @@
default:
veth_error("Unknown ack type %d from LPAR %d.\n",
event->base_event.xSubtype, rlp);
- };
+ }
}
static void veth_handle_int(struct veth_lpevent *event)
@@ -584,7 +584,7 @@
default:
veth_error("Unknown interrupt type %d from LPAR %d.\n",
event->base_event.xSubtype, rlp);
- };
+ }
}
static void veth_handle_event(struct HvLpEvent *event)
@@ -964,11 +964,9 @@
u8 *addr = ha->addr;
u64 xaddr = 0;
- if (addr[0] & 0x01) {/* multicast address? */
- memcpy(&xaddr, addr, ETH_ALEN);
- port->mcast_addr[port->num_mcast] = xaddr;
- port->num_mcast++;
- }
+ memcpy(&xaddr, addr, ETH_ALEN);
+ port->mcast_addr[port->num_mcast] = xaddr;
+ port->num_mcast++;
}
}
@@ -1184,7 +1182,7 @@
struct veth_port *port = netdev_priv(dev);
HvLpIndexMap lpmask;
- if (! (frame[0] & 0x01)) {
+ if (is_unicast_ether_addr(frame)) {
/* unicast packet */
HvLpIndex rlp = frame[5];
diff --git a/drivers/net/ixgbe/ixgbe.h b/drivers/net/ixgbe/ixgbe.h
index e467b20..744b641 100644
--- a/drivers/net/ixgbe/ixgbe.h
+++ b/drivers/net/ixgbe/ixgbe.h
@@ -131,6 +131,13 @@
u8 vf_macvlan[ETH_ALEN];
};
+#define IXGBE_MAX_TXD_PWR 14
+#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 * TXD_USE_COUNT(PAGE_SIZE)) + 4)
+
/* wrapper around a pointer to a socket buffer,
* so a DMA handle can be stored along with the buffer */
struct ixgbe_tx_buffer {
@@ -244,7 +251,6 @@
enum ixgbe_ring_f_enum {
RING_F_NONE = 0,
- RING_F_DCB,
RING_F_VMDQ, /* SR-IOV uses the same ring feature */
RING_F_RSS,
RING_F_FDIR,
@@ -255,7 +261,6 @@
RING_F_ARRAY_SIZE /* must be last in enum set */
};
-#define IXGBE_MAX_DCB_INDICES 64
#define IXGBE_MAX_RSS_INDICES 16
#define IXGBE_MAX_VMDQ_INDICES 64
#define IXGBE_MAX_FDIR_INDICES 64
@@ -308,9 +313,13 @@
((_eitr) ? (1000000000 / ((_eitr) * 256)) : 8)
#define EITR_REG_TO_INTS_PER_SEC EITR_INTS_PER_SEC_TO_REG
-#define IXGBE_DESC_UNUSED(R) \
- ((((R)->next_to_clean > (R)->next_to_use) ? 0 : (R)->count) + \
- (R)->next_to_clean - (R)->next_to_use - 1)
+static inline u16 ixgbe_desc_unused(struct ixgbe_ring *ring)
+{
+ u16 ntc = ring->next_to_clean;
+ u16 ntu = ring->next_to_use;
+
+ return ((ntc > ntu) ? 0 : ring->count) + ntc - ntu - 1;
+}
#define IXGBE_RX_DESC_ADV(R, i) \
(&(((union ixgbe_adv_rx_desc *)((R)->desc))[i]))
@@ -484,6 +493,17 @@
struct vf_macvlans vf_mvs;
struct vf_macvlans *mv_list;
bool antispoofing_enabled;
+
+ struct hlist_head fdir_filter_list;
+ union ixgbe_atr_input fdir_mask;
+ int fdir_filter_count;
+};
+
+struct ixgbe_fdir_filter {
+ struct hlist_node fdir_node;
+ union ixgbe_atr_input filter;
+ u16 sw_idx;
+ u16 action;
};
enum ixbge_state_t {
@@ -545,26 +565,32 @@
extern void ixgbe_write_eitr(struct ixgbe_q_vector *);
extern int ethtool_ioctl(struct ifreq *ifr);
extern s32 ixgbe_reinit_fdir_tables_82599(struct ixgbe_hw *hw);
-extern s32 ixgbe_init_fdir_signature_82599(struct ixgbe_hw *hw, u32 pballoc);
-extern s32 ixgbe_init_fdir_perfect_82599(struct ixgbe_hw *hw, u32 pballoc);
+extern s32 ixgbe_init_fdir_signature_82599(struct ixgbe_hw *hw, u32 fdirctrl);
+extern s32 ixgbe_init_fdir_perfect_82599(struct ixgbe_hw *hw, u32 fdirctrl);
extern s32 ixgbe_fdir_add_signature_filter_82599(struct ixgbe_hw *hw,
union ixgbe_atr_hash_dword input,
union ixgbe_atr_hash_dword common,
u8 queue);
-extern s32 ixgbe_fdir_add_perfect_filter_82599(struct ixgbe_hw *hw,
- union ixgbe_atr_input *input,
- struct ixgbe_atr_input_masks *input_masks,
- u16 soft_id, u8 queue);
+extern s32 ixgbe_fdir_set_input_mask_82599(struct ixgbe_hw *hw,
+ union ixgbe_atr_input *input_mask);
+extern s32 ixgbe_fdir_write_perfect_filter_82599(struct ixgbe_hw *hw,
+ union ixgbe_atr_input *input,
+ u16 soft_id, u8 queue);
+extern s32 ixgbe_fdir_erase_perfect_filter_82599(struct ixgbe_hw *hw,
+ union ixgbe_atr_input *input,
+ u16 soft_id);
+extern void ixgbe_atr_compute_perfect_hash_82599(union ixgbe_atr_input *input,
+ union ixgbe_atr_input *mask);
extern void ixgbe_configure_rscctl(struct ixgbe_adapter *adapter,
struct ixgbe_ring *ring);
extern void ixgbe_clear_rscctl(struct ixgbe_adapter *adapter,
struct ixgbe_ring *ring);
extern void ixgbe_set_rx_mode(struct net_device *netdev);
extern int ixgbe_setup_tc(struct net_device *dev, u8 tc);
+extern void ixgbe_tx_ctxtdesc(struct ixgbe_ring *, u32, u32, u32, u32);
#ifdef IXGBE_FCOE
extern void ixgbe_configure_fcoe(struct ixgbe_adapter *adapter);
-extern int ixgbe_fso(struct ixgbe_adapter *adapter,
- struct ixgbe_ring *tx_ring, struct sk_buff *skb,
+extern int ixgbe_fso(struct ixgbe_ring *tx_ring, struct sk_buff *skb,
u32 tx_flags, u8 *hdr_len);
extern void ixgbe_cleanup_fcoe(struct ixgbe_adapter *adapter);
extern int ixgbe_fcoe_ddp(struct ixgbe_adapter *adapter,
diff --git a/drivers/net/ixgbe/ixgbe_82598.c b/drivers/net/ixgbe/ixgbe_82598.c
index 8179e50..0d4e382 100644
--- a/drivers/net/ixgbe/ixgbe_82598.c
+++ b/drivers/net/ixgbe/ixgbe_82598.c
@@ -1242,6 +1242,47 @@
}
}
+/**
+ * ixgbe_set_rxpba_82598 - Configure packet buffers
+ * @hw: pointer to hardware structure
+ * @dcb_config: pointer to ixgbe_dcb_config structure
+ *
+ * Configure packet buffers.
+ */
+static void ixgbe_set_rxpba_82598(struct ixgbe_hw *hw, int num_pb, u32 headroom,
+ int strategy)
+{
+ u32 rxpktsize = IXGBE_RXPBSIZE_64KB;
+ u8 i = 0;
+
+ if (!num_pb)
+ return;
+
+ /* Setup Rx packet buffer sizes */
+ switch (strategy) {
+ case PBA_STRATEGY_WEIGHTED:
+ /* Setup the first four at 80KB */
+ rxpktsize = IXGBE_RXPBSIZE_80KB;
+ for (; i < 4; i++)
+ IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), rxpktsize);
+ /* Setup the last four at 48KB...don't re-init i */
+ rxpktsize = IXGBE_RXPBSIZE_48KB;
+ /* Fall Through */
+ case PBA_STRATEGY_EQUAL:
+ default:
+ /* Divide the remaining Rx packet buffer evenly among the TCs */
+ for (; i < IXGBE_MAX_PACKET_BUFFERS; i++)
+ IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), rxpktsize);
+ break;
+ }
+
+ /* Setup Tx packet buffer sizes */
+ for (i = 0; i < IXGBE_MAX_PACKET_BUFFERS; i++)
+ IXGBE_WRITE_REG(hw, IXGBE_TXPBSIZE(i), IXGBE_TXPBSIZE_40KB);
+
+ return;
+}
+
static struct ixgbe_mac_operations mac_ops_82598 = {
.init_hw = &ixgbe_init_hw_generic,
.reset_hw = &ixgbe_reset_hw_82598,
@@ -1257,6 +1298,7 @@
.read_analog_reg8 = &ixgbe_read_analog_reg8_82598,
.write_analog_reg8 = &ixgbe_write_analog_reg8_82598,
.setup_link = &ixgbe_setup_mac_link_82598,
+ .set_rxpba = &ixgbe_set_rxpba_82598,
.check_link = &ixgbe_check_mac_link_82598,
.get_link_capabilities = &ixgbe_get_link_capabilities_82598,
.led_on = &ixgbe_led_on_generic,
@@ -1274,6 +1316,7 @@
.clear_vfta = &ixgbe_clear_vfta_82598,
.set_vfta = &ixgbe_set_vfta_82598,
.fc_enable = &ixgbe_fc_enable_82598,
+ .set_fw_drv_ver = NULL,
.acquire_swfw_sync = &ixgbe_acquire_swfw_sync,
.release_swfw_sync = &ixgbe_release_swfw_sync,
};
diff --git a/drivers/net/ixgbe/ixgbe_82599.c b/drivers/net/ixgbe/ixgbe_82599.c
index 8ee66124..3b3dd4d 100644
--- a/drivers/net/ixgbe/ixgbe_82599.c
+++ b/drivers/net/ixgbe/ixgbe_82599.c
@@ -1107,61 +1107,86 @@
}
/**
- * ixgbe_init_fdir_signature_82599 - Initialize Flow Director signature filters
+ * ixgbe_set_fdir_rxpba_82599 - Initialize Flow Director Rx packet buffer
* @hw: pointer to hardware structure
* @pballoc: which mode to allocate filters with
**/
-s32 ixgbe_init_fdir_signature_82599(struct ixgbe_hw *hw, u32 pballoc)
+static s32 ixgbe_set_fdir_rxpba_82599(struct ixgbe_hw *hw, const u32 pballoc)
{
- u32 fdirctrl = 0;
- u32 pbsize;
+ u32 fdir_pbsize = hw->mac.rx_pb_size << IXGBE_RXPBSIZE_SHIFT;
+ u32 current_rxpbsize = 0;
int i;
- /*
- * Before enabling Flow Director, the Rx Packet Buffer size
- * must be reduced. The new value is the current size minus
- * flow director memory usage size.
- */
- pbsize = (1 << (IXGBE_FDIR_PBALLOC_SIZE_SHIFT + pballoc));
- IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(0),
- (IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(0)) - pbsize));
-
- /*
- * The defaults in the HW for RX PB 1-7 are not zero and so should be
- * initialized to zero for non DCB mode otherwise actual total RX PB
- * would be bigger than programmed and filter space would run into
- * the PB 0 region.
- */
- for (i = 1; i < 8; i++)
- IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), 0);
-
- /* Send interrupt when 64 filters are left */
- fdirctrl |= 4 << IXGBE_FDIRCTRL_FULL_THRESH_SHIFT;
-
- /* Set the maximum length per hash bucket to 0xA filters */
- fdirctrl |= 0xA << IXGBE_FDIRCTRL_MAX_LENGTH_SHIFT;
-
+ /* reserve space for Flow Director filters */
switch (pballoc) {
- case IXGBE_FDIR_PBALLOC_64K:
- /* 8k - 1 signature filters */
- fdirctrl |= IXGBE_FDIRCTRL_PBALLOC_64K;
+ case IXGBE_FDIR_PBALLOC_256K:
+ fdir_pbsize -= 256 << IXGBE_RXPBSIZE_SHIFT;
break;
case IXGBE_FDIR_PBALLOC_128K:
- /* 16k - 1 signature filters */
- fdirctrl |= IXGBE_FDIRCTRL_PBALLOC_128K;
+ fdir_pbsize -= 128 << IXGBE_RXPBSIZE_SHIFT;
break;
- case IXGBE_FDIR_PBALLOC_256K:
- /* 32k - 1 signature filters */
- fdirctrl |= IXGBE_FDIRCTRL_PBALLOC_256K;
+ case IXGBE_FDIR_PBALLOC_64K:
+ fdir_pbsize -= 64 << IXGBE_RXPBSIZE_SHIFT;
break;
+ case IXGBE_FDIR_PBALLOC_NONE:
default:
- /* bad value */
- return IXGBE_ERR_CONFIG;
- };
+ return IXGBE_ERR_PARAM;
+ }
- /* Move the flexible bytes to use the ethertype - shift 6 words */
- fdirctrl |= (0x6 << IXGBE_FDIRCTRL_FLEX_SHIFT);
+ /* determine current RX packet buffer size */
+ for (i = 0; i < 8; i++)
+ current_rxpbsize += IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(i));
+ /* if there is already room for the filters do nothing */
+ if (current_rxpbsize <= fdir_pbsize)
+ return 0;
+
+ if (current_rxpbsize > hw->mac.rx_pb_size) {
+ /*
+ * if rxpbsize is greater than max then HW max the Rx buffer
+ * sizes are unconfigured or misconfigured since HW default is
+ * to give the full buffer to each traffic class resulting in
+ * the total size being buffer size 8x actual size
+ *
+ * This assumes no DCB since the RXPBSIZE registers appear to
+ * be unconfigured.
+ */
+ IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(0), fdir_pbsize);
+ for (i = 1; i < 8; i++)
+ IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), 0);
+ } else {
+ /*
+ * Since the Rx packet buffer appears to have already been
+ * configured we need to shrink each packet buffer by enough
+ * to make room for the filters. As such we take each rxpbsize
+ * value and multiply it by a fraction representing the size
+ * needed over the size we currently have.
+ *
+ * We need to reduce fdir_pbsize and current_rxpbsize to
+ * 1/1024 of their original values in order to avoid
+ * overflowing the u32 being used to store rxpbsize.
+ */
+ fdir_pbsize >>= IXGBE_RXPBSIZE_SHIFT;
+ current_rxpbsize >>= IXGBE_RXPBSIZE_SHIFT;
+ for (i = 0; i < 8; i++) {
+ u32 rxpbsize = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(i));
+ rxpbsize *= fdir_pbsize;
+ rxpbsize /= current_rxpbsize;
+ IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), rxpbsize);
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * ixgbe_fdir_enable_82599 - Initialize Flow Director control registers
+ * @hw: pointer to hardware structure
+ * @fdirctrl: value to write to flow director control register
+ **/
+static void ixgbe_fdir_enable_82599(struct ixgbe_hw *hw, u32 fdirctrl)
+{
+ int i;
/* Prime the keys for hashing */
IXGBE_WRITE_REG(hw, IXGBE_FDIRHKEY, IXGBE_ATR_BUCKET_HASH_KEY);
@@ -1188,8 +1213,38 @@
break;
usleep_range(1000, 2000);
}
+
if (i >= IXGBE_FDIR_INIT_DONE_POLL)
- hw_dbg(hw, "Flow Director Signature poll time exceeded!\n");
+ hw_dbg(hw, "Flow Director poll time exceeded!\n");
+}
+
+/**
+ * ixgbe_init_fdir_signature_82599 - Initialize Flow Director signature filters
+ * @hw: pointer to hardware structure
+ * @fdirctrl: value to write to flow director control register, initially
+ * contains just the value of the Rx packet buffer allocation
+ **/
+s32 ixgbe_init_fdir_signature_82599(struct ixgbe_hw *hw, u32 fdirctrl)
+{
+ s32 err;
+
+ /* Before enabling Flow Director, verify the Rx Packet Buffer size */
+ err = ixgbe_set_fdir_rxpba_82599(hw, fdirctrl);
+ if (err)
+ return err;
+
+ /*
+ * Continue setup of fdirctrl register bits:
+ * Move the flexible bytes to use the ethertype - shift 6 words
+ * Set the maximum length per hash bucket to 0xA filters
+ * Send interrupt when 64 filters are left
+ */
+ fdirctrl |= (0x6 << IXGBE_FDIRCTRL_FLEX_SHIFT) |
+ (0xA << IXGBE_FDIRCTRL_MAX_LENGTH_SHIFT) |
+ (4 << IXGBE_FDIRCTRL_FULL_THRESH_SHIFT);
+
+ /* write hashes and fdirctrl register, poll for completion */
+ ixgbe_fdir_enable_82599(hw, fdirctrl);
return 0;
}
@@ -1197,189 +1252,40 @@
/**
* ixgbe_init_fdir_perfect_82599 - Initialize Flow Director perfect filters
* @hw: pointer to hardware structure
- * @pballoc: which mode to allocate filters with
+ * @fdirctrl: value to write to flow director control register, initially
+ * contains just the value of the Rx packet buffer allocation
**/
-s32 ixgbe_init_fdir_perfect_82599(struct ixgbe_hw *hw, u32 pballoc)
+s32 ixgbe_init_fdir_perfect_82599(struct ixgbe_hw *hw, u32 fdirctrl)
{
- u32 fdirctrl = 0;
- u32 pbsize;
- int i;
+ s32 err;
+
+ /* Before enabling Flow Director, verify the Rx Packet Buffer size */
+ err = ixgbe_set_fdir_rxpba_82599(hw, fdirctrl);
+ if (err)
+ return err;
/*
- * Before enabling Flow Director, the Rx Packet Buffer size
- * must be reduced. The new value is the current size minus
- * flow director memory usage size.
+ * Continue setup of fdirctrl register bits:
+ * Turn perfect match filtering on
+ * Report hash in RSS field of Rx wb descriptor
+ * Initialize the drop queue
+ * Move the flexible bytes to use the ethertype - shift 6 words
+ * Set the maximum length per hash bucket to 0xA filters
+ * Send interrupt when 64 (0x4 * 16) filters are left
*/
- pbsize = (1 << (IXGBE_FDIR_PBALLOC_SIZE_SHIFT + pballoc));
- IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(0),
- (IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(0)) - pbsize));
+ fdirctrl |= IXGBE_FDIRCTRL_PERFECT_MATCH |
+ IXGBE_FDIRCTRL_REPORT_STATUS |
+ (IXGBE_FDIR_DROP_QUEUE << IXGBE_FDIRCTRL_DROP_Q_SHIFT) |
+ (0x6 << IXGBE_FDIRCTRL_FLEX_SHIFT) |
+ (0xA << IXGBE_FDIRCTRL_MAX_LENGTH_SHIFT) |
+ (4 << IXGBE_FDIRCTRL_FULL_THRESH_SHIFT);
- /*
- * The defaults in the HW for RX PB 1-7 are not zero and so should be
- * initialized to zero for non DCB mode otherwise actual total RX PB
- * would be bigger than programmed and filter space would run into
- * the PB 0 region.
- */
- for (i = 1; i < 8; i++)
- IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), 0);
-
- /* Send interrupt when 64 filters are left */
- fdirctrl |= 4 << IXGBE_FDIRCTRL_FULL_THRESH_SHIFT;
-
- /* Initialize the drop queue to Rx queue 127 */
- fdirctrl |= (127 << IXGBE_FDIRCTRL_DROP_Q_SHIFT);
-
- switch (pballoc) {
- case IXGBE_FDIR_PBALLOC_64K:
- /* 2k - 1 perfect filters */
- fdirctrl |= IXGBE_FDIRCTRL_PBALLOC_64K;
- break;
- case IXGBE_FDIR_PBALLOC_128K:
- /* 4k - 1 perfect filters */
- fdirctrl |= IXGBE_FDIRCTRL_PBALLOC_128K;
- break;
- case IXGBE_FDIR_PBALLOC_256K:
- /* 8k - 1 perfect filters */
- fdirctrl |= IXGBE_FDIRCTRL_PBALLOC_256K;
- break;
- default:
- /* bad value */
- return IXGBE_ERR_CONFIG;
- };
-
- /* Turn perfect match filtering on */
- fdirctrl |= IXGBE_FDIRCTRL_PERFECT_MATCH;
- fdirctrl |= IXGBE_FDIRCTRL_REPORT_STATUS;
-
- /* Move the flexible bytes to use the ethertype - shift 6 words */
- fdirctrl |= (0x6 << IXGBE_FDIRCTRL_FLEX_SHIFT);
-
- /* Prime the keys for hashing */
- IXGBE_WRITE_REG(hw, IXGBE_FDIRHKEY, IXGBE_ATR_BUCKET_HASH_KEY);
- IXGBE_WRITE_REG(hw, IXGBE_FDIRSKEY, IXGBE_ATR_SIGNATURE_HASH_KEY);
-
- /*
- * Poll init-done after we write the register. Estimated times:
- * 10G: PBALLOC = 11b, timing is 60us
- * 1G: PBALLOC = 11b, timing is 600us
- * 100M: PBALLOC = 11b, timing is 6ms
- *
- * Multiple these timings by 4 if under full Rx load
- *
- * So we'll poll for IXGBE_FDIR_INIT_DONE_POLL times, sleeping for
- * 1 msec per poll time. If we're at line rate and drop to 100M, then
- * this might not finish in our poll time, but we can live with that
- * for now.
- */
-
- /* Set the maximum length per hash bucket to 0xA filters */
- fdirctrl |= (0xA << IXGBE_FDIRCTRL_MAX_LENGTH_SHIFT);
-
- IXGBE_WRITE_REG(hw, IXGBE_FDIRCTRL, fdirctrl);
- IXGBE_WRITE_FLUSH(hw);
- for (i = 0; i < IXGBE_FDIR_INIT_DONE_POLL; i++) {
- if (IXGBE_READ_REG(hw, IXGBE_FDIRCTRL) &
- IXGBE_FDIRCTRL_INIT_DONE)
- break;
- usleep_range(1000, 2000);
- }
- if (i >= IXGBE_FDIR_INIT_DONE_POLL)
- hw_dbg(hw, "Flow Director Perfect poll time exceeded!\n");
+ /* write hashes and fdirctrl register, poll for completion */
+ ixgbe_fdir_enable_82599(hw, fdirctrl);
return 0;
}
-
-/**
- * ixgbe_atr_compute_hash_82599 - Compute the hashes for SW ATR
- * @stream: input bitstream to compute the hash on
- * @key: 32-bit hash key
- **/
-static u32 ixgbe_atr_compute_hash_82599(union ixgbe_atr_input *atr_input,
- u32 key)
-{
- /*
- * The algorithm is as follows:
- * Hash[15:0] = Sum { S[n] x K[n+16] }, n = 0...350
- * where Sum {A[n]}, n = 0...n is bitwise XOR of A[0], A[1]...A[n]
- * and A[n] x B[n] is bitwise AND between same length strings
- *
- * K[n] is 16 bits, defined as:
- * for n modulo 32 >= 15, K[n] = K[n % 32 : (n % 32) - 15]
- * for n modulo 32 < 15, K[n] =
- * K[(n % 32:0) | (31:31 - (14 - (n % 32)))]
- *
- * S[n] is 16 bits, defined as:
- * for n >= 15, S[n] = S[n:n - 15]
- * for n < 15, S[n] = S[(n:0) | (350:350 - (14 - n))]
- *
- * To simplify for programming, the algorithm is implemented
- * in software this way:
- *
- * key[31:0], hi_hash_dword[31:0], lo_hash_dword[31:0], hash[15:0]
- *
- * for (i = 0; i < 352; i+=32)
- * hi_hash_dword[31:0] ^= Stream[(i+31):i];
- *
- * lo_hash_dword[15:0] ^= Stream[15:0];
- * lo_hash_dword[15:0] ^= hi_hash_dword[31:16];
- * lo_hash_dword[31:16] ^= hi_hash_dword[15:0];
- *
- * hi_hash_dword[31:0] ^= Stream[351:320];
- *
- * if(key[0])
- * hash[15:0] ^= Stream[15:0];
- *
- * for (i = 0; i < 16; i++) {
- * if (key[i])
- * hash[15:0] ^= lo_hash_dword[(i+15):i];
- * if (key[i + 16])
- * hash[15:0] ^= hi_hash_dword[(i+15):i];
- * }
- *
- */
- __be32 common_hash_dword = 0;
- u32 hi_hash_dword, lo_hash_dword, flow_vm_vlan;
- u32 hash_result = 0;
- u8 i;
-
- /* record the flow_vm_vlan bits as they are a key part to the hash */
- flow_vm_vlan = ntohl(atr_input->dword_stream[0]);
-
- /* generate common hash dword */
- for (i = 10; i; i -= 2)
- common_hash_dword ^= atr_input->dword_stream[i] ^
- atr_input->dword_stream[i - 1];
-
- hi_hash_dword = ntohl(common_hash_dword);
-
- /* low dword is word swapped version of common */
- lo_hash_dword = (hi_hash_dword >> 16) | (hi_hash_dword << 16);
-
- /* apply flow ID/VM pool/VLAN ID bits to hash words */
- hi_hash_dword ^= flow_vm_vlan ^ (flow_vm_vlan >> 16);
-
- /* Process bits 0 and 16 */
- if (key & 0x0001) hash_result ^= lo_hash_dword;
- if (key & 0x00010000) hash_result ^= hi_hash_dword;
-
- /*
- * apply flow ID/VM pool/VLAN ID bits to lo hash dword, we had to
- * delay this because bit 0 of the stream should not be processed
- * so we do not add the vlan until after bit 0 was processed
- */
- lo_hash_dword ^= flow_vm_vlan ^ (flow_vm_vlan << 16);
-
-
- /* process the remaining 30 bits in the key 2 bits at a time */
- for (i = 15; i; i-- ) {
- if (key & (0x0001 << i)) hash_result ^= lo_hash_dword >> i;
- if (key & (0x00010000 << i)) hash_result ^= hi_hash_dword >> i;
- }
-
- return hash_result & IXGBE_ATR_HASH_MASK;
-}
-
/*
* These defines allow us to quickly generate all of the necessary instructions
* in the function below by simply calling out IXGBE_COMPUTE_SIG_HASH_ITERATION
@@ -1514,7 +1420,6 @@
*/
fdirhashcmd = (u64)fdircmd << 32;
fdirhashcmd |= ixgbe_atr_compute_sig_hash_82599(input, common);
-
IXGBE_WRITE_REG64(hw, IXGBE_FDIRHASH, fdirhashcmd);
hw_dbg(hw, "Tx Queue=%x hash=%x\n", queue, (u32)fdirhashcmd);
@@ -1522,6 +1427,101 @@
return 0;
}
+#define IXGBE_COMPUTE_BKT_HASH_ITERATION(_n) \
+do { \
+ u32 n = (_n); \
+ if (IXGBE_ATR_BUCKET_HASH_KEY & (0x01 << n)) \
+ bucket_hash ^= lo_hash_dword >> n; \
+ if (IXGBE_ATR_BUCKET_HASH_KEY & (0x01 << (n + 16))) \
+ bucket_hash ^= hi_hash_dword >> n; \
+} while (0);
+
+/**
+ * ixgbe_atr_compute_perfect_hash_82599 - Compute the perfect filter hash
+ * @atr_input: input bitstream to compute the hash on
+ * @input_mask: mask for the input bitstream
+ *
+ * This function serves two main purposes. First it applys the input_mask
+ * to the atr_input resulting in a cleaned up atr_input data stream.
+ * Secondly it computes the hash and stores it in the bkt_hash field at
+ * the end of the input byte stream. This way it will be available for
+ * future use without needing to recompute the hash.
+ **/
+void ixgbe_atr_compute_perfect_hash_82599(union ixgbe_atr_input *input,
+ union ixgbe_atr_input *input_mask)
+{
+
+ u32 hi_hash_dword, lo_hash_dword, flow_vm_vlan;
+ u32 bucket_hash = 0;
+
+ /* Apply masks to input data */
+ input->dword_stream[0] &= input_mask->dword_stream[0];
+ input->dword_stream[1] &= input_mask->dword_stream[1];
+ input->dword_stream[2] &= input_mask->dword_stream[2];
+ input->dword_stream[3] &= input_mask->dword_stream[3];
+ input->dword_stream[4] &= input_mask->dword_stream[4];
+ input->dword_stream[5] &= input_mask->dword_stream[5];
+ input->dword_stream[6] &= input_mask->dword_stream[6];
+ input->dword_stream[7] &= input_mask->dword_stream[7];
+ input->dword_stream[8] &= input_mask->dword_stream[8];
+ input->dword_stream[9] &= input_mask->dword_stream[9];
+ input->dword_stream[10] &= input_mask->dword_stream[10];
+
+ /* record the flow_vm_vlan bits as they are a key part to the hash */
+ flow_vm_vlan = ntohl(input->dword_stream[0]);
+
+ /* generate common hash dword */
+ hi_hash_dword = ntohl(input->dword_stream[1] ^
+ input->dword_stream[2] ^
+ input->dword_stream[3] ^
+ input->dword_stream[4] ^
+ input->dword_stream[5] ^
+ input->dword_stream[6] ^
+ input->dword_stream[7] ^
+ input->dword_stream[8] ^
+ input->dword_stream[9] ^
+ input->dword_stream[10]);
+
+ /* low dword is word swapped version of common */
+ lo_hash_dword = (hi_hash_dword >> 16) | (hi_hash_dword << 16);
+
+ /* apply flow ID/VM pool/VLAN ID bits to hash words */
+ hi_hash_dword ^= flow_vm_vlan ^ (flow_vm_vlan >> 16);
+
+ /* Process bits 0 and 16 */
+ IXGBE_COMPUTE_BKT_HASH_ITERATION(0);
+
+ /*
+ * apply flow ID/VM pool/VLAN ID bits to lo hash dword, we had to
+ * delay this because bit 0 of the stream should not be processed
+ * so we do not add the vlan until after bit 0 was processed
+ */
+ lo_hash_dword ^= flow_vm_vlan ^ (flow_vm_vlan << 16);
+
+ /* Process remaining 30 bit of the key */
+ IXGBE_COMPUTE_BKT_HASH_ITERATION(1);
+ IXGBE_COMPUTE_BKT_HASH_ITERATION(2);
+ IXGBE_COMPUTE_BKT_HASH_ITERATION(3);
+ IXGBE_COMPUTE_BKT_HASH_ITERATION(4);
+ IXGBE_COMPUTE_BKT_HASH_ITERATION(5);
+ IXGBE_COMPUTE_BKT_HASH_ITERATION(6);
+ IXGBE_COMPUTE_BKT_HASH_ITERATION(7);
+ IXGBE_COMPUTE_BKT_HASH_ITERATION(8);
+ IXGBE_COMPUTE_BKT_HASH_ITERATION(9);
+ IXGBE_COMPUTE_BKT_HASH_ITERATION(10);
+ IXGBE_COMPUTE_BKT_HASH_ITERATION(11);
+ IXGBE_COMPUTE_BKT_HASH_ITERATION(12);
+ IXGBE_COMPUTE_BKT_HASH_ITERATION(13);
+ IXGBE_COMPUTE_BKT_HASH_ITERATION(14);
+ IXGBE_COMPUTE_BKT_HASH_ITERATION(15);
+
+ /*
+ * Limit hash to 13 bits since max bucket count is 8K.
+ * Store result at the end of the input stream.
+ */
+ input->formatted.bkt_hash = bucket_hash & 0x1FFF;
+}
+
/**
* ixgbe_get_fdirtcpm_82599 - generate a tcp port from atr_input_masks
* @input_mask: mask to be bit swapped
@@ -1531,11 +1531,11 @@
* generate a correctly swapped value we need to bit swap the mask and that
* is what is accomplished by this function.
**/
-static u32 ixgbe_get_fdirtcpm_82599(struct ixgbe_atr_input_masks *input_masks)
+static u32 ixgbe_get_fdirtcpm_82599(union ixgbe_atr_input *input_mask)
{
- u32 mask = ntohs(input_masks->dst_port_mask);
+ u32 mask = ntohs(input_mask->formatted.dst_port);
mask <<= IXGBE_FDIRTCPM_DPORTM_SHIFT;
- mask |= ntohs(input_masks->src_port_mask);
+ mask |= ntohs(input_mask->formatted.src_port);
mask = ((mask & 0x55555555) << 1) | ((mask & 0xAAAAAAAA) >> 1);
mask = ((mask & 0x33333333) << 2) | ((mask & 0xCCCCCCCC) >> 2);
mask = ((mask & 0x0F0F0F0F) << 4) | ((mask & 0xF0F0F0F0) >> 4);
@@ -1557,52 +1557,14 @@
IXGBE_WRITE_REG((a), (reg), IXGBE_STORE_AS_BE32(ntohl(value)))
#define IXGBE_STORE_AS_BE16(_value) \
- (((u16)(_value) >> 8) | ((u16)(_value) << 8))
+ ntohs(((u16)(_value) >> 8) | ((u16)(_value) << 8))
-/**
- * ixgbe_fdir_add_perfect_filter_82599 - Adds a perfect filter
- * @hw: pointer to hardware structure
- * @input: input bitstream
- * @input_masks: bitwise masks for relevant fields
- * @soft_id: software index into the silicon hash tables for filter storage
- * @queue: queue index to direct traffic to
- *
- * Note that the caller to this function must lock before calling, since the
- * hardware writes must be protected from one another.
- **/
-s32 ixgbe_fdir_add_perfect_filter_82599(struct ixgbe_hw *hw,
- union ixgbe_atr_input *input,
- struct ixgbe_atr_input_masks *input_masks,
- u16 soft_id, u8 queue)
+s32 ixgbe_fdir_set_input_mask_82599(struct ixgbe_hw *hw,
+ union ixgbe_atr_input *input_mask)
{
- u32 fdirhash;
- u32 fdircmd;
- u32 fdirport, fdirtcpm;
- u32 fdirvlan;
- /* start with VLAN, flex bytes, VM pool, and IPv6 destination masked */
- u32 fdirm = IXGBE_FDIRM_VLANID | IXGBE_FDIRM_VLANP | IXGBE_FDIRM_FLEX |
- IXGBE_FDIRM_POOL | IXGBE_FDIRM_DIPv6;
-
- /*
- * Check flow_type formatting, and bail out before we touch the hardware
- * if there's a configuration issue
- */
- switch (input->formatted.flow_type) {
- case IXGBE_ATR_FLOW_TYPE_IPV4:
- /* use the L4 protocol mask for raw IPv4/IPv6 traffic */
- fdirm |= IXGBE_FDIRM_L4P;
- case IXGBE_ATR_FLOW_TYPE_SCTPV4:
- if (input_masks->dst_port_mask || input_masks->src_port_mask) {
- hw_dbg(hw, " Error on src/dst port mask\n");
- return IXGBE_ERR_CONFIG;
- }
- case IXGBE_ATR_FLOW_TYPE_TCPV4:
- case IXGBE_ATR_FLOW_TYPE_UDPV4:
- break;
- default:
- hw_dbg(hw, " Error on flow type input\n");
- return IXGBE_ERR_CONFIG;
- }
+ /* mask IPv6 since it is currently not supported */
+ u32 fdirm = IXGBE_FDIRM_DIPv6;
+ u32 fdirtcpm;
/*
* Program the relevant mask registers. If src/dst_port or src/dst_addr
@@ -1614,41 +1576,71 @@
* point in time.
*/
- /* Program FDIRM */
- switch (ntohs(input_masks->vlan_id_mask) & 0xEFFF) {
- case 0xEFFF:
- /* Unmask VLAN ID - bit 0 and fall through to unmask prio */
- fdirm &= ~IXGBE_FDIRM_VLANID;
- case 0xE000:
- /* Unmask VLAN prio - bit 1 */
- fdirm &= ~IXGBE_FDIRM_VLANP;
+ /* verify bucket hash is cleared on hash generation */
+ if (input_mask->formatted.bkt_hash)
+ hw_dbg(hw, " bucket hash should always be 0 in mask\n");
+
+ /* Program FDIRM and verify partial masks */
+ switch (input_mask->formatted.vm_pool & 0x7F) {
+ case 0x0:
+ fdirm |= IXGBE_FDIRM_POOL;
+ case 0x7F:
break;
- case 0x0FFF:
- /* Unmask VLAN ID - bit 0 */
- fdirm &= ~IXGBE_FDIRM_VLANID;
+ default:
+ hw_dbg(hw, " Error on vm pool mask\n");
+ return IXGBE_ERR_CONFIG;
+ }
+
+ switch (input_mask->formatted.flow_type & IXGBE_ATR_L4TYPE_MASK) {
+ case 0x0:
+ fdirm |= IXGBE_FDIRM_L4P;
+ if (input_mask->formatted.dst_port ||
+ input_mask->formatted.src_port) {
+ hw_dbg(hw, " Error on src/dst port mask\n");
+ return IXGBE_ERR_CONFIG;
+ }
+ case IXGBE_ATR_L4TYPE_MASK:
break;
+ default:
+ hw_dbg(hw, " Error on flow type mask\n");
+ return IXGBE_ERR_CONFIG;
+ }
+
+ switch (ntohs(input_mask->formatted.vlan_id) & 0xEFFF) {
case 0x0000:
- /* do nothing, vlans already masked */
+ /* mask VLAN ID, fall through to mask VLAN priority */
+ fdirm |= IXGBE_FDIRM_VLANID;
+ case 0x0FFF:
+ /* mask VLAN priority */
+ fdirm |= IXGBE_FDIRM_VLANP;
+ break;
+ case 0xE000:
+ /* mask VLAN ID only, fall through */
+ fdirm |= IXGBE_FDIRM_VLANID;
+ case 0xEFFF:
+ /* no VLAN fields masked */
break;
default:
hw_dbg(hw, " Error on VLAN mask\n");
return IXGBE_ERR_CONFIG;
}
- if (input_masks->flex_mask & 0xFFFF) {
- if ((input_masks->flex_mask & 0xFFFF) != 0xFFFF) {
- hw_dbg(hw, " Error on flexible byte mask\n");
- return IXGBE_ERR_CONFIG;
- }
- /* Unmask Flex Bytes - bit 4 */
- fdirm &= ~IXGBE_FDIRM_FLEX;
+ switch (input_mask->formatted.flex_bytes & 0xFFFF) {
+ case 0x0000:
+ /* Mask Flex Bytes, fall through */
+ fdirm |= IXGBE_FDIRM_FLEX;
+ case 0xFFFF:
+ break;
+ default:
+ hw_dbg(hw, " Error on flexible byte mask\n");
+ return IXGBE_ERR_CONFIG;
}
/* Now mask VM pool and destination IPv6 - bits 5 and 2 */
IXGBE_WRITE_REG(hw, IXGBE_FDIRM, fdirm);
/* store the TCP/UDP port masks, bit reversed from port layout */
- fdirtcpm = ixgbe_get_fdirtcpm_82599(input_masks);
+ fdirtcpm = ixgbe_get_fdirtcpm_82599(input_mask);
/* write both the same so that UDP and TCP use the same mask */
IXGBE_WRITE_REG(hw, IXGBE_FDIRTCPM, ~fdirtcpm);
@@ -1656,24 +1648,32 @@
/* store source and destination IP masks (big-enian) */
IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRSIP4M,
- ~input_masks->src_ip_mask[0]);
+ ~input_mask->formatted.src_ip[0]);
IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRDIP4M,
- ~input_masks->dst_ip_mask[0]);
+ ~input_mask->formatted.dst_ip[0]);
- /* Apply masks to input data */
- input->formatted.vlan_id &= input_masks->vlan_id_mask;
- input->formatted.flex_bytes &= input_masks->flex_mask;
- input->formatted.src_port &= input_masks->src_port_mask;
- input->formatted.dst_port &= input_masks->dst_port_mask;
- input->formatted.src_ip[0] &= input_masks->src_ip_mask[0];
- input->formatted.dst_ip[0] &= input_masks->dst_ip_mask[0];
+ return 0;
+}
- /* record vlan (little-endian) and flex_bytes(big-endian) */
- fdirvlan =
- IXGBE_STORE_AS_BE16(ntohs(input->formatted.flex_bytes));
- fdirvlan <<= IXGBE_FDIRVLAN_FLEX_SHIFT;
- fdirvlan |= ntohs(input->formatted.vlan_id);
- IXGBE_WRITE_REG(hw, IXGBE_FDIRVLAN, fdirvlan);
+s32 ixgbe_fdir_write_perfect_filter_82599(struct ixgbe_hw *hw,
+ union ixgbe_atr_input *input,
+ u16 soft_id, u8 queue)
+{
+ u32 fdirport, fdirvlan, fdirhash, fdircmd;
+
+ /* currently IPv6 is not supported, must be programmed with 0 */
+ IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRSIPv6(0),
+ input->formatted.src_ip[0]);
+ IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRSIPv6(1),
+ input->formatted.src_ip[1]);
+ IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRSIPv6(2),
+ input->formatted.src_ip[2]);
+
+ /* record the source address (big-endian) */
+ IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRIPSA, input->formatted.src_ip[0]);
+
+ /* record the first 32 bits of the destination address (big-endian) */
+ IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRIPDA, input->formatted.dst_ip[0]);
/* record source and destination port (little-endian)*/
fdirport = ntohs(input->formatted.dst_port);
@@ -1681,29 +1681,80 @@
fdirport |= ntohs(input->formatted.src_port);
IXGBE_WRITE_REG(hw, IXGBE_FDIRPORT, fdirport);
- /* record the first 32 bits of the destination address (big-endian) */
- IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRIPDA, input->formatted.dst_ip[0]);
+ /* record vlan (little-endian) and flex_bytes(big-endian) */
+ fdirvlan = IXGBE_STORE_AS_BE16(input->formatted.flex_bytes);
+ fdirvlan <<= IXGBE_FDIRVLAN_FLEX_SHIFT;
+ fdirvlan |= ntohs(input->formatted.vlan_id);
+ IXGBE_WRITE_REG(hw, IXGBE_FDIRVLAN, fdirvlan);
- /* record the source address (big-endian) */
- IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRIPSA, input->formatted.src_ip[0]);
+ /* configure FDIRHASH register */
+ fdirhash = input->formatted.bkt_hash;
+ fdirhash |= soft_id << IXGBE_FDIRHASH_SIG_SW_INDEX_SHIFT;
+ IXGBE_WRITE_REG(hw, IXGBE_FDIRHASH, fdirhash);
+
+ /*
+ * flush all previous writes to make certain registers are
+ * programmed prior to issuing the command
+ */
+ IXGBE_WRITE_FLUSH(hw);
/* configure FDIRCMD register */
fdircmd = IXGBE_FDIRCMD_CMD_ADD_FLOW | IXGBE_FDIRCMD_FILTER_UPDATE |
IXGBE_FDIRCMD_LAST | IXGBE_FDIRCMD_QUEUE_EN;
+ if (queue == IXGBE_FDIR_DROP_QUEUE)
+ fdircmd |= IXGBE_FDIRCMD_DROP;
fdircmd |= input->formatted.flow_type << IXGBE_FDIRCMD_FLOW_TYPE_SHIFT;
fdircmd |= (u32)queue << IXGBE_FDIRCMD_RX_QUEUE_SHIFT;
+ fdircmd |= (u32)input->formatted.vm_pool << IXGBE_FDIRCMD_VT_POOL_SHIFT;
- /* we only want the bucket hash so drop the upper 16 bits */
- fdirhash = ixgbe_atr_compute_hash_82599(input,
- IXGBE_ATR_BUCKET_HASH_KEY);
- fdirhash |= soft_id << IXGBE_FDIRHASH_SIG_SW_INDEX_SHIFT;
-
- IXGBE_WRITE_REG(hw, IXGBE_FDIRHASH, fdirhash);
IXGBE_WRITE_REG(hw, IXGBE_FDIRCMD, fdircmd);
return 0;
}
+s32 ixgbe_fdir_erase_perfect_filter_82599(struct ixgbe_hw *hw,
+ union ixgbe_atr_input *input,
+ u16 soft_id)
+{
+ u32 fdirhash;
+ u32 fdircmd = 0;
+ u32 retry_count;
+ s32 err = 0;
+
+ /* configure FDIRHASH register */
+ fdirhash = input->formatted.bkt_hash;
+ fdirhash |= soft_id << IXGBE_FDIRHASH_SIG_SW_INDEX_SHIFT;
+ IXGBE_WRITE_REG(hw, IXGBE_FDIRHASH, fdirhash);
+
+ /* flush hash to HW */
+ IXGBE_WRITE_FLUSH(hw);
+
+ /* Query if filter is present */
+ IXGBE_WRITE_REG(hw, IXGBE_FDIRCMD, IXGBE_FDIRCMD_CMD_QUERY_REM_FILT);
+
+ for (retry_count = 10; retry_count; retry_count--) {
+ /* allow 10us for query to process */
+ udelay(10);
+ /* verify query completed successfully */
+ fdircmd = IXGBE_READ_REG(hw, IXGBE_FDIRCMD);
+ if (!(fdircmd & IXGBE_FDIRCMD_CMD_MASK))
+ break;
+ }
+
+ if (!retry_count)
+ err = IXGBE_ERR_FDIR_REINIT_FAILED;
+
+ /* if filter exists in hardware then remove it */
+ if (fdircmd & IXGBE_FDIRCMD_FILTER_VALID) {
+ IXGBE_WRITE_REG(hw, IXGBE_FDIRHASH, fdirhash);
+ IXGBE_WRITE_FLUSH(hw);
+ IXGBE_WRITE_REG(hw, IXGBE_FDIRCMD,
+ IXGBE_FDIRCMD_CMD_REMOVE_FLOW);
+ }
+
+ return err;
+}
+
/**
* ixgbe_read_analog_reg8_82599 - Reads 8 bit Omer analog register
* @hw: pointer to hardware structure
@@ -2146,6 +2197,7 @@
.read_analog_reg8 = &ixgbe_read_analog_reg8_82599,
.write_analog_reg8 = &ixgbe_write_analog_reg8_82599,
.setup_link = &ixgbe_setup_mac_link_82599,
+ .set_rxpba = &ixgbe_set_rxpba_generic,
.check_link = &ixgbe_check_mac_link_generic,
.get_link_capabilities = &ixgbe_get_link_capabilities_82599,
.led_on = &ixgbe_led_on_generic,
@@ -2163,6 +2215,7 @@
.clear_vfta = &ixgbe_clear_vfta_generic,
.set_vfta = &ixgbe_set_vfta_generic,
.fc_enable = &ixgbe_fc_enable_generic,
+ .set_fw_drv_ver = &ixgbe_set_fw_drv_ver_generic,
.init_uta_tables = &ixgbe_init_uta_tables_generic,
.setup_sfp = &ixgbe_setup_sfp_modules_82599,
.set_mac_anti_spoofing = &ixgbe_set_mac_anti_spoofing,
diff --git a/drivers/net/ixgbe/ixgbe_common.c b/drivers/net/ixgbe/ixgbe_common.c
index b894b42..777051f 100644
--- a/drivers/net/ixgbe/ixgbe_common.c
+++ b/drivers/net/ixgbe/ixgbe_common.c
@@ -1292,7 +1292,7 @@
udelay(5);
ixgbe_standby_eeprom(hw);
- };
+ }
/*
* On some parts, SPI write time could vary from 0-20mSec on 3.3V
@@ -1374,7 +1374,7 @@
* EEPROM
*/
mask = mask >> 1;
- };
+ }
/* We leave the "DI" bit set to "0" when we leave this routine. */
eec &= ~IXGBE_EEC_DI;
@@ -3267,3 +3267,243 @@
return 0;
}
+
+/**
+ * ixgbe_set_rxpba_generic - Initialize RX packet buffer
+ * @hw: pointer to hardware structure
+ * @num_pb: number of packet buffers to allocate
+ * @headroom: reserve n KB of headroom
+ * @strategy: packet buffer allocation strategy
+ **/
+void ixgbe_set_rxpba_generic(struct ixgbe_hw *hw,
+ int num_pb,
+ u32 headroom,
+ int strategy)
+{
+ u32 pbsize = hw->mac.rx_pb_size;
+ int i = 0;
+ u32 rxpktsize, txpktsize, txpbthresh;
+
+ /* Reserve headroom */
+ pbsize -= headroom;
+
+ if (!num_pb)
+ num_pb = 1;
+
+ /* Divide remaining packet buffer space amongst the number
+ * of packet buffers requested using supplied strategy.
+ */
+ switch (strategy) {
+ case (PBA_STRATEGY_WEIGHTED):
+ /* pba_80_48 strategy weight first half of packet buffer with
+ * 5/8 of the packet buffer space.
+ */
+ rxpktsize = ((pbsize * 5 * 2) / (num_pb * 8));
+ pbsize -= rxpktsize * (num_pb / 2);
+ rxpktsize <<= IXGBE_RXPBSIZE_SHIFT;
+ for (; i < (num_pb / 2); i++)
+ IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), rxpktsize);
+ /* Fall through to configure remaining packet buffers */
+ case (PBA_STRATEGY_EQUAL):
+ /* Divide the remaining Rx packet buffer evenly among the TCs */
+ rxpktsize = (pbsize / (num_pb - i)) << IXGBE_RXPBSIZE_SHIFT;
+ for (; i < num_pb; i++)
+ IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), rxpktsize);
+ break;
+ default:
+ break;
+ }
+
+ /*
+ * Setup Tx packet buffer and threshold equally for all TCs
+ * TXPBTHRESH register is set in K so divide by 1024 and subtract
+ * 10 since the largest packet we support is just over 9K.
+ */
+ txpktsize = IXGBE_TXPBSIZE_MAX / num_pb;
+ txpbthresh = (txpktsize / 1024) - IXGBE_TXPKT_SIZE_MAX;
+ for (i = 0; i < num_pb; i++) {
+ IXGBE_WRITE_REG(hw, IXGBE_TXPBSIZE(i), txpktsize);
+ IXGBE_WRITE_REG(hw, IXGBE_TXPBTHRESH(i), txpbthresh);
+ }
+
+ /* Clear unused TCs, if any, to zero buffer size*/
+ for (; i < IXGBE_MAX_PB; i++) {
+ IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), 0);
+ IXGBE_WRITE_REG(hw, IXGBE_TXPBSIZE(i), 0);
+ IXGBE_WRITE_REG(hw, IXGBE_TXPBTHRESH(i), 0);
+ }
+}
+
+/**
+ * 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.
+ **/
+static u8 ixgbe_calculate_checksum(u8 *buffer, u32 length)
+{
+ u32 i;
+ u8 sum = 0;
+
+ if (!buffer)
+ return 0;
+
+ for (i = 0; i < length; i++)
+ sum += buffer[i];
+
+ return (u8) (0 - sum);
+}
+
+/**
+ * ixgbe_host_interface_command - Issue command to manageability block
+ * @hw: pointer to the HW structure
+ * @buffer: contains the command to write and where the return status will
+ * be placed
+ * @lenght: lenght of buffer, must be multiple of 4 bytes
+ *
+ * Communicates with the manageability block. On success return 0
+ * else return IXGBE_ERR_HOST_INTERFACE_COMMAND.
+ **/
+static s32 ixgbe_host_interface_command(struct ixgbe_hw *hw, u8 *buffer,
+ u32 length)
+{
+ u32 hicr, i;
+ u32 hdr_size = sizeof(struct ixgbe_hic_hdr);
+ u8 buf_len, dword_len;
+
+ s32 ret_val = 0;
+
+ if (length == 0 || length & 0x3 ||
+ length > IXGBE_HI_MAX_BLOCK_BYTE_LENGTH) {
+ hw_dbg(hw, "Buffer length failure.\n");
+ ret_val = IXGBE_ERR_HOST_INTERFACE_COMMAND;
+ goto out;
+ }
+
+ /* Check that the host interface is enabled. */
+ hicr = IXGBE_READ_REG(hw, IXGBE_HICR);
+ if ((hicr & IXGBE_HICR_EN) == 0) {
+ hw_dbg(hw, "IXGBE_HOST_EN bit disabled.\n");
+ ret_val = IXGBE_ERR_HOST_INTERFACE_COMMAND;
+ goto out;
+ }
+
+ /* Calculate length in DWORDs */
+ dword_len = length >> 2;
+
+ /*
+ * The device driver writes the relevant command block
+ * into the ram area.
+ */
+ for (i = 0; i < dword_len; i++)
+ IXGBE_WRITE_REG_ARRAY(hw, IXGBE_FLEX_MNG,
+ i, *((u32 *)buffer + i));
+
+ /* Setting this bit tells the ARC that a new command is pending. */
+ IXGBE_WRITE_REG(hw, IXGBE_HICR, hicr | IXGBE_HICR_C);
+
+ for (i = 0; i < IXGBE_HI_COMMAND_TIMEOUT; i++) {
+ hicr = IXGBE_READ_REG(hw, IXGBE_HICR);
+ if (!(hicr & IXGBE_HICR_C))
+ break;
+ usleep_range(1000, 2000);
+ }
+
+ /* Check command successful completion. */
+ if (i == IXGBE_HI_COMMAND_TIMEOUT ||
+ (!(IXGBE_READ_REG(hw, IXGBE_HICR) & IXGBE_HICR_SV))) {
+ hw_dbg(hw, "Command has failed with no status valid.\n");
+ ret_val = IXGBE_ERR_HOST_INTERFACE_COMMAND;
+ goto out;
+ }
+
+ /* Calculate length in DWORDs */
+ dword_len = hdr_size >> 2;
+
+ /* first pull in the header so we know the buffer length */
+ for (i = 0; i < dword_len; i++)
+ *((u32 *)buffer + i) =
+ IXGBE_READ_REG_ARRAY(hw, IXGBE_FLEX_MNG, i);
+
+ /* If there is any thing in data position pull it in */
+ buf_len = ((struct ixgbe_hic_hdr *)buffer)->buf_len;
+ if (buf_len == 0)
+ goto out;
+
+ if (length < (buf_len + hdr_size)) {
+ hw_dbg(hw, "Buffer not large enough for reply message.\n");
+ ret_val = IXGBE_ERR_HOST_INTERFACE_COMMAND;
+ goto out;
+ }
+
+ /* Calculate length in DWORDs, add one for odd lengths */
+ dword_len = (buf_len + 1) >> 2;
+
+ /* Pull in the rest of the buffer (i is where we left off)*/
+ for (; i < buf_len; i++)
+ *((u32 *)buffer + i) =
+ IXGBE_READ_REG_ARRAY(hw, IXGBE_FLEX_MNG, i);
+
+out:
+ return ret_val;
+}
+
+/**
+ * ixgbe_set_fw_drv_ver_generic - Sends driver version to firmware
+ * @hw: pointer to the HW structure
+ * @maj: driver version major number
+ * @min: driver version minor number
+ * @build: driver version build number
+ * @sub: driver version sub build number
+ *
+ * Sends driver version number to firmware through the manageability
+ * block. On success return 0
+ * else returns IXGBE_ERR_SWFW_SYNC when encountering an error acquiring
+ * semaphore or IXGBE_ERR_HOST_INTERFACE_COMMAND when command fails.
+ **/
+s32 ixgbe_set_fw_drv_ver_generic(struct ixgbe_hw *hw, u8 maj, u8 min,
+ u8 build, u8 sub)
+{
+ struct ixgbe_hic_drv_info fw_cmd;
+ int i;
+ s32 ret_val = 0;
+
+ if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_SW_MNG_SM) != 0) {
+ ret_val = IXGBE_ERR_SWFW_SYNC;
+ goto out;
+ }
+
+ fw_cmd.hdr.cmd = FW_CEM_CMD_DRIVER_INFO;
+ fw_cmd.hdr.buf_len = FW_CEM_CMD_DRIVER_INFO_LEN;
+ fw_cmd.hdr.cmd_or_resp.cmd_resv = FW_CEM_CMD_RESERVED;
+ fw_cmd.port_num = (u8)hw->bus.func;
+ fw_cmd.ver_maj = maj;
+ fw_cmd.ver_min = min;
+ fw_cmd.ver_build = build;
+ fw_cmd.ver_sub = sub;
+ fw_cmd.hdr.checksum = 0;
+ fw_cmd.hdr.checksum = ixgbe_calculate_checksum((u8 *)&fw_cmd,
+ (FW_CEM_HDR_LEN + fw_cmd.hdr.buf_len));
+ fw_cmd.pad = 0;
+ fw_cmd.pad2 = 0;
+
+ for (i = 0; i <= FW_CEM_MAX_RETRIES; i++) {
+ ret_val = ixgbe_host_interface_command(hw, (u8 *)&fw_cmd,
+ sizeof(fw_cmd));
+ if (ret_val != 0)
+ continue;
+
+ if (fw_cmd.hdr.cmd_or_resp.ret_status ==
+ FW_CEM_RESP_STATUS_SUCCESS)
+ ret_val = 0;
+ else
+ ret_val = IXGBE_ERR_HOST_INTERFACE_COMMAND;
+
+ break;
+ }
+
+ hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_SW_MNG_SM);
+out:
+ return ret_val;
+}
diff --git a/drivers/net/ixgbe/ixgbe_common.h b/drivers/net/ixgbe/ixgbe_common.h
index 46be83c..f24fd64 100644
--- a/drivers/net/ixgbe/ixgbe_common.h
+++ b/drivers/net/ixgbe/ixgbe_common.h
@@ -99,6 +99,11 @@
void ixgbe_set_mac_anti_spoofing(struct ixgbe_hw *hw, bool enable, int pf);
void ixgbe_set_vlan_anti_spoofing(struct ixgbe_hw *hw, bool enable, int vf);
s32 ixgbe_get_device_caps_generic(struct ixgbe_hw *hw, u16 *device_caps);
+s32 ixgbe_set_fw_drv_ver_generic(struct ixgbe_hw *hw, u8 maj, u8 min,
+ u8 build, u8 ver);
+
+void ixgbe_set_rxpba_generic(struct ixgbe_hw *hw, int num_pb,
+ u32 headroom, int strategy);
#define IXGBE_WRITE_REG(a, reg, value) writel((value), ((a)->hw_addr + (reg)))
diff --git a/drivers/net/ixgbe/ixgbe_dcb.c b/drivers/net/ixgbe/ixgbe_dcb.c
index 686a17a..9d88c31 100644
--- a/drivers/net/ixgbe/ixgbe_dcb.c
+++ b/drivers/net/ixgbe/ixgbe_dcb.c
@@ -258,15 +258,13 @@
switch (hw->mac.type) {
case ixgbe_mac_82598EB:
- ret = ixgbe_dcb_hw_config_82598(hw, dcb_config->rx_pba_cfg,
- pfc_en, refill, max, bwgid,
- ptype);
+ ret = ixgbe_dcb_hw_config_82598(hw, pfc_en, refill, max,
+ bwgid, ptype);
break;
case ixgbe_mac_82599EB:
case ixgbe_mac_X540:
- ret = ixgbe_dcb_hw_config_82599(hw, dcb_config->rx_pba_cfg,
- pfc_en, refill, max, bwgid,
- ptype, prio_tc);
+ ret = ixgbe_dcb_hw_config_82599(hw, pfc_en, refill, max,
+ bwgid, ptype, prio_tc);
break;
default:
break;
diff --git a/drivers/net/ixgbe/ixgbe_dcb.h b/drivers/net/ixgbe/ixgbe_dcb.h
index 944838f..e85826a 100644
--- a/drivers/net/ixgbe/ixgbe_dcb.h
+++ b/drivers/net/ixgbe/ixgbe_dcb.h
@@ -123,11 +123,6 @@
u8 tc; /* Traffic class (TC) */
};
-enum dcb_rx_pba_cfg {
- pba_equal, /* PBA[0-7] each use 64KB FIFO */
- pba_80_48 /* PBA[0-3] each use 80KB, PBA[4-7] each use 48KB */
-};
-
struct dcb_num_tcs {
u8 pg_tcs;
u8 pfc_tcs;
@@ -140,8 +135,6 @@
u8 bw_percentage[2][MAX_BW_GROUP]; /* One each for Tx/Rx */
bool pfc_mode_enable;
- enum dcb_rx_pba_cfg rx_pba_cfg;
-
u32 dcb_cfg_version; /* Not used...OS-specific? */
u32 link_speed; /* For bandwidth allocation validation purpose */
};
diff --git a/drivers/net/ixgbe/ixgbe_dcb_82598.c b/drivers/net/ixgbe/ixgbe_dcb_82598.c
index 771d01a..2288c3c 100644
--- a/drivers/net/ixgbe/ixgbe_dcb_82598.c
+++ b/drivers/net/ixgbe/ixgbe_dcb_82598.c
@@ -32,45 +32,6 @@
#include "ixgbe_dcb_82598.h"
/**
- * ixgbe_dcb_config_packet_buffers_82598 - Configure packet buffers
- * @hw: pointer to hardware structure
- * @dcb_config: pointer to ixgbe_dcb_config structure
- *
- * Configure packet buffers for DCB mode.
- */
-static s32 ixgbe_dcb_config_packet_buffers_82598(struct ixgbe_hw *hw, u8 rx_pba)
-{
- s32 ret_val = 0;
- u32 value = IXGBE_RXPBSIZE_64KB;
- u8 i = 0;
-
- /* Setup Rx packet buffer sizes */
- switch (rx_pba) {
- case pba_80_48:
- /* Setup the first four at 80KB */
- value = IXGBE_RXPBSIZE_80KB;
- for (; i < 4; i++)
- IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), value);
- /* Setup the last four at 48KB...don't re-init i */
- value = IXGBE_RXPBSIZE_48KB;
- /* Fall Through */
- case pba_equal:
- default:
- for (; i < IXGBE_MAX_PACKET_BUFFERS; i++)
- IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), value);
-
- /* Setup Tx packet buffer sizes */
- for (i = 0; i < IXGBE_MAX_PACKET_BUFFERS; i++) {
- IXGBE_WRITE_REG(hw, IXGBE_TXPBSIZE(i),
- IXGBE_TXPBSIZE_40KB);
- }
- break;
- }
-
- return ret_val;
-}
-
-/**
* ixgbe_dcb_config_rx_arbiter_82598 - Config Rx data arbiter
* @hw: pointer to hardware structure
* @dcb_config: pointer to ixgbe_dcb_config structure
@@ -321,11 +282,9 @@
*
* Configure dcb settings and enable dcb mode.
*/
-s32 ixgbe_dcb_hw_config_82598(struct ixgbe_hw *hw,
- u8 rx_pba, u8 pfc_en, u16 *refill,
+s32 ixgbe_dcb_hw_config_82598(struct ixgbe_hw *hw, u8 pfc_en, u16 *refill,
u16 *max, u8 *bwg_id, u8 *prio_type)
{
- ixgbe_dcb_config_packet_buffers_82598(hw, rx_pba);
ixgbe_dcb_config_rx_arbiter_82598(hw, refill, max, prio_type);
ixgbe_dcb_config_tx_desc_arbiter_82598(hw, refill, max,
bwg_id, prio_type);
diff --git a/drivers/net/ixgbe/ixgbe_dcb_82598.h b/drivers/net/ixgbe/ixgbe_dcb_82598.h
index 1e9750c..2f31893 100644
--- a/drivers/net/ixgbe/ixgbe_dcb_82598.h
+++ b/drivers/net/ixgbe/ixgbe_dcb_82598.h
@@ -91,8 +91,7 @@
u8 *bwg_id,
u8 *prio_type);
-s32 ixgbe_dcb_hw_config_82598(struct ixgbe_hw *hw,
- u8 rx_pba, u8 pfc_en, u16 *refill,
+s32 ixgbe_dcb_hw_config_82598(struct ixgbe_hw *hw, u8 pfc_en, u16 *refill,
u16 *max, u8 *bwg_id, u8 *prio_type);
#endif /* _DCB_82598_CONFIG_H */
diff --git a/drivers/net/ixgbe/ixgbe_dcb_82599.c b/drivers/net/ixgbe/ixgbe_dcb_82599.c
index d50cf78..ade9820 100644
--- a/drivers/net/ixgbe/ixgbe_dcb_82599.c
+++ b/drivers/net/ixgbe/ixgbe_dcb_82599.c
@@ -31,63 +31,6 @@
#include "ixgbe_dcb_82599.h"
/**
- * ixgbe_dcb_config_packet_buffers_82599 - Configure DCB packet buffers
- * @hw: pointer to hardware structure
- * @rx_pba: method to distribute packet buffer
- *
- * Configure packet buffers for DCB mode.
- */
-static s32 ixgbe_dcb_config_packet_buffers_82599(struct ixgbe_hw *hw, u8 rx_pba)
-{
- int num_tcs = IXGBE_MAX_PACKET_BUFFERS;
- u32 rx_pb_size = hw->mac.rx_pb_size << IXGBE_RXPBSIZE_SHIFT;
- u32 rxpktsize;
- u32 txpktsize;
- u32 txpbthresh;
- u8 i = 0;
-
- /*
- * This really means configure the first half of the TCs
- * (Traffic Classes) to use 5/8 of the Rx packet buffer
- * space. To determine the size of the buffer for each TC,
- * we are multiplying the average size by 5/4 and applying
- * it to half of the traffic classes.
- */
- if (rx_pba == pba_80_48) {
- rxpktsize = (rx_pb_size * 5) / (num_tcs * 4);
- rx_pb_size -= rxpktsize * (num_tcs / 2);
- for (; i < (num_tcs / 2); i++)
- IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), rxpktsize);
- }
-
- /* Divide the remaining Rx packet buffer evenly among the TCs */
- rxpktsize = rx_pb_size / (num_tcs - i);
- for (; i < num_tcs; i++)
- IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), rxpktsize);
-
- /*
- * Setup Tx packet buffer and threshold equally for all TCs
- * TXPBTHRESH register is set in K so divide by 1024 and subtract
- * 10 since the largest packet we support is just over 9K.
- */
- txpktsize = IXGBE_TXPBSIZE_MAX / num_tcs;
- txpbthresh = (txpktsize / 1024) - IXGBE_TXPKT_SIZE_MAX;
- for (i = 0; i < num_tcs; i++) {
- IXGBE_WRITE_REG(hw, IXGBE_TXPBSIZE(i), txpktsize);
- IXGBE_WRITE_REG(hw, IXGBE_TXPBTHRESH(i), txpbthresh);
- }
-
- /* Clear unused TCs, if any, to zero buffer size*/
- for (; i < MAX_TRAFFIC_CLASS; i++) {
- IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), 0);
- IXGBE_WRITE_REG(hw, IXGBE_TXPBSIZE(i), 0);
- IXGBE_WRITE_REG(hw, IXGBE_TXPBTHRESH(i), 0);
- }
-
- return 0;
-}
-
-/**
* ixgbe_dcb_config_rx_arbiter_82599 - Config Rx Data arbiter
* @hw: pointer to hardware structure
* @refill: refill credits index by traffic class
@@ -376,65 +319,8 @@
}
/**
- * ixgbe_dcb_config_82599 - Configure general DCB parameters
- * @hw: pointer to hardware structure
- *
- * Configure general DCB parameters.
- */
-static s32 ixgbe_dcb_config_82599(struct ixgbe_hw *hw)
-{
- u32 reg;
- u32 q;
-
- /* Disable the Tx desc arbiter so that MTQC can be changed */
- reg = IXGBE_READ_REG(hw, IXGBE_RTTDCS);
- reg |= IXGBE_RTTDCS_ARBDIS;
- IXGBE_WRITE_REG(hw, IXGBE_RTTDCS, reg);
-
- /* Enable DCB for Rx with 8 TCs */
- reg = IXGBE_READ_REG(hw, IXGBE_MRQC);
- switch (reg & IXGBE_MRQC_MRQE_MASK) {
- case 0:
- case IXGBE_MRQC_RT4TCEN:
- /* RSS disabled cases */
- reg = (reg & ~IXGBE_MRQC_MRQE_MASK) | IXGBE_MRQC_RT8TCEN;
- break;
- case IXGBE_MRQC_RSSEN:
- case IXGBE_MRQC_RTRSS4TCEN:
- /* RSS enabled cases */
- reg = (reg & ~IXGBE_MRQC_MRQE_MASK) | IXGBE_MRQC_RTRSS8TCEN;
- break;
- default:
- /* Unsupported value, assume stale data, overwrite no RSS */
- reg = (reg & ~IXGBE_MRQC_MRQE_MASK) | IXGBE_MRQC_RT8TCEN;
- }
- IXGBE_WRITE_REG(hw, IXGBE_MRQC, reg);
-
- /* Enable DCB for Tx with 8 TCs */
- reg = IXGBE_MTQC_RT_ENA | IXGBE_MTQC_8TC_8TQ;
- IXGBE_WRITE_REG(hw, IXGBE_MTQC, reg);
-
- /* Disable drop for all queues */
- for (q = 0; q < 128; q++)
- IXGBE_WRITE_REG(hw, IXGBE_QDE, q << IXGBE_QDE_IDX_SHIFT);
-
- /* Enable the Tx desc arbiter */
- reg = IXGBE_READ_REG(hw, IXGBE_RTTDCS);
- reg &= ~IXGBE_RTTDCS_ARBDIS;
- IXGBE_WRITE_REG(hw, IXGBE_RTTDCS, reg);
-
- /* Enable Security TX Buffer IFG for DCB */
- reg = IXGBE_READ_REG(hw, IXGBE_SECTXMINIFG);
- reg |= IXGBE_SECTX_DCB;
- IXGBE_WRITE_REG(hw, IXGBE_SECTXMINIFG, reg);
-
- return 0;
-}
-
-/**
* ixgbe_dcb_hw_config_82599 - Configure and enable DCB
* @hw: pointer to hardware structure
- * @rx_pba: method to distribute packet buffer
* @refill: refill credits index by traffic class
* @max: max credits index by traffic class
* @bwg_id: bandwidth grouping indexed by traffic class
@@ -443,12 +329,9 @@
*
* Configure dcb settings and enable dcb mode.
*/
-s32 ixgbe_dcb_hw_config_82599(struct ixgbe_hw *hw,
- u8 rx_pba, u8 pfc_en, u16 *refill,
+s32 ixgbe_dcb_hw_config_82599(struct ixgbe_hw *hw, u8 pfc_en, u16 *refill,
u16 *max, u8 *bwg_id, u8 *prio_type, u8 *prio_tc)
{
- ixgbe_dcb_config_packet_buffers_82599(hw, rx_pba);
- ixgbe_dcb_config_82599(hw);
ixgbe_dcb_config_rx_arbiter_82599(hw, refill, max, bwg_id,
prio_type, prio_tc);
ixgbe_dcb_config_tx_desc_arbiter_82599(hw, refill, max,
diff --git a/drivers/net/ixgbe/ixgbe_dcb_82599.h b/drivers/net/ixgbe/ixgbe_dcb_82599.h
index 2de71a5..08d1749 100644
--- a/drivers/net/ixgbe/ixgbe_dcb_82599.h
+++ b/drivers/net/ixgbe/ixgbe_dcb_82599.h
@@ -86,17 +86,6 @@
#define IXGBE_RTTPCS_ARBD_SHIFT 22
#define IXGBE_RTTPCS_ARBD_DCB 0x4 /* Arbitration delay in DCB mode */
-#define IXGBE_TXPBSIZE_20KB 0x00005000 /* 20KB Packet Buffer */
-#define IXGBE_TXPBSIZE_40KB 0x0000A000 /* 40KB Packet Buffer */
-#define IXGBE_RXPBSIZE_48KB 0x0000C000 /* 48KB Packet Buffer */
-#define IXGBE_RXPBSIZE_64KB 0x00010000 /* 64KB Packet Buffer */
-#define IXGBE_RXPBSIZE_80KB 0x00014000 /* 80KB Packet Buffer */
-#define IXGBE_RXPBSIZE_128KB 0x00020000 /* 128KB Packet Buffer */
-#define IXGBE_TXPBSIZE_MAX 0x00028000 /* 160KB Packet Buffer*/
-
-#define IXGBE_TXPBTHRESH_DCB 0xA /* THRESH value for DCB mode */
-#define IXGBE_TXPKT_SIZE_MAX 0xA /* Max Tx Packet size */
-
/* SECTXMINIFG DCB */
#define IXGBE_SECTX_DCB 0x00001F00 /* DCB TX Buffer IFG */
@@ -127,8 +116,7 @@
u8 *prio_type,
u8 *prio_tc);
-s32 ixgbe_dcb_hw_config_82599(struct ixgbe_hw *hw,
- u8 rx_pba, u8 pfc_en, u16 *refill,
+s32 ixgbe_dcb_hw_config_82599(struct ixgbe_hw *hw, u8 pfc_en, u16 *refill,
u16 *max, u8 *bwg_id, u8 *prio_type,
u8 *prio_tc);
diff --git a/drivers/net/ixgbe/ixgbe_dcb_nl.c b/drivers/net/ixgbe/ixgbe_dcb_nl.c
index 5e7ed22..0ace6ce 100644
--- a/drivers/net/ixgbe/ixgbe_dcb_nl.c
+++ b/drivers/net/ixgbe/ixgbe_dcb_nl.c
@@ -114,20 +114,19 @@
u8 err = 0;
struct ixgbe_adapter *adapter = netdev_priv(netdev);
+ /* verify there is something to do, if not then exit */
+ if (!!state != !(adapter->flags & IXGBE_FLAG_DCB_ENABLED))
+ return err;
+
if (state > 0) {
/* Turn on DCB */
- if (adapter->flags & IXGBE_FLAG_DCB_ENABLED)
- goto out;
-
if (!(adapter->flags & IXGBE_FLAG_MSIX_ENABLED)) {
e_err(drv, "Enable failed, needs MSI-X\n");
err = 1;
goto out;
}
- if (netif_running(netdev))
- netdev->netdev_ops->ndo_stop(netdev);
- ixgbe_clear_interrupt_scheme(adapter);
+ adapter->flags |= IXGBE_FLAG_DCB_ENABLED;
switch (adapter->hw.mac.type) {
case ixgbe_mac_82598EB:
@@ -137,46 +136,30 @@
case ixgbe_mac_82599EB:
case ixgbe_mac_X540:
adapter->flags &= ~IXGBE_FLAG_FDIR_HASH_CAPABLE;
- adapter->flags &= ~IXGBE_FLAG_FDIR_PERFECT_CAPABLE;
break;
default:
break;
}
- adapter->flags |= IXGBE_FLAG_DCB_ENABLED;
- if (!netdev_get_num_tc(netdev))
- ixgbe_setup_tc(netdev, MAX_TRAFFIC_CLASS);
-
- ixgbe_init_interrupt_scheme(adapter);
- if (netif_running(netdev))
- netdev->netdev_ops->ndo_open(netdev);
+ ixgbe_setup_tc(netdev, MAX_TRAFFIC_CLASS);
} else {
/* Turn off DCB */
- if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) {
- if (netif_running(netdev))
- netdev->netdev_ops->ndo_stop(netdev);
- ixgbe_clear_interrupt_scheme(adapter);
-
- adapter->hw.fc.requested_mode = adapter->last_lfc_mode;
- adapter->temp_dcb_cfg.pfc_mode_enable = false;
- adapter->dcb_cfg.pfc_mode_enable = false;
- adapter->flags &= ~IXGBE_FLAG_DCB_ENABLED;
- switch (adapter->hw.mac.type) {
- case ixgbe_mac_82599EB:
- case ixgbe_mac_X540:
+ adapter->hw.fc.requested_mode = adapter->last_lfc_mode;
+ adapter->temp_dcb_cfg.pfc_mode_enable = false;
+ adapter->dcb_cfg.pfc_mode_enable = false;
+ adapter->flags &= ~IXGBE_FLAG_DCB_ENABLED;
+ switch (adapter->hw.mac.type) {
+ case ixgbe_mac_82599EB:
+ case ixgbe_mac_X540:
+ if (!(adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE))
adapter->flags |= IXGBE_FLAG_FDIR_HASH_CAPABLE;
- break;
- default:
- break;
- }
-
- ixgbe_setup_tc(netdev, 0);
-
- ixgbe_init_interrupt_scheme(adapter);
- if (netif_running(netdev))
- netdev->netdev_ops->ndo_open(netdev);
+ break;
+ default:
+ break;
}
+ ixgbe_setup_tc(netdev, 0);
}
+
out:
return err;
}
@@ -347,24 +330,20 @@
static u8 ixgbe_dcbnl_set_all(struct net_device *netdev)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
+ int ret;
+#ifdef IXGBE_FCOE
struct dcb_app app = {
.selector = DCB_APP_IDTYPE_ETHTYPE,
.protocol = ETH_P_FCOE,
};
u8 up = dcb_getapp(netdev, &app);
- int ret;
+#endif
ret = ixgbe_copy_dcb_cfg(&adapter->temp_dcb_cfg, &adapter->dcb_cfg,
MAX_TRAFFIC_CLASS);
if (ret)
return DCB_NO_HW_CHG;
- /* In IEEE mode app data must be parsed into DCBX format for
- * hardware routines.
- */
- if (adapter->dcbx_cap & DCB_CAP_DCBX_VER_IEEE)
- up = (1 << up);
-
#ifdef IXGBE_FCOE
if (up && (up != (1 << adapter->fcoe.up)))
adapter->dcb_set_bitmap |= BIT_APP_UPCHG;
@@ -378,7 +357,7 @@
while (test_and_set_bit(__IXGBE_RESETTING, &adapter->state))
usleep_range(1000, 2000);
- ixgbe_fcoe_setapp(adapter, up);
+ adapter->fcoe.up = ffs(up) - 1;
if (netif_running(netdev))
netdev->netdev_ops->ndo_stop(netdev);
@@ -691,22 +670,73 @@
return err;
}
+#ifdef IXGBE_FCOE
+static void ixgbe_dcbnl_devreset(struct net_device *dev)
+{
+ struct ixgbe_adapter *adapter = netdev_priv(dev);
+
+ if (netif_running(dev))
+ dev->netdev_ops->ndo_stop(dev);
+
+ ixgbe_clear_interrupt_scheme(adapter);
+ ixgbe_init_interrupt_scheme(adapter);
+
+ if (netif_running(dev))
+ dev->netdev_ops->ndo_open(dev);
+}
+#endif
+
static int ixgbe_dcbnl_ieee_setapp(struct net_device *dev,
struct dcb_app *app)
{
struct ixgbe_adapter *adapter = netdev_priv(dev);
+ int err = -EINVAL;
+
+ if (!(adapter->dcbx_cap & DCB_CAP_DCBX_VER_IEEE))
+ return err;
+
+ err = dcb_ieee_setapp(dev, app);
+
+#ifdef IXGBE_FCOE
+ if (!err && app->selector == IEEE_8021QAZ_APP_SEL_ETHERTYPE &&
+ app->protocol == ETH_P_FCOE) {
+ u8 app_mask = dcb_ieee_getapp_mask(dev, app);
+
+ if (app_mask & (1 << adapter->fcoe.up))
+ return err;
+
+ adapter->fcoe.up = app->priority;
+ ixgbe_dcbnl_devreset(dev);
+ }
+#endif
+ return 0;
+}
+
+static int ixgbe_dcbnl_ieee_delapp(struct net_device *dev,
+ struct dcb_app *app)
+{
+ struct ixgbe_adapter *adapter = netdev_priv(dev);
+ int err;
if (!(adapter->dcbx_cap & DCB_CAP_DCBX_VER_IEEE))
return -EINVAL;
- dcb_setapp(dev, app);
+ err = dcb_ieee_delapp(dev, app);
#ifdef IXGBE_FCOE
- if (app->selector == 1 && app->protocol == ETH_P_FCOE &&
- adapter->fcoe.tc == app->priority)
- ixgbe_dcbnl_set_all(dev);
+ if (!err && app->selector == IEEE_8021QAZ_APP_SEL_ETHERTYPE &&
+ app->protocol == ETH_P_FCOE) {
+ u8 app_mask = dcb_ieee_getapp_mask(dev, app);
+
+ if (app_mask & (1 << adapter->fcoe.up))
+ return err;
+
+ adapter->fcoe.up = app_mask ?
+ ffs(app_mask) - 1 : IXGBE_FCOE_DEFTC;
+ ixgbe_dcbnl_devreset(dev);
+ }
#endif
- return 0;
+ return err;
}
static u8 ixgbe_dcbnl_getdcbx(struct net_device *dev)
@@ -760,6 +790,7 @@
.ieee_getpfc = ixgbe_dcbnl_ieee_getpfc,
.ieee_setpfc = ixgbe_dcbnl_ieee_setpfc,
.ieee_setapp = ixgbe_dcbnl_ieee_setapp,
+ .ieee_delapp = ixgbe_dcbnl_ieee_delapp,
.getstate = ixgbe_dcbnl_get_state,
.setstate = ixgbe_dcbnl_set_state,
.getpermhwaddr = ixgbe_dcbnl_get_perm_hw_addr,
diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c
index cb1555b..074e9ba 100644
--- a/drivers/net/ixgbe/ixgbe_ethtool.c
+++ b/drivers/net/ixgbe/ixgbe_ethtool.c
@@ -27,6 +27,7 @@
/* ethtool support for ixgbe */
+#include <linux/interrupt.h>
#include <linux/types.h>
#include <linux/module.h>
#include <linux/slab.h>
@@ -441,20 +442,67 @@
return 0;
}
+static void ixgbe_do_reset(struct net_device *netdev)
+{
+ struct ixgbe_adapter *adapter = netdev_priv(netdev);
+
+ if (netif_running(netdev))
+ ixgbe_reinit_locked(adapter);
+ else
+ ixgbe_reset(adapter);
+}
+
static u32 ixgbe_get_rx_csum(struct net_device *netdev)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
return adapter->flags & IXGBE_FLAG_RX_CSUM_ENABLED;
}
+static void ixgbe_set_rsc(struct ixgbe_adapter *adapter)
+{
+ int i;
+
+ for (i = 0; i < adapter->num_rx_queues; i++) {
+ struct ixgbe_ring *ring = adapter->rx_ring[i];
+ if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED) {
+ set_ring_rsc_enabled(ring);
+ ixgbe_configure_rscctl(adapter, ring);
+ } else {
+ ixgbe_clear_rscctl(adapter, ring);
+ }
+ }
+}
+
static int ixgbe_set_rx_csum(struct net_device *netdev, u32 data)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
- if (data)
+ bool need_reset = false;
+
+ if (data) {
adapter->flags |= IXGBE_FLAG_RX_CSUM_ENABLED;
- else
+ } else {
adapter->flags &= ~IXGBE_FLAG_RX_CSUM_ENABLED;
+ if (adapter->flags2 & IXGBE_FLAG2_RSC_CAPABLE) {
+ adapter->flags2 &= ~IXGBE_FLAG2_RSC_ENABLED;
+ netdev->features &= ~NETIF_F_LRO;
+ }
+
+ switch (adapter->hw.mac.type) {
+ case ixgbe_mac_X540:
+ ixgbe_set_rsc(adapter);
+ break;
+ case ixgbe_mac_82599EB:
+ need_reset = true;
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (need_reset)
+ ixgbe_do_reset(netdev);
+
return 0;
}
@@ -2233,12 +2281,8 @@
* correctly w.r.t stopping tx, and changing TXDCTL.WTHRESH settings
* also locks in RSC enable/disable which requires reset
*/
- if (need_reset) {
- if (netif_running(netdev))
- ixgbe_reinit_locked(adapter);
- else
- ixgbe_reset(adapter);
- }
+ if (need_reset)
+ ixgbe_do_reset(netdev);
return 0;
}
@@ -2280,25 +2324,12 @@
} else {
adapter->flags2 ^= IXGBE_FLAG2_RSC_ENABLED;
switch (adapter->hw.mac.type) {
+ case ixgbe_mac_X540:
+ ixgbe_set_rsc(adapter);
+ break;
case ixgbe_mac_82599EB:
need_reset = true;
break;
- case ixgbe_mac_X540: {
- int i;
- for (i = 0; i < adapter->num_rx_queues; i++) {
- struct ixgbe_ring *ring =
- adapter->rx_ring[i];
- if (adapter->flags2 &
- IXGBE_FLAG2_RSC_ENABLED) {
- ixgbe_configure_rscctl(adapter,
- ring);
- } else {
- ixgbe_clear_rscctl(adapter,
- ring);
- }
- }
- }
- break;
default:
break;
}
@@ -2309,165 +2340,392 @@
* Check if Flow Director n-tuple support was enabled or disabled. If
* the state changed, we need to reset.
*/
- if ((adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE) &&
- (!(data & ETH_FLAG_NTUPLE))) {
- /* turn off Flow Director perfect, set hash and reset */
+ if (!(adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE)) {
+ /* turn off ATR, enable perfect filters and reset */
+ if (data & ETH_FLAG_NTUPLE) {
+ adapter->flags &= ~IXGBE_FLAG_FDIR_HASH_CAPABLE;
+ adapter->flags |= IXGBE_FLAG_FDIR_PERFECT_CAPABLE;
+ need_reset = true;
+ }
+ } else if (!(data & ETH_FLAG_NTUPLE)) {
+ /* turn off Flow Director, set ATR and reset */
adapter->flags &= ~IXGBE_FLAG_FDIR_PERFECT_CAPABLE;
- adapter->flags |= IXGBE_FLAG_FDIR_HASH_CAPABLE;
+ if ((adapter->flags & IXGBE_FLAG_RSS_ENABLED) &&
+ !(adapter->flags & IXGBE_FLAG_DCB_ENABLED))
+ adapter->flags |= IXGBE_FLAG_FDIR_HASH_CAPABLE;
need_reset = true;
- } else if ((!(adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE)) &&
- (data & ETH_FLAG_NTUPLE)) {
- /* turn off Flow Director hash, enable perfect and reset */
- adapter->flags &= ~IXGBE_FLAG_FDIR_HASH_CAPABLE;
- adapter->flags |= IXGBE_FLAG_FDIR_PERFECT_CAPABLE;
- need_reset = true;
- } else {
- /* no state change */
}
- if (need_reset) {
- if (netif_running(netdev))
- ixgbe_reinit_locked(adapter);
- else
- ixgbe_reset(adapter);
+ if (need_reset)
+ ixgbe_do_reset(netdev);
+
+ return 0;
+}
+
+static int ixgbe_get_ethtool_fdir_entry(struct ixgbe_adapter *adapter,
+ struct ethtool_rxnfc *cmd)
+{
+ union ixgbe_atr_input *mask = &adapter->fdir_mask;
+ struct ethtool_rx_flow_spec *fsp =
+ (struct ethtool_rx_flow_spec *)&cmd->fs;
+ struct hlist_node *node, *node2;
+ struct ixgbe_fdir_filter *rule = NULL;
+
+ /* report total rule count */
+ cmd->data = (1024 << adapter->fdir_pballoc) - 2;
+
+ hlist_for_each_entry_safe(rule, node, node2,
+ &adapter->fdir_filter_list, fdir_node) {
+ if (fsp->location <= rule->sw_idx)
+ break;
+ }
+
+ if (!rule || fsp->location != rule->sw_idx)
+ return -EINVAL;
+
+ /* fill out the flow spec entry */
+
+ /* set flow type field */
+ switch (rule->filter.formatted.flow_type) {
+ case IXGBE_ATR_FLOW_TYPE_TCPV4:
+ fsp->flow_type = TCP_V4_FLOW;
+ break;
+ case IXGBE_ATR_FLOW_TYPE_UDPV4:
+ fsp->flow_type = UDP_V4_FLOW;
+ break;
+ case IXGBE_ATR_FLOW_TYPE_SCTPV4:
+ fsp->flow_type = SCTP_V4_FLOW;
+ break;
+ case IXGBE_ATR_FLOW_TYPE_IPV4:
+ fsp->flow_type = IP_USER_FLOW;
+ fsp->h_u.usr_ip4_spec.ip_ver = ETH_RX_NFC_IP4;
+ fsp->h_u.usr_ip4_spec.proto = 0;
+ fsp->m_u.usr_ip4_spec.proto = 0;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ fsp->h_u.tcp_ip4_spec.psrc = rule->filter.formatted.src_port;
+ fsp->m_u.tcp_ip4_spec.psrc = mask->formatted.src_port;
+ fsp->h_u.tcp_ip4_spec.pdst = rule->filter.formatted.dst_port;
+ fsp->m_u.tcp_ip4_spec.pdst = mask->formatted.dst_port;
+ fsp->h_u.tcp_ip4_spec.ip4src = rule->filter.formatted.src_ip[0];
+ fsp->m_u.tcp_ip4_spec.ip4src = mask->formatted.src_ip[0];
+ fsp->h_u.tcp_ip4_spec.ip4dst = rule->filter.formatted.dst_ip[0];
+ fsp->m_u.tcp_ip4_spec.ip4dst = mask->formatted.dst_ip[0];
+ fsp->h_ext.vlan_tci = rule->filter.formatted.vlan_id;
+ fsp->m_ext.vlan_tci = mask->formatted.vlan_id;
+ fsp->h_ext.vlan_etype = rule->filter.formatted.flex_bytes;
+ fsp->m_ext.vlan_etype = mask->formatted.flex_bytes;
+ fsp->h_ext.data[1] = htonl(rule->filter.formatted.vm_pool);
+ fsp->m_ext.data[1] = htonl(mask->formatted.vm_pool);
+ fsp->flow_type |= FLOW_EXT;
+
+ /* record action */
+ if (rule->action == IXGBE_FDIR_DROP_QUEUE)
+ fsp->ring_cookie = RX_CLS_FLOW_DISC;
+ else
+ fsp->ring_cookie = rule->action;
+
+ return 0;
+}
+
+static int ixgbe_get_ethtool_fdir_all(struct ixgbe_adapter *adapter,
+ struct ethtool_rxnfc *cmd,
+ u32 *rule_locs)
+{
+ struct hlist_node *node, *node2;
+ struct ixgbe_fdir_filter *rule;
+ int cnt = 0;
+
+ /* report total rule count */
+ cmd->data = (1024 << adapter->fdir_pballoc) - 2;
+
+ hlist_for_each_entry_safe(rule, node, node2,
+ &adapter->fdir_filter_list, fdir_node) {
+ if (cnt == cmd->rule_cnt)
+ return -EMSGSIZE;
+ rule_locs[cnt] = rule->sw_idx;
+ cnt++;
}
return 0;
}
-static int ixgbe_set_rx_ntuple(struct net_device *dev,
- struct ethtool_rx_ntuple *cmd)
+static int ixgbe_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd,
+ void *rule_locs)
{
struct ixgbe_adapter *adapter = netdev_priv(dev);
- struct ethtool_rx_ntuple_flow_spec *fs = &cmd->fs;
- union ixgbe_atr_input input_struct;
- struct ixgbe_atr_input_masks input_masks;
- int target_queue;
+ int ret = -EOPNOTSUPP;
+
+ switch (cmd->cmd) {
+ case ETHTOOL_GRXRINGS:
+ cmd->data = adapter->num_rx_queues;
+ ret = 0;
+ break;
+ case ETHTOOL_GRXCLSRLCNT:
+ cmd->rule_cnt = adapter->fdir_filter_count;
+ ret = 0;
+ break;
+ case ETHTOOL_GRXCLSRULE:
+ ret = ixgbe_get_ethtool_fdir_entry(adapter, cmd);
+ break;
+ case ETHTOOL_GRXCLSRLALL:
+ ret = ixgbe_get_ethtool_fdir_all(adapter, cmd,
+ (u32 *)rule_locs);
+ break;
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+static int ixgbe_update_ethtool_fdir_entry(struct ixgbe_adapter *adapter,
+ struct ixgbe_fdir_filter *input,
+ u16 sw_idx)
+{
+ struct ixgbe_hw *hw = &adapter->hw;
+ struct hlist_node *node, *node2, *parent;
+ struct ixgbe_fdir_filter *rule;
+ int err = -EINVAL;
+
+ parent = NULL;
+ rule = NULL;
+
+ hlist_for_each_entry_safe(rule, node, node2,
+ &adapter->fdir_filter_list, fdir_node) {
+ /* hash found, or no matching entry */
+ if (rule->sw_idx >= sw_idx)
+ break;
+ parent = node;
+ }
+
+ /* if there is an old rule occupying our place remove it */
+ if (rule && (rule->sw_idx == sw_idx)) {
+ if (!input || (rule->filter.formatted.bkt_hash !=
+ input->filter.formatted.bkt_hash)) {
+ err = ixgbe_fdir_erase_perfect_filter_82599(hw,
+ &rule->filter,
+ sw_idx);
+ }
+
+ hlist_del(&rule->fdir_node);
+ kfree(rule);
+ adapter->fdir_filter_count--;
+ }
+
+ /*
+ * If no input this was a delete, err should be 0 if a rule was
+ * successfully found and removed from the list else -EINVAL
+ */
+ if (!input)
+ return err;
+
+ /* initialize node and set software index */
+ INIT_HLIST_NODE(&input->fdir_node);
+
+ /* add filter to the list */
+ if (parent)
+ hlist_add_after(parent, &input->fdir_node);
+ else
+ hlist_add_head(&input->fdir_node,
+ &adapter->fdir_filter_list);
+
+ /* update counts */
+ adapter->fdir_filter_count++;
+
+ return 0;
+}
+
+static int ixgbe_flowspec_to_flow_type(struct ethtool_rx_flow_spec *fsp,
+ u8 *flow_type)
+{
+ switch (fsp->flow_type & ~FLOW_EXT) {
+ case TCP_V4_FLOW:
+ *flow_type = IXGBE_ATR_FLOW_TYPE_TCPV4;
+ break;
+ case UDP_V4_FLOW:
+ *flow_type = IXGBE_ATR_FLOW_TYPE_UDPV4;
+ break;
+ case SCTP_V4_FLOW:
+ *flow_type = IXGBE_ATR_FLOW_TYPE_SCTPV4;
+ break;
+ case IP_USER_FLOW:
+ switch (fsp->h_u.usr_ip4_spec.proto) {
+ case IPPROTO_TCP:
+ *flow_type = IXGBE_ATR_FLOW_TYPE_TCPV4;
+ break;
+ case IPPROTO_UDP:
+ *flow_type = IXGBE_ATR_FLOW_TYPE_UDPV4;
+ break;
+ case IPPROTO_SCTP:
+ *flow_type = IXGBE_ATR_FLOW_TYPE_SCTPV4;
+ break;
+ case 0:
+ if (!fsp->m_u.usr_ip4_spec.proto) {
+ *flow_type = IXGBE_ATR_FLOW_TYPE_IPV4;
+ break;
+ }
+ default:
+ return 0;
+ }
+ break;
+ default:
+ return 0;
+ }
+
+ return 1;
+}
+
+static int ixgbe_add_ethtool_fdir_entry(struct ixgbe_adapter *adapter,
+ struct ethtool_rxnfc *cmd)
+{
+ struct ethtool_rx_flow_spec *fsp =
+ (struct ethtool_rx_flow_spec *)&cmd->fs;
+ struct ixgbe_hw *hw = &adapter->hw;
+ struct ixgbe_fdir_filter *input;
+ union ixgbe_atr_input mask;
int err;
- if (adapter->hw.mac.type == ixgbe_mac_82598EB)
+ if (!(adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE))
return -EOPNOTSUPP;
/*
* Don't allow programming if the action is a queue greater than
- * the number of online Tx queues.
+ * the number of online Rx queues.
*/
- if ((fs->action >= adapter->num_tx_queues) ||
- (fs->action < ETHTOOL_RXNTUPLE_ACTION_DROP))
+ if ((fsp->ring_cookie != RX_CLS_FLOW_DISC) &&
+ (fsp->ring_cookie >= adapter->num_rx_queues))
return -EINVAL;
- memset(&input_struct, 0, sizeof(union ixgbe_atr_input));
- memset(&input_masks, 0, sizeof(struct ixgbe_atr_input_masks));
+ /* Don't allow indexes to exist outside of available space */
+ if (fsp->location >= ((1024 << adapter->fdir_pballoc) - 2)) {
+ e_err(drv, "Location out of range\n");
+ return -EINVAL;
+ }
+
+ input = kzalloc(sizeof(*input), GFP_ATOMIC);
+ if (!input)
+ return -ENOMEM;
+
+ memset(&mask, 0, sizeof(union ixgbe_atr_input));
+
+ /* set SW index */
+ input->sw_idx = fsp->location;
/* record flow type */
- switch (fs->flow_type) {
- case IPV4_FLOW:
- input_struct.formatted.flow_type = IXGBE_ATR_FLOW_TYPE_IPV4;
- break;
- case TCP_V4_FLOW:
- input_struct.formatted.flow_type = IXGBE_ATR_FLOW_TYPE_TCPV4;
- break;
- case UDP_V4_FLOW:
- input_struct.formatted.flow_type = IXGBE_ATR_FLOW_TYPE_UDPV4;
- break;
- case SCTP_V4_FLOW:
- input_struct.formatted.flow_type = IXGBE_ATR_FLOW_TYPE_SCTPV4;
- break;
- default:
- return -1;
+ if (!ixgbe_flowspec_to_flow_type(fsp,
+ &input->filter.formatted.flow_type)) {
+ e_err(drv, "Unrecognized flow type\n");
+ goto err_out;
}
- /* copy vlan tag minus the CFI bit */
- if ((fs->vlan_tag & 0xEFFF) || (~fs->vlan_tag_mask & 0xEFFF)) {
- input_struct.formatted.vlan_id = htons(fs->vlan_tag & 0xEFFF);
- if (!fs->vlan_tag_mask) {
- input_masks.vlan_id_mask = htons(0xEFFF);
- } else {
- switch (~fs->vlan_tag_mask & 0xEFFF) {
- /* all of these are valid vlan-mask values */
- case 0xEFFF:
- case 0xE000:
- case 0x0FFF:
- case 0x0000:
- input_masks.vlan_id_mask =
- htons(~fs->vlan_tag_mask);
- break;
- /* exit with error if vlan-mask is invalid */
- default:
- e_err(drv, "Partial VLAN ID or "
- "priority mask in vlan-mask is not "
- "supported by hardware\n");
- return -1;
- }
- }
- }
+ mask.formatted.flow_type = IXGBE_ATR_L4TYPE_IPV6_MASK |
+ IXGBE_ATR_L4TYPE_MASK;
- /* make sure we only use the first 2 bytes of user data */
- if ((fs->data & 0xFFFF) || (~fs->data_mask & 0xFFFF)) {
- input_struct.formatted.flex_bytes = htons(fs->data & 0xFFFF);
- if (!(fs->data_mask & 0xFFFF)) {
- input_masks.flex_mask = 0xFFFF;
- } else if (~fs->data_mask & 0xFFFF) {
- e_err(drv, "Partial user-def-mask is not "
- "supported by hardware\n");
- return -1;
- }
- }
+ if (input->filter.formatted.flow_type == IXGBE_ATR_FLOW_TYPE_IPV4)
+ mask.formatted.flow_type &= IXGBE_ATR_L4TYPE_IPV6_MASK;
- /*
- * Copy input into formatted structures
- *
- * These assignments are based on the following logic
- * If neither input or mask are set assume value is masked out.
- * If input is set, but mask is not mask should default to accept all.
- * If input is not set, but mask is set then mask likely results in 0.
- * If input is set and mask is set then assign both.
- */
- if (fs->h_u.tcp_ip4_spec.ip4src || ~fs->m_u.tcp_ip4_spec.ip4src) {
- input_struct.formatted.src_ip[0] = fs->h_u.tcp_ip4_spec.ip4src;
- if (!fs->m_u.tcp_ip4_spec.ip4src)
- input_masks.src_ip_mask[0] = 0xFFFFFFFF;
- else
- input_masks.src_ip_mask[0] =
- ~fs->m_u.tcp_ip4_spec.ip4src;
- }
- if (fs->h_u.tcp_ip4_spec.ip4dst || ~fs->m_u.tcp_ip4_spec.ip4dst) {
- input_struct.formatted.dst_ip[0] = fs->h_u.tcp_ip4_spec.ip4dst;
- if (!fs->m_u.tcp_ip4_spec.ip4dst)
- input_masks.dst_ip_mask[0] = 0xFFFFFFFF;
- else
- input_masks.dst_ip_mask[0] =
- ~fs->m_u.tcp_ip4_spec.ip4dst;
- }
- if (fs->h_u.tcp_ip4_spec.psrc || ~fs->m_u.tcp_ip4_spec.psrc) {
- input_struct.formatted.src_port = fs->h_u.tcp_ip4_spec.psrc;
- if (!fs->m_u.tcp_ip4_spec.psrc)
- input_masks.src_port_mask = 0xFFFF;
- else
- input_masks.src_port_mask = ~fs->m_u.tcp_ip4_spec.psrc;
- }
- if (fs->h_u.tcp_ip4_spec.pdst || ~fs->m_u.tcp_ip4_spec.pdst) {
- input_struct.formatted.dst_port = fs->h_u.tcp_ip4_spec.pdst;
- if (!fs->m_u.tcp_ip4_spec.pdst)
- input_masks.dst_port_mask = 0xFFFF;
- else
- input_masks.dst_port_mask = ~fs->m_u.tcp_ip4_spec.pdst;
+ /* Copy input into formatted structures */
+ input->filter.formatted.src_ip[0] = fsp->h_u.tcp_ip4_spec.ip4src;
+ mask.formatted.src_ip[0] = fsp->m_u.tcp_ip4_spec.ip4src;
+ input->filter.formatted.dst_ip[0] = fsp->h_u.tcp_ip4_spec.ip4dst;
+ mask.formatted.dst_ip[0] = fsp->m_u.tcp_ip4_spec.ip4dst;
+ input->filter.formatted.src_port = fsp->h_u.tcp_ip4_spec.psrc;
+ mask.formatted.src_port = fsp->m_u.tcp_ip4_spec.psrc;
+ input->filter.formatted.dst_port = fsp->h_u.tcp_ip4_spec.pdst;
+ mask.formatted.dst_port = fsp->m_u.tcp_ip4_spec.pdst;
+
+ if (fsp->flow_type & FLOW_EXT) {
+ input->filter.formatted.vm_pool =
+ (unsigned char)ntohl(fsp->h_ext.data[1]);
+ mask.formatted.vm_pool =
+ (unsigned char)ntohl(fsp->m_ext.data[1]);
+ input->filter.formatted.vlan_id = fsp->h_ext.vlan_tci;
+ mask.formatted.vlan_id = fsp->m_ext.vlan_tci;
+ input->filter.formatted.flex_bytes =
+ fsp->h_ext.vlan_etype;
+ mask.formatted.flex_bytes = fsp->m_ext.vlan_etype;
}
/* determine if we need to drop or route the packet */
- if (fs->action == ETHTOOL_RXNTUPLE_ACTION_DROP)
- target_queue = MAX_RX_QUEUES - 1;
+ if (fsp->ring_cookie == RX_CLS_FLOW_DISC)
+ input->action = IXGBE_FDIR_DROP_QUEUE;
else
- target_queue = fs->action;
+ input->action = fsp->ring_cookie;
spin_lock(&adapter->fdir_perfect_lock);
- err = ixgbe_fdir_add_perfect_filter_82599(&adapter->hw,
- &input_struct,
- &input_masks, 0,
- target_queue);
+
+ if (hlist_empty(&adapter->fdir_filter_list)) {
+ /* save mask and program input mask into HW */
+ memcpy(&adapter->fdir_mask, &mask, sizeof(mask));
+ err = ixgbe_fdir_set_input_mask_82599(hw, &mask);
+ if (err) {
+ e_err(drv, "Error writing mask\n");
+ goto err_out_w_lock;
+ }
+ } else if (memcmp(&adapter->fdir_mask, &mask, sizeof(mask))) {
+ e_err(drv, "Only one mask supported per port\n");
+ goto err_out_w_lock;
+ }
+
+ /* apply mask and compute/store hash */
+ ixgbe_atr_compute_perfect_hash_82599(&input->filter, &mask);
+
+ /* program filters to filter memory */
+ err = ixgbe_fdir_write_perfect_filter_82599(hw,
+ &input->filter, input->sw_idx,
+ (input->action == IXGBE_FDIR_DROP_QUEUE) ?
+ IXGBE_FDIR_DROP_QUEUE :
+ adapter->rx_ring[input->action]->reg_idx);
+ if (err)
+ goto err_out_w_lock;
+
+ ixgbe_update_ethtool_fdir_entry(adapter, input, input->sw_idx);
+
spin_unlock(&adapter->fdir_perfect_lock);
- return err ? -1 : 0;
+ return err;
+err_out_w_lock:
+ spin_unlock(&adapter->fdir_perfect_lock);
+err_out:
+ kfree(input);
+ return -EINVAL;
+}
+
+static int ixgbe_del_ethtool_fdir_entry(struct ixgbe_adapter *adapter,
+ struct ethtool_rxnfc *cmd)
+{
+ struct ethtool_rx_flow_spec *fsp =
+ (struct ethtool_rx_flow_spec *)&cmd->fs;
+ int err;
+
+ spin_lock(&adapter->fdir_perfect_lock);
+ err = ixgbe_update_ethtool_fdir_entry(adapter, NULL, fsp->location);
+ spin_unlock(&adapter->fdir_perfect_lock);
+
+ return err;
+}
+
+static int ixgbe_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd)
+{
+ struct ixgbe_adapter *adapter = netdev_priv(dev);
+ int ret = -EOPNOTSUPP;
+
+ switch (cmd->cmd) {
+ case ETHTOOL_SRXCLSRLINS:
+ ret = ixgbe_add_ethtool_fdir_entry(adapter, cmd);
+ break;
+ case ETHTOOL_SRXCLSRLDEL:
+ ret = ixgbe_del_ethtool_fdir_entry(adapter, cmd);
+ break;
+ default:
+ break;
+ }
+
+ return ret;
}
static const struct ethtool_ops ixgbe_ethtool_ops = {
@@ -2505,7 +2763,8 @@
.set_coalesce = ixgbe_set_coalesce,
.get_flags = ethtool_op_get_flags,
.set_flags = ixgbe_set_flags,
- .set_rx_ntuple = ixgbe_set_rx_ntuple,
+ .get_rxnfc = ixgbe_get_rxnfc,
+ .set_rxnfc = ixgbe_set_rxnfc,
};
void ixgbe_set_ethtool_ops(struct net_device *netdev)
diff --git a/drivers/net/ixgbe/ixgbe_fcoe.c b/drivers/net/ixgbe/ixgbe_fcoe.c
index 0592072..f0c1018 100644
--- a/drivers/net/ixgbe/ixgbe_fcoe.c
+++ b/drivers/net/ixgbe/ixgbe_fcoe.c
@@ -26,9 +26,6 @@
*******************************************************************************/
#include "ixgbe.h"
-#ifdef CONFIG_IXGBE_DCB
-#include "ixgbe_dcb_82599.h"
-#endif /* CONFIG_IXGBE_DCB */
#include <linux/if_ether.h>
#include <linux/gfp.h>
#include <linux/if_vlan.h>
@@ -128,7 +125,11 @@
if (ddp->sgl)
pci_unmap_sg(adapter->pdev, ddp->sgl, ddp->sgc,
DMA_FROM_DEVICE);
- pci_pool_free(fcoe->pool, ddp->udl, ddp->udp);
+ if (ddp->pool) {
+ pci_pool_free(ddp->pool, ddp->udl, ddp->udp);
+ ddp->pool = NULL;
+ }
+
ixgbe_fcoe_clear_ddp(ddp);
out_ddp_put:
@@ -163,6 +164,7 @@
unsigned int thislen = 0;
u32 fcbuff, fcdmarw, fcfltrw, fcrxctl;
dma_addr_t addr = 0;
+ struct pci_pool *pool;
if (!netdev || !sgl)
return 0;
@@ -199,12 +201,14 @@
return 0;
}
- /* alloc the udl from our ddp pool */
- ddp->udl = pci_pool_alloc(fcoe->pool, GFP_ATOMIC, &ddp->udp);
+ /* alloc the udl from per cpu ddp pool */
+ pool = *per_cpu_ptr(fcoe->pool, get_cpu());
+ ddp->udl = pci_pool_alloc(pool, GFP_ATOMIC, &ddp->udp);
if (!ddp->udl) {
e_err(drv, "failed allocated ddp context\n");
goto out_noddp_unmap;
}
+ ddp->pool = pool;
ddp->sgl = sgl;
ddp->sgc = sgc;
@@ -268,6 +272,7 @@
j++;
lastsize = 1;
}
+ put_cpu();
fcbuff = (IXGBE_FCBUFF_4KB << IXGBE_FCBUFF_BUFFSIZE_SHIFT);
fcbuff |= ((j & 0xff) << IXGBE_FCBUFF_BUFFCNT_SHIFT);
@@ -311,11 +316,12 @@
return 1;
out_noddp_free:
- pci_pool_free(fcoe->pool, ddp->udl, ddp->udp);
+ pci_pool_free(pool, ddp->udl, ddp->udp);
ixgbe_fcoe_clear_ddp(ddp);
out_noddp_unmap:
pci_unmap_sg(adapter->pdev, sgl, sgc, DMA_FROM_DEVICE);
+ put_cpu();
return 0;
}
@@ -465,24 +471,18 @@
*
* Returns : 0 indicates no FSO, > 0 for FSO, < 0 for error
*/
-int ixgbe_fso(struct ixgbe_adapter *adapter,
- struct ixgbe_ring *tx_ring, struct sk_buff *skb,
+int ixgbe_fso(struct ixgbe_ring *tx_ring, struct sk_buff *skb,
u32 tx_flags, u8 *hdr_len)
{
- u8 sof, eof;
- u32 vlan_macip_lens;
- u32 fcoe_sof_eof;
- u32 type_tucmd;
- u32 mss_l4len_idx;
- int mss = 0;
- unsigned int i;
- struct ixgbe_tx_buffer *tx_buffer_info;
- struct ixgbe_adv_tx_context_desc *context_desc;
struct fc_frame_header *fh;
+ u32 vlan_macip_lens;
+ u32 fcoe_sof_eof = 0;
+ u32 mss_l4len_idx;
+ u8 sof, eof;
if (skb_is_gso(skb) && (skb_shinfo(skb)->gso_type != SKB_GSO_FCOE)) {
- e_err(drv, "Wrong gso type %d:expecting SKB_GSO_FCOE\n",
- skb_shinfo(skb)->gso_type);
+ dev_err(tx_ring->dev, "Wrong gso type %d:expecting SKB_GSO_FCOE\n",
+ skb_shinfo(skb)->gso_type);
return -EINVAL;
}
@@ -492,23 +492,22 @@
sizeof(struct fcoe_hdr));
/* sets up SOF and ORIS */
- fcoe_sof_eof = 0;
sof = ((struct fcoe_hdr *)skb_network_header(skb))->fcoe_sof;
switch (sof) {
case FC_SOF_I2:
- fcoe_sof_eof |= IXGBE_ADVTXD_FCOEF_ORIS;
+ fcoe_sof_eof = IXGBE_ADVTXD_FCOEF_ORIS;
break;
case FC_SOF_I3:
- fcoe_sof_eof |= IXGBE_ADVTXD_FCOEF_SOF;
- fcoe_sof_eof |= IXGBE_ADVTXD_FCOEF_ORIS;
+ fcoe_sof_eof = IXGBE_ADVTXD_FCOEF_SOF |
+ IXGBE_ADVTXD_FCOEF_ORIS;
break;
case FC_SOF_N2:
break;
case FC_SOF_N3:
- fcoe_sof_eof |= IXGBE_ADVTXD_FCOEF_SOF;
+ fcoe_sof_eof = IXGBE_ADVTXD_FCOEF_SOF;
break;
default:
- e_warn(drv, "unknown sof = 0x%x\n", sof);
+ dev_warn(tx_ring->dev, "unknown sof = 0x%x\n", sof);
return -EINVAL;
}
@@ -521,12 +520,11 @@
break;
case FC_EOF_T:
/* lso needs ORIE */
- if (skb_is_gso(skb)) {
- fcoe_sof_eof |= IXGBE_ADVTXD_FCOEF_EOF_N;
- fcoe_sof_eof |= IXGBE_ADVTXD_FCOEF_ORIE;
- } else {
+ if (skb_is_gso(skb))
+ fcoe_sof_eof |= IXGBE_ADVTXD_FCOEF_EOF_N |
+ IXGBE_ADVTXD_FCOEF_ORIE;
+ else
fcoe_sof_eof |= IXGBE_ADVTXD_FCOEF_EOF_T;
- }
break;
case FC_EOF_NI:
fcoe_sof_eof |= IXGBE_ADVTXD_FCOEF_EOF_NI;
@@ -535,7 +533,7 @@
fcoe_sof_eof |= IXGBE_ADVTXD_FCOEF_EOF_A;
break;
default:
- e_warn(drv, "unknown eof = 0x%x\n", eof);
+ dev_warn(tx_ring->dev, "unknown eof = 0x%x\n", eof);
return -EINVAL;
}
@@ -544,47 +542,72 @@
if (fh->fh_f_ctl[2] & FC_FC_REL_OFF)
fcoe_sof_eof |= IXGBE_ADVTXD_FCOEF_PARINC;
- /* hdr_len includes fc_hdr if FCoE lso is enabled */
+ /* include trailer in headlen as it is replicated per frame */
*hdr_len = sizeof(struct fcoe_crc_eof);
+
+ /* hdr_len includes fc_hdr if FCoE LSO is enabled */
if (skb_is_gso(skb))
*hdr_len += (skb_transport_offset(skb) +
sizeof(struct fc_frame_header));
- /* vlan_macip_lens: HEADLEN, MACLEN, VLAN tag */
- vlan_macip_lens = (skb_transport_offset(skb) +
- sizeof(struct fc_frame_header));
- vlan_macip_lens |= ((skb_transport_offset(skb) - 4)
- << IXGBE_ADVTXD_MACLEN_SHIFT);
- vlan_macip_lens |= (tx_flags & IXGBE_TX_FLAGS_VLAN_MASK);
- /* type_tycmd and mss: set TUCMD.FCoE to enable offload */
- type_tucmd = IXGBE_TXD_CMD_DEXT | IXGBE_ADVTXD_DTYP_CTXT |
- IXGBE_ADVTXT_TUCMD_FCOE;
- if (skb_is_gso(skb))
- mss = skb_shinfo(skb)->gso_size;
/* mss_l4len_id: use 1 for FSO as TSO, no need for L4LEN */
- mss_l4len_idx = (mss << IXGBE_ADVTXD_MSS_SHIFT) |
- (1 << IXGBE_ADVTXD_IDX_SHIFT);
+ mss_l4len_idx = skb_shinfo(skb)->gso_size << IXGBE_ADVTXD_MSS_SHIFT;
+ mss_l4len_idx |= 1 << IXGBE_ADVTXD_IDX_SHIFT;
+
+ /* vlan_macip_lens: HEADLEN, MACLEN, VLAN tag */
+ vlan_macip_lens = skb_transport_offset(skb) +
+ sizeof(struct fc_frame_header);
+ vlan_macip_lens |= (skb_transport_offset(skb) - 4)
+ << IXGBE_ADVTXD_MACLEN_SHIFT;
+ vlan_macip_lens |= tx_flags & IXGBE_TX_FLAGS_VLAN_MASK;
/* write context desc */
- i = tx_ring->next_to_use;
- context_desc = IXGBE_TX_CTXTDESC_ADV(tx_ring, i);
- context_desc->vlan_macip_lens = cpu_to_le32(vlan_macip_lens);
- context_desc->seqnum_seed = cpu_to_le32(fcoe_sof_eof);
- context_desc->type_tucmd_mlhl = cpu_to_le32(type_tucmd);
- context_desc->mss_l4len_idx = cpu_to_le32(mss_l4len_idx);
-
- tx_buffer_info = &tx_ring->tx_buffer_info[i];
- tx_buffer_info->time_stamp = jiffies;
- tx_buffer_info->next_to_watch = i;
-
- i++;
- if (i == tx_ring->count)
- i = 0;
- tx_ring->next_to_use = i;
+ ixgbe_tx_ctxtdesc(tx_ring, vlan_macip_lens, fcoe_sof_eof,
+ IXGBE_ADVTXT_TUCMD_FCOE, mss_l4len_idx);
return skb_is_gso(skb);
}
+static void ixgbe_fcoe_ddp_pools_free(struct ixgbe_fcoe *fcoe)
+{
+ unsigned int cpu;
+ struct pci_pool **pool;
+
+ for_each_possible_cpu(cpu) {
+ pool = per_cpu_ptr(fcoe->pool, cpu);
+ if (*pool)
+ pci_pool_destroy(*pool);
+ }
+ free_percpu(fcoe->pool);
+ fcoe->pool = NULL;
+}
+
+static void ixgbe_fcoe_ddp_pools_alloc(struct ixgbe_adapter *adapter)
+{
+ struct ixgbe_fcoe *fcoe = &adapter->fcoe;
+ unsigned int cpu;
+ struct pci_pool **pool;
+ char pool_name[32];
+
+ fcoe->pool = alloc_percpu(struct pci_pool *);
+ if (!fcoe->pool)
+ return;
+
+ /* allocate pci pool for each cpu */
+ for_each_possible_cpu(cpu) {
+ snprintf(pool_name, 32, "ixgbe_fcoe_ddp_%d", cpu);
+ pool = per_cpu_ptr(fcoe->pool, cpu);
+ *pool = pci_pool_create(pool_name,
+ adapter->pdev, IXGBE_FCPTR_MAX,
+ IXGBE_FCPTR_ALIGN, PAGE_SIZE);
+ if (!*pool) {
+ e_err(drv, "failed to alloc DDP pool on cpu:%d\n", cpu);
+ ixgbe_fcoe_ddp_pools_free(fcoe);
+ return;
+ }
+ }
+}
+
/**
* ixgbe_configure_fcoe - configures registers for fcoe at start
* @adapter: ptr to ixgbe adapter
@@ -599,27 +622,21 @@
struct ixgbe_hw *hw = &adapter->hw;
struct ixgbe_fcoe *fcoe = &adapter->fcoe;
struct ixgbe_ring_feature *f = &adapter->ring_feature[RING_F_FCOE];
-#ifdef CONFIG_IXGBE_DCB
- u8 tc;
- u32 up2tc;
-#endif
- /* create the pool for ddp if not created yet */
if (!fcoe->pool) {
- /* allocate ddp pool */
- fcoe->pool = pci_pool_create("ixgbe_fcoe_ddp",
- adapter->pdev, IXGBE_FCPTR_MAX,
- IXGBE_FCPTR_ALIGN, PAGE_SIZE);
- if (!fcoe->pool)
- e_err(drv, "failed to allocated FCoE DDP pool\n");
-
spin_lock_init(&fcoe->lock);
+ ixgbe_fcoe_ddp_pools_alloc(adapter);
+ if (!fcoe->pool) {
+ e_err(drv, "failed to alloc percpu fcoe DDP pools\n");
+ return;
+ }
+
/* Extra buffer to be shared by all DDPs for HW work around */
fcoe->extra_ddp_buffer = kmalloc(IXGBE_FCBUFF_MIN, GFP_ATOMIC);
if (fcoe->extra_ddp_buffer == NULL) {
e_err(drv, "failed to allocated extra DDP buffer\n");
- goto out_extra_ddp_buffer_alloc;
+ goto out_ddp_pools;
}
fcoe->extra_ddp_buffer_dma =
@@ -630,7 +647,7 @@
if (dma_mapping_error(&adapter->pdev->dev,
fcoe->extra_ddp_buffer_dma)) {
e_err(drv, "failed to map extra DDP buffer\n");
- goto out_extra_ddp_buffer_dma;
+ goto out_extra_ddp_buffer;
}
}
@@ -670,25 +687,12 @@
IXGBE_FCRXCTRL_FCOELLI |
IXGBE_FCRXCTRL_FCCRCBO |
(FC_FCOE_VER << IXGBE_FCRXCTRL_FCOEVER_SHIFT));
-#ifdef CONFIG_IXGBE_DCB
- up2tc = IXGBE_READ_REG(&adapter->hw, IXGBE_RTTUP2TC);
- for (i = 0; i < MAX_USER_PRIORITY; i++) {
- tc = (u8)(up2tc >> (i * IXGBE_RTTUP2TC_UP_SHIFT));
- tc &= (MAX_TRAFFIC_CLASS - 1);
- if (fcoe->tc == tc) {
- fcoe->up = i;
- break;
- }
- }
-#endif
-
return;
-out_extra_ddp_buffer_dma:
+out_extra_ddp_buffer:
kfree(fcoe->extra_ddp_buffer);
-out_extra_ddp_buffer_alloc:
- pci_pool_destroy(fcoe->pool);
- fcoe->pool = NULL;
+out_ddp_pools:
+ ixgbe_fcoe_ddp_pools_free(fcoe);
}
/**
@@ -704,18 +708,17 @@
int i;
struct ixgbe_fcoe *fcoe = &adapter->fcoe;
- /* release ddp resource */
- if (fcoe->pool) {
- for (i = 0; i < IXGBE_FCOE_DDP_MAX; i++)
- ixgbe_fcoe_ddp_put(adapter->netdev, i);
- dma_unmap_single(&adapter->pdev->dev,
- fcoe->extra_ddp_buffer_dma,
- IXGBE_FCBUFF_MIN,
- DMA_FROM_DEVICE);
- kfree(fcoe->extra_ddp_buffer);
- pci_pool_destroy(fcoe->pool);
- fcoe->pool = NULL;
- }
+ if (!fcoe->pool)
+ return;
+
+ for (i = 0; i < IXGBE_FCOE_DDP_MAX; i++)
+ ixgbe_fcoe_ddp_put(adapter->netdev, i);
+ dma_unmap_single(&adapter->pdev->dev,
+ fcoe->extra_ddp_buffer_dma,
+ IXGBE_FCBUFF_MIN,
+ DMA_FROM_DEVICE);
+ kfree(fcoe->extra_ddp_buffer);
+ ixgbe_fcoe_ddp_pools_free(fcoe);
}
/**
@@ -811,41 +814,6 @@
return rc;
}
-#ifdef CONFIG_IXGBE_DCB
-/**
- * ixgbe_fcoe_setapp - sets the user priority bitmap for FCoE
- * @adapter : ixgbe adapter
- * @up : 802.1p user priority bitmap
- *
- * Finds out the traffic class from the input user priority
- * bitmap for FCoE.
- *
- * Returns : 0 on success otherwise returns 1 on error
- */
-u8 ixgbe_fcoe_setapp(struct ixgbe_adapter *adapter, u8 up)
-{
- int i;
- u32 up2tc;
-
- /* valid user priority bitmap must not be 0 */
- if (up) {
- /* from user priority to the corresponding traffic class */
- up2tc = IXGBE_READ_REG(&adapter->hw, IXGBE_RTTUP2TC);
- for (i = 0; i < MAX_USER_PRIORITY; i++) {
- if (up & (1 << i)) {
- up2tc >>= (i * IXGBE_RTTUP2TC_UP_SHIFT);
- up2tc &= (MAX_TRAFFIC_CLASS - 1);
- adapter->fcoe.tc = (u8)up2tc;
- adapter->fcoe.up = i;
- return 0;
- }
- }
- }
-
- return 1;
-}
-#endif /* CONFIG_IXGBE_DCB */
-
/**
* ixgbe_fcoe_get_wwn - get world wide name for the node or the port
* @netdev : ixgbe adapter
diff --git a/drivers/net/ixgbe/ixgbe_fcoe.h b/drivers/net/ixgbe/ixgbe_fcoe.h
index 5a650a4..99de145 100644
--- a/drivers/net/ixgbe/ixgbe_fcoe.h
+++ b/drivers/net/ixgbe/ixgbe_fcoe.h
@@ -62,20 +62,20 @@
struct scatterlist *sgl;
dma_addr_t udp;
u64 *udl;
+ struct pci_pool *pool;
};
struct ixgbe_fcoe {
-#ifdef CONFIG_IXGBE_DCB
- u8 tc;
- u8 up;
-#endif
- unsigned long mode;
+ struct pci_pool **pool;
atomic_t refcnt;
spinlock_t lock;
- struct pci_pool *pool;
struct ixgbe_fcoe_ddp ddp[IXGBE_FCOE_DDP_MAX];
unsigned char *extra_ddp_buffer;
dma_addr_t extra_ddp_buffer_dma;
+ unsigned long mode;
+#ifdef CONFIG_IXGBE_DCB
+ u8 up;
+#endif
};
#endif /* _IXGBE_FCOE_H */
diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c
index 08e8e25..fa671ae 100644
--- a/drivers/net/ixgbe/ixgbe_main.c
+++ b/drivers/net/ixgbe/ixgbe_main.c
@@ -32,8 +32,10 @@
#include <linux/vmalloc.h>
#include <linux/string.h>
#include <linux/in.h>
+#include <linux/interrupt.h>
#include <linux/ip.h>
#include <linux/tcp.h>
+#include <linux/sctp.h>
#include <linux/pkt_sched.h>
#include <linux/ipv6.h>
#include <linux/slab.h>
@@ -53,11 +55,10 @@
static const char ixgbe_driver_string[] =
"Intel(R) 10 Gigabit PCI Express Network Driver";
#define MAJ 3
-#define MIN 3
+#define MIN 4
#define BUILD 8
-#define KFIX 2
#define DRV_VERSION __stringify(MAJ) "." __stringify(MIN) "." \
- __stringify(BUILD) "-k" __stringify(KFIX)
+ __stringify(BUILD) "-k"
const char ixgbe_driver_version[] = DRV_VERSION;
static const char ixgbe_copyright[] =
"Copyright (c) 1999-2011 Intel Corporation.";
@@ -664,62 +665,6 @@
/* tx_buffer_info must be completely set up in the transmit path */
}
-/**
- * ixgbe_dcb_txq_to_tc - convert a reg index to a traffic class
- * @adapter: driver private struct
- * @index: reg idx of queue to query (0-127)
- *
- * Helper function to determine the traffic index for a particular
- * register index.
- *
- * Returns : a tc index for use in range 0-7, or 0-3
- */
-static u8 ixgbe_dcb_txq_to_tc(struct ixgbe_adapter *adapter, u8 reg_idx)
-{
- int tc = -1;
- int dcb_i = netdev_get_num_tc(adapter->netdev);
-
- /* if DCB is not enabled the queues have no TC */
- if (!(adapter->flags & IXGBE_FLAG_DCB_ENABLED))
- return tc;
-
- /* check valid range */
- if (reg_idx >= adapter->hw.mac.max_tx_queues)
- return tc;
-
- switch (adapter->hw.mac.type) {
- case ixgbe_mac_82598EB:
- tc = reg_idx >> 2;
- break;
- default:
- if (dcb_i != 4 && dcb_i != 8)
- break;
-
- /* if VMDq is enabled the lowest order bits determine TC */
- if (adapter->flags & (IXGBE_FLAG_SRIOV_ENABLED |
- IXGBE_FLAG_VMDQ_ENABLED)) {
- tc = reg_idx & (dcb_i - 1);
- break;
- }
-
- /*
- * Convert the reg_idx into the correct TC. This bitmask
- * targets the last full 32 ring traffic class and assigns
- * it a value of 1. From there the rest of the rings are
- * based on shifting the mask further up to include the
- * reg_idx / 16 and then reg_idx / 8. It assumes dcB_i
- * will only ever be 8 or 4 and that reg_idx will never
- * be greater then 128. The code without the power of 2
- * optimizations would be:
- * (((reg_idx % 32) + 32) * dcb_i) >> (9 - reg_idx / 32)
- */
- tc = ((reg_idx & 0X1F) + 0x20) * dcb_i;
- tc >>= 9 - (reg_idx >> 5);
- }
-
- return tc;
-}
-
static void ixgbe_update_xoff_received(struct ixgbe_adapter *adapter)
{
struct ixgbe_hw *hw = &adapter->hw;
@@ -765,7 +710,7 @@
/* disarm tx queues that have received xoff frames */
for (i = 0; i < adapter->num_tx_queues; i++) {
struct ixgbe_ring *tx_ring = adapter->tx_ring[i];
- u32 tc = ixgbe_dcb_txq_to_tc(adapter, tx_ring->reg_idx);
+ u8 tc = tx_ring->dcb_tc;
if (xoff[tc])
clear_bit(__IXGBE_HANG_CHECK_ARMED, &tx_ring->state);
@@ -827,15 +772,6 @@
return ret;
}
-#define IXGBE_MAX_TXD_PWR 14
-#define IXGBE_MAX_DATA_PER_TXD (1 << IXGBE_MAX_TXD_PWR)
-
-/* Tx Descriptors needed, worst case */
-#define TXD_USE_COUNT(S) (((S) >> IXGBE_MAX_TXD_PWR) + \
- (((S) & (IXGBE_MAX_DATA_PER_TXD - 1)) ? 1 : 0))
-#define DESC_NEEDED (TXD_USE_COUNT(IXGBE_MAX_DATA_PER_TXD) /* skb->data */ + \
- MAX_SKB_FRAGS * TXD_USE_COUNT(PAGE_SIZE) + 1) /* for context */
-
/**
* ixgbe_tx_timeout_reset - initiate reset due to Tx timeout
* @adapter: driver private struct
@@ -938,7 +874,7 @@
#define TX_WAKE_THRESHOLD (DESC_NEEDED * 2)
if (unlikely(count && netif_carrier_ok(tx_ring->netdev) &&
- (IXGBE_DESC_UNUSED(tx_ring) >= TX_WAKE_THRESHOLD))) {
+ (ixgbe_desc_unused(tx_ring) >= TX_WAKE_THRESHOLD))) {
/* Make sure that anybody stopping the queue after this
* sees the new next_to_clean.
*/
@@ -1530,7 +1466,7 @@
}
rx_ring->next_to_clean = i;
- cleaned_count = IXGBE_DESC_UNUSED(rx_ring);
+ cleaned_count = ixgbe_desc_unused(rx_ring);
if (cleaned_count)
ixgbe_alloc_rx_buffers(rx_ring, cleaned_count);
@@ -1610,9 +1546,8 @@
q_vector->eitr = adapter->rx_eitr_param;
ixgbe_write_eitr(q_vector);
- /* If Flow Director is enabled, set interrupt affinity */
- if ((adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE) ||
- (adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE)) {
+ /* If ATR is enabled, set interrupt affinity */
+ if (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE) {
/*
* Allocate the affinity_hint cpumask, assign the mask
* for this vector, and set our affinity_hint for
@@ -1937,8 +1872,7 @@
static irqreturn_t ixgbe_msix_lsc(int irq, void *data)
{
- struct net_device *netdev = data;
- struct ixgbe_adapter *adapter = netdev_priv(netdev);
+ struct ixgbe_adapter *adapter = data;
struct ixgbe_hw *hw = &adapter->hw;
u32 eicr;
@@ -2433,7 +2367,7 @@
sprintf(adapter->lsc_int_name, "%s:lsc", netdev->name);
err = request_irq(adapter->msix_entries[vector].vector,
- ixgbe_msix_lsc, 0, adapter->lsc_int_name, netdev);
+ ixgbe_msix_lsc, 0, adapter->lsc_int_name, adapter);
if (err) {
e_err(probe, "request_irq for msix_lsc failed: %d\n", err);
goto free_queue_irqs;
@@ -2523,8 +2457,7 @@
default:
break;
}
- if (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE ||
- adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE)
+ if (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE)
mask |= IXGBE_EIMS_FLOW_DIR;
IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, mask);
@@ -2546,8 +2479,7 @@
**/
static irqreturn_t ixgbe_intr(int irq, void *data)
{
- struct net_device *netdev = data;
- struct ixgbe_adapter *adapter = netdev_priv(netdev);
+ struct ixgbe_adapter *adapter = data;
struct ixgbe_hw *hw = &adapter->hw;
struct ixgbe_q_vector *q_vector = adapter->q_vector[0];
u32 eicr;
@@ -2644,10 +2576,10 @@
err = ixgbe_request_msix_irqs(adapter);
} else if (adapter->flags & IXGBE_FLAG_MSI_ENABLED) {
err = request_irq(adapter->pdev->irq, ixgbe_intr, 0,
- netdev->name, netdev);
+ netdev->name, adapter);
} else {
err = request_irq(adapter->pdev->irq, ixgbe_intr, IRQF_SHARED,
- netdev->name, netdev);
+ netdev->name, adapter);
}
if (err)
@@ -2658,15 +2590,13 @@
static void ixgbe_free_irq(struct ixgbe_adapter *adapter)
{
- struct net_device *netdev = adapter->netdev;
-
if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) {
int i, q_vectors;
q_vectors = adapter->num_msix_vectors;
i = q_vectors - 1;
- free_irq(adapter->msix_entries[i].vector, netdev);
+ free_irq(adapter->msix_entries[i].vector, adapter);
i--;
for (; i >= 0; i--) {
@@ -2681,7 +2611,7 @@
ixgbe_reset_q_vectors(adapter);
} else {
- free_irq(adapter->pdev->irq, netdev);
+ free_irq(adapter->pdev->irq, adapter);
}
}
@@ -2814,7 +2744,8 @@
{
struct ixgbe_hw *hw = &adapter->hw;
u32 rttdcs;
- u32 mask;
+ u32 reg;
+ u8 tcs = netdev_get_num_tc(adapter->netdev);
if (hw->mac.type == ixgbe_mac_82598EB)
return;
@@ -2825,22 +2756,27 @@
IXGBE_WRITE_REG(hw, IXGBE_RTTDCS, rttdcs);
/* set transmit pool layout */
- mask = (IXGBE_FLAG_SRIOV_ENABLED | IXGBE_FLAG_DCB_ENABLED);
- switch (adapter->flags & mask) {
-
+ switch (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED) {
case (IXGBE_FLAG_SRIOV_ENABLED):
IXGBE_WRITE_REG(hw, IXGBE_MTQC,
(IXGBE_MTQC_VT_ENA | IXGBE_MTQC_64VF));
break;
-
- case (IXGBE_FLAG_DCB_ENABLED):
- /* We enable 8 traffic classes, DCB only */
- IXGBE_WRITE_REG(hw, IXGBE_MTQC,
- (IXGBE_MTQC_RT_ENA | IXGBE_MTQC_8TC_8TQ));
- break;
-
default:
- IXGBE_WRITE_REG(hw, IXGBE_MTQC, IXGBE_MTQC_64Q_1PB);
+ if (!tcs)
+ reg = IXGBE_MTQC_64Q_1PB;
+ else if (tcs <= 4)
+ reg = IXGBE_MTQC_RT_ENA | IXGBE_MTQC_4TC_4TQ;
+ else
+ reg = IXGBE_MTQC_RT_ENA | IXGBE_MTQC_8TC_8TQ;
+
+ IXGBE_WRITE_REG(hw, IXGBE_MTQC, reg);
+
+ /* Enable Security TX Buffer IFG for multiple pb */
+ if (tcs) {
+ reg = IXGBE_READ_REG(hw, IXGBE_SECTXMINIFG);
+ reg |= IXGBE_SECTX_DCB;
+ IXGBE_WRITE_REG(hw, IXGBE_SECTXMINIFG, reg);
+ }
break;
}
@@ -2931,7 +2867,11 @@
u32 mrqc = 0, reta = 0;
u32 rxcsum;
int i, j;
- int mask;
+ u8 tcs = netdev_get_num_tc(adapter->netdev);
+ int maxq = adapter->ring_feature[RING_F_RSS].indices;
+
+ if (tcs)
+ maxq = min(maxq, adapter->num_tx_queues / tcs);
/* Fill out hash function seeds */
for (i = 0; i < 10; i++)
@@ -2939,7 +2879,7 @@
/* Fill out redirection table */
for (i = 0, j = 0; i < 128; i++, j++) {
- if (j == adapter->ring_feature[RING_F_RSS].indices)
+ if (j == maxq)
j = 0;
/* reta = 4-byte sliding window of
* 0x00..(indices-1)(indices-1)00..etc. */
@@ -2953,33 +2893,28 @@
rxcsum |= IXGBE_RXCSUM_PCSD;
IXGBE_WRITE_REG(hw, IXGBE_RXCSUM, rxcsum);
- if (adapter->hw.mac.type == ixgbe_mac_82598EB)
- mask = adapter->flags & IXGBE_FLAG_RSS_ENABLED;
- else
- mask = adapter->flags & (IXGBE_FLAG_RSS_ENABLED
-#ifdef CONFIG_IXGBE_DCB
- | IXGBE_FLAG_DCB_ENABLED
-#endif
- | IXGBE_FLAG_SRIOV_ENABLED
- );
-
- switch (mask) {
-#ifdef CONFIG_IXGBE_DCB
- case (IXGBE_FLAG_DCB_ENABLED | IXGBE_FLAG_RSS_ENABLED):
- mrqc = IXGBE_MRQC_RTRSS8TCEN;
- break;
- case (IXGBE_FLAG_DCB_ENABLED):
- mrqc = IXGBE_MRQC_RT8TCEN;
- break;
-#endif /* CONFIG_IXGBE_DCB */
- case (IXGBE_FLAG_RSS_ENABLED):
+ if (adapter->hw.mac.type == ixgbe_mac_82598EB &&
+ (adapter->flags & IXGBE_FLAG_RSS_ENABLED)) {
mrqc = IXGBE_MRQC_RSSEN;
- break;
- case (IXGBE_FLAG_SRIOV_ENABLED):
- mrqc = IXGBE_MRQC_VMDQEN;
- break;
- default:
- break;
+ } else {
+ int mask = adapter->flags & (IXGBE_FLAG_RSS_ENABLED
+ | IXGBE_FLAG_SRIOV_ENABLED);
+
+ switch (mask) {
+ case (IXGBE_FLAG_RSS_ENABLED):
+ if (!tcs)
+ mrqc = IXGBE_MRQC_RSSEN;
+ else if (tcs <= 4)
+ mrqc = IXGBE_MRQC_RTRSS4TCEN;
+ else
+ mrqc = IXGBE_MRQC_RTRSS8TCEN;
+ break;
+ case (IXGBE_FLAG_SRIOV_ENABLED):
+ mrqc = IXGBE_MRQC_VMDQEN;
+ break;
+ default:
+ break;
+ }
}
/* Perform hash on these packet types */
@@ -3183,7 +3118,7 @@
IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(reg_idx), rxdctl);
ixgbe_rx_desc_queue_enable(adapter, ring);
- ixgbe_alloc_rx_buffers(ring, IXGBE_DESC_UNUSED(ring));
+ ixgbe_alloc_rx_buffers(ring, ixgbe_desc_unused(ring));
}
static void ixgbe_setup_psrtype(struct ixgbe_adapter *adapter)
@@ -3739,7 +3674,7 @@
hw->mac.ops.set_vfta(&adapter->hw, 0, 0, true);
/* reconfigure the hardware */
- if (adapter->dcbx_cap & (DCB_CAP_DCBX_HOST | DCB_CAP_DCBX_VER_CEE)) {
+ if (adapter->dcbx_cap & DCB_CAP_DCBX_VER_CEE) {
#ifdef CONFIG_FCOE
if (adapter->netdev->features & NETIF_F_FCOE_MTU)
max_frame = max(max_frame, IXGBE_FCOE_JUMBO_FRAME_SIZE);
@@ -3779,12 +3714,51 @@
}
#endif
+
+static void ixgbe_configure_pb(struct ixgbe_adapter *adapter)
+{
+ int hdrm = 0;
+ int num_tc = netdev_get_num_tc(adapter->netdev);
+ struct ixgbe_hw *hw = &adapter->hw;
+
+ if (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE ||
+ adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE)
+ hdrm = 64 << adapter->fdir_pballoc;
+
+ hw->mac.ops.set_rxpba(&adapter->hw, num_tc, hdrm, PBA_STRATEGY_EQUAL);
+}
+
+static void ixgbe_fdir_filter_restore(struct ixgbe_adapter *adapter)
+{
+ struct ixgbe_hw *hw = &adapter->hw;
+ struct hlist_node *node, *node2;
+ struct ixgbe_fdir_filter *filter;
+
+ spin_lock(&adapter->fdir_perfect_lock);
+
+ if (!hlist_empty(&adapter->fdir_filter_list))
+ ixgbe_fdir_set_input_mask_82599(hw, &adapter->fdir_mask);
+
+ hlist_for_each_entry_safe(filter, node, node2,
+ &adapter->fdir_filter_list, fdir_node) {
+ ixgbe_fdir_write_perfect_filter_82599(hw,
+ &filter->filter,
+ filter->sw_idx,
+ (filter->action == IXGBE_FDIR_DROP_QUEUE) ?
+ IXGBE_FDIR_DROP_QUEUE :
+ adapter->rx_ring[filter->action]->reg_idx);
+ }
+
+ spin_unlock(&adapter->fdir_perfect_lock);
+}
+
static void ixgbe_configure(struct ixgbe_adapter *adapter)
{
struct net_device *netdev = adapter->netdev;
struct ixgbe_hw *hw = &adapter->hw;
int i;
+ ixgbe_configure_pb(adapter);
#ifdef CONFIG_IXGBE_DCB
ixgbe_configure_dcb(adapter);
#endif
@@ -3803,7 +3777,9 @@
adapter->atr_sample_rate;
ixgbe_init_fdir_signature_82599(hw, adapter->fdir_pballoc);
} else if (adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE) {
- ixgbe_init_fdir_perfect_82599(hw, adapter->fdir_pballoc);
+ ixgbe_init_fdir_perfect_82599(&adapter->hw,
+ adapter->fdir_pballoc);
+ ixgbe_fdir_filter_restore(adapter);
}
ixgbe_configure_virtualization(adapter);
@@ -4180,6 +4156,23 @@
ixgbe_clean_tx_ring(adapter->tx_ring[i]);
}
+static void ixgbe_fdir_filter_exit(struct ixgbe_adapter *adapter)
+{
+ struct hlist_node *node, *node2;
+ struct ixgbe_fdir_filter *filter;
+
+ spin_lock(&adapter->fdir_perfect_lock);
+
+ hlist_for_each_entry_safe(filter, node, node2,
+ &adapter->fdir_filter_list, fdir_node) {
+ hlist_del(&filter->fdir_node);
+ kfree(filter);
+ }
+ adapter->fdir_filter_count = 0;
+
+ spin_unlock(&adapter->fdir_perfect_lock);
+}
+
void ixgbe_down(struct ixgbe_adapter *adapter)
{
struct net_device *netdev = adapter->netdev;
@@ -4369,15 +4362,13 @@
f_fdir->mask = 0;
/* Flow Director must have RSS enabled */
- if (adapter->flags & IXGBE_FLAG_RSS_ENABLED &&
- ((adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE ||
- (adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE)))) {
+ 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;
- adapter->flags &= ~IXGBE_FLAG_FDIR_PERFECT_CAPABLE;
}
return ret;
}
@@ -4400,69 +4391,72 @@
if (!(adapter->flags & IXGBE_FLAG_FCOE_ENABLED))
return false;
- if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) {
-#ifdef CONFIG_IXGBE_DCB
- int tc;
- struct net_device *dev = adapter->netdev;
+ f->indices = min((int)num_online_cpus(), f->indices);
- tc = netdev_get_prio_tc_map(dev, adapter->fcoe.up);
- f->indices = dev->tc_to_txq[tc].count;
- f->mask = dev->tc_to_txq[tc].offset;
-#endif
- } else {
- f->indices = min((int)num_online_cpus(), f->indices);
+ adapter->num_rx_queues = 1;
+ adapter->num_tx_queues = 1;
- adapter->num_rx_queues = 1;
- adapter->num_tx_queues = 1;
-
- if (adapter->flags & IXGBE_FLAG_RSS_ENABLED) {
- e_info(probe, "FCoE enabled with RSS\n");
- if ((adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE) ||
- (adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE))
- ixgbe_set_fdir_queues(adapter);
- else
- ixgbe_set_rss_queues(adapter);
- }
- /* 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;
+ 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);
}
+ /* 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;
+
return true;
}
#endif /* IXGBE_FCOE */
+/* Artificial max queue cap per traffic class in DCB mode */
+#define DCB_QUEUE_CAP 8
+
#ifdef CONFIG_IXGBE_DCB
static inline bool ixgbe_set_dcb_queues(struct ixgbe_adapter *adapter)
{
- bool ret = false;
- struct ixgbe_ring_feature *f = &adapter->ring_feature[RING_F_DCB];
- int i, q;
+ int per_tc_q, q, i, offset = 0;
+ struct net_device *dev = adapter->netdev;
+ int tcs = netdev_get_num_tc(dev);
- if (!(adapter->flags & IXGBE_FLAG_DCB_ENABLED))
- return ret;
+ if (!tcs)
+ return false;
- f->indices = 0;
- for (i = 0; i < MAX_TRAFFIC_CLASS; i++) {
- q = min((int)num_online_cpus(), MAX_TRAFFIC_CLASS);
- f->indices += q;
+ /* Map queue offset and counts onto allocated tx queues */
+ per_tc_q = min(dev->num_tx_queues / tcs, (unsigned int)DCB_QUEUE_CAP);
+ q = min((int)num_online_cpus(), per_tc_q);
+
+ for (i = 0; i < tcs; i++) {
+ netdev_set_prio_tc_map(dev, i, i);
+ netdev_set_tc_queue(dev, i, q, offset);
+ offset += q;
}
- f->mask = 0x7 << 3;
- adapter->num_rx_queues = f->indices;
- adapter->num_tx_queues = f->indices;
- ret = true;
+ adapter->num_tx_queues = q * tcs;
+ adapter->num_rx_queues = q * tcs;
#ifdef IXGBE_FCOE
- /* FCoE enabled queues require special configuration done through
- * configure_fcoe() and others. Here we map FCoE indices onto the
- * DCB queue pairs allowing FCoE to own configuration later.
+ /* 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.
*/
- ixgbe_set_fcoe_queues(adapter);
+ if (adapter->flags & IXGBE_FLAG_FCOE_ENABLED) {
+ int tc;
+ struct ixgbe_ring_feature *f =
+ &adapter->ring_feature[RING_F_FCOE];
+
+ tc = netdev_get_prio_tc_map(dev, adapter->fcoe.up);
+ f->indices = dev->tc_to_txq[tc].count;
+ f->mask = dev->tc_to_txq[tc].offset;
+ }
#endif
- return ret;
+ return true;
}
#endif
@@ -4616,8 +4610,8 @@
switch (hw->mac.type) {
case ixgbe_mac_82598EB:
- *tx = tc << 3;
- *rx = tc << 2;
+ *tx = tc << 2;
+ *rx = tc << 3;
break;
case ixgbe_mac_82599EB:
case ixgbe_mac_X540:
@@ -4657,55 +4651,6 @@
}
}
-#define IXGBE_MAX_Q_PER_TC (IXGBE_MAX_DCB_INDICES / MAX_TRAFFIC_CLASS)
-
-/* ixgbe_setup_tc - routine to configure net_device for multiple traffic
- * classes.
- *
- * @netdev: net device to configure
- * @tc: number of traffic classes to enable
- */
-int ixgbe_setup_tc(struct net_device *dev, u8 tc)
-{
- int i;
- unsigned int q, offset = 0;
-
- if (!tc) {
- netdev_reset_tc(dev);
- } else {
- struct ixgbe_adapter *adapter = netdev_priv(dev);
-
- /* Hardware supports up to 8 traffic classes */
- if (tc > MAX_TRAFFIC_CLASS || netdev_set_num_tc(dev, tc))
- return -EINVAL;
-
- /* Partition Tx queues evenly amongst traffic classes */
- for (i = 0; i < tc; i++) {
- q = min((int)num_online_cpus(), IXGBE_MAX_Q_PER_TC);
- netdev_set_prio_tc_map(dev, i, i);
- netdev_set_tc_queue(dev, i, q, offset);
- offset += q;
- }
-
- /* This enables multiple traffic class support in the hardware
- * which defaults to strict priority transmission by default.
- * If traffic classes are already enabled perhaps through DCB
- * code path then existing configuration will be used.
- */
- if (!(adapter->flags & IXGBE_FLAG_DCB_ENABLED) &&
- dev->dcbnl_ops && dev->dcbnl_ops->setdcbx) {
- struct ieee_ets ets = {
- .prio_tc = {0, 1, 2, 3, 4, 5, 6, 7},
- };
- u8 mode = DCB_CAP_DCBX_HOST | DCB_CAP_DCBX_VER_IEEE;
-
- dev->dcbnl_ops->setdcbx(dev, mode);
- dev->dcbnl_ops->ieee_setets(dev, &ets);
- }
- }
- return 0;
-}
-
/**
* ixgbe_cache_ring_dcb - Descriptor ring to register mapping for DCB
* @adapter: board private structure to initialize
@@ -4719,7 +4664,7 @@
int i, j, k;
u8 num_tcs = netdev_get_num_tc(dev);
- if (!(adapter->flags & IXGBE_FLAG_DCB_ENABLED))
+ if (!num_tcs)
return false;
for (i = 0, k = 0; i < num_tcs; i++) {
@@ -4751,9 +4696,8 @@
int i;
bool ret = false;
- if (adapter->flags & IXGBE_FLAG_RSS_ENABLED &&
- ((adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE) ||
- (adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE))) {
+ 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++)
@@ -4782,8 +4726,7 @@
return false;
if (adapter->flags & IXGBE_FLAG_RSS_ENABLED) {
- if ((adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE) ||
- (adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE))
+ if (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE)
ixgbe_cache_ring_fdir(adapter);
else
ixgbe_cache_ring_rss(adapter);
@@ -4963,14 +4906,12 @@
adapter->flags &= ~IXGBE_FLAG_DCB_ENABLED;
adapter->flags &= ~IXGBE_FLAG_RSS_ENABLED;
- if (adapter->flags & (IXGBE_FLAG_FDIR_HASH_CAPABLE |
- IXGBE_FLAG_FDIR_PERFECT_CAPABLE)) {
+ if (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE) {
e_err(probe,
- "Flow Director is not supported while multiple "
+ "ATR is not supported while multiple "
"queues are disabled. Disabling Flow Director\n");
}
adapter->flags &= ~IXGBE_FLAG_FDIR_HASH_CAPABLE;
- adapter->flags &= ~IXGBE_FLAG_FDIR_PERFECT_CAPABLE;
adapter->atr_sample_rate = 0;
if (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED)
ixgbe_disable_sriov(adapter);
@@ -5201,7 +5142,6 @@
rss = min(IXGBE_MAX_RSS_INDICES, (int)num_online_cpus());
adapter->ring_feature[RING_F_RSS].indices = rss;
adapter->flags |= IXGBE_FLAG_RSS_ENABLED;
- adapter->ring_feature[RING_F_DCB].indices = IXGBE_MAX_DCB_INDICES;
switch (hw->mac.type) {
case ixgbe_mac_82598EB:
if (hw->device_id == IXGBE_DEV_ID_82598AT)
@@ -5222,14 +5162,13 @@
adapter->atr_sample_rate = 20;
adapter->ring_feature[RING_F_FDIR].indices =
IXGBE_MAX_FDIR_INDICES;
- adapter->fdir_pballoc = 0;
+ 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.tc = IXGBE_FCOE_DEFTC;
adapter->fcoe.up = IXGBE_FCOE_DEFTC;
#endif
#endif /* IXGBE_FCOE */
@@ -5250,7 +5189,6 @@
}
adapter->dcb_cfg.bw_percentage[DCB_TX_CONFIG][0] = 100;
adapter->dcb_cfg.bw_percentage[DCB_RX_CONFIG][0] = 100;
- adapter->dcb_cfg.rx_pba_cfg = pba_equal;
adapter->dcb_cfg.pfc_mode_enable = false;
adapter->dcb_set_bitmap = 0x00;
adapter->dcbx_cap = DCB_CAP_DCBX_HOST | DCB_CAP_DCBX_VER_CEE;
@@ -5620,6 +5558,8 @@
ixgbe_down(adapter);
ixgbe_free_irq(adapter);
+ ixgbe_fdir_filter_exit(adapter);
+
ixgbe_free_all_tx_resources(adapter);
ixgbe_free_all_rx_resources(adapter);
@@ -6404,179 +6344,145 @@
ixgbe_service_event_complete(adapter);
}
-static int ixgbe_tso(struct ixgbe_adapter *adapter,
- struct ixgbe_ring *tx_ring, struct sk_buff *skb,
- u32 tx_flags, u8 *hdr_len, __be16 protocol)
+void ixgbe_tx_ctxtdesc(struct ixgbe_ring *tx_ring, u32 vlan_macip_lens,
+ u32 fcoe_sof_eof, u32 type_tucmd, u32 mss_l4len_idx)
{
struct ixgbe_adv_tx_context_desc *context_desc;
- unsigned int i;
+ u16 i = tx_ring->next_to_use;
+
+ context_desc = IXGBE_TX_CTXTDESC_ADV(tx_ring, i);
+
+ i++;
+ tx_ring->next_to_use = (i < tx_ring->count) ? i : 0;
+
+ /* set bits to identify this as an advanced context descriptor */
+ type_tucmd |= IXGBE_TXD_CMD_DEXT | IXGBE_ADVTXD_DTYP_CTXT;
+
+ context_desc->vlan_macip_lens = cpu_to_le32(vlan_macip_lens);
+ context_desc->seqnum_seed = cpu_to_le32(fcoe_sof_eof);
+ context_desc->type_tucmd_mlhl = cpu_to_le32(type_tucmd);
+ context_desc->mss_l4len_idx = cpu_to_le32(mss_l4len_idx);
+}
+
+static int ixgbe_tso(struct ixgbe_ring *tx_ring, struct sk_buff *skb,
+ u32 tx_flags, __be16 protocol, u8 *hdr_len)
+{
int err;
- struct ixgbe_tx_buffer *tx_buffer_info;
- u32 vlan_macip_lens = 0, type_tucmd_mlhl;
+ u32 vlan_macip_lens, type_tucmd;
u32 mss_l4len_idx, l4len;
- if (skb_is_gso(skb)) {
- if (skb_header_cloned(skb)) {
- err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
- if (err)
- return err;
- }
- l4len = tcp_hdrlen(skb);
- *hdr_len += l4len;
+ if (!skb_is_gso(skb))
+ return 0;
- if (protocol == htons(ETH_P_IP)) {
- struct iphdr *iph = ip_hdr(skb);
- iph->tot_len = 0;
- iph->check = 0;
- tcp_hdr(skb)->check = ~csum_tcpudp_magic(iph->saddr,
- iph->daddr, 0,
- IPPROTO_TCP,
- 0);
- } else if (skb_is_gso_v6(skb)) {
- ipv6_hdr(skb)->payload_len = 0;
- tcp_hdr(skb)->check =
- ~csum_ipv6_magic(&ipv6_hdr(skb)->saddr,
- &ipv6_hdr(skb)->daddr,
- 0, IPPROTO_TCP, 0);
- }
-
- i = tx_ring->next_to_use;
-
- tx_buffer_info = &tx_ring->tx_buffer_info[i];
- context_desc = IXGBE_TX_CTXTDESC_ADV(tx_ring, i);
-
- /* VLAN MACLEN IPLEN */
- if (tx_flags & IXGBE_TX_FLAGS_VLAN)
- vlan_macip_lens |=
- (tx_flags & IXGBE_TX_FLAGS_VLAN_MASK);
- vlan_macip_lens |= ((skb_network_offset(skb)) <<
- IXGBE_ADVTXD_MACLEN_SHIFT);
- *hdr_len += skb_network_offset(skb);
- vlan_macip_lens |=
- (skb_transport_header(skb) - skb_network_header(skb));
- *hdr_len +=
- (skb_transport_header(skb) - skb_network_header(skb));
- context_desc->vlan_macip_lens = cpu_to_le32(vlan_macip_lens);
- context_desc->seqnum_seed = 0;
-
- /* ADV DTYP TUCMD MKRLOC/ISCSIHEDLEN */
- type_tucmd_mlhl = (IXGBE_TXD_CMD_DEXT |
- IXGBE_ADVTXD_DTYP_CTXT);
-
- if (protocol == htons(ETH_P_IP))
- type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_IPV4;
- type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_L4T_TCP;
- context_desc->type_tucmd_mlhl = cpu_to_le32(type_tucmd_mlhl);
-
- /* MSS L4LEN IDX */
- mss_l4len_idx =
- (skb_shinfo(skb)->gso_size << IXGBE_ADVTXD_MSS_SHIFT);
- mss_l4len_idx |= (l4len << IXGBE_ADVTXD_L4LEN_SHIFT);
- /* use index 1 for TSO */
- mss_l4len_idx |= (1 << IXGBE_ADVTXD_IDX_SHIFT);
- context_desc->mss_l4len_idx = cpu_to_le32(mss_l4len_idx);
-
- tx_buffer_info->time_stamp = jiffies;
- tx_buffer_info->next_to_watch = i;
-
- i++;
- if (i == tx_ring->count)
- i = 0;
- tx_ring->next_to_use = i;
-
- return true;
- }
- return false;
-}
-
-static u32 ixgbe_psum(struct ixgbe_adapter *adapter, struct sk_buff *skb,
- __be16 protocol)
-{
- u32 rtn = 0;
-
- switch (protocol) {
- case cpu_to_be16(ETH_P_IP):
- rtn |= IXGBE_ADVTXD_TUCMD_IPV4;
- switch (ip_hdr(skb)->protocol) {
- case IPPROTO_TCP:
- rtn |= IXGBE_ADVTXD_TUCMD_L4T_TCP;
- break;
- case IPPROTO_SCTP:
- rtn |= IXGBE_ADVTXD_TUCMD_L4T_SCTP;
- break;
- }
- break;
- case cpu_to_be16(ETH_P_IPV6):
- /* XXX what about other V6 headers?? */
- switch (ipv6_hdr(skb)->nexthdr) {
- case IPPROTO_TCP:
- rtn |= IXGBE_ADVTXD_TUCMD_L4T_TCP;
- break;
- case IPPROTO_SCTP:
- rtn |= IXGBE_ADVTXD_TUCMD_L4T_SCTP;
- break;
- }
- break;
- default:
- if (unlikely(net_ratelimit()))
- e_warn(probe, "partial checksum but proto=%x!\n",
- protocol);
- break;
+ if (skb_header_cloned(skb)) {
+ err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
+ if (err)
+ return err;
}
- return rtn;
+ /* ADV DTYP TUCMD MKRLOC/ISCSIHEDLEN */
+ type_tucmd = IXGBE_ADVTXD_TUCMD_L4T_TCP;
+
+ if (protocol == __constant_htons(ETH_P_IP)) {
+ struct iphdr *iph = ip_hdr(skb);
+ iph->tot_len = 0;
+ iph->check = 0;
+ tcp_hdr(skb)->check = ~csum_tcpudp_magic(iph->saddr,
+ iph->daddr, 0,
+ IPPROTO_TCP,
+ 0);
+ type_tucmd |= IXGBE_ADVTXD_TUCMD_IPV4;
+ } else if (skb_is_gso_v6(skb)) {
+ ipv6_hdr(skb)->payload_len = 0;
+ tcp_hdr(skb)->check =
+ ~csum_ipv6_magic(&ipv6_hdr(skb)->saddr,
+ &ipv6_hdr(skb)->daddr,
+ 0, IPPROTO_TCP, 0);
+ }
+
+ l4len = tcp_hdrlen(skb);
+ *hdr_len = skb_transport_offset(skb) + l4len;
+
+ /* mss_l4len_id: use 1 as index for TSO */
+ mss_l4len_idx = l4len << IXGBE_ADVTXD_L4LEN_SHIFT;
+ mss_l4len_idx |= skb_shinfo(skb)->gso_size << IXGBE_ADVTXD_MSS_SHIFT;
+ mss_l4len_idx |= 1 << IXGBE_ADVTXD_IDX_SHIFT;
+
+ /* vlan_macip_lens: HEADLEN, MACLEN, VLAN tag */
+ vlan_macip_lens = skb_network_header_len(skb);
+ vlan_macip_lens |= skb_network_offset(skb) << IXGBE_ADVTXD_MACLEN_SHIFT;
+ vlan_macip_lens |= tx_flags & IXGBE_TX_FLAGS_VLAN_MASK;
+
+ ixgbe_tx_ctxtdesc(tx_ring, vlan_macip_lens, 0, type_tucmd,
+ mss_l4len_idx);
+
+ return 1;
}
-static bool ixgbe_tx_csum(struct ixgbe_adapter *adapter,
- struct ixgbe_ring *tx_ring,
+static bool ixgbe_tx_csum(struct ixgbe_ring *tx_ring,
struct sk_buff *skb, u32 tx_flags,
__be16 protocol)
{
- struct ixgbe_adv_tx_context_desc *context_desc;
- unsigned int i;
- struct ixgbe_tx_buffer *tx_buffer_info;
- u32 vlan_macip_lens = 0, type_tucmd_mlhl = 0;
+ u32 vlan_macip_lens = 0;
+ u32 mss_l4len_idx = 0;
+ u32 type_tucmd = 0;
- if (skb->ip_summed == CHECKSUM_PARTIAL ||
- (tx_flags & IXGBE_TX_FLAGS_VLAN)) {
- i = tx_ring->next_to_use;
- tx_buffer_info = &tx_ring->tx_buffer_info[i];
- context_desc = IXGBE_TX_CTXTDESC_ADV(tx_ring, i);
+ if (skb->ip_summed != CHECKSUM_PARTIAL) {
+ if (!(tx_flags & IXGBE_TX_FLAGS_VLAN))
+ return false;
+ } else {
+ u8 l4_hdr = 0;
+ switch (protocol) {
+ case __constant_htons(ETH_P_IP):
+ vlan_macip_lens |= skb_network_header_len(skb);
+ type_tucmd |= IXGBE_ADVTXD_TUCMD_IPV4;
+ l4_hdr = ip_hdr(skb)->protocol;
+ break;
+ case __constant_htons(ETH_P_IPV6):
+ vlan_macip_lens |= skb_network_header_len(skb);
+ l4_hdr = ipv6_hdr(skb)->nexthdr;
+ break;
+ default:
+ if (unlikely(net_ratelimit())) {
+ dev_warn(tx_ring->dev,
+ "partial checksum but proto=%x!\n",
+ skb->protocol);
+ }
+ break;
+ }
- if (tx_flags & IXGBE_TX_FLAGS_VLAN)
- vlan_macip_lens |=
- (tx_flags & IXGBE_TX_FLAGS_VLAN_MASK);
- vlan_macip_lens |= (skb_network_offset(skb) <<
- IXGBE_ADVTXD_MACLEN_SHIFT);
- if (skb->ip_summed == CHECKSUM_PARTIAL)
- vlan_macip_lens |= (skb_transport_header(skb) -
- skb_network_header(skb));
-
- context_desc->vlan_macip_lens = cpu_to_le32(vlan_macip_lens);
- context_desc->seqnum_seed = 0;
-
- type_tucmd_mlhl |= (IXGBE_TXD_CMD_DEXT |
- IXGBE_ADVTXD_DTYP_CTXT);
-
- if (skb->ip_summed == CHECKSUM_PARTIAL)
- type_tucmd_mlhl |= ixgbe_psum(adapter, skb, protocol);
-
- context_desc->type_tucmd_mlhl = cpu_to_le32(type_tucmd_mlhl);
- /* use index zero for tx checksum offload */
- context_desc->mss_l4len_idx = 0;
-
- tx_buffer_info->time_stamp = jiffies;
- tx_buffer_info->next_to_watch = i;
-
- i++;
- if (i == tx_ring->count)
- i = 0;
- tx_ring->next_to_use = i;
-
- return true;
+ switch (l4_hdr) {
+ case IPPROTO_TCP:
+ type_tucmd |= IXGBE_ADVTXD_TUCMD_L4T_TCP;
+ mss_l4len_idx = tcp_hdrlen(skb) <<
+ IXGBE_ADVTXD_L4LEN_SHIFT;
+ break;
+ case IPPROTO_SCTP:
+ type_tucmd |= IXGBE_ADVTXD_TUCMD_L4T_SCTP;
+ mss_l4len_idx = sizeof(struct sctphdr) <<
+ IXGBE_ADVTXD_L4LEN_SHIFT;
+ break;
+ case IPPROTO_UDP:
+ mss_l4len_idx = sizeof(struct udphdr) <<
+ IXGBE_ADVTXD_L4LEN_SHIFT;
+ break;
+ default:
+ if (unlikely(net_ratelimit())) {
+ dev_warn(tx_ring->dev,
+ "partial checksum but l4 proto=%x!\n",
+ skb->protocol);
+ }
+ break;
+ }
}
- return false;
+ vlan_macip_lens |= skb_network_offset(skb) << IXGBE_ADVTXD_MACLEN_SHIFT;
+ vlan_macip_lens |= tx_flags & IXGBE_TX_FLAGS_VLAN_MASK;
+
+ ixgbe_tx_ctxtdesc(tx_ring, vlan_macip_lens, 0,
+ type_tucmd, mss_l4len_idx);
+
+ return (skb->ip_summed == CHECKSUM_PARTIAL);
}
static int ixgbe_tx_map(struct ixgbe_adapter *adapter,
@@ -6588,11 +6494,12 @@
struct ixgbe_tx_buffer *tx_buffer_info;
unsigned int len;
unsigned int total = skb->len;
- unsigned int offset = 0, size, count = 0, i;
+ unsigned int offset = 0, size, count = 0;
unsigned int nr_frags = skb_shinfo(skb)->nr_frags;
unsigned int f;
unsigned int bytecount = skb->len;
u16 gso_segs = 1;
+ u16 i;
i = tx_ring->next_to_use;
@@ -6858,7 +6765,7 @@
input, common, ring->queue_index);
}
-static int __ixgbe_maybe_stop_tx(struct ixgbe_ring *tx_ring, int size)
+static int __ixgbe_maybe_stop_tx(struct ixgbe_ring *tx_ring, u16 size)
{
netif_stop_subqueue(tx_ring->netdev, tx_ring->queue_index);
/* Herbert's original patch had:
@@ -6868,7 +6775,7 @@
/* We need to check again in a case another CPU has just
* made room available. */
- if (likely(IXGBE_DESC_UNUSED(tx_ring) < size))
+ if (likely(ixgbe_desc_unused(tx_ring) < size))
return -EBUSY;
/* A reprieve! - use start_queue because it doesn't call schedule */
@@ -6877,9 +6784,9 @@
return 0;
}
-static int ixgbe_maybe_stop_tx(struct ixgbe_ring *tx_ring, int size)
+static int ixgbe_maybe_stop_tx(struct ixgbe_ring *tx_ring, u16 size)
{
- if (likely(IXGBE_DESC_UNUSED(tx_ring) >= size))
+ if (likely(ixgbe_desc_unused(tx_ring) >= size))
return 0;
return __ixgbe_maybe_stop_tx(tx_ring, size);
}
@@ -6915,13 +6822,33 @@
struct ixgbe_adapter *adapter,
struct ixgbe_ring *tx_ring)
{
- unsigned int first;
- unsigned int tx_flags = 0;
- u8 hdr_len = 0;
int tso;
- int count = 0;
- unsigned int f;
+ u32 tx_flags = 0;
+#if PAGE_SIZE > IXGBE_MAX_DATA_PER_TXD
+ unsigned short f;
+#endif
+ u16 first;
+ u16 count = TXD_USE_COUNT(skb_headlen(skb));
__be16 protocol;
+ u8 hdr_len = 0;
+
+ /*
+ * need: 1 descriptor per page * PAGE_SIZE/IXGBE_MAX_DATA_PER_TXD,
+ * + 1 desc for skb_head_len/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 (ixgbe_maybe_stop_tx(tx_ring, count + 3)) {
+ tx_ring->tx_stats.tx_busy++;
+ return NETDEV_TX_BUSY;
+ }
protocol = vlan_get_protocol(skb);
@@ -6946,51 +6873,29 @@
if (adapter->flags & IXGBE_FLAG_FCOE_ENABLED &&
(protocol == htons(ETH_P_FCOE)))
tx_flags |= IXGBE_TX_FLAGS_FCOE;
+
#endif
-
- /* 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) ||
- (tx_flags & IXGBE_TX_FLAGS_FCOE))
- count++;
-
- count += TXD_USE_COUNT(skb_headlen(skb));
- for (f = 0; f < skb_shinfo(skb)->nr_frags; f++)
- count += TXD_USE_COUNT(skb_shinfo(skb)->frags[f].size);
-
- if (ixgbe_maybe_stop_tx(tx_ring, count)) {
- tx_ring->tx_stats.tx_busy++;
- return NETDEV_TX_BUSY;
- }
-
+ /* record the location of the first descriptor for this packet */
first = tx_ring->next_to_use;
+
if (tx_flags & IXGBE_TX_FLAGS_FCOE) {
#ifdef IXGBE_FCOE
/* setup tx offload for FCoE */
- tso = ixgbe_fso(adapter, tx_ring, skb, tx_flags, &hdr_len);
- if (tso < 0) {
- dev_kfree_skb_any(skb);
- return NETDEV_TX_OK;
- }
- if (tso)
+ tso = ixgbe_fso(tx_ring, skb, tx_flags, &hdr_len);
+ if (tso < 0)
+ goto out_drop;
+ else if (tso)
tx_flags |= IXGBE_TX_FLAGS_FSO;
#endif /* IXGBE_FCOE */
} else {
if (protocol == htons(ETH_P_IP))
tx_flags |= IXGBE_TX_FLAGS_IPV4;
- tso = ixgbe_tso(adapter, tx_ring, skb, tx_flags, &hdr_len,
- protocol);
- if (tso < 0) {
- dev_kfree_skb_any(skb);
- return NETDEV_TX_OK;
- }
-
- if (tso)
+ tso = ixgbe_tso(tx_ring, skb, tx_flags, protocol, &hdr_len);
+ if (tso < 0)
+ goto out_drop;
+ else if (tso)
tx_flags |= IXGBE_TX_FLAGS_TSO;
- else if (ixgbe_tx_csum(adapter, tx_ring, skb, tx_flags,
- protocol) &&
- (skb->ip_summed == CHECKSUM_PARTIAL))
+ else if (ixgbe_tx_csum(tx_ring, skb, tx_flags, protocol))
tx_flags |= IXGBE_TX_FLAGS_CSUM;
}
@@ -7003,12 +6908,16 @@
ixgbe_maybe_stop_tx(tx_ring, DESC_NEEDED);
} else {
- dev_kfree_skb_any(skb);
tx_ring->tx_buffer_info[first].time_stamp = 0;
tx_ring->next_to_use = first;
+ goto out_drop;
}
return NETDEV_TX_OK;
+
+out_drop:
+ dev_kfree_skb_any(skb);
+ return NETDEV_TX_OK;
}
static netdev_tx_t ixgbe_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
@@ -7198,6 +7107,85 @@
return stats;
}
+/* 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
+ * 802.1Q priority maps to a packet buffer that exists.
+ */
+static void ixgbe_validate_rtr(struct ixgbe_adapter *adapter, u8 tc)
+{
+ struct ixgbe_hw *hw = &adapter->hw;
+ u32 reg, rsave;
+ int i;
+
+ /* 82598 have a static priority to TC mapping that can not
+ * be changed so no validation is needed.
+ */
+ if (hw->mac.type == ixgbe_mac_82598EB)
+ return;
+
+ reg = IXGBE_READ_REG(hw, IXGBE_RTRUP2TC);
+ rsave = reg;
+
+ for (i = 0; i < MAX_TRAFFIC_CLASS; i++) {
+ u8 up2tc = reg >> (i * IXGBE_RTRUP2TC_UP_SHIFT);
+
+ /* If up2tc is out of bounds default to zero */
+ if (up2tc > tc)
+ reg &= ~(0x7 << IXGBE_RTRUP2TC_UP_SHIFT);
+ }
+
+ if (reg != rsave)
+ IXGBE_WRITE_REG(hw, IXGBE_RTRUP2TC, reg);
+
+ return;
+}
+
+
+/* ixgbe_setup_tc - routine to configure net_device for multiple traffic
+ * classes.
+ *
+ * @netdev: net device to configure
+ * @tc: number of traffic classes to enable
+ */
+int ixgbe_setup_tc(struct net_device *dev, u8 tc)
+{
+ struct ixgbe_adapter *adapter = netdev_priv(dev);
+ struct ixgbe_hw *hw = &adapter->hw;
+
+ /* If DCB is anabled do not remove traffic classes, multiple
+ * traffic classes are required to implement DCB
+ */
+ if (!tc && (adapter->flags & IXGBE_FLAG_DCB_ENABLED))
+ return 0;
+
+ /* Hardware supports up to 8 traffic classes */
+ if (tc > MAX_TRAFFIC_CLASS ||
+ (hw->mac.type == ixgbe_mac_82598EB && tc < MAX_TRAFFIC_CLASS))
+ return -EINVAL;
+
+ /* Hardware has to reinitialize queues and interrupts to
+ * match packet buffer alignment. Unfortunantly, the
+ * hardware is not flexible enough to do this dynamically.
+ */
+ if (netif_running(dev))
+ ixgbe_close(dev);
+ ixgbe_clear_interrupt_scheme(adapter);
+
+ if (tc)
+ netdev_set_num_tc(dev, tc);
+ else
+ netdev_reset_tc(dev);
+
+ ixgbe_init_interrupt_scheme(adapter);
+ ixgbe_validate_rtr(adapter, tc);
+ if (netif_running(dev))
+ ixgbe_open(dev);
+
+ return 0;
+}
static const struct net_device_ops ixgbe_netdev_ops = {
.ndo_open = ixgbe_open,
@@ -7218,9 +7206,7 @@
.ndo_set_vf_tx_rate = ixgbe_ndo_set_vf_bw,
.ndo_get_vf_config = ixgbe_ndo_get_vf_config,
.ndo_get_stats64 = ixgbe_get_stats64,
-#ifdef CONFIG_IXGBE_DCB
.ndo_setup_tc = ixgbe_setup_tc,
-#endif
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = ixgbe_netpoll,
#endif
@@ -7379,14 +7365,16 @@
pci_set_master(pdev);
pci_save_state(pdev);
+#ifdef CONFIG_IXGBE_DCB
+ indices *= MAX_TRAFFIC_CLASS;
+#endif
+
if (ii->mac == ixgbe_mac_82598EB)
indices = min_t(unsigned int, indices, IXGBE_MAX_RSS_INDICES);
else
indices = min_t(unsigned int, indices, IXGBE_MAX_FDIR_INDICES);
-#if defined(CONFIG_DCB)
- indices = max_t(unsigned int, indices, IXGBE_MAX_DCB_INDICES);
-#elif defined(IXGBE_FCOE)
+#ifdef IXGBE_FCOE
indices += min_t(unsigned int, num_possible_cpus(),
IXGBE_MAX_FCOE_INDICES);
#endif
@@ -7678,6 +7666,11 @@
ixgbe_vf_configuration(pdev, (i | 0x10000000));
}
+ /* Inform firmware of driver version */
+ if (hw->mac.ops.set_fw_drv_ver)
+ hw->mac.ops.set_fw_drv_ver(hw, MAJ, MIN, BUILD,
+ FW_CEM_UNUSED_VER);
+
/* add san mac addr to netdev */
ixgbe_add_sanmac_netdev(netdev);
diff --git a/drivers/net/ixgbe/ixgbe_sriov.c b/drivers/net/ixgbe/ixgbe_sriov.c
index ac99b04..d99d01e 100644
--- a/drivers/net/ixgbe/ixgbe_sriov.c
+++ b/drivers/net/ixgbe/ixgbe_sriov.c
@@ -605,6 +605,22 @@
}
IXGBE_WRITE_REG(hw, IXGBE_RTTDQSEL, 2*vf); /* vf Y uses queue 2*Y */
+ /*
+ * Set global transmit compensation time to the MMW_SIZE in RTTBCNRM
+ * register. Typically MMW_SIZE=0x014 if 9728-byte jumbo is supported
+ * and 0x004 otherwise.
+ */
+ switch (hw->mac.type) {
+ case ixgbe_mac_82599EB:
+ IXGBE_WRITE_REG(hw, IXGBE_RTTBCNRM, 0x4);
+ break;
+ case ixgbe_mac_X540:
+ IXGBE_WRITE_REG(hw, IXGBE_RTTBCNRM, 0x14);
+ break;
+ default:
+ break;
+ }
+
IXGBE_WRITE_REG(hw, IXGBE_RTTBCNRC, bcnrc_val);
}
diff --git a/drivers/net/ixgbe/ixgbe_type.h b/drivers/net/ixgbe/ixgbe_type.h
index fa43f25..e0d970e 100644
--- a/drivers/net/ixgbe/ixgbe_type.h
+++ b/drivers/net/ixgbe/ixgbe_type.h
@@ -534,7 +534,7 @@
#define IXGBE_RTTBCNRC_RF_INT_SHIFT 14
#define IXGBE_RTTBCNRC_RF_INT_MASK \
(IXGBE_RTTBCNRC_RF_DEC_MASK << IXGBE_RTTBCNRC_RF_INT_SHIFT)
-
+#define IXGBE_RTTBCNRM 0x04980
/* FCoE DMA Context Registers */
#define IXGBE_FCPTRL 0x02410 /* FC User Desc. PTR Low */
@@ -707,6 +707,13 @@
#define IXGBE_HFDR 0x15FE8
#define IXGBE_FLEX_MNG 0x15800 /* 0x15800 - 0x15EFC */
+#define IXGBE_HICR_EN 0x01 /* Enable bit - RO */
+/* Driver sets this bit when done to put command in RAM */
+#define IXGBE_HICR_C 0x02
+#define IXGBE_HICR_SV 0x04 /* Status Validity */
+#define IXGBE_HICR_FW_RESET_ENABLE 0x40
+#define IXGBE_HICR_FW_RESET 0x80
+
/* PCI-E registers */
#define IXGBE_GCR 0x11000
#define IXGBE_GTV 0x11004
@@ -1118,6 +1125,27 @@
#define IXGBE_GPIE_VTMODE_32 0x00008000 /* 32 VFs 4 queues per VF */
#define IXGBE_GPIE_VTMODE_64 0x0000C000 /* 64 VFs 2 queues per VF */
+/* Packet Buffer Initialization */
+#define IXGBE_TXPBSIZE_20KB 0x00005000 /* 20KB Packet Buffer */
+#define IXGBE_TXPBSIZE_40KB 0x0000A000 /* 40KB Packet Buffer */
+#define IXGBE_RXPBSIZE_48KB 0x0000C000 /* 48KB Packet Buffer */
+#define IXGBE_RXPBSIZE_64KB 0x00010000 /* 64KB Packet Buffer */
+#define IXGBE_RXPBSIZE_80KB 0x00014000 /* 80KB Packet Buffer */
+#define IXGBE_RXPBSIZE_128KB 0x00020000 /* 128KB Packet Buffer */
+#define IXGBE_RXPBSIZE_MAX 0x00080000 /* 512KB Packet Buffer*/
+#define IXGBE_TXPBSIZE_MAX 0x00028000 /* 160KB Packet Buffer*/
+
+#define IXGBE_TXPKT_SIZE_MAX 0xA /* Max Tx Packet size */
+#define IXGBE_MAX_PB 8
+
+/* Packet buffer allocation strategies */
+enum {
+ PBA_STRATEGY_EQUAL = 0, /* Distribute PB space equally */
+#define PBA_STRATEGY_EQUAL PBA_STRATEGY_EQUAL
+ PBA_STRATEGY_WEIGHTED = 1, /* Weight front half of TCs */
+#define PBA_STRATEGY_WEIGHTED PBA_STRATEGY_WEIGHTED
+};
+
/* Transmit Flow Control status */
#define IXGBE_TFCS_TXOFF 0x00000001
#define IXGBE_TFCS_TXOFF0 0x00000100
@@ -1860,6 +1888,7 @@
#define IXGBE_MTQC_32VF 0x8 /* 4 TX Queues per pool w/32VF's */
#define IXGBE_MTQC_64VF 0x4 /* 2 TX Queues per pool w/64VF's */
#define IXGBE_MTQC_8TC_8TQ 0xC /* 8 TC if RT_ENA or 8 TQ if VT_ENA */
+#define IXGBE_MTQC_4TC_4TQ 0x8 /* 4 TC if RT_ENA or 4 TQ if VT_ENA */
/* Receive Descriptor bit definitions */
#define IXGBE_RXD_STAT_DD 0x01 /* Descriptor Done */
@@ -2027,9 +2056,10 @@
#define IXGBE_VFLREC(_i) (0x00700 + (_i * 4))
enum ixgbe_fdir_pballoc_type {
- IXGBE_FDIR_PBALLOC_64K = 0,
- IXGBE_FDIR_PBALLOC_128K,
- IXGBE_FDIR_PBALLOC_256K,
+ IXGBE_FDIR_PBALLOC_NONE = 0,
+ IXGBE_FDIR_PBALLOC_64K = 1,
+ IXGBE_FDIR_PBALLOC_128K = 2,
+ IXGBE_FDIR_PBALLOC_256K = 3,
};
#define IXGBE_FDIR_PBALLOC_SIZE_SHIFT 16
@@ -2083,7 +2113,7 @@
#define IXGBE_FDIRCMD_CMD_ADD_FLOW 0x00000001
#define IXGBE_FDIRCMD_CMD_REMOVE_FLOW 0x00000002
#define IXGBE_FDIRCMD_CMD_QUERY_REM_FILT 0x00000003
-#define IXGBE_FDIRCMD_CMD_QUERY_REM_HASH 0x00000007
+#define IXGBE_FDIRCMD_FILTER_VALID 0x00000004
#define IXGBE_FDIRCMD_FILTER_UPDATE 0x00000008
#define IXGBE_FDIRCMD_IPv6DMATCH 0x00000010
#define IXGBE_FDIRCMD_L4TYPE_UDP 0x00000020
@@ -2102,6 +2132,44 @@
#define IXGBE_FDIR_INIT_DONE_POLL 10
#define IXGBE_FDIRCMD_CMD_POLL 10
+#define IXGBE_FDIR_DROP_QUEUE 127
+
+/* Manageablility Host Interface defines */
+#define IXGBE_HI_MAX_BLOCK_BYTE_LENGTH 1792 /* Num of bytes in range */
+#define IXGBE_HI_MAX_BLOCK_DWORD_LENGTH 448 /* Num of dwords in range */
+#define IXGBE_HI_COMMAND_TIMEOUT 500 /* Process HI command limit */
+
+/* CEM Support */
+#define FW_CEM_HDR_LEN 0x4
+#define FW_CEM_CMD_DRIVER_INFO 0xDD
+#define FW_CEM_CMD_DRIVER_INFO_LEN 0x5
+#define FW_CEM_CMD_RESERVED 0x0
+#define FW_CEM_UNUSED_VER 0x0
+#define FW_CEM_MAX_RETRIES 3
+#define FW_CEM_RESP_STATUS_SUCCESS 0x1
+
+/* Host Interface Command Structures */
+struct ixgbe_hic_hdr {
+ u8 cmd;
+ u8 buf_len;
+ union {
+ u8 cmd_resv;
+ u8 ret_status;
+ } cmd_or_resp;
+ u8 checksum;
+};
+
+struct ixgbe_hic_drv_info {
+ struct ixgbe_hic_hdr hdr;
+ u8 port_num;
+ u8 ver_sub;
+ u8 ver_build;
+ u8 ver_min;
+ u8 ver_maj;
+ u8 pad; /* end spacing to ensure length is mult. of dword */
+ u16 pad2; /* end spacing to ensure length is mult. of dword2 */
+};
+
/* Transmit Descriptor - Advanced */
union ixgbe_adv_tx_desc {
struct {
@@ -2286,7 +2354,7 @@
* src_port - 2 bytes
* dst_port - 2 bytes
* flex_bytes - 2 bytes
- * rsvd0 - 2 bytes - space reserved must be 0.
+ * bkt_hash - 2 bytes
*/
struct {
u8 vm_pool;
@@ -2297,7 +2365,7 @@
__be16 src_port;
__be16 dst_port;
__be16 flex_bytes;
- __be16 rsvd0;
+ __be16 bkt_hash;
} formatted;
__be32 dword_stream[11];
};
@@ -2318,16 +2386,6 @@
__be32 dword;
};
-struct ixgbe_atr_input_masks {
- __be16 rsvd0;
- __be16 vlan_id_mask;
- __be32 dst_ip_mask[4];
- __be32 src_ip_mask[4];
- __be16 src_port_mask;
- __be16 dst_port_mask;
- __be16 flex_mask;
-};
-
enum ixgbe_eeprom_type {
ixgbe_eeprom_uninitialized = 0,
ixgbe_eeprom_spi,
@@ -2615,6 +2673,9 @@
s32 (*get_link_capabilities)(struct ixgbe_hw *, ixgbe_link_speed *,
bool *);
+ /* Packet Buffer Manipulation */
+ void (*set_rxpba)(struct ixgbe_hw *, int, u32, int);
+
/* LED */
s32 (*led_on)(struct ixgbe_hw *, u32);
s32 (*led_off)(struct ixgbe_hw *, u32);
@@ -2638,6 +2699,9 @@
/* Flow Control */
s32 (*fc_enable)(struct ixgbe_hw *, s32);
+
+ /* Manageability interface */
+ s32 (*set_fw_drv_ver)(struct ixgbe_hw *, u8, u8, u8, u8);
};
struct ixgbe_phy_operations {
@@ -2807,6 +2871,7 @@
#define IXGBE_ERR_SFP_SETUP_NOT_COMPLETE -30
#define IXGBE_ERR_PBA_SECTION -31
#define IXGBE_ERR_INVALID_ARGUMENT -32
+#define IXGBE_ERR_HOST_INTERFACE_COMMAND -33
#define IXGBE_NOT_IMPLEMENTED 0x7FFFFFFF
#endif /* _IXGBE_TYPE_H_ */
diff --git a/drivers/net/ixgbe/ixgbe_x540.c b/drivers/net/ixgbe/ixgbe_x540.c
index 4ed687b..bec30ed 100644
--- a/drivers/net/ixgbe/ixgbe_x540.c
+++ b/drivers/net/ixgbe/ixgbe_x540.c
@@ -876,6 +876,7 @@
.read_analog_reg8 = NULL,
.write_analog_reg8 = NULL,
.setup_link = &ixgbe_setup_mac_link_X540,
+ .set_rxpba = &ixgbe_set_rxpba_generic,
.check_link = &ixgbe_check_mac_link_generic,
.get_link_capabilities = &ixgbe_get_copper_link_capabilities_generic,
.led_on = &ixgbe_led_on_generic,
@@ -893,6 +894,7 @@
.clear_vfta = &ixgbe_clear_vfta_generic,
.set_vfta = &ixgbe_set_vfta_generic,
.fc_enable = &ixgbe_fc_enable_generic,
+ .set_fw_drv_ver = &ixgbe_set_fw_drv_ver_generic,
.init_uta_tables = &ixgbe_init_uta_tables_generic,
.setup_sfp = NULL,
.set_mac_anti_spoofing = &ixgbe_set_mac_anti_spoofing,
diff --git a/drivers/net/ixgbevf/ixgbevf.h b/drivers/net/ixgbevf/ixgbevf.h
index b703f60..a2bbbb3 100644
--- a/drivers/net/ixgbevf/ixgbevf.h
+++ b/drivers/net/ixgbevf/ixgbevf.h
@@ -279,7 +279,7 @@
extern struct ixgbevf_info ixgbevf_82599_vf_info;
extern struct ixgbevf_info ixgbevf_X540_vf_info;
-extern struct ixgbe_mac_operations ixgbevf_mbx_ops;
+extern struct ixgbe_mbx_operations ixgbevf_mbx_ops;
/* needed by ethtool.c */
extern char ixgbevf_driver_name[];
diff --git a/drivers/net/ixgbevf/ixgbevf_main.c b/drivers/net/ixgbevf/ixgbevf_main.c
index 28d3cb2..fec36bd 100644
--- a/drivers/net/ixgbevf/ixgbevf_main.c
+++ b/drivers/net/ixgbevf/ixgbevf_main.c
@@ -52,7 +52,7 @@
static const char ixgbevf_driver_string[] =
"Intel(R) 10 Gigabit PCI Express Virtual Function Network Driver";
-#define DRV_VERSION "2.0.0-k2"
+#define DRV_VERSION "2.1.0-k"
const char ixgbevf_driver_version[] = DRV_VERSION;
static char ixgbevf_copyright[] =
"Copyright (c) 2009 - 2010 Intel Corporation.";
@@ -3249,18 +3249,18 @@
}
static const struct net_device_ops ixgbe_netdev_ops = {
- .ndo_open = &ixgbevf_open,
- .ndo_stop = &ixgbevf_close,
- .ndo_start_xmit = &ixgbevf_xmit_frame,
- .ndo_set_rx_mode = &ixgbevf_set_rx_mode,
- .ndo_set_multicast_list = &ixgbevf_set_rx_mode,
+ .ndo_open = ixgbevf_open,
+ .ndo_stop = ixgbevf_close,
+ .ndo_start_xmit = ixgbevf_xmit_frame,
+ .ndo_set_rx_mode = ixgbevf_set_rx_mode,
+ .ndo_set_multicast_list = ixgbevf_set_rx_mode,
.ndo_validate_addr = eth_validate_addr,
- .ndo_set_mac_address = &ixgbevf_set_mac,
- .ndo_change_mtu = &ixgbevf_change_mtu,
- .ndo_tx_timeout = &ixgbevf_tx_timeout,
- .ndo_vlan_rx_register = &ixgbevf_vlan_rx_register,
- .ndo_vlan_rx_add_vid = &ixgbevf_vlan_rx_add_vid,
- .ndo_vlan_rx_kill_vid = &ixgbevf_vlan_rx_kill_vid,
+ .ndo_set_mac_address = ixgbevf_set_mac,
+ .ndo_change_mtu = ixgbevf_change_mtu,
+ .ndo_tx_timeout = ixgbevf_tx_timeout,
+ .ndo_vlan_rx_register = ixgbevf_vlan_rx_register,
+ .ndo_vlan_rx_add_vid = ixgbevf_vlan_rx_add_vid,
+ .ndo_vlan_rx_kill_vid = ixgbevf_vlan_rx_kill_vid,
};
static void ixgbevf_assign_netdev_ops(struct net_device *dev)
@@ -3364,7 +3364,7 @@
hw->mac.type = ii->mac;
memcpy(&hw->mbx.ops, &ixgbevf_mbx_ops,
- sizeof(struct ixgbe_mac_operations));
+ sizeof(struct ixgbe_mbx_operations));
adapter->flags &= ~IXGBE_FLAG_RX_PS_CAPABLE;
adapter->flags &= ~IXGBE_FLAG_RX_PS_ENABLED;
diff --git a/drivers/net/ixp2000/ixpdev.c b/drivers/net/ixp2000/ixpdev.c
index 78ddd8b..e122493 100644
--- a/drivers/net/ixp2000/ixpdev.c
+++ b/drivers/net/ixp2000/ixpdev.c
@@ -14,6 +14,7 @@
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/moduleparam.h>
#include <linux/gfp.h>
#include <asm/hardware/uengine.h>
diff --git a/drivers/net/jme.c b/drivers/net/jme.c
index b5b174a..6b2a5e7 100644
--- a/drivers/net/jme.c
+++ b/drivers/net/jme.c
@@ -271,9 +271,7 @@
static inline void
jme_clear_pm(struct jme_adapter *jme)
{
- jwrite32(jme, JME_PMCS, 0xFFFF0000 | jme->reg_pmcs);
- pci_set_power_state(jme->pdev, PCI_D0);
- device_set_wakeup_enable(&jme->pdev->dev, false);
+ jwrite32(jme, JME_PMCS, PMCS_STMASK | jme->reg_pmcs);
}
static int
@@ -1817,11 +1815,9 @@
{
if (jme->reg_pmcs) {
jme_set_100m_half(jme);
-
if (jme->reg_pmcs & (PMCS_LFEN | PMCS_LREN))
jme_wait_link(jme);
-
- jwrite32(jme, JME_PMCS, jme->reg_pmcs);
+ jme_clear_pm(jme);
} else {
jme_phy_off(jme);
}
@@ -2529,8 +2525,7 @@
jme->reg_pmcs |= PMCS_MFEN;
jwrite32(jme, JME_PMCS, jme->reg_pmcs);
-
- device_set_wakeup_enable(&jme->pdev->dev, jme->reg_pmcs);
+ device_set_wakeup_enable(&jme->pdev->dev, !!(jme->reg_pmcs));
return 0;
}
@@ -3058,6 +3053,9 @@
jme->mii_if.mdio_write = jme_mdio_write;
jme_clear_pm(jme);
+ pci_set_power_state(jme->pdev, PCI_D0);
+ device_set_wakeup_enable(&pdev->dev, true);
+
jme_set_phyfifo_5level(jme);
jme->pcirev = pdev->revision;
if (!jme->fpgaver)
@@ -3135,8 +3133,9 @@
pci_pme_active(pdev, true);
}
-#ifdef CONFIG_PM
-static int jme_suspend(struct device *dev)
+#ifdef CONFIG_PM_SLEEP
+static int
+jme_suspend(struct device *dev)
{
struct pci_dev *pdev = to_pci_dev(dev);
struct net_device *netdev = pci_get_drvdata(pdev);
@@ -3175,14 +3174,14 @@
return 0;
}
-static int jme_resume(struct device *dev)
+static int
+jme_resume(struct device *dev)
{
struct pci_dev *pdev = to_pci_dev(dev);
struct net_device *netdev = pci_get_drvdata(pdev);
struct jme_adapter *jme = netdev_priv(netdev);
- jwrite32(jme, JME_PMCS, 0xFFFF0000 | jme->reg_pmcs);
-
+ jme_clear_pm(jme);
jme_phy_on(jme);
if (test_bit(JME_FLAG_SSET, &jme->flags))
jme_set_settings(netdev, &jme->old_ecmd);
diff --git a/drivers/net/jme.h b/drivers/net/jme.h
index e9aaeca..1481a62 100644
--- a/drivers/net/jme.h
+++ b/drivers/net/jme.h
@@ -24,6 +24,7 @@
#ifndef __JME_H_INCLUDED__
#define __JME_H_INCLUDED__
+#include <linux/interrupt.h>
#define DRV_NAME "jme"
#define DRV_VERSION "1.0.8"
@@ -851,6 +852,7 @@
* Power management control and status register
*/
enum jme_pmcs_bit_masks {
+ PMCS_STMASK = 0xFFFF0000,
PMCS_WF7DET = 0x80000000,
PMCS_WF6DET = 0x40000000,
PMCS_WF5DET = 0x20000000,
@@ -862,6 +864,7 @@
PMCS_LFDET = 0x00040000,
PMCS_LRDET = 0x00020000,
PMCS_MFDET = 0x00010000,
+ PMCS_ENMASK = 0x0000FFFF,
PMCS_WF7EN = 0x00008000,
PMCS_WF6EN = 0x00004000,
PMCS_WF5EN = 0x00002000,
diff --git a/drivers/net/ks8842.c b/drivers/net/ks8842.c
index fc12ac0..4a6ae05 100644
--- a/drivers/net/ks8842.c
+++ b/drivers/net/ks8842.c
@@ -23,6 +23,7 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
diff --git a/drivers/net/ks8851.c b/drivers/net/ks8851.c
index bcd9ba6..f56743a 100644
--- a/drivers/net/ks8851.c
+++ b/drivers/net/ks8851.c
@@ -13,6 +13,7 @@
#define DEBUG
+#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/netdevice.h>
diff --git a/drivers/net/ks8851_mll.c b/drivers/net/ks8851_mll.c
index 61631ca..a823782 100644
--- a/drivers/net/ks8851_mll.c
+++ b/drivers/net/ks8851_mll.c
@@ -23,6 +23,7 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/netdevice.h>
@@ -34,6 +35,7 @@
#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/slab.h>
+#include <asm/io.h>
#define DRV_NAME "ks8851_mll"
diff --git a/drivers/net/ksz884x.c b/drivers/net/ksz884x.c
index 41ea592..2ac6c6c 100644
--- a/drivers/net/ksz884x.c
+++ b/drivers/net/ksz884x.c
@@ -17,6 +17,7 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/ioport.h>
diff --git a/drivers/net/lib8390.c b/drivers/net/lib8390.c
index 17b75e5..05ae214 100644
--- a/drivers/net/lib8390.c
+++ b/drivers/net/lib8390.c
@@ -36,7 +36,7 @@
Paul Gortmaker : tweak ANK's above multicast changes a bit.
Paul Gortmaker : update packet statistics for v2.1.x
Alan Cox : support arbitrary stupid port mappings on the
- 68K Macintosh. Support >16bit I/O spaces
+ 68K Macintosh. Support >16bit I/O spaces
Paul Gortmaker : add kmod support for auto-loading of the 8390
module by all drivers that require it.
Alan Cox : Spinlocking work, added 'BUG_83C690'
@@ -58,8 +58,8 @@
#include <linux/string.h>
#include <linux/bitops.h>
#include <asm/system.h>
-#include <asm/uaccess.h>
-#include <asm/io.h>
+#include <linux/uaccess.h>
+#include <linux/io.h>
#include <asm/irq.h>
#include <linux/delay.h>
#include <linux/errno.h>
@@ -108,7 +108,6 @@
/* Index to functions. */
static void ei_tx_intr(struct net_device *dev);
static void ei_tx_err(struct net_device *dev);
-void ei_tx_timeout(struct net_device *dev);
static void ei_receive(struct net_device *dev);
static void ei_rx_overrun(struct net_device *dev);
@@ -206,19 +205,19 @@
struct ei_device *ei_local = netdev_priv(dev);
if (dev->watchdog_timeo <= 0)
- dev->watchdog_timeo = TX_TIMEOUT;
+ dev->watchdog_timeo = TX_TIMEOUT;
/*
* Grab the page lock so we own the register set, then call
* the init function.
*/
- spin_lock_irqsave(&ei_local->page_lock, flags);
+ spin_lock_irqsave(&ei_local->page_lock, flags);
__NS8390_init(dev, 1);
/* Set the flag before we drop the lock, That way the IRQ arrives
after its set and we get no silly warnings */
netif_start_queue(dev);
- spin_unlock_irqrestore(&ei_local->page_lock, flags);
+ spin_unlock_irqrestore(&ei_local->page_lock, flags);
ei_local->irqlock = 0;
return 0;
}
@@ -238,9 +237,9 @@
* Hold the page lock during close
*/
- spin_lock_irqsave(&ei_local->page_lock, flags);
+ spin_lock_irqsave(&ei_local->page_lock, flags);
__NS8390_init(dev, 0);
- spin_unlock_irqrestore(&ei_local->page_lock, flags);
+ spin_unlock_irqrestore(&ei_local->page_lock, flags);
netif_stop_queue(dev);
return 0;
}
@@ -267,12 +266,12 @@
isr = ei_inb(e8390_base+EN0_ISR);
spin_unlock_irqrestore(&ei_local->page_lock, flags);
- printk(KERN_DEBUG "%s: Tx timed out, %s TSR=%#2x, ISR=%#2x, t=%d.\n",
- dev->name, (txsr & ENTSR_ABT) ? "excess collisions." :
- (isr) ? "lost interrupt?" : "cable problem?", txsr, isr, tickssofar);
+ netdev_dbg(dev, "Tx timed out, %s TSR=%#2x, ISR=%#2x, t=%d\n",
+ (txsr & ENTSR_ABT) ? "excess collisions." :
+ (isr) ? "lost interrupt?" : "cable problem?",
+ txsr, isr, tickssofar);
- if (!isr && !dev->stats.tx_packets)
- {
+ if (!isr && !dev->stats.tx_packets) {
/* The 8390 probably hasn't gotten on the cable yet. */
ei_local->interface_num ^= 1; /* Try a different xcvr. */
}
@@ -344,27 +343,22 @@
* card, leaving a substantial gap between each transmitted packet.
*/
- if (ei_local->tx1 == 0)
- {
+ if (ei_local->tx1 == 0) {
output_page = ei_local->tx_start_page;
ei_local->tx1 = send_length;
if (ei_debug && ei_local->tx2 > 0)
- printk(KERN_DEBUG "%s: idle transmitter tx2=%d, lasttx=%d, txing=%d.\n",
- dev->name, ei_local->tx2, ei_local->lasttx, ei_local->txing);
- }
- else if (ei_local->tx2 == 0)
- {
+ netdev_dbg(dev, "idle transmitter tx2=%d, lasttx=%d, txing=%d\n",
+ ei_local->tx2, ei_local->lasttx, ei_local->txing);
+ } else if (ei_local->tx2 == 0) {
output_page = ei_local->tx_start_page + TX_PAGES/2;
ei_local->tx2 = send_length;
if (ei_debug && ei_local->tx1 > 0)
- printk(KERN_DEBUG "%s: idle transmitter, tx1=%d, lasttx=%d, txing=%d.\n",
- dev->name, ei_local->tx1, ei_local->lasttx, ei_local->txing);
- }
- else
- { /* We should never get here. */
+ netdev_dbg(dev, "idle transmitter, tx1=%d, lasttx=%d, txing=%d\n",
+ ei_local->tx1, ei_local->lasttx, ei_local->txing);
+ } else { /* We should never get here. */
if (ei_debug)
- printk(KERN_DEBUG "%s: No Tx buffers free! tx1=%d tx2=%d last=%d\n",
- dev->name, ei_local->tx1, ei_local->tx2, ei_local->lasttx);
+ netdev_dbg(dev, "No Tx buffers free! tx1=%d tx2=%d last=%d\n",
+ ei_local->tx1, ei_local->tx2, ei_local->lasttx);
ei_local->irqlock = 0;
netif_stop_queue(dev);
ei_outb_p(ENISR_ALL, e8390_base + EN0_IMR);
@@ -382,22 +376,18 @@
ei_block_output(dev, send_length, data, output_page);
- if (! ei_local->txing)
- {
+ if (!ei_local->txing) {
ei_local->txing = 1;
NS8390_trigger_send(dev, send_length, output_page);
- if (output_page == ei_local->tx_start_page)
- {
+ if (output_page == ei_local->tx_start_page) {
ei_local->tx1 = -1;
ei_local->lasttx = -1;
- }
- else
- {
+ } else {
ei_local->tx2 = -1;
ei_local->lasttx = -2;
}
- }
- else ei_local->txqueue++;
+ } else
+ ei_local->txqueue++;
if (ei_local->tx1 && ei_local->tx2)
netif_stop_queue(dev);
@@ -410,8 +400,8 @@
spin_unlock(&ei_local->page_lock);
enable_irq_lockdep_irqrestore(dev->irq, &flags);
-
- dev_kfree_skb (skb);
+ skb_tx_timestamp(skb);
+ dev_kfree_skb(skb);
dev->stats.tx_bytes += send_length;
return NETDEV_TX_OK;
@@ -442,15 +432,13 @@
spin_lock(&ei_local->page_lock);
- if (ei_local->irqlock)
- {
+ if (ei_local->irqlock) {
/*
* This might just be an interrupt for a PCI device sharing
* this line
*/
- printk("%s: Interrupted while interrupts are masked!"
- " isr=%#2x imr=%#2x.\n",
- dev->name, ei_inb_p(e8390_base + EN0_ISR),
+ netdev_err(dev, "Interrupted while interrupts are masked! isr=%#2x imr=%#2x\n",
+ ei_inb_p(e8390_base + EN0_ISR),
ei_inb_p(e8390_base + EN0_IMR));
spin_unlock(&ei_local->page_lock);
return IRQ_NONE;
@@ -459,15 +447,14 @@
/* Change to page 0 and read the intr status reg. */
ei_outb_p(E8390_NODMA+E8390_PAGE0, e8390_base + E8390_CMD);
if (ei_debug > 3)
- printk(KERN_DEBUG "%s: interrupt(isr=%#2.2x).\n", dev->name,
+ netdev_dbg(dev, "interrupt(isr=%#2.2x)\n",
ei_inb_p(e8390_base + EN0_ISR));
/* !!Assumption!! -- we stay in page 0. Don't break this. */
while ((interrupts = ei_inb_p(e8390_base + EN0_ISR)) != 0 &&
- ++nr_serviced < MAX_SERVICE)
- {
+ ++nr_serviced < MAX_SERVICE) {
if (!netif_running(dev)) {
- printk(KERN_WARNING "%s: interrupt from stopped card\n", dev->name);
+ netdev_warn(dev, "interrupt from stopped card\n");
/* rmk - acknowledge the interrupts */
ei_outb_p(interrupts, e8390_base + EN0_ISR);
interrupts = 0;
@@ -475,8 +462,7 @@
}
if (interrupts & ENISR_OVER)
ei_rx_overrun(dev);
- else if (interrupts & (ENISR_RX+ENISR_RX_ERR))
- {
+ else if (interrupts & (ENISR_RX+ENISR_RX_ERR)) {
/* Got a good (?) packet. */
ei_receive(dev);
}
@@ -486,35 +472,30 @@
else if (interrupts & ENISR_TX_ERR)
ei_tx_err(dev);
- if (interrupts & ENISR_COUNTERS)
- {
+ if (interrupts & ENISR_COUNTERS) {
dev->stats.rx_frame_errors += ei_inb_p(e8390_base + EN0_COUNTER0);
dev->stats.rx_crc_errors += ei_inb_p(e8390_base + EN0_COUNTER1);
- dev->stats.rx_missed_errors+= ei_inb_p(e8390_base + EN0_COUNTER2);
+ dev->stats.rx_missed_errors += ei_inb_p(e8390_base + EN0_COUNTER2);
ei_outb_p(ENISR_COUNTERS, e8390_base + EN0_ISR); /* Ack intr. */
}
/* Ignore any RDC interrupts that make it back to here. */
if (interrupts & ENISR_RDC)
- {
ei_outb_p(ENISR_RDC, e8390_base + EN0_ISR);
- }
ei_outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, e8390_base + E8390_CMD);
}
- if (interrupts && ei_debug)
- {
+ if (interrupts && ei_debug) {
ei_outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, e8390_base + E8390_CMD);
- if (nr_serviced >= MAX_SERVICE)
- {
+ if (nr_serviced >= MAX_SERVICE) {
/* 0xFF is valid for a card removal */
- if(interrupts!=0xFF)
- printk(KERN_WARNING "%s: Too much work at interrupt, status %#2.2x\n",
- dev->name, interrupts);
+ if (interrupts != 0xFF)
+ netdev_warn(dev, "Too much work at interrupt, status %#2.2x\n",
+ interrupts);
ei_outb_p(ENISR_ALL, e8390_base + EN0_ISR); /* Ack. most intrs. */
} else {
- printk(KERN_WARNING "%s: unknown interrupt %#2x\n", dev->name, interrupts);
+ netdev_warn(dev, "unknown interrupt %#2x\n", interrupts);
ei_outb_p(0xff, e8390_base + EN0_ISR); /* Ack. all intrs. */
}
}
@@ -554,30 +535,32 @@
unsigned char tx_was_aborted = txsr & (ENTSR_ABT+ENTSR_FU);
#ifdef VERBOSE_ERROR_DUMP
- printk(KERN_DEBUG "%s: transmitter error (%#2x): ", dev->name, txsr);
+ netdev_dbg(dev, "transmitter error (%#2x):", txsr);
if (txsr & ENTSR_ABT)
- printk("excess-collisions ");
+ pr_cont(" excess-collisions ");
if (txsr & ENTSR_ND)
- printk("non-deferral ");
+ pr_cont(" non-deferral ");
if (txsr & ENTSR_CRS)
- printk("lost-carrier ");
+ pr_cont(" lost-carrier ");
if (txsr & ENTSR_FU)
- printk("FIFO-underrun ");
+ pr_cont(" FIFO-underrun ");
if (txsr & ENTSR_CDH)
- printk("lost-heartbeat ");
- printk("\n");
+ pr_cont(" lost-heartbeat ");
+ pr_cont("\n");
#endif
ei_outb_p(ENISR_TX_ERR, e8390_base + EN0_ISR); /* Ack intr. */
if (tx_was_aborted)
ei_tx_intr(dev);
- else
- {
+ else {
dev->stats.tx_errors++;
- if (txsr & ENTSR_CRS) dev->stats.tx_carrier_errors++;
- if (txsr & ENTSR_CDH) dev->stats.tx_heartbeat_errors++;
- if (txsr & ENTSR_OWC) dev->stats.tx_window_errors++;
+ if (txsr & ENTSR_CRS)
+ dev->stats.tx_carrier_errors++;
+ if (txsr & ENTSR_CDH)
+ dev->stats.tx_heartbeat_errors++;
+ if (txsr & ENTSR_OWC)
+ dev->stats.tx_window_errors++;
}
}
@@ -603,52 +586,45 @@
*/
ei_local->txqueue--;
- if (ei_local->tx1 < 0)
- {
+ if (ei_local->tx1 < 0) {
if (ei_local->lasttx != 1 && ei_local->lasttx != -1)
- printk(KERN_ERR "%s: bogus last_tx_buffer %d, tx1=%d.\n",
- ei_local->name, ei_local->lasttx, ei_local->tx1);
+ pr_err("%s: bogus last_tx_buffer %d, tx1=%d\n",
+ ei_local->name, ei_local->lasttx, ei_local->tx1);
ei_local->tx1 = 0;
- if (ei_local->tx2 > 0)
- {
+ if (ei_local->tx2 > 0) {
ei_local->txing = 1;
NS8390_trigger_send(dev, ei_local->tx2, ei_local->tx_start_page + 6);
dev->trans_start = jiffies;
ei_local->tx2 = -1,
ei_local->lasttx = 2;
- }
- else ei_local->lasttx = 20, ei_local->txing = 0;
- }
- else if (ei_local->tx2 < 0)
- {
+ } else
+ ei_local->lasttx = 20, ei_local->txing = 0;
+ } else if (ei_local->tx2 < 0) {
if (ei_local->lasttx != 2 && ei_local->lasttx != -2)
- printk("%s: bogus last_tx_buffer %d, tx2=%d.\n",
- ei_local->name, ei_local->lasttx, ei_local->tx2);
+ pr_err("%s: bogus last_tx_buffer %d, tx2=%d\n",
+ ei_local->name, ei_local->lasttx, ei_local->tx2);
ei_local->tx2 = 0;
- if (ei_local->tx1 > 0)
- {
+ if (ei_local->tx1 > 0) {
ei_local->txing = 1;
NS8390_trigger_send(dev, ei_local->tx1, ei_local->tx_start_page);
dev->trans_start = jiffies;
ei_local->tx1 = -1;
ei_local->lasttx = 1;
- }
- else
+ } else
ei_local->lasttx = 10, ei_local->txing = 0;
- }
-// else printk(KERN_WARNING "%s: unexpected TX-done interrupt, lasttx=%d.\n",
-// dev->name, ei_local->lasttx);
+ } /* else
+ netdev_warn(dev, "unexpected TX-done interrupt, lasttx=%d\n",
+ ei_local->lasttx);
+*/
/* Minimize Tx latency: update the statistics after we restart TXing. */
if (status & ENTSR_COL)
dev->stats.collisions++;
if (status & ENTSR_PTX)
dev->stats.tx_packets++;
- else
- {
+ else {
dev->stats.tx_errors++;
- if (status & ENTSR_ABT)
- {
+ if (status & ENTSR_ABT) {
dev->stats.tx_aborted_errors++;
dev->stats.collisions += 16;
}
@@ -682,8 +658,7 @@
struct e8390_pkt_hdr rx_frame;
int num_rx_pages = ei_local->stop_page-ei_local->rx_start_page;
- while (++rx_pkt_count < 10)
- {
+ while (++rx_pkt_count < 10) {
int pkt_len, pkt_stat;
/* Get the rx page (incoming packet pointer). */
@@ -702,9 +677,11 @@
Keep quiet if it looks like a card removal. One problem here
is that some clones crash in roughly the same way.
*/
- if (ei_debug > 0 && this_frame != ei_local->current_page && (this_frame!=0x0 || rxing_page!=0xFF))
- printk(KERN_ERR "%s: mismatched read page pointers %2x vs %2x.\n",
- dev->name, this_frame, ei_local->current_page);
+ if (ei_debug > 0 &&
+ this_frame != ei_local->current_page &&
+ (this_frame != 0x0 || rxing_page != 0xFF))
+ netdev_err(dev, "mismatched read page pointers %2x vs %2x\n",
+ this_frame, ei_local->current_page);
if (this_frame == rxing_page) /* Read all the frames? */
break; /* Done for now */
@@ -730,46 +707,39 @@
continue;
}
- if (pkt_len < 60 || pkt_len > 1518)
- {
+ if (pkt_len < 60 || pkt_len > 1518) {
if (ei_debug)
- printk(KERN_DEBUG "%s: bogus packet size: %d, status=%#2x nxpg=%#2x.\n",
- dev->name, rx_frame.count, rx_frame.status,
+ netdev_dbg(dev, "bogus packet size: %d, status=%#2x nxpg=%#2x\n",
+ rx_frame.count, rx_frame.status,
rx_frame.next);
dev->stats.rx_errors++;
dev->stats.rx_length_errors++;
- }
- else if ((pkt_stat & 0x0F) == ENRSR_RXOK)
- {
+ } else if ((pkt_stat & 0x0F) == ENRSR_RXOK) {
struct sk_buff *skb;
skb = dev_alloc_skb(pkt_len+2);
- if (skb == NULL)
- {
+ if (skb == NULL) {
if (ei_debug > 1)
- printk(KERN_DEBUG "%s: Couldn't allocate a sk_buff of size %d.\n",
- dev->name, pkt_len);
+ netdev_dbg(dev, "Couldn't allocate a sk_buff of size %d\n",
+ pkt_len);
dev->stats.rx_dropped++;
break;
- }
- else
- {
- skb_reserve(skb,2); /* IP headers on 16 byte boundaries */
+ } else {
+ skb_reserve(skb, 2); /* IP headers on 16 byte boundaries */
skb_put(skb, pkt_len); /* Make room */
ei_block_input(dev, pkt_len, skb, current_offset + sizeof(rx_frame));
- skb->protocol=eth_type_trans(skb,dev);
- netif_rx(skb);
+ skb->protocol = eth_type_trans(skb, dev);
+ if (!skb_defer_rx_timestamp(skb))
+ netif_rx(skb);
dev->stats.rx_packets++;
dev->stats.rx_bytes += pkt_len;
if (pkt_stat & ENRSR_PHY)
dev->stats.multicast++;
}
- }
- else
- {
+ } else {
if (ei_debug)
- printk(KERN_DEBUG "%s: bogus packet: status=%#2x nxpg=%#2x size=%d\n",
- dev->name, rx_frame.status, rx_frame.next,
+ netdev_dbg(dev, "bogus packet: status=%#2x nxpg=%#2x size=%d\n",
+ rx_frame.status, rx_frame.next,
rx_frame.count);
dev->stats.rx_errors++;
/* NB: The NIC counts CRC, frame and missed errors. */
@@ -780,8 +750,8 @@
/* This _should_ never happen: it's here for avoiding bad clones. */
if (next_frame >= ei_local->stop_page) {
- printk("%s: next frame inconsistency, %#2x\n", dev->name,
- next_frame);
+ netdev_notice(dev, "next frame inconsistency, %#2x\n",
+ next_frame);
next_frame = ei_local->rx_start_page;
}
ei_local->current_page = next_frame;
@@ -821,7 +791,7 @@
ei_outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, e8390_base+E8390_CMD);
if (ei_debug > 1)
- printk(KERN_DEBUG "%s: Receiver overrun.\n", dev->name);
+ netdev_dbg(dev, "Receiver overrun\n");
dev->stats.rx_over_errors++;
/*
@@ -844,8 +814,7 @@
* step is vital, and skipping it will cause no end of havoc.
*/
- if (was_txing)
- {
+ if (was_txing) {
unsigned char tx_completed = ei_inb_p(e8390_base+EN0_ISR) & (ENISR_TX+ENISR_TX_ERR);
if (!tx_completed)
must_resend = 1;
@@ -869,7 +838,7 @@
*/
ei_outb_p(E8390_TXCONFIG, e8390_base + EN0_TXCR);
if (must_resend)
- ei_outb_p(E8390_NODMA + E8390_PAGE0 + E8390_START + E8390_TRANS, e8390_base + E8390_CMD);
+ ei_outb_p(E8390_NODMA + E8390_PAGE0 + E8390_START + E8390_TRANS, e8390_base + E8390_CMD);
}
/*
@@ -886,11 +855,11 @@
if (!netif_running(dev))
return &dev->stats;
- spin_lock_irqsave(&ei_local->page_lock,flags);
+ spin_lock_irqsave(&ei_local->page_lock, flags);
/* Read the counter registers, assuming we are in page 0. */
- dev->stats.rx_frame_errors += ei_inb_p(ioaddr + EN0_COUNTER0);
- dev->stats.rx_crc_errors += ei_inb_p(ioaddr + EN0_COUNTER1);
- dev->stats.rx_missed_errors+= ei_inb_p(ioaddr + EN0_COUNTER2);
+ dev->stats.rx_frame_errors += ei_inb_p(ioaddr + EN0_COUNTER0);
+ dev->stats.rx_crc_errors += ei_inb_p(ioaddr + EN0_COUNTER1);
+ dev->stats.rx_missed_errors += ei_inb_p(ioaddr + EN0_COUNTER2);
spin_unlock_irqrestore(&ei_local->page_lock, flags);
return &dev->stats;
@@ -929,13 +898,11 @@
int i;
struct ei_device *ei_local = netdev_priv(dev);
- if (!(dev->flags&(IFF_PROMISC|IFF_ALLMULTI)))
- {
+ if (!(dev->flags&(IFF_PROMISC|IFF_ALLMULTI))) {
memset(ei_local->mcfilter, 0, 8);
if (!netdev_mc_empty(dev))
make_mc_bits(ei_local->mcfilter, dev);
- }
- else
+ } else
memset(ei_local->mcfilter, 0xFF, 8); /* mcast set to accept-all */
/*
@@ -954,23 +921,23 @@
if (netif_running(dev))
ei_outb_p(E8390_RXCONFIG, e8390_base + EN0_RXCR);
ei_outb_p(E8390_NODMA + E8390_PAGE1, e8390_base + E8390_CMD);
- for(i = 0; i < 8; i++)
- {
+ for (i = 0; i < 8; i++) {
ei_outb_p(ei_local->mcfilter[i], e8390_base + EN1_MULT_SHIFT(i));
#ifndef BUG_83C690
- if(ei_inb_p(e8390_base + EN1_MULT_SHIFT(i))!=ei_local->mcfilter[i])
- printk(KERN_ERR "Multicast filter read/write mismap %d\n",i);
+ if (ei_inb_p(e8390_base + EN1_MULT_SHIFT(i)) != ei_local->mcfilter[i])
+ netdev_err(dev, "Multicast filter read/write mismap %d\n",
+ i);
#endif
}
ei_outb_p(E8390_NODMA + E8390_PAGE0, e8390_base + E8390_CMD);
- if(dev->flags&IFF_PROMISC)
- ei_outb_p(E8390_RXCONFIG | 0x18, e8390_base + EN0_RXCR);
+ if (dev->flags&IFF_PROMISC)
+ ei_outb_p(E8390_RXCONFIG | 0x18, e8390_base + EN0_RXCR);
else if (dev->flags & IFF_ALLMULTI || !netdev_mc_empty(dev))
- ei_outb_p(E8390_RXCONFIG | 0x08, e8390_base + EN0_RXCR);
- else
- ei_outb_p(E8390_RXCONFIG, e8390_base + EN0_RXCR);
- }
+ ei_outb_p(E8390_RXCONFIG | 0x08, e8390_base + EN0_RXCR);
+ else
+ ei_outb_p(E8390_RXCONFIG, e8390_base + EN0_RXCR);
+}
/*
* Called without lock held. This is invoked from user context and may
@@ -1042,8 +1009,8 @@
? (0x48 | ENDCFG_WTS | (ei_local->bigendian ? ENDCFG_BOS : 0))
: 0x48;
- if(sizeof(struct e8390_pkt_hdr)!=4)
- panic("8390.c: header struct mispacked\n");
+ if (sizeof(struct e8390_pkt_hdr) != 4)
+ panic("8390.c: header struct mispacked\n");
/* Follow National Semi's recommendations for initing the DP83902. */
ei_outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, e8390_base+E8390_CMD); /* 0x21 */
ei_outb_p(endcfg, e8390_base + EN0_DCFG); /* 0x48 or 0x49 */
@@ -1067,11 +1034,11 @@
/* Copy the station address into the DS8390 registers. */
ei_outb_p(E8390_NODMA + E8390_PAGE1 + E8390_STOP, e8390_base+E8390_CMD); /* 0x61 */
- for(i = 0; i < 6; i++)
- {
+ for (i = 0; i < 6; i++) {
ei_outb_p(dev->dev_addr[i], e8390_base + EN1_PHYS_SHIFT(i));
- if (ei_debug > 1 && ei_inb_p(e8390_base + EN1_PHYS_SHIFT(i))!=dev->dev_addr[i])
- printk(KERN_ERR "Hw. address read/write mismap %d\n",i);
+ if (ei_debug > 1 &&
+ ei_inb_p(e8390_base + EN1_PHYS_SHIFT(i)) != dev->dev_addr[i])
+ netdev_err(dev, "Hw. address read/write mismap %d\n", i);
}
ei_outb_p(ei_local->rx_start_page, e8390_base + EN1_CURPAG);
@@ -1080,8 +1047,7 @@
ei_local->tx1 = ei_local->tx2 = 0;
ei_local->txing = 0;
- if (startp)
- {
+ if (startp) {
ei_outb_p(0xff, e8390_base + EN0_ISR);
ei_outb_p(ENISR_ALL, e8390_base + EN0_IMR);
ei_outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, e8390_base+E8390_CMD);
@@ -1099,14 +1065,12 @@
int start_page)
{
unsigned long e8390_base = dev->base_addr;
- struct ei_device *ei_local __attribute((unused)) = netdev_priv(dev);
+ struct ei_device *ei_local __attribute((unused)) = netdev_priv(dev);
ei_outb_p(E8390_NODMA+E8390_PAGE0, e8390_base+E8390_CMD);
- if (ei_inb_p(e8390_base + E8390_CMD) & E8390_TRANS)
- {
- printk(KERN_WARNING "%s: trigger_send() called with the transmitter busy.\n",
- dev->name);
+ if (ei_inb_p(e8390_base + E8390_CMD) & E8390_TRANS) {
+ netdev_warn(dev, "trigger_send() called with the transmitter busy\n");
return;
}
ei_outb_p(length & 0xff, e8390_base + EN0_TCNTLO);
diff --git a/drivers/net/ll_temac_main.c b/drivers/net/ll_temac_main.c
index b7948cc..728fe41 100644
--- a/drivers/net/ll_temac_main.c
+++ b/drivers/net/ll_temac_main.c
@@ -48,6 +48,8 @@
#include <linux/io.h>
#include <linux/ip.h>
#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/dma-mapping.h>
#include "ll_temac.h"
@@ -727,6 +729,8 @@
if (lp->tx_bd_tail >= TX_BD_NUM)
lp->tx_bd_tail = 0;
+ skb_tx_timestamp(skb);
+
/* Kick off the transfer */
lp->dma_out(lp, TX_TAILDESC_PTR, tail_p); /* DMA start */
@@ -772,7 +776,8 @@
skb->ip_summed = CHECKSUM_COMPLETE;
}
- netif_rx(skb);
+ if (!skb_defer_rx_timestamp(skb))
+ netif_rx(skb);
ndev->stats.rx_packets++;
ndev->stats.rx_bytes += length;
diff --git a/drivers/net/lne390.c b/drivers/net/lne390.c
index 8a1097c..f9888d2 100644
--- a/drivers/net/lne390.c
+++ b/drivers/net/lne390.c
@@ -41,6 +41,7 @@
#include <linux/string.h>
#include <linux/delay.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
diff --git a/drivers/net/macb.c b/drivers/net/macb.c
index 6c6a028..dcf6011 100644
--- a/drivers/net/macb.c
+++ b/drivers/net/macb.c
@@ -15,6 +15,7 @@
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/dma-mapping.h>
@@ -669,6 +670,8 @@
entry = NEXT_TX(entry);
bp->tx_head = entry;
+ skb_tx_timestamp(skb);
+
macb_writel(bp, NCR, macb_readl(bp, NCR) | MACB_BIT(TSTART));
if (TX_BUFFS_AVAIL(bp) < 1)
diff --git a/drivers/net/mace.c b/drivers/net/mace.c
index 1c5221f..2074e97 100644
--- a/drivers/net/mace.c
+++ b/drivers/net/mace.c
@@ -13,6 +13,7 @@
#include <linux/string.h>
#include <linux/timer.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/crc32.h>
#include <linux/spinlock.h>
#include <linux/bitrev.h>
diff --git a/drivers/net/macmace.c b/drivers/net/macmace.c
index c685a46..4286e67 100644
--- a/drivers/net/macmace.c
+++ b/drivers/net/macmace.c
@@ -221,7 +221,7 @@
SET_NETDEV_DEV(dev, &pdev->dev);
dev->base_addr = (u32)MACE_BASE;
- mp->mace = (volatile struct mace *) MACE_BASE;
+ mp->mace = MACE_BASE;
dev->irq = IRQ_MAC_MACE;
mp->dma_intr = IRQ_MAC_MACE_DMA;
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index d6aeaa5..cc67cbe 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -414,7 +414,8 @@
#define MACVLAN_FEATURES \
(NETIF_F_SG | NETIF_F_ALL_CSUM | NETIF_F_HIGHDMA | NETIF_F_FRAGLIST | \
NETIF_F_GSO | NETIF_F_TSO | NETIF_F_UFO | NETIF_F_GSO_ROBUST | \
- NETIF_F_TSO_ECN | NETIF_F_TSO6 | NETIF_F_GRO | NETIF_F_RXCSUM)
+ NETIF_F_TSO_ECN | NETIF_F_TSO6 | NETIF_F_GRO | NETIF_F_RXCSUM | \
+ NETIF_F_HW_VLAN_FILTER)
#define MACVLAN_STATE_MASK \
((1<<__LINK_STATE_NOCARRIER) | (1<<__LINK_STATE_DORMANT))
@@ -509,6 +510,39 @@
return stats;
}
+static void macvlan_vlan_rx_register(struct net_device *dev,
+ struct vlan_group *grp)
+{
+ struct macvlan_dev *vlan = netdev_priv(dev);
+ struct net_device *lowerdev = vlan->lowerdev;
+ const struct net_device_ops *ops = lowerdev->netdev_ops;
+
+ if (ops->ndo_vlan_rx_register)
+ ops->ndo_vlan_rx_register(lowerdev, grp);
+}
+
+static void macvlan_vlan_rx_add_vid(struct net_device *dev,
+ unsigned short vid)
+{
+ struct macvlan_dev *vlan = netdev_priv(dev);
+ struct net_device *lowerdev = vlan->lowerdev;
+ const struct net_device_ops *ops = lowerdev->netdev_ops;
+
+ if (ops->ndo_vlan_rx_add_vid)
+ ops->ndo_vlan_rx_add_vid(lowerdev, vid);
+}
+
+static void macvlan_vlan_rx_kill_vid(struct net_device *dev,
+ unsigned short vid)
+{
+ struct macvlan_dev *vlan = netdev_priv(dev);
+ struct net_device *lowerdev = vlan->lowerdev;
+ const struct net_device_ops *ops = lowerdev->netdev_ops;
+
+ if (ops->ndo_vlan_rx_kill_vid)
+ ops->ndo_vlan_rx_kill_vid(lowerdev, vid);
+}
+
static void macvlan_ethtool_get_drvinfo(struct net_device *dev,
struct ethtool_drvinfo *drvinfo)
{
@@ -541,6 +575,9 @@
.ndo_set_multicast_list = macvlan_set_multicast_list,
.ndo_get_stats64 = macvlan_dev_get_stats64,
.ndo_validate_addr = eth_validate_addr,
+ .ndo_vlan_rx_register = macvlan_vlan_rx_register,
+ .ndo_vlan_rx_add_vid = macvlan_vlan_rx_add_vid,
+ .ndo_vlan_rx_kill_vid = macvlan_vlan_rx_kill_vid,
};
void macvlan_common_setup(struct net_device *dev)
diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c
index 6696e56..ecee0fe 100644
--- a/drivers/net/macvtap.c
+++ b/drivers/net/macvtap.c
@@ -508,6 +508,8 @@
vnet_hdr->flags = VIRTIO_NET_HDR_F_NEEDS_CSUM;
vnet_hdr->csum_start = skb_checksum_start_offset(skb);
vnet_hdr->csum_offset = skb->csum_offset;
+ } else if (skb->ip_summed == CHECKSUM_UNNECESSARY) {
+ vnet_hdr->flags = VIRTIO_NET_HDR_F_DATA_VALID;
} /* else everything is zero */
return 0;
diff --git a/drivers/net/mipsnet.c b/drivers/net/mipsnet.c
index 869f0ea..004e64a 100644
--- a/drivers/net/mipsnet.c
+++ b/drivers/net/mipsnet.c
@@ -5,6 +5,7 @@
*/
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/module.h>
diff --git a/drivers/net/mlx4/en_rx.c b/drivers/net/mlx4/en_rx.c
index 277215f..5197b50 100644
--- a/drivers/net/mlx4/en_rx.c
+++ b/drivers/net/mlx4/en_rx.c
@@ -859,7 +859,7 @@
priv->rx_ring[0].cqn, &context);
ptr = ((void *) &context) + 0x3c;
- rss_context = (struct mlx4_en_rss_context *) ptr;
+ rss_context = ptr;
rss_context->base_qpn = cpu_to_be32(ilog2(priv->rx_ring_num) << 24 |
(rss_map->base_qpn));
rss_context->default_qpn = cpu_to_be32(rss_map->base_qpn);
diff --git a/drivers/net/mlx4/en_tx.c b/drivers/net/mlx4/en_tx.c
index b229acf..6e03de0 100644
--- a/drivers/net/mlx4/en_tx.c
+++ b/drivers/net/mlx4/en_tx.c
@@ -238,8 +238,7 @@
} else {
if (!tx_info->inl) {
if ((void *) data >= end) {
- data = (struct mlx4_wqe_data_seg *)
- (ring->buf + ((void *) data - end));
+ data = ring->buf + ((void *)data - end);
}
if (tx_info->linear) {
@@ -253,7 +252,7 @@
for (i = 0; i < frags; i++) {
/* Check for wraparound before unmapping */
if ((void *) data >= end)
- data = (struct mlx4_wqe_data_seg *) ring->buf;
+ data = ring->buf;
frag = &skb_shinfo(skb)->frags[i];
pci_unmap_page(mdev->pdev,
(dma_addr_t) be64_to_cpu(data->addr),
diff --git a/drivers/net/mlx4/main.c b/drivers/net/mlx4/main.c
index 3814fc9..0cb0431 100644
--- a/drivers/net/mlx4/main.c
+++ b/drivers/net/mlx4/main.c
@@ -1230,11 +1230,11 @@
INIT_LIST_HEAD(&priv->pgdir_list);
mutex_init(&priv->pgdir_mutex);
- pci_read_config_byte(pdev, PCI_REVISION_ID, &dev->rev_id);
-
INIT_LIST_HEAD(&priv->bf_list);
mutex_init(&priv->bf_mutex);
+ dev->rev_id = pdev->revision;
+
/*
* Now reset the HCA before we touch the PCI capabilities or
* attempt a firmware command, since a boot ROM may have left
diff --git a/drivers/net/mlx4/reset.c b/drivers/net/mlx4/reset.c
index e5741da..11e7c1c 100644
--- a/drivers/net/mlx4/reset.c
+++ b/drivers/net/mlx4/reset.c
@@ -77,7 +77,7 @@
goto out;
}
- pcie_cap = pci_find_capability(dev->pdev, PCI_CAP_ID_EXP);
+ pcie_cap = pci_pcie_cap(dev->pdev);
for (i = 0; i < 64; ++i) {
if (i == 22 || i == 23)
diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c
index a5d9b1c..77dc6ab 100644
--- a/drivers/net/mv643xx_eth.c
+++ b/drivers/net/mv643xx_eth.c
@@ -840,6 +840,8 @@
__skb_queue_tail(&txq->tx_skb, skb);
+ skb_tx_timestamp(skb);
+
/* ensure all other descriptors are written before first cmd_sts */
wmb();
desc->cmd_sts = cmd_sts;
@@ -859,7 +861,7 @@
static netdev_tx_t mv643xx_eth_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct mv643xx_eth_private *mp = netdev_priv(dev);
- int queue;
+ int length, queue;
struct tx_queue *txq;
struct netdev_queue *nq;
@@ -881,10 +883,12 @@
return NETDEV_TX_OK;
}
+ length = skb->len;
+
if (!txq_submit_skb(txq, skb)) {
int entries_left;
- txq->tx_bytes += skb->len;
+ txq->tx_bytes += length;
txq->tx_packets++;
entries_left = txq->tx_ring_size - txq->tx_desc_count;
diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c
index bf84849..1d22475 100644
--- a/drivers/net/myri10ge/myri10ge.c
+++ b/drivers/net/myri10ge/myri10ge.c
@@ -1,7 +1,7 @@
/*************************************************************************
* myri10ge.c: Myricom Myri-10G Ethernet driver.
*
- * Copyright (C) 2005 - 2009 Myricom, Inc.
+ * Copyright (C) 2005 - 2011 Myricom, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -79,7 +79,7 @@
#include "myri10ge_mcp.h"
#include "myri10ge_mcp_gen_header.h"
-#define MYRI10GE_VERSION_STR "1.5.2-1.459"
+#define MYRI10GE_VERSION_STR "1.5.3-1.534"
MODULE_DESCRIPTION("Myricom 10G driver (10GbE)");
MODULE_AUTHOR("Maintainer: help@myri.com");
@@ -193,6 +193,7 @@
int watchdog_tx_done;
int watchdog_tx_req;
int watchdog_rx_done;
+ int stuck;
#ifdef CONFIG_MYRI10GE_DCA
int cached_dca_tag;
int cpu;
@@ -210,7 +211,6 @@
int big_bytes;
int max_intr_slots;
struct net_device *dev;
- spinlock_t stats_lock;
u8 __iomem *sram;
int sram_size;
unsigned long board_span;
@@ -377,7 +377,8 @@
__raw_writel((__force __u32) val, (__force void __iomem *)p);
}
-static struct net_device_stats *myri10ge_get_stats(struct net_device *dev);
+static struct rtnl_link_stats64 *myri10ge_get_stats(struct net_device *dev,
+ struct rtnl_link_stats64 *stats);
static void set_fw_name(struct myri10ge_priv *mgp, char *name, bool allocated)
{
@@ -1013,7 +1014,7 @@
cmd.data2 = i;
status |= myri10ge_send_cmd(mgp, MXGEFW_CMD_SET_INTRQ_DMA,
&cmd, 0);
- };
+ }
status |=
myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_IRQ_ACK_OFFSET, &cmd, 0);
@@ -1080,11 +1081,14 @@
int ret, cap, err;
u16 ctl;
- cap = pci_find_capability(pdev, PCI_CAP_ID_EXP);
+ cap = pci_pcie_cap(pdev);
if (!cap)
return 0;
err = pci_read_config_word(pdev, cap + PCI_EXP_DEVCTL, &ctl);
+ if (err)
+ return 0;
+
ret = (ctl & PCI_EXP_DEVCTL_RELAX_EN) >> 4;
if (ret != on) {
ctl &= ~PCI_EXP_DEVCTL_RELAX_EN;
@@ -1139,20 +1143,19 @@
mgp->ss[i].cpu = -1;
mgp->ss[i].cached_dca_tag = -1;
myri10ge_update_dca(&mgp->ss[i]);
- }
+ }
}
static void myri10ge_teardown_dca(struct myri10ge_priv *mgp)
{
struct pci_dev *pdev = mgp->pdev;
- int err;
if (!mgp->dca_enabled)
return;
mgp->dca_enabled = 0;
if (mgp->relaxed_order)
myri10ge_toggle_relaxed(pdev, 1);
- err = dca_remove_requester(&pdev->dev);
+ dca_remove_requester(&pdev->dev);
}
static int myri10ge_notify_dca_device(struct device *dev, void *data)
@@ -1313,7 +1316,7 @@
static inline int
myri10ge_rx_done(struct myri10ge_slice_state *ss, int len, __wsum csum,
- int lro_enabled)
+ bool lro_enabled)
{
struct myri10ge_priv *mgp = ss->mgp;
struct sk_buff *skb;
@@ -1461,7 +1464,8 @@
/* start the queue if we've stopped it */
if (netif_tx_queue_stopped(dev_queue) &&
- tx->req - tx->done < (tx->mask >> 1)) {
+ tx->req - tx->done < (tx->mask >> 1) &&
+ ss->mgp->running == MYRI10GE_ETH_RUNNING) {
tx->wake_queue++;
netif_tx_wake_queue(dev_queue);
}
@@ -1472,11 +1476,9 @@
{
struct myri10ge_rx_done *rx_done = &ss->rx_done;
struct myri10ge_priv *mgp = ss->mgp;
-
unsigned long rx_bytes = 0;
unsigned long rx_packets = 0;
unsigned long rx_ok;
-
int idx = rx_done->idx;
int cnt = rx_done->cnt;
int work_done = 0;
@@ -1529,16 +1531,14 @@
mgp->link_state = link_up;
if (mgp->link_state == MXGEFW_LINK_UP) {
- if (netif_msg_link(mgp))
- netdev_info(mgp->dev, "link up\n");
+ netif_info(mgp, link, mgp->dev, "link up\n");
netif_carrier_on(mgp->dev);
mgp->link_changes++;
} else {
- if (netif_msg_link(mgp))
- netdev_info(mgp->dev, "link %s\n",
- link_up == MXGEFW_LINK_MYRINET ?
+ netif_info(mgp, link, mgp->dev, "link %s\n",
+ (link_up == MXGEFW_LINK_MYRINET ?
"mismatch (Myrinet detected)" :
- "down");
+ "down"));
netif_carrier_off(mgp->dev);
mgp->link_changes++;
}
@@ -1619,7 +1619,7 @@
if (send_done_count != tx->pkt_done)
myri10ge_tx_done(ss, (int)send_done_count);
if (unlikely(i > myri10ge_max_irq_loops)) {
- netdev_err(mgp->dev, "irq stuck?\n");
+ netdev_warn(mgp->dev, "irq stuck?\n");
stats->valid = 0;
schedule_work(&mgp->watchdog_work);
}
@@ -1783,9 +1783,8 @@
"----------- slice ---------",
"tx_pkt_start", "tx_pkt_done", "tx_req", "tx_done",
"rx_small_cnt", "rx_big_cnt",
- "wake_queue", "stop_queue", "tx_linearized", "LRO aggregated",
- "LRO flushed",
- "LRO avg aggr", "LRO no_desc"
+ "wake_queue", "stop_queue", "tx_linearized",
+ "LRO aggregated", "LRO flushed", "LRO avg aggr", "LRO no_desc",
};
#define MYRI10GE_NET_STATS_LEN 21
@@ -1831,13 +1830,15 @@
{
struct myri10ge_priv *mgp = netdev_priv(netdev);
struct myri10ge_slice_state *ss;
+ struct rtnl_link_stats64 link_stats;
int slice;
int i;
/* force stats update */
- (void)myri10ge_get_stats(netdev);
+ memset(&link_stats, 0, sizeof(link_stats));
+ (void)myri10ge_get_stats(netdev, &link_stats);
for (i = 0; i < MYRI10GE_NET_STATS_LEN; i++)
- data[i] = ((unsigned long *)&netdev->stats)[i];
+ data[i] = ((u64 *)&link_stats)[i];
data[i++] = (unsigned int)mgp->tx_boundary;
data[i++] = (unsigned int)mgp->wc_enabled;
@@ -1907,6 +1908,60 @@
return mgp->msg_enable;
}
+/*
+ * Use a low-level command to change the LED behavior. Rather than
+ * blinking (which is the normal case), when identify is used, the
+ * yellow LED turns solid.
+ */
+static int myri10ge_led(struct myri10ge_priv *mgp, int on)
+{
+ struct mcp_gen_header *hdr;
+ struct device *dev = &mgp->pdev->dev;
+ size_t hdr_off, pattern_off, hdr_len;
+ u32 pattern = 0xfffffffe;
+
+ /* find running firmware header */
+ hdr_off = swab32(readl(mgp->sram + MCP_HEADER_PTR_OFFSET));
+ if ((hdr_off & 3) || hdr_off + sizeof(*hdr) > mgp->sram_size) {
+ dev_err(dev, "Running firmware has bad header offset (%d)\n",
+ (int)hdr_off);
+ return -EIO;
+ }
+ hdr_len = swab32(readl(mgp->sram + hdr_off +
+ offsetof(struct mcp_gen_header, header_length)));
+ pattern_off = hdr_off + offsetof(struct mcp_gen_header, led_pattern);
+ if (pattern_off >= (hdr_len + hdr_off)) {
+ dev_info(dev, "Firmware does not support LED identification\n");
+ return -EINVAL;
+ }
+ if (!on)
+ pattern = swab32(readl(mgp->sram + pattern_off + 4));
+ writel(htonl(pattern), mgp->sram + pattern_off);
+ return 0;
+}
+
+static int
+myri10ge_phys_id(struct net_device *netdev, enum ethtool_phys_id_state state)
+{
+ struct myri10ge_priv *mgp = netdev_priv(netdev);
+ int rc;
+
+ switch (state) {
+ case ETHTOOL_ID_ACTIVE:
+ rc = myri10ge_led(mgp, 1);
+ break;
+
+ case ETHTOOL_ID_INACTIVE:
+ rc = myri10ge_led(mgp, 0);
+ break;
+
+ default:
+ rc = -EINVAL;
+ }
+
+ return rc;
+}
+
static const struct ethtool_ops myri10ge_ethtool_ops = {
.get_settings = myri10ge_get_settings,
.get_drvinfo = myri10ge_get_drvinfo,
@@ -1921,6 +1976,7 @@
.get_ethtool_stats = myri10ge_get_ethtool_stats,
.set_msglevel = myri10ge_set_msglevel,
.get_msglevel = myri10ge_get_msglevel,
+ .set_phys_id = myri10ge_phys_id,
};
static int myri10ge_allocate_rings(struct myri10ge_slice_state *ss)
@@ -2000,8 +2056,12 @@
ss->rx_big.page_offset = MYRI10GE_ALLOC_SIZE;
ss->rx_small.watchdog_needed = 0;
ss->rx_big.watchdog_needed = 0;
- myri10ge_alloc_rx_pages(mgp, &ss->rx_small,
- mgp->small_bytes + MXGEFW_PAD, 0);
+ if (mgp->small_bytes == 0) {
+ ss->rx_small.fill_cnt = ss->rx_small.mask + 1;
+ } else {
+ myri10ge_alloc_rx_pages(mgp, &ss->rx_small,
+ mgp->small_bytes + MXGEFW_PAD, 0);
+ }
if (ss->rx_small.fill_cnt < ss->rx_small.mask + 1) {
netdev_err(dev, "slice-%d: alloced only %d small bufs\n",
@@ -2027,6 +2087,8 @@
}
abort_with_rx_small_ring:
+ if (mgp->small_bytes == 0)
+ ss->rx_small.fill_cnt = ss->rx_small.cnt;
for (i = ss->rx_small.cnt; i < ss->rx_small.fill_cnt; i++) {
int idx = i & ss->rx_small.mask;
myri10ge_unmap_rx_page(mgp->pdev, &ss->rx_small.info[idx],
@@ -2077,6 +2139,8 @@
put_page(ss->rx_big.info[idx].page);
}
+ if (mgp->small_bytes == 0)
+ ss->rx_small.fill_cnt = ss->rx_small.cnt;
for (i = ss->rx_small.cnt; i < ss->rx_small.fill_cnt; i++) {
idx = i & ss->rx_small.mask;
if (i == ss->rx_small.fill_cnt - 1)
@@ -2255,7 +2319,7 @@
*ip_hdr = iph;
if (iph->protocol != IPPROTO_TCP)
return -1;
- if (iph->frag_off & htons(IP_MF | IP_OFFSET))
+ if (ip_is_fragment(iph))
return -1;
*hdr_flags |= LRO_TCP;
*tcpudp_hdr = (u8 *) (*ip_hdr) + (iph->ihl << 2);
@@ -2414,7 +2478,7 @@
mgp->small_bytes = VLAN_ETH_FRAME_LEN;
/* Override the small buffer size? */
- if (myri10ge_small_bytes > 0)
+ if (myri10ge_small_bytes >= 0)
mgp->small_bytes = myri10ge_small_bytes;
/* Firmware needs the big buff size as a power of 2. Lie and
@@ -2976,15 +3040,13 @@
return NETDEV_TX_OK;
}
-static struct net_device_stats *myri10ge_get_stats(struct net_device *dev)
+static struct rtnl_link_stats64 *myri10ge_get_stats(struct net_device *dev,
+ struct rtnl_link_stats64 *stats)
{
- struct myri10ge_priv *mgp = netdev_priv(dev);
- struct myri10ge_slice_netstats *slice_stats;
- struct net_device_stats *stats = &dev->stats;
+ const struct myri10ge_priv *mgp = netdev_priv(dev);
+ const struct myri10ge_slice_netstats *slice_stats;
int i;
- spin_lock(&mgp->stats_lock);
- memset(stats, 0, sizeof(*stats));
for (i = 0; i < mgp->num_slices; i++) {
slice_stats = &mgp->ss[i].stats;
stats->rx_packets += slice_stats->rx_packets;
@@ -2994,7 +3056,6 @@
stats->rx_dropped += slice_stats->rx_dropped;
stats->tx_dropped += slice_stats->tx_dropped;
}
- spin_unlock(&mgp->stats_lock);
return stats;
}
@@ -3127,7 +3188,7 @@
{
struct pci_dev *bridge = mgp->pdev->bus->self;
struct device *dev = &mgp->pdev->dev;
- unsigned cap;
+ int cap;
unsigned err_cap;
u16 val;
u8 ext_type;
@@ -3137,7 +3198,7 @@
return;
/* check that the bridge is a root port */
- cap = pci_find_capability(bridge, PCI_CAP_ID_EXP);
+ cap = pci_pcie_cap(bridge);
pci_read_config_word(bridge, cap + PCI_CAP_FLAGS, &val);
ext_type = (val & PCI_EXP_FLAGS_TYPE) >> 4;
if (ext_type != PCI_EXP_TYPE_ROOT_PORT) {
@@ -3155,8 +3216,7 @@
" to force ECRC\n");
return;
}
- cap =
- pci_find_capability(bridge, PCI_CAP_ID_EXP);
+ cap = pci_pcie_cap(bridge);
pci_read_config_word(bridge,
cap + PCI_CAP_FLAGS, &val);
ext_type = (val & PCI_EXP_FLAGS_TYPE) >> 4;
@@ -3266,7 +3326,6 @@
/* fall back to using the unaligned firmware */
mgp->tx_boundary = 2048;
set_fw_name(mgp, myri10ge_fw_unaligned, false);
-
}
static void myri10ge_select_firmware(struct myri10ge_priv *mgp)
@@ -3277,7 +3336,7 @@
int link_width, exp_cap;
u16 lnk;
- exp_cap = pci_find_capability(mgp->pdev, PCI_CAP_ID_EXP);
+ exp_cap = pci_pcie_cap(mgp->pdev);
pci_read_config_word(mgp->pdev, exp_cap + PCI_EXP_LNKSTA, &lnk);
link_width = (lnk >> 4) & 0x3f;
@@ -3327,6 +3386,26 @@
mgp->fw_name);
}
+static void myri10ge_mask_surprise_down(struct pci_dev *pdev)
+{
+ struct pci_dev *bridge = pdev->bus->self;
+ int cap;
+ u32 mask;
+
+ if (bridge == NULL)
+ return;
+
+ cap = pci_find_ext_capability(bridge, PCI_EXT_CAP_ID_ERR);
+ if (cap) {
+ /* a sram parity error can cause a surprise link
+ * down; since we expect and can recover from sram
+ * parity errors, mask surprise link down events */
+ pci_read_config_dword(bridge, cap + PCI_ERR_UNCOR_MASK, &mask);
+ mask |= 0x20;
+ pci_write_config_dword(bridge, cap + PCI_ERR_UNCOR_MASK, mask);
+ }
+}
+
#ifdef CONFIG_PM
static int myri10ge_suspend(struct pci_dev *pdev, pm_message_t state)
{
@@ -3422,6 +3501,42 @@
return reboot;
}
+static void
+myri10ge_check_slice(struct myri10ge_slice_state *ss, int *reset_needed,
+ int *busy_slice_cnt, u32 rx_pause_cnt)
+{
+ struct myri10ge_priv *mgp = ss->mgp;
+ int slice = ss - mgp->ss;
+
+ if (ss->tx.req != ss->tx.done &&
+ ss->tx.done == ss->watchdog_tx_done &&
+ ss->watchdog_tx_req != ss->watchdog_tx_done) {
+ /* nic seems like it might be stuck.. */
+ if (rx_pause_cnt != mgp->watchdog_pause) {
+ if (net_ratelimit())
+ netdev_warn(mgp->dev, "slice %d: TX paused, "
+ "check link partner\n", slice);
+ } else {
+ netdev_warn(mgp->dev,
+ "slice %d: TX stuck %d %d %d %d %d %d\n",
+ slice, ss->tx.queue_active, ss->tx.req,
+ ss->tx.done, ss->tx.pkt_start,
+ ss->tx.pkt_done,
+ (int)ntohl(mgp->ss[slice].fw_stats->
+ send_done_count));
+ *reset_needed = 1;
+ ss->stuck = 1;
+ }
+ }
+ if (ss->watchdog_tx_done != ss->tx.done ||
+ ss->watchdog_rx_done != ss->rx_done.cnt) {
+ *busy_slice_cnt += 1;
+ }
+ ss->watchdog_tx_done = ss->tx.done;
+ ss->watchdog_tx_req = ss->tx.req;
+ ss->watchdog_rx_done = ss->rx_done.cnt;
+}
+
/*
* This watchdog is used to check whether the board has suffered
* from a parity error and needs to be recovered.
@@ -3430,10 +3545,12 @@
{
struct myri10ge_priv *mgp =
container_of(work, struct myri10ge_priv, watchdog_work);
- struct myri10ge_tx_buf *tx;
- u32 reboot;
+ struct myri10ge_slice_state *ss;
+ u32 reboot, rx_pause_cnt;
int status, rebooted;
int i;
+ int reset_needed = 0;
+ int busy_slice_cnt = 0;
u16 cmd, vendor;
mgp->watchdog_resets++;
@@ -3445,8 +3562,7 @@
* For now, just report it */
reboot = myri10ge_read_reboot(mgp);
netdev_err(mgp->dev, "NIC rebooted (0x%x),%s resetting\n",
- reboot,
- myri10ge_reset_recover ? "" : " not");
+ reboot, myri10ge_reset_recover ? "" : " not");
if (myri10ge_reset_recover == 0)
return;
rtnl_lock();
@@ -3478,23 +3594,24 @@
return;
}
}
- /* Perhaps it is a software error. Try to reset */
+ /* Perhaps it is a software error. See if stuck slice
+ * has recovered, reset if not */
+ rx_pause_cnt = ntohl(mgp->ss[0].fw_stats->dropped_pause);
+ for (i = 0; i < mgp->num_slices; i++) {
+ ss = mgp->ss;
+ if (ss->stuck) {
+ myri10ge_check_slice(ss, &reset_needed,
+ &busy_slice_cnt,
+ rx_pause_cnt);
+ ss->stuck = 0;
+ }
+ }
+ if (!reset_needed) {
+ netdev_dbg(mgp->dev, "not resetting\n");
+ return;
+ }
netdev_err(mgp->dev, "device timeout, resetting\n");
- for (i = 0; i < mgp->num_slices; i++) {
- tx = &mgp->ss[i].tx;
- netdev_err(mgp->dev, "(%d): %d %d %d %d %d %d\n",
- i, tx->queue_active, tx->req,
- tx->done, tx->pkt_start, tx->pkt_done,
- (int)ntohl(mgp->ss[i].fw_stats->
- send_done_count));
- msleep(2000);
- netdev_info(mgp->dev, "(%d): %d %d %d %d %d %d\n",
- i, tx->queue_active, tx->req,
- tx->done, tx->pkt_start, tx->pkt_done,
- (int)ntohl(mgp->ss[i].fw_stats->
- send_done_count));
- }
}
if (!rebooted) {
@@ -3547,27 +3664,8 @@
myri10ge_fill_thresh)
ss->rx_big.watchdog_needed = 0;
}
-
- if (ss->tx.req != ss->tx.done &&
- ss->tx.done == ss->watchdog_tx_done &&
- ss->watchdog_tx_req != ss->watchdog_tx_done) {
- /* nic seems like it might be stuck.. */
- if (rx_pause_cnt != mgp->watchdog_pause) {
- if (net_ratelimit())
- netdev_err(mgp->dev, "slice %d: TX paused, check link partner\n",
- i);
- } else {
- netdev_warn(mgp->dev, "slice %d stuck:", i);
- reset_needed = 1;
- }
- }
- if (ss->watchdog_tx_done != ss->tx.done ||
- ss->watchdog_rx_done != ss->rx_done.cnt) {
- busy_slice_cnt++;
- }
- ss->watchdog_tx_done = ss->tx.done;
- ss->watchdog_tx_req = ss->tx.req;
- ss->watchdog_rx_done = ss->rx_done.cnt;
+ myri10ge_check_slice(ss, &reset_needed, &busy_slice_cnt,
+ rx_pause_cnt);
}
/* if we've sent or received no traffic, poll the NIC to
* ensure it is still there. Otherwise, we risk not noticing
@@ -3613,8 +3711,8 @@
dma_free_coherent(&pdev->dev, bytes,
ss->fw_stats, ss->fw_stats_bus);
ss->fw_stats = NULL;
- netif_napi_del(&ss->napi);
}
+ netif_napi_del(&ss->napi);
}
kfree(mgp->ss);
mgp->ss = NULL;
@@ -3790,7 +3888,7 @@
.ndo_open = myri10ge_open,
.ndo_stop = myri10ge_close,
.ndo_start_xmit = myri10ge_xmit,
- .ndo_get_stats = myri10ge_get_stats,
+ .ndo_get_stats64 = myri10ge_get_stats,
.ndo_validate_addr = eth_validate_addr,
.ndo_change_mtu = myri10ge_change_mtu,
.ndo_fix_features = myri10ge_fix_features,
@@ -3845,6 +3943,7 @@
goto abort_with_enabled;
}
+ myri10ge_mask_surprise_down(pdev);
pci_set_master(pdev);
dac_enabled = 1;
status = pci_set_dma_mask(pdev, DMA_BIT_MASK(64));
@@ -3964,7 +4063,6 @@
setup_timer(&mgp->watchdog_timer, myri10ge_watchdog_timer,
(unsigned long)mgp);
- spin_lock_init(&mgp->stats_lock);
SET_ETHTOOL_OPS(netdev, &myri10ge_ethtool_ops);
INIT_WORK(&mgp->watchdog_work, myri10ge_watchdog);
status = register_netdev(netdev);
diff --git a/drivers/net/myri10ge/myri10ge_mcp_gen_header.h b/drivers/net/myri10ge/myri10ge_mcp_gen_header.h
index 62a1cba..7ec4b86 100644
--- a/drivers/net/myri10ge/myri10ge_mcp_gen_header.h
+++ b/drivers/net/myri10ge/myri10ge_mcp_gen_header.h
@@ -45,6 +45,8 @@
unsigned bss_addr; /* start of bss */
unsigned features;
unsigned ee_hdr_addr;
+ unsigned led_pattern;
+ unsigned led_pattern_dflt;
/* 8 */
};
diff --git a/drivers/net/myri_sbus.c b/drivers/net/myri_sbus.c
deleted file mode 100644
index 53aeea4..0000000
--- a/drivers/net/myri_sbus.c
+++ /dev/null
@@ -1,1187 +0,0 @@
-/* myri_sbus.c: MyriCOM MyriNET SBUS card driver.
- *
- * Copyright (C) 1996, 1999, 2006, 2008 David S. Miller (davem@davemloft.net)
- */
-
-static char version[] =
- "myri_sbus.c:v2.0 June 23, 2006 David S. Miller (davem@davemloft.net)\n";
-
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/fcntl.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/in.h>
-#include <linux/string.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <linux/bitops.h>
-#include <linux/dma-mapping.h>
-#include <linux/of.h>
-#include <linux/of_device.h>
-#include <linux/firmware.h>
-#include <linux/gfp.h>
-
-#include <net/dst.h>
-#include <net/arp.h>
-#include <net/sock.h>
-#include <net/ipv6.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/dma.h>
-#include <asm/byteorder.h>
-#include <asm/idprom.h>
-#include <asm/openprom.h>
-#include <asm/oplib.h>
-#include <asm/auxio.h>
-#include <asm/pgtable.h>
-#include <asm/irq.h>
-
-#include "myri_sbus.h"
-
-/* #define DEBUG_DETECT */
-/* #define DEBUG_IRQ */
-/* #define DEBUG_TRANSMIT */
-/* #define DEBUG_RECEIVE */
-/* #define DEBUG_HEADER */
-
-#ifdef DEBUG_DETECT
-#define DET(x) printk x
-#else
-#define DET(x)
-#endif
-
-#ifdef DEBUG_IRQ
-#define DIRQ(x) printk x
-#else
-#define DIRQ(x)
-#endif
-
-#ifdef DEBUG_TRANSMIT
-#define DTX(x) printk x
-#else
-#define DTX(x)
-#endif
-
-#ifdef DEBUG_RECEIVE
-#define DRX(x) printk x
-#else
-#define DRX(x)
-#endif
-
-#ifdef DEBUG_HEADER
-#define DHDR(x) printk x
-#else
-#define DHDR(x)
-#endif
-
-/* Firmware name */
-#define FWNAME "myricom/lanai.bin"
-
-static void myri_reset_off(void __iomem *lp, void __iomem *cregs)
-{
- /* Clear IRQ mask. */
- sbus_writel(0, lp + LANAI_EIMASK);
-
- /* Turn RESET function off. */
- sbus_writel(CONTROL_ROFF, cregs + MYRICTRL_CTRL);
-}
-
-static void myri_reset_on(void __iomem *cregs)
-{
- /* Enable RESET function. */
- sbus_writel(CONTROL_RON, cregs + MYRICTRL_CTRL);
-
- /* Disable IRQ's. */
- sbus_writel(CONTROL_DIRQ, cregs + MYRICTRL_CTRL);
-}
-
-static void myri_disable_irq(void __iomem *lp, void __iomem *cregs)
-{
- sbus_writel(CONTROL_DIRQ, cregs + MYRICTRL_CTRL);
- sbus_writel(0, lp + LANAI_EIMASK);
- sbus_writel(ISTAT_HOST, lp + LANAI_ISTAT);
-}
-
-static void myri_enable_irq(void __iomem *lp, void __iomem *cregs)
-{
- sbus_writel(CONTROL_EIRQ, cregs + MYRICTRL_CTRL);
- sbus_writel(ISTAT_HOST, lp + LANAI_EIMASK);
-}
-
-static inline void bang_the_chip(struct myri_eth *mp)
-{
- struct myri_shmem __iomem *shmem = mp->shmem;
- void __iomem *cregs = mp->cregs;
-
- sbus_writel(1, &shmem->send);
- sbus_writel(CONTROL_WON, cregs + MYRICTRL_CTRL);
-}
-
-static int myri_do_handshake(struct myri_eth *mp)
-{
- struct myri_shmem __iomem *shmem = mp->shmem;
- void __iomem *cregs = mp->cregs;
- struct myri_channel __iomem *chan = &shmem->channel;
- int tick = 0;
-
- DET(("myri_do_handshake: "));
- if (sbus_readl(&chan->state) == STATE_READY) {
- DET(("Already STATE_READY, failed.\n"));
- return -1; /* We're hosed... */
- }
-
- myri_disable_irq(mp->lregs, cregs);
-
- while (tick++ < 25) {
- u32 softstate;
-
- /* Wake it up. */
- DET(("shakedown, CONTROL_WON, "));
- sbus_writel(1, &shmem->shakedown);
- sbus_writel(CONTROL_WON, cregs + MYRICTRL_CTRL);
-
- softstate = sbus_readl(&chan->state);
- DET(("chanstate[%08x] ", softstate));
- if (softstate == STATE_READY) {
- DET(("wakeup successful, "));
- break;
- }
-
- if (softstate != STATE_WFN) {
- DET(("not WFN setting that, "));
- sbus_writel(STATE_WFN, &chan->state);
- }
-
- udelay(20);
- }
-
- myri_enable_irq(mp->lregs, cregs);
-
- if (tick > 25) {
- DET(("25 ticks we lose, failure.\n"));
- return -1;
- }
- DET(("success\n"));
- return 0;
-}
-
-static int __devinit myri_load_lanai(struct myri_eth *mp)
-{
- const struct firmware *fw;
- struct net_device *dev = mp->dev;
- struct myri_shmem __iomem *shmem = mp->shmem;
- void __iomem *rptr;
- int i, lanai4_data_size;
-
- myri_disable_irq(mp->lregs, mp->cregs);
- myri_reset_on(mp->cregs);
-
- rptr = mp->lanai;
- for (i = 0; i < mp->eeprom.ramsz; i++)
- sbus_writeb(0, rptr + i);
-
- if (mp->eeprom.cpuvers >= CPUVERS_3_0)
- sbus_writel(mp->eeprom.cval, mp->lregs + LANAI_CVAL);
-
- i = request_firmware(&fw, FWNAME, &mp->myri_op->dev);
- if (i) {
- printk(KERN_ERR "Failed to load image \"%s\" err %d\n",
- FWNAME, i);
- return i;
- }
- if (fw->size < 2) {
- printk(KERN_ERR "Bogus length %zu in image \"%s\"\n",
- fw->size, FWNAME);
- release_firmware(fw);
- return -EINVAL;
- }
- lanai4_data_size = fw->data[0] << 8 | fw->data[1];
-
- /* Load executable code. */
- for (i = 2; i < fw->size; i++)
- sbus_writeb(fw->data[i], rptr++);
-
- /* Load data segment. */
- for (i = 0; i < lanai4_data_size; i++)
- sbus_writeb(0, rptr++);
-
- /* Set device address. */
- sbus_writeb(0, &shmem->addr[0]);
- sbus_writeb(0, &shmem->addr[1]);
- for (i = 0; i < 6; i++)
- sbus_writeb(dev->dev_addr[i],
- &shmem->addr[i + 2]);
-
- /* Set SBUS bursts and interrupt mask. */
- sbus_writel(((mp->myri_bursts & 0xf8) >> 3), &shmem->burst);
- sbus_writel(SHMEM_IMASK_RX, &shmem->imask);
-
- /* Release the LANAI. */
- myri_disable_irq(mp->lregs, mp->cregs);
- myri_reset_off(mp->lregs, mp->cregs);
- myri_disable_irq(mp->lregs, mp->cregs);
-
- /* Wait for the reset to complete. */
- for (i = 0; i < 5000; i++) {
- if (sbus_readl(&shmem->channel.state) != STATE_READY)
- break;
- else
- udelay(10);
- }
-
- if (i == 5000)
- printk(KERN_ERR "myricom: Chip would not reset after firmware load.\n");
-
- i = myri_do_handshake(mp);
- if (i)
- printk(KERN_ERR "myricom: Handshake with LANAI failed.\n");
-
- if (mp->eeprom.cpuvers == CPUVERS_4_0)
- sbus_writel(0, mp->lregs + LANAI_VERS);
-
- release_firmware(fw);
- return i;
-}
-
-static void myri_clean_rings(struct myri_eth *mp)
-{
- struct sendq __iomem *sq = mp->sq;
- struct recvq __iomem *rq = mp->rq;
- int i;
-
- sbus_writel(0, &rq->tail);
- sbus_writel(0, &rq->head);
- for (i = 0; i < (RX_RING_SIZE+1); i++) {
- if (mp->rx_skbs[i] != NULL) {
- struct myri_rxd __iomem *rxd = &rq->myri_rxd[i];
- u32 dma_addr;
-
- dma_addr = sbus_readl(&rxd->myri_scatters[0].addr);
- dma_unmap_single(&mp->myri_op->dev, dma_addr,
- RX_ALLOC_SIZE, DMA_FROM_DEVICE);
- dev_kfree_skb(mp->rx_skbs[i]);
- mp->rx_skbs[i] = NULL;
- }
- }
-
- mp->tx_old = 0;
- sbus_writel(0, &sq->tail);
- sbus_writel(0, &sq->head);
- for (i = 0; i < TX_RING_SIZE; i++) {
- if (mp->tx_skbs[i] != NULL) {
- struct sk_buff *skb = mp->tx_skbs[i];
- struct myri_txd __iomem *txd = &sq->myri_txd[i];
- u32 dma_addr;
-
- dma_addr = sbus_readl(&txd->myri_gathers[0].addr);
- dma_unmap_single(&mp->myri_op->dev, dma_addr,
- (skb->len + 3) & ~3,
- DMA_TO_DEVICE);
- dev_kfree_skb(mp->tx_skbs[i]);
- mp->tx_skbs[i] = NULL;
- }
- }
-}
-
-static void myri_init_rings(struct myri_eth *mp, int from_irq)
-{
- struct recvq __iomem *rq = mp->rq;
- struct myri_rxd __iomem *rxd = &rq->myri_rxd[0];
- struct net_device *dev = mp->dev;
- gfp_t gfp_flags = GFP_KERNEL;
- int i;
-
- if (from_irq || in_interrupt())
- gfp_flags = GFP_ATOMIC;
-
- myri_clean_rings(mp);
- for (i = 0; i < RX_RING_SIZE; i++) {
- struct sk_buff *skb = myri_alloc_skb(RX_ALLOC_SIZE, gfp_flags);
- u32 dma_addr;
-
- if (!skb)
- continue;
- mp->rx_skbs[i] = skb;
- skb->dev = dev;
- skb_put(skb, RX_ALLOC_SIZE);
-
- dma_addr = dma_map_single(&mp->myri_op->dev,
- skb->data, RX_ALLOC_SIZE,
- DMA_FROM_DEVICE);
- sbus_writel(dma_addr, &rxd[i].myri_scatters[0].addr);
- sbus_writel(RX_ALLOC_SIZE, &rxd[i].myri_scatters[0].len);
- sbus_writel(i, &rxd[i].ctx);
- sbus_writel(1, &rxd[i].num_sg);
- }
- sbus_writel(0, &rq->head);
- sbus_writel(RX_RING_SIZE, &rq->tail);
-}
-
-static int myri_init(struct myri_eth *mp, int from_irq)
-{
- myri_init_rings(mp, from_irq);
- return 0;
-}
-
-static void myri_is_not_so_happy(struct myri_eth *mp)
-{
-}
-
-#ifdef DEBUG_HEADER
-static void dump_ehdr(struct ethhdr *ehdr)
-{
- printk("ehdr[h_dst(%pM)"
- "h_source(%pM)"
- "h_proto(%04x)]\n",
- ehdr->h_dest, ehdr->h_source, ehdr->h_proto);
-}
-
-static void dump_ehdr_and_myripad(unsigned char *stuff)
-{
- struct ethhdr *ehdr = (struct ethhdr *) (stuff + 2);
-
- printk("pad[%02x:%02x]", stuff[0], stuff[1]);
- dump_ehdr(ehdr);
-}
-#endif
-
-static void myri_tx(struct myri_eth *mp, struct net_device *dev)
-{
- struct sendq __iomem *sq= mp->sq;
- int entry = mp->tx_old;
- int limit = sbus_readl(&sq->head);
-
- DTX(("entry[%d] limit[%d] ", entry, limit));
- if (entry == limit)
- return;
- while (entry != limit) {
- struct sk_buff *skb = mp->tx_skbs[entry];
- u32 dma_addr;
-
- DTX(("SKB[%d] ", entry));
- dma_addr = sbus_readl(&sq->myri_txd[entry].myri_gathers[0].addr);
- dma_unmap_single(&mp->myri_op->dev, dma_addr,
- skb->len, DMA_TO_DEVICE);
- dev_kfree_skb(skb);
- mp->tx_skbs[entry] = NULL;
- dev->stats.tx_packets++;
- entry = NEXT_TX(entry);
- }
- mp->tx_old = entry;
-}
-
-/* Determine the packet's protocol ID. The rule here is that we
- * assume 802.3 if the type field is short enough to be a length.
- * This is normal practice and works for any 'now in use' protocol.
- */
-static __be16 myri_type_trans(struct sk_buff *skb, struct net_device *dev)
-{
- struct ethhdr *eth;
- unsigned char *rawp;
-
- skb_set_mac_header(skb, MYRI_PAD_LEN);
- skb_pull(skb, dev->hard_header_len);
- eth = eth_hdr(skb);
-
-#ifdef DEBUG_HEADER
- DHDR(("myri_type_trans: "));
- dump_ehdr(eth);
-#endif
- if (*eth->h_dest & 1) {
- if (memcmp(eth->h_dest, dev->broadcast, ETH_ALEN)==0)
- skb->pkt_type = PACKET_BROADCAST;
- else
- skb->pkt_type = PACKET_MULTICAST;
- } else if (dev->flags & (IFF_PROMISC|IFF_ALLMULTI)) {
- if (memcmp(eth->h_dest, dev->dev_addr, ETH_ALEN))
- skb->pkt_type = PACKET_OTHERHOST;
- }
-
- if (ntohs(eth->h_proto) >= 1536)
- return eth->h_proto;
-
- rawp = skb->data;
-
- /* This is a magic hack to spot IPX packets. Older Novell breaks
- * the protocol design and runs IPX over 802.3 without an 802.2 LLC
- * layer. We look for FFFF which isn't a used 802.2 SSAP/DSAP. This
- * won't work for fault tolerant netware but does for the rest.
- */
- if (*(unsigned short *)rawp == 0xFFFF)
- return htons(ETH_P_802_3);
-
- /* Real 802.2 LLC */
- return htons(ETH_P_802_2);
-}
-
-static void myri_rx(struct myri_eth *mp, struct net_device *dev)
-{
- struct recvq __iomem *rq = mp->rq;
- struct recvq __iomem *rqa = mp->rqack;
- int entry = sbus_readl(&rqa->head);
- int limit = sbus_readl(&rqa->tail);
- int drops;
-
- DRX(("entry[%d] limit[%d] ", entry, limit));
- if (entry == limit)
- return;
- drops = 0;
- DRX(("\n"));
- while (entry != limit) {
- struct myri_rxd __iomem *rxdack = &rqa->myri_rxd[entry];
- u32 csum = sbus_readl(&rxdack->csum);
- int len = sbus_readl(&rxdack->myri_scatters[0].len);
- int index = sbus_readl(&rxdack->ctx);
- struct myri_rxd __iomem *rxd = &rq->myri_rxd[sbus_readl(&rq->tail)];
- struct sk_buff *skb = mp->rx_skbs[index];
-
- /* Ack it. */
- sbus_writel(NEXT_RX(entry), &rqa->head);
-
- /* Check for errors. */
- DRX(("rxd[%d]: %p len[%d] csum[%08x] ", entry, rxd, len, csum));
- dma_sync_single_for_cpu(&mp->myri_op->dev,
- sbus_readl(&rxd->myri_scatters[0].addr),
- RX_ALLOC_SIZE, DMA_FROM_DEVICE);
- if (len < (ETH_HLEN + MYRI_PAD_LEN) || (skb->data[0] != MYRI_PAD_LEN)) {
- DRX(("ERROR["));
- dev->stats.rx_errors++;
- if (len < (ETH_HLEN + MYRI_PAD_LEN)) {
- DRX(("BAD_LENGTH] "));
- dev->stats.rx_length_errors++;
- } else {
- DRX(("NO_PADDING] "));
- dev->stats.rx_frame_errors++;
- }
-
- /* Return it to the LANAI. */
- drop_it:
- drops++;
- DRX(("DROP "));
- dev->stats.rx_dropped++;
- dma_sync_single_for_device(&mp->myri_op->dev,
- sbus_readl(&rxd->myri_scatters[0].addr),
- RX_ALLOC_SIZE,
- DMA_FROM_DEVICE);
- sbus_writel(RX_ALLOC_SIZE, &rxd->myri_scatters[0].len);
- sbus_writel(index, &rxd->ctx);
- sbus_writel(1, &rxd->num_sg);
- sbus_writel(NEXT_RX(sbus_readl(&rq->tail)), &rq->tail);
- goto next;
- }
-
- DRX(("len[%d] ", len));
- if (len > RX_COPY_THRESHOLD) {
- struct sk_buff *new_skb;
- u32 dma_addr;
-
- DRX(("BIGBUFF "));
- new_skb = myri_alloc_skb(RX_ALLOC_SIZE, GFP_ATOMIC);
- if (new_skb == NULL) {
- DRX(("skb_alloc(FAILED) "));
- goto drop_it;
- }
- dma_unmap_single(&mp->myri_op->dev,
- sbus_readl(&rxd->myri_scatters[0].addr),
- RX_ALLOC_SIZE,
- DMA_FROM_DEVICE);
- mp->rx_skbs[index] = new_skb;
- new_skb->dev = dev;
- skb_put(new_skb, RX_ALLOC_SIZE);
- dma_addr = dma_map_single(&mp->myri_op->dev,
- new_skb->data,
- RX_ALLOC_SIZE,
- DMA_FROM_DEVICE);
- sbus_writel(dma_addr, &rxd->myri_scatters[0].addr);
- sbus_writel(RX_ALLOC_SIZE, &rxd->myri_scatters[0].len);
- sbus_writel(index, &rxd->ctx);
- sbus_writel(1, &rxd->num_sg);
- sbus_writel(NEXT_RX(sbus_readl(&rq->tail)), &rq->tail);
-
- /* Trim the original skb for the netif. */
- DRX(("trim(%d) ", len));
- skb_trim(skb, len);
- } else {
- struct sk_buff *copy_skb = dev_alloc_skb(len);
-
- DRX(("SMALLBUFF "));
- if (copy_skb == NULL) {
- DRX(("dev_alloc_skb(FAILED) "));
- goto drop_it;
- }
- /* DMA sync already done above. */
- copy_skb->dev = dev;
- DRX(("resv_and_put "));
- skb_put(copy_skb, len);
- skb_copy_from_linear_data(skb, copy_skb->data, len);
-
- /* Reuse original ring buffer. */
- DRX(("reuse "));
- dma_sync_single_for_device(&mp->myri_op->dev,
- sbus_readl(&rxd->myri_scatters[0].addr),
- RX_ALLOC_SIZE,
- DMA_FROM_DEVICE);
- sbus_writel(RX_ALLOC_SIZE, &rxd->myri_scatters[0].len);
- sbus_writel(index, &rxd->ctx);
- sbus_writel(1, &rxd->num_sg);
- sbus_writel(NEXT_RX(sbus_readl(&rq->tail)), &rq->tail);
-
- skb = copy_skb;
- }
-
- /* Just like the happy meal we get checksums from this card. */
- skb->csum = csum;
- skb->ip_summed = CHECKSUM_UNNECESSARY; /* XXX */
-
- skb->protocol = myri_type_trans(skb, dev);
- DRX(("prot[%04x] netif_rx ", skb->protocol));
- netif_rx(skb);
-
- dev->stats.rx_packets++;
- dev->stats.rx_bytes += len;
- next:
- DRX(("NEXT\n"));
- entry = NEXT_RX(entry);
- }
-}
-
-static irqreturn_t myri_interrupt(int irq, void *dev_id)
-{
- struct net_device *dev = (struct net_device *) dev_id;
- struct myri_eth *mp = netdev_priv(dev);
- void __iomem *lregs = mp->lregs;
- struct myri_channel __iomem *chan = &mp->shmem->channel;
- unsigned long flags;
- u32 status;
- int handled = 0;
-
- spin_lock_irqsave(&mp->irq_lock, flags);
-
- status = sbus_readl(lregs + LANAI_ISTAT);
- DIRQ(("myri_interrupt: status[%08x] ", status));
- if (status & ISTAT_HOST) {
- u32 softstate;
-
- handled = 1;
- DIRQ(("IRQ_DISAB "));
- myri_disable_irq(lregs, mp->cregs);
- softstate = sbus_readl(&chan->state);
- DIRQ(("state[%08x] ", softstate));
- if (softstate != STATE_READY) {
- DIRQ(("myri_not_so_happy "));
- myri_is_not_so_happy(mp);
- }
- DIRQ(("\nmyri_rx: "));
- myri_rx(mp, dev);
- DIRQ(("\nistat=ISTAT_HOST "));
- sbus_writel(ISTAT_HOST, lregs + LANAI_ISTAT);
- DIRQ(("IRQ_ENAB "));
- myri_enable_irq(lregs, mp->cregs);
- }
- DIRQ(("\n"));
-
- spin_unlock_irqrestore(&mp->irq_lock, flags);
-
- return IRQ_RETVAL(handled);
-}
-
-static int myri_open(struct net_device *dev)
-{
- struct myri_eth *mp = netdev_priv(dev);
-
- return myri_init(mp, in_interrupt());
-}
-
-static int myri_close(struct net_device *dev)
-{
- struct myri_eth *mp = netdev_priv(dev);
-
- myri_clean_rings(mp);
- return 0;
-}
-
-static void myri_tx_timeout(struct net_device *dev)
-{
- struct myri_eth *mp = netdev_priv(dev);
-
- printk(KERN_ERR "%s: transmit timed out, resetting\n", dev->name);
-
- dev->stats.tx_errors++;
- myri_init(mp, 0);
- netif_wake_queue(dev);
-}
-
-static int myri_start_xmit(struct sk_buff *skb, struct net_device *dev)
-{
- struct myri_eth *mp = netdev_priv(dev);
- struct sendq __iomem *sq = mp->sq;
- struct myri_txd __iomem *txd;
- unsigned long flags;
- unsigned int head, tail;
- int len, entry;
- u32 dma_addr;
-
- DTX(("myri_start_xmit: "));
-
- myri_tx(mp, dev);
-
- netif_stop_queue(dev);
-
- /* This is just to prevent multiple PIO reads for TX_BUFFS_AVAIL. */
- head = sbus_readl(&sq->head);
- tail = sbus_readl(&sq->tail);
-
- if (!TX_BUFFS_AVAIL(head, tail)) {
- DTX(("no buffs available, returning 1\n"));
- return NETDEV_TX_BUSY;
- }
-
- spin_lock_irqsave(&mp->irq_lock, flags);
-
- DHDR(("xmit[skbdata(%p)]\n", skb->data));
-#ifdef DEBUG_HEADER
- dump_ehdr_and_myripad(((unsigned char *) skb->data));
-#endif
-
- /* XXX Maybe this can go as well. */
- len = skb->len;
- if (len & 3) {
- DTX(("len&3 "));
- len = (len + 4) & (~3);
- }
-
- entry = sbus_readl(&sq->tail);
-
- txd = &sq->myri_txd[entry];
- mp->tx_skbs[entry] = skb;
-
- /* Must do this before we sbus map it. */
- if (skb->data[MYRI_PAD_LEN] & 0x1) {
- sbus_writew(0xffff, &txd->addr[0]);
- sbus_writew(0xffff, &txd->addr[1]);
- sbus_writew(0xffff, &txd->addr[2]);
- sbus_writew(0xffff, &txd->addr[3]);
- } else {
- sbus_writew(0xffff, &txd->addr[0]);
- sbus_writew((skb->data[0] << 8) | skb->data[1], &txd->addr[1]);
- sbus_writew((skb->data[2] << 8) | skb->data[3], &txd->addr[2]);
- sbus_writew((skb->data[4] << 8) | skb->data[5], &txd->addr[3]);
- }
-
- dma_addr = dma_map_single(&mp->myri_op->dev, skb->data,
- len, DMA_TO_DEVICE);
- sbus_writel(dma_addr, &txd->myri_gathers[0].addr);
- sbus_writel(len, &txd->myri_gathers[0].len);
- sbus_writel(1, &txd->num_sg);
- sbus_writel(KERNEL_CHANNEL, &txd->chan);
- sbus_writel(len, &txd->len);
- sbus_writel((u32)-1, &txd->csum_off);
- sbus_writel(0, &txd->csum_field);
-
- sbus_writel(NEXT_TX(entry), &sq->tail);
- DTX(("BangTheChip "));
- bang_the_chip(mp);
-
- DTX(("tbusy=0, returning 0\n"));
- netif_start_queue(dev);
- spin_unlock_irqrestore(&mp->irq_lock, flags);
- return NETDEV_TX_OK;
-}
-
-/* Create the MyriNet MAC header for an arbitrary protocol layer
- *
- * saddr=NULL means use device source address
- * daddr=NULL means leave destination address (eg unresolved arp)
- */
-static int myri_header(struct sk_buff *skb, struct net_device *dev,
- unsigned short type, const void *daddr,
- const void *saddr, unsigned len)
-{
- struct ethhdr *eth = (struct ethhdr *) skb_push(skb, ETH_HLEN);
- unsigned char *pad = (unsigned char *) skb_push(skb, MYRI_PAD_LEN);
-
-#ifdef DEBUG_HEADER
- DHDR(("myri_header: pad[%02x,%02x] ", pad[0], pad[1]));
- dump_ehdr(eth);
-#endif
-
- /* Set the MyriNET padding identifier. */
- pad[0] = MYRI_PAD_LEN;
- pad[1] = 0xab;
-
- /* Set the protocol type. For a packet of type ETH_P_802_3/2 we put the
- * length in here instead.
- */
- if (type != ETH_P_802_3 && type != ETH_P_802_2)
- eth->h_proto = htons(type);
- else
- eth->h_proto = htons(len);
-
- /* Set the source hardware address. */
- if (saddr)
- memcpy(eth->h_source, saddr, dev->addr_len);
- else
- memcpy(eth->h_source, dev->dev_addr, dev->addr_len);
-
- /* Anyway, the loopback-device should never use this function... */
- if (dev->flags & IFF_LOOPBACK) {
- int i;
- for (i = 0; i < dev->addr_len; i++)
- eth->h_dest[i] = 0;
- return dev->hard_header_len;
- }
-
- if (daddr) {
- memcpy(eth->h_dest, daddr, dev->addr_len);
- return dev->hard_header_len;
- }
- return -dev->hard_header_len;
-}
-
-/* Rebuild the MyriNet MAC header. This is called after an ARP
- * (or in future other address resolution) has completed on this
- * sk_buff. We now let ARP fill in the other fields.
- */
-static int myri_rebuild_header(struct sk_buff *skb)
-{
- unsigned char *pad = (unsigned char *) skb->data;
- struct ethhdr *eth = (struct ethhdr *) (pad + MYRI_PAD_LEN);
- struct net_device *dev = skb->dev;
-
-#ifdef DEBUG_HEADER
- DHDR(("myri_rebuild_header: pad[%02x,%02x] ", pad[0], pad[1]));
- dump_ehdr(eth);
-#endif
-
- /* Refill MyriNet padding identifiers, this is just being anal. */
- pad[0] = MYRI_PAD_LEN;
- pad[1] = 0xab;
-
- switch (eth->h_proto)
- {
-#ifdef CONFIG_INET
- case cpu_to_be16(ETH_P_IP):
- return arp_find(eth->h_dest, skb);
-#endif
-
- default:
- printk(KERN_DEBUG
- "%s: unable to resolve type %X addresses.\n",
- dev->name, (int)eth->h_proto);
-
- memcpy(eth->h_source, dev->dev_addr, dev->addr_len);
- return 0;
- break;
- }
-
- return 0;
-}
-
-static int myri_header_cache(const struct neighbour *neigh, struct hh_cache *hh)
-{
- unsigned short type = hh->hh_type;
- unsigned char *pad;
- struct ethhdr *eth;
- const struct net_device *dev = neigh->dev;
-
- pad = ((unsigned char *) hh->hh_data) +
- HH_DATA_OFF(sizeof(*eth) + MYRI_PAD_LEN);
- eth = (struct ethhdr *) (pad + MYRI_PAD_LEN);
-
- if (type == htons(ETH_P_802_3))
- return -1;
-
- /* Refill MyriNet padding identifiers, this is just being anal. */
- pad[0] = MYRI_PAD_LEN;
- pad[1] = 0xab;
-
- eth->h_proto = type;
- memcpy(eth->h_source, dev->dev_addr, dev->addr_len);
- memcpy(eth->h_dest, neigh->ha, dev->addr_len);
- hh->hh_len = 16;
- return 0;
-}
-
-
-/* Called by Address Resolution module to notify changes in address. */
-void myri_header_cache_update(struct hh_cache *hh,
- const struct net_device *dev,
- const unsigned char * haddr)
-{
- memcpy(((u8*)hh->hh_data) + HH_DATA_OFF(sizeof(struct ethhdr)),
- haddr, dev->addr_len);
-}
-
-static int myri_change_mtu(struct net_device *dev, int new_mtu)
-{
- if ((new_mtu < (ETH_HLEN + MYRI_PAD_LEN)) || (new_mtu > MYRINET_MTU))
- return -EINVAL;
- dev->mtu = new_mtu;
- return 0;
-}
-
-static void myri_set_multicast(struct net_device *dev)
-{
- /* Do nothing, all MyriCOM nodes transmit multicast frames
- * as broadcast packets...
- */
-}
-
-static inline void set_boardid_from_idprom(struct myri_eth *mp, int num)
-{
- mp->eeprom.id[0] = 0;
- mp->eeprom.id[1] = idprom->id_machtype;
- mp->eeprom.id[2] = (idprom->id_sernum >> 16) & 0xff;
- mp->eeprom.id[3] = (idprom->id_sernum >> 8) & 0xff;
- mp->eeprom.id[4] = (idprom->id_sernum >> 0) & 0xff;
- mp->eeprom.id[5] = num;
-}
-
-static inline void determine_reg_space_size(struct myri_eth *mp)
-{
- switch(mp->eeprom.cpuvers) {
- case CPUVERS_2_3:
- case CPUVERS_3_0:
- case CPUVERS_3_1:
- case CPUVERS_3_2:
- mp->reg_size = (3 * 128 * 1024) + 4096;
- break;
-
- case CPUVERS_4_0:
- case CPUVERS_4_1:
- mp->reg_size = ((4096<<1) + mp->eeprom.ramsz);
- break;
-
- case CPUVERS_4_2:
- case CPUVERS_5_0:
- default:
- printk("myricom: AIEEE weird cpu version %04x assuming pre4.0\n",
- mp->eeprom.cpuvers);
- mp->reg_size = (3 * 128 * 1024) + 4096;
- }
-}
-
-#ifdef DEBUG_DETECT
-static void dump_eeprom(struct myri_eth *mp)
-{
- printk("EEPROM: clockval[%08x] cpuvers[%04x] "
- "id[%02x,%02x,%02x,%02x,%02x,%02x]\n",
- mp->eeprom.cval, mp->eeprom.cpuvers,
- mp->eeprom.id[0], mp->eeprom.id[1], mp->eeprom.id[2],
- mp->eeprom.id[3], mp->eeprom.id[4], mp->eeprom.id[5]);
- printk("EEPROM: ramsz[%08x]\n", mp->eeprom.ramsz);
- printk("EEPROM: fvers[%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x\n",
- mp->eeprom.fvers[0], mp->eeprom.fvers[1], mp->eeprom.fvers[2],
- mp->eeprom.fvers[3], mp->eeprom.fvers[4], mp->eeprom.fvers[5],
- mp->eeprom.fvers[6], mp->eeprom.fvers[7]);
- printk("EEPROM: %02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x\n",
- mp->eeprom.fvers[8], mp->eeprom.fvers[9], mp->eeprom.fvers[10],
- mp->eeprom.fvers[11], mp->eeprom.fvers[12], mp->eeprom.fvers[13],
- mp->eeprom.fvers[14], mp->eeprom.fvers[15]);
- printk("EEPROM: %02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x\n",
- mp->eeprom.fvers[16], mp->eeprom.fvers[17], mp->eeprom.fvers[18],
- mp->eeprom.fvers[19], mp->eeprom.fvers[20], mp->eeprom.fvers[21],
- mp->eeprom.fvers[22], mp->eeprom.fvers[23]);
- printk("EEPROM: %02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x]\n",
- mp->eeprom.fvers[24], mp->eeprom.fvers[25], mp->eeprom.fvers[26],
- mp->eeprom.fvers[27], mp->eeprom.fvers[28], mp->eeprom.fvers[29],
- mp->eeprom.fvers[30], mp->eeprom.fvers[31]);
- printk("EEPROM: mvers[%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x\n",
- mp->eeprom.mvers[0], mp->eeprom.mvers[1], mp->eeprom.mvers[2],
- mp->eeprom.mvers[3], mp->eeprom.mvers[4], mp->eeprom.mvers[5],
- mp->eeprom.mvers[6], mp->eeprom.mvers[7]);
- printk("EEPROM: %02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x]\n",
- mp->eeprom.mvers[8], mp->eeprom.mvers[9], mp->eeprom.mvers[10],
- mp->eeprom.mvers[11], mp->eeprom.mvers[12], mp->eeprom.mvers[13],
- mp->eeprom.mvers[14], mp->eeprom.mvers[15]);
- printk("EEPROM: dlval[%04x] brd_type[%04x] bus_type[%04x] prod_code[%04x]\n",
- mp->eeprom.dlval, mp->eeprom.brd_type, mp->eeprom.bus_type,
- mp->eeprom.prod_code);
- printk("EEPROM: serial_num[%08x]\n", mp->eeprom.serial_num);
-}
-#endif
-
-static const struct header_ops myri_header_ops = {
- .create = myri_header,
- .rebuild = myri_rebuild_header,
- .cache = myri_header_cache,
- .cache_update = myri_header_cache_update,
-};
-
-static const struct net_device_ops myri_ops = {
- .ndo_open = myri_open,
- .ndo_stop = myri_close,
- .ndo_start_xmit = myri_start_xmit,
- .ndo_set_multicast_list = myri_set_multicast,
- .ndo_tx_timeout = myri_tx_timeout,
- .ndo_change_mtu = myri_change_mtu,
- .ndo_set_mac_address = eth_mac_addr,
- .ndo_validate_addr = eth_validate_addr,
-};
-
-static int __devinit myri_sbus_probe(struct platform_device *op)
-{
- struct device_node *dp = op->dev.of_node;
- static unsigned version_printed;
- struct net_device *dev;
- struct myri_eth *mp;
- const void *prop;
- static int num;
- int i, len;
-
- DET(("myri_ether_init(%p,%d):\n", op, num));
- dev = alloc_etherdev(sizeof(struct myri_eth));
- if (!dev)
- return -ENOMEM;
-
- if (version_printed++ == 0)
- printk(version);
-
- SET_NETDEV_DEV(dev, &op->dev);
-
- mp = netdev_priv(dev);
- spin_lock_init(&mp->irq_lock);
- mp->myri_op = op;
-
- /* Clean out skb arrays. */
- for (i = 0; i < (RX_RING_SIZE + 1); i++)
- mp->rx_skbs[i] = NULL;
-
- for (i = 0; i < TX_RING_SIZE; i++)
- mp->tx_skbs[i] = NULL;
-
- /* First check for EEPROM information. */
- prop = of_get_property(dp, "myrinet-eeprom-info", &len);
-
- if (prop)
- memcpy(&mp->eeprom, prop, sizeof(struct myri_eeprom));
- if (!prop) {
- /* No eeprom property, must cook up the values ourselves. */
- DET(("No EEPROM: "));
- mp->eeprom.bus_type = BUS_TYPE_SBUS;
- mp->eeprom.cpuvers =
- of_getintprop_default(dp, "cpu_version", 0);
- mp->eeprom.cval =
- of_getintprop_default(dp, "clock_value", 0);
- mp->eeprom.ramsz = of_getintprop_default(dp, "sram_size", 0);
- if (!mp->eeprom.cpuvers)
- mp->eeprom.cpuvers = CPUVERS_2_3;
- if (mp->eeprom.cpuvers < CPUVERS_3_0)
- mp->eeprom.cval = 0;
- if (!mp->eeprom.ramsz)
- mp->eeprom.ramsz = (128 * 1024);
-
- prop = of_get_property(dp, "myrinet-board-id", &len);
- if (prop)
- memcpy(&mp->eeprom.id[0], prop, 6);
- else
- set_boardid_from_idprom(mp, num);
-
- prop = of_get_property(dp, "fpga_version", &len);
- if (prop)
- memcpy(&mp->eeprom.fvers[0], prop, 32);
- else
- memset(&mp->eeprom.fvers[0], 0, 32);
-
- if (mp->eeprom.cpuvers == CPUVERS_4_1) {
- if (mp->eeprom.ramsz == (128 * 1024))
- mp->eeprom.ramsz = (256 * 1024);
- if ((mp->eeprom.cval == 0x40414041) ||
- (mp->eeprom.cval == 0x90449044))
- mp->eeprom.cval = 0x50e450e4;
- }
- }
-#ifdef DEBUG_DETECT
- dump_eeprom(mp);
-#endif
-
- for (i = 0; i < 6; i++)
- dev->dev_addr[i] = mp->eeprom.id[i];
-
- determine_reg_space_size(mp);
-
- /* Map in the MyriCOM register/localram set. */
- if (mp->eeprom.cpuvers < CPUVERS_4_0) {
- /* XXX Makes no sense, if control reg is non-existent this
- * XXX driver cannot function at all... maybe pre-4.0 is
- * XXX only a valid version for PCI cards? Ask feldy...
- */
- DET(("Mapping regs for cpuvers < CPUVERS_4_0\n"));
- mp->regs = of_ioremap(&op->resource[0], 0,
- mp->reg_size, "MyriCOM Regs");
- if (!mp->regs) {
- printk("MyriCOM: Cannot map MyriCOM registers.\n");
- goto err;
- }
- mp->lanai = mp->regs + (256 * 1024);
- mp->lregs = mp->lanai + (0x10000 * 2);
- } else {
- DET(("Mapping regs for cpuvers >= CPUVERS_4_0\n"));
- mp->cregs = of_ioremap(&op->resource[0], 0,
- PAGE_SIZE, "MyriCOM Control Regs");
- mp->lregs = of_ioremap(&op->resource[0], (256 * 1024),
- PAGE_SIZE, "MyriCOM LANAI Regs");
- mp->lanai = of_ioremap(&op->resource[0], (512 * 1024),
- mp->eeprom.ramsz, "MyriCOM SRAM");
- }
- DET(("Registers mapped: cregs[%p] lregs[%p] lanai[%p]\n",
- mp->cregs, mp->lregs, mp->lanai));
-
- if (mp->eeprom.cpuvers >= CPUVERS_4_0)
- mp->shmem_base = 0xf000;
- else
- mp->shmem_base = 0x8000;
-
- DET(("Shared memory base is %04x, ", mp->shmem_base));
-
- mp->shmem = (struct myri_shmem __iomem *)
- (mp->lanai + (mp->shmem_base * 2));
- DET(("shmem mapped at %p\n", mp->shmem));
-
- mp->rqack = &mp->shmem->channel.recvqa;
- mp->rq = &mp->shmem->channel.recvq;
- mp->sq = &mp->shmem->channel.sendq;
-
- /* Reset the board. */
- DET(("Resetting LANAI\n"));
- myri_reset_off(mp->lregs, mp->cregs);
- myri_reset_on(mp->cregs);
-
- /* Turn IRQ's off. */
- myri_disable_irq(mp->lregs, mp->cregs);
-
- /* Reset once more. */
- myri_reset_on(mp->cregs);
-
- /* Get the supported DVMA burst sizes from our SBUS. */
- mp->myri_bursts = of_getintprop_default(dp->parent,
- "burst-sizes", 0x00);
- if (!sbus_can_burst64())
- mp->myri_bursts &= ~(DMA_BURST64);
-
- DET(("MYRI bursts %02x\n", mp->myri_bursts));
-
- /* Encode SBUS interrupt level in second control register. */
- i = of_getintprop_default(dp, "interrupts", 0);
- if (i == 0)
- i = 4;
- DET(("prom_getint(interrupts)==%d, irqlvl set to %04x\n",
- i, (1 << i)));
-
- sbus_writel((1 << i), mp->cregs + MYRICTRL_IRQLVL);
-
- mp->dev = dev;
- dev->watchdog_timeo = 5*HZ;
- dev->irq = op->archdata.irqs[0];
- dev->netdev_ops = &myri_ops;
-
- /* Register interrupt handler now. */
- DET(("Requesting MYRIcom IRQ line.\n"));
- if (request_irq(dev->irq, myri_interrupt,
- IRQF_SHARED, "MyriCOM Ethernet", (void *) dev)) {
- printk("MyriCOM: Cannot register interrupt handler.\n");
- goto err;
- }
-
- dev->mtu = MYRINET_MTU;
- dev->header_ops = &myri_header_ops;
-
- dev->hard_header_len = (ETH_HLEN + MYRI_PAD_LEN);
-
- /* Load code onto the LANai. */
- DET(("Loading LANAI firmware\n"));
- if (myri_load_lanai(mp)) {
- printk(KERN_ERR "MyriCOM: Cannot Load LANAI firmware.\n");
- goto err_free_irq;
- }
-
- if (register_netdev(dev)) {
- printk("MyriCOM: Cannot register device.\n");
- goto err_free_irq;
- }
-
- dev_set_drvdata(&op->dev, mp);
-
- num++;
-
- printk("%s: MyriCOM MyriNET Ethernet %pM\n",
- dev->name, dev->dev_addr);
-
- return 0;
-
-err_free_irq:
- free_irq(dev->irq, dev);
-err:
- /* This will also free the co-allocated private data*/
- free_netdev(dev);
- return -ENODEV;
-}
-
-static int __devexit myri_sbus_remove(struct platform_device *op)
-{
- struct myri_eth *mp = dev_get_drvdata(&op->dev);
- struct net_device *net_dev = mp->dev;
-
- unregister_netdev(net_dev);
-
- free_irq(net_dev->irq, net_dev);
-
- if (mp->eeprom.cpuvers < CPUVERS_4_0) {
- of_iounmap(&op->resource[0], mp->regs, mp->reg_size);
- } else {
- of_iounmap(&op->resource[0], mp->cregs, PAGE_SIZE);
- of_iounmap(&op->resource[0], mp->lregs, (256 * 1024));
- of_iounmap(&op->resource[0], mp->lanai, (512 * 1024));
- }
-
- free_netdev(net_dev);
-
- dev_set_drvdata(&op->dev, NULL);
-
- return 0;
-}
-
-static const struct of_device_id myri_sbus_match[] = {
- {
- .name = "MYRICOM,mlanai",
- },
- {
- .name = "myri",
- },
- {},
-};
-
-MODULE_DEVICE_TABLE(of, myri_sbus_match);
-
-static struct platform_driver myri_sbus_driver = {
- .driver = {
- .name = "myri",
- .owner = THIS_MODULE,
- .of_match_table = myri_sbus_match,
- },
- .probe = myri_sbus_probe,
- .remove = __devexit_p(myri_sbus_remove),
-};
-
-static int __init myri_sbus_init(void)
-{
- return platform_driver_register(&myri_sbus_driver);
-}
-
-static void __exit myri_sbus_exit(void)
-{
- platform_driver_unregister(&myri_sbus_driver);
-}
-
-module_init(myri_sbus_init);
-module_exit(myri_sbus_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_FIRMWARE(FWNAME);
diff --git a/drivers/net/myri_sbus.h b/drivers/net/myri_sbus.h
deleted file mode 100644
index 80a2fa5..0000000
--- a/drivers/net/myri_sbus.h
+++ /dev/null
@@ -1,311 +0,0 @@
-/* myri_sbus.h: Defines for MyriCOM MyriNET SBUS card driver.
- *
- * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
- */
-
-#ifndef _MYRI_SBUS_H
-#define _MYRI_SBUS_H
-
-/* LANAI Registers */
-#define LANAI_IPF0 0x00UL /* Context zero state registers.*/
-#define LANAI_CUR0 0x04UL
-#define LANAI_PREV0 0x08UL
-#define LANAI_DATA0 0x0cUL
-#define LANAI_DPF0 0x10UL
-#define LANAI_IPF1 0x14UL /* Context one state registers. */
-#define LANAI_CUR1 0x18UL
-#define LANAI_PREV1 0x1cUL
-#define LANAI_DATA1 0x20UL
-#define LANAI_DPF1 0x24UL
-#define LANAI_ISTAT 0x28UL /* Interrupt status. */
-#define LANAI_EIMASK 0x2cUL /* External IRQ mask. */
-#define LANAI_ITIMER 0x30UL /* IRQ timer. */
-#define LANAI_RTC 0x34UL /* Real Time Clock */
-#define LANAI_CSUM 0x38UL /* Checksum. */
-#define LANAI_DMAXADDR 0x3cUL /* SBUS DMA external address. */
-#define LANAI_DMALADDR 0x40UL /* SBUS DMA local address. */
-#define LANAI_DMACTR 0x44UL /* SBUS DMA counter. */
-#define LANAI_RXDMAPTR 0x48UL /* Receive DMA pointer. */
-#define LANAI_RXDMALIM 0x4cUL /* Receive DMA limit. */
-#define LANAI_TXDMAPTR 0x50UL /* Transmit DMA pointer. */
-#define LANAI_TXDMALIM 0x54UL /* Transmit DMA limit. */
-#define LANAI_TXDMALIMT 0x58UL /* Transmit DMA limit w/tail. */
- /* 0x5cUL, reserved */
-#define LANAI_RBYTE 0x60UL /* Receive byte. */
- /* 0x64-->0x6c, reserved */
-#define LANAI_RHALF 0x70UL /* Receive half-word. */
- /* 0x72UL, reserved */
-#define LANAI_RWORD 0x74UL /* Receive word. */
-#define LANAI_SALIGN 0x78UL /* Send align. */
-#define LANAI_SBYTE 0x7cUL /* SingleSend send-byte. */
-#define LANAI_SHALF 0x80UL /* SingleSend send-halfword. */
-#define LANAI_SWORD 0x84UL /* SingleSend send-word. */
-#define LANAI_SSENDT 0x88UL /* SingleSend special. */
-#define LANAI_DMADIR 0x8cUL /* DMA direction. */
-#define LANAI_DMASTAT 0x90UL /* DMA status. */
-#define LANAI_TIMEO 0x94UL /* Timeout register. */
-#define LANAI_MYRINET 0x98UL /* XXX MAGIC myricom thing */
-#define LANAI_HWDEBUG 0x9cUL /* Hardware debugging reg. */
-#define LANAI_LEDS 0xa0UL /* LED control. */
-#define LANAI_VERS 0xa4UL /* Version register. */
-#define LANAI_LINKON 0xa8UL /* Link activation reg. */
- /* 0xac-->0x104, reserved */
-#define LANAI_CVAL 0x108UL /* Clock value register. */
-#define LANAI_REG_SIZE 0x10cUL
-
-/* Interrupt status bits. */
-#define ISTAT_DEBUG 0x80000000
-#define ISTAT_HOST 0x40000000
-#define ISTAT_LAN7 0x00800000
-#define ISTAT_LAN6 0x00400000
-#define ISTAT_LAN5 0x00200000
-#define ISTAT_LAN4 0x00100000
-#define ISTAT_LAN3 0x00080000
-#define ISTAT_LAN2 0x00040000
-#define ISTAT_LAN1 0x00020000
-#define ISTAT_LAN0 0x00010000
-#define ISTAT_WRDY 0x00008000
-#define ISTAT_HRDY 0x00004000
-#define ISTAT_SRDY 0x00002000
-#define ISTAT_LINK 0x00001000
-#define ISTAT_FRES 0x00000800
-#define ISTAT_NRES 0x00000800
-#define ISTAT_WAKE 0x00000400
-#define ISTAT_OB2 0x00000200
-#define ISTAT_OB1 0x00000100
-#define ISTAT_TAIL 0x00000080
-#define ISTAT_WDOG 0x00000040
-#define ISTAT_TIME 0x00000020
-#define ISTAT_DMA 0x00000010
-#define ISTAT_SEND 0x00000008
-#define ISTAT_BUF 0x00000004
-#define ISTAT_RECV 0x00000002
-#define ISTAT_BRDY 0x00000001
-
-/* MYRI Registers */
-#define MYRI_RESETOFF 0x00UL
-#define MYRI_RESETON 0x04UL
-#define MYRI_IRQOFF 0x08UL
-#define MYRI_IRQON 0x0cUL
-#define MYRI_WAKEUPOFF 0x10UL
-#define MYRI_WAKEUPON 0x14UL
-#define MYRI_IRQREAD 0x18UL
- /* 0x1c-->0x3ffc, reserved */
-#define MYRI_LOCALMEM 0x4000UL
-#define MYRI_REG_SIZE 0x25000UL
-
-/* Shared memory interrupt mask. */
-#define SHMEM_IMASK_RX 0x00000002
-#define SHMEM_IMASK_TX 0x00000001
-
-/* Just to make things readable. */
-#define KERNEL_CHANNEL 0
-
-/* The size of this must be >= 129 bytes. */
-struct myri_eeprom {
- unsigned int cval;
- unsigned short cpuvers;
- unsigned char id[6];
- unsigned int ramsz;
- unsigned char fvers[32];
- unsigned char mvers[16];
- unsigned short dlval;
- unsigned short brd_type;
- unsigned short bus_type;
- unsigned short prod_code;
- unsigned int serial_num;
- unsigned short _reserved[24];
- unsigned int _unused[2];
-};
-
-/* EEPROM bus types, only SBUS is valid in this driver. */
-#define BUS_TYPE_SBUS 1
-
-/* EEPROM CPU revisions. */
-#define CPUVERS_2_3 0x0203
-#define CPUVERS_3_0 0x0300
-#define CPUVERS_3_1 0x0301
-#define CPUVERS_3_2 0x0302
-#define CPUVERS_4_0 0x0400
-#define CPUVERS_4_1 0x0401
-#define CPUVERS_4_2 0x0402
-#define CPUVERS_5_0 0x0500
-
-/* MYRI Control Registers */
-#define MYRICTRL_CTRL 0x00UL
-#define MYRICTRL_IRQLVL 0x02UL
-#define MYRICTRL_REG_SIZE 0x04UL
-
-/* Global control register defines. */
-#define CONTROL_ROFF 0x8000 /* Reset OFF. */
-#define CONTROL_RON 0x4000 /* Reset ON. */
-#define CONTROL_EIRQ 0x2000 /* Enable IRQ's. */
-#define CONTROL_DIRQ 0x1000 /* Disable IRQ's. */
-#define CONTROL_WON 0x0800 /* Wake-up ON. */
-
-#define MYRI_SCATTER_ENTRIES 8
-#define MYRI_GATHER_ENTRIES 16
-
-struct myri_sglist {
- u32 addr;
- u32 len;
-};
-
-struct myri_rxd {
- struct myri_sglist myri_scatters[MYRI_SCATTER_ENTRIES]; /* DMA scatter list.*/
- u32 csum; /* HW computed checksum. */
- u32 ctx;
- u32 num_sg; /* Total scatter entries. */
-};
-
-struct myri_txd {
- struct myri_sglist myri_gathers[MYRI_GATHER_ENTRIES]; /* DMA scatter list. */
- u32 num_sg; /* Total scatter entries. */
- u16 addr[4]; /* XXX address */
- u32 chan;
- u32 len; /* Total length of packet. */
- u32 csum_off; /* Where data to csum is. */
- u32 csum_field; /* Where csum goes in pkt. */
-};
-
-#define MYRINET_MTU 8432
-#define RX_ALLOC_SIZE 8448
-#define MYRI_PAD_LEN 2
-#define RX_COPY_THRESHOLD 256
-
-/* These numbers are cast in stone, new firmware is needed if
- * you want to change them.
- */
-#define TX_RING_MAXSIZE 16
-#define RX_RING_MAXSIZE 16
-
-#define TX_RING_SIZE 16
-#define RX_RING_SIZE 16
-
-/* GRRR... */
-static __inline__ int NEXT_RX(int num)
-{
- /* XXX >=??? */
- if(++num > RX_RING_SIZE)
- num = 0;
- return num;
-}
-
-static __inline__ int PREV_RX(int num)
-{
- if(--num < 0)
- num = RX_RING_SIZE;
- return num;
-}
-
-#define NEXT_TX(num) (((num) + 1) & (TX_RING_SIZE - 1))
-#define PREV_TX(num) (((num) - 1) & (TX_RING_SIZE - 1))
-
-#define TX_BUFFS_AVAIL(head, tail) \
- ((head) <= (tail) ? \
- (head) + (TX_RING_SIZE - 1) - (tail) : \
- (head) - (tail) - 1)
-
-struct sendq {
- u32 tail;
- u32 head;
- u32 hdebug;
- u32 mdebug;
- struct myri_txd myri_txd[TX_RING_MAXSIZE];
-};
-
-struct recvq {
- u32 head;
- u32 tail;
- u32 hdebug;
- u32 mdebug;
- struct myri_rxd myri_rxd[RX_RING_MAXSIZE + 1];
-};
-
-#define MYRI_MLIST_SIZE 8
-
-struct mclist {
- u32 maxlen;
- u32 len;
- u32 cache;
- struct pair {
- u8 addr[8];
- u32 val;
- } mc_pairs[MYRI_MLIST_SIZE];
- u8 bcast_addr[8];
-};
-
-struct myri_channel {
- u32 state; /* State of the channel. */
- u32 busy; /* Channel is busy. */
- struct sendq sendq; /* Device tx queue. */
- struct recvq recvq; /* Device rx queue. */
- struct recvq recvqa; /* Device rx queue acked. */
- u32 rbytes; /* Receive bytes. */
- u32 sbytes; /* Send bytes. */
- u32 rmsgs; /* Receive messages. */
- u32 smsgs; /* Send messages. */
- struct mclist mclist; /* Device multicast list. */
-};
-
-/* Values for per-channel state. */
-#define STATE_WFH 0 /* Waiting for HOST. */
-#define STATE_WFN 1 /* Waiting for NET. */
-#define STATE_READY 2 /* Ready. */
-
-struct myri_shmem {
- u8 addr[8]; /* Board's address. */
- u32 nchan; /* Number of channels. */
- u32 burst; /* SBUS dma burst enable. */
- u32 shakedown; /* DarkkkkStarrr Crashesss... */
- u32 send; /* Send wanted. */
- u32 imask; /* Interrupt enable mask. */
- u32 mlevel; /* Map level. */
- u32 debug[4]; /* Misc. debug areas. */
- struct myri_channel channel; /* Only one channel on a host. */
-};
-
-struct myri_eth {
- /* These are frequently accessed, keep together
- * to obtain good cache hit rates.
- */
- spinlock_t irq_lock;
- struct myri_shmem __iomem *shmem; /* Shared data structures. */
- void __iomem *cregs; /* Control register space. */
- struct recvq __iomem *rqack; /* Where we ack rx's. */
- struct recvq __iomem *rq; /* Where we put buffers. */
- struct sendq __iomem *sq; /* Where we stuff tx's. */
- struct net_device *dev; /* Linux/NET dev struct. */
- int tx_old; /* To speed up tx cleaning. */
- void __iomem *lregs; /* Quick ptr to LANAI regs. */
- struct sk_buff *rx_skbs[RX_RING_SIZE+1];/* RX skb's */
- struct sk_buff *tx_skbs[TX_RING_SIZE]; /* TX skb's */
-
- /* These are less frequently accessed. */
- void __iomem *regs; /* MyriCOM register space. */
- void __iomem *lanai; /* View 2 of register space. */
- unsigned int myri_bursts; /* SBUS bursts. */
- struct myri_eeprom eeprom; /* Local copy of EEPROM. */
- unsigned int reg_size; /* Size of register space. */
- unsigned int shmem_base; /* Offset to shared ram. */
- struct platform_device *myri_op; /* Our OF device struct. */
-};
-
-/* We use this to acquire receive skb's that we can DMA directly into. */
-#define ALIGNED_RX_SKB_ADDR(addr) \
- ((((unsigned long)(addr) + (64 - 1)) & ~(64 - 1)) - (unsigned long)(addr))
-static inline struct sk_buff *myri_alloc_skb(unsigned int length, gfp_t gfp_flags)
-{
- struct sk_buff *skb;
-
- skb = alloc_skb(length + 64, gfp_flags);
- if(skb) {
- int offset = ALIGNED_RX_SKB_ADDR(skb->data);
-
- if(offset)
- skb_reserve(skb, offset);
- }
- return skb;
-}
-
-#endif /* !(_MYRI_SBUS_H) */
diff --git a/drivers/net/netx-eth.c b/drivers/net/netx-eth.c
index 2e4b421..2dfee89 100644
--- a/drivers/net/netx-eth.c
+++ b/drivers/net/netx-eth.c
@@ -18,6 +18,7 @@
*/
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/delay.h>
diff --git a/drivers/net/netxen/netxen_nic_ctx.c b/drivers/net/netxen/netxen_nic_ctx.c
index f16966a..a925392 100644
--- a/drivers/net/netxen/netxen_nic_ctx.c
+++ b/drivers/net/netxen/netxen_nic_ctx.c
@@ -163,7 +163,7 @@
rq_size, &hostrq_phys_addr);
if (addr == NULL)
return -ENOMEM;
- prq = (nx_hostrq_rx_ctx_t *)addr;
+ prq = addr;
addr = pci_alloc_consistent(adapter->pdev,
rsp_size, &cardrsp_phys_addr);
@@ -171,7 +171,7 @@
err = -ENOMEM;
goto out_free_rq;
}
- prsp = (nx_cardrsp_rx_ctx_t *)addr;
+ prsp = addr;
prq->host_rsp_dma_addr = cpu_to_le64(cardrsp_phys_addr);
@@ -318,10 +318,10 @@
}
memset(rq_addr, 0, rq_size);
- prq = (nx_hostrq_tx_ctx_t *)rq_addr;
+ prq = rq_addr;
memset(rsp_addr, 0, rsp_size);
- prsp = (nx_cardrsp_tx_ctx_t *)rsp_addr;
+ prsp = rsp_addr;
prq->host_rsp_dma_addr = cpu_to_le64(rsp_phys_addr);
@@ -629,7 +629,7 @@
}
memset(addr, 0, sizeof(struct netxen_ring_ctx));
- recv_ctx->hwctx = (struct netxen_ring_ctx *)addr;
+ recv_ctx->hwctx = addr;
recv_ctx->hwctx->ctx_id = cpu_to_le32(port);
recv_ctx->hwctx->cmd_consumer_offset =
cpu_to_le64(recv_ctx->phys_addr +
@@ -648,7 +648,7 @@
goto err_out_free;
}
- tx_ring->desc_head = (struct cmd_desc_type0 *)addr;
+ tx_ring->desc_head = addr;
for (ring = 0; ring < adapter->max_rds_rings; ring++) {
rds_ring = &recv_ctx->rds_rings[ring];
@@ -662,7 +662,7 @@
err = -ENOMEM;
goto err_out_free;
}
- rds_ring->desc_head = (struct rcv_desc *)addr;
+ rds_ring->desc_head = addr;
if (NX_IS_REVISION_P2(adapter->ahw.revision_id))
rds_ring->crb_rcv_producer =
@@ -683,7 +683,7 @@
err = -ENOMEM;
goto err_out_free;
}
- sds_ring->desc_head = (struct status_desc *)addr;
+ sds_ring->desc_head = addr;
if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
sds_ring->crb_sts_consumer =
diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c
index 5cef718..3f89e57 100644
--- a/drivers/net/netxen/netxen_nic_hw.c
+++ b/drivers/net/netxen/netxen_nic_hw.c
@@ -809,6 +809,9 @@
u64 word;
int rv = 0;
+ if (!test_bit(__NX_FW_ATTACHED, &adapter->state))
+ return 0;
+
memset(&req, 0, sizeof(nx_nic_req_t));
req.qhdr = cpu_to_le64(NX_HOST_REQUEST << 23);
@@ -959,6 +962,9 @@
u64 word;
int rv;
+ if (!test_bit(__NX_FW_ATTACHED, &adapter->state))
+ return 0;
+
memset(&req, 0, sizeof(nx_nic_req_t));
req.qhdr = cpu_to_le64(NX_HOST_REQUEST << 23);
diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c
index 7f99967..ca59b4f 100644
--- a/drivers/net/netxen/netxen_nic_init.c
+++ b/drivers/net/netxen/netxen_nic_init.c
@@ -1279,7 +1279,7 @@
if (--i == 0)
break;
- };
+ }
}
if (i) {
diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c
index c0788a3..30f41e6 100644
--- a/drivers/net/netxen/netxen_nic_main.c
+++ b/drivers/net/netxen/netxen_nic_main.c
@@ -92,7 +92,8 @@
static irqreturn_t netxen_msix_intr(int irq, void *data);
static void netxen_config_indev_addr(struct net_device *dev, unsigned long);
-static struct net_device_stats *netxen_nic_get_stats(struct net_device *netdev);
+static struct rtnl_link_stats64 *netxen_nic_get_stats(struct net_device *dev,
+ struct rtnl_link_stats64 *stats);
static int netxen_nic_set_mac(struct net_device *netdev, void *p);
/* PCI Device ID Table */
@@ -520,7 +521,7 @@
.ndo_open = netxen_nic_open,
.ndo_stop = netxen_nic_close,
.ndo_start_xmit = netxen_nic_xmit_frame,
- .ndo_get_stats = netxen_nic_get_stats,
+ .ndo_get_stats64 = netxen_nic_get_stats,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_multicast_list = netxen_set_multicast_list,
.ndo_set_mac_address = netxen_nic_set_mac,
@@ -2110,10 +2111,10 @@
clear_bit(__NX_RESETTING, &adapter->state);
}
-static struct net_device_stats *netxen_nic_get_stats(struct net_device *netdev)
+static struct rtnl_link_stats64 *netxen_nic_get_stats(struct net_device *netdev,
+ struct rtnl_link_stats64 *stats)
{
struct netxen_adapter *adapter = netdev_priv(netdev);
- struct net_device_stats *stats = &netdev->stats;
stats->rx_packets = adapter->stats.rx_pkts + adapter->stats.lro_pkts;
stats->tx_packets = adapter->stats.xmitfinished;
diff --git a/drivers/net/niu.c b/drivers/net/niu.c
index cc25bff0..cd6c231 100644
--- a/drivers/net/niu.c
+++ b/drivers/net/niu.c
@@ -7,6 +7,7 @@
#include <linux/module.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/pci.h>
#include <linux/dma-mapping.h>
#include <linux/netdevice.h>
@@ -6248,9 +6249,10 @@
niu_sync_bmac_stats(np);
}
-static void niu_get_rx_stats(struct niu *np)
+static void niu_get_rx_stats(struct niu *np,
+ struct rtnl_link_stats64 *stats)
{
- unsigned long pkts, dropped, errors, bytes;
+ u64 pkts, dropped, errors, bytes;
struct rx_ring_info *rx_rings;
int i;
@@ -6272,15 +6274,16 @@
}
no_rings:
- np->dev->stats.rx_packets = pkts;
- np->dev->stats.rx_bytes = bytes;
- np->dev->stats.rx_dropped = dropped;
- np->dev->stats.rx_errors = errors;
+ stats->rx_packets = pkts;
+ stats->rx_bytes = bytes;
+ stats->rx_dropped = dropped;
+ stats->rx_errors = errors;
}
-static void niu_get_tx_stats(struct niu *np)
+static void niu_get_tx_stats(struct niu *np,
+ struct rtnl_link_stats64 *stats)
{
- unsigned long pkts, errors, bytes;
+ u64 pkts, errors, bytes;
struct tx_ring_info *tx_rings;
int i;
@@ -6299,20 +6302,22 @@
}
no_rings:
- np->dev->stats.tx_packets = pkts;
- np->dev->stats.tx_bytes = bytes;
- np->dev->stats.tx_errors = errors;
+ stats->tx_packets = pkts;
+ stats->tx_bytes = bytes;
+ stats->tx_errors = errors;
}
-static struct net_device_stats *niu_get_stats(struct net_device *dev)
+static struct rtnl_link_stats64 *niu_get_stats(struct net_device *dev,
+ struct rtnl_link_stats64 *stats)
{
struct niu *np = netdev_priv(dev);
if (netif_running(dev)) {
- niu_get_rx_stats(np);
- niu_get_tx_stats(np);
+ niu_get_rx_stats(np, stats);
+ niu_get_tx_stats(np, stats);
}
- return &dev->stats;
+
+ return stats;
}
static void niu_load_hash_xmac(struct niu *np, u16 *hash)
@@ -9710,7 +9715,7 @@
.ndo_open = niu_open,
.ndo_stop = niu_close,
.ndo_start_xmit = niu_start_xmit,
- .ndo_get_stats = niu_get_stats,
+ .ndo_get_stats64 = niu_get_stats,
.ndo_set_multicast_list = niu_set_rx_mode,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = niu_set_mac_addr,
@@ -9792,7 +9797,7 @@
goto err_out_disable_pdev;
}
- pos = pci_find_capability(pdev, PCI_CAP_ID_EXP);
+ pos = pci_pcie_cap(pdev);
if (pos <= 0) {
dev_err(&pdev->dev, "Cannot find PCI Express capability, aborting\n");
goto err_out_free_res;
diff --git a/drivers/net/ns83820.c b/drivers/net/ns83820.c
index 3e4040f..d3afb45 100644
--- a/drivers/net/ns83820.c
+++ b/drivers/net/ns83820.c
@@ -106,6 +106,7 @@
#include <linux/delay.h>
#include <linux/workqueue.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/ip.h> /* for iph */
#include <linux/in.h> /* for IPPROTO_... */
#include <linux/compiler.h>
diff --git a/drivers/net/octeon/octeon_mgmt.c b/drivers/net/octeon/octeon_mgmt.c
index b264f0f..429e08c 100644
--- a/drivers/net/octeon/octeon_mgmt.c
+++ b/drivers/net/octeon/octeon_mgmt.c
@@ -9,6 +9,7 @@
#include <linux/capability.h>
#include <linux/dma-mapping.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
diff --git a/drivers/net/phy/icplus.c b/drivers/net/phy/icplus.c
index 9a09e24..d4cbc29 100644
--- a/drivers/net/phy/icplus.c
+++ b/drivers/net/phy/icplus.c
@@ -109,11 +109,7 @@
value = phy_read(phydev, 16);
value |= 0x3;
- err = phy_write(phydev, 16, value);
- if (err < 0)
- return err;
-
- return err;
+ return phy_write(phydev, 16, value);
}
static int ip175c_read_status(struct phy_device *phydev)
diff --git a/drivers/net/ppp_async.c b/drivers/net/ppp_async.c
index c554a39..c6ba643 100644
--- a/drivers/net/ppp_async.c
+++ b/drivers/net/ppp_async.c
@@ -30,6 +30,7 @@
#include <linux/ppp_channel.h>
#include <linux/spinlock.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/jiffies.h>
#include <linux/slab.h>
#include <asm/unaligned.h>
diff --git a/drivers/net/ppp_synctty.c b/drivers/net/ppp_synctty.c
index 2573f52..736a39e 100644
--- a/drivers/net/ppp_synctty.c
+++ b/drivers/net/ppp_synctty.c
@@ -44,6 +44,7 @@
#include <linux/spinlock.h>
#include <linux/completion.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/slab.h>
#include <asm/unaligned.h>
#include <asm/uaccess.h>
diff --git a/drivers/net/pptp.c b/drivers/net/pptp.c
index 1286fe2..eae542a 100644
--- a/drivers/net/pptp.c
+++ b/drivers/net/pptp.c
@@ -30,7 +30,6 @@
#include <linux/ip.h>
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>
-#include <linux/version.h>
#include <linux/rcupdate.h>
#include <linux/spinlock.h>
diff --git a/drivers/net/ps3_gelic_net.c b/drivers/net/ps3_gelic_net.c
index b1f251d..35e47c3 100644
--- a/drivers/net/ps3_gelic_net.c
+++ b/drivers/net/ps3_gelic_net.c
@@ -28,6 +28,7 @@
#undef DEBUG
+#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
@@ -1009,7 +1010,7 @@
netdev = card->netdev[i];
break;
}
- };
+ }
if (GELIC_PORT_MAX <= i) {
pr_info("%s: unknown packet vid=%x\n", __func__, vid);
goto refill;
diff --git a/drivers/net/pxa168_eth.c b/drivers/net/pxa168_eth.c
index 5f597ca5..c1bb05b 100644
--- a/drivers/net/pxa168_eth.c
+++ b/drivers/net/pxa168_eth.c
@@ -502,7 +502,7 @@
* Pick the appropriate table, start scanning for free/reusable
* entries at the index obtained by hashing the specified MAC address
*/
- start = (struct addr_table_entry *)(pep->htpr);
+ start = pep->htpr;
entry = start + hash_function(mac_addr);
for (i = 0; i < HOP_NUMBER; i++) {
if (!(le32_to_cpu(entry->lo) & HASH_ENTRY_VALID)) {
@@ -1267,6 +1267,9 @@
pep->tx_skb[tx_index] = skb;
desc->byte_cnt = length;
desc->buf_ptr = dma_map_single(NULL, skb->data, length, DMA_TO_DEVICE);
+
+ skb_tx_timestamp(skb);
+
wmb();
desc->cmd_sts = BUF_OWNED_BY_DMA | TX_GEN_CRC | TX_FIRST_DESC |
TX_ZERO_PADDING | TX_LAST_DESC | TX_EN_INT;
diff --git a/drivers/net/qla3xxx.c b/drivers/net/qla3xxx.c
index 771bb61..2f691402 100644
--- a/drivers/net/qla3xxx.c
+++ b/drivers/net/qla3xxx.c
@@ -2873,7 +2873,7 @@
PAGE_SIZE, &qdev->shadow_reg_phy_addr);
if (qdev->shadow_reg_virt_addr != NULL) {
- qdev->preq_consumer_index = (u16 *) qdev->shadow_reg_virt_addr;
+ qdev->preq_consumer_index = qdev->shadow_reg_virt_addr;
qdev->req_consumer_index_phy_addr_high =
MS_64BITS(qdev->shadow_reg_phy_addr);
qdev->req_consumer_index_phy_addr_low =
@@ -3114,8 +3114,7 @@
qdev->small_buf_release_cnt = 8;
qdev->lrg_buf_q_producer_index = qdev->num_lbufq_entries - 1;
qdev->lrg_buf_release_cnt = 8;
- qdev->lrg_buf_next_free =
- (struct bufq_addr_element *)qdev->lrg_buf_q_virt_addr;
+ qdev->lrg_buf_next_free = qdev->lrg_buf_q_virt_addr;
qdev->small_buf_index = 0;
qdev->lrg_buf_index = 0;
qdev->lrg_buf_free_count = 0;
diff --git a/drivers/net/qlcnic/qlcnic.h b/drivers/net/qlcnic/qlcnic.h
index 480ef5c..9899a79 100644
--- a/drivers/net/qlcnic/qlcnic.h
+++ b/drivers/net/qlcnic/qlcnic.h
@@ -36,8 +36,8 @@
#define _QLCNIC_LINUX_MAJOR 5
#define _QLCNIC_LINUX_MINOR 0
-#define _QLCNIC_LINUX_SUBVERSION 18
-#define QLCNIC_LINUX_VERSIONID "5.0.18"
+#define _QLCNIC_LINUX_SUBVERSION 20
+#define QLCNIC_LINUX_VERSIONID "5.0.20"
#define QLCNIC_DRV_IDC_VER 0x01
#define QLCNIC_DRIVER_VERSION ((_QLCNIC_LINUX_MAJOR << 16) |\
(_QLCNIC_LINUX_MINOR << 8) | (_QLCNIC_LINUX_SUBVERSION))
@@ -429,6 +429,7 @@
struct qlcnic_fw_dump {
u8 clr; /* flag to indicate if dump is cleared */
+ u8 enable; /* enable/disable dump */
u32 size; /* total size of the dump */
void *data; /* dump data area */
struct qlcnic_dump_template_hdr *tmpl_hdr;
@@ -450,6 +451,7 @@
u8 revision_id;
u8 pci_func;
u8 linkup;
+ u8 loopback_state;
u16 port_type;
u16 board_type;
@@ -779,6 +781,14 @@
#define QLCNIC_IP_UP 2
#define QLCNIC_IP_DOWN 3
+#define QLCNIC_ILB_MODE 0x1
+#define QLCNIC_ELB_MODE 0x2
+
+#define QLCNIC_LINKEVENT 0x1
+#define QLCNIC_LB_RESPONSE 0x2
+#define QLCNIC_IS_LB_CONFIGURED(VAL) \
+ (VAL == (QLCNIC_LINKEVENT | QLCNIC_LB_RESPONSE))
+
/*
* Driver --> Firmware
*/
@@ -788,13 +798,17 @@
#define QLCNIC_H2C_OPCODE_LRO_REQUEST 0x7
#define QLCNIC_H2C_OPCODE_SET_MAC_RECEIVE_MODE 0xc
#define QLCNIC_H2C_OPCODE_CONFIG_IPADDR 0x12
+
#define QLCNIC_H2C_OPCODE_GET_LINKEVENT 0x15
#define QLCNIC_H2C_OPCODE_CONFIG_BRIDGING 0x17
#define QLCNIC_H2C_OPCODE_CONFIG_HW_LRO 0x18
+#define QLCNIC_H2C_OPCODE_CONFIG_LOOPBACK 0x13
+
/*
* Firmware --> Driver
*/
+#define QLCNIC_C2H_OPCODE_CONFIG_LOOPBACK 0x8f
#define QLCNIC_C2H_OPCODE_GET_LINKEVENT_RESPONSE 141
#define VPORT_MISS_MODE_DROP 0 /* drop all unmatched */
@@ -895,11 +909,11 @@
#define QLCNIC_MAC_OVERRIDE_DISABLED 0x400
#define QLCNIC_PROMISC_DISABLED 0x800
#define QLCNIC_NEED_FLR 0x1000
+#define QLCNIC_FW_RESET_OWNER 0x2000
#define QLCNIC_IS_MSI_FAMILY(adapter) \
((adapter)->flags & (QLCNIC_MSI_ENABLED | QLCNIC_MSIX_ENABLED))
#define QLCNIC_DEF_NUM_STS_DESC_RINGS 4
-#define QLCNIC_MIN_NUM_RSS_RINGS 2
#define QLCNIC_MSIX_TBL_SPACE 8192
#define QLCNIC_PCI_REG_MSIX_TBL 0x44
#define QLCNIC_MSIX_TBL_PGSIZE 4096
@@ -1219,8 +1233,7 @@
struct __cache {
__le32 addr;
- u8 stride;
- u8 rsvd;
+ __le16 stride;
__le16 init_tag_val;
__le32 size;
__le32 no_ops;
@@ -1318,9 +1331,11 @@
#define QLCNIC_DUMP_SKIP BIT_7
#define QLCNIC_DUMP_MASK_MIN 3
-#define QLCNIC_DUMP_MASK_DEF 0x0f
+#define QLCNIC_DUMP_MASK_DEF 0x7f
#define QLCNIC_DUMP_MASK_MAX 0xff
#define QLCNIC_FORCE_FW_DUMP_KEY 0xdeadfeed
+#define QLCNIC_ENABLE_FW_DUMP 0xaddfeed
+#define QLCNIC_DISABLE_FW_DUMP 0xbadfeed
struct qlcnic_dump_operations {
enum op_codes opcode;
@@ -1428,6 +1443,12 @@
void qlcnic_update_cmd_producer(struct qlcnic_adapter *adapter,
struct qlcnic_host_tx_ring *tx_ring);
void qlcnic_fetch_mac(struct qlcnic_adapter *, u32, u32, u8, u8 *);
+void qlcnic_process_rcv_ring_diag(struct qlcnic_host_sds_ring *sds_ring);
+void qlcnic_clear_lb_mode(struct qlcnic_adapter *adapter);
+int qlcnic_set_lb_mode(struct qlcnic_adapter *adapter, u8 mode);
+
+/* Functions from qlcnic_ethtool.c */
+int qlcnic_check_loopback_buff(unsigned char *data, u8 mac[]);
/* Functions from qlcnic_main.c */
int qlcnic_reset_context(struct qlcnic_adapter *);
diff --git a/drivers/net/qlcnic/qlcnic_ctx.c b/drivers/net/qlcnic/qlcnic_ctx.c
index bab041a..33f5c8a 100644
--- a/drivers/net/qlcnic/qlcnic_ctx.c
+++ b/drivers/net/qlcnic/qlcnic_ctx.c
@@ -95,8 +95,8 @@
QLCNIC_CDRP_CMD_TEMP_SIZE);
if (err != QLCNIC_RCODE_SUCCESS) {
err = QLCRD32(adapter, QLCNIC_ARG1_CRB_OFFSET);
- dev_err(&adapter->pdev->dev,
- "Failed to get template size %d\n", err);
+ dev_info(&adapter->pdev->dev,
+ "Can't get template size %d\n", err);
err = -EIO;
return err;
}
@@ -126,7 +126,7 @@
err = -EIO;
goto error;
}
- tmp_tmpl = (struct qlcnic_dump_template_hdr *) tmp_addr;
+ tmp_tmpl = tmp_addr;
csum = qlcnic_temp_checksum((uint32_t *) tmp_addr, temp_size);
if (csum) {
dev_err(&adapter->pdev->dev,
@@ -139,7 +139,7 @@
err = -EIO;
goto error;
}
- tmp_buf = (u32 *) tmp_addr;
+ tmp_buf = tmp_addr;
template = (u32 *) ahw->fw_dump.tmpl_hdr;
for (i = 0; i < temp_size/sizeof(u32); i++)
*template++ = __le32_to_cpu(*tmp_buf++);
@@ -150,6 +150,7 @@
tmpl_hdr->drv_cap_mask = tmpl_hdr->cap_mask;
else
tmpl_hdr->drv_cap_mask = QLCNIC_DUMP_MASK_DEF;
+ ahw->fw_dump.enable = 1;
error:
dma_free_coherent(&adapter->pdev->dev, temp_size, tmp_addr, tmp_addr_t);
return err;
@@ -214,7 +215,7 @@
&hostrq_phys_addr, GFP_KERNEL);
if (addr == NULL)
return -ENOMEM;
- prq = (struct qlcnic_hostrq_rx_ctx *)addr;
+ prq = addr;
addr = dma_alloc_coherent(&adapter->pdev->dev, rsp_size,
&cardrsp_phys_addr, GFP_KERNEL);
@@ -222,7 +223,7 @@
err = -ENOMEM;
goto out_free_rq;
}
- prsp = (struct qlcnic_cardrsp_rx_ctx *)addr;
+ prsp = addr;
prq->host_rsp_dma_addr = cpu_to_le64(cardrsp_phys_addr);
@@ -380,10 +381,10 @@
}
memset(rq_addr, 0, rq_size);
- prq = (struct qlcnic_hostrq_tx_ctx *)rq_addr;
+ prq = rq_addr;
memset(rsp_addr, 0, rsp_size);
- prsp = (struct qlcnic_cardrsp_tx_ctx *)rsp_addr;
+ prsp = rsp_addr;
prq->host_rsp_dma_addr = cpu_to_le64(rsp_phys_addr);
@@ -493,7 +494,7 @@
goto err_out_free;
}
- tx_ring->desc_head = (struct cmd_desc_type0 *)addr;
+ tx_ring->desc_head = addr;
for (ring = 0; ring < adapter->max_rds_rings; ring++) {
rds_ring = &recv_ctx->rds_rings[ring];
@@ -506,7 +507,7 @@
err = -ENOMEM;
goto err_out_free;
}
- rds_ring->desc_head = (struct rcv_desc *)addr;
+ rds_ring->desc_head = addr;
}
@@ -522,7 +523,7 @@
err = -ENOMEM;
goto err_out_free;
}
- sds_ring->desc_head = (struct status_desc *)addr;
+ sds_ring->desc_head = addr;
}
return 0;
@@ -662,7 +663,7 @@
return -ENOMEM;
memset(nic_info_addr, 0, nic_size);
- nic_info = (struct qlcnic_info *) nic_info_addr;
+ nic_info = nic_info_addr;
err = qlcnic_issue_cmd(adapter,
adapter->ahw->pci_func,
adapter->fw_hal_version,
@@ -720,7 +721,7 @@
return -ENOMEM;
memset(nic_info_addr, 0, nic_size);
- nic_info = (struct qlcnic_info *)nic_info_addr;
+ nic_info = nic_info_addr;
nic_info->pci_func = cpu_to_le16(nic->pci_func);
nic_info->op_mode = cpu_to_le16(nic->op_mode);
@@ -769,7 +770,7 @@
return -ENOMEM;
memset(pci_info_addr, 0, pci_size);
- npar = (struct qlcnic_pci_info *) pci_info_addr;
+ npar = pci_info_addr;
err = qlcnic_issue_cmd(adapter,
adapter->ahw->pci_func,
adapter->fw_hal_version,
@@ -877,7 +878,7 @@
QLCNIC_CDRP_CMD_GET_ESWITCH_STATS);
if (!err) {
- stats = (struct __qlcnic_esw_statistics *)stats_addr;
+ stats = stats_addr;
esw_stats->context_id = le16_to_cpu(stats->context_id);
esw_stats->version = le16_to_cpu(stats->version);
esw_stats->size = le16_to_cpu(stats->size);
diff --git a/drivers/net/qlcnic/qlcnic_ethtool.c b/drivers/net/qlcnic/qlcnic_ethtool.c
index 9efc690..3ea04e7 100644
--- a/drivers/net/qlcnic/qlcnic_ethtool.c
+++ b/drivers/net/qlcnic/qlcnic_ethtool.c
@@ -84,7 +84,9 @@
static const char qlcnic_gstrings_test[][ETH_GSTRING_LEN] = {
"Register_Test_on_offline",
"Link_Test_on_offline",
- "Interrupt_Test_offline"
+ "Interrupt_Test_offline",
+ "Internal_Loopback_offline",
+ "External_Loopback_offline"
};
#define QLCNIC_TEST_LEN ARRAY_SIZE(qlcnic_gstrings_test)
@@ -685,6 +687,124 @@
return ret;
}
+#define QLCNIC_ILB_PKT_SIZE 64
+#define QLCNIC_NUM_ILB_PKT 16
+#define QLCNIC_ILB_MAX_RCV_LOOP 10
+
+static void qlcnic_create_loopback_buff(unsigned char *data, u8 mac[])
+{
+ unsigned char random_data[] = {0xa8, 0x06, 0x45, 0x00};
+
+ memset(data, 0x4e, QLCNIC_ILB_PKT_SIZE);
+
+ memcpy(data, mac, ETH_ALEN);
+ memcpy(data + ETH_ALEN, mac, ETH_ALEN);
+
+ memcpy(data + 2 * ETH_ALEN, random_data, sizeof(random_data));
+}
+
+int qlcnic_check_loopback_buff(unsigned char *data, u8 mac[])
+{
+ unsigned char buff[QLCNIC_ILB_PKT_SIZE];
+ qlcnic_create_loopback_buff(buff, mac);
+ return memcmp(data, buff, QLCNIC_ILB_PKT_SIZE);
+}
+
+static int qlcnic_do_lb_test(struct qlcnic_adapter *adapter)
+{
+ struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
+ struct qlcnic_host_sds_ring *sds_ring = &recv_ctx->sds_rings[0];
+ struct sk_buff *skb;
+ int i, loop, cnt = 0;
+
+ for (i = 0; i < QLCNIC_NUM_ILB_PKT; i++) {
+ skb = dev_alloc_skb(QLCNIC_ILB_PKT_SIZE);
+ qlcnic_create_loopback_buff(skb->data, adapter->mac_addr);
+ skb_put(skb, QLCNIC_ILB_PKT_SIZE);
+
+ adapter->diag_cnt = 0;
+ qlcnic_xmit_frame(skb, adapter->netdev);
+
+ loop = 0;
+ do {
+ msleep(1);
+ qlcnic_process_rcv_ring_diag(sds_ring);
+ if (loop++ > QLCNIC_ILB_MAX_RCV_LOOP)
+ break;
+ } while (!adapter->diag_cnt);
+
+ dev_kfree_skb_any(skb);
+
+ if (!adapter->diag_cnt)
+ dev_warn(&adapter->pdev->dev, "LB Test: %dth packet"
+ " not recevied\n", i + 1);
+ else
+ cnt++;
+ }
+ if (cnt != i) {
+ dev_warn(&adapter->pdev->dev, "LB Test failed\n");
+ return -1;
+ }
+ return 0;
+}
+
+static int qlcnic_loopback_test(struct net_device *netdev, u8 mode)
+{
+ struct qlcnic_adapter *adapter = netdev_priv(netdev);
+ int max_sds_rings = adapter->max_sds_rings;
+ struct qlcnic_host_sds_ring *sds_ring;
+ int loop = 0;
+ int ret;
+
+ netdev_info(netdev, "%s loopback test in progress\n",
+ mode == QLCNIC_ILB_MODE ? "internal" : "external");
+ if (adapter->op_mode == QLCNIC_NON_PRIV_FUNC) {
+ netdev_warn(netdev, "Loopback test not supported for non "
+ "privilege function\n");
+ return 0;
+ }
+
+ if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state))
+ return -EIO;
+
+
+ ret = qlcnic_diag_alloc_res(netdev, QLCNIC_LOOPBACK_TEST);
+ if (ret)
+ goto clear_it;
+
+ sds_ring = &adapter->recv_ctx->sds_rings[0];
+
+ ret = qlcnic_set_lb_mode(adapter, mode);
+ if (ret)
+ goto free_res;
+
+ do {
+ msleep(500);
+ qlcnic_process_rcv_ring_diag(sds_ring);
+ if (loop++ > QLCNIC_ILB_MAX_RCV_LOOP)
+ break;
+ } while (!QLCNIC_IS_LB_CONFIGURED(adapter->ahw->loopback_state));
+
+ if (!QLCNIC_IS_LB_CONFIGURED(adapter->ahw->loopback_state)) {
+ netdev_info(netdev, "firmware didnt respond to loopback "
+ "configure request\n");
+ ret = adapter->ahw->loopback_state;
+ goto free_res;
+ }
+
+ ret = qlcnic_do_lb_test(adapter);
+
+ qlcnic_clear_lb_mode(adapter);
+
+ free_res:
+ qlcnic_diag_free_res(netdev, max_sds_rings);
+
+ clear_it:
+ adapter->max_sds_rings = max_sds_rings;
+ clear_bit(__QLCNIC_RESETTING, &adapter->state);
+ return ret;
+}
+
static void
qlcnic_diag_test(struct net_device *dev, struct ethtool_test *eth_test,
u64 *data)
@@ -704,7 +824,16 @@
if (data[2])
eth_test->flags |= ETH_TEST_FL_FAILED;
+ data[3] = qlcnic_loopback_test(dev, QLCNIC_ILB_MODE);
+ if (data[3])
+ eth_test->flags |= ETH_TEST_FL_FAILED;
+ if (eth_test->flags & ETH_TEST_FL_EXTERNAL_LB) {
+ data[4] = qlcnic_loopback_test(dev, QLCNIC_ELB_MODE);
+ if (data[4])
+ eth_test->flags |= ETH_TEST_FL_FAILED;
+ eth_test->flags |= ETH_TEST_FL_EXTERNAL_LB_DONE;
+ }
}
}
@@ -986,8 +1115,6 @@
struct qlcnic_adapter *adapter = netdev_priv(netdev);
struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump;
- if (qlcnic_api_lock(adapter))
- return -EIO;
if (!fw_dump->clr) {
netdev_info(netdev, "Dump not available\n");
qlcnic_api_unlock(adapter);
@@ -996,7 +1123,7 @@
/* Copy template header first */
copy_sz = fw_dump->tmpl_hdr->size;
hdr_ptr = (u32 *) fw_dump->tmpl_hdr;
- data = (u32 *) buffer;
+ data = buffer;
for (i = 0; i < copy_sz/sizeof(u32); i++)
*data++ = cpu_to_le32(*hdr_ptr++);
@@ -1009,7 +1136,6 @@
vfree(fw_dump->data);
fw_dump->data = NULL;
fw_dump->clr = 0;
- qlcnic_api_unlock(adapter);
return 0;
}
@@ -1022,8 +1148,27 @@
struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump;
if (val->flag == QLCNIC_FORCE_FW_DUMP_KEY) {
+ if (!fw_dump->enable) {
+ netdev_info(netdev, "FW dump not enabled\n");
+ return ret;
+ }
+ if (fw_dump->clr) {
+ dev_info(&adapter->pdev->dev,
+ "Previous dump not cleared, not forcing dump\n");
+ return ret;
+ }
netdev_info(netdev, "Forcing a FW dump\n");
qlcnic_dev_request_reset(adapter);
+ } else if (val->flag == QLCNIC_DISABLE_FW_DUMP) {
+ if (fw_dump->enable) {
+ netdev_info(netdev, "Disabling FW dump\n");
+ fw_dump->enable = 0;
+ }
+ } else if (val->flag == QLCNIC_ENABLE_FW_DUMP) {
+ if (!fw_dump->enable && fw_dump->tmpl_hdr) {
+ netdev_info(netdev, "Enabling FW dump\n");
+ fw_dump->enable = 1;
+ }
} else {
if (val->flag > QLCNIC_DUMP_MASK_MAX ||
val->flag < QLCNIC_DUMP_MASK_MIN) {
@@ -1032,10 +1177,7 @@
ret = -EINVAL;
goto out;
}
- if (qlcnic_api_lock(adapter))
- return -EIO;
fw_dump->tmpl_hdr->drv_cap_mask = val->flag & 0xff;
- qlcnic_api_unlock(adapter);
netdev_info(netdev, "Driver mask changed to: 0x%x\n",
fw_dump->tmpl_hdr->drv_cap_mask);
}
diff --git a/drivers/net/qlcnic/qlcnic_hw.c b/drivers/net/qlcnic/qlcnic_hw.c
index a5d9fbf..0391a04 100644
--- a/drivers/net/qlcnic/qlcnic_hw.c
+++ b/drivers/net/qlcnic/qlcnic_hw.c
@@ -533,6 +533,56 @@
}
}
+int qlcnic_set_fw_loopback(struct qlcnic_adapter *adapter, u8 flag)
+{
+ struct qlcnic_nic_req req;
+ int rv;
+
+ memset(&req, 0, sizeof(struct qlcnic_nic_req));
+
+ req.qhdr = cpu_to_le64(QLCNIC_HOST_REQUEST << 23);
+ req.req_hdr = cpu_to_le64(QLCNIC_H2C_OPCODE_CONFIG_LOOPBACK |
+ ((u64) adapter->portnum << 16) | ((u64) 0x1 << 32));
+
+ req.words[0] = cpu_to_le64(flag);
+
+ rv = qlcnic_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1);
+ if (rv != 0)
+ dev_err(&adapter->pdev->dev, "%sting loopback mode failed\n",
+ flag ? "Set" : "Reset");
+ return rv;
+}
+
+int qlcnic_set_lb_mode(struct qlcnic_adapter *adapter, u8 mode)
+{
+ if (qlcnic_set_fw_loopback(adapter, mode))
+ return -EIO;
+
+ if (qlcnic_nic_set_promisc(adapter, VPORT_MISS_MODE_ACCEPT_ALL)) {
+ qlcnic_set_fw_loopback(adapter, mode);
+ return -EIO;
+ }
+
+ msleep(1000);
+ return 0;
+}
+
+void qlcnic_clear_lb_mode(struct qlcnic_adapter *adapter)
+{
+ int mode = VPORT_MISS_MODE_DROP;
+ struct net_device *netdev = adapter->netdev;
+
+ qlcnic_set_fw_loopback(adapter, 0);
+
+ if (netdev->flags & IFF_PROMISC)
+ mode = VPORT_MISS_MODE_ACCEPT_ALL;
+ else if (netdev->flags & IFF_ALLMULTI)
+ mode = VPORT_MISS_MODE_ACCEPT_MULTI;
+
+ qlcnic_nic_set_promisc(adapter, mode);
+ msleep(1000);
+}
+
/*
* Send the interrupt coalescing parameter set by ethtool to the card.
*/
@@ -1509,18 +1559,26 @@
for (i = 0; i < l2->no_ops; i++) {
QLCNIC_WR_DUMP_REG(l2->addr, base, val);
- do {
+ if (LSW(l2->ctrl_val))
QLCNIC_WR_DUMP_REG(l2->ctrl_addr, base,
LSW(l2->ctrl_val));
+ if (!poll_mask)
+ goto skip_poll;
+ do {
QLCNIC_RD_DUMP_REG(l2->ctrl_addr, base, &data);
if (!(data & poll_mask))
break;
msleep(1);
time_out++;
} while (time_out <= poll_to);
- if (time_out > poll_to)
- return -EINVAL;
+ if (time_out > poll_to) {
+ dev_err(&adapter->pdev->dev,
+ "Timeout exceeded in %s, aborting dump\n",
+ __func__);
+ return -EINVAL;
+ }
+skip_poll:
addr = l2->read_addr;
cnt = l2->read_addr_num;
while (cnt) {
@@ -1673,8 +1731,7 @@
tmpl_hdr->sys_info[1] = adapter->fw_version;
for (i = 0; i < no_entries; i++) {
- entry = (struct qlcnic_dump_entry *) ((void *) tmpl_hdr +
- entry_offset);
+ entry = (void *)tmpl_hdr + entry_offset;
if (!(entry->hdr.mask & tmpl_hdr->drv_cap_mask)) {
entry->hdr.flags |= QLCNIC_DUMP_SKIP;
entry_offset += entry->hdr.offset;
diff --git a/drivers/net/qlcnic/qlcnic_init.c b/drivers/net/qlcnic/qlcnic_init.c
index 5b8bbcf..6ec1baa 100644
--- a/drivers/net/qlcnic/qlcnic_init.c
+++ b/drivers/net/qlcnic/qlcnic_init.c
@@ -1281,6 +1281,7 @@
u16 cable_len;
u16 link_speed;
u8 link_status, module, duplex, autoneg;
+ u8 lb_status = 0;
struct net_device *netdev = adapter->netdev;
adapter->has_link_events = 1;
@@ -1292,6 +1293,7 @@
link_status = msg->body[2] & 0xff;
duplex = (msg->body[2] >> 16) & 0xff;
autoneg = (msg->body[2] >> 24) & 0xff;
+ lb_status = (msg->body[2] >> 32) & 0x3;
module = (msg->body[2] >> 8) & 0xff;
if (module == LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLE)
@@ -1301,6 +1303,10 @@
dev_info(&netdev->dev, "unsupported cable length %d\n",
cable_len);
+ if (!link_status && (lb_status == QLCNIC_ILB_MODE ||
+ lb_status == QLCNIC_ELB_MODE))
+ adapter->ahw->loopback_state |= QLCNIC_LINKEVENT;
+
qlcnic_advert_link_change(adapter, link_status);
if (duplex == LINKEVENT_FULL_DUPLEX)
@@ -1319,7 +1325,9 @@
{
struct qlcnic_fw_msg msg;
struct status_desc *desc;
- int i = 0, opcode;
+ struct qlcnic_adapter *adapter;
+ struct device *dev;
+ int i = 0, opcode, ret;
while (desc_cnt > 0 && i < 8) {
desc = &sds_ring->desc_head[index];
@@ -1330,10 +1338,28 @@
desc_cnt--;
}
+ adapter = sds_ring->adapter;
+ dev = &adapter->pdev->dev;
opcode = qlcnic_get_nic_msg_opcode(msg.body[0]);
+
switch (opcode) {
case QLCNIC_C2H_OPCODE_GET_LINKEVENT_RESPONSE:
- qlcnic_handle_linkevent(sds_ring->adapter, &msg);
+ qlcnic_handle_linkevent(adapter, &msg);
+ break;
+ case QLCNIC_C2H_OPCODE_CONFIG_LOOPBACK:
+ ret = (u32)(msg.body[1]);
+ switch (ret) {
+ case 0:
+ adapter->ahw->loopback_state |= QLCNIC_LB_RESPONSE;
+ break;
+ case 1:
+ dev_info(dev, "loopback already in progress\n");
+ break;
+ default:
+ dev_info(dev, "loopback configure request failed,"
+ " ret %x\n", ret);
+ break;
+ }
break;
default:
break;
@@ -1746,6 +1772,103 @@
spin_unlock(&rds_ring->lock);
}
+static void dump_skb(struct sk_buff *skb)
+{
+ int i;
+ unsigned char *data = skb->data;
+
+ printk(KERN_INFO "\n");
+ for (i = 0; i < skb->len; i++) {
+ printk(KERN_INFO "%02x ", data[i]);
+ if ((i & 0x0f) == 8)
+ printk(KERN_INFO "\n");
+ }
+}
+
+void qlcnic_process_rcv_diag(struct qlcnic_adapter *adapter,
+ struct qlcnic_host_sds_ring *sds_ring,
+ int ring, u64 sts_data0)
+{
+ struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
+ struct sk_buff *skb;
+ struct qlcnic_host_rds_ring *rds_ring;
+ int index, length, cksum, pkt_offset;
+
+ if (unlikely(ring >= adapter->max_rds_rings))
+ return;
+
+ rds_ring = &recv_ctx->rds_rings[ring];
+
+ index = qlcnic_get_sts_refhandle(sts_data0);
+ length = qlcnic_get_sts_totallength(sts_data0);
+ if (unlikely(index >= rds_ring->num_desc))
+ return;
+
+ cksum = qlcnic_get_sts_status(sts_data0);
+ pkt_offset = qlcnic_get_sts_pkt_offset(sts_data0);
+
+ skb = qlcnic_process_rxbuf(adapter, rds_ring, index, cksum);
+ if (!skb)
+ return;
+
+ if (length > rds_ring->skb_size)
+ skb_put(skb, rds_ring->skb_size);
+ else
+ skb_put(skb, length);
+
+ if (pkt_offset)
+ skb_pull(skb, pkt_offset);
+
+ if (!qlcnic_check_loopback_buff(skb->data, adapter->mac_addr))
+ adapter->diag_cnt++;
+ else
+ dump_skb(skb);
+
+ dev_kfree_skb_any(skb);
+ adapter->stats.rx_pkts++;
+ adapter->stats.rxbytes += length;
+
+ return;
+}
+
+void
+qlcnic_process_rcv_ring_diag(struct qlcnic_host_sds_ring *sds_ring)
+{
+ struct qlcnic_adapter *adapter = sds_ring->adapter;
+ struct status_desc *desc;
+ u64 sts_data0;
+ int ring, opcode, desc_cnt;
+
+ u32 consumer = sds_ring->consumer;
+
+ desc = &sds_ring->desc_head[consumer];
+ sts_data0 = le64_to_cpu(desc->status_desc_data[0]);
+
+ if (!(sts_data0 & STATUS_OWNER_HOST))
+ return;
+
+ desc_cnt = qlcnic_get_sts_desc_cnt(sts_data0);
+ opcode = qlcnic_get_sts_opcode(sts_data0);
+ switch (opcode) {
+ case QLCNIC_RESPONSE_DESC:
+ qlcnic_handle_fw_message(desc_cnt, consumer, sds_ring);
+ break;
+ default:
+ ring = qlcnic_get_sts_type(sts_data0);
+ qlcnic_process_rcv_diag(adapter, sds_ring, ring, sts_data0);
+ break;
+ }
+
+ for (; desc_cnt > 0; desc_cnt--) {
+ desc = &sds_ring->desc_head[consumer];
+ desc->status_desc_data[0] = cpu_to_le64(STATUS_OWNER_PHANTOM);
+ consumer = get_next_index(consumer, sds_ring->num_desc);
+ }
+
+ sds_ring->consumer = consumer;
+ writel(consumer, sds_ring->crb_sts_consumer);
+}
+
void
qlcnic_fetch_mac(struct qlcnic_adapter *adapter, u32 off1, u32 off2,
u8 alt_mac, u8 *mac)
diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c
index 0f6af5c..357436b 100644
--- a/drivers/net/qlcnic/qlcnic_main.c
+++ b/drivers/net/qlcnic/qlcnic_main.c
@@ -418,10 +418,8 @@
int num_msix;
if (adapter->msix_supported) {
- num_msix = (num_online_cpus() >=
- QLCNIC_DEF_NUM_STS_DESC_RINGS) ?
- QLCNIC_DEF_NUM_STS_DESC_RINGS :
- QLCNIC_MIN_NUM_RSS_RINGS;
+ num_msix = rounddown_pow_of_two(min_t(int, num_online_cpus(),
+ QLCNIC_DEF_NUM_STS_DESC_RINGS));
} else
num_msix = 1;
@@ -1393,6 +1391,12 @@
qlcnic_enable_int(sds_ring);
}
}
+
+ if (adapter->diag_test == QLCNIC_LOOPBACK_TEST) {
+ adapter->ahw->loopback_state = 0;
+ qlcnic_linkevent_request(adapter, 1);
+ }
+
set_bit(__QLCNIC_DEV_UP, &adapter->state);
return 0;
@@ -1487,8 +1491,6 @@
netdev->irq = adapter->msix_entries[0].vector;
- netif_carrier_off(netdev);
-
err = register_netdev(netdev);
if (err) {
dev_err(&pdev->dev, "failed to register net device\n");
@@ -1590,10 +1592,6 @@
/* This will be reset for mezz cards */
adapter->portnum = adapter->ahw->pci_func;
- /* Get FW dump template and store it */
- if (adapter->op_mode != QLCNIC_NON_PRIV_FUNC)
- qlcnic_fw_cmd_get_minidump_temp(adapter);
-
err = qlcnic_get_board_info(adapter);
if (err) {
dev_err(&pdev->dev, "Error getting board config info.\n");
@@ -1612,6 +1610,12 @@
goto err_out_decr_ref;
}
+ /* Get FW dump template and store it */
+ if (adapter->op_mode != QLCNIC_NON_PRIV_FUNC)
+ if (!qlcnic_fw_cmd_get_minidump_temp(adapter))
+ dev_info(&pdev->dev,
+ "Supports FW dump capability\n");
+
if (qlcnic_read_mac_addr(adapter))
dev_warn(&pdev->dev, "failed to read mac addr\n");
@@ -1816,6 +1820,8 @@
struct qlcnic_adapter *adapter = netdev_priv(netdev);
int err;
+ netif_carrier_off(netdev);
+
err = qlcnic_attach(adapter);
if (err)
return err;
@@ -1861,7 +1867,7 @@
return;
adapter->fhash.fmax = QLCNIC_LB_MAX_FILTERS;
- adapter->fhash.fhead = (struct hlist_head *)head;
+ adapter->fhash.fhead = head;
for (i = 0; i < adapter->fhash.fmax; i++)
INIT_HLIST_HEAD(&adapter->fhash.fhead[i]);
@@ -2683,11 +2689,16 @@
static int
qlcnic_check_drv_state(struct qlcnic_adapter *adapter)
{
- int act, state;
+ int act, state, active_mask;
state = QLCRD32(adapter, QLCNIC_CRB_DRV_STATE);
act = QLCRD32(adapter, QLCNIC_CRB_DRV_ACTIVE);
+ if (adapter->flags & QLCNIC_FW_RESET_OWNER) {
+ active_mask = (~(1 << (adapter->ahw->pci_func * 4)));
+ act = act & active_mask;
+ }
+
if (((state & 0x11111111) == (act & 0x11111111)) ||
((act & 0x11111111) == ((state >> 1) & 0x11111111)))
return 0;
@@ -2826,6 +2837,11 @@
if (!qlcnic_check_drv_state(adapter)) {
skip_ack_check:
+ if (!(adapter->flags & QLCNIC_FW_RESET_OWNER)) {
+ qlcnic_api_unlock(adapter);
+ goto wait_npar;
+ }
+
dev_state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE);
if (dev_state == QLCNIC_DEV_NEED_RESET) {
@@ -2834,12 +2850,17 @@
set_bit(__QLCNIC_START_FW, &adapter->state);
QLCDB(adapter, DRV, "Restarting fw\n");
qlcnic_idc_debug_info(adapter, 0);
- QLCDB(adapter, DRV, "Take FW dump\n");
- qlcnic_dump_fw(adapter);
}
qlcnic_api_unlock(adapter);
+ rtnl_lock();
+ if (adapter->ahw->fw_dump.enable) {
+ QLCDB(adapter, DRV, "Take FW dump\n");
+ qlcnic_dump_fw(adapter);
+ adapter->flags &= ~QLCNIC_FW_RESET_OWNER;
+ }
+ rtnl_unlock();
if (!adapter->nic_ops->start_firmware(adapter)) {
qlcnic_schedule_work(adapter, qlcnic_attach_work, 0);
adapter->fw_wait_cnt = 0;
@@ -2900,9 +2921,11 @@
if (adapter->temp == QLCNIC_TEMP_PANIC)
goto err_ret;
-
- if (qlcnic_set_drv_state(adapter, adapter->dev_state))
- goto err_ret;
+ /* Dont ack if this instance is the reset owner */
+ if (!(adapter->flags & QLCNIC_FW_RESET_OWNER)) {
+ if (qlcnic_set_drv_state(adapter, adapter->dev_state))
+ goto err_ret;
+ }
adapter->fw_wait_cnt = 0;
@@ -2947,6 +2970,7 @@
if (state == QLCNIC_DEV_READY) {
QLCWR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_NEED_RESET);
+ adapter->flags |= QLCNIC_FW_RESET_OWNER;
QLCDB(adapter, DRV, "NEED_RESET state set\n");
qlcnic_idc_debug_info(adapter, 0);
}
diff --git a/drivers/net/qlge/qlge.h b/drivers/net/qlge/qlge.h
index ca306fd..794252c 100644
--- a/drivers/net/qlge/qlge.h
+++ b/drivers/net/qlge/qlge.h
@@ -7,6 +7,7 @@
#ifndef _QLGE_H_
#define _QLGE_H_
+#include <linux/interrupt.h>
#include <linux/pci.h>
#include <linux/netdevice.h>
#include <linux/rtnetlink.h>
diff --git a/drivers/net/qlge/qlge_ethtool.c b/drivers/net/qlge/qlge_ethtool.c
index 19b00fa..9b67bfe 100644
--- a/drivers/net/qlge/qlge_ethtool.c
+++ b/drivers/net/qlge/qlge_ethtool.c
@@ -650,8 +650,6 @@
return -EINVAL;
status = ql_mb_set_port_cfg(qdev);
- if (status)
- return status;
return status;
}
diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c
index 6b4ff97..68fbfac 100644
--- a/drivers/net/qlge/qlge_main.c
+++ b/drivers/net/qlge/qlge_main.c
@@ -3096,7 +3096,7 @@
if (rx_ring->lbq_len) {
cqicb->flags |= FLAGS_LL; /* Load lbq values */
tmp = (u64)rx_ring->lbq_base_dma;
- base_indirect_ptr = (__le64 *) rx_ring->lbq_base_indirect;
+ base_indirect_ptr = rx_ring->lbq_base_indirect;
page_entries = 0;
do {
*base_indirect_ptr = cpu_to_le64(tmp);
@@ -3120,7 +3120,7 @@
if (rx_ring->sbq_len) {
cqicb->flags |= FLAGS_LS; /* Load sbq values */
tmp = (u64)rx_ring->sbq_base_dma;
- base_indirect_ptr = (__le64 *) rx_ring->sbq_base_indirect;
+ base_indirect_ptr = rx_ring->sbq_base_indirect;
page_entries = 0;
do {
*base_indirect_ptr = cpu_to_le64(tmp);
diff --git a/drivers/net/r6040.c b/drivers/net/r6040.c
index 200a363..00f06e9 100644
--- a/drivers/net/r6040.c
+++ b/drivers/net/r6040.c
@@ -836,6 +836,9 @@
descptr->buf = cpu_to_le32(pci_map_single(lp->pdev,
skb->data, skb->len, PCI_DMA_TODEVICE));
descptr->status = DSC_OWNER_MAC;
+
+ skb_tx_timestamp(skb);
+
/* Trigger the MAC to check the TX descriptor */
iowrite16(0x01, ioaddr + MTPR);
lp->tx_insert_ptr = descptr->vndescp;
diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
index 5990621..ef1a43d 100644
--- a/drivers/net/r8169.c
+++ b/drivers/net/r8169.c
@@ -22,6 +22,7 @@
#include <linux/ip.h>
#include <linux/tcp.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/dma-mapping.h>
#include <linux/pm_runtime.h>
#include <linux/firmware.h>
@@ -658,7 +659,6 @@
unsigned int (*phy_reset_pending)(struct rtl8169_private *tp);
unsigned int (*link_ok)(void __iomem *);
int (*do_ioctl)(struct rtl8169_private *tp, struct mii_ioctl_data *data, int cmd);
- int pcie_cap;
struct delayed_work task;
unsigned features;
@@ -666,7 +666,18 @@
struct rtl8169_counters counters;
u32 saved_wolopts;
- const struct firmware *fw;
+ struct rtl_fw {
+ const struct firmware *fw;
+
+#define RTL_VER_SIZE 32
+
+ char version[RTL_VER_SIZE];
+
+ struct rtl_fw_phy_action {
+ __le32 *code;
+ size_t size;
+ } phy_action;
+ } *rtl_fw;
#define RTL_FIRMWARE_UNKNOWN ERR_PTR(-EAGAIN);
};
@@ -1221,12 +1232,14 @@
struct ethtool_drvinfo *info)
{
struct rtl8169_private *tp = netdev_priv(dev);
+ struct rtl_fw *rtl_fw = tp->rtl_fw;
strcpy(info->driver, MODULENAME);
strcpy(info->version, RTL8169_VERSION);
strcpy(info->bus_info, pci_name(tp->pci_dev));
- strncpy(info->fw_version, IS_ERR_OR_NULL(tp->fw) ? "N/A" :
- rtl_lookup_firmware_name(tp), sizeof(info->fw_version) - 1);
+ BUILD_BUG_ON(sizeof(info->fw_version) < sizeof(rtl_fw->version));
+ strcpy(info->fw_version, IS_ERR_OR_NULL(rtl_fw) ? "N/A" :
+ rtl_fw->version);
}
static int rtl8169_get_regs_len(struct net_device *dev)
@@ -1741,21 +1754,75 @@
#define PHY_DELAY_MS 0xe0000000
#define PHY_WRITE_ERI_WORD 0xf0000000
-static void
-rtl_phy_write_fw(struct rtl8169_private *tp, const struct firmware *fw)
+struct fw_info {
+ u32 magic;
+ char version[RTL_VER_SIZE];
+ __le32 fw_start;
+ __le32 fw_len;
+ u8 chksum;
+} __packed;
+
+#define FW_OPCODE_SIZE sizeof(typeof(*((struct rtl_fw_phy_action *)0)->code))
+
+static bool rtl_fw_format_ok(struct rtl8169_private *tp, struct rtl_fw *rtl_fw)
{
- __le32 *phytable = (__le32 *)fw->data;
- struct net_device *dev = tp->dev;
- size_t index, fw_size = fw->size / sizeof(*phytable);
- u32 predata, count;
+ const struct firmware *fw = rtl_fw->fw;
+ struct fw_info *fw_info = (struct fw_info *)fw->data;
+ struct rtl_fw_phy_action *pa = &rtl_fw->phy_action;
+ char *version = rtl_fw->version;
+ bool rc = false;
- if (fw->size % sizeof(*phytable)) {
- netif_err(tp, probe, dev, "odd sized firmware %zd\n", fw->size);
- return;
+ if (fw->size < FW_OPCODE_SIZE)
+ goto out;
+
+ if (!fw_info->magic) {
+ size_t i, size, start;
+ u8 checksum = 0;
+
+ if (fw->size < sizeof(*fw_info))
+ goto out;
+
+ for (i = 0; i < fw->size; i++)
+ checksum += fw->data[i];
+ if (checksum != 0)
+ goto out;
+
+ start = le32_to_cpu(fw_info->fw_start);
+ if (start > fw->size)
+ goto out;
+
+ size = le32_to_cpu(fw_info->fw_len);
+ if (size > (fw->size - start) / FW_OPCODE_SIZE)
+ goto out;
+
+ memcpy(version, fw_info->version, RTL_VER_SIZE);
+
+ pa->code = (__le32 *)(fw->data + start);
+ pa->size = size;
+ } else {
+ if (fw->size % FW_OPCODE_SIZE)
+ goto out;
+
+ strlcpy(version, rtl_lookup_firmware_name(tp), RTL_VER_SIZE);
+
+ pa->code = (__le32 *)fw->data;
+ pa->size = fw->size / FW_OPCODE_SIZE;
}
+ version[RTL_VER_SIZE - 1] = 0;
- for (index = 0; index < fw_size; index++) {
- u32 action = le32_to_cpu(phytable[index]);
+ rc = true;
+out:
+ return rc;
+}
+
+static bool rtl_fw_data_ok(struct rtl8169_private *tp, struct net_device *dev,
+ struct rtl_fw_phy_action *pa)
+{
+ bool rc = false;
+ size_t index;
+
+ for (index = 0; index < pa->size; index++) {
+ u32 action = le32_to_cpu(pa->code[index]);
u32 regno = (action & 0x0fff0000) >> 16;
switch(action & 0xf0000000) {
@@ -1771,25 +1838,25 @@
case PHY_BJMPN:
if (regno > index) {
- netif_err(tp, probe, tp->dev,
+ netif_err(tp, ifup, tp->dev,
"Out of range of firmware\n");
- return;
+ goto out;
}
break;
case PHY_READCOUNT_EQ_SKIP:
- if (index + 2 >= fw_size) {
- netif_err(tp, probe, tp->dev,
+ if (index + 2 >= pa->size) {
+ netif_err(tp, ifup, tp->dev,
"Out of range of firmware\n");
- return;
+ goto out;
}
break;
case PHY_COMP_EQ_SKIPN:
case PHY_COMP_NEQ_SKIPN:
case PHY_SKIPN:
- if (index + 1 + regno >= fw_size) {
- netif_err(tp, probe, tp->dev,
+ if (index + 1 + regno >= pa->size) {
+ netif_err(tp, ifup, tp->dev,
"Out of range of firmware\n");
- return;
+ goto out;
}
break;
@@ -1797,17 +1864,42 @@
case PHY_WRITE_MAC_BYTE:
case PHY_WRITE_ERI_WORD:
default:
- netif_err(tp, probe, tp->dev,
+ netif_err(tp, ifup, tp->dev,
"Invalid action 0x%08x\n", action);
- return;
+ goto out;
}
}
+ rc = true;
+out:
+ return rc;
+}
- predata = 0;
- count = 0;
+static int rtl_check_firmware(struct rtl8169_private *tp, struct rtl_fw *rtl_fw)
+{
+ struct net_device *dev = tp->dev;
+ int rc = -EINVAL;
- for (index = 0; index < fw_size; ) {
- u32 action = le32_to_cpu(phytable[index]);
+ if (!rtl_fw_format_ok(tp, rtl_fw)) {
+ netif_err(tp, ifup, dev, "invalid firwmare\n");
+ goto out;
+ }
+
+ if (rtl_fw_data_ok(tp, dev, &rtl_fw->phy_action))
+ rc = 0;
+out:
+ return rc;
+}
+
+static void rtl_phy_write_fw(struct rtl8169_private *tp, struct rtl_fw *rtl_fw)
+{
+ struct rtl_fw_phy_action *pa = &rtl_fw->phy_action;
+ u32 predata, count;
+ size_t index;
+
+ predata = count = 0;
+
+ for (index = 0; index < pa->size; ) {
+ u32 action = le32_to_cpu(pa->code[index]);
u32 data = action & 0x0000ffff;
u32 regno = (action & 0x0fff0000) >> 16;
@@ -1879,18 +1971,20 @@
static void rtl_release_firmware(struct rtl8169_private *tp)
{
- if (!IS_ERR_OR_NULL(tp->fw))
- release_firmware(tp->fw);
- tp->fw = RTL_FIRMWARE_UNKNOWN;
+ if (!IS_ERR_OR_NULL(tp->rtl_fw)) {
+ release_firmware(tp->rtl_fw->fw);
+ kfree(tp->rtl_fw);
+ }
+ tp->rtl_fw = RTL_FIRMWARE_UNKNOWN;
}
static void rtl_apply_firmware(struct rtl8169_private *tp)
{
- const struct firmware *fw = tp->fw;
+ struct rtl_fw *rtl_fw = tp->rtl_fw;
/* TODO: release firmware once rtl_phy_write_fw signals failures. */
- if (!IS_ERR_OR_NULL(fw))
- rtl_phy_write_fw(tp, fw);
+ if (!IS_ERR_OR_NULL(rtl_fw))
+ rtl_phy_write_fw(tp, rtl_fw);
}
static void rtl_apply_firmware_cond(struct rtl8169_private *tp, u8 reg, u16 val)
@@ -3349,9 +3443,8 @@
}
tp->mmio_addr = ioaddr;
- tp->pcie_cap = pci_find_capability(pdev, PCI_CAP_ID_EXP);
- if (!tp->pcie_cap)
- netif_info(tp, probe, dev, "no PCI Express capability\n");
+ if (!pci_is_pcie(pdev))
+ netif_info(tp, probe, dev, "not PCI Express\n");
RTL_W16(IntrMask, 0x0000);
@@ -3443,7 +3536,7 @@
tp->timer.data = (unsigned long) dev;
tp->timer.function = rtl8169_phy_timer;
- tp->fw = RTL_FIRMWARE_UNKNOWN;
+ tp->rtl_fw = RTL_FIRMWARE_UNKNOWN;
rc = register_netdev(dev);
if (rc < 0)
@@ -3512,25 +3605,48 @@
pci_set_drvdata(pdev, NULL);
}
+static void rtl_request_uncached_firmware(struct rtl8169_private *tp)
+{
+ struct rtl_fw *rtl_fw;
+ const char *name;
+ int rc = -ENOMEM;
+
+ name = rtl_lookup_firmware_name(tp);
+ if (!name)
+ goto out_no_firmware;
+
+ rtl_fw = kzalloc(sizeof(*rtl_fw), GFP_KERNEL);
+ if (!rtl_fw)
+ goto err_warn;
+
+ rc = request_firmware(&rtl_fw->fw, name, &tp->pci_dev->dev);
+ if (rc < 0)
+ goto err_free;
+
+ rc = rtl_check_firmware(tp, rtl_fw);
+ if (rc < 0)
+ goto err_release_firmware;
+
+ tp->rtl_fw = rtl_fw;
+out:
+ return;
+
+err_release_firmware:
+ release_firmware(rtl_fw->fw);
+err_free:
+ kfree(rtl_fw);
+err_warn:
+ netif_warn(tp, ifup, tp->dev, "unable to load firmware patch %s (%d)\n",
+ name, rc);
+out_no_firmware:
+ tp->rtl_fw = NULL;
+ goto out;
+}
+
static void rtl_request_firmware(struct rtl8169_private *tp)
{
- /* Return early if the firmware is already loaded / cached. */
- if (IS_ERR(tp->fw)) {
- const char *name;
-
- name = rtl_lookup_firmware_name(tp);
- if (name) {
- int rc;
-
- rc = request_firmware(&tp->fw, name, &tp->pci_dev->dev);
- if (rc >= 0)
- return;
-
- netif_warn(tp, ifup, tp->dev, "unable to load "
- "firmware patch %s (%d)\n", name, rc);
- }
- tp->fw = NULL;
- }
+ if (IS_ERR(tp->rtl_fw))
+ rtl_request_uncached_firmware(tp);
}
static int rtl8169_open(struct net_device *dev)
@@ -3780,9 +3896,7 @@
static void rtl_tx_performance_tweak(struct pci_dev *pdev, u16 force)
{
- struct net_device *dev = pci_get_drvdata(pdev);
- struct rtl8169_private *tp = netdev_priv(dev);
- int cap = tp->pcie_cap;
+ int cap = pci_pcie_cap(pdev);
if (cap) {
u16 ctl;
@@ -3830,9 +3944,7 @@
static void rtl_disable_clock_request(struct pci_dev *pdev)
{
- struct net_device *dev = pci_get_drvdata(pdev);
- struct rtl8169_private *tp = netdev_priv(dev);
- int cap = tp->pcie_cap;
+ int cap = pci_pcie_cap(pdev);
if (cap) {
u16 ctl;
@@ -3845,9 +3957,7 @@
static void rtl_enable_clock_request(struct pci_dev *pdev)
{
- struct net_device *dev = pci_get_drvdata(pdev);
- struct rtl8169_private *tp = netdev_priv(dev);
- int cap = tp->pcie_cap;
+ int cap = pci_pcie_cap(pdev);
if (cap) {
u16 ctl;
@@ -4277,7 +4387,7 @@
if (tp->mac_version == RTL_GIGA_MAC_VER_13 ||
tp->mac_version == RTL_GIGA_MAC_VER_16) {
- int cap = tp->pcie_cap;
+ int cap = pci_pcie_cap(pdev);
if (cap) {
pci_write_config_word(pdev, cap + PCI_EXP_DEVCTL,
diff --git a/drivers/net/rionet.c b/drivers/net/rionet.c
index 5d3436d..86ac38c 100644
--- a/drivers/net/rionet.c
+++ b/drivers/net/rionet.c
@@ -190,7 +190,7 @@
return NETDEV_TX_BUSY;
}
- if (eth->h_dest[0] & 0x01) {
+ if (is_multicast_ether_addr(eth->h_dest)) {
for (i = 0; i < RIO_MAX_ROUTE_ENTRIES(rnet->mport->sys_size);
i++)
if (rionet_active[i])
diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c
index df0d2c8..043850b 100644
--- a/drivers/net/s2io.c
+++ b/drivers/net/s2io.c
@@ -841,7 +841,7 @@
tmp_p_addr = ring->rx_blocks[j].block_dma_addr;
tmp_p_addr_next = ring->rx_blocks[next].block_dma_addr;
- pre_rxd_blk = (struct RxD_block *)tmp_v_addr;
+ pre_rxd_blk = tmp_v_addr;
pre_rxd_blk->reserved_2_pNext_RxD_block =
(unsigned long)tmp_v_addr_next;
pre_rxd_blk->pNext_RxD_Blk_physical =
@@ -918,7 +918,7 @@
mac_control->stats_mem_sz = size;
tmp_v_addr = mac_control->stats_mem;
- mac_control->stats_info = (struct stat_block *)tmp_v_addr;
+ mac_control->stats_info = tmp_v_addr;
memset(tmp_v_addr, 0, size);
DBG_PRINT(INIT_DBG, "%s: Ring Mem PHY: 0x%llx\n",
dev_name(&nic->pdev->dev), (unsigned long long)tmp_p_addr);
@@ -2439,7 +2439,7 @@
spin_lock_irqsave(&fifo->tx_lock, flags);
for (j = 0; j < tx_cfg->fifo_len; j++) {
- txdp = (struct TxD *)fifo->list_info[j].list_virt_addr;
+ txdp = fifo->list_info[j].list_virt_addr;
skb = s2io_txdl_getskb(&mac_control->fifos[i], txdp, j);
if (skb) {
swstats->mem_freed += skb->truesize;
@@ -3075,8 +3075,7 @@
get_info = fifo_data->tx_curr_get_info;
memcpy(&put_info, &fifo_data->tx_curr_put_info, sizeof(put_info));
- txdlp = (struct TxD *)
- fifo_data->list_info[get_info.offset].list_virt_addr;
+ txdlp = fifo_data->list_info[get_info.offset].list_virt_addr;
while ((!(txdlp->Control_1 & TXD_LIST_OWN_XENA)) &&
(get_info.offset != put_info.offset) &&
(txdlp->Host_Control)) {
@@ -3129,8 +3128,7 @@
get_info.offset++;
if (get_info.offset == get_info.fifo_len + 1)
get_info.offset = 0;
- txdlp = (struct TxD *)
- fifo_data->list_info[get_info.offset].list_virt_addr;
+ txdlp = fifo_data->list_info[get_info.offset].list_virt_addr;
fifo_data->tx_curr_get_info.offset = get_info.offset;
}
@@ -4111,7 +4109,7 @@
struct tcphdr *th;
ip = ip_hdr(skb);
- if ((ip->frag_off & htons(IP_OFFSET|IP_MF)) == 0) {
+ if (!ip_is_fragment(ip)) {
th = (struct tcphdr *)(((unsigned char *)ip) +
ip->ihl*4);
@@ -4163,7 +4161,7 @@
put_off = (u16)fifo->tx_curr_put_info.offset;
get_off = (u16)fifo->tx_curr_get_info.offset;
- txdp = (struct TxD *)fifo->list_info[put_off].list_virt_addr;
+ txdp = fifo->list_info[put_off].list_virt_addr;
queue_len = fifo->tx_curr_put_info.fifo_len + 1;
/* Avoid "put" pointer going beyond "get" pointer */
@@ -7972,9 +7970,7 @@
/* Initializing the BAR1 address as the start of the FIFO pointer. */
for (j = 0; j < MAX_TX_FIFOS; j++) {
- mac_control->tx_FIFO_start[j] =
- (struct TxFIFO_element __iomem *)
- (sp->bar1 + (j * 0x00020000));
+ mac_control->tx_FIFO_start[j] = sp->bar1 + (j * 0x00020000);
}
/* Driver entry points */
diff --git a/drivers/net/sc92031.c b/drivers/net/sc92031.c
index fa74314..9da4733 100644
--- a/drivers/net/sc92031.c
+++ b/drivers/net/sc92031.c
@@ -22,6 +22,7 @@
* matching, so you need to enable IFF_PROMISC when using it.
*/
+#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/delay.h>
diff --git a/drivers/net/sfc/filter.c b/drivers/net/sfc/filter.c
index 95a980f..f2fc258 100644
--- a/drivers/net/sfc/filter.c
+++ b/drivers/net/sfc/filter.c
@@ -652,7 +652,7 @@
/* RFS must validate the IP header length before calling us */
EFX_BUG_ON_PARANOID(!pskb_may_pull(skb, nhoff + sizeof(*ip)));
ip = (const struct iphdr *)(skb->data + nhoff);
- if (ip->frag_off & htons(IP_MF | IP_OFFSET))
+ if (ip_is_fragment(ip))
return -EPROTONOSUPPORT;
EFX_BUG_ON_PARANOID(!pskb_may_pull(skb, nhoff + 4 * ip->ihl + 4));
ports = (const __be16 *)(skb->data + nhoff + 4 * ip->ihl);
diff --git a/drivers/net/sfc/net_driver.h b/drivers/net/sfc/net_driver.h
index e8d5f03..1affbf4 100644
--- a/drivers/net/sfc/net_driver.h
+++ b/drivers/net/sfc/net_driver.h
@@ -17,7 +17,6 @@
#define DEBUG
#endif
-#include <linux/version.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/ethtool.h>
diff --git a/drivers/net/sfc/nic.c b/drivers/net/sfc/nic.c
index f2a2b94..bafa23a 100644
--- a/drivers/net/sfc/nic.c
+++ b/drivers/net/sfc/nic.c
@@ -10,6 +10,7 @@
#include <linux/bitops.h>
#include <linux/delay.h>
+#include <linux/interrupt.h>
#include <linux/pci.h>
#include <linux/module.h>
#include <linux/seq_file.h>
diff --git a/drivers/net/sfc/siena.c b/drivers/net/sfc/siena.c
index fb4721f..a66818e 100644
--- a/drivers/net/sfc/siena.c
+++ b/drivers/net/sfc/siena.c
@@ -400,7 +400,7 @@
u64 generation_end;
mac_stats = &efx->mac_stats;
- dma_stats = (u64 *)efx->stats_buffer.addr;
+ dma_stats = efx->stats_buffer.addr;
generation_end = dma_stats[MC_CMD_MAC_GENERATION_END];
if (generation_end == STATS_GENERATION_INVALID)
diff --git a/drivers/net/sgiseeq.c b/drivers/net/sgiseeq.c
index 54415c7b..52fb7ed 100644
--- a/drivers/net/sgiseeq.c
+++ b/drivers/net/sgiseeq.c
@@ -6,6 +6,7 @@
#undef DEBUG
+#include <linux/dma-mapping.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
diff --git a/drivers/net/sh_eth.c b/drivers/net/sh_eth.c
index 8a72a97..3da168a 100644
--- a/drivers/net/sh_eth.c
+++ b/drivers/net/sh_eth.c
@@ -33,7 +33,6 @@
#include <linux/pm_runtime.h>
#include <linux/slab.h>
#include <linux/ethtool.h>
-#include <asm/cacheflush.h>
#include "sh_eth.h"
@@ -864,6 +863,8 @@
break;
/* Free the original skb. */
if (mdp->tx_skbuff[entry]) {
+ dma_unmap_single(&ndev->dev, txdesc->addr,
+ txdesc->buffer_length, DMA_TO_DEVICE);
dev_kfree_skb_irq(mdp->tx_skbuff[entry]);
mdp->tx_skbuff[entry] = NULL;
freeNum++;
@@ -1487,13 +1488,12 @@
entry = mdp->cur_tx % TX_RING_SIZE;
mdp->tx_skbuff[entry] = skb;
txdesc = &mdp->tx_ring[entry];
- txdesc->addr = virt_to_phys(skb->data);
/* soft swap. */
if (!mdp->cd->hw_swap)
sh_eth_soft_swap(phys_to_virt(ALIGN(txdesc->addr, 4)),
skb->len + 2);
- /* write back */
- __flush_purge_region(skb->data, skb->len);
+ txdesc->addr = dma_map_single(&ndev->dev, skb->data, skb->len,
+ DMA_TO_DEVICE);
if (skb->len < ETHERSMALL)
txdesc->buffer_length = ETHERSMALL;
else
@@ -1770,7 +1770,7 @@
int ret, devno = 0;
struct resource *res;
struct net_device *ndev = NULL;
- struct sh_eth_private *mdp;
+ struct sh_eth_private *mdp = NULL;
struct sh_eth_plat_data *pd;
/* get base addr */
@@ -1888,7 +1888,7 @@
out_release:
/* net_dev free */
- if (mdp->tsu_addr)
+ if (mdp && mdp->tsu_addr)
iounmap(mdp->tsu_addr);
if (ndev)
free_netdev(ndev);
diff --git a/drivers/net/sis190.c b/drivers/net/sis190.c
index b436e00..8ad7bfb 100644
--- a/drivers/net/sis190.c
+++ b/drivers/net/sis190.c
@@ -21,6 +21,7 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/netdevice.h>
diff --git a/drivers/net/sis900.c b/drivers/net/sis900.c
index 484f795..658a192 100644
--- a/drivers/net/sis900.c
+++ b/drivers/net/sis900.c
@@ -482,7 +482,7 @@
ret = -ENOMEM;
goto err_out_cleardev;
}
- sis_priv->tx_ring = (BufferDesc *)ring_space;
+ sis_priv->tx_ring = ring_space;
sis_priv->tx_ring_dma = ring_dma;
ring_space = pci_alloc_consistent(pci_dev, RX_TOTAL_SIZE, &ring_dma);
@@ -490,7 +490,7 @@
ret = -ENOMEM;
goto err_unmap_tx;
}
- sis_priv->rx_ring = (BufferDesc *)ring_space;
+ sis_priv->rx_ring = ring_space;
sis_priv->rx_ring_dma = ring_dma;
/* The SiS900-specific entries in the device structure. */
diff --git a/drivers/net/skge.h b/drivers/net/skge.h
index 598bf7a..a2eb341 100644
--- a/drivers/net/skge.h
+++ b/drivers/net/skge.h
@@ -3,6 +3,7 @@
*/
#ifndef _SKGE_H
#define _SKGE_H
+#include <linux/interrupt.h>
/* PCI config registers */
#define PCI_DEV_REG1 0x40
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c
index 3ee41da..e14b86e 100644
--- a/drivers/net/sky2.c
+++ b/drivers/net/sky2.c
@@ -32,6 +32,7 @@
#include <linux/etherdevice.h>
#include <linux/ethtool.h>
#include <linux/pci.h>
+#include <linux/interrupt.h>
#include <linux/ip.h>
#include <linux/slab.h>
#include <net/ip.h>
@@ -1448,7 +1449,7 @@
sky2_qset(hw, rxq);
/* On PCI express lowering the watermark gives better performance */
- if (pci_find_capability(hw->pdev, PCI_CAP_ID_EXP))
+ if (pci_is_pcie(hw->pdev))
sky2_write32(hw, Q_ADDR(rxq, Q_WM), BMU_WM_PEX);
/* These chips have no ram buffer?
@@ -3071,7 +3072,7 @@
{
struct pci_dev *pdev = hw->pdev;
u16 status;
- int i, cap;
+ int i;
u32 hwe_mask = Y2_HWE_ALL_MASK;
/* disable ASF */
@@ -3107,8 +3108,7 @@
sky2_write8(hw, B0_CTST, CS_MRST_CLR);
- cap = pci_find_capability(pdev, PCI_CAP_ID_EXP);
- if (cap) {
+ if (pci_is_pcie(pdev)) {
sky2_write32(hw, Y2_CFG_AER + PCI_ERR_UNCOR_STATUS,
0xfffffffful);
@@ -3170,11 +3170,11 @@
/* check if PSMv2 was running before */
reg = sky2_pci_read16(hw, PSM_CONFIG_REG3);
- if (reg & PCI_EXP_LNKCTL_ASPMC) {
- cap = pci_find_capability(pdev, PCI_CAP_ID_EXP);
+ if (reg & PCI_EXP_LNKCTL_ASPMC)
/* restore the PCIe Link Control register */
- sky2_pci_write16(hw, cap + PCI_EXP_LNKCTL, reg);
- }
+ sky2_pci_write16(hw, pdev->pcie_cap + PCI_EXP_LNKCTL,
+ reg);
+
sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
/* re-enable PEX PM in PEX PHY debug reg. 8 (clear bit 12) */
diff --git a/drivers/net/slhc.c b/drivers/net/slhc.c
index ab9e3b7..0a0a664 100644
--- a/drivers/net/slhc.c
+++ b/drivers/net/slhc.c
@@ -297,7 +297,7 @@
lcs = cs;
cs = cs->next;
comp->sls_o_searches++;
- };
+ }
/*
* Didn't find it -- re-use oldest cstate. Send an
* uncompressed packet that tells the other side what
diff --git a/drivers/net/smc-mca.c b/drivers/net/smc-mca.c
index d07c39c..34934fb 100644
--- a/drivers/net/smc-mca.c
+++ b/drivers/net/smc-mca.c
@@ -42,6 +42,7 @@
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
diff --git a/drivers/net/smc-ultra.c b/drivers/net/smc-ultra.c
index 235a3c6..ba44ede 100644
--- a/drivers/net/smc-ultra.c
+++ b/drivers/net/smc-ultra.c
@@ -62,6 +62,7 @@
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/isapnp.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
diff --git a/drivers/net/smsc911x.c b/drivers/net/smsc911x.c
index c6d47d1..b9016a3 100644
--- a/drivers/net/smsc911x.c
+++ b/drivers/net/smsc911x.c
@@ -37,6 +37,7 @@
#include <linux/etherdevice.h>
#include <linux/ethtool.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/kernel.h>
#include <linux/module.h>
@@ -1473,6 +1474,7 @@
pdata->ops->tx_writefifo(pdata, (unsigned int *)bufp, wrsz);
freespace -= (skb->len + 32);
+ skb_tx_timestamp(skb);
dev_kfree_skb(skb);
if (unlikely(smsc911x_tx_get_txstatcount(pdata) >= 30))
diff --git a/drivers/net/smsc9420.c b/drivers/net/smsc9420.c
index 4c92ad8..459726f 100644
--- a/drivers/net/smsc9420.c
+++ b/drivers/net/smsc9420.c
@@ -19,6 +19,7 @@
***************************************************************************
*/
+#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/netdevice.h>
#include <linux/phy.h>
@@ -1030,6 +1031,8 @@
pd->tx_ring[index].status = TDES0_OWN_;
wmb();
+ skb_tx_timestamp(skb);
+
/* kick the DMA */
smsc9420_reg_write(pd, TX_POLL_DEMAND, 1);
smsc9420_pci_flush_write(pd);
diff --git a/drivers/net/spider_net.c b/drivers/net/spider_net.c
index 949f124..9bc6c20 100644
--- a/drivers/net/spider_net.c
+++ b/drivers/net/spider_net.c
@@ -31,6 +31,7 @@
#include <linux/if_vlan.h>
#include <linux/in.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/gfp.h>
#include <linux/ioport.h>
#include <linux/ip.h>
diff --git a/drivers/net/starfire.c b/drivers/net/starfire.c
index 36045f3..860a508 100644
--- a/drivers/net/starfire.c
+++ b/drivers/net/starfire.c
@@ -30,6 +30,7 @@
#define DRV_VERSION "2.1"
#define DRV_RELDATE "July 6, 2008"
+#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/pci.h>
diff --git a/drivers/net/stmmac/dwmac1000_core.c b/drivers/net/stmmac/dwmac1000_core.c
index f20455c..0f63b3c 100644
--- a/drivers/net/stmmac/dwmac1000_core.c
+++ b/drivers/net/stmmac/dwmac1000_core.c
@@ -28,6 +28,7 @@
#include <linux/crc32.h>
#include <linux/slab.h>
+#include <asm/io.h>
#include "dwmac1000.h"
static void dwmac1000_core_init(void __iomem *ioaddr)
diff --git a/drivers/net/stmmac/dwmac1000_dma.c b/drivers/net/stmmac/dwmac1000_dma.c
index 2c47712..3dbeea6 100644
--- a/drivers/net/stmmac/dwmac1000_dma.c
+++ b/drivers/net/stmmac/dwmac1000_dma.c
@@ -26,6 +26,7 @@
Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
*******************************************************************************/
+#include <asm/io.h>
#include "dwmac1000.h"
#include "dwmac_dma.h"
diff --git a/drivers/net/stmmac/dwmac100_core.c b/drivers/net/stmmac/dwmac100_core.c
index c724fc3..743a580 100644
--- a/drivers/net/stmmac/dwmac100_core.c
+++ b/drivers/net/stmmac/dwmac100_core.c
@@ -29,6 +29,7 @@
*******************************************************************************/
#include <linux/crc32.h>
+#include <asm/io.h>
#include "dwmac100.h"
static void dwmac100_core_init(void __iomem *ioaddr)
diff --git a/drivers/net/stmmac/dwmac100_dma.c b/drivers/net/stmmac/dwmac100_dma.c
index e3e224b..627f656 100644
--- a/drivers/net/stmmac/dwmac100_dma.c
+++ b/drivers/net/stmmac/dwmac100_dma.c
@@ -28,6 +28,7 @@
Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
*******************************************************************************/
+#include <asm/io.h>
#include "dwmac100.h"
#include "dwmac_dma.h"
diff --git a/drivers/net/stmmac/stmmac_ethtool.c b/drivers/net/stmmac/stmmac_ethtool.c
index ae5213a..7ed8fb6 100644
--- a/drivers/net/stmmac/stmmac_ethtool.c
+++ b/drivers/net/stmmac/stmmac_ethtool.c
@@ -24,8 +24,10 @@
#include <linux/etherdevice.h>
#include <linux/ethtool.h>
+#include <linux/interrupt.h>
#include <linux/mii.h>
#include <linux/phy.h>
+#include <asm/io.h>
#include "stmmac.h"
#include "dwmac_dma.h"
diff --git a/drivers/net/stmmac/stmmac_main.c b/drivers/net/stmmac/stmmac_main.c
index e25e44a..d4adc80 100644
--- a/drivers/net/stmmac/stmmac_main.c
+++ b/drivers/net/stmmac/stmmac_main.c
@@ -1079,6 +1079,8 @@
dev->stats.tx_bytes += skb->len;
+ skb_tx_timestamp(skb);
+
priv->hw->dma->enable_dma_transmission(priv->ioaddr);
return NETDEV_TX_OK;
diff --git a/drivers/net/stmmac/stmmac_mdio.c b/drivers/net/stmmac/stmmac_mdio.c
index 234b406..29a6bb6 100644
--- a/drivers/net/stmmac/stmmac_mdio.c
+++ b/drivers/net/stmmac/stmmac_mdio.c
@@ -27,6 +27,7 @@
#include <linux/mii.h>
#include <linux/phy.h>
#include <linux/slab.h>
+#include <asm/io.h>
#include "stmmac.h"
diff --git a/drivers/net/sungem.c b/drivers/net/sungem.c
index ab59300..71d4a03 100644
--- a/drivers/net/sungem.c
+++ b/drivers/net/sungem.c
@@ -10,25 +10,6 @@
* NAPI and NETPOLL support
* (C) 2004 by Eric Lemoine (eric.lemoine@gmail.com)
*
- * TODO:
- * - Now that the driver was significantly simplified, I need to rework
- * the locking. I'm sure we don't need _2_ spinlocks, and we probably
- * can avoid taking most of them for so long period of time (and schedule
- * instead). The main issues at this point are caused by the netdev layer
- * though:
- *
- * gem_change_mtu() and gem_set_multicast() are called with a read_lock()
- * help by net/core/dev.c, thus they can't schedule. That means they can't
- * call napi_disable() neither, thus force gem_poll() to keep a spinlock
- * where it could have been dropped. change_mtu especially would love also to
- * be able to msleep instead of horrid locked delays when resetting the HW,
- * but that read_lock() makes it impossible, unless I defer it's action to
- * the reset task, which means it'll be asynchronous (won't take effect until
- * the system schedules a bit).
- *
- * Also, it would probably be possible to also remove most of the long-life
- * locking in open/resume code path (gem_reinit_chip) by beeing more careful
- * about when we can start taking interrupts or get xmit() called...
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
@@ -57,7 +38,6 @@
#include <linux/workqueue.h>
#include <linux/if_vlan.h>
#include <linux/bitops.h>
-#include <linux/mutex.h>
#include <linux/mm.h>
#include <linux/gfp.h>
@@ -95,12 +75,11 @@
SUPPORTED_Pause | SUPPORTED_Autoneg)
#define DRV_NAME "sungem"
-#define DRV_VERSION "0.98"
-#define DRV_RELDATE "8/24/03"
-#define DRV_AUTHOR "David S. Miller (davem@redhat.com)"
+#define DRV_VERSION "1.0"
+#define DRV_AUTHOR "David S. Miller <davem@redhat.com>"
static char version[] __devinitdata =
- DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " " DRV_AUTHOR "\n";
+ DRV_NAME ".c:v" DRV_VERSION " " DRV_AUTHOR "\n";
MODULE_AUTHOR(DRV_AUTHOR);
MODULE_DESCRIPTION("Sun GEM Gbit ethernet driver");
@@ -218,6 +197,7 @@
{
/* Disable all interrupts, including TXDONE */
writel(GREG_STAT_NAPI | GREG_STAT_TXDONE, gp->regs + GREG_IMASK);
+ (void)readl(gp->regs + GREG_IMASK); /* write posting */
}
static void gem_get_cell(struct gem *gp)
@@ -247,6 +227,29 @@
#endif /* CONFIG_PPC_PMAC */
}
+static inline void gem_netif_stop(struct gem *gp)
+{
+ gp->dev->trans_start = jiffies; /* prevent tx timeout */
+ napi_disable(&gp->napi);
+ netif_tx_disable(gp->dev);
+}
+
+static inline void gem_netif_start(struct gem *gp)
+{
+ /* NOTE: unconditional netif_wake_queue is only
+ * appropriate so long as all callers are assured to
+ * have free tx slots.
+ */
+ netif_wake_queue(gp->dev);
+ napi_enable(&gp->napi);
+}
+
+static void gem_schedule_reset(struct gem *gp)
+{
+ gp->reset_task_pending = 1;
+ schedule_work(&gp->reset_task);
+}
+
static void gem_handle_mif_event(struct gem *gp, u32 reg_val, u32 changed_bits)
{
if (netif_msg_intr(gp))
@@ -604,56 +607,46 @@
gp->dev->name);
dev->stats.rx_errors++;
- goto do_reset;
+ return 1;
}
if (gem_status & GREG_STAT_PCS) {
if (gem_pcs_interrupt(dev, gp, gem_status))
- goto do_reset;
+ return 1;
}
if (gem_status & GREG_STAT_TXMAC) {
if (gem_txmac_interrupt(dev, gp, gem_status))
- goto do_reset;
+ return 1;
}
if (gem_status & GREG_STAT_RXMAC) {
if (gem_rxmac_interrupt(dev, gp, gem_status))
- goto do_reset;
+ return 1;
}
if (gem_status & GREG_STAT_MAC) {
if (gem_mac_interrupt(dev, gp, gem_status))
- goto do_reset;
+ return 1;
}
if (gem_status & GREG_STAT_MIF) {
if (gem_mif_interrupt(dev, gp, gem_status))
- goto do_reset;
+ return 1;
}
if (gem_status & GREG_STAT_PCIERR) {
if (gem_pci_interrupt(dev, gp, gem_status))
- goto do_reset;
+ return 1;
}
return 0;
-
-do_reset:
- gp->reset_task_pending = 1;
- schedule_work(&gp->reset_task);
-
- return 1;
}
static __inline__ void gem_tx(struct net_device *dev, struct gem *gp, u32 gem_status)
{
int entry, limit;
- if (netif_msg_intr(gp))
- printk(KERN_DEBUG "%s: tx interrupt, gem_status: 0x%x\n",
- gp->dev->name, gem_status);
-
entry = gp->tx_old;
limit = ((gem_status & GREG_STAT_TXNR) >> GREG_STAT_TXNR_SHIFT);
while (entry != limit) {
@@ -697,13 +690,27 @@
}
dev->stats.tx_packets++;
- dev_kfree_skb_irq(skb);
+ dev_kfree_skb(skb);
}
gp->tx_old = entry;
- if (netif_queue_stopped(dev) &&
- TX_BUFFS_AVAIL(gp) > (MAX_SKB_FRAGS + 1))
- netif_wake_queue(dev);
+ /* Need to make the tx_old update visible to gem_start_xmit()
+ * before checking for netif_queue_stopped(). Without the
+ * memory barrier, there is a small possibility that gem_start_xmit()
+ * will miss it and cause the queue to be stopped forever.
+ */
+ smp_mb();
+
+ if (unlikely(netif_queue_stopped(dev) &&
+ TX_BUFFS_AVAIL(gp) > (MAX_SKB_FRAGS + 1))) {
+ struct netdev_queue *txq = netdev_get_tx_queue(dev, 0);
+
+ __netif_tx_lock(txq, smp_processor_id());
+ if (netif_queue_stopped(dev) &&
+ TX_BUFFS_AVAIL(gp) > (MAX_SKB_FRAGS + 1))
+ netif_wake_queue(dev);
+ __netif_tx_unlock(txq);
+ }
}
static __inline__ void gem_post_rxds(struct gem *gp, int limit)
@@ -736,6 +743,21 @@
}
}
+#define ALIGNED_RX_SKB_ADDR(addr) \
+ ((((unsigned long)(addr) + (64UL - 1UL)) & ~(64UL - 1UL)) - (unsigned long)(addr))
+static __inline__ struct sk_buff *gem_alloc_skb(struct net_device *dev, int size,
+ gfp_t gfp_flags)
+{
+ struct sk_buff *skb = alloc_skb(size + 64, gfp_flags);
+
+ if (likely(skb)) {
+ unsigned long offset = ALIGNED_RX_SKB_ADDR(skb->data);
+ skb_reserve(skb, offset);
+ skb->dev = dev;
+ }
+ return skb;
+}
+
static int gem_rx(struct gem *gp, int work_to_do)
{
struct net_device *dev = gp->dev;
@@ -799,7 +821,7 @@
if (len > RX_COPY_THRESHOLD) {
struct sk_buff *new_skb;
- new_skb = gem_alloc_skb(RX_BUF_ALLOC_SIZE(gp), GFP_ATOMIC);
+ new_skb = gem_alloc_skb(dev, RX_BUF_ALLOC_SIZE(gp), GFP_ATOMIC);
if (new_skb == NULL) {
drops++;
goto drop_it;
@@ -808,7 +830,6 @@
RX_BUF_ALLOC_SIZE(gp),
PCI_DMA_FROMDEVICE);
gp->rx_skbs[entry] = new_skb;
- new_skb->dev = gp->dev;
skb_put(new_skb, (gp->rx_buf_sz + RX_OFFSET));
rxd->buffer = cpu_to_le64(pci_map_page(gp->pdev,
virt_to_page(new_skb->data),
@@ -820,7 +841,7 @@
/* Trim the original skb for the netif. */
skb_trim(skb, len);
} else {
- struct sk_buff *copy_skb = dev_alloc_skb(len + 2);
+ struct sk_buff *copy_skb = netdev_alloc_skb(dev, len + 2);
if (copy_skb == NULL) {
drops++;
@@ -842,7 +863,7 @@
skb->ip_summed = CHECKSUM_COMPLETE;
skb->protocol = eth_type_trans(skb, gp->dev);
- netif_receive_skb(skb);
+ napi_gro_receive(&gp->napi, skb);
dev->stats.rx_packets++;
dev->stats.rx_bytes += len;
@@ -865,28 +886,32 @@
{
struct gem *gp = container_of(napi, struct gem, napi);
struct net_device *dev = gp->dev;
- unsigned long flags;
int work_done;
- /*
- * NAPI locking nightmare: See comment at head of driver
- */
- spin_lock_irqsave(&gp->lock, flags);
-
work_done = 0;
do {
/* Handle anomalies */
- if (gp->status & GREG_STAT_ABNORMAL) {
- if (gem_abnormal_irq(dev, gp, gp->status))
- break;
+ if (unlikely(gp->status & GREG_STAT_ABNORMAL)) {
+ struct netdev_queue *txq = netdev_get_tx_queue(dev, 0);
+ int reset;
+
+ /* We run the abnormal interrupt handling code with
+ * the Tx lock. It only resets the Rx portion of the
+ * chip, but we need to guard it against DMA being
+ * restarted by the link poll timer
+ */
+ __netif_tx_lock(txq, smp_processor_id());
+ reset = gem_abnormal_irq(dev, gp, gp->status);
+ __netif_tx_unlock(txq);
+ if (reset) {
+ gem_schedule_reset(gp);
+ napi_complete(napi);
+ return work_done;
+ }
}
/* Run TX completion thread */
- spin_lock(&gp->tx_lock);
gem_tx(dev, gp, gp->status);
- spin_unlock(&gp->tx_lock);
-
- spin_unlock_irqrestore(&gp->lock, flags);
/* Run RX thread. We don't use any locking here,
* code willing to do bad things - like cleaning the
@@ -898,16 +923,12 @@
if (work_done >= budget)
return work_done;
- spin_lock_irqsave(&gp->lock, flags);
-
gp->status = readl(gp->regs + GREG_STAT);
} while (gp->status & GREG_STAT_NAPI);
- __napi_complete(napi);
+ napi_complete(napi);
gem_enable_ints(gp);
- spin_unlock_irqrestore(&gp->lock, flags);
-
return work_done;
}
@@ -915,32 +936,23 @@
{
struct net_device *dev = dev_id;
struct gem *gp = netdev_priv(dev);
- unsigned long flags;
-
- /* Swallow interrupts when shutting the chip down, though
- * that shouldn't happen, we should have done free_irq() at
- * this point...
- */
- if (!gp->running)
- return IRQ_HANDLED;
-
- spin_lock_irqsave(&gp->lock, flags);
if (napi_schedule_prep(&gp->napi)) {
u32 gem_status = readl(gp->regs + GREG_STAT);
- if (gem_status == 0) {
+ if (unlikely(gem_status == 0)) {
napi_enable(&gp->napi);
- spin_unlock_irqrestore(&gp->lock, flags);
return IRQ_NONE;
}
+ if (netif_msg_intr(gp))
+ printk(KERN_DEBUG "%s: gem_interrupt() gem_status: 0x%x\n",
+ gp->dev->name, gem_status);
+
gp->status = gem_status;
gem_disable_ints(gp);
__napi_schedule(&gp->napi);
}
- spin_unlock_irqrestore(&gp->lock, flags);
-
/* If polling was disabled at the time we received that
* interrupt, we may return IRQ_HANDLED here while we
* should return IRQ_NONE. No big deal...
@@ -951,10 +963,11 @@
#ifdef CONFIG_NET_POLL_CONTROLLER
static void gem_poll_controller(struct net_device *dev)
{
- /* gem_interrupt is safe to reentrance so no need
- * to disable_irq here.
- */
- gem_interrupt(dev->irq, dev);
+ struct gem *gp = netdev_priv(dev);
+
+ disable_irq(gp->pdev->irq);
+ gem_interrupt(gp->pdev->irq, dev);
+ enable_irq(gp->pdev->irq);
}
#endif
@@ -963,10 +976,7 @@
struct gem *gp = netdev_priv(dev);
netdev_err(dev, "transmit timed out, resetting\n");
- if (!gp->running) {
- netdev_err(dev, "hrm.. hw not running !\n");
- return;
- }
+
netdev_err(dev, "TX_STATE[%08x:%08x:%08x]\n",
readl(gp->regs + TXDMA_CFG),
readl(gp->regs + MAC_TXSTAT),
@@ -976,14 +986,7 @@
readl(gp->regs + MAC_RXSTAT),
readl(gp->regs + MAC_RXCFG));
- spin_lock_irq(&gp->lock);
- spin_lock(&gp->tx_lock);
-
- gp->reset_task_pending = 1;
- schedule_work(&gp->reset_task);
-
- spin_unlock(&gp->tx_lock);
- spin_unlock_irq(&gp->lock);
+ gem_schedule_reset(gp);
}
static __inline__ int gem_intme(int entry)
@@ -1001,7 +1004,6 @@
struct gem *gp = netdev_priv(dev);
int entry;
u64 ctrl;
- unsigned long flags;
ctrl = 0;
if (skb->ip_summed == CHECKSUM_PARTIAL) {
@@ -1013,21 +1015,12 @@
(csum_stuff_off << 21));
}
- if (!spin_trylock_irqsave(&gp->tx_lock, flags)) {
- /* Tell upper layer to requeue */
- return NETDEV_TX_LOCKED;
- }
- /* We raced with gem_do_stop() */
- if (!gp->running) {
- spin_unlock_irqrestore(&gp->tx_lock, flags);
- return NETDEV_TX_BUSY;
- }
-
- /* This is a hard error, log it. */
- if (TX_BUFFS_AVAIL(gp) <= (skb_shinfo(skb)->nr_frags + 1)) {
- netif_stop_queue(dev);
- spin_unlock_irqrestore(&gp->tx_lock, flags);
- netdev_err(dev, "BUG! Tx Ring full when queue awake!\n");
+ if (unlikely(TX_BUFFS_AVAIL(gp) <= (skb_shinfo(skb)->nr_frags + 1))) {
+ /* This is a hard error, log it. */
+ if (!netif_queue_stopped(dev)) {
+ netif_stop_queue(dev);
+ netdev_err(dev, "BUG! Tx Ring full when queue awake!\n");
+ }
return NETDEV_TX_BUSY;
}
@@ -1104,17 +1097,23 @@
}
gp->tx_new = entry;
- if (TX_BUFFS_AVAIL(gp) <= (MAX_SKB_FRAGS + 1))
+ if (unlikely(TX_BUFFS_AVAIL(gp) <= (MAX_SKB_FRAGS + 1))) {
netif_stop_queue(dev);
+ /* netif_stop_queue() must be done before checking
+ * checking tx index in TX_BUFFS_AVAIL() below, because
+ * in gem_tx(), we update tx_old before checking for
+ * netif_queue_stopped().
+ */
+ smp_mb();
+ if (TX_BUFFS_AVAIL(gp) > (MAX_SKB_FRAGS + 1))
+ netif_wake_queue(dev);
+ }
if (netif_msg_tx_queued(gp))
printk(KERN_DEBUG "%s: tx queued, slot %d, skblen %d\n",
dev->name, entry, skb->len);
mb();
writel(gp->tx_new, gp->regs + TXDMA_KICK);
- spin_unlock_irqrestore(&gp->tx_lock, flags);
-
- dev->trans_start = jiffies; /* NETIF_F_LLTX driver :( */
return NETDEV_TX_OK;
}
@@ -1184,7 +1183,6 @@
#define STOP_TRIES 32
-/* Must be invoked under gp->lock and gp->tx_lock. */
static void gem_reset(struct gem *gp)
{
int limit;
@@ -1213,7 +1211,6 @@
gem_pcs_reinit_adv(gp);
}
-/* Must be invoked under gp->lock and gp->tx_lock. */
static void gem_start_dma(struct gem *gp)
{
u32 val;
@@ -1236,8 +1233,7 @@
writel(RX_RING_SIZE - 4, gp->regs + RXDMA_KICK);
}
-/* Must be invoked under gp->lock and gp->tx_lock. DMA won't be
- * actually stopped before about 4ms tho ...
+/* DMA won't be actually stopped before about 4ms tho ...
*/
static void gem_stop_dma(struct gem *gp)
{
@@ -1259,7 +1255,6 @@
}
-/* Must be invoked under gp->lock and gp->tx_lock. */
// XXX dbl check what that function should do when called on PCS PHY
static void gem_begin_auto_negotiation(struct gem *gp, struct ethtool_cmd *ep)
{
@@ -1319,7 +1314,7 @@
/* If we are asleep, we don't try to actually setup the PHY, we
* just store the settings
*/
- if (gp->asleep) {
+ if (!netif_device_present(gp->dev)) {
gp->phy_mii.autoneg = gp->want_autoneg = autoneg;
gp->phy_mii.speed = speed;
gp->phy_mii.duplex = duplex;
@@ -1345,13 +1340,12 @@
/* A link-up condition has occurred, initialize and enable the
* rest of the chip.
- *
- * Must be invoked under gp->lock and gp->tx_lock.
*/
static int gem_set_link_modes(struct gem *gp)
{
- u32 val;
+ struct netdev_queue *txq = netdev_get_tx_queue(gp->dev, 0);
int full_duplex, speed, pause;
+ u32 val;
full_duplex = 0;
speed = SPEED_10;
@@ -1375,8 +1369,11 @@
netif_info(gp, link, gp->dev, "Link is up at %d Mbps, %s-duplex\n",
speed, (full_duplex ? "full" : "half"));
- if (!gp->running)
- return 0;
+
+ /* We take the tx queue lock to avoid collisions between
+ * this code, the tx path and the NAPI-driven error path
+ */
+ __netif_tx_lock(txq, smp_processor_id());
val = (MAC_TXCFG_EIPG0 | MAC_TXCFG_NGU);
if (full_duplex) {
@@ -1425,18 +1422,6 @@
pause = 1;
}
- if (netif_msg_link(gp)) {
- if (pause) {
- netdev_info(gp->dev,
- "Pause is enabled (rxfifo: %d off: %d on: %d)\n",
- gp->rx_fifo_sz,
- gp->rx_pause_off,
- gp->rx_pause_on);
- } else {
- netdev_info(gp->dev, "Pause is disabled\n");
- }
- }
-
if (!full_duplex)
writel(512, gp->regs + MAC_STIME);
else
@@ -1450,10 +1435,23 @@
gem_start_dma(gp);
+ __netif_tx_unlock(txq);
+
+ if (netif_msg_link(gp)) {
+ if (pause) {
+ netdev_info(gp->dev,
+ "Pause is enabled (rxfifo: %d off: %d on: %d)\n",
+ gp->rx_fifo_sz,
+ gp->rx_pause_off,
+ gp->rx_pause_on);
+ } else {
+ netdev_info(gp->dev, "Pause is disabled\n");
+ }
+ }
+
return 0;
}
-/* Must be invoked under gp->lock and gp->tx_lock. */
static int gem_mdio_link_not_up(struct gem *gp)
{
switch (gp->lstate) {
@@ -1501,20 +1499,12 @@
static void gem_link_timer(unsigned long data)
{
struct gem *gp = (struct gem *) data;
+ struct net_device *dev = gp->dev;
int restart_aneg = 0;
- if (gp->asleep)
- return;
-
- spin_lock_irq(&gp->lock);
- spin_lock(&gp->tx_lock);
- gem_get_cell(gp);
-
- /* If the reset task is still pending, we just
- * reschedule the link timer
- */
+ /* There's no point doing anything if we're going to be reset */
if (gp->reset_task_pending)
- goto restart;
+ return;
if (gp->phy_type == phy_serialink ||
gp->phy_type == phy_serdes) {
@@ -1528,7 +1518,7 @@
goto restart;
gp->lstate = link_up;
- netif_carrier_on(gp->dev);
+ netif_carrier_on(dev);
(void)gem_set_link_modes(gp);
}
goto restart;
@@ -1544,12 +1534,12 @@
gp->last_forced_speed = gp->phy_mii.speed;
gp->timer_ticks = 5;
if (netif_msg_link(gp))
- netdev_info(gp->dev,
+ netdev_info(dev,
"Got link after fallback, retrying autoneg once...\n");
gp->phy_mii.def->ops->setup_aneg(&gp->phy_mii, gp->phy_mii.advertising);
} else if (gp->lstate != link_up) {
gp->lstate = link_up;
- netif_carrier_on(gp->dev);
+ netif_carrier_on(dev);
if (gem_set_link_modes(gp))
restart_aneg = 1;
}
@@ -1559,11 +1549,11 @@
*/
if (gp->lstate == link_up) {
gp->lstate = link_down;
- netif_info(gp, link, gp->dev, "Link down\n");
- netif_carrier_off(gp->dev);
- gp->reset_task_pending = 1;
- schedule_work(&gp->reset_task);
- restart_aneg = 1;
+ netif_info(gp, link, dev, "Link down\n");
+ netif_carrier_off(dev);
+ gem_schedule_reset(gp);
+ /* The reset task will restart the timer */
+ return;
} else if (++gp->timer_ticks > 10) {
if (found_mii_phy(gp))
restart_aneg = gem_mdio_link_not_up(gp);
@@ -1573,17 +1563,12 @@
}
if (restart_aneg) {
gem_begin_auto_negotiation(gp, NULL);
- goto out_unlock;
+ return;
}
restart:
mod_timer(&gp->link_timer, jiffies + ((12 * HZ) / 10));
-out_unlock:
- gem_put_cell(gp);
- spin_unlock(&gp->tx_lock);
- spin_unlock_irq(&gp->lock);
}
-/* Must be invoked under gp->lock and gp->tx_lock. */
static void gem_clean_rings(struct gem *gp)
{
struct gem_init_block *gb = gp->init_block;
@@ -1634,7 +1619,6 @@
}
}
-/* Must be invoked under gp->lock and gp->tx_lock. */
static void gem_init_rings(struct gem *gp)
{
struct gem_init_block *gb = gp->init_block;
@@ -1653,7 +1637,7 @@
struct sk_buff *skb;
struct gem_rxd *rxd = &gb->rxd[i];
- skb = gem_alloc_skb(RX_BUF_ALLOC_SIZE(gp), GFP_ATOMIC);
+ skb = gem_alloc_skb(dev, RX_BUF_ALLOC_SIZE(gp), GFP_KERNEL);
if (!skb) {
rxd->buffer = 0;
rxd->status_word = 0;
@@ -1661,7 +1645,6 @@
}
gp->rx_skbs[i] = skb;
- skb->dev = dev;
skb_put(skb, (gp->rx_buf_sz + RX_OFFSET));
dma_addr = pci_map_page(gp->pdev,
virt_to_page(skb->data),
@@ -1737,7 +1720,7 @@
if (gp->phy_type == phy_mii_mdio0 ||
gp->phy_type == phy_mii_mdio1) {
- // XXX check for errors
+ /* Reset and detect MII PHY */
mii_phy_probe(&gp->phy_mii, gp->mii_phy_addr);
/* Init PHY */
@@ -1753,13 +1736,15 @@
gp->lstate = link_down;
netif_carrier_off(gp->dev);
- /* Can I advertise gigabit here ? I'd need BCM PHY docs... */
- spin_lock_irq(&gp->lock);
+ /* Print things out */
+ if (gp->phy_type == phy_mii_mdio0 ||
+ gp->phy_type == phy_mii_mdio1)
+ netdev_info(gp->dev, "Found %s PHY\n",
+ gp->phy_mii.def ? gp->phy_mii.def->name : "no");
+
gem_begin_auto_negotiation(gp, NULL);
- spin_unlock_irq(&gp->lock);
}
-/* Must be invoked under gp->lock and gp->tx_lock. */
static void gem_init_dma(struct gem *gp)
{
u64 desc_dma = (u64) gp->gblock_dvma;
@@ -1797,7 +1782,6 @@
gp->regs + RXDMA_BLANK);
}
-/* Must be invoked under gp->lock and gp->tx_lock. */
static u32 gem_setup_multicast(struct gem *gp)
{
u32 rxcfg = 0;
@@ -1835,7 +1819,6 @@
return rxcfg;
}
-/* Must be invoked under gp->lock and gp->tx_lock. */
static void gem_init_mac(struct gem *gp)
{
unsigned char *e = &gp->dev->dev_addr[0];
@@ -1918,7 +1901,6 @@
writel(0, gp->regs + WOL_WAKECSR);
}
-/* Must be invoked under gp->lock and gp->tx_lock. */
static void gem_init_pause_thresholds(struct gem *gp)
{
u32 cfg;
@@ -2079,7 +2061,6 @@
return 0;
}
-/* Must be invoked under gp->lock and gp->tx_lock. */
static void gem_reinit_chip(struct gem *gp)
{
/* Reset the chip */
@@ -2100,11 +2081,9 @@
}
-/* Must be invoked with no lock held. */
static void gem_stop_phy(struct gem *gp, int wol)
{
u32 mifcfg;
- unsigned long flags;
/* Let the chip settle down a bit, it seems that helps
* for sleep mode on some models
@@ -2150,15 +2129,9 @@
writel(0, gp->regs + RXDMA_CFG);
if (!wol) {
- spin_lock_irqsave(&gp->lock, flags);
- spin_lock(&gp->tx_lock);
gem_reset(gp);
writel(MAC_TXRST_CMD, gp->regs + MAC_TXRST);
writel(MAC_RXRST_CMD, gp->regs + MAC_RXRST);
- spin_unlock(&gp->tx_lock);
- spin_unlock_irqrestore(&gp->lock, flags);
-
- /* No need to take the lock here */
if (found_mii_phy(gp) && gp->phy_mii.def->ops->suspend)
gp->phy_mii.def->ops->suspend(&gp->phy_mii);
@@ -2175,77 +2148,86 @@
}
}
-
static int gem_do_start(struct net_device *dev)
{
struct gem *gp = netdev_priv(dev);
- unsigned long flags;
-
- spin_lock_irqsave(&gp->lock, flags);
- spin_lock(&gp->tx_lock);
+ int rc;
/* Enable the cell */
gem_get_cell(gp);
+ /* Make sure PCI access and bus master are enabled */
+ rc = pci_enable_device(gp->pdev);
+ if (rc) {
+ netdev_err(dev, "Failed to enable chip on PCI bus !\n");
+
+ /* Put cell and forget it for now, it will be considered as
+ * still asleep, a new sleep cycle may bring it back
+ */
+ gem_put_cell(gp);
+ return -ENXIO;
+ }
+ pci_set_master(gp->pdev);
+
/* Init & setup chip hardware */
gem_reinit_chip(gp);
- gp->running = 1;
-
- napi_enable(&gp->napi);
-
- if (gp->lstate == link_up) {
- netif_carrier_on(gp->dev);
- gem_set_link_modes(gp);
- }
-
- netif_wake_queue(gp->dev);
-
- spin_unlock(&gp->tx_lock);
- spin_unlock_irqrestore(&gp->lock, flags);
-
- if (request_irq(gp->pdev->irq, gem_interrupt,
- IRQF_SHARED, dev->name, (void *)dev)) {
+ /* An interrupt might come in handy */
+ rc = request_irq(gp->pdev->irq, gem_interrupt,
+ IRQF_SHARED, dev->name, (void *)dev);
+ if (rc) {
netdev_err(dev, "failed to request irq !\n");
- spin_lock_irqsave(&gp->lock, flags);
- spin_lock(&gp->tx_lock);
-
- napi_disable(&gp->napi);
-
- gp->running = 0;
gem_reset(gp);
gem_clean_rings(gp);
gem_put_cell(gp);
-
- spin_unlock(&gp->tx_lock);
- spin_unlock_irqrestore(&gp->lock, flags);
-
- return -EAGAIN;
+ return rc;
}
+ /* Mark us as attached again if we come from resume(), this has
+ * no effect if we weren't detatched and needs to be done now.
+ */
+ netif_device_attach(dev);
+
+ /* Restart NAPI & queues */
+ gem_netif_start(gp);
+
+ /* Detect & init PHY, start autoneg etc... this will
+ * eventually result in starting DMA operations when
+ * the link is up
+ */
+ gem_init_phy(gp);
+
return 0;
}
static void gem_do_stop(struct net_device *dev, int wol)
{
struct gem *gp = netdev_priv(dev);
- unsigned long flags;
- spin_lock_irqsave(&gp->lock, flags);
- spin_lock(&gp->tx_lock);
+ /* Stop NAPI and stop tx queue */
+ gem_netif_stop(gp);
- gp->running = 0;
-
- /* Stop netif queue */
- netif_stop_queue(dev);
-
- /* Make sure ints are disabled */
+ /* Make sure ints are disabled. We don't care about
+ * synchronizing as NAPI is disabled, thus a stray
+ * interrupt will do nothing bad (our irq handler
+ * just schedules NAPI)
+ */
gem_disable_ints(gp);
- /* We can drop the lock now */
- spin_unlock(&gp->tx_lock);
- spin_unlock_irqrestore(&gp->lock, flags);
+ /* Stop the link timer */
+ del_timer_sync(&gp->link_timer);
+
+ /* We cannot cancel the reset task while holding the
+ * rtnl lock, we'd get an A->B / B->A deadlock stituation
+ * if we did. This is not an issue however as the reset
+ * task is synchronized vs. us (rtnl_lock) and will do
+ * nothing if the device is down or suspended. We do
+ * still clear reset_task_pending to avoid a spurrious
+ * reset later on in case we do resume before it gets
+ * scheduled.
+ */
+ gp->reset_task_pending = 0;
/* If we are going to sleep with WOL */
gem_stop_dma(gp);
@@ -2260,79 +2242,79 @@
/* No irq needed anymore */
free_irq(gp->pdev->irq, (void *) dev);
+ /* Shut the PHY down eventually and setup WOL */
+ gem_stop_phy(gp, wol);
+
+ /* Make sure bus master is disabled */
+ pci_disable_device(gp->pdev);
+
/* Cell not needed neither if no WOL */
- if (!wol) {
- spin_lock_irqsave(&gp->lock, flags);
+ if (!wol)
gem_put_cell(gp);
- spin_unlock_irqrestore(&gp->lock, flags);
- }
}
static void gem_reset_task(struct work_struct *work)
{
struct gem *gp = container_of(work, struct gem, reset_task);
- mutex_lock(&gp->pm_mutex);
+ /* Lock out the network stack (essentially shield ourselves
+ * against a racing open, close, control call, or suspend
+ */
+ rtnl_lock();
- if (gp->opened)
- napi_disable(&gp->napi);
-
- spin_lock_irq(&gp->lock);
- spin_lock(&gp->tx_lock);
-
- if (gp->running) {
- netif_stop_queue(gp->dev);
-
- /* Reset the chip & rings */
- gem_reinit_chip(gp);
- if (gp->lstate == link_up)
- gem_set_link_modes(gp);
- netif_wake_queue(gp->dev);
+ /* Skip the reset task if suspended or closed, or if it's
+ * been cancelled by gem_do_stop (see comment there)
+ */
+ if (!netif_device_present(gp->dev) ||
+ !netif_running(gp->dev) ||
+ !gp->reset_task_pending) {
+ rtnl_unlock();
+ return;
}
+ /* Stop the link timer */
+ del_timer_sync(&gp->link_timer);
+
+ /* Stop NAPI and tx */
+ gem_netif_stop(gp);
+
+ /* Reset the chip & rings */
+ gem_reinit_chip(gp);
+ if (gp->lstate == link_up)
+ gem_set_link_modes(gp);
+
+ /* Restart NAPI and Tx */
+ gem_netif_start(gp);
+
+ /* We are back ! */
gp->reset_task_pending = 0;
- spin_unlock(&gp->tx_lock);
- spin_unlock_irq(&gp->lock);
+ /* If the link is not up, restart autoneg, else restart the
+ * polling timer
+ */
+ if (gp->lstate != link_up)
+ gem_begin_auto_negotiation(gp, NULL);
+ else
+ mod_timer(&gp->link_timer, jiffies + ((12 * HZ) / 10));
- if (gp->opened)
- napi_enable(&gp->napi);
-
- mutex_unlock(&gp->pm_mutex);
+ rtnl_unlock();
}
-
static int gem_open(struct net_device *dev)
{
- struct gem *gp = netdev_priv(dev);
- int rc = 0;
-
- mutex_lock(&gp->pm_mutex);
-
- /* We need the cell enabled */
- if (!gp->asleep)
- rc = gem_do_start(dev);
- gp->opened = (rc == 0);
-
- mutex_unlock(&gp->pm_mutex);
-
- return rc;
+ /* We allow open while suspended, we just do nothing,
+ * the chip will be initialized in resume()
+ */
+ if (netif_device_present(dev))
+ return gem_do_start(dev);
+ return 0;
}
static int gem_close(struct net_device *dev)
{
- struct gem *gp = netdev_priv(dev);
-
- mutex_lock(&gp->pm_mutex);
-
- napi_disable(&gp->napi);
-
- gp->opened = 0;
- if (!gp->asleep)
+ if (netif_device_present(dev))
gem_do_stop(dev, 0);
- mutex_unlock(&gp->pm_mutex);
-
return 0;
}
@@ -2341,59 +2323,35 @@
{
struct net_device *dev = pci_get_drvdata(pdev);
struct gem *gp = netdev_priv(dev);
- unsigned long flags;
- mutex_lock(&gp->pm_mutex);
+ /* Lock the network stack first to avoid racing with open/close,
+ * reset task and setting calls
+ */
+ rtnl_lock();
- netdev_info(dev, "suspending, WakeOnLan %s\n",
- (gp->wake_on_lan && gp->opened) ? "enabled" : "disabled");
-
- /* Keep the cell enabled during the entire operation */
- spin_lock_irqsave(&gp->lock, flags);
- spin_lock(&gp->tx_lock);
- gem_get_cell(gp);
- spin_unlock(&gp->tx_lock);
- spin_unlock_irqrestore(&gp->lock, flags);
-
- /* If the driver is opened, we stop the MAC */
- if (gp->opened) {
- napi_disable(&gp->napi);
-
- /* Stop traffic, mark us closed */
+ /* Not running, mark ourselves non-present, no need for
+ * a lock here
+ */
+ if (!netif_running(dev)) {
netif_device_detach(dev);
+ rtnl_unlock();
+ return 0;
+ }
+ netdev_info(dev, "suspending, WakeOnLan %s\n",
+ (gp->wake_on_lan && netif_running(dev)) ?
+ "enabled" : "disabled");
- /* Switch off MAC, remember WOL setting */
- gp->asleep_wol = gp->wake_on_lan;
- gem_do_stop(dev, gp->asleep_wol);
- } else
- gp->asleep_wol = 0;
-
- /* Mark us asleep */
- gp->asleep = 1;
- wmb();
-
- /* Stop the link timer */
- del_timer_sync(&gp->link_timer);
-
- /* Now we release the mutex to not block the reset task who
- * can take it too. We are marked asleep, so there will be no
- * conflict here
+ /* Tell the network stack we're gone. gem_do_stop() below will
+ * synchronize with TX, stop NAPI etc...
*/
- mutex_unlock(&gp->pm_mutex);
+ netif_device_detach(dev);
- /* Wait for the pending reset task to complete */
- flush_work_sync(&gp->reset_task);
+ /* Switch off chip, remember WOL setting */
+ gp->asleep_wol = gp->wake_on_lan;
+ gem_do_stop(dev, gp->asleep_wol);
- /* Shut the PHY down eventually and setup WOL */
- gem_stop_phy(gp, gp->asleep_wol);
-
- /* Make sure bus master is disabled */
- pci_disable_device(gp->pdev);
-
- /* Release the cell, no need to take a lock at this point since
- * nothing else can happen now
- */
- gem_put_cell(gp);
+ /* Unlock the network stack */
+ rtnl_unlock();
return 0;
}
@@ -2402,53 +2360,23 @@
{
struct net_device *dev = pci_get_drvdata(pdev);
struct gem *gp = netdev_priv(dev);
- unsigned long flags;
- netdev_info(dev, "resuming\n");
+ /* See locking comment in gem_suspend */
+ rtnl_lock();
- mutex_lock(&gp->pm_mutex);
-
- /* Keep the cell enabled during the entire operation, no need to
- * take a lock here tho since nothing else can happen while we are
- * marked asleep
+ /* Not running, mark ourselves present, no need for
+ * a lock here
*/
- gem_get_cell(gp);
-
- /* Make sure PCI access and bus master are enabled */
- if (pci_enable_device(gp->pdev)) {
- netdev_err(dev, "Can't re-enable chip !\n");
- /* Put cell and forget it for now, it will be considered as
- * still asleep, a new sleep cycle may bring it back
- */
- gem_put_cell(gp);
- mutex_unlock(&gp->pm_mutex);
+ if (!netif_running(dev)) {
+ netif_device_attach(dev);
+ rtnl_unlock();
return 0;
}
- pci_set_master(gp->pdev);
- /* Reset everything */
- gem_reset(gp);
-
- /* Mark us woken up */
- gp->asleep = 0;
- wmb();
-
- /* Bring the PHY back. Again, lock is useless at this point as
- * nothing can be happening until we restart the whole thing
+ /* Restart chip. If that fails there isn't much we can do, we
+ * leave things stopped.
*/
- gem_init_phy(gp);
-
- /* If we were opened, bring everything back */
- if (gp->opened) {
- /* Restart MAC */
- gem_do_start(dev);
-
- /* Re-attach net device */
- netif_device_attach(dev);
- }
-
- spin_lock_irqsave(&gp->lock, flags);
- spin_lock(&gp->tx_lock);
+ gem_do_start(dev);
/* If we had WOL enabled, the cell clock was never turned off during
* sleep, so we end up beeing unbalanced. Fix that here
@@ -2456,15 +2384,8 @@
if (gp->asleep_wol)
gem_put_cell(gp);
- /* This function doesn't need to hold the cell, it will be held if the
- * driver is open by gem_do_start().
- */
- gem_put_cell(gp);
-
- spin_unlock(&gp->tx_lock);
- spin_unlock_irqrestore(&gp->lock, flags);
-
- mutex_unlock(&gp->pm_mutex);
+ /* Unlock the network stack */
+ rtnl_unlock();
return 0;
}
@@ -2474,33 +2395,35 @@
{
struct gem *gp = netdev_priv(dev);
- spin_lock_irq(&gp->lock);
- spin_lock(&gp->tx_lock);
-
/* I have seen this being called while the PM was in progress,
- * so we shield against this
+ * so we shield against this. Let's also not poke at registers
+ * while the reset task is going on.
+ *
+ * TODO: Move stats collection elsewhere (link timer ?) and
+ * make this a nop to avoid all those synchro issues
*/
- if (gp->running) {
- dev->stats.rx_crc_errors += readl(gp->regs + MAC_FCSERR);
- writel(0, gp->regs + MAC_FCSERR);
+ if (!netif_device_present(dev) || !netif_running(dev))
+ goto bail;
- dev->stats.rx_frame_errors += readl(gp->regs + MAC_AERR);
- writel(0, gp->regs + MAC_AERR);
+ /* Better safe than sorry... */
+ if (WARN_ON(!gp->cell_enabled))
+ goto bail;
- dev->stats.rx_length_errors += readl(gp->regs + MAC_LERR);
- writel(0, gp->regs + MAC_LERR);
+ dev->stats.rx_crc_errors += readl(gp->regs + MAC_FCSERR);
+ writel(0, gp->regs + MAC_FCSERR);
- dev->stats.tx_aborted_errors += readl(gp->regs + MAC_ECOLL);
- dev->stats.collisions +=
- (readl(gp->regs + MAC_ECOLL) +
- readl(gp->regs + MAC_LCOLL));
- writel(0, gp->regs + MAC_ECOLL);
- writel(0, gp->regs + MAC_LCOLL);
- }
+ dev->stats.rx_frame_errors += readl(gp->regs + MAC_AERR);
+ writel(0, gp->regs + MAC_AERR);
- spin_unlock(&gp->tx_lock);
- spin_unlock_irq(&gp->lock);
+ dev->stats.rx_length_errors += readl(gp->regs + MAC_LERR);
+ writel(0, gp->regs + MAC_LERR);
+ dev->stats.tx_aborted_errors += readl(gp->regs + MAC_ECOLL);
+ dev->stats.collisions +=
+ (readl(gp->regs + MAC_ECOLL) + readl(gp->regs + MAC_LCOLL));
+ writel(0, gp->regs + MAC_ECOLL);
+ writel(0, gp->regs + MAC_LCOLL);
+ bail:
return &dev->stats;
}
@@ -2513,22 +2436,19 @@
if (!is_valid_ether_addr(macaddr->sa_data))
return -EADDRNOTAVAIL;
- if (!netif_running(dev) || !netif_device_present(dev)) {
- /* We'll just catch it later when the
- * device is up'd or resumed.
- */
- memcpy(dev->dev_addr, macaddr->sa_data, dev->addr_len);
- return 0;
- }
-
- mutex_lock(&gp->pm_mutex);
memcpy(dev->dev_addr, macaddr->sa_data, dev->addr_len);
- if (gp->running) {
- writel((e[4] << 8) | e[5], gp->regs + MAC_ADDR0);
- writel((e[2] << 8) | e[3], gp->regs + MAC_ADDR1);
- writel((e[0] << 8) | e[1], gp->regs + MAC_ADDR2);
- }
- mutex_unlock(&gp->pm_mutex);
+
+ /* We'll just catch it later when the device is up'd or resumed */
+ if (!netif_running(dev) || !netif_device_present(dev))
+ return 0;
+
+ /* Better safe than sorry... */
+ if (WARN_ON(!gp->cell_enabled))
+ return 0;
+
+ writel((e[4] << 8) | e[5], gp->regs + MAC_ADDR0);
+ writel((e[2] << 8) | e[3], gp->regs + MAC_ADDR1);
+ writel((e[0] << 8) | e[1], gp->regs + MAC_ADDR2);
return 0;
}
@@ -2539,14 +2459,12 @@
u32 rxcfg, rxcfg_new;
int limit = 10000;
+ if (!netif_running(dev) || !netif_device_present(dev))
+ return;
- spin_lock_irq(&gp->lock);
- spin_lock(&gp->tx_lock);
-
- if (!gp->running)
- goto bail;
-
- netif_stop_queue(dev);
+ /* Better safe than sorry... */
+ if (gp->reset_task_pending || WARN_ON(!gp->cell_enabled))
+ return;
rxcfg = readl(gp->regs + MAC_RXCFG);
rxcfg_new = gem_setup_multicast(gp);
@@ -2566,12 +2484,6 @@
rxcfg |= rxcfg_new;
writel(rxcfg, gp->regs + MAC_RXCFG);
-
- netif_wake_queue(dev);
-
- bail:
- spin_unlock(&gp->tx_lock);
- spin_unlock_irq(&gp->lock);
}
/* Jumbo-grams don't seem to work :-( */
@@ -2589,26 +2501,21 @@
if (new_mtu < GEM_MIN_MTU || new_mtu > GEM_MAX_MTU)
return -EINVAL;
- if (!netif_running(dev) || !netif_device_present(dev)) {
- /* We'll just catch it later when the
- * device is up'd or resumed.
- */
- dev->mtu = new_mtu;
- return 0;
- }
-
- mutex_lock(&gp->pm_mutex);
- spin_lock_irq(&gp->lock);
- spin_lock(&gp->tx_lock);
dev->mtu = new_mtu;
- if (gp->running) {
- gem_reinit_chip(gp);
- if (gp->lstate == link_up)
- gem_set_link_modes(gp);
- }
- spin_unlock(&gp->tx_lock);
- spin_unlock_irq(&gp->lock);
- mutex_unlock(&gp->pm_mutex);
+
+ /* We'll just catch it later when the device is up'd or resumed */
+ if (!netif_running(dev) || !netif_device_present(dev))
+ return 0;
+
+ /* Better safe than sorry... */
+ if (WARN_ON(!gp->cell_enabled))
+ return 0;
+
+ gem_netif_stop(gp);
+ gem_reinit_chip(gp);
+ if (gp->lstate == link_up)
+ gem_set_link_modes(gp);
+ gem_netif_start(gp);
return 0;
}
@@ -2640,7 +2547,6 @@
cmd->phy_address = 0; /* XXX fixed PHYAD */
/* Return current PHY settings */
- spin_lock_irq(&gp->lock);
cmd->autoneg = gp->want_autoneg;
ethtool_cmd_speed_set(cmd, gp->phy_mii.speed);
cmd->duplex = gp->phy_mii.duplex;
@@ -2652,7 +2558,6 @@
*/
if (cmd->advertising == 0)
cmd->advertising = cmd->supported;
- spin_unlock_irq(&gp->lock);
} else { // XXX PCS ?
cmd->supported =
(SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full |
@@ -2706,11 +2611,10 @@
return -EINVAL;
/* Apply settings and restart link process. */
- spin_lock_irq(&gp->lock);
- gem_get_cell(gp);
- gem_begin_auto_negotiation(gp, cmd);
- gem_put_cell(gp);
- spin_unlock_irq(&gp->lock);
+ if (netif_device_present(gp->dev)) {
+ del_timer_sync(&gp->link_timer);
+ gem_begin_auto_negotiation(gp, cmd);
+ }
return 0;
}
@@ -2722,12 +2626,11 @@
if (!gp->want_autoneg)
return -EINVAL;
- /* Restart link process. */
- spin_lock_irq(&gp->lock);
- gem_get_cell(gp);
- gem_begin_auto_negotiation(gp, NULL);
- gem_put_cell(gp);
- spin_unlock_irq(&gp->lock);
+ /* Restart link process */
+ if (netif_device_present(gp->dev)) {
+ del_timer_sync(&gp->link_timer);
+ gem_begin_auto_negotiation(gp, NULL);
+ }
return 0;
}
@@ -2791,16 +2694,11 @@
struct gem *gp = netdev_priv(dev);
struct mii_ioctl_data *data = if_mii(ifr);
int rc = -EOPNOTSUPP;
- unsigned long flags;
- /* Hold the PM mutex while doing ioctl's or we may collide
- * with power management.
+ /* For SIOCGMIIREG and SIOCSMIIREG the core checks for us that
+ * netif_device_present() is true and holds rtnl_lock for us
+ * so we have nothing to worry about
*/
- mutex_lock(&gp->pm_mutex);
-
- spin_lock_irqsave(&gp->lock, flags);
- gem_get_cell(gp);
- spin_unlock_irqrestore(&gp->lock, flags);
switch (cmd) {
case SIOCGMIIPHY: /* Get address of MII PHY in use. */
@@ -2808,32 +2706,17 @@
/* Fallthrough... */
case SIOCGMIIREG: /* Read MII PHY register. */
- if (!gp->running)
- rc = -EAGAIN;
- else {
- data->val_out = __phy_read(gp, data->phy_id & 0x1f,
- data->reg_num & 0x1f);
- rc = 0;
- }
+ data->val_out = __phy_read(gp, data->phy_id & 0x1f,
+ data->reg_num & 0x1f);
+ rc = 0;
break;
case SIOCSMIIREG: /* Write MII PHY register. */
- if (!gp->running)
- rc = -EAGAIN;
- else {
- __phy_write(gp, data->phy_id & 0x1f, data->reg_num & 0x1f,
- data->val_in);
- rc = 0;
- }
+ __phy_write(gp, data->phy_id & 0x1f, data->reg_num & 0x1f,
+ data->val_in);
+ rc = 0;
break;
- };
-
- spin_lock_irqsave(&gp->lock, flags);
- gem_put_cell(gp);
- spin_unlock_irqrestore(&gp->lock, flags);
-
- mutex_unlock(&gp->pm_mutex);
-
+ }
return rc;
}
@@ -2921,23 +2804,9 @@
unregister_netdev(dev);
- /* Stop the link timer */
- del_timer_sync(&gp->link_timer);
-
- /* We shouldn't need any locking here */
- gem_get_cell(gp);
-
- /* Cancel reset task */
+ /* Ensure reset task is truely gone */
cancel_work_sync(&gp->reset_task);
- /* Shut the PHY down */
- gem_stop_phy(gp, 0);
-
- gem_put_cell(gp);
-
- /* Make sure bus master is disabled */
- pci_disable_device(gp->pdev);
-
/* Free resources */
pci_free_consistent(pdev,
sizeof(struct gem_init_block),
@@ -3043,10 +2912,6 @@
gp->msg_enable = DEFAULT_MSG;
- spin_lock_init(&gp->lock);
- spin_lock_init(&gp->tx_lock);
- mutex_init(&gp->pm_mutex);
-
init_timer(&gp->link_timer);
gp->link_timer.function = gem_link_timer;
gp->link_timer.data = (unsigned long) gp;
@@ -3122,14 +2987,11 @@
/* Set that now, in case PM kicks in now */
pci_set_drvdata(pdev, dev);
- /* Detect & init PHY, start autoneg, we release the cell now
- * too, it will be managed by whoever needs it
- */
- gem_init_phy(gp);
-
- spin_lock_irq(&gp->lock);
- gem_put_cell(gp);
- spin_unlock_irq(&gp->lock);
+ /* We can do scatter/gather and HW checksum */
+ dev->hw_features = NETIF_F_SG | NETIF_F_HW_CSUM;
+ dev->features |= dev->hw_features | NETIF_F_RXCSUM;
+ if (pci_using_dac)
+ dev->features |= NETIF_F_HIGHDMA;
/* Register with kernel */
if (register_netdev(dev)) {
@@ -3138,20 +3000,15 @@
goto err_out_free_consistent;
}
+ /* Undo the get_cell with appropriate locking (we could use
+ * ndo_init/uninit but that would be even more clumsy imho)
+ */
+ rtnl_lock();
+ gem_put_cell(gp);
+ rtnl_unlock();
+
netdev_info(dev, "Sun GEM (PCI) 10/100/1000BaseT Ethernet %pM\n",
dev->dev_addr);
-
- if (gp->phy_type == phy_mii_mdio0 ||
- gp->phy_type == phy_mii_mdio1)
- netdev_info(dev, "Found %s PHY\n",
- gp->phy_mii.def ? gp->phy_mii.def->name : "no");
-
- /* GEM can do it all... */
- dev->hw_features = NETIF_F_SG | NETIF_F_HW_CSUM;
- dev->features |= dev->hw_features | NETIF_F_RXCSUM | NETIF_F_LLTX;
- if (pci_using_dac)
- dev->features |= NETIF_F_HIGHDMA;
-
return 0;
err_out_free_consistent:
diff --git a/drivers/net/sungem.h b/drivers/net/sungem.h
index d2250779..835ce1b 100644
--- a/drivers/net/sungem.h
+++ b/drivers/net/sungem.h
@@ -973,23 +973,14 @@
};
struct gem {
- spinlock_t lock;
- spinlock_t tx_lock;
void __iomem *regs;
int rx_new, rx_old;
int tx_new, tx_old;
unsigned int has_wol : 1; /* chip supports wake-on-lan */
- unsigned int asleep : 1; /* chip asleep, protected by pm_mutex */
unsigned int asleep_wol : 1; /* was asleep with WOL enabled */
- unsigned int opened : 1; /* driver opened, protected by pm_mutex */
- unsigned int running : 1; /* chip running, protected by lock */
- /* cell enable count, protected by lock */
int cell_enabled;
-
- struct mutex pm_mutex;
-
u32 msg_enable;
u32 status;
@@ -1033,20 +1024,4 @@
#define found_mii_phy(gp) ((gp->phy_type == phy_mii_mdio0 || gp->phy_type == phy_mii_mdio1) && \
gp->phy_mii.def && gp->phy_mii.def->ops)
-#define ALIGNED_RX_SKB_ADDR(addr) \
- ((((unsigned long)(addr) + (64UL - 1UL)) & ~(64UL - 1UL)) - (unsigned long)(addr))
-static __inline__ struct sk_buff *gem_alloc_skb(int size,
- gfp_t gfp_flags)
-{
- struct sk_buff *skb = alloc_skb(size + 64, gfp_flags);
-
- if (skb) {
- int offset = (int) ALIGNED_RX_SKB_ADDR(skb->data);
- if (offset)
- skb_reserve(skb, offset);
- }
-
- return skb;
-}
-
#endif /* _SUNGEM_H */
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index a1f9f9e..8211b9a 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -26,6 +26,7 @@
#include <linux/delay.h>
#include <linux/in.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/pci.h>
#include <linux/netdevice.h>
@@ -106,6 +107,8 @@
NETIF_MSG_RX_ERR | \
NETIF_MSG_TX_ERR)
+#define TG3_GRC_LCLCTL_PWRSW_DELAY 100
+
/* length of time before we decide the hardware is borked,
* and dev->tx_timeout() should be called to fix the problem
*/
@@ -860,7 +863,7 @@
int ret;
if ((tp->phy_flags & TG3_PHYFLG_IS_FET) &&
- (reg == MII_TG3_CTRL || reg == MII_TG3_AUX_CTRL))
+ (reg == MII_CTRL1000 || reg == MII_TG3_AUX_CTRL))
return 0;
if ((tp->mi_mode & MAC_MI_MODE_AUTO_POLL) != 0) {
@@ -1980,15 +1983,14 @@
/* Set full-duplex, 1000 mbps. */
tg3_writephy(tp, MII_BMCR,
- BMCR_FULLDPLX | TG3_BMCR_SPEED1000);
+ BMCR_FULLDPLX | BMCR_SPEED1000);
/* Set to master mode. */
- if (tg3_readphy(tp, MII_TG3_CTRL, &phy9_orig))
+ if (tg3_readphy(tp, MII_CTRL1000, &phy9_orig))
continue;
- tg3_writephy(tp, MII_TG3_CTRL,
- (MII_TG3_CTRL_AS_MASTER |
- MII_TG3_CTRL_ENABLE_AS_MASTER));
+ tg3_writephy(tp, MII_CTRL1000,
+ CTL1000_AS_MASTER | CTL1000_ENABLE_MASTER);
err = TG3_PHY_AUXCTL_SMDSP_ENABLE(tp);
if (err)
@@ -2013,7 +2015,7 @@
TG3_PHY_AUXCTL_SMDSP_DISABLE(tp);
- tg3_writephy(tp, MII_TG3_CTRL, phy9_orig);
+ tg3_writephy(tp, MII_CTRL1000, phy9_orig);
if (!tg3_readphy(tp, MII_TG3_EXT_CTRL, ®32)) {
reg32 &= ~0x3000;
@@ -2165,6 +2167,118 @@
return 0;
}
+static inline int tg3_pwrsrc_switch_to_vmain(struct tg3 *tp)
+{
+ if (!tg3_flag(tp, IS_NIC))
+ return 0;
+
+ tw32_wait_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl,
+ TG3_GRC_LCLCTL_PWRSW_DELAY);
+
+ return 0;
+}
+
+static void tg3_pwrsrc_die_with_vmain(struct tg3 *tp)
+{
+ u32 grc_local_ctrl;
+
+ if (!tg3_flag(tp, IS_NIC) ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701)
+ return;
+
+ grc_local_ctrl = tp->grc_local_ctrl | GRC_LCLCTRL_GPIO_OE1;
+
+ tw32_wait_f(GRC_LOCAL_CTRL,
+ grc_local_ctrl | GRC_LCLCTRL_GPIO_OUTPUT1,
+ TG3_GRC_LCLCTL_PWRSW_DELAY);
+
+ tw32_wait_f(GRC_LOCAL_CTRL,
+ grc_local_ctrl,
+ TG3_GRC_LCLCTL_PWRSW_DELAY);
+
+ tw32_wait_f(GRC_LOCAL_CTRL,
+ grc_local_ctrl | GRC_LCLCTRL_GPIO_OUTPUT1,
+ TG3_GRC_LCLCTL_PWRSW_DELAY);
+}
+
+static void tg3_pwrsrc_switch_to_vaux(struct tg3 *tp)
+{
+ if (!tg3_flag(tp, IS_NIC))
+ return;
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701) {
+ tw32_wait_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl |
+ (GRC_LCLCTRL_GPIO_OE0 |
+ GRC_LCLCTRL_GPIO_OE1 |
+ GRC_LCLCTRL_GPIO_OE2 |
+ GRC_LCLCTRL_GPIO_OUTPUT0 |
+ GRC_LCLCTRL_GPIO_OUTPUT1),
+ TG3_GRC_LCLCTL_PWRSW_DELAY);
+ } else if (tp->pdev->device == PCI_DEVICE_ID_TIGON3_5761 ||
+ tp->pdev->device == TG3PCI_DEVICE_TIGON3_5761S) {
+ /* The 5761 non-e device swaps GPIO 0 and GPIO 2. */
+ u32 grc_local_ctrl = GRC_LCLCTRL_GPIO_OE0 |
+ GRC_LCLCTRL_GPIO_OE1 |
+ GRC_LCLCTRL_GPIO_OE2 |
+ GRC_LCLCTRL_GPIO_OUTPUT0 |
+ GRC_LCLCTRL_GPIO_OUTPUT1 |
+ tp->grc_local_ctrl;
+ tw32_wait_f(GRC_LOCAL_CTRL, grc_local_ctrl,
+ TG3_GRC_LCLCTL_PWRSW_DELAY);
+
+ grc_local_ctrl |= GRC_LCLCTRL_GPIO_OUTPUT2;
+ tw32_wait_f(GRC_LOCAL_CTRL, grc_local_ctrl,
+ TG3_GRC_LCLCTL_PWRSW_DELAY);
+
+ grc_local_ctrl &= ~GRC_LCLCTRL_GPIO_OUTPUT0;
+ tw32_wait_f(GRC_LOCAL_CTRL, grc_local_ctrl,
+ TG3_GRC_LCLCTL_PWRSW_DELAY);
+ } else {
+ u32 no_gpio2;
+ u32 grc_local_ctrl = 0;
+
+ /* Workaround to prevent overdrawing Amps. */
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714) {
+ grc_local_ctrl |= GRC_LCLCTRL_GPIO_OE3;
+ tw32_wait_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl |
+ grc_local_ctrl,
+ TG3_GRC_LCLCTL_PWRSW_DELAY);
+ }
+
+ /* On 5753 and variants, GPIO2 cannot be used. */
+ no_gpio2 = tp->nic_sram_data_cfg &
+ NIC_SRAM_DATA_CFG_NO_GPIO2;
+
+ grc_local_ctrl |= GRC_LCLCTRL_GPIO_OE0 |
+ GRC_LCLCTRL_GPIO_OE1 |
+ GRC_LCLCTRL_GPIO_OE2 |
+ GRC_LCLCTRL_GPIO_OUTPUT1 |
+ GRC_LCLCTRL_GPIO_OUTPUT2;
+ if (no_gpio2) {
+ grc_local_ctrl &= ~(GRC_LCLCTRL_GPIO_OE2 |
+ GRC_LCLCTRL_GPIO_OUTPUT2);
+ }
+ tw32_wait_f(GRC_LOCAL_CTRL,
+ tp->grc_local_ctrl | grc_local_ctrl,
+ TG3_GRC_LCLCTL_PWRSW_DELAY);
+
+ grc_local_ctrl |= GRC_LCLCTRL_GPIO_OUTPUT0;
+
+ tw32_wait_f(GRC_LOCAL_CTRL,
+ tp->grc_local_ctrl | grc_local_ctrl,
+ TG3_GRC_LCLCTL_PWRSW_DELAY);
+
+ if (!no_gpio2) {
+ grc_local_ctrl &= ~GRC_LCLCTRL_GPIO_OUTPUT2;
+ tw32_wait_f(GRC_LOCAL_CTRL,
+ tp->grc_local_ctrl | grc_local_ctrl,
+ TG3_GRC_LCLCTL_PWRSW_DELAY);
+ }
+ }
+}
+
static void tg3_frob_aux_power(struct tg3 *tp)
{
bool need_vaux = false;
@@ -2200,86 +2314,10 @@
if (tg3_flag(tp, WOL_ENABLE) || tg3_flag(tp, ENABLE_ASF))
need_vaux = true;
- if (need_vaux) {
- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701) {
- tw32_wait_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl |
- (GRC_LCLCTRL_GPIO_OE0 |
- GRC_LCLCTRL_GPIO_OE1 |
- GRC_LCLCTRL_GPIO_OE2 |
- GRC_LCLCTRL_GPIO_OUTPUT0 |
- GRC_LCLCTRL_GPIO_OUTPUT1),
- 100);
- } else if (tp->pdev->device == PCI_DEVICE_ID_TIGON3_5761 ||
- tp->pdev->device == TG3PCI_DEVICE_TIGON3_5761S) {
- /* The 5761 non-e device swaps GPIO 0 and GPIO 2. */
- u32 grc_local_ctrl = GRC_LCLCTRL_GPIO_OE0 |
- GRC_LCLCTRL_GPIO_OE1 |
- GRC_LCLCTRL_GPIO_OE2 |
- GRC_LCLCTRL_GPIO_OUTPUT0 |
- GRC_LCLCTRL_GPIO_OUTPUT1 |
- tp->grc_local_ctrl;
- tw32_wait_f(GRC_LOCAL_CTRL, grc_local_ctrl, 100);
-
- grc_local_ctrl |= GRC_LCLCTRL_GPIO_OUTPUT2;
- tw32_wait_f(GRC_LOCAL_CTRL, grc_local_ctrl, 100);
-
- grc_local_ctrl &= ~GRC_LCLCTRL_GPIO_OUTPUT0;
- tw32_wait_f(GRC_LOCAL_CTRL, grc_local_ctrl, 100);
- } else {
- u32 no_gpio2;
- u32 grc_local_ctrl = 0;
-
- /* Workaround to prevent overdrawing Amps. */
- if (GET_ASIC_REV(tp->pci_chip_rev_id) ==
- ASIC_REV_5714) {
- grc_local_ctrl |= GRC_LCLCTRL_GPIO_OE3;
- tw32_wait_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl |
- grc_local_ctrl, 100);
- }
-
- /* On 5753 and variants, GPIO2 cannot be used. */
- no_gpio2 = tp->nic_sram_data_cfg &
- NIC_SRAM_DATA_CFG_NO_GPIO2;
-
- grc_local_ctrl |= GRC_LCLCTRL_GPIO_OE0 |
- GRC_LCLCTRL_GPIO_OE1 |
- GRC_LCLCTRL_GPIO_OE2 |
- GRC_LCLCTRL_GPIO_OUTPUT1 |
- GRC_LCLCTRL_GPIO_OUTPUT2;
- if (no_gpio2) {
- grc_local_ctrl &= ~(GRC_LCLCTRL_GPIO_OE2 |
- GRC_LCLCTRL_GPIO_OUTPUT2);
- }
- tw32_wait_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl |
- grc_local_ctrl, 100);
-
- grc_local_ctrl |= GRC_LCLCTRL_GPIO_OUTPUT0;
-
- tw32_wait_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl |
- grc_local_ctrl, 100);
-
- if (!no_gpio2) {
- grc_local_ctrl &= ~GRC_LCLCTRL_GPIO_OUTPUT2;
- tw32_wait_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl |
- grc_local_ctrl, 100);
- }
- }
- } else {
- if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700 &&
- GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701) {
- tw32_wait_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl |
- (GRC_LCLCTRL_GPIO_OE1 |
- GRC_LCLCTRL_GPIO_OUTPUT1), 100);
-
- tw32_wait_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl |
- GRC_LCLCTRL_GPIO_OE1, 100);
-
- tw32_wait_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl |
- (GRC_LCLCTRL_GPIO_OE1 |
- GRC_LCLCTRL_GPIO_OUTPUT1), 100);
- }
- }
+ if (need_vaux)
+ tg3_pwrsrc_switch_to_vaux(tp);
+ else
+ tg3_pwrsrc_die_with_vmain(tp);
}
static int tg3_5700_link_polarity(struct tg3 *tp, u32 speed)
@@ -2624,8 +2662,7 @@
pci_set_power_state(tp->pdev, PCI_D0);
/* Switch out of Vaux if it is a NIC */
- if (tg3_flag(tp, IS_NIC))
- tw32_wait_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl, 100);
+ tg3_pwrsrc_switch_to_vmain(tp);
return 0;
}
@@ -2642,11 +2679,11 @@
u16 lnkctl;
pci_read_config_word(tp->pdev,
- tp->pcie_cap + PCI_EXP_LNKCTL,
+ pci_pcie_cap(tp->pdev) + PCI_EXP_LNKCTL,
&lnkctl);
lnkctl |= PCI_EXP_LNKCTL_CLKREQ_EN;
pci_write_config_word(tp->pdev,
- tp->pcie_cap + PCI_EXP_LNKCTL,
+ pci_pcie_cap(tp->pdev) + PCI_EXP_LNKCTL,
lnkctl);
}
@@ -2957,16 +2994,15 @@
new_adv = 0;
if (advertise & ADVERTISED_1000baseT_Half)
- new_adv |= MII_TG3_CTRL_ADV_1000_HALF;
+ new_adv |= ADVERTISE_1000HALF;
if (advertise & ADVERTISED_1000baseT_Full)
- new_adv |= MII_TG3_CTRL_ADV_1000_FULL;
+ new_adv |= ADVERTISE_1000FULL;
if (tp->pci_chip_rev_id == CHIPREV_ID_5701_A0 ||
tp->pci_chip_rev_id == CHIPREV_ID_5701_B0)
- new_adv |= (MII_TG3_CTRL_AS_MASTER |
- MII_TG3_CTRL_ENABLE_AS_MASTER);
+ new_adv |= CTL1000_AS_MASTER | CTL1000_ENABLE_MASTER;
- err = tg3_writephy(tp, MII_TG3_CTRL, new_adv);
+ err = tg3_writephy(tp, MII_CTRL1000, new_adv);
if (err)
goto done;
@@ -3075,7 +3111,7 @@
break;
case SPEED_1000:
- bmcr |= TG3_BMCR_SPEED1000;
+ bmcr |= BMCR_SPEED1000;
break;
}
@@ -3152,7 +3188,7 @@
if (mask & ADVERTISED_1000baseT_Full)
all_mask |= ADVERTISE_1000FULL;
- if (tg3_readphy(tp, MII_TG3_CTRL, &tg3_ctrl))
+ if (tg3_readphy(tp, MII_CTRL1000, &tg3_ctrl))
return 0;
if ((tg3_ctrl & all_mask) != all_mask)
@@ -3449,7 +3485,7 @@
u16 oldlnkctl, newlnkctl;
pci_read_config_word(tp->pdev,
- tp->pcie_cap + PCI_EXP_LNKCTL,
+ pci_pcie_cap(tp->pdev) + PCI_EXP_LNKCTL,
&oldlnkctl);
if (tp->link_config.active_speed == SPEED_100 ||
tp->link_config.active_speed == SPEED_10)
@@ -3458,7 +3494,7 @@
newlnkctl = oldlnkctl | PCI_EXP_LNKCTL_CLKREQ_EN;
if (newlnkctl != oldlnkctl)
pci_write_config_word(tp->pdev,
- tp->pcie_cap + PCI_EXP_LNKCTL,
+ pci_pcie_cap(tp->pdev) + PCI_EXP_LNKCTL,
newlnkctl);
}
@@ -5821,8 +5857,7 @@
/* Make sure new skb does not cross any 4G boundaries.
* Drop the packet if it does.
*/
- } else if (tg3_flag(tp, 4G_DMA_BNDRY_BUG) &&
- tg3_4g_overflow_test(new_addr, new_skb->len)) {
+ } else if (tg3_4g_overflow_test(new_addr, new_skb->len)) {
pci_unmap_single(tp->pdev, new_addr, new_skb->len,
PCI_DMA_TODEVICE);
ret = -1;
@@ -6017,12 +6052,10 @@
if (tg3_flag(tp, SHORT_DMA_BUG) && len <= 8)
would_hit_hwbug = 1;
- if (tg3_flag(tp, 4G_DMA_BNDRY_BUG) &&
- tg3_4g_overflow_test(mapping, len))
+ if (tg3_4g_overflow_test(mapping, len))
would_hit_hwbug = 1;
- if (tg3_flag(tp, 40BIT_DMA_LIMIT_BUG) &&
- tg3_40bit_overflow_test(tp, mapping, len))
+ if (tg3_40bit_overflow_test(tp, mapping, len))
would_hit_hwbug = 1;
if (tg3_flag(tp, 5701_DMA_BUG))
@@ -6055,12 +6088,10 @@
len <= 8)
would_hit_hwbug = 1;
- if (tg3_flag(tp, 4G_DMA_BNDRY_BUG) &&
- tg3_4g_overflow_test(mapping, len))
+ if (tg3_4g_overflow_test(mapping, len))
would_hit_hwbug = 1;
- if (tg3_flag(tp, 40BIT_DMA_LIMIT_BUG) &&
- tg3_40bit_overflow_test(tp, mapping, len))
+ if (tg3_40bit_overflow_test(tp, mapping, len))
would_hit_hwbug = 1;
if (tg3_flag(tp, HW_TSO_1) ||
@@ -6088,6 +6119,8 @@
entry = NEXT_TX(tnapi->tx_prod);
}
+ skb_tx_timestamp(skb);
+
/* Packets are ready, update Tx producer idx local and on card. */
tw32_tx_mbox(tnapi->prodmbox, entry);
@@ -7193,7 +7226,7 @@
udelay(120);
- if (tg3_flag(tp, PCI_EXPRESS) && tp->pcie_cap) {
+ if (tg3_flag(tp, PCI_EXPRESS) && pci_pcie_cap(tp->pdev)) {
u16 val16;
if (tp->pci_chip_rev_id == CHIPREV_ID_5750_A0) {
@@ -7211,7 +7244,7 @@
/* Clear the "no snoop" and "relaxed ordering" bits. */
pci_read_config_word(tp->pdev,
- tp->pcie_cap + PCI_EXP_DEVCTL,
+ pci_pcie_cap(tp->pdev) + PCI_EXP_DEVCTL,
&val16);
val16 &= ~(PCI_EXP_DEVCTL_RELAX_EN |
PCI_EXP_DEVCTL_NOSNOOP_EN);
@@ -7222,14 +7255,14 @@
if (!tg3_flag(tp, CPMU_PRESENT))
val16 &= ~PCI_EXP_DEVCTL_PAYLOAD;
pci_write_config_word(tp->pdev,
- tp->pcie_cap + PCI_EXP_DEVCTL,
+ pci_pcie_cap(tp->pdev) + PCI_EXP_DEVCTL,
val16);
pcie_set_readrq(tp->pdev, tp->pcie_readrq);
/* Clear error status */
pci_write_config_word(tp->pdev,
- tp->pcie_cap + PCI_EXP_DEVSTA,
+ pci_pcie_cap(tp->pdev) + PCI_EXP_DEVSTA,
PCI_EXP_DEVSTA_CED |
PCI_EXP_DEVSTA_NFED |
PCI_EXP_DEVSTA_FED |
@@ -7751,6 +7784,9 @@
/* Disable interrupts */
tw32_mailbox_f(tp->napi[0].int_mbox, 1);
+ tp->napi[0].chk_msi_cnt = 0;
+ tp->napi[0].last_rx_cons = 0;
+ tp->napi[0].last_tx_cons = 0;
/* Zero mailbox registers. */
if (tg3_flag(tp, SUPPORT_MSIX)) {
@@ -7761,6 +7797,9 @@
tw32_mailbox(tp->napi[i].prodmbox, 0);
tw32_rx_mbox(tp->napi[i].consmbox, 0);
tw32_mailbox_f(tp->napi[i].int_mbox, 1);
+ tp->napi[0].chk_msi_cnt = 0;
+ tp->napi[i].last_rx_cons = 0;
+ tp->napi[i].last_tx_cons = 0;
}
if (!tg3_flag(tp, ENABLE_TSS))
tw32_mailbox(tp->napi[0].prodmbox, 0);
@@ -8816,6 +8855,30 @@
TG3_STAT_ADD32(&sp->rx_errors, RCVLPC_IN_ERRORS_CNT);
}
+static void tg3_chk_missed_msi(struct tg3 *tp)
+{
+ u32 i;
+
+ for (i = 0; i < tp->irq_cnt; i++) {
+ struct tg3_napi *tnapi = &tp->napi[i];
+
+ if (tg3_has_work(tnapi)) {
+ if (tnapi->last_rx_cons == tnapi->rx_rcb_ptr &&
+ tnapi->last_tx_cons == tnapi->tx_cons) {
+ if (tnapi->chk_msi_cnt < 1) {
+ tnapi->chk_msi_cnt++;
+ return;
+ }
+ tw32_mailbox(tnapi->int_mbox,
+ tnapi->last_tag << 24);
+ }
+ }
+ tnapi->chk_msi_cnt = 0;
+ tnapi->last_rx_cons = tnapi->rx_rcb_ptr;
+ tnapi->last_tx_cons = tnapi->tx_cons;
+ }
+}
+
static void tg3_timer(unsigned long __opaque)
{
struct tg3 *tp = (struct tg3 *) __opaque;
@@ -8825,6 +8888,10 @@
spin_lock(&tp->lock);
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765)
+ tg3_chk_missed_msi(tp);
+
if (!tg3_flag(tp, TAGGED_STATUS)) {
/* All of this garbage is because when using non-tagged
* IRQ status the mailbox/status_block protocol the chip
@@ -9300,7 +9367,9 @@
tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
tg3_free_rings(tp);
} else {
- if (tg3_flag(tp, TAGGED_STATUS))
+ if (tg3_flag(tp, TAGGED_STATUS) &&
+ GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5717 &&
+ GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_57765)
tp->timer_offset = HZ;
else
tp->timer_offset = HZ / 10;
@@ -9902,6 +9971,18 @@
}
cmd->advertising = tp->link_config.advertising;
+ if (tg3_flag(tp, PAUSE_AUTONEG)) {
+ if (tp->link_config.flowctrl & FLOW_CTRL_RX) {
+ if (tp->link_config.flowctrl & FLOW_CTRL_TX) {
+ cmd->advertising |= ADVERTISED_Pause;
+ } else {
+ cmd->advertising |= ADVERTISED_Pause |
+ ADVERTISED_Asym_Pause;
+ }
+ } else if (tp->link_config.flowctrl & FLOW_CTRL_TX) {
+ cmd->advertising |= ADVERTISED_Asym_Pause;
+ }
+ }
if (netif_running(dev)) {
ethtool_cmd_speed_set(cmd, tp->link_config.active_speed);
cmd->duplex = tp->link_config.active_duplex;
@@ -10436,6 +10517,9 @@
#define NVRAM_SELFBOOT_FORMAT1_0_SIZE 0x14
#define NVRAM_SELFBOOT_FORMAT1_2_SIZE 0x18
#define NVRAM_SELFBOOT_FORMAT1_3_SIZE 0x1c
+#define NVRAM_SELFBOOT_FORMAT1_4_SIZE 0x20
+#define NVRAM_SELFBOOT_FORMAT1_5_SIZE 0x24
+#define NVRAM_SELFBOOT_FORMAT1_6_SIZE 0x4c
#define NVRAM_SELFBOOT_HW_SIZE 0x20
#define NVRAM_SELFBOOT_DATA_SIZE 0x1c
@@ -10466,8 +10550,17 @@
case TG3_EEPROM_SB_REVISION_3:
size = NVRAM_SELFBOOT_FORMAT1_3_SIZE;
break;
+ case TG3_EEPROM_SB_REVISION_4:
+ size = NVRAM_SELFBOOT_FORMAT1_4_SIZE;
+ break;
+ case TG3_EEPROM_SB_REVISION_5:
+ size = NVRAM_SELFBOOT_FORMAT1_5_SIZE;
+ break;
+ case TG3_EEPROM_SB_REVISION_6:
+ size = NVRAM_SELFBOOT_FORMAT1_6_SIZE;
+ break;
default:
- return 0;
+ return -EIO;
}
} else
return 0;
@@ -13666,15 +13759,8 @@
}
}
- /* All chips can get confused if TX buffers
- * straddle the 4GB address boundary.
- */
- tg3_flag_set(tp, 4G_DMA_BNDRY_BUG);
-
if (tg3_flag(tp, 5755_PLUS))
tg3_flag_set(tp, SHORT_DMA_BUG);
- else
- tg3_flag_set(tp, 40BIT_DMA_LIMIT_BUG);
if (tg3_flag(tp, 5717_PLUS))
tg3_flag_set(tp, LRG_PROD_RING_CAP);
@@ -13691,8 +13777,7 @@
pci_read_config_dword(tp->pdev, TG3PCI_PCISTATE,
&pci_state_reg);
- tp->pcie_cap = pci_find_capability(tp->pdev, PCI_CAP_ID_EXP);
- if (tp->pcie_cap != 0) {
+ if (pci_is_pcie(tp->pdev)) {
u16 lnkctl;
tg3_flag_set(tp, PCI_EXPRESS);
@@ -13705,7 +13790,7 @@
pcie_set_readrq(tp->pdev, tp->pcie_readrq);
pci_read_config_word(tp->pdev,
- tp->pcie_cap + PCI_EXP_LNKCTL,
+ pci_pcie_cap(tp->pdev) + PCI_EXP_LNKCTL,
&lnkctl);
if (lnkctl & PCI_EXP_LNKCTL_CLKREQ_EN) {
if (GET_ASIC_REV(tp->pci_chip_rev_id) ==
@@ -13722,6 +13807,10 @@
tg3_flag_set(tp, L1PLLPD_EN);
}
} else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785) {
+ /* BCM5785 devices are effectively PCIe devices, and should
+ * follow PCIe codepaths, but do not have a PCIe capabilities
+ * section.
+ */
tg3_flag_set(tp, PCI_EXPRESS);
} else if (!tg3_flag(tp, 5705_PLUS) ||
tg3_flag(tp, 5780_CLASS)) {
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h
index 5b3d2f3..5f250ae 100644
--- a/drivers/net/tg3.h
+++ b/drivers/net/tg3.h
@@ -1118,10 +1118,10 @@
#define TG3_CPMU_EEEMD_EEE_ENABLE 0x00100000
#define TG3_CPMU_EEE_DBTMR1 0x000036b4
#define TG3_CPMU_DBTMR1_PCIEXIT_2047US 0x07ff0000
-#define TG3_CPMU_DBTMR1_LNKIDLE_2047US 0x000070ff
+#define TG3_CPMU_DBTMR1_LNKIDLE_2047US 0x000007ff
#define TG3_CPMU_EEE_DBTMR2 0x000036b8
#define TG3_CPMU_DBTMR2_APE_TX_2047US 0x07ff0000
-#define TG3_CPMU_DBTMR2_TXIDXEQ_2047US 0x000070ff
+#define TG3_CPMU_DBTMR2_TXIDXEQ_2047US 0x000007ff
#define TG3_CPMU_EEE_LNKIDL_CTRL 0x000036bc
#define TG3_CPMU_EEE_LNKIDL_PCIE_NL0 0x01000000
#define TG3_CPMU_EEE_LNKIDL_UART_IDL 0x00000004
@@ -2152,14 +2152,6 @@
/*** Tigon3 specific PHY MII registers. ***/
-#define TG3_BMCR_SPEED1000 0x0040
-
-#define MII_TG3_CTRL 0x09 /* 1000-baseT control register */
-#define MII_TG3_CTRL_ADV_1000_HALF 0x0100
-#define MII_TG3_CTRL_ADV_1000_FULL 0x0200
-#define MII_TG3_CTRL_AS_MASTER 0x0800
-#define MII_TG3_CTRL_ENABLE_AS_MASTER 0x1000
-
#define MII_TG3_MMD_CTRL 0x0d /* MMD Access Control register */
#define MII_TG3_MMD_CTRL_DATA_NOINC 0x4000
#define MII_TG3_MMD_ADDRESS 0x0e /* MMD Address Data register */
@@ -2800,6 +2792,7 @@
struct tg3 *tp;
struct tg3_hw_status *hw_status;
+ u32 chk_msi_cnt;
u32 last_tag;
u32 last_irq_tag;
u32 int_mbox;
@@ -2807,6 +2800,7 @@
u32 consmbox ____cacheline_aligned;
u32 rx_rcb_ptr;
+ u32 last_rx_cons;
u16 *rx_rcb_prod_idx;
struct tg3_rx_prodring_set prodring;
struct tg3_rx_buffer_desc *rx_rcb;
@@ -2814,6 +2808,7 @@
u32 tx_prod ____cacheline_aligned;
u32 tx_cons;
u32 tx_pending;
+ u32 last_tx_cons;
u32 prodmbox;
struct tg3_tx_buffer_desc *tx_ring;
struct ring_info *tx_buffers;
@@ -2862,7 +2857,7 @@
TG3_FLAG_IS_5788,
TG3_FLAG_MAX_RXPEND_64,
TG3_FLAG_TSO_CAPABLE,
- TG3_FLAG_PCI_EXPRESS,
+ TG3_FLAG_PCI_EXPRESS, /* BCM5785 + pci_is_pcie() */
TG3_FLAG_ASF_NEW_HANDSHAKE,
TG3_FLAG_HW_AUTONEG,
TG3_FLAG_IS_NIC,
@@ -2893,8 +2888,6 @@
TG3_FLAG_NO_NVRAM,
TG3_FLAG_ENABLE_RSS,
TG3_FLAG_ENABLE_TSS,
- TG3_FLAG_4G_DMA_BNDRY_BUG,
- TG3_FLAG_40BIT_DMA_LIMIT_BUG,
TG3_FLAG_SHORT_DMA_BUG,
TG3_FLAG_USE_JUMBO_BDFLAG,
TG3_FLAG_L1PLLPD_EN,
@@ -3029,10 +3022,7 @@
int pm_cap;
int msi_cap;
- union {
int pcix_cap;
- int pcie_cap;
- };
int pcie_readrq;
struct mii_bus *mdio_bus;
diff --git a/drivers/net/tlan.c b/drivers/net/tlan.c
index ace6404..145871b 100644
--- a/drivers/net/tlan.c
+++ b/drivers/net/tlan.c
@@ -29,8 +29,10 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#include <linux/hardirq.h>
#include <linux/module.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/eisa.h>
#include <linux/pci.h>
diff --git a/drivers/net/tokenring/3c359.c b/drivers/net/tokenring/3c359.c
index ff32bef..b6162fe 100644
--- a/drivers/net/tokenring/3c359.c
+++ b/drivers/net/tokenring/3c359.c
@@ -304,7 +304,7 @@
if ((i = pci_request_regions(pdev,"3c359"))) {
return i ;
- } ;
+ }
/*
* Allowing init_trdev to allocate the private data will align
@@ -1773,7 +1773,9 @@
if (readb(xl_mmio + MMIO_MACDATA) != 0) { /* Misr not clear */
for (i=0; i<6; i++) {
writel(MEM_BYTE_READ | 0xDFFE0 | i, xl_mmio + MMIO_MAC_ACCESS_CMD) ;
- while (readb(xl_mmio + MMIO_MACDATA) != 0 ) {} ; /* Empty Loop */
+ while (readb(xl_mmio + MMIO_MACDATA) != 0) {
+ ; /* Empty Loop */
+ }
}
}
diff --git a/drivers/net/tokenring/ibmtr.c b/drivers/net/tokenring/ibmtr.c
index 4786497..e257a00 100644
--- a/drivers/net/tokenring/ibmtr.c
+++ b/drivers/net/tokenring/ibmtr.c
@@ -123,6 +123,7 @@
/* some 95 OS send many non UI frame; this allow removing the warning */
#define TR_FILTERNONUI 1
+#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/netdevice.h>
#include <linux/ip.h>
@@ -177,7 +178,7 @@
case 0xD: return "16/4 Adapter/A (short) | 16/4 ISA-16 Adapter";
case 0xC: return "Auto 16/4 Adapter";
default: return "adapter (unknown type)";
- };
+ }
};
#define TRC_INIT 0x01 /* Trace initialization & PROBEs */
diff --git a/drivers/net/tokenring/madgemc.c b/drivers/net/tokenring/madgemc.c
index 2bedc0a..6153cfd 100644
--- a/drivers/net/tokenring/madgemc.c
+++ b/drivers/net/tokenring/madgemc.c
@@ -418,7 +418,7 @@
return IRQ_NONE;
}
- dev = (struct net_device *)dev_id;
+ dev = dev_id;
/* Make sure its really us. -- the Madge way */
pending = inb(dev->base_addr + MC_CONTROL_REG0);
diff --git a/drivers/net/tsi108_eth.c b/drivers/net/tsi108_eth.c
index 5c633a32..64cb9ac 100644
--- a/drivers/net/tsi108_eth.c
+++ b/drivers/net/tsi108_eth.c
@@ -33,6 +33,7 @@
#include <linux/module.h>
#include <linux/types.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/net.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
diff --git a/drivers/net/tulip/de2104x.c b/drivers/net/tulip/de2104x.c
index e2f6923..ce90efc 100644
--- a/drivers/net/tulip/de2104x.c
+++ b/drivers/net/tulip/de2104x.c
@@ -38,6 +38,7 @@
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/pci.h>
#include <linux/delay.h>
#include <linux/ethtool.h>
diff --git a/drivers/net/tulip/de4x5.c b/drivers/net/tulip/de4x5.c
index efaa1d6..959b410 100644
--- a/drivers/net/tulip/de4x5.c
+++ b/drivers/net/tulip/de4x5.c
@@ -1868,14 +1868,13 @@
i = DE4X5_PKT_STAT_SZ;
}
}
- if (buf[0] & 0x01) { /* Multicast/Broadcast */
- if ((*(s32 *)&buf[0] == -1) && (*(s16 *)&buf[4] == -1)) {
+ if (is_multicast_ether_addr(buf)) {
+ if (is_broadcast_ether_addr(buf)) {
lp->pktStats.broadcast++;
} else {
lp->pktStats.multicast++;
}
- } else if ((*(s32 *)&buf[0] == *(s32 *)&dev->dev_addr[0]) &&
- (*(s16 *)&buf[4] == *(s16 *)&dev->dev_addr[4])) {
+ } else if (compare_ether_addr(buf, dev->dev_addr) == 0) {
lp->pktStats.unicast++;
}
@@ -1964,9 +1963,7 @@
omr |= OMR_PM; /* Pass all multicasts */
} else if (lp->setup_f == HASH_PERF) { /* Hash Filtering */
netdev_for_each_mc_addr(ha, dev) {
- addrs = ha->addr;
- if ((*addrs & 0x01) == 1) { /* multicast address? */
- crc = ether_crc_le(ETH_ALEN, addrs);
+ crc = ether_crc_le(ETH_ALEN, ha->addr);
hashcode = crc & HASH_BITS; /* hashcode is 9 LSb of CRC */
byte = hashcode >> 3; /* bit[3-8] -> byte in filter */
@@ -1977,7 +1974,6 @@
byte -= 1;
}
lp->setup_frame[byte] |= bit;
- }
}
} else { /* Perfect filtering */
netdev_for_each_mc_addr(ha, dev) {
diff --git a/drivers/net/tulip/pnic.c b/drivers/net/tulip/pnic.c
index aa4d9da..52d898b 100644
--- a/drivers/net/tulip/pnic.c
+++ b/drivers/net/tulip/pnic.c
@@ -13,6 +13,7 @@
Please submit bugs to http://bugzilla.kernel.org/ .
*/
+#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/jiffies.h>
#include "tulip.h"
diff --git a/drivers/net/tulip/tulip_core.c b/drivers/net/tulip/tulip_core.c
index 82f8764..1246998 100644
--- a/drivers/net/tulip/tulip_core.c
+++ b/drivers/net/tulip/tulip_core.c
@@ -28,6 +28,7 @@
#include <linux/slab.h>
#include "tulip.h"
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/etherdevice.h>
#include <linux/delay.h>
#include <linux/mii.h>
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 5235f48..9a6b382 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -572,9 +572,9 @@
/* prepad is the amount to reserve at front. len is length after that.
* linear is a hint as to how much to copy (usually headers). */
-static inline struct sk_buff *tun_alloc_skb(struct tun_struct *tun,
- size_t prepad, size_t len,
- size_t linear, int noblock)
+static struct sk_buff *tun_alloc_skb(struct tun_struct *tun,
+ size_t prepad, size_t len,
+ size_t linear, int noblock)
{
struct sock *sk = tun->socket.sk;
struct sk_buff *skb;
@@ -600,13 +600,13 @@
}
/* Get packet from user space buffer */
-static __inline__ ssize_t tun_get_user(struct tun_struct *tun,
- const struct iovec *iv, size_t count,
- int noblock)
+static ssize_t tun_get_user(struct tun_struct *tun,
+ const struct iovec *iv, size_t count,
+ int noblock)
{
struct tun_pi pi = { 0, cpu_to_be16(ETH_P_IP) };
struct sk_buff *skb;
- size_t len = count, align = 0;
+ size_t len = count, align = NET_SKB_PAD;
struct virtio_net_hdr gso = { 0 };
int offset = 0;
@@ -636,7 +636,7 @@
}
if ((tun->flags & TUN_TYPE_MASK) == TUN_TAP_DEV) {
- align = NET_IP_ALIGN;
+ align += NET_IP_ALIGN;
if (unlikely(len < ETH_HLEN ||
(gso.hdr_len && gso.hdr_len < ETH_HLEN)))
return -EINVAL;
@@ -688,7 +688,7 @@
case TUN_TAP_DEV:
skb->protocol = eth_type_trans(skb, tun->dev);
break;
- };
+ }
if (gso.gso_type != VIRTIO_NET_HDR_GSO_NONE) {
pr_debug("GSO!\n");
@@ -751,9 +751,9 @@
}
/* Put packet to the user space buffer */
-static __inline__ ssize_t tun_put_user(struct tun_struct *tun,
- struct sk_buff *skb,
- const struct iovec *iv, int len)
+static ssize_t tun_put_user(struct tun_struct *tun,
+ struct sk_buff *skb,
+ const struct iovec *iv, int len)
{
struct tun_pi pi = { 0, skb->protocol };
ssize_t total = 0;
@@ -810,6 +810,8 @@
gso.flags = VIRTIO_NET_HDR_F_NEEDS_CSUM;
gso.csum_start = skb_checksum_start_offset(skb);
gso.csum_offset = skb->csum_offset;
+ } else if (skb->ip_summed == CHECKSUM_UNNECESSARY) {
+ gso.flags = VIRTIO_NET_HDR_F_DATA_VALID;
} /* else everything is zero */
if (unlikely(memcpy_toiovecend(iv, (void *)&gso, total,
@@ -839,7 +841,8 @@
tun_debug(KERN_INFO, tun, "tun_chr_read\n");
- add_wait_queue(&tun->wq.wait, &wait);
+ if (unlikely(!noblock))
+ add_wait_queue(&tun->wq.wait, &wait);
while (len) {
current->state = TASK_INTERRUPTIBLE;
@@ -870,7 +873,8 @@
}
current->state = TASK_RUNNING;
- remove_wait_queue(&tun->wq.wait, &wait);
+ if (unlikely(!noblock))
+ remove_wait_queue(&tun->wq.wait, &wait);
return ret;
}
diff --git a/drivers/net/typhoon.c b/drivers/net/typhoon.c
index 3de4283..1d5091a 100644
--- a/drivers/net/typhoon.c
+++ b/drivers/net/typhoon.c
@@ -2367,7 +2367,7 @@
dev->irq = pdev->irq;
tp = netdev_priv(dev);
- tp->shared = (struct typhoon_shared *) shared;
+ tp->shared = shared;
tp->shared_dma = shared_dma;
tp->pdev = pdev;
tp->tx_pdev = pdev;
diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c
index ef04105..d3465ab 100644
--- a/drivers/net/ucc_geth.c
+++ b/drivers/net/ucc_geth.c
@@ -2030,11 +2030,6 @@
out_be32(&p_82xx_addr_filt->gaddr_l, 0x0);
netdev_for_each_mc_addr(ha, dev) {
- /* Only support group multicast for now.
- */
- if (!is_multicast_ether_addr(ha->addr))
- continue;
-
/* Ask CPM to run CRC and set bit in
* filter mask.
*/
@@ -3165,6 +3160,8 @@
ugeth->txBd[txQ] = bd;
+ skb_tx_timestamp(skb);
+
if (ugeth->p_scheduler) {
ugeth->cpucount[txQ]++;
/* Indicate to QE that there are more Tx bds ready for
diff --git a/drivers/net/usb/cdc-phonet.c b/drivers/net/usb/cdc-phonet.c
index f967913..a60d006 100644
--- a/drivers/net/usb/cdc-phonet.c
+++ b/drivers/net/usb/cdc-phonet.c
@@ -21,6 +21,7 @@
*/
#include <linux/kernel.h>
+#include <linux/mm.h>
#include <linux/module.h>
#include <linux/gfp.h>
#include <linux/usb.h>
diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c
index f33ca6a..fd622a6 100644
--- a/drivers/net/usb/cdc_ncm.c
+++ b/drivers/net/usb/cdc_ncm.c
@@ -47,7 +47,6 @@
#include <linux/mii.h>
#include <linux/crc32.h>
#include <linux/usb.h>
-#include <linux/version.h>
#include <linux/timer.h>
#include <linux/spinlock.h>
#include <linux/atomic.h>
diff --git a/drivers/net/usb/ipheth.c b/drivers/net/usb/ipheth.c
index 81126ff..15772b1 100644
--- a/drivers/net/usb/ipheth.c
+++ b/drivers/net/usb/ipheth.c
@@ -409,12 +409,6 @@
usb_unlink_urb(dev->tx_urb);
}
-static struct net_device_stats *ipheth_stats(struct net_device *net)
-{
- struct ipheth_device *dev = netdev_priv(net);
- return &dev->net->stats;
-}
-
static u32 ipheth_ethtool_op_get_link(struct net_device *net)
{
struct ipheth_device *dev = netdev_priv(net);
@@ -426,11 +420,10 @@
};
static const struct net_device_ops ipheth_netdev_ops = {
- .ndo_open = &ipheth_open,
- .ndo_stop = &ipheth_close,
- .ndo_start_xmit = &ipheth_tx,
- .ndo_tx_timeout = &ipheth_tx_timeout,
- .ndo_get_stats = &ipheth_stats,
+ .ndo_open = ipheth_open,
+ .ndo_stop = ipheth_close,
+ .ndo_start_xmit = ipheth_tx,
+ .ndo_tx_timeout = ipheth_tx_timeout,
};
static int ipheth_probe(struct usb_interface *intf,
diff --git a/drivers/net/veth.c b/drivers/net/veth.c
index 8461576..9eb92bf 100644
--- a/drivers/net/veth.c
+++ b/drivers/net/veth.c
@@ -12,6 +12,7 @@
#include <linux/slab.h>
#include <linux/ethtool.h>
#include <linux/etherdevice.h>
+#include <linux/u64_stats_sync.h>
#include <net/dst.h>
#include <net/xfrm.h>
@@ -24,12 +25,13 @@
#define MAX_MTU 65535 /* Max L3 MTU (arbitrary) */
struct veth_net_stats {
- unsigned long rx_packets;
- unsigned long tx_packets;
- unsigned long rx_bytes;
- unsigned long tx_bytes;
- unsigned long tx_dropped;
- unsigned long rx_dropped;
+ u64 rx_packets;
+ u64 tx_packets;
+ u64 rx_bytes;
+ u64 tx_bytes;
+ u64 rx_dropped;
+ u64 tx_dropped;
+ struct u64_stats_sync syncp;
};
struct veth_priv {
@@ -124,9 +126,6 @@
stats = this_cpu_ptr(priv->stats);
rcv_stats = this_cpu_ptr(rcv_priv->stats);
- if (!(rcv->flags & IFF_UP))
- goto tx_drop;
-
/* don't change ip_summed == CHECKSUM_PARTIAL, as that
will cause bad checksum on forwarded packets */
if (skb->ip_summed == CHECKSUM_NONE &&
@@ -137,21 +136,29 @@
if (dev_forward_skb(rcv, skb) != NET_RX_SUCCESS)
goto rx_drop;
+ u64_stats_update_begin(&stats->syncp);
stats->tx_bytes += length;
stats->tx_packets++;
+ u64_stats_update_end(&stats->syncp);
+ u64_stats_update_begin(&rcv_stats->syncp);
rcv_stats->rx_bytes += length;
rcv_stats->rx_packets++;
+ u64_stats_update_end(&rcv_stats->syncp);
return NETDEV_TX_OK;
tx_drop:
kfree_skb(skb);
+ u64_stats_update_begin(&stats->syncp);
stats->tx_dropped++;
+ u64_stats_update_end(&stats->syncp);
return NETDEV_TX_OK;
rx_drop:
+ u64_stats_update_begin(&rcv_stats->syncp);
rcv_stats->rx_dropped++;
+ u64_stats_update_end(&rcv_stats->syncp);
return NETDEV_TX_OK;
}
@@ -159,32 +166,36 @@
* general routines
*/
-static struct net_device_stats *veth_get_stats(struct net_device *dev)
+static struct rtnl_link_stats64 *veth_get_stats64(struct net_device *dev,
+ struct rtnl_link_stats64 *tot)
{
- struct veth_priv *priv;
+ struct veth_priv *priv = netdev_priv(dev);
int cpu;
- struct veth_net_stats *stats, total = {0};
-
- priv = netdev_priv(dev);
for_each_possible_cpu(cpu) {
- stats = per_cpu_ptr(priv->stats, cpu);
+ struct veth_net_stats *stats = per_cpu_ptr(priv->stats, cpu);
+ u64 rx_packets, rx_bytes, rx_dropped;
+ u64 tx_packets, tx_bytes, tx_dropped;
+ unsigned int start;
- total.rx_packets += stats->rx_packets;
- total.tx_packets += stats->tx_packets;
- total.rx_bytes += stats->rx_bytes;
- total.tx_bytes += stats->tx_bytes;
- total.tx_dropped += stats->tx_dropped;
- total.rx_dropped += stats->rx_dropped;
+ do {
+ start = u64_stats_fetch_begin_bh(&stats->syncp);
+ rx_packets = stats->rx_packets;
+ tx_packets = stats->tx_packets;
+ rx_bytes = stats->rx_bytes;
+ tx_bytes = stats->tx_bytes;
+ rx_dropped = stats->rx_dropped;
+ tx_dropped = stats->tx_dropped;
+ } while (u64_stats_fetch_retry_bh(&stats->syncp, start));
+ tot->rx_packets += rx_packets;
+ tot->tx_packets += tx_packets;
+ tot->rx_bytes += rx_bytes;
+ tot->tx_bytes += tx_bytes;
+ tot->rx_dropped += rx_dropped;
+ tot->tx_dropped += tx_dropped;
}
- dev->stats.rx_packets = total.rx_packets;
- dev->stats.tx_packets = total.tx_packets;
- dev->stats.rx_bytes = total.rx_bytes;
- dev->stats.tx_bytes = total.tx_bytes;
- dev->stats.tx_dropped = total.tx_dropped;
- dev->stats.rx_dropped = total.rx_dropped;
- return &dev->stats;
+ return tot;
}
static int veth_open(struct net_device *dev)
@@ -254,7 +265,7 @@
.ndo_stop = veth_close,
.ndo_start_xmit = veth_xmit,
.ndo_change_mtu = veth_change_mtu,
- .ndo_get_stats = veth_get_stats,
+ .ndo_get_stats64 = veth_get_stats64,
.ndo_set_mac_address = eth_mac_addr,
};
diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c
index 06daa9d..f929242 100644
--- a/drivers/net/via-velocity.c
+++ b/drivers/net/via-velocity.c
@@ -1887,7 +1887,7 @@
else
netif_wake_queue(vptr->dev);
- };
+ }
if (status & ISR_MIBFI)
velocity_update_hw_mibs(vptr);
if (status & ISR_LSTEI)
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index f685324..fbea637 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -40,6 +40,15 @@
#define VIRTNET_SEND_COMMAND_SG_MAX 2
+struct virtnet_stats {
+ struct u64_stats_sync syncp;
+ u64 tx_bytes;
+ u64 tx_packets;
+
+ u64 rx_bytes;
+ u64 rx_packets;
+};
+
struct virtnet_info {
struct virtio_device *vdev;
struct virtqueue *rvq, *svq, *cvq;
@@ -56,6 +65,9 @@
/* Host will merge rx buffers for big packets (shake it! shake it!) */
bool mergeable_rx_bufs;
+ /* Active statistics */
+ struct virtnet_stats __percpu *stats;
+
/* Work struct for refilling if we run low on memory. */
struct delayed_work refill;
@@ -209,7 +221,6 @@
skb->dev->stats.rx_length_errors++;
return -EINVAL;
}
-
page = virtqueue_get_buf(vi->rvq, &len);
if (!page) {
pr_debug("%s: rx error: %d buffers missing\n",
@@ -217,6 +228,7 @@
skb->dev->stats.rx_length_errors++;
return -EINVAL;
}
+
if (len > PAGE_SIZE)
len = PAGE_SIZE;
@@ -230,6 +242,7 @@
static void receive_buf(struct net_device *dev, void *buf, unsigned int len)
{
struct virtnet_info *vi = netdev_priv(dev);
+ struct virtnet_stats __percpu *stats = this_cpu_ptr(vi->stats);
struct sk_buff *skb;
struct page *page;
struct skb_vnet_hdr *hdr;
@@ -265,8 +278,11 @@
hdr = skb_vnet_hdr(skb);
skb->truesize += skb->data_len;
- dev->stats.rx_bytes += skb->len;
- dev->stats.rx_packets++;
+
+ u64_stats_update_begin(&stats->syncp);
+ stats->rx_bytes += skb->len;
+ stats->rx_packets++;
+ u64_stats_update_end(&stats->syncp);
if (hdr->hdr.flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) {
pr_debug("Needs csum!\n");
@@ -274,6 +290,8 @@
hdr->hdr.csum_start,
hdr->hdr.csum_offset))
goto frame_err;
+ } else if (hdr->hdr.flags & VIRTIO_NET_HDR_F_DATA_VALID) {
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
}
skb->protocol = eth_type_trans(skb, dev);
@@ -513,11 +531,16 @@
{
struct sk_buff *skb;
unsigned int len, tot_sgs = 0;
+ struct virtnet_stats __percpu *stats = this_cpu_ptr(vi->stats);
while ((skb = virtqueue_get_buf(vi->svq, &len)) != NULL) {
pr_debug("Sent skb %p\n", skb);
- vi->dev->stats.tx_bytes += skb->len;
- vi->dev->stats.tx_packets++;
+
+ u64_stats_update_begin(&stats->syncp);
+ stats->tx_bytes += skb->len;
+ stats->tx_packets++;
+ u64_stats_update_end(&stats->syncp);
+
tot_sgs += skb_vnet_hdr(skb)->num_sg;
dev_kfree_skb_any(skb);
}
@@ -639,6 +662,40 @@
return 0;
}
+static struct rtnl_link_stats64 *virtnet_stats(struct net_device *dev,
+ struct rtnl_link_stats64 *tot)
+{
+ struct virtnet_info *vi = netdev_priv(dev);
+ int cpu;
+ unsigned int start;
+
+ for_each_possible_cpu(cpu) {
+ struct virtnet_stats __percpu *stats
+ = per_cpu_ptr(vi->stats, cpu);
+ u64 tpackets, tbytes, rpackets, rbytes;
+
+ do {
+ start = u64_stats_fetch_begin(&stats->syncp);
+ tpackets = stats->tx_packets;
+ tbytes = stats->tx_bytes;
+ rpackets = stats->rx_packets;
+ rbytes = stats->rx_bytes;
+ } while (u64_stats_fetch_retry(&stats->syncp, start));
+
+ tot->rx_packets += rpackets;
+ tot->tx_packets += tpackets;
+ tot->rx_bytes += rbytes;
+ tot->tx_bytes += tbytes;
+ }
+
+ tot->tx_dropped = dev->stats.tx_dropped;
+ tot->rx_dropped = dev->stats.rx_dropped;
+ tot->rx_length_errors = dev->stats.rx_length_errors;
+ tot->rx_frame_errors = dev->stats.rx_frame_errors;
+
+ return tot;
+}
+
#ifdef CONFIG_NET_POLL_CONTROLLER
static void virtnet_netpoll(struct net_device *dev)
{
@@ -648,6 +705,14 @@
}
#endif
+static void virtnet_free(struct net_device *dev)
+{
+ struct virtnet_info *vi = netdev_priv(dev);
+
+ free_percpu(vi->stats);
+ free_netdev(dev);
+}
+
static int virtnet_open(struct net_device *dev)
{
struct virtnet_info *vi = netdev_priv(dev);
@@ -833,6 +898,7 @@
.ndo_set_mac_address = virtnet_set_mac_address,
.ndo_set_rx_mode = virtnet_set_rx_mode,
.ndo_change_mtu = virtnet_change_mtu,
+ .ndo_get_stats64 = virtnet_stats,
.ndo_vlan_rx_add_vid = virtnet_vlan_rx_add_vid,
.ndo_vlan_rx_kill_vid = virtnet_vlan_rx_kill_vid,
#ifdef CONFIG_NET_POLL_CONTROLLER
@@ -893,6 +959,8 @@
/* Set up network device as normal. */
dev->netdev_ops = &virtnet_netdev;
dev->features = NETIF_F_HIGHDMA;
+ dev->destructor = virtnet_free;
+
SET_ETHTOOL_OPS(dev, &virtnet_ethtool_ops);
SET_NETDEV_DEV(dev, &vdev->dev);
@@ -937,6 +1005,11 @@
vi->vdev = vdev;
vdev->priv = vi;
vi->pages = NULL;
+ vi->stats = alloc_percpu(struct virtnet_stats);
+ err = -ENOMEM;
+ if (vi->stats == NULL)
+ goto free;
+
INIT_DELAYED_WORK(&vi->refill, refill_work);
sg_init_table(vi->rx_sg, ARRAY_SIZE(vi->rx_sg));
sg_init_table(vi->tx_sg, ARRAY_SIZE(vi->tx_sg));
@@ -956,7 +1029,7 @@
err = vdev->config->find_vqs(vdev, nvqs, vqs, callbacks, names);
if (err)
- goto free;
+ goto free_stats;
vi->rvq = vqs[0];
vi->svq = vqs[1];
@@ -1001,6 +1074,8 @@
cancel_delayed_work_sync(&vi->refill);
free_vqs:
vdev->config->del_vqs(vdev);
+free_stats:
+ free_percpu(vi->stats);
free:
free_netdev(dev);
return err;
diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c
index 45a23b2..fabcded 100644
--- a/drivers/net/vmxnet3/vmxnet3_drv.c
+++ b/drivers/net/vmxnet3/vmxnet3_drv.c
@@ -405,10 +405,8 @@
while (tq->tx_ring.next2comp != tq->tx_ring.next2fill) {
struct vmxnet3_tx_buf_info *tbi;
- union Vmxnet3_GenericDesc *gdesc;
tbi = tq->buf_info + tq->tx_ring.next2comp;
- gdesc = tq->tx_ring.base + tq->tx_ring.next2comp;
vmxnet3_unmap_tx_buf(tbi, adapter->pdev);
if (tbi->skb) {
@@ -926,7 +924,7 @@
count = VMXNET3_TXD_NEEDED(skb_headlen(skb)) +
skb_shinfo(skb)->nr_frags + 1;
- ctx.ipv4 = (skb->protocol == cpu_to_be16(ETH_P_IP));
+ ctx.ipv4 = (vlan_get_protocol(skb) == cpu_to_be16(ETH_P_IP));
ctx.mss = skb_shinfo(skb)->gso_size;
if (ctx.mss) {
@@ -1285,12 +1283,13 @@
(union Vmxnet3_GenericDesc *)rcd);
skb->protocol = eth_type_trans(skb, adapter->netdev);
- if (unlikely(adapter->vlan_grp && rcd->ts)) {
- vlan_hwaccel_receive_skb(skb,
- adapter->vlan_grp, rcd->tci);
- } else {
+ if (unlikely(rcd->ts))
+ __vlan_hwaccel_put_tag(skb, rcd->tci);
+
+ if (adapter->netdev->features & NETIF_F_LRO)
netif_receive_skb(skb);
- }
+ else
+ napi_gro_receive(&rq->napi, skb);
ctx->skb = NULL;
}
@@ -1911,79 +1910,18 @@
}
}
-static void
-vmxnet3_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp)
-{
- struct vmxnet3_adapter *adapter = netdev_priv(netdev);
- struct Vmxnet3_DriverShared *shared = adapter->shared;
- u32 *vfTable = adapter->shared->devRead.rxFilterConf.vfTable;
- unsigned long flags;
-
- if (grp) {
- /* add vlan rx stripping. */
- if (adapter->netdev->features & NETIF_F_HW_VLAN_RX) {
- int i;
- adapter->vlan_grp = grp;
-
- /*
- * Clear entire vfTable; then enable untagged pkts.
- * Note: setting one entry in vfTable to non-zero turns
- * on VLAN rx filtering.
- */
- for (i = 0; i < VMXNET3_VFT_SIZE; i++)
- vfTable[i] = 0;
-
- VMXNET3_SET_VFTABLE_ENTRY(vfTable, 0);
- spin_lock_irqsave(&adapter->cmd_lock, flags);
- VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
- VMXNET3_CMD_UPDATE_VLAN_FILTERS);
- spin_unlock_irqrestore(&adapter->cmd_lock, flags);
- } else {
- printk(KERN_ERR "%s: vlan_rx_register when device has "
- "no NETIF_F_HW_VLAN_RX\n", netdev->name);
- }
- } else {
- /* remove vlan rx stripping. */
- struct Vmxnet3_DSDevRead *devRead = &shared->devRead;
- adapter->vlan_grp = NULL;
-
- if (devRead->misc.uptFeatures & UPT1_F_RXVLAN) {
- int i;
-
- for (i = 0; i < VMXNET3_VFT_SIZE; i++) {
- /* clear entire vfTable; this also disables
- * VLAN rx filtering
- */
- vfTable[i] = 0;
- }
- spin_lock_irqsave(&adapter->cmd_lock, flags);
- VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
- VMXNET3_CMD_UPDATE_VLAN_FILTERS);
- spin_unlock_irqrestore(&adapter->cmd_lock, flags);
- }
- }
-}
-
static void
vmxnet3_restore_vlan(struct vmxnet3_adapter *adapter)
{
- if (adapter->vlan_grp) {
- u16 vid;
- u32 *vfTable = adapter->shared->devRead.rxFilterConf.vfTable;
- bool activeVlan = false;
+ u32 *vfTable = adapter->shared->devRead.rxFilterConf.vfTable;
+ u16 vid;
- for (vid = 0; vid < VLAN_N_VID; vid++) {
- if (vlan_group_get_device(adapter->vlan_grp, vid)) {
- VMXNET3_SET_VFTABLE_ENTRY(vfTable, vid);
- activeVlan = true;
- }
- }
- if (activeVlan) {
- /* continue to allow untagged pkts */
- VMXNET3_SET_VFTABLE_ENTRY(vfTable, 0);
- }
- }
+ /* allow untagged pkts */
+ VMXNET3_SET_VFTABLE_ENTRY(vfTable, 0);
+
+ for_each_set_bit(vid, adapter->active_vlans, VLAN_N_VID)
+ VMXNET3_SET_VFTABLE_ENTRY(vfTable, vid);
}
@@ -1999,6 +1937,8 @@
VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
VMXNET3_CMD_UPDATE_VLAN_FILTERS);
spin_unlock_irqrestore(&adapter->cmd_lock, flags);
+
+ set_bit(vid, adapter->active_vlans);
}
@@ -2014,6 +1954,8 @@
VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
VMXNET3_CMD_UPDATE_VLAN_FILTERS);
spin_unlock_irqrestore(&adapter->cmd_lock, flags);
+
+ clear_bit(vid, adapter->active_vlans);
}
@@ -2050,8 +1992,14 @@
u8 *new_table = NULL;
u32 new_mode = VMXNET3_RXM_UCAST;
- if (netdev->flags & IFF_PROMISC)
+ if (netdev->flags & IFF_PROMISC) {
+ u32 *vfTable = adapter->shared->devRead.rxFilterConf.vfTable;
+ memset(vfTable, 0, VMXNET3_VFT_SIZE * sizeof(*vfTable));
+
new_mode |= VMXNET3_RXM_PROMISC;
+ } else {
+ vmxnet3_restore_vlan(adapter);
+ }
if (netdev->flags & IFF_BROADCAST)
new_mode |= VMXNET3_RXM_BCAST;
@@ -2085,6 +2033,8 @@
rxConf->rxMode = cpu_to_le32(new_mode);
VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
VMXNET3_CMD_UPDATE_RX_MODE);
+ VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
+ VMXNET3_CMD_UPDATE_VLAN_FILTERS);
}
VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
@@ -2694,12 +2644,13 @@
netdev->hw_features = NETIF_F_SG | NETIF_F_RXCSUM |
NETIF_F_HW_CSUM | NETIF_F_HW_VLAN_TX |
- NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_LRO;
+ NETIF_F_HW_VLAN_RX | NETIF_F_TSO | NETIF_F_TSO6 |
+ NETIF_F_LRO;
if (dma64)
netdev->features |= NETIF_F_HIGHDMA;
- netdev->vlan_features = netdev->hw_features & ~NETIF_F_HW_VLAN_TX;
- netdev->features = netdev->hw_features |
- NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_FILTER;
+ netdev->vlan_features = netdev->hw_features &
+ ~(NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX);
+ netdev->features = netdev->hw_features | NETIF_F_HW_VLAN_FILTER;
netdev_info(adapter->netdev,
"features: sg csum vlan jf tso tsoIPv6 lro%s\n",
@@ -2917,10 +2868,9 @@
.ndo_set_mac_address = vmxnet3_set_mac_addr,
.ndo_change_mtu = vmxnet3_change_mtu,
.ndo_set_features = vmxnet3_set_features,
- .ndo_get_stats = vmxnet3_get_stats,
+ .ndo_get_stats64 = vmxnet3_get_stats64,
.ndo_tx_timeout = vmxnet3_tx_timeout,
.ndo_set_multicast_list = vmxnet3_set_mc,
- .ndo_vlan_rx_register = vmxnet3_vlan_rx_register,
.ndo_vlan_rx_add_vid = vmxnet3_vlan_rx_add_vid,
.ndo_vlan_rx_kill_vid = vmxnet3_vlan_rx_kill_vid,
#ifdef CONFIG_NET_POLL_CONTROLLER
diff --git a/drivers/net/vmxnet3/vmxnet3_ethtool.c b/drivers/net/vmxnet3/vmxnet3_ethtool.c
index dc959fe..27400ed 100644
--- a/drivers/net/vmxnet3/vmxnet3_ethtool.c
+++ b/drivers/net/vmxnet3/vmxnet3_ethtool.c
@@ -113,15 +113,15 @@
};
-struct net_device_stats *
-vmxnet3_get_stats(struct net_device *netdev)
+struct rtnl_link_stats64 *
+vmxnet3_get_stats64(struct net_device *netdev,
+ struct rtnl_link_stats64 *stats)
{
struct vmxnet3_adapter *adapter;
struct vmxnet3_tq_driver_stats *drvTxStats;
struct vmxnet3_rq_driver_stats *drvRxStats;
struct UPT1_TxStats *devTxStats;
struct UPT1_RxStats *devRxStats;
- struct net_device_stats *net_stats = &netdev->stats;
unsigned long flags;
int i;
@@ -132,36 +132,36 @@
VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD, VMXNET3_CMD_GET_STATS);
spin_unlock_irqrestore(&adapter->cmd_lock, flags);
- memset(net_stats, 0, sizeof(*net_stats));
for (i = 0; i < adapter->num_tx_queues; i++) {
devTxStats = &adapter->tqd_start[i].stats;
drvTxStats = &adapter->tx_queue[i].stats;
- net_stats->tx_packets += devTxStats->ucastPktsTxOK +
- devTxStats->mcastPktsTxOK +
- devTxStats->bcastPktsTxOK;
- net_stats->tx_bytes += devTxStats->ucastBytesTxOK +
- devTxStats->mcastBytesTxOK +
- devTxStats->bcastBytesTxOK;
- net_stats->tx_errors += devTxStats->pktsTxError;
- net_stats->tx_dropped += drvTxStats->drop_total;
+ stats->tx_packets += devTxStats->ucastPktsTxOK +
+ devTxStats->mcastPktsTxOK +
+ devTxStats->bcastPktsTxOK;
+ stats->tx_bytes += devTxStats->ucastBytesTxOK +
+ devTxStats->mcastBytesTxOK +
+ devTxStats->bcastBytesTxOK;
+ stats->tx_errors += devTxStats->pktsTxError;
+ stats->tx_dropped += drvTxStats->drop_total;
}
for (i = 0; i < adapter->num_rx_queues; i++) {
devRxStats = &adapter->rqd_start[i].stats;
drvRxStats = &adapter->rx_queue[i].stats;
- net_stats->rx_packets += devRxStats->ucastPktsRxOK +
- devRxStats->mcastPktsRxOK +
- devRxStats->bcastPktsRxOK;
+ stats->rx_packets += devRxStats->ucastPktsRxOK +
+ devRxStats->mcastPktsRxOK +
+ devRxStats->bcastPktsRxOK;
- net_stats->rx_bytes += devRxStats->ucastBytesRxOK +
- devRxStats->mcastBytesRxOK +
- devRxStats->bcastBytesRxOK;
+ stats->rx_bytes += devRxStats->ucastBytesRxOK +
+ devRxStats->mcastBytesRxOK +
+ devRxStats->bcastBytesRxOK;
- net_stats->rx_errors += devRxStats->pktsRxError;
- net_stats->rx_dropped += drvRxStats->drop_total;
- net_stats->multicast += devRxStats->mcastPktsRxOK;
+ stats->rx_errors += devRxStats->pktsRxError;
+ stats->rx_dropped += drvRxStats->drop_total;
+ stats->multicast += devRxStats->mcastPktsRxOK;
}
- return net_stats;
+
+ return stats;
}
static int
@@ -268,7 +268,7 @@
unsigned long flags;
u32 changed = features ^ netdev->features;
- if (changed & (NETIF_F_RXCSUM|NETIF_F_LRO)) {
+ if (changed & (NETIF_F_RXCSUM | NETIF_F_LRO | NETIF_F_HW_VLAN_RX)) {
if (features & NETIF_F_RXCSUM)
adapter->shared->devRead.misc.uptFeatures |=
UPT1_F_RXCSUM;
@@ -284,6 +284,13 @@
adapter->shared->devRead.misc.uptFeatures &=
~UPT1_F_LRO;
+ if (features & NETIF_F_HW_VLAN_RX)
+ adapter->shared->devRead.misc.uptFeatures |=
+ UPT1_F_RXVLAN;
+ else
+ adapter->shared->devRead.misc.uptFeatures &=
+ ~UPT1_F_RXVLAN;
+
spin_lock_irqsave(&adapter->cmd_lock, flags);
VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
VMXNET3_CMD_UPDATE_FEATURE);
diff --git a/drivers/net/vmxnet3/vmxnet3_int.h b/drivers/net/vmxnet3/vmxnet3_int.h
index 8db7ecf..a9cb3fa 100644
--- a/drivers/net/vmxnet3/vmxnet3_int.h
+++ b/drivers/net/vmxnet3/vmxnet3_int.h
@@ -27,6 +27,7 @@
#ifndef _VMXNET3_INT_H
#define _VMXNET3_INT_H
+#include <linux/bitops.h>
#include <linux/ethtool.h>
#include <linux/delay.h>
#include <linux/netdevice.h>
@@ -315,7 +316,7 @@
struct vmxnet3_adapter {
struct vmxnet3_tx_queue tx_queue[VMXNET3_DEVICE_MAX_TX_QUEUES];
struct vmxnet3_rx_queue rx_queue[VMXNET3_DEVICE_MAX_RX_QUEUES];
- struct vlan_group *vlan_grp;
+ unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
struct vmxnet3_intr intr;
spinlock_t cmd_lock;
struct Vmxnet3_DriverShared *shared;
@@ -323,7 +324,6 @@
struct Vmxnet3_TxQueueDesc *tqd_start; /* all tx queue desc */
struct Vmxnet3_RxQueueDesc *rqd_start; /* all rx queue desc */
struct net_device *netdev;
- struct net_device_stats net_stats;
struct pci_dev *pdev;
u8 __iomem *hw_addr0; /* for BAR 0 */
@@ -407,7 +407,9 @@
u32 tx_ring_size, u32 rx_ring_size, u32 rx_ring2_size);
extern void vmxnet3_set_ethtool_ops(struct net_device *netdev);
-extern struct net_device_stats *vmxnet3_get_stats(struct net_device *netdev);
+
+extern struct rtnl_link_stats64 *
+vmxnet3_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats);
extern char vmxnet3_driver_name[];
#endif
diff --git a/drivers/net/vxge/vxge-config.c b/drivers/net/vxge/vxge-config.c
index 32763b2..1520c57 100644
--- a/drivers/net/vxge/vxge-config.c
+++ b/drivers/net/vxge/vxge-config.c
@@ -582,7 +582,7 @@
goto exit;
val64 = readq(&legacy_reg->toc_first_pointer);
- toc = (struct vxge_hw_toc_reg __iomem *)(bar0+val64);
+ toc = bar0 + val64;
exit:
return toc;
}
@@ -600,7 +600,7 @@
u32 i;
enum vxge_hw_status status = VXGE_HW_OK;
- hldev->legacy_reg = (struct vxge_hw_legacy_reg __iomem *)hldev->bar0;
+ hldev->legacy_reg = hldev->bar0;
hldev->toc_reg = __vxge_hw_device_toc_get(hldev->bar0);
if (hldev->toc_reg == NULL) {
@@ -609,39 +609,31 @@
}
val64 = readq(&hldev->toc_reg->toc_common_pointer);
- hldev->common_reg =
- (struct vxge_hw_common_reg __iomem *)(hldev->bar0 + val64);
+ hldev->common_reg = hldev->bar0 + val64;
val64 = readq(&hldev->toc_reg->toc_mrpcim_pointer);
- hldev->mrpcim_reg =
- (struct vxge_hw_mrpcim_reg __iomem *)(hldev->bar0 + val64);
+ hldev->mrpcim_reg = hldev->bar0 + val64;
for (i = 0; i < VXGE_HW_TITAN_SRPCIM_REG_SPACES; i++) {
val64 = readq(&hldev->toc_reg->toc_srpcim_pointer[i]);
- hldev->srpcim_reg[i] =
- (struct vxge_hw_srpcim_reg __iomem *)
- (hldev->bar0 + val64);
+ hldev->srpcim_reg[i] = hldev->bar0 + val64;
}
for (i = 0; i < VXGE_HW_TITAN_VPMGMT_REG_SPACES; i++) {
val64 = readq(&hldev->toc_reg->toc_vpmgmt_pointer[i]);
- hldev->vpmgmt_reg[i] =
- (struct vxge_hw_vpmgmt_reg __iomem *)(hldev->bar0 + val64);
+ hldev->vpmgmt_reg[i] = hldev->bar0 + val64;
}
for (i = 0; i < VXGE_HW_TITAN_VPATH_REG_SPACES; i++) {
val64 = readq(&hldev->toc_reg->toc_vpath_pointer[i]);
- hldev->vpath_reg[i] =
- (struct vxge_hw_vpath_reg __iomem *)
- (hldev->bar0 + val64);
+ hldev->vpath_reg[i] = hldev->bar0 + val64;
}
val64 = readq(&hldev->toc_reg->toc_kdfc);
switch (VXGE_HW_TOC_GET_KDFC_INITIAL_BIR(val64)) {
case 0:
- hldev->kdfc = (u8 __iomem *)(hldev->bar0 +
- VXGE_HW_TOC_GET_KDFC_INITIAL_OFFSET(val64));
+ hldev->kdfc = hldev->bar0 + VXGE_HW_TOC_GET_KDFC_INITIAL_OFFSET(val64) ;
break;
default:
break;
@@ -761,12 +753,11 @@
static enum vxge_hw_status
__vxge_hw_verify_pci_e_info(struct __vxge_hw_device *hldev)
{
- int exp_cap;
+ struct pci_dev *dev = hldev->pdev;
u16 lnk;
/* Get the negotiated link width and speed from PCI config space */
- exp_cap = pci_find_capability(hldev->pdev, PCI_CAP_ID_EXP);
- pci_read_config_word(hldev->pdev, exp_cap + PCI_EXP_LNKSTA, &lnk);
+ pci_read_config_word(dev, dev->pcie_cap + PCI_EXP_LNKSTA, &lnk);
if ((lnk & PCI_EXP_LNKSTA_CLS) != 1)
return VXGE_HW_ERR_INVALID_PCI_INFO;
@@ -1024,7 +1015,7 @@
}
val64 = readq(&toc->toc_common_pointer);
- common_reg = (struct vxge_hw_common_reg __iomem *)(bar0 + val64);
+ common_reg = bar0 + val64;
status = __vxge_hw_device_vpath_reset_in_prog_check(
(u64 __iomem *)&common_reg->vpath_rst_in_prog);
@@ -1044,8 +1035,7 @@
val64 = readq(&toc->toc_vpmgmt_pointer[i]);
- vpmgmt_reg = (struct vxge_hw_vpmgmt_reg __iomem *)
- (bar0 + val64);
+ vpmgmt_reg = bar0 + val64;
hw_info->func_id = __vxge_hw_vpath_func_id_get(vpmgmt_reg);
if (__vxge_hw_device_access_rights_get(hw_info->host_type,
@@ -1054,8 +1044,7 @@
val64 = readq(&toc->toc_mrpcim_pointer);
- mrpcim_reg = (struct vxge_hw_mrpcim_reg __iomem *)
- (bar0 + val64);
+ mrpcim_reg = bar0 + val64;
writeq(0, &mrpcim_reg->xgmac_gen_fw_memo_mask);
wmb();
@@ -1064,8 +1053,7 @@
val64 = readq(&toc->toc_vpath_pointer[i]);
spin_lock_init(&vpath.lock);
- vpath.vp_reg = (struct vxge_hw_vpath_reg __iomem *)
- (bar0 + val64);
+ vpath.vp_reg = bar0 + val64;
vpath.vp_open = VXGE_HW_VP_NOT_OPEN;
status = __vxge_hw_vpath_pci_func_mode_get(&vpath, hw_info);
@@ -1088,8 +1076,7 @@
continue;
val64 = readq(&toc->toc_vpath_pointer[i]);
- vpath.vp_reg = (struct vxge_hw_vpath_reg __iomem *)
- (bar0 + val64);
+ vpath.vp_reg = bar0 + val64;
vpath.vp_open = VXGE_HW_VP_NOT_OPEN;
status = __vxge_hw_vpath_addr_get(&vpath,
@@ -1994,13 +1981,11 @@
u16 vxge_hw_device_link_width_get(struct __vxge_hw_device *hldev)
{
- int link_width, exp_cap;
+ struct pci_dev *dev = hldev->pdev;
u16 lnk;
- exp_cap = pci_find_capability(hldev->pdev, PCI_CAP_ID_EXP);
- pci_read_config_word(hldev->pdev, exp_cap + PCI_EXP_LNKSTA, &lnk);
- link_width = (lnk & VXGE_HW_PCI_EXP_LNKCAP_LNK_WIDTH) >> 4;
- return link_width;
+ pci_read_config_word(dev, dev->pcie_cap + PCI_EXP_LNKSTA, &lnk);
+ return (lnk & VXGE_HW_PCI_EXP_LNKCAP_LNK_WIDTH) >> 4;
}
/*
@@ -2140,8 +2125,7 @@
memblock_index, item,
&memblock_item_idx);
- rxdp = (struct vxge_hw_ring_rxd_1 *)
- ring->channel.reserve_arr[reserve_index];
+ rxdp = ring->channel.reserve_arr[reserve_index];
uld_priv = ((u8 *)rxdblock_priv + ring->rxd_priv_size * i);
@@ -4880,8 +4864,7 @@
goto vpath_open_exit8;
}
- vpath->hw_stats = (struct vxge_hw_vpath_stats_hw_info *)vpath->
- stats_block->memblock;
+ vpath->hw_stats = vpath->stats_block->memblock;
memset(vpath->hw_stats, 0,
sizeof(struct vxge_hw_vpath_stats_hw_info));
diff --git a/drivers/net/vxge/vxge-config.h b/drivers/net/vxge/vxge-config.h
index 359b9b9..dd36258 100644
--- a/drivers/net/vxge/vxge-config.h
+++ b/drivers/net/vxge/vxge-config.h
@@ -13,8 +13,10 @@
******************************************************************************/
#ifndef VXGE_CONFIG_H
#define VXGE_CONFIG_H
+#include <linux/hardirq.h>
#include <linux/list.h>
#include <linux/slab.h>
+#include <asm/io.h>
#ifndef VXGE_CACHE_LINE_SIZE
#define VXGE_CACHE_LINE_SIZE 128
diff --git a/drivers/net/vxge/vxge-main.c b/drivers/net/vxge/vxge-main.c
index 8ab870a..15d878b 100644
--- a/drivers/net/vxge/vxge-main.c
+++ b/drivers/net/vxge/vxge-main.c
@@ -44,6 +44,7 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/if_vlan.h>
+#include <linux/interrupt.h>
#include <linux/pci.h>
#include <linux/slab.h>
#include <linux/tcp.h>
@@ -295,11 +296,13 @@
skb_record_rx_queue(skb, ring->driver_id);
skb->protocol = eth_type_trans(skb, ring->ndev);
+ u64_stats_update_begin(&ring->stats.syncp);
ring->stats.rx_frms++;
ring->stats.rx_bytes += pkt_length;
if (skb->pkt_type == PACKET_MULTICAST)
ring->stats.rx_mcast++;
+ u64_stats_update_end(&ring->stats.syncp);
vxge_debug_rx(VXGE_TRACE,
"%s: %s:%d skb protocol = %d",
@@ -591,8 +594,10 @@
vxge_hw_fifo_txdl_free(fifo_hw, dtr);
/* Updating the statistics block */
+ u64_stats_update_begin(&fifo->stats.syncp);
fifo->stats.tx_frms++;
fifo->stats.tx_bytes += skb->len;
+ u64_stats_update_end(&fifo->stats.syncp);
*done_skb++ = skb;
@@ -628,7 +633,7 @@
ip = ip_hdr(skb);
- if ((ip->frag_off & htons(IP_OFFSET|IP_MF)) == 0) {
+ if (!ip_is_fragment(ip)) {
th = (struct tcphdr *)(((unsigned char *)ip) +
ip->ihl*4);
@@ -679,8 +684,7 @@
new_mac_entry->state = mac->state;
vpath->mac_addr_cnt++;
- /* Is this a multicast address */
- if (0x01 & mac->macaddr[0])
+ if (is_multicast_ether_addr(mac->macaddr))
vpath->mcast_addr_cnt++;
return TRUE;
@@ -694,7 +698,7 @@
struct vxge_vpath *vpath;
enum vxge_hw_vpath_mac_addr_add_mode duplicate_mode;
- if (0x01 & mac->macaddr[0]) /* multicast address */
+ if (is_multicast_ether_addr(mac->macaddr))
duplicate_mode = VXGE_HW_VPATH_MAC_ADDR_ADD_DUPLICATE;
else
duplicate_mode = VXGE_HW_VPATH_MAC_ADDR_REPLACE_DUPLICATE;
@@ -1073,8 +1077,7 @@
kfree((struct vxge_mac_addrs *)entry);
vpath->mac_addr_cnt--;
- /* Is this a multicast address */
- if (0x01 & mac->macaddr[0])
+ if (is_multicast_ether_addr(mac->macaddr))
vpath->mcast_addr_cnt--;
return TRUE;
}
@@ -1196,8 +1199,7 @@
mac_address = (u8 *)&mac_entry->macaddr;
memcpy(mac_info.macaddr, mac_address, ETH_ALEN);
- /* Is this a multicast address */
- if (0x01 & mac_info.macaddr[0]) {
+ if (is_multicast_ether_addr(mac_info.macaddr)) {
for (vpath_idx = 0; vpath_idx <
vdev->no_of_vpath;
vpath_idx++) {
@@ -1239,8 +1241,7 @@
mac_address = (u8 *)&mac_entry->macaddr;
memcpy(mac_info.macaddr, mac_address, ETH_ALEN);
- /* Is this a multicast address */
- if (0x01 & mac_info.macaddr[0])
+ if (is_multicast_ether_addr(mac_info.macaddr))
break;
}
@@ -2629,11 +2630,16 @@
struct vxge_vpath *vpath;
struct vxge_ring *ring;
int i;
+ unsigned long rx_frms;
for (i = 0; i < vdev->no_of_vpath; i++) {
ring = &vdev->vpaths[i].ring;
+
+ /* Truncated to machine word size number of frames */
+ rx_frms = ACCESS_ONCE(ring->stats.rx_frms);
+
/* Did this vpath received any packets */
- if (ring->stats.prev_rx_frms == ring->stats.rx_frms) {
+ if (ring->stats.prev_rx_frms == rx_frms) {
status = vxge_hw_vpath_check_leak(ring->handle);
/* Did it received any packets last time */
@@ -2653,7 +2659,7 @@
}
}
}
- ring->stats.prev_rx_frms = ring->stats.rx_frms;
+ ring->stats.prev_rx_frms = rx_frms;
ring->last_status = status;
}
@@ -3124,14 +3130,36 @@
/* net_stats already zeroed by caller */
for (k = 0; k < vdev->no_of_vpath; k++) {
- net_stats->rx_packets += vdev->vpaths[k].ring.stats.rx_frms;
- net_stats->rx_bytes += vdev->vpaths[k].ring.stats.rx_bytes;
- net_stats->rx_errors += vdev->vpaths[k].ring.stats.rx_errors;
- net_stats->multicast += vdev->vpaths[k].ring.stats.rx_mcast;
- net_stats->rx_dropped += vdev->vpaths[k].ring.stats.rx_dropped;
- net_stats->tx_packets += vdev->vpaths[k].fifo.stats.tx_frms;
- net_stats->tx_bytes += vdev->vpaths[k].fifo.stats.tx_bytes;
- net_stats->tx_errors += vdev->vpaths[k].fifo.stats.tx_errors;
+ struct vxge_ring_stats *rxstats = &vdev->vpaths[k].ring.stats;
+ struct vxge_fifo_stats *txstats = &vdev->vpaths[k].fifo.stats;
+ unsigned int start;
+ u64 packets, bytes, multicast;
+
+ do {
+ start = u64_stats_fetch_begin(&rxstats->syncp);
+
+ packets = rxstats->rx_frms;
+ multicast = rxstats->rx_mcast;
+ bytes = rxstats->rx_bytes;
+ } while (u64_stats_fetch_retry(&rxstats->syncp, start));
+
+ net_stats->rx_packets += packets;
+ net_stats->rx_bytes += bytes;
+ net_stats->multicast += multicast;
+
+ net_stats->rx_errors += rxstats->rx_errors;
+ net_stats->rx_dropped += rxstats->rx_dropped;
+
+ do {
+ start = u64_stats_fetch_begin(&txstats->syncp);
+
+ packets = txstats->tx_frms;
+ bytes = txstats->tx_bytes;
+ } while (u64_stats_fetch_retry(&txstats->syncp, start));
+
+ net_stats->tx_packets += packets;
+ net_stats->tx_bytes += bytes;
+ net_stats->tx_errors += txstats->tx_errors;
}
return net_stats;
diff --git a/drivers/net/vxge/vxge-main.h b/drivers/net/vxge/vxge-main.h
index ed120ab..66e6de8 100644
--- a/drivers/net/vxge/vxge-main.h
+++ b/drivers/net/vxge/vxge-main.h
@@ -201,30 +201,14 @@
/* Software Statistics */
struct vxge_sw_stats {
- /* Network Stats (interface stats) */
-
- /* Tx */
- u64 tx_frms;
- u64 tx_errors;
- u64 tx_bytes;
- u64 txd_not_free;
- u64 txd_out_of_desc;
/* Virtual Path */
- u64 vpaths_open;
- u64 vpath_open_fail;
-
- /* Rx */
- u64 rx_frms;
- u64 rx_errors;
- u64 rx_bytes;
- u64 rx_mcast;
+ unsigned long vpaths_open;
+ unsigned long vpath_open_fail;
/* Misc. */
- u64 link_up;
- u64 link_down;
- u64 pci_map_fail;
- u64 skb_alloc_fail;
+ unsigned long link_up;
+ unsigned long link_down;
};
struct vxge_mac_addrs {
@@ -237,12 +221,14 @@
struct vxgedev;
struct vxge_fifo_stats {
+ struct u64_stats_sync syncp;
u64 tx_frms;
- u64 tx_errors;
u64 tx_bytes;
- u64 txd_not_free;
- u64 txd_out_of_desc;
- u64 pci_map_fail;
+
+ unsigned long tx_errors;
+ unsigned long txd_not_free;
+ unsigned long txd_out_of_desc;
+ unsigned long pci_map_fail;
};
struct vxge_fifo {
@@ -264,14 +250,16 @@
} ____cacheline_aligned;
struct vxge_ring_stats {
- u64 prev_rx_frms;
+ struct u64_stats_sync syncp;
u64 rx_frms;
- u64 rx_errors;
- u64 rx_dropped;
- u64 rx_bytes;
u64 rx_mcast;
- u64 pci_map_fail;
- u64 skb_alloc_fail;
+ u64 rx_bytes;
+
+ unsigned long rx_errors;
+ unsigned long rx_dropped;
+ unsigned long prev_rx_frms;
+ unsigned long pci_map_fail;
+ unsigned long skb_alloc_fail;
};
struct vxge_ring {
diff --git a/drivers/net/vxge/vxge-traffic.c b/drivers/net/vxge/vxge-traffic.c
index f935170..ad64ce0 100644
--- a/drivers/net/vxge/vxge-traffic.c
+++ b/drivers/net/vxge/vxge-traffic.c
@@ -1309,7 +1309,7 @@
vxge_hw_channel_dtr_try_complete(channel, rxdh);
- rxdp = (struct vxge_hw_ring_rxd_1 *)*rxdh;
+ rxdp = *rxdh;
if (rxdp == NULL) {
status = VXGE_HW_INF_NO_MORE_COMPLETED_DESCRIPTORS;
goto exit;
@@ -1565,7 +1565,7 @@
channel = &fifo->channel;
txdl_priv = __vxge_hw_fifo_txdl_priv(fifo, txdlh);
- txdp_first = (struct vxge_hw_fifo_txd *)txdlh;
+ txdp_first = txdlh;
txdp_last = (struct vxge_hw_fifo_txd *)txdlh + (txdl_priv->frags - 1);
txdp_last->control_0 |=
@@ -1631,7 +1631,7 @@
vxge_hw_channel_dtr_try_complete(channel, txdlh);
- txdp = (struct vxge_hw_fifo_txd *)*txdlh;
+ txdp = *txdlh;
if (txdp == NULL) {
status = VXGE_HW_INF_NO_MORE_COMPLETED_DESCRIPTORS;
goto exit;
diff --git a/drivers/net/wan/c101.c b/drivers/net/wan/c101.c
index 4ac85a0..54f995f 100644
--- a/drivers/net/wan/c101.c
+++ b/drivers/net/wan/c101.c
@@ -14,6 +14,8 @@
* Moxa C101 User's Manual
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/capability.h>
@@ -313,44 +315,44 @@
int result;
if (irq<3 || irq>15 || irq == 6) /* FIXME */ {
- printk(KERN_ERR "c101: invalid IRQ value\n");
+ pr_err("invalid IRQ value\n");
return -ENODEV;
}
if (winbase < 0xC0000 || winbase > 0xDFFFF || (winbase & 0x3FFF) !=0) {
- printk(KERN_ERR "c101: invalid RAM value\n");
+ pr_err("invalid RAM value\n");
return -ENODEV;
}
card = kzalloc(sizeof(card_t), GFP_KERNEL);
if (card == NULL) {
- printk(KERN_ERR "c101: unable to allocate memory\n");
+ pr_err("unable to allocate memory\n");
return -ENOBUFS;
}
card->dev = alloc_hdlcdev(card);
if (!card->dev) {
- printk(KERN_ERR "c101: unable to allocate memory\n");
+ pr_err("unable to allocate memory\n");
kfree(card);
return -ENOBUFS;
}
if (request_irq(irq, sca_intr, 0, devname, card)) {
- printk(KERN_ERR "c101: could not allocate IRQ\n");
+ pr_err("could not allocate IRQ\n");
c101_destroy_card(card);
return -EBUSY;
}
card->irq = irq;
if (!request_mem_region(winbase, C101_MAPPED_RAM_SIZE, devname)) {
- printk(KERN_ERR "c101: could not request RAM window\n");
+ pr_err("could not request RAM window\n");
c101_destroy_card(card);
return -EBUSY;
}
card->phy_winbase = winbase;
card->win0base = ioremap(winbase, C101_MAPPED_RAM_SIZE);
if (!card->win0base) {
- printk(KERN_ERR "c101: could not map I/O address\n");
+ pr_err("could not map I/O address\n");
c101_destroy_card(card);
return -EFAULT;
}
@@ -381,7 +383,7 @@
result = register_hdlc_device(dev);
if (result) {
- printk(KERN_WARNING "c101: unable to register hdlc device\n");
+ pr_warn("unable to register hdlc device\n");
c101_destroy_card(card);
return result;
}
@@ -389,10 +391,8 @@
sca_init_port(card); /* Set up C101 memory */
set_carrier(card);
- printk(KERN_INFO "%s: Moxa C101 on IRQ%u,"
- " using %u TX + %u RX packets rings\n",
- dev->name, card->irq,
- card->tx_ring_buffers, card->rx_ring_buffers);
+ netdev_info(dev, "Moxa C101 on IRQ%u, using %u TX + %u RX packets rings\n",
+ card->irq, card->tx_ring_buffers, card->rx_ring_buffers);
*new_card = card;
new_card = &card->next_card;
@@ -405,12 +405,12 @@
{
if (hw == NULL) {
#ifdef MODULE
- printk(KERN_INFO "c101: no card initialized\n");
+ pr_info("no card initialized\n");
#endif
return -EINVAL; /* no parameters specified, abort */
}
- printk(KERN_INFO "%s\n", version);
+ pr_info("%s\n", version);
do {
unsigned long irq, ram;
@@ -428,7 +428,7 @@
return first_card ? 0 : -EINVAL;
}while(*hw++ == ':');
- printk(KERN_ERR "c101: invalid hardware parameters\n");
+ pr_err("invalid hardware parameters\n");
return first_card ? 0 : -EINVAL;
}
diff --git a/drivers/net/wan/cosa.c b/drivers/net/wan/cosa.c
index 6fb6f8e..6aed238 100644
--- a/drivers/net/wan/cosa.c
+++ b/drivers/net/wan/cosa.c
@@ -74,6 +74,8 @@
* The Sync PPP/Cisco HDLC layer (syncppp.c) ported to Linux by Alan Cox
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/sched.h>
@@ -361,14 +363,13 @@
if (cosa_major > 0) {
if (register_chrdev(cosa_major, "cosa", &cosa_fops)) {
- printk(KERN_WARNING "cosa: unable to get major %d\n",
- cosa_major);
+ pr_warn("unable to get major %d\n", cosa_major);
err = -EIO;
goto out;
}
} else {
if (!(cosa_major=register_chrdev(0, "cosa", &cosa_fops))) {
- printk(KERN_WARNING "cosa: unable to register chardev\n");
+ pr_warn("unable to register chardev\n");
err = -EIO;
goto out;
}
@@ -378,7 +379,7 @@
for (i=0; io[i] != 0 && i < MAX_CARDS; i++)
cosa_probe(io[i], irq[i], dma[i]);
if (!nr_cards) {
- printk(KERN_WARNING "cosa: no devices found.\n");
+ pr_warn("no devices found\n");
unregister_chrdev(cosa_major, "cosa");
err = -ENODEV;
goto out;
@@ -447,26 +448,25 @@
/* Checking validity of parameters: */
/* IRQ should be 2-7 or 10-15; negative IRQ means autoprobe */
if ((irq >= 0 && irq < 2) || irq > 15 || (irq < 10 && irq > 7)) {
- printk (KERN_INFO "cosa_probe: invalid IRQ %d\n", irq);
+ pr_info("invalid IRQ %d\n", irq);
return -1;
}
/* I/O address should be between 0x100 and 0x3ff and should be
* multiple of 8. */
if (base < 0x100 || base > 0x3ff || base & 0x7) {
- printk (KERN_INFO "cosa_probe: invalid I/O address 0x%x\n",
- base);
+ pr_info("invalid I/O address 0x%x\n", base);
return -1;
}
/* DMA should be 0,1 or 3-7 */
if (dma < 0 || dma == 4 || dma > 7) {
- printk (KERN_INFO "cosa_probe: invalid DMA %d\n", dma);
+ pr_info("invalid DMA %d\n", dma);
return -1;
}
/* and finally, on 16-bit COSA DMA should be 4-7 and
* I/O base should not be multiple of 0x10 */
if (((base & 0x8) && dma < 4) || (!(base & 0x8) && dma > 3)) {
- printk (KERN_INFO "cosa_probe: 8/16 bit base and DMA mismatch"
- " (base=0x%x, dma=%d)\n", base, dma);
+ pr_info("8/16 bit base and DMA mismatch (base=0x%x, dma=%d)\n",
+ base, dma);
return -1;
}
@@ -479,7 +479,7 @@
return -1;
if (cosa_reset_and_read_id(cosa, cosa->id_string) < 0) {
- printk(KERN_DEBUG "cosa: probe at 0x%x failed.\n", base);
+ printk(KERN_DEBUG "probe at 0x%x failed.\n", base);
err = -1;
goto err_out;
}
@@ -492,8 +492,7 @@
else {
/* Print a warning only if we are not autoprobing */
#ifndef COSA_ISA_AUTOPROBE
- printk(KERN_INFO "cosa: valid signature not found at 0x%x.\n",
- base);
+ pr_info("valid signature not found at 0x%x\n", base);
#endif
err = -1;
goto err_out;
@@ -501,14 +500,14 @@
/* Update the name of the region now we know the type of card */
release_region(base, is_8bit(cosa)?2:4);
if (!request_region(base, is_8bit(cosa)?2:4, cosa->type)) {
- printk(KERN_DEBUG "cosa: changing name at 0x%x failed.\n", base);
+ printk(KERN_DEBUG "changing name at 0x%x failed.\n", base);
return -1;
}
/* Now do IRQ autoprobe */
if (irq < 0) {
unsigned long irqs;
-/* printk(KERN_INFO "IRQ autoprobe\n"); */
+/* pr_info("IRQ autoprobe\n"); */
irqs = probe_irq_on();
/*
* Enable interrupt on tx buffer empty (it sure is)
@@ -526,13 +525,13 @@
cosa_getdata8(cosa);
if (irq < 0) {
- printk (KERN_INFO "cosa IRQ autoprobe: multiple interrupts obtained (%d, board at 0x%x)\n",
+ pr_info("multiple interrupts obtained (%d, board at 0x%x)\n",
irq, cosa->datareg);
err = -1;
goto err_out;
}
if (irq == 0) {
- printk (KERN_INFO "cosa IRQ autoprobe: no interrupt obtained (board at 0x%x)\n",
+ pr_info("no interrupt obtained (board at 0x%x)\n",
cosa->datareg);
/* return -1; */
}
@@ -579,8 +578,7 @@
/* Register the network interface */
if (!(chan->netdev = alloc_hdlcdev(chan))) {
- printk(KERN_WARNING "%s: alloc_hdlcdev failed.\n",
- chan->name);
+ pr_warn("%s: alloc_hdlcdev failed\n", chan->name);
goto err_hdlcdev;
}
dev_to_hdlc(chan->netdev)->attach = cosa_net_attach;
@@ -591,14 +589,14 @@
chan->netdev->irq = chan->cosa->irq;
chan->netdev->dma = chan->cosa->dma;
if (register_hdlc_device(chan->netdev)) {
- printk(KERN_WARNING "%s: register_hdlc_device()"
- " failed.\n", chan->netdev->name);
+ netdev_warn(chan->netdev,
+ "register_hdlc_device() failed\n");
free_netdev(chan->netdev);
goto err_hdlcdev;
}
}
- printk (KERN_INFO "cosa%d: %s (%s at 0x%x irq %d dma %d), %d channels\n",
+ pr_info("cosa%d: %s (%s at 0x%x irq %d dma %d), %d channels\n",
cosa->num, cosa->id_string, cosa->type,
cosa->datareg, cosa->irq, cosa->dma, cosa->nchannels);
@@ -618,8 +616,7 @@
free_irq(cosa->irq, cosa);
err_out:
release_region(cosa->datareg,is_8bit(cosa)?2:4);
- printk(KERN_NOTICE "cosa%d: allocating resources failed\n",
- cosa->num);
+ pr_notice("cosa%d: allocating resources failed\n", cosa->num);
return err;
}
@@ -641,14 +638,14 @@
unsigned long flags;
if (!(chan->cosa->firmware_status & COSA_FW_START)) {
- printk(KERN_NOTICE "%s: start the firmware first (status %d)\n",
- chan->cosa->name, chan->cosa->firmware_status);
+ pr_notice("%s: start the firmware first (status %d)\n",
+ chan->cosa->name, chan->cosa->firmware_status);
return -EPERM;
}
spin_lock_irqsave(&chan->cosa->lock, flags);
if (chan->usage != 0) {
- printk(KERN_WARNING "%s: cosa_net_open called with usage count"
- " %d\n", chan->name, chan->usage);
+ pr_warn("%s: cosa_net_open called with usage count %d\n",
+ chan->name, chan->usage);
spin_unlock_irqrestore(&chan->cosa->lock, flags);
return -EBUSY;
}
@@ -736,8 +733,7 @@
kfree_skb(chan->rx_skb);
chan->rx_skb = dev_alloc_skb(size);
if (chan->rx_skb == NULL) {
- printk(KERN_NOTICE "%s: Memory squeeze, dropping packet\n",
- chan->name);
+ pr_notice("%s: Memory squeeze, dropping packet\n", chan->name);
chan->netdev->stats.rx_dropped++;
return NULL;
}
@@ -748,8 +744,7 @@
static int cosa_net_rx_done(struct channel_data *chan)
{
if (!chan->rx_skb) {
- printk(KERN_WARNING "%s: rx_done with empty skb!\n",
- chan->name);
+ pr_warn("%s: rx_done with empty skb!\n", chan->name);
chan->netdev->stats.rx_errors++;
chan->netdev->stats.rx_frame_errors++;
return 0;
@@ -768,8 +763,7 @@
static int cosa_net_tx_done(struct channel_data *chan, int size)
{
if (!chan->tx_skb) {
- printk(KERN_WARNING "%s: tx_done with empty skb!\n",
- chan->name);
+ pr_warn("%s: tx_done with empty skb!\n", chan->name);
chan->netdev->stats.tx_errors++;
chan->netdev->stats.tx_aborted_errors++;
return 1;
@@ -794,15 +788,15 @@
char *kbuf;
if (!(cosa->firmware_status & COSA_FW_START)) {
- printk(KERN_NOTICE "%s: start the firmware first (status %d)\n",
- cosa->name, cosa->firmware_status);
+ pr_notice("%s: start the firmware first (status %d)\n",
+ cosa->name, cosa->firmware_status);
return -EPERM;
}
if (mutex_lock_interruptible(&chan->rlock))
return -ERESTARTSYS;
if ((chan->rxdata = kmalloc(COSA_MTU, GFP_DMA|GFP_KERNEL)) == NULL) {
- printk(KERN_INFO "%s: cosa_read() - OOM\n", cosa->name);
+ pr_info("%s: cosa_read() - OOM\n", cosa->name);
mutex_unlock(&chan->rlock);
return -ENOMEM;
}
@@ -869,8 +863,8 @@
char *kbuf;
if (!(cosa->firmware_status & COSA_FW_START)) {
- printk(KERN_NOTICE "%s: start the firmware first (status %d)\n",
- cosa->name, cosa->firmware_status);
+ pr_notice("%s: start the firmware first (status %d)\n",
+ cosa->name, cosa->firmware_status);
return -EPERM;
}
if (down_interruptible(&chan->wsem))
@@ -881,8 +875,8 @@
/* Allocate the buffer */
if ((kbuf = kmalloc(count, GFP_KERNEL|GFP_DMA)) == NULL) {
- printk(KERN_NOTICE "%s: cosa_write() OOM - dropping packet\n",
- cosa->name);
+ pr_notice("%s: cosa_write() OOM - dropping packet\n",
+ cosa->name);
up(&chan->wsem);
return -ENOMEM;
}
@@ -932,7 +926,7 @@
static unsigned int cosa_poll(struct file *file, poll_table *poll)
{
- printk(KERN_INFO "cosa_poll is here\n");
+ pr_info("cosa_poll is here\n");
return 0;
}
@@ -1017,15 +1011,14 @@
{
char idstring[COSA_MAX_ID_STRING];
if (cosa->usage > 1)
- printk(KERN_INFO "cosa%d: WARNING: reset requested with cosa->usage > 1 (%d). Odd things may happen.\n",
+ pr_info("cosa%d: WARNING: reset requested with cosa->usage > 1 (%d). Odd things may happen.\n",
cosa->num, cosa->usage);
cosa->firmware_status &= ~(COSA_FW_RESET|COSA_FW_START);
if (cosa_reset_and_read_id(cosa, idstring) < 0) {
- printk(KERN_NOTICE "cosa%d: reset failed\n", cosa->num);
+ pr_notice("cosa%d: reset failed\n", cosa->num);
return -EIO;
}
- printk(KERN_INFO "cosa%d: resetting device: %s\n", cosa->num,
- idstring);
+ pr_info("cosa%d: resetting device: %s\n", cosa->num, idstring);
cosa->firmware_status |= COSA_FW_RESET;
return 0;
}
@@ -1037,11 +1030,11 @@
int i;
if (cosa->usage > 1)
- printk(KERN_INFO "%s: WARNING: download of microcode requested with cosa->usage > 1 (%d). Odd things may happen.\n",
+ pr_info("%s: WARNING: download of microcode requested with cosa->usage > 1 (%d). Odd things may happen.\n",
cosa->name, cosa->usage);
if (!(cosa->firmware_status & COSA_FW_RESET)) {
- printk(KERN_NOTICE "%s: reset the card first (status %d).\n",
- cosa->name, cosa->firmware_status);
+ pr_notice("%s: reset the card first (status %d)\n",
+ cosa->name, cosa->firmware_status);
return -EPERM;
}
@@ -1059,11 +1052,11 @@
i = download(cosa, d.code, d.len, d.addr);
if (i < 0) {
- printk(KERN_NOTICE "cosa%d: microcode download failed: %d\n",
- cosa->num, i);
+ pr_notice("cosa%d: microcode download failed: %d\n",
+ cosa->num, i);
return -EIO;
}
- printk(KERN_INFO "cosa%d: downloading microcode - 0x%04x bytes at 0x%04x\n",
+ pr_info("cosa%d: downloading microcode - 0x%04x bytes at 0x%04x\n",
cosa->num, d.len, d.addr);
cosa->firmware_status |= COSA_FW_RESET|COSA_FW_DOWNLOAD;
return 0;
@@ -1076,12 +1069,11 @@
int i;
if (cosa->usage > 1)
- printk(KERN_INFO "cosa%d: WARNING: readmem requested with "
- "cosa->usage > 1 (%d). Odd things may happen.\n",
+ pr_info("cosa%d: WARNING: readmem requested with cosa->usage > 1 (%d). Odd things may happen.\n",
cosa->num, cosa->usage);
if (!(cosa->firmware_status & COSA_FW_RESET)) {
- printk(KERN_NOTICE "%s: reset the card first (status %d).\n",
- cosa->name, cosa->firmware_status);
+ pr_notice("%s: reset the card first (status %d)\n",
+ cosa->name, cosa->firmware_status);
return -EPERM;
}
@@ -1093,11 +1085,10 @@
i = readmem(cosa, d.code, d.len, d.addr);
if (i < 0) {
- printk(KERN_NOTICE "cosa%d: reading memory failed: %d\n",
- cosa->num, i);
+ pr_notice("cosa%d: reading memory failed: %d\n", cosa->num, i);
return -EIO;
}
- printk(KERN_INFO "cosa%d: reading card memory - 0x%04x bytes at 0x%04x\n",
+ pr_info("cosa%d: reading card memory - 0x%04x bytes at 0x%04x\n",
cosa->num, d.len, d.addr);
cosa->firmware_status |= COSA_FW_RESET;
return 0;
@@ -1109,23 +1100,22 @@
int i;
if (cosa->usage > 1)
- printk(KERN_INFO "cosa%d: WARNING: start microcode requested with cosa->usage > 1 (%d). Odd things may happen.\n",
+ pr_info("cosa%d: WARNING: start microcode requested with cosa->usage > 1 (%d). Odd things may happen.\n",
cosa->num, cosa->usage);
if ((cosa->firmware_status & (COSA_FW_RESET|COSA_FW_DOWNLOAD))
!= (COSA_FW_RESET|COSA_FW_DOWNLOAD)) {
- printk(KERN_NOTICE "%s: download the microcode and/or reset the card first (status %d).\n",
- cosa->name, cosa->firmware_status);
+ pr_notice("%s: download the microcode and/or reset the card first (status %d)\n",
+ cosa->name, cosa->firmware_status);
return -EPERM;
}
cosa->firmware_status &= ~COSA_FW_RESET;
if ((i=startmicrocode(cosa, address)) < 0) {
- printk(KERN_NOTICE "cosa%d: start microcode at 0x%04x failed: %d\n",
- cosa->num, address, i);
+ pr_notice("cosa%d: start microcode at 0x%04x failed: %d\n",
+ cosa->num, address, i);
return -EIO;
}
- printk(KERN_INFO "cosa%d: starting microcode at 0x%04x\n",
- cosa->num, address);
+ pr_info("cosa%d: starting microcode at 0x%04x\n", cosa->num, address);
cosa->startaddr = address;
cosa->firmware_status |= COSA_FW_START;
return 0;
@@ -1255,11 +1245,11 @@
#ifdef DEBUG_DATA
int i;
- printk(KERN_INFO "cosa%dc%d: starting tx(0x%x)", chan->cosa->num,
- chan->num, len);
+ pr_info("cosa%dc%d: starting tx(0x%x)",
+ chan->cosa->num, chan->num, len);
for (i=0; i<len; i++)
- printk(" %02x", buf[i]&0xff);
- printk("\n");
+ pr_cont(" %02x", buf[i]&0xff);
+ pr_cont("\n");
#endif
spin_lock_irqsave(&cosa->lock, flags);
chan->txbuf = buf;
@@ -1353,7 +1343,7 @@
if (test_bit(TXBIT, &cosa->rxtx))
s = "TX DMA";
- printk(KERN_INFO "%s: %s timeout - restarting.\n", cosa->name, s);
+ pr_info("%s: %s timeout - restarting\n", cosa->name, s);
spin_lock_irqsave(&cosa->lock, flags);
cosa->rxtx = 0;
@@ -1387,7 +1377,7 @@
return 0;
if ((b^ (b+len)) & 0x10000) {
if (count++ < 5)
- printk(KERN_INFO "%s: packet spanning a 64k boundary\n",
+ pr_info("%s: packet spanning a 64k boundary\n",
chan->name);
return 0;
}
@@ -1498,8 +1488,7 @@
char c;
int i;
if ((i=get_wait_data(cosa)) == -1) {
- printk (KERN_INFO "cosa: 0x%04x bytes remaining\n",
- length);
+ pr_info("0x%04x bytes remaining\n", length);
return -11;
}
c=i;
@@ -1582,14 +1571,15 @@
short r;
r = cosa_getdata8(cosa);
#if 0
- printk(KERN_INFO "cosa: get_wait_data returning after %d retries\n", 999-retries);
+ pr_info("get_wait_data returning after %d retries\n",
+ 999-retries);
#endif
return r;
}
/* sleep if not ready to read */
schedule_timeout_interruptible(1);
}
- printk(KERN_INFO "cosa: timeout in get_wait_data (status 0x%x)\n",
+ pr_info("timeout in get_wait_data (status 0x%x)\n",
cosa_getstatus(cosa));
return -1;
}
@@ -1607,7 +1597,7 @@
if (cosa_getstatus(cosa) & SR_TX_RDY) {
cosa_putdata8(cosa, data);
#if 0
- printk(KERN_INFO "Putdata: %d retries\n", 999-retries);
+ pr_info("Putdata: %d retries\n", 999-retries);
#endif
return 0;
}
@@ -1616,7 +1606,7 @@
schedule_timeout_interruptible(1);
#endif
}
- printk(KERN_INFO "cosa%d: timeout in put_wait_data (status 0x%x)\n",
+ pr_info("cosa%d: timeout in put_wait_data (status 0x%x)\n",
cosa->num, cosa_getstatus(cosa));
return -1;
}
@@ -1636,13 +1626,13 @@
sprintf(temp, "%04X", number);
for (i=0; i<4; i++) {
if (put_wait_data(cosa, temp[i]) == -1) {
- printk(KERN_NOTICE "cosa%d: puthexnumber failed to write byte %d\n",
- cosa->num, i);
+ pr_notice("cosa%d: puthexnumber failed to write byte %d\n",
+ cosa->num, i);
return -1-2*i;
}
if (get_wait_data(cosa) != temp[i]) {
- printk(KERN_NOTICE "cosa%d: puthexhumber failed to read echo of byte %d\n",
- cosa->num, i);
+ pr_notice("cosa%d: puthexhumber failed to read echo of byte %d\n",
+ cosa->num, i);
return -2-2*i;
}
}
@@ -1687,8 +1677,7 @@
{
unsigned long flags, flags1;
#ifdef DEBUG_IRQS
- printk(KERN_INFO "cosa%d: SR_DOWN_REQUEST status=0x%04x\n",
- cosa->num, status);
+ pr_info("cosa%d: SR_DOWN_REQUEST status=0x%04x\n", cosa->num, status);
#endif
spin_lock_irqsave(&cosa->lock, flags);
set_bit(TXBIT, &cosa->rxtx);
@@ -1696,8 +1685,7 @@
/* flow control, see the comment above */
int i=0;
if (!cosa->txbitmap) {
- printk(KERN_WARNING "%s: No channel wants data "
- "in TX IRQ. Expect DMA timeout.",
+ pr_warn("%s: No channel wants data in TX IRQ. Expect DMA timeout.\n",
cosa->name);
put_driver_status_nolock(cosa);
clear_bit(TXBIT, &cosa->rxtx);
@@ -1780,14 +1768,14 @@
if (cosa->busmaster) {
unsigned long addr = virt_to_bus(cosa->txbuf);
int count=0;
- printk(KERN_INFO "busmaster IRQ\n");
+ pr_info("busmaster IRQ\n");
while (!(cosa_getstatus(cosa)&SR_TX_RDY)) {
count++;
udelay(10);
if (count > 1000) break;
}
- printk(KERN_INFO "status %x\n", cosa_getstatus(cosa));
- printk(KERN_INFO "ready after %d loops\n", count);
+ pr_info("status %x\n", cosa_getstatus(cosa));
+ pr_info("ready after %d loops\n", count);
cosa_putdata16(cosa, (addr >> 16)&0xffff);
count = 0;
@@ -1796,7 +1784,7 @@
if (count > 1000) break;
udelay(10);
}
- printk(KERN_INFO "ready after %d loops\n", count);
+ pr_info("ready after %d loops\n", count);
cosa_putdata16(cosa, addr &0xffff);
flags1 = claim_dma_lock();
set_dma_mode(cosa->dma, DMA_MODE_CASCADE);
@@ -1824,7 +1812,7 @@
{
unsigned long flags;
#ifdef DEBUG_IRQS
- printk(KERN_INFO "cosa%d: SR_UP_REQUEST\n", cosa->num);
+ pr_info("cosa%d: SR_UP_REQUEST\n", cosa->num);
#endif
spin_lock_irqsave(&cosa->lock, flags);
@@ -1847,7 +1835,7 @@
debug_data_in(cosa, cosa->rxsize & 0xff);
#endif
#if 0
- printk(KERN_INFO "cosa%d: receive rxsize = (0x%04x).\n",
+ pr_info("cosa%d: receive rxsize = (0x%04x)\n",
cosa->num, cosa->rxsize);
#endif
}
@@ -1857,12 +1845,12 @@
debug_data_in(cosa, cosa->rxsize);
#endif
#if 0
- printk(KERN_INFO "cosa%d: receive rxsize = (0x%04x).\n",
+ pr_info("cosa%d: receive rxsize = (0x%04x)\n",
cosa->num, cosa->rxsize);
#endif
}
if (((cosa->rxsize & 0xe000) >> 13) >= cosa->nchannels) {
- printk(KERN_WARNING "%s: rx for unknown channel (0x%04x)\n",
+ pr_warn("%s: rx for unknown channel (0x%04x)\n",
cosa->name, cosa->rxsize);
spin_unlock_irqrestore(&cosa->lock, flags);
goto reject;
@@ -1877,7 +1865,7 @@
if (!cosa->rxbuf) {
reject: /* Reject the packet */
- printk(KERN_INFO "cosa%d: rejecting packet on channel %d\n",
+ pr_info("cosa%d: rejecting packet on channel %d\n",
cosa->num, cosa->rxchan->num);
cosa->rxbuf = cosa->bouncebuf;
}
@@ -1924,11 +1912,11 @@
#ifdef DEBUG_DATA
{
int i;
- printk(KERN_INFO "cosa%dc%d: done rx(0x%x)", cosa->num,
- cosa->rxchan->num, cosa->rxsize);
+ pr_info("cosa%dc%d: done rx(0x%x)",
+ cosa->num, cosa->rxchan->num, cosa->rxsize);
for (i=0; i<cosa->rxsize; i++)
- printk (" %02x", cosa->rxbuf[i]&0xff);
- printk("\n");
+ pr_cont(" %02x", cosa->rxbuf[i]&0xff);
+ pr_cont("\n");
}
#endif
/* Packet for unknown channel? */
@@ -1940,8 +1928,7 @@
if (cosa->rxchan->rx_done(cosa->rxchan))
clear_bit(cosa->rxchan->num, &cosa->rxbitmap);
} else {
- printk(KERN_NOTICE "cosa%d: unexpected EOT interrupt\n",
- cosa->num);
+ pr_notice("cosa%d: unexpected EOT interrupt\n", cosa->num);
}
/*
* Clear the RXBIT, TXBIT and IRQBIT (the latest should be
@@ -1963,8 +1950,7 @@
again:
status = cosa_getstatus(cosa);
#ifdef DEBUG_IRQS
- printk(KERN_INFO "cosa%d: got IRQ, status 0x%02x\n", cosa->num,
- status & 0xff);
+ pr_info("cosa%d: got IRQ, status 0x%02x\n", cosa->num, status & 0xff);
#endif
#ifdef DEBUG_IO
debug_status_in(cosa, status);
@@ -1985,15 +1971,15 @@
udelay(100);
goto again;
}
- printk(KERN_INFO "cosa%d: unknown status 0x%02x in IRQ after %d retries\n",
+ pr_info("cosa%d: unknown status 0x%02x in IRQ after %d retries\n",
cosa->num, status & 0xff, count);
}
#ifdef DEBUG_IRQS
if (count)
- printk(KERN_INFO "%s: %d-times got unknown status in IRQ\n",
+ pr_info("%s: %d-times got unknown status in IRQ\n",
cosa->name, count);
else
- printk(KERN_INFO "%s: returning from IRQ\n", cosa->name);
+ pr_info("%s: returning from IRQ\n", cosa->name);
#endif
return IRQ_HANDLED;
}
@@ -2024,41 +2010,41 @@
s = "NO_REQ";
break;
}
- printk(KERN_INFO "%s: IO: status -> 0x%02x (%s%s%s%s)\n",
+ pr_info("%s: IO: status -> 0x%02x (%s%s%s%s)\n",
cosa->name,
status,
- status & SR_USR_RQ ? "USR_RQ|":"",
- status & SR_TX_RDY ? "TX_RDY|":"",
- status & SR_RX_RDY ? "RX_RDY|":"",
+ status & SR_USR_RQ ? "USR_RQ|" : "",
+ status & SR_TX_RDY ? "TX_RDY|" : "",
+ status & SR_RX_RDY ? "RX_RDY|" : "",
s);
}
static void debug_status_out(struct cosa_data *cosa, int status)
{
- printk(KERN_INFO "%s: IO: status <- 0x%02x (%s%s%s%s%s%s)\n",
+ pr_info("%s: IO: status <- 0x%02x (%s%s%s%s%s%s)\n",
cosa->name,
status,
- status & SR_RX_DMA_ENA ? "RXDMA|":"!rxdma|",
- status & SR_TX_DMA_ENA ? "TXDMA|":"!txdma|",
- status & SR_RST ? "RESET|":"",
- status & SR_USR_INT_ENA ? "USRINT|":"!usrint|",
- status & SR_TX_INT_ENA ? "TXINT|":"!txint|",
- status & SR_RX_INT_ENA ? "RXINT":"!rxint");
+ status & SR_RX_DMA_ENA ? "RXDMA|" : "!rxdma|",
+ status & SR_TX_DMA_ENA ? "TXDMA|" : "!txdma|",
+ status & SR_RST ? "RESET|" : "",
+ status & SR_USR_INT_ENA ? "USRINT|" : "!usrint|",
+ status & SR_TX_INT_ENA ? "TXINT|" : "!txint|",
+ status & SR_RX_INT_ENA ? "RXINT" : "!rxint");
}
static void debug_data_in(struct cosa_data *cosa, int data)
{
- printk(KERN_INFO "%s: IO: data -> 0x%04x\n", cosa->name, data);
+ pr_info("%s: IO: data -> 0x%04x\n", cosa->name, data);
}
static void debug_data_out(struct cosa_data *cosa, int data)
{
- printk(KERN_INFO "%s: IO: data <- 0x%04x\n", cosa->name, data);
+ pr_info("%s: IO: data <- 0x%04x\n", cosa->name, data);
}
static void debug_data_cmd(struct cosa_data *cosa, int data)
{
- printk(KERN_INFO "%s: IO: data <- 0x%04x (%s|%s)\n",
+ pr_info("%s: IO: data <- 0x%04x (%s|%s)\n",
cosa->name, data,
data & SR_RDY_RCV ? "RX_RDY" : "!rx_rdy",
data & SR_RDY_SND ? "TX_RDY" : "!tx_rdy");
diff --git a/drivers/net/wan/cycx_drv.c b/drivers/net/wan/cycx_drv.c
index 164c362..2a3ecae 100644
--- a/drivers/net/wan/cycx_drv.c
+++ b/drivers/net/wan/cycx_drv.c
@@ -48,6 +48,8 @@
* Aug 8, 1998 acme Initial version.
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/init.h> /* __init */
#include <linux/module.h>
#include <linux/kernel.h> /* printk(), and other useful stuff */
@@ -81,10 +83,9 @@
/* Global Data */
/* private data */
-static const char modname[] = "cycx_drv";
static const char fullname[] = "Cyclom 2X Support Module";
-static const char copyright[] = "(c) 1998-2003 Arnaldo Carvalho de Melo "
- "<acme@conectiva.com.br>";
+static const char copyright[] =
+ "(c) 1998-2003 Arnaldo Carvalho de Melo <acme@conectiva.com.br>";
/* Hardware configuration options.
* These are arrays of configuration options used by verification routines.
@@ -110,8 +111,8 @@
static int __init cycx_drv_init(void)
{
- printk(KERN_INFO "%s v%u.%u %s\n", fullname, MOD_VERSION, MOD_RELEASE,
- copyright);
+ pr_info("%s v%u.%u %s\n",
+ fullname, MOD_VERSION, MOD_RELEASE, copyright);
return 0;
}
@@ -139,18 +140,16 @@
/* Verify IRQ configuration options */
if (!get_option_index(cycx_2x_irq_options, hw->irq)) {
- printk(KERN_ERR "%s: IRQ %d is invalid!\n", modname, hw->irq);
+ pr_err("IRQ %d is invalid!\n", hw->irq);
return -EINVAL;
}
/* Setup adapter dual-port memory window and test memory */
if (!dpmbase) {
- printk(KERN_ERR "%s: you must specify the dpm address!\n",
- modname);
+ pr_err("you must specify the dpm address!\n");
return -EINVAL;
} else if (!get_option_index(cyc2x_dpmbase_options, dpmbase)) {
- printk(KERN_ERR "%s: memory address 0x%lX is invalid!\n",
- modname, dpmbase);
+ pr_err("memory address 0x%lX is invalid!\n", dpmbase);
return -EINVAL;
}
@@ -158,13 +157,12 @@
hw->dpmsize = CYCX_WINDOWSIZE;
if (!detect_cyc2x(hw->dpmbase)) {
- printk(KERN_ERR "%s: adapter Cyclom 2X not found at "
- "address 0x%lX!\n", modname, dpmbase);
+ pr_err("adapter Cyclom 2X not found at address 0x%lX!\n",
+ dpmbase);
return -EINVAL;
}
- printk(KERN_INFO "%s: found Cyclom 2X card at address 0x%lX.\n",
- modname, dpmbase);
+ pr_info("found Cyclom 2X card at address 0x%lX\n", dpmbase);
/* Load firmware. If loader fails then shut down adapter */
err = load_cyc2x(hw, cfm, len);
@@ -339,7 +337,7 @@
for (i = 0 ; i < len ; i += CFM_LOAD_BUFSZ)
if (buffer_load(addr, code + i,
min_t(u32, CFM_LOAD_BUFSZ, (len - i))) < 0) {
- printk(KERN_ERR "%s: Error !!\n", modname);
+ pr_err("Error !!\n");
return -1;
}
@@ -370,7 +368,7 @@
for (i = 0 ; i < len ; i += CFM_LOAD_BUFSZ)
if (buffer_load(addr, code + i,
min_t(u32, CFM_LOAD_BUFSZ, (len - i)))) {
- printk(KERN_ERR "%s: Error !!\n", modname);
+ pr_err("Error !!\n");
return -1;
}
@@ -391,23 +389,20 @@
u16 cksum;
/* Announce */
- printk(KERN_INFO "%s: firmware signature=\"%s\"\n", modname,
- cfm->signature);
+ pr_info("firmware signature=\"%s\"\n", cfm->signature);
/* Verify firmware signature */
if (strcmp(cfm->signature, CFM_SIGNATURE)) {
- printk(KERN_ERR "%s:load_cyc2x: not Cyclom-2X firmware!\n",
- modname);
+ pr_err("load_cyc2x: not Cyclom-2X firmware!\n");
return -EINVAL;
}
- printk(KERN_INFO "%s: firmware version=%u\n", modname, cfm->version);
+ pr_info("firmware version=%u\n", cfm->version);
/* Verify firmware module format version */
if (cfm->version != CFM_VERSION) {
- printk(KERN_ERR "%s:%s: firmware format %u rejected! "
- "Expecting %u.\n",
- modname, __func__, cfm->version, CFM_VERSION);
+ pr_err("%s: firmware format %u rejected! Expecting %u.\n",
+ __func__, cfm->version, CFM_VERSION);
return -EINVAL;
}
@@ -419,23 +414,22 @@
if (((len - sizeof(struct cycx_firmware) - 1) != cfm->info.codesize) ||
*/
if (cksum != cfm->checksum) {
- printk(KERN_ERR "%s:%s: firmware corrupted!\n",
- modname, __func__);
- printk(KERN_ERR " cdsize = 0x%x (expected 0x%lx)\n",
- len - (int)sizeof(struct cycx_firmware) - 1,
- cfm->info.codesize);
- printk(KERN_ERR " chksum = 0x%x (expected 0x%x)\n",
- cksum, cfm->checksum);
+ pr_err("%s: firmware corrupted!\n", __func__);
+ pr_err(" cdsize = 0x%x (expected 0x%lx)\n",
+ len - (int)sizeof(struct cycx_firmware) - 1,
+ cfm->info.codesize);
+ pr_err(" chksum = 0x%x (expected 0x%x)\n",
+ cksum, cfm->checksum);
return -EINVAL;
}
/* If everything is ok, set reset, data and code pointers */
img_hdr = (struct cycx_fw_header *)&cfm->image;
#ifdef FIRMWARE_DEBUG
- printk(KERN_INFO "%s:%s: image sizes\n", __func__, modname);
- printk(KERN_INFO " reset=%lu\n", img_hdr->reset_size);
- printk(KERN_INFO " data=%lu\n", img_hdr->data_size);
- printk(KERN_INFO " code=%lu\n", img_hdr->code_size);
+ pr_info("%s: image sizes\n", __func__);
+ pr_info(" reset=%lu\n", img_hdr->reset_size);
+ pr_info(" data=%lu\n", img_hdr->data_size);
+ pr_info(" code=%lu\n", img_hdr->code_size);
#endif
reset_image = ((u8 *)img_hdr) + sizeof(struct cycx_fw_header);
data_image = reset_image + img_hdr->reset_size;
@@ -443,15 +437,14 @@
/*---- Start load ----*/
/* Announce */
- printk(KERN_INFO "%s: loading firmware %s (ID=%u)...\n", modname,
- cfm->descr[0] ? cfm->descr : "unknown firmware",
- cfm->info.codeid);
+ pr_info("loading firmware %s (ID=%u)...\n",
+ cfm->descr[0] ? cfm->descr : "unknown firmware",
+ cfm->info.codeid);
for (i = 0 ; i < 5 ; i++) {
/* Reset Cyclom hardware */
if (!reset_cyc2x(hw->dpmbase)) {
- printk(KERN_ERR "%s: dpm problem or board not found\n",
- modname);
+ pr_err("dpm problem or board not found\n");
return -EINVAL;
}
@@ -468,19 +461,19 @@
msleep_interruptible(1 * 1000);
}
- printk(KERN_ERR "%s: reset not started.\n", modname);
+ pr_err("reset not started\n");
return -EINVAL;
reset_loaded:
/* Load data.bin */
if (cycx_data_boot(hw->dpmbase, data_image, img_hdr->data_size)) {
- printk(KERN_ERR "%s: cannot load data file.\n", modname);
+ pr_err("cannot load data file\n");
return -EINVAL;
}
/* Load code.bin */
if (cycx_code_boot(hw->dpmbase, code_image, img_hdr->code_size)) {
- printk(KERN_ERR "%s: cannot load code file.\n", modname);
+ pr_err("cannot load code file\n");
return -EINVAL;
}
@@ -493,7 +486,7 @@
/* Arthur Ganzert's tip: wait a while after the firmware loading...
seg abr 26 17:17:12 EST 1999 - acme */
msleep_interruptible(7 * 1000);
- printk(KERN_INFO "%s: firmware loaded!\n", modname);
+ pr_info("firmware loaded!\n");
/* enable interrupts */
cycx_inten(hw);
diff --git a/drivers/net/wan/cycx_main.c b/drivers/net/wan/cycx_main.c
index 859dba9..81fbbad 100644
--- a/drivers/net/wan/cycx_main.c
+++ b/drivers/net/wan/cycx_main.c
@@ -40,6 +40,8 @@
* 1998/08/08 acme Initial version.
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/stddef.h> /* offsetof(), etc. */
#include <linux/errno.h> /* return codes */
#include <linux/string.h> /* inline memset(), etc. */
@@ -50,6 +52,7 @@
#include <linux/wanrouter.h> /* WAN router definitions */
#include <linux/cyclomx.h> /* cyclomx common user API definitions */
#include <linux/init.h> /* __init (when not using as a module) */
+#include <linux/interrupt.h>
unsigned int cycx_debug;
@@ -106,7 +109,7 @@
{
int cnt, err = -ENOMEM;
- printk(KERN_INFO "%s v%u.%u %s\n",
+ pr_info("%s v%u.%u %s\n",
cycx_fullname, CYCX_DRV_VERSION, CYCX_DRV_RELEASE,
cycx_copyright);
@@ -132,9 +135,8 @@
err = register_wan_device(wandev);
if (err) {
- printk(KERN_ERR "%s: %s registration failed with "
- "error %d!\n",
- cycx_drvname, card->devname, err);
+ pr_err("%s registration failed with error %d!\n",
+ card->devname, err);
break;
}
}
@@ -197,14 +199,13 @@
rc = -EINVAL;
if (!conf->data_size || !conf->data) {
- printk(KERN_ERR "%s: firmware not found in configuration "
- "data!\n", wandev->name);
+ pr_err("%s: firmware not found in configuration data!\n",
+ wandev->name);
goto out;
}
if (conf->irq <= 0) {
- printk(KERN_ERR "%s: can't configure without IRQ!\n",
- wandev->name);
+ pr_err("%s: can't configure without IRQ!\n", wandev->name);
goto out;
}
@@ -212,8 +213,7 @@
irq = conf->irq == 2 ? 9 : conf->irq; /* IRQ2 -> IRQ9 */
if (request_irq(irq, cycx_isr, 0, wandev->name, card)) {
- printk(KERN_ERR "%s: can't reserve IRQ %d!\n",
- wandev->name, irq);
+ pr_err("%s: can't reserve IRQ %d!\n", wandev->name, irq);
goto out;
}
@@ -245,8 +245,7 @@
break;
#endif
default:
- printk(KERN_ERR "%s: this firmware is not supported!\n",
- wandev->name);
+ pr_err("%s: this firmware is not supported!\n", wandev->name);
rc = -EINVAL;
}
@@ -287,8 +286,7 @@
card = wandev->private;
wandev->state = WAN_UNCONFIGURED;
cycx_down(&card->hw);
- printk(KERN_INFO "%s: irq %d being freed!\n", wandev->name,
- wandev->irq);
+ pr_info("%s: irq %d being freed!\n", wandev->name, wandev->irq);
free_irq(wandev->irq, card);
out: return ret;
}
@@ -307,8 +305,8 @@
goto out;
if (card->in_isr) {
- printk(KERN_WARNING "%s: interrupt re-entrancy on IRQ %d!\n",
- card->devname, card->wandev.irq);
+ pr_warn("%s: interrupt re-entrancy on IRQ %d!\n",
+ card->devname, card->wandev.irq);
goto out;
}
@@ -336,7 +334,7 @@
string_state = "disconnected!";
break;
}
- printk(KERN_INFO "%s: link %s\n", card->devname, string_state);
+ pr_info("%s: link %s\n", card->devname, string_state);
card->wandev.state = state;
}
diff --git a/drivers/net/wan/cycx_x25.c b/drivers/net/wan/cycx_x25.c
index cf9e15f..06f3f63 100644
--- a/drivers/net/wan/cycx_x25.c
+++ b/drivers/net/wan/cycx_x25.c
@@ -76,6 +76,8 @@
* 1998/08/08 acme Initial version.
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#define CYCLOMX_X25_DEBUG 1
#include <linux/ctype.h> /* isdigit() */
@@ -230,8 +232,8 @@
/* Verify configuration ID */
if (conf->config_id != WANCONFIG_X25) {
- printk(KERN_INFO "%s: invalid configuration ID %u!\n",
- card->devname, conf->config_id);
+ pr_info("%s: invalid configuration ID %u!\n",
+ card->devname, conf->config_id);
return -EINVAL;
}
@@ -374,8 +376,7 @@
int err = 0;
if (!conf->name[0] || strlen(conf->name) > WAN_IFNAME_SZ) {
- printk(KERN_INFO "%s: invalid interface name!\n",
- card->devname);
+ pr_info("%s: invalid interface name!\n", card->devname);
return -EINVAL;
}
@@ -398,8 +399,8 @@
if (len) {
if (len > WAN_ADDRESS_SZ) {
- printk(KERN_ERR "%s: %s local addr too long!\n",
- wandev->name, chan->name);
+ pr_err("%s: %s local addr too long!\n",
+ wandev->name, chan->name);
err = -EINVAL;
goto error;
} else {
@@ -429,15 +430,14 @@
if (lcn >= card->u.x.lo_pvc && lcn <= card->u.x.hi_pvc)
chan->lcn = lcn;
else {
- printk(KERN_ERR
- "%s: PVC %u is out of range on interface %s!\n",
- wandev->name, lcn, chan->name);
+ pr_err("%s: PVC %u is out of range on interface %s!\n",
+ wandev->name, lcn, chan->name);
err = -EINVAL;
goto error;
}
} else {
- printk(KERN_ERR "%s: invalid media address on interface %s!\n",
- wandev->name, chan->name);
+ pr_err("%s: invalid media address on interface %s!\n",
+ wandev->name, chan->name);
err = -EINVAL;
goto error;
}
@@ -607,9 +607,8 @@
++chan->ifstats.tx_dropped;
else if (chan->svc && chan->protocol &&
chan->protocol != ntohs(skb->protocol)) {
- printk(KERN_INFO
- "%s: unsupported Ethertype 0x%04X on interface %s!\n",
- card->devname, ntohs(skb->protocol), dev->name);
+ pr_info("%s: unsupported Ethertype 0x%04X on interface %s!\n",
+ card->devname, ntohs(skb->protocol), dev->name);
++chan->ifstats.tx_errors;
} else if (chan->protocol == ETH_P_IP) {
switch (chan->state) {
@@ -643,9 +642,8 @@
cycx_x25_chan_disconnect(dev);
goto free_packet;
default:
- printk(KERN_INFO
- "%s: unknown %d x25-iface request on %s!\n",
- card->devname, skb->data[0], dev->name);
+ pr_info("%s: unknown %d x25-iface request on %s!\n",
+ card->devname, skb->data[0], dev->name);
++chan->ifstats.tx_errors;
goto free_packet;
}
@@ -746,8 +744,7 @@
card->buff_int_mode_unbusy = 1;
netif_wake_queue(dev);
} else
- printk(KERN_ERR "%s:ackvc for inexistent lcn %d\n",
- card->devname, lcn);
+ pr_err("%s:ackvc for inexistent lcn %d\n", card->devname, lcn);
}
/* Receive interrupt handler.
@@ -780,8 +777,8 @@
dev = cycx_x25_get_dev_by_lcn(wandev, lcn);
if (!dev) {
/* Invalid channel, discard packet */
- printk(KERN_INFO "%s: receiving on orphaned LCN %d!\n",
- card->devname, lcn);
+ pr_info("%s: receiving on orphaned LCN %d!\n",
+ card->devname, lcn);
return;
}
@@ -802,8 +799,8 @@
if ((skb = dev_alloc_skb((chan->protocol == ETH_P_X25 ? 1 : 0) +
bufsize +
dev->hard_header_len)) == NULL) {
- printk(KERN_INFO "%s: no socket buffers available!\n",
- card->devname);
+ pr_info("%s: no socket buffers available!\n",
+ card->devname);
chan->drop_sequence = 1;
++chan->ifstats.rx_dropped;
return;
@@ -826,8 +823,8 @@
if (bitm)
chan->drop_sequence = 1;
- printk(KERN_INFO "%s: unexpectedly long packet sequence "
- "on interface %s!\n", card->devname, dev->name);
+ pr_info("%s: unexpectedly long packet sequence on interface %s!\n",
+ card->devname, dev->name);
++chan->ifstats.rx_length_errors;
return;
}
@@ -880,8 +877,8 @@
dev = cycx_x25_get_dev_by_dte_addr(wandev, rem);
if (!dev) {
/* Invalid channel, discard packet */
- printk(KERN_INFO "%s: connect not expected: remote %s!\n",
- card->devname, rem);
+ pr_info("%s: connect not expected: remote %s!\n",
+ card->devname, rem);
return;
}
@@ -909,8 +906,8 @@
if (!dev) {
/* Invalid channel, discard packet */
clear_bit(--key, (void*)&card->u.x.connection_keys);
- printk(KERN_INFO "%s: connect confirm not expected: lcn %d, "
- "key=%d!\n", card->devname, lcn, key);
+ pr_info("%s: connect confirm not expected: lcn %d, key=%d!\n",
+ card->devname, lcn, key);
return;
}
@@ -934,8 +931,8 @@
dev = cycx_x25_get_dev_by_lcn(wandev, lcn);
if (!dev) {
/* Invalid channel, discard packet */
- printk(KERN_INFO "%s:disconnect confirm not expected!:lcn %d\n",
- card->devname, lcn);
+ pr_info("%s:disconnect confirm not expected!:lcn %d\n",
+ card->devname, lcn);
return;
}
@@ -980,13 +977,13 @@
cycx_peek(&card->hw, cmd->buf + 10 + toread, &code, 1);
cycx_peek(&card->hw, cmd->buf + 10 + toread + 1, &routine, 1);
- printk(KERN_INFO "cycx_x25_irq_handler: X25_LOG (0x4500) indic.:\n");
- printk(KERN_INFO "cmd->buf=0x%X\n", cmd->buf);
- printk(KERN_INFO "Log message code=0x%X\n", msg_code);
- printk(KERN_INFO "Link=%d\n", link);
- printk(KERN_INFO "log code=0x%X\n", code);
- printk(KERN_INFO "log routine=0x%X\n", routine);
- printk(KERN_INFO "Message size=%d\n", size);
+ pr_info("cycx_x25_irq_handler: X25_LOG (0x4500) indic.:\n");
+ pr_info("cmd->buf=0x%X\n", cmd->buf);
+ pr_info("Log message code=0x%X\n", msg_code);
+ pr_info("Link=%d\n", link);
+ pr_info("log code=0x%X\n", code);
+ pr_info("log routine=0x%X\n", routine);
+ pr_info("Message size=%d\n", size);
hex_dump("Message", bf, toread);
#endif
}
@@ -1009,24 +1006,14 @@
static void cycx_x25_irq_spurious(struct cycx_device *card,
struct cycx_x25_cmd *cmd)
{
- printk(KERN_INFO "%s: spurious interrupt (0x%X)!\n",
- card->devname, cmd->command);
+ pr_info("%s: spurious interrupt (0x%X)!\n",
+ card->devname, cmd->command);
}
#ifdef CYCLOMX_X25_DEBUG
static void hex_dump(char *msg, unsigned char *p, int len)
{
- unsigned char hex[1024],
- * phex = hex;
-
- if (len >= (sizeof(hex) / 2))
- len = (sizeof(hex) / 2) - 1;
-
- while (len--) {
- sprintf(phex, "%02x", *p++);
- phex += 2;
- }
-
- printk(KERN_INFO "%s: %s\n", msg, hex);
+ print_hex_dump(KERN_INFO, msg, DUMP_PREFIX_OFFSET, 16, 1,
+ p, len, true);
}
#endif
@@ -1203,8 +1190,8 @@
u8 key;
if (card->u.x.connection_keys == ~0U) {
- printk(KERN_INFO "%s: too many simultaneous connection "
- "requests!\n", card->devname);
+ pr_info("%s: too many simultaneous connection requests!\n",
+ card->devname);
return -EAGAIN;
}
@@ -1381,8 +1368,8 @@
if (chan->state == WAN_CONNECTED)
cycx_x25_chan_disconnect(dev);
else
- printk(KERN_ERR "%s: %s for svc (%s) not connected!\n",
- chan->card->devname, __func__, dev->name);
+ pr_err("%s: %s for svc (%s) not connected!\n",
+ chan->card->devname, __func__, dev->name);
}
/* Set logical channel state. */
@@ -1433,8 +1420,8 @@
break;
}
- printk(KERN_INFO "%s: interface %s %s\n", card->devname,
- dev->name, string_state);
+ pr_info("%s: interface %s %s\n",
+ card->devname, dev->name, string_state);
chan->state = state;
}
@@ -1488,7 +1475,7 @@
unsigned char *ptr;
if ((skb = dev_alloc_skb(1)) == NULL) {
- printk(KERN_ERR "%s: out of memory\n", __func__);
+ pr_err("%s: out of memory\n", __func__);
return;
}
@@ -1557,56 +1544,56 @@
#ifdef CYCLOMX_X25_DEBUG
static void cycx_x25_dump_config(struct cycx_x25_config *conf)
{
- printk(KERN_INFO "X.25 configuration\n");
- printk(KERN_INFO "-----------------\n");
- printk(KERN_INFO "link number=%d\n", conf->link);
- printk(KERN_INFO "line speed=%d\n", conf->speed);
- printk(KERN_INFO "clock=%sternal\n", conf->clock == 8 ? "Ex" : "In");
- printk(KERN_INFO "# level 2 retransm.=%d\n", conf->n2);
- printk(KERN_INFO "level 2 window=%d\n", conf->n2win);
- printk(KERN_INFO "level 3 window=%d\n", conf->n3win);
- printk(KERN_INFO "# logical channels=%d\n", conf->nvc);
- printk(KERN_INFO "level 3 pkt len=%d\n", conf->pktlen);
- printk(KERN_INFO "my address=%d\n", conf->locaddr);
- printk(KERN_INFO "remote address=%d\n", conf->remaddr);
- printk(KERN_INFO "t1=%d seconds\n", conf->t1);
- printk(KERN_INFO "t2=%d seconds\n", conf->t2);
- printk(KERN_INFO "t21=%d seconds\n", conf->t21);
- printk(KERN_INFO "# PVCs=%d\n", conf->npvc);
- printk(KERN_INFO "t23=%d seconds\n", conf->t23);
- printk(KERN_INFO "flags=0x%x\n", conf->flags);
+ pr_info("X.25 configuration\n");
+ pr_info("-----------------\n");
+ pr_info("link number=%d\n", conf->link);
+ pr_info("line speed=%d\n", conf->speed);
+ pr_info("clock=%sternal\n", conf->clock == 8 ? "Ex" : "In");
+ pr_info("# level 2 retransm.=%d\n", conf->n2);
+ pr_info("level 2 window=%d\n", conf->n2win);
+ pr_info("level 3 window=%d\n", conf->n3win);
+ pr_info("# logical channels=%d\n", conf->nvc);
+ pr_info("level 3 pkt len=%d\n", conf->pktlen);
+ pr_info("my address=%d\n", conf->locaddr);
+ pr_info("remote address=%d\n", conf->remaddr);
+ pr_info("t1=%d seconds\n", conf->t1);
+ pr_info("t2=%d seconds\n", conf->t2);
+ pr_info("t21=%d seconds\n", conf->t21);
+ pr_info("# PVCs=%d\n", conf->npvc);
+ pr_info("t23=%d seconds\n", conf->t23);
+ pr_info("flags=0x%x\n", conf->flags);
}
static void cycx_x25_dump_stats(struct cycx_x25_stats *stats)
{
- printk(KERN_INFO "X.25 statistics\n");
- printk(KERN_INFO "--------------\n");
- printk(KERN_INFO "rx_crc_errors=%d\n", stats->rx_crc_errors);
- printk(KERN_INFO "rx_over_errors=%d\n", stats->rx_over_errors);
- printk(KERN_INFO "n2_tx_frames=%d\n", stats->n2_tx_frames);
- printk(KERN_INFO "n2_rx_frames=%d\n", stats->n2_rx_frames);
- printk(KERN_INFO "tx_timeouts=%d\n", stats->tx_timeouts);
- printk(KERN_INFO "rx_timeouts=%d\n", stats->rx_timeouts);
- printk(KERN_INFO "n3_tx_packets=%d\n", stats->n3_tx_packets);
- printk(KERN_INFO "n3_rx_packets=%d\n", stats->n3_rx_packets);
- printk(KERN_INFO "tx_aborts=%d\n", stats->tx_aborts);
- printk(KERN_INFO "rx_aborts=%d\n", stats->rx_aborts);
+ pr_info("X.25 statistics\n");
+ pr_info("--------------\n");
+ pr_info("rx_crc_errors=%d\n", stats->rx_crc_errors);
+ pr_info("rx_over_errors=%d\n", stats->rx_over_errors);
+ pr_info("n2_tx_frames=%d\n", stats->n2_tx_frames);
+ pr_info("n2_rx_frames=%d\n", stats->n2_rx_frames);
+ pr_info("tx_timeouts=%d\n", stats->tx_timeouts);
+ pr_info("rx_timeouts=%d\n", stats->rx_timeouts);
+ pr_info("n3_tx_packets=%d\n", stats->n3_tx_packets);
+ pr_info("n3_rx_packets=%d\n", stats->n3_rx_packets);
+ pr_info("tx_aborts=%d\n", stats->tx_aborts);
+ pr_info("rx_aborts=%d\n", stats->rx_aborts);
}
static void cycx_x25_dump_devs(struct wan_device *wandev)
{
struct net_device *dev = wandev->dev;
- printk(KERN_INFO "X.25 dev states\n");
- printk(KERN_INFO "name: addr: txoff: protocol:\n");
- printk(KERN_INFO "---------------------------------------\n");
+ pr_info("X.25 dev states\n");
+ pr_info("name: addr: txoff: protocol:\n");
+ pr_info("---------------------------------------\n");
while(dev) {
struct cycx_x25_channel *chan = netdev_priv(dev);
- printk(KERN_INFO "%-5.5s %-15.15s %d ETH_P_%s\n",
- chan->name, chan->addr, netif_queue_stopped(dev),
- chan->protocol == ETH_P_IP ? "IP" : "X25");
+ pr_info("%-5.5s %-15.15s %d ETH_P_%s\n",
+ chan->name, chan->addr, netif_queue_stopped(dev),
+ chan->protocol == ETH_P_IP ? "IP" : "X25");
dev = chan->slave;
}
}
diff --git a/drivers/net/wan/dlci.c b/drivers/net/wan/dlci.c
index 21b104d..48ab38a 100644
--- a/drivers/net/wan/dlci.c
+++ b/drivers/net/wan/dlci.c
@@ -28,6 +28,8 @@
* 2 of the License, or (at your option) any later version.
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/types.h>
@@ -112,8 +114,7 @@
dlp = netdev_priv(dev);
if (!pskb_may_pull(skb, sizeof(*hdr))) {
- printk(KERN_NOTICE "%s: invalid data no header\n",
- dev->name);
+ netdev_notice(dev, "invalid data no header\n");
dev->stats.rx_errors++;
kfree_skb(skb);
return;
@@ -126,7 +127,8 @@
if (hdr->control != FRAD_I_UI)
{
- printk(KERN_NOTICE "%s: Invalid header flag 0x%02X.\n", dev->name, hdr->control);
+ netdev_notice(dev, "Invalid header flag 0x%02X\n",
+ hdr->control);
dev->stats.rx_errors++;
}
else
@@ -135,14 +137,18 @@
case FRAD_P_PADDING:
if (hdr->NLPID != FRAD_P_SNAP)
{
- printk(KERN_NOTICE "%s: Unsupported NLPID 0x%02X.\n", dev->name, hdr->NLPID);
+ netdev_notice(dev, "Unsupported NLPID 0x%02X\n",
+ hdr->NLPID);
dev->stats.rx_errors++;
break;
}
if (hdr->OUI[0] + hdr->OUI[1] + hdr->OUI[2] != 0)
{
- printk(KERN_NOTICE "%s: Unsupported organizationally unique identifier 0x%02X-%02X-%02X.\n", dev->name, hdr->OUI[0], hdr->OUI[1], hdr->OUI[2]);
+ netdev_notice(dev, "Unsupported organizationally unique identifier 0x%02X-%02X-%02X\n",
+ hdr->OUI[0],
+ hdr->OUI[1],
+ hdr->OUI[2]);
dev->stats.rx_errors++;
break;
}
@@ -163,12 +169,14 @@
case FRAD_P_SNAP:
case FRAD_P_Q933:
case FRAD_P_CLNP:
- printk(KERN_NOTICE "%s: Unsupported NLPID 0x%02X.\n", dev->name, hdr->pad);
+ netdev_notice(dev, "Unsupported NLPID 0x%02X\n",
+ hdr->pad);
dev->stats.rx_errors++;
break;
default:
- printk(KERN_NOTICE "%s: Invalid pad byte 0x%02X.\n", dev->name, hdr->pad);
+ netdev_notice(dev, "Invalid pad byte 0x%02X\n",
+ hdr->pad);
dev->stats.rx_errors++;
break;
}
diff --git a/drivers/net/wan/dscc4.c b/drivers/net/wan/dscc4.c
index acb9ea8..058e169 100644
--- a/drivers/net/wan/dscc4.c
+++ b/drivers/net/wan/dscc4.c
@@ -80,6 +80,8 @@
* - misc crapectomy.
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/types.h>
@@ -99,6 +101,7 @@
#include <asm/irq.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/string.h>
#include <linux/if_arp.h>
@@ -552,7 +555,7 @@
schedule_timeout_uninterruptible(10);
rmb();
} while (++i > 0);
- printk(KERN_ERR "%s: %s timeout\n", dev->name, msg);
+ netdev_err(dev, "%s timeout\n", msg);
done:
return (i >= 0) ? i : -EAGAIN;
}
@@ -568,18 +571,18 @@
u32 state = readl(ioaddr);
if (state & ArAck) {
- printk(KERN_DEBUG "%s: %s ack\n", dev->name, msg);
+ netdev_dbg(dev, "%s ack\n", msg);
writel(ArAck, ioaddr);
goto done;
} else if (state & Arf) {
- printk(KERN_ERR "%s: %s failed\n", dev->name, msg);
+ netdev_err(dev, "%s failed\n", msg);
writel(Arf, ioaddr);
i = -1;
goto done;
}
rmb();
} while (++i > 0);
- printk(KERN_ERR "%s: %s timeout\n", dev->name, msg);
+ netdev_err(dev, "%s timeout\n", msg);
done:
return i;
}
@@ -635,7 +638,7 @@
writel(MTFi|Rdt, dpriv->base_addr + dpriv->dev_id*0x0c + CH0CFG);
if (dscc4_do_action(dev, "Rdt") < 0)
- printk(KERN_ERR "%s: Tx reset failed\n", dev->name);
+ netdev_err(dev, "Tx reset failed\n");
}
#endif
@@ -721,22 +724,20 @@
rc = pci_request_region(pdev, 0, "registers");
if (rc < 0) {
- printk(KERN_ERR "%s: can't reserve MMIO region (regs)\n",
- DRV_NAME);
+ pr_err("can't reserve MMIO region (regs)\n");
goto err_disable_0;
}
rc = pci_request_region(pdev, 1, "LBI interface");
if (rc < 0) {
- printk(KERN_ERR "%s: can't reserve MMIO region (lbi)\n",
- DRV_NAME);
+ pr_err("can't reserve MMIO region (lbi)\n");
goto err_free_mmio_region_1;
}
ioaddr = pci_ioremap_bar(pdev, 0);
if (!ioaddr) {
- printk(KERN_ERR "%s: cannot remap MMIO region %llx @ %llx\n",
- DRV_NAME, (unsigned long long)pci_resource_len(pdev, 0),
- (unsigned long long)pci_resource_start(pdev, 0));
+ pr_err("cannot remap MMIO region %llx @ %llx\n",
+ (unsigned long long)pci_resource_len(pdev, 0),
+ (unsigned long long)pci_resource_start(pdev, 0));
rc = -EIO;
goto err_free_mmio_regions_2;
}
@@ -756,7 +757,7 @@
rc = request_irq(pdev->irq, dscc4_irq, IRQF_SHARED, DRV_NAME, priv->root);
if (rc < 0) {
- printk(KERN_WARNING "%s: IRQ %d busy\n", DRV_NAME, pdev->irq);
+ pr_warn("IRQ %d busy\n", pdev->irq);
goto err_release_4;
}
@@ -903,7 +904,7 @@
root = kcalloc(dev_per_card, sizeof(*root), GFP_KERNEL);
if (!root) {
- printk(KERN_ERR "%s: can't allocate data\n", DRV_NAME);
+ pr_err("can't allocate data\n");
goto err_out;
}
@@ -915,7 +916,7 @@
ppriv = kzalloc(sizeof(*ppriv), GFP_KERNEL);
if (!ppriv) {
- printk(KERN_ERR "%s: can't allocate private data\n", DRV_NAME);
+ pr_err("can't allocate private data\n");
goto err_free_dev;
}
@@ -951,7 +952,7 @@
ret = register_hdlc_device(d);
if (ret < 0) {
- printk(KERN_ERR "%s: unable to register\n", DRV_NAME);
+ pr_err("unable to register\n");
dscc4_release_ring(dpriv);
goto err_unregister;
}
@@ -1004,7 +1005,7 @@
if (settings->loopback && (settings->clock_type != CLOCK_INT)) {
struct net_device *dev = dscc4_to_dev(dpriv);
- printk(KERN_INFO "%s: loopback requires clock\n", dev->name);
+ netdev_info(dev, "loopback requires clock\n");
return -1;
}
return 0;
@@ -1077,7 +1078,7 @@
scc_patchl(0, PowerUp, dpriv, dev, CCR0);
scc_patchl(0, 0x00050000, dpriv, dev, CCR2);
scc_writel(EventsMask, dpriv, dev, IMR);
- printk(KERN_INFO "%s: up again.\n", dev->name);
+ netdev_info(dev, "up again\n");
goto done;
}
@@ -1094,11 +1095,11 @@
* situations.
*/
if (scc_readl_star(dpriv, dev) & SccBusy) {
- printk(KERN_ERR "%s busy. Try later\n", dev->name);
+ netdev_err(dev, "busy - try later\n");
ret = -EAGAIN;
goto err_out;
} else
- printk(KERN_INFO "%s: available. Good\n", dev->name);
+ netdev_info(dev, "available - good\n");
scc_writel(EventsMask, dpriv, dev, IMR);
@@ -1116,7 +1117,7 @@
* reset is needed. Suggestions anyone ?
*/
if ((ret = dscc4_xpr_ack(dpriv)) < 0) {
- printk(KERN_ERR "%s: %s timeout\n", DRV_NAME, "XPR");
+ pr_err("XPR timeout\n");
goto err_disable_scc_events;
}
@@ -1341,8 +1342,7 @@
return -EPERM;
if (dpriv->flags & FakeReset) {
- printk(KERN_INFO "%s: please reset the device"
- " before this command\n", dev->name);
+ netdev_info(dev, "please reset the device before this command\n");
return -EPERM;
}
if (copy_from_user(&dpriv->settings, line, size))
@@ -1505,8 +1505,7 @@
writel(state, ioaddr + GSTAR);
if (state & Arf) {
- printk(KERN_ERR "%s: failure (Arf). Harass the maintener\n",
- dev->name);
+ netdev_err(dev, "failure (Arf). Harass the maintainer\n");
goto out;
}
state &= ~ArAck;
@@ -1514,7 +1513,7 @@
if (debug > 0)
printk(KERN_DEBUG "%s: CfgIV\n", DRV_NAME);
if (priv->iqcfg[priv->cfg_cur++%IRQ_RING_SIZE] & cpu_to_le32(Arf))
- printk(KERN_ERR "%s: %s failed\n", dev->name, "CFG");
+ netdev_err(dev, "CFG failed\n");
if (!(state &= ~Cfg))
goto out;
}
@@ -1595,8 +1594,8 @@
++dpriv->tx_dirty;
} else {
if (debug > 1)
- printk(KERN_ERR "%s Tx: NULL skb %d\n",
- dev->name, cur);
+ netdev_err(dev, "Tx: NULL skb %d\n",
+ cur);
}
/*
* If the driver ends sending crap on the wire, it
@@ -1615,7 +1614,7 @@
* Transmit Data Underrun
*/
if (state & Xdu) {
- printk(KERN_ERR "%s: XDU. Ask maintainer\n", DRV_NAME);
+ netdev_err(dev, "Tx Data Underrun. Ask maintainer\n");
dpriv->flags = NeedIDT;
/* Tx reset */
writel(MTFi | Rdt,
@@ -1624,13 +1623,13 @@
return;
}
if (state & Cts) {
- printk(KERN_INFO "%s: CTS transition\n", dev->name);
+ netdev_info(dev, "CTS transition\n");
if (!(state &= ~Cts)) /* DEBUG */
goto try;
}
if (state & Xmr) {
/* Frame needs to be sent again - FIXME */
- printk(KERN_ERR "%s: Xmr. Ask maintainer\n", DRV_NAME);
+ netdev_err(dev, "Tx ReTx. Ask maintainer\n");
if (!(state &= ~Xmr)) /* DEBUG */
goto try;
}
@@ -1648,7 +1647,7 @@
break;
}
if (!i)
- printk(KERN_INFO "%s busy in irq\n", dev->name);
+ netdev_info(dev, "busy in irq\n");
scc_addr = dpriv->base_addr + 0x0c*dpriv->dev_id;
/* Keep this order: IDT before IDR */
@@ -1685,7 +1684,7 @@
}
if (state & Cd) {
if (debug > 0)
- printk(KERN_INFO "%s: CD transition\n", dev->name);
+ netdev_info(dev, "CD transition\n");
if (!(state &= ~Cd)) /* DEBUG */
goto try;
}
@@ -1694,11 +1693,11 @@
#ifdef DSCC4_POLLING
while (!dscc4_tx_poll(dpriv, dev));
#endif
- printk(KERN_INFO "%s: Tx Hi\n", dev->name);
+ netdev_info(dev, "Tx Hi\n");
state &= ~Hi;
}
if (state & Err) {
- printk(KERN_INFO "%s: Tx ERR\n", dev->name);
+ netdev_info(dev, "Tx ERR\n");
dev->stats.tx_errors++;
state &= ~Err;
}
@@ -1768,7 +1767,7 @@
goto try;
}
if (state & Hi ) { /* HI bit */
- printk(KERN_INFO "%s: Rx Hi\n", dev->name);
+ netdev_info(dev, "Rx Hi\n");
state &= ~Hi;
goto try;
}
@@ -1799,7 +1798,7 @@
goto try;
}
if (state & Cts) {
- printk(KERN_INFO "%s: CTS transition\n", dev->name);
+ netdev_info(dev, "CTS transition\n");
if (!(state &= ~Cts)) /* DEBUG */
goto try;
}
@@ -1858,14 +1857,12 @@
sizeof(struct RxFD), scc_addr + CH0BRDA);
writel(MTFi|Rdr|Idr, scc_addr + CH0CFG);
if (dscc4_do_action(dev, "RDR") < 0) {
- printk(KERN_ERR "%s: RDO recovery failed(%s)\n",
- dev->name, "RDR");
+ netdev_err(dev, "RDO recovery failed(RDR)\n");
goto rdo_end;
}
writel(MTFi|Idr, scc_addr + CH0CFG);
if (dscc4_do_action(dev, "IDR") < 0) {
- printk(KERN_ERR "%s: RDO recovery failed(%s)\n",
- dev->name, "IDR");
+ netdev_err(dev, "RDO recovery failed(IDR)\n");
goto rdo_end;
}
rdo_end:
@@ -1874,7 +1871,7 @@
goto try;
}
if (state & Cd) {
- printk(KERN_INFO "%s: CD transition\n", dev->name);
+ netdev_info(dev, "CD transition\n");
if (!(state &= ~Cd)) /* DEBUG */
goto try;
}
diff --git a/drivers/net/wan/farsync.c b/drivers/net/wan/farsync.c
index 777d1a4..ebb9f24 100644
--- a/drivers/net/wan/farsync.c
+++ b/drivers/net/wan/farsync.c
@@ -25,6 +25,7 @@
#include <linux/slab.h>
#include <linux/ioport.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/if.h>
#include <linux/hdlc.h>
#include <asm/io.h>
@@ -1664,10 +1665,9 @@
* existing firmware etc so we just report it for the moment.
*/
if (FST_RDL(card, numberOfPorts) != card->nports) {
- pr_warning("Port count mismatch on card %d. "
- "Firmware thinks %d we say %d\n",
- card->card_no,
- FST_RDL(card, numberOfPorts), card->nports);
+ pr_warn("Port count mismatch on card %d. Firmware thinks %d we say %d\n",
+ card->card_no,
+ FST_RDL(card, numberOfPorts), card->nports);
}
}
diff --git a/drivers/net/wan/hd64570.c b/drivers/net/wan/hd64570.c
index a3ea27c..33b67d8 100644
--- a/drivers/net/wan/hd64570.c
+++ b/drivers/net/wan/hd64570.c
@@ -582,8 +582,8 @@
sca_in(DSR_RX(phy_node(port)), card), port->rxin,
sca_in(DSR_RX(phy_node(port)), card) & DSR_DE ? "" : "in");
for (cnt = 0; cnt < port_to_card(port)->rx_ring_buffers; cnt++)
- printk(" %02X", readb(&(desc_address(port, cnt, 0)->stat)));
- printk(KERN_CONT "\n");
+ pr_cont(" %02X", readb(&(desc_address(port, cnt, 0)->stat)));
+ pr_cont("\n");
printk(KERN_DEBUG "TX ring: CDA=%u EDA=%u DSR=%02X in=%u "
"last=%u %sactive",
@@ -593,8 +593,8 @@
sca_in(DSR_TX(phy_node(port)), card) & DSR_DE ? "" : "in");
for (cnt = 0; cnt < port_to_card(port)->tx_ring_buffers; cnt++)
- printk(" %02X", readb(&(desc_address(port, cnt, 1)->stat)));
- printk("\n");
+ pr_cont(" %02X", readb(&(desc_address(port, cnt, 1)->stat)));
+ pr_cont("\n");
printk(KERN_DEBUG "MSCI: MD: %02x %02x %02x, ST: %02x %02x %02x %02x,"
" FST: %02x CST: %02x %02x\n",
diff --git a/drivers/net/wan/hd64572.c b/drivers/net/wan/hd64572.c
index e305274..efc0db1 100644
--- a/drivers/net/wan/hd64572.c
+++ b/drivers/net/wan/hd64572.c
@@ -530,8 +530,8 @@
sca_in(DSR_RX(port->chan), card), port->rxin,
sca_in(DSR_RX(port->chan), card) & DSR_DE ? "" : "in");
for (cnt = 0; cnt < port->card->rx_ring_buffers; cnt++)
- printk(" %02X", readb(&(desc_address(port, cnt, 0)->stat)));
- printk(KERN_CONT "\n");
+ pr_cont(" %02X", readb(&(desc_address(port, cnt, 0)->stat)));
+ pr_cont("\n");
printk(KERN_DEBUG "TX ring: CDA=%u EDA=%u DSR=%02X in=%u "
"last=%u %sactive",
@@ -541,8 +541,8 @@
sca_in(DSR_TX(port->chan), card) & DSR_DE ? "" : "in");
for (cnt = 0; cnt < port->card->tx_ring_buffers; cnt++)
- printk(" %02X", readb(&(desc_address(port, cnt, 1)->stat)));
- printk("\n");
+ pr_cont(" %02X", readb(&(desc_address(port, cnt, 1)->stat)));
+ pr_cont("\n");
printk(KERN_DEBUG "MSCI: MD: %02x %02x %02x,"
" ST: %02x %02x %02x %02x %02x, FST: %02x CST: %02x %02x\n",
diff --git a/drivers/net/wan/hdlc.c b/drivers/net/wan/hdlc.c
index 5d4bb61..10cc7df 100644
--- a/drivers/net/wan/hdlc.c
+++ b/drivers/net/wan/hdlc.c
@@ -22,6 +22,8 @@
* - proto->start() and stop() are called with spin_lock_irq held.
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/errno.h>
#include <linux/hdlc.h>
#include <linux/if_arp.h>
@@ -130,10 +132,10 @@
goto carrier_exit;
if (hdlc->carrier) {
- printk(KERN_INFO "%s: Carrier detected\n", dev->name);
+ netdev_info(dev, "Carrier detected\n");
hdlc_proto_start(dev);
} else {
- printk(KERN_INFO "%s: Carrier lost\n", dev->name);
+ netdev_info(dev, "Carrier lost\n");
hdlc_proto_stop(dev);
}
@@ -165,10 +167,10 @@
spin_lock_irq(&hdlc->state_lock);
if (hdlc->carrier) {
- printk(KERN_INFO "%s: Carrier detected\n", dev->name);
+ netdev_info(dev, "Carrier detected\n");
hdlc_proto_start(dev);
} else
- printk(KERN_INFO "%s: No carrier\n", dev->name);
+ netdev_info(dev, "No carrier\n");
hdlc->open = 1;
@@ -281,8 +283,8 @@
if (size)
if ((dev_to_hdlc(dev)->state = kmalloc(size,
GFP_KERNEL)) == NULL) {
- printk(KERN_WARNING "Memory squeeze on"
- " hdlc_proto_attach()\n");
+ netdev_warn(dev,
+ "Memory squeeze on hdlc_proto_attach()\n");
module_put(proto->module);
return -ENOBUFS;
}
@@ -363,7 +365,7 @@
{
int result;
- printk(KERN_INFO "%s\n", version);
+ pr_info("%s\n", version);
if ((result = register_netdevice_notifier(&hdlc_notifier)) != 0)
return result;
dev_add_pack(&hdlc_packet_type);
diff --git a/drivers/net/wan/hdlc_cisco.c b/drivers/net/wan/hdlc_cisco.c
index b1e5e5b..3f20808 100644
--- a/drivers/net/wan/hdlc_cisco.c
+++ b/drivers/net/wan/hdlc_cisco.c
@@ -103,9 +103,7 @@
skb = dev_alloc_skb(sizeof(struct hdlc_header) +
sizeof(struct cisco_packet));
if (!skb) {
- printk(KERN_WARNING
- "%s: Memory squeeze on cisco_keepalive_send()\n",
- dev->name);
+ netdev_warn(dev, "Memory squeeze on cisco_keepalive_send()\n");
return;
}
skb_reserve(skb, 4);
@@ -181,8 +179,8 @@
CISCO_PACKET_LEN) &&
(skb->len != sizeof(struct hdlc_header) +
CISCO_BIG_PACKET_LEN)) {
- printk(KERN_INFO "%s: Invalid length of Cisco control"
- " packet (%d bytes)\n", dev->name, skb->len);
+ netdev_info(dev, "Invalid length of Cisco control packet (%d bytes)\n",
+ skb->len);
goto rx_error;
}
@@ -217,8 +215,7 @@
return NET_RX_SUCCESS;
case CISCO_ADDR_REPLY:
- printk(KERN_INFO "%s: Unexpected Cisco IP address "
- "reply\n", dev->name);
+ netdev_info(dev, "Unexpected Cisco IP address reply\n");
goto rx_error;
case CISCO_KEEPALIVE_REQ:
@@ -235,9 +232,8 @@
min = sec / 60; sec -= min * 60;
hrs = min / 60; min -= hrs * 60;
days = hrs / 24; hrs -= days * 24;
- printk(KERN_INFO "%s: Link up (peer "
- "uptime %ud%uh%um%us)\n",
- dev->name, days, hrs, min, sec);
+ netdev_info(dev, "Link up (peer uptime %ud%uh%um%us)\n",
+ days, hrs, min, sec);
netif_dormant_off(dev);
st->up = 1;
}
@@ -249,8 +245,7 @@
} /* switch (keepalive type) */
} /* switch (protocol) */
- printk(KERN_INFO "%s: Unsupported protocol %x\n", dev->name,
- ntohs(data->protocol));
+ netdev_info(dev, "Unsupported protocol %x\n", ntohs(data->protocol));
dev_kfree_skb_any(skb);
return NET_RX_DROP;
@@ -272,7 +267,7 @@
if (st->up &&
time_after(jiffies, st->last_poll + st->settings.timeout * HZ)) {
st->up = 0;
- printk(KERN_INFO "%s: Link down\n", dev->name);
+ netdev_info(dev, "Link down\n");
netif_dormant_on(dev);
}
diff --git a/drivers/net/wan/hdlc_fr.c b/drivers/net/wan/hdlc_fr.c
index fc433f2..b25c922 100644
--- a/drivers/net/wan/hdlc_fr.c
+++ b/drivers/net/wan/hdlc_fr.c
@@ -446,15 +446,14 @@
static inline void fr_log_dlci_active(pvc_device *pvc)
{
- printk(KERN_INFO "%s: DLCI %d [%s%s%s]%s %s\n",
- pvc->frad->name,
- pvc->dlci,
- pvc->main ? pvc->main->name : "",
- pvc->main && pvc->ether ? " " : "",
- pvc->ether ? pvc->ether->name : "",
- pvc->state.new ? " new" : "",
- !pvc->state.exist ? "deleted" :
- pvc->state.active ? "active" : "inactive");
+ netdev_info(pvc->frad, "DLCI %d [%s%s%s]%s %s\n",
+ pvc->dlci,
+ pvc->main ? pvc->main->name : "",
+ pvc->main && pvc->ether ? " " : "",
+ pvc->ether ? pvc->ether->name : "",
+ pvc->state.new ? " new" : "",
+ !pvc->state.exist ? "deleted" :
+ pvc->state.active ? "active" : "inactive");
}
@@ -481,16 +480,14 @@
if (dce && fullrep) {
len += state(hdlc)->dce_pvc_count * (2 + stat_len);
if (len > HDLC_MAX_MRU) {
- printk(KERN_WARNING "%s: Too many PVCs while sending "
- "LMI full report\n", dev->name);
+ netdev_warn(dev, "Too many PVCs while sending LMI full report\n");
return;
}
}
skb = dev_alloc_skb(len);
if (!skb) {
- printk(KERN_WARNING "%s: Memory squeeze on fr_lmi_send()\n",
- dev->name);
+ netdev_warn(dev, "Memory squeeze on fr_lmi_send()\n");
return;
}
memset(skb->data, 0, len);
@@ -615,8 +612,7 @@
state(hdlc)->last_errors <<= 1; /* Shift the list */
if (state(hdlc)->request) {
if (state(hdlc)->reliable)
- printk(KERN_INFO "%s: No LMI status reply "
- "received\n", dev->name);
+ netdev_info(dev, "No LMI status reply received\n");
state(hdlc)->last_errors |= 1;
}
@@ -628,8 +624,7 @@
}
if (state(hdlc)->reliable != reliable) {
- printk(KERN_INFO "%s: Link %sreliable\n", dev->name,
- reliable ? "" : "un");
+ netdev_info(dev, "Link %sreliable\n", reliable ? "" : "un");
fr_set_link_state(reliable, dev);
}
@@ -665,33 +660,32 @@
if (skb->len < (lmi == LMI_ANSI ? LMI_ANSI_LENGTH :
LMI_CCITT_CISCO_LENGTH)) {
- printk(KERN_INFO "%s: Short LMI frame\n", dev->name);
+ netdev_info(dev, "Short LMI frame\n");
return 1;
}
if (skb->data[3] != (lmi == LMI_CISCO ? NLPID_CISCO_LMI :
NLPID_CCITT_ANSI_LMI)) {
- printk(KERN_INFO "%s: Received non-LMI frame with LMI DLCI\n",
- dev->name);
+ netdev_info(dev, "Received non-LMI frame with LMI DLCI\n");
return 1;
}
if (skb->data[4] != LMI_CALLREF) {
- printk(KERN_INFO "%s: Invalid LMI Call reference (0x%02X)\n",
- dev->name, skb->data[4]);
+ netdev_info(dev, "Invalid LMI Call reference (0x%02X)\n",
+ skb->data[4]);
return 1;
}
if (skb->data[5] != (dce ? LMI_STATUS_ENQUIRY : LMI_STATUS)) {
- printk(KERN_INFO "%s: Invalid LMI Message type (0x%02X)\n",
- dev->name, skb->data[5]);
+ netdev_info(dev, "Invalid LMI Message type (0x%02X)\n",
+ skb->data[5]);
return 1;
}
if (lmi == LMI_ANSI) {
if (skb->data[6] != LMI_ANSI_LOCKSHIFT) {
- printk(KERN_INFO "%s: Not ANSI locking shift in LMI"
- " message (0x%02X)\n", dev->name, skb->data[6]);
+ netdev_info(dev, "Not ANSI locking shift in LMI message (0x%02X)\n",
+ skb->data[6]);
return 1;
}
i = 7;
@@ -700,34 +694,34 @@
if (skb->data[i] != (lmi == LMI_CCITT ? LMI_CCITT_REPTYPE :
LMI_ANSI_CISCO_REPTYPE)) {
- printk(KERN_INFO "%s: Not an LMI Report type IE (0x%02X)\n",
- dev->name, skb->data[i]);
+ netdev_info(dev, "Not an LMI Report type IE (0x%02X)\n",
+ skb->data[i]);
return 1;
}
if (skb->data[++i] != LMI_REPT_LEN) {
- printk(KERN_INFO "%s: Invalid LMI Report type IE length"
- " (%u)\n", dev->name, skb->data[i]);
+ netdev_info(dev, "Invalid LMI Report type IE length (%u)\n",
+ skb->data[i]);
return 1;
}
reptype = skb->data[++i];
if (reptype != LMI_INTEGRITY && reptype != LMI_FULLREP) {
- printk(KERN_INFO "%s: Unsupported LMI Report type (0x%02X)\n",
- dev->name, reptype);
+ netdev_info(dev, "Unsupported LMI Report type (0x%02X)\n",
+ reptype);
return 1;
}
if (skb->data[++i] != (lmi == LMI_CCITT ? LMI_CCITT_ALIVE :
LMI_ANSI_CISCO_ALIVE)) {
- printk(KERN_INFO "%s: Not an LMI Link integrity verification"
- " IE (0x%02X)\n", dev->name, skb->data[i]);
+ netdev_info(dev, "Not an LMI Link integrity verification IE (0x%02X)\n",
+ skb->data[i]);
return 1;
}
if (skb->data[++i] != LMI_INTEG_LEN) {
- printk(KERN_INFO "%s: Invalid LMI Link integrity verification"
- " IE length (%u)\n", dev->name, skb->data[i]);
+ netdev_info(dev, "Invalid LMI Link integrity verification IE length (%u)\n",
+ skb->data[i]);
return 1;
}
i++;
@@ -801,14 +795,14 @@
if (skb->data[i] != (lmi == LMI_CCITT ? LMI_CCITT_PVCSTAT :
LMI_ANSI_CISCO_PVCSTAT)) {
- printk(KERN_INFO "%s: Not an LMI PVC status IE"
- " (0x%02X)\n", dev->name, skb->data[i]);
+ netdev_info(dev, "Not an LMI PVC status IE (0x%02X)\n",
+ skb->data[i]);
return 1;
}
if (skb->data[++i] != stat_len) {
- printk(KERN_INFO "%s: Invalid LMI PVC status IE length"
- " (%u)\n", dev->name, skb->data[i]);
+ netdev_info(dev, "Invalid LMI PVC status IE length (%u)\n",
+ skb->data[i]);
return 1;
}
i++;
@@ -829,9 +823,7 @@
pvc = add_pvc(dev, dlci);
if (!pvc && !no_ram) {
- printk(KERN_WARNING
- "%s: Memory squeeze on fr_lmi_recv()\n",
- dev->name);
+ netdev_warn(dev, "Memory squeeze on fr_lmi_recv()\n");
no_ram = 1;
}
@@ -902,8 +894,8 @@
pvc = find_pvc(hdlc, dlci);
if (!pvc) {
#ifdef DEBUG_PKT
- printk(KERN_INFO "%s: No PVC for received frame's DLCI %d\n",
- frad->name, dlci);
+ netdev_info(frad, "No PVC for received frame's DLCI %d\n",
+ dlci);
#endif
dev_kfree_skb_any(skb);
return NET_RX_DROP;
@@ -962,14 +954,14 @@
break;
default:
- printk(KERN_INFO "%s: Unsupported protocol, OUI=%x "
- "PID=%x\n", frad->name, oui, pid);
+ netdev_info(frad, "Unsupported protocol, OUI=%x PID=%x\n",
+ oui, pid);
dev_kfree_skb_any(skb);
return NET_RX_DROP;
}
} else {
- printk(KERN_INFO "%s: Unsupported protocol, NLPID=%x "
- "length = %i\n", frad->name, data[3], skb->len);
+ netdev_info(frad, "Unsupported protocol, NLPID=%x length=%i\n",
+ data[3], skb->len);
dev_kfree_skb_any(skb);
return NET_RX_DROP;
}
@@ -1073,8 +1065,7 @@
int used;
if ((pvc = add_pvc(frad, dlci)) == NULL) {
- printk(KERN_WARNING "%s: Memory squeeze on fr_add_pvc()\n",
- frad->name);
+ netdev_warn(frad, "Memory squeeze on fr_add_pvc()\n");
return -ENOBUFS;
}
@@ -1089,8 +1080,7 @@
dev = alloc_netdev(0, "pvc%d", pvc_setup);
if (!dev) {
- printk(KERN_WARNING "%s: Memory squeeze on fr_pvc()\n",
- frad->name);
+ netdev_warn(frad, "Memory squeeze on fr_pvc()\n");
delete_unused_pvcs(hdlc);
return -ENOBUFS;
}
diff --git a/drivers/net/wan/hdlc_ppp.c b/drivers/net/wan/hdlc_ppp.c
index 941f053..055a918 100644
--- a/drivers/net/wan/hdlc_ppp.c
+++ b/drivers/net/wan/hdlc_ppp.c
@@ -223,8 +223,7 @@
skb = dev_alloc_skb(sizeof(struct hdlc_header) +
sizeof(struct cp_header) + magic_len + len);
if (!skb) {
- printk(KERN_WARNING "%s: out of memory in ppp_tx_cp()\n",
- dev->name);
+ netdev_warn(dev, "out of memory in ppp_tx_cp()\n");
return;
}
skb_reserve(skb, sizeof(struct hdlc_header));
@@ -345,7 +344,7 @@
ppp_tx_cp(dev, pid, CP_CODE_REJ, ++ppp->seq, len, data);
if (old_state != OPENED && proto->state == OPENED) {
- printk(KERN_INFO "%s: %s up\n", dev->name, proto_name(pid));
+ netdev_info(dev, "%s up\n", proto_name(pid));
if (pid == PID_LCP) {
netif_dormant_off(dev);
ppp_cp_event(dev, PID_IPCP, START, 0, 0, 0, NULL);
@@ -356,7 +355,7 @@
}
}
if (old_state == OPENED && proto->state != OPENED) {
- printk(KERN_INFO "%s: %s down\n", dev->name, proto_name(pid));
+ netdev_info(dev, "%s down\n", proto_name(pid));
if (pid == PID_LCP) {
netif_dormant_on(dev);
ppp_cp_event(dev, PID_IPCP, STOP, 0, 0, 0, NULL);
@@ -585,7 +584,7 @@
break;
if (time_after(jiffies, ppp->last_pong +
ppp->keepalive_timeout * HZ)) {
- printk(KERN_INFO "%s: Link down\n", proto->dev->name);
+ netdev_info(proto->dev, "Link down\n");
ppp_cp_event(proto->dev, PID_LCP, STOP, 0, 0, 0, NULL);
ppp_cp_event(proto->dev, PID_LCP, START, 0, 0, 0, NULL);
} else { /* send keep-alive packet */
diff --git a/drivers/net/wan/hdlc_x25.c b/drivers/net/wan/hdlc_x25.c
index 70527e5..56aeb01 100644
--- a/drivers/net/wan/hdlc_x25.c
+++ b/drivers/net/wan/hdlc_x25.c
@@ -34,7 +34,7 @@
unsigned char *ptr;
if ((skb = dev_alloc_skb(1)) == NULL) {
- printk(KERN_ERR "%s: out of memory\n", dev->name);
+ netdev_err(dev, "out of memory\n");
return;
}
@@ -106,9 +106,8 @@
/* Send connect confirm. msg to level 3 */
x25_connected(dev, 0);
else
- printk(KERN_ERR "%s: LAPB connect request "
- "failed, error code = %i\n",
- dev->name, result);
+ netdev_err(dev, "LAPB connect request failed, error code = %i\n",
+ result);
}
break;
@@ -118,9 +117,8 @@
/* Send disconnect confirm. msg to level 3 */
x25_disconnected(dev, 0);
else
- printk(KERN_ERR "%s: LAPB disconnect request "
- "failed, error code = %i\n",
- dev->name, result);
+ netdev_err(dev, "LAPB disconnect request failed, error code = %i\n",
+ result);
}
break;
diff --git a/drivers/net/wan/hostess_sv11.c b/drivers/net/wan/hostess_sv11.c
index e817583..3d80e42 100644
--- a/drivers/net/wan/hostess_sv11.c
+++ b/drivers/net/wan/hostess_sv11.c
@@ -20,6 +20,8 @@
* Generic HDLC port Copyright (C) 2008 Krzysztof Halasa <khc@pm.waw.pl>
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/mm.h>
@@ -192,8 +194,7 @@
*/
if (!request_region(iobase, 8, "Comtrol SV11")) {
- printk(KERN_WARNING "hostess: I/O 0x%X already in use.\n",
- iobase);
+ pr_warn("I/O 0x%X already in use\n", iobase);
return NULL;
}
@@ -221,7 +222,7 @@
if (request_irq(irq, z8530_interrupt, IRQF_DISABLED,
"Hostess SV11", sv) < 0) {
- printk(KERN_WARNING "hostess: IRQ %d already in use.\n", irq);
+ pr_warn("IRQ %d already in use\n", irq);
goto err_irq;
}
@@ -255,7 +256,7 @@
*/
if (z8530_init(sv)) {
- printk(KERN_ERR "Z8530 series device not found.\n");
+ pr_err("Z8530 series device not found\n");
enable_irq(irq);
goto free_dma;
}
@@ -282,7 +283,7 @@
netdev->irq = irq;
if (register_hdlc_device(netdev)) {
- printk(KERN_ERR "hostess: unable to register HDLC device.\n");
+ pr_err("unable to register HDLC device\n");
free_netdev(netdev);
goto free_dma;
}
diff --git a/drivers/net/wan/ixp4xx_hss.c b/drivers/net/wan/ixp4xx_hss.c
index f1e1643..aaaca9a 100644
--- a/drivers/net/wan/ixp4xx_hss.c
+++ b/drivers/net/wan/ixp4xx_hss.c
@@ -8,6 +8,8 @@
* as published by the Free Software Foundation.
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/bitops.h>
#include <linux/cdev.h>
#include <linux/dma-mapping.h>
@@ -358,9 +360,8 @@
{
u32 *val = (u32*)msg;
if (npe_send_message(port->npe, msg, what)) {
- printk(KERN_CRIT "HSS-%i: unable to send command [%08X:%08X]"
- " to %s\n", port->id, val[0], val[1],
- npe_name(port->npe));
+ pr_crit("HSS-%i: unable to send command [%08X:%08X] to %s\n",
+ port->id, val[0], val[1], npe_name(port->npe));
BUG();
}
}
@@ -447,8 +448,7 @@
if (npe_recv_message(port->npe, &msg, "HSS_LOAD_CONFIG") ||
/* HSS_LOAD_CONFIG for port #1 returns port_id = #4 */
msg.cmd != PORT_CONFIG_LOAD || msg.data32) {
- printk(KERN_CRIT "HSS-%i: HSS_LOAD_CONFIG failed\n",
- port->id);
+ pr_crit("HSS-%i: HSS_LOAD_CONFIG failed\n", port->id);
BUG();
}
@@ -477,8 +477,7 @@
msg.hss_port = port->id;
hss_npe_send(port, &msg, "PORT_ERROR_READ");
if (npe_recv_message(port->npe, &msg, "PORT_ERROR_READ")) {
- printk(KERN_CRIT "HSS-%i: unable to read HSS status\n",
- port->id);
+ pr_crit("HSS-%i: unable to read HSS status\n", port->id);
BUG();
}
@@ -736,9 +735,8 @@
dev->stats.rx_errors++;
break;
default: /* FIXME - remove printk */
- printk(KERN_ERR "%s: hss_hdlc_poll: status 0x%02X"
- " errors %u\n", dev->name, desc->status,
- desc->error_count);
+ netdev_err(dev, "hss_hdlc_poll: status 0x%02X errors %u\n",
+ desc->status, desc->error_count);
dev->stats.rx_errors++;
}
@@ -1127,8 +1125,8 @@
buffs--;
if (buffs)
- printk(KERN_CRIT "%s: unable to drain RX queue, %i buffer(s)"
- " left in NPE\n", dev->name, buffs);
+ netdev_crit(dev, "unable to drain RX queue, %i buffer(s) left in NPE\n",
+ buffs);
buffs = TX_DESCS;
while (queue_get_desc(queue_ids[port->id].tx, port, 1) >= 0)
@@ -1143,8 +1141,8 @@
} while (++i < MAX_CLOSE_WAIT);
if (buffs)
- printk(KERN_CRIT "%s: unable to drain TX queue, %i buffer(s) "
- "left in NPE\n", dev->name, buffs);
+ netdev_crit(dev, "unable to drain TX queue, %i buffer(s) left in NPE\n",
+ buffs);
#if DEBUG_CLOSE
if (!buffs)
printk(KERN_DEBUG "Draining TX queues took %i cycles\n", i);
@@ -1364,7 +1362,7 @@
platform_set_drvdata(pdev, port);
- printk(KERN_INFO "%s: HSS-%i\n", dev->name, port->id);
+ netdev_info(dev, "HSS-%i\n", port->id);
return 0;
err_free_netdev:
diff --git a/drivers/net/wan/lapbether.c b/drivers/net/wan/lapbether.c
index eec463f..a817081 100644
--- a/drivers/net/wan/lapbether.c
+++ b/drivers/net/wan/lapbether.c
@@ -20,6 +20,8 @@
* 2000-11-14 Henner Eisen dev_hold/put, NETDEV_GOING_DOWN support
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/socket.h>
@@ -165,13 +167,11 @@
break;
case X25_IFACE_CONNECT:
if ((err = lapb_connect_request(dev)) != LAPB_OK)
- printk(KERN_ERR "lapbeth: lapb_connect_request "
- "error: %d\n", err);
+ pr_err("lapb_connect_request error: %d\n", err);
goto drop;
case X25_IFACE_DISCONNECT:
if ((err = lapb_disconnect_request(dev)) != LAPB_OK)
- printk(KERN_ERR "lapbeth: lapb_disconnect_request "
- "err: %d\n", err);
+ pr_err("lapb_disconnect_request err: %d\n", err);
/* Fall thru */
default:
goto drop;
@@ -180,7 +180,7 @@
skb_pull(skb, 1);
if ((err = lapb_data_request(dev, skb)) != LAPB_OK) {
- printk(KERN_ERR "lapbeth: lapb_data_request error - %d\n", err);
+ pr_err("lapb_data_request error - %d\n", err);
goto drop;
}
out:
@@ -220,7 +220,7 @@
struct sk_buff *skb = dev_alloc_skb(1);
if (!skb) {
- printk(KERN_ERR "lapbeth: out of memory\n");
+ pr_err("out of memory\n");
return;
}
@@ -237,7 +237,7 @@
struct sk_buff *skb = dev_alloc_skb(1);
if (!skb) {
- printk(KERN_ERR "lapbeth: out of memory\n");
+ pr_err("out of memory\n");
return;
}
@@ -277,7 +277,7 @@
int err;
if ((err = lapb_register(dev, &lapbeth_callbacks)) != LAPB_OK) {
- printk(KERN_ERR "lapbeth: lapb_register error - %d\n", err);
+ pr_err("lapb_register error: %d\n", err);
return -ENODEV;
}
@@ -292,7 +292,7 @@
netif_stop_queue(dev);
if ((err = lapb_unregister(dev)) != LAPB_OK)
- printk(KERN_ERR "lapbeth: lapb_unregister error - %d\n", err);
+ pr_err("lapb_unregister error: %d\n", err);
return 0;
}
diff --git a/drivers/net/wan/n2.c b/drivers/net/wan/n2.c
index 17d408f..5129ad5 100644
--- a/drivers/net/wan/n2.c
+++ b/drivers/net/wan/n2.c
@@ -16,6 +16,8 @@
* SDL Inc. PPP/HDLC/CISCO driver
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/capability.h>
@@ -341,57 +343,57 @@
int i;
if (io < 0x200 || io > 0x3FF || (io % N2_IOPORTS) != 0) {
- printk(KERN_ERR "n2: invalid I/O port value\n");
+ pr_err("invalid I/O port value\n");
return -ENODEV;
}
if (irq < 3 || irq > 15 || irq == 6) /* FIXME */ {
- printk(KERN_ERR "n2: invalid IRQ value\n");
+ pr_err("invalid IRQ value\n");
return -ENODEV;
}
if (winbase < 0xA0000 || winbase > 0xFFFFF || (winbase & 0xFFF) != 0) {
- printk(KERN_ERR "n2: invalid RAM value\n");
+ pr_err("invalid RAM value\n");
return -ENODEV;
}
card = kzalloc(sizeof(card_t), GFP_KERNEL);
if (card == NULL) {
- printk(KERN_ERR "n2: unable to allocate memory\n");
+ pr_err("unable to allocate memory\n");
return -ENOBUFS;
}
card->ports[0].dev = alloc_hdlcdev(&card->ports[0]);
card->ports[1].dev = alloc_hdlcdev(&card->ports[1]);
if (!card->ports[0].dev || !card->ports[1].dev) {
- printk(KERN_ERR "n2: unable to allocate memory\n");
+ pr_err("unable to allocate memory\n");
n2_destroy_card(card);
return -ENOMEM;
}
if (!request_region(io, N2_IOPORTS, devname)) {
- printk(KERN_ERR "n2: I/O port region in use\n");
+ pr_err("I/O port region in use\n");
n2_destroy_card(card);
return -EBUSY;
}
card->io = io;
if (request_irq(irq, sca_intr, 0, devname, card)) {
- printk(KERN_ERR "n2: could not allocate IRQ\n");
+ pr_err("could not allocate IRQ\n");
n2_destroy_card(card);
return -EBUSY;
}
card->irq = irq;
if (!request_mem_region(winbase, USE_WINDOWSIZE, devname)) {
- printk(KERN_ERR "n2: could not request RAM window\n");
+ pr_err("could not request RAM window\n");
n2_destroy_card(card);
return -EBUSY;
}
card->phy_winbase = winbase;
card->winbase = ioremap(winbase, USE_WINDOWSIZE);
if (!card->winbase) {
- printk(KERN_ERR "n2: ioremap() failed\n");
+ pr_err("ioremap() failed\n");
n2_destroy_card(card);
return -EFAULT;
}
@@ -413,7 +415,7 @@
break;
default:
- printk(KERN_ERR "n2: invalid window size\n");
+ pr_err("invalid window size\n");
n2_destroy_card(card);
return -ENODEV;
}
@@ -433,12 +435,12 @@
card->buff_offset = (valid0 + valid1) * sizeof(pkt_desc) *
(card->tx_ring_buffers + card->rx_ring_buffers);
- printk(KERN_INFO "n2: RISCom/N2 %u KB RAM, IRQ%u, "
- "using %u TX + %u RX packets rings\n", card->ram_size / 1024,
- card->irq, card->tx_ring_buffers, card->rx_ring_buffers);
+ pr_info("RISCom/N2 %u KB RAM, IRQ%u, using %u TX + %u RX packets rings\n",
+ card->ram_size / 1024, card->irq,
+ card->tx_ring_buffers, card->rx_ring_buffers);
if (card->tx_ring_buffers < 1) {
- printk(KERN_ERR "n2: RAM test failed\n");
+ pr_err("RAM test failed\n");
n2_destroy_card(card);
return -EIO;
}
@@ -474,16 +476,14 @@
port->card = card;
if (register_hdlc_device(dev)) {
- printk(KERN_WARNING "n2: unable to register hdlc "
- "device\n");
+ pr_warn("unable to register hdlc device\n");
port->card = NULL;
n2_destroy_card(card);
return -ENOBUFS;
}
sca_init_port(port); /* Set up SCA memory */
- printk(KERN_INFO "%s: RISCom/N2 node %d\n",
- dev->name, port->phy_node);
+ netdev_info(dev, "RISCom/N2 node %d\n", port->phy_node);
}
*new_card = card;
@@ -498,12 +498,12 @@
{
if (hw==NULL) {
#ifdef MODULE
- printk(KERN_INFO "n2: no card initialized\n");
+ pr_info("no card initialized\n");
#endif
return -EINVAL; /* no parameters specified, abort */
}
- printk(KERN_INFO "%s\n", version);
+ pr_info("%s\n", version);
do {
unsigned long io, irq, ram;
@@ -541,7 +541,7 @@
return first_card ? 0 : -EINVAL;
}while(*hw++ == ':');
- printk(KERN_ERR "n2: invalid hardware parameters\n");
+ pr_err("invalid hardware parameters\n");
return first_card ? 0 : -EINVAL;
}
diff --git a/drivers/net/wan/pc300_drv.c b/drivers/net/wan/pc300_drv.c
index 9617d3d..1eeedd6 100644
--- a/drivers/net/wan/pc300_drv.c
+++ b/drivers/net/wan/pc300_drv.c
@@ -212,6 +212,8 @@
*
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/mm.h>
@@ -3242,7 +3244,7 @@
rcsdate++;
tmp = strrchr(rcsdate, ' ');
*tmp = '\0';
- printk(KERN_INFO "Cyclades-PC300 driver %s %s\n", rcsvers, rcsdate);
+ pr_info("Cyclades-PC300 driver %s %s\n", rcsvers, rcsdate);
} /* show_version */
static const struct net_device_ops cpc_netdev_ops = {
diff --git a/drivers/net/wan/pc300_tty.c b/drivers/net/wan/pc300_tty.c
index 1c65d1c..d47d2cd 100644
--- a/drivers/net/wan/pc300_tty.c
+++ b/drivers/net/wan/pc300_tty.c
@@ -755,7 +755,7 @@
dsr_rx = cpc_readb(card->hw.scabase + DSR_RX(ch));
- cpc_tty = (st_cpc_tty_area *)pc300dev->cpc_tty;
+ cpc_tty = pc300dev->cpc_tty;
while (1) {
rx_len = 0;
diff --git a/drivers/net/wan/pc300too.c b/drivers/net/wan/pc300too.c
index c7ab3be..c49c1b3 100644
--- a/drivers/net/wan/pc300too.c
+++ b/drivers/net/wan/pc300too.c
@@ -17,6 +17,8 @@
* PC300/X21 cards.
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/slab.h>
@@ -318,7 +320,7 @@
card = kzalloc(sizeof(card_t), GFP_KERNEL);
if (card == NULL) {
- printk(KERN_ERR "pc300: unable to allocate memory\n");
+ pr_err("unable to allocate memory\n");
pci_release_regions(pdev);
pci_disable_device(pdev);
return -ENOBUFS;
@@ -328,7 +330,7 @@
if (pci_resource_len(pdev, 0) != PC300_PLX_SIZE ||
pci_resource_len(pdev, 2) != PC300_SCA_SIZE ||
pci_resource_len(pdev, 3) < 16384) {
- printk(KERN_ERR "pc300: invalid card EEPROM parameters\n");
+ pr_err("invalid card EEPROM parameters\n");
pc300_pci_remove_one(pdev);
return -EFAULT;
}
@@ -345,7 +347,7 @@
if (card->plxbase == NULL ||
card->scabase == NULL ||
card->rambase == NULL) {
- printk(KERN_ERR "pc300: ioremap() failed\n");
+ pr_err("ioremap() failed\n");
pc300_pci_remove_one(pdev);
}
@@ -370,7 +372,7 @@
for (i = 0; i < card->n_ports; i++)
if (!(card->ports[i].netdev = alloc_hdlcdev(&card->ports[i]))) {
- printk(KERN_ERR "pc300: unable to allocate memory\n");
+ pr_err("unable to allocate memory\n");
pc300_pci_remove_one(pdev);
return -ENOMEM;
}
@@ -411,15 +413,14 @@
card->buff_offset = card->n_ports * sizeof(pkt_desc) *
(card->tx_ring_buffers + card->rx_ring_buffers);
- printk(KERN_INFO "pc300: PC300/%s, %u KB RAM at 0x%x, IRQ%u, "
- "using %u TX + %u RX packets rings\n",
- card->type == PC300_X21 ? "X21" :
- card->type == PC300_TE ? "TE" : "RSV",
- ramsize / 1024, ramphys, pdev->irq,
- card->tx_ring_buffers, card->rx_ring_buffers);
+ pr_info("PC300/%s, %u KB RAM at 0x%x, IRQ%u, using %u TX + %u RX packets rings\n",
+ card->type == PC300_X21 ? "X21" :
+ card->type == PC300_TE ? "TE" : "RSV",
+ ramsize / 1024, ramphys, pdev->irq,
+ card->tx_ring_buffers, card->rx_ring_buffers);
if (card->tx_ring_buffers < 1) {
- printk(KERN_ERR "pc300: RAM test failed\n");
+ pr_err("RAM test failed\n");
pc300_pci_remove_one(pdev);
return -EFAULT;
}
@@ -429,8 +430,7 @@
/* Allocate IRQ */
if (request_irq(pdev->irq, sca_intr, IRQF_SHARED, "pc300", card)) {
- printk(KERN_WARNING "pc300: could not allocate IRQ%d.\n",
- pdev->irq);
+ pr_warn("could not allocate IRQ%d\n", pdev->irq);
pc300_pci_remove_one(pdev);
return -EBUSY;
}
@@ -466,15 +466,13 @@
sca_init_port(port);
if (register_hdlc_device(dev)) {
- printk(KERN_ERR "pc300: unable to register hdlc "
- "device\n");
+ pr_err("unable to register hdlc device\n");
port->card = NULL;
pc300_pci_remove_one(pdev);
return -ENOBUFS;
}
- printk(KERN_INFO "%s: PC300 channel %d\n",
- dev->name, port->chan);
+ netdev_info(dev, "PC300 channel %d\n", port->chan);
}
return 0;
}
@@ -505,11 +503,11 @@
static int __init pc300_init_module(void)
{
if (pci_clock_freq < 1000000 || pci_clock_freq > 80000000) {
- printk(KERN_ERR "pc300: Invalid PCI clock frequency\n");
+ pr_err("Invalid PCI clock frequency\n");
return -EINVAL;
}
if (use_crystal_clock != 0 && use_crystal_clock != 1) {
- printk(KERN_ERR "pc300: Invalid 'use_crystal_clock' value\n");
+ pr_err("Invalid 'use_crystal_clock' value\n");
return -EINVAL;
}
diff --git a/drivers/net/wan/pci200syn.c b/drivers/net/wan/pci200syn.c
index fd73759..1ce2116 100644
--- a/drivers/net/wan/pci200syn.c
+++ b/drivers/net/wan/pci200syn.c
@@ -14,6 +14,8 @@
* PLX Technology Inc. PCI9052 Data Book
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/capability.h>
@@ -297,7 +299,7 @@
card = kzalloc(sizeof(card_t), GFP_KERNEL);
if (card == NULL) {
- printk(KERN_ERR "pci200syn: unable to allocate memory\n");
+ pr_err("unable to allocate memory\n");
pci_release_regions(pdev);
pci_disable_device(pdev);
return -ENOBUFS;
@@ -306,7 +308,7 @@
card->ports[0].netdev = alloc_hdlcdev(&card->ports[0]);
card->ports[1].netdev = alloc_hdlcdev(&card->ports[1]);
if (!card->ports[0].netdev || !card->ports[1].netdev) {
- printk(KERN_ERR "pci200syn: unable to allocate memory\n");
+ pr_err("unable to allocate memory\n");
pci200_pci_remove_one(pdev);
return -ENOMEM;
}
@@ -314,7 +316,7 @@
if (pci_resource_len(pdev, 0) != PCI200SYN_PLX_SIZE ||
pci_resource_len(pdev, 2) != PCI200SYN_SCA_SIZE ||
pci_resource_len(pdev, 3) < 16384) {
- printk(KERN_ERR "pci200syn: invalid card EEPROM parameters\n");
+ pr_err("invalid card EEPROM parameters\n");
pci200_pci_remove_one(pdev);
return -EFAULT;
}
@@ -331,7 +333,7 @@
if (card->plxbase == NULL ||
card->scabase == NULL ||
card->rambase == NULL) {
- printk(KERN_ERR "pci200syn: ioremap() failed\n");
+ pr_err("ioremap() failed\n");
pci200_pci_remove_one(pdev);
return -EFAULT;
}
@@ -357,12 +359,12 @@
card->buff_offset = 2 * sizeof(pkt_desc) * (card->tx_ring_buffers +
card->rx_ring_buffers);
- printk(KERN_INFO "pci200syn: %u KB RAM at 0x%x, IRQ%u, using %u TX +"
- " %u RX packets rings\n", ramsize / 1024, ramphys,
- pdev->irq, card->tx_ring_buffers, card->rx_ring_buffers);
+ pr_info("%u KB RAM at 0x%x, IRQ%u, using %u TX + %u RX packets rings\n",
+ ramsize / 1024, ramphys,
+ pdev->irq, card->tx_ring_buffers, card->rx_ring_buffers);
if (card->tx_ring_buffers < 1) {
- printk(KERN_ERR "pci200syn: RAM test failed\n");
+ pr_err("RAM test failed\n");
pci200_pci_remove_one(pdev);
return -EFAULT;
}
@@ -373,8 +375,7 @@
/* Allocate IRQ */
if (request_irq(pdev->irq, sca_intr, IRQF_SHARED, "pci200syn", card)) {
- printk(KERN_WARNING "pci200syn: could not allocate IRQ%d.\n",
- pdev->irq);
+ pr_warn("could not allocate IRQ%d\n", pdev->irq);
pci200_pci_remove_one(pdev);
return -EBUSY;
}
@@ -400,15 +401,13 @@
port->card = card;
sca_init_port(port);
if (register_hdlc_device(dev)) {
- printk(KERN_ERR "pci200syn: unable to register hdlc "
- "device\n");
+ pr_err("unable to register hdlc device\n");
port->card = NULL;
pci200_pci_remove_one(pdev);
return -ENOBUFS;
}
- printk(KERN_INFO "%s: PCI200SYN channel %d\n",
- dev->name, port->chan);
+ netdev_info(dev, "PCI200SYN channel %d\n", port->chan);
}
sca_flush(card);
@@ -435,7 +434,7 @@
static int __init pci200_init_module(void)
{
if (pci_clock_freq < 1000000 || pci_clock_freq > 80000000) {
- printk(KERN_ERR "pci200syn: Invalid PCI clock frequency\n");
+ pr_err("Invalid PCI clock frequency\n");
return -EINVAL;
}
return pci_register_driver(&pci200_pci_driver);
diff --git a/drivers/net/wan/sbni.c b/drivers/net/wan/sbni.c
index cff13a9..40e95fa 100644
--- a/drivers/net/wan/sbni.c
+++ b/drivers/net/wan/sbni.c
@@ -37,6 +37,8 @@
* Known problem: this driver wasn't tested on multiprocessor machine.
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/ptrace.h>
@@ -200,8 +202,8 @@
return 0;
else {
- printk( KERN_ERR "sbni: base address 0x%lx is busy, or adapter "
- "is malfunctional!\n", dev->base_addr );
+ pr_err("base address 0x%lx is busy, or adapter is malfunctional!\n",
+ dev->base_addr);
return -ENODEV;
}
}
@@ -226,7 +228,6 @@
int __init sbni_probe(int unit)
{
struct net_device *dev;
- static unsigned version_printed __initdata = 0;
int err;
dev = alloc_netdev(sizeof(struct net_local), "sbni", sbni_devsetup);
@@ -250,8 +251,7 @@
free_netdev(dev);
return err;
}
- if( version_printed++ == 0 )
- printk( KERN_INFO "%s", version );
+ pr_info_once("%s", version);
return 0;
}
@@ -326,9 +326,9 @@
}
if (pci_irq_line <= 0 || pci_irq_line >= nr_irqs)
- printk( KERN_WARNING
- " WARNING: The PCI BIOS assigned this PCI card to IRQ %d, which is unlikely to work!.\n"
- " You should use the PCI BIOS setup to assign a valid IRQ line.\n",
+ pr_warn(
+"WARNING: The PCI BIOS assigned this PCI card to IRQ %d, which is unlikely to work!.\n"
+"You should use the PCI BIOS setup to assign a valid IRQ line.\n",
pci_irq_line );
/* avoiding re-enable dual adapters */
@@ -372,8 +372,7 @@
outb( 0, ioaddr + CSR0 );
if( !irq ) {
- printk( KERN_ERR "%s: can't detect device irq!\n",
- dev->name );
+ pr_err("%s: can't detect device irq!\n", dev->name);
release_region( ioaddr, SBNI_IO_EXTENT );
return NULL;
}
@@ -386,7 +385,7 @@
/* Fill in sbni-specific dev fields. */
nl = netdev_priv(dev);
if( !nl ) {
- printk( KERN_ERR "%s: unable to get memory!\n", dev->name );
+ pr_err("%s: unable to get memory!\n", dev->name);
release_region( ioaddr, SBNI_IO_EXTENT );
return NULL;
}
@@ -415,21 +414,21 @@
if( inb( ioaddr + CSR0 ) & 0x01 )
nl->state |= FL_SLOW_MODE;
- printk( KERN_NOTICE "%s: ioaddr %#lx, irq %d, "
- "MAC: 00:ff:01:%02x:%02x:%02x\n",
- dev->name, dev->base_addr, dev->irq,
- ((u8 *) dev->dev_addr) [3],
- ((u8 *) dev->dev_addr) [4],
- ((u8 *) dev->dev_addr) [5] );
+ pr_notice("%s: ioaddr %#lx, irq %d, MAC: 00:ff:01:%02x:%02x:%02x\n",
+ dev->name, dev->base_addr, dev->irq,
+ ((u8 *)dev->dev_addr)[3],
+ ((u8 *)dev->dev_addr)[4],
+ ((u8 *)dev->dev_addr)[5]);
- printk( KERN_NOTICE "%s: speed %d, receive level ", dev->name,
- ( (nl->state & FL_SLOW_MODE) ? 500000 : 2000000)
- / (1 << nl->csr1.rate) );
+ pr_notice("%s: speed %d",
+ dev->name,
+ ((nl->state & FL_SLOW_MODE) ? 500000 : 2000000)
+ / (1 << nl->csr1.rate));
if( nl->delta_rxl == 0 )
- printk( "0x%x (fixed)\n", nl->cur_rxl_index );
+ pr_cont(", receive level 0x%x (fixed)\n", nl->cur_rxl_index);
else
- printk( "(auto)\n");
+ pr_cont(", receive level (auto)\n");
#ifdef CONFIG_SBNI_MULTILINE
nl->master = dev;
@@ -568,7 +567,7 @@
*/
csr0 = inb( ioaddr + CSR0 );
if( !(csr0 & TR_RDY) || (csr0 & RC_RDY) )
- printk( KERN_ERR "%s: internal error!\n", dev->name );
+ netdev_err(dev, "internal error!\n");
/* if state & FL_NEED_RESEND != 0 then tx_frameno != 0 */
if( req_ans || nl->tx_frameno != 0 )
@@ -851,7 +850,7 @@
/* nl->tx_buf_p == NULL here! */
if( nl->tx_buf_p )
- printk( KERN_ERR "%s: memory leak!\n", dev->name );
+ netdev_err(dev, "memory leak!\n");
nl->outpos = 0;
nl->state &= ~(FL_WAIT_ACK | FL_NEED_RESEND);
@@ -1179,16 +1178,15 @@
((struct net_local *) (netdev_priv(*p)))
->second = dev;
- printk( KERN_NOTICE "%s: using shared irq "
- "with %s\n", dev->name, (*p)->name );
+ netdev_notice(dev, "using shared irq with %s\n",
+ (*p)->name);
nl->state |= FL_SECONDARY;
goto handler_attached;
}
}
if( request_irq(dev->irq, sbni_interrupt, IRQF_SHARED, dev->name, dev) ) {
- printk( KERN_ERR "%s: unable to get IRQ %d.\n",
- dev->name, dev->irq );
+ netdev_err(dev, "unable to get IRQ %d\n", dev->irq);
return -EAGAIN;
}
@@ -1220,8 +1218,8 @@
struct net_local *nl = netdev_priv(dev);
if( nl->second && nl->second->flags & IFF_UP ) {
- printk( KERN_NOTICE "Secondary channel (%s) is active!\n",
- nl->second->name );
+ netdev_notice(dev, "Secondary channel (%s) is active!\n",
+ nl->second->name);
return -EBUSY;
}
@@ -1363,8 +1361,8 @@
return -EFAULT;
slave_dev = dev_get_by_name(&init_net, slave_name );
if( !slave_dev || !(slave_dev->flags & IFF_UP) ) {
- printk( KERN_ERR "%s: trying to enslave non-active "
- "device %s\n", dev->name, slave_name );
+ netdev_err(dev, "trying to enslave non-active device %s\n",
+ slave_name);
return -EPERM;
}
@@ -1417,8 +1415,7 @@
spin_unlock( &snl->lock );
spin_unlock( &nl->lock );
- printk( KERN_NOTICE "%s: slave device (%s) attached.\n",
- dev->name, slave_dev->name );
+ netdev_notice(dev, "slave device (%s) attached\n", slave_dev->name);
return 0;
}
@@ -1547,7 +1544,7 @@
break;
}
bad_param:
- printk( KERN_ERR "Error in sbni kernel parameter!\n" );
+ pr_err("Error in sbni kernel parameter!\n");
return 0;
}
diff --git a/drivers/net/wan/sdla.c b/drivers/net/wan/sdla.c
index 3f4e2b5..c853161 100644
--- a/drivers/net/wan/sdla.c
+++ b/drivers/net/wan/sdla.c
@@ -32,6 +32,8 @@
* 2 of the License, or (at your option) any later version.
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/types.h>
@@ -350,24 +352,24 @@
case SDLA_RET_MODEM:
state = data;
if (*state & SDLA_MODEM_DCD_LOW)
- printk(KERN_INFO "%s: Modem DCD unexpectedly low!\n", dev->name);
+ netdev_info(dev, "Modem DCD unexpectedly low!\n");
if (*state & SDLA_MODEM_CTS_LOW)
- printk(KERN_INFO "%s: Modem CTS unexpectedly low!\n", dev->name);
+ netdev_info(dev, "Modem CTS unexpectedly low!\n");
/* I should probably do something about this! */
break;
case SDLA_RET_CHANNEL_OFF:
- printk(KERN_INFO "%s: Channel became inoperative!\n", dev->name);
+ netdev_info(dev, "Channel became inoperative!\n");
/* same here */
break;
case SDLA_RET_CHANNEL_ON:
- printk(KERN_INFO "%s: Channel became operative!\n", dev->name);
+ netdev_info(dev, "Channel became operative!\n");
/* same here */
break;
case SDLA_RET_DLCI_STATUS:
- printk(KERN_INFO "%s: Status change reported by Access Node.\n", dev->name);
+ netdev_info(dev, "Status change reported by Access Node\n");
len /= sizeof(struct _dlci_stat);
for(pstatus = data, i=0;i < len;i++,pstatus++)
{
@@ -382,29 +384,32 @@
sprintf(line, "unknown status: %02X", pstatus->flags);
state = line;
}
- printk(KERN_INFO "%s: DLCI %i: %s.\n", dev->name, pstatus->dlci, state);
+ netdev_info(dev, "DLCI %i: %s\n",
+ pstatus->dlci, state);
/* same here */
}
break;
case SDLA_RET_DLCI_UNKNOWN:
- printk(KERN_INFO "%s: Received unknown DLCIs:", dev->name);
+ netdev_info(dev, "Received unknown DLCIs:");
len /= sizeof(short);
for(pdlci = data,i=0;i < len;i++,pdlci++)
- printk(" %i", *pdlci);
- printk("\n");
+ pr_cont(" %i", *pdlci);
+ pr_cont("\n");
break;
case SDLA_RET_TIMEOUT:
- printk(KERN_ERR "%s: Command timed out!\n", dev->name);
+ netdev_err(dev, "Command timed out!\n");
break;
case SDLA_RET_BUF_OVERSIZE:
- printk(KERN_INFO "%s: Bc/CIR overflow, acceptable size is %i\n", dev->name, len);
+ netdev_info(dev, "Bc/CIR overflow, acceptable size is %i\n",
+ len);
break;
case SDLA_RET_BUF_TOO_BIG:
- printk(KERN_INFO "%s: Buffer size over specified max of %i\n", dev->name, len);
+ netdev_info(dev, "Buffer size over specified max of %i\n",
+ len);
break;
case SDLA_RET_CHANNEL_INACTIVE:
@@ -415,7 +420,8 @@
break;
default:
- printk(KERN_DEBUG "%s: Cmd 0x%2.2X generated return code 0x%2.2X\n", dev->name, cmd, ret);
+ netdev_dbg(dev, "Cmd 0x%02X generated return code 0x%02X\n",
+ cmd, ret);
/* Further processing could be done here */
break;
}
@@ -678,12 +684,14 @@
case ARPHRD_FRAD:
if (skb->dev->type != ARPHRD_DLCI)
{
- printk(KERN_WARNING "%s: Non DLCI device, type %i, tried to send on FRAD module.\n", dev->name, skb->dev->type);
+ netdev_warn(dev, "Non DLCI device, type %i, tried to send on FRAD module\n",
+ skb->dev->type);
accept = 0;
}
break;
default:
- printk(KERN_WARNING "%s: unknown firmware type 0x%4.4X\n", dev->name, dev->type);
+ netdev_warn(dev, "unknown firmware type 0x%04X\n",
+ dev->type);
accept = 0;
break;
}
@@ -807,7 +815,8 @@
if (i == CONFIG_DLCI_MAX)
{
- printk(KERN_NOTICE "%s: Received packet from invalid DLCI %i, ignoring.", dev->name, dlci);
+ netdev_notice(dev, "Received packet from invalid DLCI %i, ignoring\n",
+ dlci);
dev->stats.rx_errors++;
success = 0;
}
@@ -819,7 +828,7 @@
skb = dev_alloc_skb(len + sizeof(struct frhdr));
if (skb == NULL)
{
- printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n", dev->name);
+ netdev_notice(dev, "Memory squeeze, dropping packet\n");
dev->stats.rx_dropped++;
success = 0;
}
@@ -880,8 +889,7 @@
if (!flp->initialized)
{
- printk(KERN_WARNING "%s: irq %d for uninitialized device.\n",
- dev->name, dev->irq);
+ netdev_warn(dev, "irq %d for uninitialized device\n", dev->irq);
return IRQ_NONE;
}
@@ -901,7 +909,7 @@
case SDLA_INTR_TX:
case SDLA_INTR_COMPLETE:
case SDLA_INTR_TIMER:
- printk(KERN_WARNING "%s: invalid irq flag 0x%02X.\n", dev->name, byte);
+ netdev_warn(dev, "invalid irq flag 0x%02X\n", byte);
break;
}
@@ -1347,7 +1355,7 @@
return -EINVAL;
if (!request_region(map->base_addr, SDLA_IO_EXTENTS, dev->name)){
- printk(KERN_WARNING "SDLA: io-port 0x%04lx in use\n", dev->base_addr);
+ pr_warn("io-port 0x%04lx in use\n", dev->base_addr);
return -EINVAL;
}
base = map->base_addr;
@@ -1412,7 +1420,7 @@
}
}
- printk(KERN_NOTICE "%s: Unknown card type\n", dev->name);
+ netdev_notice(dev, "Unknown card type\n");
err = -ENODEV;
goto fail;
diff --git a/drivers/net/wan/sealevel.c b/drivers/net/wan/sealevel.c
index e91457d..0b4fd05 100644
--- a/drivers/net/wan/sealevel.c
+++ b/drivers/net/wan/sealevel.c
@@ -12,6 +12,8 @@
*
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/mm.h>
@@ -190,7 +192,7 @@
dev->irq = irq;
if (register_hdlc_device(dev)) {
- printk(KERN_ERR "sealevel: unable to register HDLC device\n");
+ pr_err("unable to register HDLC device\n");
free_netdev(dev);
return -1;
}
@@ -215,8 +217,7 @@
*/
if (!request_region(iobase, 8, "Sealevel 4021")) {
- printk(KERN_WARNING "sealevel: I/O 0x%X already in use.\n",
- iobase);
+ pr_warn("I/O 0x%X already in use\n", iobase);
return NULL;
}
@@ -267,7 +268,7 @@
if (request_irq(irq, z8530_interrupt, IRQF_DISABLED,
"SeaLevel", dev) < 0) {
- printk(KERN_WARNING "sealevel: IRQ %d already in use.\n", irq);
+ pr_warn("IRQ %d already in use\n", irq);
goto err_request_irq;
}
@@ -292,7 +293,7 @@
*/
if (z8530_init(dev) != 0) {
- printk(KERN_ERR "Z8530 series device not found.\n");
+ pr_err("Z8530 series device not found\n");
enable_irq(irq);
goto free_hw;
}
diff --git a/drivers/net/wan/wanxl.c b/drivers/net/wan/wanxl.c
index db73a7b..44b7071 100644
--- a/drivers/net/wan/wanxl.c
+++ b/drivers/net/wan/wanxl.c
@@ -13,6 +13,8 @@
* - wanXL100 will require minor driver modifications, no access to hw
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/slab.h>
@@ -22,6 +24,7 @@
#include <linux/string.h>
#include <linux/errno.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/netdevice.h>
#include <linux/hdlc.h>
@@ -101,9 +104,8 @@
{
dma_addr_t addr = pci_map_single(pdev, ptr, size, direction);
if (addr + size > 0x100000000LL)
- printk(KERN_CRIT "wanXL %s: pci_map_single() returned memory"
- " at 0x%LX!\n", pci_name(pdev),
- (unsigned long long)addr);
+ pr_crit("%s: pci_map_single() returned memory at 0x%llx!\n",
+ pci_name(pdev), (unsigned long long)addr);
return addr;
}
@@ -146,8 +148,8 @@
}
dte = (value & STATUS_CABLE_DCE) ? " DCE" : " DTE";
}
- printk(KERN_INFO "%s: %s%s module, %s cable%s%s\n",
- port->dev->name, pm, dte, cable, dsr, dcd);
+ netdev_info(port->dev, "%s%s module, %s cable%s%s\n",
+ pm, dte, cable, dsr, dcd);
if (value & STATUS_CABLE_DCD)
netif_carrier_on(port->dev);
@@ -197,8 +199,8 @@
while (desc = &card->status->rx_descs[card->rx_in],
desc->stat != PACKET_EMPTY) {
if ((desc->stat & PACKET_PORT_MASK) > card->n_ports)
- printk(KERN_CRIT "wanXL %s: received packet for"
- " nonexistent port\n", pci_name(card->pdev));
+ pr_crit("%s: received packet for nonexistent port\n",
+ pci_name(card->pdev));
else {
struct sk_buff *skb = card->rx_skbs[card->rx_in];
port_t *port = &card->ports[desc->stat &
@@ -282,7 +284,7 @@
printk(KERN_DEBUG "%s: transmitter buffer full\n", dev->name);
#endif
netif_stop_queue(dev);
- spin_unlock_irq(&port->lock);
+ spin_unlock(&port->lock);
return NETDEV_TX_BUSY; /* request packet to be queued */
}
@@ -396,7 +398,7 @@
int i;
if (get_status(port)->open) {
- printk(KERN_ERR "%s: port already open\n", dev->name);
+ netdev_err(dev, "port already open\n");
return -EIO;
}
if ((i = hdlc_open(dev)) != 0)
@@ -416,7 +418,7 @@
}
} while (time_after(timeout, jiffies));
- printk(KERN_ERR "%s: unable to open port\n", dev->name);
+ netdev_err(dev, "unable to open port\n");
/* ask the card to close the port, should it be still alive */
writel(1 << (DOORBELL_TO_CARD_CLOSE_0 + port->node), dbr);
return -EFAULT;
@@ -442,7 +444,7 @@
} while (time_after(timeout, jiffies));
if (get_status(port)->open)
- printk(KERN_ERR "%s: unable to close port\n", dev->name);
+ netdev_err(dev, "unable to close port\n");
netif_stop_queue(dev);
@@ -567,11 +569,7 @@
int i, ports, alloc_size;
#ifndef MODULE
- static int printed_version;
- if (!printed_version) {
- printed_version++;
- printk(KERN_INFO "%s\n", version);
- }
+ pr_info_once("%s\n", version);
#endif
i = pci_enable_device(pdev);
@@ -587,7 +585,7 @@
work on most platforms */
if (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(28)) ||
pci_set_dma_mask(pdev, DMA_BIT_MASK(28))) {
- printk(KERN_ERR "wanXL: No usable DMA configuration\n");
+ pr_err("No usable DMA configuration\n");
return -EIO;
}
@@ -606,8 +604,7 @@
alloc_size = sizeof(card_t) + ports * sizeof(port_t);
card = kzalloc(alloc_size, GFP_KERNEL);
if (card == NULL) {
- printk(KERN_ERR "wanXL %s: unable to allocate memory\n",
- pci_name(pdev));
+ pr_err("%s: unable to allocate memory\n", pci_name(pdev));
pci_release_regions(pdev);
pci_disable_device(pdev);
return -ENOBUFS;
@@ -634,7 +631,7 @@
to indicate the card can do 32-bit DMA addressing */
if (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)) ||
pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) {
- printk(KERN_ERR "wanXL: No usable DMA configuration\n");
+ pr_err("No usable DMA configuration\n");
wanxl_pci_remove_one(pdev);
return -EIO;
}
@@ -644,7 +641,7 @@
card->plx = ioremap_nocache(plx_phy, 0x70);
if (!card->plx) {
- printk(KERN_ERR "wanxl: ioremap() failed\n");
+ pr_err("ioremap() failed\n");
wanxl_pci_remove_one(pdev);
return -EFAULT;
}
@@ -656,8 +653,8 @@
timeout = jiffies + 20 * HZ;
while ((stat = readl(card->plx + PLX_MAILBOX_0)) != 0) {
if (time_before(timeout, jiffies)) {
- printk(KERN_WARNING "wanXL %s: timeout waiting for"
- " PUTS to complete\n", pci_name(pdev));
+ pr_warn("%s: timeout waiting for PUTS to complete\n",
+ pci_name(pdev));
wanxl_pci_remove_one(pdev);
return -ENODEV;
}
@@ -668,8 +665,8 @@
break;
default:
- printk(KERN_WARNING "wanXL %s: PUTS test 0x%X"
- " failed\n", pci_name(pdev), stat & 0x30);
+ pr_warn("%s: PUTS test 0x%X failed\n",
+ pci_name(pdev), stat & 0x30);
wanxl_pci_remove_one(pdev);
return -ENODEV;
}
@@ -687,17 +684,16 @@
/* sanity check the board's reported memory size */
if (ramsize < BUFFERS_ADDR +
(TX_BUFFERS + RX_BUFFERS) * BUFFER_LENGTH * ports) {
- printk(KERN_WARNING "wanXL %s: no enough on-board RAM"
- " (%u bytes detected, %u bytes required)\n",
- pci_name(pdev), ramsize, BUFFERS_ADDR +
- (TX_BUFFERS + RX_BUFFERS) * BUFFER_LENGTH * ports);
+ pr_warn("%s: no enough on-board RAM (%u bytes detected, %u bytes required)\n",
+ pci_name(pdev), ramsize,
+ BUFFERS_ADDR +
+ (TX_BUFFERS + RX_BUFFERS) * BUFFER_LENGTH * ports);
wanxl_pci_remove_one(pdev);
return -ENODEV;
}
if (wanxl_puts_command(card, MBX1_CMD_BSWAP)) {
- printk(KERN_WARNING "wanXL %s: unable to Set Byte Swap"
- " Mode\n", pci_name(pdev));
+ pr_warn("%s: unable to Set Byte Swap Mode\n", pci_name(pdev));
wanxl_pci_remove_one(pdev);
return -ENODEV;
}
@@ -714,7 +710,7 @@
mem = ioremap_nocache(mem_phy, PDM_OFFSET + sizeof(firmware));
if (!mem) {
- printk(KERN_ERR "wanxl: ioremap() failed\n");
+ pr_err("ioremap() failed\n");
wanxl_pci_remove_one(pdev);
return -EFAULT;
}
@@ -733,8 +729,7 @@
writel(0, card->plx + PLX_MAILBOX_5);
if (wanxl_puts_command(card, MBX1_CMD_ABORTJ)) {
- printk(KERN_WARNING "wanXL %s: unable to Abort and Jump\n",
- pci_name(pdev));
+ pr_warn("%s: unable to Abort and Jump\n", pci_name(pdev));
wanxl_pci_remove_one(pdev);
return -ENODEV;
}
@@ -748,8 +743,8 @@
}while (time_after(timeout, jiffies));
if (!stat) {
- printk(KERN_WARNING "wanXL %s: timeout while initializing card "
- "firmware\n", pci_name(pdev));
+ pr_warn("%s: timeout while initializing card firmware\n",
+ pci_name(pdev));
wanxl_pci_remove_one(pdev);
return -ENODEV;
}
@@ -758,13 +753,13 @@
ramsize = stat;
#endif
- printk(KERN_INFO "wanXL %s: at 0x%X, %u KB of RAM at 0x%X, irq %u\n",
- pci_name(pdev), plx_phy, ramsize / 1024, mem_phy, pdev->irq);
+ pr_info("%s: at 0x%X, %u KB of RAM at 0x%X, irq %u\n",
+ pci_name(pdev), plx_phy, ramsize / 1024, mem_phy, pdev->irq);
/* Allocate IRQ */
if (request_irq(pdev->irq, wanxl_intr, IRQF_SHARED, "wanXL", card)) {
- printk(KERN_WARNING "wanXL %s: could not allocate IRQ%i.\n",
- pci_name(pdev), pdev->irq);
+ pr_warn("%s: could not allocate IRQ%i\n",
+ pci_name(pdev), pdev->irq);
wanxl_pci_remove_one(pdev);
return -EBUSY;
}
@@ -775,8 +770,8 @@
port_t *port = &card->ports[i];
struct net_device *dev = alloc_hdlcdev(port);
if (!dev) {
- printk(KERN_ERR "wanXL %s: unable to allocate"
- " memory\n", pci_name(pdev));
+ pr_err("%s: unable to allocate memory\n",
+ pci_name(pdev));
wanxl_pci_remove_one(pdev);
return -ENOMEM;
}
@@ -792,8 +787,8 @@
port->node = i;
get_status(port)->clocking = CLOCK_EXT;
if (register_hdlc_device(dev)) {
- printk(KERN_ERR "wanXL %s: unable to register hdlc"
- " device\n", pci_name(pdev));
+ pr_err("%s: unable to register hdlc device\n",
+ pci_name(pdev));
free_netdev(dev);
wanxl_pci_remove_one(pdev);
return -ENOBUFS;
@@ -801,11 +796,11 @@
card->n_ports++;
}
- printk(KERN_INFO "wanXL %s: port", pci_name(pdev));
+ pr_info("%s: port", pci_name(pdev));
for (i = 0; i < ports; i++)
- printk("%s #%i: %s", i ? "," : "", i,
- card->ports[i].dev->name);
- printk("\n");
+ pr_cont("%s #%i: %s",
+ i ? "," : "", i, card->ports[i].dev->name);
+ pr_cont("\n");
for (i = 0; i < ports; i++)
wanxl_cable_intr(&card->ports[i]); /* get carrier status etc.*/
@@ -835,7 +830,7 @@
static int __init wanxl_init_module(void)
{
#ifdef MODULE
- printk(KERN_INFO "%s\n", version);
+ pr_info("%s\n", version);
#endif
return pci_register_driver(&wanxl_pci_driver);
}
diff --git a/drivers/net/wan/x25_asy.c b/drivers/net/wan/x25_asy.c
index 24297b2..46ceb3a 100644
--- a/drivers/net/wan/x25_asy.c
+++ b/drivers/net/wan/x25_asy.c
@@ -14,6 +14,8 @@
* 2000-10-29 Henner Eisen lapb_data_indication() return status.
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/module.h>
#include <asm/system.h>
@@ -96,7 +98,7 @@
x25_asy_devs[i] = dev;
return sl;
} else {
- printk(KERN_WARNING "x25_asy_alloc() - register_netdev() failure.\n");
+ pr_warn("%s(): register_netdev() failure\n", __func__);
free_netdev(dev);
}
}
@@ -114,8 +116,7 @@
sl->xbuff = NULL;
if (!test_and_clear_bit(SLF_INUSE, &sl->flags))
- printk(KERN_ERR "%s: x25_asy_free for already free unit.\n",
- sl->dev->name);
+ netdev_err(sl->dev, "x25_asy_free for already free unit\n");
}
static int x25_asy_change_mtu(struct net_device *dev, int newmtu)
@@ -128,8 +129,7 @@
rbuff = kmalloc(len + 4, GFP_ATOMIC);
if (xbuff == NULL || rbuff == NULL) {
- printk(KERN_WARNING "%s: unable to grow X.25 buffers, MTU change cancelled.\n",
- dev->name);
+ netdev_warn(dev, "unable to grow X.25 buffers, MTU change cancelled\n");
kfree(xbuff);
kfree(rbuff);
return -ENOMEM;
@@ -198,8 +198,7 @@
skb = dev_alloc_skb(count+1);
if (skb == NULL) {
- printk(KERN_WARNING "%s: memory squeeze, dropping packet.\n",
- sl->dev->name);
+ netdev_warn(sl->dev, "memory squeeze, dropping packet\n");
dev->stats.rx_dropped++;
return;
}
@@ -287,9 +286,9 @@
/* May be we must check transmitter timeout here ?
* 14 Oct 1994 Dmitry Gorodchanin.
*/
- printk(KERN_WARNING "%s: transmit timed out, %s?\n", dev->name,
- (tty_chars_in_buffer(sl->tty) || sl->xleft) ?
- "bad line quality" : "driver error");
+ netdev_warn(dev, "transmit timed out, %s?\n",
+ (tty_chars_in_buffer(sl->tty) || sl->xleft) ?
+ "bad line quality" : "driver error");
sl->xleft = 0;
clear_bit(TTY_DO_WRITE_WAKEUP, &sl->tty->flags);
x25_asy_unlock(sl);
@@ -306,8 +305,7 @@
int err;
if (!netif_running(sl->dev)) {
- printk(KERN_ERR "%s: xmit call when iface is down\n",
- dev->name);
+ netdev_err(dev, "xmit call when iface is down\n");
kfree_skb(skb);
return NETDEV_TX_OK;
}
@@ -318,13 +316,15 @@
case X25_IFACE_CONNECT: /* Connection request .. do nothing */
err = lapb_connect_request(dev);
if (err != LAPB_OK)
- printk(KERN_ERR "x25_asy: lapb_connect_request error - %d\n", err);
+ netdev_err(dev, "lapb_connect_request error: %d\n",
+ err);
kfree_skb(skb);
return NETDEV_TX_OK;
case X25_IFACE_DISCONNECT: /* do nothing - hang up ?? */
err = lapb_disconnect_request(dev);
if (err != LAPB_OK)
- printk(KERN_ERR "x25_asy: lapb_disconnect_request error - %d\n", err);
+ netdev_err(dev, "lapb_disconnect_request error: %d\n",
+ err);
default:
kfree_skb(skb);
return NETDEV_TX_OK;
@@ -343,7 +343,7 @@
err = lapb_data_request(dev, skb);
if (err != LAPB_OK) {
- printk(KERN_ERR "x25_asy: lapb_data_request error - %d\n", err);
+ netdev_err(dev, "lapb_data_request error: %d\n", err);
kfree_skb(skb);
return NETDEV_TX_OK;
}
@@ -378,7 +378,7 @@
spin_lock(&sl->lock);
if (netif_queue_stopped(sl->dev) || sl->tty == NULL) {
spin_unlock(&sl->lock);
- printk(KERN_ERR "x25_asy: tbusy drop\n");
+ netdev_err(dev, "tbusy drop\n");
kfree_skb(skb);
return;
}
@@ -404,7 +404,7 @@
skb = dev_alloc_skb(1);
if (skb == NULL) {
- printk(KERN_ERR "x25_asy: out of memory\n");
+ netdev_err(dev, "out of memory\n");
return;
}
@@ -423,7 +423,7 @@
skb = dev_alloc_skb(1);
if (skb == NULL) {
- printk(KERN_ERR "x25_asy: out of memory\n");
+ netdev_err(dev, "out of memory\n");
return;
}
@@ -603,8 +603,8 @@
err = lapb_unregister(sl->dev);
if (err != LAPB_OK)
- printk(KERN_ERR "x25_asy_close: lapb_unregister error -%d\n",
- err);
+ pr_err("x25_asy_close: lapb_unregister error: %d\n",
+ err);
tty->disc_data = NULL;
sl->tty = NULL;
@@ -782,14 +782,13 @@
if (x25_asy_maxdev < 4)
x25_asy_maxdev = 4; /* Sanity */
- printk(KERN_INFO "X.25 async: version 0.00 ALPHA "
- "(dynamic channels, max=%d).\n", x25_asy_maxdev);
+ pr_info("X.25 async: version 0.00 ALPHA (dynamic channels, max=%d)\n",
+ x25_asy_maxdev);
x25_asy_devs = kcalloc(x25_asy_maxdev, sizeof(struct net_device *),
GFP_KERNEL);
if (!x25_asy_devs) {
- printk(KERN_WARNING "X25 async: Can't allocate x25_asy_ctrls[] "
- "array! Uaargh! (-> No X.25 available)\n");
+ pr_warn("Can't allocate x25_asy_ctrls[] array! Uaargh! (-> No X.25 available)\n");
return -ENOMEM;
}
diff --git a/drivers/net/wan/z85230.c b/drivers/net/wan/z85230.c
index 0806232..0e57690 100644
--- a/drivers/net/wan/z85230.c
+++ b/drivers/net/wan/z85230.c
@@ -36,6 +36,8 @@
* Synchronous mode without DMA is unlikely to pass about 2400 baud.
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/mm.h>
@@ -365,7 +367,7 @@
c->count=0;
if(stat&Rx_OVR)
{
- printk(KERN_WARNING "%s: overrun\n", c->dev->name);
+ pr_warn("%s: overrun\n", c->dev->name);
c->rx_overrun++;
}
if(stat&CRC_ERR)
@@ -464,12 +466,12 @@
if (altered & chan->dcdcheck)
{
if (status & chan->dcdcheck) {
- printk(KERN_INFO "%s: DCD raised\n", chan->dev->name);
+ pr_info("%s: DCD raised\n", chan->dev->name);
write_zsreg(chan, R3, chan->regs[3] | RxENABLE);
if (chan->netdevice)
netif_carrier_on(chan->netdevice);
} else {
- printk(KERN_INFO "%s: DCD lost\n", chan->dev->name);
+ pr_info("%s: DCD lost\n", chan->dev->name);
write_zsreg(chan, R3, chan->regs[3] & ~RxENABLE);
z8530_flush_fifo(chan);
if (chan->netdevice)
@@ -538,12 +540,12 @@
{
if(!chan->dma_tx)
{
- printk(KERN_WARNING "Hey who turned the DMA off?\n");
+ pr_warn("Hey who turned the DMA off?\n");
z8530_tx(chan);
return;
}
/* This shouldn't occur in DMA mode */
- printk(KERN_ERR "DMA tx - bogus event!\n");
+ pr_err("DMA tx - bogus event!\n");
z8530_tx(chan);
}
@@ -585,12 +587,12 @@
if (altered & chan->dcdcheck)
{
if (status & chan->dcdcheck) {
- printk(KERN_INFO "%s: DCD raised\n", chan->dev->name);
+ pr_info("%s: DCD raised\n", chan->dev->name);
write_zsreg(chan, R3, chan->regs[3] | RxENABLE);
if (chan->netdevice)
netif_carrier_on(chan->netdevice);
} else {
- printk(KERN_INFO "%s:DCD lost\n", chan->dev->name);
+ pr_info("%s: DCD lost\n", chan->dev->name);
write_zsreg(chan, R3, chan->regs[3] & ~RxENABLE);
z8530_flush_fifo(chan);
if (chan->netdevice)
@@ -712,7 +714,7 @@
if(locker)
{
- printk(KERN_ERR "IRQ re-enter\n");
+ pr_err("IRQ re-enter\n");
return IRQ_NONE;
}
locker=1;
@@ -758,7 +760,8 @@
}
spin_unlock(&dev->lock);
if(work==5000)
- printk(KERN_ERR "%s: interrupt jammed - abort(0x%X)!\n", dev->name, intr);
+ pr_err("%s: interrupt jammed - abort(0x%X)!\n",
+ dev->name, intr);
/* Ok all done */
locker=0;
return IRQ_HANDLED;
@@ -1225,7 +1228,7 @@
void z8530_describe(struct z8530_dev *dev, char *mapping, unsigned long io)
{
- printk(KERN_INFO "%s: %s found at %s 0x%lX, IRQ %d.\n",
+ pr_info("%s: %s found at %s 0x%lX, IRQ %d\n",
dev->name,
z8530_type_name[dev->type],
mapping,
@@ -1621,8 +1624,7 @@
else
/* Can't occur as we dont reenable the DMA irq until
after the flip is done */
- printk(KERN_WARNING "%s: DMA flip overrun!\n",
- c->netdevice->name);
+ netdev_warn(c->netdevice, "DMA flip overrun!\n");
release_dma_lock(flags);
@@ -1637,8 +1639,7 @@
skb = dev_alloc_skb(ct);
if (skb == NULL) {
c->netdevice->stats.rx_dropped++;
- printk(KERN_WARNING "%s: Memory squeeze.\n",
- c->netdevice->name);
+ netdev_warn(c->netdevice, "Memory squeeze\n");
} else {
skb_put(skb, ct);
skb_copy_to_linear_data(skb, rxb, ct);
@@ -1678,8 +1679,7 @@
c->skb2 = dev_alloc_skb(c->mtu);
if (c->skb2 == NULL)
- printk(KERN_WARNING "%s: memory squeeze.\n",
- c->netdevice->name);
+ netdev_warn(c->netdevice, "memory squeeze\n");
else
skb_put(c->skb2, c->mtu);
c->netdevice->stats.rx_packets++;
@@ -1693,7 +1693,7 @@
c->rx_function(c, skb);
} else {
c->netdevice->stats.rx_dropped++;
- printk(KERN_ERR "%s: Lost a frame\n", c->netdevice->name);
+ netdev_err(c->netdevice, "Lost a frame\n");
}
}
diff --git a/drivers/net/wireless/adm8211.c b/drivers/net/wireless/adm8211.c
index afe2cbc..43ebc44 100644
--- a/drivers/net/wireless/adm8211.c
+++ b/drivers/net/wireless/adm8211.c
@@ -16,6 +16,7 @@
*/
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/if.h>
#include <linux/skbuff.h>
#include <linux/slab.h>
diff --git a/drivers/net/wireless/ath/ath.h b/drivers/net/wireless/ath/ath.h
index 7cf4317..17c4b56 100644
--- a/drivers/net/wireless/ath/ath.h
+++ b/drivers/net/wireless/ath/ath.h
@@ -161,6 +161,7 @@
const struct ath_bus_ops *bus_ops;
bool btcoex_enabled;
+ bool disable_ani;
};
struct sk_buff *ath_rxbuf_alloc(struct ath_common *common,
diff --git a/drivers/net/wireless/ath/ath5k/ahb.c b/drivers/net/wireless/ath/ath5k/ahb.c
index ea99827..c38e9e8 100644
--- a/drivers/net/wireless/ath/ath5k/ahb.c
+++ b/drivers/net/wireless/ath/ath5k/ahb.c
@@ -219,6 +219,7 @@
ath5k_deinit_softc(sc);
platform_set_drvdata(pdev, NULL);
+ ieee80211_free_hw(hw);
return 0;
}
diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h
index bb50700..c4c02d5 100644
--- a/drivers/net/wireless/ath/ath5k/ath5k.h
+++ b/drivers/net/wireless/ath/ath5k/ath5k.h
@@ -767,6 +767,7 @@
*/
#define AR5K_KEYCACHE_SIZE 8
+extern int ath5k_modparam_nohwcrypt;
/***********************\
HW RELATED DEFINITIONS
@@ -1180,8 +1181,8 @@
struct ath5k_buf;
struct ath5k_txq;
-void set_beacon_filter(struct ieee80211_hw *hw, bool enable);
-bool ath_any_vif_assoc(struct ath5k_softc *sc);
+void ath5k_set_beacon_filter(struct ieee80211_hw *hw, bool enable);
+bool ath5k_any_vif_assoc(struct ath5k_softc *sc);
void ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb,
struct ath5k_txq *txq);
int ath5k_init_hw(struct ath5k_softc *sc);
@@ -1253,7 +1254,7 @@
int len, struct ieee80211_rate *rate, bool shortpre);
unsigned int ath5k_hw_get_default_slottime(struct ath5k_hw *ah);
unsigned int ath5k_hw_get_default_sifs(struct ath5k_hw *ah);
-extern int ath5k_hw_set_opmode(struct ath5k_hw *ah, enum nl80211_iftype opmode);
+int ath5k_hw_set_opmode(struct ath5k_hw *ah, enum nl80211_iftype opmode);
void ath5k_hw_set_coverage_class(struct ath5k_hw *ah, u8 coverage_class);
/* RX filter control*/
int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac);
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c
index b6c5d37..fb05bf8 100644
--- a/drivers/net/wireless/ath/ath5k/base.c
+++ b/drivers/net/wireless/ath/ath5k/base.c
@@ -42,6 +42,7 @@
#include <linux/module.h>
#include <linux/delay.h>
+#include <linux/dma-mapping.h>
#include <linux/hardirq.h>
#include <linux/if.h>
#include <linux/io.h>
@@ -87,8 +88,6 @@
static int ath5k_init(struct ieee80211_hw *hw);
static int ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan,
bool skip_pcu);
-int ath5k_beacon_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
-void ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf);
/* Known SREVs */
static const struct ath5k_srev_name srev_names[] = {
@@ -2161,7 +2160,7 @@
tasklet_schedule(&sc->txtq);
}
-irqreturn_t
+static irqreturn_t
ath5k_intr(int irq, void *dev_id)
{
struct ath5k_softc *sc = dev_id;
@@ -2615,7 +2614,7 @@
return ret;
}
-static void stop_tasklets(struct ath5k_softc *sc)
+static void ath5k_stop_tasklets(struct ath5k_softc *sc)
{
sc->rx_pending = false;
sc->tx_pending = false;
@@ -2669,7 +2668,7 @@
mmiowb();
mutex_unlock(&sc->lock);
- stop_tasklets(sc);
+ ath5k_stop_tasklets(sc);
cancel_delayed_work_sync(&sc->tx_complete_work);
@@ -2697,7 +2696,7 @@
ath5k_hw_set_imr(ah, 0);
synchronize_irq(sc->irq);
- stop_tasklets(sc);
+ ath5k_stop_tasklets(sc);
/* Save ani mode and disable ANI during
* reset. If we don't we might get false
@@ -2962,11 +2961,12 @@
* state and potentially want to use them.
*/
ath5k_hw_deinit(sc->ah);
+ kfree(sc->ah);
free_irq(sc->irq, sc);
}
bool
-ath_any_vif_assoc(struct ath5k_softc *sc)
+ath5k_any_vif_assoc(struct ath5k_softc *sc)
{
struct ath5k_vif_iter_data iter_data;
iter_data.hw_macaddr = NULL;
@@ -2980,7 +2980,7 @@
}
void
-set_beacon_filter(struct ieee80211_hw *hw, bool enable)
+ath5k_set_beacon_filter(struct ieee80211_hw *hw, bool enable)
{
struct ath5k_softc *sc = hw->priv;
struct ath5k_hw *ah = sc->ah;
diff --git a/drivers/net/wireless/ath/ath5k/mac80211-ops.c b/drivers/net/wireless/ath/ath5k/mac80211-ops.c
index 807bd64..4939082 100644
--- a/drivers/net/wireless/ath/ath5k/mac80211-ops.c
+++ b/drivers/net/wireless/ath/ath5k/mac80211-ops.c
@@ -46,8 +46,6 @@
#include "base.h"
#include "reg.h"
-extern int ath5k_modparam_nohwcrypt;
-
/********************\
* Mac80211 functions *
\********************/
@@ -296,10 +294,10 @@
if (bss_conf->assoc)
sc->assoc = bss_conf->assoc;
else
- sc->assoc = ath_any_vif_assoc(sc);
+ sc->assoc = ath5k_any_vif_assoc(sc);
if (sc->opmode == NL80211_IFTYPE_STATION)
- set_beacon_filter(hw, sc->assoc);
+ ath5k_set_beacon_filter(hw, sc->assoc);
ath5k_hw_set_ledstate(sc->ah, sc->assoc ?
AR5K_LED_ASSOC : AR5K_LED_INIT);
if (bss_conf->assoc) {
diff --git a/drivers/net/wireless/ath/ath5k/reset.c b/drivers/net/wireless/ath/ath5k/reset.c
index 126a4ea..1676a3e 100644
--- a/drivers/net/wireless/ath/ath5k/reset.c
+++ b/drivers/net/wireless/ath/ath5k/reset.c
@@ -375,19 +375,19 @@
static int ath5k_hw_wisoc_reset(struct ath5k_hw *ah, u32 flags)
{
u32 mask = flags ? flags : ~0U;
- volatile u32 *reg;
+ volatile __iomem u32 *reg;
u32 regval;
u32 val = 0;
/* ah->ah_mac_srev is not available at this point yet */
if (ah->ah_sc->devid >= AR5K_SREV_AR2315_R6) {
- reg = (u32 *) AR5K_AR2315_RESET;
+ reg = (u32 __iomem *) AR5K_AR2315_RESET;
if (mask & AR5K_RESET_CTL_PCU)
val |= AR5K_AR2315_RESET_WMAC;
if (mask & AR5K_RESET_CTL_BASEBAND)
val |= AR5K_AR2315_RESET_BB_WARM;
} else {
- reg = (u32 *) AR5K_AR5312_RESET;
+ reg = (u32 __iomem *) AR5K_AR5312_RESET;
if (to_platform_device(ah->ah_sc->dev)->id == 0) {
if (mask & AR5K_RESET_CTL_PCU)
val |= AR5K_AR5312_RESET_WMAC0;
diff --git a/drivers/net/wireless/ath/ath9k/ahb.c b/drivers/net/wireless/ath/ath9k/ahb.c
index 5b49cd0..0b36fcf 100644
--- a/drivers/net/wireless/ath/ath9k/ahb.c
+++ b/drivers/net/wireless/ath/ath9k/ahb.c
@@ -27,6 +27,10 @@
.driver_data = AR5416_AR9100_DEVID,
},
{
+ .name = "ar933x_wmac",
+ .driver_data = AR9300_DEVID_AR9330,
+ },
+ {
.name = "ar934x_wmac",
.driver_data = AR9300_DEVID_AR9340,
},
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_mac.c b/drivers/net/wireless/ath/ath9k/ar9002_mac.c
index 077e8a6..45b262f 100644
--- a/drivers/net/wireless/ath/ath9k/ar9002_mac.c
+++ b/drivers/net/wireless/ath/ath9k/ar9002_mac.c
@@ -28,11 +28,6 @@
((struct ath_desc*) ds)->ds_link = ds_link;
}
-static void ar9002_hw_get_desc_link(void *ds, u32 **ds_link)
-{
- *ds_link = &((struct ath_desc *)ds)->ds_link;
-}
-
static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
{
u32 isr = 0;
@@ -437,7 +432,6 @@
ops->rx_enable = ar9002_hw_rx_enable;
ops->set_desc_link = ar9002_hw_set_desc_link;
- ops->get_desc_link = ar9002_hw_get_desc_link;
ops->get_isr = ar9002_hw_get_isr;
ops->fill_txdesc = ar9002_hw_fill_txdesc;
ops->proc_txdesc = ar9002_hw_proc_txdesc;
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
index ff8150e..1d09f22 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
@@ -1461,7 +1461,7 @@
{ { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
{ { CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 1) } },
- { { CTL(60, 1), CTL(60, 0), CTL(0, 0), CTL(0, 0) } },
+ { { CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0) } },
{ { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
{ { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
@@ -2616,7 +2616,7 @@
{ { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
{ { CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 1) } },
- { { CTL(60, 1), CTL(60, 0), CTL(0, 0), CTL(0, 0) } },
+ { { CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0) } },
{ { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
{ { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
@@ -3324,6 +3324,8 @@
read = ar9300_read_eeprom;
if (AR_SREV_9485(ah))
cptr = AR9300_BASE_ADDR_4K;
+ else if (AR_SREV_9330(ah))
+ cptr = AR9300_BASE_ADDR_512;
else
cptr = AR9300_BASE_ADDR;
ath_dbg(common, ATH_DBG_EEPROM,
@@ -3442,7 +3444,7 @@
{
int bias = ar9003_hw_xpa_bias_level_get(ah, is2ghz);
- if (AR_SREV_9485(ah) || AR_SREV_9340(ah))
+ 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 {
REG_RMW_FIELD(ah, AR_CH0_TOP, AR_CH0_TOP_XPABIASLVL, bias);
@@ -3523,7 +3525,7 @@
}
}
- if (AR_SREV_9485(ah)) {
+ if (AR_SREV_9330(ah) || AR_SREV_9485(ah)) {
value = ath9k_hw_ar9300_get_eeprom(ah, EEP_ANT_DIV_CTL1);
/*
* main_lnaconf, alt_lnaconf, main_tb, alt_tb
@@ -3710,7 +3712,7 @@
ath9k_hw_ar9300_get_eeprom(ah, EEP_INTERNAL_REGULATOR);
if (internal_regulator) {
- if (AR_SREV_9485(ah)) {
+ if (AR_SREV_9330(ah) || AR_SREV_9485(ah)) {
int reg_pmu_set;
reg_pmu_set = REG_READ(ah, AR_PHY_PMU2) & ~AR_PHY_PMU2_PGM;
@@ -3718,9 +3720,24 @@
if (!is_pmu_set(ah, AR_PHY_PMU2, reg_pmu_set))
return;
- reg_pmu_set = (5 << 1) | (7 << 4) | (1 << 8) |
- (2 << 14) | (6 << 17) | (1 << 20) |
- (3 << 24) | (1 << 28);
+ if (AR_SREV_9330(ah)) {
+ if (ah->is_clk_25mhz) {
+ reg_pmu_set = (3 << 1) | (8 << 4) |
+ (3 << 8) | (1 << 14) |
+ (6 << 17) | (1 << 20) |
+ (3 << 24);
+ } else {
+ reg_pmu_set = (4 << 1) | (7 << 4) |
+ (3 << 8) | (1 << 14) |
+ (6 << 17) | (1 << 20) |
+ (3 << 24);
+ }
+ } else {
+ reg_pmu_set = (5 << 1) | (7 << 4) |
+ (1 << 8) | (2 << 14) |
+ (6 << 17) | (1 << 20) |
+ (3 << 24) | (1 << 28);
+ }
REG_WRITE(ah, AR_PHY_PMU1, reg_pmu_set);
if (!is_pmu_set(ah, AR_PHY_PMU1, reg_pmu_set))
@@ -3751,7 +3768,7 @@
AR_RTC_REG_CONTROL1_SWREG_PROGRAM);
}
} else {
- if (AR_SREV_9485(ah)) {
+ if (AR_SREV_9330(ah) || AR_SREV_9485(ah)) {
REG_RMW_FIELD(ah, AR_PHY_PMU2, AR_PHY_PMU2_PGM, 0);
while (REG_READ_FIELD(ah, AR_PHY_PMU2,
AR_PHY_PMU2_PGM))
@@ -3795,9 +3812,9 @@
ar9003_hw_ant_ctrl_apply(ah, IS_CHAN_2GHZ(chan));
ar9003_hw_drive_strength_apply(ah);
ar9003_hw_atten_apply(ah, chan);
- if (!AR_SREV_9340(ah))
+ if (!AR_SREV_9330(ah) && !AR_SREV_9340(ah))
ar9003_hw_internal_regulator_apply(ah);
- if (AR_SREV_9485(ah) || AR_SREV_9340(ah))
+ if (AR_SREV_9485(ah) || AR_SREV_9330(ah) || AR_SREV_9340(ah))
ar9003_hw_apply_tuning_caps(ah);
}
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_hw.c b/drivers/net/wireless/ath/ath9k/ar9003_hw.c
index 392bf0f..8efdec2 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c
@@ -19,6 +19,8 @@
#include "ar9003_2p2_initvals.h"
#include "ar9485_initvals.h"
#include "ar9340_initvals.h"
+#include "ar9330_1p1_initvals.h"
+#include "ar9330_1p2_initvals.h"
/* General hardware code for the AR9003 hadware family */
@@ -29,7 +31,113 @@
*/
static void ar9003_hw_init_mode_regs(struct ath_hw *ah)
{
- if (AR_SREV_9340(ah)) {
+ if (AR_SREV_9330_11(ah)) {
+ /* mac */
+ INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0);
+ INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE],
+ ar9331_1p1_mac_core,
+ ARRAY_SIZE(ar9331_1p1_mac_core), 2);
+ INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST],
+ ar9331_1p1_mac_postamble,
+ ARRAY_SIZE(ar9331_1p1_mac_postamble), 5);
+
+ /* bb */
+ INIT_INI_ARRAY(&ah->iniBB[ATH_INI_PRE], NULL, 0, 0);
+ INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE],
+ ar9331_1p1_baseband_core,
+ ARRAY_SIZE(ar9331_1p1_baseband_core), 2);
+ INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST],
+ ar9331_1p1_baseband_postamble,
+ ARRAY_SIZE(ar9331_1p1_baseband_postamble), 5);
+
+ /* radio */
+ INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_PRE], NULL, 0, 0);
+ INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE],
+ ar9331_1p1_radio_core,
+ ARRAY_SIZE(ar9331_1p1_radio_core), 2);
+ INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST], NULL, 0, 0);
+
+ /* soc */
+ INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE],
+ ar9331_1p1_soc_preamble,
+ ARRAY_SIZE(ar9331_1p1_soc_preamble), 2);
+ INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_CORE], NULL, 0, 0);
+ INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST],
+ ar9331_1p1_soc_postamble,
+ ARRAY_SIZE(ar9331_1p1_soc_postamble), 2);
+
+ /* rx/tx gain */
+ INIT_INI_ARRAY(&ah->iniModesRxGain,
+ ar9331_common_rx_gain_1p1,
+ ARRAY_SIZE(ar9331_common_rx_gain_1p1), 2);
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9331_modes_lowest_ob_db_tx_gain_1p1,
+ ARRAY_SIZE(ar9331_modes_lowest_ob_db_tx_gain_1p1),
+ 5);
+
+ /* additional clock settings */
+ if (ah->is_clk_25mhz)
+ INIT_INI_ARRAY(&ah->iniModesAdditional,
+ ar9331_1p1_xtal_25M,
+ ARRAY_SIZE(ar9331_1p1_xtal_25M), 2);
+ else
+ INIT_INI_ARRAY(&ah->iniModesAdditional,
+ ar9331_1p1_xtal_40M,
+ ARRAY_SIZE(ar9331_1p1_xtal_40M), 2);
+ } else if (AR_SREV_9330_12(ah)) {
+ /* mac */
+ INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0);
+ INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE],
+ ar9331_1p2_mac_core,
+ ARRAY_SIZE(ar9331_1p2_mac_core), 2);
+ INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST],
+ ar9331_1p2_mac_postamble,
+ ARRAY_SIZE(ar9331_1p2_mac_postamble), 5);
+
+ /* bb */
+ INIT_INI_ARRAY(&ah->iniBB[ATH_INI_PRE], NULL, 0, 0);
+ INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE],
+ ar9331_1p2_baseband_core,
+ ARRAY_SIZE(ar9331_1p2_baseband_core), 2);
+ INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST],
+ ar9331_1p2_baseband_postamble,
+ ARRAY_SIZE(ar9331_1p2_baseband_postamble), 5);
+
+ /* radio */
+ INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_PRE], NULL, 0, 0);
+ INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE],
+ ar9331_1p2_radio_core,
+ ARRAY_SIZE(ar9331_1p2_radio_core), 2);
+ INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST], NULL, 0, 0);
+
+ /* soc */
+ INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE],
+ ar9331_1p2_soc_preamble,
+ ARRAY_SIZE(ar9331_1p2_soc_preamble), 2);
+ INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_CORE], NULL, 0, 0);
+ INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST],
+ ar9331_1p2_soc_postamble,
+ ARRAY_SIZE(ar9331_1p2_soc_postamble), 2);
+
+ /* rx/tx gain */
+ INIT_INI_ARRAY(&ah->iniModesRxGain,
+ ar9331_common_rx_gain_1p2,
+ ARRAY_SIZE(ar9331_common_rx_gain_1p2), 2);
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9331_modes_lowest_ob_db_tx_gain_1p2,
+ ARRAY_SIZE(ar9331_modes_lowest_ob_db_tx_gain_1p2),
+ 5);
+
+ /* additional clock settings */
+ if (ah->is_clk_25mhz)
+ INIT_INI_ARRAY(&ah->iniModesAdditional,
+ ar9331_1p2_xtal_25M,
+ ARRAY_SIZE(ar9331_1p2_xtal_25M), 2);
+ else
+ INIT_INI_ARRAY(&ah->iniModesAdditional,
+ ar9331_1p2_xtal_40M,
+ ARRAY_SIZE(ar9331_1p2_xtal_40M), 2);
+ } else if (AR_SREV_9340(ah)) {
/* mac */
INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0);
INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE],
@@ -220,7 +328,17 @@
switch (ar9003_hw_get_tx_gain_idx(ah)) {
case 0:
default:
- if (AR_SREV_9340(ah))
+ if (AR_SREV_9330_12(ah))
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9331_modes_lowest_ob_db_tx_gain_1p2,
+ ARRAY_SIZE(ar9331_modes_lowest_ob_db_tx_gain_1p2),
+ 5);
+ else if (AR_SREV_9330_11(ah))
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9331_modes_lowest_ob_db_tx_gain_1p1,
+ ARRAY_SIZE(ar9331_modes_lowest_ob_db_tx_gain_1p1),
+ 5);
+ else if (AR_SREV_9340(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9340Modes_lowest_ob_db_tx_gain_table_1p0,
ARRAY_SIZE(ar9340Modes_lowest_ob_db_tx_gain_table_1p0),
@@ -237,7 +355,17 @@
5);
break;
case 1:
- if (AR_SREV_9340(ah))
+ if (AR_SREV_9330_12(ah))
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9331_modes_high_ob_db_tx_gain_1p2,
+ ARRAY_SIZE(ar9331_modes_high_ob_db_tx_gain_1p2),
+ 5);
+ else if (AR_SREV_9330_11(ah))
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9331_modes_high_ob_db_tx_gain_1p1,
+ ARRAY_SIZE(ar9331_modes_high_ob_db_tx_gain_1p1),
+ 5);
+ else if (AR_SREV_9340(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9340Modes_lowest_ob_db_tx_gain_table_1p0,
ARRAY_SIZE(ar9340Modes_lowest_ob_db_tx_gain_table_1p0),
@@ -254,7 +382,17 @@
5);
break;
case 2:
- if (AR_SREV_9340(ah))
+ if (AR_SREV_9330_12(ah))
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9331_modes_low_ob_db_tx_gain_1p2,
+ ARRAY_SIZE(ar9331_modes_low_ob_db_tx_gain_1p2),
+ 5);
+ else if (AR_SREV_9330_11(ah))
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9331_modes_low_ob_db_tx_gain_1p1,
+ ARRAY_SIZE(ar9331_modes_low_ob_db_tx_gain_1p1),
+ 5);
+ else if (AR_SREV_9340(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9340Modes_lowest_ob_db_tx_gain_table_1p0,
ARRAY_SIZE(ar9340Modes_lowest_ob_db_tx_gain_table_1p0),
@@ -271,7 +409,17 @@
5);
break;
case 3:
- if (AR_SREV_9340(ah))
+ if (AR_SREV_9330_12(ah))
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9331_modes_high_power_tx_gain_1p2,
+ ARRAY_SIZE(ar9331_modes_high_power_tx_gain_1p2),
+ 5);
+ else if (AR_SREV_9330_11(ah))
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9331_modes_high_power_tx_gain_1p1,
+ ARRAY_SIZE(ar9331_modes_high_power_tx_gain_1p1),
+ 5);
+ else if (AR_SREV_9340(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9340Modes_lowest_ob_db_tx_gain_table_1p0,
ARRAY_SIZE(ar9340Modes_lowest_ob_db_tx_gain_table_1p0),
@@ -295,7 +443,17 @@
switch (ar9003_hw_get_rx_gain_idx(ah)) {
case 0:
default:
- if (AR_SREV_9340(ah))
+ if (AR_SREV_9330_12(ah))
+ INIT_INI_ARRAY(&ah->iniModesRxGain,
+ ar9331_common_rx_gain_1p2,
+ ARRAY_SIZE(ar9331_common_rx_gain_1p2),
+ 2);
+ else if (AR_SREV_9330_11(ah))
+ INIT_INI_ARRAY(&ah->iniModesRxGain,
+ ar9331_common_rx_gain_1p1,
+ ARRAY_SIZE(ar9331_common_rx_gain_1p1),
+ 2);
+ else if (AR_SREV_9340(ah))
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9340Common_rx_gain_table_1p0,
ARRAY_SIZE(ar9340Common_rx_gain_table_1p0),
@@ -312,7 +470,17 @@
2);
break;
case 1:
- if (AR_SREV_9340(ah))
+ if (AR_SREV_9330_12(ah))
+ INIT_INI_ARRAY(&ah->iniModesRxGain,
+ ar9331_common_wo_xlna_rx_gain_1p2,
+ ARRAY_SIZE(ar9331_common_wo_xlna_rx_gain_1p2),
+ 2);
+ else if (AR_SREV_9330_11(ah))
+ INIT_INI_ARRAY(&ah->iniModesRxGain,
+ ar9331_common_wo_xlna_rx_gain_1p1,
+ ARRAY_SIZE(ar9331_common_wo_xlna_rx_gain_1p1),
+ 2);
+ else if (AR_SREV_9340(ah))
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9340Common_wo_xlna_rx_gain_table_1p0,
ARRAY_SIZE(ar9340Common_wo_xlna_rx_gain_table_1p0),
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.c b/drivers/net/wireless/ath/ath9k/ar9003_mac.c
index 10d71f7..575e185 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c
@@ -43,13 +43,6 @@
ads->ctl10 |= ar9003_calc_ptr_chksum(ads);
}
-static void ar9003_hw_get_desc_link(void *ds, u32 **ds_link)
-{
- struct ar9003_txc *ads = ds;
-
- *ds_link = &ads->link;
-}
-
static bool ar9003_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
{
u32 isr = 0;
@@ -236,6 +229,7 @@
static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds,
struct ath_tx_status *ts)
{
+ struct ar9003_txc *txc = (struct ar9003_txc *) ds;
struct ar9003_txs *ads;
u32 status;
@@ -245,7 +239,11 @@
if ((status & AR_TxDone) == 0)
return -EINPROGRESS;
- ah->ts_tail = (ah->ts_tail + 1) % ah->ts_size;
+ ts->qid = MS(ads->ds_info, AR_TxQcuNum);
+ if (!txc || (MS(txc->info, AR_TxQcuNum) == ts->qid))
+ ah->ts_tail = (ah->ts_tail + 1) % ah->ts_size;
+ else
+ return -ENOENT;
if ((MS(ads->ds_info, AR_DescId) != ATHEROS_VENDOR_ID) ||
(MS(ads->ds_info, AR_TxRxDesc) != 1)) {
@@ -261,7 +259,6 @@
ts->ts_seqnum = MS(status, AR_SeqNum);
ts->tid = MS(status, AR_TxTid);
- ts->qid = MS(ads->ds_info, AR_TxQcuNum);
ts->desc_id = MS(ads->status1, AR_TxDescId);
ts->ts_tstamp = ads->status4;
ts->ts_status = 0;
@@ -498,7 +495,6 @@
ops->rx_enable = ar9003_hw_rx_enable;
ops->set_desc_link = ar9003_hw_set_desc_link;
- ops->get_desc_link = ar9003_hw_get_desc_link;
ops->get_isr = ar9003_hw_get_isr;
ops->fill_txdesc = ar9003_hw_fill_txdesc;
ops->proc_txdesc = ar9003_hw_proc_txdesc;
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_paprd.c b/drivers/net/wireless/ath/ath9k/ar9003_paprd.c
index e4d6a87..de19723 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_paprd.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_paprd.c
@@ -46,11 +46,10 @@
static int ar9003_get_training_power_2g(struct ath_hw *ah)
{
- struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
- struct ar9300_modal_eep_header *hdr = &eep->modalHeader2G;
+ struct ath9k_channel *chan = ah->curchan;
unsigned int power, scale, delta;
- scale = MS(le32_to_cpu(hdr->papdRateMaskHt20), AR9300_PAPRD_SCALE_1);
+ scale = ar9003_get_paprd_scale_factor(ah, chan);
power = REG_READ_FIELD(ah, AR_PHY_POWERTX_RATE5,
AR_PHY_POWERTX_RATE5_POWERTXHT20_0);
@@ -67,20 +66,10 @@
static int ar9003_get_training_power_5g(struct ath_hw *ah)
{
struct ath_common *common = ath9k_hw_common(ah);
- struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
- struct ar9300_modal_eep_header *hdr = &eep->modalHeader5G;
struct ath9k_channel *chan = ah->curchan;
unsigned int power, scale, delta;
- if (chan->channel >= 5700)
- scale = MS(le32_to_cpu(hdr->papdRateMaskHt20),
- AR9300_PAPRD_SCALE_1);
- else if (chan->channel >= 5400)
- scale = MS(le32_to_cpu(hdr->papdRateMaskHt40),
- AR9300_PAPRD_SCALE_2);
- else
- scale = MS(le32_to_cpu(hdr->papdRateMaskHt40),
- AR9300_PAPRD_SCALE_1);
+ scale = ar9003_get_paprd_scale_factor(ah, chan);
if (IS_CHAN_HT40(chan))
power = REG_READ_FIELD(ah, AR_PHY_POWERTX_RATE8,
@@ -94,7 +83,23 @@
if (delta > scale)
return -1;
- power += 2 * get_streams(common->tx_chainmask);
+ switch (get_streams(common->tx_chainmask)) {
+ case 1:
+ delta = 6;
+ break;
+ case 2:
+ delta = 4;
+ break;
+ case 3:
+ delta = 2;
+ break;
+ default:
+ delta = 0;
+ ath_dbg(common, ATH_DBG_CALIBRATE,
+ "Invalid tx-chainmask: %u\n", common->tx_chainmask);
+ }
+
+ power += delta;
return power;
}
@@ -119,15 +124,16 @@
else
training_power = ar9003_get_training_power_5g(ah);
+ ath_dbg(common, ATH_DBG_CALIBRATE,
+ "Training power: %d, Target power: %d\n",
+ training_power, ah->paprd_target_power);
+
if (training_power < 0) {
ath_dbg(common, ATH_DBG_CALIBRATE,
"PAPRD target power delta out of range");
return -ERANGE;
}
ah->paprd_training_power = training_power;
- ath_dbg(common, ATH_DBG_CALIBRATE,
- "Training power: %d, Target power: %d\n",
- ah->paprd_training_power, ah->paprd_target_power);
REG_RMW_FIELD(ah, AR_PHY_PAPRD_AM2AM, AR_PHY_PAPRD_AM2AM_MASK,
ah->paprd_ratemask);
@@ -230,7 +236,7 @@
memset(entry, 0, sizeof(ah->paprd_gain_table_entries));
memset(index, 0, sizeof(ah->paprd_gain_table_index));
- for (i = 0; i < 32; i++) {
+ for (i = 0; i < PAPRD_GAIN_TABLE_ENTRIES; i++) {
entry[i] = REG_READ(ah, reg);
index[i] = (entry[i] >> 24) & 0xff;
reg += 4;
@@ -240,13 +246,13 @@
static unsigned int ar9003_get_desired_gain(struct ath_hw *ah, int chain,
int target_power)
{
- int olpc_gain_delta = 0;
+ int olpc_gain_delta = 0, cl_gain_mod;
int alpha_therm, alpha_volt;
int therm_cal_value, volt_cal_value;
int therm_value, volt_value;
int thermal_gain_corr, voltage_gain_corr;
int desired_scale, desired_gain = 0;
- u32 reg;
+ u32 reg_olpc = 0, reg_cl_gain = 0;
REG_CLR_BIT(ah, AR_PHY_PAPRD_TRAINER_STAT1,
AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_DONE);
@@ -265,15 +271,29 @@
volt_value = REG_READ_FIELD(ah, AR_PHY_BB_THERM_ADC_4,
AR_PHY_BB_THERM_ADC_4_LATEST_VOLT_VALUE);
- if (chain == 0)
- reg = AR_PHY_TPC_11_B0;
- else if (chain == 1)
- reg = AR_PHY_TPC_11_B1;
- else
- reg = AR_PHY_TPC_11_B2;
+ switch (chain) {
+ case 0:
+ reg_olpc = AR_PHY_TPC_11_B0;
+ reg_cl_gain = AR_PHY_CL_TAB_0;
+ break;
+ case 1:
+ reg_olpc = AR_PHY_TPC_11_B1;
+ reg_cl_gain = AR_PHY_CL_TAB_1;
+ break;
+ case 2:
+ reg_olpc = AR_PHY_TPC_11_B2;
+ reg_cl_gain = AR_PHY_CL_TAB_2;
+ break;
+ default:
+ ath_dbg(ath9k_hw_common(ah), ATH_DBG_CALIBRATE,
+ "Invalid chainmask: %d\n", chain);
+ break;
+ }
- olpc_gain_delta = REG_READ_FIELD(ah, reg,
+ olpc_gain_delta = REG_READ_FIELD(ah, reg_olpc,
AR_PHY_TPC_11_OLPC_GAIN_DELTA);
+ cl_gain_mod = REG_READ_FIELD(ah, reg_cl_gain,
+ AR_PHY_CL_TAB_CL_GAIN_MOD);
if (olpc_gain_delta >= 128)
olpc_gain_delta = olpc_gain_delta - 256;
@@ -283,7 +303,7 @@
voltage_gain_corr = (alpha_volt * (volt_value - volt_cal_value) +
(128 / 2)) / 128;
desired_gain = target_power - olpc_gain_delta - thermal_gain_corr -
- voltage_gain_corr + desired_scale;
+ voltage_gain_corr + desired_scale + cl_gain_mod;
return desired_gain;
}
@@ -721,7 +741,7 @@
desired_gain = ar9003_get_desired_gain(ah, chain, train_power);
gain_index = 0;
- for (i = 0; i < 32; i++) {
+ for (i = 0; i < PAPRD_GAIN_TABLE_ENTRIES; i++) {
if (ah->paprd_gain_table_index[i] >= desired_gain)
break;
gain_index++;
@@ -795,7 +815,26 @@
bool ar9003_paprd_is_done(struct ath_hw *ah)
{
- return !!REG_READ_FIELD(ah, AR_PHY_PAPRD_TRAINER_STAT1,
+ int paprd_done, agc2_pwr;
+ paprd_done = REG_READ_FIELD(ah, AR_PHY_PAPRD_TRAINER_STAT1,
AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_DONE);
+
+ if (paprd_done == 0x1) {
+ agc2_pwr = REG_READ_FIELD(ah, AR_PHY_PAPRD_TRAINER_STAT1,
+ AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_AGC2_PWR);
+
+ ath_dbg(ath9k_hw_common(ah), ATH_DBG_CALIBRATE,
+ "AGC2_PWR = 0x%x training done = 0x%x\n",
+ agc2_pwr, paprd_done);
+ /*
+ * agc2_pwr range should not be less than 'IDEAL_AGC2_PWR_CHANGE'
+ * when the training is completely done, otherwise retraining is
+ * done to make sure the value is in ideal range
+ */
+ if (agc2_pwr <= PAPRD_IDEAL_AGC2_PWR_RANGE)
+ paprd_done = 0;
+ }
+
+ return !!paprd_done;
}
EXPORT_SYMBOL(ar9003_paprd_is_done);
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
index 892c48b..1baca8e 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
@@ -75,7 +75,19 @@
freq = centers.synth_center;
if (freq < 4800) { /* 2 GHz, fractional mode */
- if (AR_SREV_9485(ah)) {
+ if (AR_SREV_9330(ah)) {
+ u32 chan_frac;
+ u32 div;
+
+ if (ah->is_clk_25mhz)
+ div = 75;
+ else
+ div = 120;
+
+ channelSel = (freq * 4) / div;
+ chan_frac = (((freq * 4) % div) * 0x20000) / div;
+ channelSel = (channelSel << 17) | chan_frac;
+ } else if (AR_SREV_9485(ah)) {
u32 chan_frac;
/*
@@ -104,7 +116,7 @@
u32 chan_frac;
channelSel = (freq * 2) / 75;
- chan_frac = ((freq % 75) * 0x20000) / 75;
+ chan_frac = (((freq * 2) % 75) * 0x20000) / 75;
channelSel = (channelSel << 17) | chan_frac;
} else {
channelSel = CHANSEL_5G(freq);
@@ -168,7 +180,7 @@
* is out-of-band and can be ignored.
*/
- if (AR_SREV_9485(ah) || AR_SREV_9340(ah)) {
+ if (AR_SREV_9485(ah) || AR_SREV_9340(ah) || AR_SREV_9330(ah)) {
spur_fbin_ptr = ar9003_get_spur_chan_ptr(ah,
IS_CHAN_2GHZ(chan));
if (spur_fbin_ptr[0] == 0) /* No spur */
@@ -193,7 +205,7 @@
for (i = 0; i < max_spur_cnts; i++) {
negative = 0;
- if (AR_SREV_9485(ah) || AR_SREV_9340(ah))
+ if (AR_SREV_9485(ah) || AR_SREV_9340(ah) || AR_SREV_9330(ah))
cur_bb_spur = FBIN2FREQ(spur_fbin_ptr[i],
IS_CHAN_2GHZ(chan)) - synth_freq;
else
@@ -659,6 +671,9 @@
REG_WRITE_ARRAY(&ah->iniModesAdditional,
modesIndex, regWrites);
+ if (AR_SREV_9300(ah))
+ REG_WRITE_ARRAY(&ah->iniModesAdditional, 1, regWrites);
+
if (AR_SREV_9340(ah) && !ah->is_clk_25mhz)
REG_WRITE_ARRAY(&ah->iniModesAdditional_40M, 1, regWrites);
@@ -1074,7 +1089,10 @@
{
ah->nf_2g.max = AR_PHY_CCA_MAX_GOOD_VAL_9300_2GHZ;
ah->nf_2g.min = AR_PHY_CCA_MIN_GOOD_VAL_9300_2GHZ;
- ah->nf_2g.nominal = AR_PHY_CCA_NOM_VAL_9300_2GHZ;
+ if (AR_SREV_9330(ah))
+ ah->nf_2g.nominal = AR_PHY_CCA_NOM_VAL_9330_2GHZ;
+ else
+ ah->nf_2g.nominal = AR_PHY_CCA_NOM_VAL_9300_2GHZ;
ah->nf_5g.max = AR_PHY_CCA_MAX_GOOD_VAL_9300_5GHZ;
ah->nf_5g.min = AR_PHY_CCA_MIN_GOOD_VAL_9300_5GHZ;
ah->nf_5g.nominal = AR_PHY_CCA_NOM_VAL_9300_5GHZ;
@@ -1196,8 +1214,17 @@
AR_PHY_9485_ANT_DIV_ALT_LNACONF_S;
antconf->fast_div_bias = (regval & AR_PHY_9485_ANT_FAST_DIV_BIAS) >>
AR_PHY_9485_ANT_FAST_DIV_BIAS_S;
- antconf->lna1_lna2_delta = -9;
- antconf->div_group = 2;
+
+ if (AR_SREV_9330_11(ah)) {
+ antconf->lna1_lna2_delta = -9;
+ antconf->div_group = 1;
+ } else if (AR_SREV_9485(ah)) {
+ antconf->lna1_lna2_delta = -9;
+ antconf->div_group = 2;
+ } else {
+ antconf->lna1_lna2_delta = -3;
+ antconf->div_group = 0;
+ }
}
static void ar9003_hw_antdiv_comb_conf_set(struct ath_hw *ah,
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.h b/drivers/net/wireless/ath/ath9k/ar9003_phy.h
index 443090d..6de3f0b 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.h
+++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.h
@@ -332,6 +332,8 @@
#define AR_PHY_CCA_MAX_GOOD_VAL_9300_2GHZ -95
#define AR_PHY_CCA_MAX_GOOD_VAL_9300_5GHZ -100
+#define AR_PHY_CCA_NOM_VAL_9330_2GHZ -118
+
/*
* AGC Field Definitions
*/
@@ -623,11 +625,11 @@
#define AR_PHY_65NM_CH2_RXTX1 0x16900
#define AR_PHY_65NM_CH2_RXTX2 0x16904
-#define AR_CH0_TOP2 (AR_SREV_9485(ah) ? 0x00016284 : 0x0001628c)
+#define AR_CH0_TOP2 (AR_SREV_9300(ah) ? 0x1628c : 0x16284)
#define AR_CH0_TOP2_XPABIASLVL 0xf000
#define AR_CH0_TOP2_XPABIASLVL_S 12
-#define AR_CH0_XTAL (AR_SREV_9485(ah) ? 0x16290 : 0x16294)
+#define AR_CH0_XTAL (AR_SREV_9300(ah) ? 0x16294 : 0x16290)
#define AR_CH0_XTAL_CAPINDAC 0x7f000000
#define AR_CH0_XTAL_CAPINDAC_S 24
#define AR_CH0_XTAL_CAPOUTDAC 0x00fe0000
@@ -1119,6 +1121,9 @@
#define AR_PHY_POWERTX_RATE8_POWERTXHT40_5 0x3F00
#define AR_PHY_POWERTX_RATE8_POWERTXHT40_5_S 8
+#define AR_PHY_CL_TAB_CL_GAIN_MOD 0x1f
+#define AR_PHY_CL_TAB_CL_GAIN_MOD_S 0
+
void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx);
#endif /* AR9003_PHY_H */
diff --git a/drivers/net/wireless/ath/ath9k/ar9330_1p1_initvals.h b/drivers/net/wireless/ath/ath9k/ar9330_1p1_initvals.h
new file mode 100644
index 0000000..f11d9b2
--- /dev/null
+++ b/drivers/net/wireless/ath/ath9k/ar9330_1p1_initvals.h
@@ -0,0 +1,1147 @@
+/*
+ * Copyright (c) 2011 Atheros Communications 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_9330_1P1_H
+#define INITVALS_9330_1P1_H
+
+static const u32 ar9331_1p1_baseband_postamble[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8005, 0xd00a8005},
+ {0x00009820, 0x206a002e, 0x206a002e, 0x206a002e, 0x206a002e},
+ {0x00009824, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0},
+ {0x00009828, 0x06903081, 0x06903081, 0x06903881, 0x06903881},
+ {0x0000982c, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4},
+ {0x00009830, 0x0000059c, 0x0000059c, 0x0000059c, 0x0000059c},
+ {0x00009c00, 0x00000044, 0x00000044, 0x00000044, 0x00000044},
+ {0x00009e00, 0x0372161e, 0x0372161e, 0x037216a4, 0x037216a4},
+ {0x00009e04, 0x00182020, 0x00182020, 0x00182020, 0x00182020},
+ {0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2},
+ {0x00009e10, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e},
+ {0x00009e14, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e},
+ {0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c},
+ {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce},
+ {0x00009e2c, 0x0000001c, 0x0000001c, 0x00003221, 0x00003221},
+ {0x00009e3c, 0xcf946222, 0xcf946222, 0xcf946222, 0xcf946222},
+ {0x00009e44, 0x02321e27, 0x02321e27, 0x02282324, 0x02282324},
+ {0x00009e48, 0x5030201a, 0x5030201a, 0x50302010, 0x50302010},
+ {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000},
+ {0x0000a204, 0x00003fc0, 0x00003fc4, 0x00003fc4, 0x00003fc0},
+ {0x0000a208, 0x00000104, 0x00000104, 0x00000004, 0x00000004},
+ {0x0000a230, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b},
+ {0x0000a234, 0x00000fff, 0x00000fff, 0x10000fff, 0x00000fff},
+ {0x0000a238, 0xffb81018, 0xffb81018, 0xffb81018, 0xffb81018},
+ {0x0000a250, 0x00000000, 0x00000000, 0x00000210, 0x00000108},
+ {0x0000a254, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898},
+ {0x0000a258, 0x02020002, 0x02020002, 0x02020002, 0x02020002},
+ {0x0000a25c, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e},
+ {0x0000a260, 0x3a021501, 0x3a021501, 0x3a021501, 0x3a021501},
+ {0x0000a264, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
+ {0x0000a280, 0x00000007, 0x00000007, 0x0000000b, 0x0000000b},
+ {0x0000a284, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a288, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a28c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18},
+ {0x0000a2d0, 0x00071981, 0x00071981, 0x00071981, 0x00071981},
+ {0x0000a2d8, 0xf999a83a, 0xf999a83a, 0xf999a83a, 0xf999a83a},
+ {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000ae04, 0x00802020, 0x00802020, 0x00802020, 0x00802020},
+ {0x0000ae18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+};
+
+static const u32 ar9331_modes_lowest_ob_db_tx_gain_1p1[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x0000a2d8, 0x7999a83a, 0x7999a83a, 0x7999a83a, 0x7999a83a},
+ {0x0000a2dc, 0xffff2a52, 0xffff2a52, 0xffff2a52, 0xffff2a52},
+ {0x0000a2e0, 0xffffcc84, 0xffffcc84, 0xffffcc84, 0xffffcc84},
+ {0x0000a2e4, 0xfffff000, 0xfffff000, 0xfffff000, 0xfffff000},
+ {0x0000a2e8, 0xfffe0000, 0xfffe0000, 0xfffe0000, 0xfffe0000},
+ {0x0000a410, 0x000050d7, 0x000050d7, 0x000050d0, 0x000050d0},
+ {0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
+ {0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
+ {0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
+ {0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200},
+ {0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202},
+ {0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400},
+ {0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402},
+ {0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404},
+ {0x0000a520, 0x2f001f04, 0x2f001f04, 0x23000a00, 0x23000a00},
+ {0x0000a524, 0x35001fc4, 0x35001fc4, 0x27000a02, 0x27000a02},
+ {0x0000a528, 0x3c022f04, 0x3c022f04, 0x2b000a04, 0x2b000a04},
+ {0x0000a52c, 0x41023e85, 0x41023e85, 0x2d000a20, 0x2d000a20},
+ {0x0000a530, 0x48023ec6, 0x48023ec6, 0x31000a22, 0x31000a22},
+ {0x0000a534, 0x4d023f01, 0x4d023f01, 0x35000a24, 0x35000a24},
+ {0x0000a538, 0x53023f4b, 0x53023f4b, 0x38000a43, 0x38000a43},
+ {0x0000a53c, 0x5a027f09, 0x5a027f09, 0x3b000e42, 0x3b000e42},
+ {0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x3f000e44, 0x3f000e44},
+ {0x0000a544, 0x6502feca, 0x6502feca, 0x42000e64, 0x42000e64},
+ {0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x46000e66, 0x46000e66},
+ {0x0000a54c, 0x7203feca, 0x7203feca, 0x4a000ea6, 0x4a000ea6},
+ {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x4a000ea6, 0x4a000ea6},
+ {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x4a000ea6, 0x4a000ea6},
+ {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x4a000ea6, 0x4a000ea6},
+ {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x4a000ea6, 0x4a000ea6},
+ {0x0000a560, 0x900fff0b, 0x900fff0b, 0x4a000ea6, 0x4a000ea6},
+ {0x0000a564, 0x960fffcb, 0x960fffcb, 0x4a000ea6, 0x4a000ea6},
+ {0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
+ {0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
+ {0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
+ {0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
+ {0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
+ {0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
+ {0x0000a580, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
+ {0x0000a584, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
+ {0x0000a588, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
+ {0x0000a58c, 0x11062202, 0x11062202, 0x0b000200, 0x0b000200},
+ {0x0000a590, 0x17022e00, 0x17022e00, 0x0f000202, 0x0f000202},
+ {0x0000a594, 0x1d000ec2, 0x1d000ec2, 0x11000400, 0x11000400},
+ {0x0000a598, 0x25020ec0, 0x25020ec0, 0x15000402, 0x15000402},
+ {0x0000a59c, 0x2b020ec3, 0x2b020ec3, 0x19000404, 0x19000404},
+ {0x0000a5a0, 0x2f001f04, 0x2f001f04, 0x1b000603, 0x1b000603},
+ {0x0000a5a4, 0x35001fc4, 0x35001fc4, 0x1f000a02, 0x1f000a02},
+ {0x0000a5a8, 0x3c022f04, 0x3c022f04, 0x23000a04, 0x23000a04},
+ {0x0000a5ac, 0x41023e85, 0x41023e85, 0x26000a20, 0x26000a20},
+ {0x0000a5b0, 0x48023ec6, 0x48023ec6, 0x2a000e20, 0x2a000e20},
+ {0x0000a5b4, 0x4d023f01, 0x4d023f01, 0x2e000e22, 0x2e000e22},
+ {0x0000a5b8, 0x53023f4b, 0x53023f4b, 0x31000e24, 0x31000e24},
+ {0x0000a5bc, 0x5a027f09, 0x5a027f09, 0x34001640, 0x34001640},
+ {0x0000a5c0, 0x5f027fc9, 0x5f027fc9, 0x38001660, 0x38001660},
+ {0x0000a5c4, 0x6502feca, 0x6502feca, 0x3b001861, 0x3b001861},
+ {0x0000a5c8, 0x6b02ff4a, 0x6b02ff4a, 0x3e001a81, 0x3e001a81},
+ {0x0000a5cc, 0x7203feca, 0x7203feca, 0x42001a83, 0x42001a83},
+ {0x0000a5d0, 0x7703ff0b, 0x7703ff0b, 0x44001c84, 0x44001c84},
+ {0x0000a5d4, 0x7d06ffcb, 0x7d06ffcb, 0x48001ce3, 0x48001ce3},
+ {0x0000a5d8, 0x8407ff0b, 0x8407ff0b, 0x4c001ce5, 0x4c001ce5},
+ {0x0000a5dc, 0x8907ffcb, 0x8907ffcb, 0x50001ce9, 0x50001ce9},
+ {0x0000a5e0, 0x900fff0b, 0x900fff0b, 0x54001ceb, 0x54001ceb},
+ {0x0000a5e4, 0x960fffcb, 0x960fffcb, 0x56001eec, 0x56001eec},
+ {0x0000a5e8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+ {0x0000a5ec, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+ {0x0000a5f0, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+ {0x0000a5f4, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+ {0x0000a5f8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+ {0x0000a5fc, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+ {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000},
+ {0x0000a618, 0x01404501, 0x01404501, 0x01404501, 0x01404501},
+ {0x0000a61c, 0x02008802, 0x02008802, 0x02008802, 0x02008802},
+ {0x0000a620, 0x0280c802, 0x0280c802, 0x0280c802, 0x0280c802},
+ {0x0000a624, 0x03010a03, 0x03010a03, 0x03010a03, 0x03010a03},
+ {0x0000a628, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
+ {0x0000a62c, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
+ {0x0000a630, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
+ {0x0000a634, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
+ {0x0000a638, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
+ {0x0000a63c, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
+ {0x00016044, 0x034922db, 0x034922db, 0x034922db, 0x034922db},
+ {0x00016284, 0x14d3f000, 0x14d3f000, 0x14d3f000, 0x14d3f000},
+};
+
+static const u32 ar9331_modes_high_ob_db_tx_gain_1p1[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x0000a2d8, 0x7999a83a, 0x7999a83a, 0x7999a83a, 0x7999a83a},
+ {0x0000a2dc, 0xffaa9a52, 0xffaa9a52, 0xffaa9a52, 0xffaa9a52},
+ {0x0000a2e0, 0xffb31c84, 0xffb31c84, 0xffb31c84, 0xffb31c84},
+ {0x0000a2e4, 0xff43e000, 0xff43e000, 0xff43e000, 0xff43e000},
+ {0x0000a2e8, 0xfffc0000, 0xfffc0000, 0xfffc0000, 0xfffc0000},
+ {0x0000a410, 0x000050d7, 0x000050d7, 0x000050d7, 0x000050d7},
+ {0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
+ {0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
+ {0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
+ {0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200},
+ {0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202},
+ {0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400},
+ {0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402},
+ {0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404},
+ {0x0000a520, 0x2f001f04, 0x2f001f04, 0x23000a00, 0x23000a00},
+ {0x0000a524, 0x35001fc4, 0x35001fc4, 0x27000a02, 0x27000a02},
+ {0x0000a528, 0x3c022f04, 0x3c022f04, 0x2b000a04, 0x2b000a04},
+ {0x0000a52c, 0x41023e85, 0x41023e85, 0x3d001620, 0x3d001620},
+ {0x0000a530, 0x48023ec6, 0x48023ec6, 0x3f001621, 0x3f001621},
+ {0x0000a534, 0x4d023f01, 0x4d023f01, 0x42001640, 0x42001640},
+ {0x0000a538, 0x53023f4b, 0x53023f4b, 0x44001641, 0x44001641},
+ {0x0000a53c, 0x5a027f09, 0x5a027f09, 0x46001642, 0x46001642},
+ {0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x49001644, 0x49001644},
+ {0x0000a544, 0x6502feca, 0x6502feca, 0x4c001a81, 0x4c001a81},
+ {0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x4f001a83, 0x4f001a83},
+ {0x0000a54c, 0x7203feca, 0x7203feca, 0x52001c84, 0x52001c84},
+ {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x55001ce3, 0x55001ce3},
+ {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x59001ce5, 0x59001ce5},
+ {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5d001ce9, 0x5d001ce9},
+ {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x64001eec, 0x64001eec},
+ {0x0000a560, 0x900fff0b, 0x900fff0b, 0x64001eec, 0x64001eec},
+ {0x0000a564, 0x960fffcb, 0x960fffcb, 0x64001eec, 0x64001eec},
+ {0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x64001eec, 0x64001eec},
+ {0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x64001eec, 0x64001eec},
+ {0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x64001eec, 0x64001eec},
+ {0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x64001eec, 0x64001eec},
+ {0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x64001eec, 0x64001eec},
+ {0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x64001eec, 0x64001eec},
+ {0x0000a580, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
+ {0x0000a584, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
+ {0x0000a588, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
+ {0x0000a58c, 0x11062202, 0x11062202, 0x0b000200, 0x0b000200},
+ {0x0000a590, 0x17022e00, 0x17022e00, 0x0f000202, 0x0f000202},
+ {0x0000a594, 0x1d000ec2, 0x1d000ec2, 0x11000400, 0x11000400},
+ {0x0000a598, 0x25020ec0, 0x25020ec0, 0x15000402, 0x15000402},
+ {0x0000a59c, 0x2b020ec3, 0x2b020ec3, 0x19000404, 0x19000404},
+ {0x0000a5a0, 0x2f001f04, 0x2f001f04, 0x1b000603, 0x1b000603},
+ {0x0000a5a4, 0x35001fc4, 0x35001fc4, 0x1f000a02, 0x1f000a02},
+ {0x0000a5a8, 0x3c022f04, 0x3c022f04, 0x23000a04, 0x23000a04},
+ {0x0000a5ac, 0x41023e85, 0x41023e85, 0x26000a20, 0x26000a20},
+ {0x0000a5b0, 0x48023ec6, 0x48023ec6, 0x2a000e20, 0x2a000e20},
+ {0x0000a5b4, 0x4d023f01, 0x4d023f01, 0x2e000e22, 0x2e000e22},
+ {0x0000a5b8, 0x53023f4b, 0x53023f4b, 0x31000e24, 0x31000e24},
+ {0x0000a5bc, 0x5a027f09, 0x5a027f09, 0x34001640, 0x34001640},
+ {0x0000a5c0, 0x5f027fc9, 0x5f027fc9, 0x38001660, 0x38001660},
+ {0x0000a5c4, 0x6502feca, 0x6502feca, 0x3b001861, 0x3b001861},
+ {0x0000a5c8, 0x6b02ff4a, 0x6b02ff4a, 0x3e001a81, 0x3e001a81},
+ {0x0000a5cc, 0x7203feca, 0x7203feca, 0x42001a83, 0x42001a83},
+ {0x0000a5d0, 0x7703ff0b, 0x7703ff0b, 0x44001c84, 0x44001c84},
+ {0x0000a5d4, 0x7d06ffcb, 0x7d06ffcb, 0x48001ce3, 0x48001ce3},
+ {0x0000a5d8, 0x8407ff0b, 0x8407ff0b, 0x4c001ce5, 0x4c001ce5},
+ {0x0000a5dc, 0x8907ffcb, 0x8907ffcb, 0x50001ce9, 0x50001ce9},
+ {0x0000a5e0, 0x900fff0b, 0x900fff0b, 0x54001ceb, 0x54001ceb},
+ {0x0000a5e4, 0x960fffcb, 0x960fffcb, 0x56001eec, 0x56001eec},
+ {0x0000a5e8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+ {0x0000a5ec, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+ {0x0000a5f0, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+ {0x0000a5f4, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+ {0x0000a5f8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+ {0x0000a5fc, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+ {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000},
+ {0x0000a618, 0x02008501, 0x02008501, 0x02008501, 0x02008501},
+ {0x0000a61c, 0x02008802, 0x02008802, 0x02008802, 0x02008802},
+ {0x0000a620, 0x0280c802, 0x0280c802, 0x0280c802, 0x0280c802},
+ {0x0000a624, 0x0280ca03, 0x0280ca03, 0x0280ca03, 0x0280ca03},
+ {0x0000a628, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
+ {0x0000a62c, 0x04015005, 0x04015005, 0x04015005, 0x04015005},
+ {0x0000a630, 0x04015005, 0x04015005, 0x04015005, 0x04015005},
+ {0x0000a634, 0x04015005, 0x04015005, 0x04015005, 0x04015005},
+ {0x0000a638, 0x04015005, 0x04015005, 0x04015005, 0x04015005},
+ {0x0000a63c, 0x04015005, 0x04015005, 0x04015005, 0x04015005},
+};
+
+static const u32 ar9331_modes_low_ob_db_tx_gain_1p1[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x0000a2d8, 0x7999a83a, 0x7999a83a, 0x7999a83a, 0x7999a83a},
+ {0x0000a2dc, 0xffff2a52, 0xffff2a52, 0xffff2a52, 0xffff2a52},
+ {0x0000a2e0, 0xffffcc84, 0xffffcc84, 0xffffcc84, 0xffffcc84},
+ {0x0000a2e4, 0xfffff000, 0xfffff000, 0xfffff000, 0xfffff000},
+ {0x0000a2e8, 0xfffe0000, 0xfffe0000, 0xfffe0000, 0xfffe0000},
+ {0x0000a410, 0x000050d7, 0x000050d7, 0x000050d0, 0x000050d0},
+ {0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
+ {0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
+ {0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
+ {0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200},
+ {0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202},
+ {0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400},
+ {0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402},
+ {0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404},
+ {0x0000a520, 0x2f001f04, 0x2f001f04, 0x23000a00, 0x23000a00},
+ {0x0000a524, 0x35001fc4, 0x35001fc4, 0x27000a02, 0x27000a02},
+ {0x0000a528, 0x3c022f04, 0x3c022f04, 0x2b000a04, 0x2b000a04},
+ {0x0000a52c, 0x41023e85, 0x41023e85, 0x2d000a20, 0x2d000a20},
+ {0x0000a530, 0x48023ec6, 0x48023ec6, 0x31000a22, 0x31000a22},
+ {0x0000a534, 0x4d023f01, 0x4d023f01, 0x35000a24, 0x35000a24},
+ {0x0000a538, 0x53023f4b, 0x53023f4b, 0x38000a43, 0x38000a43},
+ {0x0000a53c, 0x5a027f09, 0x5a027f09, 0x3b000e42, 0x3b000e42},
+ {0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x3f000e44, 0x3f000e44},
+ {0x0000a544, 0x6502feca, 0x6502feca, 0x42000e64, 0x42000e64},
+ {0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x46000e66, 0x46000e66},
+ {0x0000a54c, 0x7203feca, 0x7203feca, 0x4a000ea6, 0x4a000ea6},
+ {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x4a000ea6, 0x4a000ea6},
+ {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x4a000ea6, 0x4a000ea6},
+ {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x4a000ea6, 0x4a000ea6},
+ {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x4a000ea6, 0x4a000ea6},
+ {0x0000a560, 0x900fff0b, 0x900fff0b, 0x4a000ea6, 0x4a000ea6},
+ {0x0000a564, 0x960fffcb, 0x960fffcb, 0x4a000ea6, 0x4a000ea6},
+ {0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
+ {0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
+ {0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
+ {0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
+ {0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
+ {0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
+ {0x0000a580, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
+ {0x0000a584, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
+ {0x0000a588, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
+ {0x0000a58c, 0x11062202, 0x11062202, 0x0b000200, 0x0b000200},
+ {0x0000a590, 0x17022e00, 0x17022e00, 0x0f000202, 0x0f000202},
+ {0x0000a594, 0x1d000ec2, 0x1d000ec2, 0x11000400, 0x11000400},
+ {0x0000a598, 0x25020ec0, 0x25020ec0, 0x15000402, 0x15000402},
+ {0x0000a59c, 0x2b020ec3, 0x2b020ec3, 0x19000404, 0x19000404},
+ {0x0000a5a0, 0x2f001f04, 0x2f001f04, 0x1b000603, 0x1b000603},
+ {0x0000a5a4, 0x35001fc4, 0x35001fc4, 0x1f000a02, 0x1f000a02},
+ {0x0000a5a8, 0x3c022f04, 0x3c022f04, 0x23000a04, 0x23000a04},
+ {0x0000a5ac, 0x41023e85, 0x41023e85, 0x26000a20, 0x26000a20},
+ {0x0000a5b0, 0x48023ec6, 0x48023ec6, 0x2a000e20, 0x2a000e20},
+ {0x0000a5b4, 0x4d023f01, 0x4d023f01, 0x2e000e22, 0x2e000e22},
+ {0x0000a5b8, 0x53023f4b, 0x53023f4b, 0x31000e24, 0x31000e24},
+ {0x0000a5bc, 0x5a027f09, 0x5a027f09, 0x34001640, 0x34001640},
+ {0x0000a5c0, 0x5f027fc9, 0x5f027fc9, 0x38001660, 0x38001660},
+ {0x0000a5c4, 0x6502feca, 0x6502feca, 0x3b001861, 0x3b001861},
+ {0x0000a5c8, 0x6b02ff4a, 0x6b02ff4a, 0x3e001a81, 0x3e001a81},
+ {0x0000a5cc, 0x7203feca, 0x7203feca, 0x42001a83, 0x42001a83},
+ {0x0000a5d0, 0x7703ff0b, 0x7703ff0b, 0x44001c84, 0x44001c84},
+ {0x0000a5d4, 0x7d06ffcb, 0x7d06ffcb, 0x48001ce3, 0x48001ce3},
+ {0x0000a5d8, 0x8407ff0b, 0x8407ff0b, 0x4c001ce5, 0x4c001ce5},
+ {0x0000a5dc, 0x8907ffcb, 0x8907ffcb, 0x50001ce9, 0x50001ce9},
+ {0x0000a5e0, 0x900fff0b, 0x900fff0b, 0x54001ceb, 0x54001ceb},
+ {0x0000a5e4, 0x960fffcb, 0x960fffcb, 0x56001eec, 0x56001eec},
+ {0x0000a5e8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+ {0x0000a5ec, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+ {0x0000a5f0, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+ {0x0000a5f4, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+ {0x0000a5f8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+ {0x0000a5fc, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+ {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000},
+ {0x0000a618, 0x01404501, 0x01404501, 0x01404501, 0x01404501},
+ {0x0000a61c, 0x02008802, 0x02008802, 0x02008802, 0x02008802},
+ {0x0000a620, 0x0280c802, 0x0280c802, 0x0280c802, 0x0280c802},
+ {0x0000a624, 0x03010a03, 0x03010a03, 0x03010a03, 0x03010a03},
+ {0x0000a628, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
+ {0x0000a62c, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
+ {0x0000a630, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
+ {0x0000a634, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
+ {0x0000a638, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
+ {0x0000a63c, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
+ {0x00016044, 0x034922db, 0x034922db, 0x034922db, 0x034922db},
+ {0x00016284, 0x14d3f000, 0x14d3f000, 0x14d3f000, 0x14d3f000},
+};
+
+static const u32 ar9331_1p1_baseband_core_txfir_coeff_japan_2484[][2] = {
+ /* Addr allmodes */
+ {0x0000a398, 0x00000000},
+ {0x0000a39c, 0x6f7f0301},
+ {0x0000a3a0, 0xca9228ee},
+};
+
+static const u32 ar9331_1p1_xtal_25M[][2] = {
+ /* Addr allmodes */
+ {0x00007038, 0x000002f8},
+ {0x00008244, 0x0010f3d7},
+ {0x0000824c, 0x0001e7ae},
+ {0x0001609c, 0x0f508f29},
+};
+
+static const u32 ar9331_1p1_radio_core[][2] = {
+ /* Addr allmodes */
+ {0x00016000, 0x36db6db6},
+ {0x00016004, 0x6db6db40},
+ {0x00016008, 0x73800000},
+ {0x0001600c, 0x00000000},
+ {0x00016040, 0x7f80fff8},
+ {0x00016044, 0x03db62db},
+ {0x00016048, 0x6c924268},
+ {0x0001604c, 0x000f0278},
+ {0x00016050, 0x4db6db8c},
+ {0x00016054, 0x6db60000},
+ {0x00016080, 0x00080000},
+ {0x00016084, 0x0e48048c},
+ {0x00016088, 0x14214514},
+ {0x0001608c, 0x119f081c},
+ {0x00016090, 0x24926490},
+ {0x00016098, 0xd411eb84},
+ {0x000160a0, 0xc2108ffe},
+ {0x000160a4, 0x812fc370},
+ {0x000160a8, 0x423c8000},
+ {0x000160ac, 0x24651800},
+ {0x000160b0, 0x03284f3e},
+ {0x000160b4, 0x92480040},
+ {0x000160c0, 0x006db6db},
+ {0x000160c4, 0x0186db60},
+ {0x000160c8, 0x6db6db6c},
+ {0x000160cc, 0x6de6c300},
+ {0x000160d0, 0x14500820},
+ {0x00016100, 0x04cb0001},
+ {0x00016104, 0xfff80015},
+ {0x00016108, 0x00080010},
+ {0x0001610c, 0x00170000},
+ {0x00016140, 0x10804000},
+ {0x00016144, 0x01884080},
+ {0x00016148, 0x000080c0},
+ {0x00016280, 0x01000015},
+ {0x00016284, 0x14d20000},
+ {0x00016288, 0x00318000},
+ {0x0001628c, 0x50000000},
+ {0x00016290, 0x4b96210f},
+ {0x00016380, 0x00000000},
+ {0x00016384, 0x00000000},
+ {0x00016388, 0x00800700},
+ {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},
+};
+
+static const u32 ar9331_1p1_soc_postamble[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x00007010, 0x00000022, 0x00000022, 0x00000022, 0x00000022},
+};
+
+static const u32 ar9331_common_wo_xlna_rx_gain_1p1[][2] = {
+ /* Addr allmodes */
+ {0x0000a000, 0x00060005},
+ {0x0000a004, 0x00810080},
+ {0x0000a008, 0x00830082},
+ {0x0000a00c, 0x00850084},
+ {0x0000a010, 0x01820181},
+ {0x0000a014, 0x01840183},
+ {0x0000a018, 0x01880185},
+ {0x0000a01c, 0x018a0189},
+ {0x0000a020, 0x02850284},
+ {0x0000a024, 0x02890288},
+ {0x0000a028, 0x028b028a},
+ {0x0000a02c, 0x03850384},
+ {0x0000a030, 0x03890388},
+ {0x0000a034, 0x038b038a},
+ {0x0000a038, 0x038d038c},
+ {0x0000a03c, 0x03910390},
+ {0x0000a040, 0x03930392},
+ {0x0000a044, 0x03950394},
+ {0x0000a048, 0x00000396},
+ {0x0000a04c, 0x00000000},
+ {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, 0x28282828},
+ {0x0000a084, 0x28282828},
+ {0x0000a088, 0x28282828},
+ {0x0000a08c, 0x28282828},
+ {0x0000a090, 0x28282828},
+ {0x0000a094, 0x24242428},
+ {0x0000a098, 0x171e1e1e},
+ {0x0000a09c, 0x02020b0b},
+ {0x0000a0a0, 0x02020202},
+ {0x0000a0a4, 0x00000000},
+ {0x0000a0a8, 0x00000000},
+ {0x0000a0ac, 0x00000000},
+ {0x0000a0b0, 0x00000000},
+ {0x0000a0b4, 0x00000000},
+ {0x0000a0b8, 0x00000000},
+ {0x0000a0bc, 0x00000000},
+ {0x0000a0c0, 0x22072208},
+ {0x0000a0c4, 0x22052206},
+ {0x0000a0c8, 0x22032204},
+ {0x0000a0cc, 0x22012202},
+ {0x0000a0d0, 0x221f2200},
+ {0x0000a0d4, 0x221d221e},
+ {0x0000a0d8, 0x33023303},
+ {0x0000a0dc, 0x33003301},
+ {0x0000a0e0, 0x331e331f},
+ {0x0000a0e4, 0x4402331d},
+ {0x0000a0e8, 0x44004401},
+ {0x0000a0ec, 0x441e441f},
+ {0x0000a0f0, 0x55025503},
+ {0x0000a0f4, 0x55005501},
+ {0x0000a0f8, 0x551e551f},
+ {0x0000a0fc, 0x6602551d},
+ {0x0000a100, 0x66006601},
+ {0x0000a104, 0x661e661f},
+ {0x0000a108, 0x7703661d},
+ {0x0000a10c, 0x77017702},
+ {0x0000a110, 0x00007700},
+ {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, 0x111f1100},
+ {0x0000a148, 0x111d111e},
+ {0x0000a14c, 0x111b111c},
+ {0x0000a150, 0x22032204},
+ {0x0000a154, 0x22012202},
+ {0x0000a158, 0x221f2200},
+ {0x0000a15c, 0x221d221e},
+ {0x0000a160, 0x33013302},
+ {0x0000a164, 0x331f3300},
+ {0x0000a168, 0x4402331e},
+ {0x0000a16c, 0x44004401},
+ {0x0000a170, 0x441e441f},
+ {0x0000a174, 0x55015502},
+ {0x0000a178, 0x551f5500},
+ {0x0000a17c, 0x6602551e},
+ {0x0000a180, 0x66006601},
+ {0x0000a184, 0x661e661f},
+ {0x0000a188, 0x7703661d},
+ {0x0000a18c, 0x77017702},
+ {0x0000a190, 0x00007700},
+ {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, 0x00000296},
+};
+
+static const u32 ar9331_1p1_baseband_core[][2] = {
+ /* Addr allmodes */
+ {0x00009800, 0xafe68e30},
+ {0x00009804, 0xfd14e000},
+ {0x00009808, 0x9c0a8f6b},
+ {0x0000980c, 0x04800000},
+ {0x00009814, 0x9280c00a},
+ {0x00009818, 0x00000000},
+ {0x0000981c, 0x00020028},
+ {0x00009834, 0x5f3ca3de},
+ {0x00009838, 0x0108ecff},
+ {0x0000983c, 0x14750600},
+ {0x00009880, 0x201fff00},
+ {0x00009884, 0x00001042},
+ {0x000098a4, 0x00200400},
+ {0x000098b0, 0x32840bbe},
+ {0x000098d0, 0x004b6a8e},
+ {0x000098d4, 0x00000820},
+ {0x000098dc, 0x00000000},
+ {0x000098f0, 0x00000000},
+ {0x000098f4, 0x00000000},
+ {0x00009c04, 0x00000000},
+ {0x00009c08, 0x03200000},
+ {0x00009c0c, 0x00000000},
+ {0x00009c10, 0x00000000},
+ {0x00009c14, 0x00046384},
+ {0x00009c18, 0x05b6b440},
+ {0x00009c1c, 0x00b6b440},
+ {0x00009d00, 0xc080a333},
+ {0x00009d04, 0x40206c10},
+ {0x00009d08, 0x009c4060},
+ {0x00009d0c, 0x1883800a},
+ {0x00009d10, 0x01834061},
+ {0x00009d14, 0x00c00400},
+ {0x00009d18, 0x00000000},
+ {0x00009e08, 0x0038233c},
+ {0x00009e24, 0x9927b515},
+ {0x00009e28, 0x12ef0200},
+ {0x00009e30, 0x06336f77},
+ {0x00009e34, 0x6af6532f},
+ {0x00009e38, 0x0cc80c00},
+ {0x00009e40, 0x0d261820},
+ {0x00009e4c, 0x00001004},
+ {0x00009e50, 0x00ff03f1},
+ {0x00009fc0, 0x803e4788},
+ {0x00009fc4, 0x0001efb5},
+ {0x00009fcc, 0x40000014},
+ {0x0000a20c, 0x00000000},
+ {0x0000a220, 0x00000000},
+ {0x0000a224, 0x00000000},
+ {0x0000a228, 0x10002310},
+ {0x0000a23c, 0x00000000},
+ {0x0000a244, 0x0c000000},
+ {0x0000a2a0, 0x00000001},
+ {0x0000a2c0, 0x00000001},
+ {0x0000a2c8, 0x00000000},
+ {0x0000a2cc, 0x18c43433},
+ {0x0000a2d4, 0x00000000},
+ {0x0000a2dc, 0x00000000},
+ {0x0000a2e0, 0x00000000},
+ {0x0000a2e4, 0x00000000},
+ {0x0000a2e8, 0x00000000},
+ {0x0000a2ec, 0x00000000},
+ {0x0000a2f0, 0x00000000},
+ {0x0000a2f4, 0x00000000},
+ {0x0000a2f8, 0x00000000},
+ {0x0000a344, 0x00000000},
+ {0x0000a34c, 0x00000000},
+ {0x0000a350, 0x0000a000},
+ {0x0000a364, 0x00000000},
+ {0x0000a370, 0x00000000},
+ {0x0000a390, 0x00000001},
+ {0x0000a394, 0x00000444},
+ {0x0000a398, 0x001f0e0f},
+ {0x0000a39c, 0x0075393f},
+ {0x0000a3a0, 0xb79f6427},
+ {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, 0x00000006},
+ {0x0000a3f8, 0x0cdbd380},
+ {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, 0x00000000},
+ {0x0000a440, 0x00000000},
+ {0x0000a444, 0x00000000},
+ {0x0000a448, 0x04000000},
+ {0x0000a44c, 0x00000001},
+ {0x0000a450, 0x00010000},
+ {0x0000a458, 0x00000000},
+ {0x0000a640, 0x00000000},
+ {0x0000a644, 0x3fad9d74},
+ {0x0000a648, 0x0048060a},
+ {0x0000a64c, 0x00003c37},
+ {0x0000a670, 0x03020100},
+ {0x0000a674, 0x09080504},
+ {0x0000a678, 0x0d0c0b0a},
+ {0x0000a67c, 0x13121110},
+ {0x0000a680, 0x31301514},
+ {0x0000a684, 0x35343332},
+ {0x0000a688, 0x00000036},
+ {0x0000a690, 0x00000838},
+ {0x0000a7c0, 0x00000000},
+ {0x0000a7c4, 0xfffffffc},
+ {0x0000a7c8, 0x00000000},
+ {0x0000a7cc, 0x00000000},
+ {0x0000a7d0, 0x00000000},
+ {0x0000a7d4, 0x00000004},
+ {0x0000a7dc, 0x00000001},
+};
+
+static const u32 ar9331_modes_high_power_tx_gain_1p1[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x0000a2d8, 0x7999a83a, 0x7999a83a, 0x7999a83a, 0x7999a83a},
+ {0x0000a2dc, 0xffff2a52, 0xffff2a52, 0xffff2a52, 0xffff2a52},
+ {0x0000a2e0, 0xffffcc84, 0xffffcc84, 0xffffcc84, 0xffffcc84},
+ {0x0000a2e4, 0xfffff000, 0xfffff000, 0xfffff000, 0xfffff000},
+ {0x0000a2e8, 0xfffe0000, 0xfffe0000, 0xfffe0000, 0xfffe0000},
+ {0x0000a410, 0x000050d7, 0x000050d7, 0x000050d0, 0x000050d0},
+ {0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
+ {0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
+ {0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
+ {0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200},
+ {0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202},
+ {0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400},
+ {0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402},
+ {0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404},
+ {0x0000a520, 0x2f001f04, 0x2f001f04, 0x23000a00, 0x23000a00},
+ {0x0000a524, 0x35001fc4, 0x35001fc4, 0x27000a02, 0x27000a02},
+ {0x0000a528, 0x3c022f04, 0x3c022f04, 0x2b000a04, 0x2b000a04},
+ {0x0000a52c, 0x41023e85, 0x41023e85, 0x2d000a20, 0x2d000a20},
+ {0x0000a530, 0x48023ec6, 0x48023ec6, 0x31000a22, 0x31000a22},
+ {0x0000a534, 0x4d023f01, 0x4d023f01, 0x35000a24, 0x35000a24},
+ {0x0000a538, 0x53023f4b, 0x53023f4b, 0x38000a43, 0x38000a43},
+ {0x0000a53c, 0x5a027f09, 0x5a027f09, 0x3b000e42, 0x3b000e42},
+ {0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x3f000e44, 0x3f000e44},
+ {0x0000a544, 0x6502feca, 0x6502feca, 0x42000e64, 0x42000e64},
+ {0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x46000e66, 0x46000e66},
+ {0x0000a54c, 0x7203feca, 0x7203feca, 0x4a000ea6, 0x4a000ea6},
+ {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x4a000ea6, 0x4a000ea6},
+ {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x4a000ea6, 0x4a000ea6},
+ {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x4a000ea6, 0x4a000ea6},
+ {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x4a000ea6, 0x4a000ea6},
+ {0x0000a560, 0x900fff0b, 0x900fff0b, 0x4a000ea6, 0x4a000ea6},
+ {0x0000a564, 0x960fffcb, 0x960fffcb, 0x4a000ea6, 0x4a000ea6},
+ {0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
+ {0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
+ {0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
+ {0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
+ {0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
+ {0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
+ {0x0000a580, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
+ {0x0000a584, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
+ {0x0000a588, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
+ {0x0000a58c, 0x11062202, 0x11062202, 0x0b000200, 0x0b000200},
+ {0x0000a590, 0x17022e00, 0x17022e00, 0x0f000202, 0x0f000202},
+ {0x0000a594, 0x1d000ec2, 0x1d000ec2, 0x11000400, 0x11000400},
+ {0x0000a598, 0x25020ec0, 0x25020ec0, 0x15000402, 0x15000402},
+ {0x0000a59c, 0x2b020ec3, 0x2b020ec3, 0x19000404, 0x19000404},
+ {0x0000a5a0, 0x2f001f04, 0x2f001f04, 0x1b000603, 0x1b000603},
+ {0x0000a5a4, 0x35001fc4, 0x35001fc4, 0x1f000a02, 0x1f000a02},
+ {0x0000a5a8, 0x3c022f04, 0x3c022f04, 0x23000a04, 0x23000a04},
+ {0x0000a5ac, 0x41023e85, 0x41023e85, 0x26000a20, 0x26000a20},
+ {0x0000a5b0, 0x48023ec6, 0x48023ec6, 0x2a000e20, 0x2a000e20},
+ {0x0000a5b4, 0x4d023f01, 0x4d023f01, 0x2e000e22, 0x2e000e22},
+ {0x0000a5b8, 0x53023f4b, 0x53023f4b, 0x31000e24, 0x31000e24},
+ {0x0000a5bc, 0x5a027f09, 0x5a027f09, 0x34001640, 0x34001640},
+ {0x0000a5c0, 0x5f027fc9, 0x5f027fc9, 0x38001660, 0x38001660},
+ {0x0000a5c4, 0x6502feca, 0x6502feca, 0x3b001861, 0x3b001861},
+ {0x0000a5c8, 0x6b02ff4a, 0x6b02ff4a, 0x3e001a81, 0x3e001a81},
+ {0x0000a5cc, 0x7203feca, 0x7203feca, 0x42001a83, 0x42001a83},
+ {0x0000a5d0, 0x7703ff0b, 0x7703ff0b, 0x44001c84, 0x44001c84},
+ {0x0000a5d4, 0x7d06ffcb, 0x7d06ffcb, 0x48001ce3, 0x48001ce3},
+ {0x0000a5d8, 0x8407ff0b, 0x8407ff0b, 0x4c001ce5, 0x4c001ce5},
+ {0x0000a5dc, 0x8907ffcb, 0x8907ffcb, 0x50001ce9, 0x50001ce9},
+ {0x0000a5e0, 0x900fff0b, 0x900fff0b, 0x54001ceb, 0x54001ceb},
+ {0x0000a5e4, 0x960fffcb, 0x960fffcb, 0x56001eec, 0x56001eec},
+ {0x0000a5e8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+ {0x0000a5ec, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+ {0x0000a5f0, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+ {0x0000a5f4, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+ {0x0000a5f8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+ {0x0000a5fc, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+ {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000},
+ {0x0000a618, 0x01404501, 0x01404501, 0x01404501, 0x01404501},
+ {0x0000a61c, 0x02008802, 0x02008802, 0x02008802, 0x02008802},
+ {0x0000a620, 0x0280c802, 0x0280c802, 0x0280c802, 0x0280c802},
+ {0x0000a624, 0x03010a03, 0x03010a03, 0x03010a03, 0x03010a03},
+ {0x0000a628, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
+ {0x0000a62c, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
+ {0x0000a630, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
+ {0x0000a634, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
+ {0x0000a638, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
+ {0x0000a63c, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
+ {0x00016044, 0x034922db, 0x034922db, 0x034922db, 0x034922db},
+ {0x00016284, 0x14d3f000, 0x14d3f000, 0x14d3f000, 0x14d3f000},
+};
+
+static const u32 ar9331_1p1_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 ar9331_1p1_soc_preamble[][2] = {
+ /* Addr allmodes */
+ {0x00007020, 0x00000000},
+ {0x00007034, 0x00000002},
+ {0x00007038, 0x000002f8},
+};
+
+static const u32 ar9331_1p1_xtal_40M[][2] = {
+ /* Addr allmodes */
+ {0x00007038, 0x000004c2},
+ {0x00008244, 0x0010f400},
+ {0x0000824c, 0x0001e800},
+ {0x0001609c, 0x0b283f31},
+};
+
+static const u32 ar9331_1p1_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, 0x13881c20},
+ {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},
+ {0x00008144, 0xffffffff},
+ {0x00008168, 0x00000000},
+ {0x0000816c, 0x00000000},
+ {0x00008170, 0x18486200},
+ {0x00008174, 0x33332210},
+ {0x00008178, 0x00000000},
+ {0x0000817c, 0x00020000},
+ {0x000081c0, 0x00000000},
+ {0x000081c4, 0x33332210},
+ {0x000081c8, 0x00000000},
+ {0x000081cc, 0x00000000},
+ {0x000081d4, 0x00000000},
+ {0x000081ec, 0x00000000},
+ {0x000081f0, 0x00000000},
+ {0x000081f4, 0x00000000},
+ {0x000081f8, 0x00000000},
+ {0x000081fc, 0x00000000},
+ {0x00008240, 0x00100000},
+ {0x00008248, 0x00000800},
+ {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, 0x00000140},
+ {0x00008314, 0x00000000},
+ {0x0000831c, 0x0000010d},
+ {0x00008328, 0x00000000},
+ {0x0000832c, 0x00000007},
+ {0x00008330, 0x00000302},
+ {0x00008334, 0x00000700},
+ {0x00008338, 0x00ff0000},
+ {0x0000833c, 0x02400000},
+ {0x00008340, 0x000107ff},
+ {0x00008344, 0xaa48105b},
+ {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, 0x000301ff},
+};
+
+static const u32 ar9331_common_rx_gain_1p1[][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},
+};
+
+static const u32 ar9331_common_tx_gain_offset1_1[][1] = {
+ {0},
+ {3},
+ {0},
+ {0},
+};
+
+static const u32 ar9331_1p1_chansel_xtal_25M[] = {
+ 0x0101479e,
+ 0x0101d027,
+ 0x010258af,
+ 0x0102e138,
+ 0x010369c0,
+ 0x0103f249,
+ 0x01047ad1,
+ 0x0105035a,
+ 0x01058be2,
+ 0x0106146b,
+ 0x01069cf3,
+ 0x0107257c,
+ 0x0107ae04,
+ 0x0108f5b2,
+};
+
+static const u32 ar9331_1p1_chansel_xtal_40M[] = {
+ 0x00a0ccbe,
+ 0x00a12213,
+ 0x00a17769,
+ 0x00a1ccbe,
+ 0x00a22213,
+ 0x00a27769,
+ 0x00a2ccbe,
+ 0x00a32213,
+ 0x00a37769,
+ 0x00a3ccbe,
+ 0x00a42213,
+ 0x00a47769,
+ 0x00a4ccbe,
+ 0x00a5998b,
+};
+
+#endif /* INITVALS_9330_1P1_H */
diff --git a/drivers/net/wireless/ath/ath9k/ar9330_1p2_initvals.h b/drivers/net/wireless/ath/ath9k/ar9330_1p2_initvals.h
new file mode 100644
index 0000000..0e6ca08
--- /dev/null
+++ b/drivers/net/wireless/ath/ath9k/ar9330_1p2_initvals.h
@@ -0,0 +1,1080 @@
+/*
+ * Copyright (c) 2011 Atheros Communications 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_9330_1P2_H
+#define INITVALS_9330_1P2_H
+
+static const u32 ar9331_modes_lowest_ob_db_tx_gain_1p2[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x0000a410, 0x000050d7, 0x000050d7, 0x000050d7, 0x000050d7},
+ {0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
+ {0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
+ {0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
+ {0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200},
+ {0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202},
+ {0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400},
+ {0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402},
+ {0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404},
+ {0x0000a520, 0x2f001f04, 0x2f001f04, 0x23000a00, 0x23000a00},
+ {0x0000a524, 0x35001fc4, 0x35001fc4, 0x27000a02, 0x27000a02},
+ {0x0000a528, 0x3c022f04, 0x3c022f04, 0x2b000a04, 0x2b000a04},
+ {0x0000a52c, 0x41023e85, 0x41023e85, 0x3f001620, 0x3f001620},
+ {0x0000a530, 0x48023ec6, 0x48023ec6, 0x41001621, 0x41001621},
+ {0x0000a534, 0x4d023f01, 0x4d023f01, 0x44001640, 0x44001640},
+ {0x0000a538, 0x53023f4b, 0x53023f4b, 0x46001641, 0x46001641},
+ {0x0000a53c, 0x5a027f09, 0x5a027f09, 0x48001642, 0x48001642},
+ {0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x4b001644, 0x4b001644},
+ {0x0000a544, 0x6502feca, 0x6502feca, 0x4e001a81, 0x4e001a81},
+ {0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x51001a83, 0x51001a83},
+ {0x0000a54c, 0x7203feca, 0x7203feca, 0x54001c84, 0x54001c84},
+ {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x57001ce3, 0x57001ce3},
+ {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x5b001ce5, 0x5b001ce5},
+ {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5f001ce9, 0x5f001ce9},
+ {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x66001eec, 0x66001eec},
+ {0x0000a560, 0x900fff0b, 0x900fff0b, 0x66001eec, 0x66001eec},
+ {0x0000a564, 0x960fffcb, 0x960fffcb, 0x66001eec, 0x66001eec},
+ {0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+ {0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+ {0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+ {0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+ {0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+ {0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+ {0x0000a580, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
+ {0x0000a584, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
+ {0x0000a588, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
+ {0x0000a58c, 0x11062202, 0x11062202, 0x0b000200, 0x0b000200},
+ {0x0000a590, 0x17022e00, 0x17022e00, 0x0f000202, 0x0f000202},
+ {0x0000a594, 0x1d000ec2, 0x1d000ec2, 0x11000400, 0x11000400},
+ {0x0000a598, 0x25020ec0, 0x25020ec0, 0x15000402, 0x15000402},
+ {0x0000a59c, 0x2b020ec3, 0x2b020ec3, 0x19000404, 0x19000404},
+ {0x0000a5a0, 0x2f001f04, 0x2f001f04, 0x1b000603, 0x1b000603},
+ {0x0000a5a4, 0x35001fc4, 0x35001fc4, 0x1f000a02, 0x1f000a02},
+ {0x0000a5a8, 0x3c022f04, 0x3c022f04, 0x23000a04, 0x23000a04},
+ {0x0000a5ac, 0x41023e85, 0x41023e85, 0x26000a20, 0x26000a20},
+ {0x0000a5b0, 0x48023ec6, 0x48023ec6, 0x2a000e20, 0x2a000e20},
+ {0x0000a5b4, 0x4d023f01, 0x4d023f01, 0x2e000e22, 0x2e000e22},
+ {0x0000a5b8, 0x53023f4b, 0x53023f4b, 0x31000e24, 0x31000e24},
+ {0x0000a5bc, 0x5a027f09, 0x5a027f09, 0x34001640, 0x34001640},
+ {0x0000a5c0, 0x5f027fc9, 0x5f027fc9, 0x38001660, 0x38001660},
+ {0x0000a5c4, 0x6502feca, 0x6502feca, 0x3b001861, 0x3b001861},
+ {0x0000a5c8, 0x6b02ff4a, 0x6b02ff4a, 0x3e001a81, 0x3e001a81},
+ {0x0000a5cc, 0x7203feca, 0x7203feca, 0x42001a83, 0x42001a83},
+ {0x0000a5d0, 0x7703ff0b, 0x7703ff0b, 0x44001c84, 0x44001c84},
+ {0x0000a5d4, 0x7d06ffcb, 0x7d06ffcb, 0x48001ce3, 0x48001ce3},
+ {0x0000a5d8, 0x8407ff0b, 0x8407ff0b, 0x4c001ce5, 0x4c001ce5},
+ {0x0000a5dc, 0x8907ffcb, 0x8907ffcb, 0x50001ce9, 0x50001ce9},
+ {0x0000a5e0, 0x900fff0b, 0x900fff0b, 0x54001ceb, 0x54001ceb},
+ {0x0000a5e4, 0x960fffcb, 0x960fffcb, 0x56001eec, 0x56001eec},
+ {0x0000a5e8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+ {0x0000a5ec, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+ {0x0000a5f0, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+ {0x0000a5f4, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+ {0x0000a5f8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+ {0x0000a5fc, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+ {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000},
+ {0x0000a618, 0x02008501, 0x02008501, 0x02008501, 0x02008501},
+ {0x0000a61c, 0x02008802, 0x02008802, 0x02008802, 0x02008802},
+ {0x0000a620, 0x0300c802, 0x0300c802, 0x0300c802, 0x0300c802},
+ {0x0000a624, 0x0300cc03, 0x0300cc03, 0x0300cc03, 0x0300cc03},
+ {0x0000a628, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+ {0x0000a62c, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+ {0x0000a630, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+ {0x0000a634, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+ {0x0000a638, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+ {0x0000a63c, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+};
+
+static const u32 ar9331_1p2_baseband_postamble[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8005, 0xd00a8005},
+ {0x00009820, 0x206a002e, 0x206a002e, 0x206a002e, 0x206a002e},
+ {0x00009824, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0},
+ {0x00009828, 0x06903081, 0x06903081, 0x06903881, 0x06903881},
+ {0x0000982c, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4},
+ {0x00009830, 0x0000059c, 0x0000059c, 0x0000059c, 0x0000059c},
+ {0x00009c00, 0x00000044, 0x00000044, 0x00000044, 0x00000044},
+ {0x00009e00, 0x0372161e, 0x0372161e, 0x037216a4, 0x037216a4},
+ {0x00009e04, 0x00182020, 0x00182020, 0x00182020, 0x00182020},
+ {0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2},
+ {0x00009e10, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e},
+ {0x00009e14, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e},
+ {0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c},
+ {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce},
+ {0x00009e2c, 0x0000001c, 0x0000001c, 0x00003221, 0x00003221},
+ {0x00009e3c, 0xcf946222, 0xcf946222, 0xcf946222, 0xcf946222},
+ {0x00009e44, 0x02321e27, 0x02321e27, 0x02282324, 0x02282324},
+ {0x00009e48, 0x5030201a, 0x5030201a, 0x50302010, 0x50302010},
+ {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000},
+ {0x0000a204, 0x00003fc0, 0x00003fc4, 0x00003fc4, 0x00003fc0},
+ {0x0000a208, 0x00000104, 0x00000104, 0x00000004, 0x00000004},
+ {0x0000a230, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b},
+ {0x0000a234, 0x00000fff, 0x00000fff, 0x10000fff, 0x00000fff},
+ {0x0000a238, 0xffb81018, 0xffb81018, 0xffb81018, 0xffb81018},
+ {0x0000a250, 0x00000000, 0x00000000, 0x00000210, 0x00000108},
+ {0x0000a254, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898},
+ {0x0000a258, 0x02020002, 0x02020002, 0x02020002, 0x02020002},
+ {0x0000a25c, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e},
+ {0x0000a260, 0x3a021501, 0x3a021501, 0x3a021501, 0x3a021501},
+ {0x0000a264, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
+ {0x0000a280, 0x00000007, 0x00000007, 0x0000000b, 0x0000000b},
+ {0x0000a284, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a288, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a28c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18},
+ {0x0000a2d0, 0x00071981, 0x00071981, 0x00071981, 0x00071981},
+ {0x0000a2d8, 0xf999a83a, 0xf999a83a, 0xf999a83a, 0xf999a83a},
+ {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000ae04, 0x00802020, 0x00802020, 0x00802020, 0x00802020},
+ {0x0000ae18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+};
+
+static const u32 ar9331_modes_high_ob_db_tx_gain_1p2[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x0000a410, 0x000050d7, 0x000050d7, 0x000050d7, 0x000050d7},
+ {0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
+ {0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
+ {0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
+ {0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200},
+ {0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202},
+ {0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400},
+ {0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402},
+ {0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404},
+ {0x0000a520, 0x2f001f04, 0x2f001f04, 0x23000a00, 0x23000a00},
+ {0x0000a524, 0x35001fc4, 0x35001fc4, 0x27000a02, 0x27000a02},
+ {0x0000a528, 0x3c022f04, 0x3c022f04, 0x2b000a04, 0x2b000a04},
+ {0x0000a52c, 0x41023e85, 0x41023e85, 0x3f001620, 0x3f001620},
+ {0x0000a530, 0x48023ec6, 0x48023ec6, 0x41001621, 0x41001621},
+ {0x0000a534, 0x4d023f01, 0x4d023f01, 0x44001640, 0x44001640},
+ {0x0000a538, 0x53023f4b, 0x53023f4b, 0x46001641, 0x46001641},
+ {0x0000a53c, 0x5a027f09, 0x5a027f09, 0x48001642, 0x48001642},
+ {0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x4b001644, 0x4b001644},
+ {0x0000a544, 0x6502feca, 0x6502feca, 0x4e001a81, 0x4e001a81},
+ {0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x51001a83, 0x51001a83},
+ {0x0000a54c, 0x7203feca, 0x7203feca, 0x54001c84, 0x54001c84},
+ {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x57001ce3, 0x57001ce3},
+ {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x5b001ce5, 0x5b001ce5},
+ {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5f001ce9, 0x5f001ce9},
+ {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x66001eec, 0x66001eec},
+ {0x0000a560, 0x900fff0b, 0x900fff0b, 0x66001eec, 0x66001eec},
+ {0x0000a564, 0x960fffcb, 0x960fffcb, 0x66001eec, 0x66001eec},
+ {0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+ {0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+ {0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+ {0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+ {0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+ {0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+ {0x0000a580, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
+ {0x0000a584, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
+ {0x0000a588, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
+ {0x0000a58c, 0x11062202, 0x11062202, 0x0b000200, 0x0b000200},
+ {0x0000a590, 0x17022e00, 0x17022e00, 0x0f000202, 0x0f000202},
+ {0x0000a594, 0x1d000ec2, 0x1d000ec2, 0x11000400, 0x11000400},
+ {0x0000a598, 0x25020ec0, 0x25020ec0, 0x15000402, 0x15000402},
+ {0x0000a59c, 0x2b020ec3, 0x2b020ec3, 0x19000404, 0x19000404},
+ {0x0000a5a0, 0x2f001f04, 0x2f001f04, 0x1b000603, 0x1b000603},
+ {0x0000a5a4, 0x35001fc4, 0x35001fc4, 0x1f000a02, 0x1f000a02},
+ {0x0000a5a8, 0x3c022f04, 0x3c022f04, 0x23000a04, 0x23000a04},
+ {0x0000a5ac, 0x41023e85, 0x41023e85, 0x26000a20, 0x26000a20},
+ {0x0000a5b0, 0x48023ec6, 0x48023ec6, 0x2a000e20, 0x2a000e20},
+ {0x0000a5b4, 0x4d023f01, 0x4d023f01, 0x2e000e22, 0x2e000e22},
+ {0x0000a5b8, 0x53023f4b, 0x53023f4b, 0x31000e24, 0x31000e24},
+ {0x0000a5bc, 0x5a027f09, 0x5a027f09, 0x34001640, 0x34001640},
+ {0x0000a5c0, 0x5f027fc9, 0x5f027fc9, 0x38001660, 0x38001660},
+ {0x0000a5c4, 0x6502feca, 0x6502feca, 0x3b001861, 0x3b001861},
+ {0x0000a5c8, 0x6b02ff4a, 0x6b02ff4a, 0x3e001a81, 0x3e001a81},
+ {0x0000a5cc, 0x7203feca, 0x7203feca, 0x42001a83, 0x42001a83},
+ {0x0000a5d0, 0x7703ff0b, 0x7703ff0b, 0x44001c84, 0x44001c84},
+ {0x0000a5d4, 0x7d06ffcb, 0x7d06ffcb, 0x48001ce3, 0x48001ce3},
+ {0x0000a5d8, 0x8407ff0b, 0x8407ff0b, 0x4c001ce5, 0x4c001ce5},
+ {0x0000a5dc, 0x8907ffcb, 0x8907ffcb, 0x50001ce9, 0x50001ce9},
+ {0x0000a5e0, 0x900fff0b, 0x900fff0b, 0x54001ceb, 0x54001ceb},
+ {0x0000a5e4, 0x960fffcb, 0x960fffcb, 0x56001eec, 0x56001eec},
+ {0x0000a5e8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+ {0x0000a5ec, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+ {0x0000a5f0, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+ {0x0000a5f4, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+ {0x0000a5f8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+ {0x0000a5fc, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+ {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000},
+ {0x0000a618, 0x02008501, 0x02008501, 0x02008501, 0x02008501},
+ {0x0000a61c, 0x02008802, 0x02008802, 0x02008802, 0x02008802},
+ {0x0000a620, 0x0300c802, 0x0300c802, 0x0300c802, 0x0300c802},
+ {0x0000a624, 0x0300cc03, 0x0300cc03, 0x0300cc03, 0x0300cc03},
+ {0x0000a628, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+ {0x0000a62c, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+ {0x0000a630, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+ {0x0000a634, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+ {0x0000a638, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+ {0x0000a63c, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+};
+
+static const u32 ar9331_modes_low_ob_db_tx_gain_1p2[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x0000a410, 0x000050d7, 0x000050d7, 0x000050d7, 0x000050d7},
+ {0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
+ {0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
+ {0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
+ {0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200},
+ {0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202},
+ {0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400},
+ {0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402},
+ {0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404},
+ {0x0000a520, 0x2f001f04, 0x2f001f04, 0x23000a00, 0x23000a00},
+ {0x0000a524, 0x35001fc4, 0x35001fc4, 0x27000a02, 0x27000a02},
+ {0x0000a528, 0x3c022f04, 0x3c022f04, 0x2b000a04, 0x2b000a04},
+ {0x0000a52c, 0x41023e85, 0x41023e85, 0x3f001620, 0x3f001620},
+ {0x0000a530, 0x48023ec6, 0x48023ec6, 0x41001621, 0x41001621},
+ {0x0000a534, 0x4d023f01, 0x4d023f01, 0x44001640, 0x44001640},
+ {0x0000a538, 0x53023f4b, 0x53023f4b, 0x46001641, 0x46001641},
+ {0x0000a53c, 0x5a027f09, 0x5a027f09, 0x48001642, 0x48001642},
+ {0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x4b001644, 0x4b001644},
+ {0x0000a544, 0x6502feca, 0x6502feca, 0x4e001a81, 0x4e001a81},
+ {0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x51001a83, 0x51001a83},
+ {0x0000a54c, 0x7203feca, 0x7203feca, 0x54001c84, 0x54001c84},
+ {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x57001ce3, 0x57001ce3},
+ {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x5b001ce5, 0x5b001ce5},
+ {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5f001ce9, 0x5f001ce9},
+ {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x66001eec, 0x66001eec},
+ {0x0000a560, 0x900fff0b, 0x900fff0b, 0x66001eec, 0x66001eec},
+ {0x0000a564, 0x960fffcb, 0x960fffcb, 0x66001eec, 0x66001eec},
+ {0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+ {0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+ {0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+ {0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+ {0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+ {0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+ {0x0000a580, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
+ {0x0000a584, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
+ {0x0000a588, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
+ {0x0000a58c, 0x11062202, 0x11062202, 0x0b000200, 0x0b000200},
+ {0x0000a590, 0x17022e00, 0x17022e00, 0x0f000202, 0x0f000202},
+ {0x0000a594, 0x1d000ec2, 0x1d000ec2, 0x11000400, 0x11000400},
+ {0x0000a598, 0x25020ec0, 0x25020ec0, 0x15000402, 0x15000402},
+ {0x0000a59c, 0x2b020ec3, 0x2b020ec3, 0x19000404, 0x19000404},
+ {0x0000a5a0, 0x2f001f04, 0x2f001f04, 0x1b000603, 0x1b000603},
+ {0x0000a5a4, 0x35001fc4, 0x35001fc4, 0x1f000a02, 0x1f000a02},
+ {0x0000a5a8, 0x3c022f04, 0x3c022f04, 0x23000a04, 0x23000a04},
+ {0x0000a5ac, 0x41023e85, 0x41023e85, 0x26000a20, 0x26000a20},
+ {0x0000a5b0, 0x48023ec6, 0x48023ec6, 0x2a000e20, 0x2a000e20},
+ {0x0000a5b4, 0x4d023f01, 0x4d023f01, 0x2e000e22, 0x2e000e22},
+ {0x0000a5b8, 0x53023f4b, 0x53023f4b, 0x31000e24, 0x31000e24},
+ {0x0000a5bc, 0x5a027f09, 0x5a027f09, 0x34001640, 0x34001640},
+ {0x0000a5c0, 0x5f027fc9, 0x5f027fc9, 0x38001660, 0x38001660},
+ {0x0000a5c4, 0x6502feca, 0x6502feca, 0x3b001861, 0x3b001861},
+ {0x0000a5c8, 0x6b02ff4a, 0x6b02ff4a, 0x3e001a81, 0x3e001a81},
+ {0x0000a5cc, 0x7203feca, 0x7203feca, 0x42001a83, 0x42001a83},
+ {0x0000a5d0, 0x7703ff0b, 0x7703ff0b, 0x44001c84, 0x44001c84},
+ {0x0000a5d4, 0x7d06ffcb, 0x7d06ffcb, 0x48001ce3, 0x48001ce3},
+ {0x0000a5d8, 0x8407ff0b, 0x8407ff0b, 0x4c001ce5, 0x4c001ce5},
+ {0x0000a5dc, 0x8907ffcb, 0x8907ffcb, 0x50001ce9, 0x50001ce9},
+ {0x0000a5e0, 0x900fff0b, 0x900fff0b, 0x54001ceb, 0x54001ceb},
+ {0x0000a5e4, 0x960fffcb, 0x960fffcb, 0x56001eec, 0x56001eec},
+ {0x0000a5e8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+ {0x0000a5ec, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+ {0x0000a5f0, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+ {0x0000a5f4, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+ {0x0000a5f8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+ {0x0000a5fc, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+ {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000},
+ {0x0000a618, 0x02008501, 0x02008501, 0x02008501, 0x02008501},
+ {0x0000a61c, 0x02008802, 0x02008802, 0x02008802, 0x02008802},
+ {0x0000a620, 0x0300c802, 0x0300c802, 0x0300c802, 0x0300c802},
+ {0x0000a624, 0x0300cc03, 0x0300cc03, 0x0300cc03, 0x0300cc03},
+ {0x0000a628, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+ {0x0000a62c, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+ {0x0000a630, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+ {0x0000a634, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+ {0x0000a638, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+ {0x0000a63c, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+};
+
+static const u32 ar9331_1p2_baseband_core_txfir_coeff_japan_2484[][2] = {
+ /* Addr allmodes */
+ {0x0000a398, 0x00000000},
+ {0x0000a39c, 0x6f7f0301},
+ {0x0000a3a0, 0xca9228ee},
+};
+
+static const u32 ar9331_1p2_xtal_25M[][2] = {
+ /* Addr allmodes */
+ {0x00007038, 0x000002f8},
+ {0x00008244, 0x0010f3d7},
+ {0x0000824c, 0x0001e7ae},
+ {0x0001609c, 0x0f508f29},
+};
+
+static const u32 ar9331_1p2_radio_core[][2] = {
+ /* Addr allmodes */
+ {0x00016000, 0x36db6db6},
+ {0x00016004, 0x6db6db40},
+ {0x00016008, 0x73800000},
+ {0x0001600c, 0x00000000},
+ {0x00016040, 0x7f80fff8},
+ {0x00016044, 0x03d6d2db},
+ {0x00016048, 0x6c924268},
+ {0x0001604c, 0x000f0278},
+ {0x00016050, 0x4db6db8c},
+ {0x00016054, 0x6db60000},
+ {0x00016080, 0x00080000},
+ {0x00016084, 0x0e48048c},
+ {0x00016088, 0x14214514},
+ {0x0001608c, 0x119f081c},
+ {0x00016090, 0x24926490},
+ {0x00016098, 0xd411eb84},
+ {0x000160a0, 0xc2108ffe},
+ {0x000160a4, 0x812fc370},
+ {0x000160a8, 0x423c8000},
+ {0x000160ac, 0x24651800},
+ {0x000160b0, 0x03284f3e},
+ {0x000160b4, 0x92480040},
+ {0x000160c0, 0x006db6db},
+ {0x000160c4, 0x0186db60},
+ {0x000160c8, 0x6db6db6c},
+ {0x000160cc, 0x6de6c300},
+ {0x000160d0, 0x14500820},
+ {0x00016100, 0x04cb0001},
+ {0x00016104, 0xfff80015},
+ {0x00016108, 0x00080010},
+ {0x0001610c, 0x00170000},
+ {0x00016140, 0x10804000},
+ {0x00016144, 0x01884080},
+ {0x00016148, 0x000080c0},
+ {0x00016280, 0x01000015},
+ {0x00016284, 0x14d20000},
+ {0x00016288, 0x00318000},
+ {0x0001628c, 0x50000000},
+ {0x00016290, 0x4b96210f},
+ {0x00016380, 0x00000000},
+ {0x00016384, 0x00000000},
+ {0x00016388, 0x00800700},
+ {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},
+};
+
+static const u32 ar9331_1p2_soc_postamble[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x00007010, 0x00000022, 0x00000022, 0x00000022, 0x00000022},
+};
+
+static const u32 ar9331_common_wo_xlna_rx_gain_1p2[][2] = {
+ /* Addr allmodes */
+ {0x0000a000, 0x00060005},
+ {0x0000a004, 0x00810080},
+ {0x0000a008, 0x00830082},
+ {0x0000a00c, 0x00850084},
+ {0x0000a010, 0x01820181},
+ {0x0000a014, 0x01840183},
+ {0x0000a018, 0x01880185},
+ {0x0000a01c, 0x018a0189},
+ {0x0000a020, 0x02850284},
+ {0x0000a024, 0x02890288},
+ {0x0000a028, 0x028b028a},
+ {0x0000a02c, 0x03850384},
+ {0x0000a030, 0x03890388},
+ {0x0000a034, 0x038b038a},
+ {0x0000a038, 0x038d038c},
+ {0x0000a03c, 0x03910390},
+ {0x0000a040, 0x03930392},
+ {0x0000a044, 0x03950394},
+ {0x0000a048, 0x00000396},
+ {0x0000a04c, 0x00000000},
+ {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, 0x28282828},
+ {0x0000a084, 0x28282828},
+ {0x0000a088, 0x28282828},
+ {0x0000a08c, 0x28282828},
+ {0x0000a090, 0x28282828},
+ {0x0000a094, 0x24242428},
+ {0x0000a098, 0x171e1e1e},
+ {0x0000a09c, 0x02020b0b},
+ {0x0000a0a0, 0x02020202},
+ {0x0000a0a4, 0x00000000},
+ {0x0000a0a8, 0x00000000},
+ {0x0000a0ac, 0x00000000},
+ {0x0000a0b0, 0x00000000},
+ {0x0000a0b4, 0x00000000},
+ {0x0000a0b8, 0x00000000},
+ {0x0000a0bc, 0x00000000},
+ {0x0000a0c0, 0x22072208},
+ {0x0000a0c4, 0x22052206},
+ {0x0000a0c8, 0x22032204},
+ {0x0000a0cc, 0x22012202},
+ {0x0000a0d0, 0x221f2200},
+ {0x0000a0d4, 0x221d221e},
+ {0x0000a0d8, 0x33023303},
+ {0x0000a0dc, 0x33003301},
+ {0x0000a0e0, 0x331e331f},
+ {0x0000a0e4, 0x4402331d},
+ {0x0000a0e8, 0x44004401},
+ {0x0000a0ec, 0x441e441f},
+ {0x0000a0f0, 0x55025503},
+ {0x0000a0f4, 0x55005501},
+ {0x0000a0f8, 0x551e551f},
+ {0x0000a0fc, 0x6602551d},
+ {0x0000a100, 0x66006601},
+ {0x0000a104, 0x661e661f},
+ {0x0000a108, 0x7703661d},
+ {0x0000a10c, 0x77017702},
+ {0x0000a110, 0x00007700},
+ {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, 0x111f1100},
+ {0x0000a148, 0x111d111e},
+ {0x0000a14c, 0x111b111c},
+ {0x0000a150, 0x22032204},
+ {0x0000a154, 0x22012202},
+ {0x0000a158, 0x221f2200},
+ {0x0000a15c, 0x221d221e},
+ {0x0000a160, 0x33013302},
+ {0x0000a164, 0x331f3300},
+ {0x0000a168, 0x4402331e},
+ {0x0000a16c, 0x44004401},
+ {0x0000a170, 0x441e441f},
+ {0x0000a174, 0x55015502},
+ {0x0000a178, 0x551f5500},
+ {0x0000a17c, 0x6602551e},
+ {0x0000a180, 0x66006601},
+ {0x0000a184, 0x661e661f},
+ {0x0000a188, 0x7703661d},
+ {0x0000a18c, 0x77017702},
+ {0x0000a190, 0x00007700},
+ {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, 0x00000296},
+};
+
+static const u32 ar9331_1p2_baseband_core[][2] = {
+ /* Addr allmodes */
+ {0x00009800, 0xafe68e30},
+ {0x00009804, 0xfd14e000},
+ {0x00009808, 0x9c0a8f6b},
+ {0x0000980c, 0x04800000},
+ {0x00009814, 0x9280c00a},
+ {0x00009818, 0x00000000},
+ {0x0000981c, 0x00020028},
+ {0x00009834, 0x5f3ca3de},
+ {0x00009838, 0x0108ecff},
+ {0x0000983c, 0x14750600},
+ {0x00009880, 0x201fff00},
+ {0x00009884, 0x00001042},
+ {0x000098a4, 0x00200400},
+ {0x000098b0, 0x32840bbe},
+ {0x000098d0, 0x004b6a8e},
+ {0x000098d4, 0x00000820},
+ {0x000098dc, 0x00000000},
+ {0x000098f0, 0x00000000},
+ {0x000098f4, 0x00000000},
+ {0x00009c04, 0x00000000},
+ {0x00009c08, 0x03200000},
+ {0x00009c0c, 0x00000000},
+ {0x00009c10, 0x00000000},
+ {0x00009c14, 0x00046384},
+ {0x00009c18, 0x05b6b440},
+ {0x00009c1c, 0x00b6b440},
+ {0x00009d00, 0xc080a333},
+ {0x00009d04, 0x40206c10},
+ {0x00009d08, 0x009c4060},
+ {0x00009d0c, 0x1883800a},
+ {0x00009d10, 0x01834061},
+ {0x00009d14, 0x00c00400},
+ {0x00009d18, 0x00000000},
+ {0x00009e08, 0x0038233c},
+ {0x00009e24, 0x9927b515},
+ {0x00009e28, 0x12ef0200},
+ {0x00009e30, 0x06336f77},
+ {0x00009e34, 0x6af6532f},
+ {0x00009e38, 0x0cc80c00},
+ {0x00009e40, 0x0d261820},
+ {0x00009e4c, 0x00001004},
+ {0x00009e50, 0x00ff03f1},
+ {0x00009fc0, 0x803e4788},
+ {0x00009fc4, 0x0001efb5},
+ {0x00009fcc, 0x40000014},
+ {0x0000a20c, 0x00000000},
+ {0x0000a220, 0x00000000},
+ {0x0000a224, 0x00000000},
+ {0x0000a228, 0x10002310},
+ {0x0000a23c, 0x00000000},
+ {0x0000a244, 0x0c000000},
+ {0x0000a2a0, 0x00000001},
+ {0x0000a2c0, 0x00000001},
+ {0x0000a2c8, 0x00000000},
+ {0x0000a2cc, 0x18c43433},
+ {0x0000a2d4, 0x00000000},
+ {0x0000a2dc, 0x00000000},
+ {0x0000a2e0, 0x00000000},
+ {0x0000a2e4, 0x00000000},
+ {0x0000a2e8, 0x00000000},
+ {0x0000a2ec, 0x00000000},
+ {0x0000a2f0, 0x00000000},
+ {0x0000a2f4, 0x00000000},
+ {0x0000a2f8, 0x00000000},
+ {0x0000a344, 0x00000000},
+ {0x0000a34c, 0x00000000},
+ {0x0000a350, 0x0000a000},
+ {0x0000a364, 0x00000000},
+ {0x0000a370, 0x00000000},
+ {0x0000a390, 0x00000001},
+ {0x0000a394, 0x00000444},
+ {0x0000a398, 0x001f0e0f},
+ {0x0000a39c, 0x0075393f},
+ {0x0000a3a0, 0xb79f6427},
+ {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, 0x00000006},
+ {0x0000a3f8, 0x0cdbd380},
+ {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, 0x00000000},
+ {0x0000a440, 0x00000000},
+ {0x0000a444, 0x00000000},
+ {0x0000a448, 0x04000000},
+ {0x0000a44c, 0x00000001},
+ {0x0000a450, 0x00010000},
+ {0x0000a458, 0x00000000},
+ {0x0000a640, 0x00000000},
+ {0x0000a644, 0x3fad9d74},
+ {0x0000a648, 0x0048060a},
+ {0x0000a64c, 0x00003c37},
+ {0x0000a670, 0x03020100},
+ {0x0000a674, 0x09080504},
+ {0x0000a678, 0x0d0c0b0a},
+ {0x0000a67c, 0x13121110},
+ {0x0000a680, 0x31301514},
+ {0x0000a684, 0x35343332},
+ {0x0000a688, 0x00000036},
+ {0x0000a690, 0x00000838},
+ {0x0000a7c0, 0x00000000},
+ {0x0000a7c4, 0xfffffffc},
+ {0x0000a7c8, 0x00000000},
+ {0x0000a7cc, 0x00000000},
+ {0x0000a7d0, 0x00000000},
+ {0x0000a7d4, 0x00000004},
+ {0x0000a7dc, 0x00000001},
+};
+
+static const u32 ar9331_modes_high_power_tx_gain_1p2[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x0000a410, 0x000050d7, 0x000050d7, 0x000050d7, 0x000050d7},
+ {0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
+ {0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
+ {0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
+ {0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200},
+ {0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202},
+ {0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400},
+ {0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402},
+ {0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404},
+ {0x0000a520, 0x2f001f04, 0x2f001f04, 0x23000a00, 0x23000a00},
+ {0x0000a524, 0x35001fc4, 0x35001fc4, 0x27000a02, 0x27000a02},
+ {0x0000a528, 0x3c022f04, 0x3c022f04, 0x2b000a04, 0x2b000a04},
+ {0x0000a52c, 0x41023e85, 0x41023e85, 0x3f001620, 0x3f001620},
+ {0x0000a530, 0x48023ec6, 0x48023ec6, 0x41001621, 0x41001621},
+ {0x0000a534, 0x4d023f01, 0x4d023f01, 0x44001640, 0x44001640},
+ {0x0000a538, 0x53023f4b, 0x53023f4b, 0x46001641, 0x46001641},
+ {0x0000a53c, 0x5a027f09, 0x5a027f09, 0x48001642, 0x48001642},
+ {0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x4b001644, 0x4b001644},
+ {0x0000a544, 0x6502feca, 0x6502feca, 0x4e001a81, 0x4e001a81},
+ {0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x51001a83, 0x51001a83},
+ {0x0000a54c, 0x7203feca, 0x7203feca, 0x54001c84, 0x54001c84},
+ {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x57001ce3, 0x57001ce3},
+ {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x5b001ce5, 0x5b001ce5},
+ {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5f001ce9, 0x5f001ce9},
+ {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x66001eec, 0x66001eec},
+ {0x0000a560, 0x900fff0b, 0x900fff0b, 0x66001eec, 0x66001eec},
+ {0x0000a564, 0x960fffcb, 0x960fffcb, 0x66001eec, 0x66001eec},
+ {0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+ {0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+ {0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+ {0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+ {0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+ {0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+ {0x0000a580, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
+ {0x0000a584, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
+ {0x0000a588, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
+ {0x0000a58c, 0x11062202, 0x11062202, 0x0b000200, 0x0b000200},
+ {0x0000a590, 0x17022e00, 0x17022e00, 0x0f000202, 0x0f000202},
+ {0x0000a594, 0x1d000ec2, 0x1d000ec2, 0x11000400, 0x11000400},
+ {0x0000a598, 0x25020ec0, 0x25020ec0, 0x15000402, 0x15000402},
+ {0x0000a59c, 0x2b020ec3, 0x2b020ec3, 0x19000404, 0x19000404},
+ {0x0000a5a0, 0x2f001f04, 0x2f001f04, 0x1b000603, 0x1b000603},
+ {0x0000a5a4, 0x35001fc4, 0x35001fc4, 0x1f000a02, 0x1f000a02},
+ {0x0000a5a8, 0x3c022f04, 0x3c022f04, 0x23000a04, 0x23000a04},
+ {0x0000a5ac, 0x41023e85, 0x41023e85, 0x26000a20, 0x26000a20},
+ {0x0000a5b0, 0x48023ec6, 0x48023ec6, 0x2a000e20, 0x2a000e20},
+ {0x0000a5b4, 0x4d023f01, 0x4d023f01, 0x2e000e22, 0x2e000e22},
+ {0x0000a5b8, 0x53023f4b, 0x53023f4b, 0x31000e24, 0x31000e24},
+ {0x0000a5bc, 0x5a027f09, 0x5a027f09, 0x34001640, 0x34001640},
+ {0x0000a5c0, 0x5f027fc9, 0x5f027fc9, 0x38001660, 0x38001660},
+ {0x0000a5c4, 0x6502feca, 0x6502feca, 0x3b001861, 0x3b001861},
+ {0x0000a5c8, 0x6b02ff4a, 0x6b02ff4a, 0x3e001a81, 0x3e001a81},
+ {0x0000a5cc, 0x7203feca, 0x7203feca, 0x42001a83, 0x42001a83},
+ {0x0000a5d0, 0x7703ff0b, 0x7703ff0b, 0x44001c84, 0x44001c84},
+ {0x0000a5d4, 0x7d06ffcb, 0x7d06ffcb, 0x48001ce3, 0x48001ce3},
+ {0x0000a5d8, 0x8407ff0b, 0x8407ff0b, 0x4c001ce5, 0x4c001ce5},
+ {0x0000a5dc, 0x8907ffcb, 0x8907ffcb, 0x50001ce9, 0x50001ce9},
+ {0x0000a5e0, 0x900fff0b, 0x900fff0b, 0x54001ceb, 0x54001ceb},
+ {0x0000a5e4, 0x960fffcb, 0x960fffcb, 0x56001eec, 0x56001eec},
+ {0x0000a5e8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+ {0x0000a5ec, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+ {0x0000a5f0, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+ {0x0000a5f4, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+ {0x0000a5f8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+ {0x0000a5fc, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+ {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000},
+ {0x0000a618, 0x02008501, 0x02008501, 0x02008501, 0x02008501},
+ {0x0000a61c, 0x02008802, 0x02008802, 0x02008802, 0x02008802},
+ {0x0000a620, 0x0300c802, 0x0300c802, 0x0300c802, 0x0300c802},
+ {0x0000a624, 0x0300cc03, 0x0300cc03, 0x0300cc03, 0x0300cc03},
+ {0x0000a628, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+ {0x0000a62c, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+ {0x0000a630, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+ {0x0000a634, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+ {0x0000a638, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+ {0x0000a63c, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+};
+
+static const u32 ar9331_1p2_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 ar9331_1p2_soc_preamble[][2] = {
+ /* Addr allmodes */
+ {0x00007020, 0x00000000},
+ {0x00007034, 0x00000002},
+ {0x00007038, 0x000002f8},
+};
+
+static const u32 ar9331_1p2_xtal_40M[][2] = {
+ /* Addr allmodes */
+ {0x00007038, 0x000004c2},
+ {0x00008244, 0x0010f400},
+ {0x0000824c, 0x0001e800},
+ {0x0001609c, 0x0b283f31},
+};
+
+static const u32 ar9331_1p2_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, 0x13881c20},
+ {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},
+ {0x00008144, 0xffffffff},
+ {0x00008168, 0x00000000},
+ {0x0000816c, 0x00000000},
+ {0x00008170, 0x18486200},
+ {0x00008174, 0x33332210},
+ {0x00008178, 0x00000000},
+ {0x0000817c, 0x00020000},
+ {0x000081c0, 0x00000000},
+ {0x000081c4, 0x33332210},
+ {0x000081c8, 0x00000000},
+ {0x000081cc, 0x00000000},
+ {0x000081d4, 0x00000000},
+ {0x000081ec, 0x00000000},
+ {0x000081f0, 0x00000000},
+ {0x000081f4, 0x00000000},
+ {0x000081f8, 0x00000000},
+ {0x000081fc, 0x00000000},
+ {0x00008240, 0x00100000},
+ {0x00008248, 0x00000800},
+ {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, 0x00000140},
+ {0x00008314, 0x00000000},
+ {0x0000831c, 0x0000010d},
+ {0x00008328, 0x00000000},
+ {0x0000832c, 0x00000007},
+ {0x00008330, 0x00000302},
+ {0x00008334, 0x00000700},
+ {0x00008338, 0x00ff0000},
+ {0x0000833c, 0x02400000},
+ {0x00008340, 0x000107ff},
+ {0x00008344, 0xaa48105b},
+ {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, 0x000301ff},
+};
+
+static const u32 ar9331_common_rx_gain_1p2[][2] = {
+ /* Addr allmodes */
+ {0x0000a000, 0x00010000},
+ {0x0000a004, 0x00030002},
+ {0x0000a008, 0x00050004},
+ {0x0000a00c, 0x00810080},
+ {0x0000a010, 0x01800082},
+ {0x0000a014, 0x01820181},
+ {0x0000a018, 0x01840183},
+ {0x0000a01c, 0x01880185},
+ {0x0000a020, 0x018a0189},
+ {0x0000a024, 0x02850284},
+ {0x0000a028, 0x02890288},
+ {0x0000a02c, 0x03850384},
+ {0x0000a030, 0x03890388},
+ {0x0000a034, 0x038b038a},
+ {0x0000a038, 0x038d038c},
+ {0x0000a03c, 0x03910390},
+ {0x0000a040, 0x03930392},
+ {0x0000a044, 0x03950394},
+ {0x0000a048, 0x00000396},
+ {0x0000a04c, 0x00000000},
+ {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, 0x28282828},
+ {0x0000a084, 0x28282828},
+ {0x0000a088, 0x28282828},
+ {0x0000a08c, 0x28282828},
+ {0x0000a090, 0x28282828},
+ {0x0000a094, 0x21212128},
+ {0x0000a098, 0x171c1c1c},
+ {0x0000a09c, 0x02020212},
+ {0x0000a0a0, 0x00000202},
+ {0x0000a0a4, 0x00000000},
+ {0x0000a0a8, 0x00000000},
+ {0x0000a0ac, 0x00000000},
+ {0x0000a0b0, 0x00000000},
+ {0x0000a0b4, 0x00000000},
+ {0x0000a0b8, 0x00000000},
+ {0x0000a0bc, 0x00000000},
+ {0x0000a0c0, 0x001f0000},
+ {0x0000a0c4, 0x111f1100},
+ {0x0000a0c8, 0x111d111e},
+ {0x0000a0cc, 0x111b111c},
+ {0x0000a0d0, 0x22032204},
+ {0x0000a0d4, 0x22012202},
+ {0x0000a0d8, 0x221f2200},
+ {0x0000a0dc, 0x221d221e},
+ {0x0000a0e0, 0x33013302},
+ {0x0000a0e4, 0x331f3300},
+ {0x0000a0e8, 0x4402331e},
+ {0x0000a0ec, 0x44004401},
+ {0x0000a0f0, 0x441e441f},
+ {0x0000a0f4, 0x55015502},
+ {0x0000a0f8, 0x551f5500},
+ {0x0000a0fc, 0x6602551e},
+ {0x0000a100, 0x66006601},
+ {0x0000a104, 0x661e661f},
+ {0x0000a108, 0x7703661d},
+ {0x0000a10c, 0x77017702},
+ {0x0000a110, 0x00007700},
+ {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, 0x111f1100},
+ {0x0000a148, 0x111d111e},
+ {0x0000a14c, 0x111b111c},
+ {0x0000a150, 0x22032204},
+ {0x0000a154, 0x22012202},
+ {0x0000a158, 0x221f2200},
+ {0x0000a15c, 0x221d221e},
+ {0x0000a160, 0x33013302},
+ {0x0000a164, 0x331f3300},
+ {0x0000a168, 0x4402331e},
+ {0x0000a16c, 0x44004401},
+ {0x0000a170, 0x441e441f},
+ {0x0000a174, 0x55015502},
+ {0x0000a178, 0x551f5500},
+ {0x0000a17c, 0x6602551e},
+ {0x0000a180, 0x66006601},
+ {0x0000a184, 0x661e661f},
+ {0x0000a188, 0x7703661d},
+ {0x0000a18c, 0x77017702},
+ {0x0000a190, 0x00007700},
+ {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, 0x00000296},
+};
+
+#endif /* INITVALS_9330_1P2_H */
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index f75068b..46393f9 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -19,6 +19,7 @@
#include <linux/etherdevice.h>
#include <linux/device.h>
+#include <linux/interrupt.h>
#include <linux/leds.h>
#include <linux/completion.h>
@@ -54,8 +55,6 @@
(_l) &= ((_sz) - 1); \
} while (0)
-#define A_MAX(a, b) ((a) > (b) ? (a) : (b))
-
#define TSF_TO_TU(_h,_l) \
((((u32)(_h)) << 22) | (((u32)(_l)) >> 10))
@@ -102,6 +101,11 @@
#define ATH_TXSTATUS_RING_SIZE 64
+#define DS2PHYS(_dd, _ds) \
+ ((_dd)->dd_desc_paddr + ((caddr_t)(_ds) - (caddr_t)(_dd)->dd_desc))
+#define ATH_DESC_4KB_BOUND_CHECK(_daddr) ((((_daddr) & 0xFFF) > 0xF7F) ? 1 : 0)
+#define ATH_DESC_4KB_BOUND_NUM_SKIPPED(_len) ((_len) / 4096)
+
struct ath_descdma {
void *dd_desc;
dma_addr_t dd_desc_paddr;
@@ -179,7 +183,7 @@
struct ath_txq {
int mac80211_qnum; /* mac80211 queue number, -1 means not mac80211 Q */
u32 axq_qnum; /* ath9k hardware queue number */
- u32 *axq_link;
+ void *axq_link;
struct list_head axq_q;
spinlock_t axq_lock;
u32 axq_depth;
@@ -188,7 +192,6 @@
bool axq_tx_inprogress;
struct list_head axq_acq;
struct list_head txq_fifo[ATH_TXFIFO_DEPTH];
- struct list_head txq_fifo_pending;
u8 txq_headidx;
u8 txq_tailidx;
int pending_frames;
@@ -428,6 +431,7 @@
void ath_hw_pll_work(struct work_struct *work);
void ath_paprd_calibrate(struct work_struct *work);
void ath_ani_calibrate(unsigned long data);
+void ath_start_ani(struct ath_common *common);
/**********/
/* BTCOEX */
@@ -579,7 +583,7 @@
int naps; /* number of AP vifs */
int nmeshes; /* number of mesh vifs */
int nstations; /* number of station vifs */
- int nwds; /* number of nwd vifs */
+ int nwds; /* number of WDS vifs */
int nadhocs; /* number of adhoc vifs */
int nothers; /* number of vifs not specified above. */
};
@@ -669,12 +673,8 @@
const struct ath_bus_ops *bus_ops);
void ath9k_deinit_device(struct ath_softc *sc);
void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw);
-int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
- struct ath9k_channel *hchan);
-void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw);
void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw);
-bool ath9k_setpower(struct ath_softc *sc, enum ath9k_power_mode mode);
bool ath9k_uses_beacons(int type);
#ifdef CONFIG_ATH9K_PCI
diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c
index d4d8cec..0d13ff7 100644
--- a/drivers/net/wireless/ath/ath9k/beacon.c
+++ b/drivers/net/wireless/ath/ath9k/beacon.c
@@ -14,6 +14,7 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include <linux/dma-mapping.h>
#include "ath9k.h"
#define FUDGE 2
@@ -360,6 +361,7 @@
struct ath_common *common = ath9k_hw_common(ah);
struct ath_buf *bf = NULL;
struct ieee80211_vif *vif;
+ struct ath_tx_status ts;
int slot;
u32 bfaddr, bc = 0;
@@ -384,7 +386,9 @@
ath_dbg(common, ATH_DBG_BSTUCK,
"beacon is officially stuck\n");
sc->sc_flags |= SC_OP_TSF_RESET;
+ spin_lock(&sc->sc_pcu_lock);
ath_reset(sc, true);
+ spin_unlock(&sc->sc_pcu_lock);
}
return;
@@ -464,6 +468,11 @@
ath9k_hw_txstart(ah, sc->beacon.beaconq);
sc->beacon.ast_be_xmit += bc; /* XXX per-vif? */
+ if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
+ spin_lock_bh(&sc->sc_pcu_lock);
+ ath9k_hw_txprocdesc(ah, bf->bf_desc, (void *)&ts);
+ spin_unlock_bh(&sc->sc_pcu_lock);
+ }
}
}
@@ -496,7 +505,7 @@
u32 nexttbtt, intval;
/* NB: the beacon interval is kept internally in TU's */
- intval = TU_TO_USEC(conf->beacon_interval & ATH9K_BEACON_PERIOD);
+ intval = TU_TO_USEC(conf->beacon_interval);
intval /= ATH_BCBUF; /* for staggered beacons */
nexttbtt = intval;
@@ -543,7 +552,7 @@
}
memset(&bs, 0, sizeof(bs));
- intval = conf->beacon_interval & ATH9K_BEACON_PERIOD;
+ intval = conf->beacon_interval;
/*
* Setup dtim and cfp parameters according to
@@ -652,22 +661,13 @@
{
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah);
- u32 tsf, delta, intval, nexttbtt;
+ u32 tsf, intval, nexttbtt;
ath9k_reset_beacon_status(sc);
- tsf = ath9k_hw_gettsf32(ah) + TU_TO_USEC(FUDGE);
- intval = TU_TO_USEC(conf->beacon_interval & ATH9K_BEACON_PERIOD);
-
- if (!sc->beacon.bc_tstamp)
- nexttbtt = tsf + intval;
- else {
- if (tsf > sc->beacon.bc_tstamp)
- delta = (tsf - sc->beacon.bc_tstamp);
- else
- delta = (tsf + 1 + (~0U - sc->beacon.bc_tstamp));
- nexttbtt = tsf + intval - (delta % intval);
- }
+ intval = TU_TO_USEC(conf->beacon_interval);
+ tsf = roundup(ath9k_hw_gettsf32(ah) + TU_TO_USEC(FUDGE), intval);
+ nexttbtt = tsf + intval;
ath_dbg(common, ATH_DBG_BEACON,
"IBSS nexttbtt %u intval %u (%u)\n",
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c
index d55ffd7..22d3a26e 100644
--- a/drivers/net/wireless/ath/ath9k/debug.c
+++ b/drivers/net/wireless/ath/ath9k/debug.c
@@ -176,6 +176,56 @@
.llseek = default_llseek,
};
+static ssize_t read_file_disable_ani(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ath_softc *sc = file->private_data;
+ struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+ char buf[32];
+ unsigned int len;
+
+ len = sprintf(buf, "%d\n", common->disable_ani);
+ return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static ssize_t write_file_disable_ani(struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ath_softc *sc = file->private_data;
+ struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+ unsigned long disable_ani;
+ char buf[32];
+ ssize_t len;
+
+ len = min(count, sizeof(buf) - 1);
+ if (copy_from_user(buf, user_buf, len))
+ return -EFAULT;
+
+ buf[len] = '\0';
+ if (strict_strtoul(buf, 0, &disable_ani))
+ return -EINVAL;
+
+ common->disable_ani = !!disable_ani;
+
+ if (disable_ani) {
+ sc->sc_flags &= ~SC_OP_ANI_RUN;
+ del_timer_sync(&common->ani.timer);
+ } else {
+ sc->sc_flags |= SC_OP_ANI_RUN;
+ ath_start_ani(common);
+ }
+
+ return count;
+}
+
+static const struct file_operations fops_disable_ani = {
+ .read = read_file_disable_ani,
+ .write = write_file_disable_ani,
+ .open = ath9k_debugfs_open,
+ .owner = THIS_MODULE,
+ .llseek = default_llseek,
+};
static ssize_t read_file_dma(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
@@ -550,6 +600,7 @@
PR("MPDUs Queued: ", queued);
PR("MPDUs Completed: ", completed);
+ PR("MPDUs XRetried: ", xretries);
PR("Aggregates: ", a_aggr);
PR("AMPDUs Queued HW:", a_queued_hw);
PR("AMPDUs Queued SW:", a_queued_sw);
@@ -587,7 +638,6 @@
PRQLE("axq_q empty: ", axq_q);
PRQLE("axq_acq empty: ", axq_acq);
- PRQLE("txq_fifo_pending: ", txq_fifo_pending);
for (i = 0; i < ATH_TXFIFO_DEPTH; i++) {
snprintf(tmp, sizeof(tmp) - 1, "txq_fifo[%i] empty: ", i);
PRQLE(tmp, txq_fifo[i]);
@@ -807,7 +857,10 @@
else
TX_STAT_INC(qnum, a_completed);
} else {
- TX_STAT_INC(qnum, completed);
+ if (bf_isxretried(bf))
+ TX_STAT_INC(qnum, xretries);
+ else
+ TX_STAT_INC(qnum, completed);
}
if (ts->ts_status & ATH9K_TXERR_FIFO)
@@ -1160,6 +1213,8 @@
sc->debug.debugfs_phy, sc, &fops_rx_chainmask);
debugfs_create_file("tx_chainmask", S_IRUSR | S_IWUSR,
sc->debug.debugfs_phy, sc, &fops_tx_chainmask);
+ debugfs_create_file("disable_ani", S_IRUSR | S_IWUSR,
+ sc->debug.debugfs_phy, sc, &fops_disable_ani);
debugfs_create_file("regidx", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy,
sc, &fops_regidx);
debugfs_create_file("regval", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy,
diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h
index 8ce6ad8..4a04510 100644
--- a/drivers/net/wireless/ath/ath9k/debug.h
+++ b/drivers/net/wireless/ath/ath9k/debug.h
@@ -116,6 +116,7 @@
u32 tx_bytes_all;
u32 queued;
u32 completed;
+ u32 xretries;
u32 a_aggr;
u32 a_queued_hw;
u32 a_queued_sw;
diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c
index 260f1f3..8028fe9 100644
--- a/drivers/net/wireless/ath/ath9k/hif_usb.c
+++ b/drivers/net/wireless/ath/ath9k/hif_usb.c
@@ -49,6 +49,8 @@
.driver_info = AR9280_USB }, /* Netgear WNDA3200 */
{ USB_DEVICE(0x083A, 0xA704),
.driver_info = AR9280_USB }, /* SMC Networks */
+ { USB_DEVICE(0x0411, 0x017f),
+ .driver_info = AR9280_USB }, /* Sony UWA-BR100 */
{ USB_DEVICE(0x0cf3, 0x20ff),
.driver_info = STORAGE_DEVICE },
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c
index aa6a731..57fe22b 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c
@@ -79,7 +79,7 @@
memset(&bs, 0, sizeof(bs));
- intval = bss_conf->beacon_interval & ATH9K_BEACON_PERIOD;
+ intval = bss_conf->beacon_interval;
bmiss_timeout = (ATH_DEFAULT_BMISS_LIMIT * bss_conf->beacon_interval);
/*
@@ -194,7 +194,7 @@
u8 cmd_rsp;
u64 tsf;
- intval = bss_conf->beacon_interval & ATH9K_BEACON_PERIOD;
+ intval = bss_conf->beacon_interval;
intval /= ATH9K_HTC_MAX_BCN_VIF;
nexttbtt = intval;
@@ -250,7 +250,7 @@
u8 cmd_rsp;
u64 tsf;
- intval = bss_conf->beacon_interval & ATH9K_BEACON_PERIOD;
+ intval = bss_conf->beacon_interval;
nexttbtt = intval;
/*
@@ -427,7 +427,7 @@
u16 intval;
int slot;
- intval = priv->cur_beacon_conf.beacon_interval & ATH9K_BEACON_PERIOD;
+ intval = priv->cur_beacon_conf.beacon_interval;
tsf = be64_to_cpu(swba->tsf);
tsftu = TSF_TO_TU(tsf >> 32, tsf);
diff --git a/drivers/net/wireless/ath/ath9k/hw-ops.h b/drivers/net/wireless/ath/ath9k/hw-ops.h
index 2f3e072..cb29e88 100644
--- a/drivers/net/wireless/ath/ath9k/hw-ops.h
+++ b/drivers/net/wireless/ath/ath9k/hw-ops.h
@@ -39,11 +39,6 @@
ath9k_hw_ops(ah)->set_desc_link(ds, link);
}
-static inline void ath9k_hw_get_desc_link(struct ath_hw *ah, void *ds,
- u32 **link)
-{
- ath9k_hw_ops(ah)->get_desc_link(ds, link);
-}
static inline bool ath9k_hw_calibrate(struct ath_hw *ah,
struct ath9k_channel *chan,
u8 rxchainmask,
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index 1be7c8b..07827b5 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -251,6 +251,15 @@
case AR5416_AR9100_DEVID:
ah->hw_version.macVersion = AR_SREV_VERSION_9100;
break;
+ case AR9300_DEVID_AR9330:
+ ah->hw_version.macVersion = AR_SREV_VERSION_9330;
+ if (ah->get_mac_revision) {
+ ah->hw_version.macRev = ah->get_mac_revision();
+ } else {
+ val = REG_READ(ah, AR_SREV);
+ ah->hw_version.macRev = MS(val, AR_SREV_REVISION2);
+ }
+ return;
case AR9300_DEVID_AR9340:
ah->hw_version.macVersion = AR_SREV_VERSION_9340;
val = REG_READ(ah, AR_SREV);
@@ -551,6 +560,7 @@
case AR_SREV_VERSION_9287:
case AR_SREV_VERSION_9271:
case AR_SREV_VERSION_9300:
+ case AR_SREV_VERSION_9330:
case AR_SREV_VERSION_9485:
case AR_SREV_VERSION_9340:
break;
@@ -561,7 +571,8 @@
return -EOPNOTSUPP;
}
- if (AR_SREV_9271(ah) || AR_SREV_9100(ah) || AR_SREV_9340(ah))
+ if (AR_SREV_9271(ah) || AR_SREV_9100(ah) || AR_SREV_9340(ah) ||
+ AR_SREV_9330(ah))
ah->is_pciexpress = false;
ah->hw_version.phyRev = REG_READ(ah, AR_PHY_CHIP_ID);
@@ -604,7 +615,10 @@
else
ah->tx_trig_level = (AR_FTRIG_512B >> AR_FTRIG_S);
- ah->bb_watchdog_timeout_ms = 25;
+ if (AR_SREV_9330(ah))
+ ah->bb_watchdog_timeout_ms = 85;
+ else
+ ah->bb_watchdog_timeout_ms = 25;
common->state = ATH_HW_INITIALIZED;
@@ -630,6 +644,7 @@
case AR2427_DEVID_PCIE:
case AR9300_DEVID_PCIE:
case AR9300_DEVID_AR9485_PCIE:
+ case AR9300_DEVID_AR9330:
case AR9300_DEVID_AR9340:
break;
default:
@@ -722,6 +737,39 @@
REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2,
AR_CH0_BB_DPLL2_PLL_PWD, 0x0);
udelay(1000);
+ } else if (AR_SREV_9330(ah)) {
+ u32 ddr_dpll2, pll_control2, kd;
+
+ if (ah->is_clk_25mhz) {
+ ddr_dpll2 = 0x18e82f01;
+ pll_control2 = 0xe04a3d;
+ kd = 0x1d;
+ } else {
+ ddr_dpll2 = 0x19e82f01;
+ pll_control2 = 0x886666;
+ kd = 0x3d;
+ }
+
+ /* program DDR PLL ki and kd value */
+ REG_WRITE(ah, AR_CH0_DDR_DPLL2, ddr_dpll2);
+
+ /* program DDR PLL phase_shift */
+ REG_RMW_FIELD(ah, AR_CH0_DDR_DPLL3,
+ AR_CH0_DPLL3_PHASE_SHIFT, 0x1);
+
+ REG_WRITE(ah, AR_RTC_PLL_CONTROL, 0x1142c);
+ udelay(1000);
+
+ /* program refdiv, nint, frac to RTC register */
+ REG_WRITE(ah, AR_RTC_PLL_CONTROL2, pll_control2);
+
+ /* program BB PLL kd and ki value */
+ REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2, AR_CH0_DPLL2_KD, kd);
+ REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2, AR_CH0_DPLL2_KI, 0x06);
+
+ /* 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)) {
u32 regval, pll2_divint, pll2_divfrac, refdiv;
@@ -763,7 +811,7 @@
REG_WRITE(ah, AR_RTC_PLL_CONTROL, pll);
- if (AR_SREV_9485(ah) || AR_SREV_9340(ah))
+ if (AR_SREV_9485(ah) || AR_SREV_9340(ah) || AR_SREV_9330(ah))
udelay(1000);
/* Switch the core clock for ar9271 to 117Mhz */
@@ -1114,6 +1162,41 @@
rst_flags |= AR_RTC_RC_MAC_COLD;
}
+ if (AR_SREV_9330(ah)) {
+ int npend = 0;
+ int i;
+
+ /* AR9330 WAR:
+ * call external reset function to reset WMAC if:
+ * - doing a cold reset
+ * - we have pending frames in the TX queues
+ */
+
+ for (i = 0; i < AR_NUM_QCU; i++) {
+ npend = ath9k_hw_numtxpending(ah, i);
+ if (npend)
+ break;
+ }
+
+ if (ah->external_reset &&
+ (npend || type == ATH9K_RESET_COLD)) {
+ int reset_err = 0;
+
+ ath_dbg(ath9k_hw_common(ah), ATH_DBG_RESET,
+ "reset MAC via external reset\n");
+
+ reset_err = ah->external_reset();
+ if (reset_err) {
+ ath_err(ath9k_hw_common(ah),
+ "External reset failed, err=%d\n",
+ reset_err);
+ return false;
+ }
+
+ REG_WRITE(ah, AR_RTC_RESET, 1);
+ }
+ }
+
REG_WRITE(ah, AR_RTC_RC, rst_flags);
REGWRITE_BUFFER_FLUSH(ah);
@@ -1545,7 +1628,7 @@
REG_WRITE(ah, AR_CFG, AR_CFG_SWTD | AR_CFG_SWRD);
}
#ifdef __BIG_ENDIAN
- else if (AR_SREV_9340(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);
@@ -1785,16 +1868,16 @@
REG_WRITE(ah, AR_NEXT_TBTT_TIMER, TU_TO_USEC(bs->bs_nexttbtt));
REG_WRITE(ah, AR_BEACON_PERIOD,
- TU_TO_USEC(bs->bs_intval & ATH9K_BEACON_PERIOD));
+ TU_TO_USEC(bs->bs_intval));
REG_WRITE(ah, AR_DMA_BEACON_PERIOD,
- TU_TO_USEC(bs->bs_intval & ATH9K_BEACON_PERIOD));
+ TU_TO_USEC(bs->bs_intval));
REGWRITE_BUFFER_FLUSH(ah);
REG_RMW_FIELD(ah, AR_RSSI_THR,
AR_RSSI_THR_BM_THR, bs->bs_bmissthreshold);
- beaconintval = bs->bs_intval & ATH9K_BEACON_PERIOD;
+ beaconintval = bs->bs_intval;
if (bs->bs_sleepduration > beaconintval)
beaconintval = bs->bs_sleepduration;
@@ -1983,7 +2066,7 @@
if (AR_SREV_9300_20_OR_LATER(ah)) {
pCap->hw_caps |= ATH9K_HW_CAP_EDMA | ATH9K_HW_CAP_FASTCLOCK;
- if (!AR_SREV_9485(ah))
+ if (!AR_SREV_9330(ah) && !AR_SREV_9485(ah))
pCap->hw_caps |= ATH9K_HW_CAP_LDPC;
pCap->rx_hp_qdepth = ATH9K_HW_RX_HP_QDEPTH;
@@ -2025,7 +2108,7 @@
}
- if (AR_SREV_9485(ah)) {
+ if (AR_SREV_9330(ah) || AR_SREV_9485(ah)) {
ant_div_ctl1 = ah->eep_ops->get_eeprom(ah, EEP_ANT_DIV_CTL1);
/*
* enable the diversity-combining algorithm only when
@@ -2574,6 +2657,7 @@
{ AR_SREV_VERSION_9287, "9287" },
{ AR_SREV_VERSION_9271, "9271" },
{ AR_SREV_VERSION_9300, "9300" },
+ { AR_SREV_VERSION_9330, "9330" },
{ AR_SREV_VERSION_9485, "9485" },
};
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h
index 4b157c5..818acdd 100644
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
@@ -45,6 +45,7 @@
#define AR9300_DEVID_PCIE 0x0030
#define AR9300_DEVID_AR9340 0x0031
#define AR9300_DEVID_AR9485_PCIE 0x0032
+#define AR9300_DEVID_AR9330 0x0035
#define AR5416_AR9100_DEVID 0x000b
@@ -157,8 +158,9 @@
#define ATH9K_HW_RX_HP_QDEPTH 16
#define ATH9K_HW_RX_LP_QDEPTH 128
-#define PAPRD_GAIN_TABLE_ENTRIES 32
-#define PAPRD_TABLE_SZ 24
+#define PAPRD_GAIN_TABLE_ENTRIES 32
+#define PAPRD_TABLE_SZ 24
+#define PAPRD_IDEAL_AGC2_PWR_RANGE 0xe0
enum ath_hw_txq_subtype {
ATH_TXQ_AC_BE = 0,
@@ -403,7 +405,6 @@
u32 bs_nexttbtt;
u32 bs_nextdtim;
u32 bs_intval;
-#define ATH9K_BEACON_PERIOD 0x0000ffff
#define ATH9K_TSFOOR_THRESHOLD 0x00004240 /* 16k us */
u32 bs_dtimperiod;
u16 bs_cfpperiod;
@@ -603,7 +604,6 @@
int power_off);
void (*rx_enable)(struct ath_hw *ah);
void (*set_desc_link)(void *ds, u32 link);
- void (*get_desc_link)(void *ds, u32 **link);
bool (*calibrate)(struct ath_hw *ah,
struct ath9k_channel *chan,
u8 rxchainmask,
@@ -862,6 +862,8 @@
u32 ent_mode;
bool is_clk_25mhz;
+ int (*get_mac_revision)(void);
+ int (*external_reset)(void);
};
struct ath_bus_ops {
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c
index 45c585a..b855fe1 100644
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
@@ -14,6 +14,7 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include <linux/dma-mapping.h>
#include <linux/slab.h>
#include <linux/ath9k_platform.h>
@@ -245,7 +246,7 @@
ht_info->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
ht_info->ampdu_density = IEEE80211_HT_MPDU_DENSITY_8;
- if (AR_SREV_9485(ah))
+ if (AR_SREV_9330(ah) || AR_SREV_9485(ah))
max_streams = 1;
else if (AR_SREV_9300_20_OR_LATER(ah))
max_streams = 3;
@@ -298,10 +299,6 @@
struct list_head *head, const char *name,
int nbuf, int ndesc, bool is_tx)
{
-#define DS2PHYS(_dd, _ds) \
- ((_dd)->dd_desc_paddr + ((caddr_t)(_ds) - (caddr_t)(_dd)->dd_desc))
-#define ATH_DESC_4KB_BOUND_CHECK(_daddr) ((((_daddr) & 0xFFF) > 0xF7F) ? 1 : 0)
-#define ATH_DESC_4KB_BOUND_NUM_SKIPPED(_len) ((_len) / 4096)
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
u8 *ds;
struct ath_buf *bf;
@@ -396,9 +393,6 @@
fail:
memset(dd, 0, sizeof(*dd));
return error;
-#undef ATH_DESC_4KB_BOUND_CHECK
-#undef ATH_DESC_4KB_BOUND_NUM_SKIPPED
-#undef DS2PHYS
}
void ath9k_init_crypto(struct ath_softc *sc)
@@ -519,7 +513,6 @@
{
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
int i = 0;
-
setup_timer(&common->ani.timer, ath_ani_calibrate, (unsigned long)sc);
sc->config.txpowlimit = ATH_TXPOWER_MAX;
@@ -575,6 +568,8 @@
sc->sc_ah->gpio_val = pdata->gpio_val;
sc->sc_ah->led_pin = pdata->led_pin;
ah->is_clk_25mhz = pdata->is_clk_25mhz;
+ ah->get_mac_revision = pdata->get_mac_revision;
+ ah->external_reset = pdata->external_reset;
}
common = ath9k_hw_common(ah);
@@ -585,6 +580,7 @@
common->priv = sc;
common->debug_mask = ath9k_debug;
common->btcoex_enabled = ath9k_btcoex_enable == 1;
+ common->disable_ani = false;
spin_lock_init(&common->cc_lock);
spin_lock_init(&sc->sc_serial_rw);
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index 2ca351f..9098aaa 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -62,14 +62,12 @@
if (txq->axq_depth || !list_empty(&txq->axq_acq))
pending = true;
- else if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)
- pending = !list_empty(&txq->txq_fifo_pending);
spin_unlock_bh(&txq->axq_lock);
return pending;
}
-bool ath9k_setpower(struct ath_softc *sc, enum ath9k_power_mode mode)
+static bool ath9k_setpower(struct ath_softc *sc, enum ath9k_power_mode mode)
{
unsigned long flags;
bool ret;
@@ -136,7 +134,7 @@
spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
}
-static void ath_start_ani(struct ath_common *common)
+void ath_start_ani(struct ath_common *common)
{
struct ath_hw *ah = common->ah;
unsigned long timestamp = jiffies_to_msecs(jiffies);
@@ -219,7 +217,7 @@
* by reseting the chip. To accomplish this we must first cleanup any pending
* DMA, then restart stuff.
*/
-int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
+static int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
struct ath9k_channel *hchan)
{
struct ath_hw *ah = sc->sc_ah;
@@ -302,7 +300,8 @@
ath_set_beacon(sc);
ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0);
ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work, HZ/2);
- ath_start_ani(common);
+ if (!common->disable_ani)
+ ath_start_ani(common);
}
ps_restore:
@@ -361,7 +360,7 @@
txctl.paprd = BIT(chain);
if (ath_tx_start(hw, skb, &txctl) != 0) {
- ath_dbg(common, ATH_DBG_XMIT, "PAPRD TX failed\n");
+ ath_dbg(common, ATH_DBG_CALIBRATE, "PAPRD TX failed\n");
dev_kfree_skb_any(skb);
return false;
}
@@ -370,7 +369,7 @@
msecs_to_jiffies(ATH_PAPRD_TIMEOUT));
if (!time_left)
- ath_dbg(ath9k_hw_common(sc->sc_ah), ATH_DBG_CALIBRATE,
+ ath_dbg(common, ATH_DBG_CALIBRATE,
"Timeout waiting for paprd training on TX chain %d\n",
chain);
@@ -394,12 +393,14 @@
if (!caldata)
return;
+ ath9k_ps_wakeup(sc);
+
if (ar9003_paprd_init_table(ah) < 0)
- return;
+ goto fail_paprd;
skb = alloc_skb(len, GFP_KERNEL);
if (!skb)
- return;
+ goto fail_paprd;
skb_put(skb, len);
memset(skb->data, 0, len);
@@ -411,7 +412,6 @@
memcpy(hdr->addr2, hw->wiphy->perm_addr, ETH_ALEN);
memcpy(hdr->addr3, hw->wiphy->perm_addr, ETH_ALEN);
- ath9k_ps_wakeup(sc);
for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) {
if (!(common->tx_chainmask & BIT(chain)))
continue;
@@ -431,11 +431,18 @@
if (!ath_paprd_send_frame(sc, skb, chain))
goto fail_paprd;
- if (!ar9003_paprd_is_done(ah))
+ if (!ar9003_paprd_is_done(ah)) {
+ ath_dbg(common, ATH_DBG_CALIBRATE,
+ "PAPRD not yet done on chain %d\n", chain);
break;
+ }
- if (ar9003_paprd_create_curve(ah, caldata, chain) != 0)
+ if (ar9003_paprd_create_curve(ah, caldata, chain)) {
+ ath_dbg(common, ATH_DBG_CALIBRATE,
+ "PAPRD create curve failed on chain %d\n",
+ chain);
break;
+ }
chain_ok = 1;
}
@@ -515,24 +522,19 @@
common->ani.checkani_timer = timestamp;
}
- /* Skip all processing if there's nothing to do. */
- if (longcal || shortcal || aniflag) {
- /* Call ANI routine if necessary */
- if (aniflag) {
- spin_lock_irqsave(&common->cc_lock, flags);
- ath9k_hw_ani_monitor(ah, ah->curchan);
- ath_update_survey_stats(sc);
- spin_unlock_irqrestore(&common->cc_lock, flags);
- }
+ /* Call ANI routine if necessary */
+ if (aniflag) {
+ spin_lock_irqsave(&common->cc_lock, flags);
+ ath9k_hw_ani_monitor(ah, ah->curchan);
+ ath_update_survey_stats(sc);
+ spin_unlock_irqrestore(&common->cc_lock, flags);
+ }
- /* Perform calibration if necessary */
- if (longcal || shortcal) {
- common->ani.caldone =
- ath9k_hw_calibrate(ah,
- ah->curchan,
- common->rx_chainmask,
- longcal);
- }
+ /* Perform calibration if necessary */
+ if (longcal || shortcal) {
+ common->ani.caldone =
+ ath9k_hw_calibrate(ah, ah->curchan,
+ common->rx_chainmask, longcal);
}
ath9k_ps_restore(sc);
@@ -615,8 +617,11 @@
ath_dbg(common, ATH_DBG_RESET, "Possible baseband hang, "
"busy=%d (try %d)\n", busy, sc->hw_busy_count + 1);
if (busy >= 99) {
- if (++sc->hw_busy_count >= 3)
+ if (++sc->hw_busy_count >= 3) {
+ spin_lock_bh(&sc->sc_pcu_lock);
ath_reset(sc, true);
+ spin_unlock_bh(&sc->sc_pcu_lock);
+ }
} else if (busy >= 0)
sc->hw_busy_count = 0;
@@ -635,7 +640,9 @@
/* Rx is hung for more than 500ms. Reset it */
ath_dbg(common, ATH_DBG_RESET,
"Possible RX hang, resetting");
+ spin_lock_bh(&sc->sc_pcu_lock);
ath_reset(sc, true);
+ spin_unlock_bh(&sc->sc_pcu_lock);
count = 0;
}
} else
@@ -672,7 +679,9 @@
if ((status & ATH9K_INT_FATAL) ||
(status & ATH9K_INT_BB_WATCHDOG)) {
+ spin_lock(&sc->sc_pcu_lock);
ath_reset(sc, true);
+ spin_unlock(&sc->sc_pcu_lock);
return;
}
@@ -868,7 +877,7 @@
#undef SCHED_INTR
}
-void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw)
+static void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw)
{
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah);
@@ -974,10 +983,10 @@
sc->hw_busy_count = 0;
/* Stop ANI */
+
del_timer_sync(&common->ani.timer);
ath9k_ps_wakeup(sc);
- spin_lock_bh(&sc->sc_pcu_lock);
ieee80211_stop_queues(hw);
@@ -1020,10 +1029,11 @@
}
ieee80211_wake_queues(hw);
- spin_unlock_bh(&sc->sc_pcu_lock);
/* Start ANI */
- ath_start_ani(common);
+ if (!common->disable_ani)
+ ath_start_ani(common);
+
ath9k_ps_restore(sc);
return r;
@@ -1261,7 +1271,6 @@
/* disable HAL and put h/w to sleep */
ath9k_hw_disable(ah);
- ath9k_hw_configpcipowersave(ah, 1, 1);
spin_unlock_bh(&sc->sc_pcu_lock);
@@ -1412,10 +1421,14 @@
ath9k_hw_set_interrupts(ah, ah->imask);
/* Set up ANI */
- if ((iter_data.naps + iter_data.nadhocs) > 0) {
+ if (iter_data.naps > 0) {
sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER;
- sc->sc_flags |= SC_OP_ANI_RUN;
- ath_start_ani(common);
+
+ if (!common->disable_ani) {
+ sc->sc_flags |= SC_OP_ANI_RUN;
+ ath_start_ani(common);
+ }
+
} else {
sc->sc_flags &= ~SC_OP_ANI_RUN;
del_timer_sync(&common->ani.timer);
@@ -1952,50 +1965,38 @@
struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
struct ath_vif *avp = (void *)vif->drv_priv;
- switch (sc->sc_ah->opmode) {
- case NL80211_IFTYPE_ADHOC:
- /* There can be only one vif available */
+ /*
+ * Skip iteration if primary station vif's bss info
+ * was not changed
+ */
+ if (sc->sc_flags & SC_OP_PRIM_STA_VIF)
+ return;
+
+ if (bss_conf->assoc) {
+ sc->sc_flags |= SC_OP_PRIM_STA_VIF;
+ avp->primary_sta_vif = true;
memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN);
common->curaid = bss_conf->aid;
ath9k_hw_write_associd(sc->sc_ah);
- /* configure beacon */
- if (bss_conf->enable_beacon)
- ath_beacon_config(sc, vif);
- break;
- case NL80211_IFTYPE_STATION:
- /*
- * Skip iteration if primary station vif's bss info
- * was not changed
- */
- if (sc->sc_flags & SC_OP_PRIM_STA_VIF)
- break;
-
- if (bss_conf->assoc) {
- sc->sc_flags |= SC_OP_PRIM_STA_VIF;
- avp->primary_sta_vif = true;
- memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN);
- common->curaid = bss_conf->aid;
- ath9k_hw_write_associd(sc->sc_ah);
- ath_dbg(common, ATH_DBG_CONFIG,
+ ath_dbg(common, ATH_DBG_CONFIG,
"Bss Info ASSOC %d, bssid: %pM\n",
bss_conf->aid, common->curbssid);
- ath_beacon_config(sc, vif);
- /*
- * Request a re-configuration of Beacon related timers
- * on the receipt of the first Beacon frame (i.e.,
- * after time sync with the AP).
- */
- sc->ps_flags |= PS_BEACON_SYNC | PS_WAIT_FOR_BEACON;
- /* Reset rssi stats */
- sc->last_rssi = ATH_RSSI_DUMMY_MARKER;
- sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER;
+ ath_beacon_config(sc, vif);
+ /*
+ * Request a re-configuration of Beacon related timers
+ * on the receipt of the first Beacon frame (i.e.,
+ * after time sync with the AP).
+ */
+ sc->ps_flags |= PS_BEACON_SYNC | PS_WAIT_FOR_BEACON;
+ /* Reset rssi stats */
+ sc->last_rssi = ATH_RSSI_DUMMY_MARKER;
+ sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER;
+ if (!common->disable_ani) {
sc->sc_flags |= SC_OP_ANI_RUN;
ath_start_ani(common);
}
- break;
- default:
- break;
+
}
}
@@ -2005,6 +2006,9 @@
struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
struct ath_vif *avp = (void *)vif->drv_priv;
+ if (sc->sc_ah->opmode != NL80211_IFTYPE_STATION)
+ return;
+
/* Reconfigure bss info */
if (avp->primary_sta_vif && !bss_conf->assoc) {
ath_dbg(common, ATH_DBG_CONFIG,
@@ -2023,8 +2027,7 @@
* None of station vifs are associated.
* Clear bssid & aid
*/
- if ((sc->sc_ah->opmode == NL80211_IFTYPE_STATION) &&
- !(sc->sc_flags & SC_OP_PRIM_STA_VIF)) {
+ if (!(sc->sc_flags & SC_OP_PRIM_STA_VIF)) {
ath9k_hw_write_associd(sc->sc_ah);
/* Stop ANI */
sc->sc_flags &= ~SC_OP_ANI_RUN;
@@ -2054,6 +2057,26 @@
common->curbssid, common->curaid);
}
+ if (changed & BSS_CHANGED_IBSS) {
+ /* There can be only one vif available */
+ memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN);
+ common->curaid = bss_conf->aid;
+ ath9k_hw_write_associd(sc->sc_ah);
+
+ if (bss_conf->ibss_joined) {
+ sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER;
+
+ if (!common->disable_ani) {
+ sc->sc_flags |= SC_OP_ANI_RUN;
+ ath_start_ani(common);
+ }
+
+ } else {
+ sc->sc_flags &= ~SC_OP_ANI_RUN;
+ del_timer_sync(&common->ani.timer);
+ }
+ }
+
/* Enable transmission of beacons (AP, IBSS, MESH) */
if ((changed & BSS_CHANGED_BEACON) ||
((changed & BSS_CHANGED_BEACON_ENABLED) && bss_conf->enable_beacon)) {
@@ -2308,9 +2331,9 @@
ath9k_ps_wakeup(sc);
spin_lock_bh(&sc->sc_pcu_lock);
drain_txq = ath_drain_all_txq(sc, false);
- spin_unlock_bh(&sc->sc_pcu_lock);
if (!drain_txq)
ath_reset(sc, false);
+ spin_unlock_bh(&sc->sc_pcu_lock);
ath9k_ps_restore(sc);
ieee80211_wake_queues(hw);
@@ -2334,7 +2357,7 @@
return false;
}
-int ath9k_tx_last_beacon(struct ieee80211_hw *hw)
+static int ath9k_tx_last_beacon(struct ieee80211_hw *hw)
{
struct ath_softc *sc = hw->priv;
struct ath_hw *ah = sc->sc_ah;
diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c
index ba7f36a..e7fe4d9 100644
--- a/drivers/net/wireless/ath/ath9k/rc.c
+++ b/drivers/net/wireless/ath/ath9k/rc.c
@@ -533,7 +533,7 @@
[valid_rate_count] = j;
ath_rc_priv->valid_phy_ratecnt[phy] += 1;
ath_rc_set_valid_rate_idx(ath_rc_priv, j, 1);
- hi = A_MAX(hi, j);
+ hi = max(hi, j);
}
}
}
@@ -569,7 +569,7 @@
[ath_rc_priv->valid_phy_ratecnt[phy]] = j;
ath_rc_priv->valid_phy_ratecnt[phy] += 1;
ath_rc_set_valid_rate_idx(ath_rc_priv, j, 1);
- hi = A_MAX(hi, j);
+ hi = max(hi, j);
}
}
@@ -1228,7 +1228,7 @@
ht_mcs,
ath_rc_priv->ht_cap);
}
- hi = A_MAX(hi, hthi);
+ hi = max(hi, hthi);
}
ath_rc_priv->rate_table_size = hi + 1;
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c
index 07e35e5..70dc8ec 100644
--- a/drivers/net/wireless/ath/ath9k/recv.c
+++ b/drivers/net/wireless/ath/ath9k/recv.c
@@ -14,6 +14,7 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include <linux/dma-mapping.h>
#include "ath9k.h"
#include "ar9003_mac.h"
@@ -39,6 +40,7 @@
result = true;
break;
case 1:
+ case 2:
if ((((curr_main_set == ATH_ANT_DIV_COMB_LNA2) &&
(curr_alt_set == ATH_ANT_DIV_COMB_LNA1) &&
(alt_rssi_avg >= (main_rssi_avg - 5))) ||
@@ -1075,39 +1077,39 @@
antcomb->rssi_lna1 = main_rssi_avg;
switch ((ant_conf.main_lna_conf << 4) | ant_conf.alt_lna_conf) {
- case (0x10): /* LNA2 A-B */
+ case 0x10: /* LNA2 A-B */
antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2;
antcomb->first_quick_scan_conf =
ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;
antcomb->second_quick_scan_conf = ATH_ANT_DIV_COMB_LNA1;
break;
- case (0x20): /* LNA1 A-B */
+ case 0x20: /* LNA1 A-B */
antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2;
antcomb->first_quick_scan_conf =
ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;
antcomb->second_quick_scan_conf = ATH_ANT_DIV_COMB_LNA2;
break;
- case (0x21): /* LNA1 LNA2 */
+ case 0x21: /* LNA1 LNA2 */
antcomb->main_conf = ATH_ANT_DIV_COMB_LNA2;
antcomb->first_quick_scan_conf =
ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2;
antcomb->second_quick_scan_conf =
ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;
break;
- case (0x12): /* LNA2 LNA1 */
+ case 0x12: /* LNA2 LNA1 */
antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1;
antcomb->first_quick_scan_conf =
ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2;
antcomb->second_quick_scan_conf =
ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;
break;
- case (0x13): /* LNA2 A+B */
+ case 0x13: /* LNA2 A+B */
antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;
antcomb->first_quick_scan_conf =
ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2;
antcomb->second_quick_scan_conf = ATH_ANT_DIV_COMB_LNA1;
break;
- case (0x23): /* LNA1 A+B */
+ case 0x23: /* LNA1 A+B */
antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;
antcomb->first_quick_scan_conf =
ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2;
@@ -1324,65 +1326,148 @@
/* Adjust the fast_div_bias based on main and alt lna conf */
switch ((ant_conf->main_lna_conf << 4) |
ant_conf->alt_lna_conf) {
- case (0x01): /* A-B LNA2 */
+ case 0x01: /* A-B LNA2 */
ant_conf->fast_div_bias = 0x3b;
break;
- case (0x02): /* A-B LNA1 */
+ case 0x02: /* A-B LNA1 */
ant_conf->fast_div_bias = 0x3d;
break;
- case (0x03): /* A-B A+B */
+ case 0x03: /* A-B A+B */
ant_conf->fast_div_bias = 0x1;
break;
- case (0x10): /* LNA2 A-B */
+ case 0x10: /* LNA2 A-B */
ant_conf->fast_div_bias = 0x7;
break;
- case (0x12): /* LNA2 LNA1 */
+ case 0x12: /* LNA2 LNA1 */
ant_conf->fast_div_bias = 0x2;
break;
- case (0x13): /* LNA2 A+B */
+ case 0x13: /* LNA2 A+B */
ant_conf->fast_div_bias = 0x7;
break;
- case (0x20): /* LNA1 A-B */
+ case 0x20: /* LNA1 A-B */
ant_conf->fast_div_bias = 0x6;
break;
- case (0x21): /* LNA1 LNA2 */
+ case 0x21: /* LNA1 LNA2 */
ant_conf->fast_div_bias = 0x0;
break;
- case (0x23): /* LNA1 A+B */
+ case 0x23: /* LNA1 A+B */
ant_conf->fast_div_bias = 0x6;
break;
- case (0x30): /* A+B A-B */
+ case 0x30: /* A+B A-B */
ant_conf->fast_div_bias = 0x1;
break;
- case (0x31): /* A+B LNA2 */
+ case 0x31: /* A+B LNA2 */
ant_conf->fast_div_bias = 0x3b;
break;
- case (0x32): /* A+B LNA1 */
+ case 0x32: /* A+B LNA1 */
ant_conf->fast_div_bias = 0x3d;
break;
default:
break;
}
+ } else if (ant_conf->div_group == 1) {
+ /* Adjust the fast_div_bias based on main and alt_lna_conf */
+ switch ((ant_conf->main_lna_conf << 4) |
+ ant_conf->alt_lna_conf) {
+ case 0x01: /* A-B LNA2 */
+ ant_conf->fast_div_bias = 0x1;
+ ant_conf->main_gaintb = 0;
+ ant_conf->alt_gaintb = 0;
+ break;
+ case 0x02: /* A-B LNA1 */
+ ant_conf->fast_div_bias = 0x1;
+ ant_conf->main_gaintb = 0;
+ ant_conf->alt_gaintb = 0;
+ break;
+ case 0x03: /* A-B A+B */
+ ant_conf->fast_div_bias = 0x1;
+ ant_conf->main_gaintb = 0;
+ ant_conf->alt_gaintb = 0;
+ break;
+ case 0x10: /* LNA2 A-B */
+ if (!(antcomb->scan) &&
+ (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO))
+ ant_conf->fast_div_bias = 0x3f;
+ else
+ ant_conf->fast_div_bias = 0x1;
+ ant_conf->main_gaintb = 0;
+ ant_conf->alt_gaintb = 0;
+ break;
+ case 0x12: /* LNA2 LNA1 */
+ ant_conf->fast_div_bias = 0x1;
+ ant_conf->main_gaintb = 0;
+ ant_conf->alt_gaintb = 0;
+ break;
+ case 0x13: /* LNA2 A+B */
+ if (!(antcomb->scan) &&
+ (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO))
+ ant_conf->fast_div_bias = 0x3f;
+ else
+ ant_conf->fast_div_bias = 0x1;
+ ant_conf->main_gaintb = 0;
+ ant_conf->alt_gaintb = 0;
+ break;
+ case 0x20: /* LNA1 A-B */
+ if (!(antcomb->scan) &&
+ (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO))
+ ant_conf->fast_div_bias = 0x3f;
+ else
+ ant_conf->fast_div_bias = 0x1;
+ ant_conf->main_gaintb = 0;
+ ant_conf->alt_gaintb = 0;
+ break;
+ case 0x21: /* LNA1 LNA2 */
+ ant_conf->fast_div_bias = 0x1;
+ ant_conf->main_gaintb = 0;
+ ant_conf->alt_gaintb = 0;
+ break;
+ case 0x23: /* LNA1 A+B */
+ if (!(antcomb->scan) &&
+ (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO))
+ ant_conf->fast_div_bias = 0x3f;
+ else
+ ant_conf->fast_div_bias = 0x1;
+ ant_conf->main_gaintb = 0;
+ ant_conf->alt_gaintb = 0;
+ break;
+ case 0x30: /* A+B A-B */
+ ant_conf->fast_div_bias = 0x1;
+ ant_conf->main_gaintb = 0;
+ ant_conf->alt_gaintb = 0;
+ break;
+ case 0x31: /* A+B LNA2 */
+ ant_conf->fast_div_bias = 0x1;
+ ant_conf->main_gaintb = 0;
+ ant_conf->alt_gaintb = 0;
+ break;
+ case 0x32: /* A+B LNA1 */
+ ant_conf->fast_div_bias = 0x1;
+ ant_conf->main_gaintb = 0;
+ ant_conf->alt_gaintb = 0;
+ break;
+ default:
+ break;
+ }
} else if (ant_conf->div_group == 2) {
/* Adjust the fast_div_bias based on main and alt_lna_conf */
switch ((ant_conf->main_lna_conf << 4) |
ant_conf->alt_lna_conf) {
- case (0x01): /* A-B LNA2 */
+ case 0x01: /* A-B LNA2 */
ant_conf->fast_div_bias = 0x1;
ant_conf->main_gaintb = 0;
ant_conf->alt_gaintb = 0;
break;
- case (0x02): /* A-B LNA1 */
+ case 0x02: /* A-B LNA1 */
ant_conf->fast_div_bias = 0x1;
ant_conf->main_gaintb = 0;
ant_conf->alt_gaintb = 0;
break;
- case (0x03): /* A-B A+B */
+ case 0x03: /* A-B A+B */
ant_conf->fast_div_bias = 0x1;
ant_conf->main_gaintb = 0;
ant_conf->alt_gaintb = 0;
break;
- case (0x10): /* LNA2 A-B */
+ case 0x10: /* LNA2 A-B */
if (!(antcomb->scan) &&
(alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO))
ant_conf->fast_div_bias = 0x1;
@@ -1391,12 +1476,12 @@
ant_conf->main_gaintb = 0;
ant_conf->alt_gaintb = 0;
break;
- case (0x12): /* LNA2 LNA1 */
+ case 0x12: /* LNA2 LNA1 */
ant_conf->fast_div_bias = 0x1;
ant_conf->main_gaintb = 0;
ant_conf->alt_gaintb = 0;
break;
- case (0x13): /* LNA2 A+B */
+ case 0x13: /* LNA2 A+B */
if (!(antcomb->scan) &&
(alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO))
ant_conf->fast_div_bias = 0x1;
@@ -1405,7 +1490,7 @@
ant_conf->main_gaintb = 0;
ant_conf->alt_gaintb = 0;
break;
- case (0x20): /* LNA1 A-B */
+ case 0x20: /* LNA1 A-B */
if (!(antcomb->scan) &&
(alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO))
ant_conf->fast_div_bias = 0x1;
@@ -1414,12 +1499,12 @@
ant_conf->main_gaintb = 0;
ant_conf->alt_gaintb = 0;
break;
- case (0x21): /* LNA1 LNA2 */
+ case 0x21: /* LNA1 LNA2 */
ant_conf->fast_div_bias = 0x1;
ant_conf->main_gaintb = 0;
ant_conf->alt_gaintb = 0;
break;
- case (0x23): /* LNA1 A+B */
+ case 0x23: /* LNA1 A+B */
if (!(antcomb->scan) &&
(alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO))
ant_conf->fast_div_bias = 0x1;
@@ -1428,17 +1513,17 @@
ant_conf->main_gaintb = 0;
ant_conf->alt_gaintb = 0;
break;
- case (0x30): /* A+B A-B */
+ case 0x30: /* A+B A-B */
ant_conf->fast_div_bias = 0x1;
ant_conf->main_gaintb = 0;
ant_conf->alt_gaintb = 0;
break;
- case (0x31): /* A+B LNA2 */
+ case 0x31: /* A+B LNA2 */
ant_conf->fast_div_bias = 0x1;
ant_conf->main_gaintb = 0;
ant_conf->alt_gaintb = 0;
break;
- case (0x32): /* A+B LNA1 */
+ case 0x32: /* A+B LNA1 */
ant_conf->fast_div_bias = 0x1;
ant_conf->main_gaintb = 0;
ant_conf->alt_gaintb = 0;
@@ -1446,9 +1531,7 @@
default:
break;
}
-
}
-
}
/* Antenna diversity and combining */
diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h
index c18ee99..a483388 100644
--- a/drivers/net/wireless/ath/ath9k/reg.h
+++ b/drivers/net/wireless/ath/ath9k/reg.h
@@ -788,6 +788,10 @@
#define AR_SREV_REVISION_9271_11 1
#define AR_SREV_VERSION_9300 0x1c0
#define AR_SREV_REVISION_9300_20 2 /* 2.0 and 2.1 */
+#define AR_SREV_VERSION_9330 0x200
+#define AR_SREV_REVISION_9330_10 0
+#define AR_SREV_REVISION_9330_11 1
+#define AR_SREV_REVISION_9330_12 2
#define AR_SREV_VERSION_9485 0x240
#define AR_SREV_REVISION_9485_10 0
#define AR_SREV_REVISION_9485_11 1
@@ -862,6 +866,18 @@
#define AR_SREV_9300_20_OR_LATER(_ah) \
((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9300)
+#define AR_SREV_9330(_ah) \
+ (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9330))
+#define AR_SREV_9330_10(_ah) \
+ (AR_SREV_9330((_ah)) && \
+ ((_ah)->hw_version.macRev == AR_SREV_REVISION_9330_10))
+#define AR_SREV_9330_11(_ah) \
+ (AR_SREV_9330((_ah)) && \
+ ((_ah)->hw_version.macRev == AR_SREV_REVISION_9330_11))
+#define AR_SREV_9330_12(_ah) \
+ (AR_SREV_9330((_ah)) && \
+ ((_ah)->hw_version.macRev == AR_SREV_REVISION_9330_12))
+
#define AR_SREV_9485(_ah) \
(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9485))
#define AR_SREV_9485_10(_ah) \
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index 3779b89..52dadfc 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -14,6 +14,7 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include <linux/dma-mapping.h>
#include "ath9k.h"
#include "ar9003_mac.h"
@@ -53,7 +54,7 @@
struct ath_txq *txq, struct list_head *bf_q,
struct ath_tx_status *ts, int txok, int sendbar);
static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq,
- struct list_head *head);
+ struct list_head *head, bool internal);
static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf, int len);
static void ath_tx_rc_status(struct ath_softc *sc, struct ath_buf *bf,
struct ath_tx_status *ts, int nframes, int nbad,
@@ -377,8 +378,7 @@
bf_next = bf->bf_next;
bf->bf_state.bf_type |= BUF_XRETRY;
- if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) ||
- !bf->bf_stale || bf_next != NULL)
+ if (!bf->bf_stale || bf_next != NULL)
list_move_tail(&bf->list, &bf_head);
ath_tx_rc_status(sc, bf, ts, 1, 1, 0, false);
@@ -463,20 +463,14 @@
}
}
- if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) &&
- bf_next == NULL) {
- /*
- * Make sure the last desc is reclaimed if it
- * not a holding desc.
- */
- if (!bf_last->bf_stale)
- list_move_tail(&bf->list, &bf_head);
- else
- INIT_LIST_HEAD(&bf_head);
- } else {
- BUG_ON(list_empty(bf_q));
+ /*
+ * Make sure the last desc is reclaimed if it
+ * not a holding desc.
+ */
+ if (!bf_last->bf_stale || bf_next != NULL)
list_move_tail(&bf->list, &bf_head);
- }
+ else
+ INIT_LIST_HEAD(&bf_head);
if (!txpending || (tid->state & AGGR_CLEANUP)) {
/*
@@ -572,11 +566,8 @@
rcu_read_unlock();
- if (needreset) {
- spin_unlock_bh(&sc->sc_pcu_lock);
+ if (needreset)
ath_reset(sc, false);
- spin_lock_bh(&sc->sc_pcu_lock);
- }
}
static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf,
@@ -837,7 +828,7 @@
bf->bf_state.bf_type &= ~BUF_AGGR;
ath9k_hw_clr11n_aggr(sc->sc_ah, bf->bf_desc);
ath_buf_set_rate(sc, bf, fi->framelen);
- ath_tx_txqaddbuf(sc, txq, &bf_q);
+ ath_tx_txqaddbuf(sc, txq, &bf_q, false);
continue;
}
@@ -849,7 +840,7 @@
/* anchor last desc of aggregate */
ath9k_hw_set11n_aggr_last(sc->sc_ah, bf->bf_lastbf->bf_desc);
- ath_tx_txqaddbuf(sc, txq, &bf_q);
+ ath_tx_txqaddbuf(sc, txq, &bf_q, false);
TX_STAT_INC(txq->axq_qnum, a_aggr);
} while (txq->axq_ampdu_depth < ATH_AGGR_MIN_QDEPTH &&
@@ -1085,7 +1076,6 @@
txq->txq_headidx = txq->txq_tailidx = 0;
for (i = 0; i < ATH_TXFIFO_DEPTH; i++)
INIT_LIST_HEAD(&txq->txq_fifo[i]);
- INIT_LIST_HEAD(&txq->txq_fifo_pending);
}
return &sc->tx.txq[axq_qnum];
}
@@ -1155,13 +1145,8 @@
return bf_isampdu(bf) && !(info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE);
}
-/*
- * Drain a given TX queue (could be Beacon or Data)
- *
- * This assumes output has been stopped and
- * we do not need to block ath_tx_tasklet.
- */
-void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx)
+static void ath_drain_txq_list(struct ath_softc *sc, struct ath_txq *txq,
+ struct list_head *list, bool retry_tx)
{
struct ath_buf *bf, *lastbf;
struct list_head bf_head;
@@ -1170,93 +1155,63 @@
memset(&ts, 0, sizeof(ts));
INIT_LIST_HEAD(&bf_head);
- for (;;) {
- spin_lock_bh(&txq->axq_lock);
+ while (!list_empty(list)) {
+ bf = list_first_entry(list, struct ath_buf, list);
- if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
- if (list_empty(&txq->txq_fifo[txq->txq_tailidx])) {
- txq->txq_headidx = txq->txq_tailidx = 0;
- spin_unlock_bh(&txq->axq_lock);
- break;
- } else {
- bf = list_first_entry(&txq->txq_fifo[txq->txq_tailidx],
- struct ath_buf, list);
- }
- } else {
- if (list_empty(&txq->axq_q)) {
- txq->axq_link = NULL;
- spin_unlock_bh(&txq->axq_lock);
- break;
- }
- bf = list_first_entry(&txq->axq_q, struct ath_buf,
- list);
+ if (bf->bf_stale) {
+ list_del(&bf->list);
- if (bf->bf_stale) {
- list_del(&bf->list);
- spin_unlock_bh(&txq->axq_lock);
-
- ath_tx_return_buffer(sc, bf);
- continue;
- }
+ ath_tx_return_buffer(sc, bf);
+ continue;
}
lastbf = bf->bf_lastbf;
-
- if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
- list_cut_position(&bf_head,
- &txq->txq_fifo[txq->txq_tailidx],
- &lastbf->list);
- INCR(txq->txq_tailidx, ATH_TXFIFO_DEPTH);
- } else {
- /* remove ath_buf's of the same mpdu from txq */
- list_cut_position(&bf_head, &txq->axq_q, &lastbf->list);
- }
+ list_cut_position(&bf_head, list, &lastbf->list);
txq->axq_depth--;
if (bf_is_ampdu_not_probing(bf))
txq->axq_ampdu_depth--;
- spin_unlock_bh(&txq->axq_lock);
+ spin_unlock_bh(&txq->axq_lock);
if (bf_isampdu(bf))
ath_tx_complete_aggr(sc, txq, bf, &bf_head, &ts, 0,
retry_tx);
else
ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0);
- }
-
- spin_lock_bh(&txq->axq_lock);
- txq->axq_tx_inprogress = false;
- spin_unlock_bh(&txq->axq_lock);
-
- if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
spin_lock_bh(&txq->axq_lock);
- while (!list_empty(&txq->txq_fifo_pending)) {
- bf = list_first_entry(&txq->txq_fifo_pending,
- struct ath_buf, list);
- list_cut_position(&bf_head,
- &txq->txq_fifo_pending,
- &bf->bf_lastbf->list);
- spin_unlock_bh(&txq->axq_lock);
-
- if (bf_isampdu(bf))
- ath_tx_complete_aggr(sc, txq, bf, &bf_head,
- &ts, 0, retry_tx);
- else
- ath_tx_complete_buf(sc, bf, txq, &bf_head,
- &ts, 0, 0);
- spin_lock_bh(&txq->axq_lock);
- }
- spin_unlock_bh(&txq->axq_lock);
}
+}
+
+/*
+ * Drain a given TX queue (could be Beacon or Data)
+ *
+ * This assumes output has been stopped and
+ * we do not need to block ath_tx_tasklet.
+ */
+void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx)
+{
+ spin_lock_bh(&txq->axq_lock);
+ if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
+ int idx = txq->txq_tailidx;
+
+ while (!list_empty(&txq->txq_fifo[idx])) {
+ ath_drain_txq_list(sc, txq, &txq->txq_fifo[idx],
+ retry_tx);
+
+ INCR(idx, ATH_TXFIFO_DEPTH);
+ }
+ txq->txq_tailidx = idx;
+ }
+
+ txq->axq_link = NULL;
+ txq->axq_tx_inprogress = false;
+ ath_drain_txq_list(sc, txq, &txq->axq_q, retry_tx);
/* flush any pending frames if aggregation is enabled */
- if (sc->sc_flags & SC_OP_TXAGGR) {
- if (!retry_tx) {
- spin_lock_bh(&txq->axq_lock);
- ath_txq_drain_pending_buffers(sc, txq);
- spin_unlock_bh(&txq->axq_lock);
- }
- }
+ if ((sc->sc_flags & SC_OP_TXAGGR) && !retry_tx)
+ ath_txq_drain_pending_buffers(sc, txq);
+
+ spin_unlock_bh(&txq->axq_lock);
}
bool ath_drain_all_txq(struct ath_softc *sc, bool retry_tx)
@@ -1370,11 +1325,13 @@
* assume the descriptors are already chained together by caller.
*/
static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq,
- struct list_head *head)
+ struct list_head *head, bool internal)
{
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah);
- struct ath_buf *bf;
+ struct ath_buf *bf, *bf_last;
+ bool puttxbuf = false;
+ bool edma;
/*
* Insert the frame on the outbound list and
@@ -1384,51 +1341,49 @@
if (list_empty(head))
return;
+ edma = !!(ah->caps.hw_caps & ATH9K_HW_CAP_EDMA);
bf = list_first_entry(head, struct ath_buf, list);
+ bf_last = list_entry(head->prev, struct ath_buf, list);
ath_dbg(common, ATH_DBG_QUEUE,
"qnum: %d, txq depth: %d\n", txq->axq_qnum, txq->axq_depth);
- if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
- if (txq->axq_depth >= ATH_TXFIFO_DEPTH) {
- list_splice_tail_init(head, &txq->txq_fifo_pending);
- return;
- }
- if (!list_empty(&txq->txq_fifo[txq->txq_headidx]))
- ath_dbg(common, ATH_DBG_XMIT,
- "Initializing tx fifo %d which is non-empty\n",
- txq->txq_headidx);
- INIT_LIST_HEAD(&txq->txq_fifo[txq->txq_headidx]);
- list_splice_init(head, &txq->txq_fifo[txq->txq_headidx]);
+ if (edma && list_empty(&txq->txq_fifo[txq->txq_headidx])) {
+ list_splice_tail_init(head, &txq->txq_fifo[txq->txq_headidx]);
INCR(txq->txq_headidx, ATH_TXFIFO_DEPTH);
- TX_STAT_INC(txq->axq_qnum, puttxbuf);
- ath9k_hw_puttxbuf(ah, txq->axq_qnum, bf->bf_daddr);
- ath_dbg(common, ATH_DBG_XMIT, "TXDP[%u] = %llx (%p)\n",
- txq->axq_qnum, ito64(bf->bf_daddr), bf->bf_desc);
+ puttxbuf = true;
} else {
list_splice_tail_init(head, &txq->axq_q);
- if (txq->axq_link == NULL) {
- TX_STAT_INC(txq->axq_qnum, puttxbuf);
- ath9k_hw_puttxbuf(ah, txq->axq_qnum, bf->bf_daddr);
- ath_dbg(common, ATH_DBG_XMIT, "TXDP[%u] = %llx (%p)\n",
- txq->axq_qnum, ito64(bf->bf_daddr),
- bf->bf_desc);
- } else {
- *txq->axq_link = bf->bf_daddr;
+ if (txq->axq_link) {
+ ath9k_hw_set_desc_link(ah, txq->axq_link, bf->bf_daddr);
ath_dbg(common, ATH_DBG_XMIT,
"link[%u] (%p)=%llx (%p)\n",
txq->axq_qnum, txq->axq_link,
ito64(bf->bf_daddr), bf->bf_desc);
- }
- ath9k_hw_get_desc_link(ah, bf->bf_lastbf->bf_desc,
- &txq->axq_link);
+ } else if (!edma)
+ puttxbuf = true;
+
+ txq->axq_link = bf_last->bf_desc;
+ }
+
+ if (puttxbuf) {
+ TX_STAT_INC(txq->axq_qnum, puttxbuf);
+ ath9k_hw_puttxbuf(ah, txq->axq_qnum, bf->bf_daddr);
+ ath_dbg(common, ATH_DBG_XMIT, "TXDP[%u] = %llx (%p)\n",
+ txq->axq_qnum, ito64(bf->bf_daddr), bf->bf_desc);
+ }
+
+ if (!edma) {
TX_STAT_INC(txq->axq_qnum, txstart);
ath9k_hw_txstart(ah, txq->axq_qnum);
}
- txq->axq_depth++;
- if (bf_is_ampdu_not_probing(bf))
- txq->axq_ampdu_depth++;
+
+ if (!internal) {
+ txq->axq_depth++;
+ if (bf_is_ampdu_not_probing(bf))
+ txq->axq_ampdu_depth++;
+ }
}
static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid,
@@ -1470,7 +1425,7 @@
TX_STAT_INC(txctl->txq->axq_qnum, a_queued_hw);
bf->bf_lastbf = bf;
ath_buf_set_rate(sc, bf, fi->framelen);
- ath_tx_txqaddbuf(sc, txctl->txq, &bf_head);
+ ath_tx_txqaddbuf(sc, txctl->txq, &bf_head, false);
}
static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq,
@@ -1490,7 +1445,7 @@
bf->bf_lastbf = bf;
fi = get_frame_info(bf->bf_mpdu);
ath_buf_set_rate(sc, bf, fi->framelen);
- ath_tx_txqaddbuf(sc, txq, bf_head);
+ ath_tx_txqaddbuf(sc, txq, bf_head, false);
TX_STAT_INC(txq->axq_qnum, queued);
}
@@ -2077,6 +2032,38 @@
tx_info->status.rates[tx_rateindex].count = ts->ts_longretry + 1;
}
+static void ath_tx_process_buffer(struct ath_softc *sc, struct ath_txq *txq,
+ struct ath_tx_status *ts, struct ath_buf *bf,
+ struct list_head *bf_head)
+{
+ int txok;
+
+ txq->axq_depth--;
+ txok = !(ts->ts_status & ATH9K_TXERR_MASK);
+ txq->axq_tx_inprogress = false;
+ if (bf_is_ampdu_not_probing(bf))
+ txq->axq_ampdu_depth--;
+
+ spin_unlock_bh(&txq->axq_lock);
+
+ if (!bf_isampdu(bf)) {
+ /*
+ * This frame is sent out as a single frame.
+ * Use hardware retry status for this frame.
+ */
+ if (ts->ts_status & ATH9K_TXERR_XRETRY)
+ bf->bf_state.bf_type |= BUF_XRETRY;
+ ath_tx_rc_status(sc, bf, ts, 1, txok ? 0 : 1, txok, true);
+ ath_tx_complete_buf(sc, bf, txq, bf_head, ts, txok, 0);
+ } else
+ ath_tx_complete_aggr(sc, txq, bf, bf_head, ts, txok, true);
+
+ spin_lock_bh(&txq->axq_lock);
+
+ if (sc->sc_flags & SC_OP_TXAGGR)
+ ath_txq_schedule(sc, txq);
+}
+
static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
{
struct ath_hw *ah = sc->sc_ah;
@@ -2085,20 +2072,18 @@
struct list_head bf_head;
struct ath_desc *ds;
struct ath_tx_status ts;
- int txok;
int status;
ath_dbg(common, ATH_DBG_QUEUE, "tx queue %d (%x), link %p\n",
txq->axq_qnum, ath9k_hw_gettxbuf(sc->sc_ah, txq->axq_qnum),
txq->axq_link);
+ spin_lock_bh(&txq->axq_lock);
for (;;) {
- spin_lock_bh(&txq->axq_lock);
if (list_empty(&txq->axq_q)) {
txq->axq_link = NULL;
if (sc->sc_flags & SC_OP_TXAGGR)
ath_txq_schedule(sc, txq);
- spin_unlock_bh(&txq->axq_lock);
break;
}
bf = list_first_entry(&txq->axq_q, struct ath_buf, list);
@@ -2114,13 +2099,11 @@
bf_held = NULL;
if (bf->bf_stale) {
bf_held = bf;
- if (list_is_last(&bf_held->list, &txq->axq_q)) {
- spin_unlock_bh(&txq->axq_lock);
+ if (list_is_last(&bf_held->list, &txq->axq_q))
break;
- } else {
- bf = list_entry(bf_held->list.next,
- struct ath_buf, list);
- }
+
+ bf = list_entry(bf_held->list.next, struct ath_buf,
+ list);
}
lastbf = bf->bf_lastbf;
@@ -2128,10 +2111,9 @@
memset(&ts, 0, sizeof(ts));
status = ath9k_hw_txprocdesc(ah, ds, &ts);
- if (status == -EINPROGRESS) {
- spin_unlock_bh(&txq->axq_lock);
+ if (status == -EINPROGRESS)
break;
- }
+
TX_STAT_INC(txq->axq_qnum, txprocdesc);
/*
@@ -2145,42 +2127,14 @@
list_cut_position(&bf_head,
&txq->axq_q, lastbf->list.prev);
- txq->axq_depth--;
- txok = !(ts.ts_status & ATH9K_TXERR_MASK);
- txq->axq_tx_inprogress = false;
- if (bf_held)
+ if (bf_held) {
list_del(&bf_held->list);
-
- if (bf_is_ampdu_not_probing(bf))
- txq->axq_ampdu_depth--;
-
- spin_unlock_bh(&txq->axq_lock);
-
- if (bf_held)
ath_tx_return_buffer(sc, bf_held);
-
- if (!bf_isampdu(bf)) {
- /*
- * This frame is sent out as a single frame.
- * Use hardware retry status for this frame.
- */
- if (ts.ts_status & ATH9K_TXERR_XRETRY)
- bf->bf_state.bf_type |= BUF_XRETRY;
- ath_tx_rc_status(sc, bf, &ts, 1, txok ? 0 : 1, txok, true);
}
- if (bf_isampdu(bf))
- ath_tx_complete_aggr(sc, txq, bf, &bf_head, &ts, txok,
- true);
- else
- ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, txok, 0);
-
- spin_lock_bh(&txq->axq_lock);
-
- if (sc->sc_flags & SC_OP_TXAGGR)
- ath_txq_schedule(sc, txq);
- spin_unlock_bh(&txq->axq_lock);
+ ath_tx_process_buffer(sc, txq, &ts, bf, &bf_head);
}
+ spin_unlock_bh(&txq->axq_lock);
}
static void ath_tx_complete_poll_work(struct work_struct *work)
@@ -2213,7 +2167,9 @@
if (needreset) {
ath_dbg(ath9k_hw_common(sc->sc_ah), ATH_DBG_RESET,
"tx hung, resetting the chip\n");
+ spin_lock_bh(&sc->sc_pcu_lock);
ath_reset(sc, true);
+ spin_unlock_bh(&sc->sc_pcu_lock);
}
ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work,
@@ -2237,17 +2193,16 @@
void ath_tx_edma_tasklet(struct ath_softc *sc)
{
- struct ath_tx_status txs;
+ struct ath_tx_status ts;
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
struct ath_hw *ah = sc->sc_ah;
struct ath_txq *txq;
struct ath_buf *bf, *lastbf;
struct list_head bf_head;
int status;
- int txok;
for (;;) {
- status = ath9k_hw_txprocdesc(ah, NULL, (void *)&txs);
+ status = ath9k_hw_txprocdesc(ah, NULL, (void *)&ts);
if (status == -EINPROGRESS)
break;
if (status == -EIO) {
@@ -2257,12 +2212,13 @@
}
/* Skip beacon completions */
- if (txs.qid == sc->beacon.beaconq)
+ if (ts.qid == sc->beacon.beaconq)
continue;
- txq = &sc->tx.txq[txs.qid];
+ txq = &sc->tx.txq[ts.qid];
spin_lock_bh(&txq->axq_lock);
+
if (list_empty(&txq->txq_fifo[txq->txq_tailidx])) {
spin_unlock_bh(&txq->axq_lock);
return;
@@ -2275,41 +2231,21 @@
INIT_LIST_HEAD(&bf_head);
list_cut_position(&bf_head, &txq->txq_fifo[txq->txq_tailidx],
&lastbf->list);
- INCR(txq->txq_tailidx, ATH_TXFIFO_DEPTH);
- txq->axq_depth--;
- txq->axq_tx_inprogress = false;
- if (bf_is_ampdu_not_probing(bf))
- txq->axq_ampdu_depth--;
- spin_unlock_bh(&txq->axq_lock);
- txok = !(txs.ts_status & ATH9K_TXERR_MASK);
+ if (list_empty(&txq->txq_fifo[txq->txq_tailidx])) {
+ INCR(txq->txq_tailidx, ATH_TXFIFO_DEPTH);
- if (!bf_isampdu(bf)) {
- if (txs.ts_status & ATH9K_TXERR_XRETRY)
- bf->bf_state.bf_type |= BUF_XRETRY;
- ath_tx_rc_status(sc, bf, &txs, 1, txok ? 0 : 1, txok, true);
+ if (!list_empty(&txq->axq_q)) {
+ struct list_head bf_q;
+
+ INIT_LIST_HEAD(&bf_q);
+ txq->axq_link = NULL;
+ list_splice_tail_init(&txq->axq_q, &bf_q);
+ ath_tx_txqaddbuf(sc, txq, &bf_q, true);
+ }
}
- if (bf_isampdu(bf))
- ath_tx_complete_aggr(sc, txq, bf, &bf_head, &txs,
- txok, true);
- else
- ath_tx_complete_buf(sc, bf, txq, &bf_head,
- &txs, txok, 0);
-
- spin_lock_bh(&txq->axq_lock);
-
- if (!list_empty(&txq->txq_fifo_pending)) {
- INIT_LIST_HEAD(&bf_head);
- bf = list_first_entry(&txq->txq_fifo_pending,
- struct ath_buf, list);
- list_cut_position(&bf_head,
- &txq->txq_fifo_pending,
- &bf->bf_lastbf->list);
- ath_tx_txqaddbuf(sc, txq, &bf_head);
- } else if (sc->sc_flags & SC_OP_TXAGGR)
- ath_txq_schedule(sc, txq);
-
+ ath_tx_process_buffer(sc, txq, &ts, bf, &bf_head);
spin_unlock_bh(&txq->axq_lock);
}
}
diff --git a/drivers/net/wireless/ath/carl9170/rx.c b/drivers/net/wireless/ath/carl9170/rx.c
index ec21ea9..dc99030 100644
--- a/drivers/net/wireless/ath/carl9170/rx.c
+++ b/drivers/net/wireless/ath/carl9170/rx.c
@@ -472,7 +472,7 @@
u8 *qc = ieee80211_get_qos_ctl(hdr);
reserved += NET_IP_ALIGN;
- if (*qc & IEEE80211_QOS_CONTROL_A_MSDU_PRESENT)
+ if (*qc & IEEE80211_QOS_CTL_A_MSDU_PRESENT)
reserved += NET_IP_ALIGN;
}
diff --git a/drivers/net/wireless/atmel.c b/drivers/net/wireless/atmel.c
index 39a11e8..7e45ca2 100644
--- a/drivers/net/wireless/atmel.c
+++ b/drivers/net/wireless/atmel.c
@@ -40,6 +40,7 @@
******************************************************************************/
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/ptrace.h>
diff --git a/drivers/net/wireless/b43/Kconfig b/drivers/net/wireless/b43/Kconfig
index 480595f..d5add69 100644
--- a/drivers/net/wireless/b43/Kconfig
+++ b/drivers/net/wireless/b43/Kconfig
@@ -26,6 +26,16 @@
This driver can be built as a module (recommended) that will be called "b43".
If unsure, say M.
+config B43_BCMA
+ bool "Support for BCMA bus"
+ depends on B43 && BCMA && BROKEN
+ default y
+
+config B43_SSB
+ bool
+ depends on B43 && SSB
+ default y
+
# Auto-select SSB PCI-HOST support, if possible
config B43_PCI_AUTOSELECT
bool
@@ -107,6 +117,14 @@
and embedded devices. It supports 802.11a/g
(802.11a support is optional, and currently disabled).
+config B43_PHY_HT
+ bool "Support for HT-PHY devices (BROKEN)"
+ depends on B43 && BROKEN
+ ---help---
+ Support for the HT-PHY.
+
+ Say N, this is BROKEN and crashes driver.
+
# This config option automatically enables b43 LEDS support,
# if it's possible.
config B43_LEDS
diff --git a/drivers/net/wireless/b43/Makefile b/drivers/net/wireless/b43/Makefile
index cef334a..1b25604 100644
--- a/drivers/net/wireless/b43/Makefile
+++ b/drivers/net/wireless/b43/Makefile
@@ -1,4 +1,5 @@
b43-y += main.o
+b43-y += bus.o
b43-y += tables.o
b43-$(CONFIG_B43_PHY_N) += tables_nphy.o
b43-$(CONFIG_B43_PHY_N) += radio_2055.o
@@ -9,6 +10,9 @@
b43-$(CONFIG_B43_PHY_N) += phy_n.o
b43-$(CONFIG_B43_PHY_LP) += phy_lp.o
b43-$(CONFIG_B43_PHY_LP) += tables_lpphy.o
+b43-$(CONFIG_B43_PHY_HT) += phy_ht.o
+b43-$(CONFIG_B43_PHY_HT) += tables_phy_ht.o
+b43-$(CONFIG_B43_PHY_HT) += radio_2059.o
b43-y += sysfs.o
b43-y += xmit.o
b43-y += lo.o
diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h
index 25a78cf..666515e 100644
--- a/drivers/net/wireless/b43/b43.h
+++ b/drivers/net/wireless/b43/b43.h
@@ -5,12 +5,14 @@
#include <linux/spinlock.h>
#include <linux/interrupt.h>
#include <linux/hw_random.h>
+#include <linux/bcma/bcma.h>
#include <linux/ssb/ssb.h>
#include <net/mac80211.h>
#include "debugfs.h"
#include "leds.h"
#include "rfkill.h"
+#include "bus.h"
#include "lo.h"
#include "phy_common.h"
@@ -90,6 +92,8 @@
#define B43_MMIO_PIO11_BASE4 0x300
#define B43_MMIO_PIO11_BASE5 0x340
+#define B43_MMIO_RADIO24_CONTROL 0x3D8 /* core rev >= 24 only */
+#define B43_MMIO_RADIO24_DATA 0x3DA /* core rev >= 24 only */
#define B43_MMIO_PHY_VER 0x3E0
#define B43_MMIO_PHY_RADIO 0x3E2
#define B43_MMIO_PHY0 0x3E6
@@ -361,6 +365,10 @@
#define B43_PHYTYPE_G 0x02
#define B43_PHYTYPE_N 0x04
#define B43_PHYTYPE_LP 0x05
+#define B43_PHYTYPE_SSLPN 0x06
+#define B43_PHYTYPE_HT 0x07
+#define B43_PHYTYPE_LCN 0x08
+#define B43_PHYTYPE_LCNXN 0x09
/* PHYRegisters */
#define B43_PHY_ILT_A_CTRL 0x0072
@@ -414,6 +422,17 @@
#define B43_MACCMD_CCA 0x00000008 /* Clear channel assessment */
#define B43_MACCMD_BGNOISE 0x00000010 /* Background noise */
+/* BCMA 802.11 core specific IO Control (BCMA_IOCTL) flags */
+#define B43_BCMA_IOCTL_PHY_CLKEN 0x00000004 /* PHY Clock Enable */
+#define B43_BCMA_IOCTL_PHY_RESET 0x00000008 /* PHY Reset */
+#define B43_BCMA_IOCTL_MACPHYCLKEN 0x00000010 /* MAC PHY Clock Control Enable */
+#define B43_BCMA_IOCTL_PLLREFSEL 0x00000020 /* PLL Frequency Reference Select */
+#define B43_BCMA_IOCTL_PHY_BW 0x000000C0 /* PHY band width and clock speed mask (N-PHY+ only?) */
+#define B43_BCMA_IOCTL_PHY_BW_10MHZ 0x00000000 /* 10 MHz bandwidth, 40 MHz PHY */
+#define B43_BCMA_IOCTL_PHY_BW_20MHZ 0x00000040 /* 20 MHz bandwidth, 80 MHz PHY */
+#define B43_BCMA_IOCTL_PHY_BW_40MHZ 0x00000080 /* 40 MHz bandwidth, 160 MHz PHY */
+#define B43_BCMA_IOCTL_GMODE 0x00002000 /* G Mode Enable */
+
/* 802.11 core specific TM State Low (SSB_TMSLOW) flags */
#define B43_TMSLOW_GMODE 0x20000000 /* G Mode Enable */
#define B43_TMSLOW_PHY_BANDWIDTH 0x00C00000 /* PHY band width and clock speed mask (N-PHY only) */
@@ -707,7 +726,8 @@
/* Data structure for one wireless device (802.11 core) */
struct b43_wldev {
- struct ssb_device *sdev;
+ struct ssb_device *sdev; /* TODO: remove when b43_bus_dev is ready */
+ struct b43_bus_dev *dev;
struct b43_wl *wl;
/* The device initialization status.
@@ -879,36 +899,59 @@
return wl->hw->conf.channel->band;
}
+static inline int b43_bus_may_powerdown(struct b43_wldev *wldev)
+{
+ return wldev->dev->bus_may_powerdown(wldev->dev);
+}
+static inline int b43_bus_powerup(struct b43_wldev *wldev, bool dynamic_pctl)
+{
+ return wldev->dev->bus_powerup(wldev->dev, dynamic_pctl);
+}
+static inline int b43_device_is_enabled(struct b43_wldev *wldev)
+{
+ return wldev->dev->device_is_enabled(wldev->dev);
+}
+static inline void b43_device_enable(struct b43_wldev *wldev,
+ u32 core_specific_flags)
+{
+ wldev->dev->device_enable(wldev->dev, core_specific_flags);
+}
+static inline void b43_device_disable(struct b43_wldev *wldev,
+ u32 core_specific_flags)
+{
+ wldev->dev->device_disable(wldev->dev, core_specific_flags);
+}
+
static inline u16 b43_read16(struct b43_wldev *dev, u16 offset)
{
- return ssb_read16(dev->sdev, offset);
+ return dev->dev->read16(dev->dev, offset);
}
static inline void b43_write16(struct b43_wldev *dev, u16 offset, u16 value)
{
- ssb_write16(dev->sdev, offset, value);
+ dev->dev->write16(dev->dev, offset, value);
}
static inline u32 b43_read32(struct b43_wldev *dev, u16 offset)
{
- return ssb_read32(dev->sdev, offset);
+ return dev->dev->read32(dev->dev, offset);
}
static inline void b43_write32(struct b43_wldev *dev, u16 offset, u32 value)
{
- ssb_write32(dev->sdev, offset, value);
+ dev->dev->write32(dev->dev, offset, value);
}
static inline void b43_block_read(struct b43_wldev *dev, void *buffer,
size_t count, u16 offset, u8 reg_width)
{
- ssb_block_read(dev->sdev, buffer, count, offset, reg_width);
+ dev->dev->block_read(dev->dev, buffer, count, offset, reg_width);
}
static inline void b43_block_write(struct b43_wldev *dev, const void *buffer,
size_t count, u16 offset, u8 reg_width)
{
- ssb_block_write(dev->sdev, buffer, count, offset, reg_width);
+ dev->dev->block_write(dev->dev, buffer, count, offset, reg_width);
}
static inline bool b43_using_pio_transfers(struct b43_wldev *dev)
diff --git a/drivers/net/wireless/b43/bus.c b/drivers/net/wireless/b43/bus.c
new file mode 100644
index 0000000..4200713
--- /dev/null
+++ b/drivers/net/wireless/b43/bus.c
@@ -0,0 +1,127 @@
+/*
+
+ Broadcom B43 wireless driver
+ Bus abstraction layer
+
+ 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; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+
+*/
+
+#include "b43.h"
+#include "bus.h"
+
+
+/* SSB */
+#ifdef CONFIG_B43_SSB
+static inline int b43_bus_ssb_bus_may_powerdown(struct b43_bus_dev *dev)
+{
+ return ssb_bus_may_powerdown(dev->sdev->bus);
+}
+static inline int b43_bus_ssb_bus_powerup(struct b43_bus_dev *dev,
+ bool dynamic_pctl)
+{
+ return ssb_bus_powerup(dev->sdev->bus, dynamic_pctl);
+}
+static inline int b43_bus_ssb_device_is_enabled(struct b43_bus_dev *dev)
+{
+ return ssb_device_is_enabled(dev->sdev);
+}
+static inline void b43_bus_ssb_device_enable(struct b43_bus_dev *dev,
+ u32 core_specific_flags)
+{
+ ssb_device_enable(dev->sdev, core_specific_flags);
+}
+static inline void b43_bus_ssb_device_disable(struct b43_bus_dev *dev,
+ u32 core_specific_flags)
+{
+ ssb_device_disable(dev->sdev, core_specific_flags);
+}
+
+static inline u16 b43_bus_ssb_read16(struct b43_bus_dev *dev, u16 offset)
+{
+ return ssb_read16(dev->sdev, offset);
+}
+static inline u32 b43_bus_ssb_read32(struct b43_bus_dev *dev, u16 offset)
+{
+ return ssb_read32(dev->sdev, offset);
+}
+static inline
+void b43_bus_ssb_write16(struct b43_bus_dev *dev, u16 offset, u16 value)
+{
+ ssb_write16(dev->sdev, offset, value);
+}
+static inline
+void b43_bus_ssb_write32(struct b43_bus_dev *dev, u16 offset, u32 value)
+{
+ ssb_write32(dev->sdev, offset, value);
+}
+static inline
+void b43_bus_ssb_block_read(struct b43_bus_dev *dev, void *buffer,
+ size_t count, u16 offset, u8 reg_width)
+{
+ ssb_block_read(dev->sdev, buffer, count, offset, reg_width);
+}
+static inline
+void b43_bus_ssb_block_write(struct b43_bus_dev *dev, const void *buffer,
+ size_t count, u16 offset, u8 reg_width)
+{
+ ssb_block_write(dev->sdev, buffer, count, offset, reg_width);
+}
+
+struct b43_bus_dev *b43_bus_dev_ssb_init(struct ssb_device *sdev)
+{
+ struct b43_bus_dev *dev;
+
+ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+ if (!dev)
+ return NULL;
+
+ dev->bus_type = B43_BUS_SSB;
+ dev->sdev = sdev;
+
+ dev->bus_may_powerdown = b43_bus_ssb_bus_may_powerdown;
+ dev->bus_powerup = b43_bus_ssb_bus_powerup;
+ dev->device_is_enabled = b43_bus_ssb_device_is_enabled;
+ dev->device_enable = b43_bus_ssb_device_enable;
+ dev->device_disable = b43_bus_ssb_device_disable;
+
+ dev->read16 = b43_bus_ssb_read16;
+ dev->read32 = b43_bus_ssb_read32;
+ dev->write16 = b43_bus_ssb_write16;
+ dev->write32 = b43_bus_ssb_write32;
+ dev->block_read = b43_bus_ssb_block_read;
+ dev->block_write = b43_bus_ssb_block_write;
+
+ dev->dev = sdev->dev;
+ dev->dma_dev = sdev->dma_dev;
+ dev->irq = sdev->irq;
+
+ dev->board_vendor = sdev->bus->boardinfo.vendor;
+ dev->board_type = sdev->bus->boardinfo.type;
+ dev->board_rev = sdev->bus->boardinfo.rev;
+
+ dev->chip_id = sdev->bus->chip_id;
+ dev->chip_rev = sdev->bus->chip_rev;
+ dev->chip_pkg = sdev->bus->chip_package;
+
+ dev->bus_sprom = &sdev->bus->sprom;
+
+ dev->core_id = sdev->id.coreid;
+ dev->core_rev = sdev->id.revision;
+
+ return dev;
+}
+#endif /* CONFIG_B43_SSB */
diff --git a/drivers/net/wireless/b43/bus.h b/drivers/net/wireless/b43/bus.h
new file mode 100644
index 0000000..79a5ab4
--- /dev/null
+++ b/drivers/net/wireless/b43/bus.h
@@ -0,0 +1,62 @@
+#ifndef B43_BUS_H_
+#define B43_BUS_H_
+
+enum b43_bus_type {
+ B43_BUS_SSB,
+};
+
+struct b43_bus_dev {
+ enum b43_bus_type bus_type;
+ union {
+ struct ssb_device *sdev;
+ };
+
+ int (*bus_may_powerdown)(struct b43_bus_dev *dev);
+ int (*bus_powerup)(struct b43_bus_dev *dev, bool dynamic_pctl);
+ int (*device_is_enabled)(struct b43_bus_dev *dev);
+ void (*device_enable)(struct b43_bus_dev *dev,
+ u32 core_specific_flags);
+ void (*device_disable)(struct b43_bus_dev *dev,
+ u32 core_specific_flags);
+
+ u16 (*read16)(struct b43_bus_dev *dev, u16 offset);
+ u32 (*read32)(struct b43_bus_dev *dev, u16 offset);
+ void (*write16)(struct b43_bus_dev *dev, u16 offset, u16 value);
+ void (*write32)(struct b43_bus_dev *dev, u16 offset, u32 value);
+ void (*block_read)(struct b43_bus_dev *dev, void *buffer,
+ size_t count, u16 offset, u8 reg_width);
+ void (*block_write)(struct b43_bus_dev *dev, const void *buffer,
+ size_t count, u16 offset, u8 reg_width);
+
+ struct device *dev;
+ struct device *dma_dev;
+ unsigned int irq;
+
+ u16 board_vendor;
+ u16 board_type;
+ u16 board_rev;
+
+ u16 chip_id;
+ u8 chip_rev;
+ u8 chip_pkg;
+
+ struct ssb_sprom *bus_sprom;
+
+ u16 core_id;
+ u8 core_rev;
+};
+
+static inline bool b43_bus_host_is_pcmcia(struct b43_bus_dev *dev)
+{
+ return (dev->bus_type == B43_BUS_SSB &&
+ dev->sdev->bus->bustype == SSB_BUSTYPE_PCMCIA);
+}
+static inline bool b43_bus_host_is_sdio(struct b43_bus_dev *dev)
+{
+ return (dev->bus_type == B43_BUS_SSB &&
+ dev->sdev->bus->bustype == SSB_BUSTYPE_SDIO);
+}
+
+struct b43_bus_dev *b43_bus_dev_ssb_init(struct ssb_device *sdev);
+
+#endif /* B43_BUS_H_ */
diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c
index 47d44bc..d02cf83 100644
--- a/drivers/net/wireless/b43/dma.c
+++ b/drivers/net/wireless/b43/dma.c
@@ -333,10 +333,10 @@
dma_addr_t dmaaddr;
if (tx) {
- dmaaddr = dma_map_single(ring->dev->sdev->dma_dev,
+ dmaaddr = dma_map_single(ring->dev->dev->dma_dev,
buf, len, DMA_TO_DEVICE);
} else {
- dmaaddr = dma_map_single(ring->dev->sdev->dma_dev,
+ dmaaddr = dma_map_single(ring->dev->dev->dma_dev,
buf, len, DMA_FROM_DEVICE);
}
@@ -348,10 +348,10 @@
dma_addr_t addr, size_t len, int tx)
{
if (tx) {
- dma_unmap_single(ring->dev->sdev->dma_dev,
+ dma_unmap_single(ring->dev->dev->dma_dev,
addr, len, DMA_TO_DEVICE);
} else {
- dma_unmap_single(ring->dev->sdev->dma_dev,
+ dma_unmap_single(ring->dev->dev->dma_dev,
addr, len, DMA_FROM_DEVICE);
}
}
@@ -361,7 +361,7 @@
dma_addr_t addr, size_t len)
{
B43_WARN_ON(ring->tx);
- dma_sync_single_for_cpu(ring->dev->sdev->dma_dev,
+ dma_sync_single_for_cpu(ring->dev->dev->dma_dev,
addr, len, DMA_FROM_DEVICE);
}
@@ -370,7 +370,7 @@
dma_addr_t addr, size_t len)
{
B43_WARN_ON(ring->tx);
- dma_sync_single_for_device(ring->dev->sdev->dma_dev,
+ dma_sync_single_for_device(ring->dev->dev->dma_dev,
addr, len, DMA_FROM_DEVICE);
}
@@ -401,7 +401,7 @@
*/
if (ring->type == B43_DMA_64BIT)
flags |= GFP_DMA;
- ring->descbase = dma_alloc_coherent(ring->dev->sdev->dma_dev,
+ ring->descbase = dma_alloc_coherent(ring->dev->dev->dma_dev,
B43_DMA_RINGMEMSIZE,
&(ring->dmabase), flags);
if (!ring->descbase) {
@@ -415,7 +415,7 @@
static void free_ringmemory(struct b43_dmaring *ring)
{
- dma_free_coherent(ring->dev->sdev->dma_dev, B43_DMA_RINGMEMSIZE,
+ dma_free_coherent(ring->dev->dev->dma_dev, B43_DMA_RINGMEMSIZE,
ring->descbase, ring->dmabase);
}
@@ -523,7 +523,7 @@
dma_addr_t addr,
size_t buffersize, bool dma_to_device)
{
- if (unlikely(dma_mapping_error(ring->dev->sdev->dma_dev, addr)))
+ if (unlikely(dma_mapping_error(ring->dev->dev->dma_dev, addr)))
return 1;
switch (ring->type) {
@@ -757,14 +757,14 @@
static void free_all_descbuffers(struct b43_dmaring *ring)
{
- struct b43_dmadesc_generic *desc;
struct b43_dmadesc_meta *meta;
int i;
if (!ring->used_slots)
return;
for (i = 0; i < ring->nr_slots; i++) {
- desc = ring->ops->idx2desc(ring, i, &meta);
+ /* get meta - ignore returned value */
+ ring->ops->idx2desc(ring, i, &meta);
if (!meta->skb || b43_dma_ptr_is_poisoned(meta->skb)) {
B43_WARN_ON(!ring->tx);
@@ -869,7 +869,7 @@
goto err_kfree_meta;
/* test for ability to dma to txhdr_cache */
- dma_test = dma_map_single(dev->sdev->dma_dev,
+ dma_test = dma_map_single(dev->dev->dma_dev,
ring->txhdr_cache,
b43_txhdr_size(dev),
DMA_TO_DEVICE);
@@ -884,7 +884,7 @@
if (!ring->txhdr_cache)
goto err_kfree_meta;
- dma_test = dma_map_single(dev->sdev->dma_dev,
+ dma_test = dma_map_single(dev->dev->dma_dev,
ring->txhdr_cache,
b43_txhdr_size(dev),
DMA_TO_DEVICE);
@@ -898,7 +898,7 @@
}
}
- dma_unmap_single(dev->sdev->dma_dev,
+ dma_unmap_single(dev->dev->dma_dev,
dma_test, b43_txhdr_size(dev),
DMA_TO_DEVICE);
}
@@ -1013,9 +1013,9 @@
/* Try to set the DMA mask. If it fails, try falling back to a
* lower mask, as we can always also support a lower one. */
while (1) {
- err = dma_set_mask(dev->sdev->dma_dev, mask);
+ err = dma_set_mask(dev->dev->dma_dev, mask);
if (!err) {
- err = dma_set_coherent_mask(dev->sdev->dma_dev, mask);
+ err = dma_set_coherent_mask(dev->dev->dma_dev, mask);
if (!err)
break;
}
@@ -1085,7 +1085,7 @@
goto err_destroy_mcast;
/* No support for the TX status DMA ring. */
- B43_WARN_ON(dev->sdev->id.revision < 5);
+ B43_WARN_ON(dev->dev->core_rev < 5);
b43dbg(dev->wl, "%u-bit DMA initialized\n",
(unsigned int)type);
@@ -1388,7 +1388,6 @@
{
const struct b43_dma_ops *ops;
struct b43_dmaring *ring;
- struct b43_dmadesc_generic *desc;
struct b43_dmadesc_meta *meta;
int slot, firstused;
bool frame_succeed;
@@ -1416,7 +1415,8 @@
ops = ring->ops;
while (1) {
B43_WARN_ON(slot < 0 || slot >= ring->nr_slots);
- desc = ops->idx2desc(ring, slot, &meta);
+ /* get meta - ignore returned value */
+ ops->idx2desc(ring, slot, &meta);
if (b43_dma_ptr_is_poisoned(meta->skb)) {
b43dbg(dev->wl, "Poisoned TX slot %d (first=%d) "
diff --git a/drivers/net/wireless/b43/leds.c b/drivers/net/wireless/b43/leds.c
index 0cafafe..b56ed41 100644
--- a/drivers/net/wireless/b43/leds.c
+++ b/drivers/net/wireless/b43/leds.c
@@ -138,7 +138,7 @@
led->led_dev.default_trigger = default_trigger;
led->led_dev.brightness_set = b43_led_brightness_set;
- err = led_classdev_register(dev->sdev->dev, &led->led_dev);
+ err = led_classdev_register(dev->dev->dev, &led->led_dev);
if (err) {
b43warn(dev->wl, "LEDs: Failed to register %s\n", name);
led->wl = NULL;
@@ -215,13 +215,12 @@
enum b43_led_behaviour *behaviour,
bool *activelow)
{
- struct ssb_bus *bus = dev->sdev->bus;
u8 sprom[4];
- sprom[0] = bus->sprom.gpio0;
- sprom[1] = bus->sprom.gpio1;
- sprom[2] = bus->sprom.gpio2;
- sprom[3] = bus->sprom.gpio3;
+ sprom[0] = dev->dev->bus_sprom->gpio0;
+ sprom[1] = dev->dev->bus_sprom->gpio1;
+ sprom[2] = dev->dev->bus_sprom->gpio2;
+ sprom[3] = dev->dev->bus_sprom->gpio3;
if (sprom[led_index] == 0xFF) {
/* There is no LED information in the SPROM
@@ -231,12 +230,12 @@
case 0:
*behaviour = B43_LED_ACTIVITY;
*activelow = 1;
- if (bus->boardinfo.vendor == PCI_VENDOR_ID_COMPAQ)
+ if (dev->dev->board_vendor == PCI_VENDOR_ID_COMPAQ)
*behaviour = B43_LED_RADIO_ALL;
break;
case 1:
*behaviour = B43_LED_RADIO_B;
- if (bus->boardinfo.vendor == PCI_VENDOR_ID_ASUSTEK)
+ if (dev->dev->board_vendor == PCI_VENDOR_ID_ASUSTEK)
*behaviour = B43_LED_ASSOC;
break;
case 2:
diff --git a/drivers/net/wireless/b43/lo.c b/drivers/net/wireless/b43/lo.c
index 2ef7d4b..a3dc8bb 100644
--- a/drivers/net/wireless/b43/lo.c
+++ b/drivers/net/wireless/b43/lo.c
@@ -98,7 +98,7 @@
rfover |= pga;
rfover |= lna;
rfover |= trsw_rx;
- if ((dev->sdev->bus->sprom.boardflags_lo & B43_BFL_EXTLNA)
+ if ((dev->dev->bus_sprom->boardflags_lo & B43_BFL_EXTLNA)
&& phy->rev > 6)
rfover |= B43_PHY_RFOVERVAL_EXTLNA;
@@ -301,14 +301,12 @@
max_rx_gain = 0;
if (has_loopback_gain(phy)) {
- int trsw_rx = 0;
int trsw_rx_gain;
if (use_trsw_rx) {
trsw_rx_gain = gphy->trsw_rx_gain / 2;
if (max_rx_gain >= trsw_rx_gain) {
trsw_rx_gain = max_rx_gain - trsw_rx_gain;
- trsw_rx = 0x20;
}
} else
trsw_rx_gain = max_rx_gain;
@@ -387,7 +385,7 @@
static void lo_measure_setup(struct b43_wldev *dev,
struct lo_g_saved_values *sav)
{
- struct ssb_sprom *sprom = &dev->sdev->bus->sprom;
+ struct ssb_sprom *sprom = dev->dev->bus_sprom;
struct b43_phy *phy = &dev->phy;
struct b43_phy_g *gphy = phy->g;
struct b43_txpower_lo_control *lo = gphy->lo_control;
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
index eb41596..e9a01e3 100644
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -113,6 +113,17 @@
module_param_named(pio, b43_modparam_pio, int, 0644);
MODULE_PARM_DESC(pio, "Use PIO accesses by default: 0=DMA, 1=PIO");
+#ifdef CONFIG_B43_BCMA
+static const struct bcma_device_id b43_bcma_tbl[] = {
+ BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x17, BCMA_ANY_CLASS),
+ BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x18, BCMA_ANY_CLASS),
+ BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x1D, BCMA_ANY_CLASS),
+ BCMA_CORETABLE_END
+};
+MODULE_DEVICE_TABLE(bcma, b43_bcma_tbl);
+#endif
+
+#ifdef CONFIG_B43_SSB
static const struct ssb_device_id b43_ssb_tbl[] = {
SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 5),
SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 6),
@@ -126,8 +137,8 @@
SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 16),
SSB_DEVTABLE_END
};
-
MODULE_DEVICE_TABLE(ssb, b43_ssb_tbl);
+#endif
/* Channel and ratetables are shared for all devices.
* They can't be const, because ieee80211 puts some precalculated
@@ -548,7 +559,7 @@
{
u32 low, high;
- B43_WARN_ON(dev->sdev->id.revision < 3);
+ B43_WARN_ON(dev->dev->core_rev < 3);
/* The hardware guarantees us an atomic read, if we
* read the low register first. */
@@ -586,7 +597,7 @@
{
u32 low, high;
- B43_WARN_ON(dev->sdev->id.revision < 3);
+ B43_WARN_ON(dev->dev->core_rev < 3);
low = tsf;
high = (tsf >> 32);
@@ -714,7 +725,7 @@
b43_ram_write(dev, i * 4, buffer[i]);
b43_write16(dev, 0x0568, 0x0000);
- if (dev->sdev->id.revision < 11)
+ if (dev->dev->core_rev < 11)
b43_write16(dev, 0x07C0, 0x0000);
else
b43_write16(dev, 0x07C0, 0x0100);
@@ -1132,7 +1143,7 @@
b43_write32(dev, B43_MMIO_MACCTL, macctl);
/* Commit write */
b43_read32(dev, B43_MMIO_MACCTL);
- if (awake && dev->sdev->id.revision >= 5) {
+ if (awake && dev->dev->core_rev >= 5) {
/* Wait for the microcode to wake up. */
for (i = 0; i < 100; i++) {
ucstat = b43_shm_read16(dev, B43_SHM_SHARED,
@@ -1144,35 +1155,39 @@
}
}
-static void b43_ssb_wireless_core_reset(struct b43_wldev *dev, u32 flags)
+static void b43_ssb_wireless_core_reset(struct b43_wldev *dev, bool gmode)
{
+ struct ssb_device *sdev = dev->dev->sdev;
u32 tmslow;
+ u32 flags = 0;
+ if (gmode)
+ flags |= B43_TMSLOW_GMODE;
flags |= B43_TMSLOW_PHYCLKEN;
flags |= B43_TMSLOW_PHYRESET;
if (dev->phy.type == B43_PHYTYPE_N)
flags |= B43_TMSLOW_PHY_BANDWIDTH_20MHZ; /* Make 20 MHz def */
- ssb_device_enable(dev->sdev, flags);
+ b43_device_enable(dev, flags);
msleep(2); /* Wait for the PLL to turn on. */
/* Now take the PHY out of Reset again */
- tmslow = ssb_read32(dev->sdev, SSB_TMSLOW);
+ tmslow = ssb_read32(sdev, SSB_TMSLOW);
tmslow |= SSB_TMSLOW_FGC;
tmslow &= ~B43_TMSLOW_PHYRESET;
- ssb_write32(dev->sdev, SSB_TMSLOW, tmslow);
- ssb_read32(dev->sdev, SSB_TMSLOW); /* flush */
+ ssb_write32(sdev, SSB_TMSLOW, tmslow);
+ ssb_read32(sdev, SSB_TMSLOW); /* flush */
msleep(1);
tmslow &= ~SSB_TMSLOW_FGC;
- ssb_write32(dev->sdev, SSB_TMSLOW, tmslow);
- ssb_read32(dev->sdev, SSB_TMSLOW); /* flush */
+ ssb_write32(sdev, SSB_TMSLOW, tmslow);
+ ssb_read32(sdev, SSB_TMSLOW); /* flush */
msleep(1);
}
-void b43_wireless_core_reset(struct b43_wldev *dev, u32 flags)
+void b43_wireless_core_reset(struct b43_wldev *dev, bool gmode)
{
u32 macctl;
- b43_ssb_wireless_core_reset(dev, flags);
+ b43_ssb_wireless_core_reset(dev, gmode);
/* Turn Analog ON, but only if we already know the PHY-type.
* This protects against very early setup where we don't know the
@@ -1183,7 +1198,7 @@
macctl = b43_read32(dev, B43_MMIO_MACCTL);
macctl &= ~B43_MACCTL_GMODE;
- if (flags & B43_TMSLOW_GMODE)
+ if (gmode)
macctl |= B43_MACCTL_GMODE;
macctl |= B43_MACCTL_IHR_ENABLED;
b43_write32(dev, B43_MMIO_MACCTL, macctl);
@@ -1221,7 +1236,7 @@
{
u32 dummy;
- if (dev->sdev->id.revision < 5)
+ if (dev->dev->core_rev < 5)
return;
/* Read all entries from the microcode TXstatus FIFO
* and throw them away.
@@ -1427,9 +1442,9 @@
/* Get the mask of available antennas. */
if (dev->phy.gmode)
- antenna_mask = dev->sdev->bus->sprom.ant_available_bg;
+ antenna_mask = dev->dev->bus_sprom->ant_available_bg;
else
- antenna_mask = dev->sdev->bus->sprom.ant_available_a;
+ antenna_mask = dev->dev->bus_sprom->ant_available_a;
if (!(antenna_mask & (1 << (antenna_nr - 1)))) {
/* This antenna is not available. Fall back to default. */
@@ -1644,7 +1659,7 @@
mutex_lock(&wl->mutex);
dev = wl->current_dev;
if (likely(dev && (b43_status(dev) >= B43_STAT_INITIALIZED))) {
- if (dev->sdev->bus->bustype == SSB_BUSTYPE_SDIO) {
+ if (b43_bus_host_is_sdio(dev->dev)) {
/* wl->mutex is enough. */
b43_do_beacon_update_trigger_work(dev);
mmiowb();
@@ -1689,7 +1704,7 @@
static void b43_set_beacon_int(struct b43_wldev *dev, u16 beacon_int)
{
b43_time_lock(dev);
- if (dev->sdev->id.revision >= 3) {
+ if (dev->dev->core_rev >= 3) {
b43_write32(dev, B43_MMIO_TSF_CFP_REP, (beacon_int << 16));
b43_write32(dev, B43_MMIO_TSF_CFP_START, (beacon_int << 10));
} else {
@@ -2063,7 +2078,7 @@
B43_WARN_ON(1);
return -ENOSYS;
}
- err = request_firmware(&blob, ctx->fwname, ctx->dev->sdev->dev);
+ err = request_firmware(&blob, ctx->fwname, ctx->dev->dev->dev);
if (err == -ENOENT) {
snprintf(ctx->errors[ctx->req_type],
sizeof(ctx->errors[ctx->req_type]),
@@ -2113,7 +2128,7 @@
{
struct b43_wldev *dev = ctx->dev;
struct b43_firmware *fw = &ctx->dev->fw;
- const u8 rev = ctx->dev->sdev->id.revision;
+ const u8 rev = ctx->dev->dev->core_rev;
const char *filename;
u32 tmshigh;
int err;
@@ -2157,7 +2172,7 @@
switch (dev->phy.type) {
case B43_PHYTYPE_A:
if ((rev >= 5) && (rev <= 10)) {
- tmshigh = ssb_read32(dev->sdev, SSB_TMSHIGH);
+ tmshigh = ssb_read32(dev->dev->sdev, SSB_TMSHIGH);
if (tmshigh & B43_TMSHIGH_HAVE_2GHZ_PHY)
filename = "a0g1initvals5";
else
@@ -2202,7 +2217,7 @@
switch (dev->phy.type) {
case B43_PHYTYPE_A:
if ((rev >= 5) && (rev <= 10)) {
- tmshigh = ssb_read32(dev->sdev, SSB_TMSHIGH);
+ tmshigh = ssb_read32(dev->dev->sdev, SSB_TMSHIGH);
if (tmshigh & B43_TMSHIGH_HAVE_2GHZ_PHY)
filename = "a0g1bsinitvals5";
else
@@ -2448,7 +2463,7 @@
snprintf(wiphy->fw_version, sizeof(wiphy->fw_version), "%u.%u",
dev->fw.rev, dev->fw.patch);
- wiphy->hw_version = dev->sdev->id.coreid;
+ wiphy->hw_version = dev->dev->core_id;
if (b43_is_old_txhdr_format(dev)) {
/* We're over the deadline, but we keep support for old fw
@@ -2566,7 +2581,7 @@
*/
static struct ssb_device *b43_ssb_gpio_dev(struct b43_wldev *dev)
{
- struct ssb_bus *bus = dev->sdev->bus;
+ struct ssb_bus *bus = dev->dev->sdev->bus;
#ifdef CONFIG_SSB_DRIVER_PCICORE
return (bus->chipco.dev ? bus->chipco.dev : bus->pcicore.dev);
@@ -2588,7 +2603,7 @@
mask = 0x0000001F;
set = 0x0000000F;
- if (dev->sdev->bus->chip_id == 0x4301) {
+ if (dev->dev->chip_id == 0x4301) {
mask |= 0x0060;
set |= 0x0060;
}
@@ -2599,14 +2614,14 @@
mask |= 0x0180;
set |= 0x0180;
}
- if (dev->sdev->bus->sprom.boardflags_lo & B43_BFL_PACTRL) {
+ if (dev->dev->bus_sprom->boardflags_lo & B43_BFL_PACTRL) {
b43_write16(dev, B43_MMIO_GPIO_MASK,
b43_read16(dev, B43_MMIO_GPIO_MASK)
| 0x0200);
mask |= 0x0200;
set |= 0x0200;
}
- if (dev->sdev->id.revision >= 2)
+ if (dev->dev->core_rev >= 2)
mask |= 0x0010; /* FIXME: This is redundant. */
gpiodev = b43_ssb_gpio_dev(dev);
@@ -2741,15 +2756,15 @@
/* Workaround: On old hardware the HW-MAC-address-filter
* doesn't work properly, so always run promisc in filter
* it in software. */
- if (dev->sdev->id.revision <= 4)
+ if (dev->dev->core_rev <= 4)
ctl |= B43_MACCTL_PROMISC;
b43_write32(dev, B43_MMIO_MACCTL, ctl);
cfp_pretbtt = 2;
if ((ctl & B43_MACCTL_INFRA) && !(ctl & B43_MACCTL_AP)) {
- if (dev->sdev->bus->chip_id == 0x4306 &&
- dev->sdev->bus->chip_rev == 3)
+ if (dev->dev->chip_id == 0x4306 &&
+ dev->dev->chip_rev == 3)
cfp_pretbtt = 100;
else
cfp_pretbtt = 50;
@@ -2907,7 +2922,7 @@
b43_write16(dev, 0x005E, value16);
}
b43_write32(dev, 0x0100, 0x01000000);
- if (dev->sdev->id.revision < 5)
+ if (dev->dev->core_rev < 5)
b43_write32(dev, 0x010C, 0x01000000);
b43_write32(dev, B43_MMIO_MACCTL, b43_read32(dev, B43_MMIO_MACCTL)
@@ -2922,7 +2937,7 @@
/* Initially set the wireless operation mode. */
b43_adjust_opmode(dev);
- if (dev->sdev->id.revision < 3) {
+ if (dev->dev->core_rev < 3) {
b43_write16(dev, 0x060E, 0x0000);
b43_write16(dev, 0x0610, 0x8000);
b43_write16(dev, 0x0604, 0x0000);
@@ -3105,7 +3120,7 @@
b43_shm_write32(dev, B43_SHM_SHARED, 0, backup0);
b43_shm_write32(dev, B43_SHM_SHARED, 4, backup4);
- if ((dev->sdev->id.revision >= 3) && (dev->sdev->id.revision <= 10)) {
+ if ((dev->dev->core_rev >= 3) && (dev->dev->core_rev <= 10)) {
/* The 32bit register shadows the two 16bit registers
* with update sideeffects. Validate this. */
b43_write16(dev, B43_MMIO_TSF_CFP_START, 0xAAAA);
@@ -3954,7 +3969,7 @@
/* Disable interrupts on the device. */
b43_set_status(dev, B43_STAT_INITIALIZED);
- if (dev->sdev->bus->bustype == SSB_BUSTYPE_SDIO) {
+ if (b43_bus_host_is_sdio(dev->dev)) {
/* wl->mutex is locked. That is enough. */
b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, 0);
b43_read32(dev, B43_MMIO_GEN_IRQ_MASK); /* Flush */
@@ -3967,11 +3982,11 @@
/* Synchronize and free the interrupt handlers. Unlock to avoid deadlocks. */
orig_dev = dev;
mutex_unlock(&wl->mutex);
- if (dev->sdev->bus->bustype == SSB_BUSTYPE_SDIO) {
+ if (b43_bus_host_is_sdio(dev->dev)) {
b43_sdio_free_irq(dev);
} else {
- synchronize_irq(dev->sdev->irq);
- free_irq(dev->sdev->irq, dev);
+ synchronize_irq(dev->dev->irq);
+ free_irq(dev->dev->irq, dev);
}
mutex_lock(&wl->mutex);
dev = wl->current_dev;
@@ -4004,19 +4019,19 @@
B43_WARN_ON(b43_status(dev) != B43_STAT_INITIALIZED);
drain_txstatus_queue(dev);
- if (dev->sdev->bus->bustype == SSB_BUSTYPE_SDIO) {
+ if (b43_bus_host_is_sdio(dev->dev)) {
err = b43_sdio_request_irq(dev, b43_sdio_interrupt_handler);
if (err) {
b43err(dev->wl, "Cannot request SDIO IRQ\n");
goto out;
}
} else {
- err = request_threaded_irq(dev->sdev->irq, b43_interrupt_handler,
+ err = request_threaded_irq(dev->dev->irq, b43_interrupt_handler,
b43_interrupt_thread_handler,
IRQF_SHARED, KBUILD_MODNAME, dev);
if (err) {
b43err(dev->wl, "Cannot request IRQ-%d\n",
- dev->sdev->irq);
+ dev->dev->irq);
goto out;
}
}
@@ -4083,9 +4098,15 @@
unsupported = 1;
break;
#endif
+#ifdef CONFIG_B43_PHY_HT
+ case B43_PHYTYPE_HT:
+ if (phy_rev > 1)
+ unsupported = 1;
+ break;
+#endif
default:
unsupported = 1;
- };
+ }
if (unsupported) {
b43err(dev->wl, "FOUND UNSUPPORTED PHY "
"(Analog %u, Type %u, Revision %u)\n",
@@ -4096,10 +4117,10 @@
analog_type, phy_type, phy_rev);
/* Get RADIO versioning */
- if (dev->sdev->bus->chip_id == 0x4317) {
- if (dev->sdev->bus->chip_rev == 0)
+ if (dev->dev->chip_id == 0x4317) {
+ if (dev->dev->chip_rev == 0)
tmp = 0x3205017F;
- else if (dev->sdev->bus->chip_rev == 1)
+ else if (dev->dev->chip_rev == 1)
tmp = 0x4205017F;
else
tmp = 0x5205017F;
@@ -4139,6 +4160,10 @@
if (radio_ver != 0x2062 && radio_ver != 0x2063)
unsupported = 1;
break;
+ case B43_PHYTYPE_HT:
+ if (radio_ver != 0x2059)
+ unsupported = 1;
+ break;
default:
B43_WARN_ON(1);
}
@@ -4204,7 +4229,7 @@
static void b43_bluetooth_coext_enable(struct b43_wldev *dev)
{
- struct ssb_sprom *sprom = &dev->sdev->bus->sprom;
+ struct ssb_sprom *sprom = dev->dev->bus_sprom;
u64 hf;
if (!modparam_btcoex)
@@ -4231,16 +4256,21 @@
static void b43_imcfglo_timeouts_workaround(struct b43_wldev *dev)
{
- struct ssb_bus *bus = dev->sdev->bus;
+ struct ssb_bus *bus;
u32 tmp;
+ if (dev->dev->bus_type != B43_BUS_SSB)
+ return;
+
+ bus = dev->dev->sdev->bus;
+
if ((bus->chip_id == 0x4311 && bus->chip_rev == 2) ||
(bus->chip_id == 0x4312)) {
- tmp = ssb_read32(dev->sdev, SSB_IMCFGLO);
+ tmp = ssb_read32(dev->dev->sdev, SSB_IMCFGLO);
tmp &= ~SSB_IMCFGLO_REQTO;
tmp &= ~SSB_IMCFGLO_SERTO;
tmp |= 0x3;
- ssb_write32(dev->sdev, SSB_IMCFGLO, tmp);
+ ssb_write32(dev->dev->sdev, SSB_IMCFGLO, tmp);
ssb_commit_settings(bus);
}
}
@@ -4310,29 +4340,26 @@
dev->wl->current_beacon = NULL;
}
- ssb_device_disable(dev->sdev, 0);
- ssb_bus_may_powerdown(dev->sdev->bus);
+ b43_device_disable(dev, 0);
+ b43_bus_may_powerdown(dev);
}
/* Initialize a wireless core */
static int b43_wireless_core_init(struct b43_wldev *dev)
{
struct ssb_bus *bus = dev->sdev->bus;
- struct ssb_sprom *sprom = &bus->sprom;
+ struct ssb_sprom *sprom = dev->dev->bus_sprom;
struct b43_phy *phy = &dev->phy;
int err;
u64 hf;
- u32 tmp;
B43_WARN_ON(b43_status(dev) != B43_STAT_UNINIT);
- err = ssb_bus_powerup(bus, 0);
+ err = b43_bus_powerup(dev, 0);
if (err)
goto out;
- if (!ssb_device_is_enabled(dev->sdev)) {
- tmp = phy->gmode ? B43_TMSLOW_GMODE : 0;
- b43_wireless_core_reset(dev, tmp);
- }
+ if (!b43_device_is_enabled(dev))
+ b43_wireless_core_reset(dev, phy->gmode);
/* Reset all data structures. */
setup_struct_wldev_for_init(dev);
@@ -4352,7 +4379,7 @@
if (err)
goto err_busdown;
b43_shm_write16(dev, B43_SHM_SHARED,
- B43_SHM_SH_WLCOREREV, dev->sdev->id.revision);
+ B43_SHM_SH_WLCOREREV, dev->dev->core_rev);
hf = b43_hf_read(dev);
if (phy->type == B43_PHYTYPE_G) {
hf |= B43_HF_SYMW;
@@ -4399,8 +4426,8 @@
/* Maximum Contention Window */
b43_shm_write16(dev, B43_SHM_SCRATCH, B43_SHM_SC_MAXCONT, 0x3FF);
- if ((dev->sdev->bus->bustype == SSB_BUSTYPE_PCMCIA) ||
- (dev->sdev->bus->bustype == SSB_BUSTYPE_SDIO) ||
+ if (b43_bus_host_is_pcmcia(dev->dev) ||
+ b43_bus_host_is_sdio(dev->dev) ||
dev->use_pio) {
dev->__using_pio_transfers = 1;
err = b43_pio_init(dev);
@@ -4414,7 +4441,7 @@
b43_set_synth_pu_delay(dev, 1);
b43_bluetooth_coext_enable(dev);
- ssb_bus_powerup(bus, !(sprom->boardflags_lo & B43_BFL_XTAL_NOSLOW));
+ b43_bus_powerup(dev, !(sprom->boardflags_lo & B43_BFL_XTAL_NOSLOW));
b43_upload_card_macaddress(dev);
b43_security_init(dev);
@@ -4431,7 +4458,7 @@
err_chip_exit:
b43_chip_exit(dev);
err_busdown:
- ssb_bus_may_powerdown(bus);
+ b43_bus_may_powerdown(dev);
B43_WARN_ON(b43_status(dev) != B43_STAT_UNINIT);
return err;
}
@@ -4741,7 +4768,6 @@
struct pci_dev *pdev = (bus->bustype == SSB_BUSTYPE_PCI) ? bus->host_pci : NULL;
int err;
bool have_2ghz_phy = 0, have_5ghz_phy = 0;
- u32 tmp;
/* Do NOT do any device initialization here.
* Do it in wireless_core_init() instead.
@@ -4750,13 +4776,13 @@
* that in core_init(), too.
*/
- err = ssb_bus_powerup(bus, 0);
+ err = b43_bus_powerup(dev, 0);
if (err) {
b43err(wl, "Bus powerup failed\n");
goto out;
}
/* Get the PHY type. */
- if (dev->sdev->id.revision >= 5) {
+ if (dev->dev->core_rev >= 5) {
u32 tmshigh;
tmshigh = ssb_read32(dev->sdev, SSB_TMSHIGH);
@@ -4767,8 +4793,7 @@
dev->phy.gmode = have_2ghz_phy;
dev->phy.radio_on = 1;
- tmp = dev->phy.gmode ? B43_TMSLOW_GMODE : 0;
- b43_wireless_core_reset(dev, tmp);
+ b43_wireless_core_reset(dev, dev->phy.gmode);
err = b43_phy_versioning(dev);
if (err)
@@ -4816,8 +4841,7 @@
goto err_powerdown;
dev->phy.gmode = have_2ghz_phy;
- tmp = dev->phy.gmode ? B43_TMSLOW_GMODE : 0;
- b43_wireless_core_reset(dev, tmp);
+ b43_wireless_core_reset(dev, dev->phy.gmode);
err = b43_validate_chipaccess(dev);
if (err)
@@ -4832,8 +4856,8 @@
INIT_WORK(&dev->restart_work, b43_chip_reset);
dev->phy.ops->switch_analog(dev, 0);
- ssb_device_disable(dev->sdev, 0);
- ssb_bus_may_powerdown(bus);
+ b43_device_disable(dev, 0);
+ b43_bus_may_powerdown(dev);
out:
return err;
@@ -4841,11 +4865,11 @@
err_phy_free:
b43_phy_free(dev);
err_powerdown:
- ssb_bus_may_powerdown(bus);
+ b43_bus_may_powerdown(dev);
return err;
}
-static void b43_one_core_detach(struct ssb_device *dev)
+static void b43_one_core_detach(struct b43_bus_dev *dev)
{
struct b43_wldev *wldev;
struct b43_wl *wl;
@@ -4853,17 +4877,17 @@
/* Do not cancel ieee80211-workqueue based work here.
* See comment in b43_remove(). */
- wldev = ssb_get_drvdata(dev);
+ wldev = ssb_get_drvdata(dev->sdev);
wl = wldev->wl;
b43_debugfs_remove_device(wldev);
b43_wireless_core_detach(wldev);
list_del(&wldev->list);
wl->nr_devs--;
- ssb_set_drvdata(dev, NULL);
+ ssb_set_drvdata(dev->sdev, NULL);
kfree(wldev);
}
-static int b43_one_core_attach(struct ssb_device *dev, struct b43_wl *wl)
+static int b43_one_core_attach(struct b43_bus_dev *dev, struct b43_wl *wl)
{
struct b43_wldev *wldev;
int err = -ENOMEM;
@@ -4873,7 +4897,8 @@
goto out;
wldev->use_pio = b43_modparam_pio;
- wldev->sdev = dev;
+ wldev->dev = dev;
+ wldev->sdev = dev->sdev; /* TODO: Remove when not needed */
wldev->wl = wl;
b43_set_status(wldev, B43_STAT_UNINIT);
wldev->bad_frames_preempt = modparam_bad_frames_preempt;
@@ -4885,7 +4910,7 @@
list_add(&wldev->list, &wl->devlist);
wl->nr_devs++;
- ssb_set_drvdata(dev, wldev);
+ ssb_set_drvdata(dev->sdev, wldev);
b43_debugfs_add_device(wldev);
out:
@@ -4926,11 +4951,11 @@
}
}
-static void b43_wireless_exit(struct ssb_device *dev, struct b43_wl *wl)
+static void b43_wireless_exit(struct b43_bus_dev *dev, struct b43_wl *wl)
{
struct ieee80211_hw *hw = wl->hw;
- ssb_set_devtypedata(dev, NULL);
+ ssb_set_devtypedata(dev->sdev, NULL);
ieee80211_free_hw(hw);
}
@@ -4982,24 +5007,51 @@
return wl;
}
-static int b43_ssb_probe(struct ssb_device *dev, const struct ssb_device_id *id)
+#ifdef CONFIG_B43_BCMA
+static int b43_bcma_probe(struct bcma_device *core)
{
+ b43err(NULL, "BCMA is not supported yet!");
+ return -EOPNOTSUPP;
+}
+
+static void b43_bcma_remove(struct bcma_device *core)
+{
+ /* TODO */
+}
+
+static struct bcma_driver b43_bcma_driver = {
+ .name = KBUILD_MODNAME,
+ .id_table = b43_bcma_tbl,
+ .probe = b43_bcma_probe,
+ .remove = b43_bcma_remove,
+};
+#endif
+
+#ifdef CONFIG_B43_SSB
+static
+int b43_ssb_probe(struct ssb_device *sdev, const struct ssb_device_id *id)
+{
+ struct b43_bus_dev *dev;
struct b43_wl *wl;
int err;
int first = 0;
- wl = ssb_get_devtypedata(dev);
+ dev = b43_bus_dev_ssb_init(sdev);
+ if (!dev)
+ return -ENOMEM;
+
+ wl = ssb_get_devtypedata(sdev);
if (!wl) {
/* Probing the first core. Must setup common struct b43_wl */
first = 1;
- b43_sprom_fixup(dev->bus);
- wl = b43_wireless_init(dev);
+ b43_sprom_fixup(sdev->bus);
+ wl = b43_wireless_init(sdev);
if (IS_ERR(wl)) {
err = PTR_ERR(wl);
goto out;
}
- ssb_set_devtypedata(dev, wl);
- B43_WARN_ON(ssb_get_devtypedata(dev) != wl);
+ ssb_set_devtypedata(sdev, wl);
+ B43_WARN_ON(ssb_get_devtypedata(sdev) != wl);
}
err = b43_one_core_attach(dev, wl);
if (err)
@@ -5023,10 +5075,10 @@
return err;
}
-static void b43_ssb_remove(struct ssb_device *dev)
+static void b43_ssb_remove(struct ssb_device *sdev)
{
- struct b43_wl *wl = ssb_get_devtypedata(dev);
- struct b43_wldev *wldev = ssb_get_drvdata(dev);
+ struct b43_wl *wl = ssb_get_devtypedata(sdev);
+ struct b43_wldev *wldev = ssb_get_drvdata(sdev);
/* We must cancel any work here before unregistering from ieee80211,
* as the ieee80211 unreg will destroy the workqueue. */
@@ -5042,17 +5094,25 @@
ieee80211_unregister_hw(wl->hw);
}
- b43_one_core_detach(dev);
+ b43_one_core_detach(wldev->dev);
if (list_empty(&wl->devlist)) {
b43_leds_unregister(wl);
/* Last core on the chip unregistered.
* We can destroy common struct b43_wl.
*/
- b43_wireless_exit(dev, wl);
+ b43_wireless_exit(wldev->dev, wl);
}
}
+static struct ssb_driver b43_ssb_driver = {
+ .name = KBUILD_MODNAME,
+ .id_table = b43_ssb_tbl,
+ .probe = b43_ssb_probe,
+ .remove = b43_ssb_remove,
+};
+#endif /* CONFIG_B43_SSB */
+
/* Perform a hardware reset. This can be called from any context. */
void b43_controller_restart(struct b43_wldev *dev, const char *reason)
{
@@ -5063,13 +5123,6 @@
ieee80211_queue_work(dev->wl->hw, &dev->restart_work);
}
-static struct ssb_driver b43_ssb_driver = {
- .name = KBUILD_MODNAME,
- .id_table = b43_ssb_tbl,
- .probe = b43_ssb_probe,
- .remove = b43_ssb_remove,
-};
-
static void b43_print_driverinfo(void)
{
const char *feat_pci = "", *feat_pcmcia = "", *feat_nphy = "",
@@ -5108,14 +5161,27 @@
err = b43_sdio_init();
if (err)
goto err_pcmcia_exit;
- err = ssb_driver_register(&b43_ssb_driver);
+#ifdef CONFIG_B43_BCMA
+ err = bcma_driver_register(&b43_bcma_driver);
if (err)
goto err_sdio_exit;
+#endif
+#ifdef CONFIG_B43_SSB
+ err = ssb_driver_register(&b43_ssb_driver);
+ if (err)
+ goto err_bcma_driver_exit;
+#endif
b43_print_driverinfo();
return err;
+#ifdef CONFIG_B43_SSB
+err_bcma_driver_exit:
+#endif
+#ifdef CONFIG_B43_BCMA
+ bcma_driver_unregister(&b43_bcma_driver);
err_sdio_exit:
+#endif
b43_sdio_exit();
err_pcmcia_exit:
b43_pcmcia_exit();
@@ -5126,7 +5192,12 @@
static void __exit b43_exit(void)
{
+#ifdef CONFIG_B43_SSB
ssb_driver_unregister(&b43_ssb_driver);
+#endif
+#ifdef CONFIG_B43_BCMA
+ bcma_driver_unregister(&b43_bcma_driver);
+#endif
b43_sdio_exit();
b43_pcmcia_exit();
b43_debugfs_exit();
diff --git a/drivers/net/wireless/b43/main.h b/drivers/net/wireless/b43/main.h
index a0d327f..e4ebce9 100644
--- a/drivers/net/wireless/b43/main.h
+++ b/drivers/net/wireless/b43/main.h
@@ -121,7 +121,7 @@
void b43_dummy_transmission(struct b43_wldev *dev, bool ofdm, bool pa_on);
-void b43_wireless_core_reset(struct b43_wldev *dev, u32 flags);
+void b43_wireless_core_reset(struct b43_wldev *dev, bool gmode);
void b43_controller_restart(struct b43_wldev *dev, const char *reason);
diff --git a/drivers/net/wireless/b43/phy_a.c b/drivers/net/wireless/b43/phy_a.c
index b01c8ced..73ace55 100644
--- a/drivers/net/wireless/b43/phy_a.c
+++ b/drivers/net/wireless/b43/phy_a.c
@@ -265,7 +265,6 @@
void b43_phy_inita(struct b43_wldev *dev)
{
- struct ssb_bus *bus = dev->sdev->bus;
struct b43_phy *phy = &dev->phy;
/* This lowlevel A-PHY init is also called from G-PHY init.
@@ -296,9 +295,9 @@
b43_radio_init2060(dev);
- if ((bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM) &&
- ((bus->boardinfo.type == SSB_BOARD_BU4306) ||
- (bus->boardinfo.type == SSB_BOARD_BU4309))) {
+ if ((dev->dev->board_vendor == SSB_BOARDVENDOR_BCM) &&
+ ((dev->dev->board_type == SSB_BOARD_BU4306) ||
+ (dev->dev->board_type == SSB_BOARD_BU4309))) {
; //TODO: A PHY LO
}
@@ -311,7 +310,7 @@
}
if ((phy->type == B43_PHYTYPE_G) &&
- (dev->sdev->bus->sprom.boardflags_lo & B43_BFL_PACTRL)) {
+ (dev->dev->bus_sprom->boardflags_lo & B43_BFL_PACTRL)) {
b43_phy_maskset(dev, B43_PHY_OFDM(0x6E), 0xE000, 0x3CF);
}
}
@@ -323,17 +322,17 @@
struct b43_phy_a *aphy = phy->a;
s16 pab0, pab1, pab2;
- pab0 = (s16) (dev->sdev->bus->sprom.pa1b0);
- pab1 = (s16) (dev->sdev->bus->sprom.pa1b1);
- pab2 = (s16) (dev->sdev->bus->sprom.pa1b2);
+ pab0 = (s16) (dev->dev->bus_sprom->pa1b0);
+ pab1 = (s16) (dev->dev->bus_sprom->pa1b1);
+ pab2 = (s16) (dev->dev->bus_sprom->pa1b2);
if (pab0 != 0 && pab1 != 0 && pab2 != 0 &&
pab0 != -1 && pab1 != -1 && pab2 != -1) {
/* The pabX values are set in SPROM. Use them. */
- if ((s8) dev->sdev->bus->sprom.itssi_a != 0 &&
- (s8) dev->sdev->bus->sprom.itssi_a != -1)
+ if ((s8) dev->dev->bus_sprom->itssi_a != 0 &&
+ (s8) dev->dev->bus_sprom->itssi_a != -1)
aphy->tgt_idle_tssi =
- (s8) (dev->sdev->bus->sprom.itssi_a);
+ (s8) (dev->dev->bus_sprom->itssi_a);
else
aphy->tgt_idle_tssi = 62;
aphy->tssi2dbm = b43_generate_dyn_tssi2dbm_tab(dev, pab0,
diff --git a/drivers/net/wireless/b43/phy_common.c b/drivers/net/wireless/b43/phy_common.c
index e46b2f4..9705950 100644
--- a/drivers/net/wireless/b43/phy_common.c
+++ b/drivers/net/wireless/b43/phy_common.c
@@ -31,6 +31,7 @@
#include "phy_a.h"
#include "phy_n.h"
#include "phy_lp.h"
+#include "phy_ht.h"
#include "b43.h"
#include "main.h"
@@ -59,6 +60,11 @@
phy->ops = &b43_phyops_lp;
#endif
break;
+ case B43_PHYTYPE_HT:
+#ifdef CONFIG_B43_PHY_HT
+ phy->ops = &b43_phyops_ht;
+#endif
+ break;
}
if (B43_WARN_ON(!phy->ops))
return -ENODEV;
@@ -168,7 +174,7 @@
B43_WARN_ON(dev->phy.phy_locked);
dev->phy.phy_locked = 1;
#endif
- B43_WARN_ON(dev->sdev->id.revision < 3);
+ B43_WARN_ON(dev->dev->core_rev < 3);
if (!b43_is_mode(dev->wl, NL80211_IFTYPE_AP))
b43_power_saving_ctl_bits(dev, B43_PS_AWAKE);
@@ -180,7 +186,7 @@
B43_WARN_ON(!dev->phy.phy_locked);
dev->phy.phy_locked = 0;
#endif
- B43_WARN_ON(dev->sdev->id.revision < 3);
+ B43_WARN_ON(dev->dev->core_rev < 3);
if (!b43_is_mode(dev->wl, NL80211_IFTYPE_AP))
b43_power_saving_ctl_bits(dev, 0);
@@ -368,8 +374,8 @@
/* The next check will be needed in two seconds, or later. */
phy->next_txpwr_check_time = round_jiffies(now + (HZ * 2));
- if ((dev->sdev->bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM) &&
- (dev->sdev->bus->boardinfo.type == SSB_BOARD_BU4306))
+ if ((dev->dev->board_vendor == SSB_BOARDVENDOR_BCM) &&
+ (dev->dev->board_type == SSB_BOARD_BU4306))
return; /* No software txpower adjustment needed */
result = phy->ops->recalc_txpower(dev, !!(flags & B43_TXPWR_IGNORE_TSSI));
diff --git a/drivers/net/wireless/b43/phy_common.h b/drivers/net/wireless/b43/phy_common.h
index 2401bee..47dcb80 100644
--- a/drivers/net/wireless/b43/phy_common.h
+++ b/drivers/net/wireless/b43/phy_common.h
@@ -194,6 +194,7 @@
struct b43_phy_g;
struct b43_phy_n;
struct b43_phy_lp;
+struct b43_phy_ht;
struct b43_phy {
/* Hardware operation callbacks. */
@@ -216,6 +217,8 @@
struct b43_phy_n *n;
/* LP-PHY specific information */
struct b43_phy_lp *lp;
+ /* HT-PHY specific information */
+ struct b43_phy_ht *ht;
};
/* Band support flags. */
diff --git a/drivers/net/wireless/b43/phy_g.c b/drivers/net/wireless/b43/phy_g.c
index 1758a28..83532d1 100644
--- a/drivers/net/wireless/b43/phy_g.c
+++ b/drivers/net/wireless/b43/phy_g.c
@@ -718,7 +718,7 @@
B43_WARN_ON(phy->type != B43_PHYTYPE_G);
if (!phy->gmode ||
- !(dev->sdev->bus->sprom.boardflags_lo & B43_BFL_RSSI)) {
+ !(dev->dev->bus_sprom->boardflags_lo & B43_BFL_RSSI)) {
tmp16 = b43_nrssi_hw_read(dev, 0x20);
if (tmp16 >= 0x20)
tmp16 -= 0x40;
@@ -1114,7 +1114,7 @@
{
struct b43_phy *phy = &dev->phy;
struct b43_phy_g *gphy = phy->g;
- struct ssb_sprom *sprom = &(dev->sdev->bus->sprom);
+ struct ssb_sprom *sprom = dev->dev->bus_sprom;
if (!phy->gmode)
return 0;
@@ -1491,7 +1491,6 @@
static void b43_phy_initb5(struct b43_wldev *dev)
{
- struct ssb_bus *bus = dev->sdev->bus;
struct b43_phy *phy = &dev->phy;
struct b43_phy_g *gphy = phy->g;
u16 offset, value;
@@ -1500,8 +1499,8 @@
if (phy->analog == 1) {
b43_radio_set(dev, 0x007A, 0x0050);
}
- if ((bus->boardinfo.vendor != SSB_BOARDVENDOR_BCM) &&
- (bus->boardinfo.type != SSB_BOARD_BU4306)) {
+ if ((dev->dev->board_vendor != SSB_BOARDVENDOR_BCM) &&
+ (dev->dev->board_type != SSB_BOARD_BU4306)) {
value = 0x2120;
for (offset = 0x00A8; offset < 0x00C7; offset++) {
b43_phy_write(dev, offset, value);
@@ -1620,7 +1619,7 @@
b43_radio_write16(dev, 0x5A, 0x88);
b43_radio_write16(dev, 0x5B, 0x6B);
b43_radio_write16(dev, 0x5C, 0x0F);
- if (dev->sdev->bus->sprom.boardflags_lo & B43_BFL_ALTIQ) {
+ if (dev->dev->bus_sprom->boardflags_lo & B43_BFL_ALTIQ) {
b43_radio_write16(dev, 0x5D, 0xFA);
b43_radio_write16(dev, 0x5E, 0xD8);
} else {
@@ -1787,7 +1786,7 @@
b43_phy_set(dev, B43_PHY_RFOVER, 0x0100);
b43_phy_mask(dev, B43_PHY_RFOVERVAL, 0xCFFF);
- if (dev->sdev->bus->sprom.boardflags_lo & B43_BFL_EXTLNA) {
+ if (dev->dev->bus_sprom->boardflags_lo & B43_BFL_EXTLNA) {
if (phy->rev >= 7) {
b43_phy_set(dev, B43_PHY_RFOVER, 0x0800);
b43_phy_set(dev, B43_PHY_RFOVERVAL, 0x8000);
@@ -1922,7 +1921,6 @@
/* Initialize B/G PHY power control */
static void b43_phy_init_pctl(struct b43_wldev *dev)
{
- struct ssb_bus *bus = dev->sdev->bus;
struct b43_phy *phy = &dev->phy;
struct b43_phy_g *gphy = phy->g;
struct b43_rfatt old_rfatt;
@@ -1931,8 +1929,8 @@
B43_WARN_ON(phy->type != B43_PHYTYPE_G);
- if ((bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM) &&
- (bus->boardinfo.type == SSB_BOARD_BU4306))
+ if ((dev->dev->board_vendor == SSB_BOARDVENDOR_BCM) &&
+ (dev->dev->board_type == SSB_BOARD_BU4306))
return;
b43_phy_write(dev, 0x0028, 0x8018);
@@ -2053,7 +2051,7 @@
if (phy->rev >= 6) {
b43_phy_maskset(dev, B43_PHY_CCK(0x36), 0x0FFF, (gphy->lo_control->tx_bias << 12));
}
- if (dev->sdev->bus->sprom.boardflags_lo & B43_BFL_PACTRL)
+ if (dev->dev->bus_sprom->boardflags_lo & B43_BFL_PACTRL)
b43_phy_write(dev, B43_PHY_CCK(0x2E), 0x8075);
else
b43_phy_write(dev, B43_PHY_CCK(0x2E), 0x807F);
@@ -2066,7 +2064,7 @@
b43_phy_write(dev, B43_PHY_LO_MASK, 0x8078);
}
- if (!(dev->sdev->bus->sprom.boardflags_lo & B43_BFL_RSSI)) {
+ if (!(dev->dev->bus_sprom->boardflags_lo & B43_BFL_RSSI)) {
/* The specs state to update the NRSSI LT with
* the value 0x7FFFFFFF here. I think that is some weird
* compiler optimization in the original driver.
@@ -2088,8 +2086,8 @@
/* FIXME: The spec says in the following if, the 0 should be replaced
'if OFDM may not be used in the current locale'
but OFDM is legal everywhere */
- if ((dev->sdev->bus->chip_id == 0x4306
- && dev->sdev->bus->chip_package == 2) || 0) {
+ if ((dev->dev->chip_id == 0x4306
+ && dev->dev->chip_pkg == 2) || 0) {
b43_phy_mask(dev, B43_PHY_CRS0, 0xBFFF);
b43_phy_mask(dev, B43_PHY_OFDM(0xC3), 0x7FFF);
}
@@ -2105,7 +2103,7 @@
b43_write16(dev, B43_MMIO_CHANNEL, channel2freq_bg(channel));
if (channel == 14) {
- if (dev->sdev->bus->sprom.country_code ==
+ if (dev->dev->bus_sprom->country_code ==
SSB_SPROM1CCODE_JAPAN)
b43_hf_write(dev,
b43_hf_read(dev) & ~B43_HF_ACPR);
@@ -2136,17 +2134,17 @@
static void default_radio_attenuation(struct b43_wldev *dev,
struct b43_rfatt *rf)
{
- struct ssb_bus *bus = dev->sdev->bus;
+ struct b43_bus_dev *bdev = dev->dev;
struct b43_phy *phy = &dev->phy;
rf->with_padmix = 0;
- if (bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM &&
- bus->boardinfo.type == SSB_BOARD_BCM4309G) {
- if (bus->boardinfo.rev < 0x43) {
+ if (dev->dev->board_vendor == SSB_BOARDVENDOR_BCM &&
+ dev->dev->board_type == SSB_BOARD_BCM4309G) {
+ if (dev->dev->board_rev < 0x43) {
rf->att = 2;
return;
- } else if (bus->boardinfo.rev < 0x51) {
+ } else if (dev->dev->board_rev < 0x51) {
rf->att = 3;
return;
}
@@ -2172,21 +2170,21 @@
return;
case 1:
if (phy->type == B43_PHYTYPE_G) {
- if (bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM
- && bus->boardinfo.type == SSB_BOARD_BCM4309G
- && bus->boardinfo.rev >= 30)
+ if (bdev->board_vendor == SSB_BOARDVENDOR_BCM
+ && bdev->board_type == SSB_BOARD_BCM4309G
+ && bdev->board_rev >= 30)
rf->att = 3;
- else if (bus->boardinfo.vendor ==
+ else if (bdev->board_vendor ==
SSB_BOARDVENDOR_BCM
- && bus->boardinfo.type ==
+ && bdev->board_type ==
SSB_BOARD_BU4306)
rf->att = 3;
else
rf->att = 1;
} else {
- if (bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM
- && bus->boardinfo.type == SSB_BOARD_BCM4309G
- && bus->boardinfo.rev >= 30)
+ if (bdev->board_vendor == SSB_BOARDVENDOR_BCM
+ && bdev->board_type == SSB_BOARD_BCM4309G
+ && bdev->board_rev >= 30)
rf->att = 7;
else
rf->att = 6;
@@ -2194,16 +2192,16 @@
return;
case 2:
if (phy->type == B43_PHYTYPE_G) {
- if (bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM
- && bus->boardinfo.type == SSB_BOARD_BCM4309G
- && bus->boardinfo.rev >= 30)
+ if (bdev->board_vendor == SSB_BOARDVENDOR_BCM
+ && bdev->board_type == SSB_BOARD_BCM4309G
+ && bdev->board_rev >= 30)
rf->att = 3;
- else if (bus->boardinfo.vendor ==
+ else if (bdev->board_vendor ==
SSB_BOARDVENDOR_BCM
- && bus->boardinfo.type ==
+ && bdev->board_type ==
SSB_BOARD_BU4306)
rf->att = 5;
- else if (bus->chip_id == 0x4320)
+ else if (bdev->chip_id == 0x4320)
rf->att = 4;
else
rf->att = 3;
@@ -2384,11 +2382,11 @@
struct b43_phy_g *gphy = phy->g;
s16 pab0, pab1, pab2;
- pab0 = (s16) (dev->sdev->bus->sprom.pa0b0);
- pab1 = (s16) (dev->sdev->bus->sprom.pa0b1);
- pab2 = (s16) (dev->sdev->bus->sprom.pa0b2);
+ pab0 = (s16) (dev->dev->bus_sprom->pa0b0);
+ pab1 = (s16) (dev->dev->bus_sprom->pa0b1);
+ pab2 = (s16) (dev->dev->bus_sprom->pa0b2);
- B43_WARN_ON((dev->sdev->bus->chip_id == 0x4301) &&
+ B43_WARN_ON((dev->dev->chip_id == 0x4301) &&
(phy->radio_ver != 0x2050)); /* Not supported anymore */
gphy->dyn_tssi_tbl = 0;
@@ -2396,10 +2394,10 @@
if (pab0 != 0 && pab1 != 0 && pab2 != 0 &&
pab0 != -1 && pab1 != -1 && pab2 != -1) {
/* The pabX values are set in SPROM. Use them. */
- if ((s8) dev->sdev->bus->sprom.itssi_bg != 0 &&
- (s8) dev->sdev->bus->sprom.itssi_bg != -1) {
+ if ((s8) dev->dev->bus_sprom->itssi_bg != 0 &&
+ (s8) dev->dev->bus_sprom->itssi_bg != -1) {
gphy->tgt_idle_tssi =
- (s8) (dev->sdev->bus->sprom.itssi_bg);
+ (s8) (dev->dev->bus_sprom->itssi_bg);
} else
gphy->tgt_idle_tssi = 62;
gphy->tssi2dbm = b43_generate_dyn_tssi2dbm_tab(dev, pab0,
@@ -2537,7 +2535,7 @@
b43_wireless_core_reset(dev, 0);
b43_phy_initg(dev);
phy->gmode = 1;
- b43_wireless_core_reset(dev, B43_TMSLOW_GMODE);
+ b43_wireless_core_reset(dev, 1);
}
return 0;
@@ -2840,7 +2838,7 @@
B43_TXCTL_TXMIX;
rfatt += 2;
bbatt += 2;
- } else if (dev->sdev->bus->sprom.
+ } else if (dev->dev->bus_sprom->
boardflags_lo &
B43_BFL_PACTRL) {
bbatt += 4 * (rfatt - 2);
@@ -2914,14 +2912,14 @@
estimated_pwr = b43_gphy_estimate_power_out(dev, average_tssi);
B43_WARN_ON(phy->type != B43_PHYTYPE_G);
- max_pwr = dev->sdev->bus->sprom.maxpwr_bg;
- if (dev->sdev->bus->sprom.boardflags_lo & B43_BFL_PACTRL)
+ max_pwr = dev->dev->bus_sprom->maxpwr_bg;
+ if (dev->dev->bus_sprom->boardflags_lo & B43_BFL_PACTRL)
max_pwr -= 3; /* minus 0.75 */
if (unlikely(max_pwr >= INT_TO_Q52(30/*dBm*/))) {
b43warn(dev->wl,
"Invalid max-TX-power value in SPROM.\n");
max_pwr = INT_TO_Q52(20); /* fake it */
- dev->sdev->bus->sprom.maxpwr_bg = max_pwr;
+ dev->dev->bus_sprom->maxpwr_bg = max_pwr;
}
/* Get desired power (in Q5.2) */
@@ -3014,7 +3012,7 @@
{
struct b43_phy *phy = &dev->phy;
- if (!(dev->sdev->bus->sprom.boardflags_lo & B43_BFL_RSSI))
+ if (!(dev->dev->bus_sprom->boardflags_lo & B43_BFL_RSSI))
return;
b43_mac_suspend(dev);
diff --git a/drivers/net/wireless/b43/phy_ht.c b/drivers/net/wireless/b43/phy_ht.c
new file mode 100644
index 0000000..30b19c6
--- /dev/null
+++ b/drivers/net/wireless/b43/phy_ht.c
@@ -0,0 +1,398 @@
+/*
+
+ Broadcom B43 wireless driver
+ IEEE 802.11n HT-PHY support
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+
+*/
+
+#include <linux/slab.h>
+
+#include "b43.h"
+#include "phy_ht.h"
+#include "tables_phy_ht.h"
+#include "radio_2059.h"
+#include "main.h"
+
+/**************************************************
+ * Radio 2059.
+ **************************************************/
+
+static void b43_radio_2059_channel_setup(struct b43_wldev *dev,
+ const struct b43_phy_ht_channeltab_e_radio2059 *e)
+{
+ u8 i;
+ u16 routing;
+
+ b43_radio_write(dev, 0x16, e->radio_syn16);
+ b43_radio_write(dev, 0x17, e->radio_syn17);
+ b43_radio_write(dev, 0x22, e->radio_syn22);
+ b43_radio_write(dev, 0x25, e->radio_syn25);
+ b43_radio_write(dev, 0x27, e->radio_syn27);
+ b43_radio_write(dev, 0x28, e->radio_syn28);
+ b43_radio_write(dev, 0x29, e->radio_syn29);
+ b43_radio_write(dev, 0x2c, e->radio_syn2c);
+ b43_radio_write(dev, 0x2d, e->radio_syn2d);
+ b43_radio_write(dev, 0x37, e->radio_syn37);
+ b43_radio_write(dev, 0x41, e->radio_syn41);
+ b43_radio_write(dev, 0x43, e->radio_syn43);
+ b43_radio_write(dev, 0x47, e->radio_syn47);
+ b43_radio_write(dev, 0x4a, e->radio_syn4a);
+ b43_radio_write(dev, 0x58, e->radio_syn58);
+ b43_radio_write(dev, 0x5a, e->radio_syn5a);
+ b43_radio_write(dev, 0x6a, e->radio_syn6a);
+ b43_radio_write(dev, 0x6d, e->radio_syn6d);
+ b43_radio_write(dev, 0x6e, e->radio_syn6e);
+ b43_radio_write(dev, 0x92, e->radio_syn92);
+ b43_radio_write(dev, 0x98, e->radio_syn98);
+
+ for (i = 0; i < 2; i++) {
+ routing = i ? R2059_RXRX1 : R2059_TXRX0;
+ b43_radio_write(dev, routing | 0x4a, e->radio_rxtx4a);
+ b43_radio_write(dev, routing | 0x58, e->radio_rxtx58);
+ b43_radio_write(dev, routing | 0x5a, e->radio_rxtx5a);
+ b43_radio_write(dev, routing | 0x6a, e->radio_rxtx6a);
+ b43_radio_write(dev, routing | 0x6d, e->radio_rxtx6d);
+ b43_radio_write(dev, routing | 0x6e, e->radio_rxtx6e);
+ b43_radio_write(dev, routing | 0x92, e->radio_rxtx92);
+ b43_radio_write(dev, routing | 0x98, e->radio_rxtx98);
+ }
+
+ udelay(50);
+
+ /* Calibration */
+ b43_radio_mask(dev, 0x2b, ~0x1);
+ b43_radio_mask(dev, 0x2e, ~0x4);
+ b43_radio_set(dev, 0x2e, 0x4);
+ b43_radio_set(dev, 0x2b, 0x1);
+
+ udelay(300);
+}
+
+static void b43_radio_2059_init(struct b43_wldev *dev)
+{
+ const u16 routing[] = { R2059_SYN, R2059_TXRX0, R2059_RXRX1 };
+ const u16 radio_values[3][2] = {
+ { 0x61, 0xE9 }, { 0x69, 0xD5 }, { 0x73, 0x99 },
+ };
+ u16 i, j;
+
+ b43_radio_write(dev, R2059_ALL | 0x51, 0x0070);
+ b43_radio_write(dev, R2059_ALL | 0x5a, 0x0003);
+
+ for (i = 0; i < ARRAY_SIZE(routing); i++)
+ b43_radio_set(dev, routing[i] | 0x146, 0x3);
+
+ b43_radio_set(dev, 0x2e, 0x0078);
+ b43_radio_set(dev, 0xc0, 0x0080);
+ msleep(2);
+ b43_radio_mask(dev, 0x2e, ~0x0078);
+ b43_radio_mask(dev, 0xc0, ~0x0080);
+
+ if (1) { /* FIXME */
+ b43_radio_set(dev, R2059_RXRX1 | 0x4, 0x1);
+ udelay(10);
+ b43_radio_set(dev, R2059_RXRX1 | 0x0BF, 0x1);
+ b43_radio_maskset(dev, R2059_RXRX1 | 0x19B, 0x3, 0x2);
+
+ b43_radio_set(dev, R2059_RXRX1 | 0x4, 0x2);
+ udelay(100);
+ b43_radio_mask(dev, R2059_RXRX1 | 0x4, ~0x2);
+
+ for (i = 0; i < 10000; i++) {
+ if (b43_radio_read(dev, R2059_RXRX1 | 0x145) & 1) {
+ i = 0;
+ break;
+ }
+ udelay(100);
+ }
+ if (i)
+ b43err(dev->wl, "radio 0x945 timeout\n");
+
+ b43_radio_mask(dev, R2059_RXRX1 | 0x4, ~0x1);
+ b43_radio_set(dev, 0xa, 0x60);
+
+ for (i = 0; i < 3; i++) {
+ b43_radio_write(dev, 0x17F, radio_values[i][0]);
+ b43_radio_write(dev, 0x13D, 0x6E);
+ b43_radio_write(dev, 0x13E, radio_values[i][1]);
+ b43_radio_write(dev, 0x13C, 0x55);
+
+ for (j = 0; j < 10000; j++) {
+ if (b43_radio_read(dev, 0x140) & 2) {
+ j = 0;
+ break;
+ }
+ udelay(500);
+ }
+ if (j)
+ b43err(dev->wl, "radio 0x140 timeout\n");
+
+ b43_radio_write(dev, 0x13C, 0x15);
+ }
+
+ b43_radio_mask(dev, 0x17F, ~0x1);
+ }
+
+ b43_radio_mask(dev, 0x11, 0x0008);
+}
+
+/**************************************************
+ * Channel switching ops.
+ **************************************************/
+
+static void b43_phy_ht_channel_setup(struct b43_wldev *dev,
+ const struct b43_phy_ht_channeltab_e_phy *e,
+ struct ieee80211_channel *new_channel)
+{
+ bool old_band_5ghz;
+ u8 i;
+
+ old_band_5ghz = b43_phy_read(dev, B43_PHY_HT_BANDCTL) & 0; /* FIXME */
+ if (new_channel->band == IEEE80211_BAND_5GHZ && !old_band_5ghz) {
+ /* TODO */
+ } else if (new_channel->band == IEEE80211_BAND_2GHZ && old_band_5ghz) {
+ /* TODO */
+ }
+
+ b43_phy_write(dev, B43_PHY_HT_BW1, e->bw1);
+ b43_phy_write(dev, B43_PHY_HT_BW2, e->bw2);
+ b43_phy_write(dev, B43_PHY_HT_BW3, e->bw3);
+ b43_phy_write(dev, B43_PHY_HT_BW4, e->bw4);
+ b43_phy_write(dev, B43_PHY_HT_BW5, e->bw5);
+ b43_phy_write(dev, B43_PHY_HT_BW6, e->bw6);
+
+ /* TODO: some ops on PHY regs 0x0B0 and 0xC0A */
+
+ /* TODO: separated function? */
+ for (i = 0; i < 3; i++) {
+ u16 mask;
+ u32 tmp = b43_httab_read(dev, B43_HTTAB32(26, 0xE8));
+
+ if (0) /* FIXME */
+ mask = 0x2 << (i * 4);
+ else
+ mask = 0;
+ b43_phy_mask(dev, B43_PHY_EXTG(0x108), mask);
+
+ b43_httab_write(dev, B43_HTTAB16(7, 0x110 + i), tmp >> 16);
+ b43_httab_write(dev, B43_HTTAB8(13, 0x63 + (i * 4)),
+ tmp & 0xFF);
+ b43_httab_write(dev, B43_HTTAB8(13, 0x73 + (i * 4)),
+ tmp & 0xFF);
+ }
+
+ b43_phy_write(dev, 0x017e, 0x3830);
+}
+
+static int b43_phy_ht_set_channel(struct b43_wldev *dev,
+ struct ieee80211_channel *channel,
+ enum nl80211_channel_type channel_type)
+{
+ struct b43_phy *phy = &dev->phy;
+
+ const struct b43_phy_ht_channeltab_e_radio2059 *chent_r2059 = NULL;
+
+ if (phy->radio_ver == 0x2059) {
+ chent_r2059 = b43_phy_ht_get_channeltab_e_r2059(dev,
+ channel->center_freq);
+ if (!chent_r2059)
+ return -ESRCH;
+ } else {
+ return -ESRCH;
+ }
+
+ /* TODO: In case of N-PHY some bandwidth switching goes here */
+
+ if (phy->radio_ver == 0x2059) {
+ b43_radio_2059_channel_setup(dev, chent_r2059);
+ b43_phy_ht_channel_setup(dev, &(chent_r2059->phy_regs),
+ channel);
+ } else {
+ return -ESRCH;
+ }
+
+ return 0;
+}
+
+/**************************************************
+ * Basic PHY ops.
+ **************************************************/
+
+static int b43_phy_ht_op_allocate(struct b43_wldev *dev)
+{
+ struct b43_phy_ht *phy_ht;
+
+ phy_ht = kzalloc(sizeof(*phy_ht), GFP_KERNEL);
+ if (!phy_ht)
+ return -ENOMEM;
+ dev->phy.ht = phy_ht;
+
+ return 0;
+}
+
+static void b43_phy_ht_op_prepare_structs(struct b43_wldev *dev)
+{
+ struct b43_phy *phy = &dev->phy;
+ struct b43_phy_ht *phy_ht = phy->ht;
+
+ memset(phy_ht, 0, sizeof(*phy_ht));
+}
+
+static int b43_phy_ht_op_init(struct b43_wldev *dev)
+{
+ b43_phy_ht_tables_init(dev);
+
+ return 0;
+}
+
+static void b43_phy_ht_op_free(struct b43_wldev *dev)
+{
+ struct b43_phy *phy = &dev->phy;
+ struct b43_phy_ht *phy_ht = phy->ht;
+
+ kfree(phy_ht);
+ phy->ht = NULL;
+}
+
+/* http://bcm-v4.sipsolutions.net/802.11/Radio/Switch%20Radio */
+static void b43_phy_ht_op_software_rfkill(struct b43_wldev *dev,
+ bool blocked)
+{
+ if (b43_read32(dev, B43_MMIO_MACCTL) & B43_MACCTL_ENABLED)
+ b43err(dev->wl, "MAC not suspended\n");
+
+ if (blocked) {
+ b43_phy_mask(dev, B43_PHY_HT_RF_CTL1, ~0);
+ } else {
+ b43_phy_mask(dev, B43_PHY_HT_RF_CTL1, ~0);
+ b43_phy_maskset(dev, B43_PHY_HT_RF_CTL1, ~0, 0x1);
+ b43_phy_mask(dev, B43_PHY_HT_RF_CTL1, ~0);
+ b43_phy_maskset(dev, B43_PHY_HT_RF_CTL1, ~0, 0x2);
+
+ if (dev->phy.radio_ver == 0x2059)
+ b43_radio_2059_init(dev);
+ else
+ B43_WARN_ON(1);
+ }
+}
+
+static void b43_phy_ht_op_switch_analog(struct b43_wldev *dev, bool on)
+{
+ if (on) {
+ b43_phy_write(dev, B43_PHY_HT_AFE_CTL2, 0x00cd);
+ b43_phy_write(dev, B43_PHY_HT_AFE_CTL1, 0x0000);
+ b43_phy_write(dev, B43_PHY_HT_AFE_CTL4, 0x00cd);
+ b43_phy_write(dev, B43_PHY_HT_AFE_CTL3, 0x0000);
+ b43_phy_write(dev, B43_PHY_HT_AFE_CTL6, 0x00cd);
+ b43_phy_write(dev, B43_PHY_HT_AFE_CTL5, 0x0000);
+ } else {
+ b43_phy_write(dev, B43_PHY_HT_AFE_CTL1, 0x07ff);
+ b43_phy_write(dev, B43_PHY_HT_AFE_CTL2, 0x00fd);
+ b43_phy_write(dev, B43_PHY_HT_AFE_CTL3, 0x07ff);
+ b43_phy_write(dev, B43_PHY_HT_AFE_CTL4, 0x00fd);
+ b43_phy_write(dev, B43_PHY_HT_AFE_CTL5, 0x07ff);
+ b43_phy_write(dev, B43_PHY_HT_AFE_CTL6, 0x00fd);
+ }
+}
+
+static int b43_phy_ht_op_switch_channel(struct b43_wldev *dev,
+ unsigned int new_channel)
+{
+ struct ieee80211_channel *channel = dev->wl->hw->conf.channel;
+ enum nl80211_channel_type channel_type = dev->wl->hw->conf.channel_type;
+
+ if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
+ if ((new_channel < 1) || (new_channel > 14))
+ return -EINVAL;
+ } else {
+ return -EINVAL;
+ }
+
+ return b43_phy_ht_set_channel(dev, channel, channel_type);
+}
+
+static unsigned int b43_phy_ht_op_get_default_chan(struct b43_wldev *dev)
+{
+ if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
+ return 1;
+ return 36;
+}
+
+/**************************************************
+ * R/W ops.
+ **************************************************/
+
+static u16 b43_phy_ht_op_read(struct b43_wldev *dev, u16 reg)
+{
+ b43_write16(dev, B43_MMIO_PHY_CONTROL, reg);
+ return b43_read16(dev, B43_MMIO_PHY_DATA);
+}
+
+static void b43_phy_ht_op_write(struct b43_wldev *dev, u16 reg, u16 value)
+{
+ b43_write16(dev, B43_MMIO_PHY_CONTROL, reg);
+ b43_write16(dev, B43_MMIO_PHY_DATA, value);
+}
+
+static void b43_phy_ht_op_maskset(struct b43_wldev *dev, u16 reg, u16 mask,
+ u16 set)
+{
+ b43_write16(dev, B43_MMIO_PHY_CONTROL, reg);
+ b43_write16(dev, B43_MMIO_PHY_DATA,
+ (b43_read16(dev, B43_MMIO_PHY_DATA) & mask) | set);
+}
+
+static u16 b43_phy_ht_op_radio_read(struct b43_wldev *dev, u16 reg)
+{
+ /* HT-PHY needs 0x200 for read access */
+ reg |= 0x200;
+
+ b43_write16(dev, B43_MMIO_RADIO24_CONTROL, reg);
+ return b43_read16(dev, B43_MMIO_RADIO24_DATA);
+}
+
+static void b43_phy_ht_op_radio_write(struct b43_wldev *dev, u16 reg,
+ u16 value)
+{
+ b43_write16(dev, B43_MMIO_RADIO24_CONTROL, reg);
+ b43_write16(dev, B43_MMIO_RADIO24_DATA, value);
+}
+
+/**************************************************
+ * PHY ops struct.
+ **************************************************/
+
+const struct b43_phy_operations b43_phyops_ht = {
+ .allocate = b43_phy_ht_op_allocate,
+ .free = b43_phy_ht_op_free,
+ .prepare_structs = b43_phy_ht_op_prepare_structs,
+ .init = b43_phy_ht_op_init,
+ .phy_read = b43_phy_ht_op_read,
+ .phy_write = b43_phy_ht_op_write,
+ .phy_maskset = b43_phy_ht_op_maskset,
+ .radio_read = b43_phy_ht_op_radio_read,
+ .radio_write = b43_phy_ht_op_radio_write,
+ .software_rfkill = b43_phy_ht_op_software_rfkill,
+ .switch_analog = b43_phy_ht_op_switch_analog,
+ .switch_channel = b43_phy_ht_op_switch_channel,
+ .get_default_chan = b43_phy_ht_op_get_default_chan,
+ /*
+ .recalc_txpower = b43_phy_ht_op_recalc_txpower,
+ .adjust_txpower = b43_phy_ht_op_adjust_txpower,
+ */
+};
diff --git a/drivers/net/wireless/b43/phy_ht.h b/drivers/net/wireless/b43/phy_ht.h
new file mode 100644
index 0000000..7ad7aff
--- /dev/null
+++ b/drivers/net/wireless/b43/phy_ht.h
@@ -0,0 +1,46 @@
+#ifndef B43_PHY_HT_H_
+#define B43_PHY_HT_H_
+
+#include "phy_common.h"
+
+
+#define B43_PHY_HT_BANDCTL 0x009 /* Band control */
+#define B43_PHY_HT_TABLE_ADDR 0x072 /* Table address */
+#define B43_PHY_HT_TABLE_DATALO 0x073 /* Table data low */
+#define B43_PHY_HT_TABLE_DATAHI 0x074 /* Table data high */
+#define B43_PHY_HT_BW1 0x1CE
+#define B43_PHY_HT_BW2 0x1CF
+#define B43_PHY_HT_BW3 0x1D0
+#define B43_PHY_HT_BW4 0x1D1
+#define B43_PHY_HT_BW5 0x1D2
+#define B43_PHY_HT_BW6 0x1D3
+
+#define B43_PHY_HT_RF_CTL1 B43_PHY_EXTG(0x010)
+
+#define B43_PHY_HT_AFE_CTL1 B43_PHY_EXTG(0x110)
+#define B43_PHY_HT_AFE_CTL2 B43_PHY_EXTG(0x111)
+#define B43_PHY_HT_AFE_CTL3 B43_PHY_EXTG(0x114)
+#define B43_PHY_HT_AFE_CTL4 B43_PHY_EXTG(0x115)
+#define B43_PHY_HT_AFE_CTL5 B43_PHY_EXTG(0x118)
+#define B43_PHY_HT_AFE_CTL6 B43_PHY_EXTG(0x119)
+
+
+/* Values for PHY registers used on channel switching */
+struct b43_phy_ht_channeltab_e_phy {
+ u16 bw1;
+ u16 bw2;
+ u16 bw3;
+ u16 bw4;
+ u16 bw5;
+ u16 bw6;
+};
+
+
+struct b43_phy_ht {
+};
+
+
+struct b43_phy_operations;
+extern const struct b43_phy_operations b43_phyops_ht;
+
+#endif /* B43_PHY_HT_H_ */
diff --git a/drivers/net/wireless/b43/phy_lp.c b/drivers/net/wireless/b43/phy_lp.c
index 012c8da..daec1d9 100644
--- a/drivers/net/wireless/b43/phy_lp.c
+++ b/drivers/net/wireless/b43/phy_lp.c
@@ -85,39 +85,39 @@
/* http://bcm-v4.sipsolutions.net/802.11/PHY/LP/ReadBandSrom */
static void lpphy_read_band_sprom(struct b43_wldev *dev)
{
+ struct ssb_sprom *sprom = dev->dev->bus_sprom;
struct b43_phy_lp *lpphy = dev->phy.lp;
- struct ssb_bus *bus = dev->sdev->bus;
u16 cckpo, maxpwr;
u32 ofdmpo;
int i;
if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
- lpphy->tx_isolation_med_band = bus->sprom.tri2g;
- lpphy->bx_arch = bus->sprom.bxa2g;
- lpphy->rx_pwr_offset = bus->sprom.rxpo2g;
- lpphy->rssi_vf = bus->sprom.rssismf2g;
- lpphy->rssi_vc = bus->sprom.rssismc2g;
- lpphy->rssi_gs = bus->sprom.rssisav2g;
- lpphy->txpa[0] = bus->sprom.pa0b0;
- lpphy->txpa[1] = bus->sprom.pa0b1;
- lpphy->txpa[2] = bus->sprom.pa0b2;
- maxpwr = bus->sprom.maxpwr_bg;
+ lpphy->tx_isolation_med_band = sprom->tri2g;
+ lpphy->bx_arch = sprom->bxa2g;
+ lpphy->rx_pwr_offset = sprom->rxpo2g;
+ lpphy->rssi_vf = sprom->rssismf2g;
+ lpphy->rssi_vc = sprom->rssismc2g;
+ lpphy->rssi_gs = sprom->rssisav2g;
+ lpphy->txpa[0] = sprom->pa0b0;
+ lpphy->txpa[1] = sprom->pa0b1;
+ lpphy->txpa[2] = sprom->pa0b2;
+ maxpwr = sprom->maxpwr_bg;
lpphy->max_tx_pwr_med_band = maxpwr;
- cckpo = bus->sprom.cck2gpo;
+ cckpo = sprom->cck2gpo;
/*
* We don't read SPROM's opo as specs say. On rev8 SPROMs
* opo == ofdm2gpo and we don't know any SSB with LP-PHY
* and SPROM rev below 8.
*/
- B43_WARN_ON(bus->sprom.revision < 8);
- ofdmpo = bus->sprom.ofdm2gpo;
+ B43_WARN_ON(sprom->revision < 8);
+ ofdmpo = sprom->ofdm2gpo;
if (cckpo) {
for (i = 0; i < 4; i++) {
lpphy->tx_max_rate[i] =
maxpwr - (ofdmpo & 0xF) * 2;
ofdmpo >>= 4;
}
- ofdmpo = bus->sprom.ofdm2gpo;
+ ofdmpo = sprom->ofdm2gpo;
for (i = 4; i < 15; i++) {
lpphy->tx_max_rate[i] =
maxpwr - (ofdmpo & 0xF) * 2;
@@ -131,39 +131,39 @@
lpphy->tx_max_rate[i] = maxpwr - ofdmpo;
}
} else { /* 5GHz */
- lpphy->tx_isolation_low_band = bus->sprom.tri5gl;
- lpphy->tx_isolation_med_band = bus->sprom.tri5g;
- lpphy->tx_isolation_hi_band = bus->sprom.tri5gh;
- lpphy->bx_arch = bus->sprom.bxa5g;
- lpphy->rx_pwr_offset = bus->sprom.rxpo5g;
- lpphy->rssi_vf = bus->sprom.rssismf5g;
- lpphy->rssi_vc = bus->sprom.rssismc5g;
- lpphy->rssi_gs = bus->sprom.rssisav5g;
- lpphy->txpa[0] = bus->sprom.pa1b0;
- lpphy->txpa[1] = bus->sprom.pa1b1;
- lpphy->txpa[2] = bus->sprom.pa1b2;
- lpphy->txpal[0] = bus->sprom.pa1lob0;
- lpphy->txpal[1] = bus->sprom.pa1lob1;
- lpphy->txpal[2] = bus->sprom.pa1lob2;
- lpphy->txpah[0] = bus->sprom.pa1hib0;
- lpphy->txpah[1] = bus->sprom.pa1hib1;
- lpphy->txpah[2] = bus->sprom.pa1hib2;
- maxpwr = bus->sprom.maxpwr_al;
- ofdmpo = bus->sprom.ofdm5glpo;
+ lpphy->tx_isolation_low_band = sprom->tri5gl;
+ lpphy->tx_isolation_med_band = sprom->tri5g;
+ lpphy->tx_isolation_hi_band = sprom->tri5gh;
+ lpphy->bx_arch = sprom->bxa5g;
+ lpphy->rx_pwr_offset = sprom->rxpo5g;
+ lpphy->rssi_vf = sprom->rssismf5g;
+ lpphy->rssi_vc = sprom->rssismc5g;
+ lpphy->rssi_gs = sprom->rssisav5g;
+ lpphy->txpa[0] = sprom->pa1b0;
+ lpphy->txpa[1] = sprom->pa1b1;
+ lpphy->txpa[2] = sprom->pa1b2;
+ lpphy->txpal[0] = sprom->pa1lob0;
+ lpphy->txpal[1] = sprom->pa1lob1;
+ lpphy->txpal[2] = sprom->pa1lob2;
+ lpphy->txpah[0] = sprom->pa1hib0;
+ lpphy->txpah[1] = sprom->pa1hib1;
+ lpphy->txpah[2] = sprom->pa1hib2;
+ maxpwr = sprom->maxpwr_al;
+ ofdmpo = sprom->ofdm5glpo;
lpphy->max_tx_pwr_low_band = maxpwr;
for (i = 4; i < 12; i++) {
lpphy->tx_max_ratel[i] = maxpwr - (ofdmpo & 0xF) * 2;
ofdmpo >>= 4;
}
- maxpwr = bus->sprom.maxpwr_a;
- ofdmpo = bus->sprom.ofdm5gpo;
+ maxpwr = sprom->maxpwr_a;
+ ofdmpo = sprom->ofdm5gpo;
lpphy->max_tx_pwr_med_band = maxpwr;
for (i = 4; i < 12; i++) {
lpphy->tx_max_rate[i] = maxpwr - (ofdmpo & 0xF) * 2;
ofdmpo >>= 4;
}
- maxpwr = bus->sprom.maxpwr_ah;
- ofdmpo = bus->sprom.ofdm5ghpo;
+ maxpwr = sprom->maxpwr_ah;
+ ofdmpo = sprom->ofdm5ghpo;
lpphy->max_tx_pwr_hi_band = maxpwr;
for (i = 4; i < 12; i++) {
lpphy->tx_max_rateh[i] = maxpwr - (ofdmpo & 0xF) * 2;
@@ -214,7 +214,8 @@
static void lpphy_baseband_rev0_1_init(struct b43_wldev *dev)
{
- struct ssb_bus *bus = dev->sdev->bus;
+ struct ssb_bus *bus = dev->dev->sdev->bus;
+ struct ssb_sprom *sprom = dev->dev->bus_sprom;
struct b43_phy_lp *lpphy = dev->phy.lp;
u16 tmp, tmp2;
@@ -242,9 +243,9 @@
b43_phy_maskset(dev, B43_LPPHY_CRS_ED_THRESH, 0x00FF, 0xAD00);
b43_phy_maskset(dev, B43_LPPHY_INPUT_PWRDB,
0xFF00, lpphy->rx_pwr_offset);
- if ((bus->sprom.boardflags_lo & B43_BFL_FEM) &&
+ if ((sprom->boardflags_lo & B43_BFL_FEM) &&
((b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) ||
- (bus->sprom.boardflags_hi & B43_BFH_PAREF))) {
+ (sprom->boardflags_hi & B43_BFH_PAREF))) {
ssb_pmu_set_ldo_voltage(&bus->chipco, LDO_PAREF, 0x28);
ssb_pmu_set_ldo_paref(&bus->chipco, true);
if (dev->phy.rev == 0) {
@@ -260,7 +261,7 @@
}
tmp = lpphy->rssi_vf | lpphy->rssi_vc << 4 | 0xA000;
b43_phy_write(dev, B43_LPPHY_AFE_RSSI_CTL_0, tmp);
- if (bus->sprom.boardflags_hi & B43_BFH_RSSIINV)
+ if (sprom->boardflags_hi & B43_BFH_RSSIINV)
b43_phy_maskset(dev, B43_LPPHY_AFE_RSSI_CTL_1, 0xF000, 0x0AAA);
else
b43_phy_maskset(dev, B43_LPPHY_AFE_RSSI_CTL_1, 0xF000, 0x02AA);
@@ -268,7 +269,7 @@
b43_phy_maskset(dev, B43_LPPHY_RX_RADIO_CTL,
0xFFF9, (lpphy->bx_arch << 1));
if (dev->phy.rev == 1 &&
- (bus->sprom.boardflags_hi & B43_BFH_FEM_BT)) {
+ (sprom->boardflags_hi & B43_BFH_FEM_BT)) {
b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_1, 0xFFC0, 0x000A);
b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_1, 0x3F00, 0x0900);
b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_2, 0xFFC0, 0x000A);
@@ -286,8 +287,8 @@
b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_8, 0xFFC0, 0x000A);
b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_8, 0xC0FF, 0x0B00);
} else if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ ||
- (bus->boardinfo.type == 0x048A) || ((dev->phy.rev == 0) &&
- (bus->sprom.boardflags_lo & B43_BFL_FEM))) {
+ (dev->dev->board_type == 0x048A) || ((dev->phy.rev == 0) &&
+ (sprom->boardflags_lo & B43_BFL_FEM))) {
b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_1, 0xFFC0, 0x0001);
b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_1, 0xC0FF, 0x0400);
b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_2, 0xFFC0, 0x0001);
@@ -297,7 +298,7 @@
b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_4, 0xFFC0, 0x0002);
b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_4, 0xC0FF, 0x0A00);
} else if (dev->phy.rev == 1 ||
- (bus->sprom.boardflags_lo & B43_BFL_FEM)) {
+ (sprom->boardflags_lo & B43_BFL_FEM)) {
b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_1, 0xFFC0, 0x0004);
b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_1, 0xC0FF, 0x0800);
b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_2, 0xFFC0, 0x0004);
@@ -316,15 +317,15 @@
b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_4, 0xFFC0, 0x0006);
b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_4, 0xC0FF, 0x0700);
}
- if (dev->phy.rev == 1 && (bus->sprom.boardflags_hi & B43_BFH_PAREF)) {
+ if (dev->phy.rev == 1 && (sprom->boardflags_hi & B43_BFH_PAREF)) {
b43_phy_copy(dev, B43_LPPHY_TR_LOOKUP_5, B43_LPPHY_TR_LOOKUP_1);
b43_phy_copy(dev, B43_LPPHY_TR_LOOKUP_6, B43_LPPHY_TR_LOOKUP_2);
b43_phy_copy(dev, B43_LPPHY_TR_LOOKUP_7, B43_LPPHY_TR_LOOKUP_3);
b43_phy_copy(dev, B43_LPPHY_TR_LOOKUP_8, B43_LPPHY_TR_LOOKUP_4);
}
- if ((bus->sprom.boardflags_hi & B43_BFH_FEM_BT) &&
- (bus->chip_id == 0x5354) &&
- (bus->chip_package == SSB_CHIPPACK_BCM4712S)) {
+ if ((sprom->boardflags_hi & B43_BFH_FEM_BT) &&
+ (dev->dev->chip_id == 0x5354) &&
+ (dev->dev->chip_pkg == SSB_CHIPPACK_BCM4712S)) {
b43_phy_set(dev, B43_LPPHY_CRSGAIN_CTL, 0x0006);
b43_phy_write(dev, B43_LPPHY_GPIO_SELECT, 0x0005);
b43_phy_write(dev, B43_LPPHY_GPIO_OUTEN, 0xFFFF);
@@ -412,7 +413,6 @@
static void lpphy_baseband_rev2plus_init(struct b43_wldev *dev)
{
- struct ssb_bus *bus = dev->sdev->bus;
struct b43_phy_lp *lpphy = dev->phy.lp;
b43_phy_write(dev, B43_LPPHY_AFE_DAC_CTL, 0x50);
@@ -432,7 +432,7 @@
b43_phy_mask(dev, B43_LPPHY_CRSGAIN_CTL, ~0x4000);
b43_phy_mask(dev, B43_LPPHY_CRSGAIN_CTL, ~0x2000);
b43_phy_set(dev, B43_PHY_OFDM(0x10A), 0x1);
- if (bus->boardinfo.rev >= 0x18) {
+ if (dev->dev->board_rev >= 0x18) {
b43_lptab_write(dev, B43_LPTAB32(17, 65), 0xEC);
b43_phy_maskset(dev, B43_PHY_OFDM(0x10A), 0xFF01, 0x14);
} else {
@@ -449,7 +449,7 @@
b43_phy_maskset(dev, B43_LPPHY_CLIPCTRTHRESH, 0xFC1F, 0xA0);
b43_phy_maskset(dev, B43_LPPHY_GAINDIRECTMISMATCH, 0xE0FF, 0x300);
b43_phy_maskset(dev, B43_LPPHY_HIGAINDB, 0x00FF, 0x2A00);
- if ((bus->chip_id == 0x4325) && (bus->chip_rev == 0)) {
+ if ((dev->dev->chip_id == 0x4325) && (dev->dev->chip_rev == 0)) {
b43_phy_maskset(dev, B43_LPPHY_LOWGAINDB, 0x00FF, 0x2100);
b43_phy_maskset(dev, B43_LPPHY_VERYLOWGAINDB, 0xFF00, 0xA);
} else {
@@ -467,7 +467,7 @@
b43_phy_maskset(dev, B43_LPPHY_CLIPCTRTHRESH, 0xFFE0, 0x12);
b43_phy_maskset(dev, B43_LPPHY_GAINMISMATCH, 0x0FFF, 0x9000);
- if ((bus->chip_id == 0x4325) && (bus->chip_rev == 0)) {
+ if ((dev->dev->chip_id == 0x4325) && (dev->dev->chip_rev == 0)) {
b43_lptab_write(dev, B43_LPTAB16(0x08, 0x14), 0);
b43_lptab_write(dev, B43_LPTAB16(0x08, 0x12), 0x40);
}
@@ -492,7 +492,7 @@
0x2000 | ((u16)lpphy->rssi_gs << 10) |
((u16)lpphy->rssi_vc << 4) | lpphy->rssi_vf);
- if ((bus->chip_id == 0x4325) && (bus->chip_rev == 0)) {
+ if ((dev->dev->chip_id == 0x4325) && (dev->dev->chip_rev == 0)) {
b43_phy_set(dev, B43_LPPHY_AFE_ADC_CTL_0, 0x1C);
b43_phy_maskset(dev, B43_LPPHY_AFE_CTL, 0x00FF, 0x8800);
b43_phy_maskset(dev, B43_LPPHY_AFE_ADC_CTL_1, 0xFC3C, 0x0400);
@@ -519,7 +519,7 @@
static void lpphy_2062_init(struct b43_wldev *dev)
{
struct b43_phy_lp *lpphy = dev->phy.lp;
- struct ssb_bus *bus = dev->sdev->bus;
+ struct ssb_bus *bus = dev->dev->sdev->bus;
u32 crystalfreq, tmp, ref;
unsigned int i;
const struct b2062_freqdata *fd = NULL;
@@ -697,7 +697,7 @@
lpphy_sync_stx(dev);
b43_phy_write(dev, B43_PHY_OFDM(0xF0), 0x5F80);
b43_phy_write(dev, B43_PHY_OFDM(0xF1), 0);
- if (dev->sdev->bus->chip_id == 0x4325) {
+ if (dev->dev->chip_id == 0x4325) {
// TODO SSB PMU recalibration
}
}
@@ -1289,7 +1289,7 @@
static void lpphy_rev2plus_rc_calib(struct b43_wldev *dev)
{
- struct ssb_bus *bus = dev->sdev->bus;
+ struct ssb_bus *bus = dev->dev->sdev->bus;
u32 crystal_freq = bus->chipco.pmu.crystalfreq * 1000;
u8 tmp = b43_radio_read(dev, B2063_RX_BB_SP8) & 0xFF;
int i;
@@ -1840,7 +1840,6 @@
static void lpphy_papd_cal_txpwr(struct b43_wldev *dev)
{
struct b43_phy_lp *lpphy = dev->phy.lp;
- struct ssb_bus *bus = dev->sdev->bus;
struct lpphy_tx_gains gains, oldgains;
int old_txpctl, old_afe_ovr, old_rf, old_bbmult;
@@ -1854,7 +1853,7 @@
lpphy_set_tx_power_control(dev, B43_LPPHY_TXPCTL_OFF);
- if (bus->chip_id == 0x4325 && bus->chip_rev == 0)
+ if (dev->dev->chip_id == 0x4325 && dev->dev->chip_rev == 0)
lpphy_papd_cal(dev, gains, 0, 1, 30);
else
lpphy_papd_cal(dev, gains, 0, 1, 65);
@@ -1870,7 +1869,6 @@
bool rx, bool pa, struct lpphy_tx_gains *gains)
{
struct b43_phy_lp *lpphy = dev->phy.lp;
- struct ssb_bus *bus = dev->sdev->bus;
const struct lpphy_rx_iq_comp *iqcomp = NULL;
struct lpphy_tx_gains nogains, oldgains;
u16 tmp;
@@ -1879,7 +1877,7 @@
memset(&nogains, 0, sizeof(nogains));
memset(&oldgains, 0, sizeof(oldgains));
- if (bus->chip_id == 0x5354) {
+ if (dev->dev->chip_id == 0x5354) {
for (i = 0; i < ARRAY_SIZE(lpphy_5354_iq_table); i++) {
if (lpphy_5354_iq_table[i].chan == lpphy->channel) {
iqcomp = &lpphy_5354_iq_table[i];
@@ -2408,11 +2406,9 @@
static void lpphy_b2062_reset_pll_bias(struct b43_wldev *dev)
{
- struct ssb_bus *bus = dev->sdev->bus;
-
b43_radio_write(dev, B2062_S_RFPLL_CTL2, 0xFF);
udelay(20);
- if (bus->chip_id == 0x5354) {
+ if (dev->dev->chip_id == 0x5354) {
b43_radio_write(dev, B2062_N_COMM1, 4);
b43_radio_write(dev, B2062_S_RFPLL_CTL2, 4);
} else {
@@ -2432,7 +2428,7 @@
unsigned int channel)
{
struct b43_phy_lp *lpphy = dev->phy.lp;
- struct ssb_bus *bus = dev->sdev->bus;
+ struct ssb_bus *bus = dev->dev->sdev->bus;
const struct b206x_channel *chandata = NULL;
u32 crystal_freq = bus->chipco.pmu.crystalfreq * 1000;
u32 tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8, tmp9;
@@ -2522,7 +2518,7 @@
static int lpphy_b2063_tune(struct b43_wldev *dev,
unsigned int channel)
{
- struct ssb_bus *bus = dev->sdev->bus;
+ struct ssb_bus *bus = dev->dev->sdev->bus;
static const struct b206x_channel *chandata = NULL;
u32 crystal_freq = bus->chipco.pmu.crystalfreq * 1000;
@@ -2670,6 +2666,11 @@
{
int err;
+ if (dev->dev->bus_type != B43_BUS_SSB) {
+ b43err(dev->wl, "LP-PHY is supported only on SSB!\n");
+ return -EOPNOTSUPP;
+ }
+
lpphy_read_band_sprom(dev); //FIXME should this be in prepare_structs?
lpphy_baseband_init(dev);
lpphy_radio_init(dev);
diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c
index 05960dd..e7dfdac 100644
--- a/drivers/net/wireless/b43/phy_n.c
+++ b/drivers/net/wireless/b43/phy_n.c
@@ -299,7 +299,7 @@
static void b43_nphy_tx_power_fix(struct b43_wldev *dev)
{
struct b43_phy_n *nphy = dev->phy.n;
- struct ssb_sprom *sprom = &(dev->sdev->bus->sprom);
+ struct ssb_sprom *sprom = dev->dev->bus_sprom;
u8 txpi[2], bbmult, i;
u16 tmp, radio_gain, dac_gain;
@@ -423,16 +423,15 @@
static void b43_radio_init2055_post(struct b43_wldev *dev)
{
struct b43_phy_n *nphy = dev->phy.n;
- struct ssb_sprom *sprom = &(dev->sdev->bus->sprom);
- struct ssb_boardinfo *binfo = &(dev->sdev->bus->boardinfo);
+ struct ssb_sprom *sprom = dev->dev->bus_sprom;
int i;
u16 val;
bool workaround = false;
if (sprom->revision < 4)
- workaround = (binfo->vendor != PCI_VENDOR_ID_BROADCOM &&
- binfo->type == 0x46D &&
- binfo->rev >= 0x41);
+ workaround = (dev->dev->board_vendor != PCI_VENDOR_ID_BROADCOM
+ && dev->dev->board_type == 0x46D
+ && dev->dev->board_rev >= 0x41);
else
workaround =
!(sprom->boardflags2_lo & B43_BFL2_RXBB_INT_REG_DIS);
@@ -983,7 +982,7 @@
{
u16 tmp;
- if (dev->sdev->id.revision == 16)
+ if (dev->dev->core_rev == 16)
b43_mac_suspend(dev);
tmp = b43_phy_read(dev, B43_NPHY_CLASSCTL);
@@ -993,7 +992,7 @@
tmp |= (val & mask);
b43_phy_maskset(dev, B43_NPHY_CLASSCTL, 0xFFF8, tmp);
- if (dev->sdev->id.revision == 16)
+ if (dev->dev->core_rev == 16)
b43_mac_enable(dev);
return tmp;
@@ -1168,7 +1167,7 @@
static void b43_nphy_gain_ctrl_workarounds(struct b43_wldev *dev)
{
struct b43_phy_n *nphy = dev->phy.n;
- struct ssb_sprom *sprom = &(dev->sdev->bus->sprom);
+ struct ssb_sprom *sprom = dev->dev->bus_sprom;
/* PHY rev 0, 1, 2 */
u8 i, j;
@@ -1373,7 +1372,7 @@
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/Workarounds */
static void b43_nphy_workarounds(struct b43_wldev *dev)
{
- struct ssb_bus *bus = dev->sdev->bus;
+ struct ssb_sprom *sprom = dev->dev->bus_sprom;
struct b43_phy *phy = &dev->phy;
struct b43_phy_n *nphy = phy->n;
@@ -1443,9 +1442,9 @@
/* N PHY WAR TX Chain Update with hw_phytxchain as argument */
- if ((bus->sprom.boardflags2_lo & B43_BFL2_APLL_WAR &&
+ if ((sprom->boardflags2_lo & B43_BFL2_APLL_WAR &&
b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) ||
- (bus->sprom.boardflags2_lo & B43_BFL2_GPLL_WAR &&
+ (sprom->boardflags2_lo & B43_BFL2_GPLL_WAR &&
b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ))
tmp32 = 0x00088888;
else
@@ -1503,8 +1502,8 @@
b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO2, 0x2D8);
b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP2, 0x301);
- if (bus->sprom.boardflags2_lo & 0x100 &&
- bus->boardinfo.type == 0x8B) {
+ if (sprom->boardflags2_lo & 0x100 &&
+ dev->dev->board_type == 0x8B) {
delays1[0] = 0x1;
delays1[5] = 0x14;
}
@@ -3586,7 +3585,7 @@
*/
int b43_phy_initn(struct b43_wldev *dev)
{
- struct ssb_bus *bus = dev->sdev->bus;
+ struct ssb_sprom *sprom = dev->dev->bus_sprom;
struct b43_phy *phy = &dev->phy;
struct b43_phy_n *nphy = phy->n;
u8 tx_pwr_state;
@@ -3599,7 +3598,7 @@
bool do_cal = false;
if ((dev->phy.rev >= 3) &&
- (bus->sprom.boardflags_lo & B43_BFL_EXTLNA) &&
+ (sprom->boardflags_lo & B43_BFL_EXTLNA) &&
(b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)) {
chipco_set32(&dev->sdev->bus->chipco, SSB_CHIPCO_CHIPCTL, 0x40);
}
@@ -3639,9 +3638,9 @@
b43_phy_write(dev, B43_NPHY_AFESEQ_TX2RX_PUD_20M, 0x20);
b43_phy_write(dev, B43_NPHY_AFESEQ_TX2RX_PUD_40M, 0x20);
- if (bus->sprom.boardflags2_lo & 0x100 ||
- (bus->boardinfo.vendor == PCI_VENDOR_ID_APPLE &&
- bus->boardinfo.type == 0x8B))
+ if (sprom->boardflags2_lo & 0x100 ||
+ (dev->dev->board_vendor == PCI_VENDOR_ID_APPLE &&
+ dev->dev->board_type == 0x8B))
b43_phy_write(dev, B43_NPHY_TXREALFD, 0xA0);
else
b43_phy_write(dev, B43_NPHY_TXREALFD, 0xB8);
@@ -4026,11 +4025,24 @@
/* http://bcm-v4.sipsolutions.net/802.11/PHY/Anacore */
static void b43_nphy_op_switch_analog(struct b43_wldev *dev, bool on)
{
- u16 val = on ? 0 : 0x7FFF;
+ u16 override = on ? 0x0 : 0x7FFF;
+ u16 core = on ? 0xD : 0x00FD;
- if (dev->phy.rev >= 3)
- b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, val);
- b43_phy_write(dev, B43_NPHY_AFECTL_OVER, val);
+ if (dev->phy.rev >= 3) {
+ if (on) {
+ b43_phy_write(dev, B43_NPHY_AFECTL_C1, core);
+ b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, override);
+ b43_phy_write(dev, B43_NPHY_AFECTL_C2, core);
+ b43_phy_write(dev, B43_NPHY_AFECTL_OVER, override);
+ } else {
+ b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, override);
+ b43_phy_write(dev, B43_NPHY_AFECTL_C1, core);
+ b43_phy_write(dev, B43_NPHY_AFECTL_OVER, override);
+ b43_phy_write(dev, B43_NPHY_AFECTL_C2, core);
+ }
+ } else {
+ b43_phy_write(dev, B43_NPHY_AFECTL_OVER, override);
+ }
}
static int b43_nphy_op_switch_channel(struct b43_wldev *dev,
diff --git a/drivers/net/wireless/b43/pio.c b/drivers/net/wireless/b43/pio.c
index 72ab94d..44da620 100644
--- a/drivers/net/wireless/b43/pio.c
+++ b/drivers/net/wireless/b43/pio.c
@@ -111,7 +111,7 @@
B43_MMIO_PIO11_BASE5,
};
- if (dev->sdev->id.revision >= 11) {
+ if (dev->dev->core_rev >= 11) {
B43_WARN_ON(index >= ARRAY_SIZE(bases_rev11));
return bases_rev11[index];
}
@@ -121,14 +121,14 @@
static u16 pio_txqueue_offset(struct b43_wldev *dev)
{
- if (dev->sdev->id.revision >= 11)
+ if (dev->dev->core_rev >= 11)
return 0x18;
return 0;
}
static u16 pio_rxqueue_offset(struct b43_wldev *dev)
{
- if (dev->sdev->id.revision >= 11)
+ if (dev->dev->core_rev >= 11)
return 0x38;
return 8;
}
@@ -144,7 +144,7 @@
if (!q)
return NULL;
q->dev = dev;
- q->rev = dev->sdev->id.revision;
+ q->rev = dev->dev->core_rev;
q->mmio_base = index_to_pioqueue_base(dev, index) +
pio_txqueue_offset(dev);
q->index = index;
@@ -178,7 +178,7 @@
if (!q)
return NULL;
q->dev = dev;
- q->rev = dev->sdev->id.revision;
+ q->rev = dev->dev->core_rev;
q->mmio_base = index_to_pioqueue_base(dev, index) +
pio_rxqueue_offset(dev);
diff --git a/drivers/net/wireless/b43/radio_2055.h b/drivers/net/wireless/b43/radio_2055.h
index d9bfa0f..67f9612 100644
--- a/drivers/net/wireless/b43/radio_2055.h
+++ b/drivers/net/wireless/b43/radio_2055.h
@@ -251,4 +251,9 @@
void b2055_upload_inittab(struct b43_wldev *dev,
bool ghz5, bool ignore_uploadflag);
+/* Get the NPHY Channel Switch Table entry for a channel.
+ * Returns NULL on failure to find an entry. */
+const struct b43_nphy_channeltab_entry_rev2 *
+b43_nphy_get_chantabent_rev2(struct b43_wldev *dev, u8 channel);
+
#endif /* B43_RADIO_2055_H_ */
diff --git a/drivers/net/wireless/b43/radio_2056.h b/drivers/net/wireless/b43/radio_2056.h
index d601f6e..d52df6b 100644
--- a/drivers/net/wireless/b43/radio_2056.h
+++ b/drivers/net/wireless/b43/radio_2056.h
@@ -1117,4 +1117,9 @@
void b2056_upload_inittabs(struct b43_wldev *dev,
bool ghz5, bool ignore_uploadflag);
+/* Get the NPHY Channel Switch Table entry for a channel.
+ * Returns NULL on failure to find an entry. */
+const struct b43_nphy_channeltab_entry_rev3 *
+b43_nphy_get_chantabent_rev3(struct b43_wldev *dev, u16 freq);
+
#endif /* B43_RADIO_2056_H_ */
diff --git a/drivers/net/wireless/b43/radio_2059.c b/drivers/net/wireless/b43/radio_2059.c
new file mode 100644
index 0000000..23dea4b
--- /dev/null
+++ b/drivers/net/wireless/b43/radio_2059.c
@@ -0,0 +1,165 @@
+/*
+
+ Broadcom B43 wireless driver
+ IEEE 802.11n 2059 radio device data tables
+
+ 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; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+
+*/
+
+#include "b43.h"
+#include "radio_2059.h"
+
+#define RADIOREGS(r00, r01, r02, r03, r04, r05, r06, r07, r08, r09, \
+ r10, r11, r12, r13, r14, r15, r16, r17, r18, r19, \
+ r20, r21, r22, r23, r24, r25, r26, r27, r28) \
+ .radio_syn16 = r00, \
+ .radio_syn17 = r01, \
+ .radio_syn22 = r02, \
+ .radio_syn25 = r03, \
+ .radio_syn27 = r04, \
+ .radio_syn28 = r05, \
+ .radio_syn29 = r06, \
+ .radio_syn2c = r07, \
+ .radio_syn2d = r08, \
+ .radio_syn37 = r09, \
+ .radio_syn41 = r10, \
+ .radio_syn43 = r11, \
+ .radio_syn47 = r12, \
+ .radio_syn4a = r13, \
+ .radio_syn58 = r14, \
+ .radio_syn5a = r15, \
+ .radio_syn6a = r16, \
+ .radio_syn6d = r17, \
+ .radio_syn6e = r18, \
+ .radio_syn92 = r19, \
+ .radio_syn98 = r20, \
+ .radio_rxtx4a = r21, \
+ .radio_rxtx58 = r22, \
+ .radio_rxtx5a = r23, \
+ .radio_rxtx6a = r24, \
+ .radio_rxtx6d = r25, \
+ .radio_rxtx6e = r26, \
+ .radio_rxtx92 = r27, \
+ .radio_rxtx98 = r28
+
+#define PHYREGS(r0, r1, r2, r3, r4, r5) \
+ .phy_regs.bw1 = r0, \
+ .phy_regs.bw2 = r1, \
+ .phy_regs.bw3 = r2, \
+ .phy_regs.bw4 = r3, \
+ .phy_regs.bw5 = r4, \
+ .phy_regs.bw6 = r5
+
+static const struct b43_phy_ht_channeltab_e_radio2059 b43_phy_ht_channeltab_radio2059[] = {
+ { .freq = 2412,
+ RADIOREGS(0x48, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x6c,
+ 0x09, 0x0f, 0x0a, 0x00, 0x0a, 0x00, 0x61, 0x03,
+ 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
+ 0x00, 0x00, 0x00, 0xf0, 0x00),
+ PHYREGS(0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443),
+ },
+ { .freq = 2417,
+ RADIOREGS(0x4b, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x71,
+ 0x09, 0x0f, 0x0a, 0x00, 0x0a, 0x00, 0x61, 0x03,
+ 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
+ 0x00, 0x00, 0x00, 0xf0, 0x00),
+ PHYREGS(0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441),
+ },
+ { .freq = 2422,
+ RADIOREGS(0x4e, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x76,
+ 0x09, 0x0f, 0x09, 0x00, 0x09, 0x00, 0x61, 0x03,
+ 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
+ 0x00, 0x00, 0x00, 0xf0, 0x00),
+ PHYREGS(0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f),
+ },
+ { .freq = 2427,
+ RADIOREGS(0x52, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x7b,
+ 0x09, 0x0f, 0x09, 0x00, 0x09, 0x00, 0x61, 0x03,
+ 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
+ 0x00, 0x00, 0x00, 0xf0, 0x00),
+ PHYREGS(0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d),
+ },
+ { .freq = 2432,
+ RADIOREGS(0x55, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x80,
+ 0x09, 0x0f, 0x08, 0x00, 0x08, 0x00, 0x61, 0x03,
+ 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
+ 0x00, 0x00, 0x00, 0xf0, 0x00),
+ PHYREGS(0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a),
+ },
+ { .freq = 2437,
+ RADIOREGS(0x58, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x85,
+ 0x09, 0x0f, 0x08, 0x00, 0x08, 0x00, 0x61, 0x03,
+ 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
+ 0x00, 0x00, 0x00, 0xf0, 0x00),
+ PHYREGS(0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438),
+ },
+ { .freq = 2442,
+ RADIOREGS(0x5c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8a,
+ 0x09, 0x0f, 0x07, 0x00, 0x07, 0x00, 0x61, 0x03,
+ 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
+ 0x00, 0x00, 0x00, 0xf0, 0x00),
+ PHYREGS(0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436),
+ },
+ { .freq = 2447,
+ RADIOREGS(0x5f, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8f,
+ 0x09, 0x0f, 0x07, 0x00, 0x07, 0x00, 0x61, 0x03,
+ 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
+ 0x00, 0x00, 0x00, 0xf0, 0x00),
+ PHYREGS(0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434),
+ },
+ { .freq = 2452,
+ RADIOREGS(0x62, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x94,
+ 0x09, 0x0f, 0x07, 0x00, 0x07, 0x00, 0x61, 0x03,
+ 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
+ 0x00, 0x00, 0x00, 0xf0, 0x00),
+ PHYREGS(0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431),
+ },
+ { .freq = 2457,
+ RADIOREGS(0x66, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x99,
+ 0x09, 0x0f, 0x06, 0x00, 0x06, 0x00, 0x61, 0x03,
+ 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
+ 0x00, 0x00, 0x00, 0xf0, 0x00),
+ PHYREGS(0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f),
+ },
+ { .freq = 2462,
+ RADIOREGS(0x69, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x9e,
+ 0x09, 0x0f, 0x06, 0x00, 0x06, 0x00, 0x61, 0x03,
+ 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
+ 0x00, 0x00, 0x00, 0xf0, 0x00),
+ PHYREGS(0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d),
+ },
+ { .freq = 2467,
+ RADIOREGS(0x6c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa3,
+ 0x09, 0x0f, 0x05, 0x00, 0x05, 0x00, 0x61, 0x03,
+ 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
+ 0x00, 0x00, 0x00, 0xf0, 0x00),
+ PHYREGS(0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b),
+ },
+ { .freq = 2472,
+ RADIOREGS(0x70, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa8,
+ 0x09, 0x0f, 0x05, 0x00, 0x05, 0x00, 0x61, 0x03,
+ 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
+ 0x00, 0x00, 0x00, 0xf0, 0x00),
+ PHYREGS(0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429),
+ },
+};
+
+const struct b43_phy_ht_channeltab_e_radio2059
+*b43_phy_ht_get_channeltab_e_r2059(struct b43_wldev *dev, u16 freq)
+{
+ return NULL;
+}
diff --git a/drivers/net/wireless/b43/radio_2059.h b/drivers/net/wireless/b43/radio_2059.h
new file mode 100644
index 0000000..e4d69e5
--- /dev/null
+++ b/drivers/net/wireless/b43/radio_2059.h
@@ -0,0 +1,54 @@
+#ifndef B43_RADIO_2059_H_
+#define B43_RADIO_2059_H_
+
+#include <linux/types.h>
+
+#include "phy_ht.h"
+
+#define R2059_SYN 0x000
+#define R2059_TXRX0 0x400
+#define R2059_RXRX1 0x800
+#define R2059_ALL 0xC00
+
+/* Values for various registers uploaded on channel switching */
+struct b43_phy_ht_channeltab_e_radio2059 {
+ /* The channel frequency in MHz */
+ u16 freq;
+ /* Values for radio registers */
+ u8 radio_syn16;
+ u8 radio_syn17;
+ u8 radio_syn22;
+ u8 radio_syn25;
+ u8 radio_syn27;
+ u8 radio_syn28;
+ u8 radio_syn29;
+ u8 radio_syn2c;
+ u8 radio_syn2d;
+ u8 radio_syn37;
+ u8 radio_syn41;
+ u8 radio_syn43;
+ u8 radio_syn47;
+ u8 radio_syn4a;
+ u8 radio_syn58;
+ u8 radio_syn5a;
+ u8 radio_syn6a;
+ u8 radio_syn6d;
+ u8 radio_syn6e;
+ u8 radio_syn92;
+ u8 radio_syn98;
+ u8 radio_rxtx4a;
+ u8 radio_rxtx58;
+ u8 radio_rxtx5a;
+ u8 radio_rxtx6a;
+ u8 radio_rxtx6d;
+ u8 radio_rxtx6e;
+ u8 radio_rxtx92;
+ u8 radio_rxtx98;
+ /* Values for PHY registers */
+ struct b43_phy_ht_channeltab_e_phy phy_regs;
+};
+
+const struct b43_phy_ht_channeltab_e_radio2059
+*b43_phy_ht_get_channeltab_e_r2059(struct b43_wldev *dev, u16 freq);
+
+#endif /* B43_RADIO_2059_H_ */
diff --git a/drivers/net/wireless/b43/rfkill.c b/drivers/net/wireless/b43/rfkill.c
index a617efe..59c3afe 100644
--- a/drivers/net/wireless/b43/rfkill.c
+++ b/drivers/net/wireless/b43/rfkill.c
@@ -37,17 +37,16 @@
{
struct b43_wl *wl = hw_to_b43_wl(hw);
struct b43_wldev *dev = wl->current_dev;
- struct ssb_bus *bus = dev->sdev->bus;
bool enabled;
bool brought_up = false;
mutex_lock(&wl->mutex);
if (unlikely(b43_status(dev) < B43_STAT_INITIALIZED)) {
- if (ssb_bus_powerup(bus, 0)) {
+ if (b43_bus_powerup(dev, 0)) {
mutex_unlock(&wl->mutex);
return;
}
- ssb_device_enable(dev->sdev, 0);
+ b43_device_enable(dev, 0);
brought_up = true;
}
@@ -63,8 +62,8 @@
}
if (brought_up) {
- ssb_device_disable(dev->sdev, 0);
- ssb_bus_may_powerdown(bus);
+ b43_device_disable(dev, 0);
+ b43_bus_may_powerdown(dev);
}
mutex_unlock(&wl->mutex);
diff --git a/drivers/net/wireless/b43/sdio.c b/drivers/net/wireless/b43/sdio.c
index 808e25b..4fd6775 100644
--- a/drivers/net/wireless/b43/sdio.c
+++ b/drivers/net/wireless/b43/sdio.c
@@ -66,7 +66,7 @@
int b43_sdio_request_irq(struct b43_wldev *dev,
void (*handler)(struct b43_wldev *dev))
{
- struct ssb_bus *bus = dev->sdev->bus;
+ struct ssb_bus *bus = dev->dev->sdev->bus;
struct sdio_func *func = bus->host_sdio;
struct b43_sdio *sdio = sdio_get_drvdata(func);
int err;
@@ -82,7 +82,7 @@
void b43_sdio_free_irq(struct b43_wldev *dev)
{
- struct ssb_bus *bus = dev->sdev->bus;
+ struct ssb_bus *bus = dev->dev->sdev->bus;
struct sdio_func *func = bus->host_sdio;
struct b43_sdio *sdio = sdio_get_drvdata(func);
@@ -93,8 +93,8 @@
sdio->irq_handler = NULL;
}
-static int b43_sdio_probe(struct sdio_func *func,
- const struct sdio_device_id *id)
+static int __devinit b43_sdio_probe(struct sdio_func *func,
+ const struct sdio_device_id *id)
{
struct b43_sdio *sdio;
struct sdio_func_tuple *tuple;
@@ -171,7 +171,7 @@
return error;
}
-static void b43_sdio_remove(struct sdio_func *func)
+static void __devexit b43_sdio_remove(struct sdio_func *func)
{
struct b43_sdio *sdio = sdio_get_drvdata(func);
diff --git a/drivers/net/wireless/b43/sysfs.c b/drivers/net/wireless/b43/sysfs.c
index 57af619..f1ae4e0 100644
--- a/drivers/net/wireless/b43/sysfs.c
+++ b/drivers/net/wireless/b43/sysfs.c
@@ -140,7 +140,7 @@
int b43_sysfs_register(struct b43_wldev *wldev)
{
- struct device *dev = wldev->sdev->dev;
+ struct device *dev = wldev->dev->dev;
B43_WARN_ON(b43_status(wldev) != B43_STAT_INITIALIZED);
@@ -149,7 +149,7 @@
void b43_sysfs_unregister(struct b43_wldev *wldev)
{
- struct device *dev = wldev->sdev->dev;
+ struct device *dev = wldev->dev->dev;
device_remove_file(dev, &dev_attr_interference);
}
diff --git a/drivers/net/wireless/b43/tables_lpphy.c b/drivers/net/wireless/b43/tables_lpphy.c
index 59df3c6..6748c5a 100644
--- a/drivers/net/wireless/b43/tables_lpphy.c
+++ b/drivers/net/wireless/b43/tables_lpphy.c
@@ -2304,7 +2304,6 @@
void lpphy_rev2plus_table_init(struct b43_wldev *dev)
{
- struct ssb_bus *bus = dev->sdev->bus;
int i;
B43_WARN_ON(dev->phy.rev < 2);
@@ -2341,7 +2340,7 @@
b43_lptab_write_bulk(dev, B43_LPTAB32(10, 0),
ARRAY_SIZE(lpphy_papd_mult_table), lpphy_papd_mult_table);
- if ((bus->chip_id == 0x4325) && (bus->chip_rev == 0)) {
+ if ((dev->dev->chip_id == 0x4325) && (dev->dev->chip_rev == 0)) {
b43_lptab_write_bulk(dev, B43_LPTAB32(13, 0),
ARRAY_SIZE(lpphy_a0_gain_idx_table), lpphy_a0_gain_idx_table);
b43_lptab_write_bulk(dev, B43_LPTAB16(14, 0),
@@ -2416,12 +2415,12 @@
void lpphy_init_tx_gain_table(struct b43_wldev *dev)
{
- struct ssb_bus *bus = dev->sdev->bus;
+ struct ssb_sprom *sprom = dev->dev->bus_sprom;
switch (dev->phy.rev) {
case 0:
- if ((bus->sprom.boardflags_hi & B43_BFH_NOPA) ||
- (bus->sprom.boardflags_lo & B43_BFL_HGPA))
+ if ((sprom->boardflags_hi & B43_BFH_NOPA) ||
+ (sprom->boardflags_lo & B43_BFL_HGPA))
lpphy_write_gain_table_bulk(dev, 0, 128,
lpphy_rev0_nopa_tx_gain_table);
else if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
@@ -2432,8 +2431,8 @@
lpphy_rev0_5ghz_tx_gain_table);
break;
case 1:
- if ((bus->sprom.boardflags_hi & B43_BFH_NOPA) ||
- (bus->sprom.boardflags_lo & B43_BFL_HGPA))
+ if ((sprom->boardflags_hi & B43_BFH_NOPA) ||
+ (sprom->boardflags_lo & B43_BFL_HGPA))
lpphy_write_gain_table_bulk(dev, 0, 128,
lpphy_rev1_nopa_tx_gain_table);
else if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
@@ -2444,7 +2443,7 @@
lpphy_rev1_5ghz_tx_gain_table);
break;
default:
- if (bus->sprom.boardflags_hi & B43_BFH_NOPA)
+ if (sprom->boardflags_hi & B43_BFH_NOPA)
lpphy_write_gain_table_bulk(dev, 0, 128,
lpphy_rev2_nopa_tx_gain_table);
else if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
diff --git a/drivers/net/wireless/b43/tables_nphy.h b/drivers/net/wireless/b43/tables_nphy.h
index 1856936..a81696b 100644
--- a/drivers/net/wireless/b43/tables_nphy.h
+++ b/drivers/net/wireless/b43/tables_nphy.h
@@ -60,16 +60,8 @@
struct nphy_gain_ctl_workaround_entry *b43_nphy_get_gain_ctl_workaround_ent(
struct b43_wldev *dev, bool ghz5, bool ext_lna);
-/* Get the NPHY Channel Switch Table entry for a channel.
- * Returns NULL on failure to find an entry. */
-const struct b43_nphy_channeltab_entry_rev2 *
-b43_nphy_get_chantabent_rev2(struct b43_wldev *dev, u8 channel);
-const struct b43_nphy_channeltab_entry_rev3 *
-b43_nphy_get_chantabent_rev3(struct b43_wldev *dev, u16 freq);
-
/* The N-PHY tables. */
-
#define B43_NTAB_TYPEMASK 0xF0000000
#define B43_NTAB_8BIT 0x10000000
#define B43_NTAB_16BIT 0x20000000
diff --git a/drivers/net/wireless/b43/tables_phy_ht.c b/drivers/net/wireless/b43/tables_phy_ht.c
new file mode 100644
index 0000000..6039386
--- /dev/null
+++ b/drivers/net/wireless/b43/tables_phy_ht.c
@@ -0,0 +1,750 @@
+/*
+
+ Broadcom B43 wireless driver
+ IEEE 802.11n HT-PHY data tables
+
+ 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; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+
+*/
+
+#include "b43.h"
+#include "tables_phy_ht.h"
+#include "phy_common.h"
+#include "phy_ht.h"
+
+static const u16 b43_httab_0x12[] = {
+ 0x0000, 0x0008, 0x000a, 0x0010, 0x0012, 0x0019,
+ 0x001a, 0x001c, 0x0080, 0x0088, 0x008a, 0x0090,
+ 0x0092, 0x0099, 0x009a, 0x009c, 0x0100, 0x0108,
+ 0x010a, 0x0110, 0x0112, 0x0119, 0x011a, 0x011c,
+ 0x0180, 0x0188, 0x018a, 0x0190, 0x0192, 0x0199,
+ 0x019a, 0x019c, 0x0000, 0x0098, 0x00a0, 0x00a8,
+ 0x009a, 0x00a2, 0x00aa, 0x0120, 0x0128, 0x0128,
+ 0x0130, 0x0138, 0x0138, 0x0140, 0x0122, 0x012a,
+ 0x012a, 0x0132, 0x013a, 0x013a, 0x0142, 0x01a8,
+ 0x01b0, 0x01b8, 0x01b0, 0x01b8, 0x01c0, 0x01c8,
+ 0x01c0, 0x01c8, 0x01d0, 0x01d0, 0x01d8, 0x01aa,
+ 0x01b2, 0x01ba, 0x01b2, 0x01ba, 0x01c2, 0x01ca,
+ 0x01c2, 0x01ca, 0x01d2, 0x01d2, 0x01da, 0x0001,
+ 0x0002, 0x0004, 0x0009, 0x000c, 0x0011, 0x0014,
+ 0x0018, 0x0020, 0x0021, 0x0022, 0x0024, 0x0081,
+ 0x0082, 0x0084, 0x0089, 0x008c, 0x0091, 0x0094,
+ 0x0098, 0x00a0, 0x00a1, 0x00a2, 0x00a4, 0x0007,
+ 0x0007, 0x0007, 0x0007, 0x0007, 0x0007, 0x0007,
+ 0x0007, 0x0007, 0x0007, 0x0007, 0x0007, 0x0007,
+ 0x0007, 0x0007, 0x0007, 0x0007, 0x0007, 0x0007,
+ 0x0007, 0x0007, 0x0007, 0x0007, 0x0007, 0x0007,
+ 0x0007, 0x0007,
+};
+
+static const u16 b43_httab_0x27[] = {
+ 0x0009, 0x000e, 0x0011, 0x0014, 0x0017, 0x001a,
+ 0x001d, 0x0020, 0x0009, 0x000e, 0x0011, 0x0014,
+ 0x0017, 0x001a, 0x001d, 0x0020, 0x0009, 0x000e,
+ 0x0011, 0x0014, 0x0017, 0x001a, 0x001d, 0x0020,
+ 0x0009, 0x000e, 0x0011, 0x0014, 0x0017, 0x001a,
+ 0x001d, 0x0020,
+};
+
+static const u16 b43_httab_0x26[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000,
+};
+
+static const u32 b43_httab_0x25[] = {
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+};
+
+static const u32 b43_httab_0x2f[] = {
+ 0x00035700, 0x0002cc9a, 0x00026666, 0x0001581f,
+ 0x0001581f, 0x0001581f, 0x0001581f, 0x0001581f,
+ 0x0001581f, 0x0001581f, 0x0001581f, 0x00035700,
+ 0x0002cc9a, 0x00026666, 0x0001581f, 0x0001581f,
+ 0x0001581f, 0x0001581f, 0x0001581f, 0x0001581f,
+ 0x0001581f, 0x0001581f,
+};
+
+static const u16 b43_httab_0x1a[] = {
+ 0x0055, 0x0054, 0x0054, 0x0053, 0x0052, 0x0052,
+ 0x0051, 0x0051, 0x0050, 0x004f, 0x004f, 0x004e,
+ 0x004e, 0x004d, 0x004c, 0x004c, 0x004b, 0x004a,
+ 0x0049, 0x0049, 0x0048, 0x0047, 0x0046, 0x0046,
+ 0x0045, 0x0044, 0x0043, 0x0042, 0x0041, 0x0040,
+ 0x0040, 0x003f, 0x003e, 0x003d, 0x003c, 0x003a,
+ 0x0039, 0x0038, 0x0037, 0x0036, 0x0035, 0x0033,
+ 0x0032, 0x0031, 0x002f, 0x002e, 0x002c, 0x002b,
+ 0x0029, 0x0027, 0x0025, 0x0023, 0x0021, 0x001f,
+ 0x001d, 0x001a, 0x0018, 0x0015, 0x0012, 0x000e,
+ 0x000b, 0x0007, 0x0002, 0x00fd,
+};
+
+static const u16 b43_httab_0x1b[] = {
+ 0x0055, 0x0054, 0x0054, 0x0053, 0x0052, 0x0052,
+ 0x0051, 0x0051, 0x0050, 0x004f, 0x004f, 0x004e,
+ 0x004e, 0x004d, 0x004c, 0x004c, 0x004b, 0x004a,
+ 0x0049, 0x0049, 0x0048, 0x0047, 0x0046, 0x0046,
+ 0x0045, 0x0044, 0x0043, 0x0042, 0x0041, 0x0040,
+ 0x0040, 0x003f, 0x003e, 0x003d, 0x003c, 0x003a,
+ 0x0039, 0x0038, 0x0037, 0x0036, 0x0035, 0x0033,
+ 0x0032, 0x0031, 0x002f, 0x002e, 0x002c, 0x002b,
+ 0x0029, 0x0027, 0x0025, 0x0023, 0x0021, 0x001f,
+ 0x001d, 0x001a, 0x0018, 0x0015, 0x0012, 0x000e,
+ 0x000b, 0x0007, 0x0002, 0x00fd,
+};
+
+static const u16 b43_httab_0x1c[] = {
+ 0x0055, 0x0054, 0x0054, 0x0053, 0x0052, 0x0052,
+ 0x0051, 0x0051, 0x0050, 0x004f, 0x004f, 0x004e,
+ 0x004e, 0x004d, 0x004c, 0x004c, 0x004b, 0x004a,
+ 0x0049, 0x0049, 0x0048, 0x0047, 0x0046, 0x0046,
+ 0x0045, 0x0044, 0x0043, 0x0042, 0x0041, 0x0040,
+ 0x0040, 0x003f, 0x003e, 0x003d, 0x003c, 0x003a,
+ 0x0039, 0x0038, 0x0037, 0x0036, 0x0035, 0x0033,
+ 0x0032, 0x0031, 0x002f, 0x002e, 0x002c, 0x002b,
+ 0x0029, 0x0027, 0x0025, 0x0023, 0x0021, 0x001f,
+ 0x001d, 0x001a, 0x0018, 0x0015, 0x0012, 0x000e,
+ 0x000b, 0x0007, 0x0002, 0x00fd,
+};
+
+static const u32 b43_httab_0x1a_0xc0[] = {
+ 0x5bf70044, 0x5bf70042, 0x5bf70040, 0x5bf7003e,
+ 0x5bf7003c, 0x5bf7003b, 0x5bf70039, 0x5bf70037,
+ 0x5bf70036, 0x5bf70034, 0x5bf70033, 0x5bf70031,
+ 0x5bf70030, 0x5ba70044, 0x5ba70042, 0x5ba70040,
+ 0x5ba7003e, 0x5ba7003c, 0x5ba7003b, 0x5ba70039,
+ 0x5ba70037, 0x5ba70036, 0x5ba70034, 0x5ba70033,
+ 0x5b770044, 0x5b770042, 0x5b770040, 0x5b77003e,
+ 0x5b77003c, 0x5b77003b, 0x5b770039, 0x5b770037,
+ 0x5b770036, 0x5b770034, 0x5b770033, 0x5b770031,
+ 0x5b770030, 0x5b77002f, 0x5b77002d, 0x5b77002c,
+ 0x5b470044, 0x5b470042, 0x5b470040, 0x5b47003e,
+ 0x5b47003c, 0x5b47003b, 0x5b470039, 0x5b470037,
+ 0x5b470036, 0x5b470034, 0x5b470033, 0x5b470031,
+ 0x5b470030, 0x5b47002f, 0x5b47002d, 0x5b47002c,
+ 0x5b47002b, 0x5b47002a, 0x5b270044, 0x5b270042,
+ 0x5b270040, 0x5b27003e, 0x5b27003c, 0x5b27003b,
+ 0x5b270039, 0x5b270037, 0x5b270036, 0x5b270034,
+ 0x5b270033, 0x5b270031, 0x5b270030, 0x5b27002f,
+ 0x5b170044, 0x5b170042, 0x5b170040, 0x5b17003e,
+ 0x5b17003c, 0x5b17003b, 0x5b170039, 0x5b170037,
+ 0x5b170036, 0x5b170034, 0x5b170033, 0x5b170031,
+ 0x5b170030, 0x5b17002f, 0x5b17002d, 0x5b17002c,
+ 0x5b17002b, 0x5b17002a, 0x5b170028, 0x5b170027,
+ 0x5b170026, 0x5b170025, 0x5b170024, 0x5b170023,
+ 0x5b070044, 0x5b070042, 0x5b070040, 0x5b07003e,
+ 0x5b07003c, 0x5b07003b, 0x5b070039, 0x5b070037,
+ 0x5b070036, 0x5b070034, 0x5b070033, 0x5b070031,
+ 0x5b070030, 0x5b07002f, 0x5b07002d, 0x5b07002c,
+ 0x5b07002b, 0x5b07002a, 0x5b070028, 0x5b070027,
+ 0x5b070026, 0x5b070025, 0x5b070024, 0x5b070023,
+ 0x5b070022, 0x5b070021, 0x5b070020, 0x5b07001f,
+ 0x5b07001e, 0x5b07001d, 0x5b07001d, 0x5b07001c,
+};
+
+static const u32 b43_httab_0x1a_0x140[] = {
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+};
+
+static const u32 b43_httab_0x1b_0x140[] = {
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+};
+
+static const u32 b43_httab_0x1c_0x140[] = {
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+};
+
+static const u16 b43_httab_0x1a_0x1c0[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000,
+};
+
+static const u16 b43_httab_0x1b_0x1c0[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000,
+};
+
+static const u16 b43_httab_0x1c_0x1c0[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000,
+};
+
+static const u16 b43_httab_0x1a_0x240[] = {
+ 0x0036, 0x0036, 0x0036, 0x0036, 0x0036, 0x0036,
+ 0x0036, 0x0036, 0x0036, 0x0036, 0x0036, 0x0036,
+ 0x0036, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a,
+ 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a,
+ 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e,
+ 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e,
+ 0x001e, 0x001e, 0x001e, 0x001e, 0x000e, 0x000e,
+ 0x000e, 0x000e, 0x000e, 0x000e, 0x000e, 0x000e,
+ 0x000e, 0x000e, 0x000e, 0x000e, 0x000e, 0x000e,
+ 0x000e, 0x000e, 0x000e, 0x000e, 0x01fc, 0x01fc,
+ 0x01fc, 0x01fc, 0x01fc, 0x01fc, 0x01fc, 0x01fc,
+ 0x01fc, 0x01fc, 0x01fc, 0x01fc, 0x01fc, 0x01fc,
+ 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee,
+ 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee,
+ 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee,
+ 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee,
+ 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6,
+ 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6,
+ 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6,
+ 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6,
+ 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6,
+ 0x01d6, 0x01d6,
+};
+
+static const u16 b43_httab_0x1b_0x240[] = {
+ 0x0036, 0x0036, 0x0036, 0x0036, 0x0036, 0x0036,
+ 0x0036, 0x0036, 0x0036, 0x0036, 0x0036, 0x0036,
+ 0x0036, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a,
+ 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a,
+ 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e,
+ 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e,
+ 0x001e, 0x001e, 0x001e, 0x001e, 0x000e, 0x000e,
+ 0x000e, 0x000e, 0x000e, 0x000e, 0x000e, 0x000e,
+ 0x000e, 0x000e, 0x000e, 0x000e, 0x000e, 0x000e,
+ 0x000e, 0x000e, 0x000e, 0x000e, 0x01fc, 0x01fc,
+ 0x01fc, 0x01fc, 0x01fc, 0x01fc, 0x01fc, 0x01fc,
+ 0x01fc, 0x01fc, 0x01fc, 0x01fc, 0x01fc, 0x01fc,
+ 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee,
+ 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee,
+ 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee,
+ 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee,
+ 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6,
+ 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6,
+ 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6,
+ 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6,
+ 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6,
+ 0x01d6, 0x01d6,
+};
+
+static const u16 b43_httab_0x1c_0x240[] = {
+ 0x0036, 0x0036, 0x0036, 0x0036, 0x0036, 0x0036,
+ 0x0036, 0x0036, 0x0036, 0x0036, 0x0036, 0x0036,
+ 0x0036, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a,
+ 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a,
+ 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e,
+ 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e,
+ 0x001e, 0x001e, 0x001e, 0x001e, 0x000e, 0x000e,
+ 0x000e, 0x000e, 0x000e, 0x000e, 0x000e, 0x000e,
+ 0x000e, 0x000e, 0x000e, 0x000e, 0x000e, 0x000e,
+ 0x000e, 0x000e, 0x000e, 0x000e, 0x01fc, 0x01fc,
+ 0x01fc, 0x01fc, 0x01fc, 0x01fc, 0x01fc, 0x01fc,
+ 0x01fc, 0x01fc, 0x01fc, 0x01fc, 0x01fc, 0x01fc,
+ 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee,
+ 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee,
+ 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee,
+ 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee,
+ 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6,
+ 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6,
+ 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6,
+ 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6,
+ 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6,
+ 0x01d6, 0x01d6,
+};
+
+static const u32 b43_httab_0x1f[] = {
+ 0x00000000, 0x00000000, 0x00016023, 0x00006028,
+ 0x00034036, 0x0003402e, 0x0007203c, 0x0006e037,
+ 0x00070030, 0x0009401f, 0x0009a00f, 0x000b600d,
+ 0x000c8007, 0x000ce007, 0x00101fff, 0x00121ff9,
+ 0x0012e004, 0x0014dffc, 0x0016dff6, 0x0018dfe9,
+ 0x001b3fe5, 0x001c5fd0, 0x001ddfc2, 0x001f1fb6,
+ 0x00207fa4, 0x00219f8f, 0x0022ff7d, 0x00247f6c,
+ 0x0024df5b, 0x00267f4b, 0x0027df3b, 0x0029bf3b,
+ 0x002b5f2f, 0x002d3f2e, 0x002f5f2a, 0x002fff15,
+ 0x00315f0b, 0x0032defa, 0x0033beeb, 0x0034fed9,
+ 0x00353ec5, 0x00361eb0, 0x00363e9b, 0x0036be87,
+ 0x0036be70, 0x0038fe67, 0x0044beb2, 0x00513ef3,
+ 0x00595f11, 0x00669f3d, 0x0078dfdf, 0x00a143aa,
+ 0x01642fff, 0x0162afff, 0x01620fff, 0x0160cfff,
+ 0x015f0fff, 0x015dafff, 0x015bcfff, 0x015bcfff,
+ 0x015b4fff, 0x015acfff, 0x01590fff, 0x0156cfff,
+};
+
+static const u32 b43_httab_0x21[] = {
+ 0x00000000, 0x00000000, 0x00016023, 0x00006028,
+ 0x00034036, 0x0003402e, 0x0007203c, 0x0006e037,
+ 0x00070030, 0x0009401f, 0x0009a00f, 0x000b600d,
+ 0x000c8007, 0x000ce007, 0x00101fff, 0x00121ff9,
+ 0x0012e004, 0x0014dffc, 0x0016dff6, 0x0018dfe9,
+ 0x001b3fe5, 0x001c5fd0, 0x001ddfc2, 0x001f1fb6,
+ 0x00207fa4, 0x00219f8f, 0x0022ff7d, 0x00247f6c,
+ 0x0024df5b, 0x00267f4b, 0x0027df3b, 0x0029bf3b,
+ 0x002b5f2f, 0x002d3f2e, 0x002f5f2a, 0x002fff15,
+ 0x00315f0b, 0x0032defa, 0x0033beeb, 0x0034fed9,
+ 0x00353ec5, 0x00361eb0, 0x00363e9b, 0x0036be87,
+ 0x0036be70, 0x0038fe67, 0x0044beb2, 0x00513ef3,
+ 0x00595f11, 0x00669f3d, 0x0078dfdf, 0x00a143aa,
+ 0x01642fff, 0x0162afff, 0x01620fff, 0x0160cfff,
+ 0x015f0fff, 0x015dafff, 0x015bcfff, 0x015bcfff,
+ 0x015b4fff, 0x015acfff, 0x01590fff, 0x0156cfff,
+};
+
+static const u32 b43_httab_0x23[] = {
+ 0x00000000, 0x00000000, 0x00016023, 0x00006028,
+ 0x00034036, 0x0003402e, 0x0007203c, 0x0006e037,
+ 0x00070030, 0x0009401f, 0x0009a00f, 0x000b600d,
+ 0x000c8007, 0x000ce007, 0x00101fff, 0x00121ff9,
+ 0x0012e004, 0x0014dffc, 0x0016dff6, 0x0018dfe9,
+ 0x001b3fe5, 0x001c5fd0, 0x001ddfc2, 0x001f1fb6,
+ 0x00207fa4, 0x00219f8f, 0x0022ff7d, 0x00247f6c,
+ 0x0024df5b, 0x00267f4b, 0x0027df3b, 0x0029bf3b,
+ 0x002b5f2f, 0x002d3f2e, 0x002f5f2a, 0x002fff15,
+ 0x00315f0b, 0x0032defa, 0x0033beeb, 0x0034fed9,
+ 0x00353ec5, 0x00361eb0, 0x00363e9b, 0x0036be87,
+ 0x0036be70, 0x0038fe67, 0x0044beb2, 0x00513ef3,
+ 0x00595f11, 0x00669f3d, 0x0078dfdf, 0x00a143aa,
+ 0x01642fff, 0x0162afff, 0x01620fff, 0x0160cfff,
+ 0x015f0fff, 0x015dafff, 0x015bcfff, 0x015bcfff,
+ 0x015b4fff, 0x015acfff, 0x01590fff, 0x0156cfff,
+};
+
+static const u32 b43_httab_0x20[] = {
+ 0x0b5e002d, 0x0ae2002f, 0x0a3b0032, 0x09a70035,
+ 0x09220038, 0x08ab003b, 0x081f003f, 0x07a20043,
+ 0x07340047, 0x06d2004b, 0x067a004f, 0x06170054,
+ 0x05bf0059, 0x0571005e, 0x051e0064, 0x04d3006a,
+ 0x04910070, 0x044c0077, 0x040f007e, 0x03d90085,
+ 0x03a1008d, 0x036f0095, 0x033d009e, 0x030b00a8,
+ 0x02e000b2, 0x02b900bc, 0x029200c7, 0x026d00d3,
+ 0x024900e0, 0x022900ed, 0x020a00fb, 0x01ec010a,
+ 0x01d20119, 0x01b7012a, 0x019e013c, 0x0188014e,
+ 0x01720162, 0x015d0177, 0x0149018e, 0x013701a5,
+ 0x012601be, 0x011501d8, 0x010601f4, 0x00f70212,
+ 0x00e90231, 0x00dc0253, 0x00d00276, 0x00c4029b,
+ 0x00b902c3, 0x00af02ed, 0x00a50319, 0x009c0348,
+ 0x0093037a, 0x008b03af, 0x008303e6, 0x007c0422,
+ 0x00750460, 0x006e04a3, 0x006804e9, 0x00620533,
+ 0x005d0582, 0x005805d6, 0x0053062e, 0x004e068c,
+};
+
+static const u32 b43_httab_0x22[] = {
+ 0x0b5e002d, 0x0ae2002f, 0x0a3b0032, 0x09a70035,
+ 0x09220038, 0x08ab003b, 0x081f003f, 0x07a20043,
+ 0x07340047, 0x06d2004b, 0x067a004f, 0x06170054,
+ 0x05bf0059, 0x0571005e, 0x051e0064, 0x04d3006a,
+ 0x04910070, 0x044c0077, 0x040f007e, 0x03d90085,
+ 0x03a1008d, 0x036f0095, 0x033d009e, 0x030b00a8,
+ 0x02e000b2, 0x02b900bc, 0x029200c7, 0x026d00d3,
+ 0x024900e0, 0x022900ed, 0x020a00fb, 0x01ec010a,
+ 0x01d20119, 0x01b7012a, 0x019e013c, 0x0188014e,
+ 0x01720162, 0x015d0177, 0x0149018e, 0x013701a5,
+ 0x012601be, 0x011501d8, 0x010601f4, 0x00f70212,
+ 0x00e90231, 0x00dc0253, 0x00d00276, 0x00c4029b,
+ 0x00b902c3, 0x00af02ed, 0x00a50319, 0x009c0348,
+ 0x0093037a, 0x008b03af, 0x008303e6, 0x007c0422,
+ 0x00750460, 0x006e04a3, 0x006804e9, 0x00620533,
+ 0x005d0582, 0x005805d6, 0x0053062e, 0x004e068c,
+};
+
+static const u32 b43_httab_0x24[] = {
+ 0x0b5e002d, 0x0ae2002f, 0x0a3b0032, 0x09a70035,
+ 0x09220038, 0x08ab003b, 0x081f003f, 0x07a20043,
+ 0x07340047, 0x06d2004b, 0x067a004f, 0x06170054,
+ 0x05bf0059, 0x0571005e, 0x051e0064, 0x04d3006a,
+ 0x04910070, 0x044c0077, 0x040f007e, 0x03d90085,
+ 0x03a1008d, 0x036f0095, 0x033d009e, 0x030b00a8,
+ 0x02e000b2, 0x02b900bc, 0x029200c7, 0x026d00d3,
+ 0x024900e0, 0x022900ed, 0x020a00fb, 0x01ec010a,
+ 0x01d20119, 0x01b7012a, 0x019e013c, 0x0188014e,
+ 0x01720162, 0x015d0177, 0x0149018e, 0x013701a5,
+ 0x012601be, 0x011501d8, 0x010601f4, 0x00f70212,
+ 0x00e90231, 0x00dc0253, 0x00d00276, 0x00c4029b,
+ 0x00b902c3, 0x00af02ed, 0x00a50319, 0x009c0348,
+ 0x0093037a, 0x008b03af, 0x008303e6, 0x007c0422,
+ 0x00750460, 0x006e04a3, 0x006804e9, 0x00620533,
+ 0x005d0582, 0x005805d6, 0x0053062e, 0x004e068c,
+};
+
+/**************************************************
+ * R/W ops.
+ **************************************************/
+
+u32 b43_httab_read(struct b43_wldev *dev, u32 offset)
+{
+ u32 type, value;
+
+ type = offset & B43_HTTAB_TYPEMASK;
+ offset &= ~B43_HTTAB_TYPEMASK;
+ B43_WARN_ON(offset > 0xFFFF);
+
+ switch (type) {
+ case B43_HTTAB_8BIT:
+ b43_phy_write(dev, B43_PHY_HT_TABLE_ADDR, offset);
+ value = b43_phy_read(dev, B43_PHY_HT_TABLE_DATALO) & 0xFF;
+ break;
+ case B43_HTTAB_16BIT:
+ b43_phy_write(dev, B43_PHY_HT_TABLE_ADDR, offset);
+ value = b43_phy_read(dev, B43_PHY_HT_TABLE_DATALO);
+ break;
+ case B43_HTTAB_32BIT:
+ b43_phy_write(dev, B43_PHY_HT_TABLE_ADDR, offset);
+ value = b43_phy_read(dev, B43_PHY_HT_TABLE_DATAHI);
+ value <<= 16;
+ value |= b43_phy_read(dev, B43_PHY_HT_TABLE_DATALO);
+ break;
+ default:
+ B43_WARN_ON(1);
+ value = 0;
+ }
+
+ return value;
+}
+
+void b43_httab_read_bulk(struct b43_wldev *dev, u32 offset,
+ unsigned int nr_elements, void *_data)
+{
+ u32 type;
+ u8 *data = _data;
+ unsigned int i;
+
+ type = offset & B43_HTTAB_TYPEMASK;
+ offset &= ~B43_HTTAB_TYPEMASK;
+ B43_WARN_ON(offset > 0xFFFF);
+
+ b43_phy_write(dev, B43_PHY_HT_TABLE_ADDR, offset);
+
+ for (i = 0; i < nr_elements; i++) {
+ switch (type) {
+ case B43_HTTAB_8BIT:
+ *data = b43_phy_read(dev, B43_PHY_HT_TABLE_DATALO) & 0xFF;
+ data++;
+ break;
+ case B43_HTTAB_16BIT:
+ *((u16 *)data) = b43_phy_read(dev, B43_PHY_HT_TABLE_DATALO);
+ data += 2;
+ break;
+ case B43_HTTAB_32BIT:
+ *((u32 *)data) = b43_phy_read(dev, B43_PHY_HT_TABLE_DATAHI);
+ *((u32 *)data) <<= 16;
+ *((u32 *)data) |= b43_phy_read(dev, B43_PHY_HT_TABLE_DATALO);
+ data += 4;
+ break;
+ default:
+ B43_WARN_ON(1);
+ }
+ }
+}
+
+void b43_httab_write(struct b43_wldev *dev, u32 offset, u32 value)
+{
+ u32 type;
+
+ type = offset & B43_HTTAB_TYPEMASK;
+ offset &= 0xFFFF;
+
+ switch (type) {
+ case B43_HTTAB_8BIT:
+ B43_WARN_ON(value & ~0xFF);
+ b43_phy_write(dev, B43_PHY_HT_TABLE_ADDR, offset);
+ b43_phy_write(dev, B43_PHY_HT_TABLE_DATALO, value);
+ break;
+ case B43_HTTAB_16BIT:
+ B43_WARN_ON(value & ~0xFFFF);
+ b43_phy_write(dev, B43_PHY_HT_TABLE_ADDR, offset);
+ b43_phy_write(dev, B43_PHY_HT_TABLE_DATALO, value);
+ break;
+ case B43_HTTAB_32BIT:
+ b43_phy_write(dev, B43_PHY_HT_TABLE_ADDR, offset);
+ b43_phy_write(dev, B43_PHY_HT_TABLE_DATAHI, value >> 16);
+ b43_phy_write(dev, B43_PHY_HT_TABLE_DATALO, value & 0xFFFF);
+ break;
+ default:
+ B43_WARN_ON(1);
+ }
+
+ return;
+}
+
+void b43_httab_write_bulk(struct b43_wldev *dev, u32 offset,
+ unsigned int nr_elements, const void *_data)
+{
+ u32 type, value;
+ const u8 *data = _data;
+ unsigned int i;
+
+ type = offset & B43_HTTAB_TYPEMASK;
+ offset &= ~B43_HTTAB_TYPEMASK;
+ B43_WARN_ON(offset > 0xFFFF);
+
+ b43_phy_write(dev, B43_PHY_HT_TABLE_ADDR, offset);
+
+ for (i = 0; i < nr_elements; i++) {
+ switch (type) {
+ case B43_HTTAB_8BIT:
+ value = *data;
+ data++;
+ B43_WARN_ON(value & ~0xFF);
+ b43_phy_write(dev, B43_PHY_HT_TABLE_DATALO, value);
+ break;
+ case B43_HTTAB_16BIT:
+ value = *((u16 *)data);
+ data += 2;
+ B43_WARN_ON(value & ~0xFFFF);
+ b43_phy_write(dev, B43_PHY_HT_TABLE_DATALO, value);
+ break;
+ case B43_HTTAB_32BIT:
+ value = *((u32 *)data);
+ data += 4;
+ b43_phy_write(dev, B43_PHY_HT_TABLE_DATAHI, value >> 16);
+ b43_phy_write(dev, B43_PHY_HT_TABLE_DATALO,
+ value & 0xFFFF);
+ break;
+ default:
+ B43_WARN_ON(1);
+ }
+ }
+}
+
+/**************************************************
+ * Tables ops.
+ **************************************************/
+
+#define httab_upload(dev, offset, data) do { \
+ b43_httab_write_bulk(dev, offset, ARRAY_SIZE(data), data); \
+ } while (0)
+void b43_phy_ht_tables_init(struct b43_wldev *dev)
+{
+ httab_upload(dev, B43_HTTAB16(0x12, 0), b43_httab_0x12);
+ httab_upload(dev, B43_HTTAB16(0x27, 0), b43_httab_0x27);
+ httab_upload(dev, B43_HTTAB16(0x26, 0), b43_httab_0x26);
+ httab_upload(dev, B43_HTTAB32(0x25, 0), b43_httab_0x25);
+ httab_upload(dev, B43_HTTAB32(0x2f, 0), b43_httab_0x2f);
+ httab_upload(dev, B43_HTTAB16(0x1a, 0), b43_httab_0x1a);
+ httab_upload(dev, B43_HTTAB16(0x1b, 0), b43_httab_0x1b);
+ httab_upload(dev, B43_HTTAB16(0x1c, 0), b43_httab_0x1c);
+ httab_upload(dev, B43_HTTAB32(0x1a, 0x0c0), b43_httab_0x1a_0xc0);
+ httab_upload(dev, B43_HTTAB32(0x1a, 0x140), b43_httab_0x1a_0x140);
+ httab_upload(dev, B43_HTTAB32(0x1b, 0x140), b43_httab_0x1b_0x140);
+ httab_upload(dev, B43_HTTAB32(0x1c, 0x140), b43_httab_0x1c_0x140);
+ httab_upload(dev, B43_HTTAB16(0x1a, 0x1c0), b43_httab_0x1a_0x1c0);
+ httab_upload(dev, B43_HTTAB16(0x1b, 0x1c0), b43_httab_0x1b_0x1c0);
+ httab_upload(dev, B43_HTTAB16(0x1c, 0x1c0), b43_httab_0x1c_0x1c0);
+ httab_upload(dev, B43_HTTAB16(0x1a, 0x240), b43_httab_0x1a_0x240);
+ httab_upload(dev, B43_HTTAB16(0x1b, 0x240), b43_httab_0x1b_0x240);
+ httab_upload(dev, B43_HTTAB16(0x1c, 0x240), b43_httab_0x1c_0x240);
+ httab_upload(dev, B43_HTTAB32(0x1f, 0), b43_httab_0x1f);
+ httab_upload(dev, B43_HTTAB32(0x21, 0), b43_httab_0x21);
+ httab_upload(dev, B43_HTTAB32(0x23, 0), b43_httab_0x23);
+ httab_upload(dev, B43_HTTAB32(0x20, 0), b43_httab_0x20);
+ httab_upload(dev, B43_HTTAB32(0x22, 0), b43_httab_0x22);
+ httab_upload(dev, B43_HTTAB32(0x24, 0), b43_httab_0x24);
+}
diff --git a/drivers/net/wireless/b43/tables_phy_ht.h b/drivers/net/wireless/b43/tables_phy_ht.h
new file mode 100644
index 0000000..ea3be38
--- /dev/null
+++ b/drivers/net/wireless/b43/tables_phy_ht.h
@@ -0,0 +1,22 @@
+#ifndef B43_TABLES_PHY_HT_H_
+#define B43_TABLES_PHY_HT_H_
+
+/* The HT-PHY tables. */
+#define B43_HTTAB_TYPEMASK 0xF0000000
+#define B43_HTTAB_8BIT 0x10000000
+#define B43_HTTAB_16BIT 0x20000000
+#define B43_HTTAB_32BIT 0x30000000
+#define B43_HTTAB8(table, offset) (((table) << 10) | (offset) | B43_HTTAB_8BIT)
+#define B43_HTTAB16(table, offset) (((table) << 10) | (offset) | B43_HTTAB_16BIT)
+#define B43_HTTAB32(table, offset) (((table) << 10) | (offset) | B43_HTTAB_32BIT)
+
+u32 b43_httab_read(struct b43_wldev *dev, u32 offset);
+void b43_httab_read_bulk(struct b43_wldev *dev, u32 offset,
+ unsigned int nr_elements, void *_data);
+void b43_httab_write(struct b43_wldev *dev, u32 offset, u32 value);
+void b43_httab_write_bulk(struct b43_wldev *dev, u32 offset,
+ unsigned int nr_elements, const void *_data);
+
+void b43_phy_ht_tables_init(struct b43_wldev *dev);
+
+#endif /* B43_TABLES_PHY_HT_H_ */
diff --git a/drivers/net/wireless/b43/wa.c b/drivers/net/wireless/b43/wa.c
index 8f4db44..5d00d0e 100644
--- a/drivers/net/wireless/b43/wa.c
+++ b/drivers/net/wireless/b43/wa.c
@@ -458,17 +458,15 @@
static void b43_wa_boards_a(struct b43_wldev *dev)
{
- struct ssb_bus *bus = dev->sdev->bus;
-
- if (bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM &&
- bus->boardinfo.type == SSB_BOARD_BU4306 &&
- bus->boardinfo.rev < 0x30) {
+ if (dev->dev->board_vendor == SSB_BOARDVENDOR_BCM &&
+ dev->dev->board_type == SSB_BOARD_BU4306 &&
+ dev->dev->board_rev < 0x30) {
b43_phy_write(dev, 0x0010, 0xE000);
b43_phy_write(dev, 0x0013, 0x0140);
b43_phy_write(dev, 0x0014, 0x0280);
} else {
- if (bus->boardinfo.type == SSB_BOARD_MP4318 &&
- bus->boardinfo.rev < 0x20) {
+ if (dev->dev->board_type == SSB_BOARD_MP4318 &&
+ dev->dev->board_rev < 0x20) {
b43_phy_write(dev, 0x0013, 0x0210);
b43_phy_write(dev, 0x0014, 0x0840);
} else {
@@ -486,19 +484,19 @@
static void b43_wa_boards_g(struct b43_wldev *dev)
{
- struct ssb_bus *bus = dev->sdev->bus;
+ struct ssb_sprom *sprom = dev->dev->bus_sprom;
struct b43_phy *phy = &dev->phy;
- if (bus->boardinfo.vendor != SSB_BOARDVENDOR_BCM ||
- bus->boardinfo.type != SSB_BOARD_BU4306 ||
- bus->boardinfo.rev != 0x17) {
+ if (dev->dev->board_vendor != SSB_BOARDVENDOR_BCM ||
+ dev->dev->board_type != SSB_BOARD_BU4306 ||
+ dev->dev->board_rev != 0x17) {
if (phy->rev < 2) {
b43_ofdmtab_write16(dev, B43_OFDMTAB_GAINX_R1, 1, 0x0002);
b43_ofdmtab_write16(dev, B43_OFDMTAB_GAINX_R1, 2, 0x0001);
} else {
b43_ofdmtab_write16(dev, B43_OFDMTAB_GAINX, 1, 0x0002);
b43_ofdmtab_write16(dev, B43_OFDMTAB_GAINX, 2, 0x0001);
- if ((bus->sprom.boardflags_lo & B43_BFL_EXTLNA) &&
+ if ((sprom->boardflags_lo & B43_BFL_EXTLNA) &&
(phy->rev >= 7)) {
b43_phy_mask(dev, B43_PHY_EXTG(0x11), 0xF7FF);
b43_ofdmtab_write16(dev, B43_OFDMTAB_GAINX, 0x0020, 0x0001);
@@ -510,7 +508,7 @@
}
}
}
- if (bus->sprom.boardflags_lo & B43_BFL_FEM) {
+ if (sprom->boardflags_lo & B43_BFL_FEM) {
b43_phy_write(dev, B43_PHY_GTABCTL, 0x3120);
b43_phy_write(dev, B43_PHY_GTABDATA, 0xC480);
}
diff --git a/drivers/net/wireless/b43/xmit.c b/drivers/net/wireless/b43/xmit.c
index c8f99ae..488b898 100644
--- a/drivers/net/wireless/b43/xmit.c
+++ b/drivers/net/wireless/b43/xmit.c
@@ -547,7 +547,7 @@
else
tmp -= 3;
} else {
- if (dev->sdev->bus->sprom.
+ if (dev->dev->bus_sprom->
boardflags_lo & B43_BFL_RSSI) {
if (in_rssi > 63)
in_rssi = 63;
diff --git a/drivers/net/wireless/b43legacy/dma.c b/drivers/net/wireless/b43legacy/dma.c
index e03e01d..c33934a 100644
--- a/drivers/net/wireless/b43legacy/dma.c
+++ b/drivers/net/wireless/b43legacy/dma.c
@@ -817,14 +817,13 @@
static void free_all_descbuffers(struct b43legacy_dmaring *ring)
{
- struct b43legacy_dmadesc_generic *desc;
struct b43legacy_dmadesc_meta *meta;
int i;
if (!ring->used_slots)
return;
for (i = 0; i < ring->nr_slots; i++) {
- desc = ring->ops->idx2desc(ring, i, &meta);
+ ring->ops->idx2desc(ring, i, &meta);
if (!meta->skb) {
B43legacy_WARN_ON(!ring->tx);
@@ -1371,10 +1370,8 @@
struct sk_buff *skb)
{
struct b43legacy_dmaring *ring;
- struct ieee80211_hdr *hdr;
int err = 0;
unsigned long flags;
- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
ring = priority_to_txring(dev, skb_get_queue_mapping(skb));
spin_lock_irqsave(&ring->lock, flags);
@@ -1401,8 +1398,6 @@
/* dma_tx_fragment might reallocate the skb, so invalidate pointers pointing
* into the skb data or cb now. */
- hdr = NULL;
- info = NULL;
err = dma_tx_fragment(ring, &skb);
if (unlikely(err == -ENOKEY)) {
/* Drop this packet, as we don't have the encryption key
@@ -1435,7 +1430,6 @@
{
const struct b43legacy_dma_ops *ops;
struct b43legacy_dmaring *ring;
- struct b43legacy_dmadesc_generic *desc;
struct b43legacy_dmadesc_meta *meta;
int retry_limit;
int slot;
@@ -1450,7 +1444,7 @@
ops = ring->ops;
while (1) {
B43legacy_WARN_ON(!(slot >= 0 && slot < ring->nr_slots));
- desc = ops->idx2desc(ring, slot, &meta);
+ ops->idx2desc(ring, slot, &meta);
if (meta->skb)
unmap_descbuffer(ring, meta->dmaaddr,
diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c
index 1ab8861..d6db6c1 100644
--- a/drivers/net/wireless/b43legacy/main.c
+++ b/drivers/net/wireless/b43legacy/main.c
@@ -1564,10 +1564,10 @@
struct b43legacy_firmware *fw = &dev->fw;
const u8 rev = dev->dev->id.revision;
const char *filename;
- u32 tmshigh;
int err;
- tmshigh = ssb_read32(dev->dev, SSB_TMSHIGH);
+ /* do dummy read */
+ ssb_read32(dev->dev, SSB_TMSHIGH);
if (!fw->ucode) {
if (rev == 2)
filename = "ucode2";
@@ -2634,11 +2634,9 @@
unsigned long flags;
unsigned int new_phymode = 0xFFFF;
int antenna_tx;
- int antenna_rx;
int err = 0;
antenna_tx = B43legacy_ANTENNA_DEFAULT;
- antenna_rx = B43legacy_ANTENNA_DEFAULT;
mutex_lock(&wl->mutex);
dev = wl->current_dev;
@@ -2775,14 +2773,12 @@
{
struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
struct b43legacy_wldev *dev;
- struct b43legacy_phy *phy;
unsigned long flags;
mutex_lock(&wl->mutex);
B43legacy_WARN_ON(wl->vif != vif);
dev = wl->current_dev;
- phy = &dev->phy;
/* Disable IRQs while reconfiguring the device.
* This makes it possible to drop the spinlock throughout
@@ -2974,7 +2970,7 @@
break;
default:
unsupported = 1;
- };
+ }
if (unsupported) {
b43legacyerr(dev->wl, "FOUND UNSUPPORTED PHY "
"(Analog %u, Type %u, Revision %u)\n",
diff --git a/drivers/net/wireless/b43legacy/xmit.c b/drivers/net/wireless/b43legacy/xmit.c
index 3a95541..6c174f3 100644
--- a/drivers/net/wireless/b43legacy/xmit.c
+++ b/drivers/net/wireless/b43legacy/xmit.c
@@ -321,11 +321,9 @@
struct ieee80211_hdr *hdr;
int rts_rate;
int rts_rate_fb;
- int rts_rate_ofdm;
int rts_rate_fb_ofdm;
rts_rate = ieee80211_get_rts_cts_rate(dev->wl->hw, info)->hw_value;
- rts_rate_ofdm = b43legacy_is_ofdm_rate(rts_rate);
rts_rate_fb = b43legacy_calc_fallback_rate(rts_rate);
rts_rate_fb_ofdm = b43legacy_is_ofdm_rate(rts_rate_fb);
if (rts_rate_fb_ofdm)
diff --git a/drivers/net/wireless/hostap/hostap_wlan.h b/drivers/net/wireless/hostap/hostap_wlan.h
index 88dc6a5..7bb0b4b 100644
--- a/drivers/net/wireless/hostap/hostap_wlan.h
+++ b/drivers/net/wireless/hostap/hostap_wlan.h
@@ -1,6 +1,7 @@
#ifndef HOSTAP_WLAN_H
#define HOSTAP_WLAN_H
+#include <linux/interrupt.h>
#include <linux/wireless.h>
#include <linux/netdevice.h>
#include <linux/mutex.h>
diff --git a/drivers/net/wireless/ipw2x00/ipw2200.h b/drivers/net/wireless/ipw2x00/ipw2200.h
index 91795b5..ecb561d 100644
--- a/drivers/net/wireless/ipw2x00/ipw2200.h
+++ b/drivers/net/wireless/ipw2x00/ipw2200.h
@@ -32,6 +32,7 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/mutex.h>
#include <linux/pci.h>
diff --git a/drivers/net/wireless/ipw2x00/libipw_rx.c b/drivers/net/wireless/ipw2x00/libipw_rx.c
index e5ad76c..32a9966 100644
--- a/drivers/net/wireless/ipw2x00/libipw_rx.c
+++ b/drivers/net/wireless/ipw2x00/libipw_rx.c
@@ -442,7 +442,7 @@
* 802.11, but makes it easier to use different keys with
* stations that do not support WEP key mapping). */
- if (!(hdr->addr1[0] & 0x01) || local->bcrx_sta_key)
+ if (is_unicast_ether_addr(hdr->addr1) || local->bcrx_sta_key)
(void)hostap_handle_sta_crypto(local, hdr, &crypt,
&sta);
#endif
@@ -772,7 +772,7 @@
#ifdef NOT_YET
if (ieee->iw_mode == IW_MODE_MASTER && !wds && ieee->ap->bridge_packets) {
- if (dst[0] & 0x01) {
+ if (is_multicast_ether_addr(dst)) {
/* copy multicast frame both to the higher layers and
* to the wireless media */
ieee->ap->bridged_multicast++;
diff --git a/drivers/net/wireless/ipw2x00/libipw_wx.c b/drivers/net/wireless/ipw2x00/libipw_wx.c
index d7bd6cf0..6623e50 100644
--- a/drivers/net/wireless/ipw2x00/libipw_wx.c
+++ b/drivers/net/wireless/ipw2x00/libipw_wx.c
@@ -30,6 +30,7 @@
******************************************************************************/
+#include <linux/hardirq.h>
#include <linux/kmod.h>
#include <linux/slab.h>
#include <linux/module.h>
diff --git a/drivers/net/wireless/iwlegacy/iwl-3945.c b/drivers/net/wireless/iwlegacy/iwl-3945.c
index d096dc2..dab67a1 100644
--- a/drivers/net/wireless/iwlegacy/iwl-3945.c
+++ b/drivers/net/wireless/iwlegacy/iwl-3945.c
@@ -408,7 +408,6 @@
#ifdef CONFIG_IWLWIFI_LEGACY_DEBUGFS
iwl3945_accumulative_statistics(priv, (__le32 *)&pkt->u.raw);
#endif
- iwl_legacy_recover_from_statistics(priv, pkt);
memcpy(&priv->_3945.statistics, pkt->u.raw, sizeof(priv->_3945.statistics));
}
@@ -2640,7 +2639,6 @@
.txq_free_tfd = iwl3945_hw_txq_free_tfd,
.txq_init = iwl3945_hw_tx_queue_init,
.load_ucode = iwl3945_load_bsm,
- .dump_nic_event_log = iwl3945_dump_nic_event_log,
.dump_nic_error_log = iwl3945_dump_nic_error_log,
.apm_ops = {
.init = iwl3945_apm_init,
@@ -2698,9 +2696,7 @@
.set_l0s = false,
.use_bsm = true,
.led_compensation = 64,
- .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF,
.wd_timeout = IWL_DEF_WD_TIMEOUT,
- .max_event_log_size = 512,
};
static struct iwl_cfg iwl3945_bg_cfg = {
diff --git a/drivers/net/wireless/iwlegacy/iwl-4965-lib.c b/drivers/net/wireless/iwlegacy/iwl-4965-lib.c
index a7a4739..2be6d9e 100644
--- a/drivers/net/wireless/iwlegacy/iwl-4965-lib.c
+++ b/drivers/net/wireless/iwlegacy/iwl-4965-lib.c
@@ -694,47 +694,6 @@
sizeof(struct iwl_rx_phy_res));
}
-static int iwl4965_get_single_channel_for_scan(struct iwl_priv *priv,
- struct ieee80211_vif *vif,
- enum ieee80211_band band,
- struct iwl_scan_channel *scan_ch)
-{
- const struct ieee80211_supported_band *sband;
- u16 passive_dwell = 0;
- u16 active_dwell = 0;
- int added = 0;
- u16 channel = 0;
-
- sband = iwl_get_hw_mode(priv, band);
- if (!sband) {
- IWL_ERR(priv, "invalid band\n");
- return added;
- }
-
- active_dwell = iwl_legacy_get_active_dwell_time(priv, band, 0);
- passive_dwell = iwl_legacy_get_passive_dwell_time(priv, band, vif);
-
- if (passive_dwell <= active_dwell)
- passive_dwell = active_dwell + 1;
-
- channel = iwl_legacy_get_single_channel_number(priv, band);
- if (channel) {
- scan_ch->channel = cpu_to_le16(channel);
- scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE;
- scan_ch->active_dwell = cpu_to_le16(active_dwell);
- scan_ch->passive_dwell = cpu_to_le16(passive_dwell);
- /* Set txpower levels to defaults */
- scan_ch->dsp_atten = 110;
- if (band == IEEE80211_BAND_5GHZ)
- scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3;
- else
- scan_ch->tx_gain = ((1 << 5) | (5 << 3));
- added++;
- } else
- IWL_ERR(priv, "no valid channel found\n");
- return added;
-}
-
static int iwl4965_get_channels_for_scan(struct iwl_priv *priv,
struct ieee80211_vif *vif,
enum ieee80211_band band,
@@ -858,16 +817,13 @@
scan->quiet_time = IWL_ACTIVE_QUIET_TIME;
if (iwl_legacy_is_any_associated(priv)) {
- u16 interval = 0;
+ u16 interval;
u32 extra;
u32 suspend_time = 100;
u32 scan_suspend_time = 100;
IWL_DEBUG_INFO(priv, "Scanning while associated...\n");
- if (priv->is_internal_short_scan)
- interval = 0;
- else
- interval = vif->bss_conf.beacon_int;
+ interval = vif->bss_conf.beacon_int;
scan->suspend_time = 0;
scan->max_out_time = cpu_to_le32(200 * 1024);
@@ -882,9 +838,7 @@
scan_suspend_time, interval);
}
- if (priv->is_internal_short_scan) {
- IWL_DEBUG_SCAN(priv, "Start internal passive scan.\n");
- } else if (priv->scan_request->n_ssids) {
+ if (priv->scan_request->n_ssids) {
int i, p = 0;
IWL_DEBUG_SCAN(priv, "Kicking off active scan\n");
for (i = 0; i < priv->scan_request->n_ssids; i++) {
@@ -981,38 +935,21 @@
rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_SEL_POS;
rx_chain |= 0x1 << RXON_RX_CHAIN_DRIVER_FORCE_POS;
scan->rx_chain = cpu_to_le16(rx_chain);
- if (!priv->is_internal_short_scan) {
- cmd_len = iwl_legacy_fill_probe_req(priv,
+
+ cmd_len = iwl_legacy_fill_probe_req(priv,
(struct ieee80211_mgmt *)scan->data,
vif->addr,
priv->scan_request->ie,
priv->scan_request->ie_len,
IWL_MAX_SCAN_SIZE - sizeof(*scan));
- } else {
- /* use bcast addr, will not be transmitted but must be valid */
- cmd_len = iwl_legacy_fill_probe_req(priv,
- (struct ieee80211_mgmt *)scan->data,
- iwlegacy_bcast_addr, NULL, 0,
- IWL_MAX_SCAN_SIZE - sizeof(*scan));
-
- }
scan->tx_cmd.len = cpu_to_le16(cmd_len);
scan->filter_flags |= (RXON_FILTER_ACCEPT_GRP_MSK |
RXON_FILTER_BCON_AWARE_MSK);
- if (priv->is_internal_short_scan) {
- scan->channel_count =
- iwl4965_get_single_channel_for_scan(priv, vif, band,
- (void *)&scan->data[le16_to_cpu(
- scan->tx_cmd.len)]);
- } else {
- scan->channel_count =
- iwl4965_get_channels_for_scan(priv, vif, band,
- is_active, n_probes,
- (void *)&scan->data[le16_to_cpu(
- scan->tx_cmd.len)]);
- }
+ scan->channel_count = iwl4965_get_channels_for_scan(priv, vif, band,
+ is_active, n_probes,
+ (void *)&scan->data[cmd_len]);
if (scan->channel_count == 0) {
IWL_DEBUG_SCAN(priv, "channel count %d\n", scan->channel_count);
return -EIO;
diff --git a/drivers/net/wireless/iwlegacy/iwl-4965-rs.c b/drivers/net/wireless/iwlegacy/iwl-4965-rs.c
index 24d1499..9b65153 100644
--- a/drivers/net/wireless/iwlegacy/iwl-4965-rs.c
+++ b/drivers/net/wireless/iwlegacy/iwl-4965-rs.c
@@ -2275,6 +2275,9 @@
if (rate_control_send_low(sta, priv_sta, txrc))
return;
+ if (!lq_sta)
+ return;
+
rate_idx = lq_sta->last_txrate_idx;
if (lq_sta->last_rate_n_flags & RATE_MCS_HT_MSK) {
diff --git a/drivers/net/wireless/iwlegacy/iwl-4965-rx.c b/drivers/net/wireless/iwlegacy/iwl-4965-rx.c
index b9fa2f6..2b144bb 100644
--- a/drivers/net/wireless/iwlegacy/iwl-4965-rx.c
+++ b/drivers/net/wireless/iwlegacy/iwl-4965-rx.c
@@ -151,81 +151,6 @@
#define REG_RECALIB_PERIOD (60)
-/**
- * iwl4965_good_plcp_health - checks for plcp error.
- *
- * When the plcp error is exceeding the thresholds, reset the radio
- * to improve the throughput.
- */
-bool iwl4965_good_plcp_health(struct iwl_priv *priv,
- struct iwl_rx_packet *pkt)
-{
- bool rc = true;
- int combined_plcp_delta;
- unsigned int plcp_msec;
- unsigned long plcp_received_jiffies;
-
- if (priv->cfg->base_params->plcp_delta_threshold ==
- IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE) {
- IWL_DEBUG_RADIO(priv, "plcp_err check disabled\n");
- return rc;
- }
-
- /*
- * check for plcp_err and trigger radio reset if it exceeds
- * the plcp error threshold plcp_delta.
- */
- plcp_received_jiffies = jiffies;
- plcp_msec = jiffies_to_msecs((long) plcp_received_jiffies -
- (long) priv->plcp_jiffies);
- priv->plcp_jiffies = plcp_received_jiffies;
- /*
- * check to make sure plcp_msec is not 0 to prevent division
- * by zero.
- */
- if (plcp_msec) {
- struct statistics_rx_phy *ofdm;
- struct statistics_rx_ht_phy *ofdm_ht;
-
- ofdm = &pkt->u.stats.rx.ofdm;
- ofdm_ht = &pkt->u.stats.rx.ofdm_ht;
- combined_plcp_delta =
- (le32_to_cpu(ofdm->plcp_err) -
- le32_to_cpu(priv->_4965.statistics.
- rx.ofdm.plcp_err)) +
- (le32_to_cpu(ofdm_ht->plcp_err) -
- le32_to_cpu(priv->_4965.statistics.
- rx.ofdm_ht.plcp_err));
-
- if ((combined_plcp_delta > 0) &&
- ((combined_plcp_delta * 100) / plcp_msec) >
- priv->cfg->base_params->plcp_delta_threshold) {
- /*
- * if plcp_err exceed the threshold,
- * the following data is printed in csv format:
- * Text: plcp_err exceeded %d,
- * Received ofdm.plcp_err,
- * Current ofdm.plcp_err,
- * Received ofdm_ht.plcp_err,
- * Current ofdm_ht.plcp_err,
- * combined_plcp_delta,
- * plcp_msec
- */
- IWL_DEBUG_RADIO(priv, "plcp_err exceeded %u, "
- "%u, %u, %u, %u, %d, %u mSecs\n",
- priv->cfg->base_params->plcp_delta_threshold,
- le32_to_cpu(ofdm->plcp_err),
- le32_to_cpu(ofdm->plcp_err),
- le32_to_cpu(ofdm_ht->plcp_err),
- le32_to_cpu(ofdm_ht->plcp_err),
- combined_plcp_delta, plcp_msec);
-
- rc = false;
- }
- }
- return rc;
-}
-
void iwl4965_rx_statistics(struct iwl_priv *priv,
struct iwl_rx_mem_buffer *rxb)
{
@@ -248,8 +173,7 @@
iwl4965_accumulative_statistics(priv, (__le32 *)&pkt->u.stats);
#endif
- iwl_legacy_recover_from_statistics(priv, pkt);
-
+ /* TODO: reading some of statistics is unneeded */
memcpy(&priv->_4965.statistics, &pkt->u.stats,
sizeof(priv->_4965.statistics));
diff --git a/drivers/net/wireless/iwlegacy/iwl-4965.c b/drivers/net/wireless/iwlegacy/iwl-4965.c
index facc94e..bd4b000 100644
--- a/drivers/net/wireless/iwlegacy/iwl-4965.c
+++ b/drivers/net/wireless/iwlegacy/iwl-4965.c
@@ -496,7 +496,7 @@
channel <= CALIB_IWL_TX_ATTEN_GR4_LCH)
return CALIB_CH_GROUP_4;
- return -1;
+ return -EINVAL;
}
static u32 iwl4965_get_sub_band(const struct iwl_priv *priv, u32 channel)
@@ -915,7 +915,7 @@
if (txatten_grp < 0) {
IWL_ERR(priv, "Can't find txatten group for channel %d.\n",
channel);
- return -EINVAL;
+ return txatten_grp;
}
IWL_DEBUG_TXPOWER(priv, "channel %d belongs to txatten group %d\n",
@@ -1185,8 +1185,6 @@
ret = iwl_legacy_send_cmd_pdu_async(priv, REPLY_RXON_ASSOC,
sizeof(rxon_assoc), &rxon_assoc, NULL);
- if (ret)
- return ret;
return ret;
}
@@ -2071,7 +2069,6 @@
.is_valid_rtc_data_addr = iwl4965_hw_valid_rtc_data_addr,
.init_alive_start = iwl4965_init_alive_start,
.load_ucode = iwl4965_load_bsm,
- .dump_nic_event_log = iwl4965_dump_nic_event_log,
.dump_nic_error_log = iwl4965_dump_nic_error_log,
.dump_fh = iwl4965_dump_fh,
.set_channel_switch = iwl4965_hw_channel_switch,
@@ -2102,7 +2099,6 @@
.tx_stats_read = iwl4965_ucode_tx_stats_read,
.general_stats_read = iwl4965_ucode_general_stats_read,
},
- .check_plcp_health = iwl4965_good_plcp_health,
};
static const struct iwl_legacy_ops iwl4965_legacy_ops = {
@@ -2152,10 +2148,8 @@
.use_bsm = true,
.led_compensation = 61,
.chain_noise_num_beacons = IWL4965_CAL_NUM_BEACONS,
- .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
.wd_timeout = IWL_DEF_WD_TIMEOUT,
.temperature_kelvin = true,
- .max_event_log_size = 512,
.ucode_tracing = true,
.sensitivity_calib_by_driver = true,
.chain_noise_calib_by_driver = true,
diff --git a/drivers/net/wireless/iwlegacy/iwl-commands.h b/drivers/net/wireless/iwlegacy/iwl-commands.h
index 17a1d50..ee21210 100644
--- a/drivers/net/wireless/iwlegacy/iwl-commands.h
+++ b/drivers/net/wireless/iwlegacy/iwl-commands.h
@@ -2297,14 +2297,7 @@
#define IWL_POWER_VEC_SIZE 5
#define IWL_POWER_DRIVER_ALLOW_SLEEP_MSK cpu_to_le16(BIT(0))
-#define IWL_POWER_POWER_SAVE_ENA_MSK cpu_to_le16(BIT(0))
-#define IWL_POWER_POWER_MANAGEMENT_ENA_MSK cpu_to_le16(BIT(1))
-#define IWL_POWER_SLEEP_OVER_DTIM_MSK cpu_to_le16(BIT(2))
#define IWL_POWER_PCI_PM_MSK cpu_to_le16(BIT(3))
-#define IWL_POWER_FAST_PD cpu_to_le16(BIT(4))
-#define IWL_POWER_BEACON_FILTERING cpu_to_le16(BIT(5))
-#define IWL_POWER_SHADOW_REG_ENA cpu_to_le16(BIT(6))
-#define IWL_POWER_CT_KILL_SET cpu_to_le16(BIT(7))
struct iwl3945_powertable_cmd {
__le16 flags;
diff --git a/drivers/net/wireless/iwlegacy/iwl-core.c b/drivers/net/wireless/iwlegacy/iwl-core.c
index 3be76bd..35cd2537 100644
--- a/drivers/net/wireless/iwlegacy/iwl-core.c
+++ b/drivers/net/wireless/iwlegacy/iwl-core.c
@@ -931,7 +931,6 @@
priv->cfg->ops->lib->dump_nic_error_log(priv);
if (priv->cfg->ops->lib->dump_fh)
priv->cfg->ops->lib->dump_fh(priv, NULL, false);
- priv->cfg->ops->lib->dump_nic_event_log(priv, false, NULL, false);
#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
if (iwl_legacy_get_debug_level(priv) & IWL_DL_FW_ERRORS)
iwl_legacy_print_rx_config_cmd(priv,
@@ -1707,41 +1706,14 @@
EXPORT_SYMBOL(iwl_legacy_update_stats);
#endif
-static void _iwl_legacy_force_rf_reset(struct iwl_priv *priv)
-{
- if (test_bit(STATUS_EXIT_PENDING, &priv->status))
- return;
-
- if (!iwl_legacy_is_any_associated(priv)) {
- IWL_DEBUG_SCAN(priv, "force reset rejected: not associated\n");
- return;
- }
- /*
- * There is no easy and better way to force reset the radio,
- * the only known method is switching channel which will force to
- * reset and tune the radio.
- * Use internal short scan (single channel) operation to should
- * achieve this objective.
- * Driver should reset the radio when number of consecutive missed
- * beacon, or any other uCode error condition detected.
- */
- IWL_DEBUG_INFO(priv, "perform radio reset.\n");
- iwl_legacy_internal_short_hw_scan(priv);
-}
-
-
-int iwl_legacy_force_reset(struct iwl_priv *priv, int mode, bool external)
+int iwl_legacy_force_reset(struct iwl_priv *priv, bool external)
{
struct iwl_force_reset *force_reset;
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return -EINVAL;
- if (mode >= IWL_MAX_FORCE_RESET) {
- IWL_DEBUG_INFO(priv, "invalid reset request.\n");
- return -EINVAL;
- }
- force_reset = &priv->force_reset[mode];
+ force_reset = &priv->force_reset;
force_reset->reset_request_count++;
if (!external) {
if (force_reset->last_force_reset_jiffies &&
@@ -1754,37 +1726,34 @@
}
force_reset->reset_success_count++;
force_reset->last_force_reset_jiffies = jiffies;
- IWL_DEBUG_INFO(priv, "perform force reset (%d)\n", mode);
- switch (mode) {
- case IWL_RF_RESET:
- _iwl_legacy_force_rf_reset(priv);
- break;
- case IWL_FW_RESET:
- /*
- * if the request is from external(ex: debugfs),
- * then always perform the request in regardless the module
- * parameter setting
- * if the request is from internal (uCode error or driver
- * detect failure), then fw_restart module parameter
- * need to be check before performing firmware reload
- */
- if (!external && !priv->cfg->mod_params->restart_fw) {
- IWL_DEBUG_INFO(priv, "Cancel firmware reload based on "
- "module parameter setting\n");
- break;
- }
- IWL_ERR(priv, "On demand firmware reload\n");
- /* Set the FW error flag -- cleared on iwl_down */
- set_bit(STATUS_FW_ERROR, &priv->status);
- wake_up_interruptible(&priv->wait_command_queue);
- /*
- * Keep the restart process from trying to send host
- * commands by clearing the INIT status bit
- */
- clear_bit(STATUS_READY, &priv->status);
- queue_work(priv->workqueue, &priv->restart);
- break;
+
+ /*
+ * if the request is from external(ex: debugfs),
+ * then always perform the request in regardless the module
+ * parameter setting
+ * if the request is from internal (uCode error or driver
+ * detect failure), then fw_restart module parameter
+ * need to be check before performing firmware reload
+ */
+
+ if (!external && !priv->cfg->mod_params->restart_fw) {
+ IWL_DEBUG_INFO(priv, "Cancel firmware reload based on "
+ "module parameter setting\n");
+ return 0;
}
+
+ IWL_ERR(priv, "On demand firmware reload\n");
+
+ /* Set the FW error flag -- cleared on iwl_down */
+ set_bit(STATUS_FW_ERROR, &priv->status);
+ wake_up_interruptible(&priv->wait_command_queue);
+ /*
+ * Keep the restart process from trying to send host
+ * commands by clearing the INIT status bit
+ */
+ clear_bit(STATUS_READY, &priv->status);
+ queue_work(priv->workqueue, &priv->restart);
+
return 0;
}
@@ -1879,7 +1848,7 @@
if (time_after(jiffies, timeout)) {
IWL_ERR(priv, "Queue %d stuck for %u ms.\n",
q->id, priv->cfg->base_params->wd_timeout);
- ret = iwl_legacy_force_reset(priv, IWL_FW_RESET, false);
+ ret = iwl_legacy_force_reset(priv, false);
return (ret == -EAGAIN) ? 0 : 1;
}
diff --git a/drivers/net/wireless/iwlegacy/iwl-core.h b/drivers/net/wireless/iwlegacy/iwl-core.h
index c5fbda0..84da793 100644
--- a/drivers/net/wireless/iwlegacy/iwl-core.h
+++ b/drivers/net/wireless/iwlegacy/iwl-core.h
@@ -143,8 +143,7 @@
int (*is_valid_rtc_data_addr)(u32 addr);
/* 1st ucode load */
int (*load_ucode)(struct iwl_priv *priv);
- int (*dump_nic_event_log)(struct iwl_priv *priv,
- bool full_log, char **buf, bool display);
+
void (*dump_nic_error_log)(struct iwl_priv *priv);
int (*dump_fh)(struct iwl_priv *priv, char **buf, bool display);
int (*set_channel_switch)(struct iwl_priv *priv,
@@ -161,9 +160,6 @@
/* temperature */
struct iwl_temp_ops temp_ops;
- /* check for plcp health */
- bool (*check_plcp_health)(struct iwl_priv *priv,
- struct iwl_rx_packet *pkt);
struct iwl_debugfs_ops debugfs_ops;
@@ -207,11 +203,8 @@
* to the deviation to achieve the desired led frequency.
* The detail algorithm is described in iwl-led.c
* @chain_noise_num_beacons: number of beacons used to compute chain noise
- * @plcp_delta_threshold: plcp error rate threshold used to trigger
- * radio tuning when there is a high receiving plcp error rate
* @wd_timeout: TX queues watchdog timeout
* @temperature_kelvin: temperature report by uCode in kelvin
- * @max_event_log_size: size of event log buffer size for ucode event logging
* @ucode_tracing: support ucode continuous tracing
* @sensitivity_calib_by_driver: driver has the capability to perform
* sensitivity calibration operation
@@ -229,10 +222,8 @@
u16 led_compensation;
int chain_noise_num_beacons;
- u8 plcp_delta_threshold;
unsigned int wd_timeout;
bool temperature_kelvin;
- u32 max_event_log_size;
const bool ucode_tracing;
const bool sensitivity_calib_by_driver;
const bool chain_noise_calib_by_driver;
@@ -441,7 +432,7 @@
struct ieee80211_vif *vif,
struct cfg80211_scan_request *req);
void iwl_legacy_internal_short_hw_scan(struct iwl_priv *priv);
-int iwl_legacy_force_reset(struct iwl_priv *priv, int mode, bool external);
+int iwl_legacy_force_reset(struct iwl_priv *priv, bool external);
u16 iwl_legacy_fill_probe_req(struct iwl_priv *priv,
struct ieee80211_mgmt *frame,
const u8 *ta, const u8 *ie, int ie_len, int left);
@@ -493,7 +484,7 @@
{
int pos;
u16 pci_lnk_ctl;
- pos = pci_find_capability(priv->pci_dev, PCI_CAP_ID_EXP);
+ pos = pci_pcie_cap(priv->pci_dev);
pci_read_config_word(priv->pci_dev, pos + PCI_EXP_LNKCTL, &pci_lnk_ctl);
return pci_lnk_ctl;
}
@@ -521,8 +512,6 @@
* Error Handling Debugging
******************************************************/
void iwl4965_dump_nic_error_log(struct iwl_priv *priv);
-int iwl4965_dump_nic_event_log(struct iwl_priv *priv,
- bool full_log, char **buf, bool display);
#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
void iwl_legacy_print_rx_config_cmd(struct iwl_priv *priv,
struct iwl_rxon_context *ctx);
diff --git a/drivers/net/wireless/iwlegacy/iwl-debugfs.c b/drivers/net/wireless/iwlegacy/iwl-debugfs.c
index 2d32438..996996a 100644
--- a/drivers/net/wireless/iwlegacy/iwl-debugfs.c
+++ b/drivers/net/wireless/iwlegacy/iwl-debugfs.c
@@ -391,48 +391,6 @@
return ret;
}
-static ssize_t iwl_legacy_dbgfs_log_event_read(struct file *file,
- char __user *user_buf,
- size_t count, loff_t *ppos)
-{
- struct iwl_priv *priv = file->private_data;
- char *buf;
- int pos = 0;
- ssize_t ret = -ENOMEM;
-
- ret = pos = priv->cfg->ops->lib->dump_nic_event_log(
- priv, true, &buf, true);
- if (buf) {
- ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
- kfree(buf);
- }
- return ret;
-}
-
-static ssize_t iwl_legacy_dbgfs_log_event_write(struct file *file,
- const char __user *user_buf,
- size_t count, loff_t *ppos)
-{
- struct iwl_priv *priv = file->private_data;
- u32 event_log_flag;
- char buf[8];
- int buf_size;
-
- memset(buf, 0, sizeof(buf));
- buf_size = min(count, sizeof(buf) - 1);
- if (copy_from_user(buf, user_buf, buf_size))
- return -EFAULT;
- if (sscanf(buf, "%d", &event_log_flag) != 1)
- return -EFAULT;
- if (event_log_flag == 1)
- priv->cfg->ops->lib->dump_nic_event_log(priv, true,
- NULL, false);
-
- return count;
-}
-
-
-
static ssize_t
iwl_legacy_dbgfs_channels_read(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
@@ -706,7 +664,6 @@
}
DEBUGFS_READ_WRITE_FILE_OPS(sram);
-DEBUGFS_READ_WRITE_FILE_OPS(log_event);
DEBUGFS_READ_FILE_OPS(nvm);
DEBUGFS_READ_FILE_OPS(stations);
DEBUGFS_READ_FILE_OPS(channels);
@@ -1098,56 +1055,6 @@
return count;
}
-static ssize_t iwl_legacy_dbgfs_ucode_tracing_read(struct file *file,
- char __user *user_buf,
- size_t count, loff_t *ppos) {
-
- struct iwl_priv *priv = file->private_data;
- int pos = 0;
- char buf[128];
- const size_t bufsz = sizeof(buf);
-
- pos += scnprintf(buf + pos, bufsz - pos, "ucode trace timer is %s\n",
- priv->event_log.ucode_trace ? "On" : "Off");
- pos += scnprintf(buf + pos, bufsz - pos, "non_wraps_count:\t\t %u\n",
- priv->event_log.non_wraps_count);
- pos += scnprintf(buf + pos, bufsz - pos, "wraps_once_count:\t\t %u\n",
- priv->event_log.wraps_once_count);
- pos += scnprintf(buf + pos, bufsz - pos, "wraps_more_count:\t\t %u\n",
- priv->event_log.wraps_more_count);
-
- return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
-}
-
-static ssize_t iwl_legacy_dbgfs_ucode_tracing_write(struct file *file,
- const char __user *user_buf,
- size_t count, loff_t *ppos)
-{
- struct iwl_priv *priv = file->private_data;
- char buf[8];
- int buf_size;
- int trace;
-
- memset(buf, 0, sizeof(buf));
- buf_size = min(count, sizeof(buf) - 1);
- if (copy_from_user(buf, user_buf, buf_size))
- return -EFAULT;
- if (sscanf(buf, "%d", &trace) != 1)
- return -EFAULT;
-
- if (trace) {
- priv->event_log.ucode_trace = true;
- /* schedule the ucode timer to occur in UCODE_TRACE_PERIOD */
- mod_timer(&priv->ucode_trace,
- jiffies + msecs_to_jiffies(UCODE_TRACE_PERIOD));
- } else {
- priv->event_log.ucode_trace = false;
- del_timer_sync(&priv->ucode_trace);
- }
-
- return count;
-}
-
static ssize_t iwl_legacy_dbgfs_rxon_flags_read(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos) {
@@ -1236,72 +1143,31 @@
return count;
}
-static ssize_t iwl_legacy_dbgfs_plcp_delta_read(struct file *file,
- char __user *user_buf,
- size_t count, loff_t *ppos) {
-
- struct iwl_priv *priv = file->private_data;
- int pos = 0;
- char buf[12];
- const size_t bufsz = sizeof(buf);
-
- pos += scnprintf(buf + pos, bufsz - pos, "%u\n",
- priv->cfg->base_params->plcp_delta_threshold);
-
- return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
-}
-
-static ssize_t iwl_legacy_dbgfs_plcp_delta_write(struct file *file,
- const char __user *user_buf,
- size_t count, loff_t *ppos) {
-
- struct iwl_priv *priv = file->private_data;
- char buf[8];
- int buf_size;
- int plcp;
-
- memset(buf, 0, sizeof(buf));
- buf_size = min(count, sizeof(buf) - 1);
- if (copy_from_user(buf, user_buf, buf_size))
- return -EFAULT;
- if (sscanf(buf, "%d", &plcp) != 1)
- return -EINVAL;
- if ((plcp < IWL_MAX_PLCP_ERR_THRESHOLD_MIN) ||
- (plcp > IWL_MAX_PLCP_ERR_THRESHOLD_MAX))
- priv->cfg->base_params->plcp_delta_threshold =
- IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE;
- else
- priv->cfg->base_params->plcp_delta_threshold = plcp;
- return count;
-}
-
static ssize_t iwl_legacy_dbgfs_force_reset_read(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos) {
struct iwl_priv *priv = file->private_data;
- int i, pos = 0;
+ int pos = 0;
char buf[300];
const size_t bufsz = sizeof(buf);
struct iwl_force_reset *force_reset;
- for (i = 0; i < IWL_MAX_FORCE_RESET; i++) {
- force_reset = &priv->force_reset[i];
- pos += scnprintf(buf + pos, bufsz - pos,
- "Force reset method %d\n", i);
- pos += scnprintf(buf + pos, bufsz - pos,
- "\tnumber of reset request: %d\n",
- force_reset->reset_request_count);
- pos += scnprintf(buf + pos, bufsz - pos,
- "\tnumber of reset request success: %d\n",
- force_reset->reset_success_count);
- pos += scnprintf(buf + pos, bufsz - pos,
- "\tnumber of reset request reject: %d\n",
- force_reset->reset_reject_count);
- pos += scnprintf(buf + pos, bufsz - pos,
- "\treset duration: %lu\n",
- force_reset->reset_duration);
- }
+ force_reset = &priv->force_reset;
+
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "\tnumber of reset request: %d\n",
+ force_reset->reset_request_count);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "\tnumber of reset request success: %d\n",
+ force_reset->reset_success_count);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "\tnumber of reset request reject: %d\n",
+ force_reset->reset_reject_count);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "\treset duration: %lu\n",
+ force_reset->reset_duration);
+
return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
}
@@ -1309,25 +1175,11 @@
const char __user *user_buf,
size_t count, loff_t *ppos) {
+ int ret;
struct iwl_priv *priv = file->private_data;
- char buf[8];
- int buf_size;
- int reset, ret;
- memset(buf, 0, sizeof(buf));
- buf_size = min(count, sizeof(buf) - 1);
- if (copy_from_user(buf, user_buf, buf_size))
- return -EFAULT;
- if (sscanf(buf, "%d", &reset) != 1)
- return -EINVAL;
- switch (reset) {
- case IWL_RF_RESET:
- case IWL_FW_RESET:
- ret = iwl_legacy_force_reset(priv, reset, true);
- break;
- default:
- return -EINVAL;
- }
+ ret = iwl_legacy_force_reset(priv, true);
+
return ret ? ret : count;
}
@@ -1367,10 +1219,8 @@
DEBUGFS_READ_FILE_OPS(power_save_status);
DEBUGFS_WRITE_FILE_OPS(clear_ucode_statistics);
DEBUGFS_WRITE_FILE_OPS(clear_traffic_statistics);
-DEBUGFS_READ_WRITE_FILE_OPS(ucode_tracing);
DEBUGFS_READ_FILE_OPS(fh_reg);
DEBUGFS_READ_WRITE_FILE_OPS(missed_beacon);
-DEBUGFS_READ_WRITE_FILE_OPS(plcp_delta);
DEBUGFS_READ_WRITE_FILE_OPS(force_reset);
DEBUGFS_READ_FILE_OPS(rxon_flags);
DEBUGFS_READ_FILE_OPS(rxon_filter_flags);
@@ -1403,7 +1253,6 @@
DEBUGFS_ADD_FILE(nvm, dir_data, S_IRUSR);
DEBUGFS_ADD_FILE(sram, dir_data, S_IWUSR | S_IRUSR);
- DEBUGFS_ADD_FILE(log_event, dir_data, S_IWUSR | S_IRUSR);
DEBUGFS_ADD_FILE(stations, dir_data, S_IRUSR);
DEBUGFS_ADD_FILE(channels, dir_data, S_IRUSR);
DEBUGFS_ADD_FILE(status, dir_data, S_IRUSR);
@@ -1420,7 +1269,6 @@
DEBUGFS_ADD_FILE(clear_traffic_statistics, dir_debug, S_IWUSR);
DEBUGFS_ADD_FILE(fh_reg, dir_debug, S_IRUSR);
DEBUGFS_ADD_FILE(missed_beacon, dir_debug, S_IWUSR);
- DEBUGFS_ADD_FILE(plcp_delta, dir_debug, S_IWUSR | S_IRUSR);
DEBUGFS_ADD_FILE(force_reset, dir_debug, S_IWUSR | S_IRUSR);
DEBUGFS_ADD_FILE(ucode_rx_stats, dir_debug, S_IRUSR);
DEBUGFS_ADD_FILE(ucode_tx_stats, dir_debug, S_IRUSR);
@@ -1430,8 +1278,6 @@
DEBUGFS_ADD_FILE(sensitivity, dir_debug, S_IRUSR);
if (priv->cfg->base_params->chain_noise_calib_by_driver)
DEBUGFS_ADD_FILE(chain_noise, dir_debug, S_IRUSR);
- if (priv->cfg->base_params->ucode_tracing)
- DEBUGFS_ADD_FILE(ucode_tracing, dir_debug, S_IWUSR | S_IRUSR);
DEBUGFS_ADD_FILE(rxon_flags, dir_debug, S_IWUSR);
DEBUGFS_ADD_FILE(rxon_filter_flags, dir_debug, S_IWUSR);
DEBUGFS_ADD_FILE(wd_timeout, dir_debug, S_IWUSR);
diff --git a/drivers/net/wireless/iwlegacy/iwl-dev.h b/drivers/net/wireless/iwlegacy/iwl-dev.h
index ea30122..9c786ed 100644
--- a/drivers/net/wireless/iwlegacy/iwl-dev.h
+++ b/drivers/net/wireless/iwlegacy/iwl-dev.h
@@ -32,6 +32,7 @@
#ifndef __iwl_legacy_dev_h__
#define __iwl_legacy_dev_h__
+#include <linux/interrupt.h>
#include <linux/pci.h> /* for struct pci_device_id */
#include <linux/kernel.h>
#include <linux/leds.h>
@@ -855,32 +856,6 @@
};
/*
- * schedule the timer to wake up every UCODE_TRACE_PERIOD milliseconds
- * to perform continuous uCode event logging operation if enabled
- */
-#define UCODE_TRACE_PERIOD (100)
-
-/*
- * iwl_event_log: current uCode event log position
- *
- * @ucode_trace: enable/disable ucode continuous trace timer
- * @num_wraps: how many times the event buffer wraps
- * @next_entry: the entry just before the next one that uCode would fill
- * @non_wraps_count: counter for no wrap detected when dump ucode events
- * @wraps_once_count: counter for wrap once detected when dump ucode events
- * @wraps_more_count: counter for wrap more than once detected
- * when dump ucode events
- */
-struct iwl_event_log {
- bool ucode_trace;
- u32 num_wraps;
- u32 next_entry;
- int non_wraps_count;
- int wraps_once_count;
- int wraps_more_count;
-};
-
-/*
* host interrupt timeout value
* used with setting interrupt coalescing timer
* the CSR_INT_COALESCING is an 8 bit register in 32-usec unit
@@ -895,18 +870,6 @@
#define IWL_HOST_INT_CALIB_TIMEOUT_DEF (0x10)
#define IWL_HOST_INT_CALIB_TIMEOUT_MIN (0x0)
-/*
- * This is the threshold value of plcp error rate per 100mSecs. It is
- * used to set and check for the validity of plcp_delta.
- */
-#define IWL_MAX_PLCP_ERR_THRESHOLD_MIN (1)
-#define IWL_MAX_PLCP_ERR_THRESHOLD_DEF (50)
-#define IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF (100)
-#define IWL_MAX_PLCP_ERR_EXT_LONG_THRESHOLD_DEF (200)
-#define IWL_MAX_PLCP_ERR_THRESHOLD_MAX (255)
-#define IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE (0)
-
-#define IWL_DELAY_NEXT_FORCE_RF_RESET (HZ*3)
#define IWL_DELAY_NEXT_FORCE_FW_RELOAD (HZ*5)
/* TX queue watchdog timeouts in mSecs */
@@ -914,12 +877,6 @@
#define IWL_LONG_WD_TIMEOUT (10000)
#define IWL_MAX_WD_TIMEOUT (120000)
-enum iwl_reset {
- IWL_RF_RESET = 0,
- IWL_FW_RESET,
- IWL_MAX_FORCE_RESET,
-};
-
struct iwl_force_reset {
int reset_request_count;
int reset_success_count;
@@ -1032,11 +989,8 @@
/* track IBSS manager (last beacon) status */
u32 ibss_manager;
- /* storing the jiffies when the plcp error rate is received */
- unsigned long plcp_jiffies;
-
/* force reset */
- struct iwl_force_reset force_reset[IWL_MAX_FORCE_RESET];
+ struct iwl_force_reset force_reset;
/* we allocate array of iwl_channel_info for NIC's valid channels.
* Access via channel # using indirect index array */
@@ -1057,7 +1011,6 @@
enum ieee80211_band scan_band;
struct cfg80211_scan_request *scan_request;
struct ieee80211_vif *scan_vif;
- bool is_internal_short_scan;
u8 scan_tx_ant[IEEE80211_NUM_BANDS];
u8 mgmt_tx_ant;
@@ -1212,12 +1165,6 @@
#endif
#if defined(CONFIG_IWL4965) || defined(CONFIG_IWL4965_MODULE)
struct {
- /*
- * reporting the number of tids has AGG on. 0 means
- * no AGGREGATION
- */
- u8 agg_tids_count;
-
struct iwl_rx_phy_res last_phy_res;
bool last_phy_res_valid;
@@ -1256,7 +1203,6 @@
struct iwl_rxon_context *beacon_ctx;
struct sk_buff *beacon_skb;
- struct work_struct start_internal_scan;
struct work_struct tx_flush;
struct tasklet_struct irq_tasklet;
@@ -1293,12 +1239,9 @@
u32 disable_tx_power_cal;
struct work_struct run_time_calib_work;
struct timer_list statistics_periodic;
- struct timer_list ucode_trace;
struct timer_list watchdog;
bool hw_ready;
- struct iwl_event_log event_log;
-
struct led_classdev led;
unsigned long blink_on, blink_off;
bool led_registered;
diff --git a/drivers/net/wireless/iwlegacy/iwl-devtrace.c b/drivers/net/wireless/iwlegacy/iwl-devtrace.c
index 080b852..acec991 100644
--- a/drivers/net/wireless/iwlegacy/iwl-devtrace.c
+++ b/drivers/net/wireless/iwlegacy/iwl-devtrace.c
@@ -38,8 +38,5 @@
EXPORT_TRACEPOINT_SYMBOL(iwlwifi_legacy_dev_iowrite32);
EXPORT_TRACEPOINT_SYMBOL(iwlwifi_legacy_dev_rx);
EXPORT_TRACEPOINT_SYMBOL(iwlwifi_legacy_dev_tx);
-EXPORT_TRACEPOINT_SYMBOL(iwlwifi_legacy_dev_ucode_event);
EXPORT_TRACEPOINT_SYMBOL(iwlwifi_legacy_dev_ucode_error);
-EXPORT_TRACEPOINT_SYMBOL(iwlwifi_legacy_dev_ucode_cont_event);
-EXPORT_TRACEPOINT_SYMBOL(iwlwifi_legacy_dev_ucode_wrap_event);
#endif
diff --git a/drivers/net/wireless/iwlegacy/iwl-devtrace.h b/drivers/net/wireless/iwlegacy/iwl-devtrace.h
index 9612aa0..a443725 100644
--- a/drivers/net/wireless/iwlegacy/iwl-devtrace.h
+++ b/drivers/net/wireless/iwlegacy/iwl-devtrace.h
@@ -96,47 +96,6 @@
#undef TRACE_SYSTEM
#define TRACE_SYSTEM iwlwifi_legacy_ucode
-TRACE_EVENT(iwlwifi_legacy_dev_ucode_cont_event,
- TP_PROTO(struct iwl_priv *priv, u32 time, u32 data, u32 ev),
- TP_ARGS(priv, time, data, ev),
- TP_STRUCT__entry(
- PRIV_ENTRY
-
- __field(u32, time)
- __field(u32, data)
- __field(u32, ev)
- ),
- TP_fast_assign(
- PRIV_ASSIGN;
- __entry->time = time;
- __entry->data = data;
- __entry->ev = ev;
- ),
- TP_printk("[%p] EVT_LOGT:%010u:0x%08x:%04u",
- __entry->priv, __entry->time, __entry->data, __entry->ev)
-);
-
-TRACE_EVENT(iwlwifi_legacy_dev_ucode_wrap_event,
- TP_PROTO(struct iwl_priv *priv, u32 wraps, u32 n_entry, u32 p_entry),
- TP_ARGS(priv, wraps, n_entry, p_entry),
- TP_STRUCT__entry(
- PRIV_ENTRY
-
- __field(u32, wraps)
- __field(u32, n_entry)
- __field(u32, p_entry)
- ),
- TP_fast_assign(
- PRIV_ASSIGN;
- __entry->wraps = wraps;
- __entry->n_entry = n_entry;
- __entry->p_entry = p_entry;
- ),
- TP_printk("[%p] wraps=#%02d n=0x%X p=0x%X",
- __entry->priv, __entry->wraps, __entry->n_entry,
- __entry->p_entry)
-);
-
#undef TRACE_SYSTEM
#define TRACE_SYSTEM iwlwifi
@@ -242,25 +201,6 @@
__entry->blink2, __entry->ilink1, __entry->ilink2)
);
-TRACE_EVENT(iwlwifi_legacy_dev_ucode_event,
- TP_PROTO(struct iwl_priv *priv, u32 time, u32 data, u32 ev),
- TP_ARGS(priv, time, data, ev),
- TP_STRUCT__entry(
- PRIV_ENTRY
-
- __field(u32, time)
- __field(u32, data)
- __field(u32, ev)
- ),
- TP_fast_assign(
- PRIV_ASSIGN;
- __entry->time = time;
- __entry->data = data;
- __entry->ev = ev;
- ),
- TP_printk("[%p] EVT_LOGT:%010u:0x%08x:%04u",
- __entry->priv, __entry->time, __entry->data, __entry->ev)
-);
#endif /* __IWLWIFI_DEVICE_TRACE */
#undef TRACE_INCLUDE_PATH
diff --git a/drivers/net/wireless/iwlegacy/iwl-eeprom.c b/drivers/net/wireless/iwlegacy/iwl-eeprom.c
index cb346d1..5bf3f49 100644
--- a/drivers/net/wireless/iwlegacy/iwl-eeprom.c
+++ b/drivers/net/wireless/iwlegacy/iwl-eeprom.c
@@ -316,7 +316,6 @@
break;
default:
BUG();
- return;
}
}
diff --git a/drivers/net/wireless/iwlegacy/iwl-helpers.h b/drivers/net/wireless/iwlegacy/iwl-helpers.h
index a6effda..5cf23ea 100644
--- a/drivers/net/wireless/iwlegacy/iwl-helpers.h
+++ b/drivers/net/wireless/iwlegacy/iwl-helpers.h
@@ -132,7 +132,16 @@
ieee80211_stop_queue(priv->hw, ac);
}
+#ifdef ieee80211_stop_queue
+#undef ieee80211_stop_queue
+#endif
+
#define ieee80211_stop_queue DO_NOT_USE_ieee80211_stop_queue
+
+#ifdef ieee80211_wake_queue
+#undef ieee80211_wake_queue
+#endif
+
#define ieee80211_wake_queue DO_NOT_USE_ieee80211_wake_queue
static inline void iwl_legacy_disable_interrupts(struct iwl_priv *priv)
diff --git a/drivers/net/wireless/iwlegacy/iwl-rx.c b/drivers/net/wireless/iwlegacy/iwl-rx.c
index 654cf23..9b5d0ab 100644
--- a/drivers/net/wireless/iwlegacy/iwl-rx.c
+++ b/drivers/net/wireless/iwlegacy/iwl-rx.c
@@ -227,27 +227,6 @@
}
EXPORT_SYMBOL(iwl_legacy_rx_spectrum_measure_notif);
-void iwl_legacy_recover_from_statistics(struct iwl_priv *priv,
- struct iwl_rx_packet *pkt)
-{
- if (test_bit(STATUS_EXIT_PENDING, &priv->status))
- return;
- if (iwl_legacy_is_any_associated(priv)) {
- if (priv->cfg->ops->lib->check_plcp_health) {
- if (!priv->cfg->ops->lib->check_plcp_health(
- priv, pkt)) {
- /*
- * high plcp error detected
- * reset Radio
- */
- iwl_legacy_force_reset(priv,
- IWL_RF_RESET, false);
- }
- }
- }
-}
-EXPORT_SYMBOL(iwl_legacy_recover_from_statistics);
-
/*
* returns non-zero if packet should be dropped
*/
diff --git a/drivers/net/wireless/iwlegacy/iwl-scan.c b/drivers/net/wireless/iwlegacy/iwl-scan.c
index 353234a..a6b5222 100644
--- a/drivers/net/wireless/iwlegacy/iwl-scan.c
+++ b/drivers/net/wireless/iwlegacy/iwl-scan.c
@@ -101,7 +101,6 @@
ieee80211_scan_completed(priv->hw, aborted);
}
- priv->is_internal_short_scan = false;
priv->scan_vif = NULL;
priv->scan_request = NULL;
}
@@ -329,10 +328,8 @@
}
EXPORT_SYMBOL(iwl_legacy_init_scan_params);
-static int __must_check iwl_legacy_scan_initiate(struct iwl_priv *priv,
- struct ieee80211_vif *vif,
- bool internal,
- enum ieee80211_band band)
+static int iwl_legacy_scan_initiate(struct iwl_priv *priv,
+ struct ieee80211_vif *vif)
{
int ret;
@@ -359,18 +356,14 @@
return -EBUSY;
}
- IWL_DEBUG_SCAN(priv, "Starting %sscan...\n",
- internal ? "internal short " : "");
+ IWL_DEBUG_SCAN(priv, "Starting scan...\n");
set_bit(STATUS_SCANNING, &priv->status);
- priv->is_internal_short_scan = internal;
priv->scan_start = jiffies;
- priv->scan_band = band;
ret = priv->cfg->ops->utils->request_scan(priv, vif);
if (ret) {
clear_bit(STATUS_SCANNING, &priv->status);
- priv->is_internal_short_scan = false;
return ret;
}
@@ -394,8 +387,7 @@
mutex_lock(&priv->mutex);
- if (test_bit(STATUS_SCANNING, &priv->status) &&
- !priv->is_internal_short_scan) {
+ if (test_bit(STATUS_SCANNING, &priv->status)) {
IWL_DEBUG_SCAN(priv, "Scan already in progress.\n");
ret = -EAGAIN;
goto out_unlock;
@@ -404,17 +396,9 @@
/* mac80211 will only ask for one band at a time */
priv->scan_request = req;
priv->scan_vif = vif;
+ priv->scan_band = req->channels[0]->band;
- /*
- * If an internal scan is in progress, just set
- * up the scan_request as per above.
- */
- if (priv->is_internal_short_scan) {
- IWL_DEBUG_SCAN(priv, "SCAN request during internal scan\n");
- ret = 0;
- } else
- ret = iwl_legacy_scan_initiate(priv, vif, false,
- req->channels[0]->band);
+ ret = iwl_legacy_scan_initiate(priv, vif);
IWL_DEBUG_MAC80211(priv, "leave\n");
@@ -425,40 +409,6 @@
}
EXPORT_SYMBOL(iwl_legacy_mac_hw_scan);
-/*
- * internal short scan, this function should only been called while associated.
- * It will reset and tune the radio to prevent possible RF related problem
- */
-void iwl_legacy_internal_short_hw_scan(struct iwl_priv *priv)
-{
- queue_work(priv->workqueue, &priv->start_internal_scan);
-}
-
-static void iwl_legacy_bg_start_internal_scan(struct work_struct *work)
-{
- struct iwl_priv *priv =
- container_of(work, struct iwl_priv, start_internal_scan);
-
- IWL_DEBUG_SCAN(priv, "Start internal scan\n");
-
- mutex_lock(&priv->mutex);
-
- if (priv->is_internal_short_scan == true) {
- IWL_DEBUG_SCAN(priv, "Internal scan already in progress\n");
- goto unlock;
- }
-
- if (test_bit(STATUS_SCANNING, &priv->status)) {
- IWL_DEBUG_SCAN(priv, "Scan already in progress.\n");
- goto unlock;
- }
-
- if (iwl_legacy_scan_initiate(priv, NULL, true, priv->band))
- IWL_DEBUG_SCAN(priv, "failed to start internal short scan\n");
- unlock:
- mutex_unlock(&priv->mutex);
-}
-
static void iwl_legacy_bg_scan_check(struct work_struct *data)
{
struct iwl_priv *priv =
@@ -542,8 +492,7 @@
container_of(work, struct iwl_priv, scan_completed);
bool aborted;
- IWL_DEBUG_SCAN(priv, "Completed %sscan.\n",
- priv->is_internal_short_scan ? "internal short " : "");
+ IWL_DEBUG_SCAN(priv, "Completed scan.\n");
cancel_delayed_work(&priv->scan_check);
@@ -558,27 +507,6 @@
goto out_settings;
}
- if (priv->is_internal_short_scan && !aborted) {
- int err;
-
- /* Check if mac80211 requested scan during our internal scan */
- if (priv->scan_request == NULL)
- goto out_complete;
-
- /* If so request a new scan */
- err = iwl_legacy_scan_initiate(priv, priv->scan_vif, false,
- priv->scan_request->channels[0]->band);
- if (err) {
- IWL_DEBUG_SCAN(priv,
- "failed to initiate pending scan: %d\n", err);
- aborted = true;
- goto out_complete;
- }
-
- goto out;
- }
-
-out_complete:
iwl_legacy_complete_scan(priv, aborted);
out_settings:
@@ -590,8 +518,7 @@
* We do not commit power settings while scan is pending,
* do it now if the settings changed.
*/
- iwl_legacy_power_set_mode(priv, &priv->power_data.sleep_cmd_next,
- false);
+ iwl_legacy_power_set_mode(priv, &priv->power_data.sleep_cmd_next, false);
iwl_legacy_set_tx_power(priv, priv->tx_power_next, false);
priv->cfg->ops->utils->post_scan(priv);
@@ -604,15 +531,12 @@
{
INIT_WORK(&priv->scan_completed, iwl_legacy_bg_scan_completed);
INIT_WORK(&priv->abort_scan, iwl_legacy_bg_abort_scan);
- INIT_WORK(&priv->start_internal_scan,
- iwl_legacy_bg_start_internal_scan);
INIT_DELAYED_WORK(&priv->scan_check, iwl_legacy_bg_scan_check);
}
EXPORT_SYMBOL(iwl_legacy_setup_scan_deferred_work);
void iwl_legacy_cancel_scan_deferred_work(struct iwl_priv *priv)
{
- cancel_work_sync(&priv->start_internal_scan);
cancel_work_sync(&priv->abort_scan);
cancel_work_sync(&priv->scan_completed);
diff --git a/drivers/net/wireless/iwlegacy/iwl3945-base.c b/drivers/net/wireless/iwlegacy/iwl3945-base.c
index 0ee6be6..795826a 100644
--- a/drivers/net/wireless/iwlegacy/iwl3945-base.c
+++ b/drivers/net/wireless/iwlegacy/iwl3945-base.c
@@ -1409,212 +1409,6 @@
}
}
-#define EVENT_START_OFFSET (6 * sizeof(u32))
-
-/**
- * iwl3945_print_event_log - Dump error event log to syslog
- *
- */
-static int iwl3945_print_event_log(struct iwl_priv *priv, u32 start_idx,
- u32 num_events, u32 mode,
- int pos, char **buf, size_t bufsz)
-{
- u32 i;
- u32 base; /* SRAM byte address of event log header */
- u32 event_size; /* 2 u32s, or 3 u32s if timestamp recorded */
- u32 ptr; /* SRAM byte address of log data */
- u32 ev, time, data; /* event log data */
- unsigned long reg_flags;
-
- if (num_events == 0)
- return pos;
-
- base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
-
- if (mode == 0)
- event_size = 2 * sizeof(u32);
- else
- event_size = 3 * sizeof(u32);
-
- ptr = base + EVENT_START_OFFSET + (start_idx * event_size);
-
- /* Make sure device is powered up for SRAM reads */
- spin_lock_irqsave(&priv->reg_lock, reg_flags);
- iwl_grab_nic_access(priv);
-
- /* Set starting address; reads will auto-increment */
- _iwl_legacy_write_direct32(priv, HBUS_TARG_MEM_RADDR, ptr);
- rmb();
-
- /* "time" is actually "data" for mode 0 (no timestamp).
- * place event id # at far right for easier visual parsing. */
- for (i = 0; i < num_events; i++) {
- ev = _iwl_legacy_read_direct32(priv, HBUS_TARG_MEM_RDAT);
- time = _iwl_legacy_read_direct32(priv, HBUS_TARG_MEM_RDAT);
- if (mode == 0) {
- /* data, ev */
- if (bufsz) {
- pos += scnprintf(*buf + pos, bufsz - pos,
- "0x%08x:%04u\n",
- time, ev);
- } else {
- IWL_ERR(priv, "0x%08x\t%04u\n", time, ev);
- trace_iwlwifi_legacy_dev_ucode_event(priv, 0,
- time, ev);
- }
- } else {
- data = _iwl_legacy_read_direct32(priv,
- HBUS_TARG_MEM_RDAT);
- if (bufsz) {
- pos += scnprintf(*buf + pos, bufsz - pos,
- "%010u:0x%08x:%04u\n",
- time, data, ev);
- } else {
- IWL_ERR(priv, "%010u\t0x%08x\t%04u\n",
- time, data, ev);
- trace_iwlwifi_legacy_dev_ucode_event(priv, time,
- data, ev);
- }
- }
- }
-
- /* Allow device to power down */
- iwl_release_nic_access(priv);
- spin_unlock_irqrestore(&priv->reg_lock, reg_flags);
- return pos;
-}
-
-/**
- * iwl3945_print_last_event_logs - Dump the newest # of event log to syslog
- */
-static int iwl3945_print_last_event_logs(struct iwl_priv *priv, u32 capacity,
- u32 num_wraps, u32 next_entry,
- u32 size, u32 mode,
- int pos, char **buf, size_t bufsz)
-{
- /*
- * display the newest DEFAULT_LOG_ENTRIES entries
- * i.e the entries just before the next ont that uCode would fill.
- */
- if (num_wraps) {
- if (next_entry < size) {
- pos = iwl3945_print_event_log(priv,
- capacity - (size - next_entry),
- size - next_entry, mode,
- pos, buf, bufsz);
- pos = iwl3945_print_event_log(priv, 0,
- next_entry, mode,
- pos, buf, bufsz);
- } else
- pos = iwl3945_print_event_log(priv, next_entry - size,
- size, mode,
- pos, buf, bufsz);
- } else {
- if (next_entry < size)
- pos = iwl3945_print_event_log(priv, 0,
- next_entry, mode,
- pos, buf, bufsz);
- else
- pos = iwl3945_print_event_log(priv, next_entry - size,
- size, mode,
- pos, buf, bufsz);
- }
- return pos;
-}
-
-#define DEFAULT_IWL3945_DUMP_EVENT_LOG_ENTRIES (20)
-
-int iwl3945_dump_nic_event_log(struct iwl_priv *priv, bool full_log,
- char **buf, bool display)
-{
- u32 base; /* SRAM byte address of event log header */
- u32 capacity; /* event log capacity in # entries */
- u32 mode; /* 0 - no timestamp, 1 - timestamp recorded */
- u32 num_wraps; /* # times uCode wrapped to top of log */
- u32 next_entry; /* index of next entry to be written by uCode */
- u32 size; /* # entries that we'll print */
- int pos = 0;
- size_t bufsz = 0;
-
- base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
- if (!iwl3945_hw_valid_rtc_data_addr(base)) {
- IWL_ERR(priv, "Invalid event log pointer 0x%08X\n", base);
- return -EINVAL;
- }
-
- /* event log header */
- capacity = iwl_legacy_read_targ_mem(priv, base);
- mode = iwl_legacy_read_targ_mem(priv, base + (1 * sizeof(u32)));
- num_wraps = iwl_legacy_read_targ_mem(priv, base + (2 * sizeof(u32)));
- next_entry = iwl_legacy_read_targ_mem(priv, base + (3 * sizeof(u32)));
-
- if (capacity > priv->cfg->base_params->max_event_log_size) {
- IWL_ERR(priv, "Log capacity %d is bogus, limit to %d entries\n",
- capacity, priv->cfg->base_params->max_event_log_size);
- capacity = priv->cfg->base_params->max_event_log_size;
- }
-
- if (next_entry > priv->cfg->base_params->max_event_log_size) {
- IWL_ERR(priv, "Log write index %d is bogus, limit to %d\n",
- next_entry, priv->cfg->base_params->max_event_log_size);
- next_entry = priv->cfg->base_params->max_event_log_size;
- }
-
- size = num_wraps ? capacity : next_entry;
-
- /* bail out if nothing in log */
- if (size == 0) {
- IWL_ERR(priv, "Start IWL Event Log Dump: nothing in log\n");
- return pos;
- }
-
-#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
- if (!(iwl_legacy_get_debug_level(priv) & IWL_DL_FW_ERRORS) && !full_log)
- size = (size > DEFAULT_IWL3945_DUMP_EVENT_LOG_ENTRIES)
- ? DEFAULT_IWL3945_DUMP_EVENT_LOG_ENTRIES : size;
-#else
- size = (size > DEFAULT_IWL3945_DUMP_EVENT_LOG_ENTRIES)
- ? DEFAULT_IWL3945_DUMP_EVENT_LOG_ENTRIES : size;
-#endif
-
- IWL_ERR(priv, "Start IWL Event Log Dump: display last %d count\n",
- size);
-
-#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
- if (display) {
- if (full_log)
- bufsz = capacity * 48;
- else
- bufsz = size * 48;
- *buf = kmalloc(bufsz, GFP_KERNEL);
- if (!*buf)
- return -ENOMEM;
- }
- if ((iwl_legacy_get_debug_level(priv) & IWL_DL_FW_ERRORS) || full_log) {
- /* if uCode has wrapped back to top of log,
- * start at the oldest entry,
- * i.e the next one that uCode would fill.
- */
- if (num_wraps)
- pos = iwl3945_print_event_log(priv, next_entry,
- capacity - next_entry, mode,
- pos, buf, bufsz);
-
- /* (then/else) start at top of log */
- pos = iwl3945_print_event_log(priv, 0, next_entry, mode,
- pos, buf, bufsz);
- } else
- pos = iwl3945_print_last_event_logs(priv, capacity, num_wraps,
- next_entry, size, mode,
- pos, buf, bufsz);
-#else
- pos = iwl3945_print_last_event_logs(priv, capacity, num_wraps,
- next_entry, size, mode,
- pos, buf, bufsz);
-#endif
- return pos;
-}
-
static void iwl3945_irq_tasklet(struct iwl_priv *priv)
{
u32 inta, handled = 0;
@@ -1762,49 +1556,6 @@
#endif
}
-static int iwl3945_get_single_channel_for_scan(struct iwl_priv *priv,
- struct ieee80211_vif *vif,
- enum ieee80211_band band,
- struct iwl3945_scan_channel *scan_ch)
-{
- const struct ieee80211_supported_band *sband;
- u16 passive_dwell = 0;
- u16 active_dwell = 0;
- int added = 0;
- u8 channel = 0;
-
- sband = iwl_get_hw_mode(priv, band);
- if (!sband) {
- IWL_ERR(priv, "invalid band\n");
- return added;
- }
-
- active_dwell = iwl_legacy_get_active_dwell_time(priv, band, 0);
- passive_dwell = iwl_legacy_get_passive_dwell_time(priv, band, vif);
-
- if (passive_dwell <= active_dwell)
- passive_dwell = active_dwell + 1;
-
-
- channel = iwl_legacy_get_single_channel_number(priv, band);
-
- if (channel) {
- scan_ch->channel = channel;
- scan_ch->type = 0; /* passive */
- scan_ch->active_dwell = cpu_to_le16(active_dwell);
- scan_ch->passive_dwell = cpu_to_le16(passive_dwell);
- /* Set txpower levels to defaults */
- scan_ch->tpc.dsp_atten = 110;
- if (band == IEEE80211_BAND_5GHZ)
- scan_ch->tpc.tx_gain = ((1 << 5) | (3 << 3)) | 3;
- else
- scan_ch->tpc.tx_gain = ((1 << 5) | (5 << 3));
- added++;
- } else
- IWL_ERR(priv, "no valid channel found\n");
- return added;
-}
-
static int iwl3945_get_channels_for_scan(struct iwl_priv *priv,
enum ieee80211_band band,
u8 is_active, u8 n_probes,
@@ -2816,6 +2567,7 @@
enum ieee80211_band band;
bool is_active = false;
int ret;
+ u16 len;
lockdep_assert_held(&priv->mutex);
@@ -2834,17 +2586,14 @@
scan->quiet_time = IWL_ACTIVE_QUIET_TIME;
if (iwl_legacy_is_associated(priv, IWL_RXON_CTX_BSS)) {
- u16 interval = 0;
+ u16 interval;
u32 extra;
u32 suspend_time = 100;
u32 scan_suspend_time = 100;
IWL_DEBUG_INFO(priv, "Scanning while associated...\n");
- if (priv->is_internal_short_scan)
- interval = 0;
- else
- interval = vif->bss_conf.beacon_int;
+ interval = vif->bss_conf.beacon_int;
scan->suspend_time = 0;
scan->max_out_time = cpu_to_le32(200 * 1024);
@@ -2866,9 +2615,7 @@
scan_suspend_time, interval);
}
- if (priv->is_internal_short_scan) {
- IWL_DEBUG_SCAN(priv, "Start internal passive scan.\n");
- } else if (priv->scan_request->n_ssids) {
+ if (priv->scan_request->n_ssids) {
int i, p = 0;
IWL_DEBUG_SCAN(priv, "Kicking off active scan\n");
for (i = 0; i < priv->scan_request->n_ssids; i++) {
@@ -2919,36 +2666,17 @@
scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH_DEFAULT :
IWL_GOOD_CRC_TH_DISABLED;
- if (!priv->is_internal_short_scan) {
- scan->tx_cmd.len = cpu_to_le16(
- iwl_legacy_fill_probe_req(priv,
- (struct ieee80211_mgmt *)scan->data,
- vif->addr,
- priv->scan_request->ie,
- priv->scan_request->ie_len,
- IWL_MAX_SCAN_SIZE - sizeof(*scan)));
- } else {
- /* use bcast addr, will not be transmitted but must be valid */
- scan->tx_cmd.len = cpu_to_le16(
- iwl_legacy_fill_probe_req(priv,
- (struct ieee80211_mgmt *)scan->data,
- iwlegacy_bcast_addr, NULL, 0,
- IWL_MAX_SCAN_SIZE - sizeof(*scan)));
- }
+ len = iwl_legacy_fill_probe_req(priv, (struct ieee80211_mgmt *)scan->data,
+ vif->addr, priv->scan_request->ie,
+ priv->scan_request->ie_len,
+ IWL_MAX_SCAN_SIZE - sizeof(*scan));
+ scan->tx_cmd.len = cpu_to_le16(len);
+
/* select Rx antennas */
scan->flags |= iwl3945_get_antenna_flags(priv);
- if (priv->is_internal_short_scan) {
- scan->channel_count =
- iwl3945_get_single_channel_for_scan(priv, vif, band,
- (void *)&scan->data[le16_to_cpu(
- scan->tx_cmd.len)]);
- } else {
- scan->channel_count =
- iwl3945_get_channels_for_scan(priv, band, is_active, n_probes,
- (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)], vif);
- }
-
+ scan->channel_count = iwl3945_get_channels_for_scan(priv, band, is_active, n_probes,
+ (void *)&scan->data[len], vif);
if (scan->channel_count == 0) {
IWL_DEBUG_SCAN(priv, "channel count %d\n", scan->channel_count);
return -EIO;
@@ -3824,10 +3552,7 @@
priv->missed_beacon_threshold = IWL_MISSED_BEACON_THRESHOLD_DEF;
/* initialize force reset */
- priv->force_reset[IWL_RF_RESET].reset_duration =
- IWL_DELAY_NEXT_FORCE_RF_RESET;
- priv->force_reset[IWL_FW_RESET].reset_duration =
- IWL_DELAY_NEXT_FORCE_FW_RELOAD;
+ priv->force_reset.reset_duration = IWL_DELAY_NEXT_FORCE_FW_RELOAD;
if (eeprom->version < EEPROM_3945_EEPROM_VERSION) {
IWL_WARN(priv, "Unsupported EEPROM version: 0x%04X\n",
diff --git a/drivers/net/wireless/iwlegacy/iwl4965-base.c b/drivers/net/wireless/iwlegacy/iwl4965-base.c
index 7157ba5..46242d2 100644
--- a/drivers/net/wireless/iwlegacy/iwl4965-base.c
+++ b/drivers/net/wireless/iwlegacy/iwl4965-base.c
@@ -488,134 +488,6 @@
iwl_legacy_send_statistics_request(priv, CMD_ASYNC, false);
}
-
-static void iwl4965_print_cont_event_trace(struct iwl_priv *priv, u32 base,
- u32 start_idx, u32 num_events,
- u32 mode)
-{
- u32 i;
- u32 ptr; /* SRAM byte address of log data */
- u32 ev, time, data; /* event log data */
- unsigned long reg_flags;
-
- if (mode == 0)
- ptr = base + (4 * sizeof(u32)) + (start_idx * 2 * sizeof(u32));
- else
- ptr = base + (4 * sizeof(u32)) + (start_idx * 3 * sizeof(u32));
-
- /* Make sure device is powered up for SRAM reads */
- spin_lock_irqsave(&priv->reg_lock, reg_flags);
- if (iwl_grab_nic_access(priv)) {
- spin_unlock_irqrestore(&priv->reg_lock, reg_flags);
- return;
- }
-
- /* Set starting address; reads will auto-increment */
- _iwl_legacy_write_direct32(priv, HBUS_TARG_MEM_RADDR, ptr);
- rmb();
-
- /*
- * "time" is actually "data" for mode 0 (no timestamp).
- * place event id # at far right for easier visual parsing.
- */
- for (i = 0; i < num_events; i++) {
- ev = _iwl_legacy_read_direct32(priv, HBUS_TARG_MEM_RDAT);
- time = _iwl_legacy_read_direct32(priv, HBUS_TARG_MEM_RDAT);
- if (mode == 0) {
- trace_iwlwifi_legacy_dev_ucode_cont_event(priv,
- 0, time, ev);
- } else {
- data = _iwl_legacy_read_direct32(priv,
- HBUS_TARG_MEM_RDAT);
- trace_iwlwifi_legacy_dev_ucode_cont_event(priv,
- time, data, ev);
- }
- }
- /* Allow device to power down */
- iwl_release_nic_access(priv);
- spin_unlock_irqrestore(&priv->reg_lock, reg_flags);
-}
-
-static void iwl4965_continuous_event_trace(struct iwl_priv *priv)
-{
- u32 capacity; /* event log capacity in # entries */
- u32 base; /* SRAM byte address of event log header */
- u32 mode; /* 0 - no timestamp, 1 - timestamp recorded */
- u32 num_wraps; /* # times uCode wrapped to top of log */
- u32 next_entry; /* index of next entry to be written by uCode */
-
- if (priv->ucode_type == UCODE_INIT)
- base = le32_to_cpu(priv->card_alive_init.error_event_table_ptr);
- else
- base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
- if (priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) {
- capacity = iwl_legacy_read_targ_mem(priv, base);
- num_wraps = iwl_legacy_read_targ_mem(priv,
- base + (2 * sizeof(u32)));
- mode = iwl_legacy_read_targ_mem(priv, base + (1 * sizeof(u32)));
- next_entry = iwl_legacy_read_targ_mem(priv,
- base + (3 * sizeof(u32)));
- } else
- return;
-
- if (num_wraps == priv->event_log.num_wraps) {
- iwl4965_print_cont_event_trace(priv,
- base, priv->event_log.next_entry,
- next_entry - priv->event_log.next_entry,
- mode);
- priv->event_log.non_wraps_count++;
- } else {
- if ((num_wraps - priv->event_log.num_wraps) > 1)
- priv->event_log.wraps_more_count++;
- else
- priv->event_log.wraps_once_count++;
- trace_iwlwifi_legacy_dev_ucode_wrap_event(priv,
- num_wraps - priv->event_log.num_wraps,
- next_entry, priv->event_log.next_entry);
- if (next_entry < priv->event_log.next_entry) {
- iwl4965_print_cont_event_trace(priv, base,
- priv->event_log.next_entry,
- capacity - priv->event_log.next_entry,
- mode);
-
- iwl4965_print_cont_event_trace(priv, base, 0,
- next_entry, mode);
- } else {
- iwl4965_print_cont_event_trace(priv, base,
- next_entry, capacity - next_entry,
- mode);
-
- iwl4965_print_cont_event_trace(priv, base, 0,
- next_entry, mode);
- }
- }
- priv->event_log.num_wraps = num_wraps;
- priv->event_log.next_entry = next_entry;
-}
-
-/**
- * iwl4965_bg_ucode_trace - Timer callback to log ucode event
- *
- * The timer is continually set to execute every
- * UCODE_TRACE_PERIOD milliseconds after the last timer expired
- * this function is to perform continuous uCode event logging operation
- * if enabled
- */
-static void iwl4965_bg_ucode_trace(unsigned long data)
-{
- struct iwl_priv *priv = (struct iwl_priv *)data;
-
- if (test_bit(STATUS_EXIT_PENDING, &priv->status))
- return;
-
- if (priv->event_log.ucode_trace) {
- iwl4965_continuous_event_trace(priv);
- /* Reschedule the timer to occur in UCODE_TRACE_PERIOD */
- mod_timer(&priv->ucode_trace,
- jiffies + msecs_to_jiffies(UCODE_TRACE_PERIOD));
- }
-}
-
static void iwl4965_rx_beacon_notif(struct iwl_priv *priv,
struct iwl_rx_mem_buffer *rxb)
{
@@ -1711,209 +1583,6 @@
pc, blink1, blink2, ilink1, ilink2, hcmd);
}
-#define EVENT_START_OFFSET (4 * sizeof(u32))
-
-/**
- * iwl4965_print_event_log - Dump error event log to syslog
- *
- */
-static int iwl4965_print_event_log(struct iwl_priv *priv, u32 start_idx,
- u32 num_events, u32 mode,
- int pos, char **buf, size_t bufsz)
-{
- u32 i;
- u32 base; /* SRAM byte address of event log header */
- u32 event_size; /* 2 u32s, or 3 u32s if timestamp recorded */
- u32 ptr; /* SRAM byte address of log data */
- u32 ev, time, data; /* event log data */
- unsigned long reg_flags;
-
- if (num_events == 0)
- return pos;
-
- if (priv->ucode_type == UCODE_INIT) {
- base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr);
- } else {
- base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
- }
-
- if (mode == 0)
- event_size = 2 * sizeof(u32);
- else
- event_size = 3 * sizeof(u32);
-
- ptr = base + EVENT_START_OFFSET + (start_idx * event_size);
-
- /* Make sure device is powered up for SRAM reads */
- spin_lock_irqsave(&priv->reg_lock, reg_flags);
- iwl_grab_nic_access(priv);
-
- /* Set starting address; reads will auto-increment */
- _iwl_legacy_write_direct32(priv, HBUS_TARG_MEM_RADDR, ptr);
- rmb();
-
- /* "time" is actually "data" for mode 0 (no timestamp).
- * place event id # at far right for easier visual parsing. */
- for (i = 0; i < num_events; i++) {
- ev = _iwl_legacy_read_direct32(priv, HBUS_TARG_MEM_RDAT);
- time = _iwl_legacy_read_direct32(priv, HBUS_TARG_MEM_RDAT);
- if (mode == 0) {
- /* data, ev */
- if (bufsz) {
- pos += scnprintf(*buf + pos, bufsz - pos,
- "EVT_LOG:0x%08x:%04u\n",
- time, ev);
- } else {
- trace_iwlwifi_legacy_dev_ucode_event(priv, 0,
- time, ev);
- IWL_ERR(priv, "EVT_LOG:0x%08x:%04u\n",
- time, ev);
- }
- } else {
- data = _iwl_legacy_read_direct32(priv,
- HBUS_TARG_MEM_RDAT);
- if (bufsz) {
- pos += scnprintf(*buf + pos, bufsz - pos,
- "EVT_LOGT:%010u:0x%08x:%04u\n",
- time, data, ev);
- } else {
- IWL_ERR(priv, "EVT_LOGT:%010u:0x%08x:%04u\n",
- time, data, ev);
- trace_iwlwifi_legacy_dev_ucode_event(priv, time,
- data, ev);
- }
- }
- }
-
- /* Allow device to power down */
- iwl_release_nic_access(priv);
- spin_unlock_irqrestore(&priv->reg_lock, reg_flags);
- return pos;
-}
-
-/**
- * iwl4965_print_last_event_logs - Dump the newest # of event log to syslog
- */
-static int iwl4965_print_last_event_logs(struct iwl_priv *priv, u32 capacity,
- u32 num_wraps, u32 next_entry,
- u32 size, u32 mode,
- int pos, char **buf, size_t bufsz)
-{
- /*
- * display the newest DEFAULT_LOG_ENTRIES entries
- * i.e the entries just before the next ont that uCode would fill.
- */
- if (num_wraps) {
- if (next_entry < size) {
- pos = iwl4965_print_event_log(priv,
- capacity - (size - next_entry),
- size - next_entry, mode,
- pos, buf, bufsz);
- pos = iwl4965_print_event_log(priv, 0,
- next_entry, mode,
- pos, buf, bufsz);
- } else
- pos = iwl4965_print_event_log(priv, next_entry - size,
- size, mode, pos, buf, bufsz);
- } else {
- if (next_entry < size) {
- pos = iwl4965_print_event_log(priv, 0, next_entry,
- mode, pos, buf, bufsz);
- } else {
- pos = iwl4965_print_event_log(priv, next_entry - size,
- size, mode, pos, buf, bufsz);
- }
- }
- return pos;
-}
-
-#define DEFAULT_DUMP_EVENT_LOG_ENTRIES (20)
-
-int iwl4965_dump_nic_event_log(struct iwl_priv *priv, bool full_log,
- char **buf, bool display)
-{
- u32 base; /* SRAM byte address of event log header */
- u32 capacity; /* event log capacity in # entries */
- u32 mode; /* 0 - no timestamp, 1 - timestamp recorded */
- u32 num_wraps; /* # times uCode wrapped to top of log */
- u32 next_entry; /* index of next entry to be written by uCode */
- u32 size; /* # entries that we'll print */
- int pos = 0;
- size_t bufsz = 0;
-
- if (priv->ucode_type == UCODE_INIT) {
- base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr);
- } else {
- base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
- }
-
- if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) {
- IWL_ERR(priv,
- "Invalid event log pointer 0x%08X for %s uCode\n",
- base, (priv->ucode_type == UCODE_INIT) ? "Init" : "RT");
- return -EINVAL;
- }
-
- /* event log header */
- capacity = iwl_legacy_read_targ_mem(priv, base);
- mode = iwl_legacy_read_targ_mem(priv, base + (1 * sizeof(u32)));
- num_wraps = iwl_legacy_read_targ_mem(priv, base + (2 * sizeof(u32)));
- next_entry = iwl_legacy_read_targ_mem(priv, base + (3 * sizeof(u32)));
-
- size = num_wraps ? capacity : next_entry;
-
- /* bail out if nothing in log */
- if (size == 0) {
- IWL_ERR(priv, "Start IWL Event Log Dump: nothing in log\n");
- return pos;
- }
-
-#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
- if (!(iwl_legacy_get_debug_level(priv) & IWL_DL_FW_ERRORS) && !full_log)
- size = (size > DEFAULT_DUMP_EVENT_LOG_ENTRIES)
- ? DEFAULT_DUMP_EVENT_LOG_ENTRIES : size;
-#else
- size = (size > DEFAULT_DUMP_EVENT_LOG_ENTRIES)
- ? DEFAULT_DUMP_EVENT_LOG_ENTRIES : size;
-#endif
- IWL_ERR(priv, "Start IWL Event Log Dump: display last %u entries\n",
- size);
-
-#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
- if (display) {
- if (full_log)
- bufsz = capacity * 48;
- else
- bufsz = size * 48;
- *buf = kmalloc(bufsz, GFP_KERNEL);
- if (!*buf)
- return -ENOMEM;
- }
- if ((iwl_legacy_get_debug_level(priv) & IWL_DL_FW_ERRORS) || full_log) {
- /*
- * if uCode has wrapped back to top of log,
- * start at the oldest entry,
- * i.e the next one that uCode would fill.
- */
- if (num_wraps)
- pos = iwl4965_print_event_log(priv, next_entry,
- capacity - next_entry, mode,
- pos, buf, bufsz);
- /* (then/else) start at top of log */
- pos = iwl4965_print_event_log(priv, 0,
- next_entry, mode, pos, buf, bufsz);
- } else
- pos = iwl4965_print_last_event_logs(priv, capacity, num_wraps,
- next_entry, size, mode,
- pos, buf, bufsz);
-#else
- pos = iwl4965_print_last_event_logs(priv, capacity, num_wraps,
- next_entry, size, mode,
- pos, buf, bufsz);
-#endif
- return pos;
-}
-
static void iwl4965_rf_kill_ct_config(struct iwl_priv *priv)
{
struct iwl_ct_kill_config cmd;
@@ -2773,20 +2442,10 @@
case IEEE80211_AMPDU_TX_START:
IWL_DEBUG_HT(priv, "start Tx\n");
ret = iwl4965_tx_agg_start(priv, vif, sta, tid, ssn);
- if (ret == 0) {
- priv->_4965.agg_tids_count++;
- IWL_DEBUG_HT(priv, "priv->_4965.agg_tids_count = %u\n",
- priv->_4965.agg_tids_count);
- }
break;
case IEEE80211_AMPDU_TX_STOP:
IWL_DEBUG_HT(priv, "stop Tx\n");
ret = iwl4965_tx_agg_stop(priv, vif, sta, tid);
- if ((ret == 0) && (priv->_4965.agg_tids_count > 0)) {
- priv->_4965.agg_tids_count--;
- IWL_DEBUG_HT(priv, "priv->_4965.agg_tids_count = %u\n",
- priv->_4965.agg_tids_count);
- }
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
ret = 0;
break;
@@ -2851,7 +2510,6 @@
struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
u16 ch;
- unsigned long flags = 0;
IWL_DEBUG_MAC80211(priv, "enter\n");
@@ -2868,64 +2526,64 @@
if (!iwl_legacy_is_associated_ctx(ctx))
goto out;
- if (priv->cfg->ops->lib->set_channel_switch) {
+ if (!priv->cfg->ops->lib->set_channel_switch)
+ goto out;
- ch = channel->hw_value;
- if (le16_to_cpu(ctx->active.channel) != ch) {
- ch_info = iwl_legacy_get_channel_info(priv,
- channel->band,
- ch);
- if (!iwl_legacy_is_channel_valid(ch_info)) {
- IWL_DEBUG_MAC80211(priv, "invalid channel\n");
- goto out;
- }
- spin_lock_irqsave(&priv->lock, flags);
+ ch = channel->hw_value;
+ if (le16_to_cpu(ctx->active.channel) == ch)
+ goto out;
- priv->current_ht_config.smps = conf->smps_mode;
-
- /* Configure HT40 channels */
- ctx->ht.enabled = conf_is_ht(conf);
- if (ctx->ht.enabled) {
- if (conf_is_ht40_minus(conf)) {
- ctx->ht.extension_chan_offset =
- IEEE80211_HT_PARAM_CHA_SEC_BELOW;
- ctx->ht.is_40mhz = true;
- } else if (conf_is_ht40_plus(conf)) {
- ctx->ht.extension_chan_offset =
- IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
- ctx->ht.is_40mhz = true;
- } else {
- ctx->ht.extension_chan_offset =
- IEEE80211_HT_PARAM_CHA_SEC_NONE;
- ctx->ht.is_40mhz = false;
- }
- } else
- ctx->ht.is_40mhz = false;
-
- if ((le16_to_cpu(ctx->staging.channel) != ch))
- ctx->staging.flags = 0;
-
- iwl_legacy_set_rxon_channel(priv, channel, ctx);
- iwl_legacy_set_rxon_ht(priv, ht_conf);
- iwl_legacy_set_flags_for_band(priv, ctx, channel->band,
- ctx->vif);
- spin_unlock_irqrestore(&priv->lock, flags);
-
- iwl_legacy_set_rate(priv);
- /*
- * at this point, staging_rxon has the
- * configuration for channel switch
- */
- set_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status);
- priv->switch_channel = cpu_to_le16(ch);
- if (priv->cfg->ops->lib->set_channel_switch(priv, ch_switch)) {
- clear_bit(STATUS_CHANNEL_SWITCH_PENDING,
- &priv->status);
- priv->switch_channel = 0;
- ieee80211_chswitch_done(ctx->vif, false);
- }
- }
+ ch_info = iwl_legacy_get_channel_info(priv, channel->band, ch);
+ if (!iwl_legacy_is_channel_valid(ch_info)) {
+ IWL_DEBUG_MAC80211(priv, "invalid channel\n");
+ goto out;
}
+
+ spin_lock_irq(&priv->lock);
+
+ priv->current_ht_config.smps = conf->smps_mode;
+
+ /* Configure HT40 channels */
+ ctx->ht.enabled = conf_is_ht(conf);
+ if (ctx->ht.enabled) {
+ if (conf_is_ht40_minus(conf)) {
+ ctx->ht.extension_chan_offset =
+ IEEE80211_HT_PARAM_CHA_SEC_BELOW;
+ ctx->ht.is_40mhz = true;
+ } else if (conf_is_ht40_plus(conf)) {
+ ctx->ht.extension_chan_offset =
+ IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
+ ctx->ht.is_40mhz = true;
+ } else {
+ ctx->ht.extension_chan_offset =
+ IEEE80211_HT_PARAM_CHA_SEC_NONE;
+ ctx->ht.is_40mhz = false;
+ }
+ } else
+ ctx->ht.is_40mhz = false;
+
+ if ((le16_to_cpu(ctx->staging.channel) != ch))
+ ctx->staging.flags = 0;
+
+ iwl_legacy_set_rxon_channel(priv, channel, ctx);
+ iwl_legacy_set_rxon_ht(priv, ht_conf);
+ iwl_legacy_set_flags_for_band(priv, ctx, channel->band, ctx->vif);
+
+ spin_unlock_irq(&priv->lock);
+
+ iwl_legacy_set_rate(priv);
+ /*
+ * at this point, staging_rxon has the
+ * configuration for channel switch
+ */
+ set_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status);
+ priv->switch_channel = cpu_to_le16(ch);
+ if (priv->cfg->ops->lib->set_channel_switch(priv, ch_switch)) {
+ clear_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status);
+ priv->switch_channel = 0;
+ ieee80211_chswitch_done(ctx->vif, false);
+ }
+
out:
mutex_unlock(&priv->mutex);
IWL_DEBUG_MAC80211(priv, "leave\n");
@@ -3034,10 +2692,6 @@
priv->statistics_periodic.data = (unsigned long)priv;
priv->statistics_periodic.function = iwl4965_bg_statistics_periodic;
- init_timer(&priv->ucode_trace);
- priv->ucode_trace.data = (unsigned long)priv;
- priv->ucode_trace.function = iwl4965_bg_ucode_trace;
-
init_timer(&priv->watchdog);
priv->watchdog.data = (unsigned long)priv;
priv->watchdog.function = iwl_legacy_bg_watchdog;
@@ -3056,7 +2710,6 @@
iwl_legacy_cancel_scan_deferred_work(priv);
del_timer_sync(&priv->statistics_periodic);
- del_timer_sync(&priv->ucode_trace);
}
static void iwl4965_init_hw_rates(struct iwl_priv *priv,
@@ -3132,13 +2785,9 @@
priv->iw_mode = NL80211_IFTYPE_STATION;
priv->current_ht_config.smps = IEEE80211_SMPS_STATIC;
priv->missed_beacon_threshold = IWL_MISSED_BEACON_THRESHOLD_DEF;
- priv->_4965.agg_tids_count = 0;
/* initialize force reset */
- priv->force_reset[IWL_RF_RESET].reset_duration =
- IWL_DELAY_NEXT_FORCE_RF_RESET;
- priv->force_reset[IWL_FW_RESET].reset_duration =
- IWL_DELAY_NEXT_FORCE_FW_RELOAD;
+ priv->force_reset.reset_duration = IWL_DELAY_NEXT_FORCE_FW_RELOAD;
/* Choose which receivers/antennas to use */
if (priv->cfg->ops->hcmd->set_rxon_chain)
diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile
index 8226604..9a56ce5 100644
--- a/drivers/net/wireless/iwlwifi/Makefile
+++ b/drivers/net/wireless/iwlwifi/Makefile
@@ -13,6 +13,7 @@
iwlagn-objs += iwl-6000.o
iwlagn-objs += iwl-1000.o
iwlagn-objs += iwl-2000.o
+iwlagn-objs += iwl-pci.o
iwlagn-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o
iwlagn-$(CONFIG_IWLWIFI_DEVICE_TRACING) += iwl-devtrace.o
diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c
index 2a88e73..e57fad9 100644
--- a/drivers/net/wireless/iwlwifi/iwl-1000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-1000.c
@@ -27,8 +27,6 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/dma-mapping.h>
#include <linux/delay.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
@@ -175,7 +173,6 @@
.rx_handler_setup = iwlagn_rx_handler_setup,
.setup_deferred_work = iwlagn_setup_deferred_work,
.is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr,
- .send_tx_power = iwlagn_send_tx_power,
.update_chain_flags = iwl_update_chain_flags,
.apm_ops = {
.init = iwl_apm_init,
@@ -196,8 +193,6 @@
.temp_ops = {
.temperature = iwlagn_temperature,
},
- .txfifo_flush = iwlagn_txfifo_flush,
- .dev_txfifo_flush = iwlagn_dev_txfifo_flush,
};
static const struct iwl_ops iwl1000_ops = {
@@ -224,6 +219,7 @@
static struct iwl_ht_params iwl1000_ht_params = {
.ht_greenfield_support = true,
.use_rts_for_aggregation = true, /* use rts/cts protection */
+ .smps_mode = IEEE80211_SMPS_STATIC,
};
#define IWL_DEVICE_1000 \
diff --git a/drivers/net/wireless/iwlwifi/iwl-2000.c b/drivers/net/wireless/iwlwifi/iwl-2000.c
index 3df76f5..64ed1f2 100644
--- a/drivers/net/wireless/iwlwifi/iwl-2000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-2000.c
@@ -27,8 +27,6 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/dma-mapping.h>
#include <linux/delay.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
@@ -77,21 +75,7 @@
/* NIC configuration for 2000 series */
static void iwl2000_nic_config(struct iwl_priv *priv)
{
- u16 radio_cfg;
-
- radio_cfg = iwl_eeprom_query16(priv, EEPROM_RADIO_CONFIG);
-
- /* write radio config values to register */
- if (EEPROM_RF_CFG_TYPE_MSK(radio_cfg) <= EEPROM_RF_CONFIG_TYPE_MAX)
- iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
- EEPROM_RF_CFG_TYPE_MSK(radio_cfg) |
- EEPROM_RF_CFG_STEP_MSK(radio_cfg) |
- EEPROM_RF_CFG_DASH_MSK(radio_cfg));
-
- /* set CSR_HW_CONFIG_REG for uCode use */
- iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
- CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI |
- CSR_HW_IF_CONFIG_REG_BIT_MAC_SI);
+ iwl_rf_config(priv);
if (priv->cfg->iq_invert)
iwl_set_bit(priv, CSR_GP_DRIVER_REG,
@@ -184,7 +168,6 @@
.setup_deferred_work = iwlagn_bt_setup_deferred_work,
.cancel_deferred_work = iwlagn_bt_cancel_deferred_work,
.is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr,
- .send_tx_power = iwlagn_send_tx_power,
.update_chain_flags = iwl_update_chain_flags,
.apm_ops = {
.init = iwl_apm_init,
@@ -206,8 +189,6 @@
.temp_ops = {
.temperature = iwlagn_temperature,
},
- .txfifo_flush = iwlagn_txfifo_flush,
- .dev_txfifo_flush = iwlagn_dev_txfifo_flush,
};
static const struct iwl_ops iwl2000_ops = {
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000-hw.h b/drivers/net/wireless/iwlwifi/iwl-5000-hw.h
index 05ad476..f9630a3 100644
--- a/drivers/net/wireless/iwlwifi/iwl-5000-hw.h
+++ b/drivers/net/wireless/iwlwifi/iwl-5000-hw.h
@@ -75,7 +75,7 @@
{
u16 temperature, voltage;
__le16 *temp_calib =
- (__le16 *)iwl_eeprom_query_addr(priv, EEPROM_5000_TEMPERATURE);
+ (__le16 *)iwl_eeprom_query_addr(priv, EEPROM_TEMPERATURE);
temperature = le16_to_cpu(temp_calib[0]);
voltage = le16_to_cpu(temp_calib[1]);
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c
index e816c27..269dfdb 100644
--- a/drivers/net/wireless/iwlwifi/iwl-5000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-5000.c
@@ -27,8 +27,6 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/dma-mapping.h>
#include <linux/delay.h>
#include <linux/sched.h>
#include <linux/skbuff.h>
@@ -67,24 +65,11 @@
static void iwl5000_nic_config(struct iwl_priv *priv)
{
unsigned long flags;
- u16 radio_cfg;
+
+ iwl_rf_config(priv);
spin_lock_irqsave(&priv->lock, flags);
- radio_cfg = iwl_eeprom_query16(priv, EEPROM_RADIO_CONFIG);
-
- /* write radio config values to register */
- if (EEPROM_RF_CFG_TYPE_MSK(radio_cfg) < EEPROM_RF_CONFIG_TYPE_MAX)
- iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
- EEPROM_RF_CFG_TYPE_MSK(radio_cfg) |
- EEPROM_RF_CFG_STEP_MSK(radio_cfg) |
- EEPROM_RF_CFG_DASH_MSK(radio_cfg));
-
- /* set CSR_HW_CONFIG_REG for uCode use */
- iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
- CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI |
- CSR_HW_IF_CONFIG_REG_BIT_MAC_SI);
-
/* W/A : NIC is stuck in a reset state after Early PCIe power off
* (PCIe power is lost before PERST# is asserted),
* causing ME FW to lose ownership and not being able to obtain it back.
@@ -341,7 +326,6 @@
.rx_handler_setup = iwlagn_rx_handler_setup,
.setup_deferred_work = iwlagn_setup_deferred_work,
.is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr,
- .send_tx_power = iwlagn_send_tx_power,
.update_chain_flags = iwl_update_chain_flags,
.set_channel_switch = iwl5000_hw_channel_switch,
.apm_ops = {
@@ -363,8 +347,6 @@
.temp_ops = {
.temperature = iwlagn_temperature,
},
- .txfifo_flush = iwlagn_txfifo_flush,
- .dev_txfifo_flush = iwlagn_dev_txfifo_flush,
};
static struct iwl_lib_ops iwl5150_lib = {
@@ -372,7 +354,6 @@
.rx_handler_setup = iwlagn_rx_handler_setup,
.setup_deferred_work = iwlagn_setup_deferred_work,
.is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr,
- .send_tx_power = iwlagn_send_tx_power,
.update_chain_flags = iwl_update_chain_flags,
.set_channel_switch = iwl5000_hw_channel_switch,
.apm_ops = {
@@ -394,8 +375,6 @@
.temp_ops = {
.temperature = iwl5150_temperature,
},
- .txfifo_flush = iwlagn_txfifo_flush,
- .dev_txfifo_flush = iwlagn_dev_txfifo_flush,
};
static const struct iwl_ops iwl5000_ops = {
diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c
index 5b150bc..f1c1db7 100644
--- a/drivers/net/wireless/iwlwifi/iwl-6000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-6000.c
@@ -27,8 +27,6 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/dma-mapping.h>
#include <linux/delay.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
@@ -98,21 +96,7 @@
/* NIC configuration for 6000 series */
static void iwl6000_nic_config(struct iwl_priv *priv)
{
- u16 radio_cfg;
-
- radio_cfg = iwl_eeprom_query16(priv, EEPROM_RADIO_CONFIG);
-
- /* write radio config values to register */
- if (EEPROM_RF_CFG_TYPE_MSK(radio_cfg) <= EEPROM_RF_CONFIG_TYPE_MAX)
- iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
- EEPROM_RF_CFG_TYPE_MSK(radio_cfg) |
- EEPROM_RF_CFG_STEP_MSK(radio_cfg) |
- EEPROM_RF_CFG_DASH_MSK(radio_cfg));
-
- /* set CSR_HW_CONFIG_REG for uCode use */
- iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
- CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI |
- CSR_HW_IF_CONFIG_REG_BIT_MAC_SI);
+ iwl_rf_config(priv);
/* no locking required for register write */
if (priv->cfg->pa_type == IWL_PA_INTERNAL) {
@@ -280,7 +264,6 @@
.rx_handler_setup = iwlagn_rx_handler_setup,
.setup_deferred_work = iwlagn_setup_deferred_work,
.is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr,
- .send_tx_power = iwlagn_send_tx_power,
.update_chain_flags = iwl_update_chain_flags,
.set_channel_switch = iwl6000_hw_channel_switch,
.apm_ops = {
@@ -303,8 +286,6 @@
.temp_ops = {
.temperature = iwlagn_temperature,
},
- .txfifo_flush = iwlagn_txfifo_flush,
- .dev_txfifo_flush = iwlagn_dev_txfifo_flush,
};
static struct iwl_lib_ops iwl6030_lib = {
@@ -313,7 +294,6 @@
.setup_deferred_work = iwlagn_bt_setup_deferred_work,
.cancel_deferred_work = iwlagn_bt_cancel_deferred_work,
.is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr,
- .send_tx_power = iwlagn_send_tx_power,
.update_chain_flags = iwl_update_chain_flags,
.set_channel_switch = iwl6000_hw_channel_switch,
.apm_ops = {
@@ -336,8 +316,6 @@
.temp_ops = {
.temperature = iwlagn_temperature,
},
- .txfifo_flush = iwlagn_txfifo_flush,
- .dev_txfifo_flush = iwlagn_dev_txfifo_flush,
};
static struct iwl_nic_ops iwl6050_nic_ops = {
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c
index 2ef9448..7745816 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c
@@ -108,18 +108,16 @@
int iwl_eeprom_check_sku(struct iwl_priv *priv)
{
- u16 eeprom_sku;
u16 radio_cfg;
- eeprom_sku = iwl_eeprom_query16(priv, EEPROM_SKU_CAP);
-
if (!priv->cfg->sku) {
/* not using sku overwrite */
- priv->cfg->sku =
- ((eeprom_sku & EEPROM_SKU_CAP_BAND_SELECTION) >>
- EEPROM_SKU_CAP_BAND_POS);
- if (eeprom_sku & EEPROM_SKU_CAP_11N_ENABLE)
- priv->cfg->sku |= IWL_SKU_N;
+ priv->cfg->sku = iwl_eeprom_query16(priv, EEPROM_SKU_CAP);
+ if (priv->cfg->sku & EEPROM_SKU_CAP_11N_ENABLE &&
+ !priv->cfg->ht_params) {
+ IWL_ERR(priv, "Invalid 11n configuration\n");
+ return -EINVAL;
+ }
}
if (!priv->cfg->sku) {
IWL_ERR(priv, "Invalid device sku\n");
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c
index 23fa93d..ba7ed91 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c
@@ -111,10 +111,8 @@
memset(&cmd, 0, sizeof(cmd));
- cmd.hdr.op_code = priv->_agn.phy_calib_chain_noise_gain_cmd;
- cmd.hdr.first_group = 0;
- cmd.hdr.groups_num = 1;
- cmd.hdr.data_valid = 1;
+ iwl_set_calib_hdr(&cmd.hdr,
+ priv->_agn.phy_calib_chain_noise_gain_cmd);
cmd.delta_gain_1 = data->delta_gain_code[1];
cmd.delta_gain_2 = data->delta_gain_code[2];
iwl_send_cmd_pdu_async(priv, REPLY_PHY_CALIBRATION_CMD,
@@ -144,10 +142,8 @@
data->beacon_count = 0;
memset(&cmd, 0, sizeof(cmd));
- cmd.hdr.op_code = priv->_agn.phy_calib_chain_noise_reset_cmd;
- cmd.hdr.first_group = 0;
- cmd.hdr.groups_num = 1;
- cmd.hdr.data_valid = 1;
+ iwl_set_calib_hdr(&cmd.hdr,
+ priv->_agn.phy_calib_chain_noise_reset_cmd);
ret = iwl_send_cmd_pdu(priv, REPLY_PHY_CALIBRATION_CMD,
sizeof(cmd), &cmd);
if (ret)
@@ -302,7 +298,6 @@
}
struct iwl_hcmd_ops iwlagn_hcmd = {
- .commit_rxon = iwlagn_commit_rxon,
.set_rxon_chain = iwlagn_set_rxon_chain,
.set_tx_ant = iwlagn_send_tx_ant_config,
.send_bt_config = iwl_send_bt_config,
@@ -310,7 +305,6 @@
};
struct iwl_hcmd_ops iwlagn_bt_hcmd = {
- .commit_rxon = iwlagn_commit_rxon,
.set_rxon_chain = iwlagn_set_rxon_chain,
.set_tx_ant = iwlagn_send_tx_ant_config,
.send_bt_config = iwlagn_send_advance_bt_config,
@@ -324,5 +318,4 @@
.tx_cmd_protection = iwlagn_tx_cmd_protection,
.calc_rssi = iwlagn_calc_rssi,
.request_scan = iwlagn_request_scan,
- .post_scan = iwlagn_post_scan,
};
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-hw.h b/drivers/net/wireless/iwlwifi/iwl-agn-hw.h
index 7bd19f4..0e5b842 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-hw.h
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-hw.h
@@ -81,13 +81,6 @@
/* RSSI to dBm */
#define IWLAGN_RSSI_OFFSET 44
-/* PCI registers */
-#define PCI_CFG_RETRY_TIMEOUT 0x041
-
-/* PCI register values */
-#define PCI_CFG_LINK_CTRL_VAL_L0S_EN 0x01
-#define PCI_CFG_LINK_CTRL_VAL_L1_EN 0x02
-
#define IWLAGN_DEFAULT_TX_RETRY 15
/* Limit range of txpower output target to be between these values */
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ict.c b/drivers/net/wireless/iwlwifi/iwl-agn-ict.c
index 0d5fda4..f1b40ec 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-ict.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-ict.c
@@ -44,7 +44,7 @@
void iwl_free_isr_ict(struct iwl_priv *priv)
{
if (priv->_agn.ict_tbl_vir) {
- dma_free_coherent(&priv->pci_dev->dev,
+ dma_free_coherent(priv->bus.dev,
(sizeof(u32) * ICT_COUNT) + PAGE_SIZE,
priv->_agn.ict_tbl_vir,
priv->_agn.ict_tbl_dma);
@@ -61,7 +61,7 @@
/* allocate shrared data table */
priv->_agn.ict_tbl_vir =
- dma_alloc_coherent(&priv->pci_dev->dev,
+ dma_alloc_coherent(priv->bus.dev,
(sizeof(u32) * ICT_COUNT) + PAGE_SIZE,
&priv->_agn.ict_tbl_dma, GFP_KERNEL);
if (!priv->_agn.ict_tbl_vir)
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
index f803fb6..efdab65 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
@@ -408,9 +408,9 @@
unsigned long flags;
if ((index >= txq->q.n_bd) || (iwl_queue_used(&txq->q, index) == 0)) {
- IWL_ERR(priv, "Read index for DMA queue txq_id (%d) index %d "
- "is out of range [0-%d] %d %d\n", txq_id,
- index, txq->q.n_bd, txq->q.write_ptr,
+ IWL_ERR(priv, "%s: Read index for DMA queue txq_id (%d) "
+ "index %d is out of range [0-%d] %d %d\n", __func__,
+ txq_id, index, txq->q.n_bd, txq->q.write_ptr,
txq->q.read_ptr);
return;
}
@@ -438,7 +438,7 @@
if (tx_resp->bt_kill_count && tx_resp->frame_count == 1 &&
priv->cfg->bt_params &&
priv->cfg->bt_params->advanced_bt_coexist) {
- IWL_WARN(priv, "receive reply tx with bt_kill\n");
+ IWL_DEBUG_COEX(priv, "receive reply tx with bt_kill\n");
}
iwlagn_tx_status_reply_tx(priv, agg, tx_resp, txq_id, index);
@@ -622,6 +622,9 @@
.amsdu_size_8K = 1,
.restart_fw = 1,
.plcp_check = true,
+ .bt_coex_active = true,
+ .no_sleep_autoadjust = true,
+ .power_level = IWL_POWER_INDEX_1,
/* the rest are 0 by default */
};
@@ -637,9 +640,9 @@
/* In the reset function, these buffers may have been allocated
* to an SKB, so we need to unmap and free potential storage */
if (rxq->pool[i].page != NULL) {
- pci_unmap_page(priv->pci_dev, rxq->pool[i].page_dma,
+ dma_unmap_page(priv->bus.dev, rxq->pool[i].page_dma,
PAGE_SIZE << priv->hw_params.rx_page_order,
- PCI_DMA_FROMDEVICE);
+ DMA_FROM_DEVICE);
__iwl_free_pages(priv, rxq->pool[i].page);
rxq->pool[i].page = NULL;
}
@@ -911,9 +914,9 @@
BUG_ON(rxb->page);
rxb->page = page;
/* Get physical address of the RB */
- rxb->page_dma = pci_map_page(priv->pci_dev, page, 0,
+ rxb->page_dma = dma_map_page(priv->bus.dev, page, 0,
PAGE_SIZE << priv->hw_params.rx_page_order,
- PCI_DMA_FROMDEVICE);
+ DMA_FROM_DEVICE);
/* dma address must be no more than 36 bits */
BUG_ON(rxb->page_dma & ~DMA_BIT_MASK(36));
/* and also 256 byte aligned! */
@@ -956,17 +959,18 @@
int i;
for (i = 0; i < RX_QUEUE_SIZE + RX_FREE_BUFFERS; i++) {
if (rxq->pool[i].page != NULL) {
- pci_unmap_page(priv->pci_dev, rxq->pool[i].page_dma,
+ dma_unmap_page(priv->bus.dev, rxq->pool[i].page_dma,
PAGE_SIZE << priv->hw_params.rx_page_order,
- PCI_DMA_FROMDEVICE);
+ DMA_FROM_DEVICE);
__iwl_free_pages(priv, rxq->pool[i].page);
rxq->pool[i].page = NULL;
}
}
- dma_free_coherent(&priv->pci_dev->dev, 4 * RX_QUEUE_SIZE, rxq->bd,
- rxq->bd_dma);
- dma_free_coherent(&priv->pci_dev->dev, sizeof(struct iwl_rb_status),
+ dma_free_coherent(priv->bus.dev, 4 * RX_QUEUE_SIZE,
+ rxq->bd, rxq->bd_dma);
+ dma_free_coherent(priv->bus.dev,
+ sizeof(struct iwl_rb_status),
rxq->rb_stts, rxq->rb_stts_dma);
rxq->bd = NULL;
rxq->rb_stts = NULL;
@@ -1528,9 +1532,18 @@
might_sleep();
memset(&flush_cmd, 0, sizeof(flush_cmd));
- flush_cmd.fifo_control = IWL_TX_FIFO_VO_MSK | IWL_TX_FIFO_VI_MSK |
- IWL_TX_FIFO_BE_MSK | IWL_TX_FIFO_BK_MSK;
- if (priv->cfg->sku & IWL_SKU_N)
+ if (flush_control & BIT(IWL_RXON_CTX_BSS))
+ flush_cmd.fifo_control = IWL_SCD_VO_MSK | IWL_SCD_VI_MSK |
+ IWL_SCD_BE_MSK | IWL_SCD_BK_MSK |
+ IWL_SCD_MGMT_MSK;
+ if ((flush_control & BIT(IWL_RXON_CTX_PAN)) &&
+ (priv->valid_contexts != BIT(IWL_RXON_CTX_BSS)))
+ flush_cmd.fifo_control |= IWL_PAN_SCD_VO_MSK |
+ IWL_PAN_SCD_VI_MSK | IWL_PAN_SCD_BE_MSK |
+ IWL_PAN_SCD_BK_MSK | IWL_PAN_SCD_MGMT_MSK |
+ IWL_PAN_SCD_MULTICAST_MSK;
+
+ if (priv->cfg->sku & EEPROM_SKU_CAP_11N_ENABLE)
flush_cmd.fifo_control |= IWL_AGG_TX_QUEUE_MSK;
IWL_DEBUG_INFO(priv, "fifo queue control: 0X%x\n",
@@ -1544,7 +1557,7 @@
{
mutex_lock(&priv->mutex);
ieee80211_stop_queues(priv->hw);
- if (priv->cfg->ops->lib->txfifo_flush(priv, IWL_DROP_ALL)) {
+ if (iwlagn_txfifo_flush(priv, IWL_DROP_ALL)) {
IWL_ERR(priv, "flush request fail\n");
goto done;
}
@@ -1699,7 +1712,8 @@
* (might be in monitor mode), or the interface is in
* IBSS mode (no proper uCode support for coex then).
*/
- if (!bt_coex_active || priv->iw_mode == NL80211_IFTYPE_ADHOC) {
+ if (!iwlagn_mod_params.bt_coex_active ||
+ priv->iw_mode == NL80211_IFTYPE_ADHOC) {
basic.flags = IWLAGN_BT_FLAG_COEX_MODE_DISABLED;
} else {
basic.flags = IWLAGN_BT_FLAG_COEX_MODE_3W <<
@@ -1710,7 +1724,7 @@
if (priv->bt_ch_announce)
basic.flags |= IWLAGN_BT_FLAG_CHANNEL_INHIBITION;
- IWL_DEBUG_INFO(priv, "BT coex flag: 0X%x\n", basic.flags);
+ IWL_DEBUG_COEX(priv, "BT coex flag: 0X%x\n", basic.flags);
}
priv->bt_enable_flag = basic.flags;
if (priv->bt_full_concurrent)
@@ -1720,7 +1734,7 @@
memcpy(basic.bt3_lookup_table, iwlagn_def_3w_lookup,
sizeof(iwlagn_def_3w_lookup));
- IWL_DEBUG_INFO(priv, "BT coex %s in %s mode\n",
+ IWL_DEBUG_COEX(priv, "BT coex %s in %s mode\n",
basic.flags ? "active" : "disabled",
priv->bt_full_concurrent ?
"full concurrency" : "3-wire");
@@ -1758,7 +1772,7 @@
* coex profile notifications. Ignore that since only bad consequence
* can be not matching debug print with actual state.
*/
- IWL_DEBUG_INFO(priv, "BT traffic load changes: %d\n",
+ IWL_DEBUG_COEX(priv, "BT traffic load changes: %d\n",
priv->bt_traffic_load);
switch (priv->bt_traffic_load) {
@@ -1797,6 +1811,7 @@
priv->cfg->ops->lib->update_chain_flags(priv);
if (smps_request != -1) {
+ priv->current_ht_config.smps = smps_request;
for_each_context(priv, ctx) {
if (ctx->vif && ctx->vif->type == NL80211_IFTYPE_STATION)
ieee80211_request_smps(ctx->vif, smps_request);
@@ -1809,7 +1824,7 @@
static void iwlagn_print_uartmsg(struct iwl_priv *priv,
struct iwl_bt_uart_msg *uart_msg)
{
- IWL_DEBUG_NOTIF(priv, "Message Type = 0x%X, SSN = 0x%X, "
+ IWL_DEBUG_COEX(priv, "Message Type = 0x%X, SSN = 0x%X, "
"Update Req = 0x%X",
(BT_UART_MSG_FRAME1MSGTYPE_MSK & uart_msg->frame1) >>
BT_UART_MSG_FRAME1MSGTYPE_POS,
@@ -1818,7 +1833,7 @@
(BT_UART_MSG_FRAME1UPDATEREQ_MSK & uart_msg->frame1) >>
BT_UART_MSG_FRAME1UPDATEREQ_POS);
- IWL_DEBUG_NOTIF(priv, "Open connections = 0x%X, Traffic load = 0x%X, "
+ IWL_DEBUG_COEX(priv, "Open connections = 0x%X, Traffic load = 0x%X, "
"Chl_SeqN = 0x%X, In band = 0x%X",
(BT_UART_MSG_FRAME2OPENCONNECTIONS_MSK & uart_msg->frame2) >>
BT_UART_MSG_FRAME2OPENCONNECTIONS_POS,
@@ -1829,7 +1844,7 @@
(BT_UART_MSG_FRAME2INBAND_MSK & uart_msg->frame2) >>
BT_UART_MSG_FRAME2INBAND_POS);
- IWL_DEBUG_NOTIF(priv, "SCO/eSCO = 0x%X, Sniff = 0x%X, A2DP = 0x%X, "
+ IWL_DEBUG_COEX(priv, "SCO/eSCO = 0x%X, Sniff = 0x%X, A2DP = 0x%X, "
"ACL = 0x%X, Master = 0x%X, OBEX = 0x%X",
(BT_UART_MSG_FRAME3SCOESCO_MSK & uart_msg->frame3) >>
BT_UART_MSG_FRAME3SCOESCO_POS,
@@ -1844,11 +1859,11 @@
(BT_UART_MSG_FRAME3OBEX_MSK & uart_msg->frame3) >>
BT_UART_MSG_FRAME3OBEX_POS);
- IWL_DEBUG_NOTIF(priv, "Idle duration = 0x%X",
+ IWL_DEBUG_COEX(priv, "Idle duration = 0x%X",
(BT_UART_MSG_FRAME4IDLEDURATION_MSK & uart_msg->frame4) >>
BT_UART_MSG_FRAME4IDLEDURATION_POS);
- IWL_DEBUG_NOTIF(priv, "Tx Activity = 0x%X, Rx Activity = 0x%X, "
+ IWL_DEBUG_COEX(priv, "Tx Activity = 0x%X, Rx Activity = 0x%X, "
"eSCO Retransmissions = 0x%X",
(BT_UART_MSG_FRAME5TXACTIVITY_MSK & uart_msg->frame5) >>
BT_UART_MSG_FRAME5TXACTIVITY_POS,
@@ -1857,13 +1872,13 @@
(BT_UART_MSG_FRAME5ESCORETRANSMIT_MSK & uart_msg->frame5) >>
BT_UART_MSG_FRAME5ESCORETRANSMIT_POS);
- IWL_DEBUG_NOTIF(priv, "Sniff Interval = 0x%X, Discoverable = 0x%X",
+ IWL_DEBUG_COEX(priv, "Sniff Interval = 0x%X, Discoverable = 0x%X",
(BT_UART_MSG_FRAME6SNIFFINTERVAL_MSK & uart_msg->frame6) >>
BT_UART_MSG_FRAME6SNIFFINTERVAL_POS,
(BT_UART_MSG_FRAME6DISCOVERABLE_MSK & uart_msg->frame6) >>
BT_UART_MSG_FRAME6DISCOVERABLE_POS);
- IWL_DEBUG_NOTIF(priv, "Sniff Activity = 0x%X, Page = "
+ IWL_DEBUG_COEX(priv, "Sniff Activity = 0x%X, Page = "
"0x%X, Inquiry = 0x%X, Connectable = 0x%X",
(BT_UART_MSG_FRAME7SNIFFACTIVITY_MSK & uart_msg->frame7) >>
BT_UART_MSG_FRAME7SNIFFACTIVITY_POS,
@@ -1913,10 +1928,10 @@
return;
}
- IWL_DEBUG_NOTIF(priv, "BT Coex notification:\n");
- IWL_DEBUG_NOTIF(priv, " status: %d\n", coex->bt_status);
- IWL_DEBUG_NOTIF(priv, " traffic load: %d\n", coex->bt_traffic_load);
- IWL_DEBUG_NOTIF(priv, " CI compliance: %d\n",
+ IWL_DEBUG_COEX(priv, "BT Coex notification:\n");
+ IWL_DEBUG_COEX(priv, " status: %d\n", coex->bt_status);
+ IWL_DEBUG_COEX(priv, " traffic load: %d\n", coex->bt_traffic_load);
+ IWL_DEBUG_COEX(priv, " CI compliance: %d\n",
coex->bt_ci_compliance);
iwlagn_print_uartmsg(priv, uart_msg);
@@ -2314,7 +2329,8 @@
{
int ret;
- if (iwl_prepare_card_hw(priv)) {
+ if ((priv->cfg->sku & EEPROM_SKU_CAP_AMT_ENABLE) &&
+ iwl_prepare_card_hw(priv)) {
IWL_WARN(priv, "Exit HW not ready\n");
return -EIO;
}
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
index 592b0cf..85e0828 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
@@ -426,7 +426,7 @@
ieee80211_stop_tx_ba_session(sta, tid);
}
} else {
- IWL_ERR(priv, "Aggregation not enabled for tid %d "
+ IWL_DEBUG_HT(priv, "Aggregation not enabled for tid %d "
"because load = %u\n", tid, load);
}
return ret;
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
index 09f679d..8fa43d4 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
@@ -81,6 +81,21 @@
return ret;
}
+static int iwlagn_disconn_pan(struct iwl_priv *priv,
+ struct iwl_rxon_context *ctx,
+ struct iwl_rxon_cmd *send)
+{
+ __le32 old_filter = send->filter_flags;
+ int ret;
+
+ send->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
+ ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd, sizeof(*send), send);
+
+ send->filter_flags = old_filter;
+
+ return ret;
+}
+
static void iwlagn_update_qos(struct iwl_priv *priv,
struct iwl_rxon_context *ctx)
{
@@ -163,9 +178,6 @@
ret = iwl_send_cmd_pdu_async(priv, ctx->rxon_assoc_cmd,
sizeof(rxon_assoc), &rxon_assoc, NULL);
- if (ret)
- return ret;
-
return ret;
}
@@ -175,10 +187,21 @@
int ret;
struct iwl_rxon_cmd *active = (void *)&ctx->active;
- if (ctx->ctxid == IWL_RXON_CTX_BSS)
+ if (ctx->ctxid == IWL_RXON_CTX_BSS) {
ret = iwlagn_disable_bss(priv, ctx, &ctx->staging);
- else
+ } else {
ret = iwlagn_disable_pan(priv, ctx, &ctx->staging);
+ if (ret)
+ return ret;
+ if (ctx->vif) {
+ ret = iwl_send_rxon_timing(priv, ctx);
+ if (ret) {
+ IWL_ERR(priv, "Failed to send timing (%d)!\n", ret);
+ return ret;
+ }
+ ret = iwlagn_disconn_pan(priv, ctx, &ctx->staging);
+ }
+ }
if (ret)
return ret;
@@ -187,6 +210,8 @@
* keys, so we have to restore those afterwards.
*/
iwl_clear_ucode_stations(priv, ctx);
+ /* update -- might need P2P now */
+ iwl_update_bcast_station(priv, ctx);
iwl_restore_stations(priv, ctx);
ret = iwl_restore_default_wep_keys(priv, ctx);
if (ret) {
@@ -205,10 +230,12 @@
struct iwl_rxon_cmd *active = (void *)&ctx->active;
/* RXON timing must be before associated RXON */
- ret = iwl_send_rxon_timing(priv, ctx);
- if (ret) {
- IWL_ERR(priv, "Failed to send timing (%d)!\n", ret);
- return ret;
+ if (ctx->ctxid == IWL_RXON_CTX_BSS) {
+ ret = iwl_send_rxon_timing(priv, ctx);
+ if (ret) {
+ IWL_ERR(priv, "Failed to send timing (%d)!\n", ret);
+ return ret;
+ }
}
/* QoS info may be cleared by previous un-assoc RXON */
iwlagn_update_qos(priv, ctx);
@@ -263,6 +290,12 @@
IWL_ERR(priv, "Error sending TX power (%d)\n", ret);
return ret;
}
+
+ if ((ctx->vif && ctx->vif->type == NL80211_IFTYPE_STATION) &&
+ priv->cfg->ht_params->smps_mode)
+ ieee80211_request_smps(ctx->vif,
+ priv->cfg->ht_params->smps_mode);
+
return 0;
}
@@ -375,13 +408,11 @@
* do it now if after settings changed.
*/
iwl_set_tx_power(priv, priv->tx_power_next, false);
- return 0;
- }
- if (priv->cfg->ops->hcmd->set_pan_params) {
- ret = priv->cfg->ops->hcmd->set_pan_params(priv);
- if (ret)
- return ret;
+ /* make sure we are in the right PS state */
+ iwl_power_update_mode(priv, true);
+
+ return 0;
}
iwl_set_rxon_hwcrypto(priv, ctx, !iwlagn_mod_params.sw_crypto);
@@ -405,6 +436,12 @@
if (ret)
return ret;
+ if (priv->cfg->ops->hcmd->set_pan_params) {
+ ret = priv->cfg->ops->hcmd->set_pan_params(priv);
+ if (ret)
+ return ret;
+ }
+
if (new_assoc)
return iwlagn_rxon_connect(priv, ctx);
@@ -770,6 +807,13 @@
struct iwl_rxon_context *ctx;
/*
+ * We do not commit power settings while scan is pending,
+ * do it now if the settings changed.
+ */
+ iwl_power_set_mode(priv, &priv->power_data.sleep_cmd_next, false);
+ iwl_set_tx_power(priv, priv->tx_power_next, false);
+
+ /*
* Since setting the RXON may have been deferred while
* performing the scan, fire one off if needed
*/
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c
index 0bd722c..9b32f83f 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c
@@ -35,7 +35,7 @@
#include "iwl-agn.h"
static struct iwl_link_quality_cmd *
-iwl_sta_alloc_lq(struct iwl_priv *priv, u8 sta_id)
+iwl_sta_alloc_lq(struct iwl_priv *priv, struct iwl_rxon_context *ctx, u8 sta_id)
{
int i, r;
struct iwl_link_quality_cmd *link_cmd;
@@ -47,10 +47,15 @@
IWL_ERR(priv, "Unable to allocate memory for LQ cmd.\n");
return NULL;
}
+
+ lockdep_assert_held(&priv->mutex);
+
/* Set up the rate scaling to start at selected rate, fall back
* all the way down to 1M in IEEE order, and then spin on 1M */
if (priv->band == IEEE80211_BAND_5GHZ)
r = IWL_RATE_6M_INDEX;
+ else if (ctx && ctx->vif && ctx->vif->p2p)
+ r = IWL_RATE_6M_INDEX;
else
r = IWL_RATE_1M_INDEX;
@@ -115,7 +120,7 @@
spin_unlock_irqrestore(&priv->sta_lock, flags);
/* Set up default rate scaling table in device's station table */
- link_cmd = iwl_sta_alloc_lq(priv, sta_id);
+ link_cmd = iwl_sta_alloc_lq(priv, ctx, sta_id);
if (!link_cmd) {
IWL_ERR(priv, "Unable to initialize rate scaling for station %pM.\n",
addr);
@@ -554,7 +559,7 @@
priv->stations[sta_id].used |= IWL_STA_BCAST;
spin_unlock_irqrestore(&priv->sta_lock, flags);
- link_cmd = iwl_sta_alloc_lq(priv, sta_id);
+ link_cmd = iwl_sta_alloc_lq(priv, ctx, sta_id);
if (!link_cmd) {
IWL_ERR(priv,
"Unable to initialize rate scaling for bcast station.\n");
@@ -574,14 +579,14 @@
* Only used by iwlagn. Placed here to have all bcast station management
* code together.
*/
-static int iwl_update_bcast_station(struct iwl_priv *priv,
- struct iwl_rxon_context *ctx)
+int iwl_update_bcast_station(struct iwl_priv *priv,
+ struct iwl_rxon_context *ctx)
{
unsigned long flags;
struct iwl_link_quality_cmd *link_cmd;
u8 sta_id = ctx->bcast_sta_id;
- link_cmd = iwl_sta_alloc_lq(priv, sta_id);
+ link_cmd = iwl_sta_alloc_lq(priv, ctx, sta_id);
if (!link_cmd) {
IWL_ERR(priv, "Unable to initialize rate scaling for bcast station.\n");
return -ENOMEM;
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tt.c b/drivers/net/wireless/iwlwifi/iwl-agn-tt.c
index 348f74f..f501d74 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-tt.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-tt.c
@@ -198,7 +198,7 @@
/* Reschedule the ct_kill timer to occur in
* CT_KILL_EXIT_DURATION seconds to ensure we get a
* thermal update */
- IWL_DEBUG_POWER(priv, "schedule ct_kill exit timer\n");
+ IWL_DEBUG_TEMP(priv, "schedule ct_kill exit timer\n");
mod_timer(&priv->thermal_throttle.ct_kill_exit_tm,
jiffies + CT_KILL_EXIT_DURATION * HZ);
}
@@ -208,15 +208,15 @@
bool stop)
{
if (stop) {
- IWL_DEBUG_POWER(priv, "Stop all queues\n");
+ IWL_DEBUG_TEMP(priv, "Stop all queues\n");
if (priv->mac80211_registered)
ieee80211_stop_queues(priv->hw);
- IWL_DEBUG_POWER(priv,
+ IWL_DEBUG_TEMP(priv,
"Schedule 5 seconds CT_KILL Timer\n");
mod_timer(&priv->thermal_throttle.ct_kill_exit_tm,
jiffies + CT_KILL_EXIT_DURATION * HZ);
} else {
- IWL_DEBUG_POWER(priv, "Wake all queues\n");
+ IWL_DEBUG_TEMP(priv, "Wake all queues\n");
if (priv->mac80211_registered)
ieee80211_wake_queues(priv->hw);
}
@@ -232,7 +232,7 @@
/* temperature timer expired, ready to go into CT_KILL state */
if (tt->state != IWL_TI_CT_KILL) {
- IWL_DEBUG_POWER(priv, "entering CT_KILL state when "
+ IWL_DEBUG_TEMP(priv, "entering CT_KILL state when "
"temperature timer expired\n");
tt->state = IWL_TI_CT_KILL;
set_bit(STATUS_CT_KILL, &priv->status);
@@ -242,7 +242,7 @@
static void iwl_prepare_ct_kill_task(struct iwl_priv *priv)
{
- IWL_DEBUG_POWER(priv, "Prepare to enter IWL_TI_CT_KILL\n");
+ IWL_DEBUG_TEMP(priv, "Prepare to enter IWL_TI_CT_KILL\n");
/* make request to retrieve statistics information */
iwl_send_statistics_request(priv, CMD_SYNC, false);
/* Reschedule the ct_kill wait timer */
@@ -273,7 +273,7 @@
(temp > tt->tt_previous_temp) &&
((temp - tt->tt_previous_temp) >
IWL_TT_INCREASE_MARGIN)) {
- IWL_DEBUG_POWER(priv,
+ IWL_DEBUG_TEMP(priv,
"Temperature increase %d degree Celsius\n",
(temp - tt->tt_previous_temp));
}
@@ -338,9 +338,9 @@
} else if (old_state == IWL_TI_CT_KILL &&
tt->state != IWL_TI_CT_KILL)
iwl_perform_ct_kill_task(priv, false);
- IWL_DEBUG_POWER(priv, "Temperature state changed %u\n",
+ IWL_DEBUG_TEMP(priv, "Temperature state changed %u\n",
tt->state);
- IWL_DEBUG_POWER(priv, "Power Index change to %u\n",
+ IWL_DEBUG_TEMP(priv, "Power Index change to %u\n",
tt->tt_power_mode);
}
mutex_unlock(&priv->mutex);
@@ -397,7 +397,7 @@
(temp > tt->tt_previous_temp) &&
((temp - tt->tt_previous_temp) >
IWL_TT_INCREASE_MARGIN)) {
- IWL_DEBUG_POWER(priv,
+ IWL_DEBUG_TEMP(priv,
"Temperature increase %d "
"degree Celsius\n",
(temp - tt->tt_previous_temp));
@@ -467,13 +467,13 @@
set_bit(STATUS_CT_KILL, &priv->status);
tt->state = old_state;
} else {
- IWL_DEBUG_POWER(priv,
+ IWL_DEBUG_TEMP(priv,
"Thermal Throttling to new state: %u\n",
tt->state);
if (old_state != IWL_TI_CT_KILL &&
tt->state == IWL_TI_CT_KILL) {
if (force) {
- IWL_DEBUG_POWER(priv,
+ IWL_DEBUG_TEMP(priv,
"Enter IWL_TI_CT_KILL\n");
set_bit(STATUS_CT_KILL, &priv->status);
iwl_perform_ct_kill_task(priv, true);
@@ -483,7 +483,7 @@
}
} else if (old_state == IWL_TI_CT_KILL &&
tt->state != IWL_TI_CT_KILL) {
- IWL_DEBUG_POWER(priv, "Exit IWL_TI_CT_KILL\n");
+ IWL_DEBUG_TEMP(priv, "Exit IWL_TI_CT_KILL\n");
iwl_perform_ct_kill_task(priv, false);
}
}
@@ -568,7 +568,7 @@
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return;
- IWL_DEBUG_POWER(priv, "Queueing critical temperature enter.\n");
+ IWL_DEBUG_TEMP(priv, "Queueing critical temperature enter.\n");
queue_work(priv->workqueue, &priv->ct_enter);
}
@@ -577,7 +577,7 @@
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return;
- IWL_DEBUG_POWER(priv, "Queueing critical temperature exit.\n");
+ IWL_DEBUG_TEMP(priv, "Queueing critical temperature exit.\n");
queue_work(priv->workqueue, &priv->ct_exit);
}
@@ -603,7 +603,7 @@
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return;
- IWL_DEBUG_POWER(priv, "Queueing thermal throttling work.\n");
+ IWL_DEBUG_TEMP(priv, "Queueing thermal throttling work.\n");
queue_work(priv->workqueue, &priv->tt_work);
}
@@ -618,7 +618,7 @@
int size = sizeof(struct iwl_tt_trans) * (IWL_TI_STATE_MAX - 1);
struct iwl_tt_trans *transaction;
- IWL_DEBUG_POWER(priv, "Initialize Thermal Throttling\n");
+ IWL_DEBUG_TEMP(priv, "Initialize Thermal Throttling\n");
memset(tt, 0, sizeof(struct iwl_tt_mgmt));
@@ -638,7 +638,7 @@
INIT_WORK(&priv->ct_exit, iwl_bg_ct_exit);
if (priv->cfg->base_params->adv_thermal_throttle) {
- IWL_DEBUG_POWER(priv, "Advanced Thermal Throttling\n");
+ IWL_DEBUG_TEMP(priv, "Advanced Thermal Throttling\n");
tt->restriction = kzalloc(sizeof(struct iwl_tt_restriction) *
IWL_TI_STATE_MAX, GFP_KERNEL);
tt->transaction = kzalloc(sizeof(struct iwl_tt_trans) *
@@ -671,7 +671,7 @@
priv->thermal_throttle.advanced_tt = true;
}
} else {
- IWL_DEBUG_POWER(priv, "Legacy Thermal Throttling\n");
+ IWL_DEBUG_TEMP(priv, "Legacy Thermal Throttling\n");
priv->thermal_throttle.advanced_tt = false;
}
}
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
index 4974cd7..d0ac090 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
@@ -716,10 +716,10 @@
/* Physical address of this Tx command's header (not MAC header!),
* within command buffer array. */
- txcmd_phys = pci_map_single(priv->pci_dev,
+ txcmd_phys = dma_map_single(priv->bus.dev,
&out_cmd->hdr, firstlen,
- PCI_DMA_BIDIRECTIONAL);
- if (unlikely(pci_dma_mapping_error(priv->pci_dev, txcmd_phys)))
+ DMA_BIDIRECTIONAL);
+ if (unlikely(dma_mapping_error(priv->bus.dev, txcmd_phys)))
goto drop_unlock_sta;
dma_unmap_addr_set(out_meta, mapping, txcmd_phys);
dma_unmap_len_set(out_meta, len, firstlen);
@@ -735,13 +735,13 @@
* if any (802.11 null frames have no payload). */
secondlen = skb->len - hdr_len;
if (secondlen > 0) {
- phys_addr = pci_map_single(priv->pci_dev, skb->data + hdr_len,
- secondlen, PCI_DMA_TODEVICE);
- if (unlikely(pci_dma_mapping_error(priv->pci_dev, phys_addr))) {
- pci_unmap_single(priv->pci_dev,
+ phys_addr = dma_map_single(priv->bus.dev, skb->data + hdr_len,
+ secondlen, DMA_TO_DEVICE);
+ if (unlikely(dma_mapping_error(priv->bus.dev, phys_addr))) {
+ dma_unmap_single(priv->bus.dev,
dma_unmap_addr(out_meta, mapping),
dma_unmap_len(out_meta, len),
- PCI_DMA_BIDIRECTIONAL);
+ DMA_BIDIRECTIONAL);
goto drop_unlock_sta;
}
}
@@ -764,8 +764,8 @@
offsetof(struct iwl_tx_cmd, scratch);
/* take back ownership of DMA buffer to enable update */
- pci_dma_sync_single_for_cpu(priv->pci_dev, txcmd_phys,
- firstlen, PCI_DMA_BIDIRECTIONAL);
+ dma_sync_single_for_cpu(priv->bus.dev, txcmd_phys, firstlen,
+ DMA_BIDIRECTIONAL);
tx_cmd->dram_lsb_ptr = cpu_to_le32(scratch_phys);
tx_cmd->dram_msb_ptr = iwl_get_dma_hi_addr(scratch_phys);
@@ -780,8 +780,8 @@
iwlagn_txq_update_byte_cnt_tbl(priv, txq,
le16_to_cpu(tx_cmd->len));
- pci_dma_sync_single_for_device(priv->pci_dev, txcmd_phys,
- firstlen, PCI_DMA_BIDIRECTIONAL);
+ dma_sync_single_for_device(priv->bus.dev, txcmd_phys, firstlen,
+ DMA_BIDIRECTIONAL);
trace_iwlwifi_dev_tx(priv,
&((struct iwl_tfd *)txq->tfds)[txq->q.write_ptr],
@@ -834,8 +834,8 @@
static inline int iwlagn_alloc_dma_ptr(struct iwl_priv *priv,
struct iwl_dma_ptr *ptr, size_t size)
{
- ptr->addr = dma_alloc_coherent(&priv->pci_dev->dev, size, &ptr->dma,
- GFP_KERNEL);
+ ptr->addr = dma_alloc_coherent(priv->bus.dev, size,
+ &ptr->dma, GFP_KERNEL);
if (!ptr->addr)
return -ENOMEM;
ptr->size = size;
@@ -848,7 +848,7 @@
if (unlikely(!ptr->addr))
return;
- dma_free_coherent(&priv->pci_dev->dev, ptr->size, ptr->addr, ptr->dma);
+ dma_free_coherent(priv->bus.dev, ptr->size, ptr->addr, ptr->dma);
memset(ptr, 0, sizeof(*ptr));
}
@@ -1033,8 +1033,8 @@
if (unlikely(tx_fifo < 0))
return tx_fifo;
- IWL_WARN(priv, "%s on ra = %pM tid = %d\n",
- __func__, sta->addr, tid);
+ IWL_DEBUG_HT(priv, "TX AGG request on ra = %pM tid = %d\n",
+ sta->addr, tid);
sta_id = iwl_sta_id(sta);
if (sta_id == IWL_INVALID_STATION) {
@@ -1236,9 +1236,9 @@
struct ieee80211_hdr *hdr;
if ((index >= q->n_bd) || (iwl_queue_used(q, index) == 0)) {
- IWL_ERR(priv, "Read index for DMA queue txq id (%d), index %d, "
- "is out of range [0-%d] %d %d.\n", txq_id,
- index, q->n_bd, q->write_ptr, q->read_ptr);
+ IWL_ERR(priv, "%s: Read index for DMA queue txq id (%d), "
+ "index %d is out of range [0-%d] %d %d.\n", __func__,
+ txq_id, index, q->n_bd, q->write_ptr, q->read_ptr);
return 0;
}
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c
index 97de5d9..de8277e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c
@@ -143,7 +143,7 @@
FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE |
FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_ENDTFD);
- IWL_DEBUG_INFO(priv, "%s uCode section being loaded...\n", name);
+ IWL_DEBUG_FW(priv, "%s uCode section being loaded...\n", name);
ret = wait_event_interruptible_timeout(priv->wait_command_queue,
priv->ucode_write_complete, 5 * HZ);
if (ret == -ERESTARTSYS) {
@@ -183,10 +183,7 @@
__le16 *xtal_calib =
(__le16 *)iwl_eeprom_query_addr(priv, EEPROM_XTAL);
- cmd.hdr.op_code = IWL_PHY_CALIBRATE_CRYSTAL_FRQ_CMD;
- cmd.hdr.first_group = 0;
- cmd.hdr.groups_num = 1;
- cmd.hdr.data_valid = 1;
+ iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_CRYSTAL_FRQ_CMD);
cmd.cap_pin1 = le16_to_cpu(xtal_calib[0]);
cmd.cap_pin2 = le16_to_cpu(xtal_calib[1]);
return iwl_calib_set(&priv->calib_results[IWL_CALIB_XTAL],
@@ -197,15 +194,14 @@
{
struct iwl_calib_temperature_offset_cmd cmd;
__le16 *offset_calib =
- (__le16 *)iwl_eeprom_query_addr(priv, EEPROM_5000_TEMPERATURE);
- cmd.hdr.op_code = IWL_PHY_CALIBRATE_TEMP_OFFSET_CMD;
- cmd.hdr.first_group = 0;
- cmd.hdr.groups_num = 1;
- cmd.hdr.data_valid = 1;
+ (__le16 *)iwl_eeprom_query_addr(priv, EEPROM_TEMPERATURE);
+
+ memset(&cmd, 0, sizeof(cmd));
+ iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_TEMP_OFFSET_CMD);
cmd.radio_sensor_offset = le16_to_cpu(offset_calib[1]);
if (!(cmd.radio_sensor_offset))
cmd.radio_sensor_offset = DEFAULT_RADIO_SENSOR_OFFSET;
- cmd.reserved = 0;
+
IWL_DEBUG_CALIB(priv, "Radio sensor offset: %d\n",
cmd.radio_sensor_offset);
return iwl_calib_set(&priv->calib_results[IWL_CALIB_TEMP_OFFSET],
@@ -508,7 +504,7 @@
u32 val;
u32 i;
- IWL_DEBUG_INFO(priv, "ucode inst image size is %u\n", len);
+ IWL_DEBUG_FW(priv, "ucode inst image size is %u\n", len);
for (i = 0; i < len; i += 100, image += 100/sizeof(u32)) {
/* read data comes through single port, auto-incr addr */
@@ -533,7 +529,7 @@
u32 offs;
int errors = 0;
- IWL_DEBUG_INFO(priv, "ucode inst image size is %u\n", len);
+ IWL_DEBUG_FW(priv, "ucode inst image size is %u\n", len);
iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR,
IWLAGN_RTC_INST_LOWER_BOUND);
@@ -559,7 +555,7 @@
static int iwl_verify_ucode(struct iwl_priv *priv, struct fw_img *img)
{
if (!iwlcore_verify_inst_sparse(priv, &img->code)) {
- IWL_DEBUG_INFO(priv, "uCode is good in inst SRAM\n");
+ IWL_DEBUG_FW(priv, "uCode is good in inst SRAM\n");
return 0;
}
@@ -583,7 +579,7 @@
palive = &pkt->u.alive_frame;
- IWL_DEBUG_INFO(priv, "Alive ucode status 0x%08X revision "
+ IWL_DEBUG_FW(priv, "Alive ucode status 0x%08X revision "
"0x%01X 0x%01X\n",
palive->is_valid, palive->ver_type,
palive->ver_subtype);
@@ -602,12 +598,12 @@
int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv,
struct fw_img *image,
- int subtype, int alternate_subtype)
+ enum iwlagn_ucode_type ucode_type)
{
struct iwl_notification_wait alive_wait;
struct iwlagn_alive_data alive_data;
int ret;
- enum iwlagn_ucode_subtype old_type;
+ enum iwlagn_ucode_type old_type;
ret = iwlagn_start_device(priv);
if (ret)
@@ -617,7 +613,7 @@
iwlagn_alive_fn, &alive_data);
old_type = priv->ucode_type;
- priv->ucode_type = subtype;
+ priv->ucode_type = ucode_type;
ret = iwlagn_load_given_ucode(priv, image);
if (ret) {
@@ -645,15 +641,6 @@
return -EIO;
}
- if (alive_data.subtype != subtype &&
- alive_data.subtype != alternate_subtype) {
- IWL_ERR(priv,
- "Loaded ucode is not expected type (got %d, expected %d)!\n",
- alive_data.subtype, subtype);
- priv->ucode_type = old_type;
- return -EIO;
- }
-
ret = iwl_verify_ucode(priv, image);
if (ret) {
priv->ucode_type = old_type;
@@ -685,7 +672,7 @@
if (!priv->ucode_init.code.len)
return 0;
- if (priv->ucode_type != UCODE_SUBTYPE_NONE_LOADED)
+ if (priv->ucode_type != IWL_UCODE_NONE)
return 0;
iwlagn_init_notification_wait(priv, &calib_wait,
@@ -694,7 +681,7 @@
/* Will also start the device */
ret = iwlagn_load_ucode_wait_alive(priv, &priv->ucode_init,
- UCODE_SUBTYPE_INIT, -1);
+ IWL_UCODE_INIT);
if (ret)
goto error;
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index 8e1942e..e2f6b2a 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -32,8 +32,6 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/pci-aspm.h>
#include <linux/slab.h>
#include <linux/dma-mapping.h>
#include <linux/delay.h>
@@ -49,8 +47,6 @@
#include <asm/div64.h>
-#define DRV_NAME "iwlagn"
-
#include "iwl-eeprom.h"
#include "iwl-dev.h"
#include "iwl-core.h"
@@ -59,6 +55,7 @@
#include "iwl-sta.h"
#include "iwl-agn-calib.h"
#include "iwl-agn.h"
+#include "iwl-pci.h"
/******************************************************************************
@@ -97,7 +94,7 @@
for_each_context(priv, ctx) {
priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
if (ctx->active.rx_chain != ctx->staging.rx_chain)
- iwlcore_commit_rxon(priv, ctx);
+ iwlagn_commit_rxon(priv, ctx);
}
}
}
@@ -135,6 +132,7 @@
struct iwl_host_cmd cmd = {
.id = REPLY_TX_BEACON,
};
+ struct ieee80211_tx_info *info;
u32 frame_size;
u32 rate_flags;
u32 rate;
@@ -175,14 +173,31 @@
frame_size);
/* Set up packet rate and flags */
- rate = iwl_rate_get_lowest_plcp(priv, priv->beacon_ctx);
+ info = IEEE80211_SKB_CB(priv->beacon_skb);
+
+ /*
+ * Let's set up the rate at least somewhat correctly;
+ * it will currently not actually be used by the uCode,
+ * it uses the broadcast station's rate instead.
+ */
+ if (info->control.rates[0].idx < 0 ||
+ info->control.rates[0].flags & IEEE80211_TX_RC_MCS)
+ rate = 0;
+ else
+ rate = info->control.rates[0].idx;
+
priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant,
priv->hw_params.valid_tx_ant);
rate_flags = iwl_ant_idx_to_flags(priv->mgmt_tx_ant);
- if ((rate >= IWL_FIRST_CCK_RATE) && (rate <= IWL_LAST_CCK_RATE))
+
+ /* In mac80211, rates for 5 GHz start at 0 */
+ if (info->band == IEEE80211_BAND_5GHZ)
+ rate += IWL_FIRST_OFDM_RATE;
+ else if (rate >= IWL_FIRST_CCK_RATE && rate <= IWL_LAST_CCK_RATE)
rate_flags |= RATE_MCS_CCK_MSK;
- tx_beacon_cmd->tx.rate_n_flags = iwl_hw_set_rate_n_flags(rate,
- rate_flags);
+
+ tx_beacon_cmd->tx.rate_n_flags =
+ iwl_hw_set_rate_n_flags(rate, rate_flags);
/* Submit command */
cmd.len[0] = sizeof(*tx_beacon_cmd);
@@ -274,7 +289,7 @@
for_each_context(priv, ctx) {
if (priv->cfg->ops->hcmd->set_rxon_chain)
priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
- iwlcore_commit_rxon(priv, ctx);
+ iwlagn_commit_rxon(priv, ctx);
}
priv->cfg->ops->hcmd->send_bt_config(priv);
@@ -440,10 +455,8 @@
if (!iwl_is_ready_rf(priv))
return;
- if (priv->cfg->ops->lib->txfifo_flush) {
- IWL_DEBUG_INFO(priv, "device request: flush all tx frames\n");
- iwlagn_dev_txfifo_flush(priv, IWL_DROP_ALL);
- }
+ IWL_DEBUG_INFO(priv, "device request: flush all tx frames\n");
+ iwlagn_dev_txfifo_flush(priv, IWL_DROP_ALL);
}
/**
@@ -497,9 +510,9 @@
rxq->queue[i] = NULL;
- pci_unmap_page(priv->pci_dev, rxb->page_dma,
+ dma_unmap_page(priv->bus.dev, rxb->page_dma,
PAGE_SIZE << priv->hw_params.rx_page_order,
- PCI_DMA_FROMDEVICE);
+ DMA_FROM_DEVICE);
pkt = rxb_addr(rxb);
len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK;
@@ -581,9 +594,9 @@
* rx_free list for reuse later. */
spin_lock_irqsave(&rxq->lock, flags);
if (rxb->page != NULL) {
- rxb->page_dma = pci_map_page(priv->pci_dev, rxb->page,
+ rxb->page_dma = dma_map_page(priv->bus.dev, rxb->page,
0, PAGE_SIZE << priv->hw_params.rx_page_order,
- PCI_DMA_FROMDEVICE);
+ DMA_FROM_DEVICE);
list_add_tail(&rxb->list, &rxq->rx_free);
rxq->free_count++;
} else
@@ -939,22 +952,28 @@
*
******************************************************************************/
-static void iwl_free_fw_desc(struct pci_dev *pci_dev, struct fw_desc *desc)
+static void iwl_free_fw_desc(struct iwl_priv *priv, struct fw_desc *desc)
{
if (desc->v_addr)
- dma_free_coherent(&pci_dev->dev, desc->len,
+ dma_free_coherent(priv->bus.dev, desc->len,
desc->v_addr, desc->p_addr);
desc->v_addr = NULL;
desc->len = 0;
}
-static void iwl_free_fw_img(struct pci_dev *pci_dev, struct fw_img *img)
+static void iwl_free_fw_img(struct iwl_priv *priv, struct fw_img *img)
{
- iwl_free_fw_desc(pci_dev, &img->code);
- iwl_free_fw_desc(pci_dev, &img->data);
+ iwl_free_fw_desc(priv, &img->code);
+ iwl_free_fw_desc(priv, &img->data);
}
-static int iwl_alloc_fw_desc(struct pci_dev *pci_dev, struct fw_desc *desc,
+static void iwl_dealloc_ucode(struct iwl_priv *priv)
+{
+ iwl_free_fw_img(priv, &priv->ucode_rt);
+ iwl_free_fw_img(priv, &priv->ucode_init);
+}
+
+static int iwl_alloc_fw_desc(struct iwl_priv *priv, struct fw_desc *desc,
const void *data, size_t len)
{
if (!len) {
@@ -962,21 +981,16 @@
return -EINVAL;
}
- desc->v_addr = dma_alloc_coherent(&pci_dev->dev, len,
+ desc->v_addr = dma_alloc_coherent(priv->bus.dev, len,
&desc->p_addr, GFP_KERNEL);
if (!desc->v_addr)
return -ENOMEM;
+
desc->len = len;
memcpy(desc->v_addr, data, len);
return 0;
}
-static void iwl_dealloc_ucode_pci(struct iwl_priv *priv)
-{
- iwl_free_fw_img(priv->pci_dev, &priv->ucode_rt);
- iwl_free_fw_img(priv->pci_dev, &priv->ucode_init);
-}
-
struct iwlagn_ucode_capabilities {
u32 max_probe_length;
u32 standard_phy_calibration_size;
@@ -1021,8 +1035,8 @@
priv->firmware_name);
return request_firmware_nowait(THIS_MODULE, 1, priv->firmware_name,
- &priv->pci_dev->dev, GFP_KERNEL, priv,
- iwl_ucode_callback);
+ priv->bus.dev,
+ GFP_KERNEL, priv, iwl_ucode_callback);
}
struct iwlagn_firmware_pieces {
@@ -1443,19 +1457,19 @@
/* Runtime instructions and 2 copies of data:
* 1) unmodified from disk
* 2) backup cache for save/restore during power-downs */
- if (iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_rt.code,
+ if (iwl_alloc_fw_desc(priv, &priv->ucode_rt.code,
pieces.inst, pieces.inst_size))
goto err_pci_alloc;
- if (iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_rt.data,
+ if (iwl_alloc_fw_desc(priv, &priv->ucode_rt.data,
pieces.data, pieces.data_size))
goto err_pci_alloc;
/* Initialization instructions and data */
if (pieces.init_size && pieces.init_data_size) {
- if (iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_init.code,
+ if (iwl_alloc_fw_desc(priv, &priv->ucode_init.code,
pieces.init, pieces.init_size))
goto err_pci_alloc;
- if (iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_init.data,
+ if (iwl_alloc_fw_desc(priv, &priv->ucode_init.data,
pieces.init_data, pieces.init_data_size))
goto err_pci_alloc;
}
@@ -1485,7 +1499,8 @@
priv->new_scan_threshold_behaviour =
!!(ucode_capa.flags & IWL_UCODE_TLV_FLAGS_NEWSCAN);
- if (ucode_capa.flags & IWL_UCODE_TLV_FLAGS_PAN) {
+ if ((priv->cfg->sku & EEPROM_SKU_CAP_IPAN_ENABLE) &&
+ (ucode_capa.flags & IWL_UCODE_TLV_FLAGS_PAN)) {
priv->valid_contexts |= BIT(IWL_RXON_CTX_PAN);
priv->sta_key_max_num = STA_KEY_MAX_NUM_PAN;
} else
@@ -1523,7 +1538,7 @@
if (err)
IWL_ERR(priv, "failed to create debugfs files. Ignoring error: %d\n", err);
- err = sysfs_create_group(&priv->pci_dev->dev.kobj,
+ err = sysfs_create_group(&(priv->bus.dev->kobj),
&iwl_attribute_group);
if (err) {
IWL_ERR(priv, "failed to create sysfs device attributes\n");
@@ -1544,10 +1559,10 @@
err_pci_alloc:
IWL_ERR(priv, "failed to allocate pci memory\n");
- iwl_dealloc_ucode_pci(priv);
+ iwl_dealloc_ucode(priv);
out_unbind:
complete(&priv->_agn.firmware_loading_complete);
- device_release_driver(&priv->pci_dev->dev);
+ device_release_driver(priv->bus.dev);
release_firmware(ucode_raw);
}
@@ -1626,7 +1641,7 @@
struct iwl_error_event_table table;
base = priv->device_pointers.error_event_table;
- if (priv->ucode_type == UCODE_SUBTYPE_INIT) {
+ if (priv->ucode_type == IWL_UCODE_INIT) {
if (!base)
base = priv->_agn.init_errlog_ptr;
} else {
@@ -1638,7 +1653,7 @@
IWL_ERR(priv,
"Not valid error log pointer 0x%08X for %s uCode\n",
base,
- (priv->ucode_type == UCODE_SUBTYPE_INIT)
+ (priv->ucode_type == IWL_UCODE_INIT)
? "Init" : "RT");
return;
}
@@ -1702,7 +1717,7 @@
return pos;
base = priv->device_pointers.log_event_table;
- if (priv->ucode_type == UCODE_SUBTYPE_INIT) {
+ if (priv->ucode_type == IWL_UCODE_INIT) {
if (!base)
base = priv->_agn.init_evtlog_ptr;
} else {
@@ -1815,7 +1830,7 @@
size_t bufsz = 0;
base = priv->device_pointers.log_event_table;
- if (priv->ucode_type == UCODE_SUBTYPE_INIT) {
+ if (priv->ucode_type == IWL_UCODE_INIT) {
logsize = priv->_agn.init_evtlog_size;
if (!base)
base = priv->_agn.init_evtlog_ptr;
@@ -1829,7 +1844,7 @@
IWL_ERR(priv,
"Invalid event log pointer 0x%08X for %s uCode\n",
base,
- (priv->ucode_type == UCODE_SUBTYPE_INIT)
+ (priv->ucode_type == IWL_UCODE_INIT)
? "Init" : "RT");
return -EINVAL;
}
@@ -2056,7 +2071,7 @@
set_bit(STATUS_READY, &priv->status);
/* Configure the adapter for unassociated operation */
- ret = iwlcore_commit_rxon(priv, ctx);
+ ret = iwlagn_commit_rxon(priv, ctx);
if (ret)
return ret;
@@ -2210,8 +2225,7 @@
ret = iwlagn_load_ucode_wait_alive(priv,
&priv->ucode_rt,
- UCODE_SUBTYPE_REGULAR,
- UCODE_SUBTYPE_REGULAR_NEW);
+ IWL_UCODE_REGULAR);
if (ret) {
IWL_ERR(priv, "Failed to start RT ucode: %d\n", ret);
goto error;
@@ -2420,6 +2434,77 @@
*
*****************************************************************************/
+static const struct ieee80211_iface_limit iwlagn_sta_ap_limits[] = {
+ {
+ .max = 1,
+ .types = BIT(NL80211_IFTYPE_STATION),
+ },
+ {
+ .max = 1,
+ .types = BIT(NL80211_IFTYPE_AP),
+ },
+};
+
+static const struct ieee80211_iface_limit iwlagn_2sta_limits[] = {
+ {
+ .max = 2,
+ .types = BIT(NL80211_IFTYPE_STATION),
+ },
+};
+
+static const struct ieee80211_iface_limit iwlagn_p2p_sta_go_limits[] = {
+ {
+ .max = 1,
+ .types = BIT(NL80211_IFTYPE_STATION),
+ },
+ {
+ .max = 1,
+ .types = BIT(NL80211_IFTYPE_P2P_GO) |
+ BIT(NL80211_IFTYPE_AP),
+ },
+};
+
+static const struct ieee80211_iface_limit iwlagn_p2p_2sta_limits[] = {
+ {
+ .max = 2,
+ .types = BIT(NL80211_IFTYPE_STATION),
+ },
+ {
+ .max = 1,
+ .types = BIT(NL80211_IFTYPE_P2P_CLIENT),
+ },
+};
+
+static const struct ieee80211_iface_combination
+iwlagn_iface_combinations_dualmode[] = {
+ { .num_different_channels = 1,
+ .max_interfaces = 2,
+ .beacon_int_infra_match = true,
+ .limits = iwlagn_sta_ap_limits,
+ .n_limits = ARRAY_SIZE(iwlagn_sta_ap_limits),
+ },
+ { .num_different_channels = 1,
+ .max_interfaces = 2,
+ .limits = iwlagn_2sta_limits,
+ .n_limits = ARRAY_SIZE(iwlagn_2sta_limits),
+ },
+};
+
+static const struct ieee80211_iface_combination
+iwlagn_iface_combinations_p2p[] = {
+ { .num_different_channels = 1,
+ .max_interfaces = 2,
+ .beacon_int_infra_match = true,
+ .limits = iwlagn_p2p_sta_go_limits,
+ .n_limits = ARRAY_SIZE(iwlagn_p2p_sta_go_limits),
+ },
+ { .num_different_channels = 1,
+ .max_interfaces = 2,
+ .limits = iwlagn_p2p_2sta_limits,
+ .n_limits = ARRAY_SIZE(iwlagn_p2p_2sta_limits),
+ },
+};
+
/*
* Not a mac80211 entry point function, but it fits in with all the
* other mac80211 functions grouped here.
@@ -2445,7 +2530,7 @@
hw->flags |= IEEE80211_HW_SUPPORTS_PS |
IEEE80211_HW_SUPPORTS_DYNAMIC_PS;
- if (priv->cfg->sku & IWL_SKU_N)
+ if (priv->cfg->sku & EEPROM_SKU_CAP_11N_ENABLE)
hw->flags |= IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS |
IEEE80211_HW_SUPPORTS_STATIC_SMPS;
@@ -2460,17 +2545,28 @@
hw->wiphy->interface_modes |= ctx->exclusive_interface_modes;
}
+ BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2);
+
+ if (hw->wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_CLIENT)) {
+ hw->wiphy->iface_combinations = iwlagn_iface_combinations_p2p;
+ hw->wiphy->n_iface_combinations =
+ ARRAY_SIZE(iwlagn_iface_combinations_p2p);
+ } else if (hw->wiphy->interface_modes & BIT(NL80211_IFTYPE_AP)) {
+ hw->wiphy->iface_combinations = iwlagn_iface_combinations_dualmode;
+ hw->wiphy->n_iface_combinations =
+ ARRAY_SIZE(iwlagn_iface_combinations_dualmode);
+ }
+
hw->wiphy->max_remain_on_channel_duration = 1000;
hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY |
WIPHY_FLAG_DISABLE_BEACON_HINTS |
WIPHY_FLAG_IBSS_RSN;
- /*
- * For now, disable PS by default because it affects
- * RX performance significantly.
- */
- hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
+ if (iwlagn_mod_params.power_save)
+ hw->wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT;
+ else
+ hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX;
/* we create the 802.11 header and a zero-length SSID element */
@@ -2674,7 +2770,7 @@
IWL_DEBUG_HT(priv, "A-MPDU action on addr %pM tid %d\n",
sta->addr, tid);
- if (!(priv->cfg->sku & IWL_SKU_N))
+ if (!(priv->cfg->sku & EEPROM_SKU_CAP_11N_ENABLE))
return -EACCES;
mutex_lock(&priv->mutex);
@@ -2711,12 +2807,9 @@
ret = 0;
if (priv->cfg->ht_params &&
priv->cfg->ht_params->use_rts_for_aggregation) {
- struct iwl_station_priv *sta_priv =
- (void *) sta->drv_priv;
/*
* switch off RTS/CTS if it was previously enabled
*/
-
sta_priv->lq_sta.lq.general_params.flags &=
~LINK_QUAL_FLAGS_SET_STA_TLC_RTS_MSK;
iwl_send_lq_cmd(priv, iwl_rxon_ctx_from_vif(vif),
@@ -2764,6 +2857,9 @@
iwl_send_lq_cmd(priv, iwl_rxon_ctx_from_vif(vif),
&sta_priv->lq_sta.lq, CMD_ASYNC, false);
+
+ IWL_INFO(priv, "Tx aggregation enabled on ra = %pM tid = %d\n",
+ sta->addr, tid);
ret = 0;
break;
}
@@ -2833,7 +2929,6 @@
*/
struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
u16 ch;
- unsigned long flags = 0;
IWL_DEBUG_MAC80211(priv, "enter\n");
@@ -2850,65 +2945,64 @@
if (!iwl_is_associated_ctx(ctx))
goto out;
- if (priv->cfg->ops->lib->set_channel_switch) {
+ if (!priv->cfg->ops->lib->set_channel_switch)
+ goto out;
- ch = channel->hw_value;
- if (le16_to_cpu(ctx->active.channel) != ch) {
- ch_info = iwl_get_channel_info(priv,
- channel->band,
- ch);
- if (!is_channel_valid(ch_info)) {
- IWL_DEBUG_MAC80211(priv, "invalid channel\n");
- goto out;
- }
- spin_lock_irqsave(&priv->lock, flags);
+ ch = channel->hw_value;
+ if (le16_to_cpu(ctx->active.channel) == ch)
+ goto out;
- priv->current_ht_config.smps = conf->smps_mode;
-
- /* Configure HT40 channels */
- ctx->ht.enabled = conf_is_ht(conf);
- if (ctx->ht.enabled) {
- if (conf_is_ht40_minus(conf)) {
- ctx->ht.extension_chan_offset =
- IEEE80211_HT_PARAM_CHA_SEC_BELOW;
- ctx->ht.is_40mhz = true;
- } else if (conf_is_ht40_plus(conf)) {
- ctx->ht.extension_chan_offset =
- IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
- ctx->ht.is_40mhz = true;
- } else {
- ctx->ht.extension_chan_offset =
- IEEE80211_HT_PARAM_CHA_SEC_NONE;
- ctx->ht.is_40mhz = false;
- }
- } else
- ctx->ht.is_40mhz = false;
-
- if ((le16_to_cpu(ctx->staging.channel) != ch))
- ctx->staging.flags = 0;
-
- iwl_set_rxon_channel(priv, channel, ctx);
- iwl_set_rxon_ht(priv, ht_conf);
- iwl_set_flags_for_band(priv, ctx, channel->band,
- ctx->vif);
- spin_unlock_irqrestore(&priv->lock, flags);
-
- iwl_set_rate(priv);
- /*
- * at this point, staging_rxon has the
- * configuration for channel switch
- */
- set_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status);
- priv->switch_channel = cpu_to_le16(ch);
- if (priv->cfg->ops->lib->set_channel_switch(priv,
- ch_switch)) {
- clear_bit(STATUS_CHANNEL_SWITCH_PENDING,
- &priv->status);
- priv->switch_channel = 0;
- ieee80211_chswitch_done(ctx->vif, false);
- }
- }
+ ch_info = iwl_get_channel_info(priv, channel->band, ch);
+ if (!is_channel_valid(ch_info)) {
+ IWL_DEBUG_MAC80211(priv, "invalid channel\n");
+ goto out;
}
+
+ spin_lock_irq(&priv->lock);
+
+ priv->current_ht_config.smps = conf->smps_mode;
+
+ /* Configure HT40 channels */
+ ctx->ht.enabled = conf_is_ht(conf);
+ if (ctx->ht.enabled) {
+ if (conf_is_ht40_minus(conf)) {
+ ctx->ht.extension_chan_offset =
+ IEEE80211_HT_PARAM_CHA_SEC_BELOW;
+ ctx->ht.is_40mhz = true;
+ } else if (conf_is_ht40_plus(conf)) {
+ ctx->ht.extension_chan_offset =
+ IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
+ ctx->ht.is_40mhz = true;
+ } else {
+ ctx->ht.extension_chan_offset =
+ IEEE80211_HT_PARAM_CHA_SEC_NONE;
+ ctx->ht.is_40mhz = false;
+ }
+ } else
+ ctx->ht.is_40mhz = false;
+
+ if ((le16_to_cpu(ctx->staging.channel) != ch))
+ ctx->staging.flags = 0;
+
+ iwl_set_rxon_channel(priv, channel, ctx);
+ iwl_set_rxon_ht(priv, ht_conf);
+ iwl_set_flags_for_band(priv, ctx, channel->band, ctx->vif);
+
+ spin_unlock_irq(&priv->lock);
+
+ iwl_set_rate(priv);
+ /*
+ * at this point, staging_rxon has the
+ * configuration for channel switch
+ */
+ set_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status);
+ priv->switch_channel = cpu_to_le16(ch);
+ if (priv->cfg->ops->lib->set_channel_switch(priv, ch_switch)) {
+ clear_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status);
+ priv->switch_channel = 0;
+ ieee80211_chswitch_done(ctx->vif, false);
+ }
+
out:
mutex_unlock(&priv->mutex);
IWL_DEBUG_MAC80211(priv, "leave\n");
@@ -2971,10 +3065,6 @@
mutex_lock(&priv->mutex);
IWL_DEBUG_MAC80211(priv, "enter\n");
- /* do not support "flush" */
- if (!priv->cfg->ops->lib->txfifo_flush)
- goto done;
-
if (test_bit(STATUS_EXIT_PENDING, &priv->status)) {
IWL_DEBUG_TX(priv, "Aborting flush due to device shutdown\n");
goto done;
@@ -2990,7 +3080,7 @@
*/
if (drop) {
IWL_DEBUG_MAC80211(priv, "send flush command\n");
- if (priv->cfg->ops->lib->txfifo_flush(priv, IWL_DROP_ALL)) {
+ if (iwlagn_txfifo_flush(priv, IWL_DROP_ALL)) {
IWL_ERR(priv, "flush request fail\n");
goto done;
}
@@ -3019,7 +3109,7 @@
priv->_agn.hw_roc_channel = NULL;
- iwlcore_commit_rxon(priv, ctx);
+ iwlagn_commit_rxon(priv, ctx);
ctx->is_active = false;
}
@@ -3062,7 +3152,7 @@
priv->_agn.hw_roc_channel = channel;
priv->_agn.hw_roc_chantype = channel_type;
priv->_agn.hw_roc_duration = DIV_ROUND_UP(duration * 1000, 1024);
- iwlcore_commit_rxon(priv, &priv->contexts[IWL_RXON_CTX_PAN]);
+ iwlagn_commit_rxon(priv, &priv->contexts[IWL_RXON_CTX_PAN]);
queue_delayed_work(priv->workqueue, &priv->_agn.hw_roc_work,
msecs_to_jiffies(duration + 20));
@@ -3271,14 +3361,11 @@
.offchannel_tx = iwl_mac_offchannel_tx,
.offchannel_tx_cancel_wait = iwl_mac_offchannel_tx_cancel_wait,
CFG80211_TESTMODE_CMD(iwl_testmode_cmd)
+ CFG80211_TESTMODE_DUMP(iwl_testmode_dump)
};
static u32 iwl_hw_detect(struct iwl_priv *priv)
{
- u8 rev_id;
-
- pci_read_config_byte(priv->pci_dev, PCI_REVISION_ID, &rev_id);
- IWL_DEBUG_INFO(priv, "HW Revision ID = 0x%X\n", rev_id);
return iwl_read32(priv, CSR_HW_REV);
}
@@ -3294,7 +3381,7 @@
priv->hw_params.max_beacon_itrvl = IWL_MAX_UCODE_BEACON_INTERVAL;
if (iwlagn_mod_params.disable_11n)
- priv->cfg->sku &= ~IWL_SKU_N;
+ priv->cfg->sku &= ~EEPROM_SKU_CAP_11N_ENABLE;
/* Device-specific setup */
return priv->cfg->ops->lib->set_hw_params(priv);
@@ -3344,29 +3431,9 @@
return hw;
}
-static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+static void iwl_init_context(struct iwl_priv *priv)
{
- int err = 0, i;
- struct iwl_priv *priv;
- struct ieee80211_hw *hw;
- struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data);
- unsigned long flags;
- u16 pci_cmd, num_mac;
- u32 hw_rev;
-
- /************************
- * 1. Allocating HW data
- ************************/
-
- hw = iwl_alloc_all(cfg);
- if (!hw) {
- err = -ENOMEM;
- goto out;
- }
- priv = hw->priv;
- /* At this point both hw and priv are allocated. */
-
- priv->ucode_type = UCODE_SUBTYPE_NONE_LOADED;
+ int i;
/*
* The default context is always valid,
@@ -3398,8 +3465,10 @@
priv->contexts[IWL_RXON_CTX_BSS].unused_devtype = RXON_DEV_TYPE_ESS;
priv->contexts[IWL_RXON_CTX_PAN].rxon_cmd = REPLY_WIPAN_RXON;
- priv->contexts[IWL_RXON_CTX_PAN].rxon_timing_cmd = REPLY_WIPAN_RXON_TIMING;
- priv->contexts[IWL_RXON_CTX_PAN].rxon_assoc_cmd = REPLY_WIPAN_RXON_ASSOC;
+ priv->contexts[IWL_RXON_CTX_PAN].rxon_timing_cmd =
+ REPLY_WIPAN_RXON_TIMING;
+ priv->contexts[IWL_RXON_CTX_PAN].rxon_assoc_cmd =
+ REPLY_WIPAN_RXON_ASSOC;
priv->contexts[IWL_RXON_CTX_PAN].qos_cmd = REPLY_WIPAN_QOS_PARAM;
priv->contexts[IWL_RXON_CTX_PAN].ap_sta_id = IWL_AP_ID_PAN;
priv->contexts[IWL_RXON_CTX_PAN].wep_key_cmd = REPLY_WIPAN_WEPKEY;
@@ -3419,12 +3488,41 @@
priv->contexts[IWL_RXON_CTX_PAN].unused_devtype = RXON_DEV_TYPE_P2P;
BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2);
+}
- SET_IEEE80211_DEV(hw, &pdev->dev);
+int iwl_probe(void *bus_specific, struct iwl_bus_ops *bus_ops,
+ struct iwl_cfg *cfg)
+{
+ int err = 0;
+ struct iwl_priv *priv;
+ struct ieee80211_hw *hw;
+ u16 num_mac;
+ u32 hw_rev;
+
+ /************************
+ * 1. Allocating HW data
+ ************************/
+ hw = iwl_alloc_all(cfg);
+ if (!hw) {
+ err = -ENOMEM;
+ goto out;
+ }
+
+ priv = hw->priv;
+
+ priv->bus.priv = priv;
+ priv->bus.bus_specific = bus_specific;
+ priv->bus.ops = bus_ops;
+ priv->bus.irq = priv->bus.ops->get_irq(&priv->bus);
+ priv->bus.ops->set_drv_data(&priv->bus, priv);
+ priv->bus.dev = priv->bus.ops->get_dev(&priv->bus);
+
+ /* At this point both hw and priv are allocated. */
+
+ SET_IEEE80211_DEV(hw, priv->bus.dev);
IWL_DEBUG_INFO(priv, "*** LOAD DRIVER ***\n");
priv->cfg = cfg;
- priv->pci_dev = pdev;
priv->inta_mask = CSR_INI_SET_MASK;
/* is antenna coupling more than 35dB ? */
@@ -3440,52 +3538,6 @@
if (iwl_alloc_traffic_mem(priv))
IWL_ERR(priv, "Not enough memory to generate traffic log\n");
- /**************************
- * 2. Initializing PCI bus
- **************************/
- pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 |
- PCIE_LINK_STATE_CLKPM);
-
- if (pci_enable_device(pdev)) {
- err = -ENODEV;
- goto out_ieee80211_free_hw;
- }
-
- pci_set_master(pdev);
-
- err = pci_set_dma_mask(pdev, DMA_BIT_MASK(36));
- if (!err)
- err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(36));
- if (err) {
- err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
- if (!err)
- err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
- /* both attempts failed: */
- if (err) {
- IWL_WARN(priv, "No suitable DMA available.\n");
- goto out_pci_disable_device;
- }
- }
-
- err = pci_request_regions(pdev, DRV_NAME);
- if (err)
- goto out_pci_disable_device;
-
- pci_set_drvdata(pdev, priv);
-
-
- /***********************
- * 3. Read REV register
- ***********************/
- priv->hw_base = pci_iomap(pdev, 0, 0);
- if (!priv->hw_base) {
- err = -ENODEV;
- goto out_pci_release_regions;
- }
-
- IWL_DEBUG_INFO(priv, "pci_resource_len = 0x%08llx\n",
- (unsigned long long) pci_resource_len(pdev, 0));
- IWL_DEBUG_INFO(priv, "pci_resource_base = %p\n", priv->hw_base);
/* these spin locks will be used in apm_ops.init and EEPROM access
* we should init now
@@ -3500,17 +3552,17 @@
*/
iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET);
+ /***********************
+ * 3. Read REV register
+ ***********************/
hw_rev = iwl_hw_detect(priv);
IWL_INFO(priv, "Detected %s, REV=0x%X\n",
priv->cfg->name, hw_rev);
- /* We disable the RETRY_TIMEOUT register (0x41) to keep
- * PCI Tx retries from interfering with C3 CPU state */
- pci_write_config_byte(pdev, PCI_CFG_RETRY_TIMEOUT, 0x00);
-
if (iwl_prepare_card_hw(priv)) {
+ err = -EIO;
IWL_WARN(priv, "Failed, HW not ready\n");
- goto out_iounmap;
+ goto out_free_traffic_mem;
}
/*****************
@@ -3520,7 +3572,7 @@
err = iwl_eeprom_init(priv, hw_rev);
if (err) {
IWL_ERR(priv, "Unable to init EEPROM\n");
- goto out_iounmap;
+ goto out_free_traffic_mem;
}
err = iwl_eeprom_check_version(priv);
if (err)
@@ -3543,10 +3595,14 @@
priv->hw->wiphy->n_addresses++;
}
+ /* initialize all valid contexts */
+ iwl_init_context(priv);
+
/************************
* 5. Setup HW constants
************************/
if (iwl_set_hw_params(priv)) {
+ err = -ENOENT;
IWL_ERR(priv, "failed to set hw parameters\n");
goto out_free_eeprom;
}
@@ -3563,19 +3619,13 @@
/********************
* 7. Setup services
********************/
- spin_lock_irqsave(&priv->lock, flags);
- iwl_disable_interrupts(priv);
- spin_unlock_irqrestore(&priv->lock, flags);
-
- pci_enable_msi(priv->pci_dev);
-
iwl_alloc_isr_ict(priv);
- err = request_irq(priv->pci_dev->irq, iwl_isr_ict,
- IRQF_SHARED, DRV_NAME, priv);
+ err = request_irq(priv->bus.irq, iwl_isr_ict, IRQF_SHARED,
+ DRV_NAME, priv);
if (err) {
- IWL_ERR(priv, "Error allocating IRQ %d\n", priv->pci_dev->irq);
- goto out_disable_msi;
+ IWL_ERR(priv, "Error allocating IRQ %d\n", priv->bus.irq);
+ goto out_uninit_drv;
}
iwl_setup_deferred_work(priv);
@@ -3583,16 +3633,9 @@
iwl_testmode_init(priv);
/*********************************************
- * 8. Enable interrupts and read RFKILL state
+ * 8. Enable interrupts
*********************************************/
- /* enable rfkill interrupt: hw bug w/a */
- pci_read_config_word(priv->pci_dev, PCI_COMMAND, &pci_cmd);
- if (pci_cmd & PCI_COMMAND_INTX_DISABLE) {
- pci_cmd &= ~PCI_COMMAND_INTX_DISABLE;
- pci_write_config_word(priv->pci_dev, PCI_COMMAND, pci_cmd);
- }
-
iwl_enable_rfkill_int(priv);
/* If platform's RF_KILL switch is NOT set to KILL */
@@ -3618,41 +3661,30 @@
out_destroy_workqueue:
destroy_workqueue(priv->workqueue);
priv->workqueue = NULL;
- free_irq(priv->pci_dev->irq, priv);
+ free_irq(priv->bus.irq, priv);
iwl_free_isr_ict(priv);
- out_disable_msi:
- pci_disable_msi(priv->pci_dev);
+ out_uninit_drv:
iwl_uninit_drv(priv);
out_free_eeprom:
iwl_eeprom_free(priv);
- out_iounmap:
- pci_iounmap(pdev, priv->hw_base);
- out_pci_release_regions:
- pci_set_drvdata(pdev, NULL);
- pci_release_regions(pdev);
- out_pci_disable_device:
- pci_disable_device(pdev);
- out_ieee80211_free_hw:
+ out_free_traffic_mem:
iwl_free_traffic_mem(priv);
ieee80211_free_hw(priv->hw);
out:
return err;
}
-static void __devexit iwl_pci_remove(struct pci_dev *pdev)
+void __devexit iwl_remove(struct iwl_priv * priv)
{
- struct iwl_priv *priv = pci_get_drvdata(pdev);
unsigned long flags;
- if (!priv)
- return;
-
wait_for_completion(&priv->_agn.firmware_loading_complete);
IWL_DEBUG_INFO(priv, "*** UNLOAD DRIVER ***\n");
iwl_dbgfs_unregister(priv);
- sysfs_remove_group(&pdev->dev.kobj, &iwl_attribute_group);
+ sysfs_remove_group(&priv->bus.dev->kobj,
+ &iwl_attribute_group);
/* ieee80211_unregister_hw call wil cause iwl_mac_stop to
* to be called and iwl_down since we are removing the device
@@ -3682,7 +3714,7 @@
iwl_synchronize_irq(priv);
- iwl_dealloc_ucode_pci(priv);
+ iwl_dealloc_ucode(priv);
if (priv->rxq.bd)
iwlagn_rx_queue_free(priv, &priv->rxq);
@@ -3701,12 +3733,8 @@
priv->workqueue = NULL;
iwl_free_traffic_mem(priv);
- free_irq(priv->pci_dev->irq, priv);
- pci_disable_msi(priv->pci_dev);
- pci_iounmap(pdev, priv->hw_base);
- pci_release_regions(pdev);
- pci_disable_device(pdev);
- pci_set_drvdata(pdev, NULL);
+ free_irq(priv->bus.irq, priv);
+ priv->bus.ops->set_drv_data(&priv->bus, NULL);
iwl_uninit_drv(priv);
@@ -3723,206 +3751,6 @@
* driver and module entry point
*
*****************************************************************************/
-
-/* Hardware specific file defines the PCI IDs table for that hardware module */
-static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = {
- {IWL_PCI_DEVICE(0x4232, 0x1201, iwl5100_agn_cfg)}, /* Mini Card */
- {IWL_PCI_DEVICE(0x4232, 0x1301, iwl5100_agn_cfg)}, /* Half Mini Card */
- {IWL_PCI_DEVICE(0x4232, 0x1204, iwl5100_agn_cfg)}, /* Mini Card */
- {IWL_PCI_DEVICE(0x4232, 0x1304, iwl5100_agn_cfg)}, /* Half Mini Card */
- {IWL_PCI_DEVICE(0x4232, 0x1205, iwl5100_bgn_cfg)}, /* Mini Card */
- {IWL_PCI_DEVICE(0x4232, 0x1305, iwl5100_bgn_cfg)}, /* Half Mini Card */
- {IWL_PCI_DEVICE(0x4232, 0x1206, iwl5100_abg_cfg)}, /* Mini Card */
- {IWL_PCI_DEVICE(0x4232, 0x1306, iwl5100_abg_cfg)}, /* Half Mini Card */
- {IWL_PCI_DEVICE(0x4232, 0x1221, iwl5100_agn_cfg)}, /* Mini Card */
- {IWL_PCI_DEVICE(0x4232, 0x1321, iwl5100_agn_cfg)}, /* Half Mini Card */
- {IWL_PCI_DEVICE(0x4232, 0x1224, iwl5100_agn_cfg)}, /* Mini Card */
- {IWL_PCI_DEVICE(0x4232, 0x1324, iwl5100_agn_cfg)}, /* Half Mini Card */
- {IWL_PCI_DEVICE(0x4232, 0x1225, iwl5100_bgn_cfg)}, /* Mini Card */
- {IWL_PCI_DEVICE(0x4232, 0x1325, iwl5100_bgn_cfg)}, /* Half Mini Card */
- {IWL_PCI_DEVICE(0x4232, 0x1226, iwl5100_abg_cfg)}, /* Mini Card */
- {IWL_PCI_DEVICE(0x4232, 0x1326, iwl5100_abg_cfg)}, /* Half Mini Card */
- {IWL_PCI_DEVICE(0x4237, 0x1211, iwl5100_agn_cfg)}, /* Mini Card */
- {IWL_PCI_DEVICE(0x4237, 0x1311, iwl5100_agn_cfg)}, /* Half Mini Card */
- {IWL_PCI_DEVICE(0x4237, 0x1214, iwl5100_agn_cfg)}, /* Mini Card */
- {IWL_PCI_DEVICE(0x4237, 0x1314, iwl5100_agn_cfg)}, /* Half Mini Card */
- {IWL_PCI_DEVICE(0x4237, 0x1215, iwl5100_bgn_cfg)}, /* Mini Card */
- {IWL_PCI_DEVICE(0x4237, 0x1315, iwl5100_bgn_cfg)}, /* Half Mini Card */
- {IWL_PCI_DEVICE(0x4237, 0x1216, iwl5100_abg_cfg)}, /* Mini Card */
- {IWL_PCI_DEVICE(0x4237, 0x1316, iwl5100_abg_cfg)}, /* Half Mini Card */
-
-/* 5300 Series WiFi */
- {IWL_PCI_DEVICE(0x4235, 0x1021, iwl5300_agn_cfg)}, /* Mini Card */
- {IWL_PCI_DEVICE(0x4235, 0x1121, iwl5300_agn_cfg)}, /* Half Mini Card */
- {IWL_PCI_DEVICE(0x4235, 0x1024, iwl5300_agn_cfg)}, /* Mini Card */
- {IWL_PCI_DEVICE(0x4235, 0x1124, iwl5300_agn_cfg)}, /* Half Mini Card */
- {IWL_PCI_DEVICE(0x4235, 0x1001, iwl5300_agn_cfg)}, /* Mini Card */
- {IWL_PCI_DEVICE(0x4235, 0x1101, iwl5300_agn_cfg)}, /* Half Mini Card */
- {IWL_PCI_DEVICE(0x4235, 0x1004, iwl5300_agn_cfg)}, /* Mini Card */
- {IWL_PCI_DEVICE(0x4235, 0x1104, iwl5300_agn_cfg)}, /* Half Mini Card */
- {IWL_PCI_DEVICE(0x4236, 0x1011, iwl5300_agn_cfg)}, /* Mini Card */
- {IWL_PCI_DEVICE(0x4236, 0x1111, iwl5300_agn_cfg)}, /* Half Mini Card */
- {IWL_PCI_DEVICE(0x4236, 0x1014, iwl5300_agn_cfg)}, /* Mini Card */
- {IWL_PCI_DEVICE(0x4236, 0x1114, iwl5300_agn_cfg)}, /* Half Mini Card */
-
-/* 5350 Series WiFi/WiMax */
- {IWL_PCI_DEVICE(0x423A, 0x1001, iwl5350_agn_cfg)}, /* Mini Card */
- {IWL_PCI_DEVICE(0x423A, 0x1021, iwl5350_agn_cfg)}, /* Mini Card */
- {IWL_PCI_DEVICE(0x423B, 0x1011, iwl5350_agn_cfg)}, /* Mini Card */
-
-/* 5150 Series Wifi/WiMax */
- {IWL_PCI_DEVICE(0x423C, 0x1201, iwl5150_agn_cfg)}, /* Mini Card */
- {IWL_PCI_DEVICE(0x423C, 0x1301, iwl5150_agn_cfg)}, /* Half Mini Card */
- {IWL_PCI_DEVICE(0x423C, 0x1206, iwl5150_abg_cfg)}, /* Mini Card */
- {IWL_PCI_DEVICE(0x423C, 0x1306, iwl5150_abg_cfg)}, /* Half Mini Card */
- {IWL_PCI_DEVICE(0x423C, 0x1221, iwl5150_agn_cfg)}, /* Mini Card */
- {IWL_PCI_DEVICE(0x423C, 0x1321, iwl5150_agn_cfg)}, /* Half Mini Card */
-
- {IWL_PCI_DEVICE(0x423D, 0x1211, iwl5150_agn_cfg)}, /* Mini Card */
- {IWL_PCI_DEVICE(0x423D, 0x1311, iwl5150_agn_cfg)}, /* Half Mini Card */
- {IWL_PCI_DEVICE(0x423D, 0x1216, iwl5150_abg_cfg)}, /* Mini Card */
- {IWL_PCI_DEVICE(0x423D, 0x1316, iwl5150_abg_cfg)}, /* Half Mini Card */
-
-/* 6x00 Series */
- {IWL_PCI_DEVICE(0x422B, 0x1101, iwl6000_3agn_cfg)},
- {IWL_PCI_DEVICE(0x422B, 0x1121, iwl6000_3agn_cfg)},
- {IWL_PCI_DEVICE(0x422C, 0x1301, iwl6000i_2agn_cfg)},
- {IWL_PCI_DEVICE(0x422C, 0x1306, iwl6000i_2abg_cfg)},
- {IWL_PCI_DEVICE(0x422C, 0x1307, iwl6000i_2bg_cfg)},
- {IWL_PCI_DEVICE(0x422C, 0x1321, iwl6000i_2agn_cfg)},
- {IWL_PCI_DEVICE(0x422C, 0x1326, iwl6000i_2abg_cfg)},
- {IWL_PCI_DEVICE(0x4238, 0x1111, iwl6000_3agn_cfg)},
- {IWL_PCI_DEVICE(0x4239, 0x1311, iwl6000i_2agn_cfg)},
- {IWL_PCI_DEVICE(0x4239, 0x1316, iwl6000i_2abg_cfg)},
-
-/* 6x05 Series */
- {IWL_PCI_DEVICE(0x0082, 0x1301, iwl6005_2agn_cfg)},
- {IWL_PCI_DEVICE(0x0082, 0x1306, iwl6005_2abg_cfg)},
- {IWL_PCI_DEVICE(0x0082, 0x1307, iwl6005_2bg_cfg)},
- {IWL_PCI_DEVICE(0x0082, 0x1321, iwl6005_2agn_cfg)},
- {IWL_PCI_DEVICE(0x0082, 0x1326, iwl6005_2abg_cfg)},
- {IWL_PCI_DEVICE(0x0085, 0x1311, iwl6005_2agn_cfg)},
- {IWL_PCI_DEVICE(0x0085, 0x1316, iwl6005_2abg_cfg)},
-
-/* 6x30 Series */
- {IWL_PCI_DEVICE(0x008A, 0x5305, iwl1030_bgn_cfg)},
- {IWL_PCI_DEVICE(0x008A, 0x5307, iwl1030_bg_cfg)},
- {IWL_PCI_DEVICE(0x008A, 0x5325, iwl1030_bgn_cfg)},
- {IWL_PCI_DEVICE(0x008A, 0x5327, iwl1030_bg_cfg)},
- {IWL_PCI_DEVICE(0x008B, 0x5315, iwl1030_bgn_cfg)},
- {IWL_PCI_DEVICE(0x008B, 0x5317, iwl1030_bg_cfg)},
- {IWL_PCI_DEVICE(0x0090, 0x5211, iwl6030_2agn_cfg)},
- {IWL_PCI_DEVICE(0x0090, 0x5215, iwl6030_2bgn_cfg)},
- {IWL_PCI_DEVICE(0x0090, 0x5216, iwl6030_2abg_cfg)},
- {IWL_PCI_DEVICE(0x0091, 0x5201, iwl6030_2agn_cfg)},
- {IWL_PCI_DEVICE(0x0091, 0x5205, iwl6030_2bgn_cfg)},
- {IWL_PCI_DEVICE(0x0091, 0x5206, iwl6030_2abg_cfg)},
- {IWL_PCI_DEVICE(0x0091, 0x5207, iwl6030_2bg_cfg)},
- {IWL_PCI_DEVICE(0x0091, 0x5221, iwl6030_2agn_cfg)},
- {IWL_PCI_DEVICE(0x0091, 0x5225, iwl6030_2bgn_cfg)},
- {IWL_PCI_DEVICE(0x0091, 0x5226, iwl6030_2abg_cfg)},
-
-/* 6x50 WiFi/WiMax Series */
- {IWL_PCI_DEVICE(0x0087, 0x1301, iwl6050_2agn_cfg)},
- {IWL_PCI_DEVICE(0x0087, 0x1306, iwl6050_2abg_cfg)},
- {IWL_PCI_DEVICE(0x0087, 0x1321, iwl6050_2agn_cfg)},
- {IWL_PCI_DEVICE(0x0087, 0x1326, iwl6050_2abg_cfg)},
- {IWL_PCI_DEVICE(0x0089, 0x1311, iwl6050_2agn_cfg)},
- {IWL_PCI_DEVICE(0x0089, 0x1316, iwl6050_2abg_cfg)},
-
-/* 6150 WiFi/WiMax Series */
- {IWL_PCI_DEVICE(0x0885, 0x1305, iwl6150_bgn_cfg)},
- {IWL_PCI_DEVICE(0x0885, 0x1307, iwl6150_bg_cfg)},
- {IWL_PCI_DEVICE(0x0885, 0x1325, iwl6150_bgn_cfg)},
- {IWL_PCI_DEVICE(0x0885, 0x1327, iwl6150_bg_cfg)},
- {IWL_PCI_DEVICE(0x0886, 0x1315, iwl6150_bgn_cfg)},
- {IWL_PCI_DEVICE(0x0886, 0x1317, iwl6150_bg_cfg)},
-
-/* 1000 Series WiFi */
- {IWL_PCI_DEVICE(0x0083, 0x1205, iwl1000_bgn_cfg)},
- {IWL_PCI_DEVICE(0x0083, 0x1305, iwl1000_bgn_cfg)},
- {IWL_PCI_DEVICE(0x0083, 0x1225, iwl1000_bgn_cfg)},
- {IWL_PCI_DEVICE(0x0083, 0x1325, iwl1000_bgn_cfg)},
- {IWL_PCI_DEVICE(0x0084, 0x1215, iwl1000_bgn_cfg)},
- {IWL_PCI_DEVICE(0x0084, 0x1315, iwl1000_bgn_cfg)},
- {IWL_PCI_DEVICE(0x0083, 0x1206, iwl1000_bg_cfg)},
- {IWL_PCI_DEVICE(0x0083, 0x1306, iwl1000_bg_cfg)},
- {IWL_PCI_DEVICE(0x0083, 0x1226, iwl1000_bg_cfg)},
- {IWL_PCI_DEVICE(0x0083, 0x1326, iwl1000_bg_cfg)},
- {IWL_PCI_DEVICE(0x0084, 0x1216, iwl1000_bg_cfg)},
- {IWL_PCI_DEVICE(0x0084, 0x1316, iwl1000_bg_cfg)},
-
-/* 100 Series WiFi */
- {IWL_PCI_DEVICE(0x08AE, 0x1005, iwl100_bgn_cfg)},
- {IWL_PCI_DEVICE(0x08AE, 0x1007, iwl100_bg_cfg)},
- {IWL_PCI_DEVICE(0x08AF, 0x1015, iwl100_bgn_cfg)},
- {IWL_PCI_DEVICE(0x08AF, 0x1017, iwl100_bg_cfg)},
- {IWL_PCI_DEVICE(0x08AE, 0x1025, iwl100_bgn_cfg)},
- {IWL_PCI_DEVICE(0x08AE, 0x1027, iwl100_bg_cfg)},
-
-/* 130 Series WiFi */
- {IWL_PCI_DEVICE(0x0896, 0x5005, iwl130_bgn_cfg)},
- {IWL_PCI_DEVICE(0x0896, 0x5007, iwl130_bg_cfg)},
- {IWL_PCI_DEVICE(0x0897, 0x5015, iwl130_bgn_cfg)},
- {IWL_PCI_DEVICE(0x0897, 0x5017, iwl130_bg_cfg)},
- {IWL_PCI_DEVICE(0x0896, 0x5025, iwl130_bgn_cfg)},
- {IWL_PCI_DEVICE(0x0896, 0x5027, iwl130_bg_cfg)},
-
-/* 2x00 Series */
- {IWL_PCI_DEVICE(0x0890, 0x4022, iwl2000_2bgn_cfg)},
- {IWL_PCI_DEVICE(0x0891, 0x4222, iwl2000_2bgn_cfg)},
- {IWL_PCI_DEVICE(0x0890, 0x4422, iwl2000_2bgn_cfg)},
- {IWL_PCI_DEVICE(0x0890, 0x4026, iwl2000_2bg_cfg)},
- {IWL_PCI_DEVICE(0x0891, 0x4226, iwl2000_2bg_cfg)},
- {IWL_PCI_DEVICE(0x0890, 0x4426, iwl2000_2bg_cfg)},
-
-/* 2x30 Series */
- {IWL_PCI_DEVICE(0x0887, 0x4062, iwl2030_2bgn_cfg)},
- {IWL_PCI_DEVICE(0x0888, 0x4262, iwl2030_2bgn_cfg)},
- {IWL_PCI_DEVICE(0x0887, 0x4462, iwl2030_2bgn_cfg)},
- {IWL_PCI_DEVICE(0x0887, 0x4066, iwl2030_2bg_cfg)},
- {IWL_PCI_DEVICE(0x0888, 0x4266, iwl2030_2bg_cfg)},
- {IWL_PCI_DEVICE(0x0887, 0x4466, iwl2030_2bg_cfg)},
-
-/* 6x35 Series */
- {IWL_PCI_DEVICE(0x088E, 0x4060, iwl6035_2agn_cfg)},
- {IWL_PCI_DEVICE(0x088F, 0x4260, iwl6035_2agn_cfg)},
- {IWL_PCI_DEVICE(0x088E, 0x4460, iwl6035_2agn_cfg)},
- {IWL_PCI_DEVICE(0x088E, 0x4064, iwl6035_2abg_cfg)},
- {IWL_PCI_DEVICE(0x088F, 0x4264, iwl6035_2abg_cfg)},
- {IWL_PCI_DEVICE(0x088E, 0x4464, iwl6035_2abg_cfg)},
- {IWL_PCI_DEVICE(0x088E, 0x4066, iwl6035_2bg_cfg)},
- {IWL_PCI_DEVICE(0x088F, 0x4266, iwl6035_2bg_cfg)},
- {IWL_PCI_DEVICE(0x088E, 0x4466, iwl6035_2bg_cfg)},
-
-/* 105 Series */
- {IWL_PCI_DEVICE(0x0894, 0x0022, iwl105_bgn_cfg)},
- {IWL_PCI_DEVICE(0x0895, 0x0222, iwl105_bgn_cfg)},
- {IWL_PCI_DEVICE(0x0894, 0x0422, iwl105_bgn_cfg)},
- {IWL_PCI_DEVICE(0x0894, 0x0026, iwl105_bg_cfg)},
- {IWL_PCI_DEVICE(0x0895, 0x0226, iwl105_bg_cfg)},
- {IWL_PCI_DEVICE(0x0894, 0x0426, iwl105_bg_cfg)},
-
-/* 135 Series */
- {IWL_PCI_DEVICE(0x0892, 0x0062, iwl135_bgn_cfg)},
- {IWL_PCI_DEVICE(0x0893, 0x0262, iwl135_bgn_cfg)},
- {IWL_PCI_DEVICE(0x0892, 0x0462, iwl135_bgn_cfg)},
- {IWL_PCI_DEVICE(0x0892, 0x0066, iwl135_bg_cfg)},
- {IWL_PCI_DEVICE(0x0893, 0x0266, iwl135_bg_cfg)},
- {IWL_PCI_DEVICE(0x0892, 0x0466, iwl135_bg_cfg)},
-
- {0}
-};
-MODULE_DEVICE_TABLE(pci, iwl_hw_card_ids);
-
-static struct pci_driver iwl_driver = {
- .name = DRV_NAME,
- .id_table = iwl_hw_card_ids,
- .probe = iwl_pci_probe,
- .remove = __devexit_p(iwl_pci_remove),
- .driver.pm = IWL_PM_OPS,
-};
-
static int __init iwl_init(void)
{
@@ -3936,12 +3764,10 @@
return ret;
}
- ret = pci_register_driver(&iwl_driver);
- if (ret) {
- pr_err("Unable to initialize PCI module\n");
- goto error_register;
- }
+ ret = iwl_pci_register_driver();
+ if (ret)
+ goto error_register;
return ret;
error_register:
@@ -3951,7 +3777,7 @@
static void __exit iwl_exit(void)
{
- pci_unregister_driver(&iwl_driver);
+ iwl_pci_unregister_driver();
iwlagn_rate_control_unregister();
}
@@ -3993,3 +3819,47 @@
module_param_named(ack_check, iwlagn_mod_params.ack_check, bool, S_IRUGO);
MODULE_PARM_DESC(ack_check, "Check ack health (default: 0 [disabled])");
+
+/*
+ * set bt_coex_active to true, uCode will do kill/defer
+ * every time the priority line is asserted (BT is sending signals on the
+ * priority line in the PCIx).
+ * set bt_coex_active to false, uCode will ignore the BT activity and
+ * perform the normal operation
+ *
+ * User might experience transmit issue on some platform due to WiFi/BT
+ * co-exist problem. The possible behaviors are:
+ * Able to scan and finding all the available AP
+ * Not able to associate with any AP
+ * On those platforms, WiFi communication can be restored by set
+ * "bt_coex_active" module parameter to "false"
+ *
+ * default: bt_coex_active = true (BT_COEX_ENABLE)
+ */
+module_param_named(bt_coex_active, iwlagn_mod_params.bt_coex_active,
+ bool, S_IRUGO);
+MODULE_PARM_DESC(bt_coex_active, "enable wifi/bt co-exist (default: enable)");
+
+module_param_named(led_mode, iwlagn_mod_params.led_mode, int, S_IRUGO);
+MODULE_PARM_DESC(led_mode, "0=system default, "
+ "1=On(RF On)/Off(RF Off), 2=blinking (default: 0)");
+
+module_param_named(power_save, iwlagn_mod_params.power_save,
+ bool, S_IRUGO);
+MODULE_PARM_DESC(power_save,
+ "enable WiFi power management (default: disable)");
+
+module_param_named(power_level, iwlagn_mod_params.power_level,
+ int, S_IRUGO);
+MODULE_PARM_DESC(power_level,
+ "default power save level (range from 1 - 5, default: 1)");
+
+/*
+ * For now, keep using power level 1 instead of automatically
+ * adjusting ...
+ */
+module_param_named(no_sleep_autoadjust, iwlagn_mod_params.no_sleep_autoadjust,
+ bool, S_IRUGO);
+MODULE_PARM_DESC(no_sleep_autoadjust,
+ "don't automatically adjust sleep level "
+ "according to maximum network latency (default: true)");
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h
index d171684..dcdf225 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.h
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.h
@@ -125,10 +125,18 @@
static inline void iwl_synchronize_irq(struct iwl_priv *priv)
{
/* wait to make sure we flush pending tasklet*/
- synchronize_irq(priv->pci_dev->irq);
+ synchronize_irq(priv->bus.irq);
tasklet_kill(&priv->irq_tasklet);
}
+static inline void iwl_set_calib_hdr(struct iwl_calib_hdr *hdr, u8 cmd)
+{
+ hdr->op_code = cmd;
+ hdr->first_group = 0;
+ hdr->groups_num = 1;
+ hdr->data_valid = 1;
+}
+
int iwl_prepare_card_hw(struct iwl_priv *priv);
int iwlagn_start_device(struct iwl_priv *priv);
@@ -161,7 +169,7 @@
int iwlagn_run_init_ucode(struct iwl_priv *priv);
int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv,
struct fw_img *image,
- int subtype, int alternate_subtype);
+ enum iwlagn_ucode_type ucode_type);
/* lib */
void iwl_check_abort_status(struct iwl_priv *priv,
@@ -296,6 +304,8 @@
int iwl_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta,
int tid);
void iwl_sta_modify_sleep_tx_count(struct iwl_priv *priv, int sta_id, int cnt);
+int iwl_update_bcast_station(struct iwl_priv *priv,
+ struct iwl_rxon_context *ctx);
int iwl_update_bcast_stations(struct iwl_priv *priv);
void iwlagn_mac_sta_notify(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
@@ -343,6 +353,9 @@
/* svtool */
#ifdef CONFIG_IWLWIFI_DEVICE_SVTOOL
extern int iwl_testmode_cmd(struct ieee80211_hw *hw, void *data, int len);
+extern int iwl_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *skb,
+ struct netlink_callback *cb,
+ void *data, int len);
extern void iwl_testmode_init(struct iwl_priv *priv);
extern void iwl_testmode_cleanup(struct iwl_priv *priv);
#else
@@ -352,6 +365,13 @@
return -ENOSYS;
}
static inline
+int iwl_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *skb,
+ struct netlink_callback *cb,
+ void *data, int len)
+{
+ return -ENOSYS;
+}
+static inline
void iwl_testmode_init(struct iwl_priv *priv)
{
}
@@ -361,4 +381,8 @@
}
#endif
+int iwl_probe(void *bus_specific, struct iwl_bus_ops *bus_ops,
+ struct iwl_cfg *cfg);
+void __devexit iwl_remove(struct iwl_priv * priv);
+
#endif /* __iwl_agn_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h
index 6ee5f1a..8a2edf8 100644
--- a/drivers/net/wireless/iwlwifi/iwl-commands.h
+++ b/drivers/net/wireless/iwlwifi/iwl-commands.h
@@ -384,18 +384,6 @@
#define UCODE_VALID_OK cpu_to_le32(0x1)
-enum iwlagn_ucode_subtype {
- UCODE_SUBTYPE_REGULAR = 0,
- UCODE_SUBTYPE_REGULAR_NEW = 1,
- UCODE_SUBTYPE_INIT = 9,
-
- /*
- * Not a valid subtype, the ucode has just a u8, so
- * we can use something > 0xff for this value.
- */
- UCODE_SUBTYPE_NONE_LOADED = 0x100,
-};
-
/**
* REPLY_ALIVE = 0x1 (response only, not a command)
*
@@ -984,15 +972,26 @@
u8 reserved2[2];
} __packed;
-#define IWL_TX_FIFO_BK_MSK cpu_to_le32(BIT(0))
-#define IWL_TX_FIFO_BE_MSK cpu_to_le32(BIT(1))
-#define IWL_TX_FIFO_VI_MSK cpu_to_le32(BIT(2))
-#define IWL_TX_FIFO_VO_MSK cpu_to_le32(BIT(3))
+
+/* WiFi queues mask */
+#define IWL_SCD_BK_MSK cpu_to_le32(BIT(0))
+#define IWL_SCD_BE_MSK cpu_to_le32(BIT(1))
+#define IWL_SCD_VI_MSK cpu_to_le32(BIT(2))
+#define IWL_SCD_VO_MSK cpu_to_le32(BIT(3))
+#define IWL_SCD_MGMT_MSK cpu_to_le32(BIT(3))
+
+/* PAN queues mask */
+#define IWL_PAN_SCD_BK_MSK cpu_to_le32(BIT(4))
+#define IWL_PAN_SCD_BE_MSK cpu_to_le32(BIT(5))
+#define IWL_PAN_SCD_VI_MSK cpu_to_le32(BIT(6))
+#define IWL_PAN_SCD_VO_MSK cpu_to_le32(BIT(7))
+#define IWL_PAN_SCD_MGMT_MSK cpu_to_le32(BIT(7))
+#define IWL_PAN_SCD_MULTICAST_MSK cpu_to_le32(BIT(8))
+
#define IWL_AGG_TX_QUEUE_MSK cpu_to_le32(0xffc00)
#define IWL_DROP_SINGLE 0
-#define IWL_DROP_SELECTED 1
-#define IWL_DROP_ALL 2
+#define IWL_DROP_ALL (BIT(IWL_RXON_CTX_BSS) | BIT(IWL_RXON_CTX_PAN))
/*
* REPLY_TXFIFO_FLUSH = 0x1e(command and response)
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index 45cc51c..7f16d12 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -43,27 +43,6 @@
#include "iwl-helpers.h"
#include "iwl-agn.h"
-
-/*
- * set bt_coex_active to true, uCode will do kill/defer
- * every time the priority line is asserted (BT is sending signals on the
- * priority line in the PCIx).
- * set bt_coex_active to false, uCode will ignore the BT activity and
- * perform the normal operation
- *
- * User might experience transmit issue on some platform due to WiFi/BT
- * co-exist problem. The possible behaviors are:
- * Able to scan and finding all the available AP
- * Not able to associate with any AP
- * On those platforms, WiFi communication can be restored by set
- * "bt_coex_active" module parameter to "false"
- *
- * default: bt_coex_active = true (BT_COEX_ENABLE)
- */
-bool bt_coex_active = true;
-module_param(bt_coex_active, bool, S_IRUGO);
-MODULE_PARM_DESC(bt_coex_active, "enable wifi/bluetooth co-exist");
-
u32 iwl_debug_level;
const u8 iwl_bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
@@ -164,7 +143,7 @@
sband->bitrates = &rates[IWL_FIRST_OFDM_RATE];
sband->n_bitrates = IWL_RATE_COUNT_LEGACY - IWL_FIRST_OFDM_RATE;
- if (priv->cfg->sku & IWL_SKU_N)
+ if (priv->cfg->sku & EEPROM_SKU_CAP_11N_ENABLE)
iwlcore_init_ht_hw_capab(priv, &sband->ht_cap,
IEEE80211_BAND_5GHZ);
@@ -174,7 +153,7 @@
sband->bitrates = rates;
sband->n_bitrates = IWL_RATE_COUNT_LEGACY;
- if (priv->cfg->sku & IWL_SKU_N)
+ if (priv->cfg->sku & EEPROM_SKU_CAP_11N_ENABLE)
iwlcore_init_ht_hw_capab(priv, &sband->ht_cap,
IEEE80211_BAND_2GHZ);
@@ -229,12 +208,12 @@
priv->tx_power_next = max_tx_power;
if ((priv->bands[IEEE80211_BAND_5GHZ].n_channels == 0) &&
- priv->cfg->sku & IWL_SKU_A) {
+ priv->cfg->sku & EEPROM_SKU_CAP_BAND_52GHZ) {
+ char buf[32];
+ priv->bus.ops->get_hw_id(&priv->bus, buf, sizeof(buf));
IWL_INFO(priv, "Incorrectly detected BG card as ABG. "
- "Please send your PCI ID 0x%04X:0x%04X to maintainer.\n",
- priv->pci_dev->device,
- priv->pci_dev->subsystem_device);
- priv->cfg->sku &= ~IWL_SKU_A;
+ "Please send your %s to maintainer.\n", buf);
+ priv->cfg->sku &= ~EEPROM_SKU_CAP_BAND_52GHZ;
}
IWL_INFO(priv, "Tunable channels: %d 802.11bg, %d 802.11a channels\n",
@@ -547,19 +526,6 @@
return 0;
}
-u8 iwl_rate_get_lowest_plcp(struct iwl_priv *priv,
- struct iwl_rxon_context *ctx)
-{
- /*
- * Assign the lowest rate -- should really get this from
- * the beacon skb from mac80211.
- */
- if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK)
- return IWL_RATE_1M_PLCP;
- else
- return IWL_RATE_6M_PLCP;
-}
-
static void _iwl_set_rxon_ht(struct iwl_priv *priv,
struct iwl_ht_config *ht_conf,
struct iwl_rxon_context *ctx)
@@ -1018,8 +984,6 @@
int iwl_apm_init(struct iwl_priv *priv)
{
int ret = 0;
- u16 lctl;
-
IWL_DEBUG_INFO(priv, "Init card's basic functions\n");
/*
@@ -1048,27 +1012,7 @@
iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
CSR_HW_IF_CONFIG_REG_BIT_HAP_WAKE_L1A);
- /*
- * HW bug W/A for instability in PCIe bus L0->L0S->L1 transition.
- * Check if BIOS (or OS) enabled L1-ASPM on this device.
- * If so (likely), disable L0S, so device moves directly L0->L1;
- * costs negligible amount of power savings.
- * If not (unlikely), enable L0S, so there is at least some
- * power savings, even without L1.
- */
- lctl = iwl_pcie_link_ctl(priv);
- if ((lctl & PCI_CFG_LINK_CTRL_VAL_L1_EN) ==
- PCI_CFG_LINK_CTRL_VAL_L1_EN) {
- /* L1-ASPM enabled; disable(!) L0S */
- iwl_set_bit(priv, CSR_GIO_REG,
- CSR_GIO_REG_VAL_L0S_ENABLED);
- IWL_DEBUG_POWER(priv, "L1 Enabled; Disabling L0S\n");
- } else {
- /* L1-ASPM disabled; enable(!) L0S */
- iwl_clear_bit(priv, CSR_GIO_REG,
- CSR_GIO_REG_VAL_L0S_ENABLED);
- IWL_DEBUG_POWER(priv, "L1 Disabled; Enabling L0S\n");
- }
+ priv->bus.ops->apm_config(&priv->bus);
/* Configure analog phase-lock-loop before activating to D0A */
if (priv->cfg->base_params->pll_cfg_val)
@@ -1127,9 +1071,6 @@
if (priv->tx_power_user_lmt == tx_power && !force)
return 0;
- if (!priv->cfg->ops->lib->send_tx_power)
- return -EOPNOTSUPP;
-
if (tx_power < IWLAGN_TX_POWER_TARGET_POWER_MIN) {
IWL_WARN(priv,
"Requested user TXPOWER %d below lower limit %d.\n",
@@ -1163,7 +1104,7 @@
prev_tx_power = priv->tx_power_user_lmt;
priv->tx_power_user_lmt = tx_power;
- ret = priv->cfg->ops->lib->send_tx_power(priv);
+ ret = iwlagn_send_tx_power(priv);
/* if fail to set tx_power, restore the orig. tx power */
if (ret) {
@@ -1182,7 +1123,7 @@
.kill_cts_mask = 0,
};
- if (!bt_coex_active)
+ if (!iwlagn_mod_params.bt_coex_active)
bt_cmd.flags = BT_COEX_DISABLE;
else
bt_cmd.flags = BT_COEX_ENABLE;
@@ -1278,7 +1219,7 @@
if (priv->cfg->ops->hcmd->set_rxon_chain)
priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
- return iwlcore_commit_rxon(priv, ctx);
+ return iwlagn_commit_rxon(priv, ctx);
}
static int iwl_setup_interface(struct iwl_priv *priv,
@@ -1973,11 +1914,8 @@
#ifdef CONFIG_PM
-int iwl_pci_suspend(struct device *device)
+int iwl_suspend(struct iwl_priv *priv)
{
- struct pci_dev *pdev = to_pci_dev(device);
- struct iwl_priv *priv = pci_get_drvdata(pdev);
-
/*
* This function is called when system goes into suspend state
* mac80211 will call iwl_mac_stop() from the mac80211 suspend function
@@ -1990,18 +1928,10 @@
return 0;
}
-int iwl_pci_resume(struct device *device)
+int iwl_resume(struct iwl_priv *priv)
{
- struct pci_dev *pdev = to_pci_dev(device);
- struct iwl_priv *priv = pci_get_drvdata(pdev);
bool hw_rfkill = false;
- /*
- * We disable the RETRY_TIMEOUT register (0x41) to keep
- * PCI Tx retries from interfering with C3 CPU state.
- */
- pci_write_config_byte(pdev, PCI_CFG_RETRY_TIMEOUT, 0x00);
-
iwl_enable_interrupts(priv);
if (!(iwl_read32(priv, CSR_GP_CNTRL) &
@@ -2018,13 +1948,4 @@
return 0;
}
-const struct dev_pm_ops iwl_pm_ops = {
- .suspend = iwl_pci_suspend,
- .resume = iwl_pci_resume,
- .freeze = iwl_pci_suspend,
- .thaw = iwl_pci_resume,
- .poweroff = iwl_pci_suspend,
- .restore = iwl_pci_resume,
-};
-
#endif /* CONFIG_PM */
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index a54d416..f881678 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -76,21 +76,11 @@
#define DRV_COPYRIGHT "Copyright(c) 2003-2011 Intel Corporation"
#define DRV_AUTHOR "<ilw@linux.intel.com>"
-#define IWL_PCI_DEVICE(dev, subdev, cfg) \
- .vendor = PCI_VENDOR_ID_INTEL, .device = (dev), \
- .subvendor = PCI_ANY_ID, .subdevice = (subdev), \
- .driver_data = (kernel_ulong_t)&(cfg)
-
#define TIME_UNIT 1024
-#define IWL_SKU_G 0x1
-#define IWL_SKU_A 0x2
-#define IWL_SKU_N 0x8
-
#define IWL_CMD(x) case x: return #x
struct iwl_hcmd_ops {
- int (*commit_rxon)(struct iwl_priv *priv, struct iwl_rxon_context *ctx);
void (*set_rxon_chain)(struct iwl_priv *priv,
struct iwl_rxon_context *ctx);
int (*set_tx_ant)(struct iwl_priv *priv, u8 valid_tx_ant);
@@ -112,7 +102,6 @@
int (*calc_rssi)(struct iwl_priv *priv,
struct iwl_rx_phy_res *rx_resp);
int (*request_scan)(struct iwl_priv *priv, struct ieee80211_vif *vif);
- void (*post_scan)(struct iwl_priv *priv);
};
struct iwl_apm_ops {
@@ -141,7 +130,6 @@
struct iwl_apm_ops apm_ops;
/* power */
- int (*send_tx_power) (struct iwl_priv *priv);
void (*update_chain_flags)(struct iwl_priv *priv);
/* eeprom operations (as defined in iwl-eeprom.h) */
@@ -149,10 +137,6 @@
/* temperature */
struct iwl_temp_ops temp_ops;
-
- int (*txfifo_flush)(struct iwl_priv *priv, u16 flush_control);
- void (*dev_txfifo_flush)(struct iwl_priv *priv, u16 flush_control);
-
};
/* NIC specific ops */
@@ -176,6 +160,11 @@
int restart_fw; /* def: 1 = restart firmware */
bool plcp_check; /* def: true = enable plcp health check */
bool ack_check; /* def: false = disable ack health check */
+ bool bt_coex_active; /* def: true = enable bt coex */
+ int led_mode; /* def: 0 = system default */
+ bool no_sleep_autoadjust; /* def: true = disable autoadjust */
+ bool power_save; /* def: false = disable power save */
+ int power_level; /* def: 1 = power level */
};
/*
@@ -225,7 +214,7 @@
* @ampdu_factor: Maximum A-MPDU length factor
* @ampdu_density: Minimum A-MPDU spacing
* @bt_sco_disable: uCode should not response to BT in SCO/ESCO mode
-*/
+ */
struct iwl_bt_params {
bool advanced_bt_coexist;
u8 bt_init_traffic_load;
@@ -238,10 +227,11 @@
};
/*
* @use_rts_for_aggregation: use rts/cts protection for HT traffic
-*/
+ */
struct iwl_ht_params {
const bool ht_greenfield_support; /* if used set to true */
bool use_rts_for_aggregation;
+ enum ieee80211_smps_mode smps_mode;
};
/**
@@ -291,7 +281,7 @@
const unsigned int ucode_api_min;
u8 valid_tx_ant;
u8 valid_rx_ant;
- unsigned int sku;
+ u16 sku;
u16 eeprom_ver;
u16 eeprom_calib_ver;
const struct iwl_ops *ops;
@@ -419,13 +409,6 @@
int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force);
/*******************************************************************************
- * Rate
- ******************************************************************************/
-
-u8 iwl_rate_get_lowest_plcp(struct iwl_priv *priv,
- struct iwl_rxon_context *ctx);
-
-/*******************************************************************************
* Scanning
******************************************************************************/
void iwl_init_scan_params(struct iwl_priv *priv);
@@ -482,36 +465,14 @@
int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd);
-
-/*****************************************************
- * PCI *
- *****************************************************/
-
-static inline u16 iwl_pcie_link_ctl(struct iwl_priv *priv)
-{
- int pos;
- u16 pci_lnk_ctl;
- pos = pci_find_capability(priv->pci_dev, PCI_CAP_ID_EXP);
- pci_read_config_word(priv->pci_dev, pos + PCI_EXP_LNKCTL, &pci_lnk_ctl);
- return pci_lnk_ctl;
-}
-
void iwl_bg_watchdog(unsigned long data);
u32 iwl_usecs_to_beacons(struct iwl_priv *priv, u32 usec, u32 beacon_interval);
__le32 iwl_add_beacon_time(struct iwl_priv *priv, u32 base,
u32 addon, u32 beacon_interval);
#ifdef CONFIG_PM
-int iwl_pci_suspend(struct device *device);
-int iwl_pci_resume(struct device *device);
-extern const struct dev_pm_ops iwl_pm_ops;
-
-#define IWL_PM_OPS (&iwl_pm_ops)
-
-#else /* !CONFIG_PM */
-
-#define IWL_PM_OPS NULL
-
+int iwl_suspend(struct iwl_priv *priv);
+int iwl_resume(struct iwl_priv *priv);
#endif /* !CONFIG_PM */
/*****************************************************
@@ -613,11 +574,7 @@
int iwl_apm_init(struct iwl_priv *priv);
int iwl_send_rxon_timing(struct iwl_priv *priv, struct iwl_rxon_context *ctx);
-static inline int iwlcore_commit_rxon(struct iwl_priv *priv,
- struct iwl_rxon_context *ctx)
-{
- return priv->cfg->ops->hcmd->commit_rxon(priv, ctx);
-}
+
static inline const struct ieee80211_supported_band *iwl_get_hw_mode(
struct iwl_priv *priv, enum ieee80211_band band)
{
@@ -630,7 +587,6 @@
priv->cfg->bt_params->advanced_bt_coexist;
}
-extern bool bt_coex_active;
extern bool bt_siso_mode;
diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h
index 2824ccb..eb95d1a 100644
--- a/drivers/net/wireless/iwlwifi/iwl-debug.h
+++ b/drivers/net/wireless/iwlwifi/iwl-debug.h
@@ -32,10 +32,10 @@
struct iwl_priv;
extern u32 iwl_debug_level;
-#define IWL_ERR(p, f, a...) dev_err(&((p)->pci_dev->dev), f, ## a)
-#define IWL_WARN(p, f, a...) dev_warn(&((p)->pci_dev->dev), f, ## a)
-#define IWL_INFO(p, f, a...) dev_info(&((p)->pci_dev->dev), f, ## a)
-#define IWL_CRIT(p, f, a...) dev_crit(&((p)->pci_dev->dev), f, ## a)
+#define IWL_ERR(p, f, a...) dev_err(p->bus.ops->get_dev(&p->bus), f, ## a)
+#define IWL_WARN(p, f, a...) dev_warn(p->bus.ops->get_dev(&p->bus), f, ## a)
+#define IWL_INFO(p, f, a...) dev_info(p->bus.ops->get_dev(&p->bus), f, ## a)
+#define IWL_CRIT(p, f, a...) dev_crit(p->bus.ops->get_dev(&p->bus), f, ## a)
#define iwl_print_hex_error(priv, p, len) \
do { \
@@ -125,13 +125,13 @@
/* 0x00000F00 - 0x00000100 */
#define IWL_DL_POWER (1 << 8)
#define IWL_DL_TEMP (1 << 9)
-#define IWL_DL_NOTIF (1 << 10)
+/* reserved (1 << 10) */
#define IWL_DL_SCAN (1 << 11)
/* 0x0000F000 - 0x00001000 */
#define IWL_DL_ASSOC (1 << 12)
#define IWL_DL_DROP (1 << 13)
-#define IWL_DL_TXPOWER (1 << 14)
-#define IWL_DL_AP (1 << 15)
+/* reserved (1 << 14) */
+#define IWL_DL_COEX (1 << 15)
/* 0x000F0000 - 0x00010000 */
#define IWL_DL_FW (1 << 16)
#define IWL_DL_RF_KILL (1 << 17)
@@ -171,12 +171,10 @@
#define IWL_DEBUG_DROP(p, f, a...) IWL_DEBUG(p, IWL_DL_DROP, f, ## a)
#define IWL_DEBUG_DROP_LIMIT(p, f, a...) \
IWL_DEBUG_LIMIT(p, IWL_DL_DROP, f, ## a)
-#define IWL_DEBUG_AP(p, f, a...) IWL_DEBUG(p, IWL_DL_AP, f, ## a)
-#define IWL_DEBUG_TXPOWER(p, f, a...) IWL_DEBUG(p, IWL_DL_TXPOWER, f, ## a)
+#define IWL_DEBUG_COEX(p, f, a...) IWL_DEBUG(p, IWL_DL_COEX, f, ## a)
#define IWL_DEBUG_RATE(p, f, a...) IWL_DEBUG(p, IWL_DL_RATE, f, ## a)
#define IWL_DEBUG_RATE_LIMIT(p, f, a...) \
IWL_DEBUG_LIMIT(p, IWL_DL_RATE, f, ## a)
-#define IWL_DEBUG_NOTIF(p, f, a...) IWL_DEBUG(p, IWL_DL_NOTIF, f, ## a)
#define IWL_DEBUG_ASSOC(p, f, a...) \
IWL_DEBUG(p, IWL_DL_ASSOC | IWL_DL_INFO, f, ## a)
#define IWL_DEBUG_ASSOC_LIMIT(p, f, a...) \
diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
index 0e6a04b..6f9ebae 100644
--- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
@@ -227,7 +227,7 @@
/* default is to dump the entire data segment */
if (!priv->dbgfs_sram_offset && !priv->dbgfs_sram_len) {
priv->dbgfs_sram_offset = 0x800000;
- if (priv->ucode_type == UCODE_SUBTYPE_INIT)
+ if (priv->ucode_type == IWL_UCODE_INIT)
priv->dbgfs_sram_len = priv->ucode_init.data.len;
else
priv->dbgfs_sram_len = priv->ucode_rt.data.len;
@@ -2493,7 +2493,7 @@
if (iwl_is_rfkill(priv))
return -EFAULT;
- priv->cfg->ops->lib->dev_txfifo_flush(priv, IWL_DROP_ALL);
+ iwlagn_dev_txfifo_flush(priv, IWL_DROP_ALL);
return count;
}
@@ -2693,8 +2693,7 @@
DEBUGFS_ADD_FILE(ucode_rx_stats, dir_debug, S_IRUSR);
DEBUGFS_ADD_FILE(ucode_tx_stats, dir_debug, S_IRUSR);
DEBUGFS_ADD_FILE(ucode_general_stats, dir_debug, S_IRUSR);
- if (priv->cfg->ops->lib->dev_txfifo_flush)
- DEBUGFS_ADD_FILE(txfifo_flush, dir_debug, S_IWUSR);
+ DEBUGFS_ADD_FILE(txfifo_flush, dir_debug, S_IWUSR);
DEBUGFS_ADD_FILE(protection_mode, dir_debug, S_IWUSR | S_IRUSR);
DEBUGFS_ADD_FILE(sensitivity, dir_debug, S_IRUSR);
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index c8de236..f1b1128 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -31,6 +31,7 @@
#ifndef __iwl_dev_h__
#define __iwl_dev_h__
+#include <linux/interrupt.h>
#include <linux/pci.h> /* for struct pci_device_id */
#include <linux/kernel.h>
#include <linux/wait.h>
@@ -48,6 +49,8 @@
#include "iwl-agn-rs.h"
#include "iwl-agn-tt.h"
+#define DRV_NAME "iwlagn"
+
struct iwl_tx_queue;
/* CT-KILL constants */
@@ -1168,14 +1171,63 @@
IWL_SCAN_OFFCH_TX,
};
+enum iwlagn_ucode_type {
+ IWL_UCODE_NONE,
+ IWL_UCODE_REGULAR,
+ IWL_UCODE_INIT,
+ IWL_UCODE_WOWLAN,
+};
+
#ifdef CONFIG_IWLWIFI_DEVICE_SVTOOL
struct iwl_testmode_trace {
+ u32 buff_size;
+ u32 total_size;
+ u32 num_chunks;
u8 *cpu_addr;
u8 *trace_addr;
dma_addr_t dma_addr;
bool trace_enabled;
};
#endif
+
+struct iwl_bus;
+
+/**
+ * struct iwl_bus_ops - bus specific operations
+
+ * @get_pm_support: must returns true if the bus can go to sleep
+ * @apm_config: will be called during the config of the APM configuration
+ * @set_drv_data: set the priv pointer to the bus layer
+ * @get_dev: returns the device struct
+ * @get_irq: returns the irq number
+ * @get_hw_id: prints the hw_id in the provided buffer
+ * @write8: write a byte to register at offset ofs
+ * @write32: write a dword to register at offset ofs
+ * @wread32: read a dword at register at offset ofs
+ */
+struct iwl_bus_ops {
+ bool (*get_pm_support)(struct iwl_bus *bus);
+ void (*apm_config)(struct iwl_bus *bus);
+ void (*set_drv_data)(struct iwl_bus *bus, void *priv);
+ struct device *(*get_dev)(const struct iwl_bus *bus);
+ unsigned int (*get_irq)(const struct iwl_bus *bus);
+ void (*get_hw_id)(struct iwl_bus *bus, char buf[], int buf_len);
+ void (*write8)(struct iwl_bus *bus, u32 ofs, u8 val);
+ void (*write32)(struct iwl_bus *bus, u32 ofs, u32 val);
+ u32 (*read32)(struct iwl_bus *bus, u32 ofs);
+};
+
+struct iwl_bus {
+ /* pointer to bus specific struct */
+ void *bus_specific;
+
+ /* Common data to all buses */
+ struct iwl_priv *priv; /* driver's context */
+ struct device *dev;
+ struct iwl_bus_ops *ops;
+ unsigned int irq;
+};
+
struct iwl_priv {
/* ieee device used by generic ieee processing code */
@@ -1243,17 +1295,14 @@
spinlock_t reg_lock; /* protect hw register access */
struct mutex mutex;
- /* basic pci-network driver stuff */
- struct pci_dev *pci_dev;
-
- /* pci hardware address support */
- void __iomem *hw_base;
+ struct iwl_bus bus; /* bus specific data */
/* microcode/device supports multiple contexts */
u8 valid_contexts;
/* command queue number */
u8 cmd_queue;
+ u8 last_sync_cmd_id;
/* max number of station keys */
u8 sta_key_max_num;
@@ -1270,7 +1319,7 @@
struct fw_img ucode_rt;
struct fw_img ucode_init;
- enum iwlagn_ucode_subtype ucode_type;
+ enum iwlagn_ucode_type ucode_type;
u8 ucode_write_complete; /* the image write is complete */
char firmware_name[25];
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c
index 47a56bc..768d0ee 100644
--- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c
+++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c
@@ -834,3 +834,28 @@
return NULL;
}
+
+void iwl_rf_config(struct iwl_priv *priv)
+{
+ u16 radio_cfg;
+
+ radio_cfg = iwl_eeprom_query16(priv, EEPROM_RADIO_CONFIG);
+
+ /* write radio config values to register */
+ if (EEPROM_RF_CFG_TYPE_MSK(radio_cfg) <= EEPROM_RF_CONFIG_TYPE_MAX) {
+ iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
+ EEPROM_RF_CFG_TYPE_MSK(radio_cfg) |
+ EEPROM_RF_CFG_STEP_MSK(radio_cfg) |
+ EEPROM_RF_CFG_DASH_MSK(radio_cfg));
+ IWL_INFO(priv, "Radio type=0x%x-0x%x-0x%x\n",
+ EEPROM_RF_CFG_TYPE_MSK(radio_cfg),
+ EEPROM_RF_CFG_STEP_MSK(radio_cfg),
+ EEPROM_RF_CFG_DASH_MSK(radio_cfg));
+ } else
+ WARN_ON(1);
+
+ /* set CSR_HW_CONFIG_REG for uCode use */
+ iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
+ CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI |
+ CSR_HW_IF_CONFIG_REG_BIT_MAC_SI);
+}
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.h b/drivers/net/wireless/iwlwifi/iwl-eeprom.h
index c960c6f..804f910 100644
--- a/drivers/net/wireless/iwlwifi/iwl-eeprom.h
+++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.h
@@ -110,12 +110,10 @@
};
/* SKU Capabilities */
-/* 5000 and up */
-#define EEPROM_SKU_CAP_BAND_POS (4)
-#define EEPROM_SKU_CAP_BAND_SELECTION \
- (3 << EEPROM_SKU_CAP_BAND_POS)
+#define EEPROM_SKU_CAP_BAND_24GHZ (1 << 4)
+#define EEPROM_SKU_CAP_BAND_52GHZ (1 << 5)
#define EEPROM_SKU_CAP_11N_ENABLE (1 << 6)
-#define EEPROM_SKU_CAP_AMT_ENABLE (1 << 7)
+#define EEPROM_SKU_CAP_AMT_ENABLE (1 << 7)
#define EEPROM_SKU_CAP_IPAN_ENABLE (1 << 8)
/* *regulatory* channel data format in eeprom, one for each channel.
@@ -164,16 +162,12 @@
s8 mimo3_max;
} __packed;
-/* 5000 Specific */
-#define EEPROM_5000_TX_POWER_VERSION (4)
-#define EEPROM_5000_EEPROM_VERSION (0x11A)
-
-/* 5000 and up calibration */
+/* calibration */
#define EEPROM_CALIB_ALL (INDIRECT_ADDRESS | INDIRECT_CALIBRATION)
#define EEPROM_XTAL ((2*0x128) | EEPROM_CALIB_ALL)
-/* 5000 temperature */
-#define EEPROM_5000_TEMPERATURE ((2*0x12A) | EEPROM_CALIB_ALL)
+/* temperature */
+#define EEPROM_TEMPERATURE ((2*0x12A) | EEPROM_CALIB_ALL)
/* agn links */
#define EEPROM_LINK_HOST (2*0x64)
@@ -205,6 +199,10 @@
#define EEPROM_6000_REG_BAND_24_HT40_CHANNELS ((0x80)\
| INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 14 bytes */
+/* 5000 Specific */
+#define EEPROM_5000_TX_POWER_VERSION (4)
+#define EEPROM_5000_EEPROM_VERSION (0x11A)
+
/* 5050 Specific */
#define EEPROM_5050_TX_POWER_VERSION (4)
#define EEPROM_5050_EEPROM_VERSION (0x21E)
@@ -270,13 +268,13 @@
/* General */
#define EEPROM_DEVICE_ID (2*0x08) /* 2 bytes */
+#define EEPROM_SUBSYSTEM_ID (2*0x0A) /* 2 bytes */
#define EEPROM_MAC_ADDRESS (2*0x15) /* 6 bytes */
#define EEPROM_BOARD_REVISION (2*0x35) /* 2 bytes */
#define EEPROM_BOARD_PBA_NUMBER (2*0x3B+1) /* 9 bytes */
#define EEPROM_VERSION (2*0x44) /* 2 bytes */
#define EEPROM_SKU_CAP (2*0x45) /* 2 bytes */
#define EEPROM_OEM_MODE (2*0x46) /* 2 bytes */
-#define EEPROM_WOWLAN_MODE (2*0x47) /* 2 bytes */
#define EEPROM_RADIO_CONFIG (2*0x48) /* 2 bytes */
#define EEPROM_NUM_MAC_ADDRESS (2*0x4C) /* 2 bytes */
@@ -311,5 +309,6 @@
const struct iwl_channel_info *iwl_get_channel_info(
const struct iwl_priv *priv,
enum ieee80211_band band, u16 channel);
+void iwl_rf_config(struct iwl_priv *priv);
#endif /* __iwl_eeprom_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-hcmd.c
index 76f9966..e3e5fb6 100644
--- a/drivers/net/wireless/iwlwifi/iwl-hcmd.c
+++ b/drivers/net/wireless/iwlwifi/iwl-hcmd.c
@@ -113,7 +113,7 @@
}
}
-#define HOST_COMPLETE_TIMEOUT (HZ / 2)
+#define HOST_COMPLETE_TIMEOUT (2 * HZ)
static void iwl_generic_cmd_callback(struct iwl_priv *priv,
struct iwl_device_cmd *cmd,
@@ -181,7 +181,16 @@
IWL_DEBUG_INFO(priv, "Attempting to send sync command %s\n",
get_cmd_string(cmd->id));
- set_bit(STATUS_HCMD_ACTIVE, &priv->status);
+ if (test_and_set_bit(STATUS_HCMD_ACTIVE, &priv->status)) {
+ IWL_ERR(priv, "STATUS_HCMD_ACTIVE already set while sending %s"
+ ". Previous SYNC cmdn is %s\n",
+ get_cmd_string(cmd->id),
+ get_cmd_string(priv->last_sync_cmd_id));
+ WARN_ON(1);
+ } else {
+ priv->last_sync_cmd_id = cmd->id;
+ }
+
IWL_DEBUG_INFO(priv, "Setting HCMD_ACTIVE for command %s\n",
get_cmd_string(cmd->id));
diff --git a/drivers/net/wireless/iwlwifi/iwl-helpers.h b/drivers/net/wireless/iwlwifi/iwl-helpers.h
index 41207a3..9d91552 100644
--- a/drivers/net/wireless/iwlwifi/iwl-helpers.h
+++ b/drivers/net/wireless/iwlwifi/iwl-helpers.h
@@ -120,7 +120,16 @@
}
}
+#ifdef ieee80211_stop_queue
+#undef ieee80211_stop_queue
+#endif
+
#define ieee80211_stop_queue DO_NOT_USE_ieee80211_stop_queue
+
+#ifdef ieee80211_wake_queue
+#undef ieee80211_wake_queue
+#endif
+
#define ieee80211_wake_queue DO_NOT_USE_ieee80211_wake_queue
static inline void iwl_disable_interrupts(struct iwl_priv *priv)
diff --git a/drivers/net/wireless/iwlwifi/iwl-io.h b/drivers/net/wireless/iwlwifi/iwl-io.h
index 869edc5..c56eae7 100644
--- a/drivers/net/wireless/iwlwifi/iwl-io.h
+++ b/drivers/net/wireless/iwlwifi/iwl-io.h
@@ -38,18 +38,18 @@
static inline void iwl_write8(struct iwl_priv *priv, u32 ofs, u8 val)
{
trace_iwlwifi_dev_iowrite8(priv, ofs, val);
- iowrite8(val, priv->hw_base + ofs);
+ priv->bus.ops->write8(&priv->bus, ofs, val);
}
static inline void iwl_write32(struct iwl_priv *priv, u32 ofs, u32 val)
{
trace_iwlwifi_dev_iowrite32(priv, ofs, val);
- iowrite32(val, priv->hw_base + ofs);
+ priv->bus.ops->write32(&priv->bus, ofs, val);
}
static inline u32 iwl_read32(struct iwl_priv *priv, u32 ofs)
{
- u32 val = ioread32(priv->hw_base + ofs);
+ u32 val = priv->bus.ops->read32(&priv->bus, ofs);
trace_iwlwifi_dev_ioread32(priv, ofs, val);
return val;
}
diff --git a/drivers/net/wireless/iwlwifi/iwl-led.c b/drivers/net/wireless/iwlwifi/iwl-led.c
index 7c23beb..ff08da0 100644
--- a/drivers/net/wireless/iwlwifi/iwl-led.c
+++ b/drivers/net/wireless/iwlwifi/iwl-led.c
@@ -28,8 +28,6 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/dma-mapping.h>
#include <linux/delay.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
@@ -40,14 +38,9 @@
#include "iwl-dev.h"
#include "iwl-core.h"
+#include "iwl-agn.h"
#include "iwl-io.h"
-/* default: IWL_LED_BLINK(0) using blinking index table */
-static int led_mode;
-module_param(led_mode, int, S_IRUGO);
-MODULE_PARM_DESC(led_mode, "0=system default, "
- "1=On(RF On)/Off(RF Off), 2=blinking");
-
/* Throughput OFF time(ms) ON time (ms)
* >300 25 25
* >200 to 300 40 40
@@ -181,7 +174,7 @@
void iwl_leds_init(struct iwl_priv *priv)
{
- int mode = led_mode;
+ int mode = iwlagn_mod_params.led_mode;
int ret;
if (mode == IWL_LED_DEFAULT)
@@ -209,7 +202,8 @@
break;
}
- ret = led_classdev_register(&priv->pci_dev->dev, &priv->led);
+ ret = led_classdev_register(priv->bus.dev,
+ &priv->led);
if (ret) {
kfree(priv->led.name);
return;
diff --git a/drivers/net/wireless/iwlwifi/iwl-pci.c b/drivers/net/wireless/iwlwifi/iwl-pci.c
new file mode 100644
index 0000000..3b5844b
--- /dev/null
+++ b/drivers/net/wireless/iwlwifi/iwl-pci.c
@@ -0,0 +1,559 @@
+/******************************************************************************
+ *
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2007 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License 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,
+ * USA
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * Contact Information:
+ * Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved.
+ * 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 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.
+ *
+ *****************************************************************************/
+#include <linux/pci.h>
+#include <linux/pci-aspm.h>
+
+#include "iwl-pci.h"
+#include "iwl-agn.h"
+#include "iwl-core.h"
+#include "iwl-io.h"
+
+/* PCI registers */
+#define PCI_CFG_RETRY_TIMEOUT 0x041
+#define PCI_CFG_LINK_CTRL_VAL_L0S_EN 0x01
+#define PCI_CFG_LINK_CTRL_VAL_L1_EN 0x02
+
+struct iwl_pci_bus {
+ /* basic pci-network driver stuff */
+ struct pci_dev *pci_dev;
+
+ /* pci hardware address support */
+ void __iomem *hw_base;
+};
+
+#define IWL_BUS_GET_PCI_BUS(_iwl_bus) \
+ ((struct iwl_pci_bus *) ((_iwl_bus)->bus_specific))
+
+#define IWL_BUS_GET_PCI_DEV(_iwl_bus) \
+ ((IWL_BUS_GET_PCI_BUS(_iwl_bus))->pci_dev)
+
+static u16 iwl_pciexp_link_ctrl(struct iwl_bus *bus)
+{
+ int pos;
+ u16 pci_lnk_ctl;
+ struct pci_dev *pci_dev = IWL_BUS_GET_PCI_DEV(bus);
+
+ pos = pci_find_capability(pci_dev, PCI_CAP_ID_EXP);
+ pci_read_config_word(pci_dev, pos + PCI_EXP_LNKCTL, &pci_lnk_ctl);
+ return pci_lnk_ctl;
+}
+
+static bool iwl_pci_is_pm_supported(struct iwl_bus *bus)
+{
+ u16 lctl = iwl_pciexp_link_ctrl(bus);
+
+ return !(lctl & PCI_CFG_LINK_CTRL_VAL_L0S_EN);
+}
+
+static void iwl_pci_apm_config(struct iwl_bus *bus)
+{
+ /*
+ * HW bug W/A for instability in PCIe bus L0S->L1 transition.
+ * Check if BIOS (or OS) enabled L1-ASPM on this device.
+ * If so (likely), disable L0S, so device moves directly L0->L1;
+ * costs negligible amount of power savings.
+ * If not (unlikely), enable L0S, so there is at least some
+ * power savings, even without L1.
+ */
+ u16 lctl = iwl_pciexp_link_ctrl(bus);
+
+ if ((lctl & PCI_CFG_LINK_CTRL_VAL_L1_EN) ==
+ PCI_CFG_LINK_CTRL_VAL_L1_EN) {
+ /* L1-ASPM enabled; disable(!) L0S */
+ iwl_set_bit(bus->priv, CSR_GIO_REG,
+ CSR_GIO_REG_VAL_L0S_ENABLED);
+ IWL_DEBUG_POWER(bus->priv, "L1 Enabled; Disabling L0S\n");
+ } else {
+ /* L1-ASPM disabled; enable(!) L0S */
+ iwl_clear_bit(bus->priv, CSR_GIO_REG,
+ CSR_GIO_REG_VAL_L0S_ENABLED);
+ IWL_DEBUG_POWER(bus->priv, "L1 Disabled; Enabling L0S\n");
+ }
+}
+
+static void iwl_pci_set_drv_data(struct iwl_bus *bus, void *drv_priv)
+{
+ pci_set_drvdata(IWL_BUS_GET_PCI_DEV(bus), drv_priv);
+}
+
+static struct device *iwl_pci_get_dev(const struct iwl_bus *bus)
+{
+ return &(IWL_BUS_GET_PCI_DEV(bus)->dev);
+}
+
+static unsigned int iwl_pci_get_irq(const struct iwl_bus *bus)
+{
+ return IWL_BUS_GET_PCI_DEV(bus)->irq;
+}
+
+static void iwl_pci_get_hw_id(struct iwl_bus *bus, char buf[],
+ int buf_len)
+{
+ struct pci_dev *pci_dev = IWL_BUS_GET_PCI_DEV(bus);
+
+ snprintf(buf, buf_len, "PCI ID: 0x%04X:0x%04X", pci_dev->device,
+ pci_dev->subsystem_device);
+}
+
+static void iwl_pci_write8(struct iwl_bus *bus, u32 ofs, u8 val)
+{
+ iowrite8(val, IWL_BUS_GET_PCI_BUS(bus)->hw_base + ofs);
+}
+
+static void iwl_pci_write32(struct iwl_bus *bus, u32 ofs, u32 val)
+{
+ iowrite32(val, IWL_BUS_GET_PCI_BUS(bus)->hw_base + ofs);
+}
+
+static u32 iwl_pci_read32(struct iwl_bus *bus, u32 ofs)
+{
+ u32 val = ioread32(IWL_BUS_GET_PCI_BUS(bus)->hw_base + ofs);
+ return val;
+}
+
+static struct iwl_bus_ops pci_ops = {
+ .get_pm_support = iwl_pci_is_pm_supported,
+ .apm_config = iwl_pci_apm_config,
+ .set_drv_data = iwl_pci_set_drv_data,
+ .get_dev = iwl_pci_get_dev,
+ .get_irq = iwl_pci_get_irq,
+ .get_hw_id = iwl_pci_get_hw_id,
+ .write8 = iwl_pci_write8,
+ .write32 = iwl_pci_write32,
+ .read32 = iwl_pci_read32,
+};
+
+#define IWL_PCI_DEVICE(dev, subdev, cfg) \
+ .vendor = PCI_VENDOR_ID_INTEL, .device = (dev), \
+ .subvendor = PCI_ANY_ID, .subdevice = (subdev), \
+ .driver_data = (kernel_ulong_t)&(cfg)
+
+/* Hardware specific file defines the PCI IDs table for that hardware module */
+static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = {
+ {IWL_PCI_DEVICE(0x4232, 0x1201, iwl5100_agn_cfg)}, /* Mini Card */
+ {IWL_PCI_DEVICE(0x4232, 0x1301, iwl5100_agn_cfg)}, /* Half Mini Card */
+ {IWL_PCI_DEVICE(0x4232, 0x1204, iwl5100_agn_cfg)}, /* Mini Card */
+ {IWL_PCI_DEVICE(0x4232, 0x1304, iwl5100_agn_cfg)}, /* Half Mini Card */
+ {IWL_PCI_DEVICE(0x4232, 0x1205, iwl5100_bgn_cfg)}, /* Mini Card */
+ {IWL_PCI_DEVICE(0x4232, 0x1305, iwl5100_bgn_cfg)}, /* Half Mini Card */
+ {IWL_PCI_DEVICE(0x4232, 0x1206, iwl5100_abg_cfg)}, /* Mini Card */
+ {IWL_PCI_DEVICE(0x4232, 0x1306, iwl5100_abg_cfg)}, /* Half Mini Card */
+ {IWL_PCI_DEVICE(0x4232, 0x1221, iwl5100_agn_cfg)}, /* Mini Card */
+ {IWL_PCI_DEVICE(0x4232, 0x1321, iwl5100_agn_cfg)}, /* Half Mini Card */
+ {IWL_PCI_DEVICE(0x4232, 0x1224, iwl5100_agn_cfg)}, /* Mini Card */
+ {IWL_PCI_DEVICE(0x4232, 0x1324, iwl5100_agn_cfg)}, /* Half Mini Card */
+ {IWL_PCI_DEVICE(0x4232, 0x1225, iwl5100_bgn_cfg)}, /* Mini Card */
+ {IWL_PCI_DEVICE(0x4232, 0x1325, iwl5100_bgn_cfg)}, /* Half Mini Card */
+ {IWL_PCI_DEVICE(0x4232, 0x1226, iwl5100_abg_cfg)}, /* Mini Card */
+ {IWL_PCI_DEVICE(0x4232, 0x1326, iwl5100_abg_cfg)}, /* Half Mini Card */
+ {IWL_PCI_DEVICE(0x4237, 0x1211, iwl5100_agn_cfg)}, /* Mini Card */
+ {IWL_PCI_DEVICE(0x4237, 0x1311, iwl5100_agn_cfg)}, /* Half Mini Card */
+ {IWL_PCI_DEVICE(0x4237, 0x1214, iwl5100_agn_cfg)}, /* Mini Card */
+ {IWL_PCI_DEVICE(0x4237, 0x1314, iwl5100_agn_cfg)}, /* Half Mini Card */
+ {IWL_PCI_DEVICE(0x4237, 0x1215, iwl5100_bgn_cfg)}, /* Mini Card */
+ {IWL_PCI_DEVICE(0x4237, 0x1315, iwl5100_bgn_cfg)}, /* Half Mini Card */
+ {IWL_PCI_DEVICE(0x4237, 0x1216, iwl5100_abg_cfg)}, /* Mini Card */
+ {IWL_PCI_DEVICE(0x4237, 0x1316, iwl5100_abg_cfg)}, /* Half Mini Card */
+
+/* 5300 Series WiFi */
+ {IWL_PCI_DEVICE(0x4235, 0x1021, iwl5300_agn_cfg)}, /* Mini Card */
+ {IWL_PCI_DEVICE(0x4235, 0x1121, iwl5300_agn_cfg)}, /* Half Mini Card */
+ {IWL_PCI_DEVICE(0x4235, 0x1024, iwl5300_agn_cfg)}, /* Mini Card */
+ {IWL_PCI_DEVICE(0x4235, 0x1124, iwl5300_agn_cfg)}, /* Half Mini Card */
+ {IWL_PCI_DEVICE(0x4235, 0x1001, iwl5300_agn_cfg)}, /* Mini Card */
+ {IWL_PCI_DEVICE(0x4235, 0x1101, iwl5300_agn_cfg)}, /* Half Mini Card */
+ {IWL_PCI_DEVICE(0x4235, 0x1004, iwl5300_agn_cfg)}, /* Mini Card */
+ {IWL_PCI_DEVICE(0x4235, 0x1104, iwl5300_agn_cfg)}, /* Half Mini Card */
+ {IWL_PCI_DEVICE(0x4236, 0x1011, iwl5300_agn_cfg)}, /* Mini Card */
+ {IWL_PCI_DEVICE(0x4236, 0x1111, iwl5300_agn_cfg)}, /* Half Mini Card */
+ {IWL_PCI_DEVICE(0x4236, 0x1014, iwl5300_agn_cfg)}, /* Mini Card */
+ {IWL_PCI_DEVICE(0x4236, 0x1114, iwl5300_agn_cfg)}, /* Half Mini Card */
+
+/* 5350 Series WiFi/WiMax */
+ {IWL_PCI_DEVICE(0x423A, 0x1001, iwl5350_agn_cfg)}, /* Mini Card */
+ {IWL_PCI_DEVICE(0x423A, 0x1021, iwl5350_agn_cfg)}, /* Mini Card */
+ {IWL_PCI_DEVICE(0x423B, 0x1011, iwl5350_agn_cfg)}, /* Mini Card */
+
+/* 5150 Series Wifi/WiMax */
+ {IWL_PCI_DEVICE(0x423C, 0x1201, iwl5150_agn_cfg)}, /* Mini Card */
+ {IWL_PCI_DEVICE(0x423C, 0x1301, iwl5150_agn_cfg)}, /* Half Mini Card */
+ {IWL_PCI_DEVICE(0x423C, 0x1206, iwl5150_abg_cfg)}, /* Mini Card */
+ {IWL_PCI_DEVICE(0x423C, 0x1306, iwl5150_abg_cfg)}, /* Half Mini Card */
+ {IWL_PCI_DEVICE(0x423C, 0x1221, iwl5150_agn_cfg)}, /* Mini Card */
+ {IWL_PCI_DEVICE(0x423C, 0x1321, iwl5150_agn_cfg)}, /* Half Mini Card */
+
+ {IWL_PCI_DEVICE(0x423D, 0x1211, iwl5150_agn_cfg)}, /* Mini Card */
+ {IWL_PCI_DEVICE(0x423D, 0x1311, iwl5150_agn_cfg)}, /* Half Mini Card */
+ {IWL_PCI_DEVICE(0x423D, 0x1216, iwl5150_abg_cfg)}, /* Mini Card */
+ {IWL_PCI_DEVICE(0x423D, 0x1316, iwl5150_abg_cfg)}, /* Half Mini Card */
+
+/* 6x00 Series */
+ {IWL_PCI_DEVICE(0x422B, 0x1101, iwl6000_3agn_cfg)},
+ {IWL_PCI_DEVICE(0x422B, 0x1121, iwl6000_3agn_cfg)},
+ {IWL_PCI_DEVICE(0x422C, 0x1301, iwl6000i_2agn_cfg)},
+ {IWL_PCI_DEVICE(0x422C, 0x1306, iwl6000i_2abg_cfg)},
+ {IWL_PCI_DEVICE(0x422C, 0x1307, iwl6000i_2bg_cfg)},
+ {IWL_PCI_DEVICE(0x422C, 0x1321, iwl6000i_2agn_cfg)},
+ {IWL_PCI_DEVICE(0x422C, 0x1326, iwl6000i_2abg_cfg)},
+ {IWL_PCI_DEVICE(0x4238, 0x1111, iwl6000_3agn_cfg)},
+ {IWL_PCI_DEVICE(0x4239, 0x1311, iwl6000i_2agn_cfg)},
+ {IWL_PCI_DEVICE(0x4239, 0x1316, iwl6000i_2abg_cfg)},
+
+/* 6x05 Series */
+ {IWL_PCI_DEVICE(0x0082, 0x1301, iwl6005_2agn_cfg)},
+ {IWL_PCI_DEVICE(0x0082, 0x1306, iwl6005_2abg_cfg)},
+ {IWL_PCI_DEVICE(0x0082, 0x1307, iwl6005_2bg_cfg)},
+ {IWL_PCI_DEVICE(0x0082, 0x1321, iwl6005_2agn_cfg)},
+ {IWL_PCI_DEVICE(0x0082, 0x1326, iwl6005_2abg_cfg)},
+ {IWL_PCI_DEVICE(0x0085, 0x1311, iwl6005_2agn_cfg)},
+ {IWL_PCI_DEVICE(0x0085, 0x1316, iwl6005_2abg_cfg)},
+
+/* 6x30 Series */
+ {IWL_PCI_DEVICE(0x008A, 0x5305, iwl1030_bgn_cfg)},
+ {IWL_PCI_DEVICE(0x008A, 0x5307, iwl1030_bg_cfg)},
+ {IWL_PCI_DEVICE(0x008A, 0x5325, iwl1030_bgn_cfg)},
+ {IWL_PCI_DEVICE(0x008A, 0x5327, iwl1030_bg_cfg)},
+ {IWL_PCI_DEVICE(0x008B, 0x5315, iwl1030_bgn_cfg)},
+ {IWL_PCI_DEVICE(0x008B, 0x5317, iwl1030_bg_cfg)},
+ {IWL_PCI_DEVICE(0x0090, 0x5211, iwl6030_2agn_cfg)},
+ {IWL_PCI_DEVICE(0x0090, 0x5215, iwl6030_2bgn_cfg)},
+ {IWL_PCI_DEVICE(0x0090, 0x5216, iwl6030_2abg_cfg)},
+ {IWL_PCI_DEVICE(0x0091, 0x5201, iwl6030_2agn_cfg)},
+ {IWL_PCI_DEVICE(0x0091, 0x5205, iwl6030_2bgn_cfg)},
+ {IWL_PCI_DEVICE(0x0091, 0x5206, iwl6030_2abg_cfg)},
+ {IWL_PCI_DEVICE(0x0091, 0x5207, iwl6030_2bg_cfg)},
+ {IWL_PCI_DEVICE(0x0091, 0x5221, iwl6030_2agn_cfg)},
+ {IWL_PCI_DEVICE(0x0091, 0x5225, iwl6030_2bgn_cfg)},
+ {IWL_PCI_DEVICE(0x0091, 0x5226, iwl6030_2abg_cfg)},
+
+/* 6x50 WiFi/WiMax Series */
+ {IWL_PCI_DEVICE(0x0087, 0x1301, iwl6050_2agn_cfg)},
+ {IWL_PCI_DEVICE(0x0087, 0x1306, iwl6050_2abg_cfg)},
+ {IWL_PCI_DEVICE(0x0087, 0x1321, iwl6050_2agn_cfg)},
+ {IWL_PCI_DEVICE(0x0087, 0x1326, iwl6050_2abg_cfg)},
+ {IWL_PCI_DEVICE(0x0089, 0x1311, iwl6050_2agn_cfg)},
+ {IWL_PCI_DEVICE(0x0089, 0x1316, iwl6050_2abg_cfg)},
+
+/* 6150 WiFi/WiMax Series */
+ {IWL_PCI_DEVICE(0x0885, 0x1305, iwl6150_bgn_cfg)},
+ {IWL_PCI_DEVICE(0x0885, 0x1307, iwl6150_bg_cfg)},
+ {IWL_PCI_DEVICE(0x0885, 0x1325, iwl6150_bgn_cfg)},
+ {IWL_PCI_DEVICE(0x0885, 0x1327, iwl6150_bg_cfg)},
+ {IWL_PCI_DEVICE(0x0886, 0x1315, iwl6150_bgn_cfg)},
+ {IWL_PCI_DEVICE(0x0886, 0x1317, iwl6150_bg_cfg)},
+
+/* 1000 Series WiFi */
+ {IWL_PCI_DEVICE(0x0083, 0x1205, iwl1000_bgn_cfg)},
+ {IWL_PCI_DEVICE(0x0083, 0x1305, iwl1000_bgn_cfg)},
+ {IWL_PCI_DEVICE(0x0083, 0x1225, iwl1000_bgn_cfg)},
+ {IWL_PCI_DEVICE(0x0083, 0x1325, iwl1000_bgn_cfg)},
+ {IWL_PCI_DEVICE(0x0084, 0x1215, iwl1000_bgn_cfg)},
+ {IWL_PCI_DEVICE(0x0084, 0x1315, iwl1000_bgn_cfg)},
+ {IWL_PCI_DEVICE(0x0083, 0x1206, iwl1000_bg_cfg)},
+ {IWL_PCI_DEVICE(0x0083, 0x1306, iwl1000_bg_cfg)},
+ {IWL_PCI_DEVICE(0x0083, 0x1226, iwl1000_bg_cfg)},
+ {IWL_PCI_DEVICE(0x0083, 0x1326, iwl1000_bg_cfg)},
+ {IWL_PCI_DEVICE(0x0084, 0x1216, iwl1000_bg_cfg)},
+ {IWL_PCI_DEVICE(0x0084, 0x1316, iwl1000_bg_cfg)},
+
+/* 100 Series WiFi */
+ {IWL_PCI_DEVICE(0x08AE, 0x1005, iwl100_bgn_cfg)},
+ {IWL_PCI_DEVICE(0x08AE, 0x1007, iwl100_bg_cfg)},
+ {IWL_PCI_DEVICE(0x08AF, 0x1015, iwl100_bgn_cfg)},
+ {IWL_PCI_DEVICE(0x08AF, 0x1017, iwl100_bg_cfg)},
+ {IWL_PCI_DEVICE(0x08AE, 0x1025, iwl100_bgn_cfg)},
+ {IWL_PCI_DEVICE(0x08AE, 0x1027, iwl100_bg_cfg)},
+
+/* 130 Series WiFi */
+ {IWL_PCI_DEVICE(0x0896, 0x5005, iwl130_bgn_cfg)},
+ {IWL_PCI_DEVICE(0x0896, 0x5007, iwl130_bg_cfg)},
+ {IWL_PCI_DEVICE(0x0897, 0x5015, iwl130_bgn_cfg)},
+ {IWL_PCI_DEVICE(0x0897, 0x5017, iwl130_bg_cfg)},
+ {IWL_PCI_DEVICE(0x0896, 0x5025, iwl130_bgn_cfg)},
+ {IWL_PCI_DEVICE(0x0896, 0x5027, iwl130_bg_cfg)},
+
+/* 2x00 Series */
+ {IWL_PCI_DEVICE(0x0890, 0x4022, iwl2000_2bgn_cfg)},
+ {IWL_PCI_DEVICE(0x0891, 0x4222, iwl2000_2bgn_cfg)},
+ {IWL_PCI_DEVICE(0x0890, 0x4422, iwl2000_2bgn_cfg)},
+ {IWL_PCI_DEVICE(0x0890, 0x4026, iwl2000_2bg_cfg)},
+ {IWL_PCI_DEVICE(0x0891, 0x4226, iwl2000_2bg_cfg)},
+ {IWL_PCI_DEVICE(0x0890, 0x4426, iwl2000_2bg_cfg)},
+
+/* 2x30 Series */
+ {IWL_PCI_DEVICE(0x0887, 0x4062, iwl2030_2bgn_cfg)},
+ {IWL_PCI_DEVICE(0x0888, 0x4262, iwl2030_2bgn_cfg)},
+ {IWL_PCI_DEVICE(0x0887, 0x4462, iwl2030_2bgn_cfg)},
+ {IWL_PCI_DEVICE(0x0887, 0x4066, iwl2030_2bg_cfg)},
+ {IWL_PCI_DEVICE(0x0888, 0x4266, iwl2030_2bg_cfg)},
+ {IWL_PCI_DEVICE(0x0887, 0x4466, iwl2030_2bg_cfg)},
+
+/* 6x35 Series */
+ {IWL_PCI_DEVICE(0x088E, 0x4060, iwl6035_2agn_cfg)},
+ {IWL_PCI_DEVICE(0x088F, 0x4260, iwl6035_2agn_cfg)},
+ {IWL_PCI_DEVICE(0x088E, 0x4460, iwl6035_2agn_cfg)},
+ {IWL_PCI_DEVICE(0x088E, 0x4064, iwl6035_2abg_cfg)},
+ {IWL_PCI_DEVICE(0x088F, 0x4264, iwl6035_2abg_cfg)},
+ {IWL_PCI_DEVICE(0x088E, 0x4464, iwl6035_2abg_cfg)},
+ {IWL_PCI_DEVICE(0x088E, 0x4066, iwl6035_2bg_cfg)},
+ {IWL_PCI_DEVICE(0x088F, 0x4266, iwl6035_2bg_cfg)},
+ {IWL_PCI_DEVICE(0x088E, 0x4466, iwl6035_2bg_cfg)},
+
+/* 105 Series */
+ {IWL_PCI_DEVICE(0x0894, 0x0022, iwl105_bgn_cfg)},
+ {IWL_PCI_DEVICE(0x0895, 0x0222, iwl105_bgn_cfg)},
+ {IWL_PCI_DEVICE(0x0894, 0x0422, iwl105_bgn_cfg)},
+ {IWL_PCI_DEVICE(0x0894, 0x0026, iwl105_bg_cfg)},
+ {IWL_PCI_DEVICE(0x0895, 0x0226, iwl105_bg_cfg)},
+ {IWL_PCI_DEVICE(0x0894, 0x0426, iwl105_bg_cfg)},
+
+/* 135 Series */
+ {IWL_PCI_DEVICE(0x0892, 0x0062, iwl135_bgn_cfg)},
+ {IWL_PCI_DEVICE(0x0893, 0x0262, iwl135_bgn_cfg)},
+ {IWL_PCI_DEVICE(0x0892, 0x0462, iwl135_bgn_cfg)},
+ {IWL_PCI_DEVICE(0x0892, 0x0066, iwl135_bg_cfg)},
+ {IWL_PCI_DEVICE(0x0893, 0x0266, iwl135_bg_cfg)},
+ {IWL_PCI_DEVICE(0x0892, 0x0466, iwl135_bg_cfg)},
+
+ {0}
+};
+MODULE_DEVICE_TABLE(pci, iwl_hw_card_ids);
+
+static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+ struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data);
+ struct iwl_pci_bus *bus;
+ u16 pci_cmd;
+ int err;
+
+ bus = kzalloc(sizeof(*bus), GFP_KERNEL);
+ if (!bus) {
+ pr_err("Couldn't allocate iwl_pci_bus");
+ err = -ENOMEM;
+ goto out_no_pci;
+ }
+
+ bus->pci_dev = pdev;
+
+ /* W/A - seems to solve weird behavior. We need to remove this if we
+ * don't want to stay in L1 all the time. This wastes a lot of power */
+ pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 |
+ PCIE_LINK_STATE_CLKPM);
+
+ if (pci_enable_device(pdev)) {
+ err = -ENODEV;
+ goto out_no_pci;
+ }
+
+ pci_set_master(pdev);
+
+ err = pci_set_dma_mask(pdev, DMA_BIT_MASK(36));
+ if (!err)
+ err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(36));
+ if (err) {
+ err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
+ if (!err)
+ err = pci_set_consistent_dma_mask(pdev,
+ DMA_BIT_MASK(32));
+ /* both attempts failed: */
+ if (err) {
+ pr_err("No suitable DMA available.\n");
+ goto out_pci_disable_device;
+ }
+ }
+
+ err = pci_request_regions(pdev, DRV_NAME);
+ if (err) {
+ pr_err("pci_request_regions failed");
+ goto out_pci_disable_device;
+ }
+
+ bus->hw_base = pci_iomap(pdev, 0, 0);
+ if (!bus->hw_base) {
+ pr_err("pci_iomap failed");
+ err = -ENODEV;
+ goto out_pci_release_regions;
+ }
+
+ pr_info("pci_resource_len = 0x%08llx\n",
+ (unsigned long long) pci_resource_len(pdev, 0));
+ pr_info("pci_resource_base = %p\n", bus->hw_base);
+
+ pr_info("HW Revision ID = 0x%X\n", pdev->revision);
+
+ /* We disable the RETRY_TIMEOUT register (0x41) to keep
+ * PCI Tx retries from interfering with C3 CPU state */
+ pci_write_config_byte(pdev, PCI_CFG_RETRY_TIMEOUT, 0x00);
+
+ err = pci_enable_msi(pdev);
+ if (err) {
+ pr_err("pci_enable_msi failed");
+ goto out_iounmap;
+ }
+
+ /* TODO: Move this away, not needed if not MSI */
+ /* enable rfkill interrupt: hw bug w/a */
+ pci_read_config_word(pdev, PCI_COMMAND, &pci_cmd);
+ if (pci_cmd & PCI_COMMAND_INTX_DISABLE) {
+ pci_cmd &= ~PCI_COMMAND_INTX_DISABLE;
+ pci_write_config_word(pdev, PCI_COMMAND, pci_cmd);
+ }
+
+ err = iwl_probe((void *) bus, &pci_ops, cfg);
+ if (err)
+ goto out_disable_msi;
+ return 0;
+
+out_disable_msi:
+ pci_disable_msi(pdev);
+out_iounmap:
+ pci_iounmap(pdev, bus->hw_base);
+out_pci_release_regions:
+ pci_set_drvdata(pdev, NULL);
+ pci_release_regions(pdev);
+out_pci_disable_device:
+ pci_disable_device(pdev);
+out_no_pci:
+ kfree(bus);
+ return err;
+}
+
+static void iwl_pci_down(void *bus)
+{
+ struct iwl_pci_bus *pci_bus = (struct iwl_pci_bus *) bus;
+
+ pci_disable_msi(pci_bus->pci_dev);
+ pci_iounmap(pci_bus->pci_dev, pci_bus->hw_base);
+ pci_release_regions(pci_bus->pci_dev);
+ pci_disable_device(pci_bus->pci_dev);
+ pci_set_drvdata(pci_bus->pci_dev, NULL);
+
+ kfree(pci_bus);
+}
+
+static void __devexit iwl_pci_remove(struct pci_dev *pdev)
+{
+ struct iwl_priv *priv = pci_get_drvdata(pdev);
+ void *bus_specific = priv->bus.bus_specific;
+
+ iwl_remove(priv);
+
+ iwl_pci_down(bus_specific);
+}
+
+#ifdef CONFIG_PM
+
+static int iwl_pci_suspend(struct device *device)
+{
+ struct pci_dev *pdev = to_pci_dev(device);
+ struct iwl_priv *priv = pci_get_drvdata(pdev);
+
+ return iwl_suspend(priv);
+}
+
+static int iwl_pci_resume(struct device *device)
+{
+ struct pci_dev *pdev = to_pci_dev(device);
+ struct iwl_priv *priv = pci_get_drvdata(pdev);
+
+ /*
+ * We disable the RETRY_TIMEOUT register (0x41) to keep
+ * PCI Tx retries from interfering with C3 CPU state.
+ */
+ pci_write_config_byte(pdev, PCI_CFG_RETRY_TIMEOUT, 0x00);
+
+ return iwl_resume(priv);
+}
+
+static SIMPLE_DEV_PM_OPS(iwl_dev_pm_ops, iwl_pci_suspend, iwl_pci_resume);
+
+#define IWL_PM_OPS (&iwl_dev_pm_ops)
+
+#else
+
+#define IWL_PM_OPS NULL
+
+#endif
+
+static struct pci_driver iwl_pci_driver = {
+ .name = DRV_NAME,
+ .id_table = iwl_hw_card_ids,
+ .probe = iwl_pci_probe,
+ .remove = __devexit_p(iwl_pci_remove),
+ .driver.pm = IWL_PM_OPS,
+};
+
+int __must_check iwl_pci_register_driver(void)
+{
+ int ret;
+ ret = pci_register_driver(&iwl_pci_driver);
+ if (ret)
+ pr_err("Unable to initialize PCI module\n");
+
+ return ret;
+}
+
+void iwl_pci_unregister_driver(void)
+{
+ pci_unregister_driver(&iwl_pci_driver);
+}
diff --git a/drivers/net/wireless/iwlwifi/iwl-pci.h b/drivers/net/wireless/iwlwifi/iwl-pci.h
new file mode 100644
index 0000000..9396c7c
--- /dev/null
+++ b/drivers/net/wireless/iwlwifi/iwl-pci.h
@@ -0,0 +1,69 @@
+/******************************************************************************
+ *
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2007 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License 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,
+ * USA
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * Contact Information:
+ * Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved.
+ * 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 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.
+ *
+ *****************************************************************************/
+#ifndef __iwl_pci_h__
+#define __iwl_pci_h__
+
+int __must_check iwl_pci_register_driver(void);
+void iwl_pci_unregister_driver(void);
+
+#endif
diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c
index 595c930..565e57e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-power.c
+++ b/drivers/net/wireless/iwlwifi/iwl-power.c
@@ -36,6 +36,7 @@
#include "iwl-eeprom.h"
#include "iwl-dev.h"
+#include "iwl-agn.h"
#include "iwl-core.h"
#include "iwl-io.h"
#include "iwl-commands.h"
@@ -51,16 +52,6 @@
*/
/*
- * For now, keep using power level 1 instead of automatically
- * adjusting ...
- */
-bool no_sleep_autoadjust = true;
-module_param(no_sleep_autoadjust, bool, S_IRUGO);
-MODULE_PARM_DESC(no_sleep_autoadjust,
- "don't automatically adjust sleep level "
- "according to maximum network latency");
-
-/*
* This defines the old power levels. They are still used by default
* (level 1) and for thermal throttle (levels 3 through 5)
*/
@@ -254,7 +245,7 @@
}
}
- if (priv->power_data.pci_pm)
+ if (priv->power_data.bus_pm)
cmd->flags |= IWL_POWER_PCI_PM_MSK;
else
cmd->flags &= ~IWL_POWER_PCI_PM_MSK;
@@ -269,7 +260,7 @@
{
memset(cmd, 0, sizeof(*cmd));
- if (priv->power_data.pci_pm)
+ if (priv->power_data.bus_pm)
cmd->flags |= IWL_POWER_PCI_PM_MSK;
IWL_DEBUG_POWER(priv, "Sleep command for CAM\n");
@@ -305,7 +296,7 @@
cmd->flags = IWL_POWER_DRIVER_ALLOW_SLEEP_MSK |
IWL_POWER_FAST_PD; /* no use seeing frames for others */
- if (priv->power_data.pci_pm)
+ if (priv->power_data.bus_pm)
cmd->flags |= IWL_POWER_PCI_PM_MSK;
if (priv->cfg->base_params->shadow_reg_enable)
@@ -367,9 +358,15 @@
iwl_static_sleep_cmd(priv, cmd,
priv->power_data.debug_sleep_level_override,
dtimper);
- else if (no_sleep_autoadjust)
- iwl_static_sleep_cmd(priv, cmd, IWL_POWER_INDEX_1, dtimper);
- else
+ else if (iwlagn_mod_params.no_sleep_autoadjust) {
+ if (iwlagn_mod_params.power_level > IWL_POWER_INDEX_1 &&
+ iwlagn_mod_params.power_level <= IWL_POWER_INDEX_5)
+ iwl_static_sleep_cmd(priv, cmd,
+ iwlagn_mod_params.power_level, dtimper);
+ else
+ iwl_static_sleep_cmd(priv, cmd,
+ IWL_POWER_INDEX_1, dtimper);
+ } else
iwl_power_fill_sleep_cmd(priv, cmd,
priv->hw->conf.dynamic_ps_timeout,
priv->hw->conf.max_sleep_period);
@@ -434,9 +431,7 @@
/* initialize to default */
void iwl_power_initialize(struct iwl_priv *priv)
{
- u16 lctl = iwl_pcie_link_ctl(priv);
-
- priv->power_data.pci_pm = !(lctl & PCI_CFG_LINK_CTRL_VAL_L0S_EN);
+ priv->power_data.bus_pm = priv->bus.ops->get_pm_support(&priv->bus);
priv->power_data.debug_sleep_level_override = -1;
diff --git a/drivers/net/wireless/iwlwifi/iwl-power.h b/drivers/net/wireless/iwlwifi/iwl-power.h
index 59635d7..5f7b720 100644
--- a/drivers/net/wireless/iwlwifi/iwl-power.h
+++ b/drivers/net/wireless/iwlwifi/iwl-power.h
@@ -43,7 +43,7 @@
struct iwl_powertable_cmd sleep_cmd;
struct iwl_powertable_cmd sleep_cmd_next;
int debug_sleep_level_override;
- bool pci_pm;
+ bool bus_pm;
};
int iwl_power_set_mode(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd,
diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c
index b774517..3efa706 100644
--- a/drivers/net/wireless/iwlwifi/iwl-rx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-rx.c
@@ -182,7 +182,7 @@
int iwl_rx_queue_alloc(struct iwl_priv *priv)
{
struct iwl_rx_queue *rxq = &priv->rxq;
- struct device *dev = &priv->pci_dev->dev;
+ struct device *dev = priv->bus.dev;
int i;
spin_lock_init(&rxq->lock);
@@ -213,7 +213,7 @@
return 0;
err_rb:
- dma_free_coherent(&priv->pci_dev->dev, 4 * RX_QUEUE_SIZE, rxq->bd,
+ dma_free_coherent(dev, 4 * RX_QUEUE_SIZE, rxq->bd,
rxq->bd_dma);
err_bd:
return -ENOMEM;
diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c
index d60d630..438eecd 100644
--- a/drivers/net/wireless/iwlwifi/iwl-scan.c
+++ b/drivers/net/wireless/iwlwifi/iwl-scan.c
@@ -36,6 +36,7 @@
#include "iwl-sta.h"
#include "iwl-io.h"
#include "iwl-helpers.h"
+#include "iwl-agn.h"
/* For active scan, listen ACTIVE_DWELL_TIME (msec) on each channel after
* sending probe req. This should be set long enough to hear probe responses
@@ -600,14 +601,7 @@
if (!iwl_is_ready_rf(priv))
goto out;
- /*
- * We do not commit power settings while scan is pending,
- * do it now if the settings changed.
- */
- iwl_power_set_mode(priv, &priv->power_data.sleep_cmd_next, false);
- iwl_set_tx_power(priv, priv->tx_power_next, false);
-
- priv->cfg->ops->utils->post_scan(priv);
+ iwlagn_post_scan(priv);
out:
mutex_unlock(&priv->mutex);
diff --git a/drivers/net/wireless/iwlwifi/iwl-sv-open.c b/drivers/net/wireless/iwlwifi/iwl-sv-open.c
index 69b7e6b..c00aa5a 100644
--- a/drivers/net/wireless/iwlwifi/iwl-sv-open.c
+++ b/drivers/net/wireless/iwlwifi/iwl-sv-open.c
@@ -69,7 +69,6 @@
#include <net/mac80211.h>
#include <net/netlink.h>
-
#include "iwl-dev.h"
#include "iwl-core.h"
#include "iwl-debug.h"
@@ -101,9 +100,11 @@
[IWL_TM_ATTR_EEPROM] = { .type = NLA_UNSPEC, },
[IWL_TM_ATTR_TRACE_ADDR] = { .type = NLA_UNSPEC, },
- [IWL_TM_ATTR_TRACE_DATA] = { .type = NLA_UNSPEC, },
+ [IWL_TM_ATTR_TRACE_DUMP] = { .type = NLA_UNSPEC, },
+ [IWL_TM_ATTR_TRACE_SIZE] = { .type = NLA_U32, },
[IWL_TM_ATTR_FIXRATE] = { .type = NLA_U32, },
+
};
/*
@@ -179,19 +180,21 @@
static void iwl_trace_cleanup(struct iwl_priv *priv)
{
- struct device *dev = &priv->pci_dev->dev;
+ struct device *dev = priv->bus.dev;
if (priv->testmode_trace.trace_enabled) {
if (priv->testmode_trace.cpu_addr &&
priv->testmode_trace.dma_addr)
dma_free_coherent(dev,
- TRACE_TOTAL_SIZE,
+ priv->testmode_trace.total_size,
priv->testmode_trace.cpu_addr,
priv->testmode_trace.dma_addr);
priv->testmode_trace.trace_enabled = false;
priv->testmode_trace.cpu_addr = NULL;
priv->testmode_trace.trace_addr = NULL;
priv->testmode_trace.dma_addr = 0;
+ priv->testmode_trace.buff_size = 0;
+ priv->testmode_trace.total_size = 0;
}
}
@@ -394,7 +397,7 @@
case IWL_TM_CMD_APP2DEV_LOAD_INIT_FW:
status = iwlagn_load_ucode_wait_alive(priv, &priv->ucode_init,
- UCODE_SUBTYPE_INIT, -1);
+ IWL_UCODE_INIT);
if (status)
IWL_DEBUG_INFO(priv,
"Error loading init ucode: %d\n", status);
@@ -408,8 +411,7 @@
case IWL_TM_CMD_APP2DEV_LOAD_RUNTIME_FW:
status = iwlagn_load_ucode_wait_alive(priv,
&priv->ucode_rt,
- UCODE_SUBTYPE_REGULAR,
- UCODE_SUBTYPE_REGULAR_NEW);
+ IWL_UCODE_REGULAR);
if (status) {
IWL_DEBUG_INFO(priv,
"Error loading runtime ucode: %d\n", status);
@@ -482,16 +484,29 @@
struct iwl_priv *priv = hw->priv;
struct sk_buff *skb;
int status = 0;
- struct device *dev = &priv->pci_dev->dev;
+ struct device *dev = priv->bus.dev;
switch (nla_get_u32(tb[IWL_TM_ATTR_COMMAND])) {
case IWL_TM_CMD_APP2DEV_BEGIN_TRACE:
if (priv->testmode_trace.trace_enabled)
return -EBUSY;
+ if (!tb[IWL_TM_ATTR_TRACE_SIZE])
+ priv->testmode_trace.buff_size = TRACE_BUFF_SIZE_DEF;
+ else
+ priv->testmode_trace.buff_size =
+ nla_get_u32(tb[IWL_TM_ATTR_TRACE_SIZE]);
+ if (!priv->testmode_trace.buff_size)
+ return -EINVAL;
+ if (priv->testmode_trace.buff_size < TRACE_BUFF_SIZE_MIN ||
+ priv->testmode_trace.buff_size > TRACE_BUFF_SIZE_MAX)
+ return -EINVAL;
+
+ priv->testmode_trace.total_size =
+ priv->testmode_trace.buff_size + TRACE_BUFF_PADD;
priv->testmode_trace.cpu_addr =
dma_alloc_coherent(dev,
- TRACE_TOTAL_SIZE,
+ priv->testmode_trace.total_size,
&priv->testmode_trace.dma_addr,
GFP_KERNEL);
if (!priv->testmode_trace.cpu_addr)
@@ -500,7 +515,7 @@
priv->testmode_trace.trace_addr = (u8 *)PTR_ALIGN(
priv->testmode_trace.cpu_addr, 0x100);
memset(priv->testmode_trace.trace_addr, 0x03B,
- TRACE_BUFF_SIZE);
+ priv->testmode_trace.buff_size);
skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy,
sizeof(priv->testmode_trace.dma_addr) + 20);
if (!skb) {
@@ -518,34 +533,14 @@
"Error sending msg : %d\n",
status);
}
+ priv->testmode_trace.num_chunks =
+ DIV_ROUND_UP(priv->testmode_trace.buff_size,
+ TRACE_CHUNK_SIZE);
break;
case IWL_TM_CMD_APP2DEV_END_TRACE:
iwl_trace_cleanup(priv);
break;
-
- case IWL_TM_CMD_APP2DEV_READ_TRACE:
- if (priv->testmode_trace.trace_enabled &&
- priv->testmode_trace.trace_addr) {
- skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy,
- 20 + TRACE_BUFF_SIZE);
- if (skb == NULL) {
- IWL_DEBUG_INFO(priv,
- "Error allocating memory\n");
- return -ENOMEM;
- }
- NLA_PUT(skb, IWL_TM_ATTR_TRACE_DATA,
- TRACE_BUFF_SIZE,
- priv->testmode_trace.trace_addr);
- status = cfg80211_testmode_reply(skb);
- if (status < 0) {
- IWL_DEBUG_INFO(priv,
- "Error sending msg : %d\n", status);
- }
- } else
- return -EFAULT;
- break;
-
default:
IWL_DEBUG_INFO(priv, "Unknown testmode mem command ID\n");
return -ENOSYS;
@@ -560,6 +555,37 @@
return -EMSGSIZE;
}
+static int iwl_testmode_trace_dump(struct ieee80211_hw *hw, struct nlattr **tb,
+ struct sk_buff *skb,
+ struct netlink_callback *cb)
+{
+ struct iwl_priv *priv = hw->priv;
+ int idx, length;
+
+ if (priv->testmode_trace.trace_enabled &&
+ priv->testmode_trace.trace_addr) {
+ idx = cb->args[4];
+ if (idx >= priv->testmode_trace.num_chunks)
+ return -ENOENT;
+ length = TRACE_CHUNK_SIZE;
+ if (((idx + 1) == priv->testmode_trace.num_chunks) &&
+ (priv->testmode_trace.buff_size % TRACE_CHUNK_SIZE))
+ length = priv->testmode_trace.buff_size %
+ TRACE_CHUNK_SIZE;
+
+ NLA_PUT(skb, IWL_TM_ATTR_TRACE_DUMP, length,
+ priv->testmode_trace.trace_addr +
+ (TRACE_CHUNK_SIZE * idx));
+ idx++;
+ cb->args[4] = idx;
+ return 0;
+ } else
+ return -EFAULT;
+
+ nla_put_failure:
+ return -ENOBUFS;
+}
+
/* The testmode gnl message handler that takes the gnl message from the
* user space and parses it per the policy iwl_testmode_gnl_msg_policy, then
* invoke the corresponding handlers.
@@ -638,3 +664,50 @@
mutex_unlock(&priv->mutex);
return result;
}
+
+int iwl_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *skb,
+ struct netlink_callback *cb,
+ void *data, int len)
+{
+ struct nlattr *tb[IWL_TM_ATTR_MAX];
+ struct iwl_priv *priv = hw->priv;
+ int result;
+ u32 cmd;
+
+ if (cb->args[3]) {
+ /* offset by 1 since commands start at 0 */
+ cmd = cb->args[3] - 1;
+ } else {
+ result = nla_parse(tb, IWL_TM_ATTR_MAX - 1, data, len,
+ iwl_testmode_gnl_msg_policy);
+ if (result) {
+ IWL_DEBUG_INFO(priv,
+ "Error parsing the gnl message : %d\n", result);
+ return result;
+ }
+
+ /* IWL_TM_ATTR_COMMAND is absolutely mandatory */
+ if (!tb[IWL_TM_ATTR_COMMAND]) {
+ IWL_DEBUG_INFO(priv,
+ "Error finding testmode command type\n");
+ return -ENOMSG;
+ }
+ cmd = nla_get_u32(tb[IWL_TM_ATTR_COMMAND]);
+ cb->args[3] = cmd + 1;
+ }
+
+ /* in case multiple accesses to the device happens */
+ mutex_lock(&priv->mutex);
+ switch (cmd) {
+ case IWL_TM_CMD_APP2DEV_READ_TRACE:
+ IWL_DEBUG_INFO(priv, "uCode trace cmd to driver\n");
+ result = iwl_testmode_trace_dump(hw, tb, skb, cb);
+ break;
+ default:
+ result = -EINVAL;
+ break;
+ }
+
+ mutex_unlock(&priv->mutex);
+ return result;
+}
diff --git a/drivers/net/wireless/iwlwifi/iwl-testmode.h b/drivers/net/wireless/iwlwifi/iwl-testmode.h
index a88085e..160911a 100644
--- a/drivers/net/wireless/iwlwifi/iwl-testmode.h
+++ b/drivers/net/wireless/iwlwifi/iwl-testmode.h
@@ -166,7 +166,8 @@
* IWL_TM_ATTR_MEM_TRACE_ADDR for the trace address
*/
IWL_TM_ATTR_TRACE_ADDR,
- IWL_TM_ATTR_TRACE_DATA,
+ IWL_TM_ATTR_TRACE_SIZE,
+ IWL_TM_ATTR_TRACE_DUMP,
/* When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_FIXRATE_REQ,
* The mandatory fields are:
@@ -178,8 +179,10 @@
};
/* uCode trace buffer */
-#define TRACE_BUFF_SIZE 0x20000
+#define TRACE_BUFF_SIZE_MAX 0x200000
+#define TRACE_BUFF_SIZE_MIN 0x20000
+#define TRACE_BUFF_SIZE_DEF TRACE_BUFF_SIZE_MIN
#define TRACE_BUFF_PADD 0x2000
-#define TRACE_TOTAL_SIZE (TRACE_BUFF_SIZE + TRACE_BUFF_PADD)
+#define TRACE_CHUNK_SIZE (PAGE_SIZE - 1024)
#endif
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c
index 137dba9..e72d227 100644
--- a/drivers/net/wireless/iwlwifi/iwl-tx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-tx.c
@@ -126,9 +126,8 @@
}
static void iwlagn_unmap_tfd(struct iwl_priv *priv, struct iwl_cmd_meta *meta,
- struct iwl_tfd *tfd, int dma_dir)
+ struct iwl_tfd *tfd, enum dma_data_direction dma_dir)
{
- struct pci_dev *dev = priv->pci_dev;
int i;
int num_tbs;
@@ -143,14 +142,14 @@
/* Unmap tx_cmd */
if (num_tbs)
- pci_unmap_single(dev,
+ dma_unmap_single(priv->bus.dev,
dma_unmap_addr(meta, mapping),
dma_unmap_len(meta, len),
- PCI_DMA_BIDIRECTIONAL);
+ DMA_BIDIRECTIONAL);
/* Unmap chunks, if any. */
for (i = 1; i < num_tbs; i++)
- pci_unmap_single(dev, iwl_tfd_tb_get_addr(tfd, i),
+ dma_unmap_single(priv->bus.dev, iwl_tfd_tb_get_addr(tfd, i),
iwl_tfd_tb_get_len(tfd, i), dma_dir);
}
@@ -168,7 +167,7 @@
int index = txq->q.read_ptr;
iwlagn_unmap_tfd(priv, &txq->meta[index], &tfd_tmp[index],
- PCI_DMA_TODEVICE);
+ DMA_TO_DEVICE);
/* free SKB */
if (txq->txb) {
@@ -267,7 +266,7 @@
void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id)
{
struct iwl_tx_queue *txq = &priv->txq[txq_id];
- struct device *dev = &priv->pci_dev->dev;
+ struct device *dev = priv->bus.dev;
int i;
iwl_tx_queue_unmap(priv, txq_id);
@@ -312,7 +311,7 @@
if (txq->meta[i].flags & CMD_MAPPED) {
iwlagn_unmap_tfd(priv, &txq->meta[i], &txq->tfds[i],
- PCI_DMA_BIDIRECTIONAL);
+ DMA_BIDIRECTIONAL);
txq->meta[i].flags = 0;
}
@@ -331,7 +330,7 @@
void iwl_cmd_queue_free(struct iwl_priv *priv)
{
struct iwl_tx_queue *txq = &priv->txq[priv->cmd_queue];
- struct device *dev = &priv->pci_dev->dev;
+ struct device *dev = priv->bus.dev;
int i;
iwl_cmd_queue_unmap(priv);
@@ -433,7 +432,7 @@
static int iwl_tx_queue_alloc(struct iwl_priv *priv,
struct iwl_tx_queue *txq, u32 id)
{
- struct device *dev = &priv->pci_dev->dev;
+ struct device *dev = priv->bus.dev;
size_t tfd_sz = priv->hw_params.tfd_size * TFD_QUEUE_SIZE_MAX;
/* Driver private data, only for Tx (not command) queues,
@@ -455,7 +454,7 @@
txq->tfds = dma_alloc_coherent(dev, tfd_sz, &txq->q.dma_addr,
GFP_KERNEL);
if (!txq->tfds) {
- IWL_ERR(priv, "pci_alloc_consistent(%zd) failed\n", tfd_sz);
+ IWL_ERR(priv, "dma_alloc_coherent(%zd) failed\n", tfd_sz);
goto error;
}
txq->q.id = id;
@@ -671,9 +670,9 @@
le16_to_cpu(out_cmd->hdr.sequence), cmd_size,
q->write_ptr, idx, priv->cmd_queue);
- phys_addr = pci_map_single(priv->pci_dev, &out_cmd->hdr,
- copy_size, PCI_DMA_BIDIRECTIONAL);
- if (unlikely(pci_dma_mapping_error(priv->pci_dev, phys_addr))) {
+ phys_addr = dma_map_single(priv->bus.dev, &out_cmd->hdr, copy_size,
+ DMA_BIDIRECTIONAL);
+ if (unlikely(dma_mapping_error(priv->bus.dev, phys_addr))) {
idx = -ENOMEM;
goto out;
}
@@ -693,12 +692,12 @@
continue;
if (!(cmd->dataflags[i] & IWL_HCMD_DFL_NOCOPY))
continue;
- phys_addr = pci_map_single(priv->pci_dev, (void *)cmd->data[i],
- cmd->len[i], PCI_DMA_BIDIRECTIONAL);
- if (pci_dma_mapping_error(priv->pci_dev, phys_addr)) {
+ phys_addr = dma_map_single(priv->bus.dev, (void *)cmd->data[i],
+ cmd->len[i], DMA_BIDIRECTIONAL);
+ if (dma_mapping_error(priv->bus.dev, phys_addr)) {
iwlagn_unmap_tfd(priv, out_meta,
&txq->tfds[q->write_ptr],
- PCI_DMA_BIDIRECTIONAL);
+ DMA_BIDIRECTIONAL);
idx = -ENOMEM;
goto out;
}
@@ -748,9 +747,9 @@
int nfreed = 0;
if ((idx >= q->n_bd) || (iwl_queue_used(q, idx) == 0)) {
- IWL_ERR(priv, "Read index for DMA queue txq id (%d), index %d, "
- "is out of range [0-%d] %d %d.\n", txq_id,
- idx, q->n_bd, q->write_ptr, q->read_ptr);
+ IWL_ERR(priv, "%s: Read index for DMA queue txq id (%d), "
+ "index %d is out of range [0-%d] %d %d.\n", __func__,
+ txq_id, idx, q->n_bd, q->write_ptr, q->read_ptr);
return;
}
@@ -802,7 +801,7 @@
cmd = txq->cmd[cmd_index];
meta = &txq->meta[cmd_index];
- iwlagn_unmap_tfd(priv, meta, &txq->tfds[index], PCI_DMA_BIDIRECTIONAL);
+ iwlagn_unmap_tfd(priv, meta, &txq->tfds[index], DMA_BIDIRECTIONAL);
/* Input error checking is done when commands are added to queue. */
if (meta->flags & CMD_WANT_SKB) {
diff --git a/drivers/net/wireless/iwmc3200wifi/fw.c b/drivers/net/wireless/iwmc3200wifi/fw.c
index 4906709..6f1afe6 100644
--- a/drivers/net/wireless/iwmc3200wifi/fw.c
+++ b/drivers/net/wireless/iwmc3200wifi/fw.c
@@ -187,7 +187,7 @@
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);
diff --git a/drivers/net/wireless/libertas/cfg.c b/drivers/net/wireless/libertas/cfg.c
index 5d637af..b456a53 100644
--- a/drivers/net/wireless/libertas/cfg.c
+++ b/drivers/net/wireless/libertas/cfg.c
@@ -8,6 +8,7 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#include <linux/hardirq.h>
#include <linux/sched.h>
#include <linux/wait.h>
#include <linux/slab.h>
diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c
index 71c8f3f..9dcf967 100644
--- a/drivers/net/wireless/libertas/cmd.c
+++ b/drivers/net/wireless/libertas/cmd.c
@@ -3,6 +3,7 @@
* It prepares command and sends it to firmware when it is ready.
*/
+#include <linux/hardirq.h>
#include <linux/kfifo.h>
#include <linux/sched.h>
#include <linux/slab.h>
diff --git a/drivers/net/wireless/libertas/cmdresp.c b/drivers/net/wireless/libertas/cmdresp.c
index 207fc36..2ffe5a1 100644
--- a/drivers/net/wireless/libertas/cmdresp.c
+++ b/drivers/net/wireless/libertas/cmdresp.c
@@ -3,6 +3,7 @@
* responses as well as events generated by firmware.
*/
+#include <linux/hardirq.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/sched.h>
diff --git a/drivers/net/wireless/libertas/debugfs.c b/drivers/net/wireless/libertas/debugfs.c
index 23250f6..1af1827 100644
--- a/drivers/net/wireless/libertas/debugfs.c
+++ b/drivers/net/wireless/libertas/debugfs.c
@@ -1,6 +1,7 @@
#include <linux/dcache.h>
#include <linux/debugfs.h>
#include <linux/delay.h>
+#include <linux/hardirq.h>
#include <linux/mm.h>
#include <linux/string.h>
#include <linux/slab.h>
diff --git a/drivers/net/wireless/libertas/ethtool.c b/drivers/net/wireless/libertas/ethtool.c
index 29dbce4..4dfb3bf 100644
--- a/drivers/net/wireless/libertas/ethtool.c
+++ b/drivers/net/wireless/libertas/ethtool.c
@@ -1,3 +1,4 @@
+#include <linux/hardirq.h>
#include <linux/netdevice.h>
#include <linux/ethtool.h>
#include <linux/delay.h>
diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c
index 224e985..387786e 100644
--- a/drivers/net/wireless/libertas/if_sdio.c
+++ b/drivers/net/wireless/libertas/if_sdio.c
@@ -892,6 +892,37 @@
}
+static struct mmc_host *reset_host;
+
+static void if_sdio_reset_card_worker(struct work_struct *work)
+{
+ /*
+ * The actual reset operation must be run outside of lbs_thread. This
+ * is because mmc_remove_host() will cause the device to be instantly
+ * destroyed, and the libertas driver then needs to end lbs_thread,
+ * leading to a deadlock.
+ *
+ * We run it in a workqueue totally independent from the if_sdio_card
+ * instance for that reason.
+ */
+
+ pr_info("Resetting card...");
+ mmc_remove_host(reset_host);
+ mmc_add_host(reset_host);
+}
+static DECLARE_WORK(card_reset_work, if_sdio_reset_card_worker);
+
+static void if_sdio_reset_card(struct lbs_private *priv)
+{
+ struct if_sdio_card *card = priv->card;
+
+ if (work_pending(&card_reset_work))
+ return;
+
+ reset_host = card->func->card->host;
+ schedule_work(&card_reset_work);
+}
+
/*******************************************************************/
/* SDIO callbacks */
/*******************************************************************/
@@ -1065,6 +1096,7 @@
priv->enter_deep_sleep = if_sdio_enter_deep_sleep;
priv->exit_deep_sleep = if_sdio_exit_deep_sleep;
priv->reset_deep_sleep_wakeup = if_sdio_reset_deep_sleep_wakeup;
+ priv->reset_card = if_sdio_reset_card;
sdio_claim_host(func);
@@ -1301,6 +1333,8 @@
/* Set the flag as user is removing this module. */
user_rmmod = 1;
+ cancel_work_sync(&card_reset_work);
+
sdio_unregister_driver(&if_sdio_driver);
lbs_deb_leave(LBS_DEB_SDIO);
diff --git a/drivers/net/wireless/libertas/if_spi.c b/drivers/net/wireless/libertas/if_spi.c
index 463352c..e0286cf 100644
--- a/drivers/net/wireless/libertas/if_spi.c
+++ b/drivers/net/wireless/libertas/if_spi.c
@@ -19,6 +19,8 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#include <linux/hardirq.h>
+#include <linux/interrupt.h>
#include <linux/moduleparam.h>
#include <linux/firmware.h>
#include <linux/jiffies.h>
@@ -1032,7 +1034,6 @@
static int if_spi_init_card(struct if_spi_card *card)
{
struct lbs_private *priv = card->priv;
- struct spi_device *spi = card->spi;
int err, i;
u32 scratch;
const struct firmware *helper = NULL;
@@ -1080,8 +1081,9 @@
"attached to SPI bus_num %d, chip_select %d. "
"spi->max_speed_hz=%d\n",
card->card_id, card->card_rev,
- spi->master->bus_num, spi->chip_select,
- spi->max_speed_hz);
+ card->spi->master->bus_num,
+ card->spi->chip_select,
+ card->spi->max_speed_hz);
err = if_spi_prog_helper_firmware(card, helper);
if (err)
goto out;
diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c
index 8c40949..cf3d2c8 100644
--- a/drivers/net/wireless/libertas/main.c
+++ b/drivers/net/wireless/libertas/main.c
@@ -9,6 +9,7 @@
#include <linux/moduleparam.h>
#include <linux/delay.h>
#include <linux/etherdevice.h>
+#include <linux/hardirq.h>
#include <linux/netdevice.h>
#include <linux/if_arp.h>
#include <linux/kthread.h>
diff --git a/drivers/net/wireless/libertas/mesh.c b/drivers/net/wireless/libertas/mesh.c
index 24cf066..7969d10 100644
--- a/drivers/net/wireless/libertas/mesh.c
+++ b/drivers/net/wireless/libertas/mesh.c
@@ -2,6 +2,7 @@
#include <linux/delay.h>
#include <linux/etherdevice.h>
+#include <linux/hardirq.h>
#include <linux/netdevice.h>
#include <linux/if_ether.h>
#include <linux/if_arp.h>
diff --git a/drivers/net/wireless/libertas/rx.c b/drivers/net/wireless/libertas/rx.c
index fdb0448..bfb8898 100644
--- a/drivers/net/wireless/libertas/rx.c
+++ b/drivers/net/wireless/libertas/rx.c
@@ -5,6 +5,7 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/etherdevice.h>
+#include <linux/hardirq.h>
#include <linux/slab.h>
#include <linux/types.h>
#include <net/cfg80211.h>
diff --git a/drivers/net/wireless/libertas/tx.c b/drivers/net/wireless/libertas/tx.c
index bbb95f8..f19495b 100644
--- a/drivers/net/wireless/libertas/tx.c
+++ b/drivers/net/wireless/libertas/tx.c
@@ -1,6 +1,7 @@
/*
* This file contains the handling of TX in wlan driver.
*/
+#include <linux/hardirq.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/sched.h>
diff --git a/drivers/net/wireless/libertas_tf/cmd.c b/drivers/net/wireless/libertas_tf/cmd.c
index 8945afd..13557fe 100644
--- a/drivers/net/wireless/libertas_tf/cmd.c
+++ b/drivers/net/wireless/libertas_tf/cmd.c
@@ -9,6 +9,7 @@
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#include <linux/hardirq.h>
#include <linux/slab.h>
#include "libertas_tf.h"
diff --git a/drivers/net/wireless/libertas_tf/main.c b/drivers/net/wireless/libertas_tf/main.c
index d400508..acc461a 100644
--- a/drivers/net/wireless/libertas_tf/main.c
+++ b/drivers/net/wireless/libertas_tf/main.c
@@ -9,6 +9,7 @@
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#include <linux/hardirq.h>
#include <linux/slab.h>
#include <linux/etherdevice.h>
@@ -585,7 +586,7 @@
need_padding ^= ieee80211_has_a4(hdr->frame_control);
need_padding ^= ieee80211_is_data_qos(hdr->frame_control) &&
(*ieee80211_get_qos_ctl(hdr) &
- IEEE80211_QOS_CONTROL_A_MSDU_PRESENT);
+ IEEE80211_QOS_CTL_A_MSDU_PRESENT);
if (need_padding) {
memmove(skb->data + 2, skb->data, skb->len);
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
index 9d4a40e..031cd89 100644
--- a/drivers/net/wireless/mac80211_hwsim.c
+++ b/drivers/net/wireless/mac80211_hwsim.c
@@ -1,6 +1,7 @@
/*
* mac80211_hwsim - software simulator of 802.11 radio(s) for mac80211
* Copyright (c) 2008, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2011, Javier Lopez <jlopex@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -25,11 +26,17 @@
#include <linux/rtnetlink.h>
#include <linux/etherdevice.h>
#include <linux/debugfs.h>
+#include <net/genetlink.h>
+#include "mac80211_hwsim.h"
+
+#define WARN_QUEUE 100
+#define MAX_QUEUE 200
MODULE_AUTHOR("Jouni Malinen");
MODULE_DESCRIPTION("Software simulator of 802.11 radio(s) for mac80211");
MODULE_LICENSE("GPL");
+int wmediumd_pid;
static int radios = 2;
module_param(radios, int, 0444);
MODULE_PARM_DESC(radios, "Number of simulated radios");
@@ -302,6 +309,7 @@
struct dentry *debugfs;
struct dentry *debugfs_ps;
+ struct sk_buff_head pending; /* packets pending */
/*
* Only radios in the same group can communicate together (the
* channel has to match too). Each bit represents a group. A
@@ -322,6 +330,32 @@
__le16 rt_chbitmask;
} __packed;
+/* MAC80211_HWSIM netlinf family */
+static struct genl_family hwsim_genl_family = {
+ .id = GENL_ID_GENERATE,
+ .hdrsize = 0,
+ .name = "MAC80211_HWSIM",
+ .version = 1,
+ .maxattr = HWSIM_ATTR_MAX,
+};
+
+/* MAC80211_HWSIM netlink policy */
+
+static struct nla_policy hwsim_genl_policy[HWSIM_ATTR_MAX + 1] = {
+ [HWSIM_ATTR_ADDR_RECEIVER] = { .type = NLA_UNSPEC,
+ .len = 6*sizeof(u8) },
+ [HWSIM_ATTR_ADDR_TRANSMITTER] = { .type = NLA_UNSPEC,
+ .len = 6*sizeof(u8) },
+ [HWSIM_ATTR_FRAME] = { .type = NLA_BINARY,
+ .len = IEEE80211_MAX_DATA_LEN },
+ [HWSIM_ATTR_FLAGS] = { .type = NLA_U32 },
+ [HWSIM_ATTR_RX_RATE] = { .type = NLA_U32 },
+ [HWSIM_ATTR_SIGNAL] = { .type = NLA_U32 },
+ [HWSIM_ATTR_TX_INFO] = { .type = NLA_UNSPEC,
+ .len = IEEE80211_TX_MAX_RATES*sizeof(
+ struct hwsim_tx_rate)},
+ [HWSIM_ATTR_COOKIE] = { .type = NLA_U64 },
+};
static netdev_tx_t hwsim_mon_xmit(struct sk_buff *skb,
struct net_device *dev)
@@ -478,9 +512,89 @@
return md.ret;
}
+static void mac80211_hwsim_tx_frame_nl(struct ieee80211_hw *hw,
+ struct sk_buff *my_skb,
+ int dst_pid)
+{
+ struct sk_buff *skb;
+ struct mac80211_hwsim_data *data = hw->priv;
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) my_skb->data;
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(my_skb);
+ void *msg_head;
+ unsigned int hwsim_flags = 0;
+ int i;
+ struct hwsim_tx_rate tx_attempts[IEEE80211_TX_MAX_RATES];
-static bool mac80211_hwsim_tx_frame(struct ieee80211_hw *hw,
- struct sk_buff *skb)
+ if (data->idle) {
+ wiphy_debug(hw->wiphy, "Trying to TX when idle - reject\n");
+ dev_kfree_skb(my_skb);
+ return;
+ }
+
+ if (data->ps != PS_DISABLED)
+ hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM);
+ /* If the queue contains MAX_QUEUE skb's drop some */
+ if (skb_queue_len(&data->pending) >= MAX_QUEUE) {
+ /* Droping until WARN_QUEUE level */
+ while (skb_queue_len(&data->pending) >= WARN_QUEUE)
+ skb_dequeue(&data->pending);
+ }
+
+ skb = genlmsg_new(NLMSG_GOODSIZE, GFP_ATOMIC);
+ if (skb == NULL)
+ goto nla_put_failure;
+
+ msg_head = genlmsg_put(skb, 0, 0, &hwsim_genl_family, 0,
+ HWSIM_CMD_FRAME);
+ if (msg_head == NULL) {
+ printk(KERN_DEBUG "mac80211_hwsim: problem with msg_head\n");
+ goto nla_put_failure;
+ }
+
+ NLA_PUT(skb, HWSIM_ATTR_ADDR_TRANSMITTER,
+ sizeof(struct mac_address), data->addresses[1].addr);
+
+ /* We get the skb->data */
+ NLA_PUT(skb, HWSIM_ATTR_FRAME, my_skb->len, my_skb->data);
+
+ /* We get the flags for this transmission, and we translate them to
+ wmediumd flags */
+
+ if (info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS)
+ hwsim_flags |= HWSIM_TX_CTL_REQ_TX_STATUS;
+
+ if (info->flags & IEEE80211_TX_CTL_NO_ACK)
+ hwsim_flags |= HWSIM_TX_CTL_NO_ACK;
+
+ NLA_PUT_U32(skb, HWSIM_ATTR_FLAGS, hwsim_flags);
+
+ /* We get the tx control (rate and retries) info*/
+
+ for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
+ tx_attempts[i].idx = info->status.rates[i].idx;
+ tx_attempts[i].count = info->status.rates[i].count;
+ }
+
+ NLA_PUT(skb, HWSIM_ATTR_TX_INFO,
+ sizeof(struct hwsim_tx_rate)*IEEE80211_TX_MAX_RATES,
+ tx_attempts);
+
+ /* We create a cookie to identify this skb */
+ NLA_PUT_U64(skb, HWSIM_ATTR_COOKIE, (unsigned long) my_skb);
+
+ genlmsg_end(skb, msg_head);
+ genlmsg_unicast(&init_net, skb, dst_pid);
+
+ /* Enqueue the packet */
+ skb_queue_tail(&data->pending, my_skb);
+ return;
+
+nla_put_failure:
+ printk(KERN_DEBUG "mac80211_hwsim: error occured in %s\n", __func__);
+}
+
+static bool mac80211_hwsim_tx_frame_no_nl(struct ieee80211_hw *hw,
+ struct sk_buff *skb)
{
struct mac80211_hwsim_data *data = hw->priv, *data2;
bool ack = false;
@@ -540,11 +654,11 @@
return ack;
}
-
static void mac80211_hwsim_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
{
bool ack;
struct ieee80211_tx_info *txi;
+ int _pid;
mac80211_hwsim_monitor_rx(hw, skb);
@@ -554,7 +668,15 @@
return;
}
- ack = mac80211_hwsim_tx_frame(hw, skb);
+ /* wmediumd mode check */
+ _pid = wmediumd_pid;
+
+ if (_pid)
+ return mac80211_hwsim_tx_frame_nl(hw, skb, _pid);
+
+ /* NO wmediumd detected, perfect medium simulation */
+ ack = mac80211_hwsim_tx_frame_no_nl(hw, skb);
+
if (ack && skb->len >= 16) {
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
mac80211_hwsim_monitor_ack(hw, hdr->addr2);
@@ -635,6 +757,7 @@
struct ieee80211_hw *hw = arg;
struct sk_buff *skb;
struct ieee80211_tx_info *info;
+ int _pid;
hwsim_check_magic(vif);
@@ -649,7 +772,14 @@
info = IEEE80211_SKB_CB(skb);
mac80211_hwsim_monitor_rx(hw, skb);
- mac80211_hwsim_tx_frame(hw, skb);
+
+ /* wmediumd mode check */
+ _pid = wmediumd_pid;
+
+ if (_pid)
+ return mac80211_hwsim_tx_frame_nl(hw, skb, _pid);
+
+ mac80211_hwsim_tx_frame_no_nl(hw, skb);
dev_kfree_skb(skb);
}
@@ -966,12 +1096,7 @@
static void mac80211_hwsim_flush(struct ieee80211_hw *hw, bool drop)
{
- /*
- * In this special case, there's nothing we need to
- * do because hwsim does transmission synchronously.
- * In the future, when it does transmissions via
- * userspace, we may need to do something.
- */
+ /* Not implemented, queues only on kernel side */
}
struct hw_scan_done {
@@ -1005,6 +1130,8 @@
for (i = 0; i < req->n_channels; i++)
printk(KERN_DEBUG "hwsim hw_scan freq %d\n",
req->channels[i]->center_freq);
+ print_hex_dump(KERN_DEBUG, "scan IEs: ", DUMP_PREFIX_OFFSET,
+ 16, 1, req->ie, req->ie_len, 1);
ieee80211_queue_delayed_work(hw, &hsd->w, 2 * HZ);
@@ -1119,6 +1246,7 @@
struct hwsim_vif_priv *vp = (void *)vif->drv_priv;
struct sk_buff *skb;
struct ieee80211_pspoll *pspoll;
+ int _pid;
if (!vp->assoc)
return;
@@ -1137,8 +1265,15 @@
pspoll->aid = cpu_to_le16(0xc000 | vp->aid);
memcpy(pspoll->bssid, vp->bssid, ETH_ALEN);
memcpy(pspoll->ta, mac, ETH_ALEN);
- if (!mac80211_hwsim_tx_frame(data->hw, skb))
- printk(KERN_DEBUG "%s: PS-Poll frame not ack'ed\n", __func__);
+
+ /* wmediumd mode check */
+ _pid = wmediumd_pid;
+
+ if (_pid)
+ return mac80211_hwsim_tx_frame_nl(data->hw, skb, _pid);
+
+ if (!mac80211_hwsim_tx_frame_no_nl(data->hw, skb))
+ printk(KERN_DEBUG "%s: PS-poll frame not ack'ed\n", __func__);
dev_kfree_skb(skb);
}
@@ -1149,6 +1284,7 @@
struct hwsim_vif_priv *vp = (void *)vif->drv_priv;
struct sk_buff *skb;
struct ieee80211_hdr *hdr;
+ int _pid;
if (!vp->assoc)
return;
@@ -1168,7 +1304,14 @@
memcpy(hdr->addr1, vp->bssid, ETH_ALEN);
memcpy(hdr->addr2, mac, ETH_ALEN);
memcpy(hdr->addr3, vp->bssid, ETH_ALEN);
- if (!mac80211_hwsim_tx_frame(data->hw, skb))
+
+ /* wmediumd mode check */
+ _pid = wmediumd_pid;
+
+ if (_pid)
+ return mac80211_hwsim_tx_frame_nl(data->hw, skb, _pid);
+
+ if (!mac80211_hwsim_tx_frame_no_nl(data->hw, skb))
printk(KERN_DEBUG "%s: nullfunc frame not ack'ed\n", __func__);
dev_kfree_skb(skb);
}
@@ -1248,6 +1391,273 @@
hwsim_fops_group_read, hwsim_fops_group_write,
"%llx\n");
+struct mac80211_hwsim_data *get_hwsim_data_ref_from_addr(
+ struct mac_address *addr)
+{
+ struct mac80211_hwsim_data *data;
+ bool _found = false;
+
+ spin_lock_bh(&hwsim_radio_lock);
+ list_for_each_entry(data, &hwsim_radios, list) {
+ if (memcmp(data->addresses[1].addr, addr,
+ sizeof(struct mac_address)) == 0) {
+ _found = true;
+ break;
+ }
+ }
+ spin_unlock_bh(&hwsim_radio_lock);
+
+ if (!_found)
+ return NULL;
+
+ return data;
+}
+
+static int hwsim_tx_info_frame_received_nl(struct sk_buff *skb_2,
+ struct genl_info *info)
+{
+
+ struct ieee80211_hdr *hdr;
+ struct mac80211_hwsim_data *data2;
+ struct ieee80211_tx_info *txi;
+ struct hwsim_tx_rate *tx_attempts;
+ struct sk_buff __user *ret_skb;
+ struct sk_buff *skb, *tmp;
+ struct mac_address *src;
+ unsigned int hwsim_flags;
+
+ int i;
+ bool found = false;
+
+ if (!info->attrs[HWSIM_ATTR_ADDR_TRANSMITTER] ||
+ !info->attrs[HWSIM_ATTR_FLAGS] ||
+ !info->attrs[HWSIM_ATTR_COOKIE] ||
+ !info->attrs[HWSIM_ATTR_TX_INFO])
+ goto out;
+
+ src = (struct mac_address *)nla_data(
+ info->attrs[HWSIM_ATTR_ADDR_TRANSMITTER]);
+ hwsim_flags = nla_get_u32(info->attrs[HWSIM_ATTR_FLAGS]);
+
+ ret_skb = (struct sk_buff __user *)
+ (unsigned long) nla_get_u64(info->attrs[HWSIM_ATTR_COOKIE]);
+
+ data2 = get_hwsim_data_ref_from_addr(src);
+
+ if (data2 == NULL)
+ goto out;
+
+ /* look for the skb matching the cookie passed back from user */
+ skb_queue_walk_safe(&data2->pending, skb, tmp) {
+ if (skb == ret_skb) {
+ skb_unlink(skb, &data2->pending);
+ found = true;
+ break;
+ }
+ }
+
+ /* not found */
+ if (!found)
+ goto out;
+
+ /* Tx info received because the frame was broadcasted on user space,
+ so we get all the necessary info: tx attempts and skb control buff */
+
+ tx_attempts = (struct hwsim_tx_rate *)nla_data(
+ info->attrs[HWSIM_ATTR_TX_INFO]);
+
+ /* now send back TX status */
+ txi = IEEE80211_SKB_CB(skb);
+
+ if (txi->control.vif)
+ hwsim_check_magic(txi->control.vif);
+ if (txi->control.sta)
+ hwsim_check_sta_magic(txi->control.sta);
+
+ ieee80211_tx_info_clear_status(txi);
+
+ for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
+ txi->status.rates[i].idx = tx_attempts[i].idx;
+ txi->status.rates[i].count = tx_attempts[i].count;
+ /*txi->status.rates[i].flags = 0;*/
+ }
+
+ txi->status.ack_signal = nla_get_u32(info->attrs[HWSIM_ATTR_SIGNAL]);
+
+ if (!(hwsim_flags & HWSIM_TX_CTL_NO_ACK) &&
+ (hwsim_flags & HWSIM_TX_STAT_ACK)) {
+ if (skb->len >= 16) {
+ hdr = (struct ieee80211_hdr *) skb->data;
+ mac80211_hwsim_monitor_ack(data2->hw, hdr->addr2);
+ }
+ }
+ ieee80211_tx_status_irqsafe(data2->hw, skb);
+ return 0;
+out:
+ return -EINVAL;
+
+}
+
+static int hwsim_cloned_frame_received_nl(struct sk_buff *skb_2,
+ struct genl_info *info)
+{
+
+ struct mac80211_hwsim_data *data2;
+ struct ieee80211_rx_status rx_status;
+ struct mac_address *dst;
+ int frame_data_len;
+ char *frame_data;
+ struct sk_buff *skb = NULL;
+
+ if (!info->attrs[HWSIM_ATTR_ADDR_RECEIVER] ||
+ !info->attrs[HWSIM_ATTR_FRAME] ||
+ !info->attrs[HWSIM_ATTR_RX_RATE] ||
+ !info->attrs[HWSIM_ATTR_SIGNAL])
+ goto out;
+
+ dst = (struct mac_address *)nla_data(
+ info->attrs[HWSIM_ATTR_ADDR_RECEIVER]);
+
+ frame_data_len = nla_len(info->attrs[HWSIM_ATTR_FRAME]);
+ frame_data = (char *)nla_data(info->attrs[HWSIM_ATTR_FRAME]);
+
+ /* Allocate new skb here */
+ skb = alloc_skb(frame_data_len, GFP_KERNEL);
+ if (skb == NULL)
+ goto err;
+
+ if (frame_data_len <= IEEE80211_MAX_DATA_LEN) {
+ /* Copy the data */
+ memcpy(skb_put(skb, frame_data_len), frame_data,
+ frame_data_len);
+ } else
+ goto err;
+
+ data2 = get_hwsim_data_ref_from_addr(dst);
+
+ if (data2 == NULL)
+ goto out;
+
+ /* check if radio is configured properly */
+
+ if (data2->idle || !data2->started || !data2->channel)
+ goto out;
+
+ /*A frame is received from user space*/
+ memset(&rx_status, 0, sizeof(rx_status));
+ rx_status.freq = data2->channel->center_freq;
+ rx_status.band = data2->channel->band;
+ rx_status.rate_idx = nla_get_u32(info->attrs[HWSIM_ATTR_RX_RATE]);
+ rx_status.signal = nla_get_u32(info->attrs[HWSIM_ATTR_SIGNAL]);
+
+ memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status));
+ ieee80211_rx_irqsafe(data2->hw, skb);
+
+ return 0;
+err:
+ printk(KERN_DEBUG "mac80211_hwsim: error occured in %s\n", __func__);
+ goto out;
+out:
+ dev_kfree_skb(skb);
+ return -EINVAL;
+}
+
+static int hwsim_register_received_nl(struct sk_buff *skb_2,
+ struct genl_info *info)
+{
+ if (info == NULL)
+ goto out;
+
+ wmediumd_pid = info->snd_pid;
+
+ printk(KERN_DEBUG "mac80211_hwsim: received a REGISTER, "
+ "switching to wmediumd mode with pid %d\n", info->snd_pid);
+
+ return 0;
+out:
+ printk(KERN_DEBUG "mac80211_hwsim: error occured in %s\n", __func__);
+ return -EINVAL;
+}
+
+/* Generic Netlink operations array */
+static struct genl_ops hwsim_ops[] = {
+ {
+ .cmd = HWSIM_CMD_REGISTER,
+ .policy = hwsim_genl_policy,
+ .doit = hwsim_register_received_nl,
+ .flags = GENL_ADMIN_PERM,
+ },
+ {
+ .cmd = HWSIM_CMD_FRAME,
+ .policy = hwsim_genl_policy,
+ .doit = hwsim_cloned_frame_received_nl,
+ },
+ {
+ .cmd = HWSIM_CMD_TX_INFO_FRAME,
+ .policy = hwsim_genl_policy,
+ .doit = hwsim_tx_info_frame_received_nl,
+ },
+};
+
+static int mac80211_hwsim_netlink_notify(struct notifier_block *nb,
+ unsigned long state,
+ void *_notify)
+{
+ struct netlink_notify *notify = _notify;
+
+ if (state != NETLINK_URELEASE)
+ return NOTIFY_DONE;
+
+ if (notify->pid == wmediumd_pid) {
+ printk(KERN_INFO "mac80211_hwsim: wmediumd released netlink"
+ " socket, switching to perfect channel medium\n");
+ wmediumd_pid = 0;
+ }
+ return NOTIFY_DONE;
+
+}
+
+static struct notifier_block hwsim_netlink_notifier = {
+ .notifier_call = mac80211_hwsim_netlink_notify,
+};
+
+static int hwsim_init_netlink(void)
+{
+ int rc;
+ printk(KERN_INFO "mac80211_hwsim: initializing netlink\n");
+
+ wmediumd_pid = 0;
+
+ rc = genl_register_family_with_ops(&hwsim_genl_family,
+ hwsim_ops, ARRAY_SIZE(hwsim_ops));
+ if (rc)
+ goto failure;
+
+ rc = netlink_register_notifier(&hwsim_netlink_notifier);
+ if (rc)
+ goto failure;
+
+ return 0;
+
+failure:
+ printk(KERN_DEBUG "mac80211_hwsim: error occured in %s\n", __func__);
+ return -EINVAL;
+}
+
+static void hwsim_exit_netlink(void)
+{
+ int ret;
+
+ printk(KERN_INFO "mac80211_hwsim: closing netlink\n");
+ /* unregister the notifier */
+ netlink_unregister_notifier(&hwsim_netlink_notifier);
+ /* unregister the family */
+ ret = genl_unregister_family(&hwsim_genl_family);
+ if (ret)
+ printk(KERN_DEBUG "mac80211_hwsim: "
+ "unregister family %i\n", ret);
+}
+
static int __init init_mac80211_hwsim(void)
{
int i, err = 0;
@@ -1298,6 +1708,7 @@
goto failed_drvdata;
}
data->dev->driver = &mac80211_hwsim_driver;
+ skb_queue_head_init(&data->pending);
SET_IEEE80211_DEV(hw, data->dev);
addr[3] = i >> 8;
@@ -1379,6 +1790,10 @@
data->group = 1;
mutex_init(&data->mutex);
+ /* Enable frame retransmissions for lossy channels */
+ hw->max_rates = 4;
+ hw->max_rate_tries = 11;
+
/* Work to be done prior to ieee80211_register_hw() */
switch (regtest) {
case HWSIM_REGTEST_DISABLED:
@@ -1515,12 +1930,29 @@
if (hwsim_mon == NULL)
goto failed;
- err = register_netdev(hwsim_mon);
+ rtnl_lock();
+
+ err = dev_alloc_name(hwsim_mon, hwsim_mon->name);
if (err < 0)
goto failed_mon;
+
+ err = register_netdevice(hwsim_mon);
+ if (err < 0)
+ goto failed_mon;
+
+ rtnl_unlock();
+
+ err = hwsim_init_netlink();
+ if (err < 0)
+ goto failed_nl;
+
return 0;
+failed_nl:
+ printk(KERN_DEBUG "mac_80211_hwsim: failed initializing netlink\n");
+ return err;
+
failed_mon:
rtnl_unlock();
free_netdev(hwsim_mon);
@@ -1541,6 +1973,8 @@
{
printk(KERN_DEBUG "mac80211_hwsim: unregister radios\n");
+ hwsim_exit_netlink();
+
mac80211_hwsim_free();
unregister_netdev(hwsim_mon);
}
diff --git a/drivers/net/wireless/mac80211_hwsim.h b/drivers/net/wireless/mac80211_hwsim.h
new file mode 100644
index 0000000..afaad5a
--- /dev/null
+++ b/drivers/net/wireless/mac80211_hwsim.h
@@ -0,0 +1,133 @@
+/*
+ * mac80211_hwsim - software simulator of 802.11 radio(s) for mac80211
+ * Copyright (c) 2008, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2011, Javier Lopez <jlopex@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __MAC80211_HWSIM_H
+#define __MAC80211_HWSIM_H
+
+/**
+ * enum hwsim_tx_control_flags - flags to describe transmission info/status
+ *
+ * These flags are used to give the wmediumd extra information in order to
+ * modify its behavior for each frame
+ *
+ * @HWSIM_TX_CTL_REQ_TX_STATUS: require TX status callback for this frame.
+ * @HWSIM_TX_CTL_NO_ACK: tell the wmediumd not to wait for an ack
+ * @HWSIM_TX_STAT_ACK: Frame was acknowledged
+ *
+ */
+enum hwsim_tx_control_flags {
+ HWSIM_TX_CTL_REQ_TX_STATUS = BIT(0),
+ HWSIM_TX_CTL_NO_ACK = BIT(1),
+ HWSIM_TX_STAT_ACK = BIT(2),
+};
+
+/**
+ * DOC: Frame transmission/registration support
+ *
+ * Frame transmission and registration support exists to allow userspace
+ * entities such as wmediumd to receive and process all broadcasted
+ * frames from a mac80211_hwsim radio device.
+ *
+ * This allow user space applications to decide if the frame should be
+ * dropped or not and implement a wireless medium simulator at user space.
+ *
+ * Registration is done by sending a register message to the driver and
+ * will be automatically unregistered if the user application doesn't
+ * responds to sent frames.
+ * Once registered the user application has to take responsibility of
+ * broadcasting the frames to all listening mac80211_hwsim radio
+ * interfaces.
+ *
+ * For more technical details, see the corresponding command descriptions
+ * below.
+ */
+
+/**
+ * enum hwsim_commands - supported hwsim commands
+ *
+ * @HWSIM_CMD_UNSPEC: unspecified command to catch errors
+ *
+ * @HWSIM_CMD_REGISTER: request to register and received all broadcasted
+ * frames by any mac80211_hwsim radio device.
+ * @HWSIM_CMD_FRAME: send/receive a broadcasted frame from/to kernel/user
+ * space, uses:
+ * %HWSIM_ATTR_ADDR_TRANSMITTER, %HWSIM_ATTR_ADDR_RECEIVER,
+ * %HWSIM_ATTR_FRAME, %HWSIM_ATTR_FLAGS, %HWSIM_ATTR_RX_RATE,
+ * %HWSIM_ATTR_SIGNAL, %HWSIM_ATTR_COOKIE
+ * @HWSIM_CMD_TX_INFO_FRAME: Transmission info report from user space to
+ * kernel, uses:
+ * %HWSIM_ATTR_ADDR_TRANSMITTER, %HWSIM_ATTR_FLAGS,
+ * %HWSIM_ATTR_TX_INFO, %HWSIM_ATTR_SIGNAL, %HWSIM_ATTR_COOKIE
+ * @__HWSIM_CMD_MAX: enum limit
+ */
+enum {
+ HWSIM_CMD_UNSPEC,
+ HWSIM_CMD_REGISTER,
+ HWSIM_CMD_FRAME,
+ HWSIM_CMD_TX_INFO_FRAME,
+ __HWSIM_CMD_MAX,
+};
+#define HWSIM_CMD_MAX (_HWSIM_CMD_MAX - 1)
+
+/**
+ * enum hwsim_attrs - hwsim netlink attributes
+ *
+ * @HWSIM_ATTR_UNSPEC: unspecified attribute to catch errors
+ *
+ * @HWSIM_ATTR_ADDR_RECEIVER: MAC address of the radio device that
+ * the frame is broadcasted to
+ * @HWSIM_ATTR_ADDR_TRANSMITTER: MAC address of the radio device that
+ * the frame was broadcasted from
+ * @HWSIM_ATTR_FRAME: Data array
+ * @HWSIM_ATTR_FLAGS: mac80211 transmission flags, used to process
+ properly the frame at user space
+ * @HWSIM_ATTR_RX_RATE: estimated rx rate index for this frame at user
+ space
+ * @HWSIM_ATTR_SIGNAL: estimated RX signal for this frame at user
+ space
+ * @HWSIM_ATTR_TX_INFO: ieee80211_tx_rate array
+ * @HWSIM_ATTR_COOKIE: sk_buff cookie to identify the frame
+ * @__HWSIM_ATTR_MAX: enum limit
+ */
+
+
+enum {
+ HWSIM_ATTR_UNSPEC,
+ HWSIM_ATTR_ADDR_RECEIVER,
+ HWSIM_ATTR_ADDR_TRANSMITTER,
+ HWSIM_ATTR_FRAME,
+ HWSIM_ATTR_FLAGS,
+ HWSIM_ATTR_RX_RATE,
+ HWSIM_ATTR_SIGNAL,
+ HWSIM_ATTR_TX_INFO,
+ HWSIM_ATTR_COOKIE,
+ __HWSIM_ATTR_MAX,
+};
+#define HWSIM_ATTR_MAX (__HWSIM_ATTR_MAX - 1)
+
+/**
+ * struct hwsim_tx_rate - rate selection/status
+ *
+ * @idx: rate index to attempt to send with
+ * @count: number of tries in this rate before going to the next rate
+ *
+ * A value of -1 for @idx indicates an invalid rate and, if used
+ * in an array of retry rates, that no more rates should be tried.
+ *
+ * When used for transmit status reporting, the driver should
+ * always report the rate and number of retries used.
+ *
+ */
+struct hwsim_tx_rate {
+ s8 idx;
+ u8 count;
+} __packed;
+
+#endif /* __MAC80211_HWSIM_H */
diff --git a/drivers/net/wireless/mwifiex/11n.c b/drivers/net/wireless/mwifiex/11n.c
index 916183d..34bba52 100644
--- a/drivers/net/wireless/mwifiex/11n.c
+++ b/drivers/net/wireless/mwifiex/11n.c
@@ -185,13 +185,12 @@
*
* Handling includes changing the header fields into CPU format.
*/
-int mwifiex_ret_11n_cfg(struct host_cmd_ds_command *resp, void *data_buf)
+int mwifiex_ret_11n_cfg(struct host_cmd_ds_command *resp,
+ struct mwifiex_ds_11n_tx_cfg *tx_cfg)
{
- struct mwifiex_ds_11n_tx_cfg *tx_cfg;
struct host_cmd_ds_11n_cfg *htcfg = &resp->params.htcfg;
- if (data_buf) {
- tx_cfg = (struct mwifiex_ds_11n_tx_cfg *) data_buf;
+ if (tx_cfg) {
tx_cfg->tx_htcap = le16_to_cpu(htcfg->ht_tx_cap);
tx_cfg->tx_htinfo = le16_to_cpu(htcfg->ht_tx_info);
}
@@ -208,11 +207,10 @@
*/
int mwifiex_cmd_recfg_tx_buf(struct mwifiex_private *priv,
struct host_cmd_ds_command *cmd, int cmd_action,
- void *data_buf)
+ u16 *buf_size)
{
struct host_cmd_ds_txbuf_cfg *tx_buf = &cmd->params.tx_buf;
u16 action = (u16) cmd_action;
- u16 buf_size = *((u16 *) data_buf);
cmd->command = cpu_to_le16(HostCmd_CMD_RECONFIGURE_TX_BUFF);
cmd->size =
@@ -220,8 +218,8 @@
tx_buf->action = cpu_to_le16(action);
switch (action) {
case HostCmd_ACT_GEN_SET:
- dev_dbg(priv->adapter->dev, "cmd: set tx_buf=%d\n", buf_size);
- tx_buf->buff_size = cpu_to_le16(buf_size);
+ dev_dbg(priv->adapter->dev, "cmd: set tx_buf=%d\n", *buf_size);
+ tx_buf->buff_size = cpu_to_le16(*buf_size);
break;
case HostCmd_ACT_GEN_GET:
default:
@@ -240,13 +238,12 @@
* - Ensuring correct endian-ness
*/
int mwifiex_cmd_amsdu_aggr_ctrl(struct host_cmd_ds_command *cmd,
- int cmd_action, void *data_buf)
+ int cmd_action,
+ struct mwifiex_ds_11n_amsdu_aggr_ctrl *aa_ctrl)
{
struct host_cmd_ds_amsdu_aggr_ctrl *amsdu_ctrl =
&cmd->params.amsdu_aggr_ctrl;
u16 action = (u16) cmd_action;
- struct mwifiex_ds_11n_amsdu_aggr_ctrl *aa_ctrl =
- (struct mwifiex_ds_11n_amsdu_aggr_ctrl *) data_buf;
cmd->command = cpu_to_le16(HostCmd_CMD_AMSDU_AGGR_CTRL);
cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_amsdu_aggr_ctrl)
@@ -272,15 +269,13 @@
* Handling includes changing the header fields into CPU format.
*/
int mwifiex_ret_amsdu_aggr_ctrl(struct host_cmd_ds_command *resp,
- void *data_buf)
+ struct mwifiex_ds_11n_amsdu_aggr_ctrl
+ *amsdu_aggr_ctrl)
{
- struct mwifiex_ds_11n_amsdu_aggr_ctrl *amsdu_aggr_ctrl;
struct host_cmd_ds_amsdu_aggr_ctrl *amsdu_ctrl =
&resp->params.amsdu_aggr_ctrl;
- if (data_buf) {
- amsdu_aggr_ctrl =
- (struct mwifiex_ds_11n_amsdu_aggr_ctrl *) data_buf;
+ if (amsdu_aggr_ctrl) {
amsdu_aggr_ctrl->enable = le16_to_cpu(amsdu_ctrl->enable);
amsdu_aggr_ctrl->curr_buf_size =
le16_to_cpu(amsdu_ctrl->curr_buf_size);
@@ -296,12 +291,10 @@
* - Setting HT Tx capability and HT Tx information fields
* - Ensuring correct endian-ness
*/
-int mwifiex_cmd_11n_cfg(struct host_cmd_ds_command *cmd,
- u16 cmd_action, void *data_buf)
+int mwifiex_cmd_11n_cfg(struct host_cmd_ds_command *cmd, u16 cmd_action,
+ struct mwifiex_ds_11n_tx_cfg *txcfg)
{
struct host_cmd_ds_11n_cfg *htcfg = &cmd->params.htcfg;
- struct mwifiex_ds_11n_tx_cfg *txcfg =
- (struct mwifiex_ds_11n_tx_cfg *) data_buf;
cmd->command = cpu_to_le16(HostCmd_CMD_11N_CFG);
cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_11n_cfg) + S_DS_GEN);
diff --git a/drivers/net/wireless/mwifiex/11n.h b/drivers/net/wireless/mwifiex/11n.h
index a4390a1..90b421e 100644
--- a/drivers/net/wireless/mwifiex/11n.h
+++ b/drivers/net/wireless/mwifiex/11n.h
@@ -29,9 +29,9 @@
int mwifiex_ret_11n_addba_req(struct mwifiex_private *priv,
struct host_cmd_ds_command *resp);
int mwifiex_ret_11n_cfg(struct host_cmd_ds_command *resp,
- void *data_buf);
-int mwifiex_cmd_11n_cfg(struct host_cmd_ds_command *cmd,
- u16 cmd_action, void *data_buf);
+ struct mwifiex_ds_11n_tx_cfg *tx_cfg);
+int mwifiex_cmd_11n_cfg(struct host_cmd_ds_command *cmd, u16 cmd_action,
+ struct mwifiex_ds_11n_tx_cfg *txcfg);
int mwifiex_cmd_append_11n_tlv(struct mwifiex_private *priv,
struct mwifiex_bssdescriptor *bss_desc,
@@ -62,12 +62,14 @@
int mwifiex_get_tx_ba_stream_tbl(struct mwifiex_private *priv,
struct mwifiex_ds_tx_ba_stream_tbl *buf);
int mwifiex_ret_amsdu_aggr_ctrl(struct host_cmd_ds_command *resp,
- void *data_buf);
+ struct mwifiex_ds_11n_amsdu_aggr_ctrl
+ *amsdu_aggr_ctrl);
int mwifiex_cmd_recfg_tx_buf(struct mwifiex_private *priv,
struct host_cmd_ds_command *cmd,
- int cmd_action, void *data_buf);
+ int cmd_action, u16 *buf_size);
int mwifiex_cmd_amsdu_aggr_ctrl(struct host_cmd_ds_command *cmd,
- int cmd_action, void *data_buf);
+ int cmd_action,
+ struct mwifiex_ds_11n_amsdu_aggr_ctrl *aa_ctrl);
/*
* This function checks whether AMPDU is allowed or not for a particular TID.
diff --git a/drivers/net/wireless/mwifiex/11n_aggr.c b/drivers/net/wireless/mwifiex/11n_aggr.c
index f807447..1a453a6 100644
--- a/drivers/net/wireless/mwifiex/11n_aggr.c
+++ b/drivers/net/wireless/mwifiex/11n_aggr.c
@@ -164,12 +164,13 @@
struct mwifiex_tx_param tx_param;
struct txpd *ptx_pd = NULL;
- if (skb_queue_empty(&pra_list->skb_head)) {
+ skb_src = skb_peek(&pra_list->skb_head);
+ if (!skb_src) {
spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
ra_list_flags);
return 0;
}
- skb_src = skb_peek(&pra_list->skb_head);
+
tx_info_src = MWIFIEX_SKB_TXCB(skb_src);
skb_aggr = dev_alloc_skb(adapter->tx_buf_size);
if (!skb_aggr) {
@@ -184,17 +185,15 @@
tx_info_aggr->bss_index = tx_info_src->bss_index;
skb_aggr->priority = skb_src->priority;
- while (skb_src && ((skb_headroom(skb_aggr) + skb_src->len
- + LLC_SNAP_LEN)
- <= adapter->tx_buf_size)) {
+ do {
+ /* Check if AMSDU can accommodate this MSDU */
+ if (skb_tailroom(skb_aggr) < (skb_src->len + LLC_SNAP_LEN))
+ break;
- if (!skb_queue_empty(&pra_list->skb_head))
- skb_src = skb_dequeue(&pra_list->skb_head);
- else
- skb_src = NULL;
+ skb_src = skb_dequeue(&pra_list->skb_head);
- if (skb_src)
- pra_list->total_pkts_size -= skb_src->len;
+ pra_list->total_pkts_size -= skb_src->len;
+ pra_list->total_pkts--;
atomic_dec(&priv->wmm.tx_pkts_queued);
@@ -212,11 +211,15 @@
return -1;
}
- if (!skb_queue_empty(&pra_list->skb_head))
- skb_src = skb_peek(&pra_list->skb_head);
- else
- skb_src = NULL;
- }
+ if (skb_tailroom(skb_aggr) < pad) {
+ pad = 0;
+ break;
+ }
+ skb_put(skb_aggr, pad);
+
+ skb_src = skb_peek(&pra_list->skb_head);
+
+ } while (skb_src);
spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, ra_list_flags);
@@ -230,11 +233,19 @@
skb_push(skb_aggr, headroom);
- tx_param.next_pkt_len = ((pra_list->total_pkts_size) ?
- (((pra_list->total_pkts_size) >
- adapter->tx_buf_size) ? adapter->
- tx_buf_size : pra_list->total_pkts_size +
- LLC_SNAP_LEN + sizeof(struct txpd)) : 0);
+ /*
+ * Padding per MSDU will affect the length of next
+ * packet and hence the exact length of next packet
+ * is uncertain here.
+ *
+ * Also, aggregation of transmission buffer, while
+ * downloading the data to the card, wont gain much
+ * on the AMSDU packets as the AMSDU packets utilizes
+ * the transmission buffer space to the maximum
+ * (adapter->tx_buf_size).
+ */
+ tx_param.next_pkt_len = 0;
+
ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_TYPE_DATA,
skb_aggr->data,
skb_aggr->len, &tx_param);
@@ -258,6 +269,7 @@
skb_queue_tail(&pra_list->skb_head, skb_aggr);
pra_list->total_pkts_size += skb_aggr->len;
+ pra_list->total_pkts++;
atomic_inc(&priv->wmm.tx_pkts_queued);
diff --git a/drivers/net/wireless/mwifiex/11n_rxreorder.c b/drivers/net/wireless/mwifiex/11n_rxreorder.c
index e5dfdc3..7aa9aa0 100644
--- a/drivers/net/wireless/mwifiex/11n_rxreorder.c
+++ b/drivers/net/wireless/mwifiex/11n_rxreorder.c
@@ -328,13 +328,12 @@
*/
int mwifiex_cmd_11n_addba_rsp_gen(struct mwifiex_private *priv,
struct host_cmd_ds_command *cmd,
- void *data_buf)
+ struct host_cmd_ds_11n_addba_req
+ *cmd_addba_req)
{
struct host_cmd_ds_11n_addba_rsp *add_ba_rsp =
(struct host_cmd_ds_11n_addba_rsp *)
&cmd->params.add_ba_rsp;
- struct host_cmd_ds_11n_addba_req *cmd_addba_req =
- (struct host_cmd_ds_11n_addba_req *) data_buf;
u8 tid;
int win_size;
uint16_t block_ack_param_set;
diff --git a/drivers/net/wireless/mwifiex/11n_rxreorder.h b/drivers/net/wireless/mwifiex/11n_rxreorder.h
index f3ca8c8..033c8ad 100644
--- a/drivers/net/wireless/mwifiex/11n_rxreorder.h
+++ b/drivers/net/wireless/mwifiex/11n_rxreorder.h
@@ -52,8 +52,9 @@
int mwifiex_cmd_11n_delba(struct host_cmd_ds_command *cmd,
void *data_buf);
int mwifiex_cmd_11n_addba_rsp_gen(struct mwifiex_private *priv,
- struct host_cmd_ds_command
- *cmd, void *data_buf);
+ struct host_cmd_ds_command *cmd,
+ struct host_cmd_ds_11n_addba_req
+ *cmd_addba_req);
int mwifiex_cmd_11n_addba_req(struct host_cmd_ds_command *cmd,
void *data_buf);
void mwifiex_11n_cleanup_reorder_tbl(struct mwifiex_private *priv);
diff --git a/drivers/net/wireless/mwifiex/cmdevt.c b/drivers/net/wireless/mwifiex/cmdevt.c
index cd89fed..b5352af 100644
--- a/drivers/net/wireless/mwifiex/cmdevt.c
+++ b/drivers/net/wireless/mwifiex/cmdevt.c
@@ -104,13 +104,11 @@
* main thread.
*/
static int mwifiex_cmd_host_cmd(struct mwifiex_private *priv,
- struct host_cmd_ds_command *cmd, void *data_buf)
+ struct host_cmd_ds_command *cmd,
+ struct mwifiex_ds_misc_cmd *pcmd_ptr)
{
- struct mwifiex_ds_misc_cmd *pcmd_ptr =
- (struct mwifiex_ds_misc_cmd *) data_buf;
-
/* Copy the HOST command to command buffer */
- memcpy((void *) cmd, pcmd_ptr->cmd, pcmd_ptr->len);
+ memcpy(cmd, pcmd_ptr->cmd, pcmd_ptr->len);
dev_dbg(priv->adapter->dev, "cmd: host cmd size = %d\n", pcmd_ptr->len);
return 0;
}
@@ -707,15 +705,14 @@
if (adapter->curr_cmd->cmd_flag & CMD_F_HOSTCMD) {
/* Copy original response back to response buffer */
- struct mwifiex_ds_misc_cmd *hostcmd = NULL;
+ struct mwifiex_ds_misc_cmd *hostcmd;
uint16_t size = le16_to_cpu(resp->size);
dev_dbg(adapter->dev, "info: host cmd resp size = %d\n", size);
size = min_t(u16, size, MWIFIEX_SIZE_OF_CMD_BUFFER);
if (adapter->curr_cmd->data_buf) {
- hostcmd = (struct mwifiex_ds_misc_cmd *)
- adapter->curr_cmd->data_buf;
+ hostcmd = adapter->curr_cmd->data_buf;
hostcmd->len = size;
- memcpy(hostcmd->cmd, (void *) resp, size);
+ memcpy(hostcmd->cmd, resp, size);
}
}
orig_cmdresp_no = le16_to_cpu(resp->command);
@@ -1155,7 +1152,7 @@
int mwifiex_cmd_enh_power_mode(struct mwifiex_private *priv,
struct host_cmd_ds_command *cmd,
u16 cmd_action, uint16_t ps_bitmap,
- void *data_buf)
+ struct mwifiex_ds_auto_ds *auto_ds)
{
struct host_cmd_ds_802_11_ps_mode_enh *psmode_enh =
&cmd->params.psmode_enh;
@@ -1218,9 +1215,8 @@
sizeof(struct mwifiex_ie_types_header));
cmd_size += sizeof(*auto_ds_tlv);
tlv += sizeof(*auto_ds_tlv);
- if (data_buf)
- idletime = ((struct mwifiex_ds_auto_ds *)
- data_buf)->idle_time;
+ if (auto_ds)
+ idletime = auto_ds->idle_time;
dev_dbg(priv->adapter->dev,
"cmd: PS Command: Enter Auto Deep Sleep\n");
auto_ds_tlv->deep_sleep_timeout = cpu_to_le16(idletime);
@@ -1239,7 +1235,7 @@
*/
int mwifiex_ret_enh_power_mode(struct mwifiex_private *priv,
struct host_cmd_ds_command *resp,
- void *data_buf)
+ struct mwifiex_ds_pm_cfg *pm_cfg)
{
struct mwifiex_adapter *adapter = priv->adapter;
struct host_cmd_ds_802_11_ps_mode_enh *ps_mode =
@@ -1282,10 +1278,8 @@
dev_dbg(adapter->dev, "cmd: ps_bitmap=%#x\n", ps_bitmap);
- if (data_buf) {
+ if (pm_cfg) {
/* This section is for get power save mode */
- struct mwifiex_ds_pm_cfg *pm_cfg =
- (struct mwifiex_ds_pm_cfg *)data_buf;
if (ps_bitmap & BITMAP_STA_PS)
pm_cfg->param.ps_mode = 1;
else
diff --git a/drivers/net/wireless/mwifiex/join.c b/drivers/net/wireless/mwifiex/join.c
index 5eab3dc..644e2e40 100644
--- a/drivers/net/wireless/mwifiex/join.c
+++ b/drivers/net/wireless/mwifiex/join.c
@@ -364,10 +364,9 @@
*/
int mwifiex_cmd_802_11_associate(struct mwifiex_private *priv,
struct host_cmd_ds_command *cmd,
- void *data_buf)
+ struct mwifiex_bssdescriptor *bss_desc)
{
struct host_cmd_ds_802_11_associate *assoc = &cmd->params.associate;
- struct mwifiex_bssdescriptor *bss_desc;
struct mwifiex_ie_types_ssid_param_set *ssid_tlv;
struct mwifiex_ie_types_phy_param_set *phy_tlv;
struct mwifiex_ie_types_ss_param_set *ss_tlv;
@@ -380,7 +379,6 @@
u8 *pos;
int rsn_ie_len = 0;
- bss_desc = (struct mwifiex_bssdescriptor *) data_buf;
pos = (u8 *) assoc;
mwifiex_cfg_tx_buf(priv, bss_desc);
@@ -748,7 +746,8 @@
*/
int
mwifiex_cmd_802_11_ad_hoc_start(struct mwifiex_private *priv,
- struct host_cmd_ds_command *cmd, void *data_buf)
+ struct host_cmd_ds_command *cmd,
+ struct mwifiex_802_11_ssid *req_ssid)
{
int rsn_ie_len = 0;
struct mwifiex_adapter *adapter = priv->adapter;
@@ -786,20 +785,15 @@
memset(adhoc_start->ssid, 0, IEEE80211_MAX_SSID_LEN);
- memcpy(adhoc_start->ssid,
- ((struct mwifiex_802_11_ssid *) data_buf)->ssid,
- ((struct mwifiex_802_11_ssid *) data_buf)->ssid_len);
+ memcpy(adhoc_start->ssid, req_ssid->ssid, req_ssid->ssid_len);
dev_dbg(adapter->dev, "info: ADHOC_S_CMD: SSID = %s\n",
adhoc_start->ssid);
memset(bss_desc->ssid.ssid, 0, IEEE80211_MAX_SSID_LEN);
- memcpy(bss_desc->ssid.ssid,
- ((struct mwifiex_802_11_ssid *) data_buf)->ssid,
- ((struct mwifiex_802_11_ssid *) data_buf)->ssid_len);
+ memcpy(bss_desc->ssid.ssid, req_ssid->ssid, req_ssid->ssid_len);
- bss_desc->ssid.ssid_len =
- ((struct mwifiex_802_11_ssid *) data_buf)->ssid_len;
+ bss_desc->ssid.ssid_len = req_ssid->ssid_len;
/* Set the BSS mode */
adhoc_start->bss_mode = HostCmd_BSS_MODE_IBSS;
@@ -1036,13 +1030,12 @@
*/
int
mwifiex_cmd_802_11_ad_hoc_join(struct mwifiex_private *priv,
- struct host_cmd_ds_command *cmd, void *data_buf)
+ struct host_cmd_ds_command *cmd,
+ struct mwifiex_bssdescriptor *bss_desc)
{
int rsn_ie_len = 0;
struct host_cmd_ds_802_11_ad_hoc_join *adhoc_join =
&cmd->params.adhoc_join;
- struct mwifiex_bssdescriptor *bss_desc =
- (struct mwifiex_bssdescriptor *) data_buf;
struct mwifiex_ie_types_chan_list_param_set *chan_tlv;
u32 cmd_append_size = 0;
u16 tmp_cap;
diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c
index f058225..e5fc53d 100644
--- a/drivers/net/wireless/mwifiex/main.c
+++ b/drivers/net/wireless/mwifiex/main.c
@@ -26,17 +26,12 @@
const char driver_version[] = "mwifiex " VERSION " (%s) ";
-struct mwifiex_adapter *g_adapter;
-EXPORT_SYMBOL_GPL(g_adapter);
-
static struct mwifiex_bss_attr mwifiex_bss_sta[] = {
{MWIFIEX_BSS_TYPE_STA, MWIFIEX_DATA_FRAME_TYPE_ETH_II, true, 0, 0},
};
static int drv_mode = DRV_MODE_STA;
-static char fw_name[32] = DEFAULT_FW_NAME;
-
/* Supported drv_mode table */
static struct mwifiex_drv_mode mwifiex_drv_mode_tbl[] = {
{
@@ -62,7 +57,8 @@
* proper cleanup before exiting.
*/
static int mwifiex_register(void *card, struct mwifiex_if_ops *if_ops,
- struct mwifiex_drv_mode *drv_mode_ptr)
+ struct mwifiex_drv_mode *drv_mode_ptr,
+ void **padapter)
{
struct mwifiex_adapter *adapter;
int i;
@@ -71,7 +67,7 @@
if (!adapter)
return -ENOMEM;
- g_adapter = adapter;
+ *padapter = adapter;
adapter->card = card;
/* Save interface specific operations in adapter */
@@ -326,7 +322,7 @@
* and initializing the private structures.
*/
static int
-mwifiex_init_sw(void *card, struct mwifiex_if_ops *if_ops)
+mwifiex_init_sw(void *card, struct mwifiex_if_ops *if_ops, void **padapter)
{
int i;
struct mwifiex_drv_mode *drv_mode_ptr;
@@ -345,7 +341,7 @@
return -1;
}
- if (mwifiex_register(card, if_ops, drv_mode_ptr))
+ if (mwifiex_register(card, if_ops, drv_mode_ptr, padapter))
return -1;
return 0;
@@ -384,20 +380,8 @@
memset(&fw, 0, sizeof(struct mwifiex_fw_image));
- switch (adapter->revision_id) {
- case SD8787_W0:
- case SD8787_W1:
- strcpy(fw_name, SD8787_W1_FW_NAME);
- break;
- case SD8787_A0:
- case SD8787_A1:
- strcpy(fw_name, SD8787_AX_FW_NAME);
- break;
- default:
- break;
- }
-
- err = request_firmware(&adapter->firmware, fw_name, adapter->dev);
+ err = request_firmware(&adapter->firmware, adapter->fw_name,
+ adapter->dev);
if (err < 0) {
dev_err(adapter->dev, "request_firmware() returned"
" error code %#x\n", err);
@@ -569,7 +553,7 @@
mwifiex_set_mac_address(struct net_device *dev, void *addr)
{
struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
- struct sockaddr *hw_addr = (struct sockaddr *) addr;
+ struct sockaddr *hw_addr = addr;
int ret;
memcpy(priv->curr_addr, hw_addr->sa_data, ETH_ALEN);
@@ -869,13 +853,11 @@
if (down_interruptible(sem))
goto exit_sem_err;
- if (mwifiex_init_sw(card, if_ops)) {
+ if (mwifiex_init_sw(card, if_ops, (void **)&adapter)) {
pr_err("%s: software init failed\n", __func__);
goto err_init_sw;
}
- adapter = g_adapter;
-
adapter->hw_status = MWIFIEX_HW_STATUS_INITIALIZING;
adapter->surprise_removed = false;
init_waitqueue_head(&adapter->init_wait_q);
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h
index 8316b3c..03691c0 100644
--- a/drivers/net/wireless/mwifiex/main.h
+++ b/drivers/net/wireless/mwifiex/main.h
@@ -39,7 +39,6 @@
#include "fw.h"
extern const char driver_version[];
-extern struct mwifiex_adapter *g_adapter;
enum {
MWIFIEX_ASYNC_CMD,
@@ -48,15 +47,6 @@
#define DRV_MODE_STA 0x1
-#define SD8787_W0 0x30
-#define SD8787_W1 0x31
-#define SD8787_A0 0x40
-#define SD8787_A1 0x41
-
-#define DEFAULT_FW_NAME "mrvl/sd8787_uapsta.bin"
-#define SD8787_W1_FW_NAME "mrvl/sd8787_uapsta_w1.bin"
-#define SD8787_AX_FW_NAME "mrvl/sd8787_uapsta.bin"
-
struct mwifiex_drv_mode {
u16 drv_mode;
u16 intf_num;
@@ -190,6 +180,7 @@
struct sk_buff_head skb_head;
u8 ra[ETH_ALEN];
u32 total_pkts_size;
+ u32 total_pkts;
u32 is_11n_enabled;
};
@@ -576,10 +567,10 @@
u8 priv_num;
struct mwifiex_drv_mode *drv_mode;
const struct firmware *firmware;
+ char fw_name[32];
struct device *dev;
bool surprise_removed;
u32 fw_release_number;
- u32 revision_id;
u16 init_wait_q_woken;
wait_queue_head_t init_wait_q;
void *card;
@@ -745,10 +736,10 @@
int mwifiex_cmd_enh_power_mode(struct mwifiex_private *priv,
struct host_cmd_ds_command *cmd,
u16 cmd_action, uint16_t ps_bitmap,
- void *data_buf);
+ struct mwifiex_ds_auto_ds *auto_ds);
int mwifiex_ret_enh_power_mode(struct mwifiex_private *priv,
struct host_cmd_ds_command *resp,
- void *data_buf);
+ struct mwifiex_ds_pm_cfg *pm_cfg);
void mwifiex_process_hs_config(struct mwifiex_adapter *adapter);
void mwifiex_hs_activated_event(struct mwifiex_private *priv,
u8 activated);
@@ -760,7 +751,7 @@
u16 cmd_action, u32 cmd_oid,
void *data_buf, void *cmd_buf);
int mwifiex_process_sta_cmdresp(struct mwifiex_private *, u16 cmdresp_no,
- void *cmd_buf);
+ struct host_cmd_ds_command *resp);
int mwifiex_process_sta_rx_packet(struct mwifiex_adapter *,
struct sk_buff *skb);
int mwifiex_process_sta_event(struct mwifiex_private *);
@@ -769,7 +760,7 @@
int mwifiex_scan_networks(struct mwifiex_private *priv,
const struct mwifiex_user_scan_cfg *user_scan_in);
int mwifiex_cmd_802_11_scan(struct host_cmd_ds_command *cmd,
- void *data_buf);
+ struct mwifiex_scan_cmd_config *scan_cfg);
void mwifiex_queue_scan_cmd(struct mwifiex_private *priv,
struct cmd_ctrl_node *cmd_node);
int mwifiex_ret_802_11_scan(struct mwifiex_private *priv,
@@ -786,8 +777,8 @@
int mwifiex_associate(struct mwifiex_private *priv,
struct mwifiex_bssdescriptor *bss_desc);
int mwifiex_cmd_802_11_associate(struct mwifiex_private *priv,
- struct host_cmd_ds_command
- *cmd, void *data_buf);
+ struct host_cmd_ds_command *cmd,
+ struct mwifiex_bssdescriptor *bss_desc);
int mwifiex_ret_802_11_associate(struct mwifiex_private *priv,
struct host_cmd_ds_command *resp);
void mwifiex_reset_connect_state(struct mwifiex_private *priv);
@@ -800,10 +791,10 @@
struct mwifiex_bssdescriptor *bss_desc);
int mwifiex_cmd_802_11_ad_hoc_start(struct mwifiex_private *priv,
struct host_cmd_ds_command *cmd,
- void *data_buf);
+ struct mwifiex_802_11_ssid *req_ssid);
int mwifiex_cmd_802_11_ad_hoc_join(struct mwifiex_private *priv,
struct host_cmd_ds_command *cmd,
- void *data_buf);
+ struct mwifiex_bssdescriptor *bss_desc);
int mwifiex_ret_802_11_ad_hoc(struct mwifiex_private *priv,
struct host_cmd_ds_command *resp);
int mwifiex_cmd_802_11_bg_scan_query(struct host_cmd_ds_command *cmd);
diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c
index 5c22860..6f88c8a 100644
--- a/drivers/net/wireless/mwifiex/scan.c
+++ b/drivers/net/wireless/mwifiex/scan.c
@@ -2357,12 +2357,10 @@
* - Setting command ID, and proper size
* - Ensuring correct endian-ness
*/
-int mwifiex_cmd_802_11_scan(struct host_cmd_ds_command *cmd, void *data_buf)
+int mwifiex_cmd_802_11_scan(struct host_cmd_ds_command *cmd,
+ struct mwifiex_scan_cmd_config *scan_cfg)
{
struct host_cmd_ds_802_11_scan *scan_cmd = &cmd->params.scan;
- struct mwifiex_scan_cmd_config *scan_cfg;
-
- scan_cfg = (struct mwifiex_scan_cmd_config *) data_buf;
/* Set fixed field variables in scan command */
scan_cmd->bss_mode = scan_cfg->bss_mode;
diff --git a/drivers/net/wireless/mwifiex/sdio.c b/drivers/net/wireless/mwifiex/sdio.c
index d425dbd..711fa68 100644
--- a/drivers/net/wireless/mwifiex/sdio.c
+++ b/drivers/net/wireless/mwifiex/sdio.c
@@ -31,10 +31,27 @@
#define SDIO_VERSION "1.0"
+/* The mwifiex_sdio_remove() callback function is called when
+ * user removes this module from kernel space or ejects
+ * the card from the slot. The driver handles these 2 cases
+ * differently.
+ * If the user is removing the module, the few commands (FUNC_SHUTDOWN,
+ * HS_CANCEL etc.) are sent to the firmware.
+ * If the card is removed, there is no need to send these command.
+ *
+ * The variable 'user_rmmod' is used to distinguish these two
+ * scenarios. This flag is initialized as FALSE in case the card
+ * is removed, and will be set to TRUE for module removal when
+ * module_exit function is called.
+ */
+static u8 user_rmmod;
+
static struct mwifiex_if_ops sdio_ops;
static struct semaphore add_remove_card_sem;
+static int mwifiex_sdio_resume(struct device *dev);
+
/*
* SDIO probe.
*
@@ -93,17 +110,36 @@
mwifiex_sdio_remove(struct sdio_func *func)
{
struct sdio_mmc_card *card;
+ struct mwifiex_adapter *adapter;
+ int i;
pr_debug("info: SDIO func num=%d\n", func->num);
- if (func) {
- card = sdio_get_drvdata(func);
- if (card) {
- mwifiex_remove_card(card->adapter,
- &add_remove_card_sem);
- kfree(card);
- }
+ card = sdio_get_drvdata(func);
+ if (!card)
+ return;
+
+ adapter = card->adapter;
+ if (!adapter || !adapter->priv_num)
+ return;
+
+ if (user_rmmod) {
+ if (adapter->is_suspended)
+ mwifiex_sdio_resume(adapter->dev);
+
+ for (i = 0; i < adapter->priv_num; i++)
+ if ((GET_BSS_ROLE(adapter->priv[i]) ==
+ MWIFIEX_BSS_ROLE_STA) &&
+ adapter->priv[i]->media_connected)
+ mwifiex_deauthenticate(adapter->priv[i], NULL);
+
+ mwifiex_init_shutdown_fw(mwifiex_get_priv(adapter,
+ MWIFIEX_BSS_ROLE_ANY),
+ MWIFIEX_FUNC_SHUTDOWN);
}
+
+ mwifiex_remove_card(card->adapter, &add_remove_card_sem);
+ kfree(card);
}
/*
@@ -1531,6 +1567,7 @@
sdio_set_drvdata(func, card);
adapter->dev = &func->dev;
+ strcpy(adapter->fw_name, SD8787_DEFAULT_FW_NAME);
return 0;
@@ -1552,7 +1589,6 @@
* the first interrupt got from bootloader
* - Disable host interrupt mask register
* - Get SDIO port
- * - Get revision ID
* - Initialize SDIO variables in card
* - Allocate MP registers
* - Allocate MPA Tx and Rx buffers
@@ -1576,10 +1612,6 @@
/* Get SDIO ioport */
mwifiex_init_sdio_ioport(adapter);
- /* Get revision ID */
-#define REV_ID_REG 0x5c
- mwifiex_read_reg(adapter, REV_ID_REG, &adapter->revision_id);
-
/* Initialize SDIO variables in card */
card->mp_rd_bitmap = 0;
card->mp_wr_bitmap = 0;
@@ -1700,6 +1732,9 @@
{
sema_init(&add_remove_card_sem, 1);
+ /* Clear the flag in case user removes the card. */
+ user_rmmod = 0;
+
return sdio_register_driver(&mwifiex_sdio);
}
@@ -1715,32 +1750,12 @@
static void
mwifiex_sdio_cleanup_module(void)
{
- struct mwifiex_adapter *adapter = g_adapter;
- int i;
+ if (!down_interruptible(&add_remove_card_sem))
+ up(&add_remove_card_sem);
- if (down_interruptible(&add_remove_card_sem))
- goto exit_sem_err;
+ /* Set the flag as user is removing this module. */
+ user_rmmod = 1;
- if (!adapter || !adapter->priv_num)
- goto exit;
-
- if (adapter->is_suspended)
- mwifiex_sdio_resume(adapter->dev);
-
- for (i = 0; i < adapter->priv_num; i++)
- if ((GET_BSS_ROLE(adapter->priv[i]) == MWIFIEX_BSS_ROLE_STA) &&
- adapter->priv[i]->media_connected)
- mwifiex_deauthenticate(adapter->priv[i], NULL);
-
- if (!adapter->surprise_removed)
- mwifiex_init_shutdown_fw(mwifiex_get_priv(adapter,
- MWIFIEX_BSS_ROLE_ANY),
- MWIFIEX_FUNC_SHUTDOWN);
-
-exit:
- up(&add_remove_card_sem);
-
-exit_sem_err:
sdio_unregister_driver(&mwifiex_sdio);
}
@@ -1751,4 +1766,4 @@
MODULE_DESCRIPTION("Marvell WiFi-Ex SDIO Driver version " SDIO_VERSION);
MODULE_VERSION(SDIO_VERSION);
MODULE_LICENSE("GPL v2");
-MODULE_FIRMWARE("sd8787.bin");
+MODULE_FIRMWARE("mrvl/sd8787_uapsta.bin");
diff --git a/drivers/net/wireless/mwifiex/sdio.h b/drivers/net/wireless/mwifiex/sdio.h
index 4e97e90..c925376 100644
--- a/drivers/net/wireless/mwifiex/sdio.h
+++ b/drivers/net/wireless/mwifiex/sdio.h
@@ -28,6 +28,8 @@
#include "main.h"
+#define SD8787_DEFAULT_FW_NAME "mrvl/sd8787_uapsta.bin"
+
#define BLOCK_MODE 1
#define BYTE_MODE 0
diff --git a/drivers/net/wireless/mwifiex/sta_cmd.c b/drivers/net/wireless/mwifiex/sta_cmd.c
index 8af3a78..49b9c13 100644
--- a/drivers/net/wireless/mwifiex/sta_cmd.c
+++ b/drivers/net/wireless/mwifiex/sta_cmd.c
@@ -67,10 +67,9 @@
*/
static int mwifiex_cmd_mac_control(struct mwifiex_private *priv,
struct host_cmd_ds_command *cmd,
- u16 cmd_action, void *data_buf)
+ u16 cmd_action, u16 *action)
{
struct host_cmd_ds_mac_control *mac_ctrl = &cmd->params.mac_ctrl;
- u16 action = *((u16 *) data_buf);
if (cmd_action != HostCmd_ACT_GEN_SET) {
dev_err(priv->adapter->dev,
@@ -81,7 +80,7 @@
cmd->command = cpu_to_le16(HostCmd_CMD_MAC_CONTROL);
cmd->size =
cpu_to_le16(sizeof(struct host_cmd_ds_mac_control) + S_DS_GEN);
- mac_ctrl->action = cpu_to_le16(action);
+ mac_ctrl->action = cpu_to_le16(*action);
return 0;
}
@@ -104,10 +103,9 @@
static int mwifiex_cmd_802_11_snmp_mib(struct mwifiex_private *priv,
struct host_cmd_ds_command *cmd,
u16 cmd_action, u32 cmd_oid,
- void *data_buf)
+ u32 *ul_temp)
{
struct host_cmd_ds_802_11_snmp_mib *snmp_mib = &cmd->params.smib;
- u32 ul_temp;
dev_dbg(priv->adapter->dev, "cmd: SNMP_CMD: cmd_oid = 0x%x\n", cmd_oid);
cmd->command = cpu_to_le16(HostCmd_CMD_802_11_SNMP_MIB);
@@ -127,9 +125,8 @@
if (cmd_action == HostCmd_ACT_GEN_SET) {
snmp_mib->query_type = cpu_to_le16(HostCmd_ACT_GEN_SET);
snmp_mib->buf_size = cpu_to_le16(sizeof(u16));
- ul_temp = *((u32 *) data_buf);
*((__le16 *) (snmp_mib->value)) =
- cpu_to_le16((u16) ul_temp);
+ cpu_to_le16((u16) *ul_temp);
cmd->size = cpu_to_le16(le16_to_cpu(cmd->size)
+ sizeof(u16));
}
@@ -139,9 +136,8 @@
if (cmd_action == HostCmd_ACT_GEN_SET) {
snmp_mib->query_type = cpu_to_le16(HostCmd_ACT_GEN_SET);
snmp_mib->buf_size = cpu_to_le16(sizeof(u16));
- ul_temp = *((u32 *) data_buf);
*(__le16 *) (snmp_mib->value) =
- cpu_to_le16((u16) ul_temp);
+ cpu_to_le16((u16) *ul_temp);
cmd->size = cpu_to_le16(le16_to_cpu(cmd->size)
+ sizeof(u16));
}
@@ -152,9 +148,8 @@
if (cmd_action == HostCmd_ACT_GEN_SET) {
snmp_mib->query_type = cpu_to_le16(HostCmd_ACT_GEN_SET);
snmp_mib->buf_size = cpu_to_le16(sizeof(u16));
- ul_temp = (*(u32 *) data_buf);
*((__le16 *) (snmp_mib->value)) =
- cpu_to_le16((u16) ul_temp);
+ cpu_to_le16((u16) *ul_temp);
cmd->size = cpu_to_le16(le16_to_cpu(cmd->size)
+ sizeof(u16));
}
@@ -164,9 +159,8 @@
if (cmd_action == HostCmd_ACT_GEN_SET) {
snmp_mib->query_type = cpu_to_le16(HostCmd_ACT_GEN_SET);
snmp_mib->buf_size = cpu_to_le16(sizeof(u16));
- ul_temp = *(u32 *) data_buf;
*((__le16 *) (snmp_mib->value)) =
- cpu_to_le16((u16) ul_temp);
+ cpu_to_le16((u16) *ul_temp);
cmd->size = cpu_to_le16(le16_to_cpu(cmd->size)
+ sizeof(u16));
}
@@ -209,13 +203,11 @@
*/
static int mwifiex_cmd_tx_rate_cfg(struct mwifiex_private *priv,
struct host_cmd_ds_command *cmd,
- u16 cmd_action, void *data_buf)
+ u16 cmd_action, u16 *pbitmap_rates)
{
struct host_cmd_ds_tx_rate_cfg *rate_cfg = &cmd->params.tx_rate_cfg;
struct mwifiex_rate_scope *rate_scope;
struct mwifiex_rate_drop_pattern *rate_drop;
- u16 *pbitmap_rates = (u16 *) data_buf;
-
u32 i;
cmd->command = cpu_to_le16(HostCmd_CMD_TX_RATE_CFG);
@@ -272,10 +264,10 @@
* - Ensuring correct endian-ness
*/
static int mwifiex_cmd_tx_power_cfg(struct host_cmd_ds_command *cmd,
- u16 cmd_action, void *data_buf)
+ u16 cmd_action,
+ struct host_cmd_ds_txpwr_cfg *txp)
{
struct mwifiex_types_power_group *pg_tlv;
- struct host_cmd_ds_txpwr_cfg *txp;
struct host_cmd_ds_txpwr_cfg *cmd_txp_cfg = &cmd->params.txp_cfg;
cmd->command = cpu_to_le16(HostCmd_CMD_TXPWR_CFG);
@@ -283,12 +275,11 @@
cpu_to_le16(S_DS_GEN + sizeof(struct host_cmd_ds_txpwr_cfg));
switch (cmd_action) {
case HostCmd_ACT_GEN_SET:
- txp = (struct host_cmd_ds_txpwr_cfg *) data_buf;
if (txp->mode) {
pg_tlv = (struct mwifiex_types_power_group
- *) ((unsigned long) data_buf +
+ *) ((unsigned long) txp +
sizeof(struct host_cmd_ds_txpwr_cfg));
- memmove(cmd_txp_cfg, data_buf,
+ memmove(cmd_txp_cfg, txp,
sizeof(struct host_cmd_ds_txpwr_cfg) +
sizeof(struct mwifiex_types_power_group) +
pg_tlv->length);
@@ -300,8 +291,7 @@
sizeof(struct mwifiex_types_power_group) +
pg_tlv->length);
} else {
- memmove(cmd_txp_cfg, data_buf,
- sizeof(struct host_cmd_ds_txpwr_cfg));
+ memmove(cmd_txp_cfg, txp, sizeof(*txp));
}
cmd_txp_cfg->action = cpu_to_le16(cmd_action);
break;
@@ -322,22 +312,23 @@
* (as required)
* - Ensuring correct endian-ness
*/
-static int mwifiex_cmd_802_11_hs_cfg(struct mwifiex_private *priv,
- struct host_cmd_ds_command *cmd,
- u16 cmd_action,
- struct mwifiex_hs_config_param *data_buf)
+static int
+mwifiex_cmd_802_11_hs_cfg(struct mwifiex_private *priv,
+ struct host_cmd_ds_command *cmd,
+ u16 cmd_action,
+ struct mwifiex_hs_config_param *hscfg_param)
{
struct mwifiex_adapter *adapter = priv->adapter;
struct host_cmd_ds_802_11_hs_cfg_enh *hs_cfg = &cmd->params.opt_hs_cfg;
u16 hs_activate = false;
- if (data_buf == NULL)
+ if (!hscfg_param)
/* New Activate command */
hs_activate = true;
cmd->command = cpu_to_le16(HostCmd_CMD_802_11_HS_CFG_ENH);
if (!hs_activate &&
- (data_buf->conditions
+ (hscfg_param->conditions
!= cpu_to_le32(HOST_SLEEP_CFG_CANCEL))
&& ((adapter->arp_filter_size > 0)
&& (adapter->arp_filter_size <= ARP_FILTER_MAX_BUF_SIZE))) {
@@ -359,9 +350,9 @@
hs_cfg->params.hs_activate.resp_ctrl = RESP_NEEDED;
} else {
hs_cfg->action = cpu_to_le16(HS_CONFIGURE);
- hs_cfg->params.hs_config.conditions = data_buf->conditions;
- hs_cfg->params.hs_config.gpio = data_buf->gpio;
- hs_cfg->params.hs_config.gap = data_buf->gap;
+ hs_cfg->params.hs_config.conditions = hscfg_param->conditions;
+ hs_cfg->params.hs_config.gpio = hscfg_param->gpio;
+ hs_cfg->params.hs_config.gap = hscfg_param->gap;
dev_dbg(adapter->dev,
"cmd: HS_CFG_CMD: condition:0x%x gpio:0x%x gap:0x%x\n",
hs_cfg->params.hs_config.conditions,
@@ -405,11 +396,11 @@
* - Setting MAC multicast address
* - Ensuring correct endian-ness
*/
-static int mwifiex_cmd_mac_multicast_adr(struct host_cmd_ds_command *cmd,
- u16 cmd_action, void *data_buf)
+static int
+mwifiex_cmd_mac_multicast_adr(struct host_cmd_ds_command *cmd,
+ u16 cmd_action,
+ struct mwifiex_multicast_list *mcast_list)
{
- struct mwifiex_multicast_list *mcast_list =
- (struct mwifiex_multicast_list *) data_buf;
struct host_cmd_ds_mac_multicast_adr *mcast_addr = &cmd->params.mc_addr;
cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_mac_multicast_adr) +
@@ -435,7 +426,7 @@
*/
static int mwifiex_cmd_802_11_deauthenticate(struct mwifiex_private *priv,
struct host_cmd_ds_command *cmd,
- void *data_buf)
+ u8 *mac)
{
struct host_cmd_ds_802_11_deauthenticate *deauth = &cmd->params.deauth;
@@ -444,7 +435,7 @@
+ S_DS_GEN);
/* Set AP MAC address */
- memcpy(deauth->mac_addr, (u8 *) data_buf, ETH_ALEN);
+ memcpy(deauth->mac_addr, mac, ETH_ALEN);
dev_dbg(priv->adapter->dev, "cmd: Deauth: %pM\n", deauth->mac_addr);
@@ -543,15 +534,14 @@
* encryption (TKIP, AES) (as required)
* - Ensuring correct endian-ness
*/
-static int mwifiex_cmd_802_11_key_material(struct mwifiex_private *priv,
- struct host_cmd_ds_command *cmd,
- u16 cmd_action,
- u32 cmd_oid, void *data_buf)
+static int
+mwifiex_cmd_802_11_key_material(struct mwifiex_private *priv,
+ struct host_cmd_ds_command *cmd,
+ u16 cmd_action, u32 cmd_oid,
+ struct mwifiex_ds_encrypt_key *enc_key)
{
struct host_cmd_ds_802_11_key_material *key_material =
&cmd->params.key_material;
- struct mwifiex_ds_encrypt_key *enc_key =
- (struct mwifiex_ds_encrypt_key *) data_buf;
u16 key_param_len = 0;
int ret = 0;
const u8 bc_mac[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
@@ -741,7 +731,7 @@
*/
static int mwifiex_cmd_802_11_rf_channel(struct mwifiex_private *priv,
struct host_cmd_ds_command *cmd,
- u16 cmd_action, void *data_buf)
+ u16 cmd_action, u16 *channel)
{
struct host_cmd_ds_802_11_rf_channel *rf_chan =
&cmd->params.rf_channel;
@@ -759,7 +749,7 @@
rf_type = le16_to_cpu(rf_chan->rf_type);
SET_SECONDARYCHAN(rf_type, priv->adapter->chan_offset);
- rf_chan->current_channel = cpu_to_le16(*((u16 *) data_buf));
+ rf_chan->current_channel = cpu_to_le16(*channel);
}
rf_chan->action = cpu_to_le16(cmd_action);
return 0;
@@ -774,11 +764,10 @@
* - Ensuring correct endian-ness
*/
static int mwifiex_cmd_ibss_coalescing_status(struct host_cmd_ds_command *cmd,
- u16 cmd_action, void *data_buf)
+ u16 cmd_action, u16 *enable)
{
struct host_cmd_ds_802_11_ibss_status *ibss_coal =
&(cmd->params.ibss_coalescing);
- u16 enable = 0;
cmd->command = cpu_to_le16(HostCmd_CMD_802_11_IBSS_COALESCING_STATUS);
cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_802_11_ibss_status) +
@@ -788,9 +777,10 @@
switch (cmd_action) {
case HostCmd_ACT_GEN_SET:
- if (data_buf != NULL)
- enable = *(u16 *) data_buf;
- ibss_coal->enable = cpu_to_le16(enable);
+ if (enable)
+ ibss_coal->enable = cpu_to_le16(*enable);
+ else
+ ibss_coal->enable = 0;
break;
/* In other case.. Nothing to do */
@@ -822,9 +812,8 @@
static int mwifiex_cmd_reg_access(struct host_cmd_ds_command *cmd,
u16 cmd_action, void *data_buf)
{
- struct mwifiex_ds_reg_rw *reg_rw;
+ struct mwifiex_ds_reg_rw *reg_rw = data_buf;
- reg_rw = (struct mwifiex_ds_reg_rw *) data_buf;
switch (le16_to_cpu(cmd->command)) {
case HostCmd_CMD_MAC_REG_ACCESS:
{
@@ -893,8 +882,7 @@
}
case HostCmd_CMD_802_11_EEPROM_ACCESS:
{
- struct mwifiex_ds_read_eeprom *rd_eeprom =
- (struct mwifiex_ds_read_eeprom *) data_buf;
+ struct mwifiex_ds_read_eeprom *rd_eeprom = data_buf;
struct host_cmd_ds_802_11_eeprom_access *cmd_eeprom =
(struct host_cmd_ds_802_11_eeprom_access *)
&cmd->params.eeprom;
@@ -923,8 +911,7 @@
u16 cmd_action, u32 cmd_oid,
void *data_buf, void *cmd_buf)
{
- struct host_cmd_ds_command *cmd_ptr =
- (struct host_cmd_ds_command *) cmd_buf;
+ struct host_cmd_ds_command *cmd_ptr = cmd_buf;
int ret = 0;
/* Prepare command */
@@ -1181,7 +1168,7 @@
/* Send request to firmware */
ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_AMSDU_AGGR_CTRL,
HostCmd_ACT_GEN_SET, 0,
- (void *) &amsdu_aggr_ctrl);
+ &amsdu_aggr_ctrl);
if (ret)
return -1;
/* MAC Control must be the last command in init_fw */
diff --git a/drivers/net/wireless/mwifiex/sta_cmdresp.c b/drivers/net/wireless/mwifiex/sta_cmdresp.c
index d08f764..6804239 100644
--- a/drivers/net/wireless/mwifiex/sta_cmdresp.c
+++ b/drivers/net/wireless/mwifiex/sta_cmdresp.c
@@ -120,11 +120,10 @@
*/
static int mwifiex_ret_802_11_rssi_info(struct mwifiex_private *priv,
struct host_cmd_ds_command *resp,
- void *data_buf)
+ struct mwifiex_ds_get_signal *signal)
{
struct host_cmd_ds_802_11_rssi_info_rsp *rssi_info_rsp =
&resp->params.rssi_info_rsp;
- struct mwifiex_ds_get_signal *signal;
priv->data_rssi_last = le16_to_cpu(rssi_info_rsp->data_rssi_last);
priv->data_nf_last = le16_to_cpu(rssi_info_rsp->data_nf_last);
@@ -139,9 +138,8 @@
priv->bcn_nf_avg = le16_to_cpu(rssi_info_rsp->bcn_nf_avg);
/* Need to indicate IOCTL complete */
- if (data_buf) {
- signal = (struct mwifiex_ds_get_signal *) data_buf;
- memset(signal, 0, sizeof(struct mwifiex_ds_get_signal));
+ if (signal) {
+ memset(signal, 0, sizeof(*signal));
signal->selector = ALL_RSSI_INFO_MASK;
@@ -185,7 +183,7 @@
*/
static int mwifiex_ret_802_11_snmp_mib(struct mwifiex_private *priv,
struct host_cmd_ds_command *resp,
- void *data_buf)
+ u32 *data_buf)
{
struct host_cmd_ds_802_11_snmp_mib *smib = &resp->params.smib;
u16 oid = le16_to_cpu(smib->oid);
@@ -198,7 +196,7 @@
if (query_type == HostCmd_ACT_GEN_GET) {
ul_temp = le16_to_cpu(*((__le16 *) (smib->value)));
if (data_buf)
- *(u32 *)data_buf = ul_temp;
+ *data_buf = ul_temp;
switch (oid) {
case FRAG_THRESH_I:
dev_dbg(priv->adapter->dev,
@@ -228,14 +226,12 @@
*/
static int mwifiex_ret_get_log(struct mwifiex_private *priv,
struct host_cmd_ds_command *resp,
- void *data_buf)
+ struct mwifiex_ds_get_stats *stats)
{
struct host_cmd_ds_802_11_get_log *get_log =
(struct host_cmd_ds_802_11_get_log *) &resp->params.get_log;
- struct mwifiex_ds_get_stats *stats;
- if (data_buf) {
- stats = (struct mwifiex_ds_get_stats *) data_buf;
+ if (stats) {
stats->mcast_tx_frame = le32_to_cpu(get_log->mcast_tx_frame);
stats->failed = le32_to_cpu(get_log->failed);
stats->retry = le32_to_cpu(get_log->retry);
@@ -278,9 +274,8 @@
*/
static int mwifiex_ret_tx_rate_cfg(struct mwifiex_private *priv,
struct host_cmd_ds_command *resp,
- void *data_buf)
+ struct mwifiex_rate_cfg *ds_rate)
{
- struct mwifiex_rate_cfg *ds_rate;
struct host_cmd_ds_tx_rate_cfg *rate_cfg = &resp->params.tx_rate_cfg;
struct mwifiex_rate_scope *rate_scope;
struct mwifiex_ie_types_header *head;
@@ -329,8 +324,7 @@
HostCmd_CMD_802_11_TX_RATE_QUERY,
HostCmd_ACT_GEN_GET, 0, NULL);
- if (data_buf) {
- ds_rate = (struct mwifiex_rate_cfg *) data_buf;
+ if (ds_rate) {
if (le16_to_cpu(rate_cfg->action) == HostCmd_ACT_GEN_GET) {
if (priv->is_data_rate_auto) {
ds_rate->is_rate_auto = 1;
@@ -413,8 +407,7 @@
* and saving the current Tx power level in driver.
*/
static int mwifiex_ret_tx_power_cfg(struct mwifiex_private *priv,
- struct host_cmd_ds_command *resp,
- void *data_buf)
+ struct host_cmd_ds_command *resp)
{
struct mwifiex_adapter *adapter = priv->adapter;
struct host_cmd_ds_txpwr_cfg *txp_cfg = &resp->params.txp_cfg;
@@ -631,7 +624,7 @@
*/
static int mwifiex_ret_802_11_rf_channel(struct mwifiex_private *priv,
struct host_cmd_ds_command *resp,
- void *data_buf)
+ u16 *data_buf)
{
struct host_cmd_ds_802_11_rf_channel *rf_channel =
&resp->params.rf_channel;
@@ -644,8 +637,9 @@
/* Update the channel again */
priv->curr_bss_params.bss_descriptor.channel = new_channel;
}
+
if (data_buf)
- *((u16 *)data_buf) = new_channel;
+ *data_buf = new_channel;
return 0;
}
@@ -658,13 +652,11 @@
*/
static int mwifiex_ret_ver_ext(struct mwifiex_private *priv,
struct host_cmd_ds_command *resp,
- void *data_buf)
+ struct host_cmd_ds_version_ext *version_ext)
{
struct host_cmd_ds_version_ext *ver_ext = &resp->params.verext;
- struct host_cmd_ds_version_ext *version_ext;
- if (data_buf) {
- version_ext = (struct host_cmd_ds_version_ext *)data_buf;
+ if (version_ext) {
version_ext->version_str_sel = ver_ext->version_str_sel;
memcpy(version_ext->version_str, ver_ext->version_str,
sizeof(char) * 128);
@@ -686,8 +678,8 @@
struct mwifiex_ds_read_eeprom *eeprom;
if (data_buf) {
- reg_rw = (struct mwifiex_ds_reg_rw *) data_buf;
- eeprom = (struct mwifiex_ds_read_eeprom *) data_buf;
+ reg_rw = data_buf;
+ eeprom = data_buf;
switch (type) {
case HostCmd_CMD_MAC_REG_ACCESS:
{
@@ -825,13 +817,11 @@
* This is a generic function, which calls command specific
* response handlers based on the command ID.
*/
-int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv,
- u16 cmdresp_no, void *cmd_buf)
+int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no,
+ struct host_cmd_ds_command *resp)
{
int ret = 0;
struct mwifiex_adapter *adapter = priv->adapter;
- struct host_cmd_ds_command *resp =
- (struct host_cmd_ds_command *) cmd_buf;
void *data_buf = adapter->curr_cmd->data_buf;
/* If the command is not successful, cleanup and return failure */
@@ -865,7 +855,7 @@
"info: CMD_RESP: BG_SCAN result is ready!\n");
break;
case HostCmd_CMD_TXPWR_CFG:
- ret = mwifiex_ret_tx_power_cfg(priv, resp, data_buf);
+ ret = mwifiex_ret_tx_power_cfg(priv, resp);
break;
case HostCmd_CMD_802_11_PS_MODE_ENH:
ret = mwifiex_ret_enh_power_mode(priv, resp, data_buf);
diff --git a/drivers/net/wireless/mwifiex/sta_rx.c b/drivers/net/wireless/mwifiex/sta_rx.c
index 1fdddec..2743051 100644
--- a/drivers/net/wireless/mwifiex/sta_rx.c
+++ b/drivers/net/wireless/mwifiex/sta_rx.c
@@ -187,7 +187,7 @@
ret = mwifiex_11n_rx_reorder_pkt(priv, local_rx_pd->seq_num,
local_rx_pd->priority, ta,
(u8) local_rx_pd->rx_pkt_type,
- (void *) skb);
+ skb);
if (ret || (rx_pkt_type == PKT_TYPE_BAR)) {
if (priv && (ret == -1))
diff --git a/drivers/net/wireless/mwifiex/txrx.c b/drivers/net/wireless/mwifiex/txrx.c
index aaa50c0..6190b2f 100644
--- a/drivers/net/wireless/mwifiex/txrx.c
+++ b/drivers/net/wireless/mwifiex/txrx.c
@@ -71,7 +71,7 @@
u8 *head_ptr;
struct txpd *local_tx_pd = NULL;
- head_ptr = (u8 *) mwifiex_process_sta_txpd(priv, skb);
+ head_ptr = mwifiex_process_sta_txpd(priv, skb);
if (head_ptr) {
if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA)
local_tx_pd =
diff --git a/drivers/net/wireless/mwifiex/wmm.c b/drivers/net/wireless/mwifiex/wmm.c
index 91634da..67b2d0b 100644
--- a/drivers/net/wireless/mwifiex/wmm.c
+++ b/drivers/net/wireless/mwifiex/wmm.c
@@ -121,6 +121,7 @@
memcpy(ra_list->ra, ra, ETH_ALEN);
ra_list->total_pkts_size = 0;
+ ra_list->total_pkts = 0;
dev_dbg(adapter->dev, "info: allocated ra_list %p\n", ra_list);
@@ -645,6 +646,7 @@
skb_queue_tail(&ra_list->skb_head, skb);
ra_list->total_pkts_size += skb->len;
+ ra_list->total_pkts++;
atomic_inc(&priv->wmm.tx_pkts_queued);
@@ -971,28 +973,6 @@
}
/*
- * This function gets the number of packets in the Tx queue of a
- * particular RA list.
- */
-static int
-mwifiex_num_pkts_in_txq(struct mwifiex_private *priv,
- struct mwifiex_ra_list_tbl *ptr, int max_buf_size)
-{
- int count = 0, total_size = 0;
- struct sk_buff *skb, *tmp;
-
- skb_queue_walk_safe(&ptr->skb_head, skb, tmp) {
- total_size += skb->len;
- if (total_size < max_buf_size)
- ++count;
- else
- break;
- }
-
- return count;
-}
-
-/*
* This function sends a single packet to firmware for transmission.
*/
static void
@@ -1019,6 +999,7 @@
dev_dbg(adapter->dev, "data: dequeuing the packet %p %p\n", ptr, skb);
ptr->total_pkts_size -= skb->len;
+ ptr->total_pkts--;
if (!skb_queue_empty(&ptr->skb_head))
skb_next = skb_peek(&ptr->skb_head);
@@ -1044,6 +1025,7 @@
skb_queue_tail(&ptr->skb_head, skb);
ptr->total_pkts_size += skb->len;
+ ptr->total_pkts++;
tx_info->flags |= MWIFIEX_BUF_FLAG_REQUEUED_PKT;
spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
ra_list_flags);
@@ -1231,9 +1213,9 @@
}
/* Minimum number of AMSDU */
#define MIN_NUM_AMSDU 2
+
if (mwifiex_is_amsdu_allowed(priv, tid) &&
- (mwifiex_num_pkts_in_txq(priv, ptr, adapter->tx_buf_size) >=
- MIN_NUM_AMSDU))
+ (ptr->total_pkts >= MIN_NUM_AMSDU))
mwifiex_11n_aggregate_pkt(priv, ptr, INTF_HEADER_LEN,
ptr_index, flags);
/* ra_list_spinlock has been freed in
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c
index aeac3cc..d633edb 100644
--- a/drivers/net/wireless/mwl8k.c
+++ b/drivers/net/wireless/mwl8k.c
@@ -10,6 +10,7 @@
*/
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/sched.h>
diff --git a/drivers/net/wireless/orinoco/main.c b/drivers/net/wireless/orinoco/main.c
index 62c6b2b..b0f233f 100644
--- a/drivers/net/wireless/orinoco/main.c
+++ b/drivers/net/wireless/orinoco/main.c
@@ -1958,7 +1958,7 @@
evstat = hermes_read_regn(hw, EVSTAT);
events = evstat & hw->inten;
- };
+ }
orinoco_unlock(priv, &flags);
return IRQ_HANDLED;
diff --git a/drivers/net/wireless/p54/p54pci.h b/drivers/net/wireless/p54/p54pci.h
index ee9bc62..7aa509f 100644
--- a/drivers/net/wireless/p54/p54pci.h
+++ b/drivers/net/wireless/p54/p54pci.h
@@ -1,5 +1,6 @@
#ifndef P54PCI_H
#define P54PCI_H
+#include <linux/interrupt.h>
/*
* Defines for PCI based mac80211 Prism54 driver
diff --git a/drivers/net/wireless/prism54/islpci_dev.c b/drivers/net/wireless/prism54/islpci_dev.c
index ec2c75d..5d0f615 100644
--- a/drivers/net/wireless/prism54/islpci_dev.c
+++ b/drivers/net/wireless/prism54/islpci_dev.c
@@ -18,6 +18,7 @@
*
*/
+#include <linux/hardirq.h>
#include <linux/module.h>
#include <linux/slab.h>
diff --git a/drivers/net/wireless/prism54/islpci_dev.h b/drivers/net/wireless/prism54/islpci_dev.h
index c4d0f19..c404038 100644
--- a/drivers/net/wireless/prism54/islpci_dev.h
+++ b/drivers/net/wireless/prism54/islpci_dev.h
@@ -22,6 +22,7 @@
#ifndef _ISLPCI_DEV_H
#define _ISLPCI_DEV_H
+#include <linux/irqreturn.h>
#include <linux/netdevice.h>
#include <linux/wireless.h>
#include <net/iw_handler.h>
diff --git a/drivers/net/wireless/prism54/islpci_hotplug.c b/drivers/net/wireless/prism54/islpci_hotplug.c
index b5e64d7..9e68e0c 100644
--- a/drivers/net/wireless/prism54/islpci_hotplug.c
+++ b/drivers/net/wireless/prism54/islpci_hotplug.c
@@ -17,6 +17,7 @@
*
*/
+#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/delay.h>
diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig
index b2f8b8f..a0a7854 100644
--- a/drivers/net/wireless/rt2x00/Kconfig
+++ b/drivers/net/wireless/rt2x00/Kconfig
@@ -83,14 +83,12 @@
config RT2800PCI_RT35XX
bool "rt2800pci - Include support for rt35xx devices (EXPERIMENTAL)"
depends on EXPERIMENTAL
- default n
+ default y
---help---
This adds support for rt35xx wireless chipset family to the
rt2800pci driver.
Supported chips: RT3060, RT3062, RT3562, RT3592
- Support for these devices is non-functional at the moment and is
- intended for testers and developers.
config RT2800PCI_RT53XX
bool "rt2800pci - Include support for rt53xx devices (EXPERIMENTAL)"
@@ -154,15 +152,12 @@
config RT2800USB_RT35XX
bool "rt2800usb - Include support for rt35xx devices (EXPERIMENTAL)"
depends on EXPERIMENTAL
- default n
+ default y
---help---
This adds support for rt35xx wireless chipset family to the
rt2800usb driver.
Supported chips: RT3572
- Support for these devices is non-functional at the moment and is
- intended for testers and developers.
-
config RT2800USB_RT53XX
bool "rt2800usb - Include support for rt53xx devices (EXPERIMENTAL)"
depends on EXPERIMENTAL
diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h
index f67bc9b..c69a7d7 100644
--- a/drivers/net/wireless/rt2x00/rt2800.h
+++ b/drivers/net/wireless/rt2x00/rt2800.h
@@ -1740,6 +1740,7 @@
/*
* BBP 3: RX Antenna
*/
+#define BBP3_RX_ADC FIELD8(0x03)
#define BBP3_RX_ANTENNA FIELD8(0x18)
#define BBP3_HT40_MINUS FIELD8(0x20)
@@ -1783,6 +1784,8 @@
#define RFCSR1_TX0_PD FIELD8(0x08)
#define RFCSR1_RX1_PD FIELD8(0x10)
#define RFCSR1_TX1_PD FIELD8(0x20)
+#define RFCSR1_RX2_PD FIELD8(0x40)
+#define RFCSR1_TX2_PD FIELD8(0x80)
/*
* RFCSR 2:
@@ -1790,15 +1793,25 @@
#define RFCSR2_RESCAL_EN FIELD8(0x80)
/*
+ * FRCSR 5:
+ */
+#define RFCSR5_R1 FIELD8(0x0c)
+
+/*
* RFCSR 6:
*/
#define RFCSR6_R1 FIELD8(0x03)
#define RFCSR6_R2 FIELD8(0x40)
+#define RFCSR6_TXDIV FIELD8(0x0c)
/*
* RFCSR 7:
*/
#define RFCSR7_RF_TUNING FIELD8(0x01)
+#define RFCSR7_R02 FIELD8(0x07)
+#define RFCSR7_R3 FIELD8(0x08)
+#define RFCSR7_R45 FIELD8(0x30)
+#define RFCSR7_R67 FIELD8(0xc0)
/*
* RFCSR 11:
@@ -1809,11 +1822,13 @@
* RFCSR 12:
*/
#define RFCSR12_TX_POWER FIELD8(0x1f)
+#define RFCSR12_DR0 FIELD8(0xe0)
/*
* RFCSR 13:
*/
#define RFCSR13_TX_POWER FIELD8(0x1f)
+#define RFCSR13_DR0 FIELD8(0xe0)
/*
* RFCSR 15:
@@ -2256,6 +2271,7 @@
#define MCU_ANT_SELECT 0X73
#define MCU_BBP_SIGNAL 0x80
#define MCU_POWER_SAVE 0x83
+#define MCU_BAND_SELECT 0x91
/*
* MCU mailbox tokens
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
index 2a6aa85..84ab7d1 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -401,7 +401,8 @@
return -EBUSY;
if (rt2x00_is_pci(rt2x00dev)) {
- if (rt2x00_rt(rt2x00dev, RT5390)) {
+ if (rt2x00_rt(rt2x00dev, RT3572) ||
+ rt2x00_rt(rt2x00dev, RT5390)) {
rt2800_register_read(rt2x00dev, AUX_CTRL, ®);
rt2x00_set_field32(®, AUX_CTRL_FORCE_PCIE_CLK, 1);
rt2x00_set_field32(®, AUX_CTRL_WAKE_PCIE_EN, 1);
@@ -600,49 +601,6 @@
}
EXPORT_SYMBOL_GPL(rt2800_process_rxwi);
-static bool rt2800_txdone_entry_check(struct queue_entry *entry, u32 reg)
-{
- __le32 *txwi;
- u32 word;
- int wcid, ack, pid;
- int tx_wcid, tx_ack, tx_pid;
-
- wcid = rt2x00_get_field32(reg, TX_STA_FIFO_WCID);
- ack = rt2x00_get_field32(reg, TX_STA_FIFO_TX_ACK_REQUIRED);
- pid = rt2x00_get_field32(reg, TX_STA_FIFO_PID_TYPE);
-
- /*
- * This frames has returned with an IO error,
- * so the status report is not intended for this
- * frame.
- */
- if (test_bit(ENTRY_DATA_IO_FAILED, &entry->flags)) {
- rt2x00lib_txdone_noinfo(entry, TXDONE_FAILURE);
- return false;
- }
-
- /*
- * Validate if this TX status report is intended for
- * this entry by comparing the WCID/ACK/PID fields.
- */
- txwi = rt2800_drv_get_txwi(entry);
-
- rt2x00_desc_read(txwi, 1, &word);
- tx_wcid = rt2x00_get_field32(word, TXWI_W1_WIRELESS_CLI_ID);
- tx_ack = rt2x00_get_field32(word, TXWI_W1_ACK);
- tx_pid = rt2x00_get_field32(word, TXWI_W1_PACKETID);
-
- if ((wcid != tx_wcid) || (ack != tx_ack) || (pid != tx_pid)) {
- WARNING(entry->queue->rt2x00dev,
- "TX status report missed for queue %d entry %d\n",
- entry->queue->qid, entry->entry_idx);
- rt2x00lib_txdone_noinfo(entry, TXDONE_UNKNOWN);
- return false;
- }
-
- return true;
-}
-
void rt2800_txdone_entry(struct queue_entry *entry, u32 status)
{
struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
@@ -725,45 +683,6 @@
}
EXPORT_SYMBOL_GPL(rt2800_txdone_entry);
-void rt2800_txdone(struct rt2x00_dev *rt2x00dev)
-{
- struct data_queue *queue;
- struct queue_entry *entry;
- u32 reg;
- u8 qid;
-
- while (kfifo_get(&rt2x00dev->txstatus_fifo, ®)) {
-
- /* TX_STA_FIFO_PID_QUEUE is a 2-bit field, thus
- * qid is guaranteed to be one of the TX QIDs
- */
- qid = rt2x00_get_field32(reg, TX_STA_FIFO_PID_QUEUE);
- queue = rt2x00queue_get_tx_queue(rt2x00dev, qid);
- if (unlikely(!queue)) {
- WARNING(rt2x00dev, "Got TX status for an unavailable "
- "queue %u, dropping\n", qid);
- continue;
- }
-
- /*
- * Inside each queue, we process each entry in a chronological
- * order. We first check that the queue is not empty.
- */
- entry = NULL;
- while (!rt2x00queue_empty(queue)) {
- entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
- if (rt2800_txdone_entry_check(entry, reg))
- break;
- }
-
- if (!entry || rt2x00queue_empty(queue))
- break;
-
- rt2800_txdone_entry(entry, reg);
- }
-}
-EXPORT_SYMBOL_GPL(rt2800_txdone);
-
void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc)
{
struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
@@ -1355,7 +1274,7 @@
gf20_rate = gf40_rate = 0x0003;
}
break;
- };
+ }
/* check for STAs not supporting greenfield mode */
if (any_sta_nongf)
@@ -1433,6 +1352,40 @@
}
EXPORT_SYMBOL_GPL(rt2800_config_erp);
+static void rt2800_config_3572bt_ant(struct rt2x00_dev *rt2x00dev)
+{
+ u32 reg;
+ u16 eeprom;
+ u8 led_ctrl, led_g_mode, led_r_mode;
+
+ rt2800_register_read(rt2x00dev, GPIO_SWITCH, ®);
+ if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) {
+ rt2x00_set_field32(®, GPIO_SWITCH_0, 1);
+ rt2x00_set_field32(®, GPIO_SWITCH_1, 1);
+ } else {
+ rt2x00_set_field32(®, GPIO_SWITCH_0, 0);
+ rt2x00_set_field32(®, GPIO_SWITCH_1, 0);
+ }
+ rt2800_register_write(rt2x00dev, GPIO_SWITCH, reg);
+
+ rt2800_register_read(rt2x00dev, LED_CFG, ®);
+ led_g_mode = rt2x00_get_field32(reg, LED_CFG_LED_POLAR) ? 3 : 0;
+ led_r_mode = rt2x00_get_field32(reg, LED_CFG_LED_POLAR) ? 0 : 3;
+ if (led_g_mode != rt2x00_get_field32(reg, LED_CFG_G_LED_MODE) ||
+ led_r_mode != rt2x00_get_field32(reg, LED_CFG_R_LED_MODE)) {
+ rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &eeprom);
+ led_ctrl = rt2x00_get_field16(eeprom, EEPROM_FREQ_LED_MODE);
+ if (led_ctrl == 0 || led_ctrl > 0x40) {
+ rt2x00_set_field32(®, LED_CFG_G_LED_MODE, led_g_mode);
+ rt2x00_set_field32(®, LED_CFG_R_LED_MODE, led_r_mode);
+ rt2800_register_write(rt2x00dev, LED_CFG, reg);
+ } else {
+ rt2800_mcu_request(rt2x00dev, MCU_BAND_SELECT, 0xff,
+ (led_g_mode << 2) | led_r_mode, 1);
+ }
+ }
+}
+
static void rt2800_set_ant_diversity(struct rt2x00_dev *rt2x00dev,
enum antenna ant)
{
@@ -1463,6 +1416,10 @@
rt2800_bbp_read(rt2x00dev, 1, &r1);
rt2800_bbp_read(rt2x00dev, 3, &r3);
+ if (rt2x00_rt(rt2x00dev, RT3572) &&
+ test_bit(CAPABILITY_BT_COEXIST, &rt2x00dev->cap_flags))
+ rt2800_config_3572bt_ant(rt2x00dev);
+
/*
* Configure the TX antenna.
*/
@@ -1471,7 +1428,11 @@
rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 0);
break;
case 2:
- rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 2);
+ if (rt2x00_rt(rt2x00dev, RT3572) &&
+ test_bit(CAPABILITY_BT_COEXIST, &rt2x00dev->cap_flags))
+ rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 1);
+ else
+ rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 2);
break;
case 3:
rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 0);
@@ -1496,7 +1457,15 @@
rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 0);
break;
case 2:
- rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 1);
+ if (rt2x00_rt(rt2x00dev, RT3572) &&
+ test_bit(CAPABILITY_BT_COEXIST, &rt2x00dev->cap_flags)) {
+ rt2x00_set_field8(&r3, BBP3_RX_ADC, 1);
+ rt2x00_set_field8(&r3, BBP3_RX_ANTENNA,
+ rt2x00dev->curr_band == IEEE80211_BAND_5GHZ);
+ rt2800_set_ant_diversity(rt2x00dev, ANTENNA_B);
+ } else {
+ rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 1);
+ }
break;
case 3:
rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 2);
@@ -1630,6 +1599,161 @@
rt2800_rfcsr_write(rt2x00dev, 7, rfcsr);
}
+static void rt2800_config_channel_rf3052(struct rt2x00_dev *rt2x00dev,
+ struct ieee80211_conf *conf,
+ struct rf_channel *rf,
+ struct channel_info *info)
+{
+ u8 rfcsr;
+ u32 reg;
+
+ if (rf->channel <= 14) {
+ rt2800_bbp_write(rt2x00dev, 25, 0x15);
+ rt2800_bbp_write(rt2x00dev, 26, 0x85);
+ } else {
+ rt2800_bbp_write(rt2x00dev, 25, 0x09);
+ rt2800_bbp_write(rt2x00dev, 26, 0xff);
+ }
+
+ rt2800_rfcsr_write(rt2x00dev, 2, rf->rf1);
+ rt2800_rfcsr_write(rt2x00dev, 3, rf->rf3);
+
+ rt2800_rfcsr_read(rt2x00dev, 6, &rfcsr);
+ rt2x00_set_field8(&rfcsr, RFCSR6_R1, rf->rf2);
+ if (rf->channel <= 14)
+ rt2x00_set_field8(&rfcsr, RFCSR6_TXDIV, 2);
+ else
+ rt2x00_set_field8(&rfcsr, RFCSR6_TXDIV, 1);
+ rt2800_rfcsr_write(rt2x00dev, 6, rfcsr);
+
+ rt2800_rfcsr_read(rt2x00dev, 5, &rfcsr);
+ if (rf->channel <= 14)
+ rt2x00_set_field8(&rfcsr, RFCSR5_R1, 1);
+ else
+ rt2x00_set_field8(&rfcsr, RFCSR5_R1, 2);
+ rt2800_rfcsr_write(rt2x00dev, 5, rfcsr);
+
+ rt2800_rfcsr_read(rt2x00dev, 12, &rfcsr);
+ if (rf->channel <= 14) {
+ rt2x00_set_field8(&rfcsr, RFCSR12_DR0, 3);
+ rt2x00_set_field8(&rfcsr, RFCSR12_TX_POWER,
+ (info->default_power1 & 0x3) |
+ ((info->default_power1 & 0xC) << 1));
+ } else {
+ rt2x00_set_field8(&rfcsr, RFCSR12_DR0, 7);
+ rt2x00_set_field8(&rfcsr, RFCSR12_TX_POWER,
+ (info->default_power1 & 0x3) |
+ ((info->default_power1 & 0xC) << 1));
+ }
+ rt2800_rfcsr_write(rt2x00dev, 12, rfcsr);
+
+ rt2800_rfcsr_read(rt2x00dev, 13, &rfcsr);
+ if (rf->channel <= 14) {
+ rt2x00_set_field8(&rfcsr, RFCSR13_DR0, 3);
+ rt2x00_set_field8(&rfcsr, RFCSR13_TX_POWER,
+ (info->default_power2 & 0x3) |
+ ((info->default_power2 & 0xC) << 1));
+ } else {
+ rt2x00_set_field8(&rfcsr, RFCSR13_DR0, 7);
+ rt2x00_set_field8(&rfcsr, RFCSR13_TX_POWER,
+ (info->default_power2 & 0x3) |
+ ((info->default_power2 & 0xC) << 1));
+ }
+ rt2800_rfcsr_write(rt2x00dev, 13, rfcsr);
+
+ rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr);
+ rt2x00_set_field8(&rfcsr, RFCSR1_RF_BLOCK_EN, 1);
+ rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 0);
+ rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 0);
+ rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, 0);
+ rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 0);
+ if (test_bit(CAPABILITY_BT_COEXIST, &rt2x00dev->cap_flags)) {
+ if (rf->channel <= 14) {
+ rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 1);
+ rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 1);
+ }
+ rt2x00_set_field8(&rfcsr, RFCSR1_RX2_PD, 1);
+ rt2x00_set_field8(&rfcsr, RFCSR1_TX2_PD, 1);
+ } else {
+ switch (rt2x00dev->default_ant.tx_chain_num) {
+ case 1:
+ rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 1);
+ case 2:
+ rt2x00_set_field8(&rfcsr, RFCSR1_TX2_PD, 1);
+ break;
+ }
+
+ switch (rt2x00dev->default_ant.rx_chain_num) {
+ case 1:
+ rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, 1);
+ case 2:
+ rt2x00_set_field8(&rfcsr, RFCSR1_RX2_PD, 1);
+ break;
+ }
+ }
+ rt2800_rfcsr_write(rt2x00dev, 1, rfcsr);
+
+ rt2800_rfcsr_read(rt2x00dev, 23, &rfcsr);
+ rt2x00_set_field8(&rfcsr, RFCSR23_FREQ_OFFSET, rt2x00dev->freq_offset);
+ rt2800_rfcsr_write(rt2x00dev, 23, rfcsr);
+
+ rt2800_rfcsr_write(rt2x00dev, 24,
+ rt2x00dev->calibration[conf_is_ht40(conf)]);
+ rt2800_rfcsr_write(rt2x00dev, 31,
+ rt2x00dev->calibration[conf_is_ht40(conf)]);
+
+ if (rf->channel <= 14) {
+ rt2800_rfcsr_write(rt2x00dev, 7, 0xd8);
+ rt2800_rfcsr_write(rt2x00dev, 9, 0xc3);
+ rt2800_rfcsr_write(rt2x00dev, 10, 0xf1);
+ rt2800_rfcsr_write(rt2x00dev, 11, 0xb9);
+ rt2800_rfcsr_write(rt2x00dev, 15, 0x53);
+ rt2800_rfcsr_write(rt2x00dev, 16, 0x4c);
+ rt2800_rfcsr_write(rt2x00dev, 17, 0x23);
+ rt2800_rfcsr_write(rt2x00dev, 19, 0x93);
+ rt2800_rfcsr_write(rt2x00dev, 20, 0xb3);
+ rt2800_rfcsr_write(rt2x00dev, 25, 0x15);
+ rt2800_rfcsr_write(rt2x00dev, 26, 0x85);
+ rt2800_rfcsr_write(rt2x00dev, 27, 0x00);
+ rt2800_rfcsr_write(rt2x00dev, 29, 0x9b);
+ } else {
+ rt2800_rfcsr_write(rt2x00dev, 7, 0x14);
+ rt2800_rfcsr_write(rt2x00dev, 9, 0xc0);
+ rt2800_rfcsr_write(rt2x00dev, 10, 0xf1);
+ rt2800_rfcsr_write(rt2x00dev, 11, 0x00);
+ rt2800_rfcsr_write(rt2x00dev, 15, 0x43);
+ rt2800_rfcsr_write(rt2x00dev, 16, 0x7a);
+ rt2800_rfcsr_write(rt2x00dev, 17, 0x23);
+ if (rf->channel <= 64) {
+ rt2800_rfcsr_write(rt2x00dev, 19, 0xb7);
+ rt2800_rfcsr_write(rt2x00dev, 20, 0xf6);
+ rt2800_rfcsr_write(rt2x00dev, 25, 0x3d);
+ } else if (rf->channel <= 128) {
+ rt2800_rfcsr_write(rt2x00dev, 19, 0x74);
+ rt2800_rfcsr_write(rt2x00dev, 20, 0xf4);
+ rt2800_rfcsr_write(rt2x00dev, 25, 0x01);
+ } else {
+ rt2800_rfcsr_write(rt2x00dev, 19, 0x72);
+ rt2800_rfcsr_write(rt2x00dev, 20, 0xf3);
+ rt2800_rfcsr_write(rt2x00dev, 25, 0x01);
+ }
+ rt2800_rfcsr_write(rt2x00dev, 26, 0x87);
+ rt2800_rfcsr_write(rt2x00dev, 27, 0x01);
+ rt2800_rfcsr_write(rt2x00dev, 29, 0x9f);
+ }
+
+ rt2800_register_read(rt2x00dev, GPIO_CTRL_CFG, ®);
+ rt2x00_set_field32(®, GPIO_CTRL_CFG_GPIOD_BIT7, 0);
+ if (rf->channel <= 14)
+ rt2x00_set_field32(®, GPIO_CTRL_CFG_BIT7, 1);
+ else
+ rt2x00_set_field32(®, GPIO_CTRL_CFG_BIT7, 0);
+ rt2800_register_write(rt2x00dev, GPIO_CTRL_CFG, reg);
+
+ rt2800_rfcsr_read(rt2x00dev, 7, &rfcsr);
+ rt2x00_set_field8(&rfcsr, RFCSR7_RF_TUNING, 1);
+ rt2800_rfcsr_write(rt2x00dev, 7, rfcsr);
+}
#define RT5390_POWER_BOUND 0x27
#define RT5390_FREQ_OFFSET_BOUND 0x5f
@@ -1748,9 +1872,10 @@
rt2x00_rf(rt2x00dev, RF3020) ||
rt2x00_rf(rt2x00dev, RF3021) ||
rt2x00_rf(rt2x00dev, RF3022) ||
- rt2x00_rf(rt2x00dev, RF3052) ||
rt2x00_rf(rt2x00dev, RF3320))
rt2800_config_channel_rf3xxx(rt2x00dev, conf, rf, info);
+ else if (rt2x00_rf(rt2x00dev, RF3052))
+ rt2800_config_channel_rf3052(rt2x00dev, conf, rf, info);
else if (rt2x00_rf(rt2x00dev, RF5370) ||
rt2x00_rf(rt2x00dev, RF5390))
rt2800_config_channel_rf53xx(rt2x00dev, conf, rf, info);
@@ -1777,7 +1902,10 @@
}
}
} else {
- rt2800_bbp_write(rt2x00dev, 82, 0xf2);
+ if (rt2x00_rt(rt2x00dev, RT3572))
+ rt2800_bbp_write(rt2x00dev, 82, 0x94);
+ else
+ rt2800_bbp_write(rt2x00dev, 82, 0xf2);
if (test_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags))
rt2800_bbp_write(rt2x00dev, 75, 0x46);
@@ -1791,12 +1919,17 @@
rt2x00_set_field32(®, TX_BAND_CFG_BG, rf->channel <= 14);
rt2800_register_write(rt2x00dev, TX_BAND_CFG, reg);
+ if (rt2x00_rt(rt2x00dev, RT3572))
+ rt2800_rfcsr_write(rt2x00dev, 8, 0);
+
tx_pin = 0;
/* Turn on unused PA or LNA when not using 1T or 1R */
if (rt2x00dev->default_ant.tx_chain_num == 2) {
- rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A1_EN, 1);
- rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G1_EN, 1);
+ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A1_EN,
+ rf->channel > 14);
+ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G1_EN,
+ rf->channel <= 14);
}
/* Turn on unused PA or LNA when not using 1T or 1R */
@@ -1809,11 +1942,18 @@
rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G0_EN, 1);
rt2x00_set_field32(&tx_pin, TX_PIN_CFG_RFTR_EN, 1);
rt2x00_set_field32(&tx_pin, TX_PIN_CFG_TRSW_EN, 1);
- rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G0_EN, rf->channel <= 14);
+ if (test_bit(CAPABILITY_BT_COEXIST, &rt2x00dev->cap_flags))
+ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G0_EN, 1);
+ else
+ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G0_EN,
+ rf->channel <= 14);
rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A0_EN, rf->channel > 14);
rt2800_register_write(rt2x00dev, TX_PIN_CFG, tx_pin);
+ if (rt2x00_rt(rt2x00dev, RT3572))
+ rt2800_rfcsr_write(rt2x00dev, 8, 0x80);
+
rt2800_bbp_read(rt2x00dev, 4, &bbp);
rt2x00_set_field8(&bbp, BBP4_BANDWIDTH, 2 * conf_is_ht40(conf));
rt2800_bbp_write(rt2x00dev, 4, bbp);
@@ -2413,6 +2553,9 @@
rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400);
rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000);
rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000030);
+ } else if (rt2x00_rt(rt2x00dev, RT3572)) {
+ rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400);
+ rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606);
} else if (rt2x00_rt(rt2x00dev, RT5390)) {
rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000404);
rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606);
@@ -2799,6 +2942,7 @@
}
if (rt2800_is_305x_soc(rt2x00dev) ||
+ rt2x00_rt(rt2x00dev, RT3572) ||
rt2x00_rt(rt2x00dev, RT5390))
rt2800_bbp_write(rt2x00dev, 31, 0x08);
@@ -2828,6 +2972,7 @@
rt2x00_rt(rt2x00dev, RT3071) ||
rt2x00_rt(rt2x00dev, RT3090) ||
rt2x00_rt(rt2x00dev, RT3390) ||
+ rt2x00_rt(rt2x00dev, RT3572) ||
rt2x00_rt(rt2x00dev, RT5390)) {
rt2800_bbp_write(rt2x00dev, 79, 0x13);
rt2800_bbp_write(rt2x00dev, 80, 0x05);
@@ -2868,6 +3013,7 @@
rt2x00_rt_rev_gte(rt2x00dev, RT3071, REV_RT3071E) ||
rt2x00_rt_rev_gte(rt2x00dev, RT3090, REV_RT3090E) ||
rt2x00_rt_rev_gte(rt2x00dev, RT3390, REV_RT3390E) ||
+ rt2x00_rt(rt2x00dev, RT3572) ||
rt2x00_rt(rt2x00dev, RT5390) ||
rt2800_is_305x_soc(rt2x00dev))
rt2800_bbp_write(rt2x00dev, 103, 0xc0);
@@ -2895,6 +3041,7 @@
if (rt2x00_rt(rt2x00dev, RT3071) ||
rt2x00_rt(rt2x00dev, RT3090) ||
rt2x00_rt(rt2x00dev, RT3390) ||
+ rt2x00_rt(rt2x00dev, RT3572) ||
rt2x00_rt(rt2x00dev, RT5390)) {
rt2800_bbp_read(rt2x00dev, 138, &value);
@@ -3031,6 +3178,7 @@
!rt2x00_rt(rt2x00dev, RT3071) &&
!rt2x00_rt(rt2x00dev, RT3090) &&
!rt2x00_rt(rt2x00dev, RT3390) &&
+ !rt2x00_rt(rt2x00dev, RT3572) &&
!rt2x00_rt(rt2x00dev, RT5390) &&
!rt2800_is_305x_soc(rt2x00dev))
return 0;
@@ -3109,6 +3257,38 @@
rt2800_rfcsr_write(rt2x00dev, 29, 0x8f);
rt2800_rfcsr_write(rt2x00dev, 30, 0x20);
rt2800_rfcsr_write(rt2x00dev, 31, 0x0f);
+ } else if (rt2x00_rt(rt2x00dev, RT3572)) {
+ rt2800_rfcsr_write(rt2x00dev, 0, 0x70);
+ rt2800_rfcsr_write(rt2x00dev, 1, 0x81);
+ rt2800_rfcsr_write(rt2x00dev, 2, 0xf1);
+ rt2800_rfcsr_write(rt2x00dev, 3, 0x02);
+ rt2800_rfcsr_write(rt2x00dev, 4, 0x4c);
+ rt2800_rfcsr_write(rt2x00dev, 5, 0x05);
+ rt2800_rfcsr_write(rt2x00dev, 6, 0x4a);
+ rt2800_rfcsr_write(rt2x00dev, 7, 0xd8);
+ rt2800_rfcsr_write(rt2x00dev, 9, 0xc3);
+ rt2800_rfcsr_write(rt2x00dev, 10, 0xf1);
+ rt2800_rfcsr_write(rt2x00dev, 11, 0xb9);
+ rt2800_rfcsr_write(rt2x00dev, 12, 0x70);
+ rt2800_rfcsr_write(rt2x00dev, 13, 0x65);
+ rt2800_rfcsr_write(rt2x00dev, 14, 0xa0);
+ rt2800_rfcsr_write(rt2x00dev, 15, 0x53);
+ rt2800_rfcsr_write(rt2x00dev, 16, 0x4c);
+ rt2800_rfcsr_write(rt2x00dev, 17, 0x23);
+ rt2800_rfcsr_write(rt2x00dev, 18, 0xac);
+ rt2800_rfcsr_write(rt2x00dev, 19, 0x93);
+ rt2800_rfcsr_write(rt2x00dev, 20, 0xb3);
+ rt2800_rfcsr_write(rt2x00dev, 21, 0xd0);
+ rt2800_rfcsr_write(rt2x00dev, 22, 0x00);
+ rt2800_rfcsr_write(rt2x00dev, 23, 0x3c);
+ rt2800_rfcsr_write(rt2x00dev, 24, 0x16);
+ rt2800_rfcsr_write(rt2x00dev, 25, 0x15);
+ rt2800_rfcsr_write(rt2x00dev, 26, 0x85);
+ rt2800_rfcsr_write(rt2x00dev, 27, 0x00);
+ rt2800_rfcsr_write(rt2x00dev, 28, 0x00);
+ rt2800_rfcsr_write(rt2x00dev, 29, 0x9b);
+ rt2800_rfcsr_write(rt2x00dev, 30, 0x09);
+ rt2800_rfcsr_write(rt2x00dev, 31, 0x10);
} else if (rt2800_is_305x_soc(rt2x00dev)) {
rt2800_rfcsr_write(rt2x00dev, 0, 0x50);
rt2800_rfcsr_write(rt2x00dev, 1, 0x01);
@@ -3258,6 +3438,19 @@
rt2800_register_read(rt2x00dev, GPIO_SWITCH, ®);
rt2x00_set_field32(®, GPIO_SWITCH_5, 0);
rt2800_register_write(rt2x00dev, GPIO_SWITCH, reg);
+ } else if (rt2x00_rt(rt2x00dev, RT3572)) {
+ rt2800_rfcsr_read(rt2x00dev, 6, &rfcsr);
+ rt2x00_set_field8(&rfcsr, RFCSR6_R2, 1);
+ rt2800_rfcsr_write(rt2x00dev, 6, rfcsr);
+
+ rt2800_register_read(rt2x00dev, LDO_CFG0, ®);
+ rt2x00_set_field32(®, LDO_CFG0_LDO_CORE_VLEVEL, 3);
+ rt2x00_set_field32(®, LDO_CFG0_BGSEL, 1);
+ rt2800_register_write(rt2x00dev, LDO_CFG0, reg);
+ msleep(1);
+ rt2800_register_read(rt2x00dev, LDO_CFG0, ®);
+ rt2x00_set_field32(®, LDO_CFG0_BGSEL, 1);
+ rt2800_register_write(rt2x00dev, LDO_CFG0, reg);
}
/*
@@ -3270,7 +3463,8 @@
rt2800_init_rx_filter(rt2x00dev, true, 0x27, 0x19);
} else if (rt2x00_rt(rt2x00dev, RT3071) ||
rt2x00_rt(rt2x00dev, RT3090) ||
- rt2x00_rt(rt2x00dev, RT3390)) {
+ rt2x00_rt(rt2x00dev, RT3390) ||
+ rt2x00_rt(rt2x00dev, RT3572)) {
rt2x00dev->calibration[0] =
rt2800_init_rx_filter(rt2x00dev, false, 0x07, 0x13);
rt2x00dev->calibration[1] =
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.h b/drivers/net/wireless/rt2x00/rt2800lib.h
index f2d1594..69deb31 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.h
+++ b/drivers/net/wireless/rt2x00/rt2800lib.h
@@ -152,7 +152,6 @@
struct txentry_desc *txdesc);
void rt2800_process_rxwi(struct queue_entry *entry, struct rxdone_entry_desc *txdesc);
-void rt2800_txdone(struct rt2x00_dev *rt2x00dev);
void rt2800_txdone_entry(struct queue_entry *entry, u32 status);
void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc);
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c
index cc4a54f..9ccc537 100644
--- a/drivers/net/wireless/rt2x00/rt2800pci.c
+++ b/drivers/net/wireless/rt2x00/rt2800pci.c
@@ -219,7 +219,7 @@
break;
default:
break;
- };
+ }
}
static void rt2800pci_kick_queue(struct data_queue *queue)
@@ -501,7 +501,9 @@
rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e1f);
rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e00);
- if (rt2x00_rt(rt2x00dev, RT5390)) {
+ if (rt2x00_is_pcie(rt2x00dev) &&
+ (rt2x00_rt(rt2x00dev, RT3572) ||
+ rt2x00_rt(rt2x00dev, RT5390))) {
rt2x00pci_register_read(rt2x00dev, AUX_CTRL, ®);
rt2x00_set_field32(®, AUX_CTRL_FORCE_PCIE_CLK, 1);
rt2x00_set_field32(®, AUX_CTRL_WAKE_PCIE_EN, 1);
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
index ba82c97..6e92298 100644
--- a/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -457,6 +457,87 @@
/*
* TX control handlers
*/
+static bool rt2800usb_txdone_entry_check(struct queue_entry *entry, u32 reg)
+{
+ __le32 *txwi;
+ u32 word;
+ int wcid, ack, pid;
+ int tx_wcid, tx_ack, tx_pid;
+
+ wcid = rt2x00_get_field32(reg, TX_STA_FIFO_WCID);
+ ack = rt2x00_get_field32(reg, TX_STA_FIFO_TX_ACK_REQUIRED);
+ pid = rt2x00_get_field32(reg, TX_STA_FIFO_PID_TYPE);
+
+ /*
+ * This frames has returned with an IO error,
+ * so the status report is not intended for this
+ * frame.
+ */
+ if (test_bit(ENTRY_DATA_IO_FAILED, &entry->flags)) {
+ rt2x00lib_txdone_noinfo(entry, TXDONE_FAILURE);
+ return false;
+ }
+
+ /*
+ * Validate if this TX status report is intended for
+ * this entry by comparing the WCID/ACK/PID fields.
+ */
+ txwi = rt2800usb_get_txwi(entry);
+
+ rt2x00_desc_read(txwi, 1, &word);
+ tx_wcid = rt2x00_get_field32(word, TXWI_W1_WIRELESS_CLI_ID);
+ tx_ack = rt2x00_get_field32(word, TXWI_W1_ACK);
+ tx_pid = rt2x00_get_field32(word, TXWI_W1_PACKETID);
+
+ if ((wcid != tx_wcid) || (ack != tx_ack) || (pid != tx_pid)) {
+ WARNING(entry->queue->rt2x00dev,
+ "TX status report missed for queue %d entry %d\n",
+ entry->queue->qid, entry->entry_idx);
+ rt2x00lib_txdone_noinfo(entry, TXDONE_UNKNOWN);
+ return false;
+ }
+
+ return true;
+}
+
+static void rt2800usb_txdone(struct rt2x00_dev *rt2x00dev)
+{
+ struct data_queue *queue;
+ struct queue_entry *entry;
+ u32 reg;
+ u8 qid;
+
+ while (kfifo_get(&rt2x00dev->txstatus_fifo, ®)) {
+
+ /* TX_STA_FIFO_PID_QUEUE is a 2-bit field, thus
+ * qid is guaranteed to be one of the TX QIDs
+ */
+ qid = rt2x00_get_field32(reg, TX_STA_FIFO_PID_QUEUE);
+ queue = rt2x00queue_get_tx_queue(rt2x00dev, qid);
+ if (unlikely(!queue)) {
+ WARNING(rt2x00dev, "Got TX status for an unavailable "
+ "queue %u, dropping\n", qid);
+ continue;
+ }
+
+ /*
+ * Inside each queue, we process each entry in a chronological
+ * order. We first check that the queue is not empty.
+ */
+ entry = NULL;
+ while (!rt2x00queue_empty(queue)) {
+ entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
+ if (rt2800usb_txdone_entry_check(entry, reg))
+ break;
+ }
+
+ if (!entry || rt2x00queue_empty(queue))
+ break;
+
+ rt2800_txdone_entry(entry, reg);
+ }
+}
+
static void rt2800usb_work_txdone(struct work_struct *work)
{
struct rt2x00_dev *rt2x00dev =
@@ -464,7 +545,7 @@
struct data_queue *queue;
struct queue_entry *entry;
- rt2800_txdone(rt2x00dev);
+ rt2800usb_txdone(rt2x00dev);
/*
* Process any trailing TX status reports for IO failures,
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
index c446db6..4efaf886 100644
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -29,6 +29,7 @@
#define RT2X00_H
#include <linux/bitops.h>
+#include <linux/interrupt.h>
#include <linux/skbuff.h>
#include <linux/workqueue.h>
#include <linux/firmware.h>
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
index 939821b..0955c94 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -583,6 +583,18 @@
rt2x00dev->ops->lib->fill_rxdone(entry, &rxdesc);
/*
+ * Check for valid size in case we get corrupted descriptor from
+ * hardware.
+ */
+ if (unlikely(rxdesc.size == 0 ||
+ rxdesc.size > entry->queue->data_size)) {
+ WARNING(rt2x00dev, "Wrong frame size %d max %d.\n",
+ rxdesc.size, entry->queue->data_size);
+ dev_kfree_skb(entry->skb);
+ goto renew_skb;
+ }
+
+ /*
* The data behind the ieee80211 header must be
* aligned on a 4 byte boundary.
*/
@@ -642,6 +654,7 @@
ieee80211_rx_ni(rt2x00dev->hw, entry->skb);
+renew_skb:
/*
* Replace the skb with the freshly allocated one.
*/
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c
index ab8c16f..c7fc9de 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.c
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.c
@@ -206,7 +206,6 @@
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb);
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)entry->skb->data;
struct rt2x00_intf *intf = vif_to_intf(tx_info->control.vif);
- unsigned long irqflags;
if (!(tx_info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ))
return;
@@ -227,14 +226,14 @@
* sequence counting per-frame, since those will override the
* sequence counter given by mac80211.
*/
- spin_lock_irqsave(&intf->seqlock, irqflags);
+ spin_lock(&intf->seqlock);
if (test_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags))
intf->seqno += 0x10;
hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
hdr->seq_ctrl |= cpu_to_le16(intf->seqno);
- spin_unlock_irqrestore(&intf->seqlock, irqflags);
+ spin_unlock(&intf->seqlock);
}
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h
index 167d458..59004749 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.h
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.h
@@ -54,7 +54,7 @@
* @QID_RX: RX queue
* @QID_OTHER: None of the above (don't use, only present for completeness)
* @QID_BEACON: Beacon queue (value unspecified, don't send it to device)
- * @QID_ATIM: Atim queue (value unspeficied, don't send it to device)
+ * @QID_ATIM: Atim queue (value unspecified, don't send it to device)
*/
enum data_queue_qid {
QID_AC_VO = 0,
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c
index 8f90f62..b6b4542 100644
--- a/drivers/net/wireless/rt2x00/rt2x00usb.c
+++ b/drivers/net/wireless/rt2x00/rt2x00usb.c
@@ -802,6 +802,7 @@
int retval;
usb_dev = usb_get_dev(usb_dev);
+ usb_reset_device(usb_dev);
hw = ieee80211_alloc_hw(sizeof(struct rt2x00_dev), ops->hw);
if (!hw) {
diff --git a/drivers/net/wireless/rtl818x/rtl8180/dev.c b/drivers/net/wireless/rtl818x/rtl8180/dev.c
index 80db5ca..66b29dc 100644
--- a/drivers/net/wireless/rtl818x/rtl8180/dev.c
+++ b/drivers/net/wireless/rtl818x/rtl8180/dev.c
@@ -16,6 +16,7 @@
*/
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/pci.h>
#include <linux/slab.h>
#include <linux/delay.h>
diff --git a/drivers/net/wireless/rtlwifi/Kconfig b/drivers/net/wireless/rtlwifi/Kconfig
index 5aee8b2..45e1476 100644
--- a/drivers/net/wireless/rtlwifi/Kconfig
+++ b/drivers/net/wireless/rtlwifi/Kconfig
@@ -21,6 +21,17 @@
If you choose to build it as a module, it will be called rtl8192se
+config RTL8192DE
+ tristate "Realtek RTL8192DE/RTL8188DE PCIe Wireless Network Adapter"
+ depends on MAC80211 && EXPERIMENTAL
+ select FW_LOADER
+ select RTLWIFI
+ ---help---
+ This is the driver for Realtek RTL8192DE/RTL8188DE 802.11n PCIe
+ wireless network adapters.
+
+ If you choose to build it as a module, it will be called rtl8192de
+
config RTL8192CU
tristate "Realtek RTL8192CU/RTL8188CU USB Wireless Network Adapter"
depends on MAC80211 && USB && EXPERIMENTAL
@@ -35,10 +46,10 @@
config RTLWIFI
tristate
- depends on RTL8192CE || RTL8192CU || RTL8192SE
+ depends on RTL8192CE || RTL8192CU || RTL8192SE || RTL8192DE
default m
config RTL8192C_COMMON
tristate
- depends on RTL8192CE || RTL8192CU || RTL8192SE
+ depends on RTL8192CE || RTL8192CU
default m
diff --git a/drivers/net/wireless/rtlwifi/Makefile b/drivers/net/wireless/rtlwifi/Makefile
index 7acce83..97935c5 100644
--- a/drivers/net/wireless/rtlwifi/Makefile
+++ b/drivers/net/wireless/rtlwifi/Makefile
@@ -23,5 +23,6 @@
obj-$(CONFIG_RTL8192CE) += rtl8192ce/
obj-$(CONFIG_RTL8192CU) += rtl8192cu/
obj-$(CONFIG_RTL8192SE) += rtl8192se/
+obj-$(CONFIG_RTL8192DE) += rtl8192de/
ccflags-y += -D__CHECK_ENDIAN__
diff --git a/drivers/net/wireless/rtlwifi/base.c b/drivers/net/wireless/rtlwifi/base.c
index ccb6da3..bc13533 100644
--- a/drivers/net/wireless/rtlwifi/base.c
+++ b/drivers/net/wireless/rtlwifi/base.c
@@ -523,7 +523,7 @@
mac->opmode == NL80211_IFTYPE_ADHOC)
bw_40 = sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40;
- if ((bw_40 == true) && sgi_40)
+ if (bw_40 && sgi_40)
tcb_desc->use_shortgi = true;
else if ((bw_40 == false) && sgi_20)
tcb_desc->use_shortgi = true;
@@ -888,7 +888,6 @@
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
- struct rtl_tid_data *tid_data;
struct rtl_sta_info *sta_entry = NULL;
if (sta == NULL)
@@ -906,7 +905,6 @@
return -EINVAL;
sta_entry = (struct rtl_sta_info *)sta->drv_priv;
- tid_data = &sta_entry->tids[tid];
sta_entry->tids[tid].agg.agg_state = RTL_AGG_STOP;
ieee80211_stop_tx_ba_cb_irqsafe(mac->vif, sta->addr, tid);
@@ -918,7 +916,6 @@
struct ieee80211_sta *sta, u16 tid)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
- struct rtl_tid_data *tid_data;
struct rtl_sta_info *sta_entry = NULL;
if (sta == NULL)
@@ -936,7 +933,6 @@
return -EINVAL;
sta_entry = (struct rtl_sta_info *)sta->drv_priv;
- tid_data = &sta_entry->tids[tid];
sta_entry->tids[tid].agg.agg_state = RTL_AGG_OPERATIONAL;
return 0;
diff --git a/drivers/net/wireless/rtlwifi/core.c b/drivers/net/wireless/rtlwifi/core.c
index d2ec253..03ce696 100644
--- a/drivers/net/wireless/rtlwifi/core.c
+++ b/drivers/net/wireless/rtlwifi/core.c
@@ -335,8 +335,8 @@
* before going offchannel, or dis-association or delete BA will
* happen by AP
*/
- if (rtlpriv->mac80211.offchan_deley) {
- rtlpriv->mac80211.offchan_deley = false;
+ if (rtlpriv->mac80211.offchan_delay) {
+ rtlpriv->mac80211.offchan_delay = false;
mdelay(50);
}
rtlphy->current_channel = wide_chan;
@@ -443,11 +443,11 @@
sta_entry->wireless_mode = WIRELESS_MODE_G;
if (sta->supp_rates[0] <= 0xf)
sta_entry->wireless_mode = WIRELESS_MODE_B;
- if (sta->ht_cap.ht_supported == true)
+ if (sta->ht_cap.ht_supported)
sta_entry->wireless_mode = WIRELESS_MODE_N_24G;
} else if (rtlhal->current_bandtype == BAND_ON_5G) {
sta_entry->wireless_mode = WIRELESS_MODE_A;
- if (sta->ht_cap.ht_supported == true)
+ if (sta->ht_cap.ht_supported)
sta_entry->wireless_mode = WIRELESS_MODE_N_24G;
}
@@ -650,7 +650,7 @@
RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE,
("BSS_CHANGED_HT\n"));
rcu_read_lock();
- sta = get_sta(hw, vif, (u8 *)bss_conf->bssid);
+ sta = get_sta(hw, vif, bss_conf->bssid);
if (sta) {
if (sta->ht_cap.ampdu_density >
mac->current_ampdu_density)
@@ -685,7 +685,7 @@
rtlpriv->cfg->ops->set_network_type(hw, vif->type);
rcu_read_lock();
- sta = get_sta(hw, vif, (u8 *)bss_conf->bssid);
+ sta = get_sta(hw, vif, bss_conf->bssid);
if (!sta) {
rcu_read_unlock();
goto out;
diff --git a/drivers/net/wireless/rtlwifi/core.h b/drivers/net/wireless/rtlwifi/core.h
index 4b247db..f02824a 100644
--- a/drivers/net/wireless/rtlwifi/core.h
+++ b/drivers/net/wireless/rtlwifi/core.h
@@ -30,6 +30,8 @@
#ifndef __RTL_CORE_H__
#define __RTL_CORE_H__
+#include <net/mac80211.h>
+
#define RTL_SUPPORTED_FILTERS \
(FIF_PROMISC_IN_BSS | \
FIF_ALLMULTI | FIF_CONTROL | \
diff --git a/drivers/net/wireless/rtlwifi/efuse.c b/drivers/net/wireless/rtlwifi/efuse.c
index 50de6f5..3fc21f6 100644
--- a/drivers/net/wireless/rtlwifi/efuse.c
+++ b/drivers/net/wireless/rtlwifi/efuse.c
@@ -382,7 +382,7 @@
}
}
- if (wordchanged == true)
+ if (wordchanged)
hdr_num++;
}
@@ -453,7 +453,7 @@
base = offset * 8;
for (i = 0; i < 8; i++) {
- if (first_pg == true) {
+ if (first_pg) {
word_en &= ~(BIT(i / 2));
@@ -505,7 +505,7 @@
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
- if (rtlefuse->autoload_failflag == true)
+ if (rtlefuse->autoload_failflag)
memset(&rtlefuse->efuse_map[EFUSE_INIT_MAP][0], 0xFF,
rtlpriv->cfg->maps[EFUSE_HWSET_MAX_SIZE]);
else
@@ -690,7 +690,7 @@
}
}
- if (dataempty == true) {
+ if (dataempty) {
*readstate = PG_STATE_DATA;
} else {
*efuse_addr = *efuse_addr + (word_cnts * 2) + 1;
@@ -925,7 +925,7 @@
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct pgpkt_struct target_pkt;
u8 write_state = PG_STATE_HEADER;
- int continual = true, dataempty = true, result = true;
+ int continual = true, result = true;
u16 efuse_addr = 0;
u8 efuse_data;
u8 target_word_cnts = 0;
@@ -953,7 +953,6 @@
(EFUSE_MAX_SIZE - EFUSE_OOB_PROTECT_BYTES))) {
if (write_state == PG_STATE_HEADER) {
- dataempty = true;
badworden = 0x0F;
RTPRINT(rtlpriv, FEEPROM, EFUSE_PG,
("efuse PG_STATE_HEADER\n"));
@@ -1176,13 +1175,12 @@
{
int continual = true;
u16 efuse_addr = 0;
- u8 hoffset, hworden;
+ u8 hworden;
u8 efuse_data, word_cnts;
while (continual && efuse_one_byte_read(hw, efuse_addr, &efuse_data)
&& (efuse_addr < EFUSE_MAX_SIZE)) {
if (efuse_data != 0xFF) {
- hoffset = (efuse_data >> 4) & 0x0F;
hworden = efuse_data & 0x0F;
word_cnts = efuse_calculate_word_cnts(hworden);
efuse_addr = efuse_addr + (word_cnts * 2) + 1;
diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c
index 254b64b..532c7d3 100644
--- a/drivers/net/wireless/rtlwifi/pci.c
+++ b/drivers/net/wireless/rtlwifi/pci.c
@@ -35,10 +35,10 @@
#include "efuse.h"
static const u16 pcibridge_vendors[PCI_BRIDGE_VENDOR_MAX] = {
- INTEL_VENDOR_ID,
- ATI_VENDOR_ID,
- AMD_VENDOR_ID,
- SIS_VENDOR_ID
+ PCI_VENDOR_ID_INTEL,
+ PCI_VENDOR_ID_ATI,
+ PCI_VENDOR_ID_AMD,
+ PCI_VENDOR_ID_SI
};
static const u8 ac_to_hwq[] = {
@@ -390,7 +390,7 @@
u8 linkctrl_reg;
/*Link Control Register */
- pos = pci_find_capability(pdev, PCI_CAP_ID_EXP);
+ pos = pci_pcie_cap(pdev);
pci_read_config_byte(pdev, pos + PCI_EXP_LNKCTL, &linkctrl_reg);
pcipriv->ndis_adapter.linkctrl_reg = linkctrl_reg;
@@ -581,7 +581,7 @@
fc = rtl_get_fc(skb);
if (ieee80211_is_nullfunc(fc)) {
if (ieee80211_has_pm(fc)) {
- rtlpriv->mac80211.offchan_deley = true;
+ rtlpriv->mac80211.offchan_delay = true;
rtlpriv->psc.state_inap = 1;
} else {
rtlpriv->psc.state_inap = 0;
@@ -622,10 +622,60 @@
if (((rtlpriv->link_info.num_rx_inperiod +
rtlpriv->link_info.num_tx_inperiod) > 8) ||
(rtlpriv->link_info.num_rx_inperiod > 2)) {
- rtl_lps_leave(hw);
+ tasklet_schedule(&rtlpriv->works.ips_leave_tasklet);
}
}
+static void _rtl_receive_one(struct ieee80211_hw *hw, struct sk_buff *skb,
+ struct ieee80211_rx_status rx_status)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct ieee80211_hdr *hdr = rtl_get_hdr(skb);
+ __le16 fc = rtl_get_fc(skb);
+ bool unicast = false;
+ struct sk_buff *uskb = NULL;
+ u8 *pdata;
+
+
+ memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status));
+
+ if (is_broadcast_ether_addr(hdr->addr1)) {
+ ;/*TODO*/
+ } else if (is_multicast_ether_addr(hdr->addr1)) {
+ ;/*TODO*/
+ } else {
+ unicast = true;
+ rtlpriv->stats.rxbytesunicast += skb->len;
+ }
+
+ rtl_is_special_data(hw, skb, false);
+
+ if (ieee80211_is_data(fc)) {
+ rtlpriv->cfg->ops->led_control(hw, LED_CTL_RX);
+
+ if (unicast)
+ rtlpriv->link_info.num_rx_inperiod++;
+ }
+
+ /* for sw lps */
+ rtl_swlps_beacon(hw, (void *)skb->data, skb->len);
+ rtl_recognize_peer(hw, (void *)skb->data, skb->len);
+ if ((rtlpriv->mac80211.opmode == NL80211_IFTYPE_AP) &&
+ (rtlpriv->rtlhal.current_bandtype == BAND_ON_2_4G) &&
+ (ieee80211_is_beacon(fc) || ieee80211_is_probe_resp(fc)))
+ return;
+
+ if (unlikely(!rtl_action_proc(hw, skb, false)))
+ return;
+
+ uskb = dev_alloc_skb(skb->len + 128);
+ memcpy(IEEE80211_SKB_RXCB(uskb), &rx_status, sizeof(rx_status));
+ pdata = (u8 *)skb_put(uskb, skb->len);
+ memcpy(pdata, skb->data, skb->len);
+
+ ieee80211_rx_irqsafe(hw, uskb);
+}
+
static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
@@ -637,170 +687,101 @@
u8 own;
u8 tmp_one;
u32 bufferaddress;
- bool unicast = false;
struct rtl_stats stats = {
.signal = 0,
.noise = -98,
.rate = 0,
};
+ int index = rtlpci->rx_ring[rx_queue_idx].idx;
/*RX NORMAL PKT */
while (count--) {
/*rx descriptor */
struct rtl_rx_desc *pdesc = &rtlpci->rx_ring[rx_queue_idx].desc[
- rtlpci->rx_ring[rx_queue_idx].idx];
+ index];
/*rx pkt */
struct sk_buff *skb = rtlpci->rx_ring[rx_queue_idx].rx_buf[
- rtlpci->rx_ring[rx_queue_idx].idx];
+ index];
+ struct sk_buff *new_skb = NULL;
own = (u8) rtlpriv->cfg->ops->get_desc((u8 *) pdesc,
false, HW_DESC_OWN);
- if (own) {
- /*wait data to be filled by hardware */
- return;
- } else {
- struct ieee80211_hdr *hdr;
- __le16 fc;
- struct sk_buff *new_skb = NULL;
+ /*wait data to be filled by hardware */
+ if (own)
+ break;
- rtlpriv->cfg->ops->query_rx_desc(hw, &stats,
- &rx_status,
- (u8 *) pdesc, skb);
+ rtlpriv->cfg->ops->query_rx_desc(hw, &stats,
+ &rx_status,
+ (u8 *) pdesc, skb);
- new_skb = dev_alloc_skb(rtlpci->rxbuffersize);
- if (unlikely(!new_skb)) {
- RT_TRACE(rtlpriv, (COMP_INTR | COMP_RECV),
- DBG_DMESG,
- ("can't alloc skb for rx\n"));
- goto done;
- }
+ if (stats.crc || stats.hwerror)
+ goto done;
- pci_unmap_single(rtlpci->pdev,
- *((dma_addr_t *) skb->cb),
- rtlpci->rxbuffersize,
- PCI_DMA_FROMDEVICE);
+ new_skb = dev_alloc_skb(rtlpci->rxbuffersize);
+ if (unlikely(!new_skb)) {
+ RT_TRACE(rtlpriv, (COMP_INTR | COMP_RECV),
+ DBG_DMESG,
+ ("can't alloc skb for rx\n"));
+ goto done;
+ }
- skb_put(skb, rtlpriv->cfg->ops->get_desc((u8 *) pdesc,
- false,
- HW_DESC_RXPKT_LEN));
- skb_reserve(skb,
- stats.rx_drvinfo_size + stats.rx_bufshift);
+ pci_unmap_single(rtlpci->pdev,
+ *((dma_addr_t *) skb->cb),
+ rtlpci->rxbuffersize,
+ PCI_DMA_FROMDEVICE);
- /*
- *NOTICE This can not be use for mac80211,
- *this is done in mac80211 code,
- *if you done here sec DHCP will fail
- *skb_trim(skb, skb->len - 4);
- */
+ skb_put(skb, rtlpriv->cfg->ops->get_desc((u8 *) pdesc, false,
+ HW_DESC_RXPKT_LEN));
+ skb_reserve(skb, stats.rx_drvinfo_size + stats.rx_bufshift);
- hdr = rtl_get_hdr(skb);
- fc = rtl_get_fc(skb);
+ /*
+ * NOTICE This can not be use for mac80211,
+ * this is done in mac80211 code,
+ * if you done here sec DHCP will fail
+ * skb_trim(skb, skb->len - 4);
+ */
- if (!stats.crc && !stats.hwerror) {
- memcpy(IEEE80211_SKB_RXCB(skb), &rx_status,
- sizeof(rx_status));
+ _rtl_receive_one(hw, skb, rx_status);
- if (is_broadcast_ether_addr(hdr->addr1)) {
- ;/*TODO*/
- } else if (is_multicast_ether_addr(hdr->addr1)) {
- ;/*TODO*/
- } else {
- unicast = true;
- rtlpriv->stats.rxbytesunicast +=
- skb->len;
- }
+ if (((rtlpriv->link_info.num_rx_inperiod +
+ rtlpriv->link_info.num_tx_inperiod) > 8) ||
+ (rtlpriv->link_info.num_rx_inperiod > 2)) {
+ tasklet_schedule(&rtlpriv->works.ips_leave_tasklet);
+ }
- rtl_is_special_data(hw, skb, false);
+ dev_kfree_skb_any(skb);
+ skb = new_skb;
- if (ieee80211_is_data(fc)) {
- rtlpriv->cfg->ops->led_control(hw,
- LED_CTL_RX);
-
- if (unicast)
- rtlpriv->link_info.
- num_rx_inperiod++;
- }
-
- /* for sw lps */
- rtl_swlps_beacon(hw, (void *)skb->data,
- skb->len);
- rtl_recognize_peer(hw, (void *)skb->data,
- skb->len);
- if ((rtlpriv->mac80211.opmode ==
- NL80211_IFTYPE_AP) &&
- (rtlpriv->rtlhal.current_bandtype ==
- BAND_ON_2_4G) &&
- (ieee80211_is_beacon(fc) ||
- ieee80211_is_probe_resp(fc))) {
- dev_kfree_skb_any(skb);
- } else {
- if (unlikely(!rtl_action_proc(hw, skb,
- false))) {
- dev_kfree_skb_any(skb);
- } else {
- struct sk_buff *uskb = NULL;
- u8 *pdata;
- uskb = dev_alloc_skb(skb->len
- + 128);
- memcpy(IEEE80211_SKB_RXCB(uskb),
- &rx_status,
- sizeof(rx_status));
- pdata = (u8 *)skb_put(uskb,
- skb->len);
- memcpy(pdata, skb->data,
- skb->len);
- dev_kfree_skb_any(skb);
-
- ieee80211_rx_irqsafe(hw, uskb);
- }
- }
- } else {
- dev_kfree_skb_any(skb);
- }
-
- if (((rtlpriv->link_info.num_rx_inperiod +
- rtlpriv->link_info.num_tx_inperiod) > 8) ||
- (rtlpriv->link_info.num_rx_inperiod > 2)) {
- rtl_lps_leave(hw);
- }
-
- skb = new_skb;
-
- rtlpci->rx_ring[rx_queue_idx].rx_buf[rtlpci->
- rx_ring
- [rx_queue_idx].
- idx] = skb;
- *((dma_addr_t *) skb->cb) =
+ rtlpci->rx_ring[rx_queue_idx].rx_buf[index] = skb;
+ *((dma_addr_t *) skb->cb) =
pci_map_single(rtlpci->pdev, skb_tail_pointer(skb),
rtlpci->rxbuffersize,
PCI_DMA_FROMDEVICE);
- }
done:
bufferaddress = (*((dma_addr_t *)skb->cb));
tmp_one = 1;
rtlpriv->cfg->ops->set_desc((u8 *) pdesc, false,
HW_DESC_RXBUFF_ADDR,
(u8 *)&bufferaddress);
- rtlpriv->cfg->ops->set_desc((u8 *)pdesc, false, HW_DESC_RXOWN,
- (u8 *)&tmp_one);
rtlpriv->cfg->ops->set_desc((u8 *)pdesc, false,
HW_DESC_RXPKT_LEN,
(u8 *)&rtlpci->rxbuffersize);
- if (rtlpci->rx_ring[rx_queue_idx].idx ==
- rtlpci->rxringcount - 1)
+ if (index == rtlpci->rxringcount - 1)
rtlpriv->cfg->ops->set_desc((u8 *)pdesc, false,
HW_DESC_RXERO,
(u8 *)&tmp_one);
- rtlpci->rx_ring[rx_queue_idx].idx =
- (rtlpci->rx_ring[rx_queue_idx].idx + 1) %
- rtlpci->rxringcount;
+ rtlpriv->cfg->ops->set_desc((u8 *)pdesc, false, HW_DESC_RXOWN,
+ (u8 *)&tmp_one);
+
+ index = (index + 1) % rtlpci->rxringcount;
}
+ rtlpci->rx_ring[rx_queue_idx].idx = index;
}
static irqreturn_t _rtl_pci_interrupt(int irq, void *dev_id)
@@ -938,6 +919,11 @@
_rtl_pci_tx_chk_waitq(hw);
}
+static void _rtl_pci_ips_leave_tasklet(struct ieee80211_hw *hw)
+{
+ rtl_lps_leave(hw);
+}
+
static void _rtl_pci_prepare_bcn_tasklet(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
@@ -1036,6 +1022,9 @@
tasklet_init(&rtlpriv->works.irq_prepare_bcn_tasklet,
(void (*)(unsigned long))_rtl_pci_prepare_bcn_tasklet,
(unsigned long)hw);
+ tasklet_init(&rtlpriv->works.ips_leave_tasklet,
+ (void (*)(unsigned long))_rtl_pci_ips_leave_tasklet,
+ (unsigned long)hw);
}
static int _rtl_pci_init_tx_ring(struct ieee80211_hw *hw,
@@ -1505,6 +1494,7 @@
synchronize_irq(rtlpci->pdev->irq);
tasklet_kill(&rtlpriv->works.irq_tasklet);
+ tasklet_kill(&rtlpriv->works.ips_leave_tasklet);
flush_workqueue(rtlpriv->works.rtl_wq);
destroy_workqueue(rtlpriv->works.rtl_wq);
@@ -1579,6 +1569,7 @@
set_hal_stop(rtlhal);
rtlpriv->cfg->ops->disable_interrupt(hw);
+ tasklet_kill(&rtlpriv->works.ips_leave_tasklet);
spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flags);
while (ppsc->rfchange_inprogress) {
diff --git a/drivers/net/wireless/rtlwifi/pci.h b/drivers/net/wireless/rtlwifi/pci.h
index 671b1f5..a50e551 100644
--- a/drivers/net/wireless/rtlwifi/pci.h
+++ b/drivers/net/wireless/rtlwifi/pci.h
@@ -62,12 +62,6 @@
.subdevice = PCI_ANY_ID,\
.driver_data = (kernel_ulong_t)&(cfg)
-#define INTEL_VENDOR_ID 0x8086
-#define SIS_VENDOR_ID 0x1039
-#define ATI_VENDOR_ID 0x1002
-#define ATI_DEVICE_ID 0x7914
-#define AMD_VENDOR_ID 0x1022
-
#define PCI_MAX_BRIDGE_NUMBER 255
#define PCI_MAX_DEVICES 32
#define PCI_MAX_FUNCTION 8
@@ -75,11 +69,6 @@
#define PCI_CONF_ADDRESS 0x0CF8 /*PCI Configuration Space Address */
#define PCI_CONF_DATA 0x0CFC /*PCI Configuration Space Data */
-#define PCI_CLASS_BRIDGE_DEV 0x06
-#define PCI_SUBCLASS_BR_PCI_TO_PCI 0x04
-#define PCI_CAPABILITY_ID_PCI_EXPRESS 0x10
-#define PCI_CAP_ID_EXP 0x10
-
#define U1DONTCARE 0xFF
#define U2DONTCARE 0xFFFF
#define U4DONTCARE 0xFFFFFFFF
diff --git a/drivers/net/wireless/rtlwifi/ps.c b/drivers/net/wireless/rtlwifi/ps.c
index 39b0297..a693fef 100644
--- a/drivers/net/wireless/rtlwifi/ps.c
+++ b/drivers/net/wireless/rtlwifi/ps.c
@@ -68,6 +68,7 @@
/*<2> Disable Interrupt */
rtlpriv->cfg->ops->disable_interrupt(hw);
+ tasklet_kill(&rtlpriv->works.irq_tasklet);
/*<3> Disable Adapter */
rtlpriv->cfg->ops->hw_disable(hw);
@@ -78,65 +79,18 @@
bool rtl_ps_set_rf_state(struct ieee80211_hw *hw,
enum rf_pwrstate state_toset,
- u32 changesource, bool protect_or_not)
+ u32 changesource)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
- enum rf_pwrstate rtstate;
bool actionallowed = false;
- u16 rfwait_cnt = 0;
- unsigned long flag;
-
- /*protect_or_not = true; */
-
- if (protect_or_not)
- goto no_protect;
-
- /*
- *Only one thread can change
- *the RF state at one time, and others
- *should wait to be executed.
- */
- while (true) {
- spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flag);
- if (ppsc->rfchange_inprogress) {
- spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock,
- flag);
-
- RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
- ("RF Change in progress!"
- "Wait to set..state_toset(%d).\n",
- state_toset));
-
- /* Set RF after the previous action is done. */
- while (ppsc->rfchange_inprogress) {
- rfwait_cnt++;
- mdelay(1);
-
- /*
- *Wait too long, return false to avoid
- *to be stuck here.
- */
- if (rfwait_cnt > 100)
- return false;
- }
- } else {
- ppsc->rfchange_inprogress = true;
- spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock,
- flag);
- break;
- }
- }
-
-no_protect:
- rtstate = ppsc->rfpwr_state;
switch (state_toset) {
case ERFON:
ppsc->rfoff_reason &= (~changesource);
if ((changesource == RF_CHANGE_BY_HW) &&
- (ppsc->hwradiooff == true)) {
+ (ppsc->hwradiooff)) {
ppsc->hwradiooff = false;
}
@@ -172,12 +126,6 @@
if (actionallowed)
rtlpriv->cfg->ops->set_rf_power_state(hw, state_toset);
- if (!protect_or_not) {
- spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flag);
- ppsc->rfchange_inprogress = false;
- spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag);
- }
-
return actionallowed;
}
EXPORT_SYMBOL(rtl_ps_set_rf_state);
@@ -200,8 +148,7 @@
}
}
- rtl_ps_set_rf_state(hw, ppsc->inactive_pwrstate,
- RF_CHANGE_BY_IPS, false);
+ rtl_ps_set_rf_state(hw, ppsc->inactive_pwrstate, RF_CHANGE_BY_IPS);
if (ppsc->inactive_pwrstate == ERFOFF &&
rtlhal->interface == INTF_PCI) {
@@ -289,12 +236,11 @@
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
enum rf_pwrstate rtstate;
- unsigned long flags;
if (mac->opmode != NL80211_IFTYPE_STATION)
return;
- spin_lock_irqsave(&rtlpriv->locks.ips_lock, flags);
+ spin_lock(&rtlpriv->locks.ips_lock);
if (ppsc->inactiveps) {
rtstate = ppsc->rfpwr_state;
@@ -310,7 +256,7 @@
}
}
- spin_unlock_irqrestore(&rtlpriv->locks.ips_lock, flags);
+ spin_unlock(&rtlpriv->locks.ips_lock);
}
/*for FW LPS*/
@@ -428,7 +374,6 @@
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
struct rtl_priv *rtlpriv = rtl_priv(hw);
- unsigned long flag;
if (!ppsc->fwctrl_lps)
return;
@@ -449,7 +394,7 @@
if (mac->link_state != MAC80211_LINKED)
return;
- spin_lock_irqsave(&rtlpriv->locks.lps_lock, flag);
+ spin_lock(&rtlpriv->locks.lps_lock);
/* Idle for a while if we connect to AP a while ago. */
if (mac->cnt_after_linked >= 2) {
@@ -461,7 +406,7 @@
}
}
- spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flag);
+ spin_unlock(&rtlpriv->locks.lps_lock);
}
/*Leave the leisure power save mode.*/
@@ -470,9 +415,8 @@
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
- unsigned long flag;
- spin_lock_irqsave(&rtlpriv->locks.lps_lock, flag);
+ spin_lock(&rtlpriv->locks.lps_lock);
if (ppsc->fwctrl_lps) {
if (ppsc->dot11_psmode != EACTIVE) {
@@ -493,7 +437,7 @@
rtl_lps_set_psmode(hw, EACTIVE);
}
}
- spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flag);
+ spin_unlock(&rtlpriv->locks.lps_lock);
}
/* For sw LPS*/
@@ -582,7 +526,6 @@
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
- unsigned long flag;
if (!rtlpriv->psc.swctrl_lps)
return;
@@ -595,9 +538,9 @@
RT_CLEAR_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM);
}
- spin_lock_irqsave(&rtlpriv->locks.lps_lock, flag);
- rtl_ps_set_rf_state(hw, ERFON, RF_CHANGE_BY_PS, false);
- spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flag);
+ spin_lock(&rtlpriv->locks.lps_lock);
+ rtl_ps_set_rf_state(hw, ERFON, RF_CHANGE_BY_PS);
+ spin_unlock(&rtlpriv->locks.lps_lock);
}
void rtl_swlps_rfon_wq_callback(void *data)
@@ -614,7 +557,6 @@
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
- unsigned long flag;
u8 sleep_intv;
if (!rtlpriv->psc.sw_ps_enabled)
@@ -631,16 +573,9 @@
if (rtlpriv->link_info.busytraffic)
return;
- spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flag);
- if (rtlpriv->psc.rfchange_inprogress) {
- spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag);
- return;
- }
- spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag);
-
- spin_lock_irqsave(&rtlpriv->locks.lps_lock, flag);
- rtl_ps_set_rf_state(hw, ERFSLEEP, RF_CHANGE_BY_PS, false);
- spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flag);
+ spin_lock(&rtlpriv->locks.lps_lock);
+ rtl_ps_set_rf_state(hw, ERFSLEEP, RF_CHANGE_BY_PS);
+ spin_unlock(&rtlpriv->locks.lps_lock);
if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM &&
!RT_IN_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM)) {
diff --git a/drivers/net/wireless/rtlwifi/ps.h b/drivers/net/wireless/rtlwifi/ps.h
index e3bf898..84628e60 100644
--- a/drivers/net/wireless/rtlwifi/ps.h
+++ b/drivers/net/wireless/rtlwifi/ps.h
@@ -33,8 +33,7 @@
#define MAX_SW_LPS_SLEEP_INTV 5
bool rtl_ps_set_rf_state(struct ieee80211_hw *hw,
- enum rf_pwrstate state_toset, u32 changesource,
- bool protect_or_not);
+ enum rf_pwrstate state_toset, u32 changesource);
bool rtl_ps_enable_nic(struct ieee80211_hw *hw);
bool rtl_ps_disable_nic(struct ieee80211_hw *hw);
void rtl_ips_nic_off(struct ieee80211_hw *hw);
diff --git a/drivers/net/wireless/rtlwifi/rc.c b/drivers/net/wireless/rtlwifi/rc.c
index 30da68a..539df66d 100644
--- a/drivers/net/wireless/rtlwifi/rc.c
+++ b/drivers/net/wireless/rtlwifi/rc.c
@@ -200,7 +200,7 @@
if (sta) {
/* Check if aggregation has to be enabled for this tid */
sta_entry = (struct rtl_sta_info *) sta->drv_priv;
- if ((sta->ht_cap.ht_supported == true) &&
+ if ((sta->ht_cap.ht_supported) &&
!(skb->protocol == cpu_to_be16(ETH_P_PAE))) {
if (ieee80211_is_data_qos(fc)) {
u8 tid = rtl_get_tid(skb);
diff --git a/drivers/net/wireless/rtlwifi/regd.c b/drivers/net/wireless/rtlwifi/regd.c
index 8f6718f..9fedb1f 100644
--- a/drivers/net/wireless/rtlwifi/regd.c
+++ b/drivers/net/wireless/rtlwifi/regd.c
@@ -303,22 +303,6 @@
return;
}
-static void _rtl_dump_channel_map(struct wiphy *wiphy)
-{
- enum ieee80211_band band;
- struct ieee80211_supported_band *sband;
- struct ieee80211_channel *ch;
- unsigned int i;
-
- for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
- if (!wiphy->bands[band])
- continue;
- sband = wiphy->bands[band];
- for (i = 0; i < sband->n_channels; i++)
- ch = &sband->channels[i];
- }
-}
-
static int _rtl_reg_notifier_apply(struct wiphy *wiphy,
struct regulatory_request *request,
struct rtl_regulatory *reg)
@@ -336,8 +320,6 @@
break;
}
- _rtl_dump_channel_map(wiphy);
-
return 0;
}
diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c b/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c
index 9718382..a00774e 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c
@@ -474,7 +474,7 @@
{
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
- if (mac->act_scanning == true)
+ if (mac->act_scanning)
return;
if (mac->link_state >= MAC80211_LINKED)
@@ -670,7 +670,7 @@
u8 ofdm_index[2], cck_index = 0, ofdm_index_old[2], cck_index_old = 0;
int i;
bool is2t = IS_92C_SERIAL(rtlhal->version);
- u8 txpwr_level[2] = {0, 0};
+ s8 txpwr_level[2] = {0, 0};
u8 ofdm_min_index = 6, rf;
rtlpriv->dm.txpower_trackinginit = true;
diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c b/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c
index 50303e1..f9f2370 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c
@@ -546,7 +546,6 @@
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
struct rtl8192_tx_ring *ring;
struct rtl_tx_desc *pdesc;
- u8 own;
unsigned long flags;
struct sk_buff *pskb = NULL;
@@ -559,7 +558,6 @@
spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags);
pdesc = &ring->desc[0];
- own = (u8) rtlpriv->cfg->ops->get_desc((u8 *) pdesc, true, HW_DESC_OWN);
rtlpriv->cfg->ops->fill_tx_cmddesc(hw, (u8 *) pdesc, 1, 1, skb);
diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c b/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c
index d2cc815..3b11642 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c
@@ -1253,10 +1253,9 @@
const u32 retrycount = 2;
- u32 bbvalue;
-
if (t == 0) {
- bbvalue = rtl_get_bbreg(hw, 0x800, MASKDWORD);
+ /* dummy read */
+ rtl_get_bbreg(hw, 0x800, MASKDWORD);
_rtl92c_phy_save_adda_registers(hw, adda_reg,
rtlphy->adda_backup, 16);
@@ -1762,8 +1761,7 @@
long result[4][8];
u8 i, final_candidate;
bool patha_ok, pathb_ok;
- long reg_e94, reg_e9c, reg_ea4, reg_eac, reg_eb4, reg_ebc, reg_ec4,
- reg_ecc, reg_tmp = 0;
+ long reg_e94, reg_e9c, reg_ea4, reg_eb4, reg_ebc, reg_ec4, reg_tmp = 0;
bool is12simular, is13simular, is23simular;
bool start_conttx = false, singletone = false;
u32 iqk_bb_reg[10] = {
@@ -1841,21 +1839,17 @@
reg_e94 = result[i][0];
reg_e9c = result[i][1];
reg_ea4 = result[i][2];
- reg_eac = result[i][3];
reg_eb4 = result[i][4];
reg_ebc = result[i][5];
reg_ec4 = result[i][6];
- reg_ecc = result[i][7];
}
if (final_candidate != 0xff) {
rtlphy->reg_e94 = reg_e94 = result[final_candidate][0];
rtlphy->reg_e9c = reg_e9c = result[final_candidate][1];
reg_ea4 = result[final_candidate][2];
- reg_eac = result[final_candidate][3];
rtlphy->reg_eb4 = reg_eb4 = result[final_candidate][4];
rtlphy->reg_ebc = reg_ebc = result[final_candidate][5];
reg_ec4 = result[final_candidate][6];
- reg_ecc = result[final_candidate][7];
patha_ok = pathb_ok = true;
} else {
rtlphy->reg_e94 = rtlphy->reg_eb4 = 0x100;
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c
index defb437..bc6ae9d 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c
@@ -488,7 +488,7 @@
case HW_VAR_CORRECT_TSF:{
u8 btype_ibss = ((u8 *) (val))[0];
- if (btype_ibss == true)
+ if (btype_ibss)
_rtl92ce_stop_tx_beacon(hw);
_rtl92ce_set_bcn_ctrl_reg(hw, 0, BIT(3));
@@ -500,7 +500,7 @@
_rtl92ce_set_bcn_ctrl_reg(hw, BIT(3), 0);
- if (btype_ibss == true)
+ if (btype_ibss)
_rtl92ce_resume_tx_beacon(hw);
break;
@@ -763,11 +763,9 @@
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
u8 reg_bw_opmode;
- u32 reg_ratr, reg_prsr;
+ u32 reg_prsr;
reg_bw_opmode = BW_OPMODE_20MHZ;
- reg_ratr = RATE_ALL_CCK | RATE_ALL_OFDM_AG |
- RATE_ALL_OFDM_1SS | RATE_ALL_OFDM_2SS;
reg_prsr = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
rtl_write_byte(rtlpriv, REG_INIRTS_RATE_SEL, 0x8);
@@ -1123,7 +1121,7 @@
if (rtlpriv->psc.rfpwr_state != ERFON)
return;
- if (check_bssid == true) {
+ if (check_bssid) {
reg_rcr |= (RCR_CBSSID_DATA | RCR_CBSSID_BCN);
rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR,
(u8 *) (®_rcr));
@@ -1196,6 +1194,7 @@
rtl_write_dword(rtlpriv, REG_HIMR, IMR8190_DISABLED);
rtl_write_dword(rtlpriv, REG_HIMRE, IMR8190_DISABLED);
rtlpci->irq_enabled = false;
+ synchronize_irq(rtlpci->pdev->irq);
}
static void _rtl92ce_poweroff_adapter(struct ieee80211_hw *hw)
@@ -1586,7 +1585,7 @@
rtlefuse->autoload_failflag = false;
}
- if (rtlefuse->autoload_failflag == true)
+ if (rtlefuse->autoload_failflag)
return;
for (i = 0; i < 6; i += 2) {
@@ -1969,7 +1968,7 @@
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
- enum rf_pwrstate e_rfpowerstate_toset, cur_rfstate;
+ enum rf_pwrstate e_rfpowerstate_toset;
u8 u1tmp;
bool actuallyset = false;
unsigned long flag;
@@ -1989,15 +1988,13 @@
spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag);
}
- cur_rfstate = ppsc->rfpwr_state;
-
rtl_write_byte(rtlpriv, REG_MAC_PINMUX_CFG, rtl_read_byte(rtlpriv,
REG_MAC_PINMUX_CFG)&~(BIT(3)));
u1tmp = rtl_read_byte(rtlpriv, REG_GPIO_IO_SEL);
e_rfpowerstate_toset = (u1tmp & BIT(3)) ? ERFON : ERFOFF;
- if ((ppsc->hwradiooff == true) && (e_rfpowerstate_toset == ERFON)) {
+ if ((ppsc->hwradiooff) && (e_rfpowerstate_toset == ERFON)) {
RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
("GPIOChangeRF - HW Radio ON, RF ON\n"));
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/led.c b/drivers/net/wireless/rtlwifi/rtl8192ce/led.c
index 9dd1ed7..28a1a70 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/led.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/led.c
@@ -84,7 +84,7 @@
break;
case LED_PIN_LED0:
ledcfg &= 0xf0;
- if (pcipriv->ledctl.led_opendrain == true)
+ if (pcipriv->ledctl.led_opendrain)
rtl_write_byte(rtlpriv, REG_LEDCFG2,
(ledcfg | BIT(1) | BIT(5) | BIT(6)));
else
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/phy.c b/drivers/net/wireless/rtlwifi/rtl8192ce/phy.c
index abe0fcc..592a10a 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/phy.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/phy.c
@@ -46,13 +46,12 @@
struct rtl_priv *rtlpriv = rtl_priv(hw);
u32 original_value, readback_value, bitshift;
struct rtl_phy *rtlphy = &(rtlpriv->phy);
- unsigned long flags;
RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("regaddr(%#x), "
"rfpath(%#x), bitmask(%#x)\n",
regaddr, rfpath, bitmask));
- spin_lock_irqsave(&rtlpriv->locks.rf_lock, flags);
+ spin_lock(&rtlpriv->locks.rf_lock);
if (rtlphy->rf_mode != RF_OP_BY_FW) {
original_value = _rtl92c_phy_rf_serial_read(hw,
@@ -65,7 +64,7 @@
bitshift = _rtl92c_phy_calculate_bit_shift(bitmask);
readback_value = (original_value & bitmask) >> bitshift;
- spin_unlock_irqrestore(&rtlpriv->locks.rf_lock, flags);
+ spin_unlock(&rtlpriv->locks.rf_lock);
RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
("regaddr(%#x), rfpath(%#x), "
@@ -120,13 +119,12 @@
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_phy *rtlphy = &(rtlpriv->phy);
u32 original_value, bitshift;
- unsigned long flags;
RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
("regaddr(%#x), bitmask(%#x), data(%#x), rfpath(%#x)\n",
regaddr, bitmask, data, rfpath));
- spin_lock_irqsave(&rtlpriv->locks.rf_lock, flags);
+ spin_lock(&rtlpriv->locks.rf_lock);
if (rtlphy->rf_mode != RF_OP_BY_FW) {
if (bitmask != RFREG_OFFSET_MASK) {
@@ -153,7 +151,7 @@
_rtl92c_phy_fw_rf_serial_write(hw, rfpath, regaddr, data);
}
- spin_unlock_irqrestore(&rtlpriv->locks.rf_lock, flags);
+ spin_unlock(&rtlpriv->locks.rf_lock);
RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("regaddr(%#x), "
"bitmask(%#x), data(%#x), "
@@ -281,7 +279,6 @@
{
int i;
- bool rtstatus = true;
u32 *radioa_array_table;
u32 *radiob_array_table;
u16 radioa_arraylen, radiob_arraylen;
@@ -308,7 +305,6 @@
("Radio_B:RTL8192CE_RADIOB_1TARRAY\n"));
}
RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, ("Radio No %x\n", rfpath));
- rtstatus = true;
switch (rfpath) {
case RF90_PATH_A:
for (i = 0; i < radioa_arraylen; i = i + 2) {
@@ -521,7 +517,6 @@
u8 i, queue_id;
struct rtl8192_tx_ring *ring = NULL;
- ppsc->set_rfpowerstate_inprogress = true;
switch (rfpwr_state) {
case ERFON:{
if ((ppsc->rfpwr_state == ERFOFF) &&
@@ -617,7 +612,6 @@
}
if (bresult)
ppsc->rfpwr_state = rfpwr_state;
- ppsc->set_rfpowerstate_inprogress = false;
return bresult;
}
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/reg.h b/drivers/net/wireless/rtlwifi/rtl8192ce/reg.h
index 598cecc..72a3d54 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/reg.h
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/reg.h
@@ -1203,7 +1203,9 @@
#define EPROM_CMD_CONFIG 0x3
#define EPROM_CMD_LOAD 1
+#define HWSET_MAX_SIZE 128
#define HWSET_MAX_SIZE_92S HWSET_MAX_SIZE
+#define EFUSE_MAX_SECTION 16
#define WL_HWPDN_EN BIT(0)
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/rf.c b/drivers/net/wireless/rtlwifi/rtl8192ce/rf.c
index 90d0f2c..d3b01e6 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/rf.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/rf.c
@@ -76,7 +76,7 @@
if (rtlefuse->eeprom_regulatory != 0)
turbo_scanoff = true;
- if (mac->act_scanning == true) {
+ if (mac->act_scanning) {
tx_agc[RF90_PATH_A] = 0x3f3f3f3f;
tx_agc[RF90_PATH_B] = 0x3f3f3f3f;
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c b/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c
index 54b2bd5..230bbe9 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c
@@ -225,7 +225,7 @@
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct phy_sts_cck_8192s_t *cck_buf;
- s8 rx_pwr_all, rx_pwr[4];
+ s8 rx_pwr_all = 0, rx_pwr[4];
u8 evm, pwdb_all, rf_rx_num = 0;
u8 i, max_spatial_stream;
u32 rssi, total_rssi = 0;
@@ -592,7 +592,6 @@
struct ieee80211_hdr *hdr;
u8 *tmp_buf;
u8 *praddr;
- u8 *psaddr;
__le16 fc;
u16 type, c_fc;
bool packet_matchbssid, packet_toself, packet_beacon;
@@ -604,7 +603,6 @@
c_fc = le16_to_cpu(fc);
type = WLAN_FC_GET_TYPE(fc);
praddr = hdr->addr1;
- psaddr = hdr->addr2;
packet_matchbssid =
((IEEE80211_FTYPE_CTL != type) &&
@@ -680,7 +678,7 @@
GET_RX_DESC_PAGGR(pdesc));
rx_status->mactime = GET_RX_DESC_TSFL(pdesc);
- if (phystatus == true) {
+ if (phystatus) {
p_drvinfo = (struct rx_fwinfo_92c *)(skb->data +
stats->rx_bufshift);
@@ -929,9 +927,10 @@
void rtl92ce_set_desc(u8 *pdesc, bool istx, u8 desc_name, u8 *val)
{
- if (istx == true) {
+ if (istx) {
switch (desc_name) {
case HW_DESC_OWN:
+ wmb();
SET_TX_DESC_OWN(pdesc, 1);
break;
case HW_DESC_TX_NEXTDESC_ADDR:
@@ -945,6 +944,7 @@
} else {
switch (desc_name) {
case HW_DESC_RXOWN:
+ wmb();
SET_RX_DESC_OWN(pdesc, 1);
break;
case HW_DESC_RXBUFF_ADDR:
@@ -968,7 +968,7 @@
{
u32 ret = 0;
- if (istx == true) {
+ if (istx) {
switch (desc_name) {
case HW_DESC_OWN:
ret = GET_TX_DESC_OWN(p_desc);
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c
index 52e2af5..2b34764 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c
@@ -520,7 +520,7 @@
RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("Autoload OK\n"));
rtlefuse->autoload_failflag = false;
}
- if (rtlefuse->autoload_failflag == true)
+ if (rtlefuse->autoload_failflag)
return;
for (i = 0; i < 6; i += 2) {
usvalue = *(u16 *)&hwinfo[EEPROM_MAC_ADDR + i];
@@ -1594,7 +1594,7 @@
default:
break;
}
- if (filterout_non_associated_bssid == true) {
+ if (filterout_non_associated_bssid) {
if (IS_NORMAL_CHIP(rtlhal->version)) {
switch (rtlphy->current_io_type) {
case IO_CMD_RESUME_DM_BY_SCAN:
@@ -2155,7 +2155,7 @@
case HW_VAR_CORRECT_TSF:{
u8 btype_ibss = ((u8 *) (val))[0];
- if (btype_ibss == true)
+ if (btype_ibss)
_rtl92cu_stop_tx_beacon(hw);
_rtl92cu_set_bcn_ctrl_reg(hw, 0, BIT(3));
rtl_write_dword(rtlpriv, REG_TSFTR, (u32)(mac->tsf &
@@ -2163,7 +2163,7 @@
rtl_write_dword(rtlpriv, REG_TSFTR + 4,
(u32)((mac->tsf >> 32) & 0xffffffff));
_rtl92cu_set_bcn_ctrl_reg(hw, BIT(3), 0);
- if (btype_ibss == true)
+ if (btype_ibss)
_rtl92cu_resume_tx_beacon(hw);
break;
}
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/led.c b/drivers/net/wireless/rtlwifi/rtl8192cu/led.c
index 332c743..2ff9d83 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/led.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/led.c
@@ -82,7 +82,7 @@
break;
case LED_PIN_LED0:
ledcfg &= 0xf0;
- if (usbpriv->ledctl.led_opendrain == true)
+ if (usbpriv->ledctl.led_opendrain)
rtl_write_byte(rtlpriv, REG_LEDCFG2,
(ledcfg | BIT(1) | BIT(5) | BIT(6)));
else
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c b/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c
index f8514cb..4e057df 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c
@@ -1113,7 +1113,6 @@
struct ieee80211_hdr *hdr;
u8 *tmp_buf;
u8 *praddr;
- u8 *psaddr;
__le16 fc;
u16 type, cpu_fc;
bool packet_matchbssid, packet_toself, packet_beacon;
@@ -1124,7 +1123,6 @@
cpu_fc = le16_to_cpu(fc);
type = WLAN_FC_GET_TYPE(fc);
praddr = hdr->addr1;
- psaddr = hdr->addr2;
packet_matchbssid =
((IEEE80211_FTYPE_CTL != type) &&
(!compare_ether_addr(mac->bssid,
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/phy.c b/drivers/net/wireless/rtlwifi/rtl8192cu/phy.c
index 9a3d023..7285290 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/phy.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/phy.c
@@ -470,7 +470,6 @@
u8 i, queue_id;
struct rtl8192_tx_ring *ring = NULL;
- ppsc->set_rfpowerstate_inprogress = true;
switch (rfpwr_state) {
case ERFON:
if ((ppsc->rfpwr_state == ERFOFF) &&
@@ -590,7 +589,6 @@
}
if (bresult)
ppsc->rfpwr_state = rfpwr_state;
- ppsc->set_rfpowerstate_inprogress = false;
return bresult;
}
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c b/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c
index c7576ec..1e851aa 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c
@@ -82,7 +82,7 @@
(rtlefuse->external_pa))
turbo_scanoff = true;
}
- if (mac->act_scanning == true) {
+ if (mac->act_scanning) {
tx_agc[RF90_PATH_A] = 0x3f3f3f3f;
tx_agc[RF90_PATH_B] = 0x3f3f3f3f;
if (turbo_scanoff) {
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c b/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c
index 3a92ba3..906e7aa 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c
@@ -342,7 +342,7 @@
(u8)GET_RX_DESC_RX_MCS(pdesc),
(bool)GET_RX_DESC_PAGGR(pdesc));
rx_status->mactime = GET_RX_DESC_TSFL(pdesc);
- if (phystatus == true) {
+ if (phystatus) {
p_drvinfo = (struct rx_fwinfo_92c *)(pdesc + RTL_RX_DESC_SIZE);
rtl92c_translate_rx_signal_stuff(hw, skb, stats, pdesc,
p_drvinfo);
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/Makefile b/drivers/net/wireless/rtlwifi/rtl8192de/Makefile
new file mode 100644
index 0000000..e3213c8
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8192de/Makefile
@@ -0,0 +1,14 @@
+rtl8192de-objs := \
+ dm.o \
+ fw.o \
+ hw.o \
+ led.o \
+ phy.o \
+ rf.o \
+ sw.o \
+ table.o \
+ trx.o
+
+obj-$(CONFIG_RTL8192DE) += rtl8192de.o
+
+ccflags-y += -D__CHECK_ENDIAN__
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/def.h b/drivers/net/wireless/rtlwifi/rtl8192de/def.h
new file mode 100644
index 0000000..f0f5f9b
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8192de/def.h
@@ -0,0 +1,269 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010 Realtek Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License 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, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#ifndef __RTL92D_DEF_H__
+#define __RTL92D_DEF_H__
+
+/* Min Spacing related settings. */
+#define MAX_MSS_DENSITY_2T 0x13
+#define MAX_MSS_DENSITY_1T 0x0A
+
+#define RF6052_MAX_TX_PWR 0x3F
+#define RF6052_MAX_REG 0x3F
+#define RF6052_MAX_PATH 2
+
+#define HAL_RETRY_LIMIT_INFRA 48
+#define HAL_RETRY_LIMIT_AP_ADHOC 7
+
+#define PHY_RSSI_SLID_WIN_MAX 100
+#define PHY_LINKQUALITY_SLID_WIN_MAX 20
+#define PHY_BEACON_RSSI_SLID_WIN_MAX 10
+
+#define RESET_DELAY_8185 20
+
+#define RT_IBSS_INT_MASKS (IMR_BCNINT | IMR_TBDOK | IMR_TBDER)
+#define RT_AC_INT_MASKS (IMR_VIDOK | IMR_VODOK | IMR_BEDOK|IMR_BKDOK)
+
+#define NUM_OF_FIRMWARE_QUEUE 10
+#define NUM_OF_PAGES_IN_FW 0x100
+#define NUM_OF_PAGE_IN_FW_QUEUE_BK 0x07
+#define NUM_OF_PAGE_IN_FW_QUEUE_BE 0x07
+#define NUM_OF_PAGE_IN_FW_QUEUE_VI 0x07
+#define NUM_OF_PAGE_IN_FW_QUEUE_VO 0x07
+#define NUM_OF_PAGE_IN_FW_QUEUE_HCCA 0x0
+#define NUM_OF_PAGE_IN_FW_QUEUE_CMD 0x0
+#define NUM_OF_PAGE_IN_FW_QUEUE_MGNT 0x02
+#define NUM_OF_PAGE_IN_FW_QUEUE_HIGH 0x02
+#define NUM_OF_PAGE_IN_FW_QUEUE_BCN 0x2
+#define NUM_OF_PAGE_IN_FW_QUEUE_PUB 0xA1
+
+#define NUM_OF_PAGE_IN_FW_QUEUE_BK_DTM 0x026
+#define NUM_OF_PAGE_IN_FW_QUEUE_BE_DTM 0x048
+#define NUM_OF_PAGE_IN_FW_QUEUE_VI_DTM 0x048
+#define NUM_OF_PAGE_IN_FW_QUEUE_VO_DTM 0x026
+#define NUM_OF_PAGE_IN_FW_QUEUE_PUB_DTM 0x00
+
+#define MAX_LINES_HWCONFIG_TXT 1000
+#define MAX_BYTES_LINE_HWCONFIG_TXT 256
+
+#define SW_THREE_WIRE 0
+#define HW_THREE_WIRE 2
+
+#define BT_DEMO_BOARD 0
+#define BT_QA_BOARD 1
+#define BT_FPGA 2
+
+#define RX_SMOOTH_FACTOR 20
+
+#define HAL_PRIME_CHNL_OFFSET_DONT_CARE 0
+#define HAL_PRIME_CHNL_OFFSET_LOWER 1
+#define HAL_PRIME_CHNL_OFFSET_UPPER 2
+
+#define MAX_H2C_QUEUE_NUM 10
+
+#define RX_MPDU_QUEUE 0
+#define RX_CMD_QUEUE 1
+#define RX_MAX_QUEUE 2
+
+#define C2H_RX_CMD_HDR_LEN 8
+#define GET_C2H_CMD_CMD_LEN(__prxhdr) \
+ LE_BITS_TO_4BYTE((__prxhdr), 0, 16)
+#define GET_C2H_CMD_ELEMENT_ID(__prxhdr) \
+ LE_BITS_TO_4BYTE((__prxhdr), 16, 8)
+#define GET_C2H_CMD_CMD_SEQ(__prxhdr) \
+ LE_BITS_TO_4BYTE((__prxhdr), 24, 7)
+#define GET_C2H_CMD_CONTINUE(__prxhdr) \
+ LE_BITS_TO_4BYTE((__prxhdr), 31, 1)
+#define GET_C2H_CMD_CONTENT(__prxhdr) \
+ ((u8 *)(__prxhdr) + C2H_RX_CMD_HDR_LEN)
+
+#define GET_C2H_CMD_FEEDBACK_ELEMENT_ID(__pcmdfbhdr) \
+ LE_BITS_TO_4BYTE((__pcmdfbhdr), 0, 8)
+#define GET_C2H_CMD_FEEDBACK_CCX_LEN(__pcmdfbhdr) \
+ LE_BITS_TO_4BYTE((__pcmdfbhdr), 8, 8)
+#define GET_C2H_CMD_FEEDBACK_CCX_CMD_CNT(__pcmdfbhdr) \
+ LE_BITS_TO_4BYTE((__pcmdfbhdr), 16, 16)
+#define GET_C2H_CMD_FEEDBACK_CCX_MAC_ID(__pcmdfbhdr) \
+ LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 0, 5)
+#define GET_C2H_CMD_FEEDBACK_CCX_VALID(__pcmdfbhdr) \
+ LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 7, 1)
+#define GET_C2H_CMD_FEEDBACK_CCX_RETRY_CNT(__pcmdfbhdr) \
+ LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 8, 5)
+#define GET_C2H_CMD_FEEDBACK_CCX_TOK(__pcmdfbhdr) \
+ LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 15, 1)
+#define GET_C2H_CMD_FEEDBACK_CCX_QSEL(__pcmdfbhdr) \
+ LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 16, 4)
+#define GET_C2H_CMD_FEEDBACK_CCX_SEQ(__pcmdfbhdr) \
+ LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 20, 12)
+
+/*
+ * 92D chip ver:
+ * BIT8: IS 92D
+ * BIT9: single phy
+ * BIT10: C-cut
+ * BIT11: D-cut
+ */
+
+/* Chip specific */
+#define CHIP_92C BIT(0)
+#define CHIP_92C_1T2R BIT(1)
+#define CHIP_8723 BIT(2) /* RTL8723 With BT feature */
+#define CHIP_8723_DRV_REV BIT(3) /* RTL8723 Driver Revised */
+#define NORMAL_CHIP BIT(4)
+#define CHIP_VENDOR_UMC BIT(5)
+#define CHIP_VENDOR_UMC_B_CUT BIT(6) /* Chip version for ECO */
+
+/* for 92D */
+#define CHIP_92D BIT(8)
+#define CHIP_92D_SINGLEPHY BIT(9)
+#define CHIP_92D_C_CUT BIT(10)
+#define CHIP_92D_D_CUT BIT(11)
+
+enum version_8192d {
+ VERSION_TEST_CHIP_88C = 0x00,
+ VERSION_TEST_CHIP_92C = 0x01,
+ VERSION_NORMAL_TSMC_CHIP_88C = 0x10,
+ VERSION_NORMAL_TSMC_CHIP_92C = 0x11,
+ VERSION_NORMAL_TSMC_CHIP_92C_1T2R = 0x13,
+ VERSION_NORMAL_UMC_CHIP_88C_A_CUT = 0x30,
+ VERSION_NORMAL_UMC_CHIP_92C_A_CUT = 0x31,
+ VERSION_NORMAL_UMC_CHIP_92C_1T2R_A_CUT = 0x33,
+ VERSION_NORMA_UMC_CHIP_8723_1T1R_A_CUT = 0x34,
+ VERSION_NORMA_UMC_CHIP_8723_1T1R_B_CUT = 0x3c,
+ VERSION_NORMAL_UMC_CHIP_88C_B_CUT = 0x70,
+ VERSION_NORMAL_UMC_CHIP_92C_B_CUT = 0x71,
+ VERSION_NORMAL_UMC_CHIP_92C_1T2R_B_CUT = 0x73,
+ VERSION_TEST_CHIP_92D_SINGLEPHY = 0x300,
+ VERSION_TEST_CHIP_92D_DUALPHY = 0x100,
+ VERSION_NORMAL_CHIP_92D_SINGLEPHY = 0x310,
+ VERSION_NORMAL_CHIP_92D_DUALPHY = 0x110,
+ VERSION_NORMAL_CHIP_92D_C_CUT_SINGLEPHY = 0x710,
+ VERSION_NORMAL_CHIP_92D_C_CUT_DUALPHY = 0x510,
+ VERSION_NORMAL_CHIP_92D_D_CUT_SINGLEPHY = 0xB10,
+ VERSION_NORMAL_CHIP_92D_D_CUT_DUALPHY = 0x910,
+};
+
+#define IS_92D_SINGLEPHY(version) \
+ ((version & CHIP_92D_SINGLEPHY) ? true : false)
+#define IS_92D_C_CUT(version) \
+ ((version & CHIP_92D_C_CUT) ? true : false)
+#define IS_92D_D_CUT(version) \
+ ((version & CHIP_92D_D_CUT) ? true : false)
+
+enum rf_optype {
+ RF_OP_BY_SW_3WIRE = 0,
+ RF_OP_BY_FW,
+ RF_OP_MAX
+};
+
+enum rtl_desc_qsel {
+ QSLT_BK = 0x2,
+ QSLT_BE = 0x0,
+ QSLT_VI = 0x5,
+ QSLT_VO = 0x7,
+ QSLT_BEACON = 0x10,
+ QSLT_HIGH = 0x11,
+ QSLT_MGNT = 0x12,
+ QSLT_CMD = 0x13,
+};
+
+enum rtl_desc92d_rate {
+ DESC92D_RATE1M = 0x00,
+ DESC92D_RATE2M = 0x01,
+ DESC92D_RATE5_5M = 0x02,
+ DESC92D_RATE11M = 0x03,
+
+ DESC92D_RATE6M = 0x04,
+ DESC92D_RATE9M = 0x05,
+ DESC92D_RATE12M = 0x06,
+ DESC92D_RATE18M = 0x07,
+ DESC92D_RATE24M = 0x08,
+ DESC92D_RATE36M = 0x09,
+ DESC92D_RATE48M = 0x0a,
+ DESC92D_RATE54M = 0x0b,
+
+ DESC92D_RATEMCS0 = 0x0c,
+ DESC92D_RATEMCS1 = 0x0d,
+ DESC92D_RATEMCS2 = 0x0e,
+ DESC92D_RATEMCS3 = 0x0f,
+ DESC92D_RATEMCS4 = 0x10,
+ DESC92D_RATEMCS5 = 0x11,
+ DESC92D_RATEMCS6 = 0x12,
+ DESC92D_RATEMCS7 = 0x13,
+ DESC92D_RATEMCS8 = 0x14,
+ DESC92D_RATEMCS9 = 0x15,
+ DESC92D_RATEMCS10 = 0x16,
+ DESC92D_RATEMCS11 = 0x17,
+ DESC92D_RATEMCS12 = 0x18,
+ DESC92D_RATEMCS13 = 0x19,
+ DESC92D_RATEMCS14 = 0x1a,
+ DESC92D_RATEMCS15 = 0x1b,
+ DESC92D_RATEMCS15_SG = 0x1c,
+ DESC92D_RATEMCS32 = 0x20,
+};
+
+enum channel_plan {
+ CHPL_FCC = 0,
+ CHPL_IC = 1,
+ CHPL_ETSI = 2,
+ CHPL_SPAIN = 3,
+ CHPL_FRANCE = 4,
+ CHPL_MKK = 5,
+ CHPL_MKK1 = 6,
+ CHPL_ISRAEL = 7,
+ CHPL_TELEC = 8,
+ CHPL_GLOBAL = 9,
+ CHPL_WORLD = 10,
+};
+
+struct phy_sts_cck_8192d {
+ u8 adc_pwdb_X[4];
+ u8 sq_rpt;
+ u8 cck_agc_rpt;
+};
+
+struct h2c_cmd_8192c {
+ u8 element_id;
+ u32 cmd_len;
+ u8 *p_cmdbuffer;
+};
+
+struct txpower_info {
+ u8 cck_index[RF6052_MAX_PATH][CHANNEL_GROUP_MAX];
+ u8 ht40_1sindex[RF6052_MAX_PATH][CHANNEL_GROUP_MAX];
+ u8 ht40_2sindexdiff[RF6052_MAX_PATH][CHANNEL_GROUP_MAX];
+ u8 ht20indexdiff[RF6052_MAX_PATH][CHANNEL_GROUP_MAX];
+ u8 ofdmindexdiff[RF6052_MAX_PATH][CHANNEL_GROUP_MAX];
+ u8 ht40maxoffset[RF6052_MAX_PATH][CHANNEL_GROUP_MAX];
+ u8 ht20maxoffset[RF6052_MAX_PATH][CHANNEL_GROUP_MAX];
+ u8 tssi_a[3]; /* 5GL/5GM/5GH */
+ u8 tssi_b[3];
+};
+
+#endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/dm.c b/drivers/net/wireless/rtlwifi/rtl8192de/dm.c
new file mode 100644
index 0000000..3cd0736
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8192de/dm.c
@@ -0,0 +1,1355 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010 Realtek Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License 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, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#include "../wifi.h"
+#include "../base.h"
+#include "reg.h"
+#include "def.h"
+#include "phy.h"
+#include "dm.h"
+#include "fw.h"
+
+#define UNDEC_SM_PWDB entry_min_undecoratedsmoothed_pwdb
+
+struct dig_t de_digtable;
+
+static const u32 ofdmswing_table[OFDM_TABLE_SIZE_92D] = {
+ 0x7f8001fe, /* 0, +6.0dB */
+ 0x788001e2, /* 1, +5.5dB */
+ 0x71c001c7, /* 2, +5.0dB */
+ 0x6b8001ae, /* 3, +4.5dB */
+ 0x65400195, /* 4, +4.0dB */
+ 0x5fc0017f, /* 5, +3.5dB */
+ 0x5a400169, /* 6, +3.0dB */
+ 0x55400155, /* 7, +2.5dB */
+ 0x50800142, /* 8, +2.0dB */
+ 0x4c000130, /* 9, +1.5dB */
+ 0x47c0011f, /* 10, +1.0dB */
+ 0x43c0010f, /* 11, +0.5dB */
+ 0x40000100, /* 12, +0dB */
+ 0x3c8000f2, /* 13, -0.5dB */
+ 0x390000e4, /* 14, -1.0dB */
+ 0x35c000d7, /* 15, -1.5dB */
+ 0x32c000cb, /* 16, -2.0dB */
+ 0x300000c0, /* 17, -2.5dB */
+ 0x2d4000b5, /* 18, -3.0dB */
+ 0x2ac000ab, /* 19, -3.5dB */
+ 0x288000a2, /* 20, -4.0dB */
+ 0x26000098, /* 21, -4.5dB */
+ 0x24000090, /* 22, -5.0dB */
+ 0x22000088, /* 23, -5.5dB */
+ 0x20000080, /* 24, -6.0dB */
+ 0x1e400079, /* 25, -6.5dB */
+ 0x1c800072, /* 26, -7.0dB */
+ 0x1b00006c, /* 27. -7.5dB */
+ 0x19800066, /* 28, -8.0dB */
+ 0x18000060, /* 29, -8.5dB */
+ 0x16c0005b, /* 30, -9.0dB */
+ 0x15800056, /* 31, -9.5dB */
+ 0x14400051, /* 32, -10.0dB */
+ 0x1300004c, /* 33, -10.5dB */
+ 0x12000048, /* 34, -11.0dB */
+ 0x11000044, /* 35, -11.5dB */
+ 0x10000040, /* 36, -12.0dB */
+ 0x0f00003c, /* 37, -12.5dB */
+ 0x0e400039, /* 38, -13.0dB */
+ 0x0d800036, /* 39, -13.5dB */
+ 0x0cc00033, /* 40, -14.0dB */
+ 0x0c000030, /* 41, -14.5dB */
+ 0x0b40002d, /* 42, -15.0dB */
+};
+
+static const u8 cckswing_table_ch1ch13[CCK_TABLE_SIZE][8] = {
+ {0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04}, /* 0, +0dB */
+ {0x33, 0x32, 0x2b, 0x23, 0x1a, 0x11, 0x08, 0x04}, /* 1, -0.5dB */
+ {0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03}, /* 2, -1.0dB */
+ {0x2d, 0x2d, 0x27, 0x1f, 0x18, 0x0f, 0x08, 0x03}, /* 3, -1.5dB */
+ {0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03}, /* 4, -2.0dB */
+ {0x28, 0x28, 0x22, 0x1c, 0x15, 0x0d, 0x07, 0x03}, /* 5, -2.5dB */
+ {0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03}, /* 6, -3.0dB */
+ {0x24, 0x23, 0x1f, 0x19, 0x13, 0x0c, 0x06, 0x03}, /* 7, -3.5dB */
+ {0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02}, /* 8, -4.0dB */
+ {0x20, 0x20, 0x1b, 0x16, 0x11, 0x08, 0x05, 0x02}, /* 9, -4.5dB */
+ {0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02}, /* 10, -5.0dB */
+ {0x1d, 0x1c, 0x18, 0x14, 0x0f, 0x0a, 0x05, 0x02}, /* 11, -5.5dB */
+ {0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02}, /* 12, -6.0dB */
+ {0x1a, 0x19, 0x16, 0x12, 0x0d, 0x09, 0x04, 0x02}, /* 13, -6.5dB */
+ {0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02}, /* 14, -7.0dB */
+ {0x17, 0x16, 0x13, 0x10, 0x0c, 0x08, 0x04, 0x02}, /* 15, -7.5dB */
+ {0x16, 0x15, 0x12, 0x0f, 0x0b, 0x07, 0x04, 0x01}, /* 16, -8.0dB */
+ {0x14, 0x14, 0x11, 0x0e, 0x0b, 0x07, 0x03, 0x02}, /* 17, -8.5dB */
+ {0x13, 0x13, 0x10, 0x0d, 0x0a, 0x06, 0x03, 0x01}, /* 18, -9.0dB */
+ {0x12, 0x12, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, /* 19, -9.5dB */
+ {0x11, 0x11, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, /* 20, -10.0dB */
+ {0x10, 0x10, 0x0e, 0x0b, 0x08, 0x05, 0x03, 0x01}, /* 21, -10.5dB */
+ {0x0f, 0x0f, 0x0d, 0x0b, 0x08, 0x05, 0x03, 0x01}, /* 22, -11.0dB */
+ {0x0e, 0x0e, 0x0c, 0x0a, 0x08, 0x05, 0x02, 0x01}, /* 23, -11.5dB */
+ {0x0d, 0x0d, 0x0c, 0x0a, 0x07, 0x05, 0x02, 0x01}, /* 24, -12.0dB */
+ {0x0d, 0x0c, 0x0b, 0x09, 0x07, 0x04, 0x02, 0x01}, /* 25, -12.5dB */
+ {0x0c, 0x0c, 0x0a, 0x09, 0x06, 0x04, 0x02, 0x01}, /* 26, -13.0dB */
+ {0x0b, 0x0b, 0x0a, 0x08, 0x06, 0x04, 0x02, 0x01}, /* 27, -13.5dB */
+ {0x0b, 0x0a, 0x09, 0x08, 0x06, 0x04, 0x02, 0x01}, /* 28, -14.0dB */
+ {0x0a, 0x0a, 0x09, 0x07, 0x05, 0x03, 0x02, 0x01}, /* 29, -14.5dB */
+ {0x0a, 0x09, 0x08, 0x07, 0x05, 0x03, 0x02, 0x01}, /* 30, -15.0dB */
+ {0x09, 0x09, 0x08, 0x06, 0x05, 0x03, 0x01, 0x01}, /* 31, -15.5dB */
+ {0x09, 0x08, 0x07, 0x06, 0x04, 0x03, 0x01, 0x01} /* 32, -16.0dB */
+};
+
+static const u8 cckswing_table_ch14[CCK_TABLE_SIZE][8] = {
+ {0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00}, /* 0, +0dB */
+ {0x33, 0x32, 0x2b, 0x19, 0x00, 0x00, 0x00, 0x00}, /* 1, -0.5dB */
+ {0x30, 0x2f, 0x29, 0x18, 0x00, 0x00, 0x00, 0x00}, /* 2, -1.0dB */
+ {0x2d, 0x2d, 0x17, 0x17, 0x00, 0x00, 0x00, 0x00}, /* 3, -1.5dB */
+ {0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00}, /* 4, -2.0dB */
+ {0x28, 0x28, 0x24, 0x14, 0x00, 0x00, 0x00, 0x00}, /* 5, -2.5dB */
+ {0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00}, /* 6, -3.0dB */
+ {0x24, 0x23, 0x1f, 0x12, 0x00, 0x00, 0x00, 0x00}, /* 7, -3.5dB */
+ {0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00}, /* 8, -4.0dB */
+ {0x20, 0x20, 0x1b, 0x10, 0x00, 0x00, 0x00, 0x00}, /* 9, -4.5dB */
+ {0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00}, /* 10, -5.0dB */
+ {0x1d, 0x1c, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00}, /* 11, -5.5dB */
+ {0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00}, /* 12, -6.0dB */
+ {0x1a, 0x19, 0x16, 0x0d, 0x00, 0x00, 0x00, 0x00}, /* 13, -6.5dB */
+ {0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00}, /* 14, -7.0dB */
+ {0x17, 0x16, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x00}, /* 15, -7.5dB */
+ {0x16, 0x15, 0x12, 0x0b, 0x00, 0x00, 0x00, 0x00}, /* 16, -8.0dB */
+ {0x14, 0x14, 0x11, 0x0a, 0x00, 0x00, 0x00, 0x00}, /* 17, -8.5dB */
+ {0x13, 0x13, 0x10, 0x0a, 0x00, 0x00, 0x00, 0x00}, /* 18, -9.0dB */
+ {0x12, 0x12, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, /* 19, -9.5dB */
+ {0x11, 0x11, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, /* 20, -10.0dB */
+ {0x10, 0x10, 0x0e, 0x08, 0x00, 0x00, 0x00, 0x00}, /* 21, -10.5dB */
+ {0x0f, 0x0f, 0x0d, 0x08, 0x00, 0x00, 0x00, 0x00}, /* 22, -11.0dB */
+ {0x0e, 0x0e, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00}, /* 23, -11.5dB */
+ {0x0d, 0x0d, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00}, /* 24, -12.0dB */
+ {0x0d, 0x0c, 0x0b, 0x06, 0x00, 0x00, 0x00, 0x00}, /* 25, -12.5dB */
+ {0x0c, 0x0c, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00}, /* 26, -13.0dB */
+ {0x0b, 0x0b, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00}, /* 27, -13.5dB */
+ {0x0b, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 28, -14.0dB */
+ {0x0a, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 29, -14.5dB */
+ {0x0a, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 30, -15.0dB */
+ {0x09, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 31, -15.5dB */
+ {0x09, 0x08, 0x07, 0x04, 0x00, 0x00, 0x00, 0x00} /* 32, -16.0dB */
+};
+
+static void rtl92d_dm_diginit(struct ieee80211_hw *hw)
+{
+ de_digtable.dig_enable_flag = true;
+ de_digtable.dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX;
+ de_digtable.cur_igvalue = 0x20;
+ de_digtable.pre_igvalue = 0x0;
+ de_digtable.cursta_connectctate = DIG_STA_DISCONNECT;
+ de_digtable.presta_connectstate = DIG_STA_DISCONNECT;
+ de_digtable.curmultista_connectstate = DIG_MULTISTA_DISCONNECT;
+ de_digtable.rssi_lowthresh = DM_DIG_THRESH_LOW;
+ de_digtable.rssi_highthresh = DM_DIG_THRESH_HIGH;
+ de_digtable.fa_lowthresh = DM_FALSEALARM_THRESH_LOW;
+ de_digtable.fa_highthresh = DM_FALSEALARM_THRESH_HIGH;
+ de_digtable.rx_gain_range_max = DM_DIG_FA_UPPER;
+ de_digtable.rx_gain_range_min = DM_DIG_FA_LOWER;
+ de_digtable.backoff_val = DM_DIG_BACKOFF_DEFAULT;
+ de_digtable.backoff_val_range_max = DM_DIG_BACKOFF_MAX;
+ de_digtable.backoff_val_range_min = DM_DIG_BACKOFF_MIN;
+ de_digtable.pre_cck_pd_state = CCK_PD_STAGE_LOWRSSI;
+ de_digtable.cur_cck_pd_state = CCK_PD_STAGE_MAX;
+ de_digtable.large_fa_hit = 0;
+ de_digtable.recover_cnt = 0;
+ de_digtable.forbidden_igi = DM_DIG_FA_LOWER;
+}
+
+static void rtl92d_dm_false_alarm_counter_statistics(struct ieee80211_hw *hw)
+{
+ u32 ret_value;
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct false_alarm_statistics *falsealm_cnt = &(rtlpriv->falsealm_cnt);
+ unsigned long flag = 0;
+
+ /* hold ofdm counter */
+ rtl_set_bbreg(hw, ROFDM0_LSTF, BIT(31), 1); /* hold page C counter */
+ rtl_set_bbreg(hw, ROFDM1_LSTF, BIT(31), 1); /*hold page D counter */
+
+ ret_value = rtl_get_bbreg(hw, ROFDM0_FRAMESYNC, BMASKDWORD);
+ falsealm_cnt->cnt_fast_fsync_fail = (ret_value & 0xffff);
+ falsealm_cnt->cnt_sb_search_fail = ((ret_value & 0xffff0000) >> 16);
+ ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER1, BMASKDWORD);
+ falsealm_cnt->cnt_parity_fail = ((ret_value & 0xffff0000) >> 16);
+ ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER2, BMASKDWORD);
+ falsealm_cnt->cnt_rate_illegal = (ret_value & 0xffff);
+ falsealm_cnt->cnt_crc8_fail = ((ret_value & 0xffff0000) >> 16);
+ ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER3, BMASKDWORD);
+ falsealm_cnt->cnt_mcs_fail = (ret_value & 0xffff);
+ falsealm_cnt->cnt_ofdm_fail = falsealm_cnt->cnt_parity_fail +
+ falsealm_cnt->cnt_rate_illegal +
+ falsealm_cnt->cnt_crc8_fail +
+ falsealm_cnt->cnt_mcs_fail +
+ falsealm_cnt->cnt_fast_fsync_fail +
+ falsealm_cnt->cnt_sb_search_fail;
+
+ if (rtlpriv->rtlhal.current_bandtype != BAND_ON_5G) {
+ /* hold cck counter */
+ rtl92d_acquire_cckandrw_pagea_ctl(hw, &flag);
+ ret_value = rtl_get_bbreg(hw, RCCK0_FACOUNTERLOWER, BMASKBYTE0);
+ falsealm_cnt->cnt_cck_fail = ret_value;
+ ret_value = rtl_get_bbreg(hw, RCCK0_FACOUNTERUPPER, BMASKBYTE3);
+ falsealm_cnt->cnt_cck_fail += (ret_value & 0xff) << 8;
+ rtl92d_release_cckandrw_pagea_ctl(hw, &flag);
+ } else {
+ falsealm_cnt->cnt_cck_fail = 0;
+ }
+
+ /* reset false alarm counter registers */
+ falsealm_cnt->cnt_all = falsealm_cnt->cnt_fast_fsync_fail +
+ falsealm_cnt->cnt_sb_search_fail +
+ falsealm_cnt->cnt_parity_fail +
+ falsealm_cnt->cnt_rate_illegal +
+ falsealm_cnt->cnt_crc8_fail +
+ falsealm_cnt->cnt_mcs_fail +
+ falsealm_cnt->cnt_cck_fail;
+
+ rtl_set_bbreg(hw, ROFDM1_LSTF, 0x08000000, 1);
+ /* update ofdm counter */
+ rtl_set_bbreg(hw, ROFDM1_LSTF, 0x08000000, 0);
+ /* update page C counter */
+ rtl_set_bbreg(hw, ROFDM0_LSTF, BIT(31), 0);
+ /* update page D counter */
+ rtl_set_bbreg(hw, ROFDM1_LSTF, BIT(31), 0);
+ if (rtlpriv->rtlhal.current_bandtype != BAND_ON_5G) {
+ /* reset cck counter */
+ rtl92d_acquire_cckandrw_pagea_ctl(hw, &flag);
+ rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, 0x0000c000, 0);
+ /* enable cck counter */
+ rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, 0x0000c000, 2);
+ rtl92d_release_cckandrw_pagea_ctl(hw, &flag);
+ }
+ RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, ("Cnt_Fast_Fsync_fail = %x, "
+ "Cnt_SB_Search_fail = %x\n",
+ falsealm_cnt->cnt_fast_fsync_fail,
+ falsealm_cnt->cnt_sb_search_fail));
+ RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, ("Cnt_Parity_Fail = %x, "
+ "Cnt_Rate_Illegal = %x, Cnt_Crc8_fail = %x, "
+ "Cnt_Mcs_fail = %x\n",
+ falsealm_cnt->cnt_parity_fail,
+ falsealm_cnt->cnt_rate_illegal,
+ falsealm_cnt->cnt_crc8_fail,
+ falsealm_cnt->cnt_mcs_fail));
+ RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
+ ("Cnt_Ofdm_fail = %x, " "Cnt_Cck_fail = %x, "
+ "Cnt_all = %x\n",
+ falsealm_cnt->cnt_ofdm_fail,
+ falsealm_cnt->cnt_cck_fail,
+ falsealm_cnt->cnt_all));
+}
+
+static void rtl92d_dm_find_minimum_rssi(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_mac *mac = rtl_mac(rtlpriv);
+
+ /* Determine the minimum RSSI */
+ if ((mac->link_state < MAC80211_LINKED) &&
+ (rtlpriv->dm.UNDEC_SM_PWDB == 0)) {
+ de_digtable.min_undecorated_pwdb_for_dm = 0;
+ RT_TRACE(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD,
+ ("Not connected to any\n"));
+ }
+ if (mac->link_state >= MAC80211_LINKED) {
+ if (mac->opmode == NL80211_IFTYPE_AP ||
+ mac->opmode == NL80211_IFTYPE_ADHOC) {
+ de_digtable.min_undecorated_pwdb_for_dm =
+ rtlpriv->dm.UNDEC_SM_PWDB;
+ RT_TRACE(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD,
+ ("AP Client PWDB = 0x%lx\n",
+ rtlpriv->dm.UNDEC_SM_PWDB));
+ } else {
+ de_digtable.min_undecorated_pwdb_for_dm =
+ rtlpriv->dm.undecorated_smoothed_pwdb;
+ RT_TRACE(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD,
+ ("STA Default Port PWDB = 0x%x\n",
+ de_digtable.min_undecorated_pwdb_for_dm));
+ }
+ } else {
+ de_digtable.min_undecorated_pwdb_for_dm =
+ rtlpriv->dm.UNDEC_SM_PWDB;
+ RT_TRACE(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD,
+ ("AP Ext Port or disconnet PWDB = 0x%x\n",
+ de_digtable.min_undecorated_pwdb_for_dm));
+ }
+
+ RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, ("MinUndecoratedPWDBForDM =%d\n",
+ de_digtable.min_undecorated_pwdb_for_dm));
+}
+
+static void rtl92d_dm_cck_packet_detection_thresh(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ unsigned long flag = 0;
+
+ if (de_digtable.cursta_connectctate == DIG_STA_CONNECT) {
+ if (de_digtable.pre_cck_pd_state == CCK_PD_STAGE_LOWRSSI) {
+ if (de_digtable.min_undecorated_pwdb_for_dm <= 25)
+ de_digtable.cur_cck_pd_state =
+ CCK_PD_STAGE_LOWRSSI;
+ else
+ de_digtable.cur_cck_pd_state =
+ CCK_PD_STAGE_HIGHRSSI;
+ } else {
+ if (de_digtable.min_undecorated_pwdb_for_dm <= 20)
+ de_digtable.cur_cck_pd_state =
+ CCK_PD_STAGE_LOWRSSI;
+ else
+ de_digtable.cur_cck_pd_state =
+ CCK_PD_STAGE_HIGHRSSI;
+ }
+ } else {
+ de_digtable.cur_cck_pd_state = CCK_PD_STAGE_LOWRSSI;
+ }
+ if (de_digtable.pre_cck_pd_state != de_digtable.cur_cck_pd_state) {
+ if (de_digtable.cur_cck_pd_state == CCK_PD_STAGE_LOWRSSI) {
+ rtl92d_acquire_cckandrw_pagea_ctl(hw, &flag);
+ rtl_set_bbreg(hw, RCCK0_CCA, BMASKBYTE2, 0x83);
+ rtl92d_release_cckandrw_pagea_ctl(hw, &flag);
+ } else {
+ rtl92d_acquire_cckandrw_pagea_ctl(hw, &flag);
+ rtl_set_bbreg(hw, RCCK0_CCA, BMASKBYTE2, 0xcd);
+ rtl92d_release_cckandrw_pagea_ctl(hw, &flag);
+ }
+ de_digtable.pre_cck_pd_state = de_digtable.cur_cck_pd_state;
+ }
+ RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, ("CurSTAConnectState=%s\n",
+ (de_digtable.cursta_connectctate == DIG_STA_CONNECT ?
+ "DIG_STA_CONNECT " : "DIG_STA_DISCONNECT")));
+ RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, ("CCKPDStage=%s\n",
+ (de_digtable.cur_cck_pd_state == CCK_PD_STAGE_LOWRSSI ?
+ "Low RSSI " : "High RSSI ")));
+ RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, ("is92d single phy =%x\n",
+ IS_92D_SINGLEPHY(rtlpriv->rtlhal.version)));
+
+}
+
+void rtl92d_dm_write_dig(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+ RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, ("cur_igvalue = 0x%x, "
+ "pre_igvalue = 0x%x, backoff_val = %d\n",
+ de_digtable.cur_igvalue, de_digtable.pre_igvalue,
+ de_digtable.backoff_val));
+ if (de_digtable.dig_enable_flag == false) {
+ RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, ("DIG is disabled\n"));
+ de_digtable.pre_igvalue = 0x17;
+ return;
+ }
+ if (de_digtable.pre_igvalue != de_digtable.cur_igvalue) {
+ rtl_set_bbreg(hw, ROFDM0_XAAGCCORE1, 0x7f,
+ de_digtable.cur_igvalue);
+ rtl_set_bbreg(hw, ROFDM0_XBAGCCORE1, 0x7f,
+ de_digtable.cur_igvalue);
+ de_digtable.pre_igvalue = de_digtable.cur_igvalue;
+ }
+}
+
+static void rtl92d_early_mode_enabled(struct rtl_priv *rtlpriv)
+{
+ if ((rtlpriv->mac80211.link_state >= MAC80211_LINKED) &&
+ (rtlpriv->mac80211.vendor == PEER_CISCO)) {
+ RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
+ ("IOT_PEER = CISCO\n"));
+ if (de_digtable.last_min_undecorated_pwdb_for_dm >= 50
+ && de_digtable.min_undecorated_pwdb_for_dm < 50) {
+ rtl_write_byte(rtlpriv, REG_EARLY_MODE_CONTROL, 0x00);
+ RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
+ ("Early Mode Off\n"));
+ } else if (de_digtable.last_min_undecorated_pwdb_for_dm <= 55 &&
+ de_digtable.min_undecorated_pwdb_for_dm > 55) {
+ rtl_write_byte(rtlpriv, REG_EARLY_MODE_CONTROL, 0x0f);
+ RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
+ ("Early Mode On\n"));
+ }
+ } else if (!(rtl_read_byte(rtlpriv, REG_EARLY_MODE_CONTROL) & 0xf)) {
+ rtl_write_byte(rtlpriv, REG_EARLY_MODE_CONTROL, 0x0f);
+ RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, ("Early Mode On\n"));
+ }
+}
+
+static void rtl92d_dm_dig(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u8 value_igi = de_digtable.cur_igvalue;
+ struct false_alarm_statistics *falsealm_cnt = &(rtlpriv->falsealm_cnt);
+
+ RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, ("==>\n"));
+ if (rtlpriv->rtlhal.earlymode_enable) {
+ rtl92d_early_mode_enabled(rtlpriv);
+ de_digtable.last_min_undecorated_pwdb_for_dm =
+ de_digtable.min_undecorated_pwdb_for_dm;
+ }
+ if (rtlpriv->dm.dm_initialgain_enable == false)
+ return;
+
+ /* because we will send data pkt when scanning
+ * this will cause some ap like gear-3700 wep TP
+ * lower if we retrun here, this is the diff of
+ * mac80211 driver vs ieee80211 driver */
+ /* if (rtlpriv->mac80211.act_scanning)
+ * return; */
+
+ /* Not STA mode return tmp */
+ if (rtlpriv->mac80211.opmode != NL80211_IFTYPE_STATION)
+ return;
+ RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, ("progress\n"));
+ /* Decide the current status and if modify initial gain or not */
+ if (rtlpriv->mac80211.link_state >= MAC80211_LINKED)
+ de_digtable.cursta_connectctate = DIG_STA_CONNECT;
+ else
+ de_digtable.cursta_connectctate = DIG_STA_DISCONNECT;
+
+ /* adjust initial gain according to false alarm counter */
+ if (falsealm_cnt->cnt_all < DM_DIG_FA_TH0)
+ value_igi--;
+ else if (falsealm_cnt->cnt_all < DM_DIG_FA_TH1)
+ value_igi += 0;
+ else if (falsealm_cnt->cnt_all < DM_DIG_FA_TH2)
+ value_igi++;
+ else if (falsealm_cnt->cnt_all >= DM_DIG_FA_TH2)
+ value_igi += 2;
+ RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
+ ("dm_DIG() Before: large_fa_hit=%d, forbidden_igi=%x\n",
+ de_digtable.large_fa_hit, de_digtable.forbidden_igi));
+ RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
+ ("dm_DIG() Before: Recover_cnt=%d, rx_gain_range_min=%x\n",
+ de_digtable.recover_cnt, de_digtable.rx_gain_range_min));
+
+ /* deal with abnorally large false alarm */
+ if (falsealm_cnt->cnt_all > 10000) {
+ RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
+ ("dm_DIG(): Abnornally false alarm case.\n"));
+
+ de_digtable.large_fa_hit++;
+ if (de_digtable.forbidden_igi < de_digtable.cur_igvalue) {
+ de_digtable.forbidden_igi = de_digtable.cur_igvalue;
+ de_digtable.large_fa_hit = 1;
+ }
+ if (de_digtable.large_fa_hit >= 3) {
+ if ((de_digtable.forbidden_igi + 1) > DM_DIG_MAX)
+ de_digtable.rx_gain_range_min = DM_DIG_MAX;
+ else
+ de_digtable.rx_gain_range_min =
+ (de_digtable.forbidden_igi + 1);
+ de_digtable.recover_cnt = 3600; /* 3600=2hr */
+ }
+ } else {
+ /* Recovery mechanism for IGI lower bound */
+ if (de_digtable.recover_cnt != 0) {
+ de_digtable.recover_cnt--;
+ } else {
+ if (de_digtable.large_fa_hit == 0) {
+ if ((de_digtable.forbidden_igi - 1) <
+ DM_DIG_FA_LOWER) {
+ de_digtable.forbidden_igi =
+ DM_DIG_FA_LOWER;
+ de_digtable.rx_gain_range_min =
+ DM_DIG_FA_LOWER;
+
+ } else {
+ de_digtable.forbidden_igi--;
+ de_digtable.rx_gain_range_min =
+ (de_digtable.forbidden_igi + 1);
+ }
+ } else if (de_digtable.large_fa_hit == 3) {
+ de_digtable.large_fa_hit = 0;
+ }
+ }
+ }
+ RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
+ ("dm_DIG() After: large_fa_hit=%d, forbidden_igi=%x\n",
+ de_digtable.large_fa_hit, de_digtable.forbidden_igi));
+ RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
+ ("dm_DIG() After: recover_cnt=%d, rx_gain_range_min=%x\n",
+ de_digtable.recover_cnt, de_digtable.rx_gain_range_min));
+
+ if (value_igi > DM_DIG_MAX)
+ value_igi = DM_DIG_MAX;
+ else if (value_igi < de_digtable.rx_gain_range_min)
+ value_igi = de_digtable.rx_gain_range_min;
+ de_digtable.cur_igvalue = value_igi;
+ rtl92d_dm_write_dig(hw);
+ if (rtlpriv->rtlhal.current_bandtype != BAND_ON_5G)
+ rtl92d_dm_cck_packet_detection_thresh(hw);
+ RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, ("<<==\n"));
+}
+
+static void rtl92d_dm_init_dynamic_txpower(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+ rtlpriv->dm.dynamic_txpower_enable = true;
+ rtlpriv->dm.last_dtp_lvl = TXHIGHPWRLEVEL_NORMAL;
+ rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL;
+}
+
+static void rtl92d_dm_dynamic_txpower(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
+ struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+ long undecorated_smoothed_pwdb;
+
+ if ((!rtlpriv->dm.dynamic_txpower_enable)
+ || rtlpriv->dm.dm_flag & HAL_DM_HIPWR_DISABLE) {
+ rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL;
+ return;
+ }
+ if ((mac->link_state < MAC80211_LINKED) &&
+ (rtlpriv->dm.UNDEC_SM_PWDB == 0)) {
+ RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE,
+ ("Not connected to any\n"));
+ rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL;
+ rtlpriv->dm.last_dtp_lvl = TXHIGHPWRLEVEL_NORMAL;
+ return;
+ }
+ if (mac->link_state >= MAC80211_LINKED) {
+ if (mac->opmode == NL80211_IFTYPE_ADHOC) {
+ undecorated_smoothed_pwdb =
+ rtlpriv->dm.UNDEC_SM_PWDB;
+ RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
+ ("IBSS Client PWDB = 0x%lx\n",
+ undecorated_smoothed_pwdb));
+ } else {
+ undecorated_smoothed_pwdb =
+ rtlpriv->dm.undecorated_smoothed_pwdb;
+ RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
+ ("STA Default Port PWDB = 0x%lx\n",
+ undecorated_smoothed_pwdb));
+ }
+ } else {
+ undecorated_smoothed_pwdb =
+ rtlpriv->dm.UNDEC_SM_PWDB;
+
+ RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
+ ("AP Ext Port PWDB = 0x%lx\n",
+ undecorated_smoothed_pwdb));
+ }
+ if (rtlhal->current_bandtype == BAND_ON_5G) {
+ if (undecorated_smoothed_pwdb >= 0x33) {
+ rtlpriv->dm.dynamic_txhighpower_lvl =
+ TXHIGHPWRLEVEL_LEVEL2;
+ RT_TRACE(rtlpriv, COMP_HIPWR, DBG_LOUD,
+ ("5G:TxHighPwrLevel_Level2 (TxPwr=0x0)\n"));
+ } else if ((undecorated_smoothed_pwdb < 0x33)
+ && (undecorated_smoothed_pwdb >= 0x2b)) {
+ rtlpriv->dm.dynamic_txhighpower_lvl =
+ TXHIGHPWRLEVEL_LEVEL1;
+ RT_TRACE(rtlpriv, COMP_HIPWR, DBG_LOUD,
+ ("5G:TxHighPwrLevel_Level1 (TxPwr=0x10)\n"));
+ } else if (undecorated_smoothed_pwdb < 0x2b) {
+ rtlpriv->dm.dynamic_txhighpower_lvl =
+ TXHIGHPWRLEVEL_NORMAL;
+ RT_TRACE(rtlpriv, COMP_HIPWR, DBG_LOUD,
+ ("5G:TxHighPwrLevel_Normal\n"));
+ }
+ } else {
+ if (undecorated_smoothed_pwdb >=
+ TX_POWER_NEAR_FIELD_THRESH_LVL2) {
+ rtlpriv->dm.dynamic_txhighpower_lvl =
+ TXHIGHPWRLEVEL_LEVEL2;
+ RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
+ ("TXHIGHPWRLEVEL_LEVEL1 (TxPwr=0x0)\n"));
+ } else
+ if ((undecorated_smoothed_pwdb <
+ (TX_POWER_NEAR_FIELD_THRESH_LVL2 - 3))
+ && (undecorated_smoothed_pwdb >=
+ TX_POWER_NEAR_FIELD_THRESH_LVL1)) {
+
+ rtlpriv->dm.dynamic_txhighpower_lvl =
+ TXHIGHPWRLEVEL_LEVEL1;
+ RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
+ ("TXHIGHPWRLEVEL_LEVEL1 (TxPwr=0x10)\n"));
+ } else if (undecorated_smoothed_pwdb <
+ (TX_POWER_NEAR_FIELD_THRESH_LVL1 - 5)) {
+ rtlpriv->dm.dynamic_txhighpower_lvl =
+ TXHIGHPWRLEVEL_NORMAL;
+ RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
+ ("TXHIGHPWRLEVEL_NORMAL\n"));
+ }
+ }
+ if ((rtlpriv->dm.dynamic_txhighpower_lvl != rtlpriv->dm.last_dtp_lvl)) {
+ RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
+ ("PHY_SetTxPowerLevel8192S() Channel = %d\n",
+ rtlphy->current_channel));
+ rtl92d_phy_set_txpower_level(hw, rtlphy->current_channel);
+ }
+ rtlpriv->dm.last_dtp_lvl = rtlpriv->dm.dynamic_txhighpower_lvl;
+}
+
+static void rtl92d_dm_pwdb_monitor(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+ /* AP & ADHOC & MESH will return tmp */
+ if (rtlpriv->mac80211.opmode != NL80211_IFTYPE_STATION)
+ return;
+ /* Indicate Rx signal strength to FW. */
+ if (rtlpriv->dm.useramask) {
+ u32 temp = rtlpriv->dm.undecorated_smoothed_pwdb;
+
+ temp <<= 16;
+ temp |= 0x100;
+ /* fw v12 cmdid 5:use max macid ,for nic ,
+ * default macid is 0 ,max macid is 1 */
+ rtl92d_fill_h2c_cmd(hw, H2C_RSSI_REPORT, 3, (u8 *) (&temp));
+ } else {
+ rtl_write_byte(rtlpriv, 0x4fe,
+ (u8) rtlpriv->dm.undecorated_smoothed_pwdb);
+ }
+}
+
+void rtl92d_dm_init_edca_turbo(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+ rtlpriv->dm.current_turbo_edca = false;
+ rtlpriv->dm.is_any_nonbepkts = false;
+ rtlpriv->dm.is_cur_rdlstate = false;
+}
+
+static void rtl92d_dm_check_edca_turbo(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+ static u64 last_txok_cnt;
+ static u64 last_rxok_cnt;
+ u64 cur_txok_cnt;
+ u64 cur_rxok_cnt;
+ u32 edca_be_ul = 0x5ea42b;
+ u32 edca_be_dl = 0x5ea42b;
+
+ if (mac->link_state != MAC80211_LINKED) {
+ rtlpriv->dm.current_turbo_edca = false;
+ goto exit;
+ }
+
+ /* Enable BEQ TxOP limit configuration in wireless G-mode. */
+ /* To check whether we shall force turn on TXOP configuration. */
+ if ((!rtlpriv->dm.disable_framebursting) &&
+ (rtlpriv->sec.pairwise_enc_algorithm == WEP40_ENCRYPTION ||
+ rtlpriv->sec.pairwise_enc_algorithm == WEP104_ENCRYPTION ||
+ rtlpriv->sec.pairwise_enc_algorithm == TKIP_ENCRYPTION)) {
+ /* Force TxOP limit to 0x005e for UL. */
+ if (!(edca_be_ul & 0xffff0000))
+ edca_be_ul |= 0x005e0000;
+ /* Force TxOP limit to 0x005e for DL. */
+ if (!(edca_be_dl & 0xffff0000))
+ edca_be_dl |= 0x005e0000;
+ }
+
+ if ((!rtlpriv->dm.is_any_nonbepkts) &&
+ (!rtlpriv->dm.disable_framebursting)) {
+ cur_txok_cnt = rtlpriv->stats.txbytesunicast - last_txok_cnt;
+ cur_rxok_cnt = rtlpriv->stats.rxbytesunicast - last_rxok_cnt;
+ if (cur_rxok_cnt > 4 * cur_txok_cnt) {
+ if (!rtlpriv->dm.is_cur_rdlstate ||
+ !rtlpriv->dm.current_turbo_edca) {
+ rtl_write_dword(rtlpriv, REG_EDCA_BE_PARAM,
+ edca_be_dl);
+ rtlpriv->dm.is_cur_rdlstate = true;
+ }
+ } else {
+ if (rtlpriv->dm.is_cur_rdlstate ||
+ !rtlpriv->dm.current_turbo_edca) {
+ rtl_write_dword(rtlpriv, REG_EDCA_BE_PARAM,
+ edca_be_ul);
+ rtlpriv->dm.is_cur_rdlstate = false;
+ }
+ }
+ rtlpriv->dm.current_turbo_edca = true;
+ } else {
+ if (rtlpriv->dm.current_turbo_edca) {
+ u8 tmp = AC0_BE;
+ rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AC_PARAM,
+ (u8 *) (&tmp));
+ rtlpriv->dm.current_turbo_edca = false;
+ }
+ }
+
+exit:
+ rtlpriv->dm.is_any_nonbepkts = false;
+ last_txok_cnt = rtlpriv->stats.txbytesunicast;
+ last_rxok_cnt = rtlpriv->stats.rxbytesunicast;
+}
+
+static void rtl92d_dm_rxgain_tracking_thermalmeter(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u8 index_mapping[RX_INDEX_MAPPING_NUM] = {
+ 0x0f, 0x0f, 0x0d, 0x0c, 0x0b,
+ 0x0a, 0x09, 0x08, 0x07, 0x06,
+ 0x05, 0x04, 0x04, 0x03, 0x02
+ };
+ int i;
+ u32 u4tmp;
+
+ u4tmp = (index_mapping[(rtlpriv->efuse.eeprom_thermalmeter -
+ rtlpriv->dm.thermalvalue_rxgain)]) << 12;
+ RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
+ ("===> Rx Gain %x\n", u4tmp));
+ for (i = RF90_PATH_A; i < rtlpriv->phy.num_total_rfpath; i++)
+ rtl_set_rfreg(hw, i, 0x3C, BRFREGOFFSETMASK,
+ (rtlpriv->phy.reg_rf3c[i] & (~(0xF000))) | u4tmp);
+}
+
+static void rtl92d_bandtype_2_4G(struct ieee80211_hw *hw, long *temp_cckg,
+ u8 *cck_index_old)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ int i;
+ unsigned long flag = 0;
+ long temp_cck;
+
+ /* Query CCK default setting From 0xa24 */
+ rtl92d_acquire_cckandrw_pagea_ctl(hw, &flag);
+ temp_cck = rtl_get_bbreg(hw, RCCK0_TXFILTER2,
+ BMASKDWORD) & BMASKCCK;
+ rtl92d_release_cckandrw_pagea_ctl(hw, &flag);
+ for (i = 0; i < CCK_TABLE_LENGTH; i++) {
+ if (rtlpriv->dm.cck_inch14) {
+ if (!memcmp((void *)&temp_cck,
+ (void *)&cckswing_table_ch14[i][2], 4)) {
+ *cck_index_old = (u8) i;
+ RT_TRACE(rtlpriv,
+ COMP_POWER_TRACKING,
+ DBG_LOUD,
+ ("Initial reg0x%x = 0x%lx, "
+ "cck_index=0x%x, ch 14 %d\n",
+ RCCK0_TXFILTER2,
+ temp_cck, *cck_index_old,
+ rtlpriv->dm.cck_inch14));
+ break;
+ }
+ } else {
+ if (!memcmp((void *) &temp_cck,
+ &cckswing_table_ch1ch13[i][2], 4)) {
+ *cck_index_old = (u8) i;
+ RT_TRACE(rtlpriv, COMP_POWER_TRACKING,
+ DBG_LOUD,
+ ("Initial reg0x%x = 0x%lx, "
+ "cck_index = 0x%x, ch14 %d\n",
+ RCCK0_TXFILTER2,
+ temp_cck, *cck_index_old,
+ rtlpriv->dm.cck_inch14));
+ break;
+ }
+ }
+ }
+ *temp_cckg = temp_cck;
+}
+
+static void rtl92d_bandtype_5G(struct rtl_hal *rtlhal, u8 *ofdm_index,
+ bool *internal_pa, u8 thermalvalue, u8 delta,
+ u8 rf, struct rtl_efuse *rtlefuse,
+ struct rtl_priv *rtlpriv, struct rtl_phy *rtlphy,
+ u8 index_mapping[5][INDEX_MAPPING_NUM],
+ u8 index_mapping_pa[8][INDEX_MAPPING_NUM])
+{
+ int i;
+ u8 index;
+ u8 offset = 0;
+
+ for (i = 0; i < rf; i++) {
+ if (rtlhal->macphymode == DUALMAC_DUALPHY &&
+ rtlhal->interfaceindex == 1) /* MAC 1 5G */
+ *internal_pa = rtlefuse->internal_pa_5g[1];
+ else
+ *internal_pa = rtlefuse->internal_pa_5g[i];
+ if (*internal_pa) {
+ if (rtlhal->interfaceindex == 1 || i == rf)
+ offset = 4;
+ else
+ offset = 0;
+ if (rtlphy->current_channel >= 100 &&
+ rtlphy->current_channel <= 165)
+ offset += 2;
+ } else {
+ if (rtlhal->interfaceindex == 1 || i == rf)
+ offset = 2;
+ else
+ offset = 0;
+ }
+ if (thermalvalue > rtlefuse->eeprom_thermalmeter)
+ offset++;
+ if (*internal_pa) {
+ if (delta > INDEX_MAPPING_NUM - 1)
+ index = index_mapping_pa[offset]
+ [INDEX_MAPPING_NUM - 1];
+ else
+ index =
+ index_mapping_pa[offset][delta];
+ } else {
+ if (delta > INDEX_MAPPING_NUM - 1)
+ index =
+ index_mapping[offset][INDEX_MAPPING_NUM - 1];
+ else
+ index = index_mapping[offset][delta];
+ }
+ if (thermalvalue > rtlefuse->eeprom_thermalmeter) {
+ if (*internal_pa && thermalvalue > 0x12) {
+ ofdm_index[i] = rtlpriv->dm.ofdm_index[i] -
+ ((delta / 2) * 3 + (delta % 2));
+ } else {
+ ofdm_index[i] -= index;
+ }
+ } else {
+ ofdm_index[i] += index;
+ }
+ }
+}
+
+static void rtl92d_dm_txpower_tracking_callback_thermalmeter(
+ struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+ u8 thermalvalue, delta, delta_lck, delta_iqk, delta_rxgain;
+ u8 offset, thermalvalue_avg_count = 0;
+ u32 thermalvalue_avg = 0;
+ bool internal_pa = false;
+ long ele_a = 0, ele_d, temp_cck, val_x, value32;
+ long val_y, ele_c = 0;
+ u8 ofdm_index[2];
+ u8 cck_index = 0;
+ u8 ofdm_index_old[2];
+ u8 cck_index_old = 0;
+ u8 index;
+ int i;
+ bool is2t = IS_92D_SINGLEPHY(rtlhal->version);
+ u8 ofdm_min_index = 6, ofdm_min_index_internal_pa = 3, rf;
+ u8 indexforchannel =
+ rtl92d_get_rightchnlplace_for_iqk(rtlphy->current_channel);
+ u8 index_mapping[5][INDEX_MAPPING_NUM] = {
+ /* 5G, path A/MAC 0, decrease power */
+ {0, 1, 3, 6, 8, 9, 11, 13, 14, 16, 17, 18, 18},
+ /* 5G, path A/MAC 0, increase power */
+ {0, 2, 4, 5, 7, 10, 12, 14, 16, 18, 18, 18, 18},
+ /* 5G, path B/MAC 1, decrease power */
+ {0, 2, 3, 6, 8, 9, 11, 13, 14, 16, 17, 18, 18},
+ /* 5G, path B/MAC 1, increase power */
+ {0, 2, 4, 5, 7, 10, 13, 16, 16, 18, 18, 18, 18},
+ /* 2.4G, for decreas power */
+ {0, 1, 2, 3, 4, 5, 6, 7, 7, 8, 9, 10, 10},
+ };
+ u8 index_mapping_internal_pa[8][INDEX_MAPPING_NUM] = {
+ /* 5G, path A/MAC 0, ch36-64, decrease power */
+ {0, 1, 2, 4, 6, 7, 9, 11, 12, 14, 15, 16, 16},
+ /* 5G, path A/MAC 0, ch36-64, increase power */
+ {0, 2, 4, 5, 7, 10, 12, 14, 16, 18, 18, 18, 18},
+ /* 5G, path A/MAC 0, ch100-165, decrease power */
+ {0, 1, 2, 3, 5, 6, 8, 10, 11, 13, 14, 15, 15},
+ /* 5G, path A/MAC 0, ch100-165, increase power */
+ {0, 2, 4, 5, 7, 10, 12, 14, 16, 18, 18, 18, 18},
+ /* 5G, path B/MAC 1, ch36-64, decrease power */
+ {0, 1, 2, 4, 6, 7, 9, 11, 12, 14, 15, 16, 16},
+ /* 5G, path B/MAC 1, ch36-64, increase power */
+ {0, 2, 4, 5, 7, 10, 13, 16, 16, 18, 18, 18, 18},
+ /* 5G, path B/MAC 1, ch100-165, decrease power */
+ {0, 1, 2, 3, 5, 6, 8, 9, 10, 12, 13, 14, 14},
+ /* 5G, path B/MAC 1, ch100-165, increase power */
+ {0, 2, 4, 5, 7, 10, 13, 16, 16, 18, 18, 18, 18},
+ };
+
+ rtlpriv->dm.txpower_trackinginit = true;
+ RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, ("\n"));
+ thermalvalue = (u8) rtl_get_rfreg(hw, RF90_PATH_A, RF_T_METER, 0xf800);
+ RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
+ ("Readback Thermal Meter = 0x%x pre thermal meter 0x%x "
+ "eeprom_thermalmeter 0x%x\n", thermalvalue,
+ rtlpriv->dm.thermalvalue, rtlefuse->eeprom_thermalmeter));
+ rtl92d_phy_ap_calibrate(hw, (thermalvalue -
+ rtlefuse->eeprom_thermalmeter));
+ if (is2t)
+ rf = 2;
+ else
+ rf = 1;
+ if (thermalvalue) {
+ ele_d = rtl_get_bbreg(hw, ROFDM0_XATxIQIMBALANCE,
+ BMASKDWORD) & BMASKOFDM_D;
+ for (i = 0; i < OFDM_TABLE_SIZE_92D; i++) {
+ if (ele_d == (ofdmswing_table[i] & BMASKOFDM_D)) {
+ ofdm_index_old[0] = (u8) i;
+
+ RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
+ ("Initial pathA ele_d reg0x%x = 0x%lx,"
+ " ofdm_index=0x%x\n",
+ ROFDM0_XATxIQIMBALANCE,
+ ele_d, ofdm_index_old[0]));
+ break;
+ }
+ }
+ if (is2t) {
+ ele_d = rtl_get_bbreg(hw, ROFDM0_XBTxIQIMBALANCE,
+ BMASKDWORD) & BMASKOFDM_D;
+ for (i = 0; i < OFDM_TABLE_SIZE_92D; i++) {
+ if (ele_d ==
+ (ofdmswing_table[i] & BMASKOFDM_D)) {
+ ofdm_index_old[1] = (u8) i;
+ RT_TRACE(rtlpriv, COMP_POWER_TRACKING,
+ DBG_LOUD,
+ ("Initial pathB ele_d reg "
+ "0x%x = 0x%lx, ofdm_index "
+ "= 0x%x\n",
+ ROFDM0_XBTxIQIMBALANCE, ele_d,
+ ofdm_index_old[1]));
+ break;
+ }
+ }
+ }
+ if (rtlhal->current_bandtype == BAND_ON_2_4G) {
+ rtl92d_bandtype_2_4G(hw, &temp_cck, &cck_index_old);
+ } else {
+ temp_cck = 0x090e1317;
+ cck_index_old = 12;
+ }
+
+ if (!rtlpriv->dm.thermalvalue) {
+ rtlpriv->dm.thermalvalue =
+ rtlefuse->eeprom_thermalmeter;
+ rtlpriv->dm.thermalvalue_lck = thermalvalue;
+ rtlpriv->dm.thermalvalue_iqk = thermalvalue;
+ rtlpriv->dm.thermalvalue_rxgain =
+ rtlefuse->eeprom_thermalmeter;
+ for (i = 0; i < rf; i++)
+ rtlpriv->dm.ofdm_index[i] = ofdm_index_old[i];
+ rtlpriv->dm.cck_index = cck_index_old;
+ }
+ if (rtlhal->reloadtxpowerindex) {
+ for (i = 0; i < rf; i++)
+ rtlpriv->dm.ofdm_index[i] = ofdm_index_old[i];
+ rtlpriv->dm.cck_index = cck_index_old;
+ RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
+ ("reload ofdm index for band switch\n"));
+ }
+ rtlpriv->dm.thermalvalue_avg
+ [rtlpriv->dm.thermalvalue_avg_index] = thermalvalue;
+ rtlpriv->dm.thermalvalue_avg_index++;
+ if (rtlpriv->dm.thermalvalue_avg_index == AVG_THERMAL_NUM)
+ rtlpriv->dm.thermalvalue_avg_index = 0;
+ for (i = 0; i < AVG_THERMAL_NUM; i++) {
+ if (rtlpriv->dm.thermalvalue_avg[i]) {
+ thermalvalue_avg +=
+ rtlpriv->dm.thermalvalue_avg[i];
+ thermalvalue_avg_count++;
+ }
+ }
+ if (thermalvalue_avg_count)
+ thermalvalue = (u8) (thermalvalue_avg /
+ thermalvalue_avg_count);
+ if (rtlhal->reloadtxpowerindex) {
+ delta = (thermalvalue > rtlefuse->eeprom_thermalmeter) ?
+ (thermalvalue - rtlefuse->eeprom_thermalmeter) :
+ (rtlefuse->eeprom_thermalmeter - thermalvalue);
+ rtlhal->reloadtxpowerindex = false;
+ rtlpriv->dm.done_txpower = false;
+ } else if (rtlpriv->dm.done_txpower) {
+ delta = (thermalvalue > rtlpriv->dm.thermalvalue) ?
+ (thermalvalue - rtlpriv->dm.thermalvalue) :
+ (rtlpriv->dm.thermalvalue - thermalvalue);
+ } else {
+ delta = (thermalvalue > rtlefuse->eeprom_thermalmeter) ?
+ (thermalvalue - rtlefuse->eeprom_thermalmeter) :
+ (rtlefuse->eeprom_thermalmeter - thermalvalue);
+ }
+ delta_lck = (thermalvalue > rtlpriv->dm.thermalvalue_lck) ?
+ (thermalvalue - rtlpriv->dm.thermalvalue_lck) :
+ (rtlpriv->dm.thermalvalue_lck - thermalvalue);
+ delta_iqk = (thermalvalue > rtlpriv->dm.thermalvalue_iqk) ?
+ (thermalvalue - rtlpriv->dm.thermalvalue_iqk) :
+ (rtlpriv->dm.thermalvalue_iqk - thermalvalue);
+ delta_rxgain =
+ (thermalvalue > rtlpriv->dm.thermalvalue_rxgain) ?
+ (thermalvalue - rtlpriv->dm.thermalvalue_rxgain) :
+ (rtlpriv->dm.thermalvalue_rxgain - thermalvalue);
+ RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
+ ("Readback Thermal Meter = 0x%x pre thermal meter 0x%x"
+ " eeprom_thermalmeter 0x%x delta 0x%x "
+ "delta_lck 0x%x delta_iqk 0x%x\n",
+ thermalvalue, rtlpriv->dm.thermalvalue,
+ rtlefuse->eeprom_thermalmeter, delta, delta_lck,
+ delta_iqk));
+ if ((delta_lck > rtlefuse->delta_lck) &&
+ (rtlefuse->delta_lck != 0)) {
+ rtlpriv->dm.thermalvalue_lck = thermalvalue;
+ rtl92d_phy_lc_calibrate(hw);
+ }
+ if (delta > 0 && rtlpriv->dm.txpower_track_control) {
+ rtlpriv->dm.done_txpower = true;
+ delta = (thermalvalue > rtlefuse->eeprom_thermalmeter) ?
+ (thermalvalue - rtlefuse->eeprom_thermalmeter) :
+ (rtlefuse->eeprom_thermalmeter - thermalvalue);
+ if (rtlhal->current_bandtype == BAND_ON_2_4G) {
+ offset = 4;
+ if (delta > INDEX_MAPPING_NUM - 1)
+ index = index_mapping[offset]
+ [INDEX_MAPPING_NUM - 1];
+ else
+ index = index_mapping[offset][delta];
+ if (thermalvalue > rtlpriv->dm.thermalvalue) {
+ for (i = 0; i < rf; i++)
+ ofdm_index[i] -= delta;
+ cck_index -= delta;
+ } else {
+ for (i = 0; i < rf; i++)
+ ofdm_index[i] += index;
+ cck_index += index;
+ }
+ } else if (rtlhal->current_bandtype == BAND_ON_5G) {
+ rtl92d_bandtype_5G(rtlhal, ofdm_index,
+ &internal_pa, thermalvalue,
+ delta, rf, rtlefuse, rtlpriv,
+ rtlphy, index_mapping,
+ index_mapping_internal_pa);
+ }
+ if (is2t) {
+ RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
+ ("temp OFDM_A_index=0x%x, OFDM_B_index"
+ " = 0x%x,cck_index=0x%x\n",
+ rtlpriv->dm.ofdm_index[0],
+ rtlpriv->dm.ofdm_index[1],
+ rtlpriv->dm.cck_index));
+ } else {
+ RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
+ ("temp OFDM_A_index=0x%x,cck_index = "
+ "0x%x\n",
+ rtlpriv->dm.ofdm_index[0],
+ rtlpriv->dm.cck_index));
+ }
+ for (i = 0; i < rf; i++) {
+ if (ofdm_index[i] > OFDM_TABLE_SIZE_92D - 1)
+ ofdm_index[i] = OFDM_TABLE_SIZE_92D - 1;
+ else if (ofdm_index[i] < ofdm_min_index)
+ ofdm_index[i] = ofdm_min_index;
+ }
+ if (rtlhal->current_bandtype == BAND_ON_2_4G) {
+ if (cck_index > CCK_TABLE_SIZE - 1) {
+ cck_index = CCK_TABLE_SIZE - 1;
+ } else if (internal_pa ||
+ rtlhal->current_bandtype ==
+ BAND_ON_2_4G) {
+ if (ofdm_index[i] <
+ ofdm_min_index_internal_pa)
+ ofdm_index[i] =
+ ofdm_min_index_internal_pa;
+ } else if (cck_index < 0) {
+ cck_index = 0;
+ }
+ }
+ if (is2t) {
+ RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
+ ("new OFDM_A_index=0x%x, OFDM_B_index "
+ "= 0x%x, cck_index=0x%x\n",
+ ofdm_index[0], ofdm_index[1],
+ cck_index));
+ } else {
+ RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
+ ("new OFDM_A_index=0x%x,cck_index = "
+ "0x%x\n",
+ ofdm_index[0], cck_index));
+ }
+ ele_d = (ofdmswing_table[(u8) ofdm_index[0]] &
+ 0xFFC00000) >> 22;
+ val_x = rtlphy->iqk_matrix_regsetting
+ [indexforchannel].value[0][0];
+ val_y = rtlphy->iqk_matrix_regsetting
+ [indexforchannel].value[0][1];
+ if (val_x != 0) {
+ if ((val_x & 0x00000200) != 0)
+ val_x = val_x | 0xFFFFFC00;
+ ele_a =
+ ((val_x * ele_d) >> 8) & 0x000003FF;
+
+ /* new element C = element D x Y */
+ if ((val_y & 0x00000200) != 0)
+ val_y = val_y | 0xFFFFFC00;
+ ele_c = ((val_y * ele_d) >> 8) & 0x000003FF;
+
+ /* wirte new elements A, C, D to regC80 and
+ * regC94, element B is always 0 */
+ value32 = (ele_d << 22) | ((ele_c & 0x3F) <<
+ 16) | ele_a;
+ rtl_set_bbreg(hw, ROFDM0_XATxIQIMBALANCE,
+ BMASKDWORD, value32);
+
+ value32 = (ele_c & 0x000003C0) >> 6;
+ rtl_set_bbreg(hw, ROFDM0_XCTxAFE, BMASKH4BITS,
+ value32);
+
+ value32 = ((val_x * ele_d) >> 7) & 0x01;
+ rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(24),
+ value32);
+
+ } else {
+ rtl_set_bbreg(hw, ROFDM0_XATxIQIMBALANCE,
+ BMASKDWORD,
+ ofdmswing_table
+ [(u8)ofdm_index[0]]);
+ rtl_set_bbreg(hw, ROFDM0_XCTxAFE, BMASKH4BITS,
+ 0x00);
+ rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD,
+ BIT(24), 0x00);
+ }
+
+ RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
+ ("TxPwrTracking for interface %d path A: X ="
+ " 0x%lx, Y = 0x%lx ele_A = 0x%lx ele_C = "
+ "0x%lx ele_D = 0x%lx 0xe94 = 0x%lx 0xe9c = "
+ "0x%lx\n", rtlhal->interfaceindex,
+ val_x, val_y, ele_a, ele_c, ele_d,
+ val_x, val_y));
+
+ if (rtlhal->current_bandtype == BAND_ON_2_4G) {
+ /* Adjust CCK according to IQK result */
+ if (!rtlpriv->dm.cck_inch14) {
+ rtl_write_byte(rtlpriv, 0xa22,
+ cckswing_table_ch1ch13
+ [(u8)cck_index][0]);
+ rtl_write_byte(rtlpriv, 0xa23,
+ cckswing_table_ch1ch13
+ [(u8)cck_index][1]);
+ rtl_write_byte(rtlpriv, 0xa24,
+ cckswing_table_ch1ch13
+ [(u8)cck_index][2]);
+ rtl_write_byte(rtlpriv, 0xa25,
+ cckswing_table_ch1ch13
+ [(u8)cck_index][3]);
+ rtl_write_byte(rtlpriv, 0xa26,
+ cckswing_table_ch1ch13
+ [(u8)cck_index][4]);
+ rtl_write_byte(rtlpriv, 0xa27,
+ cckswing_table_ch1ch13
+ [(u8)cck_index][5]);
+ rtl_write_byte(rtlpriv, 0xa28,
+ cckswing_table_ch1ch13
+ [(u8)cck_index][6]);
+ rtl_write_byte(rtlpriv, 0xa29,
+ cckswing_table_ch1ch13
+ [(u8)cck_index][7]);
+ } else {
+ rtl_write_byte(rtlpriv, 0xa22,
+ cckswing_table_ch14
+ [(u8)cck_index][0]);
+ rtl_write_byte(rtlpriv, 0xa23,
+ cckswing_table_ch14
+ [(u8)cck_index][1]);
+ rtl_write_byte(rtlpriv, 0xa24,
+ cckswing_table_ch14
+ [(u8)cck_index][2]);
+ rtl_write_byte(rtlpriv, 0xa25,
+ cckswing_table_ch14
+ [(u8)cck_index][3]);
+ rtl_write_byte(rtlpriv, 0xa26,
+ cckswing_table_ch14
+ [(u8)cck_index][4]);
+ rtl_write_byte(rtlpriv, 0xa27,
+ cckswing_table_ch14
+ [(u8)cck_index][5]);
+ rtl_write_byte(rtlpriv, 0xa28,
+ cckswing_table_ch14
+ [(u8)cck_index][6]);
+ rtl_write_byte(rtlpriv, 0xa29,
+ cckswing_table_ch14
+ [(u8)cck_index][7]);
+ }
+ }
+ if (is2t) {
+ ele_d = (ofdmswing_table[(u8) ofdm_index[1]] &
+ 0xFFC00000) >> 22;
+ val_x = rtlphy->iqk_matrix_regsetting
+ [indexforchannel].value[0][4];
+ val_y = rtlphy->iqk_matrix_regsetting
+ [indexforchannel].value[0][5];
+ if (val_x != 0) {
+ if ((val_x & 0x00000200) != 0)
+ /* consider minus */
+ val_x = val_x | 0xFFFFFC00;
+ ele_a = ((val_x * ele_d) >> 8) &
+ 0x000003FF;
+ /* new element C = element D x Y */
+ if ((val_y & 0x00000200) != 0)
+ val_y =
+ val_y | 0xFFFFFC00;
+ ele_c =
+ ((val_y *
+ ele_d) >> 8) & 0x00003FF;
+ /* write new elements A, C, D to regC88
+ * and regC9C, element B is always 0
+ */
+ value32 = (ele_d << 22) |
+ ((ele_c & 0x3F) << 16) |
+ ele_a;
+ rtl_set_bbreg(hw,
+ ROFDM0_XBTxIQIMBALANCE,
+ BMASKDWORD, value32);
+ value32 = (ele_c & 0x000003C0) >> 6;
+ rtl_set_bbreg(hw, ROFDM0_XDTxAFE,
+ BMASKH4BITS, value32);
+ value32 = ((val_x * ele_d) >> 7) & 0x01;
+ rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD,
+ BIT(28), value32);
+ } else {
+ rtl_set_bbreg(hw,
+ ROFDM0_XBTxIQIMBALANCE,
+ BMASKDWORD,
+ ofdmswing_table
+ [(u8) ofdm_index[1]]);
+ rtl_set_bbreg(hw, ROFDM0_XDTxAFE,
+ BMASKH4BITS, 0x00);
+ rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD,
+ BIT(28), 0x00);
+ }
+ RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
+ ("TxPwrTracking path B: X = 0x%lx, "
+ "Y = 0x%lx ele_A = 0x%lx ele_C = 0x"
+ "%lx ele_D = 0x%lx 0xeb4 = 0x%lx "
+ "0xebc = 0x%lx\n",
+ val_x, val_y, ele_a, ele_c,
+ ele_d, val_x, val_y));
+ }
+ RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
+ ("TxPwrTracking 0xc80 = 0x%x, 0xc94 = "
+ "0x%x RF 0x24 = 0x%x\n",
+ rtl_get_bbreg(hw, 0xc80, BMASKDWORD),
+ rtl_get_bbreg(hw, 0xc94, BMASKDWORD),
+ rtl_get_rfreg(hw, RF90_PATH_A, 0x24,
+ BRFREGOFFSETMASK)));
+ }
+ if ((delta_iqk > rtlefuse->delta_iqk) &&
+ (rtlefuse->delta_iqk != 0)) {
+ rtl92d_phy_reset_iqk_result(hw);
+ rtlpriv->dm.thermalvalue_iqk = thermalvalue;
+ rtl92d_phy_iq_calibrate(hw);
+ }
+ if (delta_rxgain > 0 && rtlhal->current_bandtype == BAND_ON_5G
+ && thermalvalue <= rtlefuse->eeprom_thermalmeter) {
+ rtlpriv->dm.thermalvalue_rxgain = thermalvalue;
+ rtl92d_dm_rxgain_tracking_thermalmeter(hw);
+ }
+ if (rtlpriv->dm.txpower_track_control)
+ rtlpriv->dm.thermalvalue = thermalvalue;
+ }
+
+ RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, ("<===\n"));
+}
+
+static void rtl92d_dm_initialize_txpower_tracking(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+ rtlpriv->dm.txpower_tracking = true;
+ rtlpriv->dm.txpower_trackinginit = false;
+ rtlpriv->dm.txpower_track_control = true;
+ RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
+ ("pMgntInfo->txpower_tracking = %d\n",
+ rtlpriv->dm.txpower_tracking));
+}
+
+void rtl92d_dm_check_txpower_tracking_thermal_meter(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ static u8 tm_trigger;
+
+ if (!rtlpriv->dm.txpower_tracking)
+ return;
+
+ if (!tm_trigger) {
+ rtl_set_rfreg(hw, RF90_PATH_A, RF_T_METER, BIT(17) |
+ BIT(16), 0x03);
+ RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
+ ("Trigger 92S Thermal Meter!!\n"));
+ tm_trigger = 1;
+ return;
+ } else {
+ RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
+ ("Schedule TxPowerTracking direct call!!\n"));
+ rtl92d_dm_txpower_tracking_callback_thermalmeter(hw);
+ tm_trigger = 0;
+ }
+}
+
+void rtl92d_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rate_adaptive *ra = &(rtlpriv->ra);
+
+ ra->ratr_state = DM_RATR_STA_INIT;
+ ra->pre_ratr_state = DM_RATR_STA_INIT;
+ if (rtlpriv->dm.dm_type == DM_TYPE_BYDRIVER)
+ rtlpriv->dm.useramask = true;
+ else
+ rtlpriv->dm.useramask = false;
+}
+
+void rtl92d_dm_init(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+ rtlpriv->dm.dm_type = DM_TYPE_BYDRIVER;
+ rtl92d_dm_diginit(hw);
+ rtl92d_dm_init_dynamic_txpower(hw);
+ rtl92d_dm_init_edca_turbo(hw);
+ rtl92d_dm_init_rate_adaptive_mask(hw);
+ rtl92d_dm_initialize_txpower_tracking(hw);
+}
+
+void rtl92d_dm_watchdog(struct ieee80211_hw *hw)
+{
+ struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+ bool fw_current_inpsmode = false;
+ bool fwps_awake = true;
+
+ /* 1. RF is OFF. (No need to do DM.)
+ * 2. Fw is under power saving mode for FwLPS.
+ * (Prevent from SW/FW I/O racing.)
+ * 3. IPS workitem is scheduled. (Prevent from IPS sequence
+ * to be swapped with DM.
+ * 4. RFChangeInProgress is TRUE.
+ * (Prevent from broken by IPS/HW/SW Rf off.) */
+
+ if ((ppsc->rfpwr_state == ERFON) && ((!fw_current_inpsmode) &&
+ fwps_awake) && (!ppsc->rfchange_inprogress)) {
+ rtl92d_dm_pwdb_monitor(hw);
+ rtl92d_dm_false_alarm_counter_statistics(hw);
+ rtl92d_dm_find_minimum_rssi(hw);
+ rtl92d_dm_dig(hw);
+ /* rtl92d_dm_dynamic_bb_powersaving(hw); */
+ rtl92d_dm_dynamic_txpower(hw);
+ /* rtl92d_dm_check_txpower_tracking_thermal_meter(hw); */
+ /* rtl92d_dm_refresh_rate_adaptive_mask(hw); */
+ /* rtl92d_dm_interrupt_migration(hw); */
+ rtl92d_dm_check_edca_turbo(hw);
+ }
+}
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/dm.h b/drivers/net/wireless/rtlwifi/rtl8192de/dm.h
new file mode 100644
index 0000000..6935465
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8192de/dm.h
@@ -0,0 +1,212 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010 Realtek Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License 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, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#ifndef __RTL92C_DM_H__
+#define __RTL92C_DM_H__
+
+#define HAL_DM_DIG_DISABLE BIT(0)
+#define HAL_DM_HIPWR_DISABLE BIT(1)
+
+#define OFDM_TABLE_LENGTH 37
+#define OFDM_TABLE_SIZE_92D 43
+#define CCK_TABLE_LENGTH 33
+
+#define CCK_TABLE_SIZE 33
+
+#define BW_AUTO_SWITCH_HIGH_LOW 25
+#define BW_AUTO_SWITCH_LOW_HIGH 30
+
+#define DM_DIG_THRESH_HIGH 40
+#define DM_DIG_THRESH_LOW 35
+
+#define DM_FALSEALARM_THRESH_LOW 400
+#define DM_FALSEALARM_THRESH_HIGH 1000
+
+#define DM_DIG_MAX 0x3e
+#define DM_DIG_MIN 0x1c
+
+#define DM_DIG_FA_UPPER 0x32
+#define DM_DIG_FA_LOWER 0x20
+#define DM_DIG_FA_TH0 0x100
+#define DM_DIG_FA_TH1 0x400
+#define DM_DIG_FA_TH2 0x600
+
+#define DM_DIG_BACKOFF_MAX 12
+#define DM_DIG_BACKOFF_MIN -4
+#define DM_DIG_BACKOFF_DEFAULT 10
+
+#define RXPATHSELECTION_SS_TH_lOW 30
+#define RXPATHSELECTION_DIFF_TH 18
+
+#define DM_RATR_STA_INIT 0
+#define DM_RATR_STA_HIGH 1
+#define DM_RATR_STA_MIDDLE 2
+#define DM_RATR_STA_LOW 3
+
+#define CTS2SELF_THVAL 30
+#define REGC38_TH 20
+
+#define WAIOTTHVAL 25
+
+#define TXHIGHPWRLEVEL_NORMAL 0
+#define TXHIGHPWRLEVEL_LEVEL1 1
+#define TXHIGHPWRLEVEL_LEVEL2 2
+#define TXHIGHPWRLEVEL_BT1 3
+#define TXHIGHPWRLEVEL_BT2 4
+
+#define DM_TYPE_BYFW 0
+#define DM_TYPE_BYDRIVER 1
+
+#define TX_POWER_NEAR_FIELD_THRESH_LVL2 74
+#define TX_POWER_NEAR_FIELD_THRESH_LVL1 67
+#define INDEX_MAPPING_NUM 13
+
+struct ps_t {
+ u8 pre_ccastate;
+ u8 cur_ccasate;
+
+ u8 pre_rfstate;
+ u8 cur_rfstate;
+
+ long rssi_val_min;
+};
+
+struct dig_t {
+ u8 dig_enable_flag;
+ u8 dig_ext_port_stage;
+
+ u32 rssi_lowthresh;
+ u32 rssi_highthresh;
+
+ u32 fa_lowthresh;
+ u32 fa_highthresh;
+
+ u8 cursta_connectctate;
+ u8 presta_connectstate;
+ u8 curmultista_connectstate;
+
+ u8 pre_igvalue;
+ u8 cur_igvalue;
+
+ char backoff_val;
+ char backoff_val_range_max;
+ char backoff_val_range_min;
+ u8 rx_gain_range_max;
+ u8 rx_gain_range_min;
+ u8 min_undecorated_pwdb_for_dm;
+ long last_min_undecorated_pwdb_for_dm;
+
+ u8 pre_cck_pd_state;
+ u8 cur_cck_pd_state;
+
+ u8 pre_cck_fa_state;
+ u8 cur_cck_fa_state;
+
+ u8 pre_ccastate;
+ u8 cur_ccasate;
+
+ u8 large_fa_hit;
+ u8 forbidden_igi;
+ u32 recover_cnt;
+};
+
+struct swat {
+ u8 failure_cnt;
+ u8 try_flag;
+ u8 stop_trying;
+ long pre_rssi;
+ long trying_threshold;
+ u8 cur_antenna;
+ u8 pre_antenna;
+};
+
+enum tag_dynamic_init_gain_operation_type_definition {
+ DIG_TYPE_THRESH_HIGH = 0,
+ DIG_TYPE_THRESH_LOW = 1,
+ DIG_TYPE_BACKOFF = 2,
+ DIG_TYPE_RX_GAIN_MIN = 3,
+ DIG_TYPE_RX_GAIN_MAX = 4,
+ DIG_TYPE_ENABLE = 5,
+ DIG_TYPE_DISABLE = 6,
+ DIG_OP_TYPE_MAX
+};
+
+enum tag_cck_packet_detection_threshold_type_definition {
+ CCK_PD_STAGE_LOWRSSI = 0,
+ CCK_PD_STAGE_HIGHRSSI = 1,
+ CCK_FA_STAGE_LOW = 2,
+ CCK_FA_STAGE_HIGH = 3,
+ CCK_PD_STAGE_MAX = 4,
+};
+
+enum dm_1r_cca {
+ CCA_1R = 0,
+ CCA_2R = 1,
+ CCA_MAX = 2,
+};
+
+enum dm_rf {
+ RF_SAVE = 0,
+ RF_NORMAL = 1,
+ RF_MAX = 2,
+};
+
+enum dm_sw_ant_switch {
+ ANS_ANTENNA_B = 1,
+ ANS_ANTENNA_A = 2,
+ ANS_ANTENNA_MAX = 3,
+};
+
+enum dm_dig_ext_port_alg {
+ DIG_EXT_PORT_STAGE_0 = 0,
+ DIG_EXT_PORT_STAGE_1 = 1,
+ DIG_EXT_PORT_STAGE_2 = 2,
+ DIG_EXT_PORT_STAGE_3 = 3,
+ DIG_EXT_PORT_STAGE_MAX = 4,
+};
+
+enum dm_dig_connect {
+ DIG_STA_DISCONNECT = 0,
+ DIG_STA_CONNECT = 1,
+ DIG_STA_BEFORE_CONNECT = 2,
+ DIG_MULTISTA_DISCONNECT = 3,
+ DIG_MULTISTA_CONNECT = 4,
+ DIG_CONNECT_MAX
+};
+
+extern struct dig_t de_digtable;
+
+void rtl92d_dm_init(struct ieee80211_hw *hw);
+void rtl92d_dm_watchdog(struct ieee80211_hw *hw);
+void rtl92d_dm_init_edca_turbo(struct ieee80211_hw *hw);
+void rtl92d_dm_write_dig(struct ieee80211_hw *hw);
+void rtl92d_dm_check_txpower_tracking_thermal_meter(struct ieee80211_hw *hw);
+void rtl92d_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw);
+
+#endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/fw.c b/drivers/net/wireless/rtlwifi/rtl8192de/fw.c
new file mode 100644
index 0000000..82f060b
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8192de/fw.c
@@ -0,0 +1,790 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010 Realtek Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License 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, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#include "../wifi.h"
+#include "../pci.h"
+#include "../base.h"
+#include "reg.h"
+#include "def.h"
+#include "fw.h"
+#include "sw.h"
+
+static bool _rtl92d_is_fw_downloaded(struct rtl_priv *rtlpriv)
+{
+ return (rtl_read_dword(rtlpriv, REG_MCUFWDL) & MCUFWDL_RDY) ?
+ true : false;
+}
+
+static void _rtl92d_enable_fw_download(struct ieee80211_hw *hw, bool enable)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u8 tmp;
+
+ if (enable) {
+ tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
+ rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, tmp | 0x04);
+ tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL);
+ rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp | 0x01);
+ tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL + 2);
+ rtl_write_byte(rtlpriv, REG_MCUFWDL + 2, tmp & 0xf7);
+ } else {
+ tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL);
+ rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp & 0xfe);
+ /* Reserved for fw extension.
+ * 0x81[7] is used for mac0 status ,
+ * so don't write this reg here
+ * rtl_write_byte(rtlpriv, REG_MCUFWDL + 1, 0x00);*/
+ }
+}
+
+static void _rtl92d_fw_block_write(struct ieee80211_hw *hw,
+ const u8 *buffer, u32 size)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u32 blocksize = sizeof(u32);
+ u8 *bufferptr = (u8 *) buffer;
+ u32 *pu4BytePtr = (u32 *) buffer;
+ u32 i, offset, blockCount, remainSize;
+
+ blockCount = size / blocksize;
+ remainSize = size % blocksize;
+ for (i = 0; i < blockCount; i++) {
+ offset = i * blocksize;
+ rtl_write_dword(rtlpriv, (FW_8192D_START_ADDRESS + offset),
+ *(pu4BytePtr + i));
+ }
+ if (remainSize) {
+ offset = blockCount * blocksize;
+ bufferptr += offset;
+ for (i = 0; i < remainSize; i++) {
+ rtl_write_byte(rtlpriv, (FW_8192D_START_ADDRESS +
+ offset + i), *(bufferptr + i));
+ }
+ }
+}
+
+static void _rtl92d_fw_page_write(struct ieee80211_hw *hw,
+ u32 page, const u8 *buffer, u32 size)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u8 value8;
+ u8 u8page = (u8) (page & 0x07);
+
+ value8 = (rtl_read_byte(rtlpriv, REG_MCUFWDL + 2) & 0xF8) | u8page;
+ rtl_write_byte(rtlpriv, (REG_MCUFWDL + 2), value8);
+ _rtl92d_fw_block_write(hw, buffer, size);
+}
+
+static void _rtl92d_fill_dummy(u8 *pfwbuf, u32 *pfwlen)
+{
+ u32 fwlen = *pfwlen;
+ u8 remain = (u8) (fwlen % 4);
+
+ remain = (remain == 0) ? 0 : (4 - remain);
+ while (remain > 0) {
+ pfwbuf[fwlen] = 0;
+ fwlen++;
+ remain--;
+ }
+ *pfwlen = fwlen;
+}
+
+static void _rtl92d_write_fw(struct ieee80211_hw *hw,
+ enum version_8192d version, u8 *buffer, u32 size)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+ u8 *bufferPtr = (u8 *) buffer;
+ u32 pagenums, remainSize;
+ u32 page, offset;
+
+ RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, ("FW size is %d bytes,\n", size));
+ if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192DE)
+ _rtl92d_fill_dummy(bufferPtr, &size);
+ pagenums = size / FW_8192D_PAGE_SIZE;
+ remainSize = size % FW_8192D_PAGE_SIZE;
+ if (pagenums > 8) {
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+ ("Page numbers should not greater then 8\n"));
+ }
+ for (page = 0; page < pagenums; page++) {
+ offset = page * FW_8192D_PAGE_SIZE;
+ _rtl92d_fw_page_write(hw, page, (bufferPtr + offset),
+ FW_8192D_PAGE_SIZE);
+ }
+ if (remainSize) {
+ offset = pagenums * FW_8192D_PAGE_SIZE;
+ page = pagenums;
+ _rtl92d_fw_page_write(hw, page, (bufferPtr + offset),
+ remainSize);
+ }
+}
+
+static int _rtl92d_fw_free_to_go(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u32 counter = 0;
+ u32 value32;
+
+ do {
+ value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
+ } while ((counter++ < FW_8192D_POLLING_TIMEOUT_COUNT) &&
+ (!(value32 & FWDL_ChkSum_rpt)));
+ if (counter >= FW_8192D_POLLING_TIMEOUT_COUNT) {
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+ ("chksum report faill ! REG_MCUFWDL:0x%08x .\n",
+ value32));
+ return -EIO;
+ }
+ RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
+ ("Checksum report OK ! REG_MCUFWDL:0x%08x .\n", value32));
+ value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
+ value32 |= MCUFWDL_RDY;
+ rtl_write_dword(rtlpriv, REG_MCUFWDL, value32);
+ return 0;
+}
+
+void rtl92d_firmware_selfreset(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u8 u1b_tmp;
+ u8 delay = 100;
+
+ /* Set (REG_HMETFR + 3) to 0x20 is reset 8051 */
+ rtl_write_byte(rtlpriv, REG_HMETFR + 3, 0x20);
+ u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
+ while (u1b_tmp & BIT(2)) {
+ delay--;
+ if (delay == 0)
+ break;
+ udelay(50);
+ u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
+ }
+ RT_ASSERT((delay > 0), ("8051 reset failed!\n"));
+ RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
+ ("=====> 8051 reset success (%d) .\n", delay));
+}
+
+static int _rtl92d_fw_init(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+ u32 counter;
+
+ RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG, ("FW already have download\n"));
+ /* polling for FW ready */
+ counter = 0;
+ do {
+ if (rtlhal->interfaceindex == 0) {
+ if (rtl_read_byte(rtlpriv, FW_MAC0_READY) &
+ MAC0_READY) {
+ RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
+ ("Polling FW ready success!! "
+ "REG_MCUFWDL: 0x%x .\n",
+ rtl_read_byte(rtlpriv,
+ FW_MAC0_READY)));
+ return 0;
+ }
+ udelay(5);
+ } else {
+ if (rtl_read_byte(rtlpriv, FW_MAC1_READY) &
+ MAC1_READY) {
+ RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
+ ("Polling FW ready success!! "
+ "REG_MCUFWDL: 0x%x .\n",
+ rtl_read_byte(rtlpriv,
+ FW_MAC1_READY)));
+ return 0;
+ }
+ udelay(5);
+ }
+ } while (counter++ < POLLING_READY_TIMEOUT_COUNT);
+
+ if (rtlhal->interfaceindex == 0) {
+ RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
+ ("Polling FW ready fail!! MAC0 FW init not ready: "
+ "0x%x .\n",
+ rtl_read_byte(rtlpriv, FW_MAC0_READY)));
+ } else {
+ RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
+ ("Polling FW ready fail!! MAC1 FW init not ready: "
+ "0x%x .\n",
+ rtl_read_byte(rtlpriv, FW_MAC1_READY)));
+ }
+ RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
+ ("Polling FW ready fail!! REG_MCUFWDL:0x%08ul .\n",
+ rtl_read_dword(rtlpriv, REG_MCUFWDL)));
+ return -1;
+}
+
+int rtl92d_download_fw(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+ u8 *pfwheader;
+ u8 *pfwdata;
+ u32 fwsize;
+ int err;
+ enum version_8192d version = rtlhal->version;
+ u8 value;
+ u32 count;
+ bool fw_downloaded = false, fwdl_in_process = false;
+ unsigned long flags;
+
+ if (!rtlhal->pfirmware)
+ return 1;
+ fwsize = rtlhal->fwsize;
+ pfwheader = (u8 *) rtlhal->pfirmware;
+ pfwdata = (u8 *) rtlhal->pfirmware;
+ rtlhal->fw_version = (u16) GET_FIRMWARE_HDR_VERSION(pfwheader);
+ rtlhal->fw_subversion = (u16) GET_FIRMWARE_HDR_SUB_VER(pfwheader);
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, (" FirmwareVersion(%d),"
+ "FirmwareSubVersion(%d), Signature(%#x)\n",
+ rtlhal->fw_version, rtlhal->fw_subversion,
+ GET_FIRMWARE_HDR_SIGNATURE(pfwheader)));
+ if (IS_FW_HEADER_EXIST(pfwheader)) {
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+ ("Shift 32 bytes for FW header!!\n"));
+ pfwdata = pfwdata + 32;
+ fwsize = fwsize - 32;
+ }
+
+ spin_lock_irqsave(&globalmutex_for_fwdownload, flags);
+ fw_downloaded = _rtl92d_is_fw_downloaded(rtlpriv);
+ if ((rtl_read_byte(rtlpriv, 0x1f) & BIT(5)) == BIT(5))
+ fwdl_in_process = true;
+ else
+ fwdl_in_process = false;
+ if (fw_downloaded) {
+ spin_unlock_irqrestore(&globalmutex_for_fwdownload, flags);
+ goto exit;
+ } else if (fwdl_in_process) {
+ spin_unlock_irqrestore(&globalmutex_for_fwdownload, flags);
+ for (count = 0; count < 5000; count++) {
+ udelay(500);
+ spin_lock_irqsave(&globalmutex_for_fwdownload, flags);
+ fw_downloaded = _rtl92d_is_fw_downloaded(rtlpriv);
+ if ((rtl_read_byte(rtlpriv, 0x1f) & BIT(5)) == BIT(5))
+ fwdl_in_process = true;
+ else
+ fwdl_in_process = false;
+ spin_unlock_irqrestore(&globalmutex_for_fwdownload,
+ flags);
+ if (fw_downloaded)
+ goto exit;
+ else if (!fwdl_in_process)
+ break;
+ else
+ RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
+ ("Wait for another mac "
+ "download fw\n"));
+ }
+ spin_lock_irqsave(&globalmutex_for_fwdownload, flags);
+ value = rtl_read_byte(rtlpriv, 0x1f);
+ value |= BIT(5);
+ rtl_write_byte(rtlpriv, 0x1f, value);
+ spin_unlock_irqrestore(&globalmutex_for_fwdownload, flags);
+ } else {
+ value = rtl_read_byte(rtlpriv, 0x1f);
+ value |= BIT(5);
+ rtl_write_byte(rtlpriv, 0x1f, value);
+ spin_unlock_irqrestore(&globalmutex_for_fwdownload, flags);
+ }
+
+ /* If 8051 is running in RAM code, driver should
+ * inform Fw to reset by itself, or it will cause
+ * download Fw fail.*/
+ /* 8051 RAM code */
+ if (rtl_read_byte(rtlpriv, REG_MCUFWDL) & BIT(7)) {
+ rtl92d_firmware_selfreset(hw);
+ rtl_write_byte(rtlpriv, REG_MCUFWDL, 0x00);
+ }
+ _rtl92d_enable_fw_download(hw, true);
+ _rtl92d_write_fw(hw, version, pfwdata, fwsize);
+ _rtl92d_enable_fw_download(hw, false);
+ spin_lock_irqsave(&globalmutex_for_fwdownload, flags);
+ err = _rtl92d_fw_free_to_go(hw);
+ /* download fw over,clear 0x1f[5] */
+ value = rtl_read_byte(rtlpriv, 0x1f);
+ value &= (~BIT(5));
+ rtl_write_byte(rtlpriv, 0x1f, value);
+ spin_unlock_irqrestore(&globalmutex_for_fwdownload, flags);
+ if (err) {
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+ ("fw is not ready to run!\n"));
+ goto exit;
+ } else {
+ RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
+ ("fw is ready to run!\n"));
+ }
+exit:
+ err = _rtl92d_fw_init(hw);
+ return err;
+}
+
+static bool _rtl92d_check_fw_read_last_h2c(struct ieee80211_hw *hw, u8 boxnum)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u8 val_hmetfr;
+ bool result = false;
+
+ val_hmetfr = rtl_read_byte(rtlpriv, REG_HMETFR);
+ if (((val_hmetfr >> boxnum) & BIT(0)) == 0)
+ result = true;
+ return result;
+}
+
+static void _rtl92d_fill_h2c_command(struct ieee80211_hw *hw,
+ u8 element_id, u32 cmd_len, u8 *cmdbuffer)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+ struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+ u8 boxnum;
+ u16 box_reg = 0, box_extreg = 0;
+ u8 u1b_tmp;
+ bool isfw_read = false;
+ u8 buf_index = 0;
+ bool bwrite_sucess = false;
+ u8 wait_h2c_limmit = 100;
+ u8 wait_writeh2c_limmit = 100;
+ u8 boxcontent[4], boxextcontent[2];
+ u32 h2c_waitcounter = 0;
+ unsigned long flag;
+ u8 idx;
+
+ if (ppsc->rfpwr_state == ERFOFF || ppsc->inactive_pwrstate == ERFOFF) {
+ RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
+ ("Return as RF is off!!!\n"));
+ return;
+ }
+ RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, ("come in\n"));
+ while (true) {
+ spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
+ if (rtlhal->h2c_setinprogress) {
+ RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
+ ("H2C set in progress! Wait to set.."
+ "element_id(%d).\n", element_id));
+
+ while (rtlhal->h2c_setinprogress) {
+ spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock,
+ flag);
+ h2c_waitcounter++;
+ RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
+ ("Wait 100 us (%d times)...\n",
+ h2c_waitcounter));
+ udelay(100);
+
+ if (h2c_waitcounter > 1000)
+ return;
+
+ spin_lock_irqsave(&rtlpriv->locks.h2c_lock,
+ flag);
+ }
+ spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
+ } else {
+ rtlhal->h2c_setinprogress = true;
+ spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
+ break;
+ }
+ }
+ while (!bwrite_sucess) {
+ wait_writeh2c_limmit--;
+ if (wait_writeh2c_limmit == 0) {
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+ ("Write H2C fail because no trigger "
+ "for FW INT!\n"));
+ break;
+ }
+ boxnum = rtlhal->last_hmeboxnum;
+ switch (boxnum) {
+ case 0:
+ box_reg = REG_HMEBOX_0;
+ box_extreg = REG_HMEBOX_EXT_0;
+ break;
+ case 1:
+ box_reg = REG_HMEBOX_1;
+ box_extreg = REG_HMEBOX_EXT_1;
+ break;
+ case 2:
+ box_reg = REG_HMEBOX_2;
+ box_extreg = REG_HMEBOX_EXT_2;
+ break;
+ case 3:
+ box_reg = REG_HMEBOX_3;
+ box_extreg = REG_HMEBOX_EXT_3;
+ break;
+ default:
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+ ("switch case not process\n"));
+ break;
+ }
+ isfw_read = _rtl92d_check_fw_read_last_h2c(hw, boxnum);
+ while (!isfw_read) {
+ wait_h2c_limmit--;
+ if (wait_h2c_limmit == 0) {
+ RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
+ ("Wating too long for FW read "
+ "clear HMEBox(%d)!\n", boxnum));
+ break;
+ }
+ udelay(10);
+ isfw_read = _rtl92d_check_fw_read_last_h2c(hw, boxnum);
+ u1b_tmp = rtl_read_byte(rtlpriv, 0x1BF);
+ RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
+ ("Wating for FW read clear HMEBox(%d)!!! "
+ "0x1BF = %2x\n", boxnum, u1b_tmp));
+ }
+ if (!isfw_read) {
+ RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
+ ("Write H2C register BOX[%d] fail!!!!! "
+ "Fw do not read.\n", boxnum));
+ break;
+ }
+ memset(boxcontent, 0, sizeof(boxcontent));
+ memset(boxextcontent, 0, sizeof(boxextcontent));
+ boxcontent[0] = element_id;
+ RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
+ ("Write element_id box_reg(%4x) = %2x\n",
+ box_reg, element_id));
+ switch (cmd_len) {
+ case 1:
+ boxcontent[0] &= ~(BIT(7));
+ memcpy(boxcontent + 1, cmdbuffer + buf_index, 1);
+ for (idx = 0; idx < 4; idx++)
+ rtl_write_byte(rtlpriv, box_reg + idx,
+ boxcontent[idx]);
+ break;
+ case 2:
+ boxcontent[0] &= ~(BIT(7));
+ memcpy(boxcontent + 1, cmdbuffer + buf_index, 2);
+ for (idx = 0; idx < 4; idx++)
+ rtl_write_byte(rtlpriv, box_reg + idx,
+ boxcontent[idx]);
+ break;
+ case 3:
+ boxcontent[0] &= ~(BIT(7));
+ memcpy(boxcontent + 1, cmdbuffer + buf_index, 3);
+ for (idx = 0; idx < 4; idx++)
+ rtl_write_byte(rtlpriv, box_reg + idx,
+ boxcontent[idx]);
+ break;
+ case 4:
+ boxcontent[0] |= (BIT(7));
+ memcpy(boxextcontent, cmdbuffer + buf_index, 2);
+ memcpy(boxcontent + 1, cmdbuffer + buf_index + 2, 2);
+ for (idx = 0; idx < 2; idx++)
+ rtl_write_byte(rtlpriv, box_extreg + idx,
+ boxextcontent[idx]);
+ for (idx = 0; idx < 4; idx++)
+ rtl_write_byte(rtlpriv, box_reg + idx,
+ boxcontent[idx]);
+ break;
+ case 5:
+ boxcontent[0] |= (BIT(7));
+ memcpy(boxextcontent, cmdbuffer + buf_index, 2);
+ memcpy(boxcontent + 1, cmdbuffer + buf_index + 2, 3);
+ for (idx = 0; idx < 2; idx++)
+ rtl_write_byte(rtlpriv, box_extreg + idx,
+ boxextcontent[idx]);
+ for (idx = 0; idx < 4; idx++)
+ rtl_write_byte(rtlpriv, box_reg + idx,
+ boxcontent[idx]);
+ break;
+ default:
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+ ("switch case not process\n"));
+ break;
+ }
+ bwrite_sucess = true;
+ rtlhal->last_hmeboxnum = boxnum + 1;
+ if (rtlhal->last_hmeboxnum == 4)
+ rtlhal->last_hmeboxnum = 0;
+ RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
+ ("pHalData->last_hmeboxnum = %d\n",
+ rtlhal->last_hmeboxnum));
+ }
+ spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
+ rtlhal->h2c_setinprogress = false;
+ spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
+ RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, ("go out\n"));
+}
+
+void rtl92d_fill_h2c_cmd(struct ieee80211_hw *hw,
+ u8 element_id, u32 cmd_len, u8 *cmdbuffer)
+{
+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+ u32 tmp_cmdbuf[2];
+
+ if (rtlhal->fw_ready == false) {
+ RT_ASSERT(false, ("return H2C cmd because of Fw "
+ "download fail!!!\n"));
+ return;
+ }
+ memset(tmp_cmdbuf, 0, 8);
+ memcpy(tmp_cmdbuf, cmdbuffer, cmd_len);
+ _rtl92d_fill_h2c_command(hw, element_id, cmd_len, (u8 *)&tmp_cmdbuf);
+ return;
+}
+
+void rtl92d_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u8 u1_h2c_set_pwrmode[3] = { 0 };
+ struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+
+ RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, ("FW LPS mode = %d\n", mode));
+ SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, mode);
+ SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode, 1);
+ SET_H2CCMD_PWRMODE_PARM_BCN_PASS_TIME(u1_h2c_set_pwrmode,
+ ppsc->reg_max_lps_awakeintvl);
+ RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
+ "rtl92d_set_fw_rsvdpagepkt(): u1_h2c_set_pwrmode\n",
+ u1_h2c_set_pwrmode, 3);
+ rtl92d_fill_h2c_cmd(hw, H2C_SETPWRMODE, 3, u1_h2c_set_pwrmode);
+}
+
+static bool _rtl92d_cmd_send_packet(struct ieee80211_hw *hw,
+ struct sk_buff *skb)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+ struct rtl8192_tx_ring *ring;
+ struct rtl_tx_desc *pdesc;
+ u8 idx = 0;
+ unsigned long flags;
+ struct sk_buff *pskb;
+
+ ring = &rtlpci->tx_ring[BEACON_QUEUE];
+ pskb = __skb_dequeue(&ring->queue);
+ if (pskb)
+ kfree_skb(pskb);
+ spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags);
+ pdesc = &ring->desc[idx];
+ /* discard output from call below */
+ rtlpriv->cfg->ops->get_desc((u8 *) pdesc, true, HW_DESC_OWN);
+ rtlpriv->cfg->ops->fill_tx_cmddesc(hw, (u8 *) pdesc, 1, 1, skb);
+ __skb_queue_tail(&ring->queue, skb);
+ spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags);
+ rtlpriv->cfg->ops->tx_polling(hw, BEACON_QUEUE);
+ return true;
+}
+
+#define BEACON_PG 0 /*->1 */
+#define PSPOLL_PG 2
+#define NULL_PG 3
+#define PROBERSP_PG 4 /*->5 */
+#define TOTAL_RESERVED_PKT_LEN 768
+
+static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = {
+ /* page 0 beacon */
+ 0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
+ 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x50, 0x08,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
+ 0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
+ 0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
+ 0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
+ 0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
+ 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
+ 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+ /* page 1 beacon */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x10, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+ /* page 2 ps-poll */
+ 0xA4, 0x10, 0x01, 0xC0, 0x00, 0x40, 0x10, 0x10,
+ 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x18, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+ 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+ /* page 3 null */
+ 0x48, 0x01, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
+ 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
+ 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x72, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+ 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+ /* page 4 probe_resp */
+ 0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
+ 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
+ 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
+ 0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00,
+ 0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
+ 0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
+ 0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
+ 0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
+ 0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
+ 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
+ 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+ /* page 5 probe_resp */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+void rtl92d_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool dl_finished)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+ struct sk_buff *skb = NULL;
+ u32 totalpacketlen;
+ bool rtstatus;
+ u8 u1RsvdPageLoc[3] = { 0 };
+ bool dlok = false;
+ u8 *beacon;
+ u8 *p_pspoll;
+ u8 *nullfunc;
+ u8 *p_probersp;
+ /*---------------------------------------------------------
+ (1) beacon
+ ---------------------------------------------------------*/
+ beacon = &reserved_page_packet[BEACON_PG * 128];
+ SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr);
+ SET_80211_HDR_ADDRESS3(beacon, mac->bssid);
+ /*-------------------------------------------------------
+ (2) ps-poll
+ --------------------------------------------------------*/
+ p_pspoll = &reserved_page_packet[PSPOLL_PG * 128];
+ SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000));
+ SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid);
+ SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr);
+ SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1RsvdPageLoc, PSPOLL_PG);
+ /*--------------------------------------------------------
+ (3) null data
+ ---------------------------------------------------------*/
+ nullfunc = &reserved_page_packet[NULL_PG * 128];
+ SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid);
+ SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr);
+ SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid);
+ SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1RsvdPageLoc, NULL_PG);
+ /*---------------------------------------------------------
+ (4) probe response
+ ----------------------------------------------------------*/
+ p_probersp = &reserved_page_packet[PROBERSP_PG * 128];
+ SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid);
+ SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr);
+ SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid);
+ SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1RsvdPageLoc, PROBERSP_PG);
+ totalpacketlen = TOTAL_RESERVED_PKT_LEN;
+ RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD,
+ "rtl92d_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
+ &reserved_page_packet[0], totalpacketlen);
+ RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
+ "rtl92d_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
+ u1RsvdPageLoc, 3);
+ skb = dev_alloc_skb(totalpacketlen);
+ memcpy((u8 *) skb_put(skb, totalpacketlen), &reserved_page_packet,
+ totalpacketlen);
+ rtstatus = _rtl92d_cmd_send_packet(hw, skb);
+
+ if (rtstatus)
+ dlok = true;
+ if (dlok) {
+ RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
+ ("Set RSVD page location to Fw.\n"));
+ RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
+ "H2C_RSVDPAGE:\n", u1RsvdPageLoc, 3);
+ rtl92d_fill_h2c_cmd(hw, H2C_RSVDPAGE,
+ sizeof(u1RsvdPageLoc), u1RsvdPageLoc);
+ } else
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
+ ("Set RSVD page location to Fw FAIL!!!!!!.\n"));
+}
+
+void rtl92d_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus)
+{
+ u8 u1_joinbssrpt_parm[1] = {0};
+
+ SET_H2CCMD_JOINBSSRPT_PARM_OPMODE(u1_joinbssrpt_parm, mstatus);
+ rtl92d_fill_h2c_cmd(hw, H2C_JOINBSSRPT, 1, u1_joinbssrpt_parm);
+}
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/fw.h b/drivers/net/wireless/rtlwifi/rtl8192de/fw.h
new file mode 100644
index 0000000..0c4d489
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8192de/fw.h
@@ -0,0 +1,155 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010 Realtek Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License 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, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#ifndef __RTL92D__FW__H__
+#define __RTL92D__FW__H__
+
+#define FW_8192D_START_ADDRESS 0x1000
+#define FW_8192D_PAGE_SIZE 4096
+#define FW_8192D_POLLING_TIMEOUT_COUNT 1000
+
+#define IS_FW_HEADER_EXIST(_pfwhdr) \
+ ((GET_FIRMWARE_HDR_SIGNATURE(_pfwhdr) & 0xFFF0) == 0x92C0 || \
+ (GET_FIRMWARE_HDR_SIGNATURE(_pfwhdr) & 0xFFF0) == 0x88C0 || \
+ (GET_FIRMWARE_HDR_SIGNATURE(_pfwhdr) & 0xFFFF) == 0x92D0 || \
+ (GET_FIRMWARE_HDR_SIGNATURE(_pfwhdr) & 0xFFFF) == 0x92D1 || \
+ (GET_FIRMWARE_HDR_SIGNATURE(_pfwhdr) & 0xFFFF) == 0x92D2 || \
+ (GET_FIRMWARE_HDR_SIGNATURE(_pfwhdr) & 0xFFFF) == 0x92D3)
+
+/* Define a macro that takes an le32 word, converts it to host ordering,
+ * right shifts by a specified count, creates a mask of the specified
+ * bit count, and extracts that number of bits.
+ */
+
+#define SHIFT_AND_MASK_LE(__pdesc, __shift, __mask) \
+ ((le32_to_cpu(*(((__le32 *)(__pdesc)))) >> (__shift)) & \
+ BIT_LEN_MASK_32(__mask))
+
+/* Firmware Header(8-byte alinment required) */
+/* --- LONG WORD 0 ---- */
+#define GET_FIRMWARE_HDR_SIGNATURE(__fwhdr) \
+ SHIFT_AND_MASK_LE(__fwhdr, 0, 16)
+#define GET_FIRMWARE_HDR_CATEGORY(__fwhdr) \
+ SHIFT_AND_MASK_LE(__fwhdr, 16, 8)
+#define GET_FIRMWARE_HDR_FUNCTION(__fwhdr) \
+ SHIFT_AND_MASK_LE(__fwhdr, 24, 8)
+#define GET_FIRMWARE_HDR_VERSION(__fwhdr) \
+ SHIFT_AND_MASK_LE(__fwhdr + 4, 0, 16)
+#define GET_FIRMWARE_HDR_SUB_VER(__fwhdr) \
+ SHIFT_AND_MASK_LE(__fwhdr + 4, 16, 8)
+#define GET_FIRMWARE_HDR_RSVD1(__fwhdr) \
+ SHIFT_AND_MASK_LE(__fwhdr + 4, 24, 8)
+
+/* --- LONG WORD 1 ---- */
+#define GET_FIRMWARE_HDR_MONTH(__fwhdr) \
+ SHIFT_AND_MASK_LE(__fwhdr + 8, 0, 8)
+#define GET_FIRMWARE_HDR_DATE(__fwhdr) \
+ SHIFT_AND_MASK_LE(__fwhdr + 8, 8, 8)
+#define GET_FIRMWARE_HDR_HOUR(__fwhdr) \
+ SHIFT_AND_MASK_LE(__fwhdr + 8, 16, 8)
+#define GET_FIRMWARE_HDR_MINUTE(__fwhdr) \
+ SHIFT_AND_MASK_LE(__fwhdr + 8, 24, 8)
+#define GET_FIRMWARE_HDR_ROMCODE_SIZE(__fwhdr) \
+ SHIFT_AND_MASK_LE(__fwhdr + 12, 0, 16)
+#define GET_FIRMWARE_HDR_RSVD2(__fwhdr) \
+ SHIFT_AND_MASK_LE(__fwhdr + 12, 16, 16)
+
+/* --- LONG WORD 2 ---- */
+#define GET_FIRMWARE_HDR_SVN_IDX(__fwhdr) \
+ SHIFT_AND_MASK_LE(__fwhdr + 16, 0, 32)
+#define GET_FIRMWARE_HDR_RSVD3(__fwhdr) \
+ SHIFT_AND_MASK_LE(__fwhdr + 20, 0, 32)
+
+/* --- LONG WORD 3 ---- */
+#define GET_FIRMWARE_HDR_RSVD4(__fwhdr) \
+ SHIFT_AND_MASK_LE(__fwhdr + 24, 0, 32)
+#define GET_FIRMWARE_HDR_RSVD5(__fwhdr) \
+ SHIFT_AND_MASK_LE(__fwhdr + 28, 0, 32)
+
+#define pagenum_128(_len) \
+ (u32)(((_len) >> 7) + ((_len) & 0x7F ? 1 : 0))
+
+#define SET_H2CCMD_PWRMODE_PARM_MODE(__ph2ccmd, __val) \
+ SET_BITS_TO_LE_1BYTE(__ph2ccmd, 0, 8, __val)
+#define SET_H2CCMD_PWRMODE_PARM_SMART_PS(__ph2ccmd, __val) \
+ SET_BITS_TO_LE_1BYTE((__ph2ccmd) + 1, 0, 8, __val)
+#define SET_H2CCMD_PWRMODE_PARM_BCN_PASS_TIME(__ph2ccmd, __val) \
+ SET_BITS_TO_LE_1BYTE((__ph2ccmd) + 2, 0, 8, __val)
+#define SET_H2CCMD_JOINBSSRPT_PARM_OPMODE(__ph2ccmd, __val) \
+ SET_BITS_TO_LE_1BYTE(__ph2ccmd, 0, 8, __val)
+#define SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(__ph2ccmd, __val) \
+ SET_BITS_TO_LE_1BYTE(__ph2ccmd, 0, 8, __val)
+#define SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(__ph2ccmd, __val) \
+ SET_BITS_TO_LE_1BYTE((__ph2ccmd) + 1, 0, 8, __val)
+#define SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(__ph2ccmd, __val) \
+ SET_BITS_TO_LE_1BYTE((__ph2ccmd) + 2, 0, 8, __val)
+
+struct rtl92d_firmware_header {
+ u16 signature;
+ u8 category;
+ u8 function;
+ u16 version;
+ u8 subversion;
+ u8 rsvd1;
+
+ u8 month;
+ u8 date;
+ u8 hour;
+ u8 minute;
+ u16 ramcodeSize;
+ u16 rsvd2;
+
+ u32 svnindex;
+ u32 rsvd3;
+
+ u32 rsvd4;
+ u32 rsvd5;
+};
+
+enum rtl8192d_h2c_cmd {
+ H2C_AP_OFFLOAD = 0,
+ H2C_SETPWRMODE = 1,
+ H2C_JOINBSSRPT = 2,
+ H2C_RSVDPAGE = 3,
+ H2C_RSSI_REPORT = 5,
+ H2C_RA_MASK = 6,
+ H2C_MAC_MODE_SEL = 9,
+ H2C_PWRM = 15,
+ MAX_H2CCMD
+};
+
+int rtl92d_download_fw(struct ieee80211_hw *hw);
+void rtl92d_fill_h2c_cmd(struct ieee80211_hw *hw, u8 element_id,
+ u32 cmd_len, u8 *p_cmdbuffer);
+void rtl92d_firmware_selfreset(struct ieee80211_hw *hw);
+void rtl92d_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode);
+void rtl92d_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished);
+void rtl92d_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus);
+
+#endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/hw.c b/drivers/net/wireless/rtlwifi/rtl8192de/hw.c
new file mode 100644
index 0000000..e833bbf
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8192de/hw.c
@@ -0,0 +1,2326 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010 Realtek Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License 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, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#include "../wifi.h"
+#include "../efuse.h"
+#include "../base.h"
+#include "../regd.h"
+#include "../cam.h"
+#include "../ps.h"
+#include "../pci.h"
+#include "reg.h"
+#include "def.h"
+#include "phy.h"
+#include "dm.h"
+#include "fw.h"
+#include "led.h"
+#include "sw.h"
+#include "hw.h"
+
+u32 rtl92de_read_dword_dbi(struct ieee80211_hw *hw, u16 offset, u8 direct)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u32 value;
+
+ rtl_write_word(rtlpriv, REG_DBI_CTRL, (offset & 0xFFC));
+ rtl_write_byte(rtlpriv, REG_DBI_FLAG, BIT(1) | direct);
+ udelay(10);
+ value = rtl_read_dword(rtlpriv, REG_DBI_RDATA);
+ return value;
+}
+
+void rtl92de_write_dword_dbi(struct ieee80211_hw *hw,
+ u16 offset, u32 value, u8 direct)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+ rtl_write_word(rtlpriv, REG_DBI_CTRL, ((offset & 0xFFC) | 0xF000));
+ rtl_write_dword(rtlpriv, REG_DBI_WDATA, value);
+ rtl_write_byte(rtlpriv, REG_DBI_FLAG, BIT(0) | direct);
+}
+
+static void _rtl92de_set_bcn_ctrl_reg(struct ieee80211_hw *hw,
+ u8 set_bits, u8 clear_bits)
+{
+ struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+ rtlpci->reg_bcn_ctrl_val |= set_bits;
+ rtlpci->reg_bcn_ctrl_val &= ~clear_bits;
+ rtl_write_byte(rtlpriv, REG_BCN_CTRL, (u8) rtlpci->reg_bcn_ctrl_val);
+}
+
+static void _rtl92de_stop_tx_beacon(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u8 tmp1byte;
+
+ tmp1byte = rtl_read_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2);
+ rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, tmp1byte & (~BIT(6)));
+ rtl_write_byte(rtlpriv, REG_BCN_MAX_ERR, 0xff);
+ rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 1, 0x64);
+ tmp1byte = rtl_read_byte(rtlpriv, REG_TBTT_PROHIBIT + 2);
+ tmp1byte &= ~(BIT(0));
+ rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 2, tmp1byte);
+}
+
+static void _rtl92de_resume_tx_beacon(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u8 tmp1byte;
+
+ tmp1byte = rtl_read_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2);
+ rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, tmp1byte | BIT(6));
+ rtl_write_byte(rtlpriv, REG_BCN_MAX_ERR, 0x0a);
+ rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 1, 0xff);
+ tmp1byte = rtl_read_byte(rtlpriv, REG_TBTT_PROHIBIT + 2);
+ tmp1byte |= BIT(0);
+ rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 2, tmp1byte);
+}
+
+static void _rtl92de_enable_bcn_sub_func(struct ieee80211_hw *hw)
+{
+ _rtl92de_set_bcn_ctrl_reg(hw, 0, BIT(1));
+}
+
+static void _rtl92de_disable_bcn_sub_func(struct ieee80211_hw *hw)
+{
+ _rtl92de_set_bcn_ctrl_reg(hw, BIT(1), 0);
+}
+
+void rtl92de_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+ struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+
+ switch (variable) {
+ case HW_VAR_RCR:
+ *((u32 *) (val)) = rtlpci->receive_config;
+ break;
+ case HW_VAR_RF_STATE:
+ *((enum rf_pwrstate *)(val)) = ppsc->rfpwr_state;
+ break;
+ case HW_VAR_FWLPS_RF_ON:{
+ enum rf_pwrstate rfState;
+ u32 val_rcr;
+
+ rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_RF_STATE,
+ (u8 *) (&rfState));
+ if (rfState == ERFOFF) {
+ *((bool *) (val)) = true;
+ } else {
+ val_rcr = rtl_read_dword(rtlpriv, REG_RCR);
+ val_rcr &= 0x00070000;
+ if (val_rcr)
+ *((bool *) (val)) = false;
+ else
+ *((bool *) (val)) = true;
+ }
+ break;
+ }
+ case HW_VAR_FW_PSMODE_STATUS:
+ *((bool *) (val)) = ppsc->fw_current_inpsmode;
+ break;
+ case HW_VAR_CORRECT_TSF:{
+ u64 tsf;
+ u32 *ptsf_low = (u32 *)&tsf;
+ u32 *ptsf_high = ((u32 *)&tsf) + 1;
+
+ *ptsf_high = rtl_read_dword(rtlpriv, (REG_TSFTR + 4));
+ *ptsf_low = rtl_read_dword(rtlpriv, REG_TSFTR);
+ *((u64 *) (val)) = tsf;
+ break;
+ }
+ case HW_VAR_INT_MIGRATION:
+ *((bool *)(val)) = rtlpriv->dm.interrupt_migration;
+ break;
+ case HW_VAR_INT_AC:
+ *((bool *)(val)) = rtlpriv->dm.disable_tx_int;
+ break;
+ default:
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+ ("switch case not process\n"));
+ break;
+ }
+}
+
+void rtl92de_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+ struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+ struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+ struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+ u8 idx;
+
+ switch (variable) {
+ case HW_VAR_ETHER_ADDR:
+ for (idx = 0; idx < ETH_ALEN; idx++) {
+ rtl_write_byte(rtlpriv, (REG_MACID + idx),
+ val[idx]);
+ }
+ break;
+ case HW_VAR_BASIC_RATE: {
+ u16 rate_cfg = ((u16 *) val)[0];
+ u8 rate_index = 0;
+
+ rate_cfg = rate_cfg & 0x15f;
+ if (mac->vendor == PEER_CISCO &&
+ ((rate_cfg & 0x150) == 0))
+ rate_cfg |= 0x01;
+ rtl_write_byte(rtlpriv, REG_RRSR, rate_cfg & 0xff);
+ rtl_write_byte(rtlpriv, REG_RRSR + 1,
+ (rate_cfg >> 8) & 0xff);
+ while (rate_cfg > 0x1) {
+ rate_cfg = (rate_cfg >> 1);
+ rate_index++;
+ }
+ if (rtlhal->fw_version > 0xe)
+ rtl_write_byte(rtlpriv, REG_INIRTS_RATE_SEL,
+ rate_index);
+ break;
+ }
+ case HW_VAR_BSSID:
+ for (idx = 0; idx < ETH_ALEN; idx++) {
+ rtl_write_byte(rtlpriv, (REG_BSSID + idx),
+ val[idx]);
+ }
+ break;
+ case HW_VAR_SIFS:
+ rtl_write_byte(rtlpriv, REG_SIFS_CTX + 1, val[0]);
+ rtl_write_byte(rtlpriv, REG_SIFS_TRX + 1, val[1]);
+ rtl_write_byte(rtlpriv, REG_SPEC_SIFS + 1, val[0]);
+ rtl_write_byte(rtlpriv, REG_MAC_SPEC_SIFS + 1, val[0]);
+ if (!mac->ht_enable)
+ rtl_write_word(rtlpriv, REG_RESP_SIFS_OFDM,
+ 0x0e0e);
+ else
+ rtl_write_word(rtlpriv, REG_RESP_SIFS_OFDM,
+ *((u16 *) val));
+ break;
+ case HW_VAR_SLOT_TIME: {
+ u8 e_aci;
+
+ RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD,
+ ("HW_VAR_SLOT_TIME %x\n", val[0]));
+ rtl_write_byte(rtlpriv, REG_SLOT, val[0]);
+ for (e_aci = 0; e_aci < AC_MAX; e_aci++)
+ rtlpriv->cfg->ops->set_hw_reg(hw,
+ HW_VAR_AC_PARAM,
+ (u8 *) (&e_aci));
+ break;
+ }
+ case HW_VAR_ACK_PREAMBLE: {
+ u8 reg_tmp;
+ u8 short_preamble = (bool) (*(u8 *) val);
+
+ reg_tmp = (mac->cur_40_prime_sc) << 5;
+ if (short_preamble)
+ reg_tmp |= 0x80;
+ rtl_write_byte(rtlpriv, REG_RRSR + 2, reg_tmp);
+ break;
+ }
+ case HW_VAR_AMPDU_MIN_SPACE: {
+ u8 min_spacing_to_set;
+ u8 sec_min_space;
+
+ min_spacing_to_set = *((u8 *) val);
+ if (min_spacing_to_set <= 7) {
+ sec_min_space = 0;
+ if (min_spacing_to_set < sec_min_space)
+ min_spacing_to_set = sec_min_space;
+ mac->min_space_cfg = ((mac->min_space_cfg & 0xf8) |
+ min_spacing_to_set);
+ *val = min_spacing_to_set;
+ RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD,
+ ("Set HW_VAR_AMPDU_MIN_SPACE: %#x\n",
+ mac->min_space_cfg));
+ rtl_write_byte(rtlpriv, REG_AMPDU_MIN_SPACE,
+ mac->min_space_cfg);
+ }
+ break;
+ }
+ case HW_VAR_SHORTGI_DENSITY: {
+ u8 density_to_set;
+
+ density_to_set = *((u8 *) val);
+ mac->min_space_cfg = rtlpriv->rtlhal.minspace_cfg;
+ mac->min_space_cfg |= (density_to_set << 3);
+ RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD,
+ ("Set HW_VAR_SHORTGI_DENSITY: %#x\n",
+ mac->min_space_cfg));
+ rtl_write_byte(rtlpriv, REG_AMPDU_MIN_SPACE,
+ mac->min_space_cfg);
+ break;
+ }
+ case HW_VAR_AMPDU_FACTOR: {
+ u8 factor_toset;
+ u32 regtoSet;
+ u8 *ptmp_byte = NULL;
+ u8 index;
+
+ if (rtlhal->macphymode == DUALMAC_DUALPHY)
+ regtoSet = 0xb9726641;
+ else if (rtlhal->macphymode == DUALMAC_SINGLEPHY)
+ regtoSet = 0x66626641;
+ else
+ regtoSet = 0xb972a841;
+ factor_toset = *((u8 *) val);
+ if (factor_toset <= 3) {
+ factor_toset = (1 << (factor_toset + 2));
+ if (factor_toset > 0xf)
+ factor_toset = 0xf;
+ for (index = 0; index < 4; index++) {
+ ptmp_byte = (u8 *) (®toSet) + index;
+ if ((*ptmp_byte & 0xf0) >
+ (factor_toset << 4))
+ *ptmp_byte = (*ptmp_byte & 0x0f)
+ | (factor_toset << 4);
+ if ((*ptmp_byte & 0x0f) > factor_toset)
+ *ptmp_byte = (*ptmp_byte & 0xf0)
+ | (factor_toset);
+ }
+ rtl_write_dword(rtlpriv, REG_AGGLEN_LMT, regtoSet);
+ RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD,
+ ("Set HW_VAR_AMPDU_FACTOR: %#x\n",
+ factor_toset));
+ }
+ break;
+ }
+ case HW_VAR_AC_PARAM: {
+ u8 e_aci = *((u8 *) val);
+ rtl92d_dm_init_edca_turbo(hw);
+ if (rtlpci->acm_method != eAcmWay2_SW)
+ rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_ACM_CTRL,
+ (u8 *) (&e_aci));
+ break;
+ }
+ case HW_VAR_ACM_CTRL: {
+ u8 e_aci = *((u8 *) val);
+ union aci_aifsn *p_aci_aifsn =
+ (union aci_aifsn *)(&(mac->ac[0].aifs));
+ u8 acm = p_aci_aifsn->f.acm;
+ u8 acm_ctrl = rtl_read_byte(rtlpriv, REG_ACMHWCTRL);
+
+ acm_ctrl = acm_ctrl | ((rtlpci->acm_method == 2) ? 0x0 : 0x1);
+ if (acm) {
+ switch (e_aci) {
+ case AC0_BE:
+ acm_ctrl |= ACMHW_BEQEN;
+ break;
+ case AC2_VI:
+ acm_ctrl |= ACMHW_VIQEN;
+ break;
+ case AC3_VO:
+ acm_ctrl |= ACMHW_VOQEN;
+ break;
+ default:
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
+ ("HW_VAR_ACM_CTRL acm set "
+ "failed: eACI is %d\n", acm));
+ break;
+ }
+ } else {
+ switch (e_aci) {
+ case AC0_BE:
+ acm_ctrl &= (~ACMHW_BEQEN);
+ break;
+ case AC2_VI:
+ acm_ctrl &= (~ACMHW_VIQEN);
+ break;
+ case AC3_VO:
+ acm_ctrl &= (~ACMHW_VOQEN);
+ break;
+ default:
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+ ("switch case not process\n"));
+ break;
+ }
+ }
+ RT_TRACE(rtlpriv, COMP_QOS, DBG_TRACE,
+ ("SetHwReg8190pci(): [HW_VAR_ACM_CTRL] "
+ "Write 0x%X\n", acm_ctrl));
+ rtl_write_byte(rtlpriv, REG_ACMHWCTRL, acm_ctrl);
+ break;
+ }
+ case HW_VAR_RCR:
+ rtl_write_dword(rtlpriv, REG_RCR, ((u32 *) (val))[0]);
+ rtlpci->receive_config = ((u32 *) (val))[0];
+ break;
+ case HW_VAR_RETRY_LIMIT: {
+ u8 retry_limit = ((u8 *) (val))[0];
+
+ rtl_write_word(rtlpriv, REG_RL,
+ retry_limit << RETRY_LIMIT_SHORT_SHIFT |
+ retry_limit << RETRY_LIMIT_LONG_SHIFT);
+ break;
+ }
+ case HW_VAR_DUAL_TSF_RST:
+ rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, (BIT(0) | BIT(1)));
+ break;
+ case HW_VAR_EFUSE_BYTES:
+ rtlefuse->efuse_usedbytes = *((u16 *) val);
+ break;
+ case HW_VAR_EFUSE_USAGE:
+ rtlefuse->efuse_usedpercentage = *((u8 *) val);
+ break;
+ case HW_VAR_IO_CMD:
+ rtl92d_phy_set_io_cmd(hw, (*(enum io_type *)val));
+ break;
+ case HW_VAR_WPA_CONFIG:
+ rtl_write_byte(rtlpriv, REG_SECCFG, *((u8 *) val));
+ break;
+ case HW_VAR_SET_RPWM:
+ rtl92d_fill_h2c_cmd(hw, H2C_PWRM, 1, (u8 *) (val));
+ break;
+ case HW_VAR_H2C_FW_PWRMODE:
+ break;
+ case HW_VAR_FW_PSMODE_STATUS:
+ ppsc->fw_current_inpsmode = *((bool *) val);
+ break;
+ case HW_VAR_H2C_FW_JOINBSSRPT: {
+ u8 mstatus = (*(u8 *) val);
+ u8 tmp_regcr, tmp_reg422;
+ bool recover = false;
+
+ if (mstatus == RT_MEDIA_CONNECT) {
+ rtlpriv->cfg->ops->set_hw_reg(hw,
+ HW_VAR_AID, NULL);
+ tmp_regcr = rtl_read_byte(rtlpriv, REG_CR + 1);
+ rtl_write_byte(rtlpriv, REG_CR + 1,
+ (tmp_regcr | BIT(0)));
+ _rtl92de_set_bcn_ctrl_reg(hw, 0, BIT(3));
+ _rtl92de_set_bcn_ctrl_reg(hw, BIT(4), 0);
+ tmp_reg422 = rtl_read_byte(rtlpriv,
+ REG_FWHW_TXQ_CTRL + 2);
+ if (tmp_reg422 & BIT(6))
+ recover = true;
+ rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2,
+ tmp_reg422 & (~BIT(6)));
+ rtl92d_set_fw_rsvdpagepkt(hw, 0);
+ _rtl92de_set_bcn_ctrl_reg(hw, BIT(3), 0);
+ _rtl92de_set_bcn_ctrl_reg(hw, 0, BIT(4));
+ if (recover)
+ rtl_write_byte(rtlpriv,
+ REG_FWHW_TXQ_CTRL + 2,
+ tmp_reg422);
+ rtl_write_byte(rtlpriv, REG_CR + 1,
+ (tmp_regcr & ~(BIT(0))));
+ }
+ rtl92d_set_fw_joinbss_report_cmd(hw, (*(u8 *) val));
+ break;
+ }
+ case HW_VAR_AID: {
+ u16 u2btmp;
+ u2btmp = rtl_read_word(rtlpriv, REG_BCN_PSR_RPT);
+ u2btmp &= 0xC000;
+ rtl_write_word(rtlpriv, REG_BCN_PSR_RPT, (u2btmp |
+ mac->assoc_id));
+ break;
+ }
+ case HW_VAR_CORRECT_TSF: {
+ u8 btype_ibss = ((u8 *) (val))[0];
+
+ if (btype_ibss == true)
+ _rtl92de_stop_tx_beacon(hw);
+ _rtl92de_set_bcn_ctrl_reg(hw, 0, BIT(3));
+ rtl_write_dword(rtlpriv, REG_TSFTR,
+ (u32) (mac->tsf & 0xffffffff));
+ rtl_write_dword(rtlpriv, REG_TSFTR + 4,
+ (u32) ((mac->tsf >> 32) & 0xffffffff));
+ _rtl92de_set_bcn_ctrl_reg(hw, BIT(3), 0);
+ if (btype_ibss == true)
+ _rtl92de_resume_tx_beacon(hw);
+
+ break;
+ }
+ case HW_VAR_INT_MIGRATION: {
+ bool int_migration = *(bool *) (val);
+
+ if (int_migration) {
+ /* Set interrrupt migration timer and
+ * corresponging Tx/Rx counter.
+ * timer 25ns*0xfa0=100us for 0xf packets.
+ * 0x306:Rx, 0x307:Tx */
+ rtl_write_dword(rtlpriv, REG_INT_MIG, 0xfe000fa0);
+ rtlpriv->dm.interrupt_migration = int_migration;
+ } else {
+ /* Reset all interrupt migration settings. */
+ rtl_write_dword(rtlpriv, REG_INT_MIG, 0);
+ rtlpriv->dm.interrupt_migration = int_migration;
+ }
+ break;
+ }
+ case HW_VAR_INT_AC: {
+ bool disable_ac_int = *((bool *) val);
+
+ /* Disable four ACs interrupts. */
+ if (disable_ac_int) {
+ /* Disable VO, VI, BE and BK four AC interrupts
+ * to gain more efficient CPU utilization.
+ * When extremely highly Rx OK occurs,
+ * we will disable Tx interrupts.
+ */
+ rtlpriv->cfg->ops->update_interrupt_mask(hw, 0,
+ RT_AC_INT_MASKS);
+ rtlpriv->dm.disable_tx_int = disable_ac_int;
+ /* Enable four ACs interrupts. */
+ } else {
+ rtlpriv->cfg->ops->update_interrupt_mask(hw,
+ RT_AC_INT_MASKS, 0);
+ rtlpriv->dm.disable_tx_int = disable_ac_int;
+ }
+ break;
+ }
+ default:
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+ ("switch case not process\n"));
+ break;
+ }
+}
+
+static bool _rtl92de_llt_write(struct ieee80211_hw *hw, u32 address, u32 data)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ bool status = true;
+ long count = 0;
+ u32 value = _LLT_INIT_ADDR(address) |
+ _LLT_INIT_DATA(data) | _LLT_OP(_LLT_WRITE_ACCESS);
+
+ rtl_write_dword(rtlpriv, REG_LLT_INIT, value);
+ do {
+ value = rtl_read_dword(rtlpriv, REG_LLT_INIT);
+ if (_LLT_NO_ACTIVE == _LLT_OP_VALUE(value))
+ break;
+ if (count > POLLING_LLT_THRESHOLD) {
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+ ("Failed to polling write LLT done at "
+ "address %d!\n", address));
+ status = false;
+ break;
+ }
+ } while (++count);
+ return status;
+}
+
+static bool _rtl92de_llt_table_init(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ unsigned short i;
+ u8 txpktbuf_bndy;
+ u8 maxPage;
+ bool status;
+ u32 value32; /* High+low page number */
+ u8 value8; /* normal page number */
+
+ if (rtlpriv->rtlhal.macphymode == SINGLEMAC_SINGLEPHY) {
+ maxPage = 255;
+ txpktbuf_bndy = 246;
+ value8 = 0;
+ value32 = 0x80bf0d29;
+ } else if (rtlpriv->rtlhal.macphymode != SINGLEMAC_SINGLEPHY) {
+ maxPage = 127;
+ txpktbuf_bndy = 123;
+ value8 = 0;
+ value32 = 0x80750005;
+ }
+
+ /* Set reserved page for each queue */
+ /* 11. RQPN 0x200[31:0] = 0x80BD1C1C */
+ /* load RQPN */
+ rtl_write_byte(rtlpriv, REG_RQPN_NPQ, value8);
+ rtl_write_dword(rtlpriv, REG_RQPN, value32);
+
+ /* 12. TXRKTBUG_PG_BNDY 0x114[31:0] = 0x27FF00F6 */
+ /* TXRKTBUG_PG_BNDY */
+ rtl_write_dword(rtlpriv, REG_TRXFF_BNDY,
+ (rtl_read_word(rtlpriv, REG_TRXFF_BNDY + 2) << 16 |
+ txpktbuf_bndy));
+
+ /* 13. TDECTRL[15:8] 0x209[7:0] = 0xF6 */
+ /* Beacon Head for TXDMA */
+ rtl_write_byte(rtlpriv, REG_TDECTRL + 1, txpktbuf_bndy);
+
+ /* 14. BCNQ_PGBNDY 0x424[7:0] = 0xF6 */
+ /* BCNQ_PGBNDY */
+ rtl_write_byte(rtlpriv, REG_TXPKTBUF_BCNQ_BDNY, txpktbuf_bndy);
+ rtl_write_byte(rtlpriv, REG_TXPKTBUF_MGQ_BDNY, txpktbuf_bndy);
+
+ /* 15. WMAC_LBK_BF_HD 0x45D[7:0] = 0xF6 */
+ /* WMAC_LBK_BF_HD */
+ rtl_write_byte(rtlpriv, 0x45D, txpktbuf_bndy);
+
+ /* Set Tx/Rx page size (Tx must be 128 Bytes, */
+ /* Rx can be 64,128,256,512,1024 bytes) */
+ /* 16. PBP [7:0] = 0x11 */
+ /* TRX page size */
+ rtl_write_byte(rtlpriv, REG_PBP, 0x11);
+
+ /* 17. DRV_INFO_SZ = 0x04 */
+ rtl_write_byte(rtlpriv, REG_RX_DRVINFO_SZ, 0x4);
+
+ /* 18. LLT_table_init(Adapter); */
+ for (i = 0; i < (txpktbuf_bndy - 1); i++) {
+ status = _rtl92de_llt_write(hw, i, i + 1);
+ if (true != status)
+ return status;
+ }
+
+ /* end of list */
+ status = _rtl92de_llt_write(hw, (txpktbuf_bndy - 1), 0xFF);
+ if (true != status)
+ return status;
+
+ /* Make the other pages as ring buffer */
+ /* This ring buffer is used as beacon buffer if we */
+ /* config this MAC as two MAC transfer. */
+ /* Otherwise used as local loopback buffer. */
+ for (i = txpktbuf_bndy; i < maxPage; i++) {
+ status = _rtl92de_llt_write(hw, i, (i + 1));
+ if (true != status)
+ return status;
+ }
+
+ /* Let last entry point to the start entry of ring buffer */
+ status = _rtl92de_llt_write(hw, maxPage, txpktbuf_bndy);
+ if (true != status)
+ return status;
+
+ return true;
+}
+
+static void _rtl92de_gen_refresh_led_state(struct ieee80211_hw *hw)
+{
+ struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
+ struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+ struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+ struct rtl_led *pLed0 = &(pcipriv->ledctl.sw_led0);
+
+ if (rtlpci->up_first_time)
+ return;
+ if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS)
+ rtl92de_sw_led_on(hw, pLed0);
+ else if (ppsc->rfoff_reason == RF_CHANGE_BY_INIT)
+ rtl92de_sw_led_on(hw, pLed0);
+ else
+ rtl92de_sw_led_off(hw, pLed0);
+}
+
+static bool _rtl92de_init_mac(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+ unsigned char bytetmp;
+ unsigned short wordtmp;
+ u16 retry;
+
+ rtl92d_phy_set_poweron(hw);
+ /* Add for resume sequence of power domain according
+ * to power document V11. Chapter V.11.... */
+ /* 0. RSV_CTRL 0x1C[7:0] = 0x00 */
+ /* unlock ISO/CLK/Power control register */
+ rtl_write_byte(rtlpriv, REG_RSV_CTRL, 0x00);
+ rtl_write_byte(rtlpriv, REG_LDOA15_CTRL, 0x05);
+
+ /* 1. AFE_XTAL_CTRL [7:0] = 0x0F enable XTAL */
+ /* 2. SPS0_CTRL 0x11[7:0] = 0x2b enable SPS into PWM mode */
+ /* 3. delay (1ms) this is not necessary when initially power on */
+
+ /* C. Resume Sequence */
+ /* a. SPS0_CTRL 0x11[7:0] = 0x2b */
+ rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x2b);
+
+ /* b. AFE_XTAL_CTRL [7:0] = 0x0F */
+ rtl_write_byte(rtlpriv, REG_AFE_XTAL_CTRL, 0x0F);
+
+ /* c. DRV runs power on init flow */
+
+ /* auto enable WLAN */
+ /* 4. APS_FSMCO 0x04[8] = 1; wait till 0x04[8] = 0 */
+ /* Power On Reset for MAC Block */
+ bytetmp = rtl_read_byte(rtlpriv, REG_APS_FSMCO + 1) | BIT(0);
+ udelay(2);
+ rtl_write_byte(rtlpriv, REG_APS_FSMCO + 1, bytetmp);
+ udelay(2);
+
+ /* 5. Wait while 0x04[8] == 0 goto 2, otherwise goto 1 */
+ bytetmp = rtl_read_byte(rtlpriv, REG_APS_FSMCO + 1);
+ udelay(50);
+ retry = 0;
+ while ((bytetmp & BIT(0)) && retry < 1000) {
+ retry++;
+ bytetmp = rtl_read_byte(rtlpriv, REG_APS_FSMCO + 1);
+ udelay(50);
+ }
+
+ /* Enable Radio off, GPIO, and LED function */
+ /* 6. APS_FSMCO 0x04[15:0] = 0x0012 when enable HWPDN */
+ rtl_write_word(rtlpriv, REG_APS_FSMCO, 0x1012);
+
+ /* release RF digital isolation */
+ /* 7. SYS_ISO_CTRL 0x01[1] = 0x0; */
+ /*Set REG_SYS_ISO_CTRL 0x1=0x82 to prevent wake# problem. */
+ rtl_write_byte(rtlpriv, REG_SYS_ISO_CTRL + 1, 0x82);
+ udelay(2);
+
+ /* make sure that BB reset OK. */
+ /* rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE3); */
+
+ /* Disable REG_CR before enable it to assure reset */
+ rtl_write_word(rtlpriv, REG_CR, 0x0);
+
+ /* Release MAC IO register reset */
+ rtl_write_word(rtlpriv, REG_CR, 0x2ff);
+
+ /* clear stopping tx/rx dma */
+ rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG + 1, 0x0);
+
+ /* rtl_write_word(rtlpriv,REG_CR+2, 0x2); */
+
+ /* System init */
+ /* 18. LLT_table_init(Adapter); */
+ if (_rtl92de_llt_table_init(hw) == false)
+ return false;
+
+ /* Clear interrupt and enable interrupt */
+ /* 19. HISR 0x124[31:0] = 0xffffffff; */
+ /* HISRE 0x12C[7:0] = 0xFF */
+ rtl_write_dword(rtlpriv, REG_HISR, 0xffffffff);
+ rtl_write_byte(rtlpriv, REG_HISRE, 0xff);
+
+ /* 20. HIMR 0x120[31:0] |= [enable INT mask bit map]; */
+ /* 21. HIMRE 0x128[7:0] = [enable INT mask bit map] */
+ /* The IMR should be enabled later after all init sequence
+ * is finished. */
+
+ /* 22. PCIE configuration space configuration */
+ /* 23. Ensure PCIe Device 0x80[15:0] = 0x0143 (ASPM+CLKREQ), */
+ /* and PCIe gated clock function is enabled. */
+ /* PCIE configuration space will be written after
+ * all init sequence.(Or by BIOS) */
+
+ rtl92d_phy_config_maccoexist_rfpage(hw);
+
+ /* THe below section is not related to power document Vxx . */
+ /* This is only useful for driver and OS setting. */
+ /* -------------------Software Relative Setting---------------------- */
+ wordtmp = rtl_read_word(rtlpriv, REG_TRXDMA_CTRL);
+ wordtmp &= 0xf;
+ wordtmp |= 0xF771;
+ rtl_write_word(rtlpriv, REG_TRXDMA_CTRL, wordtmp);
+
+ /* Reported Tx status from HW for rate adaptive. */
+ /* This should be realtive to power on step 14. But in document V11 */
+ /* still not contain the description.!!! */
+ rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 1, 0x1F);
+
+ /* Set Tx/Rx page size (Tx must be 128 Bytes,
+ * Rx can be 64,128,256,512,1024 bytes) */
+ /* rtl_write_byte(rtlpriv,REG_PBP, 0x11); */
+
+ /* Set RCR register */
+ rtl_write_dword(rtlpriv, REG_RCR, rtlpci->receive_config);
+ /* rtl_write_byte(rtlpriv,REG_RX_DRVINFO_SZ, 4); */
+
+ /* Set TCR register */
+ rtl_write_dword(rtlpriv, REG_TCR, rtlpci->transmit_config);
+
+ /* disable earlymode */
+ rtl_write_byte(rtlpriv, 0x4d0, 0x0);
+
+ /* Set TX/RX descriptor physical address(from OS API). */
+ rtl_write_dword(rtlpriv, REG_BCNQ_DESA,
+ rtlpci->tx_ring[BEACON_QUEUE].dma);
+ rtl_write_dword(rtlpriv, REG_MGQ_DESA, rtlpci->tx_ring[MGNT_QUEUE].dma);
+ rtl_write_dword(rtlpriv, REG_VOQ_DESA, rtlpci->tx_ring[VO_QUEUE].dma);
+ rtl_write_dword(rtlpriv, REG_VIQ_DESA, rtlpci->tx_ring[VI_QUEUE].dma);
+ rtl_write_dword(rtlpriv, REG_BEQ_DESA, rtlpci->tx_ring[BE_QUEUE].dma);
+ rtl_write_dword(rtlpriv, REG_BKQ_DESA, rtlpci->tx_ring[BK_QUEUE].dma);
+ rtl_write_dword(rtlpriv, REG_HQ_DESA, rtlpci->tx_ring[HIGH_QUEUE].dma);
+ /* Set RX Desc Address */
+ rtl_write_dword(rtlpriv, REG_RX_DESA,
+ rtlpci->rx_ring[RX_MPDU_QUEUE].dma);
+
+ /* if we want to support 64 bit DMA, we should set it here,
+ * but now we do not support 64 bit DMA*/
+
+ rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG + 3, 0x33);
+
+ /* Reset interrupt migration setting when initialization */
+ rtl_write_dword(rtlpriv, REG_INT_MIG, 0);
+
+ /* Reconsider when to do this operation after asking HWSD. */
+ bytetmp = rtl_read_byte(rtlpriv, REG_APSD_CTRL);
+ rtl_write_byte(rtlpriv, REG_APSD_CTRL, bytetmp & ~BIT(6));
+ do {
+ retry++;
+ bytetmp = rtl_read_byte(rtlpriv, REG_APSD_CTRL);
+ } while ((retry < 200) && !(bytetmp & BIT(7)));
+
+ /* After MACIO reset,we must refresh LED state. */
+ _rtl92de_gen_refresh_led_state(hw);
+
+ /* Reset H2C protection register */
+ rtl_write_dword(rtlpriv, REG_MCUTST_1, 0x0);
+
+ return true;
+}
+
+static void _rtl92de_hw_configure(struct ieee80211_hw *hw)
+{
+ struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+ u8 reg_bw_opmode = BW_OPMODE_20MHZ;
+ u32 reg_rrsr;
+
+ reg_rrsr = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
+ rtl_write_byte(rtlpriv, REG_INIRTS_RATE_SEL, 0x8);
+ rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode);
+ rtl_write_dword(rtlpriv, REG_RRSR, reg_rrsr);
+ rtl_write_byte(rtlpriv, REG_SLOT, 0x09);
+ rtl_write_byte(rtlpriv, REG_AMPDU_MIN_SPACE, 0x0);
+ rtl_write_word(rtlpriv, REG_FWHW_TXQ_CTRL, 0x1F80);
+ rtl_write_word(rtlpriv, REG_RL, 0x0707);
+ rtl_write_dword(rtlpriv, REG_BAR_MODE_CTRL, 0x02012802);
+ rtl_write_byte(rtlpriv, REG_HWSEQ_CTRL, 0xFF);
+ rtl_write_dword(rtlpriv, REG_DARFRC, 0x01000000);
+ rtl_write_dword(rtlpriv, REG_DARFRC + 4, 0x07060504);
+ rtl_write_dword(rtlpriv, REG_RARFRC, 0x01000000);
+ rtl_write_dword(rtlpriv, REG_RARFRC + 4, 0x07060504);
+ /* Aggregation threshold */
+ if (rtlhal->macphymode == DUALMAC_DUALPHY)
+ rtl_write_dword(rtlpriv, REG_AGGLEN_LMT, 0xb9726641);
+ else if (rtlhal->macphymode == DUALMAC_SINGLEPHY)
+ rtl_write_dword(rtlpriv, REG_AGGLEN_LMT, 0x66626641);
+ else
+ rtl_write_dword(rtlpriv, REG_AGGLEN_LMT, 0xb972a841);
+ rtl_write_byte(rtlpriv, REG_ATIMWND, 0x2);
+ rtl_write_byte(rtlpriv, REG_BCN_MAX_ERR, 0x0a);
+ rtlpci->reg_bcn_ctrl_val = 0x1f;
+ rtl_write_byte(rtlpriv, REG_BCN_CTRL, rtlpci->reg_bcn_ctrl_val);
+ rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 1, 0xff);
+ rtl_write_byte(rtlpriv, REG_PIFS, 0x1C);
+ rtl_write_byte(rtlpriv, REG_AGGR_BREAK_TIME, 0x16);
+ rtl_write_word(rtlpriv, REG_NAV_PROT_LEN, 0x0020);
+ /* For throughput */
+ rtl_write_word(rtlpriv, REG_FAST_EDCA_CTRL, 0x6666);
+ /* ACKTO for IOT issue. */
+ rtl_write_byte(rtlpriv, REG_ACKTO, 0x40);
+ /* Set Spec SIFS (used in NAV) */
+ rtl_write_word(rtlpriv, REG_SPEC_SIFS, 0x1010);
+ rtl_write_word(rtlpriv, REG_MAC_SPEC_SIFS, 0x1010);
+ /* Set SIFS for CCK */
+ rtl_write_word(rtlpriv, REG_SIFS_CTX, 0x1010);
+ /* Set SIFS for OFDM */
+ rtl_write_word(rtlpriv, REG_SIFS_TRX, 0x1010);
+ /* Set Multicast Address. */
+ rtl_write_dword(rtlpriv, REG_MAR, 0xffffffff);
+ rtl_write_dword(rtlpriv, REG_MAR + 4, 0xffffffff);
+ switch (rtlpriv->phy.rf_type) {
+ case RF_1T2R:
+ case RF_1T1R:
+ rtlhal->minspace_cfg = (MAX_MSS_DENSITY_1T << 3);
+ break;
+ case RF_2T2R:
+ case RF_2T2R_GREEN:
+ rtlhal->minspace_cfg = (MAX_MSS_DENSITY_2T << 3);
+ break;
+ }
+}
+
+static void _rtl92de_enable_aspm_back_door(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+
+ rtl_write_byte(rtlpriv, 0x34b, 0x93);
+ rtl_write_word(rtlpriv, 0x350, 0x870c);
+ rtl_write_byte(rtlpriv, 0x352, 0x1);
+ if (ppsc->support_backdoor)
+ rtl_write_byte(rtlpriv, 0x349, 0x1b);
+ else
+ rtl_write_byte(rtlpriv, 0x349, 0x03);
+ rtl_write_word(rtlpriv, 0x350, 0x2718);
+ rtl_write_byte(rtlpriv, 0x352, 0x1);
+}
+
+void rtl92de_enable_hw_security_config(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u8 sec_reg_value;
+
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+ ("PairwiseEncAlgorithm = %d GroupEncAlgorithm = %d\n",
+ rtlpriv->sec.pairwise_enc_algorithm,
+ rtlpriv->sec.group_enc_algorithm));
+ if (rtlpriv->cfg->mod_params->sw_crypto || rtlpriv->sec.use_sw_sec) {
+ RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
+ ("not open hw encryption\n"));
+ return;
+ }
+ sec_reg_value = SCR_TXENCENABLE | SCR_RXENCENABLE;
+ if (rtlpriv->sec.use_defaultkey) {
+ sec_reg_value |= SCR_TXUSEDK;
+ sec_reg_value |= SCR_RXUSEDK;
+ }
+ sec_reg_value |= (SCR_RXBCUSEDK | SCR_TXBCUSEDK);
+ rtl_write_byte(rtlpriv, REG_CR + 1, 0x02);
+ RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD,
+ ("The SECR-value %x\n", sec_reg_value));
+ rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_WPA_CONFIG, &sec_reg_value);
+}
+
+int rtl92de_hw_init(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+ struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+ struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+ bool rtstatus = true;
+ u8 tmp_u1b;
+ int i;
+ int err;
+ unsigned long flags;
+
+ rtlpci->being_init_adapter = true;
+ rtlpci->init_ready = false;
+ spin_lock_irqsave(&globalmutex_for_power_and_efuse, flags);
+ /* we should do iqk after disable/enable */
+ rtl92d_phy_reset_iqk_result(hw);
+ /* rtlpriv->intf_ops->disable_aspm(hw); */
+ rtstatus = _rtl92de_init_mac(hw);
+ if (rtstatus != true) {
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("Init MAC failed\n"));
+ err = 1;
+ spin_unlock_irqrestore(&globalmutex_for_power_and_efuse, flags);
+ return err;
+ }
+ err = rtl92d_download_fw(hw);
+ spin_unlock_irqrestore(&globalmutex_for_power_and_efuse, flags);
+ if (err) {
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
+ ("Failed to download FW. Init HW "
+ "without FW..\n"));
+ err = 1;
+ rtlhal->fw_ready = false;
+ } else {
+ rtlhal->fw_ready = true;
+ }
+ rtlhal->last_hmeboxnum = 0;
+ rtlpriv->psc.fw_current_inpsmode = false;
+
+ tmp_u1b = rtl_read_byte(rtlpriv, 0x605);
+ tmp_u1b = tmp_u1b | 0x30;
+ rtl_write_byte(rtlpriv, 0x605, tmp_u1b);
+
+ if (rtlhal->earlymode_enable) {
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+ ("EarlyMode Enabled!!!\n"));
+
+ tmp_u1b = rtl_read_byte(rtlpriv, 0x4d0);
+ tmp_u1b = tmp_u1b | 0x1f;
+ rtl_write_byte(rtlpriv, 0x4d0, tmp_u1b);
+
+ rtl_write_byte(rtlpriv, 0x4d3, 0x80);
+
+ tmp_u1b = rtl_read_byte(rtlpriv, 0x605);
+ tmp_u1b = tmp_u1b | 0x40;
+ rtl_write_byte(rtlpriv, 0x605, tmp_u1b);
+ }
+
+ if (mac->rdg_en) {
+ rtl_write_byte(rtlpriv, REG_RD_CTRL, 0xff);
+ rtl_write_word(rtlpriv, REG_RD_NAV_NXT, 0x200);
+ rtl_write_byte(rtlpriv, REG_RD_RESP_PKT_TH, 0x05);
+ }
+
+ rtl92d_phy_mac_config(hw);
+ /* because last function modify RCR, so we update
+ * rcr var here, or TP will unstable for receive_config
+ * is wrong, RX RCR_ACRC32 will cause TP unstabel & Rx
+ * RCR_APP_ICV will cause mac80211 unassoc for cisco 1252*/
+ rtlpci->receive_config = rtl_read_dword(rtlpriv, REG_RCR);
+ rtlpci->receive_config &= ~(RCR_ACRC32 | RCR_AICV);
+
+ rtl92d_phy_bb_config(hw);
+
+ rtlphy->rf_mode = RF_OP_BY_SW_3WIRE;
+ /* set before initialize RF */
+ rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER4, 0x00f00000, 0xf);
+
+ /* config RF */
+ rtl92d_phy_rf_config(hw);
+
+ /* After read predefined TXT, we must set BB/MAC/RF
+ * register as our requirement */
+ /* After load BB,RF params,we need do more for 92D. */
+ rtl92d_update_bbrf_configuration(hw);
+ /* set default value after initialize RF, */
+ rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER4, 0x00f00000, 0);
+ rtlphy->rfreg_chnlval[0] = rtl_get_rfreg(hw, (enum radio_path)0,
+ RF_CHNLBW, BRFREGOFFSETMASK);
+ rtlphy->rfreg_chnlval[1] = rtl_get_rfreg(hw, (enum radio_path)1,
+ RF_CHNLBW, BRFREGOFFSETMASK);
+
+ /*---- Set CCK and OFDM Block "ON"----*/
+ if (rtlhal->current_bandtype == BAND_ON_2_4G)
+ rtl_set_bbreg(hw, RFPGA0_RFMOD, BCCKEN, 0x1);
+ rtl_set_bbreg(hw, RFPGA0_RFMOD, BOFDMEN, 0x1);
+ if (rtlhal->interfaceindex == 0) {
+ /* RFPGA0_ANALOGPARAMETER2: cck clock select,
+ * set to 20MHz by default */
+ rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10) |
+ BIT(11), 3);
+ } else {
+ /* Mac1 */
+ rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(11) |
+ BIT(10), 3);
+ }
+
+ _rtl92de_hw_configure(hw);
+
+ /* reset hw sec */
+ rtl_cam_reset_all_entry(hw);
+ rtl92de_enable_hw_security_config(hw);
+
+ /* Read EEPROM TX power index and PHY_REG_PG.txt to capture correct */
+ /* TX power index for different rate set. */
+ rtl92d_phy_get_hw_reg_originalvalue(hw);
+ rtl92d_phy_set_txpower_level(hw, rtlphy->current_channel);
+
+ ppsc->rfpwr_state = ERFON;
+
+ rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_ETHER_ADDR, mac->mac_addr);
+
+ _rtl92de_enable_aspm_back_door(hw);
+ /* rtlpriv->intf_ops->enable_aspm(hw); */
+
+ rtl92d_dm_init(hw);
+ rtlpci->being_init_adapter = false;
+
+ if (ppsc->rfpwr_state == ERFON) {
+ rtl92d_phy_lc_calibrate(hw);
+ /* 5G and 2.4G must wait sometime to let RF LO ready */
+ if (rtlhal->macphymode == DUALMAC_DUALPHY) {
+ u32 tmp_rega;
+ for (i = 0; i < 10000; i++) {
+ udelay(MAX_STALL_TIME);
+
+ tmp_rega = rtl_get_rfreg(hw,
+ (enum radio_path)RF90_PATH_A,
+ 0x2a, BMASKDWORD);
+
+ if (((tmp_rega & BIT(11)) == BIT(11)))
+ break;
+ }
+ }
+ }
+ rtlpci->init_ready = true;
+ return err;
+}
+
+static enum version_8192d _rtl92de_read_chip_version(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ enum version_8192d version = VERSION_NORMAL_CHIP_92D_SINGLEPHY;
+ u32 value32;
+
+ value32 = rtl_read_dword(rtlpriv, REG_SYS_CFG);
+ if (!(value32 & 0x000f0000)) {
+ version = VERSION_TEST_CHIP_92D_SINGLEPHY;
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("TEST CHIP!!!\n"));
+ } else {
+ version = VERSION_NORMAL_CHIP_92D_SINGLEPHY;
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("Normal CHIP!!!\n"));
+ }
+ return version;
+}
+
+static int _rtl92de_set_media_status(struct ieee80211_hw *hw,
+ enum nl80211_iftype type)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u8 bt_msr = rtl_read_byte(rtlpriv, MSR);
+ enum led_ctl_mode ledaction = LED_CTL_NO_LINK;
+ u8 bcnfunc_enable;
+
+ bt_msr &= 0xfc;
+
+ if (type == NL80211_IFTYPE_UNSPECIFIED ||
+ type == NL80211_IFTYPE_STATION) {
+ _rtl92de_stop_tx_beacon(hw);
+ _rtl92de_enable_bcn_sub_func(hw);
+ } else if (type == NL80211_IFTYPE_ADHOC ||
+ type == NL80211_IFTYPE_AP) {
+ _rtl92de_resume_tx_beacon(hw);
+ _rtl92de_disable_bcn_sub_func(hw);
+ } else {
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
+ ("Set HW_VAR_MEDIA_STATUS: No such media "
+ "status(%x).\n", type));
+ }
+ bcnfunc_enable = rtl_read_byte(rtlpriv, REG_BCN_CTRL);
+ switch (type) {
+ case NL80211_IFTYPE_UNSPECIFIED:
+ bt_msr |= MSR_NOLINK;
+ ledaction = LED_CTL_LINK;
+ bcnfunc_enable &= 0xF7;
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+ ("Set Network type to NO LINK!\n"));
+ break;
+ case NL80211_IFTYPE_ADHOC:
+ bt_msr |= MSR_ADHOC;
+ bcnfunc_enable |= 0x08;
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+ ("Set Network type to Ad Hoc!\n"));
+ break;
+ case NL80211_IFTYPE_STATION:
+ bt_msr |= MSR_INFRA;
+ ledaction = LED_CTL_LINK;
+ bcnfunc_enable &= 0xF7;
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+ ("Set Network type to STA!\n"));
+ break;
+ case NL80211_IFTYPE_AP:
+ bt_msr |= MSR_AP;
+ bcnfunc_enable |= 0x08;
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+ ("Set Network type to AP!\n"));
+ break;
+ default:
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+ ("Network type %d not support!\n", type));
+ return 1;
+ break;
+
+ }
+ rtl_write_byte(rtlpriv, REG_CR + 2, bt_msr);
+ rtlpriv->cfg->ops->led_control(hw, ledaction);
+ if ((bt_msr & 0xfc) == MSR_AP)
+ rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x00);
+ else
+ rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x66);
+ return 0;
+}
+
+void rtl92de_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+ u32 reg_rcr = rtlpci->receive_config;
+
+ if (rtlpriv->psc.rfpwr_state != ERFON)
+ return;
+ if (check_bssid == true) {
+ reg_rcr |= (RCR_CBSSID_DATA | RCR_CBSSID_BCN);
+ rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR, (u8 *)(®_rcr));
+ _rtl92de_set_bcn_ctrl_reg(hw, 0, BIT(4));
+ } else if (check_bssid == false) {
+ reg_rcr &= (~(RCR_CBSSID_DATA | RCR_CBSSID_BCN));
+ _rtl92de_set_bcn_ctrl_reg(hw, BIT(4), 0);
+ rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR, (u8 *)(®_rcr));
+ }
+}
+
+int rtl92de_set_network_type(struct ieee80211_hw *hw, enum nl80211_iftype type)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+ if (_rtl92de_set_media_status(hw, type))
+ return -EOPNOTSUPP;
+
+ /* check bssid */
+ if (rtlpriv->mac80211.link_state == MAC80211_LINKED) {
+ if (type != NL80211_IFTYPE_AP)
+ rtl92de_set_check_bssid(hw, true);
+ } else {
+ rtl92de_set_check_bssid(hw, false);
+ }
+ return 0;
+}
+
+/* do iqk or reload iqk */
+/* windows just rtl92d_phy_reload_iqk_setting in set channel,
+ * but it's very strict for time sequence so we add
+ * rtl92d_phy_reload_iqk_setting here */
+void rtl92d_linked_set_reg(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ u8 indexforchannel;
+ u8 channel = rtlphy->current_channel;
+
+ indexforchannel = rtl92d_get_rightchnlplace_for_iqk(channel);
+ if (!rtlphy->iqk_matrix_regsetting[indexforchannel].iqk_done) {
+ RT_TRACE(rtlpriv, COMP_SCAN | COMP_INIT, DBG_DMESG,
+ ("Do IQK for channel:%d.\n", channel));
+ rtl92d_phy_iq_calibrate(hw);
+ }
+}
+
+/* don't set REG_EDCA_BE_PARAM here because
+ * mac80211 will send pkt when scan */
+void rtl92de_set_qos(struct ieee80211_hw *hw, int aci)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ rtl92d_dm_init_edca_turbo(hw);
+ return;
+ switch (aci) {
+ case AC1_BK:
+ rtl_write_dword(rtlpriv, REG_EDCA_BK_PARAM, 0xa44f);
+ break;
+ case AC0_BE:
+ break;
+ case AC2_VI:
+ rtl_write_dword(rtlpriv, REG_EDCA_VI_PARAM, 0x5e4322);
+ break;
+ case AC3_VO:
+ rtl_write_dword(rtlpriv, REG_EDCA_VO_PARAM, 0x2f3222);
+ break;
+ default:
+ RT_ASSERT(false, ("invalid aci: %d !\n", aci));
+ break;
+ }
+}
+
+void rtl92de_enable_interrupt(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+
+ rtl_write_dword(rtlpriv, REG_HIMR, rtlpci->irq_mask[0] & 0xFFFFFFFF);
+ rtl_write_dword(rtlpriv, REG_HIMRE, rtlpci->irq_mask[1] & 0xFFFFFFFF);
+ rtlpci->irq_enabled = true;
+}
+
+void rtl92de_disable_interrupt(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+
+ rtl_write_dword(rtlpriv, REG_HIMR, IMR8190_DISABLED);
+ rtl_write_dword(rtlpriv, REG_HIMRE, IMR8190_DISABLED);
+ rtlpci->irq_enabled = false;
+ synchronize_irq(rtlpci->pdev->irq);
+}
+
+static void _rtl92de_poweroff_adapter(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u8 u1b_tmp;
+ unsigned long flags;
+
+ rtlpriv->intf_ops->enable_aspm(hw);
+ rtl_write_byte(rtlpriv, REG_RF_CTRL, 0x00);
+ rtl_set_bbreg(hw, RFPGA0_XCD_RFPARAMETER, BIT(3), 0);
+ rtl_set_bbreg(hw, RFPGA0_XCD_RFPARAMETER, BIT(15), 0);
+
+ /* 0x20:value 05-->04 */
+ rtl_write_byte(rtlpriv, REG_LDOA15_CTRL, 0x04);
+
+ /* ==== Reset digital sequence ====== */
+ rtl92d_firmware_selfreset(hw);
+
+ /* f. SYS_FUNC_EN 0x03[7:0]=0x51 reset MCU, MAC register, DCORE */
+ rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, 0x51);
+
+ /* g. MCUFWDL 0x80[1:0]=0 reset MCU ready status */
+ rtl_write_byte(rtlpriv, REG_MCUFWDL, 0x00);
+
+ /* ==== Pull GPIO PIN to balance level and LED control ====== */
+
+ /* h. GPIO_PIN_CTRL 0x44[31:0]=0x000 */
+ rtl_write_dword(rtlpriv, REG_GPIO_PIN_CTRL, 0x00000000);
+
+ /* i. Value = GPIO_PIN_CTRL[7:0] */
+ u1b_tmp = rtl_read_byte(rtlpriv, REG_GPIO_PIN_CTRL);
+
+ /* j. GPIO_PIN_CTRL 0x44[31:0] = 0x00FF0000 | (value <<8); */
+ /* write external PIN level */
+ rtl_write_dword(rtlpriv, REG_GPIO_PIN_CTRL,
+ 0x00FF0000 | (u1b_tmp << 8));
+
+ /* k. GPIO_MUXCFG 0x42 [15:0] = 0x0780 */
+ rtl_write_word(rtlpriv, REG_GPIO_IO_SEL, 0x0790);
+
+ /* l. LEDCFG 0x4C[15:0] = 0x8080 */
+ rtl_write_word(rtlpriv, REG_LEDCFG0, 0x8080);
+
+ /* ==== Disable analog sequence === */
+
+ /* m. AFE_PLL_CTRL[7:0] = 0x80 disable PLL */
+ rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL, 0x80);
+
+ /* n. SPS0_CTRL 0x11[7:0] = 0x22 enter PFM mode */
+ rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x23);
+
+ /* o. AFE_XTAL_CTRL 0x24[7:0] = 0x0E disable XTAL, if No BT COEX */
+ rtl_write_byte(rtlpriv, REG_AFE_XTAL_CTRL, 0x0e);
+
+ /* p. RSV_CTRL 0x1C[7:0] = 0x0E lock ISO/CLK/Power control register */
+ rtl_write_byte(rtlpriv, REG_RSV_CTRL, 0x0e);
+
+ /* ==== interface into suspend === */
+
+ /* q. APS_FSMCO[15:8] = 0x58 PCIe suspend mode */
+ /* According to power document V11, we need to set this */
+ /* value as 0x18. Otherwise, we may not L0s sometimes. */
+ /* This indluences power consumption. Bases on SD1's test, */
+ /* set as 0x00 do not affect power current. And if it */
+ /* is set as 0x18, they had ever met auto load fail problem. */
+ rtl_write_byte(rtlpriv, REG_APS_FSMCO + 1, 0x10);
+
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+ ("In PowerOff,reg0x%x=%X\n", REG_SPS0_CTRL,
+ rtl_read_byte(rtlpriv, REG_SPS0_CTRL)));
+ /* r. Note: for PCIe interface, PON will not turn */
+ /* off m-bias and BandGap in PCIe suspend mode. */
+
+ /* 0x17[7] 1b': power off in process 0b' : power off over */
+ if (rtlpriv->rtlhal.macphymode != SINGLEMAC_SINGLEPHY) {
+ spin_lock_irqsave(&globalmutex_power, flags);
+ u1b_tmp = rtl_read_byte(rtlpriv, REG_POWER_OFF_IN_PROCESS);
+ u1b_tmp &= (~BIT(7));
+ rtl_write_byte(rtlpriv, REG_POWER_OFF_IN_PROCESS, u1b_tmp);
+ spin_unlock_irqrestore(&globalmutex_power, flags);
+ }
+
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("<=======\n"));
+}
+
+void rtl92de_card_disable(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+ struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+ struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+ enum nl80211_iftype opmode;
+
+ mac->link_state = MAC80211_NOLINK;
+ opmode = NL80211_IFTYPE_UNSPECIFIED;
+ _rtl92de_set_media_status(hw, opmode);
+
+ if (rtlpci->driver_is_goingto_unload ||
+ ppsc->rfoff_reason > RF_CHANGE_BY_PS)
+ rtlpriv->cfg->ops->led_control(hw, LED_CTL_POWER_OFF);
+ RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC);
+ /* Power sequence for each MAC. */
+ /* a. stop tx DMA */
+ /* b. close RF */
+ /* c. clear rx buf */
+ /* d. stop rx DMA */
+ /* e. reset MAC */
+
+ /* a. stop tx DMA */
+ rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG + 1, 0xFE);
+ udelay(50);
+
+ /* b. TXPAUSE 0x522[7:0] = 0xFF Pause MAC TX queue */
+
+ /* c. ========RF OFF sequence========== */
+ /* 0x88c[23:20] = 0xf. */
+ rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER4, 0x00f00000, 0xf);
+ rtl_set_rfreg(hw, RF90_PATH_A, 0x00, BRFREGOFFSETMASK, 0x00);
+
+ /* APSD_CTRL 0x600[7:0] = 0x40 */
+ rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x40);
+
+ /* Close antenna 0,0xc04,0xd04 */
+ rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE, BMASKBYTE0, 0);
+ rtl_set_bbreg(hw, ROFDM1_TRXPATHENABLE, BDWORD, 0);
+
+ /* SYS_FUNC_EN 0x02[7:0] = 0xE2 reset BB state machine */
+ rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2);
+
+ /* Mac0 can not do Global reset. Mac1 can do. */
+ /* SYS_FUNC_EN 0x02[7:0] = 0xE0 reset BB state machine */
+ if (rtlpriv->rtlhal.interfaceindex == 1)
+ rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE0);
+ udelay(50);
+
+ /* d. stop tx/rx dma before disable REG_CR (0x100) to fix */
+ /* dma hang issue when disable/enable device. */
+ rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG + 1, 0xff);
+ udelay(50);
+ rtl_write_byte(rtlpriv, REG_CR, 0x0);
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("==> Do power off.......\n"));
+ if (rtl92d_phy_check_poweroff(hw))
+ _rtl92de_poweroff_adapter(hw);
+ return;
+}
+
+void rtl92de_interrupt_recognized(struct ieee80211_hw *hw,
+ u32 *p_inta, u32 *p_intb)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+
+ *p_inta = rtl_read_dword(rtlpriv, ISR) & rtlpci->irq_mask[0];
+ rtl_write_dword(rtlpriv, ISR, *p_inta);
+
+ /*
+ * *p_intb = rtl_read_dword(rtlpriv, REG_HISRE) & rtlpci->irq_mask[1];
+ * rtl_write_dword(rtlpriv, ISR + 4, *p_intb);
+ */
+}
+
+void rtl92de_set_beacon_related_registers(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+ u16 bcn_interval, atim_window;
+
+ bcn_interval = mac->beacon_interval;
+ atim_window = 2;
+ /*rtl92de_disable_interrupt(hw); */
+ rtl_write_word(rtlpriv, REG_ATIMWND, atim_window);
+ rtl_write_word(rtlpriv, REG_BCN_INTERVAL, bcn_interval);
+ rtl_write_word(rtlpriv, REG_BCNTCFG, 0x660f);
+ rtl_write_byte(rtlpriv, REG_RXTSF_OFFSET_CCK, 0x20);
+ if (rtlpriv->rtlhal.current_bandtype == BAND_ON_5G)
+ rtl_write_byte(rtlpriv, REG_RXTSF_OFFSET_OFDM, 0x30);
+ else
+ rtl_write_byte(rtlpriv, REG_RXTSF_OFFSET_OFDM, 0x20);
+ rtl_write_byte(rtlpriv, 0x606, 0x30);
+}
+
+void rtl92de_set_beacon_interval(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+ u16 bcn_interval = mac->beacon_interval;
+
+ RT_TRACE(rtlpriv, COMP_BEACON, DBG_DMESG,
+ ("beacon_interval:%d\n", bcn_interval));
+ /* rtl92de_disable_interrupt(hw); */
+ rtl_write_word(rtlpriv, REG_BCN_INTERVAL, bcn_interval);
+ /* rtl92de_enable_interrupt(hw); */
+}
+
+void rtl92de_update_interrupt_mask(struct ieee80211_hw *hw,
+ u32 add_msr, u32 rm_msr)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+
+ RT_TRACE(rtlpriv, COMP_INTR, DBG_LOUD,
+ ("add_msr:%x, rm_msr:%x\n", add_msr, rm_msr));
+ if (add_msr)
+ rtlpci->irq_mask[0] |= add_msr;
+ if (rm_msr)
+ rtlpci->irq_mask[0] &= (~rm_msr);
+ rtl92de_disable_interrupt(hw);
+ rtl92de_enable_interrupt(hw);
+}
+
+static void _rtl92de_readpowervalue_fromprom(struct txpower_info *pwrinfo,
+ u8 *rom_content, bool autoLoadfail)
+{
+ u32 rfpath, eeaddr, group, offset1, offset2;
+ u8 i;
+
+ memset(pwrinfo, 0, sizeof(struct txpower_info));
+ if (autoLoadfail) {
+ for (group = 0; group < CHANNEL_GROUP_MAX; group++) {
+ for (rfpath = 0; rfpath < RF6052_MAX_PATH; rfpath++) {
+ if (group < CHANNEL_GROUP_MAX_2G) {
+ pwrinfo->cck_index[rfpath][group] =
+ EEPROM_DEFAULT_TXPOWERLEVEL_2G;
+ pwrinfo->ht40_1sindex[rfpath][group] =
+ EEPROM_DEFAULT_TXPOWERLEVEL_2G;
+ } else {
+ pwrinfo->ht40_1sindex[rfpath][group] =
+ EEPROM_DEFAULT_TXPOWERLEVEL_5G;
+ }
+ pwrinfo->ht40_2sindexdiff[rfpath][group] =
+ EEPROM_DEFAULT_HT40_2SDIFF;
+ pwrinfo->ht20indexdiff[rfpath][group] =
+ EEPROM_DEFAULT_HT20_DIFF;
+ pwrinfo->ofdmindexdiff[rfpath][group] =
+ EEPROM_DEFAULT_LEGACYHTTXPOWERDIFF;
+ pwrinfo->ht40maxoffset[rfpath][group] =
+ EEPROM_DEFAULT_HT40_PWRMAXOFFSET;
+ pwrinfo->ht20maxoffset[rfpath][group] =
+ EEPROM_DEFAULT_HT20_PWRMAXOFFSET;
+ }
+ }
+ for (i = 0; i < 3; i++) {
+ pwrinfo->tssi_a[i] = EEPROM_DEFAULT_TSSI;
+ pwrinfo->tssi_b[i] = EEPROM_DEFAULT_TSSI;
+ }
+ return;
+ }
+
+ /* Maybe autoload OK,buf the tx power index value is not filled.
+ * If we find it, we set it to default value. */
+ for (rfpath = 0; rfpath < RF6052_MAX_PATH; rfpath++) {
+ for (group = 0; group < CHANNEL_GROUP_MAX_2G; group++) {
+ eeaddr = EEPROM_CCK_TX_PWR_INX_2G + (rfpath * 3)
+ + group;
+ pwrinfo->cck_index[rfpath][group] =
+ (rom_content[eeaddr] == 0xFF) ?
+ (eeaddr > 0x7B ?
+ EEPROM_DEFAULT_TXPOWERLEVEL_5G :
+ EEPROM_DEFAULT_TXPOWERLEVEL_2G) :
+ rom_content[eeaddr];
+ }
+ }
+ for (rfpath = 0; rfpath < RF6052_MAX_PATH; rfpath++) {
+ for (group = 0; group < CHANNEL_GROUP_MAX; group++) {
+ offset1 = group / 3;
+ offset2 = group % 3;
+ eeaddr = EEPROM_HT40_1S_TX_PWR_INX_2G + (rfpath * 3) +
+ offset2 + offset1 * 21;
+ pwrinfo->ht40_1sindex[rfpath][group] =
+ (rom_content[eeaddr] == 0xFF) ? (eeaddr > 0x7B ?
+ EEPROM_DEFAULT_TXPOWERLEVEL_5G :
+ EEPROM_DEFAULT_TXPOWERLEVEL_2G) :
+ rom_content[eeaddr];
+ }
+ }
+ /* These just for 92D efuse offset. */
+ for (group = 0; group < CHANNEL_GROUP_MAX; group++) {
+ for (rfpath = 0; rfpath < RF6052_MAX_PATH; rfpath++) {
+ int base1 = EEPROM_HT40_2S_TX_PWR_INX_DIFF_2G;
+
+ offset1 = group / 3;
+ offset2 = group % 3;
+
+ if (rom_content[base1 + offset2 + offset1 * 21] != 0xFF)
+ pwrinfo->ht40_2sindexdiff[rfpath][group] =
+ (rom_content[base1 +
+ offset2 + offset1 * 21] >> (rfpath * 4))
+ & 0xF;
+ else
+ pwrinfo->ht40_2sindexdiff[rfpath][group] =
+ EEPROM_DEFAULT_HT40_2SDIFF;
+ if (rom_content[EEPROM_HT20_TX_PWR_INX_DIFF_2G + offset2
+ + offset1 * 21] != 0xFF)
+ pwrinfo->ht20indexdiff[rfpath][group] =
+ (rom_content[EEPROM_HT20_TX_PWR_INX_DIFF_2G
+ + offset2 + offset1 * 21] >> (rfpath * 4))
+ & 0xF;
+ else
+ pwrinfo->ht20indexdiff[rfpath][group] =
+ EEPROM_DEFAULT_HT20_DIFF;
+ if (rom_content[EEPROM_OFDM_TX_PWR_INX_DIFF_2G + offset2
+ + offset1 * 21] != 0xFF)
+ pwrinfo->ofdmindexdiff[rfpath][group] =
+ (rom_content[EEPROM_OFDM_TX_PWR_INX_DIFF_2G
+ + offset2 + offset1 * 21] >> (rfpath * 4))
+ & 0xF;
+ else
+ pwrinfo->ofdmindexdiff[rfpath][group] =
+ EEPROM_DEFAULT_LEGACYHTTXPOWERDIFF;
+ if (rom_content[EEPROM_HT40_MAX_PWR_OFFSET_2G + offset2
+ + offset1 * 21] != 0xFF)
+ pwrinfo->ht40maxoffset[rfpath][group] =
+ (rom_content[EEPROM_HT40_MAX_PWR_OFFSET_2G
+ + offset2 + offset1 * 21] >> (rfpath * 4))
+ & 0xF;
+ else
+ pwrinfo->ht40maxoffset[rfpath][group] =
+ EEPROM_DEFAULT_HT40_PWRMAXOFFSET;
+ if (rom_content[EEPROM_HT20_MAX_PWR_OFFSET_2G + offset2
+ + offset1 * 21] != 0xFF)
+ pwrinfo->ht20maxoffset[rfpath][group] =
+ (rom_content[EEPROM_HT20_MAX_PWR_OFFSET_2G +
+ offset2 + offset1 * 21] >> (rfpath * 4)) &
+ 0xF;
+ else
+ pwrinfo->ht20maxoffset[rfpath][group] =
+ EEPROM_DEFAULT_HT20_PWRMAXOFFSET;
+ }
+ }
+ if (rom_content[EEPROM_TSSI_A_5G] != 0xFF) {
+ /* 5GL */
+ pwrinfo->tssi_a[0] = rom_content[EEPROM_TSSI_A_5G] & 0x3F;
+ pwrinfo->tssi_b[0] = rom_content[EEPROM_TSSI_B_5G] & 0x3F;
+ /* 5GM */
+ pwrinfo->tssi_a[1] = rom_content[EEPROM_TSSI_AB_5G] & 0x3F;
+ pwrinfo->tssi_b[1] =
+ (rom_content[EEPROM_TSSI_AB_5G] & 0xC0) >> 6 |
+ (rom_content[EEPROM_TSSI_AB_5G + 1] & 0x0F) << 2;
+ /* 5GH */
+ pwrinfo->tssi_a[2] = (rom_content[EEPROM_TSSI_AB_5G + 1] &
+ 0xF0) >> 4 |
+ (rom_content[EEPROM_TSSI_AB_5G + 2] & 0x03) << 4;
+ pwrinfo->tssi_b[2] = (rom_content[EEPROM_TSSI_AB_5G + 2] &
+ 0xFC) >> 2;
+ } else {
+ for (i = 0; i < 3; i++) {
+ pwrinfo->tssi_a[i] = EEPROM_DEFAULT_TSSI;
+ pwrinfo->tssi_b[i] = EEPROM_DEFAULT_TSSI;
+ }
+ }
+}
+
+static void _rtl92de_read_txpower_info(struct ieee80211_hw *hw,
+ bool autoload_fail, u8 *hwinfo)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+ struct txpower_info pwrinfo;
+ u8 tempval[2], i, pwr, diff;
+ u32 ch, rfPath, group;
+
+ _rtl92de_readpowervalue_fromprom(&pwrinfo, hwinfo, autoload_fail);
+ if (!autoload_fail) {
+ /* bit0~2 */
+ rtlefuse->eeprom_regulatory = (hwinfo[EEPROM_RF_OPT1] & 0x7);
+ rtlefuse->eeprom_thermalmeter =
+ hwinfo[EEPROM_THERMAL_METER] & 0x1f;
+ rtlefuse->crystalcap = hwinfo[EEPROM_XTAL_K];
+ tempval[0] = hwinfo[EEPROM_IQK_DELTA] & 0x03;
+ tempval[1] = (hwinfo[EEPROM_LCK_DELTA] & 0x0C) >> 2;
+ rtlefuse->txpwr_fromeprom = true;
+ if (IS_92D_D_CUT(rtlpriv->rtlhal.version)) {
+ rtlefuse->internal_pa_5g[0] =
+ !((hwinfo[EEPROM_TSSI_A_5G] &
+ BIT(6)) >> 6);
+ rtlefuse->internal_pa_5g[1] =
+ !((hwinfo[EEPROM_TSSI_B_5G] &
+ BIT(6)) >> 6);
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+ ("Is D cut,Internal PA0 %d Internal PA1 %d\n",
+ rtlefuse->internal_pa_5g[0],
+ rtlefuse->internal_pa_5g[1]))
+ }
+ rtlefuse->eeprom_c9 = hwinfo[EEPROM_RF_OPT6];
+ rtlefuse->eeprom_cc = hwinfo[EEPROM_RF_OPT7];
+ } else {
+ rtlefuse->eeprom_regulatory = 0;
+ rtlefuse->eeprom_thermalmeter = EEPROM_DEFAULT_THERMALMETER;
+ rtlefuse->crystalcap = EEPROM_DEFAULT_CRYSTALCAP;
+ tempval[0] = tempval[1] = 3;
+ }
+
+ /* Use default value to fill parameters if
+ * efuse is not filled on some place. */
+
+ /* ThermalMeter from EEPROM */
+ if (rtlefuse->eeprom_thermalmeter < 0x06 ||
+ rtlefuse->eeprom_thermalmeter > 0x1c)
+ rtlefuse->eeprom_thermalmeter = 0x12;
+ rtlefuse->thermalmeter[0] = rtlefuse->eeprom_thermalmeter;
+
+ /* check XTAL_K */
+ if (rtlefuse->crystalcap == 0xFF)
+ rtlefuse->crystalcap = 0;
+ if (rtlefuse->eeprom_regulatory > 3)
+ rtlefuse->eeprom_regulatory = 0;
+
+ for (i = 0; i < 2; i++) {
+ switch (tempval[i]) {
+ case 0:
+ tempval[i] = 5;
+ break;
+ case 1:
+ tempval[i] = 4;
+ break;
+ case 2:
+ tempval[i] = 3;
+ break;
+ case 3:
+ default:
+ tempval[i] = 0;
+ break;
+ }
+ }
+
+ rtlefuse->delta_iqk = tempval[0];
+ if (tempval[1] > 0)
+ rtlefuse->delta_lck = tempval[1] - 1;
+ if (rtlefuse->eeprom_c9 == 0xFF)
+ rtlefuse->eeprom_c9 = 0x00;
+ RT_TRACE(rtlpriv, COMP_INTR, DBG_LOUD,
+ ("EEPROMRegulatory = 0x%x\n", rtlefuse->eeprom_regulatory));
+ RT_TRACE(rtlpriv, COMP_INTR, DBG_LOUD,
+ ("ThermalMeter = 0x%x\n", rtlefuse->eeprom_thermalmeter));
+ RT_TRACE(rtlpriv, COMP_INTR, DBG_LOUD,
+ ("CrystalCap = 0x%x\n", rtlefuse->crystalcap));
+ RT_TRACE(rtlpriv, COMP_INTR, DBG_LOUD,
+ ("Delta_IQK = 0x%x Delta_LCK = 0x%x\n", rtlefuse->delta_iqk,
+ rtlefuse->delta_lck));
+
+ for (rfPath = 0; rfPath < RF6052_MAX_PATH; rfPath++) {
+ for (ch = 0; ch < CHANNEL_MAX_NUMBER; ch++) {
+ group = rtl92d_get_chnlgroup_fromarray((u8) ch);
+ if (ch < CHANNEL_MAX_NUMBER_2G)
+ rtlefuse->txpwrlevel_cck[rfPath][ch] =
+ pwrinfo.cck_index[rfPath][group];
+ rtlefuse->txpwrlevel_ht40_1s[rfPath][ch] =
+ pwrinfo.ht40_1sindex[rfPath][group];
+ rtlefuse->txpwr_ht20diff[rfPath][ch] =
+ pwrinfo.ht20indexdiff[rfPath][group];
+ rtlefuse->txpwr_legacyhtdiff[rfPath][ch] =
+ pwrinfo.ofdmindexdiff[rfPath][group];
+ rtlefuse->pwrgroup_ht20[rfPath][ch] =
+ pwrinfo.ht20maxoffset[rfPath][group];
+ rtlefuse->pwrgroup_ht40[rfPath][ch] =
+ pwrinfo.ht40maxoffset[rfPath][group];
+ pwr = pwrinfo.ht40_1sindex[rfPath][group];
+ diff = pwrinfo.ht40_2sindexdiff[rfPath][group];
+ rtlefuse->txpwrlevel_ht40_2s[rfPath][ch] =
+ (pwr > diff) ? (pwr - diff) : 0;
+ }
+ }
+}
+
+static void _rtl92de_read_macphymode_from_prom(struct ieee80211_hw *hw,
+ u8 *content)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+ u8 macphy_crvalue = content[EEPROM_MAC_FUNCTION];
+
+ if (macphy_crvalue & BIT(3)) {
+ rtlhal->macphymode = SINGLEMAC_SINGLEPHY;
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+ ("MacPhyMode SINGLEMAC_SINGLEPHY\n"));
+ } else {
+ rtlhal->macphymode = DUALMAC_DUALPHY;
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+ ("MacPhyMode DUALMAC_DUALPHY\n"));
+ }
+}
+
+static void _rtl92de_read_macphymode_and_bandtype(struct ieee80211_hw *hw,
+ u8 *content)
+{
+ _rtl92de_read_macphymode_from_prom(hw, content);
+ rtl92d_phy_config_macphymode(hw);
+ rtl92d_phy_config_macphymode_info(hw);
+}
+
+static void _rtl92de_efuse_update_chip_version(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ enum version_8192d chipver = rtlpriv->rtlhal.version;
+ u8 cutvalue[2];
+ u16 chipvalue;
+
+ rtlpriv->intf_ops->read_efuse_byte(hw, EEPROME_CHIP_VERSION_H,
+ &cutvalue[1]);
+ rtlpriv->intf_ops->read_efuse_byte(hw, EEPROME_CHIP_VERSION_L,
+ &cutvalue[0]);
+ chipvalue = (cutvalue[1] << 8) | cutvalue[0];
+ switch (chipvalue) {
+ case 0xAA55:
+ chipver |= CHIP_92D_C_CUT;
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("C-CUT!!!\n"));
+ break;
+ case 0x9966:
+ chipver |= CHIP_92D_D_CUT;
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("D-CUT!!!\n"));
+ break;
+ default:
+ chipver |= CHIP_92D_D_CUT;
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG, ("Unkown CUT!\n"));
+ break;
+ }
+ rtlpriv->rtlhal.version = chipver;
+}
+
+static void _rtl92de_read_adapter_info(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+ u16 i, usvalue;
+ u8 hwinfo[HWSET_MAX_SIZE];
+ u16 eeprom_id;
+ unsigned long flags;
+
+ if (rtlefuse->epromtype == EEPROM_BOOT_EFUSE) {
+ spin_lock_irqsave(&globalmutex_for_power_and_efuse, flags);
+ rtl_efuse_shadow_map_update(hw);
+ _rtl92de_efuse_update_chip_version(hw);
+ spin_unlock_irqrestore(&globalmutex_for_power_and_efuse, flags);
+ memcpy((void *)hwinfo, (void *)&rtlefuse->efuse_map
+ [EFUSE_INIT_MAP][0],
+ HWSET_MAX_SIZE);
+ } else if (rtlefuse->epromtype == EEPROM_93C46) {
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+ ("RTL819X Not boot from eeprom, check it !!"));
+ }
+ RT_PRINT_DATA(rtlpriv, COMP_INIT, DBG_DMESG, ("MAP\n"),
+ hwinfo, HWSET_MAX_SIZE);
+
+ eeprom_id = *((u16 *)&hwinfo[0]);
+ if (eeprom_id != RTL8190_EEPROM_ID) {
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
+ ("EEPROM ID(%#x) is invalid!!\n", eeprom_id));
+ rtlefuse->autoload_failflag = true;
+ } else {
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("Autoload OK\n"));
+ rtlefuse->autoload_failflag = false;
+ }
+ if (rtlefuse->autoload_failflag == true) {
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+ ("RTL819X Not boot from eeprom, check it !!"));
+ return;
+ }
+ rtlefuse->eeprom_oemid = *(u8 *)&hwinfo[EEPROM_CUSTOMER_ID];
+ _rtl92de_read_macphymode_and_bandtype(hw, hwinfo);
+
+ /* VID, DID SE 0xA-D */
+ rtlefuse->eeprom_vid = *(u16 *)&hwinfo[EEPROM_VID];
+ rtlefuse->eeprom_did = *(u16 *)&hwinfo[EEPROM_DID];
+ rtlefuse->eeprom_svid = *(u16 *)&hwinfo[EEPROM_SVID];
+ rtlefuse->eeprom_smid = *(u16 *)&hwinfo[EEPROM_SMID];
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+ ("EEPROMId = 0x%4x\n", eeprom_id));
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+ ("EEPROM VID = 0x%4x\n", rtlefuse->eeprom_vid));
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+ ("EEPROM DID = 0x%4x\n", rtlefuse->eeprom_did));
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+ ("EEPROM SVID = 0x%4x\n", rtlefuse->eeprom_svid));
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+ ("EEPROM SMID = 0x%4x\n", rtlefuse->eeprom_smid));
+
+ /* Read Permanent MAC address */
+ if (rtlhal->interfaceindex == 0) {
+ for (i = 0; i < 6; i += 2) {
+ usvalue = *(u16 *)&hwinfo[EEPROM_MAC_ADDR_MAC0_92D + i];
+ *((u16 *) (&rtlefuse->dev_addr[i])) = usvalue;
+ }
+ } else {
+ for (i = 0; i < 6; i += 2) {
+ usvalue = *(u16 *)&hwinfo[EEPROM_MAC_ADDR_MAC1_92D + i];
+ *((u16 *) (&rtlefuse->dev_addr[i])) = usvalue;
+ }
+ }
+ rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_ETHER_ADDR,
+ rtlefuse->dev_addr);
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
+ (MAC_FMT "\n", MAC_ARG(rtlefuse->dev_addr)));
+ _rtl92de_read_txpower_info(hw, rtlefuse->autoload_failflag, hwinfo);
+
+ /* Read Channel Plan */
+ switch (rtlhal->bandset) {
+ case BAND_ON_2_4G:
+ rtlefuse->channel_plan = COUNTRY_CODE_TELEC;
+ break;
+ case BAND_ON_5G:
+ rtlefuse->channel_plan = COUNTRY_CODE_FCC;
+ break;
+ case BAND_ON_BOTH:
+ rtlefuse->channel_plan = COUNTRY_CODE_FCC;
+ break;
+ default:
+ rtlefuse->channel_plan = COUNTRY_CODE_FCC;
+ break;
+ }
+ rtlefuse->eeprom_version = *(u16 *)&hwinfo[EEPROM_VERSION];
+ rtlefuse->txpwr_fromeprom = true;
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+ ("EEPROM Customer ID: 0x%2x\n", rtlefuse->eeprom_oemid));
+}
+
+void rtl92de_read_eeprom_info(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+ u8 tmp_u1b;
+
+ rtlhal->version = _rtl92de_read_chip_version(hw);
+ tmp_u1b = rtl_read_byte(rtlpriv, REG_9346CR);
+ rtlefuse->autoload_status = tmp_u1b;
+ if (tmp_u1b & BIT(4)) {
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, ("Boot from EEPROM\n"));
+ rtlefuse->epromtype = EEPROM_93C46;
+ } else {
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, ("Boot from EFUSE\n"));
+ rtlefuse->epromtype = EEPROM_BOOT_EFUSE;
+ }
+ if (tmp_u1b & BIT(5)) {
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("Autoload OK\n"));
+
+ rtlefuse->autoload_failflag = false;
+ _rtl92de_read_adapter_info(hw);
+ } else {
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("Autoload ERR!!\n"));
+ }
+ return;
+}
+
+static void rtl92de_update_hal_rate_table(struct ieee80211_hw *hw,
+ struct ieee80211_sta *sta)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+ u32 ratr_value;
+ u8 ratr_index = 0;
+ u8 nmode = mac->ht_enable;
+ u8 mimo_ps = IEEE80211_SMPS_OFF;
+ u16 shortgi_rate;
+ u32 tmp_ratr_value;
+ u8 curtxbw_40mhz = mac->bw_40;
+ u8 curshortgi_40mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) ?
+ 1 : 0;
+ u8 curshortgi_20mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) ?
+ 1 : 0;
+ enum wireless_mode wirelessmode = mac->mode;
+
+ if (rtlhal->current_bandtype == BAND_ON_5G)
+ ratr_value = sta->supp_rates[1] << 4;
+ else
+ ratr_value = sta->supp_rates[0];
+ ratr_value |= (sta->ht_cap.mcs.rx_mask[1] << 20 |
+ sta->ht_cap.mcs.rx_mask[0] << 12);
+ switch (wirelessmode) {
+ case WIRELESS_MODE_A:
+ ratr_value &= 0x00000FF0;
+ break;
+ case WIRELESS_MODE_B:
+ if (ratr_value & 0x0000000c)
+ ratr_value &= 0x0000000d;
+ else
+ ratr_value &= 0x0000000f;
+ break;
+ case WIRELESS_MODE_G:
+ ratr_value &= 0x00000FF5;
+ break;
+ case WIRELESS_MODE_N_24G:
+ case WIRELESS_MODE_N_5G:
+ nmode = 1;
+ if (mimo_ps == IEEE80211_SMPS_STATIC) {
+ ratr_value &= 0x0007F005;
+ } else {
+ u32 ratr_mask;
+
+ if (get_rf_type(rtlphy) == RF_1T2R ||
+ get_rf_type(rtlphy) == RF_1T1R) {
+ ratr_mask = 0x000ff005;
+ } else {
+ ratr_mask = 0x0f0ff005;
+ }
+
+ ratr_value &= ratr_mask;
+ }
+ break;
+ default:
+ if (rtlphy->rf_type == RF_1T2R)
+ ratr_value &= 0x000ff0ff;
+ else
+ ratr_value &= 0x0f0ff0ff;
+
+ break;
+ }
+ ratr_value &= 0x0FFFFFFF;
+ if (nmode && ((curtxbw_40mhz && curshortgi_40mhz) ||
+ (!curtxbw_40mhz && curshortgi_20mhz))) {
+ ratr_value |= 0x10000000;
+ tmp_ratr_value = (ratr_value >> 12);
+ for (shortgi_rate = 15; shortgi_rate > 0; shortgi_rate--) {
+ if ((1 << shortgi_rate) & tmp_ratr_value)
+ break;
+ }
+ shortgi_rate = (shortgi_rate << 12) | (shortgi_rate << 8) |
+ (shortgi_rate << 4) | (shortgi_rate);
+ }
+ rtl_write_dword(rtlpriv, REG_ARFR0 + ratr_index * 4, ratr_value);
+ RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG,
+ ("%x\n", rtl_read_dword(rtlpriv, REG_ARFR0)));
+}
+
+static void rtl92de_update_hal_rate_mask(struct ieee80211_hw *hw,
+ struct ieee80211_sta *sta, u8 rssi_level)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+ struct rtl_sta_info *sta_entry = NULL;
+ u32 ratr_bitmap;
+ u8 ratr_index;
+ u8 curtxbw_40mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40)
+ ? 1 : 0;
+ u8 curshortgi_40mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) ?
+ 1 : 0;
+ u8 curshortgi_20mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) ?
+ 1 : 0;
+ enum wireless_mode wirelessmode = 0;
+ bool shortgi = false;
+ u32 value[2];
+ u8 macid = 0;
+ u8 mimo_ps = IEEE80211_SMPS_OFF;
+
+ sta_entry = (struct rtl_sta_info *) sta->drv_priv;
+ mimo_ps = sta_entry->mimo_ps;
+ wirelessmode = sta_entry->wireless_mode;
+ if (mac->opmode == NL80211_IFTYPE_STATION)
+ curtxbw_40mhz = mac->bw_40;
+ else if (mac->opmode == NL80211_IFTYPE_AP ||
+ mac->opmode == NL80211_IFTYPE_ADHOC)
+ macid = sta->aid + 1;
+
+ if (rtlhal->current_bandtype == BAND_ON_5G)
+ ratr_bitmap = sta->supp_rates[1] << 4;
+ else
+ ratr_bitmap = sta->supp_rates[0];
+ ratr_bitmap |= (sta->ht_cap.mcs.rx_mask[1] << 20 |
+ sta->ht_cap.mcs.rx_mask[0] << 12);
+ switch (wirelessmode) {
+ case WIRELESS_MODE_B:
+ ratr_index = RATR_INX_WIRELESS_B;
+ if (ratr_bitmap & 0x0000000c)
+ ratr_bitmap &= 0x0000000d;
+ else
+ ratr_bitmap &= 0x0000000f;
+ break;
+ case WIRELESS_MODE_G:
+ ratr_index = RATR_INX_WIRELESS_GB;
+
+ if (rssi_level == 1)
+ ratr_bitmap &= 0x00000f00;
+ else if (rssi_level == 2)
+ ratr_bitmap &= 0x00000ff0;
+ else
+ ratr_bitmap &= 0x00000ff5;
+ break;
+ case WIRELESS_MODE_A:
+ ratr_index = RATR_INX_WIRELESS_G;
+ ratr_bitmap &= 0x00000ff0;
+ break;
+ case WIRELESS_MODE_N_24G:
+ case WIRELESS_MODE_N_5G:
+ if (wirelessmode == WIRELESS_MODE_N_24G)
+ ratr_index = RATR_INX_WIRELESS_NGB;
+ else
+ ratr_index = RATR_INX_WIRELESS_NG;
+ if (mimo_ps == IEEE80211_SMPS_STATIC) {
+ if (rssi_level == 1)
+ ratr_bitmap &= 0x00070000;
+ else if (rssi_level == 2)
+ ratr_bitmap &= 0x0007f000;
+ else
+ ratr_bitmap &= 0x0007f005;
+ } else {
+ if (rtlphy->rf_type == RF_1T2R ||
+ rtlphy->rf_type == RF_1T1R) {
+ if (curtxbw_40mhz) {
+ if (rssi_level == 1)
+ ratr_bitmap &= 0x000f0000;
+ else if (rssi_level == 2)
+ ratr_bitmap &= 0x000ff000;
+ else
+ ratr_bitmap &= 0x000ff015;
+ } else {
+ if (rssi_level == 1)
+ ratr_bitmap &= 0x000f0000;
+ else if (rssi_level == 2)
+ ratr_bitmap &= 0x000ff000;
+ else
+ ratr_bitmap &= 0x000ff005;
+ }
+ } else {
+ if (curtxbw_40mhz) {
+ if (rssi_level == 1)
+ ratr_bitmap &= 0x0f0f0000;
+ else if (rssi_level == 2)
+ ratr_bitmap &= 0x0f0ff000;
+ else
+ ratr_bitmap &= 0x0f0ff015;
+ } else {
+ if (rssi_level == 1)
+ ratr_bitmap &= 0x0f0f0000;
+ else if (rssi_level == 2)
+ ratr_bitmap &= 0x0f0ff000;
+ else
+ ratr_bitmap &= 0x0f0ff005;
+ }
+ }
+ }
+ if ((curtxbw_40mhz && curshortgi_40mhz) ||
+ (!curtxbw_40mhz && curshortgi_20mhz)) {
+
+ if (macid == 0)
+ shortgi = true;
+ else if (macid == 1)
+ shortgi = false;
+ }
+ break;
+ default:
+ ratr_index = RATR_INX_WIRELESS_NGB;
+
+ if (rtlphy->rf_type == RF_1T2R)
+ ratr_bitmap &= 0x000ff0ff;
+ else
+ ratr_bitmap &= 0x0f0ff0ff;
+ break;
+ }
+
+ value[0] = (ratr_bitmap & 0x0fffffff) | (ratr_index << 28);
+ value[1] = macid | (shortgi ? 0x20 : 0x00) | 0x80;
+ RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG,
+ ("ratr_bitmap :%x value0:%x value1:%x\n",
+ ratr_bitmap, value[0], value[1]));
+ rtl92d_fill_h2c_cmd(hw, H2C_RA_MASK, 5, (u8 *) value);
+ if (macid != 0)
+ sta_entry->ratr_index = ratr_index;
+}
+
+void rtl92de_update_hal_rate_tbl(struct ieee80211_hw *hw,
+ struct ieee80211_sta *sta, u8 rssi_level)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+ if (rtlpriv->dm.useramask)
+ rtl92de_update_hal_rate_mask(hw, sta, rssi_level);
+ else
+ rtl92de_update_hal_rate_table(hw, sta);
+}
+
+void rtl92de_update_channel_access_setting(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+ u16 sifs_timer;
+
+ rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SLOT_TIME,
+ (u8 *)&mac->slot_time);
+ if (!mac->ht_enable)
+ sifs_timer = 0x0a0a;
+ else
+ sifs_timer = 0x1010;
+ rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SIFS, (u8 *)&sifs_timer);
+}
+
+bool rtl92de_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+ struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+ enum rf_pwrstate e_rfpowerstate_toset;
+ u8 u1tmp;
+ bool actuallyset = false;
+ unsigned long flag;
+
+ if (rtlpci->being_init_adapter)
+ return false;
+ if (ppsc->swrf_processing)
+ return false;
+ spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flag);
+ if (ppsc->rfchange_inprogress) {
+ spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag);
+ return false;
+ } else {
+ ppsc->rfchange_inprogress = true;
+ spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag);
+ }
+ rtl_write_byte(rtlpriv, REG_MAC_PINMUX_CFG, rtl_read_byte(rtlpriv,
+ REG_MAC_PINMUX_CFG) & ~(BIT(3)));
+ u1tmp = rtl_read_byte(rtlpriv, REG_GPIO_IO_SEL);
+ e_rfpowerstate_toset = (u1tmp & BIT(3)) ? ERFON : ERFOFF;
+ if ((ppsc->hwradiooff == true) && (e_rfpowerstate_toset == ERFON)) {
+ RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
+ ("GPIOChangeRF - HW Radio ON, RF ON\n"));
+ e_rfpowerstate_toset = ERFON;
+ ppsc->hwradiooff = false;
+ actuallyset = true;
+ } else if ((ppsc->hwradiooff == false)
+ && (e_rfpowerstate_toset == ERFOFF)) {
+ RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
+ ("GPIOChangeRF - HW Radio OFF, RF OFF\n"));
+ e_rfpowerstate_toset = ERFOFF;
+ ppsc->hwradiooff = true;
+ actuallyset = true;
+ }
+ if (actuallyset) {
+ spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flag);
+ ppsc->rfchange_inprogress = false;
+ spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag);
+ } else {
+ if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_HALT_NIC)
+ RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC);
+ spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flag);
+ ppsc->rfchange_inprogress = false;
+ spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag);
+ }
+ *valid = 1;
+ return !ppsc->hwradiooff;
+}
+
+void rtl92de_set_key(struct ieee80211_hw *hw, u32 key_index,
+ u8 *p_macaddr, bool is_group, u8 enc_algo,
+ bool is_wepkey, bool clear_all)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+ struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+ u8 *macaddr = p_macaddr;
+ u32 entry_id;
+ bool is_pairwise = false;
+ static u8 cam_const_addr[4][6] = {
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x01},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x02},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x03}
+ };
+ static u8 cam_const_broad[] = {
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
+ };
+
+ if (clear_all) {
+ u8 idx;
+ u8 cam_offset = 0;
+ u8 clear_number = 5;
+ RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, ("clear_all\n"));
+ for (idx = 0; idx < clear_number; idx++) {
+ rtl_cam_mark_invalid(hw, cam_offset + idx);
+ rtl_cam_empty_entry(hw, cam_offset + idx);
+
+ if (idx < 5) {
+ memset(rtlpriv->sec.key_buf[idx], 0,
+ MAX_KEY_LEN);
+ rtlpriv->sec.key_len[idx] = 0;
+ }
+ }
+ } else {
+ switch (enc_algo) {
+ case WEP40_ENCRYPTION:
+ enc_algo = CAM_WEP40;
+ break;
+ case WEP104_ENCRYPTION:
+ enc_algo = CAM_WEP104;
+ break;
+ case TKIP_ENCRYPTION:
+ enc_algo = CAM_TKIP;
+ break;
+ case AESCCMP_ENCRYPTION:
+ enc_algo = CAM_AES;
+ break;
+ default:
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("switch case "
+ "not process\n"));
+ enc_algo = CAM_TKIP;
+ break;
+ }
+ if (is_wepkey || rtlpriv->sec.use_defaultkey) {
+ macaddr = cam_const_addr[key_index];
+ entry_id = key_index;
+ } else {
+ if (is_group) {
+ macaddr = cam_const_broad;
+ entry_id = key_index;
+ } else {
+ if (mac->opmode == NL80211_IFTYPE_AP) {
+ entry_id = rtl_cam_get_free_entry(hw,
+ p_macaddr);
+ if (entry_id >= TOTAL_CAM_ENTRY) {
+ RT_TRACE(rtlpriv, COMP_SEC,
+ DBG_EMERG, ("Can not "
+ "find free hw security"
+ " cam entry\n"));
+ return;
+ }
+ } else {
+ entry_id = CAM_PAIRWISE_KEY_POSITION;
+ }
+ key_index = PAIRWISE_KEYIDX;
+ is_pairwise = true;
+ }
+ }
+ if (rtlpriv->sec.key_len[key_index] == 0) {
+ RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
+ ("delete one entry, entry_id is %d\n",
+ entry_id));
+ if (mac->opmode == NL80211_IFTYPE_AP)
+ rtl_cam_del_entry(hw, p_macaddr);
+ rtl_cam_delete_one_entry(hw, p_macaddr, entry_id);
+ } else {
+ RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD,
+ ("The insert KEY length is %d\n",
+ rtlpriv->sec.key_len[PAIRWISE_KEYIDX]));
+ RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD,
+ ("The insert KEY is %x %x\n",
+ rtlpriv->sec.key_buf[0][0],
+ rtlpriv->sec.key_buf[0][1]));
+ RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
+ ("add one entry\n"));
+ if (is_pairwise) {
+ RT_PRINT_DATA(rtlpriv, COMP_SEC, DBG_LOUD,
+ "Pairwiase Key content :",
+ rtlpriv->sec.pairwise_key,
+ rtlpriv->
+ sec.key_len[PAIRWISE_KEYIDX]);
+ RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
+ ("set Pairwiase key\n"));
+ rtl_cam_add_one_entry(hw, macaddr, key_index,
+ entry_id, enc_algo,
+ CAM_CONFIG_NO_USEDK,
+ rtlpriv->
+ sec.key_buf[key_index]);
+ } else {
+ RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
+ ("set group key\n"));
+ if (mac->opmode == NL80211_IFTYPE_ADHOC) {
+ rtl_cam_add_one_entry(hw,
+ rtlefuse->dev_addr,
+ PAIRWISE_KEYIDX,
+ CAM_PAIRWISE_KEY_POSITION,
+ enc_algo, CAM_CONFIG_NO_USEDK,
+ rtlpriv->sec.key_buf[entry_id]);
+ }
+ rtl_cam_add_one_entry(hw, macaddr, key_index,
+ entry_id, enc_algo,
+ CAM_CONFIG_NO_USEDK,
+ rtlpriv->sec.key_buf
+ [entry_id]);
+ }
+ }
+ }
+}
+
+void rtl92de_suspend(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+ rtlpriv->rtlhal.macphyctl_reg = rtl_read_byte(rtlpriv,
+ REG_MAC_PHY_CTRL_NORMAL);
+}
+
+void rtl92de_resume(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+ rtl_write_byte(rtlpriv, REG_MAC_PHY_CTRL_NORMAL,
+ rtlpriv->rtlhal.macphyctl_reg);
+}
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/hw.h b/drivers/net/wireless/rtlwifi/rtl8192de/hw.h
new file mode 100644
index 0000000..ad44ffa
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8192de/hw.h
@@ -0,0 +1,66 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010 Realtek Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License 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, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#ifndef __RTL92DE_HW_H__
+#define __RTL92DE_HW_H__
+
+void rtl92de_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val);
+void rtl92de_read_eeprom_info(struct ieee80211_hw *hw);
+void rtl92de_interrupt_recognized(struct ieee80211_hw *hw,
+ u32 *p_inta, u32 *p_intb);
+int rtl92de_hw_init(struct ieee80211_hw *hw);
+void rtl92de_card_disable(struct ieee80211_hw *hw);
+void rtl92de_enable_interrupt(struct ieee80211_hw *hw);
+void rtl92de_disable_interrupt(struct ieee80211_hw *hw);
+int rtl92de_set_network_type(struct ieee80211_hw *hw, enum nl80211_iftype type);
+void rtl92de_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid);
+void rtl92de_set_qos(struct ieee80211_hw *hw, int aci);
+void rtl92de_set_beacon_related_registers(struct ieee80211_hw *hw);
+void rtl92de_set_beacon_interval(struct ieee80211_hw *hw);
+void rtl92de_update_interrupt_mask(struct ieee80211_hw *hw,
+ u32 add_msr, u32 rm_msr);
+void rtl92de_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val);
+void rtl92de_update_hal_rate_tbl(struct ieee80211_hw *hw,
+ struct ieee80211_sta *sta, u8 rssi_level);
+void rtl92de_update_channel_access_setting(struct ieee80211_hw *hw);
+bool rtl92de_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid);
+void rtl92de_enable_hw_security_config(struct ieee80211_hw *hw);
+void rtl92de_set_key(struct ieee80211_hw *hw, u32 key_index,
+ u8 *p_macaddr, bool is_group, u8 enc_algo,
+ bool is_wepkey, bool clear_all);
+
+extern void rtl92de_write_dword_dbi(struct ieee80211_hw *hw, u16 offset,
+ u32 value, u8 direct);
+extern u32 rtl92de_read_dword_dbi(struct ieee80211_hw *hw, u16 offset,
+ u8 direct);
+void rtl92de_suspend(struct ieee80211_hw *hw);
+void rtl92de_resume(struct ieee80211_hw *hw);
+void rtl92d_linked_set_reg(struct ieee80211_hw *hw);
+
+#endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/led.c b/drivers/net/wireless/rtlwifi/rtl8192de/led.c
new file mode 100644
index 0000000..719972c
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8192de/led.c
@@ -0,0 +1,159 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010 Realtek Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License 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, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#include "../wifi.h"
+#include "../pci.h"
+#include "reg.h"
+#include "led.h"
+
+static void _rtl92ce_init_led(struct ieee80211_hw *hw,
+ struct rtl_led *pled, enum rtl_led_pin ledpin)
+{
+ pled->hw = hw;
+ pled->ledpin = ledpin;
+ pled->ledon = false;
+}
+
+void rtl92de_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled)
+{
+ u8 ledcfg;
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+ RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD,
+ ("LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pled->ledpin));
+
+ switch (pled->ledpin) {
+ case LED_PIN_GPIO0:
+ break;
+ case LED_PIN_LED0:
+ ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG2);
+
+ if ((rtlpriv->efuse.eeprom_did == 0x8176) ||
+ (rtlpriv->efuse.eeprom_did == 0x8193))
+ /* BIT7 of REG_LEDCFG2 should be set to
+ * make sure we could emit the led2. */
+ rtl_write_byte(rtlpriv, REG_LEDCFG2, (ledcfg & 0xf0) |
+ BIT(7) | BIT(5) | BIT(6));
+ else
+ rtl_write_byte(rtlpriv, REG_LEDCFG2, (ledcfg & 0xf0) |
+ BIT(7) | BIT(5));
+ break;
+ case LED_PIN_LED1:
+ ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG1);
+
+ rtl_write_byte(rtlpriv, REG_LEDCFG2, (ledcfg & 0x0f) | BIT(5));
+ break;
+ default:
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+ ("switch case not process\n"));
+ break;
+ }
+ pled->ledon = true;
+}
+
+void rtl92de_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
+ u8 ledcfg;
+
+ RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD,
+ ("LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pled->ledpin));
+
+ ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG2);
+
+ switch (pled->ledpin) {
+ case LED_PIN_GPIO0:
+ break;
+ case LED_PIN_LED0:
+ ledcfg &= 0xf0;
+ if (pcipriv->ledctl.led_opendrain == true)
+ rtl_write_byte(rtlpriv, REG_LEDCFG2,
+ (ledcfg | BIT(1) | BIT(5) | BIT(6)));
+ else
+ rtl_write_byte(rtlpriv, REG_LEDCFG2,
+ (ledcfg | BIT(3) | BIT(5) | BIT(6)));
+ break;
+ case LED_PIN_LED1:
+ ledcfg &= 0x0f;
+ rtl_write_byte(rtlpriv, REG_LEDCFG2, (ledcfg | BIT(3)));
+ break;
+ default:
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+ ("switch case not process\n"));
+ break;
+ }
+ pled->ledon = false;
+}
+
+void rtl92de_init_sw_leds(struct ieee80211_hw *hw)
+{
+ struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
+ _rtl92ce_init_led(hw, &(pcipriv->ledctl.sw_led0), LED_PIN_LED0);
+ _rtl92ce_init_led(hw, &(pcipriv->ledctl.sw_led1), LED_PIN_LED1);
+}
+
+static void _rtl92ce_sw_led_control(struct ieee80211_hw *hw,
+ enum led_ctl_mode ledaction)
+{
+ struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
+ struct rtl_led *pLed0 = &(pcipriv->ledctl.sw_led0);
+ switch (ledaction) {
+ case LED_CTL_POWER_ON:
+ case LED_CTL_LINK:
+ case LED_CTL_NO_LINK:
+ rtl92de_sw_led_on(hw, pLed0);
+ break;
+ case LED_CTL_POWER_OFF:
+ rtl92de_sw_led_off(hw, pLed0);
+ break;
+ default:
+ break;
+ }
+}
+
+void rtl92de_led_control(struct ieee80211_hw *hw, enum led_ctl_mode ledaction)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+
+ if ((ppsc->rfoff_reason > RF_CHANGE_BY_PS) &&
+ (ledaction == LED_CTL_TX ||
+ ledaction == LED_CTL_RX ||
+ ledaction == LED_CTL_SITE_SURVEY ||
+ ledaction == LED_CTL_LINK ||
+ ledaction == LED_CTL_NO_LINK ||
+ ledaction == LED_CTL_START_TO_LINK ||
+ ledaction == LED_CTL_POWER_ON)) {
+ return;
+ }
+ RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, ("ledaction %d,\n", ledaction));
+
+ _rtl92ce_sw_led_control(hw, ledaction);
+}
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/led.h b/drivers/net/wireless/rtlwifi/rtl8192de/led.h
new file mode 100644
index 0000000..57f4a3c
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8192de/led.h
@@ -0,0 +1,38 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010 Realtek Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License 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, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#ifndef __RTL92CE_LED_H__
+#define __RTL92CE_LED_H__
+
+void rtl92de_init_sw_leds(struct ieee80211_hw *hw);
+void rtl92de_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled);
+void rtl92de_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled);
+void rtl92de_led_control(struct ieee80211_hw *hw, enum led_ctl_mode ledaction);
+
+#endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/phy.c b/drivers/net/wireless/rtlwifi/rtl8192de/phy.c
new file mode 100644
index 0000000..97fb6ca
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8192de/phy.c
@@ -0,0 +1,3837 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010 Realtek Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License 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, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#include "../wifi.h"
+#include "../pci.h"
+#include "../ps.h"
+#include "reg.h"
+#include "def.h"
+#include "phy.h"
+#include "rf.h"
+#include "dm.h"
+#include "table.h"
+#include "sw.h"
+#include "hw.h"
+
+#define MAX_RF_IMR_INDEX 12
+#define MAX_RF_IMR_INDEX_NORMAL 13
+#define RF_REG_NUM_FOR_C_CUT_5G 6
+#define RF_REG_NUM_FOR_C_CUT_5G_INTERNALPA 7
+#define RF_REG_NUM_FOR_C_CUT_2G 5
+#define RF_CHNL_NUM_5G 19
+#define RF_CHNL_NUM_5G_40M 17
+#define TARGET_CHNL_NUM_5G 221
+#define TARGET_CHNL_NUM_2G 14
+#define CV_CURVE_CNT 64
+
+static u32 rf_reg_for_5g_swchnl_normal[MAX_RF_IMR_INDEX_NORMAL] = {
+ 0, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x0
+};
+
+static u8 rf_reg_for_c_cut_5g[RF_REG_NUM_FOR_C_CUT_5G] = {
+ RF_SYN_G1, RF_SYN_G2, RF_SYN_G3, RF_SYN_G4, RF_SYN_G5, RF_SYN_G6
+};
+
+static u8 rf_reg_for_c_cut_2g[RF_REG_NUM_FOR_C_CUT_2G] = {
+ RF_SYN_G1, RF_SYN_G2, RF_SYN_G3, RF_SYN_G7, RF_SYN_G8
+};
+
+static u8 rf_for_c_cut_5g_internal_pa[RF_REG_NUM_FOR_C_CUT_5G_INTERNALPA] = {
+ 0x0B, 0x48, 0x49, 0x4B, 0x03, 0x04, 0x0E
+};
+
+static u32 rf_reg_mask_for_c_cut_2g[RF_REG_NUM_FOR_C_CUT_2G] = {
+ BIT(19) | BIT(18) | BIT(17) | BIT(14) | BIT(1),
+ BIT(10) | BIT(9),
+ BIT(18) | BIT(17) | BIT(16) | BIT(1),
+ BIT(2) | BIT(1),
+ BIT(15) | BIT(14) | BIT(13) | BIT(12) | BIT(11)
+};
+
+static u8 rf_chnl_5g[RF_CHNL_NUM_5G] = {
+ 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108,
+ 112, 116, 120, 124, 128, 132, 136, 140
+};
+
+static u8 rf_chnl_5g_40m[RF_CHNL_NUM_5G_40M] = {
+ 38, 42, 46, 50, 54, 58, 62, 102, 106, 110, 114,
+ 118, 122, 126, 130, 134, 138
+};
+static u32 rf_reg_pram_c_5g[5][RF_REG_NUM_FOR_C_CUT_5G] = {
+ {0xE43BE, 0xFC638, 0x77C0A, 0xDE471, 0xd7110, 0x8EB04},
+ {0xE43BE, 0xFC078, 0xF7C1A, 0xE0C71, 0xD7550, 0xAEB04},
+ {0xE43BF, 0xFF038, 0xF7C0A, 0xDE471, 0xE5550, 0xAEB04},
+ {0xE43BF, 0xFF079, 0xF7C1A, 0xDE471, 0xE5550, 0xAEB04},
+ {0xE43BF, 0xFF038, 0xF7C1A, 0xDE471, 0xd7550, 0xAEB04}
+};
+
+static u32 rf_reg_param_for_c_cut_2g[3][RF_REG_NUM_FOR_C_CUT_2G] = {
+ {0x643BC, 0xFC038, 0x77C1A, 0x41289, 0x01840},
+ {0x643BC, 0xFC038, 0x07C1A, 0x41289, 0x01840},
+ {0x243BC, 0xFC438, 0x07C1A, 0x4128B, 0x0FC41}
+};
+
+static u32 rf_syn_g4_for_c_cut_2g = 0xD1C31 & 0x7FF;
+
+static u32 rf_pram_c_5g_int_pa[3][RF_REG_NUM_FOR_C_CUT_5G_INTERNALPA] = {
+ {0x01a00, 0x40443, 0x00eb5, 0x89bec, 0x94a12, 0x94a12, 0x94a12},
+ {0x01800, 0xc0443, 0x00730, 0x896ee, 0x94a52, 0x94a52, 0x94a52},
+ {0x01800, 0xc0443, 0x00730, 0x896ee, 0x94a12, 0x94a12, 0x94a12}
+};
+
+/* [mode][patha+b][reg] */
+static u32 rf_imr_param_normal[1][3][MAX_RF_IMR_INDEX_NORMAL] = {
+ {
+ /* channel 1-14. */
+ {
+ 0x70000, 0x00ff0, 0x4400f, 0x00ff0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x64888, 0xe266c, 0x00090, 0x22fff
+ },
+ /* path 36-64 */
+ {
+ 0x70000, 0x22880, 0x4470f, 0x55880, 0x00070, 0x88000,
+ 0x0, 0x88080, 0x70000, 0x64a82, 0xe466c, 0x00090,
+ 0x32c9a
+ },
+ /* 100 -165 */
+ {
+ 0x70000, 0x44880, 0x4477f, 0x77880, 0x00070, 0x88000,
+ 0x0, 0x880b0, 0x0, 0x64b82, 0xe466c, 0x00090, 0x32c9a
+ }
+ }
+};
+
+static u32 curveindex_5g[TARGET_CHNL_NUM_5G] = {0};
+
+static u32 curveindex_2g[TARGET_CHNL_NUM_2G] = {0};
+
+static u32 targetchnl_5g[TARGET_CHNL_NUM_5G] = {
+ 25141, 25116, 25091, 25066, 25041,
+ 25016, 24991, 24966, 24941, 24917,
+ 24892, 24867, 24843, 24818, 24794,
+ 24770, 24765, 24721, 24697, 24672,
+ 24648, 24624, 24600, 24576, 24552,
+ 24528, 24504, 24480, 24457, 24433,
+ 24409, 24385, 24362, 24338, 24315,
+ 24291, 24268, 24245, 24221, 24198,
+ 24175, 24151, 24128, 24105, 24082,
+ 24059, 24036, 24013, 23990, 23967,
+ 23945, 23922, 23899, 23876, 23854,
+ 23831, 23809, 23786, 23764, 23741,
+ 23719, 23697, 23674, 23652, 23630,
+ 23608, 23586, 23564, 23541, 23519,
+ 23498, 23476, 23454, 23432, 23410,
+ 23388, 23367, 23345, 23323, 23302,
+ 23280, 23259, 23237, 23216, 23194,
+ 23173, 23152, 23130, 23109, 23088,
+ 23067, 23046, 23025, 23003, 22982,
+ 22962, 22941, 22920, 22899, 22878,
+ 22857, 22837, 22816, 22795, 22775,
+ 22754, 22733, 22713, 22692, 22672,
+ 22652, 22631, 22611, 22591, 22570,
+ 22550, 22530, 22510, 22490, 22469,
+ 22449, 22429, 22409, 22390, 22370,
+ 22350, 22336, 22310, 22290, 22271,
+ 22251, 22231, 22212, 22192, 22173,
+ 22153, 22134, 22114, 22095, 22075,
+ 22056, 22037, 22017, 21998, 21979,
+ 21960, 21941, 21921, 21902, 21883,
+ 21864, 21845, 21826, 21807, 21789,
+ 21770, 21751, 21732, 21713, 21695,
+ 21676, 21657, 21639, 21620, 21602,
+ 21583, 21565, 21546, 21528, 21509,
+ 21491, 21473, 21454, 21436, 21418,
+ 21400, 21381, 21363, 21345, 21327,
+ 21309, 21291, 21273, 21255, 21237,
+ 21219, 21201, 21183, 21166, 21148,
+ 21130, 21112, 21095, 21077, 21059,
+ 21042, 21024, 21007, 20989, 20972,
+ 25679, 25653, 25627, 25601, 25575,
+ 25549, 25523, 25497, 25471, 25446,
+ 25420, 25394, 25369, 25343, 25318,
+ 25292, 25267, 25242, 25216, 25191,
+ 25166
+};
+
+/* channel 1~14 */
+static u32 targetchnl_2g[TARGET_CHNL_NUM_2G] = {
+ 26084, 26030, 25976, 25923, 25869, 25816, 25764,
+ 25711, 25658, 25606, 25554, 25502, 25451, 25328
+};
+
+static u32 _rtl92d_phy_calculate_bit_shift(u32 bitmask)
+{
+ u32 i;
+
+ for (i = 0; i <= 31; i++) {
+ if (((bitmask >> i) & 0x1) == 1)
+ break;
+ }
+
+ return i;
+}
+
+u32 rtl92d_phy_query_bb_reg(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
+ u32 returnvalue, originalvalue, bitshift;
+ u8 dbi_direct;
+
+ RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("regaddr(%#x), "
+ "bitmask(%#x)\n", regaddr, bitmask));
+ if (rtlhal->during_mac1init_radioa || rtlhal->during_mac0init_radiob) {
+ /* mac1 use phy0 read radio_b. */
+ /* mac0 use phy1 read radio_b. */
+ if (rtlhal->during_mac1init_radioa)
+ dbi_direct = BIT(3);
+ else if (rtlhal->during_mac0init_radiob)
+ dbi_direct = BIT(3) | BIT(2);
+ originalvalue = rtl92de_read_dword_dbi(hw, (u16)regaddr,
+ dbi_direct);
+ } else {
+ originalvalue = rtl_read_dword(rtlpriv, regaddr);
+ }
+ bitshift = _rtl92d_phy_calculate_bit_shift(bitmask);
+ returnvalue = (originalvalue & bitmask) >> bitshift;
+ RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("BBR MASK=0x%x "
+ "Addr[0x%x]=0x%x\n", bitmask, regaddr, originalvalue));
+ return returnvalue;
+}
+
+void rtl92d_phy_set_bb_reg(struct ieee80211_hw *hw,
+ u32 regaddr, u32 bitmask, u32 data)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
+ u8 dbi_direct = 0;
+ u32 originalvalue, bitshift;
+
+ RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("regaddr(%#x), bitmask(%#x),"
+ " data(%#x)\n", regaddr, bitmask, data));
+ if (rtlhal->during_mac1init_radioa)
+ dbi_direct = BIT(3);
+ else if (rtlhal->during_mac0init_radiob)
+ /* mac0 use phy1 write radio_b. */
+ dbi_direct = BIT(3) | BIT(2);
+ if (bitmask != BMASKDWORD) {
+ if (rtlhal->during_mac1init_radioa ||
+ rtlhal->during_mac0init_radiob)
+ originalvalue = rtl92de_read_dword_dbi(hw,
+ (u16) regaddr,
+ dbi_direct);
+ else
+ originalvalue = rtl_read_dword(rtlpriv, regaddr);
+ bitshift = _rtl92d_phy_calculate_bit_shift(bitmask);
+ data = ((originalvalue & (~bitmask)) | (data << bitshift));
+ }
+ if (rtlhal->during_mac1init_radioa || rtlhal->during_mac0init_radiob)
+ rtl92de_write_dword_dbi(hw, (u16) regaddr, data, dbi_direct);
+ else
+ rtl_write_dword(rtlpriv, regaddr, data);
+ RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("regaddr(%#x), bitmask(%#x),"
+ " data(%#x)\n", regaddr, bitmask, data));
+}
+
+static u32 _rtl92d_phy_rf_serial_read(struct ieee80211_hw *hw,
+ enum radio_path rfpath, u32 offset)
+{
+
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ struct bb_reg_def *pphyreg = &rtlphy->phyreg_def[rfpath];
+ u32 newoffset;
+ u32 tmplong, tmplong2;
+ u8 rfpi_enable = 0;
+ u32 retvalue;
+
+ newoffset = offset;
+ tmplong = rtl_get_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2, BMASKDWORD);
+ if (rfpath == RF90_PATH_A)
+ tmplong2 = tmplong;
+ else
+ tmplong2 = rtl_get_bbreg(hw, pphyreg->rfhssi_para2, BMASKDWORD);
+ tmplong2 = (tmplong2 & (~BLSSIREADADDRESS)) |
+ (newoffset << 23) | BLSSIREADEDGE;
+ rtl_set_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2, BMASKDWORD,
+ tmplong & (~BLSSIREADEDGE));
+ udelay(10);
+ rtl_set_bbreg(hw, pphyreg->rfhssi_para2, BMASKDWORD, tmplong2);
+ udelay(50);
+ udelay(50);
+ rtl_set_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2, BMASKDWORD,
+ tmplong | BLSSIREADEDGE);
+ udelay(10);
+ if (rfpath == RF90_PATH_A)
+ rfpi_enable = (u8) rtl_get_bbreg(hw, RFPGA0_XA_HSSIPARAMETER1,
+ BIT(8));
+ else if (rfpath == RF90_PATH_B)
+ rfpi_enable = (u8) rtl_get_bbreg(hw, RFPGA0_XB_HSSIPARAMETER1,
+ BIT(8));
+ if (rfpi_enable)
+ retvalue = rtl_get_bbreg(hw, pphyreg->rflssi_readbackpi,
+ BLSSIREADBACKDATA);
+ else
+ retvalue = rtl_get_bbreg(hw, pphyreg->rflssi_readback,
+ BLSSIREADBACKDATA);
+ RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("RFR-%d Addr[0x%x] = 0x%x\n",
+ rfpath, pphyreg->rflssi_readback, retvalue));
+ return retvalue;
+}
+
+static void _rtl92d_phy_rf_serial_write(struct ieee80211_hw *hw,
+ enum radio_path rfpath,
+ u32 offset, u32 data)
+{
+ u32 data_and_addr;
+ u32 newoffset;
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ struct bb_reg_def *pphyreg = &rtlphy->phyreg_def[rfpath];
+
+ newoffset = offset;
+ /* T65 RF */
+ data_and_addr = ((newoffset << 20) | (data & 0x000fffff)) & 0x0fffffff;
+ rtl_set_bbreg(hw, pphyreg->rf3wire_offset, BMASKDWORD, data_and_addr);
+ RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("RFW-%d Addr[0x%x]=0x%x\n",
+ rfpath, pphyreg->rf3wire_offset, data_and_addr));
+}
+
+u32 rtl92d_phy_query_rf_reg(struct ieee80211_hw *hw,
+ enum radio_path rfpath, u32 regaddr, u32 bitmask)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u32 original_value, readback_value, bitshift;
+ unsigned long flags;
+
+ RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("regaddr(%#x), "
+ "rfpath(%#x), bitmask(%#x)\n",
+ regaddr, rfpath, bitmask));
+ spin_lock_irqsave(&rtlpriv->locks.rf_lock, flags);
+ original_value = _rtl92d_phy_rf_serial_read(hw, rfpath, regaddr);
+ bitshift = _rtl92d_phy_calculate_bit_shift(bitmask);
+ readback_value = (original_value & bitmask) >> bitshift;
+ spin_unlock_irqrestore(&rtlpriv->locks.rf_lock, flags);
+ RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("regaddr(%#x), rfpath(%#x), "
+ "bitmask(%#x), original_value(%#x)\n",
+ regaddr, rfpath, bitmask, original_value));
+ return readback_value;
+}
+
+void rtl92d_phy_set_rf_reg(struct ieee80211_hw *hw, enum radio_path rfpath,
+ u32 regaddr, u32 bitmask, u32 data)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ u32 original_value, bitshift;
+ unsigned long flags;
+
+ RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
+ ("regaddr(%#x), bitmask(%#x), data(%#x), rfpath(%#x)\n",
+ regaddr, bitmask, data, rfpath));
+ if (bitmask == 0)
+ return;
+ spin_lock_irqsave(&rtlpriv->locks.rf_lock, flags);
+ if (rtlphy->rf_mode != RF_OP_BY_FW) {
+ if (bitmask != BRFREGOFFSETMASK) {
+ original_value = _rtl92d_phy_rf_serial_read(hw,
+ rfpath, regaddr);
+ bitshift = _rtl92d_phy_calculate_bit_shift(bitmask);
+ data = ((original_value & (~bitmask)) |
+ (data << bitshift));
+ }
+ _rtl92d_phy_rf_serial_write(hw, rfpath, regaddr, data);
+ }
+ spin_unlock_irqrestore(&rtlpriv->locks.rf_lock, flags);
+ RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("regaddr(%#x), "
+ "bitmask(%#x), data(%#x), rfpath(%#x)\n",
+ regaddr, bitmask, data, rfpath));
+}
+
+bool rtl92d_phy_mac_config(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u32 i;
+ u32 arraylength;
+ u32 *ptrarray;
+
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, ("Read Rtl819XMACPHY_Array\n"));
+ arraylength = MAC_2T_ARRAYLENGTH;
+ ptrarray = rtl8192de_mac_2tarray;
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, ("Img:Rtl819XMAC_Array\n"));
+ for (i = 0; i < arraylength; i = i + 2)
+ rtl_write_byte(rtlpriv, ptrarray[i], (u8) ptrarray[i + 1]);
+ if (rtlpriv->rtlhal.macphymode == SINGLEMAC_SINGLEPHY) {
+ /* improve 2-stream TX EVM */
+ /* rtl_write_byte(rtlpriv, 0x14,0x71); */
+ /* AMPDU aggregation number 9 */
+ /* rtl_write_word(rtlpriv, REG_MAX_AGGR_NUM, MAX_AGGR_NUM); */
+ rtl_write_byte(rtlpriv, REG_MAX_AGGR_NUM, 0x0B);
+ } else {
+ /* 92D need to test to decide the num. */
+ rtl_write_byte(rtlpriv, REG_MAX_AGGR_NUM, 0x07);
+ }
+ return true;
+}
+
+static void _rtl92d_phy_init_bb_rf_register_definition(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+
+ /* RF Interface Sowrtware Control */
+ /* 16 LSBs if read 32-bit from 0x870 */
+ rtlphy->phyreg_def[RF90_PATH_A].rfintfs = RFPGA0_XAB_RFINTERFACESW;
+ /* 16 MSBs if read 32-bit from 0x870 (16-bit for 0x872) */
+ rtlphy->phyreg_def[RF90_PATH_B].rfintfs = RFPGA0_XAB_RFINTERFACESW;
+ /* 16 LSBs if read 32-bit from 0x874 */
+ rtlphy->phyreg_def[RF90_PATH_C].rfintfs = RFPGA0_XCD_RFINTERFACESW;
+ /* 16 MSBs if read 32-bit from 0x874 (16-bit for 0x876) */
+
+ rtlphy->phyreg_def[RF90_PATH_D].rfintfs = RFPGA0_XCD_RFINTERFACESW;
+ /* RF Interface Readback Value */
+ /* 16 LSBs if read 32-bit from 0x8E0 */
+ rtlphy->phyreg_def[RF90_PATH_A].rfintfi = RFPGA0_XAB_RFINTERFACERB;
+ /* 16 MSBs if read 32-bit from 0x8E0 (16-bit for 0x8E2) */
+ rtlphy->phyreg_def[RF90_PATH_B].rfintfi = RFPGA0_XAB_RFINTERFACERB;
+ /* 16 LSBs if read 32-bit from 0x8E4 */
+ rtlphy->phyreg_def[RF90_PATH_C].rfintfi = RFPGA0_XCD_RFINTERFACERB;
+ /* 16 MSBs if read 32-bit from 0x8E4 (16-bit for 0x8E6) */
+ rtlphy->phyreg_def[RF90_PATH_D].rfintfi = RFPGA0_XCD_RFINTERFACERB;
+
+ /* RF Interface Output (and Enable) */
+ /* 16 LSBs if read 32-bit from 0x860 */
+ rtlphy->phyreg_def[RF90_PATH_A].rfintfo = RFPGA0_XA_RFINTERFACEOE;
+ /* 16 LSBs if read 32-bit from 0x864 */
+ rtlphy->phyreg_def[RF90_PATH_B].rfintfo = RFPGA0_XB_RFINTERFACEOE;
+
+ /* RF Interface (Output and) Enable */
+ /* 16 MSBs if read 32-bit from 0x860 (16-bit for 0x862) */
+ rtlphy->phyreg_def[RF90_PATH_A].rfintfe = RFPGA0_XA_RFINTERFACEOE;
+ /* 16 MSBs if read 32-bit from 0x864 (16-bit for 0x866) */
+ rtlphy->phyreg_def[RF90_PATH_B].rfintfe = RFPGA0_XB_RFINTERFACEOE;
+
+ /* Addr of LSSI. Wirte RF register by driver */
+ /* LSSI Parameter */
+ rtlphy->phyreg_def[RF90_PATH_A].rf3wire_offset =
+ RFPGA0_XA_LSSIPARAMETER;
+ rtlphy->phyreg_def[RF90_PATH_B].rf3wire_offset =
+ RFPGA0_XB_LSSIPARAMETER;
+
+ /* RF parameter */
+ /* BB Band Select */
+ rtlphy->phyreg_def[RF90_PATH_A].rflssi_select = RFPGA0_XAB_RFPARAMETER;
+ rtlphy->phyreg_def[RF90_PATH_B].rflssi_select = RFPGA0_XAB_RFPARAMETER;
+ rtlphy->phyreg_def[RF90_PATH_C].rflssi_select = RFPGA0_XCD_RFPARAMETER;
+ rtlphy->phyreg_def[RF90_PATH_D].rflssi_select = RFPGA0_XCD_RFPARAMETER;
+
+ /* Tx AGC Gain Stage (same for all path. Should we remove this?) */
+ /* Tx gain stage */
+ rtlphy->phyreg_def[RF90_PATH_A].rftxgain_stage = RFPGA0_TXGAINSTAGE;
+ /* Tx gain stage */
+ rtlphy->phyreg_def[RF90_PATH_B].rftxgain_stage = RFPGA0_TXGAINSTAGE;
+ /* Tx gain stage */
+ rtlphy->phyreg_def[RF90_PATH_C].rftxgain_stage = RFPGA0_TXGAINSTAGE;
+ /* Tx gain stage */
+ rtlphy->phyreg_def[RF90_PATH_D].rftxgain_stage = RFPGA0_TXGAINSTAGE;
+
+ /* Tranceiver A~D HSSI Parameter-1 */
+ /* wire control parameter1 */
+ rtlphy->phyreg_def[RF90_PATH_A].rfhssi_para1 = RFPGA0_XA_HSSIPARAMETER1;
+ /* wire control parameter1 */
+ rtlphy->phyreg_def[RF90_PATH_B].rfhssi_para1 = RFPGA0_XB_HSSIPARAMETER1;
+
+ /* Tranceiver A~D HSSI Parameter-2 */
+ /* wire control parameter2 */
+ rtlphy->phyreg_def[RF90_PATH_A].rfhssi_para2 = RFPGA0_XA_HSSIPARAMETER2;
+ /* wire control parameter2 */
+ rtlphy->phyreg_def[RF90_PATH_B].rfhssi_para2 = RFPGA0_XB_HSSIPARAMETER2;
+
+ /* RF switch Control */
+ /* TR/Ant switch control */
+ rtlphy->phyreg_def[RF90_PATH_A].rfswitch_control =
+ RFPGA0_XAB_SWITCHCONTROL;
+ rtlphy->phyreg_def[RF90_PATH_B].rfswitch_control =
+ RFPGA0_XAB_SWITCHCONTROL;
+ rtlphy->phyreg_def[RF90_PATH_C].rfswitch_control =
+ RFPGA0_XCD_SWITCHCONTROL;
+ rtlphy->phyreg_def[RF90_PATH_D].rfswitch_control =
+ RFPGA0_XCD_SWITCHCONTROL;
+
+ /* AGC control 1 */
+ rtlphy->phyreg_def[RF90_PATH_A].rfagc_control1 = ROFDM0_XAAGCCORE1;
+ rtlphy->phyreg_def[RF90_PATH_B].rfagc_control1 = ROFDM0_XBAGCCORE1;
+ rtlphy->phyreg_def[RF90_PATH_C].rfagc_control1 = ROFDM0_XCAGCCORE1;
+ rtlphy->phyreg_def[RF90_PATH_D].rfagc_control1 = ROFDM0_XDAGCCORE1;
+
+ /* AGC control 2 */
+ rtlphy->phyreg_def[RF90_PATH_A].rfagc_control2 = ROFDM0_XAAGCCORE2;
+ rtlphy->phyreg_def[RF90_PATH_B].rfagc_control2 = ROFDM0_XBAGCCORE2;
+ rtlphy->phyreg_def[RF90_PATH_C].rfagc_control2 = ROFDM0_XCAGCCORE2;
+ rtlphy->phyreg_def[RF90_PATH_D].rfagc_control2 = ROFDM0_XDAGCCORE2;
+
+ /* RX AFE control 1 */
+ rtlphy->phyreg_def[RF90_PATH_A].rfrxiq_imbalance =
+ ROFDM0_XARXIQIMBALANCE;
+ rtlphy->phyreg_def[RF90_PATH_B].rfrxiq_imbalance =
+ ROFDM0_XBRXIQIMBALANCE;
+ rtlphy->phyreg_def[RF90_PATH_C].rfrxiq_imbalance =
+ ROFDM0_XCRXIQIMBALANCE;
+ rtlphy->phyreg_def[RF90_PATH_D].rfrxiq_imbalance =
+ ROFDM0_XDRXIQIMBALANCE;
+
+ /*RX AFE control 1 */
+ rtlphy->phyreg_def[RF90_PATH_A].rfrx_afe = ROFDM0_XARXAFE;
+ rtlphy->phyreg_def[RF90_PATH_B].rfrx_afe = ROFDM0_XBRXAFE;
+ rtlphy->phyreg_def[RF90_PATH_C].rfrx_afe = ROFDM0_XCRXAFE;
+ rtlphy->phyreg_def[RF90_PATH_D].rfrx_afe = ROFDM0_XDRXAFE;
+
+ /* Tx AFE control 1 */
+ rtlphy->phyreg_def[RF90_PATH_A].rftxiq_imbalance =
+ ROFDM0_XATxIQIMBALANCE;
+ rtlphy->phyreg_def[RF90_PATH_B].rftxiq_imbalance =
+ ROFDM0_XBTxIQIMBALANCE;
+ rtlphy->phyreg_def[RF90_PATH_C].rftxiq_imbalance =
+ ROFDM0_XCTxIQIMBALANCE;
+ rtlphy->phyreg_def[RF90_PATH_D].rftxiq_imbalance =
+ ROFDM0_XDTxIQIMBALANCE;
+
+ /* Tx AFE control 2 */
+ rtlphy->phyreg_def[RF90_PATH_A].rftx_afe = ROFDM0_XATxAFE;
+ rtlphy->phyreg_def[RF90_PATH_B].rftx_afe = ROFDM0_XBTxAFE;
+ rtlphy->phyreg_def[RF90_PATH_C].rftx_afe = ROFDM0_XCTxAFE;
+ rtlphy->phyreg_def[RF90_PATH_D].rftx_afe = ROFDM0_XDTxAFE;
+
+ /* Tranceiver LSSI Readback SI mode */
+ rtlphy->phyreg_def[RF90_PATH_A].rflssi_readback =
+ RFPGA0_XA_LSSIREADBACK;
+ rtlphy->phyreg_def[RF90_PATH_B].rflssi_readback =
+ RFPGA0_XB_LSSIREADBACK;
+ rtlphy->phyreg_def[RF90_PATH_C].rflssi_readback =
+ RFPGA0_XC_LSSIREADBACK;
+ rtlphy->phyreg_def[RF90_PATH_D].rflssi_readback =
+ RFPGA0_XD_LSSIREADBACK;
+
+ /* Tranceiver LSSI Readback PI mode */
+ rtlphy->phyreg_def[RF90_PATH_A].rflssi_readbackpi =
+ TRANSCEIVERA_HSPI_READBACK;
+ rtlphy->phyreg_def[RF90_PATH_B].rflssi_readbackpi =
+ TRANSCEIVERB_HSPI_READBACK;
+}
+
+static bool _rtl92d_phy_config_bb_with_headerfile(struct ieee80211_hw *hw,
+ u8 configtype)
+{
+ int i;
+ u32 *phy_regarray_table;
+ u32 *agctab_array_table = NULL;
+ u32 *agctab_5garray_table;
+ u16 phy_reg_arraylen, agctab_arraylen = 0, agctab_5garraylen;
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+
+ /* Normal chip,Mac0 use AGC_TAB.txt for 2G and 5G band. */
+ if (rtlhal->interfaceindex == 0) {
+ agctab_arraylen = AGCTAB_ARRAYLENGTH;
+ agctab_array_table = rtl8192de_agctab_array;
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+ (" ===> phy:MAC0, Rtl819XAGCTAB_Array\n"));
+ } else {
+ if (rtlhal->current_bandtype == BAND_ON_2_4G) {
+ agctab_arraylen = AGCTAB_2G_ARRAYLENGTH;
+ agctab_array_table = rtl8192de_agctab_2garray;
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+ (" ===> phy:MAC1, Rtl819XAGCTAB_2GArray\n"));
+ } else {
+ agctab_5garraylen = AGCTAB_5G_ARRAYLENGTH;
+ agctab_5garray_table = rtl8192de_agctab_5garray;
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+ (" ===> phy:MAC1, Rtl819XAGCTAB_5GArray\n"));
+
+ }
+ }
+ phy_reg_arraylen = PHY_REG_2T_ARRAYLENGTH;
+ phy_regarray_table = rtl8192de_phy_reg_2tarray;
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+ (" ===> phy:Rtl819XPHY_REG_Array_PG\n"));
+ if (configtype == BASEBAND_CONFIG_PHY_REG) {
+ for (i = 0; i < phy_reg_arraylen; i = i + 2) {
+ if (phy_regarray_table[i] == 0xfe)
+ mdelay(50);
+ else if (phy_regarray_table[i] == 0xfd)
+ mdelay(5);
+ else if (phy_regarray_table[i] == 0xfc)
+ mdelay(1);
+ else if (phy_regarray_table[i] == 0xfb)
+ udelay(50);
+ else if (phy_regarray_table[i] == 0xfa)
+ udelay(5);
+ else if (phy_regarray_table[i] == 0xf9)
+ udelay(1);
+ rtl_set_bbreg(hw, phy_regarray_table[i], BMASKDWORD,
+ phy_regarray_table[i + 1]);
+ udelay(1);
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+ ("The phy_regarray_table[0] is %x"
+ " Rtl819XPHY_REGArray[1] is %x\n",
+ phy_regarray_table[i],
+ phy_regarray_table[i + 1]));
+ }
+ } else if (configtype == BASEBAND_CONFIG_AGC_TAB) {
+ if (rtlhal->interfaceindex == 0) {
+ for (i = 0; i < agctab_arraylen; i = i + 2) {
+ rtl_set_bbreg(hw, agctab_array_table[i],
+ BMASKDWORD,
+ agctab_array_table[i + 1]);
+ /* Add 1us delay between BB/RF register
+ * setting. */
+ udelay(1);
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+ ("The Rtl819XAGCTAB_Array_"
+ "Table[0] is %ul "
+ "Rtl819XPHY_REGArray[1] is %ul\n",
+ agctab_array_table[i],
+ agctab_array_table[i + 1]));
+ }
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+ ("Normal Chip, MAC0, load "
+ "Rtl819XAGCTAB_Array\n"));
+ } else {
+ if (rtlhal->current_bandtype == BAND_ON_2_4G) {
+ for (i = 0; i < agctab_arraylen; i = i + 2) {
+ rtl_set_bbreg(hw, agctab_array_table[i],
+ BMASKDWORD,
+ agctab_array_table[i + 1]);
+ /* Add 1us delay between BB/RF register
+ * setting. */
+ udelay(1);
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+ ("The Rtl819XAGCTAB_Array_"
+ "Table[0] is %ul Rtl819XPHY_"
+ "REGArray[1] is %ul\n",
+ agctab_array_table[i],
+ agctab_array_table[i + 1]));
+ }
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+ ("Load Rtl819XAGCTAB_2GArray\n"));
+ } else {
+ for (i = 0; i < agctab_5garraylen; i = i + 2) {
+ rtl_set_bbreg(hw,
+ agctab_5garray_table[i],
+ BMASKDWORD,
+ agctab_5garray_table[i + 1]);
+ /* Add 1us delay between BB/RF registeri
+ * setting. */
+ udelay(1);
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+ ("The Rtl819XAGCTAB_5GArray_"
+ "Table[0] is %ul Rtl819XPHY_"
+ "REGArray[1] is %ul\n",
+ agctab_5garray_table[i],
+ agctab_5garray_table[i + 1]));
+ }
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+ ("Load Rtl819XAGCTAB_5GArray\n"));
+ }
+ }
+ }
+ return true;
+}
+
+static void _rtl92d_store_pwrindex_diffrate_offset(struct ieee80211_hw *hw,
+ u32 regaddr, u32 bitmask,
+ u32 data)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+
+ if (regaddr == RTXAGC_A_RATE18_06) {
+ rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][0] =
+ data;
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+ ("MCSTxPowerLevelOriginalOffset[%d][0] = 0x%ulx\n",
+ rtlphy->pwrgroup_cnt,
+ rtlphy->mcs_txpwrlevel_origoffset
+ [rtlphy->pwrgroup_cnt][0]));
+ }
+ if (regaddr == RTXAGC_A_RATE54_24) {
+ rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][1] =
+ data;
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+ ("MCSTxPowerLevelOriginalOffset[%d][1] = 0x%ulx\n",
+ rtlphy->pwrgroup_cnt,
+ rtlphy->mcs_txpwrlevel_origoffset
+ [rtlphy->pwrgroup_cnt][1]));
+ }
+ if (regaddr == RTXAGC_A_CCK1_MCS32) {
+ rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][6] =
+ data;
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+ ("MCSTxPowerLevelOriginalOffset[%d][6] = 0x%ulx\n",
+ rtlphy->pwrgroup_cnt,
+ rtlphy->mcs_txpwrlevel_origoffset
+ [rtlphy->pwrgroup_cnt][6]));
+ }
+ if (regaddr == RTXAGC_B_CCK11_A_CCK2_11 && bitmask == 0xffffff00) {
+ rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][7] =
+ data;
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+ ("MCSTxPowerLevelOriginalOffset[%d][7] = 0x%ulx\n",
+ rtlphy->pwrgroup_cnt,
+ rtlphy->mcs_txpwrlevel_origoffset
+ [rtlphy->pwrgroup_cnt][7]));
+ }
+ if (regaddr == RTXAGC_A_MCS03_MCS00) {
+ rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][2] =
+ data;
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+ ("MCSTxPowerLevelOriginalOffset[%d][2] = 0x%ulx\n",
+ rtlphy->pwrgroup_cnt,
+ rtlphy->mcs_txpwrlevel_origoffset
+ [rtlphy->pwrgroup_cnt][2]));
+ }
+ if (regaddr == RTXAGC_A_MCS07_MCS04) {
+ rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][3] =
+ data;
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+ ("MCSTxPowerLevelOriginalOffset[%d][3] = 0x%ulx\n",
+ rtlphy->pwrgroup_cnt,
+ rtlphy->mcs_txpwrlevel_origoffset
+ [rtlphy->pwrgroup_cnt][3]));
+ }
+ if (regaddr == RTXAGC_A_MCS11_MCS08) {
+ rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][4] =
+ data;
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+ ("MCSTxPowerLevelOriginalOffset[%d][4] = 0x%ulx\n",
+ rtlphy->pwrgroup_cnt,
+ rtlphy->mcs_txpwrlevel_origoffset
+ [rtlphy->pwrgroup_cnt][4]));
+ }
+ if (regaddr == RTXAGC_A_MCS15_MCS12) {
+ rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][5] =
+ data;
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+ ("MCSTxPowerLevelOriginalOffset[%d][5] = 0x%ulx\n",
+ rtlphy->pwrgroup_cnt,
+ rtlphy->mcs_txpwrlevel_origoffset
+ [rtlphy->pwrgroup_cnt][5]));
+ }
+ if (regaddr == RTXAGC_B_RATE18_06) {
+ rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][8] =
+ data;
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+ ("MCSTxPowerLevelOriginalOffset[%d][8] = 0x%ulx\n",
+ rtlphy->pwrgroup_cnt,
+ rtlphy->mcs_txpwrlevel_origoffset
+ [rtlphy->pwrgroup_cnt][8]));
+ }
+ if (regaddr == RTXAGC_B_RATE54_24) {
+ rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][9] =
+ data;
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+ ("MCSTxPowerLevelOriginalOffset[%d][9] = 0x%ulx\n",
+ rtlphy->pwrgroup_cnt,
+ rtlphy->mcs_txpwrlevel_origoffset
+ [rtlphy->pwrgroup_cnt][9]));
+ }
+ if (regaddr == RTXAGC_B_CCK1_55_MCS32) {
+ rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][14] =
+ data;
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+ ("MCSTxPowerLevelOriginalOffset[%d][14] = 0x%ulx\n",
+ rtlphy->pwrgroup_cnt,
+ rtlphy->mcs_txpwrlevel_origoffset
+ [rtlphy->pwrgroup_cnt][14]));
+ }
+ if (regaddr == RTXAGC_B_CCK11_A_CCK2_11 && bitmask == 0x000000ff) {
+ rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][15] =
+ data;
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+ ("MCSTxPowerLevelOriginalOffset[%d][15] = 0x%ulx\n",
+ rtlphy->pwrgroup_cnt,
+ rtlphy->mcs_txpwrlevel_origoffset
+ [rtlphy->pwrgroup_cnt][15]));
+ }
+ if (regaddr == RTXAGC_B_MCS03_MCS00) {
+ rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][10] =
+ data;
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+ ("MCSTxPowerLevelOriginalOffset[%d][10] = 0x%ulx\n",
+ rtlphy->pwrgroup_cnt,
+ rtlphy->mcs_txpwrlevel_origoffset
+ [rtlphy->pwrgroup_cnt][10]));
+ }
+ if (regaddr == RTXAGC_B_MCS07_MCS04) {
+ rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][11] =
+ data;
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+ ("MCSTxPowerLevelOriginalOffset[%d][11] = 0x%ulx\n",
+ rtlphy->pwrgroup_cnt,
+ rtlphy->mcs_txpwrlevel_origoffset
+ [rtlphy->pwrgroup_cnt][11]));
+ }
+ if (regaddr == RTXAGC_B_MCS11_MCS08) {
+ rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][12] =
+ data;
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+ ("MCSTxPowerLevelOriginalOffset[%d][12] = 0x%ulx\n",
+ rtlphy->pwrgroup_cnt,
+ rtlphy->mcs_txpwrlevel_origoffset
+ [rtlphy->pwrgroup_cnt][12]));
+ }
+ if (regaddr == RTXAGC_B_MCS15_MCS12) {
+ rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][13] =
+ data;
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+ ("MCSTxPowerLevelOriginalOffset[%d][13] = 0x%ulx\n",
+ rtlphy->pwrgroup_cnt,
+ rtlphy->mcs_txpwrlevel_origoffset
+ [rtlphy->pwrgroup_cnt][13]));
+ rtlphy->pwrgroup_cnt++;
+ }
+}
+
+static bool _rtl92d_phy_config_bb_with_pgheaderfile(struct ieee80211_hw *hw,
+ u8 configtype)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ int i;
+ u32 *phy_regarray_table_pg;
+ u16 phy_regarray_pg_len;
+
+ phy_regarray_pg_len = PHY_REG_ARRAY_PG_LENGTH;
+ phy_regarray_table_pg = rtl8192de_phy_reg_array_pg;
+ if (configtype == BASEBAND_CONFIG_PHY_REG) {
+ for (i = 0; i < phy_regarray_pg_len; i = i + 3) {
+ if (phy_regarray_table_pg[i] == 0xfe)
+ mdelay(50);
+ else if (phy_regarray_table_pg[i] == 0xfd)
+ mdelay(5);
+ else if (phy_regarray_table_pg[i] == 0xfc)
+ mdelay(1);
+ else if (phy_regarray_table_pg[i] == 0xfb)
+ udelay(50);
+ else if (phy_regarray_table_pg[i] == 0xfa)
+ udelay(5);
+ else if (phy_regarray_table_pg[i] == 0xf9)
+ udelay(1);
+ _rtl92d_store_pwrindex_diffrate_offset(hw,
+ phy_regarray_table_pg[i],
+ phy_regarray_table_pg[i + 1],
+ phy_regarray_table_pg[i + 2]);
+ }
+ } else {
+ RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE,
+ ("configtype != BaseBand_Config_PHY_REG\n"));
+ }
+ return true;
+}
+
+static bool _rtl92d_phy_bb_config(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+ bool rtstatus = true;
+
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, ("==>\n"));
+ rtstatus = _rtl92d_phy_config_bb_with_headerfile(hw,
+ BASEBAND_CONFIG_PHY_REG);
+ if (rtstatus != true) {
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("Write BB Reg Fail!!"));
+ return false;
+ }
+
+ /* if (rtlphy->rf_type == RF_1T2R) {
+ * _rtl92c_phy_bb_config_1t(hw);
+ * RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, ("Config to 1T!!\n"));
+ *} */
+
+ if (rtlefuse->autoload_failflag == false) {
+ rtlphy->pwrgroup_cnt = 0;
+ rtstatus = _rtl92d_phy_config_bb_with_pgheaderfile(hw,
+ BASEBAND_CONFIG_PHY_REG);
+ }
+ if (rtstatus != true) {
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("BB_PG Reg Fail!!"));
+ return false;
+ }
+ rtstatus = _rtl92d_phy_config_bb_with_headerfile(hw,
+ BASEBAND_CONFIG_AGC_TAB);
+ if (rtstatus != true) {
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("AGC Table Fail\n"));
+ return false;
+ }
+ rtlphy->cck_high_power = (bool) (rtl_get_bbreg(hw,
+ RFPGA0_XA_HSSIPARAMETER2, 0x200));
+
+ return true;
+}
+
+bool rtl92d_phy_bb_config(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u16 regval;
+ u32 regvaldw;
+ u8 value;
+
+ _rtl92d_phy_init_bb_rf_register_definition(hw);
+ regval = rtl_read_word(rtlpriv, REG_SYS_FUNC_EN);
+ rtl_write_word(rtlpriv, REG_SYS_FUNC_EN,
+ regval | BIT(13) | BIT(0) | BIT(1));
+ rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL, 0x83);
+ rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL + 1, 0xdb);
+ /* 0x1f bit7 bit6 represent for mac0/mac1 driver ready */
+ value = rtl_read_byte(rtlpriv, REG_RF_CTRL);
+ rtl_write_byte(rtlpriv, REG_RF_CTRL, value | RF_EN | RF_RSTB |
+ RF_SDMRSTB);
+ rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, FEN_PPLL | FEN_PCIEA |
+ FEN_DIO_PCIE | FEN_BB_GLB_RSTn | FEN_BBRSTB);
+ rtl_write_byte(rtlpriv, REG_AFE_XTAL_CTRL + 1, 0x80);
+ if (!(IS_92D_SINGLEPHY(rtlpriv->rtlhal.version))) {
+ regvaldw = rtl_read_dword(rtlpriv, REG_LEDCFG0);
+ rtl_write_dword(rtlpriv, REG_LEDCFG0, regvaldw | BIT(23));
+ }
+
+ return _rtl92d_phy_bb_config(hw);
+}
+
+bool rtl92d_phy_rf_config(struct ieee80211_hw *hw)
+{
+ return rtl92d_phy_rf6052_config(hw);
+}
+
+bool rtl92d_phy_config_rf_with_headerfile(struct ieee80211_hw *hw,
+ enum rf_content content,
+ enum radio_path rfpath)
+{
+ int i, j;
+ u32 *radioa_array_table;
+ u32 *radiob_array_table;
+ u16 radioa_arraylen, radiob_arraylen;
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+ radioa_arraylen = RADIOA_2T_ARRAYLENGTH;
+ radioa_array_table = rtl8192de_radioa_2tarray;
+ radiob_arraylen = RADIOB_2T_ARRAYLENGTH;
+ radiob_array_table = rtl8192de_radiob_2tarray;
+ if (rtlpriv->efuse.internal_pa_5g[0]) {
+ radioa_arraylen = RADIOA_2T_INT_PA_ARRAYLENGTH;
+ radioa_array_table = rtl8192de_radioa_2t_int_paarray;
+ }
+ if (rtlpriv->efuse.internal_pa_5g[1]) {
+ radiob_arraylen = RADIOB_2T_INT_PA_ARRAYLENGTH;
+ radiob_array_table = rtl8192de_radiob_2t_int_paarray;
+ }
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+ ("PHY_ConfigRFWithHeaderFile() "
+ "Radio_A:Rtl819XRadioA_1TArray\n"));
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+ ("PHY_ConfigRFWithHeaderFile() "
+ "Radio_B:Rtl819XRadioB_1TArray\n"));
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, ("Radio No %x\n", rfpath));
+
+ /* this only happens when DMDP, mac0 start on 2.4G,
+ * mac1 start on 5G, mac 0 has to set phy0&phy1
+ * pathA or mac1 has to set phy0&phy1 pathA */
+ if ((content == radiob_txt) && (rfpath == RF90_PATH_A)) {
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+ (" ===> althougth Path A, we load radiob.txt\n"));
+ radioa_arraylen = radiob_arraylen;
+ radioa_array_table = radiob_array_table;
+ }
+ switch (rfpath) {
+ case RF90_PATH_A:
+ for (i = 0; i < radioa_arraylen; i = i + 2) {
+ if (radioa_array_table[i] == 0xfe) {
+ mdelay(50);
+ } else if (radioa_array_table[i] == 0xfd) {
+ /* delay_ms(5); */
+ for (j = 0; j < 100; j++)
+ udelay(MAX_STALL_TIME);
+ } else if (radioa_array_table[i] == 0xfc) {
+ /* delay_ms(1); */
+ for (j = 0; j < 20; j++)
+ udelay(MAX_STALL_TIME);
+
+ } else if (radioa_array_table[i] == 0xfb) {
+ udelay(50);
+ } else if (radioa_array_table[i] == 0xfa) {
+ udelay(5);
+ } else if (radioa_array_table[i] == 0xf9) {
+ udelay(1);
+ } else {
+ rtl_set_rfreg(hw, rfpath, radioa_array_table[i],
+ BRFREGOFFSETMASK,
+ radioa_array_table[i + 1]);
+ /* Add 1us delay between BB/RF register set. */
+ udelay(1);
+ }
+ }
+ break;
+ case RF90_PATH_B:
+ for (i = 0; i < radiob_arraylen; i = i + 2) {
+ if (radiob_array_table[i] == 0xfe) {
+ /* Delay specific ms. Only RF configuration
+ * requires delay. */
+ mdelay(50);
+ } else if (radiob_array_table[i] == 0xfd) {
+ /* delay_ms(5); */
+ for (j = 0; j < 100; j++)
+ udelay(MAX_STALL_TIME);
+ } else if (radiob_array_table[i] == 0xfc) {
+ /* delay_ms(1); */
+ for (j = 0; j < 20; j++)
+ udelay(MAX_STALL_TIME);
+ } else if (radiob_array_table[i] == 0xfb) {
+ udelay(50);
+ } else if (radiob_array_table[i] == 0xfa) {
+ udelay(5);
+ } else if (radiob_array_table[i] == 0xf9) {
+ udelay(1);
+ } else {
+ rtl_set_rfreg(hw, rfpath, radiob_array_table[i],
+ BRFREGOFFSETMASK,
+ radiob_array_table[i + 1]);
+ /* Add 1us delay between BB/RF register set. */
+ udelay(1);
+ }
+ }
+ break;
+ case RF90_PATH_C:
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+ ("switch case not process\n"));
+ break;
+ case RF90_PATH_D:
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+ ("switch case not process\n"));
+ break;
+ }
+ return true;
+}
+
+void rtl92d_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+
+ rtlphy->default_initialgain[0] =
+ (u8) rtl_get_bbreg(hw, ROFDM0_XAAGCCORE1, BMASKBYTE0);
+ rtlphy->default_initialgain[1] =
+ (u8) rtl_get_bbreg(hw, ROFDM0_XBAGCCORE1, BMASKBYTE0);
+ rtlphy->default_initialgain[2] =
+ (u8) rtl_get_bbreg(hw, ROFDM0_XCAGCCORE1, BMASKBYTE0);
+ rtlphy->default_initialgain[3] =
+ (u8) rtl_get_bbreg(hw, ROFDM0_XDAGCCORE1, BMASKBYTE0);
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+ ("Default initial gain (c50=0x%x, "
+ "c58=0x%x, c60=0x%x, c68=0x%x\n",
+ rtlphy->default_initialgain[0],
+ rtlphy->default_initialgain[1],
+ rtlphy->default_initialgain[2],
+ rtlphy->default_initialgain[3]));
+ rtlphy->framesync = (u8)rtl_get_bbreg(hw, ROFDM0_RXDETECTOR3,
+ BMASKBYTE0);
+ rtlphy->framesync_c34 = rtl_get_bbreg(hw, ROFDM0_RXDETECTOR2,
+ BMASKDWORD);
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+ ("Default framesync (0x%x) = 0x%x\n",
+ ROFDM0_RXDETECTOR3, rtlphy->framesync));
+}
+
+static void _rtl92d_get_txpower_index(struct ieee80211_hw *hw, u8 channel,
+ u8 *cckpowerlevel, u8 *ofdmpowerlevel)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ struct rtl_hal *rtlhal = &(rtlpriv->rtlhal);
+ struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+ u8 index = (channel - 1);
+
+ /* 1. CCK */
+ if (rtlhal->current_bandtype == BAND_ON_2_4G) {
+ /* RF-A */
+ cckpowerlevel[RF90_PATH_A] =
+ rtlefuse->txpwrlevel_cck[RF90_PATH_A][index];
+ /* RF-B */
+ cckpowerlevel[RF90_PATH_B] =
+ rtlefuse->txpwrlevel_cck[RF90_PATH_B][index];
+ } else {
+ cckpowerlevel[RF90_PATH_A] = 0;
+ cckpowerlevel[RF90_PATH_B] = 0;
+ }
+ /* 2. OFDM for 1S or 2S */
+ if (rtlphy->rf_type == RF_1T2R || rtlphy->rf_type == RF_1T1R) {
+ /* Read HT 40 OFDM TX power */
+ ofdmpowerlevel[RF90_PATH_A] =
+ rtlefuse->txpwrlevel_ht40_1s[RF90_PATH_A][index];
+ ofdmpowerlevel[RF90_PATH_B] =
+ rtlefuse->txpwrlevel_ht40_1s[RF90_PATH_B][index];
+ } else if (rtlphy->rf_type == RF_2T2R) {
+ /* Read HT 40 OFDM TX power */
+ ofdmpowerlevel[RF90_PATH_A] =
+ rtlefuse->txpwrlevel_ht40_2s[RF90_PATH_A][index];
+ ofdmpowerlevel[RF90_PATH_B] =
+ rtlefuse->txpwrlevel_ht40_2s[RF90_PATH_B][index];
+ }
+}
+
+static void _rtl92d_ccxpower_index_check(struct ieee80211_hw *hw,
+ u8 channel, u8 *cckpowerlevel, u8 *ofdmpowerlevel)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+
+ rtlphy->cur_cck_txpwridx = cckpowerlevel[0];
+ rtlphy->cur_ofdm24g_txpwridx = ofdmpowerlevel[0];
+}
+
+static u8 _rtl92c_phy_get_rightchnlplace(u8 chnl)
+{
+ u8 channel_5g[59] = {
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58,
+ 60, 62, 64, 100, 102, 104, 106, 108, 110, 112,
+ 114, 116, 118, 120, 122, 124, 126, 128,
+ 130, 132, 134, 136, 138, 140, 149, 151,
+ 153, 155, 157, 159, 161, 163, 165
+ };
+ u8 place = chnl;
+
+ if (chnl > 14) {
+ for (place = 14; place < sizeof(channel_5g); place++) {
+ if (channel_5g[place] == chnl) {
+ place++;
+ break;
+ }
+ }
+ }
+ return place;
+}
+
+void rtl92d_phy_set_txpower_level(struct ieee80211_hw *hw, u8 channel)
+{
+ struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u8 cckpowerlevel[2], ofdmpowerlevel[2];
+
+ if (rtlefuse->txpwr_fromeprom == false)
+ return;
+ channel = _rtl92c_phy_get_rightchnlplace(channel);
+ _rtl92d_get_txpower_index(hw, channel, &cckpowerlevel[0],
+ &ofdmpowerlevel[0]);
+ if (rtlpriv->rtlhal.current_bandtype == BAND_ON_2_4G)
+ _rtl92d_ccxpower_index_check(hw, channel, &cckpowerlevel[0],
+ &ofdmpowerlevel[0]);
+ if (rtlpriv->rtlhal.current_bandtype == BAND_ON_2_4G)
+ rtl92d_phy_rf6052_set_cck_txpower(hw, &cckpowerlevel[0]);
+ rtl92d_phy_rf6052_set_ofdm_txpower(hw, &ofdmpowerlevel[0], channel);
+}
+
+void rtl92d_phy_scan_operation_backup(struct ieee80211_hw *hw, u8 operation)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+ enum io_type iotype;
+
+ if (!is_hal_stop(rtlhal)) {
+ switch (operation) {
+ case SCAN_OPT_BACKUP:
+ rtlhal->current_bandtypebackup =
+ rtlhal->current_bandtype;
+ iotype = IO_CMD_PAUSE_DM_BY_SCAN;
+ rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_IO_CMD,
+ (u8 *)&iotype);
+ break;
+ case SCAN_OPT_RESTORE:
+ iotype = IO_CMD_RESUME_DM_BY_SCAN;
+ rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_IO_CMD,
+ (u8 *)&iotype);
+ break;
+ default:
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+ ("Unknown Scan Backup operation.\n"));
+ break;
+ }
+ }
+}
+
+void rtl92d_phy_set_bw_mode(struct ieee80211_hw *hw,
+ enum nl80211_channel_type ch_type)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+ struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+ unsigned long flag = 0;
+ u8 reg_prsr_rsc;
+ u8 reg_bw_opmode;
+
+ if (rtlphy->set_bwmode_inprogress)
+ return;
+ if ((is_hal_stop(rtlhal)) || (RT_CANNOT_IO(hw))) {
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
+ ("FALSE driver sleep or unload\n"));
+ return;
+ }
+ rtlphy->set_bwmode_inprogress = true;
+ RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE,
+ ("Switch to %s bandwidth\n",
+ rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20 ?
+ "20MHz" : "40MHz"));
+ reg_bw_opmode = rtl_read_byte(rtlpriv, REG_BWOPMODE);
+ reg_prsr_rsc = rtl_read_byte(rtlpriv, REG_RRSR + 2);
+ switch (rtlphy->current_chan_bw) {
+ case HT_CHANNEL_WIDTH_20:
+ reg_bw_opmode |= BW_OPMODE_20MHZ;
+ rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode);
+ break;
+ case HT_CHANNEL_WIDTH_20_40:
+ reg_bw_opmode &= ~BW_OPMODE_20MHZ;
+ rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode);
+
+ reg_prsr_rsc = (reg_prsr_rsc & 0x90) |
+ (mac->cur_40_prime_sc << 5);
+ rtl_write_byte(rtlpriv, REG_RRSR + 2, reg_prsr_rsc);
+ break;
+ default:
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+ ("unknown bandwidth: %#X\n", rtlphy->current_chan_bw));
+ break;
+ }
+ switch (rtlphy->current_chan_bw) {
+ case HT_CHANNEL_WIDTH_20:
+ rtl_set_bbreg(hw, RFPGA0_RFMOD, BRFMOD, 0x0);
+ rtl_set_bbreg(hw, RFPGA1_RFMOD, BRFMOD, 0x0);
+ /* SET BIT10 BIT11 for receive cck */
+ rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10) |
+ BIT(11), 3);
+ break;
+ case HT_CHANNEL_WIDTH_20_40:
+ rtl_set_bbreg(hw, RFPGA0_RFMOD, BRFMOD, 0x1);
+ rtl_set_bbreg(hw, RFPGA1_RFMOD, BRFMOD, 0x1);
+ /* Set Control channel to upper or lower.
+ * These settings are required only for 40MHz */
+ if (rtlhal->current_bandtype == BAND_ON_2_4G) {
+ rtl92d_acquire_cckandrw_pagea_ctl(hw, &flag);
+ rtl_set_bbreg(hw, RCCK0_SYSTEM, BCCKSIDEBAND,
+ (mac->cur_40_prime_sc >> 1));
+ rtl92d_release_cckandrw_pagea_ctl(hw, &flag);
+ }
+ rtl_set_bbreg(hw, ROFDM1_LSTF, 0xC00, mac->cur_40_prime_sc);
+ /* SET BIT10 BIT11 for receive cck */
+ rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10) |
+ BIT(11), 0);
+ rtl_set_bbreg(hw, 0x818, (BIT(26) | BIT(27)),
+ (mac->cur_40_prime_sc ==
+ HAL_PRIME_CHNL_OFFSET_LOWER) ? 2 : 1);
+ break;
+ default:
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+ ("unknown bandwidth: %#X\n", rtlphy->current_chan_bw));
+ break;
+
+ }
+ rtl92d_phy_rf6052_set_bandwidth(hw, rtlphy->current_chan_bw);
+ rtlphy->set_bwmode_inprogress = false;
+ RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, ("<==\n"));
+}
+
+static void _rtl92d_phy_stop_trx_before_changeband(struct ieee80211_hw *hw)
+{
+ rtl_set_bbreg(hw, RFPGA0_RFMOD, BCCKEN, 0);
+ rtl_set_bbreg(hw, RFPGA0_RFMOD, BOFDMEN, 0);
+ rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE, BMASKBYTE0, 0x00);
+ rtl_set_bbreg(hw, ROFDM1_TRXPATHENABLE, BDWORD, 0x0);
+}
+
+static void rtl92d_phy_switch_wirelessband(struct ieee80211_hw *hw, u8 band)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+ u8 i, value8;
+
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("==>\n"));
+ rtlhal->bandset = band;
+ rtlhal->current_bandtype = band;
+ if (IS_92D_SINGLEPHY(rtlhal->version))
+ rtlhal->bandset = BAND_ON_BOTH;
+ /* stop RX/Tx */
+ _rtl92d_phy_stop_trx_before_changeband(hw);
+ /* reconfig BB/RF according to wireless mode */
+ if (rtlhal->current_bandtype == BAND_ON_2_4G) {
+ /* BB & RF Config */
+ RT_TRACE(rtlpriv, COMP_CMD, DBG_DMESG, ("====>2.4G\n"));
+ if (rtlhal->interfaceindex == 1)
+ _rtl92d_phy_config_bb_with_headerfile(hw,
+ BASEBAND_CONFIG_AGC_TAB);
+ } else {
+ /* 5G band */
+ RT_TRACE(rtlpriv, COMP_CMD, DBG_DMESG, ("====>5G\n"));
+ if (rtlhal->interfaceindex == 1)
+ _rtl92d_phy_config_bb_with_headerfile(hw,
+ BASEBAND_CONFIG_AGC_TAB);
+ }
+ rtl92d_update_bbrf_configuration(hw);
+ if (rtlhal->current_bandtype == BAND_ON_2_4G)
+ rtl_set_bbreg(hw, RFPGA0_RFMOD, BCCKEN, 0x1);
+ rtl_set_bbreg(hw, RFPGA0_RFMOD, BOFDMEN, 0x1);
+
+ /* 20M BW. */
+ /* rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10), 1); */
+ rtlhal->reloadtxpowerindex = true;
+ /* notice fw know band status 0x81[1]/0x53[1] = 0: 5G, 1: 2G */
+ if (rtlhal->current_bandtype == BAND_ON_2_4G) {
+ value8 = rtl_read_byte(rtlpriv, (rtlhal->interfaceindex ==
+ 0 ? REG_MAC0 : REG_MAC1));
+ value8 |= BIT(1);
+ rtl_write_byte(rtlpriv, (rtlhal->interfaceindex ==
+ 0 ? REG_MAC0 : REG_MAC1), value8);
+ } else {
+ value8 = rtl_read_byte(rtlpriv, (rtlhal->interfaceindex ==
+ 0 ? REG_MAC0 : REG_MAC1));
+ value8 &= (~BIT(1));
+ rtl_write_byte(rtlpriv, (rtlhal->interfaceindex ==
+ 0 ? REG_MAC0 : REG_MAC1), value8);
+ }
+ for (i = 0; i < 20; i++)
+ udelay(MAX_STALL_TIME);
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("<==Switch Band OK.\n"));
+}
+
+static void _rtl92d_phy_reload_imr_setting(struct ieee80211_hw *hw,
+ u8 channel, u8 rfpath)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u32 imr_num = MAX_RF_IMR_INDEX;
+ u32 rfmask = BRFREGOFFSETMASK;
+ u8 group, i;
+ unsigned long flag = 0;
+
+ RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, ("====>path %d\n", rfpath));
+ if (rtlpriv->rtlhal.current_bandtype == BAND_ON_5G) {
+ RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, ("====>5G\n"));
+ rtl_set_bbreg(hw, RFPGA0_RFMOD, BIT(25) | BIT(24), 0);
+ rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER4, 0x00f00000, 0xf);
+ /* fc area 0xd2c */
+ if (channel > 99)
+ rtl_set_bbreg(hw, ROFDM1_CFOTRACKING, BIT(13) |
+ BIT(14), 2);
+ else
+ rtl_set_bbreg(hw, ROFDM1_CFOTRACKING, BIT(13) |
+ BIT(14), 1);
+ /* leave 0 for channel1-14. */
+ group = channel <= 64 ? 1 : 2;
+ imr_num = MAX_RF_IMR_INDEX_NORMAL;
+ for (i = 0; i < imr_num; i++)
+ rtl_set_rfreg(hw, (enum radio_path)rfpath,
+ rf_reg_for_5g_swchnl_normal[i], rfmask,
+ rf_imr_param_normal[0][group][i]);
+ rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER4, 0x00f00000, 0);
+ rtl_set_bbreg(hw, RFPGA0_RFMOD, BOFDMEN, 1);
+ } else {
+ /* G band. */
+ RT_TRACE(rtlpriv, COMP_SCAN, DBG_LOUD,
+ ("Load RF IMR parameters for G band. IMR already "
+ "setting %d\n",
+ rtlpriv->rtlhal.load_imrandiqk_setting_for2g));
+ RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, ("====>2.4G\n"));
+ if (!rtlpriv->rtlhal.load_imrandiqk_setting_for2g) {
+ RT_TRACE(rtlpriv, COMP_SCAN, DBG_LOUD,
+ ("Load RF IMR parameters "
+ "for G band. %d\n", rfpath));
+ rtl92d_acquire_cckandrw_pagea_ctl(hw, &flag);
+ rtl_set_bbreg(hw, RFPGA0_RFMOD, BIT(25) | BIT(24), 0);
+ rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER4,
+ 0x00f00000, 0xf);
+ imr_num = MAX_RF_IMR_INDEX_NORMAL;
+ for (i = 0; i < imr_num; i++) {
+ rtl_set_rfreg(hw, (enum radio_path)rfpath,
+ rf_reg_for_5g_swchnl_normal[i],
+ BRFREGOFFSETMASK,
+ rf_imr_param_normal[0][0][i]);
+ }
+ rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER4,
+ 0x00f00000, 0);
+ rtl_set_bbreg(hw, RFPGA0_RFMOD, BOFDMEN | BCCKEN, 3);
+ rtl92d_release_cckandrw_pagea_ctl(hw, &flag);
+ }
+ }
+ RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, ("<====\n"));
+}
+
+static void _rtl92d_phy_enable_rf_env(struct ieee80211_hw *hw,
+ u8 rfpath, u32 *pu4_regval)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ struct bb_reg_def *pphyreg = &rtlphy->phyreg_def[rfpath];
+
+ RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD, ("====>\n"));
+ /*----Store original RFENV control type----*/
+ switch (rfpath) {
+ case RF90_PATH_A:
+ case RF90_PATH_C:
+ *pu4_regval = rtl_get_bbreg(hw, pphyreg->rfintfs, BRFSI_RFENV);
+ break;
+ case RF90_PATH_B:
+ case RF90_PATH_D:
+ *pu4_regval =
+ rtl_get_bbreg(hw, pphyreg->rfintfs, BRFSI_RFENV << 16);
+ break;
+ }
+ /*----Set RF_ENV enable----*/
+ rtl_set_bbreg(hw, pphyreg->rfintfe, BRFSI_RFENV << 16, 0x1);
+ udelay(1);
+ /*----Set RF_ENV output high----*/
+ rtl_set_bbreg(hw, pphyreg->rfintfo, BRFSI_RFENV, 0x1);
+ udelay(1);
+ /* Set bit number of Address and Data for RF register */
+ /* Set 1 to 4 bits for 8255 */
+ rtl_set_bbreg(hw, pphyreg->rfhssi_para2, B3WIREADDRESSLENGTH, 0x0);
+ udelay(1);
+ /*Set 0 to 12 bits for 8255 */
+ rtl_set_bbreg(hw, pphyreg->rfhssi_para2, B3WIREDATALENGTH, 0x0);
+ udelay(1);
+ RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD, ("<====\n"));
+}
+
+static void _rtl92d_phy_restore_rf_env(struct ieee80211_hw *hw, u8 rfpath,
+ u32 *pu4_regval)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ struct bb_reg_def *pphyreg = &rtlphy->phyreg_def[rfpath];
+
+ RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD, ("=====>\n"));
+ /*----Restore RFENV control type----*/ ;
+ switch (rfpath) {
+ case RF90_PATH_A:
+ case RF90_PATH_C:
+ rtl_set_bbreg(hw, pphyreg->rfintfs, BRFSI_RFENV, *pu4_regval);
+ break;
+ case RF90_PATH_B:
+ case RF90_PATH_D:
+ rtl_set_bbreg(hw, pphyreg->rfintfs, BRFSI_RFENV << 16,
+ *pu4_regval);
+ break;
+ }
+ RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD, ("<=====\n"));
+}
+
+static void _rtl92d_phy_switch_rf_setting(struct ieee80211_hw *hw, u8 channel)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ struct rtl_hal *rtlhal = &(rtlpriv->rtlhal);
+ u8 path = rtlhal->current_bandtype ==
+ BAND_ON_5G ? RF90_PATH_A : RF90_PATH_B;
+ u8 index = 0, i = 0, rfpath = RF90_PATH_A;
+ bool need_pwr_down = false, internal_pa = false;
+ u32 u4regvalue, mask = 0x1C000, value = 0, u4tmp, u4tmp2;
+
+ RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, ("====>\n"));
+ /* config path A for 5G */
+ if (rtlhal->current_bandtype == BAND_ON_5G) {
+ RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, ("====>5G\n"));
+ u4tmp = curveindex_5g[channel - 1];
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("ver 1 set RF-A, 5G, "
+ "0x28 = 0x%x !!\n", u4tmp));
+ for (i = 0; i < RF_CHNL_NUM_5G; i++) {
+ if (channel == rf_chnl_5g[i] && channel <= 140)
+ index = 0;
+ }
+ for (i = 0; i < RF_CHNL_NUM_5G_40M; i++) {
+ if (channel == rf_chnl_5g_40m[i] && channel <= 140)
+ index = 1;
+ }
+ if (channel == 149 || channel == 155 || channel == 161)
+ index = 2;
+ else if (channel == 151 || channel == 153 || channel == 163
+ || channel == 165)
+ index = 3;
+ else if (channel == 157 || channel == 159)
+ index = 4;
+
+ if (rtlhal->macphymode == DUALMAC_DUALPHY
+ && rtlhal->interfaceindex == 1) {
+ need_pwr_down = rtl92d_phy_enable_anotherphy(hw, false);
+ rtlhal->during_mac1init_radioa = true;
+ /* asume no this case */
+ if (need_pwr_down)
+ _rtl92d_phy_enable_rf_env(hw, path,
+ &u4regvalue);
+ }
+ for (i = 0; i < RF_REG_NUM_FOR_C_CUT_5G; i++) {
+ if (i == 0 && (rtlhal->macphymode == DUALMAC_DUALPHY)) {
+ rtl_set_rfreg(hw, (enum radio_path)path,
+ rf_reg_for_c_cut_5g[i],
+ BRFREGOFFSETMASK, 0xE439D);
+ } else if (rf_reg_for_c_cut_5g[i] == RF_SYN_G4) {
+ u4tmp2 = (rf_reg_pram_c_5g[index][i] &
+ 0x7FF) | (u4tmp << 11);
+ if (channel == 36)
+ u4tmp2 &= ~(BIT(7) | BIT(6));
+ rtl_set_rfreg(hw, (enum radio_path)path,
+ rf_reg_for_c_cut_5g[i],
+ BRFREGOFFSETMASK, u4tmp2);
+ } else {
+ rtl_set_rfreg(hw, (enum radio_path)path,
+ rf_reg_for_c_cut_5g[i],
+ BRFREGOFFSETMASK,
+ rf_reg_pram_c_5g[index][i]);
+ }
+ RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
+ ("offset 0x%x value 0x%x "
+ "path %d index %d readback 0x%x\n",
+ rf_reg_for_c_cut_5g[i],
+ rf_reg_pram_c_5g[index][i], path,
+ index, rtl_get_rfreg(hw, (enum radio_path)path,
+ rf_reg_for_c_cut_5g[i], BRFREGOFFSETMASK)));
+ }
+ if (need_pwr_down)
+ _rtl92d_phy_restore_rf_env(hw, path, &u4regvalue);
+ if (rtlhal->during_mac1init_radioa)
+ rtl92d_phy_powerdown_anotherphy(hw, false);
+ if (channel < 149)
+ value = 0x07;
+ else if (channel >= 149)
+ value = 0x02;
+ if (channel >= 36 && channel <= 64)
+ index = 0;
+ else if (channel >= 100 && channel <= 140)
+ index = 1;
+ else
+ index = 2;
+ for (rfpath = RF90_PATH_A; rfpath < rtlphy->num_total_rfpath;
+ rfpath++) {
+ if (rtlhal->macphymode == DUALMAC_DUALPHY &&
+ rtlhal->interfaceindex == 1) /* MAC 1 5G */
+ internal_pa = rtlpriv->efuse.internal_pa_5g[1];
+ else
+ internal_pa =
+ rtlpriv->efuse.internal_pa_5g[rfpath];
+ if (internal_pa) {
+ for (i = 0;
+ i < RF_REG_NUM_FOR_C_CUT_5G_INTERNALPA;
+ i++) {
+ rtl_set_rfreg(hw, rfpath,
+ rf_for_c_cut_5g_internal_pa[i],
+ BRFREGOFFSETMASK,
+ rf_pram_c_5g_int_pa[index][i]);
+ RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD,
+ ("offset 0x%x value 0x%x "
+ "path %d index %d\n",
+ rf_for_c_cut_5g_internal_pa[i],
+ rf_pram_c_5g_int_pa[index][i],
+ rfpath, index));
+ }
+ } else {
+ rtl_set_rfreg(hw, (enum radio_path)rfpath, 0x0B,
+ mask, value);
+ }
+ }
+ } else if (rtlhal->current_bandtype == BAND_ON_2_4G) {
+ RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, ("====>2.4G\n"));
+ u4tmp = curveindex_2g[channel - 1];
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("ver 3 set RF-B, 2G, "
+ "0x28 = 0x%x !!\n", u4tmp));
+ if (channel == 1 || channel == 2 || channel == 4 || channel == 9
+ || channel == 10 || channel == 11 || channel == 12)
+ index = 0;
+ else if (channel == 3 || channel == 13 || channel == 14)
+ index = 1;
+ else if (channel >= 5 && channel <= 8)
+ index = 2;
+ if (rtlhal->macphymode == DUALMAC_DUALPHY) {
+ path = RF90_PATH_A;
+ if (rtlhal->interfaceindex == 0) {
+ need_pwr_down =
+ rtl92d_phy_enable_anotherphy(hw, true);
+ rtlhal->during_mac0init_radiob = true;
+
+ if (need_pwr_down)
+ _rtl92d_phy_enable_rf_env(hw, path,
+ &u4regvalue);
+ }
+ }
+ for (i = 0; i < RF_REG_NUM_FOR_C_CUT_2G; i++) {
+ if (rf_reg_for_c_cut_2g[i] == RF_SYN_G7)
+ rtl_set_rfreg(hw, (enum radio_path)path,
+ rf_reg_for_c_cut_2g[i],
+ BRFREGOFFSETMASK,
+ (rf_reg_param_for_c_cut_2g[index][i] |
+ BIT(17)));
+ else
+ rtl_set_rfreg(hw, (enum radio_path)path,
+ rf_reg_for_c_cut_2g[i],
+ BRFREGOFFSETMASK,
+ rf_reg_param_for_c_cut_2g
+ [index][i]);
+ RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
+ ("offset 0x%x value 0x%x mak 0x%x path %d "
+ "index %d readback 0x%x\n",
+ rf_reg_for_c_cut_2g[i],
+ rf_reg_param_for_c_cut_2g[index][i],
+ rf_reg_mask_for_c_cut_2g[i], path, index,
+ rtl_get_rfreg(hw, (enum radio_path)path,
+ rf_reg_for_c_cut_2g[i],
+ BRFREGOFFSETMASK)));
+ }
+ RTPRINT(rtlpriv, FINIT, INIT_IQK,
+ ("cosa ver 3 set RF-B, 2G, 0x28 = 0x%x !!\n",
+ rf_syn_g4_for_c_cut_2g | (u4tmp << 11)));
+
+ rtl_set_rfreg(hw, (enum radio_path)path, RF_SYN_G4,
+ BRFREGOFFSETMASK,
+ rf_syn_g4_for_c_cut_2g | (u4tmp << 11));
+ if (need_pwr_down)
+ _rtl92d_phy_restore_rf_env(hw, path, &u4regvalue);
+ if (rtlhal->during_mac0init_radiob)
+ rtl92d_phy_powerdown_anotherphy(hw, true);
+ }
+ RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, ("<====\n"));
+}
+
+u8 rtl92d_get_rightchnlplace_for_iqk(u8 chnl)
+{
+ u8 channel_all[59] = {
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58,
+ 60, 62, 64, 100, 102, 104, 106, 108, 110, 112,
+ 114, 116, 118, 120, 122, 124, 126, 128, 130,
+ 132, 134, 136, 138, 140, 149, 151, 153, 155,
+ 157, 159, 161, 163, 165
+ };
+ u8 place = chnl;
+
+ if (chnl > 14) {
+ for (place = 14; place < sizeof(channel_all); place++) {
+ if (channel_all[place] == chnl)
+ return place - 13;
+ }
+ }
+
+ return 0;
+}
+
+#define MAX_TOLERANCE 5
+#define IQK_DELAY_TIME 1 /* ms */
+#define MAX_TOLERANCE_92D 3
+
+/* bit0 = 1 => Tx OK, bit1 = 1 => Rx OK */
+static u8 _rtl92d_phy_patha_iqk(struct ieee80211_hw *hw, bool configpathb)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+ u32 regeac, rege94, rege9c, regea4;
+ u8 result = 0;
+
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("Path A IQK!\n"));
+ /* path-A IQK setting */
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("Path-A IQK setting!\n"));
+ if (rtlhal->interfaceindex == 0) {
+ rtl_set_bbreg(hw, 0xe30, BMASKDWORD, 0x10008c1f);
+ rtl_set_bbreg(hw, 0xe34, BMASKDWORD, 0x10008c1f);
+ } else {
+ rtl_set_bbreg(hw, 0xe30, BMASKDWORD, 0x10008c22);
+ rtl_set_bbreg(hw, 0xe34, BMASKDWORD, 0x10008c22);
+ }
+ rtl_set_bbreg(hw, 0xe38, BMASKDWORD, 0x82140102);
+ rtl_set_bbreg(hw, 0xe3c, BMASKDWORD, 0x28160206);
+ /* path-B IQK setting */
+ if (configpathb) {
+ rtl_set_bbreg(hw, 0xe50, BMASKDWORD, 0x10008c22);
+ rtl_set_bbreg(hw, 0xe54, BMASKDWORD, 0x10008c22);
+ rtl_set_bbreg(hw, 0xe58, BMASKDWORD, 0x82140102);
+ rtl_set_bbreg(hw, 0xe5c, BMASKDWORD, 0x28160206);
+ }
+ /* LO calibration setting */
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("LO calibration setting!\n"));
+ rtl_set_bbreg(hw, 0xe4c, BMASKDWORD, 0x00462911);
+ /* One shot, path A LOK & IQK */
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("One shot, path A LOK & IQK!\n"));
+ rtl_set_bbreg(hw, 0xe48, BMASKDWORD, 0xf9000000);
+ rtl_set_bbreg(hw, 0xe48, BMASKDWORD, 0xf8000000);
+ /* delay x ms */
+ RTPRINT(rtlpriv, FINIT, INIT_IQK,
+ ("Delay %d ms for One shot, path A LOK & IQK.\n",
+ IQK_DELAY_TIME));
+ udelay(IQK_DELAY_TIME * 1000);
+ /* Check failed */
+ regeac = rtl_get_bbreg(hw, 0xeac, BMASKDWORD);
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("0xeac = 0x%x\n", regeac));
+ rege94 = rtl_get_bbreg(hw, 0xe94, BMASKDWORD);
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("0xe94 = 0x%x\n", rege94));
+ rege9c = rtl_get_bbreg(hw, 0xe9c, BMASKDWORD);
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("0xe9c = 0x%x\n", rege9c));
+ regea4 = rtl_get_bbreg(hw, 0xea4, BMASKDWORD);
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("0xea4 = 0x%x\n", regea4));
+ if (!(regeac & BIT(28)) && (((rege94 & 0x03FF0000) >> 16) != 0x142) &&
+ (((rege9c & 0x03FF0000) >> 16) != 0x42))
+ result |= 0x01;
+ else /* if Tx not OK, ignore Rx */
+ return result;
+ /* if Tx is OK, check whether Rx is OK */
+ if (!(regeac & BIT(27)) && (((regea4 & 0x03FF0000) >> 16) != 0x132) &&
+ (((regeac & 0x03FF0000) >> 16) != 0x36))
+ result |= 0x02;
+ else
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("Path A Rx IQK fail!!\n"));
+ return result;
+}
+
+/* bit0 = 1 => Tx OK, bit1 = 1 => Rx OK */
+static u8 _rtl92d_phy_patha_iqk_5g_normal(struct ieee80211_hw *hw,
+ bool configpathb)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ u32 regeac, rege94, rege9c, regea4;
+ u8 result = 0;
+ u8 i;
+ u8 retrycount = 2;
+ u32 TxOKBit = BIT(28), RxOKBit = BIT(27);
+
+ if (rtlhal->interfaceindex == 1) { /* PHY1 */
+ TxOKBit = BIT(31);
+ RxOKBit = BIT(30);
+ }
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("Path A IQK!\n"));
+ /* path-A IQK setting */
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("Path-A IQK setting!\n"));
+ rtl_set_bbreg(hw, 0xe30, BMASKDWORD, 0x18008c1f);
+ rtl_set_bbreg(hw, 0xe34, BMASKDWORD, 0x18008c1f);
+ rtl_set_bbreg(hw, 0xe38, BMASKDWORD, 0x82140307);
+ rtl_set_bbreg(hw, 0xe3c, BMASKDWORD, 0x68160960);
+ /* path-B IQK setting */
+ if (configpathb) {
+ rtl_set_bbreg(hw, 0xe50, BMASKDWORD, 0x18008c2f);
+ rtl_set_bbreg(hw, 0xe54, BMASKDWORD, 0x18008c2f);
+ rtl_set_bbreg(hw, 0xe58, BMASKDWORD, 0x82110000);
+ rtl_set_bbreg(hw, 0xe5c, BMASKDWORD, 0x68110000);
+ }
+ /* LO calibration setting */
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("LO calibration setting!\n"));
+ rtl_set_bbreg(hw, 0xe4c, BMASKDWORD, 0x00462911);
+ /* path-A PA on */
+ rtl_set_bbreg(hw, RFPGA0_XAB_RFINTERFACESW, BMASKDWORD, 0x07000f60);
+ rtl_set_bbreg(hw, RFPGA0_XA_RFINTERFACEOE, BMASKDWORD, 0x66e60e30);
+ for (i = 0; i < retrycount; i++) {
+ /* One shot, path A LOK & IQK */
+ RTPRINT(rtlpriv, FINIT, INIT_IQK,
+ ("One shot, path A LOK & IQK!\n"));
+ rtl_set_bbreg(hw, 0xe48, BMASKDWORD, 0xf9000000);
+ rtl_set_bbreg(hw, 0xe48, BMASKDWORD, 0xf8000000);
+ /* delay x ms */
+ RTPRINT(rtlpriv, FINIT, INIT_IQK,
+ ("Delay %d ms for One shot, path A LOK & IQK.\n",
+ IQK_DELAY_TIME));
+ udelay(IQK_DELAY_TIME * 1000 * 10);
+ /* Check failed */
+ regeac = rtl_get_bbreg(hw, 0xeac, BMASKDWORD);
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("0xeac = 0x%x\n", regeac));
+ rege94 = rtl_get_bbreg(hw, 0xe94, BMASKDWORD);
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("0xe94 = 0x%x\n", rege94));
+ rege9c = rtl_get_bbreg(hw, 0xe9c, BMASKDWORD);
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("0xe9c = 0x%x\n", rege9c));
+ regea4 = rtl_get_bbreg(hw, 0xea4, BMASKDWORD);
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("0xea4 = 0x%x\n", regea4));
+ if (!(regeac & TxOKBit) &&
+ (((rege94 & 0x03FF0000) >> 16) != 0x142)) {
+ result |= 0x01;
+ } else { /* if Tx not OK, ignore Rx */
+ RTPRINT(rtlpriv, FINIT, INIT_IQK,
+ ("Path A Tx IQK fail!!\n"));
+ continue;
+ }
+
+ /* if Tx is OK, check whether Rx is OK */
+ if (!(regeac & RxOKBit) &&
+ (((regea4 & 0x03FF0000) >> 16) != 0x132)) {
+ result |= 0x02;
+ break;
+ } else {
+ RTPRINT(rtlpriv, FINIT, INIT_IQK,
+ ("Path A Rx IQK fail!!\n"));
+ }
+ }
+ /* path A PA off */
+ rtl_set_bbreg(hw, RFPGA0_XAB_RFINTERFACESW, BMASKDWORD,
+ rtlphy->iqk_bb_backup[0]);
+ rtl_set_bbreg(hw, RFPGA0_XA_RFINTERFACEOE, BMASKDWORD,
+ rtlphy->iqk_bb_backup[1]);
+ return result;
+}
+
+/* bit0 = 1 => Tx OK, bit1 = 1 => Rx OK */
+static u8 _rtl92d_phy_pathb_iqk(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u32 regeac, regeb4, regebc, regec4, regecc;
+ u8 result = 0;
+
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("Path B IQK!\n"));
+ /* One shot, path B LOK & IQK */
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("One shot, path A LOK & IQK!\n"));
+ rtl_set_bbreg(hw, 0xe60, BMASKDWORD, 0x00000002);
+ rtl_set_bbreg(hw, 0xe60, BMASKDWORD, 0x00000000);
+ /* delay x ms */
+ RTPRINT(rtlpriv, FINIT, INIT_IQK,
+ ("Delay %d ms for One shot, path B LOK & IQK.\n",
+ IQK_DELAY_TIME));
+ udelay(IQK_DELAY_TIME * 1000);
+ /* Check failed */
+ regeac = rtl_get_bbreg(hw, 0xeac, BMASKDWORD);
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("0xeac = 0x%x\n", regeac));
+ regeb4 = rtl_get_bbreg(hw, 0xeb4, BMASKDWORD);
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("0xeb4 = 0x%x\n", regeb4));
+ regebc = rtl_get_bbreg(hw, 0xebc, BMASKDWORD);
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("0xebc = 0x%x\n", regebc));
+ regec4 = rtl_get_bbreg(hw, 0xec4, BMASKDWORD);
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("0xec4 = 0x%x\n", regec4));
+ regecc = rtl_get_bbreg(hw, 0xecc, BMASKDWORD);
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("0xecc = 0x%x\n", regecc));
+ if (!(regeac & BIT(31)) && (((regeb4 & 0x03FF0000) >> 16) != 0x142) &&
+ (((regebc & 0x03FF0000) >> 16) != 0x42))
+ result |= 0x01;
+ else
+ return result;
+ if (!(regeac & BIT(30)) && (((regec4 & 0x03FF0000) >> 16) != 0x132) &&
+ (((regecc & 0x03FF0000) >> 16) != 0x36))
+ result |= 0x02;
+ else
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("Path B Rx IQK fail!!\n"));
+ return result;
+}
+
+/* bit0 = 1 => Tx OK, bit1 = 1 => Rx OK */
+static u8 _rtl92d_phy_pathb_iqk_5g_normal(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ u32 regeac, regeb4, regebc, regec4, regecc;
+ u8 result = 0;
+ u8 i;
+ u8 retrycount = 2;
+
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("Path B IQK!\n"));
+ /* path-A IQK setting */
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("Path-A IQK setting!\n"));
+ rtl_set_bbreg(hw, 0xe30, BMASKDWORD, 0x18008c1f);
+ rtl_set_bbreg(hw, 0xe34, BMASKDWORD, 0x18008c1f);
+ rtl_set_bbreg(hw, 0xe38, BMASKDWORD, 0x82110000);
+ rtl_set_bbreg(hw, 0xe3c, BMASKDWORD, 0x68110000);
+
+ /* path-B IQK setting */
+ rtl_set_bbreg(hw, 0xe50, BMASKDWORD, 0x18008c2f);
+ rtl_set_bbreg(hw, 0xe54, BMASKDWORD, 0x18008c2f);
+ rtl_set_bbreg(hw, 0xe58, BMASKDWORD, 0x82140307);
+ rtl_set_bbreg(hw, 0xe5c, BMASKDWORD, 0x68160960);
+
+ /* LO calibration setting */
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("LO calibration setting!\n"));
+ rtl_set_bbreg(hw, 0xe4c, BMASKDWORD, 0x00462911);
+
+ /* path-B PA on */
+ rtl_set_bbreg(hw, RFPGA0_XAB_RFINTERFACESW, BMASKDWORD, 0x0f600700);
+ rtl_set_bbreg(hw, RFPGA0_XB_RFINTERFACEOE, BMASKDWORD, 0x061f0d30);
+
+ for (i = 0; i < retrycount; i++) {
+ /* One shot, path B LOK & IQK */
+ RTPRINT(rtlpriv, FINIT, INIT_IQK,
+ ("One shot, path A LOK & IQK!\n"));
+ rtl_set_bbreg(hw, 0xe48, BMASKDWORD, 0xfa000000);
+ rtl_set_bbreg(hw, 0xe48, BMASKDWORD, 0xf8000000);
+
+ /* delay x ms */
+ RTPRINT(rtlpriv, FINIT, INIT_IQK,
+ ("Delay %d ms for One shot, path B LOK & IQK.\n", 10));
+ udelay(IQK_DELAY_TIME * 1000 * 10);
+
+ /* Check failed */
+ regeac = rtl_get_bbreg(hw, 0xeac, BMASKDWORD);
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("0xeac = 0x%x\n", regeac));
+ regeb4 = rtl_get_bbreg(hw, 0xeb4, BMASKDWORD);
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("0xeb4 = 0x%x\n", regeb4));
+ regebc = rtl_get_bbreg(hw, 0xebc, BMASKDWORD);
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("0xebc = 0x%x\n", regebc));
+ regec4 = rtl_get_bbreg(hw, 0xec4, BMASKDWORD);
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("0xec4 = 0x%x\n", regec4));
+ regecc = rtl_get_bbreg(hw, 0xecc, BMASKDWORD);
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("0xecc = 0x%x\n", regecc));
+ if (!(regeac & BIT(31)) &&
+ (((regeb4 & 0x03FF0000) >> 16) != 0x142))
+ result |= 0x01;
+ else
+ continue;
+ if (!(regeac & BIT(30)) &&
+ (((regec4 & 0x03FF0000) >> 16) != 0x132)) {
+ result |= 0x02;
+ break;
+ } else {
+ RTPRINT(rtlpriv, FINIT, INIT_IQK,
+ ("Path B Rx IQK fail!!\n"));
+ }
+ }
+
+ /* path B PA off */
+ rtl_set_bbreg(hw, RFPGA0_XAB_RFINTERFACESW, BMASKDWORD,
+ rtlphy->iqk_bb_backup[0]);
+ rtl_set_bbreg(hw, RFPGA0_XB_RFINTERFACEOE, BMASKDWORD,
+ rtlphy->iqk_bb_backup[2]);
+ return result;
+}
+
+static void _rtl92d_phy_save_adda_registers(struct ieee80211_hw *hw,
+ u32 *adda_reg, u32 *adda_backup,
+ u32 regnum)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u32 i;
+
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("Save ADDA parameters.\n"));
+ for (i = 0; i < regnum; i++)
+ adda_backup[i] = rtl_get_bbreg(hw, adda_reg[i], BMASKDWORD);
+}
+
+static void _rtl92d_phy_save_mac_registers(struct ieee80211_hw *hw,
+ u32 *macreg, u32 *macbackup)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u32 i;
+
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("Save MAC parameters.\n"));
+ for (i = 0; i < (IQK_MAC_REG_NUM - 1); i++)
+ macbackup[i] = rtl_read_byte(rtlpriv, macreg[i]);
+ macbackup[i] = rtl_read_dword(rtlpriv, macreg[i]);
+}
+
+static void _rtl92d_phy_reload_adda_registers(struct ieee80211_hw *hw,
+ u32 *adda_reg, u32 *adda_backup,
+ u32 regnum)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u32 i;
+
+ RTPRINT(rtlpriv, FINIT, INIT_IQK,
+ ("Reload ADDA power saving parameters !\n"));
+ for (i = 0; i < regnum; i++)
+ rtl_set_bbreg(hw, adda_reg[i], BMASKDWORD, adda_backup[i]);
+}
+
+static void _rtl92d_phy_reload_mac_registers(struct ieee80211_hw *hw,
+ u32 *macreg, u32 *macbackup)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u32 i;
+
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("Reload MAC parameters !\n"));
+ for (i = 0; i < (IQK_MAC_REG_NUM - 1); i++)
+ rtl_write_byte(rtlpriv, macreg[i], (u8) macbackup[i]);
+ rtl_write_byte(rtlpriv, macreg[i], macbackup[i]);
+}
+
+static void _rtl92d_phy_path_adda_on(struct ieee80211_hw *hw,
+ u32 *adda_reg, bool patha_on, bool is2t)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u32 pathon;
+ u32 i;
+
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("ADDA ON.\n"));
+ pathon = patha_on ? 0x04db25a4 : 0x0b1b25a4;
+ if (patha_on)
+ pathon = rtlpriv->rtlhal.interfaceindex == 0 ?
+ 0x04db25a4 : 0x0b1b25a4;
+ for (i = 0; i < IQK_ADDA_REG_NUM; i++)
+ rtl_set_bbreg(hw, adda_reg[i], BMASKDWORD, pathon);
+}
+
+static void _rtl92d_phy_mac_setting_calibration(struct ieee80211_hw *hw,
+ u32 *macreg, u32 *macbackup)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u32 i;
+
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("MAC settings for Calibration.\n"));
+ rtl_write_byte(rtlpriv, macreg[0], 0x3F);
+
+ for (i = 1; i < (IQK_MAC_REG_NUM - 1); i++)
+ rtl_write_byte(rtlpriv, macreg[i], (u8)(macbackup[i] &
+ (~BIT(3))));
+ rtl_write_byte(rtlpriv, macreg[i], (u8) (macbackup[i] & (~BIT(5))));
+}
+
+static void _rtl92d_phy_patha_standby(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("Path-A standby mode!\n"));
+
+ rtl_set_bbreg(hw, 0xe28, BMASKDWORD, 0x0);
+ rtl_set_bbreg(hw, RFPGA0_XA_LSSIPARAMETER, BMASKDWORD, 0x00010000);
+ rtl_set_bbreg(hw, 0xe28, BMASKDWORD, 0x80800000);
+}
+
+static void _rtl92d_phy_pimode_switch(struct ieee80211_hw *hw, bool pi_mode)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u32 mode;
+
+ RTPRINT(rtlpriv, FINIT, INIT_IQK,
+ ("BB Switch to %s mode!\n", (pi_mode ? "PI" : "SI")));
+ mode = pi_mode ? 0x01000100 : 0x01000000;
+ rtl_set_bbreg(hw, 0x820, BMASKDWORD, mode);
+ rtl_set_bbreg(hw, 0x828, BMASKDWORD, mode);
+}
+
+static void _rtl92d_phy_iq_calibrate(struct ieee80211_hw *hw, long result[][8],
+ u8 t, bool is2t)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ u32 i;
+ u8 patha_ok, pathb_ok;
+ static u32 adda_reg[IQK_ADDA_REG_NUM] = {
+ RFPGA0_XCD_SWITCHCONTROL, 0xe6c, 0xe70, 0xe74,
+ 0xe78, 0xe7c, 0xe80, 0xe84,
+ 0xe88, 0xe8c, 0xed0, 0xed4,
+ 0xed8, 0xedc, 0xee0, 0xeec
+ };
+ static u32 iqk_mac_reg[IQK_MAC_REG_NUM] = {
+ 0x522, 0x550, 0x551, 0x040
+ };
+ static u32 iqk_bb_reg[IQK_BB_REG_NUM] = {
+ RFPGA0_XAB_RFINTERFACESW, RFPGA0_XA_RFINTERFACEOE,
+ RFPGA0_XB_RFINTERFACEOE, ROFDM0_TRMUXPAR,
+ RFPGA0_XCD_RFINTERFACESW, ROFDM0_TRXPATHENABLE,
+ RFPGA0_RFMOD, RFPGA0_ANALOGPARAMETER4,
+ ROFDM0_XAAGCCORE1, ROFDM0_XBAGCCORE1
+ };
+ const u32 retrycount = 2;
+ u32 bbvalue;
+
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("IQK for 2.4G :Start!!!\n"));
+ if (t == 0) {
+ bbvalue = rtl_get_bbreg(hw, RFPGA0_RFMOD, BMASKDWORD);
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("==>0x%08x\n", bbvalue));
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("IQ Calibration for %s\n",
+ (is2t ? "2T2R" : "1T1R")));
+
+ /* Save ADDA parameters, turn Path A ADDA on */
+ _rtl92d_phy_save_adda_registers(hw, adda_reg,
+ rtlphy->adda_backup, IQK_ADDA_REG_NUM);
+ _rtl92d_phy_save_mac_registers(hw, iqk_mac_reg,
+ rtlphy->iqk_mac_backup);
+ _rtl92d_phy_save_adda_registers(hw, iqk_bb_reg,
+ rtlphy->iqk_bb_backup, IQK_BB_REG_NUM);
+ }
+ _rtl92d_phy_path_adda_on(hw, adda_reg, true, is2t);
+ if (t == 0)
+ rtlphy->rfpi_enable = (u8) rtl_get_bbreg(hw,
+ RFPGA0_XA_HSSIPARAMETER1, BIT(8));
+
+ /* Switch BB to PI mode to do IQ Calibration. */
+ if (!rtlphy->rfpi_enable)
+ _rtl92d_phy_pimode_switch(hw, true);
+
+ rtl_set_bbreg(hw, RFPGA0_RFMOD, BIT(24), 0x00);
+ rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE, BMASKDWORD, 0x03a05600);
+ rtl_set_bbreg(hw, ROFDM0_TRMUXPAR, BMASKDWORD, 0x000800e4);
+ rtl_set_bbreg(hw, RFPGA0_XCD_RFINTERFACESW, BMASKDWORD, 0x22204000);
+ rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER4, 0xf00000, 0x0f);
+ if (is2t) {
+ rtl_set_bbreg(hw, RFPGA0_XA_LSSIPARAMETER, BMASKDWORD,
+ 0x00010000);
+ rtl_set_bbreg(hw, RFPGA0_XB_LSSIPARAMETER, BMASKDWORD,
+ 0x00010000);
+ }
+ /* MAC settings */
+ _rtl92d_phy_mac_setting_calibration(hw, iqk_mac_reg,
+ rtlphy->iqk_mac_backup);
+ /* Page B init */
+ rtl_set_bbreg(hw, 0xb68, BMASKDWORD, 0x0f600000);
+ if (is2t)
+ rtl_set_bbreg(hw, 0xb6c, BMASKDWORD, 0x0f600000);
+ /* IQ calibration setting */
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("IQK setting!\n"));
+ rtl_set_bbreg(hw, 0xe28, BMASKDWORD, 0x80800000);
+ rtl_set_bbreg(hw, 0xe40, BMASKDWORD, 0x01007c00);
+ rtl_set_bbreg(hw, 0xe44, BMASKDWORD, 0x01004800);
+ for (i = 0; i < retrycount; i++) {
+ patha_ok = _rtl92d_phy_patha_iqk(hw, is2t);
+ if (patha_ok == 0x03) {
+ RTPRINT(rtlpriv, FINIT, INIT_IQK,
+ ("Path A IQK Success!!\n"));
+ result[t][0] = (rtl_get_bbreg(hw, 0xe94, BMASKDWORD) &
+ 0x3FF0000) >> 16;
+ result[t][1] = (rtl_get_bbreg(hw, 0xe9c, BMASKDWORD) &
+ 0x3FF0000) >> 16;
+ result[t][2] = (rtl_get_bbreg(hw, 0xea4, BMASKDWORD) &
+ 0x3FF0000) >> 16;
+ result[t][3] = (rtl_get_bbreg(hw, 0xeac, BMASKDWORD) &
+ 0x3FF0000) >> 16;
+ break;
+ } else if (i == (retrycount - 1) && patha_ok == 0x01) {
+ /* Tx IQK OK */
+ RTPRINT(rtlpriv, FINIT, INIT_IQK,
+ ("Path A IQK Only Tx Success!!\n"));
+
+ result[t][0] = (rtl_get_bbreg(hw, 0xe94, BMASKDWORD) &
+ 0x3FF0000) >> 16;
+ result[t][1] = (rtl_get_bbreg(hw, 0xe9c, BMASKDWORD) &
+ 0x3FF0000) >> 16;
+ }
+ }
+ if (0x00 == patha_ok)
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("Path A IQK failed!!\n"));
+ if (is2t) {
+ _rtl92d_phy_patha_standby(hw);
+ /* Turn Path B ADDA on */
+ _rtl92d_phy_path_adda_on(hw, adda_reg, false, is2t);
+ for (i = 0; i < retrycount; i++) {
+ pathb_ok = _rtl92d_phy_pathb_iqk(hw);
+ if (pathb_ok == 0x03) {
+ RTPRINT(rtlpriv, FINIT, INIT_IQK,
+ ("Path B IQK Success!!\n"));
+ result[t][4] = (rtl_get_bbreg(hw, 0xeb4,
+ BMASKDWORD) & 0x3FF0000) >> 16;
+ result[t][5] = (rtl_get_bbreg(hw, 0xebc,
+ BMASKDWORD) & 0x3FF0000) >> 16;
+ result[t][6] = (rtl_get_bbreg(hw, 0xec4,
+ BMASKDWORD) & 0x3FF0000) >> 16;
+ result[t][7] = (rtl_get_bbreg(hw, 0xecc,
+ BMASKDWORD) & 0x3FF0000) >> 16;
+ break;
+ } else if (i == (retrycount - 1) && pathb_ok == 0x01) {
+ /* Tx IQK OK */
+ RTPRINT(rtlpriv, FINIT, INIT_IQK,
+ ("Path B Only Tx IQK Success!!\n"));
+ result[t][4] = (rtl_get_bbreg(hw, 0xeb4,
+ BMASKDWORD) & 0x3FF0000) >> 16;
+ result[t][5] = (rtl_get_bbreg(hw, 0xebc,
+ BMASKDWORD) & 0x3FF0000) >> 16;
+ }
+ }
+ if (0x00 == pathb_ok)
+ RTPRINT(rtlpriv, FINIT, INIT_IQK,
+ ("Path B IQK failed!!\n"));
+ }
+
+ /* Back to BB mode, load original value */
+ RTPRINT(rtlpriv, FINIT, INIT_IQK,
+ ("IQK:Back to BB mode, load original value!\n"));
+
+ rtl_set_bbreg(hw, 0xe28, BMASKDWORD, 0);
+ if (t != 0) {
+ /* Switch back BB to SI mode after finish IQ Calibration. */
+ if (!rtlphy->rfpi_enable)
+ _rtl92d_phy_pimode_switch(hw, false);
+ /* Reload ADDA power saving parameters */
+ _rtl92d_phy_reload_adda_registers(hw, adda_reg,
+ rtlphy->adda_backup, IQK_ADDA_REG_NUM);
+ /* Reload MAC parameters */
+ _rtl92d_phy_reload_mac_registers(hw, iqk_mac_reg,
+ rtlphy->iqk_mac_backup);
+ if (is2t)
+ _rtl92d_phy_reload_adda_registers(hw, iqk_bb_reg,
+ rtlphy->iqk_bb_backup,
+ IQK_BB_REG_NUM);
+ else
+ _rtl92d_phy_reload_adda_registers(hw, iqk_bb_reg,
+ rtlphy->iqk_bb_backup,
+ IQK_BB_REG_NUM - 1);
+ /* load 0xe30 IQC default value */
+ rtl_set_bbreg(hw, 0xe30, BMASKDWORD, 0x01008c00);
+ rtl_set_bbreg(hw, 0xe34, BMASKDWORD, 0x01008c00);
+ }
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("<==\n"));
+}
+
+static void _rtl92d_phy_iq_calibrate_5g_normal(struct ieee80211_hw *hw,
+ long result[][8], u8 t)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ struct rtl_hal *rtlhal = &(rtlpriv->rtlhal);
+ u8 patha_ok, pathb_ok;
+ static u32 adda_reg[IQK_ADDA_REG_NUM] = {
+ RFPGA0_XCD_SWITCHCONTROL, 0xe6c, 0xe70, 0xe74,
+ 0xe78, 0xe7c, 0xe80, 0xe84,
+ 0xe88, 0xe8c, 0xed0, 0xed4,
+ 0xed8, 0xedc, 0xee0, 0xeec
+ };
+ static u32 iqk_mac_reg[IQK_MAC_REG_NUM] = {
+ 0x522, 0x550, 0x551, 0x040
+ };
+ static u32 iqk_bb_reg[IQK_BB_REG_NUM] = {
+ RFPGA0_XAB_RFINTERFACESW, RFPGA0_XA_RFINTERFACEOE,
+ RFPGA0_XB_RFINTERFACEOE, ROFDM0_TRMUXPAR,
+ RFPGA0_XCD_RFINTERFACESW, ROFDM0_TRXPATHENABLE,
+ RFPGA0_RFMOD, RFPGA0_ANALOGPARAMETER4,
+ ROFDM0_XAAGCCORE1, ROFDM0_XBAGCCORE1
+ };
+ u32 bbvalue;
+ bool is2t = IS_92D_SINGLEPHY(rtlhal->version);
+
+ /* Note: IQ calibration must be performed after loading
+ * PHY_REG.txt , and radio_a, radio_b.txt */
+
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("IQK for 5G NORMAL:Start!!!\n"));
+ udelay(IQK_DELAY_TIME * 1000 * 20);
+ if (t == 0) {
+ bbvalue = rtl_get_bbreg(hw, RFPGA0_RFMOD, BMASKDWORD);
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("==>0x%08x\n", bbvalue));
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("IQ Calibration for %s\n",
+ (is2t ? "2T2R" : "1T1R")));
+ /* Save ADDA parameters, turn Path A ADDA on */
+ _rtl92d_phy_save_adda_registers(hw, adda_reg,
+ rtlphy->adda_backup,
+ IQK_ADDA_REG_NUM);
+ _rtl92d_phy_save_mac_registers(hw, iqk_mac_reg,
+ rtlphy->iqk_mac_backup);
+ if (is2t)
+ _rtl92d_phy_save_adda_registers(hw, iqk_bb_reg,
+ rtlphy->iqk_bb_backup,
+ IQK_BB_REG_NUM);
+ else
+ _rtl92d_phy_save_adda_registers(hw, iqk_bb_reg,
+ rtlphy->iqk_bb_backup,
+ IQK_BB_REG_NUM - 1);
+ }
+ _rtl92d_phy_path_adda_on(hw, adda_reg, true, is2t);
+ /* MAC settings */
+ _rtl92d_phy_mac_setting_calibration(hw, iqk_mac_reg,
+ rtlphy->iqk_mac_backup);
+ if (t == 0)
+ rtlphy->rfpi_enable = (u8) rtl_get_bbreg(hw,
+ RFPGA0_XA_HSSIPARAMETER1, BIT(8));
+ /* Switch BB to PI mode to do IQ Calibration. */
+ if (!rtlphy->rfpi_enable)
+ _rtl92d_phy_pimode_switch(hw, true);
+ rtl_set_bbreg(hw, RFPGA0_RFMOD, BIT(24), 0x00);
+ rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE, BMASKDWORD, 0x03a05600);
+ rtl_set_bbreg(hw, ROFDM0_TRMUXPAR, BMASKDWORD, 0x000800e4);
+ rtl_set_bbreg(hw, RFPGA0_XCD_RFINTERFACESW, BMASKDWORD, 0x22208000);
+ rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER4, 0xf00000, 0x0f);
+
+ /* Page B init */
+ rtl_set_bbreg(hw, 0xb68, BMASKDWORD, 0x0f600000);
+ if (is2t)
+ rtl_set_bbreg(hw, 0xb6c, BMASKDWORD, 0x0f600000);
+ /* IQ calibration setting */
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("IQK setting!\n"));
+ rtl_set_bbreg(hw, 0xe28, BMASKDWORD, 0x80800000);
+ rtl_set_bbreg(hw, 0xe40, BMASKDWORD, 0x10007c00);
+ rtl_set_bbreg(hw, 0xe44, BMASKDWORD, 0x01004800);
+ patha_ok = _rtl92d_phy_patha_iqk_5g_normal(hw, is2t);
+ if (patha_ok == 0x03) {
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("Path A IQK Success!!\n"));
+ result[t][0] = (rtl_get_bbreg(hw, 0xe94, BMASKDWORD) &
+ 0x3FF0000) >> 16;
+ result[t][1] = (rtl_get_bbreg(hw, 0xe9c, BMASKDWORD) &
+ 0x3FF0000) >> 16;
+ result[t][2] = (rtl_get_bbreg(hw, 0xea4, BMASKDWORD) &
+ 0x3FF0000) >> 16;
+ result[t][3] = (rtl_get_bbreg(hw, 0xeac, BMASKDWORD) &
+ 0x3FF0000) >> 16;
+ } else if (patha_ok == 0x01) { /* Tx IQK OK */
+ RTPRINT(rtlpriv, FINIT, INIT_IQK,
+ ("Path A IQK Only Tx Success!!\n"));
+
+ result[t][0] = (rtl_get_bbreg(hw, 0xe94, BMASKDWORD) &
+ 0x3FF0000) >> 16;
+ result[t][1] = (rtl_get_bbreg(hw, 0xe9c, BMASKDWORD) &
+ 0x3FF0000) >> 16;
+ } else {
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("Path A IQK Fail!!\n"));
+ }
+ if (is2t) {
+ /* _rtl92d_phy_patha_standby(hw); */
+ /* Turn Path B ADDA on */
+ _rtl92d_phy_path_adda_on(hw, adda_reg, false, is2t);
+ pathb_ok = _rtl92d_phy_pathb_iqk_5g_normal(hw);
+ if (pathb_ok == 0x03) {
+ RTPRINT(rtlpriv, FINIT, INIT_IQK,
+ ("Path B IQK Success!!\n"));
+ result[t][4] = (rtl_get_bbreg(hw, 0xeb4, BMASKDWORD) &
+ 0x3FF0000) >> 16;
+ result[t][5] = (rtl_get_bbreg(hw, 0xebc, BMASKDWORD) &
+ 0x3FF0000) >> 16;
+ result[t][6] = (rtl_get_bbreg(hw, 0xec4, BMASKDWORD) &
+ 0x3FF0000) >> 16;
+ result[t][7] = (rtl_get_bbreg(hw, 0xecc, BMASKDWORD) &
+ 0x3FF0000) >> 16;
+ } else if (pathb_ok == 0x01) { /* Tx IQK OK */
+ RTPRINT(rtlpriv, FINIT, INIT_IQK,
+ ("Path B Only Tx IQK Success!!\n"));
+ result[t][4] = (rtl_get_bbreg(hw, 0xeb4, BMASKDWORD) &
+ 0x3FF0000) >> 16;
+ result[t][5] = (rtl_get_bbreg(hw, 0xebc, BMASKDWORD) &
+ 0x3FF0000) >> 16;
+ } else {
+ RTPRINT(rtlpriv, FINIT, INIT_IQK,
+ ("Path B IQK failed!!\n"));
+ }
+ }
+
+ /* Back to BB mode, load original value */
+ RTPRINT(rtlpriv, FINIT, INIT_IQK,
+ ("IQK:Back to BB mode, load original value!\n"));
+ rtl_set_bbreg(hw, 0xe28, BMASKDWORD, 0);
+ if (t != 0) {
+ if (is2t)
+ _rtl92d_phy_reload_adda_registers(hw, iqk_bb_reg,
+ rtlphy->iqk_bb_backup,
+ IQK_BB_REG_NUM);
+ else
+ _rtl92d_phy_reload_adda_registers(hw, iqk_bb_reg,
+ rtlphy->iqk_bb_backup,
+ IQK_BB_REG_NUM - 1);
+ /* Reload MAC parameters */
+ _rtl92d_phy_reload_mac_registers(hw, iqk_mac_reg,
+ rtlphy->iqk_mac_backup);
+ /* Switch back BB to SI mode after finish IQ Calibration. */
+ if (!rtlphy->rfpi_enable)
+ _rtl92d_phy_pimode_switch(hw, false);
+ /* Reload ADDA power saving parameters */
+ _rtl92d_phy_reload_adda_registers(hw, adda_reg,
+ rtlphy->adda_backup,
+ IQK_ADDA_REG_NUM);
+ }
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("<==\n"));
+}
+
+static bool _rtl92d_phy_simularity_compare(struct ieee80211_hw *hw,
+ long result[][8], u8 c1, u8 c2)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_hal *rtlhal = &(rtlpriv->rtlhal);
+ u32 i, j, diff, sim_bitmap, bound;
+ u8 final_candidate[2] = {0xFF, 0xFF}; /* for path A and path B */
+ bool bresult = true;
+ bool is2t = IS_92D_SINGLEPHY(rtlhal->version);
+
+ if (is2t)
+ bound = 8;
+ else
+ bound = 4;
+ sim_bitmap = 0;
+ for (i = 0; i < bound; i++) {
+ diff = (result[c1][i] > result[c2][i]) ? (result[c1][i] -
+ result[c2][i]) : (result[c2][i] - result[c1][i]);
+ if (diff > MAX_TOLERANCE_92D) {
+ if ((i == 2 || i == 6) && !sim_bitmap) {
+ if (result[c1][i] + result[c1][i + 1] == 0)
+ final_candidate[(i / 4)] = c2;
+ else if (result[c2][i] + result[c2][i + 1] == 0)
+ final_candidate[(i / 4)] = c1;
+ else
+ sim_bitmap = sim_bitmap | (1 << i);
+ } else {
+ sim_bitmap = sim_bitmap | (1 << i);
+ }
+ }
+ }
+ if (sim_bitmap == 0) {
+ for (i = 0; i < (bound / 4); i++) {
+ if (final_candidate[i] != 0xFF) {
+ for (j = i * 4; j < (i + 1) * 4 - 2; j++)
+ result[3][j] =
+ result[final_candidate[i]][j];
+ bresult = false;
+ }
+ }
+ return bresult;
+ }
+ if (!(sim_bitmap & 0x0F)) { /* path A OK */
+ for (i = 0; i < 4; i++)
+ result[3][i] = result[c1][i];
+ } else if (!(sim_bitmap & 0x03)) { /* path A, Tx OK */
+ for (i = 0; i < 2; i++)
+ result[3][i] = result[c1][i];
+ }
+ if (!(sim_bitmap & 0xF0) && is2t) { /* path B OK */
+ for (i = 4; i < 8; i++)
+ result[3][i] = result[c1][i];
+ } else if (!(sim_bitmap & 0x30)) { /* path B, Tx OK */
+ for (i = 4; i < 6; i++)
+ result[3][i] = result[c1][i];
+ }
+ return false;
+}
+
+static void _rtl92d_phy_patha_fill_iqk_matrix(struct ieee80211_hw *hw,
+ bool iqk_ok, long result[][8],
+ u8 final_candidate, bool txonly)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_hal *rtlhal = &(rtlpriv->rtlhal);
+ u32 oldval_0, val_x, tx0_a, reg;
+ long val_y, tx0_c;
+ bool is2t = IS_92D_SINGLEPHY(rtlhal->version) ||
+ rtlhal->macphymode == DUALMAC_DUALPHY;
+
+ RTPRINT(rtlpriv, FINIT, INIT_IQK,
+ ("Path A IQ Calibration %s !\n",
+ (iqk_ok) ? "Success" : "Failed"));
+ if (final_candidate == 0xFF) {
+ return;
+ } else if (iqk_ok) {
+ oldval_0 = (rtl_get_bbreg(hw, ROFDM0_XATxIQIMBALANCE,
+ BMASKDWORD) >> 22) & 0x3FF; /* OFDM0_D */
+ val_x = result[final_candidate][0];
+ if ((val_x & 0x00000200) != 0)
+ val_x = val_x | 0xFFFFFC00;
+ tx0_a = (val_x * oldval_0) >> 8;
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("X = 0x%x, tx0_a = 0x%x,"
+ " oldval_0 0x%x\n", val_x, tx0_a, oldval_0));
+ rtl_set_bbreg(hw, ROFDM0_XATxIQIMBALANCE, 0x3FF, tx0_a);
+ rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(24),
+ ((val_x * oldval_0 >> 7) & 0x1));
+ val_y = result[final_candidate][1];
+ if ((val_y & 0x00000200) != 0)
+ val_y = val_y | 0xFFFFFC00;
+ /* path B IQK result + 3 */
+ if (rtlhal->interfaceindex == 1 &&
+ rtlhal->current_bandtype == BAND_ON_5G)
+ val_y += 3;
+ tx0_c = (val_y * oldval_0) >> 8;
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("Y = 0x%lx, tx0_c = 0x%lx\n",
+ val_y, tx0_c));
+ rtl_set_bbreg(hw, ROFDM0_XCTxAFE, 0xF0000000,
+ ((tx0_c & 0x3C0) >> 6));
+ rtl_set_bbreg(hw, ROFDM0_XATxIQIMBALANCE, 0x003F0000,
+ (tx0_c & 0x3F));
+ if (is2t)
+ rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(26),
+ ((val_y * oldval_0 >> 7) & 0x1));
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("0xC80 = 0x%x\n",
+ rtl_get_bbreg(hw, ROFDM0_XATxIQIMBALANCE,
+ BMASKDWORD)));
+ if (txonly) {
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("only Tx OK\n"));
+ return;
+ }
+ reg = result[final_candidate][2];
+ rtl_set_bbreg(hw, ROFDM0_XARXIQIMBALANCE, 0x3FF, reg);
+ reg = result[final_candidate][3] & 0x3F;
+ rtl_set_bbreg(hw, ROFDM0_XARXIQIMBALANCE, 0xFC00, reg);
+ reg = (result[final_candidate][3] >> 6) & 0xF;
+ rtl_set_bbreg(hw, 0xca0, 0xF0000000, reg);
+ }
+}
+
+static void _rtl92d_phy_pathb_fill_iqk_matrix(struct ieee80211_hw *hw,
+ bool iqk_ok, long result[][8], u8 final_candidate, bool txonly)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_hal *rtlhal = &(rtlpriv->rtlhal);
+ u32 oldval_1, val_x, tx1_a, reg;
+ long val_y, tx1_c;
+
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("Path B IQ Calibration %s !\n",
+ (iqk_ok) ? "Success" : "Failed"));
+ if (final_candidate == 0xFF) {
+ return;
+ } else if (iqk_ok) {
+ oldval_1 = (rtl_get_bbreg(hw, ROFDM0_XBTxIQIMBALANCE,
+ BMASKDWORD) >> 22) & 0x3FF;
+ val_x = result[final_candidate][4];
+ if ((val_x & 0x00000200) != 0)
+ val_x = val_x | 0xFFFFFC00;
+ tx1_a = (val_x * oldval_1) >> 8;
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("X = 0x%x, tx1_a = 0x%x\n",
+ val_x, tx1_a));
+ rtl_set_bbreg(hw, ROFDM0_XBTxIQIMBALANCE, 0x3FF, tx1_a);
+ rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(28),
+ ((val_x * oldval_1 >> 7) & 0x1));
+ val_y = result[final_candidate][5];
+ if ((val_y & 0x00000200) != 0)
+ val_y = val_y | 0xFFFFFC00;
+ if (rtlhal->current_bandtype == BAND_ON_5G)
+ val_y += 3;
+ tx1_c = (val_y * oldval_1) >> 8;
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("Y = 0x%lx, tx1_c = 0x%lx\n",
+ val_y, tx1_c));
+ rtl_set_bbreg(hw, ROFDM0_XDTxAFE, 0xF0000000,
+ ((tx1_c & 0x3C0) >> 6));
+ rtl_set_bbreg(hw, ROFDM0_XBTxIQIMBALANCE, 0x003F0000,
+ (tx1_c & 0x3F));
+ rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(30),
+ ((val_y * oldval_1 >> 7) & 0x1));
+ if (txonly)
+ return;
+ reg = result[final_candidate][6];
+ rtl_set_bbreg(hw, ROFDM0_XBRXIQIMBALANCE, 0x3FF, reg);
+ reg = result[final_candidate][7] & 0x3F;
+ rtl_set_bbreg(hw, ROFDM0_XBRXIQIMBALANCE, 0xFC00, reg);
+ reg = (result[final_candidate][7] >> 6) & 0xF;
+ rtl_set_bbreg(hw, ROFDM0_AGCRSSITABLE, 0x0000F000, reg);
+ }
+}
+
+void rtl92d_phy_iq_calibrate(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ struct rtl_hal *rtlhal = &(rtlpriv->rtlhal);
+ long result[4][8];
+ u8 i, final_candidate, indexforchannel;
+ bool patha_ok, pathb_ok;
+ long rege94, rege9c, regea4, regeac, regeb4;
+ long regebc, regec4, regecc, regtmp = 0;
+ bool is12simular, is13simular, is23simular;
+ unsigned long flag = 0;
+
+ RTPRINT(rtlpriv, FINIT, INIT_IQK,
+ ("IQK:Start!!!channel %d\n", rtlphy->current_channel));
+ for (i = 0; i < 8; i++) {
+ result[0][i] = 0;
+ result[1][i] = 0;
+ result[2][i] = 0;
+ result[3][i] = 0;
+ }
+ final_candidate = 0xff;
+ patha_ok = false;
+ pathb_ok = false;
+ is12simular = false;
+ is23simular = false;
+ is13simular = false;
+ RTPRINT(rtlpriv, FINIT, INIT_IQK,
+ ("IQK !!!currentband %d\n", rtlhal->current_bandtype));
+ rtl92d_acquire_cckandrw_pagea_ctl(hw, &flag);
+ for (i = 0; i < 3; i++) {
+ if (rtlhal->current_bandtype == BAND_ON_5G) {
+ _rtl92d_phy_iq_calibrate_5g_normal(hw, result, i);
+ } else if (rtlhal->current_bandtype == BAND_ON_2_4G) {
+ if (IS_92D_SINGLEPHY(rtlhal->version))
+ _rtl92d_phy_iq_calibrate(hw, result, i, true);
+ else
+ _rtl92d_phy_iq_calibrate(hw, result, i, false);
+ }
+ if (i == 1) {
+ is12simular = _rtl92d_phy_simularity_compare(hw, result,
+ 0, 1);
+ if (is12simular) {
+ final_candidate = 0;
+ break;
+ }
+ }
+ if (i == 2) {
+ is13simular = _rtl92d_phy_simularity_compare(hw, result,
+ 0, 2);
+ if (is13simular) {
+ final_candidate = 0;
+ break;
+ }
+ is23simular = _rtl92d_phy_simularity_compare(hw, result,
+ 1, 2);
+ if (is23simular) {
+ final_candidate = 1;
+ } else {
+ for (i = 0; i < 8; i++)
+ regtmp += result[3][i];
+
+ if (regtmp != 0)
+ final_candidate = 3;
+ else
+ final_candidate = 0xFF;
+ }
+ }
+ }
+ rtl92d_release_cckandrw_pagea_ctl(hw, &flag);
+ for (i = 0; i < 4; i++) {
+ rege94 = result[i][0];
+ rege9c = result[i][1];
+ regea4 = result[i][2];
+ regeac = result[i][3];
+ regeb4 = result[i][4];
+ regebc = result[i][5];
+ regec4 = result[i][6];
+ regecc = result[i][7];
+ RTPRINT(rtlpriv, FINIT, INIT_IQK,
+ ("IQK: rege94=%lx rege9c=%lx regea4=%lx regeac=%lx "
+ "regeb4=%lx regebc=%lx regec4=%lx regecc=%lx\n ",
+ rege94, rege9c, regea4, regeac, regeb4, regebc, regec4,
+ regecc));
+ }
+ if (final_candidate != 0xff) {
+ rtlphy->reg_e94 = rege94 = result[final_candidate][0];
+ rtlphy->reg_e9c = rege9c = result[final_candidate][1];
+ regea4 = result[final_candidate][2];
+ regeac = result[final_candidate][3];
+ rtlphy->reg_eb4 = regeb4 = result[final_candidate][4];
+ rtlphy->reg_ebc = regebc = result[final_candidate][5];
+ regec4 = result[final_candidate][6];
+ regecc = result[final_candidate][7];
+ RTPRINT(rtlpriv, FINIT, INIT_IQK,
+ ("IQK: final_candidate is %x\n", final_candidate));
+ RTPRINT(rtlpriv, FINIT, INIT_IQK,
+ ("IQK: rege94=%lx rege9c=%lx regea4=%lx regeac=%lx "
+ "regeb4=%lx regebc=%lx regec4=%lx regecc=%lx\n ",
+ rege94, rege9c, regea4, regeac, regeb4, regebc, regec4,
+ regecc));
+ patha_ok = pathb_ok = true;
+ } else {
+ rtlphy->reg_e94 = rtlphy->reg_eb4 = 0x100; /* X default value */
+ rtlphy->reg_e9c = rtlphy->reg_ebc = 0x0; /* Y default value */
+ }
+ if ((rege94 != 0) /*&&(regea4 != 0) */)
+ _rtl92d_phy_patha_fill_iqk_matrix(hw, patha_ok, result,
+ final_candidate, (regea4 == 0));
+ if (IS_92D_SINGLEPHY(rtlhal->version)) {
+ if ((regeb4 != 0) /*&&(regec4 != 0) */)
+ _rtl92d_phy_pathb_fill_iqk_matrix(hw, pathb_ok, result,
+ final_candidate, (regec4 == 0));
+ }
+ if (final_candidate != 0xFF) {
+ indexforchannel = rtl92d_get_rightchnlplace_for_iqk(
+ rtlphy->current_channel);
+
+ for (i = 0; i < IQK_MATRIX_REG_NUM; i++)
+ rtlphy->iqk_matrix_regsetting[indexforchannel].
+ value[0][i] = result[final_candidate][i];
+ rtlphy->iqk_matrix_regsetting[indexforchannel].iqk_done =
+ true;
+
+ RT_TRACE(rtlpriv, COMP_SCAN | COMP_MLME, DBG_LOUD,
+ ("\nIQK OK indexforchannel %d.\n", indexforchannel));
+ }
+}
+
+void rtl92d_phy_reload_iqk_setting(struct ieee80211_hw *hw, u8 channel)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ struct rtl_hal *rtlhal = &(rtlpriv->rtlhal);
+ u8 indexforchannel;
+
+ RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, ("channel %d\n", channel));
+ /*------Do IQK for normal chip and test chip 5G band------- */
+ indexforchannel = rtl92d_get_rightchnlplace_for_iqk(channel);
+ RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
+ ("indexforchannel %d done %d\n", indexforchannel,
+ rtlphy->iqk_matrix_regsetting[indexforchannel].iqk_done));
+ if (0 && !rtlphy->iqk_matrix_regsetting[indexforchannel].iqk_done &&
+ rtlphy->need_iqk) {
+ /* Re Do IQK. */
+ RT_TRACE(rtlpriv, COMP_SCAN | COMP_INIT, DBG_LOUD,
+ ("Do IQK Matrix reg for channel:%d....\n", channel));
+ rtl92d_phy_iq_calibrate(hw);
+ } else {
+ /* Just load the value. */
+ /* 2G band just load once. */
+ if (((!rtlhal->load_imrandiqk_setting_for2g) &&
+ indexforchannel == 0) || indexforchannel > 0) {
+ RT_TRACE(rtlpriv, COMP_SCAN, DBG_LOUD,
+ ("Just Read IQK Matrix reg for channel:%d"
+ "....\n", channel));
+ if ((rtlphy->iqk_matrix_regsetting[indexforchannel].
+ value[0] != NULL)
+ /*&&(regea4 != 0) */)
+ _rtl92d_phy_patha_fill_iqk_matrix(hw, true,
+ rtlphy->iqk_matrix_regsetting[
+ indexforchannel].value, 0,
+ (rtlphy->iqk_matrix_regsetting[
+ indexforchannel].value[0][2] == 0));
+ if (IS_92D_SINGLEPHY(rtlhal->version)) {
+ if ((rtlphy->iqk_matrix_regsetting[
+ indexforchannel].value[0][4] != 0)
+ /*&&(regec4 != 0) */)
+ _rtl92d_phy_pathb_fill_iqk_matrix(hw,
+ true,
+ rtlphy->iqk_matrix_regsetting[
+ indexforchannel].value, 0,
+ (rtlphy->iqk_matrix_regsetting[
+ indexforchannel].value[0][6]
+ == 0));
+ }
+ }
+ }
+ rtlphy->need_iqk = false;
+ RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, ("<====\n"));
+}
+
+static u32 _rtl92d_phy_get_abs(u32 val1, u32 val2)
+{
+ u32 ret;
+
+ if (val1 >= val2)
+ ret = val1 - val2;
+ else
+ ret = val2 - val1;
+ return ret;
+}
+
+static bool _rtl92d_is_legal_5g_channel(struct ieee80211_hw *hw, u8 channel)
+{
+
+ int i;
+ u8 channel_5g[45] = {
+ 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58,
+ 60, 62, 64, 100, 102, 104, 106, 108, 110, 112,
+ 114, 116, 118, 120, 122, 124, 126, 128, 130, 132,
+ 134, 136, 138, 140, 149, 151, 153, 155, 157, 159,
+ 161, 163, 165
+ };
+
+ for (i = 0; i < sizeof(channel_5g); i++)
+ if (channel == channel_5g[i])
+ return true;
+ return false;
+}
+
+static void _rtl92d_phy_calc_curvindex(struct ieee80211_hw *hw,
+ u32 *targetchnl, u32 * curvecount_val,
+ bool is5g, u32 *curveindex)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u32 smallest_abs_val = 0xffffffff, u4tmp;
+ u8 i, j;
+ u8 chnl_num = is5g ? TARGET_CHNL_NUM_5G : TARGET_CHNL_NUM_2G;
+
+ for (i = 0; i < chnl_num; i++) {
+ if (is5g && !_rtl92d_is_legal_5g_channel(hw, i + 1))
+ continue;
+ curveindex[i] = 0;
+ for (j = 0; j < (CV_CURVE_CNT * 2); j++) {
+ u4tmp = _rtl92d_phy_get_abs(targetchnl[i],
+ curvecount_val[j]);
+
+ if (u4tmp < smallest_abs_val) {
+ curveindex[i] = j;
+ smallest_abs_val = u4tmp;
+ }
+ }
+ smallest_abs_val = 0xffffffff;
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("curveindex[%d] = %x\n", i,
+ curveindex[i]));
+ }
+}
+
+static void _rtl92d_phy_reload_lck_setting(struct ieee80211_hw *hw,
+ u8 channel)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u8 erfpath = rtlpriv->rtlhal.current_bandtype ==
+ BAND_ON_5G ? RF90_PATH_A :
+ IS_92D_SINGLEPHY(rtlpriv->rtlhal.version) ?
+ RF90_PATH_B : RF90_PATH_A;
+ u32 u4tmp = 0, u4regvalue = 0;
+ bool bneed_powerdown_radio = false;
+
+ RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, ("path %d\n", erfpath));
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("band type = %d\n",
+ rtlpriv->rtlhal.current_bandtype));
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("channel = %d\n", channel));
+ if (rtlpriv->rtlhal.current_bandtype == BAND_ON_5G) {/* Path-A for 5G */
+ u4tmp = curveindex_5g[channel-1];
+ RTPRINT(rtlpriv, FINIT, INIT_IQK,
+ ("ver 1 set RF-A, 5G, 0x28 = 0x%ulx !!\n", u4tmp));
+ if (rtlpriv->rtlhal.macphymode == DUALMAC_DUALPHY &&
+ rtlpriv->rtlhal.interfaceindex == 1) {
+ bneed_powerdown_radio =
+ rtl92d_phy_enable_anotherphy(hw, false);
+ rtlpriv->rtlhal.during_mac1init_radioa = true;
+ /* asume no this case */
+ if (bneed_powerdown_radio)
+ _rtl92d_phy_enable_rf_env(hw, erfpath,
+ &u4regvalue);
+ }
+ rtl_set_rfreg(hw, erfpath, RF_SYN_G4, 0x3f800, u4tmp);
+ if (bneed_powerdown_radio)
+ _rtl92d_phy_restore_rf_env(hw, erfpath, &u4regvalue);
+ if (rtlpriv->rtlhal.during_mac1init_radioa)
+ rtl92d_phy_powerdown_anotherphy(hw, false);
+ } else if (rtlpriv->rtlhal.current_bandtype == BAND_ON_2_4G) {
+ u4tmp = curveindex_2g[channel-1];
+ RTPRINT(rtlpriv, FINIT, INIT_IQK,
+ ("ver 3 set RF-B, 2G, 0x28 = 0x%ulx !!\n", u4tmp));
+ if (rtlpriv->rtlhal.macphymode == DUALMAC_DUALPHY &&
+ rtlpriv->rtlhal.interfaceindex == 0) {
+ bneed_powerdown_radio =
+ rtl92d_phy_enable_anotherphy(hw, true);
+ rtlpriv->rtlhal.during_mac0init_radiob = true;
+ if (bneed_powerdown_radio)
+ _rtl92d_phy_enable_rf_env(hw, erfpath,
+ &u4regvalue);
+ }
+ rtl_set_rfreg(hw, erfpath, RF_SYN_G4, 0x3f800, u4tmp);
+ RTPRINT(rtlpriv, FINIT, INIT_IQK,
+ ("ver 3 set RF-B, 2G, 0x28 = 0x%ulx !!\n",
+ rtl_get_rfreg(hw, erfpath, RF_SYN_G4, 0x3f800)));
+ if (bneed_powerdown_radio)
+ _rtl92d_phy_restore_rf_env(hw, erfpath, &u4regvalue);
+ if (rtlpriv->rtlhal.during_mac0init_radiob)
+ rtl92d_phy_powerdown_anotherphy(hw, true);
+ }
+ RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, ("<====\n"));
+}
+
+static void _rtl92d_phy_lc_calibrate_sw(struct ieee80211_hw *hw, bool is2t)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_hal *rtlhal = &(rtlpriv->rtlhal);
+ struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+ u8 tmpreg, index, rf_mode[2];
+ u8 path = is2t ? 2 : 1;
+ u8 i;
+ u32 u4tmp, offset;
+ u32 curvecount_val[CV_CURVE_CNT * 2] = {0};
+ u16 timeout = 800, timecount = 0;
+
+ /* Check continuous TX and Packet TX */
+ tmpreg = rtl_read_byte(rtlpriv, 0xd03);
+ /* if Deal with contisuous TX case, disable all continuous TX */
+ /* if Deal with Packet TX case, block all queues */
+ if ((tmpreg & 0x70) != 0)
+ rtl_write_byte(rtlpriv, 0xd03, tmpreg & 0x8F);
+ else
+ rtl_write_byte(rtlpriv, REG_TXPAUSE, 0xFF);
+ rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER4, 0xF00000, 0x0F);
+ for (index = 0; index < path; index++) {
+ /* 1. Read original RF mode */
+ offset = index == 0 ? ROFDM0_XAAGCCORE1 : ROFDM0_XBAGCCORE1;
+ rf_mode[index] = rtl_read_byte(rtlpriv, offset);
+ /* 2. Set RF mode = standby mode */
+ rtl_set_rfreg(hw, (enum radio_path)index, RF_AC,
+ BRFREGOFFSETMASK, 0x010000);
+ if (rtlpci->init_ready) {
+ /* switch CV-curve control by LC-calibration */
+ rtl_set_rfreg(hw, (enum radio_path)index, RF_SYN_G7,
+ BIT(17), 0x0);
+ /* 4. Set LC calibration begin */
+ rtl_set_rfreg(hw, (enum radio_path)index, RF_CHNLBW,
+ 0x08000, 0x01);
+ }
+ u4tmp = rtl_get_rfreg(hw, (enum radio_path)index, RF_SYN_G6,
+ BRFREGOFFSETMASK);
+ while ((!(u4tmp & BIT(11))) && timecount <= timeout) {
+ mdelay(50);
+ timecount += 50;
+ u4tmp = rtl_get_rfreg(hw, (enum radio_path)index,
+ RF_SYN_G6, BRFREGOFFSETMASK);
+ }
+ RTPRINT(rtlpriv, FINIT, INIT_IQK,
+ ("PHY_LCK finish delay for %d ms=2\n", timecount));
+ u4tmp = rtl_get_rfreg(hw, index, RF_SYN_G4, BRFREGOFFSETMASK);
+ if (index == 0 && rtlhal->interfaceindex == 0) {
+ RTPRINT(rtlpriv, FINIT, INIT_IQK,
+ ("path-A / 5G LCK\n"));
+ } else {
+ RTPRINT(rtlpriv, FINIT, INIT_IQK,
+ ("path-B / 2.4G LCK\n"));
+ }
+ memset(&curvecount_val[0], 0, CV_CURVE_CNT * 2);
+ /* Set LC calibration off */
+ rtl_set_rfreg(hw, (enum radio_path)index, RF_CHNLBW,
+ 0x08000, 0x0);
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("set RF 0x18[15] = 0\n"));
+ /* save Curve-counting number */
+ for (i = 0; i < CV_CURVE_CNT; i++) {
+ u32 readval = 0, readval2 = 0;
+ rtl_set_rfreg(hw, (enum radio_path)index, 0x3F,
+ 0x7f, i);
+
+ rtl_set_rfreg(hw, (enum radio_path)index, 0x4D,
+ BRFREGOFFSETMASK, 0x0);
+ readval = rtl_get_rfreg(hw, (enum radio_path)index,
+ 0x4F, BRFREGOFFSETMASK);
+ curvecount_val[2 * i + 1] = (readval & 0xfffe0) >> 5;
+ /* reg 0x4f [4:0] */
+ /* reg 0x50 [19:10] */
+ readval2 = rtl_get_rfreg(hw, (enum radio_path)index,
+ 0x50, 0xffc00);
+ curvecount_val[2 * i] = (((readval & 0x1F) << 10) |
+ readval2);
+ }
+ if (index == 0 && rtlhal->interfaceindex == 0)
+ _rtl92d_phy_calc_curvindex(hw, targetchnl_5g,
+ curvecount_val,
+ true, curveindex_5g);
+ else
+ _rtl92d_phy_calc_curvindex(hw, targetchnl_2g,
+ curvecount_val,
+ false, curveindex_2g);
+ /* switch CV-curve control mode */
+ rtl_set_rfreg(hw, (enum radio_path)index, RF_SYN_G7,
+ BIT(17), 0x1);
+ }
+
+ /* Restore original situation */
+ for (index = 0; index < path; index++) {
+ offset = index == 0 ? ROFDM0_XAAGCCORE1 : ROFDM0_XBAGCCORE1;
+ rtl_write_byte(rtlpriv, offset, 0x50);
+ rtl_write_byte(rtlpriv, offset, rf_mode[index]);
+ }
+ if ((tmpreg & 0x70) != 0)
+ rtl_write_byte(rtlpriv, 0xd03, tmpreg);
+ else /*Deal with Packet TX case */
+ rtl_write_byte(rtlpriv, REG_TXPAUSE, 0x00);
+ rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER4, 0xF00000, 0x00);
+ _rtl92d_phy_reload_lck_setting(hw, rtlpriv->phy.current_channel);
+}
+
+static void _rtl92d_phy_lc_calibrate(struct ieee80211_hw *hw, bool is2t)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("cosa PHY_LCK ver=2\n"));
+ _rtl92d_phy_lc_calibrate_sw(hw, is2t);
+}
+
+void rtl92d_phy_lc_calibrate(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ struct rtl_hal *rtlhal = &(rtlpriv->rtlhal);
+ u32 timeout = 2000, timecount = 0;
+
+ while (rtlpriv->mac80211.act_scanning && timecount < timeout) {
+ udelay(50);
+ timecount += 50;
+ }
+
+ rtlphy->lck_inprogress = true;
+ RTPRINT(rtlpriv, FINIT, INIT_IQK,
+ ("LCK:Start!!! currentband %x delay %d ms\n",
+ rtlhal->current_bandtype, timecount));
+ if (IS_92D_SINGLEPHY(rtlhal->version)) {
+ _rtl92d_phy_lc_calibrate(hw, true);
+ } else {
+ /* For 1T1R */
+ _rtl92d_phy_lc_calibrate(hw, false);
+ }
+ rtlphy->lck_inprogress = false;
+ RTPRINT(rtlpriv, FINIT, INIT_IQK, ("LCK:Finish!!!\n"));
+}
+
+void rtl92d_phy_ap_calibrate(struct ieee80211_hw *hw, char delta)
+{
+ return;
+}
+
+static bool _rtl92d_phy_set_sw_chnl_cmdarray(struct swchnlcmd *cmdtable,
+ u32 cmdtableidx, u32 cmdtablesz, enum swchnlcmd_id cmdid,
+ u32 para1, u32 para2, u32 msdelay)
+{
+ struct swchnlcmd *pcmd;
+
+ if (cmdtable == NULL) {
+ RT_ASSERT(false, ("cmdtable cannot be NULL.\n"));
+ return false;
+ }
+ if (cmdtableidx >= cmdtablesz)
+ return false;
+
+ pcmd = cmdtable + cmdtableidx;
+ pcmd->cmdid = cmdid;
+ pcmd->para1 = para1;
+ pcmd->para2 = para2;
+ pcmd->msdelay = msdelay;
+ return true;
+}
+
+void rtl92d_phy_reset_iqk_result(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ u8 i;
+
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+ ("settings regs %d default regs %d\n",
+ (int)(sizeof(rtlphy->iqk_matrix_regsetting) /
+ sizeof(struct iqk_matrix_regs)),
+ IQK_MATRIX_REG_NUM));
+ /* 0xe94, 0xe9c, 0xea4, 0xeac, 0xeb4, 0xebc, 0xec4, 0xecc */
+ for (i = 0; i < IQK_MATRIX_SETTINGS_NUM; i++) {
+ rtlphy->iqk_matrix_regsetting[i].value[0][0] = 0x100;
+ rtlphy->iqk_matrix_regsetting[i].value[0][2] = 0x100;
+ rtlphy->iqk_matrix_regsetting[i].value[0][4] = 0x100;
+ rtlphy->iqk_matrix_regsetting[i].value[0][6] = 0x100;
+ rtlphy->iqk_matrix_regsetting[i].value[0][1] = 0x0;
+ rtlphy->iqk_matrix_regsetting[i].value[0][3] = 0x0;
+ rtlphy->iqk_matrix_regsetting[i].value[0][5] = 0x0;
+ rtlphy->iqk_matrix_regsetting[i].value[0][7] = 0x0;
+ rtlphy->iqk_matrix_regsetting[i].iqk_done = false;
+ }
+}
+
+static bool _rtl92d_phy_sw_chnl_step_by_step(struct ieee80211_hw *hw,
+ u8 channel, u8 *stage, u8 *step,
+ u32 *delay)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ struct swchnlcmd precommoncmd[MAX_PRECMD_CNT];
+ u32 precommoncmdcnt;
+ struct swchnlcmd postcommoncmd[MAX_POSTCMD_CNT];
+ u32 postcommoncmdcnt;
+ struct swchnlcmd rfdependcmd[MAX_RFDEPENDCMD_CNT];
+ u32 rfdependcmdcnt;
+ struct swchnlcmd *currentcmd = NULL;
+ u8 rfpath;
+ u8 num_total_rfpath = rtlphy->num_total_rfpath;
+
+ precommoncmdcnt = 0;
+ _rtl92d_phy_set_sw_chnl_cmdarray(precommoncmd, precommoncmdcnt++,
+ MAX_PRECMD_CNT,
+ CMDID_SET_TXPOWEROWER_LEVEL, 0, 0, 0);
+ _rtl92d_phy_set_sw_chnl_cmdarray(precommoncmd, precommoncmdcnt++,
+ MAX_PRECMD_CNT, CMDID_END, 0, 0, 0);
+ postcommoncmdcnt = 0;
+ _rtl92d_phy_set_sw_chnl_cmdarray(postcommoncmd, postcommoncmdcnt++,
+ MAX_POSTCMD_CNT, CMDID_END, 0, 0, 0);
+ rfdependcmdcnt = 0;
+ _rtl92d_phy_set_sw_chnl_cmdarray(rfdependcmd, rfdependcmdcnt++,
+ MAX_RFDEPENDCMD_CNT, CMDID_RF_WRITEREG,
+ RF_CHNLBW, channel, 0);
+ _rtl92d_phy_set_sw_chnl_cmdarray(rfdependcmd, rfdependcmdcnt++,
+ MAX_RFDEPENDCMD_CNT, CMDID_END,
+ 0, 0, 0);
+
+ do {
+ switch (*stage) {
+ case 0:
+ currentcmd = &precommoncmd[*step];
+ break;
+ case 1:
+ currentcmd = &rfdependcmd[*step];
+ break;
+ case 2:
+ currentcmd = &postcommoncmd[*step];
+ break;
+ }
+ if (currentcmd->cmdid == CMDID_END) {
+ if ((*stage) == 2) {
+ return true;
+ } else {
+ (*stage)++;
+ (*step) = 0;
+ continue;
+ }
+ }
+ switch (currentcmd->cmdid) {
+ case CMDID_SET_TXPOWEROWER_LEVEL:
+ rtl92d_phy_set_txpower_level(hw, channel);
+ break;
+ case CMDID_WRITEPORT_ULONG:
+ rtl_write_dword(rtlpriv, currentcmd->para1,
+ currentcmd->para2);
+ break;
+ case CMDID_WRITEPORT_USHORT:
+ rtl_write_word(rtlpriv, currentcmd->para1,
+ (u16)currentcmd->para2);
+ break;
+ case CMDID_WRITEPORT_UCHAR:
+ rtl_write_byte(rtlpriv, currentcmd->para1,
+ (u8)currentcmd->para2);
+ break;
+ case CMDID_RF_WRITEREG:
+ for (rfpath = 0; rfpath < num_total_rfpath; rfpath++) {
+ rtlphy->rfreg_chnlval[rfpath] =
+ ((rtlphy->rfreg_chnlval[rfpath] &
+ 0xffffff00) | currentcmd->para2);
+ if (rtlpriv->rtlhal.current_bandtype ==
+ BAND_ON_5G) {
+ if (currentcmd->para2 > 99)
+ rtlphy->rfreg_chnlval[rfpath] =
+ rtlphy->rfreg_chnlval
+ [rfpath] | (BIT(18));
+ else
+ rtlphy->rfreg_chnlval[rfpath] =
+ rtlphy->rfreg_chnlval
+ [rfpath] & (~BIT(18));
+ rtlphy->rfreg_chnlval[rfpath] |=
+ (BIT(16) | BIT(8));
+ } else {
+ rtlphy->rfreg_chnlval[rfpath] &=
+ ~(BIT(8) | BIT(16) | BIT(18));
+ }
+ rtl_set_rfreg(hw, (enum radio_path)rfpath,
+ currentcmd->para1,
+ BRFREGOFFSETMASK,
+ rtlphy->rfreg_chnlval[rfpath]);
+ _rtl92d_phy_reload_imr_setting(hw, channel,
+ rfpath);
+ }
+ _rtl92d_phy_switch_rf_setting(hw, channel);
+ /* do IQK when all parameters are ready */
+ rtl92d_phy_reload_iqk_setting(hw, channel);
+ break;
+ default:
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+ ("switch case not process\n"));
+ break;
+ }
+ break;
+ } while (true);
+ (*delay) = currentcmd->msdelay;
+ (*step)++;
+ return false;
+}
+
+u8 rtl92d_phy_sw_chnl(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+ u32 delay;
+ u32 timeout = 1000, timecount = 0;
+ u8 channel = rtlphy->current_channel;
+ u32 ret_value;
+
+ if (rtlphy->sw_chnl_inprogress)
+ return 0;
+ if (rtlphy->set_bwmode_inprogress)
+ return 0;
+
+ if ((is_hal_stop(rtlhal)) || (RT_CANNOT_IO(hw))) {
+ RT_TRACE(rtlpriv, COMP_CHAN, DBG_LOUD,
+ ("sw_chnl_inprogress false driver sleep or unload\n"));
+ return 0;
+ }
+ while (rtlphy->lck_inprogress && timecount < timeout) {
+ mdelay(50);
+ timecount += 50;
+ }
+ if (rtlhal->macphymode == SINGLEMAC_SINGLEPHY &&
+ rtlhal->bandset == BAND_ON_BOTH) {
+ ret_value = rtl_get_bbreg(hw, RFPGA0_XAB_RFPARAMETER,
+ BMASKDWORD);
+ if (rtlphy->current_channel > 14 && !(ret_value & BIT(0)))
+ rtl92d_phy_switch_wirelessband(hw, BAND_ON_5G);
+ else if (rtlphy->current_channel <= 14 && (ret_value & BIT(0)))
+ rtl92d_phy_switch_wirelessband(hw, BAND_ON_2_4G);
+ }
+ switch (rtlhal->current_bandtype) {
+ case BAND_ON_5G:
+ /* Get first channel error when change between
+ * 5G and 2.4G band. */
+ if (channel <= 14)
+ return 0;
+ RT_ASSERT((channel > 14), ("5G but channel<=14"));
+ break;
+ case BAND_ON_2_4G:
+ /* Get first channel error when change between
+ * 5G and 2.4G band. */
+ if (channel > 14)
+ return 0;
+ RT_ASSERT((channel <= 14), ("2G but channel>14"));
+ break;
+ default:
+ RT_ASSERT(false,
+ ("Invalid WirelessMode(%#x)!!\n",
+ rtlpriv->mac80211.mode));
+ break;
+ }
+ rtlphy->sw_chnl_inprogress = true;
+ if (channel == 0)
+ channel = 1;
+ rtlphy->sw_chnl_stage = 0;
+ rtlphy->sw_chnl_step = 0;
+ RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE,
+ ("switch to channel%d\n", rtlphy->current_channel));
+
+ do {
+ if (!rtlphy->sw_chnl_inprogress)
+ break;
+ if (!_rtl92d_phy_sw_chnl_step_by_step(hw,
+ rtlphy->current_channel,
+ &rtlphy->sw_chnl_stage, &rtlphy->sw_chnl_step, &delay)) {
+ if (delay > 0)
+ mdelay(delay);
+ else
+ continue;
+ } else {
+ rtlphy->sw_chnl_inprogress = false;
+ }
+ break;
+ } while (true);
+ RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, ("<==\n"));
+ rtlphy->sw_chnl_inprogress = false;
+ return 1;
+}
+
+static void rtl92d_phy_set_io(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+
+ RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE,
+ ("--->Cmd(%#x), set_io_inprogress(%d)\n",
+ rtlphy->current_io_type, rtlphy->set_io_inprogress));
+ switch (rtlphy->current_io_type) {
+ case IO_CMD_RESUME_DM_BY_SCAN:
+ de_digtable.cur_igvalue = rtlphy->initgain_backup.xaagccore1;
+ rtl92d_dm_write_dig(hw);
+ rtl92d_phy_set_txpower_level(hw, rtlphy->current_channel);
+ break;
+ case IO_CMD_PAUSE_DM_BY_SCAN:
+ rtlphy->initgain_backup.xaagccore1 = de_digtable.cur_igvalue;
+ de_digtable.cur_igvalue = 0x17;
+ rtl92d_dm_write_dig(hw);
+ break;
+ default:
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+ ("switch case not process\n"));
+ break;
+ }
+ rtlphy->set_io_inprogress = false;
+ RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE,
+ ("<---(%#x)\n", rtlphy->current_io_type));
+}
+
+bool rtl92d_phy_set_io_cmd(struct ieee80211_hw *hw, enum io_type iotype)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ bool postprocessing = false;
+
+ RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE,
+ ("-->IO Cmd(%#x), set_io_inprogress(%d)\n",
+ iotype, rtlphy->set_io_inprogress));
+ do {
+ switch (iotype) {
+ case IO_CMD_RESUME_DM_BY_SCAN:
+ RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE,
+ ("[IO CMD] Resume DM after scan.\n"));
+ postprocessing = true;
+ break;
+ case IO_CMD_PAUSE_DM_BY_SCAN:
+ RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE,
+ ("[IO CMD] Pause DM before scan.\n"));
+ postprocessing = true;
+ break;
+ default:
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+ ("switch case not process\n"));
+ break;
+ }
+ } while (false);
+ if (postprocessing && !rtlphy->set_io_inprogress) {
+ rtlphy->set_io_inprogress = true;
+ rtlphy->current_io_type = iotype;
+ } else {
+ return false;
+ }
+ rtl92d_phy_set_io(hw);
+ RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, ("<--IO Type(%#x)\n", iotype));
+ return true;
+}
+
+static void _rtl92d_phy_set_rfon(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+ /* a. SYS_CLKR 0x08[11] = 1 restore MAC clock */
+ /* b. SPS_CTRL 0x11[7:0] = 0x2b */
+ if (rtlpriv->rtlhal.macphymode == SINGLEMAC_SINGLEPHY)
+ rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x2b);
+ /* c. For PCIE: SYS_FUNC_EN 0x02[7:0] = 0xE3 enable BB TRX function */
+ rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE3);
+ /* RF_ON_EXCEP(d~g): */
+ /* d. APSD_CTRL 0x600[7:0] = 0x00 */
+ rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x00);
+ /* e. SYS_FUNC_EN 0x02[7:0] = 0xE2 reset BB TRX function again */
+ /* f. SYS_FUNC_EN 0x02[7:0] = 0xE3 enable BB TRX function*/
+ rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2);
+ rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE3);
+ /* g. txpause 0x522[7:0] = 0x00 enable mac tx queue */
+ rtl_write_byte(rtlpriv, REG_TXPAUSE, 0x00);
+}
+
+static void _rtl92d_phy_set_rfsleep(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u32 u4btmp;
+ u8 delay = 5;
+
+ /* a. TXPAUSE 0x522[7:0] = 0xFF Pause MAC TX queue */
+ rtl_write_byte(rtlpriv, REG_TXPAUSE, 0xFF);
+ /* b. RF path 0 offset 0x00 = 0x00 disable RF */
+ rtl_set_rfreg(hw, RF90_PATH_A, 0x00, BRFREGOFFSETMASK, 0x00);
+ /* c. APSD_CTRL 0x600[7:0] = 0x40 */
+ rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x40);
+ /* d. APSD_CTRL 0x600[7:0] = 0x00
+ * APSD_CTRL 0x600[7:0] = 0x00
+ * RF path 0 offset 0x00 = 0x00
+ * APSD_CTRL 0x600[7:0] = 0x40
+ * */
+ u4btmp = rtl_get_rfreg(hw, RF90_PATH_A, 0, BRFREGOFFSETMASK);
+ while (u4btmp != 0 && delay > 0) {
+ rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x0);
+ rtl_set_rfreg(hw, RF90_PATH_A, 0x00, BRFREGOFFSETMASK, 0x00);
+ rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x40);
+ u4btmp = rtl_get_rfreg(hw, RF90_PATH_A, 0, BRFREGOFFSETMASK);
+ delay--;
+ }
+ if (delay == 0) {
+ /* Jump out the LPS turn off sequence to RF_ON_EXCEP */
+ rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x00);
+
+ rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2);
+ rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE3);
+ rtl_write_byte(rtlpriv, REG_TXPAUSE, 0x00);
+ RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
+ ("Fail !!! Switch RF timeout.\n"));
+ return;
+ }
+ /* e. For PCIE: SYS_FUNC_EN 0x02[7:0] = 0xE2 reset BB TRX function */
+ rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2);
+ /* f. SPS_CTRL 0x11[7:0] = 0x22 */
+ if (rtlpriv->rtlhal.macphymode == SINGLEMAC_SINGLEPHY)
+ rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x22);
+ /* g. SYS_CLKR 0x08[11] = 0 gated MAC clock */
+}
+
+bool rtl92d_phy_set_rf_power_state(struct ieee80211_hw *hw,
+ enum rf_pwrstate rfpwr_state)
+{
+
+ bool bresult = true;
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
+ struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+ struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+ struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+ u8 i, queue_id;
+ struct rtl8192_tx_ring *ring = NULL;
+
+ if (rfpwr_state == ppsc->rfpwr_state)
+ return false;
+ switch (rfpwr_state) {
+ case ERFON:
+ if ((ppsc->rfpwr_state == ERFOFF) &&
+ RT_IN_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC)) {
+ bool rtstatus;
+ u32 InitializeCount = 0;
+ do {
+ InitializeCount++;
+ RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
+ ("IPS Set eRf nic enable\n"));
+ rtstatus = rtl_ps_enable_nic(hw);
+ } while ((rtstatus != true) &&
+ (InitializeCount < 10));
+
+ RT_CLEAR_PS_LEVEL(ppsc,
+ RT_RF_OFF_LEVL_HALT_NIC);
+ } else {
+ RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG,
+ ("awake, sleeped:%d ms state_"
+ "inap:%x\n",
+ jiffies_to_msecs(jiffies -
+ ppsc->last_sleep_jiffies),
+ rtlpriv->psc.state_inap));
+ ppsc->last_awake_jiffies = jiffies;
+ _rtl92d_phy_set_rfon(hw);
+ }
+
+ if (mac->link_state == MAC80211_LINKED)
+ rtlpriv->cfg->ops->led_control(hw,
+ LED_CTL_LINK);
+ else
+ rtlpriv->cfg->ops->led_control(hw,
+ LED_CTL_NO_LINK);
+ break;
+ case ERFOFF:
+ if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_HALT_NIC) {
+ RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
+ ("IPS Set eRf nic disable\n"));
+ rtl_ps_disable_nic(hw);
+ RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC);
+ } else {
+ if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS)
+ rtlpriv->cfg->ops->led_control(hw,
+ LED_CTL_NO_LINK);
+ else
+ rtlpriv->cfg->ops->led_control(hw,
+ LED_CTL_POWER_OFF);
+ }
+ break;
+ case ERFSLEEP:
+ if (ppsc->rfpwr_state == ERFOFF)
+ break;
+
+ for (queue_id = 0, i = 0;
+ queue_id < RTL_PCI_MAX_TX_QUEUE_COUNT;) {
+ ring = &pcipriv->dev.tx_ring[queue_id];
+ if (skb_queue_len(&ring->queue) == 0 ||
+ queue_id == BEACON_QUEUE) {
+ queue_id++;
+ continue;
+ } else if (rtlpci->pdev->current_state != PCI_D0) {
+ RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
+ ("eRf Off/Sleep: %d times TcbBusyQueu"
+ "e[%d] !=0 but lower power state!\n",
+ (i + 1), queue_id));
+ break;
+ } else {
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
+ ("eRf Off/Sleep: %d times TcbBusyQueu"
+ "e[%d] =%d "
+ "before doze!\n", (i + 1), queue_id,
+ skb_queue_len(&ring->queue)));
+ udelay(10);
+ i++;
+ }
+
+ if (i >= MAX_DOZE_WAITING_TIMES_9x) {
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
+ ("\nERFOFF: %d times TcbBusyQueue[%d] "
+ "= %d !\n",
+ MAX_DOZE_WAITING_TIMES_9x, queue_id,
+ skb_queue_len(&ring->queue)));
+ break;
+ }
+ }
+ RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG,
+ ("Set rfsleep awaked:%d ms\n",
+ jiffies_to_msecs(jiffies - ppsc->last_awake_jiffies)));
+ RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, ("sleep awaked:%d ms "
+ "state_inap:%x\n", jiffies_to_msecs(jiffies -
+ ppsc->last_awake_jiffies), rtlpriv->psc.state_inap));
+ ppsc->last_sleep_jiffies = jiffies;
+ _rtl92d_phy_set_rfsleep(hw);
+ break;
+ default:
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+ ("switch case not process\n"));
+ bresult = false;
+ break;
+ }
+ if (bresult)
+ ppsc->rfpwr_state = rfpwr_state;
+ return bresult;
+}
+
+void rtl92d_phy_config_macphymode(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+ u8 offset = REG_MAC_PHY_CTRL_NORMAL;
+
+ switch (rtlhal->macphymode) {
+ case DUALMAC_DUALPHY:
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+ ("MacPhyMode: DUALMAC_DUALPHY\n"));
+ rtl_write_byte(rtlpriv, offset, 0xF3);
+ break;
+ case SINGLEMAC_SINGLEPHY:
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+ ("MacPhyMode: SINGLEMAC_SINGLEPHY\n"));
+ rtl_write_byte(rtlpriv, offset, 0xF4);
+ break;
+ case DUALMAC_SINGLEPHY:
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+ ("MacPhyMode: DUALMAC_SINGLEPHY\n"));
+ rtl_write_byte(rtlpriv, offset, 0xF1);
+ break;
+ }
+}
+
+void rtl92d_phy_config_macphymode_info(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+
+ switch (rtlhal->macphymode) {
+ case DUALMAC_SINGLEPHY:
+ rtlphy->rf_type = RF_2T2R;
+ rtlhal->version |= CHIP_92D_SINGLEPHY;
+ rtlhal->bandset = BAND_ON_BOTH;
+ rtlhal->current_bandtype = BAND_ON_2_4G;
+ break;
+
+ case SINGLEMAC_SINGLEPHY:
+ rtlphy->rf_type = RF_2T2R;
+ rtlhal->version |= CHIP_92D_SINGLEPHY;
+ rtlhal->bandset = BAND_ON_BOTH;
+ rtlhal->current_bandtype = BAND_ON_2_4G;
+ break;
+
+ case DUALMAC_DUALPHY:
+ rtlphy->rf_type = RF_1T1R;
+ rtlhal->version &= (~CHIP_92D_SINGLEPHY);
+ /* Now we let MAC0 run on 5G band. */
+ if (rtlhal->interfaceindex == 0) {
+ rtlhal->bandset = BAND_ON_5G;
+ rtlhal->current_bandtype = BAND_ON_5G;
+ } else {
+ rtlhal->bandset = BAND_ON_2_4G;
+ rtlhal->current_bandtype = BAND_ON_2_4G;
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+u8 rtl92d_get_chnlgroup_fromarray(u8 chnl)
+{
+ u8 group;
+ u8 channel_info[59] = {
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56,
+ 58, 60, 62, 64, 100, 102, 104, 106, 108,
+ 110, 112, 114, 116, 118, 120, 122, 124,
+ 126, 128, 130, 132, 134, 136, 138, 140,
+ 149, 151, 153, 155, 157, 159, 161, 163,
+ 165
+ };
+
+ if (channel_info[chnl] <= 3)
+ group = 0;
+ else if (channel_info[chnl] <= 9)
+ group = 1;
+ else if (channel_info[chnl] <= 14)
+ group = 2;
+ else if (channel_info[chnl] <= 44)
+ group = 3;
+ else if (channel_info[chnl] <= 54)
+ group = 4;
+ else if (channel_info[chnl] <= 64)
+ group = 5;
+ else if (channel_info[chnl] <= 112)
+ group = 6;
+ else if (channel_info[chnl] <= 126)
+ group = 7;
+ else if (channel_info[chnl] <= 140)
+ group = 8;
+ else if (channel_info[chnl] <= 153)
+ group = 9;
+ else if (channel_info[chnl] <= 159)
+ group = 10;
+ else
+ group = 11;
+ return group;
+}
+
+void rtl92d_phy_set_poweron(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+ unsigned long flags;
+ u8 value8;
+ u16 i;
+ u32 mac_reg = (rtlhal->interfaceindex == 0 ? REG_MAC0 : REG_MAC1);
+
+ /* notice fw know band status 0x81[1]/0x53[1] = 0: 5G, 1: 2G */
+ if (rtlhal->current_bandtype == BAND_ON_2_4G) {
+ value8 = rtl_read_byte(rtlpriv, mac_reg);
+ value8 |= BIT(1);
+ rtl_write_byte(rtlpriv, mac_reg, value8);
+ } else {
+ value8 = rtl_read_byte(rtlpriv, mac_reg);
+ value8 &= (~BIT(1));
+ rtl_write_byte(rtlpriv, mac_reg, value8);
+ }
+
+ if (rtlhal->macphymode == SINGLEMAC_SINGLEPHY) {
+ value8 = rtl_read_byte(rtlpriv, REG_MAC0);
+ rtl_write_byte(rtlpriv, REG_MAC0, value8 | MAC0_ON);
+ } else {
+ spin_lock_irqsave(&globalmutex_power, flags);
+ if (rtlhal->interfaceindex == 0) {
+ value8 = rtl_read_byte(rtlpriv, REG_MAC0);
+ rtl_write_byte(rtlpriv, REG_MAC0, value8 | MAC0_ON);
+ } else {
+ value8 = rtl_read_byte(rtlpriv, REG_MAC1);
+ rtl_write_byte(rtlpriv, REG_MAC1, value8 | MAC1_ON);
+ }
+ value8 = rtl_read_byte(rtlpriv, REG_POWER_OFF_IN_PROCESS);
+ spin_unlock_irqrestore(&globalmutex_power, flags);
+ for (i = 0; i < 200; i++) {
+ if ((value8 & BIT(7)) == 0) {
+ break;
+ } else {
+ udelay(500);
+ spin_lock_irqsave(&globalmutex_power, flags);
+ value8 = rtl_read_byte(rtlpriv,
+ REG_POWER_OFF_IN_PROCESS);
+ spin_unlock_irqrestore(&globalmutex_power,
+ flags);
+ }
+ }
+ if (i == 200)
+ RT_ASSERT(false, ("Another mac power off over time\n"));
+ }
+}
+
+void rtl92d_phy_config_maccoexist_rfpage(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+ switch (rtlpriv->rtlhal.macphymode) {
+ case DUALMAC_DUALPHY:
+ rtl_write_byte(rtlpriv, REG_DMC, 0x0);
+ rtl_write_byte(rtlpriv, REG_RX_PKT_LIMIT, 0x08);
+ rtl_write_word(rtlpriv, REG_TRXFF_BNDY + 2, 0x13ff);
+ break;
+ case DUALMAC_SINGLEPHY:
+ rtl_write_byte(rtlpriv, REG_DMC, 0xf8);
+ rtl_write_byte(rtlpriv, REG_RX_PKT_LIMIT, 0x08);
+ rtl_write_word(rtlpriv, REG_TRXFF_BNDY + 2, 0x13ff);
+ break;
+ case SINGLEMAC_SINGLEPHY:
+ rtl_write_byte(rtlpriv, REG_DMC, 0x0);
+ rtl_write_byte(rtlpriv, REG_RX_PKT_LIMIT, 0x10);
+ rtl_write_word(rtlpriv, (REG_TRXFF_BNDY + 2), 0x27FF);
+ break;
+ default:
+ break;
+ }
+}
+
+void rtl92d_update_bbrf_configuration(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+ u8 rfpath, i;
+
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("==>\n"));
+ /* r_select_5G for path_A/B 0 for 2.4G, 1 for 5G */
+ if (rtlhal->current_bandtype == BAND_ON_2_4G) {
+ /* r_select_5G for path_A/B,0x878 */
+ rtl_set_bbreg(hw, RFPGA0_XAB_RFPARAMETER, BIT(0), 0x0);
+ rtl_set_bbreg(hw, RFPGA0_XAB_RFPARAMETER, BIT(15), 0x0);
+ if (rtlhal->macphymode != DUALMAC_DUALPHY) {
+ rtl_set_bbreg(hw, RFPGA0_XAB_RFPARAMETER, BIT(16), 0x0);
+ rtl_set_bbreg(hw, RFPGA0_XAB_RFPARAMETER, BIT(31), 0x0);
+ }
+ /* rssi_table_select:index 0 for 2.4G.1~3 for 5G,0xc78 */
+ rtl_set_bbreg(hw, ROFDM0_AGCRSSITABLE, BIT(6) | BIT(7), 0x0);
+ /* fc_area 0xd2c */
+ rtl_set_bbreg(hw, ROFDM1_CFOTRACKING, BIT(14) | BIT(13), 0x0);
+ /* 5G LAN ON */
+ rtl_set_bbreg(hw, 0xB30, 0x00F00000, 0xa);
+ /* TX BB gain shift*1,Just for testchip,0xc80,0xc88 */
+ rtl_set_bbreg(hw, ROFDM0_XATxIQIMBALANCE, BMASKDWORD,
+ 0x40000100);
+ rtl_set_bbreg(hw, ROFDM0_XBTxIQIMBALANCE, BMASKDWORD,
+ 0x40000100);
+ if (rtlhal->macphymode == DUALMAC_DUALPHY) {
+ rtl_set_bbreg(hw, RFPGA0_XAB_RFINTERFACESW,
+ BIT(10) | BIT(6) | BIT(5),
+ ((rtlefuse->eeprom_c9 & BIT(3)) >> 3) |
+ (rtlefuse->eeprom_c9 & BIT(1)) |
+ ((rtlefuse->eeprom_cc & BIT(1)) << 4));
+ rtl_set_bbreg(hw, RFPGA0_XA_RFINTERFACEOE,
+ BIT(10) | BIT(6) | BIT(5),
+ ((rtlefuse->eeprom_c9 & BIT(2)) >> 2) |
+ ((rtlefuse->eeprom_c9 & BIT(0)) << 1) |
+ ((rtlefuse->eeprom_cc & BIT(0)) << 5));
+ rtl_set_bbreg(hw, RFPGA0_XAB_RFPARAMETER, BIT(15), 0);
+ } else {
+ rtl_set_bbreg(hw, RFPGA0_XAB_RFINTERFACESW,
+ BIT(26) | BIT(22) | BIT(21) | BIT(10) |
+ BIT(6) | BIT(5),
+ ((rtlefuse->eeprom_c9 & BIT(3)) >> 3) |
+ (rtlefuse->eeprom_c9 & BIT(1)) |
+ ((rtlefuse->eeprom_cc & BIT(1)) << 4) |
+ ((rtlefuse->eeprom_c9 & BIT(7)) << 9) |
+ ((rtlefuse->eeprom_c9 & BIT(5)) << 12) |
+ ((rtlefuse->eeprom_cc & BIT(3)) << 18));
+ rtl_set_bbreg(hw, RFPGA0_XA_RFINTERFACEOE,
+ BIT(10) | BIT(6) | BIT(5),
+ ((rtlefuse->eeprom_c9 & BIT(2)) >> 2) |
+ ((rtlefuse->eeprom_c9 & BIT(0)) << 1) |
+ ((rtlefuse->eeprom_cc & BIT(0)) << 5));
+ rtl_set_bbreg(hw, RFPGA0_XB_RFINTERFACEOE,
+ BIT(10) | BIT(6) | BIT(5),
+ ((rtlefuse->eeprom_c9 & BIT(6)) >> 6) |
+ ((rtlefuse->eeprom_c9 & BIT(4)) >> 3) |
+ ((rtlefuse->eeprom_cc & BIT(2)) << 3));
+ rtl_set_bbreg(hw, RFPGA0_XAB_RFPARAMETER,
+ BIT(31) | BIT(15), 0);
+ }
+ /* 1.5V_LDO */
+ } else {
+ /* r_select_5G for path_A/B */
+ rtl_set_bbreg(hw, RFPGA0_XAB_RFPARAMETER, BIT(0), 0x1);
+ rtl_set_bbreg(hw, RFPGA0_XAB_RFPARAMETER, BIT(15), 0x1);
+ if (rtlhal->macphymode != DUALMAC_DUALPHY) {
+ rtl_set_bbreg(hw, RFPGA0_XAB_RFPARAMETER, BIT(16), 0x1);
+ rtl_set_bbreg(hw, RFPGA0_XAB_RFPARAMETER, BIT(31), 0x1);
+ }
+ /* rssi_table_select:index 0 for 2.4G.1~3 for 5G */
+ rtl_set_bbreg(hw, ROFDM0_AGCRSSITABLE, BIT(6) | BIT(7), 0x1);
+ /* fc_area */
+ rtl_set_bbreg(hw, ROFDM1_CFOTRACKING, BIT(14) | BIT(13), 0x1);
+ /* 5G LAN ON */
+ rtl_set_bbreg(hw, 0xB30, 0x00F00000, 0x0);
+ /* TX BB gain shift,Just for testchip,0xc80,0xc88 */
+ if (rtlefuse->internal_pa_5g[0])
+ rtl_set_bbreg(hw, ROFDM0_XATxIQIMBALANCE, BMASKDWORD,
+ 0x2d4000b5);
+ else
+ rtl_set_bbreg(hw, ROFDM0_XATxIQIMBALANCE, BMASKDWORD,
+ 0x20000080);
+ if (rtlefuse->internal_pa_5g[1])
+ rtl_set_bbreg(hw, ROFDM0_XBTxIQIMBALANCE, BMASKDWORD,
+ 0x2d4000b5);
+ else
+ rtl_set_bbreg(hw, ROFDM0_XBTxIQIMBALANCE, BMASKDWORD,
+ 0x20000080);
+ if (rtlhal->macphymode == DUALMAC_DUALPHY) {
+ rtl_set_bbreg(hw, RFPGA0_XAB_RFINTERFACESW,
+ BIT(10) | BIT(6) | BIT(5),
+ (rtlefuse->eeprom_cc & BIT(5)));
+ rtl_set_bbreg(hw, RFPGA0_XA_RFINTERFACEOE, BIT(10),
+ ((rtlefuse->eeprom_cc & BIT(4)) >> 4));
+ rtl_set_bbreg(hw, RFPGA0_XAB_RFPARAMETER, BIT(15),
+ (rtlefuse->eeprom_cc & BIT(4)) >> 4);
+ } else {
+ rtl_set_bbreg(hw, RFPGA0_XAB_RFINTERFACESW,
+ BIT(26) | BIT(22) | BIT(21) | BIT(10) |
+ BIT(6) | BIT(5),
+ (rtlefuse->eeprom_cc & BIT(5)) |
+ ((rtlefuse->eeprom_cc & BIT(7)) << 14));
+ rtl_set_bbreg(hw, RFPGA0_XA_RFINTERFACEOE, BIT(10),
+ ((rtlefuse->eeprom_cc & BIT(4)) >> 4));
+ rtl_set_bbreg(hw, RFPGA0_XB_RFINTERFACEOE, BIT(10),
+ ((rtlefuse->eeprom_cc & BIT(6)) >> 6));
+ rtl_set_bbreg(hw, RFPGA0_XAB_RFPARAMETER,
+ BIT(31) | BIT(15),
+ ((rtlefuse->eeprom_cc & BIT(4)) >> 4) |
+ ((rtlefuse->eeprom_cc & BIT(6)) << 10));
+ }
+ }
+ /* update IQK related settings */
+ rtl_set_bbreg(hw, ROFDM0_XARXIQIMBALANCE, BMASKDWORD, 0x40000100);
+ rtl_set_bbreg(hw, ROFDM0_XBRXIQIMBALANCE, BMASKDWORD, 0x40000100);
+ rtl_set_bbreg(hw, ROFDM0_XCTxAFE, 0xF0000000, 0x00);
+ rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(30) | BIT(28) |
+ BIT(26) | BIT(24), 0x00);
+ rtl_set_bbreg(hw, ROFDM0_XDTxAFE, 0xF0000000, 0x00);
+ rtl_set_bbreg(hw, 0xca0, 0xF0000000, 0x00);
+ rtl_set_bbreg(hw, ROFDM0_AGCRSSITABLE, 0x0000F000, 0x00);
+
+ /* Update RF */
+ for (rfpath = RF90_PATH_A; rfpath < rtlphy->num_total_rfpath;
+ rfpath++) {
+ if (rtlhal->current_bandtype == BAND_ON_2_4G) {
+ /* MOD_AG for RF paht_A 0x18 BIT8,BIT16 */
+ rtl_set_rfreg(hw, rfpath, RF_CHNLBW, BIT(8) | BIT(16) |
+ BIT(18), 0);
+ /* RF0x0b[16:14] =3b'111 */
+ rtl_set_rfreg(hw, (enum radio_path)rfpath, 0x0B,
+ 0x1c000, 0x07);
+ } else {
+ /* MOD_AG for RF paht_A 0x18 BIT8,BIT16 */
+ rtl_set_rfreg(hw, rfpath, RF_CHNLBW, BIT(8) |
+ BIT(16) | BIT(18),
+ (BIT(16) | BIT(8)) >> 8);
+ }
+ }
+ /* Update for all band. */
+ /* DMDP */
+ if (rtlphy->rf_type == RF_1T1R) {
+ /* Use antenna 0,0xc04,0xd04 */
+ rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE, BMASKBYTE0, 0x11);
+ rtl_set_bbreg(hw, ROFDM1_TRXPATHENABLE, BDWORD, 0x1);
+
+ /* enable ad/da clock1 for dual-phy reg0x888 */
+ if (rtlhal->interfaceindex == 0) {
+ rtl_set_bbreg(hw, RFPGA0_ADDALLOCKEN, BIT(12) |
+ BIT(13), 0x3);
+ } else {
+ rtl92d_phy_enable_anotherphy(hw, false);
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+ ("MAC1 use DBI to update 0x888"));
+ /* 0x888 */
+ rtl92de_write_dword_dbi(hw, RFPGA0_ADDALLOCKEN,
+ rtl92de_read_dword_dbi(hw,
+ RFPGA0_ADDALLOCKEN,
+ BIT(3)) | BIT(12) | BIT(13),
+ BIT(3));
+ rtl92d_phy_powerdown_anotherphy(hw, false);
+ }
+ } else {
+ /* Single PHY */
+ /* Use antenna 0 & 1,0xc04,0xd04 */
+ rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE, BMASKBYTE0, 0x33);
+ rtl_set_bbreg(hw, ROFDM1_TRXPATHENABLE, BDWORD, 0x3);
+ /* disable ad/da clock1,0x888 */
+ rtl_set_bbreg(hw, RFPGA0_ADDALLOCKEN, BIT(12) | BIT(13), 0);
+ }
+ for (rfpath = RF90_PATH_A; rfpath < rtlphy->num_total_rfpath;
+ rfpath++) {
+ rtlphy->rfreg_chnlval[rfpath] = rtl_get_rfreg(hw, rfpath,
+ RF_CHNLBW, BRFREGOFFSETMASK);
+ rtlphy->reg_rf3c[rfpath] = rtl_get_rfreg(hw, rfpath, 0x3C,
+ BRFREGOFFSETMASK);
+ }
+ for (i = 0; i < 2; i++)
+ RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD, ("RF 0x18 = 0x%x\n",
+ rtlphy->rfreg_chnlval[i]));
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("<==\n"));
+
+}
+
+bool rtl92d_phy_check_poweroff(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+ u8 u1btmp;
+ unsigned long flags;
+
+ if (rtlhal->macphymode == SINGLEMAC_SINGLEPHY) {
+ u1btmp = rtl_read_byte(rtlpriv, REG_MAC0);
+ rtl_write_byte(rtlpriv, REG_MAC0, u1btmp & (~MAC0_ON));
+ return true;
+ }
+ spin_lock_irqsave(&globalmutex_power, flags);
+ if (rtlhal->interfaceindex == 0) {
+ u1btmp = rtl_read_byte(rtlpriv, REG_MAC0);
+ rtl_write_byte(rtlpriv, REG_MAC0, u1btmp & (~MAC0_ON));
+ u1btmp = rtl_read_byte(rtlpriv, REG_MAC1);
+ u1btmp &= MAC1_ON;
+ } else {
+ u1btmp = rtl_read_byte(rtlpriv, REG_MAC1);
+ rtl_write_byte(rtlpriv, REG_MAC1, u1btmp & (~MAC1_ON));
+ u1btmp = rtl_read_byte(rtlpriv, REG_MAC0);
+ u1btmp &= MAC0_ON;
+ }
+ if (u1btmp) {
+ spin_unlock_irqrestore(&globalmutex_power, flags);
+ return false;
+ }
+ u1btmp = rtl_read_byte(rtlpriv, REG_POWER_OFF_IN_PROCESS);
+ u1btmp |= BIT(7);
+ rtl_write_byte(rtlpriv, REG_POWER_OFF_IN_PROCESS, u1btmp);
+ spin_unlock_irqrestore(&globalmutex_power, flags);
+ return true;
+}
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/phy.h b/drivers/net/wireless/rtlwifi/rtl8192de/phy.h
new file mode 100644
index 0000000..a52c824
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8192de/phy.h
@@ -0,0 +1,178 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010 Realtek Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License 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, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#ifndef __RTL92D_PHY_H__
+#define __RTL92D_PHY_H__
+
+#define MAX_PRECMD_CNT 16
+#define MAX_RFDEPENDCMD_CNT 16
+#define MAX_POSTCMD_CNT 16
+
+#define MAX_DOZE_WAITING_TIMES_9x 64
+
+#define RT_CANNOT_IO(hw) false
+#define HIGHPOWER_RADIOA_ARRAYLEN 22
+
+#define IQK_ADDA_REG_NUM 16
+#define MAX_TOLERANCE 5
+#define IQK_DELAY_TIME 1
+
+#define APK_BB_REG_NUM 5
+#define APK_AFE_REG_NUM 16
+#define APK_CURVE_REG_NUM 4
+#define PATH_NUM 2
+
+#define LOOP_LIMIT 5
+#define MAX_STALL_TIME 50
+#define ANTENNA_DIVERSITY_VALUE 0x80
+#define MAX_TXPWR_IDX_NMODE_92S 63
+#define RESET_CNT_LIMIT 3
+
+#define IQK_ADDA_REG_NUM 16
+#define IQK_BB_REG_NUM 10
+#define IQK_BB_REG_NUM_test 6
+#define IQK_MAC_REG_NUM 4
+#define RX_INDEX_MAPPING_NUM 15
+
+#define IQK_DELAY_TIME 1
+
+#define CT_OFFSET_MAC_ADDR 0X16
+
+#define CT_OFFSET_CCK_TX_PWR_IDX 0x5A
+#define CT_OFFSET_HT401S_TX_PWR_IDX 0x60
+#define CT_OFFSET_HT402S_TX_PWR_IDX_DIFF 0x66
+#define CT_OFFSET_HT20_TX_PWR_IDX_DIFF 0x69
+#define CT_OFFSET_OFDM_TX_PWR_IDX_DIFF 0x6C
+
+#define CT_OFFSET_HT40_MAX_PWR_OFFSET 0x6F
+#define CT_OFFSET_HT20_MAX_PWR_OFFSET 0x72
+
+#define CT_OFFSET_CHANNEL_PLAH 0x75
+#define CT_OFFSET_THERMAL_METER 0x78
+#define CT_OFFSET_RF_OPTION 0x79
+#define CT_OFFSET_VERSION 0x7E
+#define CT_OFFSET_CUSTOMER_ID 0x7F
+
+enum swchnlcmd_id {
+ CMDID_END,
+ CMDID_SET_TXPOWEROWER_LEVEL,
+ CMDID_BBREGWRITE10,
+ CMDID_WRITEPORT_ULONG,
+ CMDID_WRITEPORT_USHORT,
+ CMDID_WRITEPORT_UCHAR,
+ CMDID_RF_WRITEREG,
+};
+
+struct swchnlcmd {
+ enum swchnlcmd_id cmdid;
+ u32 para1;
+ u32 para2;
+ u32 msdelay;
+};
+
+enum baseband_config_type {
+ BASEBAND_CONFIG_PHY_REG = 0,
+ BASEBAND_CONFIG_AGC_TAB = 1,
+};
+
+enum rf_content {
+ radioa_txt = 0,
+ radiob_txt = 1,
+ radioc_txt = 2,
+ radiod_txt = 3
+};
+
+static inline void rtl92d_acquire_cckandrw_pagea_ctl(struct ieee80211_hw *hw,
+ unsigned long *flag)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+ if (rtlpriv->rtlhal.interfaceindex == 1)
+ spin_lock_irqsave(&rtlpriv->locks.cck_and_rw_pagea_lock, *flag);
+}
+
+static inline void rtl92d_release_cckandrw_pagea_ctl(struct ieee80211_hw *hw,
+ unsigned long *flag)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+ if (rtlpriv->rtlhal.interfaceindex == 1)
+ spin_unlock_irqrestore(&rtlpriv->locks.cck_and_rw_pagea_lock,
+ *flag);
+}
+
+extern u32 rtl92d_phy_query_bb_reg(struct ieee80211_hw *hw,
+ u32 regaddr, u32 bitmask);
+extern void rtl92d_phy_set_bb_reg(struct ieee80211_hw *hw,
+ u32 regaddr, u32 bitmask, u32 data);
+extern u32 rtl92d_phy_query_rf_reg(struct ieee80211_hw *hw,
+ enum radio_path rfpath, u32 regaddr,
+ u32 bitmask);
+extern void rtl92d_phy_set_rf_reg(struct ieee80211_hw *hw,
+ enum radio_path rfpath, u32 regaddr,
+ u32 bitmask, u32 data);
+extern bool rtl92d_phy_mac_config(struct ieee80211_hw *hw);
+extern bool rtl92d_phy_bb_config(struct ieee80211_hw *hw);
+extern bool rtl92d_phy_rf_config(struct ieee80211_hw *hw);
+extern bool rtl92c_phy_config_rf_with_feaderfile(struct ieee80211_hw *hw,
+ enum radio_path rfpath);
+extern void rtl92d_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw);
+extern void rtl92d_phy_set_txpower_level(struct ieee80211_hw *hw, u8 channel);
+extern void rtl92d_phy_scan_operation_backup(struct ieee80211_hw *hw,
+ u8 operation);
+extern void rtl92d_phy_set_bw_mode(struct ieee80211_hw *hw,
+ enum nl80211_channel_type ch_type);
+extern u8 rtl92d_phy_sw_chnl(struct ieee80211_hw *hw);
+bool rtl92d_phy_config_rf_with_headerfile(struct ieee80211_hw *hw,
+ enum rf_content content,
+ enum radio_path rfpath);
+bool rtl92d_phy_set_io_cmd(struct ieee80211_hw *hw, enum io_type iotype);
+extern bool rtl92d_phy_set_rf_power_state(struct ieee80211_hw *hw,
+ enum rf_pwrstate rfpwr_state);
+
+void rtl92d_phy_config_macphymode(struct ieee80211_hw *hw);
+void rtl92d_phy_config_macphymode_info(struct ieee80211_hw *hw);
+u8 rtl92d_get_chnlgroup_fromarray(u8 chnl);
+void rtl92d_phy_set_poweron(struct ieee80211_hw *hw);
+void rtl92d_phy_config_maccoexist_rfpage(struct ieee80211_hw *hw);
+bool rtl92d_phy_check_poweroff(struct ieee80211_hw *hw);
+void rtl92d_phy_lc_calibrate(struct ieee80211_hw *hw);
+void rtl92d_update_bbrf_configuration(struct ieee80211_hw *hw);
+void rtl92d_phy_ap_calibrate(struct ieee80211_hw *hw, char delta);
+void rtl92d_phy_iq_calibrate(struct ieee80211_hw *hw);
+void rtl92d_phy_reset_iqk_result(struct ieee80211_hw *hw);
+void rtl92d_release_cckandrw_pagea_ctl(struct ieee80211_hw *hw,
+ unsigned long *flag);
+void rtl92d_acquire_cckandrw_pagea_ctl(struct ieee80211_hw *hw,
+ unsigned long *flag);
+u8 rtl92d_get_rightchnlplace_for_iqk(u8 chnl);
+void rtl92d_phy_reload_iqk_setting(struct ieee80211_hw *hw, u8 channel);
+void rtl92d_phy_iq_calibrate(struct ieee80211_hw *hw);
+
+#endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/reg.h b/drivers/net/wireless/rtlwifi/rtl8192de/reg.h
new file mode 100644
index 0000000..131acc3
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8192de/reg.h
@@ -0,0 +1,1313 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010 Realtek Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License 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, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#ifndef __RTL92D_REG_H__
+#define __RTL92D_REG_H__
+
+/* ----------------------------------------------------- */
+/* 0x0000h ~ 0x00FFh System Configuration */
+/* ----------------------------------------------------- */
+#define REG_SYS_ISO_CTRL 0x0000
+#define REG_SYS_FUNC_EN 0x0002
+#define REG_APS_FSMCO 0x0004
+#define REG_SYS_CLKR 0x0008
+#define REG_9346CR 0x000A
+#define REG_EE_VPD 0x000C
+#define REG_AFE_MISC 0x0010
+#define REG_SPS0_CTRL 0x0011
+#define REG_POWER_OFF_IN_PROCESS 0x0017
+#define REG_SPS_OCP_CFG 0x0018
+#define REG_RSV_CTRL 0x001C
+#define REG_RF_CTRL 0x001F
+#define REG_LDOA15_CTRL 0x0020
+#define REG_LDOV12D_CTRL 0x0021
+#define REG_LDOHCI12_CTRL 0x0022
+#define REG_LPLDO_CTRL 0x0023
+#define REG_AFE_XTAL_CTRL 0x0024
+#define REG_AFE_PLL_CTRL 0x0028
+/* for 92d, DMDP,SMSP,DMSP contrl */
+#define REG_MAC_PHY_CTRL 0x002c
+#define REG_EFUSE_CTRL 0x0030
+#define REG_EFUSE_TEST 0x0034
+#define REG_PWR_DATA 0x0038
+#define REG_CAL_TIMER 0x003C
+#define REG_ACLK_MON 0x003E
+#define REG_GPIO_MUXCFG 0x0040
+#define REG_GPIO_IO_SEL 0x0042
+#define REG_MAC_PINMUX_CFG 0x0043
+#define REG_GPIO_PIN_CTRL 0x0044
+#define REG_GPIO_INTM 0x0048
+#define REG_LEDCFG0 0x004C
+#define REG_LEDCFG1 0x004D
+#define REG_LEDCFG2 0x004E
+#define REG_LEDCFG3 0x004F
+#define REG_FSIMR 0x0050
+#define REG_FSISR 0x0054
+
+#define REG_MCUFWDL 0x0080
+
+#define REG_HMEBOX_EXT_0 0x0088
+#define REG_HMEBOX_EXT_1 0x008A
+#define REG_HMEBOX_EXT_2 0x008C
+#define REG_HMEBOX_EXT_3 0x008E
+
+#define REG_BIST_SCAN 0x00D0
+#define REG_BIST_RPT 0x00D4
+#define REG_BIST_ROM_RPT 0x00D8
+#define REG_USB_SIE_INTF 0x00E0
+#define REG_PCIE_MIO_INTF 0x00E4
+#define REG_PCIE_MIO_INTD 0x00E8
+#define REG_HPON_FSM 0x00EC
+#define REG_SYS_CFG 0x00F0
+#define REG_MAC_PHY_CTRL_NORMAL 0x00f8
+
+#define REG_MAC0 0x0081
+#define REG_MAC1 0x0053
+#define FW_MAC0_READY 0x18
+#define FW_MAC1_READY 0x1A
+#define MAC0_ON BIT(7)
+#define MAC1_ON BIT(0)
+#define MAC0_READY BIT(0)
+#define MAC1_READY BIT(0)
+
+/* ----------------------------------------------------- */
+/* 0x0100h ~ 0x01FFh MACTOP General Configuration */
+/* ----------------------------------------------------- */
+#define REG_CR 0x0100
+#define REG_PBP 0x0104
+#define REG_TRXDMA_CTRL 0x010C
+#define REG_TRXFF_BNDY 0x0114
+#define REG_TRXFF_STATUS 0x0118
+#define REG_RXFF_PTR 0x011C
+#define REG_HIMR 0x0120
+#define REG_HISR 0x0124
+#define REG_HIMRE 0x0128
+#define REG_HISRE 0x012C
+#define REG_CPWM 0x012F
+#define REG_FWIMR 0x0130
+#define REG_FWISR 0x0134
+#define REG_PKTBUF_DBG_CTRL 0x0140
+#define REG_PKTBUF_DBG_DATA_L 0x0144
+#define REG_PKTBUF_DBG_DATA_H 0x0148
+
+#define REG_TC0_CTRL 0x0150
+#define REG_TC1_CTRL 0x0154
+#define REG_TC2_CTRL 0x0158
+#define REG_TC3_CTRL 0x015C
+#define REG_TC4_CTRL 0x0160
+#define REG_TCUNIT_BASE 0x0164
+#define REG_MBIST_START 0x0174
+#define REG_MBIST_DONE 0x0178
+#define REG_MBIST_FAIL 0x017C
+#define REG_C2HEVT_MSG_NORMAL 0x01A0
+#define REG_C2HEVT_MSG_TEST 0x01B8
+#define REG_C2HEVT_CLEAR 0x01BF
+#define REG_MCUTST_1 0x01c0
+#define REG_FMETHR 0x01C8
+#define REG_HMETFR 0x01CC
+#define REG_HMEBOX_0 0x01D0
+#define REG_HMEBOX_1 0x01D4
+#define REG_HMEBOX_2 0x01D8
+#define REG_HMEBOX_3 0x01DC
+
+#define REG_LLT_INIT 0x01E0
+#define REG_BB_ACCEESS_CTRL 0x01E8
+#define REG_BB_ACCESS_DATA 0x01EC
+
+
+/* ----------------------------------------------------- */
+/* 0x0200h ~ 0x027Fh TXDMA Configuration */
+/* ----------------------------------------------------- */
+#define REG_RQPN 0x0200
+#define REG_FIFOPAGE 0x0204
+#define REG_TDECTRL 0x0208
+#define REG_TXDMA_OFFSET_CHK 0x020C
+#define REG_TXDMA_STATUS 0x0210
+#define REG_RQPN_NPQ 0x0214
+
+/* ----------------------------------------------------- */
+/* 0x0280h ~ 0x02FFh RXDMA Configuration */
+/* ----------------------------------------------------- */
+#define REG_RXDMA_AGG_PG_TH 0x0280
+#define REG_RXPKT_NUM 0x0284
+#define REG_RXDMA_STATUS 0x0288
+
+/* ----------------------------------------------------- */
+/* 0x0300h ~ 0x03FFh PCIe */
+/* ----------------------------------------------------- */
+#define REG_PCIE_CTRL_REG 0x0300
+#define REG_INT_MIG 0x0304
+#define REG_BCNQ_DESA 0x0308
+#define REG_HQ_DESA 0x0310
+#define REG_MGQ_DESA 0x0318
+#define REG_VOQ_DESA 0x0320
+#define REG_VIQ_DESA 0x0328
+#define REG_BEQ_DESA 0x0330
+#define REG_BKQ_DESA 0x0338
+#define REG_RX_DESA 0x0340
+#define REG_DBI 0x0348
+#define REG_DBI_WDATA 0x0348
+#define REG_DBI_RDATA 0x034C
+#define REG_DBI_CTRL 0x0350
+#define REG_DBI_FLAG 0x0352
+#define REG_MDIO 0x0354
+#define REG_DBG_SEL 0x0360
+#define REG_PCIE_HRPWM 0x0361
+#define REG_PCIE_HCPWM 0x0363
+#define REG_UART_CTRL 0x0364
+#define REG_UART_TX_DESA 0x0370
+#define REG_UART_RX_DESA 0x0378
+
+/* ----------------------------------------------------- */
+/* 0x0400h ~ 0x047Fh Protocol Configuration */
+/* ----------------------------------------------------- */
+#define REG_VOQ_INFORMATION 0x0400
+#define REG_VIQ_INFORMATION 0x0404
+#define REG_BEQ_INFORMATION 0x0408
+#define REG_BKQ_INFORMATION 0x040C
+#define REG_MGQ_INFORMATION 0x0410
+#define REG_HGQ_INFORMATION 0x0414
+#define REG_BCNQ_INFORMATION 0x0418
+
+
+#define REG_CPU_MGQ_INFORMATION 0x041C
+#define REG_FWHW_TXQ_CTRL 0x0420
+#define REG_HWSEQ_CTRL 0x0423
+#define REG_TXPKTBUF_BCNQ_BDNY 0x0424
+#define REG_TXPKTBUF_MGQ_BDNY 0x0425
+#define REG_MULTI_BCNQ_EN 0x0426
+#define REG_MULTI_BCNQ_OFFSET 0x0427
+#define REG_SPEC_SIFS 0x0428
+#define REG_RL 0x042A
+#define REG_DARFRC 0x0430
+#define REG_RARFRC 0x0438
+#define REG_RRSR 0x0440
+#define REG_ARFR0 0x0444
+#define REG_ARFR1 0x0448
+#define REG_ARFR2 0x044C
+#define REG_ARFR3 0x0450
+#define REG_AGGLEN_LMT 0x0458
+#define REG_AMPDU_MIN_SPACE 0x045C
+#define REG_TXPKTBUF_WMAC_LBK_BF_HD 0x045D
+#define REG_FAST_EDCA_CTRL 0x0460
+#define REG_RD_RESP_PKT_TH 0x0463
+#define REG_INIRTS_RATE_SEL 0x0480
+#define REG_INIDATA_RATE_SEL 0x0484
+#define REG_POWER_STATUS 0x04A4
+#define REG_POWER_STAGE1 0x04B4
+#define REG_POWER_STAGE2 0x04B8
+#define REG_PKT_LIFE_TIME 0x04C0
+#define REG_STBC_SETTING 0x04C4
+#define REG_PROT_MODE_CTRL 0x04C8
+#define REG_MAX_AGGR_NUM 0x04CA
+#define REG_RTS_MAX_AGGR_NUM 0x04CB
+#define REG_BAR_MODE_CTRL 0x04CC
+#define REG_RA_TRY_RATE_AGG_LMT 0x04CF
+#define REG_EARLY_MODE_CONTROL 0x4D0
+#define REG_NQOS_SEQ 0x04DC
+#define REG_QOS_SEQ 0x04DE
+#define REG_NEED_CPU_HANDLE 0x04E0
+#define REG_PKT_LOSE_RPT 0x04E1
+#define REG_PTCL_ERR_STATUS 0x04E2
+#define REG_DUMMY 0x04FC
+
+/* ----------------------------------------------------- */
+/* 0x0500h ~ 0x05FFh EDCA Configuration */
+/* ----------------------------------------------------- */
+#define REG_EDCA_VO_PARAM 0x0500
+#define REG_EDCA_VI_PARAM 0x0504
+#define REG_EDCA_BE_PARAM 0x0508
+#define REG_EDCA_BK_PARAM 0x050C
+#define REG_BCNTCFG 0x0510
+#define REG_PIFS 0x0512
+#define REG_RDG_PIFS 0x0513
+#define REG_SIFS_CTX 0x0514
+#define REG_SIFS_TRX 0x0516
+#define REG_AGGR_BREAK_TIME 0x051A
+#define REG_SLOT 0x051B
+#define REG_TX_PTCL_CTRL 0x0520
+#define REG_TXPAUSE 0x0522
+#define REG_DIS_TXREQ_CLR 0x0523
+#define REG_RD_CTRL 0x0524
+#define REG_TBTT_PROHIBIT 0x0540
+#define REG_RD_NAV_NXT 0x0544
+#define REG_NAV_PROT_LEN 0x0546
+#define REG_BCN_CTRL 0x0550
+#define REG_USTIME_TSF 0x0551
+#define REG_MBID_NUM 0x0552
+#define REG_DUAL_TSF_RST 0x0553
+#define REG_BCN_INTERVAL 0x0554
+#define REG_MBSSID_BCN_SPACE 0x0554
+#define REG_DRVERLYINT 0x0558
+#define REG_BCNDMATIM 0x0559
+#define REG_ATIMWND 0x055A
+#define REG_BCN_MAX_ERR 0x055D
+#define REG_RXTSF_OFFSET_CCK 0x055E
+#define REG_RXTSF_OFFSET_OFDM 0x055F
+#define REG_TSFTR 0x0560
+#define REG_INIT_TSFTR 0x0564
+#define REG_PSTIMER 0x0580
+#define REG_TIMER0 0x0584
+#define REG_TIMER1 0x0588
+#define REG_ACMHWCTRL 0x05C0
+#define REG_ACMRSTCTRL 0x05C1
+#define REG_ACMAVG 0x05C2
+#define REG_VO_ADMTIME 0x05C4
+#define REG_VI_ADMTIME 0x05C6
+#define REG_BE_ADMTIME 0x05C8
+#define REG_EDCA_RANDOM_GEN 0x05CC
+#define REG_SCH_TXCMD 0x05D0
+
+/* Dual MAC Co-Existence Register */
+#define REG_DMC 0x05F0
+
+/* ----------------------------------------------------- */
+/* 0x0600h ~ 0x07FFh WMAC Configuration */
+/* ----------------------------------------------------- */
+#define REG_APSD_CTRL 0x0600
+#define REG_BWOPMODE 0x0603
+#define REG_TCR 0x0604
+#define REG_RCR 0x0608
+#define REG_RX_PKT_LIMIT 0x060C
+#define REG_RX_DLK_TIME 0x060D
+#define REG_RX_DRVINFO_SZ 0x060F
+
+#define REG_MACID 0x0610
+#define REG_BSSID 0x0618
+#define REG_MAR 0x0620
+#define REG_MBIDCAMCFG 0x0628
+
+#define REG_USTIME_EDCA 0x0638
+#define REG_MAC_SPEC_SIFS 0x063A
+#define REG_RESP_SIFS_CCK 0x063C
+#define REG_RESP_SIFS_OFDM 0x063E
+#define REG_ACKTO 0x0640
+#define REG_CTS2TO 0x0641
+#define REG_EIFS 0x0642
+
+
+/* WMA, BA, CCX */
+#define REG_NAV_CTRL 0x0650
+#define REG_BACAMCMD 0x0654
+#define REG_BACAMCONTENT 0x0658
+#define REG_LBDLY 0x0660
+#define REG_FWDLY 0x0661
+#define REG_RXERR_RPT 0x0664
+#define REG_WMAC_TRXPTCL_CTL 0x0668
+
+
+/* Security */
+#define REG_CAMCMD 0x0670
+#define REG_CAMWRITE 0x0674
+#define REG_CAMREAD 0x0678
+#define REG_CAMDBG 0x067C
+#define REG_SECCFG 0x0680
+
+/* Power */
+#define REG_WOW_CTRL 0x0690
+#define REG_PSSTATUS 0x0691
+#define REG_PS_RX_INFO 0x0692
+#define REG_LPNAV_CTRL 0x0694
+#define REG_WKFMCAM_CMD 0x0698
+#define REG_WKFMCAM_RWD 0x069C
+#define REG_RXFLTMAP0 0x06A0
+#define REG_RXFLTMAP1 0x06A2
+#define REG_RXFLTMAP2 0x06A4
+#define REG_BCN_PSR_RPT 0x06A8
+#define REG_CALB32K_CTRL 0x06AC
+#define REG_PKT_MON_CTRL 0x06B4
+#define REG_BT_COEX_TABLE 0x06C0
+#define REG_WMAC_RESP_TXINFO 0x06D8
+
+
+/* ----------------------------------------------------- */
+/* Redifine 8192C register definition for compatibility */
+/* ----------------------------------------------------- */
+#define CR9346 REG_9346CR
+#define MSR (REG_CR + 2)
+#define ISR REG_HISR
+#define TSFR REG_TSFTR
+
+#define MACIDR0 REG_MACID
+#define MACIDR4 (REG_MACID + 4)
+
+#define PBP REG_PBP
+
+#define IDR0 MACIDR0
+#define IDR4 MACIDR4
+
+/* ----------------------------------------------------- */
+/* 8192C (MSR) Media Status Register(Offset 0x4C, 8 bits)*/
+/* ----------------------------------------------------- */
+#define MSR_NOLINK 0x00
+#define MSR_ADHOC 0x01
+#define MSR_INFRA 0x02
+#define MSR_AP 0x03
+
+/* 6. Adaptive Control Registers (Offset: 0x0160 - 0x01CF) */
+/* ----------------------------------------------------- */
+/* 8192C Response Rate Set Register(offset 0x181, 24bits)*/
+/* ----------------------------------------------------- */
+#define RRSR_RSC_OFFSET 21
+#define RRSR_SHORT_OFFSET 23
+#define RRSR_RSC_BW_40M 0x600000
+#define RRSR_RSC_UPSUBCHNL 0x400000
+#define RRSR_RSC_LOWSUBCHNL 0x200000
+#define RRSR_SHORT 0x800000
+#define RRSR_1M BIT0
+#define RRSR_2M BIT1
+#define RRSR_5_5M BIT2
+#define RRSR_11M BIT3
+#define RRSR_6M BIT4
+#define RRSR_9M BIT5
+#define RRSR_12M BIT6
+#define RRSR_18M BIT7
+#define RRSR_24M BIT8
+#define RRSR_36M BIT9
+#define RRSR_48M BIT10
+#define RRSR_54M BIT11
+#define RRSR_MCS0 BIT12
+#define RRSR_MCS1 BIT13
+#define RRSR_MCS2 BIT14
+#define RRSR_MCS3 BIT15
+#define RRSR_MCS4 BIT16
+#define RRSR_MCS5 BIT17
+#define RRSR_MCS6 BIT18
+#define RRSR_MCS7 BIT19
+#define BRSR_ACKSHORTPMB BIT23
+
+/* ----------------------------------------------------- */
+/* 8192C Rate Definition */
+/* ----------------------------------------------------- */
+/* CCK */
+#define RATR_1M 0x00000001
+#define RATR_2M 0x00000002
+#define RATR_55M 0x00000004
+#define RATR_11M 0x00000008
+/* OFDM */
+#define RATR_6M 0x00000010
+#define RATR_9M 0x00000020
+#define RATR_12M 0x00000040
+#define RATR_18M 0x00000080
+#define RATR_24M 0x00000100
+#define RATR_36M 0x00000200
+#define RATR_48M 0x00000400
+#define RATR_54M 0x00000800
+/* MCS 1 Spatial Stream */
+#define RATR_MCS0 0x00001000
+#define RATR_MCS1 0x00002000
+#define RATR_MCS2 0x00004000
+#define RATR_MCS3 0x00008000
+#define RATR_MCS4 0x00010000
+#define RATR_MCS5 0x00020000
+#define RATR_MCS6 0x00040000
+#define RATR_MCS7 0x00080000
+/* MCS 2 Spatial Stream */
+#define RATR_MCS8 0x00100000
+#define RATR_MCS9 0x00200000
+#define RATR_MCS10 0x00400000
+#define RATR_MCS11 0x00800000
+#define RATR_MCS12 0x01000000
+#define RATR_MCS13 0x02000000
+#define RATR_MCS14 0x04000000
+#define RATR_MCS15 0x08000000
+
+/* CCK */
+#define RATE_1M BIT(0)
+#define RATE_2M BIT(1)
+#define RATE_5_5M BIT(2)
+#define RATE_11M BIT(3)
+/* OFDM */
+#define RATE_6M BIT(4)
+#define RATE_9M BIT(5)
+#define RATE_12M BIT(6)
+#define RATE_18M BIT(7)
+#define RATE_24M BIT(8)
+#define RATE_36M BIT(9)
+#define RATE_48M BIT(10)
+#define RATE_54M BIT(11)
+/* MCS 1 Spatial Stream */
+#define RATE_MCS0 BIT(12)
+#define RATE_MCS1 BIT(13)
+#define RATE_MCS2 BIT(14)
+#define RATE_MCS3 BIT(15)
+#define RATE_MCS4 BIT(16)
+#define RATE_MCS5 BIT(17)
+#define RATE_MCS6 BIT(18)
+#define RATE_MCS7 BIT(19)
+/* MCS 2 Spatial Stream */
+#define RATE_MCS8 BIT(20)
+#define RATE_MCS9 BIT(21)
+#define RATE_MCS10 BIT(22)
+#define RATE_MCS11 BIT(23)
+#define RATE_MCS12 BIT(24)
+#define RATE_MCS13 BIT(25)
+#define RATE_MCS14 BIT(26)
+#define RATE_MCS15 BIT(27)
+
+/* ALL CCK Rate */
+#define RATE_ALL_CCK (RATR_1M | RATR_2M | RATR_55M | \
+ RATR_11M)
+#define RATE_ALL_OFDM_AG (RATR_6M | RATR_9M | RATR_12M | \
+ RATR_18M | RATR_24M | \
+ RATR_36M | RATR_48M | RATR_54M)
+#define RATE_ALL_OFDM_1SS (RATR_MCS0 | RATR_MCS1 | RATR_MCS2 | \
+ RATR_MCS3 | RATR_MCS4 | RATR_MCS5 | \
+ RATR_MCS6 | RATR_MCS7)
+#define RATE_ALL_OFDM_2SS (RATR_MCS8 | RATR_MCS9 | RATR_MCS10 | \
+ RATR_MCS11 | RATR_MCS12 | RATR_MCS13 | \
+ RATR_MCS14 | RATR_MCS15)
+
+/* ----------------------------------------------------- */
+/* 8192C BW_OPMODE bits (Offset 0x203, 8bit) */
+/* ----------------------------------------------------- */
+#define BW_OPMODE_20MHZ BIT(2)
+#define BW_OPMODE_5G BIT(1)
+#define BW_OPMODE_11J BIT(0)
+
+
+/* ----------------------------------------------------- */
+/* 8192C CAM Config Setting (offset 0x250, 1 byte) */
+/* ----------------------------------------------------- */
+#define CAM_VALID BIT(15)
+#define CAM_NOTVALID 0x0000
+#define CAM_USEDK BIT(5)
+
+#define CAM_NONE 0x0
+#define CAM_WEP40 0x01
+#define CAM_TKIP 0x02
+#define CAM_AES 0x04
+#define CAM_WEP104 0x05
+#define CAM_SMS4 0x6
+
+
+#define TOTAL_CAM_ENTRY 32
+#define HALF_CAM_ENTRY 16
+
+#define CAM_WRITE BIT(16)
+#define CAM_READ 0x00000000
+#define CAM_POLLINIG BIT(31)
+
+/* 10. Power Save Control Registers (Offset: 0x0260 - 0x02DF) */
+#define WOW_PMEN BIT0 /* Power management Enable. */
+#define WOW_WOMEN BIT1 /* WoW function on or off. */
+#define WOW_MAGIC BIT2 /* Magic packet */
+#define WOW_UWF BIT3 /* Unicast Wakeup frame. */
+
+/* 12. Host Interrupt Status Registers (Offset: 0x0300 - 0x030F) */
+/* ----------------------------------------------------- */
+/* 8190 IMR/ISR bits (offset 0xfd, 8bits) */
+/* ----------------------------------------------------- */
+#define IMR8190_DISABLED 0x0
+#define IMR_BCNDMAINT6 BIT(31)
+#define IMR_BCNDMAINT5 BIT(30)
+#define IMR_BCNDMAINT4 BIT(29)
+#define IMR_BCNDMAINT3 BIT(28)
+#define IMR_BCNDMAINT2 BIT(27)
+#define IMR_BCNDMAINT1 BIT(26)
+#define IMR_BCNDOK8 BIT(25)
+#define IMR_BCNDOK7 BIT(24)
+#define IMR_BCNDOK6 BIT(23)
+#define IMR_BCNDOK5 BIT(22)
+#define IMR_BCNDOK4 BIT(21)
+#define IMR_BCNDOK3 BIT(20)
+#define IMR_BCNDOK2 BIT(19)
+#define IMR_BCNDOK1 BIT(18)
+#define IMR_TIMEOUT2 BIT(17)
+#define IMR_TIMEOUT1 BIT(16)
+#define IMR_TXFOVW BIT(15)
+#define IMR_PSTIMEOUT BIT(14)
+#define IMR_BcnInt BIT(13)
+#define IMR_RXFOVW BIT(12)
+#define IMR_RDU BIT(11)
+#define IMR_ATIMEND BIT(10)
+#define IMR_BDOK BIT(9)
+#define IMR_HIGHDOK BIT(8)
+#define IMR_TBDOK BIT(7)
+#define IMR_MGNTDOK BIT(6)
+#define IMR_TBDER BIT(5)
+#define IMR_BKDOK BIT(4)
+#define IMR_BEDOK BIT(3)
+#define IMR_VIDOK BIT(2)
+#define IMR_VODOK BIT(1)
+#define IMR_ROK BIT(0)
+
+#define IMR_TXERR BIT(11)
+#define IMR_RXERR BIT(10)
+#define IMR_C2HCMD BIT(9)
+#define IMR_CPWM BIT(8)
+#define IMR_OCPINT BIT(1)
+#define IMR_WLANOFF BIT(0)
+
+/* ----------------------------------------------------- */
+/* 8192C EFUSE */
+/* ----------------------------------------------------- */
+#define HWSET_MAX_SIZE 256
+#define EFUSE_MAX_SECTION 32
+#define EFUSE_REAL_CONTENT_LEN 512
+
+/* ----------------------------------------------------- */
+/* 8192C EEPROM/EFUSE share register definition. */
+/* ----------------------------------------------------- */
+#define EEPROM_DEFAULT_TSSI 0x0
+#define EEPROM_DEFAULT_CRYSTALCAP 0x0
+#define EEPROM_DEFAULT_THERMALMETER 0x12
+
+#define EEPROM_DEFAULT_TXPOWERLEVEL_2G 0x2C
+#define EEPROM_DEFAULT_TXPOWERLEVEL_5G 0x22
+
+#define EEPROM_DEFAULT_HT40_2SDIFF 0x0
+/* HT20<->40 default Tx Power Index Difference */
+#define EEPROM_DEFAULT_HT20_DIFF 2
+/* OFDM Tx Power index diff */
+#define EEPROM_DEFAULT_LEGACYHTTXPOWERDIFF 0x4
+#define EEPROM_DEFAULT_HT40_PWRMAXOFFSET 0
+#define EEPROM_DEFAULT_HT20_PWRMAXOFFSET 0
+
+#define EEPROM_CHANNEL_PLAN_FCC 0x0
+#define EEPROM_CHANNEL_PLAN_IC 0x1
+#define EEPROM_CHANNEL_PLAN_ETSI 0x2
+#define EEPROM_CHANNEL_PLAN_SPAIN 0x3
+#define EEPROM_CHANNEL_PLAN_FRANCE 0x4
+#define EEPROM_CHANNEL_PLAN_MKK 0x5
+#define EEPROM_CHANNEL_PLAN_MKK1 0x6
+#define EEPROM_CHANNEL_PLAN_ISRAEL 0x7
+#define EEPROM_CHANNEL_PLAN_TELEC 0x8
+#define EEPROM_CHANNEL_PLAN_GLOBAL_DOMAIN 0x9
+#define EEPROM_CHANNEL_PLAN_WORLD_WIDE_13 0xA
+#define EEPROM_CHANNEL_PLAN_NCC 0xB
+#define EEPROM_CHANNEL_PLAN_BY_HW_MASK 0x80
+
+#define EEPROM_CID_DEFAULT 0x0
+#define EEPROM_CID_TOSHIBA 0x4
+#define EEPROM_CID_CCX 0x10
+#define EEPROM_CID_QMI 0x0D
+#define EEPROM_CID_WHQL 0xFE
+
+
+#define RTL8192_EEPROM_ID 0x8129
+#define EEPROM_WAPI_SUPPORT 0x78
+
+
+#define RTL8190_EEPROM_ID 0x8129 /* 0-1 */
+#define EEPROM_HPON 0x02 /* LDO settings.2-5 */
+#define EEPROM_CLK 0x06 /* Clock settings.6-7 */
+#define EEPROM_MAC_FUNCTION 0x08 /* SE Test mode.8 */
+
+#define EEPROM_VID 0x28 /* SE Vendor ID.A-B */
+#define EEPROM_DID 0x2A /* SE Device ID. C-D */
+#define EEPROM_SVID 0x2C /* SE Vendor ID.E-F */
+#define EEPROM_SMID 0x2E /* SE PCI Subsystem ID. 10-11 */
+
+#define EEPROM_MAC_ADDR 0x16 /* SEMAC Address. 12-17 */
+#define EEPROM_MAC_ADDR_MAC0_92D 0x55
+#define EEPROM_MAC_ADDR_MAC1_92D 0x5B
+
+/* 2.4G band Tx power index setting */
+#define EEPROM_CCK_TX_PWR_INX_2G 0x61
+#define EEPROM_HT40_1S_TX_PWR_INX_2G 0x67
+#define EEPROM_HT40_2S_TX_PWR_INX_DIFF_2G 0x6D
+#define EEPROM_HT20_TX_PWR_INX_DIFF_2G 0x70
+#define EEPROM_OFDM_TX_PWR_INX_DIFF_2G 0x73
+#define EEPROM_HT40_MAX_PWR_OFFSET_2G 0x76
+#define EEPROM_HT20_MAX_PWR_OFFSET_2G 0x79
+
+/*5GL channel 32-64 */
+#define EEPROM_HT40_1S_TX_PWR_INX_5GL 0x7C
+#define EEPROM_HT40_2S_TX_PWR_INX_DIFF_5GL 0x82
+#define EEPROM_HT20_TX_PWR_INX_DIFF_5GL 0x85
+#define EEPROM_OFDM_TX_PWR_INX_DIFF_5GL 0x88
+#define EEPROM_HT40_MAX_PWR_OFFSET_5GL 0x8B
+#define EEPROM_HT20_MAX_PWR_OFFSET_5GL 0x8E
+
+/* 5GM channel 100-140 */
+#define EEPROM_HT40_1S_TX_PWR_INX_5GM 0x91
+#define EEPROM_HT40_2S_TX_PWR_INX_DIFF_5GM 0x97
+#define EEPROM_HT20_TX_PWR_INX_DIFF_5GM 0x9A
+#define EEPROM_OFDM_TX_PWR_INX_DIFF_5GM 0x9D
+#define EEPROM_HT40_MAX_PWR_OFFSET_5GM 0xA0
+#define EEPROM_HT20_MAX_PWR_OFFSET_5GM 0xA3
+
+/* 5GH channel 149-165 */
+#define EEPROM_HT40_1S_TX_PWR_INX_5GH 0xA6
+#define EEPROM_HT40_2S_TX_PWR_INX_DIFF_5GH 0xAC
+#define EEPROM_HT20_TX_PWR_INX_DIFF_5GH 0xAF
+#define EEPROM_OFDM_TX_PWR_INX_DIFF_5GH 0xB2
+#define EEPROM_HT40_MAX_PWR_OFFSET_5GH 0xB5
+#define EEPROM_HT20_MAX_PWR_OFFSET_5GH 0xB8
+
+/* Map of supported channels. */
+#define EEPROM_CHANNEL_PLAN 0xBB
+#define EEPROM_IQK_DELTA 0xBC
+#define EEPROM_LCK_DELTA 0xBC
+#define EEPROM_XTAL_K 0xBD /* [7:5] */
+#define EEPROM_TSSI_A_5G 0xBE
+#define EEPROM_TSSI_B_5G 0xBF
+#define EEPROM_TSSI_AB_5G 0xC0
+#define EEPROM_THERMAL_METER 0xC3 /* [4:0] */
+#define EEPROM_RF_OPT1 0xC4
+#define EEPROM_RF_OPT2 0xC5
+#define EEPROM_RF_OPT3 0xC6
+#define EEPROM_RF_OPT4 0xC7
+#define EEPROM_RF_OPT5 0xC8
+#define EEPROM_RF_OPT6 0xC9
+#define EEPROM_VERSION 0xCA
+#define EEPROM_CUSTOMER_ID 0xCB
+#define EEPROM_RF_OPT7 0xCC
+
+#define EEPROM_DEF_PART_NO 0x3FD /* Byte */
+#define EEPROME_CHIP_VERSION_L 0x3FF
+#define EEPROME_CHIP_VERSION_H 0x3FE
+
+/*
+ * Current IOREG MAP
+ * 0x0000h ~ 0x00FFh System Configuration (256 Bytes)
+ * 0x0100h ~ 0x01FFh MACTOP General Configuration (256 Bytes)
+ * 0x0200h ~ 0x027Fh TXDMA Configuration (128 Bytes)
+ * 0x0280h ~ 0x02FFh RXDMA Configuration (128 Bytes)
+ * 0x0300h ~ 0x03FFh PCIE EMAC Reserved Region (256 Bytes)
+ * 0x0400h ~ 0x04FFh Protocol Configuration (256 Bytes)
+ * 0x0500h ~ 0x05FFh EDCA Configuration (256 Bytes)
+ * 0x0600h ~ 0x07FFh WMAC Configuration (512 Bytes)
+ * 0x2000h ~ 0x3FFFh 8051 FW Download Region (8196 Bytes)
+ */
+
+/* ----------------------------------------------------- */
+/* 8192C (RCR) (Offset 0x608, 32 bits) */
+/* ----------------------------------------------------- */
+#define RCR_APPFCS BIT(31)
+#define RCR_APP_MIC BIT(30)
+#define RCR_APP_ICV BIT(29)
+#define RCR_APP_PHYST_RXFF BIT(28)
+#define RCR_APP_BA_SSN BIT(27)
+#define RCR_ENMBID BIT(24)
+#define RCR_LSIGEN BIT(23)
+#define RCR_MFBEN BIT(22)
+#define RCR_HTC_LOC_CTRL BIT(14)
+#define RCR_AMF BIT(13)
+#define RCR_ACF BIT(12)
+#define RCR_ADF BIT(11)
+#define RCR_AICV BIT(9)
+#define RCR_ACRC32 BIT(8)
+#define RCR_CBSSID_BCN BIT(7)
+#define RCR_CBSSID_DATA BIT(6)
+#define RCR_APWRMGT BIT(5)
+#define RCR_ADD3 BIT(4)
+#define RCR_AB BIT(3)
+#define RCR_AM BIT(2)
+#define RCR_APM BIT(1)
+#define RCR_AAP BIT(0)
+#define RCR_MXDMA_OFFSET 8
+#define RCR_FIFO_OFFSET 13
+
+/* ----------------------------------------------------- */
+/* 8192C Regsiter Bit and Content definition */
+/* ----------------------------------------------------- */
+/* ----------------------------------------------------- */
+/* 0x0000h ~ 0x00FFh System Configuration */
+/* ----------------------------------------------------- */
+
+/* SPS0_CTRL */
+#define SW18_FPWM BIT(3)
+
+
+/* SYS_ISO_CTRL */
+#define ISO_MD2PP BIT(0)
+#define ISO_UA2USB BIT(1)
+#define ISO_UD2CORE BIT(2)
+#define ISO_PA2PCIE BIT(3)
+#define ISO_PD2CORE BIT(4)
+#define ISO_IP2MAC BIT(5)
+#define ISO_DIOP BIT(6)
+#define ISO_DIOE BIT(7)
+#define ISO_EB2CORE BIT(8)
+#define ISO_DIOR BIT(9)
+
+#define PWC_EV25V BIT(14)
+#define PWC_EV12V BIT(15)
+
+
+/* SYS_FUNC_EN */
+#define FEN_BBRSTB BIT(0)
+#define FEN_BB_GLB_RSTn BIT(1)
+#define FEN_USBA BIT(2)
+#define FEN_UPLL BIT(3)
+#define FEN_USBD BIT(4)
+#define FEN_DIO_PCIE BIT(5)
+#define FEN_PCIEA BIT(6)
+#define FEN_PPLL BIT(7)
+#define FEN_PCIED BIT(8)
+#define FEN_DIOE BIT(9)
+#define FEN_CPUEN BIT(10)
+#define FEN_DCORE BIT(11)
+#define FEN_ELDR BIT(12)
+#define FEN_DIO_RF BIT(13)
+#define FEN_HWPDN BIT(14)
+#define FEN_MREGEN BIT(15)
+
+/* APS_FSMCO */
+#define PFM_LDALL BIT(0)
+#define PFM_ALDN BIT(1)
+#define PFM_LDKP BIT(2)
+#define PFM_WOWL BIT(3)
+#define EnPDN BIT(4)
+#define PDN_PL BIT(5)
+#define APFM_ONMAC BIT(8)
+#define APFM_OFF BIT(9)
+#define APFM_RSM BIT(10)
+#define AFSM_HSUS BIT(11)
+#define AFSM_PCIE BIT(12)
+#define APDM_MAC BIT(13)
+#define APDM_HOST BIT(14)
+#define APDM_HPDN BIT(15)
+#define RDY_MACON BIT(16)
+#define SUS_HOST BIT(17)
+#define ROP_ALD BIT(20)
+#define ROP_PWR BIT(21)
+#define ROP_SPS BIT(22)
+#define SOP_MRST BIT(25)
+#define SOP_FUSE BIT(26)
+#define SOP_ABG BIT(27)
+#define SOP_AMB BIT(28)
+#define SOP_RCK BIT(29)
+#define SOP_A8M BIT(30)
+#define XOP_BTCK BIT(31)
+
+/* SYS_CLKR */
+#define ANAD16V_EN BIT(0)
+#define ANA8M BIT(1)
+#define MACSLP BIT(4)
+#define LOADER_CLK_EN BIT(5)
+#define _80M_SSC_DIS BIT(7)
+#define _80M_SSC_EN_HO BIT(8)
+#define PHY_SSC_RSTB BIT(9)
+#define SEC_CLK_EN BIT(10)
+#define MAC_CLK_EN BIT(11)
+#define SYS_CLK_EN BIT(12)
+#define RING_CLK_EN BIT(13)
+
+
+/* 9346CR */
+#define BOOT_FROM_EEPROM BIT(4)
+#define EEPROM_EN BIT(5)
+
+/* AFE_MISC */
+#define AFE_BGEN BIT(0)
+#define AFE_MBEN BIT(1)
+#define MAC_ID_EN BIT(7)
+
+/* RSV_CTRL */
+#define WLOCK_ALL BIT(0)
+#define WLOCK_00 BIT(1)
+#define WLOCK_04 BIT(2)
+#define WLOCK_08 BIT(3)
+#define WLOCK_40 BIT(4)
+#define R_DIS_PRST_0 BIT(5)
+#define R_DIS_PRST_1 BIT(6)
+#define LOCK_ALL_EN BIT(7)
+
+/* RF_CTRL */
+#define RF_EN BIT(0)
+#define RF_RSTB BIT(1)
+#define RF_SDMRSTB BIT(2)
+
+
+
+/* LDOA15_CTRL */
+#define LDA15_EN BIT(0)
+#define LDA15_STBY BIT(1)
+#define LDA15_OBUF BIT(2)
+#define LDA15_REG_VOS BIT(3)
+#define _LDA15_VOADJ(x) (((x) & 0x7) << 4)
+
+
+
+/* LDOV12D_CTRL */
+#define LDV12_EN BIT(0)
+#define LDV12_SDBY BIT(1)
+#define LPLDO_HSM BIT(2)
+#define LPLDO_LSM_DIS BIT(3)
+#define _LDV12_VADJ(x) (((x) & 0xF) << 4)
+
+
+/* AFE_XTAL_CTRL */
+#define XTAL_EN BIT(0)
+#define XTAL_BSEL BIT(1)
+#define _XTAL_BOSC(x) (((x) & 0x3) << 2)
+#define _XTAL_CADJ(x) (((x) & 0xF) << 4)
+#define XTAL_GATE_USB BIT(8)
+#define _XTAL_USB_DRV(x) (((x) & 0x3) << 9)
+#define XTAL_GATE_AFE BIT(11)
+#define _XTAL_AFE_DRV(x) (((x) & 0x3) << 12)
+#define XTAL_RF_GATE BIT(14)
+#define _XTAL_RF_DRV(x) (((x) & 0x3) << 15)
+#define XTAL_GATE_DIG BIT(17)
+#define _XTAL_DIG_DRV(x) (((x) & 0x3) << 18)
+#define XTAL_BT_GATE BIT(20)
+#define _XTAL_BT_DRV(x) (((x) & 0x3) << 21)
+#define _XTAL_GPIO(x) (((x) & 0x7) << 23)
+
+
+#define CKDLY_AFE BIT(26)
+#define CKDLY_USB BIT(27)
+#define CKDLY_DIG BIT(28)
+#define CKDLY_BT BIT(29)
+
+
+/* AFE_PLL_CTRL */
+#define APLL_EN BIT(0)
+#define APLL_320_EN BIT(1)
+#define APLL_FREF_SEL BIT(2)
+#define APLL_EDGE_SEL BIT(3)
+#define APLL_WDOGB BIT(4)
+#define APLL_LPFEN BIT(5)
+
+#define APLL_REF_CLK_13MHZ 0x1
+#define APLL_REF_CLK_19_2MHZ 0x2
+#define APLL_REF_CLK_20MHZ 0x3
+#define APLL_REF_CLK_25MHZ 0x4
+#define APLL_REF_CLK_26MHZ 0x5
+#define APLL_REF_CLK_38_4MHZ 0x6
+#define APLL_REF_CLK_40MHZ 0x7
+
+#define APLL_320EN BIT(14)
+#define APLL_80EN BIT(15)
+#define APLL_1MEN BIT(24)
+
+
+/* EFUSE_CTRL */
+#define ALD_EN BIT(18)
+#define EF_PD BIT(19)
+#define EF_FLAG BIT(31)
+
+/* EFUSE_TEST */
+#define EF_TRPT BIT(7)
+#define LDOE25_EN BIT(31)
+
+/* MCUFWDL */
+#define MCUFWDL_EN BIT(0)
+#define MCUFWDL_RDY BIT(1)
+#define FWDL_ChkSum_rpt BIT(2)
+#define MACINI_RDY BIT(3)
+#define BBINI_RDY BIT(4)
+#define RFINI_RDY BIT(5)
+#define WINTINI_RDY BIT(6)
+#define MAC1_WINTINI_RDY BIT(11)
+#define CPRST BIT(23)
+
+/* REG_SYS_CFG */
+#define XCLK_VLD BIT(0)
+#define ACLK_VLD BIT(1)
+#define UCLK_VLD BIT(2)
+#define PCLK_VLD BIT(3)
+#define PCIRSTB BIT(4)
+#define V15_VLD BIT(5)
+#define TRP_B15V_EN BIT(7)
+#define SIC_IDLE BIT(8)
+#define BD_MAC2 BIT(9)
+#define BD_MAC1 BIT(10)
+#define IC_MACPHY_MODE BIT(11)
+#define PAD_HWPD_IDN BIT(22)
+#define TRP_VAUX_EN BIT(23)
+#define TRP_BT_EN BIT(24)
+#define BD_PKG_SEL BIT(25)
+#define BD_HCI_SEL BIT(26)
+#define TYPE_ID BIT(27)
+
+/* LLT_INIT */
+#define _LLT_NO_ACTIVE 0x0
+#define _LLT_WRITE_ACCESS 0x1
+#define _LLT_READ_ACCESS 0x2
+
+#define _LLT_INIT_DATA(x) ((x) & 0xFF)
+#define _LLT_INIT_ADDR(x) (((x) & 0xFF) << 8)
+#define _LLT_OP(x) (((x) & 0x3) << 30)
+#define _LLT_OP_VALUE(x) (((x) >> 30) & 0x3)
+
+
+/* ----------------------------------------------------- */
+/* 0x0400h ~ 0x047Fh Protocol Configuration */
+/* ----------------------------------------------------- */
+#define RETRY_LIMIT_SHORT_SHIFT 8
+#define RETRY_LIMIT_LONG_SHIFT 0
+
+
+/* ----------------------------------------------------- */
+/* 0x0500h ~ 0x05FFh EDCA Configuration */
+/* ----------------------------------------------------- */
+/* EDCA setting */
+#define AC_PARAM_TXOP_LIMIT_OFFSET 16
+#define AC_PARAM_ECW_MAX_OFFSET 12
+#define AC_PARAM_ECW_MIN_OFFSET 8
+#define AC_PARAM_AIFS_OFFSET 0
+
+/* ACMHWCTRL */
+#define ACMHW_HWEN BIT(0)
+#define ACMHW_BEQEN BIT(1)
+#define ACMHW_VIQEN BIT(2)
+#define ACMHW_VOQEN BIT(3)
+
+/* ----------------------------------------------------- */
+/* 0x0600h ~ 0x07FFh WMAC Configuration */
+/* ----------------------------------------------------- */
+
+/* TCR */
+#define TSFRST BIT(0)
+#define DIS_GCLK BIT(1)
+#define PAD_SEL BIT(2)
+#define PWR_ST BIT(6)
+#define PWRBIT_OW_EN BIT(7)
+#define ACRC BIT(8)
+#define CFENDFORM BIT(9)
+#define ICV BIT(10)
+
+/* SECCFG */
+#define SCR_TXUSEDK BIT(0)
+#define SCR_RXUSEDK BIT(1)
+#define SCR_TXENCENABLE BIT(2)
+#define SCR_RXENCENABLE BIT(3)
+#define SCR_SKBYA2 BIT(4)
+#define SCR_NOSKMC BIT(5)
+#define SCR_TXBCUSEDK BIT(6)
+#define SCR_RXBCUSEDK BIT(7)
+
+/* General definitions */
+#define MAC_ADDR_LEN 6
+#define LAST_ENTRY_OF_TX_PKT_BUFFER 255
+#define LAST_ENTRY_OF_TX_PKT_BUFFER_DUAL_MAC 127
+
+#define POLLING_LLT_THRESHOLD 20
+#define POLLING_READY_TIMEOUT_COUNT 1000
+
+/* Min Spacing related settings. */
+#define MAX_MSS_DENSITY_2T 0x13
+#define MAX_MSS_DENSITY_1T 0x0A
+
+
+/* BB-PHY register PMAC 0x100 PHY 0x800 - 0xEFF */
+/* 1. PMAC duplicate register due to connection: */
+/* RF_Mode, TRxRN, NumOf L-STF */
+/* 2. 0x800/0x900/0xA00/0xC00/0xD00/0xE00 */
+/* 3. RF register 0x00-2E */
+/* 4. Bit Mask for BB/RF register */
+/* 5. Other defintion for BB/RF R/W */
+
+/* 3. Page8(0x800) */
+#define RFPGA0_RFMOD 0x800
+
+#define RFPGA0_TXINFO 0x804
+#define RFPGA0_PSDFUNCTION 0x808
+
+#define RFPGA0_TXGAINSTAGE 0x80c
+
+#define RFPGA0_RFTIMING1 0x810
+#define RFPGA0_RFTIMING2 0x814
+
+#define RFPGA0_XA_HSSIPARAMETER1 0x820
+#define RFPGA0_XA_HSSIPARAMETER2 0x824
+#define RFPGA0_XB_HSSIPARAMETER1 0x828
+#define RFPGA0_XB_HSSIPARAMETER2 0x82c
+
+#define RFPGA0_XA_LSSIPARAMETER 0x840
+#define RFPGA0_XB_LSSIPARAMETER 0x844
+
+#define RFPGA0_RFWAkEUPPARAMETER 0x850
+#define RFPGA0_RFSLEEPUPPARAMETER 0x854
+
+#define RFPGA0_XAB_SWITCHCONTROL 0x858
+#define RFPGA0_XCD_SWITCHCONTROL 0x85c
+
+#define RFPGA0_XA_RFINTERFACEOE 0x860
+#define RFPGA0_XB_RFINTERFACEOE 0x864
+
+#define RFPGA0_XAB_RFINTERFACESW 0x870
+#define RFPGA0_XCD_RFINTERFACESW 0x874
+
+#define RFPGA0_XAB_RFPARAMETER 0x878
+#define RFPGA0_XCD_RFPARAMETER 0x87c
+
+#define RFPGA0_ANALOGPARAMETER1 0x880
+#define RFPGA0_ANALOGPARAMETER2 0x884
+#define RFPGA0_ANALOGPARAMETER3 0x888
+#define RFPGA0_ADDALLOCKEN 0x888
+#define RFPGA0_ANALOGPARAMETER4 0x88c
+
+#define RFPGA0_XA_LSSIREADBACK 0x8a0
+#define RFPGA0_XB_LSSIREADBACK 0x8a4
+#define RFPGA0_XC_LSSIREADBACK 0x8a8
+#define RFPGA0_XD_LSSIREADBACK 0x8ac
+
+#define RFPGA0_PSDREPORT 0x8b4
+#define TRANSCEIVERA_HSPI_READBACK 0x8b8
+#define TRANSCEIVERB_HSPI_READBACK 0x8bc
+#define RFPGA0_XAB_RFINTERFACERB 0x8e0
+#define RFPGA0_XCD_RFINTERFACERB 0x8e4
+
+/* 4. Page9(0x900) */
+#define RFPGA1_RFMOD 0x900
+
+#define RFPGA1_TXBLOCK 0x904
+#define RFPGA1_DEBUGSELECT 0x908
+#define RFPGA1_TXINFO 0x90c
+
+/* 5. PageA(0xA00) */
+#define RCCK0_SYSTEM 0xa00
+
+#define RCCK0_AFESSTTING 0xa04
+#define RCCK0_CCA 0xa08
+
+#define RCCK0_RXAGC1 0xa0c
+#define RCCK0_RXAGC2 0xa10
+
+#define RCCK0_RXHP 0xa14
+
+#define RCCK0_DSPPARAMETER1 0xa18
+#define RCCK0_DSPPARAMETER2 0xa1c
+
+#define RCCK0_TXFILTER1 0xa20
+#define RCCK0_TXFILTER2 0xa24
+#define RCCK0_DEBUGPORT 0xa28
+#define RCCK0_FALSEALARMREPORT 0xa2c
+#define RCCK0_TRSSIREPORT 0xa50
+#define RCCK0_RXREPORT 0xa54
+#define RCCK0_FACOUNTERLOWER 0xa5c
+#define RCCK0_FACOUNTERUPPER 0xa58
+
+/* 6. PageC(0xC00) */
+#define ROFDM0_LSTF 0xc00
+
+#define ROFDM0_TRXPATHENABLE 0xc04
+#define ROFDM0_TRMUXPAR 0xc08
+#define ROFDM0_TRSWISOLATION 0xc0c
+
+#define ROFDM0_XARXAFE 0xc10
+#define ROFDM0_XARXIQIMBALANCE 0xc14
+#define ROFDM0_XBRXAFE 0xc18
+#define ROFDM0_XBRXIQIMBALANCE 0xc1c
+#define ROFDM0_XCRXAFE 0xc20
+#define ROFDM0_XCRXIQIMBALANCE 0xc24
+#define ROFDM0_XDRXAFE 0xc28
+#define ROFDM0_XDRXIQIMBALANCE 0xc2c
+
+#define ROFDM0_RXDETECTOR1 0xc30
+#define ROFDM0_RXDETECTOR2 0xc34
+#define ROFDM0_RXDETECTOR3 0xc38
+#define ROFDM0_RXDETECTOR4 0xc3c
+
+#define ROFDM0_RXDSP 0xc40
+#define ROFDM0_CFOANDDAGC 0xc44
+#define ROFDM0_CCADROPTHRESHOLD 0xc48
+#define ROFDM0_ECCATHRESHOLD 0xc4c
+
+#define ROFDM0_XAAGCCORE1 0xc50
+#define ROFDM0_XAAGCCORE2 0xc54
+#define ROFDM0_XBAGCCORE1 0xc58
+#define ROFDM0_XBAGCCORE2 0xc5c
+#define ROFDM0_XCAGCCORE1 0xc60
+#define ROFDM0_XCAGCCORE2 0xc64
+#define ROFDM0_XDAGCCORE1 0xc68
+#define ROFDM0_XDAGCCORE2 0xc6c
+
+#define ROFDM0_AGCPARAMETER1 0xc70
+#define ROFDM0_AGCPARAMETER2 0xc74
+#define ROFDM0_AGCRSSITABLE 0xc78
+#define ROFDM0_HTSTFAGC 0xc7c
+
+#define ROFDM0_XATxIQIMBALANCE 0xc80
+#define ROFDM0_XATxAFE 0xc84
+#define ROFDM0_XBTxIQIMBALANCE 0xc88
+#define ROFDM0_XBTxAFE 0xc8c
+#define ROFDM0_XCTxIQIMBALANCE 0xc90
+#define ROFDM0_XCTxAFE 0xc94
+#define ROFDM0_XDTxIQIMBALANCE 0xc98
+#define ROFDM0_XDTxAFE 0xc9c
+
+#define ROFDM0_RXHPPARAMETER 0xce0
+#define ROFDM0_TXPSEUDONOISEWGT 0xce4
+#define ROFDM0_FRAMESYNC 0xcf0
+#define ROFDM0_DFSREPORT 0xcf4
+#define ROFDM0_TXCOEFF1 0xca4
+#define ROFDM0_TXCOEFF2 0xca8
+#define ROFDM0_TXCOEFF3 0xcac
+#define ROFDM0_TXCOEFF4 0xcb0
+#define ROFDM0_TXCOEFF5 0xcb4
+#define ROFDM0_TXCOEFF6 0xcb8
+
+/* 7. PageD(0xD00) */
+#define ROFDM1_LSTF 0xd00
+#define ROFDM1_TRXPATHENABLE 0xd04
+
+#define ROFDM1_CFO 0xd08
+#define ROFDM1_CSI1 0xd10
+#define ROFDM1_SBD 0xd14
+#define ROFDM1_CSI2 0xd18
+#define ROFDM1_CFOTRACKING 0xd2c
+#define ROFDM1_TRXMESAURE1 0xd34
+#define ROFDM1_INTFDET 0xd3c
+#define ROFDM1_PSEUDONOISESTATEAB 0xd50
+#define ROFDM1_PSEUDONOISESTATECD 0xd54
+#define ROFDM1_RXPSEUDONOISEWGT 0xd58
+
+#define ROFDM_PHYCOUNTER1 0xda0
+#define ROFDM_PHYCOUNTER2 0xda4
+#define ROFDM_PHYCOUNTER3 0xda8
+
+#define ROFDM_SHORTCFOAB 0xdac
+#define ROFDM_SHORTCFOCD 0xdb0
+#define ROFDM_LONGCFOAB 0xdb4
+#define ROFDM_LONGCFOCD 0xdb8
+#define ROFDM_TAILCFOAB 0xdbc
+#define ROFDM_TAILCFOCD 0xdc0
+#define ROFDM_PWMEASURE1 0xdc4
+#define ROFDM_PWMEASURE2 0xdc8
+#define ROFDM_BWREPORT 0xdcc
+#define ROFDM_AGCREPORT 0xdd0
+#define ROFDM_RXSNR 0xdd4
+#define ROFDM_RXEVMCSI 0xdd8
+#define ROFDM_SIGReport 0xddc
+
+/* 8. PageE(0xE00) */
+#define RTXAGC_A_RATE18_06 0xe00
+#define RTXAGC_A_RATE54_24 0xe04
+#define RTXAGC_A_CCK1_MCS32 0xe08
+#define RTXAGC_A_MCS03_MCS00 0xe10
+#define RTXAGC_A_MCS07_MCS04 0xe14
+#define RTXAGC_A_MCS11_MCS08 0xe18
+#define RTXAGC_A_MCS15_MCS12 0xe1c
+
+#define RTXAGC_B_RATE18_06 0x830
+#define RTXAGC_B_RATE54_24 0x834
+#define RTXAGC_B_CCK1_55_MCS32 0x838
+#define RTXAGC_B_MCS03_MCS00 0x83c
+#define RTXAGC_B_MCS07_MCS04 0x848
+#define RTXAGC_B_MCS11_MCS08 0x84c
+#define RTXAGC_B_MCS15_MCS12 0x868
+#define RTXAGC_B_CCK11_A_CCK2_11 0x86c
+
+/* RL6052 Register definition */
+#define RF_AC 0x00
+
+#define RF_IQADJ_G1 0x01
+#define RF_IQADJ_G2 0x02
+#define RF_POW_TRSW 0x05
+
+#define RF_GAIN_RX 0x06
+#define RF_GAIN_TX 0x07
+
+#define RF_TXM_IDAC 0x08
+#define RF_BS_IQGEN 0x0F
+
+#define RF_MODE1 0x10
+#define RF_MODE2 0x11
+
+#define RF_RX_AGC_HP 0x12
+#define RF_TX_AGC 0x13
+#define RF_BIAS 0x14
+#define RF_IPA 0x15
+#define RF_POW_ABILITY 0x17
+#define RF_MODE_AG 0x18
+#define rRfChannel 0x18
+#define RF_CHNLBW 0x18
+#define RF_TOP 0x19
+
+#define RF_RX_G1 0x1A
+#define RF_RX_G2 0x1B
+
+#define RF_RX_BB2 0x1C
+#define RF_RX_BB1 0x1D
+
+#define RF_RCK1 0x1E
+#define RF_RCK2 0x1F
+
+#define RF_TX_G1 0x20
+#define RF_TX_G2 0x21
+#define RF_TX_G3 0x22
+
+#define RF_TX_BB1 0x23
+
+#define RF_T_METER 0x42
+
+#define RF_SYN_G1 0x25
+#define RF_SYN_G2 0x26
+#define RF_SYN_G3 0x27
+#define RF_SYN_G4 0x28
+#define RF_SYN_G5 0x29
+#define RF_SYN_G6 0x2A
+#define RF_SYN_G7 0x2B
+#define RF_SYN_G8 0x2C
+
+#define RF_RCK_OS 0x30
+
+#define RF_TXPA_G1 0x31
+#define RF_TXPA_G2 0x32
+#define RF_TXPA_G3 0x33
+
+/* Bit Mask */
+
+/* 2. Page8(0x800) */
+#define BRFMOD 0x1
+#define BCCKTXSC 0x30
+#define BCCKEN 0x1000000
+#define BOFDMEN 0x2000000
+
+#define B3WIREDATALENGTH 0x800
+#define B3WIREADDRESSLENGTH 0x400
+
+#define BRFSI_RFENV 0x10
+
+#define BLSSIREADADDRESS 0x7f800000
+#define BLSSIREADEDGE 0x80000000
+#define BLSSIREADBACKDATA 0xfffff
+/* 4. PageA(0xA00) */
+#define BCCKSIDEBAND 0x10
+
+/* Other Definition */
+#define BBYTE0 0x1
+#define BBYTE1 0x2
+#define BBYTE2 0x4
+#define BBYTE3 0x8
+#define BWORD0 0x3
+#define BWORD1 0xc
+#define BDWORD 0xf
+
+#define BMASKBYTE0 0xff
+#define BMASKBYTE1 0xff00
+#define BMASKBYTE2 0xff0000
+#define BMASKBYTE3 0xff000000
+#define BMASKHWORD 0xffff0000
+#define BMASKLWORD 0x0000ffff
+#define BMASKDWORD 0xffffffff
+#define BMASK12BITS 0xfff
+#define BMASKH4BITS 0xf0000000
+#define BMASKOFDM_D 0xffc00000
+#define BMASKCCK 0x3f3f3f3f
+
+#define BRFREGOFFSETMASK 0xfffff
+
+#endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/rf.c b/drivers/net/wireless/rtlwifi/rtl8192de/rf.c
new file mode 100644
index 0000000..c326372
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8192de/rf.c
@@ -0,0 +1,628 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010 Realtek Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License 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, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#include "../wifi.h"
+#include "reg.h"
+#include "def.h"
+#include "phy.h"
+#include "rf.h"
+#include "dm.h"
+#include "hw.h"
+
+void rtl92d_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, u8 bandwidth)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ u8 rfpath;
+
+ switch (bandwidth) {
+ case HT_CHANNEL_WIDTH_20:
+ for (rfpath = 0; rfpath < rtlphy->num_total_rfpath; rfpath++) {
+ rtlphy->rfreg_chnlval[rfpath] = ((rtlphy->rfreg_chnlval
+ [rfpath] & 0xfffff3ff) | 0x0400);
+ rtl_set_rfreg(hw, rfpath, RF_CHNLBW, BIT(10) |
+ BIT(11), 0x01);
+
+ RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD,
+ ("20M RF 0x18 = 0x%x\n",
+ rtlphy->rfreg_chnlval[rfpath]));
+ }
+
+ break;
+ case HT_CHANNEL_WIDTH_20_40:
+ for (rfpath = 0; rfpath < rtlphy->num_total_rfpath; rfpath++) {
+ rtlphy->rfreg_chnlval[rfpath] =
+ ((rtlphy->rfreg_chnlval[rfpath] & 0xfffff3ff));
+ rtl_set_rfreg(hw, rfpath, RF_CHNLBW, BIT(10) | BIT(11),
+ 0x00);
+ RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD,
+ ("40M RF 0x18 = 0x%x\n",
+ rtlphy->rfreg_chnlval[rfpath]));
+ }
+ break;
+ default:
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+ ("unknown bandwidth: %#X\n", bandwidth));
+ break;
+ }
+}
+
+void rtl92d_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw,
+ u8 *ppowerlevel)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+ struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+ u32 tx_agc[2] = {0, 0}, tmpval;
+ bool turbo_scanoff = false;
+ u8 idx1, idx2;
+ u8 *ptr;
+
+ if (rtlefuse->eeprom_regulatory != 0)
+ turbo_scanoff = true;
+ if (mac->act_scanning == true) {
+ tx_agc[RF90_PATH_A] = 0x3f3f3f3f;
+ tx_agc[RF90_PATH_B] = 0x3f3f3f3f;
+ if (turbo_scanoff) {
+ for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) {
+ tx_agc[idx1] = ppowerlevel[idx1] |
+ (ppowerlevel[idx1] << 8) |
+ (ppowerlevel[idx1] << 16) |
+ (ppowerlevel[idx1] << 24);
+ }
+ }
+ } else {
+ for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) {
+ tx_agc[idx1] = ppowerlevel[idx1] |
+ (ppowerlevel[idx1] << 8) |
+ (ppowerlevel[idx1] << 16) |
+ (ppowerlevel[idx1] << 24);
+ }
+ if (rtlefuse->eeprom_regulatory == 0) {
+ tmpval = (rtlphy->mcs_txpwrlevel_origoffset[0][6]) +
+ (rtlphy->mcs_txpwrlevel_origoffset[0][7] << 8);
+ tx_agc[RF90_PATH_A] += tmpval;
+ tmpval = (rtlphy->mcs_txpwrlevel_origoffset[0][14]) +
+ (rtlphy->mcs_txpwrlevel_origoffset[0][15] << 24);
+ tx_agc[RF90_PATH_B] += tmpval;
+ }
+ }
+
+ for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) {
+ ptr = (u8 *) (&(tx_agc[idx1]));
+ for (idx2 = 0; idx2 < 4; idx2++) {
+ if (*ptr > RF6052_MAX_TX_PWR)
+ *ptr = RF6052_MAX_TX_PWR;
+ ptr++;
+ }
+ }
+
+ tmpval = tx_agc[RF90_PATH_A] & 0xff;
+ rtl_set_bbreg(hw, RTXAGC_A_CCK1_MCS32, BMASKBYTE1, tmpval);
+ RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+ ("CCK PWR 1M (rf-A) = 0x%x (reg 0x%x)\n", tmpval,
+ RTXAGC_A_CCK1_MCS32));
+ tmpval = tx_agc[RF90_PATH_A] >> 8;
+ rtl_set_bbreg(hw, RTXAGC_B_CCK11_A_CCK2_11, 0xffffff00, tmpval);
+ RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+ ("CCK PWR 2~11M (rf-A) = 0x%x (reg 0x%x)\n", tmpval,
+ RTXAGC_B_CCK11_A_CCK2_11));
+ tmpval = tx_agc[RF90_PATH_B] >> 24;
+ rtl_set_bbreg(hw, RTXAGC_B_CCK11_A_CCK2_11, BMASKBYTE0, tmpval);
+ RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+ ("CCK PWR 11M (rf-B) = 0x%x (reg 0x%x)\n", tmpval,
+ RTXAGC_B_CCK11_A_CCK2_11));
+ tmpval = tx_agc[RF90_PATH_B] & 0x00ffffff;
+ rtl_set_bbreg(hw, RTXAGC_B_CCK1_55_MCS32, 0xffffff00, tmpval);
+ RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+ ("CCK PWR 1~5.5M (rf-B) = 0x%x (reg 0x%x)\n", tmpval,
+ RTXAGC_B_CCK1_55_MCS32));
+}
+
+static void _rtl92d_phy_get_power_base(struct ieee80211_hw *hw,
+ u8 *ppowerlevel, u8 channel,
+ u32 *ofdmbase, u32 *mcsbase)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+ u32 powerbase0, powerbase1;
+ u8 legacy_pwrdiff, ht20_pwrdiff;
+ u8 i, powerlevel[2];
+
+ for (i = 0; i < 2; i++) {
+ powerlevel[i] = ppowerlevel[i];
+ legacy_pwrdiff = rtlefuse->txpwr_legacyhtdiff[i][channel - 1];
+ powerbase0 = powerlevel[i] + legacy_pwrdiff;
+ powerbase0 = (powerbase0 << 24) | (powerbase0 << 16) |
+ (powerbase0 << 8) | powerbase0;
+ *(ofdmbase + i) = powerbase0;
+ RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+ (" [OFDM power base index rf(%c) = 0x%x]\n",
+ ((i == 0) ? 'A' : 'B'), *(ofdmbase + i)));
+ }
+
+ for (i = 0; i < 2; i++) {
+ if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20) {
+ ht20_pwrdiff = rtlefuse->txpwr_ht20diff[i][channel - 1];
+ powerlevel[i] += ht20_pwrdiff;
+ }
+ powerbase1 = powerlevel[i];
+ powerbase1 = (powerbase1 << 24) | (powerbase1 << 16) |
+ (powerbase1 << 8) | powerbase1;
+ *(mcsbase + i) = powerbase1;
+ RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+ (" [MCS power base index rf(%c) = 0x%x]\n",
+ ((i == 0) ? 'A' : 'B'), *(mcsbase + i)));
+ }
+}
+
+static u8 _rtl92d_phy_get_chnlgroup_bypg(u8 chnlindex)
+{
+ u8 group;
+ u8 channel_info[59] = {
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58,
+ 60, 62, 64, 100, 102, 104, 106, 108, 110, 112,
+ 114, 116, 118, 120, 122, 124, 126, 128, 130, 132,
+ 134, 136, 138, 140, 149, 151, 153, 155, 157, 159,
+ 161, 163, 165
+ };
+
+ if (channel_info[chnlindex] <= 3) /* Chanel 1-3 */
+ group = 0;
+ else if (channel_info[chnlindex] <= 9) /* Channel 4-9 */
+ group = 1;
+ else if (channel_info[chnlindex] <= 14) /* Channel 10-14 */
+ group = 2;
+ else if (channel_info[chnlindex] <= 64)
+ group = 6;
+ else if (channel_info[chnlindex] <= 140)
+ group = 7;
+ else
+ group = 8;
+ return group;
+}
+
+static void _rtl92d_get_txpower_writeval_by_regulatory(struct ieee80211_hw *hw,
+ u8 channel, u8 index,
+ u32 *powerbase0,
+ u32 *powerbase1,
+ u32 *p_outwriteval)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+ u8 i, chnlgroup = 0, pwr_diff_limit[4];
+ u32 writeval = 0, customer_limit, rf;
+
+ for (rf = 0; rf < 2; rf++) {
+ switch (rtlefuse->eeprom_regulatory) {
+ case 0:
+ chnlgroup = 0;
+ writeval = rtlphy->mcs_txpwrlevel_origoffset
+ [chnlgroup][index +
+ (rf ? 8 : 0)] + ((index < 2) ?
+ powerbase0[rf] :
+ powerbase1[rf]);
+ RTPRINT(rtlpriv, FPHY, PHY_TXPWR, ("RTK better "
+ "performance, writeval(%c) = 0x%x\n",
+ ((rf == 0) ? 'A' : 'B'), writeval));
+ break;
+ case 1:
+ if (rtlphy->pwrgroup_cnt == 1)
+ chnlgroup = 0;
+ if (rtlphy->pwrgroup_cnt >= MAX_PG_GROUP) {
+ chnlgroup = _rtl92d_phy_get_chnlgroup_bypg(
+ channel - 1);
+ if (rtlphy->current_chan_bw ==
+ HT_CHANNEL_WIDTH_20)
+ chnlgroup++;
+ else
+ chnlgroup += 4;
+ writeval = rtlphy->mcs_txpwrlevel_origoffset
+ [chnlgroup][index +
+ (rf ? 8 : 0)] + ((index < 2) ?
+ powerbase0[rf] :
+ powerbase1[rf]);
+ RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+ ("Realtek regulatory, "
+ "20MHz, writeval(%c) = 0x%x\n",
+ ((rf == 0) ? 'A' : 'B'),
+ writeval));
+ }
+ break;
+ case 2:
+ writeval = ((index < 2) ? powerbase0[rf] :
+ powerbase1[rf]);
+ RTPRINT(rtlpriv, FPHY, PHY_TXPWR, ("Better regulatory, "
+ "writeval(%c) = 0x%x\n",
+ ((rf == 0) ? 'A' : 'B'), writeval));
+ break;
+ case 3:
+ chnlgroup = 0;
+ if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) {
+ RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+ ("customer's limit, 40MHz rf(%c) = "
+ "0x%x\n", ((rf == 0) ? 'A' : 'B'),
+ rtlefuse->pwrgroup_ht40[rf]
+ [channel - 1]));
+ } else {
+ RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+ ("customer's limit, 20MHz rf(%c) = "
+ "0x%x\n", ((rf == 0) ? 'A' : 'B'),
+ rtlefuse->pwrgroup_ht20[rf]
+ [channel - 1]));
+ }
+ for (i = 0; i < 4; i++) {
+ pwr_diff_limit[i] =
+ (u8)((rtlphy->mcs_txpwrlevel_origoffset
+ [chnlgroup][index + (rf ? 8 : 0)] &
+ (0x7f << (i * 8))) >> (i * 8));
+ if (rtlphy->current_chan_bw ==
+ HT_CHANNEL_WIDTH_20_40) {
+ if (pwr_diff_limit[i] >
+ rtlefuse->pwrgroup_ht40[rf]
+ [channel - 1])
+ pwr_diff_limit[i] =
+ rtlefuse->pwrgroup_ht40
+ [rf][channel - 1];
+ } else {
+ if (pwr_diff_limit[i] >
+ rtlefuse->pwrgroup_ht20[rf][
+ channel - 1])
+ pwr_diff_limit[i] =
+ rtlefuse->pwrgroup_ht20[rf]
+ [channel - 1];
+ }
+ }
+ customer_limit = (pwr_diff_limit[3] << 24) |
+ (pwr_diff_limit[2] << 16) |
+ (pwr_diff_limit[1] << 8) |
+ (pwr_diff_limit[0]);
+ RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+ ("Customer's limit rf(%c) = 0x%x\n",
+ ((rf == 0) ? 'A' : 'B'), customer_limit));
+ writeval = customer_limit + ((index < 2) ?
+ powerbase0[rf] : powerbase1[rf]);
+ RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+ ("Customer, writeval rf(%c)= 0x%x\n",
+ ((rf == 0) ? 'A' : 'B'), writeval));
+ break;
+ default:
+ chnlgroup = 0;
+ writeval = rtlphy->mcs_txpwrlevel_origoffset
+ [chnlgroup][index +
+ (rf ? 8 : 0)] + ((index < 2) ?
+ powerbase0[rf] : powerbase1[rf]);
+ RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+ ("RTK better performance, writeval "
+ "rf(%c) = 0x%x\n",
+ ((rf == 0) ? 'A' : 'B'), writeval));
+ break;
+ }
+ *(p_outwriteval + rf) = writeval;
+ }
+}
+
+static void _rtl92d_write_ofdm_power_reg(struct ieee80211_hw *hw,
+ u8 index, u32 *pvalue)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ static u16 regoffset_a[6] = {
+ RTXAGC_A_RATE18_06, RTXAGC_A_RATE54_24,
+ RTXAGC_A_MCS03_MCS00, RTXAGC_A_MCS07_MCS04,
+ RTXAGC_A_MCS11_MCS08, RTXAGC_A_MCS15_MCS12
+ };
+ static u16 regoffset_b[6] = {
+ RTXAGC_B_RATE18_06, RTXAGC_B_RATE54_24,
+ RTXAGC_B_MCS03_MCS00, RTXAGC_B_MCS07_MCS04,
+ RTXAGC_B_MCS11_MCS08, RTXAGC_B_MCS15_MCS12
+ };
+ u8 i, rf, pwr_val[4];
+ u32 writeval;
+ u16 regoffset;
+
+ for (rf = 0; rf < 2; rf++) {
+ writeval = pvalue[rf];
+ for (i = 0; i < 4; i++) {
+ pwr_val[i] = (u8) ((writeval & (0x7f <<
+ (i * 8))) >> (i * 8));
+ if (pwr_val[i] > RF6052_MAX_TX_PWR)
+ pwr_val[i] = RF6052_MAX_TX_PWR;
+ }
+ writeval = (pwr_val[3] << 24) | (pwr_val[2] << 16) |
+ (pwr_val[1] << 8) | pwr_val[0];
+ if (rf == 0)
+ regoffset = regoffset_a[index];
+ else
+ regoffset = regoffset_b[index];
+ rtl_set_bbreg(hw, regoffset, BMASKDWORD, writeval);
+ RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+ ("Set 0x%x = %08x\n", regoffset, writeval));
+ if (((get_rf_type(rtlphy) == RF_2T2R) &&
+ (regoffset == RTXAGC_A_MCS15_MCS12 ||
+ regoffset == RTXAGC_B_MCS15_MCS12)) ||
+ ((get_rf_type(rtlphy) != RF_2T2R) &&
+ (regoffset == RTXAGC_A_MCS07_MCS04 ||
+ regoffset == RTXAGC_B_MCS07_MCS04))) {
+ writeval = pwr_val[3];
+ if (regoffset == RTXAGC_A_MCS15_MCS12 ||
+ regoffset == RTXAGC_A_MCS07_MCS04)
+ regoffset = 0xc90;
+ if (regoffset == RTXAGC_B_MCS15_MCS12 ||
+ regoffset == RTXAGC_B_MCS07_MCS04)
+ regoffset = 0xc98;
+ for (i = 0; i < 3; i++) {
+ if (i != 2)
+ writeval = (writeval > 8) ?
+ (writeval - 8) : 0;
+ else
+ writeval = (writeval > 6) ?
+ (writeval - 6) : 0;
+ rtl_write_byte(rtlpriv, (u32) (regoffset + i),
+ (u8) writeval);
+ }
+ }
+ }
+}
+
+void rtl92d_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw,
+ u8 *ppowerlevel, u8 channel)
+{
+ u32 writeval[2], powerbase0[2], powerbase1[2];
+ u8 index;
+
+ _rtl92d_phy_get_power_base(hw, ppowerlevel, channel,
+ &powerbase0[0], &powerbase1[0]);
+ for (index = 0; index < 6; index++) {
+ _rtl92d_get_txpower_writeval_by_regulatory(hw,
+ channel, index, &powerbase0[0],
+ &powerbase1[0], &writeval[0]);
+ _rtl92d_write_ofdm_power_reg(hw, index, &writeval[0]);
+ }
+}
+
+bool rtl92d_phy_enable_anotherphy(struct ieee80211_hw *hw, bool bmac0)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_hal *rtlhal = &(rtlpriv->rtlhal);
+ u8 u1btmp;
+ u8 direct = bmac0 == true ? BIT(3) | BIT(2) : BIT(3);
+ u8 mac_reg = bmac0 == true ? REG_MAC1 : REG_MAC0;
+ u8 mac_on_bit = bmac0 == true ? MAC1_ON : MAC0_ON;
+ bool bresult = true; /* true: need to enable BB/RF power */
+
+ rtlhal->during_mac0init_radiob = false;
+ rtlhal->during_mac1init_radioa = false;
+ RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD, ("===>\n"));
+ /* MAC0 Need PHY1 load radio_b.txt . Driver use DBI to write. */
+ u1btmp = rtl_read_byte(rtlpriv, mac_reg);
+ if (!(u1btmp & mac_on_bit)) {
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("enable BB & RF\n"));
+ /* Enable BB and RF power */
+ rtl92de_write_dword_dbi(hw, REG_SYS_ISO_CTRL,
+ rtl92de_read_dword_dbi(hw, REG_SYS_ISO_CTRL, direct) |
+ BIT(29) | BIT(16) | BIT(17), direct);
+ } else {
+ /* We think if MAC1 is ON,then radio_a.txt
+ * and radio_b.txt has been load. */
+ bresult = false;
+ }
+ RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD, ("<===\n"));
+ return bresult;
+
+}
+
+void rtl92d_phy_powerdown_anotherphy(struct ieee80211_hw *hw, bool bmac0)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_hal *rtlhal = &(rtlpriv->rtlhal);
+ u8 u1btmp;
+ u8 direct = bmac0 == true ? BIT(3) | BIT(2) : BIT(3);
+ u8 mac_reg = bmac0 == true ? REG_MAC1 : REG_MAC0;
+ u8 mac_on_bit = bmac0 == true ? MAC1_ON : MAC0_ON;
+
+ rtlhal->during_mac0init_radiob = false;
+ rtlhal->during_mac1init_radioa = false;
+ RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD, ("====>\n"));
+ /* check MAC0 enable or not again now, if
+ * enabled, not power down radio A. */
+ u1btmp = rtl_read_byte(rtlpriv, mac_reg);
+ if (!(u1btmp & mac_on_bit)) {
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("power down\n"));
+ /* power down RF radio A according to YuNan's advice. */
+ rtl92de_write_dword_dbi(hw, RFPGA0_XA_LSSIPARAMETER,
+ 0x00000000, direct);
+ }
+ RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD, ("<====\n"));
+}
+
+bool rtl92d_phy_rf6052_config(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ bool rtstatus = true;
+ struct rtl_hal *rtlhal = &(rtlpriv->rtlhal);
+ u32 u4_regvalue = 0;
+ u8 rfpath;
+ struct bb_reg_def *pphyreg;
+ bool mac1_initradioa_first = false, mac0_initradiob_first = false;
+ bool need_pwrdown_radioa = false, need_pwrdown_radiob = false;
+ bool true_bpath = false;
+
+ if (rtlphy->rf_type == RF_1T1R)
+ rtlphy->num_total_rfpath = 1;
+ else
+ rtlphy->num_total_rfpath = 2;
+
+ /* Single phy mode: use radio_a radio_b config path_A path_B */
+ /* seperately by MAC0, and MAC1 needn't configure RF; */
+ /* Dual PHY mode:MAC0 use radio_a config 1st phy path_A, */
+ /* MAC1 use radio_b config 2nd PHY path_A. */
+ /* DMDP,MAC0 on G band,MAC1 on A band. */
+ if (rtlhal->macphymode == DUALMAC_DUALPHY) {
+ if (rtlhal->current_bandtype == BAND_ON_2_4G &&
+ rtlhal->interfaceindex == 0) {
+ /* MAC0 needs PHY1 load radio_b.txt.
+ * Driver use DBI to write. */
+ if (rtl92d_phy_enable_anotherphy(hw, true)) {
+ rtlphy->num_total_rfpath = 2;
+ mac0_initradiob_first = true;
+ } else {
+ /* We think if MAC1 is ON,then radio_a.txt and
+ * radio_b.txt has been load. */
+ return rtstatus;
+ }
+ } else if (rtlhal->current_bandtype == BAND_ON_5G &&
+ rtlhal->interfaceindex == 1) {
+ /* MAC1 needs PHY0 load radio_a.txt.
+ * Driver use DBI to write. */
+ if (rtl92d_phy_enable_anotherphy(hw, false)) {
+ rtlphy->num_total_rfpath = 2;
+ mac1_initradioa_first = true;
+ } else {
+ /* We think if MAC0 is ON,then radio_a.txt and
+ * radio_b.txt has been load. */
+ return rtstatus;
+ }
+ } else if (rtlhal->interfaceindex == 1) {
+ /* MAC0 enabled, only init radia B. */
+ true_bpath = true;
+ }
+ }
+
+ for (rfpath = 0; rfpath < rtlphy->num_total_rfpath; rfpath++) {
+ /* Mac1 use PHY0 write */
+ if (mac1_initradioa_first) {
+ if (rfpath == RF90_PATH_A) {
+ rtlhal->during_mac1init_radioa = true;
+ need_pwrdown_radioa = true;
+ } else if (rfpath == RF90_PATH_B) {
+ rtlhal->during_mac1init_radioa = false;
+ mac1_initradioa_first = false;
+ rfpath = RF90_PATH_A;
+ true_bpath = true;
+ rtlphy->num_total_rfpath = 1;
+ }
+ } else if (mac0_initradiob_first) {
+ /* Mac0 use PHY1 write */
+ if (rfpath == RF90_PATH_A)
+ rtlhal->during_mac0init_radiob = false;
+ if (rfpath == RF90_PATH_B) {
+ rtlhal->during_mac0init_radiob = true;
+ mac0_initradiob_first = false;
+ need_pwrdown_radiob = true;
+ rfpath = RF90_PATH_A;
+ true_bpath = true;
+ rtlphy->num_total_rfpath = 1;
+ }
+ }
+ pphyreg = &rtlphy->phyreg_def[rfpath];
+ switch (rfpath) {
+ case RF90_PATH_A:
+ case RF90_PATH_C:
+ u4_regvalue = rtl_get_bbreg(hw, pphyreg->rfintfs,
+ BRFSI_RFENV);
+ break;
+ case RF90_PATH_B:
+ case RF90_PATH_D:
+ u4_regvalue = rtl_get_bbreg(hw, pphyreg->rfintfs,
+ BRFSI_RFENV << 16);
+ break;
+ }
+ rtl_set_bbreg(hw, pphyreg->rfintfe, BRFSI_RFENV << 16, 0x1);
+ udelay(1);
+ rtl_set_bbreg(hw, pphyreg->rfintfo, BRFSI_RFENV, 0x1);
+ udelay(1);
+ /* Set bit number of Address and Data for RF register */
+ /* Set 1 to 4 bits for 8255 */
+ rtl_set_bbreg(hw, pphyreg->rfhssi_para2,
+ B3WIREADDRESSLENGTH, 0x0);
+ udelay(1);
+ /* Set 0 to 12 bits for 8255 */
+ rtl_set_bbreg(hw, pphyreg->rfhssi_para2, B3WIREDATALENGTH, 0x0);
+ udelay(1);
+ switch (rfpath) {
+ case RF90_PATH_A:
+ if (true_bpath == true)
+ rtstatus = rtl92d_phy_config_rf_with_headerfile(
+ hw, radiob_txt,
+ (enum radio_path)rfpath);
+ else
+ rtstatus = rtl92d_phy_config_rf_with_headerfile(
+ hw, radioa_txt,
+ (enum radio_path)rfpath);
+ break;
+ case RF90_PATH_B:
+ rtstatus =
+ rtl92d_phy_config_rf_with_headerfile(hw, radiob_txt,
+ (enum radio_path) rfpath);
+ break;
+ case RF90_PATH_C:
+ break;
+ case RF90_PATH_D:
+ break;
+ }
+ switch (rfpath) {
+ case RF90_PATH_A:
+ case RF90_PATH_C:
+ rtl_set_bbreg(hw, pphyreg->rfintfs, BRFSI_RFENV,
+ u4_regvalue);
+ break;
+ case RF90_PATH_B:
+ case RF90_PATH_D:
+ rtl_set_bbreg(hw, pphyreg->rfintfs, BRFSI_RFENV << 16,
+ u4_regvalue);
+ break;
+ }
+ if (rtstatus != true) {
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+ ("Radio[%d] Fail!!", rfpath));
+ goto phy_rf_cfg_fail;
+ }
+
+ }
+
+ /* check MAC0 enable or not again, if enabled,
+ * not power down radio A. */
+ /* check MAC1 enable or not again, if enabled,
+ * not power down radio B. */
+ if (need_pwrdown_radioa)
+ rtl92d_phy_powerdown_anotherphy(hw, false);
+ else if (need_pwrdown_radiob)
+ rtl92d_phy_powerdown_anotherphy(hw, true);
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, ("<---\n"));
+ return rtstatus;
+
+phy_rf_cfg_fail:
+ return rtstatus;
+}
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/rf.h b/drivers/net/wireless/rtlwifi/rtl8192de/rf.h
new file mode 100644
index 0000000..74b9cfc
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8192de/rf.h
@@ -0,0 +1,44 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010 Realtek Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License 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, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#ifndef __RTL92D_RF_H__
+#define __RTL92D_RF_H__
+
+extern void rtl92d_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw,
+ u8 bandwidth);
+extern void rtl92d_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw,
+ u8 *ppowerlevel);
+extern void rtl92d_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw,
+ u8 *ppowerlevel, u8 channel);
+extern bool rtl92d_phy_rf6052_config(struct ieee80211_hw *hw);
+extern bool rtl92d_phy_enable_anotherphy(struct ieee80211_hw *hw, bool bmac0);
+extern void rtl92d_phy_powerdown_anotherphy(struct ieee80211_hw *hw,
+ bool bmac0);
+
+#endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/sw.c b/drivers/net/wireless/rtlwifi/rtl8192de/sw.c
new file mode 100644
index 0000000..0883774
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8192de/sw.c
@@ -0,0 +1,423 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010 Realtek Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License 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, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#include <linux/vmalloc.h>
+
+#include "../wifi.h"
+#include "../core.h"
+#include "../pci.h"
+#include "reg.h"
+#include "def.h"
+#include "phy.h"
+#include "dm.h"
+#include "hw.h"
+#include "sw.h"
+#include "trx.h"
+#include "led.h"
+
+static void rtl92d_init_aspm_vars(struct ieee80211_hw *hw)
+{
+ struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+
+ /*close ASPM for AMD defaultly */
+ rtlpci->const_amdpci_aspm = 0;
+
+ /*
+ * ASPM PS mode.
+ * 0 - Disable ASPM,
+ * 1 - Enable ASPM without Clock Req,
+ * 2 - Enable ASPM with Clock Req,
+ * 3 - Alwyas Enable ASPM with Clock Req,
+ * 4 - Always Enable ASPM without Clock Req.
+ * set defult to RTL8192CE:3 RTL8192E:2
+ * */
+ rtlpci->const_pci_aspm = 3;
+
+ /*Setting for PCI-E device */
+ rtlpci->const_devicepci_aspm_setting = 0x03;
+
+ /*Setting for PCI-E bridge */
+ rtlpci->const_hostpci_aspm_setting = 0x02;
+
+ /*
+ * In Hw/Sw Radio Off situation.
+ * 0 - Default,
+ * 1 - From ASPM setting without low Mac Pwr,
+ * 2 - From ASPM setting with low Mac Pwr,
+ * 3 - Bus D3
+ * set default to RTL8192CE:0 RTL8192SE:2
+ */
+ rtlpci->const_hwsw_rfoff_d3 = 0;
+
+ /*
+ * This setting works for those device with
+ * backdoor ASPM setting such as EPHY setting.
+ * 0 - Not support ASPM,
+ * 1 - Support ASPM,
+ * 2 - According to chipset.
+ */
+ rtlpci->const_support_pciaspm = 1;
+}
+
+static int rtl92d_init_sw_vars(struct ieee80211_hw *hw)
+{
+ int err;
+ u8 tid;
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+ const struct firmware *firmware;
+ static int header_print;
+
+ rtlpriv->dm.dm_initialgain_enable = true;
+ rtlpriv->dm.dm_flag = 0;
+ rtlpriv->dm.disable_framebursting = 0;
+ rtlpriv->dm.thermalvalue = 0;
+ rtlpriv->dm.useramask = 1;
+
+ /* dual mac */
+ if (rtlpriv->rtlhal.current_bandtype == BAND_ON_5G)
+ rtlpriv->phy.current_channel = 36;
+ else
+ rtlpriv->phy.current_channel = 1;
+
+ if (rtlpriv->rtlhal.macphymode != SINGLEMAC_SINGLEPHY) {
+ rtlpriv->rtlhal.disable_amsdu_8k = true;
+ /* No long RX - reduce fragmentation */
+ rtlpci->rxbuffersize = 4096;
+ }
+
+ rtlpci->transmit_config = CFENDFORM | BIT(12) | BIT(13);
+
+ rtlpci->receive_config = (
+ RCR_APPFCS
+ | RCR_AMF
+ | RCR_ADF
+ | RCR_APP_MIC
+ | RCR_APP_ICV
+ | RCR_AICV
+ | RCR_ACRC32
+ | RCR_AB
+ | RCR_AM
+ | RCR_APM
+ | RCR_APP_PHYST_RXFF
+ | RCR_HTC_LOC_CTRL
+ );
+
+ rtlpci->irq_mask[0] = (u32) (
+ IMR_ROK
+ | IMR_VODOK
+ | IMR_VIDOK
+ | IMR_BEDOK
+ | IMR_BKDOK
+ | IMR_MGNTDOK
+ | IMR_HIGHDOK
+ | IMR_BDOK
+ | IMR_RDU
+ | IMR_RXFOVW
+ );
+
+ rtlpci->irq_mask[1] = (u32) (IMR_CPWM | IMR_C2HCMD);
+
+ /* for LPS & IPS */
+ rtlpriv->psc.inactiveps = rtlpriv->cfg->mod_params->inactiveps;
+ rtlpriv->psc.swctrl_lps = rtlpriv->cfg->mod_params->swctrl_lps;
+ rtlpriv->psc.fwctrl_lps = rtlpriv->cfg->mod_params->fwctrl_lps;
+ rtlpriv->psc.reg_fwctrl_lps = 3;
+ rtlpriv->psc.reg_max_lps_awakeintvl = 5;
+ /* for ASPM, you can close aspm through
+ * set const_support_pciaspm = 0 */
+ rtl92d_init_aspm_vars(hw);
+
+ if (rtlpriv->psc.reg_fwctrl_lps == 1)
+ rtlpriv->psc.fwctrl_psmode = FW_PS_MIN_MODE;
+ else if (rtlpriv->psc.reg_fwctrl_lps == 2)
+ rtlpriv->psc.fwctrl_psmode = FW_PS_MAX_MODE;
+ else if (rtlpriv->psc.reg_fwctrl_lps == 3)
+ rtlpriv->psc.fwctrl_psmode = FW_PS_DTIM_MODE;
+
+ /* for firmware buf */
+ rtlpriv->rtlhal.pfirmware = vzalloc(0x8000);
+ if (!rtlpriv->rtlhal.pfirmware) {
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+ ("Can't alloc buffer for fw.\n"));
+ return 1;
+ }
+
+ if (!header_print) {
+ printk(KERN_INFO "rtl8192de: Driver for Realtek RTL8192DE"
+ " WLAN interface");
+ printk(KERN_INFO "rtl8192de: Loading firmware file %s\n",
+ rtlpriv->cfg->fw_name);
+ header_print++;
+ }
+ /* request fw */
+ err = request_firmware(&firmware, rtlpriv->cfg->fw_name,
+ rtlpriv->io.dev);
+ if (err) {
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+ ("Failed to request firmware!\n"));
+ return 1;
+ }
+ if (firmware->size > 0x8000) {
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+ ("Firmware is too big!\n"));
+ release_firmware(firmware);
+ return 1;
+ }
+ memcpy(rtlpriv->rtlhal.pfirmware, firmware->data, firmware->size);
+ rtlpriv->rtlhal.fwsize = firmware->size;
+ release_firmware(firmware);
+
+ /* for early mode */
+ rtlpriv->rtlhal.earlymode_enable = true;
+ for (tid = 0; tid < 8; tid++)
+ skb_queue_head_init(&rtlpriv->mac80211.skb_waitq[tid]);
+ return 0;
+}
+
+static void rtl92d_deinit_sw_vars(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u8 tid;
+
+ if (rtlpriv->rtlhal.pfirmware) {
+ vfree(rtlpriv->rtlhal.pfirmware);
+ rtlpriv->rtlhal.pfirmware = NULL;
+ }
+ for (tid = 0; tid < 8; tid++)
+ skb_queue_purge(&rtlpriv->mac80211.skb_waitq[tid]);
+}
+
+static struct rtl_hal_ops rtl8192de_hal_ops = {
+ .init_sw_vars = rtl92d_init_sw_vars,
+ .deinit_sw_vars = rtl92d_deinit_sw_vars,
+ .read_eeprom_info = rtl92de_read_eeprom_info,
+ .interrupt_recognized = rtl92de_interrupt_recognized,
+ .hw_init = rtl92de_hw_init,
+ .hw_disable = rtl92de_card_disable,
+ .hw_suspend = rtl92de_suspend,
+ .hw_resume = rtl92de_resume,
+ .enable_interrupt = rtl92de_enable_interrupt,
+ .disable_interrupt = rtl92de_disable_interrupt,
+ .set_network_type = rtl92de_set_network_type,
+ .set_chk_bssid = rtl92de_set_check_bssid,
+ .set_qos = rtl92de_set_qos,
+ .set_bcn_reg = rtl92de_set_beacon_related_registers,
+ .set_bcn_intv = rtl92de_set_beacon_interval,
+ .update_interrupt_mask = rtl92de_update_interrupt_mask,
+ .get_hw_reg = rtl92de_get_hw_reg,
+ .set_hw_reg = rtl92de_set_hw_reg,
+ .update_rate_tbl = rtl92de_update_hal_rate_tbl,
+ .fill_tx_desc = rtl92de_tx_fill_desc,
+ .fill_tx_cmddesc = rtl92de_tx_fill_cmddesc,
+ .query_rx_desc = rtl92de_rx_query_desc,
+ .set_channel_access = rtl92de_update_channel_access_setting,
+ .radio_onoff_checking = rtl92de_gpio_radio_on_off_checking,
+ .set_bw_mode = rtl92d_phy_set_bw_mode,
+ .switch_channel = rtl92d_phy_sw_chnl,
+ .dm_watchdog = rtl92d_dm_watchdog,
+ .scan_operation_backup = rtl92d_phy_scan_operation_backup,
+ .set_rf_power_state = rtl92d_phy_set_rf_power_state,
+ .led_control = rtl92de_led_control,
+ .set_desc = rtl92de_set_desc,
+ .get_desc = rtl92de_get_desc,
+ .tx_polling = rtl92de_tx_polling,
+ .enable_hw_sec = rtl92de_enable_hw_security_config,
+ .set_key = rtl92de_set_key,
+ .init_sw_leds = rtl92de_init_sw_leds,
+ .get_bbreg = rtl92d_phy_query_bb_reg,
+ .set_bbreg = rtl92d_phy_set_bb_reg,
+ .get_rfreg = rtl92d_phy_query_rf_reg,
+ .set_rfreg = rtl92d_phy_set_rf_reg,
+ .linked_set_reg = rtl92d_linked_set_reg,
+};
+
+static struct rtl_mod_params rtl92de_mod_params = {
+ .sw_crypto = false,
+ .inactiveps = true,
+ .swctrl_lps = true,
+ .fwctrl_lps = false,
+};
+
+static struct rtl_hal_cfg rtl92de_hal_cfg = {
+ .bar_id = 2,
+ .write_readback = true,
+ .name = "rtl8192de",
+ .fw_name = "rtlwifi/rtl8192defw.bin",
+ .ops = &rtl8192de_hal_ops,
+ .mod_params = &rtl92de_mod_params,
+
+ .maps[SYS_ISO_CTRL] = REG_SYS_ISO_CTRL,
+ .maps[SYS_FUNC_EN] = REG_SYS_FUNC_EN,
+ .maps[SYS_CLK] = REG_SYS_CLKR,
+ .maps[MAC_RCR_AM] = RCR_AM,
+ .maps[MAC_RCR_AB] = RCR_AB,
+ .maps[MAC_RCR_ACRC32] = RCR_ACRC32,
+ .maps[MAC_RCR_ACF] = RCR_ACF,
+ .maps[MAC_RCR_AAP] = RCR_AAP,
+
+ .maps[EFUSE_TEST] = REG_EFUSE_TEST,
+ .maps[EFUSE_CTRL] = REG_EFUSE_CTRL,
+ .maps[EFUSE_CLK] = 0, /* just for 92se */
+ .maps[EFUSE_CLK_CTRL] = REG_EFUSE_CTRL,
+ .maps[EFUSE_PWC_EV12V] = PWC_EV12V,
+ .maps[EFUSE_FEN_ELDR] = FEN_ELDR,
+ .maps[EFUSE_LOADER_CLK_EN] = LOADER_CLK_EN,
+ .maps[EFUSE_ANA8M] = 0, /* just for 92se */
+ .maps[EFUSE_HWSET_MAX_SIZE] = HWSET_MAX_SIZE,
+ .maps[EFUSE_MAX_SECTION_MAP] = EFUSE_MAX_SECTION,
+ .maps[EFUSE_REAL_CONTENT_SIZE] = EFUSE_REAL_CONTENT_LEN,
+
+ .maps[RWCAM] = REG_CAMCMD,
+ .maps[WCAMI] = REG_CAMWRITE,
+ .maps[RCAMO] = REG_CAMREAD,
+ .maps[CAMDBG] = REG_CAMDBG,
+ .maps[SECR] = REG_SECCFG,
+ .maps[SEC_CAM_NONE] = CAM_NONE,
+ .maps[SEC_CAM_WEP40] = CAM_WEP40,
+ .maps[SEC_CAM_TKIP] = CAM_TKIP,
+ .maps[SEC_CAM_AES] = CAM_AES,
+ .maps[SEC_CAM_WEP104] = CAM_WEP104,
+
+ .maps[RTL_IMR_BCNDMAINT6] = IMR_BCNDMAINT6,
+ .maps[RTL_IMR_BCNDMAINT5] = IMR_BCNDMAINT5,
+ .maps[RTL_IMR_BCNDMAINT4] = IMR_BCNDMAINT4,
+ .maps[RTL_IMR_BCNDMAINT3] = IMR_BCNDMAINT3,
+ .maps[RTL_IMR_BCNDMAINT2] = IMR_BCNDMAINT2,
+ .maps[RTL_IMR_BCNDMAINT1] = IMR_BCNDMAINT1,
+ .maps[RTL_IMR_BCNDOK8] = IMR_BCNDOK8,
+ .maps[RTL_IMR_BCNDOK7] = IMR_BCNDOK7,
+ .maps[RTL_IMR_BCNDOK6] = IMR_BCNDOK6,
+ .maps[RTL_IMR_BCNDOK5] = IMR_BCNDOK5,
+ .maps[RTL_IMR_BCNDOK4] = IMR_BCNDOK4,
+ .maps[RTL_IMR_BCNDOK3] = IMR_BCNDOK3,
+ .maps[RTL_IMR_BCNDOK2] = IMR_BCNDOK2,
+ .maps[RTL_IMR_BCNDOK1] = IMR_BCNDOK1,
+ .maps[RTL_IMR_TIMEOUT2] = IMR_TIMEOUT2,
+ .maps[RTL_IMR_TIMEOUT1] = IMR_TIMEOUT1,
+
+ .maps[RTL_IMR_TXFOVW] = IMR_TXFOVW,
+ .maps[RTL_IMR_PSTIMEOUT] = IMR_PSTIMEOUT,
+ .maps[RTL_IMR_BcnInt] = IMR_BcnInt,
+ .maps[RTL_IMR_RXFOVW] = IMR_RXFOVW,
+ .maps[RTL_IMR_RDU] = IMR_RDU,
+ .maps[RTL_IMR_ATIMEND] = IMR_ATIMEND,
+ .maps[RTL_IMR_BDOK] = IMR_BDOK,
+ .maps[RTL_IMR_MGNTDOK] = IMR_MGNTDOK,
+ .maps[RTL_IMR_TBDER] = IMR_TBDER,
+ .maps[RTL_IMR_HIGHDOK] = IMR_HIGHDOK,
+ .maps[RTL_IMR_TBDOK] = IMR_TBDOK,
+ .maps[RTL_IMR_BKDOK] = IMR_BKDOK,
+ .maps[RTL_IMR_BEDOK] = IMR_BEDOK,
+ .maps[RTL_IMR_VIDOK] = IMR_VIDOK,
+ .maps[RTL_IMR_VODOK] = IMR_VODOK,
+ .maps[RTL_IMR_ROK] = IMR_ROK,
+ .maps[RTL_IBSS_INT_MASKS] = (IMR_BcnInt | IMR_TBDOK | IMR_TBDER),
+
+ .maps[RTL_RC_CCK_RATE1M] = DESC92D_RATE1M,
+ .maps[RTL_RC_CCK_RATE2M] = DESC92D_RATE2M,
+ .maps[RTL_RC_CCK_RATE5_5M] = DESC92D_RATE5_5M,
+ .maps[RTL_RC_CCK_RATE11M] = DESC92D_RATE11M,
+ .maps[RTL_RC_OFDM_RATE6M] = DESC92D_RATE6M,
+ .maps[RTL_RC_OFDM_RATE9M] = DESC92D_RATE9M,
+ .maps[RTL_RC_OFDM_RATE12M] = DESC92D_RATE12M,
+ .maps[RTL_RC_OFDM_RATE18M] = DESC92D_RATE18M,
+ .maps[RTL_RC_OFDM_RATE24M] = DESC92D_RATE24M,
+ .maps[RTL_RC_OFDM_RATE36M] = DESC92D_RATE36M,
+ .maps[RTL_RC_OFDM_RATE48M] = DESC92D_RATE48M,
+ .maps[RTL_RC_OFDM_RATE54M] = DESC92D_RATE54M,
+
+ .maps[RTL_RC_HT_RATEMCS7] = DESC92D_RATEMCS7,
+ .maps[RTL_RC_HT_RATEMCS15] = DESC92D_RATEMCS15,
+};
+
+static struct pci_device_id rtl92de_pci_ids[] __devinitdata = {
+ {RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8193, rtl92de_hal_cfg)},
+ {RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x002B, rtl92de_hal_cfg)},
+ {},
+};
+
+MODULE_DEVICE_TABLE(pci, rtl92de_pci_ids);
+
+MODULE_AUTHOR("lizhaoming <chaoming_li@realsil.com.cn>");
+MODULE_AUTHOR("Realtek WlanFAE <wlanfae@realtek.com>");
+MODULE_AUTHOR("Larry Finger <Larry.Finger@lwfinger.net>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Realtek 8192DE 802.11n Dual Mac PCI wireless");
+MODULE_FIRMWARE("rtlwifi/rtl8192defw.bin");
+
+module_param_named(swenc, rtl92de_mod_params.sw_crypto, bool, 0444);
+module_param_named(ips, rtl92de_mod_params.inactiveps, bool, 0444);
+module_param_named(swlps, rtl92de_mod_params.swctrl_lps, bool, 0444);
+module_param_named(fwlps, rtl92de_mod_params.fwctrl_lps, bool, 0444);
+MODULE_PARM_DESC(swenc, "using hardware crypto (default 0 [hardware])\n");
+MODULE_PARM_DESC(ips, "using no link power save (default 1 is open)\n");
+MODULE_PARM_DESC(swlps, "using linked sw control power save (default 1"
+ " is open)\n");
+
+static struct pci_driver rtl92de_driver = {
+ .name = KBUILD_MODNAME,
+ .id_table = rtl92de_pci_ids,
+ .probe = rtl_pci_probe,
+ .remove = rtl_pci_disconnect,
+
+#ifdef CONFIG_PM
+ .suspend = rtl_pci_suspend,
+ .resume = rtl_pci_resume,
+#endif
+
+};
+
+/* add global spin lock to solve the problem that
+ * Dul mac register operation on the same time */
+spinlock_t globalmutex_power;
+spinlock_t globalmutex_for_fwdownload;
+spinlock_t globalmutex_for_power_and_efuse;
+
+static int __init rtl92de_module_init(void)
+{
+ int ret = 0;
+
+ spin_lock_init(&globalmutex_power);
+ spin_lock_init(&globalmutex_for_fwdownload);
+ spin_lock_init(&globalmutex_for_power_and_efuse);
+
+ ret = pci_register_driver(&rtl92de_driver);
+ if (ret)
+ RT_ASSERT(false, (": No device found\n"));
+ return ret;
+}
+
+static void __exit rtl92de_module_exit(void)
+{
+ pci_unregister_driver(&rtl92de_driver);
+}
+
+module_init(rtl92de_module_init);
+module_exit(rtl92de_module_exit);
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/sw.h b/drivers/net/wireless/rtlwifi/rtl8192de/sw.h
new file mode 100644
index 0000000..c95e47d
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8192de/sw.h
@@ -0,0 +1,37 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010 Realtek Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License 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, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#ifndef __RTL92DE_SW_H__
+#define __RTL92DE_SW_H__
+
+extern spinlock_t globalmutex_power;
+extern spinlock_t globalmutex_for_fwdownload;
+extern spinlock_t globalmutex_for_power_and_efuse;
+
+#endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/table.c b/drivers/net/wireless/rtlwifi/rtl8192de/table.c
new file mode 100644
index 0000000..bad7f94
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8192de/table.c
@@ -0,0 +1,1690 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010 Realtek Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License 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, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ * Created on 2010/12/23, 6:38
+ *****************************************************************************/
+
+#include <linux/types.h>
+
+#include "table.h"
+
+u32 rtl8192de_phy_reg_2tarray[PHY_REG_2T_ARRAYLENGTH] = {
+ 0x024, 0x0011800d,
+ 0x028, 0x00ffdb83,
+ 0x014, 0x088ba955,
+ 0x010, 0x49022b03,
+ 0x800, 0x80040002,
+ 0x804, 0x00000003,
+ 0x808, 0x0000fc00,
+ 0x80c, 0x0000000a,
+ 0x810, 0x80706388,
+ 0x814, 0x020c3d10,
+ 0x818, 0x02200385,
+ 0x81c, 0x00000000,
+ 0x820, 0x01000100,
+ 0x824, 0x00390004,
+ 0x828, 0x01000100,
+ 0x82c, 0x00390004,
+ 0x830, 0x27272727,
+ 0x834, 0x27272727,
+ 0x838, 0x27272727,
+ 0x83c, 0x27272727,
+ 0x840, 0x00010000,
+ 0x844, 0x00010000,
+ 0x848, 0x27272727,
+ 0x84c, 0x27272727,
+ 0x850, 0x00000000,
+ 0x854, 0x00000000,
+ 0x858, 0x569a569a,
+ 0x85c, 0x0c1b25a4,
+ 0x860, 0x66e60230,
+ 0x864, 0x061f0130,
+ 0x868, 0x27272727,
+ 0x86c, 0x272b2b2b,
+ 0x870, 0x07000700,
+ 0x874, 0x22188000,
+ 0x878, 0x08080808,
+ 0x87c, 0x00007ff8,
+ 0x880, 0xc0083070,
+ 0x884, 0x00000cd5,
+ 0x888, 0x00000000,
+ 0x88c, 0xcc0000c0,
+ 0x890, 0x00000800,
+ 0x894, 0xfffffffe,
+ 0x898, 0x40302010,
+ 0x89c, 0x00706050,
+ 0x900, 0x00000000,
+ 0x904, 0x00000023,
+ 0x908, 0x00000000,
+ 0x90c, 0x81121313,
+ 0xa00, 0x00d047c8,
+ 0xa04, 0x80ff000c,
+ 0xa08, 0x8c838300,
+ 0xa0c, 0x2e68120f,
+ 0xa10, 0x9500bb78,
+ 0xa14, 0x11144028,
+ 0xa18, 0x00881117,
+ 0xa1c, 0x89140f00,
+ 0xa20, 0x1a1b0000,
+ 0xa24, 0x090e1317,
+ 0xa28, 0x00000204,
+ 0xa2c, 0x00d30000,
+ 0xa70, 0x101fbf00,
+ 0xa74, 0x00000007,
+ 0xc00, 0x40071d40,
+ 0xc04, 0x03a05633,
+ 0xc08, 0x001000e4,
+ 0xc0c, 0x6c6c6c6c,
+ 0xc10, 0x08800000,
+ 0xc14, 0x40000100,
+ 0xc18, 0x08800000,
+ 0xc1c, 0x40000100,
+ 0xc20, 0x00000000,
+ 0xc24, 0x00000000,
+ 0xc28, 0x00000000,
+ 0xc2c, 0x00000000,
+ 0xc30, 0x69e9ac44,
+ 0xc34, 0x469652cf,
+ 0xc38, 0x49795994,
+ 0xc3c, 0x0a979718,
+ 0xc40, 0x1f7c403f,
+ 0xc44, 0x000100b7,
+ 0xc48, 0xec020107,
+ 0xc4c, 0x007f037f,
+ 0xc50, 0x69543420,
+ 0xc54, 0x43bc009e,
+ 0xc58, 0x69543420,
+ 0xc5c, 0x433c00a8,
+ 0xc60, 0x00000000,
+ 0xc64, 0x5116848b,
+ 0xc68, 0x47c00bff,
+ 0xc6c, 0x00000036,
+ 0xc70, 0x2c7f000d,
+ 0xc74, 0x058610db,
+ 0xc78, 0x0000001f,
+ 0xc7c, 0x40b95612,
+ 0xc80, 0x40000100,
+ 0xc84, 0x20f60000,
+ 0xc88, 0x40000100,
+ 0xc8c, 0x20e00000,
+ 0xc90, 0x00121820,
+ 0xc94, 0x00000007,
+ 0xc98, 0x00121820,
+ 0xc9c, 0x00007f7f,
+ 0xca0, 0x00000000,
+ 0xca4, 0x00000080,
+ 0xca8, 0x00000000,
+ 0xcac, 0x00000000,
+ 0xcb0, 0x00000000,
+ 0xcb4, 0x00000000,
+ 0xcb8, 0x00000000,
+ 0xcbc, 0x28000000,
+ 0xcc0, 0x00000000,
+ 0xcc4, 0x00000000,
+ 0xcc8, 0x00000000,
+ 0xccc, 0x00000000,
+ 0xcd0, 0x00000000,
+ 0xcd4, 0x00000000,
+ 0xcd8, 0x64b11e20,
+ 0xcdc, 0xe8767533,
+ 0xce0, 0x00222222,
+ 0xce4, 0x00000000,
+ 0xce8, 0x37644302,
+ 0xcec, 0x2f97d40c,
+ 0xd00, 0x00080740,
+ 0xd04, 0x00020403,
+ 0xd08, 0x0000907f,
+ 0xd0c, 0x20010201,
+ 0xd10, 0xa0633333,
+ 0xd14, 0x3333bc43,
+ 0xd18, 0x7a8f5b6b,
+ 0xd2c, 0xcc979975,
+ 0xd30, 0x00000000,
+ 0xd34, 0x80608404,
+ 0xd38, 0x00000000,
+ 0xd3c, 0x00027293,
+ 0xd40, 0x00000000,
+ 0xd44, 0x00000000,
+ 0xd48, 0x00000000,
+ 0xd4c, 0x00000000,
+ 0xd50, 0x6437140a,
+ 0xd54, 0x00000000,
+ 0xd58, 0x00000000,
+ 0xd5c, 0x30032064,
+ 0xd60, 0x4653de68,
+ 0xd64, 0x04518a3c,
+ 0xd68, 0x00002101,
+ 0xd6c, 0x2a201c16,
+ 0xd70, 0x1812362e,
+ 0xd74, 0x322c2220,
+ 0xd78, 0x000e3c24,
+ 0xe00, 0x2a2a2a2a,
+ 0xe04, 0x2a2a2a2a,
+ 0xe08, 0x03902a2a,
+ 0xe10, 0x2a2a2a2a,
+ 0xe14, 0x2a2a2a2a,
+ 0xe18, 0x2a2a2a2a,
+ 0xe1c, 0x2a2a2a2a,
+ 0xe28, 0x00000000,
+ 0xe30, 0x1000dc1f,
+ 0xe34, 0x10008c1f,
+ 0xe38, 0x02140102,
+ 0xe3c, 0x681604c2,
+ 0xe40, 0x01007c00,
+ 0xe44, 0x01004800,
+ 0xe48, 0xfb000000,
+ 0xe4c, 0x000028d1,
+ 0xe50, 0x1000dc1f,
+ 0xe54, 0x10008c1f,
+ 0xe58, 0x02140102,
+ 0xe5c, 0x28160d05,
+ 0xe60, 0x00000010,
+ 0xe68, 0x001b25a4,
+ 0xe6c, 0x63db25a4,
+ 0xe70, 0x63db25a4,
+ 0xe74, 0x0c126da4,
+ 0xe78, 0x0c126da4,
+ 0xe7c, 0x0c126da4,
+ 0xe80, 0x0c126da4,
+ 0xe84, 0x63db25a4,
+ 0xe88, 0x0c126da4,
+ 0xe8c, 0x63db25a4,
+ 0xed0, 0x63db25a4,
+ 0xed4, 0x63db25a4,
+ 0xed8, 0x63db25a4,
+ 0xedc, 0x001b25a4,
+ 0xee0, 0x001b25a4,
+ 0xeec, 0x6fdb25a4,
+ 0xf14, 0x00000003,
+ 0xf1c, 0x00000064,
+ 0xf4c, 0x00000004,
+ 0xf00, 0x00000300,
+};
+
+u32 rtl8192de_phy_reg_array_pg[PHY_REG_ARRAY_PG_LENGTH] = {
+ 0xe00, 0xffffffff, 0x07090c0c,
+ 0xe04, 0xffffffff, 0x01020405,
+ 0xe08, 0x0000ff00, 0x00000000,
+ 0x86c, 0xffffff00, 0x00000000,
+ 0xe10, 0xffffffff, 0x0b0c0c0e,
+ 0xe14, 0xffffffff, 0x01030506,
+ 0xe18, 0xffffffff, 0x0b0c0d0e,
+ 0xe1c, 0xffffffff, 0x01030509,
+ 0x830, 0xffffffff, 0x07090c0c,
+ 0x834, 0xffffffff, 0x01020405,
+ 0x838, 0xffffff00, 0x00000000,
+ 0x86c, 0x000000ff, 0x00000000,
+ 0x83c, 0xffffffff, 0x0b0c0c0e,
+ 0x848, 0xffffffff, 0x01030506,
+ 0x84c, 0xffffffff, 0x0b0c0d0e,
+ 0x868, 0xffffffff, 0x01030509,
+ 0xe00, 0xffffffff, 0x00000000,
+ 0xe04, 0xffffffff, 0x00000000,
+ 0xe08, 0x0000ff00, 0x00000000,
+ 0x86c, 0xffffff00, 0x00000000,
+ 0xe10, 0xffffffff, 0x00000000,
+ 0xe14, 0xffffffff, 0x00000000,
+ 0xe18, 0xffffffff, 0x00000000,
+ 0xe1c, 0xffffffff, 0x00000000,
+ 0x830, 0xffffffff, 0x00000000,
+ 0x834, 0xffffffff, 0x00000000,
+ 0x838, 0xffffff00, 0x00000000,
+ 0x86c, 0x000000ff, 0x00000000,
+ 0x83c, 0xffffffff, 0x00000000,
+ 0x848, 0xffffffff, 0x00000000,
+ 0x84c, 0xffffffff, 0x00000000,
+ 0x868, 0xffffffff, 0x00000000,
+ 0xe00, 0xffffffff, 0x04040404,
+ 0xe04, 0xffffffff, 0x00020204,
+ 0xe08, 0x0000ff00, 0x00000000,
+ 0x86c, 0xffffff00, 0x00000000,
+ 0xe10, 0xffffffff, 0x06060606,
+ 0xe14, 0xffffffff, 0x00020406,
+ 0xe18, 0xffffffff, 0x00000000,
+ 0xe1c, 0xffffffff, 0x00000000,
+ 0x830, 0xffffffff, 0x04040404,
+ 0x834, 0xffffffff, 0x00020204,
+ 0x838, 0xffffff00, 0x00000000,
+ 0x86c, 0x000000ff, 0x00000000,
+ 0x83c, 0xffffffff, 0x06060606,
+ 0x848, 0xffffffff, 0x00020406,
+ 0x84c, 0xffffffff, 0x00000000,
+ 0x868, 0xffffffff, 0x00000000,
+ 0xe00, 0xffffffff, 0x00000000,
+ 0xe04, 0xffffffff, 0x00000000,
+ 0xe08, 0x0000ff00, 0x00000000,
+ 0x86c, 0xffffff00, 0x00000000,
+ 0xe10, 0xffffffff, 0x00000000,
+ 0xe14, 0xffffffff, 0x00000000,
+ 0xe18, 0xffffffff, 0x00000000,
+ 0xe1c, 0xffffffff, 0x00000000,
+ 0x830, 0xffffffff, 0x00000000,
+ 0x834, 0xffffffff, 0x00000000,
+ 0x838, 0xffffff00, 0x00000000,
+ 0x86c, 0x000000ff, 0x00000000,
+ 0x83c, 0xffffffff, 0x00000000,
+ 0x848, 0xffffffff, 0x00000000,
+ 0x84c, 0xffffffff, 0x00000000,
+ 0x868, 0xffffffff, 0x00000000,
+ 0xe00, 0xffffffff, 0x00000000,
+ 0xe04, 0xffffffff, 0x00000000,
+ 0xe08, 0x0000ff00, 0x00000000,
+ 0x86c, 0xffffff00, 0x00000000,
+ 0xe10, 0xffffffff, 0x00000000,
+ 0xe14, 0xffffffff, 0x00000000,
+ 0xe18, 0xffffffff, 0x00000000,
+ 0xe1c, 0xffffffff, 0x00000000,
+ 0x830, 0xffffffff, 0x00000000,
+ 0x834, 0xffffffff, 0x00000000,
+ 0x838, 0xffffff00, 0x00000000,
+ 0x86c, 0x000000ff, 0x00000000,
+ 0x83c, 0xffffffff, 0x00000000,
+ 0x848, 0xffffffff, 0x00000000,
+ 0x84c, 0xffffffff, 0x00000000,
+ 0x868, 0xffffffff, 0x00000000,
+ 0xe00, 0xffffffff, 0x04040404,
+ 0xe04, 0xffffffff, 0x00020204,
+ 0xe08, 0x0000ff00, 0x00000000,
+ 0x86c, 0xffffff00, 0x00000000,
+ 0xe10, 0xffffffff, 0x00000000,
+ 0xe14, 0xffffffff, 0x00000000,
+ 0xe18, 0xffffffff, 0x00000000,
+ 0xe1c, 0xffffffff, 0x00000000,
+ 0x830, 0xffffffff, 0x04040404,
+ 0x834, 0xffffffff, 0x00020204,
+ 0x838, 0xffffff00, 0x00000000,
+ 0x86c, 0x000000ff, 0x00000000,
+ 0x83c, 0xffffffff, 0x00000000,
+ 0x848, 0xffffffff, 0x00000000,
+ 0x84c, 0xffffffff, 0x00000000,
+ 0x868, 0xffffffff, 0x00000000,
+ 0xe00, 0xffffffff, 0x00000000,
+ 0xe04, 0xffffffff, 0x00000000,
+ 0xe08, 0x0000ff00, 0x00000000,
+ 0x86c, 0xffffff00, 0x00000000,
+ 0xe10, 0xffffffff, 0x00000000,
+ 0xe14, 0xffffffff, 0x00000000,
+ 0xe18, 0xffffffff, 0x00000000,
+ 0xe1c, 0xffffffff, 0x00000000,
+ 0x830, 0xffffffff, 0x00000000,
+ 0x834, 0xffffffff, 0x00000000,
+ 0x838, 0xffffff00, 0x00000000,
+ 0x86c, 0x000000ff, 0x00000000,
+ 0x83c, 0xffffffff, 0x00000000,
+ 0x848, 0xffffffff, 0x00000000,
+ 0x84c, 0xffffffff, 0x00000000,
+ 0x868, 0xffffffff, 0x00000000,
+ 0xe00, 0xffffffff, 0x04040404,
+ 0xe04, 0xffffffff, 0x00020204,
+ 0xe08, 0x0000ff00, 0x00000000,
+ 0x86c, 0xffffff00, 0x00000000,
+ 0xe10, 0xffffffff, 0x08080808,
+ 0xe14, 0xffffffff, 0x00040408,
+ 0xe18, 0xffffffff, 0x00000000,
+ 0xe1c, 0xffffffff, 0x00000000,
+ 0x830, 0xffffffff, 0x04040404,
+ 0x834, 0xffffffff, 0x00020204,
+ 0x838, 0xffffff00, 0x00000000,
+ 0x86c, 0x000000ff, 0x00000000,
+ 0x83c, 0xffffffff, 0x08080808,
+ 0x848, 0xffffffff, 0x00040408,
+ 0x84c, 0xffffffff, 0x00000000,
+ 0x868, 0xffffffff, 0x00000000,
+ 0xe00, 0xffffffff, 0x04040404,
+ 0xe04, 0xffffffff, 0x00020204,
+ 0xe08, 0x0000ff00, 0x00000000,
+ 0x86c, 0xffffff00, 0x00000000,
+ 0xe10, 0xffffffff, 0x08080808,
+ 0xe14, 0xffffffff, 0x00040408,
+ 0xe18, 0xffffffff, 0x00000000,
+ 0xe1c, 0xffffffff, 0x00000000,
+ 0x830, 0xffffffff, 0x04040404,
+ 0x834, 0xffffffff, 0x00020204,
+ 0x838, 0xffffff00, 0x00000000,
+ 0x86c, 0x000000ff, 0x00000000,
+ 0x83c, 0xffffffff, 0x08080808,
+ 0x848, 0xffffffff, 0x00040408,
+ 0x84c, 0xffffffff, 0x00000000,
+ 0x868, 0xffffffff, 0x00000000,
+ 0xe00, 0xffffffff, 0x04040404,
+ 0xe04, 0xffffffff, 0x00020204,
+ 0xe08, 0x0000ff00, 0x00000000,
+ 0x86c, 0xffffff00, 0x00000000,
+ 0xe10, 0xffffffff, 0x08080808,
+ 0xe14, 0xffffffff, 0x00040408,
+ 0xe18, 0xffffffff, 0x00000000,
+ 0xe1c, 0xffffffff, 0x00000000,
+ 0x830, 0xffffffff, 0x04040404,
+ 0x834, 0xffffffff, 0x00020204,
+ 0x838, 0xffffff00, 0x00000000,
+ 0x86c, 0x000000ff, 0x00000000,
+ 0x83c, 0xffffffff, 0x08080808,
+ 0x848, 0xffffffff, 0x00040408,
+ 0x84c, 0xffffffff, 0x00000000,
+ 0x868, 0xffffffff, 0x00000000,
+ 0xe00, 0xffffffff, 0x04040404,
+ 0xe04, 0xffffffff, 0x00020204,
+ 0xe08, 0x0000ff00, 0x00000000,
+ 0x86c, 0xffffff00, 0x00000000,
+ 0xe10, 0xffffffff, 0x08080808,
+ 0xe14, 0xffffffff, 0x00040408,
+ 0xe18, 0xffffffff, 0x00000000,
+ 0xe1c, 0xffffffff, 0x00000000,
+ 0x830, 0xffffffff, 0x04040404,
+ 0x834, 0xffffffff, 0x00020204,
+ 0x838, 0xffffff00, 0x00000000,
+ 0x86c, 0x000000ff, 0x00000000,
+ 0x83c, 0xffffffff, 0x08080808,
+ 0x848, 0xffffffff, 0x00040408,
+ 0x84c, 0xffffffff, 0x00000000,
+ 0x868, 0xffffffff, 0x00000000,
+ 0xe00, 0xffffffff, 0x04040404,
+ 0xe04, 0xffffffff, 0x00020204,
+ 0xe08, 0x0000ff00, 0x00000000,
+ 0x86c, 0xffffff00, 0x00000000,
+ 0xe10, 0xffffffff, 0x08080808,
+ 0xe14, 0xffffffff, 0x00040408,
+ 0xe18, 0xffffffff, 0x00000000,
+ 0xe1c, 0xffffffff, 0x00000000,
+ 0x830, 0xffffffff, 0x04040404,
+ 0x834, 0xffffffff, 0x00020204,
+ 0x838, 0xffffff00, 0x00000000,
+ 0x86c, 0x000000ff, 0x00000000,
+ 0x83c, 0xffffffff, 0x08080808,
+ 0x848, 0xffffffff, 0x00040408,
+ 0x84c, 0xffffffff, 0x00000000,
+ 0x868, 0xffffffff, 0x00000000,
+ 0xe00, 0xffffffff, 0x04040404,
+ 0xe04, 0xffffffff, 0x00020204,
+ 0xe08, 0x0000ff00, 0x00000000,
+ 0x86c, 0xffffff00, 0x00000000,
+ 0xe10, 0xffffffff, 0x08080808,
+ 0xe14, 0xffffffff, 0x00040408,
+ 0xe18, 0xffffffff, 0x00000000,
+ 0xe1c, 0xffffffff, 0x00000000,
+ 0x830, 0xffffffff, 0x04040404,
+ 0x834, 0xffffffff, 0x00020204,
+ 0x838, 0xffffff00, 0x00000000,
+ 0x86c, 0x000000ff, 0x00000000,
+ 0x83c, 0xffffffff, 0x08080808,
+ 0x848, 0xffffffff, 0x00040408,
+ 0x84c, 0xffffffff, 0x00000000,
+ 0x868, 0xffffffff, 0x00000000,
+};
+
+u32 rtl8192de_radioa_2tarray[RADIOA_2T_ARRAYLENGTH] = {
+ 0x000, 0x00030000,
+ 0x001, 0x00030000,
+ 0x002, 0x00000000,
+ 0x003, 0x00018c63,
+ 0x004, 0x00018c63,
+ 0x008, 0x00084000,
+ 0x00b, 0x0001c000,
+ 0x00e, 0x00018c67,
+ 0x00f, 0x00000851,
+ 0x014, 0x00021440,
+ 0x018, 0x00017524,
+ 0x019, 0x00000000,
+ 0x01d, 0x000a1290,
+ 0x023, 0x00001558,
+ 0x01a, 0x00030a99,
+ 0x01b, 0x00040b00,
+ 0x01c, 0x000fc339,
+ 0x03a, 0x000a57eb,
+ 0x03b, 0x00020000,
+ 0x03c, 0x000ff454,
+ 0x020, 0x0000aa52,
+ 0x021, 0x00054000,
+ 0x040, 0x0000aa52,
+ 0x041, 0x00014000,
+ 0x025, 0x000803be,
+ 0x026, 0x000fc638,
+ 0x027, 0x00077c18,
+ 0x028, 0x000de471,
+ 0x029, 0x000d7110,
+ 0x02a, 0x0008cb04,
+ 0x02b, 0x0004128b,
+ 0x02c, 0x00001840,
+ 0x043, 0x0002444f,
+ 0x044, 0x0001adb0,
+ 0x045, 0x00056467,
+ 0x046, 0x0008992c,
+ 0x047, 0x0000452c,
+ 0x048, 0x000f9c43,
+ 0x049, 0x00002e0c,
+ 0x04a, 0x000546eb,
+ 0x04b, 0x0008966c,
+ 0x04c, 0x0000dde9,
+ 0x018, 0x00007401,
+ 0x000, 0x00070000,
+ 0x012, 0x000dc000,
+ 0x012, 0x00090000,
+ 0x012, 0x00051000,
+ 0x012, 0x00012000,
+ 0x013, 0x000287b7,
+ 0x013, 0x000247ab,
+ 0x013, 0x0002079f,
+ 0x013, 0x0001c793,
+ 0x013, 0x0001839b,
+ 0x013, 0x00014392,
+ 0x013, 0x0001019a,
+ 0x013, 0x0000c191,
+ 0x013, 0x00008194,
+ 0x013, 0x000040a0,
+ 0x013, 0x00000018,
+ 0x015, 0x0000f424,
+ 0x015, 0x0004f424,
+ 0x015, 0x0008f424,
+ 0x016, 0x000e1330,
+ 0x016, 0x000a1330,
+ 0x016, 0x00061330,
+ 0x016, 0x00021330,
+ 0x018, 0x00017524,
+ 0x000, 0x00070000,
+ 0x012, 0x000cf000,
+ 0x012, 0x000bc000,
+ 0x012, 0x00078000,
+ 0x012, 0x00000000,
+ 0x013, 0x000287bc,
+ 0x013, 0x000247b0,
+ 0x013, 0x000203b4,
+ 0x013, 0x0001c3a8,
+ 0x013, 0x000181b4,
+ 0x013, 0x000141a8,
+ 0x013, 0x000100b0,
+ 0x013, 0x0000c0a4,
+ 0x013, 0x0000b02c,
+ 0x013, 0x00004020,
+ 0x013, 0x00000014,
+ 0x015, 0x0000f4c3,
+ 0x015, 0x0004f4c3,
+ 0x015, 0x0008f4c3,
+ 0x016, 0x000e085f,
+ 0x016, 0x000a085f,
+ 0x016, 0x0006085f,
+ 0x016, 0x0002085f,
+ 0x018, 0x00037524,
+ 0x000, 0x00070000,
+ 0x012, 0x000cf000,
+ 0x012, 0x000bc000,
+ 0x012, 0x00078000,
+ 0x012, 0x00000000,
+ 0x013, 0x000287bc,
+ 0x013, 0x000247b0,
+ 0x013, 0x000203b4,
+ 0x013, 0x0001c3a8,
+ 0x013, 0x000181b4,
+ 0x013, 0x000141a8,
+ 0x013, 0x000100b0,
+ 0x013, 0x0000c0a4,
+ 0x013, 0x0000b02c,
+ 0x013, 0x00004020,
+ 0x013, 0x00000014,
+ 0x015, 0x0000f4c3,
+ 0x015, 0x0004f4c3,
+ 0x015, 0x0008f4c3,
+ 0x016, 0x000e085f,
+ 0x016, 0x000a085f,
+ 0x016, 0x0006085f,
+ 0x016, 0x0002085f,
+ 0x018, 0x00057568,
+ 0x000, 0x00070000,
+ 0x012, 0x000cf000,
+ 0x012, 0x000bc000,
+ 0x012, 0x00078000,
+ 0x012, 0x00000000,
+ 0x013, 0x000287bc,
+ 0x013, 0x000247b0,
+ 0x013, 0x000203b4,
+ 0x013, 0x0001c3a8,
+ 0x013, 0x000181b4,
+ 0x013, 0x000141a8,
+ 0x013, 0x000100b0,
+ 0x013, 0x0000c0a4,
+ 0x013, 0x0000b02c,
+ 0x013, 0x00004020,
+ 0x013, 0x00000014,
+ 0x015, 0x0000f4c3,
+ 0x015, 0x0004f4c3,
+ 0x015, 0x0008f4c3,
+ 0x016, 0x000e085f,
+ 0x016, 0x000a085f,
+ 0x016, 0x0006085f,
+ 0x016, 0x0002085f,
+ 0x030, 0x0004470f,
+ 0x031, 0x00044ff0,
+ 0x032, 0x00000070,
+ 0x033, 0x000dd480,
+ 0x034, 0x000ffac0,
+ 0x035, 0x000b80c0,
+ 0x036, 0x00077000,
+ 0x037, 0x00064ff2,
+ 0x038, 0x000e7661,
+ 0x039, 0x00000e90,
+ 0x000, 0x00030000,
+ 0x018, 0x0000f401,
+ 0x0fe, 0x00000000,
+ 0x0fe, 0x00000000,
+ 0x01e, 0x00088009,
+ 0x01f, 0x00080003,
+ 0x0fe, 0x00000000,
+ 0x01e, 0x00088001,
+ 0x01f, 0x00080000,
+ 0x0fe, 0x00000000,
+ 0x018, 0x00097524,
+ 0x0fe, 0x00000000,
+ 0x0fe, 0x00000000,
+ 0x0fe, 0x00000000,
+ 0x0fe, 0x00000000,
+ 0x02b, 0x00041289,
+ 0x0fe, 0x00000000,
+ 0x02d, 0x0006aaaa,
+ 0x02e, 0x000b4d01,
+ 0x02d, 0x00080000,
+ 0x02e, 0x00004d02,
+ 0x02d, 0x00095555,
+ 0x02e, 0x00054d03,
+ 0x02d, 0x000aaaaa,
+ 0x02e, 0x000b4d04,
+ 0x02d, 0x000c0000,
+ 0x02e, 0x00004d05,
+ 0x02d, 0x000d5555,
+ 0x02e, 0x00054d06,
+ 0x02d, 0x000eaaaa,
+ 0x02e, 0x000b4d07,
+ 0x02d, 0x00000000,
+ 0x02e, 0x00005108,
+ 0x02d, 0x00015555,
+ 0x02e, 0x00055109,
+ 0x02d, 0x0002aaaa,
+ 0x02e, 0x000b510a,
+ 0x02d, 0x00040000,
+ 0x02e, 0x0000510b,
+ 0x02d, 0x00055555,
+ 0x02e, 0x0005510c,
+};
+
+u32 rtl8192de_radiob_2tarray[RADIOB_2T_ARRAYLENGTH] = {
+ 0x000, 0x00030000,
+ 0x001, 0x00030000,
+ 0x002, 0x00000000,
+ 0x003, 0x00018c63,
+ 0x004, 0x00018c63,
+ 0x008, 0x00084000,
+ 0x00b, 0x0001c000,
+ 0x00e, 0x00018c67,
+ 0x00f, 0x00000851,
+ 0x014, 0x00021440,
+ 0x018, 0x00007401,
+ 0x019, 0x00000060,
+ 0x01d, 0x000a1290,
+ 0x023, 0x00001558,
+ 0x01a, 0x00030a99,
+ 0x01b, 0x00040b00,
+ 0x01c, 0x000fc339,
+ 0x03a, 0x000a57eb,
+ 0x03b, 0x00020000,
+ 0x03c, 0x000ff454,
+ 0x020, 0x0000aa52,
+ 0x021, 0x00054000,
+ 0x040, 0x0000aa52,
+ 0x041, 0x00014000,
+ 0x025, 0x000803be,
+ 0x026, 0x000fc638,
+ 0x027, 0x00077c18,
+ 0x028, 0x000d1c31,
+ 0x029, 0x000d7110,
+ 0x02a, 0x000aeb04,
+ 0x02b, 0x0004128b,
+ 0x02c, 0x00001840,
+ 0x043, 0x0002444f,
+ 0x044, 0x0001adb0,
+ 0x045, 0x00056467,
+ 0x046, 0x0008992c,
+ 0x047, 0x0000452c,
+ 0x048, 0x000f9c43,
+ 0x049, 0x00002e0c,
+ 0x04a, 0x000546eb,
+ 0x04b, 0x0008966c,
+ 0x04c, 0x0000dde9,
+ 0x018, 0x00007401,
+ 0x000, 0x00070000,
+ 0x012, 0x000dc000,
+ 0x012, 0x00090000,
+ 0x012, 0x00051000,
+ 0x012, 0x00012000,
+ 0x013, 0x000287b7,
+ 0x013, 0x000247ab,
+ 0x013, 0x0002079f,
+ 0x013, 0x0001c793,
+ 0x013, 0x0001839b,
+ 0x013, 0x00014392,
+ 0x013, 0x0001019a,
+ 0x013, 0x0000c191,
+ 0x013, 0x00008194,
+ 0x013, 0x000040a0,
+ 0x013, 0x00000018,
+ 0x015, 0x0000f424,
+ 0x015, 0x0004f424,
+ 0x015, 0x0008f424,
+ 0x016, 0x000e1330,
+ 0x016, 0x000a1330,
+ 0x016, 0x00061330,
+ 0x016, 0x00021330,
+ 0x018, 0x00017524,
+ 0x000, 0x00070000,
+ 0x012, 0x000cf000,
+ 0x012, 0x000bc000,
+ 0x012, 0x00078000,
+ 0x012, 0x00000000,
+ 0x013, 0x000287bc,
+ 0x013, 0x000247b0,
+ 0x013, 0x000203b4,
+ 0x013, 0x0001c3a8,
+ 0x013, 0x000181b4,
+ 0x013, 0x000141a8,
+ 0x013, 0x000100b0,
+ 0x013, 0x0000c0a4,
+ 0x013, 0x0000b02c,
+ 0x013, 0x00004020,
+ 0x013, 0x00000014,
+ 0x015, 0x0000f4c3,
+ 0x015, 0x0004f4c3,
+ 0x015, 0x0008f4c3,
+ 0x016, 0x000e085f,
+ 0x016, 0x000a085f,
+ 0x016, 0x0006085f,
+ 0x016, 0x0002085f,
+ 0x018, 0x00037524,
+ 0x000, 0x00070000,
+ 0x012, 0x000cf000,
+ 0x012, 0x000bc000,
+ 0x012, 0x00078000,
+ 0x012, 0x00000000,
+ 0x013, 0x000287bc,
+ 0x013, 0x000247b0,
+ 0x013, 0x000203b4,
+ 0x013, 0x0001c3a8,
+ 0x013, 0x000181b4,
+ 0x013, 0x000141a8,
+ 0x013, 0x000100b0,
+ 0x013, 0x0000c0a4,
+ 0x013, 0x0000b02c,
+ 0x013, 0x00004020,
+ 0x013, 0x00000014,
+ 0x015, 0x0000f4c3,
+ 0x015, 0x0004f4c3,
+ 0x015, 0x0008f4c3,
+ 0x016, 0x000e085f,
+ 0x016, 0x000a085f,
+ 0x016, 0x0006085f,
+ 0x016, 0x0002085f,
+ 0x018, 0x00057524,
+ 0x000, 0x00070000,
+ 0x012, 0x000cf000,
+ 0x012, 0x000bc000,
+ 0x012, 0x00078000,
+ 0x012, 0x00000000,
+ 0x013, 0x000287bc,
+ 0x013, 0x000247b0,
+ 0x013, 0x000203b4,
+ 0x013, 0x0001c3a8,
+ 0x013, 0x000181b4,
+ 0x013, 0x000141a8,
+ 0x013, 0x000100b0,
+ 0x013, 0x0000c0a4,
+ 0x013, 0x0000b02c,
+ 0x013, 0x00004020,
+ 0x013, 0x00000014,
+ 0x015, 0x0000f4c3,
+ 0x015, 0x0004f4c3,
+ 0x015, 0x0008f4c3,
+ 0x016, 0x000e085f,
+ 0x016, 0x000a085f,
+ 0x016, 0x0006085f,
+ 0x016, 0x0002085f,
+ 0x030, 0x0004470f,
+ 0x031, 0x00044ff0,
+ 0x032, 0x00000070,
+ 0x033, 0x000dd480,
+ 0x034, 0x000ffac0,
+ 0x035, 0x000b80c0,
+ 0x036, 0x00077000,
+ 0x037, 0x00064ff2,
+ 0x038, 0x000e7661,
+ 0x039, 0x00000e90,
+ 0x000, 0x00030000,
+ 0x018, 0x0000f401,
+ 0x0fe, 0x00000000,
+ 0x0fe, 0x00000000,
+ 0x01e, 0x00088009,
+ 0x01f, 0x00080003,
+ 0x0fe, 0x00000000,
+ 0x01e, 0x00088001,
+ 0x01f, 0x00080000,
+ 0x0fe, 0x00000000,
+ 0x018, 0x00087401,
+ 0x0fe, 0x00000000,
+ 0x0fe, 0x00000000,
+ 0x0fe, 0x00000000,
+ 0x02b, 0x00041289,
+ 0x0fe, 0x00000000,
+ 0x02d, 0x00066666,
+ 0x02e, 0x00064001,
+ 0x02d, 0x00091111,
+ 0x02e, 0x00014002,
+ 0x02d, 0x000bbbbb,
+ 0x02e, 0x000b4003,
+ 0x02d, 0x000e6666,
+ 0x02e, 0x00064004,
+ 0x02d, 0x00088888,
+ 0x02e, 0x00084005,
+ 0x02d, 0x0009dddd,
+ 0x02e, 0x000d4006,
+ 0x02d, 0x000b3333,
+ 0x02e, 0x00034007,
+ 0x02d, 0x00048888,
+ 0x02e, 0x00084408,
+ 0x02d, 0x000bbbbb,
+ 0x02e, 0x000b4409,
+ 0x02d, 0x000e6666,
+ 0x02e, 0x0006440a,
+ 0x02d, 0x00011111,
+ 0x02e, 0x0001480b,
+ 0x02d, 0x0003bbbb,
+ 0x02e, 0x000b480c,
+ 0x02d, 0x00066666,
+ 0x02e, 0x0006480d,
+ 0x02d, 0x000ccccc,
+ 0x02e, 0x000c480e,
+};
+
+u32 rtl8192de_radioa_2t_int_paarray[RADIOA_2T_INT_PA_ARRAYLENGTH] = {
+ 0x000, 0x00030000,
+ 0x001, 0x00030000,
+ 0x002, 0x00000000,
+ 0x003, 0x00018c63,
+ 0x004, 0x00018c63,
+ 0x008, 0x00084000,
+ 0x00b, 0x0001c000,
+ 0x00e, 0x00018c67,
+ 0x00f, 0x00000851,
+ 0x014, 0x00021440,
+ 0x018, 0x00017524,
+ 0x019, 0x00000000,
+ 0x01d, 0x000a1290,
+ 0x023, 0x00001558,
+ 0x01a, 0x00030a99,
+ 0x01b, 0x00040b00,
+ 0x01c, 0x000fc339,
+ 0x03a, 0x000a57eb,
+ 0x03b, 0x00020000,
+ 0x03c, 0x000ff454,
+ 0x020, 0x0000aa52,
+ 0x021, 0x00054000,
+ 0x040, 0x0000aa52,
+ 0x041, 0x00014000,
+ 0x025, 0x000803be,
+ 0x026, 0x000fc638,
+ 0x027, 0x00077c18,
+ 0x028, 0x000de471,
+ 0x029, 0x000d7110,
+ 0x02a, 0x0008eb04,
+ 0x02b, 0x0004128b,
+ 0x02c, 0x00001840,
+ 0x043, 0x0002444f,
+ 0x044, 0x0001adb0,
+ 0x045, 0x00056467,
+ 0x046, 0x0008992c,
+ 0x047, 0x0000452c,
+ 0x048, 0x000c0443,
+ 0x049, 0x00000730,
+ 0x04a, 0x00050f0f,
+ 0x04b, 0x000896ee,
+ 0x04c, 0x0000ddee,
+ 0x018, 0x00007401,
+ 0x000, 0x00070000,
+ 0x012, 0x000dc000,
+ 0x012, 0x00090000,
+ 0x012, 0x00051000,
+ 0x012, 0x00012000,
+ 0x013, 0x000287b7,
+ 0x013, 0x000247ab,
+ 0x013, 0x0002079f,
+ 0x013, 0x0001c793,
+ 0x013, 0x0001839b,
+ 0x013, 0x00014392,
+ 0x013, 0x0001019a,
+ 0x013, 0x0000c191,
+ 0x013, 0x00008194,
+ 0x013, 0x000040a0,
+ 0x013, 0x00000018,
+ 0x015, 0x0000f424,
+ 0x015, 0x0004f424,
+ 0x015, 0x0008f424,
+ 0x016, 0x000e1330,
+ 0x016, 0x000a1330,
+ 0x016, 0x00061330,
+ 0x016, 0x00021330,
+ 0x018, 0x00017524,
+ 0x000, 0x00070000,
+ 0x012, 0x000cf000,
+ 0x012, 0x000bc000,
+ 0x012, 0x00078000,
+ 0x012, 0x00000000,
+ 0x013, 0x000287bf,
+ 0x013, 0x000247b3,
+ 0x013, 0x000207a7,
+ 0x013, 0x0001c79b,
+ 0x013, 0x0001839f,
+ 0x013, 0x00014393,
+ 0x013, 0x00010399,
+ 0x013, 0x0000c38d,
+ 0x013, 0x00008199,
+ 0x013, 0x0000418d,
+ 0x013, 0x00000099,
+ 0x015, 0x0000f495,
+ 0x015, 0x0004f495,
+ 0x015, 0x0008f495,
+ 0x016, 0x000e1874,
+ 0x016, 0x000a1874,
+ 0x016, 0x00061874,
+ 0x016, 0x00021874,
+ 0x018, 0x00037564,
+ 0x000, 0x00070000,
+ 0x012, 0x000cf000,
+ 0x012, 0x000bc000,
+ 0x012, 0x00078000,
+ 0x012, 0x00000000,
+ 0x013, 0x000287bf,
+ 0x013, 0x000247b3,
+ 0x013, 0x000207a7,
+ 0x013, 0x0001c79b,
+ 0x013, 0x0001839f,
+ 0x013, 0x00014393,
+ 0x013, 0x00010399,
+ 0x013, 0x0000c38d,
+ 0x013, 0x00008199,
+ 0x013, 0x0000418d,
+ 0x013, 0x00000099,
+ 0x015, 0x0000f495,
+ 0x015, 0x0004f495,
+ 0x015, 0x0008f495,
+ 0x016, 0x000e1874,
+ 0x016, 0x000a1874,
+ 0x016, 0x00061874,
+ 0x016, 0x00021874,
+ 0x018, 0x00057595,
+ 0x000, 0x00070000,
+ 0x012, 0x000cf000,
+ 0x012, 0x000bc000,
+ 0x012, 0x00078000,
+ 0x012, 0x00000000,
+ 0x013, 0x000287bf,
+ 0x013, 0x000247b3,
+ 0x013, 0x000207a7,
+ 0x013, 0x0001c79b,
+ 0x013, 0x0001839f,
+ 0x013, 0x00014393,
+ 0x013, 0x00010399,
+ 0x013, 0x0000c38d,
+ 0x013, 0x00008199,
+ 0x013, 0x0000418d,
+ 0x013, 0x00000099,
+ 0x015, 0x0000f495,
+ 0x015, 0x0004f495,
+ 0x015, 0x0008f495,
+ 0x016, 0x000e1874,
+ 0x016, 0x000a1874,
+ 0x016, 0x00061874,
+ 0x016, 0x00021874,
+ 0x030, 0x0004470f,
+ 0x031, 0x00044ff0,
+ 0x032, 0x00000070,
+ 0x033, 0x000dd480,
+ 0x034, 0x000ffac0,
+ 0x035, 0x000b80c0,
+ 0x036, 0x00077000,
+ 0x037, 0x00064ff2,
+ 0x038, 0x000e7661,
+ 0x039, 0x00000e90,
+ 0x000, 0x00030000,
+ 0x018, 0x0000f401,
+ 0x0fe, 0x00000000,
+ 0x0fe, 0x00000000,
+ 0x01e, 0x00088009,
+ 0x01f, 0x00080003,
+ 0x0fe, 0x00000000,
+ 0x01e, 0x00088001,
+ 0x01f, 0x00080000,
+ 0x0fe, 0x00000000,
+ 0x018, 0x00097524,
+ 0x0fe, 0x00000000,
+ 0x0fe, 0x00000000,
+ 0x0fe, 0x00000000,
+ 0x0fe, 0x00000000,
+ 0x02b, 0x00041289,
+ 0x0fe, 0x00000000,
+ 0x02d, 0x0006aaaa,
+ 0x02e, 0x000b4d01,
+ 0x02d, 0x00080000,
+ 0x02e, 0x00004d02,
+ 0x02d, 0x00095555,
+ 0x02e, 0x00054d03,
+ 0x02d, 0x000aaaaa,
+ 0x02e, 0x000b4d04,
+ 0x02d, 0x000c0000,
+ 0x02e, 0x00004d05,
+ 0x02d, 0x000d5555,
+ 0x02e, 0x00054d06,
+ 0x02d, 0x000eaaaa,
+ 0x02e, 0x000b4d07,
+ 0x02d, 0x00000000,
+ 0x02e, 0x00005108,
+ 0x02d, 0x00015555,
+ 0x02e, 0x00055109,
+ 0x02d, 0x0002aaaa,
+ 0x02e, 0x000b510a,
+ 0x02d, 0x00040000,
+ 0x02e, 0x0000510b,
+ 0x02d, 0x00055555,
+ 0x02e, 0x0005510c,
+};
+
+u32 rtl8192de_radiob_2t_int_paarray[RADIOB_2T_INT_PA_ARRAYLENGTH] = {
+ 0x000, 0x00030000,
+ 0x001, 0x00030000,
+ 0x002, 0x00000000,
+ 0x003, 0x00018c63,
+ 0x004, 0x00018c63,
+ 0x008, 0x00084000,
+ 0x00b, 0x0001c000,
+ 0x00e, 0x00018c67,
+ 0x00f, 0x00000851,
+ 0x014, 0x00021440,
+ 0x018, 0x00007401,
+ 0x019, 0x00000060,
+ 0x01d, 0x000a1290,
+ 0x023, 0x00001558,
+ 0x01a, 0x00030a99,
+ 0x01b, 0x00040b00,
+ 0x01c, 0x000fc339,
+ 0x03a, 0x000a57eb,
+ 0x03b, 0x00020000,
+ 0x03c, 0x000ff454,
+ 0x020, 0x0000aa52,
+ 0x021, 0x00054000,
+ 0x040, 0x0000aa52,
+ 0x041, 0x00014000,
+ 0x025, 0x000803be,
+ 0x026, 0x000fc638,
+ 0x027, 0x00077c18,
+ 0x028, 0x000d1c31,
+ 0x029, 0x000d7110,
+ 0x02a, 0x000aeb04,
+ 0x02b, 0x0004128b,
+ 0x02c, 0x00001840,
+ 0x043, 0x0002444f,
+ 0x044, 0x0001adb0,
+ 0x045, 0x00056467,
+ 0x046, 0x0008992c,
+ 0x047, 0x0000452c,
+ 0x048, 0x000c0443,
+ 0x049, 0x00000730,
+ 0x04a, 0x00050f0f,
+ 0x04b, 0x000896ee,
+ 0x04c, 0x0000ddee,
+ 0x018, 0x00007401,
+ 0x000, 0x00070000,
+ 0x012, 0x000dc000,
+ 0x012, 0x00090000,
+ 0x012, 0x00051000,
+ 0x012, 0x00012000,
+ 0x013, 0x000287b7,
+ 0x013, 0x000247ab,
+ 0x013, 0x0002079f,
+ 0x013, 0x0001c793,
+ 0x013, 0x0001839b,
+ 0x013, 0x00014392,
+ 0x013, 0x0001019a,
+ 0x013, 0x0000c191,
+ 0x013, 0x00008194,
+ 0x013, 0x000040a0,
+ 0x013, 0x00000018,
+ 0x015, 0x0000f424,
+ 0x015, 0x0004f424,
+ 0x015, 0x0008f424,
+ 0x016, 0x000e1330,
+ 0x016, 0x000a1330,
+ 0x016, 0x00061330,
+ 0x016, 0x00021330,
+ 0x018, 0x00017524,
+ 0x000, 0x00070000,
+ 0x012, 0x000cf000,
+ 0x012, 0x000bc000,
+ 0x012, 0x00078000,
+ 0x012, 0x00000000,
+ 0x013, 0x000287bf,
+ 0x013, 0x000247b3,
+ 0x013, 0x000207a7,
+ 0x013, 0x0001c79b,
+ 0x013, 0x0001839f,
+ 0x013, 0x00014393,
+ 0x013, 0x00010399,
+ 0x013, 0x0000c38d,
+ 0x013, 0x00008199,
+ 0x013, 0x0000418d,
+ 0x013, 0x00000099,
+ 0x015, 0x0000f495,
+ 0x015, 0x0004f495,
+ 0x015, 0x0008f495,
+ 0x016, 0x000e1874,
+ 0x016, 0x000a1874,
+ 0x016, 0x00061874,
+ 0x016, 0x00021874,
+ 0x018, 0x00037564,
+ 0x000, 0x00070000,
+ 0x012, 0x000cf000,
+ 0x012, 0x000bc000,
+ 0x012, 0x00078000,
+ 0x012, 0x00000000,
+ 0x013, 0x000287bf,
+ 0x013, 0x000247b3,
+ 0x013, 0x000207a7,
+ 0x013, 0x0001c79b,
+ 0x013, 0x0001839f,
+ 0x013, 0x00014393,
+ 0x013, 0x00010399,
+ 0x013, 0x0000c38d,
+ 0x013, 0x00008199,
+ 0x013, 0x0000418d,
+ 0x013, 0x00000099,
+ 0x015, 0x0000f495,
+ 0x015, 0x0004f495,
+ 0x015, 0x0008f495,
+ 0x016, 0x000e1874,
+ 0x016, 0x000a1874,
+ 0x016, 0x00061874,
+ 0x016, 0x00021874,
+ 0x018, 0x00057595,
+ 0x000, 0x00070000,
+ 0x012, 0x000cf000,
+ 0x012, 0x000bc000,
+ 0x012, 0x00078000,
+ 0x012, 0x00000000,
+ 0x013, 0x000287bf,
+ 0x013, 0x000247b3,
+ 0x013, 0x000207a7,
+ 0x013, 0x0001c79b,
+ 0x013, 0x0001839f,
+ 0x013, 0x00014393,
+ 0x013, 0x00010399,
+ 0x013, 0x0000c38d,
+ 0x013, 0x00008199,
+ 0x013, 0x0000418d,
+ 0x013, 0x00000099,
+ 0x015, 0x0000f495,
+ 0x015, 0x0004f495,
+ 0x015, 0x0008f495,
+ 0x016, 0x000e1874,
+ 0x016, 0x000a1874,
+ 0x016, 0x00061874,
+ 0x016, 0x00021874,
+ 0x030, 0x0004470f,
+ 0x031, 0x00044ff0,
+ 0x032, 0x00000070,
+ 0x033, 0x000dd480,
+ 0x034, 0x000ffac0,
+ 0x035, 0x000b80c0,
+ 0x036, 0x00077000,
+ 0x037, 0x00064ff2,
+ 0x038, 0x000e7661,
+ 0x039, 0x00000e90,
+ 0x000, 0x00030000,
+ 0x018, 0x0000f401,
+ 0x0fe, 0x00000000,
+ 0x0fe, 0x00000000,
+ 0x01e, 0x00088009,
+ 0x01f, 0x00080003,
+ 0x0fe, 0x00000000,
+ 0x01e, 0x00088001,
+ 0x01f, 0x00080000,
+ 0x0fe, 0x00000000,
+ 0x018, 0x00087401,
+ 0x0fe, 0x00000000,
+ 0x0fe, 0x00000000,
+ 0x0fe, 0x00000000,
+ 0x02b, 0x00041289,
+ 0x0fe, 0x00000000,
+ 0x02d, 0x00066666,
+ 0x02e, 0x00064001,
+ 0x02d, 0x00091111,
+ 0x02e, 0x00014002,
+ 0x02d, 0x000bbbbb,
+ 0x02e, 0x000b4003,
+ 0x02d, 0x000e6666,
+ 0x02e, 0x00064004,
+ 0x02d, 0x00088888,
+ 0x02e, 0x00084005,
+ 0x02d, 0x0009dddd,
+ 0x02e, 0x000d4006,
+ 0x02d, 0x000b3333,
+ 0x02e, 0x00034007,
+ 0x02d, 0x00048888,
+ 0x02e, 0x00084408,
+ 0x02d, 0x000bbbbb,
+ 0x02e, 0x000b4409,
+ 0x02d, 0x000e6666,
+ 0x02e, 0x0006440a,
+ 0x02d, 0x00011111,
+ 0x02e, 0x0001480b,
+ 0x02d, 0x0003bbbb,
+ 0x02e, 0x000b480c,
+ 0x02d, 0x00066666,
+ 0x02e, 0x0006480d,
+ 0x02d, 0x000ccccc,
+ 0x02e, 0x000c480e,
+};
+
+u32 rtl8192de_mac_2tarray[MAC_2T_ARRAYLENGTH] = {
+ 0x420, 0x00000080,
+ 0x423, 0x00000000,
+ 0x430, 0x00000000,
+ 0x431, 0x00000000,
+ 0x432, 0x00000000,
+ 0x433, 0x00000001,
+ 0x434, 0x00000004,
+ 0x435, 0x00000005,
+ 0x436, 0x00000006,
+ 0x437, 0x00000007,
+ 0x438, 0x00000000,
+ 0x439, 0x00000000,
+ 0x43a, 0x00000000,
+ 0x43b, 0x00000001,
+ 0x43c, 0x00000004,
+ 0x43d, 0x00000005,
+ 0x43e, 0x00000006,
+ 0x43f, 0x00000007,
+ 0x440, 0x00000050,
+ 0x441, 0x00000001,
+ 0x442, 0x00000000,
+ 0x444, 0x00000015,
+ 0x445, 0x000000f0,
+ 0x446, 0x0000000f,
+ 0x447, 0x00000000,
+ 0x462, 0x00000008,
+ 0x463, 0x00000003,
+ 0x4c8, 0x000000ff,
+ 0x4c9, 0x00000008,
+ 0x4cc, 0x000000ff,
+ 0x4cd, 0x000000ff,
+ 0x4ce, 0x00000001,
+ 0x500, 0x00000026,
+ 0x501, 0x000000a2,
+ 0x502, 0x0000002f,
+ 0x503, 0x00000000,
+ 0x504, 0x00000028,
+ 0x505, 0x000000a3,
+ 0x506, 0x0000005e,
+ 0x507, 0x00000000,
+ 0x508, 0x0000002b,
+ 0x509, 0x000000a4,
+ 0x50a, 0x0000005e,
+ 0x50b, 0x00000000,
+ 0x50c, 0x0000004f,
+ 0x50d, 0x000000a4,
+ 0x50e, 0x00000000,
+ 0x50f, 0x00000000,
+ 0x512, 0x0000001c,
+ 0x514, 0x0000000a,
+ 0x515, 0x00000010,
+ 0x516, 0x0000000a,
+ 0x517, 0x00000010,
+ 0x51a, 0x00000016,
+ 0x524, 0x0000000f,
+ 0x525, 0x0000004f,
+ 0x546, 0x00000040,
+ 0x547, 0x00000000,
+ 0x550, 0x00000010,
+ 0x551, 0x00000010,
+ 0x559, 0x00000002,
+ 0x55a, 0x00000002,
+ 0x55d, 0x000000ff,
+ 0x605, 0x00000030,
+ 0x608, 0x0000000e,
+ 0x609, 0x0000002a,
+ 0x652, 0x00000020,
+ 0x63c, 0x0000000a,
+ 0x63d, 0x0000000a,
+ 0x63e, 0x0000000e,
+ 0x63f, 0x0000000e,
+ 0x66e, 0x00000005,
+ 0x700, 0x00000021,
+ 0x701, 0x00000043,
+ 0x702, 0x00000065,
+ 0x703, 0x00000087,
+ 0x708, 0x00000021,
+ 0x709, 0x00000043,
+ 0x70a, 0x00000065,
+ 0x70b, 0x00000087,
+};
+
+u32 rtl8192de_agctab_array[AGCTAB_ARRAYLENGTH] = {
+ 0xc78, 0x7b000001,
+ 0xc78, 0x7b010001,
+ 0xc78, 0x7b020001,
+ 0xc78, 0x7b030001,
+ 0xc78, 0x7b040001,
+ 0xc78, 0x7b050001,
+ 0xc78, 0x7b060001,
+ 0xc78, 0x7a070001,
+ 0xc78, 0x79080001,
+ 0xc78, 0x78090001,
+ 0xc78, 0x770a0001,
+ 0xc78, 0x760b0001,
+ 0xc78, 0x750c0001,
+ 0xc78, 0x740d0001,
+ 0xc78, 0x730e0001,
+ 0xc78, 0x720f0001,
+ 0xc78, 0x71100001,
+ 0xc78, 0x70110001,
+ 0xc78, 0x6f120001,
+ 0xc78, 0x6e130001,
+ 0xc78, 0x6d140001,
+ 0xc78, 0x6c150001,
+ 0xc78, 0x6b160001,
+ 0xc78, 0x6a170001,
+ 0xc78, 0x69180001,
+ 0xc78, 0x68190001,
+ 0xc78, 0x671a0001,
+ 0xc78, 0x661b0001,
+ 0xc78, 0x651c0001,
+ 0xc78, 0x641d0001,
+ 0xc78, 0x631e0001,
+ 0xc78, 0x621f0001,
+ 0xc78, 0x61200001,
+ 0xc78, 0x60210001,
+ 0xc78, 0x49220001,
+ 0xc78, 0x48230001,
+ 0xc78, 0x47240001,
+ 0xc78, 0x46250001,
+ 0xc78, 0x45260001,
+ 0xc78, 0x44270001,
+ 0xc78, 0x43280001,
+ 0xc78, 0x42290001,
+ 0xc78, 0x412a0001,
+ 0xc78, 0x402b0001,
+ 0xc78, 0x262c0001,
+ 0xc78, 0x252d0001,
+ 0xc78, 0x242e0001,
+ 0xc78, 0x232f0001,
+ 0xc78, 0x22300001,
+ 0xc78, 0x21310001,
+ 0xc78, 0x20320001,
+ 0xc78, 0x06330001,
+ 0xc78, 0x05340001,
+ 0xc78, 0x04350001,
+ 0xc78, 0x03360001,
+ 0xc78, 0x02370001,
+ 0xc78, 0x01380001,
+ 0xc78, 0x00390001,
+ 0xc78, 0x003a0001,
+ 0xc78, 0x003b0001,
+ 0xc78, 0x003c0001,
+ 0xc78, 0x003d0001,
+ 0xc78, 0x003e0001,
+ 0xc78, 0x003f0001,
+ 0xc78, 0x7b400001,
+ 0xc78, 0x7b410001,
+ 0xc78, 0x7a420001,
+ 0xc78, 0x79430001,
+ 0xc78, 0x78440001,
+ 0xc78, 0x77450001,
+ 0xc78, 0x76460001,
+ 0xc78, 0x75470001,
+ 0xc78, 0x74480001,
+ 0xc78, 0x73490001,
+ 0xc78, 0x724a0001,
+ 0xc78, 0x714b0001,
+ 0xc78, 0x704c0001,
+ 0xc78, 0x6f4d0001,
+ 0xc78, 0x6e4e0001,
+ 0xc78, 0x6d4f0001,
+ 0xc78, 0x6c500001,
+ 0xc78, 0x6b510001,
+ 0xc78, 0x6a520001,
+ 0xc78, 0x69530001,
+ 0xc78, 0x68540001,
+ 0xc78, 0x67550001,
+ 0xc78, 0x66560001,
+ 0xc78, 0x65570001,
+ 0xc78, 0x64580001,
+ 0xc78, 0x63590001,
+ 0xc78, 0x625a0001,
+ 0xc78, 0x615b0001,
+ 0xc78, 0x605c0001,
+ 0xc78, 0x485d0001,
+ 0xc78, 0x475e0001,
+ 0xc78, 0x465f0001,
+ 0xc78, 0x45600001,
+ 0xc78, 0x44610001,
+ 0xc78, 0x43620001,
+ 0xc78, 0x42630001,
+ 0xc78, 0x41640001,
+ 0xc78, 0x40650001,
+ 0xc78, 0x27660001,
+ 0xc78, 0x26670001,
+ 0xc78, 0x25680001,
+ 0xc78, 0x24690001,
+ 0xc78, 0x236a0001,
+ 0xc78, 0x226b0001,
+ 0xc78, 0x216c0001,
+ 0xc78, 0x206d0001,
+ 0xc78, 0x206e0001,
+ 0xc78, 0x206f0001,
+ 0xc78, 0x20700001,
+ 0xc78, 0x20710001,
+ 0xc78, 0x20720001,
+ 0xc78, 0x20730001,
+ 0xc78, 0x20740001,
+ 0xc78, 0x20750001,
+ 0xc78, 0x20760001,
+ 0xc78, 0x20770001,
+ 0xc78, 0x20780001,
+ 0xc78, 0x20790001,
+ 0xc78, 0x207a0001,
+ 0xc78, 0x207b0001,
+ 0xc78, 0x207c0001,
+ 0xc78, 0x207d0001,
+ 0xc78, 0x207e0001,
+ 0xc78, 0x207f0001,
+ 0xc78, 0x38000002,
+ 0xc78, 0x38010002,
+ 0xc78, 0x38020002,
+ 0xc78, 0x38030002,
+ 0xc78, 0x38040002,
+ 0xc78, 0x38050002,
+ 0xc78, 0x38060002,
+ 0xc78, 0x38070002,
+ 0xc78, 0x38080002,
+ 0xc78, 0x3c090002,
+ 0xc78, 0x3e0a0002,
+ 0xc78, 0x400b0002,
+ 0xc78, 0x440c0002,
+ 0xc78, 0x480d0002,
+ 0xc78, 0x4c0e0002,
+ 0xc78, 0x500f0002,
+ 0xc78, 0x52100002,
+ 0xc78, 0x56110002,
+ 0xc78, 0x5a120002,
+ 0xc78, 0x5e130002,
+ 0xc78, 0x60140002,
+ 0xc78, 0x60150002,
+ 0xc78, 0x60160002,
+ 0xc78, 0x62170002,
+ 0xc78, 0x62180002,
+ 0xc78, 0x62190002,
+ 0xc78, 0x621a0002,
+ 0xc78, 0x621b0002,
+ 0xc78, 0x621c0002,
+ 0xc78, 0x621d0002,
+ 0xc78, 0x621e0002,
+ 0xc78, 0x621f0002,
+ 0xc78, 0x32000044,
+ 0xc78, 0x32010044,
+ 0xc78, 0x32020044,
+ 0xc78, 0x32030044,
+ 0xc78, 0x32040044,
+ 0xc78, 0x32050044,
+ 0xc78, 0x32060044,
+ 0xc78, 0x32070044,
+ 0xc78, 0x32080044,
+ 0xc78, 0x34090044,
+ 0xc78, 0x350a0044,
+ 0xc78, 0x360b0044,
+ 0xc78, 0x370c0044,
+ 0xc78, 0x380d0044,
+ 0xc78, 0x390e0044,
+ 0xc78, 0x3a0f0044,
+ 0xc78, 0x3e100044,
+ 0xc78, 0x42110044,
+ 0xc78, 0x44120044,
+ 0xc78, 0x46130044,
+ 0xc78, 0x4a140044,
+ 0xc78, 0x4e150044,
+ 0xc78, 0x50160044,
+ 0xc78, 0x55170044,
+ 0xc78, 0x5a180044,
+ 0xc78, 0x5e190044,
+ 0xc78, 0x641a0044,
+ 0xc78, 0x6e1b0044,
+ 0xc78, 0x6e1c0044,
+ 0xc78, 0x6e1d0044,
+ 0xc78, 0x6e1e0044,
+ 0xc78, 0x6e1f0044,
+ 0xc78, 0x6e1f0000,
+};
+
+u32 rtl8192de_agctab_5garray[AGCTAB_5G_ARRAYLENGTH] = {
+ 0xc78, 0x7b000001,
+ 0xc78, 0x7b010001,
+ 0xc78, 0x7a020001,
+ 0xc78, 0x79030001,
+ 0xc78, 0x78040001,
+ 0xc78, 0x77050001,
+ 0xc78, 0x76060001,
+ 0xc78, 0x75070001,
+ 0xc78, 0x74080001,
+ 0xc78, 0x73090001,
+ 0xc78, 0x720a0001,
+ 0xc78, 0x710b0001,
+ 0xc78, 0x700c0001,
+ 0xc78, 0x6f0d0001,
+ 0xc78, 0x6e0e0001,
+ 0xc78, 0x6d0f0001,
+ 0xc78, 0x6c100001,
+ 0xc78, 0x6b110001,
+ 0xc78, 0x6a120001,
+ 0xc78, 0x69130001,
+ 0xc78, 0x68140001,
+ 0xc78, 0x67150001,
+ 0xc78, 0x66160001,
+ 0xc78, 0x65170001,
+ 0xc78, 0x64180001,
+ 0xc78, 0x63190001,
+ 0xc78, 0x621a0001,
+ 0xc78, 0x611b0001,
+ 0xc78, 0x601c0001,
+ 0xc78, 0x481d0001,
+ 0xc78, 0x471e0001,
+ 0xc78, 0x461f0001,
+ 0xc78, 0x45200001,
+ 0xc78, 0x44210001,
+ 0xc78, 0x43220001,
+ 0xc78, 0x42230001,
+ 0xc78, 0x41240001,
+ 0xc78, 0x40250001,
+ 0xc78, 0x27260001,
+ 0xc78, 0x26270001,
+ 0xc78, 0x25280001,
+ 0xc78, 0x24290001,
+ 0xc78, 0x232a0001,
+ 0xc78, 0x222b0001,
+ 0xc78, 0x212c0001,
+ 0xc78, 0x202d0001,
+ 0xc78, 0x202e0001,
+ 0xc78, 0x202f0001,
+ 0xc78, 0x20300001,
+ 0xc78, 0x20310001,
+ 0xc78, 0x20320001,
+ 0xc78, 0x20330001,
+ 0xc78, 0x20340001,
+ 0xc78, 0x20350001,
+ 0xc78, 0x20360001,
+ 0xc78, 0x20370001,
+ 0xc78, 0x20380001,
+ 0xc78, 0x20390001,
+ 0xc78, 0x203a0001,
+ 0xc78, 0x203b0001,
+ 0xc78, 0x203c0001,
+ 0xc78, 0x203d0001,
+ 0xc78, 0x203e0001,
+ 0xc78, 0x203f0001,
+ 0xc78, 0x32000044,
+ 0xc78, 0x32010044,
+ 0xc78, 0x32020044,
+ 0xc78, 0x32030044,
+ 0xc78, 0x32040044,
+ 0xc78, 0x32050044,
+ 0xc78, 0x32060044,
+ 0xc78, 0x32070044,
+ 0xc78, 0x32080044,
+ 0xc78, 0x34090044,
+ 0xc78, 0x350a0044,
+ 0xc78, 0x360b0044,
+ 0xc78, 0x370c0044,
+ 0xc78, 0x380d0044,
+ 0xc78, 0x390e0044,
+ 0xc78, 0x3a0f0044,
+ 0xc78, 0x3e100044,
+ 0xc78, 0x42110044,
+ 0xc78, 0x44120044,
+ 0xc78, 0x46130044,
+ 0xc78, 0x4a140044,
+ 0xc78, 0x4e150044,
+ 0xc78, 0x50160044,
+ 0xc78, 0x55170044,
+ 0xc78, 0x5a180044,
+ 0xc78, 0x5e190044,
+ 0xc78, 0x641a0044,
+ 0xc78, 0x6e1b0044,
+ 0xc78, 0x6e1c0044,
+ 0xc78, 0x6e1d0044,
+ 0xc78, 0x6e1e0044,
+ 0xc78, 0x6e1f0044,
+ 0xc78, 0x6e1f0000,
+};
+
+u32 rtl8192de_agctab_2garray[AGCTAB_2G_ARRAYLENGTH] = {
+ 0xc78, 0x7b000001,
+ 0xc78, 0x7b010001,
+ 0xc78, 0x7b020001,
+ 0xc78, 0x7b030001,
+ 0xc78, 0x7b040001,
+ 0xc78, 0x7b050001,
+ 0xc78, 0x7b060001,
+ 0xc78, 0x7a070001,
+ 0xc78, 0x79080001,
+ 0xc78, 0x78090001,
+ 0xc78, 0x770a0001,
+ 0xc78, 0x760b0001,
+ 0xc78, 0x750c0001,
+ 0xc78, 0x740d0001,
+ 0xc78, 0x730e0001,
+ 0xc78, 0x720f0001,
+ 0xc78, 0x71100001,
+ 0xc78, 0x70110001,
+ 0xc78, 0x6f120001,
+ 0xc78, 0x6e130001,
+ 0xc78, 0x6d140001,
+ 0xc78, 0x6c150001,
+ 0xc78, 0x6b160001,
+ 0xc78, 0x6a170001,
+ 0xc78, 0x69180001,
+ 0xc78, 0x68190001,
+ 0xc78, 0x671a0001,
+ 0xc78, 0x661b0001,
+ 0xc78, 0x651c0001,
+ 0xc78, 0x641d0001,
+ 0xc78, 0x631e0001,
+ 0xc78, 0x621f0001,
+ 0xc78, 0x61200001,
+ 0xc78, 0x60210001,
+ 0xc78, 0x49220001,
+ 0xc78, 0x48230001,
+ 0xc78, 0x47240001,
+ 0xc78, 0x46250001,
+ 0xc78, 0x45260001,
+ 0xc78, 0x44270001,
+ 0xc78, 0x43280001,
+ 0xc78, 0x42290001,
+ 0xc78, 0x412a0001,
+ 0xc78, 0x402b0001,
+ 0xc78, 0x262c0001,
+ 0xc78, 0x252d0001,
+ 0xc78, 0x242e0001,
+ 0xc78, 0x232f0001,
+ 0xc78, 0x22300001,
+ 0xc78, 0x21310001,
+ 0xc78, 0x20320001,
+ 0xc78, 0x06330001,
+ 0xc78, 0x05340001,
+ 0xc78, 0x04350001,
+ 0xc78, 0x03360001,
+ 0xc78, 0x02370001,
+ 0xc78, 0x01380001,
+ 0xc78, 0x00390001,
+ 0xc78, 0x003a0001,
+ 0xc78, 0x003b0001,
+ 0xc78, 0x003c0001,
+ 0xc78, 0x003d0001,
+ 0xc78, 0x003e0001,
+ 0xc78, 0x003f0001,
+ 0xc78, 0x38000002,
+ 0xc78, 0x38010002,
+ 0xc78, 0x38020002,
+ 0xc78, 0x38030002,
+ 0xc78, 0x38040002,
+ 0xc78, 0x38050002,
+ 0xc78, 0x38060002,
+ 0xc78, 0x38070002,
+ 0xc78, 0x38080002,
+ 0xc78, 0x3c090002,
+ 0xc78, 0x3e0a0002,
+ 0xc78, 0x400b0002,
+ 0xc78, 0x440c0002,
+ 0xc78, 0x480d0002,
+ 0xc78, 0x4c0e0002,
+ 0xc78, 0x500f0002,
+ 0xc78, 0x52100002,
+ 0xc78, 0x56110002,
+ 0xc78, 0x5a120002,
+ 0xc78, 0x5e130002,
+ 0xc78, 0x60140002,
+ 0xc78, 0x60150002,
+ 0xc78, 0x60160002,
+ 0xc78, 0x62170002,
+ 0xc78, 0x62180002,
+ 0xc78, 0x62190002,
+ 0xc78, 0x621a0002,
+ 0xc78, 0x621b0002,
+ 0xc78, 0x621c0002,
+ 0xc78, 0x621d0002,
+ 0xc78, 0x621e0002,
+ 0xc78, 0x621f0002,
+ 0xc78, 0x6e1f0000,
+};
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/table.h b/drivers/net/wireless/rtlwifi/rtl8192de/table.h
new file mode 100644
index 0000000..93f30ca
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8192de/table.h
@@ -0,0 +1,57 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010 Realtek Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License 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, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ * Created on 2010/ 5/18, 1:41
+ *****************************************************************************/
+
+#ifndef __RTL92DE_TABLE__H_
+#define __RTL92DE_TABLE__H_
+
+/*Created on 2011/ 1/14, 1:35*/
+
+#define PHY_REG_2T_ARRAYLENGTH 380
+extern u32 rtl8192de_phy_reg_2tarray[PHY_REG_2T_ARRAYLENGTH];
+#define PHY_REG_ARRAY_PG_LENGTH 624
+extern u32 rtl8192de_phy_reg_array_pg[PHY_REG_ARRAY_PG_LENGTH];
+#define RADIOA_2T_ARRAYLENGTH 378
+extern u32 rtl8192de_radioa_2tarray[RADIOA_2T_ARRAYLENGTH];
+#define RADIOB_2T_ARRAYLENGTH 384
+extern u32 rtl8192de_radiob_2tarray[RADIOB_2T_ARRAYLENGTH];
+#define RADIOA_2T_INT_PA_ARRAYLENGTH 378
+extern u32 rtl8192de_radioa_2t_int_paarray[RADIOA_2T_INT_PA_ARRAYLENGTH];
+#define RADIOB_2T_INT_PA_ARRAYLENGTH 384
+extern u32 rtl8192de_radiob_2t_int_paarray[RADIOB_2T_INT_PA_ARRAYLENGTH];
+#define MAC_2T_ARRAYLENGTH 160
+extern u32 rtl8192de_mac_2tarray[MAC_2T_ARRAYLENGTH];
+#define AGCTAB_ARRAYLENGTH 386
+extern u32 rtl8192de_agctab_array[AGCTAB_ARRAYLENGTH];
+#define AGCTAB_5G_ARRAYLENGTH 194
+extern u32 rtl8192de_agctab_5garray[AGCTAB_5G_ARRAYLENGTH];
+#define AGCTAB_2G_ARRAYLENGTH 194
+extern u32 rtl8192de_agctab_2garray[AGCTAB_2G_ARRAYLENGTH];
+
+#endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/trx.c b/drivers/net/wireless/rtlwifi/rtl8192de/trx.c
new file mode 100644
index 0000000..bf1462f
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8192de/trx.c
@@ -0,0 +1,959 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010 Realtek Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License 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, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#include "../wifi.h"
+#include "../pci.h"
+#include "../base.h"
+#include "reg.h"
+#include "def.h"
+#include "phy.h"
+#include "trx.h"
+#include "led.h"
+
+static u8 _rtl92de_map_hwqueue_to_fwqueue(struct sk_buff *skb, u8 hw_queue)
+{
+ __le16 fc = rtl_get_fc(skb);
+
+ if (unlikely(ieee80211_is_beacon(fc)))
+ return QSLT_BEACON;
+ if (ieee80211_is_mgmt(fc))
+ return QSLT_MGNT;
+
+ return skb->priority;
+}
+
+static int _rtl92de_rate_mapping(bool isht, u8 desc_rate)
+{
+ int rate_idx;
+
+ if (false == isht) {
+ switch (desc_rate) {
+ case DESC92D_RATE1M:
+ rate_idx = 0;
+ break;
+ case DESC92D_RATE2M:
+ rate_idx = 1;
+ break;
+ case DESC92D_RATE5_5M:
+ rate_idx = 2;
+ break;
+ case DESC92D_RATE11M:
+ rate_idx = 3;
+ break;
+ case DESC92D_RATE6M:
+ rate_idx = 4;
+ break;
+ case DESC92D_RATE9M:
+ rate_idx = 5;
+ break;
+ case DESC92D_RATE12M:
+ rate_idx = 6;
+ break;
+ case DESC92D_RATE18M:
+ rate_idx = 7;
+ break;
+ case DESC92D_RATE24M:
+ rate_idx = 8;
+ break;
+ case DESC92D_RATE36M:
+ rate_idx = 9;
+ break;
+ case DESC92D_RATE48M:
+ rate_idx = 10;
+ break;
+ case DESC92D_RATE54M:
+ rate_idx = 11;
+ break;
+ default:
+ rate_idx = 0;
+ break;
+ }
+ return rate_idx;
+ } else {
+ switch (desc_rate) {
+ case DESC92D_RATE1M:
+ rate_idx = 0;
+ break;
+ case DESC92D_RATE2M:
+ rate_idx = 1;
+ break;
+ case DESC92D_RATE5_5M:
+ rate_idx = 2;
+ break;
+ case DESC92D_RATE11M:
+ rate_idx = 3;
+ break;
+ case DESC92D_RATE6M:
+ rate_idx = 4;
+ break;
+ case DESC92D_RATE9M:
+ rate_idx = 5;
+ break;
+ case DESC92D_RATE12M:
+ rate_idx = 6;
+ break;
+ case DESC92D_RATE18M:
+ rate_idx = 7;
+ break;
+ case DESC92D_RATE24M:
+ rate_idx = 8;
+ break;
+ case DESC92D_RATE36M:
+ rate_idx = 9;
+ break;
+ case DESC92D_RATE48M:
+ rate_idx = 10;
+ break;
+ case DESC92D_RATE54M:
+ rate_idx = 11;
+ break;
+ default:
+ rate_idx = 11;
+ break;
+ }
+ return rate_idx;
+ }
+}
+
+static u8 _rtl92d_query_rxpwrpercentage(char antpower)
+{
+ if ((antpower <= -100) || (antpower >= 20))
+ return 0;
+ else if (antpower >= 0)
+ return 100;
+ else
+ return 100 + antpower;
+}
+
+static u8 _rtl92d_evm_db_to_percentage(char value)
+{
+ char ret_val = value;
+
+ if (ret_val >= 0)
+ ret_val = 0;
+ if (ret_val <= -33)
+ ret_val = -33;
+ ret_val = 0 - ret_val;
+ ret_val *= 3;
+ if (ret_val == 99)
+ ret_val = 100;
+ return ret_val;
+}
+
+static long _rtl92de_translate_todbm(struct ieee80211_hw *hw,
+ u8 signal_strength_index)
+{
+ long signal_power;
+
+ signal_power = (long)((signal_strength_index + 1) >> 1);
+ signal_power -= 95;
+ return signal_power;
+}
+
+static long _rtl92de_signal_scale_mapping(struct ieee80211_hw *hw, long currsig)
+{
+ long retsig;
+
+ if (currsig >= 61 && currsig <= 100)
+ retsig = 90 + ((currsig - 60) / 4);
+ else if (currsig >= 41 && currsig <= 60)
+ retsig = 78 + ((currsig - 40) / 2);
+ else if (currsig >= 31 && currsig <= 40)
+ retsig = 66 + (currsig - 30);
+ else if (currsig >= 21 && currsig <= 30)
+ retsig = 54 + (currsig - 20);
+ else if (currsig >= 5 && currsig <= 20)
+ retsig = 42 + (((currsig - 5) * 2) / 3);
+ else if (currsig == 4)
+ retsig = 36;
+ else if (currsig == 3)
+ retsig = 27;
+ else if (currsig == 2)
+ retsig = 18;
+ else if (currsig == 1)
+ retsig = 9;
+ else
+ retsig = currsig;
+ return retsig;
+}
+
+static void _rtl92de_query_rxphystatus(struct ieee80211_hw *hw,
+ struct rtl_stats *pstats,
+ struct rx_desc_92d *pdesc,
+ struct rx_fwinfo_92d *p_drvinfo,
+ bool packet_match_bssid,
+ bool packet_toself,
+ bool packet_beacon)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_ps_ctl *ppsc = rtl_psc(rtlpriv);
+ struct phy_sts_cck_8192d *cck_buf;
+ s8 rx_pwr_all, rx_pwr[4];
+ u8 rf_rx_num = 0, evm, pwdb_all;
+ u8 i, max_spatial_stream;
+ u32 rssi, total_rssi = 0;
+ bool is_cck_rate;
+
+ is_cck_rate = RX_HAL_IS_CCK_RATE(pdesc);
+ pstats->packet_matchbssid = packet_match_bssid;
+ pstats->packet_toself = packet_toself;
+ pstats->packet_beacon = packet_beacon;
+ pstats->is_cck = is_cck_rate;
+ pstats->rx_mimo_signalquality[0] = -1;
+ pstats->rx_mimo_signalquality[1] = -1;
+
+ if (is_cck_rate) {
+ u8 report, cck_highpwr;
+ cck_buf = (struct phy_sts_cck_8192d *)p_drvinfo;
+ if (ppsc->rfpwr_state == ERFON)
+ cck_highpwr = (u8) rtl_get_bbreg(hw,
+ RFPGA0_XA_HSSIPARAMETER2,
+ BIT(9));
+ else
+ cck_highpwr = false;
+ if (!cck_highpwr) {
+ u8 cck_agc_rpt = cck_buf->cck_agc_rpt;
+ report = cck_buf->cck_agc_rpt & 0xc0;
+ report = report >> 6;
+ switch (report) {
+ case 0x3:
+ rx_pwr_all = -46 - (cck_agc_rpt & 0x3e);
+ break;
+ case 0x2:
+ rx_pwr_all = -26 - (cck_agc_rpt & 0x3e);
+ break;
+ case 0x1:
+ rx_pwr_all = -12 - (cck_agc_rpt & 0x3e);
+ break;
+ case 0x0:
+ rx_pwr_all = 16 - (cck_agc_rpt & 0x3e);
+ break;
+ }
+ } else {
+ u8 cck_agc_rpt = cck_buf->cck_agc_rpt;
+ report = p_drvinfo->cfosho[0] & 0x60;
+ report = report >> 5;
+ switch (report) {
+ case 0x3:
+ rx_pwr_all = -46 - ((cck_agc_rpt & 0x1f) << 1);
+ break;
+ case 0x2:
+ rx_pwr_all = -26 - ((cck_agc_rpt & 0x1f) << 1);
+ break;
+ case 0x1:
+ rx_pwr_all = -12 - ((cck_agc_rpt & 0x1f) << 1);
+ break;
+ case 0x0:
+ rx_pwr_all = 16 - ((cck_agc_rpt & 0x1f) << 1);
+ break;
+ }
+ }
+ pwdb_all = _rtl92d_query_rxpwrpercentage(rx_pwr_all);
+ /* CCK gain is smaller than OFDM/MCS gain, */
+ /* so we add gain diff by experiences, the val is 6 */
+ pwdb_all += 6;
+ if (pwdb_all > 100)
+ pwdb_all = 100;
+ /* modify the offset to make the same gain index with OFDM. */
+ if (pwdb_all > 34 && pwdb_all <= 42)
+ pwdb_all -= 2;
+ else if (pwdb_all > 26 && pwdb_all <= 34)
+ pwdb_all -= 6;
+ else if (pwdb_all > 14 && pwdb_all <= 26)
+ pwdb_all -= 8;
+ else if (pwdb_all > 4 && pwdb_all <= 14)
+ pwdb_all -= 4;
+ pstats->rx_pwdb_all = pwdb_all;
+ pstats->recvsignalpower = rx_pwr_all;
+ if (packet_match_bssid) {
+ u8 sq;
+ if (pstats->rx_pwdb_all > 40) {
+ sq = 100;
+ } else {
+ sq = cck_buf->sq_rpt;
+ if (sq > 64)
+ sq = 0;
+ else if (sq < 20)
+ sq = 100;
+ else
+ sq = ((64 - sq) * 100) / 44;
+ }
+ pstats->signalquality = sq;
+ pstats->rx_mimo_signalquality[0] = sq;
+ pstats->rx_mimo_signalquality[1] = -1;
+ }
+ } else {
+ rtlpriv->dm.rfpath_rxenable[0] = true;
+ rtlpriv->dm.rfpath_rxenable[1] = true;
+ for (i = RF90_PATH_A; i < RF6052_MAX_PATH; i++) {
+ if (rtlpriv->dm.rfpath_rxenable[i])
+ rf_rx_num++;
+ rx_pwr[i] = ((p_drvinfo->gain_trsw[i] & 0x3f) * 2)
+ - 110;
+ rssi = _rtl92d_query_rxpwrpercentage(rx_pwr[i]);
+ total_rssi += rssi;
+ rtlpriv->stats.rx_snr_db[i] =
+ (long)(p_drvinfo->rxsnr[i] / 2);
+ if (packet_match_bssid)
+ pstats->rx_mimo_signalstrength[i] = (u8) rssi;
+ }
+ rx_pwr_all = ((p_drvinfo->pwdb_all >> 1) & 0x7f) - 106;
+ pwdb_all = _rtl92d_query_rxpwrpercentage(rx_pwr_all);
+ pstats->rx_pwdb_all = pwdb_all;
+ pstats->rxpower = rx_pwr_all;
+ pstats->recvsignalpower = rx_pwr_all;
+ if (pdesc->rxht && pdesc->rxmcs >= DESC92D_RATEMCS8 &&
+ pdesc->rxmcs <= DESC92D_RATEMCS15)
+ max_spatial_stream = 2;
+ else
+ max_spatial_stream = 1;
+ for (i = 0; i < max_spatial_stream; i++) {
+ evm = _rtl92d_evm_db_to_percentage(p_drvinfo->rxevm[i]);
+ if (packet_match_bssid) {
+ if (i == 0)
+ pstats->signalquality =
+ (u8)(evm & 0xff);
+ pstats->rx_mimo_signalquality[i] =
+ (u8)(evm & 0xff);
+ }
+ }
+ }
+ if (is_cck_rate)
+ pstats->signalstrength = (u8)(_rtl92de_signal_scale_mapping(hw,
+ pwdb_all));
+ else if (rf_rx_num != 0)
+ pstats->signalstrength = (u8)(_rtl92de_signal_scale_mapping(hw,
+ total_rssi /= rf_rx_num));
+}
+
+static void rtl92d_loop_over_paths(struct ieee80211_hw *hw,
+ struct rtl_stats *pstats)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ u8 rfpath;
+
+ for (rfpath = RF90_PATH_A; rfpath < rtlphy->num_total_rfpath;
+ rfpath++) {
+ if (rtlpriv->stats.rx_rssi_percentage[rfpath] == 0) {
+ rtlpriv->stats.rx_rssi_percentage[rfpath] =
+ pstats->rx_mimo_signalstrength[rfpath];
+
+ }
+ if (pstats->rx_mimo_signalstrength[rfpath] >
+ rtlpriv->stats.rx_rssi_percentage[rfpath]) {
+ rtlpriv->stats.rx_rssi_percentage[rfpath] =
+ ((rtlpriv->stats.rx_rssi_percentage[rfpath] *
+ (RX_SMOOTH_FACTOR - 1)) +
+ (pstats->rx_mimo_signalstrength[rfpath])) /
+ (RX_SMOOTH_FACTOR);
+ rtlpriv->stats.rx_rssi_percentage[rfpath] =
+ rtlpriv->stats.rx_rssi_percentage[rfpath] + 1;
+ } else {
+ rtlpriv->stats.rx_rssi_percentage[rfpath] =
+ ((rtlpriv->stats.rx_rssi_percentage[rfpath] *
+ (RX_SMOOTH_FACTOR - 1)) +
+ (pstats->rx_mimo_signalstrength[rfpath])) /
+ (RX_SMOOTH_FACTOR);
+ }
+ }
+}
+
+static void _rtl92de_process_ui_rssi(struct ieee80211_hw *hw,
+ struct rtl_stats *pstats)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u32 last_rssi, tmpval;
+
+ if (pstats->packet_toself || pstats->packet_beacon) {
+ rtlpriv->stats.rssi_calculate_cnt++;
+ if (rtlpriv->stats.ui_rssi.total_num++ >=
+ PHY_RSSI_SLID_WIN_MAX) {
+ rtlpriv->stats.ui_rssi.total_num =
+ PHY_RSSI_SLID_WIN_MAX;
+ last_rssi = rtlpriv->stats.ui_rssi.elements[
+ rtlpriv->stats.ui_rssi.index];
+ rtlpriv->stats.ui_rssi.total_val -= last_rssi;
+ }
+ rtlpriv->stats.ui_rssi.total_val += pstats->signalstrength;
+ rtlpriv->stats.ui_rssi.elements
+ [rtlpriv->stats.ui_rssi.index++] =
+ pstats->signalstrength;
+ if (rtlpriv->stats.ui_rssi.index >= PHY_RSSI_SLID_WIN_MAX)
+ rtlpriv->stats.ui_rssi.index = 0;
+ tmpval = rtlpriv->stats.ui_rssi.total_val /
+ rtlpriv->stats.ui_rssi.total_num;
+ rtlpriv->stats.signal_strength = _rtl92de_translate_todbm(hw,
+ (u8) tmpval);
+ pstats->rssi = rtlpriv->stats.signal_strength;
+ }
+ if (!pstats->is_cck && pstats->packet_toself)
+ rtl92d_loop_over_paths(hw, pstats);
+}
+
+static void _rtl92de_update_rxsignalstatistics(struct ieee80211_hw *hw,
+ struct rtl_stats *pstats)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ int weighting = 0;
+
+ if (rtlpriv->stats.recv_signal_power == 0)
+ rtlpriv->stats.recv_signal_power = pstats->recvsignalpower;
+ if (pstats->recvsignalpower > rtlpriv->stats.recv_signal_power)
+ weighting = 5;
+ else if (pstats->recvsignalpower < rtlpriv->stats.recv_signal_power)
+ weighting = (-5);
+ rtlpriv->stats.recv_signal_power = (rtlpriv->stats.recv_signal_power *
+ 5 + pstats->recvsignalpower + weighting) / 6;
+}
+
+static void _rtl92de_process_pwdb(struct ieee80211_hw *hw,
+ struct rtl_stats *pstats)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+ long undecorated_smoothed_pwdb;
+
+ if (mac->opmode == NL80211_IFTYPE_ADHOC ||
+ mac->opmode == NL80211_IFTYPE_AP)
+ return;
+ else
+ undecorated_smoothed_pwdb =
+ rtlpriv->dm.undecorated_smoothed_pwdb;
+
+ if (pstats->packet_toself || pstats->packet_beacon) {
+ if (undecorated_smoothed_pwdb < 0)
+ undecorated_smoothed_pwdb = pstats->rx_pwdb_all;
+ if (pstats->rx_pwdb_all > (u32) undecorated_smoothed_pwdb) {
+ undecorated_smoothed_pwdb =
+ (((undecorated_smoothed_pwdb) *
+ (RX_SMOOTH_FACTOR - 1)) +
+ (pstats->rx_pwdb_all)) / (RX_SMOOTH_FACTOR);
+ undecorated_smoothed_pwdb =
+ undecorated_smoothed_pwdb + 1;
+ } else {
+ undecorated_smoothed_pwdb =
+ (((undecorated_smoothed_pwdb) *
+ (RX_SMOOTH_FACTOR - 1)) +
+ (pstats->rx_pwdb_all)) / (RX_SMOOTH_FACTOR);
+ }
+ rtlpriv->dm.undecorated_smoothed_pwdb =
+ undecorated_smoothed_pwdb;
+ _rtl92de_update_rxsignalstatistics(hw, pstats);
+ }
+}
+
+static void rtl92d_loop_over_streams(struct ieee80211_hw *hw,
+ struct rtl_stats *pstats)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ int stream;
+
+ for (stream = 0; stream < 2; stream++) {
+ if (pstats->rx_mimo_signalquality[stream] != -1) {
+ if (rtlpriv->stats.rx_evm_percentage[stream] == 0) {
+ rtlpriv->stats.rx_evm_percentage[stream] =
+ pstats->rx_mimo_signalquality[stream];
+ }
+ rtlpriv->stats.rx_evm_percentage[stream] =
+ ((rtlpriv->stats.rx_evm_percentage[stream]
+ * (RX_SMOOTH_FACTOR - 1)) +
+ (pstats->rx_mimo_signalquality[stream] * 1)) /
+ (RX_SMOOTH_FACTOR);
+ }
+ }
+}
+
+static void _rtl92de_process_ui_link_quality(struct ieee80211_hw *hw,
+ struct rtl_stats *pstats)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u32 last_evm, tmpval;
+
+ if (pstats->signalquality == 0)
+ return;
+ if (pstats->packet_toself || pstats->packet_beacon) {
+ if (rtlpriv->stats.ui_link_quality.total_num++ >=
+ PHY_LINKQUALITY_SLID_WIN_MAX) {
+ rtlpriv->stats.ui_link_quality.total_num =
+ PHY_LINKQUALITY_SLID_WIN_MAX;
+ last_evm = rtlpriv->stats.ui_link_quality.elements[
+ rtlpriv->stats.ui_link_quality.index];
+ rtlpriv->stats.ui_link_quality.total_val -= last_evm;
+ }
+ rtlpriv->stats.ui_link_quality.total_val +=
+ pstats->signalquality;
+ rtlpriv->stats.ui_link_quality.elements[
+ rtlpriv->stats.ui_link_quality.index++] =
+ pstats->signalquality;
+ if (rtlpriv->stats.ui_link_quality.index >=
+ PHY_LINKQUALITY_SLID_WIN_MAX)
+ rtlpriv->stats.ui_link_quality.index = 0;
+ tmpval = rtlpriv->stats.ui_link_quality.total_val /
+ rtlpriv->stats.ui_link_quality.total_num;
+ rtlpriv->stats.signal_quality = tmpval;
+ rtlpriv->stats.last_sigstrength_inpercent = tmpval;
+ rtl92d_loop_over_streams(hw, pstats);
+ }
+}
+
+static void _rtl92de_process_phyinfo(struct ieee80211_hw *hw,
+ u8 *buffer,
+ struct rtl_stats *pcurrent_stats)
+{
+
+ if (!pcurrent_stats->packet_matchbssid &&
+ !pcurrent_stats->packet_beacon)
+ return;
+
+ _rtl92de_process_ui_rssi(hw, pcurrent_stats);
+ _rtl92de_process_pwdb(hw, pcurrent_stats);
+ _rtl92de_process_ui_link_quality(hw, pcurrent_stats);
+}
+
+static void _rtl92de_translate_rx_signal_stuff(struct ieee80211_hw *hw,
+ struct sk_buff *skb,
+ struct rtl_stats *pstats,
+ struct rx_desc_92d *pdesc,
+ struct rx_fwinfo_92d *p_drvinfo)
+{
+ struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+ struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+ struct ieee80211_hdr *hdr;
+ u8 *tmp_buf;
+ u8 *praddr;
+ u16 type, cfc;
+ __le16 fc;
+ bool packet_matchbssid, packet_toself, packet_beacon;
+
+ tmp_buf = skb->data + pstats->rx_drvinfo_size + pstats->rx_bufshift;
+ hdr = (struct ieee80211_hdr *)tmp_buf;
+ fc = hdr->frame_control;
+ cfc = le16_to_cpu(fc);
+ type = WLAN_FC_GET_TYPE(fc);
+ praddr = hdr->addr1;
+ packet_matchbssid = ((IEEE80211_FTYPE_CTL != type) &&
+ (!compare_ether_addr(mac->bssid, (cfc & IEEE80211_FCTL_TODS) ?
+ hdr->addr1 : (cfc & IEEE80211_FCTL_FROMDS) ?
+ hdr->addr2 : hdr->addr3)) && (!pstats->hwerror) &&
+ (!pstats->crc) && (!pstats->icv));
+ packet_toself = packet_matchbssid &&
+ (!compare_ether_addr(praddr, rtlefuse->dev_addr));
+ if (ieee80211_is_beacon(fc))
+ packet_beacon = true;
+ _rtl92de_query_rxphystatus(hw, pstats, pdesc, p_drvinfo,
+ packet_matchbssid, packet_toself,
+ packet_beacon);
+ _rtl92de_process_phyinfo(hw, tmp_buf, pstats);
+}
+
+bool rtl92de_rx_query_desc(struct ieee80211_hw *hw, struct rtl_stats *stats,
+ struct ieee80211_rx_status *rx_status,
+ u8 *p_desc, struct sk_buff *skb)
+{
+ struct rx_fwinfo_92d *p_drvinfo;
+ struct rx_desc_92d *pdesc = (struct rx_desc_92d *)p_desc;
+ u32 phystatus = GET_RX_DESC_PHYST(pdesc);
+
+ stats->length = (u16) GET_RX_DESC_PKT_LEN(pdesc);
+ stats->rx_drvinfo_size = (u8) GET_RX_DESC_DRV_INFO_SIZE(pdesc) *
+ RX_DRV_INFO_SIZE_UNIT;
+ stats->rx_bufshift = (u8) (GET_RX_DESC_SHIFT(pdesc) & 0x03);
+ stats->icv = (u16) GET_RX_DESC_ICV(pdesc);
+ stats->crc = (u16) GET_RX_DESC_CRC32(pdesc);
+ stats->hwerror = (stats->crc | stats->icv);
+ stats->decrypted = !GET_RX_DESC_SWDEC(pdesc);
+ stats->rate = (u8) GET_RX_DESC_RXMCS(pdesc);
+ stats->shortpreamble = (u16) GET_RX_DESC_SPLCP(pdesc);
+ stats->isampdu = (bool) (GET_RX_DESC_PAGGR(pdesc) == 1);
+ stats->isfirst_ampdu = (bool) ((GET_RX_DESC_PAGGR(pdesc) == 1)
+ && (GET_RX_DESC_FAGGR(pdesc) == 1));
+ stats->timestamp_low = GET_RX_DESC_TSFL(pdesc);
+ stats->rx_is40Mhzpacket = (bool) GET_RX_DESC_BW(pdesc);
+ rx_status->freq = hw->conf.channel->center_freq;
+ rx_status->band = hw->conf.channel->band;
+ if (GET_RX_DESC_CRC32(pdesc))
+ rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
+ if (!GET_RX_DESC_SWDEC(pdesc))
+ rx_status->flag |= RX_FLAG_DECRYPTED;
+ if (GET_RX_DESC_BW(pdesc))
+ rx_status->flag |= RX_FLAG_40MHZ;
+ if (GET_RX_DESC_RXHT(pdesc))
+ rx_status->flag |= RX_FLAG_HT;
+ rx_status->flag |= RX_FLAG_MACTIME_MPDU;
+ if (stats->decrypted)
+ rx_status->flag |= RX_FLAG_DECRYPTED;
+ rx_status->rate_idx = _rtl92de_rate_mapping((bool)
+ GET_RX_DESC_RXHT(pdesc),
+ (u8)
+ GET_RX_DESC_RXMCS(pdesc));
+ rx_status->mactime = GET_RX_DESC_TSFL(pdesc);
+ if (phystatus == true) {
+ p_drvinfo = (struct rx_fwinfo_92d *)(skb->data +
+ stats->rx_bufshift);
+ _rtl92de_translate_rx_signal_stuff(hw,
+ skb, stats, pdesc,
+ p_drvinfo);
+ }
+ /*rx_status->qual = stats->signal; */
+ rx_status->signal = stats->rssi + 10;
+ /*rx_status->noise = -stats->noise; */
+ return true;
+}
+
+static void _rtl92de_insert_emcontent(struct rtl_tcb_desc *ptcb_desc,
+ u8 *virtualaddress)
+{
+ memset(virtualaddress, 0, 8);
+
+ SET_EARLYMODE_PKTNUM(virtualaddress, ptcb_desc->empkt_num);
+ SET_EARLYMODE_LEN0(virtualaddress, ptcb_desc->empkt_len[0]);
+ SET_EARLYMODE_LEN1(virtualaddress, ptcb_desc->empkt_len[1]);
+ SET_EARLYMODE_LEN2_1(virtualaddress, ptcb_desc->empkt_len[2] & 0xF);
+ SET_EARLYMODE_LEN2_2(virtualaddress, ptcb_desc->empkt_len[2] >> 4);
+ SET_EARLYMODE_LEN3(virtualaddress, ptcb_desc->empkt_len[3]);
+ SET_EARLYMODE_LEN4(virtualaddress, ptcb_desc->empkt_len[4]);
+}
+
+void rtl92de_tx_fill_desc(struct ieee80211_hw *hw,
+ struct ieee80211_hdr *hdr, u8 *pdesc_tx,
+ struct ieee80211_tx_info *info, struct sk_buff *skb,
+ u8 hw_queue, struct rtl_tcb_desc *ptcb_desc)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+ struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+ struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
+ struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+ struct ieee80211_sta *sta = info->control.sta;
+ u8 *pdesc = (u8 *) pdesc_tx;
+ u16 seq_number;
+ __le16 fc = hdr->frame_control;
+ unsigned int buf_len = 0;
+ unsigned int skb_len = skb->len;
+ u8 fw_qsel = _rtl92de_map_hwqueue_to_fwqueue(skb, hw_queue);
+ bool firstseg = ((hdr->seq_ctrl &
+ cpu_to_le16(IEEE80211_SCTL_FRAG)) == 0);
+ bool lastseg = ((hdr->frame_control &
+ cpu_to_le16(IEEE80211_FCTL_MOREFRAGS)) == 0);
+ dma_addr_t mapping;
+ u8 bw_40 = 0;
+
+ if (mac->opmode == NL80211_IFTYPE_STATION) {
+ bw_40 = mac->bw_40;
+ } else if (mac->opmode == NL80211_IFTYPE_AP ||
+ mac->opmode == NL80211_IFTYPE_ADHOC) {
+ if (sta)
+ bw_40 = sta->ht_cap.cap &
+ IEEE80211_HT_CAP_SUP_WIDTH_20_40;
+ }
+ seq_number = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4;
+ rtl_get_tcb_desc(hw, info, sta, skb, ptcb_desc);
+ /* reserve 8 byte for AMPDU early mode */
+ if (rtlhal->earlymode_enable) {
+ skb_push(skb, EM_HDR_LEN);
+ memset(skb->data, 0, EM_HDR_LEN);
+ }
+ buf_len = skb->len;
+ mapping = pci_map_single(rtlpci->pdev, skb->data, skb->len,
+ PCI_DMA_TODEVICE);
+ CLEAR_PCI_TX_DESC_CONTENT(pdesc, sizeof(struct tx_desc_92d));
+ if (ieee80211_is_nullfunc(fc) || ieee80211_is_ctl(fc)) {
+ firstseg = true;
+ lastseg = true;
+ }
+ if (firstseg) {
+ if (rtlhal->earlymode_enable) {
+ SET_TX_DESC_PKT_OFFSET(pdesc, 1);
+ SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN +
+ EM_HDR_LEN);
+ if (ptcb_desc->empkt_num) {
+ RT_TRACE(rtlpriv, COMP_SEND, DBG_LOUD,
+ ("Insert 8 byte.pTcb->EMPktNum:%d\n",
+ ptcb_desc->empkt_num));
+ _rtl92de_insert_emcontent(ptcb_desc,
+ (u8 *)(skb->data));
+ }
+ } else {
+ SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN);
+ }
+ /* 5G have no CCK rate */
+ if (rtlhal->current_bandtype == BAND_ON_5G)
+ if (ptcb_desc->hw_rate < DESC92D_RATE6M)
+ ptcb_desc->hw_rate = DESC92D_RATE6M;
+ SET_TX_DESC_TX_RATE(pdesc, ptcb_desc->hw_rate);
+ if (ptcb_desc->use_shortgi || ptcb_desc->use_shortpreamble)
+ SET_TX_DESC_DATA_SHORTGI(pdesc, 1);
+
+ if (rtlhal->macphymode == DUALMAC_DUALPHY &&
+ ptcb_desc->hw_rate == DESC92D_RATEMCS7)
+ SET_TX_DESC_DATA_SHORTGI(pdesc, 1);
+
+ if (info->flags & IEEE80211_TX_CTL_AMPDU) {
+ SET_TX_DESC_AGG_ENABLE(pdesc, 1);
+ SET_TX_DESC_MAX_AGG_NUM(pdesc, 0x14);
+ }
+ SET_TX_DESC_SEQ(pdesc, seq_number);
+ SET_TX_DESC_RTS_ENABLE(pdesc, ((ptcb_desc->rts_enable &&
+ !ptcb_desc->cts_enable) ? 1 : 0));
+ SET_TX_DESC_HW_RTS_ENABLE(pdesc, ((ptcb_desc->rts_enable
+ || ptcb_desc->cts_enable) ? 1 : 0));
+ SET_TX_DESC_CTS2SELF(pdesc, ((ptcb_desc->cts_enable) ? 1 : 0));
+ SET_TX_DESC_RTS_STBC(pdesc, ((ptcb_desc->rts_stbc) ? 1 : 0));
+ /* 5G have no CCK rate */
+ if (rtlhal->current_bandtype == BAND_ON_5G)
+ if (ptcb_desc->rts_rate < DESC92D_RATE6M)
+ ptcb_desc->rts_rate = DESC92D_RATE6M;
+ SET_TX_DESC_RTS_RATE(pdesc, ptcb_desc->rts_rate);
+ SET_TX_DESC_RTS_BW(pdesc, 0);
+ SET_TX_DESC_RTS_SC(pdesc, ptcb_desc->rts_sc);
+ SET_TX_DESC_RTS_SHORT(pdesc, ((ptcb_desc->rts_rate <=
+ DESC92D_RATE54M) ?
+ (ptcb_desc->rts_use_shortpreamble ? 1 : 0) :
+ (ptcb_desc->rts_use_shortgi ? 1 : 0)));
+ if (bw_40) {
+ if (ptcb_desc->packet_bw) {
+ SET_TX_DESC_DATA_BW(pdesc, 1);
+ SET_TX_DESC_TX_SUB_CARRIER(pdesc, 3);
+ } else {
+ SET_TX_DESC_DATA_BW(pdesc, 0);
+ SET_TX_DESC_TX_SUB_CARRIER(pdesc,
+ mac->cur_40_prime_sc);
+ }
+ } else {
+ SET_TX_DESC_DATA_BW(pdesc, 0);
+ SET_TX_DESC_TX_SUB_CARRIER(pdesc, 0);
+ }
+ SET_TX_DESC_LINIP(pdesc, 0);
+ SET_TX_DESC_PKT_SIZE(pdesc, (u16) skb_len);
+ if (sta) {
+ u8 ampdu_density = sta->ht_cap.ampdu_density;
+ SET_TX_DESC_AMPDU_DENSITY(pdesc, ampdu_density);
+ }
+ if (info->control.hw_key) {
+ struct ieee80211_key_conf *keyconf;
+
+ keyconf = info->control.hw_key;
+ switch (keyconf->cipher) {
+ case WLAN_CIPHER_SUITE_WEP40:
+ case WLAN_CIPHER_SUITE_WEP104:
+ case WLAN_CIPHER_SUITE_TKIP:
+ SET_TX_DESC_SEC_TYPE(pdesc, 0x1);
+ break;
+ case WLAN_CIPHER_SUITE_CCMP:
+ SET_TX_DESC_SEC_TYPE(pdesc, 0x3);
+ break;
+ default:
+ SET_TX_DESC_SEC_TYPE(pdesc, 0x0);
+ break;
+
+ }
+ }
+ SET_TX_DESC_PKT_ID(pdesc, 0);
+ SET_TX_DESC_QUEUE_SEL(pdesc, fw_qsel);
+ SET_TX_DESC_DATA_RATE_FB_LIMIT(pdesc, 0x1F);
+ SET_TX_DESC_RTS_RATE_FB_LIMIT(pdesc, 0xF);
+ SET_TX_DESC_DISABLE_FB(pdesc, ptcb_desc->disable_ratefallback ?
+ 1 : 0);
+ SET_TX_DESC_USE_RATE(pdesc, ptcb_desc->use_driver_rate ? 1 : 0);
+
+ /* Set TxRate and RTSRate in TxDesc */
+ /* This prevent Tx initial rate of new-coming packets */
+ /* from being overwritten by retried packet rate.*/
+ if (!ptcb_desc->use_driver_rate) {
+ SET_TX_DESC_RTS_RATE(pdesc, 0x08);
+ /* SET_TX_DESC_TX_RATE(pdesc, 0x0b); */
+ }
+ if (ieee80211_is_data_qos(fc)) {
+ if (mac->rdg_en) {
+ RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE,
+ ("Enable RDG function.\n"));
+ SET_TX_DESC_RDG_ENABLE(pdesc, 1);
+ SET_TX_DESC_HTC(pdesc, 1);
+ }
+ }
+ }
+
+ SET_TX_DESC_FIRST_SEG(pdesc, (firstseg ? 1 : 0));
+ SET_TX_DESC_LAST_SEG(pdesc, (lastseg ? 1 : 0));
+ SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16) buf_len);
+ SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, mapping);
+ if (rtlpriv->dm.useramask) {
+ SET_TX_DESC_RATE_ID(pdesc, ptcb_desc->ratr_index);
+ SET_TX_DESC_MACID(pdesc, ptcb_desc->mac_id);
+ } else {
+ SET_TX_DESC_RATE_ID(pdesc, 0xC + ptcb_desc->ratr_index);
+ SET_TX_DESC_MACID(pdesc, ptcb_desc->ratr_index);
+ }
+ if (ieee80211_is_data_qos(fc))
+ SET_TX_DESC_QOS(pdesc, 1);
+
+ if ((!ieee80211_is_data_qos(fc)) && ppsc->fwctrl_lps) {
+ SET_TX_DESC_HWSEQ_EN(pdesc, 1);
+ SET_TX_DESC_PKT_ID(pdesc, 8);
+ }
+ SET_TX_DESC_MORE_FRAG(pdesc, (lastseg ? 0 : 1));
+ RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, ("\n"));
+}
+
+void rtl92de_tx_fill_cmddesc(struct ieee80211_hw *hw,
+ u8 *pdesc, bool firstseg,
+ bool lastseg, struct sk_buff *skb)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+ struct rtl_ps_ctl *ppsc = rtl_psc(rtlpriv);
+ struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
+ u8 fw_queue = QSLT_BEACON;
+ dma_addr_t mapping = pci_map_single(rtlpci->pdev,
+ skb->data, skb->len, PCI_DMA_TODEVICE);
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data);
+ __le16 fc = hdr->frame_control;
+
+ CLEAR_PCI_TX_DESC_CONTENT(pdesc, TX_DESC_SIZE);
+ if (firstseg)
+ SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN);
+ /* 5G have no CCK rate
+ * Caution: The macros below are multi-line expansions.
+ * The braces are needed no matter what checkpatch says
+ */
+ if (rtlhal->current_bandtype == BAND_ON_5G) {
+ SET_TX_DESC_TX_RATE(pdesc, DESC92D_RATE6M);
+ } else {
+ SET_TX_DESC_TX_RATE(pdesc, DESC92D_RATE1M);
+ }
+ SET_TX_DESC_SEQ(pdesc, 0);
+ SET_TX_DESC_LINIP(pdesc, 0);
+ SET_TX_DESC_QUEUE_SEL(pdesc, fw_queue);
+ SET_TX_DESC_FIRST_SEG(pdesc, 1);
+ SET_TX_DESC_LAST_SEG(pdesc, 1);
+ SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16) (skb->len));
+ SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, mapping);
+ SET_TX_DESC_RATE_ID(pdesc, 7);
+ SET_TX_DESC_MACID(pdesc, 0);
+ SET_TX_DESC_PKT_SIZE((u8 *) pdesc, (u16) (skb->len));
+ SET_TX_DESC_FIRST_SEG(pdesc, 1);
+ SET_TX_DESC_LAST_SEG(pdesc, 1);
+ SET_TX_DESC_OFFSET(pdesc, 0x20);
+ SET_TX_DESC_USE_RATE(pdesc, 1);
+
+ if (!ieee80211_is_data_qos(fc) && ppsc->fwctrl_lps) {
+ SET_TX_DESC_HWSEQ_EN(pdesc, 1);
+ SET_TX_DESC_PKT_ID(pdesc, 8);
+ }
+
+ RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD,
+ "H2C Tx Cmd Content\n", pdesc, TX_DESC_SIZE);
+ wmb();
+ SET_TX_DESC_OWN(pdesc, 1);
+}
+
+void rtl92de_set_desc(u8 *pdesc, bool istx, u8 desc_name, u8 *val)
+{
+ if (istx == true) {
+ switch (desc_name) {
+ case HW_DESC_OWN:
+ wmb();
+ SET_TX_DESC_OWN(pdesc, 1);
+ break;
+ case HW_DESC_TX_NEXTDESC_ADDR:
+ SET_TX_DESC_NEXT_DESC_ADDRESS(pdesc, *(u32 *) val);
+ break;
+ default:
+ RT_ASSERT(false, ("ERR txdesc :%d"
+ " not process\n", desc_name));
+ break;
+ }
+ } else {
+ switch (desc_name) {
+ case HW_DESC_RXOWN:
+ wmb();
+ SET_RX_DESC_OWN(pdesc, 1);
+ break;
+ case HW_DESC_RXBUFF_ADDR:
+ SET_RX_DESC_BUFF_ADDR(pdesc, *(u32 *) val);
+ break;
+ case HW_DESC_RXPKT_LEN:
+ SET_RX_DESC_PKT_LEN(pdesc, *(u32 *) val);
+ break;
+ case HW_DESC_RXERO:
+ SET_RX_DESC_EOR(pdesc, 1);
+ break;
+ default:
+ RT_ASSERT(false, ("ERR rxdesc :%d "
+ "not process\n", desc_name));
+ break;
+ }
+ }
+}
+
+u32 rtl92de_get_desc(u8 *p_desc, bool istx, u8 desc_name)
+{
+ u32 ret = 0;
+
+ if (istx == true) {
+ switch (desc_name) {
+ case HW_DESC_OWN:
+ ret = GET_TX_DESC_OWN(p_desc);
+ break;
+ case HW_DESC_TXBUFF_ADDR:
+ ret = GET_TX_DESC_TX_BUFFER_ADDRESS(p_desc);
+ break;
+ default:
+ RT_ASSERT(false, ("ERR txdesc :%d "
+ "not process\n", desc_name));
+ break;
+ }
+ } else {
+ struct rx_desc_92c *pdesc = (struct rx_desc_92c *)p_desc;
+ switch (desc_name) {
+ case HW_DESC_OWN:
+ ret = GET_RX_DESC_OWN(pdesc);
+ break;
+ case HW_DESC_RXPKT_LEN:
+ ret = GET_RX_DESC_PKT_LEN(pdesc);
+ break;
+ default:
+ RT_ASSERT(false, ("ERR rxdesc :%d "
+ "not process\n", desc_name));
+ break;
+ }
+ }
+ return ret;
+}
+
+void rtl92de_tx_polling(struct ieee80211_hw *hw, u8 hw_queue)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ if (hw_queue == BEACON_QUEUE)
+ rtl_write_word(rtlpriv, REG_PCIE_CTRL_REG, BIT(4));
+ else
+ rtl_write_word(rtlpriv, REG_PCIE_CTRL_REG,
+ BIT(0) << (hw_queue));
+}
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/trx.h b/drivers/net/wireless/rtlwifi/rtl8192de/trx.h
new file mode 100644
index 0000000..992d676
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8192de/trx.h
@@ -0,0 +1,756 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010 Realtek Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License 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, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#ifndef __RTL92DE_TRX_H__
+#define __RTL92DE_TRX_H__
+
+#define TX_DESC_SIZE 64
+#define TX_DESC_AGGR_SUBFRAME_SIZE 32
+
+#define RX_DESC_SIZE 32
+#define RX_DRV_INFO_SIZE_UNIT 8
+
+#define TX_DESC_NEXT_DESC_OFFSET 40
+#define USB_HWDESC_HEADER_LEN 32
+#define CRCLENGTH 4
+
+/* Define a macro that takes a le32 word, converts it to host ordering,
+ * right shifts by a specified count, creates a mask of the specified
+ * bit count, and extracts that number of bits.
+ */
+
+#define SHIFT_AND_MASK_LE(__pdesc, __shift, __mask) \
+ ((le32_to_cpu(*(((__le32 *)(__pdesc)))) >> (__shift)) & \
+ BIT_LEN_MASK_32(__mask))
+
+/* Define a macro that clears a bit field in an le32 word and
+ * sets the specified value into that bit field. The resulting
+ * value remains in le32 ordering; however, it is properly converted
+ * to host ordering for the clear and set operations before conversion
+ * back to le32.
+ */
+
+#define SET_BITS_OFFSET_LE(__pdesc, __shift, __len, __val) \
+ (*(__le32 *)(__pdesc) = \
+ (cpu_to_le32((le32_to_cpu(*((__le32 *)(__pdesc))) & \
+ (~(BIT_OFFSET_LEN_MASK_32((__shift), __len)))) | \
+ (((u32)(__val) & BIT_LEN_MASK_32(__len)) << (__shift)))));
+
+/* macros to read/write various fields in RX or TX descriptors */
+
+#define SET_TX_DESC_PKT_SIZE(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc, 0, 16, __val)
+#define SET_TX_DESC_OFFSET(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc, 16, 8, __val)
+#define SET_TX_DESC_BMC(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc, 24, 1, __val)
+#define SET_TX_DESC_HTC(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc, 25, 1, __val)
+#define SET_TX_DESC_LAST_SEG(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc, 26, 1, __val)
+#define SET_TX_DESC_FIRST_SEG(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc, 27, 1, __val)
+#define SET_TX_DESC_LINIP(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc, 28, 1, __val)
+#define SET_TX_DESC_NO_ACM(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc, 29, 1, __val)
+#define SET_TX_DESC_GF(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc, 30, 1, __val)
+#define SET_TX_DESC_OWN(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc, 31, 1, __val)
+
+#define GET_TX_DESC_PKT_SIZE(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc, 0, 16)
+#define GET_TX_DESC_OFFSET(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc, 16, 8)
+#define GET_TX_DESC_BMC(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc, 24, 1)
+#define GET_TX_DESC_HTC(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc, 25, 1)
+#define GET_TX_DESC_LAST_SEG(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc, 26, 1)
+#define GET_TX_DESC_FIRST_SEG(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc, 27, 1)
+#define GET_TX_DESC_LINIP(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc, 28, 1)
+#define GET_TX_DESC_NO_ACM(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc, 29, 1)
+#define GET_TX_DESC_GF(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc, 30, 1)
+#define GET_TX_DESC_OWN(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc, 31, 1)
+
+#define SET_TX_DESC_MACID(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+4, 0, 5, __val)
+#define SET_TX_DESC_AGG_ENABLE(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+4, 5, 1, __val)
+#define SET_TX_DESC_BK(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+4, 6, 1, __val)
+#define SET_TX_DESC_RDG_ENABLE(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+4, 7, 1, __val)
+#define SET_TX_DESC_QUEUE_SEL(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+4, 8, 5, __val)
+#define SET_TX_DESC_RDG_NAV_EXT(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+4, 13, 1, __val)
+#define SET_TX_DESC_LSIG_TXOP_EN(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+4, 14, 1, __val)
+#define SET_TX_DESC_PIFS(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+4, 15, 1, __val)
+#define SET_TX_DESC_RATE_ID(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+4, 16, 4, __val)
+#define SET_TX_DESC_NAV_USE_HDR(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+4, 20, 1, __val)
+#define SET_TX_DESC_EN_DESC_ID(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+4, 21, 1, __val)
+#define SET_TX_DESC_SEC_TYPE(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+4, 22, 2, __val)
+#define SET_TX_DESC_PKT_OFFSET(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+4, 26, 8, __val)
+
+#define GET_TX_DESC_MACID(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+4, 0, 5)
+#define GET_TX_DESC_AGG_ENABLE(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+4, 5, 1)
+#define GET_TX_DESC_AGG_BREAK(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+4, 6, 1)
+#define GET_TX_DESC_RDG_ENABLE(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+4, 7, 1)
+#define GET_TX_DESC_QUEUE_SEL(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+4, 8, 5)
+#define GET_TX_DESC_RDG_NAV_EXT(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+4, 13, 1)
+#define GET_TX_DESC_LSIG_TXOP_EN(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+4, 14, 1)
+#define GET_TX_DESC_PIFS(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+4, 15, 1)
+#define GET_TX_DESC_RATE_ID(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+4, 16, 4)
+#define GET_TX_DESC_NAV_USE_HDR(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+4, 20, 1)
+#define GET_TX_DESC_EN_DESC_ID(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+4, 21, 1)
+#define GET_TX_DESC_SEC_TYPE(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+4, 22, 2)
+#define GET_TX_DESC_PKT_OFFSET(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+4, 24, 8)
+
+#define SET_TX_DESC_RTS_RC(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+8, 0, 6, __val)
+#define SET_TX_DESC_DATA_RC(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+8, 6, 6, __val)
+#define SET_TX_DESC_BAR_RTY_TH(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+8, 14, 2, __val)
+#define SET_TX_DESC_MORE_FRAG(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+8, 17, 1, __val)
+#define SET_TX_DESC_RAW(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+8, 18, 1, __val)
+#define SET_TX_DESC_CCX(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+8, 19, 1, __val)
+#define SET_TX_DESC_AMPDU_DENSITY(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+8, 20, 3, __val)
+#define SET_TX_DESC_ANTSEL_A(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+8, 24, 1, __val)
+#define SET_TX_DESC_ANTSEL_B(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+8, 25, 1, __val)
+#define SET_TX_DESC_TX_ANT_CCK(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+8, 26, 2, __val)
+#define SET_TX_DESC_TX_ANTL(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+8, 28, 2, __val)
+#define SET_TX_DESC_TX_ANT_HT(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+8, 30, 2, __val)
+
+#define GET_TX_DESC_RTS_RC(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+8, 0, 6)
+#define GET_TX_DESC_DATA_RC(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+8, 6, 6)
+#define GET_TX_DESC_BAR_RTY_TH(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+8, 14, 2)
+#define GET_TX_DESC_MORE_FRAG(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+8, 17, 1)
+#define GET_TX_DESC_RAW(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+8, 18, 1)
+#define GET_TX_DESC_CCX(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+8, 19, 1)
+#define GET_TX_DESC_AMPDU_DENSITY(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+8, 20, 3)
+#define GET_TX_DESC_ANTSEL_A(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+8, 24, 1)
+#define GET_TX_DESC_ANTSEL_B(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+8, 25, 1)
+#define GET_TX_DESC_TX_ANT_CCK(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+8, 26, 2)
+#define GET_TX_DESC_TX_ANTL(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+8, 28, 2)
+#define GET_TX_DESC_TX_ANT_HT(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+8, 30, 2)
+
+#define SET_TX_DESC_NEXT_HEAP_PAGE(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+12, 0, 8, __val)
+#define SET_TX_DESC_TAIL_PAGE(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+12, 8, 8, __val)
+#define SET_TX_DESC_SEQ(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+12, 16, 12, __val)
+#define SET_TX_DESC_PKT_ID(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+12, 28, 4, __val)
+
+#define GET_TX_DESC_NEXT_HEAP_PAGE(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+12, 0, 8)
+#define GET_TX_DESC_TAIL_PAGE(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+12, 8, 8)
+#define GET_TX_DESC_SEQ(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+12, 16, 12)
+#define GET_TX_DESC_PKT_ID(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+12, 28, 4)
+
+#define SET_TX_DESC_RTS_RATE(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+16, 0, 5, __val)
+#define SET_TX_DESC_AP_DCFE(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+16, 5, 1, __val)
+#define SET_TX_DESC_QOS(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+16, 6, 1, __val)
+#define SET_TX_DESC_HWSEQ_EN(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+16, 7, 1, __val)
+#define SET_TX_DESC_USE_RATE(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+16, 8, 1, __val)
+#define SET_TX_DESC_DISABLE_RTS_FB(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+16, 9, 1, __val)
+#define SET_TX_DESC_DISABLE_FB(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+16, 10, 1, __val)
+#define SET_TX_DESC_CTS2SELF(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+16, 11, 1, __val)
+#define SET_TX_DESC_RTS_ENABLE(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+16, 12, 1, __val)
+#define SET_TX_DESC_HW_RTS_ENABLE(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+16, 13, 1, __val)
+#define SET_TX_DESC_PORT_ID(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+16, 14, 1, __val)
+#define SET_TX_DESC_WAIT_DCTS(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+16, 18, 1, __val)
+#define SET_TX_DESC_CTS2AP_EN(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+16, 19, 1, __val)
+#define SET_TX_DESC_TX_SUB_CARRIER(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+16, 20, 2, __val)
+#define SET_TX_DESC_TX_STBC(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+16, 22, 2, __val)
+#define SET_TX_DESC_DATA_SHORT(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+16, 24, 1, __val)
+#define SET_TX_DESC_DATA_BW(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+16, 25, 1, __val)
+#define SET_TX_DESC_RTS_SHORT(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+16, 26, 1, __val)
+#define SET_TX_DESC_RTS_BW(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+16, 27, 1, __val)
+#define SET_TX_DESC_RTS_SC(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+16, 28, 2, __val)
+#define SET_TX_DESC_RTS_STBC(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+16, 30, 2, __val)
+
+#define GET_TX_DESC_RTS_RATE(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+16, 0, 5)
+#define GET_TX_DESC_AP_DCFE(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+16, 5, 1)
+#define GET_TX_DESC_QOS(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+16, 6, 1)
+#define GET_TX_DESC_HWSEQ_EN(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+16, 7, 1)
+#define GET_TX_DESC_USE_RATE(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+16, 8, 1)
+#define GET_TX_DESC_DISABLE_RTS_FB(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+16, 9, 1)
+#define GET_TX_DESC_DISABLE_FB(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+16, 10, 1)
+#define GET_TX_DESC_CTS2SELF(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+16, 11, 1)
+#define GET_TX_DESC_RTS_ENABLE(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+16, 12, 1)
+#define GET_TX_DESC_HW_RTS_ENABLE(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+16, 13, 1)
+#define GET_TX_DESC_PORT_ID(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+16, 14, 1)
+#define GET_TX_DESC_WAIT_DCTS(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+16, 18, 1)
+#define GET_TX_DESC_CTS2AP_EN(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+16, 19, 1)
+#define GET_TX_DESC_TX_SUB_CARRIER(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+16, 20, 2)
+#define GET_TX_DESC_TX_STBC(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+16, 22, 2)
+#define GET_TX_DESC_DATA_SHORT(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+16, 24, 1)
+#define GET_TX_DESC_DATA_BW(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+16, 25, 1)
+#define GET_TX_DESC_RTS_SHORT(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+16, 26, 1)
+#define GET_TX_DESC_RTS_BW(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+16, 27, 1)
+#define GET_TX_DESC_RTS_SC(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+16, 28, 2)
+#define GET_TX_DESC_RTS_STBC(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+16, 30, 2)
+
+#define SET_TX_DESC_TX_RATE(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+20, 0, 6, __val)
+#define SET_TX_DESC_DATA_SHORTGI(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+20, 6, 1, __val)
+#define SET_TX_DESC_CCX_TAG(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+20, 7, 1, __val)
+#define SET_TX_DESC_DATA_RATE_FB_LIMIT(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+20, 8, 5, __val)
+#define SET_TX_DESC_RTS_RATE_FB_LIMIT(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+20, 13, 4, __val)
+#define SET_TX_DESC_RETRY_LIMIT_ENABLE(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+20, 17, 1, __val)
+#define SET_TX_DESC_DATA_RETRY_LIMIT(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+20, 18, 6, __val)
+#define SET_TX_DESC_USB_TXAGG_NUM(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+20, 24, 8, __val)
+
+#define GET_TX_DESC_TX_RATE(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+20, 0, 6)
+#define GET_TX_DESC_DATA_SHORTGI(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+20, 6, 1)
+#define GET_TX_DESC_CCX_TAG(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+20, 7, 1)
+#define GET_TX_DESC_DATA_RATE_FB_LIMIT(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+20, 8, 5)
+#define GET_TX_DESC_RTS_RATE_FB_LIMIT(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+20, 13, 4)
+#define GET_TX_DESC_RETRY_LIMIT_ENABLE(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+20, 17, 1)
+#define GET_TX_DESC_DATA_RETRY_LIMIT(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+20, 18, 6)
+#define GET_TX_DESC_USB_TXAGG_NUM(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+20, 24, 8)
+
+#define SET_TX_DESC_TXAGC_A(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+24, 0, 5, __val)
+#define SET_TX_DESC_TXAGC_B(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+24, 5, 5, __val)
+#define SET_TX_DESC_USE_MAX_LEN(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+24, 10, 1, __val)
+#define SET_TX_DESC_MAX_AGG_NUM(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+24, 11, 5, __val)
+#define SET_TX_DESC_MCSG1_MAX_LEN(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+24, 16, 4, __val)
+#define SET_TX_DESC_MCSG2_MAX_LEN(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+24, 20, 4, __val)
+#define SET_TX_DESC_MCSG3_MAX_LEN(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+24, 24, 4, __val)
+#define SET_TX_DESC_MCS7_SGI_MAX_LEN(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+24, 28, 4, __val)
+
+#define GET_TX_DESC_TXAGC_A(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+24, 0, 5)
+#define GET_TX_DESC_TXAGC_B(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+24, 5, 5)
+#define GET_TX_DESC_USE_MAX_LEN(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+24, 10, 1)
+#define GET_TX_DESC_MAX_AGG_NUM(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+24, 11, 5)
+#define GET_TX_DESC_MCSG1_MAX_LEN(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+24, 16, 4)
+#define GET_TX_DESC_MCSG2_MAX_LEN(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+24, 20, 4)
+#define GET_TX_DESC_MCSG3_MAX_LEN(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+24, 24, 4)
+#define GET_TX_DESC_MCS7_SGI_MAX_LEN(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+24, 28, 4)
+
+#define SET_TX_DESC_TX_BUFFER_SIZE(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+28, 0, 16, __val)
+#define SET_TX_DESC_MCSG4_MAX_LEN(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+28, 16, 4, __val)
+#define SET_TX_DESC_MCSG5_MAX_LEN(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+28, 20, 4, __val)
+#define SET_TX_DESC_MCSG6_MAX_LEN(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+28, 24, 4, __val)
+#define SET_TX_DESC_MCS15_SGI_MAX_LEN(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+28, 28, 4, __val)
+
+#define GET_TX_DESC_TX_BUFFER_SIZE(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+28, 0, 16)
+#define GET_TX_DESC_MCSG4_MAX_LEN(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+28, 16, 4)
+#define GET_TX_DESC_MCSG5_MAX_LEN(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+28, 20, 4)
+#define GET_TX_DESC_MCSG6_MAX_LEN(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+28, 24, 4)
+#define GET_TX_DESC_MCS15_SGI_MAX_LEN(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+28, 28, 4)
+
+#define SET_TX_DESC_TX_BUFFER_ADDRESS(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+32, 0, 32, __val)
+#define SET_TX_DESC_TX_BUFFER_ADDRESS64(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+36, 0, 32, __val)
+
+#define GET_TX_DESC_TX_BUFFER_ADDRESS(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+32, 0, 32)
+#define GET_TX_DESC_TX_BUFFER_ADDRESS64(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+36, 0, 32)
+
+#define SET_TX_DESC_NEXT_DESC_ADDRESS(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+40, 0, 32, __val)
+#define SET_TX_DESC_NEXT_DESC_ADDRESS64(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+44, 0, 32, __val)
+
+#define GET_TX_DESC_NEXT_DESC_ADDRESS(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+40, 0, 32)
+#define GET_TX_DESC_NEXT_DESC_ADDRESS64(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+44, 0, 32)
+
+#define GET_RX_DESC_PKT_LEN(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc, 0, 14)
+#define GET_RX_DESC_CRC32(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc, 14, 1)
+#define GET_RX_DESC_ICV(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc, 15, 1)
+#define GET_RX_DESC_DRV_INFO_SIZE(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc, 16, 4)
+#define GET_RX_DESC_SECURITY(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc, 20, 3)
+#define GET_RX_DESC_QOS(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc, 23, 1)
+#define GET_RX_DESC_SHIFT(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc, 24, 2)
+#define GET_RX_DESC_PHYST(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc, 26, 1)
+#define GET_RX_DESC_SWDEC(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc, 27, 1)
+#define GET_RX_DESC_LS(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc, 28, 1)
+#define GET_RX_DESC_FS(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc, 29, 1)
+#define GET_RX_DESC_EOR(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc, 30, 1)
+#define GET_RX_DESC_OWN(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc, 31, 1)
+
+#define SET_RX_DESC_PKT_LEN(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc, 0, 14, __val)
+#define SET_RX_DESC_EOR(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc, 30, 1, __val)
+#define SET_RX_DESC_OWN(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc, 31, 1, __val)
+
+#define GET_RX_DESC_MACID(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+4, 0, 5)
+#define GET_RX_DESC_TID(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+4, 5, 4)
+#define GET_RX_DESC_HWRSVD(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+4, 9, 5)
+#define GET_RX_DESC_PAGGR(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+4, 14, 1)
+#define GET_RX_DESC_FAGGR(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+4, 15, 1)
+#define GET_RX_DESC_A1_FIT(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+4, 16, 4)
+#define GET_RX_DESC_A2_FIT(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+4, 20, 4)
+#define GET_RX_DESC_PAM(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+4, 24, 1)
+#define GET_RX_DESC_PWR(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+4, 25, 1)
+#define GET_RX_DESC_MD(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+4, 26, 1)
+#define GET_RX_DESC_MF(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+4, 27, 1)
+#define GET_RX_DESC_TYPE(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+4, 28, 2)
+#define GET_RX_DESC_MC(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+4, 30, 1)
+#define GET_RX_DESC_BC(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+4, 31, 1)
+#define GET_RX_DESC_SEQ(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+8, 0, 12)
+#define GET_RX_DESC_FRAG(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+8, 12, 4)
+#define GET_RX_DESC_NEXT_PKT_LEN(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+8, 16, 14)
+#define GET_RX_DESC_NEXT_IND(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+8, 30, 1)
+#define GET_RX_DESC_RSVD(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+8, 31, 1)
+
+#define GET_RX_DESC_RXMCS(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+12, 0, 6)
+#define GET_RX_DESC_RXHT(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+12, 6, 1)
+#define GET_RX_DESC_SPLCP(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+12, 8, 1)
+#define GET_RX_DESC_BW(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+12, 9, 1)
+#define GET_RX_DESC_HTC(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+12, 10, 1)
+#define GET_RX_DESC_HWPC_ERR(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+12, 14, 1)
+#define GET_RX_DESC_HWPC_IND(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+12, 15, 1)
+#define GET_RX_DESC_IV0(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+12, 16, 16)
+
+#define GET_RX_DESC_IV1(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+16, 0, 32)
+#define GET_RX_DESC_TSFL(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+20, 0, 32)
+
+#define GET_RX_DESC_BUFF_ADDR(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+24, 0, 32)
+#define GET_RX_DESC_BUFF_ADDR64(__pdesc) \
+ SHIFT_AND_MASK_LE(__pdesc+28, 0, 32)
+
+#define SET_RX_DESC_BUFF_ADDR(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+24, 0, 32, __val)
+#define SET_RX_DESC_BUFF_ADDR64(__pdesc, __val) \
+ SET_BITS_OFFSET_LE(__pdesc+28, 0, 32, __val)
+
+#define CLEAR_PCI_TX_DESC_CONTENT(__pdesc, _size) \
+do { \
+ if (_size > TX_DESC_NEXT_DESC_OFFSET) \
+ memset((void *)__pdesc, 0, TX_DESC_NEXT_DESC_OFFSET); \
+ else \
+ memset((void *)__pdesc, 0, _size); \
+} while (0);
+
+#define RX_HAL_IS_CCK_RATE(_pdesc)\
+ (_pdesc->rxmcs == DESC92D_RATE1M || \
+ _pdesc->rxmcs == DESC92D_RATE2M || \
+ _pdesc->rxmcs == DESC92D_RATE5_5M || \
+ _pdesc->rxmcs == DESC92D_RATE11M)
+
+/* For 92D early mode */
+#define SET_EARLYMODE_PKTNUM(__paddr, __value) \
+ SET_BITS_OFFSET_LE(__paddr, 0, 3, __value)
+#define SET_EARLYMODE_LEN0(__paddr, __value) \
+ SET_BITS_OFFSET_LE(__paddr, 4, 12, __value)
+#define SET_EARLYMODE_LEN1(__paddr, __value) \
+ SET_BITS_OFFSET_LE(__paddr, 16, 12, __value)
+#define SET_EARLYMODE_LEN2_1(__paddr, __value) \
+ SET_BITS_OFFSET_LE(__paddr, 28, 4, __value)
+#define SET_EARLYMODE_LEN2_2(__paddr, __value) \
+ SET_BITS_OFFSET_LE(__paddr+4, 0, 8, __value)
+#define SET_EARLYMODE_LEN3(__paddr, __value) \
+ SET_BITS_OFFSET_LE(__paddr+4, 8, 12, __value)
+#define SET_EARLYMODE_LEN4(__paddr, __value) \
+ SET_BITS_OFFSET_LE(__paddr+4, 20, 12, __value)
+
+struct rx_fwinfo_92d {
+ u8 gain_trsw[4];
+ u8 pwdb_all;
+ u8 cfosho[4];
+ u8 cfotail[4];
+ char rxevm[2];
+ char rxsnr[4];
+ u8 pdsnr[2];
+ u8 csi_current[2];
+ u8 csi_target[2];
+ u8 sigevm;
+ u8 max_ex_pwr;
+ u8 ex_intf_flag:1;
+ u8 sgi_en:1;
+ u8 rxsc:2;
+ u8 reserve:4;
+} __packed;
+
+struct tx_desc_92d {
+ u32 pktsize:16;
+ u32 offset:8;
+ u32 bmc:1;
+ u32 htc:1;
+ u32 lastseg:1;
+ u32 firstseg:1;
+ u32 linip:1;
+ u32 noacm:1;
+ u32 gf:1;
+ u32 own:1;
+
+ u32 macid:5;
+ u32 agg_en:1;
+ u32 bk:1;
+ u32 rdg_en:1;
+ u32 queuesel:5;
+ u32 rd_nav_ext:1;
+ u32 lsig_txop_en:1;
+ u32 pifs:1;
+ u32 rateid:4;
+ u32 nav_usehdr:1;
+ u32 en_descid:1;
+ u32 sectype:2;
+ u32 pktoffset:8;
+
+ u32 rts_rc:6;
+ u32 data_rc:6;
+ u32 rsvd0:2;
+ u32 bar_retryht:2;
+ u32 rsvd1:1;
+ u32 morefrag:1;
+ u32 raw:1;
+ u32 ccx:1;
+ u32 ampdudensity:3;
+ u32 rsvd2:1;
+ u32 ant_sela:1;
+ u32 ant_selb:1;
+ u32 txant_cck:2;
+ u32 txant_l:2;
+ u32 txant_ht:2;
+
+ u32 nextheadpage:8;
+ u32 tailpage:8;
+ u32 seq:12;
+ u32 pktid:4;
+
+ u32 rtsrate:5;
+ u32 apdcfe:1;
+ u32 qos:1;
+ u32 hwseq_enable:1;
+ u32 userrate:1;
+ u32 dis_rtsfb:1;
+ u32 dis_datafb:1;
+ u32 cts2self:1;
+ u32 rts_en:1;
+ u32 hwrts_en:1;
+ u32 portid:1;
+ u32 rsvd3:3;
+ u32 waitdcts:1;
+ u32 cts2ap_en:1;
+ u32 txsc:2;
+ u32 stbc:2;
+ u32 txshort:1;
+ u32 txbw:1;
+ u32 rtsshort:1;
+ u32 rtsbw:1;
+ u32 rtssc:2;
+ u32 rtsstbc:2;
+
+ u32 txrate:6;
+ u32 shortgi:1;
+ u32 ccxt:1;
+ u32 txrate_fb_lmt:5;
+ u32 rtsrate_fb_lmt:4;
+ u32 retrylmt_en:1;
+ u32 txretrylmt:6;
+ u32 usb_txaggnum:8;
+
+ u32 txagca:5;
+ u32 txagcb:5;
+ u32 usemaxlen:1;
+ u32 maxaggnum:5;
+ u32 mcsg1maxlen:4;
+ u32 mcsg2maxlen:4;
+ u32 mcsg3maxlen:4;
+ u32 mcs7sgimaxlen:4;
+
+ u32 txbuffersize:16;
+ u32 mcsg4maxlen:4;
+ u32 mcsg5maxlen:4;
+ u32 mcsg6maxlen:4;
+ u32 mcsg15sgimaxlen:4;
+
+ u32 txbuffaddr;
+ u32 txbufferaddr64;
+ u32 nextdescaddress;
+ u32 nextdescaddress64;
+
+ u32 reserve_pass_pcie_mm_limit[4];
+} __packed;
+
+struct rx_desc_92d {
+ u32 length:14;
+ u32 crc32:1;
+ u32 icverror:1;
+ u32 drv_infosize:4;
+ u32 security:3;
+ u32 qos:1;
+ u32 shift:2;
+ u32 phystatus:1;
+ u32 swdec:1;
+ u32 lastseg:1;
+ u32 firstseg:1;
+ u32 eor:1;
+ u32 own:1;
+
+ u32 macid:5;
+ u32 tid:4;
+ u32 hwrsvd:5;
+ u32 paggr:1;
+ u32 faggr:1;
+ u32 a1_fit:4;
+ u32 a2_fit:4;
+ u32 pam:1;
+ u32 pwr:1;
+ u32 moredata:1;
+ u32 morefrag:1;
+ u32 type:2;
+ u32 mc:1;
+ u32 bc:1;
+
+ u32 seq:12;
+ u32 frag:4;
+ u32 nextpktlen:14;
+ u32 nextind:1;
+ u32 rsvd:1;
+
+ u32 rxmcs:6;
+ u32 rxht:1;
+ u32 amsdu:1;
+ u32 splcp:1;
+ u32 bandwidth:1;
+ u32 htc:1;
+ u32 tcpchk_rpt:1;
+ u32 ipcchk_rpt:1;
+ u32 tcpchk_valid:1;
+ u32 hwpcerr:1;
+ u32 hwpcind:1;
+ u32 iv0:16;
+
+ u32 iv1;
+
+ u32 tsfl;
+
+ u32 bufferaddress;
+ u32 bufferaddress64;
+
+} __packed;
+
+void rtl92de_tx_fill_desc(struct ieee80211_hw *hw,
+ struct ieee80211_hdr *hdr,
+ u8 *pdesc, struct ieee80211_tx_info *info,
+ struct sk_buff *skb, u8 hw_queue,
+ struct rtl_tcb_desc *ptcb_desc);
+bool rtl92de_rx_query_desc(struct ieee80211_hw *hw,
+ struct rtl_stats *stats,
+ struct ieee80211_rx_status *rx_status,
+ u8 *pdesc, struct sk_buff *skb);
+void rtl92de_set_desc(u8 *pdesc, bool istx, u8 desc_name, u8 *val);
+u32 rtl92de_get_desc(u8 *pdesc, bool istx, u8 desc_name);
+void rtl92de_tx_polling(struct ieee80211_hw *hw, u8 hw_queue);
+void rtl92de_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc,
+ bool b_firstseg, bool b_lastseg,
+ struct sk_buff *skb);
+
+#endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/dm.c b/drivers/net/wireless/rtlwifi/rtl8192se/dm.c
index da86db8..4203a85 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/dm.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192se/dm.c
@@ -222,7 +222,6 @@
u32 low_rssi_thresh = 0;
u32 middle_rssi_thresh = 0;
u32 high_rssi_thresh = 0;
- u8 rssi_level;
struct ieee80211_sta *sta = NULL;
if (is_hal_stop(rtlhal))
@@ -272,18 +271,14 @@
if (rtlpriv->dm.undecorated_smoothed_pwdb >
(long)high_rssi_thresh) {
ra->ratr_state = DM_RATR_STA_HIGH;
- rssi_level = 1;
} else if (rtlpriv->dm.undecorated_smoothed_pwdb >
(long)middle_rssi_thresh) {
ra->ratr_state = DM_RATR_STA_LOW;
- rssi_level = 3;
} else if (rtlpriv->dm.undecorated_smoothed_pwdb >
(long)low_rssi_thresh) {
ra->ratr_state = DM_RATR_STA_LOW;
- rssi_level = 5;
} else {
ra->ratr_state = DM_RATR_STA_ULTRALOW;
- rssi_level = 6;
}
if (ra->pre_ratr_state != ra->ratr_state) {
@@ -457,7 +452,7 @@
if (rtlpriv->psc.rfpwr_state != ERFON)
return;
- if (digtable.backoff_enable_flag == true)
+ if (digtable.backoff_enable_flag)
rtl92s_backoff_enable_flag(hw);
else
digtable.backoff_val = DM_DIG_BACKOFF;
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/fw.c b/drivers/net/wireless/rtlwifi/rtl8192se/fw.c
index 3b5af01..6f91a14 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/fw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192se/fw.c
@@ -358,7 +358,6 @@
struct fw_priv *pfw_priv = NULL;
u8 *puc_mappedfile = NULL;
u32 ul_filelength = 0;
- u32 file_length = 0;
u8 fwhdr_size = RT_8192S_FIRMWARE_HDR_SIZE;
u8 fwstatus = FW_STATUS_INIT;
bool rtstatus = true;
@@ -370,7 +369,6 @@
firmware->fwstatus = FW_STATUS_INIT;
puc_mappedfile = firmware->sz_fw_tmpbuffer;
- file_length = firmware->sz_fw_tmpbufferlen;
/* 1. Retrieve FW header. */
firmware->pfwheader = (struct fw_hdr *) puc_mappedfile;
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/hw.c b/drivers/net/wireless/rtlwifi/rtl8192se/hw.c
index 2e9005d..13da7b3 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/hw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192se/hw.c
@@ -516,7 +516,7 @@
mdelay(10);
/* check GPIO3 */
- u1tmp = rtl_read_byte(rtlpriv, GPIO_IN);
+ u1tmp = rtl_read_byte(rtlpriv, GPIO_IN_SE);
retval = (u1tmp & HAL_8192S_HW_GPIO_OFF_BIT) ? ERFON : ERFOFF;
return retval;
@@ -884,12 +884,10 @@
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
u8 reg_bw_opmode = 0;
- u32 reg_ratr = 0, reg_rrsr = 0;
+ u32 reg_rrsr = 0;
u8 regtmp = 0;
reg_bw_opmode = BW_OPMODE_20MHZ;
- reg_ratr = RATE_ALL_CCK | RATE_ALL_OFDM_AG | RATE_ALL_OFDM_1SS |
- RATE_ALL_OFDM_2SS;
reg_rrsr = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
regtmp = rtl_read_byte(rtlpriv, INIRTSMCS_SEL);
@@ -996,7 +994,8 @@
rtlpriv->psc.rfoff_reason = RF_CHANGE_BY_INIT;
rtlpriv->psc.rfpwr_state = ERFON;
- rtl_ps_set_rf_state(hw, ERFOFF, rfoffreason, true);
+ /* FIXME: check spinlocks if this block is uncommented */
+ rtl_ps_set_rf_state(hw, ERFOFF, rfoffreason);
} else {
/* gpio radio on/off is out of adapter start */
if (rtlpriv->psc.hwradiooff == false) {
@@ -1107,7 +1106,7 @@
if (rtlpriv->psc.rfpwr_state != ERFON)
return;
- if (check_bssid == true) {
+ if (check_bssid) {
reg_rcr |= (RCR_CBSSID);
rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR, (u8 *)(®_rcr));
} else if (check_bssid == false) {
@@ -1122,14 +1121,12 @@
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
u8 bt_msr = rtl_read_byte(rtlpriv, MSR);
- enum led_ctl_mode ledaction = LED_CTL_NO_LINK;
u32 temp;
bt_msr &= ~MSR_LINK_MASK;
switch (type) {
case NL80211_IFTYPE_UNSPECIFIED:
bt_msr |= (MSR_LINK_NONE << MSR_LINK_SHIFT);
- ledaction = LED_CTL_LINK;
RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
("Set Network type to NO LINK!\n"));
break;
@@ -1140,7 +1137,6 @@
break;
case NL80211_IFTYPE_STATION:
bt_msr |= (MSR_LINK_MANAGED << MSR_LINK_SHIFT);
- ledaction = LED_CTL_LINK;
RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
("Set Network type to STA!\n"));
break;
@@ -1231,6 +1227,7 @@
rtl_write_dword(rtlpriv, INTA_MASK + 4, 0);
rtlpci->irq_enabled = false;
+ synchronize_irq(rtlpci->pdev->irq);
}
@@ -1655,7 +1652,7 @@
rtlefuse->autoload_failflag = false;
}
- if (rtlefuse->autoload_failflag == true)
+ if (rtlefuse->autoload_failflag)
return;
_rtl8192se_get_IC_Inferiority(hw);
@@ -2271,7 +2268,7 @@
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
- enum rf_pwrstate rfpwr_toset, cur_rfstate;
+ enum rf_pwrstate rfpwr_toset /*, cur_rfstate */;
unsigned long flag = 0;
bool actuallyset = false;
bool turnonbypowerdomain = false;
@@ -2292,7 +2289,7 @@
spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag);
}
- cur_rfstate = ppsc->rfpwr_state;
+ /* cur_rfstate = ppsc->rfpwr_state;*/
/* because after _rtl92s_phy_set_rfhalt, all power
* closed, so we must open some power for GPIO check,
@@ -2305,7 +2302,7 @@
rfpwr_toset = _rtl92se_rf_onoff_detect(hw);
- if ((ppsc->hwradiooff == true) && (rfpwr_toset == ERFON)) {
+ if ((ppsc->hwradiooff) && (rfpwr_toset == ERFON)) {
RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
("RFKILL-HW Radio ON, RF ON\n"));
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/led.c b/drivers/net/wireless/rtlwifi/rtl8192se/led.c
index 6d4f666..e3fe7c9 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/led.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192se/led.c
@@ -90,7 +90,7 @@
break;
case LED_PIN_LED0:
ledcfg &= 0xf0;
- if (pcipriv->ledctl.led_opendrain == true)
+ if (pcipriv->ledctl.led_opendrain)
rtl_write_byte(rtlpriv, LEDCFG, (ledcfg | BIT(1)));
else
rtl_write_byte(rtlpriv, LEDCFG, (ledcfg | BIT(3)));
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/phy.c b/drivers/net/wireless/rtlwifi/rtl8192se/phy.c
index 63b45e6..81a5aa4 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/phy.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192se/phy.c
@@ -180,19 +180,18 @@
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
u32 original_value, readback_value, bitshift;
- unsigned long flags;
RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("regaddr(%#x), rfpath(%#x), "
"bitmask(%#x)\n", regaddr, rfpath, bitmask));
- spin_lock_irqsave(&rtlpriv->locks.rf_lock, flags);
+ spin_lock(&rtlpriv->locks.rf_lock);
original_value = _rtl92s_phy_rf_serial_read(hw, rfpath, regaddr);
bitshift = _rtl92s_phy_calculate_bit_shift(bitmask);
readback_value = (original_value & bitmask) >> bitshift;
- spin_unlock_irqrestore(&rtlpriv->locks.rf_lock, flags);
+ spin_unlock(&rtlpriv->locks.rf_lock);
RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("regaddr(%#x), rfpath(%#x), "
"bitmask(%#x), original_value(%#x)\n", regaddr, rfpath,
@@ -207,7 +206,6 @@
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_phy *rtlphy = &(rtlpriv->phy);
u32 original_value, bitshift;
- unsigned long flags;
if (!((rtlphy->rf_pathmap >> rfpath) & 0x1))
return;
@@ -215,7 +213,7 @@
RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("regaddr(%#x), bitmask(%#x),"
" data(%#x), rfpath(%#x)\n", regaddr, bitmask, data, rfpath));
- spin_lock_irqsave(&rtlpriv->locks.rf_lock, flags);
+ spin_lock(&rtlpriv->locks.rf_lock);
if (bitmask != RFREG_OFFSET_MASK) {
original_value = _rtl92s_phy_rf_serial_read(hw, rfpath,
@@ -226,7 +224,7 @@
_rtl92s_phy_rf_serial_write(hw, rfpath, regaddr, data);
- spin_unlock_irqrestore(&rtlpriv->locks.rf_lock, flags);
+ spin_unlock(&rtlpriv->locks.rf_lock);
RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("regaddr(%#x), bitmask(%#x), "
"data(%#x), rfpath(%#x)\n", regaddr, bitmask, data, rfpath));
@@ -263,7 +261,6 @@
struct rtl_phy *rtlphy = &(rtlpriv->phy);
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
u8 reg_bw_opmode;
- u8 reg_prsr_rsc;
RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, ("Switch to %s bandwidth\n",
rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20 ?
@@ -277,7 +274,8 @@
rtlphy->set_bwmode_inprogress = true;
reg_bw_opmode = rtl_read_byte(rtlpriv, BW_OPMODE);
- reg_prsr_rsc = rtl_read_byte(rtlpriv, RRSR + 2);
+ /* dummy read */
+ rtl_read_byte(rtlpriv, RRSR + 2);
switch (rtlphy->current_chan_bw) {
case HT_CHANNEL_WIDTH_20:
@@ -546,8 +544,6 @@
if (rfpwr_state == ppsc->rfpwr_state)
return false;
- ppsc->set_rfpowerstate_inprogress = true;
-
switch (rfpwr_state) {
case ERFON:{
if ((ppsc->rfpwr_state == ERFOFF) &&
@@ -659,8 +655,6 @@
if (bresult)
ppsc->rfpwr_state = rfpwr_state;
- ppsc->set_rfpowerstate_inprogress = false;
-
return bresult;
}
@@ -1422,7 +1416,7 @@
break;
case FW_CMD_HIGH_PWR_ENABLE:
if ((rtlpriv->dm.dm_flag & HAL_DM_HIPWR_DISABLE) ||
- (rtlpriv->dm.dynamic_txpower_enable == true))
+ rtlpriv->dm.dynamic_txpower_enable)
break;
/* CCA threshold */
@@ -1614,7 +1608,7 @@
fw_cmdmap &= ~FW_DIG_ENABLE_CTL;
if ((rtlpriv->dm.dm_flag & HAL_DM_HIPWR_DISABLE) ||
- (rtlpriv->dm.dynamic_txpower_enable == true))
+ rtlpriv->dm.dynamic_txpower_enable)
fw_cmdmap &= ~FW_HIGH_PWR_ENABLE_CTL;
if ((digtable.dig_ext_port_stage ==
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/reg.h b/drivers/net/wireless/rtlwifi/rtl8192se/reg.h
index 0116ead..ea32ef2 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/reg.h
+++ b/drivers/net/wireless/rtlwifi/rtl8192se/reg.h
@@ -248,12 +248,8 @@
#define PSTIME 0x02E0
#define TIMER0 0x02E4
#define TIMER1 0x02E8
-#define GPIO_CTRL 0x02EC
-#define GPIO_IN 0x02EC
-#define GPIO_OUT 0x02ED
+#define GPIO_IN_SE 0x02EC
#define GPIO_IO_SEL 0x02EE
-#define GPIO_MOD 0x02EF
-#define GPIO_INTCTRL 0x02F0
#define MAC_PINMUX_CFG 0x02F1
#define LEDCFG 0x02F2
#define PHY_REG 0x02F3
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/rf.c b/drivers/net/wireless/rtlwifi/rtl8192se/rf.c
index 1d3a483..c6e3a4c 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/rf.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192se/rf.c
@@ -410,7 +410,7 @@
(rtlefuse->eeprom_regulatory != 0)))
dont_inc_cck_or_turboscanoff = true;
- if (mac->act_scanning == true) {
+ if (mac->act_scanning) {
txagc = 0x3f;
if (dont_inc_cck_or_turboscanoff)
txagc = pwrlevel;
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/trx.c b/drivers/net/wireless/rtlwifi/rtl8192se/trx.c
index 5cf4423..cffe308 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/trx.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192se/trx.c
@@ -581,7 +581,6 @@
struct ieee80211_hdr *hdr;
u8 *tmp_buf;
u8 *praddr;
- u8 *psaddr;
__le16 fc;
u16 type, cfc;
bool packet_matchbssid, packet_toself, packet_beacon;
@@ -593,7 +592,6 @@
cfc = le16_to_cpu(fc);
type = WLAN_FC_GET_TYPE(fc);
praddr = hdr->addr1;
- psaddr = hdr->addr2;
packet_matchbssid = ((IEEE80211_FTYPE_CTL != type) &&
(!compare_ether_addr(mac->bssid, (cfc & IEEE80211_FCTL_TODS) ?
@@ -663,7 +661,7 @@
rx_status->mactime = GET_RX_STATUS_DESC_TSFL(pdesc);
- if (phystatus == true) {
+ if (phystatus) {
p_drvinfo = (struct rx_fwinfo *)(skb->data +
stats->rx_bufshift);
_rtl92se_translate_rx_signal_stuff(hw, skb, stats, pdesc,
@@ -875,6 +873,7 @@
SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16)(skb->len));
SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, cpu_to_le32(mapping));
+ wmb();
SET_TX_DESC_OWN(pdesc, 1);
} else { /* H2C Command Desc format (Host TXCMD) */
/* 92SE must set as 1 for firmware download HW DMA error */
@@ -893,6 +892,7 @@
SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16)(skb->len));
SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, cpu_to_le32(mapping));
+ wmb();
SET_TX_DESC_OWN(pdesc, 1);
}
@@ -900,9 +900,10 @@
void rtl92se_set_desc(u8 *pdesc, bool istx, u8 desc_name, u8 *val)
{
- if (istx == true) {
+ if (istx) {
switch (desc_name) {
case HW_DESC_OWN:
+ wmb();
SET_TX_DESC_OWN(pdesc, 1);
break;
case HW_DESC_TX_NEXTDESC_ADDR:
@@ -916,6 +917,7 @@
} else {
switch (desc_name) {
case HW_DESC_RXOWN:
+ wmb();
SET_RX_STATUS_DESC_OWN(pdesc, 1);
break;
case HW_DESC_RXBUFF_ADDR:
@@ -939,7 +941,7 @@
{
u32 ret = 0;
- if (istx == true) {
+ if (istx) {
switch (desc_name) {
case HW_DESC_OWN:
ret = GET_TX_DESC_OWN(desc);
diff --git a/drivers/net/wireless/rtlwifi/wifi.h b/drivers/net/wireless/rtlwifi/wifi.h
index 693395e..d3c3ffd 100644
--- a/drivers/net/wireless/rtlwifi/wifi.h
+++ b/drivers/net/wireless/rtlwifi/wifi.h
@@ -32,7 +32,6 @@
#include <linux/sched.h>
#include <linux/firmware.h>
-#include <linux/version.h>
#include <linux/etherdevice.h>
#include <linux/vmalloc.h>
#include <linux/usb.h>
@@ -303,9 +302,6 @@
HW_VAR_DATA_FILTER,
};
-#define HWSET_MAX_SIZE 128
-#define EFUSE_MAX_SECTION 16
-
enum _RT_MEDIA_STATUS {
RT_MEDIA_DISCONNECT = 0,
RT_MEDIA_CONNECT = 1
@@ -938,7 +934,7 @@
int n_channels;
int n_bitrates;
- bool offchan_deley;
+ bool offchan_delay;
/*filters */
u32 rx_conf;
@@ -1188,7 +1184,6 @@
struct rtl_ps_ctl {
bool pwrdomain_protect;
- bool set_rfpowerstate_inprogress;
bool in_powersavemode;
bool rfchange_inprogress;
bool swrf_processing;
@@ -1536,6 +1531,7 @@
/* For SW LPS */
struct delayed_work ps_work;
struct delayed_work ps_rfon_wq;
+ struct tasklet_struct ips_leave_tasklet;
};
struct rtl_debug {
@@ -1983,7 +1979,7 @@
static inline struct ieee80211_sta *get_sta(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
- u8 *bssid)
+ const u8 *bssid)
{
return ieee80211_find_sta(vif, bssid);
}
diff --git a/drivers/net/wireless/wl1251/sdio.c b/drivers/net/wireless/wl1251/sdio.c
index f51a024..f786942 100644
--- a/drivers/net/wireless/wl1251/sdio.c
+++ b/drivers/net/wireless/wl1251/sdio.c
@@ -19,6 +19,7 @@
* Copyright (C) 2008 Google Inc
* Copyright (C) 2009 Bob Copeland (me@bobcopeland.com)
*/
+#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/mod_devicetable.h>
#include <linux/mmc/sdio_func.h>
diff --git a/drivers/net/wireless/wl1251/spi.c b/drivers/net/wireless/wl1251/spi.c
index af6448c..eaa5f95 100644
--- a/drivers/net/wireless/wl1251/spi.c
+++ b/drivers/net/wireless/wl1251/spi.c
@@ -19,6 +19,7 @@
*
*/
+#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/module.h>
#include <linux/slab.h>
diff --git a/drivers/net/wireless/wl12xx/boot.c b/drivers/net/wireless/wl12xx/boot.c
index b07f8b7..7ccec07 100644
--- a/drivers/net/wireless/wl12xx/boot.c
+++ b/drivers/net/wireless/wl12xx/boot.c
@@ -485,7 +485,8 @@
if (wl->bss_type == BSS_TYPE_AP_BSS)
wl->event_mask |= STA_REMOVE_COMPLETE_EVENT_ID;
else
- wl->event_mask |= DUMMY_PACKET_EVENT_ID;
+ wl->event_mask |= DUMMY_PACKET_EVENT_ID |
+ BA_SESSION_RX_CONSTRAINT_EVENT_ID;
ret = wl1271_event_unmask(wl);
if (ret < 0) {
diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c
index 42935ac..5d0ad2d 100644
--- a/drivers/net/wireless/wl12xx/cmd.c
+++ b/drivers/net/wireless/wl12xx/cmd.c
@@ -1167,14 +1167,7 @@
cmd->bss_index = WL1271_AP_BSS_INDEX;
cmd->aid = sta->aid;
cmd->hlid = hlid;
-
- /*
- * FIXME: Does STA support QOS? We need to propagate this info from
- * hostapd. Currently not that important since this is only used for
- * sending the correct flavor of null-data packet in response to a
- * trigger.
- */
- cmd->wmm = 0;
+ cmd->wmm = sta->wme ? 1 : 0;
cmd->supported_rates = cpu_to_le32(wl1271_tx_enabled_rates_get(wl,
sta->supp_rates[wl->band]));
diff --git a/drivers/net/wireless/wl12xx/event.c b/drivers/net/wireless/wl12xx/event.c
index c3c554c..94bbd00 100644
--- a/drivers/net/wireless/wl12xx/event.c
+++ b/drivers/net/wireless/wl12xx/event.c
@@ -168,6 +168,21 @@
wl->last_rssi_event = event;
}
+static void wl1271_stop_ba_event(struct wl1271 *wl, u8 ba_allowed)
+{
+ /* Convert the value to bool */
+ wl->ba_allowed = !!ba_allowed;
+
+ /*
+ * Return in case:
+ * there are not BA open or the event indication is to allowed BA
+ */
+ if ((!wl->ba_rx_bitmap) || (wl->ba_allowed))
+ return;
+
+ ieee80211_stop_rx_ba_session(wl->vif, wl->ba_rx_bitmap, wl->bssid);
+}
+
static void wl1271_event_mbox_dump(struct event_mailbox *mbox)
{
wl1271_debug(DEBUG_EVENT, "MBOX DUMP:");
@@ -252,6 +267,14 @@
wl1271_event_rssi_trigger(wl, mbox);
}
+ if ((vector & BA_SESSION_RX_CONSTRAINT_EVENT_ID) && !is_ap) {
+ wl1271_debug(DEBUG_EVENT, "BA_SESSION_RX_CONSTRAINT_EVENT_ID. "
+ "ba_allowed = 0x%x", mbox->ba_allowed);
+
+ if (wl->vif)
+ wl1271_stop_ba_event(wl, mbox->ba_allowed);
+ }
+
if ((vector & DUMMY_PACKET_EVENT_ID) && !is_ap) {
wl1271_debug(DEBUG_EVENT, "DUMMY_PACKET_ID_EVENT_ID");
if (wl->vif)
diff --git a/drivers/net/wireless/wl12xx/event.h b/drivers/net/wireless/wl12xx/event.h
index b6cf06e..ce99adf 100644
--- a/drivers/net/wireless/wl12xx/event.h
+++ b/drivers/net/wireless/wl12xx/event.h
@@ -71,7 +71,7 @@
HEALTH_CHECK_REPLY_EVENT_ID = BIT(27),
PERIODIC_SCAN_COMPLETE_EVENT_ID = BIT(28),
PERIODIC_SCAN_REPORT_EVENT_ID = BIT(29),
- BA_SESSION_TEAR_DOWN_EVENT_ID = BIT(30),
+ BA_SESSION_RX_CONSTRAINT_EVENT_ID = BIT(30),
EVENT_MBOX_ALL_EVENT_ID = 0x7fffffff,
};
@@ -122,7 +122,20 @@
__le16 sta_aging_status;
__le16 sta_tx_retry_exceeded;
- u8 reserved_5[24];
+ /*
+ * Bitmap, Each bit set represents the Role ID for which this constraint
+ * is set. Range: 0 - FF, FF means ANY role
+ */
+ u8 ba_role_id;
+ /*
+ * Bitmap, Each bit set represents the Link ID for which this constraint
+ * is set. Not applicable if ba_role_id is set to ANY role (FF).
+ * Range: 0 - FFFF, FFFF means ANY link in that role
+ */
+ u8 ba_link_id;
+ u8 ba_allowed;
+
+ u8 reserved_5[21];
} __packed;
int wl1271_event_unmask(struct wl1271 *wl);
diff --git a/drivers/net/wireless/wl12xx/init.c b/drivers/net/wireless/wl12xx/init.c
index a8f4f15..f5c2c9e 100644
--- a/drivers/net/wireless/wl12xx/init.c
+++ b/drivers/net/wireless/wl12xx/init.c
@@ -541,6 +541,7 @@
/* Reset the BA RX indicators */
wl->ba_rx_bitmap = 0;
+ wl->ba_allowed = true;
/* validate that FW support BA */
wl1271_check_ba_support(wl);
diff --git a/drivers/net/wireless/wl12xx/io.h b/drivers/net/wireless/wl12xx/io.h
index beed621..20b0031 100644
--- a/drivers/net/wireless/wl12xx/io.h
+++ b/drivers/net/wireless/wl12xx/io.h
@@ -25,6 +25,7 @@
#ifndef __IO_H__
#define __IO_H__
+#include <linux/irqreturn.h>
#include "reg.h"
#define HW_ACCESS_MEMORY_MAX_RANGE 0x1FFC0
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index e6497dc..f37f0b8 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -3354,9 +3354,12 @@
if (ret < 0)
goto out;
+ wl1271_debug(DEBUG_MAC80211, "mac80211 ampdu: Rx tid %d action %d",
+ tid, action);
+
switch (action) {
case IEEE80211_AMPDU_RX_START:
- if (wl->ba_support) {
+ if ((wl->ba_support) && (wl->ba_allowed)) {
ret = wl1271_acx_set_ba_receiver_session(wl, tid, *ssn,
true);
if (!ret)
diff --git a/drivers/net/wireless/wl12xx/spi.c b/drivers/net/wireless/wl12xx/spi.c
index 51662bb..beebf64 100644
--- a/drivers/net/wireless/wl12xx/spi.c
+++ b/drivers/net/wireless/wl12xx/spi.c
@@ -21,6 +21,7 @@
*
*/
+#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/module.h>
#include <linux/crc7.h>
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h
index fbe8f46..3bc794a 100644
--- a/drivers/net/wireless/wl12xx/wl12xx.h
+++ b/drivers/net/wireless/wl12xx/wl12xx.h
@@ -564,6 +564,7 @@
/* RX BA constraint value */
bool ba_support;
u8 ba_rx_bitmap;
+ bool ba_allowed;
int tcxo_clock;
diff --git a/drivers/net/wireless/zd1211rw/zd_chip.h b/drivers/net/wireless/zd1211rw/zd_chip.h
index 4be7c3b..117c412 100644
--- a/drivers/net/wireless/zd1211rw/zd_chip.h
+++ b/drivers/net/wireless/zd1211rw/zd_chip.h
@@ -21,6 +21,8 @@
#ifndef _ZD_CHIP_H
#define _ZD_CHIP_H
+#include <net/mac80211.h>
+
#include "zd_rf.h"
#include "zd_usb.h"
diff --git a/drivers/net/wireless/zd1211rw/zd_def.h b/drivers/net/wireless/zd1211rw/zd_def.h
index 5463ca9..9a1b013 100644
--- a/drivers/net/wireless/zd1211rw/zd_def.h
+++ b/drivers/net/wireless/zd1211rw/zd_def.h
@@ -37,9 +37,15 @@
if (net_ratelimit()) \
dev_printk_f(KERN_DEBUG, dev, fmt, ## args); \
} while (0)
+# define dev_dbg_f_cond(dev, cond, fmt, args...) ({ \
+ bool __cond = !!(cond); \
+ if (unlikely(__cond)) \
+ dev_printk_f(KERN_DEBUG, dev, fmt, ## args); \
+})
#else
# define dev_dbg_f(dev, fmt, args...) do { (void)(dev); } while (0)
# define dev_dbg_f_limit(dev, fmt, args...) do { (void)(dev); } while (0)
+# define dev_dbg_f_cond(dev, cond, fmt, args...) do { (void)(dev); } while (0)
#endif /* DEBUG */
#ifdef DEBUG
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c
index 5037c8b..cabfae1 100644
--- a/drivers/net/wireless/zd1211rw/zd_mac.c
+++ b/drivers/net/wireless/zd1211rw/zd_mac.c
@@ -143,7 +143,7 @@
static void beacon_disable(struct zd_mac *mac);
static void set_rts_cts(struct zd_mac *mac, unsigned int short_preamble);
static int zd_mac_config_beacon(struct ieee80211_hw *hw,
- struct sk_buff *beacon);
+ struct sk_buff *beacon, bool in_intr);
static int zd_reg2alpha2(u8 regdomain, char *alpha2)
{
@@ -160,6 +160,22 @@
return 1;
}
+static int zd_check_signal(struct ieee80211_hw *hw, int signal)
+{
+ struct zd_mac *mac = zd_hw_mac(hw);
+
+ dev_dbg_f_cond(zd_mac_dev(mac), signal < 0 || signal > 100,
+ "%s: signal value from device not in range 0..100, "
+ "but %d.\n", __func__, signal);
+
+ if (signal < 0)
+ signal = 0;
+ else if (signal > 100)
+ signal = 100;
+
+ return signal;
+}
+
int zd_mac_preinit_hw(struct ieee80211_hw *hw)
{
int r;
@@ -387,10 +403,8 @@
mac->type == NL80211_IFTYPE_AP) {
if (mac->vif != NULL) {
beacon = ieee80211_beacon_get(mac->hw, mac->vif);
- if (beacon) {
- zd_mac_config_beacon(mac->hw, beacon);
- kfree_skb(beacon);
- }
+ if (beacon)
+ zd_mac_config_beacon(mac->hw, beacon, false);
}
zd_set_beacon_interval(&mac->chip, beacon_interval,
@@ -461,7 +475,7 @@
if (i<IEEE80211_TX_MAX_RATES)
info->status.rates[i].idx = -1; /* terminate */
- info->status.ack_signal = ackssi;
+ info->status.ack_signal = zd_check_signal(hw, ackssi);
ieee80211_tx_status_irqsafe(hw, skb);
}
@@ -664,7 +678,34 @@
/* FIXME: Management frame? */
}
-static int zd_mac_config_beacon(struct ieee80211_hw *hw, struct sk_buff *beacon)
+static bool zd_mac_match_cur_beacon(struct zd_mac *mac, struct sk_buff *beacon)
+{
+ if (!mac->beacon.cur_beacon)
+ return false;
+
+ if (mac->beacon.cur_beacon->len != beacon->len)
+ return false;
+
+ return !memcmp(beacon->data, mac->beacon.cur_beacon->data, beacon->len);
+}
+
+static void zd_mac_free_cur_beacon_locked(struct zd_mac *mac)
+{
+ ZD_ASSERT(mutex_is_locked(&mac->chip.mutex));
+
+ kfree_skb(mac->beacon.cur_beacon);
+ mac->beacon.cur_beacon = NULL;
+}
+
+static void zd_mac_free_cur_beacon(struct zd_mac *mac)
+{
+ mutex_lock(&mac->chip.mutex);
+ zd_mac_free_cur_beacon_locked(mac);
+ mutex_unlock(&mac->chip.mutex);
+}
+
+static int zd_mac_config_beacon(struct ieee80211_hw *hw, struct sk_buff *beacon,
+ bool in_intr)
{
struct zd_mac *mac = zd_hw_mac(hw);
int r, ret, num_cmds, req_pos = 0;
@@ -674,13 +715,21 @@
unsigned long end_jiffies, message_jiffies;
struct zd_ioreq32 *ioreqs;
+ mutex_lock(&mac->chip.mutex);
+
+ /* Check if hw already has this beacon. */
+ if (zd_mac_match_cur_beacon(mac, beacon)) {
+ r = 0;
+ goto out_nofree;
+ }
+
/* Alloc memory for full beacon write at once. */
num_cmds = 1 + zd_chip_is_zd1211b(&mac->chip) + full_len;
ioreqs = kmalloc(num_cmds * sizeof(struct zd_ioreq32), GFP_KERNEL);
- if (!ioreqs)
- return -ENOMEM;
-
- mutex_lock(&mac->chip.mutex);
+ if (!ioreqs) {
+ r = -ENOMEM;
+ goto out_nofree;
+ }
r = zd_iowrite32_locked(&mac->chip, 0, CR_BCN_FIFO_SEMAPHORE);
if (r < 0)
@@ -688,6 +737,10 @@
r = zd_ioread32_locked(&mac->chip, &tmp, CR_BCN_FIFO_SEMAPHORE);
if (r < 0)
goto release_sema;
+ if (in_intr && tmp & 0x2) {
+ r = -EBUSY;
+ goto release_sema;
+ }
end_jiffies = jiffies + HZ / 2; /*~500ms*/
message_jiffies = jiffies + HZ / 10; /*~100ms*/
@@ -742,7 +795,7 @@
end_jiffies = jiffies + HZ / 2; /*~500ms*/
ret = zd_iowrite32_locked(&mac->chip, 1, CR_BCN_FIFO_SEMAPHORE);
while (ret < 0) {
- if (time_is_before_eq_jiffies(end_jiffies)) {
+ if (in_intr || time_is_before_eq_jiffies(end_jiffies)) {
ret = -ETIMEDOUT;
break;
}
@@ -757,9 +810,19 @@
if (r < 0 || ret < 0) {
if (r >= 0)
r = ret;
+
+ /* We don't know if beacon was written successfully or not,
+ * so clear current. */
+ zd_mac_free_cur_beacon_locked(mac);
+
goto out;
}
+ /* Beacon has now been written successfully, update current. */
+ zd_mac_free_cur_beacon_locked(mac);
+ mac->beacon.cur_beacon = beacon;
+ beacon = NULL;
+
/* 802.11b/g 2.4G CCK 1Mb
* 802.11a, not yet implemented, uses different values (see GPL vendor
* driver)
@@ -767,11 +830,17 @@
r = zd_iowrite32_locked(&mac->chip, 0x00000400 | (full_len << 19),
CR_BCN_PLCP_CFG);
out:
- mutex_unlock(&mac->chip.mutex);
kfree(ioreqs);
+out_nofree:
+ kfree_skb(beacon);
+ mutex_unlock(&mac->chip.mutex);
+
return r;
reset_device:
+ zd_mac_free_cur_beacon_locked(mac);
+ kfree_skb(beacon);
+
mutex_unlock(&mac->chip.mutex);
kfree(ioreqs);
@@ -982,7 +1051,7 @@
stats.freq = zd_channels[_zd_chip_get_channel(&mac->chip) - 1].center_freq;
stats.band = IEEE80211_BAND_2GHZ;
- stats.signal = status->signal_strength;
+ stats.signal = zd_check_signal(hw, status->signal_strength);
rate = zd_rx_rate(buffer, status);
@@ -1057,6 +1126,8 @@
mac->vif = NULL;
zd_set_beacon_interval(&mac->chip, 0, 0, NL80211_IFTYPE_UNSPECIFIED);
zd_write_mac_addr(&mac->chip, NULL);
+
+ zd_mac_free_cur_beacon(mac);
}
static int zd_op_config(struct ieee80211_hw *hw, u32 changed)
@@ -1094,10 +1165,8 @@
* Fetch next beacon so that tim_count is updated.
*/
beacon = ieee80211_beacon_get(mac->hw, mac->vif);
- if (beacon) {
- zd_mac_config_beacon(mac->hw, beacon);
- kfree_skb(beacon);
- }
+ if (beacon)
+ zd_mac_config_beacon(mac->hw, beacon, true);
spin_lock_irq(&mac->lock);
mac->beacon.last_update = jiffies;
@@ -1222,9 +1291,8 @@
if (beacon) {
zd_chip_disable_hwint(&mac->chip);
- zd_mac_config_beacon(hw, beacon);
+ zd_mac_config_beacon(hw, beacon, false);
zd_chip_enable_hwint(&mac->chip);
- kfree_skb(beacon);
}
}
@@ -1361,7 +1429,8 @@
spin_lock_irq(&mac->lock);
interval = mac->beacon.interval;
period = mac->beacon.period;
- timeout = mac->beacon.last_update + msecs_to_jiffies(interval) + HZ;
+ timeout = mac->beacon.last_update +
+ msecs_to_jiffies(interval * 1024 / 1000) * 3;
spin_unlock_irq(&mac->lock);
if (interval > 0 && time_is_before_jiffies(timeout)) {
@@ -1374,8 +1443,9 @@
beacon = ieee80211_beacon_get(mac->hw, mac->vif);
if (beacon) {
- zd_mac_config_beacon(mac->hw, beacon);
- kfree_skb(beacon);
+ zd_mac_free_cur_beacon(mac);
+
+ zd_mac_config_beacon(mac->hw, beacon, false);
}
zd_set_beacon_interval(&mac->chip, interval, period, mac->type);
@@ -1410,6 +1480,8 @@
{
dev_dbg_f(zd_mac_dev(mac), "\n");
cancel_delayed_work_sync(&mac->beacon.watchdog_work);
+
+ zd_mac_free_cur_beacon(mac);
}
#define LINK_LED_WORK_DELAY HZ
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.h b/drivers/net/wireless/zd1211rw/zd_mac.h
index f8c93c3..c01eca8 100644
--- a/drivers/net/wireless/zd1211rw/zd_mac.h
+++ b/drivers/net/wireless/zd1211rw/zd_mac.h
@@ -165,6 +165,7 @@
struct beacon {
struct delayed_work watchdog_work;
+ struct sk_buff *cur_beacon;
unsigned long last_update;
u16 interval;
u8 period;
diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c
index 631194d..cf0d69d 100644
--- a/drivers/net/wireless/zd1211rw/zd_usb.c
+++ b/drivers/net/wireless/zd1211rw/zd_usb.c
@@ -111,6 +111,9 @@
#define FW_ZD1211_PREFIX "zd1211/zd1211_"
#define FW_ZD1211B_PREFIX "zd1211/zd1211b_"
+static bool check_read_regs(struct zd_usb *usb, struct usb_req_read_regs *req,
+ unsigned int count);
+
/* USB device initialization */
static void int_urb_complete(struct urb *urb);
@@ -365,6 +368,20 @@
#define urb_dev(urb) (&(urb)->dev->dev)
+static inline void handle_regs_int_override(struct urb *urb)
+{
+ struct zd_usb *usb = urb->context;
+ struct zd_usb_interrupt *intr = &usb->intr;
+
+ spin_lock(&intr->lock);
+ if (atomic_read(&intr->read_regs_enabled)) {
+ atomic_set(&intr->read_regs_enabled, 0);
+ intr->read_regs_int_overridden = 1;
+ complete(&intr->read_regs.completion);
+ }
+ spin_unlock(&intr->lock);
+}
+
static inline void handle_regs_int(struct urb *urb)
{
struct zd_usb *usb = urb->context;
@@ -383,25 +400,45 @@
USB_MAX_EP_INT_BUFFER);
spin_unlock(&mac->lock);
schedule_work(&mac->process_intr);
- } else if (intr->read_regs_enabled) {
- intr->read_regs.length = len = urb->actual_length;
-
+ } else if (atomic_read(&intr->read_regs_enabled)) {
+ len = urb->actual_length;
+ intr->read_regs.length = urb->actual_length;
if (len > sizeof(intr->read_regs.buffer))
len = sizeof(intr->read_regs.buffer);
+
memcpy(intr->read_regs.buffer, urb->transfer_buffer, len);
- intr->read_regs_enabled = 0;
+
+ /* Sometimes USB_INT_ID_REGS is not overridden, but comes after
+ * USB_INT_ID_RETRY_FAILED. Read-reg retry then gets this
+ * delayed USB_INT_ID_REGS, but leaves USB_INT_ID_REGS of
+ * retry unhandled. Next read-reg command then might catch
+ * this wrong USB_INT_ID_REGS. Fix by ignoring wrong reads.
+ */
+ if (!check_read_regs(usb, intr->read_regs.req,
+ intr->read_regs.req_count))
+ goto out;
+
+ atomic_set(&intr->read_regs_enabled, 0);
+ intr->read_regs_int_overridden = 0;
complete(&intr->read_regs.completion);
+
goto out;
}
out:
spin_unlock(&intr->lock);
+
+ /* CR_INTERRUPT might override read_reg too. */
+ if (int_num == CR_INTERRUPT && atomic_read(&intr->read_regs_enabled))
+ handle_regs_int_override(urb);
}
static void int_urb_complete(struct urb *urb)
{
int r;
struct usb_int_header *hdr;
+ struct zd_usb *usb;
+ struct zd_usb_interrupt *intr;
switch (urb->status) {
case 0:
@@ -430,6 +467,14 @@
goto resubmit;
}
+ /* USB_INT_ID_RETRY_FAILED triggered by tx-urb submit can override
+ * pending USB_INT_ID_REGS causing read command timeout.
+ */
+ usb = urb->context;
+ intr = &usb->intr;
+ if (hdr->id != USB_INT_ID_REGS && atomic_read(&intr->read_regs_enabled))
+ handle_regs_int_override(urb);
+
switch (hdr->id) {
case USB_INT_ID_REGS:
handle_regs_int(urb);
@@ -579,8 +624,8 @@
if (length < sizeof(struct rx_length_info)) {
/* It's not a complete packet anyhow. */
- printk("%s: invalid, small RX packet : %d\n",
- __func__, length);
+ dev_dbg_f(zd_usb_dev(usb), "invalid, small RX packet : %d\n",
+ length);
return;
}
length_info = (struct rx_length_info *)
@@ -1129,6 +1174,7 @@
spin_lock_init(&intr->lock);
intr->interval = int_urb_interval(zd_usb_to_usbdev(usb));
init_completion(&intr->read_regs.completion);
+ atomic_set(&intr->read_regs_enabled, 0);
intr->read_regs.cr_int_addr = cpu_to_le16((u16)CR_INTERRUPT);
}
@@ -1563,12 +1609,16 @@
return sizeof(struct usb_int_regs) + count * sizeof(struct reg_data);
}
-static void prepare_read_regs_int(struct zd_usb *usb)
+static void prepare_read_regs_int(struct zd_usb *usb,
+ struct usb_req_read_regs *req,
+ unsigned int count)
{
struct zd_usb_interrupt *intr = &usb->intr;
spin_lock_irq(&intr->lock);
- intr->read_regs_enabled = 1;
+ atomic_set(&intr->read_regs_enabled, 1);
+ intr->read_regs.req = req;
+ intr->read_regs.req_count = count;
INIT_COMPLETION(intr->read_regs.completion);
spin_unlock_irq(&intr->lock);
}
@@ -1578,12 +1628,52 @@
struct zd_usb_interrupt *intr = &usb->intr;
spin_lock_irq(&intr->lock);
- intr->read_regs_enabled = 0;
+ atomic_set(&intr->read_regs_enabled, 0);
spin_unlock_irq(&intr->lock);
}
+static bool check_read_regs(struct zd_usb *usb, struct usb_req_read_regs *req,
+ unsigned int count)
+{
+ int i;
+ struct zd_usb_interrupt *intr = &usb->intr;
+ struct read_regs_int *rr = &intr->read_regs;
+ struct usb_int_regs *regs = (struct usb_int_regs *)rr->buffer;
+
+ /* The created block size seems to be larger than expected.
+ * However results appear to be correct.
+ */
+ if (rr->length < usb_int_regs_length(count)) {
+ dev_dbg_f(zd_usb_dev(usb),
+ "error: actual length %d less than expected %d\n",
+ rr->length, usb_int_regs_length(count));
+ return false;
+ }
+
+ if (rr->length > sizeof(rr->buffer)) {
+ dev_dbg_f(zd_usb_dev(usb),
+ "error: actual length %d exceeds buffer size %zu\n",
+ rr->length, sizeof(rr->buffer));
+ return false;
+ }
+
+ for (i = 0; i < count; i++) {
+ struct reg_data *rd = ®s->regs[i];
+ if (rd->addr != req->addr[i]) {
+ dev_dbg_f(zd_usb_dev(usb),
+ "rd[%d] addr %#06hx expected %#06hx\n", i,
+ le16_to_cpu(rd->addr),
+ le16_to_cpu(req->addr[i]));
+ return false;
+ }
+ }
+
+ return true;
+}
+
static int get_results(struct zd_usb *usb, u16 *values,
- struct usb_req_read_regs *req, unsigned int count)
+ struct usb_req_read_regs *req, unsigned int count,
+ bool *retry)
{
int r;
int i;
@@ -1594,31 +1684,19 @@
spin_lock_irq(&intr->lock);
r = -EIO;
- /* The created block size seems to be larger than expected.
- * However results appear to be correct.
- */
- if (rr->length < usb_int_regs_length(count)) {
- dev_dbg_f(zd_usb_dev(usb),
- "error: actual length %d less than expected %d\n",
- rr->length, usb_int_regs_length(count));
+
+ /* Read failed because firmware bug? */
+ *retry = !!intr->read_regs_int_overridden;
+ if (*retry)
goto error_unlock;
- }
- if (rr->length > sizeof(rr->buffer)) {
- dev_dbg_f(zd_usb_dev(usb),
- "error: actual length %d exceeds buffer size %zu\n",
- rr->length, sizeof(rr->buffer));
+
+ if (!check_read_regs(usb, req, count)) {
+ dev_dbg_f(zd_usb_dev(usb), "error: invalid read regs\n");
goto error_unlock;
}
for (i = 0; i < count; i++) {
struct reg_data *rd = ®s->regs[i];
- if (rd->addr != req->addr[i]) {
- dev_dbg_f(zd_usb_dev(usb),
- "rd[%d] addr %#06hx expected %#06hx\n", i,
- le16_to_cpu(rd->addr),
- le16_to_cpu(req->addr[i]));
- goto error_unlock;
- }
values[i] = le16_to_cpu(rd->value);
}
@@ -1631,11 +1709,11 @@
int zd_usb_ioread16v(struct zd_usb *usb, u16 *values,
const zd_addr_t *addresses, unsigned int count)
{
- int r;
- int i, req_len, actual_req_len;
+ int r, i, req_len, actual_req_len, try_count = 0;
struct usb_device *udev;
struct usb_req_read_regs *req = NULL;
unsigned long timeout;
+ bool retry = false;
if (count < 1) {
dev_dbg_f(zd_usb_dev(usb), "error: count is zero\n");
@@ -1671,8 +1749,10 @@
for (i = 0; i < count; i++)
req->addr[i] = cpu_to_le16((u16)addresses[i]);
+retry_read:
+ try_count++;
udev = zd_usb_to_usbdev(usb);
- prepare_read_regs_int(usb);
+ prepare_read_regs_int(usb, req, count);
r = zd_ep_regs_out_msg(udev, req, req_len, &actual_req_len, 50 /*ms*/);
if (r) {
dev_dbg_f(zd_usb_dev(usb),
@@ -1696,7 +1776,12 @@
goto error;
}
- r = get_results(usb, values, req, count);
+ r = get_results(usb, values, req, count, &retry);
+ if (retry && try_count < 20) {
+ dev_dbg_f(zd_usb_dev(usb), "read retry, tries so far: %d\n",
+ try_count);
+ goto retry_read;
+ }
error:
return r;
}
diff --git a/drivers/net/wireless/zd1211rw/zd_usb.h b/drivers/net/wireless/zd1211rw/zd_usb.h
index bf94284..99193b4 100644
--- a/drivers/net/wireless/zd1211rw/zd_usb.h
+++ b/drivers/net/wireless/zd1211rw/zd_usb.h
@@ -144,6 +144,8 @@
struct read_regs_int {
struct completion completion;
+ struct usb_req_read_regs *req;
+ unsigned int req_count;
/* Stores the USB int structure and contains the USB address of the
* first requested register before request.
*/
@@ -169,7 +171,8 @@
void *buffer;
dma_addr_t buffer_dma;
int interval;
- u8 read_regs_enabled:1;
+ atomic_t read_regs_enabled;
+ u8 read_regs_int_overridden:1;
};
static inline struct usb_int_regs *get_read_regs(struct zd_usb_interrupt *intr)
diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c
index 0e4851b..fd00f25 100644
--- a/drivers/net/xen-netback/netback.c
+++ b/drivers/net/xen-netback/netback.c
@@ -1743,3 +1743,4 @@
module_init(netback_init);
MODULE_LICENSE("Dual BSD/GPL");
+MODULE_ALIAS("xen-backend:vif");
diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c
index d29365a..d7c8a98 100644
--- a/drivers/net/xen-netfront.c
+++ b/drivers/net/xen-netfront.c
@@ -70,6 +70,14 @@
#define NET_RX_RING_SIZE __CONST_RING_SIZE(xen_netif_rx, PAGE_SIZE)
#define TX_MAX_TARGET min_t(int, NET_RX_RING_SIZE, 256)
+struct netfront_stats {
+ u64 rx_packets;
+ u64 tx_packets;
+ u64 rx_bytes;
+ u64 tx_bytes;
+ struct u64_stats_sync syncp;
+};
+
struct netfront_info {
struct list_head list;
struct net_device *netdev;
@@ -122,6 +130,8 @@
struct mmu_update rx_mmu[NET_RX_RING_SIZE];
/* Statistics */
+ struct netfront_stats __percpu *stats;
+
unsigned long rx_gso_checksum_fixup;
};
@@ -468,6 +478,7 @@
{
unsigned short id;
struct netfront_info *np = netdev_priv(dev);
+ struct netfront_stats *stats = this_cpu_ptr(np->stats);
struct xen_netif_tx_request *tx;
struct xen_netif_extra_info *extra;
char *data = skb->data;
@@ -552,8 +563,10 @@
if (notify)
notify_remote_via_irq(np->netdev->irq);
- dev->stats.tx_bytes += skb->len;
- dev->stats.tx_packets++;
+ u64_stats_update_begin(&stats->syncp);
+ stats->tx_bytes += skb->len;
+ stats->tx_packets++;
+ u64_stats_update_end(&stats->syncp);
/* Note: It is not safe to access skb after xennet_tx_buf_gc()! */
xennet_tx_buf_gc(dev);
@@ -847,6 +860,8 @@
static int handle_incoming_queue(struct net_device *dev,
struct sk_buff_head *rxq)
{
+ struct netfront_info *np = netdev_priv(dev);
+ struct netfront_stats *stats = this_cpu_ptr(np->stats);
int packets_dropped = 0;
struct sk_buff *skb;
@@ -871,8 +886,10 @@
continue;
}
- dev->stats.rx_packets++;
- dev->stats.rx_bytes += skb->len;
+ u64_stats_update_begin(&stats->syncp);
+ stats->rx_packets++;
+ stats->rx_bytes += skb->len;
+ u64_stats_update_end(&stats->syncp);
/* Pass it up. */
netif_receive_skb(skb);
@@ -1034,6 +1051,38 @@
return 0;
}
+static struct rtnl_link_stats64 *xennet_get_stats64(struct net_device *dev,
+ struct rtnl_link_stats64 *tot)
+{
+ struct netfront_info *np = netdev_priv(dev);
+ int cpu;
+
+ for_each_possible_cpu(cpu) {
+ struct netfront_stats *stats = per_cpu_ptr(np->stats, cpu);
+ u64 rx_packets, rx_bytes, tx_packets, tx_bytes;
+ unsigned int start;
+
+ do {
+ start = u64_stats_fetch_begin_bh(&stats->syncp);
+
+ rx_packets = stats->rx_packets;
+ tx_packets = stats->tx_packets;
+ rx_bytes = stats->rx_bytes;
+ tx_bytes = stats->tx_bytes;
+ } while (u64_stats_fetch_retry_bh(&stats->syncp, start));
+
+ tot->rx_packets += rx_packets;
+ tot->tx_packets += tx_packets;
+ tot->rx_bytes += rx_bytes;
+ tot->tx_bytes += tx_bytes;
+ }
+
+ tot->rx_errors = dev->stats.rx_errors;
+ tot->tx_dropped = dev->stats.tx_dropped;
+
+ return tot;
+}
+
static void xennet_release_tx_bufs(struct netfront_info *np)
{
struct sk_buff *skb;
@@ -1182,6 +1231,7 @@
.ndo_stop = xennet_close,
.ndo_start_xmit = xennet_start_xmit,
.ndo_change_mtu = xennet_change_mtu,
+ .ndo_get_stats64 = xennet_get_stats64,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
.ndo_fix_features = xennet_fix_features,
@@ -1216,6 +1266,11 @@
np->rx_refill_timer.data = (unsigned long)netdev;
np->rx_refill_timer.function = rx_refill_timeout;
+ err = -ENOMEM;
+ np->stats = alloc_percpu(struct netfront_stats);
+ if (np->stats == NULL)
+ goto exit;
+
/* Initialise tx_skbs as a free chain containing every entry. */
np->tx_skb_freelist = 0;
for (i = 0; i < NET_TX_RING_SIZE; i++) {
@@ -1234,7 +1289,7 @@
&np->gref_tx_head) < 0) {
printk(KERN_ALERT "#### netfront can't alloc tx grant refs\n");
err = -ENOMEM;
- goto exit;
+ goto exit_free_stats;
}
/* A grant for every rx ring slot */
if (gnttab_alloc_grant_references(RX_MAX_TARGET,
@@ -1270,6 +1325,8 @@
exit_free_tx:
gnttab_free_grant_references(np->gref_tx_head);
+ exit_free_stats:
+ free_percpu(np->stats);
exit:
free_netdev(netdev);
return ERR_PTR(err);
@@ -1869,6 +1926,8 @@
xennet_sysfs_delif(info->netdev);
+ free_percpu(info->stats);
+
free_netdev(info->netdev);
return 0;
diff --git a/drivers/net/xilinx_emaclite.c b/drivers/net/xilinx_emaclite.c
index 372572c..8018d7d 100644
--- a/drivers/net/xilinx_emaclite.c
+++ b/drivers/net/xilinx_emaclite.c
@@ -26,6 +26,7 @@
#include <linux/of_mdio.h>
#include <linux/of_net.h>
#include <linux/phy.h>
+#include <linux/interrupt.h>
#define DRIVER_NAME "xilinx_emaclite"
@@ -251,11 +252,11 @@
u16 *from_u16_ptr, *to_u16_ptr;
to_u32_ptr = dest_ptr;
- from_u16_ptr = (u16 *) src_ptr;
+ from_u16_ptr = src_ptr;
align_buffer = 0;
for (; length > 3; length -= 4) {
- to_u16_ptr = (u16 *) ((void *) &align_buffer);
+ to_u16_ptr = (u16 *)&align_buffer;
*to_u16_ptr++ = *from_u16_ptr++;
*to_u16_ptr++ = *from_u16_ptr++;
@@ -647,7 +648,8 @@
dev->stats.rx_packets++;
dev->stats.rx_bytes += len;
- netif_rx(skb); /* Send the packet upstream */
+ if (!skb_defer_rx_timestamp(skb))
+ netif_rx(skb); /* Send the packet upstream */
}
/**
@@ -1029,15 +1031,19 @@
spin_lock_irqsave(&lp->reset_lock, flags);
if (xemaclite_send_data(lp, (u8 *) new_skb->data, len) != 0) {
/* If the Emaclite Tx buffer is busy, stop the Tx queue and
- * defer the skb for transmission at a later point when the
+ * defer the skb for transmission during the ISR, after the
* current transmission is complete */
netif_stop_queue(dev);
lp->deferred_skb = new_skb;
+ /* Take the time stamp now, since we can't do this in an ISR. */
+ skb_tx_timestamp(new_skb);
spin_unlock_irqrestore(&lp->reset_lock, flags);
return 0;
}
spin_unlock_irqrestore(&lp->reset_lock, flags);
+ skb_tx_timestamp(new_skb);
+
dev->stats.tx_bytes += len;
dev_kfree_skb(new_skb);
diff --git a/drivers/net/yellowfin.c b/drivers/net/yellowfin.c
index ec47e22..3e5ac60 100644
--- a/drivers/net/yellowfin.c
+++ b/drivers/net/yellowfin.c
@@ -442,19 +442,19 @@
ring_space = pci_alloc_consistent(pdev, TX_TOTAL_SIZE, &ring_dma);
if (!ring_space)
goto err_out_cleardev;
- np->tx_ring = (struct yellowfin_desc *)ring_space;
+ np->tx_ring = ring_space;
np->tx_ring_dma = ring_dma;
ring_space = pci_alloc_consistent(pdev, RX_TOTAL_SIZE, &ring_dma);
if (!ring_space)
goto err_out_unmap_tx;
- np->rx_ring = (struct yellowfin_desc *)ring_space;
+ np->rx_ring = ring_space;
np->rx_ring_dma = ring_dma;
ring_space = pci_alloc_consistent(pdev, STATUS_TOTAL_SIZE, &ring_dma);
if (!ring_space)
goto err_out_unmap_rx;
- np->tx_status = (struct tx_status_words *)ring_space;
+ np->tx_status = ring_space;
np->tx_status_dma = ring_dma;
if (dev->mem_start)
diff --git a/drivers/net/znet.c b/drivers/net/znet.c
index ec2800f..8b88817 100644
--- a/drivers/net/znet.c
+++ b/drivers/net/znet.c
@@ -731,7 +731,7 @@
cur_frame_end_offset -= ((count + 1)>>1) + 3;
if (cur_frame_end_offset < 0)
cur_frame_end_offset += RX_BUF_SIZE/2;
- };
+ }
/* Now step forward through the list. */
do {
diff --git a/drivers/net/zorro8390.c b/drivers/net/zorro8390.c
index 8c7c522..15e7751a 100644
--- a/drivers/net/zorro8390.c
+++ b/drivers/net/zorro8390.c
@@ -19,6 +19,8 @@
* Ethernet Controllers.
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/errno.h>
@@ -34,115 +36,242 @@
#include <asm/amigaints.h>
#include <asm/amigahw.h>
-#define EI_SHIFT(x) (ei_local->reg_offset[x])
-#define ei_inb(port) in_8(port)
-#define ei_outb(val,port) out_8(port,val)
-#define ei_inb_p(port) in_8(port)
-#define ei_outb_p(val,port) out_8(port,val)
+#define EI_SHIFT(x) (ei_local->reg_offset[x])
+#define ei_inb(port) in_8(port)
+#define ei_outb(val, port) out_8(port, val)
+#define ei_inb_p(port) in_8(port)
+#define ei_outb_p(val, port) out_8(port, val)
static const char version[] =
- "8390.c:v1.10cvs 9/23/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
+ "8390.c:v1.10cvs 9/23/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
#include "lib8390.c"
#define DRV_NAME "zorro8390"
#define NE_BASE (dev->base_addr)
-#define NE_CMD (0x00*2)
-#define NE_DATAPORT (0x10*2) /* NatSemi-defined port window offset. */
-#define NE_RESET (0x1f*2) /* Issue a read to reset, a write to clear. */
-#define NE_IO_EXTENT (0x20*2)
+#define NE_CMD (0x00 * 2)
+#define NE_DATAPORT (0x10 * 2) /* NatSemi-defined port window offset */
+#define NE_RESET (0x1f * 2) /* Issue a read to reset,
+ * a write to clear. */
+#define NE_IO_EXTENT (0x20 * 2)
-#define NE_EN0_ISR (0x07*2)
-#define NE_EN0_DCFG (0x0e*2)
+#define NE_EN0_ISR (0x07 * 2)
+#define NE_EN0_DCFG (0x0e * 2)
-#define NE_EN0_RSARLO (0x08*2)
-#define NE_EN0_RSARHI (0x09*2)
-#define NE_EN0_RCNTLO (0x0a*2)
-#define NE_EN0_RXCR (0x0c*2)
-#define NE_EN0_TXCR (0x0d*2)
-#define NE_EN0_RCNTHI (0x0b*2)
-#define NE_EN0_IMR (0x0f*2)
+#define NE_EN0_RSARLO (0x08 * 2)
+#define NE_EN0_RSARHI (0x09 * 2)
+#define NE_EN0_RCNTLO (0x0a * 2)
+#define NE_EN0_RXCR (0x0c * 2)
+#define NE_EN0_TXCR (0x0d * 2)
+#define NE_EN0_RCNTHI (0x0b * 2)
+#define NE_EN0_IMR (0x0f * 2)
#define NESM_START_PG 0x40 /* First page of TX buffer */
#define NESM_STOP_PG 0x80 /* Last page +1 of RX ring */
-
-#define WORDSWAP(a) ((((a)>>8)&0xff) | ((a)<<8))
-
+#define WORDSWAP(a) ((((a) >> 8) & 0xff) | ((a) << 8))
static struct card_info {
- zorro_id id;
- const char *name;
- unsigned int offset;
+ zorro_id id;
+ const char *name;
+ unsigned int offset;
} cards[] __devinitdata = {
- { ZORRO_PROD_VILLAGE_TRONIC_ARIADNE2, "Ariadne II", 0x0600 },
- { ZORRO_PROD_INDIVIDUAL_COMPUTERS_X_SURF, "X-Surf", 0x8600 },
+ { ZORRO_PROD_VILLAGE_TRONIC_ARIADNE2, "Ariadne II", 0x0600 },
+ { ZORRO_PROD_INDIVIDUAL_COMPUTERS_X_SURF, "X-Surf", 0x8600 },
};
-static int __devinit zorro8390_init_one(struct zorro_dev *z,
- const struct zorro_device_id *ent);
-static int __devinit zorro8390_init(struct net_device *dev,
- unsigned long board, const char *name,
- unsigned long ioaddr);
-static int zorro8390_open(struct net_device *dev);
-static int zorro8390_close(struct net_device *dev);
-static void zorro8390_reset_8390(struct net_device *dev);
+/* 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 zorro8390_reset_8390(struct net_device *dev)
+{
+ unsigned long reset_start_time = jiffies;
+
+ if (ei_debug > 1)
+ netdev_dbg(dev, "resetting - t=%ld...\n", jiffies);
+
+ z_writeb(z_readb(NE_BASE + NE_RESET), NE_BASE + NE_RESET);
+
+ ei_status.txing = 0;
+ ei_status.dmaing = 0;
+
+ /* This check _should_not_ be necessary, omit eventually. */
+ while ((z_readb(NE_BASE + 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;
+ }
+ z_writeb(ENISR_RESET, NE_BASE + NE_EN0_ISR); /* Ack intr */
+}
+
+/* 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 zorro8390_get_8390_hdr(struct net_device *dev,
- struct e8390_pkt_hdr *hdr, int ring_page);
+ struct e8390_pkt_hdr *hdr, int ring_page)
+{
+ int nic_base = dev->base_addr;
+ int cnt;
+ short *ptrs;
+
+ /* This *shouldn't* happen.
+ * If it does, it's the last thing you'll see
+ */
+ if (ei_status.dmaing) {
+ netdev_err(dev, "%s: DMAing conflict [DMAstat:%d][irqlock:%d]\n",
+ __func__, ei_status.dmaing, ei_status.irqlock);
+ return;
+ }
+
+ ei_status.dmaing |= 0x01;
+ z_writeb(E8390_NODMA + E8390_PAGE0 + E8390_START, nic_base + NE_CMD);
+ z_writeb(ENISR_RDC, nic_base + NE_EN0_ISR);
+ z_writeb(sizeof(struct e8390_pkt_hdr), nic_base + NE_EN0_RCNTLO);
+ z_writeb(0, nic_base + NE_EN0_RCNTHI);
+ z_writeb(0, nic_base + NE_EN0_RSARLO); /* On page boundary */
+ z_writeb(ring_page, nic_base + NE_EN0_RSARHI);
+ z_writeb(E8390_RREAD+E8390_START, nic_base + NE_CMD);
+
+ ptrs = (short *)hdr;
+ for (cnt = 0; cnt < sizeof(struct e8390_pkt_hdr) >> 1; cnt++)
+ *ptrs++ = z_readw(NE_BASE + NE_DATAPORT);
+
+ z_writeb(ENISR_RDC, nic_base + NE_EN0_ISR); /* Ack intr */
+
+ hdr->count = WORDSWAP(hdr->count);
+
+ ei_status.dmaing &= ~0x01;
+}
+
+/* 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 zorro8390_block_input(struct net_device *dev, int count,
- struct sk_buff *skb, int ring_offset);
-static void zorro8390_block_output(struct net_device *dev, const int count,
+ struct sk_buff *skb, int ring_offset)
+{
+ int nic_base = dev->base_addr;
+ char *buf = skb->data;
+ short *ptrs;
+ int cnt;
+
+ /* This *shouldn't* happen.
+ * If it does, it's the last thing you'll see
+ */
+ if (ei_status.dmaing) {
+ netdev_err(dev, "%s: DMAing conflict [DMAstat:%d][irqlock:%d]\n",
+ __func__, ei_status.dmaing, ei_status.irqlock);
+ return;
+ }
+ ei_status.dmaing |= 0x01;
+ z_writeb(E8390_NODMA + E8390_PAGE0 + E8390_START, nic_base + NE_CMD);
+ z_writeb(ENISR_RDC, nic_base + NE_EN0_ISR);
+ z_writeb(count & 0xff, nic_base + NE_EN0_RCNTLO);
+ z_writeb(count >> 8, nic_base + NE_EN0_RCNTHI);
+ z_writeb(ring_offset & 0xff, nic_base + NE_EN0_RSARLO);
+ z_writeb(ring_offset >> 8, nic_base + NE_EN0_RSARHI);
+ z_writeb(E8390_RREAD+E8390_START, nic_base + NE_CMD);
+ ptrs = (short *)buf;
+ for (cnt = 0; cnt < count >> 1; cnt++)
+ *ptrs++ = z_readw(NE_BASE + NE_DATAPORT);
+ if (count & 0x01)
+ buf[count - 1] = z_readb(NE_BASE + NE_DATAPORT);
+
+ z_writeb(ENISR_RDC, nic_base + NE_EN0_ISR); /* Ack intr */
+ ei_status.dmaing &= ~0x01;
+}
+
+static void zorro8390_block_output(struct net_device *dev, int count,
const unsigned char *buf,
- const int start_page);
-static void __devexit zorro8390_remove_one(struct zorro_dev *z);
+ const int start_page)
+{
+ int nic_base = NE_BASE;
+ unsigned long dma_start;
+ short *ptrs;
+ int cnt;
+
+ /* Round the count up for word writes. Do we need to do this?
+ * What effect will an odd byte count have on the 8390?
+ * I should check someday.
+ */
+ if (count & 0x01)
+ count++;
+
+ /* This *shouldn't* happen.
+ * If it does, it's the last thing you'll see
+ */
+ if (ei_status.dmaing) {
+ netdev_err(dev, "%s: DMAing conflict [DMAstat:%d][irqlock:%d]\n",
+ __func__, ei_status.dmaing, ei_status.irqlock);
+ return;
+ }
+ ei_status.dmaing |= 0x01;
+ /* We should already be in page 0, but to be safe... */
+ z_writeb(E8390_PAGE0+E8390_START+E8390_NODMA, nic_base + NE_CMD);
+
+ z_writeb(ENISR_RDC, nic_base + NE_EN0_ISR);
+
+ /* Now the normal output. */
+ z_writeb(count & 0xff, nic_base + NE_EN0_RCNTLO);
+ z_writeb(count >> 8, nic_base + NE_EN0_RCNTHI);
+ z_writeb(0x00, nic_base + NE_EN0_RSARLO);
+ z_writeb(start_page, nic_base + NE_EN0_RSARHI);
+
+ z_writeb(E8390_RWRITE + E8390_START, nic_base + NE_CMD);
+ ptrs = (short *)buf;
+ for (cnt = 0; cnt < count >> 1; cnt++)
+ z_writew(*ptrs++, NE_BASE + NE_DATAPORT);
+
+ dma_start = jiffies;
+
+ while ((z_readb(NE_BASE + 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");
+ zorro8390_reset_8390(dev);
+ __NS8390_init(dev, 1);
+ break;
+ }
+
+ z_writeb(ENISR_RDC, nic_base + NE_EN0_ISR); /* Ack intr */
+ ei_status.dmaing &= ~0x01;
+}
+
+static int zorro8390_open(struct net_device *dev)
+{
+ __ei_open(dev);
+ return 0;
+}
+
+static int zorro8390_close(struct net_device *dev)
+{
+ if (ei_debug > 1)
+ netdev_dbg(dev, "Shutting down ethercard\n");
+ __ei_close(dev);
+ return 0;
+}
+
+static void __devexit zorro8390_remove_one(struct zorro_dev *z)
+{
+ struct net_device *dev = zorro_get_drvdata(z);
+
+ unregister_netdev(dev);
+ free_irq(IRQ_AMIGA_PORTS, dev);
+ release_mem_region(ZTWO_PADDR(dev->base_addr), NE_IO_EXTENT * 2);
+ free_netdev(dev);
+}
static struct zorro_device_id zorro8390_zorro_tbl[] __devinitdata = {
- { ZORRO_PROD_VILLAGE_TRONIC_ARIADNE2, },
- { ZORRO_PROD_INDIVIDUAL_COMPUTERS_X_SURF, },
- { 0 }
+ { ZORRO_PROD_VILLAGE_TRONIC_ARIADNE2, },
+ { ZORRO_PROD_INDIVIDUAL_COMPUTERS_X_SURF, },
+ { 0 }
};
MODULE_DEVICE_TABLE(zorro, zorro8390_zorro_tbl);
-static struct zorro_driver zorro8390_driver = {
- .name = "zorro8390",
- .id_table = zorro8390_zorro_tbl,
- .probe = zorro8390_init_one,
- .remove = __devexit_p(zorro8390_remove_one),
-};
-
-static int __devinit zorro8390_init_one(struct zorro_dev *z,
- const struct zorro_device_id *ent)
-{
- struct net_device *dev;
- unsigned long board, ioaddr;
- int err, i;
-
- for (i = ARRAY_SIZE(cards)-1; i >= 0; i--)
- if (z->id == cards[i].id)
- break;
- if (i < 0)
- return -ENODEV;
-
- board = z->resource.start;
- ioaddr = board+cards[i].offset;
- dev = ____alloc_ei_netdev(0);
- if (!dev)
- return -ENOMEM;
- if (!request_mem_region(ioaddr, NE_IO_EXTENT*2, DRV_NAME)) {
- free_netdev(dev);
- return -EBUSY;
- }
- if ((err = zorro8390_init(dev, board, cards[i].name,
- ZTWO_VADDR(ioaddr)))) {
- release_mem_region(ioaddr, NE_IO_EXTENT*2);
- free_netdev(dev);
- return err;
- }
- zorro_set_drvdata(z, dev);
- return 0;
-}
-
static const struct net_device_ops zorro8390_netdev_ops = {
.ndo_open = zorro8390_open,
.ndo_stop = zorro8390_close,
@@ -151,7 +280,7 @@
.ndo_get_stats = __ei_get_stats,
.ndo_set_multicast_list = __ei_set_multicast_list,
.ndo_validate_addr = eth_validate_addr,
- .ndo_set_mac_address = eth_mac_addr,
+ .ndo_set_mac_address = eth_mac_addr,
.ndo_change_mtu = eth_change_mtu,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = __ei_poll,
@@ -162,295 +291,159 @@
unsigned long board, const char *name,
unsigned long ioaddr)
{
- int i;
- int err;
- unsigned char SA_prom[32];
- int start_page, stop_page;
- static u32 zorro8390_offsets[16] = {
- 0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e,
- 0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e,
- };
-
- /* Reset card. Who knows what dain-bramaged state it was left in. */
- {
- unsigned long reset_start_time = jiffies;
-
- z_writeb(z_readb(ioaddr + NE_RESET), ioaddr + NE_RESET);
-
- while ((z_readb(ioaddr + NE_EN0_ISR) & ENISR_RESET) == 0)
- if (time_after(jiffies, reset_start_time + 2*HZ/100)) {
- printk(KERN_WARNING " not found (no reset ack).\n");
- return -ENODEV;
- }
-
- z_writeb(0xff, ioaddr + NE_EN0_ISR); /* Ack all intr. */
- }
-
- /* 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!). */
- {
- struct {
- u32 value;
- u32 offset;
- } program_seq[] = {
- {E8390_NODMA+E8390_PAGE0+E8390_STOP, NE_CMD}, /* Select page 0*/
- {0x48, NE_EN0_DCFG}, /* Set byte-wide (0x48) 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},
+ int i;
+ int err;
+ unsigned char SA_prom[32];
+ int start_page, stop_page;
+ static u32 zorro8390_offsets[16] = {
+ 0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e,
+ 0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e,
};
- for (i = 0; i < ARRAY_SIZE(program_seq); i++) {
- z_writeb(program_seq[i].value, ioaddr + program_seq[i].offset);
- }
- }
- for (i = 0; i < 16; i++) {
- SA_prom[i] = z_readb(ioaddr + NE_DATAPORT);
- (void)z_readb(ioaddr + NE_DATAPORT);
- }
- /* We must set the 8390 for word mode. */
- z_writeb(0x49, ioaddr + NE_EN0_DCFG);
- start_page = NESM_START_PG;
- stop_page = NESM_STOP_PG;
+ /* Reset card. Who knows what dain-bramaged state it was left in. */
+ {
+ unsigned long reset_start_time = jiffies;
- dev->base_addr = ioaddr;
- dev->irq = IRQ_AMIGA_PORTS;
+ z_writeb(z_readb(ioaddr + NE_RESET), ioaddr + NE_RESET);
- /* Install the Interrupt handler */
- i = request_irq(IRQ_AMIGA_PORTS, __ei_interrupt, IRQF_SHARED, DRV_NAME, dev);
- if (i) return i;
+ while ((z_readb(ioaddr + NE_EN0_ISR) & ENISR_RESET) == 0)
+ if (time_after(jiffies,
+ reset_start_time + 2 * HZ / 100)) {
+ netdev_warn(dev, "not found (no reset ack)\n");
+ return -ENODEV;
+ }
- for(i = 0; i < ETHER_ADDR_LEN; i++)
- dev->dev_addr[i] = SA_prom[i];
-
-#ifdef DEBUG
- printk("%pM", dev->dev_addr);
-#endif
-
- ei_status.name = name;
- ei_status.tx_start_page = start_page;
- ei_status.stop_page = stop_page;
- ei_status.word16 = 1;
-
- ei_status.rx_start_page = start_page + TX_PAGES;
-
- ei_status.reset_8390 = &zorro8390_reset_8390;
- ei_status.block_input = &zorro8390_block_input;
- ei_status.block_output = &zorro8390_block_output;
- ei_status.get_8390_hdr = &zorro8390_get_8390_hdr;
- ei_status.reg_offset = zorro8390_offsets;
-
- dev->netdev_ops = &zorro8390_netdev_ops;
- __NS8390_init(dev, 0);
- err = register_netdev(dev);
- if (err) {
- free_irq(IRQ_AMIGA_PORTS, dev);
- return err;
- }
-
- printk(KERN_INFO "%s: %s at 0x%08lx, Ethernet Address %pM\n",
- dev->name, name, board, dev->dev_addr);
-
- return 0;
-}
-
-static int zorro8390_open(struct net_device *dev)
-{
- __ei_open(dev);
- return 0;
-}
-
-static int zorro8390_close(struct net_device *dev)
-{
- if (ei_debug > 1)
- printk(KERN_DEBUG "%s: Shutting down ethercard.\n", dev->name);
- __ei_close(dev);
- return 0;
-}
-
-/* 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 zorro8390_reset_8390(struct net_device *dev)
-{
- unsigned long reset_start_time = jiffies;
-
- if (ei_debug > 1)
- printk(KERN_DEBUG "resetting the 8390 t=%ld...\n", jiffies);
-
- z_writeb(z_readb(NE_BASE + NE_RESET), NE_BASE + NE_RESET);
-
- ei_status.txing = 0;
- ei_status.dmaing = 0;
-
- /* This check _should_not_ be necessary, omit eventually. */
- while ((z_readb(NE_BASE+NE_EN0_ISR) & ENISR_RESET) == 0)
- if (time_after(jiffies, reset_start_time + 2*HZ/100)) {
- printk(KERN_WARNING "%s: ne_reset_8390() did not complete.\n",
- dev->name);
- break;
- }
- z_writeb(ENISR_RESET, NE_BASE + NE_EN0_ISR); /* Ack intr. */
-}
-
-/* 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 zorro8390_get_8390_hdr(struct net_device *dev,
- struct e8390_pkt_hdr *hdr, int ring_page)
-{
- int nic_base = dev->base_addr;
- int cnt;
- short *ptrs;
-
- /* This *shouldn't* happen. If it does, it's the last thing you'll see */
- if (ei_status.dmaing) {
- printk(KERN_ERR "%s: DMAing conflict in ne_get_8390_hdr "
- "[DMAstat:%d][irqlock:%d].\n", dev->name, ei_status.dmaing,
- ei_status.irqlock);
- return;
- }
-
- ei_status.dmaing |= 0x01;
- z_writeb(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD);
- z_writeb(ENISR_RDC, nic_base + NE_EN0_ISR);
- z_writeb(sizeof(struct e8390_pkt_hdr), nic_base + NE_EN0_RCNTLO);
- z_writeb(0, nic_base + NE_EN0_RCNTHI);
- z_writeb(0, nic_base + NE_EN0_RSARLO); /* On page boundary */
- z_writeb(ring_page, nic_base + NE_EN0_RSARHI);
- z_writeb(E8390_RREAD+E8390_START, nic_base + NE_CMD);
-
- ptrs = (short*)hdr;
- for (cnt = 0; cnt < (sizeof(struct e8390_pkt_hdr)>>1); cnt++)
- *ptrs++ = z_readw(NE_BASE + NE_DATAPORT);
-
- z_writeb(ENISR_RDC, nic_base + NE_EN0_ISR); /* Ack intr. */
-
- hdr->count = WORDSWAP(hdr->count);
-
- ei_status.dmaing &= ~0x01;
-}
-
-/* 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 zorro8390_block_input(struct net_device *dev, int count,
- struct sk_buff *skb, int ring_offset)
-{
- int nic_base = dev->base_addr;
- char *buf = skb->data;
- short *ptrs;
- int cnt;
-
- /* This *shouldn't* happen. If it does, it's the last thing you'll see */
- if (ei_status.dmaing) {
- printk(KERN_ERR "%s: DMAing conflict in ne_block_input "
- "[DMAstat:%d][irqlock:%d].\n",
- dev->name, ei_status.dmaing, ei_status.irqlock);
- return;
- }
- ei_status.dmaing |= 0x01;
- z_writeb(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD);
- z_writeb(ENISR_RDC, nic_base + NE_EN0_ISR);
- z_writeb(count & 0xff, nic_base + NE_EN0_RCNTLO);
- z_writeb(count >> 8, nic_base + NE_EN0_RCNTHI);
- z_writeb(ring_offset & 0xff, nic_base + NE_EN0_RSARLO);
- z_writeb(ring_offset >> 8, nic_base + NE_EN0_RSARHI);
- z_writeb(E8390_RREAD+E8390_START, nic_base + NE_CMD);
- ptrs = (short*)buf;
- for (cnt = 0; cnt < (count>>1); cnt++)
- *ptrs++ = z_readw(NE_BASE + NE_DATAPORT);
- if (count & 0x01)
- buf[count-1] = z_readb(NE_BASE + NE_DATAPORT);
-
- z_writeb(ENISR_RDC, nic_base + NE_EN0_ISR); /* Ack intr. */
- ei_status.dmaing &= ~0x01;
-}
-
-static void zorro8390_block_output(struct net_device *dev, int count,
- const unsigned char *buf,
- const int start_page)
-{
- int nic_base = NE_BASE;
- unsigned long dma_start;
- short *ptrs;
- int cnt;
-
- /* Round the count up for word writes. Do we need to do this?
- What effect will an odd byte count have on the 8390?
- I should check someday. */
- if (count & 0x01)
- count++;
-
- /* This *shouldn't* happen. If it does, it's the last thing you'll see */
- if (ei_status.dmaing) {
- printk(KERN_ERR "%s: DMAing conflict in ne_block_output."
- "[DMAstat:%d][irqlock:%d]\n", dev->name, ei_status.dmaing,
- ei_status.irqlock);
- return;
- }
- ei_status.dmaing |= 0x01;
- /* We should already be in page 0, but to be safe... */
- z_writeb(E8390_PAGE0+E8390_START+E8390_NODMA, nic_base + NE_CMD);
-
- z_writeb(ENISR_RDC, nic_base + NE_EN0_ISR);
-
- /* Now the normal output. */
- z_writeb(count & 0xff, nic_base + NE_EN0_RCNTLO);
- z_writeb(count >> 8, nic_base + NE_EN0_RCNTHI);
- z_writeb(0x00, nic_base + NE_EN0_RSARLO);
- z_writeb(start_page, nic_base + NE_EN0_RSARHI);
-
- z_writeb(E8390_RWRITE+E8390_START, nic_base + NE_CMD);
- ptrs = (short*)buf;
- for (cnt = 0; cnt < count>>1; cnt++)
- z_writew(*ptrs++, NE_BASE+NE_DATAPORT);
-
- dma_start = jiffies;
-
- while ((z_readb(NE_BASE + NE_EN0_ISR) & ENISR_RDC) == 0)
- if (time_after(jiffies, dma_start + 2*HZ/100)) { /* 20ms */
- printk(KERN_ERR "%s: timeout waiting for Tx RDC.\n",
- dev->name);
- zorro8390_reset_8390(dev);
- __NS8390_init(dev,1);
- break;
+ z_writeb(0xff, ioaddr + NE_EN0_ISR); /* Ack all intr. */
}
- z_writeb(ENISR_RDC, nic_base + NE_EN0_ISR); /* Ack intr. */
- ei_status.dmaing &= ~0x01;
+ /* 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++)
+ z_writeb(program_seq[i].value,
+ ioaddr + program_seq[i].offset);
+ }
+ for (i = 0; i < 16; i++) {
+ SA_prom[i] = z_readb(ioaddr + NE_DATAPORT);
+ (void)z_readb(ioaddr + NE_DATAPORT);
+ }
+
+ /* We must set the 8390 for word mode. */
+ z_writeb(0x49, ioaddr + NE_EN0_DCFG);
+ start_page = NESM_START_PG;
+ stop_page = NESM_STOP_PG;
+
+ dev->base_addr = ioaddr;
+ dev->irq = IRQ_AMIGA_PORTS;
+
+ /* Install the Interrupt handler */
+ i = request_irq(IRQ_AMIGA_PORTS, __ei_interrupt,
+ IRQF_SHARED, DRV_NAME, dev);
+ if (i)
+ return i;
+
+ for (i = 0; i < ETHER_ADDR_LEN; i++)
+ dev->dev_addr[i] = SA_prom[i];
+
+ pr_debug("Found ethernet address: %pM\n", dev->dev_addr);
+
+ ei_status.name = name;
+ ei_status.tx_start_page = start_page;
+ ei_status.stop_page = stop_page;
+ ei_status.word16 = 1;
+
+ ei_status.rx_start_page = start_page + TX_PAGES;
+
+ ei_status.reset_8390 = zorro8390_reset_8390;
+ ei_status.block_input = zorro8390_block_input;
+ ei_status.block_output = zorro8390_block_output;
+ ei_status.get_8390_hdr = zorro8390_get_8390_hdr;
+ ei_status.reg_offset = zorro8390_offsets;
+
+ dev->netdev_ops = &zorro8390_netdev_ops;
+ __NS8390_init(dev, 0);
+ err = register_netdev(dev);
+ if (err) {
+ free_irq(IRQ_AMIGA_PORTS, dev);
+ return err;
+ }
+
+ netdev_info(dev, "%s at 0x%08lx, Ethernet Address %pM\n",
+ name, board, dev->dev_addr);
+
+ return 0;
}
-static void __devexit zorro8390_remove_one(struct zorro_dev *z)
+static int __devinit zorro8390_init_one(struct zorro_dev *z,
+ const struct zorro_device_id *ent)
{
- struct net_device *dev = zorro_get_drvdata(z);
+ struct net_device *dev;
+ unsigned long board, ioaddr;
+ int err, i;
- unregister_netdev(dev);
- free_irq(IRQ_AMIGA_PORTS, dev);
- release_mem_region(ZTWO_PADDR(dev->base_addr), NE_IO_EXTENT*2);
- free_netdev(dev);
+ for (i = ARRAY_SIZE(cards) - 1; i >= 0; i--)
+ if (z->id == cards[i].id)
+ break;
+ if (i < 0)
+ return -ENODEV;
+
+ board = z->resource.start;
+ ioaddr = board + cards[i].offset;
+ dev = ____alloc_ei_netdev(0);
+ if (!dev)
+ return -ENOMEM;
+ if (!request_mem_region(ioaddr, NE_IO_EXTENT * 2, DRV_NAME)) {
+ free_netdev(dev);
+ return -EBUSY;
+ }
+ err = zorro8390_init(dev, board, cards[i].name, ZTWO_VADDR(ioaddr));
+ if (err) {
+ release_mem_region(ioaddr, NE_IO_EXTENT * 2);
+ free_netdev(dev);
+ return err;
+ }
+ zorro_set_drvdata(z, dev);
+ return 0;
}
+static struct zorro_driver zorro8390_driver = {
+ .name = "zorro8390",
+ .id_table = zorro8390_zorro_tbl,
+ .probe = zorro8390_init_one,
+ .remove = __devexit_p(zorro8390_remove_one),
+};
+
static int __init zorro8390_init_module(void)
{
- return zorro_register_driver(&zorro8390_driver);
+ return zorro_register_driver(&zorro8390_driver);
}
static void __exit zorro8390_cleanup_module(void)
{
- zorro_unregister_driver(&zorro8390_driver);
+ zorro_unregister_driver(&zorro8390_driver);
}
module_init(zorro8390_init_module);
diff --git a/drivers/s390/net/ctcm_mpc.h b/drivers/s390/net/ctcm_mpc.h
index 5336120..1fa07b0 100644
--- a/drivers/s390/net/ctcm_mpc.h
+++ b/drivers/s390/net/ctcm_mpc.h
@@ -12,6 +12,7 @@
#ifndef _CTC_MPC_H_
#define _CTC_MPC_H_
+#include <linux/interrupt.h>
#include <linux/skbuff.h>
#include "fsm.h"
diff --git a/drivers/scsi/bnx2fc/57xx_hsi_bnx2fc.h b/drivers/scsi/bnx2fc/57xx_hsi_bnx2fc.h
index 97a61b4..e1f1e34 100644
--- a/drivers/scsi/bnx2fc/57xx_hsi_bnx2fc.h
+++ b/drivers/scsi/bnx2fc/57xx_hsi_bnx2fc.h
@@ -19,6 +19,23 @@
/*
* doorbell message sent to the chip
*/
+struct b577xx_doorbell {
+#if defined(__BIG_ENDIAN)
+ u16 zero_fill2;
+ u8 zero_fill1;
+ struct b577xx_doorbell_hdr header;
+#elif defined(__LITTLE_ENDIAN)
+ struct b577xx_doorbell_hdr header;
+ u8 zero_fill1;
+ u16 zero_fill2;
+#endif
+};
+
+
+
+/*
+ * doorbell message sent to the chip
+ */
struct b577xx_doorbell_set_prod {
#if defined(__BIG_ENDIAN)
u16 prod;
@@ -39,106 +56,63 @@
/*
- * Fixed size structure in order to plant it in Union structure
+ * ABTS info $$KEEP_ENDIANNESS$$
*/
-struct fcoe_abts_rsp_union {
- u32 r_ctl;
- u32 abts_rsp_payload[7];
+struct fcoe_abts_info {
+ __le16 aborted_task_id;
+ __le16 reserved0;
+ __le32 reserved1;
};
/*
- * 4 regs size
+ * Fixed size structure in order to plant it in Union structure
+ * $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_abts_rsp_union {
+ u8 r_ctl;
+ u8 rsrv[3];
+ __le32 abts_rsp_payload[7];
+};
+
+
+/*
+ * 4 regs size $$KEEP_ENDIANNESS$$
*/
struct fcoe_bd_ctx {
- u32 buf_addr_hi;
- u32 buf_addr_lo;
-#if defined(__BIG_ENDIAN)
- u16 rsrv0;
- u16 buf_len;
-#elif defined(__LITTLE_ENDIAN)
- u16 buf_len;
- u16 rsrv0;
-#endif
-#if defined(__BIG_ENDIAN)
- u16 rsrv1;
- u16 flags;
-#elif defined(__LITTLE_ENDIAN)
- u16 flags;
- u16 rsrv1;
-#endif
+ __le32 buf_addr_hi;
+ __le32 buf_addr_lo;
+ __le16 buf_len;
+ __le16 rsrv0;
+ __le16 flags;
+ __le16 rsrv1;
};
-struct fcoe_cleanup_flow_info {
-#if defined(__BIG_ENDIAN)
- u16 reserved1;
- u16 task_id;
-#elif defined(__LITTLE_ENDIAN)
- u16 task_id;
- u16 reserved1;
-#endif
- u32 reserved2[7];
+/*
+ * FCoE cached sges context $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_cached_sge_ctx {
+ struct regpair cur_buf_addr;
+ __le16 cur_buf_rem;
+ __le16 second_buf_rem;
+ struct regpair second_buf_addr;
};
-struct fcoe_fcp_cmd_payload {
- u32 opaque[8];
-};
-
-struct fcoe_fc_hdr {
-#if defined(__BIG_ENDIAN)
- u8 cs_ctl;
- u8 s_id[3];
-#elif defined(__LITTLE_ENDIAN)
- u8 s_id[3];
- u8 cs_ctl;
-#endif
-#if defined(__BIG_ENDIAN)
- u8 r_ctl;
- u8 d_id[3];
-#elif defined(__LITTLE_ENDIAN)
- u8 d_id[3];
- u8 r_ctl;
-#endif
-#if defined(__BIG_ENDIAN)
- u8 seq_id;
- u8 df_ctl;
- u16 seq_cnt;
-#elif defined(__LITTLE_ENDIAN)
- u16 seq_cnt;
- u8 df_ctl;
- u8 seq_id;
-#endif
-#if defined(__BIG_ENDIAN)
- u8 type;
- u8 f_ctl[3];
-#elif defined(__LITTLE_ENDIAN)
- u8 f_ctl[3];
- u8 type;
-#endif
- u32 parameters;
-#if defined(__BIG_ENDIAN)
- u16 ox_id;
- u16 rx_id;
-#elif defined(__LITTLE_ENDIAN)
- u16 rx_id;
- u16 ox_id;
-#endif
-};
-
-struct fcoe_fc_frame {
- struct fcoe_fc_hdr fc_hdr;
- u32 reserved0[2];
-};
-
-union fcoe_cmd_flow_info {
- struct fcoe_fcp_cmd_payload fcp_cmd_payload;
- struct fcoe_fc_frame mp_fc_frame;
+/*
+ * Cleanup info $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_cleanup_info {
+ __le16 cleaned_task_id;
+ __le16 rolled_tx_seq_cnt;
+ __le32 rolled_tx_data_offset;
};
-
+/*
+ * Fcp RSP flags $$KEEP_ENDIANNESS$$
+ */
struct fcoe_fcp_rsp_flags {
u8 flags;
#define FCOE_FCP_RSP_FLAGS_FCP_RSP_LEN_VALID (0x1<<0)
@@ -155,95 +129,168 @@
#define FCOE_FCP_RSP_FLAGS_FCP_BIDI_FLAGS_SHIFT 5
};
-
+/*
+ * Fcp RSP payload $$KEEP_ENDIANNESS$$
+ */
struct fcoe_fcp_rsp_payload {
struct regpair reserved0;
- u32 fcp_resid;
-#if defined(__BIG_ENDIAN)
- u16 retry_delay_timer;
- struct fcoe_fcp_rsp_flags fcp_flags;
- u8 scsi_status_code;
-#elif defined(__LITTLE_ENDIAN)
+ __le32 fcp_resid;
u8 scsi_status_code;
struct fcoe_fcp_rsp_flags fcp_flags;
- u16 retry_delay_timer;
-#endif
- u32 fcp_rsp_len;
- u32 fcp_sns_len;
+ __le16 retry_delay_timer;
+ __le32 fcp_rsp_len;
+ __le32 fcp_sns_len;
};
-
/*
* Fixed size structure in order to plant it in Union structure
+ * $$KEEP_ENDIANNESS$$
*/
struct fcoe_fcp_rsp_union {
struct fcoe_fcp_rsp_payload payload;
struct regpair reserved0;
};
-
-struct fcoe_fcp_xfr_rdy_payload {
- u32 burst_len;
- u32 data_ro;
+/*
+ * FC header $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_fc_hdr {
+ u8 s_id[3];
+ u8 cs_ctl;
+ u8 d_id[3];
+ u8 r_ctl;
+ __le16 seq_cnt;
+ u8 df_ctl;
+ u8 seq_id;
+ u8 f_ctl[3];
+ u8 type;
+ __le32 parameters;
+ __le16 rx_id;
+ __le16 ox_id;
};
-struct fcoe_read_flow_info {
- struct fcoe_fc_hdr fc_data_in_hdr;
- u32 reserved[2];
+/*
+ * FC header union $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_mp_rsp_union {
+ struct fcoe_fc_hdr fc_hdr;
+ __le32 mp_payload_len;
+ __le32 rsrv;
};
-struct fcoe_write_flow_info {
- struct fcoe_fc_hdr fc_data_out_hdr;
- struct fcoe_fcp_xfr_rdy_payload fcp_xfr_payload;
-};
-
-union fcoe_rsp_flow_info {
+/*
+ * Completion information $$KEEP_ENDIANNESS$$
+ */
+union fcoe_comp_flow_info {
struct fcoe_fcp_rsp_union fcp_rsp;
struct fcoe_abts_rsp_union abts_rsp;
+ struct fcoe_mp_rsp_union mp_rsp;
+ __le32 opaque[8];
};
+
/*
- * 32 bytes used for general purposes
+ * External ABTS info $$KEEP_ENDIANNESS$$
*/
-union fcoe_general_task_ctx {
- union fcoe_cmd_flow_info cmd_info;
- struct fcoe_read_flow_info read_info;
- struct fcoe_write_flow_info write_info;
- union fcoe_rsp_flow_info rsp_info;
- struct fcoe_cleanup_flow_info cleanup_info;
- u32 comp_info[8];
+struct fcoe_ext_abts_info {
+ __le32 rsrv0[6];
+ struct fcoe_abts_info ctx;
};
/*
- * FCoE KCQ CQE parameters
+ * External cleanup info $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_ext_cleanup_info {
+ __le32 rsrv0[6];
+ struct fcoe_cleanup_info ctx;
+};
+
+
+/*
+ * Fcoe FW Tx sequence context $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_fw_tx_seq_ctx {
+ __le32 data_offset;
+ __le16 seq_cnt;
+ __le16 rsrv0;
+};
+
+/*
+ * Fcoe external FW Tx sequence context $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_ext_fw_tx_seq_ctx {
+ __le32 rsrv0[6];
+ struct fcoe_fw_tx_seq_ctx ctx;
+};
+
+
+/*
+ * FCoE multiple sges context $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_mul_sges_ctx {
+ struct regpair cur_sge_addr;
+ __le16 cur_sge_off;
+ u8 cur_sge_idx;
+ u8 sgl_size;
+};
+
+/*
+ * FCoE external multiple sges context $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_ext_mul_sges_ctx {
+ struct fcoe_mul_sges_ctx mul_sgl;
+ struct regpair rsrv0;
+};
+
+
+/*
+ * FCP CMD payload $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_fcp_cmd_payload {
+ __le32 opaque[8];
+};
+
+
+
+
+
+/*
+ * Fcp xfr rdy payload $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_fcp_xfr_rdy_payload {
+ __le32 burst_len;
+ __le32 data_ro;
+};
+
+
+/*
+ * FC frame $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_fc_frame {
+ struct fcoe_fc_hdr fc_hdr;
+ __le32 reserved0[2];
+};
+
+
+
+
+/*
+ * FCoE KCQ CQE parameters $$KEEP_ENDIANNESS$$
*/
union fcoe_kcqe_params {
- u32 reserved0[4];
+ __le32 reserved0[4];
};
/*
- * FCoE KCQ CQE
+ * FCoE KCQ CQE $$KEEP_ENDIANNESS$$
*/
struct fcoe_kcqe {
- u32 fcoe_conn_id;
- u32 completion_status;
- u32 fcoe_conn_context_id;
+ __le32 fcoe_conn_id;
+ __le32 completion_status;
+ __le32 fcoe_conn_context_id;
union fcoe_kcqe_params params;
-#if defined(__BIG_ENDIAN)
- u8 flags;
-#define FCOE_KCQE_RESERVED0 (0x7<<0)
-#define FCOE_KCQE_RESERVED0_SHIFT 0
-#define FCOE_KCQE_RAMROD_COMPLETION (0x1<<3)
-#define FCOE_KCQE_RAMROD_COMPLETION_SHIFT 3
-#define FCOE_KCQE_LAYER_CODE (0x7<<4)
-#define FCOE_KCQE_LAYER_CODE_SHIFT 4
-#define FCOE_KCQE_LINKED_WITH_NEXT (0x1<<7)
-#define FCOE_KCQE_LINKED_WITH_NEXT_SHIFT 7
- u8 op_code;
- u16 qe_self_seq;
-#elif defined(__LITTLE_ENDIAN)
- u16 qe_self_seq;
+ __le16 qe_self_seq;
u8 op_code;
u8 flags;
#define FCOE_KCQE_RESERVED0 (0x7<<0)
@@ -254,23 +301,14 @@
#define FCOE_KCQE_LAYER_CODE_SHIFT 4
#define FCOE_KCQE_LINKED_WITH_NEXT (0x1<<7)
#define FCOE_KCQE_LINKED_WITH_NEXT_SHIFT 7
-#endif
};
+
+
/*
- * FCoE KWQE header
+ * FCoE KWQE header $$KEEP_ENDIANNESS$$
*/
struct fcoe_kwqe_header {
-#if defined(__BIG_ENDIAN)
- u8 flags;
-#define FCOE_KWQE_HEADER_RESERVED0 (0xF<<0)
-#define FCOE_KWQE_HEADER_RESERVED0_SHIFT 0
-#define FCOE_KWQE_HEADER_LAYER_CODE (0x7<<4)
-#define FCOE_KWQE_HEADER_LAYER_CODE_SHIFT 4
-#define FCOE_KWQE_HEADER_RESERVED1 (0x1<<7)
-#define FCOE_KWQE_HEADER_RESERVED1_SHIFT 7
- u8 op_code;
-#elif defined(__LITTLE_ENDIAN)
u8 op_code;
u8 flags;
#define FCOE_KWQE_HEADER_RESERVED0 (0xF<<0)
@@ -279,50 +317,23 @@
#define FCOE_KWQE_HEADER_LAYER_CODE_SHIFT 4
#define FCOE_KWQE_HEADER_RESERVED1 (0x1<<7)
#define FCOE_KWQE_HEADER_RESERVED1_SHIFT 7
-#endif
};
/*
- * FCoE firmware init request 1
+ * FCoE firmware init request 1 $$KEEP_ENDIANNESS$$
*/
struct fcoe_kwqe_init1 {
-#if defined(__BIG_ENDIAN)
+ __le16 num_tasks;
struct fcoe_kwqe_header hdr;
- u16 num_tasks;
-#elif defined(__LITTLE_ENDIAN)
- u16 num_tasks;
- struct fcoe_kwqe_header hdr;
-#endif
- u32 task_list_pbl_addr_lo;
- u32 task_list_pbl_addr_hi;
- u32 dummy_buffer_addr_lo;
- u32 dummy_buffer_addr_hi;
-#if defined(__BIG_ENDIAN)
- u16 rq_num_wqes;
- u16 sq_num_wqes;
-#elif defined(__LITTLE_ENDIAN)
- u16 sq_num_wqes;
- u16 rq_num_wqes;
-#endif
-#if defined(__BIG_ENDIAN)
- u16 cq_num_wqes;
- u16 rq_buffer_log_size;
-#elif defined(__LITTLE_ENDIAN)
- u16 rq_buffer_log_size;
- u16 cq_num_wqes;
-#endif
-#if defined(__BIG_ENDIAN)
- u8 flags;
-#define FCOE_KWQE_INIT1_LOG_PAGE_SIZE (0xF<<0)
-#define FCOE_KWQE_INIT1_LOG_PAGE_SIZE_SHIFT 0
-#define FCOE_KWQE_INIT1_LOG_CACHED_PBES_PER_FUNC (0x7<<4)
-#define FCOE_KWQE_INIT1_LOG_CACHED_PBES_PER_FUNC_SHIFT 4
-#define FCOE_KWQE_INIT1_RESERVED1 (0x1<<7)
-#define FCOE_KWQE_INIT1_RESERVED1_SHIFT 7
- u8 num_sessions_log;
- u16 mtu;
-#elif defined(__LITTLE_ENDIAN)
- u16 mtu;
+ __le32 task_list_pbl_addr_lo;
+ __le32 task_list_pbl_addr_hi;
+ __le32 dummy_buffer_addr_lo;
+ __le32 dummy_buffer_addr_hi;
+ __le16 sq_num_wqes;
+ __le16 rq_num_wqes;
+ __le16 rq_buffer_log_size;
+ __le16 cq_num_wqes;
+ __le16 mtu;
u8 num_sessions_log;
u8 flags;
#define FCOE_KWQE_INIT1_LOG_PAGE_SIZE (0xF<<0)
@@ -331,113 +342,73 @@
#define FCOE_KWQE_INIT1_LOG_CACHED_PBES_PER_FUNC_SHIFT 4
#define FCOE_KWQE_INIT1_RESERVED1 (0x1<<7)
#define FCOE_KWQE_INIT1_RESERVED1_SHIFT 7
-#endif
};
/*
- * FCoE firmware init request 2
+ * FCoE firmware init request 2 $$KEEP_ENDIANNESS$$
*/
struct fcoe_kwqe_init2 {
-#if defined(__BIG_ENDIAN)
+ u8 hsi_major_version;
+ u8 hsi_minor_version;
struct fcoe_kwqe_header hdr;
- u16 reserved0;
-#elif defined(__LITTLE_ENDIAN)
- u16 reserved0;
- struct fcoe_kwqe_header hdr;
-#endif
- u32 hash_tbl_pbl_addr_lo;
- u32 hash_tbl_pbl_addr_hi;
- u32 t2_hash_tbl_addr_lo;
- u32 t2_hash_tbl_addr_hi;
- u32 t2_ptr_hash_tbl_addr_lo;
- u32 t2_ptr_hash_tbl_addr_hi;
- u32 free_list_count;
+ __le32 hash_tbl_pbl_addr_lo;
+ __le32 hash_tbl_pbl_addr_hi;
+ __le32 t2_hash_tbl_addr_lo;
+ __le32 t2_hash_tbl_addr_hi;
+ __le32 t2_ptr_hash_tbl_addr_lo;
+ __le32 t2_ptr_hash_tbl_addr_hi;
+ __le32 free_list_count;
};
/*
- * FCoE firmware init request 3
+ * FCoE firmware init request 3 $$KEEP_ENDIANNESS$$
*/
struct fcoe_kwqe_init3 {
-#if defined(__BIG_ENDIAN)
+ __le16 reserved0;
struct fcoe_kwqe_header hdr;
- u16 reserved0;
-#elif defined(__LITTLE_ENDIAN)
- u16 reserved0;
- struct fcoe_kwqe_header hdr;
-#endif
- u32 error_bit_map_lo;
- u32 error_bit_map_hi;
-#if defined(__BIG_ENDIAN)
+ __le32 error_bit_map_lo;
+ __le32 error_bit_map_hi;
+ u8 perf_config;
u8 reserved21[3];
- u8 cached_session_enable;
-#elif defined(__LITTLE_ENDIAN)
- u8 cached_session_enable;
- u8 reserved21[3];
-#endif
- u32 reserved2[4];
+ __le32 reserved2[4];
};
/*
- * FCoE connection offload request 1
+ * FCoE connection offload request 1 $$KEEP_ENDIANNESS$$
*/
struct fcoe_kwqe_conn_offload1 {
-#if defined(__BIG_ENDIAN)
+ __le16 fcoe_conn_id;
struct fcoe_kwqe_header hdr;
- u16 fcoe_conn_id;
-#elif defined(__LITTLE_ENDIAN)
- u16 fcoe_conn_id;
- struct fcoe_kwqe_header hdr;
-#endif
- u32 sq_addr_lo;
- u32 sq_addr_hi;
- u32 rq_pbl_addr_lo;
- u32 rq_pbl_addr_hi;
- u32 rq_first_pbe_addr_lo;
- u32 rq_first_pbe_addr_hi;
-#if defined(__BIG_ENDIAN)
- u16 reserved0;
- u16 rq_prod;
-#elif defined(__LITTLE_ENDIAN)
- u16 rq_prod;
- u16 reserved0;
-#endif
+ __le32 sq_addr_lo;
+ __le32 sq_addr_hi;
+ __le32 rq_pbl_addr_lo;
+ __le32 rq_pbl_addr_hi;
+ __le32 rq_first_pbe_addr_lo;
+ __le32 rq_first_pbe_addr_hi;
+ __le16 rq_prod;
+ __le16 reserved0;
};
/*
- * FCoE connection offload request 2
+ * FCoE connection offload request 2 $$KEEP_ENDIANNESS$$
*/
struct fcoe_kwqe_conn_offload2 {
-#if defined(__BIG_ENDIAN)
+ __le16 tx_max_fc_pay_len;
struct fcoe_kwqe_header hdr;
- u16 tx_max_fc_pay_len;
-#elif defined(__LITTLE_ENDIAN)
- u16 tx_max_fc_pay_len;
- struct fcoe_kwqe_header hdr;
-#endif
- u32 cq_addr_lo;
- u32 cq_addr_hi;
- u32 xferq_addr_lo;
- u32 xferq_addr_hi;
- u32 conn_db_addr_lo;
- u32 conn_db_addr_hi;
- u32 reserved1;
+ __le32 cq_addr_lo;
+ __le32 cq_addr_hi;
+ __le32 xferq_addr_lo;
+ __le32 xferq_addr_hi;
+ __le32 conn_db_addr_lo;
+ __le32 conn_db_addr_hi;
+ __le32 reserved1;
};
/*
- * FCoE connection offload request 3
+ * FCoE connection offload request 3 $$KEEP_ENDIANNESS$$
*/
struct fcoe_kwqe_conn_offload3 {
-#if defined(__BIG_ENDIAN)
- struct fcoe_kwqe_header hdr;
- u16 vlan_tag;
-#define FCOE_KWQE_CONN_OFFLOAD3_VLAN_ID (0xFFF<<0)
-#define FCOE_KWQE_CONN_OFFLOAD3_VLAN_ID_SHIFT 0
-#define FCOE_KWQE_CONN_OFFLOAD3_CFI (0x1<<12)
-#define FCOE_KWQE_CONN_OFFLOAD3_CFI_SHIFT 12
-#define FCOE_KWQE_CONN_OFFLOAD3_PRIORITY (0x7<<13)
-#define FCOE_KWQE_CONN_OFFLOAD3_PRIORITY_SHIFT 13
-#elif defined(__LITTLE_ENDIAN)
- u16 vlan_tag;
+ __le16 vlan_tag;
#define FCOE_KWQE_CONN_OFFLOAD3_VLAN_ID (0xFFF<<0)
#define FCOE_KWQE_CONN_OFFLOAD3_VLAN_ID_SHIFT 0
#define FCOE_KWQE_CONN_OFFLOAD3_CFI (0x1<<12)
@@ -445,34 +416,8 @@
#define FCOE_KWQE_CONN_OFFLOAD3_PRIORITY (0x7<<13)
#define FCOE_KWQE_CONN_OFFLOAD3_PRIORITY_SHIFT 13
struct fcoe_kwqe_header hdr;
-#endif
-#if defined(__BIG_ENDIAN)
- u8 tx_max_conc_seqs_c3;
- u8 s_id[3];
-#elif defined(__LITTLE_ENDIAN)
u8 s_id[3];
u8 tx_max_conc_seqs_c3;
-#endif
-#if defined(__BIG_ENDIAN)
- u8 flags;
-#define FCOE_KWQE_CONN_OFFLOAD3_B_MUL_N_PORT_IDS (0x1<<0)
-#define FCOE_KWQE_CONN_OFFLOAD3_B_MUL_N_PORT_IDS_SHIFT 0
-#define FCOE_KWQE_CONN_OFFLOAD3_B_E_D_TOV_RES (0x1<<1)
-#define FCOE_KWQE_CONN_OFFLOAD3_B_E_D_TOV_RES_SHIFT 1
-#define FCOE_KWQE_CONN_OFFLOAD3_B_CONT_INCR_SEQ_CNT (0x1<<2)
-#define FCOE_KWQE_CONN_OFFLOAD3_B_CONT_INCR_SEQ_CNT_SHIFT 2
-#define FCOE_KWQE_CONN_OFFLOAD3_B_CONF_REQ (0x1<<3)
-#define FCOE_KWQE_CONN_OFFLOAD3_B_CONF_REQ_SHIFT 3
-#define FCOE_KWQE_CONN_OFFLOAD3_B_REC_VALID (0x1<<4)
-#define FCOE_KWQE_CONN_OFFLOAD3_B_REC_VALID_SHIFT 4
-#define FCOE_KWQE_CONN_OFFLOAD3_B_C2_VALID (0x1<<5)
-#define FCOE_KWQE_CONN_OFFLOAD3_B_C2_VALID_SHIFT 5
-#define FCOE_KWQE_CONN_OFFLOAD3_B_ACK_0 (0x1<<6)
-#define FCOE_KWQE_CONN_OFFLOAD3_B_ACK_0_SHIFT 6
-#define FCOE_KWQE_CONN_OFFLOAD3_B_VLAN_FLAG (0x1<<7)
-#define FCOE_KWQE_CONN_OFFLOAD3_B_VLAN_FLAG_SHIFT 7
- u8 d_id[3];
-#elif defined(__LITTLE_ENDIAN)
u8 d_id[3];
u8 flags;
#define FCOE_KWQE_CONN_OFFLOAD3_B_MUL_N_PORT_IDS (0x1<<0)
@@ -491,69 +436,44 @@
#define FCOE_KWQE_CONN_OFFLOAD3_B_ACK_0_SHIFT 6
#define FCOE_KWQE_CONN_OFFLOAD3_B_VLAN_FLAG (0x1<<7)
#define FCOE_KWQE_CONN_OFFLOAD3_B_VLAN_FLAG_SHIFT 7
-#endif
- u32 reserved;
- u32 confq_first_pbe_addr_lo;
- u32 confq_first_pbe_addr_hi;
-#if defined(__BIG_ENDIAN)
- u16 rx_max_fc_pay_len;
- u16 tx_total_conc_seqs;
-#elif defined(__LITTLE_ENDIAN)
- u16 tx_total_conc_seqs;
- u16 rx_max_fc_pay_len;
-#endif
-#if defined(__BIG_ENDIAN)
- u8 rx_open_seqs_exch_c3;
- u8 rx_max_conc_seqs_c3;
- u16 rx_total_conc_seqs;
-#elif defined(__LITTLE_ENDIAN)
- u16 rx_total_conc_seqs;
+ __le32 reserved;
+ __le32 confq_first_pbe_addr_lo;
+ __le32 confq_first_pbe_addr_hi;
+ __le16 tx_total_conc_seqs;
+ __le16 rx_max_fc_pay_len;
+ __le16 rx_total_conc_seqs;
u8 rx_max_conc_seqs_c3;
u8 rx_open_seqs_exch_c3;
-#endif
};
/*
- * FCoE connection offload request 4
+ * FCoE connection offload request 4 $$KEEP_ENDIANNESS$$
*/
struct fcoe_kwqe_conn_offload4 {
-#if defined(__BIG_ENDIAN)
- struct fcoe_kwqe_header hdr;
- u8 reserved2;
- u8 e_d_tov_timer_val;
-#elif defined(__LITTLE_ENDIAN)
u8 e_d_tov_timer_val;
u8 reserved2;
struct fcoe_kwqe_header hdr;
-#endif
- u8 src_mac_addr_lo32[4];
-#if defined(__BIG_ENDIAN)
- u8 dst_mac_addr_hi16[2];
- u8 src_mac_addr_hi16[2];
-#elif defined(__LITTLE_ENDIAN)
- u8 src_mac_addr_hi16[2];
- u8 dst_mac_addr_hi16[2];
-#endif
- u8 dst_mac_addr_lo32[4];
- u32 lcq_addr_lo;
- u32 lcq_addr_hi;
- u32 confq_pbl_base_addr_lo;
- u32 confq_pbl_base_addr_hi;
+ u8 src_mac_addr_lo[2];
+ u8 src_mac_addr_mid[2];
+ u8 src_mac_addr_hi[2];
+ u8 dst_mac_addr_hi[2];
+ u8 dst_mac_addr_lo[2];
+ u8 dst_mac_addr_mid[2];
+ __le32 lcq_addr_lo;
+ __le32 lcq_addr_hi;
+ __le32 confq_pbl_base_addr_lo;
+ __le32 confq_pbl_base_addr_hi;
};
/*
- * FCoE connection enable request
+ * FCoE connection enable request $$KEEP_ENDIANNESS$$
*/
struct fcoe_kwqe_conn_enable_disable {
-#if defined(__BIG_ENDIAN)
+ __le16 reserved0;
struct fcoe_kwqe_header hdr;
- u16 reserved0;
-#elif defined(__LITTLE_ENDIAN)
- u16 reserved0;
- struct fcoe_kwqe_header hdr;
-#endif
- u8 src_mac_addr_lo32[4];
-#if defined(__BIG_ENDIAN)
+ u8 src_mac_addr_lo[2];
+ u8 src_mac_addr_mid[2];
+ u8 src_mac_addr_hi[2];
u16 vlan_tag;
#define FCOE_KWQE_CONN_ENABLE_DISABLE_VLAN_ID (0xFFF<<0)
#define FCOE_KWQE_CONN_ENABLE_DISABLE_VLAN_ID_SHIFT 0
@@ -561,92 +481,52 @@
#define FCOE_KWQE_CONN_ENABLE_DISABLE_CFI_SHIFT 12
#define FCOE_KWQE_CONN_ENABLE_DISABLE_PRIORITY (0x7<<13)
#define FCOE_KWQE_CONN_ENABLE_DISABLE_PRIORITY_SHIFT 13
- u8 src_mac_addr_hi16[2];
-#elif defined(__LITTLE_ENDIAN)
- u8 src_mac_addr_hi16[2];
- u16 vlan_tag;
-#define FCOE_KWQE_CONN_ENABLE_DISABLE_VLAN_ID (0xFFF<<0)
-#define FCOE_KWQE_CONN_ENABLE_DISABLE_VLAN_ID_SHIFT 0
-#define FCOE_KWQE_CONN_ENABLE_DISABLE_CFI (0x1<<12)
-#define FCOE_KWQE_CONN_ENABLE_DISABLE_CFI_SHIFT 12
-#define FCOE_KWQE_CONN_ENABLE_DISABLE_PRIORITY (0x7<<13)
-#define FCOE_KWQE_CONN_ENABLE_DISABLE_PRIORITY_SHIFT 13
-#endif
- u8 dst_mac_addr_lo32[4];
-#if defined(__BIG_ENDIAN)
- u16 reserved1;
- u8 dst_mac_addr_hi16[2];
-#elif defined(__LITTLE_ENDIAN)
- u8 dst_mac_addr_hi16[2];
- u16 reserved1;
-#endif
-#if defined(__BIG_ENDIAN)
- u8 vlan_flag;
- u8 s_id[3];
-#elif defined(__LITTLE_ENDIAN)
+ u8 dst_mac_addr_lo[2];
+ u8 dst_mac_addr_mid[2];
+ u8 dst_mac_addr_hi[2];
+ __le16 reserved1;
u8 s_id[3];
u8 vlan_flag;
-#endif
-#if defined(__BIG_ENDIAN)
- u8 reserved3;
- u8 d_id[3];
-#elif defined(__LITTLE_ENDIAN)
u8 d_id[3];
u8 reserved3;
-#endif
- u32 context_id;
- u32 conn_id;
- u32 reserved4;
+ __le32 context_id;
+ __le32 conn_id;
+ __le32 reserved4;
};
/*
- * FCoE connection destroy request
+ * FCoE connection destroy request $$KEEP_ENDIANNESS$$
*/
struct fcoe_kwqe_conn_destroy {
-#if defined(__BIG_ENDIAN)
+ __le16 reserved0;
struct fcoe_kwqe_header hdr;
- u16 reserved0;
-#elif defined(__LITTLE_ENDIAN)
- u16 reserved0;
- struct fcoe_kwqe_header hdr;
-#endif
- u32 context_id;
- u32 conn_id;
- u32 reserved1[5];
+ __le32 context_id;
+ __le32 conn_id;
+ __le32 reserved1[5];
};
/*
- * FCoe destroy request
+ * FCoe destroy request $$KEEP_ENDIANNESS$$
*/
struct fcoe_kwqe_destroy {
-#if defined(__BIG_ENDIAN)
+ __le16 reserved0;
struct fcoe_kwqe_header hdr;
- u16 reserved0;
-#elif defined(__LITTLE_ENDIAN)
- u16 reserved0;
- struct fcoe_kwqe_header hdr;
-#endif
- u32 reserved1[7];
+ __le32 reserved1[7];
};
/*
- * FCoe statistics request
+ * FCoe statistics request $$KEEP_ENDIANNESS$$
*/
struct fcoe_kwqe_stat {
-#if defined(__BIG_ENDIAN)
+ __le16 reserved0;
struct fcoe_kwqe_header hdr;
- u16 reserved0;
-#elif defined(__LITTLE_ENDIAN)
- u16 reserved0;
- struct fcoe_kwqe_header hdr;
-#endif
- u32 stat_params_addr_lo;
- u32 stat_params_addr_hi;
- u32 reserved1[5];
+ __le32 stat_params_addr_lo;
+ __le32 stat_params_addr_hi;
+ __le32 reserved1[5];
};
/*
- * FCoE KWQ WQE
+ * FCoE KWQ WQE $$KEEP_ENDIANNESS$$
*/
union fcoe_kwqe {
struct fcoe_kwqe_init1 init1;
@@ -662,19 +542,42 @@
struct fcoe_kwqe_stat statistics;
};
-struct fcoe_mul_sges_ctx {
- struct regpair cur_sge_addr;
-#if defined(__BIG_ENDIAN)
- u8 sgl_size;
- u8 cur_sge_idx;
- u16 cur_sge_off;
-#elif defined(__LITTLE_ENDIAN)
- u16 cur_sge_off;
- u8 cur_sge_idx;
- u8 sgl_size;
-#endif
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+/*
+ * TX SGL context $$KEEP_ENDIANNESS$$
+ */
+union fcoe_sgl_union_ctx {
+ struct fcoe_cached_sge_ctx cached_sge;
+ struct fcoe_ext_mul_sges_ctx sgl;
+ __le32 opaque[5];
};
+/*
+ * Data-In/ELS/BLS information $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_read_flow_info {
+ union fcoe_sgl_union_ctx sgl_ctx;
+ __le32 rsrv0[3];
+};
+
+
+/*
+ * Fcoe stat context $$KEEP_ENDIANNESS$$
+ */
struct fcoe_s_stat_ctx {
u8 flags;
#define FCOE_S_STAT_CTX_ACTIVE (0x1<<0)
@@ -693,51 +596,34 @@
#define FCOE_S_STAT_CTX_RSRV1_SHIFT 6
};
-struct fcoe_seq_ctx {
-#if defined(__BIG_ENDIAN)
- u16 low_seq_cnt;
- struct fcoe_s_stat_ctx s_stat;
- u8 seq_id;
-#elif defined(__LITTLE_ENDIAN)
+/*
+ * Fcoe rx seq context $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_rx_seq_ctx {
u8 seq_id;
struct fcoe_s_stat_ctx s_stat;
- u16 low_seq_cnt;
-#endif
-#if defined(__BIG_ENDIAN)
- u16 err_seq_cnt;
- u16 high_seq_cnt;
-#elif defined(__LITTLE_ENDIAN)
- u16 high_seq_cnt;
- u16 err_seq_cnt;
-#endif
- u32 low_exp_ro;
- u32 high_exp_ro;
+ __le16 seq_cnt;
+ __le32 low_exp_ro;
+ __le32 high_exp_ro;
};
-struct fcoe_single_sge_ctx {
- struct regpair cur_buf_addr;
-#if defined(__BIG_ENDIAN)
- u16 reserved0;
- u16 cur_buf_rem;
-#elif defined(__LITTLE_ENDIAN)
- u16 cur_buf_rem;
- u16 reserved0;
-#endif
-};
-
-union fcoe_sgl_ctx {
- struct fcoe_single_sge_ctx single_sge;
- struct fcoe_mul_sges_ctx mul_sges;
+/*
+ * Fcoe rx_wr union context $$KEEP_ENDIANNESS$$
+ */
+union fcoe_rx_wr_union_ctx {
+ struct fcoe_read_flow_info read_info;
+ union fcoe_comp_flow_info comp_info;
+ __le32 opaque[8];
};
/*
- * FCoE SQ element
+ * FCoE SQ element $$KEEP_ENDIANNESS$$
*/
struct fcoe_sqe {
- u16 wqe;
+ __le16 wqe;
#define FCOE_SQE_TASK_ID (0x7FFF<<0)
#define FCOE_SQE_TASK_ID_SHIFT 0
#define FCOE_SQE_TOGGLE_BIT (0x1<<15)
@@ -746,135 +632,141 @@
-struct fcoe_task_ctx_entry_tx_only {
- union fcoe_sgl_ctx sgl_ctx;
-};
-
-struct fcoe_task_ctx_entry_txwr_rxrd {
-#if defined(__BIG_ENDIAN)
- u16 verify_tx_seq;
- u8 init_flags;
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TASK_TYPE (0x7<<0)
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TASK_TYPE_SHIFT 0
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_DEV_TYPE (0x1<<3)
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_DEV_TYPE_SHIFT 3
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_CLASS_TYPE (0x1<<4)
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_CLASS_TYPE_SHIFT 4
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_SINGLE_SGE (0x1<<5)
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_SINGLE_SGE_SHIFT 5
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_RSRV5 (0x3<<6)
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_RSRV5_SHIFT 6
- u8 tx_flags;
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TX_STATE (0xF<<0)
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TX_STATE_SHIFT 0
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_RSRV4 (0xF<<4)
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_RSRV4_SHIFT 4
-#elif defined(__LITTLE_ENDIAN)
- u8 tx_flags;
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TX_STATE (0xF<<0)
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TX_STATE_SHIFT 0
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_RSRV4 (0xF<<4)
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_RSRV4_SHIFT 4
- u8 init_flags;
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TASK_TYPE (0x7<<0)
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TASK_TYPE_SHIFT 0
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_DEV_TYPE (0x1<<3)
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_DEV_TYPE_SHIFT 3
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_CLASS_TYPE (0x1<<4)
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_CLASS_TYPE_SHIFT 4
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_SINGLE_SGE (0x1<<5)
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_SINGLE_SGE_SHIFT 5
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_RSRV5 (0x3<<6)
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_RSRV5_SHIFT 6
- u16 verify_tx_seq;
-#endif
-};
-
/*
- * Common section. Both TX and RX processing might write and read from it in
- * different flows
+ * 14 regs $$KEEP_ENDIANNESS$$
*/
-struct fcoe_task_ctx_entry_tx_rx_cmn {
- u32 data_2_trns;
- union fcoe_general_task_ctx general;
-#if defined(__BIG_ENDIAN)
- u16 tx_low_seq_cnt;
- struct fcoe_s_stat_ctx tx_s_stat;
- u8 tx_seq_id;
-#elif defined(__LITTLE_ENDIAN)
- u8 tx_seq_id;
- struct fcoe_s_stat_ctx tx_s_stat;
- u16 tx_low_seq_cnt;
-#endif
- u32 common_flags;
-#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_CID (0xFFFFFF<<0)
-#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_CID_SHIFT 0
-#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_VALID (0x1<<24)
-#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_VALID_SHIFT 24
-#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_SEQ_INIT (0x1<<25)
-#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_SEQ_INIT_SHIFT 25
-#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_PEND_XFER (0x1<<26)
-#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_PEND_XFER_SHIFT 26
-#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_PEND_CONF (0x1<<27)
-#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_PEND_CONF_SHIFT 27
-#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_EXP_FIRST_FRAME (0x1<<28)
-#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_EXP_FIRST_FRAME_SHIFT 28
-#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_RSRV (0x7<<29)
-#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_RSRV_SHIFT 29
+struct fcoe_tce_tx_only {
+ union fcoe_sgl_union_ctx sgl_ctx;
+ __le32 rsrv0;
};
-struct fcoe_task_ctx_entry_rxwr_txrd {
-#if defined(__BIG_ENDIAN)
- u16 rx_id;
- u16 rx_flags;
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_RX_STATE (0xF<<0)
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_RX_STATE_SHIFT 0
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_NUM_RQ_WQE (0x7<<4)
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_NUM_RQ_WQE_SHIFT 4
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_CONF_REQ (0x1<<7)
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_CONF_REQ_SHIFT 7
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_MISS_FRAME (0x1<<8)
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_MISS_FRAME_SHIFT 8
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_RESERVED0 (0x7F<<9)
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_RESERVED0_SHIFT 9
-#elif defined(__LITTLE_ENDIAN)
- u16 rx_flags;
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_RX_STATE (0xF<<0)
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_RX_STATE_SHIFT 0
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_NUM_RQ_WQE (0x7<<4)
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_NUM_RQ_WQE_SHIFT 4
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_CONF_REQ (0x1<<7)
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_CONF_REQ_SHIFT 7
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_MISS_FRAME (0x1<<8)
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_MISS_FRAME_SHIFT 8
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_RESERVED0 (0x7F<<9)
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_RESERVED0_SHIFT 9
- u16 rx_id;
-#endif
+/*
+ * 32 bytes (8 regs) used for TX only purposes $$KEEP_ENDIANNESS$$
+ */
+union fcoe_tx_wr_rx_rd_union_ctx {
+ struct fcoe_fc_frame tx_frame;
+ struct fcoe_fcp_cmd_payload fcp_cmd;
+ struct fcoe_ext_cleanup_info cleanup;
+ struct fcoe_ext_abts_info abts;
+ struct fcoe_ext_fw_tx_seq_ctx tx_seq;
+ __le32 opaque[8];
};
-struct fcoe_task_ctx_entry_rx_only {
- struct fcoe_seq_ctx seq_ctx;
- struct fcoe_seq_ctx ooo_seq_ctx;
- u32 rsrv3;
- union fcoe_sgl_ctx sgl_ctx;
+/*
+ * tce_tx_wr_rx_rd_const $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_tce_tx_wr_rx_rd_const {
+ u8 init_flags;
+#define FCOE_TCE_TX_WR_RX_RD_CONST_TASK_TYPE (0x7<<0)
+#define FCOE_TCE_TX_WR_RX_RD_CONST_TASK_TYPE_SHIFT 0
+#define FCOE_TCE_TX_WR_RX_RD_CONST_DEV_TYPE (0x1<<3)
+#define FCOE_TCE_TX_WR_RX_RD_CONST_DEV_TYPE_SHIFT 3
+#define FCOE_TCE_TX_WR_RX_RD_CONST_CLASS_TYPE (0x1<<4)
+#define FCOE_TCE_TX_WR_RX_RD_CONST_CLASS_TYPE_SHIFT 4
+#define FCOE_TCE_TX_WR_RX_RD_CONST_CACHED_SGE (0x3<<5)
+#define FCOE_TCE_TX_WR_RX_RD_CONST_CACHED_SGE_SHIFT 5
+#define FCOE_TCE_TX_WR_RX_RD_CONST_SUPPORT_REC_TOV (0x1<<7)
+#define FCOE_TCE_TX_WR_RX_RD_CONST_SUPPORT_REC_TOV_SHIFT 7
+ u8 tx_flags;
+#define FCOE_TCE_TX_WR_RX_RD_CONST_TX_VALID (0x1<<0)
+#define FCOE_TCE_TX_WR_RX_RD_CONST_TX_VALID_SHIFT 0
+#define FCOE_TCE_TX_WR_RX_RD_CONST_TX_STATE (0xF<<1)
+#define FCOE_TCE_TX_WR_RX_RD_CONST_TX_STATE_SHIFT 1
+#define FCOE_TCE_TX_WR_RX_RD_CONST_RSRV1 (0x1<<5)
+#define FCOE_TCE_TX_WR_RX_RD_CONST_RSRV1_SHIFT 5
+#define FCOE_TCE_TX_WR_RX_RD_CONST_TX_SEQ_INIT (0x1<<6)
+#define FCOE_TCE_TX_WR_RX_RD_CONST_TX_SEQ_INIT_SHIFT 6
+#define FCOE_TCE_TX_WR_RX_RD_CONST_RSRV2 (0x1<<7)
+#define FCOE_TCE_TX_WR_RX_RD_CONST_RSRV2_SHIFT 7
+ __le16 rsrv3;
+ __le32 verify_tx_seq;
};
+/*
+ * tce_tx_wr_rx_rd $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_tce_tx_wr_rx_rd {
+ union fcoe_tx_wr_rx_rd_union_ctx union_ctx;
+ struct fcoe_tce_tx_wr_rx_rd_const const_ctx;
+};
+
+/*
+ * tce_rx_wr_tx_rd_const $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_tce_rx_wr_tx_rd_const {
+ __le32 data_2_trns;
+ __le32 init_flags;
+#define FCOE_TCE_RX_WR_TX_RD_CONST_CID (0xFFFFFF<<0)
+#define FCOE_TCE_RX_WR_TX_RD_CONST_CID_SHIFT 0
+#define FCOE_TCE_RX_WR_TX_RD_CONST_RSRV0 (0xFF<<24)
+#define FCOE_TCE_RX_WR_TX_RD_CONST_RSRV0_SHIFT 24
+};
+
+/*
+ * tce_rx_wr_tx_rd_var $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_tce_rx_wr_tx_rd_var {
+ __le16 rx_flags;
+#define FCOE_TCE_RX_WR_TX_RD_VAR_RSRV1 (0xF<<0)
+#define FCOE_TCE_RX_WR_TX_RD_VAR_RSRV1_SHIFT 0
+#define FCOE_TCE_RX_WR_TX_RD_VAR_NUM_RQ_WQE (0x7<<4)
+#define FCOE_TCE_RX_WR_TX_RD_VAR_NUM_RQ_WQE_SHIFT 4
+#define FCOE_TCE_RX_WR_TX_RD_VAR_CONF_REQ (0x1<<7)
+#define FCOE_TCE_RX_WR_TX_RD_VAR_CONF_REQ_SHIFT 7
+#define FCOE_TCE_RX_WR_TX_RD_VAR_RX_STATE (0xF<<8)
+#define FCOE_TCE_RX_WR_TX_RD_VAR_RX_STATE_SHIFT 8
+#define FCOE_TCE_RX_WR_TX_RD_VAR_EXP_FIRST_FRAME (0x1<<12)
+#define FCOE_TCE_RX_WR_TX_RD_VAR_EXP_FIRST_FRAME_SHIFT 12
+#define FCOE_TCE_RX_WR_TX_RD_VAR_RX_SEQ_INIT (0x1<<13)
+#define FCOE_TCE_RX_WR_TX_RD_VAR_RX_SEQ_INIT_SHIFT 13
+#define FCOE_TCE_RX_WR_TX_RD_VAR_RSRV2 (0x1<<14)
+#define FCOE_TCE_RX_WR_TX_RD_VAR_RSRV2_SHIFT 14
+#define FCOE_TCE_RX_WR_TX_RD_VAR_RX_VALID (0x1<<15)
+#define FCOE_TCE_RX_WR_TX_RD_VAR_RX_VALID_SHIFT 15
+ __le16 rx_id;
+ struct fcoe_fcp_xfr_rdy_payload fcp_xfr_rdy;
+};
+
+/*
+ * tce_rx_wr_tx_rd $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_tce_rx_wr_tx_rd {
+ struct fcoe_tce_rx_wr_tx_rd_const const_ctx;
+ struct fcoe_tce_rx_wr_tx_rd_var var_ctx;
+};
+
+/*
+ * tce_rx_only $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_tce_rx_only {
+ struct fcoe_rx_seq_ctx rx_seq_ctx;
+ union fcoe_rx_wr_union_ctx union_ctx;
+};
+
+/*
+ * task_ctx_entry $$KEEP_ENDIANNESS$$
+ */
struct fcoe_task_ctx_entry {
- struct fcoe_task_ctx_entry_tx_only tx_wr_only;
- struct fcoe_task_ctx_entry_txwr_rxrd tx_wr_rx_rd;
- struct fcoe_task_ctx_entry_tx_rx_cmn cmn;
- struct fcoe_task_ctx_entry_rxwr_txrd rx_wr_tx_rd;
- struct fcoe_task_ctx_entry_rx_only rx_wr_only;
- u32 reserved[4];
+ struct fcoe_tce_tx_only txwr_only;
+ struct fcoe_tce_tx_wr_rx_rd txwr_rxrd;
+ struct fcoe_tce_rx_wr_tx_rd rxwr_txrd;
+ struct fcoe_tce_rx_only rxwr_only;
};
+
+
+
+
+
+
+
+
/*
- * FCoE XFRQ element
+ * FCoE XFRQ element $$KEEP_ENDIANNESS$$
*/
struct fcoe_xfrqe {
- u16 wqe;
+ __le16 wqe;
#define FCOE_XFRQE_TASK_ID (0x7FFF<<0)
#define FCOE_XFRQE_TASK_ID_SHIFT 0
#define FCOE_XFRQE_TOGGLE_BIT (0x1<<15)
@@ -883,22 +775,31 @@
/*
- * FCoE CONFQ element
+ * fcoe rx doorbell message sent to the chip $$KEEP_ENDIANNESS$$
*/
-struct fcoe_confqe {
-#if defined(__BIG_ENDIAN)
- u16 rx_id;
- u16 ox_id;
-#elif defined(__LITTLE_ENDIAN)
- u16 ox_id;
- u16 rx_id;
-#endif
- u32 param;
+struct b577xx_fcoe_rx_doorbell {
+ struct b577xx_doorbell_hdr hdr;
+ u8 params;
+#define B577XX_FCOE_RX_DOORBELL_NEGATIVE_ARM (0x1F<<0)
+#define B577XX_FCOE_RX_DOORBELL_NEGATIVE_ARM_SHIFT 0
+#define B577XX_FCOE_RX_DOORBELL_OPCODE (0x7<<5)
+#define B577XX_FCOE_RX_DOORBELL_OPCODE_SHIFT 5
+ __le16 doorbell_cq_cons;
};
/*
- * FCoE connection data base
+ * FCoE CONFQ element $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_confqe {
+ __le16 ox_id;
+ __le16 rx_id;
+ __le32 param;
+};
+
+
+/*
+ * FCoE conection data base
*/
struct fcoe_conn_db {
#if defined(__BIG_ENDIAN)
@@ -914,10 +815,10 @@
/*
- * FCoE CQ element
+ * FCoE CQ element $$KEEP_ENDIANNESS$$
*/
struct fcoe_cqe {
- u16 wqe;
+ __le16 wqe;
#define FCOE_CQE_CQE_INFO (0x3FFF<<0)
#define FCOE_CQE_CQE_INFO_SHIFT 0
#define FCOE_CQE_CQE_TYPE (0x1<<14)
@@ -928,61 +829,46 @@
/*
- * FCoE error/warning resporting entry
+ * FCoE error/warning reporting entry $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_partial_err_report_entry {
+ __le32 err_warn_bitmap_lo;
+ __le32 err_warn_bitmap_hi;
+ __le32 tx_buf_off;
+ __le32 rx_buf_off;
+};
+
+/*
+ * FCoE error/warning reporting entry $$KEEP_ENDIANNESS$$
*/
struct fcoe_err_report_entry {
- u32 err_warn_bitmap_lo;
- u32 err_warn_bitmap_hi;
- u32 tx_buf_off;
- u32 rx_buf_off;
+ struct fcoe_partial_err_report_entry data;
struct fcoe_fc_hdr fc_hdr;
};
/*
- * FCoE hash table entry (32 bytes)
+ * FCoE hash table entry (32 bytes) $$KEEP_ENDIANNESS$$
*/
struct fcoe_hash_table_entry {
-#if defined(__BIG_ENDIAN)
- u8 d_id_0;
- u8 s_id_2;
- u8 s_id_1;
- u8 s_id_0;
-#elif defined(__LITTLE_ENDIAN)
u8 s_id_0;
u8 s_id_1;
u8 s_id_2;
u8 d_id_0;
-#endif
-#if defined(__BIG_ENDIAN)
- u16 dst_mac_addr_hi;
- u8 d_id_2;
- u8 d_id_1;
-#elif defined(__LITTLE_ENDIAN)
u8 d_id_1;
u8 d_id_2;
- u16 dst_mac_addr_hi;
-#endif
- u32 dst_mac_addr_lo;
-#if defined(__BIG_ENDIAN)
- u16 vlan_id;
- u16 src_mac_addr_hi;
-#elif defined(__LITTLE_ENDIAN)
- u16 src_mac_addr_hi;
- u16 vlan_id;
-#endif
- u32 src_mac_addr_lo;
-#if defined(__BIG_ENDIAN)
- u16 reserved1;
- u8 reserved0;
- u8 vlan_flag;
-#elif defined(__LITTLE_ENDIAN)
+ __le16 dst_mac_addr_hi;
+ __le16 dst_mac_addr_mid;
+ __le16 dst_mac_addr_lo;
+ __le16 src_mac_addr_hi;
+ __le16 vlan_id;
+ __le16 src_mac_addr_lo;
+ __le16 src_mac_addr_mid;
u8 vlan_flag;
u8 reserved0;
- u16 reserved1;
-#endif
- u32 reserved2;
- u32 field_id;
+ __le16 reserved1;
+ __le32 reserved2;
+ __le32 field_id;
#define FCOE_HASH_TABLE_ENTRY_CID (0xFFFFFF<<0)
#define FCOE_HASH_TABLE_ENTRY_CID_SHIFT 0
#define FCOE_HASH_TABLE_ENTRY_RESERVED3 (0x7F<<24)
@@ -991,11 +877,27 @@
#define FCOE_HASH_TABLE_ENTRY_VALID_SHIFT 31
};
+
/*
- * FCoE pending work request CQE
+ * FCoE LCQ element $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_lcqe {
+ __le32 wqe;
+#define FCOE_LCQE_TASK_ID (0xFFFF<<0)
+#define FCOE_LCQE_TASK_ID_SHIFT 0
+#define FCOE_LCQE_LCQE_TYPE (0xFF<<16)
+#define FCOE_LCQE_LCQE_TYPE_SHIFT 16
+#define FCOE_LCQE_RESERVED (0xFF<<24)
+#define FCOE_LCQE_RESERVED_SHIFT 24
+};
+
+
+
+/*
+ * FCoE pending work request CQE $$KEEP_ENDIANNESS$$
*/
struct fcoe_pend_wq_cqe {
- u16 wqe;
+ __le16 wqe;
#define FCOE_PEND_WQ_CQE_TASK_ID (0x3FFF<<0)
#define FCOE_PEND_WQ_CQE_TASK_ID_SHIFT 0
#define FCOE_PEND_WQ_CQE_CQE_TYPE (0x1<<14)
@@ -1006,53 +908,61 @@
/*
- * FCoE RX statistics parameters section#0
+ * FCoE RX statistics parameters section#0 $$KEEP_ENDIANNESS$$
*/
struct fcoe_rx_stat_params_section0 {
- u32 fcoe_ver_cnt;
- u32 fcoe_rx_pkt_cnt;
- u32 fcoe_rx_byte_cnt;
- u32 fcoe_rx_drop_pkt_cnt;
+ __le32 fcoe_rx_pkt_cnt;
+ __le32 fcoe_rx_byte_cnt;
};
/*
- * FCoE RX statistics parameters section#1
+ * FCoE RX statistics parameters section#1 $$KEEP_ENDIANNESS$$
*/
struct fcoe_rx_stat_params_section1 {
- u32 fc_crc_cnt;
- u32 eofa_del_cnt;
- u32 miss_frame_cnt;
- u32 seq_timeout_cnt;
- u32 drop_seq_cnt;
- u32 fcoe_rx_drop_pkt_cnt;
- u32 fcp_rx_pkt_cnt;
- u32 reserved0;
+ __le32 fcoe_ver_cnt;
+ __le32 fcoe_rx_drop_pkt_cnt;
};
/*
- * FCoE TX statistics parameters
+ * FCoE RX statistics parameters section#2 $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_rx_stat_params_section2 {
+ __le32 fc_crc_cnt;
+ __le32 eofa_del_cnt;
+ __le32 miss_frame_cnt;
+ __le32 seq_timeout_cnt;
+ __le32 drop_seq_cnt;
+ __le32 fcoe_rx_drop_pkt_cnt;
+ __le32 fcp_rx_pkt_cnt;
+ __le32 reserved0;
+};
+
+
+/*
+ * FCoE TX statistics parameters $$KEEP_ENDIANNESS$$
*/
struct fcoe_tx_stat_params {
- u32 fcoe_tx_pkt_cnt;
- u32 fcoe_tx_byte_cnt;
- u32 fcp_tx_pkt_cnt;
- u32 reserved0;
+ __le32 fcoe_tx_pkt_cnt;
+ __le32 fcoe_tx_byte_cnt;
+ __le32 fcp_tx_pkt_cnt;
+ __le32 reserved0;
};
/*
- * FCoE statistics parameters
+ * FCoE statistics parameters $$KEEP_ENDIANNESS$$
*/
struct fcoe_statistics_params {
struct fcoe_tx_stat_params tx_stat;
struct fcoe_rx_stat_params_section0 rx_stat0;
struct fcoe_rx_stat_params_section1 rx_stat1;
+ struct fcoe_rx_stat_params_section2 rx_stat2;
};
/*
- * FCoE t2 hash table entry (64 bytes)
+ * FCoE t2 hash table entry (64 bytes) $$KEEP_ENDIANNESS$$
*/
struct fcoe_t2_hash_table_entry {
struct fcoe_hash_table_entry data;
@@ -1060,11 +970,13 @@
struct regpair reserved0[3];
};
+
+
/*
- * FCoE unsolicited CQE
+ * FCoE unsolicited CQE $$KEEP_ENDIANNESS$$
*/
struct fcoe_unsolicited_cqe {
- u16 wqe;
+ __le16 wqe;
#define FCOE_UNSOLICITED_CQE_SUBTYPE (0x3<<0)
#define FCOE_UNSOLICITED_CQE_SUBTYPE_SHIFT 0
#define FCOE_UNSOLICITED_CQE_PKT_LEN (0xFFF<<2)
@@ -1075,6 +987,4 @@
#define FCOE_UNSOLICITED_CQE_TOGGLE_BIT_SHIFT 15
};
-
-
#endif /* __57XX_FCOE_HSI_LINUX_LE__ */
diff --git a/drivers/scsi/bnx2fc/bnx2fc.h b/drivers/scsi/bnx2fc/bnx2fc.h
index 0a404bf..907672e 100644
--- a/drivers/scsi/bnx2fc/bnx2fc.h
+++ b/drivers/scsi/bnx2fc/bnx2fc.h
@@ -62,7 +62,7 @@
#include "bnx2fc_constants.h"
#define BNX2FC_NAME "bnx2fc"
-#define BNX2FC_VERSION "1.0.1"
+#define BNX2FC_VERSION "1.0.3"
#define PFX "bnx2fc: "
@@ -262,9 +262,14 @@
#define BNX2FC_FLAG_UPLD_REQ_COMPL 0x8
#define BNX2FC_FLAG_EXPL_LOGO 0x9
+ u8 src_addr[ETH_ALEN];
u32 max_sqes;
u32 max_rqes;
u32 max_cqes;
+ atomic_t free_sqes;
+
+ struct b577xx_doorbell_set_prod sq_db;
+ struct b577xx_fcoe_rx_doorbell rx_db;
struct fcoe_sqe *sq;
dma_addr_t sq_dma;
@@ -274,7 +279,7 @@
struct fcoe_cqe *cq;
dma_addr_t cq_dma;
- u32 cq_cons_idx;
+ u16 cq_cons_idx;
u8 cq_curr_toggle_bit;
u32 cq_mem_size;
@@ -505,6 +510,7 @@
struct fc_frame *,
void *),
void *arg, u32 timeout);
+void bnx2fc_arm_cq(struct bnx2fc_rport *tgt);
int bnx2fc_process_new_cqes(struct bnx2fc_rport *tgt);
void bnx2fc_process_cq_compl(struct bnx2fc_rport *tgt, u16 wqe);
struct bnx2fc_rport *bnx2fc_tgt_lookup(struct fcoe_port *port,
diff --git a/drivers/scsi/bnx2fc/bnx2fc_constants.h b/drivers/scsi/bnx2fc/bnx2fc_constants.h
index fe77691..399cda0 100644
--- a/drivers/scsi/bnx2fc/bnx2fc_constants.h
+++ b/drivers/scsi/bnx2fc/bnx2fc_constants.h
@@ -5,6 +5,12 @@
* This file defines HSI constants for the FCoE flows
*/
+/* Current FCoE HSI version number composed of two fields (16 bit) */
+/* Implies on a change broken previous HSI */
+#define FCOE_HSI_MAJOR_VERSION (1)
+/* Implies on a change which does not broken previous HSI */
+#define FCOE_HSI_MINOR_VERSION (1)
+
/* KWQ/KCQ FCoE layer code */
#define FCOE_KWQE_LAYER_CODE (7)
@@ -40,21 +46,62 @@
#define FCOE_KCQE_COMPLETION_STATUS_CTX_ALLOC_FAILURE (0x3)
#define FCOE_KCQE_COMPLETION_STATUS_CTX_FREE_FAILURE (0x4)
#define FCOE_KCQE_COMPLETION_STATUS_NIC_ERROR (0x5)
+#define FCOE_KCQE_COMPLETION_STATUS_WRONG_HSI_VERSION (0x6)
+
+/* CQE type */
+#define FCOE_PENDING_CQE_TYPE 0
+#define FCOE_UNSOLIC_CQE_TYPE 1
/* Unsolicited CQE type */
#define FCOE_UNSOLICITED_FRAME_CQE_TYPE 0
#define FCOE_ERROR_DETECTION_CQE_TYPE 1
#define FCOE_WARNING_DETECTION_CQE_TYPE 2
+/* E_D_TOV timer resolution in ms */
+#define FCOE_E_D_TOV_TIMER_RESOLUTION_MS (20)
+
+/* E_D_TOV timer resolution for SDM (4 micro) */
+#define FCOE_E_D_TOV_SDM_TIMER_RESOLUTION \
+ (FCOE_E_D_TOV_TIMER_RESOLUTION_MS * 1000 / 4)
+
+/* REC timer resolution in ms */
+#define FCOE_REC_TIMER_RESOLUTION_MS (20)
+
+/* REC timer resolution for SDM (4 micro) */
+#define FCOE_REC_SDM_TIMER_RESOLUTION (FCOE_REC_TIMER_RESOLUTION_MS * 1000 / 4)
+
+/* E_D_TOV timer default wraparound value (2 sec) in 20 ms resolution */
+#define FCOE_E_D_TOV_DEFAULT_WRAPAROUND_VAL \
+ (2000 / FCOE_E_D_TOV_TIMER_RESOLUTION_MS)
+
+/* REC_TOV timer default wraparound value (3 sec) in 20 ms resolution */
+#define FCOE_REC_TOV_DEFAULT_WRAPAROUND_VAL \
+ (3000 / FCOE_REC_TIMER_RESOLUTION_MS)
+
+#define FCOE_NUM_OF_TIMER_TASKS (8 * 1024)
+
+#define FCOE_NUM_OF_CACHED_TASKS_TIMER (8)
+
/* Task context constants */
+/******** Remove FCP_CMD write tce sleep ***********************/
+/* In case timer services are required then shall be updated by Xstorm after
+ * start processing the task. In case no timer facilities are required then the
+ * driver would initialize the state to this value
+ *
+#define FCOE_TASK_TX_STATE_NORMAL 0
+ * After driver has initialize the task in case timer services required *
+#define FCOE_TASK_TX_STATE_INIT 1
+******** Remove FCP_CMD write tce sleep ***********************/
/* After driver has initialize the task in case timer services required */
#define FCOE_TASK_TX_STATE_INIT 0
/* In case timer services are required then shall be updated by Xstorm after
* start processing the task. In case no timer facilities are required then the
- * driver would initialize the state to this value */
+ * driver would initialize the state to this value
+ */
#define FCOE_TASK_TX_STATE_NORMAL 1
/* Task is under abort procedure. Updated in order to stop processing of
- * pending WQEs on this task */
+ * pending WQEs on this task
+ */
#define FCOE_TASK_TX_STATE_ABORT 2
/* For E_D_T_TOV timer expiration in Xstorm (Class 2 only) */
#define FCOE_TASK_TX_STATE_ERROR 3
@@ -66,17 +113,8 @@
#define FCOE_TASK_TX_STATE_EXCHANGE_CLEANUP 6
/* For sequence cleanup request task */
#define FCOE_TASK_TX_STATE_SEQUENCE_CLEANUP 7
-/* Mark task as aborted and indicate that ABTS was not transmitted */
-#define FCOE_TASK_TX_STATE_BEFORE_ABTS_TX 8
-/* Mark task as aborted and indicate that ABTS was transmitted */
-#define FCOE_TASK_TX_STATE_AFTER_ABTS_TX 9
/* For completion the ABTS task. */
-#define FCOE_TASK_TX_STATE_ABTS_TX_COMPLETED 10
-/* Mark task as aborted and indicate that Exchange cleanup was not transmitted
- */
-#define FCOE_TASK_TX_STATE_BEFORE_EXCHANGE_CLEANUP_TX 11
-/* Mark task as aborted and indicate that Exchange cleanup was transmitted */
-#define FCOE_TASK_TX_STATE_AFTER_EXCHANGE_CLEANUP_TX 12
+#define FCOE_TASK_TX_STATE_ABTS_TX 8
#define FCOE_TASK_RX_STATE_NORMAL 0
#define FCOE_TASK_RX_STATE_COMPLETED 1
@@ -86,25 +124,25 @@
#define FCOE_TASK_RX_STATE_WARNING 3
/* For E_D_T_TOV timer expiration in Ustorm */
#define FCOE_TASK_RX_STATE_ERROR 4
-/* ABTS ACC arrived wait for local completion to finally complete the task. */
-#define FCOE_TASK_RX_STATE_ABTS_ACC_ARRIVED 5
-/* local completion arrived wait for ABTS ACC to finally complete the task. */
-#define FCOE_TASK_RX_STATE_ABTS_LOCAL_COMP_ARRIVED 6
+/* FW only: First visit at rx-path, part of the abts round trip */
+#define FCOE_TASK_RX_STATE_ABTS_IN_PROCESS 5
+/* FW only: Second visit at rx-path, after ABTS frame transmitted */
+#define FCOE_TASK_RX_STATE_ABTS_TRANSMITTED 6
/* Special completion indication in case of task was aborted. */
#define FCOE_TASK_RX_STATE_ABTS_COMPLETED 7
-/* Special completion indication in case of task was cleaned. */
-#define FCOE_TASK_RX_STATE_EXCHANGE_CLEANUP_COMPLETED 8
-/* Special completion indication (in task requested the exchange cleanup) in
- * case cleaned task is in non-valid. */
-#define FCOE_TASK_RX_STATE_ABORT_CLEANUP_COMPLETED 9
+/* FW only: First visit at rx-path, part of the cleanup round trip */
+#define FCOE_TASK_RX_STATE_EXCHANGE_CLEANUP_IN_PROCESS 8
+/* FW only: Special completion indication in case of task was cleaned. */
+#define FCOE_TASK_RX_STATE_EXCHANGE_CLEANUP_COMPLETED 9
+/* Not in used: Special completion indication (in task requested the exchange
+ * cleanup) in case cleaned task is in non-valid.
+ */
+#define FCOE_TASK_RX_STATE_ABORT_CLEANUP_COMPLETED 10
/* Special completion indication (in task requested the sequence cleanup) in
- * case cleaned task was already returned to normal. */
-#define FCOE_TASK_RX_STATE_IGNORED_SEQUENCE_CLEANUP 10
-/* Exchange cleanup arrived wait until xfer will be handled to finally
- * complete the task. */
-#define FCOE_TASK_RX_STATE_EXCHANGE_CLEANUP_ARRIVED 11
-/* Xfer handled, wait for exchange cleanup to finally complete the task. */
-#define FCOE_TASK_RX_STATE_EXCHANGE_CLEANUP_HANDLED_XFER 12
+ * case cleaned task was already returned to normal.
+ */
+#define FCOE_TASK_RX_STATE_IGNORED_SEQUENCE_CLEANUP 11
+
#define FCOE_TASK_TYPE_WRITE 0
#define FCOE_TASK_TYPE_READ 1
@@ -120,11 +158,40 @@
#define FCOE_TASK_CLASS_TYPE_3 0
#define FCOE_TASK_CLASS_TYPE_2 1
+/* FCoE/FC packet fields */
+#define FCOE_ETH_TYPE 0x8906
+
+/* FCoE maximum elements in hash table */
+#define FCOE_MAX_ELEMENTS_IN_HASH_TABLE_ROW 8
+
+/* FCoE half of the elements in hash table */
+#define FCOE_HALF_ELEMENTS_IN_HASH_TABLE_ROW \
+ (FCOE_MAX_ELEMENTS_IN_HASH_TABLE_ROW / 2)
+
+/* FcoE number of cached T2 entries */
+#define T_FCOE_NUMBER_OF_CACHED_T2_ENTRIES (4)
+
+/* FCoE maximum elements in hash table */
+#define FCOE_HASH_TBL_CHUNK_SIZE 16384
+
/* Everest FCoE connection type */
#define B577XX_FCOE_CONNECTION_TYPE 4
-/* Error codes for Error Reporting in fast path flows */
-/* XFER error codes */
+/* FCoE number of rows (in log). This number derives
+ * from the maximum connections supported which is 2048.
+ * TBA: Need a different constant for E2
+ */
+#define FCOE_MAX_NUM_SESSIONS_LOG 11
+
+#define FC_ABTS_REPLY_MAX_PAYLOAD_LEN 12
+
+/* Error codes for Error Reporting in slow path flows */
+#define FCOE_SLOW_PATH_ERROR_CODE_TOO_MANY_FUNCS 0
+#define FCOE_SLOW_PATH_ERROR_CODE_NO_LICENSE 1
+
+/* Error codes for Error Reporting in fast path flows
+ * XFER error codes
+ */
#define FCOE_ERROR_CODE_XFER_OOO_RO 0
#define FCOE_ERROR_CODE_XFER_RO_NOT_ALIGNED 1
#define FCOE_ERROR_CODE_XFER_NULL_BURST_LEN 2
@@ -155,17 +222,17 @@
#define FCOE_ERROR_CODE_DATA_SOFI3_SEQ_ACTIVE_SET 23
#define FCOE_ERROR_CODE_DATA_SOFN_SEQ_ACTIVE_RESET 24
#define FCOE_ERROR_CODE_DATA_EOFN_END_SEQ_SET 25
-#define FCOE_ERROR_CODE_DATA_EOFT_END_SEQ_RESET 26
-#define FCOE_ERROR_CODE_DATA_TASK_TYPE_NOT_READ 27
+#define FCOE_ERROR_CODE_DATA_EOFT_END_SEQ_RESET 26
+#define FCOE_ERROR_CODE_DATA_TASK_TYPE_NOT_READ 27
#define FCOE_ERROR_CODE_DATA_FCTL 28
/* Middle path error codes */
-#define FCOE_ERROR_CODE_MIDPATH_TYPE_NOT_ELS 29
+#define FCOE_ERROR_CODE_MIDPATH_INVALID_TYPE 29
#define FCOE_ERROR_CODE_MIDPATH_SOFI3_SEQ_ACTIVE_SET 30
#define FCOE_ERROR_CODE_MIDPATH_SOFN_SEQ_ACTIVE_RESET 31
#define FCOE_ERROR_CODE_MIDPATH_EOFN_END_SEQ_SET 32
#define FCOE_ERROR_CODE_MIDPATH_EOFT_END_SEQ_RESET 33
-#define FCOE_ERROR_CODE_MIDPATH_ELS_REPLY_FCTL 34
+#define FCOE_ERROR_CODE_MIDPATH_REPLY_FCTL 34
#define FCOE_ERROR_CODE_MIDPATH_INVALID_REPLY 35
#define FCOE_ERROR_CODE_MIDPATH_ELS_REPLY_RCTL 36
@@ -173,7 +240,7 @@
#define FCOE_ERROR_CODE_ABTS_REPLY_F_CTL 37
#define FCOE_ERROR_CODE_ABTS_REPLY_DDF_RCTL_FIELD 38
#define FCOE_ERROR_CODE_ABTS_REPLY_INVALID_BLS_RCTL 39
-#define FCOE_ERROR_CODE_ABTS_REPLY_INVALID_RCTL 40
+#define FCOE_ERROR_CODE_ABTS_REPLY_INVALID_RCTL 40
#define FCOE_ERROR_CODE_ABTS_REPLY_RCTL_GENERAL_MISMATCH 41
/* Common error codes */
@@ -185,7 +252,7 @@
#define FCOE_ERROR_CODE_COMMON_DATA_NO_MORE_SGES 47
#define FCOE_ERROR_CODE_COMMON_OPTIONAL_FC_HDR 48
#define FCOE_ERROR_CODE_COMMON_READ_TCE_OX_ID_TOO_BIG 49
-#define FCOE_ERROR_CODE_COMMON_DATA_WAS_NOT_TRANSMITTED 50
+#define FCOE_ERROR_CODE_COMMON_DATA_WAS_NOT_TRANSMITTED 50
/* Unsolicited Rx error codes */
#define FCOE_ERROR_CODE_UNSOLICITED_TYPE_NOT_ELS 51
diff --git a/drivers/scsi/bnx2fc/bnx2fc_els.c b/drivers/scsi/bnx2fc/bnx2fc_els.c
index 52c3584..7e89143 100644
--- a/drivers/scsi/bnx2fc/bnx2fc_els.c
+++ b/drivers/scsi/bnx2fc/bnx2fc_els.c
@@ -83,7 +83,7 @@
rrq.rrq_cmd = ELS_RRQ;
hton24(rrq.rrq_s_id, sid);
rrq.rrq_ox_id = htons(aborted_io_req->xid);
- rrq.rrq_rx_id = htons(aborted_io_req->task->rx_wr_tx_rd.rx_id);
+ rrq.rrq_rx_id = htons(aborted_io_req->task->rxwr_txrd.var_ctx.rx_id);
retry_rrq:
rc = bnx2fc_initiate_els(tgt, ELS_RRQ, &rrq, sizeof(rrq),
@@ -417,12 +417,13 @@
hdr = (u64 *)fc_hdr;
temp_hdr = (u64 *)
- &task->cmn.general.cmd_info.mp_fc_frame.fc_hdr;
+ &task->rxwr_only.union_ctx.comp_info.mp_rsp.fc_hdr;
hdr[0] = cpu_to_be64(temp_hdr[0]);
hdr[1] = cpu_to_be64(temp_hdr[1]);
hdr[2] = cpu_to_be64(temp_hdr[2]);
- mp_req->resp_len = task->rx_wr_only.sgl_ctx.mul_sges.cur_sge_off;
+ mp_req->resp_len =
+ task->rxwr_only.union_ctx.comp_info.mp_rsp.mp_payload_len;
/* Parse ELS response */
if ((els_req->cb_func) && (els_req->cb_arg)) {
diff --git a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c
index ab255fb..7a16ca1 100644
--- a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c
+++ b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c
@@ -21,7 +21,7 @@
#define DRV_MODULE_NAME "bnx2fc"
#define DRV_MODULE_VERSION BNX2FC_VERSION
-#define DRV_MODULE_RELDATE "Mar 17, 2011"
+#define DRV_MODULE_RELDATE "Jun 10, 2011"
static char version[] __devinitdata =
@@ -612,7 +612,7 @@
BNX2FC_HBA_DBG(lport, "FW stat req timed out\n");
return bnx2fc_stats;
}
- bnx2fc_stats->invalid_crc_count += fw_stats->rx_stat1.fc_crc_cnt;
+ bnx2fc_stats->invalid_crc_count += fw_stats->rx_stat2.fc_crc_cnt;
bnx2fc_stats->tx_frames += fw_stats->tx_stat.fcoe_tx_pkt_cnt;
bnx2fc_stats->tx_words += (fw_stats->tx_stat.fcoe_tx_byte_cnt) / 4;
bnx2fc_stats->rx_frames += fw_stats->rx_stat0.fcoe_rx_pkt_cnt;
diff --git a/drivers/scsi/bnx2fc/bnx2fc_hwi.c b/drivers/scsi/bnx2fc/bnx2fc_hwi.c
index f756d5f..d8e8a82 100644
--- a/drivers/scsi/bnx2fc/bnx2fc_hwi.c
+++ b/drivers/scsi/bnx2fc/bnx2fc_hwi.c
@@ -100,6 +100,9 @@
fcoe_init2.hdr.flags = (FCOE_KWQE_LAYER_CODE <<
FCOE_KWQE_HEADER_LAYER_CODE_SHIFT);
+ fcoe_init2.hsi_major_version = FCOE_HSI_MAJOR_VERSION;
+ fcoe_init2.hsi_minor_version = FCOE_HSI_MINOR_VERSION;
+
fcoe_init2.hash_tbl_pbl_addr_lo = (u32) hba->hash_tbl_pbl_dma;
fcoe_init2.hash_tbl_pbl_addr_hi = (u32)
((u64) hba->hash_tbl_pbl_dma >> 32);
@@ -122,6 +125,7 @@
fcoe_init3.error_bit_map_lo = 0xffffffff;
fcoe_init3.error_bit_map_hi = 0xffffffff;
+ fcoe_init3.perf_config = 1;
kwqe_arr[0] = (struct kwqe *) &fcoe_init1;
kwqe_arr[1] = (struct kwqe *) &fcoe_init2;
@@ -289,19 +293,19 @@
ofld_req4.e_d_tov_timer_val = lport->e_d_tov / 20;
- ofld_req4.src_mac_addr_lo32[0] = port->data_src_addr[5];
+ ofld_req4.src_mac_addr_lo[0] = port->data_src_addr[5];
/* local mac */
- ofld_req4.src_mac_addr_lo32[1] = port->data_src_addr[4];
- ofld_req4.src_mac_addr_lo32[2] = port->data_src_addr[3];
- ofld_req4.src_mac_addr_lo32[3] = port->data_src_addr[2];
- ofld_req4.src_mac_addr_hi16[0] = port->data_src_addr[1];
- ofld_req4.src_mac_addr_hi16[1] = port->data_src_addr[0];
- ofld_req4.dst_mac_addr_lo32[0] = hba->ctlr.dest_addr[5];/* fcf mac */
- ofld_req4.dst_mac_addr_lo32[1] = hba->ctlr.dest_addr[4];
- ofld_req4.dst_mac_addr_lo32[2] = hba->ctlr.dest_addr[3];
- ofld_req4.dst_mac_addr_lo32[3] = hba->ctlr.dest_addr[2];
- ofld_req4.dst_mac_addr_hi16[0] = hba->ctlr.dest_addr[1];
- ofld_req4.dst_mac_addr_hi16[1] = hba->ctlr.dest_addr[0];
+ ofld_req4.src_mac_addr_lo[1] = port->data_src_addr[4];
+ ofld_req4.src_mac_addr_mid[0] = port->data_src_addr[3];
+ ofld_req4.src_mac_addr_mid[1] = port->data_src_addr[2];
+ ofld_req4.src_mac_addr_hi[0] = port->data_src_addr[1];
+ ofld_req4.src_mac_addr_hi[1] = port->data_src_addr[0];
+ ofld_req4.dst_mac_addr_lo[0] = hba->ctlr.dest_addr[5];/* fcf mac */
+ ofld_req4.dst_mac_addr_lo[1] = hba->ctlr.dest_addr[4];
+ ofld_req4.dst_mac_addr_mid[0] = hba->ctlr.dest_addr[3];
+ ofld_req4.dst_mac_addr_mid[1] = hba->ctlr.dest_addr[2];
+ ofld_req4.dst_mac_addr_hi[0] = hba->ctlr.dest_addr[1];
+ ofld_req4.dst_mac_addr_hi[1] = hba->ctlr.dest_addr[0];
ofld_req4.lcq_addr_lo = (u32) tgt->lcq_dma;
ofld_req4.lcq_addr_hi = (u32)((u64) tgt->lcq_dma >> 32);
@@ -345,20 +349,21 @@
enbl_req.hdr.flags =
(FCOE_KWQE_LAYER_CODE << FCOE_KWQE_HEADER_LAYER_CODE_SHIFT);
- enbl_req.src_mac_addr_lo32[0] = port->data_src_addr[5];
+ enbl_req.src_mac_addr_lo[0] = port->data_src_addr[5];
/* local mac */
- enbl_req.src_mac_addr_lo32[1] = port->data_src_addr[4];
- enbl_req.src_mac_addr_lo32[2] = port->data_src_addr[3];
- enbl_req.src_mac_addr_lo32[3] = port->data_src_addr[2];
- enbl_req.src_mac_addr_hi16[0] = port->data_src_addr[1];
- enbl_req.src_mac_addr_hi16[1] = port->data_src_addr[0];
+ enbl_req.src_mac_addr_lo[1] = port->data_src_addr[4];
+ enbl_req.src_mac_addr_mid[0] = port->data_src_addr[3];
+ enbl_req.src_mac_addr_mid[1] = port->data_src_addr[2];
+ enbl_req.src_mac_addr_hi[0] = port->data_src_addr[1];
+ enbl_req.src_mac_addr_hi[1] = port->data_src_addr[0];
+ memcpy(tgt->src_addr, port->data_src_addr, ETH_ALEN);
- enbl_req.dst_mac_addr_lo32[0] = hba->ctlr.dest_addr[5];/* fcf mac */
- enbl_req.dst_mac_addr_lo32[1] = hba->ctlr.dest_addr[4];
- enbl_req.dst_mac_addr_lo32[2] = hba->ctlr.dest_addr[3];
- enbl_req.dst_mac_addr_lo32[3] = hba->ctlr.dest_addr[2];
- enbl_req.dst_mac_addr_hi16[0] = hba->ctlr.dest_addr[1];
- enbl_req.dst_mac_addr_hi16[1] = hba->ctlr.dest_addr[0];
+ enbl_req.dst_mac_addr_lo[0] = hba->ctlr.dest_addr[5];/* fcf mac */
+ enbl_req.dst_mac_addr_lo[1] = hba->ctlr.dest_addr[4];
+ enbl_req.dst_mac_addr_mid[0] = hba->ctlr.dest_addr[3];
+ enbl_req.dst_mac_addr_mid[1] = hba->ctlr.dest_addr[2];
+ enbl_req.dst_mac_addr_hi[0] = hba->ctlr.dest_addr[1];
+ enbl_req.dst_mac_addr_hi[1] = hba->ctlr.dest_addr[0];
port_id = fc_host_port_id(lport->host);
if (port_id != tgt->sid) {
@@ -411,18 +416,19 @@
disable_req.hdr.flags =
(FCOE_KWQE_LAYER_CODE << FCOE_KWQE_HEADER_LAYER_CODE_SHIFT);
- disable_req.src_mac_addr_lo32[0] = port->data_src_addr[5];
- disable_req.src_mac_addr_lo32[2] = port->data_src_addr[3];
- disable_req.src_mac_addr_lo32[3] = port->data_src_addr[2];
- disable_req.src_mac_addr_hi16[0] = port->data_src_addr[1];
- disable_req.src_mac_addr_hi16[1] = port->data_src_addr[0];
+ disable_req.src_mac_addr_lo[0] = tgt->src_addr[5];
+ disable_req.src_mac_addr_lo[1] = tgt->src_addr[4];
+ disable_req.src_mac_addr_mid[0] = tgt->src_addr[3];
+ disable_req.src_mac_addr_mid[1] = tgt->src_addr[2];
+ disable_req.src_mac_addr_hi[0] = tgt->src_addr[1];
+ disable_req.src_mac_addr_hi[1] = tgt->src_addr[0];
- disable_req.dst_mac_addr_lo32[0] = hba->ctlr.dest_addr[5];/* fcf mac */
- disable_req.dst_mac_addr_lo32[1] = hba->ctlr.dest_addr[4];
- disable_req.dst_mac_addr_lo32[2] = hba->ctlr.dest_addr[3];
- disable_req.dst_mac_addr_lo32[3] = hba->ctlr.dest_addr[2];
- disable_req.dst_mac_addr_hi16[0] = hba->ctlr.dest_addr[1];
- disable_req.dst_mac_addr_hi16[1] = hba->ctlr.dest_addr[0];
+ disable_req.dst_mac_addr_lo[0] = hba->ctlr.dest_addr[5];/* fcf mac */
+ disable_req.dst_mac_addr_lo[1] = hba->ctlr.dest_addr[4];
+ disable_req.dst_mac_addr_mid[0] = hba->ctlr.dest_addr[3];
+ disable_req.dst_mac_addr_mid[1] = hba->ctlr.dest_addr[2];
+ disable_req.dst_mac_addr_hi[0] = hba->ctlr.dest_addr[1];
+ disable_req.dst_mac_addr_hi[1] = hba->ctlr.dest_addr[0];
port_id = tgt->sid;
disable_req.s_id[0] = (port_id & 0x000000FF);
@@ -640,10 +646,10 @@
xid = err_entry->fc_hdr.ox_id;
BNX2FC_TGT_DBG(tgt, "Unsol Error Frame OX_ID = 0x%x\n", xid);
BNX2FC_TGT_DBG(tgt, "err_warn_bitmap = %08x:%08x\n",
- err_entry->err_warn_bitmap_hi,
- err_entry->err_warn_bitmap_lo);
+ err_entry->data.err_warn_bitmap_hi,
+ err_entry->data.err_warn_bitmap_lo);
BNX2FC_TGT_DBG(tgt, "buf_offsets - tx = 0x%x, rx = 0x%x\n",
- err_entry->tx_buf_off, err_entry->rx_buf_off);
+ err_entry->data.tx_buf_off, err_entry->data.rx_buf_off);
bnx2fc_return_rqe(tgt, 1);
@@ -722,10 +728,10 @@
xid = cpu_to_be16(err_entry->fc_hdr.ox_id);
BNX2FC_TGT_DBG(tgt, "Unsol Warning Frame OX_ID = 0x%x\n", xid);
BNX2FC_TGT_DBG(tgt, "err_warn_bitmap = %08x:%08x",
- err_entry->err_warn_bitmap_hi,
- err_entry->err_warn_bitmap_lo);
+ err_entry->data.err_warn_bitmap_hi,
+ err_entry->data.err_warn_bitmap_lo);
BNX2FC_TGT_DBG(tgt, "buf_offsets - tx = 0x%x, rx = 0x%x",
- err_entry->tx_buf_off, err_entry->rx_buf_off);
+ err_entry->data.tx_buf_off, err_entry->data.rx_buf_off);
bnx2fc_return_rqe(tgt, 1);
spin_unlock_bh(&tgt->tgt_lock);
@@ -762,9 +768,9 @@
task_page = (struct fcoe_task_ctx_entry *)hba->task_ctx[task_idx];
task = &(task_page[index]);
- num_rq = ((task->rx_wr_tx_rd.rx_flags &
- FCOE_TASK_CTX_ENTRY_RXWR_TXRD_NUM_RQ_WQE) >>
- FCOE_TASK_CTX_ENTRY_RXWR_TXRD_NUM_RQ_WQE_SHIFT);
+ num_rq = ((task->rxwr_txrd.var_ctx.rx_flags &
+ FCOE_TCE_RX_WR_TX_RD_VAR_NUM_RQ_WQE) >>
+ FCOE_TCE_RX_WR_TX_RD_VAR_NUM_RQ_WQE_SHIFT);
io_req = (struct bnx2fc_cmd *)hba->cmd_mgr->cmds[xid];
@@ -777,22 +783,19 @@
/* Timestamp IO completion time */
cmd_type = io_req->cmd_type;
- /* optimized completion path */
- if (cmd_type == BNX2FC_SCSI_CMD) {
- rx_state = ((task->rx_wr_tx_rd.rx_flags &
- FCOE_TASK_CTX_ENTRY_RXWR_TXRD_RX_STATE) >>
- FCOE_TASK_CTX_ENTRY_RXWR_TXRD_RX_STATE_SHIFT);
+ rx_state = ((task->rxwr_txrd.var_ctx.rx_flags &
+ FCOE_TCE_RX_WR_TX_RD_VAR_RX_STATE) >>
+ FCOE_TCE_RX_WR_TX_RD_VAR_RX_STATE_SHIFT);
+ /* Process other IO completion types */
+ switch (cmd_type) {
+ case BNX2FC_SCSI_CMD:
if (rx_state == FCOE_TASK_RX_STATE_COMPLETED) {
bnx2fc_process_scsi_cmd_compl(io_req, task, num_rq);
spin_unlock_bh(&tgt->tgt_lock);
return;
}
- }
- /* Process other IO completion types */
- switch (cmd_type) {
- case BNX2FC_SCSI_CMD:
if (rx_state == FCOE_TASK_RX_STATE_ABTS_COMPLETED)
bnx2fc_process_abts_compl(io_req, task, num_rq);
else if (rx_state ==
@@ -819,8 +822,16 @@
break;
case BNX2FC_ELS:
- BNX2FC_IO_DBG(io_req, "cq_compl - call process_els_compl\n");
- bnx2fc_process_els_compl(io_req, task, num_rq);
+ if (rx_state == FCOE_TASK_RX_STATE_COMPLETED)
+ bnx2fc_process_els_compl(io_req, task, num_rq);
+ else if (rx_state == FCOE_TASK_RX_STATE_ABTS_COMPLETED)
+ bnx2fc_process_abts_compl(io_req, task, num_rq);
+ else if (rx_state ==
+ FCOE_TASK_RX_STATE_EXCHANGE_CLEANUP_COMPLETED)
+ bnx2fc_process_cleanup_compl(io_req, task, num_rq);
+ else
+ printk(KERN_ERR PFX "Invalid rx state = %d\n",
+ rx_state);
break;
case BNX2FC_CLEANUP:
@@ -835,6 +846,20 @@
spin_unlock_bh(&tgt->tgt_lock);
}
+void bnx2fc_arm_cq(struct bnx2fc_rport *tgt)
+{
+ struct b577xx_fcoe_rx_doorbell *rx_db = &tgt->rx_db;
+ u32 msg;
+
+ wmb();
+ rx_db->doorbell_cq_cons = tgt->cq_cons_idx | (tgt->cq_curr_toggle_bit <<
+ FCOE_CQE_TOGGLE_BIT_SHIFT);
+ msg = *((u32 *)rx_db);
+ writel(cpu_to_le32(msg), tgt->ctx_base);
+ mmiowb();
+
+}
+
struct bnx2fc_work *bnx2fc_alloc_work(struct bnx2fc_rport *tgt, u16 wqe)
{
struct bnx2fc_work *work;
@@ -853,8 +878,8 @@
struct fcoe_cqe *cq;
u32 cq_cons;
struct fcoe_cqe *cqe;
+ u32 num_free_sqes = 0;
u16 wqe;
- bool more_cqes_found = false;
/*
* cq_lock is a low contention lock used to protect
@@ -872,62 +897,51 @@
cq_cons = tgt->cq_cons_idx;
cqe = &cq[cq_cons];
- do {
- more_cqes_found ^= true;
+ while (((wqe = cqe->wqe) & FCOE_CQE_TOGGLE_BIT) ==
+ (tgt->cq_curr_toggle_bit <<
+ FCOE_CQE_TOGGLE_BIT_SHIFT)) {
- while (((wqe = cqe->wqe) & FCOE_CQE_TOGGLE_BIT) ==
- (tgt->cq_curr_toggle_bit <<
- FCOE_CQE_TOGGLE_BIT_SHIFT)) {
+ /* new entry on the cq */
+ if (wqe & FCOE_CQE_CQE_TYPE) {
+ /* Unsolicited event notification */
+ bnx2fc_process_unsol_compl(tgt, wqe);
+ } else {
+ /* Pending work request completion */
+ struct bnx2fc_work *work = NULL;
+ struct bnx2fc_percpu_s *fps = NULL;
+ unsigned int cpu = wqe % num_possible_cpus();
- /* new entry on the cq */
- if (wqe & FCOE_CQE_CQE_TYPE) {
- /* Unsolicited event notification */
- bnx2fc_process_unsol_compl(tgt, wqe);
- } else {
- struct bnx2fc_work *work = NULL;
- struct bnx2fc_percpu_s *fps = NULL;
- unsigned int cpu = wqe % num_possible_cpus();
+ fps = &per_cpu(bnx2fc_percpu, cpu);
+ spin_lock_bh(&fps->fp_work_lock);
+ if (unlikely(!fps->iothread))
+ goto unlock;
- fps = &per_cpu(bnx2fc_percpu, cpu);
- spin_lock_bh(&fps->fp_work_lock);
- if (unlikely(!fps->iothread))
- goto unlock;
-
- work = bnx2fc_alloc_work(tgt, wqe);
- if (work)
- list_add_tail(&work->list,
- &fps->work_list);
+ work = bnx2fc_alloc_work(tgt, wqe);
+ if (work)
+ list_add_tail(&work->list,
+ &fps->work_list);
unlock:
- spin_unlock_bh(&fps->fp_work_lock);
+ spin_unlock_bh(&fps->fp_work_lock);
- /* Pending work request completion */
- if (fps->iothread && work)
- wake_up_process(fps->iothread);
- else
- bnx2fc_process_cq_compl(tgt, wqe);
- }
- cqe++;
- tgt->cq_cons_idx++;
-
- if (tgt->cq_cons_idx == BNX2FC_CQ_WQES_MAX) {
- tgt->cq_cons_idx = 0;
- cqe = cq;
- tgt->cq_curr_toggle_bit =
- 1 - tgt->cq_curr_toggle_bit;
- }
+ /* Pending work request completion */
+ if (fps->iothread && work)
+ wake_up_process(fps->iothread);
+ else
+ bnx2fc_process_cq_compl(tgt, wqe);
}
- /* Re-arm CQ */
- if (more_cqes_found) {
- tgt->conn_db->cq_arm.lo = -1;
- wmb();
+ cqe++;
+ tgt->cq_cons_idx++;
+ num_free_sqes++;
+
+ if (tgt->cq_cons_idx == BNX2FC_CQ_WQES_MAX) {
+ tgt->cq_cons_idx = 0;
+ cqe = cq;
+ tgt->cq_curr_toggle_bit =
+ 1 - tgt->cq_curr_toggle_bit;
}
- } while (more_cqes_found);
-
- /*
- * Commit tgt->cq_cons_idx change to the memory
- * spin_lock implies full memory barrier, no need to smp_wmb
- */
-
+ }
+ bnx2fc_arm_cq(tgt);
+ atomic_add(num_free_sqes, &tgt->free_sqes);
spin_unlock_bh(&tgt->cq_lock);
return 0;
}
@@ -1141,7 +1155,11 @@
case FCOE_KCQE_COMPLETION_STATUS_NIC_ERROR:
printk(KERN_ERR PFX "init_failure due to NIC error\n");
break;
-
+ case FCOE_KCQE_COMPLETION_STATUS_ERROR:
+ printk(KERN_ERR PFX "init failure due to compl status err\n");
+ break;
+ case FCOE_KCQE_COMPLETION_STATUS_WRONG_HSI_VERSION:
+ printk(KERN_ERR PFX "init failure due to HSI mismatch\n");
default:
printk(KERN_ERR PFX "Unknown Error code %d\n", err_code);
}
@@ -1247,21 +1265,14 @@
void bnx2fc_ring_doorbell(struct bnx2fc_rport *tgt)
{
- struct b577xx_doorbell_set_prod ev_doorbell;
+ struct b577xx_doorbell_set_prod *sq_db = &tgt->sq_db;
u32 msg;
wmb();
-
- memset(&ev_doorbell, 0, sizeof(struct b577xx_doorbell_set_prod));
- ev_doorbell.header.header = B577XX_DOORBELL_HDR_DB_TYPE;
-
- ev_doorbell.prod = tgt->sq_prod_idx |
+ sq_db->prod = tgt->sq_prod_idx |
(tgt->sq_curr_toggle_bit << 15);
- ev_doorbell.header.header |= B577XX_FCOE_CONNECTION_TYPE <<
- B577XX_DOORBELL_HDR_CONN_TYPE_SHIFT;
- msg = *((u32 *)&ev_doorbell);
+ msg = *((u32 *)sq_db);
writel(cpu_to_le32(msg), tgt->ctx_base);
-
mmiowb();
}
@@ -1322,18 +1333,26 @@
memset(task, 0, sizeof(struct fcoe_task_ctx_entry));
/* Tx Write Rx Read */
- task->tx_wr_rx_rd.tx_flags = FCOE_TASK_TX_STATE_EXCHANGE_CLEANUP <<
- FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TX_STATE_SHIFT;
- task->tx_wr_rx_rd.init_flags = task_type <<
- FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TASK_TYPE_SHIFT;
- task->tx_wr_rx_rd.init_flags |= FCOE_TASK_CLASS_TYPE_3 <<
- FCOE_TASK_CTX_ENTRY_TXWR_RXRD_CLASS_TYPE_SHIFT;
- /* Common */
- task->cmn.common_flags = context_id <<
- FCOE_TASK_CTX_ENTRY_TX_RX_CMN_CID_SHIFT;
- task->cmn.general.cleanup_info.task_id = orig_xid;
+ /* init flags */
+ task->txwr_rxrd.const_ctx.init_flags = task_type <<
+ FCOE_TCE_TX_WR_RX_RD_CONST_TASK_TYPE_SHIFT;
+ task->txwr_rxrd.const_ctx.init_flags |= FCOE_TASK_CLASS_TYPE_3 <<
+ FCOE_TCE_TX_WR_RX_RD_CONST_CLASS_TYPE_SHIFT;
+ task->txwr_rxrd.const_ctx.init_flags |=
+ FCOE_TASK_DEV_TYPE_DISK <<
+ FCOE_TCE_TX_WR_RX_RD_CONST_DEV_TYPE_SHIFT;
+ task->txwr_rxrd.union_ctx.cleanup.ctx.cleaned_task_id = orig_xid;
+ /* Tx flags */
+ task->txwr_rxrd.const_ctx.tx_flags =
+ FCOE_TASK_TX_STATE_EXCHANGE_CLEANUP <<
+ FCOE_TCE_TX_WR_RX_RD_CONST_TX_STATE_SHIFT;
+ /* Rx Read Tx Write */
+ task->rxwr_txrd.const_ctx.init_flags = context_id <<
+ FCOE_TCE_RX_WR_TX_RD_CONST_CID_SHIFT;
+ task->rxwr_txrd.var_ctx.rx_flags |= 1 <<
+ FCOE_TCE_RX_WR_TX_RD_VAR_EXP_FIRST_FRAME_SHIFT;
}
void bnx2fc_init_mp_task(struct bnx2fc_cmd *io_req,
@@ -1342,6 +1361,7 @@
struct bnx2fc_mp_req *mp_req = &(io_req->mp_req);
struct bnx2fc_rport *tgt = io_req->tgt;
struct fc_frame_header *fc_hdr;
+ struct fcoe_ext_mul_sges_ctx *sgl;
u8 task_type = 0;
u64 *hdr;
u64 temp_hdr[3];
@@ -1367,47 +1387,49 @@
/* Tx only */
if ((task_type == FCOE_TASK_TYPE_MIDPATH) ||
(task_type == FCOE_TASK_TYPE_UNSOLICITED)) {
- task->tx_wr_only.sgl_ctx.mul_sges.cur_sge_addr.lo =
+ task->txwr_only.sgl_ctx.sgl.mul_sgl.cur_sge_addr.lo =
(u32)mp_req->mp_req_bd_dma;
- task->tx_wr_only.sgl_ctx.mul_sges.cur_sge_addr.hi =
+ task->txwr_only.sgl_ctx.sgl.mul_sgl.cur_sge_addr.hi =
(u32)((u64)mp_req->mp_req_bd_dma >> 32);
- task->tx_wr_only.sgl_ctx.mul_sges.sgl_size = 1;
- BNX2FC_IO_DBG(io_req, "init_mp_task - bd_dma = 0x%llx\n",
- (unsigned long long)mp_req->mp_req_bd_dma);
+ task->txwr_only.sgl_ctx.sgl.mul_sgl.sgl_size = 1;
}
/* Tx Write Rx Read */
- task->tx_wr_rx_rd.tx_flags = FCOE_TASK_TX_STATE_INIT <<
- FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TX_STATE_SHIFT;
- task->tx_wr_rx_rd.init_flags = task_type <<
- FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TASK_TYPE_SHIFT;
- task->tx_wr_rx_rd.init_flags |= FCOE_TASK_DEV_TYPE_DISK <<
- FCOE_TASK_CTX_ENTRY_TXWR_RXRD_DEV_TYPE_SHIFT;
- task->tx_wr_rx_rd.init_flags |= FCOE_TASK_CLASS_TYPE_3 <<
- FCOE_TASK_CTX_ENTRY_TXWR_RXRD_CLASS_TYPE_SHIFT;
+ /* init flags */
+ task->txwr_rxrd.const_ctx.init_flags = task_type <<
+ FCOE_TCE_TX_WR_RX_RD_CONST_TASK_TYPE_SHIFT;
+ task->txwr_rxrd.const_ctx.init_flags |=
+ FCOE_TASK_DEV_TYPE_DISK <<
+ FCOE_TCE_TX_WR_RX_RD_CONST_DEV_TYPE_SHIFT;
+ task->txwr_rxrd.const_ctx.init_flags |= FCOE_TASK_CLASS_TYPE_3 <<
+ FCOE_TCE_TX_WR_RX_RD_CONST_CLASS_TYPE_SHIFT;
- /* Common */
- task->cmn.data_2_trns = io_req->data_xfer_len;
- context_id = tgt->context_id;
- task->cmn.common_flags = context_id <<
- FCOE_TASK_CTX_ENTRY_TX_RX_CMN_CID_SHIFT;
- task->cmn.common_flags |= 1 <<
- FCOE_TASK_CTX_ENTRY_TX_RX_CMN_VALID_SHIFT;
- task->cmn.common_flags |= 1 <<
- FCOE_TASK_CTX_ENTRY_TX_RX_CMN_EXP_FIRST_FRAME_SHIFT;
+ /* tx flags */
+ task->txwr_rxrd.const_ctx.tx_flags = FCOE_TASK_TX_STATE_INIT <<
+ FCOE_TCE_TX_WR_RX_RD_CONST_TX_STATE_SHIFT;
/* Rx Write Tx Read */
+ task->rxwr_txrd.const_ctx.data_2_trns = io_req->data_xfer_len;
+
+ /* rx flags */
+ task->rxwr_txrd.var_ctx.rx_flags |= 1 <<
+ FCOE_TCE_RX_WR_TX_RD_VAR_EXP_FIRST_FRAME_SHIFT;
+
+ context_id = tgt->context_id;
+ task->rxwr_txrd.const_ctx.init_flags = context_id <<
+ FCOE_TCE_RX_WR_TX_RD_CONST_CID_SHIFT;
+
fc_hdr = &(mp_req->req_fc_hdr);
if (task_type == FCOE_TASK_TYPE_MIDPATH) {
fc_hdr->fh_ox_id = cpu_to_be16(io_req->xid);
fc_hdr->fh_rx_id = htons(0xffff);
- task->rx_wr_tx_rd.rx_id = 0xffff;
+ task->rxwr_txrd.var_ctx.rx_id = 0xffff;
} else if (task_type == FCOE_TASK_TYPE_UNSOLICITED) {
fc_hdr->fh_rx_id = cpu_to_be16(io_req->xid);
}
/* Fill FC Header into middle path buffer */
- hdr = (u64 *) &task->cmn.general.cmd_info.mp_fc_frame.fc_hdr;
+ hdr = (u64 *) &task->txwr_rxrd.union_ctx.tx_frame.fc_hdr;
memcpy(temp_hdr, fc_hdr, sizeof(temp_hdr));
hdr[0] = cpu_to_be64(temp_hdr[0]);
hdr[1] = cpu_to_be64(temp_hdr[1]);
@@ -1415,12 +1437,12 @@
/* Rx Only */
if (task_type == FCOE_TASK_TYPE_MIDPATH) {
+ sgl = &task->rxwr_only.union_ctx.read_info.sgl_ctx.sgl;
- task->rx_wr_only.sgl_ctx.mul_sges.cur_sge_addr.lo =
- (u32)mp_req->mp_resp_bd_dma;
- task->rx_wr_only.sgl_ctx.mul_sges.cur_sge_addr.hi =
+ sgl->mul_sgl.cur_sge_addr.lo = (u32)mp_req->mp_resp_bd_dma;
+ sgl->mul_sgl.cur_sge_addr.hi =
(u32)((u64)mp_req->mp_resp_bd_dma >> 32);
- task->rx_wr_only.sgl_ctx.mul_sges.sgl_size = 1;
+ sgl->mul_sgl.sgl_size = 1;
}
}
@@ -1431,6 +1453,8 @@
struct scsi_cmnd *sc_cmd = io_req->sc_cmd;
struct io_bdt *bd_tbl = io_req->bd_tbl;
struct bnx2fc_rport *tgt = io_req->tgt;
+ struct fcoe_cached_sge_ctx *cached_sge;
+ struct fcoe_ext_mul_sges_ctx *sgl;
u64 *fcp_cmnd;
u64 tmp_fcp_cmnd[4];
u32 context_id;
@@ -1449,47 +1473,33 @@
/* Tx only */
if (task_type == FCOE_TASK_TYPE_WRITE) {
- task->tx_wr_only.sgl_ctx.mul_sges.cur_sge_addr.lo =
+ task->txwr_only.sgl_ctx.sgl.mul_sgl.cur_sge_addr.lo =
(u32)bd_tbl->bd_tbl_dma;
- task->tx_wr_only.sgl_ctx.mul_sges.cur_sge_addr.hi =
+ task->txwr_only.sgl_ctx.sgl.mul_sgl.cur_sge_addr.hi =
(u32)((u64)bd_tbl->bd_tbl_dma >> 32);
- task->tx_wr_only.sgl_ctx.mul_sges.sgl_size =
+ task->txwr_only.sgl_ctx.sgl.mul_sgl.sgl_size =
bd_tbl->bd_valid;
}
/*Tx Write Rx Read */
/* Init state to NORMAL */
- task->tx_wr_rx_rd.tx_flags = FCOE_TASK_TX_STATE_NORMAL <<
- FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TX_STATE_SHIFT;
- task->tx_wr_rx_rd.init_flags = task_type <<
- FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TASK_TYPE_SHIFT;
- task->tx_wr_rx_rd.init_flags |= FCOE_TASK_DEV_TYPE_DISK <<
- FCOE_TASK_CTX_ENTRY_TXWR_RXRD_DEV_TYPE_SHIFT;
- task->tx_wr_rx_rd.init_flags |= FCOE_TASK_CLASS_TYPE_3 <<
- FCOE_TASK_CTX_ENTRY_TXWR_RXRD_CLASS_TYPE_SHIFT;
-
- /* Common */
- task->cmn.data_2_trns = io_req->data_xfer_len;
- context_id = tgt->context_id;
- task->cmn.common_flags = context_id <<
- FCOE_TASK_CTX_ENTRY_TX_RX_CMN_CID_SHIFT;
- task->cmn.common_flags |= 1 <<
- FCOE_TASK_CTX_ENTRY_TX_RX_CMN_VALID_SHIFT;
- task->cmn.common_flags |= 1 <<
- FCOE_TASK_CTX_ENTRY_TX_RX_CMN_EXP_FIRST_FRAME_SHIFT;
-
- /* Set initiative ownership */
- task->cmn.common_flags |= FCOE_TASK_CTX_ENTRY_TX_RX_CMN_SEQ_INIT;
+ task->txwr_rxrd.const_ctx.init_flags = task_type <<
+ FCOE_TCE_TX_WR_RX_RD_CONST_TASK_TYPE_SHIFT;
+ task->txwr_rxrd.const_ctx.init_flags |=
+ FCOE_TASK_DEV_TYPE_DISK <<
+ FCOE_TCE_TX_WR_RX_RD_CONST_DEV_TYPE_SHIFT;
+ task->txwr_rxrd.const_ctx.init_flags |= FCOE_TASK_CLASS_TYPE_3 <<
+ FCOE_TCE_TX_WR_RX_RD_CONST_CLASS_TYPE_SHIFT;
+ /* tx flags */
+ task->txwr_rxrd.const_ctx.tx_flags = FCOE_TASK_TX_STATE_NORMAL <<
+ FCOE_TCE_TX_WR_RX_RD_CONST_TX_STATE_SHIFT;
/* Set initial seq counter */
- task->cmn.tx_low_seq_cnt = 1;
-
- /* Set state to "waiting for the first packet" */
- task->cmn.common_flags |= FCOE_TASK_CTX_ENTRY_TX_RX_CMN_EXP_FIRST_FRAME;
+ task->txwr_rxrd.union_ctx.tx_seq.ctx.seq_cnt = 1;
/* Fill FCP_CMND IU */
fcp_cmnd = (u64 *)
- task->cmn.general.cmd_info.fcp_cmd_payload.opaque;
+ task->txwr_rxrd.union_ctx.fcp_cmd.opaque;
bnx2fc_build_fcp_cmnd(io_req, (struct fcp_cmnd *)&tmp_fcp_cmnd);
/* swap fcp_cmnd */
@@ -1501,32 +1511,54 @@
}
/* Rx Write Tx Read */
- task->rx_wr_tx_rd.rx_id = 0xffff;
+ task->rxwr_txrd.const_ctx.data_2_trns = io_req->data_xfer_len;
+
+ context_id = tgt->context_id;
+ task->rxwr_txrd.const_ctx.init_flags = context_id <<
+ FCOE_TCE_RX_WR_TX_RD_CONST_CID_SHIFT;
+
+ /* rx flags */
+ /* Set state to "waiting for the first packet" */
+ task->rxwr_txrd.var_ctx.rx_flags |= 1 <<
+ FCOE_TCE_RX_WR_TX_RD_VAR_EXP_FIRST_FRAME_SHIFT;
+
+ task->rxwr_txrd.var_ctx.rx_id = 0xffff;
/* Rx Only */
+ cached_sge = &task->rxwr_only.union_ctx.read_info.sgl_ctx.cached_sge;
+ sgl = &task->rxwr_only.union_ctx.read_info.sgl_ctx.sgl;
+ bd_count = bd_tbl->bd_valid;
if (task_type == FCOE_TASK_TYPE_READ) {
-
- bd_count = bd_tbl->bd_valid;
if (bd_count == 1) {
struct fcoe_bd_ctx *fcoe_bd_tbl = bd_tbl->bd_tbl;
- task->rx_wr_only.sgl_ctx.single_sge.cur_buf_addr.lo =
- fcoe_bd_tbl->buf_addr_lo;
- task->rx_wr_only.sgl_ctx.single_sge.cur_buf_addr.hi =
- fcoe_bd_tbl->buf_addr_hi;
- task->rx_wr_only.sgl_ctx.single_sge.cur_buf_rem =
- fcoe_bd_tbl->buf_len;
- task->tx_wr_rx_rd.init_flags |= 1 <<
- FCOE_TASK_CTX_ENTRY_TXWR_RXRD_SINGLE_SGE_SHIFT;
+ cached_sge->cur_buf_addr.lo = fcoe_bd_tbl->buf_addr_lo;
+ cached_sge->cur_buf_addr.hi = fcoe_bd_tbl->buf_addr_hi;
+ cached_sge->cur_buf_rem = fcoe_bd_tbl->buf_len;
+ task->txwr_rxrd.const_ctx.init_flags |= 1 <<
+ FCOE_TCE_TX_WR_RX_RD_CONST_CACHED_SGE_SHIFT;
+ } else if (bd_count == 2) {
+ struct fcoe_bd_ctx *fcoe_bd_tbl = bd_tbl->bd_tbl;
+
+ cached_sge->cur_buf_addr.lo = fcoe_bd_tbl->buf_addr_lo;
+ cached_sge->cur_buf_addr.hi = fcoe_bd_tbl->buf_addr_hi;
+ cached_sge->cur_buf_rem = fcoe_bd_tbl->buf_len;
+
+ fcoe_bd_tbl++;
+ cached_sge->second_buf_addr.lo =
+ fcoe_bd_tbl->buf_addr_lo;
+ cached_sge->second_buf_addr.hi =
+ fcoe_bd_tbl->buf_addr_hi;
+ cached_sge->second_buf_rem = fcoe_bd_tbl->buf_len;
+ task->txwr_rxrd.const_ctx.init_flags |= 1 <<
+ FCOE_TCE_TX_WR_RX_RD_CONST_CACHED_SGE_SHIFT;
} else {
- task->rx_wr_only.sgl_ctx.mul_sges.cur_sge_addr.lo =
- (u32)bd_tbl->bd_tbl_dma;
- task->rx_wr_only.sgl_ctx.mul_sges.cur_sge_addr.hi =
+ sgl->mul_sgl.cur_sge_addr.lo = (u32)bd_tbl->bd_tbl_dma;
+ sgl->mul_sgl.cur_sge_addr.hi =
(u32)((u64)bd_tbl->bd_tbl_dma >> 32);
- task->rx_wr_only.sgl_ctx.mul_sges.sgl_size =
- bd_tbl->bd_valid;
+ sgl->mul_sgl.sgl_size = bd_count;
}
}
}
diff --git a/drivers/scsi/bnx2fc/bnx2fc_io.c b/drivers/scsi/bnx2fc/bnx2fc_io.c
index b5b5c34..5dc4205 100644
--- a/drivers/scsi/bnx2fc/bnx2fc_io.c
+++ b/drivers/scsi/bnx2fc/bnx2fc_io.c
@@ -425,6 +425,7 @@
struct list_head *listp;
struct io_bdt *bd_tbl;
int index = RESERVE_FREE_LIST_INDEX;
+ u32 free_sqes;
u32 max_sqes;
u16 xid;
@@ -445,8 +446,10 @@
* cmgr lock
*/
spin_lock_bh(&cmd_mgr->free_list_lock[index]);
+ free_sqes = atomic_read(&tgt->free_sqes);
if ((list_empty(&(cmd_mgr->free_list[index]))) ||
- (tgt->num_active_ios.counter >= max_sqes)) {
+ (tgt->num_active_ios.counter >= max_sqes) ||
+ (free_sqes + max_sqes <= BNX2FC_SQ_WQES_MAX)) {
BNX2FC_TGT_DBG(tgt, "No free els_tm cmds available "
"ios(%d):sqes(%d)\n",
tgt->num_active_ios.counter, tgt->max_sqes);
@@ -463,6 +466,7 @@
xid = io_req->xid;
cmd_mgr->cmds[xid] = io_req;
atomic_inc(&tgt->num_active_ios);
+ atomic_dec(&tgt->free_sqes);
spin_unlock_bh(&cmd_mgr->free_list_lock[index]);
INIT_LIST_HEAD(&io_req->link);
@@ -489,6 +493,7 @@
struct bnx2fc_cmd *io_req;
struct list_head *listp;
struct io_bdt *bd_tbl;
+ u32 free_sqes;
u32 max_sqes;
u16 xid;
int index = get_cpu();
@@ -499,8 +504,10 @@
* cmgr lock
*/
spin_lock_bh(&cmd_mgr->free_list_lock[index]);
+ free_sqes = atomic_read(&tgt->free_sqes);
if ((list_empty(&cmd_mgr->free_list[index])) ||
- (tgt->num_active_ios.counter >= max_sqes)) {
+ (tgt->num_active_ios.counter >= max_sqes) ||
+ (free_sqes + max_sqes <= BNX2FC_SQ_WQES_MAX)) {
spin_unlock_bh(&cmd_mgr->free_list_lock[index]);
put_cpu();
return NULL;
@@ -513,6 +520,7 @@
xid = io_req->xid;
cmd_mgr->cmds[xid] = io_req;
atomic_inc(&tgt->num_active_ios);
+ atomic_dec(&tgt->free_sqes);
spin_unlock_bh(&cmd_mgr->free_list_lock[index]);
put_cpu();
@@ -873,7 +881,7 @@
/* Obtain oxid and rxid for the original exchange to be aborted */
fc_hdr->fh_ox_id = htons(io_req->xid);
- fc_hdr->fh_rx_id = htons(io_req->task->rx_wr_tx_rd.rx_id);
+ fc_hdr->fh_rx_id = htons(io_req->task->rxwr_txrd.var_ctx.rx_id);
sid = tgt->sid;
did = rport->port_id;
@@ -1189,7 +1197,7 @@
kref_put(&io_req->refcount,
bnx2fc_cmd_release); /* drop timer hold */
- r_ctl = task->cmn.general.rsp_info.abts_rsp.r_ctl;
+ r_ctl = (u8)task->rxwr_only.union_ctx.comp_info.abts_rsp.r_ctl;
switch (r_ctl) {
case FC_RCTL_BA_ACC:
@@ -1344,12 +1352,13 @@
fc_hdr = &(tm_req->resp_fc_hdr);
hdr = (u64 *)fc_hdr;
temp_hdr = (u64 *)
- &task->cmn.general.cmd_info.mp_fc_frame.fc_hdr;
+ &task->rxwr_only.union_ctx.comp_info.mp_rsp.fc_hdr;
hdr[0] = cpu_to_be64(temp_hdr[0]);
hdr[1] = cpu_to_be64(temp_hdr[1]);
hdr[2] = cpu_to_be64(temp_hdr[2]);
- tm_req->resp_len = task->rx_wr_only.sgl_ctx.mul_sges.cur_sge_off;
+ tm_req->resp_len =
+ task->rxwr_only.union_ctx.comp_info.mp_rsp.mp_payload_len;
rsp_buf = tm_req->resp_buf;
@@ -1724,7 +1733,7 @@
/* Fetch fcp_rsp from task context and perform cmd completion */
fcp_rsp = (struct fcoe_fcp_rsp_payload *)
- &(task->cmn.general.rsp_info.fcp_rsp.payload);
+ &(task->rxwr_only.union_ctx.comp_info.fcp_rsp.payload);
/* parse fcp_rsp and obtain sense data from RQ if available */
bnx2fc_parse_fcp_rsp(io_req, fcp_rsp, num_rq);
diff --git a/drivers/scsi/bnx2fc/bnx2fc_tgt.c b/drivers/scsi/bnx2fc/bnx2fc_tgt.c
index a2e3830..3e892bd 100644
--- a/drivers/scsi/bnx2fc/bnx2fc_tgt.c
+++ b/drivers/scsi/bnx2fc/bnx2fc_tgt.c
@@ -133,6 +133,8 @@
/* upload will take care of cleaning up sess resc */
lport->tt.rport_logoff(rdata);
}
+ /* Arm CQ */
+ bnx2fc_arm_cq(tgt);
return;
ofld_err:
@@ -315,6 +317,8 @@
struct fc_rport *rport = rdata->rport;
struct bnx2fc_hba *hba = port->priv;
+ struct b577xx_doorbell_set_prod *sq_db = &tgt->sq_db;
+ struct b577xx_fcoe_rx_doorbell *rx_db = &tgt->rx_db;
tgt->rport = rport;
tgt->rdata = rdata;
@@ -335,6 +339,7 @@
tgt->max_sqes = BNX2FC_SQ_WQES_MAX;
tgt->max_rqes = BNX2FC_RQ_WQES_MAX;
tgt->max_cqes = BNX2FC_CQ_WQES_MAX;
+ atomic_set(&tgt->free_sqes, BNX2FC_SQ_WQES_MAX);
/* Initialize the toggle bit */
tgt->sq_curr_toggle_bit = 1;
@@ -345,7 +350,17 @@
tgt->rq_cons_idx = 0;
atomic_set(&tgt->num_active_ios, 0);
- tgt->work_time_slice = 2;
+ /* initialize sq doorbell */
+ sq_db->header.header = B577XX_DOORBELL_HDR_DB_TYPE;
+ sq_db->header.header |= B577XX_FCOE_CONNECTION_TYPE <<
+ B577XX_DOORBELL_HDR_CONN_TYPE_SHIFT;
+ /* initialize rx doorbell */
+ rx_db->hdr.header = ((0x1 << B577XX_DOORBELL_HDR_RX_SHIFT) |
+ (0x1 << B577XX_DOORBELL_HDR_DB_TYPE_SHIFT) |
+ (B577XX_FCOE_CONNECTION_TYPE <<
+ B577XX_DOORBELL_HDR_CONN_TYPE_SHIFT));
+ rx_db->params = (0x2 << B577XX_FCOE_RX_DOORBELL_NEGATIVE_ARM_SHIFT) |
+ (0x3 << B577XX_FCOE_RX_DOORBELL_OPCODE_SHIFT);
spin_lock_init(&tgt->tgt_lock);
spin_lock_init(&tgt->cq_lock);
@@ -758,8 +773,6 @@
}
memset(tgt->lcq, 0, tgt->lcq_mem_size);
- /* Arm CQ */
- tgt->conn_db->cq_arm.lo = -1;
tgt->conn_db->rq_prod = 0x8000;
return 0;
@@ -787,6 +800,8 @@
iounmap(tgt->ctx_base);
tgt->ctx_base = NULL;
}
+
+ spin_lock_bh(&tgt->cq_lock);
/* Free LCQ */
if (tgt->lcq) {
dma_free_coherent(&hba->pcidev->dev, tgt->lcq_mem_size,
@@ -828,17 +843,16 @@
tgt->rq = NULL;
}
/* Free CQ */
- spin_lock_bh(&tgt->cq_lock);
if (tgt->cq) {
dma_free_coherent(&hba->pcidev->dev, tgt->cq_mem_size,
tgt->cq, tgt->cq_dma);
tgt->cq = NULL;
}
- spin_unlock_bh(&tgt->cq_lock);
/* Free SQ */
if (tgt->sq) {
dma_free_coherent(&hba->pcidev->dev, tgt->sq_mem_size,
tgt->sq, tgt->sq_dma);
tgt->sq = NULL;
}
+ spin_unlock_bh(&tgt->cq_lock);
}
diff --git a/drivers/scsi/bnx2i/57xx_iscsi_constants.h b/drivers/scsi/bnx2i/57xx_iscsi_constants.h
index 30e6bdb..15673cc 100644
--- a/drivers/scsi/bnx2i/57xx_iscsi_constants.h
+++ b/drivers/scsi/bnx2i/57xx_iscsi_constants.h
@@ -125,7 +125,7 @@
/* SQ/RQ/CQ DB structure sizes */
#define ISCSI_SQ_DB_SIZE (16)
-#define ISCSI_RQ_DB_SIZE (16)
+#define ISCSI_RQ_DB_SIZE (64)
#define ISCSI_CQ_DB_SIZE (80)
#define ISCSI_SQN_TO_NOTIFY_NOT_VALID 0xFFFF
diff --git a/drivers/scsi/bnx2i/57xx_iscsi_hsi.h b/drivers/scsi/bnx2i/57xx_iscsi_hsi.h
index dad6c8a..71890a0 100644
--- a/drivers/scsi/bnx2i/57xx_iscsi_hsi.h
+++ b/drivers/scsi/bnx2i/57xx_iscsi_hsi.h
@@ -707,8 +707,10 @@
#define ISCSI_KWQE_CONN_UPDATE_INITIAL_R2T_SHIFT 2
#define ISCSI_KWQE_CONN_UPDATE_IMMEDIATE_DATA (0x1<<3)
#define ISCSI_KWQE_CONN_UPDATE_IMMEDIATE_DATA_SHIFT 3
-#define ISCSI_KWQE_CONN_UPDATE_RESERVED1 (0xF<<4)
-#define ISCSI_KWQE_CONN_UPDATE_RESERVED1_SHIFT 4
+#define ISCSI_KWQE_CONN_UPDATE_OOO_SUPPORT_MODE (0x3<<4)
+#define ISCSI_KWQE_CONN_UPDATE_OOO_SUPPORT_MODE_SHIFT 4
+#define ISCSI_KWQE_CONN_UPDATE_RESERVED1 (0x3<<6)
+#define ISCSI_KWQE_CONN_UPDATE_RESERVED1_SHIFT 6
#elif defined(__LITTLE_ENDIAN)
u8 conn_flags;
#define ISCSI_KWQE_CONN_UPDATE_HEADER_DIGEST (0x1<<0)
@@ -719,8 +721,10 @@
#define ISCSI_KWQE_CONN_UPDATE_INITIAL_R2T_SHIFT 2
#define ISCSI_KWQE_CONN_UPDATE_IMMEDIATE_DATA (0x1<<3)
#define ISCSI_KWQE_CONN_UPDATE_IMMEDIATE_DATA_SHIFT 3
-#define ISCSI_KWQE_CONN_UPDATE_RESERVED1 (0xF<<4)
-#define ISCSI_KWQE_CONN_UPDATE_RESERVED1_SHIFT 4
+#define ISCSI_KWQE_CONN_UPDATE_OOO_SUPPORT_MODE (0x3<<4)
+#define ISCSI_KWQE_CONN_UPDATE_OOO_SUPPORT_MODE_SHIFT 4
+#define ISCSI_KWQE_CONN_UPDATE_RESERVED1 (0x3<<6)
+#define ISCSI_KWQE_CONN_UPDATE_RESERVED1_SHIFT 6
u8 reserved2;
u8 max_outstanding_r2ts;
u8 session_error_recovery_level;
diff --git a/drivers/scsi/bnx2i/bnx2i.h b/drivers/scsi/bnx2i/bnx2i.h
index 6bdd25a..e7cb7ec 100644
--- a/drivers/scsi/bnx2i/bnx2i.h
+++ b/drivers/scsi/bnx2i/bnx2i.h
@@ -478,7 +478,7 @@
struct bnx2i_5771x_sq_rq_db {
u16 prod_idx;
- u8 reserved0[14]; /* Pad structure size to 16 bytes */
+ u8 reserved0[62]; /* Pad structure size to 64 bytes */
};
diff --git a/drivers/scsi/bnx2i/bnx2i_init.c b/drivers/scsi/bnx2i/bnx2i_init.c
index 6adbdc3..6973413 100644
--- a/drivers/scsi/bnx2i/bnx2i_init.c
+++ b/drivers/scsi/bnx2i/bnx2i_init.c
@@ -30,7 +30,7 @@
"Eddie Wai <eddie.wai@broadcom.com>");
MODULE_DESCRIPTION("Broadcom NetXtreme II BCM5706/5708/5709/57710/57711/57712"
- " iSCSI Driver");
+ "/57800/57810/57840 iSCSI Driver");
MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_MODULE_VERSION);
@@ -88,11 +88,20 @@
(hba->pci_did == PCI_DEVICE_ID_NX2_5709S)) {
set_bit(BNX2I_NX2_DEV_5709, &hba->cnic_dev_type);
hba->mail_queue_access = BNX2I_MQ_BIN_MODE;
- } else if (hba->pci_did == PCI_DEVICE_ID_NX2_57710 ||
- hba->pci_did == PCI_DEVICE_ID_NX2_57711 ||
- hba->pci_did == PCI_DEVICE_ID_NX2_57711E ||
- hba->pci_did == PCI_DEVICE_ID_NX2_57712 ||
- hba->pci_did == PCI_DEVICE_ID_NX2_57712E)
+ } else if (hba->pci_did == PCI_DEVICE_ID_NX2_57710 ||
+ hba->pci_did == PCI_DEVICE_ID_NX2_57711 ||
+ hba->pci_did == PCI_DEVICE_ID_NX2_57711E ||
+ hba->pci_did == PCI_DEVICE_ID_NX2_57712 ||
+ hba->pci_did == PCI_DEVICE_ID_NX2_57712E ||
+ hba->pci_did == PCI_DEVICE_ID_NX2_57800 ||
+ hba->pci_did == PCI_DEVICE_ID_NX2_57800_MF ||
+ hba->pci_did == PCI_DEVICE_ID_NX2_57800_VF ||
+ hba->pci_did == PCI_DEVICE_ID_NX2_57810 ||
+ hba->pci_did == PCI_DEVICE_ID_NX2_57810_MF ||
+ hba->pci_did == PCI_DEVICE_ID_NX2_57810_VF ||
+ hba->pci_did == PCI_DEVICE_ID_NX2_57840 ||
+ hba->pci_did == PCI_DEVICE_ID_NX2_57840_MF ||
+ hba->pci_did == PCI_DEVICE_ID_NX2_57840_VF)
set_bit(BNX2I_NX2_DEV_57710, &hba->cnic_dev_type);
else
printk(KERN_ALERT "bnx2i: unknown device, 0x%x\n",
diff --git a/drivers/ssb/driver_chipcommon_pmu.c b/drivers/ssb/driver_chipcommon_pmu.c
index 305ade7..a7aef47 100644
--- a/drivers/ssb/driver_chipcommon_pmu.c
+++ b/drivers/ssb/driver_chipcommon_pmu.c
@@ -417,9 +417,9 @@
u32 min_msk = 0, max_msk = 0;
unsigned int i;
const struct pmu_res_updown_tab_entry *updown_tab = NULL;
- unsigned int updown_tab_size;
+ unsigned int updown_tab_size = 0;
const struct pmu_res_depend_tab_entry *depend_tab = NULL;
- unsigned int depend_tab_size;
+ unsigned int depend_tab_size = 0;
switch (bus->chip_id) {
case 0x4312:
diff --git a/drivers/ssb/driver_gige.c b/drivers/ssb/driver_gige.c
index 5ba92a2..d758909 100644
--- a/drivers/ssb/driver_gige.c
+++ b/drivers/ssb/driver_gige.c
@@ -106,8 +106,9 @@
gige_write32(dev, SSB_GIGE_PCICFG + offset, value);
}
-static int ssb_gige_pci_read_config(struct pci_bus *bus, unsigned int devfn,
- int reg, int size, u32 *val)
+static int __devinit ssb_gige_pci_read_config(struct pci_bus *bus,
+ unsigned int devfn, int reg,
+ int size, u32 *val)
{
struct ssb_gige *dev = container_of(bus->ops, struct ssb_gige, pci_ops);
unsigned long flags;
@@ -136,8 +137,9 @@
return PCIBIOS_SUCCESSFUL;
}
-static int ssb_gige_pci_write_config(struct pci_bus *bus, unsigned int devfn,
- int reg, int size, u32 val)
+static int __devinit ssb_gige_pci_write_config(struct pci_bus *bus,
+ unsigned int devfn, int reg,
+ int size, u32 val)
{
struct ssb_gige *dev = container_of(bus->ops, struct ssb_gige, pci_ops);
unsigned long flags;
@@ -166,7 +168,8 @@
return PCIBIOS_SUCCESSFUL;
}
-static int ssb_gige_probe(struct ssb_device *sdev, const struct ssb_device_id *id)
+static int __devinit ssb_gige_probe(struct ssb_device *sdev,
+ const struct ssb_device_id *id)
{
struct ssb_gige *dev;
u32 base, tmslow, tmshigh;
diff --git a/drivers/ssb/driver_pcicore.c b/drivers/ssb/driver_pcicore.c
index 2a20dab..21b9465 100644
--- a/drivers/ssb/driver_pcicore.c
+++ b/drivers/ssb/driver_pcicore.c
@@ -314,7 +314,7 @@
return ssb_mips_irq(extpci_core->dev) + 2;
}
-static void ssb_pcicore_init_hostmode(struct ssb_pcicore *pc)
+static void __devinit ssb_pcicore_init_hostmode(struct ssb_pcicore *pc)
{
u32 val;
@@ -379,7 +379,7 @@
register_pci_controller(&ssb_pcicore_controller);
}
-static int pcicore_is_in_hostmode(struct ssb_pcicore *pc)
+static int __devinit pcicore_is_in_hostmode(struct ssb_pcicore *pc)
{
struct ssb_bus *bus = pc->dev->bus;
u16 chipid_top;
@@ -412,7 +412,7 @@
* Workarounds.
**************************************************/
-static void ssb_pcicore_fix_sprom_core_index(struct ssb_pcicore *pc)
+static void __devinit ssb_pcicore_fix_sprom_core_index(struct ssb_pcicore *pc)
{
u16 tmp = pcicore_read16(pc, SSB_PCICORE_SPROM(0));
if (((tmp & 0xF000) >> 12) != pc->dev->core_index) {
@@ -514,13 +514,13 @@
* Generic and Clientmode operation code.
**************************************************/
-static void ssb_pcicore_init_clientmode(struct ssb_pcicore *pc)
+static void __devinit ssb_pcicore_init_clientmode(struct ssb_pcicore *pc)
{
/* Disable PCI interrupts. */
ssb_write32(pc->dev, SSB_INTVEC, 0);
}
-void ssb_pcicore_init(struct ssb_pcicore *pc)
+void __devinit ssb_pcicore_init(struct ssb_pcicore *pc)
{
struct ssb_device *dev = pc->dev;
diff --git a/drivers/ssb/main.c b/drivers/ssb/main.c
index f8a13f8..57b7b64 100644
--- a/drivers/ssb/main.c
+++ b/drivers/ssb/main.c
@@ -557,7 +557,7 @@
}
/* Needs ssb_buses_lock() */
-static int ssb_attach_queued_buses(void)
+static int __devinit ssb_attach_queued_buses(void)
{
struct ssb_bus *bus, *n;
int err = 0;
@@ -768,9 +768,9 @@
return err;
}
-static int ssb_bus_register(struct ssb_bus *bus,
- ssb_invariants_func_t get_invariants,
- unsigned long baseaddr)
+static int __devinit ssb_bus_register(struct ssb_bus *bus,
+ ssb_invariants_func_t get_invariants,
+ unsigned long baseaddr)
{
int err;
@@ -851,8 +851,8 @@
}
#ifdef CONFIG_SSB_PCIHOST
-int ssb_bus_pcibus_register(struct ssb_bus *bus,
- struct pci_dev *host_pci)
+int __devinit ssb_bus_pcibus_register(struct ssb_bus *bus,
+ struct pci_dev *host_pci)
{
int err;
@@ -875,9 +875,9 @@
#endif /* CONFIG_SSB_PCIHOST */
#ifdef CONFIG_SSB_PCMCIAHOST
-int ssb_bus_pcmciabus_register(struct ssb_bus *bus,
- struct pcmcia_device *pcmcia_dev,
- unsigned long baseaddr)
+int __devinit ssb_bus_pcmciabus_register(struct ssb_bus *bus,
+ struct pcmcia_device *pcmcia_dev,
+ unsigned long baseaddr)
{
int err;
@@ -897,8 +897,9 @@
#endif /* CONFIG_SSB_PCMCIAHOST */
#ifdef CONFIG_SSB_SDIOHOST
-int ssb_bus_sdiobus_register(struct ssb_bus *bus, struct sdio_func *func,
- unsigned int quirks)
+int __devinit ssb_bus_sdiobus_register(struct ssb_bus *bus,
+ struct sdio_func *func,
+ unsigned int quirks)
{
int err;
@@ -918,9 +919,9 @@
EXPORT_SYMBOL(ssb_bus_sdiobus_register);
#endif /* CONFIG_SSB_PCMCIAHOST */
-int ssb_bus_ssbbus_register(struct ssb_bus *bus,
- unsigned long baseaddr,
- ssb_invariants_func_t get_invariants)
+int __devinit ssb_bus_ssbbus_register(struct ssb_bus *bus,
+ unsigned long baseaddr,
+ ssb_invariants_func_t get_invariants)
{
int err;
@@ -1001,8 +1002,8 @@
switch (plltype) {
case SSB_PLLTYPE_6: /* 100/200 or 120/240 only */
if (m & SSB_CHIPCO_CLK_T6_MMASK)
- return SSB_CHIPCO_CLK_T6_M0;
- return SSB_CHIPCO_CLK_T6_M1;
+ return SSB_CHIPCO_CLK_T6_M1;
+ return SSB_CHIPCO_CLK_T6_M0;
case SSB_PLLTYPE_1: /* 48Mhz base, 3 dividers */
case SSB_PLLTYPE_3: /* 25Mhz, 2 dividers */
case SSB_PLLTYPE_4: /* 48Mhz, 4 dividers */
diff --git a/drivers/ssb/pcihost_wrapper.c b/drivers/ssb/pcihost_wrapper.c
index f6c8c81..d7a9813 100644
--- a/drivers/ssb/pcihost_wrapper.c
+++ b/drivers/ssb/pcihost_wrapper.c
@@ -53,8 +53,8 @@
# define ssb_pcihost_resume NULL
#endif /* CONFIG_PM */
-static int ssb_pcihost_probe(struct pci_dev *dev,
- const struct pci_device_id *id)
+static int __devinit ssb_pcihost_probe(struct pci_dev *dev,
+ const struct pci_device_id *id)
{
struct ssb_bus *ssb;
int err = -ENOMEM;
@@ -110,7 +110,7 @@
pci_set_drvdata(dev, NULL);
}
-int ssb_pcihost_register(struct pci_driver *driver)
+int __devinit ssb_pcihost_register(struct pci_driver *driver)
{
driver->probe = ssb_pcihost_probe;
driver->remove = ssb_pcihost_remove;
diff --git a/drivers/ssb/scan.c b/drivers/ssb/scan.c
index 45e5bab..8047f9a 100644
--- a/drivers/ssb/scan.c
+++ b/drivers/ssb/scan.c
@@ -310,8 +310,7 @@
} else {
if (bus->bustype == SSB_BUSTYPE_PCI) {
bus->chip_id = pcidev_to_chipid(bus->host_pci);
- pci_read_config_byte(bus->host_pci, PCI_REVISION_ID,
- &bus->chip_rev);
+ bus->chip_rev = bus->host_pci->revision;
bus->chip_package = 0;
} else {
bus->chip_id = 0x4710;
diff --git a/drivers/staging/brcm80211/brcmfmac/dhd_linux.c b/drivers/staging/brcm80211/brcmfmac/dhd_linux.c
index f356c56..09957bd 100644
--- a/drivers/staging/brcm80211/brcmfmac/dhd_linux.c
+++ b/drivers/staging/brcm80211/brcmfmac/dhd_linux.c
@@ -31,6 +31,8 @@
#include <linux/fcntl.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
+#include <linux/interrupt.h>
+#include <linux/hardirq.h>
#include <bcmdefs.h>
#include <bcmutils.h>
diff --git a/drivers/staging/brcm80211/brcmfmac/wl_iw.c b/drivers/staging/brcm80211/brcmfmac/wl_iw.c
index 15e1b05..35eec91 100644
--- a/drivers/staging/brcm80211/brcmfmac/wl_iw.c
+++ b/drivers/staging/brcm80211/brcmfmac/wl_iw.c
@@ -18,6 +18,7 @@
#include <linux/semaphore.h>
#include <bcmdefs.h>
#include <linux/netdevice.h>
+#include <linux/hardirq.h>
#include <wlioctl.h>
#include <bcmutils.h>
diff --git a/drivers/staging/brcm80211/brcmsmac/wl_mac80211.c b/drivers/staging/brcm80211/brcmsmac/wl_mac80211.c
index 6c6236c..8261229 100644
--- a/drivers/staging/brcm80211/brcmsmac/wl_mac80211.c
+++ b/drivers/staging/brcm80211/brcmsmac/wl_mac80211.c
@@ -24,6 +24,7 @@
#include <linux/pci.h>
#include <linux/sched.h>
#include <linux/firmware.h>
+#include <linux/interrupt.h>
#include <net/mac80211.h>
#include <proto/802.11.h>
diff --git a/drivers/staging/brcm80211/brcmsmac/wl_mac80211.h b/drivers/staging/brcm80211/brcmsmac/wl_mac80211.h
index e703d8b..f7a58b7 100644
--- a/drivers/staging/brcm80211/brcmsmac/wl_mac80211.h
+++ b/drivers/staging/brcm80211/brcmsmac/wl_mac80211.h
@@ -17,6 +17,8 @@
#ifndef _wl_mac80211_h_
#define _wl_mac80211_h_
+#include <linux/interrupt.h>
+
/* BMAC Note: High-only driver is no longer working in softirq context as it needs to block and
* sleep so perimeter lock has to be a semaphore instead of spinlock. This requires timers to be
* submitted to workqueue instead of being on kernel timer
diff --git a/drivers/staging/pohmelfs/crypto.c b/drivers/staging/pohmelfs/crypto.c
index 5cca24f..ad92771 100644
--- a/drivers/staging/pohmelfs/crypto.c
+++ b/drivers/staging/pohmelfs/crypto.c
@@ -17,6 +17,7 @@
#include <linux/highmem.h>
#include <linux/kthread.h>
#include <linux/pagemap.h>
+#include <linux/scatterlist.h>
#include <linux/slab.h>
#include "netfs.h"
diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211.h b/drivers/staging/rtl8187se/ieee80211/ieee80211.h
index 16aa6a8..4384d93 100644
--- a/drivers/staging/rtl8187se/ieee80211/ieee80211.h
+++ b/drivers/staging/rtl8187se/ieee80211/ieee80211.h
@@ -32,6 +32,7 @@
#include <linux/semaphore.h>
#include <linux/wireless.h>
#include <linux/ieee80211.h>
+#include <linux/interrupt.h>
#define KEY_TYPE_NA 0x0
#define KEY_TYPE_WEP40 0x1
diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c
index 736a140..00ee02f 100644
--- a/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c
+++ b/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c
@@ -20,6 +20,7 @@
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/version.h>
+#include <linux/interrupt.h>
#include <asm/uaccess.h>
#include "dot11d.h"
diff --git a/drivers/staging/rtl8187se/r8180.h b/drivers/staging/rtl8187se/r8180.h
index d15bdf6..a2c46ae 100644
--- a/drivers/staging/rtl8187se/r8180.h
+++ b/drivers/staging/rtl8187se/r8180.h
@@ -18,6 +18,7 @@
#ifndef R8180H
#define R8180H
+#include <linux/interrupt.h>
#define RTL8180_MODULE_NAME "r8180"
#define DMESG(x,a...) printk(KERN_INFO RTL8180_MODULE_NAME ": " x "\n", ## a)
diff --git a/drivers/staging/rtl8187se/r8180_core.c b/drivers/staging/rtl8187se/r8180_core.c
index 2155a77..bae7d85 100644
--- a/drivers/staging/rtl8187se/r8180_core.c
+++ b/drivers/staging/rtl8187se/r8180_core.c
@@ -33,6 +33,7 @@
#include <linux/slab.h>
#include <linux/syscalls.h>
#include <linux/eeprom_93cx6.h>
+#include <linux/interrupt.h>
#include "r8180_hw.h"
#include "r8180.h"
diff --git a/drivers/staging/rtl8192e/ieee80211/ieee80211.h b/drivers/staging/rtl8192e/ieee80211/ieee80211.h
index dbe21ab..82bc59a 100644
--- a/drivers/staging/rtl8192e/ieee80211/ieee80211.h
+++ b/drivers/staging/rtl8192e/ieee80211/ieee80211.h
@@ -31,6 +31,7 @@
#include <linux/timer.h>
#include <linux/sched.h>
#include <linux/semaphore.h>
+#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/wireless.h>
diff --git a/drivers/staging/rtl8192e/r8192E.h b/drivers/staging/rtl8192e/r8192E.h
index 0229031..89fe8fc 100644
--- a/drivers/staging/rtl8192e/r8192E.h
+++ b/drivers/staging/rtl8192e/r8192E.h
@@ -36,6 +36,7 @@
#include <linux/if_arp.h>
#include <linux/random.h>
#include <linux/version.h>
+#include <linux/interrupt.h>
#include <asm/io.h>
#include "ieee80211/rtl819x_HT.h"
#include "ieee80211/ieee80211.h"
diff --git a/drivers/staging/rtl8192e/r8192E_core.c b/drivers/staging/rtl8192e/r8192E_core.c
index 58d800f..19a9a07 100644
--- a/drivers/staging/rtl8192e/r8192E_core.c
+++ b/drivers/staging/rtl8192e/r8192E_core.c
@@ -27,6 +27,8 @@
#include <linux/vmalloc.h>
#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/hardirq.h>
#include <asm/uaccess.h>
#include "r8192E_hw.h"
#include "r8192E.h"
diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211.h b/drivers/staging/rtl8192u/ieee80211/ieee80211.h
index e716f7b..2333257 100644
--- a/drivers/staging/rtl8192u/ieee80211/ieee80211.h
+++ b/drivers/staging/rtl8192u/ieee80211/ieee80211.h
@@ -31,6 +31,7 @@
#include <linux/timer.h>
#include <linux/sched.h>
#include <linux/semaphore.h>
+#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/wireless.h>
diff --git a/drivers/tty/serial/ifx6x60.c b/drivers/tty/serial/ifx6x60.c
index 5315525..426434e 100644
--- a/drivers/tty/serial/ifx6x60.c
+++ b/drivers/tty/serial/ifx6x60.c
@@ -36,6 +36,7 @@
* you need to use this driver for another platform.
*
*****************************************************************************/
+#include <linux/dma-mapping.h>
#include <linux/module.h>
#include <linux/termios.h>
#include <linux/tty.h>
diff --git a/drivers/usb/gadget/f_phonet.c b/drivers/usb/gadget/f_phonet.c
index 5e14950..f22fc68 100644
--- a/drivers/usb/gadget/f_phonet.c
+++ b/drivers/usb/gadget/f_phonet.c
@@ -20,6 +20,7 @@
* 02110-1301 USA
*/
+#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/kernel.h>
#include <linux/device.h>
diff --git a/include/crypto/if_alg.h b/include/crypto/if_alg.h
index c5813c8..d61c111 100644
--- a/include/crypto/if_alg.h
+++ b/include/crypto/if_alg.h
@@ -16,6 +16,7 @@
#include <linux/compiler.h>
#include <linux/completion.h>
#include <linux/if_alg.h>
+#include <linux/scatterlist.h>
#include <linux/types.h>
#include <net/sock.h>
diff --git a/include/linux/arcdevice.h b/include/linux/arcdevice.h
index 7d650a0..7216b0d 100644
--- a/include/linux/arcdevice.h
+++ b/include/linux/arcdevice.h
@@ -20,6 +20,7 @@
#include <linux/if_arcnet.h>
#ifdef __KERNEL__
+#include <linux/irqreturn.h>
#ifndef bool
#define bool int
diff --git a/include/linux/ath9k_platform.h b/include/linux/ath9k_platform.h
index 60a7c49..6e3f54f 100644
--- a/include/linux/ath9k_platform.h
+++ b/include/linux/ath9k_platform.h
@@ -30,6 +30,8 @@
u32 gpio_val;
bool is_clk_25mhz;
+ int (*get_mac_revision)(void);
+ int (*external_reset)(void);
};
#endif /* _LINUX_ATH9K_PLATFORM_H */
diff --git a/include/linux/bcma/bcma.h b/include/linux/bcma/bcma.h
index 08763e4..3895aeb 100644
--- a/include/linux/bcma/bcma.h
+++ b/include/linux/bcma/bcma.h
@@ -6,6 +6,7 @@
#include <linux/bcma/bcma_driver_chipcommon.h>
#include <linux/bcma/bcma_driver_pci.h>
+#include <linux/ssb/ssb.h> /* SPROM sharing */
#include "bcma_regs.h"
@@ -31,6 +32,12 @@
void (*write8)(struct bcma_device *core, u16 offset, u8 value);
void (*write16)(struct bcma_device *core, u16 offset, u16 value);
void (*write32)(struct bcma_device *core, u16 offset, u32 value);
+#ifdef CONFIG_BCMA_BLOCKIO
+ void (*block_read)(struct bcma_device *core, void *buffer,
+ size_t count, u16 offset, u8 reg_width);
+ void (*block_write)(struct bcma_device *core, const void *buffer,
+ size_t count, u16 offset, u8 reg_width);
+#endif
/* Agent ops */
u32 (*aread32)(struct bcma_device *core, u16 offset);
void (*awrite32)(struct bcma_device *core, u16 offset, u32 value);
@@ -117,6 +124,8 @@
struct bcma_device_id id;
struct device dev;
+ struct device *dma_dev;
+ unsigned int irq;
bool dev_registered;
u8 core_index;
@@ -179,6 +188,10 @@
struct bcma_drv_cc drv_cc;
struct bcma_drv_pci drv_pci;
+
+ /* We decided to share SPROM struct with SSB as long as we do not need
+ * any hacks for BCMA. This simplifies drivers code. */
+ struct ssb_sprom sprom;
};
extern inline u32 bcma_read8(struct bcma_device *core, u16 offset)
@@ -208,6 +221,18 @@
{
core->bus->ops->write32(core, offset, value);
}
+#ifdef CONFIG_BCMA_BLOCKIO
+extern inline void bcma_block_read(struct bcma_device *core, void *buffer,
+ size_t count, u16 offset, u8 reg_width)
+{
+ core->bus->ops->block_read(core, buffer, count, offset, reg_width);
+}
+extern inline void bcma_block_write(struct bcma_device *core, const void *buffer,
+ size_t count, u16 offset, u8 reg_width)
+{
+ core->bus->ops->block_write(core, buffer, count, offset, reg_width);
+}
+#endif
extern inline u32 bcma_aread32(struct bcma_device *core, u16 offset)
{
return core->bus->ops->aread32(core, offset);
@@ -219,6 +244,7 @@
}
extern bool bcma_core_is_enabled(struct bcma_device *core);
+extern void bcma_core_disable(struct bcma_device *core, u32 flags);
extern int bcma_core_enable(struct bcma_device *core, u32 flags);
#endif /* LINUX_BCMA_H_ */
diff --git a/include/linux/bcma/bcma_driver_chipcommon.h b/include/linux/bcma/bcma_driver_chipcommon.h
index 083c3b6..9c5b69f 100644
--- a/include/linux/bcma/bcma_driver_chipcommon.h
+++ b/include/linux/bcma/bcma_driver_chipcommon.h
@@ -244,6 +244,7 @@
#define BCMA_CC_REGCTL_DATA 0x065C
#define BCMA_CC_PLLCTL_ADDR 0x0660
#define BCMA_CC_PLLCTL_DATA 0x0664
+#define BCMA_CC_SPROM 0x0830 /* SPROM beginning */
/* Data for the PMU, if available.
* Check availability with ((struct bcma_chipcommon)->capabilities & BCMA_CC_CAP_PMU)
diff --git a/include/linux/bcma/bcma_driver_pci.h b/include/linux/bcma/bcma_driver_pci.h
index b7e191c..3871b66 100644
--- a/include/linux/bcma/bcma_driver_pci.h
+++ b/include/linux/bcma/bcma_driver_pci.h
@@ -85,5 +85,7 @@
#define pcicore_write32(pc, offset, val) bcma_write32((pc)->core, offset, val)
extern void bcma_core_pci_init(struct bcma_drv_pci *pc);
+extern int bcma_core_pci_irq_ctl(struct bcma_drv_pci *pc,
+ struct bcma_device *core, bool enable);
#endif /* LINUX_BCMA_DRIVER_PCI_H_ */
diff --git a/include/linux/cordic.h b/include/linux/cordic.h
new file mode 100644
index 0000000..f932093
--- /dev/null
+++ b/include/linux/cordic.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2011 Broadcom Corporation
+ *
+ * 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 __CORDIC_H_
+#define __CORDIC_H_
+
+#include <linux/types.h>
+
+/**
+ * struct cordic_iq - i/q coordinate.
+ *
+ * @i: real part of coordinate (in phase).
+ * @q: imaginary part of coordinate (quadrature).
+ */
+struct cordic_iq {
+ s32 i;
+ s32 q;
+};
+
+/**
+ * cordic_calc_iq() - calculates the i/q coordinate for given angle.
+ *
+ * @theta: angle in degrees for which i/q coordinate is to be calculated.
+ * @coord: function output parameter holding the i/q coordinate.
+ *
+ * The function calculates the i/q coordinate for a given angle using
+ * cordic algorithm. The coordinate consists of a real (i) and an
+ * imaginary (q) part. The real part is essentially the cosine of the
+ * angle and the imaginary part is the sine of the angle. The returned
+ * values are scaled by 2^16 for precision. The range for theta is
+ * for -180 degrees to +180 degrees. Passed values outside this range are
+ * converted before doing the actual calculation.
+ */
+struct cordic_iq cordic_calc_iq(s32 theta);
+
+#endif /* __CORDIC_H_ */
diff --git a/include/linux/crc8.h b/include/linux/crc8.h
new file mode 100644
index 0000000..13c8dab
--- /dev/null
+++ b/include/linux/crc8.h
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2011 Broadcom Corporation
+ *
+ * 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 __CRC8_H_
+#define __CRC8_H_
+
+#include <linux/types.h>
+
+/* see usage of this value in crc8() description */
+#define CRC8_INIT_VALUE 0xFF
+
+/*
+ * Return value of crc8() indicating valid message+crc. This is true
+ * if a CRC is inverted before transmission. The CRC computed over the
+ * whole received bitstream is _table[x], where x is the bit pattern
+ * of the modification (almost always 0xff).
+ */
+#define CRC8_GOOD_VALUE(_table) (_table[0xFF])
+
+/* required table size for crc8 algorithm */
+#define CRC8_TABLE_SIZE 256
+
+/* helper macro assuring right table size is used */
+#define DECLARE_CRC8_TABLE(_table) \
+ static u8 _table[CRC8_TABLE_SIZE]
+
+/**
+ * crc8_populate_lsb - fill crc table for given polynomial in regular bit order.
+ *
+ * @table: table to be filled.
+ * @polynomial: polynomial for which table is to be filled.
+ *
+ * This function fills the provided table according the polynomial provided for
+ * regular bit order (lsb first). Polynomials in CRC algorithms are typically
+ * represented as shown below.
+ *
+ * poly = x^8 + x^7 + x^6 + x^4 + x^2 + 1
+ *
+ * For lsb first direction x^7 maps to the lsb. So the polynomial is as below.
+ *
+ * - lsb first: poly = 10101011(1) = 0xAB
+ */
+void crc8_populate_lsb(u8 table[CRC8_TABLE_SIZE], u8 polynomial);
+
+/**
+ * crc8_populate_msb - fill crc table for given polynomial in reverse bit order.
+ *
+ * @table: table to be filled.
+ * @polynomial: polynomial for which table is to be filled.
+ *
+ * This function fills the provided table according the polynomial provided for
+ * reverse bit order (msb first). Polynomials in CRC algorithms are typically
+ * represented as shown below.
+ *
+ * poly = x^8 + x^7 + x^6 + x^4 + x^2 + 1
+ *
+ * For msb first direction x^7 maps to the msb. So the polynomial is as below.
+ *
+ * - msb first: poly = (1)11010101 = 0xD5
+ */
+void crc8_populate_msb(u8 table[CRC8_TABLE_SIZE], u8 polynomial);
+
+/**
+ * crc8() - calculate a crc8 over the given input data.
+ *
+ * @table: crc table used for calculation.
+ * @pdata: pointer to data buffer.
+ * @nbytes: number of bytes in data buffer.
+ * @crc: previous returned crc8 value.
+ *
+ * The CRC8 is calculated using the polynomial given in crc8_populate_msb()
+ * or crc8_populate_lsb().
+ *
+ * The caller provides the initial value (either %CRC8_INIT_VALUE
+ * or the previous returned value) to allow for processing of
+ * discontiguous blocks of data. When generating the CRC the
+ * caller is responsible for complementing the final return value
+ * and inserting it into the byte stream. When validating a byte
+ * stream (including CRC8), a final return value of %CRC8_GOOD_VALUE
+ * indicates the byte stream data can be considered valid.
+ *
+ * Reference:
+ * "A Painless Guide to CRC Error Detection Algorithms", ver 3, Aug 1993
+ * Williams, Ross N., ross<at>ross.net
+ * (see URL http://www.ross.net/crc/download/crc_v3.txt).
+ */
+u8 crc8(const u8 table[CRC8_TABLE_SIZE], u8 *pdata, size_t nbytes, u8 crc);
+
+#endif /* __CRC8_H_ */
diff --git a/include/linux/dcbnl.h b/include/linux/dcbnl.h
index c522800..66a6723 100644
--- a/include/linux/dcbnl.h
+++ b/include/linux/dcbnl.h
@@ -203,6 +203,7 @@
* @DCB_CMD_GFEATCFG: get DCBX features flags
* @DCB_CMD_SFEATCFG: set DCBX features negotiation flags
* @DCB_CMD_CEE_GET: get CEE aggregated configuration
+ * @DCB_CMD_IEEE_DEL: delete IEEE 802.1Qaz configuration
*/
enum dcbnl_commands {
DCB_CMD_UNDEFINED,
@@ -246,6 +247,7 @@
DCB_CMD_SFEATCFG,
DCB_CMD_CEE_GET,
+ DCB_CMD_IEEE_DEL,
__DCB_CMD_ENUM_MAX,
DCB_CMD_MAX = __DCB_CMD_ENUM_MAX - 1,
diff --git a/include/linux/dccp.h b/include/linux/dccp.h
index d638e85..710c043 100644
--- a/include/linux/dccp.h
+++ b/include/linux/dccp.h
@@ -236,6 +236,7 @@
#ifdef __KERNEL__
#include <linux/in.h>
+#include <linux/interrupt.h>
#include <linux/ktime.h>
#include <linux/list.h>
#include <linux/uio.h>
diff --git a/include/linux/dma-direction.h b/include/linux/dma-direction.h
new file mode 100644
index 0000000..95b6a82
--- /dev/null
+++ b/include/linux/dma-direction.h
@@ -0,0 +1,13 @@
+#ifndef _LINUX_DMA_DIRECTION_H
+#define _LINUX_DMA_DIRECTION_H
+/*
+ * These definitions mirror those in pci.h, so they can be used
+ * interchangeably with their PCI_ counterparts.
+ */
+enum dma_data_direction {
+ DMA_BIDIRECTIONAL = 0,
+ DMA_TO_DEVICE = 1,
+ DMA_FROM_DEVICE = 2,
+ DMA_NONE = 3,
+};
+#endif
diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
index ba8319a..1a167c4 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -4,17 +4,9 @@
#include <linux/device.h>
#include <linux/err.h>
#include <linux/dma-attrs.h>
+#include <linux/dma-direction.h>
#include <linux/scatterlist.h>
-/* These definitions mirror those in pci.h, so they can be used
- * interchangeably with their PCI_ counterparts */
-enum dma_data_direction {
- DMA_BIDIRECTIONAL = 0,
- DMA_TO_DEVICE = 1,
- DMA_FROM_DEVICE = 2,
- DMA_NONE = 3,
-};
-
struct dma_map_ops {
void* (*alloc_coherent)(struct device *dev, size_t size,
dma_addr_t *dma_handle, gfp_t gfp);
diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h
index eee7add..8fbf40e 100644
--- a/include/linux/dmaengine.h
+++ b/include/linux/dmaengine.h
@@ -23,7 +23,9 @@
#include <linux/device.h>
#include <linux/uio.h>
-#include <linux/dma-mapping.h>
+#include <linux/dma-direction.h>
+
+struct scatterlist;
/**
* typedef dma_cookie_t - an opaque DMA cookie
diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
index 439b173..c6e427a 100644
--- a/include/linux/ethtool.h
+++ b/include/linux/ethtool.h
@@ -287,7 +287,7 @@
ETH_SS_TEST = 0,
ETH_SS_STATS,
ETH_SS_PRIV_FLAGS,
- ETH_SS_NTUPLE_FILTERS,
+ ETH_SS_NTUPLE_FILTERS, /* Do not use, GRXNTUPLE is now deprecated */
ETH_SS_FEATURES,
};
@@ -310,9 +310,21 @@
__u32's, etc. */
};
+/**
+ * enum ethtool_test_flags - flags definition of ethtool_test
+ * @ETH_TEST_FL_OFFLINE: if set perform online and offline tests, otherwise
+ * only online tests.
+ * @ETH_TEST_FL_FAILED: Driver set this flag if test fails.
+ * @ETH_TEST_FL_EXTERNAL_LB: Application request to perform external loopback
+ * test.
+ * @ETH_TEST_FL_EXTERNAL_LB_DONE: Driver performed the external loopback test
+ */
+
enum ethtool_test_flags {
- ETH_TEST_FL_OFFLINE = (1 << 0), /* online / offline */
- ETH_TEST_FL_FAILED = (1 << 1), /* test passed / failed */
+ ETH_TEST_FL_OFFLINE = (1 << 0),
+ ETH_TEST_FL_FAILED = (1 << 1),
+ ETH_TEST_FL_EXTERNAL_LB = (1 << 2),
+ ETH_TEST_FL_EXTERNAL_LB_DONE = (1 << 3),
};
/* for requesting NIC test and getting results*/
@@ -714,18 +726,6 @@
/* needed by dev_disable_lro() */
extern int __ethtool_set_flags(struct net_device *dev, u32 flags);
-struct ethtool_rx_ntuple_flow_spec_container {
- struct ethtool_rx_ntuple_flow_spec fs;
- struct list_head list;
-};
-
-struct ethtool_rx_ntuple_list {
-#define ETHTOOL_MAX_NTUPLE_LIST_ENTRY 1024
-#define ETHTOOL_MAX_NTUPLE_STRING_PER_ENTRY 14
- struct list_head list;
- unsigned int count;
-};
-
/**
* enum ethtool_phys_id_state - indicator state for physical identification
* @ETHTOOL_ID_INACTIVE: Physical ID indicator should be deactivated
@@ -758,7 +758,6 @@
int ethtool_op_set_ufo(struct net_device *dev, u32 data);
u32 ethtool_op_get_flags(struct net_device *dev);
int ethtool_op_set_flags(struct net_device *dev, u32 data, u32 supported);
-void ethtool_ntuple_flush(struct net_device *dev);
bool ethtool_invalid_flags(struct net_device *dev, u32 data, u32 supported);
/**
@@ -865,7 +864,6 @@
* error code or zero.
* @set_rx_ntuple: Set an RX n-tuple rule. Returns a negative error code
* or zero.
- * @get_rx_ntuple: Deprecated.
* @get_rxfh_indir: Get the contents of the RX flow hash indirection table.
* Returns a negative error code or zero.
* @set_rxfh_indir: Set the contents of the RX flow hash indirection table.
@@ -944,7 +942,6 @@
int (*reset)(struct net_device *, u32 *);
int (*set_rx_ntuple)(struct net_device *,
struct ethtool_rx_ntuple *);
- int (*get_rx_ntuple)(struct net_device *, u32 stringset, void *);
int (*get_rxfh_indir)(struct net_device *,
struct ethtool_rxfh_indir *);
int (*set_rxfh_indir)(struct net_device *,
@@ -1017,7 +1014,7 @@
#define ETHTOOL_FLASHDEV 0x00000033 /* Flash firmware to device */
#define ETHTOOL_RESET 0x00000034 /* Reset hardware */
#define ETHTOOL_SRXNTUPLE 0x00000035 /* Add an n-tuple filter to device */
-#define ETHTOOL_GRXNTUPLE 0x00000036 /* Get n-tuple filters from device */
+#define ETHTOOL_GRXNTUPLE 0x00000036 /* deprecated */
#define ETHTOOL_GSSET_INFO 0x00000037 /* Get string set info */
#define ETHTOOL_GRXFHINDIR 0x00000038 /* Get RX flow hash indir'n table */
#define ETHTOOL_SRXFHINDIR 0x00000039 /* Set RX flow hash indir'n table */
diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index bf56b6f..a26108e 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -117,8 +117,19 @@
#define IEEE80211_MAX_MESH_ID_LEN 32
#define IEEE80211_QOS_CTL_LEN 2
-#define IEEE80211_QOS_CTL_TID_MASK 0x000F
-#define IEEE80211_QOS_CTL_TAG1D_MASK 0x0007
+/* 1d tag mask */
+#define IEEE80211_QOS_CTL_TAG1D_MASK 0x0007
+/* TID mask */
+#define IEEE80211_QOS_CTL_TID_MASK 0x000f
+/* EOSP */
+#define IEEE80211_QOS_CTL_EOSP 0x0010
+/* ACK policy */
+#define IEEE80211_QOS_CTL_ACK_POLICY_NORMAL 0x0000
+#define IEEE80211_QOS_CTL_ACK_POLICY_NOACK 0x0020
+#define IEEE80211_QOS_CTL_ACK_POLICY_NO_EXPL 0x0040
+#define IEEE80211_QOS_CTL_ACK_POLICY_BLOCKACK 0x0060
+/* A-MSDU 802.11n */
+#define IEEE80211_QOS_CTL_A_MSDU_PRESENT 0x0080
/* U-APSD queue for WMM IEs sent by AP */
#define IEEE80211_WMM_IE_AP_QOSINFO_UAPSD (1<<7)
@@ -1423,9 +1434,6 @@
};
-/* A-MSDU 802.11n */
-#define IEEE80211_QOS_CONTROL_A_MSDU_PRESENT 0x0080
-
/* cipher suite selectors */
#define WLAN_CIPHER_SUITE_USE_GROUP 0x000FAC00
#define WLAN_CIPHER_SUITE_WEP40 0x000FAC01
diff --git a/include/linux/if_packet.h b/include/linux/if_packet.h
index 7b31863..84e684e 100644
--- a/include/linux/if_packet.h
+++ b/include/linux/if_packet.h
@@ -49,6 +49,11 @@
#define PACKET_VNET_HDR 15
#define PACKET_TX_TIMESTAMP 16
#define PACKET_TIMESTAMP 17
+#define PACKET_FANOUT 18
+
+#define PACKET_FANOUT_HASH 0
+#define PACKET_FANOUT_LB 1
+#define PACKET_FANOUT_FLAG_DEFRAG 0x8000
struct tpacket_stats {
unsigned int tp_packets;
diff --git a/include/linux/mii.h b/include/linux/mii.h
index 359fba8..103113a 100644
--- a/include/linux/mii.h
+++ b/include/linux/mii.h
@@ -128,6 +128,8 @@
/* 1000BASE-T Control register */
#define ADVERTISE_1000FULL 0x0200 /* Advertise 1000BASE-T full duplex */
#define ADVERTISE_1000HALF 0x0100 /* Advertise 1000BASE-T half duplex */
+#define CTL1000_AS_MASTER 0x0800
+#define CTL1000_ENABLE_MASTER 0x1000
/* 1000BASE-T Status register */
#define LPA_1000LOCALRXOK 0x2000 /* Link partner local receiver status */
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 54b8b4d..011eb89 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -34,7 +34,6 @@
#include <linux/pm_qos_params.h>
#include <linux/timer.h>
#include <linux/delay.h>
-#include <linux/mm.h>
#include <asm/atomic.h>
#include <asm/cache.h>
#include <asm/byteorder.h>
@@ -1348,9 +1347,6 @@
/* max exchange id for FCoE LRO by ddp */
unsigned int fcoe_ddp_xid;
#endif
- /* n-tuple filter list attached to this device */
- struct ethtool_rx_ntuple_list ethtool_ntuple_list;
-
/* phy device may attach itself for hardware timestamping */
struct phy_device *phydev;
@@ -1563,7 +1559,6 @@
struct list_head list;
};
-#include <linux/interrupt.h>
#include <linux/notifier.h>
extern rwlock_t dev_base_lock; /* Device list lock */
diff --git a/include/linux/netfilter/ipset/ip_set.h b/include/linux/netfilter/ipset/ip_set.h
index 5a262e3..3540c6e 100644
--- a/include/linux/netfilter/ipset/ip_set.h
+++ b/include/linux/netfilter/ipset/ip_set.h
@@ -104,6 +104,8 @@
IPSET_ATTR_NAMEREF,
IPSET_ATTR_IP2,
IPSET_ATTR_CIDR2,
+ IPSET_ATTR_IP2_TO,
+ IPSET_ATTR_IFACE,
__IPSET_ATTR_ADT_MAX,
};
#define IPSET_ATTR_ADT_MAX (__IPSET_ATTR_ADT_MAX - 1)
@@ -142,12 +144,18 @@
enum ipset_cmd_flags {
IPSET_FLAG_BIT_EXIST = 0,
IPSET_FLAG_EXIST = (1 << IPSET_FLAG_BIT_EXIST),
+ IPSET_FLAG_BIT_LIST_SETNAME = 1,
+ IPSET_FLAG_LIST_SETNAME = (1 << IPSET_FLAG_BIT_LIST_SETNAME),
+ IPSET_FLAG_BIT_LIST_HEADER = 2,
+ IPSET_FLAG_LIST_HEADER = (1 << IPSET_FLAG_BIT_LIST_HEADER),
};
/* Flags at CADT attribute level */
enum ipset_cadt_flags {
IPSET_FLAG_BIT_BEFORE = 0,
IPSET_FLAG_BEFORE = (1 << IPSET_FLAG_BIT_BEFORE),
+ IPSET_FLAG_BIT_PHYSDEV = 1,
+ IPSET_FLAG_PHYSDEV = (1 << IPSET_FLAG_BIT_PHYSDEV),
};
/* Commands with settype-specific attributes */
@@ -165,6 +173,7 @@
#include <linux/ipv6.h>
#include <linux/netlink.h>
#include <linux/netfilter.h>
+#include <linux/netfilter/x_tables.h>
#include <linux/vmalloc.h>
#include <net/netlink.h>
@@ -206,6 +215,8 @@
IPSET_TYPE_IP2 = (1 << IPSET_TYPE_IP2_FLAG),
IPSET_TYPE_NAME_FLAG = 4,
IPSET_TYPE_NAME = (1 << IPSET_TYPE_NAME_FLAG),
+ IPSET_TYPE_IFACE_FLAG = 5,
+ IPSET_TYPE_IFACE = (1 << IPSET_TYPE_IFACE_FLAG),
/* Strictly speaking not a feature, but a flag for dumping:
* this settype must be dumped last */
IPSET_DUMP_LAST_FLAG = 7,
@@ -214,7 +225,17 @@
struct ip_set;
-typedef int (*ipset_adtfn)(struct ip_set *set, void *value, u32 timeout);
+typedef int (*ipset_adtfn)(struct ip_set *set, void *value,
+ u32 timeout, u32 flags);
+
+/* Kernel API function options */
+struct ip_set_adt_opt {
+ u8 family; /* Actual protocol family */
+ u8 dim; /* Dimension of match/target */
+ u8 flags; /* Direction and negation flags */
+ u32 cmdflags; /* Command-like flags */
+ u32 timeout; /* Timeout value */
+};
/* Set type, variant-specific part */
struct ip_set_type_variant {
@@ -223,14 +244,15 @@
* zero for no match/success to add/delete
* positive for matching element */
int (*kadt)(struct ip_set *set, const struct sk_buff * skb,
- enum ipset_adt adt, u8 pf, u8 dim, u8 flags);
+ const struct xt_action_param *par,
+ enum ipset_adt adt, const struct ip_set_adt_opt *opt);
/* Userspace: test/add/del entries
* returns negative error code,
* zero for no match/success to add/delete
* positive for matching element */
int (*uadt)(struct ip_set *set, struct nlattr *tb[],
- enum ipset_adt adt, u32 *lineno, u32 flags);
+ enum ipset_adt adt, u32 *lineno, u32 flags, bool retried);
/* Low level add/del/test functions */
ipset_adtfn adt[IPSET_ADT_MAX];
@@ -268,8 +290,8 @@
u8 dimension;
/* Supported family: may be AF_UNSPEC for both AF_INET/AF_INET6 */
u8 family;
- /* Type revision */
- u8 revision;
+ /* Type revisions */
+ u8 revision_min, revision_max;
/* Create set */
int (*create)(struct ip_set *set, struct nlattr *tb[], u32 flags);
@@ -300,6 +322,8 @@
const struct ip_set_type_variant *variant;
/* The actual INET family of the set */
u8 family;
+ /* The type revision */
+ u8 revision;
/* The type specific data */
void *data;
};
@@ -307,21 +331,25 @@
/* register and unregister set references */
extern ip_set_id_t ip_set_get_byname(const char *name, struct ip_set **set);
extern void ip_set_put_byindex(ip_set_id_t index);
-extern const char * ip_set_name_byindex(ip_set_id_t index);
+extern const char *ip_set_name_byindex(ip_set_id_t index);
extern ip_set_id_t ip_set_nfnl_get(const char *name);
extern ip_set_id_t ip_set_nfnl_get_byindex(ip_set_id_t index);
extern void ip_set_nfnl_put(ip_set_id_t index);
/* API for iptables set match, and SET target */
+
extern int ip_set_add(ip_set_id_t id, const struct sk_buff *skb,
- u8 family, u8 dim, u8 flags);
+ const struct xt_action_param *par,
+ const struct ip_set_adt_opt *opt);
extern int ip_set_del(ip_set_id_t id, const struct sk_buff *skb,
- u8 family, u8 dim, u8 flags);
+ const struct xt_action_param *par,
+ const struct ip_set_adt_opt *opt);
extern int ip_set_test(ip_set_id_t id, const struct sk_buff *skb,
- u8 family, u8 dim, u8 flags);
+ const struct xt_action_param *par,
+ const struct ip_set_adt_opt *opt);
/* Utility functions */
-extern void * ip_set_alloc(size_t size);
+extern void *ip_set_alloc(size_t size);
extern void ip_set_free(void *members);
extern int ip_set_get_ipaddr4(struct nlattr *nla, __be32 *ipaddr);
extern int ip_set_get_ipaddr6(struct nlattr *nla, union nf_inet_addr *ipaddr);
@@ -331,7 +359,7 @@
{
__be32 ip;
int ret = ip_set_get_ipaddr4(nla, &ip);
-
+
if (ret)
return ret;
*ipaddr = ntohl(ip);
diff --git a/include/linux/netfilter/ipset/ip_set_ahash.h b/include/linux/netfilter/ipset/ip_set_ahash.h
index ac3c822..c5b06aa 100644
--- a/include/linux/netfilter/ipset/ip_set_ahash.h
+++ b/include/linux/netfilter/ipset/ip_set_ahash.h
@@ -5,6 +5,11 @@
#include <linux/jhash.h>
#include <linux/netfilter/ipset/ip_set_timeout.h>
+#define CONCAT(a, b, c) a##b##c
+#define TOKEN(a, b, c) CONCAT(a, b, c)
+
+#define type_pf_next TOKEN(TYPE, PF, _elem)
+
/* Hashing which uses arrays to resolve clashing. The hash table is resized
* (doubled) when searching becomes too long.
* Internally jhash is used with the assumption that the size of the
@@ -38,7 +43,7 @@
struct hbucket bucket[0]; /* hashtable buckets */
};
-#define hbucket(h, i) &((h)->bucket[i])
+#define hbucket(h, i) (&((h)->bucket[i]))
/* Book-keeping of the prefixes added to the set */
struct ip_set_hash_nets {
@@ -54,9 +59,13 @@
u32 initval; /* random jhash init value */
u32 timeout; /* timeout value, if enabled */
struct timer_list gc; /* garbage collection when timeout enabled */
+ struct type_pf_next next; /* temporary storage for uadd */
#ifdef IP_SET_HASH_WITH_NETMASK
u8 netmask; /* netmask value for subnets to store */
#endif
+#ifdef IP_SET_HASH_WITH_RBTREE
+ struct rb_root rbtree;
+#endif
#ifdef IP_SET_HASH_WITH_NETS
struct ip_set_hash_nets nets[0]; /* book-keeping of prefixes */
#endif
@@ -194,6 +203,9 @@
del_timer_sync(&h->gc);
ahash_destroy(h->table);
+#ifdef IP_SET_HASH_WITH_RBTREE
+ rbtree_destroy(&h->rbtree);
+#endif
kfree(h);
set->data = NULL;
@@ -217,6 +229,7 @@
#define type_pf_data_netmask TOKEN(TYPE, PF, _data_netmask)
#define type_pf_data_list TOKEN(TYPE, PF, _data_list)
#define type_pf_data_tlist TOKEN(TYPE, PF, _data_tlist)
+#define type_pf_data_next TOKEN(TYPE, PF, _data_next)
#define type_pf_elem TOKEN(TYPE, PF, _elem)
#define type_pf_telem TOKEN(TYPE, PF, _telem)
@@ -346,10 +359,13 @@
return 0;
}
+static void
+type_pf_data_next(struct ip_set_hash *h, const struct type_pf_elem *d);
+
/* Add an element to a hash and update the internal counters when succeeded,
* otherwise report the proper error code. */
static int
-type_pf_add(struct ip_set *set, void *value, u32 timeout)
+type_pf_add(struct ip_set *set, void *value, u32 timeout, u32 flags)
{
struct ip_set_hash *h = set->data;
struct htable *t;
@@ -372,8 +388,11 @@
}
ret = type_pf_elem_add(n, value);
- if (ret != 0)
+ if (ret != 0) {
+ if (ret == -EAGAIN)
+ type_pf_data_next(h, d);
goto out;
+ }
#ifdef IP_SET_HASH_WITH_NETS
add_cidr(h, d->cidr, HOST_MASK);
@@ -388,7 +407,7 @@
* and free up space if possible.
*/
static int
-type_pf_del(struct ip_set *set, void *value, u32 timeout)
+type_pf_del(struct ip_set *set, void *value, u32 timeout, u32 flags)
{
struct ip_set_hash *h = set->data;
struct htable *t = h->table;
@@ -463,7 +482,7 @@
/* Test whether the element is added to the set */
static int
-type_pf_test(struct ip_set *set, void *value, u32 timeout)
+type_pf_test(struct ip_set *set, void *value, u32 timeout, u32 flags)
{
struct ip_set_hash *h = set->data;
struct htable *t = h->table;
@@ -586,10 +605,11 @@
static int
type_pf_kadt(struct ip_set *set, const struct sk_buff * skb,
- enum ipset_adt adt, u8 pf, u8 dim, u8 flags);
+ const struct xt_action_param *par,
+ enum ipset_adt adt, const struct ip_set_adt_opt *opt);
static int
type_pf_uadt(struct ip_set *set, struct nlattr *tb[],
- enum ipset_adt adt, u32 *lineno, u32 flags);
+ enum ipset_adt adt, u32 *lineno, u32 flags, bool retried);
static const struct ip_set_type_variant type_pf_variant = {
.kadt = type_pf_kadt,
@@ -776,7 +796,7 @@
}
static int
-type_pf_tadd(struct ip_set *set, void *value, u32 timeout)
+type_pf_tadd(struct ip_set *set, void *value, u32 timeout, u32 flags)
{
struct ip_set_hash *h = set->data;
struct htable *t = h->table;
@@ -784,6 +804,7 @@
struct hbucket *n;
struct type_pf_elem *data;
int ret = 0, i, j = AHASH_MAX_SIZE + 1;
+ bool flag_exist = flags & IPSET_FLAG_EXIST;
u32 key;
if (h->elements >= h->maxelem)
@@ -799,7 +820,7 @@
for (i = 0; i < n->pos; i++) {
data = ahash_tdata(n, i);
if (type_pf_data_equal(data, d)) {
- if (type_pf_data_expired(data))
+ if (type_pf_data_expired(data) || flag_exist)
j = i;
else {
ret = -IPSET_ERR_EXIST;
@@ -820,8 +841,11 @@
goto out;
}
ret = type_pf_elem_tadd(n, d, timeout);
- if (ret != 0)
+ if (ret != 0) {
+ if (ret == -EAGAIN)
+ type_pf_data_next(h, d);
goto out;
+ }
#ifdef IP_SET_HASH_WITH_NETS
add_cidr(h, d->cidr, HOST_MASK);
@@ -833,7 +857,7 @@
}
static int
-type_pf_tdel(struct ip_set *set, void *value, u32 timeout)
+type_pf_tdel(struct ip_set *set, void *value, u32 timeout, u32 flags)
{
struct ip_set_hash *h = set->data;
struct htable *t = h->table;
@@ -905,7 +929,7 @@
#endif
static int
-type_pf_ttest(struct ip_set *set, void *value, u32 timeout)
+type_pf_ttest(struct ip_set *set, void *value, u32 timeout, u32 flags)
{
struct ip_set_hash *h = set->data;
struct htable *t = h->table;
diff --git a/include/linux/netfilter/ipset/ip_set_hash.h b/include/linux/netfilter/ipset/ip_set_hash.h
index b86f15c..e2a9fae 100644
--- a/include/linux/netfilter/ipset/ip_set_hash.h
+++ b/include/linux/netfilter/ipset/ip_set_hash.h
@@ -11,6 +11,10 @@
IPSET_ERR_INVALID_PROTO,
/* Protocol missing but must be specified */
IPSET_ERR_MISSING_PROTO,
+ /* Range not supported */
+ IPSET_ERR_HASH_RANGE_UNSUPPORTED,
+ /* Invalid range */
+ IPSET_ERR_HASH_RANGE,
};
#ifdef __KERNEL__
diff --git a/include/linux/netfilter/ipset/ip_set_timeout.h b/include/linux/netfilter/ipset/ip_set_timeout.h
index bcdd40a..4792320 100644
--- a/include/linux/netfilter/ipset/ip_set_timeout.h
+++ b/include/linux/netfilter/ipset/ip_set_timeout.h
@@ -22,6 +22,9 @@
#define with_timeout(timeout) ((timeout) != IPSET_NO_TIMEOUT)
+#define opt_timeout(opt, map) \
+ (with_timeout((opt)->timeout) ? (opt)->timeout : (map)->timeout)
+
static inline unsigned int
ip_set_timeout_uget(struct nlattr *tb)
{
@@ -75,7 +78,7 @@
static inline u32
ip_set_timeout_get(unsigned long timeout)
{
- return timeout == IPSET_ELEM_PERMANENT ? 0 :
+ return timeout == IPSET_ELEM_PERMANENT ? 0 :
jiffies_to_msecs(timeout - jiffies)/1000;
}
diff --git a/include/linux/netfilter/ipset/pfxlen.h b/include/linux/netfilter/ipset/pfxlen.h
index 0e1fb50..199fd11 100644
--- a/include/linux/netfilter/ipset/pfxlen.h
+++ b/include/linux/netfilter/ipset/pfxlen.h
@@ -2,7 +2,8 @@
#define _PFXLEN_H
#include <asm/byteorder.h>
-#include <linux/netfilter.h>
+#include <linux/netfilter.h>
+#include <net/tcp.h>
/* Prefixlen maps, by Jan Engelhardt */
extern const union nf_inet_addr ip_set_netmask_map[];
@@ -32,4 +33,12 @@
return &ip_set_hostmask_map[pfxlen].ip6[0];
}
+extern u32 ip_set_range_to_cidr(u32 from, u32 to, u8 *cidr);
+
+#define ip_set_mask_from_to(from, to, cidr) \
+do { \
+ from &= ip_set_hostmask(cidr); \
+ to = from | ~ip_set_hostmask(cidr); \
+} while (0)
+
#endif /*_PFXLEN_H */
diff --git a/include/linux/netfilter/xt_set.h b/include/linux/netfilter/xt_set.h
index 081f1de..c0405ac 100644
--- a/include/linux/netfilter/xt_set.h
+++ b/include/linux/netfilter/xt_set.h
@@ -35,7 +35,7 @@
struct xt_set_info_v0 del_set;
};
-/* Revision 1: current interface to netfilter/iptables */
+/* Revision 1 match and target */
struct xt_set_info {
ip_set_id_t index;
@@ -44,13 +44,22 @@
};
/* match and target infos */
-struct xt_set_info_match {
+struct xt_set_info_match_v1 {
struct xt_set_info match_set;
};
-struct xt_set_info_target {
+struct xt_set_info_target_v1 {
struct xt_set_info add_set;
struct xt_set_info del_set;
};
+/* Revision 2 target */
+
+struct xt_set_info_target_v2 {
+ struct xt_set_info add_set;
+ struct xt_set_info del_set;
+ u32 flags;
+ u32 timeout;
+};
+
#endif /*_XT_SET_H*/
diff --git a/include/linux/netlink.h b/include/linux/netlink.h
index a9dd895..2e17c5d 100644
--- a/include/linux/netlink.h
+++ b/include/linux/netlink.h
@@ -49,6 +49,7 @@
#define NLM_F_MULTI 2 /* Multipart message, terminated by NLMSG_DONE */
#define NLM_F_ACK 4 /* Reply with ack, with zero or error code */
#define NLM_F_ECHO 8 /* Echo this request */
+#define NLM_F_DUMP_INTR 16 /* Dump was inconsistent due to sequence change */
/* Modifiers to GET request */
#define NLM_F_ROOT 0x100 /* specify tree root */
@@ -221,7 +222,9 @@
int (*dump)(struct sk_buff * skb,
struct netlink_callback *cb);
int (*done)(struct netlink_callback *cb);
- int family;
+ u16 family;
+ u16 min_dump_alloc;
+ unsigned int prev_seq, seq;
long args[6];
};
@@ -259,7 +262,8 @@
extern int netlink_dump_start(struct sock *ssk, struct sk_buff *skb,
const struct nlmsghdr *nlh,
int (*dump)(struct sk_buff *skb, struct netlink_callback*),
- int (*done)(struct netlink_callback*));
+ int (*done)(struct netlink_callback*),
+ u16 min_dump_alloc);
#define NL_NONROOT_RECV 0x1
diff --git a/include/linux/netpoll.h b/include/linux/netpoll.h
index 79358bb..5dfa091 100644
--- a/include/linux/netpoll.h
+++ b/include/linux/netpoll.h
@@ -40,8 +40,6 @@
struct netpoll *netpoll;
};
-void netpoll_poll_dev(struct net_device *dev);
-void netpoll_poll(struct netpoll *np);
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);
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index f8910e1..0570930 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -2103,6 +2103,9 @@
#define PCI_DEVICE_ID_TIGON3_5761E 0x1680
#define PCI_DEVICE_ID_TIGON3_5761 0x1681
#define PCI_DEVICE_ID_TIGON3_5764 0x1684
+#define PCI_DEVICE_ID_NX2_57800 0x168a
+#define PCI_DEVICE_ID_NX2_57840 0x168d
+#define PCI_DEVICE_ID_NX2_57810 0x168e
#define PCI_DEVICE_ID_TIGON3_5787M 0x1693
#define PCI_DEVICE_ID_TIGON3_5782 0x1696
#define PCI_DEVICE_ID_TIGON3_5784 0x1698
@@ -2110,11 +2113,17 @@
#define PCI_DEVICE_ID_TIGON3_5787 0x169b
#define PCI_DEVICE_ID_TIGON3_5788 0x169c
#define PCI_DEVICE_ID_TIGON3_5789 0x169d
+#define PCI_DEVICE_ID_NX2_57800_MF 0x16a5
#define PCI_DEVICE_ID_TIGON3_5702X 0x16a6
#define PCI_DEVICE_ID_TIGON3_5703X 0x16a7
#define PCI_DEVICE_ID_TIGON3_5704S 0x16a8
+#define PCI_DEVICE_ID_NX2_57800_VF 0x16a9
#define PCI_DEVICE_ID_NX2_5706S 0x16aa
+#define PCI_DEVICE_ID_NX2_57840_MF 0x16ab
#define PCI_DEVICE_ID_NX2_5708S 0x16ac
+#define PCI_DEVICE_ID_NX2_57840_VF 0x16ad
+#define PCI_DEVICE_ID_NX2_57810_MF 0x16ae
+#define PCI_DEVICE_ID_NX2_57810_VF 0x16af
#define PCI_DEVICE_ID_TIGON3_5702A3 0x16c6
#define PCI_DEVICE_ID_TIGON3_5703A3 0x16c7
#define PCI_DEVICE_ID_TIGON3_5781 0x16dd
diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h
index bbad657..c81226a 100644
--- a/include/linux/rtnetlink.h
+++ b/include/linux/rtnetlink.h
@@ -585,6 +585,8 @@
#define RTNLGRP_PHONET_IFADDR RTNLGRP_PHONET_IFADDR
RTNLGRP_PHONET_ROUTE,
#define RTNLGRP_PHONET_ROUTE RTNLGRP_PHONET_ROUTE
+ RTNLGRP_DCB,
+#define RTNLGRP_DCB RTNLGRP_DCB
__RTNLGRP_MAX
};
#define RTNLGRP_MAX (__RTNLGRP_MAX - 1)
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index c0a4f3a..3e54337 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -2028,8 +2028,7 @@
* skb_tx_timestamp() - Driver hook for transmit timestamping
*
* Ethernet MAC Drivers should call this function in their hard_xmit()
- * function as soon as possible after giving the sk_buff to the MAC
- * hardware, but before freeing the sk_buff.
+ * function immediately before giving the sk_buff to the MAC hardware.
*
* @skb: A socket buffer.
*/
diff --git a/include/linux/tcp.h b/include/linux/tcp.h
index e64f4c6..531ede8 100644
--- a/include/linux/tcp.h
+++ b/include/linux/tcp.h
@@ -282,6 +282,7 @@
#endif
u32 rcv_isn;
u32 snt_isn;
+ u32 snt_synack; /* synack sent time */
};
static inline struct tcp_request_sock *tcp_rsk(const struct request_sock *req)
diff --git a/include/linux/virtio_net.h b/include/linux/virtio_net.h
index 136040b..970d5a2 100644
--- a/include/linux/virtio_net.h
+++ b/include/linux/virtio_net.h
@@ -63,6 +63,7 @@
* specify GSO or CSUM features, you can simply ignore the header. */
struct virtio_net_hdr {
#define VIRTIO_NET_HDR_F_NEEDS_CSUM 1 // Use csum_start, csum_offset
+#define VIRTIO_NET_HDR_F_DATA_VALID 2 // Csum is valid
__u8 flags;
#define VIRTIO_NET_HDR_GSO_NONE 0 // Not a GSO frame
#define VIRTIO_NET_HDR_GSO_TCPV4 1 // GSO frame, IPv4 TCP (TSO)
diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h
index 4375043..7bccaf9 100644
--- a/include/net/bluetooth/bluetooth.h
+++ b/include/net/bluetooth/bluetooth.h
@@ -69,6 +69,13 @@
#define BT_FLUSHABLE_OFF 0
#define BT_FLUSHABLE_ON 1
+#define BT_POWER 9
+struct bt_power {
+ __u8 force_active;
+};
+#define BT_POWER_FORCE_ACTIVE_OFF 0
+#define BT_POWER_FORCE_ACTIVE_ON 1
+
#define BT_INFO(fmt, arg...) printk(KERN_INFO "Bluetooth: " fmt "\n" , ## arg)
#define BT_ERR(fmt, arg...) printk(KERN_ERR "%s: " fmt "\n" , __func__ , ## arg)
#define BT_DBG(fmt, arg...) pr_debug("%s: " fmt "\n" , __func__ , ## arg)
@@ -130,7 +137,8 @@
int bt_sock_unregister(int proto);
void bt_sock_link(struct bt_sock_list *l, struct sock *s);
void bt_sock_unlink(struct bt_sock_list *l, struct sock *s);
-int bt_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len, int flags);
+int bt_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
+ struct msghdr *msg, size_t len, int flags);
int bt_sock_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
struct msghdr *msg, size_t len, int flags);
uint bt_sock_poll(struct file * file, struct socket *sock, poll_table *wait);
@@ -150,6 +158,7 @@
__u8 retries;
__u8 sar;
unsigned short channel;
+ __u8 force_active;
};
#define bt_cb(skb) ((struct bt_skb_cb *)((skb)->cb))
@@ -164,8 +173,8 @@
return skb;
}
-static inline struct sk_buff *bt_skb_send_alloc(struct sock *sk, unsigned long len,
- int nb, int *err)
+static inline struct sk_buff *bt_skb_send_alloc(struct sock *sk,
+ unsigned long len, int nb, int *err)
{
struct sk_buff *skb;
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 0c20227..65345cd 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -710,6 +710,12 @@
__u8 le_max_pkt;
} __packed;
+#define HCI_OP_LE_SET_SCAN_ENABLE 0x200c
+struct hci_cp_le_set_scan_enable {
+ __u8 enable;
+ __u8 filter_dup;
+} __packed;
+
#define HCI_OP_LE_CREATE_CONN 0x200d
struct hci_cp_le_create_conn {
__le16 scan_interval;
@@ -739,6 +745,33 @@
__le16 max_ce_len;
} __packed;
+#define HCI_OP_LE_START_ENC 0x2019
+struct hci_cp_le_start_enc {
+ __le16 handle;
+ __u8 rand[8];
+ __le16 ediv;
+ __u8 ltk[16];
+} __packed;
+
+#define HCI_OP_LE_LTK_REPLY 0x201a
+struct hci_cp_le_ltk_reply {
+ __le16 handle;
+ __u8 ltk[16];
+} __packed;
+struct hci_rp_le_ltk_reply {
+ __u8 status;
+ __le16 handle;
+} __packed;
+
+#define HCI_OP_LE_LTK_NEG_REPLY 0x201b
+struct hci_cp_le_ltk_neg_reply {
+ __le16 handle;
+} __packed;
+struct hci_rp_le_ltk_neg_reply {
+ __u8 status;
+ __le16 handle;
+} __packed;
+
/* ---- HCI Events ---- */
#define HCI_EV_INQUIRY_COMPLETE 0x01
@@ -1029,6 +1062,32 @@
__u8 clk_accurancy;
} __packed;
+#define HCI_EV_LE_LTK_REQ 0x05
+struct hci_ev_le_ltk_req {
+ __le16 handle;
+ __u8 random[8];
+ __le16 ediv;
+} __packed;
+
+/* Advertising report event types */
+#define ADV_IND 0x00
+#define ADV_DIRECT_IND 0x01
+#define ADV_SCAN_IND 0x02
+#define ADV_NONCONN_IND 0x03
+#define ADV_SCAN_RSP 0x04
+
+#define ADDR_LE_DEV_PUBLIC 0x00
+#define ADDR_LE_DEV_RANDOM 0x01
+
+#define HCI_EV_LE_ADVERTISING_REPORT 0x02
+struct hci_ev_le_advertising_info {
+ __u8 evt_type;
+ __u8 bdaddr_type;
+ bdaddr_t bdaddr;
+ __u8 length;
+ __u8 data[0];
+} __packed;
+
/* Internal events generated by Bluetooth stack */
#define HCI_EV_STACK_INTERNAL 0xfd
struct hci_ev_stack_internal {
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 6c994c0..19639df 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -25,6 +25,7 @@
#ifndef __HCI_CORE_H
#define __HCI_CORE_H
+#include <linux/interrupt.h>
#include <net/bluetooth/hci.h>
/* HCI upper protocols */
@@ -89,6 +90,12 @@
u8 randomizer[16];
};
+struct adv_entry {
+ struct list_head list;
+ bdaddr_t bdaddr;
+ u8 bdaddr_type;
+};
+
#define NUM_REASSEMBLY 4
struct hci_dev {
struct list_head list;
@@ -171,6 +178,8 @@
__u16 init_last_cmd;
+ struct crypto_blkcipher *tfm;
+
struct inquiry_cache inq_cache;
struct hci_conn_hash conn_hash;
struct list_head blacklist;
@@ -181,6 +190,9 @@
struct list_head remote_oob_data;
+ struct list_head adv_entries;
+ struct timer_list adv_timer;
+
struct hci_dev_stats stat;
struct sk_buff_head driver_init;
@@ -215,6 +227,7 @@
spinlock_t lock;
bdaddr_t dst;
+ __u8 dst_type;
__u16 handle;
__u16 state;
__u8 mode;
@@ -237,6 +250,7 @@
__u8 power_save;
__u16 disc_timeout;
unsigned long pend;
+ __u8 ltk[16];
__u8 remote_cap;
__u8 remote_oob;
@@ -307,12 +321,14 @@
return jiffies - e->timestamp;
}
-struct inquiry_entry *hci_inquiry_cache_lookup(struct hci_dev *hdev, bdaddr_t *bdaddr);
+struct inquiry_entry *hci_inquiry_cache_lookup(struct hci_dev *hdev,
+ bdaddr_t *bdaddr);
void hci_inquiry_cache_update(struct hci_dev *hdev, struct inquiry_data *data);
/* ----- HCI Connections ----- */
enum {
HCI_CONN_AUTH_PEND,
+ HCI_CONN_REAUTH_PEND,
HCI_CONN_ENCRYPT_PEND,
HCI_CONN_RSWITCH_PEND,
HCI_CONN_MODE_CHANGE_PEND,
@@ -420,14 +436,15 @@
void hci_conn_hash_flush(struct hci_dev *hdev);
void hci_conn_check_pending(struct hci_dev *hdev);
-struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8 sec_level, __u8 auth_type);
+struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst,
+ __u8 sec_level, __u8 auth_type);
int hci_conn_check_link_mode(struct hci_conn *conn);
int hci_conn_check_secure(struct hci_conn *conn, __u8 sec_level);
int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type);
int hci_conn_change_link_key(struct hci_conn *conn);
int hci_conn_switch_role(struct hci_conn *conn, __u8 role);
-void hci_conn_enter_active_mode(struct hci_conn *conn);
+void hci_conn_enter_active_mode(struct hci_conn *conn, __u8 force_active);
void hci_conn_enter_sniff_mode(struct hci_conn *conn);
void hci_conn_hold_device(struct hci_conn *conn);
@@ -449,10 +466,12 @@
timeo = msecs_to_jiffies(conn->disc_timeout);
if (!conn->out)
timeo *= 2;
- } else
+ } else {
timeo = msecs_to_jiffies(10);
- } else
+ }
+ } else {
timeo = msecs_to_jiffies(10);
+ }
mod_timer(&conn->disc_timer, jiffies + timeo);
}
}
@@ -511,6 +530,8 @@
struct bdaddr_list *hci_blacklist_lookup(struct hci_dev *hdev, bdaddr_t *bdaddr);
int hci_blacklist_clear(struct hci_dev *hdev);
+int hci_blacklist_add(struct hci_dev *hdev, bdaddr_t *bdaddr);
+int hci_blacklist_del(struct hci_dev *hdev, bdaddr_t *bdaddr);
int hci_uuids_clear(struct hci_dev *hdev);
@@ -527,6 +548,12 @@
u8 *randomizer);
int hci_remove_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr);
+#define ADV_CLEAR_TIMEOUT (3*60*HZ) /* Three minutes */
+int hci_adv_entries_clear(struct hci_dev *hdev);
+struct adv_entry *hci_find_adv_entry(struct hci_dev *hdev, bdaddr_t *bdaddr);
+int hci_add_adv_entry(struct hci_dev *hdev,
+ struct hci_ev_le_advertising_info *ev);
+
void hci_del_off_timer(struct hci_dev *hdev);
void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb);
@@ -561,16 +588,20 @@
void *priv;
- int (*connect_ind) (struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 type);
+ int (*connect_ind) (struct hci_dev *hdev, bdaddr_t *bdaddr,
+ __u8 type);
int (*connect_cfm) (struct hci_conn *conn, __u8 status);
int (*disconn_ind) (struct hci_conn *conn);
int (*disconn_cfm) (struct hci_conn *conn, __u8 reason);
- int (*recv_acldata) (struct hci_conn *conn, struct sk_buff *skb, __u16 flags);
+ int (*recv_acldata) (struct hci_conn *conn, struct sk_buff *skb,
+ __u16 flags);
int (*recv_scodata) (struct hci_conn *conn, struct sk_buff *skb);
- int (*security_cfm) (struct hci_conn *conn, __u8 status, __u8 encrypt);
+ int (*security_cfm) (struct hci_conn *conn, __u8 status,
+ __u8 encrypt);
};
-static inline int hci_proto_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 type)
+static inline int hci_proto_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr,
+ __u8 type)
{
register struct hci_proto *hp;
int mask = 0;
@@ -656,7 +687,8 @@
conn->security_cfm_cb(conn, status);
}
-static inline void hci_proto_encrypt_cfm(struct hci_conn *conn, __u8 status, __u8 encrypt)
+static inline void hci_proto_encrypt_cfm(struct hci_conn *conn, __u8 status,
+ __u8 encrypt)
{
register struct hci_proto *hp;
@@ -681,7 +713,8 @@
char *name;
- void (*security_cfm) (struct hci_conn *conn, __u8 status, __u8 encrypt);
+ void (*security_cfm) (struct hci_conn *conn, __u8 status,
+ __u8 encrypt);
void (*key_change_cfm) (struct hci_conn *conn, __u8 status);
void (*role_switch_cfm) (struct hci_conn *conn, __u8 status, __u8 role);
};
@@ -707,13 +740,17 @@
read_unlock_bh(&hci_cb_list_lock);
}
-static inline void hci_encrypt_cfm(struct hci_conn *conn, __u8 status, __u8 encrypt)
+static inline void hci_encrypt_cfm(struct hci_conn *conn, __u8 status,
+ __u8 encrypt)
{
struct list_head *p;
if (conn->sec_level == BT_SECURITY_SDP)
conn->sec_level = BT_SECURITY_LOW;
+ if (conn->pending_sec_level > conn->sec_level)
+ conn->sec_level = conn->pending_sec_level;
+
hci_proto_encrypt_cfm(conn, status, encrypt);
read_lock_bh(&hci_cb_list_lock);
@@ -738,7 +775,8 @@
read_unlock_bh(&hci_cb_list_lock);
}
-static inline void hci_role_switch_cfm(struct hci_conn *conn, __u8 status, __u8 role)
+static inline void hci_role_switch_cfm(struct hci_conn *conn, __u8 status,
+ __u8 role)
{
struct list_head *p;
@@ -830,4 +868,9 @@
void hci_le_conn_update(struct hci_conn *conn, u16 min, u16 max,
u16 latency, u16 to_multiplier);
+void hci_le_start_enc(struct hci_conn *conn, __le16 ediv, __u8 rand[8],
+ __u8 ltk[16]);
+void hci_le_ltk_reply(struct hci_conn *conn, u8 ltk[16]);
+void hci_le_ltk_neg_reply(struct hci_conn *conn);
+
#endif /* __HCI_CORE_H */
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index d09c9b1..9c18e55 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -287,6 +287,10 @@
struct l2cap_conn *conn;
+ __u8 state;
+
+ atomic_t refcnt;
+
__le16 psm;
__u16 dcid;
__u16 scid;
@@ -295,6 +299,7 @@
__u16 omtu;
__u16 flush_to;
__u8 mode;
+ __u8 chan_type;
__le16 sport;
@@ -302,6 +307,7 @@
__u8 role_switch;
__u8 force_reliable;
__u8 flushable;
+ __u8 force_active;
__u8 ident;
@@ -318,8 +324,8 @@
__u16 monitor_timeout;
__u16 mps;
- __u8 conf_state;
- __u16 conn_state;
+ unsigned long conf_state;
+ unsigned long conn_state;
__u8 next_tx_seq;
__u8 expected_ack_seq;
@@ -339,6 +345,7 @@
__u8 remote_max_tx;
__u16 remote_mps;
+ struct timer_list chan_timer;
struct timer_list retrans_timer;
struct timer_list monitor_timer;
struct timer_list ack_timer;
@@ -351,6 +358,18 @@
struct list_head list;
struct list_head global_l;
+
+ void *data;
+ struct l2cap_ops *ops;
+};
+
+struct l2cap_ops {
+ char *name;
+
+ struct l2cap_chan *(*new_connection) (void *data);
+ int (*recv) (void *data, struct sk_buff *skb);
+ void (*close) (void *data);
+ void (*state_change) (void *data, int state);
};
struct l2cap_conn {
@@ -376,6 +395,15 @@
__u8 disc_reason;
+ __u8 preq[7]; /* SMP Pairing Request */
+ __u8 prsp[7]; /* SMP Pairing Response */
+ __u8 prnd[16]; /* SMP Pairing Random */
+ __u8 pcnf[16]; /* SMP Pairing Confirm */
+ __u8 tk[16]; /* SMP Temporary Key */
+ __u8 smp_key_size;
+
+ struct timer_list security_timer;
+
struct list_head chan_l;
rwlock_t chan_lock;
};
@@ -384,6 +412,10 @@
#define L2CAP_INFO_FEAT_MASK_REQ_SENT 0x04
#define L2CAP_INFO_FEAT_MASK_REQ_DONE 0x08
+#define L2CAP_CHAN_RAW 1
+#define L2CAP_CHAN_CONN_LESS 2
+#define L2CAP_CHAN_CONN_ORIENTED 3
+
/* ----- L2CAP socket info ----- */
#define l2cap_pi(sk) ((struct l2cap_pinfo *) sk)
@@ -392,36 +424,45 @@
struct l2cap_chan *chan;
};
-#define L2CAP_CONF_REQ_SENT 0x01
-#define L2CAP_CONF_INPUT_DONE 0x02
-#define L2CAP_CONF_OUTPUT_DONE 0x04
-#define L2CAP_CONF_MTU_DONE 0x08
-#define L2CAP_CONF_MODE_DONE 0x10
-#define L2CAP_CONF_CONNECT_PEND 0x20
-#define L2CAP_CONF_NO_FCS_RECV 0x40
-#define L2CAP_CONF_STATE2_DEVICE 0x80
+enum {
+ CONF_REQ_SENT,
+ CONF_INPUT_DONE,
+ CONF_OUTPUT_DONE,
+ CONF_MTU_DONE,
+ CONF_MODE_DONE,
+ CONF_CONNECT_PEND,
+ CONF_NO_FCS_RECV,
+ CONF_STATE2_DEVICE,
+};
#define L2CAP_CONF_MAX_CONF_REQ 2
#define L2CAP_CONF_MAX_CONF_RSP 2
-#define L2CAP_CONN_SAR_SDU 0x0001
-#define L2CAP_CONN_SREJ_SENT 0x0002
-#define L2CAP_CONN_WAIT_F 0x0004
-#define L2CAP_CONN_SREJ_ACT 0x0008
-#define L2CAP_CONN_SEND_PBIT 0x0010
-#define L2CAP_CONN_REMOTE_BUSY 0x0020
-#define L2CAP_CONN_LOCAL_BUSY 0x0040
-#define L2CAP_CONN_REJ_ACT 0x0080
-#define L2CAP_CONN_SEND_FBIT 0x0100
-#define L2CAP_CONN_RNR_SENT 0x0200
-#define L2CAP_CONN_SAR_RETRY 0x0400
+enum {
+ CONN_SAR_SDU,
+ CONN_SREJ_SENT,
+ CONN_WAIT_F,
+ CONN_SREJ_ACT,
+ CONN_SEND_PBIT,
+ CONN_REMOTE_BUSY,
+ CONN_LOCAL_BUSY,
+ CONN_REJ_ACT,
+ CONN_SEND_FBIT,
+ CONN_RNR_SENT,
+ CONN_SAR_RETRY,
+};
-#define __mod_retrans_timer() mod_timer(&chan->retrans_timer, \
- jiffies + msecs_to_jiffies(L2CAP_DEFAULT_RETRANS_TO));
-#define __mod_monitor_timer() mod_timer(&chan->monitor_timer, \
- jiffies + msecs_to_jiffies(L2CAP_DEFAULT_MONITOR_TO));
-#define __mod_ack_timer() mod_timer(&chan->ack_timer, \
- jiffies + msecs_to_jiffies(L2CAP_DEFAULT_ACK_TO));
+#define __set_chan_timer(c, t) l2cap_set_timer(c, &c->chan_timer, (t))
+#define __clear_chan_timer(c) l2cap_clear_timer(c, &c->chan_timer)
+#define __set_retrans_timer(c) l2cap_set_timer(c, &c->retrans_timer, \
+ L2CAP_DEFAULT_RETRANS_TO);
+#define __clear_retrans_timer(c) l2cap_clear_timer(c, &c->retrans_timer)
+#define __set_monitor_timer(c) l2cap_set_timer(c, &c->monitor_timer, \
+ L2CAP_DEFAULT_MONITOR_TO);
+#define __clear_monitor_timer(c) l2cap_clear_timer(c, &c->monitor_timer)
+#define __set_ack_timer(c) l2cap_set_timer(c, &chan->ack_timer, \
+ L2CAP_DEFAULT_ACK_TO);
+#define __clear_ack_timer(c) l2cap_clear_timer(c, &c->ack_timer)
static inline int l2cap_tx_window_full(struct l2cap_chan *ch)
{
@@ -446,32 +487,16 @@
int l2cap_init_sockets(void);
void l2cap_cleanup_sockets(void);
-void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data);
void __l2cap_connect_rsp_defer(struct l2cap_chan *chan);
int __l2cap_wait_ack(struct sock *sk);
-struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len);
-struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len);
-struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len, u16 control, u16 sdulen);
-int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len);
-void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb);
-void l2cap_streaming_send(struct l2cap_chan *chan);
-int l2cap_ertm_send(struct l2cap_chan *chan);
-
int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm);
int l2cap_add_scid(struct l2cap_chan *chan, __u16 scid);
-void l2cap_sock_set_timer(struct sock *sk, long timeout);
-void l2cap_sock_clear_timer(struct sock *sk);
-void __l2cap_sock_close(struct sock *sk, int reason);
-void l2cap_sock_kill(struct sock *sk);
-void l2cap_sock_init(struct sock *sk, struct sock *parent);
-struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock,
- int proto, gfp_t prio);
-void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err);
struct l2cap_chan *l2cap_chan_create(struct sock *sk);
-void l2cap_chan_del(struct l2cap_chan *chan, int err);
+void l2cap_chan_close(struct l2cap_chan *chan, int reason);
void l2cap_chan_destroy(struct l2cap_chan *chan);
int l2cap_chan_connect(struct l2cap_chan *chan);
+int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len);
#endif /* __L2CAP_H */
diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h
index 4899286..45bea25 100644
--- a/include/net/bluetooth/mgmt.h
+++ b/include/net/bluetooth/mgmt.h
@@ -199,6 +199,16 @@
#define MGMT_OP_STOP_DISCOVERY 0x001C
+#define MGMT_OP_BLOCK_DEVICE 0x001D
+struct mgmt_cp_block_device {
+ bdaddr_t bdaddr;
+} __packed;
+
+#define MGMT_OP_UNBLOCK_DEVICE 0x001E
+struct mgmt_cp_unblock_device {
+ bdaddr_t bdaddr;
+} __packed;
+
#define MGMT_EV_CMD_COMPLETE 0x0001
struct mgmt_ev_cmd_complete {
__le16 opcode;
diff --git a/include/net/bluetooth/rfcomm.h b/include/net/bluetooth/rfcomm.h
index 6eac4a7..d5eee20 100644
--- a/include/net/bluetooth/rfcomm.h
+++ b/include/net/bluetooth/rfcomm.h
@@ -234,7 +234,8 @@
/* ---- RFCOMM DLCs (channels) ---- */
struct rfcomm_dlc *rfcomm_dlc_alloc(gfp_t prio);
void rfcomm_dlc_free(struct rfcomm_dlc *d);
-int rfcomm_dlc_open(struct rfcomm_dlc *d, bdaddr_t *src, bdaddr_t *dst, u8 channel);
+int rfcomm_dlc_open(struct rfcomm_dlc *d, bdaddr_t *src, bdaddr_t *dst,
+ u8 channel);
int rfcomm_dlc_close(struct rfcomm_dlc *d, int reason);
int rfcomm_dlc_send(struct rfcomm_dlc *d, struct sk_buff *skb);
int rfcomm_dlc_set_modem_status(struct rfcomm_dlc *d, u8 v24_sig);
@@ -271,7 +272,8 @@
}
/* ---- RFCOMM sessions ---- */
-void rfcomm_session_getaddr(struct rfcomm_session *s, bdaddr_t *src, bdaddr_t *dst);
+void rfcomm_session_getaddr(struct rfcomm_session *s, bdaddr_t *src,
+ bdaddr_t *dst);
static inline void rfcomm_session_hold(struct rfcomm_session *s)
{
@@ -312,7 +314,8 @@
int rfcomm_init_sockets(void);
void rfcomm_cleanup_sockets(void);
-int rfcomm_connect_ind(struct rfcomm_session *s, u8 channel, struct rfcomm_dlc **d);
+int rfcomm_connect_ind(struct rfcomm_session *s, u8 channel,
+ struct rfcomm_dlc **d);
/* ---- RFCOMM TTY ---- */
#define RFCOMM_MAX_DEV 256
diff --git a/include/net/bluetooth/smp.h b/include/net/bluetooth/smp.h
index 8f2edbf..4fb7d19 100644
--- a/include/net/bluetooth/smp.h
+++ b/include/net/bluetooth/smp.h
@@ -1,3 +1,25 @@
+/*
+ BlueZ - Bluetooth protocol stack for Linux
+ Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+
+ 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;
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
+ IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
+ CLAIM, OR ANY SPECIAL 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.
+
+ ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
+ COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
+ SOFTWARE IS DISCLAIMED.
+*/
+
#ifndef __SMP_H
#define __SMP_H
@@ -16,6 +38,23 @@
__u8 resp_key_dist;
} __packed;
+#define SMP_IO_DISPLAY_ONLY 0x00
+#define SMP_IO_DISPLAY_YESNO 0x01
+#define SMP_IO_KEYBOARD_ONLY 0x02
+#define SMP_IO_NO_INPUT_OUTPUT 0x03
+#define SMP_IO_KEYBOARD_DISPLAY 0x04
+
+#define SMP_OOB_NOT_PRESENT 0x00
+#define SMP_OOB_PRESENT 0x01
+
+#define SMP_DIST_ENC_KEY 0x01
+#define SMP_DIST_ID_KEY 0x02
+#define SMP_DIST_SIGN 0x04
+
+#define SMP_AUTH_NONE 0x00
+#define SMP_AUTH_BONDING 0x01
+#define SMP_AUTH_MITM 0x04
+
#define SMP_CMD_PAIRING_CONFIRM 0x03
struct smp_cmd_pairing_confirm {
__u8 confirm_val[16];
@@ -73,4 +112,11 @@
#define SMP_UNSPECIFIED 0x08
#define SMP_REPEATED_ATTEMPTS 0x09
+#define SMP_MIN_ENC_KEY_SIZE 7
+#define SMP_MAX_ENC_KEY_SIZE 16
+
+/* SMP Commands */
+int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level);
+int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb);
+
#endif /* __SMP_H */
diff --git a/include/net/caif/caif_hsi.h b/include/net/caif/caif_hsi.h
new file mode 100644
index 0000000..c5dedd8
--- /dev/null
+++ b/include/net/caif/caif_hsi.h
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) ST-Ericsson AB 2010
+ * Contact: Sjur Brendeland / sjur.brandeland@stericsson.com
+ * Author: Daniel Martensson / daniel.martensson@stericsson.com
+ * Dmitry.Tarnyagin / dmitry.tarnyagin@stericsson.com
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#ifndef CAIF_HSI_H_
+#define CAIF_HSI_H_
+
+#include <net/caif/caif_layer.h>
+#include <net/caif/caif_device.h>
+#include <linux/atomic.h>
+
+/*
+ * Maximum number of CAIF frames that can reside in the same HSI frame.
+ */
+#define CFHSI_MAX_PKTS 15
+
+/*
+ * Maximum number of bytes used for the frame that can be embedded in the
+ * HSI descriptor.
+ */
+#define CFHSI_MAX_EMB_FRM_SZ 96
+
+/*
+ * Decides if HSI buffers should be prefilled with 0xFF pattern for easier
+ * debugging. Both TX and RX buffers will be filled before the transfer.
+ */
+#define CFHSI_DBG_PREFILL 0
+
+/* Structure describing a HSI packet descriptor. */
+#pragma pack(1) /* Byte alignment. */
+struct cfhsi_desc {
+ u8 header;
+ u8 offset;
+ u16 cffrm_len[CFHSI_MAX_PKTS];
+ u8 emb_frm[CFHSI_MAX_EMB_FRM_SZ];
+};
+#pragma pack() /* Default alignment. */
+
+/* Size of the complete HSI packet descriptor. */
+#define CFHSI_DESC_SZ (sizeof(struct cfhsi_desc))
+
+/*
+ * Size of the complete HSI packet descriptor excluding the optional embedded
+ * CAIF frame.
+ */
+#define CFHSI_DESC_SHORT_SZ (CFHSI_DESC_SZ - CFHSI_MAX_EMB_FRM_SZ)
+
+/*
+ * Maximum bytes transferred in one transfer.
+ */
+/* TODO: 4096 is temporary... */
+#define CFHSI_MAX_PAYLOAD_SZ (CFHSI_MAX_PKTS * 4096)
+
+/* Size of the complete HSI TX buffer. */
+#define CFHSI_BUF_SZ_TX (CFHSI_DESC_SZ + CFHSI_MAX_PAYLOAD_SZ)
+
+/* Size of the complete HSI RX buffer. */
+#define CFHSI_BUF_SZ_RX ((2 * CFHSI_DESC_SZ) + CFHSI_MAX_PAYLOAD_SZ)
+
+/* Bitmasks for the HSI descriptor. */
+#define CFHSI_PIGGY_DESC (0x01 << 7)
+
+#define CFHSI_TX_STATE_IDLE 0
+#define CFHSI_TX_STATE_XFER 1
+
+#define CFHSI_RX_STATE_DESC 0
+#define CFHSI_RX_STATE_PAYLOAD 1
+
+/* Bitmasks for power management. */
+#define CFHSI_WAKE_UP 0
+#define CFHSI_WAKE_UP_ACK 1
+#define CFHSI_WAKE_DOWN_ACK 2
+#define CFHSI_AWAKE 3
+#define CFHSI_PENDING_RX 4
+#define CFHSI_SHUTDOWN 6
+#define CFHSI_FLUSH_FIFO 7
+
+#ifndef CFHSI_INACTIVITY_TOUT
+#define CFHSI_INACTIVITY_TOUT (1 * HZ)
+#endif /* CFHSI_INACTIVITY_TOUT */
+
+#ifndef CFHSI_WAKEUP_TOUT
+#define CFHSI_WAKEUP_TOUT (3 * HZ)
+#endif /* CFHSI_WAKEUP_TOUT */
+
+
+/* Structure implemented by the CAIF HSI driver. */
+struct cfhsi_drv {
+ void (*tx_done_cb) (struct cfhsi_drv *drv);
+ void (*rx_done_cb) (struct cfhsi_drv *drv);
+ void (*wake_up_cb) (struct cfhsi_drv *drv);
+ void (*wake_down_cb) (struct cfhsi_drv *drv);
+};
+
+/* Structure implemented by HSI device. */
+struct cfhsi_dev {
+ int (*cfhsi_up) (struct cfhsi_dev *dev);
+ int (*cfhsi_down) (struct cfhsi_dev *dev);
+ int (*cfhsi_tx) (u8 *ptr, int len, struct cfhsi_dev *dev);
+ int (*cfhsi_rx) (u8 *ptr, int len, struct cfhsi_dev *dev);
+ int (*cfhsi_wake_up) (struct cfhsi_dev *dev);
+ int (*cfhsi_wake_down) (struct cfhsi_dev *dev);
+ int (*cfhsi_fifo_occupancy)(struct cfhsi_dev *dev, size_t *occupancy);
+ int (*cfhsi_rx_cancel)(struct cfhsi_dev *dev);
+ struct cfhsi_drv *drv;
+};
+
+/* Structure implemented by CAIF HSI drivers. */
+struct cfhsi {
+ struct caif_dev_common cfdev;
+ struct net_device *ndev;
+ struct platform_device *pdev;
+ struct sk_buff_head qhead;
+ struct cfhsi_drv drv;
+ struct cfhsi_dev *dev;
+ int tx_state;
+ int rx_state;
+ int rx_len;
+ u8 *rx_ptr;
+ u8 *tx_buf;
+ u8 *rx_buf;
+ spinlock_t lock;
+ int flow_off_sent;
+ u32 q_low_mark;
+ u32 q_high_mark;
+ struct list_head list;
+ struct work_struct wake_up_work;
+ struct work_struct wake_down_work;
+ struct work_struct rx_done_work;
+ struct work_struct tx_done_work;
+ struct workqueue_struct *wq;
+ wait_queue_head_t wake_up_wait;
+ wait_queue_head_t wake_down_wait;
+ wait_queue_head_t flush_fifo_wait;
+ struct timer_list timer;
+ unsigned long bits;
+};
+
+extern struct platform_driver cfhsi_driver;
+
+#endif /* CAIF_HSI_H_ */
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 396e8fc..7202bce 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -1284,6 +1284,12 @@
* frame on another channel
*
* @testmode_cmd: run a test mode command
+ * @testmode_dump: Implement a test mode dump. The cb->args[2] and up may be
+ * used by the function, but 0 and 1 must not be touched. Additionally,
+ * return error codes other than -ENOBUFS and -ENOENT will terminate the
+ * dump and return to userspace with an error, so be careful. If any data
+ * was passed in from userspace then the data/len arguments will be present
+ * and point to the data contained in %NL80211_ATTR_TESTDATA.
*
* @set_bitrate_mask: set the bitrate mask configuration
*
@@ -1433,6 +1439,9 @@
#ifdef CONFIG_NL80211_TESTMODE
int (*testmode_cmd)(struct wiphy *wiphy, void *data, int len);
+ int (*testmode_dump)(struct wiphy *wiphy, struct sk_buff *skb,
+ struct netlink_callback *cb,
+ void *data, int len);
#endif
int (*set_bitrate_mask)(struct wiphy *wiphy,
@@ -2849,8 +2858,10 @@
void cfg80211_testmode_event(struct sk_buff *skb, gfp_t gfp);
#define CFG80211_TESTMODE_CMD(cmd) .testmode_cmd = (cmd),
+#define CFG80211_TESTMODE_DUMP(cmd) .testmode_dump = (cmd),
#else
#define CFG80211_TESTMODE_CMD(cmd)
+#define CFG80211_TESTMODE_DUMP(cmd)
#endif
/**
diff --git a/include/net/dcbnl.h b/include/net/dcbnl.h
index e5983c9..d5bbb79 100644
--- a/include/net/dcbnl.h
+++ b/include/net/dcbnl.h
@@ -28,8 +28,13 @@
struct list_head list;
};
-u8 dcb_setapp(struct net_device *, struct dcb_app *);
+int dcb_setapp(struct net_device *, struct dcb_app *);
u8 dcb_getapp(struct net_device *, struct dcb_app *);
+int dcb_ieee_setapp(struct net_device *, struct dcb_app *);
+int dcb_ieee_delapp(struct net_device *, struct dcb_app *);
+u8 dcb_ieee_getapp_mask(struct net_device *, struct dcb_app *);
+
+int dcbnl_notify(struct net_device *dev, int event, int cmd, u32 seq, u32 pid);
/*
* Ops struct for the netlink callbacks. Used by DCB-enabled drivers through
@@ -43,6 +48,7 @@
int (*ieee_setpfc) (struct net_device *, struct ieee_pfc *);
int (*ieee_getapp) (struct net_device *, struct dcb_app *);
int (*ieee_setapp) (struct net_device *, struct dcb_app *);
+ int (*ieee_delapp) (struct net_device *, struct dcb_app *);
int (*ieee_peer_getets) (struct net_device *, struct ieee_ets *);
int (*ieee_peer_getpfc) (struct net_device *, struct ieee_pfc *);
diff --git a/include/net/genetlink.h b/include/net/genetlink.h
index d420f28..82d8d09 100644
--- a/include/net/genetlink.h
+++ b/include/net/genetlink.h
@@ -160,6 +160,38 @@
}
/**
+ * genlmsg_nlhdr - Obtain netlink header from user specified header
+ * @user_hdr: user header as returned from genlmsg_put()
+ * @family: generic netlink family
+ *
+ * Returns pointer to netlink header.
+ */
+static inline struct nlmsghdr *genlmsg_nlhdr(void *user_hdr,
+ struct genl_family *family)
+{
+ return (struct nlmsghdr *)((char *)user_hdr -
+ family->hdrsize -
+ GENL_HDRLEN -
+ NLMSG_HDRLEN);
+}
+
+/**
+ * genl_dump_check_consistent - check if sequence is consistent and advertise if not
+ * @cb: netlink callback structure that stores the sequence number
+ * @user_hdr: user header as returned from genlmsg_put()
+ * @family: generic netlink family
+ *
+ * Cf. nl_dump_check_consistent(), this just provides a wrapper to make it
+ * simpler to use with generic netlink.
+ */
+static inline void genl_dump_check_consistent(struct netlink_callback *cb,
+ void *user_hdr,
+ struct genl_family *family)
+{
+ nl_dump_check_consistent(cb, genlmsg_nlhdr(user_hdr, family));
+}
+
+/**
* genlmsg_put_reply - Add generic netlink header to a reply message
* @skb: socket buffer holding the message
* @info: receiver info
diff --git a/include/net/inetpeer.h b/include/net/inetpeer.h
index 8a159cc..39d1230 100644
--- a/include/net/inetpeer.h
+++ b/include/net/inetpeer.h
@@ -32,13 +32,17 @@
struct inet_peer __rcu *avl_left, *avl_right;
struct inetpeer_addr daddr;
__u32 avl_height;
- struct list_head unused;
- __u32 dtime; /* the time of last use of not
- * referenced entries */
- atomic_t refcnt;
+
+ 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;
/*
* Once inet_peer is queued for deletion (refcnt == -1), following fields
- * are not available: rid, ip_id_count, tcp_ts, tcp_ts_stamp, metrics
+ * 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 {
@@ -47,16 +51,14 @@
atomic_t ip_id_count; /* IP ID for the next packet */
__u32 tcp_ts;
__u32 tcp_ts_stamp;
- 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;
};
struct rcu_head rcu;
+ struct inet_peer *gc_next;
};
+
+ /* following fields might be frequently dirtied */
+ __u32 dtime; /* the time of last use of not referenced entries */
+ atomic_t refcnt;
};
void inet_initpeers(void) __init;
diff --git a/include/net/ip.h b/include/net/ip.h
index 66dd491..aa76c7a 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h
@@ -228,8 +228,6 @@
extern int inet_peer_threshold;
extern int inet_peer_minttl;
extern int inet_peer_maxttl;
-extern int inet_peer_gc_mintime;
-extern int inet_peer_gc_maxtime;
/* From ip_output.c */
extern int sysctl_ip_dynaddr;
@@ -238,6 +236,11 @@
extern void ip_static_sysctl_init(void);
+static inline bool ip_is_fragment(const struct iphdr *iph)
+{
+ return (iph->frag_off & htons(IP_MF | IP_OFFSET)) != 0;
+}
+
#ifdef CONFIG_INET
#include <net/dst.h>
@@ -401,7 +404,8 @@
__IP_DEFRAG_CONNTRACK_BRIDGE_IN = IP_DEFRAG_CONNTRACK_BRIDGE_IN + USHRT_MAX,
IP_DEFRAG_VS_IN,
IP_DEFRAG_VS_OUT,
- IP_DEFRAG_VS_FWD
+ IP_DEFRAG_VS_FWD,
+ IP_DEFRAG_AF_PACKET,
};
int ip_defrag(struct sk_buff *skb, u32 user);
diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h
index 481f856..b1370c4 100644
--- a/include/net/ip_vs.h
+++ b/include/net/ip_vs.h
@@ -836,8 +836,6 @@
int num_services; /* no of virtual services */
rwlock_t rs_lock; /* real services table */
- /* semaphore for IPVS sockopts. And, [gs]etsockopt may sleep. */
- struct lock_class_key ctl_key; /* ctl_mutex debuging */
/* Trash for destinations */
struct list_head dest_trash;
/* Service counters */
@@ -1089,19 +1087,19 @@
/*
* IPVS netns init & cleanup functions
*/
-extern int __ip_vs_estimator_init(struct net *net);
-extern int __ip_vs_control_init(struct net *net);
-extern int __ip_vs_protocol_init(struct net *net);
-extern int __ip_vs_app_init(struct net *net);
-extern int __ip_vs_conn_init(struct net *net);
-extern int __ip_vs_sync_init(struct net *net);
-extern void __ip_vs_conn_cleanup(struct net *net);
-extern void __ip_vs_app_cleanup(struct net *net);
-extern void __ip_vs_protocol_cleanup(struct net *net);
-extern void __ip_vs_control_cleanup(struct net *net);
-extern void __ip_vs_estimator_cleanup(struct net *net);
-extern void __ip_vs_sync_cleanup(struct net *net);
-extern void __ip_vs_service_cleanup(struct net *net);
+extern int ip_vs_estimator_net_init(struct net *net);
+extern int ip_vs_control_net_init(struct net *net);
+extern int ip_vs_protocol_net_init(struct net *net);
+extern int ip_vs_app_net_init(struct net *net);
+extern int ip_vs_conn_net_init(struct net *net);
+extern int ip_vs_sync_net_init(struct net *net);
+extern void ip_vs_conn_net_cleanup(struct net *net);
+extern void ip_vs_app_net_cleanup(struct net *net);
+extern void ip_vs_protocol_net_cleanup(struct net *net);
+extern void ip_vs_control_net_cleanup(struct net *net);
+extern void ip_vs_estimator_net_cleanup(struct net *net);
+extern void ip_vs_sync_net_cleanup(struct net *net);
+extern void ip_vs_service_net_cleanup(struct net *net);
/*
* IPVS application functions
@@ -1119,8 +1117,6 @@
extern int ip_vs_app_pkt_out(struct ip_vs_conn *, struct sk_buff *skb);
extern int ip_vs_app_pkt_in(struct ip_vs_conn *, struct sk_buff *skb);
-extern int ip_vs_app_init(void);
-extern void ip_vs_app_cleanup(void);
void ip_vs_bind_pe(struct ip_vs_service *svc, struct ip_vs_pe *pe);
void ip_vs_unbind_pe(struct ip_vs_service *svc);
@@ -1223,15 +1219,11 @@
__u8 syncid);
extern int stop_sync_thread(struct net *net, int state);
extern void ip_vs_sync_conn(struct net *net, struct ip_vs_conn *cp);
-extern int ip_vs_sync_init(void);
-extern void ip_vs_sync_cleanup(void);
/*
* IPVS rate estimator prototypes (from ip_vs_est.c)
*/
-extern int ip_vs_estimator_init(void);
-extern void ip_vs_estimator_cleanup(void);
extern void ip_vs_start_estimator(struct net *net, struct ip_vs_stats *stats);
extern void ip_vs_stop_estimator(struct net *net, struct ip_vs_stats *stats);
extern void ip_vs_zero_estimator(struct ip_vs_stats *stats);
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index e6d6a66..c9def42 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -933,6 +933,7 @@
* @aid: AID we assigned to the station if we're an AP
* @supp_rates: Bitmap of supported rates (per band)
* @ht_cap: HT capabilities of this STA; restricted to our own TX capabilities
+ * @wme: indicates whether the STA supports WME. Only valid during AP-mode.
* @drv_priv: data area for driver use, will always be aligned to
* sizeof(void *), size is determined in hw information.
*/
@@ -941,6 +942,7 @@
u8 addr[ETH_ALEN];
u16 aid;
struct ieee80211_sta_ht_cap ht_cap;
+ bool wme;
/* must be last */
u8 drv_priv[0] __attribute__((__aligned__(sizeof(void *))));
@@ -1708,6 +1710,14 @@
* any error unless this callback returned a negative error code.
* The callback can sleep.
*
+ * @cancel_hw_scan: Ask the low-level tp cancel the active hw scan.
+ * The driver should ask the hardware to cancel the scan (if possible),
+ * but the scan will be completed only after the driver will call
+ * ieee80211_scan_completed().
+ * This callback is needed for wowlan, to prevent enqueueing a new
+ * scan_work after the low-level driver was already suspended.
+ * The callback can sleep.
+ *
* @sched_scan_start: Ask the hardware to start scanning repeatedly at
* specific intervals. The driver must call the
* ieee80211_sched_scan_results() function whenever it finds results.
@@ -1816,6 +1826,7 @@
*
* @testmode_cmd: Implement a cfg80211 test mode command.
* The callback can sleep.
+ * @testmode_dump: Implement a cfg80211 test mode dump. The callback can sleep.
*
* @flush: Flush all pending frames from the hardware queue, making sure
* that the hardware queues are empty. If the parameter @drop is set
@@ -1899,6 +1910,8 @@
u32 iv32, u16 *phase1key);
int (*hw_scan)(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct cfg80211_scan_request *req);
+ void (*cancel_hw_scan)(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif);
int (*sched_scan_start)(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct cfg80211_sched_scan_request *req,
@@ -1936,6 +1949,9 @@
void (*set_coverage_class)(struct ieee80211_hw *hw, u8 coverage_class);
#ifdef CONFIG_NL80211_TESTMODE
int (*testmode_cmd)(struct ieee80211_hw *hw, void *data, int len);
+ int (*testmode_dump)(struct ieee80211_hw *hw, struct sk_buff *skb,
+ struct netlink_callback *cb,
+ void *data, int len);
#endif
void (*flush)(struct ieee80211_hw *hw, bool drop);
void (*channel_switch)(struct ieee80211_hw *hw,
@@ -2916,6 +2932,16 @@
gfp_t gfp);
/**
+ * ieee80211_get_operstate - get the operstate of the vif
+ *
+ * @vif: &struct ieee80211_vif pointer from the add_interface callback.
+ *
+ * The driver might need to know the operstate of the net_device
+ * (specifically, whether the link is IF_OPER_UP after resume)
+ */
+unsigned char ieee80211_get_operstate(struct ieee80211_vif *vif);
+
+/**
* ieee80211_chswitch_done - Complete channel switch process
* @vif: &struct ieee80211_vif pointer from the add_interface callback.
* @success: make the channel switch successful or not
@@ -2965,6 +2991,23 @@
*/
void ieee80211_remain_on_channel_expired(struct ieee80211_hw *hw);
+/**
+ * ieee80211_stop_rx_ba_session - callback to stop existing BA sessions
+ *
+ * in order not to harm the system performance and user experience, the device
+ * may request not to allow any rx ba session and tear down existing rx ba
+ * sessions based on system constraints such as periodic BT activity that needs
+ * to limit wlan activity (eg.sco or a2dp)."
+ * in such cases, the intention is to limit the duration of the rx ppdu and
+ * therefore prevent the peer device to use a-mpdu aggregation.
+ *
+ * @vif: &struct ieee80211_vif pointer from the add_interface callback.
+ * @ba_rx_bitmap: Bit map of open rx ba per tid
+ * @addr: & to bssid mac address
+ */
+void ieee80211_stop_rx_ba_session(struct ieee80211_vif *vif, u16 ba_rx_bitmap,
+ const u8 *addr);
+
/* Rate control API */
/**
diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
index aef430d..1ab1aec 100644
--- a/include/net/net_namespace.h
+++ b/include/net/net_namespace.h
@@ -65,6 +65,7 @@
struct list_head dev_base_head;
struct hlist_head *dev_name_head;
struct hlist_head *dev_index_head;
+ unsigned int dev_base_seq; /* protected by rtnl_mutex */
/* core fib_rules */
struct list_head rules_ops;
diff --git a/include/net/netlink.h b/include/net/netlink.h
index 02740a9..98c1854 100644
--- a/include/net/netlink.h
+++ b/include/net/netlink.h
@@ -638,6 +638,30 @@
nlmsg_ok(pos, rem); \
pos = nlmsg_next(pos, &(rem)))
+/**
+ * nl_dump_check_consistent - check if sequence is consistent and advertise if not
+ * @cb: netlink callback structure that stores the sequence number
+ * @nlh: netlink message header to write the flag to
+ *
+ * This function checks if the sequence (generation) number changed during dump
+ * and if it did, advertises it in the netlink message header.
+ *
+ * The correct way to use it is to set cb->seq to the generation counter when
+ * all locks for dumping have been acquired, and then call this function for
+ * each message that is generated.
+ *
+ * Note that due to initialisation concerns, 0 is an invalid sequence number
+ * and must not be used by code that uses this functionality.
+ */
+static inline void
+nl_dump_check_consistent(struct netlink_callback *cb,
+ struct nlmsghdr *nlh)
+{
+ if (cb->prev_seq && cb->seq != cb->prev_seq)
+ nlh->nlmsg_flags |= NLM_F_DUMP_INTR;
+ cb->prev_seq = cb->seq;
+}
+
/**************************************************************************
* Netlink Attributes
**************************************************************************/
diff --git a/include/net/rtnetlink.h b/include/net/rtnetlink.h
index 4093ca7..678f1ff 100644
--- a/include/net/rtnetlink.h
+++ b/include/net/rtnetlink.h
@@ -6,11 +6,14 @@
typedef int (*rtnl_doit_func)(struct sk_buff *, struct nlmsghdr *, void *);
typedef int (*rtnl_dumpit_func)(struct sk_buff *, struct netlink_callback *);
+typedef u16 (*rtnl_calcit_func)(struct sk_buff *);
extern int __rtnl_register(int protocol, int msgtype,
- rtnl_doit_func, rtnl_dumpit_func);
+ rtnl_doit_func, rtnl_dumpit_func,
+ rtnl_calcit_func);
extern void rtnl_register(int protocol, int msgtype,
- rtnl_doit_func, rtnl_dumpit_func);
+ rtnl_doit_func, rtnl_dumpit_func,
+ rtnl_calcit_func);
extern int rtnl_unregister(int protocol, int msgtype);
extern void rtnl_unregister_all(int protocol);
diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
index b2c2366..6a72a58 100644
--- a/include/net/sctp/sctp.h
+++ b/include/net/sctp/sctp.h
@@ -120,6 +120,7 @@
int flags);
extern struct sctp_pf *sctp_get_pf_specific(sa_family_t family);
extern int sctp_register_pf(struct sctp_pf *, sa_family_t);
+extern void sctp_addr_wq_mgmt(struct sctp_sockaddr_entry *, int);
/*
* sctp/socket.c
@@ -134,6 +135,7 @@
void sctp_copy_sock(struct sock *newsk, struct sock *sk,
struct sctp_association *asoc);
extern struct percpu_counter sctp_sockets_allocated;
+extern int sctp_asconf_mgmt(struct sctp_sock *, struct sctp_sockaddr_entry *);
/*
* sctp/primitive.c
@@ -285,20 +287,21 @@
pr_cont(fmt, ##args); \
} while (0)
#define SCTP_DEBUG_PRINTK_IPADDR(fmt_lead, fmt_trail, \
- args_lead, saddr, args_trail...) \
+ args_lead, addr, args_trail...) \
do { \
+ const union sctp_addr *_addr = (addr); \
if (sctp_debug_flag) { \
- if (saddr->sa.sa_family == AF_INET6) { \
+ if (_addr->sa.sa_family == AF_INET6) { \
printk(KERN_DEBUG \
pr_fmt(fmt_lead "%pI6" fmt_trail), \
args_lead, \
- &saddr->v6.sin6_addr, \
+ &_addr->v6.sin6_addr, \
args_trail); \
} else { \
printk(KERN_DEBUG \
pr_fmt(fmt_lead "%pI4" fmt_trail), \
args_lead, \
- &saddr->v4.sin_addr.s_addr, \
+ &_addr->v4.sin_addr.s_addr, \
args_trail); \
} \
} \
@@ -598,7 +601,7 @@
return AF_INET6;
default:
return 0;
- };
+ }
}
/* Convert from an address parameter type to an address family. */
@@ -611,7 +614,7 @@
return AF_INET6;
default:
return 0;
- };
+ }
}
/* Perform some sanity checks. */
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index 7df327a..31d7ea2 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -205,6 +205,11 @@
* It is a list of sctp_sockaddr_entry.
*/
struct list_head local_addr_list;
+ int default_auto_asconf;
+ struct list_head addr_waitq;
+ struct timer_list addr_wq_timer;
+ struct list_head auto_asconf_splist;
+ spinlock_t addr_wq_lock;
/* Lock that protects the local_addr_list writers */
spinlock_t addr_list_lock;
@@ -264,6 +269,11 @@
#define sctp_port_hashtable (sctp_globals.port_hashtable)
#define sctp_local_addr_list (sctp_globals.local_addr_list)
#define sctp_local_addr_lock (sctp_globals.addr_list_lock)
+#define sctp_auto_asconf_splist (sctp_globals.auto_asconf_splist)
+#define sctp_addr_waitq (sctp_globals.addr_waitq)
+#define sctp_addr_wq_timer (sctp_globals.addr_wq_timer)
+#define sctp_addr_wq_lock (sctp_globals.addr_wq_lock)
+#define sctp_default_auto_asconf (sctp_globals.default_auto_asconf)
#define sctp_scope_policy (sctp_globals.ipv4_scope_policy)
#define sctp_addip_enable (sctp_globals.addip_enable)
#define sctp_addip_noauth (sctp_globals.addip_noauth_enable)
@@ -341,6 +351,8 @@
atomic_t pd_mode;
/* Receive to here while partial delivery is in effect. */
struct sk_buff_head pd_lobby;
+ struct list_head auto_asconf_list;
+ int do_auto_asconf;
};
static inline struct sctp_sock *sctp_sk(const struct sock *sk)
@@ -792,6 +804,8 @@
__u8 valid;
};
+#define SCTP_ADDRESS_TICK_DELAY 500
+
typedef struct sctp_chunk *(sctp_packet_phandler_t)(struct sctp_association *);
/* This structure holds lists of chunks as we are assembling for
@@ -1236,6 +1250,7 @@
int sctp_in_scope(const union sctp_addr *addr, const sctp_scope_t scope);
int sctp_is_any(struct sock *sk, const union sctp_addr *addr);
int sctp_addr_is_valid(const union sctp_addr *addr);
+int sctp_is_ep_boundall(struct sock *sk);
/* What type of endpoint? */
@@ -1898,6 +1913,8 @@
* after reaching 4294967295.
*/
__u32 addip_serial;
+ union sctp_addr *asconf_addr_del_pending;
+ int src_out_of_asoc_ok;
/* SCTP AUTH: list of the endpoint shared keys. These
* keys are provided out of band by the user applicaton
diff --git a/include/net/sctp/user.h b/include/net/sctp/user.h
index 32fd512..0842ef0 100644
--- a/include/net/sctp/user.h
+++ b/include/net/sctp/user.h
@@ -92,6 +92,7 @@
#define SCTP_LOCAL_AUTH_CHUNKS 27 /* Read only */
#define SCTP_GET_ASSOC_NUMBER 28 /* Read only */
#define SCTP_GET_ASSOC_ID_LIST 29 /* Read only */
+#define SCTP_AUTO_ASCONF 30
/* Internal Socket Options. Some of the sctp library functions are
* implemented using these socket options.
diff --git a/include/net/snmp.h b/include/net/snmp.h
index 479083a..8f0f9ac 100644
--- a/include/net/snmp.h
+++ b/include/net/snmp.h
@@ -116,57 +116,51 @@
unsigned long mibs[LINUX_MIB_XFRMMAX];
};
-/*
- * FIXME: On x86 and some other CPUs the split into user and softirq parts
- * is not needed because addl $1,memory is atomic against interrupts (but
- * atomic_inc would be overkill because of the lock cycles). Wants new
- * nonlocked_atomic_inc() primitives -AK
- */
+#define SNMP_ARRAY_SZ 1
+
#define DEFINE_SNMP_STAT(type, name) \
- __typeof__(type) __percpu *name[2]
+ __typeof__(type) __percpu *name[SNMP_ARRAY_SZ]
#define DEFINE_SNMP_STAT_ATOMIC(type, name) \
__typeof__(type) *name
#define DECLARE_SNMP_STAT(type, name) \
- extern __typeof__(type) __percpu *name[2]
-
-#define SNMP_STAT_BHPTR(name) (name[0])
-#define SNMP_STAT_USRPTR(name) (name[1])
+ extern __typeof__(type) __percpu *name[SNMP_ARRAY_SZ]
#define SNMP_INC_STATS_BH(mib, field) \
__this_cpu_inc(mib[0]->mibs[field])
+
#define SNMP_INC_STATS_USER(mib, field) \
- this_cpu_inc(mib[1]->mibs[field])
+ irqsafe_cpu_inc(mib[0]->mibs[field])
+
#define SNMP_INC_STATS_ATOMIC_LONG(mib, field) \
atomic_long_inc(&mib->mibs[field])
+
#define SNMP_INC_STATS(mib, field) \
- this_cpu_inc(mib[!in_softirq()]->mibs[field])
+ irqsafe_cpu_inc(mib[0]->mibs[field])
+
#define SNMP_DEC_STATS(mib, field) \
- this_cpu_dec(mib[!in_softirq()]->mibs[field])
+ irqsafe_cpu_dec(mib[0]->mibs[field])
+
#define SNMP_ADD_STATS_BH(mib, field, addend) \
__this_cpu_add(mib[0]->mibs[field], addend)
+
#define SNMP_ADD_STATS_USER(mib, field, addend) \
- this_cpu_add(mib[1]->mibs[field], addend)
+ irqsafe_cpu_add(mib[0]->mibs[field], addend)
+
#define SNMP_ADD_STATS(mib, field, addend) \
- this_cpu_add(mib[!in_softirq()]->mibs[field], addend)
+ irqsafe_cpu_add(mib[0]->mibs[field], addend)
/*
* Use "__typeof__(*mib[0]) *ptr" instead of "__typeof__(mib[0]) ptr"
* to make @ptr a non-percpu pointer.
*/
#define SNMP_UPD_PO_STATS(mib, basefield, addend) \
do { \
- __typeof__(*mib[0]) *ptr; \
- preempt_disable(); \
- ptr = this_cpu_ptr((mib)[!in_softirq()]); \
- ptr->mibs[basefield##PKTS]++; \
- ptr->mibs[basefield##OCTETS] += addend;\
- preempt_enable(); \
+ irqsafe_cpu_inc(mib[0]->mibs[basefield##PKTS]); \
+ irqsafe_cpu_add(mib[0]->mibs[basefield##OCTETS], addend); \
} while (0)
#define SNMP_UPD_PO_STATS_BH(mib, basefield, addend) \
do { \
- __typeof__(*mib[0]) *ptr = \
- __this_cpu_ptr((mib)[0]); \
- ptr->mibs[basefield##PKTS]++; \
- ptr->mibs[basefield##OCTETS] += addend;\
+ __this_cpu_inc(mib[0]->mibs[basefield##PKTS]); \
+ __this_cpu_add(mib[0]->mibs[basefield##OCTETS], addend); \
} while (0)
@@ -179,40 +173,20 @@
ptr->mibs[field] += addend; \
u64_stats_update_end(&ptr->syncp); \
} while (0)
+
#define SNMP_ADD_STATS64_USER(mib, field, addend) \
do { \
- __typeof__(*mib[0]) *ptr; \
- preempt_disable(); \
- ptr = __this_cpu_ptr((mib)[1]); \
- u64_stats_update_begin(&ptr->syncp); \
- ptr->mibs[field] += addend; \
- u64_stats_update_end(&ptr->syncp); \
- preempt_enable(); \
+ local_bh_disable(); \
+ SNMP_ADD_STATS64_BH(mib, field, addend); \
+ local_bh_enable(); \
} while (0)
+
#define SNMP_ADD_STATS64(mib, field, addend) \
- do { \
- __typeof__(*mib[0]) *ptr; \
- preempt_disable(); \
- ptr = __this_cpu_ptr((mib)[!in_softirq()]); \
- u64_stats_update_begin(&ptr->syncp); \
- ptr->mibs[field] += addend; \
- u64_stats_update_end(&ptr->syncp); \
- preempt_enable(); \
- } while (0)
+ SNMP_ADD_STATS64_USER(mib, field, addend)
+
#define SNMP_INC_STATS64_BH(mib, field) SNMP_ADD_STATS64_BH(mib, field, 1)
#define SNMP_INC_STATS64_USER(mib, field) SNMP_ADD_STATS64_USER(mib, field, 1)
#define SNMP_INC_STATS64(mib, field) SNMP_ADD_STATS64(mib, field, 1)
-#define SNMP_UPD_PO_STATS64(mib, basefield, addend) \
- do { \
- __typeof__(*mib[0]) *ptr; \
- preempt_disable(); \
- ptr = __this_cpu_ptr((mib)[!in_softirq()]); \
- u64_stats_update_begin(&ptr->syncp); \
- ptr->mibs[basefield##PKTS]++; \
- ptr->mibs[basefield##OCTETS] += addend; \
- u64_stats_update_end(&ptr->syncp); \
- preempt_enable(); \
- } while (0)
#define SNMP_UPD_PO_STATS64_BH(mib, basefield, addend) \
do { \
__typeof__(*mib[0]) *ptr; \
@@ -222,6 +196,12 @@
ptr->mibs[basefield##OCTETS] += addend; \
u64_stats_update_end(&ptr->syncp); \
} while (0)
+#define SNMP_UPD_PO_STATS64(mib, basefield, addend) \
+ do { \
+ local_bh_disable(); \
+ SNMP_UPD_PO_STATS64_BH(mib, basefield, addend); \
+ local_bh_enable(); \
+ } while (0)
#else
#define SNMP_INC_STATS64_BH(mib, field) SNMP_INC_STATS_BH(mib, field)
#define SNMP_INC_STATS64_USER(mib, field) SNMP_INC_STATS_USER(mib, field)
diff --git a/include/net/sock.h b/include/net/sock.h
index c0b938c..ae56da6 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -40,6 +40,7 @@
#ifndef _SOCK_H
#define _SOCK_H
+#include <linux/hardirq.h>
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/list_nulls.h>
diff --git a/include/net/tcp.h b/include/net/tcp.h
index cda30ea..149a415 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -122,7 +122,13 @@
#endif
#define TCP_RTO_MAX ((unsigned)(120*HZ))
#define TCP_RTO_MIN ((unsigned)(HZ/5))
-#define TCP_TIMEOUT_INIT ((unsigned)(3*HZ)) /* RFC 1122 initial RTO value */
+#define TCP_TIMEOUT_INIT ((unsigned)(1*HZ)) /* RFC2988bis initial RTO value */
+#define TCP_TIMEOUT_FALLBACK ((unsigned)(3*HZ)) /* RFC 1122 initial RTO value, now
+ * used as a fallback RTO for the
+ * initial data transmission if no
+ * valid RTT sample has been acquired,
+ * most likely due to retrans in 3WHS.
+ */
#define TCP_RESOURCE_PROBE_INTERVAL ((unsigned)(HZ/2U)) /* Maximal interval between probes
* for local resources.
@@ -295,7 +301,7 @@
static inline int tcp_synq_no_recent_overflow(const struct sock *sk)
{
unsigned long last_overflow = tcp_sk(sk)->rx_opt.ts_recent_stamp;
- return time_after(jiffies, last_overflow + TCP_TIMEOUT_INIT);
+ return time_after(jiffies, last_overflow + TCP_TIMEOUT_FALLBACK);
}
extern struct proto tcp_prot;
@@ -508,6 +514,7 @@
extern int tcp_mtu_to_mss(struct sock *sk, int pmtu);
extern int tcp_mss_to_mtu(struct sock *sk, int mss);
extern void tcp_mtup_init(struct sock *sk);
+extern void tcp_valid_rtt_meas(struct sock *sk, u32 seq_rtt);
static inline void tcp_bound_rto(const struct sock *sk)
{
diff --git a/include/net/wimax.h b/include/net/wimax.h
index 7328d50..322ff4f 100644
--- a/include/net/wimax.h
+++ b/include/net/wimax.h
@@ -423,7 +423,6 @@
int (*op_reset)(struct wimax_dev *wimax_dev);
struct rfkill *rfkill;
- struct input_dev *rfkill_input;
unsigned rf_hw;
unsigned rf_sw;
char name[32];
diff --git a/include/trace/events/sock.h b/include/trace/events/sock.h
new file mode 100644
index 0000000..779abb9
--- /dev/null
+++ b/include/trace/events/sock.h
@@ -0,0 +1,68 @@
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM sock
+
+#if !defined(_TRACE_SOCK_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_SOCK_H
+
+#include <net/sock.h>
+#include <linux/tracepoint.h>
+
+TRACE_EVENT(sock_rcvqueue_full,
+
+ TP_PROTO(struct sock *sk, struct sk_buff *skb),
+
+ TP_ARGS(sk, skb),
+
+ TP_STRUCT__entry(
+ __field(int, rmem_alloc)
+ __field(unsigned int, truesize)
+ __field(int, sk_rcvbuf)
+ ),
+
+ TP_fast_assign(
+ __entry->rmem_alloc = atomic_read(&sk->sk_rmem_alloc);
+ __entry->truesize = skb->truesize;
+ __entry->sk_rcvbuf = sk->sk_rcvbuf;
+ ),
+
+ TP_printk("rmem_alloc=%d truesize=%u sk_rcvbuf=%d",
+ __entry->rmem_alloc, __entry->truesize, __entry->sk_rcvbuf)
+);
+
+TRACE_EVENT(sock_exceed_buf_limit,
+
+ TP_PROTO(struct sock *sk, struct proto *prot, long allocated),
+
+ TP_ARGS(sk, prot, allocated),
+
+ TP_STRUCT__entry(
+ __array(char, name, 32)
+ __field(long *, sysctl_mem)
+ __field(long, allocated)
+ __field(int, sysctl_rmem)
+ __field(int, rmem_alloc)
+ ),
+
+ TP_fast_assign(
+ strncpy(__entry->name, prot->name, 32);
+ __entry->sysctl_mem = prot->sysctl_mem;
+ __entry->allocated = allocated;
+ __entry->sysctl_rmem = prot->sysctl_rmem[0];
+ __entry->rmem_alloc = atomic_read(&sk->sk_rmem_alloc);
+ ),
+
+ TP_printk("proto:%s sysctl_mem=%ld,%ld,%ld allocated=%ld "
+ "sysctl_rmem=%d rmem_alloc=%d",
+ __entry->name,
+ __entry->sysctl_mem[0],
+ __entry->sysctl_mem[1],
+ __entry->sysctl_mem[2],
+ __entry->allocated,
+ __entry->sysctl_rmem,
+ __entry->rmem_alloc)
+);
+
+#endif /* _TRACE_SOCK_H */
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
diff --git a/include/trace/events/udp.h b/include/trace/events/udp.h
new file mode 100644
index 0000000..a664bb9
--- /dev/null
+++ b/include/trace/events/udp.h
@@ -0,0 +1,32 @@
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM udp
+
+#if !defined(_TRACE_UDP_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_UDP_H
+
+#include <linux/udp.h>
+#include <linux/tracepoint.h>
+
+TRACE_EVENT(udp_fail_queue_rcv_skb,
+
+ TP_PROTO(int rc, struct sock *sk),
+
+ TP_ARGS(rc, sk),
+
+ TP_STRUCT__entry(
+ __field(int, rc)
+ __field(__u16, lport)
+ ),
+
+ TP_fast_assign(
+ __entry->rc = rc;
+ __entry->lport = inet_sk(sk)->inet_num;
+ ),
+
+ TP_printk("rc=%d port=%hu", __entry->rc, __entry->lport)
+);
+
+#endif /* _TRACE_UDP_H */
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
diff --git a/lib/Kconfig b/lib/Kconfig
index 830181c..32f3e5a 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -79,6 +79,13 @@
require M here. See Castagnoli93.
Module will be libcrc32c.
+config CRC8
+ tristate "CRC8 function"
+ help
+ This option provides CRC8 function. Drivers may select this
+ when they need to do cyclic redundancy check according CRC8
+ algorithm. Module will be called crc8.
+
config AUDIT_GENERIC
bool
depends on AUDIT && !AUDIT_ARCH
@@ -262,4 +269,11 @@
If unsure, say N.
+config CORDIC
+ tristate "Cordic function"
+ help
+ The option provides arithmetic function using cordic algorithm
+ so its calculations are in fixed point. Modules can select this
+ when they require this function. Module will be called cordic.
+
endmenu
diff --git a/lib/Makefile b/lib/Makefile
index 6b597fd..892f4e2 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -61,6 +61,7 @@
obj-$(CONFIG_CRC32) += crc32.o
obj-$(CONFIG_CRC7) += crc7.o
obj-$(CONFIG_LIBCRC32C) += libcrc32c.o
+obj-$(CONFIG_CRC8) += crc8.o
obj-$(CONFIG_GENERIC_ALLOCATOR) += genalloc.o
obj-$(CONFIG_ZLIB_INFLATE) += zlib_inflate/
@@ -112,6 +113,8 @@
obj-$(CONFIG_CPU_RMAP) += cpu_rmap.o
+obj-$(CONFIG_CORDIC) += cordic.o
+
hostprogs-y := gen_crc32table
clean-files := crc32table.h
diff --git a/lib/cordic.c b/lib/cordic.c
new file mode 100644
index 0000000..aa27a88
--- /dev/null
+++ b/lib/cordic.c
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2011 Broadcom Corporation
+ *
+ * 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.
+ */
+#include <linux/module.h>
+#include <linux/cordic.h>
+
+#define CORDIC_ANGLE_GEN 39797
+#define CORDIC_PRECISION_SHIFT 16
+#define CORDIC_NUM_ITER (CORDIC_PRECISION_SHIFT + 2)
+
+#define FIXED(X) ((s32)((X) << CORDIC_PRECISION_SHIFT))
+#define FLOAT(X) (((X) >= 0) \
+ ? ((((X) >> (CORDIC_PRECISION_SHIFT - 1)) + 1) >> 1) \
+ : -((((-(X)) >> (CORDIC_PRECISION_SHIFT - 1)) + 1) >> 1))
+
+static const s32 arctan_table[] = {
+ 2949120,
+ 1740967,
+ 919879,
+ 466945,
+ 234379,
+ 117304,
+ 58666,
+ 29335,
+ 14668,
+ 7334,
+ 3667,
+ 1833,
+ 917,
+ 458,
+ 229,
+ 115,
+ 57,
+ 29
+};
+
+/*
+ * cordic_calc_iq() - calculates the i/q coordinate for given angle
+ *
+ * theta: angle in degrees for which i/q coordinate is to be calculated
+ * coord: function output parameter holding the i/q coordinate
+ */
+struct cordic_iq cordic_calc_iq(s32 theta)
+{
+ struct cordic_iq coord;
+ s32 angle, valtmp;
+ unsigned iter;
+ int signx = 1;
+ int signtheta;
+
+ coord.i = CORDIC_ANGLE_GEN;
+ coord.q = 0;
+ angle = 0;
+
+ theta = FIXED(theta);
+ signtheta = (theta < 0) ? -1 : 1;
+ theta = ((theta + FIXED(180) * signtheta) % FIXED(360)) -
+ FIXED(180) * signtheta;
+
+ if (FLOAT(theta) > 90) {
+ theta -= FIXED(180);
+ signx = -1;
+ } else if (FLOAT(theta) < -90) {
+ theta += FIXED(180);
+ signx = -1;
+ }
+
+ for (iter = 0; iter < CORDIC_NUM_ITER; iter++) {
+ if (theta > angle) {
+ valtmp = coord.i - (coord.q >> iter);
+ coord.q += (coord.i >> iter);
+ angle += arctan_table[iter];
+ } else {
+ valtmp = coord.i + (coord.q >> iter);
+ coord.q -= (coord.i >> iter);
+ angle -= arctan_table[iter];
+ }
+ coord.i = valtmp;
+ }
+
+ coord.i *= signx;
+ coord.q *= signx;
+ return coord;
+}
+EXPORT_SYMBOL(cordic_calc_iq);
+
+MODULE_DESCRIPTION("Cordic functions");
+MODULE_AUTHOR("Broadcom Corporation");
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/lib/crc8.c b/lib/crc8.c
new file mode 100644
index 0000000..87b59ca
--- /dev/null
+++ b/lib/crc8.c
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2011 Broadcom Corporation
+ *
+ * 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.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/crc8.h>
+#include <linux/printk.h>
+
+/*
+ * crc8_populate_msb - fill crc table for given polynomial in reverse bit order.
+ *
+ * table: table to be filled.
+ * polynomial: polynomial for which table is to be filled.
+ */
+void crc8_populate_msb(u8 table[CRC8_TABLE_SIZE], u8 polynomial)
+{
+ int i, j;
+ const u8 msbit = 0x80;
+ u8 t = msbit;
+
+ table[0] = 0;
+
+ for (i = 1; i < CRC8_TABLE_SIZE; i *= 2) {
+ t = (t << 1) ^ (t & msbit ? polynomial : 0);
+ for (j = 0; j < i; j++)
+ table[i+j] = table[j] ^ t;
+ }
+}
+EXPORT_SYMBOL(crc8_populate_msb);
+
+/*
+ * crc8_populate_lsb - fill crc table for given polynomial in regular bit order.
+ *
+ * table: table to be filled.
+ * polynomial: polynomial for which table is to be filled.
+ */
+void crc8_populate_lsb(u8 table[CRC8_TABLE_SIZE], u8 polynomial)
+{
+ int i, j;
+ u8 t = 1;
+
+ table[0] = 0;
+
+ for (i = (CRC8_TABLE_SIZE >> 1); i; i >>= 1) {
+ t = (t >> 1) ^ (t & 1 ? polynomial : 0);
+ for (j = 0; j < CRC8_TABLE_SIZE; j += 2*i)
+ table[i+j] = table[j] ^ t;
+ }
+}
+EXPORT_SYMBOL(crc8_populate_lsb);
+
+/*
+ * crc8 - calculate a crc8 over the given input data.
+ *
+ * table: crc table used for calculation.
+ * pdata: pointer to data buffer.
+ * nbytes: number of bytes in data buffer.
+ * crc: previous returned crc8 value.
+ */
+u8 crc8(const u8 table[CRC8_TABLE_SIZE], u8 *pdata, size_t nbytes, u8 crc)
+{
+ /* loop over the buffer data */
+ while (nbytes-- > 0)
+ crc = table[(crc ^ *pdata++) & 0xff];
+
+ return crc;
+}
+EXPORT_SYMBOL(crc8);
+
+MODULE_DESCRIPTION("CRC8 (by Williams, Ross N.) function");
+MODULE_AUTHOR("Broadcom Corporation");
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c
index 917ecb9..d24c464 100644
--- a/net/8021q/vlan.c
+++ b/net/8021q/vlan.c
@@ -18,6 +18,8 @@
* 2 of the License, or (at your option) any later version.
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/capability.h>
#include <linux/module.h>
#include <linux/netdevice.h>
@@ -149,13 +151,13 @@
const struct net_device_ops *ops = real_dev->netdev_ops;
if (real_dev->features & NETIF_F_VLAN_CHALLENGED) {
- pr_info("8021q: VLANs not supported on %s\n", name);
+ pr_info("VLANs not supported on %s\n", name);
return -EOPNOTSUPP;
}
if ((real_dev->features & NETIF_F_HW_VLAN_FILTER) &&
(!ops->ndo_vlan_rx_add_vid || !ops->ndo_vlan_rx_kill_vid)) {
- pr_info("8021q: Device %s has buggy VLAN hw accel\n", name);
+ pr_info("Device %s has buggy VLAN hw accel\n", name);
return -EOPNOTSUPP;
}
@@ -344,13 +346,12 @@
case NETDEV_CHANGENAME:
vlan_proc_rem_dev(dev);
if (vlan_proc_add_dev(dev) < 0)
- pr_warning("8021q: failed to change proc name for %s\n",
- dev->name);
+ pr_warn("failed to change proc name for %s\n",
+ dev->name);
break;
case NETDEV_REGISTER:
if (vlan_proc_add_dev(dev) < 0)
- pr_warning("8021q: failed to add proc entry for %s\n",
- dev->name);
+ pr_warn("failed to add proc entry for %s\n", dev->name);
break;
case NETDEV_UNREGISTER:
vlan_proc_rem_dev(dev);
@@ -374,7 +375,7 @@
if ((event == NETDEV_UP) &&
(dev->features & NETIF_F_HW_VLAN_FILTER) &&
dev->netdev_ops->ndo_vlan_rx_add_vid) {
- pr_info("8021q: adding VLAN 0 to HW filter on device %s\n",
+ pr_info("adding VLAN 0 to HW filter on device %s\n",
dev->name);
dev->netdev_ops->ndo_vlan_rx_add_vid(dev, 0);
}
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
index 86bff9b..d8f45ba 100644
--- a/net/8021q/vlan_dev.c
+++ b/net/8021q/vlan_dev.c
@@ -20,6 +20,8 @@
* 2 of the License, or (at your option) any later version.
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/skbuff.h>
@@ -55,7 +57,7 @@
return arp_find(veth->h_dest, skb);
#endif
default:
- pr_debug("%s: unable to resolve type %X addresses.\n",
+ pr_debug("%s: unable to resolve type %X addresses\n",
dev->name, ntohs(veth->h_vlan_encapsulated_proto));
memcpy(veth->h_source, dev->dev_addr, ETH_ALEN);
diff --git a/net/8021q/vlanproc.c b/net/8021q/vlanproc.c
index d940c49..d34b6da 100644
--- a/net/8021q/vlanproc.c
+++ b/net/8021q/vlanproc.c
@@ -17,6 +17,8 @@
* Jan 20, 1998 Ben Greear Initial Version
*****************************************************************************/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/kernel.h>
@@ -155,7 +157,7 @@
return 0;
err:
- pr_err("%s: can't create entry in proc filesystem!\n", __func__);
+ pr_err("can't create entry in proc filesystem!\n");
vlan_proc_cleanup(net);
return -ENOBUFS;
}
@@ -229,7 +231,7 @@
++*pos;
- dev = (struct net_device *)v;
+ dev = v;
if (v == SEQ_START_TOKEN)
dev = net_device_entry(&net->dev_base_head);
diff --git a/net/TUNABLE b/net/TUNABLE
deleted file mode 100644
index 9913211..0000000
--- a/net/TUNABLE
+++ /dev/null
@@ -1,50 +0,0 @@
-The following parameters should be tunable at compile time. Some of them
-exist as sysctls too.
-
-This is far from complete
-
-Item Description
-----------------------------------------------------------------------------
-MAX_LINKS Maximum number of netlink minor devices. (1-32)
-RIF_TABLE_SIZE Token ring RIF cache size (tunable)
-AARP_HASH_SIZE Size of Appletalk hash table (tunable)
-AX25_DEF_T1 AX.25 parameters. These are all tunable via
-AX25_DEF_T2 SIOCAX25SETPARMS
-AX25_DEF_T3 T1-T3,N2 have the meanings in the specification
-AX25_DEF_N2
-AX25_DEF_AXDEFMODE 8 = normal 128 is PE1CHL extended
-AX25_DEF_IPDEFMODE 'D' - datagram 'V' - virtual connection
-AX25_DEF_BACKOFF 'E'xponential 'L'inear
-AX25_DEF_NETROM Allow netrom 1=Y
-AX25_DF_TEXT Allow PID=Text 1=Y
-AX25_DEF_WINDOW Window for normal mode
-AX25_DEF_EWINDOW Window for PE1CHL mode
-AX25_DEF_DIGI 1 for inband 2 for cross band 3 for both
-AX25_DEF_CONMODE Allow connected modes 1=Yes
-AX25_ROUTE_MAX AX.25 route cache size - no currently tunable
-Unnamed (16) Number of protocol hash slots (tunable)
-DEV_NUMBUFFS Number of priority levels (not easily tunable)
-Unnamed (300) Maximum packet backlog queue (tunable)
-MAX_IOVEC Maximum number of iovecs in a message (tunable)
-MIN_WINDOW Offered minimum window (tunable)
-MAX_WINDOW Offered maximum window (tunable)
-MAX_HEADER Largest physical header (tunable)
-MAX_ADDR_LEN Largest physical address (tunable)
-SOCK_ARRAY_SIZE IP socket array hash size (tunable)
-IP_MAX_MEMBERSHIPS Largest number of groups per socket (BSD style) (tunable)
-16 Hard coded constant for amount of room allowed for
- cache align and faster forwarding (tunable)
-IP_FRAG_TIME Time we hold a fragment for. (tunable)
-PORT_MASQ_BEGIN First port reserved for masquerade (tunable)
-PORT_MASQ_END Last port used for masquerade (tunable)
-MASQUERADE_EXPIRE_TCP_FIN Time we keep a masquerade for after a FIN
-MASQUERADE_EXPIRE_UDP Time we keep a UDP masquerade for (tunable)
-MAXVIFS Maximum mrouted vifs (1-32)
-MFC_LINES Lines in the multicast router cache (tunable)
-
-NetROM parameters are tunable via an ioctl passing a struct
-
-4000 Size a Unix domain socket malloc falls back to
- (tunable) should be 8K - a bit for 8K machines like
- the ALPHA
-
diff --git a/net/appletalk/aarp.c b/net/appletalk/aarp.c
index 50dce79..1acc695 100644
--- a/net/appletalk/aarp.c
+++ b/net/appletalk/aarp.c
@@ -779,87 +779,87 @@
}
switch (function) {
- case AARP_REPLY:
- if (!unresolved_count) /* Speed up */
- break;
-
- /* Find the entry. */
- a = __aarp_find_entry(unresolved[hash], dev, &sa);
- if (!a || dev != a->dev)
- break;
-
- /* We can fill one in - this is good. */
- memcpy(a->hwaddr, ea->hw_src, ETH_ALEN);
- __aarp_resolved(&unresolved[hash], a, hash);
- if (!unresolved_count)
- mod_timer(&aarp_timer,
- jiffies + sysctl_aarp_expiry_time);
+ case AARP_REPLY:
+ if (!unresolved_count) /* Speed up */
break;
- case AARP_REQUEST:
- case AARP_PROBE:
+ /* Find the entry. */
+ a = __aarp_find_entry(unresolved[hash], dev, &sa);
+ if (!a || dev != a->dev)
+ break;
+
+ /* We can fill one in - this is good. */
+ memcpy(a->hwaddr, ea->hw_src, ETH_ALEN);
+ __aarp_resolved(&unresolved[hash], a, hash);
+ if (!unresolved_count)
+ mod_timer(&aarp_timer,
+ jiffies + sysctl_aarp_expiry_time);
+ break;
+
+ case AARP_REQUEST:
+ case AARP_PROBE:
+
+ /*
+ * If it is my address set ma to my address and reply.
+ * We can treat probe and request the same. Probe
+ * simply means we shouldn't cache the querying host,
+ * as in a probe they are proposing an address not
+ * using one.
+ *
+ * Support for proxy-AARP added. We check if the
+ * address is one of our proxies before we toss the
+ * packet out.
+ */
+
+ sa.s_node = ea->pa_dst_node;
+ sa.s_net = ea->pa_dst_net;
+
+ /* See if we have a matching proxy. */
+ ma = __aarp_proxy_find(dev, &sa);
+ if (!ma)
+ ma = &ifa->address;
+ else { /* We need to make a copy of the entry. */
+ da.s_node = sa.s_node;
+ da.s_net = sa.s_net;
+ ma = &da;
+ }
+
+ if (function == AARP_PROBE) {
+ /*
+ * A probe implies someone trying to get an
+ * address. So as a precaution flush any
+ * entries we have for this address.
+ */
+ a = __aarp_find_entry(resolved[sa.s_node %
+ (AARP_HASH_SIZE - 1)],
+ skb->dev, &sa);
/*
- * If it is my address set ma to my address and reply.
- * We can treat probe and request the same. Probe
- * simply means we shouldn't cache the querying host,
- * as in a probe they are proposing an address not
- * using one.
- *
- * Support for proxy-AARP added. We check if the
- * address is one of our proxies before we toss the
- * packet out.
+ * Make it expire next tick - that avoids us
+ * getting into a probe/flush/learn/probe/
+ * flush/learn cycle during probing of a slow
+ * to respond host addr.
*/
-
- sa.s_node = ea->pa_dst_node;
- sa.s_net = ea->pa_dst_net;
-
- /* See if we have a matching proxy. */
- ma = __aarp_proxy_find(dev, &sa);
- if (!ma)
- ma = &ifa->address;
- else { /* We need to make a copy of the entry. */
- da.s_node = sa.s_node;
- da.s_net = sa.s_net;
- ma = &da;
+ if (a) {
+ a->expires_at = jiffies - 1;
+ mod_timer(&aarp_timer, jiffies +
+ sysctl_aarp_tick_time);
}
+ }
- if (function == AARP_PROBE) {
- /*
- * A probe implies someone trying to get an
- * address. So as a precaution flush any
- * entries we have for this address.
- */
- a = __aarp_find_entry(resolved[sa.s_node %
- (AARP_HASH_SIZE - 1)],
- skb->dev, &sa);
-
- /*
- * Make it expire next tick - that avoids us
- * getting into a probe/flush/learn/probe/
- * flush/learn cycle during probing of a slow
- * to respond host addr.
- */
- if (a) {
- a->expires_at = jiffies - 1;
- mod_timer(&aarp_timer, jiffies +
- sysctl_aarp_tick_time);
- }
- }
-
- if (sa.s_node != ma->s_node)
- break;
-
- if (sa.s_net && ma->s_net && sa.s_net != ma->s_net)
- break;
-
- sa.s_node = ea->pa_src_node;
- sa.s_net = ea->pa_src_net;
-
- /* aarp_my_address has found the address to use for us.
- */
- aarp_send_reply(dev, ma, &sa, ea->hw_src);
+ if (sa.s_node != ma->s_node)
break;
+
+ if (sa.s_net && ma->s_net && sa.s_net != ma->s_net)
+ break;
+
+ sa.s_node = ea->pa_src_node;
+ sa.s_net = ea->pa_src_net;
+
+ /* aarp_my_address has found the address to use for us.
+ */
+ aarp_send_reply(dev, ma, &sa, ea->hw_src);
+ break;
}
unlock:
diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c
index 956a530..b1fe7c3 100644
--- a/net/appletalk/ddp.c
+++ b/net/appletalk/ddp.c
@@ -684,192 +684,192 @@
atif = atalk_find_dev(dev);
switch (cmd) {
- case SIOCSIFADDR:
- if (!capable(CAP_NET_ADMIN))
- return -EPERM;
- if (sa->sat_family != AF_APPLETALK)
- return -EINVAL;
- if (dev->type != ARPHRD_ETHER &&
- dev->type != ARPHRD_LOOPBACK &&
- dev->type != ARPHRD_LOCALTLK &&
- dev->type != ARPHRD_PPP)
- return -EPROTONOSUPPORT;
+ case SIOCSIFADDR:
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
+ if (sa->sat_family != AF_APPLETALK)
+ return -EINVAL;
+ if (dev->type != ARPHRD_ETHER &&
+ dev->type != ARPHRD_LOOPBACK &&
+ dev->type != ARPHRD_LOCALTLK &&
+ dev->type != ARPHRD_PPP)
+ return -EPROTONOSUPPORT;
- nr = (struct atalk_netrange *)&sa->sat_zero[0];
- add_route = 1;
+ nr = (struct atalk_netrange *)&sa->sat_zero[0];
+ add_route = 1;
- /*
- * if this is a point-to-point iface, and we already
- * have an iface for this AppleTalk address, then we
- * should not add a route
- */
- if ((dev->flags & IFF_POINTOPOINT) &&
- atalk_find_interface(sa->sat_addr.s_net,
- sa->sat_addr.s_node)) {
- printk(KERN_DEBUG "AppleTalk: point-to-point "
- "interface added with "
- "existing address\n");
- add_route = 0;
- }
+ /*
+ * if this is a point-to-point iface, and we already
+ * have an iface for this AppleTalk address, then we
+ * should not add a route
+ */
+ if ((dev->flags & IFF_POINTOPOINT) &&
+ atalk_find_interface(sa->sat_addr.s_net,
+ sa->sat_addr.s_node)) {
+ printk(KERN_DEBUG "AppleTalk: point-to-point "
+ "interface added with "
+ "existing address\n");
+ add_route = 0;
+ }
- /*
- * Phase 1 is fine on LocalTalk but we don't do
- * EtherTalk phase 1. Anyone wanting to add it go ahead.
- */
- if (dev->type == ARPHRD_ETHER && nr->nr_phase != 2)
- return -EPROTONOSUPPORT;
- if (sa->sat_addr.s_node == ATADDR_BCAST ||
- sa->sat_addr.s_node == 254)
- return -EINVAL;
- if (atif) {
- /* Already setting address */
- if (atif->status & ATIF_PROBE)
- return -EBUSY;
+ /*
+ * Phase 1 is fine on LocalTalk but we don't do
+ * EtherTalk phase 1. Anyone wanting to add it go ahead.
+ */
+ if (dev->type == ARPHRD_ETHER && nr->nr_phase != 2)
+ return -EPROTONOSUPPORT;
+ if (sa->sat_addr.s_node == ATADDR_BCAST ||
+ sa->sat_addr.s_node == 254)
+ return -EINVAL;
+ if (atif) {
+ /* Already setting address */
+ if (atif->status & ATIF_PROBE)
+ return -EBUSY;
- atif->address.s_net = sa->sat_addr.s_net;
- atif->address.s_node = sa->sat_addr.s_node;
- atrtr_device_down(dev); /* Flush old routes */
- } else {
- atif = atif_add_device(dev, &sa->sat_addr);
- if (!atif)
- return -ENOMEM;
- }
- atif->nets = *nr;
-
- /*
- * Check if the chosen address is used. If so we
- * error and atalkd will try another.
- */
-
- if (!(dev->flags & IFF_LOOPBACK) &&
- !(dev->flags & IFF_POINTOPOINT) &&
- atif_probe_device(atif) < 0) {
- atif_drop_device(dev);
- return -EADDRINUSE;
- }
-
- /* Hey it worked - add the direct routes */
- sa = (struct sockaddr_at *)&rtdef.rt_gateway;
- sa->sat_family = AF_APPLETALK;
- sa->sat_addr.s_net = atif->address.s_net;
- sa->sat_addr.s_node = atif->address.s_node;
- sa = (struct sockaddr_at *)&rtdef.rt_dst;
- rtdef.rt_flags = RTF_UP;
- sa->sat_family = AF_APPLETALK;
- sa->sat_addr.s_node = ATADDR_ANYNODE;
- if (dev->flags & IFF_LOOPBACK ||
- dev->flags & IFF_POINTOPOINT)
- rtdef.rt_flags |= RTF_HOST;
-
- /* Routerless initial state */
- if (nr->nr_firstnet == htons(0) &&
- nr->nr_lastnet == htons(0xFFFE)) {
- sa->sat_addr.s_net = atif->address.s_net;
- atrtr_create(&rtdef, dev);
- atrtr_set_default(dev);
- } else {
- limit = ntohs(nr->nr_lastnet);
- if (limit - ntohs(nr->nr_firstnet) > 4096) {
- printk(KERN_WARNING "Too many routes/"
- "iface.\n");
- return -EINVAL;
- }
- if (add_route)
- for (ct = ntohs(nr->nr_firstnet);
- ct <= limit; ct++) {
- sa->sat_addr.s_net = htons(ct);
- atrtr_create(&rtdef, dev);
- }
- }
- dev_mc_add_global(dev, aarp_mcast);
- return 0;
-
- case SIOCGIFADDR:
+ atif->address.s_net = sa->sat_addr.s_net;
+ atif->address.s_node = sa->sat_addr.s_node;
+ atrtr_device_down(dev); /* Flush old routes */
+ } else {
+ atif = atif_add_device(dev, &sa->sat_addr);
if (!atif)
- return -EADDRNOTAVAIL;
+ return -ENOMEM;
+ }
+ atif->nets = *nr;
- sa->sat_family = AF_APPLETALK;
- sa->sat_addr = atif->address;
- break;
+ /*
+ * Check if the chosen address is used. If so we
+ * error and atalkd will try another.
+ */
- case SIOCGIFBRDADDR:
- if (!atif)
- return -EADDRNOTAVAIL;
+ if (!(dev->flags & IFF_LOOPBACK) &&
+ !(dev->flags & IFF_POINTOPOINT) &&
+ atif_probe_device(atif) < 0) {
+ atif_drop_device(dev);
+ return -EADDRINUSE;
+ }
- sa->sat_family = AF_APPLETALK;
+ /* Hey it worked - add the direct routes */
+ sa = (struct sockaddr_at *)&rtdef.rt_gateway;
+ sa->sat_family = AF_APPLETALK;
+ sa->sat_addr.s_net = atif->address.s_net;
+ sa->sat_addr.s_node = atif->address.s_node;
+ sa = (struct sockaddr_at *)&rtdef.rt_dst;
+ rtdef.rt_flags = RTF_UP;
+ sa->sat_family = AF_APPLETALK;
+ sa->sat_addr.s_node = ATADDR_ANYNODE;
+ if (dev->flags & IFF_LOOPBACK ||
+ dev->flags & IFF_POINTOPOINT)
+ rtdef.rt_flags |= RTF_HOST;
+
+ /* Routerless initial state */
+ if (nr->nr_firstnet == htons(0) &&
+ nr->nr_lastnet == htons(0xFFFE)) {
sa->sat_addr.s_net = atif->address.s_net;
- sa->sat_addr.s_node = ATADDR_BCAST;
- break;
-
- case SIOCATALKDIFADDR:
- case SIOCDIFADDR:
- if (!capable(CAP_NET_ADMIN))
- return -EPERM;
- if (sa->sat_family != AF_APPLETALK)
+ atrtr_create(&rtdef, dev);
+ atrtr_set_default(dev);
+ } else {
+ limit = ntohs(nr->nr_lastnet);
+ if (limit - ntohs(nr->nr_firstnet) > 4096) {
+ printk(KERN_WARNING "Too many routes/"
+ "iface.\n");
return -EINVAL;
- atalk_dev_down(dev);
- break;
+ }
+ if (add_route)
+ for (ct = ntohs(nr->nr_firstnet);
+ ct <= limit; ct++) {
+ sa->sat_addr.s_net = htons(ct);
+ atrtr_create(&rtdef, dev);
+ }
+ }
+ dev_mc_add_global(dev, aarp_mcast);
+ return 0;
- case SIOCSARP:
- if (!capable(CAP_NET_ADMIN))
- return -EPERM;
- if (sa->sat_family != AF_APPLETALK)
- return -EINVAL;
- /*
- * for now, we only support proxy AARP on ELAP;
- * we should be able to do it for LocalTalk, too.
- */
- if (dev->type != ARPHRD_ETHER)
- return -EPROTONOSUPPORT;
+ case SIOCGIFADDR:
+ if (!atif)
+ return -EADDRNOTAVAIL;
- /*
- * atif points to the current interface on this network;
- * we aren't concerned about its current status (at
- * least for now), but it has all the settings about
- * the network we're going to probe. Consequently, it
- * must exist.
- */
- if (!atif)
- return -EADDRNOTAVAIL;
+ sa->sat_family = AF_APPLETALK;
+ sa->sat_addr = atif->address;
+ break;
- nr = (struct atalk_netrange *)&(atif->nets);
- /*
- * Phase 1 is fine on Localtalk but we don't do
- * Ethertalk phase 1. Anyone wanting to add it go ahead.
- */
- if (dev->type == ARPHRD_ETHER && nr->nr_phase != 2)
- return -EPROTONOSUPPORT;
+ case SIOCGIFBRDADDR:
+ if (!atif)
+ return -EADDRNOTAVAIL;
- if (sa->sat_addr.s_node == ATADDR_BCAST ||
- sa->sat_addr.s_node == 254)
- return -EINVAL;
+ sa->sat_family = AF_APPLETALK;
+ sa->sat_addr.s_net = atif->address.s_net;
+ sa->sat_addr.s_node = ATADDR_BCAST;
+ break;
- /*
- * Check if the chosen address is used. If so we
- * error and ATCP will try another.
- */
- if (atif_proxy_probe_device(atif, &(sa->sat_addr)) < 0)
- return -EADDRINUSE;
+ case SIOCATALKDIFADDR:
+ case SIOCDIFADDR:
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
+ if (sa->sat_family != AF_APPLETALK)
+ return -EINVAL;
+ atalk_dev_down(dev);
+ break;
- /*
- * We now have an address on the local network, and
- * the AARP code will defend it for us until we take it
- * down. We don't set up any routes right now, because
- * ATCP will install them manually via SIOCADDRT.
- */
- break;
+ case SIOCSARP:
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
+ if (sa->sat_family != AF_APPLETALK)
+ return -EINVAL;
+ /*
+ * for now, we only support proxy AARP on ELAP;
+ * we should be able to do it for LocalTalk, too.
+ */
+ if (dev->type != ARPHRD_ETHER)
+ return -EPROTONOSUPPORT;
- case SIOCDARP:
- if (!capable(CAP_NET_ADMIN))
- return -EPERM;
- if (sa->sat_family != AF_APPLETALK)
- return -EINVAL;
- if (!atif)
- return -EADDRNOTAVAIL;
+ /*
+ * atif points to the current interface on this network;
+ * we aren't concerned about its current status (at
+ * least for now), but it has all the settings about
+ * the network we're going to probe. Consequently, it
+ * must exist.
+ */
+ if (!atif)
+ return -EADDRNOTAVAIL;
- /* give to aarp module to remove proxy entry */
- aarp_proxy_remove(atif->dev, &(sa->sat_addr));
- return 0;
+ nr = (struct atalk_netrange *)&(atif->nets);
+ /*
+ * Phase 1 is fine on Localtalk but we don't do
+ * Ethertalk phase 1. Anyone wanting to add it go ahead.
+ */
+ if (dev->type == ARPHRD_ETHER && nr->nr_phase != 2)
+ return -EPROTONOSUPPORT;
+
+ if (sa->sat_addr.s_node == ATADDR_BCAST ||
+ sa->sat_addr.s_node == 254)
+ return -EINVAL;
+
+ /*
+ * Check if the chosen address is used. If so we
+ * error and ATCP will try another.
+ */
+ if (atif_proxy_probe_device(atif, &(sa->sat_addr)) < 0)
+ return -EADDRINUSE;
+
+ /*
+ * We now have an address on the local network, and
+ * the AARP code will defend it for us until we take it
+ * down. We don't set up any routes right now, because
+ * ATCP will install them manually via SIOCADDRT.
+ */
+ break;
+
+ case SIOCDARP:
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
+ if (sa->sat_family != AF_APPLETALK)
+ return -EINVAL;
+ if (!atif)
+ return -EADDRNOTAVAIL;
+
+ /* give to aarp module to remove proxy entry */
+ aarp_proxy_remove(atif->dev, &(sa->sat_addr));
+ return 0;
}
return copy_to_user(arg, &atreq, sizeof(atreq)) ? -EFAULT : 0;
@@ -884,25 +884,25 @@
return -EFAULT;
switch (cmd) {
- case SIOCDELRT:
- if (rt.rt_dst.sa_family != AF_APPLETALK)
- return -EINVAL;
- return atrtr_delete(&((struct sockaddr_at *)
- &rt.rt_dst)->sat_addr);
+ case SIOCDELRT:
+ if (rt.rt_dst.sa_family != AF_APPLETALK)
+ return -EINVAL;
+ return atrtr_delete(&((struct sockaddr_at *)
+ &rt.rt_dst)->sat_addr);
- case SIOCADDRT: {
- struct net_device *dev = NULL;
- if (rt.rt_dev) {
- char name[IFNAMSIZ];
- if (copy_from_user(name, rt.rt_dev, IFNAMSIZ-1))
- return -EFAULT;
- name[IFNAMSIZ-1] = '\0';
- dev = __dev_get_by_name(&init_net, name);
- if (!dev)
- return -ENODEV;
- }
- return atrtr_create(&rt, dev);
+ case SIOCADDRT: {
+ struct net_device *dev = NULL;
+ if (rt.rt_dev) {
+ char name[IFNAMSIZ];
+ if (copy_from_user(name, rt.rt_dev, IFNAMSIZ-1))
+ return -EFAULT;
+ name[IFNAMSIZ-1] = '\0';
+ dev = __dev_get_by_name(&init_net, name);
+ if (!dev)
+ return -ENODEV;
}
+ return atrtr_create(&rt, dev);
+ }
}
return -EINVAL;
}
diff --git a/net/atm/mpc.c b/net/atm/mpc.c
index 3ccca42..aa972409f 100644
--- a/net/atm/mpc.c
+++ b/net/atm/mpc.c
@@ -1005,7 +1005,7 @@
struct mpoa_client *mpc;
struct lec_priv *priv;
- dev = (struct net_device *)dev_ptr;
+ dev = dev_ptr;
if (!net_eq(dev_net(dev), &init_net))
return NOTIFY_DONE;
diff --git a/net/atm/pppoatm.c b/net/atm/pppoatm.c
index e9aced0..db4a11c 100644
--- a/net/atm/pppoatm.c
+++ b/net/atm/pppoatm.c
@@ -37,6 +37,7 @@
#include <linux/module.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/skbuff.h>
#include <linux/slab.h>
#include <linux/atm.h>
diff --git a/net/batman-adv/Kconfig b/net/batman-adv/Kconfig
index 6c051ad..2b68d06 100644
--- a/net/batman-adv/Kconfig
+++ b/net/batman-adv/Kconfig
@@ -5,6 +5,7 @@
config BATMAN_ADV
tristate "B.A.T.M.A.N. Advanced Meshing Protocol"
depends on NET
+ select CRC16
default n
---help---
diff --git a/net/batman-adv/aggregation.c b/net/batman-adv/aggregation.c
index a8c3203..69467fe7 100644
--- a/net/batman-adv/aggregation.c
+++ b/net/batman-adv/aggregation.c
@@ -20,28 +20,26 @@
*/
#include "main.h"
+#include "translation-table.h"
#include "aggregation.h"
#include "send.h"
#include "routing.h"
#include "hard-interface.h"
-/* calculate the size of the tt information for a given packet */
-static int tt_len(struct batman_packet *batman_packet)
-{
- return batman_packet->num_tt * ETH_ALEN;
-}
-
/* return true if new_packet can be aggregated with forw_packet */
-static bool can_aggregate_with(struct batman_packet *new_batman_packet,
+static bool can_aggregate_with(const struct batman_packet *new_batman_packet,
+ struct bat_priv *bat_priv,
int packet_len,
unsigned long send_time,
bool directlink,
- struct hard_iface *if_incoming,
- struct forw_packet *forw_packet)
+ const struct hard_iface *if_incoming,
+ const struct forw_packet *forw_packet)
{
struct batman_packet *batman_packet =
(struct batman_packet *)forw_packet->skb->data;
int aggregated_bytes = forw_packet->packet_len + packet_len;
+ struct hard_iface *primary_if = NULL;
+ bool res = false;
/**
* we can aggregate the current packet to this aggregated packet
@@ -66,6 +64,10 @@
* packet
*/
+ primary_if = primary_if_get_selected(bat_priv);
+ if (!primary_if)
+ goto out;
+
/* packets without direct link flag and high TTL
* are flooded through the net */
if ((!directlink) &&
@@ -75,8 +77,10 @@
/* own packets originating non-primary
* interfaces leave only that interface */
((!forw_packet->own) ||
- (forw_packet->if_incoming->if_num == 0)))
- return true;
+ (forw_packet->if_incoming == primary_if))) {
+ res = true;
+ goto out;
+ }
/* if the incoming packet is sent via this one
* interface only - we still can aggregate */
@@ -89,16 +93,22 @@
* (= secondary interface packets in general) */
(batman_packet->flags & DIRECTLINK ||
(forw_packet->own &&
- forw_packet->if_incoming->if_num != 0)))
- return true;
+ forw_packet->if_incoming != primary_if))) {
+ res = true;
+ goto out;
+ }
}
- return false;
+out:
+ if (primary_if)
+ hardif_free_ref(primary_if);
+ return res;
}
/* create a new aggregated packet and add this packet to it */
-static void new_aggregated_packet(unsigned char *packet_buff, int packet_len,
- unsigned long send_time, bool direct_link,
+static void new_aggregated_packet(const unsigned char *packet_buff,
+ int packet_len, unsigned long send_time,
+ bool direct_link,
struct hard_iface *if_incoming,
int own_packet)
{
@@ -118,7 +128,7 @@
}
}
- forw_packet_aggr = kmalloc(sizeof(struct forw_packet), GFP_ATOMIC);
+ forw_packet_aggr = kmalloc(sizeof(*forw_packet_aggr), GFP_ATOMIC);
if (!forw_packet_aggr) {
if (!own_packet)
atomic_inc(&bat_priv->batman_queue_left);
@@ -150,7 +160,7 @@
forw_packet_aggr->own = own_packet;
forw_packet_aggr->if_incoming = if_incoming;
forw_packet_aggr->num_packets = 0;
- forw_packet_aggr->direct_link_flags = 0;
+ forw_packet_aggr->direct_link_flags = NO_FLAGS;
forw_packet_aggr->send_time = send_time;
/* save packet direct link flag status */
@@ -176,8 +186,7 @@
/* aggregate a new packet into the existing aggregation */
static void aggregate(struct forw_packet *forw_packet_aggr,
- unsigned char *packet_buff,
- int packet_len,
+ const unsigned char *packet_buff, int packet_len,
bool direct_link)
{
unsigned char *skb_buff;
@@ -195,7 +204,7 @@
void add_bat_packet_to_list(struct bat_priv *bat_priv,
unsigned char *packet_buff, int packet_len,
- struct hard_iface *if_incoming, char own_packet,
+ struct hard_iface *if_incoming, int own_packet,
unsigned long send_time)
{
/**
@@ -215,6 +224,7 @@
hlist_for_each_entry(forw_packet_pos, tmp_node,
&bat_priv->forw_bat_list, list) {
if (can_aggregate_with(batman_packet,
+ bat_priv,
packet_len,
send_time,
direct_link,
@@ -253,8 +263,9 @@
}
/* unpack the aggregated packets and process them one by one */
-void receive_aggr_bat_packet(struct ethhdr *ethhdr, unsigned char *packet_buff,
- int packet_len, struct hard_iface *if_incoming)
+void receive_aggr_bat_packet(const struct ethhdr *ethhdr,
+ unsigned char *packet_buff, int packet_len,
+ struct hard_iface *if_incoming)
{
struct batman_packet *batman_packet;
int buff_pos = 0;
@@ -263,18 +274,20 @@
batman_packet = (struct batman_packet *)packet_buff;
do {
- /* network to host order for our 32bit seqno, and the
- orig_interval. */
+ /* network to host order for our 32bit seqno and the
+ orig_interval */
batman_packet->seqno = ntohl(batman_packet->seqno);
+ batman_packet->tt_crc = ntohs(batman_packet->tt_crc);
tt_buff = packet_buff + buff_pos + BAT_PACKET_LEN;
- receive_bat_packet(ethhdr, batman_packet,
- tt_buff, tt_len(batman_packet),
- if_incoming);
- buff_pos += BAT_PACKET_LEN + tt_len(batman_packet);
+ receive_bat_packet(ethhdr, batman_packet, tt_buff, if_incoming);
+
+ buff_pos += BAT_PACKET_LEN +
+ tt_len(batman_packet->tt_num_changes);
+
batman_packet = (struct batman_packet *)
(packet_buff + buff_pos);
} while (aggregated_packet(buff_pos, packet_len,
- batman_packet->num_tt));
+ batman_packet->tt_num_changes));
}
diff --git a/net/batman-adv/aggregation.h b/net/batman-adv/aggregation.h
index 7e6d72f..216337b 100644
--- a/net/batman-adv/aggregation.h
+++ b/net/batman-adv/aggregation.h
@@ -25,9 +25,11 @@
#include "main.h"
/* is there another aggregated packet here? */
-static inline int aggregated_packet(int buff_pos, int packet_len, int num_tt)
+static inline int aggregated_packet(int buff_pos, int packet_len,
+ int tt_num_changes)
{
- int next_buff_pos = buff_pos + BAT_PACKET_LEN + (num_tt * ETH_ALEN);
+ int next_buff_pos = buff_pos + BAT_PACKET_LEN + (tt_num_changes *
+ sizeof(struct tt_change));
return (next_buff_pos <= packet_len) &&
(next_buff_pos <= MAX_AGGREGATION_BYTES);
@@ -35,9 +37,10 @@
void add_bat_packet_to_list(struct bat_priv *bat_priv,
unsigned char *packet_buff, int packet_len,
- struct hard_iface *if_incoming, char own_packet,
+ struct hard_iface *if_incoming, int own_packet,
unsigned long send_time);
-void receive_aggr_bat_packet(struct ethhdr *ethhdr, unsigned char *packet_buff,
- int packet_len, struct hard_iface *if_incoming);
+void receive_aggr_bat_packet(const struct ethhdr *ethhdr,
+ unsigned char *packet_buff, int packet_len,
+ struct hard_iface *if_incoming);
#endif /* _NET_BATMAN_ADV_AGGREGATION_H_ */
diff --git a/net/batman-adv/bat_debugfs.c b/net/batman-adv/bat_debugfs.c
index abaeec5..d0af9bf 100644
--- a/net/batman-adv/bat_debugfs.c
+++ b/net/batman-adv/bat_debugfs.c
@@ -50,7 +50,8 @@
debug_log->log_start = debug_log->log_end - log_buff_len;
}
-static int fdebug_log(struct debug_log *debug_log, char *fmt, ...)
+__printf(2, 3)
+static int fdebug_log(struct debug_log *debug_log, const char *fmt, ...)
{
va_list args;
static char debug_log_buf[256];
@@ -74,14 +75,14 @@
return 0;
}
-int debug_log(struct bat_priv *bat_priv, char *fmt, ...)
+int debug_log(struct bat_priv *bat_priv, const char *fmt, ...)
{
va_list args;
char tmp_log_buf[256];
va_start(args, fmt);
vscnprintf(tmp_log_buf, sizeof(tmp_log_buf), fmt, args);
- fdebug_log(bat_priv->debug_log, "[%10u] %s",
+ fdebug_log(bat_priv->debug_log, "[%10lu] %s",
(jiffies / HZ), tmp_log_buf);
va_end(args);
@@ -114,7 +115,7 @@
!(debug_log->log_end - debug_log->log_start))
return -EAGAIN;
- if ((!buf) || (count < 0))
+ if (!buf)
return -EINVAL;
if (count == 0)
@@ -184,7 +185,7 @@
if (!bat_priv->debug_dir)
goto err;
- bat_priv->debug_log = kzalloc(sizeof(struct debug_log), GFP_ATOMIC);
+ bat_priv->debug_log = kzalloc(sizeof(*bat_priv->debug_log), GFP_ATOMIC);
if (!bat_priv->debug_log)
goto err;
diff --git a/net/batman-adv/bat_sysfs.c b/net/batman-adv/bat_sysfs.c
index 497a070..cd15deb 100644
--- a/net/batman-adv/bat_sysfs.c
+++ b/net/batman-adv/bat_sysfs.c
@@ -28,9 +28,31 @@
#include "gateway_client.h"
#include "vis.h"
-#define to_dev(obj) container_of(obj, struct device, kobj)
-#define kobj_to_netdev(obj) to_net_dev(to_dev(obj->parent))
-#define kobj_to_batpriv(obj) netdev_priv(kobj_to_netdev(obj))
+static struct net_device *kobj_to_netdev(struct kobject *obj)
+{
+ struct device *dev = container_of(obj->parent, struct device, kobj);
+ return to_net_dev(dev);
+}
+
+static struct bat_priv *kobj_to_batpriv(struct kobject *obj)
+{
+ struct net_device *net_dev = kobj_to_netdev(obj);
+ return netdev_priv(net_dev);
+}
+
+#define UEV_TYPE_VAR "BATTYPE="
+#define UEV_ACTION_VAR "BATACTION="
+#define UEV_DATA_VAR "BATDATA="
+
+static char *uev_action_str[] = {
+ "add",
+ "del",
+ "change"
+};
+
+static char *uev_type_str[] = {
+ "gw"
+};
/* Use this, if you have customized show and store functions */
#define BAT_ATTR(_name, _mode, _show, _store) \
@@ -96,7 +118,7 @@
static int store_bool_attr(char *buff, size_t count,
struct net_device *net_dev,
- char *attr_name, atomic_t *attr)
+ const char *attr_name, atomic_t *attr)
{
int enabled = -1;
@@ -138,16 +160,15 @@
{
int ret;
- ret = store_bool_attr(buff, count, net_dev, (char *)attr->name,
- attr_store);
+ ret = store_bool_attr(buff, count, net_dev, attr->name, attr_store);
if (post_func && ret)
post_func(net_dev);
return ret;
}
-static int store_uint_attr(char *buff, size_t count,
- struct net_device *net_dev, char *attr_name,
+static int store_uint_attr(const char *buff, size_t count,
+ struct net_device *net_dev, const char *attr_name,
unsigned int min, unsigned int max, atomic_t *attr)
{
unsigned long uint_val;
@@ -183,15 +204,15 @@
return count;
}
-static inline ssize_t __store_uint_attr(char *buff, size_t count,
+static inline ssize_t __store_uint_attr(const char *buff, size_t count,
int min, int max,
void (*post_func)(struct net_device *),
- struct attribute *attr,
+ const struct attribute *attr,
atomic_t *attr_store, struct net_device *net_dev)
{
int ret;
- ret = store_uint_attr(buff, count, net_dev, (char *)attr->name,
+ ret = store_uint_attr(buff, count, net_dev, attr->name,
min, max, attr_store);
if (post_func && ret)
post_func(net_dev);
@@ -368,7 +389,7 @@
static BAT_ATTR(gw_bandwidth, S_IRUGO | S_IWUSR, show_gw_bwidth,
store_gw_bwidth);
#ifdef CONFIG_BATMAN_ADV_DEBUG
-BAT_ATTR_UINT(log_level, S_IRUGO | S_IWUSR, 0, 3, NULL);
+BAT_ATTR_UINT(log_level, S_IRUGO | S_IWUSR, 0, 7, NULL);
#endif
static struct bat_attribute *mesh_attrs[] = {
@@ -594,3 +615,60 @@
kobject_put(*hardif_obj);
*hardif_obj = NULL;
}
+
+int throw_uevent(struct bat_priv *bat_priv, enum uev_type type,
+ enum uev_action action, const char *data)
+{
+ int ret = -1;
+ struct hard_iface *primary_if = NULL;
+ struct kobject *bat_kobj;
+ char *uevent_env[4] = { NULL, NULL, NULL, NULL };
+
+ primary_if = primary_if_get_selected(bat_priv);
+ if (!primary_if)
+ goto out;
+
+ bat_kobj = &primary_if->soft_iface->dev.kobj;
+
+ uevent_env[0] = kmalloc(strlen(UEV_TYPE_VAR) +
+ strlen(uev_type_str[type]) + 1,
+ GFP_ATOMIC);
+ if (!uevent_env[0])
+ goto out;
+
+ sprintf(uevent_env[0], "%s%s", UEV_TYPE_VAR, uev_type_str[type]);
+
+ uevent_env[1] = kmalloc(strlen(UEV_ACTION_VAR) +
+ strlen(uev_action_str[action]) + 1,
+ GFP_ATOMIC);
+ if (!uevent_env[1])
+ goto out;
+
+ sprintf(uevent_env[1], "%s%s", UEV_ACTION_VAR, uev_action_str[action]);
+
+ /* If the event is DEL, ignore the data field */
+ if (action != UEV_DEL) {
+ uevent_env[2] = kmalloc(strlen(UEV_DATA_VAR) +
+ strlen(data) + 1, GFP_ATOMIC);
+ if (!uevent_env[2])
+ goto out;
+
+ sprintf(uevent_env[2], "%s%s", UEV_DATA_VAR, data);
+ }
+
+ ret = kobject_uevent_env(bat_kobj, KOBJ_CHANGE, uevent_env);
+out:
+ kfree(uevent_env[0]);
+ kfree(uevent_env[1]);
+ kfree(uevent_env[2]);
+
+ if (primary_if)
+ hardif_free_ref(primary_if);
+
+ if (ret)
+ bat_dbg(DBG_BATMAN, bat_priv, "Impossible to send "
+ "uevent for (%s,%s,%s) event (err: %d)\n",
+ uev_type_str[type], uev_action_str[action],
+ (action == UEV_DEL ? "NULL" : data), ret);
+ return ret;
+}
diff --git a/net/batman-adv/bat_sysfs.h b/net/batman-adv/bat_sysfs.h
index 02f1fa7..a3f75a7 100644
--- a/net/batman-adv/bat_sysfs.h
+++ b/net/batman-adv/bat_sysfs.h
@@ -38,5 +38,7 @@
void sysfs_del_meshif(struct net_device *dev);
int sysfs_add_hardif(struct kobject **hardif_obj, struct net_device *dev);
void sysfs_del_hardif(struct kobject **hardif_obj);
+int throw_uevent(struct bat_priv *bat_priv, enum uev_type type,
+ enum uev_action action, const char *data);
#endif /* _NET_BATMAN_ADV_SYSFS_H_ */
diff --git a/net/batman-adv/bitarray.c b/net/batman-adv/bitarray.c
index ad2ca92..c1f4bfc 100644
--- a/net/batman-adv/bitarray.c
+++ b/net/batman-adv/bitarray.c
@@ -26,8 +26,8 @@
/* returns true if the corresponding bit in the given seq_bits indicates true
* and curr_seqno is within range of last_seqno */
-uint8_t get_bit_status(unsigned long *seq_bits, uint32_t last_seqno,
- uint32_t curr_seqno)
+int get_bit_status(const unsigned long *seq_bits, uint32_t last_seqno,
+ uint32_t curr_seqno)
{
int32_t diff, word_offset, word_num;
@@ -127,10 +127,10 @@
* 1 if the window was moved (either new or very old)
* 0 if the window was not moved/shifted.
*/
-char bit_get_packet(void *priv, unsigned long *seq_bits,
- int32_t seq_num_diff, int8_t set_mark)
+int bit_get_packet(void *priv, unsigned long *seq_bits,
+ int32_t seq_num_diff, int set_mark)
{
- struct bat_priv *bat_priv = (struct bat_priv *)priv;
+ struct bat_priv *bat_priv = priv;
/* sequence number is slightly older. We already got a sequence number
* higher than this one, so we just mark it. */
@@ -190,7 +190,7 @@
/* count the hamming weight, how many good packets did we receive? just count
* the 1's.
*/
-int bit_packet_count(unsigned long *seq_bits)
+int bit_packet_count(const unsigned long *seq_bits)
{
int i, hamming = 0;
diff --git a/net/batman-adv/bitarray.h b/net/batman-adv/bitarray.h
index 769c246..9c04422 100644
--- a/net/batman-adv/bitarray.h
+++ b/net/batman-adv/bitarray.h
@@ -26,8 +26,8 @@
/* returns true if the corresponding bit in the given seq_bits indicates true
* and curr_seqno is within range of last_seqno */
-uint8_t get_bit_status(unsigned long *seq_bits, uint32_t last_seqno,
- uint32_t curr_seqno);
+int get_bit_status(const unsigned long *seq_bits, uint32_t last_seqno,
+ uint32_t curr_seqno);
/* turn corresponding bit on, so we can remember that we got the packet */
void bit_mark(unsigned long *seq_bits, int32_t n);
@@ -35,10 +35,10 @@
/* receive and process one packet, returns 1 if received seq_num is considered
* new, 0 if old */
-char bit_get_packet(void *priv, unsigned long *seq_bits,
- int32_t seq_num_diff, int8_t set_mark);
+int bit_get_packet(void *priv, unsigned long *seq_bits,
+ int32_t seq_num_diff, int set_mark);
/* count the hamming weight, how many good packets did we receive? */
-int bit_packet_count(unsigned long *seq_bits);
+int bit_packet_count(const unsigned long *seq_bits);
#endif /* _NET_BATMAN_ADV_BITARRAY_H_ */
diff --git a/net/batman-adv/gateway_client.c b/net/batman-adv/gateway_client.c
index 61605a0..056180e 100644
--- a/net/batman-adv/gateway_client.c
+++ b/net/batman-adv/gateway_client.c
@@ -20,15 +20,22 @@
*/
#include "main.h"
+#include "bat_sysfs.h"
#include "gateway_client.h"
#include "gateway_common.h"
#include "hard-interface.h"
#include "originator.h"
+#include "routing.h"
#include <linux/ip.h>
#include <linux/ipv6.h>
#include <linux/udp.h>
#include <linux/if_vlan.h>
+/* This is the offset of the options field in a dhcp packet starting at
+ * the beginning of the dhcp header */
+#define DHCP_OPTIONS_OFFSET 240
+#define DHCP_REQUEST 3
+
static void gw_node_free_ref(struct gw_node *gw_node)
{
if (atomic_dec_and_test(&gw_node->refcount))
@@ -86,7 +93,7 @@
if (new_gw_node && !atomic_inc_not_zero(&new_gw_node->refcount))
new_gw_node = NULL;
- curr_gw_node = bat_priv->curr_gw;
+ curr_gw_node = rcu_dereference_protected(bat_priv->curr_gw, 1);
rcu_assign_pointer(bat_priv->curr_gw, new_gw_node);
if (curr_gw_node)
@@ -97,40 +104,19 @@
void gw_deselect(struct bat_priv *bat_priv)
{
- gw_select(bat_priv, NULL);
+ atomic_set(&bat_priv->gw_reselect, 1);
}
-void gw_election(struct bat_priv *bat_priv)
+static struct gw_node *gw_get_best_gw_node(struct bat_priv *bat_priv)
{
- struct hlist_node *node;
- struct gw_node *gw_node, *curr_gw = NULL, *curr_gw_tmp = NULL;
struct neigh_node *router;
- uint8_t max_tq = 0;
+ struct hlist_node *node;
+ struct gw_node *gw_node, *curr_gw = NULL;
uint32_t max_gw_factor = 0, tmp_gw_factor = 0;
+ uint8_t max_tq = 0;
int down, up;
- /**
- * The batman daemon checks here if we already passed a full originator
- * cycle in order to make sure we don't choose the first gateway we
- * hear about. This check is based on the daemon's uptime which we
- * don't have.
- **/
- if (atomic_read(&bat_priv->gw_mode) != GW_MODE_CLIENT)
- return;
-
- curr_gw = gw_get_selected_gw_node(bat_priv);
- if (curr_gw)
- goto out;
-
rcu_read_lock();
- if (hlist_empty(&bat_priv->gw_list)) {
- bat_dbg(DBG_BATMAN, bat_priv,
- "Removing selected gateway - "
- "no gateway in range\n");
- gw_deselect(bat_priv);
- goto unlock;
- }
-
hlist_for_each_entry_rcu(gw_node, node, &bat_priv->gw_list, list) {
if (gw_node->deleted)
continue;
@@ -139,6 +125,9 @@
if (!router)
continue;
+ if (!atomic_inc_not_zero(&gw_node->refcount))
+ goto next;
+
switch (atomic_read(&bat_priv->gw_sel_class)) {
case 1: /* fast connection */
gw_bandwidth_to_kbit(gw_node->orig_node->gw_flags,
@@ -151,8 +140,12 @@
if ((tmp_gw_factor > max_gw_factor) ||
((tmp_gw_factor == max_gw_factor) &&
- (router->tq_avg > max_tq)))
- curr_gw_tmp = gw_node;
+ (router->tq_avg > max_tq))) {
+ if (curr_gw)
+ gw_node_free_ref(curr_gw);
+ curr_gw = gw_node;
+ atomic_inc(&curr_gw->refcount);
+ }
break;
default: /**
@@ -163,8 +156,12 @@
* soon as a better gateway appears which has
* $routing_class more tq points)
**/
- if (router->tq_avg > max_tq)
- curr_gw_tmp = gw_node;
+ if (router->tq_avg > max_tq) {
+ if (curr_gw)
+ gw_node_free_ref(curr_gw);
+ curr_gw = gw_node;
+ atomic_inc(&curr_gw->refcount);
+ }
break;
}
@@ -174,42 +171,81 @@
if (tmp_gw_factor > max_gw_factor)
max_gw_factor = tmp_gw_factor;
+ gw_node_free_ref(gw_node);
+
+next:
neigh_node_free_ref(router);
}
-
- if (curr_gw != curr_gw_tmp) {
- router = orig_node_get_router(curr_gw_tmp->orig_node);
- if (!router)
- goto unlock;
-
- if ((curr_gw) && (!curr_gw_tmp))
- bat_dbg(DBG_BATMAN, bat_priv,
- "Removing selected gateway - "
- "no gateway in range\n");
- else if ((!curr_gw) && (curr_gw_tmp))
- bat_dbg(DBG_BATMAN, bat_priv,
- "Adding route to gateway %pM "
- "(gw_flags: %i, tq: %i)\n",
- curr_gw_tmp->orig_node->orig,
- curr_gw_tmp->orig_node->gw_flags,
- router->tq_avg);
- else
- bat_dbg(DBG_BATMAN, bat_priv,
- "Changing route to gateway %pM "
- "(gw_flags: %i, tq: %i)\n",
- curr_gw_tmp->orig_node->orig,
- curr_gw_tmp->orig_node->gw_flags,
- router->tq_avg);
-
- neigh_node_free_ref(router);
- gw_select(bat_priv, curr_gw_tmp);
- }
-
-unlock:
rcu_read_unlock();
+
+ return curr_gw;
+}
+
+void gw_election(struct bat_priv *bat_priv)
+{
+ struct gw_node *curr_gw = NULL, *next_gw = NULL;
+ struct neigh_node *router = NULL;
+ char gw_addr[18] = { '\0' };
+
+ /**
+ * The batman daemon checks here if we already passed a full originator
+ * cycle in order to make sure we don't choose the first gateway we
+ * hear about. This check is based on the daemon's uptime which we
+ * don't have.
+ **/
+ if (atomic_read(&bat_priv->gw_mode) != GW_MODE_CLIENT)
+ goto out;
+
+ if (!atomic_dec_not_zero(&bat_priv->gw_reselect))
+ goto out;
+
+ curr_gw = gw_get_selected_gw_node(bat_priv);
+
+ next_gw = gw_get_best_gw_node(bat_priv);
+
+ if (curr_gw == next_gw)
+ goto out;
+
+ if (next_gw) {
+ sprintf(gw_addr, "%pM", next_gw->orig_node->orig);
+
+ router = orig_node_get_router(next_gw->orig_node);
+ if (!router) {
+ gw_deselect(bat_priv);
+ goto out;
+ }
+ }
+
+ if ((curr_gw) && (!next_gw)) {
+ bat_dbg(DBG_BATMAN, bat_priv,
+ "Removing selected gateway - no gateway in range\n");
+ throw_uevent(bat_priv, UEV_GW, UEV_DEL, NULL);
+ } else if ((!curr_gw) && (next_gw)) {
+ bat_dbg(DBG_BATMAN, bat_priv,
+ "Adding route to gateway %pM (gw_flags: %i, tq: %i)\n",
+ next_gw->orig_node->orig,
+ next_gw->orig_node->gw_flags,
+ router->tq_avg);
+ throw_uevent(bat_priv, UEV_GW, UEV_ADD, gw_addr);
+ } else {
+ bat_dbg(DBG_BATMAN, bat_priv,
+ "Changing route to gateway %pM "
+ "(gw_flags: %i, tq: %i)\n",
+ next_gw->orig_node->orig,
+ next_gw->orig_node->gw_flags,
+ router->tq_avg);
+ throw_uevent(bat_priv, UEV_GW, UEV_CHANGE, gw_addr);
+ }
+
+ gw_select(bat_priv, next_gw);
+
out:
if (curr_gw)
gw_node_free_ref(curr_gw);
+ if (next_gw)
+ gw_node_free_ref(next_gw);
+ if (router)
+ neigh_node_free_ref(router);
}
void gw_check_election(struct bat_priv *bat_priv, struct orig_node *orig_node)
@@ -273,11 +309,10 @@
struct gw_node *gw_node;
int down, up;
- gw_node = kmalloc(sizeof(struct gw_node), GFP_ATOMIC);
+ gw_node = kzalloc(sizeof(*gw_node), GFP_ATOMIC);
if (!gw_node)
return;
- memset(gw_node, 0, sizeof(struct gw_node));
INIT_HLIST_NODE(&gw_node->list);
gw_node->orig_node = orig_node;
atomic_set(&gw_node->refcount, 1);
@@ -323,7 +358,7 @@
gw_node->deleted = 0;
- if (new_gwflags == 0) {
+ if (new_gwflags == NO_FLAGS) {
gw_node->deleted = jiffies;
bat_dbg(DBG_BATMAN, bat_priv,
"Gateway %pM removed from gateway list\n",
@@ -336,7 +371,7 @@
goto unlock;
}
- if (new_gwflags == 0)
+ if (new_gwflags == NO_FLAGS)
goto unlock;
gw_node_add(bat_priv, orig_node, new_gwflags);
@@ -353,7 +388,7 @@
void gw_node_delete(struct bat_priv *bat_priv, struct orig_node *orig_node)
{
- return gw_node_update(bat_priv, orig_node, 0);
+ gw_node_update(bat_priv, orig_node, 0);
}
void gw_node_purge(struct bat_priv *bat_priv)
@@ -361,7 +396,7 @@
struct gw_node *gw_node, *curr_gw;
struct hlist_node *node, *node_tmp;
unsigned long timeout = 2 * PURGE_TIMEOUT * HZ;
- char do_deselect = 0;
+ int do_deselect = 0;
curr_gw = gw_get_selected_gw_node(bat_priv);
@@ -394,8 +429,8 @@
/**
* fails if orig_node has no router
*/
-static int _write_buffer_text(struct bat_priv *bat_priv,
- struct seq_file *seq, struct gw_node *gw_node)
+static int _write_buffer_text(struct bat_priv *bat_priv, struct seq_file *seq,
+ const struct gw_node *gw_node)
{
struct gw_node *curr_gw;
struct neigh_node *router;
@@ -452,10 +487,9 @@
}
seq_printf(seq, " %-12s (%s/%i) %17s [%10s]: gw_class ... "
- "[B.A.T.M.A.N. adv %s%s, MainIF/MAC: %s/%pM (%s)]\n",
+ "[B.A.T.M.A.N. adv %s, MainIF/MAC: %s/%pM (%s)]\n",
"Gateway", "#", TQ_MAX_VALUE, "Nexthop",
- "outgoingIF", SOURCE_VERSION, REVISION_VERSION_STR,
- primary_if->net_dev->name,
+ "outgoingIF", SOURCE_VERSION, primary_if->net_dev->name,
primary_if->net_dev->dev_addr, net_dev->name);
rcu_read_lock();
@@ -480,14 +514,75 @@
return ret;
}
-int gw_is_target(struct bat_priv *bat_priv, struct sk_buff *skb)
+static bool is_type_dhcprequest(struct sk_buff *skb, int header_len)
+{
+ int ret = false;
+ unsigned char *p;
+ int pkt_len;
+
+ if (skb_linearize(skb) < 0)
+ goto out;
+
+ pkt_len = skb_headlen(skb);
+
+ if (pkt_len < header_len + DHCP_OPTIONS_OFFSET + 1)
+ goto out;
+
+ p = skb->data + header_len + DHCP_OPTIONS_OFFSET;
+ pkt_len -= header_len + DHCP_OPTIONS_OFFSET + 1;
+
+ /* Access the dhcp option lists. Each entry is made up by:
+ * - octect 1: option type
+ * - octect 2: option data len (only if type != 255 and 0)
+ * - octect 3: option data */
+ while (*p != 255 && !ret) {
+ /* p now points to the first octect: option type */
+ if (*p == 53) {
+ /* type 53 is the message type option.
+ * Jump the len octect and go to the data octect */
+ if (pkt_len < 2)
+ goto out;
+ p += 2;
+
+ /* check if the message type is what we need */
+ if (*p == DHCP_REQUEST)
+ ret = true;
+ break;
+ } else if (*p == 0) {
+ /* option type 0 (padding), just go forward */
+ if (pkt_len < 1)
+ goto out;
+ pkt_len--;
+ p++;
+ } else {
+ /* This is any other option. So we get the length... */
+ if (pkt_len < 1)
+ goto out;
+ pkt_len--;
+ p++;
+
+ /* ...and then we jump over the data */
+ if (pkt_len < *p)
+ goto out;
+ pkt_len -= *p;
+ p += (*p);
+ }
+ }
+out:
+ return ret;
+}
+
+int gw_is_target(struct bat_priv *bat_priv, struct sk_buff *skb,
+ struct orig_node *old_gw)
{
struct ethhdr *ethhdr;
struct iphdr *iphdr;
struct ipv6hdr *ipv6hdr;
struct udphdr *udphdr;
struct gw_node *curr_gw;
+ struct neigh_node *neigh_curr = NULL, *neigh_old = NULL;
unsigned int header_len = 0;
+ int ret = 1;
if (atomic_read(&bat_priv->gw_mode) == GW_MODE_OFF)
return 0;
@@ -509,7 +604,7 @@
/* check for ip header */
switch (ntohs(ethhdr->h_proto)) {
case ETH_P_IP:
- if (!pskb_may_pull(skb, header_len + sizeof(struct iphdr)))
+ if (!pskb_may_pull(skb, header_len + sizeof(*iphdr)))
return 0;
iphdr = (struct iphdr *)(skb->data + header_len);
header_len += iphdr->ihl * 4;
@@ -520,10 +615,10 @@
break;
case ETH_P_IPV6:
- if (!pskb_may_pull(skb, header_len + sizeof(struct ipv6hdr)))
+ if (!pskb_may_pull(skb, header_len + sizeof(*ipv6hdr)))
return 0;
ipv6hdr = (struct ipv6hdr *)(skb->data + header_len);
- header_len += sizeof(struct ipv6hdr);
+ header_len += sizeof(*ipv6hdr);
/* check for udp header */
if (ipv6hdr->nexthdr != IPPROTO_UDP)
@@ -534,10 +629,10 @@
return 0;
}
- if (!pskb_may_pull(skb, header_len + sizeof(struct udphdr)))
+ if (!pskb_may_pull(skb, header_len + sizeof(*udphdr)))
return 0;
udphdr = (struct udphdr *)(skb->data + header_len);
- header_len += sizeof(struct udphdr);
+ header_len += sizeof(*udphdr);
/* check for bootp port */
if ((ntohs(ethhdr->h_proto) == ETH_P_IP) &&
@@ -555,7 +650,30 @@
if (!curr_gw)
return 0;
+ /* If old_gw != NULL then this packet is unicast.
+ * So, at this point we have to check the message type: if it is a
+ * DHCPREQUEST we have to decide whether to drop it or not */
+ if (old_gw && curr_gw->orig_node != old_gw) {
+ if (is_type_dhcprequest(skb, header_len)) {
+ /* If the dhcp packet has been sent to a different gw,
+ * we have to evaluate whether the old gw is still
+ * reliable enough */
+ neigh_curr = find_router(bat_priv, curr_gw->orig_node,
+ NULL);
+ neigh_old = find_router(bat_priv, old_gw, NULL);
+ if (!neigh_curr || !neigh_old)
+ goto free_neigh;
+ if (neigh_curr->tq_avg - neigh_old->tq_avg <
+ GW_THRESHOLD)
+ ret = -1;
+ }
+ }
+free_neigh:
+ if (neigh_old)
+ neigh_node_free_ref(neigh_old);
+ if (neigh_curr)
+ neigh_node_free_ref(neigh_curr);
if (curr_gw)
gw_node_free_ref(curr_gw);
- return 1;
+ return ret;
}
diff --git a/net/batman-adv/gateway_client.h b/net/batman-adv/gateway_client.h
index 1ce8c60..b9b983c 100644
--- a/net/batman-adv/gateway_client.h
+++ b/net/batman-adv/gateway_client.h
@@ -31,6 +31,7 @@
void gw_node_delete(struct bat_priv *bat_priv, struct orig_node *orig_node);
void gw_node_purge(struct bat_priv *bat_priv);
int gw_client_seq_print_text(struct seq_file *seq, void *offset);
-int gw_is_target(struct bat_priv *bat_priv, struct sk_buff *skb);
+int gw_is_target(struct bat_priv *bat_priv, struct sk_buff *skb,
+ struct orig_node *old_gw);
#endif /* _NET_BATMAN_ADV_GATEWAY_CLIENT_H_ */
diff --git a/net/batman-adv/gateway_common.c b/net/batman-adv/gateway_common.c
index 50d3a59..18661af 100644
--- a/net/batman-adv/gateway_common.c
+++ b/net/batman-adv/gateway_common.c
@@ -61,9 +61,9 @@
/* returns the up and downspeeds in kbit, calculated from the class */
void gw_bandwidth_to_kbit(uint8_t gw_srv_class, int *down, int *up)
{
- char sbit = (gw_srv_class & 0x80) >> 7;
- char dpart = (gw_srv_class & 0x78) >> 3;
- char upart = (gw_srv_class & 0x07);
+ int sbit = (gw_srv_class & 0x80) >> 7;
+ int dpart = (gw_srv_class & 0x78) >> 3;
+ int upart = (gw_srv_class & 0x07);
if (!gw_srv_class) {
*down = 0;
@@ -76,10 +76,11 @@
}
static bool parse_gw_bandwidth(struct net_device *net_dev, char *buff,
- long *up, long *down)
+ int *up, int *down)
{
int ret, multi = 1;
char *slash_ptr, *tmp_ptr;
+ long ldown, lup;
slash_ptr = strchr(buff, '/');
if (slash_ptr)
@@ -96,7 +97,7 @@
*tmp_ptr = '\0';
}
- ret = strict_strtoul(buff, 10, down);
+ ret = strict_strtol(buff, 10, &ldown);
if (ret) {
bat_err(net_dev,
"Download speed of gateway mode invalid: %s\n",
@@ -104,7 +105,7 @@
return false;
}
- *down *= multi;
+ *down = ldown * multi;
/* we also got some upload info */
if (slash_ptr) {
@@ -121,7 +122,7 @@
*tmp_ptr = '\0';
}
- ret = strict_strtoul(slash_ptr + 1, 10, up);
+ ret = strict_strtol(slash_ptr + 1, 10, &lup);
if (ret) {
bat_err(net_dev,
"Upload speed of gateway mode invalid: "
@@ -129,7 +130,7 @@
return false;
}
- *up *= multi;
+ *up = lup * multi;
}
return true;
@@ -138,7 +139,8 @@
ssize_t gw_bandwidth_set(struct net_device *net_dev, char *buff, size_t count)
{
struct bat_priv *bat_priv = netdev_priv(net_dev);
- long gw_bandwidth_tmp = 0, up = 0, down = 0;
+ long gw_bandwidth_tmp = 0;
+ int up = 0, down = 0;
bool ret;
ret = parse_gw_bandwidth(net_dev, buff, &up, &down);
@@ -158,12 +160,11 @@
* speeds, hence we need to calculate it back to show the number
* that is going to be propagated
**/
- gw_bandwidth_to_kbit((uint8_t)gw_bandwidth_tmp,
- (int *)&down, (int *)&up);
+ gw_bandwidth_to_kbit((uint8_t)gw_bandwidth_tmp, &down, &up);
gw_deselect(bat_priv);
bat_info(net_dev, "Changing gateway bandwidth from: '%i' to: '%ld' "
- "(propagating: %ld%s/%ld%s)\n",
+ "(propagating: %d%s/%d%s)\n",
atomic_read(&bat_priv->gw_bandwidth), gw_bandwidth_tmp,
(down > 2048 ? down / 1024 : down),
(down > 2048 ? "MBit" : "KBit"),
diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c
index dfbfccc..db7aacf 100644
--- a/net/batman-adv/hard-interface.c
+++ b/net/batman-adv/hard-interface.c
@@ -46,7 +46,7 @@
kfree(hard_iface);
}
-struct hard_iface *hardif_get_by_netdev(struct net_device *net_dev)
+struct hard_iface *hardif_get_by_netdev(const struct net_device *net_dev)
{
struct hard_iface *hard_iface;
@@ -64,7 +64,7 @@
return hard_iface;
}
-static int is_valid_iface(struct net_device *net_dev)
+static int is_valid_iface(const struct net_device *net_dev)
{
if (net_dev->flags & IFF_LOOPBACK)
return 0;
@@ -86,7 +86,7 @@
return 1;
}
-static struct hard_iface *hardif_get_active(struct net_device *soft_iface)
+static struct hard_iface *hardif_get_active(const struct net_device *soft_iface)
{
struct hard_iface *hard_iface;
@@ -138,7 +138,7 @@
if (new_hard_iface && !atomic_inc_not_zero(&new_hard_iface->refcount))
new_hard_iface = NULL;
- curr_hard_iface = bat_priv->primary_if;
+ curr_hard_iface = rcu_dereference_protected(bat_priv->primary_if, 1);
rcu_assign_pointer(bat_priv->primary_if, new_hard_iface);
if (curr_hard_iface)
@@ -152,15 +152,9 @@
batman_packet->ttl = TTL;
primary_if_update_addr(bat_priv);
-
- /***
- * hacky trick to make sure that we send the TT information via
- * our new primary interface
- */
- atomic_set(&bat_priv->tt_local_changed, 1);
}
-static bool hardif_is_iface_up(struct hard_iface *hard_iface)
+static bool hardif_is_iface_up(const struct hard_iface *hard_iface)
{
if (hard_iface->net_dev->flags & IFF_UP)
return true;
@@ -176,9 +170,9 @@
hard_iface->net_dev->dev_addr, ETH_ALEN);
}
-static void check_known_mac_addr(struct net_device *net_dev)
+static void check_known_mac_addr(const struct net_device *net_dev)
{
- struct hard_iface *hard_iface;
+ const struct hard_iface *hard_iface;
rcu_read_lock();
list_for_each_entry_rcu(hard_iface, &hardif_list, list) {
@@ -204,8 +198,8 @@
int hardif_min_mtu(struct net_device *soft_iface)
{
- struct bat_priv *bat_priv = netdev_priv(soft_iface);
- struct hard_iface *hard_iface;
+ const struct bat_priv *bat_priv = netdev_priv(soft_iface);
+ const struct hard_iface *hard_iface;
/* allow big frames if all devices are capable to do so
* (have MTU > 1500 + BAT_HEADER_LEN) */
int min_mtu = ETH_DATA_LEN;
@@ -285,7 +279,8 @@
update_min_mtu(hard_iface->soft_iface);
}
-int hardif_enable_interface(struct hard_iface *hard_iface, char *iface_name)
+int hardif_enable_interface(struct hard_iface *hard_iface,
+ const char *iface_name)
{
struct bat_priv *bat_priv;
struct batman_packet *batman_packet;
@@ -336,10 +331,11 @@
batman_packet = (struct batman_packet *)(hard_iface->packet_buff);
batman_packet->packet_type = BAT_PACKET;
batman_packet->version = COMPAT_VERSION;
- batman_packet->flags = 0;
+ batman_packet->flags = NO_FLAGS;
batman_packet->ttl = 2;
batman_packet->tq = TQ_MAX_VALUE;
- batman_packet->num_tt = 0;
+ batman_packet->tt_num_changes = 0;
+ batman_packet->ttvn = 0;
hard_iface->if_num = bat_priv->num_ifaces;
bat_priv->num_ifaces++;
@@ -458,7 +454,7 @@
dev_hold(net_dev);
- hard_iface = kmalloc(sizeof(struct hard_iface), GFP_ATOMIC);
+ hard_iface = kmalloc(sizeof(*hard_iface), GFP_ATOMIC);
if (!hard_iface) {
pr_err("Can't add interface (%s): out of memory\n",
net_dev->name);
@@ -522,7 +518,7 @@
static int hard_if_event(struct notifier_block *this,
unsigned long event, void *ptr)
{
- struct net_device *net_dev = (struct net_device *)ptr;
+ struct net_device *net_dev = ptr;
struct hard_iface *hard_iface = hardif_get_by_netdev(net_dev);
struct hard_iface *primary_if = NULL;
struct bat_priv *bat_priv;
@@ -567,7 +563,7 @@
break;
default:
break;
- };
+ }
hardif_put:
hardif_free_ref(hard_iface);
@@ -658,6 +654,14 @@
case BAT_VIS:
ret = recv_vis_packet(skb, hard_iface);
break;
+ /* Translation table query (request or response) */
+ case BAT_TT_QUERY:
+ ret = recv_tt_query(skb, hard_iface);
+ break;
+ /* Roaming advertisement */
+ case BAT_ROAM_ADV:
+ ret = recv_roam_adv(skb, hard_iface);
+ break;
default:
ret = NET_RX_DROP;
}
diff --git a/net/batman-adv/hard-interface.h b/net/batman-adv/hard-interface.h
index 6426599..442eacb 100644
--- a/net/batman-adv/hard-interface.h
+++ b/net/batman-adv/hard-interface.h
@@ -22,17 +22,21 @@
#ifndef _NET_BATMAN_ADV_HARD_INTERFACE_H_
#define _NET_BATMAN_ADV_HARD_INTERFACE_H_
-#define IF_NOT_IN_USE 0
-#define IF_TO_BE_REMOVED 1
-#define IF_INACTIVE 2
-#define IF_ACTIVE 3
-#define IF_TO_BE_ACTIVATED 4
-#define IF_I_WANT_YOU 5
+enum hard_if_state {
+ IF_NOT_IN_USE,
+ IF_TO_BE_REMOVED,
+ IF_INACTIVE,
+ IF_ACTIVE,
+ IF_TO_BE_ACTIVATED,
+ IF_I_WANT_YOU
+};
extern struct notifier_block hard_if_notifier;
-struct hard_iface *hardif_get_by_netdev(struct net_device *net_dev);
-int hardif_enable_interface(struct hard_iface *hard_iface, char *iface_name);
+struct hard_iface*
+hardif_get_by_netdev(const struct net_device *net_dev);
+int hardif_enable_interface(struct hard_iface *hard_iface,
+ const char *iface_name);
void hardif_disable_interface(struct hard_iface *hard_iface);
void hardif_remove_interfaces(void);
int hardif_min_mtu(struct net_device *soft_iface);
diff --git a/net/batman-adv/hash.c b/net/batman-adv/hash.c
index c5213d8..2a17250 100644
--- a/net/batman-adv/hash.c
+++ b/net/batman-adv/hash.c
@@ -46,15 +46,16 @@
{
struct hashtable_t *hash;
- hash = kmalloc(sizeof(struct hashtable_t), GFP_ATOMIC);
+ hash = kmalloc(sizeof(*hash), GFP_ATOMIC);
if (!hash)
return NULL;
- hash->table = kmalloc(sizeof(struct element_t *) * size, GFP_ATOMIC);
+ hash->table = kmalloc(sizeof(*hash->table) * size, GFP_ATOMIC);
if (!hash->table)
goto free_hash;
- hash->list_locks = kmalloc(sizeof(spinlock_t) * size, GFP_ATOMIC);
+ hash->list_locks = kmalloc(sizeof(*hash->list_locks) * size,
+ GFP_ATOMIC);
if (!hash->list_locks)
goto free_table;
diff --git a/net/batman-adv/hash.h b/net/batman-adv/hash.h
index 434822b..dd5c9fd 100644
--- a/net/batman-adv/hash.h
+++ b/net/batman-adv/hash.h
@@ -28,12 +28,12 @@
* compare 2 element datas for their keys,
* return 0 if same and not 0 if not
* same */
-typedef int (*hashdata_compare_cb)(struct hlist_node *, void *);
+typedef int (*hashdata_compare_cb)(const struct hlist_node *, const void *);
/* the hashfunction, should return an index
* based on the key in the data of the first
* argument and the size the second */
-typedef int (*hashdata_choose_cb)(void *, int);
+typedef int (*hashdata_choose_cb)(const void *, int);
typedef void (*hashdata_free_cb)(struct hlist_node *, void *);
struct hashtable_t {
@@ -80,7 +80,7 @@
static inline int hash_add(struct hashtable_t *hash,
hashdata_compare_cb compare,
hashdata_choose_cb choose,
- void *data, struct hlist_node *data_node)
+ const void *data, struct hlist_node *data_node)
{
int index;
struct hlist_head *head;
diff --git a/net/batman-adv/icmp_socket.c b/net/batman-adv/icmp_socket.c
index fa22ba2..ac3520e 100644
--- a/net/batman-adv/icmp_socket.c
+++ b/net/batman-adv/icmp_socket.c
@@ -46,7 +46,7 @@
nonseekable_open(inode, file);
- socket_client = kmalloc(sizeof(struct socket_client), GFP_KERNEL);
+ socket_client = kmalloc(sizeof(*socket_client), GFP_KERNEL);
if (!socket_client)
return -ENOMEM;
@@ -310,7 +310,7 @@
{
struct socket_packet *socket_packet;
- socket_packet = kmalloc(sizeof(struct socket_packet), GFP_ATOMIC);
+ socket_packet = kmalloc(sizeof(*socket_packet), GFP_ATOMIC);
if (!socket_packet)
return;
diff --git a/net/batman-adv/main.c b/net/batman-adv/main.c
index 0a7cee0..b0f9068 100644
--- a/net/batman-adv/main.c
+++ b/net/batman-adv/main.c
@@ -58,9 +58,8 @@
register_netdevice_notifier(&hard_if_notifier);
- pr_info("B.A.T.M.A.N. advanced %s%s (compatibility version %i) "
- "loaded\n", SOURCE_VERSION, REVISION_VERSION_STR,
- COMPAT_VERSION);
+ pr_info("B.A.T.M.A.N. advanced %s (compatibility version %i) "
+ "loaded\n", SOURCE_VERSION, COMPAT_VERSION);
return 0;
}
@@ -84,8 +83,10 @@
spin_lock_init(&bat_priv->forw_bat_list_lock);
spin_lock_init(&bat_priv->forw_bcast_list_lock);
- spin_lock_init(&bat_priv->tt_lhash_lock);
- spin_lock_init(&bat_priv->tt_ghash_lock);
+ spin_lock_init(&bat_priv->tt_changes_list_lock);
+ spin_lock_init(&bat_priv->tt_req_list_lock);
+ spin_lock_init(&bat_priv->tt_roam_list_lock);
+ spin_lock_init(&bat_priv->tt_buff_lock);
spin_lock_init(&bat_priv->gw_list_lock);
spin_lock_init(&bat_priv->vis_hash_lock);
spin_lock_init(&bat_priv->vis_list_lock);
@@ -96,14 +97,14 @@
INIT_HLIST_HEAD(&bat_priv->forw_bcast_list);
INIT_HLIST_HEAD(&bat_priv->gw_list);
INIT_HLIST_HEAD(&bat_priv->softif_neigh_vids);
+ INIT_LIST_HEAD(&bat_priv->tt_changes_list);
+ INIT_LIST_HEAD(&bat_priv->tt_req_list);
+ INIT_LIST_HEAD(&bat_priv->tt_roam_list);
if (originator_init(bat_priv) < 1)
goto err;
- if (tt_local_init(bat_priv) < 1)
- goto err;
-
- if (tt_global_init(bat_priv) < 1)
+ if (tt_init(bat_priv) < 1)
goto err;
tt_local_add(soft_iface, soft_iface->dev_addr);
@@ -111,6 +112,7 @@
if (vis_init(bat_priv) < 1)
goto err;
+ atomic_set(&bat_priv->gw_reselect, 0);
atomic_set(&bat_priv->mesh_state, MESH_ACTIVE);
goto end;
@@ -137,8 +139,7 @@
gw_node_purge(bat_priv);
originator_free(bat_priv);
- tt_local_free(bat_priv);
- tt_global_free(bat_priv);
+ tt_free(bat_priv);
softif_neigh_purge(bat_priv);
@@ -155,9 +156,9 @@
module_put(THIS_MODULE);
}
-int is_my_mac(uint8_t *addr)
+int is_my_mac(const uint8_t *addr)
{
- struct hard_iface *hard_iface;
+ const struct hard_iface *hard_iface;
rcu_read_lock();
list_for_each_entry_rcu(hard_iface, &hardif_list, list) {
@@ -182,8 +183,4 @@
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_SUPPORTED_DEVICE(DRIVER_DEVICE);
-#ifdef REVISION_VERSION
-MODULE_VERSION(SOURCE_VERSION "-" REVISION_VERSION);
-#else
MODULE_VERSION(SOURCE_VERSION);
-#endif
diff --git a/net/batman-adv/main.h b/net/batman-adv/main.h
index 148b49e..a6df61a 100644
--- a/net/batman-adv/main.h
+++ b/net/batman-adv/main.h
@@ -27,8 +27,9 @@
#define DRIVER_DESC "B.A.T.M.A.N. advanced"
#define DRIVER_DEVICE "batman-adv"
-#define SOURCE_VERSION "next"
-
+#ifndef SOURCE_VERSION
+#define SOURCE_VERSION "2011.3.0"
+#endif
/* B.A.T.M.A.N. parameters */
@@ -42,15 +43,25 @@
* -> TODO: check influence on TQ_LOCAL_WINDOW_SIZE */
#define PURGE_TIMEOUT 200
#define TT_LOCAL_TIMEOUT 3600 /* in seconds */
-
+#define TT_CLIENT_ROAM_TIMEOUT 600
/* sliding packet range of received originator messages in squence numbers
* (should be a multiple of our word size) */
#define TQ_LOCAL_WINDOW_SIZE 64
+#define TT_REQUEST_TIMEOUT 3 /* seconds we have to keep pending tt_req */
+
#define TQ_GLOBAL_WINDOW_SIZE 5
#define TQ_LOCAL_BIDRECT_SEND_MINIMUM 1
#define TQ_LOCAL_BIDRECT_RECV_MINIMUM 1
#define TQ_TOTAL_BIDRECT_LIMIT 1
+#define TT_OGM_APPEND_MAX 3 /* number of OGMs sent with the last tt diff */
+
+#define ROAMING_MAX_TIME 20 /* Time in which a client can roam at most
+ * ROAMING_MAX_COUNT times */
+#define ROAMING_MAX_COUNT 5
+
+#define NO_FLAGS 0
+
#define NUM_WORDS (TQ_LOCAL_WINDOW_SIZE / WORD_BIT_SIZE)
#define LOG_BUF_LEN 8192 /* has to be a power of 2 */
@@ -72,13 +83,27 @@
#define RESET_PROTECTION_MS 30000
#define EXPECTED_SEQNO_RANGE 65536
-#define MESH_INACTIVE 0
-#define MESH_ACTIVE 1
-#define MESH_DEACTIVATING 2
+enum mesh_state {
+ MESH_INACTIVE,
+ MESH_ACTIVE,
+ MESH_DEACTIVATING
+};
#define BCAST_QUEUE_LEN 256
#define BATMAN_QUEUE_LEN 256
+enum uev_action {
+ UEV_ADD = 0,
+ UEV_DEL,
+ UEV_CHANGE
+};
+
+enum uev_type {
+ UEV_GW = 0
+};
+
+#define GW_THRESHOLD 50
+
/*
* Debug Messages
*/
@@ -89,10 +114,12 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
/* all messages related to routing / flooding / broadcasting / etc */
-#define DBG_BATMAN 1
-/* route or tt entry added / changed / deleted */
-#define DBG_ROUTES 2
-#define DBG_ALL 3
+enum dbg_level {
+ DBG_BATMAN = 1 << 0,
+ DBG_ROUTES = 1 << 1, /* route added / changed / deleted */
+ DBG_TT = 1 << 2, /* translation table operations */
+ DBG_ALL = 7
+};
/*
@@ -118,12 +145,6 @@
#include <linux/seq_file.h>
#include "types.h"
-#ifndef REVISION_VERSION
-#define REVISION_VERSION_STR ""
-#else
-#define REVISION_VERSION_STR " "REVISION_VERSION
-#endif
-
extern struct list_head hardif_list;
extern unsigned char broadcast_addr[];
@@ -133,10 +154,10 @@
void mesh_free(struct net_device *soft_iface);
void inc_module_count(void);
void dec_module_count(void);
-int is_my_mac(uint8_t *addr);
+int is_my_mac(const uint8_t *addr);
#ifdef CONFIG_BATMAN_ADV_DEBUG
-int debug_log(struct bat_priv *bat_priv, char *fmt, ...);
+int debug_log(struct bat_priv *bat_priv, const char *fmt, ...) __printf(2, 3);
#define bat_dbg(type, bat_priv, fmt, arg...) \
do { \
@@ -145,9 +166,10 @@
} \
while (0)
#else /* !CONFIG_BATMAN_ADV_DEBUG */
-static inline void bat_dbg(char type __always_unused,
+__printf(3, 4)
+static inline void bat_dbg(int type __always_unused,
struct bat_priv *bat_priv __always_unused,
- char *fmt __always_unused, ...)
+ const char *fmt __always_unused, ...)
{
}
#endif
@@ -172,11 +194,32 @@
*
* note: can't use compare_ether_addr() as it requires aligned memory
*/
-static inline int compare_eth(void *data1, void *data2)
+
+static inline int compare_eth(const void *data1, const void *data2)
{
return (memcmp(data1, data2, ETH_ALEN) == 0 ? 1 : 0);
}
+
#define atomic_dec_not_zero(v) atomic_add_unless((v), -1, 0)
+/* Returns the smallest signed integer in two's complement with the sizeof x */
+#define smallest_signed_int(x) (1u << (7u + 8u * (sizeof(x) - 1u)))
+
+/* Checks if a sequence number x is a predecessor/successor of y.
+ * they handle overflows/underflows and can correctly check for a
+ * predecessor/successor unless the variable sequence number has grown by
+ * more then 2**(bitwidth(x)-1)-1.
+ * This means that for a uint8_t with the maximum value 255, it would think:
+ * - when adding nothing - it is neither a predecessor nor a successor
+ * - before adding more than 127 to the starting value - it is a predecessor,
+ * - when adding 128 - it is neither a predecessor nor a successor,
+ * - after adding more than 127 to the starting value - it is a successor */
+#define seq_before(x, y) ({typeof(x) _d1 = (x); \
+ typeof(y) _d2 = (y); \
+ typeof(x) _dummy = (_d1 - _d2); \
+ (void) (&_d1 == &_d2); \
+ _dummy > smallest_signed_int(_dummy); })
+#define seq_after(x, y) seq_before(y, x)
+
#endif /* _NET_BATMAN_ADV_MAIN_H_ */
diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c
index 40a30bb..4cc94d4 100644
--- a/net/batman-adv/originator.c
+++ b/net/batman-adv/originator.c
@@ -37,6 +37,14 @@
queue_delayed_work(bat_event_workqueue, &bat_priv->orig_work, 1 * HZ);
}
+/* returns 1 if they are the same originator */
+static int compare_orig(const struct hlist_node *node, const void *data2)
+{
+ const void *data1 = container_of(node, struct orig_node, hash_entry);
+
+ return (memcmp(data1, data2, ETH_ALEN) == 0 ? 1 : 0);
+}
+
int originator_init(struct bat_priv *bat_priv)
{
if (bat_priv->orig_hash)
@@ -77,7 +85,7 @@
struct neigh_node *create_neighbor(struct orig_node *orig_node,
struct orig_node *orig_neigh_node,
- uint8_t *neigh,
+ const uint8_t *neigh,
struct hard_iface *if_incoming)
{
struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface);
@@ -86,7 +94,7 @@
bat_dbg(DBG_BATMAN, bat_priv,
"Creating new last-hop neighbor of originator\n");
- neigh_node = kzalloc(sizeof(struct neigh_node), GFP_ATOMIC);
+ neigh_node = kzalloc(sizeof(*neigh_node), GFP_ATOMIC);
if (!neigh_node)
return NULL;
@@ -137,6 +145,7 @@
tt_global_del_orig(orig_node->bat_priv, orig_node,
"originator timed out");
+ kfree(orig_node->tt_buff);
kfree(orig_node->bcast_own);
kfree(orig_node->bcast_own_sum);
kfree(orig_node);
@@ -183,7 +192,7 @@
/* this function finds or creates an originator entry for the given
* address if it does not exits */
-struct orig_node *get_orig_node(struct bat_priv *bat_priv, uint8_t *addr)
+struct orig_node *get_orig_node(struct bat_priv *bat_priv, const uint8_t *addr)
{
struct orig_node *orig_node;
int size;
@@ -196,7 +205,7 @@
bat_dbg(DBG_BATMAN, bat_priv,
"Creating new originator: %pM\n", addr);
- orig_node = kzalloc(sizeof(struct orig_node), GFP_ATOMIC);
+ orig_node = kzalloc(sizeof(*orig_node), GFP_ATOMIC);
if (!orig_node)
return NULL;
@@ -205,14 +214,18 @@
spin_lock_init(&orig_node->ogm_cnt_lock);
spin_lock_init(&orig_node->bcast_seqno_lock);
spin_lock_init(&orig_node->neigh_list_lock);
+ spin_lock_init(&orig_node->tt_buff_lock);
/* extra reference for return */
atomic_set(&orig_node->refcount, 2);
+ orig_node->tt_poss_change = false;
orig_node->bat_priv = bat_priv;
memcpy(orig_node->orig, addr, ETH_ALEN);
orig_node->router = NULL;
orig_node->tt_buff = NULL;
+ orig_node->tt_buff_len = 0;
+ atomic_set(&orig_node->tt_size, 0);
orig_node->bcast_seqno_reset = jiffies - 1
- msecs_to_jiffies(RESET_PROTECTION_MS);
orig_node->batman_seqno_reset = jiffies - 1
@@ -322,9 +335,7 @@
if (purge_orig_neighbors(bat_priv, orig_node,
&best_neigh_node)) {
update_routes(bat_priv, orig_node,
- best_neigh_node,
- orig_node->tt_buff,
- orig_node->tt_buff_len);
+ best_neigh_node);
}
}
@@ -419,9 +430,8 @@
goto out;
}
- seq_printf(seq, "[B.A.T.M.A.N. adv %s%s, MainIF/MAC: %s/%pM (%s)]\n",
- SOURCE_VERSION, REVISION_VERSION_STR,
- primary_if->net_dev->name,
+ seq_printf(seq, "[B.A.T.M.A.N. adv %s, MainIF/MAC: %s/%pM (%s)]\n",
+ SOURCE_VERSION, primary_if->net_dev->name,
primary_if->net_dev->dev_addr, net_dev->name);
seq_printf(seq, " %-15s %s (%s/%i) %17s [%10s]: %20s ...\n",
"Originator", "last-seen", "#", TQ_MAX_VALUE, "Nexthop",
@@ -559,7 +569,7 @@
memcpy(data_ptr, orig_node->bcast_own, del_if_num * chunk_size);
/* copy second part */
- memcpy(data_ptr + del_if_num * chunk_size,
+ memcpy((char *)data_ptr + del_if_num * chunk_size,
orig_node->bcast_own + ((del_if_num + 1) * chunk_size),
(max_if_num - del_if_num) * chunk_size);
@@ -579,7 +589,7 @@
memcpy(data_ptr, orig_node->bcast_own_sum,
del_if_num * sizeof(uint8_t));
- memcpy(data_ptr + del_if_num * sizeof(uint8_t),
+ memcpy((char *)data_ptr + del_if_num * sizeof(uint8_t),
orig_node->bcast_own_sum + ((del_if_num + 1) * sizeof(uint8_t)),
(max_if_num - del_if_num) * sizeof(uint8_t));
diff --git a/net/batman-adv/originator.h b/net/batman-adv/originator.h
index e1d641f..cfc1f60 100644
--- a/net/batman-adv/originator.h
+++ b/net/batman-adv/originator.h
@@ -28,10 +28,10 @@
void originator_free(struct bat_priv *bat_priv);
void purge_orig_ref(struct bat_priv *bat_priv);
void orig_node_free_ref(struct orig_node *orig_node);
-struct orig_node *get_orig_node(struct bat_priv *bat_priv, uint8_t *addr);
+struct orig_node *get_orig_node(struct bat_priv *bat_priv, const uint8_t *addr);
struct neigh_node *create_neighbor(struct orig_node *orig_node,
struct orig_node *orig_neigh_node,
- uint8_t *neigh,
+ const uint8_t *neigh,
struct hard_iface *if_incoming);
void neigh_node_free_ref(struct neigh_node *neigh_node);
struct neigh_node *orig_node_get_router(struct orig_node *orig_node);
@@ -40,19 +40,11 @@
int orig_hash_del_if(struct hard_iface *hard_iface, int max_if_num);
-/* returns 1 if they are the same originator */
-static inline int compare_orig(struct hlist_node *node, void *data2)
-{
- void *data1 = container_of(node, struct orig_node, hash_entry);
-
- return (memcmp(data1, data2, ETH_ALEN) == 0 ? 1 : 0);
-}
-
/* hashfunction to choose an entry in a hash table of given size */
/* hash algorithm from http://en.wikipedia.org/wiki/Hash_table */
-static inline int choose_orig(void *data, int32_t size)
+static inline int choose_orig(const void *data, int32_t size)
{
- unsigned char *key = data;
+ const unsigned char *key = data;
uint32_t hash = 0;
size_t i;
@@ -70,7 +62,7 @@
}
static inline struct orig_node *orig_hash_find(struct bat_priv *bat_priv,
- void *data)
+ const void *data)
{
struct hashtable_t *hash = bat_priv->orig_hash;
struct hlist_head *head;
diff --git a/net/batman-adv/packet.h b/net/batman-adv/packet.h
index eda9965..590e4a6 100644
--- a/net/batman-adv/packet.h
+++ b/net/batman-adv/packet.h
@@ -24,46 +24,82 @@
#define ETH_P_BATMAN 0x4305 /* unofficial/not registered Ethertype */
-#define BAT_PACKET 0x01
-#define BAT_ICMP 0x02
-#define BAT_UNICAST 0x03
-#define BAT_BCAST 0x04
-#define BAT_VIS 0x05
-#define BAT_UNICAST_FRAG 0x06
+enum bat_packettype {
+ BAT_PACKET = 0x01,
+ BAT_ICMP = 0x02,
+ BAT_UNICAST = 0x03,
+ BAT_BCAST = 0x04,
+ BAT_VIS = 0x05,
+ BAT_UNICAST_FRAG = 0x06,
+ BAT_TT_QUERY = 0x07,
+ BAT_ROAM_ADV = 0x08
+};
/* this file is included by batctl which needs these defines */
-#define COMPAT_VERSION 12
-#define DIRECTLINK 0x40
-#define VIS_SERVER 0x20
-#define PRIMARIES_FIRST_HOP 0x10
+#define COMPAT_VERSION 14
+
+enum batman_flags {
+ PRIMARIES_FIRST_HOP = 1 << 4,
+ VIS_SERVER = 1 << 5,
+ DIRECTLINK = 1 << 6
+};
/* ICMP message types */
-#define ECHO_REPLY 0
-#define DESTINATION_UNREACHABLE 3
-#define ECHO_REQUEST 8
-#define TTL_EXCEEDED 11
-#define PARAMETER_PROBLEM 12
+enum icmp_packettype {
+ ECHO_REPLY = 0,
+ DESTINATION_UNREACHABLE = 3,
+ ECHO_REQUEST = 8,
+ TTL_EXCEEDED = 11,
+ PARAMETER_PROBLEM = 12
+};
/* vis defines */
-#define VIS_TYPE_SERVER_SYNC 0
-#define VIS_TYPE_CLIENT_UPDATE 1
+enum vis_packettype {
+ VIS_TYPE_SERVER_SYNC = 0,
+ VIS_TYPE_CLIENT_UPDATE = 1
+};
/* fragmentation defines */
-#define UNI_FRAG_HEAD 0x01
-#define UNI_FRAG_LARGETAIL 0x02
+enum unicast_frag_flags {
+ UNI_FRAG_HEAD = 1 << 0,
+ UNI_FRAG_LARGETAIL = 1 << 1
+};
+
+/* TT_QUERY subtypes */
+#define TT_QUERY_TYPE_MASK 0x3
+
+enum tt_query_packettype {
+ TT_REQUEST = 0,
+ TT_RESPONSE = 1
+};
+
+/* TT_QUERY flags */
+enum tt_query_flags {
+ TT_FULL_TABLE = 1 << 2
+};
+
+/* TT_CLIENT flags.
+ * Flags from 1 to 1 << 7 are sent on the wire, while flags from 1 << 8 to
+ * 1 << 15 are used for local computation only */
+enum tt_client_flags {
+ TT_CLIENT_DEL = 1 << 0,
+ TT_CLIENT_ROAM = 1 << 1,
+ TT_CLIENT_NOPURGE = 1 << 8
+};
struct batman_packet {
uint8_t packet_type;
uint8_t version; /* batman version field */
+ uint8_t ttl;
uint8_t flags; /* 0x40: DIRECTLINK flag, 0x20 VIS_SERVER flag... */
- uint8_t tq;
uint32_t seqno;
uint8_t orig[6];
uint8_t prev_sender[6];
- uint8_t ttl;
- uint8_t num_tt;
uint8_t gw_flags; /* flags related to gateway class */
- uint8_t align;
+ uint8_t tq;
+ uint8_t tt_num_changes;
+ uint8_t ttvn; /* translation table version number */
+ uint16_t tt_crc;
} __packed;
#define BAT_PACKET_LEN sizeof(struct batman_packet)
@@ -71,12 +107,13 @@
struct icmp_packet {
uint8_t packet_type;
uint8_t version; /* batman version field */
- uint8_t msg_type; /* see ICMP message types above */
uint8_t ttl;
+ uint8_t msg_type; /* see ICMP message types above */
uint8_t dst[6];
uint8_t orig[6];
uint16_t seqno;
uint8_t uid;
+ uint8_t reserved;
} __packed;
#define BAT_RR_LEN 16
@@ -86,8 +123,8 @@
struct icmp_packet_rr {
uint8_t packet_type;
uint8_t version; /* batman version field */
- uint8_t msg_type; /* see ICMP message types above */
uint8_t ttl;
+ uint8_t msg_type; /* see ICMP message types above */
uint8_t dst[6];
uint8_t orig[6];
uint16_t seqno;
@@ -99,16 +136,19 @@
struct unicast_packet {
uint8_t packet_type;
uint8_t version; /* batman version field */
- uint8_t dest[6];
uint8_t ttl;
+ uint8_t ttvn; /* destination translation table version number */
+ uint8_t dest[6];
} __packed;
struct unicast_frag_packet {
uint8_t packet_type;
uint8_t version; /* batman version field */
- uint8_t dest[6];
uint8_t ttl;
+ uint8_t ttvn; /* destination translation table version number */
+ uint8_t dest[6];
uint8_t flags;
+ uint8_t align;
uint8_t orig[6];
uint16_t seqno;
} __packed;
@@ -116,21 +156,61 @@
struct bcast_packet {
uint8_t packet_type;
uint8_t version; /* batman version field */
- uint8_t orig[6];
uint8_t ttl;
+ uint8_t reserved;
uint32_t seqno;
+ uint8_t orig[6];
} __packed;
struct vis_packet {
uint8_t packet_type;
uint8_t version; /* batman version field */
- uint8_t vis_type; /* which type of vis-participant sent this? */
- uint8_t entries; /* number of entries behind this struct */
- uint32_t seqno; /* sequence number */
uint8_t ttl; /* TTL */
+ uint8_t vis_type; /* which type of vis-participant sent this? */
+ uint32_t seqno; /* sequence number */
+ uint8_t entries; /* number of entries behind this struct */
+ uint8_t reserved;
uint8_t vis_orig[6]; /* originator that announces its neighbors */
uint8_t target_orig[6]; /* who should receive this packet */
uint8_t sender_orig[6]; /* who sent or rebroadcasted this packet */
} __packed;
+struct tt_query_packet {
+ uint8_t packet_type;
+ uint8_t version; /* batman version field */
+ uint8_t ttl;
+ /* the flag field is a combination of:
+ * - TT_REQUEST or TT_RESPONSE
+ * - TT_FULL_TABLE */
+ uint8_t flags;
+ uint8_t dst[ETH_ALEN];
+ uint8_t src[ETH_ALEN];
+ /* the ttvn field is:
+ * if TT_REQUEST: ttvn that triggered the
+ * request
+ * if TT_RESPONSE: new ttvn for the src
+ * orig_node */
+ uint8_t ttvn;
+ /* tt_data field is:
+ * if TT_REQUEST: crc associated with the
+ * ttvn
+ * if TT_RESPONSE: table_size */
+ uint16_t tt_data;
+} __packed;
+
+struct roam_adv_packet {
+ uint8_t packet_type;
+ uint8_t version;
+ uint8_t ttl;
+ uint8_t reserved;
+ uint8_t dst[ETH_ALEN];
+ uint8_t src[ETH_ALEN];
+ uint8_t client[ETH_ALEN];
+} __packed;
+
+struct tt_change {
+ uint8_t flags;
+ uint8_t addr[ETH_ALEN];
+} __packed;
+
#endif /* _NET_BATMAN_ADV_PACKET_H_ */
diff --git a/net/batman-adv/ring_buffer.c b/net/batman-adv/ring_buffer.c
index 5bb6a61..f1ccfa7 100644
--- a/net/batman-adv/ring_buffer.c
+++ b/net/batman-adv/ring_buffer.c
@@ -28,9 +28,9 @@
*lq_index = (*lq_index + 1) % TQ_GLOBAL_WINDOW_SIZE;
}
-uint8_t ring_buffer_avg(uint8_t lq_recv[])
+uint8_t ring_buffer_avg(const uint8_t lq_recv[])
{
- uint8_t *ptr;
+ const uint8_t *ptr;
uint16_t count = 0, i = 0, sum = 0;
ptr = lq_recv;
diff --git a/net/batman-adv/ring_buffer.h b/net/batman-adv/ring_buffer.h
index 0395b27..7cdfe62 100644
--- a/net/batman-adv/ring_buffer.h
+++ b/net/batman-adv/ring_buffer.h
@@ -23,6 +23,6 @@
#define _NET_BATMAN_ADV_RING_BUFFER_H_
void ring_buffer_set(uint8_t lq_recv[], uint8_t *lq_index, uint8_t value);
-uint8_t ring_buffer_avg(uint8_t lq_recv[]);
+uint8_t ring_buffer_avg(const uint8_t lq_recv[]);
#endif /* _NET_BATMAN_ADV_RING_BUFFER_H_ */
diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c
index bb1c3ec..2cb98be 100644
--- a/net/batman-adv/routing.c
+++ b/net/batman-adv/routing.c
@@ -64,28 +64,57 @@
}
}
-static void update_TT(struct bat_priv *bat_priv, struct orig_node *orig_node,
- unsigned char *tt_buff, int tt_buff_len)
+static void update_transtable(struct bat_priv *bat_priv,
+ struct orig_node *orig_node,
+ const unsigned char *tt_buff,
+ uint8_t tt_num_changes, uint8_t ttvn,
+ uint16_t tt_crc)
{
- if ((tt_buff_len != orig_node->tt_buff_len) ||
- ((tt_buff_len > 0) &&
- (orig_node->tt_buff_len > 0) &&
- (memcmp(orig_node->tt_buff, tt_buff, tt_buff_len) != 0))) {
+ uint8_t orig_ttvn = (uint8_t)atomic_read(&orig_node->last_ttvn);
+ bool full_table = true;
- if (orig_node->tt_buff_len > 0)
- tt_global_del_orig(bat_priv, orig_node,
- "originator changed tt");
+ /* the ttvn increased by one -> we can apply the attached changes */
+ if (ttvn - orig_ttvn == 1) {
+ /* the OGM could not contain the changes because they were too
+ * many to fit in one frame or because they have already been
+ * sent TT_OGM_APPEND_MAX times. In this case send a tt
+ * request */
+ if (!tt_num_changes) {
+ full_table = false;
+ goto request_table;
+ }
- if ((tt_buff_len > 0) && (tt_buff))
- tt_global_add_orig(bat_priv, orig_node,
- tt_buff, tt_buff_len);
+ tt_update_changes(bat_priv, orig_node, tt_num_changes, ttvn,
+ (struct tt_change *)tt_buff);
+
+ /* Even if we received the crc into the OGM, we prefer
+ * to recompute it to spot any possible inconsistency
+ * in the global table */
+ orig_node->tt_crc = tt_global_crc(bat_priv, orig_node);
+ /* Roaming phase is over: tables are in sync again. I can
+ * unset the flag */
+ orig_node->tt_poss_change = false;
+ } else {
+ /* if we missed more than one change or our tables are not
+ * in sync anymore -> request fresh tt data */
+ if (ttvn != orig_ttvn || orig_node->tt_crc != tt_crc) {
+request_table:
+ bat_dbg(DBG_TT, bat_priv, "TT inconsistency for %pM. "
+ "Need to retrieve the correct information "
+ "(ttvn: %u last_ttvn: %u crc: %u last_crc: "
+ "%u num_changes: %u)\n", orig_node->orig, ttvn,
+ orig_ttvn, tt_crc, orig_node->tt_crc,
+ tt_num_changes);
+ send_tt_request(bat_priv, orig_node, ttvn, tt_crc,
+ full_table);
+ return;
+ }
}
}
static void update_route(struct bat_priv *bat_priv,
struct orig_node *orig_node,
- struct neigh_node *neigh_node,
- unsigned char *tt_buff, int tt_buff_len)
+ struct neigh_node *neigh_node)
{
struct neigh_node *curr_router;
@@ -93,11 +122,10 @@
/* route deleted */
if ((curr_router) && (!neigh_node)) {
-
bat_dbg(DBG_ROUTES, bat_priv, "Deleting route towards: %pM\n",
orig_node->orig);
tt_global_del_orig(bat_priv, orig_node,
- "originator timed out");
+ "Deleted route towards originator");
/* route added */
} else if ((!curr_router) && (neigh_node)) {
@@ -105,11 +133,8 @@
bat_dbg(DBG_ROUTES, bat_priv,
"Adding route towards: %pM (via %pM)\n",
orig_node->orig, neigh_node->addr);
- tt_global_add_orig(bat_priv, orig_node,
- tt_buff, tt_buff_len);
-
/* route changed */
- } else {
+ } else if (neigh_node && curr_router) {
bat_dbg(DBG_ROUTES, bat_priv,
"Changing route towards: %pM "
"(now via %pM - was via %pM)\n",
@@ -133,10 +158,8 @@
neigh_node_free_ref(curr_router);
}
-
void update_routes(struct bat_priv *bat_priv, struct orig_node *orig_node,
- struct neigh_node *neigh_node, unsigned char *tt_buff,
- int tt_buff_len)
+ struct neigh_node *neigh_node)
{
struct neigh_node *router = NULL;
@@ -146,11 +169,7 @@
router = orig_node_get_router(orig_node);
if (router != neigh_node)
- update_route(bat_priv, orig_node, neigh_node,
- tt_buff, tt_buff_len);
- /* may be just TT changed */
- else
- update_TT(bat_priv, orig_node, tt_buff, tt_buff_len);
+ update_route(bat_priv, orig_node, neigh_node);
out:
if (router)
@@ -165,7 +184,7 @@
struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface);
struct neigh_node *neigh_node = NULL, *tmp_neigh_node;
struct hlist_node *node;
- unsigned char total_count;
+ uint8_t total_count;
uint8_t orig_eq_count, neigh_rq_count, tq_own;
int tq_asym_penalty, ret = 0;
@@ -348,9 +367,9 @@
}
/* copy primary address for bonding */
-static void bonding_save_primary(struct orig_node *orig_node,
+static void bonding_save_primary(const struct orig_node *orig_node,
struct orig_node *orig_neigh_node,
- struct batman_packet *batman_packet)
+ const struct batman_packet *batman_packet)
{
if (!(batman_packet->flags & PRIMARIES_FIRST_HOP))
return;
@@ -358,19 +377,16 @@
memcpy(orig_neigh_node->primary_addr, orig_node->orig, ETH_ALEN);
}
-static void update_orig(struct bat_priv *bat_priv,
- struct orig_node *orig_node,
- struct ethhdr *ethhdr,
- struct batman_packet *batman_packet,
+static void update_orig(struct bat_priv *bat_priv, struct orig_node *orig_node,
+ const struct ethhdr *ethhdr,
+ const struct batman_packet *batman_packet,
struct hard_iface *if_incoming,
- unsigned char *tt_buff, int tt_buff_len,
- char is_duplicate)
+ const unsigned char *tt_buff, int is_duplicate)
{
struct neigh_node *neigh_node = NULL, *tmp_neigh_node = NULL;
struct neigh_node *router = NULL;
struct orig_node *orig_node_tmp;
struct hlist_node *node;
- int tmp_tt_buff_len;
uint8_t bcast_own_sum_orig, bcast_own_sum_neigh;
bat_dbg(DBG_BATMAN, bat_priv, "update_originator(): "
@@ -435,9 +451,6 @@
bonding_candidate_add(orig_node, neigh_node);
- tmp_tt_buff_len = (tt_buff_len > batman_packet->num_tt * ETH_ALEN ?
- batman_packet->num_tt * ETH_ALEN : tt_buff_len);
-
/* if this neighbor already is our next hop there is nothing
* to change */
router = orig_node_get_router(orig_node);
@@ -467,15 +480,19 @@
goto update_tt;
}
- update_routes(bat_priv, orig_node, neigh_node,
- tt_buff, tmp_tt_buff_len);
- goto update_gw;
+ update_routes(bat_priv, orig_node, neigh_node);
update_tt:
- update_routes(bat_priv, orig_node, router,
- tt_buff, tmp_tt_buff_len);
+ /* I have to check for transtable changes only if the OGM has been
+ * sent through a primary interface */
+ if (((batman_packet->orig != ethhdr->h_source) &&
+ (batman_packet->ttl > 2)) ||
+ (batman_packet->flags & PRIMARIES_FIRST_HOP))
+ update_transtable(bat_priv, orig_node, tt_buff,
+ batman_packet->tt_num_changes,
+ batman_packet->ttvn,
+ batman_packet->tt_crc);
-update_gw:
if (orig_node->gw_flags != batman_packet->gw_flags)
gw_node_update(bat_priv, orig_node, batman_packet->gw_flags);
@@ -531,15 +548,15 @@
* -1 the packet is old and has been received while the seqno window
* was protected. Caller should drop it.
*/
-static char count_real_packets(struct ethhdr *ethhdr,
- struct batman_packet *batman_packet,
- struct hard_iface *if_incoming)
+static int count_real_packets(const struct ethhdr *ethhdr,
+ const struct batman_packet *batman_packet,
+ const struct hard_iface *if_incoming)
{
struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface);
struct orig_node *orig_node;
struct neigh_node *tmp_neigh_node;
struct hlist_node *node;
- char is_duplicate = 0;
+ int is_duplicate = 0;
int32_t seq_diff;
int need_update = 0;
int set_mark, ret = -1;
@@ -595,9 +612,9 @@
return ret;
}
-void receive_bat_packet(struct ethhdr *ethhdr,
+void receive_bat_packet(const struct ethhdr *ethhdr,
struct batman_packet *batman_packet,
- unsigned char *tt_buff, int tt_buff_len,
+ const unsigned char *tt_buff,
struct hard_iface *if_incoming)
{
struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface);
@@ -605,10 +622,10 @@
struct orig_node *orig_neigh_node, *orig_node;
struct neigh_node *router = NULL, *router_router = NULL;
struct neigh_node *orig_neigh_router = NULL;
- char has_directlink_flag;
- char is_my_addr = 0, is_my_orig = 0, is_my_oldorig = 0;
- char is_broadcast = 0, is_bidirectional, is_single_hop_neigh;
- char is_duplicate;
+ int has_directlink_flag;
+ int is_my_addr = 0, is_my_orig = 0, is_my_oldorig = 0;
+ int is_broadcast = 0, is_bidirectional, is_single_hop_neigh;
+ int is_duplicate;
uint32_t if_incoming_seqno;
/* Silently drop when the batman packet is actually not a
@@ -636,12 +653,14 @@
bat_dbg(DBG_BATMAN, bat_priv,
"Received BATMAN packet via NB: %pM, IF: %s [%pM] "
- "(from OG: %pM, via prev OG: %pM, seqno %d, tq %d, "
- "TTL %d, V %d, IDF %d)\n",
+ "(from OG: %pM, via prev OG: %pM, seqno %d, ttvn %u, "
+ "crc %u, changes %u, td %d, TTL %d, V %d, IDF %d)\n",
ethhdr->h_source, if_incoming->net_dev->name,
if_incoming->net_dev->dev_addr, batman_packet->orig,
batman_packet->prev_sender, batman_packet->seqno,
- batman_packet->tq, batman_packet->ttl, batman_packet->version,
+ batman_packet->ttvn, batman_packet->tt_crc,
+ batman_packet->tt_num_changes, batman_packet->tq,
+ batman_packet->ttl, batman_packet->version,
has_directlink_flag);
rcu_read_lock();
@@ -664,7 +683,7 @@
hard_iface->net_dev->dev_addr))
is_my_oldorig = 1;
- if (compare_eth(ethhdr->h_source, broadcast_addr))
+ if (is_broadcast_ether_addr(ethhdr->h_source))
is_broadcast = 1;
}
rcu_read_unlock();
@@ -701,17 +720,16 @@
/* neighbor has to indicate direct link and it has to
* come via the corresponding interface */
- /* if received seqno equals last send seqno save new
- * seqno for bidirectional check */
+ /* save packet seqno for bidirectional check */
if (has_directlink_flag &&
compare_eth(if_incoming->net_dev->dev_addr,
- batman_packet->orig) &&
- (batman_packet->seqno - if_incoming_seqno + 2 == 0)) {
+ batman_packet->orig)) {
offset = if_incoming->if_num * NUM_WORDS;
spin_lock_bh(&orig_neigh_node->ogm_cnt_lock);
word = &(orig_neigh_node->bcast_own[offset]);
- bit_mark(word, 0);
+ bit_mark(word,
+ if_incoming_seqno - batman_packet->seqno - 2);
orig_neigh_node->bcast_own_sum[if_incoming->if_num] =
bit_packet_count(word);
spin_unlock_bh(&orig_neigh_node->ogm_cnt_lock);
@@ -794,14 +812,14 @@
((orig_node->last_real_seqno == batman_packet->seqno) &&
(orig_node->last_ttl - 3 <= batman_packet->ttl))))
update_orig(bat_priv, orig_node, ethhdr, batman_packet,
- if_incoming, tt_buff, tt_buff_len, is_duplicate);
+ if_incoming, tt_buff, is_duplicate);
/* is single hop (direct) neighbor */
if (is_single_hop_neigh) {
/* mark direct link on incoming interface */
schedule_forward_packet(orig_node, ethhdr, batman_packet,
- 1, tt_buff_len, if_incoming);
+ 1, if_incoming);
bat_dbg(DBG_BATMAN, bat_priv, "Forwarding packet: "
"rebroadcast neighbor packet with direct link flag\n");
@@ -824,7 +842,7 @@
bat_dbg(DBG_BATMAN, bat_priv,
"Forwarding packet: rebroadcast originator packet\n");
schedule_forward_packet(orig_node, ethhdr, batman_packet,
- 0, tt_buff_len, if_incoming);
+ 0, if_incoming);
out_neigh:
if ((orig_neigh_node) && (!is_single_hop_neigh))
@@ -1077,7 +1095,7 @@
* This method rotates the bonding list and increases the
* returned router's refcount. */
static struct neigh_node *find_bond_router(struct orig_node *primary_orig,
- struct hard_iface *recv_if)
+ const struct hard_iface *recv_if)
{
struct neigh_node *tmp_neigh_node;
struct neigh_node *router = NULL, *first_candidate = NULL;
@@ -1128,7 +1146,7 @@
*
* Increases the returned router's refcount */
static struct neigh_node *find_ifalter_router(struct orig_node *primary_orig,
- struct hard_iface *recv_if)
+ const struct hard_iface *recv_if)
{
struct neigh_node *tmp_neigh_node;
struct neigh_node *router = NULL, *first_candidate = NULL;
@@ -1171,12 +1189,124 @@
return router;
}
+int recv_tt_query(struct sk_buff *skb, struct hard_iface *recv_if)
+{
+ struct bat_priv *bat_priv = netdev_priv(recv_if->soft_iface);
+ struct tt_query_packet *tt_query;
+ struct ethhdr *ethhdr;
+
+ /* drop packet if it has not necessary minimum size */
+ if (unlikely(!pskb_may_pull(skb, sizeof(struct tt_query_packet))))
+ goto out;
+
+ /* I could need to modify it */
+ if (skb_cow(skb, sizeof(struct tt_query_packet)) < 0)
+ goto out;
+
+ ethhdr = (struct ethhdr *)skb_mac_header(skb);
+
+ /* packet with unicast indication but broadcast recipient */
+ if (is_broadcast_ether_addr(ethhdr->h_dest))
+ goto out;
+
+ /* packet with broadcast sender address */
+ if (is_broadcast_ether_addr(ethhdr->h_source))
+ goto out;
+
+ tt_query = (struct tt_query_packet *)skb->data;
+
+ tt_query->tt_data = ntohs(tt_query->tt_data);
+
+ switch (tt_query->flags & TT_QUERY_TYPE_MASK) {
+ case TT_REQUEST:
+ /* If we cannot provide an answer the tt_request is
+ * forwarded */
+ if (!send_tt_response(bat_priv, tt_query)) {
+ bat_dbg(DBG_TT, bat_priv,
+ "Routing TT_REQUEST to %pM [%c]\n",
+ tt_query->dst,
+ (tt_query->flags & TT_FULL_TABLE ? 'F' : '.'));
+ tt_query->tt_data = htons(tt_query->tt_data);
+ return route_unicast_packet(skb, recv_if);
+ }
+ break;
+ case TT_RESPONSE:
+ /* packet needs to be linearised to access the TT changes */
+ if (skb_linearize(skb) < 0)
+ goto out;
+
+ if (is_my_mac(tt_query->dst))
+ handle_tt_response(bat_priv, tt_query);
+ else {
+ bat_dbg(DBG_TT, bat_priv,
+ "Routing TT_RESPONSE to %pM [%c]\n",
+ tt_query->dst,
+ (tt_query->flags & TT_FULL_TABLE ? 'F' : '.'));
+ tt_query->tt_data = htons(tt_query->tt_data);
+ return route_unicast_packet(skb, recv_if);
+ }
+ break;
+ }
+
+out:
+ /* returning NET_RX_DROP will make the caller function kfree the skb */
+ return NET_RX_DROP;
+}
+
+int recv_roam_adv(struct sk_buff *skb, struct hard_iface *recv_if)
+{
+ struct bat_priv *bat_priv = netdev_priv(recv_if->soft_iface);
+ struct roam_adv_packet *roam_adv_packet;
+ struct orig_node *orig_node;
+ struct ethhdr *ethhdr;
+
+ /* drop packet if it has not necessary minimum size */
+ if (unlikely(!pskb_may_pull(skb, sizeof(struct roam_adv_packet))))
+ goto out;
+
+ ethhdr = (struct ethhdr *)skb_mac_header(skb);
+
+ /* packet with unicast indication but broadcast recipient */
+ if (is_broadcast_ether_addr(ethhdr->h_dest))
+ goto out;
+
+ /* packet with broadcast sender address */
+ if (is_broadcast_ether_addr(ethhdr->h_source))
+ goto out;
+
+ roam_adv_packet = (struct roam_adv_packet *)skb->data;
+
+ if (!is_my_mac(roam_adv_packet->dst))
+ return route_unicast_packet(skb, recv_if);
+
+ orig_node = orig_hash_find(bat_priv, roam_adv_packet->src);
+ if (!orig_node)
+ goto out;
+
+ bat_dbg(DBG_TT, bat_priv, "Received ROAMING_ADV from %pM "
+ "(client %pM)\n", roam_adv_packet->src,
+ roam_adv_packet->client);
+
+ tt_global_add(bat_priv, orig_node, roam_adv_packet->client,
+ atomic_read(&orig_node->last_ttvn) + 1, true);
+
+ /* Roaming phase starts: I have new information but the ttvn has not
+ * been incremented yet. This flag will make me check all the incoming
+ * packets for the correct destination. */
+ bat_priv->tt_poss_change = true;
+
+ orig_node_free_ref(orig_node);
+out:
+ /* returning NET_RX_DROP will make the caller function kfree the skb */
+ return NET_RX_DROP;
+}
+
/* find a suitable router for this originator, and use
* bonding if possible. increases the found neighbors
* refcount.*/
struct neigh_node *find_router(struct bat_priv *bat_priv,
struct orig_node *orig_node,
- struct hard_iface *recv_if)
+ const struct hard_iface *recv_if)
{
struct orig_node *primary_orig_node;
struct orig_node *router_orig;
@@ -1240,6 +1370,9 @@
router = find_ifalter_router(primary_orig_node, recv_if);
return_router:
+ if (router && router->if_incoming->if_status != IF_ACTIVE)
+ goto err_unlock;
+
rcu_read_unlock();
return router;
err_unlock:
@@ -1354,14 +1487,84 @@
return ret;
}
+static int check_unicast_ttvn(struct bat_priv *bat_priv,
+ struct sk_buff *skb) {
+ uint8_t curr_ttvn;
+ struct orig_node *orig_node;
+ struct ethhdr *ethhdr;
+ struct hard_iface *primary_if;
+ struct unicast_packet *unicast_packet;
+ bool tt_poss_change;
+
+ /* I could need to modify it */
+ if (skb_cow(skb, sizeof(struct unicast_packet)) < 0)
+ return 0;
+
+ unicast_packet = (struct unicast_packet *)skb->data;
+
+ if (is_my_mac(unicast_packet->dest)) {
+ tt_poss_change = bat_priv->tt_poss_change;
+ curr_ttvn = (uint8_t)atomic_read(&bat_priv->ttvn);
+ } else {
+ orig_node = orig_hash_find(bat_priv, unicast_packet->dest);
+
+ if (!orig_node)
+ return 0;
+
+ curr_ttvn = (uint8_t)atomic_read(&orig_node->last_ttvn);
+ tt_poss_change = orig_node->tt_poss_change;
+ orig_node_free_ref(orig_node);
+ }
+
+ /* Check whether I have to reroute the packet */
+ if (seq_before(unicast_packet->ttvn, curr_ttvn) || tt_poss_change) {
+ /* Linearize the skb before accessing it */
+ if (skb_linearize(skb) < 0)
+ return 0;
+
+ ethhdr = (struct ethhdr *)(skb->data +
+ sizeof(struct unicast_packet));
+ orig_node = transtable_search(bat_priv, ethhdr->h_dest);
+
+ if (!orig_node) {
+ if (!is_my_client(bat_priv, ethhdr->h_dest))
+ return 0;
+ primary_if = primary_if_get_selected(bat_priv);
+ if (!primary_if)
+ return 0;
+ memcpy(unicast_packet->dest,
+ primary_if->net_dev->dev_addr, ETH_ALEN);
+ hardif_free_ref(primary_if);
+ } else {
+ memcpy(unicast_packet->dest, orig_node->orig,
+ ETH_ALEN);
+ curr_ttvn = (uint8_t)
+ atomic_read(&orig_node->last_ttvn);
+ orig_node_free_ref(orig_node);
+ }
+
+ bat_dbg(DBG_ROUTES, bat_priv, "TTVN mismatch (old_ttvn %u "
+ "new_ttvn %u)! Rerouting unicast packet (for %pM) to "
+ "%pM\n", unicast_packet->ttvn, curr_ttvn,
+ ethhdr->h_dest, unicast_packet->dest);
+
+ unicast_packet->ttvn = curr_ttvn;
+ }
+ return 1;
+}
+
int recv_unicast_packet(struct sk_buff *skb, struct hard_iface *recv_if)
{
+ struct bat_priv *bat_priv = netdev_priv(recv_if->soft_iface);
struct unicast_packet *unicast_packet;
- int hdr_size = sizeof(struct unicast_packet);
+ int hdr_size = sizeof(*unicast_packet);
if (check_unicast_packet(skb, hdr_size) < 0)
return NET_RX_DROP;
+ if (!check_unicast_ttvn(bat_priv, skb))
+ return NET_RX_DROP;
+
unicast_packet = (struct unicast_packet *)skb->data;
/* packet for me */
@@ -1377,13 +1580,16 @@
{
struct bat_priv *bat_priv = netdev_priv(recv_if->soft_iface);
struct unicast_frag_packet *unicast_packet;
- int hdr_size = sizeof(struct unicast_frag_packet);
+ int hdr_size = sizeof(*unicast_packet);
struct sk_buff *new_skb = NULL;
int ret;
if (check_unicast_packet(skb, hdr_size) < 0)
return NET_RX_DROP;
+ if (!check_unicast_ttvn(bat_priv, skb))
+ return NET_RX_DROP;
+
unicast_packet = (struct unicast_frag_packet *)skb->data;
/* packet for me */
@@ -1413,7 +1619,7 @@
struct orig_node *orig_node = NULL;
struct bcast_packet *bcast_packet;
struct ethhdr *ethhdr;
- int hdr_size = sizeof(struct bcast_packet);
+ int hdr_size = sizeof(*bcast_packet);
int ret = NET_RX_DROP;
int32_t seq_diff;
@@ -1471,7 +1677,7 @@
spin_unlock_bh(&orig_node->bcast_seqno_lock);
/* rebroadcast packet */
- add_bcast_packet_to_list(bat_priv, skb);
+ add_bcast_packet_to_list(bat_priv, skb, 1);
/* broadcast for me */
interface_rx(recv_if->soft_iface, skb, recv_if, hdr_size);
@@ -1491,7 +1697,7 @@
struct vis_packet *vis_packet;
struct ethhdr *ethhdr;
struct bat_priv *bat_priv = netdev_priv(recv_if->soft_iface);
- int hdr_size = sizeof(struct vis_packet);
+ int hdr_size = sizeof(*vis_packet);
/* keep skb linear */
if (skb_linearize(skb) < 0)
diff --git a/net/batman-adv/routing.h b/net/batman-adv/routing.h
index 870f298..fb14e95 100644
--- a/net/batman-adv/routing.h
+++ b/net/batman-adv/routing.h
@@ -23,13 +23,12 @@
#define _NET_BATMAN_ADV_ROUTING_H_
void slide_own_bcast_window(struct hard_iface *hard_iface);
-void receive_bat_packet(struct ethhdr *ethhdr,
- struct batman_packet *batman_packet,
- unsigned char *tt_buff, int tt_buff_len,
- struct hard_iface *if_incoming);
+void receive_bat_packet(const struct ethhdr *ethhdr,
+ struct batman_packet *batman_packet,
+ const unsigned char *tt_buff,
+ struct hard_iface *if_incoming);
void update_routes(struct bat_priv *bat_priv, struct orig_node *orig_node,
- struct neigh_node *neigh_node, unsigned char *tt_buff,
- int tt_buff_len);
+ struct neigh_node *neigh_node);
int route_unicast_packet(struct sk_buff *skb, struct hard_iface *recv_if);
int recv_icmp_packet(struct sk_buff *skb, struct hard_iface *recv_if);
int recv_unicast_packet(struct sk_buff *skb, struct hard_iface *recv_if);
@@ -37,9 +36,11 @@
int recv_bcast_packet(struct sk_buff *skb, struct hard_iface *recv_if);
int recv_vis_packet(struct sk_buff *skb, struct hard_iface *recv_if);
int recv_bat_packet(struct sk_buff *skb, struct hard_iface *recv_if);
+int recv_tt_query(struct sk_buff *skb, struct hard_iface *recv_if);
+int recv_roam_adv(struct sk_buff *skb, struct hard_iface *recv_if);
struct neigh_node *find_router(struct bat_priv *bat_priv,
struct orig_node *orig_node,
- struct hard_iface *recv_if);
+ const struct hard_iface *recv_if);
void bonding_candidate_del(struct orig_node *orig_node,
struct neigh_node *neigh_node);
diff --git a/net/batman-adv/send.c b/net/batman-adv/send.c
index 3377927..4b8e11b 100644
--- a/net/batman-adv/send.c
+++ b/net/batman-adv/send.c
@@ -33,14 +33,14 @@
static void send_outstanding_bcast_packet(struct work_struct *work);
/* apply hop penalty for a normal link */
-static uint8_t hop_penalty(const uint8_t tq, struct bat_priv *bat_priv)
+static uint8_t hop_penalty(uint8_t tq, const struct bat_priv *bat_priv)
{
int hop_penalty = atomic_read(&bat_priv->hop_penalty);
return (tq * (TQ_MAX_VALUE - hop_penalty)) / (TQ_MAX_VALUE);
}
/* when do we schedule our own packet to be sent */
-static unsigned long own_send_time(struct bat_priv *bat_priv)
+static unsigned long own_send_time(const struct bat_priv *bat_priv)
{
return jiffies + msecs_to_jiffies(
atomic_read(&bat_priv->orig_interval) -
@@ -55,9 +55,8 @@
/* send out an already prepared packet to the given address via the
* specified batman interface */
-int send_skb_packet(struct sk_buff *skb,
- struct hard_iface *hard_iface,
- uint8_t *dst_addr)
+int send_skb_packet(struct sk_buff *skb, struct hard_iface *hard_iface,
+ const uint8_t *dst_addr)
{
struct ethhdr *ethhdr;
@@ -74,7 +73,7 @@
}
/* push to the ethernet header. */
- if (my_skb_head_push(skb, sizeof(struct ethhdr)) < 0)
+ if (my_skb_head_push(skb, sizeof(*ethhdr)) < 0)
goto send_skb_err;
skb_reset_mac_header(skb);
@@ -121,7 +120,7 @@
/* adjust all flags and log packets */
while (aggregated_packet(buff_pos,
forw_packet->packet_len,
- batman_packet->num_tt)) {
+ batman_packet->tt_num_changes)) {
/* we might have aggregated direct link packets with an
* ordinary base packet */
@@ -136,17 +135,17 @@
"Forwarding"));
bat_dbg(DBG_BATMAN, bat_priv,
"%s %spacket (originator %pM, seqno %d, TQ %d, TTL %d,"
- " IDF %s) on interface %s [%pM]\n",
+ " IDF %s, hvn %d) on interface %s [%pM]\n",
fwd_str, (packet_num > 0 ? "aggregated " : ""),
batman_packet->orig, ntohl(batman_packet->seqno),
batman_packet->tq, batman_packet->ttl,
(batman_packet->flags & DIRECTLINK ?
"on" : "off"),
- hard_iface->net_dev->name,
+ batman_packet->ttvn, hard_iface->net_dev->name,
hard_iface->net_dev->dev_addr);
- buff_pos += sizeof(struct batman_packet) +
- (batman_packet->num_tt * ETH_ALEN);
+ buff_pos += sizeof(*batman_packet) +
+ tt_len(batman_packet->tt_num_changes);
packet_num++;
batman_packet = (struct batman_packet *)
(forw_packet->skb->data + buff_pos);
@@ -164,26 +163,31 @@
struct hard_iface *hard_iface;
struct net_device *soft_iface;
struct bat_priv *bat_priv;
+ struct hard_iface *primary_if = NULL;
struct batman_packet *batman_packet =
(struct batman_packet *)(forw_packet->skb->data);
- unsigned char directlink = (batman_packet->flags & DIRECTLINK ? 1 : 0);
+ int directlink = (batman_packet->flags & DIRECTLINK ? 1 : 0);
if (!forw_packet->if_incoming) {
pr_err("Error - can't forward packet: incoming iface not "
"specified\n");
- return;
+ goto out;
}
soft_iface = forw_packet->if_incoming->soft_iface;
bat_priv = netdev_priv(soft_iface);
if (forw_packet->if_incoming->if_status != IF_ACTIVE)
- return;
+ goto out;
+
+ primary_if = primary_if_get_selected(bat_priv);
+ if (!primary_if)
+ goto out;
/* multihomed peer assumed */
/* non-primary OGMs are only broadcasted on their interface */
if ((directlink && (batman_packet->ttl == 1)) ||
- (forw_packet->own && (forw_packet->if_incoming->if_num > 0))) {
+ (forw_packet->own && (forw_packet->if_incoming != primary_if))) {
/* FIXME: what about aggregated packets ? */
bat_dbg(DBG_BATMAN, bat_priv,
@@ -200,7 +204,7 @@
broadcast_addr);
forw_packet->skb = NULL;
- return;
+ goto out;
}
/* broadcast on every interface */
@@ -212,28 +216,24 @@
send_packet_to_if(forw_packet, hard_iface);
}
rcu_read_unlock();
+
+out:
+ if (primary_if)
+ hardif_free_ref(primary_if);
}
-static void rebuild_batman_packet(struct bat_priv *bat_priv,
- struct hard_iface *hard_iface)
+static void realloc_packet_buffer(struct hard_iface *hard_iface,
+ int new_len)
{
- int new_len;
unsigned char *new_buff;
struct batman_packet *batman_packet;
- new_len = sizeof(struct batman_packet) +
- (bat_priv->num_local_tt * ETH_ALEN);
new_buff = kmalloc(new_len, GFP_ATOMIC);
/* keep old buffer if kmalloc should fail */
if (new_buff) {
memcpy(new_buff, hard_iface->packet_buff,
- sizeof(struct batman_packet));
- batman_packet = (struct batman_packet *)new_buff;
-
- batman_packet->num_tt = tt_local_fill_buffer(bat_priv,
- new_buff + sizeof(struct batman_packet),
- new_len - sizeof(struct batman_packet));
+ sizeof(*batman_packet));
kfree(hard_iface->packet_buff);
hard_iface->packet_buff = new_buff;
@@ -241,6 +241,46 @@
}
}
+/* when calling this function (hard_iface == primary_if) has to be true */
+static void prepare_packet_buffer(struct bat_priv *bat_priv,
+ struct hard_iface *hard_iface)
+{
+ int new_len;
+ struct batman_packet *batman_packet;
+
+ new_len = BAT_PACKET_LEN +
+ tt_len((uint8_t)atomic_read(&bat_priv->tt_local_changes));
+
+ /* if we have too many changes for one packet don't send any
+ * and wait for the tt table request which will be fragmented */
+ if (new_len > hard_iface->soft_iface->mtu)
+ new_len = BAT_PACKET_LEN;
+
+ realloc_packet_buffer(hard_iface, new_len);
+ batman_packet = (struct batman_packet *)hard_iface->packet_buff;
+
+ atomic_set(&bat_priv->tt_crc, tt_local_crc(bat_priv));
+
+ /* reset the sending counter */
+ atomic_set(&bat_priv->tt_ogm_append_cnt, TT_OGM_APPEND_MAX);
+
+ batman_packet->tt_num_changes = tt_changes_fill_buffer(bat_priv,
+ hard_iface->packet_buff + BAT_PACKET_LEN,
+ hard_iface->packet_len - BAT_PACKET_LEN);
+
+}
+
+static void reset_packet_buffer(struct bat_priv *bat_priv,
+ struct hard_iface *hard_iface)
+{
+ struct batman_packet *batman_packet;
+
+ realloc_packet_buffer(hard_iface, BAT_PACKET_LEN);
+
+ batman_packet = (struct batman_packet *)hard_iface->packet_buff;
+ batman_packet->tt_num_changes = 0;
+}
+
void schedule_own_packet(struct hard_iface *hard_iface)
{
struct bat_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
@@ -266,14 +306,23 @@
if (hard_iface->if_status == IF_TO_BE_ACTIVATED)
hard_iface->if_status = IF_ACTIVE;
- /* if local tt has changed and interface is a primary interface */
- if ((atomic_read(&bat_priv->tt_local_changed)) &&
- (hard_iface == primary_if))
- rebuild_batman_packet(bat_priv, hard_iface);
+ if (hard_iface == primary_if) {
+ /* if at least one change happened */
+ if (atomic_read(&bat_priv->tt_local_changes) > 0) {
+ prepare_packet_buffer(bat_priv, hard_iface);
+ /* Increment the TTVN only once per OGM interval */
+ atomic_inc(&bat_priv->ttvn);
+ bat_priv->tt_poss_change = false;
+ }
+
+ /* if the changes have been sent enough times */
+ if (!atomic_dec_not_zero(&bat_priv->tt_ogm_append_cnt))
+ reset_packet_buffer(bat_priv, hard_iface);
+ }
/**
* NOTE: packet_buff might just have been re-allocated in
- * rebuild_batman_packet()
+ * prepare_packet_buffer() or in reset_packet_buffer()
*/
batman_packet = (struct batman_packet *)hard_iface->packet_buff;
@@ -281,6 +330,9 @@
batman_packet->seqno =
htonl((uint32_t)atomic_read(&hard_iface->seqno));
+ batman_packet->ttvn = atomic_read(&bat_priv->ttvn);
+ batman_packet->tt_crc = htons((uint16_t)atomic_read(&bat_priv->tt_crc));
+
if (vis_server == VIS_TYPE_SERVER_SYNC)
batman_packet->flags |= VIS_SERVER;
else
@@ -291,7 +343,7 @@
batman_packet->gw_flags =
(uint8_t)atomic_read(&bat_priv->gw_bandwidth);
else
- batman_packet->gw_flags = 0;
+ batman_packet->gw_flags = NO_FLAGS;
atomic_inc(&hard_iface->seqno);
@@ -307,15 +359,16 @@
}
void schedule_forward_packet(struct orig_node *orig_node,
- struct ethhdr *ethhdr,
+ const struct ethhdr *ethhdr,
struct batman_packet *batman_packet,
- uint8_t directlink, int tt_buff_len,
+ int directlink,
struct hard_iface *if_incoming)
{
struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface);
struct neigh_node *router;
- unsigned char in_tq, in_ttl, tq_avg = 0;
+ uint8_t in_tq, in_ttl, tq_avg = 0;
unsigned long send_time;
+ uint8_t tt_num_changes;
if (batman_packet->ttl <= 1) {
bat_dbg(DBG_BATMAN, bat_priv, "ttl exceeded\n");
@@ -326,6 +379,7 @@
in_tq = batman_packet->tq;
in_ttl = batman_packet->ttl;
+ tt_num_changes = batman_packet->tt_num_changes;
batman_packet->ttl--;
memcpy(batman_packet->prev_sender, ethhdr->h_source, ETH_ALEN);
@@ -358,6 +412,7 @@
batman_packet->ttl);
batman_packet->seqno = htonl(batman_packet->seqno);
+ batman_packet->tt_crc = htons(batman_packet->tt_crc);
/* switch of primaries first hop flag when forwarding */
batman_packet->flags &= ~PRIMARIES_FIRST_HOP;
@@ -369,7 +424,7 @@
send_time = forward_send_time();
add_bat_packet_to_list(bat_priv,
(unsigned char *)batman_packet,
- sizeof(struct batman_packet) + tt_buff_len,
+ sizeof(*batman_packet) + tt_len(tt_num_changes),
if_incoming, 0, send_time);
}
@@ -408,11 +463,13 @@
*
* The skb is not consumed, so the caller should make sure that the
* skb is freed. */
-int add_bcast_packet_to_list(struct bat_priv *bat_priv, struct sk_buff *skb)
+int add_bcast_packet_to_list(struct bat_priv *bat_priv,
+ const struct sk_buff *skb, unsigned long delay)
{
struct hard_iface *primary_if = NULL;
struct forw_packet *forw_packet;
struct bcast_packet *bcast_packet;
+ struct sk_buff *newskb;
if (!atomic_dec_not_zero(&bat_priv->bcast_queue_left)) {
bat_dbg(DBG_BATMAN, bat_priv, "bcast packet queue full\n");
@@ -423,28 +480,28 @@
if (!primary_if)
goto out_and_inc;
- forw_packet = kmalloc(sizeof(struct forw_packet), GFP_ATOMIC);
+ forw_packet = kmalloc(sizeof(*forw_packet), GFP_ATOMIC);
if (!forw_packet)
goto out_and_inc;
- skb = skb_copy(skb, GFP_ATOMIC);
- if (!skb)
+ newskb = skb_copy(skb, GFP_ATOMIC);
+ if (!newskb)
goto packet_free;
/* as we have a copy now, it is safe to decrease the TTL */
- bcast_packet = (struct bcast_packet *)skb->data;
+ bcast_packet = (struct bcast_packet *)newskb->data;
bcast_packet->ttl--;
- skb_reset_mac_header(skb);
+ skb_reset_mac_header(newskb);
- forw_packet->skb = skb;
+ forw_packet->skb = newskb;
forw_packet->if_incoming = primary_if;
/* how often did we send the bcast packet ? */
forw_packet->num_packets = 0;
- _add_bcast_packet_to_list(bat_priv, forw_packet, 1);
+ _add_bcast_packet_to_list(bat_priv, forw_packet, delay);
return NETDEV_TX_OK;
packet_free:
@@ -537,7 +594,7 @@
}
void purge_outstanding_packets(struct bat_priv *bat_priv,
- struct hard_iface *hard_iface)
+ const struct hard_iface *hard_iface)
{
struct forw_packet *forw_packet;
struct hlist_node *tmp_node, *safe_tmp_node;
diff --git a/net/batman-adv/send.h b/net/batman-adv/send.h
index 247172d..1f2d1e8 100644
--- a/net/batman-adv/send.h
+++ b/net/batman-adv/send.h
@@ -22,18 +22,18 @@
#ifndef _NET_BATMAN_ADV_SEND_H_
#define _NET_BATMAN_ADV_SEND_H_
-int send_skb_packet(struct sk_buff *skb,
- struct hard_iface *hard_iface,
- uint8_t *dst_addr);
+int send_skb_packet(struct sk_buff *skb, struct hard_iface *hard_iface,
+ const uint8_t *dst_addr);
void schedule_own_packet(struct hard_iface *hard_iface);
void schedule_forward_packet(struct orig_node *orig_node,
- struct ethhdr *ethhdr,
+ const struct ethhdr *ethhdr,
struct batman_packet *batman_packet,
- uint8_t directlink, int tt_buff_len,
+ int directlink,
struct hard_iface *if_outgoing);
-int add_bcast_packet_to_list(struct bat_priv *bat_priv, struct sk_buff *skb);
+int add_bcast_packet_to_list(struct bat_priv *bat_priv,
+ const struct sk_buff *skb, unsigned long delay);
void send_outstanding_bat_packet(struct work_struct *work);
void purge_outstanding_packets(struct bat_priv *bat_priv,
- struct hard_iface *hard_iface);
+ const struct hard_iface *hard_iface);
#endif /* _NET_BATMAN_ADV_SEND_H_ */
diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c
index d5aa609..3f20332 100644
--- a/net/batman-adv/soft-interface.c
+++ b/net/batman-adv/soft-interface.c
@@ -30,6 +30,7 @@
#include "gateway_common.h"
#include "gateway_client.h"
#include "bat_sysfs.h"
+#include "originator.h"
#include <linux/slab.h>
#include <linux/ethtool.h>
#include <linux/etherdevice.h>
@@ -123,8 +124,7 @@
goto out;
}
- softif_neigh_vid = kzalloc(sizeof(struct softif_neigh_vid),
- GFP_ATOMIC);
+ softif_neigh_vid = kzalloc(sizeof(*softif_neigh_vid), GFP_ATOMIC);
if (!softif_neigh_vid)
goto out;
@@ -146,7 +146,7 @@
}
static struct softif_neigh *softif_neigh_get(struct bat_priv *bat_priv,
- uint8_t *addr, short vid)
+ const uint8_t *addr, short vid)
{
struct softif_neigh_vid *softif_neigh_vid;
struct softif_neigh *softif_neigh = NULL;
@@ -170,7 +170,7 @@
goto unlock;
}
- softif_neigh = kzalloc(sizeof(struct softif_neigh), GFP_ATOMIC);
+ softif_neigh = kzalloc(sizeof(*softif_neigh), GFP_ATOMIC);
if (!softif_neigh)
goto unlock;
@@ -242,7 +242,8 @@
if (new_neigh && !atomic_inc_not_zero(&new_neigh->refcount))
new_neigh = NULL;
- curr_neigh = softif_neigh_vid->softif_neigh;
+ curr_neigh = rcu_dereference_protected(softif_neigh_vid->softif_neigh,
+ 1);
rcu_assign_pointer(softif_neigh_vid->softif_neigh, new_neigh);
if ((curr_neigh) && (!new_neigh))
@@ -380,7 +381,7 @@
struct softif_neigh *softif_neigh, *curr_softif_neigh;
struct softif_neigh_vid *softif_neigh_vid;
struct hlist_node *node, *node_tmp, *node_tmp2;
- char do_deselect;
+ int do_deselect;
rcu_read_lock();
hlist_for_each_entry_rcu(softif_neigh_vid, node,
@@ -534,7 +535,7 @@
/* only modify transtable if it has been initialised before */
if (atomic_read(&bat_priv->mesh_state) == MESH_ACTIVE) {
tt_local_remove(bat_priv, dev->dev_addr,
- "mac address changed");
+ "mac address changed", false);
tt_local_add(dev, addr->sa_data);
}
@@ -553,7 +554,7 @@
return 0;
}
-int interface_tx(struct sk_buff *skb, struct net_device *soft_iface)
+static int interface_tx(struct sk_buff *skb, struct net_device *soft_iface)
{
struct ethhdr *ethhdr = (struct ethhdr *)skb->data;
struct bat_priv *bat_priv = netdev_priv(soft_iface);
@@ -561,6 +562,7 @@
struct bcast_packet *bcast_packet;
struct vlan_ethhdr *vhdr;
struct softif_neigh *curr_softif_neigh = NULL;
+ struct orig_node *orig_node = NULL;
int data_len = skb->len, ret;
short vid = -1;
bool do_bcast = false;
@@ -592,11 +594,13 @@
if (curr_softif_neigh)
goto dropped;
- /* TODO: check this for locks */
+ /* Register the client MAC in the transtable */
tt_local_add(soft_iface, ethhdr->h_source);
- if (is_multicast_ether_addr(ethhdr->h_dest)) {
- ret = gw_is_target(bat_priv, skb);
+ orig_node = transtable_search(bat_priv, ethhdr->h_dest);
+ if (is_multicast_ether_addr(ethhdr->h_dest) ||
+ (orig_node && orig_node->gw_flags)) {
+ ret = gw_is_target(bat_priv, skb, orig_node);
if (ret < 0)
goto dropped;
@@ -611,7 +615,7 @@
if (!primary_if)
goto dropped;
- if (my_skb_head_push(skb, sizeof(struct bcast_packet)) < 0)
+ if (my_skb_head_push(skb, sizeof(*bcast_packet)) < 0)
goto dropped;
bcast_packet = (struct bcast_packet *)skb->data;
@@ -630,7 +634,7 @@
bcast_packet->seqno =
htonl(atomic_inc_return(&bat_priv->bcast_seqno));
- add_bcast_packet_to_list(bat_priv, skb);
+ add_bcast_packet_to_list(bat_priv, skb, 1);
/* a copy is stored in the bcast list, therefore removing
* the original skb. */
@@ -656,6 +660,8 @@
softif_neigh_free_ref(curr_softif_neigh);
if (primary_if)
hardif_free_ref(primary_if);
+ if (orig_node)
+ orig_node_free_ref(orig_node);
return NETDEV_TX_OK;
}
@@ -790,17 +796,16 @@
SET_ETHTOOL_OPS(dev, &bat_ethtool_ops);
- memset(priv, 0, sizeof(struct bat_priv));
+ memset(priv, 0, sizeof(*priv));
}
-struct net_device *softif_create(char *name)
+struct net_device *softif_create(const char *name)
{
struct net_device *soft_iface;
struct bat_priv *bat_priv;
int ret;
- soft_iface = alloc_netdev(sizeof(struct bat_priv) , name,
- interface_setup);
+ soft_iface = alloc_netdev(sizeof(*bat_priv), name, interface_setup);
if (!soft_iface) {
pr_err("Unable to allocate the batman interface: %s\n", name);
@@ -831,7 +836,13 @@
atomic_set(&bat_priv->mesh_state, MESH_INACTIVE);
atomic_set(&bat_priv->bcast_seqno, 1);
- atomic_set(&bat_priv->tt_local_changed, 0);
+ atomic_set(&bat_priv->ttvn, 0);
+ atomic_set(&bat_priv->tt_local_changes, 0);
+ atomic_set(&bat_priv->tt_ogm_append_cnt, 0);
+
+ bat_priv->tt_buff = NULL;
+ bat_priv->tt_buff_len = 0;
+ bat_priv->tt_poss_change = false;
bat_priv->primary_if = NULL;
bat_priv->num_ifaces = 0;
@@ -872,7 +883,7 @@
unregister_netdevice(soft_iface);
}
-int softif_is_valid(struct net_device *net_dev)
+int softif_is_valid(const struct net_device *net_dev)
{
#ifdef HAVE_NET_DEVICE_OPS
if (net_dev->netdev_ops->ndo_start_xmit == interface_tx)
@@ -924,4 +935,3 @@
{
return 1;
}
-
diff --git a/net/batman-adv/soft-interface.h b/net/batman-adv/soft-interface.h
index 4789b6f..001546f 100644
--- a/net/batman-adv/soft-interface.h
+++ b/net/batman-adv/soft-interface.h
@@ -25,12 +25,11 @@
int my_skb_head_push(struct sk_buff *skb, unsigned int len);
int softif_neigh_seq_print_text(struct seq_file *seq, void *offset);
void softif_neigh_purge(struct bat_priv *bat_priv);
-int interface_tx(struct sk_buff *skb, struct net_device *soft_iface);
void interface_rx(struct net_device *soft_iface,
struct sk_buff *skb, struct hard_iface *recv_if,
int hdr_size);
-struct net_device *softif_create(char *name);
+struct net_device *softif_create(const char *name);
void softif_destroy(struct net_device *soft_iface);
-int softif_is_valid(struct net_device *net_dev);
+int softif_is_valid(const struct net_device *net_dev);
#endif /* _NET_BATMAN_ADV_SOFT_INTERFACE_H_ */
diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c
index 7b72966..06d361d 100644
--- a/net/batman-adv/translation-table.c
+++ b/net/batman-adv/translation-table.c
@@ -23,38 +23,45 @@
#include "translation-table.h"
#include "soft-interface.h"
#include "hard-interface.h"
+#include "send.h"
#include "hash.h"
#include "originator.h"
+#include "routing.h"
-static void tt_local_purge(struct work_struct *work);
-static void _tt_global_del_orig(struct bat_priv *bat_priv,
- struct tt_global_entry *tt_global_entry,
- char *message);
+#include <linux/crc16.h>
+
+static void _tt_global_del(struct bat_priv *bat_priv,
+ struct tt_global_entry *tt_global_entry,
+ const char *message);
+static void tt_purge(struct work_struct *work);
/* returns 1 if they are the same mac addr */
-static int compare_ltt(struct hlist_node *node, void *data2)
+static int compare_ltt(const struct hlist_node *node, const void *data2)
{
- void *data1 = container_of(node, struct tt_local_entry, hash_entry);
+ const void *data1 = container_of(node, struct tt_local_entry,
+ hash_entry);
return (memcmp(data1, data2, ETH_ALEN) == 0 ? 1 : 0);
}
/* returns 1 if they are the same mac addr */
-static int compare_gtt(struct hlist_node *node, void *data2)
+static int compare_gtt(const struct hlist_node *node, const void *data2)
{
- void *data1 = container_of(node, struct tt_global_entry, hash_entry);
+ const void *data1 = container_of(node, struct tt_global_entry,
+ hash_entry);
return (memcmp(data1, data2, ETH_ALEN) == 0 ? 1 : 0);
}
-static void tt_local_start_timer(struct bat_priv *bat_priv)
+static void tt_start_timer(struct bat_priv *bat_priv)
{
- INIT_DELAYED_WORK(&bat_priv->tt_work, tt_local_purge);
- queue_delayed_work(bat_event_workqueue, &bat_priv->tt_work, 10 * HZ);
+ INIT_DELAYED_WORK(&bat_priv->tt_work, tt_purge);
+ queue_delayed_work(bat_event_workqueue, &bat_priv->tt_work,
+ msecs_to_jiffies(5000));
}
static struct tt_local_entry *tt_local_hash_find(struct bat_priv *bat_priv,
- void *data)
+ const void *data)
{
struct hashtable_t *hash = bat_priv->tt_local_hash;
struct hlist_head *head;
@@ -73,6 +80,9 @@
if (!compare_eth(tt_local_entry, data))
continue;
+ if (!atomic_inc_not_zero(&tt_local_entry->refcount))
+ continue;
+
tt_local_entry_tmp = tt_local_entry;
break;
}
@@ -82,7 +92,7 @@
}
static struct tt_global_entry *tt_global_hash_find(struct bat_priv *bat_priv,
- void *data)
+ const void *data)
{
struct hashtable_t *hash = bat_priv->tt_global_hash;
struct hlist_head *head;
@@ -102,6 +112,9 @@
if (!compare_eth(tt_global_entry, data))
continue;
+ if (!atomic_inc_not_zero(&tt_global_entry->refcount))
+ continue;
+
tt_global_entry_tmp = tt_global_entry;
break;
}
@@ -110,7 +123,54 @@
return tt_global_entry_tmp;
}
-int tt_local_init(struct bat_priv *bat_priv)
+static bool is_out_of_time(unsigned long starting_time, unsigned long timeout)
+{
+ unsigned long deadline;
+ deadline = starting_time + msecs_to_jiffies(timeout);
+
+ return time_after(jiffies, deadline);
+}
+
+static void tt_local_entry_free_ref(struct tt_local_entry *tt_local_entry)
+{
+ if (atomic_dec_and_test(&tt_local_entry->refcount))
+ kfree_rcu(tt_local_entry, rcu);
+}
+
+static void tt_global_entry_free_ref(struct tt_global_entry *tt_global_entry)
+{
+ if (atomic_dec_and_test(&tt_global_entry->refcount))
+ kfree_rcu(tt_global_entry, rcu);
+}
+
+static void tt_local_event(struct bat_priv *bat_priv, const uint8_t *addr,
+ uint8_t flags)
+{
+ struct tt_change_node *tt_change_node;
+
+ tt_change_node = kmalloc(sizeof(*tt_change_node), GFP_ATOMIC);
+
+ if (!tt_change_node)
+ return;
+
+ tt_change_node->change.flags = flags;
+ memcpy(tt_change_node->change.addr, addr, ETH_ALEN);
+
+ spin_lock_bh(&bat_priv->tt_changes_list_lock);
+ /* track the change in the OGMinterval list */
+ list_add_tail(&tt_change_node->list, &bat_priv->tt_changes_list);
+ atomic_inc(&bat_priv->tt_local_changes);
+ spin_unlock_bh(&bat_priv->tt_changes_list_lock);
+
+ atomic_set(&bat_priv->tt_ogm_append_cnt, 0);
+}
+
+int tt_len(int changes_num)
+{
+ return changes_num * sizeof(struct tt_change);
+}
+
+static int tt_local_init(struct bat_priv *bat_priv)
{
if (bat_priv->tt_local_hash)
return 1;
@@ -120,116 +180,110 @@
if (!bat_priv->tt_local_hash)
return 0;
- atomic_set(&bat_priv->tt_local_changed, 0);
- tt_local_start_timer(bat_priv);
-
return 1;
}
-void tt_local_add(struct net_device *soft_iface, uint8_t *addr)
+void tt_local_add(struct net_device *soft_iface, const uint8_t *addr)
{
struct bat_priv *bat_priv = netdev_priv(soft_iface);
- struct tt_local_entry *tt_local_entry;
- struct tt_global_entry *tt_global_entry;
- int required_bytes;
+ struct tt_local_entry *tt_local_entry = NULL;
+ struct tt_global_entry *tt_global_entry = NULL;
- spin_lock_bh(&bat_priv->tt_lhash_lock);
tt_local_entry = tt_local_hash_find(bat_priv, addr);
- spin_unlock_bh(&bat_priv->tt_lhash_lock);
if (tt_local_entry) {
tt_local_entry->last_seen = jiffies;
- return;
+ goto out;
}
- /* only announce as many hosts as possible in the batman-packet and
- space in batman_packet->num_tt That also should give a limit to
- MAC-flooding. */
- required_bytes = (bat_priv->num_local_tt + 1) * ETH_ALEN;
- required_bytes += BAT_PACKET_LEN;
-
- if ((required_bytes > ETH_DATA_LEN) ||
- (atomic_read(&bat_priv->aggregated_ogms) &&
- required_bytes > MAX_AGGREGATION_BYTES) ||
- (bat_priv->num_local_tt + 1 > 255)) {
- bat_dbg(DBG_ROUTES, bat_priv,
- "Can't add new local tt entry (%pM): "
- "number of local tt entries exceeds packet size\n",
- addr);
- return;
- }
-
- bat_dbg(DBG_ROUTES, bat_priv,
- "Creating new local tt entry: %pM\n", addr);
-
- tt_local_entry = kmalloc(sizeof(struct tt_local_entry), GFP_ATOMIC);
+ tt_local_entry = kmalloc(sizeof(*tt_local_entry), GFP_ATOMIC);
if (!tt_local_entry)
- return;
+ goto out;
+
+ bat_dbg(DBG_TT, bat_priv,
+ "Creating new local tt entry: %pM (ttvn: %d)\n", addr,
+ (uint8_t)atomic_read(&bat_priv->ttvn));
memcpy(tt_local_entry->addr, addr, ETH_ALEN);
tt_local_entry->last_seen = jiffies;
+ tt_local_entry->flags = NO_FLAGS;
+ atomic_set(&tt_local_entry->refcount, 2);
/* the batman interface mac address should never be purged */
if (compare_eth(addr, soft_iface->dev_addr))
- tt_local_entry->never_purge = 1;
- else
- tt_local_entry->never_purge = 0;
+ tt_local_entry->flags |= TT_CLIENT_NOPURGE;
- spin_lock_bh(&bat_priv->tt_lhash_lock);
+ tt_local_event(bat_priv, addr, tt_local_entry->flags);
hash_add(bat_priv->tt_local_hash, compare_ltt, choose_orig,
tt_local_entry, &tt_local_entry->hash_entry);
- bat_priv->num_local_tt++;
- atomic_set(&bat_priv->tt_local_changed, 1);
- spin_unlock_bh(&bat_priv->tt_lhash_lock);
+ atomic_inc(&bat_priv->num_local_tt);
/* remove address from global hash if present */
- spin_lock_bh(&bat_priv->tt_ghash_lock);
-
tt_global_entry = tt_global_hash_find(bat_priv, addr);
+ /* Check whether it is a roaming! */
+ if (tt_global_entry) {
+ /* This node is probably going to update its tt table */
+ tt_global_entry->orig_node->tt_poss_change = true;
+ _tt_global_del(bat_priv, tt_global_entry,
+ "local tt received");
+ send_roam_adv(bat_priv, tt_global_entry->addr,
+ tt_global_entry->orig_node);
+ }
+out:
+ if (tt_local_entry)
+ tt_local_entry_free_ref(tt_local_entry);
if (tt_global_entry)
- _tt_global_del_orig(bat_priv, tt_global_entry,
- "local tt received");
-
- spin_unlock_bh(&bat_priv->tt_ghash_lock);
+ tt_global_entry_free_ref(tt_global_entry);
}
-int tt_local_fill_buffer(struct bat_priv *bat_priv,
- unsigned char *buff, int buff_len)
+int tt_changes_fill_buffer(struct bat_priv *bat_priv,
+ unsigned char *buff, int buff_len)
{
- struct hashtable_t *hash = bat_priv->tt_local_hash;
- struct tt_local_entry *tt_local_entry;
- struct hlist_node *node;
- struct hlist_head *head;
- int i, count = 0;
+ int count = 0, tot_changes = 0;
+ struct tt_change_node *entry, *safe;
- spin_lock_bh(&bat_priv->tt_lhash_lock);
+ if (buff_len > 0)
+ tot_changes = buff_len / tt_len(1);
- for (i = 0; i < hash->size; i++) {
- head = &hash->table[i];
+ spin_lock_bh(&bat_priv->tt_changes_list_lock);
+ atomic_set(&bat_priv->tt_local_changes, 0);
- rcu_read_lock();
- hlist_for_each_entry_rcu(tt_local_entry, node,
- head, hash_entry) {
- if (buff_len < (count + 1) * ETH_ALEN)
- break;
-
- memcpy(buff + (count * ETH_ALEN), tt_local_entry->addr,
- ETH_ALEN);
-
+ list_for_each_entry_safe(entry, safe, &bat_priv->tt_changes_list,
+ list) {
+ if (count < tot_changes) {
+ memcpy(buff + tt_len(count),
+ &entry->change, sizeof(struct tt_change));
count++;
}
- rcu_read_unlock();
+ list_del(&entry->list);
+ kfree(entry);
}
+ spin_unlock_bh(&bat_priv->tt_changes_list_lock);
- /* if we did not get all new local tts see you next time ;-) */
- if (count == bat_priv->num_local_tt)
- atomic_set(&bat_priv->tt_local_changed, 0);
+ /* Keep the buffer for possible tt_request */
+ spin_lock_bh(&bat_priv->tt_buff_lock);
+ kfree(bat_priv->tt_buff);
+ bat_priv->tt_buff_len = 0;
+ bat_priv->tt_buff = NULL;
+ /* We check whether this new OGM has no changes due to size
+ * problems */
+ if (buff_len > 0) {
+ /**
+ * if kmalloc() fails we will reply with the full table
+ * instead of providing the diff
+ */
+ bat_priv->tt_buff = kmalloc(buff_len, GFP_ATOMIC);
+ if (bat_priv->tt_buff) {
+ memcpy(bat_priv->tt_buff, buff, buff_len);
+ bat_priv->tt_buff_len = buff_len;
+ }
+ }
+ spin_unlock_bh(&bat_priv->tt_buff_lock);
- spin_unlock_bh(&bat_priv->tt_lhash_lock);
- return count;
+ return tot_changes;
}
int tt_local_seq_print_text(struct seq_file *seq, void *offset)
@@ -261,10 +315,8 @@
}
seq_printf(seq, "Locally retrieved addresses (from %s) "
- "announced via TT:\n",
- net_dev->name);
-
- spin_lock_bh(&bat_priv->tt_lhash_lock);
+ "announced via TT (TTVN: %u):\n",
+ net_dev->name, (uint8_t)atomic_read(&bat_priv->ttvn));
buf_size = 1;
/* Estimate length for: " * xx:xx:xx:xx:xx:xx\n" */
@@ -279,7 +331,6 @@
buff = kmalloc(buf_size, GFP_ATOMIC);
if (!buff) {
- spin_unlock_bh(&bat_priv->tt_lhash_lock);
ret = -ENOMEM;
goto out;
}
@@ -299,8 +350,6 @@
rcu_read_unlock();
}
- spin_unlock_bh(&bat_priv->tt_lhash_lock);
-
seq_printf(seq, "%s", buff);
kfree(buff);
out:
@@ -309,92 +358,110 @@
return ret;
}
-static void _tt_local_del(struct hlist_node *node, void *arg)
-{
- struct bat_priv *bat_priv = (struct bat_priv *)arg;
- void *data = container_of(node, struct tt_local_entry, hash_entry);
-
- kfree(data);
- bat_priv->num_local_tt--;
- atomic_set(&bat_priv->tt_local_changed, 1);
-}
-
static void tt_local_del(struct bat_priv *bat_priv,
- struct tt_local_entry *tt_local_entry,
- char *message)
+ struct tt_local_entry *tt_local_entry,
+ const char *message)
{
- bat_dbg(DBG_ROUTES, bat_priv, "Deleting local tt entry (%pM): %s\n",
+ bat_dbg(DBG_TT, bat_priv, "Deleting local tt entry (%pM): %s\n",
tt_local_entry->addr, message);
+ atomic_dec(&bat_priv->num_local_tt);
+
hash_remove(bat_priv->tt_local_hash, compare_ltt, choose_orig,
tt_local_entry->addr);
- _tt_local_del(&tt_local_entry->hash_entry, bat_priv);
+
+ tt_local_entry_free_ref(tt_local_entry);
}
-void tt_local_remove(struct bat_priv *bat_priv,
- uint8_t *addr, char *message)
+void tt_local_remove(struct bat_priv *bat_priv, const uint8_t *addr,
+ const char *message, bool roaming)
{
- struct tt_local_entry *tt_local_entry;
-
- spin_lock_bh(&bat_priv->tt_lhash_lock);
+ struct tt_local_entry *tt_local_entry = NULL;
tt_local_entry = tt_local_hash_find(bat_priv, addr);
- if (tt_local_entry)
- tt_local_del(bat_priv, tt_local_entry, message);
+ if (!tt_local_entry)
+ goto out;
- spin_unlock_bh(&bat_priv->tt_lhash_lock);
+ tt_local_event(bat_priv, tt_local_entry->addr,
+ tt_local_entry->flags | TT_CLIENT_DEL |
+ (roaming ? TT_CLIENT_ROAM : NO_FLAGS));
+ tt_local_del(bat_priv, tt_local_entry, message);
+out:
+ if (tt_local_entry)
+ tt_local_entry_free_ref(tt_local_entry);
}
-static void tt_local_purge(struct work_struct *work)
+static void tt_local_purge(struct bat_priv *bat_priv)
{
- struct delayed_work *delayed_work =
- container_of(work, struct delayed_work, work);
- struct bat_priv *bat_priv =
- container_of(delayed_work, struct bat_priv, tt_work);
struct hashtable_t *hash = bat_priv->tt_local_hash;
struct tt_local_entry *tt_local_entry;
struct hlist_node *node, *node_tmp;
struct hlist_head *head;
- unsigned long timeout;
+ spinlock_t *list_lock; /* protects write access to the hash lists */
int i;
- spin_lock_bh(&bat_priv->tt_lhash_lock);
-
for (i = 0; i < hash->size; i++) {
head = &hash->table[i];
+ list_lock = &hash->list_locks[i];
+ spin_lock_bh(list_lock);
hlist_for_each_entry_safe(tt_local_entry, node, node_tmp,
head, hash_entry) {
- if (tt_local_entry->never_purge)
+ if (tt_local_entry->flags & TT_CLIENT_NOPURGE)
continue;
- timeout = tt_local_entry->last_seen;
- timeout += TT_LOCAL_TIMEOUT * HZ;
-
- if (time_before(jiffies, timeout))
+ if (!is_out_of_time(tt_local_entry->last_seen,
+ TT_LOCAL_TIMEOUT * 1000))
continue;
- tt_local_del(bat_priv, tt_local_entry,
- "address timed out");
+ tt_local_event(bat_priv, tt_local_entry->addr,
+ tt_local_entry->flags | TT_CLIENT_DEL);
+ atomic_dec(&bat_priv->num_local_tt);
+ bat_dbg(DBG_TT, bat_priv, "Deleting local "
+ "tt entry (%pM): timed out\n",
+ tt_local_entry->addr);
+ hlist_del_rcu(node);
+ tt_local_entry_free_ref(tt_local_entry);
}
+ spin_unlock_bh(list_lock);
}
- spin_unlock_bh(&bat_priv->tt_lhash_lock);
- tt_local_start_timer(bat_priv);
}
-void tt_local_free(struct bat_priv *bat_priv)
+static void tt_local_table_free(struct bat_priv *bat_priv)
{
+ struct hashtable_t *hash;
+ spinlock_t *list_lock; /* protects write access to the hash lists */
+ struct tt_local_entry *tt_local_entry;
+ struct hlist_node *node, *node_tmp;
+ struct hlist_head *head;
+ int i;
+
if (!bat_priv->tt_local_hash)
return;
- cancel_delayed_work_sync(&bat_priv->tt_work);
- hash_delete(bat_priv->tt_local_hash, _tt_local_del, bat_priv);
+ hash = bat_priv->tt_local_hash;
+
+ for (i = 0; i < hash->size; i++) {
+ head = &hash->table[i];
+ list_lock = &hash->list_locks[i];
+
+ spin_lock_bh(list_lock);
+ hlist_for_each_entry_safe(tt_local_entry, node, node_tmp,
+ head, hash_entry) {
+ hlist_del_rcu(node);
+ tt_local_entry_free_ref(tt_local_entry);
+ }
+ spin_unlock_bh(list_lock);
+ }
+
+ hash_destroy(hash);
+
bat_priv->tt_local_hash = NULL;
}
-int tt_global_init(struct bat_priv *bat_priv)
+static int tt_global_init(struct bat_priv *bat_priv)
{
if (bat_priv->tt_global_hash)
return 1;
@@ -407,74 +474,78 @@
return 1;
}
-void tt_global_add_orig(struct bat_priv *bat_priv,
- struct orig_node *orig_node,
- unsigned char *tt_buff, int tt_buff_len)
+static void tt_changes_list_free(struct bat_priv *bat_priv)
+{
+ struct tt_change_node *entry, *safe;
+
+ spin_lock_bh(&bat_priv->tt_changes_list_lock);
+
+ list_for_each_entry_safe(entry, safe, &bat_priv->tt_changes_list,
+ list) {
+ list_del(&entry->list);
+ kfree(entry);
+ }
+
+ atomic_set(&bat_priv->tt_local_changes, 0);
+ spin_unlock_bh(&bat_priv->tt_changes_list_lock);
+}
+
+/* caller must hold orig_node refcount */
+int tt_global_add(struct bat_priv *bat_priv, struct orig_node *orig_node,
+ const unsigned char *tt_addr, uint8_t ttvn, bool roaming)
{
struct tt_global_entry *tt_global_entry;
- struct tt_local_entry *tt_local_entry;
- int tt_buff_count = 0;
- unsigned char *tt_ptr;
+ struct orig_node *orig_node_tmp;
+ int ret = 0;
- while ((tt_buff_count + 1) * ETH_ALEN <= tt_buff_len) {
- spin_lock_bh(&bat_priv->tt_ghash_lock);
+ tt_global_entry = tt_global_hash_find(bat_priv, tt_addr);
- tt_ptr = tt_buff + (tt_buff_count * ETH_ALEN);
- tt_global_entry = tt_global_hash_find(bat_priv, tt_ptr);
+ if (!tt_global_entry) {
+ tt_global_entry =
+ kmalloc(sizeof(*tt_global_entry),
+ GFP_ATOMIC);
+ if (!tt_global_entry)
+ goto out;
- if (!tt_global_entry) {
- spin_unlock_bh(&bat_priv->tt_ghash_lock);
-
- tt_global_entry =
- kmalloc(sizeof(struct tt_global_entry),
- GFP_ATOMIC);
-
- if (!tt_global_entry)
- break;
-
- memcpy(tt_global_entry->addr, tt_ptr, ETH_ALEN);
-
- bat_dbg(DBG_ROUTES, bat_priv,
- "Creating new global tt entry: "
- "%pM (via %pM)\n",
- tt_global_entry->addr, orig_node->orig);
-
- spin_lock_bh(&bat_priv->tt_ghash_lock);
- hash_add(bat_priv->tt_global_hash, compare_gtt,
- choose_orig, tt_global_entry,
- &tt_global_entry->hash_entry);
-
- }
-
+ memcpy(tt_global_entry->addr, tt_addr, ETH_ALEN);
+ /* Assign the new orig_node */
+ atomic_inc(&orig_node->refcount);
tt_global_entry->orig_node = orig_node;
- spin_unlock_bh(&bat_priv->tt_ghash_lock);
+ tt_global_entry->ttvn = ttvn;
+ tt_global_entry->flags = NO_FLAGS;
+ tt_global_entry->roam_at = 0;
+ atomic_set(&tt_global_entry->refcount, 2);
- /* remove address from local hash if present */
- spin_lock_bh(&bat_priv->tt_lhash_lock);
-
- tt_ptr = tt_buff + (tt_buff_count * ETH_ALEN);
- tt_local_entry = tt_local_hash_find(bat_priv, tt_ptr);
-
- if (tt_local_entry)
- tt_local_del(bat_priv, tt_local_entry,
- "global tt received");
-
- spin_unlock_bh(&bat_priv->tt_lhash_lock);
-
- tt_buff_count++;
- }
-
- /* initialize, and overwrite if malloc succeeds */
- orig_node->tt_buff = NULL;
- orig_node->tt_buff_len = 0;
-
- if (tt_buff_len > 0) {
- orig_node->tt_buff = kmalloc(tt_buff_len, GFP_ATOMIC);
- if (orig_node->tt_buff) {
- memcpy(orig_node->tt_buff, tt_buff, tt_buff_len);
- orig_node->tt_buff_len = tt_buff_len;
+ hash_add(bat_priv->tt_global_hash, compare_gtt,
+ choose_orig, tt_global_entry,
+ &tt_global_entry->hash_entry);
+ atomic_inc(&orig_node->tt_size);
+ } else {
+ if (tt_global_entry->orig_node != orig_node) {
+ atomic_dec(&tt_global_entry->orig_node->tt_size);
+ orig_node_tmp = tt_global_entry->orig_node;
+ atomic_inc(&orig_node->refcount);
+ tt_global_entry->orig_node = orig_node;
+ orig_node_free_ref(orig_node_tmp);
+ atomic_inc(&orig_node->tt_size);
}
+ tt_global_entry->ttvn = ttvn;
+ tt_global_entry->flags = NO_FLAGS;
+ tt_global_entry->roam_at = 0;
}
+
+ bat_dbg(DBG_TT, bat_priv,
+ "Creating new global tt entry: %pM (via %pM)\n",
+ tt_global_entry->addr, orig_node->orig);
+
+ /* remove address from local hash if present */
+ tt_local_remove(bat_priv, tt_global_entry->addr,
+ "global tt received", roaming);
+ ret = 1;
+out:
+ if (tt_global_entry)
+ tt_global_entry_free_ref(tt_global_entry);
+ return ret;
}
int tt_global_seq_print_text(struct seq_file *seq, void *offset)
@@ -508,26 +579,27 @@
seq_printf(seq,
"Globally announced TT entries received via the mesh %s\n",
net_dev->name);
-
- spin_lock_bh(&bat_priv->tt_ghash_lock);
+ seq_printf(seq, " %-13s %s %-15s %s\n",
+ "Client", "(TTVN)", "Originator", "(Curr TTVN)");
buf_size = 1;
- /* Estimate length for: " * xx:xx:xx:xx:xx:xx via xx:xx:xx:xx:xx:xx\n"*/
+ /* Estimate length for: " * xx:xx:xx:xx:xx:xx (ttvn) via
+ * xx:xx:xx:xx:xx:xx (cur_ttvn)\n"*/
for (i = 0; i < hash->size; i++) {
head = &hash->table[i];
rcu_read_lock();
__hlist_for_each_rcu(node, head)
- buf_size += 43;
+ buf_size += 59;
rcu_read_unlock();
}
buff = kmalloc(buf_size, GFP_ATOMIC);
if (!buff) {
- spin_unlock_bh(&bat_priv->tt_ghash_lock);
ret = -ENOMEM;
goto out;
}
+
buff[0] = '\0';
pos = 0;
@@ -537,16 +609,18 @@
rcu_read_lock();
hlist_for_each_entry_rcu(tt_global_entry, node,
head, hash_entry) {
- pos += snprintf(buff + pos, 44,
- " * %pM via %pM\n",
+ pos += snprintf(buff + pos, 61,
+ " * %pM (%3u) via %pM (%3u)\n",
tt_global_entry->addr,
- tt_global_entry->orig_node->orig);
+ tt_global_entry->ttvn,
+ tt_global_entry->orig_node->orig,
+ (uint8_t) atomic_read(
+ &tt_global_entry->orig_node->
+ last_ttvn));
}
rcu_read_unlock();
}
- spin_unlock_bh(&bat_priv->tt_ghash_lock);
-
seq_printf(seq, "%s", buff);
kfree(buff);
out:
@@ -555,84 +629,994 @@
return ret;
}
-static void _tt_global_del_orig(struct bat_priv *bat_priv,
- struct tt_global_entry *tt_global_entry,
- char *message)
+static void _tt_global_del(struct bat_priv *bat_priv,
+ struct tt_global_entry *tt_global_entry,
+ const char *message)
{
- bat_dbg(DBG_ROUTES, bat_priv,
+ if (!tt_global_entry)
+ goto out;
+
+ bat_dbg(DBG_TT, bat_priv,
"Deleting global tt entry %pM (via %pM): %s\n",
tt_global_entry->addr, tt_global_entry->orig_node->orig,
message);
+ atomic_dec(&tt_global_entry->orig_node->tt_size);
+
hash_remove(bat_priv->tt_global_hash, compare_gtt, choose_orig,
tt_global_entry->addr);
- kfree(tt_global_entry);
+out:
+ if (tt_global_entry)
+ tt_global_entry_free_ref(tt_global_entry);
+}
+
+void tt_global_del(struct bat_priv *bat_priv,
+ struct orig_node *orig_node, const unsigned char *addr,
+ const char *message, bool roaming)
+{
+ struct tt_global_entry *tt_global_entry = NULL;
+
+ tt_global_entry = tt_global_hash_find(bat_priv, addr);
+ if (!tt_global_entry)
+ goto out;
+
+ if (tt_global_entry->orig_node == orig_node) {
+ if (roaming) {
+ tt_global_entry->flags |= TT_CLIENT_ROAM;
+ tt_global_entry->roam_at = jiffies;
+ goto out;
+ }
+ _tt_global_del(bat_priv, tt_global_entry, message);
+ }
+out:
+ if (tt_global_entry)
+ tt_global_entry_free_ref(tt_global_entry);
}
void tt_global_del_orig(struct bat_priv *bat_priv,
- struct orig_node *orig_node, char *message)
+ struct orig_node *orig_node, const char *message)
{
struct tt_global_entry *tt_global_entry;
- int tt_buff_count = 0;
- unsigned char *tt_ptr;
+ int i;
+ struct hashtable_t *hash = bat_priv->tt_global_hash;
+ struct hlist_node *node, *safe;
+ struct hlist_head *head;
+ spinlock_t *list_lock; /* protects write access to the hash lists */
- if (orig_node->tt_buff_len == 0)
- return;
+ for (i = 0; i < hash->size; i++) {
+ head = &hash->table[i];
+ list_lock = &hash->list_locks[i];
- spin_lock_bh(&bat_priv->tt_ghash_lock);
+ spin_lock_bh(list_lock);
+ hlist_for_each_entry_safe(tt_global_entry, node, safe,
+ head, hash_entry) {
+ if (tt_global_entry->orig_node == orig_node) {
+ bat_dbg(DBG_TT, bat_priv,
+ "Deleting global tt entry %pM "
+ "(via %pM): originator time out\n",
+ tt_global_entry->addr,
+ tt_global_entry->orig_node->orig);
+ hlist_del_rcu(node);
+ tt_global_entry_free_ref(tt_global_entry);
+ }
+ }
+ spin_unlock_bh(list_lock);
+ }
+ atomic_set(&orig_node->tt_size, 0);
+}
- while ((tt_buff_count + 1) * ETH_ALEN <= orig_node->tt_buff_len) {
- tt_ptr = orig_node->tt_buff + (tt_buff_count * ETH_ALEN);
- tt_global_entry = tt_global_hash_find(bat_priv, tt_ptr);
+static void tt_global_roam_purge(struct bat_priv *bat_priv)
+{
+ struct hashtable_t *hash = bat_priv->tt_global_hash;
+ struct tt_global_entry *tt_global_entry;
+ struct hlist_node *node, *node_tmp;
+ struct hlist_head *head;
+ spinlock_t *list_lock; /* protects write access to the hash lists */
+ int i;
- if ((tt_global_entry) &&
- (tt_global_entry->orig_node == orig_node))
- _tt_global_del_orig(bat_priv, tt_global_entry,
- message);
+ for (i = 0; i < hash->size; i++) {
+ head = &hash->table[i];
+ list_lock = &hash->list_locks[i];
- tt_buff_count++;
+ spin_lock_bh(list_lock);
+ hlist_for_each_entry_safe(tt_global_entry, node, node_tmp,
+ head, hash_entry) {
+ if (!(tt_global_entry->flags & TT_CLIENT_ROAM))
+ continue;
+ if (!is_out_of_time(tt_global_entry->roam_at,
+ TT_CLIENT_ROAM_TIMEOUT * 1000))
+ continue;
+
+ bat_dbg(DBG_TT, bat_priv, "Deleting global "
+ "tt entry (%pM): Roaming timeout\n",
+ tt_global_entry->addr);
+ atomic_dec(&tt_global_entry->orig_node->tt_size);
+ hlist_del_rcu(node);
+ tt_global_entry_free_ref(tt_global_entry);
+ }
+ spin_unlock_bh(list_lock);
}
- spin_unlock_bh(&bat_priv->tt_ghash_lock);
-
- orig_node->tt_buff_len = 0;
- kfree(orig_node->tt_buff);
- orig_node->tt_buff = NULL;
}
-static void tt_global_del(struct hlist_node *node, void *arg)
+static void tt_global_table_free(struct bat_priv *bat_priv)
{
- void *data = container_of(node, struct tt_global_entry, hash_entry);
+ struct hashtable_t *hash;
+ spinlock_t *list_lock; /* protects write access to the hash lists */
+ struct tt_global_entry *tt_global_entry;
+ struct hlist_node *node, *node_tmp;
+ struct hlist_head *head;
+ int i;
- kfree(data);
-}
-
-void tt_global_free(struct bat_priv *bat_priv)
-{
if (!bat_priv->tt_global_hash)
return;
- hash_delete(bat_priv->tt_global_hash, tt_global_del, NULL);
+ hash = bat_priv->tt_global_hash;
+
+ for (i = 0; i < hash->size; i++) {
+ head = &hash->table[i];
+ list_lock = &hash->list_locks[i];
+
+ spin_lock_bh(list_lock);
+ hlist_for_each_entry_safe(tt_global_entry, node, node_tmp,
+ head, hash_entry) {
+ hlist_del_rcu(node);
+ tt_global_entry_free_ref(tt_global_entry);
+ }
+ spin_unlock_bh(list_lock);
+ }
+
+ hash_destroy(hash);
+
bat_priv->tt_global_hash = NULL;
}
-struct orig_node *transtable_search(struct bat_priv *bat_priv, uint8_t *addr)
+struct orig_node *transtable_search(struct bat_priv *bat_priv,
+ const uint8_t *addr)
{
struct tt_global_entry *tt_global_entry;
struct orig_node *orig_node = NULL;
- spin_lock_bh(&bat_priv->tt_ghash_lock);
tt_global_entry = tt_global_hash_find(bat_priv, addr);
if (!tt_global_entry)
goto out;
if (!atomic_inc_not_zero(&tt_global_entry->orig_node->refcount))
- goto out;
+ goto free_tt;
orig_node = tt_global_entry->orig_node;
+free_tt:
+ tt_global_entry_free_ref(tt_global_entry);
out:
- spin_unlock_bh(&bat_priv->tt_ghash_lock);
return orig_node;
}
+
+/* Calculates the checksum of the local table of a given orig_node */
+uint16_t tt_global_crc(struct bat_priv *bat_priv, struct orig_node *orig_node)
+{
+ uint16_t total = 0, total_one;
+ struct hashtable_t *hash = bat_priv->tt_global_hash;
+ struct tt_global_entry *tt_global_entry;
+ struct hlist_node *node;
+ struct hlist_head *head;
+ int i, j;
+
+ for (i = 0; i < hash->size; i++) {
+ head = &hash->table[i];
+
+ rcu_read_lock();
+ hlist_for_each_entry_rcu(tt_global_entry, node,
+ head, hash_entry) {
+ if (compare_eth(tt_global_entry->orig_node,
+ orig_node)) {
+ /* Roaming clients are in the global table for
+ * consistency only. They don't have to be
+ * taken into account while computing the
+ * global crc */
+ if (tt_global_entry->flags & TT_CLIENT_ROAM)
+ continue;
+ total_one = 0;
+ for (j = 0; j < ETH_ALEN; j++)
+ total_one = crc16_byte(total_one,
+ tt_global_entry->addr[j]);
+ total ^= total_one;
+ }
+ }
+ rcu_read_unlock();
+ }
+
+ return total;
+}
+
+/* Calculates the checksum of the local table */
+uint16_t tt_local_crc(struct bat_priv *bat_priv)
+{
+ uint16_t total = 0, total_one;
+ struct hashtable_t *hash = bat_priv->tt_local_hash;
+ struct tt_local_entry *tt_local_entry;
+ struct hlist_node *node;
+ struct hlist_head *head;
+ int i, j;
+
+ for (i = 0; i < hash->size; i++) {
+ head = &hash->table[i];
+
+ rcu_read_lock();
+ hlist_for_each_entry_rcu(tt_local_entry, node,
+ head, hash_entry) {
+ total_one = 0;
+ for (j = 0; j < ETH_ALEN; j++)
+ total_one = crc16_byte(total_one,
+ tt_local_entry->addr[j]);
+ total ^= total_one;
+ }
+ rcu_read_unlock();
+ }
+
+ return total;
+}
+
+static void tt_req_list_free(struct bat_priv *bat_priv)
+{
+ struct tt_req_node *node, *safe;
+
+ spin_lock_bh(&bat_priv->tt_req_list_lock);
+
+ list_for_each_entry_safe(node, safe, &bat_priv->tt_req_list, list) {
+ list_del(&node->list);
+ kfree(node);
+ }
+
+ spin_unlock_bh(&bat_priv->tt_req_list_lock);
+}
+
+void tt_save_orig_buffer(struct bat_priv *bat_priv, struct orig_node *orig_node,
+ const unsigned char *tt_buff, uint8_t tt_num_changes)
+{
+ uint16_t tt_buff_len = tt_len(tt_num_changes);
+
+ /* Replace the old buffer only if I received something in the
+ * last OGM (the OGM could carry no changes) */
+ spin_lock_bh(&orig_node->tt_buff_lock);
+ if (tt_buff_len > 0) {
+ kfree(orig_node->tt_buff);
+ orig_node->tt_buff_len = 0;
+ orig_node->tt_buff = kmalloc(tt_buff_len, GFP_ATOMIC);
+ if (orig_node->tt_buff) {
+ memcpy(orig_node->tt_buff, tt_buff, tt_buff_len);
+ orig_node->tt_buff_len = tt_buff_len;
+ }
+ }
+ spin_unlock_bh(&orig_node->tt_buff_lock);
+}
+
+static void tt_req_purge(struct bat_priv *bat_priv)
+{
+ struct tt_req_node *node, *safe;
+
+ spin_lock_bh(&bat_priv->tt_req_list_lock);
+ list_for_each_entry_safe(node, safe, &bat_priv->tt_req_list, list) {
+ if (is_out_of_time(node->issued_at,
+ TT_REQUEST_TIMEOUT * 1000)) {
+ list_del(&node->list);
+ kfree(node);
+ }
+ }
+ spin_unlock_bh(&bat_priv->tt_req_list_lock);
+}
+
+/* returns the pointer to the new tt_req_node struct if no request
+ * has already been issued for this orig_node, NULL otherwise */
+static struct tt_req_node *new_tt_req_node(struct bat_priv *bat_priv,
+ struct orig_node *orig_node)
+{
+ struct tt_req_node *tt_req_node_tmp, *tt_req_node = NULL;
+
+ spin_lock_bh(&bat_priv->tt_req_list_lock);
+ list_for_each_entry(tt_req_node_tmp, &bat_priv->tt_req_list, list) {
+ if (compare_eth(tt_req_node_tmp, orig_node) &&
+ !is_out_of_time(tt_req_node_tmp->issued_at,
+ TT_REQUEST_TIMEOUT * 1000))
+ goto unlock;
+ }
+
+ tt_req_node = kmalloc(sizeof(*tt_req_node), GFP_ATOMIC);
+ if (!tt_req_node)
+ goto unlock;
+
+ memcpy(tt_req_node->addr, orig_node->orig, ETH_ALEN);
+ tt_req_node->issued_at = jiffies;
+
+ list_add(&tt_req_node->list, &bat_priv->tt_req_list);
+unlock:
+ spin_unlock_bh(&bat_priv->tt_req_list_lock);
+ return tt_req_node;
+}
+
+static int tt_global_valid_entry(const void *entry_ptr, const void *data_ptr)
+{
+ const struct tt_global_entry *tt_global_entry = entry_ptr;
+ const struct orig_node *orig_node = data_ptr;
+
+ if (tt_global_entry->flags & TT_CLIENT_ROAM)
+ return 0;
+
+ return (tt_global_entry->orig_node == orig_node);
+}
+
+static struct sk_buff *tt_response_fill_table(uint16_t tt_len, uint8_t ttvn,
+ struct hashtable_t *hash,
+ struct hard_iface *primary_if,
+ int (*valid_cb)(const void *,
+ const void *),
+ void *cb_data)
+{
+ struct tt_local_entry *tt_local_entry;
+ struct tt_query_packet *tt_response;
+ struct tt_change *tt_change;
+ struct hlist_node *node;
+ struct hlist_head *head;
+ struct sk_buff *skb = NULL;
+ uint16_t tt_tot, tt_count;
+ ssize_t tt_query_size = sizeof(struct tt_query_packet);
+ int i;
+
+ if (tt_query_size + tt_len > primary_if->soft_iface->mtu) {
+ tt_len = primary_if->soft_iface->mtu - tt_query_size;
+ tt_len -= tt_len % sizeof(struct tt_change);
+ }
+ tt_tot = tt_len / sizeof(struct tt_change);
+
+ skb = dev_alloc_skb(tt_query_size + tt_len + ETH_HLEN);
+ if (!skb)
+ goto out;
+
+ skb_reserve(skb, ETH_HLEN);
+ tt_response = (struct tt_query_packet *)skb_put(skb,
+ tt_query_size + tt_len);
+ tt_response->ttvn = ttvn;
+ tt_response->tt_data = htons(tt_tot);
+
+ tt_change = (struct tt_change *)(skb->data + tt_query_size);
+ tt_count = 0;
+
+ rcu_read_lock();
+ for (i = 0; i < hash->size; i++) {
+ head = &hash->table[i];
+
+ hlist_for_each_entry_rcu(tt_local_entry, node,
+ head, hash_entry) {
+ if (tt_count == tt_tot)
+ break;
+
+ if ((valid_cb) && (!valid_cb(tt_local_entry, cb_data)))
+ continue;
+
+ memcpy(tt_change->addr, tt_local_entry->addr, ETH_ALEN);
+ tt_change->flags = NO_FLAGS;
+
+ tt_count++;
+ tt_change++;
+ }
+ }
+ rcu_read_unlock();
+
+out:
+ return skb;
+}
+
+int send_tt_request(struct bat_priv *bat_priv, struct orig_node *dst_orig_node,
+ uint8_t ttvn, uint16_t tt_crc, bool full_table)
+{
+ struct sk_buff *skb = NULL;
+ struct tt_query_packet *tt_request;
+ struct neigh_node *neigh_node = NULL;
+ struct hard_iface *primary_if;
+ struct tt_req_node *tt_req_node = NULL;
+ int ret = 1;
+
+ primary_if = primary_if_get_selected(bat_priv);
+ if (!primary_if)
+ goto out;
+
+ /* The new tt_req will be issued only if I'm not waiting for a
+ * reply from the same orig_node yet */
+ tt_req_node = new_tt_req_node(bat_priv, dst_orig_node);
+ if (!tt_req_node)
+ goto out;
+
+ skb = dev_alloc_skb(sizeof(struct tt_query_packet) + ETH_HLEN);
+ if (!skb)
+ goto out;
+
+ skb_reserve(skb, ETH_HLEN);
+
+ tt_request = (struct tt_query_packet *)skb_put(skb,
+ sizeof(struct tt_query_packet));
+
+ tt_request->packet_type = BAT_TT_QUERY;
+ tt_request->version = COMPAT_VERSION;
+ memcpy(tt_request->src, primary_if->net_dev->dev_addr, ETH_ALEN);
+ memcpy(tt_request->dst, dst_orig_node->orig, ETH_ALEN);
+ tt_request->ttl = TTL;
+ tt_request->ttvn = ttvn;
+ tt_request->tt_data = tt_crc;
+ tt_request->flags = TT_REQUEST;
+
+ if (full_table)
+ tt_request->flags |= TT_FULL_TABLE;
+
+ neigh_node = orig_node_get_router(dst_orig_node);
+ if (!neigh_node)
+ goto out;
+
+ bat_dbg(DBG_TT, bat_priv, "Sending TT_REQUEST to %pM via %pM "
+ "[%c]\n", dst_orig_node->orig, neigh_node->addr,
+ (full_table ? 'F' : '.'));
+
+ send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr);
+ ret = 0;
+
+out:
+ if (neigh_node)
+ neigh_node_free_ref(neigh_node);
+ if (primary_if)
+ hardif_free_ref(primary_if);
+ if (ret)
+ kfree_skb(skb);
+ if (ret && tt_req_node) {
+ spin_lock_bh(&bat_priv->tt_req_list_lock);
+ list_del(&tt_req_node->list);
+ spin_unlock_bh(&bat_priv->tt_req_list_lock);
+ kfree(tt_req_node);
+ }
+ return ret;
+}
+
+static bool send_other_tt_response(struct bat_priv *bat_priv,
+ struct tt_query_packet *tt_request)
+{
+ struct orig_node *req_dst_orig_node = NULL, *res_dst_orig_node = NULL;
+ struct neigh_node *neigh_node = NULL;
+ struct hard_iface *primary_if = NULL;
+ uint8_t orig_ttvn, req_ttvn, ttvn;
+ int ret = false;
+ unsigned char *tt_buff;
+ bool full_table;
+ uint16_t tt_len, tt_tot;
+ struct sk_buff *skb = NULL;
+ struct tt_query_packet *tt_response;
+
+ bat_dbg(DBG_TT, bat_priv,
+ "Received TT_REQUEST from %pM for "
+ "ttvn: %u (%pM) [%c]\n", tt_request->src,
+ tt_request->ttvn, tt_request->dst,
+ (tt_request->flags & TT_FULL_TABLE ? 'F' : '.'));
+
+ /* Let's get the orig node of the REAL destination */
+ req_dst_orig_node = get_orig_node(bat_priv, tt_request->dst);
+ if (!req_dst_orig_node)
+ goto out;
+
+ res_dst_orig_node = get_orig_node(bat_priv, tt_request->src);
+ if (!res_dst_orig_node)
+ goto out;
+
+ neigh_node = orig_node_get_router(res_dst_orig_node);
+ if (!neigh_node)
+ goto out;
+
+ primary_if = primary_if_get_selected(bat_priv);
+ if (!primary_if)
+ goto out;
+
+ orig_ttvn = (uint8_t)atomic_read(&req_dst_orig_node->last_ttvn);
+ req_ttvn = tt_request->ttvn;
+
+ /* I have not the requested data */
+ if (orig_ttvn != req_ttvn ||
+ tt_request->tt_data != req_dst_orig_node->tt_crc)
+ goto out;
+
+ /* If it has explicitly been requested the full table */
+ if (tt_request->flags & TT_FULL_TABLE ||
+ !req_dst_orig_node->tt_buff)
+ full_table = true;
+ else
+ full_table = false;
+
+ /* In this version, fragmentation is not implemented, then
+ * I'll send only one packet with as much TT entries as I can */
+ if (!full_table) {
+ spin_lock_bh(&req_dst_orig_node->tt_buff_lock);
+ tt_len = req_dst_orig_node->tt_buff_len;
+ tt_tot = tt_len / sizeof(struct tt_change);
+
+ skb = dev_alloc_skb(sizeof(struct tt_query_packet) +
+ tt_len + ETH_HLEN);
+ if (!skb)
+ goto unlock;
+
+ skb_reserve(skb, ETH_HLEN);
+ tt_response = (struct tt_query_packet *)skb_put(skb,
+ sizeof(struct tt_query_packet) + tt_len);
+ tt_response->ttvn = req_ttvn;
+ tt_response->tt_data = htons(tt_tot);
+
+ tt_buff = skb->data + sizeof(struct tt_query_packet);
+ /* Copy the last orig_node's OGM buffer */
+ memcpy(tt_buff, req_dst_orig_node->tt_buff,
+ req_dst_orig_node->tt_buff_len);
+
+ spin_unlock_bh(&req_dst_orig_node->tt_buff_lock);
+ } else {
+ tt_len = (uint16_t)atomic_read(&req_dst_orig_node->tt_size) *
+ sizeof(struct tt_change);
+ ttvn = (uint8_t)atomic_read(&req_dst_orig_node->last_ttvn);
+
+ skb = tt_response_fill_table(tt_len, ttvn,
+ bat_priv->tt_global_hash,
+ primary_if, tt_global_valid_entry,
+ req_dst_orig_node);
+ if (!skb)
+ goto out;
+
+ tt_response = (struct tt_query_packet *)skb->data;
+ }
+
+ tt_response->packet_type = BAT_TT_QUERY;
+ tt_response->version = COMPAT_VERSION;
+ tt_response->ttl = TTL;
+ memcpy(tt_response->src, req_dst_orig_node->orig, ETH_ALEN);
+ memcpy(tt_response->dst, tt_request->src, ETH_ALEN);
+ tt_response->flags = TT_RESPONSE;
+
+ if (full_table)
+ tt_response->flags |= TT_FULL_TABLE;
+
+ bat_dbg(DBG_TT, bat_priv,
+ "Sending TT_RESPONSE %pM via %pM for %pM (ttvn: %u)\n",
+ res_dst_orig_node->orig, neigh_node->addr,
+ req_dst_orig_node->orig, req_ttvn);
+
+ send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr);
+ ret = true;
+ goto out;
+
+unlock:
+ spin_unlock_bh(&req_dst_orig_node->tt_buff_lock);
+
+out:
+ if (res_dst_orig_node)
+ orig_node_free_ref(res_dst_orig_node);
+ if (req_dst_orig_node)
+ orig_node_free_ref(req_dst_orig_node);
+ if (neigh_node)
+ neigh_node_free_ref(neigh_node);
+ if (primary_if)
+ hardif_free_ref(primary_if);
+ if (!ret)
+ kfree_skb(skb);
+ return ret;
+
+}
+static bool send_my_tt_response(struct bat_priv *bat_priv,
+ struct tt_query_packet *tt_request)
+{
+ struct orig_node *orig_node = NULL;
+ struct neigh_node *neigh_node = NULL;
+ struct hard_iface *primary_if = NULL;
+ uint8_t my_ttvn, req_ttvn, ttvn;
+ int ret = false;
+ unsigned char *tt_buff;
+ bool full_table;
+ uint16_t tt_len, tt_tot;
+ struct sk_buff *skb = NULL;
+ struct tt_query_packet *tt_response;
+
+ bat_dbg(DBG_TT, bat_priv,
+ "Received TT_REQUEST from %pM for "
+ "ttvn: %u (me) [%c]\n", tt_request->src,
+ tt_request->ttvn,
+ (tt_request->flags & TT_FULL_TABLE ? 'F' : '.'));
+
+
+ my_ttvn = (uint8_t)atomic_read(&bat_priv->ttvn);
+ req_ttvn = tt_request->ttvn;
+
+ orig_node = get_orig_node(bat_priv, tt_request->src);
+ if (!orig_node)
+ goto out;
+
+ neigh_node = orig_node_get_router(orig_node);
+ if (!neigh_node)
+ goto out;
+
+ primary_if = primary_if_get_selected(bat_priv);
+ if (!primary_if)
+ goto out;
+
+ /* If the full table has been explicitly requested or the gap
+ * is too big send the whole local translation table */
+ if (tt_request->flags & TT_FULL_TABLE || my_ttvn != req_ttvn ||
+ !bat_priv->tt_buff)
+ full_table = true;
+ else
+ full_table = false;
+
+ /* In this version, fragmentation is not implemented, then
+ * I'll send only one packet with as much TT entries as I can */
+ if (!full_table) {
+ spin_lock_bh(&bat_priv->tt_buff_lock);
+ tt_len = bat_priv->tt_buff_len;
+ tt_tot = tt_len / sizeof(struct tt_change);
+
+ skb = dev_alloc_skb(sizeof(struct tt_query_packet) +
+ tt_len + ETH_HLEN);
+ if (!skb)
+ goto unlock;
+
+ skb_reserve(skb, ETH_HLEN);
+ tt_response = (struct tt_query_packet *)skb_put(skb,
+ sizeof(struct tt_query_packet) + tt_len);
+ tt_response->ttvn = req_ttvn;
+ tt_response->tt_data = htons(tt_tot);
+
+ tt_buff = skb->data + sizeof(struct tt_query_packet);
+ memcpy(tt_buff, bat_priv->tt_buff,
+ bat_priv->tt_buff_len);
+ spin_unlock_bh(&bat_priv->tt_buff_lock);
+ } else {
+ tt_len = (uint16_t)atomic_read(&bat_priv->num_local_tt) *
+ sizeof(struct tt_change);
+ ttvn = (uint8_t)atomic_read(&bat_priv->ttvn);
+
+ skb = tt_response_fill_table(tt_len, ttvn,
+ bat_priv->tt_local_hash,
+ primary_if, NULL, NULL);
+ if (!skb)
+ goto out;
+
+ tt_response = (struct tt_query_packet *)skb->data;
+ }
+
+ tt_response->packet_type = BAT_TT_QUERY;
+ tt_response->version = COMPAT_VERSION;
+ tt_response->ttl = TTL;
+ memcpy(tt_response->src, primary_if->net_dev->dev_addr, ETH_ALEN);
+ memcpy(tt_response->dst, tt_request->src, ETH_ALEN);
+ tt_response->flags = TT_RESPONSE;
+
+ if (full_table)
+ tt_response->flags |= TT_FULL_TABLE;
+
+ bat_dbg(DBG_TT, bat_priv,
+ "Sending TT_RESPONSE to %pM via %pM [%c]\n",
+ orig_node->orig, neigh_node->addr,
+ (tt_response->flags & TT_FULL_TABLE ? 'F' : '.'));
+
+ send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr);
+ ret = true;
+ goto out;
+
+unlock:
+ spin_unlock_bh(&bat_priv->tt_buff_lock);
+out:
+ if (orig_node)
+ orig_node_free_ref(orig_node);
+ if (neigh_node)
+ neigh_node_free_ref(neigh_node);
+ if (primary_if)
+ hardif_free_ref(primary_if);
+ if (!ret)
+ kfree_skb(skb);
+ /* This packet was for me, so it doesn't need to be re-routed */
+ return true;
+}
+
+bool send_tt_response(struct bat_priv *bat_priv,
+ struct tt_query_packet *tt_request)
+{
+ if (is_my_mac(tt_request->dst))
+ return send_my_tt_response(bat_priv, tt_request);
+ else
+ return send_other_tt_response(bat_priv, tt_request);
+}
+
+static void _tt_update_changes(struct bat_priv *bat_priv,
+ struct orig_node *orig_node,
+ struct tt_change *tt_change,
+ uint16_t tt_num_changes, uint8_t ttvn)
+{
+ int i;
+
+ for (i = 0; i < tt_num_changes; i++) {
+ if ((tt_change + i)->flags & TT_CLIENT_DEL)
+ tt_global_del(bat_priv, orig_node,
+ (tt_change + i)->addr,
+ "tt removed by changes",
+ (tt_change + i)->flags & TT_CLIENT_ROAM);
+ else
+ if (!tt_global_add(bat_priv, orig_node,
+ (tt_change + i)->addr, ttvn, false))
+ /* In case of problem while storing a
+ * global_entry, we stop the updating
+ * procedure without committing the
+ * ttvn change. This will avoid to send
+ * corrupted data on tt_request
+ */
+ return;
+ }
+}
+
+static void tt_fill_gtable(struct bat_priv *bat_priv,
+ struct tt_query_packet *tt_response)
+{
+ struct orig_node *orig_node = NULL;
+
+ orig_node = orig_hash_find(bat_priv, tt_response->src);
+ if (!orig_node)
+ goto out;
+
+ /* Purge the old table first.. */
+ tt_global_del_orig(bat_priv, orig_node, "Received full table");
+
+ _tt_update_changes(bat_priv, orig_node,
+ (struct tt_change *)(tt_response + 1),
+ tt_response->tt_data, tt_response->ttvn);
+
+ spin_lock_bh(&orig_node->tt_buff_lock);
+ kfree(orig_node->tt_buff);
+ orig_node->tt_buff_len = 0;
+ orig_node->tt_buff = NULL;
+ spin_unlock_bh(&orig_node->tt_buff_lock);
+
+ atomic_set(&orig_node->last_ttvn, tt_response->ttvn);
+
+out:
+ if (orig_node)
+ orig_node_free_ref(orig_node);
+}
+
+void tt_update_changes(struct bat_priv *bat_priv, struct orig_node *orig_node,
+ uint16_t tt_num_changes, uint8_t ttvn,
+ struct tt_change *tt_change)
+{
+ _tt_update_changes(bat_priv, orig_node, tt_change, tt_num_changes,
+ ttvn);
+
+ tt_save_orig_buffer(bat_priv, orig_node, (unsigned char *)tt_change,
+ tt_num_changes);
+ atomic_set(&orig_node->last_ttvn, ttvn);
+}
+
+bool is_my_client(struct bat_priv *bat_priv, const uint8_t *addr)
+{
+ struct tt_local_entry *tt_local_entry = NULL;
+ bool ret = false;
+
+ tt_local_entry = tt_local_hash_find(bat_priv, addr);
+ if (!tt_local_entry)
+ goto out;
+ ret = true;
+out:
+ if (tt_local_entry)
+ tt_local_entry_free_ref(tt_local_entry);
+ return ret;
+}
+
+void handle_tt_response(struct bat_priv *bat_priv,
+ struct tt_query_packet *tt_response)
+{
+ struct tt_req_node *node, *safe;
+ struct orig_node *orig_node = NULL;
+
+ bat_dbg(DBG_TT, bat_priv, "Received TT_RESPONSE from %pM for "
+ "ttvn %d t_size: %d [%c]\n",
+ tt_response->src, tt_response->ttvn,
+ tt_response->tt_data,
+ (tt_response->flags & TT_FULL_TABLE ? 'F' : '.'));
+
+ orig_node = orig_hash_find(bat_priv, tt_response->src);
+ if (!orig_node)
+ goto out;
+
+ if (tt_response->flags & TT_FULL_TABLE)
+ tt_fill_gtable(bat_priv, tt_response);
+ else
+ tt_update_changes(bat_priv, orig_node, tt_response->tt_data,
+ tt_response->ttvn,
+ (struct tt_change *)(tt_response + 1));
+
+ /* Delete the tt_req_node from pending tt_requests list */
+ spin_lock_bh(&bat_priv->tt_req_list_lock);
+ list_for_each_entry_safe(node, safe, &bat_priv->tt_req_list, list) {
+ if (!compare_eth(node->addr, tt_response->src))
+ continue;
+ list_del(&node->list);
+ kfree(node);
+ }
+ spin_unlock_bh(&bat_priv->tt_req_list_lock);
+
+ /* Recalculate the CRC for this orig_node and store it */
+ orig_node->tt_crc = tt_global_crc(bat_priv, orig_node);
+ /* Roaming phase is over: tables are in sync again. I can
+ * unset the flag */
+ orig_node->tt_poss_change = false;
+out:
+ if (orig_node)
+ orig_node_free_ref(orig_node);
+}
+
+int tt_init(struct bat_priv *bat_priv)
+{
+ if (!tt_local_init(bat_priv))
+ return 0;
+
+ if (!tt_global_init(bat_priv))
+ return 0;
+
+ tt_start_timer(bat_priv);
+
+ return 1;
+}
+
+static void tt_roam_list_free(struct bat_priv *bat_priv)
+{
+ struct tt_roam_node *node, *safe;
+
+ spin_lock_bh(&bat_priv->tt_roam_list_lock);
+
+ list_for_each_entry_safe(node, safe, &bat_priv->tt_roam_list, list) {
+ list_del(&node->list);
+ kfree(node);
+ }
+
+ spin_unlock_bh(&bat_priv->tt_roam_list_lock);
+}
+
+static void tt_roam_purge(struct bat_priv *bat_priv)
+{
+ struct tt_roam_node *node, *safe;
+
+ spin_lock_bh(&bat_priv->tt_roam_list_lock);
+ list_for_each_entry_safe(node, safe, &bat_priv->tt_roam_list, list) {
+ if (!is_out_of_time(node->first_time,
+ ROAMING_MAX_TIME * 1000))
+ continue;
+
+ list_del(&node->list);
+ kfree(node);
+ }
+ spin_unlock_bh(&bat_priv->tt_roam_list_lock);
+}
+
+/* This function checks whether the client already reached the
+ * maximum number of possible roaming phases. In this case the ROAMING_ADV
+ * will not be sent.
+ *
+ * returns true if the ROAMING_ADV can be sent, false otherwise */
+static bool tt_check_roam_count(struct bat_priv *bat_priv,
+ uint8_t *client)
+{
+ struct tt_roam_node *tt_roam_node;
+ bool ret = false;
+
+ spin_lock_bh(&bat_priv->tt_roam_list_lock);
+ /* The new tt_req will be issued only if I'm not waiting for a
+ * reply from the same orig_node yet */
+ list_for_each_entry(tt_roam_node, &bat_priv->tt_roam_list, list) {
+ if (!compare_eth(tt_roam_node->addr, client))
+ continue;
+
+ if (is_out_of_time(tt_roam_node->first_time,
+ ROAMING_MAX_TIME * 1000))
+ continue;
+
+ if (!atomic_dec_not_zero(&tt_roam_node->counter))
+ /* Sorry, you roamed too many times! */
+ goto unlock;
+ ret = true;
+ break;
+ }
+
+ if (!ret) {
+ tt_roam_node = kmalloc(sizeof(*tt_roam_node), GFP_ATOMIC);
+ if (!tt_roam_node)
+ goto unlock;
+
+ tt_roam_node->first_time = jiffies;
+ atomic_set(&tt_roam_node->counter, ROAMING_MAX_COUNT - 1);
+ memcpy(tt_roam_node->addr, client, ETH_ALEN);
+
+ list_add(&tt_roam_node->list, &bat_priv->tt_roam_list);
+ ret = true;
+ }
+
+unlock:
+ spin_unlock_bh(&bat_priv->tt_roam_list_lock);
+ return ret;
+}
+
+void send_roam_adv(struct bat_priv *bat_priv, uint8_t *client,
+ struct orig_node *orig_node)
+{
+ struct neigh_node *neigh_node = NULL;
+ struct sk_buff *skb = NULL;
+ struct roam_adv_packet *roam_adv_packet;
+ int ret = 1;
+ struct hard_iface *primary_if;
+
+ /* before going on we have to check whether the client has
+ * already roamed to us too many times */
+ if (!tt_check_roam_count(bat_priv, client))
+ goto out;
+
+ skb = dev_alloc_skb(sizeof(struct roam_adv_packet) + ETH_HLEN);
+ if (!skb)
+ goto out;
+
+ skb_reserve(skb, ETH_HLEN);
+
+ roam_adv_packet = (struct roam_adv_packet *)skb_put(skb,
+ sizeof(struct roam_adv_packet));
+
+ roam_adv_packet->packet_type = BAT_ROAM_ADV;
+ roam_adv_packet->version = COMPAT_VERSION;
+ roam_adv_packet->ttl = TTL;
+ primary_if = primary_if_get_selected(bat_priv);
+ if (!primary_if)
+ goto out;
+ memcpy(roam_adv_packet->src, primary_if->net_dev->dev_addr, ETH_ALEN);
+ hardif_free_ref(primary_if);
+ memcpy(roam_adv_packet->dst, orig_node->orig, ETH_ALEN);
+ memcpy(roam_adv_packet->client, client, ETH_ALEN);
+
+ neigh_node = orig_node_get_router(orig_node);
+ if (!neigh_node)
+ goto out;
+
+ bat_dbg(DBG_TT, bat_priv,
+ "Sending ROAMING_ADV to %pM (client %pM) via %pM\n",
+ orig_node->orig, client, neigh_node->addr);
+
+ send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr);
+ ret = 0;
+
+out:
+ if (neigh_node)
+ neigh_node_free_ref(neigh_node);
+ if (ret)
+ kfree_skb(skb);
+ return;
+}
+
+static void tt_purge(struct work_struct *work)
+{
+ struct delayed_work *delayed_work =
+ container_of(work, struct delayed_work, work);
+ struct bat_priv *bat_priv =
+ container_of(delayed_work, struct bat_priv, tt_work);
+
+ tt_local_purge(bat_priv);
+ tt_global_roam_purge(bat_priv);
+ tt_req_purge(bat_priv);
+ tt_roam_purge(bat_priv);
+
+ tt_start_timer(bat_priv);
+}
+
+void tt_free(struct bat_priv *bat_priv)
+{
+ cancel_delayed_work_sync(&bat_priv->tt_work);
+
+ tt_local_table_free(bat_priv);
+ tt_global_table_free(bat_priv);
+ tt_req_list_free(bat_priv);
+ tt_changes_list_free(bat_priv);
+ tt_roam_list_free(bat_priv);
+
+ kfree(bat_priv->tt_buff);
+}
diff --git a/net/batman-adv/translation-table.h b/net/batman-adv/translation-table.h
index 46152c3..460e583 100644
--- a/net/batman-adv/translation-table.h
+++ b/net/batman-adv/translation-table.h
@@ -22,22 +22,44 @@
#ifndef _NET_BATMAN_ADV_TRANSLATION_TABLE_H_
#define _NET_BATMAN_ADV_TRANSLATION_TABLE_H_
-int tt_local_init(struct bat_priv *bat_priv);
-void tt_local_add(struct net_device *soft_iface, uint8_t *addr);
+int tt_len(int changes_num);
+int tt_changes_fill_buffer(struct bat_priv *bat_priv,
+ unsigned char *buff, int buff_len);
+int tt_init(struct bat_priv *bat_priv);
+void tt_local_add(struct net_device *soft_iface, const uint8_t *addr);
void tt_local_remove(struct bat_priv *bat_priv,
- uint8_t *addr, char *message);
-int tt_local_fill_buffer(struct bat_priv *bat_priv,
- unsigned char *buff, int buff_len);
+ const uint8_t *addr, const char *message, bool roaming);
int tt_local_seq_print_text(struct seq_file *seq, void *offset);
-void tt_local_free(struct bat_priv *bat_priv);
-int tt_global_init(struct bat_priv *bat_priv);
-void tt_global_add_orig(struct bat_priv *bat_priv,
- struct orig_node *orig_node,
- unsigned char *tt_buff, int tt_buff_len);
+void tt_global_add_orig(struct bat_priv *bat_priv, struct orig_node *orig_node,
+ const unsigned char *tt_buff, int tt_buff_len);
+int tt_global_add(struct bat_priv *bat_priv,
+ struct orig_node *orig_node, const unsigned char *addr,
+ uint8_t ttvn, bool roaming);
int tt_global_seq_print_text(struct seq_file *seq, void *offset);
void tt_global_del_orig(struct bat_priv *bat_priv,
- struct orig_node *orig_node, char *message);
-void tt_global_free(struct bat_priv *bat_priv);
-struct orig_node *transtable_search(struct bat_priv *bat_priv, uint8_t *addr);
+ struct orig_node *orig_node, const char *message);
+void tt_global_del(struct bat_priv *bat_priv,
+ struct orig_node *orig_node, const unsigned char *addr,
+ const char *message, bool roaming);
+struct orig_node *transtable_search(struct bat_priv *bat_priv,
+ const uint8_t *addr);
+void tt_save_orig_buffer(struct bat_priv *bat_priv, struct orig_node *orig_node,
+ const unsigned char *tt_buff, uint8_t tt_num_changes);
+uint16_t tt_local_crc(struct bat_priv *bat_priv);
+uint16_t tt_global_crc(struct bat_priv *bat_priv, struct orig_node *orig_node);
+void tt_free(struct bat_priv *bat_priv);
+int send_tt_request(struct bat_priv *bat_priv,
+ struct orig_node *dst_orig_node, uint8_t hvn,
+ uint16_t tt_crc, bool full_table);
+bool send_tt_response(struct bat_priv *bat_priv,
+ struct tt_query_packet *tt_request);
+void tt_update_changes(struct bat_priv *bat_priv, struct orig_node *orig_node,
+ uint16_t tt_num_changes, uint8_t ttvn,
+ struct tt_change *tt_change);
+bool is_my_client(struct bat_priv *bat_priv, const uint8_t *addr);
+void handle_tt_response(struct bat_priv *bat_priv,
+ struct tt_query_packet *tt_response);
+void send_roam_adv(struct bat_priv *bat_priv, uint8_t *client,
+ struct orig_node *orig_node);
#endif /* _NET_BATMAN_ADV_TRANSLATION_TABLE_H_ */
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h
index fab70e8..25bd1db 100644
--- a/net/batman-adv/types.h
+++ b/net/batman-adv/types.h
@@ -75,8 +75,18 @@
unsigned long batman_seqno_reset;
uint8_t gw_flags;
uint8_t flags;
+ atomic_t last_ttvn; /* last seen translation table version number */
+ uint16_t tt_crc;
unsigned char *tt_buff;
int16_t tt_buff_len;
+ spinlock_t tt_buff_lock; /* protects tt_buff */
+ atomic_t tt_size;
+ /* The tt_poss_change flag is used to detect an ongoing roaming phase.
+ * If true, then I sent a Roaming_adv to this orig_node and I have to
+ * inspect every packet directed to it to check whether it is still
+ * the true destination or not. This flag will be reset to false as
+ * soon as I receive a new TTVN from this orig_node */
+ bool tt_poss_change;
uint32_t last_real_seqno;
uint8_t last_ttl;
unsigned long bcast_bits[NUM_WORDS];
@@ -94,6 +104,7 @@
spinlock_t ogm_cnt_lock;
/* bcast_seqno_lock protects bcast_bits, last_bcast_seqno */
spinlock_t bcast_seqno_lock;
+ spinlock_t tt_list_lock; /* protects tt_list */
atomic_t bond_candidates;
struct list_head bond_list;
};
@@ -145,6 +156,15 @@
atomic_t bcast_seqno;
atomic_t bcast_queue_left;
atomic_t batman_queue_left;
+ atomic_t ttvn; /* tranlation table version number */
+ atomic_t tt_ogm_append_cnt;
+ atomic_t tt_local_changes; /* changes registered in a OGM interval */
+ /* The tt_poss_change flag is used to detect an ongoing roaming phase.
+ * If true, then I received a Roaming_adv and I have to inspect every
+ * packet directed to me to check whether I am still the true
+ * destination or not. This flag will be reset to false as soon as I
+ * increase my TTVN */
+ bool tt_poss_change;
char num_ifaces;
struct debug_log *debug_log;
struct kobject *mesh_obj;
@@ -153,26 +173,35 @@
struct hlist_head forw_bcast_list;
struct hlist_head gw_list;
struct hlist_head softif_neigh_vids;
+ struct list_head tt_changes_list; /* tracks changes in a OGM int */
struct list_head vis_send_list;
struct hashtable_t *orig_hash;
struct hashtable_t *tt_local_hash;
struct hashtable_t *tt_global_hash;
+ struct list_head tt_req_list; /* list of pending tt_requests */
+ struct list_head tt_roam_list;
struct hashtable_t *vis_hash;
spinlock_t forw_bat_list_lock; /* protects forw_bat_list */
spinlock_t forw_bcast_list_lock; /* protects */
- spinlock_t tt_lhash_lock; /* protects tt_local_hash */
- spinlock_t tt_ghash_lock; /* protects tt_global_hash */
+ spinlock_t tt_changes_list_lock; /* protects tt_changes */
+ spinlock_t tt_req_list_lock; /* protects tt_req_list */
+ spinlock_t tt_roam_list_lock; /* protects tt_roam_list */
spinlock_t gw_list_lock; /* protects gw_list and curr_gw */
spinlock_t vis_hash_lock; /* protects vis_hash */
spinlock_t vis_list_lock; /* protects vis_info::recv_list */
spinlock_t softif_neigh_lock; /* protects soft-interface neigh list */
spinlock_t softif_neigh_vid_lock; /* protects soft-interface vid list */
- int16_t num_local_tt;
- atomic_t tt_local_changed;
+ atomic_t num_local_tt;
+ /* Checksum of the local table, recomputed before sending a new OGM */
+ atomic_t tt_crc;
+ unsigned char *tt_buff;
+ int16_t tt_buff_len;
+ spinlock_t tt_buff_lock; /* protects tt_buff */
struct delayed_work tt_work;
struct delayed_work orig_work;
struct delayed_work vis_work;
struct gw_node __rcu *curr_gw; /* rcu protected pointer */
+ atomic_t gw_reselect;
struct hard_iface __rcu *primary_if; /* rcu protected pointer */
struct vis_info *my_vis_info;
};
@@ -195,14 +224,39 @@
struct tt_local_entry {
uint8_t addr[ETH_ALEN];
unsigned long last_seen;
- char never_purge;
+ uint16_t flags;
+ atomic_t refcount;
+ struct rcu_head rcu;
struct hlist_node hash_entry;
};
struct tt_global_entry {
uint8_t addr[ETH_ALEN];
struct orig_node *orig_node;
- struct hlist_node hash_entry;
+ uint8_t ttvn;
+ uint16_t flags; /* only TT_GLOBAL_ROAM is used */
+ unsigned long roam_at; /* time at which TT_GLOBAL_ROAM was set */
+ atomic_t refcount;
+ struct rcu_head rcu;
+ struct hlist_node hash_entry; /* entry in the global table */
+};
+
+struct tt_change_node {
+ struct list_head list;
+ struct tt_change change;
+};
+
+struct tt_req_node {
+ uint8_t addr[ETH_ALEN];
+ unsigned long issued_at;
+ struct list_head list;
+};
+
+struct tt_roam_node {
+ uint8_t addr[ETH_ALEN];
+ atomic_t counter;
+ unsigned long first_time;
+ struct list_head list;
};
/**
@@ -246,10 +300,10 @@
};
struct vis_info {
- unsigned long first_seen;
- struct list_head recv_list;
- /* list of server-neighbors we received a vis-packet
- * from. we should not reply to them. */
+ unsigned long first_seen;
+ /* list of server-neighbors we received a vis-packet
+ * from. we should not reply to them. */
+ struct list_head recv_list;
struct list_head send_list;
struct kref refcount;
struct hlist_node hash_entry;
diff --git a/net/batman-adv/unicast.c b/net/batman-adv/unicast.c
index 19c3daf..32b125f 100644
--- a/net/batman-adv/unicast.c
+++ b/net/batman-adv/unicast.c
@@ -39,8 +39,8 @@
(struct unicast_frag_packet *)skb->data;
struct sk_buff *tmp_skb;
struct unicast_packet *unicast_packet;
- int hdr_len = sizeof(struct unicast_packet);
- int uni_diff = sizeof(struct unicast_frag_packet) - hdr_len;
+ int hdr_len = sizeof(*unicast_packet);
+ int uni_diff = sizeof(*up) - hdr_len;
/* set skb to the first part and tmp_skb to the second part */
if (up->flags & UNI_FRAG_HEAD) {
@@ -53,7 +53,7 @@
if (skb_linearize(skb) < 0 || skb_linearize(tmp_skb) < 0)
goto err;
- skb_pull(tmp_skb, sizeof(struct unicast_frag_packet));
+ skb_pull(tmp_skb, sizeof(*up));
if (pskb_expand_head(skb, 0, tmp_skb->len, GFP_ATOMIC) < 0)
goto err;
@@ -99,8 +99,7 @@
struct frag_packet_list_entry *tfp;
for (i = 0; i < FRAG_BUFFER_SIZE; i++) {
- tfp = kmalloc(sizeof(struct frag_packet_list_entry),
- GFP_ATOMIC);
+ tfp = kmalloc(sizeof(*tfp), GFP_ATOMIC);
if (!tfp) {
frag_list_free(head);
return -ENOMEM;
@@ -115,7 +114,7 @@
}
static struct frag_packet_list_entry *frag_search_packet(struct list_head *head,
- struct unicast_frag_packet *up)
+ const struct unicast_frag_packet *up)
{
struct frag_packet_list_entry *tfp;
struct unicast_frag_packet *tmp_up = NULL;
@@ -218,14 +217,14 @@
}
int frag_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv,
- struct hard_iface *hard_iface, uint8_t dstaddr[])
+ struct hard_iface *hard_iface, const uint8_t dstaddr[])
{
struct unicast_packet tmp_uc, *unicast_packet;
struct hard_iface *primary_if;
struct sk_buff *frag_skb;
struct unicast_frag_packet *frag1, *frag2;
- int uc_hdr_len = sizeof(struct unicast_packet);
- int ucf_hdr_len = sizeof(struct unicast_frag_packet);
+ int uc_hdr_len = sizeof(*unicast_packet);
+ int ucf_hdr_len = sizeof(*frag1);
int data_len = skb->len - uc_hdr_len;
int large_tail = 0, ret = NET_RX_DROP;
uint16_t seqno;
@@ -250,14 +249,14 @@
frag1 = (struct unicast_frag_packet *)skb->data;
frag2 = (struct unicast_frag_packet *)frag_skb->data;
- memcpy(frag1, &tmp_uc, sizeof(struct unicast_packet));
+ memcpy(frag1, &tmp_uc, sizeof(tmp_uc));
frag1->ttl--;
frag1->version = COMPAT_VERSION;
frag1->packet_type = BAT_UNICAST_FRAG;
memcpy(frag1->orig, primary_if->net_dev->dev_addr, ETH_ALEN);
- memcpy(frag2, frag1, sizeof(struct unicast_frag_packet));
+ memcpy(frag2, frag1, sizeof(*frag2));
if (data_len & 1)
large_tail = UNI_FRAG_LARGETAIL;
@@ -295,7 +294,7 @@
/* get routing information */
if (is_multicast_ether_addr(ethhdr->h_dest)) {
- orig_node = (struct orig_node *)gw_get_selected_orig(bat_priv);
+ orig_node = gw_get_selected_orig(bat_priv);
if (orig_node)
goto find_router;
}
@@ -314,10 +313,7 @@
if (!neigh_node)
goto out;
- if (neigh_node->if_incoming->if_status != IF_ACTIVE)
- goto out;
-
- if (my_skb_head_push(skb, sizeof(struct unicast_packet)) < 0)
+ if (my_skb_head_push(skb, sizeof(*unicast_packet)) < 0)
goto out;
unicast_packet = (struct unicast_packet *)skb->data;
@@ -329,9 +325,12 @@
unicast_packet->ttl = TTL;
/* copy the destination for faster routing */
memcpy(unicast_packet->dest, orig_node->orig, ETH_ALEN);
+ /* set the destination tt version number */
+ unicast_packet->ttvn =
+ (uint8_t)atomic_read(&orig_node->last_ttvn);
if (atomic_read(&bat_priv->fragmentation) &&
- data_len + sizeof(struct unicast_packet) >
+ data_len + sizeof(*unicast_packet) >
neigh_node->if_incoming->net_dev->mtu) {
/* send frag skb decreases ttl */
unicast_packet->ttl++;
diff --git a/net/batman-adv/unicast.h b/net/batman-adv/unicast.h
index 16ad7a9..62f54b9 100644
--- a/net/batman-adv/unicast.h
+++ b/net/batman-adv/unicast.h
@@ -32,11 +32,11 @@
void frag_list_free(struct list_head *head);
int unicast_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv);
int frag_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv,
- struct hard_iface *hard_iface, uint8_t dstaddr[]);
+ struct hard_iface *hard_iface, const uint8_t dstaddr[]);
-static inline int frag_can_reassemble(struct sk_buff *skb, int mtu)
+static inline int frag_can_reassemble(const struct sk_buff *skb, int mtu)
{
- struct unicast_frag_packet *unicast_packet;
+ const struct unicast_frag_packet *unicast_packet;
int uneven_correction = 0;
unsigned int merged_size;
@@ -49,7 +49,7 @@
uneven_correction = -1;
}
- merged_size = (skb->len - sizeof(struct unicast_frag_packet)) * 2;
+ merged_size = (skb->len - sizeof(*unicast_packet)) * 2;
merged_size += sizeof(struct unicast_packet) + uneven_correction;
return merged_size <= mtu;
diff --git a/net/batman-adv/vis.c b/net/batman-adv/vis.c
index c39f20c..8a1b985 100644
--- a/net/batman-adv/vis.c
+++ b/net/batman-adv/vis.c
@@ -30,22 +30,6 @@
#define MAX_VIS_PACKET_SIZE 1000
-/* Returns the smallest signed integer in two's complement with the sizeof x */
-#define smallest_signed_int(x) (1u << (7u + 8u * (sizeof(x) - 1u)))
-
-/* Checks if a sequence number x is a predecessor/successor of y.
- * they handle overflows/underflows and can correctly check for a
- * predecessor/successor unless the variable sequence number has grown by
- * more then 2**(bitwidth(x)-1)-1.
- * This means that for a uint8_t with the maximum value 255, it would think:
- * - when adding nothing - it is neither a predecessor nor a successor
- * - before adding more than 127 to the starting value - it is a predecessor,
- * - when adding 128 - it is neither a predecessor nor a successor,
- * - after adding more than 127 to the starting value - it is a successor */
-#define seq_before(x, y) ({typeof(x) _dummy = (x - y); \
- _dummy > smallest_signed_int(_dummy); })
-#define seq_after(x, y) seq_before(y, x)
-
static void start_vis_timer(struct bat_priv *bat_priv);
/* free the info */
@@ -68,10 +52,10 @@
}
/* Compare two vis packets, used by the hashing algorithm */
-static int vis_info_cmp(struct hlist_node *node, void *data2)
+static int vis_info_cmp(const struct hlist_node *node, const void *data2)
{
- struct vis_info *d1, *d2;
- struct vis_packet *p1, *p2;
+ const struct vis_info *d1, *d2;
+ const struct vis_packet *p1, *p2;
d1 = container_of(node, struct vis_info, hash_entry);
d2 = data2;
@@ -82,11 +66,11 @@
/* hash function to choose an entry in a hash table of given size */
/* hash algorithm from http://en.wikipedia.org/wiki/Hash_table */
-static int vis_info_choose(void *data, int size)
+static int vis_info_choose(const void *data, int size)
{
- struct vis_info *vis_info = data;
- struct vis_packet *packet;
- unsigned char *key;
+ const struct vis_info *vis_info = data;
+ const struct vis_packet *packet;
+ const unsigned char *key;
uint32_t hash = 0;
size_t i;
@@ -106,7 +90,7 @@
}
static struct vis_info *vis_hash_find(struct bat_priv *bat_priv,
- void *data)
+ const void *data)
{
struct hashtable_t *hash = bat_priv->vis_hash;
struct hlist_head *head;
@@ -143,7 +127,7 @@
struct hlist_node *pos;
hlist_for_each_entry(entry, pos, if_list, list) {
- if (compare_eth(entry->addr, (void *)interface))
+ if (compare_eth(entry->addr, interface))
return;
}
@@ -156,7 +140,8 @@
hlist_add_head(&entry->list, if_list);
}
-static ssize_t vis_data_read_prim_sec(char *buff, struct hlist_head *if_list)
+static ssize_t vis_data_read_prim_sec(char *buff,
+ const struct hlist_head *if_list)
{
struct if_list_entry *entry;
struct hlist_node *pos;
@@ -189,8 +174,9 @@
}
/* read an entry */
-static ssize_t vis_data_read_entry(char *buff, struct vis_info_entry *entry,
- uint8_t *src, bool primary)
+static ssize_t vis_data_read_entry(char *buff,
+ const struct vis_info_entry *entry,
+ const uint8_t *src, bool primary)
{
/* maximal length: max(4+17+2, 3+17+1+3+2) == 26 */
if (primary && entry->quality == 0)
@@ -239,7 +225,7 @@
hlist_for_each_entry_rcu(info, node, head, hash_entry) {
packet = (struct vis_packet *)info->skb_packet->data;
entries = (struct vis_info_entry *)
- ((char *)packet + sizeof(struct vis_packet));
+ ((char *)packet + sizeof(*packet));
for (j = 0; j < packet->entries; j++) {
if (entries[j].quality == 0)
@@ -287,7 +273,7 @@
hlist_for_each_entry_rcu(info, node, head, hash_entry) {
packet = (struct vis_packet *)info->skb_packet->data;
entries = (struct vis_info_entry *)
- ((char *)packet + sizeof(struct vis_packet));
+ ((char *)packet + sizeof(*packet));
for (j = 0; j < packet->entries; j++) {
if (entries[j].quality == 0)
@@ -361,11 +347,11 @@
/* tries to add one entry to the receive list. */
static void recv_list_add(struct bat_priv *bat_priv,
- struct list_head *recv_list, char *mac)
+ struct list_head *recv_list, const char *mac)
{
struct recvlist_node *entry;
- entry = kmalloc(sizeof(struct recvlist_node), GFP_ATOMIC);
+ entry = kmalloc(sizeof(*entry), GFP_ATOMIC);
if (!entry)
return;
@@ -377,9 +363,9 @@
/* returns 1 if this mac is in the recv_list */
static int recv_list_is_in(struct bat_priv *bat_priv,
- struct list_head *recv_list, char *mac)
+ const struct list_head *recv_list, const char *mac)
{
- struct recvlist_node *entry;
+ const struct recvlist_node *entry;
spin_lock_bh(&bat_priv->vis_list_lock);
list_for_each_entry(entry, recv_list, list) {
@@ -412,11 +398,11 @@
return NULL;
/* see if the packet is already in vis_hash */
- search_elem.skb_packet = dev_alloc_skb(sizeof(struct vis_packet));
+ search_elem.skb_packet = dev_alloc_skb(sizeof(*search_packet));
if (!search_elem.skb_packet)
return NULL;
search_packet = (struct vis_packet *)skb_put(search_elem.skb_packet,
- sizeof(struct vis_packet));
+ sizeof(*search_packet));
memcpy(search_packet->vis_orig, vis_packet->vis_orig, ETH_ALEN);
old_info = vis_hash_find(bat_priv, &search_elem);
@@ -442,27 +428,26 @@
kref_put(&old_info->refcount, free_info);
}
- info = kmalloc(sizeof(struct vis_info), GFP_ATOMIC);
+ info = kmalloc(sizeof(*info), GFP_ATOMIC);
if (!info)
return NULL;
- info->skb_packet = dev_alloc_skb(sizeof(struct vis_packet) +
- vis_info_len + sizeof(struct ethhdr));
+ info->skb_packet = dev_alloc_skb(sizeof(*packet) + vis_info_len +
+ sizeof(struct ethhdr));
if (!info->skb_packet) {
kfree(info);
return NULL;
}
skb_reserve(info->skb_packet, sizeof(struct ethhdr));
- packet = (struct vis_packet *)skb_put(info->skb_packet,
- sizeof(struct vis_packet) +
- vis_info_len);
+ packet = (struct vis_packet *)skb_put(info->skb_packet, sizeof(*packet)
+ + vis_info_len);
kref_init(&info->refcount);
INIT_LIST_HEAD(&info->send_list);
INIT_LIST_HEAD(&info->recv_list);
info->first_seen = jiffies;
info->bat_priv = bat_priv;
- memcpy(packet, vis_packet, sizeof(struct vis_packet) + vis_info_len);
+ memcpy(packet, vis_packet, sizeof(*packet) + vis_info_len);
/* initialize and add new packet. */
*is_new = 1;
@@ -599,9 +584,9 @@
}
/* Return true if the vis packet is full. */
-static bool vis_packet_full(struct vis_info *info)
+static bool vis_packet_full(const struct vis_info *info)
{
- struct vis_packet *packet;
+ const struct vis_packet *packet;
packet = (struct vis_packet *)info->skb_packet->data;
if (MAX_VIS_PACKET_SIZE / sizeof(struct vis_info_entry)
@@ -619,7 +604,7 @@
struct hlist_head *head;
struct orig_node *orig_node;
struct neigh_node *router;
- struct vis_info *info = (struct vis_info *)bat_priv->my_vis_info;
+ struct vis_info *info = bat_priv->my_vis_info;
struct vis_packet *packet = (struct vis_packet *)info->skb_packet->data;
struct vis_info_entry *entry;
struct tt_local_entry *tt_local_entry;
@@ -632,7 +617,7 @@
packet->ttl = TTL;
packet->seqno = htonl(ntohl(packet->seqno) + 1);
packet->entries = 0;
- skb_trim(info->skb_packet, sizeof(struct vis_packet));
+ skb_trim(info->skb_packet, sizeof(*packet));
if (packet->vis_type == VIS_TYPE_CLIENT_UPDATE) {
best_tq = find_best_vis_server(bat_priv, info);
@@ -680,11 +665,12 @@
hash = bat_priv->tt_local_hash;
- spin_lock_bh(&bat_priv->tt_lhash_lock);
for (i = 0; i < hash->size; i++) {
head = &hash->table[i];
- hlist_for_each_entry(tt_local_entry, node, head, hash_entry) {
+ rcu_read_lock();
+ hlist_for_each_entry_rcu(tt_local_entry, node, head,
+ hash_entry) {
entry = (struct vis_info_entry *)
skb_put(info->skb_packet,
sizeof(*entry));
@@ -693,14 +679,12 @@
entry->quality = 0; /* 0 means TT */
packet->entries++;
- if (vis_packet_full(info)) {
- spin_unlock_bh(&bat_priv->tt_lhash_lock);
- return 0;
- }
+ if (vis_packet_full(info))
+ goto unlock;
}
+ rcu_read_unlock();
}
- spin_unlock_bh(&bat_priv->tt_lhash_lock);
return 0;
unlock:
@@ -908,17 +892,15 @@
goto err;
}
- bat_priv->my_vis_info->skb_packet = dev_alloc_skb(
- sizeof(struct vis_packet) +
- MAX_VIS_PACKET_SIZE +
- sizeof(struct ethhdr));
+ bat_priv->my_vis_info->skb_packet = dev_alloc_skb(sizeof(*packet) +
+ MAX_VIS_PACKET_SIZE +
+ sizeof(struct ethhdr));
if (!bat_priv->my_vis_info->skb_packet)
goto free_info;
skb_reserve(bat_priv->my_vis_info->skb_packet, sizeof(struct ethhdr));
- packet = (struct vis_packet *)skb_put(
- bat_priv->my_vis_info->skb_packet,
- sizeof(struct vis_packet));
+ packet = (struct vis_packet *)skb_put(bat_priv->my_vis_info->skb_packet,
+ sizeof(*packet));
/* prefill the vis info */
bat_priv->my_vis_info->first_seen = jiffies -
diff --git a/net/bluetooth/Kconfig b/net/bluetooth/Kconfig
index 6ae5ec5..bfb3dc0 100644
--- a/net/bluetooth/Kconfig
+++ b/net/bluetooth/Kconfig
@@ -6,6 +6,7 @@
tristate "Bluetooth subsystem support"
depends on NET && !S390
depends on RFKILL || !RFKILL
+ select CRYPTO
help
Bluetooth is low-cost, low-power, short-range wireless technology.
It was designed as a replacement for cables and other short-range
@@ -22,6 +23,7 @@
BNEP Module (Bluetooth Network Encapsulation Protocol)
CMTP Module (CAPI Message Transport Protocol)
HIDP Module (Human Interface Device Protocol)
+ SMP Module (Security Manager Protocol)
Say Y here to compile Bluetooth support into the kernel or say M to
compile it as module (bluetooth).
@@ -36,11 +38,18 @@
config BT_L2CAP
bool "L2CAP protocol support"
select CRC16
+ select CRYPTO
+ select CRYPTO_BLKCIPHER
+ select CRYPTO_AES
+ select CRYPTO_ECB
help
L2CAP (Logical Link Control and Adaptation Protocol) provides
connection oriented and connection-less data transport. L2CAP
support is required for most Bluetooth applications.
+ Also included is support for SMP (Security Manager Protocol) which
+ is the security layer on top of LE (Low Energy) links.
+
config BT_SCO
bool "SCO links support"
help
diff --git a/net/bluetooth/Makefile b/net/bluetooth/Makefile
index f04fe9a..9b67f3d 100644
--- a/net/bluetooth/Makefile
+++ b/net/bluetooth/Makefile
@@ -9,5 +9,5 @@
obj-$(CONFIG_BT_HIDP) += hidp/
bluetooth-y := af_bluetooth.o hci_core.o hci_conn.o hci_event.o mgmt.o hci_sock.o hci_sysfs.o lib.o
-bluetooth-$(CONFIG_BT_L2CAP) += l2cap_core.o l2cap_sock.o
+bluetooth-$(CONFIG_BT_L2CAP) += l2cap_core.o l2cap_sock.o smp.o
bluetooth-$(CONFIG_BT_SCO) += sco.o
diff --git a/net/bluetooth/cmtp/capi.c b/net/bluetooth/cmtp/capi.c
index 744233c..040f67b 100644
--- a/net/bluetooth/cmtp/capi.c
+++ b/net/bluetooth/cmtp/capi.c
@@ -326,7 +326,7 @@
{
struct capi_ctr *ctrl = &session->ctrl;
struct cmtp_application *application;
- __u16 cmd, appl;
+ __u16 appl;
__u32 contr;
BT_DBG("session %p skb %p len %d", session, skb, skb->len);
@@ -344,7 +344,6 @@
return;
}
- cmd = CAPICMD(CAPIMSG_COMMAND(skb->data), CAPIMSG_SUBCOMMAND(skb->data));
appl = CAPIMSG_APPID(skb->data);
contr = CAPIMSG_CONTROL(skb->data);
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index d3a05b9..fa48c0b 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -53,11 +53,13 @@
conn->state = BT_CONNECT;
conn->out = 1;
conn->link_mode |= HCI_LM_MASTER;
+ conn->sec_level = BT_SECURITY_LOW;
memset(&cp, 0, sizeof(cp));
cp.scan_interval = cpu_to_le16(0x0004);
cp.scan_window = cpu_to_le16(0x0004);
bacpy(&cp.peer_addr, &conn->dst);
+ cp.peer_addr_type = conn->dst_type;
cp.conn_interval_min = cpu_to_le16(0x0008);
cp.conn_interval_max = cpu_to_le16(0x0100);
cp.supervision_timeout = cpu_to_le16(0x0064);
@@ -203,6 +205,55 @@
}
EXPORT_SYMBOL(hci_le_conn_update);
+void hci_le_start_enc(struct hci_conn *conn, __le16 ediv, __u8 rand[8],
+ __u8 ltk[16])
+{
+ struct hci_dev *hdev = conn->hdev;
+ struct hci_cp_le_start_enc cp;
+
+ BT_DBG("%p", conn);
+
+ memset(&cp, 0, sizeof(cp));
+
+ cp.handle = cpu_to_le16(conn->handle);
+ memcpy(cp.ltk, ltk, sizeof(cp.ltk));
+ cp.ediv = ediv;
+ memcpy(cp.rand, rand, sizeof(rand));
+
+ hci_send_cmd(hdev, HCI_OP_LE_START_ENC, sizeof(cp), &cp);
+}
+EXPORT_SYMBOL(hci_le_start_enc);
+
+void hci_le_ltk_reply(struct hci_conn *conn, u8 ltk[16])
+{
+ struct hci_dev *hdev = conn->hdev;
+ struct hci_cp_le_ltk_reply cp;
+
+ BT_DBG("%p", conn);
+
+ memset(&cp, 0, sizeof(cp));
+
+ cp.handle = cpu_to_le16(conn->handle);
+ memcpy(cp.ltk, ltk, sizeof(ltk));
+
+ hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp);
+}
+EXPORT_SYMBOL(hci_le_ltk_reply);
+
+void hci_le_ltk_neg_reply(struct hci_conn *conn)
+{
+ struct hci_dev *hdev = conn->hdev;
+ struct hci_cp_le_ltk_neg_reply cp;
+
+ BT_DBG("%p", conn);
+
+ memset(&cp, 0, sizeof(cp));
+
+ cp.handle = cpu_to_le16(conn->handle);
+
+ hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(cp), &cp);
+}
+
/* Device _must_ be locked */
void hci_sco_setup(struct hci_conn *conn, __u8 status)
{
@@ -447,14 +498,23 @@
BT_DBG("%s dst %s", hdev->name, batostr(dst));
if (type == LE_LINK) {
+ struct adv_entry *entry;
+
le = hci_conn_hash_lookup_ba(hdev, LE_LINK, dst);
if (le)
return ERR_PTR(-EBUSY);
+
+ entry = hci_find_adv_entry(hdev, dst);
+ if (!entry)
+ return ERR_PTR(-EHOSTUNREACH);
+
le = hci_conn_add(hdev, LE_LINK, dst);
if (!le)
return ERR_PTR(-ENOMEM);
- if (le->state == BT_OPEN)
- hci_le_connect(le);
+
+ le->dst_type = entry->bdaddr_type;
+
+ hci_le_connect(le);
hci_conn_hold(le);
@@ -497,7 +557,7 @@
if (acl->state == BT_CONNECTED &&
(sco->state == BT_OPEN || sco->state == BT_CLOSED)) {
acl->power_save = 1;
- hci_conn_enter_active_mode(acl);
+ hci_conn_enter_active_mode(acl, BT_POWER_FORCE_ACTIVE_ON);
if (test_bit(HCI_CONN_MODE_CHANGE_PEND, &acl->pend)) {
/* defer SCO setup until mode change completed */
@@ -548,6 +608,8 @@
cp.handle = cpu_to_le16(conn->handle);
hci_send_cmd(conn->hdev, HCI_OP_AUTH_REQUESTED,
sizeof(cp), &cp);
+ if (conn->key_type != 0xff)
+ set_bit(HCI_CONN_REAUTH_PEND, &conn->pend);
}
return 0;
@@ -631,9 +693,7 @@
if (sec_level != BT_SECURITY_HIGH)
return 1; /* Accept if non-secure is required */
- if (conn->key_type == HCI_LK_AUTH_COMBINATION ||
- (conn->key_type == HCI_LK_COMBINATION &&
- conn->pin_length == 16))
+ if (conn->sec_level == BT_SECURITY_HIGH)
return 1;
return 0; /* Reject not secure link */
@@ -676,7 +736,7 @@
EXPORT_SYMBOL(hci_conn_switch_role);
/* Enter active mode */
-void hci_conn_enter_active_mode(struct hci_conn *conn)
+void hci_conn_enter_active_mode(struct hci_conn *conn, __u8 force_active)
{
struct hci_dev *hdev = conn->hdev;
@@ -685,7 +745,10 @@
if (test_bit(HCI_RAW, &hdev->flags))
return;
- if (conn->mode != HCI_CM_SNIFF || !conn->power_save)
+ if (conn->mode != HCI_CM_SNIFF)
+ goto timer;
+
+ if (!conn->power_save && !force_active)
goto timer;
if (!test_and_set_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend)) {
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 815269b..b18db56 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -42,6 +42,7 @@
#include <linux/notifier.h>
#include <linux/rfkill.h>
#include <linux/timer.h>
+#include <linux/crypto.h>
#include <net/sock.h>
#include <asm/system.h>
@@ -59,6 +60,8 @@
static DEFINE_RWLOCK(hci_task_lock);
+static int enable_smp;
+
/* HCI device list */
LIST_HEAD(hci_dev_list);
DEFINE_RWLOCK(hci_dev_list_lock);
@@ -1202,6 +1205,177 @@
return 0;
}
+struct bdaddr_list *hci_blacklist_lookup(struct hci_dev *hdev,
+ bdaddr_t *bdaddr)
+{
+ struct list_head *p;
+
+ list_for_each(p, &hdev->blacklist) {
+ struct bdaddr_list *b;
+
+ b = list_entry(p, struct bdaddr_list, list);
+
+ if (bacmp(bdaddr, &b->bdaddr) == 0)
+ return b;
+ }
+
+ return NULL;
+}
+
+int hci_blacklist_clear(struct hci_dev *hdev)
+{
+ struct list_head *p, *n;
+
+ list_for_each_safe(p, n, &hdev->blacklist) {
+ struct bdaddr_list *b;
+
+ b = list_entry(p, struct bdaddr_list, list);
+
+ list_del(p);
+ kfree(b);
+ }
+
+ return 0;
+}
+
+int hci_blacklist_add(struct hci_dev *hdev, bdaddr_t *bdaddr)
+{
+ struct bdaddr_list *entry;
+ int err;
+
+ if (bacmp(bdaddr, BDADDR_ANY) == 0)
+ return -EBADF;
+
+ hci_dev_lock(hdev);
+
+ if (hci_blacklist_lookup(hdev, bdaddr)) {
+ err = -EEXIST;
+ goto err;
+ }
+
+ entry = kzalloc(sizeof(struct bdaddr_list), GFP_KERNEL);
+ if (!entry) {
+ return -ENOMEM;
+ goto err;
+ }
+
+ bacpy(&entry->bdaddr, bdaddr);
+
+ list_add(&entry->list, &hdev->blacklist);
+
+ err = 0;
+
+err:
+ hci_dev_unlock(hdev);
+ return err;
+}
+
+int hci_blacklist_del(struct hci_dev *hdev, bdaddr_t *bdaddr)
+{
+ struct bdaddr_list *entry;
+ int err = 0;
+
+ hci_dev_lock(hdev);
+
+ if (bacmp(bdaddr, BDADDR_ANY) == 0) {
+ hci_blacklist_clear(hdev);
+ goto done;
+ }
+
+ entry = hci_blacklist_lookup(hdev, bdaddr);
+ if (!entry) {
+ err = -ENOENT;
+ goto done;
+ }
+
+ list_del(&entry->list);
+ kfree(entry);
+
+done:
+ hci_dev_unlock(hdev);
+ return err;
+}
+
+static void hci_clear_adv_cache(unsigned long arg)
+{
+ struct hci_dev *hdev = (void *) arg;
+
+ hci_dev_lock(hdev);
+
+ hci_adv_entries_clear(hdev);
+
+ hci_dev_unlock(hdev);
+}
+
+int hci_adv_entries_clear(struct hci_dev *hdev)
+{
+ struct adv_entry *entry, *tmp;
+
+ list_for_each_entry_safe(entry, tmp, &hdev->adv_entries, list) {
+ list_del(&entry->list);
+ kfree(entry);
+ }
+
+ BT_DBG("%s adv cache cleared", hdev->name);
+
+ return 0;
+}
+
+struct adv_entry *hci_find_adv_entry(struct hci_dev *hdev, bdaddr_t *bdaddr)
+{
+ struct adv_entry *entry;
+
+ list_for_each_entry(entry, &hdev->adv_entries, list)
+ if (bacmp(bdaddr, &entry->bdaddr) == 0)
+ return entry;
+
+ return NULL;
+}
+
+static inline int is_connectable_adv(u8 evt_type)
+{
+ if (evt_type == ADV_IND || evt_type == ADV_DIRECT_IND)
+ return 1;
+
+ return 0;
+}
+
+int hci_add_adv_entry(struct hci_dev *hdev,
+ struct hci_ev_le_advertising_info *ev)
+{
+ struct adv_entry *entry;
+
+ if (!is_connectable_adv(ev->evt_type))
+ return -EINVAL;
+
+ /* Only new entries should be added to adv_entries. So, if
+ * bdaddr was found, don't add it. */
+ if (hci_find_adv_entry(hdev, &ev->bdaddr))
+ return 0;
+
+ entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
+ if (!entry)
+ return -ENOMEM;
+
+ bacpy(&entry->bdaddr, &ev->bdaddr);
+ entry->bdaddr_type = ev->bdaddr_type;
+
+ list_add(&entry->list, &hdev->adv_entries);
+
+ BT_DBG("%s adv entry added: address %s type %u", hdev->name,
+ batostr(&entry->bdaddr), entry->bdaddr_type);
+
+ return 0;
+}
+
+static struct crypto_blkcipher *alloc_cypher(void)
+{
+ if (enable_smp)
+ return crypto_alloc_blkcipher("ecb(aes)", 0, CRYPTO_ALG_ASYNC);
+
+ return ERR_PTR(-ENOTSUPP);
+}
+
/* Register HCI device */
int hci_register_dev(struct hci_dev *hdev)
{
@@ -1268,6 +1442,10 @@
INIT_LIST_HEAD(&hdev->remote_oob_data);
+ INIT_LIST_HEAD(&hdev->adv_entries);
+ setup_timer(&hdev->adv_timer, hci_clear_adv_cache,
+ (unsigned long) hdev);
+
INIT_WORK(&hdev->power_on, hci_power_on);
INIT_WORK(&hdev->power_off, hci_power_off);
setup_timer(&hdev->off_timer, hci_auto_off, (unsigned long) hdev);
@@ -1282,6 +1460,11 @@
if (!hdev->workqueue)
goto nomem;
+ hdev->tfm = alloc_cypher();
+ if (IS_ERR(hdev->tfm))
+ BT_INFO("Failed to load transform for ecb(aes): %ld",
+ PTR_ERR(hdev->tfm));
+
hci_register_sysfs(hdev);
hdev->rfkill = rfkill_alloc(hdev->name, &hdev->dev,
@@ -1330,6 +1513,9 @@
!test_bit(HCI_SETUP, &hdev->flags))
mgmt_index_removed(hdev->id);
+ if (!IS_ERR(hdev->tfm))
+ crypto_free_blkcipher(hdev->tfm);
+
hci_notify(hdev, HCI_DEV_UNREG);
if (hdev->rfkill) {
@@ -1340,6 +1526,7 @@
hci_unregister_sysfs(hdev);
hci_del_off_timer(hdev);
+ del_timer(&hdev->adv_timer);
destroy_workqueue(hdev->workqueue);
@@ -1348,6 +1535,7 @@
hci_uuids_clear(hdev);
hci_link_keys_clear(hdev);
hci_remote_oob_data_clear(hdev);
+ hci_adv_entries_clear(hdev);
hci_dev_unlock_bh(hdev);
__hci_dev_put(hdev);
@@ -1519,7 +1707,7 @@
data += (count - rem);
count = rem;
- };
+ }
return rem;
}
@@ -1554,7 +1742,7 @@
data += (count - rem);
count = rem;
- };
+ }
return rem;
}
@@ -1891,7 +2079,7 @@
while (quote-- && (skb = skb_dequeue(&conn->data_q))) {
BT_DBG("skb %p len %d", skb, skb->len);
- hci_conn_enter_active_mode(conn);
+ hci_conn_enter_active_mode(conn, bt_cb(skb)->force_active);
hci_send_frame(skb);
hdev->acl_last_tx = jiffies;
@@ -2030,7 +2218,7 @@
if (conn) {
register struct hci_proto *hp;
- hci_conn_enter_active_mode(conn);
+ hci_conn_enter_active_mode(conn, bt_cb(skb)->force_active);
/* Send to upper protocol */
hp = hci_proto[HCI_PROTO_L2CAP];
@@ -2164,3 +2352,6 @@
}
}
}
+
+module_param(enable_smp, bool, 0644);
+MODULE_PARM_DESC(enable_smp, "Enable SMP support (LE only)");
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 77930aa..ac2c5e8 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -841,6 +841,57 @@
rp->randomizer, rp->status);
}
+static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
+ struct sk_buff *skb)
+{
+ struct hci_cp_le_set_scan_enable *cp;
+ __u8 status = *((__u8 *) skb->data);
+
+ BT_DBG("%s status 0x%x", hdev->name, status);
+
+ if (status)
+ return;
+
+ cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE);
+ if (!cp)
+ return;
+
+ hci_dev_lock(hdev);
+
+ if (cp->enable == 0x01) {
+ del_timer(&hdev->adv_timer);
+ hci_adv_entries_clear(hdev);
+ } else if (cp->enable == 0x00) {
+ mod_timer(&hdev->adv_timer, jiffies + ADV_CLEAR_TIMEOUT);
+ }
+
+ hci_dev_unlock(hdev);
+}
+
+static void hci_cc_le_ltk_reply(struct hci_dev *hdev, struct sk_buff *skb)
+{
+ struct hci_rp_le_ltk_reply *rp = (void *) skb->data;
+
+ BT_DBG("%s status 0x%x", hdev->name, rp->status);
+
+ if (rp->status)
+ return;
+
+ hci_req_complete(hdev, HCI_OP_LE_LTK_REPLY, rp->status);
+}
+
+static void hci_cc_le_ltk_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
+{
+ struct hci_rp_le_ltk_neg_reply *rp = (void *) skb->data;
+
+ BT_DBG("%s status 0x%x", hdev->name, rp->status);
+
+ if (rp->status)
+ return;
+
+ hci_req_complete(hdev, HCI_OP_LE_LTK_NEG_REPLY, rp->status);
+}
+
static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
{
BT_DBG("%s status 0x%x", hdev->name, status);
@@ -1209,16 +1260,23 @@
} else {
if (!conn) {
conn = hci_conn_add(hdev, LE_LINK, &cp->peer_addr);
- if (conn)
+ if (conn) {
+ conn->dst_type = cp->peer_addr_type;
conn->out = 1;
- else
+ } else {
BT_ERR("No memory for new connection");
+ }
}
}
hci_dev_unlock(hdev);
}
+static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status)
+{
+ BT_DBG("%s status 0x%x", hdev->name, status);
+}
+
static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
__u8 status = *((__u8 *) skb->data);
@@ -1462,51 +1520,58 @@
hci_dev_lock(hdev);
conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
- if (conn) {
- if (!ev->status) {
+ if (!conn)
+ goto unlock;
+
+ if (!ev->status) {
+ if (!(conn->ssp_mode > 0 && hdev->ssp_mode > 0) &&
+ test_bit(HCI_CONN_REAUTH_PEND, &conn->pend)) {
+ BT_INFO("re-auth of legacy device is not possible.");
+ } else {
conn->link_mode |= HCI_LM_AUTH;
conn->sec_level = conn->pending_sec_level;
- } else {
- mgmt_auth_failed(hdev->id, &conn->dst, ev->status);
}
+ } else {
+ mgmt_auth_failed(hdev->id, &conn->dst, ev->status);
+ }
- clear_bit(HCI_CONN_AUTH_PEND, &conn->pend);
+ clear_bit(HCI_CONN_AUTH_PEND, &conn->pend);
+ clear_bit(HCI_CONN_REAUTH_PEND, &conn->pend);
- if (conn->state == BT_CONFIG) {
- if (!ev->status && hdev->ssp_mode > 0 &&
- conn->ssp_mode > 0) {
- struct hci_cp_set_conn_encrypt cp;
- cp.handle = ev->handle;
- cp.encrypt = 0x01;
- hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT,
- sizeof(cp), &cp);
- } else {
- conn->state = BT_CONNECTED;
- hci_proto_connect_cfm(conn, ev->status);
- hci_conn_put(conn);
- }
+ if (conn->state == BT_CONFIG) {
+ if (!ev->status && hdev->ssp_mode > 0 && conn->ssp_mode > 0) {
+ struct hci_cp_set_conn_encrypt cp;
+ cp.handle = ev->handle;
+ cp.encrypt = 0x01;
+ hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
+ &cp);
} else {
- hci_auth_cfm(conn, ev->status);
-
- hci_conn_hold(conn);
- conn->disc_timeout = HCI_DISCONN_TIMEOUT;
+ conn->state = BT_CONNECTED;
+ hci_proto_connect_cfm(conn, ev->status);
hci_conn_put(conn);
}
+ } else {
+ hci_auth_cfm(conn, ev->status);
- if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) {
- if (!ev->status) {
- struct hci_cp_set_conn_encrypt cp;
- cp.handle = ev->handle;
- cp.encrypt = 0x01;
- hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT,
- sizeof(cp), &cp);
- } else {
- clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend);
- hci_encrypt_cfm(conn, ev->status, 0x00);
- }
+ hci_conn_hold(conn);
+ conn->disc_timeout = HCI_DISCONN_TIMEOUT;
+ hci_conn_put(conn);
+ }
+
+ if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) {
+ if (!ev->status) {
+ struct hci_cp_set_conn_encrypt cp;
+ cp.handle = ev->handle;
+ cp.encrypt = 0x01;
+ hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
+ &cp);
+ } else {
+ clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend);
+ hci_encrypt_cfm(conn, ev->status, 0x00);
}
}
+unlock:
hci_dev_unlock(hdev);
}
@@ -1557,6 +1622,7 @@
/* Encryption implies authentication */
conn->link_mode |= HCI_LM_AUTH;
conn->link_mode |= HCI_LM_ENCRYPT;
+ conn->sec_level = conn->pending_sec_level;
} else
conn->link_mode &= ~HCI_LM_ENCRYPT;
}
@@ -1816,6 +1882,18 @@
hci_cc_user_confirm_neg_reply(hdev, skb);
break;
+ case HCI_OP_LE_SET_SCAN_ENABLE:
+ hci_cc_le_set_scan_enable(hdev, skb);
+ break;
+
+ case HCI_OP_LE_LTK_REPLY:
+ hci_cc_le_ltk_reply(hdev, skb);
+ break;
+
+ case HCI_OP_LE_LTK_NEG_REPLY:
+ hci_cc_le_ltk_neg_reply(hdev, skb);
+ break;
+
default:
BT_DBG("%s opcode 0x%x", hdev->name, opcode);
break;
@@ -1894,6 +1972,10 @@
hci_cs_le_create_conn(hdev, ev->status);
break;
+ case HCI_OP_LE_START_ENC:
+ hci_cs_le_start_enc(hdev, ev->status);
+ break;
+
default:
BT_DBG("%s opcode 0x%x", hdev->name, opcode);
break;
@@ -2658,6 +2740,8 @@
hci_dev_unlock(hdev);
return;
}
+
+ conn->dst_type = ev->bdaddr_type;
}
if (ev->status) {
@@ -2670,6 +2754,7 @@
mgmt_connected(hdev->id, &ev->bdaddr);
+ conn->sec_level = BT_SECURITY_LOW;
conn->handle = __le16_to_cpu(ev->handle);
conn->state = BT_CONNECTED;
@@ -2682,6 +2767,49 @@
hci_dev_unlock(hdev);
}
+static inline void hci_le_adv_report_evt(struct hci_dev *hdev,
+ struct sk_buff *skb)
+{
+ struct hci_ev_le_advertising_info *ev;
+ u8 num_reports;
+
+ num_reports = skb->data[0];
+ ev = (void *) &skb->data[1];
+
+ hci_dev_lock(hdev);
+
+ hci_add_adv_entry(hdev, ev);
+
+ while (--num_reports) {
+ ev = (void *) (ev->data + ev->length + 1);
+ hci_add_adv_entry(hdev, ev);
+ }
+
+ hci_dev_unlock(hdev);
+}
+
+static inline void hci_le_ltk_request_evt(struct hci_dev *hdev,
+ struct sk_buff *skb)
+{
+ struct hci_ev_le_ltk_req *ev = (void *) skb->data;
+ struct hci_cp_le_ltk_reply cp;
+ struct hci_conn *conn;
+
+ BT_DBG("%s handle %d", hdev->name, cpu_to_le16(ev->handle));
+
+ hci_dev_lock(hdev);
+
+ conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
+
+ memset(&cp, 0, sizeof(cp));
+ cp.handle = cpu_to_le16(conn->handle);
+ memcpy(cp.ltk, conn->ltk, sizeof(conn->ltk));
+
+ hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp);
+
+ hci_dev_unlock(hdev);
+}
+
static inline void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
struct hci_ev_le_meta *le_ev = (void *) skb->data;
@@ -2693,6 +2821,14 @@
hci_le_conn_complete_evt(hdev, skb);
break;
+ case HCI_EV_LE_ADVERTISING_REPORT:
+ hci_le_adv_report_evt(hdev, skb);
+ break;
+
+ case HCI_EV_LE_LTK_REQ:
+ hci_le_ltk_request_evt(hdev, skb);
+ break;
+
default:
break;
}
diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c
index 295e4a8..ff02cf5 100644
--- a/net/bluetooth/hci_sock.c
+++ b/net/bluetooth/hci_sock.c
@@ -180,82 +180,24 @@
return 0;
}
-struct bdaddr_list *hci_blacklist_lookup(struct hci_dev *hdev, bdaddr_t *bdaddr)
-{
- struct list_head *p;
-
- list_for_each(p, &hdev->blacklist) {
- struct bdaddr_list *b;
-
- b = list_entry(p, struct bdaddr_list, list);
-
- if (bacmp(bdaddr, &b->bdaddr) == 0)
- return b;
- }
-
- return NULL;
-}
-
-static int hci_blacklist_add(struct hci_dev *hdev, void __user *arg)
+static int hci_sock_blacklist_add(struct hci_dev *hdev, void __user *arg)
{
bdaddr_t bdaddr;
- struct bdaddr_list *entry;
if (copy_from_user(&bdaddr, arg, sizeof(bdaddr)))
return -EFAULT;
- if (bacmp(&bdaddr, BDADDR_ANY) == 0)
- return -EBADF;
-
- if (hci_blacklist_lookup(hdev, &bdaddr))
- return -EEXIST;
-
- entry = kzalloc(sizeof(struct bdaddr_list), GFP_KERNEL);
- if (!entry)
- return -ENOMEM;
-
- bacpy(&entry->bdaddr, &bdaddr);
-
- list_add(&entry->list, &hdev->blacklist);
-
- return 0;
+ return hci_blacklist_add(hdev, &bdaddr);
}
-int hci_blacklist_clear(struct hci_dev *hdev)
-{
- struct list_head *p, *n;
-
- list_for_each_safe(p, n, &hdev->blacklist) {
- struct bdaddr_list *b;
-
- b = list_entry(p, struct bdaddr_list, list);
-
- list_del(p);
- kfree(b);
- }
-
- return 0;
-}
-
-static int hci_blacklist_del(struct hci_dev *hdev, void __user *arg)
+static int hci_sock_blacklist_del(struct hci_dev *hdev, void __user *arg)
{
bdaddr_t bdaddr;
- struct bdaddr_list *entry;
if (copy_from_user(&bdaddr, arg, sizeof(bdaddr)))
return -EFAULT;
- if (bacmp(&bdaddr, BDADDR_ANY) == 0)
- return hci_blacklist_clear(hdev);
-
- entry = hci_blacklist_lookup(hdev, &bdaddr);
- if (!entry)
- return -ENOENT;
-
- list_del(&entry->list);
- kfree(entry);
-
- return 0;
+ return hci_blacklist_del(hdev, &bdaddr);
}
/* Ioctls that require bound socket */
@@ -290,12 +232,12 @@
case HCIBLOCKADDR:
if (!capable(CAP_NET_ADMIN))
return -EACCES;
- return hci_blacklist_add(hdev, (void __user *) arg);
+ return hci_sock_blacklist_add(hdev, (void __user *) arg);
case HCIUNBLOCKADDR:
if (!capable(CAP_NET_ADMIN))
return -EACCES;
- return hci_blacklist_del(hdev, (void __user *) arg);
+ return hci_sock_blacklist_del(hdev, (void __user *) arg);
default:
if (hdev->ioctl)
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 56fdd91..9ec9c8c 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -54,6 +54,7 @@
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
#include <net/bluetooth/l2cap.h>
+#include <net/bluetooth/smp.h>
int disable_ertm;
@@ -62,18 +63,34 @@
static struct workqueue_struct *_busy_wq;
-LIST_HEAD(chan_list);
-DEFINE_RWLOCK(chan_list_lock);
+static LIST_HEAD(chan_list);
+static DEFINE_RWLOCK(chan_list_lock);
static void l2cap_busy_work(struct work_struct *work);
static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
u8 code, u8 ident, u16 dlen, void *data);
+static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len,
+ void *data);
static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data);
+static void l2cap_send_disconn_req(struct l2cap_conn *conn,
+ struct l2cap_chan *chan, int err);
static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb);
/* ---- L2CAP channels ---- */
+
+static inline void chan_hold(struct l2cap_chan *c)
+{
+ atomic_inc(&c->refcnt);
+}
+
+static inline void chan_put(struct l2cap_chan *c)
+{
+ if (atomic_dec_and_test(&c->refcnt))
+ kfree(c);
+}
+
static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn, u16 cid)
{
struct l2cap_chan *c;
@@ -204,6 +221,62 @@
return 0;
}
+static void l2cap_set_timer(struct l2cap_chan *chan, struct timer_list *timer, long timeout)
+{
+ BT_DBG("chan %p state %d timeout %ld", chan->sk, chan->state, timeout);
+
+ if (!mod_timer(timer, jiffies + timeout))
+ chan_hold(chan);
+}
+
+static void l2cap_clear_timer(struct l2cap_chan *chan, struct timer_list *timer)
+{
+ BT_DBG("chan %p state %d", chan, chan->state);
+
+ if (timer_pending(timer) && del_timer(timer))
+ chan_put(chan);
+}
+
+static void l2cap_state_change(struct l2cap_chan *chan, int state)
+{
+ chan->state = state;
+ chan->ops->state_change(chan->data, state);
+}
+
+static void l2cap_chan_timeout(unsigned long arg)
+{
+ struct l2cap_chan *chan = (struct l2cap_chan *) arg;
+ struct sock *sk = chan->sk;
+ int reason;
+
+ BT_DBG("chan %p state %d", chan, chan->state);
+
+ bh_lock_sock(sk);
+
+ if (sock_owned_by_user(sk)) {
+ /* sk is owned by user. Try again later */
+ __set_chan_timer(chan, HZ / 5);
+ bh_unlock_sock(sk);
+ chan_put(chan);
+ return;
+ }
+
+ if (chan->state == BT_CONNECTED || chan->state == BT_CONFIG)
+ reason = ECONNREFUSED;
+ else if (chan->state == BT_CONNECT &&
+ chan->sec_level != BT_SECURITY_SDP)
+ reason = ECONNREFUSED;
+ else
+ reason = ETIMEDOUT;
+
+ l2cap_chan_close(chan, reason);
+
+ bh_unlock_sock(sk);
+
+ chan->ops->close(chan->data);
+ chan_put(chan);
+}
+
struct l2cap_chan *l2cap_chan_create(struct sock *sk)
{
struct l2cap_chan *chan;
@@ -218,6 +291,12 @@
list_add(&chan->global_l, &chan_list);
write_unlock_bh(&chan_list_lock);
+ setup_timer(&chan->chan_timer, l2cap_chan_timeout, (unsigned long) chan);
+
+ chan->state = BT_OPEN;
+
+ atomic_set(&chan->refcnt, 1);
+
return chan;
}
@@ -227,13 +306,11 @@
list_del(&chan->global_l);
write_unlock_bh(&chan_list_lock);
- kfree(chan);
+ chan_put(chan);
}
static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
{
- struct sock *sk = chan->sk;
-
BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn,
chan->psm, chan->dcid);
@@ -241,7 +318,7 @@
chan->conn = conn;
- if (sk->sk_type == SOCK_SEQPACKET || sk->sk_type == SOCK_STREAM) {
+ if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED) {
if (conn->hcon->type == LE_LINK) {
/* LE connection */
chan->omtu = L2CAP_LE_DEFAULT_MTU;
@@ -252,7 +329,7 @@
chan->scid = l2cap_alloc_cid(conn);
chan->omtu = L2CAP_DEFAULT_MTU;
}
- } else if (sk->sk_type == SOCK_DGRAM) {
+ } else if (chan->chan_type == L2CAP_CHAN_CONN_LESS) {
/* Connectionless socket */
chan->scid = L2CAP_CID_CONN_LESS;
chan->dcid = L2CAP_CID_CONN_LESS;
@@ -264,20 +341,20 @@
chan->omtu = L2CAP_DEFAULT_MTU;
}
- sock_hold(sk);
+ chan_hold(chan);
list_add(&chan->list, &conn->chan_l);
}
/* Delete channel.
* Must be called on the locked socket. */
-void l2cap_chan_del(struct l2cap_chan *chan, int err)
+static void l2cap_chan_del(struct l2cap_chan *chan, int err)
{
struct sock *sk = chan->sk;
struct l2cap_conn *conn = chan->conn;
struct sock *parent = bt_sk(sk)->parent;
- l2cap_sock_clear_timer(sk);
+ __clear_chan_timer(chan);
BT_DBG("chan %p, conn %p, err %d", chan, conn, err);
@@ -286,13 +363,13 @@
write_lock_bh(&conn->chan_lock);
list_del(&chan->list);
write_unlock_bh(&conn->chan_lock);
- __sock_put(sk);
+ chan_put(chan);
chan->conn = NULL;
hci_conn_put(conn->hcon);
}
- sk->sk_state = BT_CLOSED;
+ l2cap_state_change(chan, BT_CLOSED);
sock_set_flag(sk, SOCK_ZAPPED);
if (err)
@@ -304,8 +381,8 @@
} else
sk->sk_state_change(sk);
- if (!(chan->conf_state & L2CAP_CONF_OUTPUT_DONE &&
- chan->conf_state & L2CAP_CONF_INPUT_DONE))
+ if (!(test_bit(CONF_OUTPUT_DONE, &chan->conf_state) &&
+ test_bit(CONF_INPUT_DONE, &chan->conf_state)))
return;
skb_queue_purge(&chan->tx_q);
@@ -313,9 +390,9 @@
if (chan->mode == L2CAP_MODE_ERTM) {
struct srej_list *l, *tmp;
- del_timer(&chan->retrans_timer);
- del_timer(&chan->monitor_timer);
- del_timer(&chan->ack_timer);
+ __clear_retrans_timer(chan);
+ __clear_monitor_timer(chan);
+ __clear_ack_timer(chan);
skb_queue_purge(&chan->srej_q);
skb_queue_purge(&chan->busy_q);
@@ -327,11 +404,86 @@
}
}
-static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan)
+static void l2cap_chan_cleanup_listen(struct sock *parent)
{
+ struct sock *sk;
+
+ BT_DBG("parent %p", parent);
+
+ /* Close not yet accepted channels */
+ while ((sk = bt_accept_dequeue(parent, NULL))) {
+ struct l2cap_chan *chan = l2cap_pi(sk)->chan;
+ __clear_chan_timer(chan);
+ lock_sock(sk);
+ l2cap_chan_close(chan, ECONNRESET);
+ release_sock(sk);
+ chan->ops->close(chan->data);
+ }
+}
+
+void l2cap_chan_close(struct l2cap_chan *chan, int reason)
+{
+ struct l2cap_conn *conn = chan->conn;
struct sock *sk = chan->sk;
- if (sk->sk_type == SOCK_RAW) {
+ BT_DBG("chan %p state %d socket %p", chan, chan->state, sk->sk_socket);
+
+ switch (chan->state) {
+ case BT_LISTEN:
+ l2cap_chan_cleanup_listen(sk);
+
+ l2cap_state_change(chan, BT_CLOSED);
+ sock_set_flag(sk, SOCK_ZAPPED);
+ break;
+
+ case BT_CONNECTED:
+ case BT_CONFIG:
+ if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED &&
+ conn->hcon->type == ACL_LINK) {
+ __clear_chan_timer(chan);
+ __set_chan_timer(chan, sk->sk_sndtimeo);
+ l2cap_send_disconn_req(conn, chan, reason);
+ } else
+ l2cap_chan_del(chan, reason);
+ break;
+
+ case BT_CONNECT2:
+ if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED &&
+ conn->hcon->type == ACL_LINK) {
+ struct l2cap_conn_rsp rsp;
+ __u16 result;
+
+ if (bt_sk(sk)->defer_setup)
+ result = L2CAP_CR_SEC_BLOCK;
+ else
+ result = L2CAP_CR_BAD_PSM;
+ l2cap_state_change(chan, BT_DISCONN);
+
+ rsp.scid = cpu_to_le16(chan->dcid);
+ rsp.dcid = cpu_to_le16(chan->scid);
+ rsp.result = cpu_to_le16(result);
+ rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
+ l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
+ sizeof(rsp), &rsp);
+ }
+
+ l2cap_chan_del(chan, reason);
+ break;
+
+ case BT_CONNECT:
+ case BT_DISCONN:
+ l2cap_chan_del(chan, reason);
+ break;
+
+ default:
+ sock_set_flag(sk, SOCK_ZAPPED);
+ break;
+ }
+}
+
+static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan)
+{
+ if (chan->chan_type == L2CAP_CHAN_RAW) {
switch (chan->sec_level) {
case BT_SECURITY_HIGH:
return HCI_AT_DEDICATED_BONDING_MITM;
@@ -371,7 +523,7 @@
return hci_conn_security(conn->hcon, chan->sec_level, auth_type);
}
-u8 l2cap_get_ident(struct l2cap_conn *conn)
+static u8 l2cap_get_ident(struct l2cap_conn *conn)
{
u8 id;
@@ -393,7 +545,7 @@
return id;
}
-void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data)
+static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data)
{
struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data);
u8 flags;
@@ -408,6 +560,8 @@
else
flags = ACL_START;
+ bt_cb(skb)->force_active = BT_POWER_FORCE_ACTIVE_ON;
+
hci_send_acl(conn->hcon, skb, flags);
}
@@ -415,13 +569,11 @@
{
struct sk_buff *skb;
struct l2cap_hdr *lh;
- struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
struct l2cap_conn *conn = chan->conn;
- struct sock *sk = (struct sock *)pi;
int count, hlen = L2CAP_HDR_SIZE + 2;
u8 flags;
- if (sk->sk_state != BT_CONNECTED)
+ if (chan->state != BT_CONNECTED)
return;
if (chan->fcs == L2CAP_FCS_CRC16)
@@ -432,15 +584,11 @@
count = min_t(unsigned int, conn->mtu, hlen);
control |= L2CAP_CTRL_FRAME_TYPE;
- if (chan->conn_state & L2CAP_CONN_SEND_FBIT) {
+ if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
control |= L2CAP_CTRL_FINAL;
- chan->conn_state &= ~L2CAP_CONN_SEND_FBIT;
- }
- if (chan->conn_state & L2CAP_CONN_SEND_PBIT) {
+ if (test_and_clear_bit(CONN_SEND_PBIT, &chan->conn_state))
control |= L2CAP_CTRL_POLL;
- chan->conn_state &= ~L2CAP_CONN_SEND_PBIT;
- }
skb = bt_skb_alloc(count, GFP_ATOMIC);
if (!skb)
@@ -461,14 +609,16 @@
else
flags = ACL_START;
+ bt_cb(skb)->force_active = chan->force_active;
+
hci_send_acl(chan->conn->hcon, skb, flags);
}
static inline void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, u16 control)
{
- if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
+ if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
control |= L2CAP_SUPER_RCV_NOT_READY;
- chan->conn_state |= L2CAP_CONN_RNR_SENT;
+ set_bit(CONN_RNR_SENT, &chan->conn_state);
} else
control |= L2CAP_SUPER_RCV_READY;
@@ -479,7 +629,7 @@
static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan)
{
- return !(chan->conf_state & L2CAP_CONF_CONNECT_PEND);
+ return !test_bit(CONF_CONNECT_PEND, &chan->conf_state);
}
static void l2cap_do_start(struct l2cap_chan *chan)
@@ -497,7 +647,7 @@
req.psm = chan->psm;
chan->ident = l2cap_get_ident(conn);
- chan->conf_state |= L2CAP_CONF_CONNECT_PEND;
+ set_bit(CONF_CONNECT_PEND, &chan->conf_state);
l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
sizeof(req), &req);
@@ -533,7 +683,7 @@
}
}
-void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err)
+static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err)
{
struct sock *sk;
struct l2cap_disconn_req req;
@@ -544,9 +694,9 @@
sk = chan->sk;
if (chan->mode == L2CAP_MODE_ERTM) {
- del_timer(&chan->retrans_timer);
- del_timer(&chan->monitor_timer);
- del_timer(&chan->ack_timer);
+ __clear_retrans_timer(chan);
+ __clear_monitor_timer(chan);
+ __clear_ack_timer(chan);
}
req.dcid = cpu_to_le16(chan->dcid);
@@ -554,7 +704,7 @@
l2cap_send_cmd(conn, l2cap_get_ident(conn),
L2CAP_DISCONN_REQ, sizeof(req), &req);
- sk->sk_state = BT_DISCONN;
+ l2cap_state_change(chan, BT_DISCONN);
sk->sk_err = err;
}
@@ -572,13 +722,12 @@
bh_lock_sock(sk);
- if (sk->sk_type != SOCK_SEQPACKET &&
- sk->sk_type != SOCK_STREAM) {
+ if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
bh_unlock_sock(sk);
continue;
}
- if (sk->sk_state == BT_CONNECT) {
+ if (chan->state == BT_CONNECT) {
struct l2cap_conn_req req;
if (!l2cap_check_security(chan) ||
@@ -587,14 +736,13 @@
continue;
}
- if (!l2cap_mode_supported(chan->mode,
- conn->feat_mask)
- && chan->conf_state &
- L2CAP_CONF_STATE2_DEVICE) {
- /* __l2cap_sock_close() calls list_del(chan)
+ if (!l2cap_mode_supported(chan->mode, conn->feat_mask)
+ && test_bit(CONF_STATE2_DEVICE,
+ &chan->conf_state)) {
+ /* l2cap_chan_close() calls list_del(chan)
* so release the lock */
read_unlock_bh(&conn->chan_lock);
- __l2cap_sock_close(sk, ECONNRESET);
+ l2cap_chan_close(chan, ECONNRESET);
read_lock_bh(&conn->chan_lock);
bh_unlock_sock(sk);
continue;
@@ -604,12 +752,12 @@
req.psm = chan->psm;
chan->ident = l2cap_get_ident(conn);
- chan->conf_state |= L2CAP_CONF_CONNECT_PEND;
+ set_bit(CONF_CONNECT_PEND, &chan->conf_state);
l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
sizeof(req), &req);
- } else if (sk->sk_state == BT_CONNECT2) {
+ } else if (chan->state == BT_CONNECT2) {
struct l2cap_conn_rsp rsp;
char buf[128];
rsp.scid = cpu_to_le16(chan->dcid);
@@ -623,7 +771,7 @@
parent->sk_data_ready(parent, 0);
} else {
- sk->sk_state = BT_CONFIG;
+ l2cap_state_change(chan, BT_CONFIG);
rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
}
@@ -635,13 +783,13 @@
l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
sizeof(rsp), &rsp);
- if (chan->conf_state & L2CAP_CONF_REQ_SENT ||
+ if (test_bit(CONF_REQ_SENT, &chan->conf_state) ||
rsp.result != L2CAP_CR_SUCCESS) {
bh_unlock_sock(sk);
continue;
}
- chan->conf_state |= L2CAP_CONF_REQ_SENT;
+ set_bit(CONF_REQ_SENT, &chan->conf_state);
l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
l2cap_build_conf_req(chan, buf), buf);
chan->num_conf_req++;
@@ -665,7 +813,7 @@
list_for_each_entry(c, &chan_list, global_l) {
struct sock *sk = c->sk;
- if (state && sk->sk_state != state)
+ if (state && c->state != state)
continue;
if (c->scid == cid) {
@@ -709,24 +857,16 @@
goto clean;
}
- sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP, GFP_ATOMIC);
- if (!sk)
+ chan = pchan->ops->new_connection(pchan->data);
+ if (!chan)
goto clean;
- chan = l2cap_chan_create(sk);
- if (!chan) {
- l2cap_sock_kill(sk);
- goto clean;
- }
-
- l2cap_pi(sk)->chan = chan;
+ sk = chan->sk;
write_lock_bh(&conn->chan_lock);
hci_conn_hold(conn->hcon);
- l2cap_sock_init(sk, parent);
-
bacpy(&bt_sk(sk)->src, conn->src);
bacpy(&bt_sk(sk)->dst, conn->dst);
@@ -734,9 +874,9 @@
__l2cap_chan_add(conn, chan);
- l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
+ __set_chan_timer(chan, sk->sk_sndtimeo);
- sk->sk_state = BT_CONNECTED;
+ l2cap_state_change(chan, BT_CONNECTED);
parent->sk_data_ready(parent, 0);
write_unlock_bh(&conn->chan_lock);
@@ -745,6 +885,23 @@
bh_unlock_sock(parent);
}
+static void l2cap_chan_ready(struct sock *sk)
+{
+ struct l2cap_chan *chan = l2cap_pi(sk)->chan;
+ struct sock *parent = bt_sk(sk)->parent;
+
+ BT_DBG("sk %p, parent %p", sk, parent);
+
+ chan->conf_state = 0;
+ __clear_chan_timer(chan);
+
+ l2cap_state_change(chan, BT_CONNECTED);
+ sk->sk_state_change(sk);
+
+ if (parent)
+ parent->sk_data_ready(parent, 0);
+}
+
static void l2cap_conn_ready(struct l2cap_conn *conn)
{
struct l2cap_chan *chan;
@@ -762,17 +919,15 @@
bh_lock_sock(sk);
if (conn->hcon->type == LE_LINK) {
- l2cap_sock_clear_timer(sk);
- sk->sk_state = BT_CONNECTED;
- sk->sk_state_change(sk);
- }
+ if (smp_conn_security(conn, chan->sec_level))
+ l2cap_chan_ready(sk);
- if (sk->sk_type != SOCK_SEQPACKET &&
- sk->sk_type != SOCK_STREAM) {
- l2cap_sock_clear_timer(sk);
- sk->sk_state = BT_CONNECTED;
+ } else if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
+ __clear_chan_timer(chan);
+ l2cap_state_change(chan, BT_CONNECTED);
sk->sk_state_change(sk);
- } else if (sk->sk_state == BT_CONNECT)
+
+ } else if (chan->state == BT_CONNECT)
l2cap_do_start(chan);
bh_unlock_sock(sk);
@@ -810,6 +965,45 @@
l2cap_conn_start(conn);
}
+static void l2cap_conn_del(struct hci_conn *hcon, int err)
+{
+ struct l2cap_conn *conn = hcon->l2cap_data;
+ struct l2cap_chan *chan, *l;
+ struct sock *sk;
+
+ if (!conn)
+ return;
+
+ BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
+
+ kfree_skb(conn->rx_skb);
+
+ /* Kill channels */
+ list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
+ sk = chan->sk;
+ bh_lock_sock(sk);
+ l2cap_chan_del(chan, err);
+ bh_unlock_sock(sk);
+ chan->ops->close(chan->data);
+ }
+
+ if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
+ del_timer_sync(&conn->info_timer);
+
+ if (test_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend))
+ del_timer(&conn->security_timer);
+
+ hcon->l2cap_data = NULL;
+ kfree(conn);
+}
+
+static void security_timeout(unsigned long arg)
+{
+ struct l2cap_conn *conn = (void *) arg;
+
+ l2cap_conn_del(conn->hcon, ETIMEDOUT);
+}
+
static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
{
struct l2cap_conn *conn = hcon->l2cap_data;
@@ -841,7 +1035,10 @@
INIT_LIST_HEAD(&conn->chan_l);
- if (hcon->type != LE_LINK)
+ if (hcon->type == LE_LINK)
+ setup_timer(&conn->security_timer, security_timeout,
+ (unsigned long) conn);
+ else
setup_timer(&conn->info_timer, l2cap_info_timeout,
(unsigned long) conn);
@@ -850,35 +1047,6 @@
return conn;
}
-static void l2cap_conn_del(struct hci_conn *hcon, int err)
-{
- struct l2cap_conn *conn = hcon->l2cap_data;
- struct l2cap_chan *chan, *l;
- struct sock *sk;
-
- if (!conn)
- return;
-
- BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
-
- kfree_skb(conn->rx_skb);
-
- /* Kill channels */
- list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
- sk = chan->sk;
- bh_lock_sock(sk);
- l2cap_chan_del(chan, err);
- bh_unlock_sock(sk);
- l2cap_sock_kill(sk);
- }
-
- if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
- del_timer_sync(&conn->info_timer);
-
- hcon->l2cap_data = NULL;
- kfree(conn);
-}
-
static inline void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
{
write_lock_bh(&conn->chan_lock);
@@ -900,7 +1068,7 @@
list_for_each_entry(c, &chan_list, global_l) {
struct sock *sk = c->sk;
- if (state && sk->sk_state != state)
+ if (state && c->state != state)
continue;
if (c->psm == psm) {
@@ -967,15 +1135,14 @@
l2cap_chan_add(conn, chan);
- sk->sk_state = BT_CONNECT;
- l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
+ l2cap_state_change(chan, BT_CONNECT);
+ __set_chan_timer(chan, sk->sk_sndtimeo);
if (hcon->state == BT_CONNECTED) {
- if (sk->sk_type != SOCK_SEQPACKET &&
- sk->sk_type != SOCK_STREAM) {
- l2cap_sock_clear_timer(sk);
+ if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
+ __clear_chan_timer(chan);
if (l2cap_check_security(chan))
- sk->sk_state = BT_CONNECTED;
+ l2cap_state_change(chan, BT_CONNECTED);
} else
l2cap_do_start(chan);
}
@@ -1035,7 +1202,7 @@
}
chan->retry_count++;
- __mod_monitor_timer();
+ __set_monitor_timer(chan);
l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
bh_unlock_sock(sk);
@@ -1050,9 +1217,9 @@
bh_lock_sock(sk);
chan->retry_count = 1;
- __mod_monitor_timer();
+ __set_monitor_timer(chan);
- chan->conn_state |= L2CAP_CONN_WAIT_F;
+ set_bit(CONN_WAIT_F, &chan->conn_state);
l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
bh_unlock_sock(sk);
@@ -1074,7 +1241,7 @@
}
if (!chan->unacked_frames)
- del_timer(&chan->retrans_timer);
+ __clear_retrans_timer(chan);
}
void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb)
@@ -1089,6 +1256,7 @@
else
flags = ACL_START;
+ bt_cb(skb)->force_active = chan->force_active;
hci_send_acl(hcon, skb, flags);
}
@@ -1142,10 +1310,8 @@
control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
control &= L2CAP_CTRL_SAR;
- if (chan->conn_state & L2CAP_CONN_SEND_FBIT) {
+ if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
control |= L2CAP_CTRL_FINAL;
- chan->conn_state &= ~L2CAP_CONN_SEND_FBIT;
- }
control |= (chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
| (tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
@@ -1163,11 +1329,10 @@
int l2cap_ertm_send(struct l2cap_chan *chan)
{
struct sk_buff *skb, *tx_skb;
- struct sock *sk = chan->sk;
u16 control, fcs;
int nsent = 0;
- if (sk->sk_state != BT_CONNECTED)
+ if (chan->state != BT_CONNECTED)
return -ENOTCONN;
while ((skb = chan->tx_send_head) && (!l2cap_tx_window_full(chan))) {
@@ -1185,10 +1350,9 @@
control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
control &= L2CAP_CTRL_SAR;
- if (chan->conn_state & L2CAP_CONN_SEND_FBIT) {
+ if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
control |= L2CAP_CTRL_FINAL;
- chan->conn_state &= ~L2CAP_CONN_SEND_FBIT;
- }
+
control |= (chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
| (chan->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
@@ -1201,7 +1365,7 @@
l2cap_do_send(chan, tx_skb);
- __mod_retrans_timer();
+ __set_retrans_timer(chan);
bt_cb(skb)->tx_seq = chan->next_tx_seq;
chan->next_tx_seq = (chan->next_tx_seq + 1) % 64;
@@ -1240,9 +1404,9 @@
control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
- if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
+ if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
control |= L2CAP_SUPER_RCV_NOT_READY;
- chan->conn_state |= L2CAP_CONN_RNR_SENT;
+ set_bit(CONN_RNR_SENT, &chan->conn_state);
l2cap_send_sframe(chan, control);
return;
}
@@ -1450,28 +1614,83 @@
return size;
}
-static void l2cap_chan_ready(struct sock *sk)
+int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
{
- struct sock *parent = bt_sk(sk)->parent;
- struct l2cap_chan *chan = l2cap_pi(sk)->chan;
+ struct sk_buff *skb;
+ u16 control;
+ int err;
- BT_DBG("sk %p, parent %p", sk, parent);
+ /* Connectionless channel */
+ if (chan->chan_type == L2CAP_CHAN_CONN_LESS) {
+ skb = l2cap_create_connless_pdu(chan, msg, len);
+ if (IS_ERR(skb))
+ return PTR_ERR(skb);
- chan->conf_state = 0;
- l2cap_sock_clear_timer(sk);
-
- if (!parent) {
- /* Outgoing channel.
- * Wake up socket sleeping on connect.
- */
- sk->sk_state = BT_CONNECTED;
- sk->sk_state_change(sk);
- } else {
- /* Incoming channel.
- * Wake up socket sleeping on accept.
- */
- parent->sk_data_ready(parent, 0);
+ l2cap_do_send(chan, skb);
+ return len;
}
+
+ switch (chan->mode) {
+ case L2CAP_MODE_BASIC:
+ /* Check outgoing MTU */
+ if (len > chan->omtu)
+ return -EMSGSIZE;
+
+ /* Create a basic PDU */
+ skb = l2cap_create_basic_pdu(chan, msg, len);
+ if (IS_ERR(skb))
+ return PTR_ERR(skb);
+
+ l2cap_do_send(chan, skb);
+ err = len;
+ break;
+
+ case L2CAP_MODE_ERTM:
+ case L2CAP_MODE_STREAMING:
+ /* Entire SDU fits into one PDU */
+ if (len <= chan->remote_mps) {
+ control = L2CAP_SDU_UNSEGMENTED;
+ skb = l2cap_create_iframe_pdu(chan, msg, len, control,
+ 0);
+ if (IS_ERR(skb))
+ return PTR_ERR(skb);
+
+ __skb_queue_tail(&chan->tx_q, skb);
+
+ if (chan->tx_send_head == NULL)
+ chan->tx_send_head = skb;
+
+ } else {
+ /* Segment SDU into multiples PDUs */
+ err = l2cap_sar_segment_sdu(chan, msg, len);
+ if (err < 0)
+ return err;
+ }
+
+ if (chan->mode == L2CAP_MODE_STREAMING) {
+ l2cap_streaming_send(chan);
+ err = len;
+ break;
+ }
+
+ if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
+ test_bit(CONN_WAIT_F, &chan->conn_state)) {
+ err = len;
+ break;
+ }
+
+ err = l2cap_ertm_send(chan);
+ if (err >= 0)
+ err = len;
+
+ break;
+
+ default:
+ BT_DBG("bad state %1.1x", chan->mode);
+ err = -EBADFD;
+ }
+
+ return err;
}
/* Copy frame to all raw sockets on that connection */
@@ -1485,7 +1704,7 @@
read_lock(&conn->chan_lock);
list_for_each_entry(chan, &conn->chan_l, list) {
struct sock *sk = chan->sk;
- if (sk->sk_type != SOCK_RAW)
+ if (chan->chan_type != L2CAP_CHAN_RAW)
continue;
/* Don't send frame to the socket it came from */
@@ -1495,7 +1714,7 @@
if (!nskb)
continue;
- if (sock_queue_rcv_skb(sk, nskb))
+ if (chan->ops->recv(chan->data, nskb))
kfree_skb(nskb);
}
read_unlock(&conn->chan_lock);
@@ -1690,7 +1909,7 @@
switch (chan->mode) {
case L2CAP_MODE_STREAMING:
case L2CAP_MODE_ERTM:
- if (chan->conf_state & L2CAP_CONF_STATE2_DEVICE)
+ if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state))
break;
/* fall through */
@@ -1737,7 +1956,7 @@
break;
if (chan->fcs == L2CAP_FCS_NONE ||
- chan->conf_state & L2CAP_CONF_NO_FCS_RECV) {
+ test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
chan->fcs = L2CAP_FCS_NONE;
l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
}
@@ -1760,7 +1979,7 @@
break;
if (chan->fcs == L2CAP_FCS_NONE ||
- chan->conf_state & L2CAP_CONF_NO_FCS_RECV) {
+ test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
chan->fcs = L2CAP_FCS_NONE;
l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
}
@@ -1812,7 +2031,7 @@
case L2CAP_CONF_FCS:
if (val == L2CAP_FCS_NONE)
- chan->conf_state |= L2CAP_CONF_NO_FCS_RECV;
+ set_bit(CONF_NO_FCS_RECV, &chan->conf_state);
break;
@@ -1832,7 +2051,7 @@
switch (chan->mode) {
case L2CAP_MODE_STREAMING:
case L2CAP_MODE_ERTM:
- if (!(chan->conf_state & L2CAP_CONF_STATE2_DEVICE)) {
+ if (!test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) {
chan->mode = l2cap_select_mode(rfc.mode,
chan->conn->feat_mask);
break;
@@ -1865,14 +2084,14 @@
result = L2CAP_CONF_UNACCEPT;
else {
chan->omtu = mtu;
- chan->conf_state |= L2CAP_CONF_MTU_DONE;
+ set_bit(CONF_MTU_DONE, &chan->conf_state);
}
l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu);
switch (rfc.mode) {
case L2CAP_MODE_BASIC:
chan->fcs = L2CAP_FCS_NONE;
- chan->conf_state |= L2CAP_CONF_MODE_DONE;
+ set_bit(CONF_MODE_DONE, &chan->conf_state);
break;
case L2CAP_MODE_ERTM:
@@ -1889,7 +2108,7 @@
rfc.monitor_timeout =
le16_to_cpu(L2CAP_DEFAULT_MONITOR_TO);
- chan->conf_state |= L2CAP_CONF_MODE_DONE;
+ set_bit(CONF_MODE_DONE, &chan->conf_state);
l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
sizeof(rfc), (unsigned long) &rfc);
@@ -1902,7 +2121,7 @@
chan->remote_mps = le16_to_cpu(rfc.max_pdu_size);
- chan->conf_state |= L2CAP_CONF_MODE_DONE;
+ set_bit(CONF_MODE_DONE, &chan->conf_state);
l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
sizeof(rfc), (unsigned long) &rfc);
@@ -1917,7 +2136,7 @@
}
if (result == L2CAP_CONF_SUCCESS)
- chan->conf_state |= L2CAP_CONF_OUTPUT_DONE;
+ set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
}
rsp->scid = cpu_to_le16(chan->dcid);
rsp->result = cpu_to_le16(result);
@@ -1959,7 +2178,7 @@
if (olen == sizeof(rfc))
memcpy(&rfc, (void *)val, olen);
- if ((chan->conf_state & L2CAP_CONF_STATE2_DEVICE) &&
+ if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state) &&
rfc.mode != chan->mode)
return -ECONNREFUSED;
@@ -2021,10 +2240,9 @@
l2cap_send_cmd(conn, chan->ident,
L2CAP_CONN_RSP, sizeof(rsp), &rsp);
- if (chan->conf_state & L2CAP_CONF_REQ_SENT)
+ if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
return;
- chan->conf_state |= L2CAP_CONF_REQ_SENT;
l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
l2cap_build_conf_req(chan, buf), buf);
chan->num_conf_req++;
@@ -2124,17 +2342,11 @@
goto response;
}
- sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP, GFP_ATOMIC);
- if (!sk)
+ chan = pchan->ops->new_connection(pchan->data);
+ if (!chan)
goto response;
- chan = l2cap_chan_create(sk);
- if (!chan) {
- l2cap_sock_kill(sk);
- goto response;
- }
-
- l2cap_pi(sk)->chan = chan;
+ sk = chan->sk;
write_lock_bh(&conn->chan_lock);
@@ -2142,13 +2354,12 @@
if (__l2cap_get_chan_by_dcid(conn, scid)) {
write_unlock_bh(&conn->chan_lock);
sock_set_flag(sk, SOCK_ZAPPED);
- l2cap_sock_kill(sk);
+ chan->ops->close(chan->data);
goto response;
}
hci_conn_hold(conn->hcon);
- l2cap_sock_init(sk, parent);
bacpy(&bt_sk(sk)->src, conn->src);
bacpy(&bt_sk(sk)->dst, conn->dst);
chan->psm = psm;
@@ -2160,29 +2371,29 @@
dcid = chan->scid;
- l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
+ __set_chan_timer(chan, sk->sk_sndtimeo);
chan->ident = cmd->ident;
if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
if (l2cap_check_security(chan)) {
if (bt_sk(sk)->defer_setup) {
- sk->sk_state = BT_CONNECT2;
+ l2cap_state_change(chan, BT_CONNECT2);
result = L2CAP_CR_PEND;
status = L2CAP_CS_AUTHOR_PEND;
parent->sk_data_ready(parent, 0);
} else {
- sk->sk_state = BT_CONFIG;
+ l2cap_state_change(chan, BT_CONFIG);
result = L2CAP_CR_SUCCESS;
status = L2CAP_CS_NO_INFO;
}
} else {
- sk->sk_state = BT_CONNECT2;
+ l2cap_state_change(chan, BT_CONNECT2);
result = L2CAP_CR_PEND;
status = L2CAP_CS_AUTHEN_PEND;
}
} else {
- sk->sk_state = BT_CONNECT2;
+ l2cap_state_change(chan, BT_CONNECT2);
result = L2CAP_CR_PEND;
status = L2CAP_CS_NO_INFO;
}
@@ -2213,10 +2424,10 @@
L2CAP_INFO_REQ, sizeof(info), &info);
}
- if (chan && !(chan->conf_state & L2CAP_CONF_REQ_SENT) &&
+ if (chan && !test_bit(CONF_REQ_SENT, &chan->conf_state) &&
result == L2CAP_CR_SUCCESS) {
u8 buf[128];
- chan->conf_state |= L2CAP_CONF_REQ_SENT;
+ set_bit(CONF_REQ_SENT, &chan->conf_state);
l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
l2cap_build_conf_req(chan, buf), buf);
chan->num_conf_req++;
@@ -2254,31 +2465,29 @@
switch (result) {
case L2CAP_CR_SUCCESS:
- sk->sk_state = BT_CONFIG;
+ l2cap_state_change(chan, BT_CONFIG);
chan->ident = 0;
chan->dcid = dcid;
- chan->conf_state &= ~L2CAP_CONF_CONNECT_PEND;
+ clear_bit(CONF_CONNECT_PEND, &chan->conf_state);
- if (chan->conf_state & L2CAP_CONF_REQ_SENT)
+ if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
break;
- chan->conf_state |= L2CAP_CONF_REQ_SENT;
-
l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
l2cap_build_conf_req(chan, req), req);
chan->num_conf_req++;
break;
case L2CAP_CR_PEND:
- chan->conf_state |= L2CAP_CONF_CONNECT_PEND;
+ set_bit(CONF_CONNECT_PEND, &chan->conf_state);
break;
default:
/* don't delete l2cap channel if sk is owned by user */
if (sock_owned_by_user(sk)) {
- sk->sk_state = BT_DISCONN;
- l2cap_sock_clear_timer(sk);
- l2cap_sock_set_timer(sk, HZ / 5);
+ l2cap_state_change(chan, BT_DISCONN);
+ __clear_chan_timer(chan);
+ __set_chan_timer(chan, HZ / 5);
break;
}
@@ -2292,14 +2501,12 @@
static inline void set_default_fcs(struct l2cap_chan *chan)
{
- struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
-
/* FCS is enabled only in ERTM or streaming mode, if one or both
* sides request it.
*/
if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING)
chan->fcs = L2CAP_FCS_NONE;
- else if (!(pi->chan->conf_state & L2CAP_CONF_NO_FCS_RECV))
+ else if (!test_bit(CONF_NO_FCS_RECV, &chan->conf_state))
chan->fcs = L2CAP_FCS_CRC16;
}
@@ -2323,7 +2530,7 @@
sk = chan->sk;
- if (sk->sk_state != BT_CONFIG) {
+ if (chan->state != BT_CONFIG) {
struct l2cap_cmd_rej rej;
rej.reason = cpu_to_le16(0x0002);
@@ -2366,13 +2573,13 @@
/* Reset config buffer. */
chan->conf_len = 0;
- if (!(chan->conf_state & L2CAP_CONF_OUTPUT_DONE))
+ if (!test_bit(CONF_OUTPUT_DONE, &chan->conf_state))
goto unlock;
- if (chan->conf_state & L2CAP_CONF_INPUT_DONE) {
+ if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) {
set_default_fcs(chan);
- sk->sk_state = BT_CONNECTED;
+ l2cap_state_change(chan, BT_CONNECTED);
chan->next_tx_seq = 0;
chan->expected_tx_seq = 0;
@@ -2384,9 +2591,8 @@
goto unlock;
}
- if (!(chan->conf_state & L2CAP_CONF_REQ_SENT)) {
+ if (!test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) {
u8 buf[64];
- chan->conf_state |= L2CAP_CONF_REQ_SENT;
l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
l2cap_build_conf_req(chan, buf), buf);
chan->num_conf_req++;
@@ -2451,7 +2657,7 @@
default:
sk->sk_err = ECONNRESET;
- l2cap_sock_set_timer(sk, HZ * 5);
+ __set_chan_timer(chan, HZ * 5);
l2cap_send_disconn_req(conn, chan, ECONNRESET);
goto done;
}
@@ -2459,12 +2665,12 @@
if (flags & 0x01)
goto done;
- chan->conf_state |= L2CAP_CONF_INPUT_DONE;
+ set_bit(CONF_INPUT_DONE, &chan->conf_state);
- if (chan->conf_state & L2CAP_CONF_OUTPUT_DONE) {
+ if (test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) {
set_default_fcs(chan);
- sk->sk_state = BT_CONNECTED;
+ l2cap_state_change(chan, BT_CONNECTED);
chan->next_tx_seq = 0;
chan->expected_tx_seq = 0;
skb_queue_head_init(&chan->tx_q);
@@ -2506,9 +2712,9 @@
/* don't delete l2cap channel if sk is owned by user */
if (sock_owned_by_user(sk)) {
- sk->sk_state = BT_DISCONN;
- l2cap_sock_clear_timer(sk);
- l2cap_sock_set_timer(sk, HZ / 5);
+ l2cap_state_change(chan, BT_DISCONN);
+ __clear_chan_timer(chan);
+ __set_chan_timer(chan, HZ / 5);
bh_unlock_sock(sk);
return 0;
}
@@ -2516,7 +2722,7 @@
l2cap_chan_del(chan, ECONNRESET);
bh_unlock_sock(sk);
- l2cap_sock_kill(sk);
+ chan->ops->close(chan->data);
return 0;
}
@@ -2540,9 +2746,9 @@
/* don't delete l2cap channel if sk is owned by user */
if (sock_owned_by_user(sk)) {
- sk->sk_state = BT_DISCONN;
- l2cap_sock_clear_timer(sk);
- l2cap_sock_set_timer(sk, HZ / 5);
+ l2cap_state_change(chan,BT_DISCONN);
+ __clear_chan_timer(chan);
+ __set_chan_timer(chan, HZ / 5);
bh_unlock_sock(sk);
return 0;
}
@@ -2550,7 +2756,7 @@
l2cap_chan_del(chan, 0);
bh_unlock_sock(sk);
- l2cap_sock_kill(sk);
+ chan->ops->close(chan->data);
return 0;
}
@@ -2858,18 +3064,18 @@
control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
- if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
+ if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
control |= L2CAP_SUPER_RCV_NOT_READY;
l2cap_send_sframe(chan, control);
- chan->conn_state |= L2CAP_CONN_RNR_SENT;
+ set_bit(CONN_RNR_SENT, &chan->conn_state);
}
- if (chan->conn_state & L2CAP_CONN_REMOTE_BUSY)
+ if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
l2cap_retransmit_frames(chan);
l2cap_ertm_send(chan);
- if (!(chan->conn_state & L2CAP_CONN_LOCAL_BUSY) &&
+ if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state) &&
chan->frames_sent == 0) {
control |= L2CAP_SUPER_RCV_READY;
l2cap_send_sframe(chan, control);
@@ -2925,17 +3131,13 @@
switch (control & L2CAP_CTRL_SAR) {
case L2CAP_SDU_UNSEGMENTED:
- if (chan->conn_state & L2CAP_CONN_SAR_SDU)
+ if (test_bit(CONN_SAR_SDU, &chan->conn_state))
goto drop;
- err = sock_queue_rcv_skb(chan->sk, skb);
- if (!err)
- return err;
-
- break;
+ return chan->ops->recv(chan->data, skb);
case L2CAP_SDU_START:
- if (chan->conn_state & L2CAP_CONN_SAR_SDU)
+ if (test_bit(CONN_SAR_SDU, &chan->conn_state))
goto drop;
chan->sdu_len = get_unaligned_le16(skb->data);
@@ -2954,12 +3156,12 @@
memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
- chan->conn_state |= L2CAP_CONN_SAR_SDU;
+ set_bit(CONN_SAR_SDU, &chan->conn_state);
chan->partial_sdu_len = skb->len;
break;
case L2CAP_SDU_CONTINUE:
- if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
+ if (!test_bit(CONN_SAR_SDU, &chan->conn_state))
goto disconnect;
if (!chan->sdu)
@@ -2974,13 +3176,13 @@
break;
case L2CAP_SDU_END:
- if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
+ if (!test_bit(CONN_SAR_SDU, &chan->conn_state))
goto disconnect;
if (!chan->sdu)
goto disconnect;
- if (!(chan->conn_state & L2CAP_CONN_SAR_RETRY)) {
+ if (!test_bit(CONN_SAR_RETRY, &chan->conn_state)) {
chan->partial_sdu_len += skb->len;
if (chan->partial_sdu_len > chan->imtu)
@@ -2994,19 +3196,19 @@
_skb = skb_clone(chan->sdu, GFP_ATOMIC);
if (!_skb) {
- chan->conn_state |= L2CAP_CONN_SAR_RETRY;
+ set_bit(CONN_SAR_RETRY, &chan->conn_state);
return -ENOMEM;
}
- err = sock_queue_rcv_skb(chan->sk, _skb);
+ err = chan->ops->recv(chan->data, _skb);
if (err < 0) {
kfree_skb(_skb);
- chan->conn_state |= L2CAP_CONN_SAR_RETRY;
+ set_bit(CONN_SAR_RETRY, &chan->conn_state);
return err;
}
- chan->conn_state &= ~L2CAP_CONN_SAR_RETRY;
- chan->conn_state &= ~L2CAP_CONN_SAR_SDU;
+ clear_bit(CONN_SAR_RETRY, &chan->conn_state);
+ clear_bit(CONN_SAR_SDU, &chan->conn_state);
kfree_skb(chan->sdu);
break;
@@ -3042,7 +3244,7 @@
chan->buffer_seq = (chan->buffer_seq + 1) % 64;
}
- if (!(chan->conn_state & L2CAP_CONN_RNR_SENT))
+ if (!test_bit(CONN_RNR_SENT, &chan->conn_state))
goto done;
control = chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
@@ -3050,14 +3252,14 @@
l2cap_send_sframe(chan, control);
chan->retry_count = 1;
- del_timer(&chan->retrans_timer);
- __mod_monitor_timer();
+ __clear_retrans_timer(chan);
+ __set_monitor_timer(chan);
- chan->conn_state |= L2CAP_CONN_WAIT_F;
+ set_bit(CONN_WAIT_F, &chan->conn_state);
done:
- chan->conn_state &= ~L2CAP_CONN_LOCAL_BUSY;
- chan->conn_state &= ~L2CAP_CONN_RNR_SENT;
+ clear_bit(CONN_LOCAL_BUSY, &chan->conn_state);
+ clear_bit(CONN_RNR_SENT, &chan->conn_state);
BT_DBG("chan %p, Exit local busy", chan);
@@ -3115,7 +3317,7 @@
{
int sctrl, err;
- if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
+ if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
__skb_queue_tail(&chan->busy_q, skb);
return l2cap_try_push_rx_skb(chan);
@@ -3132,7 +3334,7 @@
/* Busy Condition */
BT_DBG("chan %p, Enter local busy", chan);
- chan->conn_state |= L2CAP_CONN_LOCAL_BUSY;
+ set_bit(CONN_LOCAL_BUSY, &chan->conn_state);
bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
__skb_queue_tail(&chan->busy_q, skb);
@@ -3140,9 +3342,9 @@
sctrl |= L2CAP_SUPER_RCV_NOT_READY;
l2cap_send_sframe(chan, sctrl);
- chan->conn_state |= L2CAP_CONN_RNR_SENT;
+ set_bit(CONN_RNR_SENT, &chan->conn_state);
- del_timer(&chan->ack_timer);
+ __clear_ack_timer(chan);
queue_work(_busy_wq, &chan->busy_work);
@@ -3161,19 +3363,19 @@
switch (control & L2CAP_CTRL_SAR) {
case L2CAP_SDU_UNSEGMENTED:
- if (chan->conn_state & L2CAP_CONN_SAR_SDU) {
+ if (test_bit(CONN_SAR_SDU, &chan->conn_state)) {
kfree_skb(chan->sdu);
break;
}
- err = sock_queue_rcv_skb(chan->sk, skb);
+ err = chan->ops->recv(chan->data, skb);
if (!err)
return 0;
break;
case L2CAP_SDU_START:
- if (chan->conn_state & L2CAP_CONN_SAR_SDU) {
+ if (test_bit(CONN_SAR_SDU, &chan->conn_state)) {
kfree_skb(chan->sdu);
break;
}
@@ -3194,13 +3396,13 @@
memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
- chan->conn_state |= L2CAP_CONN_SAR_SDU;
+ set_bit(CONN_SAR_SDU, &chan->conn_state);
chan->partial_sdu_len = skb->len;
err = 0;
break;
case L2CAP_SDU_CONTINUE:
- if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
+ if (!test_bit(CONN_SAR_SDU, &chan->conn_state))
break;
memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
@@ -3214,12 +3416,12 @@
break;
case L2CAP_SDU_END:
- if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
+ if (!test_bit(CONN_SAR_SDU, &chan->conn_state))
break;
memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
- chan->conn_state &= ~L2CAP_CONN_SAR_SDU;
+ clear_bit(CONN_SAR_SDU, &chan->conn_state);
chan->partial_sdu_len += skb->len;
if (chan->partial_sdu_len > chan->imtu)
@@ -3227,7 +3429,7 @@
if (chan->partial_sdu_len == chan->sdu_len) {
_skb = skb_clone(chan->sdu, GFP_ATOMIC);
- err = sock_queue_rcv_skb(chan->sk, _skb);
+ err = chan->ops->recv(chan->data, _skb);
if (err < 0)
kfree_skb(_skb);
}
@@ -3310,11 +3512,11 @@
tx_seq, rx_control);
if (L2CAP_CTRL_FINAL & rx_control &&
- chan->conn_state & L2CAP_CONN_WAIT_F) {
- del_timer(&chan->monitor_timer);
+ test_bit(CONN_WAIT_F, &chan->conn_state)) {
+ __clear_monitor_timer(chan);
if (chan->unacked_frames > 0)
- __mod_retrans_timer();
- chan->conn_state &= ~L2CAP_CONN_WAIT_F;
+ __set_retrans_timer(chan);
+ clear_bit(CONN_WAIT_F, &chan->conn_state);
}
chan->expected_ack_seq = req_seq;
@@ -3333,10 +3535,10 @@
goto drop;
}
- if (chan->conn_state == L2CAP_CONN_LOCAL_BUSY)
+ if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state))
goto drop;
- if (chan->conn_state & L2CAP_CONN_SREJ_SENT) {
+ if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
struct srej_list *first;
first = list_first_entry(&chan->srej_l,
@@ -3350,7 +3552,7 @@
if (list_empty(&chan->srej_l)) {
chan->buffer_seq = chan->buffer_seq_srej;
- chan->conn_state &= ~L2CAP_CONN_SREJ_SENT;
+ clear_bit(CONN_SREJ_SENT, &chan->conn_state);
l2cap_send_ack(chan);
BT_DBG("chan %p, Exit SREJ_SENT", chan);
}
@@ -3379,7 +3581,7 @@
if (tx_seq_offset < expected_tx_seq_offset)
goto drop;
- chan->conn_state |= L2CAP_CONN_SREJ_SENT;
+ set_bit(CONN_SREJ_SENT, &chan->conn_state);
BT_DBG("chan %p, Enter SREJ", chan);
@@ -3390,18 +3592,18 @@
__skb_queue_head_init(&chan->busy_q);
l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
- chan->conn_state |= L2CAP_CONN_SEND_PBIT;
+ set_bit(CONN_SEND_PBIT, &chan->conn_state);
l2cap_send_srejframe(chan, tx_seq);
- del_timer(&chan->ack_timer);
+ __clear_ack_timer(chan);
}
return 0;
expected:
chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
- if (chan->conn_state & L2CAP_CONN_SREJ_SENT) {
+ if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
bt_cb(skb)->tx_seq = tx_seq;
bt_cb(skb)->sar = sar;
__skb_queue_tail(&chan->srej_q, skb);
@@ -3413,13 +3615,11 @@
return 0;
if (rx_control & L2CAP_CTRL_FINAL) {
- if (chan->conn_state & L2CAP_CONN_REJ_ACT)
- chan->conn_state &= ~L2CAP_CONN_REJ_ACT;
- else
+ if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
l2cap_retransmit_frames(chan);
}
- __mod_ack_timer();
+ __set_ack_timer(chan);
chan->num_acked = (chan->num_acked + 1) % num_to_ack;
if (chan->num_acked == num_to_ack - 1)
@@ -3441,33 +3641,31 @@
l2cap_drop_acked_frames(chan);
if (rx_control & L2CAP_CTRL_POLL) {
- chan->conn_state |= L2CAP_CONN_SEND_FBIT;
- if (chan->conn_state & L2CAP_CONN_SREJ_SENT) {
- if ((chan->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
+ set_bit(CONN_SEND_FBIT, &chan->conn_state);
+ if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
+ if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
(chan->unacked_frames > 0))
- __mod_retrans_timer();
+ __set_retrans_timer(chan);
- chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
+ clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
l2cap_send_srejtail(chan);
} else {
l2cap_send_i_or_rr_or_rnr(chan);
}
} else if (rx_control & L2CAP_CTRL_FINAL) {
- chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
+ clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
- if (chan->conn_state & L2CAP_CONN_REJ_ACT)
- chan->conn_state &= ~L2CAP_CONN_REJ_ACT;
- else
+ if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
l2cap_retransmit_frames(chan);
} else {
- if ((chan->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
+ if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
(chan->unacked_frames > 0))
- __mod_retrans_timer();
+ __set_retrans_timer(chan);
- chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
- if (chan->conn_state & L2CAP_CONN_SREJ_SENT)
+ clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
+ if (test_bit(CONN_SREJ_SENT, &chan->conn_state))
l2cap_send_ack(chan);
else
l2cap_ertm_send(chan);
@@ -3480,21 +3678,19 @@
BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
- chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
+ clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
chan->expected_ack_seq = tx_seq;
l2cap_drop_acked_frames(chan);
if (rx_control & L2CAP_CTRL_FINAL) {
- if (chan->conn_state & L2CAP_CONN_REJ_ACT)
- chan->conn_state &= ~L2CAP_CONN_REJ_ACT;
- else
+ if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
l2cap_retransmit_frames(chan);
} else {
l2cap_retransmit_frames(chan);
- if (chan->conn_state & L2CAP_CONN_WAIT_F)
- chan->conn_state |= L2CAP_CONN_REJ_ACT;
+ if (test_bit(CONN_WAIT_F, &chan->conn_state))
+ set_bit(CONN_REJ_ACT, &chan->conn_state);
}
}
static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u16 rx_control)
@@ -3503,32 +3699,32 @@
BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
- chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
+ clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
if (rx_control & L2CAP_CTRL_POLL) {
chan->expected_ack_seq = tx_seq;
l2cap_drop_acked_frames(chan);
- chan->conn_state |= L2CAP_CONN_SEND_FBIT;
+ set_bit(CONN_SEND_FBIT, &chan->conn_state);
l2cap_retransmit_one_frame(chan, tx_seq);
l2cap_ertm_send(chan);
- if (chan->conn_state & L2CAP_CONN_WAIT_F) {
+ if (test_bit(CONN_WAIT_F, &chan->conn_state)) {
chan->srej_save_reqseq = tx_seq;
- chan->conn_state |= L2CAP_CONN_SREJ_ACT;
+ set_bit(CONN_SREJ_ACT, &chan->conn_state);
}
} else if (rx_control & L2CAP_CTRL_FINAL) {
- if ((chan->conn_state & L2CAP_CONN_SREJ_ACT) &&
+ if (test_bit(CONN_SREJ_ACT, &chan->conn_state) &&
chan->srej_save_reqseq == tx_seq)
- chan->conn_state &= ~L2CAP_CONN_SREJ_ACT;
+ clear_bit(CONN_SREJ_ACT, &chan->conn_state);
else
l2cap_retransmit_one_frame(chan, tx_seq);
} else {
l2cap_retransmit_one_frame(chan, tx_seq);
- if (chan->conn_state & L2CAP_CONN_WAIT_F) {
+ if (test_bit(CONN_WAIT_F, &chan->conn_state)) {
chan->srej_save_reqseq = tx_seq;
- chan->conn_state |= L2CAP_CONN_SREJ_ACT;
+ set_bit(CONN_SREJ_ACT, &chan->conn_state);
}
}
}
@@ -3539,15 +3735,15 @@
BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
- chan->conn_state |= L2CAP_CONN_REMOTE_BUSY;
+ set_bit(CONN_REMOTE_BUSY, &chan->conn_state);
chan->expected_ack_seq = tx_seq;
l2cap_drop_acked_frames(chan);
if (rx_control & L2CAP_CTRL_POLL)
- chan->conn_state |= L2CAP_CONN_SEND_FBIT;
+ set_bit(CONN_SEND_FBIT, &chan->conn_state);
- if (!(chan->conn_state & L2CAP_CONN_SREJ_SENT)) {
- del_timer(&chan->retrans_timer);
+ if (!test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
+ __clear_retrans_timer(chan);
if (rx_control & L2CAP_CTRL_POLL)
l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_FINAL);
return;
@@ -3564,11 +3760,11 @@
BT_DBG("chan %p rx_control 0x%4.4x len %d", chan, rx_control, skb->len);
if (L2CAP_CTRL_FINAL & rx_control &&
- chan->conn_state & L2CAP_CONN_WAIT_F) {
- del_timer(&chan->monitor_timer);
+ test_bit(CONN_WAIT_F, &chan->conn_state)) {
+ __clear_monitor_timer(chan);
if (chan->unacked_frames > 0)
- __mod_retrans_timer();
- chan->conn_state &= ~L2CAP_CONN_WAIT_F;
+ __set_retrans_timer(chan);
+ clear_bit(CONN_WAIT_F, &chan->conn_state);
}
switch (rx_control & L2CAP_CTRL_SUPERVISE) {
@@ -3667,7 +3863,6 @@
{
struct l2cap_chan *chan;
struct sock *sk = NULL;
- struct l2cap_pinfo *pi;
u16 control;
u8 tx_seq;
int len;
@@ -3679,11 +3874,10 @@
}
sk = chan->sk;
- pi = l2cap_pi(sk);
BT_DBG("chan %p, len %d", chan, skb->len);
- if (sk->sk_state != BT_CONNECTED)
+ if (chan->state != BT_CONNECTED)
goto drop;
switch (chan->mode) {
@@ -3696,7 +3890,7 @@
if (chan->imtu < skb->len)
goto drop;
- if (!sock_queue_rcv_skb(sk, skb))
+ if (!chan->ops->recv(chan->data, skb))
goto done;
break;
@@ -3768,13 +3962,13 @@
BT_DBG("sk %p, len %d", sk, skb->len);
- if (sk->sk_state != BT_BOUND && sk->sk_state != BT_CONNECTED)
+ if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
goto drop;
- if (l2cap_pi(sk)->chan->imtu < skb->len)
+ if (chan->imtu < skb->len)
goto drop;
- if (!sock_queue_rcv_skb(sk, skb))
+ if (!chan->ops->recv(chan->data, skb))
goto done;
drop:
@@ -3801,13 +3995,13 @@
BT_DBG("sk %p, len %d", sk, skb->len);
- if (sk->sk_state != BT_BOUND && sk->sk_state != BT_CONNECTED)
+ if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
goto drop;
- if (l2cap_pi(sk)->chan->imtu < skb->len)
+ if (chan->imtu < skb->len)
goto drop;
- if (!sock_queue_rcv_skb(sk, skb))
+ if (!chan->ops->recv(chan->data, skb))
goto done;
drop:
@@ -3852,6 +4046,11 @@
l2cap_att_channel(conn, cid, skb);
break;
+ case L2CAP_CID_SMP:
+ if (smp_sig_channel(conn, skb))
+ l2cap_conn_del(conn->hcon, EACCES);
+ break;
+
default:
l2cap_data_channel(conn, cid, skb);
break;
@@ -3875,7 +4074,7 @@
list_for_each_entry(c, &chan_list, global_l) {
struct sock *sk = c->sk;
- if (sk->sk_state != BT_LISTEN)
+ if (c->state != BT_LISTEN)
continue;
if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
@@ -3919,7 +4118,7 @@
BT_DBG("hcon %p", hcon);
- if (hcon->type != ACL_LINK || !conn)
+ if ((hcon->type != ACL_LINK && hcon->type != LE_LINK) || !conn)
return 0x13;
return conn->disc_reason;
@@ -3939,20 +4138,18 @@
static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt)
{
- struct sock *sk = chan->sk;
-
- if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM)
+ if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED)
return;
if (encrypt == 0x00) {
if (chan->sec_level == BT_SECURITY_MEDIUM) {
- l2cap_sock_clear_timer(sk);
- l2cap_sock_set_timer(sk, HZ * 5);
+ __clear_chan_timer(chan);
+ __set_chan_timer(chan, HZ * 5);
} else if (chan->sec_level == BT_SECURITY_HIGH)
- __l2cap_sock_close(sk, ECONNREFUSED);
+ l2cap_chan_close(chan, ECONNREFUSED);
} else {
if (chan->sec_level == BT_SECURITY_MEDIUM)
- l2cap_sock_clear_timer(sk);
+ __clear_chan_timer(chan);
}
}
@@ -3973,34 +4170,47 @@
bh_lock_sock(sk);
- if (chan->conf_state & L2CAP_CONF_CONNECT_PEND) {
+ BT_DBG("chan->scid %d", chan->scid);
+
+ if (chan->scid == L2CAP_CID_LE_DATA) {
+ if (!status && encrypt) {
+ chan->sec_level = hcon->sec_level;
+ del_timer(&conn->security_timer);
+ l2cap_chan_ready(sk);
+ }
+
bh_unlock_sock(sk);
continue;
}
- if (!status && (sk->sk_state == BT_CONNECTED ||
- sk->sk_state == BT_CONFIG)) {
+ if (test_bit(CONF_CONNECT_PEND, &chan->conf_state)) {
+ bh_unlock_sock(sk);
+ continue;
+ }
+
+ if (!status && (chan->state == BT_CONNECTED ||
+ chan->state == BT_CONFIG)) {
l2cap_check_encryption(chan, encrypt);
bh_unlock_sock(sk);
continue;
}
- if (sk->sk_state == BT_CONNECT) {
+ if (chan->state == BT_CONNECT) {
if (!status) {
struct l2cap_conn_req req;
req.scid = cpu_to_le16(chan->scid);
req.psm = chan->psm;
chan->ident = l2cap_get_ident(conn);
- chan->conf_state |= L2CAP_CONF_CONNECT_PEND;
+ set_bit(CONF_CONNECT_PEND, &chan->conf_state);
l2cap_send_cmd(conn, chan->ident,
L2CAP_CONN_REQ, sizeof(req), &req);
} else {
- l2cap_sock_clear_timer(sk);
- l2cap_sock_set_timer(sk, HZ / 10);
+ __clear_chan_timer(chan);
+ __set_chan_timer(chan, HZ / 10);
}
- } else if (sk->sk_state == BT_CONNECT2) {
+ } else if (chan->state == BT_CONNECT2) {
struct l2cap_conn_rsp rsp;
__u16 res, stat;
@@ -4011,13 +4221,13 @@
stat = L2CAP_CS_AUTHOR_PEND;
parent->sk_data_ready(parent, 0);
} else {
- sk->sk_state = BT_CONFIG;
+ l2cap_state_change(chan, BT_CONFIG);
res = L2CAP_CR_SUCCESS;
stat = L2CAP_CS_NO_INFO;
}
} else {
- sk->sk_state = BT_DISCONN;
- l2cap_sock_set_timer(sk, HZ / 10);
+ l2cap_state_change(chan, BT_DISCONN);
+ __set_chan_timer(chan, HZ / 10);
res = L2CAP_CR_SEC_BLOCK;
stat = L2CAP_CS_NO_INFO;
}
@@ -4161,10 +4371,10 @@
seq_printf(f, "%s %s %d %d 0x%4.4x 0x%4.4x %d %d %d %d\n",
batostr(&bt_sk(sk)->src),
batostr(&bt_sk(sk)->dst),
- sk->sk_state, __le16_to_cpu(c->psm),
+ c->state, __le16_to_cpu(c->psm),
c->scid, c->dcid, c->imtu, c->omtu,
c->sec_level, c->mode);
- }
+}
read_unlock_bh(&chan_list_lock);
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index 8248303..39082d4 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -29,54 +29,11 @@
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
#include <net/bluetooth/l2cap.h>
+#include <net/bluetooth/smp.h>
static const struct proto_ops l2cap_sock_ops;
-
-/* ---- L2CAP timers ---- */
-static void l2cap_sock_timeout(unsigned long arg)
-{
- struct sock *sk = (struct sock *) arg;
- int reason;
-
- BT_DBG("sock %p state %d", sk, sk->sk_state);
-
- bh_lock_sock(sk);
-
- if (sock_owned_by_user(sk)) {
- /* sk is owned by user. Try again later */
- l2cap_sock_set_timer(sk, HZ / 5);
- bh_unlock_sock(sk);
- sock_put(sk);
- return;
- }
-
- if (sk->sk_state == BT_CONNECTED || sk->sk_state == BT_CONFIG)
- reason = ECONNREFUSED;
- else if (sk->sk_state == BT_CONNECT &&
- l2cap_pi(sk)->chan->sec_level != BT_SECURITY_SDP)
- reason = ECONNREFUSED;
- else
- reason = ETIMEDOUT;
-
- __l2cap_sock_close(sk, reason);
-
- bh_unlock_sock(sk);
-
- l2cap_sock_kill(sk);
- sock_put(sk);
-}
-
-void l2cap_sock_set_timer(struct sock *sk, long timeout)
-{
- BT_DBG("sk %p state %d timeout %ld", sk, sk->sk_state, timeout);
- sk_reset_timer(sk, &sk->sk_timer, jiffies + timeout);
-}
-
-void l2cap_sock_clear_timer(struct sock *sk)
-{
- BT_DBG("sock %p state %d", sk, sk->sk_state);
- sk_stop_timer(sk, &sk->sk_timer);
-}
+static void l2cap_sock_init(struct sock *sk, struct sock *parent);
+static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, int proto, gfp_t prio);
static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
{
@@ -133,6 +90,8 @@
chan->sec_level = BT_SECURITY_SDP;
bacpy(&bt_sk(sk)->src, &la.l2_bdaddr);
+
+ chan->state = BT_BOUND;
sk->sk_state = BT_BOUND;
done:
@@ -162,7 +121,7 @@
lock_sock(sk);
- if ((sk->sk_type == SOCK_SEQPACKET || sk->sk_type == SOCK_STREAM)
+ if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED
&& !(la.l2_psm || la.l2_cid)) {
err = -EINVAL;
goto done;
@@ -204,8 +163,8 @@
}
/* PSM must be odd and lsb of upper byte must be 0 */
- if ((__le16_to_cpu(la.l2_psm) & 0x0101) != 0x0001 &&
- sk->sk_type != SOCK_RAW && !la.l2_cid) {
+ if ((__le16_to_cpu(la.l2_psm) & 0x0101) != 0x0001 && !la.l2_cid &&
+ chan->chan_type != L2CAP_CHAN_RAW) {
err = -EINVAL;
goto done;
}
@@ -258,6 +217,8 @@
sk->sk_max_ack_backlog = backlog;
sk->sk_ack_backlog = 0;
+
+ chan->state = BT_LISTEN;
sk->sk_state = BT_LISTEN;
done:
@@ -437,6 +398,7 @@
struct sock *sk = sock->sk;
struct l2cap_chan *chan = l2cap_pi(sk)->chan;
struct bt_security sec;
+ struct bt_power pwr;
int len, err = 0;
BT_DBG("sk %p", sk);
@@ -454,8 +416,8 @@
switch (optname) {
case BT_SECURITY:
- if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM
- && sk->sk_type != SOCK_RAW) {
+ if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED &&
+ chan->chan_type != L2CAP_CHAN_RAW) {
err = -EINVAL;
break;
}
@@ -485,6 +447,21 @@
break;
+ case BT_POWER:
+ if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM
+ && sk->sk_type != SOCK_RAW) {
+ err = -EINVAL;
+ break;
+ }
+
+ pwr.force_active = chan->force_active;
+
+ len = min_t(unsigned int, len, sizeof(pwr));
+ if (copy_to_user(optval, (char *) &pwr, len))
+ err = -EFAULT;
+
+ break;
+
default:
err = -ENOPROTOOPT;
break;
@@ -535,7 +512,7 @@
chan->mode = opts.mode;
switch (chan->mode) {
case L2CAP_MODE_BASIC:
- chan->conf_state &= ~L2CAP_CONF_STATE2_DEVICE;
+ clear_bit(CONF_STATE2_DEVICE, &chan->conf_state);
break;
case L2CAP_MODE_ERTM:
case L2CAP_MODE_STREAMING:
@@ -585,6 +562,8 @@
struct sock *sk = sock->sk;
struct l2cap_chan *chan = l2cap_pi(sk)->chan;
struct bt_security sec;
+ struct bt_power pwr;
+ struct l2cap_conn *conn;
int len, err = 0;
u32 opt;
@@ -600,8 +579,8 @@
switch (optname) {
case BT_SECURITY:
- if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM
- && sk->sk_type != SOCK_RAW) {
+ if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED &&
+ chan->chan_type != L2CAP_CHAN_RAW) {
err = -EINVAL;
break;
}
@@ -621,6 +600,20 @@
}
chan->sec_level = sec.level;
+
+ conn = chan->conn;
+ if (conn && chan->scid == L2CAP_CID_LE_DATA) {
+ if (!conn->hcon->out) {
+ err = -EINVAL;
+ break;
+ }
+
+ if (smp_conn_security(conn, sec.level))
+ break;
+
+ err = 0;
+ sk->sk_state = BT_CONFIG;
+ }
break;
case BT_DEFER_SETUP:
@@ -661,6 +654,23 @@
chan->flushable = opt;
break;
+ case BT_POWER:
+ if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED &&
+ chan->chan_type != L2CAP_CHAN_RAW) {
+ err = -EINVAL;
+ break;
+ }
+
+ pwr.force_active = BT_POWER_FORCE_ACTIVE_ON;
+
+ len = min_t(unsigned int, sizeof(pwr), optlen);
+ if (copy_from_user((char *) &pwr, optval, len)) {
+ err = -EFAULT;
+ break;
+ }
+ chan->force_active = pwr.force_active;
+ break;
+
default:
err = -ENOPROTOOPT;
break;
@@ -674,8 +684,6 @@
{
struct sock *sk = sock->sk;
struct l2cap_chan *chan = l2cap_pi(sk)->chan;
- struct sk_buff *skb;
- u16 control;
int err;
BT_DBG("sock %p, sk %p", sock, sk);
@@ -690,87 +698,12 @@
lock_sock(sk);
if (sk->sk_state != BT_CONNECTED) {
- err = -ENOTCONN;
- goto done;
+ release_sock(sk);
+ return -ENOTCONN;
}
- /* Connectionless channel */
- if (sk->sk_type == SOCK_DGRAM) {
- skb = l2cap_create_connless_pdu(chan, msg, len);
- if (IS_ERR(skb)) {
- err = PTR_ERR(skb);
- } else {
- l2cap_do_send(chan, skb);
- err = len;
- }
- goto done;
- }
+ err = l2cap_chan_send(chan, msg, len);
- switch (chan->mode) {
- case L2CAP_MODE_BASIC:
- /* Check outgoing MTU */
- if (len > chan->omtu) {
- err = -EMSGSIZE;
- goto done;
- }
-
- /* Create a basic PDU */
- skb = l2cap_create_basic_pdu(chan, msg, len);
- if (IS_ERR(skb)) {
- err = PTR_ERR(skb);
- goto done;
- }
-
- l2cap_do_send(chan, skb);
- err = len;
- break;
-
- case L2CAP_MODE_ERTM:
- case L2CAP_MODE_STREAMING:
- /* Entire SDU fits into one PDU */
- if (len <= chan->remote_mps) {
- control = L2CAP_SDU_UNSEGMENTED;
- skb = l2cap_create_iframe_pdu(chan, msg, len, control,
- 0);
- if (IS_ERR(skb)) {
- err = PTR_ERR(skb);
- goto done;
- }
- __skb_queue_tail(&chan->tx_q, skb);
-
- if (chan->tx_send_head == NULL)
- chan->tx_send_head = skb;
-
- } else {
- /* Segment SDU into multiples PDUs */
- err = l2cap_sar_segment_sdu(chan, msg, len);
- if (err < 0)
- goto done;
- }
-
- if (chan->mode == L2CAP_MODE_STREAMING) {
- l2cap_streaming_send(chan);
- err = len;
- break;
- }
-
- if ((chan->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
- (chan->conn_state & L2CAP_CONN_WAIT_F)) {
- err = len;
- break;
- }
- err = l2cap_ertm_send(chan);
-
- if (err >= 0)
- err = len;
- break;
-
- default:
- BT_DBG("bad state %1.1x", chan->mode);
- err = -EBADFD;
- }
-
-done:
release_sock(sk);
return err;
}
@@ -800,7 +733,7 @@
/* Kill socket (only if zapped and orphan)
* Must be called on unlocked socket.
*/
-void l2cap_sock_kill(struct sock *sk)
+static void l2cap_sock_kill(struct sock *sk)
{
if (!sock_flag(sk, SOCK_ZAPPED) || sk->sk_socket)
return;
@@ -814,87 +747,6 @@
sock_put(sk);
}
-/* Must be called on unlocked socket. */
-static void l2cap_sock_close(struct sock *sk)
-{
- l2cap_sock_clear_timer(sk);
- lock_sock(sk);
- __l2cap_sock_close(sk, ECONNRESET);
- release_sock(sk);
- l2cap_sock_kill(sk);
-}
-
-static void l2cap_sock_cleanup_listen(struct sock *parent)
-{
- struct sock *sk;
-
- BT_DBG("parent %p", parent);
-
- /* Close not yet accepted channels */
- while ((sk = bt_accept_dequeue(parent, NULL)))
- l2cap_sock_close(sk);
-
- parent->sk_state = BT_CLOSED;
- sock_set_flag(parent, SOCK_ZAPPED);
-}
-
-void __l2cap_sock_close(struct sock *sk, int reason)
-{
- struct l2cap_chan *chan = l2cap_pi(sk)->chan;
- struct l2cap_conn *conn = chan->conn;
-
- BT_DBG("sk %p state %d socket %p", sk, sk->sk_state, sk->sk_socket);
-
- switch (sk->sk_state) {
- case BT_LISTEN:
- l2cap_sock_cleanup_listen(sk);
- break;
-
- case BT_CONNECTED:
- case BT_CONFIG:
- if ((sk->sk_type == SOCK_SEQPACKET ||
- sk->sk_type == SOCK_STREAM) &&
- conn->hcon->type == ACL_LINK) {
- l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
- l2cap_send_disconn_req(conn, chan, reason);
- } else
- l2cap_chan_del(chan, reason);
- break;
-
- case BT_CONNECT2:
- if ((sk->sk_type == SOCK_SEQPACKET ||
- sk->sk_type == SOCK_STREAM) &&
- conn->hcon->type == ACL_LINK) {
- struct l2cap_conn_rsp rsp;
- __u16 result;
-
- if (bt_sk(sk)->defer_setup)
- result = L2CAP_CR_SEC_BLOCK;
- else
- result = L2CAP_CR_BAD_PSM;
-
- rsp.scid = cpu_to_le16(chan->dcid);
- rsp.dcid = cpu_to_le16(chan->scid);
- rsp.result = cpu_to_le16(result);
- rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
- l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
- sizeof(rsp), &rsp);
- }
-
- l2cap_chan_del(chan, reason);
- break;
-
- case BT_CONNECT:
- case BT_DISCONN:
- l2cap_chan_del(chan, reason);
- break;
-
- default:
- sock_set_flag(sk, SOCK_ZAPPED);
- break;
- }
-}
-
static int l2cap_sock_shutdown(struct socket *sock, int how)
{
struct sock *sk = sock->sk;
@@ -912,8 +764,7 @@
err = __l2cap_wait_ack(sk);
sk->sk_shutdown = SHUTDOWN_MASK;
- l2cap_sock_clear_timer(sk);
- __l2cap_sock_close(sk, 0);
+ l2cap_chan_close(chan, 0);
if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime)
err = bt_sock_wait_state(sk, BT_CLOSED,
@@ -944,6 +795,49 @@
return err;
}
+static struct l2cap_chan *l2cap_sock_new_connection_cb(void *data)
+{
+ struct sock *sk, *parent = data;
+
+ sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP,
+ GFP_ATOMIC);
+ if (!sk)
+ return NULL;
+
+ l2cap_sock_init(sk, parent);
+
+ return l2cap_pi(sk)->chan;
+}
+
+static int l2cap_sock_recv_cb(void *data, struct sk_buff *skb)
+{
+ struct sock *sk = data;
+
+ return sock_queue_rcv_skb(sk, skb);
+}
+
+static void l2cap_sock_close_cb(void *data)
+{
+ struct sock *sk = data;
+
+ l2cap_sock_kill(sk);
+}
+
+static void l2cap_sock_state_change_cb(void *data, int state)
+{
+ struct sock *sk = data;
+
+ sk->sk_state = state;
+}
+
+static struct l2cap_ops l2cap_chan_ops = {
+ .name = "L2CAP Socket Interface",
+ .new_connection = l2cap_sock_new_connection_cb,
+ .recv = l2cap_sock_recv_cb,
+ .close = l2cap_sock_close_cb,
+ .state_change = l2cap_sock_state_change_cb,
+};
+
static void l2cap_sock_destruct(struct sock *sk)
{
BT_DBG("sk %p", sk);
@@ -952,7 +846,7 @@
skb_queue_purge(&sk->sk_write_queue);
}
-void l2cap_sock_init(struct sock *sk, struct sock *parent)
+static void l2cap_sock_init(struct sock *sk, struct sock *parent)
{
struct l2cap_pinfo *pi = l2cap_pi(sk);
struct l2cap_chan *chan = pi->chan;
@@ -965,6 +859,7 @@
sk->sk_type = parent->sk_type;
bt_sk(sk)->defer_setup = bt_sk(parent)->defer_setup;
+ chan->chan_type = pchan->chan_type;
chan->imtu = pchan->imtu;
chan->omtu = pchan->omtu;
chan->conf_state = pchan->conf_state;
@@ -976,12 +871,27 @@
chan->role_switch = pchan->role_switch;
chan->force_reliable = pchan->force_reliable;
chan->flushable = pchan->flushable;
+ chan->force_active = pchan->force_active;
} else {
+
+ switch (sk->sk_type) {
+ case SOCK_RAW:
+ chan->chan_type = L2CAP_CHAN_RAW;
+ break;
+ case SOCK_DGRAM:
+ chan->chan_type = L2CAP_CHAN_CONN_LESS;
+ break;
+ case SOCK_SEQPACKET:
+ case SOCK_STREAM:
+ chan->chan_type = L2CAP_CHAN_CONN_ORIENTED;
+ break;
+ }
+
chan->imtu = L2CAP_DEFAULT_MTU;
chan->omtu = 0;
if (!disable_ertm && sk->sk_type == SOCK_STREAM) {
chan->mode = L2CAP_MODE_ERTM;
- chan->conf_state |= L2CAP_CONF_STATE2_DEVICE;
+ set_bit(CONF_STATE2_DEVICE, &chan->conf_state);
} else {
chan->mode = L2CAP_MODE_BASIC;
}
@@ -992,10 +902,15 @@
chan->role_switch = 0;
chan->force_reliable = 0;
chan->flushable = BT_FLUSHABLE_OFF;
+ chan->force_active = BT_POWER_FORCE_ACTIVE_ON;
+
}
/* Default config options */
chan->flush_to = L2CAP_DEFAULT_FLUSH_TO;
+
+ chan->data = sk;
+ chan->ops = &l2cap_chan_ops;
}
static struct proto l2cap_proto = {
@@ -1004,9 +919,10 @@
.obj_size = sizeof(struct l2cap_pinfo)
};
-struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, int proto, gfp_t prio)
+static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, int proto, gfp_t prio)
{
struct sock *sk;
+ struct l2cap_chan *chan;
sk = sk_alloc(net, PF_BLUETOOTH, prio, &l2cap_proto);
if (!sk)
@@ -1023,7 +939,13 @@
sk->sk_protocol = proto;
sk->sk_state = BT_OPEN;
- setup_timer(&sk->sk_timer, l2cap_sock_timeout, (unsigned long) sk);
+ chan = l2cap_chan_create(sk);
+ if (!chan) {
+ l2cap_sock_kill(sk);
+ return NULL;
+ }
+
+ l2cap_pi(sk)->chan = chan;
return sk;
}
@@ -1032,7 +954,6 @@
int kern)
{
struct sock *sk;
- struct l2cap_chan *chan;
BT_DBG("sock %p", sock);
@@ -1051,14 +972,6 @@
if (!sk)
return -ENOMEM;
- chan = l2cap_chan_create(sk);
- if (!chan) {
- l2cap_sock_kill(sk);
- return -ENOMEM;
- }
-
- l2cap_pi(sk)->chan = chan;
-
l2cap_sock_init(sk, NULL);
return 0;
}
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index dae382c..64c0418 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -41,7 +41,7 @@
void *user_data;
};
-LIST_HEAD(cmd_list);
+static LIST_HEAD(cmd_list);
static int cmd_status(struct sock *sk, u16 index, u16 cmd, u8 status)
{
@@ -990,7 +990,7 @@
put_unaligned_le16(conn->handle, &dc.handle);
dc.reason = 0x13; /* Remote User Terminated Connection */
- err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, 0, NULL);
+ err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
}
unlock:
@@ -1092,8 +1092,6 @@
put_unaligned_le16(count, &rp->conn_count);
- read_lock(&hci_dev_list_lock);
-
i = 0;
list_for_each(p, &hdev->conn_hash.list) {
struct hci_conn *c = list_entry(p, struct hci_conn, list);
@@ -1101,8 +1099,6 @@
bacpy(&rp->conn[i++], &c->dst);
}
- read_unlock(&hci_dev_list_lock);
-
err = cmd_complete(sk, index, MGMT_OP_GET_CONNECTIONS, rp, rp_len);
unlock:
@@ -1112,11 +1108,32 @@
return err;
}
+static int send_pin_code_neg_reply(struct sock *sk, u16 index,
+ struct hci_dev *hdev, struct mgmt_cp_pin_code_neg_reply *cp)
+{
+ struct pending_cmd *cmd;
+ int err;
+
+ cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, index, cp,
+ sizeof(*cp));
+ if (!cmd)
+ return -ENOMEM;
+
+ err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY, sizeof(cp->bdaddr),
+ &cp->bdaddr);
+ if (err < 0)
+ mgmt_pending_remove(cmd);
+
+ return err;
+}
+
static int pin_code_reply(struct sock *sk, u16 index, unsigned char *data,
u16 len)
{
struct hci_dev *hdev;
+ struct hci_conn *conn;
struct mgmt_cp_pin_code_reply *cp;
+ struct mgmt_cp_pin_code_neg_reply ncp;
struct hci_cp_pin_code_reply reply;
struct pending_cmd *cmd;
int err;
@@ -1139,6 +1156,25 @@
goto failed;
}
+ conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
+ if (!conn) {
+ err = cmd_status(sk, index, MGMT_OP_PIN_CODE_REPLY, ENOTCONN);
+ goto failed;
+ }
+
+ if (conn->pending_sec_level == BT_SECURITY_HIGH && cp->pin_len != 16) {
+ bacpy(&ncp.bdaddr, &cp->bdaddr);
+
+ BT_ERR("PIN code is not 16 bytes long");
+
+ err = send_pin_code_neg_reply(sk, index, hdev, &ncp);
+ if (err >= 0)
+ err = cmd_status(sk, index, MGMT_OP_PIN_CODE_REPLY,
+ EINVAL);
+
+ goto failed;
+ }
+
cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, index, data, len);
if (!cmd) {
err = -ENOMEM;
@@ -1147,7 +1183,7 @@
bacpy(&reply.bdaddr, &cp->bdaddr);
reply.pin_len = cp->pin_len;
- memcpy(reply.pin_code, cp->pin_code, 16);
+ memcpy(reply.pin_code, cp->pin_code, sizeof(reply.pin_code));
err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_REPLY, sizeof(reply), &reply);
if (err < 0)
@@ -1165,7 +1201,6 @@
{
struct hci_dev *hdev;
struct mgmt_cp_pin_code_neg_reply *cp;
- struct pending_cmd *cmd;
int err;
BT_DBG("");
@@ -1189,17 +1224,7 @@
goto failed;
}
- cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, index,
- data, len);
- if (!cmd) {
- err = -ENOMEM;
- goto failed;
- }
-
- err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY, sizeof(cp->bdaddr),
- &cp->bdaddr);
- if (err < 0)
- mgmt_pending_remove(cmd);
+ err = send_pin_code_neg_reply(sk, index, hdev, cp);
failed:
hci_dev_unlock(hdev);
@@ -1641,6 +1666,70 @@
return err;
}
+static int block_device(struct sock *sk, u16 index, unsigned char *data,
+ u16 len)
+{
+ struct hci_dev *hdev;
+ struct mgmt_cp_block_device *cp;
+ int err;
+
+ BT_DBG("hci%u", index);
+
+ cp = (void *) data;
+
+ if (len != sizeof(*cp))
+ return cmd_status(sk, index, MGMT_OP_BLOCK_DEVICE,
+ EINVAL);
+
+ hdev = hci_dev_get(index);
+ if (!hdev)
+ return cmd_status(sk, index, MGMT_OP_BLOCK_DEVICE,
+ ENODEV);
+
+ err = hci_blacklist_add(hdev, &cp->bdaddr);
+
+ if (err < 0)
+ err = cmd_status(sk, index, MGMT_OP_BLOCK_DEVICE, -err);
+ else
+ err = cmd_complete(sk, index, MGMT_OP_BLOCK_DEVICE,
+ NULL, 0);
+ hci_dev_put(hdev);
+
+ return err;
+}
+
+static int unblock_device(struct sock *sk, u16 index, unsigned char *data,
+ u16 len)
+{
+ struct hci_dev *hdev;
+ struct mgmt_cp_unblock_device *cp;
+ int err;
+
+ BT_DBG("hci%u", index);
+
+ cp = (void *) data;
+
+ if (len != sizeof(*cp))
+ return cmd_status(sk, index, MGMT_OP_UNBLOCK_DEVICE,
+ EINVAL);
+
+ hdev = hci_dev_get(index);
+ if (!hdev)
+ return cmd_status(sk, index, MGMT_OP_UNBLOCK_DEVICE,
+ ENODEV);
+
+ err = hci_blacklist_del(hdev, &cp->bdaddr);
+
+ if (err < 0)
+ err = cmd_status(sk, index, MGMT_OP_UNBLOCK_DEVICE, -err);
+ else
+ err = cmd_complete(sk, index, MGMT_OP_UNBLOCK_DEVICE,
+ NULL, 0);
+ hci_dev_put(hdev);
+
+ return err;
+}
+
int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
{
unsigned char *buf;
@@ -1755,6 +1844,12 @@
case MGMT_OP_STOP_DISCOVERY:
err = stop_discovery(sk, index);
break;
+ case MGMT_OP_BLOCK_DEVICE:
+ err = block_device(sk, index, buf + sizeof(*hdr), len);
+ break;
+ case MGMT_OP_UNBLOCK_DEVICE:
+ err = unblock_device(sk, index, buf + sizeof(*hdr), len);
+ break;
default:
BT_DBG("Unknown op %u", opcode);
err = cmd_status(sk, index, opcode, 0x01);
diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c
index 1b10727..8f01e6b 100644
--- a/net/bluetooth/rfcomm/sock.c
+++ b/net/bluetooth/rfcomm/sock.c
@@ -679,7 +679,8 @@
{
struct sock *sk = sock->sk;
struct bt_security sec;
- int len, err = 0;
+ int err = 0;
+ size_t len;
u32 opt;
BT_DBG("sk %p", sk);
@@ -741,7 +742,6 @@
static int rfcomm_sock_getsockopt_old(struct socket *sock, int optname, char __user *optval, int __user *optlen)
{
struct sock *sk = sock->sk;
- struct sock *l2cap_sk;
struct rfcomm_conninfo cinfo;
struct l2cap_conn *conn = l2cap_pi(sk)->chan->conn;
int len, err = 0;
@@ -786,8 +786,6 @@
break;
}
- l2cap_sk = rfcomm_pi(sk)->dlc->session->sock->sk;
-
memset(&cinfo, 0, sizeof(cinfo));
cinfo.hci_handle = conn->hcon->handle;
memcpy(cinfo.dev_class, conn->hcon->dev_class, 3);
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
new file mode 100644
index 0000000..a36f870
--- /dev/null
+++ b/net/bluetooth/smp.c
@@ -0,0 +1,534 @@
+/*
+ BlueZ - Bluetooth protocol stack for Linux
+ Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+
+ 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;
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
+ IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
+ CLAIM, OR ANY SPECIAL 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.
+
+ ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
+ COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
+ SOFTWARE IS DISCLAIMED.
+*/
+
+#include <net/bluetooth/bluetooth.h>
+#include <net/bluetooth/hci_core.h>
+#include <net/bluetooth/l2cap.h>
+#include <net/bluetooth/smp.h>
+#include <linux/crypto.h>
+#include <linux/scatterlist.h>
+#include <crypto/b128ops.h>
+
+#define SMP_TIMEOUT 30000 /* 30 seconds */
+
+static inline void swap128(u8 src[16], u8 dst[16])
+{
+ int i;
+ for (i = 0; i < 16; i++)
+ dst[15 - i] = src[i];
+}
+
+static inline void swap56(u8 src[7], u8 dst[7])
+{
+ int i;
+ for (i = 0; i < 7; i++)
+ dst[6 - i] = src[i];
+}
+
+static int smp_e(struct crypto_blkcipher *tfm, const u8 *k, u8 *r)
+{
+ struct blkcipher_desc desc;
+ struct scatterlist sg;
+ int err, iv_len;
+ unsigned char iv[128];
+
+ if (tfm == NULL) {
+ BT_ERR("tfm %p", tfm);
+ return -EINVAL;
+ }
+
+ desc.tfm = tfm;
+ desc.flags = 0;
+
+ err = crypto_blkcipher_setkey(tfm, k, 16);
+ if (err) {
+ BT_ERR("cipher setkey failed: %d", err);
+ return err;
+ }
+
+ sg_init_one(&sg, r, 16);
+
+ iv_len = crypto_blkcipher_ivsize(tfm);
+ if (iv_len) {
+ memset(&iv, 0xff, iv_len);
+ crypto_blkcipher_set_iv(tfm, iv, iv_len);
+ }
+
+ err = crypto_blkcipher_encrypt(&desc, &sg, &sg, 16);
+ if (err)
+ BT_ERR("Encrypt data error %d", err);
+
+ return err;
+}
+
+static int smp_c1(struct crypto_blkcipher *tfm, u8 k[16], u8 r[16],
+ u8 preq[7], u8 pres[7], u8 _iat, bdaddr_t *ia,
+ u8 _rat, bdaddr_t *ra, u8 res[16])
+{
+ u8 p1[16], p2[16];
+ int err;
+
+ memset(p1, 0, 16);
+
+ /* p1 = pres || preq || _rat || _iat */
+ swap56(pres, p1);
+ swap56(preq, p1 + 7);
+ p1[14] = _rat;
+ p1[15] = _iat;
+
+ memset(p2, 0, 16);
+
+ /* p2 = padding || ia || ra */
+ baswap((bdaddr_t *) (p2 + 4), ia);
+ baswap((bdaddr_t *) (p2 + 10), ra);
+
+ /* res = r XOR p1 */
+ u128_xor((u128 *) res, (u128 *) r, (u128 *) p1);
+
+ /* res = e(k, res) */
+ err = smp_e(tfm, k, res);
+ if (err) {
+ BT_ERR("Encrypt data error");
+ return err;
+ }
+
+ /* res = res XOR p2 */
+ u128_xor((u128 *) res, (u128 *) res, (u128 *) p2);
+
+ /* res = e(k, res) */
+ err = smp_e(tfm, k, res);
+ if (err)
+ BT_ERR("Encrypt data error");
+
+ return err;
+}
+
+static int smp_s1(struct crypto_blkcipher *tfm, u8 k[16],
+ u8 r1[16], u8 r2[16], u8 _r[16])
+{
+ int err;
+
+ /* Just least significant octets from r1 and r2 are considered */
+ memcpy(_r, r1 + 8, 8);
+ memcpy(_r + 8, r2 + 8, 8);
+
+ err = smp_e(tfm, k, _r);
+ if (err)
+ BT_ERR("Encrypt data error");
+
+ return err;
+}
+
+static int smp_rand(u8 *buf)
+{
+ get_random_bytes(buf, 16);
+
+ return 0;
+}
+
+static struct sk_buff *smp_build_cmd(struct l2cap_conn *conn, u8 code,
+ u16 dlen, void *data)
+{
+ struct sk_buff *skb;
+ struct l2cap_hdr *lh;
+ int len;
+
+ len = L2CAP_HDR_SIZE + sizeof(code) + dlen;
+
+ if (len > conn->mtu)
+ return NULL;
+
+ skb = bt_skb_alloc(len, GFP_ATOMIC);
+ if (!skb)
+ return NULL;
+
+ lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
+ lh->len = cpu_to_le16(sizeof(code) + dlen);
+ lh->cid = cpu_to_le16(L2CAP_CID_SMP);
+
+ memcpy(skb_put(skb, sizeof(code)), &code, sizeof(code));
+
+ memcpy(skb_put(skb, dlen), data, dlen);
+
+ return skb;
+}
+
+static void smp_send_cmd(struct l2cap_conn *conn, u8 code, u16 len, void *data)
+{
+ struct sk_buff *skb = smp_build_cmd(conn, code, len, data);
+
+ BT_DBG("code 0x%2.2x", code);
+
+ if (!skb)
+ return;
+
+ hci_send_acl(conn->hcon, skb, 0);
+}
+
+static __u8 seclevel_to_authreq(__u8 level)
+{
+ switch (level) {
+ case BT_SECURITY_HIGH:
+ /* Right now we don't support bonding */
+ return SMP_AUTH_MITM;
+
+ default:
+ return SMP_AUTH_NONE;
+ }
+}
+
+static void build_pairing_cmd(struct l2cap_conn *conn,
+ struct smp_cmd_pairing *cmd, __u8 authreq)
+{
+ cmd->io_capability = conn->hcon->io_capability;
+ cmd->oob_flag = SMP_OOB_NOT_PRESENT;
+ cmd->max_key_size = SMP_MAX_ENC_KEY_SIZE;
+ cmd->init_key_dist = 0x00;
+ cmd->resp_key_dist = 0x00;
+ cmd->auth_req = authreq;
+}
+
+static u8 check_enc_key_size(struct l2cap_conn *conn, __u8 max_key_size)
+{
+ if ((max_key_size > SMP_MAX_ENC_KEY_SIZE) ||
+ (max_key_size < SMP_MIN_ENC_KEY_SIZE))
+ return SMP_ENC_KEY_SIZE;
+
+ conn->smp_key_size = max_key_size;
+
+ return 0;
+}
+
+static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
+{
+ struct smp_cmd_pairing rsp, *req = (void *) skb->data;
+ u8 key_size;
+
+ BT_DBG("conn %p", conn);
+
+ conn->preq[0] = SMP_CMD_PAIRING_REQ;
+ memcpy(&conn->preq[1], req, sizeof(*req));
+ skb_pull(skb, sizeof(*req));
+
+ if (req->oob_flag)
+ return SMP_OOB_NOT_AVAIL;
+
+ /* We didn't start the pairing, so no requirements */
+ build_pairing_cmd(conn, &rsp, SMP_AUTH_NONE);
+
+ key_size = min(req->max_key_size, rsp.max_key_size);
+ if (check_enc_key_size(conn, key_size))
+ return SMP_ENC_KEY_SIZE;
+
+ /* Just works */
+ memset(conn->tk, 0, sizeof(conn->tk));
+
+ conn->prsp[0] = SMP_CMD_PAIRING_RSP;
+ memcpy(&conn->prsp[1], &rsp, sizeof(rsp));
+
+ smp_send_cmd(conn, SMP_CMD_PAIRING_RSP, sizeof(rsp), &rsp);
+
+ mod_timer(&conn->security_timer, jiffies +
+ msecs_to_jiffies(SMP_TIMEOUT));
+
+ return 0;
+}
+
+static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
+{
+ struct smp_cmd_pairing *req, *rsp = (void *) skb->data;
+ struct smp_cmd_pairing_confirm cp;
+ struct crypto_blkcipher *tfm = conn->hcon->hdev->tfm;
+ int ret;
+ u8 res[16], key_size;
+
+ BT_DBG("conn %p", conn);
+
+ skb_pull(skb, sizeof(*rsp));
+
+ req = (void *) &conn->preq[1];
+
+ key_size = min(req->max_key_size, rsp->max_key_size);
+ if (check_enc_key_size(conn, key_size))
+ return SMP_ENC_KEY_SIZE;
+
+ if (rsp->oob_flag)
+ return SMP_OOB_NOT_AVAIL;
+
+ /* Just works */
+ memset(conn->tk, 0, sizeof(conn->tk));
+
+ conn->prsp[0] = SMP_CMD_PAIRING_RSP;
+ memcpy(&conn->prsp[1], rsp, sizeof(*rsp));
+
+ ret = smp_rand(conn->prnd);
+ if (ret)
+ return SMP_UNSPECIFIED;
+
+ ret = smp_c1(tfm, conn->tk, conn->prnd, conn->preq, conn->prsp, 0,
+ conn->src, conn->hcon->dst_type, conn->dst, res);
+ if (ret)
+ return SMP_UNSPECIFIED;
+
+ swap128(res, cp.confirm_val);
+
+ smp_send_cmd(conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cp), &cp);
+
+ return 0;
+}
+
+static u8 smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb)
+{
+ struct crypto_blkcipher *tfm = conn->hcon->hdev->tfm;
+
+ BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
+
+ memcpy(conn->pcnf, skb->data, sizeof(conn->pcnf));
+ skb_pull(skb, sizeof(conn->pcnf));
+
+ if (conn->hcon->out) {
+ u8 random[16];
+
+ swap128(conn->prnd, random);
+ smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(random),
+ random);
+ } else {
+ struct smp_cmd_pairing_confirm cp;
+ int ret;
+ u8 res[16];
+
+ ret = smp_rand(conn->prnd);
+ if (ret)
+ return SMP_UNSPECIFIED;
+
+ ret = smp_c1(tfm, conn->tk, conn->prnd, conn->preq, conn->prsp,
+ conn->hcon->dst_type, conn->dst,
+ 0, conn->src, res);
+ if (ret)
+ return SMP_CONFIRM_FAILED;
+
+ swap128(res, cp.confirm_val);
+
+ smp_send_cmd(conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cp), &cp);
+ }
+
+ mod_timer(&conn->security_timer, jiffies +
+ msecs_to_jiffies(SMP_TIMEOUT));
+
+ return 0;
+}
+
+static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
+{
+ struct hci_conn *hcon = conn->hcon;
+ struct crypto_blkcipher *tfm = hcon->hdev->tfm;
+ int ret;
+ u8 key[16], res[16], random[16], confirm[16];
+
+ swap128(skb->data, random);
+ skb_pull(skb, sizeof(random));
+
+ memset(hcon->ltk, 0, sizeof(hcon->ltk));
+
+ if (conn->hcon->out)
+ ret = smp_c1(tfm, conn->tk, random, conn->preq, conn->prsp, 0,
+ conn->src, conn->hcon->dst_type, conn->dst,
+ res);
+ else
+ ret = smp_c1(tfm, conn->tk, random, conn->preq, conn->prsp,
+ conn->hcon->dst_type, conn->dst, 0, conn->src,
+ res);
+ if (ret)
+ return SMP_UNSPECIFIED;
+
+ BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
+
+ swap128(res, confirm);
+
+ if (memcmp(conn->pcnf, confirm, sizeof(conn->pcnf)) != 0) {
+ BT_ERR("Pairing failed (confirmation values mismatch)");
+ return SMP_CONFIRM_FAILED;
+ }
+
+ if (conn->hcon->out) {
+ __le16 ediv;
+ u8 rand[8];
+
+ smp_s1(tfm, conn->tk, random, conn->prnd, key);
+ swap128(key, hcon->ltk);
+
+ memset(hcon->ltk + conn->smp_key_size, 0,
+ SMP_MAX_ENC_KEY_SIZE - conn->smp_key_size);
+
+ memset(rand, 0, sizeof(rand));
+ ediv = 0;
+ hci_le_start_enc(hcon, ediv, rand, hcon->ltk);
+ } else {
+ u8 r[16];
+
+ swap128(conn->prnd, r);
+ smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(r), r);
+
+ smp_s1(tfm, conn->tk, conn->prnd, random, key);
+ swap128(key, hcon->ltk);
+
+ memset(hcon->ltk + conn->smp_key_size, 0,
+ SMP_MAX_ENC_KEY_SIZE - conn->smp_key_size);
+ }
+
+ return 0;
+}
+
+static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
+{
+ struct smp_cmd_security_req *rp = (void *) skb->data;
+ struct smp_cmd_pairing cp;
+ struct hci_conn *hcon = conn->hcon;
+
+ BT_DBG("conn %p", conn);
+
+ if (test_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend))
+ return 0;
+
+ skb_pull(skb, sizeof(*rp));
+
+ memset(&cp, 0, sizeof(cp));
+ build_pairing_cmd(conn, &cp, rp->auth_req);
+
+ conn->preq[0] = SMP_CMD_PAIRING_REQ;
+ memcpy(&conn->preq[1], &cp, sizeof(cp));
+
+ smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
+
+ mod_timer(&conn->security_timer, jiffies +
+ msecs_to_jiffies(SMP_TIMEOUT));
+
+ set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
+
+ return 0;
+}
+
+int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level)
+{
+ struct hci_conn *hcon = conn->hcon;
+ __u8 authreq;
+
+ BT_DBG("conn %p hcon %p level 0x%2.2x", conn, hcon, sec_level);
+
+ if (IS_ERR(hcon->hdev->tfm))
+ return 1;
+
+ if (test_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend))
+ return 0;
+
+ if (sec_level == BT_SECURITY_LOW)
+ return 1;
+
+ if (hcon->sec_level >= sec_level)
+ return 1;
+
+ authreq = seclevel_to_authreq(sec_level);
+
+ if (hcon->link_mode & HCI_LM_MASTER) {
+ struct smp_cmd_pairing cp;
+
+ build_pairing_cmd(conn, &cp, authreq);
+ conn->preq[0] = SMP_CMD_PAIRING_REQ;
+ memcpy(&conn->preq[1], &cp, sizeof(cp));
+
+ mod_timer(&conn->security_timer, jiffies +
+ msecs_to_jiffies(SMP_TIMEOUT));
+
+ smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
+ } else {
+ struct smp_cmd_security_req cp;
+ cp.auth_req = authreq;
+ smp_send_cmd(conn, SMP_CMD_SECURITY_REQ, sizeof(cp), &cp);
+ }
+
+ hcon->pending_sec_level = sec_level;
+ set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
+
+ return 0;
+}
+
+int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
+{
+ __u8 code = skb->data[0];
+ __u8 reason;
+ int err = 0;
+
+ if (IS_ERR(conn->hcon->hdev->tfm)) {
+ err = PTR_ERR(conn->hcon->hdev->tfm);
+ reason = SMP_PAIRING_NOTSUPP;
+ goto done;
+ }
+
+ skb_pull(skb, sizeof(code));
+
+ switch (code) {
+ case SMP_CMD_PAIRING_REQ:
+ reason = smp_cmd_pairing_req(conn, skb);
+ break;
+
+ case SMP_CMD_PAIRING_FAIL:
+ reason = 0;
+ err = -EPERM;
+ break;
+
+ case SMP_CMD_PAIRING_RSP:
+ reason = smp_cmd_pairing_rsp(conn, skb);
+ break;
+
+ case SMP_CMD_SECURITY_REQ:
+ reason = smp_cmd_security_req(conn, skb);
+ break;
+
+ case SMP_CMD_PAIRING_CONFIRM:
+ reason = smp_cmd_pairing_confirm(conn, skb);
+ break;
+
+ case SMP_CMD_PAIRING_RANDOM:
+ reason = smp_cmd_pairing_random(conn, skb);
+ break;
+
+ case SMP_CMD_ENCRYPT_INFO:
+ case SMP_CMD_MASTER_IDENT:
+ case SMP_CMD_IDENT_INFO:
+ case SMP_CMD_IDENT_ADDR_INFO:
+ case SMP_CMD_SIGN_INFO:
+ default:
+ BT_DBG("Unknown command code 0x%2.2x", code);
+
+ reason = SMP_CMD_NOTSUPP;
+ err = -EOPNOTSUPP;
+ goto done;
+ }
+
+done:
+ if (reason)
+ smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason),
+ &reason);
+
+ kfree_skb(skb);
+ return err;
+}
diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c
index ffb0dc4..6814083 100644
--- a/net/bridge/br_netlink.c
+++ b/net/bridge/br_netlink.c
@@ -218,19 +218,24 @@
if (err < 0)
goto err1;
- err = __rtnl_register(PF_BRIDGE, RTM_GETLINK, NULL, br_dump_ifinfo);
+ err = __rtnl_register(PF_BRIDGE, RTM_GETLINK, NULL,
+ br_dump_ifinfo, NULL);
if (err)
goto err2;
- err = __rtnl_register(PF_BRIDGE, RTM_SETLINK, br_rtm_setlink, NULL);
+ err = __rtnl_register(PF_BRIDGE, RTM_SETLINK,
+ br_rtm_setlink, NULL, NULL);
if (err)
goto err3;
- err = __rtnl_register(PF_BRIDGE, RTM_NEWNEIGH, br_fdb_add, NULL);
+ err = __rtnl_register(PF_BRIDGE, RTM_NEWNEIGH,
+ br_fdb_add, NULL, NULL);
if (err)
goto err3;
- err = __rtnl_register(PF_BRIDGE, RTM_DELNEIGH, br_fdb_delete, NULL);
+ err = __rtnl_register(PF_BRIDGE, RTM_DELNEIGH,
+ br_fdb_delete, NULL, NULL);
if (err)
goto err3;
- err = __rtnl_register(PF_BRIDGE, RTM_GETNEIGH, NULL, br_fdb_dump);
+ err = __rtnl_register(PF_BRIDGE, RTM_GETNEIGH,
+ NULL, br_fdb_dump, NULL);
if (err)
goto err3;
diff --git a/net/caif/caif_dev.c b/net/caif/caif_dev.c
index 682c0fe..7c2fa0a 100644
--- a/net/caif/caif_dev.c
+++ b/net/caif/caif_dev.c
@@ -11,7 +11,6 @@
#define pr_fmt(fmt) KBUILD_MODNAME ":%s(): " fmt, __func__
-#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/if_arp.h>
#include <linux/net.h>
diff --git a/net/caif/chnl_net.c b/net/caif/chnl_net.c
index adbb424..8656909 100644
--- a/net/caif/chnl_net.c
+++ b/net/caif/chnl_net.c
@@ -7,8 +7,8 @@
#define pr_fmt(fmt) KBUILD_MODNAME ":%s(): " fmt, __func__
-#include <linux/version.h>
#include <linux/fs.h>
+#include <linux/hardirq.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/netdevice.h>
diff --git a/net/can/af_can.c b/net/can/af_can.c
index 094fc53..8ce926d 100644
--- a/net/can/af_can.c
+++ b/net/can/af_can.c
@@ -58,6 +58,7 @@
#include <linux/skbuff.h>
#include <linux/can.h>
#include <linux/can/core.h>
+#include <linux/ratelimit.h>
#include <net/net_namespace.h>
#include <net/sock.h>
@@ -161,8 +162,8 @@
* return the error code immediately. Below we will
* return -EPROTONOSUPPORT
*/
- if (err && printk_ratelimit())
- printk(KERN_ERR "can: request_module "
+ if (err)
+ printk_ratelimited(KERN_ERR "can: request_module "
"(can-proto-%d) failed.\n", protocol);
cp = can_get_proto(protocol);
diff --git a/net/can/bcm.c b/net/can/bcm.c
index 184a657..d6c8ae5 100644
--- a/net/can/bcm.c
+++ b/net/can/bcm.c
@@ -43,6 +43,7 @@
#include <linux/module.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/hrtimer.h>
#include <linux/list.h>
#include <linux/proc_fs.h>
diff --git a/net/ceph/crypto.c b/net/ceph/crypto.c
index 5a8009c..85f3bc0 100644
--- a/net/ceph/crypto.c
+++ b/net/ceph/crypto.c
@@ -444,7 +444,7 @@
goto err;
/* TODO ceph_crypto_key_decode should really take const input */
- p = (void*)data;
+ p = (void *)data;
ret = ceph_crypto_key_decode(ckey, &p, (char*)data+datalen);
if (ret < 0)
goto err_ckey;
diff --git a/net/core/dev.c b/net/core/dev.c
index 9c58c1e..9ca1514 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -199,6 +199,11 @@
DEFINE_RWLOCK(dev_base_lock);
EXPORT_SYMBOL(dev_base_lock);
+static inline void dev_base_seq_inc(struct net *net)
+{
+ while (++net->dev_base_seq == 0);
+}
+
static inline struct hlist_head *dev_name_hash(struct net *net, const char *name)
{
unsigned hash = full_name_hash(name, strnlen(name, IFNAMSIZ));
@@ -237,6 +242,9 @@
hlist_add_head_rcu(&dev->index_hlist,
dev_index_hash(net, dev->ifindex));
write_unlock_bh(&dev_base_lock);
+
+ dev_base_seq_inc(net);
+
return 0;
}
@@ -253,6 +261,8 @@
hlist_del_rcu(&dev->name_hlist);
hlist_del_rcu(&dev->index_hlist);
write_unlock_bh(&dev_base_lock);
+
+ dev_base_seq_inc(dev_net(dev));
}
/*
@@ -2532,7 +2542,7 @@
goto done;
ip = (const struct iphdr *) (skb->data + nhoff);
- if (ip->frag_off & htons(IP_MF | IP_OFFSET))
+ if (ip_is_fragment(ip))
ip_proto = 0;
else
ip_proto = ip->protocol;
@@ -5478,11 +5488,12 @@
dev->features |= NETIF_F_NOCACHE_COPY;
}
- /* Enable GRO and NETIF_F_HIGHDMA for vlans by default,
- * vlan_dev_init() will do the dev->features check, so these features
- * are enabled only if supported by underlying device.
+ /* Enable GSO, GRO and NETIF_F_HIGHDMA for vlans by default,
+ * vlan_dev_fix_features() will do the features check,
+ * so NETIF_F_HIGHDMA feature is enabled only if supported
+ * by underlying device.
*/
- dev->vlan_features |= (NETIF_F_GRO | NETIF_F_HIGHDMA);
+ dev->vlan_features |= (NETIF_F_SOFT_FEATURES | NETIF_F_HIGHDMA);
ret = call_netdevice_notifiers(NETDEV_POST_INIT, dev);
ret = notifier_to_errno(ret);
@@ -5867,8 +5878,6 @@
dev->gso_max_size = GSO_MAX_SIZE;
- INIT_LIST_HEAD(&dev->ethtool_ntuple_list.list);
- dev->ethtool_ntuple_list.count = 0;
INIT_LIST_HEAD(&dev->napi_list);
INIT_LIST_HEAD(&dev->unreg_list);
INIT_LIST_HEAD(&dev->link_watch_list);
@@ -5932,9 +5941,6 @@
/* Flush device addresses */
dev_addr_flush(dev);
- /* Clear ethtool n-tuple list */
- ethtool_ntuple_flush(dev);
-
list_for_each_entry_safe(p, n, &dev->napi_list, dev_list)
netif_napi_del(p);
diff --git a/net/core/ethtool.c b/net/core/ethtool.c
index fd14116..b7c12a6 100644
--- a/net/core/ethtool.c
+++ b/net/core/ethtool.c
@@ -169,18 +169,6 @@
}
EXPORT_SYMBOL(ethtool_op_set_flags);
-void ethtool_ntuple_flush(struct net_device *dev)
-{
- struct ethtool_rx_ntuple_flow_spec_container *fsc, *f;
-
- list_for_each_entry_safe(fsc, f, &dev->ethtool_ntuple_list.list, list) {
- list_del(&fsc->list);
- kfree(fsc);
- }
- dev->ethtool_ntuple_list.count = 0;
-}
-EXPORT_SYMBOL(ethtool_ntuple_flush);
-
/* Handlers for each ethtool command */
#define ETHTOOL_DEV_FEATURE_WORDS 1
@@ -865,34 +853,6 @@
return ret;
}
-static void __rx_ntuple_filter_add(struct ethtool_rx_ntuple_list *list,
- struct ethtool_rx_ntuple_flow_spec *spec,
- struct ethtool_rx_ntuple_flow_spec_container *fsc)
-{
-
- /* don't add filters forever */
- if (list->count >= ETHTOOL_MAX_NTUPLE_LIST_ENTRY) {
- /* free the container */
- kfree(fsc);
- return;
- }
-
- /* Copy the whole filter over */
- fsc->fs.flow_type = spec->flow_type;
- memcpy(&fsc->fs.h_u, &spec->h_u, sizeof(spec->h_u));
- memcpy(&fsc->fs.m_u, &spec->m_u, sizeof(spec->m_u));
-
- fsc->fs.vlan_tag = spec->vlan_tag;
- fsc->fs.vlan_tag_mask = spec->vlan_tag_mask;
- fsc->fs.data = spec->data;
- fsc->fs.data_mask = spec->data_mask;
- fsc->fs.action = spec->action;
-
- /* add to the list */
- list_add_tail_rcu(&fsc->list, &list->list);
- list->count++;
-}
-
/*
* ethtool does not (or did not) set masks for flow parameters that are
* not specified, so if both value and mask are 0 then this must be
@@ -930,8 +890,6 @@
{
struct ethtool_rx_ntuple cmd;
const struct ethtool_ops *ops = dev->ethtool_ops;
- struct ethtool_rx_ntuple_flow_spec_container *fsc = NULL;
- int ret;
if (!ops->set_rx_ntuple)
return -EOPNOTSUPP;
@@ -944,269 +902,7 @@
rx_ntuple_fix_masks(&cmd.fs);
- /*
- * Cache filter in dev struct for GET operation only if
- * the underlying driver doesn't have its own GET operation, and
- * only if the filter was added successfully. First make sure we
- * can allocate the filter, then continue if successful.
- */
- if (!ops->get_rx_ntuple) {
- fsc = kmalloc(sizeof(*fsc), GFP_ATOMIC);
- if (!fsc)
- return -ENOMEM;
- }
-
- ret = ops->set_rx_ntuple(dev, &cmd);
- if (ret) {
- kfree(fsc);
- return ret;
- }
-
- if (!ops->get_rx_ntuple)
- __rx_ntuple_filter_add(&dev->ethtool_ntuple_list, &cmd.fs, fsc);
-
- return ret;
-}
-
-static int ethtool_get_rx_ntuple(struct net_device *dev, void __user *useraddr)
-{
- struct ethtool_gstrings gstrings;
- const struct ethtool_ops *ops = dev->ethtool_ops;
- struct ethtool_rx_ntuple_flow_spec_container *fsc;
- u8 *data;
- char *p;
- int ret, i, num_strings = 0;
-
- if (!ops->get_sset_count)
- return -EOPNOTSUPP;
-
- if (copy_from_user(&gstrings, useraddr, sizeof(gstrings)))
- return -EFAULT;
-
- ret = ops->get_sset_count(dev, gstrings.string_set);
- if (ret < 0)
- return ret;
-
- gstrings.len = ret;
-
- data = kzalloc(gstrings.len * ETH_GSTRING_LEN, GFP_USER);
- if (!data)
- return -ENOMEM;
-
- if (ops->get_rx_ntuple) {
- /* driver-specific filter grab */
- ret = ops->get_rx_ntuple(dev, gstrings.string_set, data);
- goto copy;
- }
-
- /* default ethtool filter grab */
- i = 0;
- p = (char *)data;
- list_for_each_entry(fsc, &dev->ethtool_ntuple_list.list, list) {
- sprintf(p, "Filter %d:\n", i);
- p += ETH_GSTRING_LEN;
- num_strings++;
-
- switch (fsc->fs.flow_type) {
- case TCP_V4_FLOW:
- sprintf(p, "\tFlow Type: TCP\n");
- p += ETH_GSTRING_LEN;
- num_strings++;
- break;
- case UDP_V4_FLOW:
- sprintf(p, "\tFlow Type: UDP\n");
- p += ETH_GSTRING_LEN;
- num_strings++;
- break;
- case SCTP_V4_FLOW:
- sprintf(p, "\tFlow Type: SCTP\n");
- p += ETH_GSTRING_LEN;
- num_strings++;
- break;
- case AH_ESP_V4_FLOW:
- sprintf(p, "\tFlow Type: AH ESP\n");
- p += ETH_GSTRING_LEN;
- num_strings++;
- break;
- case ESP_V4_FLOW:
- sprintf(p, "\tFlow Type: ESP\n");
- p += ETH_GSTRING_LEN;
- num_strings++;
- break;
- case IP_USER_FLOW:
- sprintf(p, "\tFlow Type: Raw IP\n");
- p += ETH_GSTRING_LEN;
- num_strings++;
- break;
- case IPV4_FLOW:
- sprintf(p, "\tFlow Type: IPv4\n");
- p += ETH_GSTRING_LEN;
- num_strings++;
- break;
- default:
- sprintf(p, "\tFlow Type: Unknown\n");
- p += ETH_GSTRING_LEN;
- num_strings++;
- goto unknown_filter;
- }
-
- /* now the rest of the filters */
- switch (fsc->fs.flow_type) {
- case TCP_V4_FLOW:
- case UDP_V4_FLOW:
- case SCTP_V4_FLOW:
- sprintf(p, "\tSrc IP addr: 0x%x\n",
- fsc->fs.h_u.tcp_ip4_spec.ip4src);
- p += ETH_GSTRING_LEN;
- num_strings++;
- sprintf(p, "\tSrc IP mask: 0x%x\n",
- fsc->fs.m_u.tcp_ip4_spec.ip4src);
- p += ETH_GSTRING_LEN;
- num_strings++;
- sprintf(p, "\tDest IP addr: 0x%x\n",
- fsc->fs.h_u.tcp_ip4_spec.ip4dst);
- p += ETH_GSTRING_LEN;
- num_strings++;
- sprintf(p, "\tDest IP mask: 0x%x\n",
- fsc->fs.m_u.tcp_ip4_spec.ip4dst);
- p += ETH_GSTRING_LEN;
- num_strings++;
- sprintf(p, "\tSrc Port: %d, mask: 0x%x\n",
- fsc->fs.h_u.tcp_ip4_spec.psrc,
- fsc->fs.m_u.tcp_ip4_spec.psrc);
- p += ETH_GSTRING_LEN;
- num_strings++;
- sprintf(p, "\tDest Port: %d, mask: 0x%x\n",
- fsc->fs.h_u.tcp_ip4_spec.pdst,
- fsc->fs.m_u.tcp_ip4_spec.pdst);
- p += ETH_GSTRING_LEN;
- num_strings++;
- sprintf(p, "\tTOS: %d, mask: 0x%x\n",
- fsc->fs.h_u.tcp_ip4_spec.tos,
- fsc->fs.m_u.tcp_ip4_spec.tos);
- p += ETH_GSTRING_LEN;
- num_strings++;
- break;
- case AH_ESP_V4_FLOW:
- case ESP_V4_FLOW:
- sprintf(p, "\tSrc IP addr: 0x%x\n",
- fsc->fs.h_u.ah_ip4_spec.ip4src);
- p += ETH_GSTRING_LEN;
- num_strings++;
- sprintf(p, "\tSrc IP mask: 0x%x\n",
- fsc->fs.m_u.ah_ip4_spec.ip4src);
- p += ETH_GSTRING_LEN;
- num_strings++;
- sprintf(p, "\tDest IP addr: 0x%x\n",
- fsc->fs.h_u.ah_ip4_spec.ip4dst);
- p += ETH_GSTRING_LEN;
- num_strings++;
- sprintf(p, "\tDest IP mask: 0x%x\n",
- fsc->fs.m_u.ah_ip4_spec.ip4dst);
- p += ETH_GSTRING_LEN;
- num_strings++;
- sprintf(p, "\tSPI: %d, mask: 0x%x\n",
- fsc->fs.h_u.ah_ip4_spec.spi,
- fsc->fs.m_u.ah_ip4_spec.spi);
- p += ETH_GSTRING_LEN;
- num_strings++;
- sprintf(p, "\tTOS: %d, mask: 0x%x\n",
- fsc->fs.h_u.ah_ip4_spec.tos,
- fsc->fs.m_u.ah_ip4_spec.tos);
- p += ETH_GSTRING_LEN;
- num_strings++;
- break;
- case IP_USER_FLOW:
- sprintf(p, "\tSrc IP addr: 0x%x\n",
- fsc->fs.h_u.usr_ip4_spec.ip4src);
- p += ETH_GSTRING_LEN;
- num_strings++;
- sprintf(p, "\tSrc IP mask: 0x%x\n",
- fsc->fs.m_u.usr_ip4_spec.ip4src);
- p += ETH_GSTRING_LEN;
- num_strings++;
- sprintf(p, "\tDest IP addr: 0x%x\n",
- fsc->fs.h_u.usr_ip4_spec.ip4dst);
- p += ETH_GSTRING_LEN;
- num_strings++;
- sprintf(p, "\tDest IP mask: 0x%x\n",
- fsc->fs.m_u.usr_ip4_spec.ip4dst);
- p += ETH_GSTRING_LEN;
- num_strings++;
- break;
- case IPV4_FLOW:
- sprintf(p, "\tSrc IP addr: 0x%x\n",
- fsc->fs.h_u.usr_ip4_spec.ip4src);
- p += ETH_GSTRING_LEN;
- num_strings++;
- sprintf(p, "\tSrc IP mask: 0x%x\n",
- fsc->fs.m_u.usr_ip4_spec.ip4src);
- p += ETH_GSTRING_LEN;
- num_strings++;
- sprintf(p, "\tDest IP addr: 0x%x\n",
- fsc->fs.h_u.usr_ip4_spec.ip4dst);
- p += ETH_GSTRING_LEN;
- num_strings++;
- sprintf(p, "\tDest IP mask: 0x%x\n",
- fsc->fs.m_u.usr_ip4_spec.ip4dst);
- p += ETH_GSTRING_LEN;
- num_strings++;
- sprintf(p, "\tL4 bytes: 0x%x, mask: 0x%x\n",
- fsc->fs.h_u.usr_ip4_spec.l4_4_bytes,
- fsc->fs.m_u.usr_ip4_spec.l4_4_bytes);
- p += ETH_GSTRING_LEN;
- num_strings++;
- sprintf(p, "\tTOS: %d, mask: 0x%x\n",
- fsc->fs.h_u.usr_ip4_spec.tos,
- fsc->fs.m_u.usr_ip4_spec.tos);
- p += ETH_GSTRING_LEN;
- num_strings++;
- sprintf(p, "\tIP Version: %d, mask: 0x%x\n",
- fsc->fs.h_u.usr_ip4_spec.ip_ver,
- fsc->fs.m_u.usr_ip4_spec.ip_ver);
- p += ETH_GSTRING_LEN;
- num_strings++;
- sprintf(p, "\tProtocol: %d, mask: 0x%x\n",
- fsc->fs.h_u.usr_ip4_spec.proto,
- fsc->fs.m_u.usr_ip4_spec.proto);
- p += ETH_GSTRING_LEN;
- num_strings++;
- break;
- }
- sprintf(p, "\tVLAN: %d, mask: 0x%x\n",
- fsc->fs.vlan_tag, fsc->fs.vlan_tag_mask);
- p += ETH_GSTRING_LEN;
- num_strings++;
- sprintf(p, "\tUser-defined: 0x%Lx\n", fsc->fs.data);
- p += ETH_GSTRING_LEN;
- num_strings++;
- sprintf(p, "\tUser-defined mask: 0x%Lx\n", fsc->fs.data_mask);
- p += ETH_GSTRING_LEN;
- num_strings++;
- if (fsc->fs.action == ETHTOOL_RXNTUPLE_ACTION_DROP)
- sprintf(p, "\tAction: Drop\n");
- else
- sprintf(p, "\tAction: Direct to queue %d\n",
- fsc->fs.action);
- p += ETH_GSTRING_LEN;
- num_strings++;
-unknown_filter:
- i++;
- }
-copy:
- /* indicate to userspace how many strings we actually have */
- gstrings.len = num_strings;
- ret = -EFAULT;
- if (copy_to_user(useraddr, &gstrings, sizeof(gstrings)))
- goto out;
- useraddr += sizeof(gstrings);
- if (copy_to_user(useraddr, data, gstrings.len * ETH_GSTRING_LEN))
- goto out;
- ret = 0;
-
-out:
- kfree(data);
- return ret;
+ return ops->set_rx_ntuple(dev, &cmd);
}
static int ethtool_get_regs(struct net_device *dev, char __user *useraddr)
@@ -2101,9 +1797,6 @@
case ETHTOOL_SRXNTUPLE:
rc = ethtool_set_rx_ntuple(dev, useraddr);
break;
- case ETHTOOL_GRXNTUPLE:
- rc = ethtool_get_rx_ntuple(dev, useraddr);
- break;
case ETHTOOL_GSSET_INFO:
rc = ethtool_get_sset_info(dev, useraddr);
break;
diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c
index 008dc70..e7ab0c0 100644
--- a/net/core/fib_rules.c
+++ b/net/core/fib_rules.c
@@ -740,9 +740,9 @@
static int __init fib_rules_init(void)
{
int err;
- rtnl_register(PF_UNSPEC, RTM_NEWRULE, fib_nl_newrule, NULL);
- rtnl_register(PF_UNSPEC, RTM_DELRULE, fib_nl_delrule, NULL);
- rtnl_register(PF_UNSPEC, RTM_GETRULE, NULL, fib_nl_dumprule);
+ rtnl_register(PF_UNSPEC, RTM_NEWRULE, fib_nl_newrule, NULL, NULL);
+ rtnl_register(PF_UNSPEC, RTM_DELRULE, fib_nl_delrule, NULL, NULL);
+ rtnl_register(PF_UNSPEC, RTM_GETRULE, NULL, fib_nl_dumprule, NULL);
err = register_pernet_subsys(&fib_rules_net_ops);
if (err < 0)
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index 799f06e..ceb505b 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -2909,12 +2909,13 @@
static int __init neigh_init(void)
{
- rtnl_register(PF_UNSPEC, RTM_NEWNEIGH, neigh_add, NULL);
- rtnl_register(PF_UNSPEC, RTM_DELNEIGH, neigh_delete, NULL);
- rtnl_register(PF_UNSPEC, RTM_GETNEIGH, NULL, neigh_dump_info);
+ rtnl_register(PF_UNSPEC, RTM_NEWNEIGH, neigh_add, NULL, NULL);
+ rtnl_register(PF_UNSPEC, RTM_DELNEIGH, neigh_delete, NULL, NULL);
+ rtnl_register(PF_UNSPEC, RTM_GETNEIGH, NULL, neigh_dump_info, NULL);
- rtnl_register(PF_UNSPEC, RTM_GETNEIGHTBL, NULL, neightbl_dump_info);
- rtnl_register(PF_UNSPEC, RTM_SETNEIGHTBL, neightbl_set, NULL);
+ rtnl_register(PF_UNSPEC, RTM_GETNEIGHTBL, NULL, neightbl_dump_info,
+ NULL);
+ rtnl_register(PF_UNSPEC, RTM_SETNEIGHTBL, neightbl_set, NULL, NULL);
return 0;
}
diff --git a/net/core/net-traces.c b/net/core/net-traces.c
index 7f1bb2a..52380b1 100644
--- a/net/core/net-traces.c
+++ b/net/core/net-traces.c
@@ -28,6 +28,8 @@
#include <trace/events/skb.h>
#include <trace/events/net.h>
#include <trace/events/napi.h>
+#include <trace/events/sock.h>
+#include <trace/events/udp.h>
EXPORT_TRACEPOINT_SYMBOL_GPL(kfree_skb);
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
index ea489db..5bbdbf0 100644
--- a/net/core/net_namespace.c
+++ b/net/core/net_namespace.c
@@ -129,6 +129,7 @@
atomic_set(&net->count, 1);
atomic_set(&net->passive, 1);
+ net->dev_base_seq = 1;
#ifdef NETNS_REFCNT_DEBUG
atomic_set(&net->use_count, 0);
diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index 18d9cbd..adf84dd 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -177,7 +177,7 @@
}
}
-void netpoll_poll_dev(struct net_device *dev)
+static void netpoll_poll_dev(struct net_device *dev)
{
const struct net_device_ops *ops;
@@ -208,13 +208,6 @@
zap_completion_queue();
}
-EXPORT_SYMBOL(netpoll_poll_dev);
-
-void netpoll_poll(struct netpoll *np)
-{
- netpoll_poll_dev(np->dev);
-}
-EXPORT_SYMBOL(netpoll_poll);
static void refill_skbs(void)
{
@@ -275,7 +268,7 @@
if (!skb) {
if (++count < 10) {
- netpoll_poll(np);
+ netpoll_poll_dev(np->dev);
goto repeat;
}
return NULL;
@@ -336,7 +329,7 @@
}
/* tickle device maybe there is some cleanup */
- netpoll_poll(np);
+ netpoll_poll_dev(np->dev);
udelay(USEC_PER_POLL);
}
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index abd936d..99d9e95 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -56,9 +56,11 @@
struct rtnl_link {
rtnl_doit_func doit;
rtnl_dumpit_func dumpit;
+ rtnl_calcit_func calcit;
};
static DEFINE_MUTEX(rtnl_mutex);
+static u16 min_ifinfo_dump_size;
void rtnl_lock(void)
{
@@ -144,12 +146,28 @@
return tab ? tab[msgindex].dumpit : NULL;
}
+static rtnl_calcit_func rtnl_get_calcit(int protocol, int msgindex)
+{
+ struct rtnl_link *tab;
+
+ if (protocol <= RTNL_FAMILY_MAX)
+ tab = rtnl_msg_handlers[protocol];
+ else
+ tab = NULL;
+
+ if (tab == NULL || tab[msgindex].calcit == NULL)
+ tab = rtnl_msg_handlers[PF_UNSPEC];
+
+ return tab ? tab[msgindex].calcit : NULL;
+}
+
/**
* __rtnl_register - Register a rtnetlink message type
* @protocol: Protocol family or PF_UNSPEC
* @msgtype: rtnetlink message type
* @doit: Function pointer called for each request message
* @dumpit: Function pointer called for each dump request (NLM_F_DUMP) message
+ * @calcit: Function pointer to calc size of dump message
*
* Registers the specified function pointers (at least one of them has
* to be non-NULL) to be called whenever a request message for the
@@ -162,7 +180,8 @@
* Returns 0 on success or a negative error code.
*/
int __rtnl_register(int protocol, int msgtype,
- rtnl_doit_func doit, rtnl_dumpit_func dumpit)
+ rtnl_doit_func doit, rtnl_dumpit_func dumpit,
+ rtnl_calcit_func calcit)
{
struct rtnl_link *tab;
int msgindex;
@@ -185,6 +204,9 @@
if (dumpit)
tab[msgindex].dumpit = dumpit;
+ if (calcit)
+ tab[msgindex].calcit = calcit;
+
return 0;
}
EXPORT_SYMBOL_GPL(__rtnl_register);
@@ -199,9 +221,10 @@
* of memory implies no sense in continuing.
*/
void rtnl_register(int protocol, int msgtype,
- rtnl_doit_func doit, rtnl_dumpit_func dumpit)
+ rtnl_doit_func doit, rtnl_dumpit_func dumpit,
+ rtnl_calcit_func calcit)
{
- if (__rtnl_register(protocol, msgtype, doit, dumpit) < 0)
+ if (__rtnl_register(protocol, msgtype, doit, dumpit, calcit) < 0)
panic("Unable to register rtnetlink message handler, "
"protocol = %d, message type = %d\n",
protocol, msgtype);
@@ -1009,6 +1032,8 @@
s_idx = cb->args[1];
rcu_read_lock();
+ cb->seq = net->dev_base_seq;
+
for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) {
idx = 0;
head = &net->dev_index_head[h];
@@ -1020,6 +1045,8 @@
cb->nlh->nlmsg_seq, 0,
NLM_F_MULTI) <= 0)
goto out;
+
+ nl_dump_check_consistent(cb, nlmsg_hdr(skb));
cont:
idx++;
}
@@ -1818,6 +1845,11 @@
return err;
}
+static u16 rtnl_calcit(struct sk_buff *skb)
+{
+ return min_ifinfo_dump_size;
+}
+
static int rtnl_dump_all(struct sk_buff *skb, struct netlink_callback *cb)
{
int idx;
@@ -1847,11 +1879,14 @@
struct net *net = dev_net(dev);
struct sk_buff *skb;
int err = -ENOBUFS;
+ size_t if_info_size;
- skb = nlmsg_new(if_nlmsg_size(dev), GFP_KERNEL);
+ skb = nlmsg_new((if_info_size = if_nlmsg_size(dev)), GFP_KERNEL);
if (skb == NULL)
goto errout;
+ min_ifinfo_dump_size = max_t(u16, if_info_size, min_ifinfo_dump_size);
+
err = rtnl_fill_ifinfo(skb, dev, type, 0, 0, change, 0);
if (err < 0) {
/* -EMSGSIZE implies BUG in if_nlmsg_size() */
@@ -1902,14 +1937,20 @@
if (kind == 2 && nlh->nlmsg_flags&NLM_F_DUMP) {
struct sock *rtnl;
rtnl_dumpit_func dumpit;
+ rtnl_calcit_func calcit;
+ u16 min_dump_alloc = 0;
dumpit = rtnl_get_dumpit(family, type);
if (dumpit == NULL)
return -EOPNOTSUPP;
+ calcit = rtnl_get_calcit(family, type);
+ if (calcit)
+ min_dump_alloc = calcit(skb);
__rtnl_unlock();
rtnl = net->rtnl;
- err = netlink_dump_start(rtnl, skb, nlh, dumpit, NULL);
+ err = netlink_dump_start(rtnl, skb, nlh, dumpit,
+ NULL, min_dump_alloc);
rtnl_lock();
return err;
}
@@ -2019,12 +2060,13 @@
netlink_set_nonroot(NETLINK_ROUTE, NL_NONROOT_RECV);
register_netdevice_notifier(&rtnetlink_dev_notifier);
- rtnl_register(PF_UNSPEC, RTM_GETLINK, rtnl_getlink, rtnl_dump_ifinfo);
- rtnl_register(PF_UNSPEC, RTM_SETLINK, rtnl_setlink, NULL);
- rtnl_register(PF_UNSPEC, RTM_NEWLINK, rtnl_newlink, NULL);
- rtnl_register(PF_UNSPEC, RTM_DELLINK, rtnl_dellink, NULL);
+ rtnl_register(PF_UNSPEC, RTM_GETLINK, rtnl_getlink,
+ rtnl_dump_ifinfo, rtnl_calcit);
+ rtnl_register(PF_UNSPEC, RTM_SETLINK, rtnl_setlink, NULL, NULL);
+ rtnl_register(PF_UNSPEC, RTM_NEWLINK, rtnl_newlink, NULL, NULL);
+ rtnl_register(PF_UNSPEC, RTM_DELLINK, rtnl_dellink, NULL, NULL);
- rtnl_register(PF_UNSPEC, RTM_GETADDR, NULL, rtnl_dump_all);
- rtnl_register(PF_UNSPEC, RTM_GETROUTE, NULL, rtnl_dump_all);
+ rtnl_register(PF_UNSPEC, RTM_GETADDR, NULL, rtnl_dump_all, NULL);
+ rtnl_register(PF_UNSPEC, RTM_GETROUTE, NULL, rtnl_dump_all, NULL);
}
diff --git a/net/core/sock.c b/net/core/sock.c
index 6e81978..76c4031 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -128,6 +128,8 @@
#include <linux/filter.h>
+#include <trace/events/sock.h>
+
#ifdef CONFIG_INET
#include <net/tcp.h>
#endif
@@ -292,6 +294,7 @@
if (atomic_read(&sk->sk_rmem_alloc) + skb->truesize >=
(unsigned)sk->sk_rcvbuf) {
atomic_inc(&sk->sk_drops);
+ trace_sock_rcvqueue_full(sk, skb);
return -ENOMEM;
}
@@ -1736,6 +1739,8 @@
return 1;
}
+ trace_sock_exceed_buf_limit(sk, prot, allocated);
+
/* Alas. Undo changes. */
sk->sk_forward_alloc -= amt * SK_MEM_QUANTUM;
atomic_long_sub(amt, prot->memory_allocated);
diff --git a/net/core/timestamping.c b/net/core/timestamping.c
index 7e7ca37..98a5264 100644
--- a/net/core/timestamping.c
+++ b/net/core/timestamping.c
@@ -68,6 +68,7 @@
break;
}
}
+EXPORT_SYMBOL_GPL(skb_clone_tx_timestamp);
void skb_complete_tx_timestamp(struct sk_buff *skb,
struct skb_shared_hwtstamps *hwtstamps)
@@ -121,6 +122,7 @@
return false;
}
+EXPORT_SYMBOL_GPL(skb_defer_rx_timestamp);
void __init skb_timestamping_init(void)
{
diff --git a/net/dcb/dcbnl.c b/net/dcb/dcbnl.c
index 3609eac..fc56e85 100644
--- a/net/dcb/dcbnl.c
+++ b/net/dcb/dcbnl.c
@@ -1166,64 +1166,6 @@
return ret;
}
-/* Handle IEEE 802.1Qaz SET commands. If any requested operation can not
- * be completed the entire msg is aborted and error value is returned.
- * No attempt is made to reconcile the case where only part of the
- * cmd can be completed.
- */
-static int dcbnl_ieee_set(struct net_device *netdev, struct nlattr **tb,
- u32 pid, u32 seq, u16 flags)
-{
- const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops;
- struct nlattr *ieee[DCB_ATTR_IEEE_MAX + 1];
- int err = -EOPNOTSUPP;
-
- if (!ops)
- goto err;
-
- err = nla_parse_nested(ieee, DCB_ATTR_IEEE_MAX,
- tb[DCB_ATTR_IEEE], dcbnl_ieee_policy);
- if (err)
- goto err;
-
- if (ieee[DCB_ATTR_IEEE_ETS] && ops->ieee_setets) {
- struct ieee_ets *ets = nla_data(ieee[DCB_ATTR_IEEE_ETS]);
- err = ops->ieee_setets(netdev, ets);
- if (err)
- goto err;
- }
-
- if (ieee[DCB_ATTR_IEEE_PFC] && ops->ieee_setpfc) {
- struct ieee_pfc *pfc = nla_data(ieee[DCB_ATTR_IEEE_PFC]);
- err = ops->ieee_setpfc(netdev, pfc);
- if (err)
- goto err;
- }
-
- if (ieee[DCB_ATTR_IEEE_APP_TABLE]) {
- struct nlattr *attr;
- int rem;
-
- nla_for_each_nested(attr, ieee[DCB_ATTR_IEEE_APP_TABLE], rem) {
- struct dcb_app *app_data;
- if (nla_type(attr) != DCB_ATTR_IEEE_APP)
- continue;
- app_data = nla_data(attr);
- if (ops->ieee_setapp)
- err = ops->ieee_setapp(netdev, app_data);
- else
- err = dcb_setapp(netdev, app_data);
- if (err)
- goto err;
- }
- }
-
-err:
- dcbnl_reply(err, RTM_SETDCB, DCB_CMD_IEEE_SET, DCB_ATTR_IEEE,
- pid, seq, flags);
- return err;
-}
-
static int dcbnl_build_peer_app(struct net_device *netdev, struct sk_buff* skb,
int app_nested_type, int app_info_type,
int app_entry_type)
@@ -1279,29 +1221,13 @@
}
/* Handle IEEE 802.1Qaz GET commands. */
-static int dcbnl_ieee_get(struct net_device *netdev, struct nlattr **tb,
- u32 pid, u32 seq, u16 flags)
+static int dcbnl_ieee_fill(struct sk_buff *skb, struct net_device *netdev)
{
- struct sk_buff *skb;
- struct nlmsghdr *nlh;
- struct dcbmsg *dcb;
struct nlattr *ieee, *app;
struct dcb_app_type *itr;
const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops;
- int err;
-
- if (!ops)
- return -EOPNOTSUPP;
-
- skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
- if (!skb)
- return -ENOBUFS;
-
- nlh = NLMSG_NEW(skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags);
-
- dcb = NLMSG_DATA(nlh);
- dcb->dcb_family = AF_UNSPEC;
- dcb->cmd = DCB_CMD_IEEE_GET;
+ int dcbx;
+ int err = -EMSGSIZE;
NLA_PUT_STRING(skb, DCB_ATTR_IFNAME, netdev->name);
@@ -1338,6 +1264,12 @@
}
}
}
+
+ if (netdev->dcbnl_ops->getdcbx)
+ dcbx = netdev->dcbnl_ops->getdcbx(netdev);
+ else
+ dcbx = -EOPNOTSUPP;
+
spin_unlock(&dcb_lock);
nla_nest_end(skb, app);
@@ -1366,16 +1298,208 @@
}
nla_nest_end(skb, ieee);
- nlmsg_end(skb, nlh);
+ if (dcbx >= 0) {
+ err = nla_put_u8(skb, DCB_ATTR_DCBX, dcbx);
+ if (err)
+ goto nla_put_failure;
+ }
- return rtnl_unicast(skb, &init_net, pid);
+ return 0;
+
nla_put_failure:
- nlmsg_cancel(skb, nlh);
-nlmsg_failure:
- kfree_skb(skb);
- return -1;
+ return err;
}
+int dcbnl_notify(struct net_device *dev, int event, int cmd,
+ u32 seq, u32 pid)
+{
+ struct net *net = dev_net(dev);
+ struct sk_buff *skb;
+ struct nlmsghdr *nlh;
+ struct dcbmsg *dcb;
+ const struct dcbnl_rtnl_ops *ops = dev->dcbnl_ops;
+ int err;
+
+ if (!ops)
+ return -EOPNOTSUPP;
+
+ skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
+ if (!skb)
+ return -ENOBUFS;
+
+ nlh = nlmsg_put(skb, pid, 0, event, sizeof(*dcb), 0);
+ if (nlh == NULL) {
+ nlmsg_free(skb);
+ return -EMSGSIZE;
+ }
+
+ dcb = NLMSG_DATA(nlh);
+ dcb->dcb_family = AF_UNSPEC;
+ dcb->cmd = cmd;
+
+ err = dcbnl_ieee_fill(skb, dev);
+ if (err < 0) {
+ /* Report error to broadcast listeners */
+ nlmsg_cancel(skb, nlh);
+ kfree_skb(skb);
+ rtnl_set_sk_err(net, RTNLGRP_DCB, err);
+ } else {
+ /* End nlmsg and notify broadcast listeners */
+ nlmsg_end(skb, nlh);
+ rtnl_notify(skb, net, 0, RTNLGRP_DCB, NULL, GFP_KERNEL);
+ }
+
+ return err;
+}
+EXPORT_SYMBOL(dcbnl_notify);
+
+/* Handle IEEE 802.1Qaz SET commands. If any requested operation can not
+ * be completed the entire msg is aborted and error value is returned.
+ * No attempt is made to reconcile the case where only part of the
+ * cmd can be completed.
+ */
+static int dcbnl_ieee_set(struct net_device *netdev, struct nlattr **tb,
+ u32 pid, u32 seq, u16 flags)
+{
+ const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops;
+ struct nlattr *ieee[DCB_ATTR_IEEE_MAX + 1];
+ int err = -EOPNOTSUPP;
+
+ if (!ops)
+ return err;
+
+ if (!tb[DCB_ATTR_IEEE])
+ return -EINVAL;
+
+ err = nla_parse_nested(ieee, DCB_ATTR_IEEE_MAX,
+ tb[DCB_ATTR_IEEE], dcbnl_ieee_policy);
+ if (err)
+ return err;
+
+ if (ieee[DCB_ATTR_IEEE_ETS] && ops->ieee_setets) {
+ struct ieee_ets *ets = nla_data(ieee[DCB_ATTR_IEEE_ETS]);
+ err = ops->ieee_setets(netdev, ets);
+ if (err)
+ goto err;
+ }
+
+ if (ieee[DCB_ATTR_IEEE_PFC] && ops->ieee_setpfc) {
+ struct ieee_pfc *pfc = nla_data(ieee[DCB_ATTR_IEEE_PFC]);
+ err = ops->ieee_setpfc(netdev, pfc);
+ if (err)
+ goto err;
+ }
+
+ if (ieee[DCB_ATTR_IEEE_APP_TABLE]) {
+ struct nlattr *attr;
+ int rem;
+
+ nla_for_each_nested(attr, ieee[DCB_ATTR_IEEE_APP_TABLE], rem) {
+ struct dcb_app *app_data;
+ if (nla_type(attr) != DCB_ATTR_IEEE_APP)
+ continue;
+ app_data = nla_data(attr);
+ if (ops->ieee_setapp)
+ err = ops->ieee_setapp(netdev, app_data);
+ else
+ err = dcb_ieee_setapp(netdev, app_data);
+ if (err)
+ goto err;
+ }
+ }
+
+err:
+ dcbnl_reply(err, RTM_SETDCB, DCB_CMD_IEEE_SET, DCB_ATTR_IEEE,
+ pid, seq, flags);
+ dcbnl_notify(netdev, RTM_SETDCB, DCB_CMD_IEEE_SET, seq, 0);
+ return err;
+}
+
+static int dcbnl_ieee_get(struct net_device *netdev, struct nlattr **tb,
+ u32 pid, u32 seq, u16 flags)
+{
+ struct net *net = dev_net(netdev);
+ struct sk_buff *skb;
+ struct nlmsghdr *nlh;
+ struct dcbmsg *dcb;
+ const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops;
+ int err;
+
+ if (!ops)
+ return -EOPNOTSUPP;
+
+ skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
+ if (!skb)
+ return -ENOBUFS;
+
+ nlh = nlmsg_put(skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags);
+ if (nlh == NULL) {
+ nlmsg_free(skb);
+ return -EMSGSIZE;
+ }
+
+ dcb = NLMSG_DATA(nlh);
+ dcb->dcb_family = AF_UNSPEC;
+ dcb->cmd = DCB_CMD_IEEE_GET;
+
+ err = dcbnl_ieee_fill(skb, netdev);
+
+ if (err < 0) {
+ nlmsg_cancel(skb, nlh);
+ kfree_skb(skb);
+ } else {
+ nlmsg_end(skb, nlh);
+ err = rtnl_unicast(skb, net, pid);
+ }
+
+ return err;
+}
+
+static int dcbnl_ieee_del(struct net_device *netdev, struct nlattr **tb,
+ u32 pid, u32 seq, u16 flags)
+{
+ const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops;
+ struct nlattr *ieee[DCB_ATTR_IEEE_MAX + 1];
+ int err = -EOPNOTSUPP;
+
+ if (!ops)
+ return -EOPNOTSUPP;
+
+ if (!tb[DCB_ATTR_IEEE])
+ return -EINVAL;
+
+ err = nla_parse_nested(ieee, DCB_ATTR_IEEE_MAX,
+ tb[DCB_ATTR_IEEE], dcbnl_ieee_policy);
+ if (err)
+ return err;
+
+ if (ieee[DCB_ATTR_IEEE_APP_TABLE]) {
+ struct nlattr *attr;
+ int rem;
+
+ nla_for_each_nested(attr, ieee[DCB_ATTR_IEEE_APP_TABLE], rem) {
+ struct dcb_app *app_data;
+
+ if (nla_type(attr) != DCB_ATTR_IEEE_APP)
+ continue;
+ app_data = nla_data(attr);
+ if (ops->ieee_delapp)
+ err = ops->ieee_delapp(netdev, app_data);
+ else
+ err = dcb_ieee_delapp(netdev, app_data);
+ if (err)
+ goto err;
+ }
+ }
+
+err:
+ dcbnl_reply(err, RTM_SETDCB, DCB_CMD_IEEE_DEL, DCB_ATTR_IEEE,
+ pid, seq, flags);
+ dcbnl_notify(netdev, RTM_SETDCB, DCB_CMD_IEEE_DEL, seq, 0);
+ return err;
+}
+
+
/* DCBX configuration */
static int dcbnl_getdcbx(struct net_device *netdev, struct nlattr **tb,
u32 pid, u32 seq, u16 flags)
@@ -1690,11 +1814,15 @@
goto out;
case DCB_CMD_IEEE_SET:
ret = dcbnl_ieee_set(netdev, tb, pid, nlh->nlmsg_seq,
- nlh->nlmsg_flags);
+ nlh->nlmsg_flags);
goto out;
case DCB_CMD_IEEE_GET:
ret = dcbnl_ieee_get(netdev, tb, pid, nlh->nlmsg_seq,
- nlh->nlmsg_flags);
+ nlh->nlmsg_flags);
+ goto out;
+ case DCB_CMD_IEEE_DEL:
+ ret = dcbnl_ieee_del(netdev, tb, pid, nlh->nlmsg_seq,
+ nlh->nlmsg_flags);
goto out;
case DCB_CMD_GDCBX:
ret = dcbnl_getdcbx(netdev, tb, pid, nlh->nlmsg_seq,
@@ -1754,12 +1882,13 @@
EXPORT_SYMBOL(dcb_getapp);
/**
- * ixgbe_dcbnl_setapp - add dcb application data to app list
+ * dcb_setapp - add CEE dcb application data to app list
*
- * Priority 0 is the default priority this removes applications
- * from the app list if the priority is set to zero.
+ * Priority 0 is an invalid priority in CEE spec. This routine
+ * removes applications from the app list if the priority is
+ * set to zero.
*/
-u8 dcb_setapp(struct net_device *dev, struct dcb_app *new)
+int dcb_setapp(struct net_device *dev, struct dcb_app *new)
{
struct dcb_app_type *itr;
struct dcb_app_type event;
@@ -1802,6 +1931,114 @@
}
EXPORT_SYMBOL(dcb_setapp);
+/**
+ * dcb_ieee_getapp_mask - retrieve the IEEE DCB application priority
+ *
+ * Helper routine which on success returns a non-zero 802.1Qaz user
+ * priority bitmap otherwise returns 0 to indicate the dcb_app was
+ * not found in APP list.
+ */
+u8 dcb_ieee_getapp_mask(struct net_device *dev, struct dcb_app *app)
+{
+ struct dcb_app_type *itr;
+ u8 prio = 0;
+
+ spin_lock(&dcb_lock);
+ list_for_each_entry(itr, &dcb_app_list, list) {
+ if (itr->app.selector == app->selector &&
+ itr->app.protocol == app->protocol &&
+ (strncmp(itr->name, dev->name, IFNAMSIZ) == 0)) {
+ prio |= 1 << itr->app.priority;
+ }
+ }
+ spin_unlock(&dcb_lock);
+
+ return prio;
+}
+EXPORT_SYMBOL(dcb_ieee_getapp_mask);
+
+/**
+ * dcb_ieee_setapp - add IEEE dcb application data to app list
+ *
+ * This adds Application data to the list. Multiple application
+ * entries may exists for the same selector and protocol as long
+ * as the priorities are different.
+ */
+int dcb_ieee_setapp(struct net_device *dev, struct dcb_app *new)
+{
+ struct dcb_app_type *itr, *entry;
+ struct dcb_app_type event;
+ int err = 0;
+
+ memcpy(&event.name, dev->name, sizeof(event.name));
+ memcpy(&event.app, new, sizeof(event.app));
+
+ spin_lock(&dcb_lock);
+ /* Search for existing match and abort if found */
+ list_for_each_entry(itr, &dcb_app_list, list) {
+ if (itr->app.selector == new->selector &&
+ itr->app.protocol == new->protocol &&
+ itr->app.priority == new->priority &&
+ (strncmp(itr->name, dev->name, IFNAMSIZ) == 0)) {
+ err = -EEXIST;
+ goto out;
+ }
+ }
+
+ /* App entry does not exist add new entry */
+ entry = kmalloc(sizeof(struct dcb_app_type), GFP_ATOMIC);
+ if (!entry) {
+ err = -ENOMEM;
+ goto out;
+ }
+
+ memcpy(&entry->app, new, sizeof(*new));
+ strncpy(entry->name, dev->name, IFNAMSIZ);
+ list_add(&entry->list, &dcb_app_list);
+out:
+ spin_unlock(&dcb_lock);
+ if (!err)
+ call_dcbevent_notifiers(DCB_APP_EVENT, &event);
+ return err;
+}
+EXPORT_SYMBOL(dcb_ieee_setapp);
+
+/**
+ * dcb_ieee_delapp - delete IEEE dcb application data from list
+ *
+ * This removes a matching APP data from the APP list
+ */
+int dcb_ieee_delapp(struct net_device *dev, struct dcb_app *del)
+{
+ struct dcb_app_type *itr;
+ struct dcb_app_type event;
+ int err = -ENOENT;
+
+ memcpy(&event.name, dev->name, sizeof(event.name));
+ memcpy(&event.app, del, sizeof(event.app));
+
+ spin_lock(&dcb_lock);
+ /* Search for existing match and remove it. */
+ list_for_each_entry(itr, &dcb_app_list, list) {
+ if (itr->app.selector == del->selector &&
+ itr->app.protocol == del->protocol &&
+ itr->app.priority == del->priority &&
+ (strncmp(itr->name, dev->name, IFNAMSIZ) == 0)) {
+ list_del(&itr->list);
+ kfree(itr);
+ err = 0;
+ goto out;
+ }
+ }
+
+out:
+ spin_unlock(&dcb_lock);
+ if (!err)
+ call_dcbevent_notifiers(DCB_APP_EVENT, &event);
+ return err;
+}
+EXPORT_SYMBOL(dcb_ieee_delapp);
+
static void dcb_flushapp(void)
{
struct dcb_app_type *app;
@@ -1819,8 +2056,8 @@
{
INIT_LIST_HEAD(&dcb_app_list);
- rtnl_register(PF_UNSPEC, RTM_GETDCB, dcb_doit, NULL);
- rtnl_register(PF_UNSPEC, RTM_SETDCB, dcb_doit, NULL);
+ rtnl_register(PF_UNSPEC, RTM_GETDCB, dcb_doit, NULL, NULL);
+ rtnl_register(PF_UNSPEC, RTM_SETDCB, dcb_doit, NULL, NULL);
return 0;
}
diff --git a/net/dccp/ccid.c b/net/dccp/ccid.c
index 36479ca..48b585a 100644
--- a/net/dccp/ccid.c
+++ b/net/dccp/ccid.c
@@ -118,7 +118,7 @@
if (ccid_ops->ccid_hc_tx_slab == NULL)
goto out_free_rx_slab;
- pr_info("CCID: Activated CCID %d (%s)\n",
+ pr_info("DCCP: Activated CCID %d (%s)\n",
ccid_ops->ccid_id, ccid_ops->ccid_name);
err = 0;
out:
@@ -136,7 +136,7 @@
ccid_kmem_cache_destroy(ccid_ops->ccid_hc_rx_slab);
ccid_ops->ccid_hc_rx_slab = NULL;
- pr_info("CCID: Deactivated CCID %d (%s)\n",
+ pr_info("DCCP: Deactivated CCID %d (%s)\n",
ccid_ops->ccid_id, ccid_ops->ccid_name);
}
diff --git a/net/dccp/ccids/ccid2.c b/net/dccp/ccids/ccid2.c
index fadecd2..0462040 100644
--- a/net/dccp/ccids/ccid2.c
+++ b/net/dccp/ccids/ccid2.c
@@ -153,17 +153,93 @@
sock_put(sk);
}
+/*
+ * Congestion window validation (RFC 2861).
+ */
+static int ccid2_do_cwv = 1;
+module_param(ccid2_do_cwv, bool, 0644);
+MODULE_PARM_DESC(ccid2_do_cwv, "Perform RFC2861 Congestion Window Validation");
+
+/**
+ * ccid2_update_used_window - Track how much of cwnd is actually used
+ * This is done in addition to CWV. The sender needs to have an idea of how many
+ * packets may be in flight, to set the local Sequence Window value accordingly
+ * (RFC 4340, 7.5.2). The CWV mechanism is exploited to keep track of the
+ * maximum-used window. We use an EWMA low-pass filter to filter out noise.
+ */
+static void ccid2_update_used_window(struct ccid2_hc_tx_sock *hc, u32 new_wnd)
+{
+ hc->tx_expected_wnd = (3 * hc->tx_expected_wnd + new_wnd) / 4;
+}
+
+/* This borrows the code of tcp_cwnd_application_limited() */
+static void ccid2_cwnd_application_limited(struct sock *sk, const u32 now)
+{
+ struct ccid2_hc_tx_sock *hc = ccid2_hc_tx_sk(sk);
+ /* don't reduce cwnd below the initial window (IW) */
+ u32 init_win = rfc3390_bytes_to_packets(dccp_sk(sk)->dccps_mss_cache),
+ win_used = max(hc->tx_cwnd_used, init_win);
+
+ if (win_used < hc->tx_cwnd) {
+ hc->tx_ssthresh = max(hc->tx_ssthresh,
+ (hc->tx_cwnd >> 1) + (hc->tx_cwnd >> 2));
+ hc->tx_cwnd = (hc->tx_cwnd + win_used) >> 1;
+ }
+ hc->tx_cwnd_used = 0;
+ hc->tx_cwnd_stamp = now;
+}
+
+/* This borrows the code of tcp_cwnd_restart() */
+static void ccid2_cwnd_restart(struct sock *sk, const u32 now)
+{
+ struct ccid2_hc_tx_sock *hc = ccid2_hc_tx_sk(sk);
+ u32 cwnd = hc->tx_cwnd, restart_cwnd,
+ iwnd = rfc3390_bytes_to_packets(dccp_sk(sk)->dccps_mss_cache);
+
+ hc->tx_ssthresh = max(hc->tx_ssthresh, (cwnd >> 1) + (cwnd >> 2));
+
+ /* don't reduce cwnd below the initial window (IW) */
+ restart_cwnd = min(cwnd, iwnd);
+ cwnd >>= (now - hc->tx_lsndtime) / hc->tx_rto;
+ hc->tx_cwnd = max(cwnd, restart_cwnd);
+
+ hc->tx_cwnd_stamp = now;
+ hc->tx_cwnd_used = 0;
+}
+
static void ccid2_hc_tx_packet_sent(struct sock *sk, unsigned int len)
{
struct dccp_sock *dp = dccp_sk(sk);
struct ccid2_hc_tx_sock *hc = ccid2_hc_tx_sk(sk);
+ const u32 now = ccid2_time_stamp;
struct ccid2_seq *next;
- hc->tx_pipe++;
+ /* slow-start after idle periods (RFC 2581, RFC 2861) */
+ if (ccid2_do_cwv && !hc->tx_pipe &&
+ (s32)(now - hc->tx_lsndtime) >= hc->tx_rto)
+ ccid2_cwnd_restart(sk, now);
+
+ hc->tx_lsndtime = now;
+ hc->tx_pipe += 1;
+
+ /* see whether cwnd was fully used (RFC 2861), update expected window */
+ if (ccid2_cwnd_network_limited(hc)) {
+ ccid2_update_used_window(hc, hc->tx_cwnd);
+ hc->tx_cwnd_used = 0;
+ hc->tx_cwnd_stamp = now;
+ } else {
+ if (hc->tx_pipe > hc->tx_cwnd_used)
+ hc->tx_cwnd_used = hc->tx_pipe;
+
+ ccid2_update_used_window(hc, hc->tx_cwnd_used);
+
+ if (ccid2_do_cwv && (s32)(now - hc->tx_cwnd_stamp) >= hc->tx_rto)
+ ccid2_cwnd_application_limited(sk, now);
+ }
hc->tx_seqh->ccid2s_seq = dp->dccps_gss;
hc->tx_seqh->ccid2s_acked = 0;
- hc->tx_seqh->ccid2s_sent = ccid2_time_stamp;
+ hc->tx_seqh->ccid2s_sent = now;
next = hc->tx_seqh->ccid2s_next;
/* check if we need to alloc more space */
@@ -583,15 +659,6 @@
dccp_ackvec_parsed_cleanup(&hc->tx_av_chunks);
}
-/*
- * Convert RFC 3390 larger initial window into an equivalent number of packets.
- * This is based on the numbers specified in RFC 5681, 3.1.
- */
-static inline u32 rfc3390_bytes_to_packets(const u32 smss)
-{
- return smss <= 1095 ? 4 : (smss > 2190 ? 2 : 3);
-}
-
static int ccid2_hc_tx_init(struct ccid *ccid, struct sock *sk)
{
struct ccid2_hc_tx_sock *hc = ccid_priv(ccid);
@@ -603,6 +670,7 @@
/* Use larger initial windows (RFC 4341, section 5). */
hc->tx_cwnd = rfc3390_bytes_to_packets(dp->dccps_mss_cache);
+ hc->tx_expected_wnd = hc->tx_cwnd;
/* Make sure that Ack Ratio is enabled and within bounds. */
max_ratio = DIV_ROUND_UP(hc->tx_cwnd, 2);
@@ -615,7 +683,8 @@
hc->tx_rto = DCCP_TIMEOUT_INIT;
hc->tx_rpdupack = -1;
- hc->tx_last_cong = ccid2_time_stamp;
+ hc->tx_last_cong = hc->tx_lsndtime = hc->tx_cwnd_stamp = ccid2_time_stamp;
+ hc->tx_cwnd_used = 0;
setup_timer(&hc->tx_rtotimer, ccid2_hc_tx_rto_expire,
(unsigned long)sk);
INIT_LIST_HEAD(&hc->tx_av_chunks);
@@ -636,18 +705,14 @@
static void ccid2_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb)
{
- const struct dccp_sock *dp = dccp_sk(sk);
struct ccid2_hc_rx_sock *hc = ccid2_hc_rx_sk(sk);
- switch (DCCP_SKB_CB(skb)->dccpd_type) {
- case DCCP_PKT_DATA:
- case DCCP_PKT_DATAACK:
- hc->rx_data++;
- if (hc->rx_data >= dp->dccps_r_ack_ratio) {
- dccp_send_ack(sk);
- hc->rx_data = 0;
- }
- break;
+ if (!dccp_data_packet(skb))
+ return;
+
+ if (++hc->rx_num_data_pkts >= dccp_sk(sk)->dccps_r_ack_ratio) {
+ dccp_send_ack(sk);
+ hc->rx_num_data_pkts = 0;
}
}
diff --git a/net/dccp/ccids/ccid2.h b/net/dccp/ccids/ccid2.h
index e9985da..f585d33 100644
--- a/net/dccp/ccids/ccid2.h
+++ b/net/dccp/ccids/ccid2.h
@@ -53,6 +53,10 @@
* @tx_rttvar: moving average/maximum of @mdev_max
* @tx_rto: RTO value deriving from SRTT and RTTVAR (RFC 2988)
* @tx_rtt_seq: to decay RTTVAR at most once per flight
+ * @tx_cwnd_used: actually used cwnd, W_used of RFC 2861
+ * @tx_expected_wnd: moving average of @tx_cwnd_used
+ * @tx_cwnd_stamp: to track idle periods in CWV
+ * @tx_lsndtime: last time (in jiffies) a data packet was sent
* @tx_rpseq: last consecutive seqno
* @tx_rpdupack: dupacks since rpseq
* @tx_av_chunks: list of Ack Vectors received on current skb
@@ -76,6 +80,12 @@
u64 tx_rtt_seq:48;
struct timer_list tx_rtotimer;
+ /* Congestion Window validation (optional, RFC 2861) */
+ u32 tx_cwnd_used,
+ tx_expected_wnd,
+ tx_cwnd_stamp,
+ tx_lsndtime;
+
u64 tx_rpseq;
int tx_rpdupack;
u32 tx_last_cong;
@@ -88,8 +98,21 @@
return hc->tx_pipe >= hc->tx_cwnd;
}
+/*
+ * Convert RFC 3390 larger initial window into an equivalent number of packets.
+ * This is based on the numbers specified in RFC 5681, 3.1.
+ */
+static inline u32 rfc3390_bytes_to_packets(const u32 smss)
+{
+ return smss <= 1095 ? 4 : (smss > 2190 ? 2 : 3);
+}
+
+/**
+ * struct ccid2_hc_rx_sock - Receiving end of CCID-2 half-connection
+ * @rx_num_data_pkts: number of data packets received since last feedback
+ */
struct ccid2_hc_rx_sock {
- int rx_data;
+ u32 rx_num_data_pkts;
};
static inline struct ccid2_hc_tx_sock *ccid2_hc_tx_sk(const struct sock *sk)
diff --git a/net/dccp/input.c b/net/dccp/input.c
index 4222e7a..51d5fe5 100644
--- a/net/dccp/input.c
+++ b/net/dccp/input.c
@@ -619,20 +619,31 @@
return 1;
}
- if (sk->sk_state != DCCP_REQUESTING && sk->sk_state != DCCP_RESPOND) {
- if (dccp_check_seqno(sk, skb))
- goto discard;
+ /* Step 6: Check sequence numbers (omitted in LISTEN/REQUEST state) */
+ if (sk->sk_state != DCCP_REQUESTING && dccp_check_seqno(sk, skb))
+ goto discard;
- /*
- * Step 8: Process options and mark acknowledgeable
- */
- if (dccp_parse_options(sk, NULL, skb))
- return 1;
-
- dccp_handle_ackvec_processing(sk, skb);
- dccp_deliver_input_to_ccids(sk, skb);
+ /*
+ * Step 7: Check for unexpected packet types
+ * If (S.is_server and P.type == Response)
+ * or (S.is_client and P.type == Request)
+ * or (S.state == RESPOND and P.type == Data),
+ * Send Sync packet acknowledging P.seqno
+ * Drop packet and return
+ */
+ if ((dp->dccps_role != DCCP_ROLE_CLIENT &&
+ dh->dccph_type == DCCP_PKT_RESPONSE) ||
+ (dp->dccps_role == DCCP_ROLE_CLIENT &&
+ dh->dccph_type == DCCP_PKT_REQUEST) ||
+ (sk->sk_state == DCCP_RESPOND && dh->dccph_type == DCCP_PKT_DATA)) {
+ dccp_send_sync(sk, dcb->dccpd_seq, DCCP_PKT_SYNC);
+ goto discard;
}
+ /* Step 8: Process options */
+ if (dccp_parse_options(sk, NULL, skb))
+ return 1;
+
/*
* Step 9: Process Reset
* If P.type == Reset,
@@ -640,31 +651,15 @@
* S.state := TIMEWAIT
* Set TIMEWAIT timer
* Drop packet and return
- */
+ */
if (dh->dccph_type == DCCP_PKT_RESET) {
dccp_rcv_reset(sk, skb);
return 0;
- /*
- * Step 7: Check for unexpected packet types
- * If (S.is_server and P.type == Response)
- * or (S.is_client and P.type == Request)
- * or (S.state == RESPOND and P.type == Data),
- * Send Sync packet acknowledging P.seqno
- * Drop packet and return
- */
- } else if ((dp->dccps_role != DCCP_ROLE_CLIENT &&
- dh->dccph_type == DCCP_PKT_RESPONSE) ||
- (dp->dccps_role == DCCP_ROLE_CLIENT &&
- dh->dccph_type == DCCP_PKT_REQUEST) ||
- (sk->sk_state == DCCP_RESPOND &&
- dh->dccph_type == DCCP_PKT_DATA)) {
- dccp_send_sync(sk, dcb->dccpd_seq, DCCP_PKT_SYNC);
- goto discard;
- } else if (dh->dccph_type == DCCP_PKT_CLOSEREQ) {
+ } else if (dh->dccph_type == DCCP_PKT_CLOSEREQ) { /* Step 13 */
if (dccp_rcv_closereq(sk, skb))
return 0;
goto discard;
- } else if (dh->dccph_type == DCCP_PKT_CLOSE) {
+ } else if (dh->dccph_type == DCCP_PKT_CLOSE) { /* Step 14 */
if (dccp_rcv_close(sk, skb))
return 0;
goto discard;
@@ -679,8 +674,12 @@
__kfree_skb(skb);
return 0;
- case DCCP_RESPOND:
case DCCP_PARTOPEN:
+ /* Step 8: if using Ack Vectors, mark packet acknowledgeable */
+ dccp_handle_ackvec_processing(sk, skb);
+ dccp_deliver_input_to_ccids(sk, skb);
+ /* fall through */
+ case DCCP_RESPOND:
queued = dccp_rcv_respond_partopen_state_process(sk, skb,
dh, len);
break;
diff --git a/net/dccp/output.c b/net/dccp/output.c
index fab108e..dede3ed 100644
--- a/net/dccp/output.c
+++ b/net/dccp/output.c
@@ -27,11 +27,13 @@
inet_csk_clear_xmit_timer(sk, ICSK_TIME_DACK);
}
-static void dccp_skb_entail(struct sock *sk, struct sk_buff *skb)
+/* enqueue @skb on sk_send_head for retransmission, return clone to send now */
+static struct sk_buff *dccp_skb_entail(struct sock *sk, struct sk_buff *skb)
{
skb_set_owner_w(skb, sk);
WARN_ON(sk->sk_send_head);
sk->sk_send_head = skb;
+ return skb_clone(sk->sk_send_head, gfp_any());
}
/*
@@ -552,8 +554,7 @@
DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_REQUEST;
- dccp_skb_entail(sk, skb);
- dccp_transmit_skb(sk, skb_clone(skb, GFP_KERNEL));
+ dccp_transmit_skb(sk, dccp_skb_entail(sk, skb));
DCCP_INC_STATS(DCCP_MIB_ACTIVEOPENS);
/* Timer for repeating the REQUEST until an answer. */
@@ -678,8 +679,7 @@
DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_CLOSE;
if (active) {
- dccp_skb_entail(sk, skb);
- dccp_transmit_skb(sk, skb_clone(skb, prio));
+ skb = dccp_skb_entail(sk, skb);
/*
* Retransmission timer for active-close: RFC 4340, 8.3 requires
* to retransmit the Close/CloseReq until the CLOSING/CLOSEREQ
@@ -692,6 +692,6 @@
*/
inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS,
DCCP_TIMEOUT_INIT, DCCP_RTO_MAX);
- } else
- dccp_transmit_skb(sk, skb);
+ }
+ dccp_transmit_skb(sk, skb);
}
diff --git a/net/decnet/af_decnet.c b/net/decnet/af_decnet.c
index ea3b6ee..19acd00 100644
--- a/net/decnet/af_decnet.c
+++ b/net/decnet/af_decnet.c
@@ -291,23 +291,23 @@
*buf++ = type;
- switch(type) {
- case 0:
- *buf++ = sdn->sdn_objnum;
- break;
- case 1:
- *buf++ = 0;
- *buf++ = le16_to_cpu(sdn->sdn_objnamel);
- memcpy(buf, sdn->sdn_objname, le16_to_cpu(sdn->sdn_objnamel));
- len = 3 + le16_to_cpu(sdn->sdn_objnamel);
- break;
- case 2:
- memset(buf, 0, 5);
- buf += 5;
- *buf++ = le16_to_cpu(sdn->sdn_objnamel);
- memcpy(buf, sdn->sdn_objname, le16_to_cpu(sdn->sdn_objnamel));
- len = 7 + le16_to_cpu(sdn->sdn_objnamel);
- break;
+ switch (type) {
+ case 0:
+ *buf++ = sdn->sdn_objnum;
+ break;
+ case 1:
+ *buf++ = 0;
+ *buf++ = le16_to_cpu(sdn->sdn_objnamel);
+ memcpy(buf, sdn->sdn_objname, le16_to_cpu(sdn->sdn_objnamel));
+ len = 3 + le16_to_cpu(sdn->sdn_objnamel);
+ break;
+ case 2:
+ memset(buf, 0, 5);
+ buf += 5;
+ *buf++ = le16_to_cpu(sdn->sdn_objnamel);
+ memcpy(buf, sdn->sdn_objname, le16_to_cpu(sdn->sdn_objnamel));
+ len = 7 + le16_to_cpu(sdn->sdn_objnamel);
+ break;
}
return len;
@@ -337,23 +337,23 @@
*fmt = *data++;
type = *data++;
- switch(*fmt) {
- case 0:
- sdn->sdn_objnum = type;
- return 2;
- case 1:
- namel = 16;
- break;
- case 2:
- len -= 4;
- data += 4;
- break;
- case 4:
- len -= 8;
- data += 8;
- break;
- default:
- return -1;
+ switch (*fmt) {
+ case 0:
+ sdn->sdn_objnum = type;
+ return 2;
+ case 1:
+ namel = 16;
+ break;
+ case 2:
+ len -= 4;
+ data += 4;
+ break;
+ case 4:
+ len -= 8;
+ data += 8;
+ break;
+ default:
+ return -1;
}
len -= 1;
@@ -575,25 +575,26 @@
scp->persist = dn_nsp_persist(sk);
- switch(scp->state) {
- case DN_DI:
- dn_nsp_send_disc(sk, NSP_DISCINIT, 0, GFP_ATOMIC);
- if (scp->nsp_rxtshift >= decnet_di_count)
- scp->state = DN_CN;
- return 0;
+ switch (scp->state) {
+ case DN_DI:
+ dn_nsp_send_disc(sk, NSP_DISCINIT, 0, GFP_ATOMIC);
+ if (scp->nsp_rxtshift >= decnet_di_count)
+ scp->state = DN_CN;
+ return 0;
- case DN_DR:
- dn_nsp_send_disc(sk, NSP_DISCINIT, 0, GFP_ATOMIC);
- if (scp->nsp_rxtshift >= decnet_dr_count)
- scp->state = DN_DRC;
- return 0;
+ case DN_DR:
+ dn_nsp_send_disc(sk, NSP_DISCINIT, 0, GFP_ATOMIC);
+ if (scp->nsp_rxtshift >= decnet_dr_count)
+ scp->state = DN_DRC;
+ return 0;
- case DN_DN:
- if (scp->nsp_rxtshift < decnet_dn_count) {
- /* printk(KERN_DEBUG "dn_destroy_timer: DN\n"); */
- dn_nsp_send_disc(sk, NSP_DISCCONF, NSP_REASON_DC, GFP_ATOMIC);
- return 0;
- }
+ case DN_DN:
+ if (scp->nsp_rxtshift < decnet_dn_count) {
+ /* printk(KERN_DEBUG "dn_destroy_timer: DN\n"); */
+ dn_nsp_send_disc(sk, NSP_DISCCONF, NSP_REASON_DC,
+ GFP_ATOMIC);
+ return 0;
+ }
}
scp->persist = (HZ * decnet_time_wait);
@@ -623,42 +624,42 @@
sk->sk_state = TCP_CLOSE;
- switch(scp->state) {
- case DN_DN:
- dn_nsp_send_disc(sk, NSP_DISCCONF, NSP_REASON_DC,
- sk->sk_allocation);
- scp->persist_fxn = dn_destroy_timer;
- scp->persist = dn_nsp_persist(sk);
- break;
- case DN_CR:
- scp->state = DN_DR;
- goto disc_reject;
- case DN_RUN:
- scp->state = DN_DI;
- case DN_DI:
- case DN_DR:
+ switch (scp->state) {
+ case DN_DN:
+ dn_nsp_send_disc(sk, NSP_DISCCONF, NSP_REASON_DC,
+ sk->sk_allocation);
+ scp->persist_fxn = dn_destroy_timer;
+ scp->persist = dn_nsp_persist(sk);
+ break;
+ case DN_CR:
+ scp->state = DN_DR;
+ goto disc_reject;
+ case DN_RUN:
+ scp->state = DN_DI;
+ case DN_DI:
+ case DN_DR:
disc_reject:
- dn_nsp_send_disc(sk, NSP_DISCINIT, 0, sk->sk_allocation);
- case DN_NC:
- case DN_NR:
- case DN_RJ:
- case DN_DIC:
- case DN_CN:
- case DN_DRC:
- case DN_CI:
- case DN_CD:
- scp->persist_fxn = dn_destroy_timer;
- scp->persist = dn_nsp_persist(sk);
- break;
- default:
- printk(KERN_DEBUG "DECnet: dn_destroy_sock passed socket in invalid state\n");
- case DN_O:
- dn_stop_slow_timer(sk);
+ dn_nsp_send_disc(sk, NSP_DISCINIT, 0, sk->sk_allocation);
+ case DN_NC:
+ case DN_NR:
+ case DN_RJ:
+ case DN_DIC:
+ case DN_CN:
+ case DN_DRC:
+ case DN_CI:
+ case DN_CD:
+ scp->persist_fxn = dn_destroy_timer;
+ scp->persist = dn_nsp_persist(sk);
+ break;
+ default:
+ printk(KERN_DEBUG "DECnet: dn_destroy_sock passed socket in invalid state\n");
+ case DN_O:
+ dn_stop_slow_timer(sk);
- dn_unhash_sock_bh(sk);
- sock_put(sk);
+ dn_unhash_sock_bh(sk);
+ sock_put(sk);
- break;
+ break;
}
}
@@ -683,15 +684,15 @@
if (!net_eq(net, &init_net))
return -EAFNOSUPPORT;
- switch(sock->type) {
- case SOCK_SEQPACKET:
- if (protocol != DNPROTO_NSP)
- return -EPROTONOSUPPORT;
- break;
- case SOCK_STREAM:
- break;
- default:
- return -ESOCKTNOSUPPORT;
+ switch (sock->type) {
+ case SOCK_SEQPACKET:
+ if (protocol != DNPROTO_NSP)
+ return -EPROTONOSUPPORT;
+ break;
+ case SOCK_STREAM:
+ break;
+ default:
+ return -ESOCKTNOSUPPORT;
}
@@ -987,16 +988,16 @@
{
struct dn_scp *scp = DN_SK(sk);
- switch(scp->state) {
- case DN_RUN:
- return 0;
- case DN_CR:
- return dn_confirm_accept(sk, timeo, sk->sk_allocation);
- case DN_CI:
- case DN_CC:
- return dn_wait_run(sk, timeo);
- case DN_O:
- return __dn_connect(sk, addr, addrlen, timeo, flags);
+ switch (scp->state) {
+ case DN_RUN:
+ return 0;
+ case DN_CR:
+ return dn_confirm_accept(sk, timeo, sk->sk_allocation);
+ case DN_CI:
+ case DN_CC:
+ return dn_wait_run(sk, timeo);
+ case DN_O:
+ return __dn_connect(sk, addr, addrlen, timeo, flags);
}
return -EINVAL;
@@ -1363,141 +1364,140 @@
if (copy_from_user(&u, optval, optlen))
return -EFAULT;
- switch(optname) {
- case DSO_CONDATA:
- if (sock->state == SS_CONNECTED)
- return -EISCONN;
- if ((scp->state != DN_O) && (scp->state != DN_CR))
- return -EINVAL;
+ switch (optname) {
+ case DSO_CONDATA:
+ if (sock->state == SS_CONNECTED)
+ return -EISCONN;
+ if ((scp->state != DN_O) && (scp->state != DN_CR))
+ return -EINVAL;
- if (optlen != sizeof(struct optdata_dn))
- return -EINVAL;
+ if (optlen != sizeof(struct optdata_dn))
+ return -EINVAL;
- if (le16_to_cpu(u.opt.opt_optl) > 16)
- return -EINVAL;
+ if (le16_to_cpu(u.opt.opt_optl) > 16)
+ return -EINVAL;
- memcpy(&scp->conndata_out, &u.opt, optlen);
- break;
+ memcpy(&scp->conndata_out, &u.opt, optlen);
+ break;
- case DSO_DISDATA:
- if (sock->state != SS_CONNECTED && scp->accept_mode == ACC_IMMED)
- return -ENOTCONN;
+ case DSO_DISDATA:
+ if (sock->state != SS_CONNECTED &&
+ scp->accept_mode == ACC_IMMED)
+ return -ENOTCONN;
- if (optlen != sizeof(struct optdata_dn))
- return -EINVAL;
+ if (optlen != sizeof(struct optdata_dn))
+ return -EINVAL;
- if (le16_to_cpu(u.opt.opt_optl) > 16)
- return -EINVAL;
+ if (le16_to_cpu(u.opt.opt_optl) > 16)
+ return -EINVAL;
- memcpy(&scp->discdata_out, &u.opt, optlen);
- break;
+ memcpy(&scp->discdata_out, &u.opt, optlen);
+ break;
- case DSO_CONACCESS:
- if (sock->state == SS_CONNECTED)
- return -EISCONN;
- if (scp->state != DN_O)
- return -EINVAL;
+ case DSO_CONACCESS:
+ if (sock->state == SS_CONNECTED)
+ return -EISCONN;
+ if (scp->state != DN_O)
+ return -EINVAL;
- if (optlen != sizeof(struct accessdata_dn))
- return -EINVAL;
+ if (optlen != sizeof(struct accessdata_dn))
+ return -EINVAL;
- if ((u.acc.acc_accl > DN_MAXACCL) ||
- (u.acc.acc_passl > DN_MAXACCL) ||
- (u.acc.acc_userl > DN_MAXACCL))
- return -EINVAL;
+ if ((u.acc.acc_accl > DN_MAXACCL) ||
+ (u.acc.acc_passl > DN_MAXACCL) ||
+ (u.acc.acc_userl > DN_MAXACCL))
+ return -EINVAL;
- memcpy(&scp->accessdata, &u.acc, optlen);
- break;
+ memcpy(&scp->accessdata, &u.acc, optlen);
+ break;
- case DSO_ACCEPTMODE:
- if (sock->state == SS_CONNECTED)
- return -EISCONN;
- if (scp->state != DN_O)
- return -EINVAL;
+ case DSO_ACCEPTMODE:
+ if (sock->state == SS_CONNECTED)
+ return -EISCONN;
+ if (scp->state != DN_O)
+ return -EINVAL;
- if (optlen != sizeof(int))
- return -EINVAL;
+ if (optlen != sizeof(int))
+ return -EINVAL;
- if ((u.mode != ACC_IMMED) && (u.mode != ACC_DEFER))
- return -EINVAL;
+ if ((u.mode != ACC_IMMED) && (u.mode != ACC_DEFER))
+ return -EINVAL;
- scp->accept_mode = (unsigned char)u.mode;
- break;
+ scp->accept_mode = (unsigned char)u.mode;
+ break;
- case DSO_CONACCEPT:
+ case DSO_CONACCEPT:
+ if (scp->state != DN_CR)
+ return -EINVAL;
+ timeo = sock_rcvtimeo(sk, 0);
+ err = dn_confirm_accept(sk, &timeo, sk->sk_allocation);
+ return err;
- if (scp->state != DN_CR)
- return -EINVAL;
- timeo = sock_rcvtimeo(sk, 0);
- err = dn_confirm_accept(sk, &timeo, sk->sk_allocation);
- return err;
+ case DSO_CONREJECT:
+ if (scp->state != DN_CR)
+ return -EINVAL;
- case DSO_CONREJECT:
+ scp->state = DN_DR;
+ sk->sk_shutdown = SHUTDOWN_MASK;
+ dn_nsp_send_disc(sk, 0x38, 0, sk->sk_allocation);
+ break;
- if (scp->state != DN_CR)
- return -EINVAL;
-
- scp->state = DN_DR;
- sk->sk_shutdown = SHUTDOWN_MASK;
- dn_nsp_send_disc(sk, 0x38, 0, sk->sk_allocation);
- break;
-
- default:
+ default:
#ifdef CONFIG_NETFILTER
return nf_setsockopt(sk, PF_DECnet, optname, optval, optlen);
#endif
- case DSO_LINKINFO:
- case DSO_STREAM:
- case DSO_SEQPACKET:
- return -ENOPROTOOPT;
+ case DSO_LINKINFO:
+ case DSO_STREAM:
+ case DSO_SEQPACKET:
+ return -ENOPROTOOPT;
- case DSO_MAXWINDOW:
- if (optlen != sizeof(unsigned long))
- return -EINVAL;
- if (u.win > NSP_MAX_WINDOW)
- u.win = NSP_MAX_WINDOW;
- if (u.win == 0)
- return -EINVAL;
- scp->max_window = u.win;
- if (scp->snd_window > u.win)
- scp->snd_window = u.win;
- break;
+ case DSO_MAXWINDOW:
+ if (optlen != sizeof(unsigned long))
+ return -EINVAL;
+ if (u.win > NSP_MAX_WINDOW)
+ u.win = NSP_MAX_WINDOW;
+ if (u.win == 0)
+ return -EINVAL;
+ scp->max_window = u.win;
+ if (scp->snd_window > u.win)
+ scp->snd_window = u.win;
+ break;
- case DSO_NODELAY:
- if (optlen != sizeof(int))
- return -EINVAL;
- if (scp->nonagle == 2)
- return -EINVAL;
- scp->nonagle = (u.val == 0) ? 0 : 1;
- /* if (scp->nonagle == 1) { Push pending frames } */
- break;
+ case DSO_NODELAY:
+ if (optlen != sizeof(int))
+ return -EINVAL;
+ if (scp->nonagle == 2)
+ return -EINVAL;
+ scp->nonagle = (u.val == 0) ? 0 : 1;
+ /* if (scp->nonagle == 1) { Push pending frames } */
+ break;
- case DSO_CORK:
- if (optlen != sizeof(int))
- return -EINVAL;
- if (scp->nonagle == 1)
- return -EINVAL;
- scp->nonagle = (u.val == 0) ? 0 : 2;
- /* if (scp->nonagle == 0) { Push pending frames } */
- break;
+ case DSO_CORK:
+ if (optlen != sizeof(int))
+ return -EINVAL;
+ if (scp->nonagle == 1)
+ return -EINVAL;
+ scp->nonagle = (u.val == 0) ? 0 : 2;
+ /* if (scp->nonagle == 0) { Push pending frames } */
+ break;
- case DSO_SERVICES:
- if (optlen != sizeof(unsigned char))
- return -EINVAL;
- if ((u.services & ~NSP_FC_MASK) != 0x01)
- return -EINVAL;
- if ((u.services & NSP_FC_MASK) == NSP_FC_MASK)
- return -EINVAL;
- scp->services_loc = u.services;
- break;
+ case DSO_SERVICES:
+ if (optlen != sizeof(unsigned char))
+ return -EINVAL;
+ if ((u.services & ~NSP_FC_MASK) != 0x01)
+ return -EINVAL;
+ if ((u.services & NSP_FC_MASK) == NSP_FC_MASK)
+ return -EINVAL;
+ scp->services_loc = u.services;
+ break;
- case DSO_INFO:
- if (optlen != sizeof(unsigned char))
- return -EINVAL;
- if (u.info & 0xfc)
- return -EINVAL;
- scp->info_loc = u.info;
- break;
+ case DSO_INFO:
+ if (optlen != sizeof(unsigned char))
+ return -EINVAL;
+ if (u.info & 0xfc)
+ return -EINVAL;
+ scp->info_loc = u.info;
+ break;
}
return 0;
@@ -1527,107 +1527,106 @@
if(get_user(r_len , optlen))
return -EFAULT;
- switch(optname) {
- case DSO_CONDATA:
- if (r_len > sizeof(struct optdata_dn))
- r_len = sizeof(struct optdata_dn);
- r_data = &scp->conndata_in;
+ switch (optname) {
+ case DSO_CONDATA:
+ if (r_len > sizeof(struct optdata_dn))
+ r_len = sizeof(struct optdata_dn);
+ r_data = &scp->conndata_in;
+ break;
+
+ case DSO_DISDATA:
+ if (r_len > sizeof(struct optdata_dn))
+ r_len = sizeof(struct optdata_dn);
+ r_data = &scp->discdata_in;
+ break;
+
+ case DSO_CONACCESS:
+ if (r_len > sizeof(struct accessdata_dn))
+ r_len = sizeof(struct accessdata_dn);
+ r_data = &scp->accessdata;
+ break;
+
+ case DSO_ACCEPTMODE:
+ if (r_len > sizeof(unsigned char))
+ r_len = sizeof(unsigned char);
+ r_data = &scp->accept_mode;
+ break;
+
+ case DSO_LINKINFO:
+ if (r_len > sizeof(struct linkinfo_dn))
+ r_len = sizeof(struct linkinfo_dn);
+
+ memset(&link, 0, sizeof(link));
+
+ switch (sock->state) {
+ case SS_CONNECTING:
+ link.idn_linkstate = LL_CONNECTING;
break;
-
- case DSO_DISDATA:
- if (r_len > sizeof(struct optdata_dn))
- r_len = sizeof(struct optdata_dn);
- r_data = &scp->discdata_in;
+ case SS_DISCONNECTING:
+ link.idn_linkstate = LL_DISCONNECTING;
break;
-
- case DSO_CONACCESS:
- if (r_len > sizeof(struct accessdata_dn))
- r_len = sizeof(struct accessdata_dn);
- r_data = &scp->accessdata;
+ case SS_CONNECTED:
+ link.idn_linkstate = LL_RUNNING;
break;
-
- case DSO_ACCEPTMODE:
- if (r_len > sizeof(unsigned char))
- r_len = sizeof(unsigned char);
- r_data = &scp->accept_mode;
- break;
-
- case DSO_LINKINFO:
- if (r_len > sizeof(struct linkinfo_dn))
- r_len = sizeof(struct linkinfo_dn);
-
- memset(&link, 0, sizeof(link));
-
- switch(sock->state) {
- case SS_CONNECTING:
- link.idn_linkstate = LL_CONNECTING;
- break;
- case SS_DISCONNECTING:
- link.idn_linkstate = LL_DISCONNECTING;
- break;
- case SS_CONNECTED:
- link.idn_linkstate = LL_RUNNING;
- break;
- default:
- link.idn_linkstate = LL_INACTIVE;
- }
-
- link.idn_segsize = scp->segsize_rem;
- r_data = &link;
- break;
-
default:
-#ifdef CONFIG_NETFILTER
- {
- int ret, len;
-
- if(get_user(len, optlen))
- return -EFAULT;
-
- ret = nf_getsockopt(sk, PF_DECnet, optname,
- optval, &len);
- if (ret >= 0)
- ret = put_user(len, optlen);
- return ret;
+ link.idn_linkstate = LL_INACTIVE;
}
+
+ link.idn_segsize = scp->segsize_rem;
+ r_data = &link;
+ break;
+
+ default:
+#ifdef CONFIG_NETFILTER
+ {
+ int ret, len;
+
+ if (get_user(len, optlen))
+ return -EFAULT;
+
+ ret = nf_getsockopt(sk, PF_DECnet, optname, optval, &len);
+ if (ret >= 0)
+ ret = put_user(len, optlen);
+ return ret;
+ }
#endif
- case DSO_STREAM:
- case DSO_SEQPACKET:
- case DSO_CONACCEPT:
- case DSO_CONREJECT:
- return -ENOPROTOOPT;
+ case DSO_STREAM:
+ case DSO_SEQPACKET:
+ case DSO_CONACCEPT:
+ case DSO_CONREJECT:
+ return -ENOPROTOOPT;
- case DSO_MAXWINDOW:
- if (r_len > sizeof(unsigned long))
- r_len = sizeof(unsigned long);
- r_data = &scp->max_window;
- break;
+ case DSO_MAXWINDOW:
+ if (r_len > sizeof(unsigned long))
+ r_len = sizeof(unsigned long);
+ r_data = &scp->max_window;
+ break;
- case DSO_NODELAY:
- if (r_len > sizeof(int))
- r_len = sizeof(int);
- val = (scp->nonagle == 1);
- r_data = &val;
- break;
+ case DSO_NODELAY:
+ if (r_len > sizeof(int))
+ r_len = sizeof(int);
+ val = (scp->nonagle == 1);
+ r_data = &val;
+ break;
- case DSO_CORK:
- if (r_len > sizeof(int))
- r_len = sizeof(int);
- val = (scp->nonagle == 2);
- r_data = &val;
- break;
+ case DSO_CORK:
+ if (r_len > sizeof(int))
+ r_len = sizeof(int);
+ val = (scp->nonagle == 2);
+ r_data = &val;
+ break;
- case DSO_SERVICES:
- if (r_len > sizeof(unsigned char))
- r_len = sizeof(unsigned char);
- r_data = &scp->services_rem;
- break;
+ case DSO_SERVICES:
+ if (r_len > sizeof(unsigned char))
+ r_len = sizeof(unsigned char);
+ r_data = &scp->services_rem;
+ break;
- case DSO_INFO:
- if (r_len > sizeof(unsigned char))
- r_len = sizeof(unsigned char);
- r_data = &scp->info_rem;
- break;
+ case DSO_INFO:
+ if (r_len > sizeof(unsigned char))
+ r_len = sizeof(unsigned char);
+ r_data = &scp->info_rem;
+ break;
}
if (r_data) {
@@ -2088,15 +2087,15 @@
if (!net_eq(dev_net(dev), &init_net))
return NOTIFY_DONE;
- switch(event) {
- case NETDEV_UP:
- dn_dev_up(dev);
- break;
- case NETDEV_DOWN:
- dn_dev_down(dev);
- break;
- default:
- break;
+ switch (event) {
+ case NETDEV_UP:
+ dn_dev_up(dev);
+ break;
+ case NETDEV_DOWN:
+ dn_dev_down(dev);
+ break;
+ default:
+ break;
}
return NOTIFY_DONE;
@@ -2209,54 +2208,54 @@
int i;
switch (le16_to_cpu(dn->sdn_objnamel)) {
- case 0:
- sprintf(buf, "%d", dn->sdn_objnum);
- break;
- default:
- for (i = 0; i < le16_to_cpu(dn->sdn_objnamel); i++) {
- buf[i] = dn->sdn_objname[i];
- if (IS_NOT_PRINTABLE(buf[i]))
- buf[i] = '.';
- }
- buf[i] = 0;
+ case 0:
+ sprintf(buf, "%d", dn->sdn_objnum);
+ break;
+ default:
+ for (i = 0; i < le16_to_cpu(dn->sdn_objnamel); i++) {
+ buf[i] = dn->sdn_objname[i];
+ if (IS_NOT_PRINTABLE(buf[i]))
+ buf[i] = '.';
+ }
+ buf[i] = 0;
}
}
static char *dn_state2asc(unsigned char state)
{
- switch(state) {
- case DN_O:
- return "OPEN";
- case DN_CR:
- return " CR";
- case DN_DR:
- return " DR";
- case DN_DRC:
- return " DRC";
- case DN_CC:
- return " CC";
- case DN_CI:
- return " CI";
- case DN_NR:
- return " NR";
- case DN_NC:
- return " NC";
- case DN_CD:
- return " CD";
- case DN_RJ:
- return " RJ";
- case DN_RUN:
- return " RUN";
- case DN_DI:
- return " DI";
- case DN_DIC:
- return " DIC";
- case DN_DN:
- return " DN";
- case DN_CL:
- return " CL";
- case DN_CN:
- return " CN";
+ switch (state) {
+ case DN_O:
+ return "OPEN";
+ case DN_CR:
+ return " CR";
+ case DN_DR:
+ return " DR";
+ case DN_DRC:
+ return " DRC";
+ case DN_CC:
+ return " CC";
+ case DN_CI:
+ return " CI";
+ case DN_NR:
+ return " NR";
+ case DN_NC:
+ return " NC";
+ case DN_CD:
+ return " CD";
+ case DN_RJ:
+ return " RJ";
+ case DN_RUN:
+ return " RUN";
+ case DN_DI:
+ return " DI";
+ case DN_DIC:
+ return " DIC";
+ case DN_DN:
+ return " DN";
+ case DN_CL:
+ return " CL";
+ case DN_CN:
+ return " CN";
}
return "????";
diff --git a/net/decnet/dn_dev.c b/net/decnet/dn_dev.c
index cf26ac7..ba4face 100644
--- a/net/decnet/dn_dev.c
+++ b/net/decnet/dn_dev.c
@@ -437,17 +437,17 @@
dev_load(&init_net, ifr->ifr_name);
- switch(cmd) {
- case SIOCGIFADDR:
- break;
- case SIOCSIFADDR:
- if (!capable(CAP_NET_ADMIN))
- return -EACCES;
- if (sdn->sdn_family != AF_DECnet)
- return -EINVAL;
- break;
- default:
+ switch (cmd) {
+ case SIOCGIFADDR:
+ break;
+ case SIOCSIFADDR:
+ if (!capable(CAP_NET_ADMIN))
+ return -EACCES;
+ if (sdn->sdn_family != AF_DECnet)
return -EINVAL;
+ break;
+ default:
+ return -EINVAL;
}
rtnl_lock();
@@ -470,27 +470,27 @@
goto done;
}
- switch(cmd) {
- case SIOCGIFADDR:
- *((__le16 *)sdn->sdn_nodeaddr) = ifa->ifa_local;
- goto rarok;
+ switch (cmd) {
+ case SIOCGIFADDR:
+ *((__le16 *)sdn->sdn_nodeaddr) = ifa->ifa_local;
+ goto rarok;
- case SIOCSIFADDR:
- if (!ifa) {
- if ((ifa = dn_dev_alloc_ifa()) == NULL) {
- ret = -ENOBUFS;
- break;
- }
- memcpy(ifa->ifa_label, dev->name, IFNAMSIZ);
- } else {
- if (ifa->ifa_local == dn_saddr2dn(sdn))
- break;
- dn_dev_del_ifa(dn_db, ifap, 0);
+ case SIOCSIFADDR:
+ if (!ifa) {
+ if ((ifa = dn_dev_alloc_ifa()) == NULL) {
+ ret = -ENOBUFS;
+ break;
}
+ memcpy(ifa->ifa_label, dev->name, IFNAMSIZ);
+ } else {
+ if (ifa->ifa_local == dn_saddr2dn(sdn))
+ break;
+ dn_dev_del_ifa(dn_db, ifap, 0);
+ }
- ifa->ifa_local = ifa->ifa_address = dn_saddr2dn(sdn);
+ ifa->ifa_local = ifa->ifa_address = dn_saddr2dn(sdn);
- ret = dn_dev_set_ifa(dev, ifa);
+ ret = dn_dev_set_ifa(dev, ifa);
}
done:
rtnl_unlock();
@@ -1313,7 +1313,7 @@
++*pos;
- dev = (struct net_device *)v;
+ dev = v;
if (v == SEQ_START_TOKEN)
dev = net_device_entry(&init_net.dev_base_head);
@@ -1335,13 +1335,13 @@
static char *dn_type2asc(char type)
{
- switch(type) {
- case DN_DEV_BCAST:
- return "B";
- case DN_DEV_UCAST:
- return "U";
- case DN_DEV_MPOINT:
- return "M";
+ switch (type) {
+ case DN_DEV_BCAST:
+ return "B";
+ case DN_DEV_UCAST:
+ return "U";
+ case DN_DEV_MPOINT:
+ return "M";
}
return "?";
@@ -1414,9 +1414,9 @@
dn_dev_devices_on();
- rtnl_register(PF_DECnet, RTM_NEWADDR, dn_nl_newaddr, NULL);
- rtnl_register(PF_DECnet, RTM_DELADDR, dn_nl_deladdr, NULL);
- rtnl_register(PF_DECnet, RTM_GETADDR, NULL, dn_nl_dump_ifaddr);
+ rtnl_register(PF_DECnet, RTM_NEWADDR, dn_nl_newaddr, NULL, NULL);
+ rtnl_register(PF_DECnet, RTM_DELADDR, dn_nl_deladdr, NULL, NULL);
+ rtnl_register(PF_DECnet, RTM_GETADDR, NULL, dn_nl_dump_ifaddr, NULL);
proc_net_fops_create(&init_net, "decnet_dev", S_IRUGO, &dn_dev_seq_fops);
diff --git a/net/decnet/dn_fib.c b/net/decnet/dn_fib.c
index 1c74ed3..2bd8e53 100644
--- a/net/decnet/dn_fib.c
+++ b/net/decnet/dn_fib.c
@@ -414,33 +414,34 @@
res->fi = fi;
- switch(type) {
- case RTN_NAT:
- DN_FIB_RES_RESET(*res);
+ switch (type) {
+ case RTN_NAT:
+ DN_FIB_RES_RESET(*res);
+ atomic_inc(&fi->fib_clntref);
+ return 0;
+ case RTN_UNICAST:
+ case RTN_LOCAL:
+ for_nexthops(fi) {
+ if (nh->nh_flags & RTNH_F_DEAD)
+ continue;
+ if (!fld->flowidn_oif ||
+ fld->flowidn_oif == nh->nh_oif)
+ break;
+ }
+ if (nhsel < fi->fib_nhs) {
+ res->nh_sel = nhsel;
atomic_inc(&fi->fib_clntref);
return 0;
- case RTN_UNICAST:
- case RTN_LOCAL:
- for_nexthops(fi) {
- if (nh->nh_flags & RTNH_F_DEAD)
- continue;
- if (!fld->flowidn_oif ||
- fld->flowidn_oif == nh->nh_oif)
- break;
- }
- if (nhsel < fi->fib_nhs) {
- res->nh_sel = nhsel;
- atomic_inc(&fi->fib_clntref);
- return 0;
- }
- endfor_nexthops(fi);
- res->fi = NULL;
- return 1;
- default:
- if (net_ratelimit())
- printk("DECnet: impossible routing event : dn_fib_semantic_match type=%d\n", type);
- res->fi = NULL;
- return -EINVAL;
+ }
+ endfor_nexthops(fi);
+ res->fi = NULL;
+ return 1;
+ default:
+ if (net_ratelimit())
+ printk("DECnet: impossible routing event : dn_fib_semantic_match type=%d\n",
+ type);
+ res->fi = NULL;
+ return -EINVAL;
}
}
return err;
@@ -647,20 +648,20 @@
{
struct dn_ifaddr *ifa = (struct dn_ifaddr *)ptr;
- switch(event) {
- case NETDEV_UP:
- dn_fib_add_ifaddr(ifa);
- dn_fib_sync_up(ifa->ifa_dev->dev);
+ switch (event) {
+ case NETDEV_UP:
+ dn_fib_add_ifaddr(ifa);
+ dn_fib_sync_up(ifa->ifa_dev->dev);
+ dn_rt_cache_flush(-1);
+ break;
+ case NETDEV_DOWN:
+ dn_fib_del_ifaddr(ifa);
+ if (ifa->ifa_dev && ifa->ifa_dev->ifa_list == NULL) {
+ dn_fib_disable_addr(ifa->ifa_dev->dev, 1);
+ } else {
dn_rt_cache_flush(-1);
- break;
- case NETDEV_DOWN:
- dn_fib_del_ifaddr(ifa);
- if (ifa->ifa_dev && ifa->ifa_dev->ifa_list == NULL) {
- dn_fib_disable_addr(ifa->ifa_dev->dev, 1);
- } else {
- dn_rt_cache_flush(-1);
- }
- break;
+ }
+ break;
}
return NOTIFY_DONE;
}
@@ -763,8 +764,8 @@
register_dnaddr_notifier(&dn_fib_dnaddr_notifier);
- rtnl_register(PF_DECnet, RTM_NEWROUTE, dn_fib_rtm_newroute, NULL);
- rtnl_register(PF_DECnet, RTM_DELROUTE, dn_fib_rtm_delroute, NULL);
+ rtnl_register(PF_DECnet, RTM_NEWROUTE, dn_fib_rtm_newroute, NULL, NULL);
+ rtnl_register(PF_DECnet, RTM_DELROUTE, dn_fib_rtm_delroute, NULL, NULL);
}
diff --git a/net/decnet/dn_neigh.c b/net/decnet/dn_neigh.c
index 602dade..03eb226 100644
--- a/net/decnet/dn_neigh.c
+++ b/net/decnet/dn_neigh.c
@@ -404,13 +404,13 @@
dn->flags &= ~DN_NDFLAG_P3;
- switch(msg->iinfo & DN_RT_INFO_TYPE) {
- case DN_RT_INFO_L1RT:
- dn->flags &=~DN_NDFLAG_R2;
- dn->flags |= DN_NDFLAG_R1;
- break;
- case DN_RT_INFO_L2RT:
- dn->flags |= DN_NDFLAG_R2;
+ switch (msg->iinfo & DN_RT_INFO_TYPE) {
+ case DN_RT_INFO_L1RT:
+ dn->flags &=~DN_NDFLAG_R2;
+ dn->flags |= DN_NDFLAG_R1;
+ break;
+ case DN_RT_INFO_L2RT:
+ dn->flags |= DN_NDFLAG_R2;
}
}
diff --git a/net/decnet/dn_nsp_in.c b/net/decnet/dn_nsp_in.c
index b430549..73fa268 100644
--- a/net/decnet/dn_nsp_in.c
+++ b/net/decnet/dn_nsp_in.c
@@ -101,23 +101,27 @@
unsigned short type = ((ack >> 12) & 0x0003);
int wakeup = 0;
- switch(type) {
- case 0: /* ACK - Data */
- if (dn_after(ack, scp->ackrcv_dat)) {
- scp->ackrcv_dat = ack & 0x0fff;
- wakeup |= dn_nsp_check_xmit_queue(sk, skb, &scp->data_xmit_queue, ack);
- }
- break;
- case 1: /* NAK - Data */
- break;
- case 2: /* ACK - OtherData */
- if (dn_after(ack, scp->ackrcv_oth)) {
- scp->ackrcv_oth = ack & 0x0fff;
- wakeup |= dn_nsp_check_xmit_queue(sk, skb, &scp->other_xmit_queue, ack);
- }
- break;
- case 3: /* NAK - OtherData */
- break;
+ switch (type) {
+ case 0: /* ACK - Data */
+ if (dn_after(ack, scp->ackrcv_dat)) {
+ scp->ackrcv_dat = ack & 0x0fff;
+ wakeup |= dn_nsp_check_xmit_queue(sk, skb,
+ &scp->data_xmit_queue,
+ ack);
+ }
+ break;
+ case 1: /* NAK - Data */
+ break;
+ case 2: /* ACK - OtherData */
+ if (dn_after(ack, scp->ackrcv_oth)) {
+ scp->ackrcv_oth = ack & 0x0fff;
+ wakeup |= dn_nsp_check_xmit_queue(sk, skb,
+ &scp->other_xmit_queue,
+ ack);
+ }
+ break;
+ case 3: /* NAK - OtherData */
+ break;
}
if (wakeup && !sock_flag(sk, SOCK_DEAD))
@@ -417,19 +421,19 @@
scp->addrrem = cb->src_port;
sk->sk_state = TCP_CLOSE;
- switch(scp->state) {
- case DN_CI:
- case DN_CD:
- scp->state = DN_RJ;
- sk->sk_err = ECONNREFUSED;
- break;
- case DN_RUN:
- sk->sk_shutdown |= SHUTDOWN_MASK;
- scp->state = DN_DN;
- break;
- case DN_DI:
- scp->state = DN_DIC;
- break;
+ switch (scp->state) {
+ case DN_CI:
+ case DN_CD:
+ scp->state = DN_RJ;
+ sk->sk_err = ECONNREFUSED;
+ break;
+ case DN_RUN:
+ sk->sk_shutdown |= SHUTDOWN_MASK;
+ scp->state = DN_DN;
+ break;
+ case DN_DI:
+ scp->state = DN_DIC;
+ break;
}
if (!sock_flag(sk, SOCK_DEAD)) {
@@ -470,23 +474,23 @@
sk->sk_state = TCP_CLOSE;
- switch(scp->state) {
- case DN_CI:
- scp->state = DN_NR;
- break;
- case DN_DR:
- if (reason == NSP_REASON_DC)
- scp->state = DN_DRC;
- if (reason == NSP_REASON_NL)
- scp->state = DN_CN;
- break;
- case DN_DI:
- scp->state = DN_DIC;
- break;
- case DN_RUN:
- sk->sk_shutdown |= SHUTDOWN_MASK;
- case DN_CC:
+ switch (scp->state) {
+ case DN_CI:
+ scp->state = DN_NR;
+ break;
+ case DN_DR:
+ if (reason == NSP_REASON_DC)
+ scp->state = DN_DRC;
+ if (reason == NSP_REASON_NL)
scp->state = DN_CN;
+ break;
+ case DN_DI:
+ scp->state = DN_DIC;
+ break;
+ case DN_RUN:
+ sk->sk_shutdown |= SHUTDOWN_MASK;
+ case DN_CC:
+ scp->state = DN_CN;
}
if (!sock_flag(sk, SOCK_DEAD)) {
@@ -692,16 +696,16 @@
goto out;
if ((reason != NSP_REASON_OK) && ((cb->nsp_flags & 0x0c) == 0x08)) {
- switch(cb->nsp_flags & 0x70) {
- case 0x10:
- case 0x60: /* (Retransmitted) Connect Init */
- dn_nsp_return_disc(skb, NSP_DISCINIT, reason);
- ret = NET_RX_SUCCESS;
- break;
- case 0x20: /* Connect Confirm */
- dn_nsp_return_disc(skb, NSP_DISCCONF, reason);
- ret = NET_RX_SUCCESS;
- break;
+ switch (cb->nsp_flags & 0x70) {
+ case 0x10:
+ case 0x60: /* (Retransmitted) Connect Init */
+ dn_nsp_return_disc(skb, NSP_DISCINIT, reason);
+ ret = NET_RX_SUCCESS;
+ break;
+ case 0x20: /* Connect Confirm */
+ dn_nsp_return_disc(skb, NSP_DISCCONF, reason);
+ ret = NET_RX_SUCCESS;
+ break;
}
}
@@ -733,17 +737,17 @@
* Filter out conninits and useless packet types
*/
if ((cb->nsp_flags & 0x0c) == 0x08) {
- switch(cb->nsp_flags & 0x70) {
- case 0x00: /* NOP */
- case 0x70: /* Reserved */
- case 0x50: /* Reserved, Phase II node init */
+ switch (cb->nsp_flags & 0x70) {
+ case 0x00: /* NOP */
+ case 0x70: /* Reserved */
+ case 0x50: /* Reserved, Phase II node init */
+ goto free_out;
+ case 0x10:
+ case 0x60:
+ if (unlikely(cb->rt_flags & DN_RT_F_RTS))
goto free_out;
- case 0x10:
- case 0x60:
- if (unlikely(cb->rt_flags & DN_RT_F_RTS))
- goto free_out;
- sk = dn_find_listener(skb, &reason);
- goto got_it;
+ sk = dn_find_listener(skb, &reason);
+ goto got_it;
}
}
@@ -836,20 +840,20 @@
* Control packet.
*/
if ((cb->nsp_flags & 0x0c) == 0x08) {
- switch(cb->nsp_flags & 0x70) {
- case 0x10:
- case 0x60:
- dn_nsp_conn_init(sk, skb);
- break;
- case 0x20:
- dn_nsp_conn_conf(sk, skb);
- break;
- case 0x30:
- dn_nsp_disc_init(sk, skb);
- break;
- case 0x40:
- dn_nsp_disc_conf(sk, skb);
- break;
+ switch (cb->nsp_flags & 0x70) {
+ case 0x10:
+ case 0x60:
+ dn_nsp_conn_init(sk, skb);
+ break;
+ case 0x20:
+ dn_nsp_conn_conf(sk, skb);
+ break;
+ case 0x30:
+ dn_nsp_disc_init(sk, skb);
+ break;
+ case 0x40:
+ dn_nsp_disc_conf(sk, skb);
+ break;
}
} else if (cb->nsp_flags == 0x24) {
@@ -890,15 +894,15 @@
if (scp->state != DN_RUN)
goto free_out;
- switch(cb->nsp_flags) {
- case 0x10: /* LS */
- dn_nsp_linkservice(sk, skb);
- break;
- case 0x30: /* OD */
- dn_nsp_otherdata(sk, skb);
- break;
- default:
- dn_nsp_data(sk, skb);
+ switch (cb->nsp_flags) {
+ case 0x10: /* LS */
+ dn_nsp_linkservice(sk, skb);
+ break;
+ case 0x30: /* OD */
+ dn_nsp_otherdata(sk, skb);
+ break;
+ default:
+ dn_nsp_data(sk, skb);
}
} else { /* Ack, chuck it out here */
diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c
index 74544bc..fceb86c 100644
--- a/net/decnet/dn_route.c
+++ b/net/decnet/dn_route.c
@@ -495,11 +495,11 @@
}
if ((skb->pkt_type == PACKET_HOST) && (cb->rt_flags & DN_RT_F_RQR)) {
- switch(cb->rt_flags & DN_RT_PKT_MSK) {
- case DN_RT_PKT_SHORT:
- return dn_return_short(skb);
- case DN_RT_PKT_LONG:
- return dn_return_long(skb);
+ switch (cb->rt_flags & DN_RT_PKT_MSK) {
+ case DN_RT_PKT_SHORT:
+ return dn_return_short(skb);
+ case DN_RT_PKT_LONG:
+ return dn_return_long(skb);
}
}
@@ -652,38 +652,38 @@
if (unlikely(skb_linearize(skb)))
goto dump_it;
- switch(flags & DN_RT_CNTL_MSK) {
- case DN_RT_PKT_INIT:
- dn_dev_init_pkt(skb);
- break;
- case DN_RT_PKT_VERI:
- dn_dev_veri_pkt(skb);
- break;
+ switch (flags & DN_RT_CNTL_MSK) {
+ case DN_RT_PKT_INIT:
+ dn_dev_init_pkt(skb);
+ break;
+ case DN_RT_PKT_VERI:
+ dn_dev_veri_pkt(skb);
+ break;
}
if (dn->parms.state != DN_DEV_S_RU)
goto dump_it;
- switch(flags & DN_RT_CNTL_MSK) {
- case DN_RT_PKT_HELO:
- return NF_HOOK(NFPROTO_DECNET, NF_DN_HELLO,
- skb, skb->dev, NULL,
- dn_route_ptp_hello);
+ switch (flags & DN_RT_CNTL_MSK) {
+ case DN_RT_PKT_HELO:
+ return NF_HOOK(NFPROTO_DECNET, NF_DN_HELLO,
+ skb, skb->dev, NULL,
+ dn_route_ptp_hello);
- case DN_RT_PKT_L1RT:
- case DN_RT_PKT_L2RT:
- return NF_HOOK(NFPROTO_DECNET, NF_DN_ROUTE,
- skb, skb->dev, NULL,
- dn_route_discard);
- case DN_RT_PKT_ERTH:
- return NF_HOOK(NFPROTO_DECNET, NF_DN_HELLO,
- skb, skb->dev, NULL,
- dn_neigh_router_hello);
+ case DN_RT_PKT_L1RT:
+ case DN_RT_PKT_L2RT:
+ return NF_HOOK(NFPROTO_DECNET, NF_DN_ROUTE,
+ skb, skb->dev, NULL,
+ dn_route_discard);
+ case DN_RT_PKT_ERTH:
+ return NF_HOOK(NFPROTO_DECNET, NF_DN_HELLO,
+ skb, skb->dev, NULL,
+ dn_neigh_router_hello);
- case DN_RT_PKT_EEDH:
- return NF_HOOK(NFPROTO_DECNET, NF_DN_HELLO,
- skb, skb->dev, NULL,
- dn_neigh_endnode_hello);
+ case DN_RT_PKT_EEDH:
+ return NF_HOOK(NFPROTO_DECNET, NF_DN_HELLO,
+ skb, skb->dev, NULL,
+ dn_neigh_endnode_hello);
}
} else {
if (dn->parms.state != DN_DEV_S_RU)
@@ -691,11 +691,11 @@
skb_pull(skb, 1); /* Pull flags */
- switch(flags & DN_RT_PKT_MSK) {
- case DN_RT_PKT_LONG:
- return dn_route_rx_long(skb);
- case DN_RT_PKT_SHORT:
- return dn_route_rx_short(skb);
+ switch (flags & DN_RT_PKT_MSK) {
+ case DN_RT_PKT_LONG:
+ return dn_route_rx_long(skb);
+ case DN_RT_PKT_SHORT:
+ return dn_route_rx_short(skb);
}
}
@@ -1419,20 +1419,20 @@
rt->dst.neighbour = neigh;
rt->dst.lastuse = jiffies;
rt->dst.output = dn_rt_bug;
- switch(res.type) {
- case RTN_UNICAST:
- rt->dst.input = dn_forward;
- break;
- case RTN_LOCAL:
- rt->dst.output = dn_output;
- rt->dst.input = dn_nsp_rx;
- rt->dst.dev = in_dev;
- flags |= RTCF_LOCAL;
- break;
- default:
- case RTN_UNREACHABLE:
- case RTN_BLACKHOLE:
- rt->dst.input = dst_discard;
+ switch (res.type) {
+ case RTN_UNICAST:
+ rt->dst.input = dn_forward;
+ break;
+ case RTN_LOCAL:
+ rt->dst.output = dn_output;
+ rt->dst.input = dn_nsp_rx;
+ rt->dst.dev = in_dev;
+ flags |= RTCF_LOCAL;
+ break;
+ default:
+ case RTN_UNREACHABLE:
+ case RTN_BLACKHOLE:
+ rt->dst.input = dst_discard;
}
rt->rt_flags = flags;
@@ -1841,10 +1841,11 @@
proc_net_fops_create(&init_net, "decnet_cache", S_IRUGO, &dn_rt_cache_seq_fops);
#ifdef CONFIG_DECNET_ROUTER
- rtnl_register(PF_DECnet, RTM_GETROUTE, dn_cache_getroute, dn_fib_dump);
+ rtnl_register(PF_DECnet, RTM_GETROUTE, dn_cache_getroute,
+ dn_fib_dump, NULL);
#else
rtnl_register(PF_DECnet, RTM_GETROUTE, dn_cache_getroute,
- dn_cache_dump);
+ dn_cache_dump, NULL);
#endif
}
diff --git a/net/decnet/dn_table.c b/net/decnet/dn_table.c
index bd0a52d..cd0354e 100644
--- a/net/decnet/dn_table.c
+++ b/net/decnet/dn_table.c
@@ -147,17 +147,18 @@
old_divisor = dz->dz_divisor;
- switch(old_divisor) {
- case 16:
- new_divisor = 256;
- new_hashmask = 0xFF;
- break;
- default:
- printk(KERN_DEBUG "DECnet: dn_rehash_zone: BUG! %d\n", old_divisor);
- case 256:
- new_divisor = 1024;
- new_hashmask = 0x3FF;
- break;
+ switch (old_divisor) {
+ case 16:
+ new_divisor = 256;
+ new_hashmask = 0xFF;
+ break;
+ default:
+ printk(KERN_DEBUG "DECnet: dn_rehash_zone: BUG! %d\n",
+ old_divisor);
+ case 256:
+ new_divisor = 1024;
+ new_hashmask = 0x3FF;
+ break;
}
ht = kcalloc(new_divisor, sizeof(struct dn_fib_node*), GFP_KERNEL);
diff --git a/net/decnet/netfilter/dn_rtmsg.c b/net/decnet/netfilter/dn_rtmsg.c
index 64a7f39..69975e0 100644
--- a/net/decnet/netfilter/dn_rtmsg.c
+++ b/net/decnet/netfilter/dn_rtmsg.c
@@ -69,15 +69,15 @@
int group = 0;
unsigned char flags = *skb->data;
- switch(flags & DN_RT_CNTL_MSK) {
- case DN_RT_PKT_L1RT:
- group = DNRNG_NLGRP_L1;
- break;
- case DN_RT_PKT_L2RT:
- group = DNRNG_NLGRP_L2;
- break;
- default:
- return;
+ switch (flags & DN_RT_CNTL_MSK) {
+ case DN_RT_PKT_L1RT:
+ group = DNRNG_NLGRP_L1;
+ break;
+ case DN_RT_PKT_L2RT:
+ group = DNRNG_NLGRP_L2;
+ break;
+ default:
+ return;
}
skb2 = dnrmg_build_message(skb, &status);
diff --git a/net/decnet/sysctl_net_decnet.c b/net/decnet/sysctl_net_decnet.c
index 28f8b5e..02e75d1 100644
--- a/net/decnet/sysctl_net_decnet.c
+++ b/net/decnet/sysctl_net_decnet.c
@@ -68,14 +68,15 @@
static void strip_it(char *str)
{
for(;;) {
- switch(*str) {
- case ' ':
- case '\n':
- case '\r':
- case ':':
- *str = 0;
- case 0:
- return;
+ switch (*str) {
+ case ' ':
+ case '\n':
+ case '\r':
+ case ':':
+ *str = 0;
+ /* Fallthrough */
+ case 0:
+ return;
}
str++;
}
diff --git a/net/dsa/mv88e6131.c b/net/dsa/mv88e6131.c
index 45f7411..9bd1061 100644
--- a/net/dsa/mv88e6131.c
+++ b/net/dsa/mv88e6131.c
@@ -118,10 +118,14 @@
REG_WRITE(REG_GLOBAL, 0x1a, (dsa_upstream_port(ds) * 0x1100) | 0x00f0);
/*
- * Disable cascade port functionality, and set the switch's
+ * Disable cascade port functionality unless this device
+ * is used in a cascade configuration, and set the switch's
* DSA device number.
*/
- REG_WRITE(REG_GLOBAL, 0x1c, 0xe000 | (ds->index & 0x1f));
+ if (ds->dst->pd->nr_chips > 1)
+ REG_WRITE(REG_GLOBAL, 0x1c, 0xf000 | (ds->index & 0x1f));
+ else
+ REG_WRITE(REG_GLOBAL, 0x1c, 0xe000 | (ds->index & 0x1f));
/*
* Send all frames with destination addresses matching
diff --git a/net/econet/af_econet.c b/net/econet/af_econet.c
index a1d9f37..1c1f26c 100644
--- a/net/econet/af_econet.c
+++ b/net/econet/af_econet.c
@@ -9,6 +9,8 @@
*
*/
+#define pr_fmt(fmt) fmt
+
#include <linux/module.h>
#include <linux/types.h>
@@ -44,7 +46,7 @@
#include <linux/bitops.h>
#include <linux/mutex.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
#include <asm/system.h>
static const struct proto_ops econet_ops;
@@ -63,9 +65,7 @@
static struct socket *udpsock;
#define AUN_PORT 0x8000
-
-struct aunhdr
-{
+struct aunhdr {
unsigned char code; /* AUN magic protocol byte */
unsigned char port;
unsigned char cb;
@@ -82,8 +82,7 @@
#endif /* CONFIG_ECONET_AUNUDP */
/* Per-packet information */
-struct ec_cb
-{
+struct ec_cb {
struct sockaddr_ec sec;
unsigned long cookie; /* Supplied by user. */
#ifdef CONFIG_ECONET_AUNUDP
@@ -137,7 +136,7 @@
* but then it will block.
*/
- skb=skb_recv_datagram(sk,flags,flags&MSG_DONTWAIT,&err);
+ skb = skb_recv_datagram(sk, flags, flags & MSG_DONTWAIT, &err);
/*
* An error occurred so return it. Because skb_recv_datagram()
@@ -145,7 +144,7 @@
* retries.
*/
- if(skb==NULL)
+ if (skb == NULL)
goto out;
/*
@@ -154,10 +153,9 @@
*/
copied = skb->len;
- if (copied > len)
- {
- copied=len;
- msg->msg_flags|=MSG_TRUNC;
+ if (copied > len) {
+ copied = len;
+ msg->msg_flags |= MSG_TRUNC;
}
/* We can't use skb_copy_datagram here */
@@ -186,7 +184,8 @@
* Bind an Econet socket.
*/
-static int econet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
+static int econet_bind(struct socket *sock, struct sockaddr *uaddr,
+ int addr_len)
{
struct sockaddr_ec *sec = (struct sockaddr_ec *)uaddr;
struct sock *sk;
@@ -226,9 +225,8 @@
struct ec_cb *eb;
struct sockaddr_ec *sec;
- if (skb == NULL)
- {
- printk(KERN_DEBUG "ec: memory squeeze, transmit result dropped.\n");
+ if (skb == NULL) {
+ pr_debug("econet: memory squeeze, transmit result dropped\n");
return;
}
@@ -265,7 +263,7 @@
static int econet_sendmsg(struct kiocb *iocb, struct socket *sock,
struct msghdr *msg, size_t len)
{
- struct sockaddr_ec *saddr=(struct sockaddr_ec *)msg->msg_name;
+ struct sockaddr_ec *saddr = (struct sockaddr_ec *)msg->msg_name;
struct net_device *dev;
struct ec_addr addr;
int err;
@@ -298,14 +296,14 @@
mutex_lock(&econet_mutex);
- if (saddr == NULL || msg->msg_namelen < sizeof(struct sockaddr_ec)) {
- mutex_unlock(&econet_mutex);
- return -EINVAL;
- }
- addr.station = saddr->addr.station;
- addr.net = saddr->addr.net;
- port = saddr->port;
- cb = saddr->cb;
+ if (saddr == NULL || msg->msg_namelen < sizeof(struct sockaddr_ec)) {
+ mutex_unlock(&econet_mutex);
+ return -EINVAL;
+ }
+ addr.station = saddr->addr.station;
+ addr.net = saddr->addr.net;
+ port = saddr->port;
+ cb = saddr->cb;
/* Look for a device with the right network number. */
dev = net2dev_map[addr.net];
@@ -333,9 +331,9 @@
dev_hold(dev);
- skb = sock_alloc_send_skb(sk, len+LL_ALLOCATED_SPACE(dev),
+ skb = sock_alloc_send_skb(sk, len + LL_ALLOCATED_SPACE(dev),
msg->msg_flags & MSG_DONTWAIT, &err);
- if (skb==NULL)
+ if (skb == NULL)
goto out_unlock;
skb_reserve(skb, LL_RESERVED_SPACE(dev));
@@ -355,7 +353,7 @@
struct ec_framehdr *fh;
/* Poke in our control byte and
port number. Hack, hack. */
- fh = (struct ec_framehdr *)(skb->data);
+ fh = (struct ec_framehdr *)skb->data;
fh->cb = cb;
fh->port = port;
if (sock->type != SOCK_DGRAM) {
@@ -365,7 +363,7 @@
}
/* Copy the data. Returns -EFAULT on error */
- err = memcpy_fromiovec(skb_put(skb,len), msg->msg_iov, len);
+ err = memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len);
skb->protocol = proto;
skb->dev = dev;
skb->priority = sk->sk_priority;
@@ -385,9 +383,9 @@
mutex_unlock(&econet_mutex);
return len;
- out_free:
+out_free:
kfree_skb(skb);
- out_unlock:
+out_unlock:
if (dev)
dev_put(dev);
#else
@@ -458,15 +456,14 @@
goto error_free_buf;
/* Get a skbuff (no data, just holds our cb information) */
- if ((skb = sock_alloc_send_skb(sk, 0,
- msg->msg_flags & MSG_DONTWAIT,
- &err)) == NULL)
+ skb = sock_alloc_send_skb(sk, 0, msg->msg_flags & MSG_DONTWAIT, &err);
+ if (skb == NULL)
goto error_free_buf;
eb = (struct ec_cb *)&skb->cb;
eb->cookie = saddr->cookie;
- eb->timeout = (5*HZ);
+ eb->timeout = 5 * HZ;
eb->start = jiffies;
ah.handle = aun_seq;
eb->seq = (aun_seq++);
@@ -480,9 +477,10 @@
udpmsg.msg_iovlen = 2;
udpmsg.msg_control = NULL;
udpmsg.msg_controllen = 0;
- udpmsg.msg_flags=0;
+ udpmsg.msg_flags = 0;
- oldfs = get_fs(); set_fs(KERNEL_DS); /* More privs :-) */
+ oldfs = get_fs();
+ set_fs(KERNEL_DS); /* More privs :-) */
err = sock_sendmsg(udpsock, &udpmsg, size);
set_fs(oldfs);
@@ -530,7 +528,7 @@
static void econet_destroy_timer(unsigned long data)
{
- struct sock *sk=(struct sock *)data;
+ struct sock *sk = (struct sock *)data;
if (!sk_has_allocations(sk)) {
sk_free(sk);
@@ -539,7 +537,7 @@
sk->sk_timer.expires = jiffies + 10 * HZ;
add_timer(&sk->sk_timer);
- printk(KERN_DEBUG "econet socket destroy delayed\n");
+ pr_debug("econet: socket destroy delayed\n");
}
/*
@@ -651,7 +649,8 @@
if (copy_from_user(&ifr, arg, sizeof(struct ifreq)))
return -EFAULT;
- if ((dev = dev_get_by_name(&init_net, ifr.ifr_name)) == NULL)
+ dev = dev_get_by_name(&init_net, ifr.ifr_name);
+ if (dev == NULL)
return -ENODEV;
sec = (struct sockaddr_ec *)&ifr.ifr_addr;
@@ -715,28 +714,26 @@
* Handle generic ioctls
*/
-static int econet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
+static int econet_ioctl(struct socket *sock, unsigned int cmd,
+ unsigned long arg)
{
struct sock *sk = sock->sk;
void __user *argp = (void __user *)arg;
- switch(cmd) {
- case SIOCGSTAMP:
- return sock_get_timestamp(sk, argp);
+ switch (cmd) {
+ case SIOCGSTAMP:
+ return sock_get_timestamp(sk, argp);
- case SIOCGSTAMPNS:
- return sock_get_timestampns(sk, argp);
+ case SIOCGSTAMPNS:
+ return sock_get_timestampns(sk, argp);
- case SIOCSIFADDR:
- case SIOCGIFADDR:
- return ec_dev_ioctl(sock, cmd, argp);
- break;
+ case SIOCSIFADDR:
+ case SIOCGIFADDR:
+ return ec_dev_ioctl(sock, cmd, argp);
- default:
- return -ENOIOCTLCMD;
}
- /*NOTREACHED*/
- return 0;
+
+ return -ENOIOCTLCMD;
}
static const struct net_proto_family econet_family_ops = {
@@ -836,7 +833,7 @@
udpmsg.msg_namelen = sizeof(sin);
udpmsg.msg_control = NULL;
udpmsg.msg_controllen = 0;
- udpmsg.msg_flags=0;
+ udpmsg.msg_flags = 0;
kernel_sendmsg(udpsock, &udpmsg, &iov, 1, sizeof(ah));
}
@@ -859,26 +856,25 @@
if (dst)
edev = dst->dev->ec_ptr;
- if (! edev)
+ if (!edev)
goto bad;
- if ((sk = ec_listening_socket(ah->port, stn, edev->net)) == NULL)
+ sk = ec_listening_socket(ah->port, stn, edev->net);
+ if (sk == NULL)
goto bad; /* Nobody wants it */
newskb = alloc_skb((len - sizeof(struct aunhdr) + 15) & ~15,
GFP_ATOMIC);
- if (newskb == NULL)
- {
- printk(KERN_DEBUG "AUN: memory squeeze, dropping packet.\n");
+ if (newskb == NULL) {
+ pr_debug("AUN: memory squeeze, dropping packet\n");
/* Send nack and hope sender tries again */
goto bad;
}
- memcpy(skb_put(newskb, len - sizeof(struct aunhdr)), (void *)(ah+1),
+ memcpy(skb_put(newskb, len - sizeof(struct aunhdr)), (void *)(ah + 1),
len - sizeof(struct aunhdr));
- if (ec_queue_packet(sk, newskb, stn, edev->net, ah->cb, ah->port))
- {
+ if (ec_queue_packet(sk, newskb, stn, edev->net, ah->cb, ah->port)) {
/* Socket is bankrupt. */
kfree_skb(newskb);
goto bad;
@@ -914,7 +910,7 @@
goto foundit;
}
spin_unlock_irqrestore(&aun_queue_lock, flags);
- printk(KERN_DEBUG "AUN: unknown sequence %ld\n", seq);
+ pr_debug("AUN: unknown sequence %ld\n", seq);
return;
foundit:
@@ -939,18 +935,17 @@
while ((skb = skb_recv_datagram(sk, 0, 1, &err)) == NULL) {
if (err == -EAGAIN) {
- printk(KERN_ERR "AUN: no data available?!");
+ pr_err("AUN: no data available?!\n");
return;
}
- printk(KERN_DEBUG "AUN: recvfrom() error %d\n", -err);
+ pr_debug("AUN: recvfrom() error %d\n", -err);
}
data = skb_transport_header(skb) + sizeof(struct udphdr);
ah = (struct aunhdr *)data;
len = skb->len - sizeof(struct udphdr);
- switch (ah->code)
- {
+ switch (ah->code) {
case 2:
aun_incoming(skb, ah, len);
break;
@@ -961,7 +956,7 @@
aun_tx_ack(ah->handle, ECTYPE_TRANSMIT_NOT_LISTENING);
break;
default:
- printk(KERN_DEBUG "unknown AUN packet (type %d)\n", data[0]);
+ pr_debug("AUN: unknown packet type: %d\n", data[0]);
}
skb_free_datagram(sk, skb);
@@ -991,7 +986,7 @@
}
spin_unlock_irqrestore(&aun_queue_lock, flags);
- mod_timer(&ab_cleanup_timer, jiffies + (HZ*2));
+ mod_timer(&ab_cleanup_timer, jiffies + (HZ * 2));
}
static int __init aun_udp_initialise(void)
@@ -1001,7 +996,7 @@
skb_queue_head_init(&aun_queue);
setup_timer(&ab_cleanup_timer, ab_cleanup, 0);
- ab_cleanup_timer.expires = jiffies + (HZ*2);
+ ab_cleanup_timer.expires = jiffies + (HZ * 2);
add_timer(&ab_cleanup_timer);
memset(&sin, 0, sizeof(sin));
@@ -1009,9 +1004,9 @@
/* We can count ourselves lucky Acorn machines are too dim to
speak IPv6. :-) */
- if ((error = sock_create_kern(PF_INET, SOCK_DGRAM, 0, &udpsock)) < 0)
- {
- printk("AUN: socket error %d\n", -error);
+ error = sock_create_kern(PF_INET, SOCK_DGRAM, 0, &udpsock);
+ if (error < 0) {
+ pr_err("AUN: socket error %d\n", -error);
return error;
}
@@ -1020,10 +1015,9 @@
from interrupts */
error = udpsock->ops->bind(udpsock, (struct sockaddr *)&sin,
- sizeof(sin));
- if (error < 0)
- {
- printk("AUN: bind error %d\n", -error);
+ sizeof(sin));
+ if (error < 0) {
+ pr_err("AUN: bind error %d\n", -error);
goto release;
}
@@ -1044,7 +1038,8 @@
* Receive an Econet frame from a device.
*/
-static int econet_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev)
+static int econet_rcv(struct sk_buff *skb, struct net_device *dev,
+ struct packet_type *pt, struct net_device *orig_dev)
{
struct ec_framehdr *hdr;
struct sock *sk = NULL;
@@ -1059,13 +1054,14 @@
if (!edev)
goto drop;
- if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL)
+ skb = skb_share_check(skb, GFP_ATOMIC);
+ if (skb == NULL)
return NET_RX_DROP;
if (!pskb_may_pull(skb, sizeof(struct ec_framehdr)))
goto drop;
- hdr = (struct ec_framehdr *) skb->data;
+ hdr = (struct ec_framehdr *)skb->data;
/* First check for encapsulated IP */
if (hdr->port == EC_PORT_IP) {
@@ -1093,8 +1089,8 @@
}
static struct packet_type econet_packet_type __read_mostly = {
- .type = cpu_to_be16(ETH_P_ECONET),
- .func = econet_rcv,
+ .type = cpu_to_be16(ETH_P_ECONET),
+ .func = econet_rcv,
};
static void econet_hw_initialise(void)
@@ -1104,9 +1100,10 @@
#endif
-static int econet_notifier(struct notifier_block *this, unsigned long msg, void *data)
+static int econet_notifier(struct notifier_block *this, unsigned long msg,
+ void *data)
{
- struct net_device *dev = (struct net_device *)data;
+ struct net_device *dev = data;
struct ec_device *edev;
if (!net_eq(dev_net(dev), &init_net))
@@ -1116,8 +1113,7 @@
case NETDEV_UNREGISTER:
/* A device has gone down - kill any data we hold for it. */
edev = dev->ec_ptr;
- if (edev)
- {
+ if (edev) {
if (net2dev_map[0] == dev)
net2dev_map[0] = NULL;
net2dev_map[edev->net] = NULL;
@@ -1131,7 +1127,7 @@
}
static struct notifier_block econet_netdev_notifier = {
- .notifier_call =econet_notifier,
+ .notifier_call = econet_notifier,
};
static void __exit econet_proto_exit(void)
diff --git a/net/ieee802154/af_ieee802154.c b/net/ieee802154/af_ieee802154.c
index 6df6ecf..40e606f 100644
--- a/net/ieee802154/af_ieee802154.c
+++ b/net/ieee802154/af_ieee802154.c
@@ -302,7 +302,7 @@
struct packet_type *pt, struct net_device *orig_dev)
{
if (!netif_running(dev))
- return -ENODEV;
+ goto drop;
pr_debug("got frame, type %d, dev %p\n", dev->type, dev);
#ifdef DEBUG
print_hex_dump_bytes("ieee802154_rcv ", DUMP_PREFIX_NONE, skb->data, skb->len);
diff --git a/net/ieee802154/dgram.c b/net/ieee802154/dgram.c
index 1a3334c..faecf64 100644
--- a/net/ieee802154/dgram.c
+++ b/net/ieee802154/dgram.c
@@ -1,5 +1,5 @@
/*
- * ZigBee socket interface
+ * IEEE 802.15.4 dgram socket interface
*
* Copyright 2007, 2008 Siemens AG
*
diff --git a/net/ieee802154/nl-phy.c b/net/ieee802154/nl-phy.c
index 02548b2..c64a38d 100644
--- a/net/ieee802154/nl-phy.c
+++ b/net/ieee802154/nl-phy.c
@@ -24,6 +24,7 @@
#include <linux/kernel.h>
#include <linux/slab.h>
+#include <linux/if_arp.h>
#include <net/netlink.h>
#include <net/genetlink.h>
#include <net/wpan-phy.h>
@@ -213,12 +214,37 @@
goto nla_put_failure;
}
+ if (info->attrs[IEEE802154_ATTR_HW_ADDR] &&
+ nla_len(info->attrs[IEEE802154_ATTR_HW_ADDR]) !=
+ IEEE802154_ADDR_LEN) {
+ rc = -EINVAL;
+ goto nla_put_failure;
+ }
+
dev = phy->add_iface(phy, devname);
if (IS_ERR(dev)) {
rc = PTR_ERR(dev);
goto nla_put_failure;
}
+ if (info->attrs[IEEE802154_ATTR_HW_ADDR]) {
+ struct sockaddr addr;
+
+ addr.sa_family = ARPHRD_IEEE802154;
+ nla_memcpy(&addr.sa_data, info->attrs[IEEE802154_ATTR_HW_ADDR],
+ IEEE802154_ADDR_LEN);
+
+ /*
+ * strangely enough, some callbacks (inetdev_event) from
+ * dev_set_mac_address require RTNL_LOCK
+ */
+ rtnl_lock();
+ rc = dev_set_mac_address(dev, &addr);
+ rtnl_unlock();
+ if (rc)
+ goto dev_unregister;
+ }
+
NLA_PUT_STRING(msg, IEEE802154_ATTR_PHY_NAME, wpan_phy_name(phy));
NLA_PUT_STRING(msg, IEEE802154_ATTR_DEV_NAME, dev->name);
@@ -228,6 +254,11 @@
return ieee802154_nl_reply(msg, info);
+dev_unregister:
+ rtnl_lock(); /* del_iface must be called with RTNL lock */
+ phy->del_iface(phy, dev);
+ dev_put(dev);
+ rtnl_unlock();
nla_put_failure:
nlmsg_free(msg);
out_dev:
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index ef1528a..1b745d4 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -1440,11 +1440,11 @@
unsigned long snmp_fold_field(void __percpu *mib[], int offt)
{
unsigned long res = 0;
- int i;
+ int i, j;
for_each_possible_cpu(i) {
- res += *(((unsigned long *) per_cpu_ptr(mib[0], i)) + offt);
- res += *(((unsigned long *) per_cpu_ptr(mib[1], i)) + offt);
+ for (j = 0; j < SNMP_ARRAY_SZ; j++)
+ res += *(((unsigned long *) per_cpu_ptr(mib[j], i)) + offt);
}
return res;
}
@@ -1458,28 +1458,19 @@
int cpu;
for_each_possible_cpu(cpu) {
- void *bhptr, *userptr;
+ void *bhptr;
struct u64_stats_sync *syncp;
- u64 v_bh, v_user;
+ u64 v;
unsigned int start;
- /* first mib used by softirq context, we must use _bh() accessors */
- bhptr = per_cpu_ptr(SNMP_STAT_BHPTR(mib), cpu);
+ bhptr = per_cpu_ptr(mib[0], cpu);
syncp = (struct u64_stats_sync *)(bhptr + syncp_offset);
do {
start = u64_stats_fetch_begin_bh(syncp);
- v_bh = *(((u64 *) bhptr) + offt);
+ v = *(((u64 *) bhptr) + offt);
} while (u64_stats_fetch_retry_bh(syncp, start));
- /* second mib used in USER context */
- userptr = per_cpu_ptr(SNMP_STAT_USRPTR(mib), cpu);
- syncp = (struct u64_stats_sync *)(userptr + syncp_offset);
- do {
- start = u64_stats_fetch_begin(syncp);
- v_user = *(((u64 *) userptr) + offt);
- } while (u64_stats_fetch_retry(syncp, start));
-
- res += v_bh + v_user;
+ res += v;
}
return res;
}
@@ -1491,25 +1482,28 @@
BUG_ON(ptr == NULL);
ptr[0] = __alloc_percpu(mibsize, align);
if (!ptr[0])
- goto err0;
+ return -ENOMEM;
+#if SNMP_ARRAY_SZ == 2
ptr[1] = __alloc_percpu(mibsize, align);
- if (!ptr[1])
- goto err1;
+ if (!ptr[1]) {
+ free_percpu(ptr[0]);
+ ptr[0] = NULL;
+ return -ENOMEM;
+ }
+#endif
return 0;
-err1:
- free_percpu(ptr[0]);
- ptr[0] = NULL;
-err0:
- return -ENOMEM;
}
EXPORT_SYMBOL_GPL(snmp_mib_init);
-void snmp_mib_free(void __percpu *ptr[2])
+void snmp_mib_free(void __percpu *ptr[SNMP_ARRAY_SZ])
{
+ int i;
+
BUG_ON(ptr == NULL);
- free_percpu(ptr[0]);
- free_percpu(ptr[1]);
- ptr[0] = ptr[1] = NULL;
+ for (i = 0; i < SNMP_ARRAY_SZ; i++) {
+ free_percpu(ptr[i]);
+ ptr[i] = NULL;
+ }
}
EXPORT_SYMBOL_GPL(snmp_mib_free);
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index 0d4a184..37b3c18 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -1833,8 +1833,8 @@
rtnl_af_register(&inet_af_ops);
- rtnl_register(PF_INET, RTM_NEWADDR, inet_rtm_newaddr, NULL);
- rtnl_register(PF_INET, RTM_DELADDR, inet_rtm_deladdr, NULL);
- rtnl_register(PF_INET, RTM_GETADDR, NULL, inet_dump_ifaddr);
+ rtnl_register(PF_INET, RTM_NEWADDR, inet_rtm_newaddr, NULL, NULL);
+ rtnl_register(PF_INET, RTM_DELADDR, inet_rtm_deladdr, NULL, NULL);
+ rtnl_register(PF_INET, RTM_GETADDR, NULL, inet_dump_ifaddr, NULL);
}
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c
index 2252471..92fc5f6 100644
--- a/net/ipv4/fib_frontend.c
+++ b/net/ipv4/fib_frontend.c
@@ -1124,9 +1124,9 @@
void __init ip_fib_init(void)
{
- rtnl_register(PF_INET, RTM_NEWROUTE, inet_rtm_newroute, NULL);
- rtnl_register(PF_INET, RTM_DELROUTE, inet_rtm_delroute, NULL);
- rtnl_register(PF_INET, RTM_GETROUTE, NULL, inet_dump_fib);
+ rtnl_register(PF_INET, RTM_NEWROUTE, inet_rtm_newroute, NULL, NULL);
+ rtnl_register(PF_INET, RTM_DELROUTE, inet_rtm_delroute, NULL, NULL);
+ rtnl_register(PF_INET, RTM_GETROUTE, NULL, inet_dump_fib, NULL);
register_pernet_subsys(&fib_net_ops);
register_netdevice_notifier(&fib_netdev_notifier);
diff --git a/net/ipv4/gre.c b/net/ipv4/gre.c
index c6933f2..9dbe108 100644
--- a/net/ipv4/gre.c
+++ b/net/ipv4/gre.c
@@ -16,7 +16,6 @@
#include <linux/skbuff.h>
#include <linux/in.h>
#include <linux/netdevice.h>
-#include <linux/version.h>
#include <linux/spinlock.h>
#include <net/protocol.h>
#include <net/gre.h>
diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c
index 3267d38..389a2e6 100644
--- a/net/ipv4/inet_diag.c
+++ b/net/ipv4/inet_diag.c
@@ -869,7 +869,7 @@
}
return netlink_dump_start(idiagnl, skb, nlh,
- inet_diag_dump, NULL);
+ inet_diag_dump, NULL, 0);
}
return inet_diag_get_exact(skb, nlh);
diff --git a/net/ipv4/inetpeer.c b/net/ipv4/inetpeer.c
index ce616d9..dafbf2c 100644
--- a/net/ipv4/inetpeer.c
+++ b/net/ipv4/inetpeer.c
@@ -54,15 +54,11 @@
* 1. Nodes may appear in the tree only with the pool lock held.
* 2. Nodes may disappear from the tree only with the pool lock held
* AND reference count being 0.
- * 3. Nodes appears and disappears from unused node list only under
- * "inet_peer_unused_lock".
- * 4. Global variable peer_total is modified under the pool lock.
- * 5. struct inet_peer fields modification:
+ * 3. Global variable peer_total is modified under the pool lock.
+ * 4. struct inet_peer fields modification:
* avl_left, avl_right, avl_parent, avl_height: pool lock
- * unused: unused node list lock
* refcnt: atomically against modifications on other CPU;
* usually under some other lock to prevent node disappearing
- * dtime: unused node list lock
* daddr: unchangeable
* ip_id_count: atomic value (no lock needed)
*/
@@ -104,19 +100,6 @@
* aggressively at this stage */
int inet_peer_minttl __read_mostly = 120 * HZ; /* TTL under high load: 120 sec */
int inet_peer_maxttl __read_mostly = 10 * 60 * HZ; /* usual time to live: 10 min */
-int inet_peer_gc_mintime __read_mostly = 10 * HZ;
-int inet_peer_gc_maxtime __read_mostly = 120 * HZ;
-
-static struct {
- struct list_head list;
- spinlock_t lock;
-} unused_peers = {
- .list = LIST_HEAD_INIT(unused_peers.list),
- .lock = __SPIN_LOCK_UNLOCKED(unused_peers.lock),
-};
-
-static void peer_check_expire(unsigned long dummy);
-static DEFINE_TIMER(peer_periodic_timer, peer_check_expire, 0, 0);
/* Called from ip_output.c:ip_init */
@@ -142,21 +125,6 @@
0, SLAB_HWCACHE_ALIGN | SLAB_PANIC,
NULL);
- /* All the timers, started at system startup tend
- to synchronize. Perturb it a bit.
- */
- peer_periodic_timer.expires = jiffies
- + net_random() % inet_peer_gc_maxtime
- + inet_peer_gc_maxtime;
- add_timer(&peer_periodic_timer);
-}
-
-/* Called with or without local BH being disabled. */
-static void unlink_from_unused(struct inet_peer *p)
-{
- spin_lock_bh(&unused_peers.lock);
- list_del_init(&p->unused);
- spin_unlock_bh(&unused_peers.lock);
}
static int addr_compare(const struct inetpeer_addr *a,
@@ -203,20 +171,6 @@
u; \
})
-static bool atomic_add_unless_return(atomic_t *ptr, int a, int u, int *newv)
-{
- int cur, old = atomic_read(ptr);
-
- while (old != u) {
- *newv = old + a;
- cur = atomic_cmpxchg(ptr, old, *newv);
- if (cur == old)
- return true;
- old = cur;
- }
- return false;
-}
-
/*
* Called with rcu_read_lock()
* Because we hold no lock against a writer, its quite possible we fall
@@ -225,8 +179,7 @@
* We exit from this function if number of links exceeds PEER_MAXDEPTH
*/
static struct inet_peer *lookup_rcu(const struct inetpeer_addr *daddr,
- struct inet_peer_base *base,
- int *newrefcnt)
+ struct inet_peer_base *base)
{
struct inet_peer *u = rcu_dereference(base->root);
int count = 0;
@@ -235,11 +188,9 @@
int cmp = addr_compare(daddr, &u->daddr);
if (cmp == 0) {
/* Before taking a reference, check if this entry was
- * deleted, unlink_from_pool() sets refcnt=-1 to make
- * distinction between an unused entry (refcnt=0) and
- * a freed one.
+ * deleted (refcnt=-1)
*/
- if (!atomic_add_unless_return(&u->refcnt, 1, -1, newrefcnt))
+ if (!atomic_add_unless(&u->refcnt, 1, -1))
u = NULL;
return u;
}
@@ -366,137 +317,96 @@
kmem_cache_free(peer_cachep, container_of(head, struct inet_peer, rcu));
}
-/* May be called with local BH enabled. */
static void unlink_from_pool(struct inet_peer *p, struct inet_peer_base *base,
struct inet_peer __rcu **stack[PEER_MAXDEPTH])
{
- int do_free;
+ struct inet_peer __rcu ***stackptr, ***delp;
- do_free = 0;
-
- write_seqlock_bh(&base->lock);
- /* Check the reference counter. It was artificially incremented by 1
- * in cleanup() function to prevent sudden disappearing. If we can
- * atomically (because of lockless readers) take this last reference,
- * it's safe to remove the node and free it later.
- * We use refcnt=-1 to alert lockless readers this entry is deleted.
- */
- if (atomic_cmpxchg(&p->refcnt, 1, -1) == 1) {
- struct inet_peer __rcu ***stackptr, ***delp;
- if (lookup(&p->daddr, stack, base) != p)
- BUG();
- delp = stackptr - 1; /* *delp[0] == p */
- if (p->avl_left == peer_avl_empty_rcu) {
- *delp[0] = p->avl_right;
- --stackptr;
- } else {
- /* look for a node to insert instead of p */
- struct inet_peer *t;
- t = lookup_rightempty(p, base);
- BUG_ON(rcu_deref_locked(*stackptr[-1], base) != t);
- **--stackptr = t->avl_left;
- /* t is removed, t->daddr > x->daddr for any
- * x in p->avl_left subtree.
- * Put t in the old place of p. */
- RCU_INIT_POINTER(*delp[0], t);
- t->avl_left = p->avl_left;
- t->avl_right = p->avl_right;
- t->avl_height = p->avl_height;
- BUG_ON(delp[1] != &p->avl_left);
- delp[1] = &t->avl_left; /* was &p->avl_left */
- }
- peer_avl_rebalance(stack, stackptr, base);
- base->total--;
- do_free = 1;
+ if (lookup(&p->daddr, stack, base) != p)
+ BUG();
+ delp = stackptr - 1; /* *delp[0] == p */
+ if (p->avl_left == peer_avl_empty_rcu) {
+ *delp[0] = p->avl_right;
+ --stackptr;
+ } else {
+ /* look for a node to insert instead of p */
+ struct inet_peer *t;
+ t = lookup_rightempty(p, base);
+ BUG_ON(rcu_deref_locked(*stackptr[-1], base) != t);
+ **--stackptr = t->avl_left;
+ /* t is removed, t->daddr > x->daddr for any
+ * x in p->avl_left subtree.
+ * Put t in the old place of p. */
+ RCU_INIT_POINTER(*delp[0], t);
+ t->avl_left = p->avl_left;
+ t->avl_right = p->avl_right;
+ t->avl_height = p->avl_height;
+ BUG_ON(delp[1] != &p->avl_left);
+ delp[1] = &t->avl_left; /* was &p->avl_left */
}
- write_sequnlock_bh(&base->lock);
-
- if (do_free)
- call_rcu(&p->rcu, inetpeer_free_rcu);
- else
- /* The node is used again. Decrease the reference counter
- * back. The loop "cleanup -> unlink_from_unused
- * -> unlink_from_pool -> putpeer -> link_to_unused
- * -> cleanup (for the same node)"
- * doesn't really exist because the entry will have a
- * recent deletion time and will not be cleaned again soon.
- */
- inet_putpeer(p);
+ peer_avl_rebalance(stack, stackptr, base);
+ base->total--;
+ call_rcu(&p->rcu, inetpeer_free_rcu);
}
static struct inet_peer_base *family_to_base(int family)
{
- return (family == AF_INET ? &v4_peers : &v6_peers);
+ return family == AF_INET ? &v4_peers : &v6_peers;
}
-static struct inet_peer_base *peer_to_base(struct inet_peer *p)
+/* perform garbage collect on all items stacked during a lookup */
+static int inet_peer_gc(struct inet_peer_base *base,
+ struct inet_peer __rcu **stack[PEER_MAXDEPTH],
+ struct inet_peer __rcu ***stackptr)
{
- return family_to_base(p->daddr.family);
-}
+ struct inet_peer *p, *gchead = NULL;
+ __u32 delta, ttl;
+ int cnt = 0;
-/* May be called with local BH enabled. */
-static int cleanup_once(unsigned long ttl, struct inet_peer __rcu **stack[PEER_MAXDEPTH])
-{
- struct inet_peer *p = NULL;
-
- /* Remove the first entry from the list of unused nodes. */
- spin_lock_bh(&unused_peers.lock);
- if (!list_empty(&unused_peers.list)) {
- __u32 delta;
-
- p = list_first_entry(&unused_peers.list, struct inet_peer, unused);
+ if (base->total >= inet_peer_threshold)
+ ttl = 0; /* be aggressive */
+ else
+ ttl = inet_peer_maxttl
+ - (inet_peer_maxttl - inet_peer_minttl) / HZ *
+ base->total / inet_peer_threshold * HZ;
+ stackptr--; /* last stack slot is peer_avl_empty */
+ while (stackptr > stack) {
+ stackptr--;
+ p = rcu_deref_locked(**stackptr, base);
delta = (__u32)jiffies - p->dtime;
-
- if (delta < ttl) {
- /* Do not prune fresh entries. */
- spin_unlock_bh(&unused_peers.lock);
- return -1;
+ if (atomic_read(&p->refcnt) == 0 && delta >= ttl &&
+ atomic_cmpxchg(&p->refcnt, 0, -1) == 0) {
+ p->gc_next = gchead;
+ gchead = p;
}
-
- list_del_init(&p->unused);
-
- /* Grab an extra reference to prevent node disappearing
- * before unlink_from_pool() call. */
- atomic_inc(&p->refcnt);
}
- spin_unlock_bh(&unused_peers.lock);
-
- if (p == NULL)
- /* It means that the total number of USED entries has
- * grown over inet_peer_threshold. It shouldn't really
- * happen because of entry limits in route cache. */
- return -1;
-
- unlink_from_pool(p, peer_to_base(p), stack);
- return 0;
+ while ((p = gchead) != NULL) {
+ gchead = p->gc_next;
+ cnt++;
+ unlink_from_pool(p, base, stack);
+ }
+ return cnt;
}
-/* Called with or without local BH being disabled. */
struct inet_peer *inet_getpeer(struct inetpeer_addr *daddr, int create)
{
struct inet_peer __rcu **stack[PEER_MAXDEPTH], ***stackptr;
struct inet_peer_base *base = family_to_base(daddr->family);
struct inet_peer *p;
unsigned int sequence;
- int invalidated, newrefcnt = 0;
+ int invalidated, gccnt = 0;
- /* Look up for the address quickly, lockless.
+ /* Attempt a lockless lookup first.
* Because of a concurrent writer, we might not find an existing entry.
*/
rcu_read_lock();
sequence = read_seqbegin(&base->lock);
- p = lookup_rcu(daddr, base, &newrefcnt);
+ p = lookup_rcu(daddr, base);
invalidated = read_seqretry(&base->lock, sequence);
rcu_read_unlock();
- if (p) {
-found: /* The existing node has been found.
- * Remove the entry from unused list if it was there.
- */
- if (newrefcnt == 1)
- unlink_from_unused(p);
+ if (p)
return p;
- }
/* If no writer did a change during our lookup, we can return early. */
if (!create && !invalidated)
@@ -506,11 +416,17 @@
* At least, nodes should be hot in our cache.
*/
write_seqlock_bh(&base->lock);
+relookup:
p = lookup(daddr, stack, base);
if (p != peer_avl_empty) {
- newrefcnt = atomic_inc_return(&p->refcnt);
+ atomic_inc(&p->refcnt);
write_sequnlock_bh(&base->lock);
- goto found;
+ return p;
+ }
+ if (!gccnt) {
+ gccnt = inet_peer_gc(base, stack, stackptr);
+ if (gccnt && create)
+ goto relookup;
}
p = create ? kmem_cache_alloc(peer_cachep, GFP_ATOMIC) : NULL;
if (p) {
@@ -525,7 +441,6 @@
p->pmtu_expires = 0;
p->pmtu_orig = 0;
memset(&p->redirect_learned, 0, sizeof(p->redirect_learned));
- INIT_LIST_HEAD(&p->unused);
/* Link the node. */
@@ -534,63 +449,14 @@
}
write_sequnlock_bh(&base->lock);
- if (base->total >= inet_peer_threshold)
- /* Remove one less-recently-used entry. */
- cleanup_once(0, stack);
-
return p;
}
-
-static int compute_total(void)
-{
- return v4_peers.total + v6_peers.total;
-}
EXPORT_SYMBOL_GPL(inet_getpeer);
-/* Called with local BH disabled. */
-static void peer_check_expire(unsigned long dummy)
-{
- unsigned long now = jiffies;
- int ttl, total;
- struct inet_peer __rcu **stack[PEER_MAXDEPTH];
-
- total = compute_total();
- if (total >= inet_peer_threshold)
- ttl = inet_peer_minttl;
- else
- ttl = inet_peer_maxttl
- - (inet_peer_maxttl - inet_peer_minttl) / HZ *
- total / inet_peer_threshold * HZ;
- while (!cleanup_once(ttl, stack)) {
- if (jiffies != now)
- break;
- }
-
- /* Trigger the timer after inet_peer_gc_mintime .. inet_peer_gc_maxtime
- * interval depending on the total number of entries (more entries,
- * less interval). */
- total = compute_total();
- if (total >= inet_peer_threshold)
- peer_periodic_timer.expires = jiffies + inet_peer_gc_mintime;
- else
- peer_periodic_timer.expires = jiffies
- + inet_peer_gc_maxtime
- - (inet_peer_gc_maxtime - inet_peer_gc_mintime) / HZ *
- total / inet_peer_threshold * HZ;
- add_timer(&peer_periodic_timer);
-}
-
void inet_putpeer(struct inet_peer *p)
{
- local_bh_disable();
-
- if (atomic_dec_and_lock(&p->refcnt, &unused_peers.lock)) {
- list_add_tail(&p->unused, &unused_peers.list);
- p->dtime = (__u32)jiffies;
- spin_unlock(&unused_peers.lock);
- }
-
- local_bh_enable();
+ p->dtime = (__u32)jiffies;
+ atomic_dec(&p->refcnt);
}
EXPORT_SYMBOL_GPL(inet_putpeer);
diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c
index 0ad6035..0e0ab98 100644
--- a/net/ipv4/ip_fragment.c
+++ b/net/ipv4/ip_fragment.c
@@ -261,8 +261,9 @@
* Only an end host needs to send an ICMP
* "Fragment Reassembly Timeout" message, per RFC792.
*/
- if (qp->user == IP_DEFRAG_CONNTRACK_IN &&
- skb_rtable(head)->rt_type != RTN_LOCAL)
+ if (qp->user == IP_DEFRAG_AF_PACKET ||
+ (qp->user == IP_DEFRAG_CONNTRACK_IN &&
+ skb_rtable(head)->rt_type != RTN_LOCAL))
goto out_rcu_unlock;
diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c
index c8f48ef..073a9b0 100644
--- a/net/ipv4/ip_input.c
+++ b/net/ipv4/ip_input.c
@@ -165,7 +165,7 @@
(!sk->sk_bound_dev_if ||
sk->sk_bound_dev_if == dev->ifindex) &&
net_eq(sock_net(sk), dev_net(dev))) {
- if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) {
+ if (ip_is_fragment(ip_hdr(skb))) {
if (ip_defrag(skb, IP_DEFRAG_CALL_RA_CHAIN))
return 1;
}
@@ -256,7 +256,7 @@
* Reassemble IP fragments.
*/
- if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) {
+ if (ip_is_fragment(ip_hdr(skb))) {
if (ip_defrag(skb, IP_DEFRAG_LOCAL_DELIVER))
return 0;
}
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index 84f26e8..54119d5 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -489,7 +489,7 @@
if (first_len - hlen > mtu ||
((first_len - hlen) & 7) ||
- (iph->frag_off & htons(IP_MF|IP_OFFSET)) ||
+ ip_is_fragment(iph) ||
skb_cloned(skb))
goto slow_path;
diff --git a/net/ipv4/ipconfig.c b/net/ipv4/ipconfig.c
index ab7e554..472a8c4 100644
--- a/net/ipv4/ipconfig.c
+++ b/net/ipv4/ipconfig.c
@@ -861,41 +861,44 @@
#endif
switch (*ext++) {
- case 1: /* Subnet mask */
- if (ic_netmask == NONE)
- memcpy(&ic_netmask, ext+1, 4);
- break;
- case 3: /* Default gateway */
- if (ic_gateway == NONE)
- memcpy(&ic_gateway, ext+1, 4);
- break;
- case 6: /* DNS server */
- servers= *ext/4;
- if (servers > CONF_NAMESERVERS_MAX)
- servers = CONF_NAMESERVERS_MAX;
- for (i = 0; i < servers; i++) {
- if (ic_nameservers[i] == NONE)
- memcpy(&ic_nameservers[i], ext+1+4*i, 4);
- }
- break;
- case 12: /* Host name */
- ic_bootp_string(utsname()->nodename, ext+1, *ext, __NEW_UTS_LEN);
- ic_host_name_set = 1;
- break;
- case 15: /* Domain name (DNS) */
- ic_bootp_string(ic_domain, ext+1, *ext, sizeof(ic_domain));
- break;
- case 17: /* Root path */
- if (!root_server_path[0])
- ic_bootp_string(root_server_path, ext+1, *ext, sizeof(root_server_path));
- break;
- case 26: /* Interface MTU */
- memcpy(&mtu, ext+1, sizeof(mtu));
- ic_dev_mtu = ntohs(mtu);
- break;
- case 40: /* NIS Domain name (_not_ DNS) */
- ic_bootp_string(utsname()->domainname, ext+1, *ext, __NEW_UTS_LEN);
- break;
+ case 1: /* Subnet mask */
+ if (ic_netmask == NONE)
+ memcpy(&ic_netmask, ext+1, 4);
+ break;
+ case 3: /* Default gateway */
+ if (ic_gateway == NONE)
+ memcpy(&ic_gateway, ext+1, 4);
+ break;
+ case 6: /* DNS server */
+ servers= *ext/4;
+ if (servers > CONF_NAMESERVERS_MAX)
+ servers = CONF_NAMESERVERS_MAX;
+ for (i = 0; i < servers; i++) {
+ if (ic_nameservers[i] == NONE)
+ memcpy(&ic_nameservers[i], ext+1+4*i, 4);
+ }
+ break;
+ case 12: /* Host name */
+ ic_bootp_string(utsname()->nodename, ext+1, *ext,
+ __NEW_UTS_LEN);
+ ic_host_name_set = 1;
+ break;
+ case 15: /* Domain name (DNS) */
+ ic_bootp_string(ic_domain, ext+1, *ext, sizeof(ic_domain));
+ break;
+ case 17: /* Root path */
+ if (!root_server_path[0])
+ ic_bootp_string(root_server_path, ext+1, *ext,
+ sizeof(root_server_path));
+ break;
+ case 26: /* Interface MTU */
+ memcpy(&mtu, ext+1, sizeof(mtu));
+ ic_dev_mtu = ntohs(mtu);
+ break;
+ case 40: /* NIS Domain name (_not_ DNS) */
+ ic_bootp_string(utsname()->domainname, ext+1, *ext,
+ __NEW_UTS_LEN);
+ break;
}
}
@@ -932,7 +935,7 @@
goto drop;
/* Fragments are not supported */
- if (h->frag_off & htons(IP_OFFSET | IP_MF)) {
+ if (ip_is_fragment(h)) {
if (net_ratelimit())
printk(KERN_ERR "DHCP/BOOTP: Ignoring fragmented "
"reply.\n");
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c
index 30a7763..aae2bd8 100644
--- a/net/ipv4/ipmr.c
+++ b/net/ipv4/ipmr.c
@@ -2544,7 +2544,8 @@
goto add_proto_fail;
}
#endif
- rtnl_register(RTNL_FAMILY_IPMR, RTM_GETROUTE, NULL, ipmr_rtm_dumproute);
+ rtnl_register(RTNL_FAMILY_IPMR, RTM_GETROUTE,
+ NULL, ipmr_rtm_dumproute, NULL);
return 0;
#ifdef CONFIG_IP_PIMSM_V2
diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c
index 5c9e97c..db8d22d 100644
--- a/net/ipv4/netfilter/ipt_CLUSTERIP.c
+++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c
@@ -317,19 +317,19 @@
hash = clusterip_hashfn(skb, cipinfo->config);
switch (ctinfo) {
- case IP_CT_NEW:
- ct->mark = hash;
- break;
- case IP_CT_RELATED:
- case IP_CT_RELATED_REPLY:
- /* FIXME: we don't handle expectations at the
- * moment. they can arrive on a different node than
- * the master connection (e.g. FTP passive mode) */
- case IP_CT_ESTABLISHED:
- case IP_CT_ESTABLISHED_REPLY:
- break;
- default:
- break;
+ case IP_CT_NEW:
+ ct->mark = hash;
+ break;
+ case IP_CT_RELATED:
+ case IP_CT_RELATED_REPLY:
+ /* FIXME: we don't handle expectations at the moment.
+ * They can arrive on a different node than
+ * the master connection (e.g. FTP passive mode) */
+ case IP_CT_ESTABLISHED:
+ case IP_CT_ESTABLISHED_REPLY:
+ break;
+ default: /* Prevent gcc warnings */
+ break;
}
#ifdef DEBUG
diff --git a/net/ipv4/netfilter/nf_defrag_ipv4.c b/net/ipv4/netfilter/nf_defrag_ipv4.c
index f3a9b42..9bb1b8a 100644
--- a/net/ipv4/netfilter/nf_defrag_ipv4.c
+++ b/net/ipv4/netfilter/nf_defrag_ipv4.c
@@ -82,7 +82,7 @@
#endif
#endif
/* Gather fragments. */
- if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) {
+ if (ip_is_fragment(ip_hdr(skb))) {
enum ip_defrag_users user = nf_ct_defrag_user(hooknum, skb);
if (nf_ct_ipv4_gather_frags(skb, user))
return NF_STOLEN;
diff --git a/net/ipv4/netfilter/nf_nat_snmp_basic.c b/net/ipv4/netfilter/nf_nat_snmp_basic.c
index 8812a02..076b7c8 100644
--- a/net/ipv4/netfilter/nf_nat_snmp_basic.c
+++ b/net/ipv4/netfilter/nf_nat_snmp_basic.c
@@ -719,117 +719,115 @@
l = 0;
switch (type) {
- case SNMP_INTEGER:
- len = sizeof(long);
- if (!asn1_long_decode(ctx, end, &l)) {
- kfree(id);
- return 0;
- }
- *obj = kmalloc(sizeof(struct snmp_object) + len,
- GFP_ATOMIC);
- if (*obj == NULL) {
- kfree(id);
- if (net_ratelimit())
- pr_notice("OOM in bsalg (%d)\n", __LINE__);
- return 0;
- }
- (*obj)->syntax.l[0] = l;
- break;
- case SNMP_OCTETSTR:
- case SNMP_OPAQUE:
- if (!asn1_octets_decode(ctx, end, &p, &len)) {
- kfree(id);
- return 0;
- }
- *obj = kmalloc(sizeof(struct snmp_object) + len,
- GFP_ATOMIC);
- if (*obj == NULL) {
- kfree(p);
- kfree(id);
- if (net_ratelimit())
- pr_notice("OOM in bsalg (%d)\n", __LINE__);
- return 0;
- }
- memcpy((*obj)->syntax.c, p, len);
- kfree(p);
- break;
- case SNMP_NULL:
- case SNMP_NOSUCHOBJECT:
- case SNMP_NOSUCHINSTANCE:
- case SNMP_ENDOFMIBVIEW:
- len = 0;
- *obj = kmalloc(sizeof(struct snmp_object), GFP_ATOMIC);
- if (*obj == NULL) {
- kfree(id);
- if (net_ratelimit())
- pr_notice("OOM in bsalg (%d)\n", __LINE__);
- return 0;
- }
- if (!asn1_null_decode(ctx, end)) {
- kfree(id);
- kfree(*obj);
- *obj = NULL;
- return 0;
- }
- break;
- case SNMP_OBJECTID:
- if (!asn1_oid_decode(ctx, end, (unsigned long **)&lp, &len)) {
- kfree(id);
- return 0;
- }
- len *= sizeof(unsigned long);
- *obj = kmalloc(sizeof(struct snmp_object) + len, GFP_ATOMIC);
- if (*obj == NULL) {
- kfree(lp);
- kfree(id);
- if (net_ratelimit())
- pr_notice("OOM in bsalg (%d)\n", __LINE__);
- return 0;
- }
- memcpy((*obj)->syntax.ul, lp, len);
- kfree(lp);
- break;
- case SNMP_IPADDR:
- if (!asn1_octets_decode(ctx, end, &p, &len)) {
- kfree(id);
- return 0;
- }
- if (len != 4) {
- kfree(p);
- kfree(id);
- return 0;
- }
- *obj = kmalloc(sizeof(struct snmp_object) + len, GFP_ATOMIC);
- if (*obj == NULL) {
- kfree(p);
- kfree(id);
- if (net_ratelimit())
- pr_notice("OOM in bsalg (%d)\n", __LINE__);
- return 0;
- }
- memcpy((*obj)->syntax.uc, p, len);
- kfree(p);
- break;
- case SNMP_COUNTER:
- case SNMP_GAUGE:
- case SNMP_TIMETICKS:
- len = sizeof(unsigned long);
- if (!asn1_ulong_decode(ctx, end, &ul)) {
- kfree(id);
- return 0;
- }
- *obj = kmalloc(sizeof(struct snmp_object) + len, GFP_ATOMIC);
- if (*obj == NULL) {
- kfree(id);
- if (net_ratelimit())
- pr_notice("OOM in bsalg (%d)\n", __LINE__);
- return 0;
- }
- (*obj)->syntax.ul[0] = ul;
- break;
- default:
+ case SNMP_INTEGER:
+ len = sizeof(long);
+ if (!asn1_long_decode(ctx, end, &l)) {
kfree(id);
return 0;
+ }
+ *obj = kmalloc(sizeof(struct snmp_object) + len, GFP_ATOMIC);
+ if (*obj == NULL) {
+ kfree(id);
+ if (net_ratelimit())
+ pr_notice("OOM in bsalg (%d)\n", __LINE__);
+ return 0;
+ }
+ (*obj)->syntax.l[0] = l;
+ break;
+ case SNMP_OCTETSTR:
+ case SNMP_OPAQUE:
+ if (!asn1_octets_decode(ctx, end, &p, &len)) {
+ kfree(id);
+ return 0;
+ }
+ *obj = kmalloc(sizeof(struct snmp_object) + len, GFP_ATOMIC);
+ if (*obj == NULL) {
+ kfree(p);
+ kfree(id);
+ if (net_ratelimit())
+ pr_notice("OOM in bsalg (%d)\n", __LINE__);
+ return 0;
+ }
+ memcpy((*obj)->syntax.c, p, len);
+ kfree(p);
+ break;
+ case SNMP_NULL:
+ case SNMP_NOSUCHOBJECT:
+ case SNMP_NOSUCHINSTANCE:
+ case SNMP_ENDOFMIBVIEW:
+ len = 0;
+ *obj = kmalloc(sizeof(struct snmp_object), GFP_ATOMIC);
+ if (*obj == NULL) {
+ kfree(id);
+ if (net_ratelimit())
+ pr_notice("OOM in bsalg (%d)\n", __LINE__);
+ return 0;
+ }
+ if (!asn1_null_decode(ctx, end)) {
+ kfree(id);
+ kfree(*obj);
+ *obj = NULL;
+ return 0;
+ }
+ break;
+ case SNMP_OBJECTID:
+ if (!asn1_oid_decode(ctx, end, (unsigned long **)&lp, &len)) {
+ kfree(id);
+ return 0;
+ }
+ len *= sizeof(unsigned long);
+ *obj = kmalloc(sizeof(struct snmp_object) + len, GFP_ATOMIC);
+ if (*obj == NULL) {
+ kfree(lp);
+ kfree(id);
+ if (net_ratelimit())
+ pr_notice("OOM in bsalg (%d)\n", __LINE__);
+ return 0;
+ }
+ memcpy((*obj)->syntax.ul, lp, len);
+ kfree(lp);
+ break;
+ case SNMP_IPADDR:
+ if (!asn1_octets_decode(ctx, end, &p, &len)) {
+ kfree(id);
+ return 0;
+ }
+ if (len != 4) {
+ kfree(p);
+ kfree(id);
+ return 0;
+ }
+ *obj = kmalloc(sizeof(struct snmp_object) + len, GFP_ATOMIC);
+ if (*obj == NULL) {
+ kfree(p);
+ kfree(id);
+ if (net_ratelimit())
+ pr_notice("OOM in bsalg (%d)\n", __LINE__);
+ return 0;
+ }
+ memcpy((*obj)->syntax.uc, p, len);
+ kfree(p);
+ break;
+ case SNMP_COUNTER:
+ case SNMP_GAUGE:
+ case SNMP_TIMETICKS:
+ len = sizeof(unsigned long);
+ if (!asn1_ulong_decode(ctx, end, &ul)) {
+ kfree(id);
+ return 0;
+ }
+ *obj = kmalloc(sizeof(struct snmp_object) + len, GFP_ATOMIC);
+ if (*obj == NULL) {
+ kfree(id);
+ if (net_ratelimit())
+ pr_notice("OOM in bsalg (%d)\n", __LINE__);
+ return 0;
+ }
+ (*obj)->syntax.ul[0] = ul;
+ break;
+ default:
+ kfree(id);
+ return 0;
}
(*obj)->syntax_len = len;
diff --git a/net/ipv4/netfilter/nf_nat_standalone.c b/net/ipv4/netfilter/nf_nat_standalone.c
index 483b76d..a6e606e 100644
--- a/net/ipv4/netfilter/nf_nat_standalone.c
+++ b/net/ipv4/netfilter/nf_nat_standalone.c
@@ -88,7 +88,7 @@
/* We never see fragments: conntrack defrags on pre-routing
and local-out, and nf_nat_out protects post-routing. */
- NF_CT_ASSERT(!(ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)));
+ NF_CT_ASSERT(!ip_is_fragment(ip_hdr(skb)));
ct = nf_ct_get(skb, &ctinfo);
/* Can't track? It's not due to stress, or conntrack would
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
index c9893d4..0852678 100644
--- a/net/ipv4/raw.c
+++ b/net/ipv4/raw.c
@@ -825,28 +825,28 @@
static int raw_ioctl(struct sock *sk, int cmd, unsigned long arg)
{
switch (cmd) {
- case SIOCOUTQ: {
- int amount = sk_wmem_alloc_get(sk);
+ case SIOCOUTQ: {
+ int amount = sk_wmem_alloc_get(sk);
- return put_user(amount, (int __user *)arg);
- }
- case SIOCINQ: {
- struct sk_buff *skb;
- int amount = 0;
+ return put_user(amount, (int __user *)arg);
+ }
+ case SIOCINQ: {
+ struct sk_buff *skb;
+ int amount = 0;
- spin_lock_bh(&sk->sk_receive_queue.lock);
- skb = skb_peek(&sk->sk_receive_queue);
- if (skb != NULL)
- amount = skb->len;
- spin_unlock_bh(&sk->sk_receive_queue.lock);
- return put_user(amount, (int __user *)arg);
- }
+ spin_lock_bh(&sk->sk_receive_queue.lock);
+ skb = skb_peek(&sk->sk_receive_queue);
+ if (skb != NULL)
+ amount = skb->len;
+ spin_unlock_bh(&sk->sk_receive_queue.lock);
+ return put_user(amount, (int __user *)arg);
+ }
- default:
+ default:
#ifdef CONFIG_IP_MROUTE
- return ipmr_ioctl(sk, cmd, (void __user *)arg);
+ return ipmr_ioctl(sk, cmd, (void __user *)arg);
#else
- return -ENOIOCTLCMD;
+ return -ENOIOCTLCMD;
#endif
}
}
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index aa13ef1..a8ccd9b 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -1439,20 +1439,20 @@
int code;
switch (rt->dst.error) {
- case EINVAL:
- default:
- goto out;
- case EHOSTUNREACH:
- code = ICMP_HOST_UNREACH;
- break;
- case ENETUNREACH:
- code = ICMP_NET_UNREACH;
- IP_INC_STATS_BH(dev_net(rt->dst.dev),
- IPSTATS_MIB_INNOROUTES);
- break;
- case EACCES:
- code = ICMP_PKT_FILTERED;
- break;
+ case EINVAL:
+ default:
+ goto out;
+ case EHOSTUNREACH:
+ code = ICMP_HOST_UNREACH;
+ break;
+ case ENETUNREACH:
+ code = ICMP_NET_UNREACH;
+ IP_INC_STATS_BH(dev_net(rt->dst.dev),
+ IPSTATS_MIB_INNOROUTES);
+ break;
+ case EACCES:
+ code = ICMP_PKT_FILTERED;
+ break;
}
if (!rt->peer)
@@ -3303,7 +3303,7 @@
xfrm_init();
xfrm4_init(ip_rt_max_size);
#endif
- rtnl_register(PF_INET, RTM_GETROUTE, inet_rtm_getroute, NULL);
+ rtnl_register(PF_INET, RTM_GETROUTE, inet_rtm_getroute, NULL, NULL);
#ifdef CONFIG_SYSCTL
register_pernet_subsys(&sysctl_route_ops);
diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c
index 2646149..92bb943 100644
--- a/net/ipv4/syncookies.c
+++ b/net/ipv4/syncookies.c
@@ -316,6 +316,7 @@
ireq->wscale_ok = tcp_opt.wscale_ok;
ireq->tstamp_ok = tcp_opt.saw_tstamp;
req->ts_recent = tcp_opt.saw_tstamp ? tcp_opt.rcv_tsval : 0;
+ treq->snt_synack = tcp_opt.saw_tstamp ? tcp_opt.rcv_tsecr : 0;
/* We throwed the options of the initial SYN away, so we hope
* the ACK carries the same options again (see RFC1122 4.2.3.8)
diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c
index 57d0752..69fd720 100644
--- a/net/ipv4/sysctl_net_ipv4.c
+++ b/net/ipv4/sysctl_net_ipv4.c
@@ -398,20 +398,6 @@
.proc_handler = proc_dointvec_jiffies,
},
{
- .procname = "inet_peer_gc_mintime",
- .data = &inet_peer_gc_mintime,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = proc_dointvec_jiffies,
- },
- {
- .procname = "inet_peer_gc_maxtime",
- .data = &inet_peer_gc_maxtime,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = proc_dointvec_jiffies,
- },
- {
.procname = "tcp_orphan_retries",
.data = &sysctl_tcp_orphan_retries,
.maxlen = sizeof(int),
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index bef9f04..ea0d218 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -880,6 +880,11 @@
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)) {
@@ -887,10 +892,7 @@
tp->reordering = dst_metric(dst, RTAX_REORDERING);
}
- if (dst_metric(dst, RTAX_RTT) == 0)
- goto reset;
-
- if (!tp->srtt && dst_metric_rtt(dst, RTAX_RTT) < (TCP_TIMEOUT_INIT << 3))
+ if (dst_metric(dst, RTAX_RTT) == 0 || tp->srtt == 0)
goto reset;
/* Initial rtt is determined from SYN,SYN-ACK.
@@ -916,19 +918,26 @@
tp->mdev_max = tp->rttvar = max(tp->mdev, tcp_rto_min(sk));
}
tcp_set_rto(sk);
- if (inet_csk(sk)->icsk_rto < TCP_TIMEOUT_INIT && !tp->rx_opt.saw_tstamp) {
reset:
- /* Play conservative. If timestamps are not
- * supported, TCP will fail to recalculate correct
- * rtt, if initial rto is too small. FORGET ALL AND RESET!
+ if (tp->srtt == 0) {
+ /* RFC2988bis: 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.
*/
- if (!tp->rx_opt.saw_tstamp && tp->srtt) {
- tp->srtt = 0;
- tp->mdev = tp->mdev_max = tp->rttvar = TCP_TIMEOUT_INIT;
- inet_csk(sk)->icsk_rto = TCP_TIMEOUT_INIT;
- }
+ tp->mdev = tp->mdev_max = tp->rttvar = TCP_TIMEOUT_FALLBACK;
+ inet_csk(sk)->icsk_rto = TCP_TIMEOUT_FALLBACK;
}
- tp->snd_cwnd = tcp_init_cwnd(tp, dst);
+ /* Cut cwnd down to 1 per RFC5681 if SYN or SYN-ACK has been
+ * retransmitted. In light of RFC2988bis' 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;
}
@@ -3112,12 +3121,13 @@
tcp_xmit_retransmit_queue(sk);
}
-static void tcp_valid_rtt_meas(struct sock *sk, u32 seq_rtt)
+void tcp_valid_rtt_meas(struct sock *sk, u32 seq_rtt)
{
tcp_rtt_estimator(sk, seq_rtt);
tcp_set_rto(sk);
inet_csk(sk)->icsk_backoff = 0;
}
+EXPORT_SYMBOL(tcp_valid_rtt_meas);
/* Read draft-ietf-tcplw-high-performance before mucking
* with this code. (Supersedes RFC1323)
@@ -5806,12 +5816,6 @@
tp->rx_opt.snd_wscale;
tcp_init_wl(tp, TCP_SKB_CB(skb)->seq);
- /* tcp_ack considers this ACK as duplicate
- * and does not calculate rtt.
- * Force it here.
- */
- tcp_ack_update_rtt(sk, 0, 0);
-
if (tp->rx_opt.tstamp_ok)
tp->advmss -= TCPOLEN_TSTAMP_ALIGNED;
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 708dc20..955b8e6 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -429,8 +429,8 @@
break;
icsk->icsk_backoff--;
- inet_csk(sk)->icsk_rto = __tcp_set_rto(tp) <<
- icsk->icsk_backoff;
+ inet_csk(sk)->icsk_rto = (tp->srtt ? __tcp_set_rto(tp) :
+ TCP_TIMEOUT_INIT) << icsk->icsk_backoff;
tcp_bound_rto(sk);
skb = tcp_write_queue_head(sk);
@@ -1384,6 +1384,7 @@
isn = tcp_v4_init_sequence(skb);
}
tcp_rsk(req)->snt_isn = isn;
+ tcp_rsk(req)->snt_synack = tcp_time_stamp;
if (tcp_v4_send_synack(sk, dst, req,
(struct request_values *)&tmp_ext) ||
@@ -1458,6 +1459,10 @@
newtp->advmss = tcp_sk(sk)->rx_opt.user_mss;
tcp_initialize_rcv_mss(newsk);
+ if (tcp_rsk(req)->snt_synack)
+ tcp_valid_rtt_meas(newsk,
+ tcp_time_stamp - tcp_rsk(req)->snt_synack);
+ newtp->total_retrans = req->retrans;
#ifdef CONFIG_TCP_MD5SIG
/* Copy over the MD5 key from the original socket */
@@ -1855,7 +1860,7 @@
* algorithms that we must have the following bandaid to talk
* efficiently to them. -DaveM
*/
- tp->snd_cwnd = 2;
+ tp->snd_cwnd = TCP_INIT_CWND;
/* See draft-stevens-tcpca-spec-01 for discussion of the
* initialization of these values.
diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c
index 80b1f80..d2fe4e0 100644
--- a/net/ipv4/tcp_minisocks.c
+++ b/net/ipv4/tcp_minisocks.c
@@ -486,7 +486,7 @@
* algorithms that we must have the following bandaid to talk
* efficiently to them. -DaveM
*/
- newtp->snd_cwnd = 2;
+ newtp->snd_cwnd = TCP_INIT_CWND;
newtp->snd_cwnd_cnt = 0;
newtp->bytes_acked = 0;
@@ -720,6 +720,10 @@
NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPDEFERACCEPTDROP);
return NULL;
}
+ if (tmp_opt.saw_tstamp && tmp_opt.rcv_tsecr)
+ tcp_rsk(req)->snt_synack = tmp_opt.rcv_tsecr;
+ else if (req->retrans) /* don't take RTT sample if retrans && ~TS */
+ tcp_rsk(req)->snt_synack = 0;
/* OK, ACK is valid, create big socket and
* feed this segment to it. It will repeat all
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 48cd88e..95e0d3b8 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -105,6 +105,7 @@
#include <net/route.h>
#include <net/checksum.h>
#include <net/xfrm.h>
+#include <trace/events/udp.h>
#include "udp_impl.h"
struct udp_table udp_table __read_mostly;
@@ -1366,6 +1367,7 @@
is_udplite);
UDP_INC_STATS_BH(sock_net(sk), UDP_MIB_INERRORS, is_udplite);
kfree_skb(skb);
+ trace_udp_fail_queue_rcv_skb(rc, sk);
return -1;
}
diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c
index 981e43e..fc5368a 100644
--- a/net/ipv4/xfrm4_policy.c
+++ b/net/ipv4/xfrm4_policy.c
@@ -117,7 +117,7 @@
memset(fl4, 0, sizeof(struct flowi4));
fl4->flowi4_mark = skb->mark;
- if (!(iph->frag_off & htons(IP_MF | IP_OFFSET))) {
+ if (!ip_is_fragment(iph)) {
switch (iph->protocol) {
case IPPROTO_UDP:
case IPPROTO_UDPLITE:
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 498b927..05838c7 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -1559,6 +1559,11 @@
return -1;
}
+static int addrconf_ifid_gre(u8 *eui, struct net_device *dev)
+{
+ return __ipv6_isatap_ifid(eui, *(__be32 *)dev->dev_addr);
+}
+
static int ipv6_generate_eui64(u8 *eui, struct net_device *dev)
{
switch (dev->type) {
@@ -1572,6 +1577,8 @@
return addrconf_ifid_infiniband(eui, dev);
case ARPHRD_SIT:
return addrconf_ifid_sit(eui, dev);
+ case ARPHRD_IPGRE:
+ return addrconf_ifid_gre(eui, dev);
}
return -1;
}
@@ -2423,6 +2430,29 @@
}
#endif
+#if defined(CONFIG_NET_IPGRE) || defined(CONFIG_NET_IPGRE_MODULE)
+static void addrconf_gre_config(struct net_device *dev)
+{
+ struct inet6_dev *idev;
+ struct in6_addr addr;
+
+ pr_info("ipv6: addrconf_gre_config(%s)\n", dev->name);
+
+ ASSERT_RTNL();
+
+ if ((idev = ipv6_find_idev(dev)) == NULL) {
+ printk(KERN_DEBUG "init gre: add_dev failed\n");
+ return;
+ }
+
+ ipv6_addr_set(&addr, htonl(0xFE800000), 0, 0, 0);
+ addrconf_prefix_route(&addr, 64, dev, 0, 0);
+
+ if (!ipv6_generate_eui64(addr.s6_addr + 8, dev))
+ addrconf_add_linklocal(idev, &addr);
+}
+#endif
+
static inline int
ipv6_inherit_linklocal(struct inet6_dev *idev, struct net_device *link_dev)
{
@@ -2539,6 +2569,11 @@
addrconf_sit_config(dev);
break;
#endif
+#if defined(CONFIG_NET_IPGRE) || defined(CONFIG_NET_IPGRE_MODULE)
+ case ARPHRD_IPGRE:
+ addrconf_gre_config(dev);
+ break;
+#endif
case ARPHRD_TUNNEL6:
addrconf_ip6_tnl_config(dev);
break;
@@ -4692,16 +4727,20 @@
if (err < 0)
goto errout_af;
- err = __rtnl_register(PF_INET6, RTM_GETLINK, NULL, inet6_dump_ifinfo);
+ err = __rtnl_register(PF_INET6, RTM_GETLINK, NULL, inet6_dump_ifinfo,
+ NULL);
if (err < 0)
goto errout;
/* Only the first call to __rtnl_register can fail */
- __rtnl_register(PF_INET6, RTM_NEWADDR, inet6_rtm_newaddr, NULL);
- __rtnl_register(PF_INET6, RTM_DELADDR, inet6_rtm_deladdr, NULL);
- __rtnl_register(PF_INET6, RTM_GETADDR, inet6_rtm_getaddr, inet6_dump_ifaddr);
- __rtnl_register(PF_INET6, RTM_GETMULTICAST, NULL, inet6_dump_ifmcaddr);
- __rtnl_register(PF_INET6, RTM_GETANYCAST, NULL, inet6_dump_ifacaddr);
+ __rtnl_register(PF_INET6, RTM_NEWADDR, inet6_rtm_newaddr, NULL, NULL);
+ __rtnl_register(PF_INET6, RTM_DELADDR, inet6_rtm_deladdr, NULL, NULL);
+ __rtnl_register(PF_INET6, RTM_GETADDR, inet6_rtm_getaddr,
+ inet6_dump_ifaddr, NULL);
+ __rtnl_register(PF_INET6, RTM_GETMULTICAST, NULL,
+ inet6_dump_ifmcaddr, NULL);
+ __rtnl_register(PF_INET6, RTM_GETANYCAST, NULL,
+ inet6_dump_ifacaddr, NULL);
ipv6_addr_label_rtnl_register();
diff --git a/net/ipv6/addrlabel.c b/net/ipv6/addrlabel.c
index c8993e5..2d8ddba 100644
--- a/net/ipv6/addrlabel.c
+++ b/net/ipv6/addrlabel.c
@@ -592,8 +592,11 @@
void __init ipv6_addr_label_rtnl_register(void)
{
- __rtnl_register(PF_INET6, RTM_NEWADDRLABEL, ip6addrlbl_newdel, NULL);
- __rtnl_register(PF_INET6, RTM_DELADDRLABEL, ip6addrlbl_newdel, NULL);
- __rtnl_register(PF_INET6, RTM_GETADDRLABEL, ip6addrlbl_get, ip6addrlbl_dump);
+ __rtnl_register(PF_INET6, RTM_NEWADDRLABEL, ip6addrlbl_newdel,
+ NULL, NULL);
+ __rtnl_register(PF_INET6, RTM_DELADDRLABEL, ip6addrlbl_newdel,
+ NULL, NULL);
+ __rtnl_register(PF_INET6, RTM_GETADDRLABEL, ip6addrlbl_get,
+ ip6addrlbl_dump, NULL);
}
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
index 4076a0b..3030bdf 100644
--- a/net/ipv6/ip6_fib.c
+++ b/net/ipv6/ip6_fib.c
@@ -1586,7 +1586,8 @@
if (ret)
goto out_kmem_cache_create;
- ret = __rtnl_register(PF_INET6, RTM_GETROUTE, NULL, inet6_dump_fib);
+ ret = __rtnl_register(PF_INET6, RTM_GETROUTE, NULL, inet6_dump_fib,
+ NULL);
if (ret)
goto out_unregister_subsys;
out:
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c
index 82a8099..705c828 100644
--- a/net/ipv6/ip6mr.c
+++ b/net/ipv6/ip6mr.c
@@ -1354,7 +1354,8 @@
goto add_proto_fail;
}
#endif
- rtnl_register(RTNL_FAMILY_IP6MR, RTM_GETROUTE, NULL, ip6mr_rtm_dumproute);
+ rtnl_register(RTNL_FAMILY_IP6MR, RTM_GETROUTE, NULL,
+ ip6mr_rtm_dumproute, NULL);
return 0;
#ifdef CONFIG_IPV6_PIMSM_V2
add_proto_fail:
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index cc7313b..6a79f308 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -959,57 +959,54 @@
return -EFAULT;
switch (optname) {
- case IPV6_CHECKSUM:
- if (inet_sk(sk)->inet_num == IPPROTO_ICMPV6 &&
- level == IPPROTO_IPV6) {
- /*
- * RFC3542 tells that IPV6_CHECKSUM socket
- * option in the IPPROTO_IPV6 level is not
- * allowed on ICMPv6 sockets.
- * If you want to set it, use IPPROTO_RAW
- * level IPV6_CHECKSUM socket option
- * (Linux extension).
- */
- return -EINVAL;
- }
+ case IPV6_CHECKSUM:
+ if (inet_sk(sk)->inet_num == IPPROTO_ICMPV6 &&
+ level == IPPROTO_IPV6) {
+ /*
+ * RFC3542 tells that IPV6_CHECKSUM socket
+ * option in the IPPROTO_IPV6 level is not
+ * allowed on ICMPv6 sockets.
+ * If you want to set it, use IPPROTO_RAW
+ * level IPV6_CHECKSUM socket option
+ * (Linux extension).
+ */
+ return -EINVAL;
+ }
- /* You may get strange result with a positive odd offset;
- RFC2292bis agrees with me. */
- if (val > 0 && (val&1))
- return -EINVAL;
- if (val < 0) {
- rp->checksum = 0;
- } else {
- rp->checksum = 1;
- rp->offset = val;
- }
+ /* You may get strange result with a positive odd offset;
+ RFC2292bis agrees with me. */
+ if (val > 0 && (val&1))
+ return -EINVAL;
+ if (val < 0) {
+ rp->checksum = 0;
+ } else {
+ rp->checksum = 1;
+ rp->offset = val;
+ }
- return 0;
- break;
+ return 0;
- default:
- return -ENOPROTOOPT;
+ default:
+ return -ENOPROTOOPT;
}
}
static int rawv6_setsockopt(struct sock *sk, int level, int optname,
char __user *optval, unsigned int optlen)
{
- switch(level) {
- case SOL_RAW:
- break;
+ switch (level) {
+ case SOL_RAW:
+ break;
- case SOL_ICMPV6:
- if (inet_sk(sk)->inet_num != IPPROTO_ICMPV6)
- return -EOPNOTSUPP;
- return rawv6_seticmpfilter(sk, level, optname, optval,
- optlen);
- case SOL_IPV6:
- if (optname == IPV6_CHECKSUM)
- break;
- default:
- return ipv6_setsockopt(sk, level, optname, optval,
- optlen);
+ case SOL_ICMPV6:
+ if (inet_sk(sk)->inet_num != IPPROTO_ICMPV6)
+ return -EOPNOTSUPP;
+ return rawv6_seticmpfilter(sk, level, optname, optval, optlen);
+ case SOL_IPV6:
+ if (optname == IPV6_CHECKSUM)
+ break;
+ default:
+ return ipv6_setsockopt(sk, level, optname, optval, optlen);
}
return do_rawv6_setsockopt(sk, level, optname, optval, optlen);
@@ -1075,21 +1072,19 @@
static int rawv6_getsockopt(struct sock *sk, int level, int optname,
char __user *optval, int __user *optlen)
{
- switch(level) {
- case SOL_RAW:
- break;
+ switch (level) {
+ case SOL_RAW:
+ break;
- case SOL_ICMPV6:
- if (inet_sk(sk)->inet_num != IPPROTO_ICMPV6)
- return -EOPNOTSUPP;
- return rawv6_geticmpfilter(sk, level, optname, optval,
- optlen);
- case SOL_IPV6:
- if (optname == IPV6_CHECKSUM)
- break;
- default:
- return ipv6_getsockopt(sk, level, optname, optval,
- optlen);
+ case SOL_ICMPV6:
+ if (inet_sk(sk)->inet_num != IPPROTO_ICMPV6)
+ return -EOPNOTSUPP;
+ return rawv6_geticmpfilter(sk, level, optname, optval, optlen);
+ case SOL_IPV6:
+ if (optname == IPV6_CHECKSUM)
+ break;
+ default:
+ return ipv6_getsockopt(sk, level, optname, optval, optlen);
}
return do_rawv6_getsockopt(sk, level, optname, optval, optlen);
@@ -1119,31 +1114,29 @@
static int rawv6_ioctl(struct sock *sk, int cmd, unsigned long arg)
{
- switch(cmd) {
- case SIOCOUTQ:
- {
- int amount = sk_wmem_alloc_get(sk);
+ switch (cmd) {
+ case SIOCOUTQ: {
+ int amount = sk_wmem_alloc_get(sk);
- return put_user(amount, (int __user *)arg);
- }
- case SIOCINQ:
- {
- struct sk_buff *skb;
- int amount = 0;
+ return put_user(amount, (int __user *)arg);
+ }
+ case SIOCINQ: {
+ struct sk_buff *skb;
+ int amount = 0;
- spin_lock_bh(&sk->sk_receive_queue.lock);
- skb = skb_peek(&sk->sk_receive_queue);
- if (skb != NULL)
- amount = skb->tail - skb->transport_header;
- spin_unlock_bh(&sk->sk_receive_queue.lock);
- return put_user(amount, (int __user *)arg);
- }
+ spin_lock_bh(&sk->sk_receive_queue.lock);
+ skb = skb_peek(&sk->sk_receive_queue);
+ if (skb != NULL)
+ amount = skb->tail - skb->transport_header;
+ spin_unlock_bh(&sk->sk_receive_queue.lock);
+ return put_user(amount, (int __user *)arg);
+ }
- default:
+ default:
#ifdef CONFIG_IPV6_MROUTE
- return ip6mr_ioctl(sk, cmd, (void __user *)arg);
+ return ip6mr_ioctl(sk, cmd, (void __user *)arg);
#else
- return -ENOIOCTLCMD;
+ return -ENOIOCTLCMD;
#endif
}
}
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 0ef1f08..f032d77 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -2918,9 +2918,9 @@
goto xfrm6_init;
ret = -ENOBUFS;
- if (__rtnl_register(PF_INET6, RTM_NEWROUTE, inet6_rtm_newroute, NULL) ||
- __rtnl_register(PF_INET6, RTM_DELROUTE, inet6_rtm_delroute, NULL) ||
- __rtnl_register(PF_INET6, RTM_GETROUTE, inet6_rtm_getroute, NULL))
+ if (__rtnl_register(PF_INET6, RTM_NEWROUTE, inet6_rtm_newroute, NULL, NULL) ||
+ __rtnl_register(PF_INET6, RTM_DELROUTE, inet6_rtm_delroute, NULL, NULL) ||
+ __rtnl_register(PF_INET6, RTM_GETROUTE, inet6_rtm_getroute, NULL, NULL))
goto fib6_rules_init;
ret = register_netdevice_notifier(&ip6_route_dev_notifier);
diff --git a/net/ipv6/syncookies.c b/net/ipv6/syncookies.c
index 8b9644a..89d5bf8 100644
--- a/net/ipv6/syncookies.c
+++ b/net/ipv6/syncookies.c
@@ -223,6 +223,7 @@
ireq->wscale_ok = tcp_opt.wscale_ok;
ireq->tstamp_ok = tcp_opt.saw_tstamp;
req->ts_recent = tcp_opt.saw_tstamp ? tcp_opt.rcv_tsval : 0;
+ treq->snt_synack = tcp_opt.saw_tstamp ? tcp_opt.rcv_tsecr : 0;
treq->rcv_isn = ntohl(th->seq) - 1;
treq->snt_isn = cookie;
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 87551ca..78aa534 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -1341,6 +1341,7 @@
}
have_isn:
tcp_rsk(req)->snt_isn = isn;
+ tcp_rsk(req)->snt_synack = tcp_time_stamp;
security_inet_conn_request(sk, skb, req);
@@ -1509,6 +1510,10 @@
tcp_sync_mss(newsk, dst_mtu(dst));
newtp->advmss = dst_metric_advmss(dst);
tcp_initialize_rcv_mss(newsk);
+ if (tcp_rsk(req)->snt_synack)
+ tcp_valid_rtt_meas(newsk,
+ tcp_time_stamp - tcp_rsk(req)->snt_synack);
+ newtp->total_retrans = req->retrans;
newinet->inet_daddr = newinet->inet_saddr = LOOPBACK4_IPV6;
newinet->inet_rcv_saddr = LOOPBACK4_IPV6;
diff --git a/net/irda/af_irda.c b/net/irda/af_irda.c
index cc61697..c24f25a 100644
--- a/net/irda/af_irda.c
+++ b/net/irda/af_irda.c
@@ -369,7 +369,7 @@
{
struct irda_sock *self;
- self = (struct irda_sock *) priv;
+ self = priv;
if (!self) {
IRDA_WARNING("%s: lost myself!\n", __func__);
return;
@@ -418,7 +418,7 @@
IRDA_DEBUG(2, "%s()\n", __func__);
- self = (struct irda_sock *) priv;
+ self = priv;
if (!self) {
IRDA_WARNING("%s: lost myself!\n", __func__);
return;
diff --git a/net/irda/ircomm/ircomm_tty_attach.c b/net/irda/ircomm/ircomm_tty_attach.c
index 3c17540..b65d66e 100644
--- a/net/irda/ircomm/ircomm_tty_attach.c
+++ b/net/irda/ircomm/ircomm_tty_attach.c
@@ -382,7 +382,7 @@
info.daddr = discovery->daddr;
info.saddr = discovery->saddr;
- self = (struct ircomm_tty_cb *) priv;
+ self = priv;
ircomm_tty_do_event(self, IRCOMM_TTY_DISCOVERY_INDICATION,
NULL, &info);
}
diff --git a/net/irda/irda_device.c b/net/irda/irda_device.c
index 25cc2e6..3eca35f 100644
--- a/net/irda/irda_device.c
+++ b/net/irda/irda_device.c
@@ -262,7 +262,7 @@
IRDA_DEBUG(2, "%s()\n", __func__);
- task = (struct irda_task *) data;
+ task = data;
irda_task_kick(task);
}
diff --git a/net/irda/iriap.c b/net/irda/iriap.c
index f876eed..e71e85b 100644
--- a/net/irda/iriap.c
+++ b/net/irda/iriap.c
@@ -305,7 +305,7 @@
IRDA_DEBUG(4, "%s(), reason=%s\n", __func__, irlmp_reasons[reason]);
- self = (struct iriap_cb *) instance;
+ self = instance;
IRDA_ASSERT(self != NULL, return;);
IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
@@ -759,7 +759,7 @@
{
struct iriap_cb *self;
- self = (struct iriap_cb *) instance;
+ self = instance;
IRDA_ASSERT(self != NULL, return;);
IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
@@ -791,7 +791,7 @@
IRDA_DEBUG(1, "%s()\n", __func__);
- self = (struct iriap_cb *) instance;
+ self = instance;
IRDA_ASSERT(skb != NULL, return;);
IRDA_ASSERT(self != NULL, goto out;);
@@ -839,7 +839,7 @@
IRDA_DEBUG(3, "%s()\n", __func__);
- self = (struct iriap_cb *) instance;
+ self = instance;
IRDA_ASSERT(skb != NULL, return 0;);
IRDA_ASSERT(self != NULL, goto out;);
diff --git a/net/irda/irlan/irlan_client.c b/net/irda/irlan/irlan_client.c
index 7ed3af9..ba1a3fc 100644
--- a/net/irda/irlan/irlan_client.c
+++ b/net/irda/irlan/irlan_client.c
@@ -198,7 +198,7 @@
IRDA_DEBUG(2, "%s()\n", __func__ );
- self = (struct irlan_cb *) instance;
+ self = instance;
IRDA_ASSERT(self != NULL, return -1;);
IRDA_ASSERT(self->magic == IRLAN_MAGIC, return -1;);
@@ -226,8 +226,8 @@
IRDA_DEBUG(4, "%s(), reason=%d\n", __func__ , reason);
- self = (struct irlan_cb *) instance;
- tsap = (struct tsap_cb *) sap;
+ self = instance;
+ tsap = sap;
IRDA_ASSERT(self != NULL, return;);
IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
@@ -298,7 +298,7 @@
IRDA_DEBUG(4, "%s()\n", __func__ );
- self = (struct irlan_cb *) instance;
+ self = instance;
IRDA_ASSERT(self != NULL, return;);
IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
@@ -542,7 +542,7 @@
IRDA_ASSERT(priv != NULL, return;);
- self = (struct irlan_cb *) priv;
+ self = priv;
IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
/* We probably don't need to make any more queries */
diff --git a/net/irda/irlan/irlan_common.c b/net/irda/irlan/irlan_common.c
index 6130f9d..7791176 100644
--- a/net/irda/irlan/irlan_common.c
+++ b/net/irda/irlan/irlan_common.c
@@ -317,8 +317,8 @@
IRDA_DEBUG(2, "%s()\n", __func__ );
- self = (struct irlan_cb *) instance;
- tsap = (struct tsap_cb *) sap;
+ self = instance;
+ tsap = sap;
IRDA_ASSERT(self != NULL, return;);
IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
@@ -361,7 +361,7 @@
{
struct irlan_cb *self;
- self = (struct irlan_cb *) instance;
+ self = instance;
IRDA_ASSERT(self != NULL, return;);
IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
@@ -406,8 +406,8 @@
IRDA_DEBUG(0, "%s(), reason=%d\n", __func__ , reason);
- self = (struct irlan_cb *) instance;
- tsap = (struct tsap_cb *) sap;
+ self = instance;
+ tsap = sap;
IRDA_ASSERT(self != NULL, return;);
IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
diff --git a/net/irda/irlan/irlan_eth.c b/net/irda/irlan/irlan_eth.c
index 8ee1ff6..e8d5f44 100644
--- a/net/irda/irlan/irlan_eth.c
+++ b/net/irda/irlan/irlan_eth.c
@@ -272,7 +272,7 @@
struct irlan_cb *self;
struct net_device *dev;
- self = (struct irlan_cb *) instance;
+ self = instance;
IRDA_ASSERT(self != NULL, return;);
IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
diff --git a/net/irda/irlan/irlan_provider.c b/net/irda/irlan/irlan_provider.c
index b8af74a..8b61cf0 100644
--- a/net/irda/irlan/irlan_provider.c
+++ b/net/irda/irlan/irlan_provider.c
@@ -73,7 +73,7 @@
IRDA_DEBUG(4, "%s()\n", __func__ );
- self = (struct irlan_cb *) instance;
+ self = instance;
IRDA_ASSERT(self != NULL, return -1;);
IRDA_ASSERT(self->magic == IRLAN_MAGIC, return -1;);
@@ -131,8 +131,8 @@
IRDA_DEBUG(0, "%s()\n", __func__ );
- self = (struct irlan_cb *) instance;
- tsap = (struct tsap_cb *) sap;
+ self = instance;
+ tsap = sap;
IRDA_ASSERT(self != NULL, return;);
IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
@@ -182,8 +182,8 @@
IRDA_DEBUG(4, "%s(), reason=%d\n", __func__ , reason);
- self = (struct irlan_cb *) instance;
- tsap = (struct tsap_cb *) sap;
+ self = instance;
+ tsap = sap;
IRDA_ASSERT(self != NULL, return;);
IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
diff --git a/net/irda/irqueue.c b/net/irda/irqueue.c
index 9715e6e..f06947c 100644
--- a/net/irda/irqueue.c
+++ b/net/irda/irqueue.c
@@ -780,7 +780,7 @@
/*
* Search for entry
*/
- entry = (irda_queue_t* ) hashbin_find( hashbin, hashv, name );
+ entry = hashbin_find(hashbin, hashv, name);
/* Release lock */
spin_unlock_irqrestore(&hashbin->hb_spinlock, flags);
@@ -813,7 +813,7 @@
* This allow to check if the current item is still in the
* hashbin or has been removed.
*/
- entry = (irda_queue_t* ) hashbin_find( hashbin, hashv, name );
+ entry = hashbin_find(hashbin, hashv, name);
/*
* Trick hashbin_get_next() to return what we want
diff --git a/net/irda/irttp.c b/net/irda/irttp.c
index 9d9af46..285ccd6 100644
--- a/net/irda/irttp.c
+++ b/net/irda/irttp.c
@@ -350,7 +350,7 @@
{
struct tsap_cb *self;
- self = (struct tsap_cb *) instance;
+ self = instance;
IRDA_ASSERT(self != NULL, return -1;);
IRDA_ASSERT(self->magic == TTP_TSAP_MAGIC, return -1;);
@@ -879,7 +879,7 @@
IRDA_DEBUG(4, "%s()\n", __func__);
- self = (struct tsap_cb *) instance;
+ self = instance;
IRDA_ASSERT(self != NULL, return -1;);
IRDA_ASSERT(self->magic == TTP_TSAP_MAGIC, return -1;);
@@ -914,7 +914,7 @@
unsigned long flags;
int n;
- self = (struct tsap_cb *) instance;
+ self = instance;
n = skb->data[0] & 0x7f; /* Extract the credits */
@@ -996,7 +996,7 @@
IRDA_DEBUG(4, "%s()\n", __func__);
- self = (struct tsap_cb *) instance;
+ self = instance;
IRDA_ASSERT(self != NULL, return;);
IRDA_ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
@@ -1025,7 +1025,7 @@
{
struct tsap_cb *self;
- self = (struct tsap_cb *) instance;
+ self = instance;
IRDA_ASSERT(self != NULL, return;);
IRDA_ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
@@ -1208,7 +1208,7 @@
IRDA_DEBUG(4, "%s()\n", __func__);
- self = (struct tsap_cb *) instance;
+ self = instance;
IRDA_ASSERT(self != NULL, return;);
IRDA_ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
@@ -1292,13 +1292,13 @@
__u8 plen;
__u8 n;
- self = (struct tsap_cb *) instance;
+ self = instance;
IRDA_ASSERT(self != NULL, return;);
IRDA_ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
IRDA_ASSERT(skb != NULL, return;);
- lsap = (struct lsap_cb *) sap;
+ lsap = sap;
self->max_seg_size = max_seg_size - TTP_HEADER;
self->max_header_size = max_header_size+TTP_HEADER;
@@ -1602,7 +1602,7 @@
IRDA_DEBUG(4, "%s()\n", __func__);
- self = (struct tsap_cb *) instance;
+ self = instance;
IRDA_ASSERT(self != NULL, return;);
IRDA_ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
diff --git a/net/key/af_key.c b/net/key/af_key.c
index 8f92cf8..1e733e9 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -621,7 +621,7 @@
unsigned short family;
xfrm_address_t *xaddr;
- sa = (const struct sadb_sa *) ext_hdrs[SADB_EXT_SA-1];
+ sa = ext_hdrs[SADB_EXT_SA - 1];
if (sa == NULL)
return NULL;
@@ -630,7 +630,7 @@
return NULL;
/* sadb_address_len should be checked by caller */
- addr = (const struct sadb_address *) ext_hdrs[SADB_EXT_ADDRESS_DST-1];
+ addr = ext_hdrs[SADB_EXT_ADDRESS_DST - 1];
if (addr == NULL)
return NULL;
@@ -1039,7 +1039,7 @@
int err;
- sa = (const struct sadb_sa *) ext_hdrs[SADB_EXT_SA-1];
+ sa = ext_hdrs[SADB_EXT_SA - 1];
if (!sa ||
!present_and_same_family(ext_hdrs[SADB_EXT_ADDRESS_SRC-1],
ext_hdrs[SADB_EXT_ADDRESS_DST-1]))
@@ -1078,7 +1078,7 @@
sa->sadb_sa_encrypt > SADB_X_CALG_MAX) ||
sa->sadb_sa_encrypt > SADB_EALG_MAX)
return ERR_PTR(-EINVAL);
- key = (const struct sadb_key*) ext_hdrs[SADB_EXT_KEY_AUTH-1];
+ key = ext_hdrs[SADB_EXT_KEY_AUTH - 1];
if (key != NULL &&
sa->sadb_sa_auth != SADB_X_AALG_NULL &&
((key->sadb_key_bits+7) / 8 == 0 ||
@@ -1105,14 +1105,14 @@
if (sa->sadb_sa_flags & SADB_SAFLAGS_NOPMTUDISC)
x->props.flags |= XFRM_STATE_NOPMTUDISC;
- lifetime = (const struct sadb_lifetime*) ext_hdrs[SADB_EXT_LIFETIME_HARD-1];
+ lifetime = ext_hdrs[SADB_EXT_LIFETIME_HARD - 1];
if (lifetime != NULL) {
x->lft.hard_packet_limit = _KEY2X(lifetime->sadb_lifetime_allocations);
x->lft.hard_byte_limit = _KEY2X(lifetime->sadb_lifetime_bytes);
x->lft.hard_add_expires_seconds = lifetime->sadb_lifetime_addtime;
x->lft.hard_use_expires_seconds = lifetime->sadb_lifetime_usetime;
}
- lifetime = (const struct sadb_lifetime*) ext_hdrs[SADB_EXT_LIFETIME_SOFT-1];
+ lifetime = ext_hdrs[SADB_EXT_LIFETIME_SOFT - 1];
if (lifetime != NULL) {
x->lft.soft_packet_limit = _KEY2X(lifetime->sadb_lifetime_allocations);
x->lft.soft_byte_limit = _KEY2X(lifetime->sadb_lifetime_bytes);
@@ -1120,7 +1120,7 @@
x->lft.soft_use_expires_seconds = lifetime->sadb_lifetime_usetime;
}
- sec_ctx = (const struct sadb_x_sec_ctx *) ext_hdrs[SADB_X_EXT_SEC_CTX-1];
+ sec_ctx = ext_hdrs[SADB_X_EXT_SEC_CTX - 1];
if (sec_ctx != NULL) {
struct xfrm_user_sec_ctx *uctx = pfkey_sadb2xfrm_user_sec_ctx(sec_ctx);
@@ -1134,7 +1134,7 @@
goto out;
}
- key = (const struct sadb_key*) ext_hdrs[SADB_EXT_KEY_AUTH-1];
+ key = ext_hdrs[SADB_EXT_KEY_AUTH - 1];
if (sa->sadb_sa_auth) {
int keysize = 0;
struct xfrm_algo_desc *a = xfrm_aalg_get_byid(sa->sadb_sa_auth);
@@ -2219,7 +2219,7 @@
if (xp->selector.dport)
xp->selector.dport_mask = htons(0xffff);
- sec_ctx = (struct sadb_x_sec_ctx *) ext_hdrs[SADB_X_EXT_SEC_CTX-1];
+ sec_ctx = ext_hdrs[SADB_X_EXT_SEC_CTX - 1];
if (sec_ctx != NULL) {
struct xfrm_user_sec_ctx *uctx = pfkey_sadb2xfrm_user_sec_ctx(sec_ctx);
@@ -2323,7 +2323,7 @@
if (sel.dport)
sel.dport_mask = htons(0xffff);
- sec_ctx = (struct sadb_x_sec_ctx *) ext_hdrs[SADB_X_EXT_SEC_CTX-1];
+ sec_ctx = ext_hdrs[SADB_X_EXT_SEC_CTX - 1];
if (sec_ctx != NULL) {
struct xfrm_user_sec_ctx *uctx = pfkey_sadb2xfrm_user_sec_ctx(sec_ctx);
diff --git a/net/l2tp/l2tp_ip.c b/net/l2tp/l2tp_ip.c
index b6466e7..d21e7eb 100644
--- a/net/l2tp/l2tp_ip.c
+++ b/net/l2tp/l2tp_ip.c
@@ -480,18 +480,16 @@
if (connected)
rt = (struct rtable *) __sk_dst_check(sk, 0);
+ rcu_read_lock();
if (rt == NULL) {
- struct ip_options_rcu *inet_opt;
+ const struct ip_options_rcu *inet_opt;
- rcu_read_lock();
inet_opt = rcu_dereference(inet->inet_opt);
/* Use correct destination address if we have options. */
if (inet_opt && inet_opt->opt.srr)
daddr = inet_opt->opt.faddr;
- rcu_read_unlock();
-
/* If this fails, retransmit mechanism of transport layer will
* keep trying until route appears or the connection times
* itself out.
@@ -503,12 +501,20 @@
sk->sk_bound_dev_if);
if (IS_ERR(rt))
goto no_route;
- sk_setup_caps(sk, &rt->dst);
+ if (connected)
+ sk_setup_caps(sk, &rt->dst);
+ else
+ dst_release(&rt->dst); /* safe since we hold rcu_read_lock */
}
- skb_dst_set(skb, dst_clone(&rt->dst));
+
+ /* We dont need to clone dst here, it is guaranteed to not disappear.
+ * __dev_xmit_skb() might force a refcount if needed.
+ */
+ skb_dst_set_noref(skb, &rt->dst);
/* Queue the packet to IP for output */
rc = ip_queue_xmit(skb, &inet->cork.fl);
+ rcu_read_unlock();
error:
/* Update stats */
@@ -525,6 +531,7 @@
return rc;
no_route:
+ rcu_read_unlock();
IP_INC_STATS(sock_net(sk), IPSTATS_MIB_OUTNOROUTES);
kfree_skb(skb);
rc = -EHOSTUNREACH;
diff --git a/net/lapb/lapb_iface.c b/net/lapb/lapb_iface.c
index d5d8d55..956b7e4 100644
--- a/net/lapb/lapb_iface.c
+++ b/net/lapb/lapb_iface.c
@@ -300,26 +300,26 @@
goto out;
switch (lapb->state) {
- case LAPB_STATE_0:
- rc = LAPB_NOTCONNECTED;
- goto out_put;
+ case LAPB_STATE_0:
+ rc = LAPB_NOTCONNECTED;
+ goto out_put;
- case LAPB_STATE_1:
+ case LAPB_STATE_1:
#if LAPB_DEBUG > 1
- printk(KERN_DEBUG "lapb: (%p) S1 TX DISC(1)\n", lapb->dev);
+ printk(KERN_DEBUG "lapb: (%p) S1 TX DISC(1)\n", lapb->dev);
#endif
#if LAPB_DEBUG > 0
- printk(KERN_DEBUG "lapb: (%p) S1 -> S0\n", lapb->dev);
+ printk(KERN_DEBUG "lapb: (%p) S1 -> S0\n", lapb->dev);
#endif
- lapb_send_control(lapb, LAPB_DISC, LAPB_POLLON, LAPB_COMMAND);
- lapb->state = LAPB_STATE_0;
- lapb_start_t1timer(lapb);
- rc = LAPB_NOTCONNECTED;
- goto out_put;
+ lapb_send_control(lapb, LAPB_DISC, LAPB_POLLON, LAPB_COMMAND);
+ lapb->state = LAPB_STATE_0;
+ lapb_start_t1timer(lapb);
+ rc = LAPB_NOTCONNECTED;
+ goto out_put;
- case LAPB_STATE_2:
- rc = LAPB_OK;
- goto out_put;
+ case LAPB_STATE_2:
+ rc = LAPB_OK;
+ goto out_put;
}
lapb_clear_queues(lapb);
diff --git a/net/lapb/lapb_in.c b/net/lapb/lapb_in.c
index 21904a0..2ec1af5 100644
--- a/net/lapb/lapb_in.c
+++ b/net/lapb/lapb_in.c
@@ -44,89 +44,86 @@
struct lapb_frame *frame)
{
switch (frame->type) {
- case LAPB_SABM:
+ case LAPB_SABM:
#if LAPB_DEBUG > 1
- printk(KERN_DEBUG "lapb: (%p) S0 RX SABM(%d)\n",
+ printk(KERN_DEBUG "lapb: (%p) S0 RX SABM(%d)\n",
+ lapb->dev, frame->pf);
+#endif
+ if (lapb->mode & LAPB_EXTENDED) {
+#if LAPB_DEBUG > 1
+ printk(KERN_DEBUG "lapb: (%p) S0 TX DM(%d)\n",
lapb->dev, frame->pf);
#endif
- if (lapb->mode & LAPB_EXTENDED) {
+ lapb_send_control(lapb, LAPB_DM, frame->pf,
+ LAPB_RESPONSE);
+ } else {
#if LAPB_DEBUG > 1
- printk(KERN_DEBUG "lapb: (%p) S0 TX DM(%d)\n",
- lapb->dev, frame->pf);
-#endif
- lapb_send_control(lapb, LAPB_DM, frame->pf,
- LAPB_RESPONSE);
- } else {
-#if LAPB_DEBUG > 1
- printk(KERN_DEBUG "lapb: (%p) S0 TX UA(%d)\n",
- lapb->dev, frame->pf);
-#endif
-#if LAPB_DEBUG > 0
- printk(KERN_DEBUG "lapb: (%p) S0 -> S3\n",
- lapb->dev);
-#endif
- lapb_send_control(lapb, LAPB_UA, frame->pf,
- LAPB_RESPONSE);
- lapb_stop_t1timer(lapb);
- lapb_stop_t2timer(lapb);
- lapb->state = LAPB_STATE_3;
- lapb->condition = 0x00;
- lapb->n2count = 0;
- lapb->vs = 0;
- lapb->vr = 0;
- lapb->va = 0;
- lapb_connect_indication(lapb, LAPB_OK);
- }
- break;
-
- case LAPB_SABME:
-#if LAPB_DEBUG > 1
- printk(KERN_DEBUG "lapb: (%p) S0 RX SABME(%d)\n",
- lapb->dev, frame->pf);
-#endif
- if (lapb->mode & LAPB_EXTENDED) {
-#if LAPB_DEBUG > 1
- printk(KERN_DEBUG "lapb: (%p) S0 TX UA(%d)\n",
- lapb->dev, frame->pf);
-#endif
-#if LAPB_DEBUG > 0
- printk(KERN_DEBUG "lapb: (%p) S0 -> S3\n",
- lapb->dev);
-#endif
- lapb_send_control(lapb, LAPB_UA, frame->pf,
- LAPB_RESPONSE);
- lapb_stop_t1timer(lapb);
- lapb_stop_t2timer(lapb);
- lapb->state = LAPB_STATE_3;
- lapb->condition = 0x00;
- lapb->n2count = 0;
- lapb->vs = 0;
- lapb->vr = 0;
- lapb->va = 0;
- lapb_connect_indication(lapb, LAPB_OK);
- } else {
-#if LAPB_DEBUG > 1
- printk(KERN_DEBUG "lapb: (%p) S0 TX DM(%d)\n",
- lapb->dev, frame->pf);
-#endif
- lapb_send_control(lapb, LAPB_DM, frame->pf,
- LAPB_RESPONSE);
- }
- break;
-
- case LAPB_DISC:
-#if LAPB_DEBUG > 1
- printk(KERN_DEBUG "lapb: (%p) S0 RX DISC(%d)\n",
- lapb->dev, frame->pf);
printk(KERN_DEBUG "lapb: (%p) S0 TX UA(%d)\n",
lapb->dev, frame->pf);
#endif
+#if LAPB_DEBUG > 0
+ printk(KERN_DEBUG "lapb: (%p) S0 -> S3\n", lapb->dev);
+#endif
lapb_send_control(lapb, LAPB_UA, frame->pf,
LAPB_RESPONSE);
- break;
+ lapb_stop_t1timer(lapb);
+ lapb_stop_t2timer(lapb);
+ lapb->state = LAPB_STATE_3;
+ lapb->condition = 0x00;
+ lapb->n2count = 0;
+ lapb->vs = 0;
+ lapb->vr = 0;
+ lapb->va = 0;
+ lapb_connect_indication(lapb, LAPB_OK);
+ }
+ break;
- default:
- break;
+ case LAPB_SABME:
+#if LAPB_DEBUG > 1
+ printk(KERN_DEBUG "lapb: (%p) S0 RX SABME(%d)\n",
+ lapb->dev, frame->pf);
+#endif
+ if (lapb->mode & LAPB_EXTENDED) {
+#if LAPB_DEBUG > 1
+ printk(KERN_DEBUG "lapb: (%p) S0 TX UA(%d)\n",
+ lapb->dev, frame->pf);
+#endif
+#if LAPB_DEBUG > 0
+ printk(KERN_DEBUG "lapb: (%p) S0 -> S3\n", lapb->dev);
+#endif
+ lapb_send_control(lapb, LAPB_UA, frame->pf,
+ LAPB_RESPONSE);
+ lapb_stop_t1timer(lapb);
+ lapb_stop_t2timer(lapb);
+ lapb->state = LAPB_STATE_3;
+ lapb->condition = 0x00;
+ lapb->n2count = 0;
+ lapb->vs = 0;
+ lapb->vr = 0;
+ lapb->va = 0;
+ lapb_connect_indication(lapb, LAPB_OK);
+ } else {
+#if LAPB_DEBUG > 1
+ printk(KERN_DEBUG "lapb: (%p) S0 TX DM(%d)\n",
+ lapb->dev, frame->pf);
+#endif
+ lapb_send_control(lapb, LAPB_DM, frame->pf,
+ LAPB_RESPONSE);
+ }
+ break;
+
+ case LAPB_DISC:
+#if LAPB_DEBUG > 1
+ printk(KERN_DEBUG "lapb: (%p) S0 RX DISC(%d)\n",
+ lapb->dev, frame->pf);
+ printk(KERN_DEBUG "lapb: (%p) S0 TX UA(%d)\n",
+ lapb->dev, frame->pf);
+#endif
+ lapb_send_control(lapb, LAPB_UA, frame->pf, LAPB_RESPONSE);
+ break;
+
+ default:
+ break;
}
kfree_skb(skb);
@@ -140,100 +137,97 @@
struct lapb_frame *frame)
{
switch (frame->type) {
- case LAPB_SABM:
+ case LAPB_SABM:
#if LAPB_DEBUG > 1
- printk(KERN_DEBUG "lapb: (%p) S1 RX SABM(%d)\n",
- lapb->dev, frame->pf);
+ printk(KERN_DEBUG "lapb: (%p) S1 RX SABM(%d)\n",
+ lapb->dev, frame->pf);
#endif
- if (lapb->mode & LAPB_EXTENDED) {
+ if (lapb->mode & LAPB_EXTENDED) {
#if LAPB_DEBUG > 1
- printk(KERN_DEBUG "lapb: (%p) S1 TX DM(%d)\n",
- lapb->dev, frame->pf);
-#endif
- lapb_send_control(lapb, LAPB_DM, frame->pf,
- LAPB_RESPONSE);
- } else {
-#if LAPB_DEBUG > 1
- printk(KERN_DEBUG "lapb: (%p) S1 TX UA(%d)\n",
- lapb->dev, frame->pf);
-#endif
- lapb_send_control(lapb, LAPB_UA, frame->pf,
- LAPB_RESPONSE);
- }
- break;
-
- case LAPB_SABME:
-#if LAPB_DEBUG > 1
- printk(KERN_DEBUG "lapb: (%p) S1 RX SABME(%d)\n",
- lapb->dev, frame->pf);
-#endif
- if (lapb->mode & LAPB_EXTENDED) {
-#if LAPB_DEBUG > 1
- printk(KERN_DEBUG "lapb: (%p) S1 TX UA(%d)\n",
- lapb->dev, frame->pf);
-#endif
- lapb_send_control(lapb, LAPB_UA, frame->pf,
- LAPB_RESPONSE);
- } else {
-#if LAPB_DEBUG > 1
- printk(KERN_DEBUG "lapb: (%p) S1 TX DM(%d)\n",
- lapb->dev, frame->pf);
-#endif
- lapb_send_control(lapb, LAPB_DM, frame->pf,
- LAPB_RESPONSE);
- }
- break;
-
- case LAPB_DISC:
-#if LAPB_DEBUG > 1
- printk(KERN_DEBUG "lapb: (%p) S1 RX DISC(%d)\n",
- lapb->dev, frame->pf);
printk(KERN_DEBUG "lapb: (%p) S1 TX DM(%d)\n",
lapb->dev, frame->pf);
#endif
lapb_send_control(lapb, LAPB_DM, frame->pf,
LAPB_RESPONSE);
- break;
-
- case LAPB_UA:
+ } else {
#if LAPB_DEBUG > 1
- printk(KERN_DEBUG "lapb: (%p) S1 RX UA(%d)\n",
+ printk(KERN_DEBUG "lapb: (%p) S1 TX UA(%d)\n",
lapb->dev, frame->pf);
#endif
- if (frame->pf) {
-#if LAPB_DEBUG > 0
- printk(KERN_DEBUG "lapb: (%p) S1 -> S3\n",
- lapb->dev);
-#endif
- lapb_stop_t1timer(lapb);
- lapb_stop_t2timer(lapb);
- lapb->state = LAPB_STATE_3;
- lapb->condition = 0x00;
- lapb->n2count = 0;
- lapb->vs = 0;
- lapb->vr = 0;
- lapb->va = 0;
- lapb_connect_confirmation(lapb, LAPB_OK);
- }
- break;
+ lapb_send_control(lapb, LAPB_UA, frame->pf,
+ LAPB_RESPONSE);
+ }
+ break;
- case LAPB_DM:
+ case LAPB_SABME:
#if LAPB_DEBUG > 1
- printk(KERN_DEBUG "lapb: (%p) S1 RX DM(%d)\n",
+ printk(KERN_DEBUG "lapb: (%p) S1 RX SABME(%d)\n",
+ lapb->dev, frame->pf);
+#endif
+ if (lapb->mode & LAPB_EXTENDED) {
+#if LAPB_DEBUG > 1
+ printk(KERN_DEBUG "lapb: (%p) S1 TX UA(%d)\n",
lapb->dev, frame->pf);
#endif
- if (frame->pf) {
-#if LAPB_DEBUG > 0
- printk(KERN_DEBUG "lapb: (%p) S1 -> S0\n",
- lapb->dev);
+ lapb_send_control(lapb, LAPB_UA, frame->pf,
+ LAPB_RESPONSE);
+ } else {
+#if LAPB_DEBUG > 1
+ printk(KERN_DEBUG "lapb: (%p) S1 TX DM(%d)\n",
+ lapb->dev, frame->pf);
#endif
- lapb_clear_queues(lapb);
- lapb->state = LAPB_STATE_0;
- lapb_start_t1timer(lapb);
- lapb_stop_t2timer(lapb);
- lapb_disconnect_indication(lapb, LAPB_REFUSED);
- }
- break;
+ lapb_send_control(lapb, LAPB_DM, frame->pf,
+ LAPB_RESPONSE);
+ }
+ break;
+
+ case LAPB_DISC:
+#if LAPB_DEBUG > 1
+ printk(KERN_DEBUG "lapb: (%p) S1 RX DISC(%d)\n",
+ lapb->dev, frame->pf);
+ printk(KERN_DEBUG "lapb: (%p) S1 TX DM(%d)\n",
+ lapb->dev, frame->pf);
+#endif
+ lapb_send_control(lapb, LAPB_DM, frame->pf, LAPB_RESPONSE);
+ break;
+
+ case LAPB_UA:
+#if LAPB_DEBUG > 1
+ printk(KERN_DEBUG "lapb: (%p) S1 RX UA(%d)\n",
+ lapb->dev, frame->pf);
+#endif
+ if (frame->pf) {
+#if LAPB_DEBUG > 0
+ printk(KERN_DEBUG "lapb: (%p) S1 -> S3\n", lapb->dev);
+#endif
+ lapb_stop_t1timer(lapb);
+ lapb_stop_t2timer(lapb);
+ lapb->state = LAPB_STATE_3;
+ lapb->condition = 0x00;
+ lapb->n2count = 0;
+ lapb->vs = 0;
+ lapb->vr = 0;
+ lapb->va = 0;
+ lapb_connect_confirmation(lapb, LAPB_OK);
+ }
+ break;
+
+ case LAPB_DM:
+#if LAPB_DEBUG > 1
+ printk(KERN_DEBUG "lapb: (%p) S1 RX DM(%d)\n",
+ lapb->dev, frame->pf);
+#endif
+ if (frame->pf) {
+#if LAPB_DEBUG > 0
+ printk(KERN_DEBUG "lapb: (%p) S1 -> S0\n", lapb->dev);
+#endif
+ lapb_clear_queues(lapb);
+ lapb->state = LAPB_STATE_0;
+ lapb_start_t1timer(lapb);
+ lapb_stop_t2timer(lapb);
+ lapb_disconnect_indication(lapb, LAPB_REFUSED);
+ }
+ break;
}
kfree_skb(skb);
@@ -247,78 +241,73 @@
struct lapb_frame *frame)
{
switch (frame->type) {
- case LAPB_SABM:
- case LAPB_SABME:
+ case LAPB_SABM:
+ case LAPB_SABME:
#if LAPB_DEBUG > 1
- printk(KERN_DEBUG "lapb: (%p) S2 RX {SABM,SABME}(%d)\n",
- lapb->dev, frame->pf);
- printk(KERN_DEBUG "lapb: (%p) S2 TX DM(%d)\n",
- lapb->dev, frame->pf);
+ printk(KERN_DEBUG "lapb: (%p) S2 RX {SABM,SABME}(%d)\n",
+ lapb->dev, frame->pf);
+ printk(KERN_DEBUG "lapb: (%p) S2 TX DM(%d)\n",
+ lapb->dev, frame->pf);
#endif
+ lapb_send_control(lapb, LAPB_DM, frame->pf, LAPB_RESPONSE);
+ break;
+
+ case LAPB_DISC:
+#if LAPB_DEBUG > 1
+ printk(KERN_DEBUG "lapb: (%p) S2 RX DISC(%d)\n",
+ lapb->dev, frame->pf);
+ printk(KERN_DEBUG "lapb: (%p) S2 TX UA(%d)\n",
+ lapb->dev, frame->pf);
+#endif
+ lapb_send_control(lapb, LAPB_UA, frame->pf, LAPB_RESPONSE);
+ break;
+
+ case LAPB_UA:
+#if LAPB_DEBUG > 1
+ printk(KERN_DEBUG "lapb: (%p) S2 RX UA(%d)\n",
+ lapb->dev, frame->pf);
+#endif
+ if (frame->pf) {
+#if LAPB_DEBUG > 0
+ printk(KERN_DEBUG "lapb: (%p) S2 -> S0\n", lapb->dev);
+#endif
+ lapb->state = LAPB_STATE_0;
+ lapb_start_t1timer(lapb);
+ lapb_stop_t2timer(lapb);
+ lapb_disconnect_confirmation(lapb, LAPB_OK);
+ }
+ break;
+
+ case LAPB_DM:
+#if LAPB_DEBUG > 1
+ printk(KERN_DEBUG "lapb: (%p) S2 RX DM(%d)\n",
+ lapb->dev, frame->pf);
+#endif
+ if (frame->pf) {
+#if LAPB_DEBUG > 0
+ printk(KERN_DEBUG "lapb: (%p) S2 -> S0\n", lapb->dev);
+#endif
+ lapb->state = LAPB_STATE_0;
+ lapb_start_t1timer(lapb);
+ lapb_stop_t2timer(lapb);
+ lapb_disconnect_confirmation(lapb, LAPB_NOTCONNECTED);
+ }
+ break;
+
+ case LAPB_I:
+ case LAPB_REJ:
+ case LAPB_RNR:
+ case LAPB_RR:
+#if LAPB_DEBUG > 1
+ printk(KERN_DEBUG "lapb: (%p) S2 RX {I,REJ,RNR,RR}(%d)\n",
+ lapb->dev, frame->pf);
+ printk(KERN_DEBUG "lapb: (%p) S2 RX DM(%d)\n",
+ lapb->dev, frame->pf);
+#endif
+ if (frame->pf)
lapb_send_control(lapb, LAPB_DM, frame->pf,
LAPB_RESPONSE);
- break;
-
- case LAPB_DISC:
-#if LAPB_DEBUG > 1
- printk(KERN_DEBUG "lapb: (%p) S2 RX DISC(%d)\n",
- lapb->dev, frame->pf);
- printk(KERN_DEBUG "lapb: (%p) S2 TX UA(%d)\n",
- lapb->dev, frame->pf);
-#endif
- lapb_send_control(lapb, LAPB_UA, frame->pf,
- LAPB_RESPONSE);
- break;
-
- case LAPB_UA:
-#if LAPB_DEBUG > 1
- printk(KERN_DEBUG "lapb: (%p) S2 RX UA(%d)\n",
- lapb->dev, frame->pf);
-#endif
- if (frame->pf) {
-#if LAPB_DEBUG > 0
- printk(KERN_DEBUG "lapb: (%p) S2 -> S0\n",
- lapb->dev);
-#endif
- lapb->state = LAPB_STATE_0;
- lapb_start_t1timer(lapb);
- lapb_stop_t2timer(lapb);
- lapb_disconnect_confirmation(lapb, LAPB_OK);
- }
- break;
-
- case LAPB_DM:
-#if LAPB_DEBUG > 1
- printk(KERN_DEBUG "lapb: (%p) S2 RX DM(%d)\n",
- lapb->dev, frame->pf);
-#endif
- if (frame->pf) {
-#if LAPB_DEBUG > 0
- printk(KERN_DEBUG "lapb: (%p) S2 -> S0\n",
- lapb->dev);
-#endif
- lapb->state = LAPB_STATE_0;
- lapb_start_t1timer(lapb);
- lapb_stop_t2timer(lapb);
- lapb_disconnect_confirmation(lapb,
- LAPB_NOTCONNECTED);
- }
- break;
-
- case LAPB_I:
- case LAPB_REJ:
- case LAPB_RNR:
- case LAPB_RR:
-#if LAPB_DEBUG > 1
- printk(KERN_DEBUG "lapb: (%p) S2 RX {I,REJ,RNR,RR}"
- "(%d)\n", lapb->dev, frame->pf);
- printk(KERN_DEBUG "lapb: (%p) S2 RX DM(%d)\n",
- lapb->dev, frame->pf);
-#endif
- if (frame->pf)
- lapb_send_control(lapb, LAPB_DM, frame->pf,
- LAPB_RESPONSE);
- break;
+ break;
}
kfree_skb(skb);
@@ -336,268 +325,177 @@
LAPB_SMODULUS;
switch (frame->type) {
- case LAPB_SABM:
+ case LAPB_SABM:
#if LAPB_DEBUG > 1
- printk(KERN_DEBUG "lapb: (%p) S3 RX SABM(%d)\n",
+ printk(KERN_DEBUG "lapb: (%p) S3 RX SABM(%d)\n",
+ lapb->dev, frame->pf);
+#endif
+ if (lapb->mode & LAPB_EXTENDED) {
+#if LAPB_DEBUG > 1
+ printk(KERN_DEBUG "lapb: (%p) S3 TX DM(%d)\n",
lapb->dev, frame->pf);
#endif
- if (lapb->mode & LAPB_EXTENDED) {
+ lapb_send_control(lapb, LAPB_DM, frame->pf,
+ LAPB_RESPONSE);
+ } else {
#if LAPB_DEBUG > 1
- printk(KERN_DEBUG "lapb: (%p) S3 TX DM(%d)\n",
- lapb->dev, frame->pf);
-#endif
- lapb_send_control(lapb, LAPB_DM, frame->pf,
- LAPB_RESPONSE);
- } else {
-#if LAPB_DEBUG > 1
- printk(KERN_DEBUG "lapb: (%p) S3 TX UA(%d)\n",
- lapb->dev, frame->pf);
-#endif
- lapb_send_control(lapb, LAPB_UA, frame->pf,
- LAPB_RESPONSE);
- lapb_stop_t1timer(lapb);
- lapb_stop_t2timer(lapb);
- lapb->condition = 0x00;
- lapb->n2count = 0;
- lapb->vs = 0;
- lapb->vr = 0;
- lapb->va = 0;
- lapb_requeue_frames(lapb);
- }
- break;
-
- case LAPB_SABME:
-#if LAPB_DEBUG > 1
- printk(KERN_DEBUG "lapb: (%p) S3 RX SABME(%d)\n",
+ printk(KERN_DEBUG "lapb: (%p) S3 TX UA(%d)\n",
lapb->dev, frame->pf);
#endif
- if (lapb->mode & LAPB_EXTENDED) {
-#if LAPB_DEBUG > 1
- printk(KERN_DEBUG "lapb: (%p) S3 TX UA(%d)\n",
- lapb->dev, frame->pf);
-#endif
- lapb_send_control(lapb, LAPB_UA, frame->pf,
- LAPB_RESPONSE);
- lapb_stop_t1timer(lapb);
- lapb_stop_t2timer(lapb);
- lapb->condition = 0x00;
- lapb->n2count = 0;
- lapb->vs = 0;
- lapb->vr = 0;
- lapb->va = 0;
- lapb_requeue_frames(lapb);
- } else {
-#if LAPB_DEBUG > 1
- printk(KERN_DEBUG "lapb: (%p) S3 TX DM(%d)\n",
- lapb->dev, frame->pf);
-#endif
- lapb_send_control(lapb, LAPB_DM, frame->pf,
- LAPB_RESPONSE);
- }
- break;
-
- case LAPB_DISC:
-#if LAPB_DEBUG > 1
- printk(KERN_DEBUG "lapb: (%p) S3 RX DISC(%d)\n",
- lapb->dev, frame->pf);
-#endif
-#if LAPB_DEBUG > 0
- printk(KERN_DEBUG "lapb: (%p) S3 -> S0\n",
- lapb->dev);
-#endif
- lapb_clear_queues(lapb);
lapb_send_control(lapb, LAPB_UA, frame->pf,
LAPB_RESPONSE);
- lapb_start_t1timer(lapb);
+ lapb_stop_t1timer(lapb);
lapb_stop_t2timer(lapb);
- lapb->state = LAPB_STATE_0;
- lapb_disconnect_indication(lapb, LAPB_OK);
- break;
-
- case LAPB_DM:
-#if LAPB_DEBUG > 1
- printk(KERN_DEBUG "lapb: (%p) S3 RX DM(%d)\n",
- lapb->dev, frame->pf);
-#endif
-#if LAPB_DEBUG > 0
- printk(KERN_DEBUG "lapb: (%p) S3 -> S0\n",
- lapb->dev);
-#endif
- lapb_clear_queues(lapb);
- lapb->state = LAPB_STATE_0;
- lapb_start_t1timer(lapb);
- lapb_stop_t2timer(lapb);
- lapb_disconnect_indication(lapb, LAPB_NOTCONNECTED);
- break;
-
- case LAPB_RNR:
-#if LAPB_DEBUG > 1
- printk(KERN_DEBUG "lapb: (%p) S3 RX RNR(%d) R%d\n",
- lapb->dev, frame->pf, frame->nr);
-#endif
- lapb->condition |= LAPB_PEER_RX_BUSY_CONDITION;
- lapb_check_need_response(lapb, frame->cr, frame->pf);
- if (lapb_validate_nr(lapb, frame->nr)) {
- lapb_check_iframes_acked(lapb, frame->nr);
- } else {
- lapb->frmr_data = *frame;
- lapb->frmr_type = LAPB_FRMR_Z;
- lapb_transmit_frmr(lapb);
-#if LAPB_DEBUG > 0
- printk(KERN_DEBUG "lapb: (%p) S3 -> S4\n",
- lapb->dev);
-#endif
- lapb_start_t1timer(lapb);
- lapb_stop_t2timer(lapb);
- lapb->state = LAPB_STATE_4;
- lapb->n2count = 0;
- }
- break;
-
- case LAPB_RR:
-#if LAPB_DEBUG > 1
- printk(KERN_DEBUG "lapb: (%p) S3 RX RR(%d) R%d\n",
- lapb->dev, frame->pf, frame->nr);
-#endif
- lapb->condition &= ~LAPB_PEER_RX_BUSY_CONDITION;
- lapb_check_need_response(lapb, frame->cr, frame->pf);
- if (lapb_validate_nr(lapb, frame->nr)) {
- lapb_check_iframes_acked(lapb, frame->nr);
- } else {
- lapb->frmr_data = *frame;
- lapb->frmr_type = LAPB_FRMR_Z;
- lapb_transmit_frmr(lapb);
-#if LAPB_DEBUG > 0
- printk(KERN_DEBUG "lapb: (%p) S3 -> S4\n",
- lapb->dev);
-#endif
- lapb_start_t1timer(lapb);
- lapb_stop_t2timer(lapb);
- lapb->state = LAPB_STATE_4;
- lapb->n2count = 0;
- }
- break;
-
- case LAPB_REJ:
-#if LAPB_DEBUG > 1
- printk(KERN_DEBUG "lapb: (%p) S3 RX REJ(%d) R%d\n",
- lapb->dev, frame->pf, frame->nr);
-#endif
- lapb->condition &= ~LAPB_PEER_RX_BUSY_CONDITION;
- lapb_check_need_response(lapb, frame->cr, frame->pf);
- if (lapb_validate_nr(lapb, frame->nr)) {
- lapb_frames_acked(lapb, frame->nr);
- lapb_stop_t1timer(lapb);
- lapb->n2count = 0;
- lapb_requeue_frames(lapb);
- } else {
- lapb->frmr_data = *frame;
- lapb->frmr_type = LAPB_FRMR_Z;
- lapb_transmit_frmr(lapb);
-#if LAPB_DEBUG > 0
- printk(KERN_DEBUG "lapb: (%p) S3 -> S4\n",
- lapb->dev);
-#endif
- lapb_start_t1timer(lapb);
- lapb_stop_t2timer(lapb);
- lapb->state = LAPB_STATE_4;
- lapb->n2count = 0;
- }
- break;
-
- case LAPB_I:
-#if LAPB_DEBUG > 1
- printk(KERN_DEBUG "lapb: (%p) S3 RX I(%d) S%d R%d\n",
- lapb->dev, frame->pf, frame->ns, frame->nr);
-#endif
- if (!lapb_validate_nr(lapb, frame->nr)) {
- lapb->frmr_data = *frame;
- lapb->frmr_type = LAPB_FRMR_Z;
- lapb_transmit_frmr(lapb);
-#if LAPB_DEBUG > 0
- printk(KERN_DEBUG "lapb: (%p) S3 -> S4\n",
- lapb->dev);
-#endif
- lapb_start_t1timer(lapb);
- lapb_stop_t2timer(lapb);
- lapb->state = LAPB_STATE_4;
- lapb->n2count = 0;
- break;
- }
- if (lapb->condition & LAPB_PEER_RX_BUSY_CONDITION)
- lapb_frames_acked(lapb, frame->nr);
- else
- lapb_check_iframes_acked(lapb, frame->nr);
-
- if (frame->ns == lapb->vr) {
- int cn;
- cn = lapb_data_indication(lapb, skb);
- queued = 1;
- /*
- * If upper layer has dropped the frame, we
- * basically ignore any further protocol
- * processing. This will cause the peer
- * to re-transmit the frame later like
- * a frame lost on the wire.
- */
- if (cn == NET_RX_DROP) {
- printk(KERN_DEBUG
- "LAPB: rx congestion\n");
- break;
- }
- lapb->vr = (lapb->vr + 1) % modulus;
- lapb->condition &= ~LAPB_REJECT_CONDITION;
- if (frame->pf)
- lapb_enquiry_response(lapb);
- else {
- if (!(lapb->condition &
- LAPB_ACK_PENDING_CONDITION)) {
- lapb->condition |= LAPB_ACK_PENDING_CONDITION;
- lapb_start_t2timer(lapb);
- }
- }
- } else {
- if (lapb->condition & LAPB_REJECT_CONDITION) {
- if (frame->pf)
- lapb_enquiry_response(lapb);
- } else {
-#if LAPB_DEBUG > 1
- printk(KERN_DEBUG
- "lapb: (%p) S3 TX REJ(%d) R%d\n",
- lapb->dev, frame->pf, lapb->vr);
-#endif
- lapb->condition |= LAPB_REJECT_CONDITION;
- lapb_send_control(lapb, LAPB_REJ,
- frame->pf,
- LAPB_RESPONSE);
- lapb->condition &= ~LAPB_ACK_PENDING_CONDITION;
- }
- }
- break;
-
- case LAPB_FRMR:
-#if LAPB_DEBUG > 1
- printk(KERN_DEBUG "lapb: (%p) S3 RX FRMR(%d) %02X "
- "%02X %02X %02X %02X\n", lapb->dev, frame->pf,
- skb->data[0], skb->data[1], skb->data[2],
- skb->data[3], skb->data[4]);
-#endif
- lapb_establish_data_link(lapb);
-#if LAPB_DEBUG > 0
- printk(KERN_DEBUG "lapb: (%p) S3 -> S1\n",
- lapb->dev);
-#endif
+ lapb->condition = 0x00;
+ lapb->n2count = 0;
+ lapb->vs = 0;
+ lapb->vr = 0;
+ lapb->va = 0;
lapb_requeue_frames(lapb);
- lapb->state = LAPB_STATE_1;
- break;
+ }
+ break;
- case LAPB_ILLEGAL:
+ case LAPB_SABME:
#if LAPB_DEBUG > 1
- printk(KERN_DEBUG "lapb: (%p) S3 RX ILLEGAL(%d)\n",
+ printk(KERN_DEBUG "lapb: (%p) S3 RX SABME(%d)\n",
+ lapb->dev, frame->pf);
+#endif
+ if (lapb->mode & LAPB_EXTENDED) {
+#if LAPB_DEBUG > 1
+ printk(KERN_DEBUG "lapb: (%p) S3 TX UA(%d)\n",
lapb->dev, frame->pf);
#endif
+ lapb_send_control(lapb, LAPB_UA, frame->pf,
+ LAPB_RESPONSE);
+ lapb_stop_t1timer(lapb);
+ lapb_stop_t2timer(lapb);
+ lapb->condition = 0x00;
+ lapb->n2count = 0;
+ lapb->vs = 0;
+ lapb->vr = 0;
+ lapb->va = 0;
+ lapb_requeue_frames(lapb);
+ } else {
+#if LAPB_DEBUG > 1
+ printk(KERN_DEBUG "lapb: (%p) S3 TX DM(%d)\n",
+ lapb->dev, frame->pf);
+#endif
+ lapb_send_control(lapb, LAPB_DM, frame->pf,
+ LAPB_RESPONSE);
+ }
+ break;
+
+ case LAPB_DISC:
+#if LAPB_DEBUG > 1
+ printk(KERN_DEBUG "lapb: (%p) S3 RX DISC(%d)\n",
+ lapb->dev, frame->pf);
+#endif
+#if LAPB_DEBUG > 0
+ printk(KERN_DEBUG "lapb: (%p) S3 -> S0\n", lapb->dev);
+#endif
+ lapb_clear_queues(lapb);
+ lapb_send_control(lapb, LAPB_UA, frame->pf, LAPB_RESPONSE);
+ lapb_start_t1timer(lapb);
+ lapb_stop_t2timer(lapb);
+ lapb->state = LAPB_STATE_0;
+ lapb_disconnect_indication(lapb, LAPB_OK);
+ break;
+
+ case LAPB_DM:
+#if LAPB_DEBUG > 1
+ printk(KERN_DEBUG "lapb: (%p) S3 RX DM(%d)\n",
+ lapb->dev, frame->pf);
+#endif
+#if LAPB_DEBUG > 0
+ printk(KERN_DEBUG "lapb: (%p) S3 -> S0\n", lapb->dev);
+#endif
+ lapb_clear_queues(lapb);
+ lapb->state = LAPB_STATE_0;
+ lapb_start_t1timer(lapb);
+ lapb_stop_t2timer(lapb);
+ lapb_disconnect_indication(lapb, LAPB_NOTCONNECTED);
+ break;
+
+ case LAPB_RNR:
+#if LAPB_DEBUG > 1
+ printk(KERN_DEBUG "lapb: (%p) S3 RX RNR(%d) R%d\n",
+ lapb->dev, frame->pf, frame->nr);
+#endif
+ lapb->condition |= LAPB_PEER_RX_BUSY_CONDITION;
+ lapb_check_need_response(lapb, frame->cr, frame->pf);
+ if (lapb_validate_nr(lapb, frame->nr)) {
+ lapb_check_iframes_acked(lapb, frame->nr);
+ } else {
lapb->frmr_data = *frame;
- lapb->frmr_type = LAPB_FRMR_W;
+ lapb->frmr_type = LAPB_FRMR_Z;
+ lapb_transmit_frmr(lapb);
+#if LAPB_DEBUG > 0
+ printk(KERN_DEBUG "lapb: (%p) S3 -> S4\n", lapb->dev);
+#endif
+ lapb_start_t1timer(lapb);
+ lapb_stop_t2timer(lapb);
+ lapb->state = LAPB_STATE_4;
+ lapb->n2count = 0;
+ }
+ break;
+
+ case LAPB_RR:
+#if LAPB_DEBUG > 1
+ printk(KERN_DEBUG "lapb: (%p) S3 RX RR(%d) R%d\n",
+ lapb->dev, frame->pf, frame->nr);
+#endif
+ lapb->condition &= ~LAPB_PEER_RX_BUSY_CONDITION;
+ lapb_check_need_response(lapb, frame->cr, frame->pf);
+ if (lapb_validate_nr(lapb, frame->nr)) {
+ lapb_check_iframes_acked(lapb, frame->nr);
+ } else {
+ lapb->frmr_data = *frame;
+ lapb->frmr_type = LAPB_FRMR_Z;
+ lapb_transmit_frmr(lapb);
+#if LAPB_DEBUG > 0
+ printk(KERN_DEBUG "lapb: (%p) S3 -> S4\n", lapb->dev);
+#endif
+ lapb_start_t1timer(lapb);
+ lapb_stop_t2timer(lapb);
+ lapb->state = LAPB_STATE_4;
+ lapb->n2count = 0;
+ }
+ break;
+
+ case LAPB_REJ:
+#if LAPB_DEBUG > 1
+ printk(KERN_DEBUG "lapb: (%p) S3 RX REJ(%d) R%d\n",
+ lapb->dev, frame->pf, frame->nr);
+#endif
+ lapb->condition &= ~LAPB_PEER_RX_BUSY_CONDITION;
+ lapb_check_need_response(lapb, frame->cr, frame->pf);
+ if (lapb_validate_nr(lapb, frame->nr)) {
+ lapb_frames_acked(lapb, frame->nr);
+ lapb_stop_t1timer(lapb);
+ lapb->n2count = 0;
+ lapb_requeue_frames(lapb);
+ } else {
+ lapb->frmr_data = *frame;
+ lapb->frmr_type = LAPB_FRMR_Z;
+ lapb_transmit_frmr(lapb);
+#if LAPB_DEBUG > 0
+ printk(KERN_DEBUG "lapb: (%p) S3 -> S4\n", lapb->dev);
+#endif
+ lapb_start_t1timer(lapb);
+ lapb_stop_t2timer(lapb);
+ lapb->state = LAPB_STATE_4;
+ lapb->n2count = 0;
+ }
+ break;
+
+ case LAPB_I:
+#if LAPB_DEBUG > 1
+ printk(KERN_DEBUG "lapb: (%p) S3 RX I(%d) S%d R%d\n",
+ lapb->dev, frame->pf, frame->ns, frame->nr);
+#endif
+ if (!lapb_validate_nr(lapb, frame->nr)) {
+ lapb->frmr_data = *frame;
+ lapb->frmr_type = LAPB_FRMR_Z;
lapb_transmit_frmr(lapb);
#if LAPB_DEBUG > 0
printk(KERN_DEBUG "lapb: (%p) S3 -> S4\n", lapb->dev);
@@ -607,6 +505,87 @@
lapb->state = LAPB_STATE_4;
lapb->n2count = 0;
break;
+ }
+ if (lapb->condition & LAPB_PEER_RX_BUSY_CONDITION)
+ lapb_frames_acked(lapb, frame->nr);
+ else
+ lapb_check_iframes_acked(lapb, frame->nr);
+
+ if (frame->ns == lapb->vr) {
+ int cn;
+ cn = lapb_data_indication(lapb, skb);
+ queued = 1;
+ /*
+ * If upper layer has dropped the frame, we
+ * basically ignore any further protocol
+ * processing. This will cause the peer
+ * to re-transmit the frame later like
+ * a frame lost on the wire.
+ */
+ if (cn == NET_RX_DROP) {
+ printk(KERN_DEBUG "LAPB: rx congestion\n");
+ break;
+ }
+ lapb->vr = (lapb->vr + 1) % modulus;
+ lapb->condition &= ~LAPB_REJECT_CONDITION;
+ if (frame->pf)
+ lapb_enquiry_response(lapb);
+ else {
+ if (!(lapb->condition &
+ LAPB_ACK_PENDING_CONDITION)) {
+ lapb->condition |= LAPB_ACK_PENDING_CONDITION;
+ lapb_start_t2timer(lapb);
+ }
+ }
+ } else {
+ if (lapb->condition & LAPB_REJECT_CONDITION) {
+ if (frame->pf)
+ lapb_enquiry_response(lapb);
+ } else {
+#if LAPB_DEBUG > 1
+ printk(KERN_DEBUG
+ "lapb: (%p) S3 TX REJ(%d) R%d\n",
+ lapb->dev, frame->pf, lapb->vr);
+#endif
+ lapb->condition |= LAPB_REJECT_CONDITION;
+ lapb_send_control(lapb, LAPB_REJ, frame->pf,
+ LAPB_RESPONSE);
+ lapb->condition &= ~LAPB_ACK_PENDING_CONDITION;
+ }
+ }
+ break;
+
+ case LAPB_FRMR:
+#if LAPB_DEBUG > 1
+ printk(KERN_DEBUG "lapb: (%p) S3 RX FRMR(%d) %02X "
+ "%02X %02X %02X %02X\n", lapb->dev, frame->pf,
+ skb->data[0], skb->data[1], skb->data[2],
+ skb->data[3], skb->data[4]);
+#endif
+ lapb_establish_data_link(lapb);
+#if LAPB_DEBUG > 0
+ printk(KERN_DEBUG "lapb: (%p) S3 -> S1\n", lapb->dev);
+#endif
+ lapb_requeue_frames(lapb);
+ lapb->state = LAPB_STATE_1;
+ break;
+
+ case LAPB_ILLEGAL:
+#if LAPB_DEBUG > 1
+ printk(KERN_DEBUG "lapb: (%p) S3 RX ILLEGAL(%d)\n",
+ lapb->dev, frame->pf);
+#endif
+ lapb->frmr_data = *frame;
+ lapb->frmr_type = LAPB_FRMR_W;
+ lapb_transmit_frmr(lapb);
+#if LAPB_DEBUG > 0
+ printk(KERN_DEBUG "lapb: (%p) S3 -> S4\n", lapb->dev);
+#endif
+ lapb_start_t1timer(lapb);
+ lapb_stop_t2timer(lapb);
+ lapb->state = LAPB_STATE_4;
+ lapb->n2count = 0;
+ break;
}
if (!queued)
@@ -621,75 +600,73 @@
struct lapb_frame *frame)
{
switch (frame->type) {
- case LAPB_SABM:
+ case LAPB_SABM:
#if LAPB_DEBUG > 1
- printk(KERN_DEBUG "lapb: (%p) S4 RX SABM(%d)\n",
+ printk(KERN_DEBUG "lapb: (%p) S4 RX SABM(%d)\n",
+ lapb->dev, frame->pf);
+#endif
+ if (lapb->mode & LAPB_EXTENDED) {
+#if LAPB_DEBUG > 1
+ printk(KERN_DEBUG "lapb: (%p) S4 TX DM(%d)\n",
lapb->dev, frame->pf);
#endif
- if (lapb->mode & LAPB_EXTENDED) {
+ lapb_send_control(lapb, LAPB_DM, frame->pf,
+ LAPB_RESPONSE);
+ } else {
#if LAPB_DEBUG > 1
- printk(KERN_DEBUG "lapb: (%p) S4 TX DM(%d)\n",
- lapb->dev, frame->pf);
-#endif
- lapb_send_control(lapb, LAPB_DM, frame->pf,
- LAPB_RESPONSE);
- } else {
-#if LAPB_DEBUG > 1
- printk(KERN_DEBUG "lapb: (%p) S4 TX UA(%d)\n",
- lapb->dev, frame->pf);
+ printk(KERN_DEBUG "lapb: (%p) S4 TX UA(%d)\n",
+ lapb->dev, frame->pf);
#endif
#if LAPB_DEBUG > 0
- printk(KERN_DEBUG "lapb: (%p) S4 -> S3\n",
- lapb->dev);
+ printk(KERN_DEBUG "lapb: (%p) S4 -> S3\n", lapb->dev);
#endif
- lapb_send_control(lapb, LAPB_UA, frame->pf,
- LAPB_RESPONSE);
- lapb_stop_t1timer(lapb);
- lapb_stop_t2timer(lapb);
- lapb->state = LAPB_STATE_3;
- lapb->condition = 0x00;
- lapb->n2count = 0;
- lapb->vs = 0;
- lapb->vr = 0;
- lapb->va = 0;
- lapb_connect_indication(lapb, LAPB_OK);
- }
- break;
+ lapb_send_control(lapb, LAPB_UA, frame->pf,
+ LAPB_RESPONSE);
+ lapb_stop_t1timer(lapb);
+ lapb_stop_t2timer(lapb);
+ lapb->state = LAPB_STATE_3;
+ lapb->condition = 0x00;
+ lapb->n2count = 0;
+ lapb->vs = 0;
+ lapb->vr = 0;
+ lapb->va = 0;
+ lapb_connect_indication(lapb, LAPB_OK);
+ }
+ break;
- case LAPB_SABME:
+ case LAPB_SABME:
#if LAPB_DEBUG > 1
- printk(KERN_DEBUG "lapb: (%p) S4 RX SABME(%d)\n",
+ printk(KERN_DEBUG "lapb: (%p) S4 RX SABME(%d)\n",
+ lapb->dev, frame->pf);
+#endif
+ if (lapb->mode & LAPB_EXTENDED) {
+#if LAPB_DEBUG > 1
+ printk(KERN_DEBUG "lapb: (%p) S4 TX UA(%d)\n",
lapb->dev, frame->pf);
#endif
- if (lapb->mode & LAPB_EXTENDED) {
-#if LAPB_DEBUG > 1
- printk(KERN_DEBUG "lapb: (%p) S4 TX UA(%d)\n",
- lapb->dev, frame->pf);
-#endif
#if LAPB_DEBUG > 0
- printk(KERN_DEBUG "lapb: (%p) S4 -> S3\n",
- lapb->dev);
+ printk(KERN_DEBUG "lapb: (%p) S4 -> S3\n", lapb->dev);
#endif
- lapb_send_control(lapb, LAPB_UA, frame->pf,
- LAPB_RESPONSE);
- lapb_stop_t1timer(lapb);
- lapb_stop_t2timer(lapb);
- lapb->state = LAPB_STATE_3;
- lapb->condition = 0x00;
- lapb->n2count = 0;
- lapb->vs = 0;
- lapb->vr = 0;
- lapb->va = 0;
- lapb_connect_indication(lapb, LAPB_OK);
- } else {
+ lapb_send_control(lapb, LAPB_UA, frame->pf,
+ LAPB_RESPONSE);
+ lapb_stop_t1timer(lapb);
+ lapb_stop_t2timer(lapb);
+ lapb->state = LAPB_STATE_3;
+ lapb->condition = 0x00;
+ lapb->n2count = 0;
+ lapb->vs = 0;
+ lapb->vr = 0;
+ lapb->va = 0;
+ lapb_connect_indication(lapb, LAPB_OK);
+ } else {
#if LAPB_DEBUG > 1
- printk(KERN_DEBUG "lapb: (%p) S4 TX DM(%d)\n",
- lapb->dev, frame->pf);
+ printk(KERN_DEBUG "lapb: (%p) S4 TX DM(%d)\n",
+ lapb->dev, frame->pf);
#endif
- lapb_send_control(lapb, LAPB_DM, frame->pf,
- LAPB_RESPONSE);
- }
- break;
+ lapb_send_control(lapb, LAPB_DM, frame->pf,
+ LAPB_RESPONSE);
+ }
+ break;
}
kfree_skb(skb);
diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c
index 9c0d76c..ebadb9a 100644
--- a/net/mac80211/agg-rx.c
+++ b/net/mac80211/agg-rx.c
@@ -100,6 +100,21 @@
mutex_unlock(&sta->ampdu_mlme.mtx);
}
+void ieee80211_stop_rx_ba_session(struct ieee80211_vif *vif, u16 ba_rx_bitmap,
+ const u8 *addr)
+{
+ struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
+ struct sta_info *sta = sta_info_get(sdata, addr);
+ int i;
+
+ for (i = 0; i < STA_TID_NUM; i++)
+ if (ba_rx_bitmap & BIT(i))
+ set_bit(i, sta->ampdu_mlme.tid_rx_stop_requested);
+
+ ieee80211_queue_work(&sta->local->hw, &sta->ampdu_mlme.work);
+}
+EXPORT_SYMBOL(ieee80211_stop_rx_ba_session);
+
/*
* After accepting the AddBA Request we activated a timer,
* resetting it after each frame that arrives from the originator.
@@ -247,7 +262,11 @@
"%pM on tid %u\n",
mgmt->sa, tid);
#endif /* CONFIG_MAC80211_HT_DEBUG */
- goto end;
+
+ /* delete existing Rx BA session on the same tid */
+ ___ieee80211_stop_rx_ba_session(sta, tid, WLAN_BACK_RECIPIENT,
+ WLAN_STATUS_UNSPECIFIED_QOS,
+ false);
}
/* prepare A-MPDU MLME for Rx aggregation */
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index be70c70..9fe22cc 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -674,8 +674,11 @@
if (mask & BIT(NL80211_STA_FLAG_WME)) {
sta->flags &= ~WLAN_STA_WME;
- if (set & BIT(NL80211_STA_FLAG_WME))
+ sta->sta.wme = false;
+ if (set & BIT(NL80211_STA_FLAG_WME)) {
sta->flags |= WLAN_STA_WME;
+ sta->sta.wme = true;
+ }
}
if (mask & BIT(NL80211_STA_FLAG_MFP)) {
@@ -1554,6 +1557,19 @@
return local->ops->testmode_cmd(&local->hw, data, len);
}
+
+static int ieee80211_testmode_dump(struct wiphy *wiphy,
+ struct sk_buff *skb,
+ struct netlink_callback *cb,
+ void *data, int len)
+{
+ struct ieee80211_local *local = wiphy_priv(wiphy);
+
+ if (!local->ops->testmode_dump)
+ return -EOPNOTSUPP;
+
+ return local->ops->testmode_dump(&local->hw, skb, cb, data, len);
+}
#endif
int __ieee80211_request_smps(struct ieee80211_sub_if_data *sdata,
@@ -2134,6 +2150,7 @@
.set_wds_peer = ieee80211_set_wds_peer,
.rfkill_poll = ieee80211_rfkill_poll,
CFG80211_TESTMODE_CMD(ieee80211_testmode_cmd)
+ CFG80211_TESTMODE_DUMP(ieee80211_testmode_dump)
.set_power_mgmt = ieee80211_set_power_mgmt,
.set_bitrate_mask = ieee80211_set_bitrate_mask,
.remain_on_channel = ieee80211_remain_on_channel,
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index eebf7a6..0e7e426 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -218,6 +218,16 @@
return ret;
}
+static inline void drv_cancel_hw_scan(struct ieee80211_local *local,
+ struct ieee80211_sub_if_data *sdata)
+{
+ might_sleep();
+
+ trace_drv_cancel_hw_scan(local, sdata);
+ local->ops->cancel_hw_scan(&local->hw, &sdata->vif);
+ trace_drv_return_void(local);
+}
+
static inline int
drv_sched_scan_start(struct ieee80211_local *local,
struct ieee80211_sub_if_data *sdata,
diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h
index ed9edcb..3cb6795 100644
--- a/net/mac80211/driver-trace.h
+++ b/net/mac80211/driver-trace.h
@@ -460,6 +460,12 @@
TP_ARGS(local, sdata)
);
+DEFINE_EVENT(local_sdata_evt, drv_cancel_hw_scan,
+ TP_PROTO(struct ieee80211_local *local,
+ struct ieee80211_sub_if_data *sdata),
+ TP_ARGS(local, sdata)
+);
+
DEFINE_EVENT(local_sdata_evt, drv_sched_scan_start,
TP_PROTO(struct ieee80211_local *local,
struct ieee80211_sub_if_data *sdata),
diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c
index 591add2..7cfc286 100644
--- a/net/mac80211/ht.c
+++ b/net/mac80211/ht.c
@@ -140,6 +140,12 @@
sta, tid, WLAN_BACK_RECIPIENT,
WLAN_REASON_QSTA_TIMEOUT, true);
+ if (test_and_clear_bit(tid,
+ sta->ampdu_mlme.tid_rx_stop_requested))
+ ___ieee80211_stop_rx_ba_session(
+ sta, tid, WLAN_BACK_RECIPIENT,
+ WLAN_REASON_UNSPECIFIED, true);
+
tid_tx = sta->ampdu_mlme.tid_start_tx[tid];
if (tid_tx) {
/*
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 090b0ec..25c15cc 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1350,10 +1350,12 @@
struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata,
u8 *dst,
const u8 *ssid, size_t ssid_len,
- const u8 *ie, size_t ie_len);
+ const u8 *ie, size_t ie_len,
+ bool directed);
void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst,
const u8 *ssid, size_t ssid_len,
- const u8 *ie, size_t ie_len);
+ const u8 *ie, size_t ie_len,
+ bool directed);
void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata,
const size_t supp_rates_len,
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index d595265..b874200 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -760,23 +760,34 @@
if (local->hw.conf.flags & IEEE80211_CONF_PS)
return;
- /*
- * transmission can be stopped by others which leads to
- * dynamic_ps_timer expiry. Postpond the ps timer if it
- * is not the actual idle state.
- */
- spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
- for (q = 0; q < local->hw.queues; q++) {
- if (local->queue_stop_reasons[q]) {
- spin_unlock_irqrestore(&local->queue_stop_reason_lock,
- flags);
+ if (!local->disable_dynamic_ps &&
+ local->hw.conf.dynamic_ps_timeout > 0) {
+ /* don't enter PS if TX frames are pending */
+ if (drv_tx_frames_pending(local)) {
mod_timer(&local->dynamic_ps_timer, jiffies +
msecs_to_jiffies(
local->hw.conf.dynamic_ps_timeout));
return;
}
+
+ /*
+ * transmission can be stopped by others which leads to
+ * dynamic_ps_timer expiry. Postpone the ps timer if it
+ * is not the actual idle state.
+ */
+ spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
+ for (q = 0; q < local->hw.queues; q++) {
+ if (local->queue_stop_reasons[q]) {
+ spin_unlock_irqrestore(&local->queue_stop_reason_lock,
+ flags);
+ mod_timer(&local->dynamic_ps_timer, jiffies +
+ msecs_to_jiffies(
+ local->hw.conf.dynamic_ps_timeout));
+ return;
+ }
+ }
+ spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
}
- spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
if ((local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) &&
(!(ifmgd->flags & IEEE80211_STA_NULLFUNC_ACKED))) {
@@ -801,7 +812,8 @@
ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
}
- netif_tx_wake_all_queues(sdata->dev);
+ if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK)
+ netif_tx_wake_all_queues(sdata->dev);
}
void ieee80211_dynamic_ps_timer(unsigned long data)
@@ -1204,7 +1216,8 @@
ieee80211_send_nullfunc(sdata->local, sdata, 0);
} else {
ssid = ieee80211_bss_get_ie(ifmgd->associated, WLAN_EID_SSID);
- ieee80211_send_probe_req(sdata, dst, ssid + 2, ssid[1], NULL, 0);
+ ieee80211_send_probe_req(sdata, dst, ssid + 2, ssid[1], NULL, 0,
+ true);
}
ifmgd->probe_send_count++;
@@ -1289,7 +1302,7 @@
ssid = ieee80211_bss_get_ie(ifmgd->associated, WLAN_EID_SSID);
skb = ieee80211_build_probe_req(sdata, ifmgd->associated->bssid,
- ssid + 2, ssid[1], NULL, 0);
+ ssid + 2, ssid[1], NULL, 0, true);
return skb;
}
@@ -2206,6 +2219,7 @@
add_timer(&ifmgd->chswitch_timer);
ieee80211_sta_reset_beacon_monitor(sdata);
ieee80211_restart_sta_timer(sdata);
+ ieee80211_queue_work(&sdata->local->hw, &sdata->u.mgd.monitor_work);
}
#endif
@@ -2652,3 +2666,10 @@
cfg80211_cqm_rssi_notify(sdata->dev, rssi_event, gfp);
}
EXPORT_SYMBOL(ieee80211_cqm_rssi_notify);
+
+unsigned char ieee80211_get_operstate(struct ieee80211_vif *vif)
+{
+ struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
+ return sdata->dev->operstate;
+}
+EXPORT_SYMBOL(ieee80211_get_operstate);
diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c
index 730778a..67839eb 100644
--- a/net/mac80211/pm.c
+++ b/net/mac80211/pm.c
@@ -6,6 +6,28 @@
#include "driver-ops.h"
#include "led.h"
+/* return value indicates whether the driver should be further notified */
+static bool ieee80211_quiesce(struct ieee80211_sub_if_data *sdata)
+{
+ switch (sdata->vif.type) {
+ case NL80211_IFTYPE_STATION:
+ ieee80211_sta_quiesce(sdata);
+ return true;
+ case NL80211_IFTYPE_ADHOC:
+ ieee80211_ibss_quiesce(sdata);
+ return true;
+ case NL80211_IFTYPE_MESH_POINT:
+ ieee80211_mesh_quiesce(sdata);
+ return true;
+ case NL80211_IFTYPE_AP_VLAN:
+ case NL80211_IFTYPE_MONITOR:
+ /* don't tell driver about this */
+ return false;
+ default:
+ return true;
+ }
+}
+
int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
{
struct ieee80211_local *local = hw_to_local(hw);
@@ -54,6 +76,10 @@
local->quiescing = false;
return err;
}
+ list_for_each_entry(sdata, &local->interfaces, list) {
+ cancel_work_sync(&sdata->work);
+ ieee80211_quiesce(sdata);
+ }
goto suspend;
}
@@ -82,23 +108,8 @@
list_for_each_entry(sdata, &local->interfaces, list) {
cancel_work_sync(&sdata->work);
- switch(sdata->vif.type) {
- case NL80211_IFTYPE_STATION:
- ieee80211_sta_quiesce(sdata);
- break;
- case NL80211_IFTYPE_ADHOC:
- ieee80211_ibss_quiesce(sdata);
- break;
- case NL80211_IFTYPE_MESH_POINT:
- ieee80211_mesh_quiesce(sdata);
- break;
- case NL80211_IFTYPE_AP_VLAN:
- case NL80211_IFTYPE_MONITOR:
- /* don't tell driver about this */
+ if (!ieee80211_quiesce(sdata))
continue;
- default:
- break;
- }
if (!ieee80211_sdata_running(sdata))
continue;
diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c
index 8adac67..58a8955 100644
--- a/net/mac80211/rc80211_minstrel.c
+++ b/net/mac80211/rc80211_minstrel.c
@@ -532,12 +532,21 @@
mp->hw = hw;
mp->update_interval = 100;
+#ifdef CONFIG_MAC80211_DEBUGFS
+ mp->fixed_rate_idx = (u32) -1;
+ mp->dbg_fixed_rate = debugfs_create_u32("fixed_rate_idx",
+ S_IRUGO | S_IWUGO, debugfsdir, &mp->fixed_rate_idx);
+#endif
+
return mp;
}
static void
minstrel_free(void *priv)
{
+#ifdef CONFIG_MAC80211_DEBUGFS
+ debugfs_remove(((struct minstrel_priv *)priv)->dbg_fixed_rate);
+#endif
kfree(priv);
}
diff --git a/net/mac80211/rc80211_minstrel.h b/net/mac80211/rc80211_minstrel.h
index 0f5a833..5d278ec 100644
--- a/net/mac80211/rc80211_minstrel.h
+++ b/net/mac80211/rc80211_minstrel.h
@@ -78,6 +78,18 @@
unsigned int update_interval;
unsigned int lookaround_rate;
unsigned int lookaround_rate_mrr;
+
+#ifdef CONFIG_MAC80211_DEBUGFS
+ /*
+ * enable fixed rate processing per RC
+ * - write static index to debugfs:ieee80211/phyX/rc/fixed_rate_idx
+ * - write -1 to enable RC processing again
+ * - setting will be applied on next update
+ */
+ u32 fixed_rate_idx;
+ struct dentry *dbg_fixed_rate;
+#endif
+
};
struct minstrel_debugfs_info {
diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c
index 333b511..66a1eeb 100644
--- a/net/mac80211/rc80211_minstrel_ht.c
+++ b/net/mac80211/rc80211_minstrel_ht.c
@@ -609,6 +609,13 @@
info->flags |= mi->tx_flags;
sample_idx = minstrel_get_sample_rate(mp, mi);
+
+#ifdef CONFIG_MAC80211_DEBUGFS
+ /* use fixed index if set */
+ if (mp->fixed_rate_idx != -1)
+ sample_idx = mp->fixed_rate_idx;
+#endif
+
if (sample_idx >= 0) {
sample = true;
minstrel_ht_set_rate(mp, mi, &ar[0], sample_idx,
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 7fa8c6b..b5493ec 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -338,7 +338,7 @@
u8 *qc = ieee80211_get_qos_ctl(hdr);
/* frame has qos control */
tid = *qc & IEEE80211_QOS_CTL_TID_MASK;
- if (*qc & IEEE80211_QOS_CONTROL_A_MSDU_PRESENT)
+ if (*qc & IEEE80211_QOS_CTL_A_MSDU_PRESENT)
status->rx_flags |= IEEE80211_RX_AMSDU;
} else {
/*
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index 58ffa7d..e5a6ea4 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -228,6 +228,7 @@
static bool ieee80211_prep_hw_scan(struct ieee80211_local *local)
{
struct cfg80211_scan_request *req = local->scan_req;
+ struct ieee80211_sub_if_data *sdata = local->scan_sdata;
enum ieee80211_band band;
int i, ielen, n_chans;
@@ -251,8 +252,8 @@
local->hw_scan_req->n_channels = n_chans;
ielen = ieee80211_build_preq_ies(local, (u8 *)local->hw_scan_req->ie,
- req->ie, req->ie_len, band, (u32) -1,
- 0);
+ req->ie, req->ie_len, band,
+ sdata->rc_rateidx_mask[band], 0);
local->hw_scan_req->ie_len = ielen;
return true;
@@ -658,7 +659,8 @@
sdata, NULL,
local->scan_req->ssids[i].ssid,
local->scan_req->ssids[i].ssid_len,
- local->scan_req->ie, local->scan_req->ie_len);
+ local->scan_req->ie, local->scan_req->ie_len,
+ false);
/*
* After sending probe requests, wait for probe responses
@@ -821,10 +823,8 @@
*/
void ieee80211_scan_cancel(struct ieee80211_local *local)
{
- bool abortscan;
-
/*
- * We are only canceling software scan, or deferred scan that was not
+ * We are canceling software scan, or deferred scan that was not
* yet really started (see __ieee80211_start_scan ).
*
* Regarding hardware scan:
@@ -836,23 +836,30 @@
* - we can not cancel scan_work since driver can schedule it
* by ieee80211_scan_completed(..., true) to finish scan
*
- * Hence low lever driver is responsible for canceling HW scan.
+ * Hence we only call the cancel_hw_scan() callback, but the low-level
+ * driver is still responsible for calling ieee80211_scan_completed()
+ * after the scan was completed/aborted.
*/
mutex_lock(&local->mtx);
- abortscan = local->scan_req && !test_bit(SCAN_HW_SCANNING, &local->scanning);
- if (abortscan) {
- /*
- * The scan is canceled, but stop work from being pending.
- *
- * If the work is currently running, it must be blocked on
- * the mutex, but we'll set scan_sdata = NULL and it'll
- * simply exit once it acquires the mutex.
- */
- cancel_delayed_work(&local->scan_work);
- /* and clean up */
- __ieee80211_scan_completed(&local->hw, true, false);
+ if (!local->scan_req)
+ goto out;
+
+ if (test_bit(SCAN_HW_SCANNING, &local->scanning)) {
+ if (local->ops->cancel_hw_scan)
+ drv_cancel_hw_scan(local, local->scan_sdata);
+ goto out;
}
+
+ /*
+ * If the work is currently running, it must be blocked on
+ * the mutex, but we'll set scan_sdata = NULL and it'll
+ * simply exit once it acquires the mutex.
+ */
+ cancel_delayed_work(&local->scan_work);
+ /* and clean up */
+ __ieee80211_scan_completed(&local->hw, true, false);
+out:
mutex_unlock(&local->mtx);
}
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index c6ae8718..a06d64e 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -158,6 +158,8 @@
* @work: work struct for starting/stopping aggregation
* @tid_rx_timer_expired: bitmap indicating on which TIDs the
* RX timer expired until the work for it runs
+ * @tid_rx_stop_requested: bitmap indicating which BA sessions per TID the
+ * driver requested to close until the work for it runs
* @mtx: mutex to protect all TX data (except non-NULL assignments
* to tid_tx[idx], which are protected by the sta spinlock)
*/
@@ -166,6 +168,7 @@
/* rx */
struct tid_ampdu_rx __rcu *tid_rx[STA_TID_NUM];
unsigned long tid_rx_timer_expired[BITS_TO_LONGS(STA_TID_NUM)];
+ unsigned long tid_rx_stop_requested[BITS_TO_LONGS(STA_TID_NUM)];
/* tx */
struct work_struct work;
struct tid_ampdu_tx __rcu *tid_tx[STA_TID_NUM];
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index d3fe2d2..652e569 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -1018,7 +1018,8 @@
struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata,
u8 *dst,
const u8 *ssid, size_t ssid_len,
- const u8 *ie, size_t ie_len)
+ const u8 *ie, size_t ie_len,
+ bool directed)
{
struct ieee80211_local *local = sdata->local;
struct sk_buff *skb;
@@ -1035,8 +1036,16 @@
return NULL;
}
- chan = ieee80211_frequency_to_channel(
- local->hw.conf.channel->center_freq);
+ /*
+ * Do not send DS Channel parameter for directed probe requests
+ * in order to maximize the chance that we get a response. Some
+ * badly-behaved APs don't respond when this parameter is included.
+ */
+ if (directed)
+ chan = 0;
+ else
+ chan = ieee80211_frequency_to_channel(
+ local->hw.conf.channel->center_freq);
buf_len = ieee80211_build_preq_ies(local, buf, ie, ie_len,
local->hw.conf.channel->band,
@@ -1062,11 +1071,13 @@
void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst,
const u8 *ssid, size_t ssid_len,
- const u8 *ie, size_t ie_len)
+ const u8 *ie, size_t ie_len,
+ bool directed)
{
struct sk_buff *skb;
- skb = ieee80211_build_probe_req(sdata, dst, ssid, ssid_len, ie, ie_len);
+ skb = ieee80211_build_probe_req(sdata, dst, ssid, ssid_len, ie, ie_len,
+ directed);
if (skb)
ieee80211_tx_skb(sdata, skb);
}
@@ -1276,7 +1287,9 @@
if (ieee80211_sdata_running(sdata))
ieee80211_enable_keys(sdata);
+#ifdef CONFIG_PM
wake_up:
+#endif
ieee80211_wake_queues_by_reason(hw,
IEEE80211_QUEUE_STOP_REASON_SUSPEND);
diff --git a/net/mac80211/wme.c b/net/mac80211/wme.c
index 28bc084..7a49532 100644
--- a/net/mac80211/wme.c
+++ b/net/mac80211/wme.c
@@ -151,8 +151,7 @@
tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK;
if (unlikely(local->wifi_wme_noack_test))
- ack_policy |= QOS_CONTROL_ACK_POLICY_NOACK <<
- QOS_CONTROL_ACK_POLICY_SHIFT;
+ ack_policy |= IEEE80211_QOS_CTL_ACK_POLICY_NOACK;
/* qos header is 2 bytes, second reserved */
*p++ = ack_policy | tid;
*p = 0;
diff --git a/net/mac80211/wme.h b/net/mac80211/wme.h
index 6053b1c..faead6d 100644
--- a/net/mac80211/wme.h
+++ b/net/mac80211/wme.h
@@ -13,11 +13,6 @@
#include <linux/netdevice.h>
#include "ieee80211_i.h"
-#define QOS_CONTROL_ACK_POLICY_NORMAL 0
-#define QOS_CONTROL_ACK_POLICY_NOACK 1
-
-#define QOS_CONTROL_ACK_POLICY_SHIFT 5
-
extern const int ieee802_1d_to_ac[8];
u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata,
diff --git a/net/mac80211/work.c b/net/mac80211/work.c
index d2e7f0e..edf8583 100644
--- a/net/mac80211/work.c
+++ b/net/mac80211/work.c
@@ -450,7 +450,7 @@
* will not answer to direct packet in unassociated state.
*/
ieee80211_send_probe_req(sdata, NULL, wk->probe_auth.ssid,
- wk->probe_auth.ssid_len, NULL, 0);
+ wk->probe_auth.ssid_len, NULL, 0, true);
wk->timeout = jiffies + IEEE80211_AUTH_TIMEOUT;
run_again(local, wk->timeout);
diff --git a/net/netfilter/ipset/Kconfig b/net/netfilter/ipset/Kconfig
index 2c5b348..ba36c28 100644
--- a/net/netfilter/ipset/Kconfig
+++ b/net/netfilter/ipset/Kconfig
@@ -109,6 +109,16 @@
To compile it as a module, choose M here. If unsure, say N.
+config IP_SET_HASH_NETIFACE
+ tristate "hash:net,iface set support"
+ depends on IP_SET
+ help
+ This option adds the hash:net,iface set type support, by which
+ one can store IPv4/IPv6 network address/prefix and
+ interface name pairs as elements in a set.
+
+ To compile it as a module, choose M here. If unsure, say N.
+
config IP_SET_LIST_SET
tristate "list:set set support"
depends on IP_SET
diff --git a/net/netfilter/ipset/Makefile b/net/netfilter/ipset/Makefile
index 5adbdab..6e965ec 100644
--- a/net/netfilter/ipset/Makefile
+++ b/net/netfilter/ipset/Makefile
@@ -19,6 +19,7 @@
obj-$(CONFIG_IP_SET_HASH_IPPORTNET) += ip_set_hash_ipportnet.o
obj-$(CONFIG_IP_SET_HASH_NET) += ip_set_hash_net.o
obj-$(CONFIG_IP_SET_HASH_NETPORT) += ip_set_hash_netport.o
+obj-$(CONFIG_IP_SET_HASH_NETIFACE) += ip_set_hash_netiface.o
# list types
obj-$(CONFIG_IP_SET_LIST_SET) += ip_set_list_set.o
diff --git a/net/netfilter/ipset/ip_set_bitmap_ip.c b/net/netfilter/ipset/ip_set_bitmap_ip.c
index ba2d166..e3e7399 100644
--- a/net/netfilter/ipset/ip_set_bitmap_ip.c
+++ b/net/netfilter/ipset/ip_set_bitmap_ip.c
@@ -54,7 +54,7 @@
}
static int
-bitmap_ip_test(struct ip_set *set, void *value, u32 timeout)
+bitmap_ip_test(struct ip_set *set, void *value, u32 timeout, u32 flags)
{
const struct bitmap_ip *map = set->data;
u16 id = *(u16 *)value;
@@ -63,7 +63,7 @@
}
static int
-bitmap_ip_add(struct ip_set *set, void *value, u32 timeout)
+bitmap_ip_add(struct ip_set *set, void *value, u32 timeout, u32 flags)
{
struct bitmap_ip *map = set->data;
u16 id = *(u16 *)value;
@@ -75,7 +75,7 @@
}
static int
-bitmap_ip_del(struct ip_set *set, void *value, u32 timeout)
+bitmap_ip_del(struct ip_set *set, void *value, u32 timeout, u32 flags)
{
struct bitmap_ip *map = set->data;
u16 id = *(u16 *)value;
@@ -131,7 +131,7 @@
/* Timeout variant */
static int
-bitmap_ip_ttest(struct ip_set *set, void *value, u32 timeout)
+bitmap_ip_ttest(struct ip_set *set, void *value, u32 timeout, u32 flags)
{
const struct bitmap_ip *map = set->data;
const unsigned long *members = map->members;
@@ -141,13 +141,13 @@
}
static int
-bitmap_ip_tadd(struct ip_set *set, void *value, u32 timeout)
+bitmap_ip_tadd(struct ip_set *set, void *value, u32 timeout, u32 flags)
{
struct bitmap_ip *map = set->data;
unsigned long *members = map->members;
u16 id = *(u16 *)value;
- if (ip_set_timeout_test(members[id]))
+ if (ip_set_timeout_test(members[id]) && !(flags & IPSET_FLAG_EXIST))
return -IPSET_ERR_EXIST;
members[id] = ip_set_timeout_set(timeout);
@@ -156,7 +156,7 @@
}
static int
-bitmap_ip_tdel(struct ip_set *set, void *value, u32 timeout)
+bitmap_ip_tdel(struct ip_set *set, void *value, u32 timeout, u32 flags)
{
struct bitmap_ip *map = set->data;
unsigned long *members = map->members;
@@ -219,24 +219,25 @@
static int
bitmap_ip_kadt(struct ip_set *set, const struct sk_buff *skb,
- enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
+ const struct xt_action_param *par,
+ enum ipset_adt adt, const struct ip_set_adt_opt *opt)
{
struct bitmap_ip *map = set->data;
ipset_adtfn adtfn = set->variant->adt[adt];
u32 ip;
- ip = ntohl(ip4addr(skb, flags & IPSET_DIM_ONE_SRC));
+ ip = ntohl(ip4addr(skb, opt->flags & IPSET_DIM_ONE_SRC));
if (ip < map->first_ip || ip > map->last_ip)
return -IPSET_ERR_BITMAP_RANGE;
ip = ip_to_id(map, ip);
- return adtfn(set, &ip, map->timeout);
+ return adtfn(set, &ip, opt_timeout(opt, map), opt->cmdflags);
}
static int
bitmap_ip_uadt(struct ip_set *set, struct nlattr *tb[],
- enum ipset_adt adt, u32 *lineno, u32 flags)
+ enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
{
struct bitmap_ip *map = set->data;
ipset_adtfn adtfn = set->variant->adt[adt];
@@ -266,7 +267,7 @@
if (adt == IPSET_TEST) {
id = ip_to_id(map, ip);
- return adtfn(set, &id, timeout);
+ return adtfn(set, &id, timeout, flags);
}
if (tb[IPSET_ATTR_IP_TO]) {
@@ -283,8 +284,7 @@
if (cidr > 32)
return -IPSET_ERR_INVALID_CIDR;
- ip &= ip_set_hostmask(cidr);
- ip_to = ip | ~ip_set_hostmask(cidr);
+ ip_set_mask_from_to(ip, ip_to, cidr);
} else
ip_to = ip;
@@ -293,7 +293,7 @@
for (; !before(ip_to, ip); ip += map->hosts) {
id = ip_to_id(map, ip);
- ret = adtfn(set, &id, timeout);
+ ret = adtfn(set, &id, timeout, flags);
if (ret && !ip_set_eexist(ret, flags))
return ret;
@@ -478,7 +478,7 @@
if (cidr >= 32)
return -IPSET_ERR_INVALID_CIDR;
- last_ip = first_ip | ~ip_set_hostmask(cidr);
+ ip_set_mask_from_to(first_ip, last_ip, cidr);
} else
return -IPSET_ERR_PROTOCOL;
@@ -551,7 +551,8 @@
.features = IPSET_TYPE_IP,
.dimension = IPSET_DIM_ONE,
.family = AF_INET,
- .revision = 0,
+ .revision_min = 0,
+ .revision_max = 0,
.create = bitmap_ip_create,
.create_policy = {
[IPSET_ATTR_IP] = { .type = NLA_NESTED },
diff --git a/net/netfilter/ipset/ip_set_bitmap_ipmac.c b/net/netfilter/ipset/ip_set_bitmap_ipmac.c
index a274300..56096f5 100644
--- a/net/netfilter/ipset/ip_set_bitmap_ipmac.c
+++ b/net/netfilter/ipset/ip_set_bitmap_ipmac.c
@@ -99,7 +99,7 @@
/* Base variant */
static int
-bitmap_ipmac_test(struct ip_set *set, void *value, u32 timeout)
+bitmap_ipmac_test(struct ip_set *set, void *value, u32 timeout, u32 flags)
{
const struct bitmap_ipmac *map = set->data;
const struct ipmac *data = value;
@@ -117,7 +117,7 @@
}
static int
-bitmap_ipmac_add(struct ip_set *set, void *value, u32 timeout)
+bitmap_ipmac_add(struct ip_set *set, void *value, u32 timeout, u32 flags)
{
struct bitmap_ipmac *map = set->data;
const struct ipmac *data = value;
@@ -146,7 +146,7 @@
}
static int
-bitmap_ipmac_del(struct ip_set *set, void *value, u32 timeout)
+bitmap_ipmac_del(struct ip_set *set, void *value, u32 timeout, u32 flags)
{
struct bitmap_ipmac *map = set->data;
const struct ipmac *data = value;
@@ -212,7 +212,7 @@
/* Timeout variant */
static int
-bitmap_ipmac_ttest(struct ip_set *set, void *value, u32 timeout)
+bitmap_ipmac_ttest(struct ip_set *set, void *value, u32 timeout, u32 flags)
{
const struct bitmap_ipmac *map = set->data;
const struct ipmac *data = value;
@@ -231,15 +231,16 @@
}
static int
-bitmap_ipmac_tadd(struct ip_set *set, void *value, u32 timeout)
+bitmap_ipmac_tadd(struct ip_set *set, void *value, u32 timeout, u32 flags)
{
struct bitmap_ipmac *map = set->data;
const struct ipmac *data = value;
struct ipmac_telem *elem = bitmap_ipmac_elem(map, data->id);
+ bool flag_exist = flags & IPSET_FLAG_EXIST;
switch (elem->match) {
case MAC_UNSET:
- if (!data->ether)
+ if (!(data->ether || flag_exist))
/* Already added without ethernet address */
return -IPSET_ERR_EXIST;
/* Fill the MAC address and activate the timer */
@@ -251,7 +252,7 @@
elem->timeout = ip_set_timeout_set(timeout);
break;
case MAC_FILLED:
- if (!bitmap_expired(map, data->id))
+ if (!(bitmap_expired(map, data->id) || flag_exist))
return -IPSET_ERR_EXIST;
/* Fall through */
case MAC_EMPTY:
@@ -273,7 +274,7 @@
}
static int
-bitmap_ipmac_tdel(struct ip_set *set, void *value, u32 timeout)
+bitmap_ipmac_tdel(struct ip_set *set, void *value, u32 timeout, u32 flags)
{
struct bitmap_ipmac *map = set->data;
const struct ipmac *data = value;
@@ -337,17 +338,18 @@
static int
bitmap_ipmac_kadt(struct ip_set *set, const struct sk_buff *skb,
- enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
+ const struct xt_action_param *par,
+ enum ipset_adt adt, const struct ip_set_adt_opt *opt)
{
struct bitmap_ipmac *map = set->data;
ipset_adtfn adtfn = set->variant->adt[adt];
struct ipmac data;
/* MAC can be src only */
- if (!(flags & IPSET_DIM_TWO_SRC))
+ if (!(opt->flags & IPSET_DIM_TWO_SRC))
return 0;
- data.id = ntohl(ip4addr(skb, flags & IPSET_DIM_ONE_SRC));
+ data.id = ntohl(ip4addr(skb, opt->flags & IPSET_DIM_ONE_SRC));
if (data.id < map->first_ip || data.id > map->last_ip)
return -IPSET_ERR_BITMAP_RANGE;
@@ -359,12 +361,12 @@
data.id -= map->first_ip;
data.ether = eth_hdr(skb)->h_source;
- return adtfn(set, &data, map->timeout);
+ return adtfn(set, &data, opt_timeout(opt, map), opt->cmdflags);
}
static int
bitmap_ipmac_uadt(struct ip_set *set, struct nlattr *tb[],
- enum ipset_adt adt, u32 *lineno, u32 flags)
+ enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
{
const struct bitmap_ipmac *map = set->data;
ipset_adtfn adtfn = set->variant->adt[adt];
@@ -399,7 +401,7 @@
data.id -= map->first_ip;
- ret = adtfn(set, &data, timeout);
+ ret = adtfn(set, &data, timeout, flags);
return ip_set_eexist(ret, flags) ? 0 : ret;
}
@@ -577,7 +579,7 @@
if (cidr >= 32)
return -IPSET_ERR_INVALID_CIDR;
- last_ip = first_ip | ~ip_set_hostmask(cidr);
+ ip_set_mask_from_to(first_ip, last_ip, cidr);
} else
return -IPSET_ERR_PROTOCOL;
@@ -622,7 +624,8 @@
.features = IPSET_TYPE_IP | IPSET_TYPE_MAC,
.dimension = IPSET_DIM_TWO,
.family = AF_INET,
- .revision = 0,
+ .revision_min = 0,
+ .revision_max = 0,
.create = bitmap_ipmac_create,
.create_policy = {
[IPSET_ATTR_IP] = { .type = NLA_NESTED },
@@ -632,7 +635,8 @@
},
.adt_policy = {
[IPSET_ATTR_IP] = { .type = NLA_NESTED },
- [IPSET_ATTR_ETHER] = { .type = NLA_BINARY, .len = ETH_ALEN },
+ [IPSET_ATTR_ETHER] = { .type = NLA_BINARY,
+ .len = ETH_ALEN },
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
[IPSET_ATTR_LINENO] = { .type = NLA_U32 },
},
diff --git a/net/netfilter/ipset/ip_set_bitmap_port.c b/net/netfilter/ipset/ip_set_bitmap_port.c
index 6b38eb8..29ba93b 100644
--- a/net/netfilter/ipset/ip_set_bitmap_port.c
+++ b/net/netfilter/ipset/ip_set_bitmap_port.c
@@ -40,7 +40,7 @@
/* Base variant */
static int
-bitmap_port_test(struct ip_set *set, void *value, u32 timeout)
+bitmap_port_test(struct ip_set *set, void *value, u32 timeout, u32 flags)
{
const struct bitmap_port *map = set->data;
u16 id = *(u16 *)value;
@@ -49,7 +49,7 @@
}
static int
-bitmap_port_add(struct ip_set *set, void *value, u32 timeout)
+bitmap_port_add(struct ip_set *set, void *value, u32 timeout, u32 flags)
{
struct bitmap_port *map = set->data;
u16 id = *(u16 *)value;
@@ -61,7 +61,7 @@
}
static int
-bitmap_port_del(struct ip_set *set, void *value, u32 timeout)
+bitmap_port_del(struct ip_set *set, void *value, u32 timeout, u32 flags)
{
struct bitmap_port *map = set->data;
u16 id = *(u16 *)value;
@@ -119,7 +119,7 @@
/* Timeout variant */
static int
-bitmap_port_ttest(struct ip_set *set, void *value, u32 timeout)
+bitmap_port_ttest(struct ip_set *set, void *value, u32 timeout, u32 flags)
{
const struct bitmap_port *map = set->data;
const unsigned long *members = map->members;
@@ -129,13 +129,13 @@
}
static int
-bitmap_port_tadd(struct ip_set *set, void *value, u32 timeout)
+bitmap_port_tadd(struct ip_set *set, void *value, u32 timeout, u32 flags)
{
struct bitmap_port *map = set->data;
unsigned long *members = map->members;
u16 id = *(u16 *)value;
- if (ip_set_timeout_test(members[id]))
+ if (ip_set_timeout_test(members[id]) && !(flags & IPSET_FLAG_EXIST))
return -IPSET_ERR_EXIST;
members[id] = ip_set_timeout_set(timeout);
@@ -144,7 +144,7 @@
}
static int
-bitmap_port_tdel(struct ip_set *set, void *value, u32 timeout)
+bitmap_port_tdel(struct ip_set *set, void *value, u32 timeout, u32 flags)
{
struct bitmap_port *map = set->data;
unsigned long *members = map->members;
@@ -208,14 +208,16 @@
static int
bitmap_port_kadt(struct ip_set *set, const struct sk_buff *skb,
- enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
+ const struct xt_action_param *par,
+ enum ipset_adt adt, const struct ip_set_adt_opt *opt)
{
struct bitmap_port *map = set->data;
ipset_adtfn adtfn = set->variant->adt[adt];
__be16 __port;
u16 port = 0;
- if (!ip_set_get_ip_port(skb, pf, flags & IPSET_DIM_ONE_SRC, &__port))
+ if (!ip_set_get_ip_port(skb, opt->family,
+ opt->flags & IPSET_DIM_ONE_SRC, &__port))
return -EINVAL;
port = ntohs(__port);
@@ -225,12 +227,12 @@
port -= map->first_port;
- return adtfn(set, &port, map->timeout);
+ return adtfn(set, &port, opt_timeout(opt, map), opt->cmdflags);
}
static int
bitmap_port_uadt(struct ip_set *set, struct nlattr *tb[],
- enum ipset_adt adt, u32 *lineno, u32 flags)
+ enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
{
struct bitmap_port *map = set->data;
ipset_adtfn adtfn = set->variant->adt[adt];
@@ -259,7 +261,7 @@
if (adt == IPSET_TEST) {
id = port - map->first_port;
- return adtfn(set, &id, timeout);
+ return adtfn(set, &id, timeout, flags);
}
if (tb[IPSET_ATTR_PORT_TO]) {
@@ -277,7 +279,7 @@
for (; port <= port_to; port++) {
id = port - map->first_port;
- ret = adtfn(set, &id, timeout);
+ ret = adtfn(set, &id, timeout, flags);
if (ret && !ip_set_eexist(ret, flags))
return ret;
@@ -482,7 +484,8 @@
.features = IPSET_TYPE_PORT,
.dimension = IPSET_DIM_ONE,
.family = AF_UNSPEC,
- .revision = 0,
+ .revision_min = 0,
+ .revision_max = 0,
.create = bitmap_port_create,
.create_policy = {
[IPSET_ATTR_PORT] = { .type = NLA_U16 },
diff --git a/net/netfilter/ipset/ip_set_core.c b/net/netfilter/ipset/ip_set_core.c
index 42aa64b..d7e86ef 100644
--- a/net/netfilter/ipset/ip_set_core.c
+++ b/net/netfilter/ipset/ip_set_core.c
@@ -17,10 +17,10 @@
#include <linux/spinlock.h>
#include <linux/netlink.h>
#include <linux/rculist.h>
-#include <linux/version.h>
#include <net/netlink.h>
#include <linux/netfilter.h>
+#include <linux/netfilter/x_tables.h>
#include <linux/netfilter/nfnetlink.h>
#include <linux/netfilter/ipset/ip_set.h>
@@ -70,7 +70,8 @@
list_for_each_entry_rcu(type, &ip_set_type_list, list)
if (STREQ(type->name, name) &&
(type->family == family || type->family == AF_UNSPEC) &&
- type->revision == revision)
+ revision >= type->revision_min &&
+ revision <= type->revision_max)
return type;
return NULL;
}
@@ -135,10 +136,10 @@
if (STREQ(type->name, name) &&
(type->family == family || type->family == AF_UNSPEC)) {
found = true;
- if (type->revision < *min)
- *min = type->revision;
- if (type->revision > *max)
- *max = type->revision;
+ if (type->revision_min < *min)
+ *min = type->revision_min;
+ if (type->revision_max > *max)
+ *max = type->revision_max;
}
rcu_read_unlock();
if (found)
@@ -159,25 +160,27 @@
int ret = 0;
if (type->protocol != IPSET_PROTOCOL) {
- pr_warning("ip_set type %s, family %s, revision %u uses "
+ pr_warning("ip_set type %s, family %s, revision %u:%u uses "
"wrong protocol version %u (want %u)\n",
type->name, family_name(type->family),
- type->revision, type->protocol, IPSET_PROTOCOL);
+ type->revision_min, type->revision_max,
+ type->protocol, IPSET_PROTOCOL);
return -EINVAL;
}
ip_set_type_lock();
- if (find_set_type(type->name, type->family, type->revision)) {
+ if (find_set_type(type->name, type->family, type->revision_min)) {
/* Duplicate! */
- pr_warning("ip_set type %s, family %s, revision %u "
+ pr_warning("ip_set type %s, family %s with revision min %u "
"already registered!\n", type->name,
- family_name(type->family), type->revision);
+ family_name(type->family), type->revision_min);
ret = -EINVAL;
goto unlock;
}
list_add_rcu(&type->list, &ip_set_type_list);
- pr_debug("type %s, family %s, revision %u registered.\n",
- type->name, family_name(type->family), type->revision);
+ pr_debug("type %s, family %s, revision %u:%u registered.\n",
+ type->name, family_name(type->family),
+ type->revision_min, type->revision_max);
unlock:
ip_set_type_unlock();
return ret;
@@ -189,15 +192,15 @@
ip_set_type_unregister(struct ip_set_type *type)
{
ip_set_type_lock();
- if (!find_set_type(type->name, type->family, type->revision)) {
- pr_warning("ip_set type %s, family %s, revision %u "
+ if (!find_set_type(type->name, type->family, type->revision_min)) {
+ pr_warning("ip_set type %s, family %s with revision min %u "
"not registered\n", type->name,
- family_name(type->family), type->revision);
+ family_name(type->family), type->revision_min);
goto unlock;
}
list_del_rcu(&type->list);
- pr_debug("type %s, family %s, revision %u unregistered.\n",
- type->name, family_name(type->family), type->revision);
+ pr_debug("type %s, family %s with revision min %u unregistered.\n",
+ type->name, family_name(type->family), type->revision_min);
unlock:
ip_set_type_unlock();
@@ -325,7 +328,8 @@
int
ip_set_test(ip_set_id_t index, const struct sk_buff *skb,
- u8 family, u8 dim, u8 flags)
+ const struct xt_action_param *par,
+ const struct ip_set_adt_opt *opt)
{
struct ip_set *set = ip_set_list[index];
int ret = 0;
@@ -333,19 +337,19 @@
BUG_ON(set == NULL);
pr_debug("set %s, index %u\n", set->name, index);
- if (dim < set->type->dimension ||
- !(family == set->family || set->family == AF_UNSPEC))
+ if (opt->dim < set->type->dimension ||
+ !(opt->family == set->family || set->family == AF_UNSPEC))
return 0;
read_lock_bh(&set->lock);
- ret = set->variant->kadt(set, skb, IPSET_TEST, family, dim, flags);
+ ret = set->variant->kadt(set, skb, par, IPSET_TEST, opt);
read_unlock_bh(&set->lock);
if (ret == -EAGAIN) {
/* Type requests element to be completed */
pr_debug("element must be competed, ADD is triggered\n");
write_lock_bh(&set->lock);
- set->variant->kadt(set, skb, IPSET_ADD, family, dim, flags);
+ set->variant->kadt(set, skb, par, IPSET_ADD, opt);
write_unlock_bh(&set->lock);
ret = 1;
}
@@ -357,7 +361,8 @@
int
ip_set_add(ip_set_id_t index, const struct sk_buff *skb,
- u8 family, u8 dim, u8 flags)
+ const struct xt_action_param *par,
+ const struct ip_set_adt_opt *opt)
{
struct ip_set *set = ip_set_list[index];
int ret;
@@ -365,12 +370,12 @@
BUG_ON(set == NULL);
pr_debug("set %s, index %u\n", set->name, index);
- if (dim < set->type->dimension ||
- !(family == set->family || set->family == AF_UNSPEC))
+ if (opt->dim < set->type->dimension ||
+ !(opt->family == set->family || set->family == AF_UNSPEC))
return 0;
write_lock_bh(&set->lock);
- ret = set->variant->kadt(set, skb, IPSET_ADD, family, dim, flags);
+ ret = set->variant->kadt(set, skb, par, IPSET_ADD, opt);
write_unlock_bh(&set->lock);
return ret;
@@ -379,7 +384,8 @@
int
ip_set_del(ip_set_id_t index, const struct sk_buff *skb,
- u8 family, u8 dim, u8 flags)
+ const struct xt_action_param *par,
+ const struct ip_set_adt_opt *opt)
{
struct ip_set *set = ip_set_list[index];
int ret = 0;
@@ -387,12 +393,12 @@
BUG_ON(set == NULL);
pr_debug("set %s, index %u\n", set->name, index);
- if (dim < set->type->dimension ||
- !(family == set->family || set->family == AF_UNSPEC))
+ if (opt->dim < set->type->dimension ||
+ !(opt->family == set->family || set->family == AF_UNSPEC))
return 0;
write_lock_bh(&set->lock);
- ret = set->variant->kadt(set, skb, IPSET_DEL, family, dim, flags);
+ ret = set->variant->kadt(set, skb, par, IPSET_DEL, opt);
write_unlock_bh(&set->lock);
return ret;
@@ -656,6 +662,7 @@
rwlock_init(&set->lock);
strlcpy(set->name, name, IPSET_MAXNAMELEN);
set->family = family;
+ set->revision = revision;
/*
* Next, check that we know the type, and take
@@ -675,8 +682,8 @@
if (attr[IPSET_ATTR_DATA] &&
nla_parse_nested(tb, IPSET_ATTR_CREATE_MAX, attr[IPSET_ATTR_DATA],
set->type->create_policy)) {
- ret = -IPSET_ERR_PROTOCOL;
- goto put_out;
+ ret = -IPSET_ERR_PROTOCOL;
+ goto put_out;
}
ret = set->type->create(set, tb, flags);
@@ -696,7 +703,8 @@
(flags & IPSET_FLAG_EXIST) &&
STREQ(set->type->name, clash->type->name) &&
set->type->family == clash->type->family &&
- set->type->revision == clash->type->revision &&
+ set->type->revision_min == clash->type->revision_min &&
+ set->type->revision_max == clash->type->revision_max &&
set->variant->same_set(set, clash))
ret = 0;
goto cleanup;
@@ -939,10 +947,13 @@
/* List/save set data */
-#define DUMP_INIT 0L
-#define DUMP_ALL 1L
-#define DUMP_ONE 2L
-#define DUMP_LAST 3L
+#define DUMP_INIT 0
+#define DUMP_ALL 1
+#define DUMP_ONE 2
+#define DUMP_LAST 3
+
+#define DUMP_TYPE(arg) (((u32)(arg)) & 0x0000FFFF)
+#define DUMP_FLAGS(arg) (((u32)(arg)) >> 16)
static int
ip_set_dump_done(struct netlink_callback *cb)
@@ -973,6 +984,7 @@
int min_len = NLMSG_SPACE(sizeof(struct nfgenmsg));
struct nlattr *cda[IPSET_ATTR_CMD_MAX+1];
struct nlattr *attr = (void *)nlh + min_len;
+ u32 dump_type;
ip_set_id_t index;
/* Second pass, so parser can't fail */
@@ -984,17 +996,22 @@
* [..]: type specific
*/
- if (!cda[IPSET_ATTR_SETNAME]) {
- cb->args[0] = DUMP_ALL;
- return 0;
+ if (cda[IPSET_ATTR_SETNAME]) {
+ index = find_set_id(nla_data(cda[IPSET_ATTR_SETNAME]));
+ if (index == IPSET_INVALID_ID)
+ return -ENOENT;
+
+ dump_type = DUMP_ONE;
+ cb->args[1] = index;
+ } else
+ dump_type = DUMP_ALL;
+
+ if (cda[IPSET_ATTR_FLAGS]) {
+ u32 f = ip_set_get_h32(cda[IPSET_ATTR_FLAGS]);
+ dump_type |= (f << 16);
}
+ cb->args[0] = dump_type;
- index = find_set_id(nla_data(cda[IPSET_ATTR_SETNAME]));
- if (index == IPSET_INVALID_ID)
- return -ENOENT;
-
- cb->args[0] = DUMP_ONE;
- cb->args[1] = index;
return 0;
}
@@ -1005,9 +1022,10 @@
struct ip_set *set = NULL;
struct nlmsghdr *nlh = NULL;
unsigned int flags = NETLINK_CB(cb->skb).pid ? NLM_F_MULTI : 0;
+ u32 dump_type, dump_flags;
int ret = 0;
- if (cb->args[0] == DUMP_INIT) {
+ if (!cb->args[0]) {
ret = dump_init(cb);
if (ret < 0) {
nlh = nlmsg_hdr(cb->skb);
@@ -1022,14 +1040,17 @@
if (cb->args[1] >= ip_set_max)
goto out;
- max = cb->args[0] == DUMP_ONE ? cb->args[1] + 1 : ip_set_max;
+ dump_type = DUMP_TYPE(cb->args[0]);
+ dump_flags = DUMP_FLAGS(cb->args[0]);
+ max = dump_type == DUMP_ONE ? cb->args[1] + 1 : ip_set_max;
dump_last:
- pr_debug("args[0]: %ld args[1]: %ld\n", cb->args[0], cb->args[1]);
+ pr_debug("args[0]: %u %u args[1]: %ld\n",
+ dump_type, dump_flags, cb->args[1]);
for (; cb->args[1] < max; cb->args[1]++) {
index = (ip_set_id_t) cb->args[1];
set = ip_set_list[index];
if (set == NULL) {
- if (cb->args[0] == DUMP_ONE) {
+ if (dump_type == DUMP_ONE) {
ret = -ENOENT;
goto out;
}
@@ -1038,8 +1059,8 @@
/* When dumping all sets, we must dump "sorted"
* so that lists (unions of sets) are dumped last.
*/
- if (cb->args[0] != DUMP_ONE &&
- ((cb->args[0] == DUMP_ALL) ==
+ if (dump_type != DUMP_ONE &&
+ ((dump_type == DUMP_ALL) ==
!!(set->type->features & IPSET_DUMP_LAST)))
continue;
pr_debug("List set: %s\n", set->name);
@@ -1057,6 +1078,8 @@
}
NLA_PUT_U8(skb, IPSET_ATTR_PROTOCOL, IPSET_PROTOCOL);
NLA_PUT_STRING(skb, IPSET_ATTR_SETNAME, set->name);
+ if (dump_flags & IPSET_FLAG_LIST_SETNAME)
+ goto next_set;
switch (cb->args[2]) {
case 0:
/* Core header data */
@@ -1065,28 +1088,27 @@
NLA_PUT_U8(skb, IPSET_ATTR_FAMILY,
set->family);
NLA_PUT_U8(skb, IPSET_ATTR_REVISION,
- set->type->revision);
+ set->revision);
ret = set->variant->head(set, skb);
if (ret < 0)
goto release_refcount;
+ if (dump_flags & IPSET_FLAG_LIST_HEADER)
+ goto next_set;
/* Fall through and add elements */
default:
read_lock_bh(&set->lock);
ret = set->variant->list(set, skb, cb);
read_unlock_bh(&set->lock);
- if (!cb->args[2]) {
+ if (!cb->args[2])
/* Set is done, proceed with next one */
- if (cb->args[0] == DUMP_ONE)
- cb->args[1] = IPSET_INVALID_ID;
- else
- cb->args[1]++;
- }
+ goto next_set;
goto release_refcount;
}
}
/* If we dump all sets, continue with dumping last ones */
- if (cb->args[0] == DUMP_ALL) {
- cb->args[0] = DUMP_LAST;
+ if (dump_type == DUMP_ALL) {
+ dump_type = DUMP_LAST;
+ cb->args[0] = dump_type | (dump_flags << 16);
cb->args[1] = 0;
goto dump_last;
}
@@ -1094,6 +1116,11 @@
nla_put_failure:
ret = -EFAULT;
+next_set:
+ if (dump_type == DUMP_ONE)
+ cb->args[1] = IPSET_INVALID_ID;
+ else
+ cb->args[1]++;
release_refcount:
/* If there was an error or set is done, release set */
if (ret || !cb->args[2]) {
@@ -1120,7 +1147,7 @@
return netlink_dump_start(ctnl, skb, nlh,
ip_set_dump_start,
- ip_set_dump_done);
+ ip_set_dump_done, 0);
}
/* Add, del and test */
@@ -1139,17 +1166,18 @@
struct nlattr *tb[], enum ipset_adt adt,
u32 flags, bool use_lineno)
{
- int ret, retried = 0;
+ int ret;
u32 lineno = 0;
- bool eexist = flags & IPSET_FLAG_EXIST;
+ bool eexist = flags & IPSET_FLAG_EXIST, retried = false;
do {
write_lock_bh(&set->lock);
- ret = set->variant->uadt(set, tb, adt, &lineno, flags);
+ ret = set->variant->uadt(set, tb, adt, &lineno, flags, retried);
write_unlock_bh(&set->lock);
+ retried = true;
} while (ret == -EAGAIN &&
set->variant->resize &&
- (ret = set->variant->resize(set, retried++)) == 0);
+ (ret = set->variant->resize(set, retried)) == 0);
if (!ret || (ret == -IPSET_ERR_EXIST && eexist))
return 0;
@@ -1322,7 +1350,7 @@
return -IPSET_ERR_PROTOCOL;
read_lock_bh(&set->lock);
- ret = set->variant->uadt(set, tb, IPSET_TEST, NULL, 0);
+ ret = set->variant->uadt(set, tb, IPSET_TEST, NULL, 0, 0);
read_unlock_bh(&set->lock);
/* Userspace can't trigger element to be re-added */
if (ret == -EAGAIN)
@@ -1365,7 +1393,7 @@
NLA_PUT_STRING(skb2, IPSET_ATTR_SETNAME, set->name);
NLA_PUT_STRING(skb2, IPSET_ATTR_TYPENAME, set->type->name);
NLA_PUT_U8(skb2, IPSET_ATTR_FAMILY, set->family);
- NLA_PUT_U8(skb2, IPSET_ATTR_REVISION, set->type->revision);
+ NLA_PUT_U8(skb2, IPSET_ATTR_REVISION, set->revision);
nlmsg_end(skb2, nlh2);
ret = netlink_unicast(ctnl, skb2, NETLINK_CB(skb).pid, MSG_DONTWAIT);
diff --git a/net/netfilter/ipset/ip_set_hash_ip.c b/net/netfilter/ipset/ip_set_hash_ip.c
index 43bcce2..fa80bb9 100644
--- a/net/netfilter/ipset/ip_set_hash_ip.c
+++ b/net/netfilter/ipset/ip_set_hash_ip.c
@@ -108,25 +108,32 @@
#define HOST_MASK 32
#include <linux/netfilter/ipset/ip_set_ahash.h>
+static inline void
+hash_ip4_data_next(struct ip_set_hash *h, const struct hash_ip4_elem *d)
+{
+ h->next.ip = ntohl(d->ip);
+}
+
static int
hash_ip4_kadt(struct ip_set *set, const struct sk_buff *skb,
- enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
+ const struct xt_action_param *par,
+ enum ipset_adt adt, const struct ip_set_adt_opt *opt)
{
const struct ip_set_hash *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt];
__be32 ip;
- ip4addrptr(skb, flags & IPSET_DIM_ONE_SRC, &ip);
+ ip4addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &ip);
ip &= ip_set_netmask(h->netmask);
if (ip == 0)
return -EINVAL;
- return adtfn(set, &ip, h->timeout);
+ return adtfn(set, &ip, opt_timeout(opt, h), opt->cmdflags);
}
static int
hash_ip4_uadt(struct ip_set *set, struct nlattr *tb[],
- enum ipset_adt adt, u32 *lineno, u32 flags)
+ enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
{
const struct ip_set_hash *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt];
@@ -157,7 +164,7 @@
nip = htonl(ip);
if (nip == 0)
return -IPSET_ERR_HASH_ELEM;
- return adtfn(set, &nip, timeout);
+ return adtfn(set, &nip, timeout, flags);
}
if (tb[IPSET_ATTR_IP_TO]) {
@@ -171,18 +178,19 @@
if (cidr > 32)
return -IPSET_ERR_INVALID_CIDR;
- ip &= ip_set_hostmask(cidr);
- ip_to = ip | ~ip_set_hostmask(cidr);
+ ip_set_mask_from_to(ip, ip_to, cidr);
} else
ip_to = ip;
hosts = h->netmask == 32 ? 1 : 2 << (32 - h->netmask - 1);
+ if (retried)
+ ip = h->next.ip;
for (; !before(ip_to, ip); ip += hosts) {
nip = htonl(ip);
if (nip == 0)
return -IPSET_ERR_HASH_ELEM;
- ret = adtfn(set, &nip, timeout);
+ ret = adtfn(set, &nip, timeout, flags);
if (ret && !ip_set_eexist(ret, flags))
return ret;
@@ -281,20 +289,26 @@
#define HOST_MASK 128
#include <linux/netfilter/ipset/ip_set_ahash.h>
+static inline void
+hash_ip6_data_next(struct ip_set_hash *h, const struct hash_ip6_elem *d)
+{
+}
+
static int
hash_ip6_kadt(struct ip_set *set, const struct sk_buff *skb,
- enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
+ const struct xt_action_param *par,
+ enum ipset_adt adt, const struct ip_set_adt_opt *opt)
{
const struct ip_set_hash *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt];
union nf_inet_addr ip;
- ip6addrptr(skb, flags & IPSET_DIM_ONE_SRC, &ip.in6);
+ ip6addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &ip.in6);
ip6_netmask(&ip, h->netmask);
if (ipv6_addr_any(&ip.in6))
return -EINVAL;
- return adtfn(set, &ip, h->timeout);
+ return adtfn(set, &ip, opt_timeout(opt, h), opt->cmdflags);
}
static const struct nla_policy hash_ip6_adt_policy[IPSET_ATTR_ADT_MAX + 1] = {
@@ -305,7 +319,7 @@
static int
hash_ip6_uadt(struct ip_set *set, struct nlattr *tb[],
- enum ipset_adt adt, u32 *lineno, u32 flags)
+ enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
{
const struct ip_set_hash *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt];
@@ -336,7 +350,7 @@
timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
}
- ret = adtfn(set, &ip, timeout);
+ ret = adtfn(set, &ip, timeout, flags);
return ip_set_eexist(ret, flags) ? 0 : ret;
}
@@ -428,7 +442,8 @@
.features = IPSET_TYPE_IP,
.dimension = IPSET_DIM_ONE,
.family = AF_UNSPEC,
- .revision = 0,
+ .revision_min = 0,
+ .revision_max = 0,
.create = hash_ip_create,
.create_policy = {
[IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 },
diff --git a/net/netfilter/ipset/ip_set_hash_ipport.c b/net/netfilter/ipset/ip_set_hash_ipport.c
index 14281b6..bbf51b6 100644
--- a/net/netfilter/ipset/ip_set_hash_ipport.c
+++ b/net/netfilter/ipset/ip_set_hash_ipport.c
@@ -124,31 +124,40 @@
#define HOST_MASK 32
#include <linux/netfilter/ipset/ip_set_ahash.h>
+static inline void
+hash_ipport4_data_next(struct ip_set_hash *h,
+ const struct hash_ipport4_elem *d)
+{
+ h->next.ip = ntohl(d->ip);
+ h->next.port = ntohs(d->port);
+}
+
static int
hash_ipport4_kadt(struct ip_set *set, const struct sk_buff *skb,
- enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
+ const struct xt_action_param *par,
+ enum ipset_adt adt, const struct ip_set_adt_opt *opt)
{
const struct ip_set_hash *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt];
struct hash_ipport4_elem data = { };
- if (!ip_set_get_ip4_port(skb, flags & IPSET_DIM_TWO_SRC,
+ if (!ip_set_get_ip4_port(skb, opt->flags & IPSET_DIM_TWO_SRC,
&data.port, &data.proto))
return -EINVAL;
- ip4addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip);
+ ip4addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &data.ip);
- return adtfn(set, &data, h->timeout);
+ return adtfn(set, &data, opt_timeout(opt, h), opt->cmdflags);
}
static int
hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[],
- enum ipset_adt adt, u32 *lineno, u32 flags)
+ enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
{
const struct ip_set_hash *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt];
struct hash_ipport4_elem data = { };
- u32 ip, ip_to, p, port, port_to;
+ u32 ip, ip_to, p = 0, port, port_to;
u32 timeout = h->timeout;
bool with_ports = false;
int ret;
@@ -192,7 +201,7 @@
if (adt == IPSET_TEST ||
!(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR] ||
tb[IPSET_ATTR_PORT_TO])) {
- ret = adtfn(set, &data, timeout);
+ ret = adtfn(set, &data, timeout, flags);
return ip_set_eexist(ret, flags) ? 0 : ret;
}
@@ -208,8 +217,7 @@
if (cidr > 32)
return -IPSET_ERR_INVALID_CIDR;
- ip &= ip_set_hostmask(cidr);
- ip_to = ip | ~ip_set_hostmask(cidr);
+ ip_set_mask_from_to(ip, ip_to, cidr);
} else
ip_to = ip;
@@ -220,17 +228,21 @@
swap(port, port_to);
}
- for (; !before(ip_to, ip); ip++)
- for (p = port; p <= port_to; p++) {
+ if (retried)
+ ip = h->next.ip;
+ for (; !before(ip_to, ip); ip++) {
+ p = retried && ip == h->next.ip ? h->next.port : port;
+ for (; p <= port_to; p++) {
data.ip = htonl(ip);
data.port = htons(p);
- ret = adtfn(set, &data, timeout);
+ ret = adtfn(set, &data, timeout, flags);
if (ret && !ip_set_eexist(ret, flags))
return ret;
else
ret = 0;
}
+ }
return ret;
}
@@ -328,26 +340,34 @@
#define HOST_MASK 128
#include <linux/netfilter/ipset/ip_set_ahash.h>
+static inline void
+hash_ipport6_data_next(struct ip_set_hash *h,
+ const struct hash_ipport6_elem *d)
+{
+ h->next.port = ntohs(d->port);
+}
+
static int
hash_ipport6_kadt(struct ip_set *set, const struct sk_buff *skb,
- enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
+ const struct xt_action_param *par,
+ enum ipset_adt adt, const struct ip_set_adt_opt *opt)
{
const struct ip_set_hash *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt];
struct hash_ipport6_elem data = { };
- if (!ip_set_get_ip6_port(skb, flags & IPSET_DIM_TWO_SRC,
+ if (!ip_set_get_ip6_port(skb, opt->flags & IPSET_DIM_TWO_SRC,
&data.port, &data.proto))
return -EINVAL;
- ip6addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip.in6);
+ ip6addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &data.ip.in6);
- return adtfn(set, &data, h->timeout);
+ return adtfn(set, &data, opt_timeout(opt, h), opt->cmdflags);
}
static int
hash_ipport6_uadt(struct ip_set *set, struct nlattr *tb[],
- enum ipset_adt adt, u32 *lineno, u32 flags)
+ enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
{
const struct ip_set_hash *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt];
@@ -396,7 +416,7 @@
}
if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) {
- ret = adtfn(set, &data, timeout);
+ ret = adtfn(set, &data, timeout, flags);
return ip_set_eexist(ret, flags) ? 0 : ret;
}
@@ -405,9 +425,11 @@
if (port > port_to)
swap(port, port_to);
+ if (retried)
+ port = h->next.port;
for (; port <= port_to; port++) {
data.port = htons(port);
- ret = adtfn(set, &data, timeout);
+ ret = adtfn(set, &data, timeout, flags);
if (ret && !ip_set_eexist(ret, flags))
return ret;
@@ -491,7 +513,8 @@
.features = IPSET_TYPE_IP | IPSET_TYPE_PORT,
.dimension = IPSET_DIM_TWO,
.family = AF_UNSPEC,
- .revision = 1,
+ .revision_min = 0,
+ .revision_max = 1, /* SCTP and UDPLITE support added */
.create = hash_ipport_create,
.create_policy = {
[IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 },
diff --git a/net/netfilter/ipset/ip_set_hash_ipportip.c b/net/netfilter/ipset/ip_set_hash_ipportip.c
index 401c8a2..96525f5 100644
--- a/net/netfilter/ipset/ip_set_hash_ipportip.c
+++ b/net/netfilter/ipset/ip_set_hash_ipportip.c
@@ -127,32 +127,41 @@
#define HOST_MASK 32
#include <linux/netfilter/ipset/ip_set_ahash.h>
+static inline void
+hash_ipportip4_data_next(struct ip_set_hash *h,
+ const struct hash_ipportip4_elem *d)
+{
+ h->next.ip = ntohl(d->ip);
+ h->next.port = ntohs(d->port);
+}
+
static int
hash_ipportip4_kadt(struct ip_set *set, const struct sk_buff *skb,
- enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
+ const struct xt_action_param *par,
+ enum ipset_adt adt, const struct ip_set_adt_opt *opt)
{
const struct ip_set_hash *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt];
struct hash_ipportip4_elem data = { };
- if (!ip_set_get_ip4_port(skb, flags & IPSET_DIM_TWO_SRC,
+ if (!ip_set_get_ip4_port(skb, opt->flags & IPSET_DIM_TWO_SRC,
&data.port, &data.proto))
return -EINVAL;
- ip4addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip);
- ip4addrptr(skb, flags & IPSET_DIM_THREE_SRC, &data.ip2);
+ ip4addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &data.ip);
+ ip4addrptr(skb, opt->flags & IPSET_DIM_THREE_SRC, &data.ip2);
- return adtfn(set, &data, h->timeout);
+ return adtfn(set, &data, opt_timeout(opt, h), opt->cmdflags);
}
static int
hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[],
- enum ipset_adt adt, u32 *lineno, u32 flags)
+ enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
{
const struct ip_set_hash *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt];
struct hash_ipportip4_elem data = { };
- u32 ip, ip_to, p, port, port_to;
+ u32 ip, ip_to, p = 0, port, port_to;
u32 timeout = h->timeout;
bool with_ports = false;
int ret;
@@ -200,7 +209,7 @@
if (adt == IPSET_TEST ||
!(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR] ||
tb[IPSET_ATTR_PORT_TO])) {
- ret = adtfn(set, &data, timeout);
+ ret = adtfn(set, &data, timeout, flags);
return ip_set_eexist(ret, flags) ? 0 : ret;
}
@@ -216,8 +225,7 @@
if (cidr > 32)
return -IPSET_ERR_INVALID_CIDR;
- ip &= ip_set_hostmask(cidr);
- ip_to = ip | ~ip_set_hostmask(cidr);
+ ip_set_mask_from_to(ip, ip_to, cidr);
} else
ip_to = ip;
@@ -228,17 +236,21 @@
swap(port, port_to);
}
- for (; !before(ip_to, ip); ip++)
- for (p = port; p <= port_to; p++) {
+ if (retried)
+ ip = h->next.ip;
+ for (; !before(ip_to, ip); ip++) {
+ p = retried && ip == h->next.ip ? h->next.port : port;
+ for (; p <= port_to; p++) {
data.ip = htonl(ip);
data.port = htons(p);
- ret = adtfn(set, &data, timeout);
+ ret = adtfn(set, &data, timeout, flags);
if (ret && !ip_set_eexist(ret, flags))
return ret;
else
ret = 0;
}
+ }
return ret;
}
@@ -341,27 +353,35 @@
#define HOST_MASK 128
#include <linux/netfilter/ipset/ip_set_ahash.h>
+static inline void
+hash_ipportip6_data_next(struct ip_set_hash *h,
+ const struct hash_ipportip6_elem *d)
+{
+ h->next.port = ntohs(d->port);
+}
+
static int
hash_ipportip6_kadt(struct ip_set *set, const struct sk_buff *skb,
- enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
+ const struct xt_action_param *par,
+ enum ipset_adt adt, const struct ip_set_adt_opt *opt)
{
const struct ip_set_hash *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt];
struct hash_ipportip6_elem data = { };
- if (!ip_set_get_ip6_port(skb, flags & IPSET_DIM_TWO_SRC,
+ if (!ip_set_get_ip6_port(skb, opt->flags & IPSET_DIM_TWO_SRC,
&data.port, &data.proto))
return -EINVAL;
- ip6addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip.in6);
- ip6addrptr(skb, flags & IPSET_DIM_THREE_SRC, &data.ip2.in6);
+ ip6addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &data.ip.in6);
+ ip6addrptr(skb, opt->flags & IPSET_DIM_THREE_SRC, &data.ip2.in6);
- return adtfn(set, &data, h->timeout);
+ return adtfn(set, &data, opt_timeout(opt, h), opt->cmdflags);
}
static int
hash_ipportip6_uadt(struct ip_set *set, struct nlattr *tb[],
- enum ipset_adt adt, u32 *lineno, u32 flags)
+ enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
{
const struct ip_set_hash *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt];
@@ -414,7 +434,7 @@
}
if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) {
- ret = adtfn(set, &data, timeout);
+ ret = adtfn(set, &data, timeout, flags);
return ip_set_eexist(ret, flags) ? 0 : ret;
}
@@ -423,9 +443,11 @@
if (port > port_to)
swap(port, port_to);
+ if (retried)
+ port = h->next.port;
for (; port <= port_to; port++) {
data.port = htons(port);
- ret = adtfn(set, &data, timeout);
+ ret = adtfn(set, &data, timeout, flags);
if (ret && !ip_set_eexist(ret, flags))
return ret;
@@ -509,7 +531,8 @@
.features = IPSET_TYPE_IP | IPSET_TYPE_PORT | IPSET_TYPE_IP2,
.dimension = IPSET_DIM_THREE,
.family = AF_UNSPEC,
- .revision = 1,
+ .revision_min = 0,
+ .revision_max = 1, /* SCTP and UDPLITE support added */
.create = hash_ipportip_create,
.create_policy = {
[IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 },
diff --git a/net/netfilter/ipset/ip_set_hash_ipportnet.c b/net/netfilter/ipset/ip_set_hash_ipportnet.c
index 565a7c5..d2d6ab8 100644
--- a/net/netfilter/ipset/ip_set_hash_ipportnet.c
+++ b/net/netfilter/ipset/ip_set_hash_ipportnet.c
@@ -140,9 +140,19 @@
#define HOST_MASK 32
#include <linux/netfilter/ipset/ip_set_ahash.h>
+static inline void
+hash_ipportnet4_data_next(struct ip_set_hash *h,
+ const struct hash_ipportnet4_elem *d)
+{
+ h->next.ip = ntohl(d->ip);
+ h->next.port = ntohs(d->port);
+ h->next.ip2 = ntohl(d->ip2);
+}
+
static int
hash_ipportnet4_kadt(struct ip_set *set, const struct sk_buff *skb,
- enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
+ const struct xt_action_param *par,
+ enum ipset_adt adt, const struct ip_set_adt_opt *opt)
{
const struct ip_set_hash *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt];
@@ -155,25 +165,26 @@
if (adt == IPSET_TEST)
data.cidr = HOST_MASK;
- if (!ip_set_get_ip4_port(skb, flags & IPSET_DIM_TWO_SRC,
+ if (!ip_set_get_ip4_port(skb, opt->flags & IPSET_DIM_TWO_SRC,
&data.port, &data.proto))
return -EINVAL;
- ip4addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip);
- ip4addrptr(skb, flags & IPSET_DIM_THREE_SRC, &data.ip2);
+ ip4addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &data.ip);
+ ip4addrptr(skb, opt->flags & IPSET_DIM_THREE_SRC, &data.ip2);
data.ip2 &= ip_set_netmask(data.cidr);
- return adtfn(set, &data, h->timeout);
+ return adtfn(set, &data, opt_timeout(opt, h), opt->cmdflags);
}
static int
hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
- enum ipset_adt adt, u32 *lineno, u32 flags)
+ enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
{
const struct ip_set_hash *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt];
struct hash_ipportnet4_elem data = { .cidr = HOST_MASK };
- u32 ip, ip_to, p, port, port_to;
+ u32 ip, ip_to, p = 0, port, port_to;
+ u32 ip2_from = 0, ip2_to, ip2_last, ip2;
u32 timeout = h->timeout;
bool with_ports = false;
int ret;
@@ -187,21 +198,19 @@
if (tb[IPSET_ATTR_LINENO])
*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
- ret = ip_set_get_ipaddr4(tb[IPSET_ATTR_IP], &data.ip);
+ ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &ip);
if (ret)
return ret;
- ret = ip_set_get_ipaddr4(tb[IPSET_ATTR_IP2], &data.ip2);
+ ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP2], &ip2_from);
if (ret)
return ret;
- if (tb[IPSET_ATTR_CIDR2])
+ if (tb[IPSET_ATTR_CIDR2]) {
data.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR2]);
-
- if (!data.cidr)
- return -IPSET_ERR_INVALID_CIDR;
-
- data.ip2 &= ip_set_netmask(data.cidr);
+ if (!data.cidr)
+ return -IPSET_ERR_INVALID_CIDR;
+ }
if (tb[IPSET_ATTR_PORT])
data.port = nla_get_be16(tb[IPSET_ATTR_PORT]);
@@ -226,14 +235,16 @@
timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
}
+ with_ports = with_ports && tb[IPSET_ATTR_PORT_TO];
if (adt == IPSET_TEST ||
- !(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR] ||
- tb[IPSET_ATTR_PORT_TO])) {
- ret = adtfn(set, &data, timeout);
+ !(tb[IPSET_ATTR_CIDR] || tb[IPSET_ATTR_IP_TO] || with_ports ||
+ tb[IPSET_ATTR_IP2_TO])) {
+ data.ip = htonl(ip);
+ data.ip2 = htonl(ip2_from & ip_set_hostmask(data.cidr));
+ ret = adtfn(set, &data, timeout, flags);
return ip_set_eexist(ret, flags) ? 0 : ret;
}
- ip = ntohl(data.ip);
if (tb[IPSET_ATTR_IP_TO]) {
ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
if (ret)
@@ -245,29 +256,50 @@
if (cidr > 32)
return -IPSET_ERR_INVALID_CIDR;
- ip &= ip_set_hostmask(cidr);
- ip_to = ip | ~ip_set_hostmask(cidr);
- } else
- ip_to = ip;
+ ip_set_mask_from_to(ip, ip_to, cidr);
+ }
port_to = port = ntohs(data.port);
- if (with_ports && tb[IPSET_ATTR_PORT_TO]) {
+ if (tb[IPSET_ATTR_PORT_TO]) {
port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
if (port > port_to)
swap(port, port_to);
}
+ if (tb[IPSET_ATTR_IP2_TO]) {
+ ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP2_TO], &ip2_to);
+ if (ret)
+ return ret;
+ if (ip2_from > ip2_to)
+ swap(ip2_from, ip2_to);
+ if (ip2_from + UINT_MAX == ip2_to)
+ return -IPSET_ERR_HASH_RANGE;
+ } else {
+ ip_set_mask_from_to(ip2_from, ip2_to, data.cidr);
+ }
- for (; !before(ip_to, ip); ip++)
- for (p = port; p <= port_to; p++) {
- data.ip = htonl(ip);
+ if (retried)
+ ip = h->next.ip;
+ for (; !before(ip_to, ip); ip++) {
+ data.ip = htonl(ip);
+ p = retried && ip == h->next.ip ? h->next.port : port;
+ for (; p <= port_to; p++) {
data.port = htons(p);
- ret = adtfn(set, &data, timeout);
+ ip2 = retried && ip == h->next.ip && p == h->next.port
+ ? h->next.ip2 : ip2_from;
+ while (!after(ip2, ip2_to)) {
+ data.ip2 = htonl(ip2);
+ ip2_last = ip_set_range_to_cidr(ip2, ip2_to,
+ &data.cidr);
+ ret = adtfn(set, &data, timeout, flags);
- if (ret && !ip_set_eexist(ret, flags))
- return ret;
- else
- ret = 0;
+ if (ret && !ip_set_eexist(ret, flags))
+ return ret;
+ else
+ ret = 0;
+ ip2 = ip2_last + 1;
+ }
}
+ }
return ret;
}
@@ -389,9 +421,17 @@
#define HOST_MASK 128
#include <linux/netfilter/ipset/ip_set_ahash.h>
+static inline void
+hash_ipportnet6_data_next(struct ip_set_hash *h,
+ const struct hash_ipportnet6_elem *d)
+{
+ h->next.port = ntohs(d->port);
+}
+
static int
hash_ipportnet6_kadt(struct ip_set *set, const struct sk_buff *skb,
- enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
+ const struct xt_action_param *par,
+ enum ipset_adt adt, const struct ip_set_adt_opt *opt)
{
const struct ip_set_hash *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt];
@@ -404,20 +444,20 @@
if (adt == IPSET_TEST)
data.cidr = HOST_MASK;
- if (!ip_set_get_ip6_port(skb, flags & IPSET_DIM_TWO_SRC,
+ if (!ip_set_get_ip6_port(skb, opt->flags & IPSET_DIM_TWO_SRC,
&data.port, &data.proto))
return -EINVAL;
- ip6addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip.in6);
- ip6addrptr(skb, flags & IPSET_DIM_THREE_SRC, &data.ip2.in6);
+ ip6addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &data.ip.in6);
+ ip6addrptr(skb, opt->flags & IPSET_DIM_THREE_SRC, &data.ip2.in6);
ip6_netmask(&data.ip2, data.cidr);
- return adtfn(set, &data, h->timeout);
+ return adtfn(set, &data, opt_timeout(opt, h), opt->cmdflags);
}
static int
hash_ipportnet6_uadt(struct ip_set *set, struct nlattr *tb[],
- enum ipset_adt adt, u32 *lineno, u32 flags)
+ enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
{
const struct ip_set_hash *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt];
@@ -434,6 +474,8 @@
tb[IPSET_ATTR_IP_TO] ||
tb[IPSET_ATTR_CIDR]))
return -IPSET_ERR_PROTOCOL;
+ if (unlikely(tb[IPSET_ATTR_IP_TO]))
+ return -IPSET_ERR_HASH_RANGE_UNSUPPORTED;
if (tb[IPSET_ATTR_LINENO])
*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
@@ -478,7 +520,7 @@
}
if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) {
- ret = adtfn(set, &data, timeout);
+ ret = adtfn(set, &data, timeout, flags);
return ip_set_eexist(ret, flags) ? 0 : ret;
}
@@ -487,9 +529,11 @@
if (port > port_to)
swap(port, port_to);
+ if (retried)
+ port = h->next.port;
for (; port <= port_to; port++) {
data.port = htons(port);
- ret = adtfn(set, &data, timeout);
+ ret = adtfn(set, &data, timeout, flags);
if (ret && !ip_set_eexist(ret, flags))
return ret;
@@ -576,7 +620,9 @@
.features = IPSET_TYPE_IP | IPSET_TYPE_PORT | IPSET_TYPE_IP2,
.dimension = IPSET_DIM_THREE,
.family = AF_UNSPEC,
- .revision = 1,
+ .revision_min = 0,
+ /* 1 SCTP and UDPLITE support added */
+ .revision_max = 2, /* Range as input support for IPv4 added */
.create = hash_ipportnet_create,
.create_policy = {
[IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 },
@@ -589,6 +635,7 @@
[IPSET_ATTR_IP] = { .type = NLA_NESTED },
[IPSET_ATTR_IP_TO] = { .type = NLA_NESTED },
[IPSET_ATTR_IP2] = { .type = NLA_NESTED },
+ [IPSET_ATTR_IP2_TO] = { .type = NLA_NESTED },
[IPSET_ATTR_PORT] = { .type = NLA_U16 },
[IPSET_ATTR_PORT_TO] = { .type = NLA_U16 },
[IPSET_ATTR_CIDR] = { .type = NLA_U8 },
diff --git a/net/netfilter/ipset/ip_set_hash_net.c b/net/netfilter/ipset/ip_set_hash_net.c
index 2aeeabc..2d4b1f4 100644
--- a/net/netfilter/ipset/ip_set_hash_net.c
+++ b/net/netfilter/ipset/ip_set_hash_net.c
@@ -125,9 +125,17 @@
#define HOST_MASK 32
#include <linux/netfilter/ipset/ip_set_ahash.h>
+static inline void
+hash_net4_data_next(struct ip_set_hash *h,
+ const struct hash_net4_elem *d)
+{
+ h->next.ip = ntohl(d->ip);
+}
+
static int
hash_net4_kadt(struct ip_set *set, const struct sk_buff *skb,
- enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
+ const struct xt_action_param *par,
+ enum ipset_adt adt, const struct ip_set_adt_opt *opt)
{
const struct ip_set_hash *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt];
@@ -140,20 +148,21 @@
if (adt == IPSET_TEST)
data.cidr = HOST_MASK;
- ip4addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip);
+ ip4addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &data.ip);
data.ip &= ip_set_netmask(data.cidr);
- return adtfn(set, &data, h->timeout);
+ return adtfn(set, &data, opt_timeout(opt, h), opt->cmdflags);
}
static int
hash_net4_uadt(struct ip_set *set, struct nlattr *tb[],
- enum ipset_adt adt, u32 *lineno, u32 flags)
+ enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
{
const struct ip_set_hash *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt];
struct hash_net4_elem data = { .cidr = HOST_MASK };
u32 timeout = h->timeout;
+ u32 ip = 0, ip_to, last;
int ret;
if (unlikely(!tb[IPSET_ATTR_IP] ||
@@ -163,17 +172,15 @@
if (tb[IPSET_ATTR_LINENO])
*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
- ret = ip_set_get_ipaddr4(tb[IPSET_ATTR_IP], &data.ip);
+ ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &ip);
if (ret)
return ret;
- if (tb[IPSET_ATTR_CIDR])
+ if (tb[IPSET_ATTR_CIDR]) {
data.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
-
- if (!data.cidr)
- return -IPSET_ERR_INVALID_CIDR;
-
- data.ip &= ip_set_netmask(data.cidr);
+ if (!data.cidr)
+ return -IPSET_ERR_INVALID_CIDR;
+ }
if (tb[IPSET_ATTR_TIMEOUT]) {
if (!with_timeout(h->timeout))
@@ -181,9 +188,35 @@
timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
}
- ret = adtfn(set, &data, timeout);
+ if (adt == IPSET_TEST || !tb[IPSET_ATTR_IP_TO]) {
+ data.ip = htonl(ip & ip_set_hostmask(data.cidr));
+ ret = adtfn(set, &data, timeout, flags);
+ return ip_set_eexist(ret, flags) ? 0 : ret;
+ }
- return ip_set_eexist(ret, flags) ? 0 : ret;
+ ip_to = ip;
+ if (tb[IPSET_ATTR_IP_TO]) {
+ ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
+ if (ret)
+ return ret;
+ if (ip_to < ip)
+ swap(ip, ip_to);
+ if (ip + UINT_MAX == ip_to)
+ return -IPSET_ERR_HASH_RANGE;
+ }
+ if (retried)
+ ip = h->next.ip;
+ while (!after(ip, ip_to)) {
+ data.ip = htonl(ip);
+ last = ip_set_range_to_cidr(ip, ip_to, &data.cidr);
+ ret = adtfn(set, &data, timeout, flags);
+ if (ret && !ip_set_eexist(ret, flags))
+ return ret;
+ else
+ ret = 0;
+ ip = last + 1;
+ }
+ return ret;
}
static bool
@@ -292,9 +325,16 @@
#define HOST_MASK 128
#include <linux/netfilter/ipset/ip_set_ahash.h>
+static inline void
+hash_net6_data_next(struct ip_set_hash *h,
+ const struct hash_net6_elem *d)
+{
+}
+
static int
hash_net6_kadt(struct ip_set *set, const struct sk_buff *skb,
- enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
+ const struct xt_action_param *par,
+ enum ipset_adt adt, const struct ip_set_adt_opt *opt)
{
const struct ip_set_hash *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt];
@@ -307,15 +347,15 @@
if (adt == IPSET_TEST)
data.cidr = HOST_MASK;
- ip6addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip.in6);
+ ip6addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &data.ip.in6);
ip6_netmask(&data.ip, data.cidr);
- return adtfn(set, &data, h->timeout);
+ return adtfn(set, &data, opt_timeout(opt, h), opt->cmdflags);
}
static int
hash_net6_uadt(struct ip_set *set, struct nlattr *tb[],
- enum ipset_adt adt, u32 *lineno, u32 flags)
+ enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
{
const struct ip_set_hash *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt];
@@ -326,6 +366,8 @@
if (unlikely(!tb[IPSET_ATTR_IP] ||
!ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
return -IPSET_ERR_PROTOCOL;
+ if (unlikely(tb[IPSET_ATTR_IP_TO]))
+ return -IPSET_ERR_HASH_RANGE_UNSUPPORTED;
if (tb[IPSET_ATTR_LINENO])
*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
@@ -348,7 +390,7 @@
timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
}
- ret = adtfn(set, &data, timeout);
+ ret = adtfn(set, &data, timeout, flags);
return ip_set_eexist(ret, flags) ? 0 : ret;
}
@@ -429,7 +471,8 @@
.features = IPSET_TYPE_IP,
.dimension = IPSET_DIM_ONE,
.family = AF_UNSPEC,
- .revision = 0,
+ .revision_min = 0,
+ .revision_max = 1, /* Range as input support for IPv4 added */
.create = hash_net_create,
.create_policy = {
[IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 },
@@ -440,6 +483,7 @@
},
.adt_policy = {
[IPSET_ATTR_IP] = { .type = NLA_NESTED },
+ [IPSET_ATTR_IP_TO] = { .type = NLA_NESTED },
[IPSET_ATTR_CIDR] = { .type = NLA_U8 },
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
},
diff --git a/net/netfilter/ipset/ip_set_hash_netiface.c b/net/netfilter/ipset/ip_set_hash_netiface.c
new file mode 100644
index 0000000..3d6c53b
--- /dev/null
+++ b/net/netfilter/ipset/ip_set_hash_netiface.c
@@ -0,0 +1,762 @@
+/* Copyright (C) 2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
+ *
+ * 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.
+ */
+
+/* Kernel module implementing an IP set type: the hash:net,iface type */
+
+#include <linux/jhash.h>
+#include <linux/module.h>
+#include <linux/ip.h>
+#include <linux/skbuff.h>
+#include <linux/errno.h>
+#include <linux/random.h>
+#include <linux/rbtree.h>
+#include <net/ip.h>
+#include <net/ipv6.h>
+#include <net/netlink.h>
+
+#include <linux/netfilter.h>
+#include <linux/netfilter/ipset/pfxlen.h>
+#include <linux/netfilter/ipset/ip_set.h>
+#include <linux/netfilter/ipset/ip_set_timeout.h>
+#include <linux/netfilter/ipset/ip_set_hash.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
+MODULE_DESCRIPTION("hash:net,iface type of IP sets");
+MODULE_ALIAS("ip_set_hash:net,iface");
+
+/* Interface name rbtree */
+
+struct iface_node {
+ struct rb_node node;
+ char iface[IFNAMSIZ];
+};
+
+#define iface_data(n) (rb_entry(n, struct iface_node, node)->iface)
+
+static inline long
+ifname_compare(const char *_a, const char *_b)
+{
+ const long *a = (const long *)_a;
+ const long *b = (const long *)_b;
+
+ BUILD_BUG_ON(IFNAMSIZ > 4 * sizeof(unsigned long));
+ if (a[0] != b[0])
+ return a[0] - b[0];
+ if (IFNAMSIZ > sizeof(long)) {
+ if (a[1] != b[1])
+ return a[1] - b[1];
+ }
+ if (IFNAMSIZ > 2 * sizeof(long)) {
+ if (a[2] != b[2])
+ return a[2] - b[2];
+ }
+ if (IFNAMSIZ > 3 * sizeof(long)) {
+ if (a[3] != b[3])
+ return a[3] - b[3];
+ }
+ return 0;
+}
+
+static void
+rbtree_destroy(struct rb_root *root)
+{
+ struct rb_node *p, *n = root->rb_node;
+ struct iface_node *node;
+
+ /* Non-recursive destroy, like in ext3 */
+ while (n) {
+ if (n->rb_left) {
+ n = n->rb_left;
+ continue;
+ }
+ if (n->rb_right) {
+ n = n->rb_right;
+ continue;
+ }
+ p = rb_parent(n);
+ node = rb_entry(n, struct iface_node, node);
+ if (!p)
+ *root = RB_ROOT;
+ else if (p->rb_left == n)
+ p->rb_left = NULL;
+ else if (p->rb_right == n)
+ p->rb_right = NULL;
+
+ kfree(node);
+ n = p;
+ }
+}
+
+static int
+iface_test(struct rb_root *root, const char **iface)
+{
+ struct rb_node *n = root->rb_node;
+
+ while (n) {
+ const char *d = iface_data(n);
+ int res = ifname_compare(*iface, d);
+
+ if (res < 0)
+ n = n->rb_left;
+ else if (res > 0)
+ n = n->rb_right;
+ else {
+ *iface = d;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+static int
+iface_add(struct rb_root *root, const char **iface)
+{
+ struct rb_node **n = &(root->rb_node), *p = NULL;
+ struct iface_node *d;
+
+ while (*n) {
+ char *ifname = iface_data(*n);
+ int res = ifname_compare(*iface, ifname);
+
+ p = *n;
+ if (res < 0)
+ n = &((*n)->rb_left);
+ else if (res > 0)
+ n = &((*n)->rb_right);
+ else {
+ *iface = ifname;
+ return 0;
+ }
+ }
+
+ d = kzalloc(sizeof(*d), GFP_ATOMIC);
+ if (!d)
+ return -ENOMEM;
+ strcpy(d->iface, *iface);
+
+ rb_link_node(&d->node, p, n);
+ rb_insert_color(&d->node, root);
+
+ *iface = d->iface;
+ return 0;
+}
+
+/* Type specific function prefix */
+#define TYPE hash_netiface
+
+static bool
+hash_netiface_same_set(const struct ip_set *a, const struct ip_set *b);
+
+#define hash_netiface4_same_set hash_netiface_same_set
+#define hash_netiface6_same_set hash_netiface_same_set
+
+#define STREQ(a, b) (strcmp(a, b) == 0)
+
+/* The type variant functions: IPv4 */
+
+/* Member elements without timeout */
+struct hash_netiface4_elem {
+ __be32 ip;
+ const char *iface;
+ u8 physdev;
+ u8 cidr;
+ u16 padding;
+};
+
+/* Member elements with timeout support */
+struct hash_netiface4_telem {
+ __be32 ip;
+ const char *iface;
+ u8 physdev;
+ u8 cidr;
+ u16 padding;
+ unsigned long timeout;
+};
+
+static inline bool
+hash_netiface4_data_equal(const struct hash_netiface4_elem *ip1,
+ const struct hash_netiface4_elem *ip2)
+{
+ return ip1->ip == ip2->ip &&
+ ip1->cidr == ip2->cidr &&
+ ip1->physdev == ip2->physdev &&
+ ip1->iface == ip2->iface;
+}
+
+static inline bool
+hash_netiface4_data_isnull(const struct hash_netiface4_elem *elem)
+{
+ return elem->cidr == 0;
+}
+
+static inline void
+hash_netiface4_data_copy(struct hash_netiface4_elem *dst,
+ const struct hash_netiface4_elem *src) {
+ dst->ip = src->ip;
+ dst->cidr = src->cidr;
+ dst->physdev = src->physdev;
+ dst->iface = src->iface;
+}
+
+static inline void
+hash_netiface4_data_netmask(struct hash_netiface4_elem *elem, u8 cidr)
+{
+ elem->ip &= ip_set_netmask(cidr);
+ elem->cidr = cidr;
+}
+
+static inline void
+hash_netiface4_data_zero_out(struct hash_netiface4_elem *elem)
+{
+ elem->cidr = 0;
+}
+
+static bool
+hash_netiface4_data_list(struct sk_buff *skb,
+ const struct hash_netiface4_elem *data)
+{
+ u32 flags = data->physdev ? IPSET_FLAG_PHYSDEV : 0;
+
+ NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, data->ip);
+ NLA_PUT_U8(skb, IPSET_ATTR_CIDR, data->cidr);
+ NLA_PUT_STRING(skb, IPSET_ATTR_IFACE, data->iface);
+ if (flags)
+ NLA_PUT_NET32(skb, IPSET_ATTR_CADT_FLAGS, flags);
+ return 0;
+
+nla_put_failure:
+ return 1;
+}
+
+static bool
+hash_netiface4_data_tlist(struct sk_buff *skb,
+ const struct hash_netiface4_elem *data)
+{
+ const struct hash_netiface4_telem *tdata =
+ (const struct hash_netiface4_telem *)data;
+ u32 flags = data->physdev ? IPSET_FLAG_PHYSDEV : 0;
+
+ NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, data->ip);
+ NLA_PUT_U8(skb, IPSET_ATTR_CIDR, data->cidr);
+ NLA_PUT_STRING(skb, IPSET_ATTR_IFACE, data->iface);
+ if (flags)
+ NLA_PUT_NET32(skb, IPSET_ATTR_CADT_FLAGS, flags);
+ NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
+ htonl(ip_set_timeout_get(tdata->timeout)));
+
+ return 0;
+
+nla_put_failure:
+ return 1;
+}
+
+#define IP_SET_HASH_WITH_NETS
+#define IP_SET_HASH_WITH_RBTREE
+
+#define PF 4
+#define HOST_MASK 32
+#include <linux/netfilter/ipset/ip_set_ahash.h>
+
+static inline void
+hash_netiface4_data_next(struct ip_set_hash *h,
+ const struct hash_netiface4_elem *d)
+{
+ h->next.ip = ntohl(d->ip);
+}
+
+static int
+hash_netiface4_kadt(struct ip_set *set, const struct sk_buff *skb,
+ const struct xt_action_param *par,
+ enum ipset_adt adt, const struct ip_set_adt_opt *opt)
+{
+ struct ip_set_hash *h = set->data;
+ ipset_adtfn adtfn = set->variant->adt[adt];
+ struct hash_netiface4_elem data = {
+ .cidr = h->nets[0].cidr ? h->nets[0].cidr : HOST_MASK
+ };
+ int ret;
+
+ if (data.cidr == 0)
+ return -EINVAL;
+ if (adt == IPSET_TEST)
+ data.cidr = HOST_MASK;
+
+ ip4addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &data.ip);
+ data.ip &= ip_set_netmask(data.cidr);
+
+#define IFACE(dir) (par->dir ? par->dir->name : NULL)
+#define PHYSDEV(dir) (nf_bridge->dir ? nf_bridge->dir->name : NULL)
+#define SRCDIR (opt->flags & IPSET_DIM_TWO_SRC)
+
+ if (opt->cmdflags & IPSET_FLAG_PHYSDEV) {
+#ifdef CONFIG_BRIDGE_NETFILTER
+ const struct nf_bridge_info *nf_bridge = skb->nf_bridge;
+
+ if (!nf_bridge)
+ return -EINVAL;
+ data.iface = SRCDIR ? PHYSDEV(physindev) : PHYSDEV(physoutdev);
+ data.physdev = 1;
+#else
+ data.iface = NULL;
+#endif
+ } else
+ data.iface = SRCDIR ? IFACE(in) : IFACE(out);
+
+ if (!data.iface)
+ return -EINVAL;
+ ret = iface_test(&h->rbtree, &data.iface);
+ if (adt == IPSET_ADD) {
+ if (!ret) {
+ ret = iface_add(&h->rbtree, &data.iface);
+ if (ret)
+ return ret;
+ }
+ } else if (!ret)
+ return ret;
+
+ return adtfn(set, &data, opt_timeout(opt, h), opt->cmdflags);
+}
+
+static int
+hash_netiface4_uadt(struct ip_set *set, struct nlattr *tb[],
+ enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
+{
+ struct ip_set_hash *h = set->data;
+ ipset_adtfn adtfn = set->variant->adt[adt];
+ struct hash_netiface4_elem data = { .cidr = HOST_MASK };
+ u32 ip = 0, ip_to, last;
+ u32 timeout = h->timeout;
+ char iface[IFNAMSIZ] = {};
+ int ret;
+
+ if (unlikely(!tb[IPSET_ATTR_IP] ||
+ !tb[IPSET_ATTR_IFACE] ||
+ !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
+ !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS)))
+ return -IPSET_ERR_PROTOCOL;
+
+ if (tb[IPSET_ATTR_LINENO])
+ *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
+
+ ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &ip);
+ if (ret)
+ return ret;
+
+ if (tb[IPSET_ATTR_CIDR]) {
+ data.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
+ if (!data.cidr)
+ return -IPSET_ERR_INVALID_CIDR;
+ }
+
+ if (tb[IPSET_ATTR_TIMEOUT]) {
+ if (!with_timeout(h->timeout))
+ return -IPSET_ERR_TIMEOUT;
+ timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
+ }
+
+ strcpy(iface, nla_data(tb[IPSET_ATTR_IFACE]));
+ data.iface = iface;
+ ret = iface_test(&h->rbtree, &data.iface);
+ if (adt == IPSET_ADD) {
+ if (!ret) {
+ ret = iface_add(&h->rbtree, &data.iface);
+ if (ret)
+ return ret;
+ }
+ } else if (!ret)
+ return ret;
+
+ if (tb[IPSET_ATTR_CADT_FLAGS]) {
+ u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]);
+ if (cadt_flags & IPSET_FLAG_PHYSDEV)
+ data.physdev = 1;
+ }
+
+ if (adt == IPSET_TEST || !tb[IPSET_ATTR_IP_TO]) {
+ data.ip = htonl(ip & ip_set_hostmask(data.cidr));
+ ret = adtfn(set, &data, timeout, flags);
+ return ip_set_eexist(ret, flags) ? 0 : ret;
+ }
+
+ if (tb[IPSET_ATTR_IP_TO]) {
+ ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
+ if (ret)
+ return ret;
+ if (ip_to < ip)
+ swap(ip, ip_to);
+ if (ip + UINT_MAX == ip_to)
+ return -IPSET_ERR_HASH_RANGE;
+ } else {
+ ip_set_mask_from_to(ip, ip_to, data.cidr);
+ }
+
+ if (retried)
+ ip = h->next.ip;
+ while (!after(ip, ip_to)) {
+ data.ip = htonl(ip);
+ last = ip_set_range_to_cidr(ip, ip_to, &data.cidr);
+ ret = adtfn(set, &data, timeout, flags);
+
+ if (ret && !ip_set_eexist(ret, flags))
+ return ret;
+ else
+ ret = 0;
+ ip = last + 1;
+ }
+ return ret;
+}
+
+static bool
+hash_netiface_same_set(const struct ip_set *a, const struct ip_set *b)
+{
+ const struct ip_set_hash *x = a->data;
+ const struct ip_set_hash *y = b->data;
+
+ /* Resizing changes htable_bits, so we ignore it */
+ return x->maxelem == y->maxelem &&
+ x->timeout == y->timeout;
+}
+
+/* The type variant functions: IPv6 */
+
+struct hash_netiface6_elem {
+ union nf_inet_addr ip;
+ const char *iface;
+ u8 physdev;
+ u8 cidr;
+ u16 padding;
+};
+
+struct hash_netiface6_telem {
+ union nf_inet_addr ip;
+ const char *iface;
+ u8 physdev;
+ u8 cidr;
+ u16 padding;
+ unsigned long timeout;
+};
+
+static inline bool
+hash_netiface6_data_equal(const struct hash_netiface6_elem *ip1,
+ const struct hash_netiface6_elem *ip2)
+{
+ return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 &&
+ ip1->cidr == ip2->cidr &&
+ ip1->physdev == ip2->physdev &&
+ ip1->iface == ip2->iface;
+}
+
+static inline bool
+hash_netiface6_data_isnull(const struct hash_netiface6_elem *elem)
+{
+ return elem->cidr == 0;
+}
+
+static inline void
+hash_netiface6_data_copy(struct hash_netiface6_elem *dst,
+ const struct hash_netiface6_elem *src)
+{
+ memcpy(dst, src, sizeof(*dst));
+}
+
+static inline void
+hash_netiface6_data_zero_out(struct hash_netiface6_elem *elem)
+{
+}
+
+static inline void
+ip6_netmask(union nf_inet_addr *ip, u8 prefix)
+{
+ ip->ip6[0] &= ip_set_netmask6(prefix)[0];
+ ip->ip6[1] &= ip_set_netmask6(prefix)[1];
+ ip->ip6[2] &= ip_set_netmask6(prefix)[2];
+ ip->ip6[3] &= ip_set_netmask6(prefix)[3];
+}
+
+static inline void
+hash_netiface6_data_netmask(struct hash_netiface6_elem *elem, u8 cidr)
+{
+ ip6_netmask(&elem->ip, cidr);
+ elem->cidr = cidr;
+}
+
+static bool
+hash_netiface6_data_list(struct sk_buff *skb,
+ const struct hash_netiface6_elem *data)
+{
+ u32 flags = data->physdev ? IPSET_FLAG_PHYSDEV : 0;
+
+ NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &data->ip);
+ NLA_PUT_U8(skb, IPSET_ATTR_CIDR, data->cidr);
+ NLA_PUT_STRING(skb, IPSET_ATTR_IFACE, data->iface);
+ if (flags)
+ NLA_PUT_NET32(skb, IPSET_ATTR_CADT_FLAGS, flags);
+ return 0;
+
+nla_put_failure:
+ return 1;
+}
+
+static bool
+hash_netiface6_data_tlist(struct sk_buff *skb,
+ const struct hash_netiface6_elem *data)
+{
+ const struct hash_netiface6_telem *e =
+ (const struct hash_netiface6_telem *)data;
+ u32 flags = data->physdev ? IPSET_FLAG_PHYSDEV : 0;
+
+ NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &e->ip);
+ NLA_PUT_U8(skb, IPSET_ATTR_CIDR, data->cidr);
+ NLA_PUT_STRING(skb, IPSET_ATTR_IFACE, data->iface);
+ if (flags)
+ NLA_PUT_NET32(skb, IPSET_ATTR_CADT_FLAGS, flags);
+ NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
+ htonl(ip_set_timeout_get(e->timeout)));
+ return 0;
+
+nla_put_failure:
+ return 1;
+}
+
+#undef PF
+#undef HOST_MASK
+
+#define PF 6
+#define HOST_MASK 128
+#include <linux/netfilter/ipset/ip_set_ahash.h>
+
+static inline void
+hash_netiface6_data_next(struct ip_set_hash *h,
+ const struct hash_netiface6_elem *d)
+{
+}
+
+static int
+hash_netiface6_kadt(struct ip_set *set, const struct sk_buff *skb,
+ const struct xt_action_param *par,
+ enum ipset_adt adt, const struct ip_set_adt_opt *opt)
+{
+ struct ip_set_hash *h = set->data;
+ ipset_adtfn adtfn = set->variant->adt[adt];
+ struct hash_netiface6_elem data = {
+ .cidr = h->nets[0].cidr ? h->nets[0].cidr : HOST_MASK
+ };
+ int ret;
+
+ if (data.cidr == 0)
+ return -EINVAL;
+ if (adt == IPSET_TEST)
+ data.cidr = HOST_MASK;
+
+ ip6addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &data.ip.in6);
+ ip6_netmask(&data.ip, data.cidr);
+
+ if (opt->cmdflags & IPSET_FLAG_PHYSDEV) {
+#ifdef CONFIG_BRIDGE_NETFILTER
+ const struct nf_bridge_info *nf_bridge = skb->nf_bridge;
+
+ if (!nf_bridge)
+ return -EINVAL;
+ data.iface = SRCDIR ? PHYSDEV(physindev) : PHYSDEV(physoutdev);
+ data.physdev = 1;
+#else
+ data.iface = NULL;
+#endif
+ } else
+ data.iface = SRCDIR ? IFACE(in) : IFACE(out);
+
+ if (!data.iface)
+ return -EINVAL;
+ ret = iface_test(&h->rbtree, &data.iface);
+ if (adt == IPSET_ADD) {
+ if (!ret) {
+ ret = iface_add(&h->rbtree, &data.iface);
+ if (ret)
+ return ret;
+ }
+ } else if (!ret)
+ return ret;
+
+ return adtfn(set, &data, opt_timeout(opt, h), opt->cmdflags);
+}
+
+static int
+hash_netiface6_uadt(struct ip_set *set, struct nlattr *tb[],
+ enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
+{
+ struct ip_set_hash *h = set->data;
+ ipset_adtfn adtfn = set->variant->adt[adt];
+ struct hash_netiface6_elem data = { .cidr = HOST_MASK };
+ u32 timeout = h->timeout;
+ char iface[IFNAMSIZ] = {};
+ int ret;
+
+ if (unlikely(!tb[IPSET_ATTR_IP] ||
+ !tb[IPSET_ATTR_IFACE] ||
+ !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
+ !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS)))
+ return -IPSET_ERR_PROTOCOL;
+ if (unlikely(tb[IPSET_ATTR_IP_TO]))
+ return -IPSET_ERR_HASH_RANGE_UNSUPPORTED;
+
+ if (tb[IPSET_ATTR_LINENO])
+ *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
+
+ ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &data.ip);
+ if (ret)
+ return ret;
+
+ if (tb[IPSET_ATTR_CIDR])
+ data.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
+ if (!data.cidr)
+ return -IPSET_ERR_INVALID_CIDR;
+ ip6_netmask(&data.ip, data.cidr);
+
+ if (tb[IPSET_ATTR_TIMEOUT]) {
+ if (!with_timeout(h->timeout))
+ return -IPSET_ERR_TIMEOUT;
+ timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
+ }
+
+ strcpy(iface, nla_data(tb[IPSET_ATTR_IFACE]));
+ data.iface = iface;
+ ret = iface_test(&h->rbtree, &data.iface);
+ if (adt == IPSET_ADD) {
+ if (!ret) {
+ ret = iface_add(&h->rbtree, &data.iface);
+ if (ret)
+ return ret;
+ }
+ } else if (!ret)
+ return ret;
+
+ if (tb[IPSET_ATTR_CADT_FLAGS]) {
+ u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]);
+ if (cadt_flags & IPSET_FLAG_PHYSDEV)
+ data.physdev = 1;
+ }
+
+ ret = adtfn(set, &data, timeout, flags);
+
+ return ip_set_eexist(ret, flags) ? 0 : ret;
+}
+
+/* Create hash:ip type of sets */
+
+static int
+hash_netiface_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
+{
+ struct ip_set_hash *h;
+ u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM;
+ u8 hbits;
+
+ if (!(set->family == AF_INET || set->family == AF_INET6))
+ return -IPSET_ERR_INVALID_FAMILY;
+
+ if (unlikely(!ip_set_optattr_netorder(tb, IPSET_ATTR_HASHSIZE) ||
+ !ip_set_optattr_netorder(tb, IPSET_ATTR_MAXELEM) ||
+ !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
+ return -IPSET_ERR_PROTOCOL;
+
+ if (tb[IPSET_ATTR_HASHSIZE]) {
+ hashsize = ip_set_get_h32(tb[IPSET_ATTR_HASHSIZE]);
+ if (hashsize < IPSET_MIMINAL_HASHSIZE)
+ hashsize = IPSET_MIMINAL_HASHSIZE;
+ }
+
+ if (tb[IPSET_ATTR_MAXELEM])
+ maxelem = ip_set_get_h32(tb[IPSET_ATTR_MAXELEM]);
+
+ h = kzalloc(sizeof(*h)
+ + sizeof(struct ip_set_hash_nets)
+ * (set->family == AF_INET ? 32 : 128), GFP_KERNEL);
+ if (!h)
+ return -ENOMEM;
+
+ h->maxelem = maxelem;
+ get_random_bytes(&h->initval, sizeof(h->initval));
+ h->timeout = IPSET_NO_TIMEOUT;
+
+ hbits = htable_bits(hashsize);
+ h->table = ip_set_alloc(
+ sizeof(struct htable)
+ + jhash_size(hbits) * sizeof(struct hbucket));
+ if (!h->table) {
+ kfree(h);
+ return -ENOMEM;
+ }
+ h->table->htable_bits = hbits;
+ h->rbtree = RB_ROOT;
+
+ set->data = h;
+
+ if (tb[IPSET_ATTR_TIMEOUT]) {
+ h->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
+
+ set->variant = set->family == AF_INET
+ ? &hash_netiface4_tvariant : &hash_netiface6_tvariant;
+
+ if (set->family == AF_INET)
+ hash_netiface4_gc_init(set);
+ else
+ hash_netiface6_gc_init(set);
+ } else {
+ set->variant = set->family == AF_INET
+ ? &hash_netiface4_variant : &hash_netiface6_variant;
+ }
+
+ pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)\n",
+ set->name, jhash_size(h->table->htable_bits),
+ h->table->htable_bits, h->maxelem, set->data, h->table);
+
+ return 0;
+}
+
+static struct ip_set_type hash_netiface_type __read_mostly = {
+ .name = "hash:net,iface",
+ .protocol = IPSET_PROTOCOL,
+ .features = IPSET_TYPE_IP | IPSET_TYPE_IFACE,
+ .dimension = IPSET_DIM_TWO,
+ .family = AF_UNSPEC,
+ .revision_min = 0,
+ .create = hash_netiface_create,
+ .create_policy = {
+ [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 },
+ [IPSET_ATTR_MAXELEM] = { .type = NLA_U32 },
+ [IPSET_ATTR_PROBES] = { .type = NLA_U8 },
+ [IPSET_ATTR_RESIZE] = { .type = NLA_U8 },
+ [IPSET_ATTR_PROTO] = { .type = NLA_U8 },
+ [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
+ },
+ .adt_policy = {
+ [IPSET_ATTR_IP] = { .type = NLA_NESTED },
+ [IPSET_ATTR_IP_TO] = { .type = NLA_NESTED },
+ [IPSET_ATTR_IFACE] = { .type = NLA_NUL_STRING,
+ .len = IPSET_MAXNAMELEN - 1 },
+ [IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 },
+ [IPSET_ATTR_CIDR] = { .type = NLA_U8 },
+ [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
+ [IPSET_ATTR_LINENO] = { .type = NLA_U32 },
+ },
+ .me = THIS_MODULE,
+};
+
+static int __init
+hash_netiface_init(void)
+{
+ return ip_set_type_register(&hash_netiface_type);
+}
+
+static void __exit
+hash_netiface_fini(void)
+{
+ ip_set_type_unregister(&hash_netiface_type);
+}
+
+module_init(hash_netiface_init);
+module_exit(hash_netiface_fini);
diff --git a/net/netfilter/ipset/ip_set_hash_netport.c b/net/netfilter/ipset/ip_set_hash_netport.c
index e50d9bb..fe203d1 100644
--- a/net/netfilter/ipset/ip_set_hash_netport.c
+++ b/net/netfilter/ipset/ip_set_hash_netport.c
@@ -137,9 +137,18 @@
#define HOST_MASK 32
#include <linux/netfilter/ipset/ip_set_ahash.h>
+static inline void
+hash_netport4_data_next(struct ip_set_hash *h,
+ const struct hash_netport4_elem *d)
+{
+ h->next.ip = ntohl(d->ip);
+ h->next.port = ntohs(d->port);
+}
+
static int
hash_netport4_kadt(struct ip_set *set, const struct sk_buff *skb,
- enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
+ const struct xt_action_param *par,
+ enum ipset_adt adt, const struct ip_set_adt_opt *opt)
{
const struct ip_set_hash *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt];
@@ -152,24 +161,24 @@
if (adt == IPSET_TEST)
data.cidr = HOST_MASK;
- if (!ip_set_get_ip4_port(skb, flags & IPSET_DIM_TWO_SRC,
+ if (!ip_set_get_ip4_port(skb, opt->flags & IPSET_DIM_TWO_SRC,
&data.port, &data.proto))
return -EINVAL;
- ip4addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip);
+ ip4addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &data.ip);
data.ip &= ip_set_netmask(data.cidr);
- return adtfn(set, &data, h->timeout);
+ return adtfn(set, &data, opt_timeout(opt, h), opt->cmdflags);
}
static int
hash_netport4_uadt(struct ip_set *set, struct nlattr *tb[],
- enum ipset_adt adt, u32 *lineno, u32 flags)
+ enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
{
const struct ip_set_hash *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt];
struct hash_netport4_elem data = { .cidr = HOST_MASK };
- u32 port, port_to;
+ u32 port, port_to, p = 0, ip = 0, ip_to, last;
u32 timeout = h->timeout;
bool with_ports = false;
int ret;
@@ -183,15 +192,15 @@
if (tb[IPSET_ATTR_LINENO])
*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
- ret = ip_set_get_ipaddr4(tb[IPSET_ATTR_IP], &data.ip);
+ ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &ip);
if (ret)
return ret;
- if (tb[IPSET_ATTR_CIDR])
+ if (tb[IPSET_ATTR_CIDR]) {
data.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
- if (!data.cidr)
- return -IPSET_ERR_INVALID_CIDR;
- data.ip &= ip_set_netmask(data.cidr);
+ if (!data.cidr)
+ return -IPSET_ERR_INVALID_CIDR;
+ }
if (tb[IPSET_ATTR_PORT])
data.port = nla_get_be16(tb[IPSET_ATTR_PORT]);
@@ -216,24 +225,47 @@
timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
}
- if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) {
- ret = adtfn(set, &data, timeout);
+ with_ports = with_ports && tb[IPSET_ATTR_PORT_TO];
+ if (adt == IPSET_TEST || !(with_ports || tb[IPSET_ATTR_IP_TO])) {
+ data.ip = htonl(ip & ip_set_hostmask(data.cidr));
+ ret = adtfn(set, &data, timeout, flags);
return ip_set_eexist(ret, flags) ? 0 : ret;
}
- port = ntohs(data.port);
- port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
- if (port > port_to)
- swap(port, port_to);
-
- for (; port <= port_to; port++) {
- data.port = htons(port);
- ret = adtfn(set, &data, timeout);
-
- if (ret && !ip_set_eexist(ret, flags))
+ port = port_to = ntohs(data.port);
+ if (tb[IPSET_ATTR_PORT_TO]) {
+ port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
+ if (port_to < port)
+ swap(port, port_to);
+ }
+ if (tb[IPSET_ATTR_IP_TO]) {
+ ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
+ if (ret)
return ret;
- else
- ret = 0;
+ if (ip_to < ip)
+ swap(ip, ip_to);
+ if (ip + UINT_MAX == ip_to)
+ return -IPSET_ERR_HASH_RANGE;
+ } else {
+ ip_set_mask_from_to(ip, ip_to, data.cidr);
+ }
+
+ if (retried)
+ ip = h->next.ip;
+ while (!after(ip, ip_to)) {
+ data.ip = htonl(ip);
+ last = ip_set_range_to_cidr(ip, ip_to, &data.cidr);
+ p = retried && ip == h->next.ip ? h->next.port : port;
+ for (; p <= port_to; p++) {
+ data.port = htons(p);
+ ret = adtfn(set, &data, timeout, flags);
+
+ if (ret && !ip_set_eexist(ret, flags))
+ return ret;
+ else
+ ret = 0;
+ }
+ ip = last + 1;
}
return ret;
}
@@ -351,9 +383,17 @@
#define HOST_MASK 128
#include <linux/netfilter/ipset/ip_set_ahash.h>
+static inline void
+hash_netport6_data_next(struct ip_set_hash *h,
+ const struct hash_netport6_elem *d)
+{
+ h->next.port = ntohs(d->port);
+}
+
static int
hash_netport6_kadt(struct ip_set *set, const struct sk_buff *skb,
- enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
+ const struct xt_action_param *par,
+ enum ipset_adt adt, const struct ip_set_adt_opt *opt)
{
const struct ip_set_hash *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt];
@@ -366,19 +406,19 @@
if (adt == IPSET_TEST)
data.cidr = HOST_MASK;
- if (!ip_set_get_ip6_port(skb, flags & IPSET_DIM_TWO_SRC,
+ if (!ip_set_get_ip6_port(skb, opt->flags & IPSET_DIM_TWO_SRC,
&data.port, &data.proto))
return -EINVAL;
- ip6addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip.in6);
+ ip6addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &data.ip.in6);
ip6_netmask(&data.ip, data.cidr);
- return adtfn(set, &data, h->timeout);
+ return adtfn(set, &data, opt_timeout(opt, h), opt->cmdflags);
}
static int
hash_netport6_uadt(struct ip_set *set, struct nlattr *tb[],
- enum ipset_adt adt, u32 *lineno, u32 flags)
+ enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
{
const struct ip_set_hash *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt];
@@ -393,6 +433,8 @@
!ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) ||
!ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
return -IPSET_ERR_PROTOCOL;
+ if (unlikely(tb[IPSET_ATTR_IP_TO]))
+ return -IPSET_ERR_HASH_RANGE_UNSUPPORTED;
if (tb[IPSET_ATTR_LINENO])
*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
@@ -431,7 +473,7 @@
}
if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) {
- ret = adtfn(set, &data, timeout);
+ ret = adtfn(set, &data, timeout, flags);
return ip_set_eexist(ret, flags) ? 0 : ret;
}
@@ -440,9 +482,11 @@
if (port > port_to)
swap(port, port_to);
+ if (retried)
+ port = h->next.port;
for (; port <= port_to; port++) {
data.port = htons(port);
- ret = adtfn(set, &data, timeout);
+ ret = adtfn(set, &data, timeout, flags);
if (ret && !ip_set_eexist(ret, flags))
return ret;
@@ -528,7 +572,9 @@
.features = IPSET_TYPE_IP | IPSET_TYPE_PORT,
.dimension = IPSET_DIM_TWO,
.family = AF_UNSPEC,
- .revision = 1,
+ .revision_min = 0,
+ /* 1 SCTP and UDPLITE support added */
+ .revision_max = 2, /* Range as input support for IPv4 added */
.create = hash_netport_create,
.create_policy = {
[IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 },
@@ -540,6 +586,7 @@
},
.adt_policy = {
[IPSET_ATTR_IP] = { .type = NLA_NESTED },
+ [IPSET_ATTR_IP_TO] = { .type = NLA_NESTED },
[IPSET_ATTR_PORT] = { .type = NLA_U16 },
[IPSET_ATTR_PORT_TO] = { .type = NLA_U16 },
[IPSET_ATTR_PROTO] = { .type = NLA_U8 },
diff --git a/net/netfilter/ipset/ip_set_list_set.c b/net/netfilter/ipset/ip_set_list_set.c
index e9159e9..4d10819 100644
--- a/net/netfilter/ipset/ip_set_list_set.c
+++ b/net/netfilter/ipset/ip_set_list_set.c
@@ -72,7 +72,8 @@
static int
list_set_kadt(struct ip_set *set, const struct sk_buff *skb,
- enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
+ const struct xt_action_param *par,
+ enum ipset_adt adt, const struct ip_set_adt_opt *opt)
{
struct list_set *map = set->data;
struct set_elem *elem;
@@ -87,17 +88,17 @@
continue;
switch (adt) {
case IPSET_TEST:
- ret = ip_set_test(elem->id, skb, pf, dim, flags);
+ ret = ip_set_test(elem->id, skb, par, opt);
if (ret > 0)
return ret;
break;
case IPSET_ADD:
- ret = ip_set_add(elem->id, skb, pf, dim, flags);
+ ret = ip_set_add(elem->id, skb, par, opt);
if (ret == 0)
return ret;
break;
case IPSET_DEL:
- ret = ip_set_del(elem->id, skb, pf, dim, flags);
+ ret = ip_set_del(elem->id, skb, par, opt);
if (ret == 0)
return ret;
break;
@@ -109,15 +110,28 @@
}
static bool
-next_id_eq(const struct list_set *map, u32 i, ip_set_id_t id)
+id_eq(const struct list_set *map, u32 i, ip_set_id_t id)
{
const struct set_elem *elem;
- if (i + 1 < map->size) {
- elem = list_set_elem(map, i + 1);
+ if (i < map->size) {
+ elem = list_set_elem(map, i);
+ return elem->id == id;
+ }
+
+ return 0;
+}
+
+static bool
+id_eq_timeout(const struct list_set *map, u32 i, ip_set_id_t id)
+{
+ const struct set_elem *elem;
+
+ if (i < map->size) {
+ elem = list_set_elem(map, i);
return !!(elem->id == id &&
!(with_timeout(map->timeout) &&
- list_set_expired(map, i + 1)));
+ list_set_expired(map, i)));
}
return 0;
@@ -190,12 +204,26 @@
return 0;
}
+static void
+cleanup_entries(struct list_set *map)
+{
+ struct set_telem *e;
+ u32 i;
+
+ for (i = 0; i < map->size; i++) {
+ e = list_set_telem(map, i);
+ if (e->id != IPSET_INVALID_ID && list_set_expired(map, i))
+ list_set_del(map, i);
+ }
+}
+
static int
list_set_uadt(struct ip_set *set, struct nlattr *tb[],
- enum ipset_adt adt, u32 *lineno, u32 flags)
+ enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
{
struct list_set *map = set->data;
bool with_timeout = with_timeout(map->timeout);
+ bool flag_exist = flags & IPSET_FLAG_EXIST;
int before = 0;
u32 timeout = map->timeout;
ip_set_id_t id, refid = IPSET_INVALID_ID;
@@ -248,6 +276,8 @@
}
timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
}
+ if (with_timeout && adt != IPSET_TEST)
+ cleanup_entries(map);
switch (adt) {
case IPSET_TEST:
@@ -259,22 +289,37 @@
else if (with_timeout && list_set_expired(map, i))
continue;
else if (before > 0 && elem->id == id)
- ret = next_id_eq(map, i, refid);
+ ret = id_eq_timeout(map, i + 1, refid);
else if (before < 0 && elem->id == refid)
- ret = next_id_eq(map, i, id);
+ ret = id_eq_timeout(map, i + 1, id);
else if (before == 0 && elem->id == id)
ret = 1;
}
break;
case IPSET_ADD:
- for (i = 0; i < map->size && !ret; i++) {
+ for (i = 0; i < map->size; i++) {
elem = list_set_elem(map, i);
- if (elem->id == id &&
- !(with_timeout && list_set_expired(map, i)))
+ if (elem->id != id)
+ continue;
+ if (!(with_timeout && flag_exist)) {
ret = -IPSET_ERR_EXIST;
+ goto finish;
+ } else {
+ struct set_telem *e = list_set_telem(map, i);
+
+ if ((before > 1 &&
+ !id_eq(map, i + 1, refid)) ||
+ (before < 0 &&
+ (i == 0 || !id_eq(map, i - 1, refid)))) {
+ ret = -IPSET_ERR_EXIST;
+ goto finish;
+ }
+ e->timeout = ip_set_timeout_set(timeout);
+ ip_set_put_byindex(id);
+ ret = 0;
+ goto finish;
+ }
}
- if (ret == -IPSET_ERR_EXIST)
- break;
ret = -IPSET_ERR_LIST_FULL;
for (i = 0; i < map->size && ret == -IPSET_ERR_LIST_FULL; i++) {
elem = list_set_elem(map, i);
@@ -283,9 +328,7 @@
: list_set_add(map, i, id, timeout);
else if (elem->id != refid)
continue;
- else if (with_timeout && list_set_expired(map, i))
- ret = -IPSET_ERR_REF_EXIST;
- else if (before)
+ else if (before > 0)
ret = list_set_add(map, i, id, timeout);
else if (i + 1 < map->size)
ret = list_set_add(map, i + 1, id, timeout);
@@ -299,16 +342,12 @@
ret = before != 0 ? -IPSET_ERR_REF_EXIST
: -IPSET_ERR_EXIST;
break;
- } else if (with_timeout && list_set_expired(map, i))
- continue;
- else if (elem->id == id &&
- (before == 0 ||
- (before > 0 &&
- next_id_eq(map, i, refid))))
+ } else if (elem->id == id &&
+ (before == 0 ||
+ (before > 0 && id_eq(map, i + 1, refid))))
ret = list_set_del(map, i);
- else if (before < 0 &&
- elem->id == refid &&
- next_id_eq(map, i, id))
+ else if (elem->id == refid &&
+ before < 0 && id_eq(map, i + 1, id))
ret = list_set_del(map, i + 1);
}
break;
@@ -454,15 +493,9 @@
{
struct ip_set *set = (struct ip_set *) ul_set;
struct list_set *map = set->data;
- struct set_telem *e;
- u32 i;
write_lock_bh(&set->lock);
- for (i = 0; i < map->size; i++) {
- e = list_set_telem(map, i);
- if (e->id != IPSET_INVALID_ID && list_set_expired(map, i))
- list_set_del(map, i);
- }
+ cleanup_entries(map);
write_unlock_bh(&set->lock);
map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ;
@@ -543,7 +576,8 @@
.features = IPSET_TYPE_NAME | IPSET_DUMP_LAST,
.dimension = IPSET_DIM_ONE,
.family = AF_UNSPEC,
- .revision = 0,
+ .revision_min = 0,
+ .revision_max = 0,
.create = list_set_create,
.create_policy = {
[IPSET_ATTR_SIZE] = { .type = NLA_U32 },
diff --git a/net/netfilter/ipset/pfxlen.c b/net/netfilter/ipset/pfxlen.c
index 23f8c81..bd13d66 100644
--- a/net/netfilter/ipset/pfxlen.c
+++ b/net/netfilter/ipset/pfxlen.c
@@ -148,7 +148,7 @@
EXPORT_SYMBOL_GPL(ip_set_netmask_map);
#undef E
-#define E(a, b, c, d) \
+#define E(a, b, c, d) \
{.ip6 = { (__force __be32) a, (__force __be32) b, \
(__force __be32) c, (__force __be32) d, \
} }
@@ -289,3 +289,24 @@
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF),
};
EXPORT_SYMBOL_GPL(ip_set_hostmask_map);
+
+/* Find the largest network which matches the range from left, in host order. */
+u32
+ip_set_range_to_cidr(u32 from, u32 to, u8 *cidr)
+{
+ u32 last;
+ u8 i;
+
+ for (i = 1; i < 32; i++) {
+ if ((from & ip_set_hostmask(i)) != from)
+ continue;
+ last = from | ~ip_set_hostmask(i);
+ if (!after(last, to)) {
+ *cidr = i;
+ return last;
+ }
+ }
+ *cidr = 32;
+ return from;
+}
+EXPORT_SYMBOL_GPL(ip_set_range_to_cidr);
diff --git a/net/netfilter/ipvs/ip_vs_app.c b/net/netfilter/ipvs/ip_vs_app.c
index 059af31..fe6cb43 100644
--- a/net/netfilter/ipvs/ip_vs_app.c
+++ b/net/netfilter/ipvs/ip_vs_app.c
@@ -576,7 +576,7 @@
};
#endif
-int __net_init __ip_vs_app_init(struct net *net)
+int __net_init ip_vs_app_net_init(struct net *net)
{
struct netns_ipvs *ipvs = net_ipvs(net);
@@ -585,17 +585,7 @@
return 0;
}
-void __net_exit __ip_vs_app_cleanup(struct net *net)
+void __net_exit ip_vs_app_net_cleanup(struct net *net)
{
proc_net_remove(net, "ip_vs_app");
}
-
-int __init ip_vs_app_init(void)
-{
- return 0;
-}
-
-
-void ip_vs_app_cleanup(void)
-{
-}
diff --git a/net/netfilter/ipvs/ip_vs_conn.c b/net/netfilter/ipvs/ip_vs_conn.c
index 782db27..12571fb 100644
--- a/net/netfilter/ipvs/ip_vs_conn.c
+++ b/net/netfilter/ipvs/ip_vs_conn.c
@@ -1255,7 +1255,7 @@
/*
* per netns init and exit
*/
-int __net_init __ip_vs_conn_init(struct net *net)
+int __net_init ip_vs_conn_net_init(struct net *net)
{
struct netns_ipvs *ipvs = net_ipvs(net);
@@ -1266,7 +1266,7 @@
return 0;
}
-void __net_exit __ip_vs_conn_cleanup(struct net *net)
+void __net_exit ip_vs_conn_net_cleanup(struct net *net)
{
/* flush all the connection entries first */
ip_vs_conn_flush(net);
diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c
index 24c28d2..4f77bb1 100644
--- a/net/netfilter/ipvs/ip_vs_core.c
+++ b/net/netfilter/ipvs/ip_vs_core.c
@@ -852,7 +852,7 @@
*related = 1;
/* reassemble IP fragments */
- if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) {
+ if (ip_is_fragment(ip_hdr(skb))) {
if (ip_vs_gather_frags(skb, ip_vs_defrag_user(hooknum)))
return NF_STOLEN;
}
@@ -1156,8 +1156,7 @@
ip_vs_fill_iphdr(af, skb_network_header(skb), &iph);
} else
#endif
- if (unlikely(ip_hdr(skb)->frag_off & htons(IP_MF|IP_OFFSET) &&
- !pp->dont_defrag)) {
+ if (unlikely(ip_is_fragment(ip_hdr(skb)) && !pp->dont_defrag)) {
if (ip_vs_gather_frags(skb,
ip_vs_defrag_user(hooknum)))
return NF_STOLEN;
@@ -1310,7 +1309,7 @@
*related = 1;
/* reassemble IP fragments */
- if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) {
+ if (ip_is_fragment(ip_hdr(skb))) {
if (ip_vs_gather_frags(skb, ip_vs_defrag_user(hooknum)))
return NF_STOLEN;
}
@@ -1384,7 +1383,7 @@
offset += 2 * sizeof(__u16);
verdict = ip_vs_icmp_xmit(skb, cp, pp, offset, hooknum);
- out:
+out:
__ip_vs_conn_put(cp);
return verdict;
@@ -1891,22 +1890,22 @@
atomic_inc(&ipvs_netns_cnt);
net->ipvs = ipvs;
- if (__ip_vs_estimator_init(net) < 0)
+ if (ip_vs_estimator_net_init(net) < 0)
goto estimator_fail;
- if (__ip_vs_control_init(net) < 0)
+ if (ip_vs_control_net_init(net) < 0)
goto control_fail;
- if (__ip_vs_protocol_init(net) < 0)
+ if (ip_vs_protocol_net_init(net) < 0)
goto protocol_fail;
- if (__ip_vs_app_init(net) < 0)
+ if (ip_vs_app_net_init(net) < 0)
goto app_fail;
- if (__ip_vs_conn_init(net) < 0)
+ if (ip_vs_conn_net_init(net) < 0)
goto conn_fail;
- if (__ip_vs_sync_init(net) < 0)
+ if (ip_vs_sync_net_init(net) < 0)
goto sync_fail;
printk(KERN_INFO "IPVS: Creating netns size=%zu id=%d\n",
@@ -1917,27 +1916,27 @@
*/
sync_fail:
- __ip_vs_conn_cleanup(net);
+ ip_vs_conn_net_cleanup(net);
conn_fail:
- __ip_vs_app_cleanup(net);
+ ip_vs_app_net_cleanup(net);
app_fail:
- __ip_vs_protocol_cleanup(net);
+ ip_vs_protocol_net_cleanup(net);
protocol_fail:
- __ip_vs_control_cleanup(net);
+ ip_vs_control_net_cleanup(net);
control_fail:
- __ip_vs_estimator_cleanup(net);
+ ip_vs_estimator_net_cleanup(net);
estimator_fail:
return -ENOMEM;
}
static void __net_exit __ip_vs_cleanup(struct net *net)
{
- __ip_vs_service_cleanup(net); /* ip_vs_flush() with locks */
- __ip_vs_conn_cleanup(net);
- __ip_vs_app_cleanup(net);
- __ip_vs_protocol_cleanup(net);
- __ip_vs_control_cleanup(net);
- __ip_vs_estimator_cleanup(net);
+ ip_vs_service_net_cleanup(net); /* ip_vs_flush() with locks */
+ ip_vs_conn_net_cleanup(net);
+ ip_vs_app_net_cleanup(net);
+ ip_vs_protocol_net_cleanup(net);
+ ip_vs_control_net_cleanup(net);
+ ip_vs_estimator_net_cleanup(net);
IP_VS_DBG(2, "ipvs netns %d released\n", net_ipvs(net)->gen);
}
@@ -1946,7 +1945,7 @@
EnterFunction(2);
net_ipvs(net)->enable = 0; /* Disable packet reception */
smp_wmb();
- __ip_vs_sync_cleanup(net);
+ ip_vs_sync_net_cleanup(net);
LeaveFunction(2);
}
@@ -1968,36 +1967,23 @@
{
int ret;
- ip_vs_estimator_init();
ret = ip_vs_control_init();
if (ret < 0) {
pr_err("can't setup control.\n");
- goto cleanup_estimator;
+ goto exit;
}
ip_vs_protocol_init();
- ret = ip_vs_app_init();
- if (ret < 0) {
- pr_err("can't setup application helper.\n");
- goto cleanup_protocol;
- }
-
ret = ip_vs_conn_init();
if (ret < 0) {
pr_err("can't setup connection table.\n");
- goto cleanup_app;
- }
-
- ret = ip_vs_sync_init();
- if (ret < 0) {
- pr_err("can't setup sync data.\n");
- goto cleanup_conn;
+ goto cleanup_protocol;
}
ret = register_pernet_subsys(&ipvs_core_ops); /* Alloc ip_vs struct */
if (ret < 0)
- goto cleanup_sync;
+ goto cleanup_conn;
ret = register_pernet_device(&ipvs_core_dev_ops);
if (ret < 0)
@@ -2017,17 +2003,12 @@
unregister_pernet_device(&ipvs_core_dev_ops);
cleanup_sub:
unregister_pernet_subsys(&ipvs_core_ops);
-cleanup_sync:
- ip_vs_sync_cleanup();
- cleanup_conn:
+cleanup_conn:
ip_vs_conn_cleanup();
- cleanup_app:
- ip_vs_app_cleanup();
- cleanup_protocol:
+cleanup_protocol:
ip_vs_protocol_cleanup();
ip_vs_control_cleanup();
- cleanup_estimator:
- ip_vs_estimator_cleanup();
+exit:
return ret;
}
@@ -2036,12 +2017,9 @@
nf_unregister_hooks(ip_vs_ops, ARRAY_SIZE(ip_vs_ops));
unregister_pernet_device(&ipvs_core_dev_ops);
unregister_pernet_subsys(&ipvs_core_ops); /* free ip_vs struct */
- ip_vs_sync_cleanup();
ip_vs_conn_cleanup();
- ip_vs_app_cleanup();
ip_vs_protocol_cleanup();
ip_vs_control_cleanup();
- ip_vs_estimator_cleanup();
pr_info("ipvs unloaded.\n");
}
diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c
index 699c79a..be43fd8 100644
--- a/net/netfilter/ipvs/ip_vs_ctl.c
+++ b/net/netfilter/ipvs/ip_vs_ctl.c
@@ -1334,9 +1334,9 @@
ip_vs_bind_pe(svc, pe);
}
- out_unlock:
+out_unlock:
write_unlock_bh(&__ip_vs_svc_lock);
- out:
+out:
ip_vs_scheduler_put(old_sched);
ip_vs_pe_put(old_pe);
return ret;
@@ -1483,7 +1483,7 @@
* Delete service by {netns} in the service table.
* Called by __ip_vs_cleanup()
*/
-void __ip_vs_service_cleanup(struct net *net)
+void ip_vs_service_net_cleanup(struct net *net)
{
EnterFunction(2);
/* Check for "full" addressed entries */
@@ -1662,7 +1662,7 @@
/*
* IPVS sysctl table (under the /proc/sys/net/ipv4/vs/)
* Do not change order or insert new entries without
- * align with netns init in __ip_vs_control_init()
+ * align with netns init in ip_vs_control_net_init()
*/
static struct ctl_table vs_vars[] = {
@@ -2469,7 +2469,7 @@
count++;
}
}
- out:
+out:
return ret;
}
@@ -2707,7 +2707,7 @@
ret = -EINVAL;
}
- out:
+out:
mutex_unlock(&__ip_vs_mutex);
return ret;
}
@@ -3595,7 +3595,7 @@
* per netns intit/exit func.
*/
#ifdef CONFIG_SYSCTL
-int __net_init __ip_vs_control_init_sysctl(struct net *net)
+int __net_init ip_vs_control_net_init_sysctl(struct net *net)
{
int idx;
struct netns_ipvs *ipvs = net_ipvs(net);
@@ -3654,7 +3654,7 @@
return 0;
}
-void __net_init __ip_vs_control_cleanup_sysctl(struct net *net)
+void __net_init ip_vs_control_net_cleanup_sysctl(struct net *net)
{
struct netns_ipvs *ipvs = net_ipvs(net);
@@ -3665,8 +3665,8 @@
#else
-int __net_init __ip_vs_control_init_sysctl(struct net *net) { return 0; }
-void __net_init __ip_vs_control_cleanup_sysctl(struct net *net) { }
+int __net_init ip_vs_control_net_init_sysctl(struct net *net) { return 0; }
+void __net_init ip_vs_control_net_cleanup_sysctl(struct net *net) { }
#endif
@@ -3674,7 +3674,7 @@
.notifier_call = ip_vs_dst_event,
};
-int __net_init __ip_vs_control_init(struct net *net)
+int __net_init ip_vs_control_net_init(struct net *net)
{
int idx;
struct netns_ipvs *ipvs = net_ipvs(net);
@@ -3702,7 +3702,7 @@
proc_net_fops_create(net, "ip_vs_stats_percpu", 0,
&ip_vs_stats_percpu_fops);
- if (__ip_vs_control_init_sysctl(net))
+ if (ip_vs_control_net_init_sysctl(net))
goto err;
return 0;
@@ -3712,13 +3712,13 @@
return -ENOMEM;
}
-void __net_exit __ip_vs_control_cleanup(struct net *net)
+void __net_exit ip_vs_control_net_cleanup(struct net *net)
{
struct netns_ipvs *ipvs = net_ipvs(net);
ip_vs_trash_cleanup(net);
ip_vs_stop_estimator(net, &ipvs->tot_stats);
- __ip_vs_control_cleanup_sysctl(net);
+ ip_vs_control_net_cleanup_sysctl(net);
proc_net_remove(net, "ip_vs_stats_percpu");
proc_net_remove(net, "ip_vs_stats");
proc_net_remove(net, "ip_vs");
diff --git a/net/netfilter/ipvs/ip_vs_est.c b/net/netfilter/ipvs/ip_vs_est.c
index 508cce9..0fac601 100644
--- a/net/netfilter/ipvs/ip_vs_est.c
+++ b/net/netfilter/ipvs/ip_vs_est.c
@@ -192,7 +192,7 @@
dst->outbps = (e->outbps + 0xF) >> 5;
}
-int __net_init __ip_vs_estimator_init(struct net *net)
+int __net_init ip_vs_estimator_net_init(struct net *net)
{
struct netns_ipvs *ipvs = net_ipvs(net);
@@ -203,16 +203,7 @@
return 0;
}
-void __net_exit __ip_vs_estimator_cleanup(struct net *net)
+void __net_exit ip_vs_estimator_net_cleanup(struct net *net)
{
del_timer_sync(&net_ipvs(net)->est_timer);
}
-
-int __init ip_vs_estimator_init(void)
-{
- return 0;
-}
-
-void ip_vs_estimator_cleanup(void)
-{
-}
diff --git a/net/netfilter/ipvs/ip_vs_ftp.c b/net/netfilter/ipvs/ip_vs_ftp.c
index af63553..4490a32 100644
--- a/net/netfilter/ipvs/ip_vs_ftp.c
+++ b/net/netfilter/ipvs/ip_vs_ftp.c
@@ -44,8 +44,8 @@
#include <net/ip_vs.h>
-#define SERVER_STRING "227 Entering Passive Mode ("
-#define CLIENT_STRING "PORT "
+#define SERVER_STRING "227 "
+#define CLIENT_STRING "PORT"
/*
@@ -79,14 +79,17 @@
/*
* Get <addr,port> from the string "xxx.xxx.xxx.xxx,ppp,ppp", started
- * with the "pattern" and terminated with the "term" character.
+ * with the "pattern", ignoring before "skip" and terminated with
+ * the "term" character.
* <addr,port> is in network order.
*/
static int ip_vs_ftp_get_addrport(char *data, char *data_limit,
- const char *pattern, size_t plen, char term,
+ const char *pattern, size_t plen,
+ char skip, char term,
__be32 *addr, __be16 *port,
char **start, char **end)
{
+ char *s, c;
unsigned char p[6];
int i = 0;
@@ -101,19 +104,38 @@
if (strnicmp(data, pattern, plen) != 0) {
return 0;
}
- *start = data + plen;
+ s = data + plen;
+ if (skip) {
+ int found = 0;
- for (data = *start; *data != term; data++) {
+ for (;; s++) {
+ if (s == data_limit)
+ return -1;
+ if (!found) {
+ if (*s == skip)
+ found = 1;
+ } else if (*s != skip) {
+ break;
+ }
+ }
+ }
+
+ for (data = s; ; data++) {
if (data == data_limit)
return -1;
+ if (*data == term)
+ break;
}
*end = data;
memset(p, 0, sizeof(p));
- for (data = *start; data != *end; data++) {
- if (*data >= '0' && *data <= '9') {
- p[i] = p[i]*10 + *data - '0';
- } else if (*data == ',' && i < 5) {
+ for (data = s; ; data++) {
+ c = *data;
+ if (c == term)
+ break;
+ if (c >= '0' && c <= '9') {
+ p[i] = p[i]*10 + c - '0';
+ } else if (c == ',' && i < 5) {
i++;
} else {
/* unexpected character */
@@ -124,8 +146,9 @@
if (i != 5)
return -1;
- *addr = get_unaligned((__be32 *)p);
- *port = get_unaligned((__be16 *)(p + 4));
+ *start = s;
+ *addr = get_unaligned((__be32 *) p);
+ *port = get_unaligned((__be16 *) (p + 4));
return 1;
}
@@ -185,7 +208,8 @@
if (ip_vs_ftp_get_addrport(data, data_limit,
SERVER_STRING,
- sizeof(SERVER_STRING)-1, ')',
+ sizeof(SERVER_STRING)-1,
+ '(', ')',
&from.ip, &port,
&start, &end) != 1)
return 1;
@@ -345,7 +369,7 @@
*/
if (ip_vs_ftp_get_addrport(data_start, data_limit,
CLIENT_STRING, sizeof(CLIENT_STRING)-1,
- '\r', &to.ip, &port,
+ ' ', '\r', &to.ip, &port,
&start, &end) != 1)
return 1;
diff --git a/net/netfilter/ipvs/ip_vs_proto.c b/net/netfilter/ipvs/ip_vs_proto.c
index eb86028..52d073c 100644
--- a/net/netfilter/ipvs/ip_vs_proto.c
+++ b/net/netfilter/ipvs/ip_vs_proto.c
@@ -316,7 +316,7 @@
/*
* per network name-space init
*/
-int __net_init __ip_vs_protocol_init(struct net *net)
+int __net_init ip_vs_protocol_net_init(struct net *net)
{
#ifdef CONFIG_IP_VS_PROTO_TCP
register_ip_vs_proto_netns(net, &ip_vs_protocol_tcp);
@@ -336,7 +336,7 @@
return 0;
}
-void __net_exit __ip_vs_protocol_cleanup(struct net *net)
+void __net_exit ip_vs_protocol_net_cleanup(struct net *net)
{
struct netns_ipvs *ipvs = net_ipvs(net);
struct ip_vs_proto_data *pd;
diff --git a/net/netfilter/ipvs/ip_vs_sync.c b/net/netfilter/ipvs/ip_vs_sync.c
index e292e5b..7ee7215 100644
--- a/net/netfilter/ipvs/ip_vs_sync.c
+++ b/net/netfilter/ipvs/ip_vs_sync.c
@@ -1663,7 +1663,7 @@
/*
* Initialize data struct for each netns
*/
-int __net_init __ip_vs_sync_init(struct net *net)
+int __net_init ip_vs_sync_net_init(struct net *net)
{
struct netns_ipvs *ipvs = net_ipvs(net);
@@ -1677,7 +1677,7 @@
return 0;
}
-void __ip_vs_sync_cleanup(struct net *net)
+void ip_vs_sync_net_cleanup(struct net *net)
{
int retc;
@@ -1689,12 +1689,3 @@
if (retc && retc != -ESRCH)
pr_err("Failed to stop Backup Daemon\n");
}
-
-int __init ip_vs_sync_init(void)
-{
- return 0;
-}
-
-void ip_vs_sync_cleanup(void)
-{
-}
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index 482e90c..7dec88a 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -970,7 +970,7 @@
if (nlh->nlmsg_flags & NLM_F_DUMP)
return netlink_dump_start(ctnl, skb, nlh, ctnetlink_dump_table,
- ctnetlink_done);
+ ctnetlink_done, 0);
err = ctnetlink_parse_zone(cda[CTA_ZONE], &zone);
if (err < 0)
@@ -1840,7 +1840,7 @@
if (nlh->nlmsg_flags & NLM_F_DUMP) {
return netlink_dump_start(ctnl, skb, nlh,
ctnetlink_exp_dump_table,
- ctnetlink_exp_done);
+ ctnetlink_exp_done, 0);
}
err = ctnetlink_parse_zone(cda[CTA_EXPECT_ZONE], &zone);
diff --git a/net/netfilter/xt_CT.c b/net/netfilter/xt_CT.c
index 782e519..0221d10 100644
--- a/net/netfilter/xt_CT.c
+++ b/net/netfilter/xt_CT.c
@@ -5,7 +5,7 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
-
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/module.h>
#include <linux/gfp.h>
#include <linux/skbuff.h>
@@ -95,8 +95,11 @@
if (info->helper[0]) {
ret = -ENOENT;
proto = xt_ct_find_proto(par);
- if (!proto)
+ if (!proto) {
+ pr_info("You must specify a L4 protocol, "
+ "and not use inversions on it.\n");
goto err3;
+ }
ret = -ENOMEM;
help = nf_ct_helper_ext_add(ct, GFP_KERNEL);
@@ -107,8 +110,10 @@
help->helper = nf_conntrack_helper_try_module_get(info->helper,
par->family,
proto);
- if (help->helper == NULL)
+ if (help->helper == NULL) {
+ pr_info("No such helper \"%s\"\n", info->helper);
goto err3;
+ }
}
__set_bit(IPS_TEMPLATE_BIT, &ct->status);
diff --git a/net/netfilter/xt_HL.c b/net/netfilter/xt_HL.c
index 95b08480..1535e87 100644
--- a/net/netfilter/xt_HL.c
+++ b/net/netfilter/xt_HL.c
@@ -38,22 +38,22 @@
iph = ip_hdr(skb);
switch (info->mode) {
- case IPT_TTL_SET:
- new_ttl = info->ttl;
- break;
- case IPT_TTL_INC:
- new_ttl = iph->ttl + info->ttl;
- if (new_ttl > 255)
- new_ttl = 255;
- break;
- case IPT_TTL_DEC:
- new_ttl = iph->ttl - info->ttl;
- if (new_ttl < 0)
- new_ttl = 0;
- break;
- default:
- new_ttl = iph->ttl;
- break;
+ case IPT_TTL_SET:
+ new_ttl = info->ttl;
+ break;
+ case IPT_TTL_INC:
+ new_ttl = iph->ttl + info->ttl;
+ if (new_ttl > 255)
+ new_ttl = 255;
+ break;
+ case IPT_TTL_DEC:
+ new_ttl = iph->ttl - info->ttl;
+ if (new_ttl < 0)
+ new_ttl = 0;
+ break;
+ default:
+ new_ttl = iph->ttl;
+ break;
}
if (new_ttl != iph->ttl) {
@@ -78,22 +78,22 @@
ip6h = ipv6_hdr(skb);
switch (info->mode) {
- case IP6T_HL_SET:
- new_hl = info->hop_limit;
- break;
- case IP6T_HL_INC:
- new_hl = ip6h->hop_limit + info->hop_limit;
- if (new_hl > 255)
- new_hl = 255;
- break;
- case IP6T_HL_DEC:
- new_hl = ip6h->hop_limit - info->hop_limit;
- if (new_hl < 0)
- new_hl = 0;
- break;
- default:
- new_hl = ip6h->hop_limit;
- break;
+ case IP6T_HL_SET:
+ new_hl = info->hop_limit;
+ break;
+ case IP6T_HL_INC:
+ new_hl = ip6h->hop_limit + info->hop_limit;
+ if (new_hl > 255)
+ new_hl = 255;
+ break;
+ case IP6T_HL_DEC:
+ new_hl = ip6h->hop_limit - info->hop_limit;
+ if (new_hl < 0)
+ new_hl = 0;
+ break;
+ default:
+ new_hl = ip6h->hop_limit;
+ break;
}
ip6h->hop_limit = new_hl;
diff --git a/net/netfilter/xt_hl.c b/net/netfilter/xt_hl.c
index 7d12221..0039511 100644
--- a/net/netfilter/xt_hl.c
+++ b/net/netfilter/xt_hl.c
@@ -31,14 +31,14 @@
const u8 ttl = ip_hdr(skb)->ttl;
switch (info->mode) {
- case IPT_TTL_EQ:
- return ttl == info->ttl;
- case IPT_TTL_NE:
- return ttl != info->ttl;
- case IPT_TTL_LT:
- return ttl < info->ttl;
- case IPT_TTL_GT:
- return ttl > info->ttl;
+ case IPT_TTL_EQ:
+ return ttl == info->ttl;
+ case IPT_TTL_NE:
+ return ttl != info->ttl;
+ case IPT_TTL_LT:
+ return ttl < info->ttl;
+ case IPT_TTL_GT:
+ return ttl > info->ttl;
}
return false;
@@ -50,14 +50,14 @@
const struct ipv6hdr *ip6h = ipv6_hdr(skb);
switch (info->mode) {
- case IP6T_HL_EQ:
- return ip6h->hop_limit == info->hop_limit;
- case IP6T_HL_NE:
- return ip6h->hop_limit != info->hop_limit;
- case IP6T_HL_LT:
- return ip6h->hop_limit < info->hop_limit;
- case IP6T_HL_GT:
- return ip6h->hop_limit > info->hop_limit;
+ case IP6T_HL_EQ:
+ return ip6h->hop_limit == info->hop_limit;
+ case IP6T_HL_NE:
+ return ip6h->hop_limit != info->hop_limit;
+ case IP6T_HL_LT:
+ return ip6h->hop_limit < info->hop_limit;
+ case IP6T_HL_GT:
+ return ip6h->hop_limit > info->hop_limit;
}
return false;
diff --git a/net/netfilter/xt_set.c b/net/netfilter/xt_set.c
index b3babae..0ec8138 100644
--- a/net/netfilter/xt_set.c
+++ b/net/netfilter/xt_set.c
@@ -13,7 +13,6 @@
#include <linux/module.h>
#include <linux/skbuff.h>
-#include <linux/version.h>
#include <linux/netfilter/x_tables.h>
#include <linux/netfilter/xt_set.h>
@@ -29,23 +28,33 @@
static inline int
match_set(ip_set_id_t index, const struct sk_buff *skb,
- u8 pf, u8 dim, u8 flags, int inv)
+ const struct xt_action_param *par,
+ const struct ip_set_adt_opt *opt, int inv)
{
- if (ip_set_test(index, skb, pf, dim, flags))
+ if (ip_set_test(index, skb, par, opt))
inv = !inv;
return inv;
}
+#define ADT_OPT(n, f, d, fs, cfs, t) \
+const struct ip_set_adt_opt n = { \
+ .family = f, \
+ .dim = d, \
+ .flags = fs, \
+ .cmdflags = cfs, \
+ .timeout = t, \
+}
+
/* Revision 0 interface: backward compatible with netfilter/iptables */
static bool
set_match_v0(const struct sk_buff *skb, struct xt_action_param *par)
{
const struct xt_set_info_match_v0 *info = par->matchinfo;
+ ADT_OPT(opt, par->family, info->match_set.u.compat.dim,
+ info->match_set.u.compat.flags, 0, UINT_MAX);
- return match_set(info->match_set.index, skb, par->family,
- info->match_set.u.compat.dim,
- info->match_set.u.compat.flags,
+ return match_set(info->match_set.index, skb, par, &opt,
info->match_set.u.compat.flags & IPSET_INV_MATCH);
}
@@ -103,15 +112,15 @@
set_target_v0(struct sk_buff *skb, const struct xt_action_param *par)
{
const struct xt_set_info_target_v0 *info = par->targinfo;
+ ADT_OPT(add_opt, par->family, info->add_set.u.compat.dim,
+ info->add_set.u.compat.flags, 0, UINT_MAX);
+ ADT_OPT(del_opt, par->family, info->del_set.u.compat.dim,
+ info->del_set.u.compat.flags, 0, UINT_MAX);
if (info->add_set.index != IPSET_INVALID_ID)
- ip_set_add(info->add_set.index, skb, par->family,
- info->add_set.u.compat.dim,
- info->add_set.u.compat.flags);
+ ip_set_add(info->add_set.index, skb, par, &add_opt);
if (info->del_set.index != IPSET_INVALID_ID)
- ip_set_del(info->del_set.index, skb, par->family,
- info->del_set.u.compat.dim,
- info->del_set.u.compat.flags);
+ ip_set_del(info->del_set.index, skb, par, &del_opt);
return XT_CONTINUE;
}
@@ -170,23 +179,23 @@
ip_set_nfnl_put(info->del_set.index);
}
-/* Revision 1: current interface to netfilter/iptables */
+/* Revision 1 match and target */
static bool
-set_match(const struct sk_buff *skb, struct xt_action_param *par)
+set_match_v1(const struct sk_buff *skb, struct xt_action_param *par)
{
- const struct xt_set_info_match *info = par->matchinfo;
+ const struct xt_set_info_match_v1 *info = par->matchinfo;
+ ADT_OPT(opt, par->family, info->match_set.dim,
+ info->match_set.flags, 0, UINT_MAX);
- return match_set(info->match_set.index, skb, par->family,
- info->match_set.dim,
- info->match_set.flags,
+ return match_set(info->match_set.index, skb, par, &opt,
info->match_set.flags & IPSET_INV_MATCH);
}
static int
-set_match_checkentry(const struct xt_mtchk_param *par)
+set_match_v1_checkentry(const struct xt_mtchk_param *par)
{
- struct xt_set_info_match *info = par->matchinfo;
+ struct xt_set_info_match_v1 *info = par->matchinfo;
ip_set_id_t index;
index = ip_set_nfnl_get_byindex(info->match_set.index);
@@ -207,36 +216,34 @@
}
static void
-set_match_destroy(const struct xt_mtdtor_param *par)
+set_match_v1_destroy(const struct xt_mtdtor_param *par)
{
- struct xt_set_info_match *info = par->matchinfo;
+ struct xt_set_info_match_v1 *info = par->matchinfo;
ip_set_nfnl_put(info->match_set.index);
}
static unsigned int
-set_target(struct sk_buff *skb, const struct xt_action_param *par)
+set_target_v1(struct sk_buff *skb, const struct xt_action_param *par)
{
- const struct xt_set_info_target *info = par->targinfo;
+ const struct xt_set_info_target_v1 *info = par->targinfo;
+ ADT_OPT(add_opt, par->family, info->add_set.dim,
+ info->add_set.flags, 0, UINT_MAX);
+ ADT_OPT(del_opt, par->family, info->del_set.dim,
+ info->del_set.flags, 0, UINT_MAX);
if (info->add_set.index != IPSET_INVALID_ID)
- ip_set_add(info->add_set.index,
- skb, par->family,
- info->add_set.dim,
- info->add_set.flags);
+ ip_set_add(info->add_set.index, skb, par, &add_opt);
if (info->del_set.index != IPSET_INVALID_ID)
- ip_set_del(info->del_set.index,
- skb, par->family,
- info->del_set.dim,
- info->del_set.flags);
+ ip_set_del(info->del_set.index, skb, par, &del_opt);
return XT_CONTINUE;
}
static int
-set_target_checkentry(const struct xt_tgchk_param *par)
+set_target_v1_checkentry(const struct xt_tgchk_param *par)
{
- const struct xt_set_info_target *info = par->targinfo;
+ const struct xt_set_info_target_v1 *info = par->targinfo;
ip_set_id_t index;
if (info->add_set.index != IPSET_INVALID_ID) {
@@ -273,9 +280,9 @@
}
static void
-set_target_destroy(const struct xt_tgdtor_param *par)
+set_target_v1_destroy(const struct xt_tgdtor_param *par)
{
- const struct xt_set_info_target *info = par->targinfo;
+ const struct xt_set_info_target_v1 *info = par->targinfo;
if (info->add_set.index != IPSET_INVALID_ID)
ip_set_nfnl_put(info->add_set.index);
@@ -283,6 +290,28 @@
ip_set_nfnl_put(info->del_set.index);
}
+/* Revision 2 target */
+
+static unsigned int
+set_target_v2(struct sk_buff *skb, const struct xt_action_param *par)
+{
+ const struct xt_set_info_target_v2 *info = par->targinfo;
+ ADT_OPT(add_opt, par->family, info->add_set.dim,
+ info->add_set.flags, info->flags, info->timeout);
+ ADT_OPT(del_opt, par->family, info->del_set.dim,
+ info->del_set.flags, 0, UINT_MAX);
+
+ if (info->add_set.index != IPSET_INVALID_ID)
+ ip_set_add(info->add_set.index, skb, par, &add_opt);
+ if (info->del_set.index != IPSET_INVALID_ID)
+ ip_set_del(info->del_set.index, skb, par, &del_opt);
+
+ return XT_CONTINUE;
+}
+
+#define set_target_v2_checkentry set_target_v1_checkentry
+#define set_target_v2_destroy set_target_v1_destroy
+
static struct xt_match set_matches[] __read_mostly = {
{
.name = "set",
@@ -298,20 +327,20 @@
.name = "set",
.family = NFPROTO_IPV4,
.revision = 1,
- .match = set_match,
- .matchsize = sizeof(struct xt_set_info_match),
- .checkentry = set_match_checkentry,
- .destroy = set_match_destroy,
+ .match = set_match_v1,
+ .matchsize = sizeof(struct xt_set_info_match_v1),
+ .checkentry = set_match_v1_checkentry,
+ .destroy = set_match_v1_destroy,
.me = THIS_MODULE
},
{
.name = "set",
.family = NFPROTO_IPV6,
.revision = 1,
- .match = set_match,
- .matchsize = sizeof(struct xt_set_info_match),
- .checkentry = set_match_checkentry,
- .destroy = set_match_destroy,
+ .match = set_match_v1,
+ .matchsize = sizeof(struct xt_set_info_match_v1),
+ .checkentry = set_match_v1_checkentry,
+ .destroy = set_match_v1_destroy,
.me = THIS_MODULE
},
};
@@ -331,20 +360,40 @@
.name = "SET",
.revision = 1,
.family = NFPROTO_IPV4,
- .target = set_target,
- .targetsize = sizeof(struct xt_set_info_target),
- .checkentry = set_target_checkentry,
- .destroy = set_target_destroy,
+ .target = set_target_v1,
+ .targetsize = sizeof(struct xt_set_info_target_v1),
+ .checkentry = set_target_v1_checkentry,
+ .destroy = set_target_v1_destroy,
.me = THIS_MODULE
},
{
.name = "SET",
.revision = 1,
.family = NFPROTO_IPV6,
- .target = set_target,
- .targetsize = sizeof(struct xt_set_info_target),
- .checkentry = set_target_checkentry,
- .destroy = set_target_destroy,
+ .target = set_target_v1,
+ .targetsize = sizeof(struct xt_set_info_target_v1),
+ .checkentry = set_target_v1_checkentry,
+ .destroy = set_target_v1_destroy,
+ .me = THIS_MODULE
+ },
+ {
+ .name = "SET",
+ .revision = 2,
+ .family = NFPROTO_IPV4,
+ .target = set_target_v2,
+ .targetsize = sizeof(struct xt_set_info_target_v2),
+ .checkentry = set_target_v2_checkentry,
+ .destroy = set_target_v2_destroy,
+ .me = THIS_MODULE
+ },
+ {
+ .name = "SET",
+ .revision = 2,
+ .family = NFPROTO_IPV6,
+ .target = set_target_v2,
+ .targetsize = sizeof(struct xt_set_info_target_v2),
+ .checkentry = set_target_v2_checkentry,
+ .destroy = set_target_v2_destroy,
.me = THIS_MODULE
},
};
diff --git a/net/netlabel/netlabel_unlabeled.c b/net/netlabel/netlabel_unlabeled.c
index 9c38658..8efd061 100644
--- a/net/netlabel/netlabel_unlabeled.c
+++ b/net/netlabel/netlabel_unlabeled.c
@@ -426,10 +426,9 @@
audit_info);
switch (addr_len) {
case sizeof(struct in_addr): {
- struct in_addr *addr4, *mask4;
+ const struct in_addr *addr4 = addr;
+ const struct in_addr *mask4 = mask;
- addr4 = (struct in_addr *)addr;
- mask4 = (struct in_addr *)mask;
ret_val = netlbl_unlhsh_add_addr4(iface, addr4, mask4, secid);
if (audit_buf != NULL)
netlbl_af4list_audit_addr(audit_buf, 1,
@@ -440,10 +439,9 @@
}
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
case sizeof(struct in6_addr): {
- struct in6_addr *addr6, *mask6;
+ const struct in6_addr *addr6 = addr;
+ const struct in6_addr *mask6 = mask;
- addr6 = (struct in6_addr *)addr;
- mask6 = (struct in6_addr *)mask;
ret_val = netlbl_unlhsh_add_addr6(iface, addr6, mask6, secid);
if (audit_buf != NULL)
netlbl_af6list_audit_addr(audit_buf, 1,
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index 6ef64ad..0a4db02 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -1659,13 +1659,10 @@
{
struct netlink_sock *nlk = nlk_sk(sk);
struct netlink_callback *cb;
- struct sk_buff *skb;
+ struct sk_buff *skb = NULL;
struct nlmsghdr *nlh;
int len, err = -ENOBUFS;
-
- skb = sock_rmalloc(sk, NLMSG_GOODSIZE, 0, GFP_KERNEL);
- if (!skb)
- goto errout;
+ int alloc_size;
mutex_lock(nlk->cb_mutex);
@@ -1675,6 +1672,12 @@
goto errout_skb;
}
+ alloc_size = max_t(int, cb->min_dump_alloc, NLMSG_GOODSIZE);
+
+ skb = sock_rmalloc(sk, alloc_size, 0, GFP_KERNEL);
+ if (!skb)
+ goto errout_skb;
+
len = cb->dump(skb, cb);
if (len > 0) {
@@ -1693,6 +1696,8 @@
if (!nlh)
goto errout_skb;
+ nl_dump_check_consistent(cb, nlh);
+
memcpy(nlmsg_data(nlh), &len, sizeof(len));
if (sk_filter(sk, skb))
@@ -1713,7 +1718,6 @@
errout_skb:
mutex_unlock(nlk->cb_mutex);
kfree_skb(skb);
-errout:
return err;
}
@@ -1721,7 +1725,8 @@
const struct nlmsghdr *nlh,
int (*dump)(struct sk_buff *skb,
struct netlink_callback *),
- int (*done)(struct netlink_callback *))
+ int (*done)(struct netlink_callback *),
+ u16 min_dump_alloc)
{
struct netlink_callback *cb;
struct sock *sk;
@@ -1735,6 +1740,7 @@
cb->dump = dump;
cb->done = done;
cb->nlh = nlh;
+ cb->min_dump_alloc = min_dump_alloc;
atomic_inc(&skb->users);
cb->skb = skb;
diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c
index 1781d99..482fa57 100644
--- a/net/netlink/genetlink.c
+++ b/net/netlink/genetlink.c
@@ -525,7 +525,7 @@
genl_unlock();
err = netlink_dump_start(net->genl_sock, skb, nlh,
- ops->dumpit, ops->done);
+ ops->dumpit, ops->done, 0);
genl_lock();
return err;
}
diff --git a/net/netrom/nr_route.c b/net/netrom/nr_route.c
index 44059d0..cd5ddb2 100644
--- a/net/netrom/nr_route.c
+++ b/net/netrom/nr_route.c
@@ -257,9 +257,12 @@
case 3:
if (nr_node->routes[1].quality > nr_node->routes[0].quality) {
switch (nr_node->which) {
- case 0: nr_node->which = 1; break;
- case 1: nr_node->which = 0; break;
- default: break;
+ case 0:
+ nr_node->which = 1;
+ break;
+ case 1:
+ nr_node->which = 0;
+ break;
}
nr_route = nr_node->routes[0];
nr_node->routes[0] = nr_node->routes[1];
@@ -505,12 +508,13 @@
s->count--;
switch (i) {
- case 0:
- s->routes[0] = s->routes[1];
- case 1:
- s->routes[1] = s->routes[2];
- case 2:
- break;
+ case 0:
+ s->routes[0] = s->routes[1];
+ /* Fallthrough */
+ case 1:
+ s->routes[1] = s->routes[2];
+ case 2:
+ break;
}
break;
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index c0c3cda..7ba6871 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -187,9 +187,11 @@
static void packet_flush_mclist(struct sock *sk);
+struct packet_fanout;
struct packet_sock {
/* struct sock has to be the first member of packet_sock */
struct sock sk;
+ struct packet_fanout *fanout;
struct tpacket_stats stats;
struct packet_ring_buffer rx_ring;
struct packet_ring_buffer tx_ring;
@@ -212,6 +214,24 @@
struct packet_type prot_hook ____cacheline_aligned_in_smp;
};
+#define PACKET_FANOUT_MAX 256
+
+struct packet_fanout {
+#ifdef CONFIG_NET_NS
+ struct net *net;
+#endif
+ unsigned int num_members;
+ u16 id;
+ u8 type;
+ u8 defrag;
+ atomic_t rr_cur;
+ struct list_head list;
+ struct sock *arr[PACKET_FANOUT_MAX];
+ spinlock_t lock;
+ atomic_t sk_ref;
+ struct packet_type prot_hook ____cacheline_aligned_in_smp;
+};
+
struct packet_skb_cb {
unsigned int origlen;
union {
@@ -222,6 +242,64 @@
#define PACKET_SKB_CB(__skb) ((struct packet_skb_cb *)((__skb)->cb))
+static inline struct packet_sock *pkt_sk(struct sock *sk)
+{
+ return (struct packet_sock *)sk;
+}
+
+static void __fanout_unlink(struct sock *sk, struct packet_sock *po);
+static void __fanout_link(struct sock *sk, struct packet_sock *po);
+
+/* register_prot_hook must be invoked with the po->bind_lock held,
+ * or from a context in which asynchronous accesses to the packet
+ * socket is not possible (packet_create()).
+ */
+static void register_prot_hook(struct sock *sk)
+{
+ struct packet_sock *po = pkt_sk(sk);
+ if (!po->running) {
+ if (po->fanout)
+ __fanout_link(sk, po);
+ else
+ dev_add_pack(&po->prot_hook);
+ sock_hold(sk);
+ po->running = 1;
+ }
+}
+
+/* {,__}unregister_prot_hook() must be invoked with the po->bind_lock
+ * held. If the sync parameter is true, we will temporarily drop
+ * the po->bind_lock and do a synchronize_net to make sure no
+ * asynchronous packet processing paths still refer to the elements
+ * of po->prot_hook. If the sync parameter is false, it is the
+ * callers responsibility to take care of this.
+ */
+static void __unregister_prot_hook(struct sock *sk, bool sync)
+{
+ struct packet_sock *po = pkt_sk(sk);
+
+ po->running = 0;
+ if (po->fanout)
+ __fanout_unlink(sk, po);
+ else
+ __dev_remove_pack(&po->prot_hook);
+ __sock_put(sk);
+
+ if (sync) {
+ spin_unlock(&po->bind_lock);
+ synchronize_net();
+ spin_lock(&po->bind_lock);
+ }
+}
+
+static void unregister_prot_hook(struct sock *sk, bool sync)
+{
+ struct packet_sock *po = pkt_sk(sk);
+
+ if (po->running)
+ __unregister_prot_hook(sk, sync);
+}
+
static inline __pure struct page *pgv_to_page(void *addr)
{
if (is_vmalloc_addr(addr))
@@ -324,11 +402,6 @@
buff->head = buff->head != buff->frame_max ? buff->head+1 : 0;
}
-static inline struct packet_sock *pkt_sk(struct sock *sk)
-{
- return (struct packet_sock *)sk;
-}
-
static void packet_sock_destruct(struct sock *sk)
{
skb_queue_purge(&sk->sk_error_queue);
@@ -344,6 +417,247 @@
sk_refcnt_debug_dec(sk);
}
+static int fanout_rr_next(struct packet_fanout *f, unsigned int num)
+{
+ int x = atomic_read(&f->rr_cur) + 1;
+
+ if (x >= num)
+ x = 0;
+
+ return x;
+}
+
+static struct sock *fanout_demux_hash(struct packet_fanout *f, struct sk_buff *skb, unsigned int num)
+{
+ u32 idx, hash = skb->rxhash;
+
+ idx = ((u64)hash * num) >> 32;
+
+ return f->arr[idx];
+}
+
+static struct sock *fanout_demux_lb(struct packet_fanout *f, struct sk_buff *skb, unsigned int num)
+{
+ int cur, old;
+
+ cur = atomic_read(&f->rr_cur);
+ while ((old = atomic_cmpxchg(&f->rr_cur, cur,
+ fanout_rr_next(f, num))) != cur)
+ cur = old;
+ return f->arr[cur];
+}
+
+static struct sk_buff *fanout_check_defrag(struct sk_buff *skb)
+{
+ const struct iphdr *iph;
+ u32 len;
+
+ if (skb->protocol != htons(ETH_P_IP))
+ return skb;
+
+ if (!pskb_may_pull(skb, sizeof(struct iphdr)))
+ return skb;
+
+ iph = ip_hdr(skb);
+ if (iph->ihl < 5 || iph->version != 4)
+ return skb;
+ if (!pskb_may_pull(skb, iph->ihl*4))
+ return skb;
+ iph = ip_hdr(skb);
+ len = ntohs(iph->tot_len);
+ if (skb->len < len || len < (iph->ihl * 4))
+ return skb;
+
+ if (ip_is_fragment(ip_hdr(skb))) {
+ skb = skb_clone(skb, GFP_ATOMIC);
+ if (skb) {
+ if (pskb_trim_rcsum(skb, len))
+ return skb;
+ memset(IPCB(skb), 0, sizeof(struct inet_skb_parm));
+ if (ip_defrag(skb, IP_DEFRAG_AF_PACKET))
+ return NULL;
+ skb->rxhash = 0;
+ }
+ }
+ return skb;
+}
+
+static int packet_rcv_fanout_hash(struct sk_buff *skb, struct net_device *dev,
+ struct packet_type *pt, struct net_device *orig_dev)
+{
+ struct packet_fanout *f = pt->af_packet_priv;
+ unsigned int num = f->num_members;
+ struct packet_sock *po;
+ struct sock *sk;
+
+ if (!net_eq(dev_net(dev), read_pnet(&f->net)) ||
+ !num) {
+ kfree_skb(skb);
+ return 0;
+ }
+
+ if (f->defrag) {
+ skb = fanout_check_defrag(skb);
+ if (!skb)
+ return 0;
+ }
+
+ skb_get_rxhash(skb);
+
+ sk = fanout_demux_hash(f, skb, num);
+ po = pkt_sk(sk);
+
+ return po->prot_hook.func(skb, dev, &po->prot_hook, orig_dev);
+}
+
+static int packet_rcv_fanout_lb(struct sk_buff *skb, struct net_device *dev,
+ struct packet_type *pt, struct net_device *orig_dev)
+{
+ struct packet_fanout *f = pt->af_packet_priv;
+ unsigned int num = f->num_members;
+ struct packet_sock *po;
+ struct sock *sk;
+
+ if (!net_eq(dev_net(dev), read_pnet(&f->net)) ||
+ !num) {
+ kfree_skb(skb);
+ return 0;
+ }
+
+ sk = fanout_demux_lb(f, skb, num);
+ po = pkt_sk(sk);
+
+ return po->prot_hook.func(skb, dev, &po->prot_hook, orig_dev);
+}
+
+static DEFINE_MUTEX(fanout_mutex);
+static LIST_HEAD(fanout_list);
+
+static void __fanout_link(struct sock *sk, struct packet_sock *po)
+{
+ struct packet_fanout *f = po->fanout;
+
+ spin_lock(&f->lock);
+ f->arr[f->num_members] = sk;
+ smp_wmb();
+ f->num_members++;
+ spin_unlock(&f->lock);
+}
+
+static void __fanout_unlink(struct sock *sk, struct packet_sock *po)
+{
+ struct packet_fanout *f = po->fanout;
+ int i;
+
+ spin_lock(&f->lock);
+ for (i = 0; i < f->num_members; i++) {
+ if (f->arr[i] == sk)
+ break;
+ }
+ BUG_ON(i >= f->num_members);
+ f->arr[i] = f->arr[f->num_members - 1];
+ f->num_members--;
+ spin_unlock(&f->lock);
+}
+
+static int fanout_add(struct sock *sk, u16 id, u16 type_flags)
+{
+ struct packet_sock *po = pkt_sk(sk);
+ struct packet_fanout *f, *match;
+ u8 type = type_flags & 0xff;
+ u8 defrag = (type_flags & PACKET_FANOUT_FLAG_DEFRAG) ? 1 : 0;
+ int err;
+
+ switch (type) {
+ case PACKET_FANOUT_HASH:
+ case PACKET_FANOUT_LB:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (!po->running)
+ return -EINVAL;
+
+ if (po->fanout)
+ return -EALREADY;
+
+ mutex_lock(&fanout_mutex);
+ match = NULL;
+ list_for_each_entry(f, &fanout_list, list) {
+ if (f->id == id &&
+ read_pnet(&f->net) == sock_net(sk)) {
+ match = f;
+ break;
+ }
+ }
+ if (match && match->defrag != defrag)
+ return -EINVAL;
+ if (!match) {
+ match = kzalloc(sizeof(*match), GFP_KERNEL);
+ if (match) {
+ write_pnet(&match->net, sock_net(sk));
+ match->id = id;
+ match->type = type;
+ match->defrag = defrag;
+ atomic_set(&match->rr_cur, 0);
+ INIT_LIST_HEAD(&match->list);
+ spin_lock_init(&match->lock);
+ atomic_set(&match->sk_ref, 0);
+ match->prot_hook.type = po->prot_hook.type;
+ match->prot_hook.dev = po->prot_hook.dev;
+ switch (type) {
+ case PACKET_FANOUT_HASH:
+ match->prot_hook.func = packet_rcv_fanout_hash;
+ break;
+ case PACKET_FANOUT_LB:
+ match->prot_hook.func = packet_rcv_fanout_lb;
+ break;
+ }
+ match->prot_hook.af_packet_priv = match;
+ dev_add_pack(&match->prot_hook);
+ list_add(&match->list, &fanout_list);
+ }
+ }
+ err = -ENOMEM;
+ if (match) {
+ err = -EINVAL;
+ if (match->type == type &&
+ match->prot_hook.type == po->prot_hook.type &&
+ match->prot_hook.dev == po->prot_hook.dev) {
+ err = -ENOSPC;
+ if (atomic_read(&match->sk_ref) < PACKET_FANOUT_MAX) {
+ __dev_remove_pack(&po->prot_hook);
+ po->fanout = match;
+ atomic_inc(&match->sk_ref);
+ __fanout_link(sk, po);
+ err = 0;
+ }
+ }
+ }
+ mutex_unlock(&fanout_mutex);
+ return err;
+}
+
+static void fanout_release(struct sock *sk)
+{
+ struct packet_sock *po = pkt_sk(sk);
+ struct packet_fanout *f;
+
+ f = po->fanout;
+ if (!f)
+ return;
+
+ po->fanout = NULL;
+
+ mutex_lock(&fanout_mutex);
+ if (atomic_dec_and_test(&f->sk_ref)) {
+ list_del(&f->list);
+ dev_remove_pack(&f->prot_hook);
+ kfree(f);
+ }
+ mutex_unlock(&fanout_mutex);
+}
static const struct proto_ops packet_ops;
@@ -975,7 +1289,8 @@
struct sk_buff *skb;
struct net_device *dev;
__be16 proto;
- int ifindex, err, reserve = 0;
+ bool need_rls_dev = false;
+ int err, reserve = 0;
void *ph;
struct sockaddr_ll *saddr = (struct sockaddr_ll *)msg->msg_name;
int tp_len, size_max;
@@ -987,7 +1302,7 @@
err = -EBUSY;
if (saddr == NULL) {
- ifindex = po->ifindex;
+ dev = po->prot_hook.dev;
proto = po->num;
addr = NULL;
} else {
@@ -998,12 +1313,12 @@
+ offsetof(struct sockaddr_ll,
sll_addr)))
goto out;
- ifindex = saddr->sll_ifindex;
proto = saddr->sll_protocol;
addr = saddr->sll_addr;
+ dev = dev_get_by_index(sock_net(&po->sk), saddr->sll_ifindex);
+ need_rls_dev = true;
}
- dev = dev_get_by_index(sock_net(&po->sk), ifindex);
err = -ENXIO;
if (unlikely(dev == NULL))
goto out;
@@ -1089,7 +1404,8 @@
__packet_set_status(po, ph, status);
kfree_skb(skb);
out_put:
- dev_put(dev);
+ if (need_rls_dev)
+ dev_put(dev);
out:
mutex_unlock(&po->pg_vec_lock);
return err;
@@ -1127,8 +1443,9 @@
struct sk_buff *skb;
struct net_device *dev;
__be16 proto;
+ bool need_rls_dev = false;
unsigned char *addr;
- int ifindex, err, reserve = 0;
+ int err, reserve = 0;
struct virtio_net_hdr vnet_hdr = { 0 };
int offset = 0;
int vnet_hdr_len;
@@ -1140,7 +1457,7 @@
*/
if (saddr == NULL) {
- ifindex = po->ifindex;
+ dev = po->prot_hook.dev;
proto = po->num;
addr = NULL;
} else {
@@ -1149,13 +1466,12 @@
goto out;
if (msg->msg_namelen < (saddr->sll_halen + offsetof(struct sockaddr_ll, sll_addr)))
goto out;
- ifindex = saddr->sll_ifindex;
proto = saddr->sll_protocol;
addr = saddr->sll_addr;
+ dev = dev_get_by_index(sock_net(sk), saddr->sll_ifindex);
+ need_rls_dev = true;
}
-
- dev = dev_get_by_index(sock_net(sk), ifindex);
err = -ENXIO;
if (dev == NULL)
goto out_unlock;
@@ -1286,14 +1602,15 @@
if (err > 0 && (err = net_xmit_errno(err)) != 0)
goto out_unlock;
- dev_put(dev);
+ if (need_rls_dev)
+ dev_put(dev);
return len;
out_free:
kfree_skb(skb);
out_unlock:
- if (dev)
+ if (dev && need_rls_dev)
dev_put(dev);
out:
return err;
@@ -1334,14 +1651,10 @@
spin_unlock_bh(&net->packet.sklist_lock);
spin_lock(&po->bind_lock);
- if (po->running) {
- /*
- * Remove from protocol table
- */
- po->running = 0;
- po->num = 0;
- __dev_remove_pack(&po->prot_hook);
- __sock_put(sk);
+ unregister_prot_hook(sk, false);
+ if (po->prot_hook.dev) {
+ dev_put(po->prot_hook.dev);
+ po->prot_hook.dev = NULL;
}
spin_unlock(&po->bind_lock);
@@ -1355,6 +1668,8 @@
if (po->tx_ring.pg_vec)
packet_set_ring(sk, &req, 1, 1);
+ fanout_release(sk);
+
synchronize_net();
/*
* Now the socket is dead. No more input will appear.
@@ -1378,24 +1693,18 @@
static int packet_do_bind(struct sock *sk, struct net_device *dev, __be16 protocol)
{
struct packet_sock *po = pkt_sk(sk);
- /*
- * Detach an existing hook if present.
- */
+
+ if (po->fanout)
+ return -EINVAL;
lock_sock(sk);
spin_lock(&po->bind_lock);
- if (po->running) {
- __sock_put(sk);
- po->running = 0;
- po->num = 0;
- spin_unlock(&po->bind_lock);
- dev_remove_pack(&po->prot_hook);
- spin_lock(&po->bind_lock);
- }
-
+ unregister_prot_hook(sk, true);
po->num = protocol;
po->prot_hook.type = protocol;
+ if (po->prot_hook.dev)
+ dev_put(po->prot_hook.dev);
po->prot_hook.dev = dev;
po->ifindex = dev ? dev->ifindex : 0;
@@ -1404,9 +1713,7 @@
goto out_unlock;
if (!dev || (dev->flags & IFF_UP)) {
- dev_add_pack(&po->prot_hook);
- sock_hold(sk);
- po->running = 1;
+ register_prot_hook(sk);
} else {
sk->sk_err = ENETDOWN;
if (!sock_flag(sk, SOCK_DEAD))
@@ -1440,10 +1747,8 @@
strlcpy(name, uaddr->sa_data, sizeof(name));
dev = dev_get_by_name(sock_net(sk), name);
- if (dev) {
+ if (dev)
err = packet_do_bind(sk, dev, pkt_sk(sk)->num);
- dev_put(dev);
- }
return err;
}
@@ -1471,8 +1776,6 @@
goto out;
}
err = packet_do_bind(sk, dev, sll->sll_protocol ? : pkt_sk(sk)->num);
- if (dev)
- dev_put(dev);
out:
return err;
@@ -1537,9 +1840,7 @@
if (proto) {
po->prot_hook.type = proto;
- dev_add_pack(&po->prot_hook);
- sock_hold(sk);
- po->running = 1;
+ register_prot_hook(sk);
}
spin_lock_bh(&net->packet.sklist_lock);
@@ -1681,6 +1982,8 @@
vnet_hdr.flags = VIRTIO_NET_HDR_F_NEEDS_CSUM;
vnet_hdr.csum_start = skb_checksum_start_offset(skb);
vnet_hdr.csum_offset = skb->csum_offset;
+ } else if (skb->ip_summed == CHECKSUM_UNNECESSARY) {
+ vnet_hdr.flags = VIRTIO_NET_HDR_F_DATA_VALID;
} /* else everything is zero */
err = memcpy_toiovec(msg->msg_iov, (void *)&vnet_hdr,
@@ -2102,6 +2405,17 @@
po->tp_tstamp = val;
return 0;
}
+ case PACKET_FANOUT:
+ {
+ int val;
+
+ if (optlen != sizeof(val))
+ return -EINVAL;
+ if (copy_from_user(&val, optval, sizeof(val)))
+ return -EFAULT;
+
+ return fanout_add(sk, val & 0xffff, val >> 16);
+ }
default:
return -ENOPROTOOPT;
}
@@ -2200,6 +2514,15 @@
val = po->tp_tstamp;
data = &val;
break;
+ case PACKET_FANOUT:
+ if (len > sizeof(int))
+ len = sizeof(int);
+ val = (po->fanout ?
+ ((u32)po->fanout->id |
+ ((u32)po->fanout->type << 16)) :
+ 0);
+ data = &val;
+ break;
default:
return -ENOPROTOOPT;
}
@@ -2233,15 +2556,15 @@
if (dev->ifindex == po->ifindex) {
spin_lock(&po->bind_lock);
if (po->running) {
- __dev_remove_pack(&po->prot_hook);
- __sock_put(sk);
- po->running = 0;
+ __unregister_prot_hook(sk, false);
sk->sk_err = ENETDOWN;
if (!sock_flag(sk, SOCK_DEAD))
sk->sk_error_report(sk);
}
if (msg == NETDEV_UNREGISTER) {
po->ifindex = -1;
+ if (po->prot_hook.dev)
+ dev_put(po->prot_hook.dev);
po->prot_hook.dev = NULL;
}
spin_unlock(&po->bind_lock);
@@ -2250,11 +2573,8 @@
case NETDEV_UP:
if (dev->ifindex == po->ifindex) {
spin_lock(&po->bind_lock);
- if (po->num && !po->running) {
- dev_add_pack(&po->prot_hook);
- sock_hold(sk);
- po->running = 1;
- }
+ if (po->num)
+ register_prot_hook(sk);
spin_unlock(&po->bind_lock);
}
break;
@@ -2521,10 +2841,8 @@
was_running = po->running;
num = po->num;
if (was_running) {
- __dev_remove_pack(&po->prot_hook);
po->num = 0;
- po->running = 0;
- __sock_put(sk);
+ __unregister_prot_hook(sk, false);
}
spin_unlock(&po->bind_lock);
@@ -2555,11 +2873,9 @@
mutex_unlock(&po->pg_vec_lock);
spin_lock(&po->bind_lock);
- if (was_running && !po->running) {
- sock_hold(sk);
- po->running = 1;
+ if (was_running) {
po->num = num;
- dev_add_pack(&po->prot_hook);
+ register_prot_hook(sk);
}
spin_unlock(&po->bind_lock);
diff --git a/net/phonet/pn_netlink.c b/net/phonet/pn_netlink.c
index 438accb..d61f676 100644
--- a/net/phonet/pn_netlink.c
+++ b/net/phonet/pn_netlink.c
@@ -289,15 +289,16 @@
int __init phonet_netlink_register(void)
{
- int err = __rtnl_register(PF_PHONET, RTM_NEWADDR, addr_doit, NULL);
+ int err = __rtnl_register(PF_PHONET, RTM_NEWADDR, addr_doit,
+ NULL, NULL);
if (err)
return err;
/* Further __rtnl_register() cannot fail */
- __rtnl_register(PF_PHONET, RTM_DELADDR, addr_doit, NULL);
- __rtnl_register(PF_PHONET, RTM_GETADDR, NULL, getaddr_dumpit);
- __rtnl_register(PF_PHONET, RTM_NEWROUTE, route_doit, NULL);
- __rtnl_register(PF_PHONET, RTM_DELROUTE, route_doit, NULL);
- __rtnl_register(PF_PHONET, RTM_GETROUTE, NULL, route_dumpit);
+ __rtnl_register(PF_PHONET, RTM_DELADDR, addr_doit, NULL, NULL);
+ __rtnl_register(PF_PHONET, RTM_GETADDR, NULL, getaddr_dumpit, NULL);
+ __rtnl_register(PF_PHONET, RTM_NEWROUTE, route_doit, NULL, NULL);
+ __rtnl_register(PF_PHONET, RTM_DELROUTE, route_doit, NULL, NULL);
+ __rtnl_register(PF_PHONET, RTM_GETROUTE, NULL, route_dumpit, NULL);
return 0;
}
diff --git a/net/rds/bind.c b/net/rds/bind.c
index 2f6b3fc..637bde5 100644
--- a/net/rds/bind.c
+++ b/net/rds/bind.c
@@ -35,6 +35,7 @@
#include <linux/in.h>
#include <linux/if_arp.h>
#include <linux/jhash.h>
+#include <linux/ratelimit.h>
#include "rds.h"
#define BIND_HASH_SIZE 1024
@@ -185,8 +186,7 @@
if (!trans) {
ret = -EADDRNOTAVAIL;
rds_remove_bound(rs);
- if (printk_ratelimit())
- printk(KERN_INFO "RDS: rds_bind() could not find a transport, "
+ printk_ratelimited(KERN_INFO "RDS: rds_bind() could not find a transport, "
"load rds_tcp or rds_rdma?\n");
goto out;
}
diff --git a/net/rds/ib.h b/net/rds/ib.h
index 4297d92..edfaaaf 100644
--- a/net/rds/ib.h
+++ b/net/rds/ib.h
@@ -3,6 +3,7 @@
#include <rdma/ib_verbs.h>
#include <rdma/rdma_cm.h>
+#include <linux/interrupt.h>
#include <linux/pci.h>
#include <linux/slab.h>
#include "rds.h"
diff --git a/net/rds/ib_cm.c b/net/rds/ib_cm.c
index fd453dd..cd67026 100644
--- a/net/rds/ib_cm.c
+++ b/net/rds/ib_cm.c
@@ -34,6 +34,7 @@
#include <linux/in.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
+#include <linux/ratelimit.h>
#include "rds.h"
#include "ib.h"
@@ -435,13 +436,12 @@
version = RDS_PROTOCOL_3_0;
while ((common >>= 1) != 0)
version++;
- } else if (printk_ratelimit()) {
- printk(KERN_NOTICE "RDS: Connection from %pI4 using "
+ }
+ printk_ratelimited(KERN_NOTICE "RDS: Connection from %pI4 using "
"incompatible protocol version %u.%u\n",
&dp->dp_saddr,
dp->dp_protocol_major,
dp->dp_protocol_minor);
- }
return version;
}
diff --git a/net/rds/ib_send.c b/net/rds/ib_send.c
index 7c4dce8..e590949 100644
--- a/net/rds/ib_send.c
+++ b/net/rds/ib_send.c
@@ -34,6 +34,7 @@
#include <linux/in.h>
#include <linux/device.h>
#include <linux/dmapool.h>
+#include <linux/ratelimit.h>
#include "rds.h"
#include "ib.h"
@@ -207,8 +208,7 @@
}
break;
default:
- if (printk_ratelimit())
- printk(KERN_NOTICE
+ printk_ratelimited(KERN_NOTICE
"RDS/IB: %s: unexpected opcode 0x%x in WR!\n",
__func__, send->s_wr.opcode);
break;
diff --git a/net/rds/iw.h b/net/rds/iw.h
index 9015192..04ce3b1 100644
--- a/net/rds/iw.h
+++ b/net/rds/iw.h
@@ -1,6 +1,7 @@
#ifndef _RDS_IW_H
#define _RDS_IW_H
+#include <linux/interrupt.h>
#include <rdma/ib_verbs.h>
#include <rdma/rdma_cm.h>
#include "rds.h"
diff --git a/net/rds/iw_cm.c b/net/rds/iw_cm.c
index c12db66..9556d28 100644
--- a/net/rds/iw_cm.c
+++ b/net/rds/iw_cm.c
@@ -34,6 +34,7 @@
#include <linux/in.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
+#include <linux/ratelimit.h>
#include "rds.h"
#include "iw.h"
@@ -258,8 +259,7 @@
*/
rds_iwdev = ib_get_client_data(dev, &rds_iw_client);
if (!rds_iwdev) {
- if (printk_ratelimit())
- printk(KERN_NOTICE "RDS/IW: No client_data for device %s\n",
+ printk_ratelimited(KERN_NOTICE "RDS/IW: No client_data for device %s\n",
dev->name);
return -EOPNOTSUPP;
}
@@ -365,13 +365,12 @@
version = RDS_PROTOCOL_3_0;
while ((common >>= 1) != 0)
version++;
- } else if (printk_ratelimit()) {
- printk(KERN_NOTICE "RDS: Connection from %pI4 using "
+ }
+ printk_ratelimited(KERN_NOTICE "RDS: Connection from %pI4 using "
"incompatible protocol version %u.%u\n",
&dp->dp_saddr,
dp->dp_protocol_major,
dp->dp_protocol_minor);
- }
return version;
}
diff --git a/net/rds/iw_rdma.c b/net/rds/iw_rdma.c
index 6deaa77..8b77edb 100644
--- a/net/rds/iw_rdma.c
+++ b/net/rds/iw_rdma.c
@@ -32,6 +32,7 @@
*/
#include <linux/kernel.h>
#include <linux/slab.h>
+#include <linux/ratelimit.h>
#include "rds.h"
#include "iw.h"
@@ -729,8 +730,8 @@
failed_wr = &f_wr;
ret = ib_post_send(ibmr->cm_id->qp, &f_wr, &failed_wr);
BUG_ON(failed_wr != &f_wr);
- if (ret && printk_ratelimit())
- printk(KERN_WARNING "RDS/IW: %s:%d ib_post_send returned %d\n",
+ if (ret)
+ printk_ratelimited(KERN_WARNING "RDS/IW: %s:%d ib_post_send returned %d\n",
__func__, __LINE__, ret);
return ret;
}
@@ -751,8 +752,8 @@
failed_wr = &s_wr;
ret = ib_post_send(ibmr->cm_id->qp, &s_wr, &failed_wr);
- if (ret && printk_ratelimit()) {
- printk(KERN_WARNING "RDS/IW: %s:%d ib_post_send returned %d\n",
+ if (ret) {
+ printk_ratelimited(KERN_WARNING "RDS/IW: %s:%d ib_post_send returned %d\n",
__func__, __LINE__, ret);
goto out;
}
diff --git a/net/rds/iw_send.c b/net/rds/iw_send.c
index 545d8ee..e40c3c5 100644
--- a/net/rds/iw_send.c
+++ b/net/rds/iw_send.c
@@ -34,6 +34,7 @@
#include <linux/in.h>
#include <linux/device.h>
#include <linux/dmapool.h>
+#include <linux/ratelimit.h>
#include "rds.h"
#include "iw.h"
@@ -258,8 +259,7 @@
* when the SEND completes. */
break;
default:
- if (printk_ratelimit())
- printk(KERN_NOTICE
+ printk_ratelimited(KERN_NOTICE
"RDS/IW: %s: unexpected opcode 0x%x in WR!\n",
__func__, send->s_wr.opcode);
break;
diff --git a/net/rds/send.c b/net/rds/send.c
index d58ae5f..aa57e22 100644
--- a/net/rds/send.c
+++ b/net/rds/send.c
@@ -35,6 +35,7 @@
#include <net/sock.h>
#include <linux/in.h>
#include <linux/list.h>
+#include <linux/ratelimit.h>
#include "rds.h"
@@ -1006,16 +1007,14 @@
goto out;
if (rm->rdma.op_active && !conn->c_trans->xmit_rdma) {
- if (printk_ratelimit())
- printk(KERN_NOTICE "rdma_op %p conn xmit_rdma %p\n",
+ printk_ratelimited(KERN_NOTICE "rdma_op %p conn xmit_rdma %p\n",
&rm->rdma, conn->c_trans->xmit_rdma);
ret = -EOPNOTSUPP;
goto out;
}
if (rm->atomic.op_active && !conn->c_trans->xmit_atomic) {
- if (printk_ratelimit())
- printk(KERN_NOTICE "atomic_op %p conn xmit_atomic %p\n",
+ printk_ratelimited(KERN_NOTICE "atomic_op %p conn xmit_atomic %p\n",
&rm->atomic, conn->c_trans->xmit_atomic);
ret = -EOPNOTSUPP;
goto out;
diff --git a/net/rds/tcp_stats.c b/net/rds/tcp_stats.c
index d5898d0..f8a7954 100644
--- a/net/rds/tcp_stats.c
+++ b/net/rds/tcp_stats.c
@@ -40,7 +40,7 @@
DEFINE_PER_CPU(struct rds_tcp_statistics, rds_tcp_stats)
____cacheline_aligned;
-static const char const *rds_tcp_stat_names[] = {
+static const char * const rds_tcp_stat_names[] = {
"tcp_data_ready_calls",
"tcp_write_space_calls",
"tcp_sndbuf_full",
diff --git a/net/sched/act_api.c b/net/sched/act_api.c
index a606025..2f64262 100644
--- a/net/sched/act_api.c
+++ b/net/sched/act_api.c
@@ -1115,9 +1115,10 @@
static int __init tc_action_init(void)
{
- rtnl_register(PF_UNSPEC, RTM_NEWACTION, tc_ctl_action, NULL);
- rtnl_register(PF_UNSPEC, RTM_DELACTION, tc_ctl_action, NULL);
- rtnl_register(PF_UNSPEC, RTM_GETACTION, tc_ctl_action, tc_dump_action);
+ rtnl_register(PF_UNSPEC, RTM_NEWACTION, tc_ctl_action, NULL, NULL);
+ rtnl_register(PF_UNSPEC, RTM_DELACTION, tc_ctl_action, NULL, NULL);
+ rtnl_register(PF_UNSPEC, RTM_GETACTION, tc_ctl_action, tc_dump_action,
+ NULL);
return 0;
}
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index bb2c523..9563887 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -610,10 +610,10 @@
static int __init tc_filter_init(void)
{
- rtnl_register(PF_UNSPEC, RTM_NEWTFILTER, tc_ctl_tfilter, NULL);
- rtnl_register(PF_UNSPEC, RTM_DELTFILTER, tc_ctl_tfilter, NULL);
+ rtnl_register(PF_UNSPEC, RTM_NEWTFILTER, tc_ctl_tfilter, NULL, NULL);
+ rtnl_register(PF_UNSPEC, RTM_DELTFILTER, tc_ctl_tfilter, NULL, NULL);
rtnl_register(PF_UNSPEC, RTM_GETTFILTER, tc_ctl_tfilter,
- tc_dump_tfilter);
+ tc_dump_tfilter, NULL);
return 0;
}
diff --git a/net/sched/cls_flow.c b/net/sched/cls_flow.c
index 8ec0139..34533a5 100644
--- a/net/sched/cls_flow.c
+++ b/net/sched/cls_flow.c
@@ -121,7 +121,7 @@
if (!pskb_network_may_pull(skb, sizeof(*iph)))
break;
iph = ip_hdr(skb);
- if (iph->frag_off & htons(IP_MF | IP_OFFSET))
+ if (ip_is_fragment(iph))
break;
poff = proto_ports_offset(iph->protocol);
if (poff >= 0 &&
@@ -163,7 +163,7 @@
if (!pskb_network_may_pull(skb, sizeof(*iph)))
break;
iph = ip_hdr(skb);
- if (iph->frag_off & htons(IP_MF | IP_OFFSET))
+ if (ip_is_fragment(iph))
break;
poff = proto_ports_offset(iph->protocol);
if (poff >= 0 &&
diff --git a/net/sched/cls_rsvp.h b/net/sched/cls_rsvp.h
index 402c44b..ed691b1 100644
--- a/net/sched/cls_rsvp.h
+++ b/net/sched/cls_rsvp.h
@@ -167,7 +167,7 @@
dst = &nhptr->daddr;
protocol = nhptr->protocol;
xprt = ((u8 *)nhptr) + (nhptr->ihl<<2);
- if (nhptr->frag_off & htons(IP_MF | IP_OFFSET))
+ if (ip_is_fragment(nhptr))
return -1;
#endif
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c
index 6b86276..8182aef 100644
--- a/net/sched/sch_api.c
+++ b/net/sched/sch_api.c
@@ -1792,12 +1792,12 @@
register_qdisc(&pfifo_head_drop_qdisc_ops);
register_qdisc(&mq_qdisc_ops);
- rtnl_register(PF_UNSPEC, RTM_NEWQDISC, tc_modify_qdisc, NULL);
- rtnl_register(PF_UNSPEC, RTM_DELQDISC, tc_get_qdisc, NULL);
- rtnl_register(PF_UNSPEC, RTM_GETQDISC, tc_get_qdisc, tc_dump_qdisc);
- rtnl_register(PF_UNSPEC, RTM_NEWTCLASS, tc_ctl_tclass, NULL);
- rtnl_register(PF_UNSPEC, RTM_DELTCLASS, tc_ctl_tclass, NULL);
- rtnl_register(PF_UNSPEC, RTM_GETTCLASS, tc_ctl_tclass, tc_dump_tclass);
+ rtnl_register(PF_UNSPEC, RTM_NEWQDISC, tc_modify_qdisc, NULL, NULL);
+ rtnl_register(PF_UNSPEC, RTM_DELQDISC, tc_get_qdisc, NULL, NULL);
+ rtnl_register(PF_UNSPEC, RTM_GETQDISC, tc_get_qdisc, tc_dump_qdisc, NULL);
+ rtnl_register(PF_UNSPEC, RTM_NEWTCLASS, tc_ctl_tclass, NULL, NULL);
+ rtnl_register(PF_UNSPEC, RTM_DELTCLASS, tc_ctl_tclass, NULL, NULL);
+ rtnl_register(PF_UNSPEC, RTM_GETTCLASS, tc_ctl_tclass, tc_dump_tclass, NULL);
return 0;
}
diff --git a/net/sched/sch_atm.c b/net/sched/sch_atm.c
index 3f08158..e25e490 100644
--- a/net/sched/sch_atm.c
+++ b/net/sched/sch_atm.c
@@ -5,6 +5,7 @@
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/string.h>
#include <linux/errno.h>
#include <linux/skbuff.h>
diff --git a/net/sched/sch_choke.c b/net/sched/sch_choke.c
index 06afbae..3422b25 100644
--- a/net/sched/sch_choke.c
+++ b/net/sched/sch_choke.c
@@ -181,7 +181,7 @@
ip1->saddr != ip2->saddr || ip1->daddr != ip2->daddr)
return false;
- if ((ip1->frag_off | ip2->frag_off) & htons(IP_MF | IP_OFFSET))
+ if (ip_is_fragment(ip1) | ip_is_fragment(ip2))
ip_proto = 0;
off1 += ip1->ihl * 4;
off2 += ip2->ihl * 4;
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c
index b4c6809..d253c16 100644
--- a/net/sched/sch_generic.c
+++ b/net/sched/sch_generic.c
@@ -189,15 +189,17 @@
void __qdisc_run(struct Qdisc *q)
{
- unsigned long start_time = jiffies;
+ int quota = weight_p;
+ int work = 0;
while (qdisc_restart(q)) {
+ work++;
/*
- * Postpone processing if
- * 1. another process needs the CPU;
- * 2. we've been doing it for too long.
+ * Ordered by possible occurrence: Postpone processing if
+ * 1. we've exceeded packet quota
+ * 2. another process needs the CPU;
*/
- if (need_resched() || jiffies != start_time) {
+ if (work >= quota || need_resched()) {
__netif_schedule(q);
break;
}
diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c
index 69c35f6..eb3b9a8 100644
--- a/net/sched/sch_netem.c
+++ b/net/sched/sch_netem.c
@@ -13,6 +13,7 @@
* Catalin(ux aka Dino) BOIE <catab at umbrella dot ro>
*/
+#include <linux/mm.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/types.h>
diff --git a/net/sched/sch_sfq.c b/net/sched/sch_sfq.c
index b6ea6af..4536ee6 100644
--- a/net/sched/sch_sfq.c
+++ b/net/sched/sch_sfq.c
@@ -157,7 +157,7 @@
iph = ip_hdr(skb);
h = (__force u32)iph->daddr;
h2 = (__force u32)iph->saddr ^ iph->protocol;
- if (iph->frag_off & htons(IP_MF | IP_OFFSET))
+ if (ip_is_fragment(iph))
break;
poff = proto_ports_offset(iph->protocol);
if (poff >= 0 &&
diff --git a/net/sctp/associola.c b/net/sctp/associola.c
index 4a62888..dc16b90 100644
--- a/net/sctp/associola.c
+++ b/net/sctp/associola.c
@@ -280,6 +280,8 @@
asoc->peer.asconf_capable = 0;
if (sctp_addip_noauth)
asoc->peer.asconf_capable = 1;
+ asoc->asconf_addr_del_pending = NULL;
+ asoc->src_out_of_asoc_ok = 0;
/* Create an input queue. */
sctp_inq_init(&asoc->base.inqueue);
@@ -446,6 +448,10 @@
sctp_asconf_queue_teardown(asoc);
+ /* Free pending address space being deleted */
+ if (asoc->asconf_addr_del_pending != NULL)
+ kfree(asoc->asconf_addr_del_pending);
+
/* AUTH - Free the endpoint shared keys */
sctp_auth_destroy_keys(&asoc->endpoint_shared_keys);
diff --git a/net/sctp/bind_addr.c b/net/sctp/bind_addr.c
index 83e3011..4ece451 100644
--- a/net/sctp/bind_addr.c
+++ b/net/sctp/bind_addr.c
@@ -430,7 +430,7 @@
list_for_each_entry(laddr, &bp->address_list, list) {
addr_buf = (union sctp_addr *)addrs;
for (i = 0; i < addrcnt; i++) {
- addr = (union sctp_addr *)addr_buf;
+ addr = addr_buf;
af = sctp_get_af_specific(addr->v4.sin_family);
if (!af)
break;
@@ -534,6 +534,21 @@
return 0;
}
+int sctp_is_ep_boundall(struct sock *sk)
+{
+ struct sctp_bind_addr *bp;
+ struct sctp_sockaddr_entry *addr;
+
+ bp = &sctp_sk(sk)->ep->base.bind_addr;
+ if (sctp_list_single_entry(&bp->address_list)) {
+ addr = list_entry(bp->address_list.next,
+ struct sctp_sockaddr_entry, list);
+ if (sctp_is_any(sk, &addr->a))
+ return 1;
+ }
+ return 0;
+}
+
/********************************************************************
* 3rd Level Abstractions
********************************************************************/
diff --git a/net/sctp/input.c b/net/sctp/input.c
index 741ed16..b7692aa 100644
--- a/net/sctp/input.c
+++ b/net/sctp/input.c
@@ -510,8 +510,7 @@
* discard the packet.
*/
if (vtag == 0) {
- chunkhdr = (struct sctp_init_chunk *)((void *)sctphdr
- + sizeof(struct sctphdr));
+ chunkhdr = (void *)sctphdr + sizeof(struct sctphdr);
if (len < sizeof(struct sctphdr) + sizeof(sctp_chunkhdr_t)
+ sizeof(__be32) ||
chunkhdr->chunk_hdr.type != SCTP_CID_INIT ||
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
index 0bb0d7c..aabaee4 100644
--- a/net/sctp/ipv6.c
+++ b/net/sctp/ipv6.c
@@ -112,6 +112,7 @@
addr->valid = 1;
spin_lock_bh(&sctp_local_addr_lock);
list_add_tail_rcu(&addr->list, &sctp_local_addr_list);
+ sctp_addr_wq_mgmt(addr, SCTP_ADDR_NEW);
spin_unlock_bh(&sctp_local_addr_lock);
}
break;
@@ -122,6 +123,7 @@
if (addr->a.sa.sa_family == AF_INET6 &&
ipv6_addr_equal(&addr->a.v6.sin6_addr,
&ifa->addr)) {
+ sctp_addr_wq_mgmt(addr, SCTP_ADDR_DEL);
found = 1;
addr->valid = 0;
list_del_rcu(&addr->list);
diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c
index 1c88c89..edc7532 100644
--- a/net/sctp/outqueue.c
+++ b/net/sctp/outqueue.c
@@ -754,6 +754,16 @@
*/
list_for_each_entry_safe(chunk, tmp, &q->control_chunk_list, list) {
+ /* RFC 5061, 5.3
+ * F1) This means that until such time as the ASCONF
+ * containing the add is acknowledged, the sender MUST
+ * NOT use the new IP address as a source for ANY SCTP
+ * packet except on carrying an ASCONF Chunk.
+ */
+ if (asoc->src_out_of_asoc_ok &&
+ chunk->chunk_hdr->type != SCTP_CID_ASCONF)
+ continue;
+
list_del_init(&chunk->list);
/* Pick the right transport to use. */
@@ -881,6 +891,9 @@
}
}
+ if (q->asoc->src_out_of_asoc_ok)
+ goto sctp_flush_out;
+
/* Is it OK to send data chunks? */
switch (asoc->state) {
case SCTP_STATE_COOKIE_ECHOED:
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
index 67380a2..ab5ded2 100644
--- a/net/sctp/protocol.c
+++ b/net/sctp/protocol.c
@@ -503,7 +503,9 @@
sctp_v4_dst_saddr(&dst_saddr, fl4, htons(bp->port));
rcu_read_lock();
list_for_each_entry_rcu(laddr, &bp->address_list, list) {
- if (!laddr->valid || (laddr->state != SCTP_ADDR_SRC))
+ if (!laddr->valid || (laddr->state == SCTP_ADDR_DEL) ||
+ (laddr->state != SCTP_ADDR_SRC &&
+ !asoc->src_out_of_asoc_ok))
continue;
if (sctp_v4_cmp_addr(&dst_saddr, &laddr->a))
goto out_unlock;
@@ -623,6 +625,143 @@
INET_ECN_xmit(sk);
}
+void sctp_addr_wq_timeout_handler(unsigned long arg)
+{
+ struct sctp_sockaddr_entry *addrw, *temp;
+ struct sctp_sock *sp;
+
+ spin_lock_bh(&sctp_addr_wq_lock);
+
+ list_for_each_entry_safe(addrw, temp, &sctp_addr_waitq, list) {
+ SCTP_DEBUG_PRINTK_IPADDR("sctp_addrwq_timo_handler: the first ent in wq %p is ",
+ " for cmd %d at entry %p\n", &sctp_addr_waitq, &addrw->a, addrw->state,
+ addrw);
+
+#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+ /* Now we send an ASCONF for each association */
+ /* Note. we currently don't handle link local IPv6 addressees */
+ if (addrw->a.sa.sa_family == AF_INET6) {
+ struct in6_addr *in6;
+
+ if (ipv6_addr_type(&addrw->a.v6.sin6_addr) &
+ IPV6_ADDR_LINKLOCAL)
+ goto free_next;
+
+ in6 = (struct in6_addr *)&addrw->a.v6.sin6_addr;
+ if (ipv6_chk_addr(&init_net, in6, NULL, 0) == 0 &&
+ addrw->state == SCTP_ADDR_NEW) {
+ unsigned long timeo_val;
+
+ SCTP_DEBUG_PRINTK("sctp_timo_handler: this is on DAD, trying %d sec later\n",
+ SCTP_ADDRESS_TICK_DELAY);
+ timeo_val = jiffies;
+ timeo_val += msecs_to_jiffies(SCTP_ADDRESS_TICK_DELAY);
+ mod_timer(&sctp_addr_wq_timer, timeo_val);
+ break;
+ }
+ }
+#endif
+ list_for_each_entry(sp, &sctp_auto_asconf_splist, auto_asconf_list) {
+ struct sock *sk;
+
+ sk = sctp_opt2sk(sp);
+ /* ignore bound-specific endpoints */
+ if (!sctp_is_ep_boundall(sk))
+ continue;
+ sctp_bh_lock_sock(sk);
+ if (sctp_asconf_mgmt(sp, addrw) < 0)
+ SCTP_DEBUG_PRINTK("sctp_addrwq_timo_handler: sctp_asconf_mgmt failed\n");
+ sctp_bh_unlock_sock(sk);
+ }
+free_next:
+ list_del(&addrw->list);
+ kfree(addrw);
+ }
+ spin_unlock_bh(&sctp_addr_wq_lock);
+}
+
+static void sctp_free_addr_wq(void)
+{
+ struct sctp_sockaddr_entry *addrw;
+ struct sctp_sockaddr_entry *temp;
+
+ spin_lock_bh(&sctp_addr_wq_lock);
+ del_timer(&sctp_addr_wq_timer);
+ list_for_each_entry_safe(addrw, temp, &sctp_addr_waitq, list) {
+ list_del(&addrw->list);
+ kfree(addrw);
+ }
+ spin_unlock_bh(&sctp_addr_wq_lock);
+}
+
+/* lookup the entry for the same address in the addr_waitq
+ * sctp_addr_wq MUST be locked
+ */
+static struct sctp_sockaddr_entry *sctp_addr_wq_lookup(struct sctp_sockaddr_entry *addr)
+{
+ struct sctp_sockaddr_entry *addrw;
+
+ list_for_each_entry(addrw, &sctp_addr_waitq, list) {
+ if (addrw->a.sa.sa_family != addr->a.sa.sa_family)
+ continue;
+ if (addrw->a.sa.sa_family == AF_INET) {
+ if (addrw->a.v4.sin_addr.s_addr ==
+ addr->a.v4.sin_addr.s_addr)
+ return addrw;
+ } else if (addrw->a.sa.sa_family == AF_INET6) {
+ if (ipv6_addr_equal(&addrw->a.v6.sin6_addr,
+ &addr->a.v6.sin6_addr))
+ return addrw;
+ }
+ }
+ return NULL;
+}
+
+void sctp_addr_wq_mgmt(struct sctp_sockaddr_entry *addr, int cmd)
+{
+ struct sctp_sockaddr_entry *addrw;
+ unsigned long timeo_val;
+
+ /* first, we check if an opposite message already exist in the queue.
+ * If we found such message, it is removed.
+ * This operation is a bit stupid, but the DHCP client attaches the
+ * new address after a couple of addition and deletion of that address
+ */
+
+ spin_lock_bh(&sctp_addr_wq_lock);
+ /* Offsets existing events in addr_wq */
+ addrw = sctp_addr_wq_lookup(addr);
+ if (addrw) {
+ if (addrw->state != cmd) {
+ SCTP_DEBUG_PRINTK_IPADDR("sctp_addr_wq_mgmt offsets existing entry for %d ",
+ " in wq %p\n", addrw->state, &addrw->a,
+ &sctp_addr_waitq);
+ list_del(&addrw->list);
+ kfree(addrw);
+ }
+ spin_unlock_bh(&sctp_addr_wq_lock);
+ return;
+ }
+
+ /* OK, we have to add the new address to the wait queue */
+ addrw = kmemdup(addr, sizeof(struct sctp_sockaddr_entry), GFP_ATOMIC);
+ if (addrw == NULL) {
+ spin_unlock_bh(&sctp_addr_wq_lock);
+ return;
+ }
+ addrw->state = cmd;
+ list_add_tail(&addrw->list, &sctp_addr_waitq);
+ SCTP_DEBUG_PRINTK_IPADDR("sctp_addr_wq_mgmt add new entry for cmd:%d ",
+ " in wq %p\n", addrw->state, &addrw->a, &sctp_addr_waitq);
+
+ if (!timer_pending(&sctp_addr_wq_timer)) {
+ timeo_val = jiffies;
+ timeo_val += msecs_to_jiffies(SCTP_ADDRESS_TICK_DELAY);
+ mod_timer(&sctp_addr_wq_timer, timeo_val);
+ }
+ spin_unlock_bh(&sctp_addr_wq_lock);
+}
+
/* Event handler for inet address addition/deletion events.
* The sctp_local_addr_list needs to be protocted by a spin lock since
* multiple notifiers (say IPv4 and IPv6) may be running at the same
@@ -650,6 +789,7 @@
addr->valid = 1;
spin_lock_bh(&sctp_local_addr_lock);
list_add_tail_rcu(&addr->list, &sctp_local_addr_list);
+ sctp_addr_wq_mgmt(addr, SCTP_ADDR_NEW);
spin_unlock_bh(&sctp_local_addr_lock);
}
break;
@@ -660,6 +800,7 @@
if (addr->a.sa.sa_family == AF_INET &&
addr->a.v4.sin_addr.s_addr ==
ifa->ifa_local) {
+ sctp_addr_wq_mgmt(addr, SCTP_ADDR_DEL);
found = 1;
addr->valid = 0;
list_del_rcu(&addr->list);
@@ -1242,6 +1383,7 @@
/* Disable ADDIP by default. */
sctp_addip_enable = 0;
sctp_addip_noauth = 0;
+ sctp_default_auto_asconf = 0;
/* Enable PR-SCTP by default. */
sctp_prsctp_enable = 1;
@@ -1266,6 +1408,13 @@
spin_lock_init(&sctp_local_addr_lock);
sctp_get_local_addr_list();
+ /* Initialize the address event list */
+ INIT_LIST_HEAD(&sctp_addr_waitq);
+ INIT_LIST_HEAD(&sctp_auto_asconf_splist);
+ spin_lock_init(&sctp_addr_wq_lock);
+ sctp_addr_wq_timer.expires = 0;
+ setup_timer(&sctp_addr_wq_timer, sctp_addr_wq_timeout_handler, 0);
+
status = sctp_v4_protosw_init();
if (status)
@@ -1337,6 +1486,7 @@
/* Unregister with inet6/inet layers. */
sctp_v6_del_protocol();
sctp_v4_del_protocol();
+ sctp_free_addr_wq();
/* Free the control endpoint. */
inet_ctl_sock_destroy(sctp_ctl_sock);
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
index 58eb27f..81db4e3 100644
--- a/net/sctp/sm_make_chunk.c
+++ b/net/sctp/sm_make_chunk.c
@@ -2768,11 +2768,12 @@
int addr_param_len = 0;
int totallen = 0;
int i;
+ int del_pickup = 0;
/* Get total length of all the address parameters. */
addr_buf = addrs;
for (i = 0; i < addrcnt; i++) {
- addr = (union sctp_addr *)addr_buf;
+ addr = addr_buf;
af = sctp_get_af_specific(addr->v4.sin_family);
addr_param_len = af->to_addr_param(addr, &addr_param);
@@ -2780,6 +2781,13 @@
totallen += addr_param_len;
addr_buf += af->sockaddr_len;
+ if (asoc->asconf_addr_del_pending && !del_pickup) {
+ /* reuse the parameter length from the same scope one */
+ totallen += paramlen;
+ totallen += addr_param_len;
+ del_pickup = 1;
+ SCTP_DEBUG_PRINTK("mkasconf_update_ip: picked same-scope del_pending addr, totallen for all addresses is %d\n", totallen);
+ }
}
/* Create an asconf chunk with the required length. */
@@ -2790,7 +2798,7 @@
/* Add the address parameters to the asconf chunk. */
addr_buf = addrs;
for (i = 0; i < addrcnt; i++) {
- addr = (union sctp_addr *)addr_buf;
+ addr = addr_buf;
af = sctp_get_af_specific(addr->v4.sin_family);
addr_param_len = af->to_addr_param(addr, &addr_param);
param.param_hdr.type = flags;
@@ -2802,6 +2810,17 @@
addr_buf += af->sockaddr_len;
}
+ if (flags == SCTP_PARAM_ADD_IP && del_pickup) {
+ addr = asoc->asconf_addr_del_pending;
+ af = sctp_get_af_specific(addr->v4.sin_family);
+ addr_param_len = af->to_addr_param(addr, &addr_param);
+ param.param_hdr.type = SCTP_PARAM_DEL_IP;
+ param.param_hdr.length = htons(paramlen + addr_param_len);
+ param.crr_id = i;
+
+ sctp_addto_chunk(retval, paramlen, ¶m);
+ sctp_addto_chunk(retval, addr_param_len, &addr_param);
+ }
return retval;
}
@@ -2939,8 +2958,7 @@
union sctp_addr addr;
union sctp_addr_param *addr_param;
- addr_param = (union sctp_addr_param *)
- ((void *)asconf_param + sizeof(sctp_addip_param_t));
+ addr_param = (void *)asconf_param + sizeof(sctp_addip_param_t);
if (asconf_param->param_hdr.type != SCTP_PARAM_ADD_IP &&
asconf_param->param_hdr.type != SCTP_PARAM_DEL_IP &&
@@ -3014,7 +3032,7 @@
* an Error Cause TLV set to the new error code 'Request to
* Delete Source IP Address'
*/
- if (sctp_cmp_addr_exact(sctp_source(asconf), &addr))
+ if (sctp_cmp_addr_exact(&asconf->source, &addr))
return SCTP_ERROR_DEL_SRC_IP;
/* Section 4.2.2
@@ -3125,7 +3143,7 @@
* asconf parameter.
*/
length = ntohs(addr_param->p.length);
- asconf_param = (sctp_addip_param_t *)((void *)addr_param + length);
+ asconf_param = (void *)addr_param + length;
chunk_len -= length;
/* create an ASCONF_ACK chunk.
@@ -3166,8 +3184,7 @@
/* Move to the next ASCONF param. */
length = ntohs(asconf_param->param_hdr.length);
- asconf_param = (sctp_addip_param_t *)((void *)asconf_param +
- length);
+ asconf_param = (void *)asconf_param + length;
chunk_len -= length;
}
@@ -3197,8 +3214,7 @@
struct sctp_transport *transport;
struct sctp_sockaddr_entry *saddr;
- addr_param = (union sctp_addr_param *)
- ((void *)asconf_param + sizeof(sctp_addip_param_t));
+ addr_param = (void *)asconf_param + sizeof(sctp_addip_param_t);
/* We have checked the packet before, so we do not check again. */
af = sctp_get_af_specific(param_type2af(addr_param->p.type));
@@ -3224,6 +3240,11 @@
case SCTP_PARAM_DEL_IP:
local_bh_disable();
sctp_del_bind_addr(bp, &addr);
+ if (asoc->asconf_addr_del_pending != NULL &&
+ sctp_cmp_addr_exact(asoc->asconf_addr_del_pending, &addr)) {
+ kfree(asoc->asconf_addr_del_pending);
+ asoc->asconf_addr_del_pending = NULL;
+ }
local_bh_enable();
list_for_each_entry(transport, &asoc->peer.transport_addr_list,
transports) {
@@ -3278,8 +3299,7 @@
return SCTP_ERROR_NO_ERROR;
case SCTP_PARAM_ERR_CAUSE:
length = sizeof(sctp_addip_param_t);
- err_param = (sctp_errhdr_t *)
- ((void *)asconf_ack_param + length);
+ err_param = (void *)asconf_ack_param + length;
asconf_ack_len -= length;
if (asconf_ack_len > 0)
return err_param->cause;
@@ -3292,8 +3312,7 @@
}
length = ntohs(asconf_ack_param->param_hdr.length);
- asconf_ack_param = (sctp_addip_param_t *)
- ((void *)asconf_ack_param + length);
+ asconf_ack_param = (void *)asconf_ack_param + length;
asconf_ack_len -= length;
}
@@ -3325,7 +3344,7 @@
* pointer to the first asconf parameter.
*/
length = ntohs(addr_param->p.length);
- asconf_param = (sctp_addip_param_t *)((void *)addr_param + length);
+ asconf_param = (void *)addr_param + length;
asconf_len -= length;
/* ADDIP 4.1
@@ -3376,11 +3395,13 @@
* one.
*/
length = ntohs(asconf_param->param_hdr.length);
- asconf_param = (sctp_addip_param_t *)((void *)asconf_param +
- length);
+ asconf_param = (void *)asconf_param + length;
asconf_len -= length;
}
+ if (no_err && asoc->src_out_of_asoc_ok)
+ asoc->src_out_of_asoc_ok = 0;
+
/* Free the cached last sent asconf chunk. */
list_del_init(&asconf->transmitted_list);
sctp_chunk_free(asconf);
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c
index 534c2e5..1b2bb64 100644
--- a/net/sctp/sm_sideeffect.c
+++ b/net/sctp/sm_sideeffect.c
@@ -1201,7 +1201,7 @@
int local_cork = 0;
if (SCTP_EVENT_T_TIMEOUT != event_type)
- chunk = (struct sctp_chunk *) event_arg;
+ chunk = event_arg;
/* Note: This whole file is a huge candidate for rework.
* For example, each command could either have its own handler, so
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index a297283..7d00b17 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -4008,31 +4008,32 @@
auth_hdr = (struct sctp_authhdr *)chunk->skb->data;
error = sctp_sf_authenticate(ep, asoc, type, chunk);
switch (error) {
- case SCTP_IERROR_AUTH_BAD_HMAC:
- /* Generate the ERROR chunk and discard the rest
- * of the packet
- */
- err_chunk = sctp_make_op_error(asoc, chunk,
- SCTP_ERROR_UNSUP_HMAC,
- &auth_hdr->hmac_id,
- sizeof(__u16), 0);
- if (err_chunk) {
- sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,
- SCTP_CHUNK(err_chunk));
- }
- /* Fall Through */
- case SCTP_IERROR_AUTH_BAD_KEYID:
- case SCTP_IERROR_BAD_SIG:
- return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
- break;
- case SCTP_IERROR_PROTO_VIOLATION:
- return sctp_sf_violation_chunklen(ep, asoc, type, arg,
- commands);
- break;
- case SCTP_IERROR_NOMEM:
- return SCTP_DISPOSITION_NOMEM;
- default:
- break;
+ case SCTP_IERROR_AUTH_BAD_HMAC:
+ /* Generate the ERROR chunk and discard the rest
+ * of the packet
+ */
+ err_chunk = sctp_make_op_error(asoc, chunk,
+ SCTP_ERROR_UNSUP_HMAC,
+ &auth_hdr->hmac_id,
+ sizeof(__u16), 0);
+ if (err_chunk) {
+ sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,
+ SCTP_CHUNK(err_chunk));
+ }
+ /* Fall Through */
+ case SCTP_IERROR_AUTH_BAD_KEYID:
+ case SCTP_IERROR_BAD_SIG:
+ return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
+
+ case SCTP_IERROR_PROTO_VIOLATION:
+ return sctp_sf_violation_chunklen(ep, asoc, type, arg,
+ commands);
+
+ case SCTP_IERROR_NOMEM:
+ return SCTP_DISPOSITION_NOMEM;
+
+ default: /* Prevent gcc warnings */
+ break;
}
if (asoc->active_key_id != ntohs(auth_hdr->shkey_id)) {
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 6766913..1c6aec1 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -476,7 +476,7 @@
/* The list may contain either IPv4 or IPv6 address;
* determine the address length for walking thru the list.
*/
- sa_addr = (struct sockaddr *)addr_buf;
+ sa_addr = addr_buf;
af = sctp_get_af_specific(sa_addr->sa_family);
if (!af) {
retval = -EINVAL;
@@ -555,7 +555,7 @@
*/
addr_buf = addrs;
for (i = 0; i < addrcnt; i++) {
- addr = (union sctp_addr *)addr_buf;
+ addr = addr_buf;
af = sctp_get_af_specific(addr->v4.sin_family);
if (!af) {
retval = -EINVAL;
@@ -583,22 +583,35 @@
goto out;
}
- retval = sctp_send_asconf(asoc, chunk);
- if (retval)
- goto out;
-
/* Add the new addresses to the bind address list with
* use_as_src set to 0.
*/
addr_buf = addrs;
for (i = 0; i < addrcnt; i++) {
- addr = (union sctp_addr *)addr_buf;
+ addr = addr_buf;
af = sctp_get_af_specific(addr->v4.sin_family);
memcpy(&saveaddr, addr, af->sockaddr_len);
retval = sctp_add_bind_addr(bp, &saveaddr,
SCTP_ADDR_NEW, GFP_ATOMIC);
addr_buf += af->sockaddr_len;
}
+ if (asoc->src_out_of_asoc_ok) {
+ struct sctp_transport *trans;
+
+ list_for_each_entry(trans,
+ &asoc->peer.transport_addr_list, transports) {
+ /* Clear the source and route cache */
+ dst_release(trans->dst);
+ trans->cwnd = min(4*asoc->pathmtu, max_t(__u32,
+ 2*asoc->pathmtu, 4380));
+ trans->ssthresh = asoc->peer.i.a_rwnd;
+ trans->rto = asoc->rto_initial;
+ trans->rtt = trans->srtt = trans->rttvar = 0;
+ sctp_transport_route(trans, NULL,
+ sctp_sk(asoc->base.sk));
+ }
+ }
+ retval = sctp_send_asconf(asoc, chunk);
}
out:
@@ -646,7 +659,7 @@
goto err_bindx_rem;
}
- sa_addr = (union sctp_addr *)addr_buf;
+ sa_addr = addr_buf;
af = sctp_get_af_specific(sa_addr->sa.sa_family);
if (!af) {
retval = -EINVAL;
@@ -715,7 +728,9 @@
struct sctp_sockaddr_entry *saddr;
int i;
int retval = 0;
+ int stored = 0;
+ chunk = NULL;
if (!sctp_addip_enable)
return retval;
@@ -743,7 +758,7 @@
*/
addr_buf = addrs;
for (i = 0; i < addrcnt; i++) {
- laddr = (union sctp_addr *)addr_buf;
+ laddr = addr_buf;
af = sctp_get_af_specific(laddr->v4.sin_family);
if (!af) {
retval = -EINVAL;
@@ -766,8 +781,37 @@
bp = &asoc->base.bind_addr;
laddr = sctp_find_unmatch_addr(bp, (union sctp_addr *)addrs,
addrcnt, sp);
- if (!laddr)
- continue;
+ if ((laddr == NULL) && (addrcnt == 1)) {
+ if (asoc->asconf_addr_del_pending)
+ continue;
+ asoc->asconf_addr_del_pending =
+ kzalloc(sizeof(union sctp_addr), GFP_ATOMIC);
+ if (asoc->asconf_addr_del_pending == NULL) {
+ retval = -ENOMEM;
+ goto out;
+ }
+ asoc->asconf_addr_del_pending->sa.sa_family =
+ addrs->sa_family;
+ asoc->asconf_addr_del_pending->v4.sin_port =
+ htons(bp->port);
+ if (addrs->sa_family == AF_INET) {
+ struct sockaddr_in *sin;
+
+ sin = (struct sockaddr_in *)addrs;
+ asoc->asconf_addr_del_pending->v4.sin_addr.s_addr = sin->sin_addr.s_addr;
+ } else if (addrs->sa_family == AF_INET6) {
+ struct sockaddr_in6 *sin6;
+
+ sin6 = (struct sockaddr_in6 *)addrs;
+ ipv6_addr_copy(&asoc->asconf_addr_del_pending->v6.sin6_addr, &sin6->sin6_addr);
+ }
+ SCTP_DEBUG_PRINTK_IPADDR("send_asconf_del_ip: keep the last address asoc: %p ",
+ " at %p\n", asoc, asoc->asconf_addr_del_pending,
+ asoc->asconf_addr_del_pending);
+ asoc->src_out_of_asoc_ok = 1;
+ stored = 1;
+ goto skip_mkasconf;
+ }
/* We do not need RCU protection throughout this loop
* because this is done under a socket lock from the
@@ -780,12 +824,13 @@
goto out;
}
+skip_mkasconf:
/* Reset use_as_src flag for the addresses in the bind address
* list that are to be deleted.
*/
addr_buf = addrs;
for (i = 0; i < addrcnt; i++) {
- laddr = (union sctp_addr *)addr_buf;
+ laddr = addr_buf;
af = sctp_get_af_specific(laddr->v4.sin_family);
list_for_each_entry(saddr, &bp->address_list, list) {
if (sctp_cmp_addr_exact(&saddr->a, laddr))
@@ -805,12 +850,37 @@
sctp_sk(asoc->base.sk));
}
+ if (stored)
+ /* We don't need to transmit ASCONF */
+ continue;
retval = sctp_send_asconf(asoc, chunk);
}
out:
return retval;
}
+/* set addr events to assocs in the endpoint. ep and addr_wq must be locked */
+int sctp_asconf_mgmt(struct sctp_sock *sp, struct sctp_sockaddr_entry *addrw)
+{
+ struct sock *sk = sctp_opt2sk(sp);
+ union sctp_addr *addr;
+ struct sctp_af *af;
+
+ /* It is safe to write port space in caller. */
+ addr = &addrw->a;
+ addr->v4.sin_port = htons(sp->ep->base.bind_addr.port);
+ af = sctp_get_af_specific(addr->sa.sa_family);
+ if (!af)
+ return -EINVAL;
+ if (sctp_verify_addr(sk, addr, af->sockaddr_len))
+ return -EINVAL;
+
+ if (addrw->state == SCTP_ADDR_NEW)
+ return sctp_send_asconf_add_ip(sk, (struct sockaddr *)addr, 1);
+ else
+ return sctp_send_asconf_del_ip(sk, (struct sockaddr *)addr, 1);
+}
+
/* Helper for tunneling sctp_bindx() requests through sctp_setsockopt()
*
* API 8.1
@@ -927,7 +997,7 @@
return -EINVAL;
}
- sa_addr = (struct sockaddr *)addr_buf;
+ sa_addr = addr_buf;
af = sctp_get_af_specific(sa_addr->sa_family);
/* If the address family is not supported or if this address
@@ -1018,7 +1088,7 @@
goto out_free;
}
- sa_addr = (union sctp_addr *)addr_buf;
+ sa_addr = addr_buf;
af = sctp_get_af_specific(sa_addr->sa.sa_family);
/* If the address family is not supported or if this address
@@ -3187,11 +3257,11 @@
return -EFAULT;
switch (val.sauth_chunk) {
- case SCTP_CID_INIT:
- case SCTP_CID_INIT_ACK:
- case SCTP_CID_SHUTDOWN_COMPLETE:
- case SCTP_CID_AUTH:
- return -EINVAL;
+ case SCTP_CID_INIT:
+ case SCTP_CID_INIT_ACK:
+ case SCTP_CID_SHUTDOWN_COMPLETE:
+ case SCTP_CID_AUTH:
+ return -EINVAL;
}
/* add this chunk id to the endpoint */
@@ -3334,6 +3404,46 @@
}
+/*
+ * 8.1.23 SCTP_AUTO_ASCONF
+ *
+ * This option will enable or disable the use of the automatic generation of
+ * ASCONF chunks to add and delete addresses to an existing association. Note
+ * that this option has two caveats namely: a) it only affects sockets that
+ * are bound to all addresses available to the SCTP stack, and b) the system
+ * administrator may have an overriding control that turns the ASCONF feature
+ * off no matter what setting the socket option may have.
+ * This option expects an integer boolean flag, where a non-zero value turns on
+ * the option, and a zero value turns off the option.
+ * Note. In this implementation, socket operation overrides default parameter
+ * being set by sysctl as well as FreeBSD implementation
+ */
+static int sctp_setsockopt_auto_asconf(struct sock *sk, char __user *optval,
+ unsigned int optlen)
+{
+ int val;
+ struct sctp_sock *sp = sctp_sk(sk);
+
+ if (optlen < sizeof(int))
+ return -EINVAL;
+ if (get_user(val, (int __user *)optval))
+ return -EFAULT;
+ if (!sctp_is_ep_boundall(sk) && val)
+ return -EINVAL;
+ if ((val && sp->do_auto_asconf) || (!val && !sp->do_auto_asconf))
+ return 0;
+
+ if (val == 0 && sp->do_auto_asconf) {
+ list_del(&sp->auto_asconf_list);
+ sp->do_auto_asconf = 0;
+ } else if (val && !sp->do_auto_asconf) {
+ list_add_tail(&sp->auto_asconf_list,
+ &sctp_auto_asconf_splist);
+ sp->do_auto_asconf = 1;
+ }
+ return 0;
+}
+
/* API 6.2 setsockopt(), getsockopt()
*
@@ -3481,6 +3591,9 @@
case SCTP_AUTH_DELETE_KEY:
retval = sctp_setsockopt_del_key(sk, optval, optlen);
break;
+ case SCTP_AUTO_ASCONF:
+ retval = sctp_setsockopt_auto_asconf(sk, optval, optlen);
+ break;
default:
retval = -ENOPROTOOPT;
break;
@@ -3763,6 +3876,12 @@
local_bh_disable();
percpu_counter_inc(&sctp_sockets_allocated);
sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1);
+ if (sctp_default_auto_asconf) {
+ list_add_tail(&sp->auto_asconf_list,
+ &sctp_auto_asconf_splist);
+ sp->do_auto_asconf = 1;
+ } else
+ sp->do_auto_asconf = 0;
local_bh_enable();
return 0;
@@ -3771,13 +3890,17 @@
/* Cleanup any SCTP per socket resources. */
SCTP_STATIC void sctp_destroy_sock(struct sock *sk)
{
- struct sctp_endpoint *ep;
+ struct sctp_sock *sp;
SCTP_DEBUG_PRINTK("sctp_destroy_sock(sk: %p)\n", sk);
/* Release our hold on the endpoint. */
- ep = sctp_sk(sk)->ep;
- sctp_endpoint_free(ep);
+ sp = sctp_sk(sk);
+ if (sp->do_auto_asconf) {
+ sp->do_auto_asconf = 0;
+ list_del(&sp->auto_asconf_list);
+ }
+ sctp_endpoint_free(sp->ep);
local_bh_disable();
percpu_counter_dec(&sctp_sockets_allocated);
sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1);
@@ -5277,6 +5400,28 @@
}
/*
+ * 8.1.23 SCTP_AUTO_ASCONF
+ * See the corresponding setsockopt entry as description
+ */
+static int sctp_getsockopt_auto_asconf(struct sock *sk, int len,
+ char __user *optval, int __user *optlen)
+{
+ int val = 0;
+
+ if (len < sizeof(int))
+ return -EINVAL;
+
+ len = sizeof(int);
+ if (sctp_sk(sk)->do_auto_asconf && sctp_is_ep_boundall(sk))
+ val = 1;
+ if (put_user(len, optlen))
+ return -EFAULT;
+ if (copy_to_user(optval, &val, len))
+ return -EFAULT;
+ return 0;
+}
+
+/*
* 8.2.6. Get the Current Identifiers of Associations
* (SCTP_GET_ASSOC_ID_LIST)
*
@@ -5460,6 +5605,9 @@
case SCTP_GET_ASSOC_ID_LIST:
retval = sctp_getsockopt_assoc_ids(sk, len, optval, optlen);
break;
+ case SCTP_AUTO_ASCONF:
+ retval = sctp_getsockopt_auto_asconf(sk, len, optval, optlen);
+ break;
default:
retval = -ENOPROTOOPT;
break;
@@ -6512,6 +6660,7 @@
struct sk_buff *skb, *tmp;
struct sctp_ulpevent *event;
struct sctp_bind_hashbucket *head;
+ struct list_head tmplist;
/* Migrate socket buffer sizes and all the socket level options to the
* new socket.
@@ -6519,7 +6668,12 @@
newsk->sk_sndbuf = oldsk->sk_sndbuf;
newsk->sk_rcvbuf = oldsk->sk_rcvbuf;
/* Brute force copy old sctp opt. */
- inet_sk_copy_descendant(newsk, oldsk);
+ if (oldsp->do_auto_asconf) {
+ memcpy(&tmplist, &newsp->auto_asconf_list, sizeof(tmplist));
+ inet_sk_copy_descendant(newsk, oldsk);
+ memcpy(&newsp->auto_asconf_list, &tmplist, sizeof(tmplist));
+ } else
+ inet_sk_copy_descendant(newsk, oldsk);
/* Restore the ep value that was overwritten with the above structure
* copy.
diff --git a/net/sctp/sysctl.c b/net/sctp/sysctl.c
index 50cb57f..6b39529 100644
--- a/net/sctp/sysctl.c
+++ b/net/sctp/sysctl.c
@@ -183,6 +183,13 @@
.proc_handler = proc_dointvec,
},
{
+ .procname = "default_auto_asconf",
+ .data = &sctp_default_auto_asconf,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = proc_dointvec,
+ },
+ {
.procname = "prsctp_enable",
.data = &sctp_prsctp_enable,
.maxlen = sizeof(int),
diff --git a/net/sunrpc/auth.c b/net/sunrpc/auth.c
index cd6e4aa..727e506 100644
--- a/net/sunrpc/auth.c
+++ b/net/sunrpc/auth.c
@@ -626,7 +626,7 @@
if (err < 0)
goto out;
cred = task->tk_rqstp->rq_cred;
- };
+ }
dprintk("RPC: %5u refreshing %s cred %p\n",
task->tk_pid, cred->cr_auth->au_ops->au_name, cred);
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
index 5daf6cc..364eb45 100644
--- a/net/sunrpc/auth_gss/auth_gss.c
+++ b/net/sunrpc/auth_gss/auth_gss.c
@@ -1421,18 +1421,16 @@
goto out;
}
switch (gss_cred->gc_service) {
- case RPC_GSS_SVC_NONE:
- gss_wrap_req_encode(encode, rqstp, p, obj);
- status = 0;
- break;
- case RPC_GSS_SVC_INTEGRITY:
- status = gss_wrap_req_integ(cred, ctx, encode,
- rqstp, p, obj);
- break;
- case RPC_GSS_SVC_PRIVACY:
- status = gss_wrap_req_priv(cred, ctx, encode,
- rqstp, p, obj);
- break;
+ case RPC_GSS_SVC_NONE:
+ gss_wrap_req_encode(encode, rqstp, p, obj);
+ status = 0;
+ break;
+ case RPC_GSS_SVC_INTEGRITY:
+ status = gss_wrap_req_integ(cred, ctx, encode, rqstp, p, obj);
+ break;
+ case RPC_GSS_SVC_PRIVACY:
+ status = gss_wrap_req_priv(cred, ctx, encode, rqstp, p, obj);
+ break;
}
out:
gss_put_ctx(ctx);
@@ -1531,18 +1529,18 @@
if (ctx->gc_proc != RPC_GSS_PROC_DATA)
goto out_decode;
switch (gss_cred->gc_service) {
- case RPC_GSS_SVC_NONE:
- break;
- case RPC_GSS_SVC_INTEGRITY:
- status = gss_unwrap_resp_integ(cred, ctx, rqstp, &p);
- if (status)
- goto out;
- break;
- case RPC_GSS_SVC_PRIVACY:
- status = gss_unwrap_resp_priv(cred, ctx, rqstp, &p);
- if (status)
- goto out;
- break;
+ case RPC_GSS_SVC_NONE:
+ break;
+ case RPC_GSS_SVC_INTEGRITY:
+ status = gss_unwrap_resp_integ(cred, ctx, rqstp, &p);
+ if (status)
+ goto out;
+ break;
+ case RPC_GSS_SVC_PRIVACY:
+ status = gss_unwrap_resp_priv(cred, ctx, rqstp, &p);
+ if (status)
+ goto out;
+ break;
}
/* take into account extra slack for integrity and privacy cases: */
cred->cr_auth->au_rslack = cred->cr_auth->au_verfsize + (p - savedp)
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index 8c91415..7389b7d 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -1666,19 +1666,18 @@
if (--len < 0)
goto out_overflow;
switch ((n = ntohl(*p++))) {
- case RPC_AUTH_ERROR:
- break;
- case RPC_MISMATCH:
- dprintk("RPC: %5u %s: RPC call version "
- "mismatch!\n",
- task->tk_pid, __func__);
- error = -EPROTONOSUPPORT;
- goto out_err;
- default:
- dprintk("RPC: %5u %s: RPC call rejected, "
- "unknown error: %x\n",
- task->tk_pid, __func__, n);
- goto out_eio;
+ case RPC_AUTH_ERROR:
+ break;
+ case RPC_MISMATCH:
+ dprintk("RPC: %5u %s: RPC call version mismatch!\n",
+ task->tk_pid, __func__);
+ error = -EPROTONOSUPPORT;
+ goto out_err;
+ default:
+ dprintk("RPC: %5u %s: RPC call rejected, "
+ "unknown error: %x\n",
+ task->tk_pid, __func__, n);
+ goto out_eio;
}
if (--len < 0)
goto out_overflow;
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c
index 72bc536..b181e34 100644
--- a/net/sunrpc/rpc_pipe.c
+++ b/net/sunrpc/rpc_pipe.c
@@ -456,13 +456,13 @@
inode->i_ino = get_next_ino();
inode->i_mode = mode;
inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
- switch(mode & S_IFMT) {
- case S_IFDIR:
- inode->i_fop = &simple_dir_operations;
- inode->i_op = &simple_dir_inode_operations;
- inc_nlink(inode);
- default:
- break;
+ switch (mode & S_IFMT) {
+ case S_IFDIR:
+ inode->i_fop = &simple_dir_operations;
+ inode->i_op = &simple_dir_inode_operations;
+ inc_nlink(inode);
+ default:
+ break;
}
return inode;
}
diff --git a/net/sunrpc/xprtrdma/svc_rdma_transport.c b/net/sunrpc/xprtrdma/svc_rdma_transport.c
index c3c232a..a385430 100644
--- a/net/sunrpc/xprtrdma/svc_rdma_transport.c
+++ b/net/sunrpc/xprtrdma/svc_rdma_transport.c
@@ -42,6 +42,7 @@
#include <linux/sunrpc/svc_xprt.h>
#include <linux/sunrpc/debug.h>
#include <linux/sunrpc/rpc_rdma.h>
+#include <linux/interrupt.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
diff --git a/net/sunrpc/xprtrdma/verbs.c b/net/sunrpc/xprtrdma/verbs.c
index 80f8da3..28236ba 100644
--- a/net/sunrpc/xprtrdma/verbs.c
+++ b/net/sunrpc/xprtrdma/verbs.c
@@ -47,6 +47,7 @@
* o buffer memory
*/
+#include <linux/interrupt.h>
#include <linux/pci.h> /* for Tavor hack below */
#include <linux/slab.h>
diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c
index fa68d1e..759b318 100644
--- a/net/tipc/bcast.c
+++ b/net/tipc/bcast.c
@@ -552,12 +552,16 @@
if (likely(!msg_non_seq(buf_msg(buf)))) {
struct tipc_msg *msg;
- assert(tipc_bcast_nmap.count != 0);
bcbuf_set_acks(buf, tipc_bcast_nmap.count);
msg = buf_msg(buf);
msg_set_non_seq(msg, 1);
msg_set_mc_netid(msg, tipc_net_id);
bcl->stats.sent_info++;
+
+ if (WARN_ON(!tipc_bcast_nmap.count)) {
+ dump_stack();
+ return 0;
+ }
}
/* Send buffer over bearers until all targets reached */
diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c
index 85209ea..85eba9c 100644
--- a/net/tipc/bearer.c
+++ b/net/tipc/bearer.c
@@ -402,7 +402,6 @@
void tipc_continue(struct tipc_bearer *b_ptr)
{
spin_lock_bh(&b_ptr->lock);
- b_ptr->continue_count++;
if (!list_empty(&b_ptr->cong_links))
tipc_k_signal((Handler)tipc_bearer_lock_push, (unsigned long)b_ptr);
b_ptr->blocked = 0;
diff --git a/net/tipc/bearer.h b/net/tipc/bearer.h
index 31d6172..5ad70ef 100644
--- a/net/tipc/bearer.h
+++ b/net/tipc/bearer.h
@@ -107,7 +107,6 @@
* @link_req: ptr to (optional) structure making periodic link setup requests
* @links: list of non-congested links associated with bearer
* @cong_links: list of congested links associated with bearer
- * @continue_count: # of times bearer has resumed after congestion or blocking
* @active: non-zero if bearer structure is represents a bearer
* @net_plane: network plane ('A' through 'H') currently associated with bearer
* @nodes: indicates which nodes in cluster can be reached through bearer
@@ -129,7 +128,6 @@
struct link_req *link_req;
struct list_head links;
struct list_head cong_links;
- u32 continue_count;
int active;
char net_plane;
struct tipc_node_map nodes;
diff --git a/net/tipc/core.h b/net/tipc/core.h
index 436dda1..d234a98 100644
--- a/net/tipc/core.h
+++ b/net/tipc/core.h
@@ -62,12 +62,6 @@
struct print_buf; /* log.h */
/*
- * TIPC sanity test macros
- */
-
-#define assert(i) BUG_ON(!(i))
-
-/*
* TIPC system monitoring code
*/
diff --git a/net/tipc/link.c b/net/tipc/link.c
index 5ed4b4f..f89570c 100644
--- a/net/tipc/link.c
+++ b/net/tipc/link.c
@@ -1572,7 +1572,7 @@
static int link_recv_buf_validate(struct sk_buff *buf)
{
static u32 min_data_hdr_size[8] = {
- SHORT_H_SIZE, MCAST_H_SIZE, LONG_H_SIZE, DIR_MSG_H_SIZE,
+ SHORT_H_SIZE, MCAST_H_SIZE, NAMED_H_SIZE, BASIC_H_SIZE,
MAX_H_SIZE, MAX_H_SIZE, MAX_H_SIZE, MAX_H_SIZE
};
@@ -2553,7 +2553,7 @@
u32 msg_sz = msg_size(imsg);
u32 fragm_sz = msg_data_sz(fragm);
u32 exp_fragm_cnt = msg_sz/fragm_sz + !!(msg_sz % fragm_sz);
- u32 max = TIPC_MAX_USER_MSG_SIZE + LONG_H_SIZE;
+ u32 max = TIPC_MAX_USER_MSG_SIZE + NAMED_H_SIZE;
if (msg_type(imsg) == TIPC_MCAST_MSG)
max = TIPC_MAX_USER_MSG_SIZE + MCAST_H_SIZE;
if (msg_size(imsg) > max) {
@@ -2882,7 +2882,7 @@
profile_total = 1;
tipc_printf(&pb, " TX profile sample:%u packets average:%u octets\n"
" 0-64:%u%% -256:%u%% -1024:%u%% -4096:%u%% "
- "-16354:%u%% -32768:%u%% -66000:%u%%\n",
+ "-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),
diff --git a/net/tipc/msg.c b/net/tipc/msg.c
index 03e57bf..83d5096 100644
--- a/net/tipc/msg.c
+++ b/net/tipc/msg.c
@@ -61,10 +61,8 @@
msg_set_size(m, hsize);
msg_set_prevnode(m, tipc_own_addr);
msg_set_type(m, type);
- if (!msg_short(m)) {
- msg_set_orignode(m, tipc_own_addr);
- msg_set_destnode(m, destnode);
- }
+ msg_set_orignode(m, tipc_own_addr);
+ msg_set_destnode(m, destnode);
}
/**
diff --git a/net/tipc/msg.h b/net/tipc/msg.h
index 8452454..d93178f 100644
--- a/net/tipc/msg.h
+++ b/net/tipc/msg.h
@@ -68,10 +68,10 @@
* Message header sizes
*/
-#define SHORT_H_SIZE 24 /* Connected, in-cluster messages */
-#define DIR_MSG_H_SIZE 32 /* Directly addressed messages */
-#define LONG_H_SIZE 40 /* Named messages */
-#define MCAST_H_SIZE 44 /* Multicast messages */
+#define SHORT_H_SIZE 24 /* In-cluster basic payload message */
+#define BASIC_H_SIZE 32 /* Basic payload message */
+#define NAMED_H_SIZE 40 /* Named payload message */
+#define MCAST_H_SIZE 44 /* Multicast payload message */
#define INT_H_SIZE 40 /* Internal messages */
#define MIN_H_SIZE 24 /* Smallest legal TIPC header size */
#define MAX_H_SIZE 60 /* Largest possible TIPC header size */
@@ -311,26 +311,6 @@
}
/*
- * TIPC may utilize the "link ack #" and "link seq #" fields of a short
- * message header to hold the destination node for the message, since the
- * normal "dest node" field isn't present. This cache is only referenced
- * when required, so populating the cache of a longer message header is
- * harmless (as long as the header has the two link sequence fields present).
- *
- * Note: Host byte order is OK here, since the info never goes off-card.
- */
-
-static inline u32 msg_destnode_cache(struct tipc_msg *m)
-{
- return m->hdr[2];
-}
-
-static inline void msg_set_destnode_cache(struct tipc_msg *m, u32 dnode)
-{
- m->hdr[2] = dnode;
-}
-
-/*
* Words 3-10
*/
@@ -377,7 +357,7 @@
static inline int msg_short(struct tipc_msg *m)
{
- return msg_hdr_sz(m) == 24;
+ return msg_hdr_sz(m) == SHORT_H_SIZE;
}
static inline u32 msg_orignode(struct tipc_msg *m)
@@ -635,7 +615,7 @@
static inline void msg_set_link_selector(struct tipc_msg *m, u32 n)
{
- msg_set_bits(m, 4, 0, 1, (n & 1));
+ msg_set_bits(m, 4, 0, 1, n);
}
/*
@@ -659,7 +639,7 @@
static inline void msg_set_probe(struct tipc_msg *m, u32 val)
{
- msg_set_bits(m, 5, 0, 1, (val & 1));
+ msg_set_bits(m, 5, 0, 1, val);
}
static inline char msg_net_plane(struct tipc_msg *m)
diff --git a/net/tipc/name_distr.c b/net/tipc/name_distr.c
index 80025a1..cd356e5 100644
--- a/net/tipc/name_distr.c
+++ b/net/tipc/name_distr.c
@@ -94,13 +94,13 @@
static struct sk_buff *named_prepare_buf(u32 type, u32 size, u32 dest)
{
- struct sk_buff *buf = tipc_buf_acquire(LONG_H_SIZE + size);
+ struct sk_buff *buf = tipc_buf_acquire(INT_H_SIZE + size);
struct tipc_msg *msg;
if (buf != NULL) {
msg = buf_msg(buf);
- tipc_msg_init(msg, NAME_DISTRIBUTOR, type, LONG_H_SIZE, dest);
- msg_set_size(msg, LONG_H_SIZE + size);
+ tipc_msg_init(msg, NAME_DISTRIBUTOR, type, INT_H_SIZE, dest);
+ msg_set_size(msg, INT_H_SIZE + size);
}
return buf;
}
diff --git a/net/tipc/name_table.c b/net/tipc/name_table.c
index 205ed4a..46e6b6c 100644
--- a/net/tipc/name_table.c
+++ b/net/tipc/name_table.c
@@ -2,7 +2,7 @@
* net/tipc/name_table.c: TIPC name table code
*
* Copyright (c) 2000-2006, Ericsson AB
- * Copyright (c) 2004-2008, Wind River Systems
+ * Copyright (c) 2004-2008, 2010-2011, Wind River Systems
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -44,9 +44,7 @@
static int tipc_nametbl_size = 1024; /* must be a power of 2 */
/**
- * struct sub_seq - container for all published instances of a name sequence
- * @lower: name sequence lower bound
- * @upper: name sequence upper bound
+ * struct name_info - name sequence publication info
* @node_list: circular list of publications made by own node
* @cluster_list: circular list of publications made by own cluster
* @zone_list: circular list of publications made by own zone
@@ -59,18 +57,29 @@
* (The cluster and node lists may be empty.)
*/
-struct sub_seq {
- u32 lower;
- u32 upper;
- struct publication *node_list;
- struct publication *cluster_list;
- struct publication *zone_list;
+struct name_info {
+ struct list_head node_list;
+ struct list_head cluster_list;
+ struct list_head zone_list;
u32 node_list_size;
u32 cluster_list_size;
u32 zone_list_size;
};
/**
+ * struct sub_seq - container for all published instances of a name sequence
+ * @lower: name sequence lower bound
+ * @upper: name sequence upper bound
+ * @info: pointer to name sequence publication info
+ */
+
+struct sub_seq {
+ u32 lower;
+ u32 upper;
+ struct name_info *info;
+};
+
+/**
* struct name_seq - container for all published instances of a name type
* @type: 32 bit 'type' value for name sequence
* @sseq: pointer to dynamically-sized array of sub-sequences of this 'type';
@@ -246,6 +255,7 @@
struct subscription *st;
struct publication *publ;
struct sub_seq *sseq;
+ struct name_info *info;
int created_subseq = 0;
sseq = nameseq_find_subseq(nseq, lower);
@@ -258,6 +268,8 @@
type, lower, upper);
return NULL;
}
+
+ info = sseq->info;
} else {
u32 inspos;
struct sub_seq *freesseq;
@@ -292,6 +304,17 @@
nseq->alloc *= 2;
}
+ info = kzalloc(sizeof(*info), GFP_ATOMIC);
+ if (!info) {
+ warn("Cannot publish {%u,%u,%u}, no memory\n",
+ type, lower, upper);
+ return NULL;
+ }
+
+ INIT_LIST_HEAD(&info->node_list);
+ INIT_LIST_HEAD(&info->cluster_list);
+ INIT_LIST_HEAD(&info->zone_list);
+
/* Insert new sub-sequence */
sseq = &nseq->sseqs[inspos];
@@ -301,6 +324,7 @@
nseq->first_free++;
sseq->lower = lower;
sseq->upper = upper;
+ sseq->info = info;
created_subseq = 1;
}
@@ -310,33 +334,17 @@
if (!publ)
return NULL;
- sseq->zone_list_size++;
- if (!sseq->zone_list)
- sseq->zone_list = publ->zone_list_next = publ;
- else {
- publ->zone_list_next = sseq->zone_list->zone_list_next;
- sseq->zone_list->zone_list_next = publ;
- }
+ list_add(&publ->zone_list, &info->zone_list);
+ info->zone_list_size++;
if (in_own_cluster(node)) {
- sseq->cluster_list_size++;
- if (!sseq->cluster_list)
- sseq->cluster_list = publ->cluster_list_next = publ;
- else {
- publ->cluster_list_next =
- sseq->cluster_list->cluster_list_next;
- sseq->cluster_list->cluster_list_next = publ;
- }
+ list_add(&publ->cluster_list, &info->cluster_list);
+ info->cluster_list_size++;
}
if (node == tipc_own_addr) {
- sseq->node_list_size++;
- if (!sseq->node_list)
- sseq->node_list = publ->node_list_next = publ;
- else {
- publ->node_list_next = sseq->node_list->node_list_next;
- sseq->node_list->node_list_next = publ;
- }
+ list_add(&publ->node_list, &info->node_list);
+ info->node_list_size++;
}
/*
@@ -370,9 +378,8 @@
u32 node, u32 ref, u32 key)
{
struct publication *publ;
- struct publication *curr;
- struct publication *prev;
struct sub_seq *sseq = nameseq_find_subseq(nseq, inst);
+ struct name_info *info;
struct sub_seq *free;
struct subscription *s, *st;
int removed_subseq = 0;
@@ -380,96 +387,41 @@
if (!sseq)
return NULL;
+ info = sseq->info;
+
+ /* Locate publication, if it exists */
+
+ list_for_each_entry(publ, &info->zone_list, zone_list) {
+ if ((publ->key == key) && (publ->ref == ref) &&
+ (!publ->node || (publ->node == node)))
+ goto found;
+ }
+ return NULL;
+
+found:
/* Remove publication from zone scope list */
- prev = sseq->zone_list;
- publ = sseq->zone_list->zone_list_next;
- while ((publ->key != key) || (publ->ref != ref) ||
- (publ->node && (publ->node != node))) {
- prev = publ;
- publ = publ->zone_list_next;
- if (prev == sseq->zone_list) {
-
- /* Prevent endless loop if publication not found */
-
- return NULL;
- }
- }
- if (publ != sseq->zone_list)
- prev->zone_list_next = publ->zone_list_next;
- else if (publ->zone_list_next != publ) {
- prev->zone_list_next = publ->zone_list_next;
- sseq->zone_list = publ->zone_list_next;
- } else {
- sseq->zone_list = NULL;
- }
- sseq->zone_list_size--;
+ list_del(&publ->zone_list);
+ info->zone_list_size--;
/* Remove publication from cluster scope list, if present */
if (in_own_cluster(node)) {
- prev = sseq->cluster_list;
- curr = sseq->cluster_list->cluster_list_next;
- while (curr != publ) {
- prev = curr;
- curr = curr->cluster_list_next;
- if (prev == sseq->cluster_list) {
-
- /* Prevent endless loop for malformed list */
-
- err("Unable to de-list cluster publication\n"
- "{%u%u}, node=0x%x, ref=%u, key=%u)\n",
- publ->type, publ->lower, publ->node,
- publ->ref, publ->key);
- goto end_cluster;
- }
- }
- if (publ != sseq->cluster_list)
- prev->cluster_list_next = publ->cluster_list_next;
- else if (publ->cluster_list_next != publ) {
- prev->cluster_list_next = publ->cluster_list_next;
- sseq->cluster_list = publ->cluster_list_next;
- } else {
- sseq->cluster_list = NULL;
- }
- sseq->cluster_list_size--;
+ list_del(&publ->cluster_list);
+ info->cluster_list_size--;
}
-end_cluster:
/* Remove publication from node scope list, if present */
if (node == tipc_own_addr) {
- prev = sseq->node_list;
- curr = sseq->node_list->node_list_next;
- while (curr != publ) {
- prev = curr;
- curr = curr->node_list_next;
- if (prev == sseq->node_list) {
-
- /* Prevent endless loop for malformed list */
-
- err("Unable to de-list node publication\n"
- "{%u%u}, node=0x%x, ref=%u, key=%u)\n",
- publ->type, publ->lower, publ->node,
- publ->ref, publ->key);
- goto end_node;
- }
- }
- if (publ != sseq->node_list)
- prev->node_list_next = publ->node_list_next;
- else if (publ->node_list_next != publ) {
- prev->node_list_next = publ->node_list_next;
- sseq->node_list = publ->node_list_next;
- } else {
- sseq->node_list = NULL;
- }
- sseq->node_list_size--;
+ list_del(&publ->node_list);
+ info->node_list_size--;
}
-end_node:
/* Contract subseq list if no more publications for that subseq */
- if (!sseq->zone_list) {
+ if (list_empty(&info->zone_list)) {
+ kfree(info);
free = &nseq->sseqs[nseq->first_free--];
memmove(sseq, sseq + 1, (free - (sseq + 1)) * sizeof(*sseq));
removed_subseq = 1;
@@ -506,12 +458,12 @@
return;
while (sseq != &nseq->sseqs[nseq->first_free]) {
- struct publication *zl = sseq->zone_list;
- if (zl && tipc_subscr_overlap(s, sseq->lower, sseq->upper)) {
- struct publication *crs = zl;
+ if (tipc_subscr_overlap(s, sseq->lower, sseq->upper)) {
+ struct publication *crs;
+ struct name_info *info = sseq->info;
int must_report = 1;
- do {
+ list_for_each_entry(crs, &info->zone_list, zone_list) {
tipc_subscr_report_overlap(s,
sseq->lower,
sseq->upper,
@@ -520,8 +472,7 @@
crs->node,
must_report);
must_report = 0;
- crs = crs->zone_list_next;
- } while (crs != zl);
+ }
}
sseq++;
}
@@ -591,9 +542,10 @@
u32 tipc_nametbl_translate(u32 type, u32 instance, u32 *destnode)
{
struct sub_seq *sseq;
- struct publication *publ = NULL;
+ struct name_info *info;
+ struct publication *publ;
struct name_seq *seq;
- u32 ref;
+ u32 ref = 0;
if (!tipc_in_scope(*destnode, tipc_own_addr))
return 0;
@@ -606,55 +558,57 @@
if (unlikely(!sseq))
goto not_found;
spin_lock_bh(&seq->lock);
+ info = sseq->info;
/* Closest-First Algorithm: */
if (likely(!*destnode)) {
- publ = sseq->node_list;
- if (publ) {
- sseq->node_list = publ->node_list_next;
-found:
- ref = publ->ref;
- *destnode = publ->node;
- spin_unlock_bh(&seq->lock);
- read_unlock_bh(&tipc_nametbl_lock);
- return ref;
- }
- publ = sseq->cluster_list;
- if (publ) {
- sseq->cluster_list = publ->cluster_list_next;
- goto found;
- }
- publ = sseq->zone_list;
- if (publ) {
- sseq->zone_list = publ->zone_list_next;
- goto found;
+ if (!list_empty(&info->node_list)) {
+ publ = list_first_entry(&info->node_list,
+ struct publication,
+ node_list);
+ list_move_tail(&publ->node_list,
+ &info->node_list);
+ } else if (!list_empty(&info->cluster_list)) {
+ publ = list_first_entry(&info->cluster_list,
+ struct publication,
+ cluster_list);
+ list_move_tail(&publ->cluster_list,
+ &info->cluster_list);
+ } else {
+ publ = list_first_entry(&info->zone_list,
+ struct publication,
+ zone_list);
+ list_move_tail(&publ->zone_list,
+ &info->zone_list);
}
}
/* Round-Robin Algorithm: */
else if (*destnode == tipc_own_addr) {
- publ = sseq->node_list;
- if (publ) {
- sseq->node_list = publ->node_list_next;
- goto found;
- }
+ if (list_empty(&info->node_list))
+ goto no_match;
+ publ = list_first_entry(&info->node_list, struct publication,
+ node_list);
+ list_move_tail(&publ->node_list, &info->node_list);
} else if (in_own_cluster(*destnode)) {
- publ = sseq->cluster_list;
- if (publ) {
- sseq->cluster_list = publ->cluster_list_next;
- goto found;
- }
+ if (list_empty(&info->cluster_list))
+ goto no_match;
+ publ = list_first_entry(&info->cluster_list, struct publication,
+ cluster_list);
+ list_move_tail(&publ->cluster_list, &info->cluster_list);
} else {
- publ = sseq->zone_list;
- if (publ) {
- sseq->zone_list = publ->zone_list_next;
- goto found;
- }
+ publ = list_first_entry(&info->zone_list, struct publication,
+ zone_list);
+ list_move_tail(&publ->zone_list, &info->zone_list);
}
+
+ ref = publ->ref;
+ *destnode = publ->node;
+no_match:
spin_unlock_bh(&seq->lock);
not_found:
read_unlock_bh(&tipc_nametbl_lock);
- return 0;
+ return ref;
}
/**
@@ -676,6 +630,7 @@
struct name_seq *seq;
struct sub_seq *sseq;
struct sub_seq *sseq_stop;
+ struct name_info *info;
int res = 0;
read_lock_bh(&tipc_nametbl_lock);
@@ -693,16 +648,13 @@
if (sseq->lower > upper)
break;
- publ = sseq->node_list;
- if (publ) {
- do {
- if (publ->scope <= limit)
- tipc_port_list_add(dports, publ->ref);
- publ = publ->node_list_next;
- } while (publ != sseq->node_list);
+ info = sseq->info;
+ list_for_each_entry(publ, &info->node_list, node_list) {
+ if (publ->scope <= limit)
+ tipc_port_list_add(dports, publ->ref);
}
- if (sseq->cluster_list_size != sseq->node_list_size)
+ if (info->cluster_list_size != info->node_list_size)
res = 1;
}
@@ -840,16 +792,19 @@
{
char portIdStr[27];
const char *scope_str[] = {"", " zone", " cluster", " node"};
- struct publication *publ = sseq->zone_list;
+ struct publication *publ;
+ struct name_info *info;
tipc_printf(buf, "%-10u %-10u ", sseq->lower, sseq->upper);
- if (depth == 2 || !publ) {
+ if (depth == 2) {
tipc_printf(buf, "\n");
return;
}
- do {
+ info = sseq->info;
+
+ list_for_each_entry(publ, &info->zone_list, zone_list) {
sprintf(portIdStr, "<%u.%u.%u:%u>",
tipc_zone(publ->node), tipc_cluster(publ->node),
tipc_node(publ->node), publ->ref);
@@ -858,13 +813,9 @@
tipc_printf(buf, "%-10u %s", publ->key,
scope_str[publ->scope]);
}
-
- publ = publ->zone_list_next;
- if (publ == sseq->zone_list)
- break;
-
- tipc_printf(buf, "\n%33s", " ");
- } while (1);
+ if (!list_is_last(&publ->zone_list, &info->zone_list))
+ tipc_printf(buf, "\n%33s", " ");
+ };
tipc_printf(buf, "\n");
}
diff --git a/net/tipc/name_table.h b/net/tipc/name_table.h
index d228bd6..62d77e5 100644
--- a/net/tipc/name_table.h
+++ b/net/tipc/name_table.h
@@ -2,7 +2,7 @@
* net/tipc/name_table.h: Include file for TIPC name table code
*
* Copyright (c) 2000-2006, Ericsson AB
- * Copyright (c) 2004-2005, Wind River Systems
+ * Copyright (c) 2004-2005, 2010-2011, Wind River Systems
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -61,9 +61,9 @@
* @subscr: subscription to "node down" event (for off-node publications only)
* @local_list: adjacent entries in list of publications made by this node
* @pport_list: adjacent entries in list of publications made by this port
- * @node_list: next matching name seq publication with >= node scope
- * @cluster_list: next matching name seq publication with >= cluster scope
- * @zone_list: next matching name seq publication with >= zone scope
+ * @node_list: adjacent matching name seq publications with >= node scope
+ * @cluster_list: adjacent matching name seq publications with >= cluster scope
+ * @zone_list: adjacent matching name seq publications with >= zone scope
*
* Note that the node list, cluster list, and zone list are circular lists.
*/
@@ -79,9 +79,9 @@
struct tipc_node_subscr subscr;
struct list_head local_list;
struct list_head pport_list;
- struct publication *node_list_next;
- struct publication *cluster_list_next;
- struct publication *zone_list_next;
+ struct list_head node_list;
+ struct list_head cluster_list;
+ struct list_head zone_list;
};
diff --git a/net/tipc/port.c b/net/tipc/port.c
index c68dc95..54d812a 100644
--- a/net/tipc/port.c
+++ b/net/tipc/port.c
@@ -222,7 +222,7 @@
p_ptr->max_pkt = MAX_PKT_DEFAULT;
p_ptr->ref = ref;
msg = &p_ptr->phdr;
- tipc_msg_init(msg, importance, TIPC_NAMED_MSG, LONG_H_SIZE, 0);
+ tipc_msg_init(msg, importance, TIPC_NAMED_MSG, NAMED_H_SIZE, 0);
msg_set_origport(msg, ref);
INIT_LIST_HEAD(&p_ptr->wait_list);
INIT_LIST_HEAD(&p_ptr->subscription.nodesub_list);
@@ -327,26 +327,23 @@
}
/*
- * port_build_proto_msg(): build a port level protocol
- * or a connection abortion message. Called with
- * tipc_port lock on.
+ * port_build_proto_msg(): create connection protocol message for port
+ *
+ * On entry the port must be locked and connected.
*/
-static struct sk_buff *port_build_proto_msg(u32 destport, u32 destnode,
- u32 origport, u32 orignode,
- u32 usr, u32 type, u32 err,
- u32 ack)
+static struct sk_buff *port_build_proto_msg(struct tipc_port *p_ptr,
+ u32 type, u32 ack)
{
struct sk_buff *buf;
struct tipc_msg *msg;
- buf = tipc_buf_acquire(LONG_H_SIZE);
+ buf = tipc_buf_acquire(INT_H_SIZE);
if (buf) {
msg = buf_msg(buf);
- tipc_msg_init(msg, usr, type, LONG_H_SIZE, destnode);
- msg_set_errcode(msg, err);
- msg_set_destport(msg, destport);
- msg_set_origport(msg, origport);
- msg_set_orignode(msg, orignode);
+ tipc_msg_init(msg, CONN_MANAGER, type, INT_H_SIZE,
+ port_peernode(p_ptr));
+ msg_set_destport(msg, port_peerport(p_ptr));
+ msg_set_origport(msg, p_ptr->ref);
msg_set_msgcnt(msg, ack);
}
return buf;
@@ -358,45 +355,48 @@
struct sk_buff *rbuf;
struct tipc_msg *rmsg;
int hdr_sz;
- u32 imp = msg_importance(msg);
+ u32 imp;
u32 data_sz = msg_data_sz(msg);
-
- if (data_sz > MAX_REJECT_SIZE)
- data_sz = MAX_REJECT_SIZE;
- if (msg_connected(msg) && (imp < TIPC_CRITICAL_IMPORTANCE))
- imp++;
+ u32 src_node;
+ u32 rmsg_sz;
/* discard rejected message if it shouldn't be returned to sender */
- if (msg_errcode(msg) || msg_dest_droppable(msg)) {
- buf_discard(buf);
- return data_sz;
- }
- /* construct rejected message */
- if (msg_mcast(msg))
- hdr_sz = MCAST_H_SIZE;
- else
- hdr_sz = LONG_H_SIZE;
- rbuf = tipc_buf_acquire(data_sz + hdr_sz);
- if (rbuf == NULL) {
- buf_discard(buf);
- return data_sz;
+ if (WARN(!msg_isdata(msg),
+ "attempt to reject message with user=%u", msg_user(msg))) {
+ dump_stack();
+ goto exit;
}
+ if (msg_errcode(msg) || msg_dest_droppable(msg))
+ goto exit;
+
+ /*
+ * construct returned message by copying rejected message header and
+ * data (or subset), then updating header fields that need adjusting
+ */
+
+ hdr_sz = msg_hdr_sz(msg);
+ rmsg_sz = hdr_sz + min_t(u32, data_sz, MAX_REJECT_SIZE);
+
+ rbuf = tipc_buf_acquire(rmsg_sz);
+ if (rbuf == NULL)
+ goto exit;
+
rmsg = buf_msg(rbuf);
- tipc_msg_init(rmsg, imp, msg_type(msg), hdr_sz, msg_orignode(msg));
- msg_set_errcode(rmsg, err);
- msg_set_destport(rmsg, msg_origport(msg));
- msg_set_origport(rmsg, msg_destport(msg));
- if (msg_short(msg)) {
- msg_set_orignode(rmsg, tipc_own_addr);
- /* leave name type & instance as zeroes */
- } else {
- msg_set_orignode(rmsg, msg_destnode(msg));
- msg_set_nametype(rmsg, msg_nametype(msg));
- msg_set_nameinst(rmsg, msg_nameinst(msg));
+ skb_copy_to_linear_data(rbuf, msg, rmsg_sz);
+
+ if (msg_connected(rmsg)) {
+ imp = msg_importance(rmsg);
+ if (imp < TIPC_CRITICAL_IMPORTANCE)
+ msg_set_importance(rmsg, ++imp);
}
- msg_set_size(rmsg, data_sz + hdr_sz);
- skb_copy_to_linear_data_offset(rbuf, hdr_sz, msg_data(msg), data_sz);
+ msg_set_non_seq(rmsg, 0);
+ msg_set_size(rmsg, rmsg_sz);
+ msg_set_errcode(rmsg, err);
+ msg_set_prevnode(rmsg, tipc_own_addr);
+ msg_swap_words(rmsg, 4, 5);
+ if (!msg_short(rmsg))
+ msg_swap_words(rmsg, 6, 7);
/* send self-abort message when rejecting on a connected port */
if (msg_connected(msg)) {
@@ -411,9 +411,15 @@
tipc_net_route_msg(abuf);
}
- /* send rejected message */
+ /* send returned message & dispose of rejected message */
+
+ src_node = msg_prevnode(msg);
+ if (src_node == tipc_own_addr)
+ tipc_port_recv_msg(rbuf);
+ else
+ tipc_link_send(rbuf, src_node, msg_link_selector(rmsg));
+exit:
buf_discard(buf);
- tipc_net_route_msg(rbuf);
return data_sz;
}
@@ -449,14 +455,7 @@
if (p_ptr->probing_state == PROBING) {
buf = port_build_self_abort_msg(p_ptr, TIPC_ERR_NO_PORT);
} else {
- buf = port_build_proto_msg(port_peerport(p_ptr),
- port_peernode(p_ptr),
- p_ptr->ref,
- tipc_own_addr,
- CONN_MANAGER,
- CONN_PROBE,
- TIPC_OK,
- 0);
+ buf = port_build_proto_msg(p_ptr, CONN_PROBE, 0);
p_ptr->probing_state = PROBING;
k_start_timer(&p_ptr->timer, p_ptr->probing_interval);
}
@@ -480,100 +479,94 @@
static struct sk_buff *port_build_self_abort_msg(struct tipc_port *p_ptr, u32 err)
{
- u32 imp = msg_importance(&p_ptr->phdr);
+ struct sk_buff *buf = port_build_peer_abort_msg(p_ptr, err);
- if (!p_ptr->connected)
- return NULL;
- if (imp < TIPC_CRITICAL_IMPORTANCE)
- imp++;
- return port_build_proto_msg(p_ptr->ref,
- tipc_own_addr,
- port_peerport(p_ptr),
- port_peernode(p_ptr),
- imp,
- TIPC_CONN_MSG,
- err,
- 0);
+ if (buf) {
+ struct tipc_msg *msg = buf_msg(buf);
+ msg_swap_words(msg, 4, 5);
+ msg_swap_words(msg, 6, 7);
+ }
+ return buf;
}
static struct sk_buff *port_build_peer_abort_msg(struct tipc_port *p_ptr, u32 err)
{
- u32 imp = msg_importance(&p_ptr->phdr);
+ struct sk_buff *buf;
+ struct tipc_msg *msg;
+ u32 imp;
if (!p_ptr->connected)
return NULL;
- if (imp < TIPC_CRITICAL_IMPORTANCE)
- imp++;
- return port_build_proto_msg(port_peerport(p_ptr),
- port_peernode(p_ptr),
- p_ptr->ref,
- tipc_own_addr,
- imp,
- TIPC_CONN_MSG,
- err,
- 0);
+
+ buf = tipc_buf_acquire(BASIC_H_SIZE);
+ if (buf) {
+ msg = buf_msg(buf);
+ memcpy(msg, &p_ptr->phdr, BASIC_H_SIZE);
+ msg_set_hdr_sz(msg, BASIC_H_SIZE);
+ msg_set_size(msg, BASIC_H_SIZE);
+ imp = msg_importance(msg);
+ if (imp < TIPC_CRITICAL_IMPORTANCE)
+ msg_set_importance(msg, ++imp);
+ msg_set_errcode(msg, err);
+ }
+ return buf;
}
void tipc_port_recv_proto_msg(struct sk_buff *buf)
{
struct tipc_msg *msg = buf_msg(buf);
- struct tipc_port *p_ptr = tipc_port_lock(msg_destport(msg));
- u32 err = TIPC_OK;
+ struct tipc_port *p_ptr;
struct sk_buff *r_buf = NULL;
- struct sk_buff *abort_buf = NULL;
+ u32 orignode = msg_orignode(msg);
+ u32 origport = msg_origport(msg);
+ u32 destport = msg_destport(msg);
+ int wakeable;
- if (!p_ptr) {
- err = TIPC_ERR_NO_PORT;
- } else if (p_ptr->connected) {
- if ((port_peernode(p_ptr) != msg_orignode(msg)) ||
- (port_peerport(p_ptr) != msg_origport(msg))) {
- err = TIPC_ERR_NO_PORT;
- } else if (msg_type(msg) == CONN_ACK) {
- int wakeup = tipc_port_congested(p_ptr) &&
- p_ptr->congested &&
- p_ptr->wakeup;
- p_ptr->acked += msg_msgcnt(msg);
- if (tipc_port_congested(p_ptr))
- goto exit;
- p_ptr->congested = 0;
- if (!wakeup)
- goto exit;
- p_ptr->wakeup(p_ptr);
- goto exit;
+ /* Validate connection */
+
+ p_ptr = tipc_port_lock(destport);
+ if (!p_ptr || !p_ptr->connected ||
+ (port_peernode(p_ptr) != orignode) ||
+ (port_peerport(p_ptr) != origport)) {
+ r_buf = tipc_buf_acquire(BASIC_H_SIZE);
+ if (r_buf) {
+ msg = buf_msg(r_buf);
+ tipc_msg_init(msg, TIPC_HIGH_IMPORTANCE, TIPC_CONN_MSG,
+ BASIC_H_SIZE, orignode);
+ msg_set_errcode(msg, TIPC_ERR_NO_PORT);
+ msg_set_origport(msg, destport);
+ msg_set_destport(msg, origport);
}
- } else if (p_ptr->published) {
- err = TIPC_ERR_NO_PORT;
- }
- if (err) {
- r_buf = port_build_proto_msg(msg_origport(msg),
- msg_orignode(msg),
- msg_destport(msg),
- tipc_own_addr,
- TIPC_HIGH_IMPORTANCE,
- TIPC_CONN_MSG,
- err,
- 0);
+ if (p_ptr)
+ tipc_port_unlock(p_ptr);
goto exit;
}
- /* All is fine */
- if (msg_type(msg) == CONN_PROBE) {
- r_buf = port_build_proto_msg(msg_origport(msg),
- msg_orignode(msg),
- msg_destport(msg),
- tipc_own_addr,
- CONN_MANAGER,
- CONN_PROBE_REPLY,
- TIPC_OK,
- 0);
+ /* Process protocol message sent by peer */
+
+ switch (msg_type(msg)) {
+ case CONN_ACK:
+ wakeable = tipc_port_congested(p_ptr) && p_ptr->congested &&
+ p_ptr->wakeup;
+ p_ptr->acked += msg_msgcnt(msg);
+ if (!tipc_port_congested(p_ptr)) {
+ p_ptr->congested = 0;
+ if (wakeable)
+ p_ptr->wakeup(p_ptr);
+ }
+ break;
+ case CONN_PROBE:
+ r_buf = port_build_proto_msg(p_ptr, CONN_PROBE_REPLY, 0);
+ break;
+ default:
+ /* CONN_PROBE_REPLY or unrecognized - no action required */
+ break;
}
p_ptr->probing_state = CONFIRMED;
+ tipc_port_unlock(p_ptr);
exit:
- if (p_ptr)
- tipc_port_unlock(p_ptr);
tipc_net_route_msg(r_buf);
- tipc_net_route_msg(abort_buf);
buf_discard(buf);
}
@@ -889,14 +882,7 @@
return;
if (p_ptr->connected) {
p_ptr->conn_unacked -= ack;
- buf = port_build_proto_msg(port_peerport(p_ptr),
- port_peernode(p_ptr),
- ref,
- tipc_own_addr,
- CONN_MANAGER,
- CONN_ACK,
- TIPC_OK,
- ack);
+ buf = port_build_proto_msg(p_ptr, CONN_ACK, ack);
}
tipc_port_unlock(p_ptr);
tipc_net_route_msg(buf);
@@ -1140,19 +1126,7 @@
if (!p_ptr)
return -EINVAL;
- if (p_ptr->connected) {
- u32 imp = msg_importance(&p_ptr->phdr);
- if (imp < TIPC_CRITICAL_IMPORTANCE)
- imp++;
- buf = port_build_proto_msg(port_peerport(p_ptr),
- port_peernode(p_ptr),
- ref,
- tipc_own_addr,
- imp,
- TIPC_CONN_MSG,
- TIPC_CONN_SHUTDOWN,
- 0);
- }
+ buf = port_build_peer_abort_msg(p_ptr, TIPC_CONN_SHUTDOWN);
tipc_port_unlock(p_ptr);
tipc_net_route_msg(buf);
return tipc_disconnect(ref);
@@ -1238,7 +1212,7 @@
msg_set_type(msg, TIPC_NAMED_MSG);
msg_set_orignode(msg, tipc_own_addr);
msg_set_origport(msg, ref);
- msg_set_hdr_sz(msg, LONG_H_SIZE);
+ msg_set_hdr_sz(msg, NAMED_H_SIZE);
msg_set_nametype(msg, name->type);
msg_set_nameinst(msg, name->instance);
msg_set_lookup_scope(msg, tipc_addr_scope(domain));
@@ -1291,7 +1265,7 @@
msg_set_origport(msg, ref);
msg_set_destnode(msg, dest->node);
msg_set_destport(msg, dest->ref);
- msg_set_hdr_sz(msg, DIR_MSG_H_SIZE);
+ msg_set_hdr_sz(msg, BASIC_H_SIZE);
if (dest->node == tipc_own_addr)
res = tipc_port_recv_sections(p_ptr, num_sect, msg_sect,
@@ -1331,13 +1305,13 @@
msg_set_origport(msg, ref);
msg_set_destnode(msg, dest->node);
msg_set_destport(msg, dest->ref);
- msg_set_hdr_sz(msg, DIR_MSG_H_SIZE);
- msg_set_size(msg, DIR_MSG_H_SIZE + dsz);
- if (skb_cow(buf, DIR_MSG_H_SIZE))
+ msg_set_hdr_sz(msg, BASIC_H_SIZE);
+ msg_set_size(msg, BASIC_H_SIZE + dsz);
+ if (skb_cow(buf, BASIC_H_SIZE))
return -ENOMEM;
- skb_push(buf, DIR_MSG_H_SIZE);
- skb_copy_to_linear_data(buf, msg, DIR_MSG_H_SIZE);
+ skb_push(buf, BASIC_H_SIZE);
+ skb_copy_to_linear_data(buf, msg, BASIC_H_SIZE);
if (dest->node == tipc_own_addr)
res = tipc_port_recv_msg(buf);
diff --git a/net/tipc/socket.c b/net/tipc/socket.c
index 3388373..adb2eff 100644
--- a/net/tipc/socket.c
+++ b/net/tipc/socket.c
@@ -36,9 +36,6 @@
#include <net/sock.h>
-#include <linux/tipc.h>
-#include <linux/tipc_config.h>
-
#include "core.h"
#include "port.h"
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
index 493b939..3633ab6 100644
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
@@ -170,7 +170,9 @@
break;
}
if (wdev->authtry_bsses[i] &&
- memcmp(wdev->authtry_bsses[i]->pub.bssid, bssid, ETH_ALEN) == 0) {
+ memcmp(wdev->authtry_bsses[i]->pub.bssid, bssid,
+ ETH_ALEN) == 0 &&
+ memcmp(mgmt->sa, dev->dev_addr, ETH_ALEN) == 0) {
cfg80211_unhold_bss(wdev->authtry_bsses[i]);
cfg80211_put_bss(&wdev->authtry_bsses[i]->pub);
wdev->authtry_bsses[i] = NULL;
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index f07602d..50ff82a 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -3620,7 +3620,8 @@
return __cfg80211_stop_sched_scan(rdev, false);
}
-static int nl80211_send_bss(struct sk_buff *msg, u32 pid, u32 seq, int flags,
+static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb,
+ u32 seq, int flags,
struct cfg80211_registered_device *rdev,
struct wireless_dev *wdev,
struct cfg80211_internal_bss *intbss)
@@ -3632,11 +3633,13 @@
ASSERT_WDEV_LOCK(wdev);
- hdr = nl80211hdr_put(msg, pid, seq, flags,
+ hdr = nl80211hdr_put(msg, NETLINK_CB(cb->skb).pid, seq, flags,
NL80211_CMD_NEW_SCAN_RESULTS);
if (!hdr)
return -1;
+ genl_dump_check_consistent(cb, hdr, &nl80211_fam);
+
NLA_PUT_U32(msg, NL80211_ATTR_GENERATION, rdev->bss_generation);
NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, wdev->netdev->ifindex);
@@ -3725,11 +3728,12 @@
spin_lock_bh(&rdev->bss_lock);
cfg80211_bss_expire(rdev);
+ cb->seq = rdev->bss_generation;
+
list_for_each_entry(scan, &rdev->bss_list, list) {
if (++idx <= start)
continue;
- if (nl80211_send_bss(skb,
- NETLINK_CB(cb->skb).pid,
+ if (nl80211_send_bss(skb, cb,
cb->nlh->nlmsg_seq, NLM_F_MULTI,
rdev, wdev, scan) < 0) {
idx--;
@@ -3753,10 +3757,6 @@
void *hdr;
struct nlattr *infoattr;
- /* Survey without a channel doesn't make sense */
- if (!survey->channel)
- return -EINVAL;
-
hdr = nl80211hdr_put(msg, pid, seq, flags,
NL80211_CMD_NEW_SURVEY_RESULTS);
if (!hdr)
@@ -3819,6 +3819,8 @@
}
while (1) {
+ struct ieee80211_channel *chan;
+
res = dev->ops->dump_survey(&dev->wiphy, netdev, survey_idx,
&survey);
if (res == -ENOENT)
@@ -3826,6 +3828,19 @@
if (res)
goto out_err;
+ /* Survey without a channel doesn't make sense */
+ if (!survey.channel) {
+ res = -EINVAL;
+ goto out;
+ }
+
+ chan = ieee80211_get_channel(&dev->wiphy,
+ survey.channel->center_freq);
+ if (!chan || chan->flags & IEEE80211_CHAN_DISABLED) {
+ survey_idx++;
+ continue;
+ }
+
if (nl80211_send_survey(skb,
NETLINK_CB(cb->skb).pid,
cb->nlh->nlmsg_seq, NLM_F_MULTI,
@@ -4360,6 +4375,93 @@
return err;
}
+static int nl80211_testmode_dump(struct sk_buff *skb,
+ struct netlink_callback *cb)
+{
+ struct cfg80211_registered_device *dev;
+ int err;
+ long phy_idx;
+ void *data = NULL;
+ int data_len = 0;
+
+ if (cb->args[0]) {
+ /*
+ * 0 is a valid index, but not valid for args[0],
+ * so we need to offset by 1.
+ */
+ phy_idx = cb->args[0] - 1;
+ } else {
+ err = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize,
+ nl80211_fam.attrbuf, nl80211_fam.maxattr,
+ nl80211_policy);
+ if (err)
+ return err;
+ if (!nl80211_fam.attrbuf[NL80211_ATTR_WIPHY])
+ return -EINVAL;
+ phy_idx = nla_get_u32(nl80211_fam.attrbuf[NL80211_ATTR_WIPHY]);
+ if (nl80211_fam.attrbuf[NL80211_ATTR_TESTDATA])
+ cb->args[1] =
+ (long)nl80211_fam.attrbuf[NL80211_ATTR_TESTDATA];
+ }
+
+ if (cb->args[1]) {
+ data = nla_data((void *)cb->args[1]);
+ data_len = nla_len((void *)cb->args[1]);
+ }
+
+ mutex_lock(&cfg80211_mutex);
+ dev = cfg80211_rdev_by_wiphy_idx(phy_idx);
+ if (!dev) {
+ mutex_unlock(&cfg80211_mutex);
+ return -ENOENT;
+ }
+ cfg80211_lock_rdev(dev);
+ mutex_unlock(&cfg80211_mutex);
+
+ if (!dev->ops->testmode_dump) {
+ err = -EOPNOTSUPP;
+ goto out_err;
+ }
+
+ while (1) {
+ void *hdr = nl80211hdr_put(skb, NETLINK_CB(cb->skb).pid,
+ cb->nlh->nlmsg_seq, NLM_F_MULTI,
+ NL80211_CMD_TESTMODE);
+ struct nlattr *tmdata;
+
+ if (nla_put_u32(skb, NL80211_ATTR_WIPHY, dev->wiphy_idx) < 0) {
+ genlmsg_cancel(skb, hdr);
+ break;
+ }
+
+ tmdata = nla_nest_start(skb, NL80211_ATTR_TESTDATA);
+ if (!tmdata) {
+ genlmsg_cancel(skb, hdr);
+ break;
+ }
+ err = dev->ops->testmode_dump(&dev->wiphy, skb, cb,
+ data, data_len);
+ nla_nest_end(skb, tmdata);
+
+ if (err == -ENOBUFS || err == -ENOENT) {
+ genlmsg_cancel(skb, hdr);
+ break;
+ } else if (err) {
+ genlmsg_cancel(skb, hdr);
+ goto out_err;
+ }
+
+ genlmsg_end(skb, hdr);
+ }
+
+ err = skb->len;
+ /* see above */
+ cb->args[0] = phy_idx + 1;
+ out_err:
+ cfg80211_unlock_rdev(dev);
+ return err;
+}
+
static struct sk_buff *
__cfg80211_testmode_alloc_skb(struct cfg80211_registered_device *rdev,
int approxlen, u32 pid, u32 seq, gfp_t gfp)
@@ -5657,6 +5759,7 @@
{
.cmd = NL80211_CMD_TESTMODE,
.doit = nl80211_testmode_do,
+ .dumpit = nl80211_testmode_dump,
.policy = nl80211_policy,
.flags = GENL_ADMIN_PERM,
.internal_flags = NL80211_FLAG_NEED_WIPHY |
diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c
index 4680b1e..d306154 100644
--- a/net/x25/af_x25.c
+++ b/net/x25/af_x25.c
@@ -237,21 +237,21 @@
#endif
) {
switch (event) {
- case NETDEV_UP:
- x25_link_device_up(dev);
- break;
- case NETDEV_GOING_DOWN:
- nb = x25_get_neigh(dev);
- if (nb) {
- x25_terminate_link(nb);
- x25_neigh_put(nb);
- }
- break;
- case NETDEV_DOWN:
- x25_kill_by_device(dev);
- x25_route_device_down(dev);
- x25_link_device_down(dev);
- break;
+ case NETDEV_UP:
+ x25_link_device_up(dev);
+ break;
+ case NETDEV_GOING_DOWN:
+ nb = x25_get_neigh(dev);
+ if (nb) {
+ x25_terminate_link(nb);
+ x25_neigh_put(nb);
+ }
+ break;
+ case NETDEV_DOWN:
+ x25_kill_by_device(dev);
+ x25_route_device_down(dev);
+ x25_link_device_down(dev);
+ break;
}
}
@@ -1336,256 +1336,253 @@
int rc;
switch (cmd) {
- case TIOCOUTQ: {
- int amount;
+ case TIOCOUTQ: {
+ int amount;
- amount = sk->sk_sndbuf - sk_wmem_alloc_get(sk);
- if (amount < 0)
- amount = 0;
- rc = put_user(amount, (unsigned int __user *)argp);
- break;
- }
+ amount = sk->sk_sndbuf - sk_wmem_alloc_get(sk);
+ if (amount < 0)
+ amount = 0;
+ rc = put_user(amount, (unsigned int __user *)argp);
+ break;
+ }
- case TIOCINQ: {
- struct sk_buff *skb;
- int amount = 0;
- /*
- * These two are safe on a single CPU system as
- * only user tasks fiddle here
- */
- lock_sock(sk);
- if ((skb = skb_peek(&sk->sk_receive_queue)) != NULL)
- amount = skb->len;
- release_sock(sk);
- rc = put_user(amount, (unsigned int __user *)argp);
- break;
- }
+ case TIOCINQ: {
+ struct sk_buff *skb;
+ int amount = 0;
+ /*
+ * These two are safe on a single CPU system as
+ * only user tasks fiddle here
+ */
+ lock_sock(sk);
+ if ((skb = skb_peek(&sk->sk_receive_queue)) != NULL)
+ amount = skb->len;
+ release_sock(sk);
+ rc = put_user(amount, (unsigned int __user *)argp);
+ break;
+ }
- case SIOCGSTAMP:
- rc = -EINVAL;
- if (sk)
- rc = sock_get_timestamp(sk,
+ case SIOCGSTAMP:
+ rc = -EINVAL;
+ if (sk)
+ rc = sock_get_timestamp(sk,
(struct timeval __user *)argp);
+ break;
+ case SIOCGSTAMPNS:
+ rc = -EINVAL;
+ if (sk)
+ rc = sock_get_timestampns(sk,
+ (struct timespec __user *)argp);
+ break;
+ case SIOCGIFADDR:
+ case SIOCSIFADDR:
+ case SIOCGIFDSTADDR:
+ case SIOCSIFDSTADDR:
+ case SIOCGIFBRDADDR:
+ case SIOCSIFBRDADDR:
+ case SIOCGIFNETMASK:
+ case SIOCSIFNETMASK:
+ case SIOCGIFMETRIC:
+ case SIOCSIFMETRIC:
+ rc = -EINVAL;
+ break;
+ case SIOCADDRT:
+ case SIOCDELRT:
+ rc = -EPERM;
+ if (!capable(CAP_NET_ADMIN))
break;
- case SIOCGSTAMPNS:
- rc = -EINVAL;
- if (sk)
- rc = sock_get_timestampns(sk,
- (struct timespec __user *)argp);
+ rc = x25_route_ioctl(cmd, argp);
+ break;
+ case SIOCX25GSUBSCRIP:
+ rc = x25_subscr_ioctl(cmd, argp);
+ break;
+ case SIOCX25SSUBSCRIP:
+ rc = -EPERM;
+ if (!capable(CAP_NET_ADMIN))
break;
- case SIOCGIFADDR:
- case SIOCSIFADDR:
- case SIOCGIFDSTADDR:
- case SIOCSIFDSTADDR:
- case SIOCGIFBRDADDR:
- case SIOCSIFBRDADDR:
- case SIOCGIFNETMASK:
- case SIOCSIFNETMASK:
- case SIOCGIFMETRIC:
- case SIOCSIFMETRIC:
- rc = -EINVAL;
- break;
- case SIOCADDRT:
- case SIOCDELRT:
- rc = -EPERM;
- if (!capable(CAP_NET_ADMIN))
- break;
- rc = x25_route_ioctl(cmd, argp);
- break;
- case SIOCX25GSUBSCRIP:
- rc = x25_subscr_ioctl(cmd, argp);
- break;
- case SIOCX25SSUBSCRIP:
- rc = -EPERM;
- if (!capable(CAP_NET_ADMIN))
- break;
- rc = x25_subscr_ioctl(cmd, argp);
- break;
- case SIOCX25GFACILITIES: {
- lock_sock(sk);
- rc = copy_to_user(argp, &x25->facilities,
- sizeof(x25->facilities))
- ? -EFAULT : 0;
- release_sock(sk);
- break;
- }
+ rc = x25_subscr_ioctl(cmd, argp);
+ break;
+ case SIOCX25GFACILITIES: {
+ lock_sock(sk);
+ rc = copy_to_user(argp, &x25->facilities,
+ sizeof(x25->facilities))
+ ? -EFAULT : 0;
+ release_sock(sk);
+ break;
+ }
- case SIOCX25SFACILITIES: {
- struct x25_facilities facilities;
- rc = -EFAULT;
- if (copy_from_user(&facilities, argp,
- sizeof(facilities)))
- break;
- rc = -EINVAL;
- lock_sock(sk);
- if (sk->sk_state != TCP_LISTEN &&
- sk->sk_state != TCP_CLOSE)
+ case SIOCX25SFACILITIES: {
+ struct x25_facilities facilities;
+ rc = -EFAULT;
+ if (copy_from_user(&facilities, argp, sizeof(facilities)))
+ break;
+ rc = -EINVAL;
+ lock_sock(sk);
+ if (sk->sk_state != TCP_LISTEN &&
+ sk->sk_state != TCP_CLOSE)
+ goto out_fac_release;
+ if (facilities.pacsize_in < X25_PS16 ||
+ facilities.pacsize_in > X25_PS4096)
+ goto out_fac_release;
+ if (facilities.pacsize_out < X25_PS16 ||
+ facilities.pacsize_out > X25_PS4096)
+ goto out_fac_release;
+ if (facilities.winsize_in < 1 ||
+ facilities.winsize_in > 127)
+ goto out_fac_release;
+ if (facilities.throughput) {
+ int out = facilities.throughput & 0xf0;
+ int in = facilities.throughput & 0x0f;
+ if (!out)
+ facilities.throughput |=
+ X25_DEFAULT_THROUGHPUT << 4;
+ else if (out < 0x30 || out > 0xD0)
goto out_fac_release;
- if (facilities.pacsize_in < X25_PS16 ||
- facilities.pacsize_in > X25_PS4096)
+ if (!in)
+ facilities.throughput |=
+ X25_DEFAULT_THROUGHPUT;
+ else if (in < 0x03 || in > 0x0D)
goto out_fac_release;
- if (facilities.pacsize_out < X25_PS16 ||
- facilities.pacsize_out > X25_PS4096)
- goto out_fac_release;
- if (facilities.winsize_in < 1 ||
- facilities.winsize_in > 127)
- goto out_fac_release;
- if (facilities.throughput) {
- int out = facilities.throughput & 0xf0;
- int in = facilities.throughput & 0x0f;
- if (!out)
- facilities.throughput |=
- X25_DEFAULT_THROUGHPUT << 4;
- else if (out < 0x30 || out > 0xD0)
- goto out_fac_release;
- if (!in)
- facilities.throughput |=
- X25_DEFAULT_THROUGHPUT;
- else if (in < 0x03 || in > 0x0D)
- goto out_fac_release;
- }
- if (facilities.reverse &&
- (facilities.reverse & 0x81) != 0x81)
- goto out_fac_release;
- x25->facilities = facilities;
- rc = 0;
+ }
+ if (facilities.reverse &&
+ (facilities.reverse & 0x81) != 0x81)
+ goto out_fac_release;
+ x25->facilities = facilities;
+ rc = 0;
out_fac_release:
- release_sock(sk);
- break;
- }
+ release_sock(sk);
+ break;
+ }
- case SIOCX25GDTEFACILITIES: {
- lock_sock(sk);
- rc = copy_to_user(argp, &x25->dte_facilities,
- sizeof(x25->dte_facilities));
- release_sock(sk);
- if (rc)
- rc = -EFAULT;
- break;
- }
-
- case SIOCX25SDTEFACILITIES: {
- struct x25_dte_facilities dtefacs;
+ case SIOCX25GDTEFACILITIES: {
+ lock_sock(sk);
+ rc = copy_to_user(argp, &x25->dte_facilities,
+ sizeof(x25->dte_facilities));
+ release_sock(sk);
+ if (rc)
rc = -EFAULT;
- if (copy_from_user(&dtefacs, argp, sizeof(dtefacs)))
- break;
- rc = -EINVAL;
- lock_sock(sk);
- if (sk->sk_state != TCP_LISTEN &&
- sk->sk_state != TCP_CLOSE)
- goto out_dtefac_release;
- if (dtefacs.calling_len > X25_MAX_AE_LEN)
- goto out_dtefac_release;
- if (dtefacs.calling_ae == NULL)
- goto out_dtefac_release;
- if (dtefacs.called_len > X25_MAX_AE_LEN)
- goto out_dtefac_release;
- if (dtefacs.called_ae == NULL)
- goto out_dtefac_release;
- x25->dte_facilities = dtefacs;
- rc = 0;
+ break;
+ }
+
+ case SIOCX25SDTEFACILITIES: {
+ struct x25_dte_facilities dtefacs;
+ rc = -EFAULT;
+ if (copy_from_user(&dtefacs, argp, sizeof(dtefacs)))
+ break;
+ rc = -EINVAL;
+ lock_sock(sk);
+ if (sk->sk_state != TCP_LISTEN &&
+ sk->sk_state != TCP_CLOSE)
+ goto out_dtefac_release;
+ if (dtefacs.calling_len > X25_MAX_AE_LEN)
+ goto out_dtefac_release;
+ if (dtefacs.calling_ae == NULL)
+ goto out_dtefac_release;
+ if (dtefacs.called_len > X25_MAX_AE_LEN)
+ goto out_dtefac_release;
+ if (dtefacs.called_ae == NULL)
+ goto out_dtefac_release;
+ x25->dte_facilities = dtefacs;
+ rc = 0;
out_dtefac_release:
- release_sock(sk);
+ release_sock(sk);
+ break;
+ }
+
+ case SIOCX25GCALLUSERDATA: {
+ lock_sock(sk);
+ rc = copy_to_user(argp, &x25->calluserdata,
+ sizeof(x25->calluserdata))
+ ? -EFAULT : 0;
+ release_sock(sk);
+ break;
+ }
+
+ case SIOCX25SCALLUSERDATA: {
+ struct x25_calluserdata calluserdata;
+
+ rc = -EFAULT;
+ if (copy_from_user(&calluserdata, argp, sizeof(calluserdata)))
break;
- }
-
- case SIOCX25GCALLUSERDATA: {
- lock_sock(sk);
- rc = copy_to_user(argp, &x25->calluserdata,
- sizeof(x25->calluserdata))
- ? -EFAULT : 0;
- release_sock(sk);
+ rc = -EINVAL;
+ if (calluserdata.cudlength > X25_MAX_CUD_LEN)
break;
- }
+ lock_sock(sk);
+ x25->calluserdata = calluserdata;
+ release_sock(sk);
+ rc = 0;
+ break;
+ }
- case SIOCX25SCALLUSERDATA: {
- struct x25_calluserdata calluserdata;
+ case SIOCX25GCAUSEDIAG: {
+ lock_sock(sk);
+ rc = copy_to_user(argp, &x25->causediag, sizeof(x25->causediag))
+ ? -EFAULT : 0;
+ release_sock(sk);
+ break;
+ }
- rc = -EFAULT;
- if (copy_from_user(&calluserdata, argp,
- sizeof(calluserdata)))
- break;
- rc = -EINVAL;
- if (calluserdata.cudlength > X25_MAX_CUD_LEN)
- break;
- lock_sock(sk);
- x25->calluserdata = calluserdata;
- release_sock(sk);
- rc = 0;
+ case SIOCX25SCAUSEDIAG: {
+ struct x25_causediag causediag;
+ rc = -EFAULT;
+ if (copy_from_user(&causediag, argp, sizeof(causediag)))
break;
- }
+ lock_sock(sk);
+ x25->causediag = causediag;
+ release_sock(sk);
+ rc = 0;
+ break;
- case SIOCX25GCAUSEDIAG: {
- lock_sock(sk);
- rc = copy_to_user(argp, &x25->causediag,
- sizeof(x25->causediag))
- ? -EFAULT : 0;
- release_sock(sk);
- break;
- }
+ }
- case SIOCX25SCAUSEDIAG: {
- struct x25_causediag causediag;
- rc = -EFAULT;
- if (copy_from_user(&causediag, argp, sizeof(causediag)))
- break;
- lock_sock(sk);
- x25->causediag = causediag;
- release_sock(sk);
- rc = 0;
- break;
-
- }
-
- case SIOCX25SCUDMATCHLEN: {
- struct x25_subaddr sub_addr;
- rc = -EINVAL;
- lock_sock(sk);
- if(sk->sk_state != TCP_CLOSE)
- goto out_cud_release;
- rc = -EFAULT;
- if (copy_from_user(&sub_addr, argp,
- sizeof(sub_addr)))
- goto out_cud_release;
- rc = -EINVAL;
- if(sub_addr.cudmatchlength > X25_MAX_CUD_LEN)
- goto out_cud_release;
- x25->cudmatchlength = sub_addr.cudmatchlength;
- rc = 0;
+ case SIOCX25SCUDMATCHLEN: {
+ struct x25_subaddr sub_addr;
+ rc = -EINVAL;
+ lock_sock(sk);
+ if(sk->sk_state != TCP_CLOSE)
+ goto out_cud_release;
+ rc = -EFAULT;
+ if (copy_from_user(&sub_addr, argp,
+ sizeof(sub_addr)))
+ goto out_cud_release;
+ rc = -EINVAL;
+ if (sub_addr.cudmatchlength > X25_MAX_CUD_LEN)
+ goto out_cud_release;
+ x25->cudmatchlength = sub_addr.cudmatchlength;
+ rc = 0;
out_cud_release:
- release_sock(sk);
- break;
- }
+ release_sock(sk);
+ break;
+ }
- case SIOCX25CALLACCPTAPPRV: {
- rc = -EINVAL;
- lock_sock(sk);
- if (sk->sk_state != TCP_CLOSE)
- break;
- clear_bit(X25_ACCPT_APPRV_FLAG, &x25->flags);
- release_sock(sk);
- rc = 0;
+ case SIOCX25CALLACCPTAPPRV: {
+ rc = -EINVAL;
+ lock_sock(sk);
+ if (sk->sk_state != TCP_CLOSE)
break;
- }
+ clear_bit(X25_ACCPT_APPRV_FLAG, &x25->flags);
+ release_sock(sk);
+ rc = 0;
+ break;
+ }
- case SIOCX25SENDCALLACCPT: {
- rc = -EINVAL;
- lock_sock(sk);
- if (sk->sk_state != TCP_ESTABLISHED)
- break;
- /* must call accptapprv above */
- if (test_bit(X25_ACCPT_APPRV_FLAG, &x25->flags))
- break;
- x25_write_internal(sk, X25_CALL_ACCEPTED);
- x25->state = X25_STATE_3;
- release_sock(sk);
- rc = 0;
+ case SIOCX25SENDCALLACCPT: {
+ rc = -EINVAL;
+ lock_sock(sk);
+ if (sk->sk_state != TCP_ESTABLISHED)
break;
- }
+ /* must call accptapprv above */
+ if (test_bit(X25_ACCPT_APPRV_FLAG, &x25->flags))
+ break;
+ x25_write_internal(sk, X25_CALL_ACCEPTED);
+ x25->state = X25_STATE_3;
+ release_sock(sk);
+ rc = 0;
+ break;
+ }
- default:
- rc = -ENOIOCTLCMD;
- break;
+ default:
+ rc = -ENOIOCTLCMD;
+ break;
}
return rc;
diff --git a/net/x25/x25_dev.c b/net/x25/x25_dev.c
index 9005f6d..e547ca1 100644
--- a/net/x25/x25_dev.c
+++ b/net/x25/x25_dev.c
@@ -146,21 +146,21 @@
unsigned char *ptr;
switch (nb->dev->type) {
- case ARPHRD_X25:
- if ((skb = alloc_skb(1, GFP_ATOMIC)) == NULL) {
- printk(KERN_ERR "x25_dev: out of memory\n");
- return;
- }
- ptr = skb_put(skb, 1);
- *ptr = X25_IFACE_CONNECT;
- break;
+ case ARPHRD_X25:
+ if ((skb = alloc_skb(1, GFP_ATOMIC)) == NULL) {
+ printk(KERN_ERR "x25_dev: out of memory\n");
+ return;
+ }
+ ptr = skb_put(skb, 1);
+ *ptr = X25_IFACE_CONNECT;
+ break;
#if defined(CONFIG_LLC) || defined(CONFIG_LLC_MODULE)
- case ARPHRD_ETHER:
- return;
+ case ARPHRD_ETHER:
+ return;
#endif
- default:
- return;
+ default:
+ return;
}
skb->protocol = htons(ETH_P_X25);
@@ -202,19 +202,19 @@
skb_reset_network_header(skb);
switch (nb->dev->type) {
- case ARPHRD_X25:
- dptr = skb_push(skb, 1);
- *dptr = X25_IFACE_DATA;
- break;
+ case ARPHRD_X25:
+ dptr = skb_push(skb, 1);
+ *dptr = X25_IFACE_DATA;
+ break;
#if defined(CONFIG_LLC) || defined(CONFIG_LLC_MODULE)
- case ARPHRD_ETHER:
- kfree_skb(skb);
- return;
+ case ARPHRD_ETHER:
+ kfree_skb(skb);
+ return;
#endif
- default:
- kfree_skb(skb);
- return;
+ default:
+ kfree_skb(skb);
+ return;
}
skb->protocol = htons(ETH_P_X25);
diff --git a/net/x25/x25_in.c b/net/x25/x25_in.c
index 15de65f..0b073b5 100644
--- a/net/x25/x25_in.c
+++ b/net/x25/x25_in.c
@@ -94,55 +94,55 @@
struct x25_sock *x25 = x25_sk(sk);
switch (frametype) {
- case X25_CALL_ACCEPTED: {
+ case X25_CALL_ACCEPTED: {
- x25_stop_timer(sk);
- x25->condition = 0x00;
- x25->vs = 0;
- x25->va = 0;
- x25->vr = 0;
- x25->vl = 0;
- x25->state = X25_STATE_3;
- sk->sk_state = TCP_ESTABLISHED;
- /*
- * Parse the data in the frame.
- */
- skb_pull(skb, X25_STD_MIN_LEN);
+ x25_stop_timer(sk);
+ x25->condition = 0x00;
+ x25->vs = 0;
+ x25->va = 0;
+ x25->vr = 0;
+ x25->vl = 0;
+ x25->state = X25_STATE_3;
+ sk->sk_state = TCP_ESTABLISHED;
+ /*
+ * Parse the data in the frame.
+ */
+ skb_pull(skb, X25_STD_MIN_LEN);
- len = x25_parse_address_block(skb, &source_addr,
- &dest_addr);
- if (len > 0)
- skb_pull(skb, len);
- else if (len < 0)
- goto out_clear;
+ len = x25_parse_address_block(skb, &source_addr,
+ &dest_addr);
+ if (len > 0)
+ skb_pull(skb, len);
+ else if (len < 0)
+ goto out_clear;
- len = x25_parse_facilities(skb, &x25->facilities,
- &x25->dte_facilities,
- &x25->vc_facil_mask);
- if (len > 0)
- skb_pull(skb, len);
- else if (len < 0)
- goto out_clear;
- /*
- * Copy any Call User Data.
- */
- if (skb->len > 0) {
- skb_copy_from_linear_data(skb,
- x25->calluserdata.cuddata,
- skb->len);
- x25->calluserdata.cudlength = skb->len;
- }
- if (!sock_flag(sk, SOCK_DEAD))
- sk->sk_state_change(sk);
- break;
+ len = x25_parse_facilities(skb, &x25->facilities,
+ &x25->dte_facilities,
+ &x25->vc_facil_mask);
+ if (len > 0)
+ skb_pull(skb, len);
+ else if (len < 0)
+ goto out_clear;
+ /*
+ * Copy any Call User Data.
+ */
+ if (skb->len > 0) {
+ skb_copy_from_linear_data(skb,
+ x25->calluserdata.cuddata,
+ skb->len);
+ x25->calluserdata.cudlength = skb->len;
}
- case X25_CLEAR_REQUEST:
- x25_write_internal(sk, X25_CLEAR_CONFIRMATION);
- x25_disconnect(sk, ECONNREFUSED, skb->data[3], skb->data[4]);
- break;
+ if (!sock_flag(sk, SOCK_DEAD))
+ sk->sk_state_change(sk);
+ break;
+ }
+ case X25_CLEAR_REQUEST:
+ x25_write_internal(sk, X25_CLEAR_CONFIRMATION);
+ x25_disconnect(sk, ECONNREFUSED, skb->data[3], skb->data[4]);
+ break;
- default:
- break;
+ default:
+ break;
}
return 0;
@@ -354,18 +354,18 @@
frametype = x25_decode(sk, skb, &ns, &nr, &q, &d, &m);
switch (x25->state) {
- case X25_STATE_1:
- queued = x25_state1_machine(sk, skb, frametype);
- break;
- case X25_STATE_2:
- queued = x25_state2_machine(sk, skb, frametype);
- break;
- case X25_STATE_3:
- queued = x25_state3_machine(sk, skb, frametype, ns, nr, q, d, m);
- break;
- case X25_STATE_4:
- queued = x25_state4_machine(sk, skb, frametype);
- break;
+ case X25_STATE_1:
+ queued = x25_state1_machine(sk, skb, frametype);
+ break;
+ case X25_STATE_2:
+ queued = x25_state2_machine(sk, skb, frametype);
+ break;
+ case X25_STATE_3:
+ queued = x25_state3_machine(sk, skb, frametype, ns, nr, q, d, m);
+ break;
+ case X25_STATE_4:
+ queued = x25_state4_machine(sk, skb, frametype);
+ break;
}
x25_kick(sk);
diff --git a/net/x25/x25_link.c b/net/x25/x25_link.c
index 2130692..037958f 100644
--- a/net/x25/x25_link.c
+++ b/net/x25/x25_link.c
@@ -76,30 +76,29 @@
int confirm;
switch (frametype) {
- case X25_RESTART_REQUEST:
- confirm = !x25_t20timer_pending(nb);
- x25_stop_t20timer(nb);
- nb->state = X25_LINK_STATE_3;
- if (confirm)
- x25_transmit_restart_confirmation(nb);
- break;
+ case X25_RESTART_REQUEST:
+ confirm = !x25_t20timer_pending(nb);
+ x25_stop_t20timer(nb);
+ nb->state = X25_LINK_STATE_3;
+ if (confirm)
+ x25_transmit_restart_confirmation(nb);
+ break;
- case X25_RESTART_CONFIRMATION:
- x25_stop_t20timer(nb);
- nb->state = X25_LINK_STATE_3;
- break;
+ case X25_RESTART_CONFIRMATION:
+ x25_stop_t20timer(nb);
+ nb->state = X25_LINK_STATE_3;
+ break;
- case X25_DIAGNOSTIC:
- printk(KERN_WARNING "x25: diagnostic #%d - "
- "%02X %02X %02X\n",
- skb->data[3], skb->data[4],
- skb->data[5], skb->data[6]);
- break;
+ case X25_DIAGNOSTIC:
+ printk(KERN_WARNING "x25: diagnostic #%d - %02X %02X %02X\n",
+ skb->data[3], skb->data[4],
+ skb->data[5], skb->data[6]);
+ break;
- default:
- printk(KERN_WARNING "x25: received unknown %02X "
- "with LCI 000\n", frametype);
- break;
+ default:
+ printk(KERN_WARNING "x25: received unknown %02X with LCI 000\n",
+ frametype);
+ break;
}
if (nb->state == X25_LINK_STATE_3)
@@ -193,18 +192,18 @@
void x25_transmit_link(struct sk_buff *skb, struct x25_neigh *nb)
{
switch (nb->state) {
- case X25_LINK_STATE_0:
- skb_queue_tail(&nb->queue, skb);
- nb->state = X25_LINK_STATE_1;
- x25_establish_link(nb);
- break;
- case X25_LINK_STATE_1:
- case X25_LINK_STATE_2:
- skb_queue_tail(&nb->queue, skb);
- break;
- case X25_LINK_STATE_3:
- x25_send_frame(skb, nb);
- break;
+ case X25_LINK_STATE_0:
+ skb_queue_tail(&nb->queue, skb);
+ nb->state = X25_LINK_STATE_1;
+ x25_establish_link(nb);
+ break;
+ case X25_LINK_STATE_1:
+ case X25_LINK_STATE_2:
+ skb_queue_tail(&nb->queue, skb);
+ break;
+ case X25_LINK_STATE_3:
+ x25_send_frame(skb, nb);
+ break;
}
}
@@ -214,14 +213,14 @@
void x25_link_established(struct x25_neigh *nb)
{
switch (nb->state) {
- case X25_LINK_STATE_0:
- nb->state = X25_LINK_STATE_2;
- break;
- case X25_LINK_STATE_1:
- x25_transmit_restart_request(nb);
- nb->state = X25_LINK_STATE_2;
- x25_start_t20timer(nb);
- break;
+ case X25_LINK_STATE_0:
+ nb->state = X25_LINK_STATE_2;
+ break;
+ case X25_LINK_STATE_1:
+ x25_transmit_restart_request(nb);
+ nb->state = X25_LINK_STATE_2;
+ x25_start_t20timer(nb);
+ break;
}
}
diff --git a/net/x25/x25_subr.c b/net/x25/x25_subr.c
index dc20cf1..24a342e 100644
--- a/net/x25/x25_subr.c
+++ b/net/x25/x25_subr.c
@@ -126,32 +126,30 @@
* Adjust frame size.
*/
switch (frametype) {
- case X25_CALL_REQUEST:
- len += 1 + X25_ADDR_LEN + X25_MAX_FAC_LEN +
- X25_MAX_CUD_LEN;
- break;
- case X25_CALL_ACCEPTED: /* fast sel with no restr on resp */
- if(x25->facilities.reverse & 0x80) {
- len += 1 + X25_MAX_FAC_LEN + X25_MAX_CUD_LEN;
- } else {
- len += 1 + X25_MAX_FAC_LEN;
- }
- break;
- case X25_CLEAR_REQUEST:
- case X25_RESET_REQUEST:
- len += 2;
- break;
- case X25_RR:
- case X25_RNR:
- case X25_REJ:
- case X25_CLEAR_CONFIRMATION:
- case X25_INTERRUPT_CONFIRMATION:
- case X25_RESET_CONFIRMATION:
- break;
- default:
- printk(KERN_ERR "X.25: invalid frame type %02X\n",
- frametype);
- return;
+ case X25_CALL_REQUEST:
+ len += 1 + X25_ADDR_LEN + X25_MAX_FAC_LEN + X25_MAX_CUD_LEN;
+ break;
+ case X25_CALL_ACCEPTED: /* fast sel with no restr on resp */
+ if (x25->facilities.reverse & 0x80) {
+ len += 1 + X25_MAX_FAC_LEN + X25_MAX_CUD_LEN;
+ } else {
+ len += 1 + X25_MAX_FAC_LEN;
+ }
+ break;
+ case X25_CLEAR_REQUEST:
+ case X25_RESET_REQUEST:
+ len += 2;
+ break;
+ case X25_RR:
+ case X25_RNR:
+ case X25_REJ:
+ case X25_CLEAR_CONFIRMATION:
+ case X25_INTERRUPT_CONFIRMATION:
+ case X25_RESET_CONFIRMATION:
+ break;
+ default:
+ printk(KERN_ERR "X.25: invalid frame type %02X\n", frametype);
+ return;
}
if ((skb = alloc_skb(len, GFP_ATOMIC)) == NULL)
@@ -276,20 +274,20 @@
*ns = *nr = *q = *d = *m = 0;
switch (frame[2]) {
- case X25_CALL_REQUEST:
- case X25_CALL_ACCEPTED:
- case X25_CLEAR_REQUEST:
- case X25_CLEAR_CONFIRMATION:
- case X25_INTERRUPT:
- case X25_INTERRUPT_CONFIRMATION:
- case X25_RESET_REQUEST:
- case X25_RESET_CONFIRMATION:
- case X25_RESTART_REQUEST:
- case X25_RESTART_CONFIRMATION:
- case X25_REGISTRATION_REQUEST:
- case X25_REGISTRATION_CONFIRMATION:
- case X25_DIAGNOSTIC:
- return frame[2];
+ case X25_CALL_REQUEST:
+ case X25_CALL_ACCEPTED:
+ case X25_CLEAR_REQUEST:
+ case X25_CLEAR_CONFIRMATION:
+ case X25_INTERRUPT:
+ case X25_INTERRUPT_CONFIRMATION:
+ case X25_RESET_REQUEST:
+ case X25_RESET_CONFIRMATION:
+ case X25_RESTART_REQUEST:
+ case X25_RESTART_CONFIRMATION:
+ case X25_REGISTRATION_REQUEST:
+ case X25_REGISTRATION_CONFIRMATION:
+ case X25_DIAGNOSTIC:
+ return frame[2];
}
if (x25->neighbour->extended) {
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index c658cb3..0256b8a 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -2299,7 +2299,8 @@
if (link->dump == NULL)
return -EINVAL;
- return netlink_dump_start(net->xfrm.nlsk, skb, nlh, link->dump, link->done);
+ return netlink_dump_start(net->xfrm.nlsk, skb, nlh,
+ link->dump, link->done, 0);
}
err = nlmsg_parse(nlh, xfrm_msg_min[type], attrs, XFRMA_MAX,
diff --git a/security/apparmor/lib.c b/security/apparmor/lib.c
index 506d2ba..b82e383 100644
--- a/security/apparmor/lib.c
+++ b/security/apparmor/lib.c
@@ -12,6 +12,7 @@
* License.
*/
+#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/vmalloc.h>