diff options
Diffstat (limited to 'drivers/net')
180 files changed, 8349 insertions, 5615 deletions
diff --git a/drivers/net/3c507.c b/drivers/net/3c507.c index ea9b7a098c9b..475a66d95b34 100644 --- a/drivers/net/3c507.c +++ b/drivers/net/3c507.c @@ -201,7 +201,7 @@ struct net_local { #define RX_BUF_SIZE (1518+14+18) /* packet+header+RBD */ #define RX_BUF_END (dev->mem_end - dev->mem_start) -#define TX_TIMEOUT 5 +#define TX_TIMEOUT (HZ/20) /* That's it: only 86 bytes to set up the beast, including every extra diff --git a/drivers/net/3c515.c b/drivers/net/3c515.c index cdf7226a7c43..d2bb4b254c57 100644 --- a/drivers/net/3c515.c +++ b/drivers/net/3c515.c @@ -98,7 +98,7 @@ static int rx_nocopy, rx_copy, queued_packet; #define WAIT_TX_AVAIL 200 /* Operational parameter that usually are not changed. */ -#define TX_TIMEOUT 40 /* Time in jiffies before concluding Tx hung */ +#define TX_TIMEOUT ((4*HZ)/10) /* Time in jiffies before concluding Tx hung */ /* The size here is somewhat misleading: the Corkscrew also uses the ISA aliased registers at <base>+0x400. diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c index e1da258bbfb7..0a92436f0538 100644 --- a/drivers/net/3c59x.c +++ b/drivers/net/3c59x.c @@ -699,7 +699,8 @@ DEFINE_WINDOW_IO(32) #define DEVICE_PCI(dev) NULL #endif -#define VORTEX_PCI(vp) (((vp)->gendev) ? DEVICE_PCI((vp)->gendev) : NULL) +#define VORTEX_PCI(vp) \ + ((struct pci_dev *) (((vp)->gendev) ? DEVICE_PCI((vp)->gendev) : NULL)) #ifdef CONFIG_EISA #define DEVICE_EISA(dev) (((dev)->bus == &eisa_bus_type) ? to_eisa_device((dev)) : NULL) @@ -707,7 +708,8 @@ DEFINE_WINDOW_IO(32) #define DEVICE_EISA(dev) NULL #endif -#define VORTEX_EISA(vp) (((vp)->gendev) ? DEVICE_EISA((vp)->gendev) : NULL) +#define VORTEX_EISA(vp) \ + ((struct eisa_device *) (((vp)->gendev) ? DEVICE_EISA((vp)->gendev) : NULL)) /* The action to take with a media selection timer tick. Note that we deviate from the 3Com order by checking 10base2 before AUI. diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c index ac422cd332ea..dd16e83933a2 100644 --- a/drivers/net/8139cp.c +++ b/drivers/net/8139cp.c @@ -490,13 +490,11 @@ static inline unsigned int cp_rx_csum_ok (u32 status) { unsigned int protocol = (status >> 16) & 0x3; - if (likely((protocol == RxProtoTCP) && (!(status & TCPFail)))) + if (((protocol == RxProtoTCP) && !(status & TCPFail)) || + ((protocol == RxProtoUDP) && !(status & UDPFail))) return 1; - else if ((protocol == RxProtoUDP) && (!(status & UDPFail))) - return 1; - else if ((protocol == RxProtoIP) && (!(status & IPFail))) - return 1; - return 0; + else + return 0; } static int cp_rx_poll(struct napi_struct *napi, int budget) diff --git a/drivers/net/82596.c b/drivers/net/82596.c index e2c9c5b949f9..be1f1970c842 100644 --- a/drivers/net/82596.c +++ b/drivers/net/82596.c @@ -191,7 +191,7 @@ enum commands { #define RX_SUSPEND 0x0030 #define RX_ABORT 0x0040 -#define TX_TIMEOUT 5 +#define TX_TIMEOUT (HZ/20) struct i596_reg { diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index f6668cdaac85..a11dc735752c 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -1533,7 +1533,7 @@ config E100 <http://support.intel.com/support/network/adapter/pro100/21397.htm> - to identify the adapter. + to identify the adapter. For the latest Intel PRO/100 network driver for Linux, see: @@ -1786,17 +1786,17 @@ config KS8842 tristate "Micrel KSZ8841/42 with generic bus interface" depends on HAS_IOMEM && DMA_ENGINE help - This platform driver is for KSZ8841(1-port) / KS8842(2-port) - ethernet switch chip (managed, VLAN, QoS) from Micrel or - Timberdale(FPGA). + This platform driver is for KSZ8841(1-port) / KS8842(2-port) + ethernet switch chip (managed, VLAN, QoS) from Micrel or + Timberdale(FPGA). config KS8851 - tristate "Micrel KS8851 SPI" - depends on SPI - select MII + tristate "Micrel KS8851 SPI" + depends on SPI + select MII select CRC32 - help - SPI driver for Micrel KS8851 SPI attached network chip. + help + SPI driver for Micrel KS8851 SPI attached network chip. config KS8851_MLL tristate "Micrel KS8851 MLL" @@ -2133,25 +2133,25 @@ config IP1000 will be called ipg. This is recommended. config IGB - tristate "Intel(R) 82575/82576 PCI-Express Gigabit Ethernet support" - depends on PCI - ---help--- - This driver supports Intel(R) 82575/82576 gigabit ethernet family of - adapters. For more information on how to identify your adapter, go - to the Adapter & Driver ID Guide at: + tristate "Intel(R) 82575/82576 PCI-Express Gigabit Ethernet support" + depends on PCI + ---help--- + This driver supports Intel(R) 82575/82576 gigabit ethernet family of + adapters. For more information on how to identify your adapter, go + to the Adapter & Driver ID Guide at: - <http://support.intel.com/support/network/adapter/pro100/21397.htm> + <http://support.intel.com/support/network/adapter/pro100/21397.htm> - For general information and support, go to the Intel support - website at: + For general information and support, go to the Intel support + website at: - <http://support.intel.com> + <http://support.intel.com> - More specific information on configuring the driver is in - <file:Documentation/networking/e1000.txt>. + More specific information on configuring the driver is in + <file:Documentation/networking/e1000.txt>. - To compile this driver as a module, choose M here. The module - will be called igb. + To compile this driver as a module, choose M here. The module + will be called igb. config IGB_DCA bool "Direct Cache Access (DCA) Support" @@ -2163,25 +2163,25 @@ config IGB_DCA is used, with the intent of lessening the impact of cache misses. config IGBVF - tristate "Intel(R) 82576 Virtual Function Ethernet support" - depends on PCI - ---help--- - This driver supports Intel(R) 82576 virtual functions. For more - information on how to identify your adapter, go to the Adapter & - Driver ID Guide at: + tristate "Intel(R) 82576 Virtual Function Ethernet support" + depends on PCI + ---help--- + This driver supports Intel(R) 82576 virtual functions. For more + information on how to identify your adapter, go to the Adapter & + Driver ID Guide at: - <http://support.intel.com/support/network/adapter/pro100/21397.htm> + <http://support.intel.com/support/network/adapter/pro100/21397.htm> - For general information and support, go to the Intel support - website at: + For general information and support, go to the Intel support + website at: - <http://support.intel.com> + <http://support.intel.com> - More specific information on configuring the driver is in - <file:Documentation/networking/e1000.txt>. + More specific information on configuring the driver is in + <file:Documentation/networking/e1000.txt>. - To compile this driver as a module, choose M here. The module - will be called igbvf. + To compile this driver as a module, choose M here. The module + will be called igbvf. source "drivers/net/ixp2000/Kconfig" @@ -2300,14 +2300,14 @@ config SKGE will be called skge. This is recommended. config SKGE_DEBUG - bool "Debugging interface" - depends on SKGE && DEBUG_FS - help - This option adds the ability to dump driver state for debugging. - The file /sys/kernel/debug/skge/ethX displays the state of the internal - transmit and receive rings. + bool "Debugging interface" + depends on SKGE && DEBUG_FS + help + This option adds the ability to dump driver state for debugging. + The file /sys/kernel/debug/skge/ethX displays the state of the internal + transmit and receive rings. - If unsure, say N. + If unsure, say N. config SKY2 tristate "SysKonnect Yukon2 support" @@ -2326,14 +2326,14 @@ config SKY2 will be called sky2. This is recommended. config SKY2_DEBUG - bool "Debugging interface" - depends on SKY2 && DEBUG_FS - help - This option adds the ability to dump driver state for debugging. - The file /sys/kernel/debug/sky2/ethX displays the state of the internal - transmit and receive rings. + bool "Debugging interface" + depends on SKY2 && DEBUG_FS + help + This option adds the ability to dump driver state for debugging. + The file /sys/kernel/debug/sky2/ethX displays the state of the internal + transmit and receive rings. - If unsure, say N. + If unsure, say N. config VIA_VELOCITY tristate "VIA Velocity support" @@ -2389,12 +2389,12 @@ config SPIDER_NET Cell Processor-Based Blades from IBM. config TSI108_ETH - tristate "Tundra TSI108 gigabit Ethernet support" - depends on TSI108_BRIDGE - help - This driver supports Tundra TSI108 gigabit Ethernet ports. - To compile this driver as a module, choose M here: the module - will be called tsi108_eth. + tristate "Tundra TSI108 gigabit Ethernet support" + depends on TSI108_BRIDGE + help + This driver supports Tundra TSI108 gigabit Ethernet ports. + To compile this driver as a module, choose M here: the module + will be called tsi108_eth. config GELIC_NET tristate "PS3 Gigabit Ethernet driver" @@ -2573,32 +2573,32 @@ config MDIO tristate config CHELSIO_T1 - tristate "Chelsio 10Gb Ethernet support" - depends on PCI + tristate "Chelsio 10Gb Ethernet support" + depends on PCI select CRC32 select MDIO - help - This driver supports Chelsio gigabit and 10-gigabit - Ethernet cards. More information about adapter features and + help + This driver supports Chelsio gigabit and 10-gigabit + Ethernet cards. More information about adapter features and performance tuning is in <file:Documentation/networking/cxgb.txt>. - For general information about Chelsio and our products, visit - our website at <http://www.chelsio.com>. + For general information about Chelsio and our products, visit + our website at <http://www.chelsio.com>. - For customer support, please visit our customer support page at - <http://www.chelsio.com/support.html>. + For customer support, please visit our customer support page at + <http://www.chelsio.com/support.html>. - Please send feedback to <linux-bugs@chelsio.com>. + Please send feedback to <linux-bugs@chelsio.com>. - To compile this driver as a module, choose M here: the module - will be called cxgb. + To compile this driver as a module, choose M here: the module + will be called cxgb. config CHELSIO_T1_1G - bool "Chelsio gigabit Ethernet support" - depends on CHELSIO_T1 - help - Enables support for Chelsio's gigabit Ethernet PCI cards. If you - are using only 10G cards say 'N' here. + bool "Chelsio gigabit Ethernet support" + depends on CHELSIO_T1 + help + Enables support for Chelsio's gigabit Ethernet PCI cards. If you + are using only 10G cards say 'N' here. config CHELSIO_T3_DEPENDS tristate @@ -2728,26 +2728,26 @@ config IXGBE_DCB If unsure, say N. config IXGBEVF - tristate "Intel(R) 82599 Virtual Function Ethernet support" - depends on PCI_MSI - ---help--- - This driver supports Intel(R) 82599 virtual functions. For more - information on how to identify your adapter, go to the Adapter & - Driver ID Guide at: + tristate "Intel(R) 82599 Virtual Function Ethernet support" + depends on PCI_MSI + ---help--- + This driver supports Intel(R) 82599 virtual functions. For more + information on how to identify your adapter, go to the Adapter & + Driver ID Guide at: - <http://support.intel.com/support/network/sb/CS-008441.htm> + <http://support.intel.com/support/network/sb/CS-008441.htm> - For general information and support, go to the Intel support - website at: + For general information and support, go to the Intel support + website at: - <http://support.intel.com> + <http://support.intel.com> - More specific information on configuring the driver is in - <file:Documentation/networking/ixgbevf.txt>. + More specific information on configuring the driver is in + <file:Documentation/networking/ixgbevf.txt>. - To compile this driver as a module, choose M here. The module - will be called ixgbevf. MSI-X interrupt support is required - for this driver to work correctly. + To compile this driver as a module, choose M here. The module + will be called ixgbevf. MSI-X interrupt support is required + for this driver to work correctly. config IXGB tristate "Intel(R) PRO/10GbE support" @@ -2772,29 +2772,38 @@ config IXGB will be called ixgb. config S2IO - tristate "S2IO 10Gbe XFrame NIC" + tristate "Exar Xframe 10Gb Ethernet Adapter" depends on PCI ---help--- - This driver supports the 10Gbe XFrame NIC of S2IO. + This driver supports Exar Corp's Xframe Series 10Gb Ethernet Adapters. + More specific information on configuring the driver is in <file:Documentation/networking/s2io.txt>. + To compile this driver as a module, choose M here. The module + will be called s2io. + config VXGE - tristate "Neterion X3100 Series 10GbE PCIe Server Adapter" + tristate "Exar X3100 Series 10GbE PCIe Server Adapter" depends on PCI && INET ---help--- - This driver supports Neterion Inc's X3100 Series 10 GbE PCIe + This driver supports Exar Corp's X3100 Series 10 GbE PCIe I/O Virtualized Server Adapter. + More specific information on configuring the driver is in <file:Documentation/networking/vxge.txt>. + To compile this driver as a module, choose M here. The module + will be called vxge. + config VXGE_DEBUG_TRACE_ALL bool "Enabling All Debug trace statments in driver" default n depends on VXGE ---help--- Say Y here if you want to enabling all the debug trace statements in - driver. By default only few debug trace statements are enabled. + the vxge driver. By default only few debug trace statements are + enabled. config MYRI10GE tristate "Myricom Myri-10G Ethernet support" @@ -2906,18 +2915,18 @@ config QLGE will be called qlge. config BNA - tristate "Brocade 1010/1020 10Gb Ethernet Driver support" - depends on PCI - ---help--- - This driver supports Brocade 1010/1020 10Gb CEE capable Ethernet - cards. - To compile this driver as a module, choose M here: the module - will be called bna. + tristate "Brocade 1010/1020 10Gb Ethernet Driver support" + depends on PCI + ---help--- + This driver supports Brocade 1010/1020 10Gb CEE capable Ethernet + cards. + To compile this driver as a module, choose M here: the module + will be called bna. - For general information and support, go to the Brocade support - website at: + For general information and support, go to the Brocade support + website at: - <http://support.brocade.com> + <http://support.brocade.com> source "drivers/net/sfc/Kconfig" @@ -3227,18 +3236,18 @@ config PPP_BSDCOMP modules once you have said "make modules". If unsure, say N. config PPP_MPPE - tristate "PPP MPPE compression (encryption) (EXPERIMENTAL)" - depends on PPP && EXPERIMENTAL - select CRYPTO - select CRYPTO_SHA1 - select CRYPTO_ARC4 - select CRYPTO_ECB - ---help--- - Support for the MPPE Encryption protocol, as employed by the - Microsoft Point-to-Point Tunneling Protocol. - - See http://pptpclient.sourceforge.net/ for information on - configuring PPTP clients and servers to utilize this method. + tristate "PPP MPPE compression (encryption) (EXPERIMENTAL)" + depends on PPP && EXPERIMENTAL + select CRYPTO + select CRYPTO_SHA1 + select CRYPTO_ARC4 + select CRYPTO_ECB + ---help--- + Support for the MPPE Encryption protocol, as employed by the + Microsoft Point-to-Point Tunneling Protocol. + + See http://pptpclient.sourceforge.net/ for information on + configuring PPTP clients and servers to utilize this method. config PPPOE tristate "PPP over Ethernet (EXPERIMENTAL)" @@ -3397,14 +3406,14 @@ config VIRTIO_NET depends on EXPERIMENTAL && VIRTIO ---help--- This is the virtual network driver for virtio. It can be used with - lguest or QEMU based VMMs (like KVM or Xen). Say Y or M. + lguest or QEMU based VMMs (like KVM or Xen). Say Y or M. config VMXNET3 - tristate "VMware VMXNET3 ethernet driver" - depends on PCI && INET - help - This driver supports VMware's vmxnet3 virtual ethernet NIC. - To compile this driver as a module, choose M here: the - module will be called vmxnet3. + tristate "VMware VMXNET3 ethernet driver" + depends on PCI && INET + help + This driver supports VMware's vmxnet3 virtual ethernet NIC. + To compile this driver as a module, choose M here: the + module will be called vmxnet3. endif # NETDEVICES diff --git a/drivers/net/arm/w90p910_ether.c b/drivers/net/arm/w90p910_ether.c index 4545d5a06c24..bfea499a3513 100644 --- a/drivers/net/arm/w90p910_ether.c +++ b/drivers/net/arm/w90p910_ether.c @@ -117,7 +117,7 @@ #define TX_DESC_SIZE 10 #define MAX_RBUFF_SZ 0x600 #define MAX_TBUFF_SZ 0x600 -#define TX_TIMEOUT 50 +#define TX_TIMEOUT (HZ/2) #define DELAY 1000 #define CAM0 0x0 diff --git a/drivers/net/at1700.c b/drivers/net/at1700.c index 89876897a6fe..871b1633f543 100644 --- a/drivers/net/at1700.c +++ b/drivers/net/at1700.c @@ -150,7 +150,7 @@ struct net_local { #define PORT_OFFSET(o) (o) -#define TX_TIMEOUT 10 +#define TX_TIMEOUT (HZ/10) /* Index to functions, as function prototypes. */ diff --git a/drivers/net/atarilance.c b/drivers/net/atarilance.c index 8cb27cb7bca1..ce0091eb06f5 100644 --- a/drivers/net/atarilance.c +++ b/drivers/net/atarilance.c @@ -116,7 +116,7 @@ MODULE_LICENSE("GPL"); #define RX_RING_LEN_BITS (RX_LOG_RING_SIZE << 5) #define RX_RING_MOD_MASK (RX_RING_SIZE - 1) -#define TX_TIMEOUT 20 +#define TX_TIMEOUT (HZ/5) /* The LANCE Rx and Tx ring descriptors. */ struct lance_rx_head { diff --git a/drivers/net/atlx/atl1.c b/drivers/net/atlx/atl1.c index 43579b3b24ac..53363108994e 100644 --- a/drivers/net/atlx/atl1.c +++ b/drivers/net/atlx/atl1.c @@ -3043,7 +3043,6 @@ static int __devinit atl1_probe(struct pci_dev *pdev, atl1_pcie_patch(adapter); /* assume we have no link for now */ netif_carrier_off(netdev); - netif_stop_queue(netdev); setup_timer(&adapter->phy_config_timer, atl1_phy_config, (unsigned long)adapter); diff --git a/drivers/net/ax88796.c b/drivers/net/ax88796.c index b6da4cf3694b..4bebff3faeab 100644 --- a/drivers/net/ax88796.c +++ b/drivers/net/ax88796.c @@ -325,7 +325,7 @@ static void ax_block_output(struct net_device *dev, int count, static void ax_mii_ei_outbits(struct net_device *dev, unsigned int bits, int len) { - struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev); + struct ei_device *ei_local = netdev_priv(dev); void __iomem *memr_addr = (void __iomem *)dev->base_addr + AX_MEMR; unsigned int memr; @@ -364,7 +364,7 @@ ax_mii_ei_outbits(struct net_device *dev, unsigned int bits, int len) static unsigned int ax_phy_ei_inbits(struct net_device *dev, int no) { - struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev); + struct ei_device *ei_local = netdev_priv(dev); void __iomem *memr_addr = (void __iomem *)dev->base_addr + AX_MEMR; unsigned int memr; unsigned int result = 0; @@ -412,7 +412,7 @@ ax_phy_issueaddr(struct net_device *dev, int phy_addr, int reg, int opc) static int ax_phy_read(struct net_device *dev, int phy_addr, int reg) { - struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev); + struct ei_device *ei_local = netdev_priv(dev); unsigned long flags; unsigned int result; @@ -435,7 +435,7 @@ ax_phy_read(struct net_device *dev, int phy_addr, int reg) static void ax_phy_write(struct net_device *dev, int phy_addr, int reg, int value) { - struct ei_device *ei = (struct ei_device *) netdev_priv(dev); + struct ei_device *ei = netdev_priv(dev); struct ax_device *ax = to_ax_dev(dev); unsigned long flags; diff --git a/drivers/net/benet/be.h b/drivers/net/benet/be.h index 4594a28b1f66..b61a1dfebcaf 100644 --- a/drivers/net/benet/be.h +++ b/drivers/net/benet/be.h @@ -38,14 +38,17 @@ #define BE_NAME "ServerEngines BladeEngine2 10Gbps NIC" #define BE3_NAME "ServerEngines BladeEngine3 10Gbps NIC" #define OC_NAME "Emulex OneConnect 10Gbps NIC" -#define OC_NAME1 "Emulex OneConnect 10Gbps NIC (be3)" +#define OC_NAME_BE OC_NAME "(be3)" +#define OC_NAME_LANCER OC_NAME "(Lancer)" #define DRV_DESC "ServerEngines BladeEngine 10Gbps NIC Driver" #define BE_VENDOR_ID 0x19a2 +#define EMULEX_VENDOR_ID 0x10df #define BE_DEVICE_ID1 0x211 #define BE_DEVICE_ID2 0x221 -#define OC_DEVICE_ID1 0x700 -#define OC_DEVICE_ID2 0x710 +#define OC_DEVICE_ID1 0x700 /* Device Id for BE2 cards */ +#define OC_DEVICE_ID2 0x710 /* Device Id for BE3 cards */ +#define OC_DEVICE_ID3 0xe220 /* Device id for Lancer cards */ static inline char *nic_name(struct pci_dev *pdev) { @@ -53,7 +56,9 @@ static inline char *nic_name(struct pci_dev *pdev) case OC_DEVICE_ID1: return OC_NAME; case OC_DEVICE_ID2: - return OC_NAME1; + return OC_NAME_BE; + case OC_DEVICE_ID3: + return OC_NAME_LANCER; case BE_DEVICE_ID2: return BE3_NAME; default: @@ -149,6 +154,7 @@ struct be_eq_obj { u16 min_eqd; /* in usecs */ u16 max_eqd; /* in usecs */ u16 cur_eqd; /* in usecs */ + u8 msix_vec_idx; struct napi_struct napi; }; @@ -260,6 +266,8 @@ struct be_adapter { u32 num_rx_qs; u32 big_page_size; /* Compounded page size shared by rx wrbs */ + u8 msix_vec_next_idx; + struct vlan_group *vlan_grp; u16 vlans_added; u16 max_vlans; /* Number of vlans supported */ @@ -299,8 +307,8 @@ struct be_adapter { bool sriov_enabled; struct be_vf_cfg vf_cfg[BE_MAX_VF]; - u8 base_eq_id; u8 is_virtfn; + u32 sli_family; }; #define be_physfn(adapter) (!adapter->is_virtfn) @@ -309,6 +317,8 @@ struct be_adapter { #define BE_GEN2 2 #define BE_GEN3 3 +#define lancer_chip(adapter) (adapter->pdev->device == OC_DEVICE_ID3) + extern const struct ethtool_ops be_ethtool_ops; #define tx_stats(adapter) (&adapter->tx_stats) @@ -416,10 +426,17 @@ static inline u8 is_udp_pkt(struct sk_buff *skb) static inline void be_check_sriov_fn_type(struct be_adapter *adapter) { u8 data; - - pci_write_config_byte(adapter->pdev, 0xFE, 0xAA); - pci_read_config_byte(adapter->pdev, 0xFE, &data); - adapter->is_virtfn = (data != 0xAA); + u32 sli_intf; + + if (lancer_chip(adapter)) { + pci_read_config_dword(adapter->pdev, SLI_INTF_REG_OFFSET, + &sli_intf); + adapter->is_virtfn = (sli_intf & SLI_INTF_FT_MASK) ? 1 : 0; + } else { + pci_write_config_byte(adapter->pdev, 0xFE, 0xAA); + pci_read_config_byte(adapter->pdev, 0xFE, &data); + adapter->is_virtfn = (data != 0xAA); + } } static inline void be_vf_eth_addr_generate(struct be_adapter *adapter, u8 *mac) diff --git a/drivers/net/benet/be_cmds.c b/drivers/net/benet/be_cmds.c index 36eca1ce75d4..3865b2bc65e6 100644 --- a/drivers/net/benet/be_cmds.c +++ b/drivers/net/benet/be_cmds.c @@ -323,7 +323,12 @@ static int be_mbox_notify_wait(struct be_adapter *adapter) static int be_POST_stage_get(struct be_adapter *adapter, u16 *stage) { - u32 sem = ioread32(adapter->csr + MPU_EP_SEMAPHORE_OFFSET); + u32 sem; + + if (lancer_chip(adapter)) + sem = ioread32(adapter->db + MPU_EP_SEMAPHORE_IF_TYPE2_OFFSET); + else + sem = ioread32(adapter->csr + MPU_EP_SEMAPHORE_OFFSET); *stage = sem & EP_SEMAPHORE_POST_STAGE_MASK; if ((sem >> EP_SEMAPHORE_POST_ERR_SHIFT) & EP_SEMAPHORE_POST_ERR_MASK) @@ -465,14 +470,25 @@ int be_cmd_fw_init(struct be_adapter *adapter) spin_lock(&adapter->mbox_lock); wrb = (u8 *)wrb_from_mbox(adapter); - *wrb++ = 0xFF; - *wrb++ = 0x12; - *wrb++ = 0x34; - *wrb++ = 0xFF; - *wrb++ = 0xFF; - *wrb++ = 0x56; - *wrb++ = 0x78; - *wrb = 0xFF; + if (lancer_chip(adapter)) { + *wrb++ = 0xFF; + *wrb++ = 0x34; + *wrb++ = 0x12; + *wrb++ = 0xFF; + *wrb++ = 0xFF; + *wrb++ = 0x78; + *wrb++ = 0x56; + *wrb = 0xFF; + } else { + *wrb++ = 0xFF; + *wrb++ = 0x12; + *wrb++ = 0x34; + *wrb++ = 0xFF; + *wrb++ = 0xFF; + *wrb++ = 0x56; + *wrb++ = 0x78; + *wrb = 0xFF; + } status = be_mbox_notify_wait(adapter); @@ -680,16 +696,36 @@ int be_cmd_cq_create(struct be_adapter *adapter, OPCODE_COMMON_CQ_CREATE, sizeof(*req)); req->num_pages = cpu_to_le16(PAGES_4K_SPANNED(q_mem->va, q_mem->size)); + if (lancer_chip(adapter)) { + req->hdr.version = 1; + req->page_size = 1; /* 1 for 4K */ + AMAP_SET_BITS(struct amap_cq_context_lancer, coalescwm, ctxt, + coalesce_wm); + AMAP_SET_BITS(struct amap_cq_context_lancer, nodelay, ctxt, + no_delay); + AMAP_SET_BITS(struct amap_cq_context_lancer, count, ctxt, + __ilog2_u32(cq->len/256)); + AMAP_SET_BITS(struct amap_cq_context_lancer, valid, ctxt, 1); + AMAP_SET_BITS(struct amap_cq_context_lancer, eventable, + ctxt, 1); + AMAP_SET_BITS(struct amap_cq_context_lancer, eqid, + ctxt, eq->id); + AMAP_SET_BITS(struct amap_cq_context_lancer, armed, ctxt, 1); + } else { + AMAP_SET_BITS(struct amap_cq_context_be, coalescwm, ctxt, + coalesce_wm); + AMAP_SET_BITS(struct amap_cq_context_be, nodelay, + ctxt, no_delay); + AMAP_SET_BITS(struct amap_cq_context_be, count, ctxt, + __ilog2_u32(cq->len/256)); + AMAP_SET_BITS(struct amap_cq_context_be, valid, ctxt, 1); + AMAP_SET_BITS(struct amap_cq_context_be, solevent, + ctxt, sol_evts); + AMAP_SET_BITS(struct amap_cq_context_be, eventable, ctxt, 1); + AMAP_SET_BITS(struct amap_cq_context_be, eqid, ctxt, eq->id); + AMAP_SET_BITS(struct amap_cq_context_be, armed, ctxt, 1); + } - AMAP_SET_BITS(struct amap_cq_context, coalescwm, ctxt, coalesce_wm); - AMAP_SET_BITS(struct amap_cq_context, nodelay, ctxt, no_delay); - AMAP_SET_BITS(struct amap_cq_context, count, ctxt, - __ilog2_u32(cq->len/256)); - AMAP_SET_BITS(struct amap_cq_context, valid, ctxt, 1); - AMAP_SET_BITS(struct amap_cq_context, solevent, ctxt, sol_evts); - AMAP_SET_BITS(struct amap_cq_context, eventable, ctxt, 1); - AMAP_SET_BITS(struct amap_cq_context, eqid, ctxt, eq->id); - AMAP_SET_BITS(struct amap_cq_context, armed, ctxt, 1); be_dws_cpu_to_le(ctxt, sizeof(req->context)); be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem); @@ -737,13 +773,27 @@ int be_cmd_mccq_create(struct be_adapter *adapter, OPCODE_COMMON_MCC_CREATE_EXT, sizeof(*req)); req->num_pages = cpu_to_le16(PAGES_4K_SPANNED(q_mem->va, q_mem->size)); + if (lancer_chip(adapter)) { + req->hdr.version = 1; + req->cq_id = cpu_to_le16(cq->id); + + AMAP_SET_BITS(struct amap_mcc_context_lancer, ring_size, ctxt, + be_encoded_q_len(mccq->len)); + AMAP_SET_BITS(struct amap_mcc_context_lancer, valid, ctxt, 1); + AMAP_SET_BITS(struct amap_mcc_context_lancer, async_cq_id, + ctxt, cq->id); + AMAP_SET_BITS(struct amap_mcc_context_lancer, async_cq_valid, + ctxt, 1); + + } else { + 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); + } - AMAP_SET_BITS(struct amap_mcc_context, valid, ctxt, 1); - AMAP_SET_BITS(struct amap_mcc_context, ring_size, ctxt, - be_encoded_q_len(mccq->len)); - AMAP_SET_BITS(struct amap_mcc_context, cq_id, ctxt, cq->id); /* Subscribe to Link State and Group 5 Events(bits 1 and 5 set) */ - req->async_event_bitmap[0] |= 0x00000022; + req->async_event_bitmap[0] = cpu_to_le32(0x00000022); be_dws_cpu_to_le(ctxt, sizeof(req->context)); be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem); diff --git a/drivers/net/benet/be_cmds.h b/drivers/net/benet/be_cmds.h index 8469ff061f30..83d15c8a9fa3 100644 --- a/drivers/net/benet/be_cmds.h +++ b/drivers/net/benet/be_cmds.h @@ -309,7 +309,7 @@ struct be_cmd_req_pmac_del { /******************** Create CQ ***************************/ /* Pseudo amap definition in which each bit of the actual structure is defined * as a byte: used to calculate offset/shift/mask of each field */ -struct amap_cq_context { +struct amap_cq_context_be { u8 cidx[11]; /* dword 0*/ u8 rsvd0; /* dword 0*/ u8 coalescwm[2]; /* dword 0*/ @@ -332,14 +332,32 @@ struct amap_cq_context { u8 rsvd5[32]; /* dword 3*/ } __packed; +struct amap_cq_context_lancer { + u8 rsvd0[12]; /* dword 0*/ + u8 coalescwm[2]; /* dword 0*/ + u8 nodelay; /* dword 0*/ + u8 rsvd1[12]; /* dword 0*/ + u8 count[2]; /* dword 0*/ + u8 valid; /* dword 0*/ + u8 rsvd2; /* dword 0*/ + u8 eventable; /* dword 0*/ + u8 eqid[16]; /* dword 1*/ + u8 rsvd3[15]; /* dword 1*/ + u8 armed; /* dword 1*/ + u8 rsvd4[32]; /* dword 2*/ + u8 rsvd5[32]; /* dword 3*/ +} __packed; + struct be_cmd_req_cq_create { struct be_cmd_req_hdr hdr; u16 num_pages; - u16 rsvd0; - u8 context[sizeof(struct amap_cq_context) / 8]; + u8 page_size; + u8 rsvd0; + u8 context[sizeof(struct amap_cq_context_be) / 8]; struct phys_addr pages[8]; } __packed; + struct be_cmd_resp_cq_create { struct be_cmd_resp_hdr hdr; u16 cq_id; @@ -349,7 +367,7 @@ struct be_cmd_resp_cq_create { /******************** Create MCCQ ***************************/ /* Pseudo amap definition in which each bit of the actual structure is defined * as a byte: used to calculate offset/shift/mask of each field */ -struct amap_mcc_context { +struct amap_mcc_context_be { u8 con_index[14]; u8 rsvd0[2]; u8 ring_size[4]; @@ -364,12 +382,23 @@ struct amap_mcc_context { u8 rsvd2[32]; } __packed; +struct amap_mcc_context_lancer { + u8 async_cq_id[16]; + u8 ring_size[4]; + u8 rsvd0[12]; + u8 rsvd1[31]; + u8 valid; + u8 async_cq_valid[1]; + u8 rsvd2[31]; + u8 rsvd3[32]; +} __packed; + struct be_cmd_req_mcc_create { struct be_cmd_req_hdr hdr; u16 num_pages; - u16 rsvd0; + u16 cq_id; u32 async_event_bitmap[1]; - u8 context[sizeof(struct amap_mcc_context) / 8]; + u8 context[sizeof(struct amap_mcc_context_be) / 8]; struct phys_addr pages[8]; } __packed; @@ -605,6 +634,7 @@ struct be_hw_stats { struct be_rxf_stats rxf; u32 rsvd[48]; struct be_erx_stats erx; + u32 rsvd1[6]; }; struct be_cmd_req_get_stats { diff --git a/drivers/net/benet/be_hw.h b/drivers/net/benet/be_hw.h index a2ec5df0d733..4096d9778234 100644 --- a/drivers/net/benet/be_hw.h +++ b/drivers/net/benet/be_hw.h @@ -32,10 +32,12 @@ #define MPU_EP_CONTROL 0 /********** MPU semphore ******************/ -#define MPU_EP_SEMAPHORE_OFFSET 0xac -#define EP_SEMAPHORE_POST_STAGE_MASK 0x0000FFFF -#define EP_SEMAPHORE_POST_ERR_MASK 0x1 -#define EP_SEMAPHORE_POST_ERR_SHIFT 31 +#define MPU_EP_SEMAPHORE_OFFSET 0xac +#define MPU_EP_SEMAPHORE_IF_TYPE2_OFFSET 0x400 +#define EP_SEMAPHORE_POST_STAGE_MASK 0x0000FFFF +#define EP_SEMAPHORE_POST_ERR_MASK 0x1 +#define EP_SEMAPHORE_POST_ERR_SHIFT 31 + /* MPU semphore POST stage values */ #define POST_STAGE_AWAITING_HOST_RDY 0x1 /* FW awaiting goahead from host */ #define POST_STAGE_HOST_RDY 0x2 /* Host has given go-ahed to FW */ @@ -66,6 +68,28 @@ #define PCICFG_UE_STATUS_LOW_MASK 0xA8 #define PCICFG_UE_STATUS_HI_MASK 0xAC +/******** SLI_INTF ***********************/ +#define SLI_INTF_REG_OFFSET 0x58 +#define SLI_INTF_VALID_MASK 0xE0000000 +#define SLI_INTF_VALID 0xC0000000 +#define SLI_INTF_HINT2_MASK 0x1F000000 +#define SLI_INTF_HINT2_SHIFT 24 +#define SLI_INTF_HINT1_MASK 0x00FF0000 +#define SLI_INTF_HINT1_SHIFT 16 +#define SLI_INTF_FAMILY_MASK 0x00000F00 +#define SLI_INTF_FAMILY_SHIFT 8 +#define SLI_INTF_IF_TYPE_MASK 0x0000F000 +#define SLI_INTF_IF_TYPE_SHIFT 12 +#define SLI_INTF_REV_MASK 0x000000F0 +#define SLI_INTF_REV_SHIFT 4 +#define SLI_INTF_FT_MASK 0x00000001 + + +/* SLI family */ +#define BE_SLI_FAMILY 0x0 +#define LANCER_A0_SLI_FAMILY 0xA + + /********* ISR0 Register offset **********/ #define CEV_ISR0_OFFSET 0xC18 #define CEV_ISR_SIZE 4 @@ -73,6 +97,9 @@ /********* Event Q door bell *************/ #define DB_EQ_OFFSET DB_CQ_OFFSET #define DB_EQ_RING_ID_MASK 0x1FF /* bits 0 - 8 */ +#define DB_EQ_RING_ID_EXT_MASK 0x3e00 /* bits 9-13 */ +#define DB_EQ_RING_ID_EXT_MASK_SHIFT (2) /* qid bits 9-13 placing at 11-15 */ + /* Clear the interrupt for this eq */ #define DB_EQ_CLR_SHIFT (9) /* bit 9 */ /* Must be 1 */ @@ -85,6 +112,10 @@ /********* Compl Q door bell *************/ #define DB_CQ_OFFSET 0x120 #define DB_CQ_RING_ID_MASK 0x3FF /* bits 0 - 9 */ +#define DB_CQ_RING_ID_EXT_MASK 0x7C00 /* bits 10-14 */ +#define DB_CQ_RING_ID_EXT_MASK_SHIFT (1) /* qid bits 10-14 + placing at 11-15 */ + /* Number of event entries processed */ #define DB_CQ_NUM_POPPED_SHIFT (16) /* bits 16 - 28 */ /* Rearm bit */ diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index c36cd2ffbadc..102567ee68c2 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -41,6 +41,7 @@ static DEFINE_PCI_DEVICE_TABLE(be_dev_ids) = { { PCI_DEVICE(BE_VENDOR_ID, BE_DEVICE_ID2) }, { PCI_DEVICE(BE_VENDOR_ID, OC_DEVICE_ID1) }, { PCI_DEVICE(BE_VENDOR_ID, OC_DEVICE_ID2) }, + { PCI_DEVICE(EMULEX_VENDOR_ID, OC_DEVICE_ID3)}, { 0 } }; MODULE_DEVICE_TABLE(pci, be_dev_ids); @@ -188,6 +189,8 @@ static void be_eq_notify(struct be_adapter *adapter, u16 qid, { u32 val = 0; val |= qid & DB_EQ_RING_ID_MASK; + val |= ((qid & DB_EQ_RING_ID_EXT_MASK) << + DB_EQ_RING_ID_EXT_MASK_SHIFT); if (adapter->eeh_err) return; @@ -205,6 +208,8 @@ void be_cq_notify(struct be_adapter *adapter, u16 qid, bool arm, u16 num_popped) { u32 val = 0; val |= qid & DB_CQ_RING_ID_MASK; + val |= ((qid & DB_CQ_RING_ID_EXT_MASK) << + DB_CQ_RING_ID_EXT_MASK_SHIFT); if (adapter->eeh_err) return; @@ -404,7 +409,8 @@ static void be_tx_stats_update(struct be_adapter *adapter, } /* Determine number of WRB entries needed to xmit data in an skb */ -static u32 wrb_cnt_for_skb(struct sk_buff *skb, bool *dummy) +static u32 wrb_cnt_for_skb(struct be_adapter *adapter, struct sk_buff *skb, + bool *dummy) { int cnt = (skb->len > skb->data_len); @@ -412,12 +418,13 @@ static u32 wrb_cnt_for_skb(struct sk_buff *skb, bool *dummy) /* to account for hdr wrb */ cnt++; - if (cnt & 1) { + if (lancer_chip(adapter) || !(cnt & 1)) { + *dummy = false; + } else { /* add a dummy to make it an even num */ cnt++; *dummy = true; - } else - *dummy = false; + } BUG_ON(cnt > BE_MAX_TX_FRAG_COUNT); return cnt; } @@ -443,8 +450,18 @@ static void wrb_fill_hdr(struct be_adapter *adapter, struct be_eth_hdr_wrb *hdr, AMAP_SET_BITS(struct amap_eth_hdr_wrb, lso, hdr, 1); AMAP_SET_BITS(struct amap_eth_hdr_wrb, lso_mss, hdr, skb_shinfo(skb)->gso_size); - if (skb_is_gso_v6(skb)) + if (skb_is_gso_v6(skb) && !lancer_chip(adapter)) AMAP_SET_BITS(struct amap_eth_hdr_wrb, lso6, hdr, 1); + if (lancer_chip(adapter) && adapter->sli_family == + LANCER_A0_SLI_FAMILY) { + AMAP_SET_BITS(struct amap_eth_hdr_wrb, ipcs, hdr, 1); + if (is_tcp_pkt(skb)) + AMAP_SET_BITS(struct amap_eth_hdr_wrb, + tcpcs, hdr, 1); + else if (is_udp_pkt(skb)) + AMAP_SET_BITS(struct amap_eth_hdr_wrb, + udpcs, hdr, 1); + } } else if (skb->ip_summed == CHECKSUM_PARTIAL) { if (is_tcp_pkt(skb)) AMAP_SET_BITS(struct amap_eth_hdr_wrb, tcpcs, hdr, 1); @@ -566,7 +583,7 @@ static netdev_tx_t be_xmit(struct sk_buff *skb, u32 start = txq->head; bool dummy_wrb, stopped = false; - wrb_cnt = wrb_cnt_for_skb(skb, &dummy_wrb); + wrb_cnt = wrb_cnt_for_skb(adapter, skb, &dummy_wrb); copied = make_tx_wrbs(adapter, skb, wrb_cnt, dummy_wrb); if (copied) { @@ -1035,7 +1052,8 @@ static void be_rx_compl_process(struct be_adapter *adapter, return; } vid = AMAP_GET_BITS(struct amap_eth_rx_compl, vlan_tag, rxcp); - vid = swab16(vid); + if (!lancer_chip(adapter)) + vid = swab16(vid); vlan_hwaccel_receive_skb(skb, adapter->vlan_grp, vid); } else { netif_receive_skb(skb); @@ -1113,7 +1131,8 @@ static void be_rx_compl_process_gro(struct be_adapter *adapter, napi_gro_frags(&eq_obj->napi); } else { vid = AMAP_GET_BITS(struct amap_eth_rx_compl, vlan_tag, rxcp); - vid = swab16(vid); + if (!lancer_chip(adapter)) + vid = swab16(vid); if (!adapter->vlan_grp || adapter->vlans_added == 0) return; @@ -1381,7 +1400,8 @@ static void be_tx_compl_clean(struct be_adapter *adapter) sent_skb = sent_skbs[txq->tail]; end_idx = txq->tail; index_adv(&end_idx, - wrb_cnt_for_skb(sent_skb, &dummy_wrb) - 1, txq->len); + wrb_cnt_for_skb(adapter, sent_skb, &dummy_wrb) - 1, + txq->len); be_tx_compl_process(adapter, end_idx); } } @@ -1476,7 +1496,9 @@ static int be_tx_queues_create(struct be_adapter *adapter) /* Ask BE to create Tx Event queue */ if (be_cmd_eq_create(adapter, eq, adapter->tx_eq.cur_eqd)) goto tx_eq_free; - adapter->base_eq_id = adapter->tx_eq.q.id; + + adapter->tx_eq.msix_vec_idx = adapter->msix_vec_next_idx++; + /* Alloc TX eth compl queue */ cq = &adapter->tx_obj.cq; @@ -1568,6 +1590,8 @@ static int be_rx_queues_create(struct be_adapter *adapter) if (rc) goto err; + rxo->rx_eq.msix_vec_idx = adapter->msix_vec_next_idx++; + /* CQ */ cq = &rxo->cq; rc = be_queue_alloc(adapter, cq, RX_CQ_LEN, @@ -1578,7 +1602,6 @@ static int be_rx_queues_create(struct be_adapter *adapter) rc = be_cmd_cq_create(adapter, cq, eq, false, false, 3); if (rc) goto err; - /* Rx Q */ q = &rxo->q; rc = be_queue_alloc(adapter, q, RX_Q_LEN, @@ -1611,29 +1634,45 @@ err: return -1; } -/* There are 8 evt ids per func. Retruns the evt id's bit number */ -static inline int be_evt_bit_get(struct be_adapter *adapter, u32 eq_id) +static bool event_peek(struct be_eq_obj *eq_obj) { - return eq_id - adapter->base_eq_id; + struct be_eq_entry *eqe = queue_tail_node(&eq_obj->q); + if (!eqe->evt) + return false; + else + return true; } static irqreturn_t be_intx(int irq, void *dev) { struct be_adapter *adapter = dev; struct be_rx_obj *rxo; - int isr, i; + int isr, i, tx = 0 , rx = 0; - isr = ioread32(adapter->csr + CEV_ISR0_OFFSET + - (adapter->tx_eq.q.id/ 8) * CEV_ISR_SIZE); - if (!isr) - return IRQ_NONE; + if (lancer_chip(adapter)) { + if (event_peek(&adapter->tx_eq)) + tx = event_handle(adapter, &adapter->tx_eq); + for_all_rx_queues(adapter, rxo, i) { + if (event_peek(&rxo->rx_eq)) + rx |= event_handle(adapter, &rxo->rx_eq); + } - if ((1 << be_evt_bit_get(adapter, adapter->tx_eq.q.id) & isr)) - event_handle(adapter, &adapter->tx_eq); + if (!(tx || rx)) + return IRQ_NONE; - for_all_rx_queues(adapter, rxo, i) { - if ((1 << be_evt_bit_get(adapter, rxo->rx_eq.q.id) & isr)) - event_handle(adapter, &rxo->rx_eq); + } else { + isr = ioread32(adapter->csr + CEV_ISR0_OFFSET + + (adapter->tx_eq.q.id / 8) * CEV_ISR_SIZE); + if (!isr) + return IRQ_NONE; + + if ((1 << adapter->tx_eq.msix_vec_idx & isr)) + event_handle(adapter, &adapter->tx_eq); + + for_all_rx_queues(adapter, rxo, i) { + if ((1 << rxo->rx_eq.msix_vec_idx & isr)) + event_handle(adapter, &rxo->rx_eq); + } } return IRQ_HANDLED; @@ -1830,8 +1869,7 @@ static void be_worker(struct work_struct *work) be_post_rx_frags(rxo); } } - - if (!adapter->ue_detected) + if (!adapter->ue_detected && !lancer_chip(adapter)) be_detect_dump_ue(adapter); reschedule: @@ -1910,10 +1948,10 @@ static void be_sriov_disable(struct be_adapter *adapter) #endif } -static inline int be_msix_vec_get(struct be_adapter *adapter, u32 eq_id) +static inline int be_msix_vec_get(struct be_adapter *adapter, + struct be_eq_obj *eq_obj) { - return adapter->msix_entries[ - be_evt_bit_get(adapter, eq_id)].vector; + return adapter->msix_entries[eq_obj->msix_vec_idx].vector; } static int be_request_irq(struct be_adapter *adapter, @@ -1924,14 +1962,14 @@ static int be_request_irq(struct be_adapter *adapter, int vec; sprintf(eq_obj->desc, "%s-%s", netdev->name, desc); - vec = be_msix_vec_get(adapter, eq_obj->q.id); + vec = be_msix_vec_get(adapter, eq_obj); return request_irq(vec, handler, 0, eq_obj->desc, context); } static void be_free_irq(struct be_adapter *adapter, struct be_eq_obj *eq_obj, void *context) { - int vec = be_msix_vec_get(adapter, eq_obj->q.id); + int vec = be_msix_vec_get(adapter, eq_obj); free_irq(vec, context); } @@ -2036,14 +2074,15 @@ static int be_close(struct net_device *netdev) netif_carrier_off(netdev); adapter->link_up = false; - be_intr_set(adapter, false); + if (!lancer_chip(adapter)) + be_intr_set(adapter, false); if (adapter->msix_enabled) { - vec = be_msix_vec_get(adapter, tx_eq->q.id); + vec = be_msix_vec_get(adapter, tx_eq); synchronize_irq(vec); for_all_rx_queues(adapter, rxo, i) { - vec = be_msix_vec_get(adapter, rxo->rx_eq.q.id); + vec = be_msix_vec_get(adapter, &rxo->rx_eq); synchronize_irq(vec); } } else { @@ -2082,7 +2121,8 @@ static int be_open(struct net_device *netdev) be_irq_register(adapter); - be_intr_set(adapter, true); + if (!lancer_chip(adapter)) + be_intr_set(adapter, true); /* The evt queues are created in unarmed state; arm them */ for_all_rx_queues(adapter, rxo, i) { @@ -2458,6 +2498,12 @@ int be_load_fw(struct be_adapter *adapter, u8 *func) int status, i = 0, num_imgs = 0; const u8 *p; + if (!netif_running(adapter->netdev)) { + dev_err(&adapter->pdev->dev, + "Firmware load not allowed (interface is down)\n"); + return -EPERM; + } + strcpy(fw_file, func); status = request_firmware(&fw, fw_file, &adapter->pdev->dev); @@ -2542,6 +2588,9 @@ static void be_netdev_init(struct net_device *netdev) netdev->vlan_features |= NETIF_F_SG | NETIF_F_TSO | NETIF_F_HW_CSUM; + if (lancer_chip(adapter)) + netdev->vlan_features |= NETIF_F_TSO6; + netdev->flags |= IFF_MULTICAST; adapter->rx_csum = true; @@ -2581,6 +2630,15 @@ static int be_map_pci_bars(struct be_adapter *adapter) u8 __iomem *addr; int pcicfg_reg, db_reg; + if (lancer_chip(adapter)) { + addr = ioremap_nocache(pci_resource_start(adapter->pdev, 0), + pci_resource_len(adapter->pdev, 0)); + if (addr == NULL) + return -ENOMEM; + adapter->db = addr; + return 0; + } + if (be_physfn(adapter)) { addr = ioremap_nocache(pci_resource_start(adapter->pdev, 2), pci_resource_len(adapter->pdev, 2)); @@ -2777,6 +2835,44 @@ static int be_get_config(struct be_adapter *adapter) return 0; } +static int be_dev_family_check(struct be_adapter *adapter) +{ + struct pci_dev *pdev = adapter->pdev; + u32 sli_intf = 0, if_type; + + switch (pdev->device) { + case BE_DEVICE_ID1: + case OC_DEVICE_ID1: + adapter->generation = BE_GEN2; + break; + case BE_DEVICE_ID2: + case OC_DEVICE_ID2: + adapter->generation = BE_GEN3; + break; + case OC_DEVICE_ID3: + pci_read_config_dword(pdev, SLI_INTF_REG_OFFSET, &sli_intf); + if_type = (sli_intf & SLI_INTF_IF_TYPE_MASK) >> + SLI_INTF_IF_TYPE_SHIFT; + + if (((sli_intf & SLI_INTF_VALID_MASK) != SLI_INTF_VALID) || + if_type != 0x02) { + dev_err(&pdev->dev, "SLI_INTF reg val is not valid\n"); + return -EINVAL; + } + if (num_vfs > 0) { + dev_err(&pdev->dev, "VFs not supported\n"); + return -EINVAL; + } + adapter->sli_family = ((sli_intf & SLI_INTF_FAMILY_MASK) >> + SLI_INTF_FAMILY_SHIFT); + adapter->generation = BE_GEN3; + break; + default: + adapter->generation = 0; + } + return 0; +} + static int __devinit be_probe(struct pci_dev *pdev, const struct pci_device_id *pdev_id) { @@ -2799,22 +2895,13 @@ static int __devinit be_probe(struct pci_dev *pdev, goto rel_reg; } adapter = netdev_priv(netdev); - - switch (pdev->device) { - case BE_DEVICE_ID1: - case OC_DEVICE_ID1: - adapter->generation = BE_GEN2; - break; - case BE_DEVICE_ID2: - case OC_DEVICE_ID2: - adapter->generation = BE_GEN3; - break; - default: - adapter->generation = 0; - } - adapter->pdev = pdev; pci_set_drvdata(pdev, adapter); + + status = be_dev_family_check(adapter); + if (!status) + goto free_netdev; + adapter->netdev = netdev; SET_NETDEV_DEV(netdev, &pdev->dev); @@ -2889,7 +2976,7 @@ ctrl_clean: be_ctrl_cleanup(adapter); free_netdev: be_sriov_disable(adapter); - free_netdev(adapter->netdev); + free_netdev(netdev); pci_set_drvdata(pdev, NULL); rel_reg: pci_release_regions(pdev); diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index 062600be073b..03209a37883e 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -56,8 +56,8 @@ #include "bnx2_fw.h" #define DRV_MODULE_NAME "bnx2" -#define DRV_MODULE_VERSION "2.0.18" -#define DRV_MODULE_RELDATE "Oct 7, 2010" +#define DRV_MODULE_VERSION "2.0.20" +#define DRV_MODULE_RELDATE "Nov 24, 2010" #define FW_MIPS_FILE_06 "bnx2/bnx2-mips-06-6.0.15.fw" #define FW_RV2P_FILE_06 "bnx2/bnx2-rv2p-06-6.0.15.fw" #define FW_MIPS_FILE_09 "bnx2/bnx2-mips-09-6.0.17.fw" @@ -766,13 +766,10 @@ bnx2_alloc_rx_mem(struct bnx2 *bp) int j; rxr->rx_buf_ring = - vmalloc(SW_RXBD_RING_SIZE * bp->rx_max_ring); + vzalloc(SW_RXBD_RING_SIZE * bp->rx_max_ring); if (rxr->rx_buf_ring == NULL) return -ENOMEM; - memset(rxr->rx_buf_ring, 0, - SW_RXBD_RING_SIZE * bp->rx_max_ring); - for (j = 0; j < bp->rx_max_ring; j++) { rxr->rx_desc_ring[j] = dma_alloc_coherent(&bp->pdev->dev, @@ -785,13 +782,11 @@ bnx2_alloc_rx_mem(struct bnx2 *bp) } if (bp->rx_pg_ring_size) { - rxr->rx_pg_ring = vmalloc(SW_RXPG_RING_SIZE * + rxr->rx_pg_ring = vzalloc(SW_RXPG_RING_SIZE * bp->rx_max_pg_ring); if (rxr->rx_pg_ring == NULL) return -ENOMEM; - memset(rxr->rx_pg_ring, 0, SW_RXPG_RING_SIZE * - bp->rx_max_pg_ring); } for (j = 0; j < bp->rx_max_pg_ring; j++) { @@ -4645,13 +4640,28 @@ bnx2_reset_chip(struct bnx2 *bp, u32 reset_code) /* Wait for the current PCI transaction to complete before * issuing a reset. */ - REG_WR(bp, BNX2_MISC_ENABLE_CLR_BITS, - BNX2_MISC_ENABLE_CLR_BITS_TX_DMA_ENABLE | - BNX2_MISC_ENABLE_CLR_BITS_DMA_ENGINE_ENABLE | - BNX2_MISC_ENABLE_CLR_BITS_RX_DMA_ENABLE | - BNX2_MISC_ENABLE_CLR_BITS_HOST_COALESCE_ENABLE); - val = REG_RD(bp, BNX2_MISC_ENABLE_CLR_BITS); - udelay(5); + if ((CHIP_NUM(bp) == CHIP_NUM_5706) || + (CHIP_NUM(bp) == CHIP_NUM_5708)) { + REG_WR(bp, BNX2_MISC_ENABLE_CLR_BITS, + BNX2_MISC_ENABLE_CLR_BITS_TX_DMA_ENABLE | + BNX2_MISC_ENABLE_CLR_BITS_DMA_ENGINE_ENABLE | + BNX2_MISC_ENABLE_CLR_BITS_RX_DMA_ENABLE | + BNX2_MISC_ENABLE_CLR_BITS_HOST_COALESCE_ENABLE); + val = REG_RD(bp, BNX2_MISC_ENABLE_CLR_BITS); + udelay(5); + } else { /* 5709 */ + val = REG_RD(bp, BNX2_MISC_NEW_CORE_CTL); + val &= ~BNX2_MISC_NEW_CORE_CTL_DMA_ENABLE; + REG_WR(bp, BNX2_MISC_NEW_CORE_CTL, val); + val = REG_RD(bp, BNX2_MISC_NEW_CORE_CTL); + + for (i = 0; i < 100; i++) { + msleep(1); + val = REG_RD(bp, BNX2_PCICFG_DEVICE_CONTROL); + if (!(val & BNX2_PCICFG_DEVICE_STATUS_NO_PEND)) + break; + } + } /* Wait for the firmware to tell us it is ok to issue a reset. */ bnx2_fw_sync(bp, BNX2_DRV_MSG_DATA_WAIT0 | reset_code, 1, 1); @@ -4673,7 +4683,7 @@ bnx2_reset_chip(struct bnx2 *bp, u32 reset_code) val = BNX2_PCICFG_MISC_CONFIG_REG_WINDOW_ENA | BNX2_PCICFG_MISC_CONFIG_TARGET_MB_WORD_SWAP; - pci_write_config_dword(bp->pdev, BNX2_PCICFG_MISC_CONFIG, val); + REG_WR(bp, BNX2_PCICFG_MISC_CONFIG, val); } else { val = BNX2_PCICFG_MISC_CONFIG_CORE_RST_REQ | @@ -7914,15 +7924,15 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) goto err_out_release; } + bnx2_set_power_state(bp, PCI_D0); + /* Configure byte swap and enable write to the reg_window registers. * Rely on CPU to do target byte swapping on big endian systems * The chip's target access swapping will not swap all accesses */ - pci_write_config_dword(bp->pdev, BNX2_PCICFG_MISC_CONFIG, - BNX2_PCICFG_MISC_CONFIG_REG_WINDOW_ENA | - BNX2_PCICFG_MISC_CONFIG_TARGET_MB_WORD_SWAP); - - bnx2_set_power_state(bp, PCI_D0); + REG_WR(bp, BNX2_PCICFG_MISC_CONFIG, + BNX2_PCICFG_MISC_CONFIG_REG_WINDOW_ENA | + BNX2_PCICFG_MISC_CONFIG_TARGET_MB_WORD_SWAP); bp->chip_id = REG_RD(bp, BNX2_MISC_ID); diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h index bf4c3421067d..5488a2e82fe9 100644 --- a/drivers/net/bnx2.h +++ b/drivers/net/bnx2.h @@ -461,6 +461,8 @@ struct l2_fhdr { #define BNX2_PCICFG_MAILBOX_QUEUE_ADDR 0x00000090 #define BNX2_PCICFG_MAILBOX_QUEUE_DATA 0x00000094 +#define BNX2_PCICFG_DEVICE_CONTROL 0x000000b4 +#define BNX2_PCICFG_DEVICE_STATUS_NO_PEND ((1L<<5)<<16) /* * pci_reg definition diff --git a/drivers/net/bnx2x/bnx2x.h b/drivers/net/bnx2x/bnx2x.h index 9eea225decaf..cfc25cf064d3 100644 --- a/drivers/net/bnx2x/bnx2x.h +++ b/drivers/net/bnx2x/bnx2x.h @@ -20,8 +20,8 @@ * (you will need to reboot afterwards) */ /* #define BNX2X_STOP_ON_ERROR */ -#define DRV_MODULE_VERSION "1.60.00-3" -#define DRV_MODULE_RELDATE "2010/10/19" +#define DRV_MODULE_VERSION "1.60.00-6" +#define DRV_MODULE_RELDATE "2010/11/29" #define BNX2X_BC_VER 0x040200 #define BNX2X_MULTI_QUEUE @@ -671,6 +671,10 @@ enum { CAM_ISCSI_ETH_LINE, CAM_MAX_PF_LINE = CAM_ISCSI_ETH_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 BNX2X_VF_ID_INVALID 0xFF @@ -967,6 +971,8 @@ struct bnx2x { u16 mf_ov; u8 mf_mode; #define IS_MF(bp) (bp->mf_mode != 0) +#define IS_MF_SI(bp) (bp->mf_mode == MULTI_FUNCTION_SI) +#define IS_MF_SD(bp) (bp->mf_mode == MULTI_FUNCTION_SD) u8 wol; @@ -1010,6 +1016,7 @@ struct bnx2x { #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; diff --git a/drivers/net/bnx2x/bnx2x_cmn.c b/drivers/net/bnx2x/bnx2x_cmn.c index 459614d2d7bc..a4555edbe9ce 100644 --- a/drivers/net/bnx2x/bnx2x_cmn.c +++ b/drivers/net/bnx2x/bnx2x_cmn.c @@ -698,6 +698,29 @@ void bnx2x_release_phy_lock(struct bnx2x *bp) mutex_unlock(&bp->port.phy_mutex); } +/* calculates MF speed according to current linespeed and MF configuration */ +u16 bnx2x_get_mf_speed(struct bnx2x *bp) +{ + u16 line_speed = bp->link_vars.line_speed; + if (IS_MF(bp)) { + u16 maxCfg = (bp->mf_config[BP_VN(bp)] & + FUNC_MF_CFG_MAX_BW_MASK) >> + FUNC_MF_CFG_MAX_BW_SHIFT; + /* Calculate the current MAX line speed limit for the DCC + * capable devices + */ + if (IS_MF_SD(bp)) { + u16 vn_max_rate = maxCfg * 100; + + if (vn_max_rate < line_speed) + line_speed = vn_max_rate; + } else /* IS_MF_SI(bp)) */ + line_speed = (line_speed * maxCfg) / 100; + } + + return line_speed; +} + void bnx2x_link_report(struct bnx2x *bp) { if (bp->flags & MF_FUNC_DIS) { @@ -713,17 +736,8 @@ void bnx2x_link_report(struct bnx2x *bp) netif_carrier_on(bp->dev); netdev_info(bp->dev, "NIC Link is Up, "); - line_speed = bp->link_vars.line_speed; - if (IS_MF(bp)) { - u16 vn_max_rate; + line_speed = bnx2x_get_mf_speed(bp); - vn_max_rate = - ((bp->mf_config[BP_VN(bp)] & - FUNC_MF_CFG_MAX_BW_MASK) >> - FUNC_MF_CFG_MAX_BW_SHIFT) * 100; - if (vn_max_rate < line_speed) - line_speed = vn_max_rate; - } pr_cont("%d Mbps ", line_speed); if (bp->link_vars.duplex == DUPLEX_FULL) @@ -1680,7 +1694,7 @@ static inline u32 bnx2x_xmit_type(struct bnx2x *bp, struct sk_buff *skb) rc = XMIT_PLAIN; else { - if (skb->protocol == htons(ETH_P_IPV6)) { + if (vlan_get_protocol(skb) == htons(ETH_P_IPV6)) { rc = XMIT_CSUM_V6; if (ipv6_hdr(skb)->nexthdr == IPPROTO_TCP) rc |= XMIT_CSUM_TCP; @@ -1692,11 +1706,10 @@ static inline u32 bnx2x_xmit_type(struct bnx2x *bp, struct sk_buff *skb) } } - if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV4) - rc |= (XMIT_GSO_V4 | XMIT_CSUM_V4 | XMIT_CSUM_TCP); - - else if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6) - rc |= (XMIT_GSO_V6 | XMIT_CSUM_TCP | XMIT_CSUM_V6); + if (skb_is_gso_v6(skb)) + rc |= XMIT_GSO_V6 | XMIT_CSUM_TCP | XMIT_CSUM_V6; + else if (skb_is_gso(skb)) + rc |= XMIT_GSO_V4 | XMIT_CSUM_V4 | XMIT_CSUM_TCP; return rc; } diff --git a/drivers/net/bnx2x/bnx2x_cmn.h b/drivers/net/bnx2x/bnx2x_cmn.h index 6b28739c5302..cb8f2a040a18 100644 --- a/drivers/net/bnx2x/bnx2x_cmn.h +++ b/drivers/net/bnx2x/bnx2x_cmn.h @@ -73,6 +73,16 @@ void bnx2x__link_status_update(struct bnx2x *bp); void bnx2x_link_report(struct bnx2x *bp); /** + * calculates MF speed according to current linespeed and MF + * configuration + * + * @param bp + * + * @return u16 + */ +u16 bnx2x_get_mf_speed(struct bnx2x *bp); + +/** * MSI-X slowpath interrupt handler * * @param irq diff --git a/drivers/net/bnx2x/bnx2x_ethtool.c b/drivers/net/bnx2x/bnx2x_ethtool.c index d02ffbdc9f0e..bd94827e5e57 100644 --- a/drivers/net/bnx2x/bnx2x_ethtool.c +++ b/drivers/net/bnx2x/bnx2x_ethtool.c @@ -45,14 +45,9 @@ static int bnx2x_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) cmd->speed = bp->link_params.req_line_speed[cfg_idx]; cmd->duplex = bp->link_params.req_duplex[cfg_idx]; } - if (IS_MF(bp)) { - u16 vn_max_rate = ((bp->mf_config[BP_VN(bp)] & - FUNC_MF_CFG_MAX_BW_MASK) >> FUNC_MF_CFG_MAX_BW_SHIFT) * - 100; - if (vn_max_rate < cmd->speed) - cmd->speed = vn_max_rate; - } + if (IS_MF(bp)) + cmd->speed = bnx2x_get_mf_speed(bp); if (bp->port.supported[cfg_idx] & SUPPORTED_TP) cmd->port = PORT_TP; @@ -87,18 +82,57 @@ static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) { struct bnx2x *bp = netdev_priv(dev); u32 advertising, cfg_idx, old_multi_phy_config, new_multi_phy_config; + u32 speed; - if (IS_MF(bp)) + if (IS_MF_SD(bp)) return 0; DP(NETIF_MSG_LINK, "ethtool_cmd: cmd %d\n" - DP_LEVEL " supported 0x%x advertising 0x%x speed %d\n" - DP_LEVEL " duplex %d port %d phy_address %d transceiver %d\n" - DP_LEVEL " autoneg %d maxtxpkt %d maxrxpkt %d\n", + " supported 0x%x advertising 0x%x speed %d speed_hi %d\n" + " duplex %d port %d phy_address %d transceiver %d\n" + " autoneg %d maxtxpkt %d maxrxpkt %d\n", cmd->cmd, cmd->supported, cmd->advertising, cmd->speed, + cmd->speed_hi, cmd->duplex, cmd->port, cmd->phy_address, cmd->transceiver, cmd->autoneg, cmd->maxtxpkt, cmd->maxrxpkt); + speed = cmd->speed; + speed |= (cmd->speed_hi << 16); + + if (IS_MF_SI(bp)) { + u32 param = 0; + u32 line_speed = bp->link_vars.line_speed; + + /* use 10G if no link detected */ + if (!line_speed) + line_speed = 10000; + + if (bp->common.bc_ver < REQ_BC_VER_4_SET_MF_BW) { + BNX2X_DEV_INFO("To set speed BC %X or higher " + "is required, please upgrade BC\n", + REQ_BC_VER_4_SET_MF_BW); + return -EINVAL; + } + if (line_speed < speed) { + BNX2X_DEV_INFO("New speed should be less or equal " + "to actual line speed\n"); + return -EINVAL; + } + /* load old values */ + param = bp->mf_config[BP_VN(bp)]; + + /* leave only MIN value */ + param &= FUNC_MF_CFG_MIN_BW_MASK; + + /* set new MAX value */ + param |= (((speed * 100) / line_speed) + << FUNC_MF_CFG_MAX_BW_SHIFT) + & FUNC_MF_CFG_MAX_BW_MASK; + + bnx2x_fw_command(bp, DRV_MSG_CODE_SET_MF_BW, param); + return 0; + } + cfg_idx = bnx2x_get_link_cfg_idx(bp); old_multi_phy_config = bp->link_params.multi_phy_config; switch (cmd->port) { @@ -168,8 +202,6 @@ static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) } else { /* forced speed */ /* advertise the requested speed and duplex if supported */ - u32 speed = cmd->speed; - speed |= (cmd->speed_hi << 16); switch (speed) { case SPEED_10: if (cmd->duplex == DUPLEX_FULL) { @@ -1499,8 +1531,15 @@ static int bnx2x_run_loopback(struct bnx2x *bp, int loopback_mode, u8 link_up) * updates that have been performed while interrupts were * disabled. */ - if (bp->common.int_block == INT_BLOCK_IGU) + if (bp->common.int_block == INT_BLOCK_IGU) { + /* Disable local BHes to prevent a dead-lock situation between + * sch_direct_xmit() and bnx2x_run_loopback() (calling + * bnx2x_tx_int()), as both are taking netif_tx_lock(). + */ + local_bh_disable(); bnx2x_tx_int(fp_tx); + local_bh_enable(); + } rx_idx = le16_to_cpu(*fp_rx->rx_cons_sb); if (rx_idx != rx_start_idx + num_pkts) diff --git a/drivers/net/bnx2x/bnx2x_hsi.h b/drivers/net/bnx2x/bnx2x_hsi.h index 18c8e23a0e82..6555c477f893 100644 --- a/drivers/net/bnx2x/bnx2x_hsi.h +++ b/drivers/net/bnx2x/bnx2x_hsi.h @@ -244,7 +244,14 @@ struct port_hw_cfg { /* port 0: 0x12c port 1: 0x2bc */ u16 xgxs_config_tx[4]; /* 0x1A0 */ - u32 Reserved1[57]; /* 0x1A8 */ + u32 Reserved1[56]; /* 0x1A8 */ + u32 default_cfg; /* 0x288 */ + /* 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 + u32 speed_capability_mask2; /* 0x28C */ #define PORT_HW_CFG_SPEED_CAPABILITY2_D3_MASK 0x0000FFFF #define PORT_HW_CFG_SPEED_CAPABILITY2_D3_SHIFT 0 @@ -427,7 +434,12 @@ struct shared_feat_cfg { /* NVRAM Offset */ #define SHARED_FEAT_CFG_OVERRIDE_PREEMPHASIS_CFG_DISABLED 0x00000000 #define SHARED_FEAT_CFG_OVERRIDE_PREEMPHASIS_CFG_ENABLED 0x00000002 -#define SHARED_FEATURE_MF_MODE_DISABLED 0x00000100 +#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 }; @@ -808,6 +820,9 @@ struct drv_func_mb { #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_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 @@ -881,6 +896,7 @@ struct drv_func_mb { u32 drv_status; #define DRV_STATUS_PMF 0x00000001 +#define DRV_STATUS_SET_MF_BW 0x00000004 #define DRV_STATUS_DCC_EVENT_MASK 0x0000ff00 #define DRV_STATUS_DCC_DISABLE_ENABLE_PF 0x00000100 @@ -981,12 +997,43 @@ struct func_mf_cfg { }; +/* 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 + + u32 iscsi_mac_addr_upper; + u32 iscsi_mac_addr_lower; + + u32 fcoe_mac_addr_upper; + u32 fcoe_mac_addr_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 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) +}; + 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]; }; diff --git a/drivers/net/bnx2x/bnx2x_link.c b/drivers/net/bnx2x/bnx2x_link.c index 2326774df843..38aeffef2a83 100644 --- a/drivers/net/bnx2x/bnx2x_link.c +++ b/drivers/net/bnx2x/bnx2x_link.c @@ -610,7 +610,7 @@ static u8 bnx2x_bmac_enable(struct link_params *params, /* reset and unreset the BigMac */ REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR, (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port)); - udelay(10); + msleep(1); REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET, (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port)); @@ -3525,13 +3525,19 @@ static u8 bnx2x_8073_config_init(struct bnx2x_phy *phy, DP(NETIF_MSG_LINK, "Before rom RX_ALARM(port1): 0x%x\n", tmp1); /* Enable CL37 BAM */ - bnx2x_cl45_read(bp, phy, - MDIO_AN_DEVAD, - MDIO_AN_REG_8073_BAM, &val); - bnx2x_cl45_write(bp, phy, - MDIO_AN_DEVAD, - MDIO_AN_REG_8073_BAM, val | 1); + 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_AN_DEVAD, + MDIO_AN_REG_8073_BAM, &val); + bnx2x_cl45_write(bp, phy, + MDIO_AN_DEVAD, + MDIO_AN_REG_8073_BAM, val | 1); + DP(NETIF_MSG_LINK, "Enable CL37 BAM on KR\n"); + } if (params->loopback_mode == LOOPBACK_EXT) { bnx2x_807x_force_10G(bp, phy); DP(NETIF_MSG_LINK, "Forced speed 10G on 807X\n"); @@ -3898,7 +3904,7 @@ static u8 bnx2x_8726_read_sfp_module_eeprom(struct bnx2x_phy *phy, MDIO_PMA_REG_SFP_TWO_WIRE_CTRL, &val); if ((val & MDIO_PMA_REG_SFP_TWO_WIRE_CTRL_STATUS_MASK) == MDIO_PMA_REG_SFP_TWO_WIRE_STATUS_IDLE) - return 0;; + return 0; msleep(1); } return -EINVAL; @@ -3982,7 +3988,7 @@ static u8 bnx2x_8727_read_sfp_module_eeprom(struct bnx2x_phy *phy, MDIO_PMA_REG_SFP_TWO_WIRE_CTRL, &val); if ((val & MDIO_PMA_REG_SFP_TWO_WIRE_CTRL_STATUS_MASK) == MDIO_PMA_REG_SFP_TWO_WIRE_STATUS_IDLE) - return 0;; + return 0; msleep(1); } @@ -5302,7 +5308,7 @@ static u8 bnx2x_848xx_cmn_config_init(struct bnx2x_phy *phy, { struct bnx2x *bp = params->bp; u16 autoneg_val, an_1000_val, an_10_100_val; - bnx2x_wait_reset_complete(bp, phy); + bnx2x_bits_en(bp, NIG_REG_LATCH_BC_0 + params->port*4, 1 << NIG_LATCH_BC_ENABLE_MI_INT); @@ -5431,6 +5437,7 @@ static u8 bnx2x_8481_config_init(struct bnx2x_phy *phy, /* HW reset */ bnx2x_ext_phy_hw_reset(bp, params->port); + bnx2x_wait_reset_complete(bp, phy); bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 1<<15); return bnx2x_848xx_cmn_config_init(phy, params, vars); @@ -5441,7 +5448,7 @@ static u8 bnx2x_848x3_config_init(struct bnx2x_phy *phy, struct link_vars *vars) { struct bnx2x *bp = params->bp; - u8 port = params->port, initialize = 1; + u8 port, initialize = 1; u16 val; u16 temp; u32 actual_phy_selection; @@ -5450,11 +5457,16 @@ static u8 bnx2x_848x3_config_init(struct bnx2x_phy *phy, /* This is just for MDIO_CTL_REG_84823_MEDIA register. */ msleep(1); + if (CHIP_IS_E2(bp)) + port = BP_PATH(bp); + else + port = params->port; bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_3, MISC_REGISTERS_GPIO_OUTPUT_HIGH, port); - msleep(200); /* 100 is not enough */ - + bnx2x_wait_reset_complete(bp, phy); + /* Wait for GPHY to come out of reset */ + msleep(50); /* BCM84823 requires that XGXS links up first @ 10G for normal behavior */ temp = vars->line_speed; @@ -5625,7 +5637,11 @@ static void bnx2x_848x3_link_reset(struct bnx2x_phy *phy, struct link_params *params) { struct bnx2x *bp = params->bp; - u8 port = params->port; + u8 port; + if (CHIP_IS_E2(bp)) + port = BP_PATH(bp); + else + port = params->port; bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_3, MISC_REGISTERS_GPIO_OUTPUT_LOW, port); @@ -6928,7 +6944,7 @@ u8 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; + u8 phy_index, port = params->port, clear_latch_ind = 0; DP(NETIF_MSG_LINK, "Resetting the link of port %d\n", port); /* disable attentions */ vars->link_status = 0; @@ -6966,9 +6982,18 @@ u8 bnx2x_link_reset(struct link_params *params, struct link_vars *vars, params->phy[phy_index].link_reset( ¶ms->phy[phy_index], params); + if (params->phy[phy_index].flags & + FLAGS_REARM_LATCH_SIGNAL) + clear_latch_ind = 1; } } + if (clear_latch_ind) { + /* Clear latching indication */ + bnx2x_rearm_latch_signal(bp, port, 0); + bnx2x_bits_dis(bp, NIG_REG_LATCH_BC_0 + port*4, + 1 << NIG_LATCH_BC_ENABLE_MI_INT); + } if (params->phy[INT_PHY].link_reset) params->phy[INT_PHY].link_reset( ¶ms->phy[INT_PHY], params); @@ -6999,6 +7024,7 @@ static u8 bnx2x_8073_common_init_phy(struct bnx2x *bp, s8 port; s8 port_of_path = 0; + bnx2x_ext_phy_hw_reset(bp, 0); /* PART1 - Reset both phys */ for (port = PORT_MAX - 1; port >= PORT_0; port--) { u32 shmem_base, shmem2_base; @@ -7021,7 +7047,8 @@ static u8 bnx2x_8073_common_init_phy(struct bnx2x *bp, return -EINVAL; } /* disable attentions */ - bnx2x_bits_dis(bp, NIG_REG_MASK_INTERRUPT_PORT0 + port*4, + bnx2x_bits_dis(bp, NIG_REG_MASK_INTERRUPT_PORT0 + + port_of_path*4, (NIG_MASK_XGXS0_LINK_STATUS | NIG_MASK_XGXS0_LINK10G | NIG_MASK_SERDES0_LINK_STATUS | @@ -7132,7 +7159,7 @@ static u8 bnx2x_8726_common_init_phy(struct bnx2x *bp, (1<<(MISC_REGISTERS_GPIO_3 + MISC_REGISTERS_GPIO_PORT_SHIFT))); REG_WR(bp, MISC_REG_GPIO_EVENT_EN, val); - bnx2x_ext_phy_hw_reset(bp, 1); + bnx2x_ext_phy_hw_reset(bp, 0); msleep(5); for (port = 0; port < PORT_MAX; port++) { u32 shmem_base, shmem2_base; diff --git a/drivers/net/bnx2x/bnx2x_main.c b/drivers/net/bnx2x/bnx2x_main.c index e9ad16f00b56..1552fc3c1351 100644 --- a/drivers/net/bnx2x/bnx2x_main.c +++ b/drivers/net/bnx2x/bnx2x_main.c @@ -2026,13 +2026,28 @@ static int bnx2x_get_cmng_fns_mode(struct bnx2x *bp) static void bnx2x_read_mf_cfg(struct bnx2x *bp) { - int vn; + int vn, n = (CHIP_MODE_IS_4_PORT(bp) ? 2 : 1); if (BP_NOMCP(bp)) return; /* what should be the default bvalue in this case */ + /* For 2 port configuration the absolute function number formula + * is: + * abs_func = 2 * vn + BP_PORT + BP_PATH + * + * and there are 4 functions per port + * + * For 4 port configuration it is + * abs_func = 4 * vn + 2 * BP_PORT + BP_PATH + * + * and there are 2 functions per port + */ for (vn = VN_0; vn < E1HVN_MAX; vn++) { - int /*abs*/func = 2*vn + BP_PORT(bp); + int /*abs*/func = n * (2 * vn + BP_PORT(bp)) + BP_PATH(bp); + + if (func >= E1H_FUNC_MAX) + break; + bp->mf_config[vn] = MF_CFG_RD(bp, func_mf_config[func].config); } @@ -2248,10 +2263,21 @@ static void bnx2x_rxq_set_mac_filters(struct bnx2x *bp, u16 cl_id, u32 filters) 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; + } } if (filters & BNX2X_ACCEPT_UNICAST) { /* accept matched ucast */ @@ -2260,6 +2286,11 @@ static void bnx2x_rxq_set_mac_filters(struct bnx2x *bp, u16 cl_id, u32 filters) if (filters & BNX2X_ACCEPT_MULTICAST) { /* accept matched mcast */ drop_all_mcast = 0; + if (IS_MF_SI(bp)) + /* since mcast addresses won't arrive with ovlan, + * fw needs to accept all of them in + * switch-independent mode */ + accp_all_mcast = 1; } if (filters & BNX2X_ACCEPT_ALL_UNICAST) { /* accept all mcast */ @@ -2372,7 +2403,7 @@ static inline u16 bnx2x_get_cl_flags(struct bnx2x *bp, /* calculate queue flags */ flags |= QUEUE_FLG_CACHE_ALIGN; flags |= QUEUE_FLG_HC; - flags |= IS_MF(bp) ? QUEUE_FLG_OV : 0; + flags |= IS_MF_SD(bp) ? QUEUE_FLG_OV : 0; flags |= QUEUE_FLG_VLAN; DP(NETIF_MSG_IFUP, "vlan removal enabled\n"); @@ -2573,6 +2604,26 @@ static void bnx2x_e1h_enable(struct bnx2x *bp) */ } +/* called due to MCP event (on pmf): + * reread new bandwidth configuration + * configure FW + * notify others function about the change + */ +static inline void bnx2x_config_mf_bw(struct bnx2x *bp) +{ + if (bp->link_vars.link_up) { + bnx2x_cmng_fns_init(bp, true, CMNG_FNS_MINMAX); + bnx2x_link_sync_notify(bp); + } + storm_memset_cmng(bp, &bp->cmng, BP_PORT(bp)); +} + +static inline void bnx2x_set_mf_bw(struct bnx2x *bp) +{ + bnx2x_config_mf_bw(bp); + bnx2x_fw_command(bp, DRV_MSG_CODE_SET_MF_BW_ACK, 0); +} + static void bnx2x_dcc_event(struct bnx2x *bp, u32 dcc_event) { DP(BNX2X_MSG_MCP, "dcc_event 0x%x\n", dcc_event); @@ -2598,10 +2649,7 @@ static void bnx2x_dcc_event(struct bnx2x *bp, u32 dcc_event) dcc_event &= ~DRV_STATUS_DCC_DISABLE_ENABLE_PF; } if (dcc_event & DRV_STATUS_DCC_BANDWIDTH_ALLOCATION) { - - bnx2x_cmng_fns_init(bp, true, CMNG_FNS_MINMAX); - bnx2x_link_sync_notify(bp); - storm_memset_cmng(bp, &bp->cmng, BP_PORT(bp)); + bnx2x_config_mf_bw(bp); dcc_event &= ~DRV_STATUS_DCC_BANDWIDTH_ALLOCATION; } @@ -3022,6 +3070,10 @@ static inline void bnx2x_attn_int_deasserted3(struct bnx2x *bp, u32 attn) if (val & DRV_STATUS_DCC_EVENT_MASK) bnx2x_dcc_event(bp, (val & DRV_STATUS_DCC_EVENT_MASK)); + + if (val & DRV_STATUS_SET_MF_BW) + bnx2x_set_mf_bw(bp); + bnx2x__link_status_update(bp); if ((bp->port.pmf == 0) && (val & DRV_STATUS_PMF)) bnx2x_pmf_update(bp); @@ -4232,6 +4284,15 @@ static void bnx2x_init_internal_common(struct bnx2x *bp) bp->mf_mode); } + if (IS_MF_SI(bp)) + /* + * In switch independent mode, the TSTORM needs to accept + * packets that failed classification, since approximate match + * mac addresses aren't written to NIG LLH + */ + REG_WR8(bp, BAR_TSTRORM_INTMEM + + TSTORM_ACCEPT_CLASSIFY_FAILED_OFFSET, 2); + /* Zero this manually as its initialization is currently missing in the initTool */ for (i = 0; i < (USTORM_AGG_DATA_SIZE >> 2); i++) @@ -5048,12 +5109,12 @@ static int bnx2x_init_hw_common(struct bnx2x *bp, u32 load_code) REG_WR(bp, PRS_REG_NIC_MODE, 1); #endif if (!CHIP_IS_E1(bp)) - REG_WR(bp, PRS_REG_E1HOV_MODE, IS_MF(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(bp); + 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)); } @@ -5087,7 +5148,7 @@ static int bnx2x_init_hw_common(struct bnx2x *bp, u32 load_code) bnx2x_init_block(bp, PBF_BLOCK, COMMON_STAGE); if (CHIP_IS_E2(bp)) { - int has_ovlan = IS_MF(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)); } @@ -5164,12 +5225,12 @@ static int bnx2x_init_hw_common(struct bnx2x *bp, u32 load_code) bnx2x_init_block(bp, NIG_BLOCK, COMMON_STAGE); if (!CHIP_IS_E1(bp)) { REG_WR(bp, NIG_REG_LLH_MF_MODE, IS_MF(bp)); - REG_WR(bp, NIG_REG_LLH_E1HOV_MODE, IS_MF(bp)); + 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(bp) ? 7 : 6)); + REG_WR(bp, NIG_REG_P0_HDRS_AFTER_BASIC, (IS_MF_SD(bp) ? 7 : 6)); } if (CHIP_REV_IS_SLOW(bp)) @@ -5386,7 +5447,7 @@ static int bnx2x_init_hw_port(struct bnx2x *bp) 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(bp) ? 0x1 : 0x2)); + (IS_MF_SD(bp) ? 0x1 : 0x2)); if (CHIP_IS_E2(bp)) { val = 0; @@ -6170,6 +6231,70 @@ static u8 bnx2x_e1h_cam_offset(struct bnx2x *bp, u8 rel_offset) return BP_VN(bp) * 32 + rel_offset; } +/** + * LLH CAM line allocations: 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 16 per function MAC + * entries in the LLH memory. + */ +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) : @@ -6179,6 +6304,8 @@ void bnx2x_set_eth_mac(struct bnx2x *bp, int set) 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 */ u8 bcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; @@ -6289,6 +6416,8 @@ static int bnx2x_set_iscsi_eth_mac_addr(struct bnx2x *bp, int set) /* Send a SET_MAC ramrod */ bnx2x_set_mac_addr_gen(bp, set, bp->iscsi_mac, cl_bit_vec, cam_offset, 0); + + bnx2x_set_mac_in_nig(bp, set, bp->iscsi_mac, LLH_CAM_ISCSI_ETH_LINE); return 0; } #endif @@ -8076,9 +8205,8 @@ static void __devinit bnx2x_set_mac_buf(u8 *mac_buf, u32 mac_lo, u16 mac_hi) static void __devinit bnx2x_get_port_hwinfo(struct bnx2x *bp) { int port = BP_PORT(bp); - u32 val, val2; u32 config; - u32 ext_phy_type, ext_phy_config;; + u32 ext_phy_type, ext_phy_config; bp->link_params.bp = bp; bp->link_params.port = port; @@ -8135,25 +8263,62 @@ static void __devinit bnx2x_get_port_hwinfo(struct bnx2x *bp) (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN)) bp->mdio.prtad = XGXS_EXT_PHY_ADDR(ext_phy_config); +} - val2 = SHMEM_RD(bp, dev_info.port_hw_config[port].mac_upper); - val = SHMEM_RD(bp, dev_info.port_hw_config[port].mac_lower); - bnx2x_set_mac_buf(bp->dev->dev_addr, val, val2); - memcpy(bp->link_params.mac_addr, bp->dev->dev_addr, ETH_ALEN); - memcpy(bp->dev->perm_addr, bp->dev->dev_addr, ETH_ALEN); +static void __devinit bnx2x_get_mac_hwinfo(struct bnx2x *bp) +{ + u32 val, val2; + int func = BP_ABS_FUNC(bp); + int port = BP_PORT(bp); + + if (BP_NOMCP(bp)) { + BNX2X_ERROR("warning: random MAC workaround active\n"); + random_ether_addr(bp->dev->dev_addr); + } else if (IS_MF(bp)) { + val2 = MF_CFG_RD(bp, func_mf_config[func].mac_upper); + val = MF_CFG_RD(bp, func_mf_config[func].mac_lower); + if ((val2 != FUNC_MF_CFG_UPPERMAC_DEFAULT) && + (val != FUNC_MF_CFG_LOWERMAC_DEFAULT)) + bnx2x_set_mac_buf(bp->dev->dev_addr, val, val2); + +#ifdef BCM_CNIC + /* iSCSI NPAR MAC */ + if (IS_MF_SI(bp)) { + u32 cfg = MF_CFG_RD(bp, func_ext_config[func].func_cfg); + if (cfg & MACP_FUNC_CFG_FLAGS_ISCSI_OFFLOAD) { + val2 = MF_CFG_RD(bp, func_ext_config[func]. + iscsi_mac_addr_upper); + val = MF_CFG_RD(bp, func_ext_config[func]. + iscsi_mac_addr_lower); + bnx2x_set_mac_buf(bp->iscsi_mac, val, val2); + } + } +#endif + } else { + /* in SF read MACs from port configuration */ + val2 = SHMEM_RD(bp, dev_info.port_hw_config[port].mac_upper); + val = SHMEM_RD(bp, dev_info.port_hw_config[port].mac_lower); + bnx2x_set_mac_buf(bp->dev->dev_addr, val, val2); #ifdef BCM_CNIC - val2 = SHMEM_RD(bp, dev_info.port_hw_config[port].iscsi_mac_upper); - val = SHMEM_RD(bp, dev_info.port_hw_config[port].iscsi_mac_lower); - bnx2x_set_mac_buf(bp->iscsi_mac, val, val2); + val2 = SHMEM_RD(bp, dev_info.port_hw_config[port]. + iscsi_mac_upper); + val = SHMEM_RD(bp, dev_info.port_hw_config[port]. + iscsi_mac_lower); + bnx2x_set_mac_buf(bp->iscsi_mac, val, val2); #endif + } + + memcpy(bp->link_params.mac_addr, bp->dev->dev_addr, ETH_ALEN); + memcpy(bp->dev->perm_addr, bp->dev->dev_addr, ETH_ALEN); + } static int __devinit bnx2x_get_hwinfo(struct bnx2x *bp) { - int func = BP_ABS_FUNC(bp); - int vn; - u32 val, val2; + int /*abs*/func = BP_ABS_FUNC(bp); + int vn, port; + u32 val = 0; int rc = 0; bnx2x_get_common_hwinfo(bp); @@ -8186,44 +8351,99 @@ static int __devinit bnx2x_get_hwinfo(struct bnx2x *bp) bp->mf_ov = 0; bp->mf_mode = 0; vn = BP_E1HVN(bp); + port = BP_PORT(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)); if (SHMEM2_HAS(bp, mf_cfg_addr)) bp->common.mf_cfg_base = SHMEM2_RD(bp, mf_cfg_addr); else bp->common.mf_cfg_base = bp->common.shmem_base + offsetof(struct shmem_region, func_mb) + E1H_FUNC_MAX * sizeof(struct drv_func_mb); - bp->mf_config[vn] = - MF_CFG_RD(bp, func_mf_config[func].config); + /* + * get mf configuration: + * 1. existance of MF configuration + * 2. MAC address must be legal (check only upper bytes) + * for Switch-Independent mode; + * OVLAN must be legal for Switch-Dependent mode + * 3. SF_MODE configures specific MF mode + */ + if (bp->common.mf_cfg_base != SHMEM_MF_CFG_ADDR_NONE) { + /* get mf configuration */ + val = SHMEM_RD(bp, + dev_info.shared_feature_config.config); + val &= SHARED_FEAT_CFG_FORCE_SF_MODE_MASK; + + switch (val) { + case SHARED_FEAT_CFG_FORCE_SF_MODE_SWITCH_INDEPT: + val = MF_CFG_RD(bp, func_mf_config[func]. + mac_upper); + /* check for legal mac (upper bytes)*/ + if (val != 0xffff) { + bp->mf_mode = MULTI_FUNCTION_SI; + bp->mf_config[vn] = MF_CFG_RD(bp, + func_mf_config[func].config); + } else + DP(NETIF_MSG_PROBE, "illegal MAC " + "address for SI\n"); + break; + case SHARED_FEAT_CFG_FORCE_SF_MODE_MF_ALLOWED: + /* get OV configuration */ + val = MF_CFG_RD(bp, + func_mf_config[FUNC_0].e1hov_tag); + val &= FUNC_MF_CFG_E1HOV_TAG_MASK; + + if (val != FUNC_MF_CFG_E1HOV_TAG_DEFAULT) { + bp->mf_mode = MULTI_FUNCTION_SD; + bp->mf_config[vn] = MF_CFG_RD(bp, + func_mf_config[func].config); + } else + DP(NETIF_MSG_PROBE, "illegal OV for " + "SD\n"); + break; + default: + /* Unknown configuration: reset mf_config */ + bp->mf_config[vn] = 0; + DP(NETIF_MSG_PROBE, "Unkown MF mode 0x%x\n", + val); + } + } - val = (MF_CFG_RD(bp, func_mf_config[FUNC_0].e1hov_tag) & - FUNC_MF_CFG_E1HOV_TAG_MASK); - if (val != FUNC_MF_CFG_E1HOV_TAG_DEFAULT) - bp->mf_mode = 1; BNX2X_DEV_INFO("%s function mode\n", IS_MF(bp) ? "multi" : "single"); - if (IS_MF(bp)) { - val = (MF_CFG_RD(bp, func_mf_config[func]. - e1hov_tag) & - FUNC_MF_CFG_E1HOV_TAG_MASK); + switch (bp->mf_mode) { + case MULTI_FUNCTION_SD: + val = MF_CFG_RD(bp, func_mf_config[func].e1hov_tag) & + 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); + BNX2X_DEV_INFO("MF OV for func %d is %d" + " (0x%04x)\n", func, + bp->mf_ov, bp->mf_ov); } else { - BNX2X_ERROR("No valid MF OV for func %d," - " aborting\n", func); + BNX2X_ERR("No valid MF OV for func %d," + " aborting\n", func); rc = -EPERM; } - } else { - if (BP_VN(bp)) { - BNX2X_ERROR("VN %d in single function mode," - " aborting\n", BP_E1HVN(bp)); + break; + case MULTI_FUNCTION_SI: + BNX2X_DEV_INFO("func %d is in MF " + "switch-independent mode\n", func); + break; + default: + if (vn) { + BNX2X_ERR("VN %d in single function mode," + " aborting\n", vn); rc = -EPERM; } + break; } + } /* adjust igu_sb_cnt to MF for E1x */ @@ -8248,32 +8468,8 @@ static int __devinit bnx2x_get_hwinfo(struct bnx2x *bp) BNX2X_DEV_INFO("fw_seq 0x%08x\n", bp->fw_seq); } - if (IS_MF(bp)) { - val2 = MF_CFG_RD(bp, func_mf_config[func].mac_upper); - val = MF_CFG_RD(bp, func_mf_config[func].mac_lower); - if ((val2 != FUNC_MF_CFG_UPPERMAC_DEFAULT) && - (val != FUNC_MF_CFG_LOWERMAC_DEFAULT)) { - bp->dev->dev_addr[0] = (u8)(val2 >> 8 & 0xff); - bp->dev->dev_addr[1] = (u8)(val2 & 0xff); - bp->dev->dev_addr[2] = (u8)(val >> 24 & 0xff); - bp->dev->dev_addr[3] = (u8)(val >> 16 & 0xff); - bp->dev->dev_addr[4] = (u8)(val >> 8 & 0xff); - bp->dev->dev_addr[5] = (u8)(val & 0xff); - memcpy(bp->link_params.mac_addr, bp->dev->dev_addr, - ETH_ALEN); - memcpy(bp->dev->perm_addr, bp->dev->dev_addr, - ETH_ALEN); - } - - return rc; - } - - if (BP_NOMCP(bp)) { - /* only supposed to happen on emulation/FPGA */ - BNX2X_ERROR("warning: random MAC workaround active\n"); - random_ether_addr(bp->dev->dev_addr); - memcpy(bp->dev->perm_addr, bp->dev->dev_addr, ETH_ALEN); - } + /* Get MAC addresses */ + bnx2x_get_mac_hwinfo(bp); return rc; } @@ -9064,7 +9260,7 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev, default: pr_err("Unknown board_type (%ld), aborting\n", ent->driver_data); - return ENODEV; + return -ENODEV; } cid_count += CNIC_CONTEXT_USE; @@ -9096,12 +9292,6 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev, /* calc qm_cid_count */ bp->qm_cid_count = bnx2x_set_qm_cid_count(bp, cid_count); - rc = register_netdev(dev); - if (rc) { - dev_err(&pdev->dev, "Cannot register net device\n"); - goto init_one_exit; - } - /* Configure interupt mode: try to enable MSI-X/MSI if * needed, set bp->num_queues appropriately. */ @@ -9110,6 +9300,12 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev, /* Add all NAPI objects */ bnx2x_add_all_napi(bp); + rc = register_netdev(dev); + if (rc) { + dev_err(&pdev->dev, "Cannot register net device\n"); + goto init_one_exit; + } + bnx2x_get_pcie_width_speed(bp, &pcie_width, &pcie_speed); netdev_info(dev, "%s (%c%d) PCI-E x%d %s found at mem %lx," diff --git a/drivers/net/bnx2x/bnx2x_reg.h b/drivers/net/bnx2x/bnx2x_reg.h index 1cefe489a955..64bdda189e5a 100644 --- a/drivers/net/bnx2x/bnx2x_reg.h +++ b/drivers/net/bnx2x/bnx2x_reg.h @@ -1774,6 +1774,8 @@ /* [RW 8] event id for llh0 */ #define NIG_REG_LLH0_EVENT_ID 0x10084 #define NIG_REG_LLH0_FUNC_EN 0x160fc +#define NIG_REG_LLH0_FUNC_MEM 0x16180 +#define NIG_REG_LLH0_FUNC_MEM_ENABLE 0x16140 #define NIG_REG_LLH0_FUNC_VLAN_ID 0x16100 /* [RW 1] Determine the IP version to look for in ~nig_registers_llh0_dest_ip_0.llh0_dest_ip_0. 0 - IPv6; 1-IPv4 */ @@ -1797,6 +1799,9 @@ #define NIG_REG_LLH1_ERROR_MASK 0x10090 /* [RW 8] event id for llh1 */ #define NIG_REG_LLH1_EVENT_ID 0x10088 +#define NIG_REG_LLH1_FUNC_MEM 0x161c0 +#define NIG_REG_LLH1_FUNC_MEM_ENABLE 0x16160 +#define NIG_REG_LLH1_FUNC_MEM_SIZE 16 /* [RW 8] init credit counter for port1 in LLH */ #define NIG_REG_LLH1_XCM_INIT_CREDIT 0x10564 #define NIG_REG_LLH1_XCM_MASK 0x10134 diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c index 881914bc4e9c..48cf24ff4e6f 100644 --- a/drivers/net/bonding/bond_3ad.c +++ b/drivers/net/bonding/bond_3ad.c @@ -2474,8 +2474,7 @@ int bond_3ad_lacpdu_recv(struct sk_buff *skb, struct net_device *dev, struct pac goto out; read_lock(&bond->lock); - slave = bond_get_slave_by_dev((struct bonding *)netdev_priv(dev), - orig_dev); + slave = bond_get_slave_by_dev(netdev_priv(dev), orig_dev); if (!slave) goto out_unlock; diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index bdb68a600382..0273ad0b57bb 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -873,15 +873,11 @@ static void bond_mc_del(struct bonding *bond, void *addr) static void __bond_resend_igmp_join_requests(struct net_device *dev) { struct in_device *in_dev; - struct ip_mc_list *im; rcu_read_lock(); in_dev = __in_dev_get_rcu(dev); - if (in_dev) { - for (im = in_dev->mc_list; im; im = im->next) - ip_mc_rejoin_group(im); - } - + if (in_dev) + ip_mc_rejoin_groups(in_dev); rcu_read_unlock(); } @@ -3209,7 +3205,7 @@ out: #ifdef CONFIG_PROC_FS static void *bond_info_seq_start(struct seq_file *seq, loff_t *pos) - __acquires(&dev_base_lock) + __acquires(RCU) __acquires(&bond->lock) { struct bonding *bond = seq->private; @@ -3218,7 +3214,7 @@ static void *bond_info_seq_start(struct seq_file *seq, loff_t *pos) int i; /* make sure the bond won't be taken away */ - read_lock(&dev_base_lock); + rcu_read_lock(); read_lock(&bond->lock); if (*pos == 0) @@ -3248,12 +3244,12 @@ static void *bond_info_seq_next(struct seq_file *seq, void *v, loff_t *pos) static void bond_info_seq_stop(struct seq_file *seq, void *v) __releases(&bond->lock) - __releases(&dev_base_lock) + __releases(RCU) { struct bonding *bond = seq->private; read_unlock(&bond->lock); - read_unlock(&dev_base_lock); + rcu_read_unlock(); } static void bond_info_show_master(struct seq_file *seq) diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h index 4eedb12df6ca..ad3ae46a4c01 100644 --- a/drivers/net/bonding/bonding.h +++ b/drivers/net/bonding/bonding.h @@ -286,7 +286,7 @@ static inline struct bonding *bond_get_bond_by_slave(struct slave *slave) return NULL; } - return (struct bonding *)netdev_priv(slave->dev->master); + return netdev_priv(slave->dev->master); } static inline bool bond_is_lb(const struct bonding *bond) diff --git a/drivers/net/caif/caif_spi.c b/drivers/net/caif/caif_spi.c index 8427533fe313..20da1996d354 100644 --- a/drivers/net/caif/caif_spi.c +++ b/drivers/net/caif/caif_spi.c @@ -33,6 +33,9 @@ MODULE_LICENSE("GPL"); MODULE_AUTHOR("Daniel Martensson<daniel.martensson@stericsson.com>"); MODULE_DESCRIPTION("CAIF SPI driver"); +/* Returns the number of padding bytes for alignment. */ +#define PAD_POW2(x, pow) ((((x)&((pow)-1))==0) ? 0 : (((pow)-((x)&((pow)-1))))) + static int spi_loop; module_param(spi_loop, bool, S_IRUGO); MODULE_PARM_DESC(spi_loop, "SPI running in loopback mode."); @@ -41,7 +44,10 @@ MODULE_PARM_DESC(spi_loop, "SPI running in loopback mode."); module_param(spi_frm_align, int, S_IRUGO); MODULE_PARM_DESC(spi_frm_align, "SPI frame alignment."); -/* SPI padding options. */ +/* + * SPI padding options. + * Warning: must be a base of 2 (& operation used) and can not be zero ! + */ module_param(spi_up_head_align, int, S_IRUGO); MODULE_PARM_DESC(spi_up_head_align, "SPI uplink head alignment."); @@ -240,15 +246,13 @@ static ssize_t dbgfs_frame(struct file *file, char __user *user_buf, static const struct file_operations dbgfs_state_fops = { .open = dbgfs_open, .read = dbgfs_state, - .owner = THIS_MODULE, - .llseek = default_llseek, + .owner = THIS_MODULE }; static const struct file_operations dbgfs_frame_fops = { .open = dbgfs_open, .read = dbgfs_frame, - .owner = THIS_MODULE, - .llseek = default_llseek, + .owner = THIS_MODULE }; static inline void dev_debugfs_add(struct cfspi *cfspi) @@ -337,6 +341,9 @@ int cfspi_xmitfrm(struct cfspi *cfspi, u8 *buf, size_t len) u8 *dst = buf; caif_assert(buf); + if (cfspi->slave && !cfspi->slave_talked) + cfspi->slave_talked = true; + do { struct sk_buff *skb; struct caif_payload_info *info; @@ -357,8 +364,8 @@ int cfspi_xmitfrm(struct cfspi *cfspi, u8 *buf, size_t len) * Compute head offset i.e. number of bytes to add to * get the start of the payload aligned. */ - if (spi_up_head_align) { - spad = 1 + ((info->hdr_len + 1) & spi_up_head_align); + if (spi_up_head_align > 1) { + spad = 1 + PAD_POW2((info->hdr_len + 1), spi_up_head_align); *dst = (u8)(spad - 1); dst += spad; } @@ -373,7 +380,7 @@ int cfspi_xmitfrm(struct cfspi *cfspi, u8 *buf, size_t len) * Compute tail offset i.e. number of bytes to add to * get the complete CAIF frame aligned. */ - epad = (skb->len + spad) & spi_up_tail_align; + epad = PAD_POW2((skb->len + spad), spi_up_tail_align); dst += epad; dev_kfree_skb(skb); @@ -417,14 +424,14 @@ int cfspi_xmitlen(struct cfspi *cfspi) * Compute head offset i.e. number of bytes to add to * get the start of the payload aligned. */ - if (spi_up_head_align) - spad = 1 + ((info->hdr_len + 1) & spi_up_head_align); + if (spi_up_head_align > 1) + spad = 1 + PAD_POW2((info->hdr_len + 1), spi_up_head_align); /* * Compute tail offset i.e. number of bytes to add to * get the complete CAIF frame aligned. */ - epad = (skb->len + spad) & spi_up_tail_align; + epad = PAD_POW2((skb->len + spad), spi_up_tail_align); if ((skb->len + spad + epad + frm_len) <= CAIF_MAX_SPI_FRAME) { skb_queue_tail(&cfspi->chead, skb); @@ -433,6 +440,7 @@ int cfspi_xmitlen(struct cfspi *cfspi) } else { /* Put back packet. */ skb_queue_head(&cfspi->qhead, skb); + break; } } while (pkts <= CAIF_MAX_SPI_PKTS); @@ -453,6 +461,15 @@ static void cfspi_ss_cb(bool assert, struct cfspi_ifc *ifc) { struct cfspi *cfspi = (struct cfspi *)ifc->priv; + /* + * The slave device is the master on the link. Interrupts before the + * slave has transmitted are considered spurious. + */ + if (cfspi->slave && !cfspi->slave_talked) { + printk(KERN_WARNING "CFSPI: Spurious SS interrupt.\n"); + return; + } + if (!in_interrupt()) spin_lock(&cfspi->lock); if (assert) { @@ -465,7 +482,8 @@ static void cfspi_ss_cb(bool assert, struct cfspi_ifc *ifc) spin_unlock(&cfspi->lock); /* Wake up the xfer thread. */ - wake_up_interruptible(&cfspi->wait); + if (assert) + wake_up_interruptible(&cfspi->wait); } static void cfspi_xfer_done_cb(struct cfspi_ifc *ifc) @@ -523,7 +541,7 @@ int cfspi_rxfrm(struct cfspi *cfspi, u8 *buf, size_t len) * Compute head offset i.e. number of bytes added to * get the start of the payload aligned. */ - if (spi_down_head_align) { + if (spi_down_head_align > 1) { spad = 1 + *src; src += spad; } @@ -564,7 +582,7 @@ int cfspi_rxfrm(struct cfspi *cfspi, u8 *buf, size_t len) * Compute tail offset i.e. number of bytes added to * get the complete CAIF frame aligned. */ - epad = (pkt_len + spad) & spi_down_tail_align; + epad = PAD_POW2((pkt_len + spad), spi_down_tail_align); src += epad; } while ((src - buf) < len); @@ -617,19 +635,28 @@ int cfspi_spi_probe(struct platform_device *pdev) ndev = alloc_netdev(sizeof(struct cfspi), "cfspi%d", cfspi_setup); - if (!dev) - return -ENODEV; + if (!ndev) + return -ENOMEM; cfspi = netdev_priv(ndev); netif_stop_queue(ndev); cfspi->ndev = ndev; cfspi->pdev = pdev; - /* Set flow info */ + /* Set flow info. */ cfspi->flow_off_sent = 0; cfspi->qd_low_mark = LOW_WATER_MARK; cfspi->qd_high_mark = HIGH_WATER_MARK; + /* Set slave info. */ + if (!strncmp(cfspi_spi_driver.driver.name, "cfspi_sspi", 10)) { + cfspi->slave = true; + cfspi->slave_talked = false; + } else { + cfspi->slave = false; + cfspi->slave_talked = false; + } + /* Assign the SPI device. */ cfspi->dev = dev; /* Assign the device ifc to this SPI interface. */ diff --git a/drivers/net/caif/caif_spi_slave.c b/drivers/net/caif/caif_spi_slave.c index 2111dbfea6fe..1b9943a4edab 100644 --- a/drivers/net/caif/caif_spi_slave.c +++ b/drivers/net/caif/caif_spi_slave.c @@ -36,10 +36,15 @@ static inline int forward_to_spi_cmd(struct cfspi *cfspi) #endif int spi_frm_align = 2; -int spi_up_head_align = 1; -int spi_up_tail_align; -int spi_down_head_align = 3; -int spi_down_tail_align = 1; + +/* + * SPI padding options. + * Warning: must be a base of 2 (& operation used) and can not be zero ! + */ +int spi_up_head_align = 1 << 1; +int spi_up_tail_align = 1 << 0; +int spi_down_head_align = 1 << 2; +int spi_down_tail_align = 1 << 1; #ifdef CONFIG_DEBUG_FS static inline void debugfs_store_prev(struct cfspi *cfspi) diff --git a/drivers/net/can/mscan/mscan.c b/drivers/net/can/mscan/mscan.c index 64c378cd0c34..74cd880c7e06 100644 --- a/drivers/net/can/mscan/mscan.c +++ b/drivers/net/can/mscan/mscan.c @@ -182,7 +182,7 @@ static int mscan_restart(struct net_device *dev) priv->can.state = CAN_STATE_ERROR_ACTIVE; WARN(!(in_8(®s->canmisc) & MSCAN_BOHOLD), - "bus-off state expected"); + "bus-off state expected\n"); out_8(®s->canmisc, MSCAN_BOHOLD); /* Re-enable receive interrupts. */ out_8(®s->canrier, MSCAN_RX_INTS_ENABLE); diff --git a/drivers/net/can/pch_can.c b/drivers/net/can/pch_can.c index 672718261c68..a9b6a6525a65 100644 --- a/drivers/net/can/pch_can.c +++ b/drivers/net/can/pch_can.c @@ -32,99 +32,91 @@ #include <linux/can/dev.h> #include <linux/can/error.h> -#define MAX_MSG_OBJ 32 -#define MSG_OBJ_RX 0 /* The receive message object flag. */ -#define MSG_OBJ_TX 1 /* The transmit message object flag. */ - -#define ENABLE 1 /* The enable flag */ -#define DISABLE 0 /* The disable flag */ -#define CAN_CTRL_INIT 0x0001 /* The INIT bit of CANCONT register. */ -#define CAN_CTRL_IE 0x0002 /* The IE bit of CAN control register */ -#define CAN_CTRL_IE_SIE_EIE 0x000e -#define CAN_CTRL_CCE 0x0040 -#define CAN_CTRL_OPT 0x0080 /* The OPT bit of CANCONT register. */ -#define CAN_OPT_SILENT 0x0008 /* The Silent bit of CANOPT reg. */ -#define CAN_OPT_LBACK 0x0010 /* The LoopBack bit of CANOPT reg. */ -#define CAN_CMASK_RX_TX_SET 0x00f3 -#define CAN_CMASK_RX_TX_GET 0x0073 -#define CAN_CMASK_ALL 0xff -#define CAN_CMASK_RDWR 0x80 -#define CAN_CMASK_ARB 0x20 -#define CAN_CMASK_CTRL 0x10 -#define CAN_CMASK_MASK 0x40 -#define CAN_CMASK_NEWDAT 0x04 -#define CAN_CMASK_CLRINTPND 0x08 - -#define CAN_IF_MCONT_NEWDAT 0x8000 -#define CAN_IF_MCONT_INTPND 0x2000 -#define CAN_IF_MCONT_UMASK 0x1000 -#define CAN_IF_MCONT_TXIE 0x0800 -#define CAN_IF_MCONT_RXIE 0x0400 -#define CAN_IF_MCONT_RMTEN 0x0200 -#define CAN_IF_MCONT_TXRQXT 0x0100 -#define CAN_IF_MCONT_EOB 0x0080 -#define CAN_IF_MCONT_DLC 0x000f -#define CAN_IF_MCONT_MSGLOST 0x4000 -#define CAN_MASK2_MDIR_MXTD 0xc000 -#define CAN_ID2_DIR 0x2000 -#define CAN_ID_MSGVAL 0x8000 - -#define CAN_STATUS_INT 0x8000 -#define CAN_IF_CREQ_BUSY 0x8000 -#define CAN_ID2_XTD 0x4000 - -#define CAN_REC 0x00007f00 -#define CAN_TEC 0x000000ff - -#define PCH_RX_OK 0x00000010 -#define PCH_TX_OK 0x00000008 -#define PCH_BUS_OFF 0x00000080 -#define PCH_EWARN 0x00000040 -#define PCH_EPASSIV 0x00000020 -#define PCH_LEC0 0x00000001 -#define PCH_LEC1 0x00000002 -#define PCH_LEC2 0x00000004 -#define PCH_LEC_ALL (PCH_LEC0 | PCH_LEC1 | PCH_LEC2) -#define PCH_STUF_ERR PCH_LEC0 -#define PCH_FORM_ERR PCH_LEC1 -#define PCH_ACK_ERR (PCH_LEC0 | PCH_LEC1) -#define PCH_BIT1_ERR PCH_LEC2 -#define PCH_BIT0_ERR (PCH_LEC0 | PCH_LEC2) -#define PCH_CRC_ERR (PCH_LEC1 | PCH_LEC2) +#define PCH_ENABLE 1 /* The enable flag */ +#define PCH_DISABLE 0 /* The disable flag */ +#define PCH_CTRL_INIT BIT(0) /* The INIT bit of CANCONT register. */ +#define PCH_CTRL_IE BIT(1) /* The IE bit of CAN control register */ +#define PCH_CTRL_IE_SIE_EIE (BIT(3) | BIT(2) | BIT(1)) +#define PCH_CTRL_CCE BIT(6) +#define PCH_CTRL_OPT BIT(7) /* The OPT bit of CANCONT register. */ +#define PCH_OPT_SILENT BIT(3) /* The Silent bit of CANOPT reg. */ +#define PCH_OPT_LBACK BIT(4) /* The LoopBack bit of CANOPT reg. */ + +#define PCH_CMASK_RX_TX_SET 0x00f3 +#define PCH_CMASK_RX_TX_GET 0x0073 +#define PCH_CMASK_ALL 0xff +#define PCH_CMASK_NEWDAT BIT(2) +#define PCH_CMASK_CLRINTPND BIT(3) +#define PCH_CMASK_CTRL BIT(4) +#define PCH_CMASK_ARB BIT(5) +#define PCH_CMASK_MASK BIT(6) +#define PCH_CMASK_RDWR BIT(7) +#define PCH_IF_MCONT_NEWDAT BIT(15) +#define PCH_IF_MCONT_MSGLOST BIT(14) +#define PCH_IF_MCONT_INTPND BIT(13) +#define PCH_IF_MCONT_UMASK BIT(12) +#define PCH_IF_MCONT_TXIE BIT(11) +#define PCH_IF_MCONT_RXIE BIT(10) +#define PCH_IF_MCONT_RMTEN BIT(9) +#define PCH_IF_MCONT_TXRQXT BIT(8) +#define PCH_IF_MCONT_EOB BIT(7) +#define PCH_IF_MCONT_DLC (BIT(0) | BIT(1) | BIT(2) | BIT(3)) +#define PCH_MASK2_MDIR_MXTD (BIT(14) | BIT(15)) +#define PCH_ID2_DIR BIT(13) +#define PCH_ID2_XTD BIT(14) +#define PCH_ID_MSGVAL BIT(15) +#define PCH_IF_CREQ_BUSY BIT(15) + +#define PCH_STATUS_INT 0x8000 +#define PCH_REC 0x00007f00 +#define PCH_TEC 0x000000ff + +#define PCH_TX_OK BIT(3) +#define PCH_RX_OK BIT(4) +#define PCH_EPASSIV BIT(5) +#define PCH_EWARN BIT(6) +#define PCH_BUS_OFF BIT(7) /* bit position of certain controller bits. */ -#define BIT_BITT_BRP 0 -#define BIT_BITT_SJW 6 -#define BIT_BITT_TSEG1 8 -#define BIT_BITT_TSEG2 12 -#define BIT_IF1_MCONT_RXIE 10 -#define BIT_IF2_MCONT_TXIE 11 -#define BIT_BRPE_BRPE 6 -#define BIT_ES_TXERRCNT 0 -#define BIT_ES_RXERRCNT 8 -#define MSK_BITT_BRP 0x3f -#define MSK_BITT_SJW 0xc0 -#define MSK_BITT_TSEG1 0xf00 -#define MSK_BITT_TSEG2 0x7000 -#define MSK_BRPE_BRPE 0x3c0 -#define MSK_BRPE_GET 0x0f -#define MSK_CTRL_IE_SIE_EIE 0x07 -#define MSK_MCONT_TXIE 0x08 -#define MSK_MCONT_RXIE 0x10 -#define PCH_CAN_NO_TX_BUFF 1 -#define COUNTER_LIMIT 10 +#define PCH_BIT_BRP 0 +#define PCH_BIT_SJW 6 +#define PCH_BIT_TSEG1 8 +#define PCH_BIT_TSEG2 12 +#define PCH_BIT_BRPE_BRPE 6 +#define PCH_MSK_BITT_BRP 0x3f +#define PCH_MSK_BRPE_BRPE 0x3c0 +#define PCH_MSK_CTRL_IE_SIE_EIE 0x07 +#define PCH_COUNTER_LIMIT 10 #define PCH_CAN_CLK 50000000 /* 50MHz */ /* Define the number of message object. * PCH CAN communications are done via Message RAM. * The Message RAM consists of 32 message objects. */ -#define PCH_RX_OBJ_NUM 26 /* 1~ PCH_RX_OBJ_NUM is Rx*/ -#define PCH_TX_OBJ_NUM 6 /* PCH_RX_OBJ_NUM is RX ~ Tx*/ -#define PCH_OBJ_NUM (PCH_TX_OBJ_NUM + PCH_RX_OBJ_NUM) +#define PCH_RX_OBJ_NUM 26 +#define PCH_TX_OBJ_NUM 6 +#define PCH_RX_OBJ_START 1 +#define PCH_RX_OBJ_END PCH_RX_OBJ_NUM +#define PCH_TX_OBJ_START (PCH_RX_OBJ_END + 1) +#define PCH_TX_OBJ_END (PCH_RX_OBJ_NUM + PCH_TX_OBJ_NUM) #define PCH_FIFO_THRESH 16 +enum pch_ifreg { + PCH_RX_IFREG, + PCH_TX_IFREG, +}; + +enum pch_can_err { + PCH_STUF_ERR = 1, + PCH_FORM_ERR, + PCH_ACK_ERR, + PCH_BIT1_ERR, + PCH_BIT0_ERR, + PCH_CRC_ERR, + PCH_LEC_ALL, +}; + enum pch_can_mode { PCH_CAN_ENABLE, PCH_CAN_DISABLE, @@ -134,6 +126,21 @@ enum pch_can_mode { PCH_CAN_RUN }; +struct pch_can_if_regs { + u32 creq; + u32 cmask; + u32 mask1; + u32 mask2; + u32 id1; + u32 id2; + u32 mcont; + u32 dataa1; + u32 dataa2; + u32 datab1; + u32 datab2; + u32 rsv[13]; +}; + struct pch_can_regs { u32 cont; u32 stat; @@ -142,38 +149,21 @@ struct pch_can_regs { u32 intr; u32 opt; u32 brpe; - u32 reserve1; - u32 if1_creq; - u32 if1_cmask; - u32 if1_mask1; - u32 if1_mask2; - u32 if1_id1; - u32 if1_id2; - u32 if1_mcont; - u32 if1_dataa1; - u32 if1_dataa2; - u32 if1_datab1; - u32 if1_datab2; - u32 reserve2; - u32 reserve3[12]; - u32 if2_creq; - u32 if2_cmask; - u32 if2_mask1; - u32 if2_mask2; - u32 if2_id1; - u32 if2_id2; - u32 if2_mcont; - u32 if2_dataa1; - u32 if2_dataa2; - u32 if2_datab1; - u32 if2_datab2; - u32 reserve4; - u32 reserve5[20]; + u32 reserve; + struct pch_can_if_regs ifregs[2]; /* [0]=if1 [1]=if2 */ + u32 reserve1[8]; u32 treq1; u32 treq2; - u32 reserve6[2]; - u32 reserve7[56]; - u32 reserve8[3]; + u32 reserve2[6]; + u32 data1; + u32 data2; + u32 reserve3[6]; + u32 canipend1; + u32 canipend2; + u32 reserve4[6]; + u32 canmval1; + u32 canmval2; + u32 reserve5[37]; u32 srst; }; @@ -181,14 +171,13 @@ struct pch_can_priv { struct can_priv can; unsigned int can_num; struct pci_dev *dev; - unsigned int tx_enable[MAX_MSG_OBJ]; - unsigned int rx_enable[MAX_MSG_OBJ]; - unsigned int rx_link[MAX_MSG_OBJ]; + int tx_enable[PCH_TX_OBJ_END]; + int rx_enable[PCH_TX_OBJ_END]; + int rx_link[PCH_TX_OBJ_END]; unsigned int int_enables; unsigned int int_stat; struct net_device *ndev; - spinlock_t msgif_reg_lock; /* Message Interface Registers Access Lock*/ - unsigned int msg_obj[MAX_MSG_OBJ]; + unsigned int msg_obj[PCH_TX_OBJ_END]; struct pch_can_regs __iomem *regs; struct napi_struct napi; unsigned int tx_obj; /* Point next Tx Obj index */ @@ -228,11 +217,11 @@ static void pch_can_set_run_mode(struct pch_can_priv *priv, { switch (mode) { case PCH_CAN_RUN: - pch_can_bit_clear(&priv->regs->cont, CAN_CTRL_INIT); + pch_can_bit_clear(&priv->regs->cont, PCH_CTRL_INIT); break; case PCH_CAN_STOP: - pch_can_bit_set(&priv->regs->cont, CAN_CTRL_INIT); + pch_can_bit_set(&priv->regs->cont, PCH_CTRL_INIT); break; default: @@ -246,30 +235,30 @@ static void pch_can_set_optmode(struct pch_can_priv *priv) u32 reg_val = ioread32(&priv->regs->opt); if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) - reg_val |= CAN_OPT_SILENT; + reg_val |= PCH_OPT_SILENT; if (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK) - reg_val |= CAN_OPT_LBACK; + reg_val |= PCH_OPT_LBACK; - pch_can_bit_set(&priv->regs->cont, CAN_CTRL_OPT); + pch_can_bit_set(&priv->regs->cont, PCH_CTRL_OPT); iowrite32(reg_val, &priv->regs->opt); } static void pch_can_set_int_custom(struct pch_can_priv *priv) { /* Clearing the IE, SIE and EIE bits of Can control register. */ - pch_can_bit_clear(&priv->regs->cont, CAN_CTRL_IE_SIE_EIE); + pch_can_bit_clear(&priv->regs->cont, PCH_CTRL_IE_SIE_EIE); /* Appropriately setting them. */ pch_can_bit_set(&priv->regs->cont, - ((priv->int_enables & MSK_CTRL_IE_SIE_EIE) << 1)); + ((priv->int_enables & PCH_MSK_CTRL_IE_SIE_EIE) << 1)); } /* This function retrieves interrupt enabled for the CAN device. */ static void pch_can_get_int_enables(struct pch_can_priv *priv, u32 *enables) { /* Obtaining the status of IE, SIE and EIE interrupt bits. */ - *enables = ((ioread32(&priv->regs->cont) & CAN_CTRL_IE_SIE_EIE) >> 1); + *enables = ((ioread32(&priv->regs->cont) & PCH_CTRL_IE_SIE_EIE) >> 1); } static void pch_can_set_int_enables(struct pch_can_priv *priv, @@ -277,19 +266,19 @@ static void pch_can_set_int_enables(struct pch_can_priv *priv, { switch (interrupt_no) { case PCH_CAN_ENABLE: - pch_can_bit_set(&priv->regs->cont, CAN_CTRL_IE); + pch_can_bit_set(&priv->regs->cont, PCH_CTRL_IE); break; case PCH_CAN_DISABLE: - pch_can_bit_clear(&priv->regs->cont, CAN_CTRL_IE); + pch_can_bit_clear(&priv->regs->cont, PCH_CTRL_IE); break; case PCH_CAN_ALL: - pch_can_bit_set(&priv->regs->cont, CAN_CTRL_IE_SIE_EIE); + pch_can_bit_set(&priv->regs->cont, PCH_CTRL_IE_SIE_EIE); break; case PCH_CAN_NONE: - pch_can_bit_clear(&priv->regs->cont, CAN_CTRL_IE_SIE_EIE); + pch_can_bit_clear(&priv->regs->cont, PCH_CTRL_IE_SIE_EIE); break; default: @@ -300,12 +289,12 @@ static void pch_can_set_int_enables(struct pch_can_priv *priv, static void pch_can_check_if_busy(u32 __iomem *creq_addr, u32 num) { - u32 counter = COUNTER_LIMIT; + u32 counter = PCH_COUNTER_LIMIT; u32 ifx_creq; iowrite32(num, creq_addr); while (counter) { - ifx_creq = ioread32(creq_addr) & CAN_IF_CREQ_BUSY; + ifx_creq = ioread32(creq_addr) & PCH_IF_CREQ_BUSY; if (!ifx_creq) break; counter--; @@ -315,143 +304,76 @@ static void pch_can_check_if_busy(u32 __iomem *creq_addr, u32 num) pr_err("%s:IF1 BUSY Flag is set forever.\n", __func__); } -static void pch_can_set_rx_enable(struct pch_can_priv *priv, u32 buff_num, - u32 set) +static void pch_can_set_rxtx(struct pch_can_priv *priv, u32 buff_num, + u32 set, enum pch_ifreg dir) { - unsigned long flags; + u32 ie; + + if (dir) + ie = PCH_IF_MCONT_TXIE; + else + ie = PCH_IF_MCONT_RXIE; - spin_lock_irqsave(&priv->msgif_reg_lock, flags); /* Reading the receive buffer data from RAM to Interface1 registers */ - iowrite32(CAN_CMASK_RX_TX_GET, &priv->regs->if1_cmask); - pch_can_check_if_busy(&priv->regs->if1_creq, buff_num); + iowrite32(PCH_CMASK_RX_TX_GET, &priv->regs->ifregs[dir].cmask); + pch_can_check_if_busy(&priv->regs->ifregs[dir].creq, buff_num); /* Setting the IF1MASK1 register to access MsgVal and RxIE bits */ - iowrite32(CAN_CMASK_RDWR | CAN_CMASK_ARB | CAN_CMASK_CTRL, - &priv->regs->if1_cmask); + iowrite32(PCH_CMASK_RDWR | PCH_CMASK_ARB | PCH_CMASK_CTRL, + &priv->regs->ifregs[dir].cmask); - if (set == ENABLE) { + if (set == PCH_ENABLE) { /* Setting the MsgVal and RxIE bits */ - pch_can_bit_set(&priv->regs->if1_mcont, CAN_IF_MCONT_RXIE); - pch_can_bit_set(&priv->regs->if1_id2, CAN_ID_MSGVAL); + pch_can_bit_set(&priv->regs->ifregs[dir].mcont, ie); + pch_can_bit_set(&priv->regs->ifregs[dir].id2, PCH_ID_MSGVAL); - } else if (set == DISABLE) { + } else if (set == PCH_DISABLE) { /* Resetting the MsgVal and RxIE bits */ - pch_can_bit_clear(&priv->regs->if1_mcont, CAN_IF_MCONT_RXIE); - pch_can_bit_clear(&priv->regs->if1_id2, CAN_ID_MSGVAL); + pch_can_bit_clear(&priv->regs->ifregs[dir].mcont, ie); + pch_can_bit_clear(&priv->regs->ifregs[dir].id2, PCH_ID_MSGVAL); } - pch_can_check_if_busy(&priv->regs->if1_creq, buff_num); - spin_unlock_irqrestore(&priv->msgif_reg_lock, flags); + pch_can_check_if_busy(&priv->regs->ifregs[dir].creq, buff_num); } -static void pch_can_rx_enable_all(struct pch_can_priv *priv) +static void pch_can_set_rx_all(struct pch_can_priv *priv, u32 set) { int i; /* Traversing to obtain the object configured as receivers. */ - for (i = 0; i < PCH_OBJ_NUM; i++) { - if (priv->msg_obj[i] == MSG_OBJ_RX) - pch_can_set_rx_enable(priv, i + 1, ENABLE); - } -} - -static void pch_can_rx_disable_all(struct pch_can_priv *priv) -{ - int i; - - /* Traversing to obtain the object configured as receivers. */ - for (i = 0; i < PCH_OBJ_NUM; i++) { - if (priv->msg_obj[i] == MSG_OBJ_RX) - pch_can_set_rx_enable(priv, i + 1, DISABLE); - } -} - -static void pch_can_set_tx_enable(struct pch_can_priv *priv, u32 buff_num, - u32 set) -{ - unsigned long flags; - - spin_lock_irqsave(&priv->msgif_reg_lock, flags); - /* Reading the Msg buffer from Message RAM to Interface2 registers. */ - iowrite32(CAN_CMASK_RX_TX_GET, &priv->regs->if2_cmask); - pch_can_check_if_busy(&priv->regs->if2_creq, buff_num); - - /* Setting the IF2CMASK register for accessing the - MsgVal and TxIE bits */ - iowrite32(CAN_CMASK_RDWR | CAN_CMASK_ARB | CAN_CMASK_CTRL, - &priv->regs->if2_cmask); - - if (set == ENABLE) { - /* Setting the MsgVal and TxIE bits */ - pch_can_bit_set(&priv->regs->if2_mcont, CAN_IF_MCONT_TXIE); - pch_can_bit_set(&priv->regs->if2_id2, CAN_ID_MSGVAL); - } else if (set == DISABLE) { - /* Resetting the MsgVal and TxIE bits. */ - pch_can_bit_clear(&priv->regs->if2_mcont, CAN_IF_MCONT_TXIE); - pch_can_bit_clear(&priv->regs->if2_id2, CAN_ID_MSGVAL); - } - - pch_can_check_if_busy(&priv->regs->if2_creq, buff_num); - spin_unlock_irqrestore(&priv->msgif_reg_lock, flags); + for (i = PCH_RX_OBJ_START; i <= PCH_RX_OBJ_END; i++) + pch_can_set_rxtx(priv, i, set, PCH_RX_IFREG); } -static void pch_can_tx_enable_all(struct pch_can_priv *priv) +static void pch_can_set_tx_all(struct pch_can_priv *priv, u32 set) { int i; /* Traversing to obtain the object configured as transmit object. */ - for (i = 0; i < PCH_OBJ_NUM; i++) { - if (priv->msg_obj[i] == MSG_OBJ_TX) - pch_can_set_tx_enable(priv, i + 1, ENABLE); - } -} - -static void pch_can_tx_disable_all(struct pch_can_priv *priv) -{ - int i; - - /* Traversing to obtain the object configured as transmit object. */ - for (i = 0; i < PCH_OBJ_NUM; i++) { - if (priv->msg_obj[i] == MSG_OBJ_TX) - pch_can_set_tx_enable(priv, i + 1, DISABLE); - } + for (i = PCH_TX_OBJ_START; i <= PCH_TX_OBJ_END; i++) + pch_can_set_rxtx(priv, i, set, PCH_TX_IFREG); } -static void pch_can_get_rx_enable(struct pch_can_priv *priv, u32 buff_num, - u32 *enable) +static u32 pch_can_get_rxtx_ir(struct pch_can_priv *priv, u32 buff_num, + enum pch_ifreg dir) { - unsigned long flags; + u32 ie, enable; - spin_lock_irqsave(&priv->msgif_reg_lock, flags); - iowrite32(CAN_CMASK_RX_TX_GET, &priv->regs->if1_cmask); - pch_can_check_if_busy(&priv->regs->if1_creq, buff_num); - - if (((ioread32(&priv->regs->if1_id2)) & CAN_ID_MSGVAL) && - ((ioread32(&priv->regs->if1_mcont)) & - CAN_IF_MCONT_RXIE)) - *enable = ENABLE; + if (dir) + ie = PCH_IF_MCONT_RXIE; else - *enable = DISABLE; - spin_unlock_irqrestore(&priv->msgif_reg_lock, flags); -} + ie = PCH_IF_MCONT_TXIE; -static void pch_can_get_tx_enable(struct pch_can_priv *priv, u32 buff_num, - u32 *enable) -{ - unsigned long flags; - - spin_lock_irqsave(&priv->msgif_reg_lock, flags); - iowrite32(CAN_CMASK_RX_TX_GET, &priv->regs->if2_cmask); - pch_can_check_if_busy(&priv->regs->if2_creq, buff_num); + iowrite32(PCH_CMASK_RX_TX_GET, &priv->regs->ifregs[dir].cmask); + pch_can_check_if_busy(&priv->regs->ifregs[dir].creq, buff_num); - if (((ioread32(&priv->regs->if2_id2)) & CAN_ID_MSGVAL) && - ((ioread32(&priv->regs->if2_mcont)) & - CAN_IF_MCONT_TXIE)) { - *enable = ENABLE; + if (((ioread32(&priv->regs->ifregs[dir].id2)) & PCH_ID_MSGVAL) && + ((ioread32(&priv->regs->ifregs[dir].mcont)) & ie)) { + enable = 1; } else { - *enable = DISABLE; + enable = 0; } - spin_unlock_irqrestore(&priv->msgif_reg_lock, flags); + return enable; } static int pch_can_int_pending(struct pch_can_priv *priv) @@ -462,141 +384,131 @@ static int pch_can_int_pending(struct pch_can_priv *priv) static void pch_can_set_rx_buffer_link(struct pch_can_priv *priv, u32 buffer_num, u32 set) { - unsigned long flags; - - spin_lock_irqsave(&priv->msgif_reg_lock, flags); - iowrite32(CAN_CMASK_RX_TX_GET, &priv->regs->if1_cmask); - pch_can_check_if_busy(&priv->regs->if1_creq, buffer_num); - iowrite32(CAN_CMASK_RDWR | CAN_CMASK_CTRL, &priv->regs->if1_cmask); - if (set == ENABLE) - pch_can_bit_clear(&priv->regs->if1_mcont, CAN_IF_MCONT_EOB); + iowrite32(PCH_CMASK_RX_TX_GET, &priv->regs->ifregs[0].cmask); + pch_can_check_if_busy(&priv->regs->ifregs[0].creq, buffer_num); + iowrite32(PCH_CMASK_RDWR | PCH_CMASK_CTRL, + &priv->regs->ifregs[0].cmask); + if (set == PCH_ENABLE) + pch_can_bit_clear(&priv->regs->ifregs[0].mcont, + PCH_IF_MCONT_EOB); else - pch_can_bit_set(&priv->regs->if1_mcont, CAN_IF_MCONT_EOB); + pch_can_bit_set(&priv->regs->ifregs[0].mcont, PCH_IF_MCONT_EOB); - pch_can_check_if_busy(&priv->regs->if1_creq, buffer_num); - spin_unlock_irqrestore(&priv->msgif_reg_lock, flags); + pch_can_check_if_busy(&priv->regs->ifregs[0].creq, buffer_num); } static void pch_can_get_rx_buffer_link(struct pch_can_priv *priv, u32 buffer_num, u32 *link) { - unsigned long flags; - - spin_lock_irqsave(&priv->msgif_reg_lock, flags); - iowrite32(CAN_CMASK_RX_TX_GET, &priv->regs->if1_cmask); - pch_can_check_if_busy(&priv->regs->if1_creq, buffer_num); + iowrite32(PCH_CMASK_RX_TX_GET, &priv->regs->ifregs[0].cmask); + pch_can_check_if_busy(&priv->regs->ifregs[0].creq, buffer_num); - if (ioread32(&priv->regs->if1_mcont) & CAN_IF_MCONT_EOB) - *link = DISABLE; + if (ioread32(&priv->regs->ifregs[0].mcont) & PCH_IF_MCONT_EOB) + *link = PCH_DISABLE; else - *link = ENABLE; - spin_unlock_irqrestore(&priv->msgif_reg_lock, flags); + *link = PCH_ENABLE; } static void pch_can_clear_buffers(struct pch_can_priv *priv) { int i; - for (i = 0; i < PCH_RX_OBJ_NUM; i++) { - iowrite32(CAN_CMASK_RX_TX_SET, &priv->regs->if1_cmask); - iowrite32(0xffff, &priv->regs->if1_mask1); - iowrite32(0xffff, &priv->regs->if1_mask2); - iowrite32(0x0, &priv->regs->if1_id1); - iowrite32(0x0, &priv->regs->if1_id2); - iowrite32(0x0, &priv->regs->if1_mcont); - iowrite32(0x0, &priv->regs->if1_dataa1); - iowrite32(0x0, &priv->regs->if1_dataa2); - iowrite32(0x0, &priv->regs->if1_datab1); - iowrite32(0x0, &priv->regs->if1_datab2); - iowrite32(CAN_CMASK_RDWR | CAN_CMASK_MASK | - CAN_CMASK_ARB | CAN_CMASK_CTRL, - &priv->regs->if1_cmask); - pch_can_check_if_busy(&priv->regs->if1_creq, i+1); + for (i = PCH_RX_OBJ_START; i <= PCH_RX_OBJ_END; i++) { + iowrite32(PCH_CMASK_RX_TX_SET, &priv->regs->ifregs[0].cmask); + iowrite32(0xffff, &priv->regs->ifregs[0].mask1); + iowrite32(0xffff, &priv->regs->ifregs[0].mask2); + iowrite32(0x0, &priv->regs->ifregs[0].id1); + iowrite32(0x0, &priv->regs->ifregs[0].id2); + iowrite32(0x0, &priv->regs->ifregs[0].mcont); + iowrite32(0x0, &priv->regs->ifregs[0].dataa1); + iowrite32(0x0, &priv->regs->ifregs[0].dataa2); + iowrite32(0x0, &priv->regs->ifregs[0].datab1); + iowrite32(0x0, &priv->regs->ifregs[0].datab2); + iowrite32(PCH_CMASK_RDWR | PCH_CMASK_MASK | + PCH_CMASK_ARB | PCH_CMASK_CTRL, + &priv->regs->ifregs[0].cmask); + pch_can_check_if_busy(&priv->regs->ifregs[0].creq, i); } - for (i = i; i < PCH_OBJ_NUM; i++) { - iowrite32(CAN_CMASK_RX_TX_SET, &priv->regs->if2_cmask); - iowrite32(0xffff, &priv->regs->if2_mask1); - iowrite32(0xffff, &priv->regs->if2_mask2); - iowrite32(0x0, &priv->regs->if2_id1); - iowrite32(0x0, &priv->regs->if2_id2); - iowrite32(0x0, &priv->regs->if2_mcont); - iowrite32(0x0, &priv->regs->if2_dataa1); - iowrite32(0x0, &priv->regs->if2_dataa2); - iowrite32(0x0, &priv->regs->if2_datab1); - iowrite32(0x0, &priv->regs->if2_datab2); - iowrite32(CAN_CMASK_RDWR | CAN_CMASK_MASK | - CAN_CMASK_ARB | CAN_CMASK_CTRL, - &priv->regs->if2_cmask); - pch_can_check_if_busy(&priv->regs->if2_creq, i+1); + for (i = PCH_TX_OBJ_START; i <= PCH_TX_OBJ_END; i++) { + iowrite32(PCH_CMASK_RX_TX_SET, &priv->regs->ifregs[1].cmask); + iowrite32(0xffff, &priv->regs->ifregs[1].mask1); + iowrite32(0xffff, &priv->regs->ifregs[1].mask2); + iowrite32(0x0, &priv->regs->ifregs[1].id1); + iowrite32(0x0, &priv->regs->ifregs[1].id2); + iowrite32(0x0, &priv->regs->ifregs[1].mcont); + iowrite32(0x0, &priv->regs->ifregs[1].dataa1); + iowrite32(0x0, &priv->regs->ifregs[1].dataa2); + iowrite32(0x0, &priv->regs->ifregs[1].datab1); + iowrite32(0x0, &priv->regs->ifregs[1].datab2); + iowrite32(PCH_CMASK_RDWR | PCH_CMASK_MASK | + PCH_CMASK_ARB | PCH_CMASK_CTRL, + &priv->regs->ifregs[1].cmask); + pch_can_check_if_busy(&priv->regs->ifregs[1].creq, i); } } static void pch_can_config_rx_tx_buffers(struct pch_can_priv *priv) { int i; - unsigned long flags; - spin_lock_irqsave(&priv->msgif_reg_lock, flags); + for (i = PCH_RX_OBJ_START; i <= PCH_RX_OBJ_END; i++) { + iowrite32(PCH_CMASK_RX_TX_GET, + &priv->regs->ifregs[0].cmask); + pch_can_check_if_busy(&priv->regs->ifregs[0].creq, i); - for (i = 0; i < PCH_OBJ_NUM; i++) { - if (priv->msg_obj[i] == MSG_OBJ_RX) { - iowrite32(CAN_CMASK_RX_TX_GET, - &priv->regs->if1_cmask); - pch_can_check_if_busy(&priv->regs->if1_creq, i+1); + iowrite32(0x0, &priv->regs->ifregs[0].id1); + iowrite32(0x0, &priv->regs->ifregs[0].id2); - iowrite32(0x0, &priv->regs->if1_id1); - iowrite32(0x0, &priv->regs->if1_id2); + pch_can_bit_set(&priv->regs->ifregs[0].mcont, + PCH_IF_MCONT_UMASK); - pch_can_bit_set(&priv->regs->if1_mcont, - CAN_IF_MCONT_UMASK); + /* Set FIFO mode set to 0 except last Rx Obj*/ + pch_can_bit_clear(&priv->regs->ifregs[0].mcont, + PCH_IF_MCONT_EOB); + /* In case FIFO mode, Last EoB of Rx Obj must be 1 */ + if (i == PCH_RX_OBJ_END) + pch_can_bit_set(&priv->regs->ifregs[0].mcont, + PCH_IF_MCONT_EOB); - /* Set FIFO mode set to 0 except last Rx Obj*/ - pch_can_bit_clear(&priv->regs->if1_mcont, - CAN_IF_MCONT_EOB); - /* In case FIFO mode, Last EoB of Rx Obj must be 1 */ - if (i == (PCH_RX_OBJ_NUM - 1)) - pch_can_bit_set(&priv->regs->if1_mcont, - CAN_IF_MCONT_EOB); + iowrite32(0, &priv->regs->ifregs[0].mask1); + pch_can_bit_clear(&priv->regs->ifregs[0].mask2, + 0x1fff | PCH_MASK2_MDIR_MXTD); - iowrite32(0, &priv->regs->if1_mask1); - pch_can_bit_clear(&priv->regs->if1_mask2, - 0x1fff | CAN_MASK2_MDIR_MXTD); + /* Setting CMASK for writing */ + iowrite32(PCH_CMASK_RDWR | PCH_CMASK_MASK | + PCH_CMASK_ARB | PCH_CMASK_CTRL, + &priv->regs->ifregs[0].cmask); - /* Setting CMASK for writing */ - iowrite32(CAN_CMASK_RDWR | CAN_CMASK_MASK | - CAN_CMASK_ARB | CAN_CMASK_CTRL, - &priv->regs->if1_cmask); + pch_can_check_if_busy(&priv->regs->ifregs[0].creq, i); + } - pch_can_check_if_busy(&priv->regs->if1_creq, i+1); - } else if (priv->msg_obj[i] == MSG_OBJ_TX) { - iowrite32(CAN_CMASK_RX_TX_GET, - &priv->regs->if2_cmask); - pch_can_check_if_busy(&priv->regs->if2_creq, i+1); + for (i = PCH_TX_OBJ_START; i <= PCH_TX_OBJ_END; i++) { + iowrite32(PCH_CMASK_RX_TX_GET, + &priv->regs->ifregs[1].cmask); + pch_can_check_if_busy(&priv->regs->ifregs[1].creq, i); - /* Resetting DIR bit for reception */ - iowrite32(0x0, &priv->regs->if2_id1); - iowrite32(0x0, &priv->regs->if2_id2); - pch_can_bit_set(&priv->regs->if2_id2, CAN_ID2_DIR); + /* Resetting DIR bit for reception */ + iowrite32(0x0, &priv->regs->ifregs[1].id1); + iowrite32(0x0, &priv->regs->ifregs[1].id2); + pch_can_bit_set(&priv->regs->ifregs[1].id2, PCH_ID2_DIR); - /* Setting EOB bit for transmitter */ - iowrite32(CAN_IF_MCONT_EOB, &priv->regs->if2_mcont); + /* Setting EOB bit for transmitter */ + iowrite32(PCH_IF_MCONT_EOB, &priv->regs->ifregs[1].mcont); - pch_can_bit_set(&priv->regs->if2_mcont, - CAN_IF_MCONT_UMASK); + pch_can_bit_set(&priv->regs->ifregs[1].mcont, + PCH_IF_MCONT_UMASK); - iowrite32(0, &priv->regs->if2_mask1); - pch_can_bit_clear(&priv->regs->if2_mask2, 0x1fff); + iowrite32(0, &priv->regs->ifregs[1].mask1); + pch_can_bit_clear(&priv->regs->ifregs[1].mask2, 0x1fff); - /* Setting CMASK for writing */ - iowrite32(CAN_CMASK_RDWR | CAN_CMASK_MASK | - CAN_CMASK_ARB | CAN_CMASK_CTRL, - &priv->regs->if2_cmask); + /* Setting CMASK for writing */ + iowrite32(PCH_CMASK_RDWR | PCH_CMASK_MASK | + PCH_CMASK_ARB | PCH_CMASK_CTRL, + &priv->regs->ifregs[1].cmask); - pch_can_check_if_busy(&priv->regs->if2_creq, i+1); - } + pch_can_check_if_busy(&priv->regs->ifregs[1].creq, i); } - spin_unlock_irqrestore(&priv->msgif_reg_lock, flags); } static void pch_can_init(struct pch_can_priv *priv) @@ -623,50 +535,50 @@ static void pch_can_release(struct pch_can_priv *priv) pch_can_set_int_enables(priv, PCH_CAN_NONE); /* Disabling all the receive object. */ - pch_can_rx_disable_all(priv); + pch_can_set_rx_all(priv, 0); /* Disabling all the transmit object. */ - pch_can_tx_disable_all(priv); + pch_can_set_tx_all(priv, 0); } /* This function clears interrupt(s) from the CAN device. */ static void pch_can_int_clr(struct pch_can_priv *priv, u32 mask) { - if (mask == CAN_STATUS_INT) { + if (mask == PCH_STATUS_INT) { ioread32(&priv->regs->stat); return; } /* Clear interrupt for transmit object */ - if (priv->msg_obj[mask - 1] == MSG_OBJ_TX) { - /* Setting CMASK for clearing interrupts for - frame transmission. */ - iowrite32(CAN_CMASK_RDWR | CAN_CMASK_CTRL | CAN_CMASK_ARB, - &priv->regs->if2_cmask); - - /* Resetting the ID registers. */ - pch_can_bit_set(&priv->regs->if2_id2, - CAN_ID2_DIR | (0x7ff << 2)); - iowrite32(0x0, &priv->regs->if2_id1); - - /* Claring NewDat, TxRqst & IntPnd */ - pch_can_bit_clear(&priv->regs->if2_mcont, - CAN_IF_MCONT_NEWDAT | CAN_IF_MCONT_INTPND | - CAN_IF_MCONT_TXRQXT); - pch_can_check_if_busy(&priv->regs->if2_creq, mask); - } else if (priv->msg_obj[mask - 1] == MSG_OBJ_RX) { + if ((mask >= PCH_RX_OBJ_START) && (mask <= PCH_RX_OBJ_END)) { /* Setting CMASK for clearing the reception interrupts. */ - iowrite32(CAN_CMASK_RDWR | CAN_CMASK_CTRL | CAN_CMASK_ARB, - &priv->regs->if1_cmask); + iowrite32(PCH_CMASK_RDWR | PCH_CMASK_CTRL | PCH_CMASK_ARB, + &priv->regs->ifregs[0].cmask); /* Clearing the Dir bit. */ - pch_can_bit_clear(&priv->regs->if1_id2, CAN_ID2_DIR); + pch_can_bit_clear(&priv->regs->ifregs[0].id2, PCH_ID2_DIR); /* Clearing NewDat & IntPnd */ - pch_can_bit_clear(&priv->regs->if1_mcont, - CAN_IF_MCONT_NEWDAT | CAN_IF_MCONT_INTPND); + pch_can_bit_clear(&priv->regs->ifregs[0].mcont, + PCH_IF_MCONT_NEWDAT | PCH_IF_MCONT_INTPND); + + pch_can_check_if_busy(&priv->regs->ifregs[0].creq, mask); + } else if ((mask >= PCH_TX_OBJ_START) && (mask <= PCH_TX_OBJ_END)) { + /* Setting CMASK for clearing interrupts for + frame transmission. */ + iowrite32(PCH_CMASK_RDWR | PCH_CMASK_CTRL | PCH_CMASK_ARB, + &priv->regs->ifregs[1].cmask); + + /* Resetting the ID registers. */ + pch_can_bit_set(&priv->regs->ifregs[1].id2, + PCH_ID2_DIR | (0x7ff << 2)); + iowrite32(0x0, &priv->regs->ifregs[1].id1); - pch_can_check_if_busy(&priv->regs->if1_creq, mask); + /* Claring NewDat, TxRqst & IntPnd */ + pch_can_bit_clear(&priv->regs->ifregs[1].mcont, + PCH_IF_MCONT_NEWDAT | PCH_IF_MCONT_INTPND | + PCH_IF_MCONT_TXRQXT); + pch_can_check_if_busy(&priv->regs->ifregs[1].creq, mask); } } @@ -688,7 +600,7 @@ static void pch_can_error(struct net_device *ndev, u32 status) struct sk_buff *skb; struct pch_can_priv *priv = netdev_priv(ndev); struct can_frame *cf; - u32 errc; + u32 errc, lec; struct net_device_stats *stats = &(priv->ndev->stats); enum can_state state = priv->can.state; @@ -697,8 +609,8 @@ static void pch_can_error(struct net_device *ndev, u32 status) return; if (status & PCH_BUS_OFF) { - pch_can_tx_disable_all(priv); - pch_can_rx_disable_all(priv); + pch_can_set_tx_all(priv, 0); + pch_can_set_rx_all(priv, 0); state = CAN_STATE_BUS_OFF; cf->can_id |= CAN_ERR_BUSOFF; can_bus_off(ndev); @@ -712,9 +624,9 @@ static void pch_can_error(struct net_device *ndev, u32 status) priv->can.can_stats.error_warning++; cf->can_id |= CAN_ERR_CRTL; errc = ioread32(&priv->regs->errc); - if (((errc & CAN_REC) >> 8) > 96) + if (((errc & PCH_REC) >> 8) > 96) cf->data[1] |= CAN_ERR_CRTL_RX_WARNING; - if ((errc & CAN_TEC) > 96) + if ((errc & PCH_TEC) > 96) cf->data[1] |= CAN_ERR_CRTL_TX_WARNING; dev_warn(&ndev->dev, "%s -> Error Counter is more than 96.\n", __func__); @@ -725,41 +637,45 @@ static void pch_can_error(struct net_device *ndev, u32 status) state = CAN_STATE_ERROR_PASSIVE; cf->can_id |= CAN_ERR_CRTL; errc = ioread32(&priv->regs->errc); - if (((errc & CAN_REC) >> 8) > 127) + if (((errc & PCH_REC) >> 8) > 127) cf->data[1] |= CAN_ERR_CRTL_RX_PASSIVE; - if ((errc & CAN_TEC) > 127) + if ((errc & PCH_TEC) > 127) cf->data[1] |= CAN_ERR_CRTL_TX_PASSIVE; dev_err(&ndev->dev, "%s -> CAN controller is ERROR PASSIVE .\n", __func__); } - if (status & PCH_LEC_ALL) { + lec = status & PCH_LEC_ALL; + switch (lec) { + case PCH_STUF_ERR: + cf->data[2] |= CAN_ERR_PROT_STUFF; priv->can.can_stats.bus_error++; stats->rx_errors++; - switch (status & PCH_LEC_ALL) { - case PCH_STUF_ERR: - cf->data[2] |= CAN_ERR_PROT_STUFF; - break; - case PCH_FORM_ERR: - cf->data[2] |= CAN_ERR_PROT_FORM; - break; - case PCH_ACK_ERR: - cf->data[2] |= CAN_ERR_PROT_LOC_ACK | - CAN_ERR_PROT_LOC_ACK_DEL; - break; - case PCH_BIT1_ERR: - case PCH_BIT0_ERR: - cf->data[2] |= CAN_ERR_PROT_BIT; - break; - case PCH_CRC_ERR: - cf->data[2] |= CAN_ERR_PROT_LOC_CRC_SEQ | - CAN_ERR_PROT_LOC_CRC_DEL; - break; - default: - iowrite32(status | PCH_LEC_ALL, &priv->regs->stat); - break; - } - + break; + case PCH_FORM_ERR: + cf->data[2] |= CAN_ERR_PROT_FORM; + priv->can.can_stats.bus_error++; + stats->rx_errors++; + break; + case PCH_ACK_ERR: + cf->can_id |= CAN_ERR_ACK; + priv->can.can_stats.bus_error++; + stats->rx_errors++; + break; + case PCH_BIT1_ERR: + case PCH_BIT0_ERR: + cf->data[2] |= CAN_ERR_PROT_BIT; + priv->can.can_stats.bus_error++; + stats->rx_errors++; + break; + case PCH_CRC_ERR: + cf->data[2] |= CAN_ERR_PROT_LOC_CRC_SEQ | + CAN_ERR_PROT_LOC_CRC_DEL; + priv->can.can_stats.bus_error++; + stats->rx_errors++; + break; + case PCH_LEC_ALL: /* Written by CPU. No error status */ + break; } priv->can.state = state; @@ -795,22 +711,22 @@ static int pch_can_rx_normal(struct net_device *ndev, u32 int_stat) struct net_device_stats *stats = &(priv->ndev->stats); /* Reading the messsage object from the Message RAM */ - iowrite32(CAN_CMASK_RX_TX_GET, &priv->regs->if1_cmask); - pch_can_check_if_busy(&priv->regs->if1_creq, int_stat); + iowrite32(PCH_CMASK_RX_TX_GET, &priv->regs->ifregs[0].cmask); + pch_can_check_if_busy(&priv->regs->ifregs[0].creq, int_stat); /* Reading the MCONT register. */ - reg = ioread32(&priv->regs->if1_mcont); + reg = ioread32(&priv->regs->ifregs[0].mcont); reg &= 0xffff; - for (k = int_stat; !(reg & CAN_IF_MCONT_EOB); k++) { + for (k = int_stat; !(reg & PCH_IF_MCONT_EOB); k++) { /* If MsgLost bit set. */ - if (reg & CAN_IF_MCONT_MSGLOST) { + if (reg & PCH_IF_MCONT_MSGLOST) { dev_err(&priv->ndev->dev, "Msg Obj is overwritten.\n"); - pch_can_bit_clear(&priv->regs->if1_mcont, - CAN_IF_MCONT_MSGLOST); - iowrite32(CAN_CMASK_RDWR | CAN_CMASK_CTRL, - &priv->regs->if1_cmask); - pch_can_check_if_busy(&priv->regs->if1_creq, k); + pch_can_bit_clear(&priv->regs->ifregs[0].mcont, + PCH_IF_MCONT_MSGLOST); + iowrite32(PCH_CMASK_RDWR | PCH_CMASK_CTRL, + &priv->regs->ifregs[0].cmask); + pch_can_check_if_busy(&priv->regs->ifregs[0].creq, k); skb = alloc_can_err_skb(ndev, &cf); if (!skb) @@ -828,7 +744,7 @@ static int pch_can_rx_normal(struct net_device *ndev, u32 int_stat) rcv_pkts++; goto RX_NEXT; } - if (!(reg & CAN_IF_MCONT_NEWDAT)) + if (!(reg & PCH_IF_MCONT_NEWDAT)) goto RX_NEXT; skb = alloc_can_skb(priv->ndev, &cf); @@ -836,29 +752,30 @@ static int pch_can_rx_normal(struct net_device *ndev, u32 int_stat) return -ENOMEM; /* Get Received data */ - ide = ((ioread32(&priv->regs->if1_id2)) & CAN_ID2_XTD) >> 14; + ide = ((ioread32(&priv->regs->ifregs[0].id2)) & PCH_ID2_XTD) >> + 14; if (ide) { - id = (ioread32(&priv->regs->if1_id1) & 0xffff); - id |= (((ioread32(&priv->regs->if1_id2)) & + id = (ioread32(&priv->regs->ifregs[0].id1) & 0xffff); + id |= (((ioread32(&priv->regs->ifregs[0].id2)) & 0x1fff) << 16); cf->can_id = (id & CAN_EFF_MASK) | CAN_EFF_FLAG; } else { - id = (((ioread32(&priv->regs->if1_id2)) & - (CAN_SFF_MASK << 2)) >> 2); + id = (((ioread32(&priv->regs->ifregs[0].id2)) & + (CAN_SFF_MASK << 2)) >> 2); cf->can_id = (id & CAN_SFF_MASK); } - rtr = (ioread32(&priv->regs->if1_id2) & CAN_ID2_DIR); + rtr = (ioread32(&priv->regs->ifregs[0].id2) & PCH_ID2_DIR); if (rtr) { cf->can_dlc = 0; cf->can_id |= CAN_RTR_FLAG; } else { - cf->can_dlc = ((ioread32(&priv->regs->if1_mcont)) & - 0x0f); + cf->can_dlc = + ((ioread32(&priv->regs->ifregs[0].mcont)) & 0x0f); } for (i = 0, j = 0; i < cf->can_dlc; j++) { - reg = ioread32(&priv->regs->if1_dataa1 + j*4); + reg = ioread32(&priv->regs->ifregs[0].dataa1 + j*4); cf->data[i++] = cpu_to_le32(reg & 0xff); if (i == cf->can_dlc) break; @@ -871,16 +788,17 @@ static int pch_can_rx_normal(struct net_device *ndev, u32 int_stat) stats->rx_bytes += cf->can_dlc; if (k < PCH_FIFO_THRESH) { - iowrite32(CAN_CMASK_RDWR | CAN_CMASK_CTRL | - CAN_CMASK_ARB, &priv->regs->if1_cmask); + iowrite32(PCH_CMASK_RDWR | PCH_CMASK_CTRL | + PCH_CMASK_ARB, &priv->regs->ifregs[0].cmask); /* Clearing the Dir bit. */ - pch_can_bit_clear(&priv->regs->if1_id2, CAN_ID2_DIR); + pch_can_bit_clear(&priv->regs->ifregs[0].id2, + PCH_ID2_DIR); /* Clearing NewDat & IntPnd */ - pch_can_bit_clear(&priv->regs->if1_mcont, - CAN_IF_MCONT_INTPND); - pch_can_check_if_busy(&priv->regs->if1_creq, k); + pch_can_bit_clear(&priv->regs->ifregs[0].mcont, + PCH_IF_MCONT_INTPND); + pch_can_check_if_busy(&priv->regs->ifregs[0].creq, k); } else if (k > PCH_FIFO_THRESH) { pch_can_int_clr(priv, k); } else if (k == PCH_FIFO_THRESH) { @@ -890,9 +808,9 @@ static int pch_can_rx_normal(struct net_device *ndev, u32 int_stat) } RX_NEXT: /* Reading the messsage object from the Message RAM */ - iowrite32(CAN_CMASK_RX_TX_GET, &priv->regs->if1_cmask); - pch_can_check_if_busy(&priv->regs->if1_creq, k + 1); - reg = ioread32(&priv->regs->if1_mcont); + iowrite32(PCH_CMASK_RX_TX_GET, &priv->regs->ifregs[0].cmask); + pch_can_check_if_busy(&priv->regs->ifregs[0].creq, k); + reg = ioread32(&priv->regs->ifregs[0].mcont); } return rcv_pkts; @@ -906,14 +824,13 @@ static int pch_can_rx_poll(struct napi_struct *napi, int quota) u32 int_stat; int rcv_pkts = 0; u32 reg_stat; - unsigned long flags; int_stat = pch_can_int_pending(priv); if (!int_stat) return 0; INT_STAT: - if (int_stat == CAN_STATUS_INT) { + if (int_stat == PCH_STATUS_INT) { reg_stat = ioread32(&priv->regs->stat); if (reg_stat & (PCH_BUS_OFF | PCH_LEC_ALL)) { if ((reg_stat & PCH_LEC_ALL) != PCH_LEC_ALL) @@ -921,11 +838,10 @@ INT_STAT: } if (reg_stat & PCH_TX_OK) { - spin_lock_irqsave(&priv->msgif_reg_lock, flags); - iowrite32(CAN_CMASK_RX_TX_GET, &priv->regs->if2_cmask); - pch_can_check_if_busy(&priv->regs->if2_creq, + iowrite32(PCH_CMASK_RX_TX_GET, + &priv->regs->ifregs[1].cmask); + pch_can_check_if_busy(&priv->regs->ifregs[1].creq, ioread32(&priv->regs->intr)); - spin_unlock_irqrestore(&priv->msgif_reg_lock, flags); pch_can_bit_clear(&priv->regs->stat, PCH_TX_OK); } @@ -933,37 +849,32 @@ INT_STAT: pch_can_bit_clear(&priv->regs->stat, PCH_RX_OK); int_stat = pch_can_int_pending(priv); - if (int_stat == CAN_STATUS_INT) + if (int_stat == PCH_STATUS_INT) goto INT_STAT; } MSG_OBJ: - if ((int_stat >= 1) && (int_stat <= PCH_RX_OBJ_NUM)) { - spin_lock_irqsave(&priv->msgif_reg_lock, flags); + if ((int_stat >= PCH_RX_OBJ_START) && (int_stat <= PCH_RX_OBJ_END)) { rcv_pkts = pch_can_rx_normal(ndev, int_stat); - spin_unlock_irqrestore(&priv->msgif_reg_lock, flags); if (rcv_pkts < 0) return 0; - } else if ((int_stat > PCH_RX_OBJ_NUM) && (int_stat <= PCH_OBJ_NUM)) { - if (priv->msg_obj[int_stat - 1] == MSG_OBJ_TX) { - /* Handle transmission interrupt */ - can_get_echo_skb(ndev, int_stat - PCH_RX_OBJ_NUM - 1); - spin_lock_irqsave(&priv->msgif_reg_lock, flags); - iowrite32(CAN_CMASK_RX_TX_GET | CAN_CMASK_CLRINTPND, - &priv->regs->if2_cmask); - dlc = ioread32(&priv->regs->if2_mcont) & - CAN_IF_MCONT_DLC; - pch_can_check_if_busy(&priv->regs->if2_creq, int_stat); - spin_unlock_irqrestore(&priv->msgif_reg_lock, flags); - if (dlc > 8) - dlc = 8; - stats->tx_bytes += dlc; - stats->tx_packets++; - } + } else if ((int_stat >= PCH_TX_OBJ_START) && + (int_stat <= PCH_TX_OBJ_END)) { + /* Handle transmission interrupt */ + can_get_echo_skb(ndev, int_stat - PCH_RX_OBJ_END - 1); + iowrite32(PCH_CMASK_RX_TX_GET | PCH_CMASK_CLRINTPND, + &priv->regs->ifregs[1].cmask); + dlc = ioread32(&priv->regs->ifregs[1].mcont) & + PCH_IF_MCONT_DLC; + pch_can_check_if_busy(&priv->regs->ifregs[1].creq, int_stat); + if (dlc > 8) + dlc = 8; + stats->tx_bytes += dlc; + stats->tx_packets++; } int_stat = pch_can_int_pending(priv); - if (int_stat == CAN_STATUS_INT) + if (int_stat == PCH_STATUS_INT) goto INT_STAT; else if (int_stat >= 1 && int_stat <= 32) goto MSG_OBJ; @@ -983,17 +894,17 @@ static int pch_set_bittiming(struct net_device *ndev) u32 brp; /* Setting the CCE bit for accessing the Can Timing register. */ - pch_can_bit_set(&priv->regs->cont, CAN_CTRL_CCE); + pch_can_bit_set(&priv->regs->cont, PCH_CTRL_CCE); brp = (bt->tq) / (1000000000/PCH_CAN_CLK) - 1; - canbit = brp & MSK_BITT_BRP; - canbit |= (bt->sjw - 1) << BIT_BITT_SJW; - canbit |= (bt->phase_seg1 + bt->prop_seg - 1) << BIT_BITT_TSEG1; - canbit |= (bt->phase_seg2 - 1) << BIT_BITT_TSEG2; - bepe = (brp & MSK_BRPE_BRPE) >> BIT_BRPE_BRPE; + canbit = brp & PCH_MSK_BITT_BRP; + canbit |= (bt->sjw - 1) << PCH_BIT_SJW; + canbit |= (bt->phase_seg1 + bt->prop_seg - 1) << PCH_BIT_TSEG1; + canbit |= (bt->phase_seg2 - 1) << PCH_BIT_TSEG2; + bepe = (brp & PCH_MSK_BRPE_BRPE) >> PCH_BIT_BRPE_BRPE; iowrite32(canbit, &priv->regs->bitt); iowrite32(bepe, &priv->regs->brpe); - pch_can_bit_clear(&priv->regs->cont, CAN_CTRL_CCE); + pch_can_bit_clear(&priv->regs->cont, PCH_CTRL_CCE); return 0; } @@ -1008,8 +919,8 @@ static void pch_can_start(struct net_device *ndev) pch_set_bittiming(ndev); pch_can_set_optmode(priv); - pch_can_tx_enable_all(priv); - pch_can_rx_enable_all(priv); + pch_can_set_tx_all(priv, 1); + pch_can_set_rx_all(priv, 1); /* Setting the CAN to run mode. */ pch_can_set_run_mode(priv, PCH_CAN_RUN); @@ -1113,7 +1024,6 @@ static int pch_get_msg_obj_sts(struct net_device *ndev, u32 obj_id) static netdev_tx_t pch_xmit(struct sk_buff *skb, struct net_device *ndev) { int i, j; - unsigned long flags; struct pch_can_priv *priv = netdev_priv(ndev); struct can_frame *cf = (struct can_frame *)skb->data; int tx_buffer_avail = 0; @@ -1121,72 +1031,68 @@ static netdev_tx_t pch_xmit(struct sk_buff *skb, struct net_device *ndev) if (can_dropped_invalid_skb(ndev, skb)) return NETDEV_TX_OK; - if (priv->tx_obj == (PCH_OBJ_NUM + 1)) { /* Point tail Obj */ + if (priv->tx_obj == PCH_TX_OBJ_END) { /* Point tail Obj */ while (pch_get_msg_obj_sts(ndev, (((1 << PCH_TX_OBJ_NUM)-1) << PCH_RX_OBJ_NUM))) udelay(500); - priv->tx_obj = PCH_RX_OBJ_NUM + 1; /* Point head of Tx Obj ID */ + priv->tx_obj = PCH_TX_OBJ_START; /* Point head of Tx Obj ID */ tx_buffer_avail = priv->tx_obj; /* Point Tail of Tx Obj */ } else { tx_buffer_avail = priv->tx_obj; } priv->tx_obj++; - /* Attaining the lock. */ - spin_lock_irqsave(&priv->msgif_reg_lock, flags); - /* Reading the Msg Obj from the Msg RAM to the Interface register. */ - iowrite32(CAN_CMASK_RX_TX_GET, &priv->regs->if2_cmask); - pch_can_check_if_busy(&priv->regs->if2_creq, tx_buffer_avail); + iowrite32(PCH_CMASK_RX_TX_GET, &priv->regs->ifregs[1].cmask); + pch_can_check_if_busy(&priv->regs->ifregs[1].creq, tx_buffer_avail); /* Setting the CMASK register. */ - pch_can_bit_set(&priv->regs->if2_cmask, CAN_CMASK_ALL); + pch_can_bit_set(&priv->regs->ifregs[1].cmask, PCH_CMASK_ALL); /* If ID extended is set. */ - pch_can_bit_clear(&priv->regs->if2_id1, 0xffff); - pch_can_bit_clear(&priv->regs->if2_id2, 0x1fff | CAN_ID2_XTD); + pch_can_bit_clear(&priv->regs->ifregs[1].id1, 0xffff); + pch_can_bit_clear(&priv->regs->ifregs[1].id2, 0x1fff | PCH_ID2_XTD); if (cf->can_id & CAN_EFF_FLAG) { - pch_can_bit_set(&priv->regs->if2_id1, cf->can_id & 0xffff); - pch_can_bit_set(&priv->regs->if2_id2, - ((cf->can_id >> 16) & 0x1fff) | CAN_ID2_XTD); + pch_can_bit_set(&priv->regs->ifregs[1].id1, + cf->can_id & 0xffff); + pch_can_bit_set(&priv->regs->ifregs[1].id2, + ((cf->can_id >> 16) & 0x1fff) | PCH_ID2_XTD); } else { - pch_can_bit_set(&priv->regs->if2_id1, 0); - pch_can_bit_set(&priv->regs->if2_id2, + pch_can_bit_set(&priv->regs->ifregs[1].id1, 0); + pch_can_bit_set(&priv->regs->ifregs[1].id2, (cf->can_id & CAN_SFF_MASK) << 2); } /* If remote frame has to be transmitted.. */ if (cf->can_id & CAN_RTR_FLAG) - pch_can_bit_clear(&priv->regs->if2_id2, CAN_ID2_DIR); + pch_can_bit_clear(&priv->regs->ifregs[1].id2, PCH_ID2_DIR); for (i = 0, j = 0; i < cf->can_dlc; j++) { iowrite32(le32_to_cpu(cf->data[i++]), - (&priv->regs->if2_dataa1) + j*4); + (&priv->regs->ifregs[1].dataa1) + j*4); if (i == cf->can_dlc) break; iowrite32(le32_to_cpu(cf->data[i++] << 8), - (&priv->regs->if2_dataa1) + j*4); + (&priv->regs->ifregs[1].dataa1) + j*4); } - can_put_echo_skb(skb, ndev, tx_buffer_avail - PCH_RX_OBJ_NUM - 1); + can_put_echo_skb(skb, ndev, tx_buffer_avail - PCH_RX_OBJ_END - 1); /* Updating the size of the data. */ - pch_can_bit_clear(&priv->regs->if2_mcont, 0x0f); - pch_can_bit_set(&priv->regs->if2_mcont, cf->can_dlc); + pch_can_bit_clear(&priv->regs->ifregs[1].mcont, 0x0f); + pch_can_bit_set(&priv->regs->ifregs[1].mcont, cf->can_dlc); /* Clearing IntPend, NewDat & TxRqst */ - pch_can_bit_clear(&priv->regs->if2_mcont, - CAN_IF_MCONT_NEWDAT | CAN_IF_MCONT_INTPND | - CAN_IF_MCONT_TXRQXT); + pch_can_bit_clear(&priv->regs->ifregs[1].mcont, + PCH_IF_MCONT_NEWDAT | PCH_IF_MCONT_INTPND | + PCH_IF_MCONT_TXRQXT); /* Setting NewDat, TxRqst bits */ - pch_can_bit_set(&priv->regs->if2_mcont, - CAN_IF_MCONT_NEWDAT | CAN_IF_MCONT_TXRQXT); - - pch_can_check_if_busy(&priv->regs->if2_creq, tx_buffer_avail); + pch_can_bit_set(&priv->regs->ifregs[1].mcont, + PCH_IF_MCONT_NEWDAT | PCH_IF_MCONT_TXRQXT); - spin_unlock_irqrestore(&priv->msgif_reg_lock, flags); + pch_can_check_if_busy(&priv->regs->ifregs[1].creq, tx_buffer_avail); return NETDEV_TX_OK; } @@ -1244,27 +1150,20 @@ static int pch_can_suspend(struct pci_dev *pdev, pm_message_t state) pch_can_set_int_enables(priv, PCH_CAN_DISABLE); /* Save Tx buffer enable state */ - for (i = 0; i < PCH_OBJ_NUM; i++) { - if (priv->msg_obj[i] == MSG_OBJ_TX) - pch_can_get_tx_enable(priv, i + 1, - &(priv->tx_enable[i])); - } + for (i = PCH_TX_OBJ_START; i <= PCH_TX_OBJ_END; i++) + priv->tx_enable[i] = pch_can_get_rxtx_ir(priv, i, PCH_TX_IFREG); /* Disable all Transmit buffers */ - pch_can_tx_disable_all(priv); + pch_can_set_tx_all(priv, 0); /* Save Rx buffer enable state */ - for (i = 0; i < PCH_OBJ_NUM; i++) { - if (priv->msg_obj[i] == MSG_OBJ_RX) { - pch_can_get_rx_enable(priv, i + 1, - &(priv->rx_enable[i])); - pch_can_get_rx_buffer_link(priv, i + 1, - &(priv->rx_link[i])); - } + for (i = PCH_RX_OBJ_START; i <= PCH_RX_OBJ_END; i++) { + priv->rx_enable[i] = pch_can_get_rxtx_ir(priv, i, PCH_RX_IFREG); + pch_can_get_rx_buffer_link(priv, i, &priv->rx_link[i]); } /* Disable all Receive buffers */ - pch_can_rx_disable_all(priv); + pch_can_set_rx_all(priv, 0); retval = pci_save_state(pdev); if (retval) { dev_err(&pdev->dev, "pci_save_state failed.\n"); @@ -1312,23 +1211,16 @@ static int pch_can_resume(struct pci_dev *pdev) pch_can_set_optmode(priv); /* Enabling the transmit buffer. */ - for (i = 0; i < PCH_OBJ_NUM; i++) { - if (priv->msg_obj[i] == MSG_OBJ_TX) { - pch_can_set_tx_enable(priv, i + 1, - priv->tx_enable[i]); - } - } + for (i = PCH_TX_OBJ_START; i <= PCH_TX_OBJ_END; i++) + pch_can_set_rxtx(priv, i, priv->tx_enable[i], PCH_TX_IFREG); /* Configuring the receive buffer and enabling them. */ - for (i = 0; i < PCH_OBJ_NUM; i++) { - if (priv->msg_obj[i] == MSG_OBJ_RX) { - /* Restore buffer link */ - pch_can_set_rx_buffer_link(priv, i + 1, - priv->rx_link[i]); - - /* Restore buffer enables */ - pch_can_set_rx_enable(priv, i + 1, priv->rx_enable[i]); - } + for (i = PCH_RX_OBJ_START; i <= PCH_RX_OBJ_END; i++) { + /* Restore buffer link */ + pch_can_set_rx_buffer_link(priv, i, priv->rx_link[i]); + + /* Restore buffer enables */ + pch_can_set_rxtx(priv, i, priv->rx_enable[i], PCH_RX_IFREG); } /* Enable CAN Interrupts */ @@ -1349,8 +1241,8 @@ static int pch_can_get_berr_counter(const struct net_device *dev, { struct pch_can_priv *priv = netdev_priv(dev); - bec->txerr = ioread32(&priv->regs->errc) & CAN_TEC; - bec->rxerr = (ioread32(&priv->regs->errc) & CAN_REC) >> 8; + bec->txerr = ioread32(&priv->regs->errc) & PCH_TEC; + bec->rxerr = (ioread32(&priv->regs->errc) & PCH_REC) >> 8; return 0; } @@ -1361,7 +1253,6 @@ static int __devinit pch_can_probe(struct pci_dev *pdev, struct net_device *ndev; struct pch_can_priv *priv; int rc; - int index; void __iomem *addr; rc = pci_enable_device(pdev); @@ -1383,7 +1274,7 @@ static int __devinit pch_can_probe(struct pci_dev *pdev, goto probe_exit_ipmap; } - ndev = alloc_candev(sizeof(struct pch_can_priv), PCH_TX_OBJ_NUM); + ndev = alloc_candev(sizeof(struct pch_can_priv), PCH_TX_OBJ_END); if (!ndev) { rc = -ENOMEM; dev_err(&pdev->dev, "Failed alloc_candev\n"); @@ -1399,7 +1290,7 @@ static int __devinit pch_can_probe(struct pci_dev *pdev, priv->can.do_get_berr_counter = pch_can_get_berr_counter; priv->can.ctrlmode_supported = CAN_CTRLMODE_LISTENONLY | CAN_CTRLMODE_LOOPBACK; - priv->tx_obj = PCH_RX_OBJ_NUM + 1; /* Point head of Tx Obj */ + priv->tx_obj = PCH_TX_OBJ_START; /* Point head of Tx Obj */ ndev->irq = pdev->irq; ndev->flags |= IFF_ECHO; @@ -1407,15 +1298,9 @@ static int __devinit pch_can_probe(struct pci_dev *pdev, pci_set_drvdata(pdev, ndev); SET_NETDEV_DEV(ndev, &pdev->dev); ndev->netdev_ops = &pch_can_netdev_ops; - priv->can.clock.freq = PCH_CAN_CLK; /* Hz */ - for (index = 0; index < PCH_RX_OBJ_NUM;) - priv->msg_obj[index++] = MSG_OBJ_RX; - - for (index = index; index < PCH_OBJ_NUM;) - priv->msg_obj[index++] = MSG_OBJ_TX; - netif_napi_add(ndev, &priv->napi, pch_can_rx_poll, PCH_RX_OBJ_NUM); + netif_napi_add(ndev, &priv->napi, pch_can_rx_poll, PCH_RX_OBJ_END); rc = register_candev(ndev); if (rc) { diff --git a/drivers/net/can/sja1000/sja1000_of_platform.c b/drivers/net/can/sja1000/sja1000_of_platform.c index 5bfccfdf3bbb..09c3e9db9316 100644 --- a/drivers/net/can/sja1000/sja1000_of_platform.c +++ b/drivers/net/can/sja1000/sja1000_of_platform.c @@ -107,17 +107,13 @@ static int __devinit sja1000_ofp_probe(struct platform_device *ofdev, res_size = resource_size(&res); if (!request_mem_region(res.start, res_size, DRV_NAME)) { - dev_err(&ofdev->dev, "couldn't request %#llx..%#llx\n", - (unsigned long long)res.start, - (unsigned long long)res.end); + dev_err(&ofdev->dev, "couldn't request %pR\n", &res); return -EBUSY; } base = ioremap_nocache(res.start, res_size); if (!base) { - dev_err(&ofdev->dev, "couldn't ioremap %#llx..%#llx\n", - (unsigned long long)res.start, - (unsigned long long)res.end); + dev_err(&ofdev->dev, "couldn't ioremap %pR\n", &res); err = -ENOMEM; goto exit_release_mem; } diff --git a/drivers/net/cnic.c b/drivers/net/cnic.c index 92bac19ad60a..594ca9c2c10a 100644 --- a/drivers/net/cnic.c +++ b/drivers/net/cnic.c @@ -1695,7 +1695,7 @@ static int cnic_bnx2x_iscsi_ofld1(struct cnic_dev *dev, struct kwqe *wqes[], *work = num; return -EINVAL; } - *work = 2 + req2->num_additional_wqes;; + *work = 2 + req2->num_additional_wqes; l5_cid = req1->iscsi_conn_id; if (l5_cid >= MAX_ISCSI_TBL_SZ) diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c index 407d4e272075..386461750d0f 100644 --- a/drivers/net/cxgb3/cxgb3_main.c +++ b/drivers/net/cxgb3/cxgb3_main.c @@ -3006,12 +3006,11 @@ static pci_ers_result_t t3_io_error_detected(struct pci_dev *pdev, pci_channel_state_t state) { struct adapter *adapter = pci_get_drvdata(pdev); - int ret; if (state == pci_channel_io_perm_failure) return PCI_ERS_RESULT_DISCONNECT; - ret = t3_adapter_error(adapter, 0, 0); + t3_adapter_error(adapter, 0, 0); /* Request a slot reset. */ return PCI_ERS_RESULT_NEED_RESET; @@ -3341,7 +3340,6 @@ static int __devinit init_one(struct pci_dev *pdev, adapter->name = adapter->port[i]->name; __set_bit(i, &adapter->registered_device_map); - netif_tx_stop_all_queues(adapter->port[i]); } } if (!adapter->registered_device_map) { diff --git a/drivers/net/cxgb3/cxgb3_offload.c b/drivers/net/cxgb3/cxgb3_offload.c index bcf07532953d..ef02aa68c926 100644 --- a/drivers/net/cxgb3/cxgb3_offload.c +++ b/drivers/net/cxgb3/cxgb3_offload.c @@ -1164,12 +1164,10 @@ static void cxgb_redirect(struct dst_entry *old, struct dst_entry *new) */ void *cxgb_alloc_mem(unsigned long size) { - void *p = kmalloc(size, GFP_KERNEL); + void *p = kzalloc(size, GFP_KERNEL); if (!p) - p = vmalloc(size); - if (p) - memset(p, 0, size); + p = vzalloc(size); return p; } diff --git a/drivers/net/cxgb4/cxgb4_main.c b/drivers/net/cxgb4/cxgb4_main.c index f17703f410b3..848f89d19fb7 100644 --- a/drivers/net/cxgb4/cxgb4_main.c +++ b/drivers/net/cxgb4/cxgb4_main.c @@ -868,12 +868,10 @@ out: release_firmware(fw); */ void *t4_alloc_mem(size_t size) { - void *p = kmalloc(size, GFP_KERNEL); + void *p = kzalloc(size, GFP_KERNEL); if (!p) - p = vmalloc(size); - if (p) - memset(p, 0, size); + p = vzalloc(size); return p; } @@ -3736,7 +3734,6 @@ static int __devinit init_one(struct pci_dev *pdev, __set_bit(i, &adapter->registered_device_map); adapter->chan_map[adap2pinfo(adapter, i)->tx_chan] = i; - netif_tx_stop_all_queues(adapter->port[i]); } } if (!adapter->registered_device_map) { diff --git a/drivers/net/cxgb4vf/adapter.h b/drivers/net/cxgb4vf/adapter.h index 8ea01962e045..4766b4116b41 100644 --- a/drivers/net/cxgb4vf/adapter.h +++ b/drivers/net/cxgb4vf/adapter.h @@ -60,7 +60,7 @@ enum { * MSI-X interrupt index usage. */ MSIX_FW = 0, /* MSI-X index for firmware Q */ - MSIX_NIQFLINT = 1, /* MSI-X index base for Ingress Qs */ + MSIX_IQFLINT = 1, /* MSI-X index base for Ingress Qs */ MSIX_EXTRAS = 1, MSIX_ENTRIES = MAX_ETH_QSETS + MSIX_EXTRAS, diff --git a/drivers/net/cxgb4vf/cxgb4vf_main.c b/drivers/net/cxgb4vf/cxgb4vf_main.c index 555ecc5a2e93..9246d2fa6cf9 100644 --- a/drivers/net/cxgb4vf/cxgb4vf_main.c +++ b/drivers/net/cxgb4vf/cxgb4vf_main.c @@ -280,9 +280,7 @@ static void name_msix_vecs(struct adapter *adapter) const struct port_info *pi = netdev_priv(dev); int qs, msi; - for (qs = 0, msi = MSIX_NIQFLINT; - qs < pi->nqsets; - qs++, msi++) { + for (qs = 0, msi = MSIX_IQFLINT; qs < pi->nqsets; qs++, msi++) { snprintf(adapter->msix_info[msi].desc, namelen, "%s-%d", dev->name, qs); adapter->msix_info[msi].desc[namelen] = 0; @@ -309,7 +307,7 @@ static int request_msix_queue_irqs(struct adapter *adapter) /* * Ethernet queues. */ - msi = MSIX_NIQFLINT; + msi = MSIX_IQFLINT; for_each_ethrxq(s, rxq) { err = request_irq(adapter->msix_info[msi].vec, t4vf_sge_intr_msix, 0, @@ -337,7 +335,7 @@ static void free_msix_queue_irqs(struct adapter *adapter) int rxq, msi; free_irq(adapter->msix_info[MSIX_FW].vec, &s->fw_evtq); - msi = MSIX_NIQFLINT; + msi = MSIX_IQFLINT; for_each_ethrxq(s, rxq) free_irq(adapter->msix_info[msi++].vec, &s->ethrxq[rxq].rspq); @@ -527,7 +525,7 @@ static int setup_sge_queues(struct adapter *adapter) * brought up at which point lots of things get nailed down * permanently ... */ - msix = MSIX_NIQFLINT; + msix = MSIX_IQFLINT; for_each_port(adapter, pidx) { struct net_device *dev = adapter->port[pidx]; struct port_info *pi = netdev_priv(dev); @@ -753,7 +751,9 @@ static int cxgb4vf_open(struct net_device *dev) if (err) return err; set_bit(pi->port_id, &adapter->open_device_map); - link_start(dev); + err = link_start(dev); + if (err) + return err; netif_tx_start_all_queues(dev); return 0; } @@ -1103,18 +1103,6 @@ static int cxgb4vf_set_mac_addr(struct net_device *dev, void *_addr) return 0; } -/* - * Return a TX Queue on which to send the specified skb. - */ -static u16 cxgb4vf_select_queue(struct net_device *dev, struct sk_buff *skb) -{ - /* - * XXX For now just use the default hash but we probably want to - * XXX look at other possibilities ... - */ - return skb_tx_hash(dev, skb); -} - #ifdef CONFIG_NET_POLL_CONTROLLER /* * Poll all of our receive queues. This is called outside of normal interrupt @@ -1358,6 +1346,8 @@ struct queue_port_stats { u64 rx_csum; u64 vlan_ex; u64 vlan_ins; + u64 lro_pkts; + u64 lro_merged; }; /* @@ -1395,6 +1385,8 @@ static const char stats_strings[][ETH_GSTRING_LEN] = { "RxCsumGood ", "VLANextractions ", "VLANinsertions ", + "GROPackets ", + "GROMerged ", }; /* @@ -1444,6 +1436,8 @@ static void collect_sge_port_stats(const struct adapter *adapter, stats->rx_csum += rxq->stats.rx_cso; stats->vlan_ex += rxq->stats.vlan_ex; stats->vlan_ins += txq->vlan_ins; + stats->lro_pkts += rxq->stats.lro_pkts; + stats->lro_merged += rxq->stats.lro_merged; } } @@ -1540,14 +1534,19 @@ static void cxgb4vf_get_wol(struct net_device *dev, } /* + * TCP Segmentation Offload flags which we support. + */ +#define TSO_FLAGS (NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_TSO_ECN) + +/* * Set TCP Segmentation Offloading feature capabilities. */ static int cxgb4vf_set_tso(struct net_device *dev, u32 tso) { if (tso) - dev->features |= NETIF_F_TSO | NETIF_F_TSO6; + dev->features |= TSO_FLAGS; else - dev->features &= ~(NETIF_F_TSO | NETIF_F_TSO6); + dev->features &= ~TSO_FLAGS; return 0; } @@ -2038,7 +2037,7 @@ static int __devinit setup_debugfs(struct adapter *adapter) * Tear down the /sys/kernel/debug/cxgb4vf sub-nodes created above. We leave * it to our caller to tear down the directory (debugfs_root). */ -static void __devexit cleanup_debugfs(struct adapter *adapter) +static void cleanup_debugfs(struct adapter *adapter) { BUG_ON(adapter->debugfs_root == NULL); @@ -2056,7 +2055,7 @@ static void __devexit cleanup_debugfs(struct adapter *adapter) * adapter parameters we're going to be using and initialize basic adapter * hardware support. */ -static int adap_init0(struct adapter *adapter) +static int __devinit adap_init0(struct adapter *adapter) { struct vf_resources *vfres = &adapter->params.vfres; struct sge_params *sge_params = &adapter->params.sge; @@ -2075,6 +2074,22 @@ static int adap_init0(struct adapter *adapter) } /* + * Some environments do not properly handle PCIE FLRs -- e.g. in Linux + * 2.6.31 and later we can't call pci_reset_function() in order to + * issue an FLR because of a self- deadlock on the device semaphore. + * Meanwhile, the OS infrastructure doesn't issue FLRs in all the + * cases where they're needed -- for instance, some versions of KVM + * fail to reset "Assigned Devices" when the VM reboots. Therefore we + * use the firmware based reset in order to reset any per function + * state. + */ + err = t4vf_fw_reset(adapter); + if (err < 0) { + dev_err(adapter->pdev_dev, "FW reset failed: err=%d\n", err); + return err; + } + + /* * Grab basic operational parameters. These will predominantly have * been set up by the Physical Function Driver or will be hard coded * into the adapter. We just have to live with them ... Note that @@ -2417,7 +2432,6 @@ static const struct net_device_ops cxgb4vf_netdev_ops = { .ndo_get_stats = cxgb4vf_get_stats, .ndo_set_rx_mode = cxgb4vf_set_rxmode, .ndo_set_mac_address = cxgb4vf_set_mac_addr, - .ndo_select_queue = cxgb4vf_select_queue, .ndo_validate_addr = eth_validate_addr, .ndo_do_ioctl = cxgb4vf_do_ioctl, .ndo_change_mtu = cxgb4vf_change_mtu, @@ -2465,7 +2479,6 @@ static int __devinit cxgb4vf_pci_probe(struct pci_dev *pdev, version_printed = 1; } - /* * Initialize generic PCI device state. */ @@ -2600,10 +2613,9 @@ static int __devinit cxgb4vf_pci_probe(struct pci_dev *pdev, pi->xact_addr_filt = -1; pi->rx_offload = RX_CSO; netif_carrier_off(netdev); - netif_tx_stop_all_queues(netdev); netdev->irq = pdev->irq; - netdev->features = (NETIF_F_SG | NETIF_F_TSO | NETIF_F_TSO6 | + netdev->features = (NETIF_F_SG | TSO_FLAGS | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX | NETIF_F_GRO); @@ -2625,7 +2637,6 @@ static int __devinit cxgb4vf_pci_probe(struct pci_dev *pdev, netdev->do_ioctl = cxgb4vf_do_ioctl; netdev->change_mtu = cxgb4vf_change_mtu; netdev->set_mac_address = cxgb4vf_set_mac_addr; - netdev->select_queue = cxgb4vf_select_queue; #ifdef CONFIG_NET_POLL_CONTROLLER netdev->poll_controller = cxgb4vf_poll_controller; #endif @@ -2844,6 +2855,14 @@ static struct pci_device_id cxgb4vf_pci_tbl[] = { CH_DEVICE(0x4800, 0), /* T440-dbg */ CH_DEVICE(0x4801, 0), /* T420-cr */ CH_DEVICE(0x4802, 0), /* T422-cr */ + CH_DEVICE(0x4803, 0), /* T440-cr */ + CH_DEVICE(0x4804, 0), /* T420-bch */ + CH_DEVICE(0x4805, 0), /* T440-bch */ + CH_DEVICE(0x4806, 0), /* T460-ch */ + CH_DEVICE(0x4807, 0), /* T420-so */ + CH_DEVICE(0x4808, 0), /* T420-cx */ + CH_DEVICE(0x4809, 0), /* T420-bt */ + CH_DEVICE(0x480a, 0), /* T404-bt */ { 0, } }; diff --git a/drivers/net/cxgb4vf/sge.c b/drivers/net/cxgb4vf/sge.c index f10864ddafbe..e0b3d1bc2fdf 100644 --- a/drivers/net/cxgb4vf/sge.c +++ b/drivers/net/cxgb4vf/sge.c @@ -154,13 +154,14 @@ enum { */ RX_COPY_THRES = 256, RX_PULL_LEN = 128, -}; -/* - * Can't define this in the above enum because PKTSHIFT isn't a constant in - * the VF Driver ... - */ -#define RX_PKT_PULL_LEN (RX_PULL_LEN + PKTSHIFT) + /* + * Main body length for sk_buffs used for RX Ethernet packets with + * fragments. Should be >= RX_PULL_LEN but possibly bigger to give + * pskb_may_pull() some room. + */ + RX_SKB_LEN = 512, +}; /* * Software state per TX descriptor. @@ -1355,6 +1356,67 @@ out_free: } /** + * t4vf_pktgl_to_skb - build an sk_buff from a packet gather list + * @gl: the gather list + * @skb_len: size of sk_buff main body if it carries fragments + * @pull_len: amount of data to move to the sk_buff's main body + * + * Builds an sk_buff from the given packet gather list. Returns the + * sk_buff or %NULL if sk_buff allocation failed. + */ +struct sk_buff *t4vf_pktgl_to_skb(const struct pkt_gl *gl, + unsigned int skb_len, unsigned int pull_len) +{ + struct sk_buff *skb; + struct skb_shared_info *ssi; + + /* + * If the ingress packet is small enough, allocate an skb large enough + * for all of the data and copy it inline. Otherwise, allocate an skb + * with enough room to pull in the header and reference the rest of + * the data via the skb fragment list. + * + * Below we rely on RX_COPY_THRES being less than the smallest Rx + * buff! size, which is expected since buffers are at least + * PAGE_SIZEd. In this case packets up to RX_COPY_THRES have only one + * fragment. + */ + if (gl->tot_len <= RX_COPY_THRES) { + /* small packets have only one fragment */ + skb = alloc_skb(gl->tot_len, GFP_ATOMIC); + if (unlikely(!skb)) + goto out; + __skb_put(skb, gl->tot_len); + skb_copy_to_linear_data(skb, gl->va, gl->tot_len); + } else { + skb = alloc_skb(skb_len, GFP_ATOMIC); + if (unlikely(!skb)) + goto out; + __skb_put(skb, pull_len); + skb_copy_to_linear_data(skb, gl->va, pull_len); + + ssi = skb_shinfo(skb); + ssi->frags[0].page = gl->frags[0].page; + ssi->frags[0].page_offset = gl->frags[0].page_offset + pull_len; + ssi->frags[0].size = gl->frags[0].size - pull_len; + if (gl->nfrags > 1) + memcpy(&ssi->frags[1], &gl->frags[1], + (gl->nfrags-1) * sizeof(skb_frag_t)); + ssi->nr_frags = gl->nfrags; + + skb->len = gl->tot_len; + skb->data_len = skb->len - pull_len; + skb->truesize += skb->data_len; + + /* Get a reference for the last page, we don't own it */ + get_page(gl->frags[gl->nfrags - 1].page); + } + +out: + return skb; +} + +/** * t4vf_pktgl_free - free a packet gather list * @gl: the gather list * @@ -1463,10 +1525,8 @@ int t4vf_ethrx_handler(struct sge_rspq *rspq, const __be64 *rsp, { struct sk_buff *skb; struct port_info *pi; - struct skb_shared_info *ssi; const struct cpl_rx_pkt *pkt = (void *)&rsp[1]; bool csum_ok = pkt->csum_calc && !pkt->err_vec; - unsigned int len = be16_to_cpu(pkt->len); struct sge_eth_rxq *rxq = container_of(rspq, struct sge_eth_rxq, rspq); /* @@ -1481,42 +1541,14 @@ int t4vf_ethrx_handler(struct sge_rspq *rspq, const __be64 *rsp, } /* - * If the ingress packet is small enough, allocate an skb large enough - * for all of the data and copy it inline. Otherwise, allocate an skb - * with enough room to pull in the header and reference the rest of - * the data via the skb fragment list. + * Convert the Packet Gather List into an skb. */ - if (len <= RX_COPY_THRES) { - /* small packets have only one fragment */ - skb = alloc_skb(gl->frags[0].size, GFP_ATOMIC); - if (!skb) - goto nomem; - __skb_put(skb, gl->frags[0].size); - skb_copy_to_linear_data(skb, gl->va, gl->frags[0].size); - } else { - skb = alloc_skb(RX_PKT_PULL_LEN, GFP_ATOMIC); - if (!skb) - goto nomem; - __skb_put(skb, RX_PKT_PULL_LEN); - skb_copy_to_linear_data(skb, gl->va, RX_PKT_PULL_LEN); - - ssi = skb_shinfo(skb); - ssi->frags[0].page = gl->frags[0].page; - ssi->frags[0].page_offset = (gl->frags[0].page_offset + - RX_PKT_PULL_LEN); - ssi->frags[0].size = gl->frags[0].size - RX_PKT_PULL_LEN; - if (gl->nfrags > 1) - memcpy(&ssi->frags[1], &gl->frags[1], - (gl->nfrags-1) * sizeof(skb_frag_t)); - ssi->nr_frags = gl->nfrags; - skb->len = len + PKTSHIFT; - skb->data_len = skb->len - RX_PKT_PULL_LEN; - skb->truesize += skb->data_len; - - /* Get a reference for the last page, we don't own it */ - get_page(gl->frags[gl->nfrags - 1].page); + skb = t4vf_pktgl_to_skb(gl, RX_SKB_LEN, RX_PULL_LEN); + if (unlikely(!skb)) { + t4vf_pktgl_free(gl); + rxq->stats.rx_drops++; + return 0; } - __skb_pull(skb, PKTSHIFT); skb->protocol = eth_type_trans(skb, rspq->netdev); skb_record_rx_queue(skb, rspq->idx); @@ -1536,6 +1568,9 @@ int t4vf_ethrx_handler(struct sge_rspq *rspq, const __be64 *rsp, } else skb_checksum_none_assert(skb); + /* + * Deliver the packet to the stack. + */ if (unlikely(pkt->vlan_ex)) { struct vlan_group *grp = pi->vlan_grp; @@ -1549,11 +1584,6 @@ int t4vf_ethrx_handler(struct sge_rspq *rspq, const __be64 *rsp, netif_receive_skb(skb); return 0; - -nomem: - t4vf_pktgl_free(gl); - rxq->stats.rx_drops++; - return 0; } /** @@ -1679,6 +1709,7 @@ int process_responses(struct sge_rspq *rspq, int budget) } len = RSPD_LEN(len); } + gl.tot_len = len; /* * Gather packet fragments. @@ -2115,7 +2146,7 @@ int t4vf_sge_alloc_rxq(struct adapter *adapter, struct sge_rspq *rspq, /* * Calculate the size of the hardware free list ring plus - * status page (which the SGE will place at the end of the + * Status Page (which the SGE will place after the end of the * free list ring) in Egress Queue Units. */ flsz = (fl->size / FL_PER_EQ_UNIT + @@ -2212,8 +2243,8 @@ int t4vf_sge_alloc_eth_txq(struct adapter *adapter, struct sge_eth_txq *txq, struct port_info *pi = netdev_priv(dev); /* - * Calculate the size of the hardware TX Queue (including the - * status age on the end) in units of TX Descriptors. + * Calculate the size of the hardware TX Queue (including the Status + * Page on the end of the TX Queue) in units of TX Descriptors. */ nentries = txq->q.size + STAT_LEN / sizeof(struct tx_desc); diff --git a/drivers/net/cxgb4vf/t4vf_common.h b/drivers/net/cxgb4vf/t4vf_common.h index 873cb7d86c57..a65c80aed1f2 100644 --- a/drivers/net/cxgb4vf/t4vf_common.h +++ b/drivers/net/cxgb4vf/t4vf_common.h @@ -235,6 +235,7 @@ static inline int t4vf_wr_mbox_ns(struct adapter *adapter, const void *cmd, int __devinit t4vf_wait_dev_ready(struct adapter *); int __devinit t4vf_port_init(struct adapter *, int); +int t4vf_fw_reset(struct adapter *); int t4vf_query_params(struct adapter *, unsigned int, const u32 *, u32 *); int t4vf_set_params(struct adapter *, unsigned int, const u32 *, const u32 *); diff --git a/drivers/net/cxgb4vf/t4vf_hw.c b/drivers/net/cxgb4vf/t4vf_hw.c index ea1c123f0cb4..f7d7f976064b 100644 --- a/drivers/net/cxgb4vf/t4vf_hw.c +++ b/drivers/net/cxgb4vf/t4vf_hw.c @@ -326,6 +326,25 @@ int __devinit t4vf_port_init(struct adapter *adapter, int pidx) } /** + * t4vf_fw_reset - issue a reset to FW + * @adapter: the adapter + * + * Issues a reset command to FW. For a Physical Function this would + * result in the Firmware reseting all of its state. For a Virtual + * Function this just resets the state associated with the VF. + */ +int t4vf_fw_reset(struct adapter *adapter) +{ + struct fw_reset_cmd cmd; + + memset(&cmd, 0, sizeof(cmd)); + cmd.op_to_write = cpu_to_be32(FW_CMD_OP(FW_RESET_CMD) | + FW_CMD_WRITE); + cmd.retval_len16 = cpu_to_be32(FW_LEN16(cmd)); + return t4vf_wr_mbox(adapter, &cmd, sizeof(cmd), NULL); +} + +/** * t4vf_query_params - query FW or device parameters * @adapter: the adapter * @nparams: the number of parameters @@ -1257,7 +1276,7 @@ int t4vf_eth_eq_free(struct adapter *adapter, unsigned int eqid) */ int t4vf_handle_fw_rpl(struct adapter *adapter, const __be64 *rpl) { - struct fw_cmd_hdr *cmd_hdr = (struct fw_cmd_hdr *)rpl; + const struct fw_cmd_hdr *cmd_hdr = (const struct fw_cmd_hdr *)rpl; u8 opcode = FW_CMD_OP_GET(be32_to_cpu(cmd_hdr->hi)); switch (opcode) { @@ -1265,7 +1284,8 @@ int t4vf_handle_fw_rpl(struct adapter *adapter, const __be64 *rpl) /* * Link/module state change message. */ - const struct fw_port_cmd *port_cmd = (void *)rpl; + const struct fw_port_cmd *port_cmd = + (const struct fw_port_cmd *)rpl; u32 word; int action, port_id, link_ok, speed, fc, pidx; diff --git a/drivers/net/dm9000.c b/drivers/net/dm9000.c index 9f6aeefa06bf..2d4c4fc1d900 100644 --- a/drivers/net/dm9000.c +++ b/drivers/net/dm9000.c @@ -1675,7 +1675,7 @@ dm9000_drv_remove(struct platform_device *pdev) platform_set_drvdata(pdev, NULL); unregister_netdev(ndev); - dm9000_release_board(pdev, (board_info_t *) netdev_priv(ndev)); + dm9000_release_board(pdev, netdev_priv(ndev)); free_netdev(ndev); /* free device structure */ dev_dbg(&pdev->dev, "released and freed device\n"); diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 4686c3983fc3..dcb7f82c2701 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -1425,13 +1425,12 @@ static int e1000_setup_tx_resources(struct e1000_adapter *adapter, int size; size = sizeof(struct e1000_buffer) * txdr->count; - txdr->buffer_info = vmalloc(size); + txdr->buffer_info = vzalloc(size); if (!txdr->buffer_info) { e_err(probe, "Unable to allocate memory for the Tx descriptor " "ring\n"); return -ENOMEM; } - memset(txdr->buffer_info, 0, size); /* round up to nearest 4K */ @@ -1621,13 +1620,12 @@ static int e1000_setup_rx_resources(struct e1000_adapter *adapter, int size, desc_len; size = sizeof(struct e1000_buffer) * rxdr->count; - rxdr->buffer_info = vmalloc(size); + rxdr->buffer_info = vzalloc(size); if (!rxdr->buffer_info) { e_err(probe, "Unable to allocate memory for the Rx descriptor " "ring\n"); return -ENOMEM; } - memset(rxdr->buffer_info, 0, size); desc_len = sizeof(struct e1000_rx_desc); diff --git a/drivers/net/e1000e/82571.c b/drivers/net/e1000e/82571.c index 7236f1a53ba0..9333921010cc 100644 --- a/drivers/net/e1000e/82571.c +++ b/drivers/net/e1000e/82571.c @@ -74,6 +74,9 @@ static bool e1000_check_mng_mode_82574(struct e1000_hw *hw); static s32 e1000_led_on_82574(struct e1000_hw *hw); static void e1000_put_hw_semaphore_82571(struct e1000_hw *hw); static void e1000_power_down_phy_copper_82571(struct e1000_hw *hw); +static void e1000_put_hw_semaphore_82573(struct e1000_hw *hw); +static s32 e1000_get_hw_semaphore_82574(struct e1000_hw *hw); +static void e1000_put_hw_semaphore_82574(struct e1000_hw *hw); /** * e1000_init_phy_params_82571 - Init PHY func ptrs. @@ -107,6 +110,8 @@ static s32 e1000_init_phy_params_82571(struct e1000_hw *hw) case e1000_82574: case e1000_82583: phy->type = e1000_phy_bm; + phy->ops.acquire = e1000_get_hw_semaphore_82574; + phy->ops.release = e1000_put_hw_semaphore_82574; break; default: return -E1000_ERR_PHY; @@ -200,6 +205,17 @@ static s32 e1000_init_nvm_params_82571(struct e1000_hw *hw) break; } + /* Function Pointers */ + switch (hw->mac.type) { + case e1000_82574: + case e1000_82583: + nvm->ops.acquire = e1000_get_hw_semaphore_82574; + nvm->ops.release = e1000_put_hw_semaphore_82574; + break; + default: + break; + } + return 0; } @@ -542,6 +558,94 @@ static void e1000_put_hw_semaphore_82571(struct e1000_hw *hw) swsm &= ~(E1000_SWSM_SMBI | E1000_SWSM_SWESMBI); ew32(SWSM, swsm); } +/** + * e1000_get_hw_semaphore_82573 - Acquire hardware semaphore + * @hw: pointer to the HW structure + * + * Acquire the HW semaphore during reset. + * + **/ +static s32 e1000_get_hw_semaphore_82573(struct e1000_hw *hw) +{ + u32 extcnf_ctrl; + s32 ret_val = 0; + s32 i = 0; + + extcnf_ctrl = er32(EXTCNF_CTRL); + extcnf_ctrl |= E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP; + do { + ew32(EXTCNF_CTRL, extcnf_ctrl); + extcnf_ctrl = er32(EXTCNF_CTRL); + + if (extcnf_ctrl & E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP) + break; + + extcnf_ctrl |= E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP; + + msleep(2); + i++; + } while (i < MDIO_OWNERSHIP_TIMEOUT); + + if (i == MDIO_OWNERSHIP_TIMEOUT) { + /* Release semaphores */ + e1000_put_hw_semaphore_82573(hw); + e_dbg("Driver can't access the PHY\n"); + ret_val = -E1000_ERR_PHY; + goto out; + } + +out: + return ret_val; +} + +/** + * e1000_put_hw_semaphore_82573 - Release hardware semaphore + * @hw: pointer to the HW structure + * + * Release hardware semaphore used during reset. + * + **/ +static void e1000_put_hw_semaphore_82573(struct e1000_hw *hw) +{ + u32 extcnf_ctrl; + + extcnf_ctrl = er32(EXTCNF_CTRL); + extcnf_ctrl &= ~E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP; + ew32(EXTCNF_CTRL, extcnf_ctrl); +} + +static DEFINE_MUTEX(swflag_mutex); + +/** + * e1000_get_hw_semaphore_82574 - Acquire hardware semaphore + * @hw: pointer to the HW structure + * + * Acquire the HW semaphore to access the PHY or NVM. + * + **/ +static s32 e1000_get_hw_semaphore_82574(struct e1000_hw *hw) +{ + s32 ret_val; + + mutex_lock(&swflag_mutex); + ret_val = e1000_get_hw_semaphore_82573(hw); + if (ret_val) + mutex_unlock(&swflag_mutex); + return ret_val; +} + +/** + * e1000_put_hw_semaphore_82574 - Release hardware semaphore + * @hw: pointer to the HW structure + * + * Release hardware semaphore used to access the PHY or NVM + * + **/ +static void e1000_put_hw_semaphore_82574(struct e1000_hw *hw) +{ + e1000_put_hw_semaphore_82573(hw); + mutex_unlock(&swflag_mutex); +} /** * e1000_acquire_nvm_82571 - Request for access to the EEPROM @@ -562,8 +666,6 @@ static s32 e1000_acquire_nvm_82571(struct e1000_hw *hw) switch (hw->mac.type) { case e1000_82573: - case e1000_82574: - case e1000_82583: break; default: ret_val = e1000e_acquire_nvm(hw); @@ -853,9 +955,8 @@ static s32 e1000_set_d0_lplu_state_82571(struct e1000_hw *hw, bool active) **/ static s32 e1000_reset_hw_82571(struct e1000_hw *hw) { - u32 ctrl, extcnf_ctrl, ctrl_ext, icr; + u32 ctrl, ctrl_ext, icr; s32 ret_val; - u16 i = 0; /* * Prevent the PCI-E bus from sticking if there is no TLP connection @@ -880,33 +981,33 @@ static s32 e1000_reset_hw_82571(struct e1000_hw *hw) */ switch (hw->mac.type) { case e1000_82573: + ret_val = e1000_get_hw_semaphore_82573(hw); + break; case e1000_82574: case e1000_82583: - extcnf_ctrl = er32(EXTCNF_CTRL); - extcnf_ctrl |= E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP; - - do { - ew32(EXTCNF_CTRL, extcnf_ctrl); - extcnf_ctrl = er32(EXTCNF_CTRL); - - if (extcnf_ctrl & E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP) - break; - - extcnf_ctrl |= E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP; - - msleep(2); - i++; - } while (i < MDIO_OWNERSHIP_TIMEOUT); + ret_val = e1000_get_hw_semaphore_82574(hw); break; default: break; } + if (ret_val) + e_dbg("Cannot acquire MDIO ownership\n"); ctrl = er32(CTRL); e_dbg("Issuing a global reset to MAC\n"); ew32(CTRL, ctrl | E1000_CTRL_RST); + /* Must release MDIO ownership and mutex after MAC reset. */ + switch (hw->mac.type) { + case e1000_82574: + case e1000_82583: + e1000_put_hw_semaphore_82574(hw); + break; + default: + break; + } + if (hw->nvm.type == e1000_nvm_flash_hw) { udelay(10); ctrl_ext = er32(CTRL_EXT); @@ -1431,8 +1532,10 @@ static s32 e1000_check_for_serdes_link_82571(struct e1000_hw *hw) * auto-negotiation in the TXCW register and disable * forced link in the Device Control register in an * attempt to auto-negotiate with our link partner. + * If the partner code word is null, stop forcing + * and restart auto negotiation. */ - if (rxcw & E1000_RXCW_C) { + if ((rxcw & E1000_RXCW_C) || !(rxcw & E1000_RXCW_CW)) { /* Enable autoneg, and unforce link up */ ew32(TXCW, mac->txcw); ew32(CTRL, (ctrl & ~E1000_CTRL_SLU)); diff --git a/drivers/net/e1000e/defines.h b/drivers/net/e1000e/defines.h index d3f7a9c3f973..016ea383145a 100644 --- a/drivers/net/e1000e/defines.h +++ b/drivers/net/e1000e/defines.h @@ -516,6 +516,7 @@ #define E1000_TXCW_ANE 0x80000000 /* Auto-neg enable */ /* Receive Configuration Word */ +#define E1000_RXCW_CW 0x0000ffff /* RxConfigWord mask */ #define E1000_RXCW_IV 0x08000000 /* Receive config invalid */ #define E1000_RXCW_C 0x20000000 /* Receive config */ #define E1000_RXCW_SYNCH 0x40000000 /* Receive config synch */ diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index c4ca1629f532..0adcb79e6386 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c @@ -2059,10 +2059,9 @@ int e1000e_setup_tx_resources(struct e1000_adapter *adapter) int err = -ENOMEM, size; size = sizeof(struct e1000_buffer) * tx_ring->count; - tx_ring->buffer_info = vmalloc(size); + tx_ring->buffer_info = vzalloc(size); if (!tx_ring->buffer_info) goto err; - memset(tx_ring->buffer_info, 0, size); /* round up to nearest 4K */ tx_ring->size = tx_ring->count * sizeof(struct e1000_tx_desc); @@ -2095,10 +2094,9 @@ int e1000e_setup_rx_resources(struct e1000_adapter *adapter) int i, size, desc_len, err = -ENOMEM; size = sizeof(struct e1000_buffer) * rx_ring->count; - rx_ring->buffer_info = vmalloc(size); + rx_ring->buffer_info = vzalloc(size); if (!rx_ring->buffer_info) goto err; - memset(rx_ring->buffer_info, 0, size); for (i = 0; i < rx_ring->count; i++) { buffer_info = &rx_ring->buffer_info[i]; @@ -4595,7 +4593,7 @@ dma_error: i += tx_ring->count; i--; buffer_info = &tx_ring->buffer_info[i]; - e1000_put_txbuf(adapter, buffer_info);; + e1000_put_txbuf(adapter, buffer_info); } return 0; @@ -5465,6 +5463,36 @@ static void e1000_shutdown(struct pci_dev *pdev) } #ifdef CONFIG_NET_POLL_CONTROLLER + +static irqreturn_t e1000_intr_msix(int irq, void *data) +{ + struct net_device *netdev = data; + struct e1000_adapter *adapter = netdev_priv(netdev); + int vector, msix_irq; + + if (adapter->msix_entries) { + vector = 0; + msix_irq = adapter->msix_entries[vector].vector; + disable_irq(msix_irq); + e1000_intr_msix_rx(msix_irq, netdev); + enable_irq(msix_irq); + + vector++; + msix_irq = adapter->msix_entries[vector].vector; + disable_irq(msix_irq); + e1000_intr_msix_tx(msix_irq, netdev); + enable_irq(msix_irq); + + vector++; + msix_irq = adapter->msix_entries[vector].vector; + disable_irq(msix_irq); + e1000_msix_other(msix_irq, netdev); + enable_irq(msix_irq); + } + + return IRQ_HANDLED; +} + /* * Polling 'interrupt' - used by things like netconsole to send skbs * without having to re-enable interrupts. It's not called while @@ -5474,10 +5502,21 @@ static void e1000_netpoll(struct net_device *netdev) { struct e1000_adapter *adapter = netdev_priv(netdev); - disable_irq(adapter->pdev->irq); - e1000_intr(adapter->pdev->irq, netdev); - - enable_irq(adapter->pdev->irq); + switch (adapter->int_mode) { + case E1000E_INT_MODE_MSIX: + e1000_intr_msix(adapter->pdev->irq, netdev); + break; + case E1000E_INT_MODE_MSI: + disable_irq(adapter->pdev->irq); + e1000_intr_msi(adapter->pdev->irq, netdev); + enable_irq(adapter->pdev->irq); + break; + default: /* E1000E_INT_MODE_LEGACY */ + disable_irq(adapter->pdev->irq); + e1000_intr(adapter->pdev->irq, netdev); + enable_irq(adapter->pdev->irq); + break; + } } #endif diff --git a/drivers/net/eepro.c b/drivers/net/eepro.c index 7c826319ee5a..9e19fbc2f176 100644 --- a/drivers/net/eepro.c +++ b/drivers/net/eepro.c @@ -302,7 +302,7 @@ struct eepro_local { #define ee_id_eepro10p0 0x10 /* ID for eepro/10+ */ #define ee_id_eepro10p1 0x31 -#define TX_TIMEOUT 40 +#define TX_TIMEOUT ((4*HZ)/10) /* Index to functions, as function prototypes. */ diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c index 182b2a7be8dc..a84c389d3db7 100644 --- a/drivers/net/ehea/ehea_main.c +++ b/drivers/net/ehea/ehea_main.c @@ -1496,12 +1496,10 @@ static int ehea_init_q_skba(struct ehea_q_skb_arr *q_skba, int max_q_entries) { int arr_size = sizeof(void *) * max_q_entries; - q_skba->arr = vmalloc(arr_size); + q_skba->arr = vzalloc(arr_size); if (!q_skba->arr) return -ENOMEM; - memset(q_skba->arr, 0, arr_size); - q_skba->len = max_q_entries; q_skba->index = 0; q_skba->os_skbs = 0; diff --git a/drivers/net/enic/enic.h b/drivers/net/enic/enic.h index c91d364c5527..70672541364e 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 "1.4.1.6" +#define DRV_VERSION "1.4.1.7" #define DRV_COPYRIGHT "Copyright 2008-2010 Cisco Systems, Inc" #define ENIC_BARS_MAX 6 diff --git a/drivers/net/enic/enic_main.c b/drivers/net/enic/enic_main.c index a466ef91dd43..9f293fa24768 100644 --- a/drivers/net/enic/enic_main.c +++ b/drivers/net/enic/enic_main.c @@ -2042,7 +2042,7 @@ static int enic_dev_hang_reset(struct enic *enic) static int enic_set_rsskey(struct enic *enic) { - u64 rss_key_buf_pa; + dma_addr_t rss_key_buf_pa; union vnic_rss_key *rss_key_buf_va = NULL; union vnic_rss_key rss_key = { .key[0].b = {85, 67, 83, 97, 119, 101, 115, 111, 109, 101}, @@ -2073,7 +2073,7 @@ static int enic_set_rsskey(struct enic *enic) static int enic_set_rsscpu(struct enic *enic, u8 rss_hash_bits) { - u64 rss_cpu_buf_pa; + dma_addr_t rss_cpu_buf_pa; union vnic_rss_cpu *rss_cpu_buf_va = NULL; unsigned int i; int err; diff --git a/drivers/net/ethoc.c b/drivers/net/ethoc.c index c5a2fe099a8d..b79d7e1555d5 100644 --- a/drivers/net/ethoc.c +++ b/drivers/net/ethoc.c @@ -19,6 +19,7 @@ #include <linux/platform_device.h> #include <linux/sched.h> #include <linux/slab.h> +#include <linux/of.h> #include <net/ethoc.h> static int buffer_size = 0x8000; /* 32 KBytes */ @@ -184,7 +185,6 @@ MODULE_PARM_DESC(buffer_size, "DMA buffer allocation size"); * @netdev: pointer to network device structure * @napi: NAPI structure * @msg_enable: device state flags - * @rx_lock: receive lock * @lock: device lock * @phy: attached PHY * @mdio: MDIO bus for PHY access @@ -209,7 +209,6 @@ struct ethoc { struct napi_struct napi; u32 msg_enable; - spinlock_t rx_lock; spinlock_t lock; struct phy_device *phy; @@ -413,10 +412,21 @@ static int ethoc_rx(struct net_device *dev, int limit) unsigned int entry; struct ethoc_bd bd; - entry = priv->num_tx + (priv->cur_rx % priv->num_rx); + entry = priv->num_tx + priv->cur_rx; ethoc_read_bd(priv, entry, &bd); - if (bd.stat & RX_BD_EMPTY) - break; + if (bd.stat & RX_BD_EMPTY) { + ethoc_ack_irq(priv, INT_MASK_RX); + /* If packet (interrupt) came in between checking + * BD_EMTPY and clearing the interrupt source, then we + * risk missing the packet as the RX interrupt won't + * trigger right away when we reenable it; hence, check + * BD_EMTPY here again to make sure there isn't such a + * packet waiting for us... + */ + ethoc_read_bd(priv, entry, &bd); + if (bd.stat & RX_BD_EMPTY) + break; + } if (ethoc_update_rx_stats(priv, &bd) == 0) { int size = bd.stat >> 16; @@ -446,13 +456,14 @@ static int ethoc_rx(struct net_device *dev, int limit) bd.stat &= ~RX_BD_STATS; bd.stat |= RX_BD_EMPTY; ethoc_write_bd(priv, entry, &bd); - priv->cur_rx++; + if (++priv->cur_rx == priv->num_rx) + priv->cur_rx = 0; } return count; } -static int ethoc_update_tx_stats(struct ethoc *dev, struct ethoc_bd *bd) +static void ethoc_update_tx_stats(struct ethoc *dev, struct ethoc_bd *bd) { struct net_device *netdev = dev->netdev; @@ -482,32 +493,44 @@ static int ethoc_update_tx_stats(struct ethoc *dev, struct ethoc_bd *bd) netdev->stats.collisions += (bd->stat >> 4) & 0xf; netdev->stats.tx_bytes += bd->stat >> 16; netdev->stats.tx_packets++; - return 0; } -static void ethoc_tx(struct net_device *dev) +static int ethoc_tx(struct net_device *dev, int limit) { struct ethoc *priv = netdev_priv(dev); + int count; + struct ethoc_bd bd; - spin_lock(&priv->lock); + for (count = 0; count < limit; ++count) { + unsigned int entry; - while (priv->dty_tx != priv->cur_tx) { - unsigned int entry = priv->dty_tx % priv->num_tx; - struct ethoc_bd bd; + entry = priv->dty_tx & (priv->num_tx-1); ethoc_read_bd(priv, entry, &bd); - if (bd.stat & TX_BD_READY) - break; - entry = (++priv->dty_tx) % priv->num_tx; - (void)ethoc_update_tx_stats(priv, &bd); + if (bd.stat & TX_BD_READY || (priv->dty_tx == priv->cur_tx)) { + ethoc_ack_irq(priv, INT_MASK_TX); + /* If interrupt came in between reading in the BD + * and clearing the interrupt source, then we risk + * missing the event as the TX interrupt won't trigger + * right away when we reenable it; hence, check + * BD_EMPTY here again to make sure there isn't such an + * event pending... + */ + ethoc_read_bd(priv, entry, &bd); + if (bd.stat & TX_BD_READY || + (priv->dty_tx == priv->cur_tx)) + break; + } + + ethoc_update_tx_stats(priv, &bd); + priv->dty_tx++; } if ((priv->cur_tx - priv->dty_tx) <= (priv->num_tx / 2)) netif_wake_queue(dev); - ethoc_ack_irq(priv, INT_MASK_TX); - spin_unlock(&priv->lock); + return count; } static irqreturn_t ethoc_interrupt(int irq, void *dev_id) @@ -515,32 +538,38 @@ static irqreturn_t ethoc_interrupt(int irq, void *dev_id) struct net_device *dev = dev_id; struct ethoc *priv = netdev_priv(dev); u32 pending; - - ethoc_disable_irq(priv, INT_MASK_ALL); + u32 mask; + + /* Figure out what triggered the interrupt... + * The tricky bit here is that the interrupt source bits get + * set in INT_SOURCE for an event irregardless of whether that + * event is masked or not. Thus, in order to figure out what + * triggered the interrupt, we need to remove the sources + * for all events that are currently masked. This behaviour + * is not particularly well documented but reasonable... + */ + mask = ethoc_read(priv, INT_MASK); pending = ethoc_read(priv, INT_SOURCE); + pending &= mask; + if (unlikely(pending == 0)) { - ethoc_enable_irq(priv, INT_MASK_ALL); return IRQ_NONE; } ethoc_ack_irq(priv, pending); + /* We always handle the dropped packet interrupt */ if (pending & INT_MASK_BUSY) { dev_err(&dev->dev, "packet dropped\n"); dev->stats.rx_dropped++; } - if (pending & INT_MASK_RX) { - if (napi_schedule_prep(&priv->napi)) - __napi_schedule(&priv->napi); - } else { - ethoc_enable_irq(priv, INT_MASK_RX); + /* Handle receive/transmit event by switching to polling */ + if (pending & (INT_MASK_TX | INT_MASK_RX)) { + ethoc_disable_irq(priv, INT_MASK_TX | INT_MASK_RX); + napi_schedule(&priv->napi); } - if (pending & INT_MASK_TX) - ethoc_tx(dev); - - ethoc_enable_irq(priv, INT_MASK_ALL & ~INT_MASK_RX); return IRQ_HANDLED; } @@ -566,26 +595,29 @@ static int ethoc_get_mac_address(struct net_device *dev, void *addr) static int ethoc_poll(struct napi_struct *napi, int budget) { struct ethoc *priv = container_of(napi, struct ethoc, napi); - int work_done = 0; + int rx_work_done = 0; + int tx_work_done = 0; + + rx_work_done = ethoc_rx(priv->netdev, budget); + tx_work_done = ethoc_tx(priv->netdev, budget); - work_done = ethoc_rx(priv->netdev, budget); - if (work_done < budget) { - ethoc_enable_irq(priv, INT_MASK_RX); + if (rx_work_done < budget && tx_work_done < budget) { napi_complete(napi); + ethoc_enable_irq(priv, INT_MASK_TX | INT_MASK_RX); } - return work_done; + return rx_work_done; } static int ethoc_mdio_read(struct mii_bus *bus, int phy, int reg) { - unsigned long timeout = jiffies + ETHOC_MII_TIMEOUT; struct ethoc *priv = bus->priv; + int i; ethoc_write(priv, MIIADDRESS, MIIADDRESS_ADDR(phy, reg)); ethoc_write(priv, MIICOMMAND, MIICOMMAND_READ); - while (time_before(jiffies, timeout)) { + for (i=0; i < 5; i++) { u32 status = ethoc_read(priv, MIISTATUS); if (!(status & MIISTATUS_BUSY)) { u32 data = ethoc_read(priv, MIIRX_DATA); @@ -593,8 +625,7 @@ static int ethoc_mdio_read(struct mii_bus *bus, int phy, int reg) ethoc_write(priv, MIICOMMAND, 0); return data; } - - schedule(); + usleep_range(100,200); } return -EBUSY; @@ -602,22 +633,21 @@ static int ethoc_mdio_read(struct mii_bus *bus, int phy, int reg) static int ethoc_mdio_write(struct mii_bus *bus, int phy, int reg, u16 val) { - unsigned long timeout = jiffies + ETHOC_MII_TIMEOUT; struct ethoc *priv = bus->priv; + int i; ethoc_write(priv, MIIADDRESS, MIIADDRESS_ADDR(phy, reg)); ethoc_write(priv, MIITX_DATA, val); ethoc_write(priv, MIICOMMAND, MIICOMMAND_WRITE); - while (time_before(jiffies, timeout)) { + for (i=0; i < 5; i++) { u32 stat = ethoc_read(priv, MIISTATUS); if (!(stat & MIISTATUS_BUSY)) { /* reset MII command register */ ethoc_write(priv, MIICOMMAND, 0); return 0; } - - schedule(); + usleep_range(100,200); } return -EBUSY; @@ -971,9 +1001,17 @@ static int __devinit ethoc_probe(struct platform_device *pdev) /* calculate the number of TX/RX buffers, maximum 128 supported */ num_bd = min_t(unsigned int, 128, (netdev->mem_end - netdev->mem_start + 1) / ETHOC_BUFSIZ); - priv->num_tx = max(2, num_bd / 4); + if (num_bd < 4) { + ret = -ENODEV; + goto error; + } + /* num_tx must be a power of two */ + priv->num_tx = rounddown_pow_of_two(num_bd >> 1); priv->num_rx = num_bd - priv->num_tx; + dev_dbg(&pdev->dev, "ethoc: num_tx: %d num_rx: %d\n", + priv->num_tx, priv->num_rx); + priv->vma = devm_kzalloc(&pdev->dev, num_bd*sizeof(void*), GFP_KERNEL); if (!priv->vma) { ret = -ENOMEM; @@ -982,10 +1020,23 @@ static int __devinit ethoc_probe(struct platform_device *pdev) /* Allow the platform setup code to pass in a MAC address. */ if (pdev->dev.platform_data) { - struct ethoc_platform_data *pdata = - (struct ethoc_platform_data *)pdev->dev.platform_data; + struct ethoc_platform_data *pdata = pdev->dev.platform_data; memcpy(netdev->dev_addr, pdata->hwaddr, IFHWADDRLEN); priv->phy_id = pdata->phy_id; + } else { + priv->phy_id = -1; + +#ifdef CONFIG_OF + { + const uint8_t* mac; + + mac = of_get_property(pdev->dev.of_node, + "local-mac-address", + NULL); + if (mac) + memcpy(netdev->dev_addr, mac, IFHWADDRLEN); + } +#endif } /* Check that the given MAC address is valid. If it isn't, read the @@ -1046,7 +1097,6 @@ static int __devinit ethoc_probe(struct platform_device *pdev) /* setup NAPI */ netif_napi_add(netdev, &priv->napi, ethoc_poll, 64); - spin_lock_init(&priv->rx_lock); spin_lock_init(&priv->lock); ret = register_netdev(netdev); @@ -1113,6 +1163,16 @@ static int ethoc_resume(struct platform_device *pdev) # define ethoc_resume NULL #endif +#ifdef CONFIG_OF +static struct of_device_id ethoc_match[] = { + { + .compatible = "opencores,ethoc", + }, + {}, +}; +MODULE_DEVICE_TABLE(of, ethoc_match); +#endif + static struct platform_driver ethoc_driver = { .probe = ethoc_probe, .remove = __devexit_p(ethoc_remove), @@ -1120,6 +1180,10 @@ static struct platform_driver ethoc_driver = { .resume = ethoc_resume, .driver = { .name = "ethoc", + .owner = THIS_MODULE, +#ifdef CONFIG_OF + .of_match_table = ethoc_match, +#endif }, }; diff --git a/drivers/net/fec_mpc52xx.c b/drivers/net/fec_mpc52xx.c index e9f5d030bc26..50c1213f61fe 100644 --- a/drivers/net/fec_mpc52xx.c +++ b/drivers/net/fec_mpc52xx.c @@ -366,9 +366,8 @@ static irqreturn_t mpc52xx_fec_tx_interrupt(int irq, void *dev_id) { struct net_device *dev = dev_id; struct mpc52xx_fec_priv *priv = netdev_priv(dev); - unsigned long flags; - spin_lock_irqsave(&priv->lock, flags); + spin_lock(&priv->lock); while (bcom_buffer_done(priv->tx_dmatsk)) { struct sk_buff *skb; struct bcom_fec_bd *bd; @@ -379,7 +378,7 @@ static irqreturn_t mpc52xx_fec_tx_interrupt(int irq, void *dev_id) dev_kfree_skb_irq(skb); } - spin_unlock_irqrestore(&priv->lock, flags); + spin_unlock(&priv->lock); netif_wake_queue(dev); @@ -395,9 +394,8 @@ static irqreturn_t mpc52xx_fec_rx_interrupt(int irq, void *dev_id) struct bcom_fec_bd *bd; u32 status, physaddr; int length; - unsigned long flags; - spin_lock_irqsave(&priv->lock, flags); + spin_lock(&priv->lock); while (bcom_buffer_done(priv->rx_dmatsk)) { @@ -429,7 +427,7 @@ static irqreturn_t mpc52xx_fec_rx_interrupt(int irq, void *dev_id) /* Process the received skb - Drop the spin lock while * calling into the network stack */ - spin_unlock_irqrestore(&priv->lock, flags); + spin_unlock(&priv->lock); dma_unmap_single(dev->dev.parent, physaddr, rskb->len, DMA_FROM_DEVICE); @@ -438,10 +436,10 @@ static irqreturn_t mpc52xx_fec_rx_interrupt(int irq, void *dev_id) rskb->protocol = eth_type_trans(rskb, dev); netif_rx(rskb); - spin_lock_irqsave(&priv->lock, flags); + spin_lock(&priv->lock); } - spin_unlock_irqrestore(&priv->lock, flags); + spin_unlock(&priv->lock); return IRQ_HANDLED; } @@ -452,7 +450,6 @@ static irqreturn_t mpc52xx_fec_interrupt(int irq, void *dev_id) struct mpc52xx_fec_priv *priv = netdev_priv(dev); struct mpc52xx_fec __iomem *fec = priv->fec; u32 ievent; - unsigned long flags; ievent = in_be32(&fec->ievent); @@ -470,9 +467,9 @@ static irqreturn_t mpc52xx_fec_interrupt(int irq, void *dev_id) if (net_ratelimit() && (ievent & FEC_IEVENT_XFIFO_ERROR)) dev_warn(&dev->dev, "FEC_IEVENT_XFIFO_ERROR\n"); - spin_lock_irqsave(&priv->lock, flags); + spin_lock(&priv->lock); mpc52xx_fec_reset(dev); - spin_unlock_irqrestore(&priv->lock, flags); + spin_unlock(&priv->lock); return IRQ_HANDLED; } diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index 0fa1776563a3..cd2d72d825df 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c @@ -39,6 +39,9 @@ * DEV_NEED_TIMERIRQ will not harm you on sane hardware, only generating a few * superfluous timer interrupts from the nic. */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #define FORCEDETH_VERSION "0.64" #define DRV_NAME "forcedeth" @@ -60,18 +63,12 @@ #include <linux/if_vlan.h> #include <linux/dma-mapping.h> #include <linux/slab.h> +#include <linux/uaccess.h> +#include <linux/io.h> #include <asm/irq.h> -#include <asm/io.h> -#include <asm/uaccess.h> #include <asm/system.h> -#if 0 -#define dprintk printk -#else -#define dprintk(x...) do { } while (0) -#endif - #define TX_WORK_PER_LOOP 64 #define RX_WORK_PER_LOOP 64 @@ -186,9 +183,9 @@ enum { NvRegSlotTime = 0x9c, #define NVREG_SLOTTIME_LEGBF_ENABLED 0x80000000 #define NVREG_SLOTTIME_10_100_FULL 0x00007f00 -#define NVREG_SLOTTIME_1000_FULL 0x0003ff00 +#define NVREG_SLOTTIME_1000_FULL 0x0003ff00 #define NVREG_SLOTTIME_HALF 0x0000ff00 -#define NVREG_SLOTTIME_DEFAULT 0x00007f00 +#define NVREG_SLOTTIME_DEFAULT 0x00007f00 #define NVREG_SLOTTIME_MASK 0x000000ff NvRegTxDeferral = 0xA0, @@ -297,7 +294,7 @@ enum { #define NVREG_WAKEUPFLAGS_ENABLE 0x1111 NvRegMgmtUnitGetVersion = 0x204, -#define NVREG_MGMTUNITGETVERSION 0x01 +#define NVREG_MGMTUNITGETVERSION 0x01 NvRegMgmtUnitVersion = 0x208, #define NVREG_MGMTUNITVERSION 0x08 NvRegPowerCap = 0x268, @@ -368,8 +365,8 @@ struct ring_desc_ex { }; union ring_type { - struct ring_desc* orig; - struct ring_desc_ex* ex; + struct ring_desc *orig; + struct ring_desc_ex *ex; }; #define FLAG_MASK_V1 0xffff0000 @@ -444,10 +441,10 @@ union ring_type { #define NV_RX3_VLAN_TAG_MASK (0x0000FFFF) /* Miscelaneous hardware related defines: */ -#define NV_PCI_REGSZ_VER1 0x270 -#define NV_PCI_REGSZ_VER2 0x2d4 -#define NV_PCI_REGSZ_VER3 0x604 -#define NV_PCI_REGSZ_MAX 0x604 +#define NV_PCI_REGSZ_VER1 0x270 +#define NV_PCI_REGSZ_VER2 0x2d4 +#define NV_PCI_REGSZ_VER3 0x604 +#define NV_PCI_REGSZ_MAX 0x604 /* various timeout delays: all in usec */ #define NV_TXRX_RESET_DELAY 4 @@ -717,7 +714,7 @@ static const struct register_test nv_registers_test[] = { { NvRegMulticastAddrA, 0xffffffff }, { NvRegTxWatermark, 0x0ff }, { NvRegWakeUpFlags, 0x07777 }, - { 0,0 } + { 0, 0 } }; struct nv_skb_map { @@ -911,7 +908,7 @@ static int phy_cross = NV_CROSSOVER_DETECTION_DISABLED; * Power down phy when interface is down (persists through reboot; * older Linux and other OSes may not power it up again) */ -static int phy_power_down = 0; +static int phy_power_down; static inline struct fe_priv *get_nvpriv(struct net_device *dev) { @@ -948,7 +945,7 @@ static bool nv_optimized(struct fe_priv *np) } static int reg_delay(struct net_device *dev, int offset, u32 mask, u32 target, - int delay, int delaymax, const char *msg) + int delay, int delaymax) { u8 __iomem *base = get_hwbase(dev); @@ -956,11 +953,8 @@ static int reg_delay(struct net_device *dev, int offset, u32 mask, u32 target, do { udelay(delay); delaymax -= delay; - if (delaymax < 0) { - if (msg) - printk("%s", msg); + if (delaymax < 0) return 1; - } } while ((readl(base + offset) & mask) != target); return 0; } @@ -984,12 +978,10 @@ static void setup_hw_rings(struct net_device *dev, int rxtx_flags) u8 __iomem *base = get_hwbase(dev); if (!nv_optimized(np)) { - if (rxtx_flags & NV_SETUP_RX_RING) { + if (rxtx_flags & NV_SETUP_RX_RING) writel(dma_low(np->ring_addr), base + NvRegRxRingPhysAddr); - } - if (rxtx_flags & NV_SETUP_TX_RING) { + if (rxtx_flags & NV_SETUP_TX_RING) writel(dma_low(np->ring_addr + np->rx_ring_size*sizeof(struct ring_desc)), base + NvRegTxRingPhysAddr); - } } else { if (rxtx_flags & NV_SETUP_RX_RING) { writel(dma_low(np->ring_addr), base + NvRegRxRingPhysAddr); @@ -1015,10 +1007,8 @@ static void free_rings(struct net_device *dev) pci_free_consistent(np->pci_dev, sizeof(struct ring_desc_ex) * (np->rx_ring_size + np->tx_ring_size), np->rx_ring.ex, np->ring_addr); } - if (np->rx_skb) - kfree(np->rx_skb); - if (np->tx_skb) - kfree(np->tx_skb); + kfree(np->rx_skb); + kfree(np->tx_skb); } static int using_multi_irqs(struct net_device *dev) @@ -1145,23 +1135,15 @@ static int mii_rw(struct net_device *dev, int addr, int miireg, int value) writel(reg, base + NvRegMIIControl); if (reg_delay(dev, NvRegMIIControl, NVREG_MIICTL_INUSE, 0, - NV_MIIPHY_DELAY, NV_MIIPHY_DELAYMAX, NULL)) { - dprintk(KERN_DEBUG "%s: mii_rw of reg %d at PHY %d timed out.\n", - dev->name, miireg, addr); + NV_MIIPHY_DELAY, NV_MIIPHY_DELAYMAX)) { retval = -1; } else if (value != MII_READ) { /* it was a write operation - fewer failures are detectable */ - dprintk(KERN_DEBUG "%s: mii_rw wrote 0x%x to reg %d at PHY %d\n", - dev->name, value, miireg, addr); retval = 0; } else if (readl(base + NvRegMIIStatus) & NVREG_MIISTAT_ERROR) { - dprintk(KERN_DEBUG "%s: mii_rw of reg %d at PHY %d failed.\n", - dev->name, miireg, addr); retval = -1; } else { retval = readl(base + NvRegMIIData); - dprintk(KERN_DEBUG "%s: mii_rw read from reg %d at PHY %d: 0x%x.\n", - dev->name, miireg, addr, retval); } return retval; @@ -1174,16 +1156,15 @@ static int phy_reset(struct net_device *dev, u32 bmcr_setup) unsigned int tries = 0; miicontrol = BMCR_RESET | bmcr_setup; - if (mii_rw(dev, np->phyaddr, MII_BMCR, miicontrol)) { + if (mii_rw(dev, np->phyaddr, MII_BMCR, miicontrol)) return -1; - } /* wait for 500ms */ msleep(500); /* must wait till reset is deasserted */ while (miicontrol & BMCR_RESET) { - msleep(10); + usleep_range(10000, 20000); miicontrol = mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ); /* FIXME: 100 tries seem excessive */ if (tries++ > 100) @@ -1192,106 +1173,239 @@ static int phy_reset(struct net_device *dev, u32 bmcr_setup) return 0; } +static int init_realtek_8211b(struct net_device *dev, struct fe_priv *np) +{ + static const struct { + int reg; + int init; + } ri[] = { + { PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1 }, + { PHY_REALTEK_INIT_REG2, PHY_REALTEK_INIT2 }, + { PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT3 }, + { PHY_REALTEK_INIT_REG3, PHY_REALTEK_INIT4 }, + { PHY_REALTEK_INIT_REG4, PHY_REALTEK_INIT5 }, + { PHY_REALTEK_INIT_REG5, PHY_REALTEK_INIT6 }, + { PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1 }, + }; + int i; + + for (i = 0; i < ARRAY_SIZE(ri); i++) { + if (mii_rw(dev, np->phyaddr, ri[i].reg, ri[i].init)) + return PHY_ERROR; + } + + return 0; +} + +static int init_realtek_8211c(struct net_device *dev, struct fe_priv *np) +{ + u32 reg; + u8 __iomem *base = get_hwbase(dev); + u32 powerstate = readl(base + NvRegPowerState2); + + /* need to perform hw phy reset */ + powerstate |= NVREG_POWERSTATE2_PHY_RESET; + writel(powerstate, base + NvRegPowerState2); + msleep(25); + + powerstate &= ~NVREG_POWERSTATE2_PHY_RESET; + writel(powerstate, base + NvRegPowerState2); + msleep(25); + + reg = mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG6, MII_READ); + reg |= PHY_REALTEK_INIT9; + if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG6, reg)) + return PHY_ERROR; + if (mii_rw(dev, np->phyaddr, + PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT10)) + return PHY_ERROR; + reg = mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG7, MII_READ); + if (!(reg & PHY_REALTEK_INIT11)) { + reg |= PHY_REALTEK_INIT11; + if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG7, reg)) + return PHY_ERROR; + } + if (mii_rw(dev, np->phyaddr, + PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1)) + return PHY_ERROR; + + return 0; +} + +static int init_realtek_8201(struct net_device *dev, struct fe_priv *np) +{ + u32 phy_reserved; + + if (np->driver_data & DEV_NEED_PHY_INIT_FIX) { + phy_reserved = mii_rw(dev, np->phyaddr, + PHY_REALTEK_INIT_REG6, MII_READ); + phy_reserved |= PHY_REALTEK_INIT7; + if (mii_rw(dev, np->phyaddr, + PHY_REALTEK_INIT_REG6, phy_reserved)) + return PHY_ERROR; + } + + return 0; +} + +static int init_realtek_8201_cross(struct net_device *dev, struct fe_priv *np) +{ + u32 phy_reserved; + + if (phy_cross == NV_CROSSOVER_DETECTION_DISABLED) { + if (mii_rw(dev, np->phyaddr, + PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT3)) + return PHY_ERROR; + phy_reserved = mii_rw(dev, np->phyaddr, + PHY_REALTEK_INIT_REG2, MII_READ); + phy_reserved &= ~PHY_REALTEK_INIT_MSK1; + phy_reserved |= PHY_REALTEK_INIT3; + if (mii_rw(dev, np->phyaddr, + PHY_REALTEK_INIT_REG2, phy_reserved)) + return PHY_ERROR; + if (mii_rw(dev, np->phyaddr, + PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1)) + return PHY_ERROR; + } + + return 0; +} + +static int init_cicada(struct net_device *dev, struct fe_priv *np, + u32 phyinterface) +{ + u32 phy_reserved; + + if (phyinterface & PHY_RGMII) { + phy_reserved = mii_rw(dev, np->phyaddr, MII_RESV1, MII_READ); + phy_reserved &= ~(PHY_CICADA_INIT1 | PHY_CICADA_INIT2); + phy_reserved |= (PHY_CICADA_INIT3 | PHY_CICADA_INIT4); + if (mii_rw(dev, np->phyaddr, MII_RESV1, phy_reserved)) + return PHY_ERROR; + phy_reserved = mii_rw(dev, np->phyaddr, MII_NCONFIG, MII_READ); + phy_reserved |= PHY_CICADA_INIT5; + if (mii_rw(dev, np->phyaddr, MII_NCONFIG, phy_reserved)) + return PHY_ERROR; + } + phy_reserved = mii_rw(dev, np->phyaddr, MII_SREVISION, MII_READ); + phy_reserved |= PHY_CICADA_INIT6; + if (mii_rw(dev, np->phyaddr, MII_SREVISION, phy_reserved)) + return PHY_ERROR; + + return 0; +} + +static int init_vitesse(struct net_device *dev, struct fe_priv *np) +{ + u32 phy_reserved; + + if (mii_rw(dev, np->phyaddr, + PHY_VITESSE_INIT_REG1, PHY_VITESSE_INIT1)) + return PHY_ERROR; + if (mii_rw(dev, np->phyaddr, + PHY_VITESSE_INIT_REG2, PHY_VITESSE_INIT2)) + return PHY_ERROR; + phy_reserved = mii_rw(dev, np->phyaddr, + PHY_VITESSE_INIT_REG4, MII_READ); + if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG4, phy_reserved)) + return PHY_ERROR; + phy_reserved = mii_rw(dev, np->phyaddr, + PHY_VITESSE_INIT_REG3, MII_READ); + phy_reserved &= ~PHY_VITESSE_INIT_MSK1; + phy_reserved |= PHY_VITESSE_INIT3; + if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG3, phy_reserved)) + return PHY_ERROR; + if (mii_rw(dev, np->phyaddr, + PHY_VITESSE_INIT_REG2, PHY_VITESSE_INIT4)) + return PHY_ERROR; + if (mii_rw(dev, np->phyaddr, + PHY_VITESSE_INIT_REG2, PHY_VITESSE_INIT5)) + return PHY_ERROR; + phy_reserved = mii_rw(dev, np->phyaddr, + PHY_VITESSE_INIT_REG4, MII_READ); + phy_reserved &= ~PHY_VITESSE_INIT_MSK1; + phy_reserved |= PHY_VITESSE_INIT3; + if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG4, phy_reserved)) + return PHY_ERROR; + phy_reserved = mii_rw(dev, np->phyaddr, + PHY_VITESSE_INIT_REG3, MII_READ); + if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG3, phy_reserved)) + return PHY_ERROR; + if (mii_rw(dev, np->phyaddr, + PHY_VITESSE_INIT_REG2, PHY_VITESSE_INIT6)) + return PHY_ERROR; + if (mii_rw(dev, np->phyaddr, + PHY_VITESSE_INIT_REG2, PHY_VITESSE_INIT7)) + return PHY_ERROR; + phy_reserved = mii_rw(dev, np->phyaddr, + PHY_VITESSE_INIT_REG4, MII_READ); + if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG4, phy_reserved)) + return PHY_ERROR; + phy_reserved = mii_rw(dev, np->phyaddr, + PHY_VITESSE_INIT_REG3, MII_READ); + phy_reserved &= ~PHY_VITESSE_INIT_MSK2; + phy_reserved |= PHY_VITESSE_INIT8; + if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG3, phy_reserved)) + return PHY_ERROR; + if (mii_rw(dev, np->phyaddr, + PHY_VITESSE_INIT_REG2, PHY_VITESSE_INIT9)) + return PHY_ERROR; + if (mii_rw(dev, np->phyaddr, + PHY_VITESSE_INIT_REG1, PHY_VITESSE_INIT10)) + return PHY_ERROR; + + return 0; +} + static int phy_init(struct net_device *dev) { struct fe_priv *np = get_nvpriv(dev); u8 __iomem *base = get_hwbase(dev); - u32 phyinterface, phy_reserved, mii_status, mii_control, mii_control_1000,reg; + u32 phyinterface; + u32 mii_status, mii_control, mii_control_1000, reg; /* phy errata for E3016 phy */ if (np->phy_model == PHY_MODEL_MARVELL_E3016) { reg = mii_rw(dev, np->phyaddr, MII_NCONFIG, MII_READ); reg &= ~PHY_MARVELL_E3016_INITMASK; if (mii_rw(dev, np->phyaddr, MII_NCONFIG, reg)) { - printk(KERN_INFO "%s: phy write to errata reg failed.\n", pci_name(np->pci_dev)); + netdev_info(dev, "%s: phy write to errata reg failed\n", + pci_name(np->pci_dev)); return PHY_ERROR; } } if (np->phy_oui == PHY_OUI_REALTEK) { if (np->phy_model == PHY_MODEL_REALTEK_8211 && np->phy_rev == PHY_REV_REALTEK_8211B) { - if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1)) { - printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); - return PHY_ERROR; - } - if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG2, PHY_REALTEK_INIT2)) { - printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); - return PHY_ERROR; - } - if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT3)) { - printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); + if (init_realtek_8211b(dev, np)) { + netdev_info(dev, "%s: phy init failed\n", + pci_name(np->pci_dev)); return PHY_ERROR; } - if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG3, PHY_REALTEK_INIT4)) { - printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); + } else if (np->phy_model == PHY_MODEL_REALTEK_8211 && + np->phy_rev == PHY_REV_REALTEK_8211C) { + if (init_realtek_8211c(dev, np)) { + netdev_info(dev, "%s: phy init failed\n", + pci_name(np->pci_dev)); return PHY_ERROR; } - if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG4, PHY_REALTEK_INIT5)) { - printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); + } else if (np->phy_model == PHY_MODEL_REALTEK_8201) { + if (init_realtek_8201(dev, np)) { + netdev_info(dev, "%s: phy init failed\n", + pci_name(np->pci_dev)); return PHY_ERROR; } - if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG5, PHY_REALTEK_INIT6)) { - printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); - return PHY_ERROR; - } - if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1)) { - printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); - return PHY_ERROR; - } - } - if (np->phy_model == PHY_MODEL_REALTEK_8211 && - np->phy_rev == PHY_REV_REALTEK_8211C) { - u32 powerstate = readl(base + NvRegPowerState2); - - /* need to perform hw phy reset */ - powerstate |= NVREG_POWERSTATE2_PHY_RESET; - writel(powerstate, base + NvRegPowerState2); - msleep(25); - - powerstate &= ~NVREG_POWERSTATE2_PHY_RESET; - writel(powerstate, base + NvRegPowerState2); - msleep(25); - - reg = mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG6, MII_READ); - reg |= PHY_REALTEK_INIT9; - if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG6, reg)) { - printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); - return PHY_ERROR; - } - if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT10)) { - printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); - return PHY_ERROR; - } - reg = mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG7, MII_READ); - if (!(reg & PHY_REALTEK_INIT11)) { - reg |= PHY_REALTEK_INIT11; - if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG7, reg)) { - printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); - return PHY_ERROR; - } - } - if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1)) { - printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); - return PHY_ERROR; - } - } - if (np->phy_model == PHY_MODEL_REALTEK_8201) { - if (np->driver_data & DEV_NEED_PHY_INIT_FIX) { - phy_reserved = mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG6, MII_READ); - phy_reserved |= PHY_REALTEK_INIT7; - if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG6, phy_reserved)) { - printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); - return PHY_ERROR; - } - } } } /* set advertise register */ reg = mii_rw(dev, np->phyaddr, MII_ADVERTISE, MII_READ); - reg |= (ADVERTISE_10HALF|ADVERTISE_10FULL|ADVERTISE_100HALF|ADVERTISE_100FULL|ADVERTISE_PAUSE_ASYM|ADVERTISE_PAUSE_CAP); + reg |= (ADVERTISE_10HALF | ADVERTISE_10FULL | + ADVERTISE_100HALF | ADVERTISE_100FULL | + ADVERTISE_PAUSE_ASYM | ADVERTISE_PAUSE_CAP); if (mii_rw(dev, np->phyaddr, MII_ADVERTISE, reg)) { - printk(KERN_INFO "%s: phy write to advertise failed.\n", pci_name(np->pci_dev)); + netdev_info(dev, "%s: phy write to advertise failed\n", + pci_name(np->pci_dev)); return PHY_ERROR; } @@ -1302,7 +1416,8 @@ static int phy_init(struct net_device *dev) mii_status = mii_rw(dev, np->phyaddr, MII_BMSR, MII_READ); if (mii_status & PHY_GIGABIT) { np->gigabit = PHY_GIGABIT; - mii_control_1000 = mii_rw(dev, np->phyaddr, MII_CTRL1000, MII_READ); + mii_control_1000 = mii_rw(dev, np->phyaddr, + MII_CTRL1000, MII_READ); mii_control_1000 &= ~ADVERTISE_1000HALF; if (phyinterface & PHY_RGMII) mii_control_1000 |= ADVERTISE_1000FULL; @@ -1310,11 +1425,11 @@ static int phy_init(struct net_device *dev) mii_control_1000 &= ~ADVERTISE_1000FULL; if (mii_rw(dev, np->phyaddr, MII_CTRL1000, mii_control_1000)) { - printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); + netdev_info(dev, "%s: phy init failed\n", + pci_name(np->pci_dev)); return PHY_ERROR; } - } - else + } else np->gigabit = 0; mii_control = mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ); @@ -1326,7 +1441,8 @@ static int phy_init(struct net_device *dev) /* start autoneg since we already performed hw reset above */ mii_control |= BMCR_ANRESTART; if (mii_rw(dev, np->phyaddr, MII_BMCR, mii_control)) { - printk(KERN_INFO "%s: phy init failed\n", pci_name(np->pci_dev)); + netdev_info(dev, "%s: phy init failed\n", + pci_name(np->pci_dev)); return PHY_ERROR; } } else { @@ -1334,165 +1450,42 @@ static int phy_init(struct net_device *dev) * (certain phys need bmcr to be setup with reset) */ if (phy_reset(dev, mii_control)) { - printk(KERN_INFO "%s: phy reset failed\n", pci_name(np->pci_dev)); + netdev_info(dev, "%s: phy reset failed\n", + pci_name(np->pci_dev)); return PHY_ERROR; } } /* phy vendor specific configuration */ - if ((np->phy_oui == PHY_OUI_CICADA) && (phyinterface & PHY_RGMII) ) { - phy_reserved = mii_rw(dev, np->phyaddr, MII_RESV1, MII_READ); - phy_reserved &= ~(PHY_CICADA_INIT1 | PHY_CICADA_INIT2); - phy_reserved |= (PHY_CICADA_INIT3 | PHY_CICADA_INIT4); - if (mii_rw(dev, np->phyaddr, MII_RESV1, phy_reserved)) { - printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); - return PHY_ERROR; - } - phy_reserved = mii_rw(dev, np->phyaddr, MII_NCONFIG, MII_READ); - phy_reserved |= PHY_CICADA_INIT5; - if (mii_rw(dev, np->phyaddr, MII_NCONFIG, phy_reserved)) { - printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); - return PHY_ERROR; - } - } - if (np->phy_oui == PHY_OUI_CICADA) { - phy_reserved = mii_rw(dev, np->phyaddr, MII_SREVISION, MII_READ); - phy_reserved |= PHY_CICADA_INIT6; - if (mii_rw(dev, np->phyaddr, MII_SREVISION, phy_reserved)) { - printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); - return PHY_ERROR; - } - } - if (np->phy_oui == PHY_OUI_VITESSE) { - if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG1, PHY_VITESSE_INIT1)) { - printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); - return PHY_ERROR; - } - if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG2, PHY_VITESSE_INIT2)) { - printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); - return PHY_ERROR; - } - phy_reserved = mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG4, MII_READ); - if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG4, phy_reserved)) { - printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); - return PHY_ERROR; - } - phy_reserved = mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG3, MII_READ); - phy_reserved &= ~PHY_VITESSE_INIT_MSK1; - phy_reserved |= PHY_VITESSE_INIT3; - if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG3, phy_reserved)) { - printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); - return PHY_ERROR; - } - if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG2, PHY_VITESSE_INIT4)) { - printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); - return PHY_ERROR; - } - if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG2, PHY_VITESSE_INIT5)) { - printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); - return PHY_ERROR; - } - phy_reserved = mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG4, MII_READ); - phy_reserved &= ~PHY_VITESSE_INIT_MSK1; - phy_reserved |= PHY_VITESSE_INIT3; - if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG4, phy_reserved)) { - printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); - return PHY_ERROR; - } - phy_reserved = mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG3, MII_READ); - if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG3, phy_reserved)) { - printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); + if ((np->phy_oui == PHY_OUI_CICADA)) { + if (init_cicada(dev, np, phyinterface)) { + netdev_info(dev, "%s: phy init failed\n", + pci_name(np->pci_dev)); return PHY_ERROR; } - if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG2, PHY_VITESSE_INIT6)) { - printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); + } else if (np->phy_oui == PHY_OUI_VITESSE) { + if (init_vitesse(dev, np)) { + netdev_info(dev, "%s: phy init failed\n", + pci_name(np->pci_dev)); return PHY_ERROR; } - if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG2, PHY_VITESSE_INIT7)) { - printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); - return PHY_ERROR; - } - phy_reserved = mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG4, MII_READ); - if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG4, phy_reserved)) { - printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); - return PHY_ERROR; - } - phy_reserved = mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG3, MII_READ); - phy_reserved &= ~PHY_VITESSE_INIT_MSK2; - phy_reserved |= PHY_VITESSE_INIT8; - if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG3, phy_reserved)) { - printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); - return PHY_ERROR; - } - if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG2, PHY_VITESSE_INIT9)) { - printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); - return PHY_ERROR; - } - if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG1, PHY_VITESSE_INIT10)) { - printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); - return PHY_ERROR; - } - } - if (np->phy_oui == PHY_OUI_REALTEK) { + } else if (np->phy_oui == PHY_OUI_REALTEK) { if (np->phy_model == PHY_MODEL_REALTEK_8211 && np->phy_rev == PHY_REV_REALTEK_8211B) { /* reset could have cleared these out, set them back */ - if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1)) { - printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); - return PHY_ERROR; - } - if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG2, PHY_REALTEK_INIT2)) { - printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); - return PHY_ERROR; - } - if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT3)) { - printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); - return PHY_ERROR; - } - if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG3, PHY_REALTEK_INIT4)) { - printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); - return PHY_ERROR; - } - if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG4, PHY_REALTEK_INIT5)) { - printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); - return PHY_ERROR; - } - if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG5, PHY_REALTEK_INIT6)) { - printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); + if (init_realtek_8211b(dev, np)) { + netdev_info(dev, "%s: phy init failed\n", + pci_name(np->pci_dev)); return PHY_ERROR; } - if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1)) { - printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); + } else if (np->phy_model == PHY_MODEL_REALTEK_8201) { + if (init_realtek_8201(dev, np) || + init_realtek_8201_cross(dev, np)) { + netdev_info(dev, "%s: phy init failed\n", + pci_name(np->pci_dev)); return PHY_ERROR; } } - if (np->phy_model == PHY_MODEL_REALTEK_8201) { - if (np->driver_data & DEV_NEED_PHY_INIT_FIX) { - phy_reserved = mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG6, MII_READ); - phy_reserved |= PHY_REALTEK_INIT7; - if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG6, phy_reserved)) { - printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); - return PHY_ERROR; - } - } - if (phy_cross == NV_CROSSOVER_DETECTION_DISABLED) { - if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT3)) { - printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); - return PHY_ERROR; - } - phy_reserved = mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG2, MII_READ); - phy_reserved &= ~PHY_REALTEK_INIT_MSK1; - phy_reserved |= PHY_REALTEK_INIT3; - if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG2, phy_reserved)) { - printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); - return PHY_ERROR; - } - if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1)) { - printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); - return PHY_ERROR; - } - } - } } /* some phys clear out pause advertisment on reset, set it back */ @@ -1501,12 +1494,10 @@ static int phy_init(struct net_device *dev) /* restart auto negotiation, power down phy */ mii_control = mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ); mii_control |= (BMCR_ANRESTART | BMCR_ANENABLE); - if (phy_power_down) { + if (phy_power_down) mii_control |= BMCR_PDOWN; - } - if (mii_rw(dev, np->phyaddr, MII_BMCR, mii_control)) { + if (mii_rw(dev, np->phyaddr, MII_BMCR, mii_control)) return PHY_ERROR; - } return 0; } @@ -1517,7 +1508,6 @@ static void nv_start_rx(struct net_device *dev) u8 __iomem *base = get_hwbase(dev); u32 rx_ctrl = readl(base + NvRegReceiverControl); - dprintk(KERN_DEBUG "%s: nv_start_rx\n", dev->name); /* Already running? Stop it. */ if ((readl(base + NvRegReceiverControl) & NVREG_RCVCTL_START) && !np->mac_in_use) { rx_ctrl &= ~NVREG_RCVCTL_START; @@ -1526,12 +1516,10 @@ static void nv_start_rx(struct net_device *dev) } writel(np->linkspeed, base + NvRegLinkSpeed); pci_push(base); - rx_ctrl |= NVREG_RCVCTL_START; - if (np->mac_in_use) + rx_ctrl |= NVREG_RCVCTL_START; + if (np->mac_in_use) rx_ctrl &= ~NVREG_RCVCTL_RX_PATH_EN; writel(rx_ctrl, base + NvRegReceiverControl); - dprintk(KERN_DEBUG "%s: nv_start_rx to duplex %d, speed 0x%08x.\n", - dev->name, np->duplex, np->linkspeed); pci_push(base); } @@ -1541,15 +1529,15 @@ static void nv_stop_rx(struct net_device *dev) u8 __iomem *base = get_hwbase(dev); u32 rx_ctrl = readl(base + NvRegReceiverControl); - dprintk(KERN_DEBUG "%s: nv_stop_rx\n", dev->name); if (!np->mac_in_use) rx_ctrl &= ~NVREG_RCVCTL_START; else rx_ctrl |= NVREG_RCVCTL_RX_PATH_EN; writel(rx_ctrl, base + NvRegReceiverControl); - reg_delay(dev, NvRegReceiverStatus, NVREG_RCVSTAT_BUSY, 0, - NV_RXSTOP_DELAY1, NV_RXSTOP_DELAY1MAX, - KERN_INFO "nv_stop_rx: ReceiverStatus remained busy"); + if (reg_delay(dev, NvRegReceiverStatus, NVREG_RCVSTAT_BUSY, 0, + NV_RXSTOP_DELAY1, NV_RXSTOP_DELAY1MAX)) + netdev_info(dev, "%s: ReceiverStatus remained busy\n", + __func__); udelay(NV_RXSTOP_DELAY2); if (!np->mac_in_use) @@ -1562,7 +1550,6 @@ static void nv_start_tx(struct net_device *dev) u8 __iomem *base = get_hwbase(dev); u32 tx_ctrl = readl(base + NvRegTransmitterControl); - dprintk(KERN_DEBUG "%s: nv_start_tx\n", dev->name); tx_ctrl |= NVREG_XMITCTL_START; if (np->mac_in_use) tx_ctrl &= ~NVREG_XMITCTL_TX_PATH_EN; @@ -1576,15 +1563,15 @@ static void nv_stop_tx(struct net_device *dev) u8 __iomem *base = get_hwbase(dev); u32 tx_ctrl = readl(base + NvRegTransmitterControl); - dprintk(KERN_DEBUG "%s: nv_stop_tx\n", dev->name); if (!np->mac_in_use) tx_ctrl &= ~NVREG_XMITCTL_START; else tx_ctrl |= NVREG_XMITCTL_TX_PATH_EN; writel(tx_ctrl, base + NvRegTransmitterControl); - reg_delay(dev, NvRegTransmitterStatus, NVREG_XMITSTAT_BUSY, 0, - NV_TXSTOP_DELAY1, NV_TXSTOP_DELAY1MAX, - KERN_INFO "nv_stop_tx: TransmitterStatus remained busy"); + if (reg_delay(dev, NvRegTransmitterStatus, NVREG_XMITSTAT_BUSY, 0, + NV_TXSTOP_DELAY1, NV_TXSTOP_DELAY1MAX)) + netdev_info(dev, "%s: TransmitterStatus remained busy\n", + __func__); udelay(NV_TXSTOP_DELAY2); if (!np->mac_in_use) @@ -1609,7 +1596,6 @@ static void nv_txrx_reset(struct net_device *dev) struct fe_priv *np = netdev_priv(dev); u8 __iomem *base = get_hwbase(dev); - dprintk(KERN_DEBUG "%s: nv_txrx_reset\n", dev->name); writel(NVREG_TXRXCTL_BIT2 | NVREG_TXRXCTL_RESET | np->txrxctl_bits, base + NvRegTxRxControl); pci_push(base); udelay(NV_TXRX_RESET_DELAY); @@ -1623,8 +1609,6 @@ static void nv_mac_reset(struct net_device *dev) u8 __iomem *base = get_hwbase(dev); u32 temp1, temp2, temp3; - dprintk(KERN_DEBUG "%s: nv_mac_reset\n", dev->name); - writel(NVREG_TXRXCTL_BIT2 | NVREG_TXRXCTL_RESET | np->txrxctl_bits, base + NvRegTxRxControl); pci_push(base); @@ -1745,7 +1729,7 @@ static struct net_device_stats *nv_get_stats(struct net_device *dev) static int nv_alloc_rx(struct net_device *dev) { struct fe_priv *np = netdev_priv(dev); - struct ring_desc* less_rx; + struct ring_desc *less_rx; less_rx = np->get_rx.orig; if (less_rx-- == np->first_rx.orig) @@ -1767,9 +1751,8 @@ static int nv_alloc_rx(struct net_device *dev) np->put_rx.orig = np->first_rx.orig; if (unlikely(np->put_rx_ctx++ == np->last_rx_ctx)) np->put_rx_ctx = np->first_rx_ctx; - } else { + } else return 1; - } } return 0; } @@ -1777,7 +1760,7 @@ static int nv_alloc_rx(struct net_device *dev) static int nv_alloc_rx_optimized(struct net_device *dev) { struct fe_priv *np = netdev_priv(dev); - struct ring_desc_ex* less_rx; + struct ring_desc_ex *less_rx; less_rx = np->get_rx.ex; if (less_rx-- == np->first_rx.ex) @@ -1800,9 +1783,8 @@ static int nv_alloc_rx_optimized(struct net_device *dev) np->put_rx.ex = np->first_rx.ex; if (unlikely(np->put_rx_ctx++ == np->last_rx_ctx)) np->put_rx_ctx = np->first_rx_ctx; - } else { + } else return 1; - } } return 0; } @@ -2018,24 +2000,24 @@ static void nv_legacybackoff_reseed(struct net_device *dev) /* Known Good seed sets */ static const u32 main_seedset[BACKOFF_SEEDSET_ROWS][BACKOFF_SEEDSET_LFSRS] = { - {145, 155, 165, 175, 185, 196, 235, 245, 255, 265, 275, 285, 660, 690, 874}, - {245, 255, 265, 575, 385, 298, 335, 345, 355, 366, 375, 385, 761, 790, 974}, - {145, 155, 165, 175, 185, 196, 235, 245, 255, 265, 275, 285, 660, 690, 874}, - {245, 255, 265, 575, 385, 298, 335, 345, 355, 366, 375, 386, 761, 790, 974}, - {266, 265, 276, 585, 397, 208, 345, 355, 365, 376, 385, 396, 771, 700, 984}, - {266, 265, 276, 586, 397, 208, 346, 355, 365, 376, 285, 396, 771, 700, 984}, - {366, 365, 376, 686, 497, 308, 447, 455, 466, 476, 485, 496, 871, 800, 84}, - {466, 465, 476, 786, 597, 408, 547, 555, 566, 576, 585, 597, 971, 900, 184}}; + {145, 155, 165, 175, 185, 196, 235, 245, 255, 265, 275, 285, 660, 690, 874}, + {245, 255, 265, 575, 385, 298, 335, 345, 355, 366, 375, 385, 761, 790, 974}, + {145, 155, 165, 175, 185, 196, 235, 245, 255, 265, 275, 285, 660, 690, 874}, + {245, 255, 265, 575, 385, 298, 335, 345, 355, 366, 375, 386, 761, 790, 974}, + {266, 265, 276, 585, 397, 208, 345, 355, 365, 376, 385, 396, 771, 700, 984}, + {266, 265, 276, 586, 397, 208, 346, 355, 365, 376, 285, 396, 771, 700, 984}, + {366, 365, 376, 686, 497, 308, 447, 455, 466, 476, 485, 496, 871, 800, 84}, + {466, 465, 476, 786, 597, 408, 547, 555, 566, 576, 585, 597, 971, 900, 184} }; static const u32 gear_seedset[BACKOFF_SEEDSET_ROWS][BACKOFF_SEEDSET_LFSRS] = { - {251, 262, 273, 324, 319, 508, 375, 364, 341, 371, 398, 193, 375, 30, 295}, - {351, 375, 373, 469, 551, 639, 477, 464, 441, 472, 498, 293, 476, 130, 395}, - {351, 375, 373, 469, 551, 639, 477, 464, 441, 472, 498, 293, 476, 130, 397}, - {251, 262, 273, 324, 319, 508, 375, 364, 341, 371, 398, 193, 375, 30, 295}, - {251, 262, 273, 324, 319, 508, 375, 364, 341, 371, 398, 193, 375, 30, 295}, - {351, 375, 373, 469, 551, 639, 477, 464, 441, 472, 498, 293, 476, 130, 395}, - {351, 375, 373, 469, 551, 639, 477, 464, 441, 472, 498, 293, 476, 130, 395}, - {351, 375, 373, 469, 551, 639, 477, 464, 441, 472, 498, 293, 476, 130, 395}}; + {251, 262, 273, 324, 319, 508, 375, 364, 341, 371, 398, 193, 375, 30, 295}, + {351, 375, 373, 469, 551, 639, 477, 464, 441, 472, 498, 293, 476, 130, 395}, + {351, 375, 373, 469, 551, 639, 477, 464, 441, 472, 498, 293, 476, 130, 397}, + {251, 262, 273, 324, 319, 508, 375, 364, 341, 371, 398, 193, 375, 30, 295}, + {251, 262, 273, 324, 319, 508, 375, 364, 341, 371, 398, 193, 375, 30, 295}, + {351, 375, 373, 469, 551, 639, 477, 464, 441, 472, 498, 293, 476, 130, 395}, + {351, 375, 373, 469, 551, 639, 477, 464, 441, 472, 498, 293, 476, 130, 395}, + {351, 375, 373, 469, 551, 639, 477, 464, 441, 472, 498, 293, 476, 130, 395} }; static void nv_gear_backoff_reseed(struct net_device *dev) { @@ -2083,13 +2065,12 @@ static void nv_gear_backoff_reseed(struct net_device *dev) temp = NVREG_BKOFFCTRL_DEFAULT | (0 << NVREG_BKOFFCTRL_SELECT); temp |= combinedSeed & NVREG_BKOFFCTRL_SEED_MASK; temp |= combinedSeed >> NVREG_BKOFFCTRL_GEAR; - writel(temp,base + NvRegBackOffControl); + writel(temp, base + NvRegBackOffControl); - /* Setup seeds for all gear LFSRs. */ + /* Setup seeds for all gear LFSRs. */ get_random_bytes(&seedset, sizeof(seedset)); seedset = seedset % BACKOFF_SEEDSET_ROWS; - for (i = 1; i <= BACKOFF_SEEDSET_LFSRS; i++) - { + for (i = 1; i <= BACKOFF_SEEDSET_LFSRS; i++) { temp = NVREG_BKOFFCTRL_DEFAULT | (i << NVREG_BKOFFCTRL_SELECT); temp |= main_seedset[seedset][i-1] & 0x3ff; temp |= ((gear_seedset[seedset][i-1] & 0x3ff) << NVREG_BKOFFCTRL_GEAR); @@ -2113,10 +2094,10 @@ static netdev_tx_t nv_start_xmit(struct sk_buff *skb, struct net_device *dev) u32 size = skb_headlen(skb); u32 entries = (size >> NV_TX2_TSO_MAX_SHIFT) + ((size & (NV_TX2_TSO_MAX_SIZE-1)) ? 1 : 0); u32 empty_slots; - struct ring_desc* put_tx; - struct ring_desc* start_tx; - struct ring_desc* prev_tx; - struct nv_skb_map* prev_tx_ctx; + struct ring_desc *put_tx; + struct ring_desc *start_tx; + struct ring_desc *prev_tx; + struct nv_skb_map *prev_tx_ctx; unsigned long flags; /* add fragments to entries count */ @@ -2204,18 +2185,6 @@ static netdev_tx_t nv_start_xmit(struct sk_buff *skb, struct net_device *dev) spin_unlock_irqrestore(&np->lock, flags); - dprintk(KERN_DEBUG "%s: nv_start_xmit: entries %d queued for transmission. tx_flags_extra: %x\n", - dev->name, entries, tx_flags_extra); - { - int j; - for (j=0; j<64; j++) { - if ((j%16) == 0) - dprintk("\n%03x:", j); - dprintk(" %02x", ((unsigned char*)skb->data)[j]); - } - dprintk("\n"); - } - writel(NVREG_TXRXCTL_KICK|np->txrxctl_bits, get_hwbase(dev) + NvRegTxRxControl); return NETDEV_TX_OK; } @@ -2233,11 +2202,11 @@ static netdev_tx_t nv_start_xmit_optimized(struct sk_buff *skb, u32 size = skb_headlen(skb); u32 entries = (size >> NV_TX2_TSO_MAX_SHIFT) + ((size & (NV_TX2_TSO_MAX_SIZE-1)) ? 1 : 0); u32 empty_slots; - struct ring_desc_ex* put_tx; - struct ring_desc_ex* start_tx; - struct ring_desc_ex* prev_tx; - struct nv_skb_map* prev_tx_ctx; - struct nv_skb_map* start_tx_ctx; + struct ring_desc_ex *put_tx; + struct ring_desc_ex *start_tx; + struct ring_desc_ex *prev_tx; + struct nv_skb_map *prev_tx_ctx; + struct nv_skb_map *start_tx_ctx; unsigned long flags; /* add fragments to entries count */ @@ -2355,18 +2324,6 @@ static netdev_tx_t nv_start_xmit_optimized(struct sk_buff *skb, spin_unlock_irqrestore(&np->lock, flags); - dprintk(KERN_DEBUG "%s: nv_start_xmit_optimized: entries %d queued for transmission. tx_flags_extra: %x\n", - dev->name, entries, tx_flags_extra); - { - int j; - for (j=0; j<64; j++) { - if ((j%16) == 0) - dprintk("\n%03x:", j); - dprintk(" %02x", ((unsigned char*)skb->data)[j]); - } - dprintk("\n"); - } - writel(NVREG_TXRXCTL_KICK|np->txrxctl_bits, get_hwbase(dev) + NvRegTxRxControl); return NETDEV_TX_OK; } @@ -2399,15 +2356,12 @@ static int nv_tx_done(struct net_device *dev, int limit) struct fe_priv *np = netdev_priv(dev); u32 flags; int tx_work = 0; - struct ring_desc* orig_get_tx = np->get_tx.orig; + struct ring_desc *orig_get_tx = np->get_tx.orig; while ((np->get_tx.orig != np->put_tx.orig) && !((flags = le32_to_cpu(np->get_tx.orig->flaglen)) & NV_TX_VALID) && (tx_work < limit)) { - dprintk(KERN_DEBUG "%s: nv_tx_done: flags 0x%x.\n", - dev->name, flags); - nv_unmap_txskb(np, np->get_tx_ctx); if (np->desc_ver == DESC_VER_1) { @@ -2464,15 +2418,12 @@ static int nv_tx_done_optimized(struct net_device *dev, int limit) struct fe_priv *np = netdev_priv(dev); u32 flags; int tx_work = 0; - struct ring_desc_ex* orig_get_tx = np->get_tx.ex; + struct ring_desc_ex *orig_get_tx = np->get_tx.ex; while ((np->get_tx.ex != np->put_tx.ex) && !((flags = le32_to_cpu(np->get_tx.ex->flaglen)) & NV_TX2_VALID) && (tx_work < limit)) { - dprintk(KERN_DEBUG "%s: nv_tx_done_optimized: flags 0x%x.\n", - dev->name, flags); - nv_unmap_txskb(np, np->get_tx_ctx); if (flags & NV_TX2_LASTPACKET) { @@ -2491,9 +2442,8 @@ static int nv_tx_done_optimized(struct net_device *dev, int limit) np->get_tx_ctx->skb = NULL; tx_work++; - if (np->tx_limit) { + if (np->tx_limit) nv_tx_flip_ownership(dev); - } } if (unlikely(np->get_tx.ex++ == np->last_tx.ex)) np->get_tx.ex = np->first_tx.ex; @@ -2518,57 +2468,56 @@ static void nv_tx_timeout(struct net_device *dev) u32 status; union ring_type put_tx; int saved_tx_limit; + int i; if (np->msi_flags & NV_MSI_X_ENABLED) status = readl(base + NvRegMSIXIrqStatus) & NVREG_IRQSTAT_MASK; else status = readl(base + NvRegIrqStatus) & NVREG_IRQSTAT_MASK; - printk(KERN_INFO "%s: Got tx_timeout. irq: %08x\n", dev->name, status); - - { - int i; - - printk(KERN_INFO "%s: Ring at %lx\n", - dev->name, (unsigned long)np->ring_addr); - printk(KERN_INFO "%s: Dumping tx registers\n", dev->name); - for (i=0;i<=np->register_size;i+= 32) { - printk(KERN_INFO "%3x: %08x %08x %08x %08x %08x %08x %08x %08x\n", - i, - readl(base + i + 0), readl(base + i + 4), - readl(base + i + 8), readl(base + i + 12), - readl(base + i + 16), readl(base + i + 20), - readl(base + i + 24), readl(base + i + 28)); - } - printk(KERN_INFO "%s: Dumping tx ring\n", dev->name); - for (i=0;i<np->tx_ring_size;i+= 4) { - if (!nv_optimized(np)) { - printk(KERN_INFO "%03x: %08x %08x // %08x %08x // %08x %08x // %08x %08x\n", - i, - le32_to_cpu(np->tx_ring.orig[i].buf), - le32_to_cpu(np->tx_ring.orig[i].flaglen), - le32_to_cpu(np->tx_ring.orig[i+1].buf), - le32_to_cpu(np->tx_ring.orig[i+1].flaglen), - le32_to_cpu(np->tx_ring.orig[i+2].buf), - le32_to_cpu(np->tx_ring.orig[i+2].flaglen), - le32_to_cpu(np->tx_ring.orig[i+3].buf), - le32_to_cpu(np->tx_ring.orig[i+3].flaglen)); - } else { - printk(KERN_INFO "%03x: %08x %08x %08x // %08x %08x %08x // %08x %08x %08x // %08x %08x %08x\n", - i, - le32_to_cpu(np->tx_ring.ex[i].bufhigh), - le32_to_cpu(np->tx_ring.ex[i].buflow), - le32_to_cpu(np->tx_ring.ex[i].flaglen), - le32_to_cpu(np->tx_ring.ex[i+1].bufhigh), - le32_to_cpu(np->tx_ring.ex[i+1].buflow), - le32_to_cpu(np->tx_ring.ex[i+1].flaglen), - le32_to_cpu(np->tx_ring.ex[i+2].bufhigh), - le32_to_cpu(np->tx_ring.ex[i+2].buflow), - le32_to_cpu(np->tx_ring.ex[i+2].flaglen), - le32_to_cpu(np->tx_ring.ex[i+3].bufhigh), - le32_to_cpu(np->tx_ring.ex[i+3].buflow), - le32_to_cpu(np->tx_ring.ex[i+3].flaglen)); - } + netdev_info(dev, "Got tx_timeout. irq: %08x\n", status); + + netdev_info(dev, "Ring at %lx\n", (unsigned long)np->ring_addr); + netdev_info(dev, "Dumping tx registers\n"); + for (i = 0; i <= np->register_size; i += 32) { + netdev_info(dev, + "%3x: %08x %08x %08x %08x %08x %08x %08x %08x\n", + i, + readl(base + i + 0), readl(base + i + 4), + readl(base + i + 8), readl(base + i + 12), + readl(base + i + 16), readl(base + i + 20), + readl(base + i + 24), readl(base + i + 28)); + } + netdev_info(dev, "Dumping tx ring\n"); + for (i = 0; i < np->tx_ring_size; i += 4) { + if (!nv_optimized(np)) { + netdev_info(dev, + "%03x: %08x %08x // %08x %08x // %08x %08x // %08x %08x\n", + i, + le32_to_cpu(np->tx_ring.orig[i].buf), + le32_to_cpu(np->tx_ring.orig[i].flaglen), + le32_to_cpu(np->tx_ring.orig[i+1].buf), + le32_to_cpu(np->tx_ring.orig[i+1].flaglen), + le32_to_cpu(np->tx_ring.orig[i+2].buf), + le32_to_cpu(np->tx_ring.orig[i+2].flaglen), + le32_to_cpu(np->tx_ring.orig[i+3].buf), + le32_to_cpu(np->tx_ring.orig[i+3].flaglen)); + } else { + netdev_info(dev, + "%03x: %08x %08x %08x // %08x %08x %08x // %08x %08x %08x // %08x %08x %08x\n", + i, + le32_to_cpu(np->tx_ring.ex[i].bufhigh), + le32_to_cpu(np->tx_ring.ex[i].buflow), + le32_to_cpu(np->tx_ring.ex[i].flaglen), + le32_to_cpu(np->tx_ring.ex[i+1].bufhigh), + le32_to_cpu(np->tx_ring.ex[i+1].buflow), + le32_to_cpu(np->tx_ring.ex[i+1].flaglen), + le32_to_cpu(np->tx_ring.ex[i+2].bufhigh), + le32_to_cpu(np->tx_ring.ex[i+2].buflow), + le32_to_cpu(np->tx_ring.ex[i+2].flaglen), + le32_to_cpu(np->tx_ring.ex[i+3].bufhigh), + le32_to_cpu(np->tx_ring.ex[i+3].buflow), + le32_to_cpu(np->tx_ring.ex[i+3].flaglen)); } } @@ -2616,15 +2565,13 @@ static int nv_getlen(struct net_device *dev, void *packet, int datalen) int protolen; /* length as stored in the proto field */ /* 1) calculate len according to header */ - if ( ((struct vlan_ethhdr *)packet)->h_vlan_proto == htons(ETH_P_8021Q)) { - protolen = ntohs( ((struct vlan_ethhdr *)packet)->h_vlan_encapsulated_proto ); + if (((struct vlan_ethhdr *)packet)->h_vlan_proto == htons(ETH_P_8021Q)) { + protolen = ntohs(((struct vlan_ethhdr *)packet)->h_vlan_encapsulated_proto); hdrlen = VLAN_HLEN; } else { - protolen = ntohs( ((struct ethhdr *)packet)->h_proto); + protolen = ntohs(((struct ethhdr *)packet)->h_proto); hdrlen = ETH_HLEN; } - dprintk(KERN_DEBUG "%s: nv_getlen: datalen %d, protolen %d, hdrlen %d\n", - dev->name, datalen, protolen, hdrlen); if (protolen > ETH_DATA_LEN) return datalen; /* Value in proto field not a len, no checks possible */ @@ -2635,26 +2582,18 @@ static int nv_getlen(struct net_device *dev, void *packet, int datalen) /* more data on wire than in 802 header, trim of * additional data. */ - dprintk(KERN_DEBUG "%s: nv_getlen: accepting %d bytes.\n", - dev->name, protolen); return protolen; } else { /* less data on wire than mentioned in header. * Discard the packet. */ - dprintk(KERN_DEBUG "%s: nv_getlen: discarding long packet.\n", - dev->name); return -1; } } else { /* short packet. Accept only if 802 values are also short */ if (protolen > ETH_ZLEN) { - dprintk(KERN_DEBUG "%s: nv_getlen: discarding short packet.\n", - dev->name); return -1; } - dprintk(KERN_DEBUG "%s: nv_getlen: accepting %d bytes.\n", - dev->name, datalen); return datalen; } } @@ -2667,13 +2606,10 @@ static int nv_rx_process(struct net_device *dev, int limit) struct sk_buff *skb; int len; - while((np->get_rx.orig != np->put_rx.orig) && + while ((np->get_rx.orig != np->put_rx.orig) && !((flags = le32_to_cpu(np->get_rx.orig->flaglen)) & NV_RX_AVAIL) && (rx_work < limit)) { - dprintk(KERN_DEBUG "%s: nv_rx_process: flags 0x%x.\n", - dev->name, flags); - /* * the packet is for us - immediately tear down the pci mapping. * TODO: check if a prefetch of the first cacheline improves @@ -2685,16 +2621,6 @@ static int nv_rx_process(struct net_device *dev, int limit) skb = np->get_rx_ctx->skb; np->get_rx_ctx->skb = NULL; - { - int j; - dprintk(KERN_DEBUG "Dumping packet (flags 0x%x).",flags); - for (j=0; j<64; j++) { - if ((j%16) == 0) - dprintk("\n%03x:", j); - dprintk(" %02x", ((unsigned char*)skb->data)[j]); - } - dprintk("\n"); - } /* look at what we actually got: */ if (np->desc_ver == DESC_VER_1) { if (likely(flags & NV_RX_DESCRIPTORVALID)) { @@ -2710,9 +2636,8 @@ static int nv_rx_process(struct net_device *dev, int limit) } /* framing errors are soft errors */ else if ((flags & NV_RX_ERROR_MASK) == NV_RX_FRAMINGERR) { - if (flags & NV_RX_SUBSTRACT1) { + if (flags & NV_RX_SUBSTRACT1) len--; - } } /* the rest are hard errors */ else { @@ -2745,9 +2670,8 @@ static int nv_rx_process(struct net_device *dev, int limit) } /* framing errors are soft errors */ else if ((flags & NV_RX2_ERROR_MASK) == NV_RX2_FRAMINGERR) { - if (flags & NV_RX2_SUBSTRACT1) { + if (flags & NV_RX2_SUBSTRACT1) len--; - } } /* the rest are hard errors */ else { @@ -2771,8 +2695,6 @@ static int nv_rx_process(struct net_device *dev, int limit) /* got a valid packet - forward it to the network core */ skb_put(skb, len); skb->protocol = eth_type_trans(skb, dev); - dprintk(KERN_DEBUG "%s: nv_rx_process: %d bytes, proto %d accepted.\n", - dev->name, len, skb->protocol); napi_gro_receive(&np->napi, skb); dev->stats.rx_packets++; dev->stats.rx_bytes += len; @@ -2797,13 +2719,10 @@ static int nv_rx_process_optimized(struct net_device *dev, int limit) struct sk_buff *skb; int len; - while((np->get_rx.ex != np->put_rx.ex) && + while ((np->get_rx.ex != np->put_rx.ex) && !((flags = le32_to_cpu(np->get_rx.ex->flaglen)) & NV_RX2_AVAIL) && (rx_work < limit)) { - dprintk(KERN_DEBUG "%s: nv_rx_process_optimized: flags 0x%x.\n", - dev->name, flags); - /* * the packet is for us - immediately tear down the pci mapping. * TODO: check if a prefetch of the first cacheline improves @@ -2815,16 +2734,6 @@ static int nv_rx_process_optimized(struct net_device *dev, int limit) skb = np->get_rx_ctx->skb; np->get_rx_ctx->skb = NULL; - { - int j; - dprintk(KERN_DEBUG "Dumping packet (flags 0x%x).",flags); - for (j=0; j<64; j++) { - if ((j%16) == 0) - dprintk("\n%03x:", j); - dprintk(" %02x", ((unsigned char*)skb->data)[j]); - } - dprintk("\n"); - } /* look at what we actually got: */ if (likely(flags & NV_RX2_DESCRIPTORVALID)) { len = flags & LEN_MASK_V2; @@ -2838,9 +2747,8 @@ static int nv_rx_process_optimized(struct net_device *dev, int limit) } /* framing errors are soft errors */ else if ((flags & NV_RX2_ERROR_MASK) == NV_RX2_FRAMINGERR) { - if (flags & NV_RX2_SUBSTRACT1) { + if (flags & NV_RX2_SUBSTRACT1) len--; - } } /* the rest are hard errors */ else { @@ -2858,9 +2766,6 @@ static int nv_rx_process_optimized(struct net_device *dev, int limit) skb->protocol = eth_type_trans(skb, dev); prefetch(skb->data); - dprintk(KERN_DEBUG "%s: nv_rx_process_optimized: %d bytes, proto %d accepted.\n", - dev->name, len, skb->protocol); - if (likely(!np->vlangrp)) { napi_gro_receive(&np->napi, skb); } else { @@ -2949,7 +2854,7 @@ static int nv_change_mtu(struct net_device *dev, int new_mtu) /* reinit nic view of the rx queue */ writel(np->rx_buf_sz, base + NvRegOffloadConfig); setup_hw_rings(dev, NV_SETUP_RX_RING | NV_SETUP_TX_RING); - writel( ((np->rx_ring_size-1) << NVREG_RINGSZ_RXSHIFT) + ((np->tx_ring_size-1) << NVREG_RINGSZ_TXSHIFT), + writel(((np->rx_ring_size-1) << NVREG_RINGSZ_RXSHIFT) + ((np->tx_ring_size-1) << NVREG_RINGSZ_TXSHIFT), base + NvRegRingSizes); pci_push(base); writel(NVREG_TXRXCTL_KICK|np->txrxctl_bits, get_hwbase(dev) + NvRegTxRxControl); @@ -2986,7 +2891,7 @@ static void nv_copy_mac_to_hw(struct net_device *dev) static int nv_set_mac_address(struct net_device *dev, void *addr) { struct fe_priv *np = netdev_priv(dev); - struct sockaddr *macaddr = (struct sockaddr*)addr; + struct sockaddr *macaddr = (struct sockaddr *)addr; if (!is_valid_ether_addr(macaddr->sa_data)) return -EADDRNOTAVAIL; @@ -3076,8 +2981,6 @@ static void nv_set_multicast(struct net_device *dev) writel(mask[0], base + NvRegMulticastMaskA); writel(mask[1], base + NvRegMulticastMaskB); writel(pff, base + NvRegPacketFilterFlags); - dprintk(KERN_INFO "%s: reconfiguration for multicast lists.\n", - dev->name); nv_start_rx(dev); spin_unlock_irq(&np->lock); } @@ -3152,8 +3055,6 @@ static int nv_update_linkspeed(struct net_device *dev) mii_status = mii_rw(dev, np->phyaddr, MII_BMSR, MII_READ); if (!(mii_status & BMSR_LSTATUS)) { - dprintk(KERN_DEBUG "%s: no link detected by phy - falling back to 10HD.\n", - dev->name); newls = NVREG_LINKSPEED_FORCE|NVREG_LINKSPEED_10; newdup = 0; retval = 0; @@ -3161,8 +3062,6 @@ static int nv_update_linkspeed(struct net_device *dev) } if (np->autoneg == 0) { - dprintk(KERN_DEBUG "%s: nv_update_linkspeed: autoneg off, PHY set to 0x%04x.\n", - dev->name, np->fixed_mode); if (np->fixed_mode & LPA_100FULL) { newls = NVREG_LINKSPEED_FORCE|NVREG_LINKSPEED_100; newdup = 1; @@ -3185,14 +3084,11 @@ static int nv_update_linkspeed(struct net_device *dev) newls = NVREG_LINKSPEED_FORCE|NVREG_LINKSPEED_10; newdup = 0; retval = 0; - dprintk(KERN_DEBUG "%s: autoneg not completed - falling back to 10HD.\n", dev->name); goto set_speed; } adv = mii_rw(dev, np->phyaddr, MII_ADVERTISE, MII_READ); lpa = mii_rw(dev, np->phyaddr, MII_LPA, MII_READ); - dprintk(KERN_DEBUG "%s: nv_update_linkspeed: PHY advertises 0x%04x, lpa 0x%04x.\n", - dev->name, adv, lpa); retval = 1; if (np->gigabit == PHY_GIGABIT) { @@ -3201,8 +3097,6 @@ static int nv_update_linkspeed(struct net_device *dev) if ((control_1000 & ADVERTISE_1000FULL) && (status_1000 & LPA_1000FULL)) { - dprintk(KERN_DEBUG "%s: nv_update_linkspeed: GBit ethernet detected.\n", - dev->name); newls = NVREG_LINKSPEED_FORCE|NVREG_LINKSPEED_1000; newdup = 1; goto set_speed; @@ -3224,7 +3118,6 @@ static int nv_update_linkspeed(struct net_device *dev) newls = NVREG_LINKSPEED_FORCE|NVREG_LINKSPEED_10; newdup = 0; } else { - dprintk(KERN_DEBUG "%s: bad ability %04x - falling back to 10HD.\n", dev->name, adv_lpa); newls = NVREG_LINKSPEED_FORCE|NVREG_LINKSPEED_10; newdup = 0; } @@ -3233,9 +3126,6 @@ set_speed: if (np->duplex == newdup && np->linkspeed == newls) return retval; - dprintk(KERN_INFO "%s: changing link setting from %d/%d to %d/%d.\n", - dev->name, np->linkspeed, np->duplex, newls, newdup); - np->duplex = newdup; np->linkspeed = newls; @@ -3302,7 +3192,7 @@ set_speed: } writel(txreg, base + NvRegTxWatermark); - writel(NVREG_MISC1_FORCE | ( np->duplex ? 0 : NVREG_MISC1_HD), + writel(NVREG_MISC1_FORCE | (np->duplex ? 0 : NVREG_MISC1_HD), base + NvRegMisc1); pci_push(base); writel(np->linkspeed, base + NvRegLinkSpeed); @@ -3312,8 +3202,8 @@ set_speed: /* setup pause frame */ if (np->duplex != 0) { if (np->autoneg && np->pause_flags & NV_PAUSEFRAME_AUTONEG) { - adv_pause = adv & (ADVERTISE_PAUSE_CAP| ADVERTISE_PAUSE_ASYM); - lpa_pause = lpa & (LPA_PAUSE_CAP| LPA_PAUSE_ASYM); + adv_pause = adv & (ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM); + lpa_pause = lpa & (LPA_PAUSE_CAP | LPA_PAUSE_ASYM); switch (adv_pause) { case ADVERTISE_PAUSE_CAP: @@ -3324,22 +3214,17 @@ set_speed: } break; case ADVERTISE_PAUSE_ASYM: - if (lpa_pause == (LPA_PAUSE_CAP| LPA_PAUSE_ASYM)) - { + if (lpa_pause == (LPA_PAUSE_CAP | LPA_PAUSE_ASYM)) pause_flags |= NV_PAUSEFRAME_TX_ENABLE; - } break; - case ADVERTISE_PAUSE_CAP| ADVERTISE_PAUSE_ASYM: - if (lpa_pause & LPA_PAUSE_CAP) - { + case ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM: + if (lpa_pause & LPA_PAUSE_CAP) { pause_flags |= NV_PAUSEFRAME_RX_ENABLE; if (np->pause_flags & NV_PAUSEFRAME_TX_REQ) pause_flags |= NV_PAUSEFRAME_TX_ENABLE; } if (lpa_pause == LPA_PAUSE_ASYM) - { pause_flags |= NV_PAUSEFRAME_RX_ENABLE; - } break; } } else { @@ -3361,14 +3246,14 @@ static void nv_linkchange(struct net_device *dev) if (nv_update_linkspeed(dev)) { if (!netif_carrier_ok(dev)) { netif_carrier_on(dev); - printk(KERN_INFO "%s: link up.\n", dev->name); + netdev_info(dev, "link up\n"); nv_txrx_gate(dev, false); nv_start_rx(dev); } } else { if (netif_carrier_ok(dev)) { netif_carrier_off(dev); - printk(KERN_INFO "%s: link down.\n", dev->name); + netdev_info(dev, "link down\n"); nv_txrx_gate(dev, true); nv_stop_rx(dev); } @@ -3382,11 +3267,9 @@ static void nv_link_irq(struct net_device *dev) miistat = readl(base + NvRegMIIStatus); writel(NVREG_MIISTAT_LINKCHANGE, base + NvRegMIIStatus); - dprintk(KERN_INFO "%s: link change irq, status 0x%x.\n", dev->name, miistat); if (miistat & (NVREG_MIISTAT_LINKCHANGE)) nv_linkchange(dev); - dprintk(KERN_DEBUG "%s: link change notification done.\n", dev->name); } static void nv_msi_workaround(struct fe_priv *np) @@ -3437,8 +3320,6 @@ static irqreturn_t nv_nic_irq(int foo, void *data) struct fe_priv *np = netdev_priv(dev); u8 __iomem *base = get_hwbase(dev); - dprintk(KERN_DEBUG "%s: nv_nic_irq\n", dev->name); - if (!(np->msi_flags & NV_MSI_X_ENABLED)) { np->events = readl(base + NvRegIrqStatus); writel(np->events, base + NvRegIrqStatus); @@ -3446,7 +3327,6 @@ static irqreturn_t nv_nic_irq(int foo, void *data) np->events = readl(base + NvRegMSIXIrqStatus); writel(np->events, base + NvRegMSIXIrqStatus); } - dprintk(KERN_DEBUG "%s: irq: %08x\n", dev->name, np->events); if (!(np->events & np->irqmask)) return IRQ_NONE; @@ -3460,8 +3340,6 @@ static irqreturn_t nv_nic_irq(int foo, void *data) __napi_schedule(&np->napi); } - dprintk(KERN_DEBUG "%s: nv_nic_irq completed\n", dev->name); - return IRQ_HANDLED; } @@ -3476,8 +3354,6 @@ static irqreturn_t nv_nic_irq_optimized(int foo, void *data) struct fe_priv *np = netdev_priv(dev); u8 __iomem *base = get_hwbase(dev); - dprintk(KERN_DEBUG "%s: nv_nic_irq_optimized\n", dev->name); - if (!(np->msi_flags & NV_MSI_X_ENABLED)) { np->events = readl(base + NvRegIrqStatus); writel(np->events, base + NvRegIrqStatus); @@ -3485,7 +3361,6 @@ static irqreturn_t nv_nic_irq_optimized(int foo, void *data) np->events = readl(base + NvRegMSIXIrqStatus); writel(np->events, base + NvRegMSIXIrqStatus); } - dprintk(KERN_DEBUG "%s: irq: %08x\n", dev->name, np->events); if (!(np->events & np->irqmask)) return IRQ_NONE; @@ -3498,7 +3373,6 @@ static irqreturn_t nv_nic_irq_optimized(int foo, void *data) writel(0, base + NvRegIrqMask); __napi_schedule(&np->napi); } - dprintk(KERN_DEBUG "%s: nv_nic_irq_optimized completed\n", dev->name); return IRQ_HANDLED; } @@ -3512,12 +3386,9 @@ static irqreturn_t nv_nic_irq_tx(int foo, void *data) int i; unsigned long flags; - dprintk(KERN_DEBUG "%s: nv_nic_irq_tx\n", dev->name); - - for (i=0; ; i++) { + for (i = 0;; i++) { events = readl(base + NvRegMSIXIrqStatus) & NVREG_IRQ_TX_ALL; writel(NVREG_IRQ_TX_ALL, base + NvRegMSIXIrqStatus); - dprintk(KERN_DEBUG "%s: tx irq: %08x\n", dev->name, events); if (!(events & np->irqmask)) break; @@ -3536,12 +3407,12 @@ static irqreturn_t nv_nic_irq_tx(int foo, void *data) mod_timer(&np->nic_poll, jiffies + POLL_WAIT); } spin_unlock_irqrestore(&np->lock, flags); - printk(KERN_DEBUG "%s: too many iterations (%d) in nv_nic_irq_tx.\n", dev->name, i); + netdev_dbg(dev, "%s: too many iterations (%d)\n", + __func__, i); break; } } - dprintk(KERN_DEBUG "%s: nv_nic_irq_tx completed\n", dev->name); return IRQ_RETVAL(i); } @@ -3553,7 +3424,7 @@ static int nv_napi_poll(struct napi_struct *napi, int budget) u8 __iomem *base = get_hwbase(dev); unsigned long flags; int retcode; - int rx_count, tx_work=0, rx_work=0; + int rx_count, tx_work = 0, rx_work = 0; do { if (!nv_optimized(np)) { @@ -3626,12 +3497,9 @@ static irqreturn_t nv_nic_irq_rx(int foo, void *data) int i; unsigned long flags; - dprintk(KERN_DEBUG "%s: nv_nic_irq_rx\n", dev->name); - - for (i=0; ; i++) { + for (i = 0;; i++) { events = readl(base + NvRegMSIXIrqStatus) & NVREG_IRQ_RX_ALL; writel(NVREG_IRQ_RX_ALL, base + NvRegMSIXIrqStatus); - dprintk(KERN_DEBUG "%s: rx irq: %08x\n", dev->name, events); if (!(events & np->irqmask)) break; @@ -3655,11 +3523,11 @@ static irqreturn_t nv_nic_irq_rx(int foo, void *data) mod_timer(&np->nic_poll, jiffies + POLL_WAIT); } spin_unlock_irqrestore(&np->lock, flags); - printk(KERN_DEBUG "%s: too many iterations (%d) in nv_nic_irq_rx.\n", dev->name, i); + netdev_dbg(dev, "%s: too many iterations (%d)\n", + __func__, i); break; } } - dprintk(KERN_DEBUG "%s: nv_nic_irq_rx completed\n", dev->name); return IRQ_RETVAL(i); } @@ -3673,12 +3541,9 @@ static irqreturn_t nv_nic_irq_other(int foo, void *data) int i; unsigned long flags; - dprintk(KERN_DEBUG "%s: nv_nic_irq_other\n", dev->name); - - for (i=0; ; i++) { + for (i = 0;; i++) { events = readl(base + NvRegMSIXIrqStatus) & NVREG_IRQ_OTHER; writel(NVREG_IRQ_OTHER, base + NvRegMSIXIrqStatus); - dprintk(KERN_DEBUG "%s: irq: %08x\n", dev->name, events); if (!(events & np->irqmask)) break; @@ -3723,12 +3588,12 @@ static irqreturn_t nv_nic_irq_other(int foo, void *data) mod_timer(&np->nic_poll, jiffies + POLL_WAIT); } spin_unlock_irqrestore(&np->lock, flags); - printk(KERN_DEBUG "%s: too many iterations (%d) in nv_nic_irq_other.\n", dev->name, i); + netdev_dbg(dev, "%s: too many iterations (%d)\n", + __func__, i); break; } } - dprintk(KERN_DEBUG "%s: nv_nic_irq_other completed\n", dev->name); return IRQ_RETVAL(i); } @@ -3740,8 +3605,6 @@ static irqreturn_t nv_nic_irq_test(int foo, void *data) u8 __iomem *base = get_hwbase(dev); u32 events; - dprintk(KERN_DEBUG "%s: nv_nic_irq_test\n", dev->name); - if (!(np->msi_flags & NV_MSI_X_ENABLED)) { events = readl(base + NvRegIrqStatus) & NVREG_IRQSTAT_MASK; writel(NVREG_IRQ_TIMER, base + NvRegIrqStatus); @@ -3750,7 +3613,6 @@ static irqreturn_t nv_nic_irq_test(int foo, void *data) writel(NVREG_IRQ_TIMER, base + NvRegMSIXIrqStatus); } pci_push(base); - dprintk(KERN_DEBUG "%s: irq: %08x\n", dev->name, events); if (!(events & NVREG_IRQ_TIMER)) return IRQ_RETVAL(0); @@ -3760,8 +3622,6 @@ static irqreturn_t nv_nic_irq_test(int foo, void *data) np->intr_test = 1; spin_unlock(&np->lock); - dprintk(KERN_DEBUG "%s: nv_nic_irq_test completed\n", dev->name); - return IRQ_RETVAL(1); } @@ -3776,17 +3636,15 @@ static void set_msix_vector_map(struct net_device *dev, u32 vector, u32 irqmask) * the remaining 8 interrupts. */ for (i = 0; i < 8; i++) { - if ((irqmask >> i) & 0x1) { + if ((irqmask >> i) & 0x1) msixmap |= vector << (i << 2); - } } writel(readl(base + NvRegMSIXMap0) | msixmap, base + NvRegMSIXMap0); msixmap = 0; for (i = 0; i < 8; i++) { - if ((irqmask >> (i + 8)) & 0x1) { + if ((irqmask >> (i + 8)) & 0x1) msixmap |= vector << (i << 2); - } } writel(readl(base + NvRegMSIXMap1) | msixmap, base + NvRegMSIXMap1); } @@ -3809,17 +3667,19 @@ static int nv_request_irq(struct net_device *dev, int intr_test) } if (np->msi_flags & NV_MSI_X_CAPABLE) { - for (i = 0; i < (np->msi_flags & NV_MSI_X_VECTORS_MASK); i++) { + for (i = 0; i < (np->msi_flags & NV_MSI_X_VECTORS_MASK); i++) np->msi_x_entry[i].entry = i; - } - if ((ret = pci_enable_msix(np->pci_dev, np->msi_x_entry, (np->msi_flags & NV_MSI_X_VECTORS_MASK))) == 0) { + ret = pci_enable_msix(np->pci_dev, np->msi_x_entry, (np->msi_flags & NV_MSI_X_VECTORS_MASK)); + if (ret == 0) { np->msi_flags |= NV_MSI_X_ENABLED; if (optimization_mode == NV_OPTIMIZATION_MODE_THROUGHPUT && !intr_test) { /* Request irq for rx handling */ sprintf(np->name_rx, "%s-rx", dev->name); if (request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector, nv_nic_irq_rx, IRQF_SHARED, np->name_rx, dev) != 0) { - printk(KERN_INFO "forcedeth: request_irq failed for rx %d\n", ret); + netdev_info(dev, + "request_irq failed for rx %d\n", + ret); pci_disable_msix(np->pci_dev); np->msi_flags &= ~NV_MSI_X_ENABLED; goto out_err; @@ -3828,7 +3688,9 @@ static int nv_request_irq(struct net_device *dev, int intr_test) sprintf(np->name_tx, "%s-tx", dev->name); if (request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector, nv_nic_irq_tx, IRQF_SHARED, np->name_tx, dev) != 0) { - printk(KERN_INFO "forcedeth: request_irq failed for tx %d\n", ret); + netdev_info(dev, + "request_irq failed for tx %d\n", + ret); pci_disable_msix(np->pci_dev); np->msi_flags &= ~NV_MSI_X_ENABLED; goto out_free_rx; @@ -3837,7 +3699,9 @@ static int nv_request_irq(struct net_device *dev, int intr_test) sprintf(np->name_other, "%s-other", dev->name); if (request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_OTHER].vector, nv_nic_irq_other, IRQF_SHARED, np->name_other, dev) != 0) { - printk(KERN_INFO "forcedeth: request_irq failed for link %d\n", ret); + netdev_info(dev, + "request_irq failed for link %d\n", + ret); pci_disable_msix(np->pci_dev); np->msi_flags &= ~NV_MSI_X_ENABLED; goto out_free_tx; @@ -3851,7 +3715,9 @@ static int nv_request_irq(struct net_device *dev, int intr_test) } else { /* Request irq for all interrupts */ if (request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector, handler, IRQF_SHARED, dev->name, dev) != 0) { - printk(KERN_INFO "forcedeth: request_irq failed %d\n", ret); + netdev_info(dev, + "request_irq failed %d\n", + ret); pci_disable_msix(np->pci_dev); np->msi_flags &= ~NV_MSI_X_ENABLED; goto out_err; @@ -3864,11 +3730,13 @@ static int nv_request_irq(struct net_device *dev, int intr_test) } } if (ret != 0 && np->msi_flags & NV_MSI_CAPABLE) { - if ((ret = pci_enable_msi(np->pci_dev)) == 0) { + ret = pci_enable_msi(np->pci_dev); + if (ret == 0) { np->msi_flags |= NV_MSI_ENABLED; dev->irq = np->pci_dev->irq; if (request_irq(np->pci_dev->irq, handler, IRQF_SHARED, dev->name, dev) != 0) { - printk(KERN_INFO "forcedeth: request_irq failed %d\n", ret); + netdev_info(dev, "request_irq failed %d\n", + ret); pci_disable_msi(np->pci_dev); np->msi_flags &= ~NV_MSI_ENABLED; dev->irq = np->pci_dev->irq; @@ -3903,9 +3771,8 @@ static void nv_free_irq(struct net_device *dev) int i; if (np->msi_flags & NV_MSI_X_ENABLED) { - for (i = 0; i < (np->msi_flags & NV_MSI_X_VECTORS_MASK); i++) { + for (i = 0; i < (np->msi_flags & NV_MSI_X_VECTORS_MASK); i++) free_irq(np->msi_x_entry[i].vector, dev); - } pci_disable_msix(np->pci_dev); np->msi_flags &= ~NV_MSI_X_ENABLED; } else { @@ -3954,7 +3821,7 @@ static void nv_do_nic_poll(unsigned long data) if (np->recover_error) { np->recover_error = 0; - printk(KERN_INFO "%s: MAC in recoverable error state\n", dev->name); + netdev_info(dev, "MAC in recoverable error state\n"); if (netif_running(dev)) { netif_tx_lock_bh(dev); netif_addr_lock(dev); @@ -3975,7 +3842,7 @@ static void nv_do_nic_poll(unsigned long data) /* reinit nic view of the rx queue */ writel(np->rx_buf_sz, base + NvRegOffloadConfig); setup_hw_rings(dev, NV_SETUP_RX_RING | NV_SETUP_TX_RING); - writel( ((np->rx_ring_size-1) << NVREG_RINGSZ_RXSHIFT) + ((np->tx_ring_size-1) << NVREG_RINGSZ_TXSHIFT), + writel(((np->rx_ring_size-1) << NVREG_RINGSZ_RXSHIFT) + ((np->tx_ring_size-1) << NVREG_RINGSZ_TXSHIFT), base + NvRegRingSizes); pci_push(base); writel(NVREG_TXRXCTL_KICK|np->txrxctl_bits, get_hwbase(dev) + NvRegTxRxControl); @@ -4105,7 +3972,7 @@ static int nv_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) } if (netif_carrier_ok(dev)) { - switch(np->linkspeed & (NVREG_LINKSPEED_MASK)) { + switch (np->linkspeed & (NVREG_LINKSPEED_MASK)) { case NVREG_LINKSPEED_10: ecmd->speed = SPEED_10; break; @@ -4250,14 +4117,14 @@ static int nv_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) } if (netif_running(dev)) - printk(KERN_INFO "%s: link down.\n", dev->name); + netdev_info(dev, "link down\n"); bmcr = mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ); if (np->phy_model == PHY_MODEL_MARVELL_E3016) { bmcr |= BMCR_ANENABLE; /* reset the phy in order for settings to stick, * and cause autoneg to start */ if (phy_reset(dev, bmcr)) { - printk(KERN_INFO "%s: phy reset failed\n", dev->name); + netdev_info(dev, "phy reset failed\n"); return -EINVAL; } } else { @@ -4306,7 +4173,7 @@ static int nv_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) if (np->phy_oui == PHY_OUI_MARVELL) { /* reset the phy in order for forced mode settings to stick */ if (phy_reset(dev, bmcr)) { - printk(KERN_INFO "%s: phy reset failed\n", dev->name); + netdev_info(dev, "phy reset failed\n"); return -EINVAL; } } else { @@ -4344,7 +4211,7 @@ static void nv_get_regs(struct net_device *dev, struct ethtool_regs *regs, void regs->version = FORCEDETH_REGS_VER; spin_lock_irq(&np->lock); - for (i = 0;i <= np->register_size/sizeof(u32); i++) + for (i = 0; i <= np->register_size/sizeof(u32); i++) rbuf[i] = readl(base + i*sizeof(u32)); spin_unlock_irq(&np->lock); } @@ -4368,7 +4235,7 @@ static int nv_nway_reset(struct net_device *dev) spin_unlock(&np->lock); netif_addr_unlock(dev); netif_tx_unlock_bh(dev); - printk(KERN_INFO "%s: link down.\n", dev->name); + netdev_info(dev, "link down\n"); } bmcr = mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ); @@ -4376,7 +4243,7 @@ static int nv_nway_reset(struct net_device *dev) bmcr |= BMCR_ANENABLE; /* reset the phy in order for settings to stick*/ if (phy_reset(dev, bmcr)) { - printk(KERN_INFO "%s: phy reset failed\n", dev->name); + netdev_info(dev, "phy reset failed\n"); return -EINVAL; } } else { @@ -4464,10 +4331,9 @@ static int nv_set_ringparam(struct net_device *dev, struct ethtool_ringparam* ri pci_free_consistent(np->pci_dev, sizeof(struct ring_desc_ex) * (ring->rx_pending + ring->tx_pending), rxtx_ring, ring_addr); } - if (rx_skbuff) - kfree(rx_skbuff); - if (tx_skbuff) - kfree(tx_skbuff); + + kfree(rx_skbuff); + kfree(tx_skbuff); goto exit; } @@ -4491,14 +4357,14 @@ static int nv_set_ringparam(struct net_device *dev, struct ethtool_ringparam* ri np->tx_ring_size = ring->tx_pending; if (!nv_optimized(np)) { - np->rx_ring.orig = (struct ring_desc*)rxtx_ring; + np->rx_ring.orig = (struct ring_desc *)rxtx_ring; np->tx_ring.orig = &np->rx_ring.orig[np->rx_ring_size]; } else { - np->rx_ring.ex = (struct ring_desc_ex*)rxtx_ring; + np->rx_ring.ex = (struct ring_desc_ex *)rxtx_ring; np->tx_ring.ex = &np->rx_ring.ex[np->rx_ring_size]; } - np->rx_skb = (struct nv_skb_map*)rx_skbuff; - np->tx_skb = (struct nv_skb_map*)tx_skbuff; + np->rx_skb = (struct nv_skb_map *)rx_skbuff; + np->tx_skb = (struct nv_skb_map *)tx_skbuff; np->ring_addr = ring_addr; memset(np->rx_skb, 0, sizeof(struct nv_skb_map) * np->rx_ring_size); @@ -4515,7 +4381,7 @@ static int nv_set_ringparam(struct net_device *dev, struct ethtool_ringparam* ri /* reinit nic view of the queues */ writel(np->rx_buf_sz, base + NvRegOffloadConfig); setup_hw_rings(dev, NV_SETUP_RX_RING | NV_SETUP_TX_RING); - writel( ((np->rx_ring_size-1) << NVREG_RINGSZ_RXSHIFT) + ((np->tx_ring_size-1) << NVREG_RINGSZ_TXSHIFT), + writel(((np->rx_ring_size-1) << NVREG_RINGSZ_RXSHIFT) + ((np->tx_ring_size-1) << NVREG_RINGSZ_TXSHIFT), base + NvRegRingSizes); pci_push(base); writel(NVREG_TXRXCTL_KICK|np->txrxctl_bits, get_hwbase(dev) + NvRegTxRxControl); @@ -4550,12 +4416,11 @@ static int nv_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam* if ((!np->autoneg && np->duplex == 0) || (np->autoneg && !pause->autoneg && np->duplex == 0)) { - printk(KERN_INFO "%s: can not set pause settings when forced link is in half duplex.\n", - dev->name); + netdev_info(dev, "can not set pause settings when forced link is in half duplex\n"); return -EINVAL; } if (pause->tx_pause && !(np->pause_flags & NV_PAUSEFRAME_TX_CAPABLE)) { - printk(KERN_INFO "%s: hardware does not support tx pause frames.\n", dev->name); + netdev_info(dev, "hardware does not support tx pause frames\n"); return -EINVAL; } @@ -4590,7 +4455,7 @@ static int nv_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam* mii_rw(dev, np->phyaddr, MII_ADVERTISE, adv); if (netif_running(dev)) - printk(KERN_INFO "%s: link down.\n", dev->name); + netdev_info(dev, "link down\n"); bmcr = mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ); bmcr |= (BMCR_ANENABLE | BMCR_ANRESTART); mii_rw(dev, np->phyaddr, MII_BMCR, bmcr); @@ -4841,7 +4706,7 @@ static int nv_loopback_test(struct net_device *dev) /* reinit nic view of the rx queue */ writel(np->rx_buf_sz, base + NvRegOffloadConfig); setup_hw_rings(dev, NV_SETUP_RX_RING | NV_SETUP_TX_RING); - writel( ((np->rx_ring_size-1) << NVREG_RINGSZ_RXSHIFT) + ((np->tx_ring_size-1) << NVREG_RINGSZ_TXSHIFT), + writel(((np->rx_ring_size-1) << NVREG_RINGSZ_RXSHIFT) + ((np->tx_ring_size-1) << NVREG_RINGSZ_TXSHIFT), base + NvRegRingSizes); pci_push(base); @@ -4852,8 +4717,7 @@ static int nv_loopback_test(struct net_device *dev) pkt_len = ETH_DATA_LEN; tx_skb = dev_alloc_skb(pkt_len); if (!tx_skb) { - printk(KERN_ERR "dev_alloc_skb() failed during loopback test" - " of %s\n", dev->name); + netdev_err(dev, "dev_alloc_skb() failed during loopback test\n"); ret = 0; goto out; } @@ -4893,29 +4757,22 @@ static int nv_loopback_test(struct net_device *dev) if (flags & NV_RX_ERROR) ret = 0; } else { - if (flags & NV_RX2_ERROR) { + if (flags & NV_RX2_ERROR) ret = 0; - } } if (ret) { if (len != pkt_len) { ret = 0; - dprintk(KERN_DEBUG "%s: loopback len mismatch %d vs %d\n", - dev->name, len, pkt_len); } else { rx_skb = np->rx_skb[0].skb; for (i = 0; i < pkt_len; i++) { if (rx_skb->data[i] != (u8)(i & 0xff)) { ret = 0; - dprintk(KERN_DEBUG "%s: loopback pattern check failed on byte %d\n", - dev->name, i); break; } } } - } else { - dprintk(KERN_DEBUG "%s: loopback - did not receive test packet\n", dev->name); } pci_unmap_single(np->pci_dev, test_dma_addr, @@ -4958,11 +4815,10 @@ static void nv_self_test(struct net_device *dev, struct ethtool_test *test, u64 netif_addr_lock(dev); spin_lock_irq(&np->lock); nv_disable_hw_interrupts(dev, np->irqmask); - if (!(np->msi_flags & NV_MSI_X_ENABLED)) { + if (!(np->msi_flags & NV_MSI_X_ENABLED)) writel(NVREG_IRQSTAT_MASK, base + NvRegIrqStatus); - } else { + else writel(NVREG_IRQSTAT_MASK, base + NvRegMSIXIrqStatus); - } /* stop engines */ nv_stop_rxtx(dev); nv_txrx_reset(dev); @@ -5003,7 +4859,7 @@ static void nv_self_test(struct net_device *dev, struct ethtool_test *test, u64 /* reinit nic view of the rx queue */ writel(np->rx_buf_sz, base + NvRegOffloadConfig); setup_hw_rings(dev, NV_SETUP_RX_RING | NV_SETUP_TX_RING); - writel( ((np->rx_ring_size-1) << NVREG_RINGSZ_RXSHIFT) + ((np->tx_ring_size-1) << NVREG_RINGSZ_TXSHIFT), + writel(((np->rx_ring_size-1) << NVREG_RINGSZ_RXSHIFT) + ((np->tx_ring_size-1) << NVREG_RINGSZ_TXSHIFT), base + NvRegRingSizes); pci_push(base); writel(NVREG_TXRXCTL_KICK|np->txrxctl_bits, get_hwbase(dev) + NvRegTxRxControl); @@ -5106,8 +4962,7 @@ static int nv_mgmt_acquire_sema(struct net_device *dev) ((tx_ctrl & NVREG_XMITCTL_MGMT_SEMA_MASK) == NVREG_XMITCTL_MGMT_SEMA_FREE)) { np->mgmt_sema = 1; return 1; - } - else + } else udelay(50); } @@ -5167,8 +5022,6 @@ static int nv_open(struct net_device *dev) int oom, i; u32 low; - dprintk(KERN_DEBUG "nv_open: begin\n"); - /* power up phy */ mii_rw(dev, np->phyaddr, MII_BMCR, mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ) & ~BMCR_PDOWN); @@ -5204,7 +5057,7 @@ static int nv_open(struct net_device *dev) /* give hw rings */ setup_hw_rings(dev, NV_SETUP_RX_RING | NV_SETUP_TX_RING); - writel( ((np->rx_ring_size-1) << NVREG_RINGSZ_RXSHIFT) + ((np->tx_ring_size-1) << NVREG_RINGSZ_TXSHIFT), + writel(((np->rx_ring_size-1) << NVREG_RINGSZ_RXSHIFT) + ((np->tx_ring_size-1) << NVREG_RINGSZ_TXSHIFT), base + NvRegRingSizes); writel(np->linkspeed, base + NvRegLinkSpeed); @@ -5216,9 +5069,11 @@ static int nv_open(struct net_device *dev) writel(np->vlanctl_bits, base + NvRegVlanControl); pci_push(base); writel(NVREG_TXRXCTL_BIT1|np->txrxctl_bits, base + NvRegTxRxControl); - reg_delay(dev, NvRegUnknownSetupReg5, NVREG_UNKSETUP5_BIT31, NVREG_UNKSETUP5_BIT31, - NV_SETUP5_DELAY, NV_SETUP5_DELAYMAX, - KERN_INFO "open: SetupReg5, Bit 31 remained off\n"); + if (reg_delay(dev, NvRegUnknownSetupReg5, + NVREG_UNKSETUP5_BIT31, NVREG_UNKSETUP5_BIT31, + NV_SETUP5_DELAY, NV_SETUP5_DELAYMAX)) + netdev_info(dev, + "%s: SetupReg5, Bit 31 remained off\n", __func__); writel(0, base + NvRegMIIMask); writel(NVREG_IRQSTAT_MASK, base + NvRegIrqStatus); @@ -5251,8 +5106,7 @@ static int nv_open(struct net_device *dev) writel(NVREG_POLL_DEFAULT_THROUGHPUT, base + NvRegPollingInterval); else writel(NVREG_POLL_DEFAULT_CPU, base + NvRegPollingInterval); - } - else + } else writel(poll_interval & 0xFFFF, base + NvRegPollingInterval); writel(NVREG_UNKSETUP6_VAL, base + NvRegUnknownSetupReg6); writel((np->phyaddr << NVREG_ADAPTCTL_PHYSHIFT)|NVREG_ADAPTCTL_PHYVALID|NVREG_ADAPTCTL_RUNNING, @@ -5263,7 +5117,7 @@ static int nv_open(struct net_device *dev) writel(NVREG_WAKEUPFLAGS_ENABLE , base + NvRegWakeUpFlags); i = readl(base + NvRegPowerState); - if ( (i & NVREG_POWERSTATE_POWEREDUP) == 0) + if ((i & NVREG_POWERSTATE_POWEREDUP) == 0) writel(NVREG_POWERSTATE_POWEREDUP|i, base + NvRegPowerState); pci_push(base); @@ -5276,9 +5130,8 @@ static int nv_open(struct net_device *dev) writel(NVREG_IRQSTAT_MASK, base + NvRegIrqStatus); pci_push(base); - if (nv_request_irq(dev, 0)) { + if (nv_request_irq(dev, 0)) goto out_drain; - } /* ask for interrupts */ nv_enable_hw_interrupts(dev, np->irqmask); @@ -5296,7 +5149,6 @@ static int nv_open(struct net_device *dev) u32 miistat; miistat = readl(base + NvRegMIIStatus); writel(NVREG_MIISTAT_MASK_ALL, base + NvRegMIIStatus); - dprintk(KERN_INFO "startup: got 0x%08x.\n", miistat); } /* set linkspeed to invalid value, thus force nv_update_linkspeed * to init hw */ @@ -5309,7 +5161,7 @@ static int nv_open(struct net_device *dev) if (ret) { netif_carrier_on(dev); } else { - printk(KERN_INFO "%s: no link during initialization.\n", dev->name); + netdev_info(dev, "no link during initialization\n"); netif_carrier_off(dev); } if (oom) @@ -5352,7 +5204,6 @@ static int nv_close(struct net_device *dev) base = get_hwbase(dev); nv_disable_hw_interrupts(dev, np->irqmask); pci_push(base); - dprintk(KERN_INFO "%s: Irqmask is zero again\n", dev->name); spin_unlock_irq(&np->lock); @@ -5421,8 +5272,8 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i static int printed_version; if (!printed_version++) - printk(KERN_INFO "%s: Reverse Engineered nForce ethernet" - " driver. Version %s.\n", DRV_NAME, FORCEDETH_VERSION); + pr_info("Reverse Engineered nForce ethernet driver. Version %s.\n", + FORCEDETH_VERSION); dev = alloc_etherdev(sizeof(struct fe_priv)); err = -ENOMEM; @@ -5465,10 +5316,6 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i err = -EINVAL; addr = 0; for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) { - dprintk(KERN_DEBUG "%s: resource %d start %p len %ld flags 0x%08lx.\n", - pci_name(pci_dev), i, (void*)pci_resource_start(pci_dev, i), - pci_resource_len(pci_dev, i), - pci_resource_flags(pci_dev, i)); if (pci_resource_flags(pci_dev, i) & IORESOURCE_MEM && pci_resource_len(pci_dev, i) >= np->register_size) { addr = pci_resource_start(pci_dev, i); @@ -5476,8 +5323,7 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i } } if (i == DEVICE_COUNT_RESOURCE) { - dev_printk(KERN_INFO, &pci_dev->dev, - "Couldn't find register window\n"); + dev_info(&pci_dev->dev, "Couldn't find register window\n"); goto out_relreg; } @@ -5493,13 +5339,13 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i np->txrxctl_bits = NVREG_TXRXCTL_DESC_3; if (dma_64bit) { if (pci_set_dma_mask(pci_dev, DMA_BIT_MASK(39))) - dev_printk(KERN_INFO, &pci_dev->dev, - "64-bit DMA failed, using 32-bit addressing\n"); + dev_info(&pci_dev->dev, + "64-bit DMA failed, using 32-bit addressing\n"); else dev->features |= NETIF_F_HIGHDMA; if (pci_set_consistent_dma_mask(pci_dev, DMA_BIT_MASK(39))) { - dev_printk(KERN_INFO, &pci_dev->dev, - "64-bit DMA (consistent) failed, using 32-bit ring buffers\n"); + dev_info(&pci_dev->dev, + "64-bit DMA (consistent) failed, using 32-bit ring buffers\n"); } } } else if (id->driver_data & DEV_HAS_LARGEDESC) { @@ -5620,7 +5466,9 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i dev->dev_addr[4] = (np->orig_mac[0] >> 8) & 0xff; dev->dev_addr[5] = (np->orig_mac[0] >> 0) & 0xff; writel(txreg|NVREG_TRANSMITPOLL_MAC_ADDR_REV, base + NvRegTransmitPoll); - printk(KERN_DEBUG "nv_probe: set workaround bit for reversed mac addr\n"); + dev_dbg(&pci_dev->dev, + "%s: set workaround bit for reversed mac addr\n", + __func__); } memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); @@ -5629,17 +5477,14 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i * Bad mac address. At least one bios sets the mac address * to 01:23:45:67:89:ab */ - dev_printk(KERN_ERR, &pci_dev->dev, - "Invalid Mac address detected: %pM\n", - dev->dev_addr); - dev_printk(KERN_ERR, &pci_dev->dev, - "Please complain to your hardware vendor. Switching to a random MAC.\n"); + dev_err(&pci_dev->dev, + "Invalid MAC address detected: %pM - Please complain to your hardware vendor.\n", + dev->dev_addr); random_ether_addr(dev->dev_addr); + dev_err(&pci_dev->dev, + "Using random MAC address: %pM\n", dev->dev_addr); } - dprintk(KERN_DEBUG "%s: MAC Address %pM\n", - pci_name(pci_dev), dev->dev_addr); - /* set mac address */ nv_copy_mac_to_hw(dev); @@ -5663,16 +5508,15 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i writel(powerstate, base + NvRegPowerState2); } - if (np->desc_ver == DESC_VER_1) { + if (np->desc_ver == DESC_VER_1) np->tx_flags = NV_TX_VALID; - } else { + else np->tx_flags = NV_TX2_VALID; - } np->msi_flags = 0; - if ((id->driver_data & DEV_HAS_MSI) && msi) { + if ((id->driver_data & DEV_HAS_MSI) && msi) np->msi_flags |= NV_MSI_CAPABLE; - } + if ((id->driver_data & DEV_HAS_MSI_X) && msix) { /* msix has had reported issues when modifying irqmask as in the case of napi, therefore, disable for now @@ -5702,11 +5546,9 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i if (id->driver_data & DEV_NEED_TIMERIRQ) np->irqmask |= NVREG_IRQ_TIMER; if (id->driver_data & DEV_NEED_LINKTIMER) { - dprintk(KERN_INFO "%s: link timer on.\n", pci_name(pci_dev)); np->need_linktimer = 1; np->link_timeout = jiffies + LINK_TIMEOUT; } else { - dprintk(KERN_INFO "%s: link timer off.\n", pci_name(pci_dev)); np->need_linktimer = 0; } @@ -5735,19 +5577,14 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i nv_mgmt_acquire_sema(dev) && nv_mgmt_get_version(dev)) { np->mac_in_use = 1; - if (np->mgmt_version > 0) { + if (np->mgmt_version > 0) np->mac_in_use = readl(base + NvRegMgmtUnitControl) & NVREG_MGMTUNITCONTROL_INUSE; - } - dprintk(KERN_INFO "%s: mgmt unit is running. mac in use %x.\n", - pci_name(pci_dev), np->mac_in_use); /* management unit setup the phy already? */ if (np->mac_in_use && ((readl(base + NvRegTransmitterControl) & NVREG_XMITCTL_SYNC_MASK) == NVREG_XMITCTL_SYNC_PHY_INIT)) { /* phy is inited by mgmt unit */ phyinitialized = 1; - dprintk(KERN_INFO "%s: Phy already initialized by mgmt unit.\n", - pci_name(pci_dev)); } else { /* we need to init the phy */ } @@ -5773,8 +5610,6 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i np->phy_model = id2 & PHYID2_MODEL_MASK; id1 = (id1 & PHYID1_OUI_MASK) << PHYID1_OUI_SHFT; id2 = (id2 & PHYID2_OUI_MASK) >> PHYID2_OUI_SHFT; - dprintk(KERN_DEBUG "%s: open: Found PHY %04x:%04x at address %d.\n", - pci_name(pci_dev), id1, id2, phyaddr); np->phyaddr = phyaddr; np->phy_oui = id1 | id2; @@ -5788,8 +5623,7 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i break; } if (i == 33) { - dev_printk(KERN_INFO, &pci_dev->dev, - "open: Could not find a valid PHY.\n"); + dev_info(&pci_dev->dev, "open: Could not find a valid PHY\n"); goto out_error; } @@ -5799,9 +5633,8 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i } else { /* see if it is a gigabit phy */ u32 mii_status = mii_rw(dev, np->phyaddr, MII_BMSR, MII_READ); - if (mii_status & PHY_GIGABIT) { + if (mii_status & PHY_GIGABIT) np->gigabit = PHY_GIGABIT; - } } /* set default link speed settings */ @@ -5811,37 +5644,27 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i err = register_netdev(dev); if (err) { - dev_printk(KERN_INFO, &pci_dev->dev, - "unable to register netdev: %d\n", err); + dev_info(&pci_dev->dev, "unable to register netdev: %d\n", err); goto out_error; } - dev_printk(KERN_INFO, &pci_dev->dev, "ifname %s, PHY OUI 0x%x @ %d, " - "addr %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n", - dev->name, - np->phy_oui, - np->phyaddr, - dev->dev_addr[0], - dev->dev_addr[1], - dev->dev_addr[2], - dev->dev_addr[3], - dev->dev_addr[4], - dev->dev_addr[5]); - - dev_printk(KERN_INFO, &pci_dev->dev, "%s%s%s%s%s%s%s%s%s%sdesc-v%u\n", - dev->features & NETIF_F_HIGHDMA ? "highdma " : "", - dev->features & (NETIF_F_IP_CSUM | NETIF_F_SG) ? - "csum " : "", - dev->features & (NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_TX) ? - "vlan " : "", - id->driver_data & DEV_HAS_POWER_CNTRL ? "pwrctl " : "", - id->driver_data & DEV_HAS_MGMT_UNIT ? "mgmt " : "", - id->driver_data & DEV_NEED_TIMERIRQ ? "timirq " : "", - np->gigabit == PHY_GIGABIT ? "gbit " : "", - np->need_linktimer ? "lnktim " : "", - np->msi_flags & NV_MSI_CAPABLE ? "msi " : "", - np->msi_flags & NV_MSI_X_CAPABLE ? "msi-x " : "", - np->desc_ver); + dev_info(&pci_dev->dev, "ifname %s, PHY OUI 0x%x @ %d, addr %pM\n", + dev->name, np->phy_oui, np->phyaddr, dev->dev_addr); + + dev_info(&pci_dev->dev, "%s%s%s%s%s%s%s%s%s%sdesc-v%u\n", + dev->features & NETIF_F_HIGHDMA ? "highdma " : "", + dev->features & (NETIF_F_IP_CSUM | NETIF_F_SG) ? + "csum " : "", + dev->features & (NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_TX) ? + "vlan " : "", + id->driver_data & DEV_HAS_POWER_CNTRL ? "pwrctl " : "", + id->driver_data & DEV_HAS_MGMT_UNIT ? "mgmt " : "", + id->driver_data & DEV_NEED_TIMERIRQ ? "timirq " : "", + np->gigabit == PHY_GIGABIT ? "gbit " : "", + np->need_linktimer ? "lnktim " : "", + np->msi_flags & NV_MSI_CAPABLE ? "msi " : "", + np->msi_flags & NV_MSI_X_CAPABLE ? "msi-x " : "", + np->desc_ver); return 0; @@ -5931,13 +5754,13 @@ static int nv_suspend(struct pci_dev *pdev, pm_message_t state) int i; if (netif_running(dev)) { - // Gross. + /* Gross. */ nv_close(dev); } netif_device_detach(dev); /* save non-pci configuration space */ - for (i = 0;i <= np->register_size/sizeof(u32); i++) + for (i = 0; i <= np->register_size/sizeof(u32); i++) np->saved_config_space[i] = readl(base + i*sizeof(u32)); pci_save_state(pdev); @@ -5960,7 +5783,7 @@ static int nv_resume(struct pci_dev *pdev) pci_enable_wake(pdev, PCI_D0, 0); /* restore non-pci configuration space */ - for (i = 0;i <= np->register_size/sizeof(u32); i++) + for (i = 0; i <= np->register_size/sizeof(u32); i++) writel(np->saved_config_space[i], base+i*sizeof(u32)); if (np->driver_data & DEV_NEED_MSI_FIX) @@ -5990,9 +5813,8 @@ static void nv_shutdown(struct pci_dev *pdev) * If we really go for poweroff, we must not restore the MAC, * otherwise the MAC for WOL will be reversed at least on some boards. */ - if (system_state != SYSTEM_POWER_OFF) { + if (system_state != SYSTEM_POWER_OFF) nv_restore_mac_addr(pdev); - } pci_disable_device(pdev); /* diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index 49e4ce1246a7..d1bec6269173 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c @@ -577,11 +577,10 @@ static int gfar_parse_group(struct device_node *np, irq_of_parse_and_map(np, 1); priv->gfargrp[priv->num_grps].interruptError = irq_of_parse_and_map(np,2); - if (priv->gfargrp[priv->num_grps].interruptTransmit < 0 || - priv->gfargrp[priv->num_grps].interruptReceive < 0 || - priv->gfargrp[priv->num_grps].interruptError < 0) { + if (priv->gfargrp[priv->num_grps].interruptTransmit == NO_IRQ || + priv->gfargrp[priv->num_grps].interruptReceive == NO_IRQ || + priv->gfargrp[priv->num_grps].interruptError == NO_IRQ) return -EINVAL; - } } priv->gfargrp[priv->num_grps].grp_id = priv->num_grps; diff --git a/drivers/net/gianfar_ethtool.c b/drivers/net/gianfar_ethtool.c index 5c566ebc54b8..3bc8e276ba4d 100644 --- a/drivers/net/gianfar_ethtool.c +++ b/drivers/net/gianfar_ethtool.c @@ -635,9 +635,10 @@ static int gfar_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) if (wol->wolopts & ~WAKE_MAGIC) return -EINVAL; + device_set_wakeup_enable(&dev->dev, wol->wolopts & WAKE_MAGIC); + spin_lock_irqsave(&priv->bflock, flags); - priv->wol_en = wol->wolopts & WAKE_MAGIC ? 1 : 0; - device_set_wakeup_enable(&dev->dev, priv->wol_en); + priv->wol_en = !!device_may_wakeup(&dev->dev); spin_unlock_irqrestore(&priv->bflock, flags); return 0; diff --git a/drivers/net/ibm_newemac/core.c b/drivers/net/ibm_newemac/core.c index 385dc3204cb7..06bb9b799458 100644 --- a/drivers/net/ibm_newemac/core.c +++ b/drivers/net/ibm_newemac/core.c @@ -2871,7 +2871,6 @@ static int __devinit emac_probe(struct platform_device *ofdev, SET_ETHTOOL_OPS(ndev, &emac_ethtool_ops); netif_carrier_off(ndev); - netif_stop_queue(ndev); err = register_netdev(ndev); if (err) { diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 892d196f17ac..67ea262e482a 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -2436,10 +2436,9 @@ int igb_setup_tx_resources(struct igb_ring *tx_ring) int size; size = sizeof(struct igb_buffer) * tx_ring->count; - tx_ring->buffer_info = vmalloc(size); + tx_ring->buffer_info = vzalloc(size); if (!tx_ring->buffer_info) goto err; - memset(tx_ring->buffer_info, 0, size); /* round up to nearest 4K */ tx_ring->size = tx_ring->count * sizeof(union e1000_adv_tx_desc); @@ -2587,10 +2586,9 @@ int igb_setup_rx_resources(struct igb_ring *rx_ring) int size, desc_len; size = sizeof(struct igb_buffer) * rx_ring->count; - rx_ring->buffer_info = vmalloc(size); + rx_ring->buffer_info = vzalloc(size); if (!rx_ring->buffer_info) goto err; - memset(rx_ring->buffer_info, 0, size); desc_len = sizeof(union e1000_adv_rx_desc); diff --git a/drivers/net/igbvf/Makefile b/drivers/net/igbvf/Makefile index c2f150d8f2d9..0fa3db3dd8b6 100644 --- a/drivers/net/igbvf/Makefile +++ b/drivers/net/igbvf/Makefile @@ -1,7 +1,7 @@ ################################################################################ # # Intel(R) 82576 Virtual Function Linux driver -# Copyright(c) 2009 Intel Corporation. +# Copyright(c) 2009 - 2010 Intel Corporation. # # This program is free software; you can redistribute it and/or modify it # under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/igbvf/defines.h b/drivers/net/igbvf/defines.h index 88a47537518a..79f2604673fe 100644 --- a/drivers/net/igbvf/defines.h +++ b/drivers/net/igbvf/defines.h @@ -1,7 +1,7 @@ /******************************************************************************* Intel(R) 82576 Virtual Function Linux driver - Copyright(c) 1999 - 2009 Intel Corporation. + Copyright(c) 1999 - 2010 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/igbvf/ethtool.c b/drivers/net/igbvf/ethtool.c index 33add708bcbe..abb3606928fb 100644 --- a/drivers/net/igbvf/ethtool.c +++ b/drivers/net/igbvf/ethtool.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel(R) 82576 Virtual Function Linux driver - Copyright(c) 2009 Intel Corporation. + Copyright(c) 2009 - 2010 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/igbvf/igbvf.h b/drivers/net/igbvf/igbvf.h index debeee2dc717..9d4d63e536d4 100644 --- a/drivers/net/igbvf/igbvf.h +++ b/drivers/net/igbvf/igbvf.h @@ -1,7 +1,7 @@ /******************************************************************************* Intel(R) 82576 Virtual Function Linux driver - Copyright(c) 2009 Intel Corporation. + Copyright(c) 2009 - 2010 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, @@ -126,7 +126,6 @@ struct igbvf_buffer { unsigned int page_offset; }; }; - struct page *page; }; union igbvf_desc { diff --git a/drivers/net/igbvf/mbx.c b/drivers/net/igbvf/mbx.c index 819a8ec901dc..3d6f4cc3998a 100644 --- a/drivers/net/igbvf/mbx.c +++ b/drivers/net/igbvf/mbx.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel(R) 82576 Virtual Function Linux driver - Copyright(c) 2009 Intel Corporation. + Copyright(c) 2009 - 2010 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/igbvf/mbx.h b/drivers/net/igbvf/mbx.h index 4938609dbfb5..c2883c45d477 100644 --- a/drivers/net/igbvf/mbx.h +++ b/drivers/net/igbvf/mbx.h @@ -1,7 +1,7 @@ /******************************************************************************* Intel(R) 82576 Virtual Function Linux driver - Copyright(c) 1999 - 2009 Intel Corporation. + Copyright(c) 1999 - 2010 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/igbvf/netdev.c b/drivers/net/igbvf/netdev.c index 28af019c97bb..8dbde2397c10 100644 --- a/drivers/net/igbvf/netdev.c +++ b/drivers/net/igbvf/netdev.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel(R) 82576 Virtual Function Linux driver - Copyright(c) 2009 Intel Corporation. + Copyright(c) 2009 - 2010 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, @@ -44,12 +44,13 @@ #include "igbvf.h" -#define DRV_VERSION "1.0.0-k0" +#define DRV_VERSION "1.0.8-k0" char igbvf_driver_name[] = "igbvf"; const char igbvf_driver_version[] = DRV_VERSION; static const char igbvf_driver_string[] = "Intel(R) Virtual Function Network Driver"; -static const char igbvf_copyright[] = "Copyright (c) 2009 Intel Corporation."; +static const char igbvf_copyright[] = + "Copyright (c) 2009 - 2010 Intel Corporation."; static int igbvf_poll(struct napi_struct *napi, int budget); static void igbvf_reset(struct igbvf_adapter *); @@ -429,10 +430,9 @@ int igbvf_setup_tx_resources(struct igbvf_adapter *adapter, int size; size = sizeof(struct igbvf_buffer) * tx_ring->count; - tx_ring->buffer_info = vmalloc(size); + tx_ring->buffer_info = vzalloc(size); if (!tx_ring->buffer_info) goto err; - memset(tx_ring->buffer_info, 0, size); /* round up to nearest 4K */ tx_ring->size = tx_ring->count * sizeof(union e1000_adv_tx_desc); @@ -469,10 +469,9 @@ int igbvf_setup_rx_resources(struct igbvf_adapter *adapter, int size, desc_len; size = sizeof(struct igbvf_buffer) * rx_ring->count; - rx_ring->buffer_info = vmalloc(size); + rx_ring->buffer_info = vzalloc(size); if (!rx_ring->buffer_info) goto err; - memset(rx_ring->buffer_info, 0, size); desc_len = sizeof(union e1000_adv_rx_desc); @@ -1851,8 +1850,6 @@ static void igbvf_watchdog_task(struct work_struct *work) if (link) { if (!netif_carrier_ok(netdev)) { - bool txb2b = 1; - mac->ops.get_link_up_info(&adapter->hw, &adapter->link_speed, &adapter->link_duplex); @@ -1862,11 +1859,9 @@ static void igbvf_watchdog_task(struct work_struct *work) adapter->tx_timeout_factor = 1; switch (adapter->link_speed) { case SPEED_10: - txb2b = 0; adapter->tx_timeout_factor = 16; break; case SPEED_100: - txb2b = 0; /* maybe add some timeout factor ? */ break; } diff --git a/drivers/net/igbvf/regs.h b/drivers/net/igbvf/regs.h index b9e24ed70d0a..77e18d3d6b15 100644 --- a/drivers/net/igbvf/regs.h +++ b/drivers/net/igbvf/regs.h @@ -1,7 +1,7 @@ /******************************************************************************* Intel(R) 82576 Virtual Function Linux driver - Copyright(c) 2009 Intel Corporation. + Copyright(c) 2009 - 2010 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/igbvf/vf.c b/drivers/net/igbvf/vf.c index a9a61efa964c..0cc13c6ed418 100644 --- a/drivers/net/igbvf/vf.c +++ b/drivers/net/igbvf/vf.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel(R) 82576 Virtual Function Linux driver - Copyright(c) 2009 Intel Corporation. + Copyright(c) 2009 - 2010 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/igbvf/vf.h b/drivers/net/igbvf/vf.h index 1e8ce3741a67..c36ea21f17fa 100644 --- a/drivers/net/igbvf/vf.h +++ b/drivers/net/igbvf/vf.h @@ -1,7 +1,7 @@ /******************************************************************************* Intel(R) 82576 Virtual Function Linux driver - Copyright(c) 2009 Intel Corporation. + Copyright(c) 2009 - 2010 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ipg.c b/drivers/net/ipg.c index dc0198092343..aa93655c3aa7 100644 --- a/drivers/net/ipg.c +++ b/drivers/net/ipg.c @@ -88,16 +88,14 @@ static const char *ipg_brand_name[] = { "IC PLUS IP1000 1000/100/10 based NIC", "Sundance Technology ST2021 based NIC", "Tamarack Microelectronics TC9020/9021 based NIC", - "Tamarack Microelectronics TC9020/9021 based NIC", "D-Link NIC IP1000A" }; static DEFINE_PCI_DEVICE_TABLE(ipg_pci_tbl) = { { PCI_VDEVICE(SUNDANCE, 0x1023), 0 }, { PCI_VDEVICE(SUNDANCE, 0x2021), 1 }, - { PCI_VDEVICE(SUNDANCE, 0x1021), 2 }, - { PCI_VDEVICE(DLINK, 0x9021), 3 }, - { PCI_VDEVICE(DLINK, 0x4020), 4 }, + { PCI_VDEVICE(DLINK, 0x9021), 2 }, + { PCI_VDEVICE(DLINK, 0x4020), 3 }, { 0, } }; diff --git a/drivers/net/iseries_veth.c b/drivers/net/iseries_veth.c index 8df645e78f2e..38e15be6d513 100644 --- a/drivers/net/iseries_veth.c +++ b/drivers/net/iseries_veth.c @@ -1605,7 +1605,7 @@ static int veth_probe(struct vio_dev *vdev, const struct vio_device_id *id) } veth_dev[i] = dev; - port = (struct veth_port*)netdev_priv(dev); + port = netdev_priv(dev); /* Start the state machine on each connection on this vlan. If we're * the first dev to do so this will commence link negotiation */ diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c index caa8192fff2a..211a1694667e 100644 --- a/drivers/net/ixgb/ixgb_main.c +++ b/drivers/net/ixgb/ixgb_main.c @@ -669,13 +669,12 @@ ixgb_setup_tx_resources(struct ixgb_adapter *adapter) int size; size = sizeof(struct ixgb_buffer) * txdr->count; - txdr->buffer_info = vmalloc(size); + txdr->buffer_info = vzalloc(size); if (!txdr->buffer_info) { netif_err(adapter, probe, adapter->netdev, "Unable to allocate transmit descriptor ring memory\n"); return -ENOMEM; } - memset(txdr->buffer_info, 0, size); /* round up to nearest 4K */ @@ -759,13 +758,12 @@ ixgb_setup_rx_resources(struct ixgb_adapter *adapter) int size; size = sizeof(struct ixgb_buffer) * rxdr->count; - rxdr->buffer_info = vmalloc(size); + rxdr->buffer_info = vzalloc(size); if (!rxdr->buffer_info) { netif_err(adapter, probe, adapter->netdev, "Unable to allocate receive descriptor ring\n"); return -ENOMEM; } - memset(rxdr->buffer_info, 0, size); /* Round up to nearest 4K */ diff --git a/drivers/net/ixgbe/Makefile b/drivers/net/ixgbe/Makefile index 8f81efb49169..7d7387fbdecd 100644 --- a/drivers/net/ixgbe/Makefile +++ b/drivers/net/ixgbe/Makefile @@ -34,7 +34,7 @@ obj-$(CONFIG_IXGBE) += ixgbe.o ixgbe-objs := ixgbe_main.o ixgbe_common.o ixgbe_ethtool.o \ ixgbe_82599.o ixgbe_82598.o ixgbe_phy.o ixgbe_sriov.o \ - ixgbe_mbx.o + ixgbe_mbx.o ixgbe_x540.o ixgbe-$(CONFIG_IXGBE_DCB) += ixgbe_dcb.o ixgbe_dcb_82598.o \ ixgbe_dcb_82599.o ixgbe_dcb_nl.o diff --git a/drivers/net/ixgbe/ixgbe.h b/drivers/net/ixgbe/ixgbe.h index ed8703cfffb7..3ae30b8cb7d6 100644 --- a/drivers/net/ixgbe/ixgbe.h +++ b/drivers/net/ixgbe/ixgbe.h @@ -61,10 +61,8 @@ #define IXGBE_MIN_RXD 64 /* flow control */ -#define IXGBE_DEFAULT_FCRTL 0x10000 #define IXGBE_MIN_FCRTL 0x40 #define IXGBE_MAX_FCRTL 0x7FF80 -#define IXGBE_DEFAULT_FCRTH 0x20000 #define IXGBE_MIN_FCRTH 0x600 #define IXGBE_MAX_FCRTH 0x7FFF0 #define IXGBE_DEFAULT_FCPAUSE 0xFFFF @@ -130,7 +128,9 @@ struct ixgbe_tx_buffer { unsigned long time_stamp; u16 length; u16 next_to_watch; - u16 mapped_as_page; + unsigned int bytecount; + u16 gso_segs; + u8 mapped_as_page; }; struct ixgbe_rx_buffer { @@ -146,12 +146,56 @@ struct ixgbe_queue_stats { u64 bytes; }; +struct ixgbe_tx_queue_stats { + u64 restart_queue; + u64 tx_busy; + u64 completed; + u64 tx_done_old; +}; + +struct ixgbe_rx_queue_stats { + u64 rsc_count; + u64 rsc_flush; + u64 non_eop_descs; + u64 alloc_rx_page_failed; + u64 alloc_rx_buff_failed; +}; + +enum ixbge_ring_state_t { + __IXGBE_TX_FDIR_INIT_DONE, + __IXGBE_TX_DETECT_HANG, + __IXGBE_HANG_CHECK_ARMED, + __IXGBE_RX_PS_ENABLED, + __IXGBE_RX_RSC_ENABLED, +}; + +#define ring_is_ps_enabled(ring) \ + test_bit(__IXGBE_RX_PS_ENABLED, &(ring)->state) +#define set_ring_ps_enabled(ring) \ + set_bit(__IXGBE_RX_PS_ENABLED, &(ring)->state) +#define clear_ring_ps_enabled(ring) \ + clear_bit(__IXGBE_RX_PS_ENABLED, &(ring)->state) +#define check_for_tx_hang(ring) \ + test_bit(__IXGBE_TX_DETECT_HANG, &(ring)->state) +#define set_check_for_tx_hang(ring) \ + set_bit(__IXGBE_TX_DETECT_HANG, &(ring)->state) +#define clear_check_for_tx_hang(ring) \ + clear_bit(__IXGBE_TX_DETECT_HANG, &(ring)->state) +#define ring_is_rsc_enabled(ring) \ + test_bit(__IXGBE_RX_RSC_ENABLED, &(ring)->state) +#define set_ring_rsc_enabled(ring) \ + set_bit(__IXGBE_RX_RSC_ENABLED, &(ring)->state) +#define clear_ring_rsc_enabled(ring) \ + clear_bit(__IXGBE_RX_RSC_ENABLED, &(ring)->state) struct ixgbe_ring { void *desc; /* descriptor ring memory */ + struct device *dev; /* device for DMA mapping */ + struct net_device *netdev; /* netdev ring belongs to */ union { struct ixgbe_tx_buffer *tx_buffer_info; struct ixgbe_rx_buffer *rx_buffer_info; }; + unsigned long state; u8 atr_sample_rate; u8 atr_count; u16 count; /* amount of descriptors */ @@ -160,38 +204,30 @@ struct ixgbe_ring { u16 next_to_clean; u8 queue_index; /* needed for multiqueue queue management */ - -#define IXGBE_RING_RX_PS_ENABLED (u8)(1) - u8 flags; /* per ring feature flags */ - u16 head; - u16 tail; - - unsigned int total_bytes; - unsigned int total_packets; - -#ifdef CONFIG_IXGBE_DCA - /* cpu for tx queue */ - int cpu; -#endif - - u16 work_limit; /* max work per interrupt */ - u16 reg_idx; /* holds the special value that gets + u8 reg_idx; /* holds the special value that gets * the hardware register offset * associated with this ring, which is * different for DCB and RSS modes */ + u16 work_limit; /* max work per interrupt */ + + u8 __iomem *tail; + + unsigned int total_bytes; + unsigned int total_packets; + struct ixgbe_queue_stats stats; struct u64_stats_sync syncp; + union { + struct ixgbe_tx_queue_stats tx_stats; + struct ixgbe_rx_queue_stats rx_stats; + }; int numa_node; - unsigned long reinit_state; - u64 rsc_count; /* stat for coalesced packets */ - u64 rsc_flush; /* stats for flushed packets */ - u32 restart_queue; /* track tx queue restarts */ - u32 non_eop_descs; /* track hardware descriptor chaining */ - unsigned int size; /* length in bytes */ dma_addr_t dma; /* phys. address of descriptor ring */ + struct rcu_head rcu; + struct ixgbe_q_vector *q_vector; /* back-pointer to host q_vector */ } ____cacheline_internodealigned_in_smp; enum ixgbe_ring_f_enum { @@ -237,6 +273,9 @@ struct ixgbe_q_vector { unsigned int v_idx; /* index of q_vector within array, also used for * finding the bit in EICR and friends that * represents the vector for this ring */ +#ifdef CONFIG_IXGBE_DCA + int cpu; /* CPU for DCA */ +#endif struct napi_struct napi; DECLARE_BITMAP(rxr_idx, MAX_RX_QUEUES); /* Rx ring indices */ DECLARE_BITMAP(txr_idx, MAX_TX_QUEUES); /* Tx ring indices */ @@ -246,6 +285,7 @@ struct ixgbe_q_vector { u8 rx_itr; u32 eitr; cpumask_var_t affinity_mask; + char name[IFNAMSIZ + 9]; }; /* Helper macros to switch between ints/sec and what the register uses. @@ -294,7 +334,6 @@ struct ixgbe_adapter { u16 bd_number; struct work_struct reset_task; struct ixgbe_q_vector *q_vector[MAX_MSIX_Q_VECTORS]; - char name[MAX_MSIX_COUNT][IFNAMSIZ + 9]; struct ixgbe_dcb_config dcb_cfg; struct ixgbe_dcb_config temp_dcb_cfg; u8 dcb_set_bitmap; @@ -417,6 +456,7 @@ struct ixgbe_adapter { int node; struct work_struct check_overtemp_task; u32 interrupt_event; + char lsc_int_name[IFNAMSIZ + 9]; /* SR-IOV */ DECLARE_BITMAP(active_vfs, IXGBE_MAX_VF_FUNCTIONS); @@ -428,17 +468,25 @@ enum ixbge_state_t { __IXGBE_TESTING, __IXGBE_RESETTING, __IXGBE_DOWN, - __IXGBE_FDIR_INIT_DONE, __IXGBE_SFP_MODULE_NOT_FOUND }; +struct ixgbe_rsc_cb { + dma_addr_t dma; + u16 skb_cnt; + bool delay_unmap; +}; +#define IXGBE_RSC_CB(skb) ((struct ixgbe_rsc_cb *)(skb)->cb) + enum ixgbe_boards { board_82598, board_82599, + board_X540, }; extern struct ixgbe_info ixgbe_82598_info; extern struct ixgbe_info ixgbe_82599_info; +extern struct ixgbe_info ixgbe_X540_info; #ifdef CONFIG_IXGBE_DCB extern const struct dcbnl_rtnl_ops dcbnl_ops; extern int ixgbe_copy_dcb_cfg(struct ixgbe_dcb_config *src_dcb_cfg, @@ -454,26 +502,24 @@ extern void ixgbe_down(struct ixgbe_adapter *adapter); extern void ixgbe_reinit_locked(struct ixgbe_adapter *adapter); extern void ixgbe_reset(struct ixgbe_adapter *adapter); extern void ixgbe_set_ethtool_ops(struct net_device *netdev); -extern int ixgbe_setup_rx_resources(struct ixgbe_adapter *, struct ixgbe_ring *); -extern int ixgbe_setup_tx_resources(struct ixgbe_adapter *, struct ixgbe_ring *); -extern void ixgbe_free_rx_resources(struct ixgbe_adapter *, struct ixgbe_ring *); -extern void ixgbe_free_tx_resources(struct ixgbe_adapter *, struct ixgbe_ring *); +extern int ixgbe_setup_rx_resources(struct ixgbe_ring *); +extern int ixgbe_setup_tx_resources(struct ixgbe_ring *); +extern void ixgbe_free_rx_resources(struct ixgbe_ring *); +extern void ixgbe_free_tx_resources(struct ixgbe_ring *); extern void ixgbe_configure_rx_ring(struct ixgbe_adapter *,struct ixgbe_ring *); extern void ixgbe_configure_tx_ring(struct ixgbe_adapter *,struct ixgbe_ring *); extern void ixgbe_update_stats(struct ixgbe_adapter *adapter); extern int ixgbe_init_interrupt_scheme(struct ixgbe_adapter *adapter); extern void ixgbe_clear_interrupt_scheme(struct ixgbe_adapter *adapter); extern netdev_tx_t ixgbe_xmit_frame_ring(struct sk_buff *, - struct net_device *, struct ixgbe_adapter *, struct ixgbe_ring *); -extern void ixgbe_unmap_and_free_tx_resource(struct ixgbe_adapter *, +extern void ixgbe_unmap_and_free_tx_resource(struct ixgbe_ring *, struct ixgbe_tx_buffer *); -extern void ixgbe_alloc_rx_buffers(struct ixgbe_adapter *adapter, - struct ixgbe_ring *rx_ring, - int cleaned_count); +extern void ixgbe_alloc_rx_buffers(struct ixgbe_ring *, u16); extern void ixgbe_write_eitr(struct ixgbe_q_vector *); extern int ethtool_ioctl(struct ifreq *ifr); +extern u8 ixgbe_dcb_txq_to_tc(struct ixgbe_adapter *adapter, u8 index); 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); @@ -498,6 +544,10 @@ extern s32 ixgbe_atr_set_flex_byte_82599(struct ixgbe_atr_input *input, u16 flex_byte); extern s32 ixgbe_atr_set_l4type_82599(struct ixgbe_atr_input *input, u8 l4type); +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); #ifdef IXGBE_FCOE extern void ixgbe_configure_fcoe(struct ixgbe_adapter *adapter); diff --git a/drivers/net/ixgbe/ixgbe_82598.c b/drivers/net/ixgbe/ixgbe_82598.c index 9c02d6014cc4..d0f1d9d2c416 100644 --- a/drivers/net/ixgbe/ixgbe_82598.c +++ b/drivers/net/ixgbe/ixgbe_82598.c @@ -38,9 +38,6 @@ #define IXGBE_82598_MC_TBL_SIZE 128 #define IXGBE_82598_VFT_TBL_SIZE 128 -static s32 ixgbe_get_copper_link_capabilities_82598(struct ixgbe_hw *hw, - ixgbe_link_speed *speed, - bool *autoneg); static s32 ixgbe_setup_copper_link_82598(struct ixgbe_hw *hw, ixgbe_link_speed speed, bool autoneg, @@ -156,7 +153,7 @@ static s32 ixgbe_init_phy_ops_82598(struct ixgbe_hw *hw) if (mac->ops.get_media_type(hw) == ixgbe_media_type_copper) { mac->ops.setup_link = &ixgbe_setup_copper_link_82598; mac->ops.get_link_capabilities = - &ixgbe_get_copper_link_capabilities_82598; + &ixgbe_get_copper_link_capabilities_generic; } switch (hw->phy.type) { @@ -274,37 +271,6 @@ static s32 ixgbe_get_link_capabilities_82598(struct ixgbe_hw *hw, } /** - * ixgbe_get_copper_link_capabilities_82598 - Determines link capabilities - * @hw: pointer to hardware structure - * @speed: pointer to link speed - * @autoneg: boolean auto-negotiation value - * - * Determines the link capabilities by reading the AUTOC register. - **/ -static s32 ixgbe_get_copper_link_capabilities_82598(struct ixgbe_hw *hw, - ixgbe_link_speed *speed, - bool *autoneg) -{ - s32 status = IXGBE_ERR_LINK_SETUP; - u16 speed_ability; - - *speed = 0; - *autoneg = true; - - status = hw->phy.ops.read_reg(hw, MDIO_SPEED, MDIO_MMD_PMAPMD, - &speed_ability); - - if (status == 0) { - if (speed_ability & MDIO_SPEED_10G) - *speed |= IXGBE_LINK_SPEED_10GB_FULL; - if (speed_ability & MDIO_PMA_SPEED_1000) - *speed |= IXGBE_LINK_SPEED_1GB_FULL; - } - - return status; -} - -/** * ixgbe_get_media_type_82598 - Determines media type * @hw: pointer to hardware structure * @@ -357,6 +323,7 @@ static s32 ixgbe_fc_enable_82598(struct ixgbe_hw *hw, s32 packetbuf_num) u32 fctrl_reg; u32 rmcs_reg; u32 reg; + u32 rx_pba_size; u32 link_speed = 0; bool link_up; @@ -459,16 +426,18 @@ static s32 ixgbe_fc_enable_82598(struct ixgbe_hw *hw, s32 packetbuf_num) /* Set up and enable Rx high/low water mark thresholds, enable XON. */ if (hw->fc.current_mode & ixgbe_fc_tx_pause) { - if (hw->fc.send_xon) { - IXGBE_WRITE_REG(hw, IXGBE_FCRTL(packetbuf_num), - (hw->fc.low_water | IXGBE_FCRTL_XONE)); - } else { - IXGBE_WRITE_REG(hw, IXGBE_FCRTL(packetbuf_num), - hw->fc.low_water); - } + rx_pba_size = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(packetbuf_num)); + rx_pba_size >>= IXGBE_RXPBSIZE_SHIFT; + + reg = (rx_pba_size - hw->fc.low_water) << 6; + if (hw->fc.send_xon) + reg |= IXGBE_FCRTL_XONE; + IXGBE_WRITE_REG(hw, IXGBE_FCRTL(packetbuf_num), reg); + + reg = (rx_pba_size - hw->fc.high_water) << 10; + reg |= IXGBE_FCRTH_FCEN; - IXGBE_WRITE_REG(hw, IXGBE_FCRTH(packetbuf_num), - (hw->fc.high_water | IXGBE_FCRTH_FCEN)); + IXGBE_WRITE_REG(hw, IXGBE_FCRTH(packetbuf_num), reg); } /* Configure pause time (2 TCs per register) */ @@ -1222,6 +1191,7 @@ static struct ixgbe_mac_operations mac_ops_82598 = { static struct ixgbe_eeprom_operations eeprom_ops_82598 = { .init_params = &ixgbe_init_eeprom_params_generic, .read = &ixgbe_read_eerd_generic, + .calc_checksum = &ixgbe_calc_eeprom_checksum_generic, .validate_checksum = &ixgbe_validate_eeprom_checksum_generic, .update_checksum = &ixgbe_update_eeprom_checksum_generic, }; diff --git a/drivers/net/ixgbe/ixgbe_82599.c b/drivers/net/ixgbe/ixgbe_82599.c index 0bd8fbb5bfd0..385ccebb826c 100644 --- a/drivers/net/ixgbe/ixgbe_82599.c +++ b/drivers/net/ixgbe/ixgbe_82599.c @@ -56,9 +56,6 @@ static s32 ixgbe_setup_mac_link_82599(struct ixgbe_hw *hw, ixgbe_link_speed speed, bool autoneg, bool autoneg_wait_to_complete); -static s32 ixgbe_get_copper_link_capabilities_82599(struct ixgbe_hw *hw, - ixgbe_link_speed *speed, - bool *autoneg); static s32 ixgbe_setup_copper_link_82599(struct ixgbe_hw *hw, ixgbe_link_speed speed, bool autoneg, @@ -68,9 +65,9 @@ static s32 ixgbe_verify_fw_version_82599(struct ixgbe_hw *hw); static void ixgbe_init_mac_link_ops_82599(struct ixgbe_hw *hw) { struct ixgbe_mac_info *mac = &hw->mac; - if (hw->phy.multispeed_fiber) { - /* Set up dual speed SFP+ support */ - mac->ops.setup_link = &ixgbe_setup_mac_link_multispeed_fiber; + + /* enable the laser control functions for SFP+ fiber */ + if (mac->ops.get_media_type(hw) == ixgbe_media_type_fiber) { mac->ops.disable_tx_laser = &ixgbe_disable_tx_laser_multispeed_fiber; mac->ops.enable_tx_laser = @@ -80,6 +77,12 @@ static void ixgbe_init_mac_link_ops_82599(struct ixgbe_hw *hw) mac->ops.disable_tx_laser = NULL; mac->ops.enable_tx_laser = NULL; mac->ops.flap_tx_laser = NULL; + } + + if (hw->phy.multispeed_fiber) { + /* Set up dual speed SFP+ support */ + mac->ops.setup_link = &ixgbe_setup_mac_link_multispeed_fiber; + } else { if ((mac->ops.get_media_type(hw) == ixgbe_media_type_backplane) && (hw->phy.smart_speed == ixgbe_smart_speed_auto || @@ -174,7 +177,7 @@ static s32 ixgbe_init_phy_ops_82599(struct ixgbe_hw *hw) if (mac->ops.get_media_type(hw) == ixgbe_media_type_copper) { mac->ops.setup_link = &ixgbe_setup_copper_link_82599; mac->ops.get_link_capabilities = - &ixgbe_get_copper_link_capabilities_82599; + &ixgbe_get_copper_link_capabilities_generic; } /* Set necessary function pointers based on phy type */ @@ -184,6 +187,10 @@ static s32 ixgbe_init_phy_ops_82599(struct ixgbe_hw *hw) phy->ops.get_firmware_version = &ixgbe_get_phy_firmware_version_tnx; break; + case ixgbe_phy_aq: + phy->ops.get_firmware_version = + &ixgbe_get_phy_firmware_version_generic; + break; default: break; } @@ -290,37 +297,6 @@ out: } /** - * ixgbe_get_copper_link_capabilities_82599 - Determines link capabilities - * @hw: pointer to hardware structure - * @speed: pointer to link speed - * @autoneg: boolean auto-negotiation value - * - * Determines the link capabilities by reading the AUTOC register. - **/ -static s32 ixgbe_get_copper_link_capabilities_82599(struct ixgbe_hw *hw, - ixgbe_link_speed *speed, - bool *autoneg) -{ - s32 status = IXGBE_ERR_LINK_SETUP; - u16 speed_ability; - - *speed = 0; - *autoneg = true; - - status = hw->phy.ops.read_reg(hw, MDIO_SPEED, MDIO_MMD_PMAPMD, - &speed_ability); - - if (status == 0) { - if (speed_ability & MDIO_SPEED_10G) - *speed |= IXGBE_LINK_SPEED_10GB_FULL; - if (speed_ability & MDIO_PMA_SPEED_1000) - *speed |= IXGBE_LINK_SPEED_1GB_FULL; - } - - return status; -} - -/** * ixgbe_get_media_type_82599 - Get media type * @hw: pointer to hardware structure * @@ -332,7 +308,8 @@ static enum ixgbe_media_type ixgbe_get_media_type_82599(struct ixgbe_hw *hw) /* Detect if there is a copper PHY attached. */ if (hw->phy.type == ixgbe_phy_cu_unknown || - hw->phy.type == ixgbe_phy_tn) { + hw->phy.type == ixgbe_phy_tn || + hw->phy.type == ixgbe_phy_aq) { media_type = ixgbe_media_type_copper; goto out; } @@ -342,11 +319,13 @@ static enum ixgbe_media_type ixgbe_get_media_type_82599(struct ixgbe_hw *hw) case IXGBE_DEV_ID_82599_KX4_MEZZ: case IXGBE_DEV_ID_82599_COMBO_BACKPLANE: case IXGBE_DEV_ID_82599_KR: + case IXGBE_DEV_ID_82599_BACKPLANE_FCOE: case IXGBE_DEV_ID_82599_XAUI_LOM: /* Default device ID is mezzanine card KX/KX4 */ media_type = ixgbe_media_type_backplane; break; case IXGBE_DEV_ID_82599_SFP: + case IXGBE_DEV_ID_82599_SFP_FCOE: case IXGBE_DEV_ID_82599_SFP_EM: media_type = ixgbe_media_type_fiber; break; @@ -1924,6 +1903,7 @@ static u32 ixgbe_get_supported_physical_layer_82599(struct ixgbe_hw *hw) hw->phy.ops.identify(hw); if (hw->phy.type == ixgbe_phy_tn || + hw->phy.type == ixgbe_phy_aq || hw->phy.type == ixgbe_phy_cu_unknown) { hw->phy.ops.read_reg(hw, MDIO_PMA_EXTABLE, MDIO_MMD_PMAPMD, &ext_ability); @@ -2125,51 +2105,6 @@ fw_version_out: return status; } -/** - * ixgbe_get_wwn_prefix_82599 - Get alternative WWNN/WWPN prefix from - * the EEPROM - * @hw: pointer to hardware structure - * @wwnn_prefix: the alternative WWNN prefix - * @wwpn_prefix: the alternative WWPN prefix - * - * This function will read the EEPROM from the alternative SAN MAC address - * block to check the support for the alternative WWNN/WWPN prefix support. - **/ -static s32 ixgbe_get_wwn_prefix_82599(struct ixgbe_hw *hw, u16 *wwnn_prefix, - u16 *wwpn_prefix) -{ - u16 offset, caps; - u16 alt_san_mac_blk_offset; - - /* clear output first */ - *wwnn_prefix = 0xFFFF; - *wwpn_prefix = 0xFFFF; - - /* check if alternative SAN MAC is supported */ - hw->eeprom.ops.read(hw, IXGBE_ALT_SAN_MAC_ADDR_BLK_PTR, - &alt_san_mac_blk_offset); - - if ((alt_san_mac_blk_offset == 0) || - (alt_san_mac_blk_offset == 0xFFFF)) - goto wwn_prefix_out; - - /* check capability in alternative san mac address block */ - offset = alt_san_mac_blk_offset + IXGBE_ALT_SAN_MAC_ADDR_CAPS_OFFSET; - hw->eeprom.ops.read(hw, offset, &caps); - if (!(caps & IXGBE_ALT_SAN_MAC_ADDR_CAPS_ALTWWN)) - goto wwn_prefix_out; - - /* get the corresponding prefix for WWNN/WWPN */ - offset = alt_san_mac_blk_offset + IXGBE_ALT_SAN_MAC_ADDR_WWNN_OFFSET; - hw->eeprom.ops.read(hw, offset, wwnn_prefix); - - offset = alt_san_mac_blk_offset + IXGBE_ALT_SAN_MAC_ADDR_WWPN_OFFSET; - hw->eeprom.ops.read(hw, offset, wwpn_prefix); - -wwn_prefix_out: - return 0; -} - static struct ixgbe_mac_operations mac_ops_82599 = { .init_hw = &ixgbe_init_hw_generic, .reset_hw = &ixgbe_reset_hw_82599, @@ -2181,7 +2116,7 @@ static struct ixgbe_mac_operations mac_ops_82599 = { .get_mac_addr = &ixgbe_get_mac_addr_generic, .get_san_mac_addr = &ixgbe_get_san_mac_addr_generic, .get_device_caps = &ixgbe_get_device_caps_82599, - .get_wwn_prefix = &ixgbe_get_wwn_prefix_82599, + .get_wwn_prefix = &ixgbe_get_wwn_prefix_generic, .stop_adapter = &ixgbe_stop_adapter_generic, .get_bus_info = &ixgbe_get_bus_info_generic, .set_lan_id = &ixgbe_set_lan_id_multi_port_pcie, @@ -2214,6 +2149,7 @@ static struct ixgbe_eeprom_operations eeprom_ops_82599 = { .init_params = &ixgbe_init_eeprom_params_generic, .read = &ixgbe_read_eerd_generic, .write = &ixgbe_write_eeprom_generic, + .calc_checksum = &ixgbe_calc_eeprom_checksum_generic, .validate_checksum = &ixgbe_validate_eeprom_checksum_generic, .update_checksum = &ixgbe_update_eeprom_checksum_generic, }; @@ -2240,5 +2176,5 @@ struct ixgbe_info ixgbe_82599_info = { .mac_ops = &mac_ops_82599, .eeprom_ops = &eeprom_ops_82599, .phy_ops = &phy_ops_82599, - .mbx_ops = &mbx_ops_82599, + .mbx_ops = &mbx_ops_generic, }; diff --git a/drivers/net/ixgbe/ixgbe_common.c b/drivers/net/ixgbe/ixgbe_common.c index e3eca1316389..cc11e422ce9b 100644 --- a/drivers/net/ixgbe/ixgbe_common.c +++ b/drivers/net/ixgbe/ixgbe_common.c @@ -45,14 +45,12 @@ static u16 ixgbe_shift_in_eeprom_bits(struct ixgbe_hw *hw, u16 count); static void ixgbe_raise_eeprom_clk(struct ixgbe_hw *hw, u32 *eec); static void ixgbe_lower_eeprom_clk(struct ixgbe_hw *hw, u32 *eec); static void ixgbe_release_eeprom(struct ixgbe_hw *hw); -static u16 ixgbe_calc_eeprom_checksum(struct ixgbe_hw *hw); static void ixgbe_enable_rar(struct ixgbe_hw *hw, u32 index); static void ixgbe_disable_rar(struct ixgbe_hw *hw, u32 index); static s32 ixgbe_mta_vector(struct ixgbe_hw *hw, u8 *mc_addr); static void ixgbe_add_uc_addr(struct ixgbe_hw *hw, u8 *addr, u32 vmdq); static s32 ixgbe_setup_fc(struct ixgbe_hw *hw, s32 packetbuf_num); -static s32 ixgbe_poll_eerd_eewr_done(struct ixgbe_hw *hw, u32 ee_reg); /** * ixgbe_start_hw_generic - Prepare hardware for Tx/Rx @@ -198,30 +196,110 @@ s32 ixgbe_clear_hw_cntrs_generic(struct ixgbe_hw *hw) } /** - * ixgbe_read_pba_num_generic - Reads part number from EEPROM + * ixgbe_read_pba_string_generic - Reads part number string from EEPROM * @hw: pointer to hardware structure - * @pba_num: stores the part number from the EEPROM + * @pba_num: stores the part number string from the EEPROM + * @pba_num_size: part number string buffer length * - * Reads the part number from the EEPROM. + * Reads the part number string from the EEPROM. **/ -s32 ixgbe_read_pba_num_generic(struct ixgbe_hw *hw, u32 *pba_num) +s32 ixgbe_read_pba_string_generic(struct ixgbe_hw *hw, u8 *pba_num, + u32 pba_num_size) { s32 ret_val; u16 data; + u16 pba_ptr; + u16 offset; + u16 length; + + if (pba_num == NULL) { + hw_dbg(hw, "PBA string buffer was null\n"); + return IXGBE_ERR_INVALID_ARGUMENT; + } ret_val = hw->eeprom.ops.read(hw, IXGBE_PBANUM0_PTR, &data); if (ret_val) { hw_dbg(hw, "NVM Read Error\n"); return ret_val; } - *pba_num = (u32)(data << 16); - ret_val = hw->eeprom.ops.read(hw, IXGBE_PBANUM1_PTR, &data); + ret_val = hw->eeprom.ops.read(hw, IXGBE_PBANUM1_PTR, &pba_ptr); if (ret_val) { hw_dbg(hw, "NVM Read Error\n"); return ret_val; } - *pba_num |= data; + + /* + * if data is not ptr guard the PBA must be in legacy format which + * means pba_ptr is actually our second data word for the PBA number + * and we can decode it into an ascii string + */ + if (data != IXGBE_PBANUM_PTR_GUARD) { + hw_dbg(hw, "NVM PBA number is not stored as string\n"); + + /* we will need 11 characters to store the PBA */ + if (pba_num_size < 11) { + hw_dbg(hw, "PBA string buffer too small\n"); + return IXGBE_ERR_NO_SPACE; + } + + /* extract hex string from data and pba_ptr */ + pba_num[0] = (data >> 12) & 0xF; + pba_num[1] = (data >> 8) & 0xF; + pba_num[2] = (data >> 4) & 0xF; + pba_num[3] = data & 0xF; + pba_num[4] = (pba_ptr >> 12) & 0xF; + pba_num[5] = (pba_ptr >> 8) & 0xF; + pba_num[6] = '-'; + pba_num[7] = 0; + pba_num[8] = (pba_ptr >> 4) & 0xF; + pba_num[9] = pba_ptr & 0xF; + + /* put a null character on the end of our string */ + pba_num[10] = '\0'; + + /* switch all the data but the '-' to hex char */ + for (offset = 0; offset < 10; offset++) { + if (pba_num[offset] < 0xA) + pba_num[offset] += '0'; + else if (pba_num[offset] < 0x10) + pba_num[offset] += 'A' - 0xA; + } + + return 0; + } + + ret_val = hw->eeprom.ops.read(hw, pba_ptr, &length); + if (ret_val) { + hw_dbg(hw, "NVM Read Error\n"); + return ret_val; + } + + if (length == 0xFFFF || length == 0) { + hw_dbg(hw, "NVM PBA number section invalid length\n"); + return IXGBE_ERR_PBA_SECTION; + } + + /* check if pba_num buffer is big enough */ + if (pba_num_size < (((u32)length * 2) - 1)) { + hw_dbg(hw, "PBA string buffer too small\n"); + return IXGBE_ERR_NO_SPACE; + } + + /* trim pba length from start of string */ + pba_ptr++; + length--; + + for (offset = 0; offset < length; offset++) { + ret_val = hw->eeprom.ops.read(hw, pba_ptr + offset, &data); + if (ret_val) { + hw_dbg(hw, "NVM Read Error\n"); + return ret_val; + } + pba_num[offset * 2] = (u8)(data >> 8); + pba_num[(offset * 2) + 1] = (u8)(data & 0xFF); + } + pba_num[offset * 2] = '\0'; return 0; } @@ -638,7 +716,7 @@ out: * Polls the status bit (bit 1) of the EERD or EEWR to determine when the * read or write is done respectively. **/ -static s32 ixgbe_poll_eerd_eewr_done(struct ixgbe_hw *hw, u32 ee_reg) +s32 ixgbe_poll_eerd_eewr_done(struct ixgbe_hw *hw, u32 ee_reg) { u32 i; u32 reg; @@ -1009,7 +1087,7 @@ static void ixgbe_release_eeprom(struct ixgbe_hw *hw) * ixgbe_calc_eeprom_checksum - Calculates and returns the checksum * @hw: pointer to hardware structure **/ -static u16 ixgbe_calc_eeprom_checksum(struct ixgbe_hw *hw) +u16 ixgbe_calc_eeprom_checksum_generic(struct ixgbe_hw *hw) { u16 i; u16 j; @@ -1072,7 +1150,7 @@ s32 ixgbe_validate_eeprom_checksum_generic(struct ixgbe_hw *hw, status = hw->eeprom.ops.read(hw, 0, &checksum); if (status == 0) { - checksum = ixgbe_calc_eeprom_checksum(hw); + checksum = hw->eeprom.ops.calc_checksum(hw); hw->eeprom.ops.read(hw, IXGBE_EEPROM_CHECKSUM, &read_checksum); @@ -1110,7 +1188,7 @@ s32 ixgbe_update_eeprom_checksum_generic(struct ixgbe_hw *hw) status = hw->eeprom.ops.read(hw, 0, &checksum); if (status == 0) { - checksum = ixgbe_calc_eeprom_checksum(hw); + checksum = hw->eeprom.ops.calc_checksum(hw); status = hw->eeprom.ops.write(hw, IXGBE_EEPROM_CHECKSUM, checksum); } else { @@ -1595,6 +1673,7 @@ s32 ixgbe_fc_enable_generic(struct ixgbe_hw *hw, s32 packetbuf_num) u32 mflcn_reg, fccfg_reg; u32 reg; u32 rx_pba_size; + u32 fcrtl, fcrth; #ifdef CONFIG_DCB if (hw->fc.requested_mode == ixgbe_fc_pfc) @@ -1671,41 +1750,21 @@ s32 ixgbe_fc_enable_generic(struct ixgbe_hw *hw, s32 packetbuf_num) IXGBE_WRITE_REG(hw, IXGBE_MFLCN, mflcn_reg); IXGBE_WRITE_REG(hw, IXGBE_FCCFG, fccfg_reg); - reg = IXGBE_READ_REG(hw, IXGBE_MTQC); - /* Thresholds are different for link flow control when in DCB mode */ - if (reg & IXGBE_MTQC_RT_ENA) { - rx_pba_size = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(packetbuf_num)); + rx_pba_size = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(packetbuf_num)); + rx_pba_size >>= IXGBE_RXPBSIZE_SHIFT; - /* Always disable XON for LFC when in DCB mode */ - reg = (rx_pba_size >> 5) & 0xFFE0; - IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(packetbuf_num), reg); + fcrth = (rx_pba_size - hw->fc.high_water) << 10; + fcrtl = (rx_pba_size - hw->fc.low_water) << 10; - reg = (rx_pba_size >> 2) & 0xFFE0; - if (hw->fc.current_mode & ixgbe_fc_tx_pause) - reg |= IXGBE_FCRTH_FCEN; - IXGBE_WRITE_REG(hw, IXGBE_FCRTH_82599(packetbuf_num), reg); - } else { - /* - * Set up and enable Rx high/low water mark thresholds, - * enable XON. - */ - if (hw->fc.current_mode & ixgbe_fc_tx_pause) { - if (hw->fc.send_xon) { - IXGBE_WRITE_REG(hw, - IXGBE_FCRTL_82599(packetbuf_num), - (hw->fc.low_water | - IXGBE_FCRTL_XONE)); - } else { - IXGBE_WRITE_REG(hw, - IXGBE_FCRTL_82599(packetbuf_num), - hw->fc.low_water); - } - - IXGBE_WRITE_REG(hw, IXGBE_FCRTH_82599(packetbuf_num), - (hw->fc.high_water | IXGBE_FCRTH_FCEN)); - } + if (hw->fc.current_mode & ixgbe_fc_tx_pause) { + fcrth |= IXGBE_FCRTH_FCEN; + if (hw->fc.send_xon) + fcrtl |= IXGBE_FCRTL_XONE; } + IXGBE_WRITE_REG(hw, IXGBE_FCRTH_82599(packetbuf_num), fcrth); + IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(packetbuf_num), fcrtl); + /* Configure pause time (2 TCs per register) */ reg = IXGBE_READ_REG(hw, IXGBE_FCTTV(packetbuf_num / 2)); if ((packetbuf_num & 1) == 0) @@ -2705,3 +2764,48 @@ s32 ixgbe_check_mac_link_generic(struct ixgbe_hw *hw, ixgbe_link_speed *speed, return 0; } + +/** + * ixgbe_get_wwn_prefix_generic Get alternative WWNN/WWPN prefix from + * the EEPROM + * @hw: pointer to hardware structure + * @wwnn_prefix: the alternative WWNN prefix + * @wwpn_prefix: the alternative WWPN prefix + * + * This function will read the EEPROM from the alternative SAN MAC address + * block to check the support for the alternative WWNN/WWPN prefix support. + **/ +s32 ixgbe_get_wwn_prefix_generic(struct ixgbe_hw *hw, u16 *wwnn_prefix, + u16 *wwpn_prefix) +{ + u16 offset, caps; + u16 alt_san_mac_blk_offset; + + /* clear output first */ + *wwnn_prefix = 0xFFFF; + *wwpn_prefix = 0xFFFF; + + /* check if alternative SAN MAC is supported */ + hw->eeprom.ops.read(hw, IXGBE_ALT_SAN_MAC_ADDR_BLK_PTR, + &alt_san_mac_blk_offset); + + if ((alt_san_mac_blk_offset == 0) || + (alt_san_mac_blk_offset == 0xFFFF)) + goto wwn_prefix_out; + + /* check capability in alternative san mac address block */ + offset = alt_san_mac_blk_offset + IXGBE_ALT_SAN_MAC_ADDR_CAPS_OFFSET; + hw->eeprom.ops.read(hw, offset, &caps); + if (!(caps & IXGBE_ALT_SAN_MAC_ADDR_CAPS_ALTWWN)) + goto wwn_prefix_out; + + /* get the corresponding prefix for WWNN/WWPN */ + offset = alt_san_mac_blk_offset + IXGBE_ALT_SAN_MAC_ADDR_WWNN_OFFSET; + hw->eeprom.ops.read(hw, offset, wwnn_prefix); + + offset = alt_san_mac_blk_offset + IXGBE_ALT_SAN_MAC_ADDR_WWPN_OFFSET; + hw->eeprom.ops.read(hw, offset, wwpn_prefix); + +wwn_prefix_out: + return 0; +} diff --git a/drivers/net/ixgbe/ixgbe_common.h b/drivers/net/ixgbe/ixgbe_common.h index 424c223437dc..e1f980a8a09d 100644 --- a/drivers/net/ixgbe/ixgbe_common.h +++ b/drivers/net/ixgbe/ixgbe_common.h @@ -35,7 +35,8 @@ s32 ixgbe_init_ops_generic(struct ixgbe_hw *hw); s32 ixgbe_init_hw_generic(struct ixgbe_hw *hw); s32 ixgbe_start_hw_generic(struct ixgbe_hw *hw); s32 ixgbe_clear_hw_cntrs_generic(struct ixgbe_hw *hw); -s32 ixgbe_read_pba_num_generic(struct ixgbe_hw *hw, u32 *pba_num); +s32 ixgbe_read_pba_string_generic(struct ixgbe_hw *hw, u8 *pba_num, + u32 pba_num_size); s32 ixgbe_get_mac_addr_generic(struct ixgbe_hw *hw, u8 *mac_addr); s32 ixgbe_get_bus_info_generic(struct ixgbe_hw *hw); void ixgbe_set_lan_id_multi_port_pcie(struct ixgbe_hw *hw); @@ -49,9 +50,11 @@ s32 ixgbe_write_eeprom_generic(struct ixgbe_hw *hw, u16 offset, u16 data); s32 ixgbe_read_eerd_generic(struct ixgbe_hw *hw, u16 offset, u16 *data); s32 ixgbe_read_eeprom_bit_bang_generic(struct ixgbe_hw *hw, u16 offset, u16 *data); +u16 ixgbe_calc_eeprom_checksum_generic(struct ixgbe_hw *hw); s32 ixgbe_validate_eeprom_checksum_generic(struct ixgbe_hw *hw, u16 *checksum_val); s32 ixgbe_update_eeprom_checksum_generic(struct ixgbe_hw *hw); +s32 ixgbe_poll_eerd_eewr_done(struct ixgbe_hw *hw, u32 ee_reg); s32 ixgbe_set_rar_generic(struct ixgbe_hw *hw, u32 index, u8 *addr, u32 vmdq, u32 enable_addr); @@ -81,7 +84,8 @@ s32 ixgbe_clear_vfta_generic(struct ixgbe_hw *hw); s32 ixgbe_check_mac_link_generic(struct ixgbe_hw *hw, ixgbe_link_speed *speed, bool *link_up, bool link_up_wait_to_complete); - +s32 ixgbe_get_wwn_prefix_generic(struct ixgbe_hw *hw, u16 *wwnn_prefix, + u16 *wwpn_prefix); s32 ixgbe_blink_led_start_generic(struct ixgbe_hw *hw, u32 index); s32 ixgbe_blink_led_stop_generic(struct ixgbe_hw *hw, u32 index); diff --git a/drivers/net/ixgbe/ixgbe_dcb.c b/drivers/net/ixgbe/ixgbe_dcb.c index 0d44c6470ca3..d16c260c1f50 100644 --- a/drivers/net/ixgbe/ixgbe_dcb.c +++ b/drivers/net/ixgbe/ixgbe_dcb.c @@ -42,7 +42,8 @@ * It should be called only after the rules are checked by * ixgbe_dcb_check_config(). */ -s32 ixgbe_dcb_calculate_tc_credits(struct ixgbe_dcb_config *dcb_config, +s32 ixgbe_dcb_calculate_tc_credits(struct ixgbe_hw *hw, + struct ixgbe_dcb_config *dcb_config, int max_frame, u8 direction) { struct tc_bw_alloc *p; @@ -124,7 +125,8 @@ s32 ixgbe_dcb_calculate_tc_credits(struct ixgbe_dcb_config *dcb_config, * credit may not be enough to send out a TSO * packet in descriptor plane arbitration. */ - if (credit_max && + if ((hw->mac.type == ixgbe_mac_82598EB) && + credit_max && (credit_max < MINIMUM_CREDIT_FOR_TSO)) credit_max = MINIMUM_CREDIT_FOR_TSO; @@ -150,10 +152,17 @@ s32 ixgbe_dcb_hw_config(struct ixgbe_hw *hw, struct ixgbe_dcb_config *dcb_config) { s32 ret = 0; - if (hw->mac.type == ixgbe_mac_82598EB) + switch (hw->mac.type) { + case ixgbe_mac_82598EB: ret = ixgbe_dcb_hw_config_82598(hw, dcb_config); - else if (hw->mac.type == ixgbe_mac_82599EB) + break; + case ixgbe_mac_82599EB: + case ixgbe_mac_X540: ret = ixgbe_dcb_hw_config_82599(hw, dcb_config); + break; + default: + break; + } return ret; } diff --git a/drivers/net/ixgbe/ixgbe_dcb.h b/drivers/net/ixgbe/ixgbe_dcb.h index 0208a87b129e..1cfe38ee1644 100644 --- a/drivers/net/ixgbe/ixgbe_dcb.h +++ b/drivers/net/ixgbe/ixgbe_dcb.h @@ -150,7 +150,8 @@ struct ixgbe_dcb_config { /* DCB driver APIs */ /* DCB credits calculation */ -s32 ixgbe_dcb_calculate_tc_credits(struct ixgbe_dcb_config *, int, u8); +s32 ixgbe_dcb_calculate_tc_credits(struct ixgbe_hw *, + struct ixgbe_dcb_config *, int, u8); /* DCB hw initialization */ s32 ixgbe_dcb_hw_config(struct ixgbe_hw *, struct ixgbe_dcb_config *); diff --git a/drivers/net/ixgbe/ixgbe_dcb_82598.c b/drivers/net/ixgbe/ixgbe_dcb_82598.c index 50288bcadc59..9a5e89c12e05 100644 --- a/drivers/net/ixgbe/ixgbe_dcb_82598.c +++ b/drivers/net/ixgbe/ixgbe_dcb_82598.c @@ -256,21 +256,17 @@ s32 ixgbe_dcb_config_pfc_82598(struct ixgbe_hw *hw, * for each traffic class. */ for (i = 0; i < MAX_TRAFFIC_CLASS; i++) { - if (dcb_config->rx_pba_cfg == pba_equal) { - rx_pba_size = IXGBE_RXPBSIZE_64KB; - } else { - rx_pba_size = (i < 4) ? IXGBE_RXPBSIZE_80KB - : IXGBE_RXPBSIZE_48KB; - } + rx_pba_size = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(i)); + rx_pba_size >>= IXGBE_RXPBSIZE_SHIFT; + reg = (rx_pba_size - hw->fc.low_water) << 10; - reg = ((rx_pba_size >> 5) & 0xFFF0); if (dcb_config->tc_config[i].dcb_pfc == pfc_enabled_tx || dcb_config->tc_config[i].dcb_pfc == pfc_enabled_full) reg |= IXGBE_FCRTL_XONE; IXGBE_WRITE_REG(hw, IXGBE_FCRTL(i), reg); - reg = ((rx_pba_size >> 2) & 0xFFF0); + reg = (rx_pba_size - hw->fc.high_water) << 10; if (dcb_config->tc_config[i].dcb_pfc == pfc_enabled_tx || dcb_config->tc_config[i].dcb_pfc == pfc_enabled_full) reg |= IXGBE_FCRTH_FCEN; diff --git a/drivers/net/ixgbe/ixgbe_dcb_82599.c b/drivers/net/ixgbe/ixgbe_dcb_82599.c index 05f224715073..374e1f74d0f5 100644 --- a/drivers/net/ixgbe/ixgbe_dcb_82599.c +++ b/drivers/net/ixgbe/ixgbe_dcb_82599.c @@ -251,19 +251,17 @@ s32 ixgbe_dcb_config_pfc_82599(struct ixgbe_hw *hw, /* Configure PFC Tx thresholds per TC */ for (i = 0; i < MAX_TRAFFIC_CLASS; i++) { - if (dcb_config->rx_pba_cfg == pba_equal) - rx_pba_size = IXGBE_RXPBSIZE_64KB; - else - rx_pba_size = (i < 4) ? IXGBE_RXPBSIZE_80KB - : IXGBE_RXPBSIZE_48KB; + rx_pba_size = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(i)); + rx_pba_size >>= IXGBE_RXPBSIZE_SHIFT; + + reg = (rx_pba_size - hw->fc.low_water) << 10; - reg = ((rx_pba_size >> 5) & 0xFFE0); if (dcb_config->tc_config[i].dcb_pfc == pfc_enabled_full || dcb_config->tc_config[i].dcb_pfc == pfc_enabled_tx) reg |= IXGBE_FCRTL_XONE; IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(i), reg); - reg = ((rx_pba_size >> 2) & 0xFFE0); + reg = (rx_pba_size - hw->fc.high_water) << 10; if (dcb_config->tc_config[i].dcb_pfc == pfc_enabled_full || dcb_config->tc_config[i].dcb_pfc == pfc_enabled_tx) reg |= IXGBE_FCRTH_FCEN; diff --git a/drivers/net/ixgbe/ixgbe_dcb_nl.c b/drivers/net/ixgbe/ixgbe_dcb_nl.c index b53b465e24af..bf566e8a455e 100644 --- a/drivers/net/ixgbe/ixgbe_dcb_nl.c +++ b/drivers/net/ixgbe/ixgbe_dcb_nl.c @@ -130,15 +130,21 @@ static u8 ixgbe_dcbnl_set_state(struct net_device *netdev, u8 state) netdev->netdev_ops->ndo_stop(netdev); ixgbe_clear_interrupt_scheme(adapter); - if (adapter->hw.mac.type == ixgbe_mac_82598EB) { + adapter->flags &= ~IXGBE_FLAG_RSS_ENABLED; + switch (adapter->hw.mac.type) { + case ixgbe_mac_82598EB: adapter->last_lfc_mode = adapter->hw.fc.current_mode; adapter->hw.fc.requested_mode = ixgbe_fc_none; - } - adapter->flags &= ~IXGBE_FLAG_RSS_ENABLED; - if (adapter->hw.mac.type == ixgbe_mac_82599EB) { + break; + 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; ixgbe_init_interrupt_scheme(adapter); if (netif_running(netdev)) @@ -155,8 +161,14 @@ static u8 ixgbe_dcbnl_set_state(struct net_device *netdev, u8 state) adapter->dcb_cfg.pfc_mode_enable = false; adapter->flags &= ~IXGBE_FLAG_DCB_ENABLED; adapter->flags |= IXGBE_FLAG_RSS_ENABLED; - if (adapter->hw.mac.type == ixgbe_mac_82599EB) + switch (adapter->hw.mac.type) { + case ixgbe_mac_82599EB: + case ixgbe_mac_X540: adapter->flags |= IXGBE_FLAG_FDIR_HASH_CAPABLE; + break; + default: + break; + } ixgbe_init_interrupt_scheme(adapter); if (netif_running(netdev)) @@ -178,9 +190,14 @@ static void ixgbe_dcbnl_get_perm_hw_addr(struct net_device *netdev, for (i = 0; i < netdev->addr_len; i++) perm_addr[i] = adapter->hw.mac.perm_addr[i]; - if (adapter->hw.mac.type == ixgbe_mac_82599EB) { + switch (adapter->hw.mac.type) { + case ixgbe_mac_82599EB: + case ixgbe_mac_X540: for (j = 0; j < netdev->addr_len; j++, i++) perm_addr[i] = adapter->hw.mac.san_addr[j]; + break; + default: + break; } } @@ -366,15 +383,29 @@ static u8 ixgbe_dcbnl_set_all(struct net_device *netdev) } if (adapter->dcb_cfg.pfc_mode_enable) { - if ((adapter->hw.mac.type != ixgbe_mac_82598EB) && - (adapter->hw.fc.current_mode != ixgbe_fc_pfc)) - adapter->last_lfc_mode = adapter->hw.fc.current_mode; + switch (adapter->hw.mac.type) { + case ixgbe_mac_82599EB: + case ixgbe_mac_X540: + if (adapter->hw.fc.current_mode != ixgbe_fc_pfc) + adapter->last_lfc_mode = + adapter->hw.fc.current_mode; + break; + default: + break; + } adapter->hw.fc.requested_mode = ixgbe_fc_pfc; } else { - if (adapter->hw.mac.type != ixgbe_mac_82598EB) - adapter->hw.fc.requested_mode = adapter->last_lfc_mode; - else + switch (adapter->hw.mac.type) { + case ixgbe_mac_82598EB: adapter->hw.fc.requested_mode = ixgbe_fc_none; + break; + case ixgbe_mac_82599EB: + case ixgbe_mac_X540: + adapter->hw.fc.requested_mode = adapter->last_lfc_mode; + break; + default: + break; + } } if (adapter->dcb_set_bitmap & BIT_RESETLINK) { diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c index 3dc731c22ff2..ef3f9105a05d 100644 --- a/drivers/net/ixgbe/ixgbe_ethtool.c +++ b/drivers/net/ixgbe/ixgbe_ethtool.c @@ -185,6 +185,16 @@ static int ixgbe_get_settings(struct net_device *netdev, ADVERTISED_FIBRE); ecmd->port = PORT_FIBRE; ecmd->autoneg = AUTONEG_DISABLE; + } else if ((hw->device_id == IXGBE_DEV_ID_82599_COMBO_BACKPLANE) || + (hw->device_id == IXGBE_DEV_ID_82599_KX4_MEZZ)) { + ecmd->supported |= (SUPPORTED_1000baseT_Full | + SUPPORTED_Autoneg | + SUPPORTED_FIBRE); + ecmd->advertising = (ADVERTISED_10000baseT_Full | + ADVERTISED_1000baseT_Full | + ADVERTISED_Autoneg | + ADVERTISED_FIBRE); + ecmd->port = PORT_FIBRE; } else { ecmd->supported |= (SUPPORTED_1000baseT_Full | SUPPORTED_FIBRE); @@ -204,6 +214,7 @@ static int ixgbe_get_settings(struct net_device *netdev, /* Get PHY type */ switch (adapter->hw.phy.type) { case ixgbe_phy_tn: + case ixgbe_phy_aq: case ixgbe_phy_cu_unknown: /* Copper 10G-BASET */ ecmd->port = PORT_TP; @@ -332,13 +343,6 @@ static void ixgbe_get_pauseparam(struct net_device *netdev, else pause->autoneg = 1; -#ifdef CONFIG_DCB - if (hw->fc.current_mode == ixgbe_fc_pfc) { - pause->rx_pause = 0; - pause->tx_pause = 0; - } - -#endif if (hw->fc.current_mode == ixgbe_fc_rx_pause) { pause->rx_pause = 1; } else if (hw->fc.current_mode == ixgbe_fc_tx_pause) { @@ -346,6 +350,11 @@ static void ixgbe_get_pauseparam(struct net_device *netdev, } else if (hw->fc.current_mode == ixgbe_fc_full) { pause->rx_pause = 1; pause->tx_pause = 1; +#ifdef CONFIG_DCB + } else if (hw->fc.current_mode == ixgbe_fc_pfc) { + pause->rx_pause = 0; + pause->tx_pause = 0; +#endif } } @@ -363,7 +372,6 @@ static int ixgbe_set_pauseparam(struct net_device *netdev, return -EINVAL; #endif - fc = hw->fc; if (pause->autoneg != AUTONEG_ENABLE) @@ -412,11 +420,6 @@ static int ixgbe_set_rx_csum(struct net_device *netdev, u32 data) else adapter->flags &= ~IXGBE_FLAG_RX_CSUM_ENABLED; - if (netif_running(netdev)) - ixgbe_reinit_locked(adapter); - else - ixgbe_reset(adapter); - return 0; } @@ -428,16 +431,21 @@ static u32 ixgbe_get_tx_csum(struct net_device *netdev) static int ixgbe_set_tx_csum(struct net_device *netdev, u32 data) { struct ixgbe_adapter *adapter = netdev_priv(netdev); + u32 feature_list; - if (data) { - netdev->features |= (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM); - if (adapter->hw.mac.type == ixgbe_mac_82599EB) - netdev->features |= NETIF_F_SCTP_CSUM; - } else { - netdev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM); - if (adapter->hw.mac.type == ixgbe_mac_82599EB) - netdev->features &= ~NETIF_F_SCTP_CSUM; + feature_list = (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM); + switch (adapter->hw.mac.type) { + case ixgbe_mac_82599EB: + case ixgbe_mac_X540: + feature_list |= NETIF_F_SCTP_CSUM; + break; + default: + break; } + if (data) + netdev->features |= feature_list; + else + netdev->features &= ~feature_list; return 0; } @@ -530,10 +538,20 @@ static void ixgbe_get_regs(struct net_device *netdev, regs_buff[32] = IXGBE_READ_REG(hw, IXGBE_FCTTV(1)); regs_buff[33] = IXGBE_READ_REG(hw, IXGBE_FCTTV(2)); regs_buff[34] = IXGBE_READ_REG(hw, IXGBE_FCTTV(3)); - for (i = 0; i < 8; i++) - regs_buff[35 + i] = IXGBE_READ_REG(hw, IXGBE_FCRTL(i)); - for (i = 0; i < 8; i++) - regs_buff[43 + i] = IXGBE_READ_REG(hw, IXGBE_FCRTH(i)); + for (i = 0; i < 8; i++) { + switch (hw->mac.type) { + case ixgbe_mac_82598EB: + regs_buff[35 + i] = IXGBE_READ_REG(hw, IXGBE_FCRTL(i)); + regs_buff[43 + i] = IXGBE_READ_REG(hw, IXGBE_FCRTH(i)); + break; + case ixgbe_mac_82599EB: + regs_buff[35 + i] = IXGBE_READ_REG(hw, IXGBE_FCRTL_82599(i)); + regs_buff[43 + i] = IXGBE_READ_REG(hw, IXGBE_FCRTH_82599(i)); + break; + default: + break; + } + } regs_buff[51] = IXGBE_READ_REG(hw, IXGBE_FCRTV); regs_buff[52] = IXGBE_READ_REG(hw, IXGBE_TFCS); @@ -615,6 +633,7 @@ static void ixgbe_get_regs(struct net_device *netdev, regs_buff[827] = IXGBE_READ_REG(hw, IXGBE_WUPM); regs_buff[828] = IXGBE_READ_REG(hw, IXGBE_FHFT(0)); + /* DCB */ regs_buff[829] = IXGBE_READ_REG(hw, IXGBE_RMCS); regs_buff[830] = IXGBE_READ_REG(hw, IXGBE_DPMCS); regs_buff[831] = IXGBE_READ_REG(hw, IXGBE_PDPMCS); @@ -905,13 +924,11 @@ static int ixgbe_set_ringparam(struct net_device *netdev, memcpy(&temp_tx_ring[i], adapter->tx_ring[i], sizeof(struct ixgbe_ring)); temp_tx_ring[i].count = new_tx_count; - err = ixgbe_setup_tx_resources(adapter, - &temp_tx_ring[i]); + err = ixgbe_setup_tx_resources(&temp_tx_ring[i]); if (err) { while (i) { i--; - ixgbe_free_tx_resources(adapter, - &temp_tx_ring[i]); + ixgbe_free_tx_resources(&temp_tx_ring[i]); } goto clear_reset; } @@ -930,13 +947,11 @@ static int ixgbe_set_ringparam(struct net_device *netdev, memcpy(&temp_rx_ring[i], adapter->rx_ring[i], sizeof(struct ixgbe_ring)); temp_rx_ring[i].count = new_rx_count; - err = ixgbe_setup_rx_resources(adapter, - &temp_rx_ring[i]); + err = ixgbe_setup_rx_resources(&temp_rx_ring[i]); if (err) { while (i) { i--; - ixgbe_free_rx_resources(adapter, - &temp_rx_ring[i]); + ixgbe_free_rx_resources(&temp_rx_ring[i]); } goto err_setup; } @@ -951,8 +966,7 @@ static int ixgbe_set_ringparam(struct net_device *netdev, /* tx */ if (new_tx_count != adapter->tx_ring_count) { for (i = 0; i < adapter->num_tx_queues; i++) { - ixgbe_free_tx_resources(adapter, - adapter->tx_ring[i]); + ixgbe_free_tx_resources(adapter->tx_ring[i]); memcpy(adapter->tx_ring[i], &temp_tx_ring[i], sizeof(struct ixgbe_ring)); } @@ -962,8 +976,7 @@ static int ixgbe_set_ringparam(struct net_device *netdev, /* rx */ if (new_rx_count != adapter->rx_ring_count) { for (i = 0; i < adapter->num_rx_queues; i++) { - ixgbe_free_rx_resources(adapter, - adapter->rx_ring[i]); + ixgbe_free_rx_resources(adapter->rx_ring[i]); memcpy(adapter->rx_ring[i], &temp_rx_ring[i], sizeof(struct ixgbe_ring)); } @@ -1237,12 +1250,20 @@ static int ixgbe_reg_test(struct ixgbe_adapter *adapter, u64 *data) u32 value, before, after; u32 i, toggle; - if (adapter->hw.mac.type == ixgbe_mac_82599EB) { - toggle = 0x7FFFF30F; - test = reg_test_82599; - } else { + switch (adapter->hw.mac.type) { + case ixgbe_mac_82598EB: toggle = 0x7FFFF3FF; test = reg_test_82598; + break; + case ixgbe_mac_82599EB: + case ixgbe_mac_X540: + toggle = 0x7FFFF30F; + test = reg_test_82599; + break; + default: + *data = 1; + return 1; + break; } /* @@ -1460,16 +1481,21 @@ static void ixgbe_free_desc_rings(struct ixgbe_adapter *adapter) reg_ctl &= ~IXGBE_TXDCTL_ENABLE; IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(tx_ring->reg_idx), reg_ctl); - if (hw->mac.type == ixgbe_mac_82599EB) { + switch (hw->mac.type) { + case ixgbe_mac_82599EB: + case ixgbe_mac_X540: reg_ctl = IXGBE_READ_REG(hw, IXGBE_DMATXCTL); reg_ctl &= ~IXGBE_DMATXCTL_TE; IXGBE_WRITE_REG(hw, IXGBE_DMATXCTL, reg_ctl); + break; + default: + break; } ixgbe_reset(adapter); - ixgbe_free_tx_resources(adapter, &adapter->test_tx_ring); - ixgbe_free_rx_resources(adapter, &adapter->test_rx_ring); + ixgbe_free_tx_resources(&adapter->test_tx_ring); + ixgbe_free_rx_resources(&adapter->test_rx_ring); } static int ixgbe_setup_desc_rings(struct ixgbe_adapter *adapter) @@ -1483,17 +1509,24 @@ static int ixgbe_setup_desc_rings(struct ixgbe_adapter *adapter) /* Setup Tx descriptor ring and Tx buffers */ tx_ring->count = IXGBE_DEFAULT_TXD; tx_ring->queue_index = 0; + tx_ring->dev = &adapter->pdev->dev; + tx_ring->netdev = adapter->netdev; tx_ring->reg_idx = adapter->tx_ring[0]->reg_idx; tx_ring->numa_node = adapter->node; - err = ixgbe_setup_tx_resources(adapter, tx_ring); + err = ixgbe_setup_tx_resources(tx_ring); if (err) return 1; - if (adapter->hw.mac.type == ixgbe_mac_82599EB) { + switch (adapter->hw.mac.type) { + case ixgbe_mac_82599EB: + case ixgbe_mac_X540: reg_data = IXGBE_READ_REG(&adapter->hw, IXGBE_DMATXCTL); reg_data |= IXGBE_DMATXCTL_TE; IXGBE_WRITE_REG(&adapter->hw, IXGBE_DMATXCTL, reg_data); + break; + default: + break; } ixgbe_configure_tx_ring(adapter, tx_ring); @@ -1501,11 +1534,13 @@ static int ixgbe_setup_desc_rings(struct ixgbe_adapter *adapter) /* Setup Rx Descriptor ring and Rx buffers */ rx_ring->count = IXGBE_DEFAULT_RXD; rx_ring->queue_index = 0; + rx_ring->dev = &adapter->pdev->dev; + rx_ring->netdev = adapter->netdev; rx_ring->reg_idx = adapter->rx_ring[0]->reg_idx; rx_ring->rx_buf_len = IXGBE_RXBUFFER_2048; rx_ring->numa_node = adapter->node; - err = ixgbe_setup_rx_resources(adapter, rx_ring); + err = ixgbe_setup_rx_resources(rx_ring); if (err) { ret_val = 4; goto err_nomem; @@ -1604,8 +1639,7 @@ static int ixgbe_check_lbtest_frame(struct sk_buff *skb, return 13; } -static u16 ixgbe_clean_test_rings(struct ixgbe_adapter *adapter, - struct ixgbe_ring *rx_ring, +static u16 ixgbe_clean_test_rings(struct ixgbe_ring *rx_ring, struct ixgbe_ring *tx_ring, unsigned int size) { @@ -1627,7 +1661,7 @@ static u16 ixgbe_clean_test_rings(struct ixgbe_adapter *adapter, rx_buffer_info = &rx_ring->rx_buffer_info[rx_ntc]; /* unmap Rx buffer, will be remapped by alloc_rx_buffers */ - dma_unmap_single(&adapter->pdev->dev, + dma_unmap_single(rx_ring->dev, rx_buffer_info->dma, bufsz, DMA_FROM_DEVICE); @@ -1639,7 +1673,7 @@ static u16 ixgbe_clean_test_rings(struct ixgbe_adapter *adapter, /* unmap buffer on Tx side */ tx_buffer_info = &tx_ring->tx_buffer_info[tx_ntc]; - ixgbe_unmap_and_free_tx_resource(adapter, tx_buffer_info); + ixgbe_unmap_and_free_tx_resource(tx_ring, tx_buffer_info); /* increment Rx/Tx next to clean counters */ rx_ntc++; @@ -1655,7 +1689,7 @@ static u16 ixgbe_clean_test_rings(struct ixgbe_adapter *adapter, } /* re-map buffers to ring, store next to clean values */ - ixgbe_alloc_rx_buffers(adapter, rx_ring, count); + ixgbe_alloc_rx_buffers(rx_ring, count); rx_ring->next_to_clean = rx_ntc; tx_ring->next_to_clean = tx_ntc; @@ -1699,7 +1733,6 @@ static int ixgbe_run_loopback_test(struct ixgbe_adapter *adapter) for (i = 0; i < 64; i++) { skb_get(skb); tx_ret_val = ixgbe_xmit_frame_ring(skb, - adapter->netdev, adapter, tx_ring); if (tx_ret_val == NETDEV_TX_OK) @@ -1714,8 +1747,7 @@ static int ixgbe_run_loopback_test(struct ixgbe_adapter *adapter) /* allow 200 milliseconds for packets to go from Tx to Rx */ msleep(200); - good_cnt = ixgbe_clean_test_rings(adapter, rx_ring, - tx_ring, size); + good_cnt = ixgbe_clean_test_rings(rx_ring, tx_ring, size); if (good_cnt != 64) { ret_val = 13; break; @@ -1847,7 +1879,25 @@ static int ixgbe_wol_exclusion(struct ixgbe_adapter *adapter, struct ixgbe_hw *hw = &adapter->hw; int retval = 1; + /* WOL not supported except for the following */ switch(hw->device_id) { + case IXGBE_DEV_ID_82599_SFP: + /* Only this subdevice supports WOL */ + if (hw->subsystem_device_id != IXGBE_SUBDEV_ID_82599_SFP) { + wol->supported = 0; + break; + } + retval = 0; + break; + case IXGBE_DEV_ID_82599_COMBO_BACKPLANE: + /* All except this subdevice support WOL */ + if (hw->subsystem_device_id == + IXGBE_SUBDEV_ID_82599_KX4_KR_MEZZ) { + wol->supported = 0; + break; + } + retval = 0; + break; case IXGBE_DEV_ID_82599_KX4: retval = 0; break; @@ -1985,6 +2035,41 @@ static int ixgbe_get_coalesce(struct net_device *netdev, return 0; } +/* + * this function must be called before setting the new value of + * rx_itr_setting + */ +static bool ixgbe_update_rsc(struct ixgbe_adapter *adapter, + struct ethtool_coalesce *ec) +{ + struct net_device *netdev = adapter->netdev; + + if (!(adapter->flags2 & IXGBE_FLAG2_RSC_CAPABLE)) + return false; + + /* if interrupt rate is too high then disable RSC */ + if (ec->rx_coalesce_usecs != 1 && + ec->rx_coalesce_usecs <= 1000000/IXGBE_MAX_RSC_INT_RATE) { + if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED) { + e_info(probe, "rx-usecs set too low, " + "disabling RSC\n"); + adapter->flags2 &= ~IXGBE_FLAG2_RSC_ENABLED; + return true; + } + } else { + /* check the feature flag value and enable RSC if necessary */ + if ((netdev->features & NETIF_F_LRO) && + !(adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED)) { + e_info(probe, "rx-usecs set to %d, " + "re-enabling RSC\n", + ec->rx_coalesce_usecs); + adapter->flags2 |= IXGBE_FLAG2_RSC_ENABLED; + return true; + } + } + return false; +} + static int ixgbe_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *ec) { @@ -2002,17 +2087,14 @@ static int ixgbe_set_coalesce(struct net_device *netdev, adapter->tx_ring[0]->work_limit = ec->tx_max_coalesced_frames_irq; if (ec->rx_coalesce_usecs > 1) { - u32 max_int; - if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED) - max_int = IXGBE_MAX_RSC_INT_RATE; - else - max_int = IXGBE_MAX_INT_RATE; - /* check the limits */ - if ((1000000/ec->rx_coalesce_usecs > max_int) || + if ((1000000/ec->rx_coalesce_usecs > IXGBE_MAX_INT_RATE) || (1000000/ec->rx_coalesce_usecs < IXGBE_MIN_INT_RATE)) return -EINVAL; + /* check the old value and enable RSC if necessary */ + need_reset = ixgbe_update_rsc(adapter, ec); + /* store the value in ints/second */ adapter->rx_eitr_param = 1000000/ec->rx_coalesce_usecs; @@ -2021,32 +2103,21 @@ static int ixgbe_set_coalesce(struct net_device *netdev, /* clear the lower bit as its used for dynamic state */ adapter->rx_itr_setting &= ~1; } else if (ec->rx_coalesce_usecs == 1) { + /* check the old value and enable RSC if necessary */ + need_reset = ixgbe_update_rsc(adapter, ec); + /* 1 means dynamic mode */ adapter->rx_eitr_param = 20000; adapter->rx_itr_setting = 1; } else { + /* check the old value and enable RSC if necessary */ + need_reset = ixgbe_update_rsc(adapter, ec); /* * any other value means disable eitr, which is best * served by setting the interrupt rate very high */ adapter->rx_eitr_param = IXGBE_MAX_INT_RATE; adapter->rx_itr_setting = 0; - - /* - * if hardware RSC is enabled, disable it when - * setting low latency mode, to avoid errata, assuming - * that when the user set low latency mode they want - * it at the cost of anything else - */ - if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED) { - adapter->flags2 &= ~IXGBE_FLAG2_RSC_ENABLED; - if (netdev->features & NETIF_F_LRO) { - netdev->features &= ~NETIF_F_LRO; - e_info(probe, "rx-usecs set to 0, " - "disabling RSC\n"); - } - need_reset = true; - } } if (ec->tx_coalesce_usecs > 1) { @@ -2133,28 +2204,39 @@ static int ixgbe_set_flags(struct net_device *netdev, u32 data) return rc; /* if state changes we need to update adapter->flags and reset */ - if (adapter->flags2 & IXGBE_FLAG2_RSC_CAPABLE) { - /* - * cast both to bool and verify if they are set the same - * but only enable RSC if itr is non-zero, as - * itr=0 and RSC are mutually exclusive - */ - if (((!!(data & ETH_FLAG_LRO)) != - (!!(adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED))) && - adapter->rx_itr_setting) { + if ((adapter->flags2 & IXGBE_FLAG2_RSC_CAPABLE) && + (!!(data & ETH_FLAG_LRO) != + !!(adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED))) { + if ((data & ETH_FLAG_LRO) && + (!adapter->rx_itr_setting || + (adapter->rx_itr_setting > IXGBE_MAX_RSC_INT_RATE))) { + e_info(probe, "rx-usecs set too low, " + "not enabling RSC.\n"); + } else { adapter->flags2 ^= IXGBE_FLAG2_RSC_ENABLED; switch (adapter->hw.mac.type) { 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; } - } else if (!adapter->rx_itr_setting) { - netdev->features &= ~NETIF_F_LRO; - if (data & ETH_FLAG_LRO) - e_info(probe, "rx-usecs set to 0, " - "LRO/RSC cannot be enabled.\n"); } } diff --git a/drivers/net/ixgbe/ixgbe_fcoe.c b/drivers/net/ixgbe/ixgbe_fcoe.c index 05efa6a8ce8e..6342d4859790 100644 --- a/drivers/net/ixgbe/ixgbe_fcoe.c +++ b/drivers/net/ixgbe/ixgbe_fcoe.c @@ -68,7 +68,7 @@ static inline bool ixgbe_rx_is_fcoe(union ixgbe_adv_rx_desc *rx_desc) static inline void ixgbe_fcoe_clear_ddp(struct ixgbe_fcoe_ddp *ddp) { ddp->len = 0; - ddp->err = 0; + ddp->err = 1; ddp->udl = NULL; ddp->udp = 0UL; ddp->sgl = NULL; @@ -92,6 +92,7 @@ int ixgbe_fcoe_ddp_put(struct net_device *netdev, u16 xid) struct ixgbe_fcoe *fcoe; struct ixgbe_adapter *adapter; struct ixgbe_fcoe_ddp *ddp; + u32 fcbuff; if (!netdev) goto out_ddp_put; @@ -115,7 +116,14 @@ int ixgbe_fcoe_ddp_put(struct net_device *netdev, u16 xid) IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCBUFF, 0); IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCDMARW, (xid | IXGBE_FCDMARW_WE)); + + /* guaranteed to be invalidated after 100us */ + IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCDMARW, + (xid | IXGBE_FCDMARW_RE)); + fcbuff = IXGBE_READ_REG(&adapter->hw, IXGBE_FCBUFF); spin_unlock_bh(&fcoe->lock); + if (fcbuff & IXGBE_FCBUFF_VALID) + udelay(100); } if (ddp->sgl) pci_unmap_sg(adapter->pdev, ddp->sgl, ddp->sgc, @@ -168,6 +176,11 @@ int ixgbe_fcoe_ddp_get(struct net_device *netdev, u16 xid, return 0; } + /* no DDP if we are already down or resetting */ + if (test_bit(__IXGBE_DOWN, &adapter->state) || + test_bit(__IXGBE_RESETTING, &adapter->state)) + return 0; + fcoe = &adapter->fcoe; if (!fcoe->pool) { e_warn(drv, "xid=0x%x no ddp pool for fcoe\n", xid); diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 2bd3eb4ee5a1..f97353cdb607 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -52,13 +52,14 @@ char ixgbe_driver_name[] = "ixgbe"; static const char ixgbe_driver_string[] = "Intel(R) 10 Gigabit PCI Express Network Driver"; -#define DRV_VERSION "2.0.84-k2" +#define DRV_VERSION "3.0.12-k2" const char ixgbe_driver_version[] = DRV_VERSION; static char ixgbe_copyright[] = "Copyright (c) 1999-2010 Intel Corporation."; static const struct ixgbe_info *ixgbe_info_tbl[] = { [board_82598] = &ixgbe_82598_info, [board_82599] = &ixgbe_82599_info, + [board_X540] = &ixgbe_X540_info, }; /* ixgbe_pci_tbl - PCI Device ID Table @@ -108,10 +109,16 @@ static DEFINE_PCI_DEVICE_TABLE(ixgbe_pci_tbl) = { board_82599 }, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_CX4), board_82599 }, + {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_BACKPLANE_FCOE), + board_82599 }, + {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_SFP_FCOE), + board_82599 }, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_T3_LOM), board_82599 }, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_COMBO_BACKPLANE), board_82599 }, + {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X540T), + board_82599 }, /* required last entry */ {0, } @@ -560,6 +567,7 @@ static void ixgbe_set_ivar(struct ixgbe_adapter *adapter, s8 direction, IXGBE_WRITE_REG(hw, IXGBE_IVAR(index), ivar); break; case ixgbe_mac_82599EB: + case ixgbe_mac_X540: if (direction == -1) { /* other causes */ msix_vector |= IXGBE_IVAR_ALLOC_VAL; @@ -589,29 +597,34 @@ static inline void ixgbe_irq_rearm_queues(struct ixgbe_adapter *adapter, { u32 mask; - if (adapter->hw.mac.type == ixgbe_mac_82598EB) { + switch (adapter->hw.mac.type) { + case ixgbe_mac_82598EB: mask = (IXGBE_EIMS_RTX_QUEUE & qmask); IXGBE_WRITE_REG(&adapter->hw, IXGBE_EICS, mask); - } else { + break; + case ixgbe_mac_82599EB: + case ixgbe_mac_X540: mask = (qmask & 0xFFFFFFFF); IXGBE_WRITE_REG(&adapter->hw, IXGBE_EICS_EX(0), mask); mask = (qmask >> 32); IXGBE_WRITE_REG(&adapter->hw, IXGBE_EICS_EX(1), mask); + break; + default: + break; } } -void ixgbe_unmap_and_free_tx_resource(struct ixgbe_adapter *adapter, - struct ixgbe_tx_buffer - *tx_buffer_info) +void ixgbe_unmap_and_free_tx_resource(struct ixgbe_ring *tx_ring, + struct ixgbe_tx_buffer *tx_buffer_info) { if (tx_buffer_info->dma) { if (tx_buffer_info->mapped_as_page) - dma_unmap_page(&adapter->pdev->dev, + dma_unmap_page(tx_ring->dev, tx_buffer_info->dma, tx_buffer_info->length, DMA_TO_DEVICE); else - dma_unmap_single(&adapter->pdev->dev, + dma_unmap_single(tx_ring->dev, tx_buffer_info->dma, tx_buffer_info->length, DMA_TO_DEVICE); @@ -626,92 +639,166 @@ void ixgbe_unmap_and_free_tx_resource(struct ixgbe_adapter *adapter, } /** - * ixgbe_tx_xon_state - check the tx ring xon state - * @adapter: the ixgbe adapter - * @tx_ring: the corresponding tx_ring + * 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) * - * If not in DCB mode, checks TFCS.TXOFF, otherwise, find out the - * corresponding TC of this tx_ring when checking TFCS. + * Helper function to determine the traffic index for a paticular + * register index. * - * Returns : true if in xon state (currently not paused) + * Returns : a tc index for use in range 0-7, or 0-3 */ -static inline bool ixgbe_tx_xon_state(struct ixgbe_adapter *adapter, - struct ixgbe_ring *tx_ring) +u8 ixgbe_dcb_txq_to_tc(struct ixgbe_adapter *adapter, u8 reg_idx) { - u32 txoff = IXGBE_TFCS_TXOFF; + int tc = -1; + int dcb_i = adapter->ring_feature[RING_F_DCB].indices; -#ifdef CONFIG_IXGBE_DCB - if (adapter->dcb_cfg.pfc_mode_enable) { - int tc; - int reg_idx = tx_ring->reg_idx; - int dcb_i = adapter->ring_feature[RING_F_DCB].indices; + /* 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; + struct ixgbe_hw_stats *hwstats = &adapter->stats; + u32 data = 0; + u32 xoff[8] = {0}; + int i; - switch (adapter->hw.mac.type) { + if ((hw->fc.current_mode == ixgbe_fc_full) || + (hw->fc.current_mode == ixgbe_fc_rx_pause)) { + switch (hw->mac.type) { case ixgbe_mac_82598EB: - tc = reg_idx >> 2; - txoff = IXGBE_TFCS_TXOFF0; + data = IXGBE_READ_REG(hw, IXGBE_LXOFFRXC); break; - case ixgbe_mac_82599EB: - tc = 0; - txoff = IXGBE_TFCS_TXOFF; - if (dcb_i == 8) { - /* TC0, TC1 */ - tc = reg_idx >> 5; - if (tc == 2) /* TC2, TC3 */ - tc += (reg_idx - 64) >> 4; - else if (tc == 3) /* TC4, TC5, TC6, TC7 */ - tc += 1 + ((reg_idx - 96) >> 3); - } else if (dcb_i == 4) { - /* TC0, TC1 */ - tc = reg_idx >> 6; - if (tc == 1) { - tc += (reg_idx - 64) >> 5; - if (tc == 2) /* TC2, TC3 */ - tc += (reg_idx - 96) >> 4; - } - } + default: + data = IXGBE_READ_REG(hw, IXGBE_LXOFFRXCNT); + } + hwstats->lxoffrxc += data; + + /* refill credits (no tx hang) if we received xoff */ + if (!data) + return; + + for (i = 0; i < adapter->num_tx_queues; i++) + clear_bit(__IXGBE_HANG_CHECK_ARMED, + &adapter->tx_ring[i]->state); + return; + } else if (!(adapter->dcb_cfg.pfc_mode_enable)) + return; + + /* update stats for each tc, only valid with PFC enabled */ + for (i = 0; i < MAX_TX_PACKET_BUFFERS; i++) { + switch (hw->mac.type) { + case ixgbe_mac_82598EB: + xoff[i] = IXGBE_READ_REG(hw, IXGBE_PXOFFRXC(i)); break; default: - tc = 0; + xoff[i] = IXGBE_READ_REG(hw, IXGBE_PXOFFRXCNT(i)); } - txoff <<= tc; + hwstats->pxoffrxc[i] += xoff[i]; } -#endif - return IXGBE_READ_REG(&adapter->hw, IXGBE_TFCS) & txoff; + + /* 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); + + if (xoff[tc]) + clear_bit(__IXGBE_HANG_CHECK_ARMED, &tx_ring->state); + } +} + +static u64 ixgbe_get_tx_completed(struct ixgbe_ring *ring) +{ + return ring->tx_stats.completed; } -static inline bool ixgbe_check_tx_hang(struct ixgbe_adapter *adapter, - struct ixgbe_ring *tx_ring, - unsigned int eop) +static u64 ixgbe_get_tx_pending(struct ixgbe_ring *ring) { + struct ixgbe_adapter *adapter = netdev_priv(ring->netdev); struct ixgbe_hw *hw = &adapter->hw; - /* Detect a transmit hang in hardware, this serializes the - * check with the clearing of time_stamp and movement of eop */ - adapter->detect_tx_hung = false; - if (tx_ring->tx_buffer_info[eop].time_stamp && - time_after(jiffies, tx_ring->tx_buffer_info[eop].time_stamp + HZ) && - ixgbe_tx_xon_state(adapter, tx_ring)) { - /* detected Tx unit hang */ - union ixgbe_adv_tx_desc *tx_desc; - tx_desc = IXGBE_TX_DESC_ADV(tx_ring, eop); - e_err(drv, "Detected Tx Unit Hang\n" - " Tx Queue <%d>\n" - " TDH, TDT <%x>, <%x>\n" - " next_to_use <%x>\n" - " next_to_clean <%x>\n" - "tx_buffer_info[next_to_clean]\n" - " time_stamp <%lx>\n" - " jiffies <%lx>\n", - tx_ring->queue_index, - IXGBE_READ_REG(hw, tx_ring->head), - IXGBE_READ_REG(hw, tx_ring->tail), - tx_ring->next_to_use, eop, - tx_ring->tx_buffer_info[eop].time_stamp, jiffies); - return true; + u32 head = IXGBE_READ_REG(hw, IXGBE_TDH(ring->reg_idx)); + u32 tail = IXGBE_READ_REG(hw, IXGBE_TDT(ring->reg_idx)); + + if (head != tail) + return (head < tail) ? + tail - head : (tail + ring->count - head); + + return 0; +} + +static inline bool ixgbe_check_tx_hang(struct ixgbe_ring *tx_ring) +{ + u32 tx_done = ixgbe_get_tx_completed(tx_ring); + u32 tx_done_old = tx_ring->tx_stats.tx_done_old; + u32 tx_pending = ixgbe_get_tx_pending(tx_ring); + bool ret = false; + + clear_check_for_tx_hang(tx_ring); + + /* + * Check for a hung queue, but be thorough. This verifies + * that a transmit has been completed since the previous + * check AND there is at least one packet pending. The + * ARMED bit is set to indicate a potential hang. The + * bit is cleared if a pause frame is received to remove + * false hang detection due to PFC or 802.3x frames. By + * requiring this to fail twice we avoid races with + * pfc clearing the ARMED bit and conditions where we + * run the check_tx_hang logic with a transmit completion + * pending but without time to complete it yet. + */ + if ((tx_done_old == tx_done) && tx_pending) { + /* make sure it is true for two checks in a row */ + ret = test_and_set_bit(__IXGBE_HANG_CHECK_ARMED, + &tx_ring->state); + } else { + /* update completed stats and continue */ + tx_ring->tx_stats.tx_done_old = tx_done; + /* reset the countdown */ + clear_bit(__IXGBE_HANG_CHECK_ARMED, &tx_ring->state); } - return false; + return ret; } #define IXGBE_MAX_TXD_PWR 14 @@ -734,11 +821,10 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_q_vector *q_vector, struct ixgbe_ring *tx_ring) { struct ixgbe_adapter *adapter = q_vector->adapter; - struct net_device *netdev = adapter->netdev; union ixgbe_adv_tx_desc *tx_desc, *eop_desc; struct ixgbe_tx_buffer *tx_buffer_info; - unsigned int i, eop, count = 0; unsigned int total_bytes = 0, total_packets = 0; + u16 i, eop, count = 0; i = tx_ring->next_to_clean; eop = tx_ring->tx_buffer_info[i].next_to_watch; @@ -749,147 +835,182 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_q_vector *q_vector, bool cleaned = false; rmb(); /* read buffer_info after eop_desc */ for ( ; !cleaned; count++) { - struct sk_buff *skb; tx_desc = IXGBE_TX_DESC_ADV(tx_ring, i); tx_buffer_info = &tx_ring->tx_buffer_info[i]; - cleaned = (i == eop); - skb = tx_buffer_info->skb; - - if (cleaned && skb) { - unsigned int segs, bytecount; - unsigned int hlen = skb_headlen(skb); - - /* gso_segs is currently only valid for tcp */ - segs = skb_shinfo(skb)->gso_segs ?: 1; -#ifdef IXGBE_FCOE - /* adjust for FCoE Sequence Offload */ - if ((adapter->flags & IXGBE_FLAG_FCOE_ENABLED) - && (skb->protocol == htons(ETH_P_FCOE)) && - skb_is_gso(skb)) { - hlen = skb_transport_offset(skb) + - sizeof(struct fc_frame_header) + - sizeof(struct fcoe_crc_eof); - segs = DIV_ROUND_UP(skb->len - hlen, - skb_shinfo(skb)->gso_size); - } -#endif /* IXGBE_FCOE */ - /* multiply data chunks by size of headers */ - bytecount = ((segs - 1) * hlen) + skb->len; - total_packets += segs; - total_bytes += bytecount; - } - - ixgbe_unmap_and_free_tx_resource(adapter, - tx_buffer_info); tx_desc->wb.status = 0; + cleaned = (i == eop); i++; if (i == tx_ring->count) i = 0; + + if (cleaned && tx_buffer_info->skb) { + total_bytes += tx_buffer_info->bytecount; + total_packets += tx_buffer_info->gso_segs; + } + + ixgbe_unmap_and_free_tx_resource(tx_ring, + tx_buffer_info); } + tx_ring->tx_stats.completed++; eop = tx_ring->tx_buffer_info[i].next_to_watch; eop_desc = IXGBE_TX_DESC_ADV(tx_ring, eop); } tx_ring->next_to_clean = i; + tx_ring->total_bytes += total_bytes; + tx_ring->total_packets += total_packets; + u64_stats_update_begin(&tx_ring->syncp); + tx_ring->stats.packets += total_packets; + tx_ring->stats.bytes += total_bytes; + u64_stats_update_end(&tx_ring->syncp); + + if (check_for_tx_hang(tx_ring) && ixgbe_check_tx_hang(tx_ring)) { + /* schedule immediate reset if we believe we hung */ + struct ixgbe_hw *hw = &adapter->hw; + tx_desc = IXGBE_TX_DESC_ADV(tx_ring, eop); + e_err(drv, "Detected Tx Unit Hang\n" + " Tx Queue <%d>\n" + " TDH, TDT <%x>, <%x>\n" + " next_to_use <%x>\n" + " next_to_clean <%x>\n" + "tx_buffer_info[next_to_clean]\n" + " time_stamp <%lx>\n" + " jiffies <%lx>\n", + tx_ring->queue_index, + IXGBE_READ_REG(hw, IXGBE_TDH(tx_ring->reg_idx)), + IXGBE_READ_REG(hw, IXGBE_TDT(tx_ring->reg_idx)), + tx_ring->next_to_use, eop, + tx_ring->tx_buffer_info[eop].time_stamp, jiffies); + + netif_stop_subqueue(tx_ring->netdev, tx_ring->queue_index); + + e_info(probe, + "tx hang %d detected on queue %d, resetting adapter\n", + adapter->tx_timeout_count + 1, tx_ring->queue_index); + + /* schedule immediate reset if we believe we hung */ + ixgbe_tx_timeout(adapter->netdev); + + /* the adapter is about to reset, no point in enabling stuff */ + return true; + } #define TX_WAKE_THRESHOLD (DESC_NEEDED * 2) - if (unlikely(count && netif_carrier_ok(netdev) && + if (unlikely(count && netif_carrier_ok(tx_ring->netdev) && (IXGBE_DESC_UNUSED(tx_ring) >= TX_WAKE_THRESHOLD))) { /* Make sure that anybody stopping the queue after this * sees the new next_to_clean. */ smp_mb(); - if (__netif_subqueue_stopped(netdev, tx_ring->queue_index) && + if (__netif_subqueue_stopped(tx_ring->netdev, tx_ring->queue_index) && !test_bit(__IXGBE_DOWN, &adapter->state)) { - netif_wake_subqueue(netdev, tx_ring->queue_index); - ++tx_ring->restart_queue; - } - } - - if (adapter->detect_tx_hung) { - if (ixgbe_check_tx_hang(adapter, tx_ring, i)) { - /* schedule immediate reset if we believe we hung */ - e_info(probe, "tx hang %d detected, resetting " - "adapter\n", adapter->tx_timeout_count + 1); - ixgbe_tx_timeout(adapter->netdev); + netif_wake_subqueue(tx_ring->netdev, tx_ring->queue_index); + ++tx_ring->tx_stats.restart_queue; } } - /* re-arm the interrupt */ - if (count >= tx_ring->work_limit) - ixgbe_irq_rearm_queues(adapter, ((u64)1 << q_vector->v_idx)); - - tx_ring->total_bytes += total_bytes; - tx_ring->total_packets += total_packets; - u64_stats_update_begin(&tx_ring->syncp); - tx_ring->stats.packets += total_packets; - tx_ring->stats.bytes += total_bytes; - u64_stats_update_end(&tx_ring->syncp); return count < tx_ring->work_limit; } #ifdef CONFIG_IXGBE_DCA static void ixgbe_update_rx_dca(struct ixgbe_adapter *adapter, - struct ixgbe_ring *rx_ring) + struct ixgbe_ring *rx_ring, + int cpu) { + struct ixgbe_hw *hw = &adapter->hw; u32 rxctrl; - int cpu = get_cpu(); - int q = rx_ring->reg_idx; - - if (rx_ring->cpu != cpu) { - rxctrl = IXGBE_READ_REG(&adapter->hw, IXGBE_DCA_RXCTRL(q)); - if (adapter->hw.mac.type == ixgbe_mac_82598EB) { - rxctrl &= ~IXGBE_DCA_RXCTRL_CPUID_MASK; - rxctrl |= dca3_get_tag(&adapter->pdev->dev, cpu); - } else if (adapter->hw.mac.type == ixgbe_mac_82599EB) { - rxctrl &= ~IXGBE_DCA_RXCTRL_CPUID_MASK_82599; - rxctrl |= (dca3_get_tag(&adapter->pdev->dev, cpu) << - IXGBE_DCA_RXCTRL_CPUID_SHIFT_82599); - } - rxctrl |= IXGBE_DCA_RXCTRL_DESC_DCA_EN; - rxctrl |= IXGBE_DCA_RXCTRL_HEAD_DCA_EN; - rxctrl &= ~(IXGBE_DCA_RXCTRL_DESC_RRO_EN); - rxctrl &= ~(IXGBE_DCA_RXCTRL_DESC_WRO_EN | - IXGBE_DCA_RXCTRL_DESC_HSRO_EN); - IXGBE_WRITE_REG(&adapter->hw, IXGBE_DCA_RXCTRL(q), rxctrl); - rx_ring->cpu = cpu; + u8 reg_idx = rx_ring->reg_idx; + + rxctrl = IXGBE_READ_REG(hw, IXGBE_DCA_RXCTRL(reg_idx)); + switch (hw->mac.type) { + case ixgbe_mac_82598EB: + rxctrl &= ~IXGBE_DCA_RXCTRL_CPUID_MASK; + rxctrl |= dca3_get_tag(&adapter->pdev->dev, cpu); + break; + case ixgbe_mac_82599EB: + case ixgbe_mac_X540: + rxctrl &= ~IXGBE_DCA_RXCTRL_CPUID_MASK_82599; + rxctrl |= (dca3_get_tag(&adapter->pdev->dev, cpu) << + IXGBE_DCA_RXCTRL_CPUID_SHIFT_82599); + break; + default: + break; } - put_cpu(); + rxctrl |= IXGBE_DCA_RXCTRL_DESC_DCA_EN; + rxctrl |= IXGBE_DCA_RXCTRL_HEAD_DCA_EN; + rxctrl &= ~(IXGBE_DCA_RXCTRL_DESC_RRO_EN); + rxctrl &= ~(IXGBE_DCA_RXCTRL_DESC_WRO_EN | + IXGBE_DCA_RXCTRL_DESC_HSRO_EN); + IXGBE_WRITE_REG(hw, IXGBE_DCA_RXCTRL(reg_idx), rxctrl); } static void ixgbe_update_tx_dca(struct ixgbe_adapter *adapter, - struct ixgbe_ring *tx_ring) + struct ixgbe_ring *tx_ring, + int cpu) { + struct ixgbe_hw *hw = &adapter->hw; u32 txctrl; + u8 reg_idx = tx_ring->reg_idx; + + switch (hw->mac.type) { + case ixgbe_mac_82598EB: + txctrl = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL(reg_idx)); + txctrl &= ~IXGBE_DCA_TXCTRL_CPUID_MASK; + txctrl |= dca3_get_tag(&adapter->pdev->dev, cpu); + txctrl |= IXGBE_DCA_TXCTRL_DESC_DCA_EN; + txctrl &= ~IXGBE_DCA_TXCTRL_TX_WB_RO_EN; + IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL(reg_idx), txctrl); + break; + case ixgbe_mac_82599EB: + case ixgbe_mac_X540: + txctrl = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL_82599(reg_idx)); + txctrl &= ~IXGBE_DCA_TXCTRL_CPUID_MASK_82599; + txctrl |= (dca3_get_tag(&adapter->pdev->dev, cpu) << + IXGBE_DCA_TXCTRL_CPUID_SHIFT_82599); + txctrl |= IXGBE_DCA_TXCTRL_DESC_DCA_EN; + txctrl &= ~IXGBE_DCA_TXCTRL_TX_WB_RO_EN; + IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL_82599(reg_idx), txctrl); + break; + default: + break; + } +} + +static void ixgbe_update_dca(struct ixgbe_q_vector *q_vector) +{ + struct ixgbe_adapter *adapter = q_vector->adapter; int cpu = get_cpu(); - int q = tx_ring->reg_idx; - struct ixgbe_hw *hw = &adapter->hw; + long r_idx; + int i; - if (tx_ring->cpu != cpu) { - if (adapter->hw.mac.type == ixgbe_mac_82598EB) { - txctrl = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL(q)); - txctrl &= ~IXGBE_DCA_TXCTRL_CPUID_MASK; - txctrl |= dca3_get_tag(&adapter->pdev->dev, cpu); - txctrl |= IXGBE_DCA_TXCTRL_DESC_DCA_EN; - IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL(q), txctrl); - } else if (adapter->hw.mac.type == ixgbe_mac_82599EB) { - txctrl = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL_82599(q)); - txctrl &= ~IXGBE_DCA_TXCTRL_CPUID_MASK_82599; - txctrl |= (dca3_get_tag(&adapter->pdev->dev, cpu) << - IXGBE_DCA_TXCTRL_CPUID_SHIFT_82599); - txctrl |= IXGBE_DCA_TXCTRL_DESC_DCA_EN; - IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL_82599(q), txctrl); - } - tx_ring->cpu = cpu; + if (q_vector->cpu == cpu) + goto out_no_update; + + r_idx = find_first_bit(q_vector->txr_idx, adapter->num_tx_queues); + for (i = 0; i < q_vector->txr_count; i++) { + ixgbe_update_tx_dca(adapter, adapter->tx_ring[r_idx], cpu); + r_idx = find_next_bit(q_vector->txr_idx, adapter->num_tx_queues, + r_idx + 1); } + + r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues); + for (i = 0; i < q_vector->rxr_count; i++) { + ixgbe_update_rx_dca(adapter, adapter->rx_ring[r_idx], cpu); + r_idx = find_next_bit(q_vector->rxr_idx, adapter->num_rx_queues, + r_idx + 1); + } + + q_vector->cpu = cpu; +out_no_update: put_cpu(); } static void ixgbe_setup_dca(struct ixgbe_adapter *adapter) { + int num_q_vectors; int i; if (!(adapter->flags & IXGBE_FLAG_DCA_ENABLED)) @@ -898,22 +1019,25 @@ static void ixgbe_setup_dca(struct ixgbe_adapter *adapter) /* always use CB2 mode, difference is masked in the CB driver */ IXGBE_WRITE_REG(&adapter->hw, IXGBE_DCA_CTRL, 2); - for (i = 0; i < adapter->num_tx_queues; i++) { - adapter->tx_ring[i]->cpu = -1; - ixgbe_update_tx_dca(adapter, adapter->tx_ring[i]); - } - for (i = 0; i < adapter->num_rx_queues; i++) { - adapter->rx_ring[i]->cpu = -1; - ixgbe_update_rx_dca(adapter, adapter->rx_ring[i]); + if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) + num_q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS; + else + num_q_vectors = 1; + + for (i = 0; i < num_q_vectors; i++) { + adapter->q_vector[i]->cpu = -1; + ixgbe_update_dca(adapter->q_vector[i]); } } static int __ixgbe_notify_dca(struct device *dev, void *data) { - struct net_device *netdev = dev_get_drvdata(dev); - struct ixgbe_adapter *adapter = netdev_priv(netdev); + struct ixgbe_adapter *adapter = dev_get_drvdata(dev); unsigned long event = *(unsigned long *)data; + if (!(adapter->flags & IXGBE_FLAG_DCA_ENABLED)) + return 0; + switch (event) { case DCA_PROVIDER_ADD: /* if we're already enabled, don't do it again */ @@ -1012,8 +1136,7 @@ static inline void ixgbe_rx_checksum(struct ixgbe_adapter *adapter, skb->ip_summed = CHECKSUM_UNNECESSARY; } -static inline void ixgbe_release_rx_desc(struct ixgbe_hw *hw, - struct ixgbe_ring *rx_ring, u32 val) +static inline void ixgbe_release_rx_desc(struct ixgbe_ring *rx_ring, u32 val) { /* * Force memory writes to complete before letting h/w @@ -1022,72 +1145,81 @@ static inline void ixgbe_release_rx_desc(struct ixgbe_hw *hw, * such as IA-64). */ wmb(); - IXGBE_WRITE_REG(hw, IXGBE_RDT(rx_ring->reg_idx), val); + writel(val, rx_ring->tail); } /** * ixgbe_alloc_rx_buffers - Replace used receive buffers; packet split - * @adapter: address of board private structure + * @rx_ring: ring to place buffers on + * @cleaned_count: number of buffers to replace **/ -void ixgbe_alloc_rx_buffers(struct ixgbe_adapter *adapter, - struct ixgbe_ring *rx_ring, - int cleaned_count) +void ixgbe_alloc_rx_buffers(struct ixgbe_ring *rx_ring, u16 cleaned_count) { - struct net_device *netdev = adapter->netdev; - struct pci_dev *pdev = adapter->pdev; union ixgbe_adv_rx_desc *rx_desc; struct ixgbe_rx_buffer *bi; - unsigned int i; - unsigned int bufsz = rx_ring->rx_buf_len; + struct sk_buff *skb; + u16 i = rx_ring->next_to_use; - i = rx_ring->next_to_use; - bi = &rx_ring->rx_buffer_info[i]; + /* do nothing if no valid netdev defined */ + if (!rx_ring->netdev) + return; while (cleaned_count--) { rx_desc = IXGBE_RX_DESC_ADV(rx_ring, i); + bi = &rx_ring->rx_buffer_info[i]; + skb = bi->skb; - if (!bi->page_dma && - (rx_ring->flags & IXGBE_RING_RX_PS_ENABLED)) { - if (!bi->page) { - bi->page = netdev_alloc_page(netdev); - if (!bi->page) { - adapter->alloc_rx_page_failed++; - goto no_buffers; - } - bi->page_offset = 0; - } else { - /* use a half page if we're re-using */ - bi->page_offset ^= (PAGE_SIZE / 2); - } - - bi->page_dma = dma_map_page(&pdev->dev, bi->page, - bi->page_offset, - (PAGE_SIZE / 2), - DMA_FROM_DEVICE); - } - - if (!bi->skb) { - struct sk_buff *skb = netdev_alloc_skb_ip_align(netdev, - bufsz); - bi->skb = skb; - + if (!skb) { + skb = netdev_alloc_skb_ip_align(rx_ring->netdev, + rx_ring->rx_buf_len); if (!skb) { - adapter->alloc_rx_buff_failed++; + rx_ring->rx_stats.alloc_rx_buff_failed++; goto no_buffers; } /* initialize queue mapping */ skb_record_rx_queue(skb, rx_ring->queue_index); + bi->skb = skb; } if (!bi->dma) { - bi->dma = dma_map_single(&pdev->dev, - bi->skb->data, + bi->dma = dma_map_single(rx_ring->dev, + skb->data, rx_ring->rx_buf_len, DMA_FROM_DEVICE); + if (dma_mapping_error(rx_ring->dev, bi->dma)) { + rx_ring->rx_stats.alloc_rx_buff_failed++; + bi->dma = 0; + goto no_buffers; + } } - /* Refresh the desc even if buffer_addrs didn't change because - * each write-back erases this info. */ - if (rx_ring->flags & IXGBE_RING_RX_PS_ENABLED) { + + if (ring_is_ps_enabled(rx_ring)) { + if (!bi->page) { + bi->page = netdev_alloc_page(rx_ring->netdev); + if (!bi->page) { + rx_ring->rx_stats.alloc_rx_page_failed++; + goto no_buffers; + } + } + + if (!bi->page_dma) { + /* use a half page if we're re-using */ + bi->page_offset ^= PAGE_SIZE / 2; + bi->page_dma = dma_map_page(rx_ring->dev, + bi->page, + bi->page_offset, + PAGE_SIZE / 2, + DMA_FROM_DEVICE); + if (dma_mapping_error(rx_ring->dev, + bi->page_dma)) { + rx_ring->rx_stats.alloc_rx_page_failed++; + bi->page_dma = 0; + goto no_buffers; + } + } + + /* Refresh the desc even if buffer_addrs didn't change + * because each write-back erases this info. */ rx_desc->read.pkt_addr = cpu_to_le64(bi->page_dma); rx_desc->read.hdr_addr = cpu_to_le64(bi->dma); } else { @@ -1098,56 +1230,48 @@ void ixgbe_alloc_rx_buffers(struct ixgbe_adapter *adapter, i++; if (i == rx_ring->count) i = 0; - bi = &rx_ring->rx_buffer_info[i]; } no_buffers: if (rx_ring->next_to_use != i) { rx_ring->next_to_use = i; - if (i-- == 0) - i = (rx_ring->count - 1); - - ixgbe_release_rx_desc(&adapter->hw, rx_ring, i); + ixgbe_release_rx_desc(rx_ring, i); } } -static inline u16 ixgbe_get_hdr_info(union ixgbe_adv_rx_desc *rx_desc) +static inline u16 ixgbe_get_hlen(union ixgbe_adv_rx_desc *rx_desc) { - return rx_desc->wb.lower.lo_dword.hs_rss.hdr_info; -} - -static inline u16 ixgbe_get_pkt_info(union ixgbe_adv_rx_desc *rx_desc) -{ - return rx_desc->wb.lower.lo_dword.hs_rss.pkt_info; -} - -static inline u32 ixgbe_get_rsc_count(union ixgbe_adv_rx_desc *rx_desc) -{ - return (le32_to_cpu(rx_desc->wb.lower.lo_dword.data) & - IXGBE_RXDADV_RSCCNT_MASK) >> - IXGBE_RXDADV_RSCCNT_SHIFT; + /* HW will not DMA in data larger than the given buffer, even if it + * parses the (NFS, of course) header to be larger. In that case, it + * fills the header buffer and spills the rest into the page. + */ + u16 hdr_info = le16_to_cpu(rx_desc->wb.lower.lo_dword.hs_rss.hdr_info); + u16 hlen = (hdr_info & IXGBE_RXDADV_HDRBUFLEN_MASK) >> + IXGBE_RXDADV_HDRBUFLEN_SHIFT; + if (hlen > IXGBE_RX_HDR_SIZE) + hlen = IXGBE_RX_HDR_SIZE; + return hlen; } /** * ixgbe_transform_rsc_queue - change rsc queue into a full packet * @skb: pointer to the last skb in the rsc queue - * @count: pointer to number of packets coalesced in this context * * This function changes a queue full of hw rsc buffers into a completed * packet. It uses the ->prev pointers to find the first packet and then * turns it into the frag list owner. **/ -static inline struct sk_buff *ixgbe_transform_rsc_queue(struct sk_buff *skb, - u64 *count) +static inline struct sk_buff *ixgbe_transform_rsc_queue(struct sk_buff *skb) { unsigned int frag_list_size = 0; + unsigned int skb_cnt = 1; while (skb->prev) { struct sk_buff *prev = skb->prev; frag_list_size += skb->len; skb->prev = NULL; skb = prev; - *count += 1; + skb_cnt++; } skb_shinfo(skb)->frag_list = skb->next; @@ -1155,68 +1279,59 @@ static inline struct sk_buff *ixgbe_transform_rsc_queue(struct sk_buff *skb, skb->len += frag_list_size; skb->data_len += frag_list_size; skb->truesize += frag_list_size; + IXGBE_RSC_CB(skb)->skb_cnt = skb_cnt; + return skb; } -struct ixgbe_rsc_cb { - dma_addr_t dma; - bool delay_unmap; -}; - -#define IXGBE_RSC_CB(skb) ((struct ixgbe_rsc_cb *)(skb)->cb) +static inline bool ixgbe_get_rsc_state(union ixgbe_adv_rx_desc *rx_desc) +{ + return !!(le32_to_cpu(rx_desc->wb.lower.lo_dword.data) & + IXGBE_RXDADV_RSCCNT_MASK); +} -static bool ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector, +static void ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector, struct ixgbe_ring *rx_ring, int *work_done, int work_to_do) { struct ixgbe_adapter *adapter = q_vector->adapter; - struct pci_dev *pdev = adapter->pdev; union ixgbe_adv_rx_desc *rx_desc, *next_rxd; struct ixgbe_rx_buffer *rx_buffer_info, *next_buffer; struct sk_buff *skb; - unsigned int i, rsc_count = 0; - u32 len, staterr; - u16 hdr_info; - bool cleaned = false; - int cleaned_count = 0; unsigned int total_rx_bytes = 0, total_rx_packets = 0; + const int current_node = numa_node_id(); #ifdef IXGBE_FCOE int ddp_bytes = 0; #endif /* IXGBE_FCOE */ + u32 staterr; + u16 i; + u16 cleaned_count = 0; + bool pkt_is_rsc = false; i = rx_ring->next_to_clean; rx_desc = IXGBE_RX_DESC_ADV(rx_ring, i); staterr = le32_to_cpu(rx_desc->wb.upper.status_error); - rx_buffer_info = &rx_ring->rx_buffer_info[i]; while (staterr & IXGBE_RXD_STAT_DD) { u32 upper_len = 0; - if (*work_done >= work_to_do) - break; - (*work_done)++; rmb(); /* read descriptor and rx_buffer_info after status DD */ - if (rx_ring->flags & IXGBE_RING_RX_PS_ENABLED) { - hdr_info = le16_to_cpu(ixgbe_get_hdr_info(rx_desc)); - len = (hdr_info & IXGBE_RXDADV_HDRBUFLEN_MASK) >> - IXGBE_RXDADV_HDRBUFLEN_SHIFT; - upper_len = le16_to_cpu(rx_desc->wb.upper.length); - if ((len > IXGBE_RX_HDR_SIZE) || - (upper_len && !(hdr_info & IXGBE_RXDADV_SPH))) - len = IXGBE_RX_HDR_SIZE; - } else { - len = le16_to_cpu(rx_desc->wb.upper.length); - } - cleaned = true; + rx_buffer_info = &rx_ring->rx_buffer_info[i]; + skb = rx_buffer_info->skb; - prefetch(skb->data); rx_buffer_info->skb = NULL; + prefetch(skb->data); + if (ring_is_rsc_enabled(rx_ring)) + pkt_is_rsc = ixgbe_get_rsc_state(rx_desc); + + /* if this is a skb from previous receive DMA will be 0 */ if (rx_buffer_info->dma) { - if ((adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED) && - (!(staterr & IXGBE_RXD_STAT_EOP)) && - (!(skb->prev))) { + u16 hlen; + if (pkt_is_rsc && + !(staterr & IXGBE_RXD_STAT_EOP) && + !skb->prev) { /* * When HWRSC is enabled, delay unmapping * of the first packet. It carries the @@ -1227,29 +1342,42 @@ static bool ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector, IXGBE_RSC_CB(skb)->delay_unmap = true; IXGBE_RSC_CB(skb)->dma = rx_buffer_info->dma; } else { - dma_unmap_single(&pdev->dev, + dma_unmap_single(rx_ring->dev, rx_buffer_info->dma, rx_ring->rx_buf_len, DMA_FROM_DEVICE); } rx_buffer_info->dma = 0; - skb_put(skb, len); + + if (ring_is_ps_enabled(rx_ring)) { + hlen = ixgbe_get_hlen(rx_desc); + upper_len = le16_to_cpu(rx_desc->wb.upper.length); + } else { + hlen = le16_to_cpu(rx_desc->wb.upper.length); + } + + skb_put(skb, hlen); + } else { + /* assume packet split since header is unmapped */ + upper_len = le16_to_cpu(rx_desc->wb.upper.length); } if (upper_len) { - dma_unmap_page(&pdev->dev, rx_buffer_info->page_dma, - PAGE_SIZE / 2, DMA_FROM_DEVICE); + dma_unmap_page(rx_ring->dev, + rx_buffer_info->page_dma, + PAGE_SIZE / 2, + DMA_FROM_DEVICE); rx_buffer_info->page_dma = 0; skb_fill_page_desc(skb, skb_shinfo(skb)->nr_frags, rx_buffer_info->page, rx_buffer_info->page_offset, upper_len); - if ((rx_ring->rx_buf_len > (PAGE_SIZE / 2)) || - (page_count(rx_buffer_info->page) != 1)) - rx_buffer_info->page = NULL; - else + if ((page_count(rx_buffer_info->page) == 1) && + (page_to_nid(rx_buffer_info->page) == current_node)) get_page(rx_buffer_info->page); + else + rx_buffer_info->page = NULL; skb->len += upper_len; skb->data_len += upper_len; @@ -1264,10 +1392,7 @@ static bool ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector, prefetch(next_rxd); cleaned_count++; - if (adapter->flags2 & IXGBE_FLAG2_RSC_CAPABLE) - rsc_count = ixgbe_get_rsc_count(rx_desc); - - if (rsc_count) { + if (pkt_is_rsc) { u32 nextp = (staterr & IXGBE_RXDADV_NEXTP_MASK) >> IXGBE_RXDADV_NEXTP_SHIFT; next_buffer = &rx_ring->rx_buffer_info[nextp]; @@ -1275,32 +1400,8 @@ static bool ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector, next_buffer = &rx_ring->rx_buffer_info[i]; } - if (staterr & IXGBE_RXD_STAT_EOP) { - if (skb->prev) - skb = ixgbe_transform_rsc_queue(skb, - &(rx_ring->rsc_count)); - if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED) { - if (IXGBE_RSC_CB(skb)->delay_unmap) { - dma_unmap_single(&pdev->dev, - IXGBE_RSC_CB(skb)->dma, - rx_ring->rx_buf_len, - DMA_FROM_DEVICE); - IXGBE_RSC_CB(skb)->dma = 0; - IXGBE_RSC_CB(skb)->delay_unmap = false; - } - if (rx_ring->flags & IXGBE_RING_RX_PS_ENABLED) - rx_ring->rsc_count += - skb_shinfo(skb)->nr_frags; - else - rx_ring->rsc_count++; - rx_ring->rsc_flush++; - } - u64_stats_update_begin(&rx_ring->syncp); - rx_ring->stats.packets++; - rx_ring->stats.bytes += skb->len; - u64_stats_update_end(&rx_ring->syncp); - } else { - if (rx_ring->flags & IXGBE_RING_RX_PS_ENABLED) { + if (!(staterr & IXGBE_RXD_STAT_EOP)) { + if (ring_is_ps_enabled(rx_ring)) { rx_buffer_info->skb = next_buffer->skb; rx_buffer_info->dma = next_buffer->dma; next_buffer->skb = skb; @@ -1309,12 +1410,45 @@ static bool ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector, skb->next = next_buffer->skb; skb->next->prev = skb; } - rx_ring->non_eop_descs++; + rx_ring->rx_stats.non_eop_descs++; goto next_desc; } + if (skb->prev) { + skb = ixgbe_transform_rsc_queue(skb); + /* if we got here without RSC the packet is invalid */ + if (!pkt_is_rsc) { + __pskb_trim(skb, 0); + rx_buffer_info->skb = skb; + goto next_desc; + } + } + + if (ring_is_rsc_enabled(rx_ring)) { + if (IXGBE_RSC_CB(skb)->delay_unmap) { + dma_unmap_single(rx_ring->dev, + IXGBE_RSC_CB(skb)->dma, + rx_ring->rx_buf_len, + DMA_FROM_DEVICE); + IXGBE_RSC_CB(skb)->dma = 0; + IXGBE_RSC_CB(skb)->delay_unmap = false; + } + } + if (pkt_is_rsc) { + if (ring_is_ps_enabled(rx_ring)) + rx_ring->rx_stats.rsc_count += + skb_shinfo(skb)->nr_frags; + else + rx_ring->rx_stats.rsc_count += + IXGBE_RSC_CB(skb)->skb_cnt; + rx_ring->rx_stats.rsc_flush++; + } + + /* ERR_MASK will only have valid bits if EOP set */ if (staterr & IXGBE_RXDADV_ERR_FRAME_ERR_MASK) { - dev_kfree_skb_irq(skb); + /* trim packet back to size 0 and recycle it */ + __pskb_trim(skb, 0); + rx_buffer_info->skb = skb; goto next_desc; } @@ -1324,7 +1458,7 @@ static bool ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector, total_rx_bytes += skb->len; total_rx_packets++; - skb->protocol = eth_type_trans(skb, adapter->netdev); + skb->protocol = eth_type_trans(skb, rx_ring->netdev); #ifdef IXGBE_FCOE /* if ddp, not passing to ULD unless for FCP_RSP or error */ if (adapter->flags & IXGBE_FLAG_FCOE_ENABLED) { @@ -1338,16 +1472,18 @@ static bool ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector, next_desc: rx_desc->wb.upper.status_error = 0; + (*work_done)++; + if (*work_done >= work_to_do) + break; + /* return some buffers to hardware, one at a time is too slow */ if (cleaned_count >= IXGBE_RX_BUFFER_WRITE) { - ixgbe_alloc_rx_buffers(adapter, rx_ring, cleaned_count); + ixgbe_alloc_rx_buffers(rx_ring, cleaned_count); cleaned_count = 0; } /* use prefetched values */ rx_desc = next_rxd; - rx_buffer_info = &rx_ring->rx_buffer_info[i]; - staterr = le32_to_cpu(rx_desc->wb.upper.status_error); } @@ -1355,14 +1491,14 @@ next_desc: cleaned_count = IXGBE_DESC_UNUSED(rx_ring); if (cleaned_count) - ixgbe_alloc_rx_buffers(adapter, rx_ring, cleaned_count); + ixgbe_alloc_rx_buffers(rx_ring, cleaned_count); #ifdef IXGBE_FCOE /* include DDPed FCoE data */ if (ddp_bytes > 0) { unsigned int mss; - mss = adapter->netdev->mtu - sizeof(struct fcoe_hdr) - + mss = rx_ring->netdev->mtu - sizeof(struct fcoe_hdr) - sizeof(struct fc_frame_header) - sizeof(struct fcoe_crc_eof); if (mss > 512) @@ -1374,8 +1510,10 @@ next_desc: rx_ring->total_packets += total_rx_packets; rx_ring->total_bytes += total_rx_bytes; - - return cleaned; + u64_stats_update_begin(&rx_ring->syncp); + rx_ring->stats.packets += total_rx_packets; + rx_ring->stats.bytes += total_rx_bytes; + u64_stats_update_end(&rx_ring->syncp); } static int ixgbe_clean_rxonly(struct napi_struct *, int); @@ -1389,7 +1527,7 @@ static int ixgbe_clean_rxonly(struct napi_struct *, int); static void ixgbe_configure_msix(struct ixgbe_adapter *adapter) { struct ixgbe_q_vector *q_vector; - int i, j, q_vectors, v_idx, r_idx; + int i, q_vectors, v_idx, r_idx; u32 mask; q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS; @@ -1405,8 +1543,8 @@ static void ixgbe_configure_msix(struct ixgbe_adapter *adapter) adapter->num_rx_queues); for (i = 0; i < q_vector->rxr_count; i++) { - j = adapter->rx_ring[r_idx]->reg_idx; - ixgbe_set_ivar(adapter, 0, j, v_idx); + u8 reg_idx = adapter->rx_ring[r_idx]->reg_idx; + ixgbe_set_ivar(adapter, 0, reg_idx, v_idx); r_idx = find_next_bit(q_vector->rxr_idx, adapter->num_rx_queues, r_idx + 1); @@ -1415,8 +1553,8 @@ static void ixgbe_configure_msix(struct ixgbe_adapter *adapter) adapter->num_tx_queues); for (i = 0; i < q_vector->txr_count; i++) { - j = adapter->tx_ring[r_idx]->reg_idx; - ixgbe_set_ivar(adapter, 1, j, v_idx); + u8 reg_idx = adapter->tx_ring[r_idx]->reg_idx; + ixgbe_set_ivar(adapter, 1, reg_idx, v_idx); r_idx = find_next_bit(q_vector->txr_idx, adapter->num_tx_queues, r_idx + 1); @@ -1447,11 +1585,19 @@ static void ixgbe_configure_msix(struct ixgbe_adapter *adapter) } } - if (adapter->hw.mac.type == ixgbe_mac_82598EB) + switch (adapter->hw.mac.type) { + case ixgbe_mac_82598EB: ixgbe_set_ivar(adapter, -1, IXGBE_IVAR_OTHER_CAUSES_INDEX, v_idx); - else if (adapter->hw.mac.type == ixgbe_mac_82599EB) + break; + case ixgbe_mac_82599EB: + case ixgbe_mac_X540: ixgbe_set_ivar(adapter, -1, 1, v_idx); + break; + + default: + break; + } IXGBE_WRITE_REG(&adapter->hw, IXGBE_EITR(v_idx), 1950); /* set up to autoclear timer, and the vectors */ @@ -1547,12 +1693,15 @@ void ixgbe_write_eitr(struct ixgbe_q_vector *q_vector) int v_idx = q_vector->v_idx; u32 itr_reg = EITR_INTS_PER_SEC_TO_REG(q_vector->eitr); - if (adapter->hw.mac.type == ixgbe_mac_82598EB) { + switch (adapter->hw.mac.type) { + case ixgbe_mac_82598EB: /* must write high and low 16 bits to reset counter */ itr_reg |= (itr_reg << 16); - } else if (adapter->hw.mac.type == ixgbe_mac_82599EB) { + break; + case ixgbe_mac_82599EB: + case ixgbe_mac_X540: /* - * 82599 can support a value of zero, so allow it for + * 82599 and X540 can support a value of zero, so allow it for * max interrupt rate, but there is an errata where it can * not be zero with RSC */ @@ -1565,6 +1714,9 @@ void ixgbe_write_eitr(struct ixgbe_q_vector *q_vector) * immediate assertion of the interrupt */ itr_reg |= IXGBE_EITR_CNT_WDIS; + break; + default: + break; } IXGBE_WRITE_REG(hw, IXGBE_EITR(v_idx), itr_reg); } @@ -1572,14 +1724,13 @@ void ixgbe_write_eitr(struct ixgbe_q_vector *q_vector) static void ixgbe_set_itr_msix(struct ixgbe_q_vector *q_vector) { struct ixgbe_adapter *adapter = q_vector->adapter; + int i, r_idx; u32 new_itr; u8 current_itr, ret_itr; - int i, r_idx; - struct ixgbe_ring *rx_ring, *tx_ring; r_idx = find_first_bit(q_vector->txr_idx, adapter->num_tx_queues); for (i = 0; i < q_vector->txr_count; i++) { - tx_ring = adapter->tx_ring[r_idx]; + struct ixgbe_ring *tx_ring = adapter->tx_ring[r_idx]; ret_itr = ixgbe_update_itr(adapter, q_vector->eitr, q_vector->tx_itr, tx_ring->total_packets, @@ -1594,7 +1745,7 @@ static void ixgbe_set_itr_msix(struct ixgbe_q_vector *q_vector) r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues); for (i = 0; i < q_vector->rxr_count; i++) { - rx_ring = adapter->rx_ring[r_idx]; + struct ixgbe_ring *rx_ring = adapter->rx_ring[r_idx]; ret_itr = ixgbe_update_itr(adapter, q_vector->eitr, q_vector->rx_itr, rx_ring->total_packets, @@ -1625,7 +1776,7 @@ static void ixgbe_set_itr_msix(struct ixgbe_q_vector *q_vector) if (new_itr != q_vector->eitr) { /* do an exponential smoothing */ - new_itr = ((q_vector->eitr * 90)/100) + ((new_itr * 10)/100); + new_itr = ((q_vector->eitr * 9) + new_itr)/10; /* save the algorithm value here, not the smoothed one */ q_vector->eitr = new_itr; @@ -1693,17 +1844,18 @@ static void ixgbe_check_sfp_event(struct ixgbe_adapter *adapter, u32 eicr) { struct ixgbe_hw *hw = &adapter->hw; + if (eicr & IXGBE_EICR_GPI_SDP2) { + /* Clear the interrupt */ + IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP2); + if (!test_bit(__IXGBE_DOWN, &adapter->state)) + schedule_work(&adapter->sfp_config_module_task); + } + if (eicr & IXGBE_EICR_GPI_SDP1) { /* Clear the interrupt */ IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP1); - schedule_work(&adapter->multispeed_fiber_task); - } else if (eicr & IXGBE_EICR_GPI_SDP2) { - /* Clear the interrupt */ - IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP2); - schedule_work(&adapter->sfp_config_module_task); - } else { - /* Interrupt isn't for us... */ - return; + if (!test_bit(__IXGBE_DOWN, &adapter->state)) + schedule_work(&adapter->multispeed_fiber_task); } } @@ -1743,16 +1895,9 @@ static irqreturn_t ixgbe_msix_lsc(int irq, void *data) if (eicr & IXGBE_EICR_MAILBOX) ixgbe_msg_task(adapter); - if (hw->mac.type == ixgbe_mac_82598EB) - ixgbe_check_fan_failure(adapter, eicr); - - if (hw->mac.type == ixgbe_mac_82599EB) { - ixgbe_check_sfp_event(adapter, eicr); - adapter->interrupt_event = eicr; - if ((adapter->flags2 & IXGBE_FLAG2_TEMP_SENSOR_CAPABLE) && - ((eicr & IXGBE_EICR_GPI_SDP0) || (eicr & IXGBE_EICR_LSC))) - schedule_work(&adapter->check_overtemp_task); - + switch (hw->mac.type) { + case ixgbe_mac_82599EB: + case ixgbe_mac_X540: /* Handle Flow Director Full threshold interrupt */ if (eicr & IXGBE_EICR_FLOW_DIR) { int i; @@ -1762,12 +1907,24 @@ static irqreturn_t ixgbe_msix_lsc(int irq, void *data) for (i = 0; i < adapter->num_tx_queues; i++) { struct ixgbe_ring *tx_ring = adapter->tx_ring[i]; - if (test_and_clear_bit(__IXGBE_FDIR_INIT_DONE, - &tx_ring->reinit_state)) + if (test_and_clear_bit(__IXGBE_TX_FDIR_INIT_DONE, + &tx_ring->state)) schedule_work(&adapter->fdir_reinit_task); } } + ixgbe_check_sfp_event(adapter, eicr); + if ((adapter->flags2 & IXGBE_FLAG2_TEMP_SENSOR_CAPABLE) && + ((eicr & IXGBE_EICR_GPI_SDP0) || (eicr & IXGBE_EICR_LSC))) { + adapter->interrupt_event = eicr; + schedule_work(&adapter->check_overtemp_task); + } + break; + default: + break; } + + ixgbe_check_fan_failure(adapter, eicr); + if (!test_bit(__IXGBE_DOWN, &adapter->state)) IXGBE_WRITE_REG(hw, IXGBE_EIMS, IXGBE_EIMS_OTHER); @@ -1778,15 +1935,24 @@ static inline void ixgbe_irq_enable_queues(struct ixgbe_adapter *adapter, u64 qmask) { u32 mask; + struct ixgbe_hw *hw = &adapter->hw; - if (adapter->hw.mac.type == ixgbe_mac_82598EB) { + switch (hw->mac.type) { + case ixgbe_mac_82598EB: mask = (IXGBE_EIMS_RTX_QUEUE & qmask); - IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, mask); - } else { + IXGBE_WRITE_REG(hw, IXGBE_EIMS, mask); + break; + case ixgbe_mac_82599EB: + case ixgbe_mac_X540: mask = (qmask & 0xFFFFFFFF); - IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS_EX(0), mask); + if (mask) + IXGBE_WRITE_REG(hw, IXGBE_EIMS_EX(0), mask); mask = (qmask >> 32); - IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS_EX(1), mask); + if (mask) + IXGBE_WRITE_REG(hw, IXGBE_EIMS_EX(1), mask); + break; + default: + break; } /* skip the flush */ } @@ -1795,15 +1961,24 @@ static inline void ixgbe_irq_disable_queues(struct ixgbe_adapter *adapter, u64 qmask) { u32 mask; + struct ixgbe_hw *hw = &adapter->hw; - if (adapter->hw.mac.type == ixgbe_mac_82598EB) { + switch (hw->mac.type) { + case ixgbe_mac_82598EB: mask = (IXGBE_EIMS_RTX_QUEUE & qmask); - IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, mask); - } else { + IXGBE_WRITE_REG(hw, IXGBE_EIMC, mask); + break; + case ixgbe_mac_82599EB: + case ixgbe_mac_X540: mask = (qmask & 0xFFFFFFFF); - IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC_EX(0), mask); + if (mask) + IXGBE_WRITE_REG(hw, IXGBE_EIMC_EX(0), mask); mask = (qmask >> 32); - IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC_EX(1), mask); + if (mask) + IXGBE_WRITE_REG(hw, IXGBE_EIMC_EX(1), mask); + break; + default: + break; } /* skip the flush */ } @@ -1846,8 +2021,13 @@ static irqreturn_t ixgbe_msix_clean_rx(int irq, void *data) int r_idx; int i; +#ifdef CONFIG_IXGBE_DCA + if (adapter->flags & IXGBE_FLAG_DCA_ENABLED) + ixgbe_update_dca(q_vector); +#endif + r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues); - for (i = 0; i < q_vector->rxr_count; i++) { + for (i = 0; i < q_vector->rxr_count; i++) { rx_ring = adapter->rx_ring[r_idx]; rx_ring->total_bytes = 0; rx_ring->total_packets = 0; @@ -1858,7 +2038,6 @@ static irqreturn_t ixgbe_msix_clean_rx(int irq, void *data) if (!q_vector->rxr_count) return IRQ_HANDLED; - /* disable interrupts on this vector only */ /* EIAM disabled interrupts (on this vector) for us */ napi_schedule(&q_vector->napi); @@ -1917,13 +2096,14 @@ static int ixgbe_clean_rxonly(struct napi_struct *napi, int budget) int work_done = 0; long r_idx; - r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues); - rx_ring = adapter->rx_ring[r_idx]; #ifdef CONFIG_IXGBE_DCA if (adapter->flags & IXGBE_FLAG_DCA_ENABLED) - ixgbe_update_rx_dca(adapter, rx_ring); + ixgbe_update_dca(q_vector); #endif + r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues); + rx_ring = adapter->rx_ring[r_idx]; + ixgbe_clean_rx_irq(q_vector, rx_ring, &work_done, budget); /* If all Rx work done, exit the polling mode */ @@ -1957,13 +2137,14 @@ static int ixgbe_clean_rxtx_many(struct napi_struct *napi, int budget) long r_idx; bool tx_clean_complete = true; +#ifdef CONFIG_IXGBE_DCA + if (adapter->flags & IXGBE_FLAG_DCA_ENABLED) + ixgbe_update_dca(q_vector); +#endif + r_idx = find_first_bit(q_vector->txr_idx, adapter->num_tx_queues); for (i = 0; i < q_vector->txr_count; i++) { ring = adapter->tx_ring[r_idx]; -#ifdef CONFIG_IXGBE_DCA - if (adapter->flags & IXGBE_FLAG_DCA_ENABLED) - ixgbe_update_tx_dca(adapter, ring); -#endif tx_clean_complete &= ixgbe_clean_tx_irq(q_vector, ring); r_idx = find_next_bit(q_vector->txr_idx, adapter->num_tx_queues, r_idx + 1); @@ -1976,10 +2157,6 @@ static int ixgbe_clean_rxtx_many(struct napi_struct *napi, int budget) r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues); for (i = 0; i < q_vector->rxr_count; i++) { ring = adapter->rx_ring[r_idx]; -#ifdef CONFIG_IXGBE_DCA - if (adapter->flags & IXGBE_FLAG_DCA_ENABLED) - ixgbe_update_rx_dca(adapter, ring); -#endif ixgbe_clean_rx_irq(q_vector, ring, &work_done, budget); r_idx = find_next_bit(q_vector->rxr_idx, adapter->num_rx_queues, r_idx + 1); @@ -2018,13 +2195,14 @@ static int ixgbe_clean_txonly(struct napi_struct *napi, int budget) int work_done = 0; long r_idx; - r_idx = find_first_bit(q_vector->txr_idx, adapter->num_tx_queues); - tx_ring = adapter->tx_ring[r_idx]; #ifdef CONFIG_IXGBE_DCA if (adapter->flags & IXGBE_FLAG_DCA_ENABLED) - ixgbe_update_tx_dca(adapter, tx_ring); + ixgbe_update_dca(q_vector); #endif + r_idx = find_first_bit(q_vector->txr_idx, adapter->num_tx_queues); + tx_ring = adapter->tx_ring[r_idx]; + if (!ixgbe_clean_tx_irq(q_vector, tx_ring)) work_done = budget; @@ -2045,24 +2223,27 @@ static inline void map_vector_to_rxq(struct ixgbe_adapter *a, int v_idx, int r_idx) { struct ixgbe_q_vector *q_vector = a->q_vector[v_idx]; + struct ixgbe_ring *rx_ring = a->rx_ring[r_idx]; set_bit(r_idx, q_vector->rxr_idx); q_vector->rxr_count++; + rx_ring->q_vector = q_vector; } static inline void map_vector_to_txq(struct ixgbe_adapter *a, int v_idx, int t_idx) { struct ixgbe_q_vector *q_vector = a->q_vector[v_idx]; + struct ixgbe_ring *tx_ring = a->tx_ring[t_idx]; set_bit(t_idx, q_vector->txr_idx); q_vector->txr_count++; + tx_ring->q_vector = q_vector; } /** * ixgbe_map_rings_to_vectors - Maps descriptor rings to vectors * @adapter: board private structure to initialize - * @vectors: allotted vector count for descriptor rings * * This function maps descriptor rings to the queue-specific vectors * we were allotted through the MSI-X enabling code. Ideally, we'd have @@ -2070,9 +2251,9 @@ static inline void map_vector_to_txq(struct ixgbe_adapter *a, int v_idx, * group the rings as "efficiently" as possible. You would add new * mapping configurations in here. **/ -static int ixgbe_map_rings_to_vectors(struct ixgbe_adapter *adapter, - int vectors) +static int ixgbe_map_rings_to_vectors(struct ixgbe_adapter *adapter) { + int q_vectors; int v_start = 0; int rxr_idx = 0, txr_idx = 0; int rxr_remaining = adapter->num_rx_queues; @@ -2085,11 +2266,13 @@ static int ixgbe_map_rings_to_vectors(struct ixgbe_adapter *adapter, if (!(adapter->flags & IXGBE_FLAG_MSIX_ENABLED)) goto out; + q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS; + /* * The ideal configuration... * We have enough vectors to map one per queue. */ - if (vectors == adapter->num_rx_queues + adapter->num_tx_queues) { + if (q_vectors == adapter->num_rx_queues + adapter->num_tx_queues) { for (; rxr_idx < rxr_remaining; v_start++, rxr_idx++) map_vector_to_rxq(adapter, v_start, rxr_idx); @@ -2105,23 +2288,20 @@ static int ixgbe_map_rings_to_vectors(struct ixgbe_adapter *adapter, * multiple queues per vector. */ /* Re-adjusting *qpv takes care of the remainder. */ - for (i = v_start; i < vectors; i++) { - rqpv = DIV_ROUND_UP(rxr_remaining, vectors - i); + for (i = v_start; i < q_vectors; i++) { + rqpv = DIV_ROUND_UP(rxr_remaining, q_vectors - i); for (j = 0; j < rqpv; j++) { map_vector_to_rxq(adapter, i, rxr_idx); rxr_idx++; rxr_remaining--; } - } - for (i = v_start; i < vectors; i++) { - tqpv = DIV_ROUND_UP(txr_remaining, vectors - i); + tqpv = DIV_ROUND_UP(txr_remaining, q_vectors - i); for (j = 0; j < tqpv; j++) { map_vector_to_txq(adapter, i, txr_idx); txr_idx++; txr_remaining--; } } - out: return err; } @@ -2143,30 +2323,36 @@ static int ixgbe_request_msix_irqs(struct ixgbe_adapter *adapter) /* Decrement for Other and TCP Timer vectors */ q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS; - /* Map the Tx/Rx rings to the vectors we were allotted. */ - err = ixgbe_map_rings_to_vectors(adapter, q_vectors); + err = ixgbe_map_rings_to_vectors(adapter); if (err) - goto out; + return err; -#define SET_HANDLER(_v) ((!(_v)->rxr_count) ? &ixgbe_msix_clean_tx : \ - (!(_v)->txr_count) ? &ixgbe_msix_clean_rx : \ - &ixgbe_msix_clean_many) +#define SET_HANDLER(_v) (((_v)->rxr_count && (_v)->txr_count) \ + ? &ixgbe_msix_clean_many : \ + (_v)->rxr_count ? &ixgbe_msix_clean_rx : \ + (_v)->txr_count ? &ixgbe_msix_clean_tx : \ + NULL) for (vector = 0; vector < q_vectors; vector++) { - handler = SET_HANDLER(adapter->q_vector[vector]); + struct ixgbe_q_vector *q_vector = adapter->q_vector[vector]; + handler = SET_HANDLER(q_vector); if (handler == &ixgbe_msix_clean_rx) { - sprintf(adapter->name[vector], "%s-%s-%d", + sprintf(q_vector->name, "%s-%s-%d", netdev->name, "rx", ri++); } else if (handler == &ixgbe_msix_clean_tx) { - sprintf(adapter->name[vector], "%s-%s-%d", + sprintf(q_vector->name, "%s-%s-%d", netdev->name, "tx", ti++); - } else - sprintf(adapter->name[vector], "%s-%s-%d", - netdev->name, "TxRx", vector); - + } else if (handler == &ixgbe_msix_clean_many) { + sprintf(q_vector->name, "%s-%s-%d", + netdev->name, "TxRx", ri++); + ti++; + } else { + /* skip this unused q_vector */ + continue; + } err = request_irq(adapter->msix_entries[vector].vector, - handler, 0, adapter->name[vector], - adapter->q_vector[vector]); + handler, 0, q_vector->name, + q_vector); if (err) { e_err(probe, "request_irq failed for MSIX interrupt " "Error: %d\n", err); @@ -2174,9 +2360,9 @@ static int ixgbe_request_msix_irqs(struct ixgbe_adapter *adapter) } } - sprintf(adapter->name[vector], "%s:lsc", netdev->name); + sprintf(adapter->lsc_int_name, "%s:lsc", netdev->name); err = request_irq(adapter->msix_entries[vector].vector, - ixgbe_msix_lsc, 0, adapter->name[vector], netdev); + ixgbe_msix_lsc, 0, adapter->lsc_int_name, netdev); if (err) { e_err(probe, "request_irq for msix_lsc failed: %d\n", err); goto free_queue_irqs; @@ -2192,17 +2378,16 @@ free_queue_irqs: pci_disable_msix(adapter->pdev); kfree(adapter->msix_entries); adapter->msix_entries = NULL; -out: return err; } static void ixgbe_set_itr(struct ixgbe_adapter *adapter) { struct ixgbe_q_vector *q_vector = adapter->q_vector[0]; - u8 current_itr; - u32 new_itr = q_vector->eitr; struct ixgbe_ring *rx_ring = adapter->rx_ring[0]; struct ixgbe_ring *tx_ring = adapter->tx_ring[0]; + u32 new_itr = q_vector->eitr; + u8 current_itr; q_vector->tx_itr = ixgbe_update_itr(adapter, new_itr, q_vector->tx_itr, @@ -2232,9 +2417,9 @@ static void ixgbe_set_itr(struct ixgbe_adapter *adapter) if (new_itr != q_vector->eitr) { /* do an exponential smoothing */ - new_itr = ((q_vector->eitr * 90)/100) + ((new_itr * 10)/100); + new_itr = ((q_vector->eitr * 9) + new_itr)/10; - /* save the algorithm value here, not the smoothed one */ + /* save the algorithm value here */ q_vector->eitr = new_itr; ixgbe_write_eitr(q_vector); @@ -2255,12 +2440,17 @@ static inline void ixgbe_irq_enable(struct ixgbe_adapter *adapter, bool queues, mask |= IXGBE_EIMS_GPI_SDP0; if (adapter->flags & IXGBE_FLAG_FAN_FAIL_CAPABLE) mask |= IXGBE_EIMS_GPI_SDP1; - if (adapter->hw.mac.type == ixgbe_mac_82599EB) { + switch (adapter->hw.mac.type) { + case ixgbe_mac_82599EB: + case ixgbe_mac_X540: mask |= IXGBE_EIMS_ECC; mask |= IXGBE_EIMS_GPI_SDP1; mask |= IXGBE_EIMS_GPI_SDP2; if (adapter->num_vfs) mask |= IXGBE_EIMS_MAILBOX; + break; + default: + break; } if (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE || adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE) @@ -2316,13 +2506,21 @@ static irqreturn_t ixgbe_intr(int irq, void *data) if (eicr & IXGBE_EICR_LSC) ixgbe_check_lsc(adapter); - if (hw->mac.type == ixgbe_mac_82599EB) + switch (hw->mac.type) { + case ixgbe_mac_82599EB: + case ixgbe_mac_X540: ixgbe_check_sfp_event(adapter, eicr); + if ((adapter->flags2 & IXGBE_FLAG2_TEMP_SENSOR_CAPABLE) && + ((eicr & IXGBE_EICR_GPI_SDP0) || (eicr & IXGBE_EICR_LSC))) { + adapter->interrupt_event = eicr; + schedule_work(&adapter->check_overtemp_task); + } + break; + default: + break; + } ixgbe_check_fan_failure(adapter, eicr); - if ((adapter->flags2 & IXGBE_FLAG2_TEMP_SENSOR_CAPABLE) && - ((eicr & IXGBE_EICR_GPI_SDP0) || (eicr & IXGBE_EICR_LSC))) - schedule_work(&adapter->check_overtemp_task); if (napi_schedule_prep(&(q_vector->napi))) { adapter->tx_ring[0]->total_packets = 0; @@ -2415,14 +2613,20 @@ static void ixgbe_free_irq(struct ixgbe_adapter *adapter) **/ static inline void ixgbe_irq_disable(struct ixgbe_adapter *adapter) { - if (adapter->hw.mac.type == ixgbe_mac_82598EB) { + switch (adapter->hw.mac.type) { + case ixgbe_mac_82598EB: IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, ~0); - } else { + break; + case ixgbe_mac_82599EB: + case ixgbe_mac_X540: IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, 0xFFFF0000); IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC_EX(0), ~0); IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC_EX(1), ~0); if (adapter->num_vfs > 32) IXGBE_WRITE_REG(&adapter->hw, IXGBE_EITRSEL, 0); + break; + default: + break; } IXGBE_WRITE_FLUSH(&adapter->hw); if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) { @@ -2468,7 +2672,7 @@ void ixgbe_configure_tx_ring(struct ixgbe_adapter *adapter, u64 tdba = ring->dma; int wait_loop = 10; u32 txdctl; - u16 reg_idx = ring->reg_idx; + u8 reg_idx = ring->reg_idx; /* disable queue to avoid issues while updating state */ txdctl = IXGBE_READ_REG(hw, IXGBE_TXDCTL(reg_idx)); @@ -2483,8 +2687,7 @@ void ixgbe_configure_tx_ring(struct ixgbe_adapter *adapter, ring->count * sizeof(union ixgbe_adv_tx_desc)); IXGBE_WRITE_REG(hw, IXGBE_TDH(reg_idx), 0); IXGBE_WRITE_REG(hw, IXGBE_TDT(reg_idx), 0); - ring->head = IXGBE_TDH(reg_idx); - ring->tail = IXGBE_TDT(reg_idx); + ring->tail = hw->hw_addr + IXGBE_TDT(reg_idx); /* configure fetching thresholds */ if (adapter->rx_itr_setting == 0) { @@ -2500,7 +2703,16 @@ void ixgbe_configure_tx_ring(struct ixgbe_adapter *adapter, } /* reinitialize flowdirector state */ - set_bit(__IXGBE_FDIR_INIT_DONE, &ring->reinit_state); + if ((adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE) && + adapter->atr_sample_rate) { + ring->atr_sample_rate = adapter->atr_sample_rate; + ring->atr_count = 0; + set_bit(__IXGBE_TX_FDIR_INIT_DONE, &ring->state); + } else { + ring->atr_sample_rate = 0; + } + + clear_bit(__IXGBE_HANG_CHECK_ARMED, &ring->state); /* enable queue */ txdctl |= IXGBE_TXDCTL_ENABLE; @@ -2591,16 +2803,22 @@ static void ixgbe_configure_srrctl(struct ixgbe_adapter *adapter, struct ixgbe_ring *rx_ring) { u32 srrctl; - int index; - struct ixgbe_ring_feature *feature = adapter->ring_feature; + u8 reg_idx = rx_ring->reg_idx; - index = rx_ring->reg_idx; - if (adapter->hw.mac.type == ixgbe_mac_82598EB) { - unsigned long mask; - mask = (unsigned long) feature[RING_F_RSS].mask; - index = index & mask; + switch (adapter->hw.mac.type) { + case ixgbe_mac_82598EB: { + struct ixgbe_ring_feature *feature = adapter->ring_feature; + const int mask = feature[RING_F_RSS].mask; + reg_idx = reg_idx & mask; + } + break; + case ixgbe_mac_82599EB: + case ixgbe_mac_X540: + default: + break; } - srrctl = IXGBE_READ_REG(&adapter->hw, IXGBE_SRRCTL(index)); + + srrctl = IXGBE_READ_REG(&adapter->hw, IXGBE_SRRCTL(reg_idx)); srrctl &= ~IXGBE_SRRCTL_BSIZEHDR_MASK; srrctl &= ~IXGBE_SRRCTL_BSIZEPKT_MASK; @@ -2610,7 +2828,7 @@ static void ixgbe_configure_srrctl(struct ixgbe_adapter *adapter, srrctl |= (IXGBE_RX_HDR_SIZE << IXGBE_SRRCTL_BSIZEHDRSIZE_SHIFT) & IXGBE_SRRCTL_BSIZEHDR_MASK; - if (rx_ring->flags & IXGBE_RING_RX_PS_ENABLED) { + if (ring_is_ps_enabled(rx_ring)) { #if (PAGE_SIZE / 2) > IXGBE_MAX_RXBUFFER srrctl |= IXGBE_MAX_RXBUFFER >> IXGBE_SRRCTL_BSIZEPKT_SHIFT; #else @@ -2623,7 +2841,7 @@ static void ixgbe_configure_srrctl(struct ixgbe_adapter *adapter, srrctl |= IXGBE_SRRCTL_DESCTYPE_ADV_ONEBUF; } - IXGBE_WRITE_REG(&adapter->hw, IXGBE_SRRCTL(index), srrctl); + IXGBE_WRITE_REG(&adapter->hw, IXGBE_SRRCTL(reg_idx), srrctl); } static void ixgbe_setup_mrqc(struct ixgbe_adapter *adapter) @@ -2693,19 +2911,36 @@ static void ixgbe_setup_mrqc(struct ixgbe_adapter *adapter) } /** + * ixgbe_clear_rscctl - disable RSC for the indicated ring + * @adapter: address of board private structure + * @ring: structure containing ring specific data + **/ +void ixgbe_clear_rscctl(struct ixgbe_adapter *adapter, + struct ixgbe_ring *ring) +{ + struct ixgbe_hw *hw = &adapter->hw; + u32 rscctrl; + u8 reg_idx = ring->reg_idx; + + rscctrl = IXGBE_READ_REG(hw, IXGBE_RSCCTL(reg_idx)); + rscctrl &= ~IXGBE_RSCCTL_RSCEN; + IXGBE_WRITE_REG(hw, IXGBE_RSCCTL(reg_idx), rscctrl); +} + +/** * ixgbe_configure_rscctl - enable RSC for the indicated ring * @adapter: address of board private structure * @index: index of ring to set **/ -static void ixgbe_configure_rscctl(struct ixgbe_adapter *adapter, +void ixgbe_configure_rscctl(struct ixgbe_adapter *adapter, struct ixgbe_ring *ring) { struct ixgbe_hw *hw = &adapter->hw; u32 rscctrl; int rx_buf_len; - u16 reg_idx = ring->reg_idx; + u8 reg_idx = ring->reg_idx; - if (!(adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED)) + if (!ring_is_rsc_enabled(ring)) return; rx_buf_len = ring->rx_buf_len; @@ -2716,7 +2951,7 @@ static void ixgbe_configure_rscctl(struct ixgbe_adapter *adapter, * total size of max desc * buf_len is not greater * than 65535 */ - if (ring->flags & IXGBE_RING_RX_PS_ENABLED) { + if (ring_is_ps_enabled(ring)) { #if (MAX_SKB_FRAGS > 16) rscctrl |= IXGBE_RSCCTL_MAXDESC_16; #elif (MAX_SKB_FRAGS > 8) @@ -2769,9 +3004,9 @@ static void ixgbe_rx_desc_queue_enable(struct ixgbe_adapter *adapter, struct ixgbe_ring *ring) { struct ixgbe_hw *hw = &adapter->hw; - int reg_idx = ring->reg_idx; int wait_loop = IXGBE_MAX_RX_DESC_POLL; u32 rxdctl; + u8 reg_idx = ring->reg_idx; /* RXDCTL.EN will return 0 on 82598 if link is down, so skip it */ if (hw->mac.type == ixgbe_mac_82598EB && @@ -2795,7 +3030,7 @@ void ixgbe_configure_rx_ring(struct ixgbe_adapter *adapter, struct ixgbe_hw *hw = &adapter->hw; u64 rdba = ring->dma; u32 rxdctl; - u16 reg_idx = ring->reg_idx; + u8 reg_idx = ring->reg_idx; /* disable queue to avoid issues while updating state */ rxdctl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(reg_idx)); @@ -2809,8 +3044,7 @@ void ixgbe_configure_rx_ring(struct ixgbe_adapter *adapter, ring->count * sizeof(union ixgbe_adv_rx_desc)); IXGBE_WRITE_REG(hw, IXGBE_RDH(reg_idx), 0); IXGBE_WRITE_REG(hw, IXGBE_RDT(reg_idx), 0); - ring->head = IXGBE_RDH(reg_idx); - ring->tail = IXGBE_RDT(reg_idx); + ring->tail = hw->hw_addr + IXGBE_RDT(reg_idx); ixgbe_configure_srrctl(adapter, ring); ixgbe_configure_rscctl(adapter, ring); @@ -2832,7 +3066,7 @@ void ixgbe_configure_rx_ring(struct ixgbe_adapter *adapter, IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(reg_idx), rxdctl); ixgbe_rx_desc_queue_enable(adapter, ring); - ixgbe_alloc_rx_buffers(adapter, ring, IXGBE_DESC_UNUSED(ring)); + ixgbe_alloc_rx_buffers(ring, IXGBE_DESC_UNUSED(ring)); } static void ixgbe_setup_psrtype(struct ixgbe_adapter *adapter) @@ -2955,24 +3189,32 @@ static void ixgbe_set_rx_buffer_len(struct ixgbe_adapter *adapter) rx_ring->rx_buf_len = rx_buf_len; if (adapter->flags & IXGBE_FLAG_RX_PS_ENABLED) - rx_ring->flags |= IXGBE_RING_RX_PS_ENABLED; + set_ring_ps_enabled(rx_ring); + else + clear_ring_ps_enabled(rx_ring); + + if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED) + set_ring_rsc_enabled(rx_ring); else - rx_ring->flags &= ~IXGBE_RING_RX_PS_ENABLED; + clear_ring_rsc_enabled(rx_ring); #ifdef IXGBE_FCOE if (netdev->features & NETIF_F_FCOE_MTU) { struct ixgbe_ring_feature *f; f = &adapter->ring_feature[RING_F_FCOE]; if ((i >= f->mask) && (i < f->mask + f->indices)) { - rx_ring->flags &= ~IXGBE_RING_RX_PS_ENABLED; + clear_ring_ps_enabled(rx_ring); if (rx_buf_len < IXGBE_FCOE_JUMBO_FRAME_SIZE) rx_ring->rx_buf_len = IXGBE_FCOE_JUMBO_FRAME_SIZE; + } else if (!ring_is_rsc_enabled(rx_ring) && + !ring_is_ps_enabled(rx_ring)) { + rx_ring->rx_buf_len = + IXGBE_FCOE_JUMBO_FRAME_SIZE; } } #endif /* IXGBE_FCOE */ } - } static void ixgbe_setup_rdrxctl(struct ixgbe_adapter *adapter) @@ -2995,6 +3237,7 @@ static void ixgbe_setup_rdrxctl(struct ixgbe_adapter *adapter) rdrxctl |= IXGBE_RDRXCTL_MVMEN; break; case ixgbe_mac_82599EB: + case ixgbe_mac_X540: /* Disable RSC for ACK packets */ IXGBE_WRITE_REG(hw, IXGBE_RSCDBU, (IXGBE_RSCDBU_RSCACKDIS | IXGBE_READ_REG(hw, IXGBE_RSCDBU))); @@ -3122,6 +3365,7 @@ static void ixgbe_vlan_strip_disable(struct ixgbe_adapter *adapter) IXGBE_WRITE_REG(hw, IXGBE_VLNCTRL, vlnctrl); break; case ixgbe_mac_82599EB: + case ixgbe_mac_X540: for (i = 0; i < adapter->num_rx_queues; i++) { j = adapter->rx_ring[i]->reg_idx; vlnctrl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(j)); @@ -3151,6 +3395,7 @@ static void ixgbe_vlan_strip_enable(struct ixgbe_adapter *adapter) IXGBE_WRITE_REG(hw, IXGBE_VLNCTRL, vlnctrl); break; case ixgbe_mac_82599EB: + case ixgbe_mac_X540: for (i = 0; i < adapter->num_rx_queues; i++) { j = adapter->rx_ring[i]->reg_idx; vlnctrl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(j)); @@ -3348,8 +3593,6 @@ static void ixgbe_configure_dcb(struct ixgbe_adapter *adapter) { struct ixgbe_hw *hw = &adapter->hw; int max_frame = adapter->netdev->mtu + ETH_HLEN + ETH_FCS_LEN; - u32 txdctl; - int i, j; if (!(adapter->flags & IXGBE_FLAG_DCB_ENABLED)) { if (hw->mac.type == ixgbe_mac_82598EB) @@ -3365,25 +3608,18 @@ static void ixgbe_configure_dcb(struct ixgbe_adapter *adapter) max_frame = max(max_frame, IXGBE_FCOE_JUMBO_FRAME_SIZE); #endif - ixgbe_dcb_calculate_tc_credits(&adapter->dcb_cfg, max_frame, + ixgbe_dcb_calculate_tc_credits(hw, &adapter->dcb_cfg, max_frame, DCB_TX_CONFIG); - ixgbe_dcb_calculate_tc_credits(&adapter->dcb_cfg, max_frame, + ixgbe_dcb_calculate_tc_credits(hw, &adapter->dcb_cfg, max_frame, DCB_RX_CONFIG); - /* reconfigure the hardware */ - ixgbe_dcb_hw_config(&adapter->hw, &adapter->dcb_cfg); - - for (i = 0; i < adapter->num_tx_queues; i++) { - j = adapter->tx_ring[i]->reg_idx; - txdctl = IXGBE_READ_REG(hw, IXGBE_TXDCTL(j)); - /* PThresh workaround for Tx hang with DFP enabled. */ - txdctl |= 32; - IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(j), txdctl); - } /* Enable VLAN tag insert/strip */ adapter->netdev->features |= NETIF_F_HW_VLAN_RX; hw->mac.ops.set_vfta(&adapter->hw, 0, 0, true); + + /* reconfigure the hardware */ + ixgbe_dcb_hw_config(hw, &adapter->dcb_cfg); } #endif @@ -3515,8 +3751,9 @@ static void ixgbe_setup_gpie(struct ixgbe_adapter *adapter) case ixgbe_mac_82598EB: IXGBE_WRITE_REG(hw, IXGBE_EIAM, IXGBE_EICS_RTX_QUEUE); break; - default: case ixgbe_mac_82599EB: + case ixgbe_mac_X540: + default: IXGBE_WRITE_REG(hw, IXGBE_EIAM_EX(0), 0xFFFFFFFF); IXGBE_WRITE_REG(hw, IXGBE_EIAM_EX(1), 0xFFFFFFFF); break; @@ -3560,13 +3797,24 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter) else ixgbe_configure_msi_and_legacy(adapter); - /* enable the optics */ - if (hw->phy.multispeed_fiber) + /* enable the optics for both mult-speed fiber and 82599 SFP+ fiber */ + if (hw->mac.ops.enable_tx_laser && + ((hw->phy.multispeed_fiber) || + ((hw->phy.type == ixgbe_media_type_fiber) && + (hw->mac.type == ixgbe_mac_82599EB)))) hw->mac.ops.enable_tx_laser(hw); clear_bit(__IXGBE_DOWN, &adapter->state); ixgbe_napi_enable_all(adapter); + if (ixgbe_is_sfp(hw)) { + ixgbe_sfp_link_config(adapter); + } else { + err = ixgbe_non_sfp_link_config(hw); + if (err) + e_err(probe, "link_config FAILED %d\n", err); + } + /* clear any pending interrupts, may auto mask */ IXGBE_READ_REG(hw, IXGBE_EICR); ixgbe_irq_enable(adapter, true, true); @@ -3589,26 +3837,8 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter) * If we're not hot-pluggable SFP+, we just need to configure link * and bring it up. */ - if (hw->phy.type == ixgbe_phy_unknown) { - err = hw->phy.ops.identify(hw); - if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) { - /* - * Take the device down and schedule the sfp tasklet - * which will unregister_netdev and log it. - */ - ixgbe_down(adapter); - schedule_work(&adapter->sfp_config_module_task); - return err; - } - } - - if (ixgbe_is_sfp(hw)) { - ixgbe_sfp_link_config(adapter); - } else { - err = ixgbe_non_sfp_link_config(hw); - if (err) - e_err(probe, "link_config FAILED %d\n", err); - } + if (hw->phy.type == ixgbe_phy_unknown) + schedule_work(&adapter->sfp_config_module_task); /* enable transmits */ netif_tx_start_all_queues(adapter->netdev); @@ -3686,15 +3916,13 @@ void ixgbe_reset(struct ixgbe_adapter *adapter) /** * ixgbe_clean_rx_ring - Free Rx Buffers per Queue - * @adapter: board private structure * @rx_ring: ring to free buffers from **/ -static void ixgbe_clean_rx_ring(struct ixgbe_adapter *adapter, - struct ixgbe_ring *rx_ring) +static void ixgbe_clean_rx_ring(struct ixgbe_ring *rx_ring) { - struct pci_dev *pdev = adapter->pdev; + struct device *dev = rx_ring->dev; unsigned long size; - unsigned int i; + u16 i; /* ring already cleared, nothing to do */ if (!rx_ring->rx_buffer_info) @@ -3706,7 +3934,7 @@ static void ixgbe_clean_rx_ring(struct ixgbe_adapter *adapter, rx_buffer_info = &rx_ring->rx_buffer_info[i]; if (rx_buffer_info->dma) { - dma_unmap_single(&pdev->dev, rx_buffer_info->dma, + dma_unmap_single(rx_ring->dev, rx_buffer_info->dma, rx_ring->rx_buf_len, DMA_FROM_DEVICE); rx_buffer_info->dma = 0; @@ -3717,7 +3945,7 @@ static void ixgbe_clean_rx_ring(struct ixgbe_adapter *adapter, do { struct sk_buff *this = skb; if (IXGBE_RSC_CB(this)->delay_unmap) { - dma_unmap_single(&pdev->dev, + dma_unmap_single(dev, IXGBE_RSC_CB(this)->dma, rx_ring->rx_buf_len, DMA_FROM_DEVICE); @@ -3731,7 +3959,7 @@ static void ixgbe_clean_rx_ring(struct ixgbe_adapter *adapter, if (!rx_buffer_info->page) continue; if (rx_buffer_info->page_dma) { - dma_unmap_page(&pdev->dev, rx_buffer_info->page_dma, + dma_unmap_page(dev, rx_buffer_info->page_dma, PAGE_SIZE / 2, DMA_FROM_DEVICE); rx_buffer_info->page_dma = 0; } @@ -3748,24 +3976,17 @@ static void ixgbe_clean_rx_ring(struct ixgbe_adapter *adapter, rx_ring->next_to_clean = 0; rx_ring->next_to_use = 0; - - if (rx_ring->head) - writel(0, adapter->hw.hw_addr + rx_ring->head); - if (rx_ring->tail) - writel(0, adapter->hw.hw_addr + rx_ring->tail); } /** * ixgbe_clean_tx_ring - Free Tx Buffers - * @adapter: board private structure * @tx_ring: ring to be cleaned **/ -static void ixgbe_clean_tx_ring(struct ixgbe_adapter *adapter, - struct ixgbe_ring *tx_ring) +static void ixgbe_clean_tx_ring(struct ixgbe_ring *tx_ring) { struct ixgbe_tx_buffer *tx_buffer_info; unsigned long size; - unsigned int i; + u16 i; /* ring already cleared, nothing to do */ if (!tx_ring->tx_buffer_info) @@ -3774,7 +3995,7 @@ static void ixgbe_clean_tx_ring(struct ixgbe_adapter *adapter, /* Free all the Tx ring sk_buffs */ for (i = 0; i < tx_ring->count; i++) { tx_buffer_info = &tx_ring->tx_buffer_info[i]; - ixgbe_unmap_and_free_tx_resource(adapter, tx_buffer_info); + ixgbe_unmap_and_free_tx_resource(tx_ring, tx_buffer_info); } size = sizeof(struct ixgbe_tx_buffer) * tx_ring->count; @@ -3785,11 +4006,6 @@ static void ixgbe_clean_tx_ring(struct ixgbe_adapter *adapter, tx_ring->next_to_use = 0; tx_ring->next_to_clean = 0; - - if (tx_ring->head) - writel(0, adapter->hw.hw_addr + tx_ring->head); - if (tx_ring->tail) - writel(0, adapter->hw.hw_addr + tx_ring->tail); } /** @@ -3801,7 +4017,7 @@ static void ixgbe_clean_all_rx_rings(struct ixgbe_adapter *adapter) int i; for (i = 0; i < adapter->num_rx_queues; i++) - ixgbe_clean_rx_ring(adapter, adapter->rx_ring[i]); + ixgbe_clean_rx_ring(adapter->rx_ring[i]); } /** @@ -3813,7 +4029,7 @@ static void ixgbe_clean_all_tx_rings(struct ixgbe_adapter *adapter) int i; for (i = 0; i < adapter->num_tx_queues; i++) - ixgbe_clean_tx_ring(adapter, adapter->tx_ring[i]); + ixgbe_clean_tx_ring(adapter->tx_ring[i]); } void ixgbe_down(struct ixgbe_adapter *adapter) @@ -3822,7 +4038,7 @@ void ixgbe_down(struct ixgbe_adapter *adapter) struct ixgbe_hw *hw = &adapter->hw; u32 rxctrl; u32 txdctl; - int i, j; + int i; int num_q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS; /* signal that we are down to the interrupt handler */ @@ -3880,26 +4096,36 @@ void ixgbe_down(struct ixgbe_adapter *adapter) /* disable transmits in the hardware now that interrupts are off */ for (i = 0; i < adapter->num_tx_queues; i++) { - j = adapter->tx_ring[i]->reg_idx; - txdctl = IXGBE_READ_REG(hw, IXGBE_TXDCTL(j)); - IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(j), + u8 reg_idx = adapter->tx_ring[i]->reg_idx; + txdctl = IXGBE_READ_REG(hw, IXGBE_TXDCTL(reg_idx)); + IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(reg_idx), (txdctl & ~IXGBE_TXDCTL_ENABLE)); } /* Disable the Tx DMA engine on 82599 */ - if (hw->mac.type == ixgbe_mac_82599EB) + switch (hw->mac.type) { + case ixgbe_mac_82599EB: + case ixgbe_mac_X540: IXGBE_WRITE_REG(hw, IXGBE_DMATXCTL, (IXGBE_READ_REG(hw, IXGBE_DMATXCTL) & ~IXGBE_DMATXCTL_TE)); - - /* power down the optics */ - if (hw->phy.multispeed_fiber) - hw->mac.ops.disable_tx_laser(hw); + break; + default: + break; + } /* clear n-tuple filters that are cached */ ethtool_ntuple_flush(netdev); if (!pci_channel_offline(adapter->pdev)) ixgbe_reset(adapter); + + /* power down the optics for multispeed fiber and 82599 SFP+ fiber */ + if (hw->mac.ops.disable_tx_laser && + ((hw->phy.multispeed_fiber) || + ((hw->phy.type == ixgbe_media_type_fiber) && + (hw->mac.type == ixgbe_mac_82599EB)))) + hw->mac.ops.disable_tx_laser(hw); + ixgbe_clean_all_tx_rings(adapter); ixgbe_clean_all_rx_rings(adapter); @@ -3924,10 +4150,8 @@ static int ixgbe_poll(struct napi_struct *napi, int budget) int tx_clean_complete, work_done = 0; #ifdef CONFIG_IXGBE_DCA - if (adapter->flags & IXGBE_FLAG_DCA_ENABLED) { - ixgbe_update_tx_dca(adapter, adapter->tx_ring[0]); - ixgbe_update_rx_dca(adapter, adapter->rx_ring[0]); - } + if (adapter->flags & IXGBE_FLAG_DCA_ENABLED) + ixgbe_update_dca(q_vector); #endif tx_clean_complete = ixgbe_clean_tx_irq(q_vector, adapter->tx_ring[0]); @@ -3955,6 +4179,8 @@ static void ixgbe_tx_timeout(struct net_device *netdev) { struct ixgbe_adapter *adapter = netdev_priv(netdev); + adapter->tx_timeout_count++; + /* Do the reset outside of interrupt context */ schedule_work(&adapter->reset_task); } @@ -3969,8 +4195,6 @@ static void ixgbe_reset_task(struct work_struct *work) test_bit(__IXGBE_RESETTING, &adapter->state)) return; - adapter->tx_timeout_count++; - ixgbe_dump(adapter); netdev_err(adapter->netdev, "Reset adapter\n"); ixgbe_reinit_locked(adapter); @@ -4220,19 +4444,16 @@ static void ixgbe_acquire_msix_vectors(struct ixgbe_adapter *adapter, static inline bool ixgbe_cache_ring_rss(struct ixgbe_adapter *adapter) { int i; - bool ret = false; - if (adapter->flags & IXGBE_FLAG_RSS_ENABLED) { - for (i = 0; i < adapter->num_rx_queues; i++) - adapter->rx_ring[i]->reg_idx = i; - for (i = 0; i < adapter->num_tx_queues; i++) - adapter->tx_ring[i]->reg_idx = i; - ret = true; - } else { - ret = false; - } + if (!(adapter->flags & IXGBE_FLAG_RSS_ENABLED)) + return false; - return ret; + for (i = 0; i < adapter->num_rx_queues; i++) + adapter->rx_ring[i]->reg_idx = i; + for (i = 0; i < adapter->num_tx_queues; i++) + adapter->tx_ring[i]->reg_idx = i; + + return true; } #ifdef CONFIG_IXGBE_DCB @@ -4249,71 +4470,67 @@ static inline bool ixgbe_cache_ring_dcb(struct ixgbe_adapter *adapter) bool ret = false; int dcb_i = adapter->ring_feature[RING_F_DCB].indices; - if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) { - if (adapter->hw.mac.type == ixgbe_mac_82598EB) { - /* the number of queues is assumed to be symmetric */ - for (i = 0; i < dcb_i; i++) { - adapter->rx_ring[i]->reg_idx = i << 3; - adapter->tx_ring[i]->reg_idx = i << 2; - } - ret = true; - } else if (adapter->hw.mac.type == ixgbe_mac_82599EB) { - if (dcb_i == 8) { - /* - * Tx TC0 starts at: descriptor queue 0 - * Tx TC1 starts at: descriptor queue 32 - * Tx TC2 starts at: descriptor queue 64 - * Tx TC3 starts at: descriptor queue 80 - * Tx TC4 starts at: descriptor queue 96 - * Tx TC5 starts at: descriptor queue 104 - * Tx TC6 starts at: descriptor queue 112 - * Tx TC7 starts at: descriptor queue 120 - * - * Rx TC0-TC7 are offset by 16 queues each - */ - for (i = 0; i < 3; i++) { - adapter->tx_ring[i]->reg_idx = i << 5; - adapter->rx_ring[i]->reg_idx = i << 4; - } - for ( ; i < 5; i++) { - adapter->tx_ring[i]->reg_idx = - ((i + 2) << 4); - adapter->rx_ring[i]->reg_idx = i << 4; - } - for ( ; i < dcb_i; i++) { - adapter->tx_ring[i]->reg_idx = - ((i + 8) << 3); - adapter->rx_ring[i]->reg_idx = i << 4; - } + if (!(adapter->flags & IXGBE_FLAG_DCB_ENABLED)) + return false; - ret = true; - } else if (dcb_i == 4) { - /* - * Tx TC0 starts at: descriptor queue 0 - * Tx TC1 starts at: descriptor queue 64 - * Tx TC2 starts at: descriptor queue 96 - * Tx TC3 starts at: descriptor queue 112 - * - * Rx TC0-TC3 are offset by 32 queues each - */ - adapter->tx_ring[0]->reg_idx = 0; - adapter->tx_ring[1]->reg_idx = 64; - adapter->tx_ring[2]->reg_idx = 96; - adapter->tx_ring[3]->reg_idx = 112; - for (i = 0 ; i < dcb_i; i++) - adapter->rx_ring[i]->reg_idx = i << 5; - - ret = true; - } else { - ret = false; + /* the number of queues is assumed to be symmetric */ + switch (adapter->hw.mac.type) { + case ixgbe_mac_82598EB: + for (i = 0; i < dcb_i; i++) { + adapter->rx_ring[i]->reg_idx = i << 3; + adapter->tx_ring[i]->reg_idx = i << 2; + } + ret = true; + break; + case ixgbe_mac_82599EB: + case ixgbe_mac_X540: + if (dcb_i == 8) { + /* + * Tx TC0 starts at: descriptor queue 0 + * Tx TC1 starts at: descriptor queue 32 + * Tx TC2 starts at: descriptor queue 64 + * Tx TC3 starts at: descriptor queue 80 + * Tx TC4 starts at: descriptor queue 96 + * Tx TC5 starts at: descriptor queue 104 + * Tx TC6 starts at: descriptor queue 112 + * Tx TC7 starts at: descriptor queue 120 + * + * Rx TC0-TC7 are offset by 16 queues each + */ + for (i = 0; i < 3; i++) { + adapter->tx_ring[i]->reg_idx = i << 5; + adapter->rx_ring[i]->reg_idx = i << 4; } - } else { - ret = false; + for ( ; i < 5; i++) { + adapter->tx_ring[i]->reg_idx = ((i + 2) << 4); + adapter->rx_ring[i]->reg_idx = i << 4; + } + for ( ; i < dcb_i; i++) { + adapter->tx_ring[i]->reg_idx = ((i + 8) << 3); + adapter->rx_ring[i]->reg_idx = i << 4; + } + ret = true; + } else if (dcb_i == 4) { + /* + * Tx TC0 starts at: descriptor queue 0 + * Tx TC1 starts at: descriptor queue 64 + * Tx TC2 starts at: descriptor queue 96 + * Tx TC3 starts at: descriptor queue 112 + * + * Rx TC0-TC3 are offset by 32 queues each + */ + adapter->tx_ring[0]->reg_idx = 0; + adapter->tx_ring[1]->reg_idx = 64; + adapter->tx_ring[2]->reg_idx = 96; + adapter->tx_ring[3]->reg_idx = 112; + for (i = 0 ; i < dcb_i; i++) + adapter->rx_ring[i]->reg_idx = i << 5; + ret = true; } - } else { - ret = false; + break; + default: + break; } - return ret; } #endif @@ -4353,55 +4570,55 @@ static inline bool ixgbe_cache_ring_fdir(struct ixgbe_adapter *adapter) */ static inline bool ixgbe_cache_ring_fcoe(struct ixgbe_adapter *adapter) { - int i, fcoe_rx_i = 0, fcoe_tx_i = 0; - bool ret = false; struct ixgbe_ring_feature *f = &adapter->ring_feature[RING_F_FCOE]; + int i; + u8 fcoe_rx_i = 0, fcoe_tx_i = 0; + + if (!(adapter->flags & IXGBE_FLAG_FCOE_ENABLED)) + return false; - if (adapter->flags & IXGBE_FLAG_FCOE_ENABLED) { #ifdef CONFIG_IXGBE_DCB - if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) { - struct ixgbe_fcoe *fcoe = &adapter->fcoe; + if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) { + struct ixgbe_fcoe *fcoe = &adapter->fcoe; - ixgbe_cache_ring_dcb(adapter); - /* find out queues in TC for FCoE */ - fcoe_rx_i = adapter->rx_ring[fcoe->tc]->reg_idx + 1; - fcoe_tx_i = adapter->tx_ring[fcoe->tc]->reg_idx + 1; - /* - * In 82599, the number of Tx queues for each traffic - * class for both 8-TC and 4-TC modes are: - * TCs : TC0 TC1 TC2 TC3 TC4 TC5 TC6 TC7 - * 8 TCs: 32 32 16 16 8 8 8 8 - * 4 TCs: 64 64 32 32 - * We have max 8 queues for FCoE, where 8 the is - * FCoE redirection table size. If TC for FCoE is - * less than or equal to TC3, we have enough queues - * to add max of 8 queues for FCoE, so we start FCoE - * tx descriptor from the next one, i.e., reg_idx + 1. - * If TC for FCoE is above TC3, implying 8 TC mode, - * and we need 8 for FCoE, we have to take all queues - * in that traffic class for FCoE. - */ - if ((f->indices == IXGBE_FCRETA_SIZE) && (fcoe->tc > 3)) - fcoe_tx_i--; - } + ixgbe_cache_ring_dcb(adapter); + /* find out queues in TC for FCoE */ + fcoe_rx_i = adapter->rx_ring[fcoe->tc]->reg_idx + 1; + fcoe_tx_i = adapter->tx_ring[fcoe->tc]->reg_idx + 1; + /* + * In 82599, the number of Tx queues for each traffic + * class for both 8-TC and 4-TC modes are: + * TCs : TC0 TC1 TC2 TC3 TC4 TC5 TC6 TC7 + * 8 TCs: 32 32 16 16 8 8 8 8 + * 4 TCs: 64 64 32 32 + * We have max 8 queues for FCoE, where 8 the is + * FCoE redirection table size. If TC for FCoE is + * less than or equal to TC3, we have enough queues + * to add max of 8 queues for FCoE, so we start FCoE + * Tx queue from the next one, i.e., reg_idx + 1. + * If TC for FCoE is above TC3, implying 8 TC mode, + * and we need 8 for FCoE, we have to take all queues + * in that traffic class for FCoE. + */ + if ((f->indices == IXGBE_FCRETA_SIZE) && (fcoe->tc > 3)) + fcoe_tx_i--; + } #endif /* CONFIG_IXGBE_DCB */ - if (adapter->flags & IXGBE_FLAG_RSS_ENABLED) { - if ((adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE) || - (adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE)) - ixgbe_cache_ring_fdir(adapter); - else - ixgbe_cache_ring_rss(adapter); + if (adapter->flags & IXGBE_FLAG_RSS_ENABLED) { + if ((adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE) || + (adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE)) + ixgbe_cache_ring_fdir(adapter); + else + ixgbe_cache_ring_rss(adapter); - fcoe_rx_i = f->mask; - fcoe_tx_i = f->mask; - } - for (i = 0; i < f->indices; i++, fcoe_rx_i++, fcoe_tx_i++) { - adapter->rx_ring[f->mask + i]->reg_idx = fcoe_rx_i; - adapter->tx_ring[f->mask + i]->reg_idx = fcoe_tx_i; - } - ret = true; + fcoe_rx_i = f->mask; + fcoe_tx_i = f->mask; } - return ret; + for (i = 0; i < f->indices; i++, fcoe_rx_i++, fcoe_tx_i++) { + adapter->rx_ring[f->mask + i]->reg_idx = fcoe_rx_i; + adapter->tx_ring[f->mask + i]->reg_idx = fcoe_tx_i; + } + return true; } #endif /* IXGBE_FCOE */ @@ -4470,65 +4687,55 @@ static void ixgbe_cache_ring_register(struct ixgbe_adapter *adapter) **/ static int ixgbe_alloc_queues(struct ixgbe_adapter *adapter) { - int i; - int orig_node = adapter->node; + int rx = 0, tx = 0, nid = adapter->node; - for (i = 0; i < adapter->num_tx_queues; i++) { - struct ixgbe_ring *ring = adapter->tx_ring[i]; - if (orig_node == -1) { - int cur_node = next_online_node(adapter->node); - if (cur_node == MAX_NUMNODES) - cur_node = first_online_node; - adapter->node = cur_node; - } - ring = kzalloc_node(sizeof(struct ixgbe_ring), GFP_KERNEL, - adapter->node); + if (nid < 0 || !node_online(nid)) + nid = first_online_node; + + for (; tx < adapter->num_tx_queues; tx++) { + struct ixgbe_ring *ring; + + ring = kzalloc_node(sizeof(*ring), GFP_KERNEL, nid); if (!ring) - ring = kzalloc(sizeof(struct ixgbe_ring), GFP_KERNEL); + ring = kzalloc(sizeof(*ring), GFP_KERNEL); if (!ring) - goto err_tx_ring_allocation; + goto err_allocation; ring->count = adapter->tx_ring_count; - ring->queue_index = i; - ring->numa_node = adapter->node; + ring->queue_index = tx; + ring->numa_node = nid; + ring->dev = &adapter->pdev->dev; + ring->netdev = adapter->netdev; - adapter->tx_ring[i] = ring; + adapter->tx_ring[tx] = ring; } - /* Restore the adapter's original node */ - adapter->node = orig_node; + for (; rx < adapter->num_rx_queues; rx++) { + struct ixgbe_ring *ring; - for (i = 0; i < adapter->num_rx_queues; i++) { - struct ixgbe_ring *ring = adapter->rx_ring[i]; - if (orig_node == -1) { - int cur_node = next_online_node(adapter->node); - if (cur_node == MAX_NUMNODES) - cur_node = first_online_node; - adapter->node = cur_node; - } - ring = kzalloc_node(sizeof(struct ixgbe_ring), GFP_KERNEL, - adapter->node); + ring = kzalloc_node(sizeof(*ring), GFP_KERNEL, nid); if (!ring) - ring = kzalloc(sizeof(struct ixgbe_ring), GFP_KERNEL); + ring = kzalloc(sizeof(*ring), GFP_KERNEL); if (!ring) - goto err_rx_ring_allocation; + goto err_allocation; ring->count = adapter->rx_ring_count; - ring->queue_index = i; - ring->numa_node = adapter->node; + ring->queue_index = rx; + ring->numa_node = nid; + ring->dev = &adapter->pdev->dev; + ring->netdev = adapter->netdev; - adapter->rx_ring[i] = ring; + adapter->rx_ring[rx] = ring; } - /* Restore the adapter's original node */ - adapter->node = orig_node; - ixgbe_cache_ring_register(adapter); return 0; -err_rx_ring_allocation: - for (i = 0; i < adapter->num_tx_queues; i++) - kfree(adapter->tx_ring[i]); -err_tx_ring_allocation: +err_allocation: + while (tx) + kfree(adapter->tx_ring[--tx]); + + while (rx) + kfree(adapter->rx_ring[--rx]); return -ENOMEM; } @@ -4750,6 +4957,11 @@ err_set_interrupt: return err; } +static void ring_free_rcu(struct rcu_head *head) +{ + kfree(container_of(head, struct ixgbe_ring, rcu)); +} + /** * ixgbe_clear_interrupt_scheme - Clear the current interrupt scheme settings * @adapter: board private structure to clear interrupt scheme on @@ -4766,7 +4978,12 @@ void ixgbe_clear_interrupt_scheme(struct ixgbe_adapter *adapter) adapter->tx_ring[i] = NULL; } for (i = 0; i < adapter->num_rx_queues; i++) { - kfree(adapter->rx_ring[i]); + struct ixgbe_ring *ring = adapter->rx_ring[i]; + + /* ixgbe_get_stats64() might access this ring, we must wait + * a grace period before freeing it. + */ + call_rcu(&ring->rcu, ring_free_rcu); adapter->rx_ring[i] = NULL; } @@ -4843,6 +5060,7 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter) int j; struct tc_configuration *tc; #endif + int max_frame = dev->mtu + ETH_HLEN + ETH_FCS_LEN; /* PCI config space info */ @@ -4857,11 +5075,14 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter) 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; - if (hw->mac.type == ixgbe_mac_82598EB) { + switch (hw->mac.type) { + case ixgbe_mac_82598EB: if (hw->device_id == IXGBE_DEV_ID_82598AT) adapter->flags |= IXGBE_FLAG_FAN_FAIL_CAPABLE; adapter->max_msix_q_vectors = MAX_MSIX_Q_VECTORS_82598; - } else if (hw->mac.type == ixgbe_mac_82599EB) { + break; + case ixgbe_mac_82599EB: + case ixgbe_mac_X540: adapter->max_msix_q_vectors = MAX_MSIX_Q_VECTORS_82599; adapter->flags2 |= IXGBE_FLAG2_RSC_CAPABLE; adapter->flags2 |= IXGBE_FLAG2_RSC_ENABLED; @@ -4890,6 +5111,9 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter) adapter->fcoe.up = IXGBE_FCOE_DEFTC; #endif #endif /* IXGBE_FCOE */ + break; + default: + break; } #ifdef CONFIG_IXGBE_DCB @@ -4919,8 +5143,8 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter) #ifdef CONFIG_DCB adapter->last_lfc_mode = hw->fc.current_mode; #endif - hw->fc.high_water = IXGBE_DEFAULT_FCRTH; - hw->fc.low_water = IXGBE_DEFAULT_FCRTL; + hw->fc.high_water = FC_HIGH_WATER(max_frame); + hw->fc.low_water = FC_LOW_WATER(max_frame); hw->fc.pause_time = IXGBE_DEFAULT_FCPAUSE; hw->fc.send_xon = true; hw->fc.disable_fc_autoneg = false; @@ -4958,30 +5182,27 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter) /** * ixgbe_setup_tx_resources - allocate Tx resources (Descriptors) - * @adapter: board private structure * @tx_ring: tx descriptor ring (for a specific queue) to setup * * Return 0 on success, negative on failure **/ -int ixgbe_setup_tx_resources(struct ixgbe_adapter *adapter, - struct ixgbe_ring *tx_ring) +int ixgbe_setup_tx_resources(struct ixgbe_ring *tx_ring) { - struct pci_dev *pdev = adapter->pdev; + struct device *dev = tx_ring->dev; int size; size = sizeof(struct ixgbe_tx_buffer) * tx_ring->count; - tx_ring->tx_buffer_info = vmalloc_node(size, tx_ring->numa_node); + tx_ring->tx_buffer_info = vzalloc_node(size, tx_ring->numa_node); if (!tx_ring->tx_buffer_info) - tx_ring->tx_buffer_info = vmalloc(size); + tx_ring->tx_buffer_info = vzalloc(size); if (!tx_ring->tx_buffer_info) goto err; - memset(tx_ring->tx_buffer_info, 0, size); /* round up to nearest 4K */ tx_ring->size = tx_ring->count * sizeof(union ixgbe_adv_tx_desc); tx_ring->size = ALIGN(tx_ring->size, 4096); - tx_ring->desc = dma_alloc_coherent(&pdev->dev, tx_ring->size, + tx_ring->desc = dma_alloc_coherent(dev, tx_ring->size, &tx_ring->dma, GFP_KERNEL); if (!tx_ring->desc) goto err; @@ -4994,7 +5215,7 @@ int ixgbe_setup_tx_resources(struct ixgbe_adapter *adapter, err: vfree(tx_ring->tx_buffer_info); tx_ring->tx_buffer_info = NULL; - e_err(probe, "Unable to allocate memory for the Tx descriptor ring\n"); + dev_err(dev, "Unable to allocate memory for the Tx descriptor ring\n"); return -ENOMEM; } @@ -5013,7 +5234,7 @@ static int ixgbe_setup_all_tx_resources(struct ixgbe_adapter *adapter) int i, err = 0; for (i = 0; i < adapter->num_tx_queues; i++) { - err = ixgbe_setup_tx_resources(adapter, adapter->tx_ring[i]); + err = ixgbe_setup_tx_resources(adapter->tx_ring[i]); if (!err) continue; e_err(probe, "Allocation for Tx Queue %u failed\n", i); @@ -5025,48 +5246,40 @@ static int ixgbe_setup_all_tx_resources(struct ixgbe_adapter *adapter) /** * ixgbe_setup_rx_resources - allocate Rx resources (Descriptors) - * @adapter: board private structure * @rx_ring: rx descriptor ring (for a specific queue) to setup * * Returns 0 on success, negative on failure **/ -int ixgbe_setup_rx_resources(struct ixgbe_adapter *adapter, - struct ixgbe_ring *rx_ring) +int ixgbe_setup_rx_resources(struct ixgbe_ring *rx_ring) { - struct pci_dev *pdev = adapter->pdev; + struct device *dev = rx_ring->dev; int size; size = sizeof(struct ixgbe_rx_buffer) * rx_ring->count; - rx_ring->rx_buffer_info = vmalloc_node(size, adapter->node); + rx_ring->rx_buffer_info = vzalloc_node(size, rx_ring->numa_node); if (!rx_ring->rx_buffer_info) - rx_ring->rx_buffer_info = vmalloc(size); - if (!rx_ring->rx_buffer_info) { - e_err(probe, "vmalloc allocation failed for the Rx " - "descriptor ring\n"); - goto alloc_failed; - } - memset(rx_ring->rx_buffer_info, 0, size); + rx_ring->rx_buffer_info = vzalloc(size); + if (!rx_ring->rx_buffer_info) + goto err; /* Round up to nearest 4K */ rx_ring->size = rx_ring->count * sizeof(union ixgbe_adv_rx_desc); rx_ring->size = ALIGN(rx_ring->size, 4096); - rx_ring->desc = dma_alloc_coherent(&pdev->dev, rx_ring->size, + rx_ring->desc = dma_alloc_coherent(dev, rx_ring->size, &rx_ring->dma, GFP_KERNEL); - if (!rx_ring->desc) { - e_err(probe, "Memory allocation failed for the Rx " - "descriptor ring\n"); - vfree(rx_ring->rx_buffer_info); - goto alloc_failed; - } + if (!rx_ring->desc) + goto err; rx_ring->next_to_clean = 0; rx_ring->next_to_use = 0; return 0; - -alloc_failed: +err: + vfree(rx_ring->rx_buffer_info); + rx_ring->rx_buffer_info = NULL; + dev_err(dev, "Unable to allocate memory for the Rx descriptor ring\n"); return -ENOMEM; } @@ -5080,13 +5293,12 @@ alloc_failed: * * Return 0 on success, negative on failure **/ - static int ixgbe_setup_all_rx_resources(struct ixgbe_adapter *adapter) { int i, err = 0; for (i = 0; i < adapter->num_rx_queues; i++) { - err = ixgbe_setup_rx_resources(adapter, adapter->rx_ring[i]); + err = ixgbe_setup_rx_resources(adapter->rx_ring[i]); if (!err) continue; e_err(probe, "Allocation for Rx Queue %u failed\n", i); @@ -5098,23 +5310,23 @@ static int ixgbe_setup_all_rx_resources(struct ixgbe_adapter *adapter) /** * ixgbe_free_tx_resources - Free Tx Resources per Queue - * @adapter: board private structure * @tx_ring: Tx descriptor ring for a specific queue * * Free all transmit software resources **/ -void ixgbe_free_tx_resources(struct ixgbe_adapter *adapter, - struct ixgbe_ring *tx_ring) +void ixgbe_free_tx_resources(struct ixgbe_ring *tx_ring) { - struct pci_dev *pdev = adapter->pdev; - - ixgbe_clean_tx_ring(adapter, tx_ring); + ixgbe_clean_tx_ring(tx_ring); vfree(tx_ring->tx_buffer_info); tx_ring->tx_buffer_info = NULL; - dma_free_coherent(&pdev->dev, tx_ring->size, tx_ring->desc, - tx_ring->dma); + /* if not set, then don't free */ + if (!tx_ring->desc) + return; + + dma_free_coherent(tx_ring->dev, tx_ring->size, + tx_ring->desc, tx_ring->dma); tx_ring->desc = NULL; } @@ -5131,28 +5343,28 @@ static void ixgbe_free_all_tx_resources(struct ixgbe_adapter *adapter) for (i = 0; i < adapter->num_tx_queues; i++) if (adapter->tx_ring[i]->desc) - ixgbe_free_tx_resources(adapter, adapter->tx_ring[i]); + ixgbe_free_tx_resources(adapter->tx_ring[i]); } /** * ixgbe_free_rx_resources - Free Rx Resources - * @adapter: board private structure * @rx_ring: ring to clean the resources from * * Free all receive software resources **/ -void ixgbe_free_rx_resources(struct ixgbe_adapter *adapter, - struct ixgbe_ring *rx_ring) +void ixgbe_free_rx_resources(struct ixgbe_ring *rx_ring) { - struct pci_dev *pdev = adapter->pdev; - - ixgbe_clean_rx_ring(adapter, rx_ring); + ixgbe_clean_rx_ring(rx_ring); vfree(rx_ring->rx_buffer_info); rx_ring->rx_buffer_info = NULL; - dma_free_coherent(&pdev->dev, rx_ring->size, rx_ring->desc, - rx_ring->dma); + /* if not set, then don't free */ + if (!rx_ring->desc) + return; + + dma_free_coherent(rx_ring->dev, rx_ring->size, + rx_ring->desc, rx_ring->dma); rx_ring->desc = NULL; } @@ -5169,7 +5381,7 @@ static void ixgbe_free_all_rx_resources(struct ixgbe_adapter *adapter) for (i = 0; i < adapter->num_rx_queues; i++) if (adapter->rx_ring[i]->desc) - ixgbe_free_rx_resources(adapter, adapter->rx_ring[i]); + ixgbe_free_rx_resources(adapter->rx_ring[i]); } /** @@ -5182,6 +5394,7 @@ static void ixgbe_free_all_rx_resources(struct ixgbe_adapter *adapter) static int ixgbe_change_mtu(struct net_device *netdev, int new_mtu) { struct ixgbe_adapter *adapter = netdev_priv(netdev); + struct ixgbe_hw *hw = &adapter->hw; int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN; /* MTU < 68 is an error and causes problems on some kernels */ @@ -5192,6 +5405,9 @@ static int ixgbe_change_mtu(struct net_device *netdev, int new_mtu) /* must set new MTU before calling down or up */ netdev->mtu = new_mtu; + hw->fc.high_water = FC_HIGH_WATER(max_frame); + hw->fc.low_water = FC_LOW_WATER(max_frame); + if (netif_running(netdev)) ixgbe_reinit_locked(adapter); @@ -5287,8 +5503,8 @@ static int ixgbe_close(struct net_device *netdev) #ifdef CONFIG_PM static int ixgbe_resume(struct pci_dev *pdev) { - struct net_device *netdev = pci_get_drvdata(pdev); - struct ixgbe_adapter *adapter = netdev_priv(netdev); + struct ixgbe_adapter *adapter = pci_get_drvdata(pdev); + struct net_device *netdev = adapter->netdev; u32 err; pci_set_power_state(pdev, PCI_D0); @@ -5319,7 +5535,7 @@ static int ixgbe_resume(struct pci_dev *pdev) IXGBE_WRITE_REG(&adapter->hw, IXGBE_WUS, ~0); if (netif_running(netdev)) { - err = ixgbe_open(adapter->netdev); + err = ixgbe_open(netdev); if (err) return err; } @@ -5332,8 +5548,8 @@ static int ixgbe_resume(struct pci_dev *pdev) static int __ixgbe_shutdown(struct pci_dev *pdev, bool *enable_wake) { - struct net_device *netdev = pci_get_drvdata(pdev); - struct ixgbe_adapter *adapter = netdev_priv(netdev); + struct ixgbe_adapter *adapter = pci_get_drvdata(pdev); + struct net_device *netdev = adapter->netdev; struct ixgbe_hw *hw = &adapter->hw; u32 ctrl, fctrl; u32 wufc = adapter->wol; @@ -5350,6 +5566,8 @@ static int __ixgbe_shutdown(struct pci_dev *pdev, bool *enable_wake) ixgbe_free_all_rx_resources(adapter); } + ixgbe_clear_interrupt_scheme(adapter); + #ifdef CONFIG_PM retval = pci_save_state(pdev); if (retval) @@ -5376,15 +5594,20 @@ static int __ixgbe_shutdown(struct pci_dev *pdev, bool *enable_wake) IXGBE_WRITE_REG(hw, IXGBE_WUFC, 0); } - if (wufc && hw->mac.type == ixgbe_mac_82599EB) - pci_wake_from_d3(pdev, true); - else + switch (hw->mac.type) { + case ixgbe_mac_82598EB: pci_wake_from_d3(pdev, false); + break; + case ixgbe_mac_82599EB: + case ixgbe_mac_X540: + pci_wake_from_d3(pdev, !!wufc); + break; + default: + break; + } *enable_wake = !!wufc; - ixgbe_clear_interrupt_scheme(adapter); - ixgbe_release_hw_control(adapter); pci_disable_device(pdev); @@ -5433,10 +5656,12 @@ void ixgbe_update_stats(struct ixgbe_adapter *adapter) { struct net_device *netdev = adapter->netdev; struct ixgbe_hw *hw = &adapter->hw; + struct ixgbe_hw_stats *hwstats = &adapter->stats; u64 total_mpc = 0; u32 i, missed_rx = 0, mpc, bprc, lxon, lxoff, xon_off_tot; - u64 non_eop_descs = 0, restart_queue = 0; - struct ixgbe_hw_stats *hwstats = &adapter->stats; + u64 non_eop_descs = 0, restart_queue = 0, tx_busy = 0; + u64 alloc_rx_page_failed = 0, alloc_rx_buff_failed = 0; + u64 bytes = 0, packets = 0; if (test_bit(__IXGBE_DOWN, &adapter->state) || test_bit(__IXGBE_RESETTING, &adapter->state)) @@ -5449,21 +5674,41 @@ void ixgbe_update_stats(struct ixgbe_adapter *adapter) adapter->hw_rx_no_dma_resources += IXGBE_READ_REG(hw, IXGBE_QPRDC(i)); for (i = 0; i < adapter->num_rx_queues; i++) { - rsc_count += adapter->rx_ring[i]->rsc_count; - rsc_flush += adapter->rx_ring[i]->rsc_flush; + rsc_count += adapter->rx_ring[i]->rx_stats.rsc_count; + rsc_flush += adapter->rx_ring[i]->rx_stats.rsc_flush; } adapter->rsc_total_count = rsc_count; adapter->rsc_total_flush = rsc_flush; } + for (i = 0; i < adapter->num_rx_queues; i++) { + struct ixgbe_ring *rx_ring = adapter->rx_ring[i]; + non_eop_descs += rx_ring->rx_stats.non_eop_descs; + alloc_rx_page_failed += rx_ring->rx_stats.alloc_rx_page_failed; + alloc_rx_buff_failed += rx_ring->rx_stats.alloc_rx_buff_failed; + bytes += rx_ring->stats.bytes; + packets += rx_ring->stats.packets; + } + adapter->non_eop_descs = non_eop_descs; + adapter->alloc_rx_page_failed = alloc_rx_page_failed; + adapter->alloc_rx_buff_failed = alloc_rx_buff_failed; + netdev->stats.rx_bytes = bytes; + netdev->stats.rx_packets = packets; + + bytes = 0; + packets = 0; /* gather some stats to the adapter struct that are per queue */ - for (i = 0; i < adapter->num_tx_queues; i++) - restart_queue += adapter->tx_ring[i]->restart_queue; + for (i = 0; i < adapter->num_tx_queues; i++) { + struct ixgbe_ring *tx_ring = adapter->tx_ring[i]; + restart_queue += tx_ring->tx_stats.restart_queue; + tx_busy += tx_ring->tx_stats.tx_busy; + bytes += tx_ring->stats.bytes; + packets += tx_ring->stats.packets; + } adapter->restart_queue = restart_queue; - - for (i = 0; i < adapter->num_rx_queues; i++) - non_eop_descs += adapter->rx_ring[i]->non_eop_descs; - adapter->non_eop_descs = non_eop_descs; + adapter->tx_busy = tx_busy; + netdev->stats.tx_bytes = bytes; + netdev->stats.tx_packets = packets; hwstats->crcerrs += IXGBE_READ_REG(hw, IXGBE_CRCERRS); for (i = 0; i < 8; i++) { @@ -5478,17 +5723,18 @@ void ixgbe_update_stats(struct ixgbe_adapter *adapter) hwstats->qbtc[i] += IXGBE_READ_REG(hw, IXGBE_QBTC(i)); hwstats->qprc[i] += IXGBE_READ_REG(hw, IXGBE_QPRC(i)); hwstats->qbrc[i] += IXGBE_READ_REG(hw, IXGBE_QBRC(i)); - if (hw->mac.type == ixgbe_mac_82599EB) { - hwstats->pxonrxc[i] += - IXGBE_READ_REG(hw, IXGBE_PXONRXCNT(i)); - hwstats->pxoffrxc[i] += - IXGBE_READ_REG(hw, IXGBE_PXOFFRXCNT(i)); - hwstats->qprdc[i] += IXGBE_READ_REG(hw, IXGBE_QPRDC(i)); - } else { + switch (hw->mac.type) { + case ixgbe_mac_82598EB: hwstats->pxonrxc[i] += IXGBE_READ_REG(hw, IXGBE_PXONRXC(i)); - hwstats->pxoffrxc[i] += - IXGBE_READ_REG(hw, IXGBE_PXOFFRXC(i)); + break; + case ixgbe_mac_82599EB: + case ixgbe_mac_X540: + hwstats->pxonrxc[i] += + IXGBE_READ_REG(hw, IXGBE_PXONRXCNT(i)); + break; + default: + break; } hwstats->pxontxc[i] += IXGBE_READ_REG(hw, IXGBE_PXONTXC(i)); hwstats->pxofftxc[i] += IXGBE_READ_REG(hw, IXGBE_PXOFFTXC(i)); @@ -5497,21 +5743,25 @@ void ixgbe_update_stats(struct ixgbe_adapter *adapter) /* work around hardware counting issue */ hwstats->gprc -= missed_rx; + ixgbe_update_xoff_received(adapter); + /* 82598 hardware only has a 32 bit counter in the high register */ - if (hw->mac.type == ixgbe_mac_82599EB) { - u64 tmp; + switch (hw->mac.type) { + case ixgbe_mac_82598EB: + hwstats->lxonrxc += IXGBE_READ_REG(hw, IXGBE_LXONRXC); + hwstats->gorc += IXGBE_READ_REG(hw, IXGBE_GORCH); + hwstats->gotc += IXGBE_READ_REG(hw, IXGBE_GOTCH); + hwstats->tor += IXGBE_READ_REG(hw, IXGBE_TORH); + break; + case ixgbe_mac_82599EB: + case ixgbe_mac_X540: hwstats->gorc += IXGBE_READ_REG(hw, IXGBE_GORCL); - tmp = IXGBE_READ_REG(hw, IXGBE_GORCH) & 0xF; - /* 4 high bits of GORC */ - hwstats->gorc += (tmp << 32); + IXGBE_READ_REG(hw, IXGBE_GORCH); /* to clear */ hwstats->gotc += IXGBE_READ_REG(hw, IXGBE_GOTCL); - tmp = IXGBE_READ_REG(hw, IXGBE_GOTCH) & 0xF; - /* 4 high bits of GOTC */ - hwstats->gotc += (tmp << 32); + IXGBE_READ_REG(hw, IXGBE_GOTCH); /* to clear */ hwstats->tor += IXGBE_READ_REG(hw, IXGBE_TORL); - IXGBE_READ_REG(hw, IXGBE_TORH); /* to clear */ + IXGBE_READ_REG(hw, IXGBE_TORH); /* to clear */ hwstats->lxonrxc += IXGBE_READ_REG(hw, IXGBE_LXONRXCNT); - hwstats->lxoffrxc += IXGBE_READ_REG(hw, IXGBE_LXOFFRXCNT); hwstats->fdirmatch += IXGBE_READ_REG(hw, IXGBE_FDIRMATCH); hwstats->fdirmiss += IXGBE_READ_REG(hw, IXGBE_FDIRMISS); #ifdef IXGBE_FCOE @@ -5522,12 +5772,9 @@ void ixgbe_update_stats(struct ixgbe_adapter *adapter) hwstats->fcoedwrc += IXGBE_READ_REG(hw, IXGBE_FCOEDWRC); hwstats->fcoedwtc += IXGBE_READ_REG(hw, IXGBE_FCOEDWTC); #endif /* IXGBE_FCOE */ - } else { - hwstats->lxonrxc += IXGBE_READ_REG(hw, IXGBE_LXONRXC); - hwstats->lxoffrxc += IXGBE_READ_REG(hw, IXGBE_LXOFFRXC); - hwstats->gorc += IXGBE_READ_REG(hw, IXGBE_GORCH); - hwstats->gotc += IXGBE_READ_REG(hw, IXGBE_GOTCH); - hwstats->tor += IXGBE_READ_REG(hw, IXGBE_TORH); + break; + default: + break; } bprc = IXGBE_READ_REG(hw, IXGBE_BPRC); hwstats->bprc += bprc; @@ -5700,8 +5947,8 @@ static void ixgbe_fdir_reinit_task(struct work_struct *work) if (ixgbe_reinit_fdir_tables_82599(hw) == 0) { for (i = 0; i < adapter->num_tx_queues; i++) - set_bit(__IXGBE_FDIR_INIT_DONE, - &(adapter->tx_ring[i]->reinit_state)); + set_bit(__IXGBE_TX_FDIR_INIT_DONE, + &(adapter->tx_ring[i]->state)); } else { e_err(probe, "failed to finish FDIR re-initialization, " "ignored adding FDIR ATR filters\n"); @@ -5763,17 +6010,27 @@ static void ixgbe_watchdog_task(struct work_struct *work) if (!netif_carrier_ok(netdev)) { bool flow_rx, flow_tx; - if (hw->mac.type == ixgbe_mac_82599EB) { - u32 mflcn = IXGBE_READ_REG(hw, IXGBE_MFLCN); - u32 fccfg = IXGBE_READ_REG(hw, IXGBE_FCCFG); - flow_rx = !!(mflcn & IXGBE_MFLCN_RFCE); - flow_tx = !!(fccfg & IXGBE_FCCFG_TFCE_802_3X); - } else { + switch (hw->mac.type) { + case ixgbe_mac_82598EB: { u32 frctl = IXGBE_READ_REG(hw, IXGBE_FCTRL); u32 rmcs = IXGBE_READ_REG(hw, IXGBE_RMCS); flow_rx = !!(frctl & IXGBE_FCTRL_RFCE); flow_tx = !!(rmcs & IXGBE_RMCS_TFCE_802_3X); } + break; + case ixgbe_mac_82599EB: + case ixgbe_mac_X540: { + u32 mflcn = IXGBE_READ_REG(hw, IXGBE_MFLCN); + u32 fccfg = IXGBE_READ_REG(hw, IXGBE_FCCFG); + flow_rx = !!(mflcn & IXGBE_MFLCN_RFCE); + flow_tx = !!(fccfg & IXGBE_FCCFG_TFCE_802_3X); + } + break; + default: + flow_tx = false; + flow_rx = false; + break; + } e_info(drv, "NIC Link is Up %s, Flow Control: %s\n", (link_speed == IXGBE_LINK_SPEED_10GB_FULL ? @@ -5787,7 +6044,10 @@ static void ixgbe_watchdog_task(struct work_struct *work) netif_carrier_on(netdev); } else { /* Force detection of hung controller */ - adapter->detect_tx_hung = true; + for (i = 0; i < adapter->num_tx_queues; i++) { + tx_ring = adapter->tx_ring[i]; + set_check_for_tx_hang(tx_ring); + } } } else { adapter->link_up = false; @@ -5823,7 +6083,7 @@ static void ixgbe_watchdog_task(struct work_struct *work) static int ixgbe_tso(struct ixgbe_adapter *adapter, struct ixgbe_ring *tx_ring, struct sk_buff *skb, - u32 tx_flags, u8 *hdr_len) + u32 tx_flags, u8 *hdr_len, __be16 protocol) { struct ixgbe_adv_tx_context_desc *context_desc; unsigned int i; @@ -5841,7 +6101,7 @@ static int ixgbe_tso(struct ixgbe_adapter *adapter, l4len = tcp_hdrlen(skb); *hdr_len += l4len; - if (skb->protocol == htons(ETH_P_IP)) { + if (protocol == htons(ETH_P_IP)) { struct iphdr *iph = ip_hdr(skb); iph->tot_len = 0; iph->check = 0; @@ -5880,7 +6140,7 @@ static int ixgbe_tso(struct ixgbe_adapter *adapter, type_tucmd_mlhl = (IXGBE_TXD_CMD_DEXT | IXGBE_ADVTXD_DTYP_CTXT); - if (skb->protocol == htons(ETH_P_IP)) + 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); @@ -5906,16 +6166,10 @@ static int ixgbe_tso(struct ixgbe_adapter *adapter, return false; } -static u32 ixgbe_psum(struct ixgbe_adapter *adapter, struct sk_buff *skb) +static u32 ixgbe_psum(struct ixgbe_adapter *adapter, struct sk_buff *skb, + __be16 protocol) { u32 rtn = 0; - __be16 protocol; - - if (skb->protocol == cpu_to_be16(ETH_P_8021Q)) - protocol = ((const struct vlan_ethhdr *)skb->data)-> - h_vlan_encapsulated_proto; - else - protocol = skb->protocol; switch (protocol) { case cpu_to_be16(ETH_P_IP): @@ -5943,7 +6197,7 @@ static u32 ixgbe_psum(struct ixgbe_adapter *adapter, struct sk_buff *skb) default: if (unlikely(net_ratelimit())) e_warn(probe, "partial checksum but proto=%x!\n", - skb->protocol); + protocol); break; } @@ -5952,7 +6206,8 @@ static u32 ixgbe_psum(struct ixgbe_adapter *adapter, struct sk_buff *skb) static bool ixgbe_tx_csum(struct ixgbe_adapter *adapter, struct ixgbe_ring *tx_ring, - struct sk_buff *skb, u32 tx_flags) + struct sk_buff *skb, u32 tx_flags, + __be16 protocol) { struct ixgbe_adv_tx_context_desc *context_desc; unsigned int i; @@ -5981,7 +6236,7 @@ static bool ixgbe_tx_csum(struct ixgbe_adapter *adapter, IXGBE_ADVTXD_DTYP_CTXT); if (skb->ip_summed == CHECKSUM_PARTIAL) - type_tucmd_mlhl |= ixgbe_psum(adapter, skb); + 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 */ @@ -6004,15 +6259,17 @@ static bool ixgbe_tx_csum(struct ixgbe_adapter *adapter, static int ixgbe_tx_map(struct ixgbe_adapter *adapter, struct ixgbe_ring *tx_ring, struct sk_buff *skb, u32 tx_flags, - unsigned int first) + unsigned int first, const u8 hdr_len) { - struct pci_dev *pdev = adapter->pdev; + struct device *dev = tx_ring->dev; 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 nr_frags = skb_shinfo(skb)->nr_frags; unsigned int f; + unsigned int bytecount = skb->len; + u16 gso_segs = 1; i = tx_ring->next_to_use; @@ -6027,10 +6284,10 @@ static int ixgbe_tx_map(struct ixgbe_adapter *adapter, tx_buffer_info->length = size; tx_buffer_info->mapped_as_page = false; - tx_buffer_info->dma = dma_map_single(&pdev->dev, + tx_buffer_info->dma = dma_map_single(dev, skb->data + offset, size, DMA_TO_DEVICE); - if (dma_mapping_error(&pdev->dev, tx_buffer_info->dma)) + if (dma_mapping_error(dev, tx_buffer_info->dma)) goto dma_error; tx_buffer_info->time_stamp = jiffies; tx_buffer_info->next_to_watch = i; @@ -6063,12 +6320,12 @@ static int ixgbe_tx_map(struct ixgbe_adapter *adapter, size = min(len, (uint)IXGBE_MAX_DATA_PER_TXD); tx_buffer_info->length = size; - tx_buffer_info->dma = dma_map_page(&adapter->pdev->dev, + tx_buffer_info->dma = dma_map_page(dev, frag->page, offset, size, DMA_TO_DEVICE); tx_buffer_info->mapped_as_page = true; - if (dma_mapping_error(&pdev->dev, tx_buffer_info->dma)) + if (dma_mapping_error(dev, tx_buffer_info->dma)) goto dma_error; tx_buffer_info->time_stamp = jiffies; tx_buffer_info->next_to_watch = i; @@ -6082,6 +6339,19 @@ static int ixgbe_tx_map(struct ixgbe_adapter *adapter, break; } + if (tx_flags & IXGBE_TX_FLAGS_TSO) + gso_segs = skb_shinfo(skb)->gso_segs; +#ifdef IXGBE_FCOE + /* adjust for FCoE Sequence Offload */ + else if (tx_flags & IXGBE_TX_FLAGS_FSO) + gso_segs = DIV_ROUND_UP(skb->len - hdr_len, + skb_shinfo(skb)->gso_size); +#endif /* IXGBE_FCOE */ + bytecount += (gso_segs - 1) * hdr_len; + + /* multiply data chunks by size of headers */ + tx_ring->tx_buffer_info[i].bytecount = bytecount; + tx_ring->tx_buffer_info[i].gso_segs = gso_segs; tx_ring->tx_buffer_info[i].skb = skb; tx_ring->tx_buffer_info[first].next_to_watch = i; @@ -6103,14 +6373,13 @@ dma_error: i += tx_ring->count; i--; tx_buffer_info = &tx_ring->tx_buffer_info[i]; - ixgbe_unmap_and_free_tx_resource(adapter, tx_buffer_info); + ixgbe_unmap_and_free_tx_resource(tx_ring, tx_buffer_info); } return 0; } -static void ixgbe_tx_queue(struct ixgbe_adapter *adapter, - struct ixgbe_ring *tx_ring, +static void ixgbe_tx_queue(struct ixgbe_ring *tx_ring, int tx_flags, int count, u32 paylen, u8 hdr_len) { union ixgbe_adv_tx_desc *tx_desc = NULL; @@ -6175,60 +6444,46 @@ static void ixgbe_tx_queue(struct ixgbe_adapter *adapter, wmb(); tx_ring->next_to_use = i; - writel(i, adapter->hw.hw_addr + tx_ring->tail); + writel(i, tx_ring->tail); } static void ixgbe_atr(struct ixgbe_adapter *adapter, struct sk_buff *skb, - int queue, u32 tx_flags) + u8 queue, u32 tx_flags, __be16 protocol) { struct ixgbe_atr_input atr_input; - struct tcphdr *th; struct iphdr *iph = ip_hdr(skb); struct ethhdr *eth = (struct ethhdr *)skb->data; - u16 vlan_id, src_port, dst_port, flex_bytes; - u32 src_ipv4_addr, dst_ipv4_addr; - u8 l4type = 0; + struct tcphdr *th; + u16 vlan_id; - /* Right now, we support IPv4 only */ - if (skb->protocol != htons(ETH_P_IP)) - return; - /* check if we're UDP or TCP */ - if (iph->protocol == IPPROTO_TCP) { - th = tcp_hdr(skb); - src_port = th->source; - dst_port = th->dest; - l4type |= IXGBE_ATR_L4TYPE_TCP; - /* l4type IPv4 type is 0, no need to assign */ - } else { - /* Unsupported L4 header, just bail here */ + /* Right now, we support IPv4 w/ TCP only */ + if (protocol != htons(ETH_P_IP) || + iph->protocol != IPPROTO_TCP) return; - } memset(&atr_input, 0, sizeof(struct ixgbe_atr_input)); vlan_id = (tx_flags & IXGBE_TX_FLAGS_VLAN_MASK) >> IXGBE_TX_FLAGS_VLAN_SHIFT; - src_ipv4_addr = iph->saddr; - dst_ipv4_addr = iph->daddr; - flex_bytes = eth->h_proto; + + th = tcp_hdr(skb); ixgbe_atr_set_vlan_id_82599(&atr_input, vlan_id); - ixgbe_atr_set_src_port_82599(&atr_input, dst_port); - ixgbe_atr_set_dst_port_82599(&atr_input, src_port); - ixgbe_atr_set_flex_byte_82599(&atr_input, flex_bytes); - ixgbe_atr_set_l4type_82599(&atr_input, l4type); + ixgbe_atr_set_src_port_82599(&atr_input, th->dest); + ixgbe_atr_set_dst_port_82599(&atr_input, th->source); + ixgbe_atr_set_flex_byte_82599(&atr_input, eth->h_proto); + ixgbe_atr_set_l4type_82599(&atr_input, IXGBE_ATR_L4TYPE_TCP); /* src and dst are inverted, think how the receiver sees them */ - ixgbe_atr_set_src_ipv4_82599(&atr_input, dst_ipv4_addr); - ixgbe_atr_set_dst_ipv4_82599(&atr_input, src_ipv4_addr); + ixgbe_atr_set_src_ipv4_82599(&atr_input, iph->daddr); + ixgbe_atr_set_dst_ipv4_82599(&atr_input, iph->saddr); /* This assumes the Rx queue and Tx queue are bound to the same CPU */ ixgbe_fdir_add_signature_filter_82599(&adapter->hw, &atr_input, queue); } -static int __ixgbe_maybe_stop_tx(struct net_device *netdev, - struct ixgbe_ring *tx_ring, int size) +static int __ixgbe_maybe_stop_tx(struct ixgbe_ring *tx_ring, int size) { - netif_stop_subqueue(netdev, tx_ring->queue_index); + netif_stop_subqueue(tx_ring->netdev, tx_ring->queue_index); /* Herbert's original patch had: * smp_mb__after_netif_stop_queue(); * but since that doesn't exist yet, just open code it. */ @@ -6240,27 +6495,29 @@ static int __ixgbe_maybe_stop_tx(struct net_device *netdev, return -EBUSY; /* A reprieve! - use start_queue because it doesn't call schedule */ - netif_start_subqueue(netdev, tx_ring->queue_index); - ++tx_ring->restart_queue; + netif_start_subqueue(tx_ring->netdev, tx_ring->queue_index); + ++tx_ring->tx_stats.restart_queue; return 0; } -static int ixgbe_maybe_stop_tx(struct net_device *netdev, - struct ixgbe_ring *tx_ring, int size) +static int ixgbe_maybe_stop_tx(struct ixgbe_ring *tx_ring, int size) { if (likely(IXGBE_DESC_UNUSED(tx_ring) >= size)) return 0; - return __ixgbe_maybe_stop_tx(netdev, tx_ring, size); + return __ixgbe_maybe_stop_tx(tx_ring, size); } static u16 ixgbe_select_queue(struct net_device *dev, struct sk_buff *skb) { struct ixgbe_adapter *adapter = netdev_priv(dev); int txq = smp_processor_id(); - #ifdef IXGBE_FCOE - if ((skb->protocol == htons(ETH_P_FCOE)) || - (skb->protocol == htons(ETH_P_FIP))) { + __be16 protocol; + + protocol = vlan_get_protocol(skb); + + if ((protocol == htons(ETH_P_FCOE)) || + (protocol == htons(ETH_P_FIP))) { if (adapter->flags & IXGBE_FLAG_FCOE_ENABLED) { txq &= (adapter->ring_feature[RING_F_FCOE].indices - 1); txq += adapter->ring_feature[RING_F_FCOE].mask; @@ -6292,10 +6549,11 @@ static u16 ixgbe_select_queue(struct net_device *dev, struct sk_buff *skb) return skb_tx_hash(dev, skb); } -netdev_tx_t ixgbe_xmit_frame_ring(struct sk_buff *skb, struct net_device *netdev, +netdev_tx_t ixgbe_xmit_frame_ring(struct sk_buff *skb, struct ixgbe_adapter *adapter, struct ixgbe_ring *tx_ring) { + struct net_device *netdev = tx_ring->netdev; struct netdev_queue *txq; unsigned int first; unsigned int tx_flags = 0; @@ -6303,6 +6561,9 @@ netdev_tx_t ixgbe_xmit_frame_ring(struct sk_buff *skb, struct net_device *netdev int tso; int count = 0; unsigned int f; + __be16 protocol; + + protocol = vlan_get_protocol(skb); if (vlan_tx_tag_present(skb)) { tx_flags |= vlan_tx_tag_get(skb); @@ -6323,8 +6584,8 @@ netdev_tx_t ixgbe_xmit_frame_ring(struct sk_buff *skb, struct net_device *netdev /* for FCoE with DCB, we force the priority to what * was specified by the switch */ if (adapter->flags & IXGBE_FLAG_FCOE_ENABLED && - (skb->protocol == htons(ETH_P_FCOE) || - skb->protocol == htons(ETH_P_FIP))) { + (protocol == htons(ETH_P_FCOE) || + protocol == htons(ETH_P_FIP))) { #ifdef CONFIG_IXGBE_DCB if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) { tx_flags &= ~(IXGBE_TX_FLAGS_VLAN_PRIO_MASK @@ -6334,7 +6595,7 @@ netdev_tx_t ixgbe_xmit_frame_ring(struct sk_buff *skb, struct net_device *netdev } #endif /* flag for FCoE offloads */ - if (skb->protocol == htons(ETH_P_FCOE)) + if (protocol == htons(ETH_P_FCOE)) tx_flags |= IXGBE_TX_FLAGS_FCOE; } #endif @@ -6350,8 +6611,8 @@ netdev_tx_t ixgbe_xmit_frame_ring(struct sk_buff *skb, struct net_device *netdev 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(netdev, tx_ring, count)) { - adapter->tx_busy++; + if (ixgbe_maybe_stop_tx(tx_ring, count)) { + tx_ring->tx_stats.tx_busy++; return NETDEV_TX_BUSY; } @@ -6368,9 +6629,10 @@ netdev_tx_t ixgbe_xmit_frame_ring(struct sk_buff *skb, struct net_device *netdev tx_flags |= IXGBE_TX_FLAGS_FSO; #endif /* IXGBE_FCOE */ } else { - if (skb->protocol == htons(ETH_P_IP)) + if (protocol == htons(ETH_P_IP)) tx_flags |= IXGBE_TX_FLAGS_IPV4; - tso = ixgbe_tso(adapter, tx_ring, skb, tx_flags, &hdr_len); + tso = ixgbe_tso(adapter, tx_ring, skb, tx_flags, &hdr_len, + protocol); if (tso < 0) { dev_kfree_skb_any(skb); return NETDEV_TX_OK; @@ -6378,30 +6640,30 @@ netdev_tx_t ixgbe_xmit_frame_ring(struct sk_buff *skb, struct net_device *netdev if (tso) tx_flags |= IXGBE_TX_FLAGS_TSO; - else if (ixgbe_tx_csum(adapter, tx_ring, skb, tx_flags) && + else if (ixgbe_tx_csum(adapter, tx_ring, skb, tx_flags, + protocol) && (skb->ip_summed == CHECKSUM_PARTIAL)) tx_flags |= IXGBE_TX_FLAGS_CSUM; } - count = ixgbe_tx_map(adapter, tx_ring, skb, tx_flags, first); + count = ixgbe_tx_map(adapter, tx_ring, skb, tx_flags, first, hdr_len); if (count) { /* add the ATR filter if ATR is on */ if (tx_ring->atr_sample_rate) { ++tx_ring->atr_count; if ((tx_ring->atr_count >= tx_ring->atr_sample_rate) && - test_bit(__IXGBE_FDIR_INIT_DONE, - &tx_ring->reinit_state)) { + test_bit(__IXGBE_TX_FDIR_INIT_DONE, + &tx_ring->state)) { ixgbe_atr(adapter, skb, tx_ring->queue_index, - tx_flags); + tx_flags, protocol); tx_ring->atr_count = 0; } } txq = netdev_get_tx_queue(netdev, tx_ring->queue_index); txq->tx_bytes += skb->len; txq->tx_packets++; - ixgbe_tx_queue(adapter, tx_ring, tx_flags, count, skb->len, - hdr_len); - ixgbe_maybe_stop_tx(netdev, tx_ring, DESC_NEEDED); + ixgbe_tx_queue(tx_ring, tx_flags, count, skb->len, hdr_len); + ixgbe_maybe_stop_tx(tx_ring, DESC_NEEDED); } else { dev_kfree_skb_any(skb); @@ -6418,7 +6680,7 @@ static netdev_tx_t ixgbe_xmit_frame(struct sk_buff *skb, struct net_device *netd struct ixgbe_ring *tx_ring; tx_ring = adapter->tx_ring[skb->queue_mapping]; - return ixgbe_xmit_frame_ring(skb, netdev, adapter, tx_ring); + return ixgbe_xmit_frame_ring(skb, adapter, tx_ring); } /** @@ -6559,20 +6821,23 @@ static struct rtnl_link_stats64 *ixgbe_get_stats64(struct net_device *netdev, /* accurate rx/tx bytes/packets stats */ dev_txq_stats_fold(netdev, stats); + rcu_read_lock(); for (i = 0; i < adapter->num_rx_queues; i++) { - struct ixgbe_ring *ring = adapter->rx_ring[i]; + struct ixgbe_ring *ring = ACCESS_ONCE(adapter->rx_ring[i]); u64 bytes, packets; unsigned int start; - do { - start = u64_stats_fetch_begin_bh(&ring->syncp); - packets = ring->stats.packets; - bytes = ring->stats.bytes; - } while (u64_stats_fetch_retry_bh(&ring->syncp, start)); - stats->rx_packets += packets; - stats->rx_bytes += bytes; + if (ring) { + do { + start = u64_stats_fetch_begin_bh(&ring->syncp); + packets = ring->stats.packets; + bytes = ring->stats.bytes; + } while (u64_stats_fetch_retry_bh(&ring->syncp, start)); + stats->rx_packets += packets; + stats->rx_bytes += bytes; + } } - + rcu_read_unlock(); /* following stats updated by ixgbe_watchdog_task() */ stats->multicast = netdev->stats.multicast; stats->rx_errors = netdev->stats.rx_errors; @@ -6687,11 +6952,12 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, const struct ixgbe_info *ii = ixgbe_info_tbl[ent->driver_data]; static int cards_found; int i, err, pci_using_dac; + u8 part_str[IXGBE_PBANUM_LENGTH]; unsigned int indices = num_possible_cpus(); #ifdef IXGBE_FCOE u16 device_caps; #endif - u32 part_num, eec; + u32 eec; /* Catch broken hardware that put the wrong VF device ID in * the PCIe SR-IOV capability. @@ -6754,8 +7020,8 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, SET_NETDEV_DEV(netdev, &pdev->dev); - pci_set_drvdata(pdev, netdev); adapter = netdev_priv(netdev); + pci_set_drvdata(pdev, adapter); adapter->netdev = netdev; adapter->pdev = pdev; @@ -6828,8 +7094,14 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, goto err_sw_init; /* Make it possible the adapter to be woken up via WOL */ - if (adapter->hw.mac.type == ixgbe_mac_82599EB) + switch (adapter->hw.mac.type) { + case ixgbe_mac_82599EB: + case ixgbe_mac_X540: IXGBE_WRITE_REG(&adapter->hw, IXGBE_WUS, ~0); + break; + default: + break; + } /* * If there is a fan on this device and it has failed log the @@ -6937,8 +7209,11 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, goto err_eeprom; } - /* power down the optics */ - if (hw->phy.multispeed_fiber) + /* power down the optics for multispeed fiber and 82599 SFP+ fiber */ + if (hw->mac.ops.disable_tx_laser && + ((hw->phy.multispeed_fiber) || + ((hw->phy.type == ixgbe_media_type_fiber) && + (hw->mac.type == ixgbe_mac_82599EB)))) hw->mac.ops.disable_tx_laser(hw); init_timer(&adapter->watchdog_timer); @@ -6953,6 +7228,18 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, goto err_sw_init; switch (pdev->device) { + case IXGBE_DEV_ID_82599_SFP: + /* Only this subdevice supports WOL */ + if (pdev->subsystem_device == IXGBE_SUBDEV_ID_82599_SFP) + adapter->wol = (IXGBE_WUFC_MAG | IXGBE_WUFC_EX | + IXGBE_WUFC_MC | IXGBE_WUFC_BC); + break; + case IXGBE_DEV_ID_82599_COMBO_BACKPLANE: + /* All except this subdevice support WOL */ + if (pdev->subsystem_device != IXGBE_SUBDEV_ID_82599_KX4_KR_MEZZ) + adapter->wol = (IXGBE_WUFC_MAG | IXGBE_WUFC_EX | + IXGBE_WUFC_MC | IXGBE_WUFC_BC); + break; case IXGBE_DEV_ID_82599_KX4: adapter->wol = (IXGBE_WUFC_MAG | IXGBE_WUFC_EX | IXGBE_WUFC_MC | IXGBE_WUFC_BC); @@ -6976,16 +7263,17 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, hw->bus.width == ixgbe_bus_width_pcie_x1 ? "Width x1" : "Unknown"), netdev->dev_addr); - ixgbe_read_pba_num_generic(hw, &part_num); + + err = ixgbe_read_pba_string_generic(hw, part_str, IXGBE_PBANUM_LENGTH); + if (err) + strcpy(part_str, "Unknown"); if (ixgbe_is_sfp(hw) && hw->phy.sfp_type != ixgbe_sfp_type_not_present) - e_dev_info("MAC: %d, PHY: %d, SFP+: %d, " - "PBA No: %06x-%03x\n", + e_dev_info("MAC: %d, PHY: %d, SFP+: %d, PBA No: %s\n", hw->mac.type, hw->phy.type, hw->phy.sfp_type, - (part_num >> 8), (part_num & 0xff)); + part_str); else - e_dev_info("MAC: %d, PHY: %d, PBA No: %06x-%03x\n", - hw->mac.type, hw->phy.type, - (part_num >> 8), (part_num & 0xff)); + e_dev_info("MAC: %d, PHY: %d, PBA No: %s\n", + hw->mac.type, hw->phy.type, part_str); if (hw->bus.width <= ixgbe_bus_width_pcie_x4) { e_dev_warn("PCI-Express bandwidth available for this card is " @@ -7078,8 +7366,8 @@ err_dma: **/ static void __devexit ixgbe_remove(struct pci_dev *pdev) { - struct net_device *netdev = pci_get_drvdata(pdev); - struct ixgbe_adapter *adapter = netdev_priv(netdev); + struct ixgbe_adapter *adapter = pci_get_drvdata(pdev); + struct net_device *netdev = adapter->netdev; set_bit(__IXGBE_DOWN, &adapter->state); /* clear the module not found bit to make sure the worker won't @@ -7149,8 +7437,8 @@ static void __devexit ixgbe_remove(struct pci_dev *pdev) static pci_ers_result_t ixgbe_io_error_detected(struct pci_dev *pdev, pci_channel_state_t state) { - struct net_device *netdev = pci_get_drvdata(pdev); - struct ixgbe_adapter *adapter = netdev_priv(netdev); + struct ixgbe_adapter *adapter = pci_get_drvdata(pdev); + struct net_device *netdev = adapter->netdev; netif_device_detach(netdev); @@ -7173,8 +7461,7 @@ static pci_ers_result_t ixgbe_io_error_detected(struct pci_dev *pdev, */ static pci_ers_result_t ixgbe_io_slot_reset(struct pci_dev *pdev) { - struct net_device *netdev = pci_get_drvdata(pdev); - struct ixgbe_adapter *adapter = netdev_priv(netdev); + struct ixgbe_adapter *adapter = pci_get_drvdata(pdev); pci_ers_result_t result; int err; @@ -7212,8 +7499,8 @@ static pci_ers_result_t ixgbe_io_slot_reset(struct pci_dev *pdev) */ static void ixgbe_io_resume(struct pci_dev *pdev) { - struct net_device *netdev = pci_get_drvdata(pdev); - struct ixgbe_adapter *adapter = netdev_priv(netdev); + struct ixgbe_adapter *adapter = pci_get_drvdata(pdev); + struct net_device *netdev = adapter->netdev; if (netif_running(netdev)) { if (ixgbe_up(adapter)) { @@ -7278,6 +7565,7 @@ static void __exit ixgbe_exit_module(void) dca_unregister_notify(&dca_notifier); #endif pci_unregister_driver(&ixgbe_driver); + rcu_barrier(); /* Wait for completion of call_rcu()'s */ } #ifdef CONFIG_IXGBE_DCA diff --git a/drivers/net/ixgbe/ixgbe_mbx.c b/drivers/net/ixgbe/ixgbe_mbx.c index 471f0f2cdb98..027c628c3aae 100644 --- a/drivers/net/ixgbe/ixgbe_mbx.c +++ b/drivers/net/ixgbe/ixgbe_mbx.c @@ -319,8 +319,14 @@ static s32 ixgbe_check_for_rst_pf(struct ixgbe_hw *hw, u16 vf_number) u32 vflre = 0; s32 ret_val = IXGBE_ERR_MBX; - if (hw->mac.type == ixgbe_mac_82599EB) + switch (hw->mac.type) { + case ixgbe_mac_82599EB: + case ixgbe_mac_X540: vflre = IXGBE_READ_REG(hw, IXGBE_VFLRE(reg_offset)); + break; + default: + break; + } if (vflre & (1 << vf_shift)) { ret_val = 0; @@ -439,22 +445,26 @@ void ixgbe_init_mbx_params_pf(struct ixgbe_hw *hw) { struct ixgbe_mbx_info *mbx = &hw->mbx; - if (hw->mac.type != ixgbe_mac_82599EB) - return; - - mbx->timeout = 0; - mbx->usec_delay = 0; - - mbx->size = IXGBE_VFMAILBOX_SIZE; - - mbx->stats.msgs_tx = 0; - mbx->stats.msgs_rx = 0; - mbx->stats.reqs = 0; - mbx->stats.acks = 0; - mbx->stats.rsts = 0; + switch (hw->mac.type) { + case ixgbe_mac_82599EB: + case ixgbe_mac_X540: + mbx->timeout = 0; + mbx->usec_delay = 0; + + mbx->size = IXGBE_VFMAILBOX_SIZE; + + mbx->stats.msgs_tx = 0; + mbx->stats.msgs_rx = 0; + mbx->stats.reqs = 0; + mbx->stats.acks = 0; + mbx->stats.rsts = 0; + break; + default: + break; + } } -struct ixgbe_mbx_operations mbx_ops_82599 = { +struct ixgbe_mbx_operations mbx_ops_generic = { .read = ixgbe_read_mbx_pf, .write = ixgbe_write_mbx_pf, .read_posted = ixgbe_read_posted_mbx, diff --git a/drivers/net/ixgbe/ixgbe_mbx.h b/drivers/net/ixgbe/ixgbe_mbx.h index 7e0d08ff5b53..3df9b1590218 100644 --- a/drivers/net/ixgbe/ixgbe_mbx.h +++ b/drivers/net/ixgbe/ixgbe_mbx.h @@ -88,6 +88,6 @@ s32 ixgbe_check_for_ack(struct ixgbe_hw *, u16); s32 ixgbe_check_for_rst(struct ixgbe_hw *, u16); void ixgbe_init_mbx_params_pf(struct ixgbe_hw *); -extern struct ixgbe_mbx_operations mbx_ops_82599; +extern struct ixgbe_mbx_operations mbx_ops_generic; #endif /* _IXGBE_MBX_H_ */ diff --git a/drivers/net/ixgbe/ixgbe_phy.c b/drivers/net/ixgbe/ixgbe_phy.c index 6c0d42e33f21..c445fbce56ee 100644 --- a/drivers/net/ixgbe/ixgbe_phy.c +++ b/drivers/net/ixgbe/ixgbe_phy.c @@ -115,6 +115,9 @@ static enum ixgbe_phy_type ixgbe_get_phy_type_from_id(u32 phy_id) case TN1010_PHY_ID: phy_type = ixgbe_phy_tn; break; + case AQ1202_PHY_ID: + phy_type = ixgbe_phy_aq; + break; case QT2022_PHY_ID: phy_type = ixgbe_phy_qt; break; @@ -425,6 +428,39 @@ s32 ixgbe_setup_phy_link_speed_generic(struct ixgbe_hw *hw, } /** + * ixgbe_get_copper_link_capabilities_generic - Determines link capabilities + * @hw: pointer to hardware structure + * @speed: pointer to link speed + * @autoneg: boolean auto-negotiation value + * + * Determines the link capabilities by reading the AUTOC register. + */ +s32 ixgbe_get_copper_link_capabilities_generic(struct ixgbe_hw *hw, + ixgbe_link_speed *speed, + bool *autoneg) +{ + s32 status = IXGBE_ERR_LINK_SETUP; + u16 speed_ability; + + *speed = 0; + *autoneg = true; + + status = hw->phy.ops.read_reg(hw, MDIO_SPEED, MDIO_MMD_PMAPMD, + &speed_ability); + + if (status == 0) { + if (speed_ability & MDIO_SPEED_10G) + *speed |= IXGBE_LINK_SPEED_10GB_FULL; + if (speed_ability & MDIO_PMA_SPEED_1000) + *speed |= IXGBE_LINK_SPEED_1GB_FULL; + if (speed_ability & MDIO_PMA_SPEED_100) + *speed |= IXGBE_LINK_SPEED_100_FULL; + } + + return status; +} + +/** * ixgbe_reset_phy_nl - Performs a PHY reset * @hw: pointer to hardware structure **/ @@ -1378,6 +1414,22 @@ s32 ixgbe_get_phy_firmware_version_tnx(struct ixgbe_hw *hw, } /** + * ixgbe_get_phy_firmware_version_generic - Gets the PHY Firmware Version + * @hw: pointer to hardware structure + * @firmware_version: pointer to the PHY Firmware Version +**/ +s32 ixgbe_get_phy_firmware_version_generic(struct ixgbe_hw *hw, + u16 *firmware_version) +{ + s32 status = 0; + + status = hw->phy.ops.read_reg(hw, AQ_FW_REV, MDIO_MMD_VEND1, + firmware_version); + + return status; +} + +/** * ixgbe_tn_check_overtemp - Checks if an overtemp occured. * @hw: pointer to hardware structure * diff --git a/drivers/net/ixgbe/ixgbe_phy.h b/drivers/net/ixgbe/ixgbe_phy.h index fb3898f12fc5..e2c6b7eac641 100644 --- a/drivers/net/ixgbe/ixgbe_phy.h +++ b/drivers/net/ixgbe/ixgbe_phy.h @@ -96,6 +96,9 @@ s32 ixgbe_setup_phy_link_speed_generic(struct ixgbe_hw *hw, ixgbe_link_speed speed, bool autoneg, bool autoneg_wait_to_complete); +s32 ixgbe_get_copper_link_capabilities_generic(struct ixgbe_hw *hw, + ixgbe_link_speed *speed, + bool *autoneg); /* PHY specific */ s32 ixgbe_check_phy_link_tnx(struct ixgbe_hw *hw, @@ -103,6 +106,8 @@ s32 ixgbe_check_phy_link_tnx(struct ixgbe_hw *hw, bool *link_up); s32 ixgbe_get_phy_firmware_version_tnx(struct ixgbe_hw *hw, u16 *firmware_version); +s32 ixgbe_get_phy_firmware_version_generic(struct ixgbe_hw *hw, + u16 *firmware_version); s32 ixgbe_reset_phy_nl(struct ixgbe_hw *hw); s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw); diff --git a/drivers/net/ixgbe/ixgbe_sriov.c b/drivers/net/ixgbe/ixgbe_sriov.c index 5428153af8f3..6e3e94b5a5f6 100644 --- a/drivers/net/ixgbe/ixgbe_sriov.c +++ b/drivers/net/ixgbe/ixgbe_sriov.c @@ -68,7 +68,7 @@ static int ixgbe_set_vf_multicasts(struct ixgbe_adapter *adapter, * addresses */ for (i = 0; i < entries; i++) { - vfinfo->vf_mc_hashes[i] = hash_list[i];; + vfinfo->vf_mc_hashes[i] = hash_list[i]; } for (i = 0; i < vfinfo->num_vf_mc_hashes; i++) { @@ -178,8 +178,7 @@ static int ixgbe_set_vf_mac(struct ixgbe_adapter *adapter, int ixgbe_vf_configuration(struct pci_dev *pdev, unsigned int event_mask) { unsigned char vf_mac_addr[6]; - struct net_device *netdev = pci_get_drvdata(pdev); - struct ixgbe_adapter *adapter = netdev_priv(netdev); + struct ixgbe_adapter *adapter = pci_get_drvdata(pdev); unsigned int vfn = (event_mask & 0x3f); bool enable = ((event_mask & 0x10000000U) != 0); diff --git a/drivers/net/ixgbe/ixgbe_type.h b/drivers/net/ixgbe/ixgbe_type.h index d3cc6ce7c973..ef816dd5a8f0 100644 --- a/drivers/net/ixgbe/ixgbe_type.h +++ b/drivers/net/ixgbe/ixgbe_type.h @@ -54,9 +54,14 @@ #define IXGBE_DEV_ID_82599_T3_LOM 0x151C #define IXGBE_DEV_ID_82599_CX4 0x10F9 #define IXGBE_DEV_ID_82599_SFP 0x10FB +#define IXGBE_DEV_ID_82599_BACKPLANE_FCOE 0x152a +#define IXGBE_DEV_ID_82599_SFP_FCOE 0x1529 +#define IXGBE_SUBDEV_ID_82599_SFP 0x11A9 #define IXGBE_DEV_ID_82599_SFP_EM 0x1507 #define IXGBE_DEV_ID_82599_XAUI_LOM 0x10FC #define IXGBE_DEV_ID_82599_COMBO_BACKPLANE 0x10F8 +#define IXGBE_SUBDEV_ID_82599_KX4_KR_MEZZ 0x000C +#define IXGBE_DEV_ID_X540T 0x1528 /* General Registers */ #define IXGBE_CTRL 0x00000 @@ -994,8 +999,10 @@ /* PHY IDs*/ #define TN1010_PHY_ID 0x00A19410 #define TNX_FW_REV 0xB +#define AQ1202_PHY_ID 0x03A1B440 #define QT2022_PHY_ID 0x0043A400 #define ATH_PHY_ID 0x03429050 +#define AQ_FW_REV 0x20 /* PHY Types */ #define IXGBE_M88E1145_E_PHY_ID 0x01410CD0 @@ -1491,6 +1498,7 @@ #define IXGBE_EEC_PRES 0x00000100 /* EEPROM Present */ #define IXGBE_EEC_ARD 0x00000200 /* EEPROM Auto Read Done */ #define IXGBE_EEC_FLUP 0x00800000 /* Flash update command */ +#define IXGBE_EEC_SEC1VAL 0x02000000 /* Sector 1 Valid */ #define IXGBE_EEC_FLUDONE 0x04000000 /* Flash update done */ /* EEPROM Addressing bits based on type (0-small, 1-large) */ #define IXGBE_EEC_ADDR_SIZE 0x00000400 @@ -1500,12 +1508,18 @@ #define IXGBE_EEPROM_WORD_SIZE_SHIFT 6 #define IXGBE_EEPROM_OPCODE_BITS 8 +/* Part Number String Length */ +#define IXGBE_PBANUM_LENGTH 11 + /* Checksum and EEPROM pointers */ +#define IXGBE_PBANUM_PTR_GUARD 0xFAFA #define IXGBE_EEPROM_CHECKSUM 0x3F #define IXGBE_EEPROM_SUM 0xBABA #define IXGBE_PCIE_ANALOG_PTR 0x03 #define IXGBE_ATLAS0_CONFIG_PTR 0x04 +#define IXGBE_PHY_PTR 0x04 #define IXGBE_ATLAS1_CONFIG_PTR 0x05 +#define IXGBE_OPTION_ROM_PTR 0x05 #define IXGBE_PCIE_GENERAL_PTR 0x06 #define IXGBE_PCIE_CONFIG0_PTR 0x07 #define IXGBE_PCIE_CONFIG1_PTR 0x08 @@ -2113,6 +2127,14 @@ typedef u32 ixgbe_physical_layer; #define IXGBE_PHYSICAL_LAYER_10GBASE_XAUI 0x1000 #define IXGBE_PHYSICAL_LAYER_SFP_ACTIVE_DA 0x2000 +/* Flow Control Macros */ +#define PAUSE_RTT 8 +#define PAUSE_MTU(MTU) ((MTU + 1024 - 1) / 1024) + +#define FC_HIGH_WATER(MTU) ((((PAUSE_RTT + PAUSE_MTU(MTU)) * 144) + 99) / 100 +\ + PAUSE_MTU(MTU)) +#define FC_LOW_WATER(MTU) (2 * (2 * PAUSE_MTU(MTU) + PAUSE_RTT)) + /* Software ATR hash keys */ #define IXGBE_ATR_BUCKET_HASH_KEY 0xE214AD3D #define IXGBE_ATR_SIGNATURE_HASH_KEY 0x14364D17 @@ -2164,6 +2186,7 @@ struct ixgbe_atr_input_masks { enum ixgbe_eeprom_type { ixgbe_eeprom_uninitialized = 0, ixgbe_eeprom_spi, + ixgbe_flash, ixgbe_eeprom_none /* No NVM support */ }; @@ -2171,12 +2194,14 @@ enum ixgbe_mac_type { ixgbe_mac_unknown = 0, ixgbe_mac_82598EB, ixgbe_mac_82599EB, + ixgbe_mac_X540, ixgbe_num_macs }; enum ixgbe_phy_type { ixgbe_phy_unknown = 0, ixgbe_phy_tn, + ixgbe_phy_aq, ixgbe_phy_cu_unknown, ixgbe_phy_qt, ixgbe_phy_xaui, @@ -2405,6 +2430,7 @@ struct ixgbe_eeprom_operations { s32 (*write)(struct ixgbe_hw *, u16, u16); s32 (*validate_checksum)(struct ixgbe_hw *, u16 *); s32 (*update_checksum)(struct ixgbe_hw *); + u16 (*calc_checksum)(struct ixgbe_hw *); }; struct ixgbe_mac_operations { @@ -2574,6 +2600,7 @@ struct ixgbe_hw { u16 subsystem_vendor_id; u8 revision_id; bool adapter_stopped; + bool force_full_reset; }; struct ixgbe_info { @@ -2614,6 +2641,8 @@ struct ixgbe_info { #define IXGBE_ERR_NO_SPACE -25 #define IXGBE_ERR_OVERTEMP -26 #define IXGBE_ERR_RAR_INDEX -27 +#define IXGBE_ERR_PBA_SECTION -31 +#define IXGBE_ERR_INVALID_ARGUMENT -32 #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 new file mode 100644 index 000000000000..9649fa727e31 --- /dev/null +++ b/drivers/net/ixgbe/ixgbe_x540.c @@ -0,0 +1,722 @@ +/******************************************************************************* + + Intel 10 Gigabit PCI Express Linux driver + Copyright(c) 1999 - 2010 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, + version 2, as published by the Free Software Foundation. + + This program is distributed in the hope 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 St - Fifth Floor, Boston, MA 02110-1301 USA. + + The full GNU General Public License is included in this distribution in + the file called "COPYING". + + Contact Information: + e1000-devel Mailing List <e1000-devel@lists.sourceforge.net> + Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + +*******************************************************************************/ + +#include <linux/pci.h> +#include <linux/delay.h> +#include <linux/sched.h> + +#include "ixgbe.h" +#include "ixgbe_phy.h" +//#include "ixgbe_mbx.h" + +#define IXGBE_X540_MAX_TX_QUEUES 128 +#define IXGBE_X540_MAX_RX_QUEUES 128 +#define IXGBE_X540_RAR_ENTRIES 128 +#define IXGBE_X540_MC_TBL_SIZE 128 +#define IXGBE_X540_VFT_TBL_SIZE 128 + +static s32 ixgbe_update_flash_X540(struct ixgbe_hw *hw); +static s32 ixgbe_poll_flash_update_done_X540(struct ixgbe_hw *hw); +static s32 ixgbe_acquire_swfw_sync_X540(struct ixgbe_hw *hw, u16 mask); +static void ixgbe_release_swfw_sync_X540(struct ixgbe_hw *hw, u16 mask); +static s32 ixgbe_get_swfw_sync_semaphore(struct ixgbe_hw *hw); +static void ixgbe_release_swfw_sync_semaphore(struct ixgbe_hw *hw); + +static enum ixgbe_media_type ixgbe_get_media_type_X540(struct ixgbe_hw *hw) +{ + return ixgbe_media_type_copper; +} + +static s32 ixgbe_get_invariants_X540(struct ixgbe_hw *hw) +{ + struct ixgbe_mac_info *mac = &hw->mac; + + /* Call PHY identify routine to get the phy type */ + ixgbe_identify_phy_generic(hw); + + mac->mcft_size = IXGBE_X540_MC_TBL_SIZE; + mac->vft_size = IXGBE_X540_VFT_TBL_SIZE; + mac->num_rar_entries = IXGBE_X540_RAR_ENTRIES; + mac->max_rx_queues = IXGBE_X540_MAX_RX_QUEUES; + mac->max_tx_queues = IXGBE_X540_MAX_TX_QUEUES; + mac->max_msix_vectors = ixgbe_get_pcie_msix_count_generic(hw); + + return 0; +} + +/** + * ixgbe_setup_mac_link_X540 - Set the auto advertised capabilitires + * @hw: pointer to hardware structure + * @speed: new link speed + * @autoneg: true if autonegotiation enabled + * @autoneg_wait_to_complete: true when waiting for completion is needed + **/ +static s32 ixgbe_setup_mac_link_X540(struct ixgbe_hw *hw, + ixgbe_link_speed speed, bool autoneg, + bool autoneg_wait_to_complete) +{ + return hw->phy.ops.setup_link_speed(hw, speed, autoneg, + autoneg_wait_to_complete); +} + +/** + * ixgbe_reset_hw_X540 - Perform hardware reset + * @hw: pointer to hardware structure + * + * Resets the hardware by resetting the transmit and receive units, masks + * and clears all interrupts, perform a PHY reset, and perform a link (MAC) + * reset. + **/ +static s32 ixgbe_reset_hw_X540(struct ixgbe_hw *hw) +{ + ixgbe_link_speed link_speed; + s32 status = 0; + u32 ctrl; + u32 ctrl_ext; + u32 reset_bit; + u32 i; + u32 autoc; + u32 autoc2; + bool link_up = false; + + /* Call adapter stop to disable tx/rx and clear interrupts */ + hw->mac.ops.stop_adapter(hw); + + /* + * Prevent the PCI-E bus from from hanging by disabling PCI-E master + * access and verify no pending requests before reset + */ + status = ixgbe_disable_pcie_master(hw); + if (status != 0) { + status = IXGBE_ERR_MASTER_REQUESTS_PENDING; + hw_dbg(hw, "PCI-E Master disable polling has failed.\n"); + } + + /* + * Issue global reset to the MAC. Needs to be SW reset if link is up. + * If link reset is used when link is up, it might reset the PHY when + * mng is using it. If link is down or the flag to force full link + * reset is set, then perform link reset. + */ + if (hw->force_full_reset) { + reset_bit = IXGBE_CTRL_LNK_RST; + } else { + hw->mac.ops.check_link(hw, &link_speed, &link_up, false); + if (!link_up) + reset_bit = IXGBE_CTRL_LNK_RST; + else + reset_bit = IXGBE_CTRL_RST; + } + + ctrl = IXGBE_READ_REG(hw, IXGBE_CTRL); + IXGBE_WRITE_REG(hw, IXGBE_CTRL, (ctrl | IXGBE_CTRL_RST)); + IXGBE_WRITE_FLUSH(hw); + + /* Poll for reset bit to self-clear indicating reset is complete */ + for (i = 0; i < 10; i++) { + udelay(1); + ctrl = IXGBE_READ_REG(hw, IXGBE_CTRL); + if (!(ctrl & IXGBE_CTRL_RST)) + break; + } + if (ctrl & IXGBE_CTRL_RST) { + status = IXGBE_ERR_RESET_FAILED; + hw_dbg(hw, "Reset polling failed to complete.\n"); + } + + /* Clear PF Reset Done bit so PF/VF Mail Ops can work */ + ctrl_ext = IXGBE_READ_REG(hw, IXGBE_CTRL_EXT); + ctrl_ext |= IXGBE_CTRL_EXT_PFRSTD; + IXGBE_WRITE_REG(hw, IXGBE_CTRL_EXT, ctrl_ext); + + msleep(50); + + /* Set the Rx packet buffer size. */ + IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(0), 384 << IXGBE_RXPBSIZE_SHIFT); + + /* Store the permanent mac address */ + hw->mac.ops.get_mac_addr(hw, hw->mac.perm_addr); + + /* + * Store the original AUTOC/AUTOC2 values if they have not been + * stored off yet. Otherwise restore the stored original + * values since the reset operation sets back to defaults. + */ + autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC); + autoc2 = IXGBE_READ_REG(hw, IXGBE_AUTOC2); + if (hw->mac.orig_link_settings_stored == false) { + hw->mac.orig_autoc = autoc; + hw->mac.orig_autoc2 = autoc2; + hw->mac.orig_link_settings_stored = true; + } else { + if (autoc != hw->mac.orig_autoc) + IXGBE_WRITE_REG(hw, IXGBE_AUTOC, (hw->mac.orig_autoc | + IXGBE_AUTOC_AN_RESTART)); + + if ((autoc2 & IXGBE_AUTOC2_UPPER_MASK) != + (hw->mac.orig_autoc2 & IXGBE_AUTOC2_UPPER_MASK)) { + autoc2 &= ~IXGBE_AUTOC2_UPPER_MASK; + autoc2 |= (hw->mac.orig_autoc2 & + IXGBE_AUTOC2_UPPER_MASK); + IXGBE_WRITE_REG(hw, IXGBE_AUTOC2, autoc2); + } + } + + /* + * Store MAC address from RAR0, clear receive address registers, and + * clear the multicast table. Also reset num_rar_entries to 128, + * since we modify this value when programming the SAN MAC address. + */ + hw->mac.num_rar_entries = 128; + hw->mac.ops.init_rx_addrs(hw); + + /* Store the permanent mac address */ + hw->mac.ops.get_mac_addr(hw, hw->mac.perm_addr); + + /* Store the permanent SAN mac address */ + hw->mac.ops.get_san_mac_addr(hw, hw->mac.san_addr); + + /* Add the SAN MAC address to the RAR only if it's a valid address */ + if (ixgbe_validate_mac_addr(hw->mac.san_addr) == 0) { + hw->mac.ops.set_rar(hw, hw->mac.num_rar_entries - 1, + hw->mac.san_addr, 0, IXGBE_RAH_AV); + + /* Reserve the last RAR for the SAN MAC address */ + hw->mac.num_rar_entries--; + } + + /* Store the alternative WWNN/WWPN prefix */ + hw->mac.ops.get_wwn_prefix(hw, &hw->mac.wwnn_prefix, + &hw->mac.wwpn_prefix); + + return status; +} + +/** + * ixgbe_get_supported_physical_layer_X540 - Returns physical layer type + * @hw: pointer to hardware structure + * + * Determines physical layer capabilities of the current configuration. + **/ +static u32 ixgbe_get_supported_physical_layer_X540(struct ixgbe_hw *hw) +{ + u32 physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN; + u16 ext_ability = 0; + + hw->phy.ops.identify(hw); + + hw->phy.ops.read_reg(hw, MDIO_PMA_EXTABLE, MDIO_MMD_PMAPMD, + &ext_ability); + if (ext_ability & MDIO_PMA_EXTABLE_10GBT) + physical_layer |= IXGBE_PHYSICAL_LAYER_10GBASE_T; + if (ext_ability & MDIO_PMA_EXTABLE_1000BT) + physical_layer |= IXGBE_PHYSICAL_LAYER_1000BASE_T; + if (ext_ability & MDIO_PMA_EXTABLE_100BTX) + physical_layer |= IXGBE_PHYSICAL_LAYER_100BASE_TX; + + return physical_layer; +} + +/** + * ixgbe_init_eeprom_params_X540 - Initialize EEPROM params + * @hw: pointer to hardware structure + **/ +static s32 ixgbe_init_eeprom_params_X540(struct ixgbe_hw *hw) +{ + struct ixgbe_eeprom_info *eeprom = &hw->eeprom; + u32 eec; + u16 eeprom_size; + + if (eeprom->type == ixgbe_eeprom_uninitialized) { + eeprom->semaphore_delay = 10; + eeprom->type = ixgbe_flash; + + eec = IXGBE_READ_REG(hw, IXGBE_EEC); + eeprom_size = (u16)((eec & IXGBE_EEC_SIZE) >> + IXGBE_EEC_SIZE_SHIFT); + eeprom->word_size = 1 << (eeprom_size + + IXGBE_EEPROM_WORD_SIZE_SHIFT); + + hw_dbg(hw, "Eeprom params: type = %d, size = %d\n", + eeprom->type, eeprom->word_size); + } + + return 0; +} + +/** + * ixgbe_read_eerd_X540 - Read EEPROM word using EERD + * @hw: pointer to hardware structure + * @offset: offset of word in the EEPROM to read + * @data: word read from the EERPOM + **/ +static s32 ixgbe_read_eerd_X540(struct ixgbe_hw *hw, u16 offset, u16 *data) +{ + s32 status; + + if (ixgbe_acquire_swfw_sync_X540(hw, IXGBE_GSSR_EEP_SM)) + status = ixgbe_read_eerd_generic(hw, offset, data); + else + status = IXGBE_ERR_SWFW_SYNC; + + ixgbe_release_swfw_sync_X540(hw, IXGBE_GSSR_EEP_SM); + return status; +} + +/** + * ixgbe_write_eewr_X540 - Write EEPROM word using EEWR + * @hw: pointer to hardware structure + * @offset: offset of word in the EEPROM to write + * @data: word write to the EEPROM + * + * Write a 16 bit word to the EEPROM using the EEWR register. + **/ +static s32 ixgbe_write_eewr_X540(struct ixgbe_hw *hw, u16 offset, u16 data) +{ + u32 eewr; + s32 status; + + hw->eeprom.ops.init_params(hw); + + if (offset >= hw->eeprom.word_size) { + status = IXGBE_ERR_EEPROM; + goto out; + } + + eewr = (offset << IXGBE_EEPROM_RW_ADDR_SHIFT) | + (data << IXGBE_EEPROM_RW_REG_DATA) | + IXGBE_EEPROM_RW_REG_START; + + if (ixgbe_acquire_swfw_sync_X540(hw, IXGBE_GSSR_EEP_SM)) { + status = ixgbe_poll_eerd_eewr_done(hw, IXGBE_NVM_POLL_WRITE); + if (status != 0) { + hw_dbg(hw, "Eeprom write EEWR timed out\n"); + goto out; + } + + IXGBE_WRITE_REG(hw, IXGBE_EEWR, eewr); + + status = ixgbe_poll_eerd_eewr_done(hw, IXGBE_NVM_POLL_WRITE); + if (status != 0) { + hw_dbg(hw, "Eeprom write EEWR timed out\n"); + goto out; + } + } else { + status = IXGBE_ERR_SWFW_SYNC; + } + +out: + ixgbe_release_swfw_sync_X540(hw, IXGBE_GSSR_EEP_SM); + return status; +} + +/** + * ixgbe_calc_eeprom_checksum_X540 - Calculates and returns the checksum + * @hw: pointer to hardware structure + **/ +static u16 ixgbe_calc_eeprom_checksum_X540(struct ixgbe_hw *hw) +{ + u16 i; + u16 j; + u16 checksum = 0; + u16 length = 0; + u16 pointer = 0; + u16 word = 0; + + /* Include 0x0-0x3F in the checksum */ + for (i = 0; i < IXGBE_EEPROM_CHECKSUM; i++) { + if (hw->eeprom.ops.read(hw, i, &word) != 0) { + hw_dbg(hw, "EEPROM read failed\n"); + break; + } + checksum += word; + } + + /* + * Include all data from pointers 0x3, 0x6-0xE. This excludes the + * FW, PHY module, and PCIe Expansion/Option ROM pointers. + */ + for (i = IXGBE_PCIE_ANALOG_PTR; i < IXGBE_FW_PTR; i++) { + if (i == IXGBE_PHY_PTR || i == IXGBE_OPTION_ROM_PTR) + continue; + + if (hw->eeprom.ops.read(hw, i, &pointer) != 0) { + hw_dbg(hw, "EEPROM read failed\n"); + break; + } + + /* Skip pointer section if the pointer is invalid. */ + if (pointer == 0xFFFF || pointer == 0 || + pointer >= hw->eeprom.word_size) + continue; + + if (hw->eeprom.ops.read(hw, pointer, &length) != 0) { + hw_dbg(hw, "EEPROM read failed\n"); + break; + } + + /* Skip pointer section if length is invalid. */ + if (length == 0xFFFF || length == 0 || + (pointer + length) >= hw->eeprom.word_size) + continue; + + for (j = pointer+1; j <= pointer+length; j++) { + if (hw->eeprom.ops.read(hw, j, &word) != 0) { + hw_dbg(hw, "EEPROM read failed\n"); + break; + } + checksum += word; + } + } + + checksum = (u16)IXGBE_EEPROM_SUM - checksum; + + return checksum; +} + +/** + * ixgbe_update_eeprom_checksum_X540 - Updates the EEPROM checksum and flash + * @hw: pointer to hardware structure + * + * After writing EEPROM to shadow RAM using EEWR register, software calculates + * checksum and updates the EEPROM and instructs the hardware to update + * the flash. + **/ +static s32 ixgbe_update_eeprom_checksum_X540(struct ixgbe_hw *hw) +{ + s32 status; + + status = ixgbe_update_eeprom_checksum_generic(hw); + + if (status) + status = ixgbe_update_flash_X540(hw); + + return status; +} + +/** + * ixgbe_update_flash_X540 - Instruct HW to copy EEPROM to Flash device + * @hw: pointer to hardware structure + * + * Set FLUP (bit 23) of the EEC register to instruct Hardware to copy + * EEPROM from shadow RAM to the flash device. + **/ +static s32 ixgbe_update_flash_X540(struct ixgbe_hw *hw) +{ + u32 flup; + s32 status = IXGBE_ERR_EEPROM; + + status = ixgbe_poll_flash_update_done_X540(hw); + if (status == IXGBE_ERR_EEPROM) { + hw_dbg(hw, "Flash update time out\n"); + goto out; + } + + flup = IXGBE_READ_REG(hw, IXGBE_EEC) | IXGBE_EEC_FLUP; + IXGBE_WRITE_REG(hw, IXGBE_EEC, flup); + + status = ixgbe_poll_flash_update_done_X540(hw); + if (status) + hw_dbg(hw, "Flash update complete\n"); + else + hw_dbg(hw, "Flash update time out\n"); + + if (hw->revision_id == 0) { + flup = IXGBE_READ_REG(hw, IXGBE_EEC); + + if (flup & IXGBE_EEC_SEC1VAL) { + flup |= IXGBE_EEC_FLUP; + IXGBE_WRITE_REG(hw, IXGBE_EEC, flup); + } + + status = ixgbe_poll_flash_update_done_X540(hw); + if (status) + hw_dbg(hw, "Flash update complete\n"); + else + hw_dbg(hw, "Flash update time out\n"); + + } +out: + return status; +} + +/** + * ixgbe_poll_flash_update_done_X540 - Poll flash update status + * @hw: pointer to hardware structure + * + * Polls the FLUDONE (bit 26) of the EEC Register to determine when the + * flash update is done. + **/ +static s32 ixgbe_poll_flash_update_done_X540(struct ixgbe_hw *hw) +{ + u32 i; + u32 reg; + s32 status = IXGBE_ERR_EEPROM; + + for (i = 0; i < IXGBE_FLUDONE_ATTEMPTS; i++) { + reg = IXGBE_READ_REG(hw, IXGBE_EEC); + if (reg & IXGBE_EEC_FLUDONE) { + status = 0; + break; + } + udelay(5); + } + return status; +} + +/** + * ixgbe_acquire_swfw_sync_X540 - Acquire SWFW semaphore + * @hw: pointer to hardware structure + * @mask: Mask to specify which semaphore to acquire + * + * Acquires the SWFW semaphore thought the SW_FW_SYNC register for + * the specified function (CSR, PHY0, PHY1, NVM, Flash) + **/ +static s32 ixgbe_acquire_swfw_sync_X540(struct ixgbe_hw *hw, u16 mask) +{ + u32 swfw_sync; + u32 swmask = mask; + u32 fwmask = mask << 5; + u32 hwmask = 0; + u32 timeout = 200; + u32 i; + + if (swmask == IXGBE_GSSR_EEP_SM) + hwmask = IXGBE_GSSR_FLASH_SM; + + for (i = 0; i < timeout; i++) { + /* + * SW NVM semaphore bit is used for access to all + * SW_FW_SYNC bits (not just NVM) + */ + if (ixgbe_get_swfw_sync_semaphore(hw)) + return IXGBE_ERR_SWFW_SYNC; + + swfw_sync = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC); + if (!(swfw_sync & (fwmask | swmask | hwmask))) { + swfw_sync |= swmask; + IXGBE_WRITE_REG(hw, IXGBE_SWFW_SYNC, swfw_sync); + ixgbe_release_swfw_sync_semaphore(hw); + break; + } else { + /* + * Firmware currently using resource (fwmask), + * hardware currently using resource (hwmask), + * or other software thread currently using + * resource (swmask) + */ + ixgbe_release_swfw_sync_semaphore(hw); + msleep(5); + } + } + + /* + * If the resource is not released by the FW/HW the SW can assume that + * the FW/HW malfunctions. In that case the SW should sets the + * SW bit(s) of the requested resource(s) while ignoring the + * corresponding FW/HW bits in the SW_FW_SYNC register. + */ + if (i >= timeout) { + swfw_sync = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC); + if (swfw_sync & (fwmask | hwmask)) { + if (ixgbe_get_swfw_sync_semaphore(hw)) + return IXGBE_ERR_SWFW_SYNC; + + swfw_sync |= swmask; + IXGBE_WRITE_REG(hw, IXGBE_SWFW_SYNC, swfw_sync); + ixgbe_release_swfw_sync_semaphore(hw); + } + } + + msleep(5); + return 0; +} + +/** + * ixgbe_release_swfw_sync_X540 - Release SWFW semaphore + * @hw: pointer to hardware structure + * @mask: Mask to specify which semaphore to release + * + * Releases the SWFW semaphore throught the SW_FW_SYNC register + * for the specified function (CSR, PHY0, PHY1, EVM, Flash) + **/ +static void ixgbe_release_swfw_sync_X540(struct ixgbe_hw *hw, u16 mask) +{ + u32 swfw_sync; + u32 swmask = mask; + + ixgbe_get_swfw_sync_semaphore(hw); + + swfw_sync = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC); + swfw_sync &= ~swmask; + IXGBE_WRITE_REG(hw, IXGBE_SWFW_SYNC, swfw_sync); + + ixgbe_release_swfw_sync_semaphore(hw); + msleep(5); +} + +/** + * ixgbe_get_nvm_semaphore - Get hardware semaphore + * @hw: pointer to hardware structure + * + * Sets the hardware semaphores so SW/FW can gain control of shared resources + **/ +static s32 ixgbe_get_swfw_sync_semaphore(struct ixgbe_hw *hw) +{ + s32 status = IXGBE_ERR_EEPROM; + u32 timeout = 2000; + u32 i; + u32 swsm; + + /* Get SMBI software semaphore between device drivers first */ + for (i = 0; i < timeout; i++) { + /* + * If the SMBI bit is 0 when we read it, then the bit will be + * set and we have the semaphore + */ + swsm = IXGBE_READ_REG(hw, IXGBE_SWSM); + if (!(swsm & IXGBE_SWSM_SMBI)) { + status = 0; + break; + } + udelay(50); + } + + /* Now get the semaphore between SW/FW through the REGSMP bit */ + if (status) { + for (i = 0; i < timeout; i++) { + swsm = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC); + if (!(swsm & IXGBE_SWFW_REGSMP)) + break; + + udelay(50); + } + } else { + hw_dbg(hw, "Software semaphore SMBI between device drivers " + "not granted.\n"); + } + + return status; +} + +/** + * ixgbe_release_nvm_semaphore - Release hardware semaphore + * @hw: pointer to hardware structure + * + * This function clears hardware semaphore bits. + **/ +static void ixgbe_release_swfw_sync_semaphore(struct ixgbe_hw *hw) +{ + u32 swsm; + + /* Release both semaphores by writing 0 to the bits REGSMP and SMBI */ + + swsm = IXGBE_READ_REG(hw, IXGBE_SWSM); + swsm &= ~IXGBE_SWSM_SMBI; + IXGBE_WRITE_REG(hw, IXGBE_SWSM, swsm); + + swsm = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC); + swsm &= ~IXGBE_SWFW_REGSMP; + IXGBE_WRITE_REG(hw, IXGBE_SWFW_SYNC, swsm); + + IXGBE_WRITE_FLUSH(hw); +} + +static struct ixgbe_mac_operations mac_ops_X540 = { + .init_hw = &ixgbe_init_hw_generic, + .reset_hw = &ixgbe_reset_hw_X540, + .start_hw = &ixgbe_start_hw_generic, + .clear_hw_cntrs = &ixgbe_clear_hw_cntrs_generic, + .get_media_type = &ixgbe_get_media_type_X540, + .get_supported_physical_layer = + &ixgbe_get_supported_physical_layer_X540, + .enable_rx_dma = &ixgbe_enable_rx_dma_generic, + .get_mac_addr = &ixgbe_get_mac_addr_generic, + .get_san_mac_addr = &ixgbe_get_san_mac_addr_generic, + .get_device_caps = NULL, + .get_wwn_prefix = &ixgbe_get_wwn_prefix_generic, + .stop_adapter = &ixgbe_stop_adapter_generic, + .get_bus_info = &ixgbe_get_bus_info_generic, + .set_lan_id = &ixgbe_set_lan_id_multi_port_pcie, + .read_analog_reg8 = NULL, + .write_analog_reg8 = NULL, + .setup_link = &ixgbe_setup_mac_link_X540, + .check_link = &ixgbe_check_mac_link_generic, + .get_link_capabilities = &ixgbe_get_copper_link_capabilities_generic, + .led_on = &ixgbe_led_on_generic, + .led_off = &ixgbe_led_off_generic, + .blink_led_start = &ixgbe_blink_led_start_generic, + .blink_led_stop = &ixgbe_blink_led_stop_generic, + .set_rar = &ixgbe_set_rar_generic, + .clear_rar = &ixgbe_clear_rar_generic, + .set_vmdq = &ixgbe_set_vmdq_generic, + .clear_vmdq = &ixgbe_clear_vmdq_generic, + .init_rx_addrs = &ixgbe_init_rx_addrs_generic, + .update_uc_addr_list = &ixgbe_update_uc_addr_list_generic, + .update_mc_addr_list = &ixgbe_update_mc_addr_list_generic, + .enable_mc = &ixgbe_enable_mc_generic, + .disable_mc = &ixgbe_disable_mc_generic, + .clear_vfta = &ixgbe_clear_vfta_generic, + .set_vfta = &ixgbe_set_vfta_generic, + .fc_enable = &ixgbe_fc_enable_generic, + .init_uta_tables = &ixgbe_init_uta_tables_generic, + .setup_sfp = NULL, +}; + +static struct ixgbe_eeprom_operations eeprom_ops_X540 = { + .init_params = &ixgbe_init_eeprom_params_X540, + .read = &ixgbe_read_eerd_X540, + .write = &ixgbe_write_eewr_X540, + .calc_checksum = &ixgbe_calc_eeprom_checksum_X540, + .validate_checksum = &ixgbe_validate_eeprom_checksum_generic, + .update_checksum = &ixgbe_update_eeprom_checksum_X540, +}; + +static struct ixgbe_phy_operations phy_ops_X540 = { + .identify = &ixgbe_identify_phy_generic, + .identify_sfp = &ixgbe_identify_sfp_module_generic, + .init = NULL, + .reset = &ixgbe_reset_phy_generic, + .read_reg = &ixgbe_read_phy_reg_generic, + .write_reg = &ixgbe_write_phy_reg_generic, + .setup_link = &ixgbe_setup_phy_link_generic, + .setup_link_speed = &ixgbe_setup_phy_link_speed_generic, + .read_i2c_byte = &ixgbe_read_i2c_byte_generic, + .write_i2c_byte = &ixgbe_write_i2c_byte_generic, + .read_i2c_eeprom = &ixgbe_read_i2c_eeprom_generic, + .write_i2c_eeprom = &ixgbe_write_i2c_eeprom_generic, + .check_overtemp = &ixgbe_tn_check_overtemp, +}; + +struct ixgbe_info ixgbe_X540_info = { + .mac = ixgbe_mac_X540, + .get_invariants = &ixgbe_get_invariants_X540, + .mac_ops = &mac_ops_X540, + .eeprom_ops = &eeprom_ops_X540, + .phy_ops = &phy_ops_X540, + .mbx_ops = &mbx_ops_generic, +}; diff --git a/drivers/net/ixgbevf/Makefile b/drivers/net/ixgbevf/Makefile index dd4e0d27e8cc..1f35d229e71a 100644 --- a/drivers/net/ixgbevf/Makefile +++ b/drivers/net/ixgbevf/Makefile @@ -1,7 +1,7 @@ ################################################################################ # # Intel 82599 Virtual Function driver -# Copyright(c) 1999 - 2009 Intel Corporation. +# Copyright(c) 1999 - 2010 Intel Corporation. # # This program is free software; you can redistribute it and/or modify it # under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ixgbevf/defines.h b/drivers/net/ixgbevf/defines.h index ca2c81f49a05..f8a807d606c7 100644 --- a/drivers/net/ixgbevf/defines.h +++ b/drivers/net/ixgbevf/defines.h @@ -1,7 +1,7 @@ /******************************************************************************* Intel 82599 Virtual Function driver - Copyright(c) 1999 - 2009 Intel Corporation. + Copyright(c) 1999 - 2010 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ixgbevf/ixgbevf.h b/drivers/net/ixgbevf/ixgbevf.h index da4033c6efa2..0cd6abcf9306 100644 --- a/drivers/net/ixgbevf/ixgbevf.h +++ b/drivers/net/ixgbevf/ixgbevf.h @@ -1,7 +1,7 @@ /******************************************************************************* Intel 82599 Virtual Function driver - Copyright(c) 1999 - 2009 Intel Corporation. + Copyright(c) 1999 - 2010 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ixgbevf/ixgbevf_main.c b/drivers/net/ixgbevf/ixgbevf_main.c index dc03c9652389..2216a3c8b12b 100644 --- a/drivers/net/ixgbevf/ixgbevf_main.c +++ b/drivers/net/ixgbevf/ixgbevf_main.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel 82599 Virtual Function driver - Copyright(c) 1999 - 2009 Intel Corporation. + Copyright(c) 1999 - 2010 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, @@ -51,9 +51,10 @@ char ixgbevf_driver_name[] = "ixgbevf"; static const char ixgbevf_driver_string[] = "Intel(R) 82599 Virtual Function"; -#define DRV_VERSION "1.0.0-k0" +#define DRV_VERSION "1.0.12-k0" const char ixgbevf_driver_version[] = DRV_VERSION; -static char ixgbevf_copyright[] = "Copyright (c) 2009 Intel Corporation."; +static char ixgbevf_copyright[] = + "Copyright (c) 2009 - 2010 Intel Corporation."; static const struct ixgbevf_info *ixgbevf_info_tbl[] = { [board_82599_vf] = &ixgbevf_vf_info, @@ -2488,10 +2489,9 @@ int ixgbevf_setup_tx_resources(struct ixgbevf_adapter *adapter, int size; size = sizeof(struct ixgbevf_tx_buffer) * tx_ring->count; - tx_ring->tx_buffer_info = vmalloc(size); + tx_ring->tx_buffer_info = vzalloc(size); if (!tx_ring->tx_buffer_info) goto err; - memset(tx_ring->tx_buffer_info, 0, size); /* round up to nearest 4K */ tx_ring->size = tx_ring->count * sizeof(union ixgbe_adv_tx_desc); @@ -2555,14 +2555,13 @@ int ixgbevf_setup_rx_resources(struct ixgbevf_adapter *adapter, int size; size = sizeof(struct ixgbevf_rx_buffer) * rx_ring->count; - rx_ring->rx_buffer_info = vmalloc(size); + rx_ring->rx_buffer_info = vzalloc(size); if (!rx_ring->rx_buffer_info) { hw_dbg(&adapter->hw, "Unable to vmalloc buffer memory for " "the receive descriptor ring\n"); goto alloc_failed; } - memset(rx_ring->rx_buffer_info, 0, size); /* Round up to nearest 4K */ rx_ring->size = rx_ring->count * sizeof(union ixgbe_adv_rx_desc); @@ -3424,10 +3423,6 @@ static int __devinit ixgbevf_probe(struct pci_dev *pdev, if (hw->mac.ops.get_bus_info) hw->mac.ops.get_bus_info(hw); - - netif_carrier_off(netdev); - netif_tx_stop_all_queues(netdev); - strcpy(netdev->name, "eth%d"); err = register_netdev(netdev); @@ -3436,6 +3431,8 @@ static int __devinit ixgbevf_probe(struct pci_dev *pdev, adapter->netdev_registered = true; + netif_carrier_off(netdev); + ixgbevf_init_last_counter_stats(adapter); /* print the MAC address */ diff --git a/drivers/net/ixgbevf/mbx.c b/drivers/net/ixgbevf/mbx.c index 84ac486f4a65..7a8833125770 100644 --- a/drivers/net/ixgbevf/mbx.c +++ b/drivers/net/ixgbevf/mbx.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel 82599 Virtual Function driver - Copyright(c) 1999 - 2009 Intel Corporation. + Copyright(c) 1999 - 2010 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ixgbevf/mbx.h b/drivers/net/ixgbevf/mbx.h index 8c063bebee7f..b2b5bf5daa3d 100644 --- a/drivers/net/ixgbevf/mbx.h +++ b/drivers/net/ixgbevf/mbx.h @@ -1,7 +1,7 @@ /******************************************************************************* Intel 82599 Virtual Function driver - Copyright(c) 1999 - 2009 Intel Corporation. + Copyright(c) 1999 - 2010 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ixgbevf/regs.h b/drivers/net/ixgbevf/regs.h index 12f75960aec1..fb80ca1bcc93 100644 --- a/drivers/net/ixgbevf/regs.h +++ b/drivers/net/ixgbevf/regs.h @@ -1,7 +1,7 @@ /******************************************************************************* Intel 82599 Virtual Function driver - Copyright(c) 1999 - 2009 Intel Corporation. + Copyright(c) 1999 - 2010 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ixgbevf/vf.c b/drivers/net/ixgbevf/vf.c index bfe42c1fcfaf..971019d819b4 100644 --- a/drivers/net/ixgbevf/vf.c +++ b/drivers/net/ixgbevf/vf.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel 82599 Virtual Function driver - Copyright(c) 1999 - 2009 Intel Corporation. + Copyright(c) 1999 - 2010 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ixgbevf/vf.h b/drivers/net/ixgbevf/vf.h index 61f9dc831424..144c99d5363a 100644 --- a/drivers/net/ixgbevf/vf.h +++ b/drivers/net/ixgbevf/vf.h @@ -1,7 +1,7 @@ /******************************************************************************* Intel 82599 Virtual Function driver - Copyright(c) 1999 - 2009 Intel Corporation. + Copyright(c) 1999 - 2010 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/jme.c b/drivers/net/jme.c index d85edf3119c2..c57d9a43ceca 100644 --- a/drivers/net/jme.c +++ b/drivers/net/jme.c @@ -2955,11 +2955,7 @@ jme_init_one(struct pci_dev *pdev, * Tell stack that we are not ready to work until open() */ netif_carrier_off(netdev); - netif_stop_queue(netdev); - /* - * Register netdev - */ rc = register_netdev(netdev); if (rc) { pr_err("Cannot register net device\n"); diff --git a/drivers/net/ks8851.c b/drivers/net/ks8851.c index 51919fcd50c2..0fa4a9887ba2 100644 --- a/drivers/net/ks8851.c +++ b/drivers/net/ks8851.c @@ -1545,6 +1545,37 @@ static int ks8851_read_selftest(struct ks8851_net *ks) /* driver bus management functions */ +#ifdef CONFIG_PM +static int ks8851_suspend(struct spi_device *spi, pm_message_t state) +{ + struct ks8851_net *ks = dev_get_drvdata(&spi->dev); + struct net_device *dev = ks->netdev; + + if (netif_running(dev)) { + netif_device_detach(dev); + ks8851_net_stop(dev); + } + + return 0; +} + +static int ks8851_resume(struct spi_device *spi) +{ + struct ks8851_net *ks = dev_get_drvdata(&spi->dev); + struct net_device *dev = ks->netdev; + + if (netif_running(dev)) { + ks8851_net_open(dev); + netif_device_attach(dev); + } + + return 0; +} +#else +#define ks8851_suspend NULL +#define ks8851_resume NULL +#endif + static int __devinit ks8851_probe(struct spi_device *spi) { struct net_device *ndev; @@ -1679,6 +1710,8 @@ static struct spi_driver ks8851_driver = { }, .probe = ks8851_probe, .remove = __devexit_p(ks8851_remove), + .suspend = ks8851_suspend, + .resume = ks8851_resume, }; static int __init ks8851_init(void) diff --git a/drivers/net/lance.c b/drivers/net/lance.c index f06296bfe293..02336edce748 100644 --- a/drivers/net/lance.c +++ b/drivers/net/lance.c @@ -207,7 +207,7 @@ tx_full and tbusy flags. #define LANCE_BUS_IF 0x16 #define LANCE_TOTAL_SIZE 0x18 -#define TX_TIMEOUT 20 +#define TX_TIMEOUT (HZ/5) /* The LANCE Rx and Tx ring descriptors. */ struct lance_rx_head { diff --git a/drivers/net/lib82596.c b/drivers/net/lib82596.c index c27f4291b350..9e042894479b 100644 --- a/drivers/net/lib82596.c +++ b/drivers/net/lib82596.c @@ -161,7 +161,7 @@ enum commands { #define RX_SUSPEND 0x0030 #define RX_ABORT 0x0040 -#define TX_TIMEOUT 5 +#define TX_TIMEOUT (HZ/20) struct i596_reg { diff --git a/drivers/net/lib8390.c b/drivers/net/lib8390.c index e7030ceb178b..da74db4a03d4 100644 --- a/drivers/net/lib8390.c +++ b/drivers/net/lib8390.c @@ -203,7 +203,7 @@ static void __NS8390_init(struct net_device *dev, int startp); static int __ei_open(struct net_device *dev) { unsigned long flags; - struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev); + struct ei_device *ei_local = netdev_priv(dev); if (dev->watchdog_timeo <= 0) dev->watchdog_timeo = TX_TIMEOUT; @@ -231,7 +231,7 @@ static int __ei_open(struct net_device *dev) */ static int __ei_close(struct net_device *dev) { - struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev); + struct ei_device *ei_local = netdev_priv(dev); unsigned long flags; /* @@ -256,7 +256,7 @@ static int __ei_close(struct net_device *dev) static void __ei_tx_timeout(struct net_device *dev) { unsigned long e8390_base = dev->base_addr; - struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev); + struct ei_device *ei_local = netdev_priv(dev); int txsr, isr, tickssofar = jiffies - dev_trans_start(dev); unsigned long flags; @@ -303,7 +303,7 @@ static netdev_tx_t __ei_start_xmit(struct sk_buff *skb, struct net_device *dev) { unsigned long e8390_base = dev->base_addr; - struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev); + struct ei_device *ei_local = netdev_priv(dev); int send_length = skb->len, output_page; unsigned long flags; char buf[ETH_ZLEN]; @@ -592,7 +592,7 @@ static void ei_tx_err(struct net_device *dev) static void ei_tx_intr(struct net_device *dev) { unsigned long e8390_base = dev->base_addr; - struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev); + struct ei_device *ei_local = netdev_priv(dev); int status = ei_inb(e8390_base + EN0_TSR); ei_outb_p(ENISR_TX, e8390_base + EN0_ISR); /* Ack intr. */ @@ -675,7 +675,7 @@ static void ei_tx_intr(struct net_device *dev) static void ei_receive(struct net_device *dev) { unsigned long e8390_base = dev->base_addr; - struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev); + struct ei_device *ei_local = netdev_priv(dev); unsigned char rxing_page, this_frame, next_frame; unsigned short current_offset; int rx_pkt_count = 0; @@ -879,7 +879,7 @@ static void ei_rx_overrun(struct net_device *dev) static struct net_device_stats *__ei_get_stats(struct net_device *dev) { unsigned long ioaddr = dev->base_addr; - struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev); + struct ei_device *ei_local = netdev_priv(dev); unsigned long flags; /* If the card is stopped, just return the present stats. */ @@ -927,7 +927,7 @@ static void do_set_multicast_list(struct net_device *dev) { unsigned long e8390_base = dev->base_addr; int i; - struct ei_device *ei_local = (struct ei_device*)netdev_priv(dev); + struct ei_device *ei_local = netdev_priv(dev); if (!(dev->flags&(IFF_PROMISC|IFF_ALLMULTI))) { @@ -981,7 +981,7 @@ static void do_set_multicast_list(struct net_device *dev) static void __ei_set_multicast_list(struct net_device *dev) { unsigned long flags; - struct ei_device *ei_local = (struct ei_device*)netdev_priv(dev); + struct ei_device *ei_local = netdev_priv(dev); spin_lock_irqsave(&ei_local->page_lock, flags); do_set_multicast_list(dev); @@ -998,7 +998,7 @@ static void __ei_set_multicast_list(struct net_device *dev) static void ethdev_setup(struct net_device *dev) { - struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev); + struct ei_device *ei_local = netdev_priv(dev); if (ei_debug > 1) printk(version); @@ -1036,7 +1036,7 @@ static struct net_device *____alloc_ei_netdev(int size) static void __NS8390_init(struct net_device *dev, int startp) { unsigned long e8390_base = dev->base_addr; - struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev); + struct ei_device *ei_local = netdev_priv(dev); int i; int endcfg = ei_local->word16 ? (0x48 | ENDCFG_WTS | (ei_local->bigendian ? ENDCFG_BOS : 0)) @@ -1099,7 +1099,7 @@ static void NS8390_trigger_send(struct net_device *dev, unsigned int length, int start_page) { unsigned long e8390_base = dev->base_addr; - struct ei_device *ei_local __attribute((unused)) = (struct ei_device *) netdev_priv(dev); + struct ei_device *ei_local __attribute((unused)) = netdev_priv(dev); ei_outb_p(E8390_NODMA+E8390_PAGE0, e8390_base+E8390_CMD); diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c index 0fc9dc7f20db..6ed577b065df 100644 --- a/drivers/net/macvlan.c +++ b/drivers/net/macvlan.c @@ -38,6 +38,7 @@ struct macvlan_port { struct hlist_head vlan_hash[MACVLAN_HASH_SIZE]; struct list_head vlans; struct rcu_head rcu; + bool passthru; }; #define macvlan_port_get_rcu(dev) \ @@ -169,6 +170,7 @@ static struct sk_buff *macvlan_handle_frame(struct sk_buff *skb) macvlan_broadcast(skb, port, NULL, MACVLAN_MODE_PRIVATE | MACVLAN_MODE_VEPA | + MACVLAN_MODE_PASSTHRU| MACVLAN_MODE_BRIDGE); else if (src->mode == MACVLAN_MODE_VEPA) /* flood to everyone except source */ @@ -185,7 +187,10 @@ static struct sk_buff *macvlan_handle_frame(struct sk_buff *skb) return skb; } - vlan = macvlan_hash_lookup(port, eth->h_dest); + if (port->passthru) + vlan = list_first_entry(&port->vlans, struct macvlan_dev, list); + else + vlan = macvlan_hash_lookup(port, eth->h_dest); if (vlan == NULL) return skb; @@ -243,18 +248,22 @@ xmit_world: netdev_tx_t macvlan_start_xmit(struct sk_buff *skb, struct net_device *dev) { - int i = skb_get_queue_mapping(skb); - struct netdev_queue *txq = netdev_get_tx_queue(dev, i); unsigned int len = skb->len; int ret; + const struct macvlan_dev *vlan = netdev_priv(dev); ret = macvlan_queue_xmit(skb, dev); if (likely(ret == NET_XMIT_SUCCESS || ret == NET_XMIT_CN)) { - txq->tx_packets++; - txq->tx_bytes += len; - } else - txq->tx_dropped++; + struct macvlan_pcpu_stats *pcpu_stats; + pcpu_stats = this_cpu_ptr(vlan->pcpu_stats); + u64_stats_update_begin(&pcpu_stats->syncp); + pcpu_stats->tx_packets++; + pcpu_stats->tx_bytes += len; + u64_stats_update_end(&pcpu_stats->syncp); + } else { + this_cpu_inc(vlan->pcpu_stats->tx_dropped); + } return ret; } EXPORT_SYMBOL_GPL(macvlan_start_xmit); @@ -284,6 +293,11 @@ static int macvlan_open(struct net_device *dev) struct net_device *lowerdev = vlan->lowerdev; int err; + if (vlan->port->passthru) { + dev_set_promiscuity(lowerdev, 1); + goto hash_add; + } + err = -EBUSY; if (macvlan_addr_busy(vlan->port, dev->dev_addr)) goto out; @@ -296,6 +310,8 @@ static int macvlan_open(struct net_device *dev) if (err < 0) goto del_unicast; } + +hash_add: macvlan_hash_add(vlan); return 0; @@ -310,12 +326,18 @@ static int macvlan_stop(struct net_device *dev) struct macvlan_dev *vlan = netdev_priv(dev); struct net_device *lowerdev = vlan->lowerdev; + if (vlan->port->passthru) { + dev_set_promiscuity(lowerdev, -1); + goto hash_del; + } + dev_mc_unsync(lowerdev, dev); if (dev->flags & IFF_ALLMULTI) dev_set_allmulti(lowerdev, -1); dev_uc_del(lowerdev, dev->dev_addr); +hash_del: macvlan_hash_del(vlan); return 0; } @@ -414,14 +436,15 @@ static int macvlan_init(struct net_device *dev) dev->state = (dev->state & ~MACVLAN_STATE_MASK) | (lowerdev->state & MACVLAN_STATE_MASK); dev->features = lowerdev->features & MACVLAN_FEATURES; + dev->features |= NETIF_F_LLTX; dev->gso_max_size = lowerdev->gso_max_size; dev->iflink = lowerdev->ifindex; dev->hard_header_len = lowerdev->hard_header_len; macvlan_set_lockdep_class(dev); - vlan->rx_stats = alloc_percpu(struct macvlan_rx_stats); - if (!vlan->rx_stats) + vlan->pcpu_stats = alloc_percpu(struct macvlan_pcpu_stats); + if (!vlan->pcpu_stats) return -ENOMEM; return 0; @@ -431,7 +454,7 @@ static void macvlan_uninit(struct net_device *dev) { struct macvlan_dev *vlan = netdev_priv(dev); - free_percpu(vlan->rx_stats); + free_percpu(vlan->pcpu_stats); } static struct rtnl_link_stats64 *macvlan_dev_get_stats64(struct net_device *dev, @@ -439,33 +462,38 @@ static struct rtnl_link_stats64 *macvlan_dev_get_stats64(struct net_device *dev, { struct macvlan_dev *vlan = netdev_priv(dev); - dev_txq_stats_fold(dev, stats); - - if (vlan->rx_stats) { - struct macvlan_rx_stats *p, accum = {0}; - u64 rx_packets, rx_bytes, rx_multicast; + if (vlan->pcpu_stats) { + struct macvlan_pcpu_stats *p; + u64 rx_packets, rx_bytes, rx_multicast, tx_packets, tx_bytes; + u32 rx_errors = 0, tx_dropped = 0; unsigned int start; int i; for_each_possible_cpu(i) { - p = per_cpu_ptr(vlan->rx_stats, i); + p = per_cpu_ptr(vlan->pcpu_stats, i); do { start = u64_stats_fetch_begin_bh(&p->syncp); rx_packets = p->rx_packets; rx_bytes = p->rx_bytes; rx_multicast = p->rx_multicast; + tx_packets = p->tx_packets; + tx_bytes = p->tx_bytes; } while (u64_stats_fetch_retry_bh(&p->syncp, start)); - accum.rx_packets += rx_packets; - accum.rx_bytes += rx_bytes; - accum.rx_multicast += rx_multicast; - /* rx_errors is an ulong, updated without syncp protection */ - accum.rx_errors += p->rx_errors; + + stats->rx_packets += rx_packets; + stats->rx_bytes += rx_bytes; + stats->multicast += rx_multicast; + stats->tx_packets += tx_packets; + stats->tx_bytes += tx_bytes; + /* rx_errors & tx_dropped are u32, updated + * without syncp protection. + */ + rx_errors += p->rx_errors; + tx_dropped += p->tx_dropped; } - stats->rx_packets = accum.rx_packets; - stats->rx_bytes = accum.rx_bytes; - stats->rx_errors = accum.rx_errors; - stats->rx_dropped = accum.rx_errors; - stats->multicast = accum.rx_multicast; + stats->rx_errors = rx_errors; + stats->rx_dropped = rx_errors; + stats->tx_dropped = tx_dropped; } return stats; } @@ -549,6 +577,7 @@ static int macvlan_port_create(struct net_device *dev) if (port == NULL) return -ENOMEM; + port->passthru = false; port->dev = dev; INIT_LIST_HEAD(&port->vlans); for (i = 0; i < MACVLAN_HASH_SIZE; i++) @@ -593,6 +622,7 @@ static int macvlan_validate(struct nlattr *tb[], struct nlattr *data[]) case MACVLAN_MODE_PRIVATE: case MACVLAN_MODE_VEPA: case MACVLAN_MODE_BRIDGE: + case MACVLAN_MODE_PASSTHRU: break; default: return -EINVAL; @@ -601,25 +631,6 @@ static int macvlan_validate(struct nlattr *tb[], struct nlattr *data[]) return 0; } -static int macvlan_get_tx_queues(struct net *net, - struct nlattr *tb[], - unsigned int *num_tx_queues, - unsigned int *real_num_tx_queues) -{ - struct net_device *real_dev; - - if (!tb[IFLA_LINK]) - return -EINVAL; - - real_dev = __dev_get_by_index(net, nla_get_u32(tb[IFLA_LINK])); - if (!real_dev) - return -ENODEV; - - *num_tx_queues = real_dev->num_tx_queues; - *real_num_tx_queues = real_dev->real_num_tx_queues; - return 0; -} - int macvlan_common_newlink(struct net *src_net, struct net_device *dev, struct nlattr *tb[], struct nlattr *data[], int (*receive)(struct sk_buff *skb), @@ -661,6 +672,10 @@ int macvlan_common_newlink(struct net *src_net, struct net_device *dev, } port = macvlan_port_get(lowerdev); + /* Only 1 macvlan device can be created in passthru mode */ + if (port->passthru) + return -EINVAL; + vlan->lowerdev = lowerdev; vlan->dev = dev; vlan->port = port; @@ -671,6 +686,13 @@ int macvlan_common_newlink(struct net *src_net, struct net_device *dev, if (data && data[IFLA_MACVLAN_MODE]) vlan->mode = nla_get_u32(data[IFLA_MACVLAN_MODE]); + if (vlan->mode == MACVLAN_MODE_PASSTHRU) { + if (!list_empty(&port->vlans)) + return -EINVAL; + port->passthru = true; + memcpy(dev->dev_addr, lowerdev->dev_addr, ETH_ALEN); + } + err = register_netdevice(dev); if (err < 0) goto destroy_port; @@ -743,7 +765,6 @@ int macvlan_link_register(struct rtnl_link_ops *ops) { /* common fields */ ops->priv_size = sizeof(struct macvlan_dev); - ops->get_tx_queues = macvlan_get_tx_queues; ops->validate = macvlan_validate; ops->maxtype = IFLA_MACVLAN_MAX; ops->policy = macvlan_policy; diff --git a/drivers/net/ne-h8300.c b/drivers/net/ne-h8300.c index e0b0ef11f110..30be8c634ebd 100644 --- a/drivers/net/ne-h8300.c +++ b/drivers/net/ne-h8300.c @@ -86,7 +86,7 @@ static u32 reg_offset[16]; static int __init init_reg_offset(struct net_device *dev,unsigned long base_addr) { - struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev); + struct ei_device *ei_local = netdev_priv(dev); int i; unsigned char bus_width; @@ -218,7 +218,7 @@ static int __init ne_probe1(struct net_device *dev, int ioaddr) int start_page, stop_page; int reg0, ret; static unsigned version_printed; - struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev); + struct ei_device *ei_local = netdev_priv(dev); unsigned char bus_width; if (!request_region(ioaddr, NE_IO_EXTENT, DRV_NAME)) @@ -371,7 +371,7 @@ static int ne_close(struct net_device *dev) static void ne_reset_8390(struct net_device *dev) { unsigned long reset_start_time = jiffies; - struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev); + struct ei_device *ei_local = netdev_priv(dev); if (ei_debug > 1) printk(KERN_DEBUG "resetting the 8390 t=%ld...", jiffies); @@ -397,7 +397,7 @@ static void ne_reset_8390(struct net_device *dev) static void ne_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page) { - struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev); + struct ei_device *ei_local = netdev_priv(dev); /* This *shouldn't* happen. If it does, it's the last thing you'll see */ if (ei_status.dmaing) @@ -437,7 +437,7 @@ static void ne_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, i static void ne_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset) { - struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev); + struct ei_device *ei_local = netdev_priv(dev); #ifdef NE_SANITY_CHECK int xfer_count = count; #endif @@ -507,7 +507,7 @@ static void ne_block_input(struct net_device *dev, int count, struct sk_buff *sk static void ne_block_output(struct net_device *dev, int count, const unsigned char *buf, const int start_page) { - struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev); + struct ei_device *ei_local = netdev_priv(dev); unsigned long dma_start; #ifdef NE_SANITY_CHECK int retries = 0; diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c index 95fe552aa279..731077d8d962 100644 --- a/drivers/net/netxen/netxen_nic_init.c +++ b/drivers/net/netxen/netxen_nic_init.c @@ -214,13 +214,12 @@ int netxen_alloc_sw_resources(struct netxen_adapter *adapter) tx_ring->num_desc = adapter->num_txd; tx_ring->txq = netdev_get_tx_queue(netdev, 0); - cmd_buf_arr = vmalloc(TX_BUFF_RINGSIZE(tx_ring)); + cmd_buf_arr = vzalloc(TX_BUFF_RINGSIZE(tx_ring)); if (cmd_buf_arr == NULL) { dev_err(&pdev->dev, "%s: failed to allocate cmd buffer ring\n", netdev->name); goto err_out; } - memset(cmd_buf_arr, 0, TX_BUFF_RINGSIZE(tx_ring)); tx_ring->cmd_buf_arr = cmd_buf_arr; recv_ctx = &adapter->recv_ctx; @@ -279,8 +278,7 @@ int netxen_alloc_sw_resources(struct netxen_adapter *adapter) break; } - rds_ring->rx_buf_arr = (struct netxen_rx_buffer *) - vmalloc(RCV_BUFF_RINGSIZE(rds_ring)); + rds_ring->rx_buf_arr = vzalloc(RCV_BUFF_RINGSIZE(rds_ring)); if (rds_ring->rx_buf_arr == NULL) { printk(KERN_ERR "%s: Failed to allocate " "rx buffer ring %d\n", @@ -288,7 +286,6 @@ int netxen_alloc_sw_resources(struct netxen_adapter *adapter) /* free whatever was already allocated */ goto err_out; } - memset(rds_ring->rx_buf_arr, 0, RCV_BUFF_RINGSIZE(rds_ring)); INIT_LIST_HEAD(&rds_ring->free_list); /* * Now go through all of them, set reference handles diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index a75ba9517404..ceeaac989df2 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -41,9 +41,6 @@ MODULE_DESCRIPTION("QLogic/NetXen (1/10) GbE Converged Ethernet Driver"); MODULE_LICENSE("GPL"); MODULE_VERSION(NETXEN_NIC_LINUX_VERSIONID); -MODULE_FIRMWARE(NX_P2_MN_ROMIMAGE_NAME); -MODULE_FIRMWARE(NX_P3_CT_ROMIMAGE_NAME); -MODULE_FIRMWARE(NX_P3_MN_ROMIMAGE_NAME); MODULE_FIRMWARE(NX_UNIFIED_ROMIMAGE_NAME); char netxen_nic_driver_name[] = "netxen_nic"; @@ -1280,6 +1277,7 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) int i = 0, err; int pci_func_id = PCI_FUNC(pdev->devfn); uint8_t revision_id; + u32 val; if (pdev->revision >= NX_P3_A0 && pdev->revision <= NX_P3_B1) { pr_warning("%s: chip revisions between 0x%x-0x%x " @@ -1355,8 +1353,9 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) break; } - if (reset_devices) { - if (adapter->portnum == 0) { + if (adapter->portnum == 0) { + val = NXRD32(adapter, NX_CRB_DEV_REF_COUNT); + if (val != 0xffffffff && val != 0) { NXWR32(adapter, NX_CRB_DEV_REF_COUNT, 0); adapter->need_fw_reset = 1; } diff --git a/drivers/net/pch_gbe/pch_gbe_main.c b/drivers/net/pch_gbe/pch_gbe_main.c index 472056b47440..afb75066b14d 100644 --- a/drivers/net/pch_gbe/pch_gbe_main.c +++ b/drivers/net/pch_gbe/pch_gbe_main.c @@ -1523,12 +1523,11 @@ int pch_gbe_setup_tx_resources(struct pch_gbe_adapter *adapter, int desNo; size = (int)sizeof(struct pch_gbe_buffer) * tx_ring->count; - tx_ring->buffer_info = vmalloc(size); + tx_ring->buffer_info = vzalloc(size); if (!tx_ring->buffer_info) { pr_err("Unable to allocate memory for the buffer infomation\n"); return -ENOMEM; } - memset(tx_ring->buffer_info, 0, size); tx_ring->size = tx_ring->count * (int)sizeof(struct pch_gbe_tx_desc); @@ -1573,12 +1572,11 @@ int pch_gbe_setup_rx_resources(struct pch_gbe_adapter *adapter, int desNo; size = (int)sizeof(struct pch_gbe_buffer) * rx_ring->count; - rx_ring->buffer_info = vmalloc(size); + rx_ring->buffer_info = vzalloc(size); if (!rx_ring->buffer_info) { pr_err("Unable to allocate memory for the receive descriptor ring\n"); return -ENOMEM; } - memset(rx_ring->buffer_info, 0, size); rx_ring->size = rx_ring->count * (int)sizeof(struct pch_gbe_rx_desc); rx_ring->desc = dma_alloc_coherent(&pdev->dev, rx_ring->size, &rx_ring->dma, GFP_KERNEL); diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c index d2e166e29dda..1a0eb128e607 100644 --- a/drivers/net/pcmcia/axnet_cs.c +++ b/drivers/net/pcmcia/axnet_cs.c @@ -111,13 +111,14 @@ static irqreturn_t ax_interrupt(int irq, void *dev_id); typedef struct axnet_dev_t { struct pcmcia_device *p_dev; - caddr_t base; - struct timer_list watchdog; - int stale, fast_poll; - u_short link_status; - u_char duplex_flag; - int phy_id; - int flags; + caddr_t base; + struct timer_list watchdog; + int stale, fast_poll; + u_short link_status; + u_char duplex_flag; + int phy_id; + int flags; + int active_low; } axnet_dev_t; static inline axnet_dev_t *PRIV(struct net_device *dev) @@ -322,6 +323,8 @@ static int axnet_config(struct pcmcia_device *link) if (info->flags & IS_AX88790) outb(0x10, dev->base_addr + AXNET_GPIO); /* select Internal PHY */ + info->active_low = 0; + for (i = 0; i < 32; i++) { j = mdio_read(dev->base_addr + AXNET_MII_EEP, i, 1); j2 = mdio_read(dev->base_addr + AXNET_MII_EEP, i, 2); @@ -329,15 +332,18 @@ static int axnet_config(struct pcmcia_device *link) if ((j != 0) && (j != 0xffff)) break; } - /* Maybe PHY is in power down mode. (PPD_SET = 1) - Bit 2 of CCSR is active low. */ if (i == 32) { + /* Maybe PHY is in power down mode. (PPD_SET = 1) + Bit 2 of CCSR is active low. */ pcmcia_write_config_byte(link, CISREG_CCSR, 0x04); for (i = 0; i < 32; i++) { j = mdio_read(dev->base_addr + AXNET_MII_EEP, i, 1); j2 = mdio_read(dev->base_addr + AXNET_MII_EEP, i, 2); if (j == j2) continue; - if ((j != 0) && (j != 0xffff)) break; + if ((j != 0) && (j != 0xffff)) { + info->active_low = 1; + break; + } } } @@ -383,8 +389,12 @@ static int axnet_suspend(struct pcmcia_device *link) static int axnet_resume(struct pcmcia_device *link) { struct net_device *dev = link->priv; + axnet_dev_t *info = PRIV(dev); if (link->open) { + if (info->active_low == 1) + pcmcia_write_config_byte(link, CISREG_CCSR, 0x04); + axnet_reset_8390(dev); AX88190_init(dev, 1); netif_device_attach(dev); @@ -865,7 +875,7 @@ static void do_set_multicast_list(struct net_device *dev); static int ax_open(struct net_device *dev) { unsigned long flags; - struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev); + struct ei_device *ei_local = netdev_priv(dev); /* * Grab the page lock so we own the register set, then call @@ -916,7 +926,7 @@ static int ax_close(struct net_device *dev) static void axnet_tx_timeout(struct net_device *dev) { long e8390_base = dev->base_addr; - struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev); + struct ei_device *ei_local = netdev_priv(dev); int txsr, isr, tickssofar = jiffies - dev_trans_start(dev); unsigned long flags; @@ -963,7 +973,7 @@ static netdev_tx_t axnet_start_xmit(struct sk_buff *skb, struct net_device *dev) { long e8390_base = dev->base_addr; - struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev); + struct ei_device *ei_local = netdev_priv(dev); int length, send_length, output_page; unsigned long flags; u8 packet[ETH_ZLEN]; @@ -1260,7 +1270,7 @@ static void ei_tx_err(struct net_device *dev) static void ei_tx_intr(struct net_device *dev) { long e8390_base = dev->base_addr; - struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev); + struct ei_device *ei_local = netdev_priv(dev); int status = inb(e8390_base + EN0_TSR); /* @@ -1344,7 +1354,7 @@ static void ei_tx_intr(struct net_device *dev) static void ei_receive(struct net_device *dev) { long e8390_base = dev->base_addr; - struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev); + struct ei_device *ei_local = netdev_priv(dev); unsigned char rxing_page, this_frame, next_frame; unsigned short current_offset; int rx_pkt_count = 0; @@ -1529,7 +1539,7 @@ static void ei_rx_overrun(struct net_device *dev) static struct net_device_stats *get_stats(struct net_device *dev) { long ioaddr = dev->base_addr; - struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev); + struct ei_device *ei_local = netdev_priv(dev); unsigned long flags; /* If the card is stopped, just return the present stats. */ @@ -1578,7 +1588,7 @@ static void do_set_multicast_list(struct net_device *dev) { long e8390_base = dev->base_addr; int i; - struct ei_device *ei_local = (struct ei_device*)netdev_priv(dev); + struct ei_device *ei_local = netdev_priv(dev); if (!(dev->flags&(IFF_PROMISC|IFF_ALLMULTI))) { memset(ei_local->mcfilter, 0, 8); @@ -1636,7 +1646,7 @@ static void AX88190_init(struct net_device *dev, int startp) { axnet_dev_t *info = PRIV(dev); long e8390_base = dev->base_addr; - struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev); + struct ei_device *ei_local = netdev_priv(dev); int i; int endcfg = ei_local->word16 ? (0x48 | ENDCFG_WTS) : 0x48; @@ -1702,7 +1712,7 @@ static void NS8390_trigger_send(struct net_device *dev, unsigned int length, int start_page) { long e8390_base = dev->base_addr; - struct ei_device *ei_local __attribute((unused)) = (struct ei_device *) netdev_priv(dev); + struct ei_device *ei_local __attribute((unused)) = netdev_priv(dev); if (inb_p(e8390_base) & E8390_TRANS) { diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index 7670aac0e93f..a8445c72fc13 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -47,11 +47,11 @@ void phy_print_status(struct phy_device *phydev) pr_info("PHY: %s - Link is %s", dev_name(&phydev->dev), phydev->link ? "Up" : "Down"); if (phydev->link) - printk(" - %d/%s", phydev->speed, + printk(KERN_CONT " - %d/%s", phydev->speed, DUPLEX_FULL == phydev->duplex ? "Full" : "Half"); - printk("\n"); + printk(KERN_CONT "\n"); } EXPORT_SYMBOL(phy_print_status); diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c index 09cf56d0416a..0c91598ae280 100644 --- a/drivers/net/ppp_generic.c +++ b/drivers/net/ppp_generic.c @@ -1136,8 +1136,7 @@ ppp_send_frame(struct ppp *ppp, struct sk_buff *skb) a four-byte PPP header on each packet */ *skb_push(skb, 2) = 1; if (ppp->pass_filter && - sk_run_filter(skb, ppp->pass_filter, - ppp->pass_len) == 0) { + sk_run_filter(skb, ppp->pass_filter) == 0) { if (ppp->debug & 1) printk(KERN_DEBUG "PPP: outbound frame not passed\n"); kfree_skb(skb); @@ -1145,8 +1144,7 @@ ppp_send_frame(struct ppp *ppp, struct sk_buff *skb) } /* if this packet passes the active filter, record the time */ if (!(ppp->active_filter && - sk_run_filter(skb, ppp->active_filter, - ppp->active_len) == 0)) + sk_run_filter(skb, ppp->active_filter) == 0)) ppp->last_xmit = jiffies; skb_pull(skb, 2); #else @@ -1758,8 +1756,7 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb) *skb_push(skb, 2) = 0; if (ppp->pass_filter && - sk_run_filter(skb, ppp->pass_filter, - ppp->pass_len) == 0) { + sk_run_filter(skb, ppp->pass_filter) == 0) { if (ppp->debug & 1) printk(KERN_DEBUG "PPP: inbound frame " "not passed\n"); @@ -1767,8 +1764,7 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb) return; } if (!(ppp->active_filter && - sk_run_filter(skb, ppp->active_filter, - ppp->active_len) == 0)) + sk_run_filter(skb, ppp->active_filter) == 0)) ppp->last_recv = jiffies; __skb_pull(skb, 2); } else diff --git a/drivers/net/pptp.c b/drivers/net/pptp.c index ccbc91326bfa..7556a9224f72 100644 --- a/drivers/net/pptp.c +++ b/drivers/net/pptp.c @@ -673,8 +673,7 @@ static int __init pptp_init_module(void) int err = 0; pr_info("PPTP driver version " PPTP_DRIVER_VERSION "\n"); - callid_sock = __vmalloc((MAX_CALLID + 1) * sizeof(void *), - GFP_KERNEL | __GFP_ZERO, PAGE_KERNEL); + callid_sock = vzalloc((MAX_CALLID + 1) * sizeof(void *)); if (!callid_sock) { pr_err("PPTP: cann't allocate memory\n"); return -ENOMEM; diff --git a/drivers/net/qla3xxx.c b/drivers/net/qla3xxx.c index 7496ed2c34ab..1a3584edd79c 100644 --- a/drivers/net/qla3xxx.c +++ b/drivers/net/qla3xxx.c @@ -2467,7 +2467,7 @@ map_error: static netdev_tx_t ql3xxx_send(struct sk_buff *skb, struct net_device *ndev) { - struct ql3_adapter *qdev = (struct ql3_adapter *)netdev_priv(ndev); + struct ql3_adapter *qdev = netdev_priv(ndev); struct ql3xxx_port_registers __iomem *port_regs = qdev->mem_map_registers; struct ql_tx_buf_cb *tx_cb; @@ -3390,7 +3390,7 @@ static void ql_set_mac_info(struct ql3_adapter *qdev) static void ql_display_dev_info(struct net_device *ndev) { - struct ql3_adapter *qdev = (struct ql3_adapter *)netdev_priv(ndev); + struct ql3_adapter *qdev = netdev_priv(ndev); struct pci_dev *pdev = qdev->pdev; netdev_info(ndev, @@ -3573,7 +3573,7 @@ static int ql3xxx_open(struct net_device *ndev) static int ql3xxx_set_mac_address(struct net_device *ndev, void *p) { - struct ql3_adapter *qdev = (struct ql3_adapter *)netdev_priv(ndev); + struct ql3_adapter *qdev = netdev_priv(ndev); struct ql3xxx_port_registers __iomem *port_regs = qdev->mem_map_registers; struct sockaddr *addr = p; @@ -3608,7 +3608,7 @@ static int ql3xxx_set_mac_address(struct net_device *ndev, void *p) static void ql3xxx_tx_timeout(struct net_device *ndev) { - struct ql3_adapter *qdev = (struct ql3_adapter *)netdev_priv(ndev); + struct ql3_adapter *qdev = netdev_priv(ndev); netdev_err(ndev, "Resetting...\n"); /* diff --git a/drivers/net/qlcnic/qlcnic.h b/drivers/net/qlcnic/qlcnic.h index 8ecc170c9b74..f267da42f243 100644 --- a/drivers/net/qlcnic/qlcnic.h +++ b/drivers/net/qlcnic/qlcnic.h @@ -1,25 +1,8 @@ /* - * Copyright (C) 2009 - QLogic Corporation. - * All rights reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - * - * The full GNU General Public License is included in this distribution - * in the file called "COPYING". + * QLogic qlcnic NIC Driver + * Copyright (c) 2009-2010 QLogic Corporation * + * See LICENSE.qlcnic for copyright and licensing details. */ #ifndef _QLCNIC_H_ @@ -51,8 +34,8 @@ #define _QLCNIC_LINUX_MAJOR 5 #define _QLCNIC_LINUX_MINOR 0 -#define _QLCNIC_LINUX_SUBVERSION 11 -#define QLCNIC_LINUX_VERSIONID "5.0.11" +#define _QLCNIC_LINUX_SUBVERSION 13 +#define QLCNIC_LINUX_VERSIONID "5.0.13" #define QLCNIC_DRV_IDC_VER 0x01 #define QLCNIC_DRIVER_VERSION ((_QLCNIC_LINUX_MAJOR << 16) |\ (_QLCNIC_LINUX_MINOR << 8) | (_QLCNIC_LINUX_SUBVERSION)) @@ -798,7 +781,6 @@ struct qlcnic_nic_intr_coalesce { #define QLCNIC_H2C_OPCODE_GET_NET_STATS 16 #define QLCNIC_H2C_OPCODE_PROXY_UPDATE_P2V 17 #define QLCNIC_H2C_OPCODE_CONFIG_IPADDR 18 -#define QLCNIC_H2C_OPCODE_CONFIG_LOOPBACK 19 #define QLCNIC_H2C_OPCODE_PROXY_STOP_DONE 20 #define QLCNIC_H2C_OPCODE_GET_LINKEVENT 21 #define QLCNIC_C2C_OPCODE 22 @@ -923,6 +905,7 @@ struct qlcnic_ipaddr { #define QLCNIC_MACSPOOF 0x200 #define QLCNIC_MAC_OVERRIDE_DISABLED 0x400 #define QLCNIC_PROMISC_DISABLED 0x800 +#define QLCNIC_NEED_FLR 0x1000 #define QLCNIC_IS_MSI_FAMILY(adapter) \ ((adapter)->flags & (QLCNIC_MSI_ENABLED | QLCNIC_MSIX_ENABLED)) @@ -1126,8 +1109,7 @@ struct qlcnic_eswitch { /* Return codes for Error handling */ #define QL_STATUS_INVALID_PARAM -1 -#define MAX_BW 100 -#define MIN_BW 1 +#define MAX_BW 100 /* % of link speed */ #define MAX_VLAN_ID 4095 #define MIN_VLAN_ID 2 #define MAX_TX_QUEUES 1 @@ -1135,7 +1117,7 @@ struct qlcnic_eswitch { #define DEFAULT_MAC_LEARN 1 #define IS_VALID_VLAN(vlan) (vlan >= MIN_VLAN_ID && vlan < MAX_VLAN_ID) -#define IS_VALID_BW(bw) (bw >= MIN_BW && bw <= MAX_BW) +#define IS_VALID_BW(bw) (bw <= MAX_BW) #define IS_VALID_TX_QUEUES(que) (que > 0 && que <= MAX_TX_QUEUES) #define IS_VALID_RX_QUEUES(que) (que > 0 && que <= MAX_RX_QUEUES) @@ -1314,21 +1296,15 @@ int qlcnic_config_bridged_mode(struct qlcnic_adapter *adapter, u32 enable); int qlcnic_send_lro_cleanup(struct qlcnic_adapter *adapter); void qlcnic_update_cmd_producer(struct qlcnic_adapter *adapter, struct qlcnic_host_tx_ring *tx_ring); -void qlcnic_clear_ilb_mode(struct qlcnic_adapter *adapter); -int qlcnic_set_ilb_mode(struct qlcnic_adapter *adapter); void qlcnic_fetch_mac(struct qlcnic_adapter *, u32, u32, u8, u8 *); /* Functions from qlcnic_main.c */ -int qlcnic_request_quiscent_mode(struct qlcnic_adapter *adapter); -void qlcnic_clear_quiscent_mode(struct qlcnic_adapter *adapter); int qlcnic_reset_context(struct qlcnic_adapter *); u32 qlcnic_issue_cmd(struct qlcnic_adapter *adapter, u32 pci_fn, u32 version, u32 arg1, u32 arg2, u32 arg3, u32 cmd); void qlcnic_diag_free_res(struct net_device *netdev, int max_sds_rings); int qlcnic_diag_alloc_res(struct net_device *netdev, int test); -int qlcnic_check_loopback_buff(unsigned char *data); netdev_tx_t qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev); -void qlcnic_process_rcv_ring_diag(struct qlcnic_host_sds_ring *sds_ring); /* Management functions */ int qlcnic_get_mac_address(struct qlcnic_adapter *, u8*); @@ -1377,6 +1353,8 @@ static const struct qlcnic_brdinfo qlcnic_boards[] = { "3200 Series Single Port 10Gb Intelligent Ethernet Adapter"}, {0x1077, 0x8020, 0x103c, 0x3733, "NC523SFP 10Gb 2-port Server Adapter"}, + {0x1077, 0x8020, 0x103c, 0x3346, + "CN1000Q Dual Port Converged Network Adapter"}, {0x1077, 0x8020, 0x0, 0x0, "cLOM8214 1/10GbE Controller"}, }; diff --git a/drivers/net/qlcnic/qlcnic_ctx.c b/drivers/net/qlcnic/qlcnic_ctx.c index 1cdc05dade6b..27631f23b3fd 100644 --- a/drivers/net/qlcnic/qlcnic_ctx.c +++ b/drivers/net/qlcnic/qlcnic_ctx.c @@ -1,25 +1,8 @@ /* - * Copyright (C) 2009 - QLogic Corporation. - * All rights reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - * - * The full GNU General Public License is included in this distribution - * in the file called "COPYING". + * QLogic qlcnic NIC Driver + * Copyright (c) 2009-2010 QLogic Corporation * + * See LICENSE.qlcnic for copyright and licensing details. */ #include "qlcnic.h" @@ -480,6 +463,11 @@ int qlcnic_fw_create_ctx(struct qlcnic_adapter *adapter) { int err; + if (adapter->flags & QLCNIC_NEED_FLR) { + pci_reset_function(adapter->pdev); + adapter->flags &= ~QLCNIC_NEED_FLR; + } + err = qlcnic_fw_cmd_create_rx_ctx(adapter); if (err) return err; diff --git a/drivers/net/qlcnic/qlcnic_ethtool.c b/drivers/net/qlcnic/qlcnic_ethtool.c index ec21d24015c4..0eaf31bf8a0d 100644 --- a/drivers/net/qlcnic/qlcnic_ethtool.c +++ b/drivers/net/qlcnic/qlcnic_ethtool.c @@ -1,25 +1,8 @@ /* - * Copyright (C) 2009 - QLogic Corporation. - * All rights reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - * - * The full GNU General Public License is included in this distribution - * in the file called "COPYING". + * QLogic qlcnic NIC Driver + * Copyright (c) 2009-2010 QLogic Corporation * + * See LICENSE.qlcnic for copyright and licensing details. */ #include <linux/types.h> @@ -101,8 +84,7 @@ static const char qlcnic_device_gstrings_stats[][ETH_GSTRING_LEN] = { static const char qlcnic_gstrings_test[][ETH_GSTRING_LEN] = { "Register_Test_on_offline", "Link_Test_on_offline", - "Interrupt_Test_offline", - "Loopback_Test_offline" + "Interrupt_Test_offline" }; #define QLCNIC_TEST_LEN ARRAY_SIZE(qlcnic_gstrings_test) @@ -643,104 +625,6 @@ static int qlcnic_get_sset_count(struct net_device *dev, int sset) } } -#define QLC_ILB_PKT_SIZE 64 -#define QLC_NUM_ILB_PKT 16 -#define QLC_ILB_MAX_RCV_LOOP 10 - -static void qlcnic_create_loopback_buff(unsigned char *data) -{ - unsigned char random_data[] = {0xa8, 0x06, 0x45, 0x00}; - memset(data, 0x4e, QLC_ILB_PKT_SIZE); - memset(data, 0xff, 12); - memcpy(data + 12, random_data, sizeof(random_data)); -} - -int qlcnic_check_loopback_buff(unsigned char *data) -{ - unsigned char buff[QLC_ILB_PKT_SIZE]; - qlcnic_create_loopback_buff(buff); - return memcmp(data, buff, QLC_ILB_PKT_SIZE); -} - -static int qlcnic_do_ilb_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 < QLC_NUM_ILB_PKT; i++) { - skb = dev_alloc_skb(QLC_ILB_PKT_SIZE); - qlcnic_create_loopback_buff(skb->data); - skb_put(skb, QLC_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); - } while (loop++ < QLC_ILB_MAX_RCV_LOOP && - !adapter->diag_cnt); - - dev_kfree_skb_any(skb); - - if (!adapter->diag_cnt) - dev_warn(&adapter->pdev->dev, "ILB Test: %dth packet" - " not recevied\n", i + 1); - else - cnt++; - } - if (cnt != i) { - dev_warn(&adapter->pdev->dev, "ILB Test failed\n"); - return -1; - } - return 0; -} - -static int qlcnic_loopback_test(struct net_device *netdev) -{ - struct qlcnic_adapter *adapter = netdev_priv(netdev); - int max_sds_rings = adapter->max_sds_rings; - int ret; - - if (adapter->op_mode == QLCNIC_NON_PRIV_FUNC) { - dev_warn(&adapter->pdev->dev, "Loopback test not supported" - "for non privilege function\n"); - return 0; - } - - if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state)) - return -EIO; - - if (qlcnic_request_quiscent_mode(adapter)) { - clear_bit(__QLCNIC_RESETTING, &adapter->state); - return -EIO; - } - - ret = qlcnic_diag_alloc_res(netdev, QLCNIC_LOOPBACK_TEST); - if (ret) - goto clear_it; - - ret = qlcnic_set_ilb_mode(adapter); - if (ret) - goto done; - - ret = qlcnic_do_ilb_test(adapter); - - qlcnic_clear_ilb_mode(adapter); - -done: - qlcnic_diag_free_res(netdev, max_sds_rings); - -clear_it: - qlcnic_clear_quiscent_mode(adapter); - adapter->max_sds_rings = max_sds_rings; - clear_bit(__QLCNIC_RESETTING, &adapter->state); - return ret; -} - static int qlcnic_irq_test(struct net_device *netdev) { struct qlcnic_adapter *adapter = netdev_priv(netdev); @@ -793,9 +677,6 @@ qlcnic_diag_test(struct net_device *dev, struct ethtool_test *eth_test, if (data[2]) eth_test->flags |= ETH_TEST_FL_FAILED; - data[3] = qlcnic_loopback_test(dev); - if (data[3]) - eth_test->flags |= ETH_TEST_FL_FAILED; } } @@ -925,9 +806,10 @@ static int qlcnic_set_rx_csum(struct net_device *dev, u32 data) dev->features &= ~NETIF_F_LRO; qlcnic_send_lro_cleanup(adapter); + dev_info(&adapter->pdev->dev, + "disabling LRO as rx_csum is off\n"); } adapter->rx_csum = !!data; - dev_info(&adapter->pdev->dev, "disabling LRO as rx_csum is off\n"); return 0; } diff --git a/drivers/net/qlcnic/qlcnic_hdr.h b/drivers/net/qlcnic/qlcnic_hdr.h index 4290b80cde1a..19328e05b75d 100644 --- a/drivers/net/qlcnic/qlcnic_hdr.h +++ b/drivers/net/qlcnic/qlcnic_hdr.h @@ -1,25 +1,8 @@ /* - * Copyright (C) 2009 - QLogic Corporation. - * All rights reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - * - * The full GNU General Public License is included in this distribution - * in the file called "COPYING". + * QLogic qlcnic NIC Driver + * Copyright (c) 2009-2010 QLogic Corporation * + * See LICENSE.qlcnic for copyright and licensing details. */ #ifndef __QLCNIC_HDR_H_ @@ -722,7 +705,7 @@ enum { #define QLCNIC_DEV_NPAR_OPER 1 /* NPAR Operational */ #define QLCNIC_DEV_NPAR_OPER_TIMEO 30 /* Operational time out */ -#define QLC_DEV_CHECK_ACTIVE(VAL, FN) ((VAL) &= (1 << (FN * 4))) +#define QLC_DEV_CHECK_ACTIVE(VAL, FN) ((VAL) & (1 << (FN * 4))) #define QLC_DEV_SET_REF_CNT(VAL, FN) ((VAL) |= (1 << (FN * 4))) #define QLC_DEV_CLR_REF_CNT(VAL, FN) ((VAL) &= ~(1 << (FN * 4))) #define QLC_DEV_SET_RST_RDY(VAL, FN) ((VAL) |= (1 << (FN * 4))) diff --git a/drivers/net/qlcnic/qlcnic_hw.c b/drivers/net/qlcnic/qlcnic_hw.c index 7a47a2a7ee27..c9c4bf1458a8 100644 --- a/drivers/net/qlcnic/qlcnic_hw.c +++ b/drivers/net/qlcnic/qlcnic_hw.c @@ -1,25 +1,8 @@ /* - * Copyright (C) 2009 - QLogic Corporation. - * All rights reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - * - * The full GNU General Public License is included in this distribution - * in the file called "COPYING". + * QLogic qlcnic NIC Driver + * Copyright (c) 2009-2010 QLogic Corporation * + * See LICENSE.qlcnic for copyright and licensing details. */ #include "qlcnic.h" @@ -1234,56 +1217,3 @@ int qlcnic_config_led(struct qlcnic_adapter *adapter, u32 state, u32 rate) return rv; } - -static int qlcnic_set_fw_loopback(struct qlcnic_adapter *adapter, u32 flag) -{ - struct qlcnic_nic_req req; - int rv; - u64 word; - - memset(&req, 0, sizeof(struct qlcnic_nic_req)); - req.qhdr = cpu_to_le64(QLCNIC_HOST_REQUEST << 23); - - word = QLCNIC_H2C_OPCODE_CONFIG_LOOPBACK | - ((u64)adapter->portnum << 16); - req.req_hdr = cpu_to_le64(word); - req.words[0] = cpu_to_le64(flag); - - rv = qlcnic_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1); - if (rv) - dev_err(&adapter->pdev->dev, - "%sting loopback mode failed.\n", - flag ? "Set" : "Reset"); - return rv; -} - -int qlcnic_set_ilb_mode(struct qlcnic_adapter *adapter) -{ - if (qlcnic_set_fw_loopback(adapter, 1)) - return -EIO; - - if (qlcnic_nic_set_promisc(adapter, - VPORT_MISS_MODE_ACCEPT_ALL)) { - qlcnic_set_fw_loopback(adapter, 0); - return -EIO; - } - - msleep(1000); - return 0; -} - -void qlcnic_clear_ilb_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); -} diff --git a/drivers/net/qlcnic/qlcnic_init.c b/drivers/net/qlcnic/qlcnic_init.c index 0d180c6e41fe..9b9c7c39d3ee 100644 --- a/drivers/net/qlcnic/qlcnic_init.c +++ b/drivers/net/qlcnic/qlcnic_init.c @@ -1,25 +1,8 @@ /* - * Copyright (C) 2009 - QLogic Corporation. - * All rights reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - * - * The full GNU General Public License is included in this distribution - * in the file called "COPYING". + * QLogic qlcnic NIC Driver + * Copyright (c) 2009-2010 QLogic Corporation * + * See LICENSE.qlcnic for copyright and licensing details. */ #include <linux/netdevice.h> @@ -236,12 +219,11 @@ int qlcnic_alloc_sw_resources(struct qlcnic_adapter *adapter) tx_ring->num_desc = adapter->num_txd; tx_ring->txq = netdev_get_tx_queue(netdev, 0); - cmd_buf_arr = vmalloc(TX_BUFF_RINGSIZE(tx_ring)); + cmd_buf_arr = vzalloc(TX_BUFF_RINGSIZE(tx_ring)); if (cmd_buf_arr == NULL) { dev_err(&netdev->dev, "failed to allocate cmd buffer ring\n"); goto err_out; } - memset(cmd_buf_arr, 0, TX_BUFF_RINGSIZE(tx_ring)); tx_ring->cmd_buf_arr = cmd_buf_arr; recv_ctx = &adapter->recv_ctx; @@ -275,14 +257,12 @@ int qlcnic_alloc_sw_resources(struct qlcnic_adapter *adapter) rds_ring->dma_size + NET_IP_ALIGN; break; } - rds_ring->rx_buf_arr = (struct qlcnic_rx_buffer *) - vmalloc(RCV_BUFF_RINGSIZE(rds_ring)); + rds_ring->rx_buf_arr = vzalloc(RCV_BUFF_RINGSIZE(rds_ring)); if (rds_ring->rx_buf_arr == NULL) { dev_err(&netdev->dev, "Failed to allocate " "rx buffer ring %d\n", ring); goto err_out; } - memset(rds_ring->rx_buf_arr, 0, RCV_BUFF_RINGSIZE(rds_ring)); INIT_LIST_HEAD(&rds_ring->free_list); /* * Now go through all of them, set reference handles @@ -1693,99 +1673,6 @@ qlcnic_post_rx_buffers_nodb(struct qlcnic_adapter *adapter, spin_unlock(&rds_ring->lock); } -static void dump_skb(struct sk_buff *skb) -{ - int i; - unsigned char *data = skb->data; - - for (i = 0; i < skb->len; i++) { - printk("%02x ", data[i]); - if ((i & 0x0f) == 8) - printk("\n"); - } -} - -static struct qlcnic_rx_buffer * -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 qlcnic_rx_buffer *buffer; - 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 NULL; - - rds_ring = &recv_ctx->rds_rings[ring]; - - index = qlcnic_get_sts_refhandle(sts_data0); - if (unlikely(index >= rds_ring->num_desc)) - return NULL; - - buffer = &rds_ring->rx_buf_arr[index]; - - length = qlcnic_get_sts_totallength(sts_data0); - 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 buffer; - - 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->diag_cnt++; - else - dump_skb(skb); - - dev_kfree_skb_any(skb); - adapter->stats.rx_pkts++; - adapter->stats.rxbytes += length; - - return buffer; -} - -void -qlcnic_process_rcv_ring_diag(struct qlcnic_host_sds_ring *sds_ring) -{ - struct qlcnic_adapter *adapter = sds_ring->adapter; - struct status_desc *desc; - struct qlcnic_rx_buffer *rxbuf; - u64 sts_data0; - - int opcode, ring, 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); - - ring = qlcnic_get_sts_type(sts_data0); - rxbuf = qlcnic_process_rcv_diag(adapter, sds_ring, - ring, sts_data0); - - 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 7a298cdf9ab3..788850e2ba4e 100644 --- a/drivers/net/qlcnic/qlcnic_main.c +++ b/drivers/net/qlcnic/qlcnic_main.c @@ -1,25 +1,8 @@ /* - * Copyright (C) 2009 - QLogic Corporation. - * All rights reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - * - * The full GNU General Public License is included in this distribution - * in the file called "COPYING". + * QLogic qlcnic NIC Driver + * Copyright (c) 2009-2010 QLogic Corporation * + * See LICENSE.qlcnic for copyright and licensing details. */ #include <linux/slab.h> @@ -1450,7 +1433,6 @@ qlcnic_setup_netdev(struct qlcnic_adapter *adapter, netdev->irq = adapter->msix_entries[0].vector; netif_carrier_off(netdev); - netif_stop_queue(netdev); err = register_netdev(netdev); if (err) { @@ -1486,6 +1468,7 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) uint8_t revision_id; uint8_t pci_using_dac; char brd_name[QLCNIC_MAX_BOARD_NAME_LEN]; + u32 val; err = pci_enable_device(pdev); if (err) @@ -1547,6 +1530,10 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) if (err) goto err_out_iounmap; + val = QLCRD32(adapter, QLCNIC_CRB_DRV_ACTIVE); + if (QLC_DEV_CHECK_ACTIVE(val, adapter->portnum)) + adapter->flags |= QLCNIC_NEED_FLR; + err = adapter->nic_ops->start_firmware(adapter); if (err) { dev_err(&pdev->dev, "Loading fw failed.Please Reboot\n"); @@ -2855,61 +2842,6 @@ qlcnic_set_npar_non_operational(struct qlcnic_adapter *adapter) qlcnic_api_unlock(adapter); } -/* Caller should held RESETTING bit. - * This should be call in sync with qlcnic_request_quiscent_mode. - */ -void qlcnic_clear_quiscent_mode(struct qlcnic_adapter *adapter) -{ - qlcnic_clr_drv_state(adapter); - qlcnic_api_lock(adapter); - QLCWR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_READY); - qlcnic_api_unlock(adapter); -} - -/* Caller should held RESETTING bit. - */ -int qlcnic_request_quiscent_mode(struct qlcnic_adapter *adapter) -{ - u8 timeo = adapter->dev_init_timeo / 2; - u32 state; - - if (qlcnic_api_lock(adapter)) - return -EIO; - - state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE); - if (state != QLCNIC_DEV_READY) - return -EIO; - - QLCWR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_NEED_QUISCENT); - qlcnic_api_unlock(adapter); - QLCDB(adapter, DRV, "NEED QUISCENT state set\n"); - qlcnic_idc_debug_info(adapter, 0); - - qlcnic_set_drv_state(adapter, QLCNIC_DEV_NEED_QUISCENT); - - do { - msleep(2000); - state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE); - if (state == QLCNIC_DEV_QUISCENT) - return 0; - if (!qlcnic_check_drv_state(adapter)) { - if (qlcnic_api_lock(adapter)) - return -EIO; - QLCWR32(adapter, QLCNIC_CRB_DEV_STATE, - QLCNIC_DEV_QUISCENT); - qlcnic_api_unlock(adapter); - QLCDB(adapter, DRV, "QUISCENT mode set\n"); - return 0; - } - } while (--timeo); - - dev_err(&adapter->pdev->dev, "Failed to quiesce device, DRV_STATE=%08x" - " DRV_ACTIVE=%08x\n", QLCRD32(adapter, QLCNIC_CRB_DRV_STATE), - QLCRD32(adapter, QLCNIC_CRB_DRV_ACTIVE)); - qlcnic_clear_quiscent_mode(adapter); - return -EIO; -} - /*Transit to RESET state from READY state only */ static void qlcnic_dev_request_reset(struct qlcnic_adapter *adapter) @@ -3588,9 +3520,12 @@ validate_esw_config(struct qlcnic_adapter *adapter, case QLCNIC_PORT_DEFAULTS: if (QLC_DEV_GET_DRV(op_mode, pci_func) != QLCNIC_NON_PRIV_FUNC) { - esw_cfg[i].mac_anti_spoof = 0; - esw_cfg[i].mac_override = 1; - esw_cfg[i].promisc_mode = 1; + if (esw_cfg[i].mac_anti_spoof != 0) + return QL_STATUS_INVALID_PARAM; + if (esw_cfg[i].mac_override != 1) + return QL_STATUS_INVALID_PARAM; + if (esw_cfg[i].promisc_mode != 1) + return QL_STATUS_INVALID_PARAM; } break; case QLCNIC_ADD_VLAN: diff --git a/drivers/net/qlge/qlge.h b/drivers/net/qlge/qlge.h index 22821398fc63..bdb8fe868539 100644 --- a/drivers/net/qlge/qlge.h +++ b/drivers/net/qlge/qlge.h @@ -16,7 +16,7 @@ */ #define DRV_NAME "qlge" #define DRV_STRING "QLogic 10 Gigabit PCI-E Ethernet Driver " -#define DRV_VERSION "v1.00.00.25.00.00-01" +#define DRV_VERSION "v1.00.00.27.00.00-01" #define WQ_ADDR_ALIGN 0x3 /* 4 byte alignment */ @@ -2221,6 +2221,7 @@ int ql_write_mpi_reg(struct ql_adapter *qdev, u32 reg, u32 data); int ql_unpause_mpi_risc(struct ql_adapter *qdev); int ql_pause_mpi_risc(struct ql_adapter *qdev); int ql_hard_reset_mpi_risc(struct ql_adapter *qdev); +int ql_soft_reset_mpi_risc(struct ql_adapter *qdev); int ql_dump_risc_ram_area(struct ql_adapter *qdev, void *buf, u32 ram_addr, int word_count); int ql_core_dump(struct ql_adapter *qdev, @@ -2236,6 +2237,7 @@ int ql_mb_set_mgmnt_traffic_ctl(struct ql_adapter *qdev, u32 control); int ql_mb_get_port_cfg(struct ql_adapter *qdev); int ql_mb_set_port_cfg(struct ql_adapter *qdev); int ql_wait_fifo_empty(struct ql_adapter *qdev); +void ql_get_dump(struct ql_adapter *qdev, void *buff); void ql_gen_reg_dump(struct ql_adapter *qdev, struct ql_reg_dump *mpi_coredump); netdev_tx_t ql_lb_send(struct sk_buff *skb, struct net_device *ndev); diff --git a/drivers/net/qlge/qlge_dbg.c b/drivers/net/qlge/qlge_dbg.c index 4747492935ef..fca804f36d61 100644 --- a/drivers/net/qlge/qlge_dbg.c +++ b/drivers/net/qlge/qlge_dbg.c @@ -1317,9 +1317,28 @@ void ql_gen_reg_dump(struct ql_adapter *qdev, status = ql_get_ets_regs(qdev, &mpi_coredump->ets[0]); if (status) return; +} + +void ql_get_dump(struct ql_adapter *qdev, void *buff) +{ + /* + * If the dump has already been taken and is stored + * in our internal buffer and if force dump is set then + * just start the spool to dump it to the log file + * and also, take a snapshot of the general regs to + * to the user's buffer or else take complete dump + * to the user's buffer if force is not set. + */ - if (test_bit(QL_FRC_COREDUMP, &qdev->flags)) + if (!test_bit(QL_FRC_COREDUMP, &qdev->flags)) { + if (!ql_core_dump(qdev, buff)) + ql_soft_reset_mpi_risc(qdev); + else + netif_err(qdev, drv, qdev->ndev, "coredump failed!\n"); + } else { + ql_gen_reg_dump(qdev, buff); ql_get_core_dump(qdev); + } } /* Coredump to messages log file using separate worker thread */ diff --git a/drivers/net/qlge/qlge_ethtool.c b/drivers/net/qlge/qlge_ethtool.c index 4892d64f4e05..8149cc9de4ca 100644 --- a/drivers/net/qlge/qlge_ethtool.c +++ b/drivers/net/qlge/qlge_ethtool.c @@ -375,7 +375,10 @@ static void ql_get_drvinfo(struct net_device *ndev, strncpy(drvinfo->bus_info, pci_name(qdev->pdev), 32); drvinfo->n_stats = 0; drvinfo->testinfo_len = 0; - drvinfo->regdump_len = 0; + if (!test_bit(QL_FRC_COREDUMP, &qdev->flags)) + drvinfo->regdump_len = sizeof(struct ql_mpi_coredump); + else + drvinfo->regdump_len = sizeof(struct ql_reg_dump); drvinfo->eedump_len = 0; } @@ -547,7 +550,12 @@ static void ql_self_test(struct net_device *ndev, static int ql_get_regs_len(struct net_device *ndev) { - return sizeof(struct ql_reg_dump); + struct ql_adapter *qdev = netdev_priv(ndev); + + if (!test_bit(QL_FRC_COREDUMP, &qdev->flags)) + return sizeof(struct ql_mpi_coredump); + else + return sizeof(struct ql_reg_dump); } static void ql_get_regs(struct net_device *ndev, @@ -555,7 +563,12 @@ static void ql_get_regs(struct net_device *ndev, { struct ql_adapter *qdev = netdev_priv(ndev); - ql_gen_reg_dump(qdev, p); + ql_get_dump(qdev, p); + qdev->core_is_dumped = 0; + if (!test_bit(QL_FRC_COREDUMP, &qdev->flags)) + regs->len = sizeof(struct ql_mpi_coredump); + else + regs->len = sizeof(struct ql_reg_dump); } static int ql_get_coalesce(struct net_device *dev, struct ethtool_coalesce *c) diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index c30e0fe55a31..d9a76260880b 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -3844,7 +3844,7 @@ static int ql_adapter_reset(struct ql_adapter *qdev) static void ql_display_dev_info(struct net_device *ndev) { - struct ql_adapter *qdev = (struct ql_adapter *)netdev_priv(ndev); + struct ql_adapter *qdev = netdev_priv(ndev); netif_info(qdev, probe, qdev->ndev, "Function #%d, Port %d, NIC Roll %d, NIC Rev = %d, " @@ -4264,7 +4264,7 @@ static struct net_device_stats *qlge_get_stats(struct net_device static void qlge_set_multicast_list(struct net_device *ndev) { - struct ql_adapter *qdev = (struct ql_adapter *)netdev_priv(ndev); + struct ql_adapter *qdev = netdev_priv(ndev); struct netdev_hw_addr *ha; int i, status; @@ -4354,7 +4354,7 @@ exit: static int qlge_set_mac_address(struct net_device *ndev, void *p) { - struct ql_adapter *qdev = (struct ql_adapter *)netdev_priv(ndev); + struct ql_adapter *qdev = netdev_priv(ndev); struct sockaddr *addr = p; int status; @@ -4377,7 +4377,7 @@ static int qlge_set_mac_address(struct net_device *ndev, void *p) static void qlge_tx_timeout(struct net_device *ndev) { - struct ql_adapter *qdev = (struct ql_adapter *)netdev_priv(ndev); + struct ql_adapter *qdev = netdev_priv(ndev); ql_queue_asic_error(qdev); } diff --git a/drivers/net/qlge/qlge_mpi.c b/drivers/net/qlge/qlge_mpi.c index 0e7c7c7ee164..100a462cc916 100644 --- a/drivers/net/qlge/qlge_mpi.c +++ b/drivers/net/qlge/qlge_mpi.c @@ -87,7 +87,7 @@ exit: return status; } -static int ql_soft_reset_mpi_risc(struct ql_adapter *qdev) +int ql_soft_reset_mpi_risc(struct ql_adapter *qdev) { int status; status = ql_write_mpi_reg(qdev, 0x00001010, 1); diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index d88ce9fb1cbd..7d33ef4bcb4a 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -846,10 +846,10 @@ static int rtl8169_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) else tp->features &= ~RTL_FEATURE_WOL; __rtl8169_set_wol(tp, wol->wolopts); - device_set_wakeup_enable(&tp->pci_dev->dev, wol->wolopts); - spin_unlock_irq(&tp->lock); + device_set_wakeup_enable(&tp->pci_dev->dev, wol->wolopts); + return 0; } @@ -2931,7 +2931,7 @@ static const struct rtl_cfg_info { .hw_start = rtl_hw_start_8168, .region = 2, .align = 8, - .intr_event = SYSErr | RxFIFOOver | LinkChg | RxOverflow | + .intr_event = SYSErr | LinkChg | RxOverflow | TxErr | TxOK | RxOK | RxErr, .napi_event = TxErr | TxOK | RxOK | RxOverflow, .features = RTL_FEATURE_GMII | RTL_FEATURE_MSI, @@ -4440,8 +4440,7 @@ static inline void rtl8169_rx_csum(struct sk_buff *skb, u32 opts1) u32 status = opts1 & RxProtoMask; if (((status == RxProtoTCP) && !(opts1 & TCPFail)) || - ((status == RxProtoUDP) && !(opts1 & UDPFail)) || - ((status == RxProtoIP) && !(opts1 & IPFail))) + ((status == RxProtoUDP) && !(opts1 & UDPFail))) skb->ip_summed = CHECKSUM_UNNECESSARY; else skb_checksum_none_assert(skb); @@ -4588,7 +4587,8 @@ static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance) } /* Work around for rx fifo overflow */ - if (unlikely(status & RxFIFOOver)) { + if (unlikely(status & RxFIFOOver) && + (tp->mac_version == RTL_GIGA_MAC_VER_11)) { netif_stop_queue(dev); rtl8169_tx_timeout(dev); break; diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c index ecc25aab896a..0f4219cb0be2 100644 --- a/drivers/net/s2io.c +++ b/drivers/net/s2io.c @@ -8321,8 +8321,7 @@ mem_alloc_failed: static void __devexit s2io_rem_nic(struct pci_dev *pdev) { - struct net_device *dev = - (struct net_device *)pci_get_drvdata(pdev); + struct net_device *dev = pci_get_drvdata(pdev); struct s2io_nic *sp; if (dev == NULL) { diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c index 05df20e47976..f3e4043d70ee 100644 --- a/drivers/net/sfc/efx.c +++ b/drivers/net/sfc/efx.c @@ -23,7 +23,6 @@ #include <linux/gfp.h> #include "net_driver.h" #include "efx.h" -#include "mdio_10g.h" #include "nic.h" #include "mcdi.h" @@ -910,6 +909,7 @@ static void efx_mac_work(struct work_struct *data) static int efx_probe_port(struct efx_nic *efx) { + unsigned char *perm_addr; int rc; netif_dbg(efx, probe, efx->net_dev, "create port\n"); @@ -923,11 +923,12 @@ static int efx_probe_port(struct efx_nic *efx) return rc; /* Sanity check MAC address */ - if (is_valid_ether_addr(efx->mac_address)) { - memcpy(efx->net_dev->dev_addr, efx->mac_address, ETH_ALEN); + perm_addr = efx->net_dev->perm_addr; + if (is_valid_ether_addr(perm_addr)) { + memcpy(efx->net_dev->dev_addr, perm_addr, ETH_ALEN); } else { netif_err(efx, probe, efx->net_dev, "invalid MAC address %pM\n", - efx->mac_address); + perm_addr); if (!allow_bad_hwaddr) { rc = -EINVAL; goto err; @@ -1962,7 +1963,6 @@ void efx_reset_down(struct efx_nic *efx, enum reset_type method) efx_stop_all(efx); mutex_lock(&efx->mac_lock); - mutex_lock(&efx->spi_lock); efx_fini_channels(efx); if (efx->port_initialized && method != RESET_TYPE_INVISIBLE) @@ -2004,7 +2004,6 @@ int efx_reset_up(struct efx_nic *efx, enum reset_type method, bool ok) efx_init_channels(efx); efx_restore_filters(efx); - mutex_unlock(&efx->spi_lock); mutex_unlock(&efx->mac_lock); efx_start_all(efx); @@ -2014,7 +2013,6 @@ int efx_reset_up(struct efx_nic *efx, enum reset_type method, bool ok) fail: efx->port_initialized = false; - mutex_unlock(&efx->spi_lock); mutex_unlock(&efx->mac_lock); return rc; @@ -2202,8 +2200,6 @@ static int efx_init_struct(struct efx_nic *efx, struct efx_nic_type *type, /* Initialise common structures */ memset(efx, 0, sizeof(*efx)); spin_lock_init(&efx->biu_lock); - mutex_init(&efx->mdio_lock); - mutex_init(&efx->spi_lock); #ifdef CONFIG_SFC_MTD INIT_LIST_HEAD(&efx->mtd_list); #endif diff --git a/drivers/net/sfc/ethtool.c b/drivers/net/sfc/ethtool.c index edb9d16b8b47..aae756bf47ee 100644 --- a/drivers/net/sfc/ethtool.c +++ b/drivers/net/sfc/ethtool.c @@ -17,8 +17,6 @@ #include "efx.h" #include "filter.h" #include "nic.h" -#include "spi.h" -#include "mdio_10g.h" struct ethtool_string { char name[ETH_GSTRING_LEN]; @@ -629,61 +627,6 @@ static u32 efx_ethtool_get_link(struct net_device *net_dev) return efx->link_state.up; } -static int efx_ethtool_get_eeprom_len(struct net_device *net_dev) -{ - struct efx_nic *efx = netdev_priv(net_dev); - struct efx_spi_device *spi = efx->spi_eeprom; - - if (!spi) - return 0; - return min(spi->size, EFX_EEPROM_BOOTCONFIG_END) - - min(spi->size, EFX_EEPROM_BOOTCONFIG_START); -} - -static int efx_ethtool_get_eeprom(struct net_device *net_dev, - struct ethtool_eeprom *eeprom, u8 *buf) -{ - struct efx_nic *efx = netdev_priv(net_dev); - struct efx_spi_device *spi = efx->spi_eeprom; - size_t len; - int rc; - - rc = mutex_lock_interruptible(&efx->spi_lock); - if (rc) - return rc; - rc = falcon_spi_read(efx, spi, - eeprom->offset + EFX_EEPROM_BOOTCONFIG_START, - eeprom->len, &len, buf); - mutex_unlock(&efx->spi_lock); - - eeprom->magic = EFX_ETHTOOL_EEPROM_MAGIC; - eeprom->len = len; - return rc; -} - -static int efx_ethtool_set_eeprom(struct net_device *net_dev, - struct ethtool_eeprom *eeprom, u8 *buf) -{ - struct efx_nic *efx = netdev_priv(net_dev); - struct efx_spi_device *spi = efx->spi_eeprom; - size_t len; - int rc; - - if (eeprom->magic != EFX_ETHTOOL_EEPROM_MAGIC) - return -EINVAL; - - rc = mutex_lock_interruptible(&efx->spi_lock); - if (rc) - return rc; - rc = falcon_spi_write(efx, spi, - eeprom->offset + EFX_EEPROM_BOOTCONFIG_START, - eeprom->len, &len, buf); - mutex_unlock(&efx->spi_lock); - - eeprom->len = len; - return rc; -} - static int efx_ethtool_get_coalesce(struct net_device *net_dev, struct ethtool_coalesce *coalesce) { @@ -1116,9 +1059,6 @@ const struct ethtool_ops efx_ethtool_ops = { .set_msglevel = efx_ethtool_set_msglevel, .nway_reset = efx_ethtool_nway_reset, .get_link = efx_ethtool_get_link, - .get_eeprom_len = efx_ethtool_get_eeprom_len, - .get_eeprom = efx_ethtool_get_eeprom, - .set_eeprom = efx_ethtool_set_eeprom, .get_coalesce = efx_ethtool_get_coalesce, .set_coalesce = efx_ethtool_set_coalesce, .get_ringparam = efx_ethtool_get_ringparam, diff --git a/drivers/net/sfc/falcon.c b/drivers/net/sfc/falcon.c index 267019bb2b15..70e4f7dcce81 100644 --- a/drivers/net/sfc/falcon.c +++ b/drivers/net/sfc/falcon.c @@ -24,7 +24,6 @@ #include "nic.h" #include "regs.h" #include "io.h" -#include "mdio_10g.h" #include "phy.h" #include "workarounds.h" @@ -255,7 +254,6 @@ int falcon_spi_cmd(struct efx_nic *efx, const struct efx_spi_device *spi, /* Input validation */ if (len > FALCON_SPI_MAX_LEN) return -EINVAL; - BUG_ON(!mutex_is_locked(&efx->spi_lock)); /* Check that previous command is not still running */ rc = falcon_spi_poll(efx); @@ -719,6 +717,7 @@ static int falcon_mdio_write(struct net_device *net_dev, int prtad, int devad, u16 addr, u16 value) { struct efx_nic *efx = netdev_priv(net_dev); + struct falcon_nic_data *nic_data = efx->nic_data; efx_oword_t reg; int rc; @@ -726,7 +725,7 @@ static int falcon_mdio_write(struct net_device *net_dev, "writing MDIO %d register %d.%d with 0x%04x\n", prtad, devad, addr, value); - mutex_lock(&efx->mdio_lock); + mutex_lock(&nic_data->mdio_lock); /* Check MDIO not currently being accessed */ rc = falcon_gmii_wait(efx); @@ -762,7 +761,7 @@ static int falcon_mdio_write(struct net_device *net_dev, } out: - mutex_unlock(&efx->mdio_lock); + mutex_unlock(&nic_data->mdio_lock); return rc; } @@ -771,10 +770,11 @@ static int falcon_mdio_read(struct net_device *net_dev, int prtad, int devad, u16 addr) { struct efx_nic *efx = netdev_priv(net_dev); + struct falcon_nic_data *nic_data = efx->nic_data; efx_oword_t reg; int rc; - mutex_lock(&efx->mdio_lock); + mutex_lock(&nic_data->mdio_lock); /* Check MDIO not currently being accessed */ rc = falcon_gmii_wait(efx); @@ -813,7 +813,7 @@ static int falcon_mdio_read(struct net_device *net_dev, } out: - mutex_unlock(&efx->mdio_lock); + mutex_unlock(&nic_data->mdio_lock); return rc; } @@ -841,6 +841,7 @@ static int falcon_probe_port(struct efx_nic *efx) } /* Fill out MDIO structure and loopback modes */ + mutex_init(&nic_data->mdio_lock); efx->mdio.mdio_read = falcon_mdio_read; efx->mdio.mdio_write = falcon_mdio_write; rc = efx->phy_op->probe(efx); @@ -880,6 +881,41 @@ static void falcon_remove_port(struct efx_nic *efx) efx_nic_free_buffer(efx, &efx->stats_buffer); } +/* Global events are basically PHY events */ +static bool +falcon_handle_global_event(struct efx_channel *channel, efx_qword_t *event) +{ + struct efx_nic *efx = channel->efx; + struct falcon_nic_data *nic_data = efx->nic_data; + + if (EFX_QWORD_FIELD(*event, FSF_AB_GLB_EV_G_PHY0_INTR) || + EFX_QWORD_FIELD(*event, FSF_AB_GLB_EV_XG_PHY0_INTR) || + EFX_QWORD_FIELD(*event, FSF_AB_GLB_EV_XFP_PHY0_INTR)) + /* Ignored */ + return true; + + if ((efx_nic_rev(efx) == EFX_REV_FALCON_B0) && + EFX_QWORD_FIELD(*event, FSF_BB_GLB_EV_XG_MGT_INTR)) { + nic_data->xmac_poll_required = true; + return true; + } + + if (efx_nic_rev(efx) <= EFX_REV_FALCON_A1 ? + EFX_QWORD_FIELD(*event, FSF_AA_GLB_EV_RX_RECOVERY) : + EFX_QWORD_FIELD(*event, FSF_BB_GLB_EV_RX_RECOVERY)) { + netif_err(efx, rx_err, efx->net_dev, + "channel %d seen global RX_RESET event. Resetting.\n", + channel->channel); + + atomic_inc(&efx->rx_reset); + efx_schedule_reset(efx, EFX_WORKAROUND_6555(efx) ? + RESET_TYPE_RX_RECOVERY : RESET_TYPE_DISABLE); + return true; + } + + return false; +} + /************************************************************************** * * Falcon test code @@ -889,6 +925,7 @@ static void falcon_remove_port(struct efx_nic *efx) static int falcon_read_nvram(struct efx_nic *efx, struct falcon_nvconfig *nvconfig_out) { + struct falcon_nic_data *nic_data = efx->nic_data; struct falcon_nvconfig *nvconfig; struct efx_spi_device *spi; void *region; @@ -896,8 +933,11 @@ falcon_read_nvram(struct efx_nic *efx, struct falcon_nvconfig *nvconfig_out) __le16 *word, *limit; u32 csum; - spi = efx->spi_flash ? efx->spi_flash : efx->spi_eeprom; - if (!spi) + if (efx_spi_present(&nic_data->spi_flash)) + spi = &nic_data->spi_flash; + else if (efx_spi_present(&nic_data->spi_eeprom)) + spi = &nic_data->spi_eeprom; + else return -EINVAL; region = kmalloc(FALCON_NVCONFIG_END, GFP_KERNEL); @@ -905,12 +945,13 @@ falcon_read_nvram(struct efx_nic *efx, struct falcon_nvconfig *nvconfig_out) return -ENOMEM; nvconfig = region + FALCON_NVCONFIG_OFFSET; - mutex_lock(&efx->spi_lock); + mutex_lock(&nic_data->spi_lock); rc = falcon_spi_read(efx, spi, 0, FALCON_NVCONFIG_END, NULL, region); - mutex_unlock(&efx->spi_lock); + mutex_unlock(&nic_data->spi_lock); if (rc) { netif_err(efx, hw, efx->net_dev, "Failed to read %s\n", - efx->spi_flash ? "flash" : "EEPROM"); + efx_spi_present(&nic_data->spi_flash) ? + "flash" : "EEPROM"); rc = -EIO; goto out; } @@ -1012,7 +1053,7 @@ static int falcon_b0_test_registers(struct efx_nic *efx) /* Resets NIC to known state. This routine must be called in process * context and is allowed to sleep. */ -static int falcon_reset_hw(struct efx_nic *efx, enum reset_type method) +static int __falcon_reset_hw(struct efx_nic *efx, enum reset_type method) { struct falcon_nic_data *nic_data = efx->nic_data; efx_oword_t glb_ctl_reg_ker; @@ -1108,6 +1149,18 @@ fail5: return rc; } +static int falcon_reset_hw(struct efx_nic *efx, enum reset_type method) +{ + struct falcon_nic_data *nic_data = efx->nic_data; + int rc; + + mutex_lock(&nic_data->spi_lock); + rc = __falcon_reset_hw(efx, method); + mutex_unlock(&nic_data->spi_lock); + + return rc; +} + static void falcon_monitor(struct efx_nic *efx) { bool link_changed; @@ -1189,16 +1242,11 @@ static int falcon_reset_sram(struct efx_nic *efx) return -ETIMEDOUT; } -static int falcon_spi_device_init(struct efx_nic *efx, - struct efx_spi_device **spi_device_ret, +static void falcon_spi_device_init(struct efx_nic *efx, + struct efx_spi_device *spi_device, unsigned int device_id, u32 device_type) { - struct efx_spi_device *spi_device; - if (device_type != 0) { - spi_device = kzalloc(sizeof(*spi_device), GFP_KERNEL); - if (!spi_device) - return -ENOMEM; spi_device->device_id = device_id; spi_device->size = 1 << SPI_DEV_TYPE_FIELD(device_type, SPI_DEV_TYPE_SIZE); @@ -1215,27 +1263,15 @@ static int falcon_spi_device_init(struct efx_nic *efx, 1 << SPI_DEV_TYPE_FIELD(device_type, SPI_DEV_TYPE_BLOCK_SIZE); } else { - spi_device = NULL; + spi_device->size = 0; } - - kfree(*spi_device_ret); - *spi_device_ret = spi_device; - return 0; -} - -static void falcon_remove_spi_devices(struct efx_nic *efx) -{ - kfree(efx->spi_eeprom); - efx->spi_eeprom = NULL; - kfree(efx->spi_flash); - efx->spi_flash = NULL; } /* Extract non-volatile configuration */ static int falcon_probe_nvconfig(struct efx_nic *efx) { + struct falcon_nic_data *nic_data = efx->nic_data; struct falcon_nvconfig *nvconfig; - int board_rev; int rc; nvconfig = kmalloc(sizeof(*nvconfig), GFP_KERNEL); @@ -1243,55 +1279,32 @@ static int falcon_probe_nvconfig(struct efx_nic *efx) return -ENOMEM; rc = falcon_read_nvram(efx, nvconfig); - if (rc == -EINVAL) { - netif_err(efx, probe, efx->net_dev, - "NVRAM is invalid therefore using defaults\n"); - efx->phy_type = PHY_TYPE_NONE; - efx->mdio.prtad = MDIO_PRTAD_NONE; - board_rev = 0; - rc = 0; - } else if (rc) { - goto fail1; - } else { - struct falcon_nvconfig_board_v2 *v2 = &nvconfig->board_v2; - struct falcon_nvconfig_board_v3 *v3 = &nvconfig->board_v3; - - efx->phy_type = v2->port0_phy_type; - efx->mdio.prtad = v2->port0_phy_addr; - board_rev = le16_to_cpu(v2->board_revision); - - if (le16_to_cpu(nvconfig->board_struct_ver) >= 3) { - rc = falcon_spi_device_init( - efx, &efx->spi_flash, FFE_AB_SPI_DEVICE_FLASH, - le32_to_cpu(v3->spi_device_type - [FFE_AB_SPI_DEVICE_FLASH])); - if (rc) - goto fail2; - rc = falcon_spi_device_init( - efx, &efx->spi_eeprom, FFE_AB_SPI_DEVICE_EEPROM, - le32_to_cpu(v3->spi_device_type - [FFE_AB_SPI_DEVICE_EEPROM])); - if (rc) - goto fail2; - } + if (rc) + goto out; + + efx->phy_type = nvconfig->board_v2.port0_phy_type; + efx->mdio.prtad = nvconfig->board_v2.port0_phy_addr; + + if (le16_to_cpu(nvconfig->board_struct_ver) >= 3) { + falcon_spi_device_init( + efx, &nic_data->spi_flash, FFE_AB_SPI_DEVICE_FLASH, + le32_to_cpu(nvconfig->board_v3 + .spi_device_type[FFE_AB_SPI_DEVICE_FLASH])); + falcon_spi_device_init( + efx, &nic_data->spi_eeprom, FFE_AB_SPI_DEVICE_EEPROM, + le32_to_cpu(nvconfig->board_v3 + .spi_device_type[FFE_AB_SPI_DEVICE_EEPROM])); } /* Read the MAC addresses */ - memcpy(efx->mac_address, nvconfig->mac_address[0], ETH_ALEN); + memcpy(efx->net_dev->perm_addr, nvconfig->mac_address[0], ETH_ALEN); netif_dbg(efx, probe, efx->net_dev, "PHY is %d phy_id %d\n", efx->phy_type, efx->mdio.prtad); - rc = falcon_probe_board(efx, board_rev); - if (rc) - goto fail2; - - kfree(nvconfig); - return 0; - - fail2: - falcon_remove_spi_devices(efx); - fail1: + rc = falcon_probe_board(efx, + le16_to_cpu(nvconfig->board_v2.board_revision)); +out: kfree(nvconfig); return rc; } @@ -1299,6 +1312,7 @@ static int falcon_probe_nvconfig(struct efx_nic *efx) /* Probe all SPI devices on the NIC */ static void falcon_probe_spi_devices(struct efx_nic *efx) { + struct falcon_nic_data *nic_data = efx->nic_data; efx_oword_t nic_stat, gpio_ctl, ee_vpd_cfg; int boot_dev; @@ -1327,12 +1341,14 @@ static void falcon_probe_spi_devices(struct efx_nic *efx) efx_writeo(efx, &ee_vpd_cfg, FR_AB_EE_VPD_CFG0); } + mutex_init(&nic_data->spi_lock); + if (boot_dev == FFE_AB_SPI_DEVICE_FLASH) - falcon_spi_device_init(efx, &efx->spi_flash, + falcon_spi_device_init(efx, &nic_data->spi_flash, FFE_AB_SPI_DEVICE_FLASH, default_flash_type); if (boot_dev == FFE_AB_SPI_DEVICE_EEPROM) - falcon_spi_device_init(efx, &efx->spi_eeprom, + falcon_spi_device_init(efx, &nic_data->spi_eeprom, FFE_AB_SPI_DEVICE_EEPROM, large_eeprom_type); } @@ -1397,7 +1413,7 @@ static int falcon_probe_nic(struct efx_nic *efx) } /* Now we can reset the NIC */ - rc = falcon_reset_hw(efx, RESET_TYPE_ALL); + rc = __falcon_reset_hw(efx, RESET_TYPE_ALL); if (rc) { netif_err(efx, probe, efx->net_dev, "failed to reset NIC\n"); goto fail3; @@ -1419,8 +1435,11 @@ static int falcon_probe_nic(struct efx_nic *efx) /* Read in the non-volatile configuration */ rc = falcon_probe_nvconfig(efx); - if (rc) + if (rc) { + if (rc == -EINVAL) + netif_err(efx, probe, efx->net_dev, "NVRAM is invalid\n"); goto fail5; + } /* Initialise I2C adapter */ board = falcon_board(efx); @@ -1452,7 +1471,6 @@ static int falcon_probe_nic(struct efx_nic *efx) BUG_ON(i2c_del_adapter(&board->i2c_adap)); memset(&board->i2c_adap, 0, sizeof(board->i2c_adap)); fail5: - falcon_remove_spi_devices(efx); efx_nic_free_buffer(efx, &efx->irq_status); fail4: fail3: @@ -1606,10 +1624,9 @@ static void falcon_remove_nic(struct efx_nic *efx) BUG_ON(rc); memset(&board->i2c_adap, 0, sizeof(board->i2c_adap)); - falcon_remove_spi_devices(efx); efx_nic_free_buffer(efx, &efx->irq_status); - falcon_reset_hw(efx, RESET_TYPE_ALL); + __falcon_reset_hw(efx, RESET_TYPE_ALL); /* Release the second function after the reset */ if (nic_data->pci_dev2) { @@ -1720,6 +1737,7 @@ struct efx_nic_type falcon_a1_nic_type = { .reset = falcon_reset_hw, .probe_port = falcon_probe_port, .remove_port = falcon_remove_port, + .handle_global_event = falcon_handle_global_event, .prepare_flush = falcon_prepare_flush, .update_stats = falcon_update_nic_stats, .start_stats = falcon_start_nic_stats, @@ -1760,6 +1778,7 @@ struct efx_nic_type falcon_b0_nic_type = { .reset = falcon_reset_hw, .probe_port = falcon_probe_port, .remove_port = falcon_remove_port, + .handle_global_event = falcon_handle_global_event, .prepare_flush = falcon_prepare_flush, .update_stats = falcon_update_nic_stats, .start_stats = falcon_start_nic_stats, diff --git a/drivers/net/sfc/falcon_boards.c b/drivers/net/sfc/falcon_boards.c index cfc6a5b5a477..2dd16f0b3ced 100644 --- a/drivers/net/sfc/falcon_boards.c +++ b/drivers/net/sfc/falcon_boards.c @@ -13,8 +13,6 @@ #include "phy.h" #include "efx.h" #include "nic.h" -#include "regs.h" -#include "io.h" #include "workarounds.h" /* Macros for unpacking the board revision */ @@ -30,17 +28,28 @@ #define FALCON_BOARD_SFN4112F 0x52 /* Board temperature is about 15°C above ambient when air flow is - * limited. */ + * limited. The maximum acceptable ambient temperature varies + * depending on the PHY specifications but the critical temperature + * above which we should shut down to avoid damage is 80°C. */ #define FALCON_BOARD_TEMP_BIAS 15 +#define FALCON_BOARD_TEMP_CRIT (80 + FALCON_BOARD_TEMP_BIAS) /* SFC4000 datasheet says: 'The maximum permitted junction temperature * is 125°C; the thermal design of the environment for the SFC4000 * should aim to keep this well below 100°C.' */ +#define FALCON_JUNC_TEMP_MIN 0 #define FALCON_JUNC_TEMP_MAX 90 +#define FALCON_JUNC_TEMP_CRIT 125 /***************************************************************************** * Support for LM87 sensor chip used on several boards */ +#define LM87_REG_TEMP_HW_INT_LOCK 0x13 +#define LM87_REG_TEMP_HW_EXT_LOCK 0x14 +#define LM87_REG_TEMP_HW_INT 0x17 +#define LM87_REG_TEMP_HW_EXT 0x18 +#define LM87_REG_TEMP_EXT1 0x26 +#define LM87_REG_TEMP_INT 0x27 #define LM87_REG_ALARMS1 0x41 #define LM87_REG_ALARMS2 0x42 #define LM87_IN_LIMITS(nr, _min, _max) \ @@ -57,6 +66,27 @@ #if defined(CONFIG_SENSORS_LM87) || defined(CONFIG_SENSORS_LM87_MODULE) +static int efx_poke_lm87(struct i2c_client *client, const u8 *reg_values) +{ + while (*reg_values) { + u8 reg = *reg_values++; + u8 value = *reg_values++; + int rc = i2c_smbus_write_byte_data(client, reg, value); + if (rc) + return rc; + } + return 0; +} + +static const u8 falcon_lm87_common_regs[] = { + LM87_REG_TEMP_HW_INT_LOCK, FALCON_BOARD_TEMP_CRIT, + LM87_REG_TEMP_HW_INT, FALCON_BOARD_TEMP_CRIT, + LM87_TEMP_EXT1_LIMITS(FALCON_JUNC_TEMP_MIN, FALCON_JUNC_TEMP_MAX), + LM87_REG_TEMP_HW_EXT_LOCK, FALCON_JUNC_TEMP_CRIT, + LM87_REG_TEMP_HW_EXT, FALCON_JUNC_TEMP_CRIT, + 0 +}; + static int efx_init_lm87(struct efx_nic *efx, struct i2c_board_info *info, const u8 *reg_values) { @@ -67,13 +97,16 @@ static int efx_init_lm87(struct efx_nic *efx, struct i2c_board_info *info, if (!client) return -EIO; - while (*reg_values) { - u8 reg = *reg_values++; - u8 value = *reg_values++; - rc = i2c_smbus_write_byte_data(client, reg, value); - if (rc) - goto err; - } + /* Read-to-clear alarm/interrupt status */ + i2c_smbus_read_byte_data(client, LM87_REG_ALARMS1); + i2c_smbus_read_byte_data(client, LM87_REG_ALARMS2); + + rc = efx_poke_lm87(client, reg_values); + if (rc) + goto err; + rc = efx_poke_lm87(client, falcon_lm87_common_regs); + if (rc) + goto err; board->hwmon_client = client; return 0; @@ -91,36 +124,56 @@ static void efx_fini_lm87(struct efx_nic *efx) static int efx_check_lm87(struct efx_nic *efx, unsigned mask) { struct i2c_client *client = falcon_board(efx)->hwmon_client; - s32 alarms1, alarms2; + bool temp_crit, elec_fault, is_failure; + u16 alarms; + s32 reg; /* If link is up then do not monitor temperature */ if (EFX_WORKAROUND_7884(efx) && efx->link_state.up) return 0; - alarms1 = i2c_smbus_read_byte_data(client, LM87_REG_ALARMS1); - alarms2 = i2c_smbus_read_byte_data(client, LM87_REG_ALARMS2); - if (alarms1 < 0) - return alarms1; - if (alarms2 < 0) - return alarms2; - alarms1 &= mask; - alarms2 &= mask >> 8; - if (alarms1 || alarms2) { + reg = i2c_smbus_read_byte_data(client, LM87_REG_ALARMS1); + if (reg < 0) + return reg; + alarms = reg; + reg = i2c_smbus_read_byte_data(client, LM87_REG_ALARMS2); + if (reg < 0) + return reg; + alarms |= reg << 8; + alarms &= mask; + + temp_crit = false; + if (alarms & LM87_ALARM_TEMP_INT) { + reg = i2c_smbus_read_byte_data(client, LM87_REG_TEMP_INT); + if (reg < 0) + return reg; + if (reg > FALCON_BOARD_TEMP_CRIT) + temp_crit = true; + } + if (alarms & LM87_ALARM_TEMP_EXT1) { + reg = i2c_smbus_read_byte_data(client, LM87_REG_TEMP_EXT1); + if (reg < 0) + return reg; + if (reg > FALCON_JUNC_TEMP_CRIT) + temp_crit = true; + } + elec_fault = alarms & ~(LM87_ALARM_TEMP_INT | LM87_ALARM_TEMP_EXT1); + is_failure = temp_crit || elec_fault; + + if (alarms) netif_err(efx, hw, efx->net_dev, - "LM87 detected a hardware failure (status %02x:%02x)" - "%s%s%s\n", - alarms1, alarms2, - (alarms1 & LM87_ALARM_TEMP_INT) ? + "LM87 detected a hardware %s (status %02x:%02x)" + "%s%s%s%s\n", + is_failure ? "failure" : "problem", + alarms & 0xff, alarms >> 8, + (alarms & LM87_ALARM_TEMP_INT) ? "; board is overheating" : "", - (alarms1 & LM87_ALARM_TEMP_EXT1) ? + (alarms & LM87_ALARM_TEMP_EXT1) ? "; controller is overheating" : "", - (alarms1 & ~(LM87_ALARM_TEMP_INT | LM87_ALARM_TEMP_EXT1) - || alarms2) ? - "; electrical fault" : ""); - return -ERANGE; - } + temp_crit ? "; reached critical temperature" : "", + elec_fault ? "; electrical fault" : ""); - return 0; + return is_failure ? -ERANGE : 0; } #else /* !CONFIG_SENSORS_LM87 */ @@ -325,7 +378,7 @@ static ssize_t set_phy_flash_cfg(struct device *dev, new_mode = old_mode & ~PHY_MODE_SPECIAL; else new_mode = PHY_MODE_SPECIAL; - if (old_mode == new_mode) { + if (!((old_mode ^ new_mode) & PHY_MODE_SPECIAL)) { err = 0; } else if (efx->state != STATE_RUNNING || netif_running(efx->net_dev)) { err = -EBUSY; @@ -362,10 +415,11 @@ static void sfe4001_fini(struct efx_nic *efx) static int sfe4001_check_hw(struct efx_nic *efx) { + struct falcon_nic_data *nic_data = efx->nic_data; s32 status; /* If XAUI link is up then do not monitor */ - if (EFX_WORKAROUND_7884(efx) && !efx->xmac_poll_required) + if (EFX_WORKAROUND_7884(efx) && !nic_data->xmac_poll_required) return 0; /* Check the powered status of the PHY. Lack of power implies that diff --git a/drivers/net/sfc/falcon_xmac.c b/drivers/net/sfc/falcon_xmac.c index b31f595ebb5b..b49e84394641 100644 --- a/drivers/net/sfc/falcon_xmac.c +++ b/drivers/net/sfc/falcon_xmac.c @@ -16,7 +16,6 @@ #include "io.h" #include "mac.h" #include "mdio_10g.h" -#include "phy.h" #include "workarounds.h" /************************************************************************** @@ -88,6 +87,7 @@ int falcon_reset_xaui(struct efx_nic *efx) static void falcon_ack_status_intr(struct efx_nic *efx) { + struct falcon_nic_data *nic_data = efx->nic_data; efx_oword_t reg; if ((efx_nic_rev(efx) != EFX_REV_FALCON_B0) || LOOPBACK_INTERNAL(efx)) @@ -99,7 +99,7 @@ static void falcon_ack_status_intr(struct efx_nic *efx) /* We can only use this interrupt to signal the negative edge of * xaui_align [we have to poll the positive edge]. */ - if (efx->xmac_poll_required) + if (nic_data->xmac_poll_required) return; efx_reado(efx, ®, FR_AB_XM_MGT_INT_MSK); @@ -277,12 +277,14 @@ static bool falcon_xmac_check_fault(struct efx_nic *efx) static int falcon_reconfigure_xmac(struct efx_nic *efx) { + struct falcon_nic_data *nic_data = efx->nic_data; + falcon_reconfigure_xgxs_core(efx); falcon_reconfigure_xmac_core(efx); falcon_reconfigure_mac_wrapper(efx); - efx->xmac_poll_required = !falcon_xmac_link_ok_retry(efx, 5); + nic_data->xmac_poll_required = !falcon_xmac_link_ok_retry(efx, 5); falcon_ack_status_intr(efx); return 0; @@ -350,11 +352,13 @@ static void falcon_update_stats_xmac(struct efx_nic *efx) void falcon_poll_xmac(struct efx_nic *efx) { + struct falcon_nic_data *nic_data = efx->nic_data; + if (!EFX_WORKAROUND_5147(efx) || !efx->link_state.up || - !efx->xmac_poll_required) + !nic_data->xmac_poll_required) return; - efx->xmac_poll_required = !falcon_xmac_link_ok_retry(efx, 1); + nic_data->xmac_poll_required = !falcon_xmac_link_ok_retry(efx, 1); falcon_ack_status_intr(efx); } diff --git a/drivers/net/sfc/filter.c b/drivers/net/sfc/filter.c index 52cb6082b910..44500b54fd5f 100644 --- a/drivers/net/sfc/filter.c +++ b/drivers/net/sfc/filter.c @@ -428,10 +428,9 @@ int efx_probe_filters(struct efx_nic *efx) GFP_KERNEL); if (!table->used_bitmap) goto fail; - table->spec = vmalloc(table->size * sizeof(*table->spec)); + table->spec = vzalloc(table->size * sizeof(*table->spec)); if (!table->spec) goto fail; - memset(table->spec, 0, table->size * sizeof(*table->spec)); } return 0; diff --git a/drivers/net/sfc/mcdi.c b/drivers/net/sfc/mcdi.c index 12cf910c2ce7..b716e827b291 100644 --- a/drivers/net/sfc/mcdi.c +++ b/drivers/net/sfc/mcdi.c @@ -381,7 +381,7 @@ int efx_mcdi_rpc(struct efx_nic *efx, unsigned cmd, -rc); efx_schedule_reset(efx, RESET_TYPE_MC_FAILURE); } else - netif_err(efx, hw, efx->net_dev, + netif_dbg(efx, hw, efx->net_dev, "MC command 0x%x inlen %d failed rc=%d\n", cmd, (int)inlen, -rc); } @@ -463,6 +463,7 @@ static void efx_mcdi_ev_death(struct efx_nic *efx, int rc) if (mcdi->mode == MCDI_MODE_EVENTS) { mcdi->resprc = rc; mcdi->resplen = 0; + ++mcdi->credits; } } else /* Nobody was waiting for an MCDI request, so trigger a reset */ diff --git a/drivers/net/sfc/mcdi_phy.c b/drivers/net/sfc/mcdi_phy.c index c992742446b1..0e97eed663c6 100644 --- a/drivers/net/sfc/mcdi_phy.c +++ b/drivers/net/sfc/mcdi_phy.c @@ -16,7 +16,6 @@ #include "phy.h" #include "mcdi.h" #include "mcdi_pcol.h" -#include "mdio_10g.h" #include "nic.h" #include "selftest.h" diff --git a/drivers/net/sfc/mdio_10g.c b/drivers/net/sfc/mdio_10g.c index 98d946020429..56b0266b441f 100644 --- a/drivers/net/sfc/mdio_10g.c +++ b/drivers/net/sfc/mdio_10g.c @@ -15,7 +15,6 @@ #include "net_driver.h" #include "mdio_10g.h" #include "workarounds.h" -#include "nic.h" unsigned efx_mdio_id_oui(u32 id) { diff --git a/drivers/net/sfc/mtd.c b/drivers/net/sfc/mtd.c index 02e54b4f701f..d38627448c22 100644 --- a/drivers/net/sfc/mtd.c +++ b/drivers/net/sfc/mtd.c @@ -321,14 +321,15 @@ static int falcon_mtd_read(struct mtd_info *mtd, loff_t start, struct efx_mtd *efx_mtd = mtd->priv; const struct efx_spi_device *spi = efx_mtd->spi; struct efx_nic *efx = efx_mtd->efx; + struct falcon_nic_data *nic_data = efx->nic_data; int rc; - rc = mutex_lock_interruptible(&efx->spi_lock); + rc = mutex_lock_interruptible(&nic_data->spi_lock); if (rc) return rc; rc = falcon_spi_read(efx, spi, part->offset + start, len, retlen, buffer); - mutex_unlock(&efx->spi_lock); + mutex_unlock(&nic_data->spi_lock); return rc; } @@ -337,13 +338,14 @@ static int falcon_mtd_erase(struct mtd_info *mtd, loff_t start, size_t len) struct efx_mtd_partition *part = to_efx_mtd_partition(mtd); struct efx_mtd *efx_mtd = mtd->priv; struct efx_nic *efx = efx_mtd->efx; + struct falcon_nic_data *nic_data = efx->nic_data; int rc; - rc = mutex_lock_interruptible(&efx->spi_lock); + rc = mutex_lock_interruptible(&nic_data->spi_lock); if (rc) return rc; rc = efx_spi_erase(part, part->offset + start, len); - mutex_unlock(&efx->spi_lock); + mutex_unlock(&nic_data->spi_lock); return rc; } @@ -354,14 +356,15 @@ static int falcon_mtd_write(struct mtd_info *mtd, loff_t start, struct efx_mtd *efx_mtd = mtd->priv; const struct efx_spi_device *spi = efx_mtd->spi; struct efx_nic *efx = efx_mtd->efx; + struct falcon_nic_data *nic_data = efx->nic_data; int rc; - rc = mutex_lock_interruptible(&efx->spi_lock); + rc = mutex_lock_interruptible(&nic_data->spi_lock); if (rc) return rc; rc = falcon_spi_write(efx, spi, part->offset + start, len, retlen, buffer); - mutex_unlock(&efx->spi_lock); + mutex_unlock(&nic_data->spi_lock); return rc; } @@ -370,11 +373,12 @@ static int falcon_mtd_sync(struct mtd_info *mtd) struct efx_mtd_partition *part = to_efx_mtd_partition(mtd); struct efx_mtd *efx_mtd = mtd->priv; struct efx_nic *efx = efx_mtd->efx; + struct falcon_nic_data *nic_data = efx->nic_data; int rc; - mutex_lock(&efx->spi_lock); + mutex_lock(&nic_data->spi_lock); rc = efx_spi_slow_wait(part, true); - mutex_unlock(&efx->spi_lock); + mutex_unlock(&nic_data->spi_lock); return rc; } @@ -387,35 +391,67 @@ static struct efx_mtd_ops falcon_mtd_ops = { static int falcon_mtd_probe(struct efx_nic *efx) { - struct efx_spi_device *spi = efx->spi_flash; + struct falcon_nic_data *nic_data = efx->nic_data; + struct efx_spi_device *spi; struct efx_mtd *efx_mtd; - int rc; + int rc = -ENODEV; ASSERT_RTNL(); - if (!spi || spi->size <= FALCON_FLASH_BOOTCODE_START) - return -ENODEV; - - efx_mtd = kzalloc(sizeof(*efx_mtd) + sizeof(efx_mtd->part[0]), - GFP_KERNEL); - if (!efx_mtd) - return -ENOMEM; - - efx_mtd->spi = spi; - efx_mtd->name = "flash"; - efx_mtd->ops = &falcon_mtd_ops; + spi = &nic_data->spi_flash; + if (efx_spi_present(spi) && spi->size > FALCON_FLASH_BOOTCODE_START) { + efx_mtd = kzalloc(sizeof(*efx_mtd) + sizeof(efx_mtd->part[0]), + GFP_KERNEL); + if (!efx_mtd) + return -ENOMEM; + + efx_mtd->spi = spi; + efx_mtd->name = "flash"; + efx_mtd->ops = &falcon_mtd_ops; + + efx_mtd->n_parts = 1; + efx_mtd->part[0].mtd.type = MTD_NORFLASH; + efx_mtd->part[0].mtd.flags = MTD_CAP_NORFLASH; + efx_mtd->part[0].mtd.size = spi->size - FALCON_FLASH_BOOTCODE_START; + efx_mtd->part[0].mtd.erasesize = spi->erase_size; + efx_mtd->part[0].offset = FALCON_FLASH_BOOTCODE_START; + efx_mtd->part[0].type_name = "sfc_flash_bootrom"; + + rc = efx_mtd_probe_device(efx, efx_mtd); + if (rc) { + kfree(efx_mtd); + return rc; + } + } - efx_mtd->n_parts = 1; - efx_mtd->part[0].mtd.type = MTD_NORFLASH; - efx_mtd->part[0].mtd.flags = MTD_CAP_NORFLASH; - efx_mtd->part[0].mtd.size = spi->size - FALCON_FLASH_BOOTCODE_START; - efx_mtd->part[0].mtd.erasesize = spi->erase_size; - efx_mtd->part[0].offset = FALCON_FLASH_BOOTCODE_START; - efx_mtd->part[0].type_name = "sfc_flash_bootrom"; + spi = &nic_data->spi_eeprom; + if (efx_spi_present(spi) && spi->size > EFX_EEPROM_BOOTCONFIG_START) { + efx_mtd = kzalloc(sizeof(*efx_mtd) + sizeof(efx_mtd->part[0]), + GFP_KERNEL); + if (!efx_mtd) + return -ENOMEM; + + efx_mtd->spi = spi; + efx_mtd->name = "EEPROM"; + efx_mtd->ops = &falcon_mtd_ops; + + efx_mtd->n_parts = 1; + efx_mtd->part[0].mtd.type = MTD_RAM; + efx_mtd->part[0].mtd.flags = MTD_CAP_RAM; + efx_mtd->part[0].mtd.size = + min(spi->size, EFX_EEPROM_BOOTCONFIG_END) - + EFX_EEPROM_BOOTCONFIG_START; + efx_mtd->part[0].mtd.erasesize = spi->erase_size; + efx_mtd->part[0].offset = EFX_EEPROM_BOOTCONFIG_START; + efx_mtd->part[0].type_name = "sfc_bootconfig"; + + rc = efx_mtd_probe_device(efx, efx_mtd); + if (rc) { + kfree(efx_mtd); + return rc; + } + } - rc = efx_mtd_probe_device(efx, efx_mtd); - if (rc) - kfree(efx_mtd); return rc; } diff --git a/drivers/net/sfc/net_driver.h b/drivers/net/sfc/net_driver.h index 0a7e26d73b52..0d19fbfc5c2c 100644 --- a/drivers/net/sfc/net_driver.h +++ b/drivers/net/sfc/net_driver.h @@ -647,6 +647,7 @@ struct efx_filter_state; * @n_tx_channels: Number of channels used for TX * @rx_buffer_len: RX buffer length * @rx_buffer_order: Order (log2) of number of pages for each RX buffer + * @rx_hash_key: Toeplitz hash key for RSS * @rx_indir_table: Indirection table for RSS * @int_error_count: Number of internal errors seen recently * @int_error_expire: Time at which error count will be expired @@ -657,11 +658,6 @@ struct efx_filter_state; * to verify that an interrupt has occurred. * @irq_zero_count: Number of legacy IRQs seen with queue flags == 0 * @fatal_irq_level: IRQ level (bit number) used for serious errors - * @spi_flash: SPI flash device - * This field will be %NULL if no flash device is present (or for Siena). - * @spi_eeprom: SPI EEPROM device - * This field will be %NULL if no EEPROM device is present (or for Siena). - * @spi_lock: SPI bus lock * @mtd_list: List of MTDs attached to the NIC * @n_rx_nodesc_drop_cnt: RX no descriptor drop count * @nic_data: Hardware dependant state @@ -682,15 +678,12 @@ struct efx_filter_state; * @stats_buffer: DMA buffer for statistics * @stats_lock: Statistics update lock. Serialises statistics fetches * @mac_op: MAC interface - * @mac_address: Permanent MAC address * @phy_type: PHY type - * @mdio_lock: MDIO lock * @phy_op: PHY interface * @phy_data: PHY private data (including PHY-specific stats) * @mdio: PHY MDIO interface * @mdio_bus: PHY MDIO bus ID (only used by Siena) * @phy_mode: PHY operating mode. Serialised by @mac_lock. - * @xmac_poll_required: XMAC link state needs polling * @link_advertising: Autonegotiation advertising flags * @link_state: Current state of the link * @n_link_state_changes: Number of times the link has changed state @@ -746,9 +739,6 @@ struct efx_nic { unsigned irq_zero_count; unsigned fatal_irq_level; - struct efx_spi_device *spi_flash; - struct efx_spi_device *spi_eeprom; - struct mutex spi_lock; #ifdef CONFIG_SFC_MTD struct list_head mtd_list; #endif @@ -771,17 +761,14 @@ struct efx_nic { spinlock_t stats_lock; struct efx_mac_operations *mac_op; - unsigned char mac_address[ETH_ALEN]; unsigned int phy_type; - struct mutex mdio_lock; struct efx_phy_operations *phy_op; void *phy_data; struct mdio_if_info mdio; unsigned int mdio_bus; enum efx_phy_mode phy_mode; - bool xmac_poll_required; u32 link_advertising; struct efx_link_state link_state; unsigned int n_link_state_changes; @@ -829,6 +816,7 @@ static inline unsigned int efx_port_num(struct efx_nic *efx) * be called while the controller is uninitialised. * @probe_port: Probe the MAC and PHY * @remove_port: Free resources allocated by probe_port() + * @handle_global_event: Handle a "global" event (may be %NULL) * @prepare_flush: Prepare the hardware for flushing the DMA queues * @update_stats: Update statistics not provided by event handling * @start_stats: Start the regular fetching of statistics @@ -873,6 +861,7 @@ struct efx_nic_type { int (*reset)(struct efx_nic *efx, enum reset_type method); int (*probe_port)(struct efx_nic *efx); void (*remove_port)(struct efx_nic *efx); + bool (*handle_global_event)(struct efx_channel *channel, efx_qword_t *); void (*prepare_flush)(struct efx_nic *efx); void (*update_stats)(struct efx_nic *efx); void (*start_stats)(struct efx_nic *efx); diff --git a/drivers/net/sfc/nic.c b/drivers/net/sfc/nic.c index 41c36b9a4244..9743cff15130 100644 --- a/drivers/net/sfc/nic.c +++ b/drivers/net/sfc/nic.c @@ -894,46 +894,6 @@ efx_handle_generated_event(struct efx_channel *channel, efx_qword_t *event) channel->channel, EFX_QWORD_VAL(*event)); } -/* Global events are basically PHY events */ -static void -efx_handle_global_event(struct efx_channel *channel, efx_qword_t *event) -{ - struct efx_nic *efx = channel->efx; - bool handled = false; - - if (EFX_QWORD_FIELD(*event, FSF_AB_GLB_EV_G_PHY0_INTR) || - EFX_QWORD_FIELD(*event, FSF_AB_GLB_EV_XG_PHY0_INTR) || - EFX_QWORD_FIELD(*event, FSF_AB_GLB_EV_XFP_PHY0_INTR)) { - /* Ignored */ - handled = true; - } - - if ((efx_nic_rev(efx) >= EFX_REV_FALCON_B0) && - EFX_QWORD_FIELD(*event, FSF_BB_GLB_EV_XG_MGT_INTR)) { - efx->xmac_poll_required = true; - handled = true; - } - - if (efx_nic_rev(efx) <= EFX_REV_FALCON_A1 ? - EFX_QWORD_FIELD(*event, FSF_AA_GLB_EV_RX_RECOVERY) : - EFX_QWORD_FIELD(*event, FSF_BB_GLB_EV_RX_RECOVERY)) { - netif_err(efx, rx_err, efx->net_dev, - "channel %d seen global RX_RESET event. Resetting.\n", - channel->channel); - - atomic_inc(&efx->rx_reset); - efx_schedule_reset(efx, EFX_WORKAROUND_6555(efx) ? - RESET_TYPE_RX_RECOVERY : RESET_TYPE_DISABLE); - handled = true; - } - - if (!handled) - netif_err(efx, hw, efx->net_dev, - "channel %d unknown global event " - EFX_QWORD_FMT "\n", channel->channel, - EFX_QWORD_VAL(*event)); -} - static void efx_handle_driver_event(struct efx_channel *channel, efx_qword_t *event) { @@ -1050,15 +1010,17 @@ int efx_nic_process_eventq(struct efx_channel *channel, int budget) case FSE_AZ_EV_CODE_DRV_GEN_EV: efx_handle_generated_event(channel, &event); break; - case FSE_AZ_EV_CODE_GLOBAL_EV: - efx_handle_global_event(channel, &event); - break; case FSE_AZ_EV_CODE_DRIVER_EV: efx_handle_driver_event(channel, &event); break; case FSE_CZ_EV_CODE_MCDI_EV: efx_mcdi_process_event(channel, &event); break; + case FSE_AZ_EV_CODE_GLOBAL_EV: + if (efx->type->handle_global_event && + efx->type->handle_global_event(channel, &event)) + break; + /* else fall through */ default: netif_err(channel->efx, hw, channel->efx->net_dev, "channel %d unknown event type %d (data " diff --git a/drivers/net/sfc/nic.h b/drivers/net/sfc/nic.h index 0438dc98722d..eb0586925b51 100644 --- a/drivers/net/sfc/nic.h +++ b/drivers/net/sfc/nic.h @@ -15,6 +15,7 @@ #include "net_driver.h" #include "efx.h" #include "mcdi.h" +#include "spi.h" /* * Falcon hardware control @@ -113,6 +114,11 @@ struct falcon_board { * @stats_pending: Is there a pending DMA of MAC statistics. * @stats_timer: A timer for regularly fetching MAC statistics. * @stats_dma_done: Pointer to the flag which indicates DMA completion. + * @spi_flash: SPI flash device + * @spi_eeprom: SPI EEPROM device + * @spi_lock: SPI bus lock + * @mdio_lock: MDIO bus lock + * @xmac_poll_required: XMAC link state needs polling */ struct falcon_nic_data { struct pci_dev *pci_dev2; @@ -121,6 +127,11 @@ struct falcon_nic_data { bool stats_pending; struct timer_list stats_timer; u32 *stats_dma_done; + struct efx_spi_device spi_flash; + struct efx_spi_device spi_eeprom; + struct mutex spi_lock; + struct mutex mdio_lock; + bool xmac_poll_required; }; static inline struct falcon_board *falcon_board(struct efx_nic *efx) @@ -135,7 +146,6 @@ static inline struct falcon_board *falcon_board(struct efx_nic *efx) * @fw_build: Firmware build number * @mcdi: Management-Controller-to-Driver Interface * @wol_filter_id: Wake-on-LAN packet filter id - * @ipv6_rss_key: Toeplitz hash key for IPv6 RSS */ struct siena_nic_data { u64 fw_version; diff --git a/drivers/net/sfc/qt202x_phy.c b/drivers/net/sfc/qt202x_phy.c index 68813d1d85f3..ea3ae0089315 100644 --- a/drivers/net/sfc/qt202x_phy.c +++ b/drivers/net/sfc/qt202x_phy.c @@ -41,6 +41,8 @@ #define PCS_UC_STATUS_LBN 0 #define PCS_UC_STATUS_WIDTH 8 #define PCS_UC_STATUS_FW_SAVE 0x20 +#define PMA_PMD_MODE_REG 0xc301 +#define PMA_PMD_RXIN_SEL_LBN 6 #define PMA_PMD_FTX_CTRL2_REG 0xc309 #define PMA_PMD_FTX_STATIC_LBN 13 #define PMA_PMD_VEND1_REG 0xc001 @@ -282,6 +284,10 @@ static int qt2025c_select_phy_mode(struct efx_nic *efx) * slow) reload of the firmware image (the microcontroller's code * memory is not affected by the microcontroller reset). */ efx_mdio_write(efx, 1, 0xc317, 0x00ff); + /* PMA/PMD loopback sets RXIN to inverse polarity and the firmware + * restart doesn't reset it. We need to do that ourselves. */ + efx_mdio_set_flag(efx, 1, PMA_PMD_MODE_REG, + 1 << PMA_PMD_RXIN_SEL_LBN, false); efx_mdio_write(efx, 1, 0xc300, 0x0002); msleep(20); diff --git a/drivers/net/sfc/siena.c b/drivers/net/sfc/siena.c index 45236f58a258..bf8456176443 100644 --- a/drivers/net/sfc/siena.c +++ b/drivers/net/sfc/siena.c @@ -194,13 +194,7 @@ static int siena_reset_hw(struct efx_nic *efx, enum reset_type method) static int siena_probe_nvconfig(struct efx_nic *efx) { - int rc; - - rc = efx_mcdi_get_board_cfg(efx, efx->mac_address, NULL); - if (rc) - return rc; - - return 0; + return efx_mcdi_get_board_cfg(efx, efx->net_dev->perm_addr, NULL); } static int siena_probe_nic(struct efx_nic *efx) @@ -562,7 +556,7 @@ static int siena_set_wol(struct efx_nic *efx, u32 type) if (nic_data->wol_filter_id != -1) efx_mcdi_wol_filter_remove(efx, nic_data->wol_filter_id); - rc = efx_mcdi_wol_filter_set_magic(efx, efx->mac_address, + rc = efx_mcdi_wol_filter_set_magic(efx, efx->net_dev->dev_addr, &nic_data->wol_filter_id); if (rc) goto fail; diff --git a/drivers/net/sfc/spi.h b/drivers/net/sfc/spi.h index 8bf4fce0813a..879b7f6bde3d 100644 --- a/drivers/net/sfc/spi.h +++ b/drivers/net/sfc/spi.h @@ -61,6 +61,11 @@ struct efx_spi_device { unsigned int block_size; }; +static inline bool efx_spi_present(const struct efx_spi_device *spi) +{ + return spi->size != 0; +} + int falcon_spi_cmd(struct efx_nic *efx, const struct efx_spi_device *spi, unsigned int command, int address, const void* in, void *out, size_t len); diff --git a/drivers/net/sfc/tenxpress.c b/drivers/net/sfc/tenxpress.c index 1bc6c48c96ee..f102912eba91 100644 --- a/drivers/net/sfc/tenxpress.c +++ b/drivers/net/sfc/tenxpress.c @@ -15,9 +15,7 @@ #include "mdio_10g.h" #include "nic.h" #include "phy.h" -#include "regs.h" #include "workarounds.h" -#include "selftest.h" /* We expect these MMDs to be in the package. */ #define TENXPRESS_REQUIRED_DEVS (MDIO_DEVS_PMAPMD | \ diff --git a/drivers/net/sfc/tx.c b/drivers/net/sfc/tx.c index 11726989fe2d..03194f7c0954 100644 --- a/drivers/net/sfc/tx.c +++ b/drivers/net/sfc/tx.c @@ -401,6 +401,7 @@ void efx_xmit_done(struct efx_tx_queue *tx_queue, unsigned int index) { unsigned fill_level; struct efx_nic *efx = tx_queue->efx; + struct netdev_queue *queue; EFX_BUG_ON_PARANOID(index > tx_queue->ptr_mask); @@ -417,12 +418,15 @@ void efx_xmit_done(struct efx_tx_queue *tx_queue, unsigned int index) /* Do this under netif_tx_lock(), to avoid racing * with efx_xmit(). */ - netif_tx_lock(efx->net_dev); + queue = netdev_get_tx_queue( + efx->net_dev, + tx_queue->queue / EFX_TXQ_TYPES); + __netif_tx_lock(queue, smp_processor_id()); if (tx_queue->stopped) { tx_queue->stopped = 0; efx_wake_queue(tx_queue->channel); } - netif_tx_unlock(efx->net_dev); + __netif_tx_unlock(queue); } } } diff --git a/drivers/net/sh_eth.c b/drivers/net/sh_eth.c index 50259dfec583..b12660d72338 100644 --- a/drivers/net/sh_eth.c +++ b/drivers/net/sh_eth.c @@ -45,9 +45,9 @@ static void sh_eth_set_duplex(struct net_device *ndev) u32 ioaddr = ndev->base_addr; if (mdp->duplex) /* Full */ - ctrl_outl(ctrl_inl(ioaddr + ECMR) | ECMR_DM, ioaddr + ECMR); + writel(readl(ioaddr + ECMR) | ECMR_DM, ioaddr + ECMR); else /* Half */ - ctrl_outl(ctrl_inl(ioaddr + ECMR) & ~ECMR_DM, ioaddr + ECMR); + writel(readl(ioaddr + ECMR) & ~ECMR_DM, ioaddr + ECMR); } static void sh_eth_set_rate(struct net_device *ndev) @@ -57,10 +57,10 @@ static void sh_eth_set_rate(struct net_device *ndev) switch (mdp->speed) { case 10: /* 10BASE */ - ctrl_outl(ctrl_inl(ioaddr + ECMR) & ~ECMR_RTM, ioaddr + ECMR); + writel(readl(ioaddr + ECMR) & ~ECMR_RTM, ioaddr + ECMR); break; case 100:/* 100BASE */ - ctrl_outl(ctrl_inl(ioaddr + ECMR) | ECMR_RTM, ioaddr + ECMR); + writel(readl(ioaddr + ECMR) | ECMR_RTM, ioaddr + ECMR); break; default: break; @@ -96,9 +96,9 @@ static void sh_eth_set_duplex(struct net_device *ndev) u32 ioaddr = ndev->base_addr; if (mdp->duplex) /* Full */ - ctrl_outl(ctrl_inl(ioaddr + ECMR) | ECMR_DM, ioaddr + ECMR); + writel(readl(ioaddr + ECMR) | ECMR_DM, ioaddr + ECMR); else /* Half */ - ctrl_outl(ctrl_inl(ioaddr + ECMR) & ~ECMR_DM, ioaddr + ECMR); + writel(readl(ioaddr + ECMR) & ~ECMR_DM, ioaddr + ECMR); } static void sh_eth_set_rate(struct net_device *ndev) @@ -108,10 +108,10 @@ static void sh_eth_set_rate(struct net_device *ndev) switch (mdp->speed) { case 10: /* 10BASE */ - ctrl_outl(0, ioaddr + RTRATE); + writel(0, ioaddr + RTRATE); break; case 100:/* 100BASE */ - ctrl_outl(1, ioaddr + RTRATE); + writel(1, ioaddr + RTRATE); break; default: break; @@ -143,7 +143,7 @@ static struct sh_eth_cpu_data sh_eth_my_cpu_data = { static void sh_eth_chip_reset(struct net_device *ndev) { /* reset device */ - ctrl_outl(ARSTR_ARSTR, ARSTR); + writel(ARSTR_ARSTR, ARSTR); mdelay(1); } @@ -152,10 +152,10 @@ static void sh_eth_reset(struct net_device *ndev) u32 ioaddr = ndev->base_addr; int cnt = 100; - ctrl_outl(EDSR_ENALL, ioaddr + EDSR); - ctrl_outl(ctrl_inl(ioaddr + EDMR) | EDMR_SRST, ioaddr + EDMR); + writel(EDSR_ENALL, ioaddr + EDSR); + writel(readl(ioaddr + EDMR) | EDMR_SRST, ioaddr + EDMR); while (cnt > 0) { - if (!(ctrl_inl(ioaddr + EDMR) & 0x3)) + if (!(readl(ioaddr + EDMR) & 0x3)) break; mdelay(1); cnt--; @@ -164,14 +164,14 @@ static void sh_eth_reset(struct net_device *ndev) printk(KERN_ERR "Device reset fail\n"); /* Table Init */ - ctrl_outl(0x0, ioaddr + TDLAR); - ctrl_outl(0x0, ioaddr + TDFAR); - ctrl_outl(0x0, ioaddr + TDFXR); - ctrl_outl(0x0, ioaddr + TDFFR); - ctrl_outl(0x0, ioaddr + RDLAR); - ctrl_outl(0x0, ioaddr + RDFAR); - ctrl_outl(0x0, ioaddr + RDFXR); - ctrl_outl(0x0, ioaddr + RDFFR); + writel(0x0, ioaddr + TDLAR); + writel(0x0, ioaddr + TDFAR); + writel(0x0, ioaddr + TDFXR); + writel(0x0, ioaddr + TDFFR); + writel(0x0, ioaddr + RDLAR); + writel(0x0, ioaddr + RDFAR); + writel(0x0, ioaddr + RDFXR); + writel(0x0, ioaddr + RDFFR); } static void sh_eth_set_duplex(struct net_device *ndev) @@ -180,9 +180,9 @@ static void sh_eth_set_duplex(struct net_device *ndev) u32 ioaddr = ndev->base_addr; if (mdp->duplex) /* Full */ - ctrl_outl(ctrl_inl(ioaddr + ECMR) | ECMR_DM, ioaddr + ECMR); + writel(readl(ioaddr + ECMR) | ECMR_DM, ioaddr + ECMR); else /* Half */ - ctrl_outl(ctrl_inl(ioaddr + ECMR) & ~ECMR_DM, ioaddr + ECMR); + writel(readl(ioaddr + ECMR) & ~ECMR_DM, ioaddr + ECMR); } static void sh_eth_set_rate(struct net_device *ndev) @@ -192,13 +192,13 @@ static void sh_eth_set_rate(struct net_device *ndev) switch (mdp->speed) { case 10: /* 10BASE */ - ctrl_outl(GECMR_10, ioaddr + GECMR); + writel(GECMR_10, ioaddr + GECMR); break; case 100:/* 100BASE */ - ctrl_outl(GECMR_100, ioaddr + GECMR); + writel(GECMR_100, ioaddr + GECMR); break; case 1000: /* 1000BASE */ - ctrl_outl(GECMR_1000, ioaddr + GECMR); + writel(GECMR_1000, ioaddr + GECMR); break; default: break; @@ -283,9 +283,9 @@ static void sh_eth_reset(struct net_device *ndev) { u32 ioaddr = ndev->base_addr; - ctrl_outl(ctrl_inl(ioaddr + EDMR) | EDMR_SRST, ioaddr + EDMR); + writel(readl(ioaddr + EDMR) | EDMR_SRST, ioaddr + EDMR); mdelay(3); - ctrl_outl(ctrl_inl(ioaddr + EDMR) & ~EDMR_SRST, ioaddr + EDMR); + writel(readl(ioaddr + EDMR) & ~EDMR_SRST, ioaddr + EDMR); } #endif @@ -336,10 +336,10 @@ static void update_mac_address(struct net_device *ndev) { u32 ioaddr = ndev->base_addr; - ctrl_outl((ndev->dev_addr[0] << 24) | (ndev->dev_addr[1] << 16) | + writel((ndev->dev_addr[0] << 24) | (ndev->dev_addr[1] << 16) | (ndev->dev_addr[2] << 8) | (ndev->dev_addr[3]), ioaddr + MAHR); - ctrl_outl((ndev->dev_addr[4] << 8) | (ndev->dev_addr[5]), + writel((ndev->dev_addr[4] << 8) | (ndev->dev_addr[5]), ioaddr + MALR); } @@ -358,12 +358,12 @@ static void read_mac_address(struct net_device *ndev, unsigned char *mac) if (mac[0] || mac[1] || mac[2] || mac[3] || mac[4] || mac[5]) { memcpy(ndev->dev_addr, mac, 6); } else { - ndev->dev_addr[0] = (ctrl_inl(ioaddr + MAHR) >> 24); - ndev->dev_addr[1] = (ctrl_inl(ioaddr + MAHR) >> 16) & 0xFF; - ndev->dev_addr[2] = (ctrl_inl(ioaddr + MAHR) >> 8) & 0xFF; - ndev->dev_addr[3] = (ctrl_inl(ioaddr + MAHR) & 0xFF); - ndev->dev_addr[4] = (ctrl_inl(ioaddr + MALR) >> 8) & 0xFF; - ndev->dev_addr[5] = (ctrl_inl(ioaddr + MALR) & 0xFF); + ndev->dev_addr[0] = (readl(ioaddr + MAHR) >> 24); + ndev->dev_addr[1] = (readl(ioaddr + MAHR) >> 16) & 0xFF; + ndev->dev_addr[2] = (readl(ioaddr + MAHR) >> 8) & 0xFF; + ndev->dev_addr[3] = (readl(ioaddr + MAHR) & 0xFF); + ndev->dev_addr[4] = (readl(ioaddr + MALR) >> 8) & 0xFF; + ndev->dev_addr[5] = (readl(ioaddr + MALR) & 0xFF); } } @@ -379,19 +379,19 @@ struct bb_info { /* PHY bit set */ static void bb_set(u32 addr, u32 msk) { - ctrl_outl(ctrl_inl(addr) | msk, addr); + writel(readl(addr) | msk, addr); } /* PHY bit clear */ static void bb_clr(u32 addr, u32 msk) { - ctrl_outl((ctrl_inl(addr) & ~msk), addr); + writel((readl(addr) & ~msk), addr); } /* PHY bit read */ static int bb_read(u32 addr, u32 msk) { - return (ctrl_inl(addr) & msk) != 0; + return (readl(addr) & msk) != 0; } /* Data I/O pin control */ @@ -506,9 +506,9 @@ static void sh_eth_ring_format(struct net_device *ndev) rxdesc->buffer_length = ALIGN(mdp->rx_buf_sz, 16); /* Rx descriptor address set */ if (i == 0) { - ctrl_outl(mdp->rx_desc_dma, ioaddr + RDLAR); + writel(mdp->rx_desc_dma, ioaddr + RDLAR); #if defined(CONFIG_CPU_SUBTYPE_SH7763) - ctrl_outl(mdp->rx_desc_dma, ioaddr + RDFAR); + writel(mdp->rx_desc_dma, ioaddr + RDFAR); #endif } } @@ -528,9 +528,9 @@ static void sh_eth_ring_format(struct net_device *ndev) txdesc->buffer_length = 0; if (i == 0) { /* Tx descriptor address set */ - ctrl_outl(mdp->tx_desc_dma, ioaddr + TDLAR); + writel(mdp->tx_desc_dma, ioaddr + TDLAR); #if defined(CONFIG_CPU_SUBTYPE_SH7763) - ctrl_outl(mdp->tx_desc_dma, ioaddr + TDFAR); + writel(mdp->tx_desc_dma, ioaddr + TDFAR); #endif } } @@ -623,71 +623,71 @@ static int sh_eth_dev_init(struct net_device *ndev) /* Descriptor format */ sh_eth_ring_format(ndev); if (mdp->cd->rpadir) - ctrl_outl(mdp->cd->rpadir_value, ioaddr + RPADIR); + writel(mdp->cd->rpadir_value, ioaddr + RPADIR); /* all sh_eth int mask */ - ctrl_outl(0, ioaddr + EESIPR); + writel(0, ioaddr + EESIPR); #if defined(__LITTLE_ENDIAN__) if (mdp->cd->hw_swap) - ctrl_outl(EDMR_EL, ioaddr + EDMR); + writel(EDMR_EL, ioaddr + EDMR); else #endif - ctrl_outl(0, ioaddr + EDMR); + writel(0, ioaddr + EDMR); /* FIFO size set */ - ctrl_outl(mdp->cd->fdr_value, ioaddr + FDR); - ctrl_outl(0, ioaddr + TFTR); + writel(mdp->cd->fdr_value, ioaddr + FDR); + writel(0, ioaddr + TFTR); /* Frame recv control */ - ctrl_outl(mdp->cd->rmcr_value, ioaddr + RMCR); + writel(mdp->cd->rmcr_value, ioaddr + RMCR); rx_int_var = mdp->rx_int_var = DESC_I_RINT8 | DESC_I_RINT5; tx_int_var = mdp->tx_int_var = DESC_I_TINT2; - ctrl_outl(rx_int_var | tx_int_var, ioaddr + TRSCER); + writel(rx_int_var | tx_int_var, ioaddr + TRSCER); if (mdp->cd->bculr) - ctrl_outl(0x800, ioaddr + BCULR); /* Burst sycle set */ + writel(0x800, ioaddr + BCULR); /* Burst sycle set */ - ctrl_outl(mdp->cd->fcftr_value, ioaddr + FCFTR); + writel(mdp->cd->fcftr_value, ioaddr + FCFTR); if (!mdp->cd->no_trimd) - ctrl_outl(0, ioaddr + TRIMD); + writel(0, ioaddr + TRIMD); /* Recv frame limit set register */ - ctrl_outl(RFLR_VALUE, ioaddr + RFLR); + writel(RFLR_VALUE, ioaddr + RFLR); - ctrl_outl(ctrl_inl(ioaddr + EESR), ioaddr + EESR); - ctrl_outl(mdp->cd->eesipr_value, ioaddr + EESIPR); + writel(readl(ioaddr + EESR), ioaddr + EESR); + writel(mdp->cd->eesipr_value, ioaddr + EESIPR); /* PAUSE Prohibition */ - val = (ctrl_inl(ioaddr + ECMR) & ECMR_DM) | + val = (readl(ioaddr + ECMR) & ECMR_DM) | ECMR_ZPF | (mdp->duplex ? ECMR_DM : 0) | ECMR_TE | ECMR_RE; - ctrl_outl(val, ioaddr + ECMR); + writel(val, ioaddr + ECMR); if (mdp->cd->set_rate) mdp->cd->set_rate(ndev); /* E-MAC Status Register clear */ - ctrl_outl(mdp->cd->ecsr_value, ioaddr + ECSR); + writel(mdp->cd->ecsr_value, ioaddr + ECSR); /* E-MAC Interrupt Enable register */ - ctrl_outl(mdp->cd->ecsipr_value, ioaddr + ECSIPR); + writel(mdp->cd->ecsipr_value, ioaddr + ECSIPR); /* Set MAC address */ update_mac_address(ndev); /* mask reset */ if (mdp->cd->apr) - ctrl_outl(APR_AP, ioaddr + APR); + writel(APR_AP, ioaddr + APR); if (mdp->cd->mpr) - ctrl_outl(MPR_MP, ioaddr + MPR); + writel(MPR_MP, ioaddr + MPR); if (mdp->cd->tpauser) - ctrl_outl(TPAUSER_UNLIMITED, ioaddr + TPAUSER); + writel(TPAUSER_UNLIMITED, ioaddr + TPAUSER); /* Setting the Rx mode will start the Rx process. */ - ctrl_outl(EDRRR_R, ioaddr + EDRRR); + writel(EDRRR_R, ioaddr + EDRRR); netif_start_queue(ndev); @@ -811,8 +811,8 @@ static int sh_eth_rx(struct net_device *ndev) /* Restart Rx engine if stopped. */ /* If we don't need to check status, don't. -KDU */ - if (!(ctrl_inl(ndev->base_addr + EDRRR) & EDRRR_R)) - ctrl_outl(EDRRR_R, ndev->base_addr + EDRRR); + if (!(readl(ndev->base_addr + EDRRR) & EDRRR_R)) + writel(EDRRR_R, ndev->base_addr + EDRRR); return 0; } @@ -827,8 +827,8 @@ static void sh_eth_error(struct net_device *ndev, int intr_status) u32 mask; if (intr_status & EESR_ECI) { - felic_stat = ctrl_inl(ioaddr + ECSR); - ctrl_outl(felic_stat, ioaddr + ECSR); /* clear int */ + felic_stat = readl(ioaddr + ECSR); + writel(felic_stat, ioaddr + ECSR); /* clear int */ if (felic_stat & ECSR_ICD) mdp->stats.tx_carrier_errors++; if (felic_stat & ECSR_LCHNG) { @@ -839,25 +839,25 @@ static void sh_eth_error(struct net_device *ndev, int intr_status) else link_stat = PHY_ST_LINK; } else { - link_stat = (ctrl_inl(ioaddr + PSR)); + link_stat = (readl(ioaddr + PSR)); if (mdp->ether_link_active_low) link_stat = ~link_stat; } if (!(link_stat & PHY_ST_LINK)) { /* Link Down : disable tx and rx */ - ctrl_outl(ctrl_inl(ioaddr + ECMR) & + writel(readl(ioaddr + ECMR) & ~(ECMR_RE | ECMR_TE), ioaddr + ECMR); } else { /* Link Up */ - ctrl_outl(ctrl_inl(ioaddr + EESIPR) & + writel(readl(ioaddr + EESIPR) & ~DMAC_M_ECI, ioaddr + EESIPR); /*clear int */ - ctrl_outl(ctrl_inl(ioaddr + ECSR), + writel(readl(ioaddr + ECSR), ioaddr + ECSR); - ctrl_outl(ctrl_inl(ioaddr + EESIPR) | + writel(readl(ioaddr + EESIPR) | DMAC_M_ECI, ioaddr + EESIPR); /* enable tx and rx */ - ctrl_outl(ctrl_inl(ioaddr + ECMR) | + writel(readl(ioaddr + ECMR) | (ECMR_RE | ECMR_TE), ioaddr + ECMR); } } @@ -888,8 +888,8 @@ static void sh_eth_error(struct net_device *ndev, int intr_status) /* Receive Descriptor Empty int */ mdp->stats.rx_over_errors++; - if (ctrl_inl(ioaddr + EDRRR) ^ EDRRR_R) - ctrl_outl(EDRRR_R, ioaddr + EDRRR); + if (readl(ioaddr + EDRRR) ^ EDRRR_R) + writel(EDRRR_R, ioaddr + EDRRR); dev_err(&ndev->dev, "Receive Descriptor Empty\n"); } if (intr_status & EESR_RFE) { @@ -903,7 +903,7 @@ static void sh_eth_error(struct net_device *ndev, int intr_status) mask &= ~EESR_ADE; if (intr_status & mask) { /* Tx error */ - u32 edtrr = ctrl_inl(ndev->base_addr + EDTRR); + u32 edtrr = readl(ndev->base_addr + EDTRR); /* dmesg */ dev_err(&ndev->dev, "TX error. status=%8.8x cur_tx=%8.8x ", intr_status, mdp->cur_tx); @@ -915,7 +915,7 @@ static void sh_eth_error(struct net_device *ndev, int intr_status) /* SH7712 BUG */ if (edtrr ^ EDTRR_TRNS) { /* tx dma start */ - ctrl_outl(EDTRR_TRNS, ndev->base_addr + EDTRR); + writel(EDTRR_TRNS, ndev->base_addr + EDTRR); } /* wakeup */ netif_wake_queue(ndev); @@ -934,12 +934,12 @@ static irqreturn_t sh_eth_interrupt(int irq, void *netdev) spin_lock(&mdp->lock); /* Get interrpt stat */ - intr_status = ctrl_inl(ioaddr + EESR); + intr_status = readl(ioaddr + EESR); /* Clear interrupt */ if (intr_status & (EESR_FRC | EESR_RMAF | EESR_RRF | EESR_RTLF | EESR_RTSF | EESR_PRE | EESR_CERF | cd->tx_check | cd->eesr_err_check)) { - ctrl_outl(intr_status, ioaddr + EESR); + writel(intr_status, ioaddr + EESR); ret = IRQ_HANDLED; } else goto other_irq; @@ -1000,7 +1000,7 @@ static void sh_eth_adjust_link(struct net_device *ndev) mdp->cd->set_rate(ndev); } if (mdp->link == PHY_DOWN) { - ctrl_outl((ctrl_inl(ioaddr + ECMR) & ~ECMR_TXF) + writel((readl(ioaddr + ECMR) & ~ECMR_TXF) | ECMR_DM, ioaddr + ECMR); new_state = 1; mdp->link = phydev->link; @@ -1125,7 +1125,7 @@ static void sh_eth_tx_timeout(struct net_device *ndev) /* worning message out. */ printk(KERN_WARNING "%s: transmit timed out, status %8.8x," - " resetting...\n", ndev->name, (int)ctrl_inl(ioaddr + EESR)); + " resetting...\n", ndev->name, (int)readl(ioaddr + EESR)); /* tx_errors count up */ mdp->stats.tx_errors++; @@ -1196,8 +1196,8 @@ static int sh_eth_start_xmit(struct sk_buff *skb, struct net_device *ndev) mdp->cur_tx++; - if (!(ctrl_inl(ndev->base_addr + EDTRR) & EDTRR_TRNS)) - ctrl_outl(EDTRR_TRNS, ndev->base_addr + EDTRR); + if (!(readl(ndev->base_addr + EDTRR) & EDTRR_TRNS)) + writel(EDTRR_TRNS, ndev->base_addr + EDTRR); return NETDEV_TX_OK; } @@ -1212,11 +1212,11 @@ static int sh_eth_close(struct net_device *ndev) netif_stop_queue(ndev); /* Disable interrupts by clearing the interrupt mask. */ - ctrl_outl(0x0000, ioaddr + EESIPR); + writel(0x0000, ioaddr + EESIPR); /* Stop the chip's Tx and Rx processes. */ - ctrl_outl(0, ioaddr + EDTRR); - ctrl_outl(0, ioaddr + EDRRR); + writel(0, ioaddr + EDTRR); + writel(0, ioaddr + EDRRR); /* PHY Disconnect */ if (mdp->phydev) { @@ -1251,20 +1251,20 @@ static struct net_device_stats *sh_eth_get_stats(struct net_device *ndev) pm_runtime_get_sync(&mdp->pdev->dev); - mdp->stats.tx_dropped += ctrl_inl(ioaddr + TROCR); - ctrl_outl(0, ioaddr + TROCR); /* (write clear) */ - mdp->stats.collisions += ctrl_inl(ioaddr + CDCR); - ctrl_outl(0, ioaddr + CDCR); /* (write clear) */ - mdp->stats.tx_carrier_errors += ctrl_inl(ioaddr + LCCR); - ctrl_outl(0, ioaddr + LCCR); /* (write clear) */ + mdp->stats.tx_dropped += readl(ioaddr + TROCR); + writel(0, ioaddr + TROCR); /* (write clear) */ + mdp->stats.collisions += readl(ioaddr + CDCR); + writel(0, ioaddr + CDCR); /* (write clear) */ + mdp->stats.tx_carrier_errors += readl(ioaddr + LCCR); + writel(0, ioaddr + LCCR); /* (write clear) */ #if defined(CONFIG_CPU_SUBTYPE_SH7763) - mdp->stats.tx_carrier_errors += ctrl_inl(ioaddr + CERCR);/* CERCR */ - ctrl_outl(0, ioaddr + CERCR); /* (write clear) */ - mdp->stats.tx_carrier_errors += ctrl_inl(ioaddr + CEECR);/* CEECR */ - ctrl_outl(0, ioaddr + CEECR); /* (write clear) */ + mdp->stats.tx_carrier_errors += readl(ioaddr + CERCR);/* CERCR */ + writel(0, ioaddr + CERCR); /* (write clear) */ + mdp->stats.tx_carrier_errors += readl(ioaddr + CEECR);/* CEECR */ + writel(0, ioaddr + CEECR); /* (write clear) */ #else - mdp->stats.tx_carrier_errors += ctrl_inl(ioaddr + CNDCR); - ctrl_outl(0, ioaddr + CNDCR); /* (write clear) */ + mdp->stats.tx_carrier_errors += readl(ioaddr + CNDCR); + writel(0, ioaddr + CNDCR); /* (write clear) */ #endif pm_runtime_put_sync(&mdp->pdev->dev); @@ -1295,11 +1295,11 @@ static void sh_eth_set_multicast_list(struct net_device *ndev) if (ndev->flags & IFF_PROMISC) { /* Set promiscuous. */ - ctrl_outl((ctrl_inl(ioaddr + ECMR) & ~ECMR_MCT) | ECMR_PRM, + writel((readl(ioaddr + ECMR) & ~ECMR_MCT) | ECMR_PRM, ioaddr + ECMR); } else { /* Normal, unicast/broadcast-only mode. */ - ctrl_outl((ctrl_inl(ioaddr + ECMR) & ~ECMR_PRM) | ECMR_MCT, + writel((readl(ioaddr + ECMR) & ~ECMR_PRM) | ECMR_MCT, ioaddr + ECMR); } } @@ -1307,30 +1307,30 @@ static void sh_eth_set_multicast_list(struct net_device *ndev) /* SuperH's TSU register init function */ static void sh_eth_tsu_init(u32 ioaddr) { - ctrl_outl(0, ioaddr + TSU_FWEN0); /* Disable forward(0->1) */ - ctrl_outl(0, ioaddr + TSU_FWEN1); /* Disable forward(1->0) */ - ctrl_outl(0, ioaddr + TSU_FCM); /* forward fifo 3k-3k */ - ctrl_outl(0xc, ioaddr + TSU_BSYSL0); - ctrl_outl(0xc, ioaddr + TSU_BSYSL1); - ctrl_outl(0, ioaddr + TSU_PRISL0); - ctrl_outl(0, ioaddr + TSU_PRISL1); - ctrl_outl(0, ioaddr + TSU_FWSL0); - ctrl_outl(0, ioaddr + TSU_FWSL1); - ctrl_outl(TSU_FWSLC_POSTENU | TSU_FWSLC_POSTENL, ioaddr + TSU_FWSLC); + writel(0, ioaddr + TSU_FWEN0); /* Disable forward(0->1) */ + writel(0, ioaddr + TSU_FWEN1); /* Disable forward(1->0) */ + writel(0, ioaddr + TSU_FCM); /* forward fifo 3k-3k */ + writel(0xc, ioaddr + TSU_BSYSL0); + writel(0xc, ioaddr + TSU_BSYSL1); + writel(0, ioaddr + TSU_PRISL0); + writel(0, ioaddr + TSU_PRISL1); + writel(0, ioaddr + TSU_FWSL0); + writel(0, ioaddr + TSU_FWSL1); + writel(TSU_FWSLC_POSTENU | TSU_FWSLC_POSTENL, ioaddr + TSU_FWSLC); #if defined(CONFIG_CPU_SUBTYPE_SH7763) - ctrl_outl(0, ioaddr + TSU_QTAG0); /* Disable QTAG(0->1) */ - ctrl_outl(0, ioaddr + TSU_QTAG1); /* Disable QTAG(1->0) */ + writel(0, ioaddr + TSU_QTAG0); /* Disable QTAG(0->1) */ + writel(0, ioaddr + TSU_QTAG1); /* Disable QTAG(1->0) */ #else - ctrl_outl(0, ioaddr + TSU_QTAGM0); /* Disable QTAG(0->1) */ - ctrl_outl(0, ioaddr + TSU_QTAGM1); /* Disable QTAG(1->0) */ + writel(0, ioaddr + TSU_QTAGM0); /* Disable QTAG(0->1) */ + writel(0, ioaddr + TSU_QTAGM1); /* Disable QTAG(1->0) */ #endif - ctrl_outl(0, ioaddr + TSU_FWSR); /* all interrupt status clear */ - ctrl_outl(0, ioaddr + TSU_FWINMK); /* Disable all interrupt */ - ctrl_outl(0, ioaddr + TSU_TEN); /* Disable all CAM entry */ - ctrl_outl(0, ioaddr + TSU_POST1); /* Disable CAM entry [ 0- 7] */ - ctrl_outl(0, ioaddr + TSU_POST2); /* Disable CAM entry [ 8-15] */ - ctrl_outl(0, ioaddr + TSU_POST3); /* Disable CAM entry [16-23] */ - ctrl_outl(0, ioaddr + TSU_POST4); /* Disable CAM entry [24-31] */ + writel(0, ioaddr + TSU_FWSR); /* all interrupt status clear */ + writel(0, ioaddr + TSU_FWINMK); /* Disable all interrupt */ + writel(0, ioaddr + TSU_TEN); /* Disable all CAM entry */ + writel(0, ioaddr + TSU_POST1); /* Disable CAM entry [ 0- 7] */ + writel(0, ioaddr + TSU_POST2); /* Disable CAM entry [ 8-15] */ + writel(0, ioaddr + TSU_POST3); /* Disable CAM entry [16-23] */ + writel(0, ioaddr + TSU_POST4); /* Disable CAM entry [24-31] */ } #endif /* SH_ETH_HAS_TSU */ diff --git a/drivers/net/skge.c b/drivers/net/skge.c index bfec2e0f5275..220e0398f1d5 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c @@ -3858,7 +3858,6 @@ static struct net_device *skge_devinit(struct skge_hw *hw, int port, /* device is off until link detection */ netif_carrier_off(dev); - netif_stop_queue(dev); return dev; } diff --git a/drivers/net/smsc911x.h b/drivers/net/smsc911x.h index 52f38e12a879..50f712e99e96 100644 --- a/drivers/net/smsc911x.h +++ b/drivers/net/smsc911x.h @@ -22,7 +22,7 @@ #define __SMSC911X_H__ #define TX_FIFO_LOW_THRESHOLD ((u32)1600) -#define SMSC911X_EEPROM_SIZE ((u32)7) +#define SMSC911X_EEPROM_SIZE ((u32)128) #define USE_DEBUG 0 /* This is the maximum number of packets to be received every diff --git a/drivers/net/stmmac/stmmac.h b/drivers/net/stmmac/stmmac.h index 79bdc2e13224..5f06c4706abe 100644 --- a/drivers/net/stmmac/stmmac.h +++ b/drivers/net/stmmac/stmmac.h @@ -20,7 +20,7 @@ Author: Giuseppe Cavallaro <peppe.cavallaro@st.com> *******************************************************************************/ -#define DRV_MODULE_VERSION "Apr_2010" +#define DRV_MODULE_VERSION "Nov_2010" #include <linux/platform_device.h> #include <linux/stmmac.h> @@ -37,7 +37,6 @@ struct stmmac_priv { unsigned int cur_tx; unsigned int dirty_tx; unsigned int dma_tx_size; - int tx_coe; int tx_coalesce; struct dma_desc *dma_rx ; @@ -48,7 +47,6 @@ struct stmmac_priv { struct sk_buff_head rx_recycle; struct net_device *dev; - int is_gmac; dma_addr_t dma_rx_phy; unsigned int dma_rx_size; unsigned int dma_buf_sz; @@ -60,14 +58,11 @@ struct stmmac_priv { struct napi_struct napi; phy_interface_t phy_interface; - int pbl; - int bus_id; int phy_addr; int phy_mask; int (*phy_reset) (void *priv); - void (*fix_mac_speed) (void *priv, unsigned int speed); - void (*bus_setup)(void __iomem *ioaddr); - void *bsp_priv; + int rx_coe; + int no_csum_insertion; int phy_irq; struct phy_device *phydev; @@ -77,47 +72,20 @@ struct stmmac_priv { unsigned int flow_ctrl; unsigned int pause; struct mii_bus *mii; - int mii_clk_csr; u32 msg_enable; spinlock_t lock; int wolopts; int wolenabled; - int shutdown; #ifdef CONFIG_STMMAC_TIMER struct stmmac_timer *tm; #endif #ifdef STMMAC_VLAN_TAG_USED struct vlan_group *vlgrp; #endif - int enh_desc; - int rx_coe; - int bugged_jumbo; - int no_csum_insertion; + struct plat_stmmacenet_data *plat; }; -#ifdef CONFIG_STM_DRIVERS -#include <linux/stm/pad.h> -static inline int stmmac_claim_resource(struct platform_device *pdev) -{ - int ret = 0; - struct plat_stmmacenet_data *plat_dat = pdev->dev.platform_data; - - /* Pad routing setup */ - if (IS_ERR(devm_stm_pad_claim(&pdev->dev, plat_dat->pad_config, - dev_name(&pdev->dev)))) { - printk(KERN_ERR "%s: Failed to request pads!\n", __func__); - ret = -ENODEV; - } - return ret; -} -#else -static inline int stmmac_claim_resource(struct platform_device *pdev) -{ - return 0; -} -#endif - extern int stmmac_mdio_unregister(struct net_device *ndev); extern int stmmac_mdio_register(struct net_device *ndev); extern void stmmac_set_ethtool_ops(struct net_device *netdev); diff --git a/drivers/net/stmmac/stmmac_ethtool.c b/drivers/net/stmmac/stmmac_ethtool.c index 6d65482e789a..f2695fd180ca 100644 --- a/drivers/net/stmmac/stmmac_ethtool.c +++ b/drivers/net/stmmac/stmmac_ethtool.c @@ -94,7 +94,7 @@ static void stmmac_ethtool_getdrvinfo(struct net_device *dev, { struct stmmac_priv *priv = netdev_priv(dev); - if (!priv->is_gmac) + if (!priv->plat->has_gmac) strcpy(info->driver, MAC100_ETHTOOL_NAME); else strcpy(info->driver, GMAC_ETHTOOL_NAME); @@ -176,7 +176,7 @@ static void stmmac_ethtool_gregs(struct net_device *dev, memset(reg_space, 0x0, REG_SPACE_SIZE); - if (!priv->is_gmac) { + if (!priv->plat->has_gmac) { /* MAC registers */ for (i = 0; i < 12; i++) reg_space[i] = readl(priv->ioaddr + (i * 4)); diff --git a/drivers/net/stmmac/stmmac_main.c b/drivers/net/stmmac/stmmac_main.c index 06bc6034ce81..730a6fd79ee0 100644 --- a/drivers/net/stmmac/stmmac_main.c +++ b/drivers/net/stmmac/stmmac_main.c @@ -186,6 +186,18 @@ static inline u32 stmmac_tx_avail(struct stmmac_priv *priv) return priv->dirty_tx + priv->dma_tx_size - priv->cur_tx - 1; } +/* On some ST platforms, some HW system configuraton registers have to be + * set according to the link speed negotiated. + */ +static inline void stmmac_hw_fix_mac_speed(struct stmmac_priv *priv) +{ + struct phy_device *phydev = priv->phydev; + + if (likely(priv->plat->fix_mac_speed)) + priv->plat->fix_mac_speed(priv->plat->bsp_priv, + phydev->speed); +} + /** * stmmac_adjust_link * @dev: net device structure @@ -228,15 +240,13 @@ static void stmmac_adjust_link(struct net_device *dev) new_state = 1; switch (phydev->speed) { case 1000: - if (likely(priv->is_gmac)) + if (likely(priv->plat->has_gmac)) ctrl &= ~priv->hw->link.port; - if (likely(priv->fix_mac_speed)) - priv->fix_mac_speed(priv->bsp_priv, - phydev->speed); + stmmac_hw_fix_mac_speed(priv); break; case 100: case 10: - if (priv->is_gmac) { + if (priv->plat->has_gmac) { ctrl |= priv->hw->link.port; if (phydev->speed == SPEED_100) { ctrl |= priv->hw->link.speed; @@ -246,9 +256,7 @@ static void stmmac_adjust_link(struct net_device *dev) } else { ctrl &= ~priv->hw->link.port; } - if (likely(priv->fix_mac_speed)) - priv->fix_mac_speed(priv->bsp_priv, - phydev->speed); + stmmac_hw_fix_mac_speed(priv); break; default: if (netif_msg_link(priv)) @@ -305,7 +313,7 @@ static int stmmac_init_phy(struct net_device *dev) return 0; } - snprintf(bus_id, MII_BUS_ID_SIZE, "%x", priv->bus_id); + snprintf(bus_id, MII_BUS_ID_SIZE, "%x", priv->plat->bus_id); snprintf(phy_id, MII_BUS_ID_SIZE + 3, PHY_ID_FMT, bus_id, priv->phy_addr); pr_debug("stmmac_init_phy: trying to attach to %s\n", phy_id); @@ -552,7 +560,7 @@ static void free_dma_desc_resources(struct stmmac_priv *priv) */ static void stmmac_dma_operation_mode(struct stmmac_priv *priv) { - if (likely((priv->tx_coe) && (!priv->no_csum_insertion))) { + if (likely((priv->plat->tx_coe) && (!priv->no_csum_insertion))) { /* In case of GMAC, SF mode has to be enabled * to perform the TX COE. This depends on: * 1) TX COE if actually supported @@ -814,7 +822,7 @@ static int stmmac_open(struct net_device *dev) init_dma_desc_rings(dev); /* DMA initialization and SW reset */ - if (unlikely(priv->hw->dma->init(priv->ioaddr, priv->pbl, + if (unlikely(priv->hw->dma->init(priv->ioaddr, priv->plat->pbl, priv->dma_tx_phy, priv->dma_rx_phy) < 0)) { @@ -825,19 +833,17 @@ static int stmmac_open(struct net_device *dev) /* Copy the MAC addr into the HW */ priv->hw->mac->set_umac_addr(priv->ioaddr, dev->dev_addr, 0); /* If required, perform hw setup of the bus. */ - if (priv->bus_setup) - priv->bus_setup(priv->ioaddr); + if (priv->plat->bus_setup) + priv->plat->bus_setup(priv->ioaddr); /* Initialize the MAC Core */ priv->hw->mac->core_init(priv->ioaddr); priv->rx_coe = priv->hw->mac->rx_coe(priv->ioaddr); if (priv->rx_coe) pr_info("stmmac: Rx Checksum Offload Engine supported\n"); - if (priv->tx_coe) + if (priv->plat->tx_coe) pr_info("\tTX Checksum insertion supported\n"); - priv->shutdown = 0; - /* Initialise the MMC (if present) to disable all interrupts. */ writel(0xffffffff, priv->ioaddr + MMC_HIGH_INTR_MASK); writel(0xffffffff, priv->ioaddr + MMC_LOW_INTR_MASK); @@ -1042,7 +1048,8 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev) return stmmac_sw_tso(priv, skb); if (likely((skb->ip_summed == CHECKSUM_PARTIAL))) { - if (unlikely((!priv->tx_coe) || (priv->no_csum_insertion))) + if (unlikely((!priv->plat->tx_coe) || + (priv->no_csum_insertion))) skb_checksum_help(skb); else csum_insertion = 1; @@ -1146,7 +1153,7 @@ static inline void stmmac_rx_refill(struct stmmac_priv *priv) DMA_FROM_DEVICE); (p + entry)->des2 = priv->rx_skbuff_dma[entry]; - if (unlikely(priv->is_gmac)) { + if (unlikely(priv->plat->has_gmac)) { if (bfsize >= BUF_SIZE_8KiB) (p + entry)->des3 = (p + entry)->des2 + BUF_SIZE_8KiB; @@ -1356,7 +1363,7 @@ static int stmmac_change_mtu(struct net_device *dev, int new_mtu) return -EBUSY; } - if (priv->is_gmac) + if (priv->plat->has_gmac) max_mtu = JUMBO_LEN; else max_mtu = ETH_DATA_LEN; @@ -1370,7 +1377,7 @@ static int stmmac_change_mtu(struct net_device *dev, int new_mtu) * needs to have the Tx COE disabled for oversized frames * (due to limited buffer sizes). In this case we disable * the TX csum insertionin the TDES and not use SF. */ - if ((priv->bugged_jumbo) && (priv->dev->mtu > ETH_DATA_LEN)) + if ((priv->plat->bugged_jumbo) && (priv->dev->mtu > ETH_DATA_LEN)) priv->no_csum_insertion = 1; else priv->no_csum_insertion = 0; @@ -1390,7 +1397,7 @@ static irqreturn_t stmmac_interrupt(int irq, void *dev_id) return IRQ_NONE; } - if (priv->is_gmac) + if (priv->plat->has_gmac) /* To handle GMAC own interrupts */ priv->hw->mac->host_irq_status((void __iomem *) dev->base_addr); @@ -1536,7 +1543,7 @@ static int stmmac_mac_device_setup(struct net_device *dev) struct mac_device_info *device; - if (priv->is_gmac) + if (priv->plat->has_gmac) device = dwmac1000_setup(priv->ioaddr); else device = dwmac100_setup(priv->ioaddr); @@ -1544,7 +1551,7 @@ static int stmmac_mac_device_setup(struct net_device *dev) if (!device) return -ENOMEM; - if (priv->enh_desc) { + if (priv->plat->enh_desc) { device->desc = &enh_desc_ops; pr_info("\tEnhanced descriptor structure\n"); } else @@ -1598,7 +1605,7 @@ static int stmmac_associate_phy(struct device *dev, void *data) plat_dat->bus_id); /* Check that this phy is for the MAC being initialised */ - if (priv->bus_id != plat_dat->bus_id) + if (priv->plat->bus_id != plat_dat->bus_id) return 0; /* OK, this PHY is connected to the MAC. @@ -1634,7 +1641,7 @@ static int stmmac_dvr_probe(struct platform_device *pdev) struct resource *res; void __iomem *addr = NULL; struct net_device *ndev = NULL; - struct stmmac_priv *priv; + struct stmmac_priv *priv = NULL; struct plat_stmmacenet_data *plat_dat; pr_info("STMMAC driver:\n\tplatform registration... "); @@ -1683,13 +1690,9 @@ static int stmmac_dvr_probe(struct platform_device *pdev) priv->device = &(pdev->dev); priv->dev = ndev; plat_dat = pdev->dev.platform_data; - priv->bus_id = plat_dat->bus_id; - priv->pbl = plat_dat->pbl; /* TLI */ - priv->mii_clk_csr = plat_dat->clk_csr; - priv->tx_coe = plat_dat->tx_coe; - priv->bugged_jumbo = plat_dat->bugged_jumbo; - priv->is_gmac = plat_dat->has_gmac; /* GMAC is on board */ - priv->enh_desc = plat_dat->enh_desc; + + priv->plat = plat_dat; + priv->ioaddr = addr; /* PMT module is not integrated in all the MAC devices. */ @@ -1703,10 +1706,12 @@ static int stmmac_dvr_probe(struct platform_device *pdev) /* Set the I/O base addr */ ndev->base_addr = (unsigned long)addr; - /* Verify embedded resource for the platform */ - ret = stmmac_claim_resource(pdev); - if (ret < 0) - goto out; + /* Custom initialisation */ + if (priv->plat->init) { + ret = priv->plat->init(pdev); + if (unlikely(ret)) + goto out; + } /* MAC HW revice detection */ ret = stmmac_mac_device_setup(ndev); @@ -1727,16 +1732,12 @@ static int stmmac_dvr_probe(struct platform_device *pdev) goto out; } - priv->fix_mac_speed = plat_dat->fix_mac_speed; - priv->bus_setup = plat_dat->bus_setup; - priv->bsp_priv = plat_dat->bsp_priv; - pr_info("\t%s - (dev. name: %s - id: %d, IRQ #%d\n" "\tIO base addr: 0x%p)\n", ndev->name, pdev->name, pdev->id, ndev->irq, addr); /* MDIO bus Registration */ - pr_debug("\tMDIO bus (id: %d)...", priv->bus_id); + pr_debug("\tMDIO bus (id: %d)...", priv->plat->bus_id); ret = stmmac_mdio_register(ndev); if (ret < 0) goto out; @@ -1744,6 +1745,9 @@ static int stmmac_dvr_probe(struct platform_device *pdev) out: if (ret < 0) { + if (priv->plat->exit) + priv->plat->exit(pdev); + platform_set_drvdata(pdev, NULL); release_mem_region(res->start, resource_size(res)); if (addr != NULL) @@ -1777,6 +1781,9 @@ static int stmmac_dvr_remove(struct platform_device *pdev) stmmac_mdio_unregister(ndev); + if (priv->plat->exit) + priv->plat->exit(pdev); + platform_set_drvdata(pdev, NULL); unregister_netdev(ndev); @@ -1790,69 +1797,54 @@ static int stmmac_dvr_remove(struct platform_device *pdev) } #ifdef CONFIG_PM -static int stmmac_suspend(struct platform_device *pdev, pm_message_t state) +static int stmmac_suspend(struct device *dev) { - struct net_device *dev = platform_get_drvdata(pdev); - struct stmmac_priv *priv = netdev_priv(dev); + struct net_device *ndev = dev_get_drvdata(dev); + struct stmmac_priv *priv = netdev_priv(ndev); int dis_ic = 0; - if (!dev || !netif_running(dev)) + if (!ndev || !netif_running(ndev)) return 0; spin_lock(&priv->lock); - if (state.event == PM_EVENT_SUSPEND) { - netif_device_detach(dev); - netif_stop_queue(dev); - if (priv->phydev) - phy_stop(priv->phydev); + netif_device_detach(ndev); + netif_stop_queue(ndev); + if (priv->phydev) + phy_stop(priv->phydev); #ifdef CONFIG_STMMAC_TIMER - priv->tm->timer_stop(); - if (likely(priv->tm->enable)) - dis_ic = 1; + priv->tm->timer_stop(); + if (likely(priv->tm->enable)) + dis_ic = 1; #endif - napi_disable(&priv->napi); - - /* Stop TX/RX DMA */ - priv->hw->dma->stop_tx(priv->ioaddr); - priv->hw->dma->stop_rx(priv->ioaddr); - /* Clear the Rx/Tx descriptors */ - priv->hw->desc->init_rx_desc(priv->dma_rx, priv->dma_rx_size, - dis_ic); - priv->hw->desc->init_tx_desc(priv->dma_tx, priv->dma_tx_size); - - /* Enable Power down mode by programming the PMT regs */ - if (device_can_wakeup(priv->device)) - priv->hw->mac->pmt(priv->ioaddr, priv->wolopts); - else - stmmac_disable_mac(priv->ioaddr); - } else { - priv->shutdown = 1; - /* Although this can appear slightly redundant it actually - * makes fast the standby operation and guarantees the driver - * working if hibernation is on media. */ - stmmac_release(dev); - } + napi_disable(&priv->napi); + + /* Stop TX/RX DMA */ + priv->hw->dma->stop_tx(priv->ioaddr); + priv->hw->dma->stop_rx(priv->ioaddr); + /* Clear the Rx/Tx descriptors */ + priv->hw->desc->init_rx_desc(priv->dma_rx, priv->dma_rx_size, + dis_ic); + priv->hw->desc->init_tx_desc(priv->dma_tx, priv->dma_tx_size); + + /* Enable Power down mode by programming the PMT regs */ + if (device_may_wakeup(priv->device)) + priv->hw->mac->pmt(priv->ioaddr, priv->wolopts); + else + stmmac_disable_mac(priv->ioaddr); spin_unlock(&priv->lock); return 0; } -static int stmmac_resume(struct platform_device *pdev) +static int stmmac_resume(struct device *dev) { - struct net_device *dev = platform_get_drvdata(pdev); - struct stmmac_priv *priv = netdev_priv(dev); - - if (!netif_running(dev)) - return 0; + struct net_device *ndev = dev_get_drvdata(dev); + struct stmmac_priv *priv = netdev_priv(ndev); - if (priv->shutdown) { - /* Re-open the interface and re-init the MAC/DMA - and the rings (i.e. on hibernation stage) */ - stmmac_open(dev); + if (!netif_running(ndev)) return 0; - } spin_lock(&priv->lock); @@ -1861,10 +1853,10 @@ static int stmmac_resume(struct platform_device *pdev) * is received. Anyway, it's better to manually clear * this bit because it can generate problems while resuming * from another devices (e.g. serial console). */ - if (device_can_wakeup(priv->device)) + if (device_may_wakeup(priv->device)) priv->hw->mac->pmt(priv->ioaddr, 0); - netif_device_attach(dev); + netif_device_attach(ndev); /* Enable the MAC and DMA */ stmmac_enable_mac(priv->ioaddr); @@ -1872,31 +1864,59 @@ static int stmmac_resume(struct platform_device *pdev) priv->hw->dma->start_rx(priv->ioaddr); #ifdef CONFIG_STMMAC_TIMER - priv->tm->timer_start(tmrate); + if (likely(priv->tm->enable)) + priv->tm->timer_start(tmrate); #endif napi_enable(&priv->napi); if (priv->phydev) phy_start(priv->phydev); - netif_start_queue(dev); + netif_start_queue(ndev); spin_unlock(&priv->lock); return 0; } -#endif -static struct platform_driver stmmac_driver = { - .driver = { - .name = STMMAC_RESOURCE_NAME, - }, - .probe = stmmac_dvr_probe, - .remove = stmmac_dvr_remove, -#ifdef CONFIG_PM +static int stmmac_freeze(struct device *dev) +{ + struct net_device *ndev = dev_get_drvdata(dev); + + if (!ndev || !netif_running(ndev)) + return 0; + + return stmmac_release(ndev); +} + +static int stmmac_restore(struct device *dev) +{ + struct net_device *ndev = dev_get_drvdata(dev); + + if (!ndev || !netif_running(ndev)) + return 0; + + return stmmac_open(ndev); +} + +static const struct dev_pm_ops stmmac_pm_ops = { .suspend = stmmac_suspend, .resume = stmmac_resume, -#endif + .freeze = stmmac_freeze, + .thaw = stmmac_restore, + .restore = stmmac_restore, +}; +#else +static const struct dev_pm_ops stmmac_pm_ops; +#endif /* CONFIG_PM */ +static struct platform_driver stmmac_driver = { + .probe = stmmac_dvr_probe, + .remove = stmmac_dvr_remove, + .driver = { + .name = STMMAC_RESOURCE_NAME, + .owner = THIS_MODULE, + .pm = &stmmac_pm_ops, + }, }; /** diff --git a/drivers/net/stmmac/stmmac_mdio.c b/drivers/net/stmmac/stmmac_mdio.c index d7441616357d..234b4068a1fc 100644 --- a/drivers/net/stmmac/stmmac_mdio.c +++ b/drivers/net/stmmac/stmmac_mdio.c @@ -53,7 +53,7 @@ static int stmmac_mdio_read(struct mii_bus *bus, int phyaddr, int phyreg) int data; u16 regValue = (((phyaddr << 11) & (0x0000F800)) | ((phyreg << 6) & (0x000007C0))); - regValue |= MII_BUSY | ((priv->mii_clk_csr & 7) << 2); + regValue |= MII_BUSY | ((priv->plat->clk_csr & 7) << 2); do {} while (((readl(priv->ioaddr + mii_address)) & MII_BUSY) == 1); writel(regValue, priv->ioaddr + mii_address); @@ -85,7 +85,7 @@ static int stmmac_mdio_write(struct mii_bus *bus, int phyaddr, int phyreg, (((phyaddr << 11) & (0x0000F800)) | ((phyreg << 6) & (0x000007C0))) | MII_WRITE; - value |= MII_BUSY | ((priv->mii_clk_csr & 7) << 2); + value |= MII_BUSY | ((priv->plat->clk_csr & 7) << 2); /* Wait until any existing MII operation is complete */ @@ -114,7 +114,7 @@ static int stmmac_mdio_reset(struct mii_bus *bus) if (priv->phy_reset) { pr_debug("stmmac_mdio_reset: calling phy_reset\n"); - priv->phy_reset(priv->bsp_priv); + priv->phy_reset(priv->plat->bsp_priv); } /* This is a workaround for problems with the STE101P PHY. @@ -157,7 +157,7 @@ int stmmac_mdio_register(struct net_device *ndev) new_bus->read = &stmmac_mdio_read; new_bus->write = &stmmac_mdio_write; new_bus->reset = &stmmac_mdio_reset; - snprintf(new_bus->id, MII_BUS_ID_SIZE, "%x", priv->bus_id); + snprintf(new_bus->id, MII_BUS_ID_SIZE, "%x", priv->plat->bus_id); new_bus->priv = ndev; new_bus->irq = irqlist; new_bus->phy_mask = priv->phy_mask; diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 30ccbb6d097a..5faa87d86c66 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -32,6 +32,7 @@ #include <linux/etherdevice.h> #include <linux/skbuff.h> #include <linux/ethtool.h> +#include <linux/mdio.h> #include <linux/mii.h> #include <linux/phy.h> #include <linux/brcmphy.h> @@ -69,10 +70,10 @@ #define DRV_MODULE_NAME "tg3" #define TG3_MAJ_NUM 3 -#define TG3_MIN_NUM 115 +#define TG3_MIN_NUM 116 #define DRV_MODULE_VERSION \ __stringify(TG3_MAJ_NUM) "." __stringify(TG3_MIN_NUM) -#define DRV_MODULE_RELDATE "October 14, 2010" +#define DRV_MODULE_RELDATE "December 3, 2010" #define TG3_DEF_MAC_MODE 0 #define TG3_DEF_RX_MODE 0 @@ -1769,9 +1770,9 @@ static void tg3_phy_eee_adjust(struct tg3 *tp, u32 current_link_up) if (tp->link_config.autoneg == AUTONEG_ENABLE && current_link_up == 1 && - (tp->link_config.active_speed == SPEED_1000 || - (tp->link_config.active_speed == SPEED_100 && - tp->link_config.active_duplex == DUPLEX_FULL))) { + tp->link_config.active_duplex == DUPLEX_FULL && + (tp->link_config.active_speed == SPEED_100 || + tp->link_config.active_speed == SPEED_1000)) { u32 eeectl; if (tp->link_config.active_speed == SPEED_1000) @@ -1781,7 +1782,8 @@ static void tg3_phy_eee_adjust(struct tg3 *tp, u32 current_link_up) tw32(TG3_CPMU_EEE_CTRL, eeectl); - tg3_phy_cl45_read(tp, 0x7, TG3_CL45_D7_EEERES_STAT, &val); + tg3_phy_cl45_read(tp, MDIO_MMD_AN, + TG3_CL45_D7_EEERES_STAT, &val); if (val == TG3_CL45_D7_EEERES_STAT_LP_1000T || val == TG3_CL45_D7_EEERES_STAT_LP_100TX) @@ -2728,12 +2730,10 @@ static int tg3_set_power_state(struct tg3 *tp, pci_power_t state) (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE))) mac_mode |= MAC_MODE_KEEP_FRAME_IN_WOL; - if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE) { - mac_mode |= tp->mac_mode & - (MAC_MODE_APE_TX_EN | MAC_MODE_APE_RX_EN); - if (mac_mode & MAC_MODE_APE_TX_EN) - mac_mode |= MAC_MODE_TDE_ENABLE; - } + if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE) + mac_mode |= MAC_MODE_APE_TX_EN | + MAC_MODE_APE_RX_EN | + MAC_MODE_TDE_ENABLE; tw32_f(MAC_MODE, mac_mode); udelay(100); @@ -2969,7 +2969,7 @@ static void tg3_phy_copper_begin(struct tg3 *tp) } if (tp->phy_flags & TG3_PHYFLG_EEE_CAP) { - u32 val = 0; + u32 val; tw32(TG3_CPMU_EEE_MODE, tr32(TG3_CPMU_EEE_MODE) & ~TG3_CPMU_EEEMD_LPI_ENABLE); @@ -2986,19 +2986,18 @@ static void tg3_phy_copper_begin(struct tg3 *tp) tg3_phydsp_write(tp, MII_TG3_DSP_CH34TP2, val | MII_TG3_DSP_CH34TP2_HIBW01); + val = 0; if (tp->link_config.autoneg == AUTONEG_ENABLE) { /* Advertise 100-BaseTX EEE ability */ if (tp->link_config.advertising & - (ADVERTISED_100baseT_Half | - ADVERTISED_100baseT_Full)) - val |= TG3_CL45_D7_EEEADV_CAP_100TX; + ADVERTISED_100baseT_Full) + val |= MDIO_AN_EEE_ADV_100TX; /* Advertise 1000-BaseT EEE ability */ if (tp->link_config.advertising & - (ADVERTISED_1000baseT_Half | - ADVERTISED_1000baseT_Full)) - val |= TG3_CL45_D7_EEEADV_CAP_1000T; + ADVERTISED_1000baseT_Full) + val |= MDIO_AN_EEE_ADV_1000T; } - tg3_phy_cl45_write(tp, 0x7, TG3_CL45_D7_EEEADV_CAP, val); + tg3_phy_cl45_write(tp, MDIO_MMD_AN, MDIO_AN_EEE_ADV, val); /* Turn off SM_DSP clock. */ val = MII_TG3_AUXCTL_SHDWSEL_AUXCTL | @@ -5763,7 +5762,7 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, dma_unmap_addr_set(&tnapi->tx_buffers[entry], mapping, mapping); if ((tp->tg3_flags3 & TG3_FLG3_USE_JUMBO_BDFLAG) && - !mss && skb->len > ETH_DATA_LEN) + !mss && skb->len > VLAN_ETH_FRAME_LEN) base_flags |= TXD_FLAG_JMB_PKT; tg3_set_txd(tnapi, entry, mapping, len, base_flags, @@ -5997,7 +5996,7 @@ static netdev_tx_t tg3_start_xmit_dma_bug(struct sk_buff *skb, #endif if ((tp->tg3_flags3 & TG3_FLG3_USE_JUMBO_BDFLAG) && - !mss && skb->len > ETH_DATA_LEN) + !mss && skb->len > VLAN_ETH_FRAME_LEN) base_flags |= TXD_FLAG_JMB_PKT; len = skb_headlen(skb); @@ -6339,13 +6338,13 @@ static void tg3_rx_prodring_fini(struct tg3 *tp, kfree(tpr->rx_jmb_buffers); tpr->rx_jmb_buffers = NULL; if (tpr->rx_std) { - pci_free_consistent(tp->pdev, TG3_RX_STD_RING_BYTES(tp), - tpr->rx_std, tpr->rx_std_mapping); + dma_free_coherent(&tp->pdev->dev, TG3_RX_STD_RING_BYTES(tp), + tpr->rx_std, tpr->rx_std_mapping); tpr->rx_std = NULL; } if (tpr->rx_jmb) { - pci_free_consistent(tp->pdev, TG3_RX_JMB_RING_BYTES(tp), - tpr->rx_jmb, tpr->rx_jmb_mapping); + dma_free_coherent(&tp->pdev->dev, TG3_RX_JMB_RING_BYTES(tp), + tpr->rx_jmb, tpr->rx_jmb_mapping); tpr->rx_jmb = NULL; } } @@ -6358,8 +6357,10 @@ static int tg3_rx_prodring_init(struct tg3 *tp, if (!tpr->rx_std_buffers) return -ENOMEM; - tpr->rx_std = pci_alloc_consistent(tp->pdev, TG3_RX_STD_RING_BYTES(tp), - &tpr->rx_std_mapping); + tpr->rx_std = dma_alloc_coherent(&tp->pdev->dev, + TG3_RX_STD_RING_BYTES(tp), + &tpr->rx_std_mapping, + GFP_KERNEL); if (!tpr->rx_std) goto err_out; @@ -6370,9 +6371,10 @@ static int tg3_rx_prodring_init(struct tg3 *tp, if (!tpr->rx_jmb_buffers) goto err_out; - tpr->rx_jmb = pci_alloc_consistent(tp->pdev, - TG3_RX_JMB_RING_BYTES(tp), - &tpr->rx_jmb_mapping); + tpr->rx_jmb = dma_alloc_coherent(&tp->pdev->dev, + TG3_RX_JMB_RING_BYTES(tp), + &tpr->rx_jmb_mapping, + GFP_KERNEL); if (!tpr->rx_jmb) goto err_out; } @@ -6491,7 +6493,7 @@ static void tg3_free_consistent(struct tg3 *tp) struct tg3_napi *tnapi = &tp->napi[i]; if (tnapi->tx_ring) { - pci_free_consistent(tp->pdev, TG3_TX_RING_BYTES, + dma_free_coherent(&tp->pdev->dev, TG3_TX_RING_BYTES, tnapi->tx_ring, tnapi->tx_desc_mapping); tnapi->tx_ring = NULL; } @@ -6500,25 +6502,26 @@ static void tg3_free_consistent(struct tg3 *tp) tnapi->tx_buffers = NULL; if (tnapi->rx_rcb) { - pci_free_consistent(tp->pdev, TG3_RX_RCB_RING_BYTES(tp), - tnapi->rx_rcb, - tnapi->rx_rcb_mapping); + dma_free_coherent(&tp->pdev->dev, + TG3_RX_RCB_RING_BYTES(tp), + tnapi->rx_rcb, + tnapi->rx_rcb_mapping); tnapi->rx_rcb = NULL; } tg3_rx_prodring_fini(tp, &tnapi->prodring); if (tnapi->hw_status) { - pci_free_consistent(tp->pdev, TG3_HW_STATUS_SIZE, - tnapi->hw_status, - tnapi->status_mapping); + dma_free_coherent(&tp->pdev->dev, TG3_HW_STATUS_SIZE, + tnapi->hw_status, + tnapi->status_mapping); tnapi->hw_status = NULL; } } if (tp->hw_stats) { - pci_free_consistent(tp->pdev, sizeof(struct tg3_hw_stats), - tp->hw_stats, tp->stats_mapping); + dma_free_coherent(&tp->pdev->dev, sizeof(struct tg3_hw_stats), + tp->hw_stats, tp->stats_mapping); tp->hw_stats = NULL; } } @@ -6531,9 +6534,10 @@ static int tg3_alloc_consistent(struct tg3 *tp) { int i; - tp->hw_stats = pci_alloc_consistent(tp->pdev, - sizeof(struct tg3_hw_stats), - &tp->stats_mapping); + tp->hw_stats = dma_alloc_coherent(&tp->pdev->dev, + sizeof(struct tg3_hw_stats), + &tp->stats_mapping, + GFP_KERNEL); if (!tp->hw_stats) goto err_out; @@ -6543,9 +6547,10 @@ static int tg3_alloc_consistent(struct tg3 *tp) struct tg3_napi *tnapi = &tp->napi[i]; struct tg3_hw_status *sblk; - tnapi->hw_status = pci_alloc_consistent(tp->pdev, - TG3_HW_STATUS_SIZE, - &tnapi->status_mapping); + tnapi->hw_status = dma_alloc_coherent(&tp->pdev->dev, + TG3_HW_STATUS_SIZE, + &tnapi->status_mapping, + GFP_KERNEL); if (!tnapi->hw_status) goto err_out; @@ -6566,9 +6571,10 @@ static int tg3_alloc_consistent(struct tg3 *tp) if (!tnapi->tx_buffers) goto err_out; - tnapi->tx_ring = pci_alloc_consistent(tp->pdev, - TG3_TX_RING_BYTES, - &tnapi->tx_desc_mapping); + tnapi->tx_ring = dma_alloc_coherent(&tp->pdev->dev, + TG3_TX_RING_BYTES, + &tnapi->tx_desc_mapping, + GFP_KERNEL); if (!tnapi->tx_ring) goto err_out; } @@ -6601,9 +6607,10 @@ static int tg3_alloc_consistent(struct tg3 *tp) if (!i && (tp->tg3_flags3 & TG3_FLG3_ENABLE_RSS)) continue; - tnapi->rx_rcb = pci_alloc_consistent(tp->pdev, - TG3_RX_RCB_RING_BYTES(tp), - &tnapi->rx_rcb_mapping); + tnapi->rx_rcb = dma_alloc_coherent(&tp->pdev->dev, + TG3_RX_RCB_RING_BYTES(tp), + &tnapi->rx_rcb_mapping, + GFP_KERNEL); if (!tnapi->rx_rcb) goto err_out; @@ -6987,7 +6994,7 @@ static void tg3_restore_pci_state(struct tg3 *tp) if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5785) { if (tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) - pcie_set_readrq(tp->pdev, 4096); + pcie_set_readrq(tp->pdev, tp->pcie_readrq); else { pci_write_config_byte(tp->pdev, PCI_CACHE_LINE_SIZE, tp->pci_cacheline_sz); @@ -7181,7 +7188,7 @@ static int tg3_chip_reset(struct tg3 *tp) tp->pcie_cap + PCI_EXP_DEVCTL, val16); - pcie_set_readrq(tp->pdev, 4096); + pcie_set_readrq(tp->pdev, tp->pcie_readrq); /* Clear error status */ pci_write_config_word(tp->pdev, @@ -7222,19 +7229,21 @@ static int tg3_chip_reset(struct tg3 *tp) tw32(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl); } + if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE) + tp->mac_mode = MAC_MODE_APE_TX_EN | + MAC_MODE_APE_RX_EN | + MAC_MODE_TDE_ENABLE; + if (tp->phy_flags & TG3_PHYFLG_PHY_SERDES) { - tp->mac_mode = MAC_MODE_PORT_MODE_TBI; - tw32_f(MAC_MODE, tp->mac_mode); + tp->mac_mode |= MAC_MODE_PORT_MODE_TBI; + val = tp->mac_mode; } else if (tp->phy_flags & TG3_PHYFLG_MII_SERDES) { - tp->mac_mode = MAC_MODE_PORT_MODE_GMII; - tw32_f(MAC_MODE, tp->mac_mode); - } else if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE) { - tp->mac_mode &= (MAC_MODE_APE_TX_EN | MAC_MODE_APE_RX_EN); - if (tp->mac_mode & MAC_MODE_APE_TX_EN) - tp->mac_mode |= MAC_MODE_TDE_ENABLE; - tw32_f(MAC_MODE, tp->mac_mode); + tp->mac_mode |= MAC_MODE_PORT_MODE_GMII; + val = tp->mac_mode; } else - tw32_f(MAC_MODE, 0); + val = 0; + + tw32_f(MAC_MODE, val); udelay(40); tg3_ape_unlock(tp, TG3_APE_LOCK_GRC); @@ -7801,6 +7810,37 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) if (tp->tg3_flags & TG3_FLAG_INIT_COMPLETE) tg3_abort_hw(tp, 1); + /* Enable MAC control of LPI */ + if (tp->phy_flags & TG3_PHYFLG_EEE_CAP) { + tw32_f(TG3_CPMU_EEE_LNKIDL_CTRL, + TG3_CPMU_EEE_LNKIDL_PCIE_NL0 | + TG3_CPMU_EEE_LNKIDL_UART_IDL); + + tw32_f(TG3_CPMU_EEE_CTRL, + TG3_CPMU_EEE_CTRL_EXIT_20_1_US); + + val = TG3_CPMU_EEEMD_ERLY_L1_XIT_DET | + TG3_CPMU_EEEMD_LPI_IN_TX | + TG3_CPMU_EEEMD_LPI_IN_RX | + TG3_CPMU_EEEMD_EEE_ENABLE; + + if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5717) + val |= TG3_CPMU_EEEMD_SND_IDX_DET_EN; + + if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE) + val |= TG3_CPMU_EEEMD_APE_TX_DET_EN; + + tw32_f(TG3_CPMU_EEE_MODE, val); + + tw32_f(TG3_CPMU_EEE_DBTMR1, + TG3_CPMU_DBTMR1_PCIEXIT_2047US | + TG3_CPMU_DBTMR1_LNKIDLE_2047US); + + tw32_f(TG3_CPMU_EEE_DBTMR2, + TG3_CPMU_DBTMR1_APE_TX_2047US | + TG3_CPMU_DBTMR2_TXIDXEQ_2047US); + } + if (reset_phy) tg3_phy_reset(tp); @@ -7860,18 +7900,21 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) tw32(GRC_MODE, grc_mode); } - if (tp->pci_chip_rev_id == CHIPREV_ID_57765_A0) { - u32 grc_mode = tr32(GRC_MODE); + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) { + if (tp->pci_chip_rev_id == CHIPREV_ID_57765_A0) { + u32 grc_mode = tr32(GRC_MODE); - /* Access the lower 1K of PL PCIE block registers. */ - val = grc_mode & ~GRC_MODE_PCIE_PORT_MASK; - tw32(GRC_MODE, val | GRC_MODE_PCIE_PL_SEL); + /* Access the lower 1K of PL PCIE block registers. */ + val = grc_mode & ~GRC_MODE_PCIE_PORT_MASK; + tw32(GRC_MODE, val | GRC_MODE_PCIE_PL_SEL); - val = tr32(TG3_PCIE_TLDLPL_PORT + TG3_PCIE_PL_LO_PHYCTL5); - tw32(TG3_PCIE_TLDLPL_PORT + TG3_PCIE_PL_LO_PHYCTL5, - val | TG3_PCIE_PL_LO_PHYCTL5_DIS_L2CLKREQ); + val = tr32(TG3_PCIE_TLDLPL_PORT + + TG3_PCIE_PL_LO_PHYCTL5); + tw32(TG3_PCIE_TLDLPL_PORT + TG3_PCIE_PL_LO_PHYCTL5, + val | TG3_PCIE_PL_LO_PHYCTL5_DIS_L2CLKREQ); - tw32(GRC_MODE, grc_mode); + tw32(GRC_MODE, grc_mode); + } val = tr32(TG3_CPMU_LSPD_10MB_CLK); val &= ~CPMU_LSPD_10MB_MACCLK_MASK; @@ -7879,22 +7922,6 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) tw32(TG3_CPMU_LSPD_10MB_CLK, val); } - /* Enable MAC control of LPI */ - if (tp->phy_flags & TG3_PHYFLG_EEE_CAP) { - tw32_f(TG3_CPMU_EEE_LNKIDL_CTRL, - TG3_CPMU_EEE_LNKIDL_PCIE_NL0 | - TG3_CPMU_EEE_LNKIDL_UART_IDL); - - tw32_f(TG3_CPMU_EEE_CTRL, - TG3_CPMU_EEE_CTRL_EXIT_20_1_US); - - tw32_f(TG3_CPMU_EEE_MODE, - TG3_CPMU_EEEMD_ERLY_L1_XIT_DET | - TG3_CPMU_EEEMD_LPI_IN_TX | - TG3_CPMU_EEEMD_LPI_IN_RX | - TG3_CPMU_EEEMD_EEE_ENABLE); - } - /* This works around an issue with Athlon chipsets on * B3 tigon3 silicon. This bit has no effect on any * other revision. But do not set this on PCI Express @@ -8162,8 +8189,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) RDMAC_MODE_FIFOURUN_ENAB | RDMAC_MODE_FIFOOREAD_ENAB | RDMAC_MODE_LNGREAD_ENAB); - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719) + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717) rdmac_mode |= RDMAC_MODE_MULT_DMA_RD_DIS; if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 || @@ -8203,6 +8229,10 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780 || (tp->tg3_flags3 & TG3_FLG3_5717_PLUS)) { val = tr32(TG3_RDMA_RSRVCTRL_REG); + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719) { + val &= ~TG3_RDMA_RSRVCTRL_TXMRGN_MASK; + val |= TG3_RDMA_RSRVCTRL_TXMRGN_320B; + } tw32(TG3_RDMA_RSRVCTRL_REG, val | TG3_RDMA_RSRVCTRL_FIFO_OFLW_FIX); } @@ -8280,7 +8310,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) } if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE) - tp->mac_mode &= MAC_MODE_APE_TX_EN | MAC_MODE_APE_RX_EN; + tp->mac_mode = MAC_MODE_APE_TX_EN | MAC_MODE_APE_RX_EN; else tp->mac_mode = 0; tp->mac_mode |= MAC_MODE_TXSTAT_ENABLE | MAC_MODE_RXSTAT_ENABLE | @@ -9031,8 +9061,14 @@ static bool tg3_enable_msix(struct tg3 *tp) pci_disable_msix(tp->pdev); return false; } - if (tp->irq_cnt > 1) + + if (tp->irq_cnt > 1) { tp->tg3_flags3 |= TG3_FLG3_ENABLE_RSS; + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719) { + tp->tg3_flags3 |= TG3_FLG3_ENABLE_TSS; + netif_set_real_num_tx_queues(tp->dev, tp->irq_cnt - 1); + } + } return true; } @@ -12411,8 +12447,9 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp) if (cfg2 & (1 << 18)) tp->phy_flags |= TG3_PHYFLG_SERDES_PREEMPHASIS; - if (((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 && - GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5784_AX)) && + if (((tp->tg3_flags3 & TG3_FLG3_5717_PLUS) || + ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 && + GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5784_AX))) && (cfg2 & NIC_SRAM_DATA_CFG_2_APD_EN)) tp->phy_flags |= TG3_PHYFLG_ENABLE_APD; @@ -12548,9 +12585,11 @@ static int __devinit tg3_phy_probe(struct tg3 *tp) } } - if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_5718 || - (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765 && - tp->pci_chip_rev_id != CHIPREV_ID_57765_A0)) + if (!(tp->phy_flags & TG3_PHYFLG_ANY_SERDES) && + ((tp->pdev->device == TG3PCI_DEVICE_TIGON3_5718 && + tp->pci_chip_rev_id != CHIPREV_ID_5717_A0) || + (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765 && + tp->pci_chip_rev_id != CHIPREV_ID_57765_A0))) tp->phy_flags |= TG3_PHYFLG_EEE_CAP; if (!(tp->phy_flags & TG3_PHYFLG_ANY_SERDES) && @@ -13359,7 +13398,45 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) tp->tg3_flags2 |= TG3_FLG2_PCI_EXPRESS; - pcie_set_readrq(tp->pdev, 4096); + tp->pcie_readrq = 4096; + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719) { + u16 word; + + pci_read_config_word(tp->pdev, + tp->pcie_cap + PCI_EXP_LNKSTA, + &word); + switch (word & PCI_EXP_LNKSTA_CLS) { + case PCI_EXP_LNKSTA_CLS_2_5GB: + word &= PCI_EXP_LNKSTA_NLW; + word >>= PCI_EXP_LNKSTA_NLW_SHIFT; + switch (word) { + case 2: + tp->pcie_readrq = 2048; + break; + case 4: + tp->pcie_readrq = 1024; + break; + } + break; + + case PCI_EXP_LNKSTA_CLS_5_0GB: + word &= PCI_EXP_LNKSTA_NLW; + word >>= PCI_EXP_LNKSTA_NLW_SHIFT; + switch (word) { + case 1: + tp->pcie_readrq = 2048; + break; + case 2: + tp->pcie_readrq = 1024; + break; + case 4: + tp->pcie_readrq = 512; + break; + } + } + } + + pcie_set_readrq(tp->pdev, tp->pcie_readrq); pci_read_config_word(tp->pdev, tp->pcie_cap + PCI_EXP_LNKCTL, @@ -13722,8 +13799,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) /* Preserve the APE MAC_MODE bits */ if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE) - tp->mac_mode = tr32(MAC_MODE) | - MAC_MODE_APE_TX_EN | MAC_MODE_APE_RX_EN; + tp->mac_mode = MAC_MODE_APE_TX_EN | MAC_MODE_APE_RX_EN; else tp->mac_mode = TG3_DEF_MAC_MODE; @@ -14159,7 +14235,8 @@ static int __devinit tg3_test_dma(struct tg3 *tp) u32 *buf, saved_dma_rwctrl; int ret = 0; - buf = pci_alloc_consistent(tp->pdev, TEST_BUFFER_SIZE, &buf_dma); + buf = dma_alloc_coherent(&tp->pdev->dev, TEST_BUFFER_SIZE, + &buf_dma, GFP_KERNEL); if (!buf) { ret = -ENOMEM; goto out_nofree; @@ -14343,7 +14420,7 @@ static int __devinit tg3_test_dma(struct tg3 *tp) } out: - pci_free_consistent(tp->pdev, TEST_BUFFER_SIZE, buf, buf_dma); + dma_free_coherent(&tp->pdev->dev, TEST_BUFFER_SIZE, buf, buf_dma); out_nofree: return ret; } diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index 4a1974804b9f..d62c8d937c82 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -1094,13 +1094,19 @@ /* 0x3664 --> 0x36b0 unused */ #define TG3_CPMU_EEE_MODE 0x000036b0 -#define TG3_CPMU_EEEMD_ERLY_L1_XIT_DET 0x00000008 -#define TG3_CPMU_EEEMD_LPI_ENABLE 0x00000080 -#define TG3_CPMU_EEEMD_LPI_IN_TX 0x00000100 -#define TG3_CPMU_EEEMD_LPI_IN_RX 0x00000200 -#define TG3_CPMU_EEEMD_EEE_ENABLE 0x00100000 -/* 0x36b4 --> 0x36b8 unused */ - +#define TG3_CPMU_EEEMD_APE_TX_DET_EN 0x00000004 +#define TG3_CPMU_EEEMD_ERLY_L1_XIT_DET 0x00000008 +#define TG3_CPMU_EEEMD_SND_IDX_DET_EN 0x00000040 +#define TG3_CPMU_EEEMD_LPI_ENABLE 0x00000080 +#define TG3_CPMU_EEEMD_LPI_IN_TX 0x00000100 +#define TG3_CPMU_EEEMD_LPI_IN_RX 0x00000200 +#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_EEE_DBTMR2 0x000036b8 +#define TG3_CPMU_DBTMR1_APE_TX_2047US 0x07ff0000 +#define TG3_CPMU_DBTMR2_TXIDXEQ_2047US 0x000070ff #define TG3_CPMU_EEE_LNKIDL_CTRL 0x000036bc #define TG3_CPMU_EEE_LNKIDL_PCIE_NL0 0x01000000 #define TG3_CPMU_EEE_LNKIDL_UART_IDL 0x00000004 @@ -1327,6 +1333,8 @@ #define TG3_RDMA_RSRVCTRL_REG 0x00004900 #define TG3_RDMA_RSRVCTRL_FIFO_OFLW_FIX 0x00000004 +#define TG3_RDMA_RSRVCTRL_TXMRGN_320B 0x28000000 +#define TG3_RDMA_RSRVCTRL_TXMRGN_MASK 0xffe00000 /* 0x4904 --> 0x4910 unused */ #define TG3_LSO_RD_DMA_CRPTEN_CTRL 0x00004910 @@ -2170,9 +2178,6 @@ #define MII_TG3_TEST1_CRC_EN 0x8000 /* Clause 45 expansion registers */ -#define TG3_CL45_D7_EEEADV_CAP 0x003c -#define TG3_CL45_D7_EEEADV_CAP_100TX 0x0002 -#define TG3_CL45_D7_EEEADV_CAP_1000T 0x0004 #define TG3_CL45_D7_EEERES_STAT 0x803e #define TG3_CL45_D7_EEERES_STAT_LP_100TX 0x0002 #define TG3_CL45_D7_EEERES_STAT_LP_1000T 0x0004 @@ -2562,10 +2567,6 @@ struct ring_info { DEFINE_DMA_UNMAP_ADDR(mapping); }; -struct tg3_config_info { - u32 flags; -}; - struct tg3_link_config { /* Describes what we're trying to get. */ u32 advertising; @@ -2713,17 +2714,17 @@ struct tg3_napi { u32 last_irq_tag; u32 int_mbox; u32 coal_now; - u32 tx_prod; - u32 tx_cons; - u32 tx_pending; - u32 prodmbox; - u32 consmbox; + u32 consmbox ____cacheline_aligned; u32 rx_rcb_ptr; u16 *rx_rcb_prod_idx; struct tg3_rx_prodring_set prodring; - struct tg3_rx_buffer_desc *rx_rcb; + + u32 tx_prod ____cacheline_aligned; + u32 tx_cons; + u32 tx_pending; + u32 prodmbox; struct tg3_tx_buffer_desc *tx_ring; struct ring_info *tx_buffers; @@ -2946,6 +2947,7 @@ struct tg3 { int pcix_cap; int pcie_cap; }; + int pcie_readrq; struct mii_bus *mdio_bus; int mdio_irq[PHY_MAX_ADDR]; diff --git a/drivers/net/tulip/de2104x.c b/drivers/net/tulip/de2104x.c index 28e1ffb13db9..c78a50586c1d 100644 --- a/drivers/net/tulip/de2104x.c +++ b/drivers/net/tulip/de2104x.c @@ -2021,7 +2021,6 @@ static int __devinit de_init_one (struct pci_dev *pdev, de->media_timer.data = (unsigned long) de; netif_carrier_off(dev); - netif_stop_queue(dev); /* wake up device, assign resources */ rc = pci_enable_device(pdev); diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c index a4c3f5708246..acbdab3d66ca 100644 --- a/drivers/net/ucc_geth.c +++ b/drivers/net/ucc_geth.c @@ -2050,12 +2050,16 @@ static void ucc_geth_stop(struct ucc_geth_private *ugeth) ugeth_vdbg("%s: IN", __func__); + /* + * Tell the kernel the link is down. + * Must be done before disabling the controller + * or deadlock may happen. + */ + phy_stop(phydev); + /* Disable the controller */ ugeth_disable(ugeth, COMM_DIR_RX_AND_TX); - /* Tell the kernel the link is down */ - phy_stop(phydev); - /* Mask all interrupts */ out_be32(ugeth->uccf->p_uccm, 0x00000000); @@ -2065,9 +2069,6 @@ static void ucc_geth_stop(struct ucc_geth_private *ugeth) /* Disable Rx and Tx */ clrbits32(&ug_regs->maccfg1, MACCFG1_ENABLE_RX | MACCFG1_ENABLE_TX); - phy_disconnect(ugeth->phydev); - ugeth->phydev = NULL; - ucc_geth_memclean(ugeth); } @@ -3550,7 +3551,10 @@ static int ucc_geth_close(struct net_device *dev) napi_disable(&ugeth->napi); + cancel_work_sync(&ugeth->timeout_work); ucc_geth_stop(ugeth); + phy_disconnect(ugeth->phydev); + ugeth->phydev = NULL; free_irq(ugeth->ug_info->uf_info.irq, ugeth->ndev); @@ -3579,8 +3583,12 @@ static void ucc_geth_timeout_work(struct work_struct *work) * Must reset MAC *and* PHY. This is done by reopening * the device. */ - ucc_geth_close(dev); - ucc_geth_open(dev); + netif_tx_stop_all_queues(dev); + ucc_geth_stop(ugeth); + ucc_geth_init_mac(ugeth); + /* Must start PHY here */ + phy_start(ugeth->phydev); + netif_tx_start_all_queues(dev); } netif_tx_schedule_all(dev); @@ -3594,7 +3602,6 @@ static void ucc_geth_timeout(struct net_device *dev) { struct ucc_geth_private *ugeth = netdev_priv(dev); - netif_carrier_off(dev); schedule_work(&ugeth->timeout_work); } diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c index b154a94de03e..be8cc2a8e213 100644 --- a/drivers/net/usb/hso.c +++ b/drivers/net/usb/hso.c @@ -1745,7 +1745,6 @@ static int hso_serial_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg) { struct hso_serial *serial = get_serial_by_tty(tty); - void __user *uarg = (void __user *)arg; int ret = 0; D4("IOCTL cmd: %d, arg: %ld", cmd, arg); diff --git a/drivers/net/usb/ipheth.c b/drivers/net/usb/ipheth.c index b2bcf99e6f08..7d42f9a2c068 100644 --- a/drivers/net/usb/ipheth.c +++ b/drivers/net/usb/ipheth.c @@ -363,7 +363,7 @@ static int ipheth_tx(struct sk_buff *skb, struct net_device *net) /* Paranoid */ if (skb->len > IPHETH_BUF_SIZE) { - WARN(1, "%s: skb too large: %d bytes", __func__, skb->len); + WARN(1, "%s: skb too large: %d bytes\n", __func__, skb->len); dev->net->stats.tx_dropped++; dev_kfree_skb_irq(skb); return NETDEV_TX_OK; diff --git a/drivers/net/usb/pegasus.c b/drivers/net/usb/pegasus.c index 6710f09346d6..ef3667690b12 100644 --- a/drivers/net/usb/pegasus.c +++ b/drivers/net/usb/pegasus.c @@ -359,7 +359,7 @@ fail: static int mdio_read(struct net_device *dev, int phy_id, int loc) { - pegasus_t *pegasus = (pegasus_t *) netdev_priv(dev); + pegasus_t *pegasus = netdev_priv(dev); u16 res; read_mii_word(pegasus, phy_id, loc, &res); @@ -397,7 +397,7 @@ fail: static void mdio_write(struct net_device *dev, int phy_id, int loc, int val) { - pegasus_t *pegasus = (pegasus_t *) netdev_priv(dev); + pegasus_t *pegasus = netdev_priv(dev); write_mii_word(pegasus, phy_id, loc, val); } diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index ca7fc9df1ccf..c04d49e31f81 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c @@ -45,6 +45,7 @@ #include <linux/usb/usbnet.h> #include <linux/slab.h> #include <linux/kernel.h> +#include <linux/pm_runtime.h> #define DRIVER_VERSION "22-Aug-2005" @@ -1273,6 +1274,16 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod) struct usb_device *xdev; int status; const char *name; + struct usb_driver *driver = to_usb_driver(udev->dev.driver); + + /* usbnet already took usb runtime pm, so have to enable the feature + * for usb interface, otherwise usb_autopm_get_interface may return + * failure if USB_SUSPEND(RUNTIME_PM) is enabled. + */ + if (!driver->supports_autosuspend) { + driver->supports_autosuspend = 1; + pm_runtime_enable(&udev->dev); + } name = udev->dev.driver->name; info = (struct driver_info *) prod->driver_info; diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index bb6b67f6b0cc..b6d402806ae6 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -986,9 +986,15 @@ static int virtnet_probe(struct virtio_device *vdev) goto unregister; } - vi->status = VIRTIO_NET_S_LINK_UP; - virtnet_update_status(vi); - netif_carrier_on(dev); + /* Assume link up if device can't report link status, + otherwise get link status from config. */ + if (virtio_has_feature(vi->vdev, VIRTIO_NET_F_STATUS)) { + netif_carrier_off(dev); + virtnet_update_status(vi); + } else { + vi->status = VIRTIO_NET_S_LINK_UP; + netif_carrier_on(dev); + } pr_debug("virtnet: registered device %s\n", dev->name); return 0; diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c index 21314e06e6d7..65860a998321 100644 --- a/drivers/net/vmxnet3/vmxnet3_drv.c +++ b/drivers/net/vmxnet3/vmxnet3_drv.c @@ -44,6 +44,9 @@ MODULE_DEVICE_TABLE(pci, vmxnet3_pciid_table); static atomic_t devices_found; +#define VMXNET3_MAX_DEVICES 10 +static int enable_mq = 1; +static int irq_share_mode; /* * Enable/Disable the given intr @@ -99,7 +102,7 @@ vmxnet3_ack_events(struct vmxnet3_adapter *adapter, u32 events) static bool vmxnet3_tq_stopped(struct vmxnet3_tx_queue *tq, struct vmxnet3_adapter *adapter) { - return netif_queue_stopped(adapter->netdev); + return tq->stopped; } @@ -107,7 +110,7 @@ static void vmxnet3_tq_start(struct vmxnet3_tx_queue *tq, struct vmxnet3_adapter *adapter) { tq->stopped = false; - netif_start_queue(adapter->netdev); + netif_start_subqueue(adapter->netdev, tq - adapter->tx_queue); } @@ -115,7 +118,7 @@ static void vmxnet3_tq_wake(struct vmxnet3_tx_queue *tq, struct vmxnet3_adapter *adapter) { tq->stopped = false; - netif_wake_queue(adapter->netdev); + netif_wake_subqueue(adapter->netdev, (tq - adapter->tx_queue)); } @@ -124,7 +127,7 @@ vmxnet3_tq_stop(struct vmxnet3_tx_queue *tq, struct vmxnet3_adapter *adapter) { tq->stopped = true; tq->num_stop++; - netif_stop_queue(adapter->netdev); + netif_stop_subqueue(adapter->netdev, (tq - adapter->tx_queue)); } @@ -135,6 +138,7 @@ static void vmxnet3_check_link(struct vmxnet3_adapter *adapter, bool affectTxQueue) { u32 ret; + int i; VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD, VMXNET3_CMD_GET_LINK); ret = VMXNET3_READ_BAR1_REG(adapter, VMXNET3_REG_CMD); @@ -145,22 +149,28 @@ vmxnet3_check_link(struct vmxnet3_adapter *adapter, bool affectTxQueue) if (!netif_carrier_ok(adapter->netdev)) netif_carrier_on(adapter->netdev); - if (affectTxQueue) - vmxnet3_tq_start(&adapter->tx_queue, adapter); + if (affectTxQueue) { + for (i = 0; i < adapter->num_tx_queues; i++) + vmxnet3_tq_start(&adapter->tx_queue[i], + adapter); + } } else { printk(KERN_INFO "%s: NIC Link is Down\n", adapter->netdev->name); if (netif_carrier_ok(adapter->netdev)) netif_carrier_off(adapter->netdev); - if (affectTxQueue) - vmxnet3_tq_stop(&adapter->tx_queue, adapter); + if (affectTxQueue) { + for (i = 0; i < adapter->num_tx_queues; i++) + vmxnet3_tq_stop(&adapter->tx_queue[i], adapter); + } } } static void vmxnet3_process_events(struct vmxnet3_adapter *adapter) { + int i; u32 events = le32_to_cpu(adapter->shared->ecr); if (!events) return; @@ -176,16 +186,18 @@ vmxnet3_process_events(struct vmxnet3_adapter *adapter) VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD, VMXNET3_CMD_GET_QUEUE_STATUS); - if (adapter->tqd_start->status.stopped) { - printk(KERN_ERR "%s: tq error 0x%x\n", - adapter->netdev->name, - le32_to_cpu(adapter->tqd_start->status.error)); - } - if (adapter->rqd_start->status.stopped) { - printk(KERN_ERR "%s: rq error 0x%x\n", - adapter->netdev->name, - adapter->rqd_start->status.error); - } + for (i = 0; i < adapter->num_tx_queues; i++) + if (adapter->tqd_start[i].status.stopped) + dev_err(&adapter->netdev->dev, + "%s: tq[%d] error 0x%x\n", + adapter->netdev->name, i, le32_to_cpu( + adapter->tqd_start[i].status.error)); + for (i = 0; i < adapter->num_rx_queues; i++) + if (adapter->rqd_start[i].status.stopped) + dev_err(&adapter->netdev->dev, + "%s: rq[%d] error 0x%x\n", + adapter->netdev->name, i, + adapter->rqd_start[i].status.error); schedule_work(&adapter->work); } @@ -410,7 +422,7 @@ vmxnet3_tq_cleanup(struct vmxnet3_tx_queue *tq, } -void +static void vmxnet3_tq_destroy(struct vmxnet3_tx_queue *tq, struct vmxnet3_adapter *adapter) { @@ -437,6 +449,17 @@ vmxnet3_tq_destroy(struct vmxnet3_tx_queue *tq, } +/* Destroy all tx queues */ +void +vmxnet3_tq_destroy_all(struct vmxnet3_adapter *adapter) +{ + int i; + + for (i = 0; i < adapter->num_tx_queues; i++) + vmxnet3_tq_destroy(&adapter->tx_queue[i], adapter); +} + + static void vmxnet3_tq_init(struct vmxnet3_tx_queue *tq, struct vmxnet3_adapter *adapter) @@ -518,6 +541,14 @@ err: return -ENOMEM; } +static void +vmxnet3_tq_cleanup_all(struct vmxnet3_adapter *adapter) +{ + int i; + + for (i = 0; i < adapter->num_tx_queues; i++) + vmxnet3_tq_cleanup(&adapter->tx_queue[i], adapter); +} /* * starting from ring->next2fill, allocate rx buffers for the given ring @@ -732,6 +763,17 @@ vmxnet3_map_pkt(struct sk_buff *skb, struct vmxnet3_tx_ctx *ctx, } +/* Init all tx queues */ +static void +vmxnet3_tq_init_all(struct vmxnet3_adapter *adapter) +{ + int i; + + for (i = 0; i < adapter->num_tx_queues; i++) + vmxnet3_tq_init(&adapter->tx_queue[i], adapter); +} + + /* * parse and copy relevant protocol headers: * For a tso pkt, relevant headers are L2/3/4 including options @@ -903,6 +945,21 @@ vmxnet3_tq_xmit(struct sk_buff *skb, struct vmxnet3_tx_queue *tq, } } + spin_lock_irqsave(&tq->tx_lock, flags); + + if (count > vmxnet3_cmd_ring_desc_avail(&tq->tx_ring)) { + tq->stats.tx_ring_full++; + dev_dbg(&adapter->netdev->dev, + "tx queue stopped on %s, next2comp %u" + " next2fill %u\n", adapter->netdev->name, + tq->tx_ring.next2comp, tq->tx_ring.next2fill); + + vmxnet3_tq_stop(tq, adapter); + spin_unlock_irqrestore(&tq->tx_lock, flags); + return NETDEV_TX_BUSY; + } + + ret = vmxnet3_parse_and_copy_hdr(skb, tq, &ctx, adapter); if (ret >= 0) { BUG_ON(ret <= 0 && ctx.copy_size != 0); @@ -926,20 +983,6 @@ vmxnet3_tq_xmit(struct sk_buff *skb, struct vmxnet3_tx_queue *tq, goto drop_pkt; } - spin_lock_irqsave(&tq->tx_lock, flags); - - if (count > vmxnet3_cmd_ring_desc_avail(&tq->tx_ring)) { - tq->stats.tx_ring_full++; - dev_dbg(&adapter->netdev->dev, - "tx queue stopped on %s, next2comp %u" - " next2fill %u\n", adapter->netdev->name, - tq->tx_ring.next2comp, tq->tx_ring.next2fill); - - vmxnet3_tq_stop(tq, adapter); - spin_unlock_irqrestore(&tq->tx_lock, flags); - return NETDEV_TX_BUSY; - } - /* fill tx descs related to addr & len */ vmxnet3_map_pkt(skb, &ctx, tq, adapter->pdev, adapter); @@ -1000,7 +1043,8 @@ vmxnet3_tq_xmit(struct sk_buff *skb, struct vmxnet3_tx_queue *tq, if (le32_to_cpu(tq->shared->txNumDeferred) >= le32_to_cpu(tq->shared->txThreshold)) { tq->shared->txNumDeferred = 0; - VMXNET3_WRITE_BAR0_REG(adapter, VMXNET3_REG_TXPROD, + VMXNET3_WRITE_BAR0_REG(adapter, + VMXNET3_REG_TXPROD + tq->qid * 8, tq->tx_ring.next2fill); } @@ -1020,7 +1064,10 @@ vmxnet3_xmit_frame(struct sk_buff *skb, struct net_device *netdev) { struct vmxnet3_adapter *adapter = netdev_priv(netdev); - return vmxnet3_tq_xmit(skb, &adapter->tx_queue, adapter, netdev); + BUG_ON(skb->queue_mapping > adapter->num_tx_queues); + return vmxnet3_tq_xmit(skb, + &adapter->tx_queue[skb->queue_mapping], + adapter, netdev); } @@ -1106,9 +1153,9 @@ vmxnet3_rq_rx_complete(struct vmxnet3_rx_queue *rq, break; } num_rxd++; - + BUG_ON(rcd->rqID != rq->qid && rcd->rqID != rq->qid2); idx = rcd->rxdIdx; - ring_idx = rcd->rqID == rq->qid ? 0 : 1; + ring_idx = rcd->rqID < adapter->num_rx_queues ? 0 : 1; vmxnet3_getRxDesc(rxd, &rq->rx_ring[ring_idx].base[idx].rxd, &rxCmdDesc); rbi = rq->buf_info[ring_idx] + idx; @@ -1260,6 +1307,16 @@ vmxnet3_rq_cleanup(struct vmxnet3_rx_queue *rq, } +static void +vmxnet3_rq_cleanup_all(struct vmxnet3_adapter *adapter) +{ + int i; + + for (i = 0; i < adapter->num_rx_queues; i++) + vmxnet3_rq_cleanup(&adapter->rx_queue[i], adapter); +} + + void vmxnet3_rq_destroy(struct vmxnet3_rx_queue *rq, struct vmxnet3_adapter *adapter) { @@ -1351,6 +1408,25 @@ vmxnet3_rq_init(struct vmxnet3_rx_queue *rq, static int +vmxnet3_rq_init_all(struct vmxnet3_adapter *adapter) +{ + int i, err = 0; + + for (i = 0; i < adapter->num_rx_queues; i++) { + err = vmxnet3_rq_init(&adapter->rx_queue[i], adapter); + if (unlikely(err)) { + dev_err(&adapter->netdev->dev, "%s: failed to " + "initialize rx queue%i\n", + adapter->netdev->name, i); + break; + } + } + return err; + +} + + +static int vmxnet3_rq_create(struct vmxnet3_rx_queue *rq, struct vmxnet3_adapter *adapter) { int i; @@ -1398,33 +1474,177 @@ err: static int +vmxnet3_rq_create_all(struct vmxnet3_adapter *adapter) +{ + int i, err = 0; + + for (i = 0; i < adapter->num_rx_queues; i++) { + err = vmxnet3_rq_create(&adapter->rx_queue[i], adapter); + if (unlikely(err)) { + dev_err(&adapter->netdev->dev, + "%s: failed to create rx queue%i\n", + adapter->netdev->name, i); + goto err_out; + } + } + return err; +err_out: + vmxnet3_rq_destroy_all(adapter); + return err; + +} + +/* Multiple queue aware polling function for tx and rx */ + +static int vmxnet3_do_poll(struct vmxnet3_adapter *adapter, int budget) { + int rcd_done = 0, i; if (unlikely(adapter->shared->ecr)) vmxnet3_process_events(adapter); + for (i = 0; i < adapter->num_tx_queues; i++) + vmxnet3_tq_tx_complete(&adapter->tx_queue[i], adapter); - vmxnet3_tq_tx_complete(&adapter->tx_queue, adapter); - return vmxnet3_rq_rx_complete(&adapter->rx_queue, adapter, budget); + for (i = 0; i < adapter->num_rx_queues; i++) + rcd_done += vmxnet3_rq_rx_complete(&adapter->rx_queue[i], + adapter, budget); + return rcd_done; } static int vmxnet3_poll(struct napi_struct *napi, int budget) { - struct vmxnet3_adapter *adapter = container_of(napi, - struct vmxnet3_adapter, napi); + struct vmxnet3_rx_queue *rx_queue = container_of(napi, + struct vmxnet3_rx_queue, napi); + int rxd_done; + + rxd_done = vmxnet3_do_poll(rx_queue->adapter, budget); + + if (rxd_done < budget) { + napi_complete(napi); + vmxnet3_enable_all_intrs(rx_queue->adapter); + } + return rxd_done; +} + +/* + * NAPI polling function for MSI-X mode with multiple Rx queues + * Returns the # of the NAPI credit consumed (# of rx descriptors processed) + */ + +static int +vmxnet3_poll_rx_only(struct napi_struct *napi, int budget) +{ + struct vmxnet3_rx_queue *rq = container_of(napi, + struct vmxnet3_rx_queue, napi); + struct vmxnet3_adapter *adapter = rq->adapter; int rxd_done; - rxd_done = vmxnet3_do_poll(adapter, budget); + /* When sharing interrupt with corresponding tx queue, process + * tx completions in that queue as well + */ + if (adapter->share_intr == VMXNET3_INTR_BUDDYSHARE) { + struct vmxnet3_tx_queue *tq = + &adapter->tx_queue[rq - adapter->rx_queue]; + vmxnet3_tq_tx_complete(tq, adapter); + } + + rxd_done = vmxnet3_rq_rx_complete(rq, adapter, budget); if (rxd_done < budget) { napi_complete(napi); - vmxnet3_enable_intr(adapter, 0); + vmxnet3_enable_intr(adapter, rq->comp_ring.intr_idx); } return rxd_done; } +#ifdef CONFIG_PCI_MSI + +/* + * Handle completion interrupts on tx queues + * Returns whether or not the intr is handled + */ + +static irqreturn_t +vmxnet3_msix_tx(int irq, void *data) +{ + struct vmxnet3_tx_queue *tq = data; + struct vmxnet3_adapter *adapter = tq->adapter; + + if (adapter->intr.mask_mode == VMXNET3_IMM_ACTIVE) + vmxnet3_disable_intr(adapter, tq->comp_ring.intr_idx); + + /* Handle the case where only one irq is allocate for all tx queues */ + if (adapter->share_intr == VMXNET3_INTR_TXSHARE) { + int i; + for (i = 0; i < adapter->num_tx_queues; i++) { + struct vmxnet3_tx_queue *txq = &adapter->tx_queue[i]; + vmxnet3_tq_tx_complete(txq, adapter); + } + } else { + vmxnet3_tq_tx_complete(tq, adapter); + } + vmxnet3_enable_intr(adapter, tq->comp_ring.intr_idx); + + return IRQ_HANDLED; +} + + +/* + * Handle completion interrupts on rx queues. Returns whether or not the + * intr is handled + */ + +static irqreturn_t +vmxnet3_msix_rx(int irq, void *data) +{ + struct vmxnet3_rx_queue *rq = data; + struct vmxnet3_adapter *adapter = rq->adapter; + + /* disable intr if needed */ + if (adapter->intr.mask_mode == VMXNET3_IMM_ACTIVE) + vmxnet3_disable_intr(adapter, rq->comp_ring.intr_idx); + napi_schedule(&rq->napi); + + return IRQ_HANDLED; +} + +/* + *---------------------------------------------------------------------------- + * + * vmxnet3_msix_event -- + * + * vmxnet3 msix event intr handler + * + * Result: + * whether or not the intr is handled + * + *---------------------------------------------------------------------------- + */ + +static irqreturn_t +vmxnet3_msix_event(int irq, void *data) +{ + struct net_device *dev = data; + struct vmxnet3_adapter *adapter = netdev_priv(dev); + + /* disable intr if needed */ + if (adapter->intr.mask_mode == VMXNET3_IMM_ACTIVE) + vmxnet3_disable_intr(adapter, adapter->intr.event_intr_idx); + + if (adapter->shared->ecr) + vmxnet3_process_events(adapter); + + vmxnet3_enable_intr(adapter, adapter->intr.event_intr_idx); + + return IRQ_HANDLED; +} + +#endif /* CONFIG_PCI_MSI */ + + /* Interrupt handler for vmxnet3 */ static irqreturn_t vmxnet3_intr(int irq, void *dev_id) @@ -1432,7 +1652,7 @@ vmxnet3_intr(int irq, void *dev_id) struct net_device *dev = dev_id; struct vmxnet3_adapter *adapter = netdev_priv(dev); - if (unlikely(adapter->intr.type == VMXNET3_IT_INTX)) { + if (adapter->intr.type == VMXNET3_IT_INTX) { u32 icr = VMXNET3_READ_BAR1_REG(adapter, VMXNET3_REG_ICR); if (unlikely(icr == 0)) /* not ours */ @@ -1442,77 +1662,144 @@ vmxnet3_intr(int irq, void *dev_id) /* disable intr if needed */ if (adapter->intr.mask_mode == VMXNET3_IMM_ACTIVE) - vmxnet3_disable_intr(adapter, 0); + vmxnet3_disable_all_intrs(adapter); - napi_schedule(&adapter->napi); + napi_schedule(&adapter->rx_queue[0].napi); return IRQ_HANDLED; } #ifdef CONFIG_NET_POLL_CONTROLLER - /* netpoll callback. */ static void vmxnet3_netpoll(struct net_device *netdev) { struct vmxnet3_adapter *adapter = netdev_priv(netdev); - int irq; -#ifdef CONFIG_PCI_MSI - if (adapter->intr.type == VMXNET3_IT_MSIX) - irq = adapter->intr.msix_entries[0].vector; - else -#endif - irq = adapter->pdev->irq; + if (adapter->intr.mask_mode == VMXNET3_IMM_ACTIVE) + vmxnet3_disable_all_intrs(adapter); + + vmxnet3_do_poll(adapter, adapter->rx_queue[0].rx_ring[0].size); + vmxnet3_enable_all_intrs(adapter); - disable_irq(irq); - vmxnet3_intr(irq, netdev); - enable_irq(irq); } -#endif +#endif /* CONFIG_NET_POLL_CONTROLLER */ static int vmxnet3_request_irqs(struct vmxnet3_adapter *adapter) { - int err; + struct vmxnet3_intr *intr = &adapter->intr; + int err = 0, i; + int vector = 0; #ifdef CONFIG_PCI_MSI if (adapter->intr.type == VMXNET3_IT_MSIX) { - /* we only use 1 MSI-X vector */ - err = request_irq(adapter->intr.msix_entries[0].vector, - vmxnet3_intr, 0, adapter->netdev->name, - adapter->netdev); - } else if (adapter->intr.type == VMXNET3_IT_MSI) { + for (i = 0; i < adapter->num_tx_queues; i++) { + if (adapter->share_intr != VMXNET3_INTR_BUDDYSHARE) { + sprintf(adapter->tx_queue[i].name, "%s-tx-%d", + adapter->netdev->name, vector); + err = request_irq( + intr->msix_entries[vector].vector, + vmxnet3_msix_tx, 0, + adapter->tx_queue[i].name, + &adapter->tx_queue[i]); + } else { + sprintf(adapter->tx_queue[i].name, "%s-rxtx-%d", + adapter->netdev->name, vector); + } + if (err) { + dev_err(&adapter->netdev->dev, + "Failed to request irq for MSIX, %s, " + "error %d\n", + adapter->tx_queue[i].name, err); + return err; + } + + /* Handle the case where only 1 MSIx was allocated for + * all tx queues */ + if (adapter->share_intr == VMXNET3_INTR_TXSHARE) { + for (; i < adapter->num_tx_queues; i++) + adapter->tx_queue[i].comp_ring.intr_idx + = vector; + vector++; + break; + } else { + adapter->tx_queue[i].comp_ring.intr_idx + = vector++; + } + } + if (adapter->share_intr == VMXNET3_INTR_BUDDYSHARE) + vector = 0; + + for (i = 0; i < adapter->num_rx_queues; i++) { + if (adapter->share_intr != VMXNET3_INTR_BUDDYSHARE) + sprintf(adapter->rx_queue[i].name, "%s-rx-%d", + adapter->netdev->name, vector); + else + sprintf(adapter->rx_queue[i].name, "%s-rxtx-%d", + adapter->netdev->name, vector); + err = request_irq(intr->msix_entries[vector].vector, + vmxnet3_msix_rx, 0, + adapter->rx_queue[i].name, + &(adapter->rx_queue[i])); + if (err) { + printk(KERN_ERR "Failed to request irq for MSIX" + ", %s, error %d\n", + adapter->rx_queue[i].name, err); + return err; + } + + adapter->rx_queue[i].comp_ring.intr_idx = vector++; + } + + sprintf(intr->event_msi_vector_name, "%s-event-%d", + adapter->netdev->name, vector); + err = request_irq(intr->msix_entries[vector].vector, + vmxnet3_msix_event, 0, + intr->event_msi_vector_name, adapter->netdev); + intr->event_intr_idx = vector; + + } else if (intr->type == VMXNET3_IT_MSI) { + adapter->num_rx_queues = 1; err = request_irq(adapter->pdev->irq, vmxnet3_intr, 0, adapter->netdev->name, adapter->netdev); - } else + } else { #endif - { + adapter->num_rx_queues = 1; err = request_irq(adapter->pdev->irq, vmxnet3_intr, IRQF_SHARED, adapter->netdev->name, adapter->netdev); +#ifdef CONFIG_PCI_MSI } - - if (err) +#endif + intr->num_intrs = vector + 1; + if (err) { printk(KERN_ERR "Failed to request irq %s (intr type:%d), error" - ":%d\n", adapter->netdev->name, adapter->intr.type, err); + ":%d\n", adapter->netdev->name, intr->type, err); + } else { + /* Number of rx queues will not change after this */ + for (i = 0; i < adapter->num_rx_queues; i++) { + struct vmxnet3_rx_queue *rq = &adapter->rx_queue[i]; + rq->qid = i; + rq->qid2 = i + adapter->num_rx_queues; + } - if (!err) { - int i; - /* init our intr settings */ - for (i = 0; i < adapter->intr.num_intrs; i++) - adapter->intr.mod_levels[i] = UPT1_IML_ADAPTIVE; - /* next setup intr index for all intr sources */ - adapter->tx_queue.comp_ring.intr_idx = 0; - adapter->rx_queue.comp_ring.intr_idx = 0; - adapter->intr.event_intr_idx = 0; + /* init our intr settings */ + for (i = 0; i < intr->num_intrs; i++) + intr->mod_levels[i] = UPT1_IML_ADAPTIVE; + if (adapter->intr.type != VMXNET3_IT_MSIX) { + adapter->intr.event_intr_idx = 0; + for (i = 0; i < adapter->num_tx_queues; i++) + adapter->tx_queue[i].comp_ring.intr_idx = 0; + adapter->rx_queue[0].comp_ring.intr_idx = 0; + } printk(KERN_INFO "%s: intr type %u, mode %u, %u vectors " - "allocated\n", adapter->netdev->name, adapter->intr.type, - adapter->intr.mask_mode, adapter->intr.num_intrs); + "allocated\n", adapter->netdev->name, intr->type, + intr->mask_mode, intr->num_intrs); } return err; @@ -1522,18 +1809,32 @@ vmxnet3_request_irqs(struct vmxnet3_adapter *adapter) static void vmxnet3_free_irqs(struct vmxnet3_adapter *adapter) { - BUG_ON(adapter->intr.type == VMXNET3_IT_AUTO || - adapter->intr.num_intrs <= 0); + struct vmxnet3_intr *intr = &adapter->intr; + BUG_ON(intr->type == VMXNET3_IT_AUTO || intr->num_intrs <= 0); - switch (adapter->intr.type) { + switch (intr->type) { #ifdef CONFIG_PCI_MSI case VMXNET3_IT_MSIX: { - int i; + int i, vector = 0; - for (i = 0; i < adapter->intr.num_intrs; i++) - free_irq(adapter->intr.msix_entries[i].vector, - adapter->netdev); + if (adapter->share_intr != VMXNET3_INTR_BUDDYSHARE) { + for (i = 0; i < adapter->num_tx_queues; i++) { + free_irq(intr->msix_entries[vector++].vector, + &(adapter->tx_queue[i])); + if (adapter->share_intr == VMXNET3_INTR_TXSHARE) + break; + } + } + + for (i = 0; i < adapter->num_rx_queues; i++) { + free_irq(intr->msix_entries[vector++].vector, + &(adapter->rx_queue[i])); + } + + free_irq(intr->msix_entries[vector].vector, + adapter->netdev); + BUG_ON(vector >= intr->num_intrs); break; } #endif @@ -1727,6 +2028,15 @@ vmxnet3_set_mc(struct net_device *netdev) kfree(new_table); } +void +vmxnet3_rq_destroy_all(struct vmxnet3_adapter *adapter) +{ + int i; + + for (i = 0; i < adapter->num_rx_queues; i++) + vmxnet3_rq_destroy(&adapter->rx_queue[i], adapter); +} + /* * Set up driver_shared based on settings in adapter. @@ -1774,40 +2084,72 @@ vmxnet3_setup_driver_shared(struct vmxnet3_adapter *adapter) devRead->misc.mtu = cpu_to_le32(adapter->netdev->mtu); devRead->misc.queueDescPA = cpu_to_le64(adapter->queue_desc_pa); devRead->misc.queueDescLen = cpu_to_le32( - sizeof(struct Vmxnet3_TxQueueDesc) + - sizeof(struct Vmxnet3_RxQueueDesc)); + adapter->num_tx_queues * sizeof(struct Vmxnet3_TxQueueDesc) + + adapter->num_rx_queues * sizeof(struct Vmxnet3_RxQueueDesc)); /* tx queue settings */ - BUG_ON(adapter->tx_queue.tx_ring.base == NULL); - - devRead->misc.numTxQueues = 1; - tqc = &adapter->tqd_start->conf; - tqc->txRingBasePA = cpu_to_le64(adapter->tx_queue.tx_ring.basePA); - tqc->dataRingBasePA = cpu_to_le64(adapter->tx_queue.data_ring.basePA); - tqc->compRingBasePA = cpu_to_le64(adapter->tx_queue.comp_ring.basePA); - tqc->ddPA = cpu_to_le64(virt_to_phys( - adapter->tx_queue.buf_info)); - tqc->txRingSize = cpu_to_le32(adapter->tx_queue.tx_ring.size); - tqc->dataRingSize = cpu_to_le32(adapter->tx_queue.data_ring.size); - tqc->compRingSize = cpu_to_le32(adapter->tx_queue.comp_ring.size); - tqc->ddLen = cpu_to_le32(sizeof(struct vmxnet3_tx_buf_info) * - tqc->txRingSize); - tqc->intrIdx = adapter->tx_queue.comp_ring.intr_idx; + devRead->misc.numTxQueues = adapter->num_tx_queues; + for (i = 0; i < adapter->num_tx_queues; i++) { + struct vmxnet3_tx_queue *tq = &adapter->tx_queue[i]; + BUG_ON(adapter->tx_queue[i].tx_ring.base == NULL); + tqc = &adapter->tqd_start[i].conf; + tqc->txRingBasePA = cpu_to_le64(tq->tx_ring.basePA); + tqc->dataRingBasePA = cpu_to_le64(tq->data_ring.basePA); + tqc->compRingBasePA = cpu_to_le64(tq->comp_ring.basePA); + tqc->ddPA = cpu_to_le64(virt_to_phys(tq->buf_info)); + tqc->txRingSize = cpu_to_le32(tq->tx_ring.size); + tqc->dataRingSize = cpu_to_le32(tq->data_ring.size); + tqc->compRingSize = cpu_to_le32(tq->comp_ring.size); + tqc->ddLen = cpu_to_le32( + sizeof(struct vmxnet3_tx_buf_info) * + tqc->txRingSize); + tqc->intrIdx = tq->comp_ring.intr_idx; + } /* rx queue settings */ - devRead->misc.numRxQueues = 1; - rqc = &adapter->rqd_start->conf; - rqc->rxRingBasePA[0] = cpu_to_le64(adapter->rx_queue.rx_ring[0].basePA); - rqc->rxRingBasePA[1] = cpu_to_le64(adapter->rx_queue.rx_ring[1].basePA); - rqc->compRingBasePA = cpu_to_le64(adapter->rx_queue.comp_ring.basePA); - rqc->ddPA = cpu_to_le64(virt_to_phys( - adapter->rx_queue.buf_info)); - rqc->rxRingSize[0] = cpu_to_le32(adapter->rx_queue.rx_ring[0].size); - rqc->rxRingSize[1] = cpu_to_le32(adapter->rx_queue.rx_ring[1].size); - rqc->compRingSize = cpu_to_le32(adapter->rx_queue.comp_ring.size); - rqc->ddLen = cpu_to_le32(sizeof(struct vmxnet3_rx_buf_info) * - (rqc->rxRingSize[0] + rqc->rxRingSize[1])); - rqc->intrIdx = adapter->rx_queue.comp_ring.intr_idx; + devRead->misc.numRxQueues = adapter->num_rx_queues; + for (i = 0; i < adapter->num_rx_queues; i++) { + struct vmxnet3_rx_queue *rq = &adapter->rx_queue[i]; + rqc = &adapter->rqd_start[i].conf; + rqc->rxRingBasePA[0] = cpu_to_le64(rq->rx_ring[0].basePA); + rqc->rxRingBasePA[1] = cpu_to_le64(rq->rx_ring[1].basePA); + rqc->compRingBasePA = cpu_to_le64(rq->comp_ring.basePA); + rqc->ddPA = cpu_to_le64(virt_to_phys( + rq->buf_info)); + rqc->rxRingSize[0] = cpu_to_le32(rq->rx_ring[0].size); + rqc->rxRingSize[1] = cpu_to_le32(rq->rx_ring[1].size); + rqc->compRingSize = cpu_to_le32(rq->comp_ring.size); + rqc->ddLen = cpu_to_le32( + sizeof(struct vmxnet3_rx_buf_info) * + (rqc->rxRingSize[0] + + rqc->rxRingSize[1])); + rqc->intrIdx = rq->comp_ring.intr_idx; + } + +#ifdef VMXNET3_RSS + memset(adapter->rss_conf, 0, sizeof(*adapter->rss_conf)); + + if (adapter->rss) { + struct UPT1_RSSConf *rssConf = adapter->rss_conf; + devRead->misc.uptFeatures |= UPT1_F_RSS; + devRead->misc.numRxQueues = adapter->num_rx_queues; + rssConf->hashType = UPT1_RSS_HASH_TYPE_TCP_IPV4 | + UPT1_RSS_HASH_TYPE_IPV4 | + UPT1_RSS_HASH_TYPE_TCP_IPV6 | + UPT1_RSS_HASH_TYPE_IPV6; + rssConf->hashFunc = UPT1_RSS_HASH_FUNC_TOEPLITZ; + rssConf->hashKeySize = UPT1_RSS_MAX_KEY_SIZE; + rssConf->indTableSize = VMXNET3_RSS_IND_TABLE_SIZE; + get_random_bytes(&rssConf->hashKey[0], rssConf->hashKeySize); + for (i = 0; i < rssConf->indTableSize; i++) + rssConf->indTable[i] = i % adapter->num_rx_queues; + + devRead->rssConfDesc.confVer = 1; + devRead->rssConfDesc.confLen = sizeof(*rssConf); + devRead->rssConfDesc.confPA = virt_to_phys(rssConf); + } + +#endif /* VMXNET3_RSS */ /* intr settings */ devRead->intrConf.autoMask = adapter->intr.mask_mode == @@ -1829,18 +2171,18 @@ vmxnet3_setup_driver_shared(struct vmxnet3_adapter *adapter) int vmxnet3_activate_dev(struct vmxnet3_adapter *adapter) { - int err; + int err, i; u32 ret; - dev_dbg(&adapter->netdev->dev, - "%s: skb_buf_size %d, rx_buf_per_pkt %d, ring sizes" - " %u %u %u\n", adapter->netdev->name, adapter->skb_buf_size, - adapter->rx_buf_per_pkt, adapter->tx_queue.tx_ring.size, - adapter->rx_queue.rx_ring[0].size, - adapter->rx_queue.rx_ring[1].size); - - vmxnet3_tq_init(&adapter->tx_queue, adapter); - err = vmxnet3_rq_init(&adapter->rx_queue, adapter); + dev_dbg(&adapter->netdev->dev, "%s: skb_buf_size %d, rx_buf_per_pkt %d," + " ring sizes %u %u %u\n", adapter->netdev->name, + adapter->skb_buf_size, adapter->rx_buf_per_pkt, + adapter->tx_queue[0].tx_ring.size, + adapter->rx_queue[0].rx_ring[0].size, + adapter->rx_queue[0].rx_ring[1].size); + + vmxnet3_tq_init_all(adapter); + err = vmxnet3_rq_init_all(adapter); if (err) { printk(KERN_ERR "Failed to init rx queue for %s: error %d\n", adapter->netdev->name, err); @@ -1870,10 +2212,15 @@ vmxnet3_activate_dev(struct vmxnet3_adapter *adapter) err = -EINVAL; goto activate_err; } - VMXNET3_WRITE_BAR0_REG(adapter, VMXNET3_REG_RXPROD, - adapter->rx_queue.rx_ring[0].next2fill); - VMXNET3_WRITE_BAR0_REG(adapter, VMXNET3_REG_RXPROD2, - adapter->rx_queue.rx_ring[1].next2fill); + + for (i = 0; i < adapter->num_rx_queues; i++) { + VMXNET3_WRITE_BAR0_REG(adapter, + VMXNET3_REG_RXPROD + i * VMXNET3_REG_ALIGN, + adapter->rx_queue[i].rx_ring[0].next2fill); + VMXNET3_WRITE_BAR0_REG(adapter, (VMXNET3_REG_RXPROD2 + + (i * VMXNET3_REG_ALIGN)), + adapter->rx_queue[i].rx_ring[1].next2fill); + } /* Apply the rx filter settins last. */ vmxnet3_set_mc(adapter->netdev); @@ -1883,8 +2230,8 @@ vmxnet3_activate_dev(struct vmxnet3_adapter *adapter) * tx queue if the link is up. */ vmxnet3_check_link(adapter, true); - - napi_enable(&adapter->napi); + for (i = 0; i < adapter->num_rx_queues; i++) + napi_enable(&adapter->rx_queue[i].napi); vmxnet3_enable_all_intrs(adapter); clear_bit(VMXNET3_STATE_BIT_QUIESCED, &adapter->state); return 0; @@ -1896,7 +2243,7 @@ activate_err: irq_err: rq_err: /* free up buffers we allocated */ - vmxnet3_rq_cleanup(&adapter->rx_queue, adapter); + vmxnet3_rq_cleanup_all(adapter); return err; } @@ -1911,6 +2258,7 @@ vmxnet3_reset_dev(struct vmxnet3_adapter *adapter) int vmxnet3_quiesce_dev(struct vmxnet3_adapter *adapter) { + int i; if (test_and_set_bit(VMXNET3_STATE_BIT_QUIESCED, &adapter->state)) return 0; @@ -1919,13 +2267,14 @@ vmxnet3_quiesce_dev(struct vmxnet3_adapter *adapter) VMXNET3_CMD_QUIESCE_DEV); vmxnet3_disable_all_intrs(adapter); - napi_disable(&adapter->napi); + for (i = 0; i < adapter->num_rx_queues; i++) + napi_disable(&adapter->rx_queue[i].napi); netif_tx_disable(adapter->netdev); adapter->link_speed = 0; netif_carrier_off(adapter->netdev); - vmxnet3_tq_cleanup(&adapter->tx_queue, adapter); - vmxnet3_rq_cleanup(&adapter->rx_queue, adapter); + vmxnet3_tq_cleanup_all(adapter); + vmxnet3_rq_cleanup_all(adapter); vmxnet3_free_irqs(adapter); return 0; } @@ -2047,7 +2396,9 @@ vmxnet3_free_pci_resources(struct vmxnet3_adapter *adapter) static void vmxnet3_adjust_rx_ring_size(struct vmxnet3_adapter *adapter) { - size_t sz; + size_t sz, i, ring0_size, ring1_size, comp_size; + struct vmxnet3_rx_queue *rq = &adapter->rx_queue[0]; + if (adapter->netdev->mtu <= VMXNET3_MAX_SKB_BUF_SIZE - VMXNET3_MAX_ETH_HDR_SIZE) { @@ -2069,11 +2420,19 @@ vmxnet3_adjust_rx_ring_size(struct vmxnet3_adapter *adapter) * rx_buf_per_pkt * VMXNET3_RING_SIZE_ALIGN */ sz = adapter->rx_buf_per_pkt * VMXNET3_RING_SIZE_ALIGN; - adapter->rx_queue.rx_ring[0].size = (adapter->rx_queue.rx_ring[0].size + - sz - 1) / sz * sz; - adapter->rx_queue.rx_ring[0].size = min_t(u32, - adapter->rx_queue.rx_ring[0].size, - VMXNET3_RX_RING_MAX_SIZE / sz * sz); + ring0_size = adapter->rx_queue[0].rx_ring[0].size; + ring0_size = (ring0_size + sz - 1) / sz * sz; + ring0_size = min_t(u32, rq->rx_ring[0].size, VMXNET3_RX_RING_MAX_SIZE / + sz * sz); + ring1_size = adapter->rx_queue[0].rx_ring[1].size; + comp_size = ring0_size + ring1_size; + + for (i = 0; i < adapter->num_rx_queues; i++) { + rq = &adapter->rx_queue[i]; + rq->rx_ring[0].size = ring0_size; + rq->rx_ring[1].size = ring1_size; + rq->comp_ring.size = comp_size; + } } @@ -2081,29 +2440,53 @@ int vmxnet3_create_queues(struct vmxnet3_adapter *adapter, u32 tx_ring_size, u32 rx_ring_size, u32 rx_ring2_size) { - int err; - - adapter->tx_queue.tx_ring.size = tx_ring_size; - adapter->tx_queue.data_ring.size = tx_ring_size; - adapter->tx_queue.comp_ring.size = tx_ring_size; - adapter->tx_queue.shared = &adapter->tqd_start->ctrl; - adapter->tx_queue.stopped = true; - err = vmxnet3_tq_create(&adapter->tx_queue, adapter); - if (err) - return err; + int err = 0, i; + + for (i = 0; i < adapter->num_tx_queues; i++) { + struct vmxnet3_tx_queue *tq = &adapter->tx_queue[i]; + tq->tx_ring.size = tx_ring_size; + tq->data_ring.size = tx_ring_size; + tq->comp_ring.size = tx_ring_size; + tq->shared = &adapter->tqd_start[i].ctrl; + tq->stopped = true; + tq->adapter = adapter; + tq->qid = i; + err = vmxnet3_tq_create(tq, adapter); + /* + * Too late to change num_tx_queues. We cannot do away with + * lesser number of queues than what we asked for + */ + if (err) + goto queue_err; + } - adapter->rx_queue.rx_ring[0].size = rx_ring_size; - adapter->rx_queue.rx_ring[1].size = rx_ring2_size; + adapter->rx_queue[0].rx_ring[0].size = rx_ring_size; + adapter->rx_queue[0].rx_ring[1].size = rx_ring2_size; vmxnet3_adjust_rx_ring_size(adapter); - adapter->rx_queue.comp_ring.size = adapter->rx_queue.rx_ring[0].size + - adapter->rx_queue.rx_ring[1].size; - adapter->rx_queue.qid = 0; - adapter->rx_queue.qid2 = 1; - adapter->rx_queue.shared = &adapter->rqd_start->ctrl; - err = vmxnet3_rq_create(&adapter->rx_queue, adapter); - if (err) - vmxnet3_tq_destroy(&adapter->tx_queue, adapter); - + for (i = 0; i < adapter->num_rx_queues; i++) { + struct vmxnet3_rx_queue *rq = &adapter->rx_queue[i]; + /* qid and qid2 for rx queues will be assigned later when num + * of rx queues is finalized after allocating intrs */ + rq->shared = &adapter->rqd_start[i].ctrl; + rq->adapter = adapter; + err = vmxnet3_rq_create(rq, adapter); + if (err) { + if (i == 0) { + printk(KERN_ERR "Could not allocate any rx" + "queues. Aborting.\n"); + goto queue_err; + } else { + printk(KERN_INFO "Number of rx queues changed " + "to : %d.\n", i); + adapter->num_rx_queues = i; + err = 0; + break; + } + } + } + return err; +queue_err: + vmxnet3_tq_destroy_all(adapter); return err; } @@ -2111,11 +2494,12 @@ static int vmxnet3_open(struct net_device *netdev) { struct vmxnet3_adapter *adapter; - int err; + int err, i; adapter = netdev_priv(netdev); - spin_lock_init(&adapter->tx_queue.tx_lock); + for (i = 0; i < adapter->num_tx_queues; i++) + spin_lock_init(&adapter->tx_queue[i].tx_lock); err = vmxnet3_create_queues(adapter, VMXNET3_DEF_TX_RING_SIZE, VMXNET3_DEF_RX_RING_SIZE, @@ -2130,8 +2514,8 @@ vmxnet3_open(struct net_device *netdev) return 0; activate_err: - vmxnet3_rq_destroy(&adapter->rx_queue, adapter); - vmxnet3_tq_destroy(&adapter->tx_queue, adapter); + vmxnet3_rq_destroy_all(adapter); + vmxnet3_tq_destroy_all(adapter); queue_err: return err; } @@ -2151,8 +2535,8 @@ vmxnet3_close(struct net_device *netdev) vmxnet3_quiesce_dev(adapter); - vmxnet3_rq_destroy(&adapter->rx_queue, adapter); - vmxnet3_tq_destroy(&adapter->tx_queue, adapter); + vmxnet3_rq_destroy_all(adapter); + vmxnet3_tq_destroy_all(adapter); clear_bit(VMXNET3_STATE_BIT_RESETTING, &adapter->state); @@ -2164,6 +2548,8 @@ vmxnet3_close(struct net_device *netdev) void vmxnet3_force_close(struct vmxnet3_adapter *adapter) { + int i; + /* * we must clear VMXNET3_STATE_BIT_RESETTING, otherwise * vmxnet3_close() will deadlock. @@ -2171,7 +2557,8 @@ vmxnet3_force_close(struct vmxnet3_adapter *adapter) BUG_ON(test_bit(VMXNET3_STATE_BIT_RESETTING, &adapter->state)); /* we need to enable NAPI, otherwise dev_close will deadlock */ - napi_enable(&adapter->napi); + for (i = 0; i < adapter->num_rx_queues; i++) + napi_enable(&adapter->rx_queue[i].napi); dev_close(adapter->netdev); } @@ -2202,14 +2589,11 @@ vmxnet3_change_mtu(struct net_device *netdev, int new_mtu) vmxnet3_reset_dev(adapter); /* we need to re-create the rx queue based on the new mtu */ - vmxnet3_rq_destroy(&adapter->rx_queue, adapter); + vmxnet3_rq_destroy_all(adapter); vmxnet3_adjust_rx_ring_size(adapter); - adapter->rx_queue.comp_ring.size = - adapter->rx_queue.rx_ring[0].size + - adapter->rx_queue.rx_ring[1].size; - err = vmxnet3_rq_create(&adapter->rx_queue, adapter); + err = vmxnet3_rq_create_all(adapter); if (err) { - printk(KERN_ERR "%s: failed to re-create rx queue," + printk(KERN_ERR "%s: failed to re-create rx queues," " error %d. Closing it.\n", netdev->name, err); goto out; } @@ -2274,6 +2658,55 @@ vmxnet3_read_mac_addr(struct vmxnet3_adapter *adapter, u8 *mac) mac[5] = (tmp >> 8) & 0xff; } +#ifdef CONFIG_PCI_MSI + +/* + * Enable MSIx vectors. + * Returns : + * 0 on successful enabling of required vectors, + * VMXNET3_LINUX_MIN_MSIX_VECT when only minumum number of vectors required + * could be enabled. + * number of vectors which can be enabled otherwise (this number is smaller + * than VMXNET3_LINUX_MIN_MSIX_VECT) + */ + +static int +vmxnet3_acquire_msix_vectors(struct vmxnet3_adapter *adapter, + int vectors) +{ + int err = 0, vector_threshold; + vector_threshold = VMXNET3_LINUX_MIN_MSIX_VECT; + + while (vectors >= vector_threshold) { + err = pci_enable_msix(adapter->pdev, adapter->intr.msix_entries, + vectors); + if (!err) { + adapter->intr.num_intrs = vectors; + return 0; + } else if (err < 0) { + printk(KERN_ERR "Failed to enable MSI-X for %s, error" + " %d\n", adapter->netdev->name, err); + vectors = 0; + } else if (err < vector_threshold) { + break; + } else { + /* If fails to enable required number of MSI-x vectors + * try enabling 3 of them. One each for rx, tx and event + */ + vectors = vector_threshold; + printk(KERN_ERR "Failed to enable %d MSI-X for %s, try" + " %d instead\n", vectors, adapter->netdev->name, + vector_threshold); + } + } + + printk(KERN_INFO "Number of MSI-X interrupts which can be allocatedi" + " are lower than min threshold required.\n"); + return err; +} + + +#endif /* CONFIG_PCI_MSI */ static void vmxnet3_alloc_intr_resources(struct vmxnet3_adapter *adapter) @@ -2293,16 +2726,47 @@ vmxnet3_alloc_intr_resources(struct vmxnet3_adapter *adapter) #ifdef CONFIG_PCI_MSI if (adapter->intr.type == VMXNET3_IT_MSIX) { - int err; - - adapter->intr.msix_entries[0].entry = 0; - err = pci_enable_msix(adapter->pdev, adapter->intr.msix_entries, - VMXNET3_LINUX_MAX_MSIX_VECT); - if (!err) { - adapter->intr.num_intrs = 1; - adapter->intr.type = VMXNET3_IT_MSIX; + int vector, err = 0; + + adapter->intr.num_intrs = (adapter->share_intr == + VMXNET3_INTR_TXSHARE) ? 1 : + adapter->num_tx_queues; + adapter->intr.num_intrs += (adapter->share_intr == + VMXNET3_INTR_BUDDYSHARE) ? 0 : + adapter->num_rx_queues; + adapter->intr.num_intrs += 1; /* for link event */ + + adapter->intr.num_intrs = (adapter->intr.num_intrs > + VMXNET3_LINUX_MIN_MSIX_VECT + ? adapter->intr.num_intrs : + VMXNET3_LINUX_MIN_MSIX_VECT); + + for (vector = 0; vector < adapter->intr.num_intrs; vector++) + adapter->intr.msix_entries[vector].entry = vector; + + err = vmxnet3_acquire_msix_vectors(adapter, + adapter->intr.num_intrs); + /* If we cannot allocate one MSIx vector per queue + * then limit the number of rx queues to 1 + */ + if (err == VMXNET3_LINUX_MIN_MSIX_VECT) { + if (adapter->share_intr != VMXNET3_INTR_BUDDYSHARE + || adapter->num_rx_queues != 2) { + adapter->share_intr = VMXNET3_INTR_TXSHARE; + printk(KERN_ERR "Number of rx queues : 1\n"); + adapter->num_rx_queues = 1; + adapter->intr.num_intrs = + VMXNET3_LINUX_MIN_MSIX_VECT; + } return; } + if (!err) + return; + + /* If we cannot allocate MSIx vectors use only one rx queue */ + printk(KERN_INFO "Failed to enable MSI-X for %s, error %d." + "#rx queues : 1, try MSI\n", adapter->netdev->name, err); + adapter->intr.type = VMXNET3_IT_MSI; } @@ -2310,12 +2774,15 @@ vmxnet3_alloc_intr_resources(struct vmxnet3_adapter *adapter) int err; err = pci_enable_msi(adapter->pdev); if (!err) { + adapter->num_rx_queues = 1; adapter->intr.num_intrs = 1; return; } } #endif /* CONFIG_PCI_MSI */ + adapter->num_rx_queues = 1; + printk(KERN_INFO "Using INTx interrupt, #Rx queues: 1.\n"); adapter->intr.type = VMXNET3_IT_INTX; /* INT-X related setting */ @@ -2343,6 +2810,7 @@ vmxnet3_tx_timeout(struct net_device *netdev) printk(KERN_ERR "%s: tx hang\n", adapter->netdev->name); schedule_work(&adapter->work); + netif_wake_queue(adapter->netdev); } @@ -2399,8 +2867,29 @@ vmxnet3_probe_device(struct pci_dev *pdev, struct net_device *netdev; struct vmxnet3_adapter *adapter; u8 mac[ETH_ALEN]; + int size; + int num_tx_queues; + int num_rx_queues; + +#ifdef VMXNET3_RSS + if (enable_mq) + num_rx_queues = min(VMXNET3_DEVICE_MAX_RX_QUEUES, + (int)num_online_cpus()); + else +#endif + num_rx_queues = 1; + + if (enable_mq) + num_tx_queues = min(VMXNET3_DEVICE_MAX_TX_QUEUES, + (int)num_online_cpus()); + else + num_tx_queues = 1; + + netdev = alloc_etherdev_mq(sizeof(struct vmxnet3_adapter), + max(num_tx_queues, num_rx_queues)); + printk(KERN_INFO "# of Tx queues : %d, # of Rx queues : %d\n", + num_tx_queues, num_rx_queues); - netdev = alloc_etherdev(sizeof(struct vmxnet3_adapter)); if (!netdev) { printk(KERN_ERR "Failed to alloc ethernet device for adapter " "%s\n", pci_name(pdev)); @@ -2422,9 +2911,12 @@ vmxnet3_probe_device(struct pci_dev *pdev, goto err_alloc_shared; } - adapter->tqd_start = pci_alloc_consistent(adapter->pdev, - sizeof(struct Vmxnet3_TxQueueDesc) + - sizeof(struct Vmxnet3_RxQueueDesc), + adapter->num_rx_queues = num_rx_queues; + adapter->num_tx_queues = num_tx_queues; + + size = sizeof(struct Vmxnet3_TxQueueDesc) * adapter->num_tx_queues; + size += sizeof(struct Vmxnet3_RxQueueDesc) * adapter->num_rx_queues; + adapter->tqd_start = pci_alloc_consistent(adapter->pdev, size, &adapter->queue_desc_pa); if (!adapter->tqd_start) { @@ -2433,8 +2925,8 @@ vmxnet3_probe_device(struct pci_dev *pdev, err = -ENOMEM; goto err_alloc_queue_desc; } - adapter->rqd_start = (struct Vmxnet3_RxQueueDesc *)(adapter->tqd_start - + 1); + adapter->rqd_start = (struct Vmxnet3_RxQueueDesc *)(adapter->tqd_start + + adapter->num_tx_queues); adapter->pm_conf = kmalloc(sizeof(struct Vmxnet3_PMConf), GFP_KERNEL); if (adapter->pm_conf == NULL) { @@ -2444,6 +2936,17 @@ vmxnet3_probe_device(struct pci_dev *pdev, goto err_alloc_pm; } +#ifdef VMXNET3_RSS + + adapter->rss_conf = kmalloc(sizeof(struct UPT1_RSSConf), GFP_KERNEL); + if (adapter->rss_conf == NULL) { + printk(KERN_ERR "Failed to allocate memory for %s\n", + pci_name(pdev)); + err = -ENOMEM; + goto err_alloc_rss; + } +#endif /* VMXNET3_RSS */ + err = vmxnet3_alloc_pci_resources(adapter, &dma64); if (err < 0) goto err_alloc_pci; @@ -2471,18 +2974,48 @@ vmxnet3_probe_device(struct pci_dev *pdev, vmxnet3_declare_features(adapter, dma64); adapter->dev_number = atomic_read(&devices_found); + + adapter->share_intr = irq_share_mode; + if (adapter->share_intr == VMXNET3_INTR_BUDDYSHARE && + adapter->num_tx_queues != adapter->num_rx_queues) + adapter->share_intr = VMXNET3_INTR_DONTSHARE; + vmxnet3_alloc_intr_resources(adapter); +#ifdef VMXNET3_RSS + if (adapter->num_rx_queues > 1 && + adapter->intr.type == VMXNET3_IT_MSIX) { + adapter->rss = true; + printk(KERN_INFO "RSS is enabled.\n"); + } else { + adapter->rss = false; + } +#endif + vmxnet3_read_mac_addr(adapter, mac); memcpy(netdev->dev_addr, mac, netdev->addr_len); netdev->netdev_ops = &vmxnet3_netdev_ops; - netdev->watchdog_timeo = 5 * HZ; vmxnet3_set_ethtool_ops(netdev); + netdev->watchdog_timeo = 5 * HZ; INIT_WORK(&adapter->work, vmxnet3_reset_work); - netif_napi_add(netdev, &adapter->napi, vmxnet3_poll, 64); + if (adapter->intr.type == VMXNET3_IT_MSIX) { + int i; + for (i = 0; i < adapter->num_rx_queues; i++) { + netif_napi_add(adapter->netdev, + &adapter->rx_queue[i].napi, + vmxnet3_poll_rx_only, 64); + } + } else { + netif_napi_add(adapter->netdev, &adapter->rx_queue[0].napi, + vmxnet3_poll, 64); + } + + netif_set_real_num_tx_queues(adapter->netdev, adapter->num_tx_queues); + netif_set_real_num_rx_queues(adapter->netdev, adapter->num_rx_queues); + SET_NETDEV_DEV(netdev, &pdev->dev); err = register_netdev(netdev); @@ -2502,11 +3035,14 @@ err_register: err_ver: vmxnet3_free_pci_resources(adapter); err_alloc_pci: +#ifdef VMXNET3_RSS + kfree(adapter->rss_conf); +err_alloc_rss: +#endif kfree(adapter->pm_conf); err_alloc_pm: - pci_free_consistent(adapter->pdev, sizeof(struct Vmxnet3_TxQueueDesc) + - sizeof(struct Vmxnet3_RxQueueDesc), - adapter->tqd_start, adapter->queue_desc_pa); + pci_free_consistent(adapter->pdev, size, adapter->tqd_start, + adapter->queue_desc_pa); err_alloc_queue_desc: pci_free_consistent(adapter->pdev, sizeof(struct Vmxnet3_DriverShared), adapter->shared, adapter->shared_pa); @@ -2522,6 +3058,16 @@ vmxnet3_remove_device(struct pci_dev *pdev) { struct net_device *netdev = pci_get_drvdata(pdev); struct vmxnet3_adapter *adapter = netdev_priv(netdev); + int size = 0; + int num_rx_queues; + +#ifdef VMXNET3_RSS + if (enable_mq) + num_rx_queues = min(VMXNET3_DEVICE_MAX_RX_QUEUES, + (int)num_online_cpus()); + else +#endif + num_rx_queues = 1; flush_scheduled_work(); @@ -2529,10 +3075,15 @@ vmxnet3_remove_device(struct pci_dev *pdev) vmxnet3_free_intr_resources(adapter); vmxnet3_free_pci_resources(adapter); +#ifdef VMXNET3_RSS + kfree(adapter->rss_conf); +#endif kfree(adapter->pm_conf); - pci_free_consistent(adapter->pdev, sizeof(struct Vmxnet3_TxQueueDesc) + - sizeof(struct Vmxnet3_RxQueueDesc), - adapter->tqd_start, adapter->queue_desc_pa); + + size = sizeof(struct Vmxnet3_TxQueueDesc) * adapter->num_tx_queues; + size += sizeof(struct Vmxnet3_RxQueueDesc) * num_rx_queues; + pci_free_consistent(adapter->pdev, size, adapter->tqd_start, + adapter->queue_desc_pa); pci_free_consistent(adapter->pdev, sizeof(struct Vmxnet3_DriverShared), adapter->shared, adapter->shared_pa); free_netdev(netdev); @@ -2563,7 +3114,7 @@ vmxnet3_suspend(struct device *device) vmxnet3_free_intr_resources(adapter); netif_device_detach(netdev); - netif_stop_queue(netdev); + netif_tx_stop_all_queues(netdev); /* Create wake-up filters. */ pmConf = adapter->pm_conf; diff --git a/drivers/net/vmxnet3/vmxnet3_ethtool.c b/drivers/net/vmxnet3/vmxnet3_ethtool.c index b79070bcc92e..8e17fc8a7fe7 100644 --- a/drivers/net/vmxnet3/vmxnet3_ethtool.c +++ b/drivers/net/vmxnet3/vmxnet3_ethtool.c @@ -151,44 +151,42 @@ vmxnet3_get_stats(struct net_device *netdev) struct UPT1_TxStats *devTxStats; struct UPT1_RxStats *devRxStats; struct net_device_stats *net_stats = &netdev->stats; + int i; adapter = netdev_priv(netdev); /* Collect the dev stats into the shared area */ VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD, VMXNET3_CMD_GET_STATS); - /* Assuming that we have a single queue device */ - devTxStats = &adapter->tqd_start->stats; - devRxStats = &adapter->rqd_start->stats; - - /* Get access to the driver stats per queue */ - drvTxStats = &adapter->tx_queue.stats; - drvRxStats = &adapter->rx_queue.stats; - 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; + } - net_stats->rx_packets = devRxStats->ucastPktsRxOK + - devRxStats->mcastPktsRxOK + - devRxStats->bcastPktsRxOK; - - net_stats->tx_packets = devTxStats->ucastPktsTxOK + - devTxStats->mcastPktsTxOK + - devTxStats->bcastPktsTxOK; - - net_stats->rx_bytes = devRxStats->ucastBytesRxOK + - devRxStats->mcastBytesRxOK + - devRxStats->bcastBytesRxOK; - - net_stats->tx_bytes = devTxStats->ucastBytesTxOK + - devTxStats->mcastBytesTxOK + - devTxStats->bcastBytesTxOK; + 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; - net_stats->rx_errors = devRxStats->pktsRxError; - net_stats->tx_errors = devTxStats->pktsTxError; - net_stats->rx_dropped = drvRxStats->drop_total; - net_stats->tx_dropped = drvTxStats->drop_total; - net_stats->multicast = devRxStats->mcastPktsRxOK; + net_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; + } return net_stats; } @@ -307,24 +305,26 @@ vmxnet3_get_ethtool_stats(struct net_device *netdev, struct vmxnet3_adapter *adapter = netdev_priv(netdev); u8 *base; int i; + int j = 0; VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD, VMXNET3_CMD_GET_STATS); /* this does assume each counter is 64-bit wide */ +/* TODO change this for multiple queues */ - base = (u8 *)&adapter->tqd_start->stats; + base = (u8 *)&adapter->tqd_start[j].stats; for (i = 0; i < ARRAY_SIZE(vmxnet3_tq_dev_stats); i++) *buf++ = *(u64 *)(base + vmxnet3_tq_dev_stats[i].offset); - base = (u8 *)&adapter->tx_queue.stats; + base = (u8 *)&adapter->tx_queue[j].stats; for (i = 0; i < ARRAY_SIZE(vmxnet3_tq_driver_stats); i++) *buf++ = *(u64 *)(base + vmxnet3_tq_driver_stats[i].offset); - base = (u8 *)&adapter->rqd_start->stats; + base = (u8 *)&adapter->rqd_start[j].stats; for (i = 0; i < ARRAY_SIZE(vmxnet3_rq_dev_stats); i++) *buf++ = *(u64 *)(base + vmxnet3_rq_dev_stats[i].offset); - base = (u8 *)&adapter->rx_queue.stats; + base = (u8 *)&adapter->rx_queue[j].stats; for (i = 0; i < ARRAY_SIZE(vmxnet3_rq_driver_stats); i++) *buf++ = *(u64 *)(base + vmxnet3_rq_driver_stats[i].offset); @@ -339,6 +339,7 @@ vmxnet3_get_regs(struct net_device *netdev, struct ethtool_regs *regs, void *p) { struct vmxnet3_adapter *adapter = netdev_priv(netdev); u32 *buf = p; + int i = 0; memset(p, 0, vmxnet3_get_regs_len(netdev)); @@ -347,28 +348,29 @@ vmxnet3_get_regs(struct net_device *netdev, struct ethtool_regs *regs, void *p) /* Update vmxnet3_get_regs_len if we want to dump more registers */ /* make each ring use multiple of 16 bytes */ - buf[0] = adapter->tx_queue.tx_ring.next2fill; - buf[1] = adapter->tx_queue.tx_ring.next2comp; - buf[2] = adapter->tx_queue.tx_ring.gen; +/* TODO change this for multiple queues */ + buf[0] = adapter->tx_queue[i].tx_ring.next2fill; + buf[1] = adapter->tx_queue[i].tx_ring.next2comp; + buf[2] = adapter->tx_queue[i].tx_ring.gen; buf[3] = 0; - buf[4] = adapter->tx_queue.comp_ring.next2proc; - buf[5] = adapter->tx_queue.comp_ring.gen; - buf[6] = adapter->tx_queue.stopped; + buf[4] = adapter->tx_queue[i].comp_ring.next2proc; + buf[5] = adapter->tx_queue[i].comp_ring.gen; + buf[6] = adapter->tx_queue[i].stopped; buf[7] = 0; - buf[8] = adapter->rx_queue.rx_ring[0].next2fill; - buf[9] = adapter->rx_queue.rx_ring[0].next2comp; - buf[10] = adapter->rx_queue.rx_ring[0].gen; + buf[8] = adapter->rx_queue[i].rx_ring[0].next2fill; + buf[9] = adapter->rx_queue[i].rx_ring[0].next2comp; + buf[10] = adapter->rx_queue[i].rx_ring[0].gen; buf[11] = 0; - buf[12] = adapter->rx_queue.rx_ring[1].next2fill; - buf[13] = adapter->rx_queue.rx_ring[1].next2comp; - buf[14] = adapter->rx_queue.rx_ring[1].gen; + buf[12] = adapter->rx_queue[i].rx_ring[1].next2fill; + buf[13] = adapter->rx_queue[i].rx_ring[1].next2comp; + buf[14] = adapter->rx_queue[i].rx_ring[1].gen; buf[15] = 0; - buf[16] = adapter->rx_queue.comp_ring.next2proc; - buf[17] = adapter->rx_queue.comp_ring.gen; + buf[16] = adapter->rx_queue[i].comp_ring.next2proc; + buf[17] = adapter->rx_queue[i].comp_ring.gen; buf[18] = 0; buf[19] = 0; } @@ -435,8 +437,10 @@ vmxnet3_get_ringparam(struct net_device *netdev, param->rx_mini_max_pending = 0; param->rx_jumbo_max_pending = 0; - param->rx_pending = adapter->rx_queue.rx_ring[0].size; - param->tx_pending = adapter->tx_queue.tx_ring.size; + param->rx_pending = adapter->rx_queue[0].rx_ring[0].size * + adapter->num_rx_queues; + param->tx_pending = adapter->tx_queue[0].tx_ring.size * + adapter->num_tx_queues; param->rx_mini_pending = 0; param->rx_jumbo_pending = 0; } @@ -480,8 +484,8 @@ vmxnet3_set_ringparam(struct net_device *netdev, sz) != 0) return -EINVAL; - if (new_tx_ring_size == adapter->tx_queue.tx_ring.size && - new_rx_ring_size == adapter->rx_queue.rx_ring[0].size) { + if (new_tx_ring_size == adapter->tx_queue[0].tx_ring.size && + new_rx_ring_size == adapter->rx_queue[0].rx_ring[0].size) { return 0; } @@ -498,11 +502,12 @@ vmxnet3_set_ringparam(struct net_device *netdev, /* recreate the rx queue and the tx queue based on the * new sizes */ - vmxnet3_tq_destroy(&adapter->tx_queue, adapter); - vmxnet3_rq_destroy(&adapter->rx_queue, adapter); + vmxnet3_tq_destroy_all(adapter); + vmxnet3_rq_destroy_all(adapter); err = vmxnet3_create_queues(adapter, new_tx_ring_size, new_rx_ring_size, VMXNET3_DEF_RX_RING_SIZE); + if (err) { /* failed, most likely because of OOM, try default * size */ @@ -535,6 +540,66 @@ out: } +static int +vmxnet3_get_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *info, + void *rules) +{ + struct vmxnet3_adapter *adapter = netdev_priv(netdev); + switch (info->cmd) { + case ETHTOOL_GRXRINGS: + info->data = adapter->num_rx_queues; + return 0; + } + return -EOPNOTSUPP; +} + +#ifdef VMXNET3_RSS +static int +vmxnet3_get_rss_indir(struct net_device *netdev, + struct ethtool_rxfh_indir *p) +{ + struct vmxnet3_adapter *adapter = netdev_priv(netdev); + struct UPT1_RSSConf *rssConf = adapter->rss_conf; + unsigned int n = min_t(unsigned int, p->size, rssConf->indTableSize); + + p->size = rssConf->indTableSize; + while (n--) + p->ring_index[n] = rssConf->indTable[n]; + return 0; + +} + +static int +vmxnet3_set_rss_indir(struct net_device *netdev, + const struct ethtool_rxfh_indir *p) +{ + unsigned int i; + struct vmxnet3_adapter *adapter = netdev_priv(netdev); + struct UPT1_RSSConf *rssConf = adapter->rss_conf; + + if (p->size != rssConf->indTableSize) + return -EINVAL; + for (i = 0; i < rssConf->indTableSize; i++) { + /* + * Return with error code if any of the queue indices + * is out of range + */ + if (p->ring_index[i] < 0 || + p->ring_index[i] >= adapter->num_rx_queues) + return -EINVAL; + } + + for (i = 0; i < rssConf->indTableSize; i++) + rssConf->indTable[i] = p->ring_index[i]; + + VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD, + VMXNET3_CMD_UPDATE_RSSIDT); + + return 0; + +} +#endif + static struct ethtool_ops vmxnet3_ethtool_ops = { .get_settings = vmxnet3_get_settings, .get_drvinfo = vmxnet3_get_drvinfo, @@ -558,6 +623,11 @@ static struct ethtool_ops vmxnet3_ethtool_ops = { .get_ethtool_stats = vmxnet3_get_ethtool_stats, .get_ringparam = vmxnet3_get_ringparam, .set_ringparam = vmxnet3_set_ringparam, + .get_rxnfc = vmxnet3_get_rxnfc, +#ifdef VMXNET3_RSS + .get_rxfh_indir = vmxnet3_get_rss_indir, + .set_rxfh_indir = vmxnet3_set_rss_indir, +#endif }; void vmxnet3_set_ethtool_ops(struct net_device *netdev) diff --git a/drivers/net/vmxnet3/vmxnet3_int.h b/drivers/net/vmxnet3/vmxnet3_int.h index edf228843afc..7fadeed37f03 100644 --- a/drivers/net/vmxnet3/vmxnet3_int.h +++ b/drivers/net/vmxnet3/vmxnet3_int.h @@ -68,11 +68,15 @@ /* * Version numbers */ -#define VMXNET3_DRIVER_VERSION_STRING "1.0.14.0-k" +#define VMXNET3_DRIVER_VERSION_STRING "1.0.16.0-k" /* a 32-bit int, each byte encode a verion number in VMXNET3_DRIVER_VERSION */ -#define VMXNET3_DRIVER_VERSION_NUM 0x01000E00 +#define VMXNET3_DRIVER_VERSION_NUM 0x01001000 +#if defined(CONFIG_PCI_MSI) + /* RSS only makes sense if MSI-X is supported. */ + #define VMXNET3_RSS +#endif /* * Capabilities @@ -218,16 +222,19 @@ struct vmxnet3_tx_ctx { }; struct vmxnet3_tx_queue { + char name[IFNAMSIZ+8]; /* To identify interrupt */ + struct vmxnet3_adapter *adapter; spinlock_t tx_lock; struct vmxnet3_cmd_ring tx_ring; - struct vmxnet3_tx_buf_info *buf_info; + struct vmxnet3_tx_buf_info *buf_info; struct vmxnet3_tx_data_ring data_ring; struct vmxnet3_comp_ring comp_ring; - struct Vmxnet3_TxQueueCtrl *shared; + struct Vmxnet3_TxQueueCtrl *shared; struct vmxnet3_tq_driver_stats stats; bool stopped; int num_stop; /* # of times the queue is * stopped */ + int qid; } __attribute__((__aligned__(SMP_CACHE_BYTES))); enum vmxnet3_rx_buf_type { @@ -259,6 +266,9 @@ struct vmxnet3_rq_driver_stats { }; struct vmxnet3_rx_queue { + char name[IFNAMSIZ + 8]; /* To identify interrupt */ + struct vmxnet3_adapter *adapter; + struct napi_struct napi; struct vmxnet3_cmd_ring rx_ring[2]; struct vmxnet3_comp_ring comp_ring; struct vmxnet3_rx_ctx rx_ctx; @@ -271,7 +281,16 @@ struct vmxnet3_rx_queue { struct vmxnet3_rq_driver_stats stats; } __attribute__((__aligned__(SMP_CACHE_BYTES))); -#define VMXNET3_LINUX_MAX_MSIX_VECT 1 +#define VMXNET3_DEVICE_MAX_TX_QUEUES 8 +#define VMXNET3_DEVICE_MAX_RX_QUEUES 8 /* Keep this value as a power of 2 */ + +/* Should be less than UPT1_RSS_MAX_IND_TABLE_SIZE */ +#define VMXNET3_RSS_IND_TABLE_SIZE (VMXNET3_DEVICE_MAX_RX_QUEUES * 4) + +#define VMXNET3_LINUX_MAX_MSIX_VECT (VMXNET3_DEVICE_MAX_TX_QUEUES + \ + VMXNET3_DEVICE_MAX_RX_QUEUES + 1) +#define VMXNET3_LINUX_MIN_MSIX_VECT 3 /* 1 for each : tx, rx and event */ + struct vmxnet3_intr { enum vmxnet3_intr_mask_mode mask_mode; @@ -279,27 +298,32 @@ struct vmxnet3_intr { u8 num_intrs; /* # of intr vectors */ u8 event_intr_idx; /* idx of the intr vector for event */ u8 mod_levels[VMXNET3_LINUX_MAX_MSIX_VECT]; /* moderation level */ + char event_msi_vector_name[IFNAMSIZ+11]; #ifdef CONFIG_PCI_MSI struct msix_entry msix_entries[VMXNET3_LINUX_MAX_MSIX_VECT]; #endif }; +/* Interrupt sharing schemes, share_intr */ +#define VMXNET3_INTR_BUDDYSHARE 0 /* Corresponding tx,rx queues share irq */ +#define VMXNET3_INTR_TXSHARE 1 /* All tx queues share one irq */ +#define VMXNET3_INTR_DONTSHARE 2 /* each queue has its own irq */ + + #define VMXNET3_STATE_BIT_RESETTING 0 #define VMXNET3_STATE_BIT_QUIESCED 1 struct vmxnet3_adapter { - struct vmxnet3_tx_queue tx_queue; - struct vmxnet3_rx_queue rx_queue; - struct napi_struct napi; - struct vlan_group *vlan_grp; - - struct vmxnet3_intr intr; - - struct Vmxnet3_DriverShared *shared; - struct Vmxnet3_PMConf *pm_conf; - struct Vmxnet3_TxQueueDesc *tqd_start; /* first tx queue desc */ - struct Vmxnet3_RxQueueDesc *rqd_start; /* first rx queue desc */ - struct net_device *netdev; - struct pci_dev *pdev; + 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; + struct vmxnet3_intr intr; + struct Vmxnet3_DriverShared *shared; + struct Vmxnet3_PMConf *pm_conf; + 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 */ u8 __iomem *hw_addr1; /* for BAR 1 */ @@ -308,6 +332,12 @@ struct vmxnet3_adapter { bool rxcsum; bool lro; bool jumbo_frame; +#ifdef VMXNET3_RSS + struct UPT1_RSSConf *rss_conf; + bool rss; +#endif + u32 num_rx_queues; + u32 num_tx_queues; /* rx buffer related */ unsigned skb_buf_size; @@ -327,6 +357,7 @@ struct vmxnet3_adapter { unsigned long state; /* VMXNET3_STATE_BIT_xxx */ int dev_number; + int share_intr; }; #define VMXNET3_WRITE_BAR0_REG(adapter, reg, val) \ @@ -366,12 +397,10 @@ void vmxnet3_reset_dev(struct vmxnet3_adapter *adapter); void -vmxnet3_tq_destroy(struct vmxnet3_tx_queue *tq, - struct vmxnet3_adapter *adapter); +vmxnet3_tq_destroy_all(struct vmxnet3_adapter *adapter); void -vmxnet3_rq_destroy(struct vmxnet3_rx_queue *rq, - struct vmxnet3_adapter *adapter); +vmxnet3_rq_destroy_all(struct vmxnet3_adapter *adapter); int vmxnet3_create_queues(struct vmxnet3_adapter *adapter, diff --git a/drivers/net/vxge/vxge-config.c b/drivers/net/vxge/vxge-config.c index 906a3ca3676b..a0241fe72d8b 100644 --- a/drivers/net/vxge/vxge-config.c +++ b/drivers/net/vxge/vxge-config.c @@ -19,19 +19,7 @@ #include "vxge-traffic.h" #include "vxge-config.h" - -static enum vxge_hw_status -__vxge_hw_fifo_create( - struct __vxge_hw_vpath_handle *vpath_handle, - struct vxge_hw_fifo_attr *attr); - -static enum vxge_hw_status -__vxge_hw_fifo_abort( - struct __vxge_hw_fifo *fifoh); - -static enum vxge_hw_status -__vxge_hw_fifo_reset( - struct __vxge_hw_fifo *ringh); +#include "vxge-main.h" static enum vxge_hw_status __vxge_hw_fifo_delete( @@ -71,53 +59,15 @@ __vxge_hw_blockpool_free(struct __vxge_hw_device *hldev, u32 size, struct vxge_hw_mempool_dma *dma_object); - -static struct __vxge_hw_channel* -__vxge_hw_channel_allocate(struct __vxge_hw_vpath_handle *vph, - enum __vxge_hw_channel_type type, u32 length, - u32 per_dtr_space, void *userdata); - static void __vxge_hw_channel_free( struct __vxge_hw_channel *channel); -static enum vxge_hw_status -__vxge_hw_channel_initialize( - struct __vxge_hw_channel *channel); - -static enum vxge_hw_status -__vxge_hw_channel_reset( - struct __vxge_hw_channel *channel); - static enum vxge_hw_status __vxge_hw_ring_delete(struct __vxge_hw_vpath_handle *vp); static enum vxge_hw_status -__vxge_hw_device_fifo_config_check(struct vxge_hw_fifo_config *fifo_config); - -static enum vxge_hw_status __vxge_hw_device_config_check(struct vxge_hw_device_config *new_config); -static void -__vxge_hw_device_id_get(struct __vxge_hw_device *hldev); - -static void -__vxge_hw_device_host_info_get(struct __vxge_hw_device *hldev); - -static enum vxge_hw_status -__vxge_hw_vpath_card_info_get( - u32 vp_id, - struct vxge_hw_vpath_reg __iomem *vpath_reg, - struct vxge_hw_device_hw_info *hw_info); - -static enum vxge_hw_status -__vxge_hw_device_initialize(struct __vxge_hw_device *hldev); - -static void -__vxge_hw_device_pci_e_init(struct __vxge_hw_device *hldev); - -static enum vxge_hw_status -__vxge_hw_device_reg_addr_get(struct __vxge_hw_device *hldev); - static enum vxge_hw_status __vxge_hw_device_register_poll( void __iomem *reg, @@ -138,9 +88,10 @@ __vxge_hw_pio_mem_write64(u64 val64, void __iomem *addr, static struct vxge_hw_mempool* __vxge_hw_mempool_create(struct __vxge_hw_device *devh, u32 memblock_size, - u32 item_size, u32 private_size, u32 items_initial, - u32 items_max, struct vxge_hw_mempool_cbs *mp_callback, - void *userdata); + u32 item_size, u32 private_size, u32 items_initial, + u32 items_max, struct vxge_hw_mempool_cbs *mp_callback, + void *userdata); + static void __vxge_hw_mempool_destroy(struct vxge_hw_mempool *mempool); static enum vxge_hw_status @@ -153,52 +104,353 @@ vxge_hw_vpath_stats_enable(struct __vxge_hw_vpath_handle *vpath_handle); static enum vxge_hw_status __vxge_hw_legacy_swapper_set(struct vxge_hw_legacy_reg __iomem *legacy_reg); -static u64 -__vxge_hw_vpath_pci_func_mode_get(u32 vp_id, - struct vxge_hw_vpath_reg __iomem *vpath_reg); - -static u32 -__vxge_hw_vpath_func_id_get(u32 vp_id, struct vxge_hw_vpmgmt_reg __iomem *vpmgmt_reg); +static void +__vxge_hw_vp_terminate(struct __vxge_hw_device *devh, u32 vp_id); static enum vxge_hw_status -__vxge_hw_vpath_addr_get(u32 vp_id, struct vxge_hw_vpath_reg __iomem *vpath_reg, - u8 (macaddr)[ETH_ALEN], u8 (macaddr_mask)[ETH_ALEN]); +__vxge_hw_vpath_xmac_tx_stats_get(struct __vxge_hw_virtualpath *vpath, + struct vxge_hw_xmac_vpath_tx_stats *vpath_tx_stats); static enum vxge_hw_status -__vxge_hw_vpath_reset_check(struct __vxge_hw_virtualpath *vpath); +__vxge_hw_vpath_xmac_rx_stats_get(struct __vxge_hw_virtualpath *vpath, + struct vxge_hw_xmac_vpath_rx_stats *vpath_rx_stats); +static void +vxge_hw_vpath_set_zero_rx_frm_len(struct vxge_hw_vpath_reg __iomem *vp_reg) +{ + u64 val64; -static enum vxge_hw_status -__vxge_hw_vpath_sw_reset(struct __vxge_hw_device *devh, u32 vp_id); + val64 = readq(&vp_reg->rxmac_vcfg0); + val64 &= ~VXGE_HW_RXMAC_VCFG0_RTS_MAX_FRM_LEN(0x3fff); + writeq(val64, &vp_reg->rxmac_vcfg0); + val64 = readq(&vp_reg->rxmac_vcfg0); -static enum vxge_hw_status -__vxge_hw_vpath_fw_ver_get(u32 vp_id, struct vxge_hw_vpath_reg __iomem *vpath_reg, - struct vxge_hw_device_hw_info *hw_info); + return; +} -static enum vxge_hw_status -__vxge_hw_vpath_mac_configure(struct __vxge_hw_device *devh, u32 vp_id); +/* + * vxge_hw_vpath_wait_receive_idle - Wait for Rx to become idle + */ +int vxge_hw_vpath_wait_receive_idle(struct __vxge_hw_device *hldev, u32 vp_id) +{ + struct vxge_hw_vpath_reg __iomem *vp_reg; + struct __vxge_hw_virtualpath *vpath; + u64 val64, rxd_count, rxd_spat; + int count = 0, total_count = 0; -static void -__vxge_hw_vp_terminate(struct __vxge_hw_device *devh, u32 vp_id); + vpath = &hldev->virtual_paths[vp_id]; + vp_reg = vpath->vp_reg; -static enum vxge_hw_status -__vxge_hw_vpath_stats_access(struct __vxge_hw_virtualpath *vpath, - u32 operation, u32 offset, u64 *stat); + vxge_hw_vpath_set_zero_rx_frm_len(vp_reg); -static enum vxge_hw_status -__vxge_hw_vpath_xmac_tx_stats_get(struct __vxge_hw_virtualpath *vpath, - struct vxge_hw_xmac_vpath_tx_stats *vpath_tx_stats); + /* Check that the ring controller for this vpath has enough free RxDs + * to send frames to the host. This is done by reading the + * PRC_RXD_DOORBELL_VPn register and comparing the read value to the + * RXD_SPAT value for the vpath. + */ + val64 = readq(&vp_reg->prc_cfg6); + rxd_spat = VXGE_HW_PRC_CFG6_GET_RXD_SPAT(val64) + 1; + /* Use a factor of 2 when comparing rxd_count against rxd_spat for some + * leg room. + */ + rxd_spat *= 2; + + do { + mdelay(1); + + rxd_count = readq(&vp_reg->prc_rxd_doorbell); + + /* Check that the ring controller for this vpath does + * not have any frame in its pipeline. + */ + val64 = readq(&vp_reg->frm_in_progress_cnt); + if ((rxd_count <= rxd_spat) || (val64 > 0)) + count = 0; + else + count++; + total_count++; + } while ((count < VXGE_HW_MIN_SUCCESSIVE_IDLE_COUNT) && + (total_count < VXGE_HW_MAX_POLLING_COUNT)); + + if (total_count >= VXGE_HW_MAX_POLLING_COUNT) + printk(KERN_ALERT "%s: Still Receiving traffic. Abort wait\n", + __func__); + + return total_count; +} + +/* vxge_hw_device_wait_receive_idle - This function waits until all frames + * stored in the frame buffer for each vpath assigned to the given + * function (hldev) have been sent to the host. + */ +void vxge_hw_device_wait_receive_idle(struct __vxge_hw_device *hldev) +{ + int i, total_count = 0; + + for (i = 0; i < VXGE_HW_MAX_VIRTUAL_PATHS; i++) { + if (!(hldev->vpaths_deployed & vxge_mBIT(i))) + continue; + + total_count += vxge_hw_vpath_wait_receive_idle(hldev, i); + if (total_count >= VXGE_HW_MAX_POLLING_COUNT) + break; + } +} static enum vxge_hw_status -__vxge_hw_vpath_xmac_rx_stats_get(struct __vxge_hw_virtualpath *vpath, - struct vxge_hw_xmac_vpath_rx_stats *vpath_rx_stats); +vxge_hw_vpath_fw_api(struct __vxge_hw_virtualpath *vpath, u32 action, + u32 fw_memo, u32 offset, u64 *data0, u64 *data1, + u64 *steer_ctrl) +{ + struct vxge_hw_vpath_reg __iomem *vp_reg; + enum vxge_hw_status status; + u64 val64; + u32 retry = 0, max_retry = 100; + + vp_reg = vpath->vp_reg; + + if (vpath->vp_open) { + max_retry = 3; + spin_lock(&vpath->lock); + } + + writeq(*data0, &vp_reg->rts_access_steer_data0); + writeq(*data1, &vp_reg->rts_access_steer_data1); + wmb(); + + val64 = VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION(action) | + VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL(fw_memo) | + VXGE_HW_RTS_ACCESS_STEER_CTRL_OFFSET(offset) | + VXGE_HW_RTS_ACCESS_STEER_CTRL_STROBE | + *steer_ctrl; + + status = __vxge_hw_pio_mem_write64(val64, + &vp_reg->rts_access_steer_ctrl, + VXGE_HW_RTS_ACCESS_STEER_CTRL_STROBE, + VXGE_HW_DEF_DEVICE_POLL_MILLIS); + + /* The __vxge_hw_device_register_poll can udelay for a significant + * amount of time, blocking other proccess from the CPU. If it delays + * for ~5secs, a NMI error can occur. A way around this is to give up + * the processor via msleep, but this is not allowed is under lock. + * So, only allow it to sleep for ~4secs if open. Otherwise, delay for + * 1sec and sleep for 10ms until the firmware operation has completed + * or timed-out. + */ + while ((status != VXGE_HW_OK) && retry++ < max_retry) { + if (!vpath->vp_open) + msleep(20); + status = __vxge_hw_device_register_poll( + &vp_reg->rts_access_steer_ctrl, + VXGE_HW_RTS_ACCESS_STEER_CTRL_STROBE, + VXGE_HW_DEF_DEVICE_POLL_MILLIS); + } + + if (status != VXGE_HW_OK) + goto out; + + val64 = readq(&vp_reg->rts_access_steer_ctrl); + if (val64 & VXGE_HW_RTS_ACCESS_STEER_CTRL_RMACJ_STATUS) { + *data0 = readq(&vp_reg->rts_access_steer_data0); + *data1 = readq(&vp_reg->rts_access_steer_data1); + *steer_ctrl = val64; + } else + status = VXGE_HW_FAIL; + +out: + if (vpath->vp_open) + spin_unlock(&vpath->lock); + return status; +} + +enum vxge_hw_status +vxge_hw_upgrade_read_version(struct __vxge_hw_device *hldev, u32 *major, + u32 *minor, u32 *build) +{ + u64 data0 = 0, data1 = 0, steer_ctrl = 0; + struct __vxge_hw_virtualpath *vpath; + enum vxge_hw_status status; + + vpath = &hldev->virtual_paths[hldev->first_vp_id]; + + status = vxge_hw_vpath_fw_api(vpath, + VXGE_HW_FW_UPGRADE_ACTION, + VXGE_HW_FW_UPGRADE_MEMO, + VXGE_HW_FW_UPGRADE_OFFSET_READ, + &data0, &data1, &steer_ctrl); + if (status != VXGE_HW_OK) + return status; + + *major = VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_FW_VER_MAJOR(data0); + *minor = VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_FW_VER_MINOR(data0); + *build = VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_FW_VER_BUILD(data0); + + return status; +} + +enum vxge_hw_status vxge_hw_flash_fw(struct __vxge_hw_device *hldev) +{ + u64 data0 = 0, data1 = 0, steer_ctrl = 0; + struct __vxge_hw_virtualpath *vpath; + enum vxge_hw_status status; + u32 ret; + + vpath = &hldev->virtual_paths[hldev->first_vp_id]; + + status = vxge_hw_vpath_fw_api(vpath, + VXGE_HW_FW_UPGRADE_ACTION, + VXGE_HW_FW_UPGRADE_MEMO, + VXGE_HW_FW_UPGRADE_OFFSET_COMMIT, + &data0, &data1, &steer_ctrl); + if (status != VXGE_HW_OK) { + vxge_debug_init(VXGE_ERR, "%s: FW upgrade failed", __func__); + goto exit; + } + + ret = VXGE_HW_RTS_ACCESS_STEER_CTRL_GET_ACTION(steer_ctrl) & 0x7F; + if (ret != 1) { + vxge_debug_init(VXGE_ERR, "%s: FW commit failed with error %d", + __func__, ret); + status = VXGE_HW_FAIL; + } + +exit: + return status; +} + +enum vxge_hw_status +vxge_update_fw_image(struct __vxge_hw_device *hldev, const u8 *fwdata, int size) +{ + u64 data0 = 0, data1 = 0, steer_ctrl = 0; + struct __vxge_hw_virtualpath *vpath; + enum vxge_hw_status status; + int ret_code, sec_code; + + vpath = &hldev->virtual_paths[hldev->first_vp_id]; + + /* send upgrade start command */ + status = vxge_hw_vpath_fw_api(vpath, + VXGE_HW_FW_UPGRADE_ACTION, + VXGE_HW_FW_UPGRADE_MEMO, + VXGE_HW_FW_UPGRADE_OFFSET_START, + &data0, &data1, &steer_ctrl); + if (status != VXGE_HW_OK) { + vxge_debug_init(VXGE_ERR, " %s: Upgrade start cmd failed", + __func__); + return status; + } + + /* Transfer fw image to adapter 16 bytes at a time */ + for (; size > 0; size -= VXGE_HW_FW_UPGRADE_BLK_SIZE) { + steer_ctrl = 0; + + /* The next 128bits of fwdata to be loaded onto the adapter */ + data0 = *((u64 *)fwdata); + data1 = *((u64 *)fwdata + 1); + + status = vxge_hw_vpath_fw_api(vpath, + VXGE_HW_FW_UPGRADE_ACTION, + VXGE_HW_FW_UPGRADE_MEMO, + VXGE_HW_FW_UPGRADE_OFFSET_SEND, + &data0, &data1, &steer_ctrl); + if (status != VXGE_HW_OK) { + vxge_debug_init(VXGE_ERR, "%s: Upgrade send failed", + __func__); + goto out; + } + + ret_code = VXGE_HW_UPGRADE_GET_RET_ERR_CODE(data0); + switch (ret_code) { + case VXGE_HW_FW_UPGRADE_OK: + /* All OK, send next 16 bytes. */ + break; + case VXGE_FW_UPGRADE_BYTES2SKIP: + /* skip bytes in the stream */ + fwdata += (data0 >> 8) & 0xFFFFFFFF; + break; + case VXGE_HW_FW_UPGRADE_DONE: + goto out; + case VXGE_HW_FW_UPGRADE_ERR: + sec_code = VXGE_HW_UPGRADE_GET_SEC_ERR_CODE(data0); + switch (sec_code) { + case VXGE_HW_FW_UPGRADE_ERR_CORRUPT_DATA_1: + case VXGE_HW_FW_UPGRADE_ERR_CORRUPT_DATA_7: + printk(KERN_ERR + "corrupted data from .ncf file\n"); + break; + case VXGE_HW_FW_UPGRADE_ERR_INV_NCF_FILE_3: + case VXGE_HW_FW_UPGRADE_ERR_INV_NCF_FILE_4: + case VXGE_HW_FW_UPGRADE_ERR_INV_NCF_FILE_5: + case VXGE_HW_FW_UPGRADE_ERR_INV_NCF_FILE_6: + case VXGE_HW_FW_UPGRADE_ERR_INV_NCF_FILE_8: + printk(KERN_ERR "invalid .ncf file\n"); + break; + case VXGE_HW_FW_UPGRADE_ERR_BUFFER_OVERFLOW: + printk(KERN_ERR "buffer overflow\n"); + break; + case VXGE_HW_FW_UPGRADE_ERR_FAILED_TO_FLASH: + printk(KERN_ERR "failed to flash the image\n"); + break; + case VXGE_HW_FW_UPGRADE_ERR_GENERIC_ERROR_UNKNOWN: + printk(KERN_ERR + "generic error. Unknown error type\n"); + break; + default: + printk(KERN_ERR "Unknown error of type %d\n", + sec_code); + break; + } + status = VXGE_HW_FAIL; + goto out; + default: + printk(KERN_ERR "Unknown FW error: %d\n", ret_code); + status = VXGE_HW_FAIL; + goto out; + } + /* point to next 16 bytes */ + fwdata += VXGE_HW_FW_UPGRADE_BLK_SIZE; + } +out: + return status; +} + +enum vxge_hw_status +vxge_hw_vpath_eprom_img_ver_get(struct __vxge_hw_device *hldev, + struct eprom_image *img) +{ + u64 data0 = 0, data1 = 0, steer_ctrl = 0; + struct __vxge_hw_virtualpath *vpath; + enum vxge_hw_status status; + int i; + + vpath = &hldev->virtual_paths[hldev->first_vp_id]; + + for (i = 0; i < VXGE_HW_MAX_ROM_IMAGES; i++) { + data0 = VXGE_HW_RTS_ACCESS_STEER_ROM_IMAGE_INDEX(i); + data1 = steer_ctrl = 0; + + status = vxge_hw_vpath_fw_api(vpath, + VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_FW_MEMO, + VXGE_HW_FW_API_GET_EPROM_REV, + 0, &data0, &data1, &steer_ctrl); + if (status != VXGE_HW_OK) + break; + + img[i].is_valid = VXGE_HW_GET_EPROM_IMAGE_VALID(data0); + img[i].index = VXGE_HW_GET_EPROM_IMAGE_INDEX(data0); + img[i].type = VXGE_HW_GET_EPROM_IMAGE_TYPE(data0); + img[i].version = VXGE_HW_GET_EPROM_IMAGE_REV(data0); + } + + return status; +} /* * __vxge_hw_channel_allocate - Allocate memory for channel * This function allocates required memory for the channel and various arrays * in the channel */ -struct __vxge_hw_channel* +static struct __vxge_hw_channel * __vxge_hw_channel_allocate(struct __vxge_hw_vpath_handle *vph, enum __vxge_hw_channel_type type, u32 length, u32 per_dtr_space, void *userdata) @@ -269,7 +521,7 @@ exit0: * This function deallocates memory from the channel and various arrays * in the channel */ -void __vxge_hw_channel_free(struct __vxge_hw_channel *channel) +static void __vxge_hw_channel_free(struct __vxge_hw_channel *channel) { kfree(channel->work_arr); kfree(channel->free_arr); @@ -283,7 +535,7 @@ void __vxge_hw_channel_free(struct __vxge_hw_channel *channel) * This function initializes a channel by properly setting the * various references */ -enum vxge_hw_status +static enum vxge_hw_status __vxge_hw_channel_initialize(struct __vxge_hw_channel *channel) { u32 i; @@ -318,7 +570,7 @@ __vxge_hw_channel_initialize(struct __vxge_hw_channel *channel) * __vxge_hw_channel_reset - Resets a channel * This function resets a channel by properly setting the various references */ -enum vxge_hw_status +static enum vxge_hw_status __vxge_hw_channel_reset(struct __vxge_hw_channel *channel) { u32 i; @@ -345,8 +597,7 @@ __vxge_hw_channel_reset(struct __vxge_hw_channel *channel) * Initialize certain PCI/PCI-X configuration registers * with recommended values. Save config space for future hw resets. */ -void -__vxge_hw_device_pci_e_init(struct __vxge_hw_device *hldev) +static void __vxge_hw_device_pci_e_init(struct __vxge_hw_device *hldev) { u16 cmd = 0; @@ -390,7 +641,7 @@ __vxge_hw_device_register_poll(void __iomem *reg, u64 mask, u32 max_millis) return ret; } - /* __vxge_hw_device_vpath_reset_in_prog_check - Check if vpath reset +/* __vxge_hw_device_vpath_reset_in_prog_check - Check if vpath reset * in progress * This routine checks the vpath reset in progress register is turned zero */ @@ -435,7 +686,7 @@ exit: * register location pointers in the device object. It waits until the ric is * completed initializing registers. */ -enum vxge_hw_status +static enum vxge_hw_status __vxge_hw_device_reg_addr_get(struct __vxge_hw_device *hldev) { u64 val64; @@ -496,26 +747,6 @@ exit: } /* - * __vxge_hw_device_id_get - * This routine returns sets the device id and revision numbers into the device - * structure - */ -void __vxge_hw_device_id_get(struct __vxge_hw_device *hldev) -{ - u64 val64; - - val64 = readq(&hldev->common_reg->titan_asic_id); - hldev->device_id = - (u16)VXGE_HW_TITAN_ASIC_ID_GET_INITIAL_DEVICE_ID(val64); - - hldev->major_revision = - (u8)VXGE_HW_TITAN_ASIC_ID_GET_INITIAL_MAJOR_REVISION(val64); - - hldev->minor_revision = - (u8)VXGE_HW_TITAN_ASIC_ID_GET_INITIAL_MINOR_REVISION(val64); -} - -/* * __vxge_hw_device_access_rights_get: Get Access Rights of the driver * This routine returns the Access Rights of the driver */ @@ -568,10 +799,25 @@ __vxge_hw_device_is_privilaged(u32 host_type, u32 func_id) } /* + * __vxge_hw_vpath_func_id_get - Get the function id of the vpath. + * Returns the function number of the vpath. + */ +static u32 +__vxge_hw_vpath_func_id_get(struct vxge_hw_vpmgmt_reg __iomem *vpmgmt_reg) +{ + u64 val64; + + val64 = readq(&vpmgmt_reg->vpath_to_func_map_cfg1); + + return + (u32)VXGE_HW_VPATH_TO_FUNC_MAP_CFG1_GET_VPATH_TO_FUNC_MAP_CFG1(val64); +} + +/* * __vxge_hw_device_host_info_get * This routine returns the host type assignments */ -void __vxge_hw_device_host_info_get(struct __vxge_hw_device *hldev) +static void __vxge_hw_device_host_info_get(struct __vxge_hw_device *hldev) { u64 val64; u32 i; @@ -584,16 +830,18 @@ void __vxge_hw_device_host_info_get(struct __vxge_hw_device *hldev) hldev->vpath_assignments = readq(&hldev->common_reg->vpath_assignments); for (i = 0; i < VXGE_HW_MAX_VIRTUAL_PATHS; i++) { - if (!(hldev->vpath_assignments & vxge_mBIT(i))) continue; hldev->func_id = - __vxge_hw_vpath_func_id_get(i, hldev->vpmgmt_reg[i]); + __vxge_hw_vpath_func_id_get(hldev->vpmgmt_reg[i]); hldev->access_rights = __vxge_hw_device_access_rights_get( hldev->host_type, hldev->func_id); + hldev->virtual_paths[i].vp_open = VXGE_HW_VP_NOT_OPEN; + hldev->virtual_paths[i].vp_reg = hldev->vpath_reg[i]; + hldev->first_vp_id = i; break; } @@ -634,7 +882,8 @@ __vxge_hw_verify_pci_e_info(struct __vxge_hw_device *hldev) * __vxge_hw_device_initialize * Initialize Titan-V hardware. */ -enum vxge_hw_status __vxge_hw_device_initialize(struct __vxge_hw_device *hldev) +static enum vxge_hw_status +__vxge_hw_device_initialize(struct __vxge_hw_device *hldev) { enum vxge_hw_status status = VXGE_HW_OK; @@ -650,6 +899,196 @@ exit: return status; } +/* + * __vxge_hw_vpath_fw_ver_get - Get the fw version + * Returns FW Version + */ +static enum vxge_hw_status +__vxge_hw_vpath_fw_ver_get(struct __vxge_hw_virtualpath *vpath, + struct vxge_hw_device_hw_info *hw_info) +{ + struct vxge_hw_device_version *fw_version = &hw_info->fw_version; + struct vxge_hw_device_date *fw_date = &hw_info->fw_date; + struct vxge_hw_device_version *flash_version = &hw_info->flash_version; + struct vxge_hw_device_date *flash_date = &hw_info->flash_date; + u64 data0, data1 = 0, steer_ctrl = 0; + enum vxge_hw_status status; + + status = vxge_hw_vpath_fw_api(vpath, + VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION_READ_ENTRY, + VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_FW_MEMO, + 0, &data0, &data1, &steer_ctrl); + if (status != VXGE_HW_OK) + goto exit; + + fw_date->day = + (u32) VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_FW_VER_DAY(data0); + fw_date->month = + (u32) VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_FW_VER_MONTH(data0); + fw_date->year = + (u32) VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_FW_VER_YEAR(data0); + + snprintf(fw_date->date, VXGE_HW_FW_STRLEN, "%2.2d/%2.2d/%4.4d", + fw_date->month, fw_date->day, fw_date->year); + + fw_version->major = + (u32) VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_FW_VER_MAJOR(data0); + fw_version->minor = + (u32) VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_FW_VER_MINOR(data0); + fw_version->build = + (u32) VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_FW_VER_BUILD(data0); + + snprintf(fw_version->version, VXGE_HW_FW_STRLEN, "%d.%d.%d", + fw_version->major, fw_version->minor, fw_version->build); + + flash_date->day = + (u32) VXGE_HW_RTS_ACCESS_STEER_DATA1_GET_FLASH_VER_DAY(data1); + flash_date->month = + (u32) VXGE_HW_RTS_ACCESS_STEER_DATA1_GET_FLASH_VER_MONTH(data1); + flash_date->year = + (u32) VXGE_HW_RTS_ACCESS_STEER_DATA1_GET_FLASH_VER_YEAR(data1); + + snprintf(flash_date->date, VXGE_HW_FW_STRLEN, "%2.2d/%2.2d/%4.4d", + flash_date->month, flash_date->day, flash_date->year); + + flash_version->major = + (u32) VXGE_HW_RTS_ACCESS_STEER_DATA1_GET_FLASH_VER_MAJOR(data1); + flash_version->minor = + (u32) VXGE_HW_RTS_ACCESS_STEER_DATA1_GET_FLASH_VER_MINOR(data1); + flash_version->build = + (u32) VXGE_HW_RTS_ACCESS_STEER_DATA1_GET_FLASH_VER_BUILD(data1); + + snprintf(flash_version->version, VXGE_HW_FW_STRLEN, "%d.%d.%d", + flash_version->major, flash_version->minor, + flash_version->build); + +exit: + return status; +} + +/* + * __vxge_hw_vpath_card_info_get - Get the serial numbers, + * part number and product description. + */ +static enum vxge_hw_status +__vxge_hw_vpath_card_info_get(struct __vxge_hw_virtualpath *vpath, + struct vxge_hw_device_hw_info *hw_info) +{ + enum vxge_hw_status status; + u64 data0, data1 = 0, steer_ctrl = 0; + u8 *serial_number = hw_info->serial_number; + u8 *part_number = hw_info->part_number; + u8 *product_desc = hw_info->product_desc; + u32 i, j = 0; + + data0 = VXGE_HW_RTS_ACCESS_STEER_DATA0_MEMO_ITEM_SERIAL_NUMBER; + + status = vxge_hw_vpath_fw_api(vpath, + VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION_READ_MEMO_ENTRY, + VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_FW_MEMO, + 0, &data0, &data1, &steer_ctrl); + if (status != VXGE_HW_OK) + return status; + + ((u64 *)serial_number)[0] = be64_to_cpu(data0); + ((u64 *)serial_number)[1] = be64_to_cpu(data1); + + data0 = VXGE_HW_RTS_ACCESS_STEER_DATA0_MEMO_ITEM_PART_NUMBER; + data1 = steer_ctrl = 0; + + status = vxge_hw_vpath_fw_api(vpath, + VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION_READ_MEMO_ENTRY, + VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_FW_MEMO, + 0, &data0, &data1, &steer_ctrl); + if (status != VXGE_HW_OK) + return status; + + ((u64 *)part_number)[0] = be64_to_cpu(data0); + ((u64 *)part_number)[1] = be64_to_cpu(data1); + + for (i = VXGE_HW_RTS_ACCESS_STEER_DATA0_MEMO_ITEM_DESC_0; + i <= VXGE_HW_RTS_ACCESS_STEER_DATA0_MEMO_ITEM_DESC_3; i++) { + data0 = i; + data1 = steer_ctrl = 0; + + status = vxge_hw_vpath_fw_api(vpath, + VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION_READ_MEMO_ENTRY, + VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_FW_MEMO, + 0, &data0, &data1, &steer_ctrl); + if (status != VXGE_HW_OK) + return status; + + ((u64 *)product_desc)[j++] = be64_to_cpu(data0); + ((u64 *)product_desc)[j++] = be64_to_cpu(data1); + } + + return status; +} + +/* + * __vxge_hw_vpath_pci_func_mode_get - Get the pci mode + * Returns pci function mode + */ +static enum vxge_hw_status +__vxge_hw_vpath_pci_func_mode_get(struct __vxge_hw_virtualpath *vpath, + struct vxge_hw_device_hw_info *hw_info) +{ + u64 data0, data1 = 0, steer_ctrl = 0; + enum vxge_hw_status status; + + data0 = 0; + + status = vxge_hw_vpath_fw_api(vpath, + VXGE_HW_FW_API_GET_FUNC_MODE, + VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_FW_MEMO, + 0, &data0, &data1, &steer_ctrl); + if (status != VXGE_HW_OK) + return status; + + hw_info->function_mode = VXGE_HW_GET_FUNC_MODE_VAL(data0); + return status; +} + +/* + * __vxge_hw_vpath_addr_get - Get the hw address entry for this vpath + * from MAC address table. + */ +static enum vxge_hw_status +__vxge_hw_vpath_addr_get(struct __vxge_hw_virtualpath *vpath, + u8 *macaddr, u8 *macaddr_mask) +{ + u64 action = VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION_LIST_FIRST_ENTRY, + data0 = 0, data1 = 0, steer_ctrl = 0; + enum vxge_hw_status status; + int i; + + do { + status = vxge_hw_vpath_fw_api(vpath, action, + VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_DA, + 0, &data0, &data1, &steer_ctrl); + if (status != VXGE_HW_OK) + goto exit; + + data0 = VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_DA_MAC_ADDR(data0); + data1 = VXGE_HW_RTS_ACCESS_STEER_DATA1_GET_DA_MAC_ADDR_MASK( + data1); + + for (i = ETH_ALEN; i > 0; i--) { + macaddr[i - 1] = (u8) (data0 & 0xFF); + data0 >>= 8; + + macaddr_mask[i - 1] = (u8) (data1 & 0xFF); + data1 >>= 8; + } + + action = VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION_LIST_NEXT_ENTRY; + data0 = 0, data1 = 0, steer_ctrl = 0; + + } while (!is_valid_ether_addr(macaddr)); +exit: + return status; +} + /** * vxge_hw_device_hw_info_get - Get the hw information * Returns the vpath mask that has the bits set for each vpath allocated @@ -665,9 +1104,9 @@ vxge_hw_device_hw_info_get(void __iomem *bar0, struct vxge_hw_toc_reg __iomem *toc; struct vxge_hw_mrpcim_reg __iomem *mrpcim_reg; struct vxge_hw_common_reg __iomem *common_reg; - struct vxge_hw_vpath_reg __iomem *vpath_reg; struct vxge_hw_vpmgmt_reg __iomem *vpmgmt_reg; enum vxge_hw_status status; + struct __vxge_hw_virtualpath vpath; memset(hw_info, 0, sizeof(struct vxge_hw_device_hw_info)); @@ -702,7 +1141,7 @@ vxge_hw_device_hw_info_get(void __iomem *bar0, vpmgmt_reg = (struct vxge_hw_vpmgmt_reg __iomem *) (bar0 + val64); - hw_info->func_id = __vxge_hw_vpath_func_id_get(i, vpmgmt_reg); + hw_info->func_id = __vxge_hw_vpath_func_id_get(vpmgmt_reg); if (__vxge_hw_device_access_rights_get(hw_info->host_type, hw_info->func_id) & VXGE_HW_DEVICE_ACCESS_RIGHT_MRPCIM) { @@ -718,16 +1157,19 @@ vxge_hw_device_hw_info_get(void __iomem *bar0, val64 = readq(&toc->toc_vpath_pointer[i]); - vpath_reg = (struct vxge_hw_vpath_reg __iomem *)(bar0 + val64); + vpath.vp_reg = (struct vxge_hw_vpath_reg __iomem *) + (bar0 + val64); + vpath.vp_open = 0; - hw_info->function_mode = - __vxge_hw_vpath_pci_func_mode_get(i, vpath_reg); + status = __vxge_hw_vpath_pci_func_mode_get(&vpath, hw_info); + if (status != VXGE_HW_OK) + goto exit; - status = __vxge_hw_vpath_fw_ver_get(i, vpath_reg, hw_info); + status = __vxge_hw_vpath_fw_ver_get(&vpath, hw_info); if (status != VXGE_HW_OK) goto exit; - status = __vxge_hw_vpath_card_info_get(i, vpath_reg, hw_info); + status = __vxge_hw_vpath_card_info_get(&vpath, hw_info); if (status != VXGE_HW_OK) goto exit; @@ -735,14 +1177,15 @@ vxge_hw_device_hw_info_get(void __iomem *bar0, } for (i = 0; i < VXGE_HW_MAX_VIRTUAL_PATHS; i++) { - if (!((hw_info->vpath_mask) & vxge_mBIT(i))) continue; val64 = readq(&toc->toc_vpath_pointer[i]); - vpath_reg = (struct vxge_hw_vpath_reg __iomem *)(bar0 + val64); + vpath.vp_reg = (struct vxge_hw_vpath_reg __iomem *) + (bar0 + val64); + vpath.vp_open = 0; - status = __vxge_hw_vpath_addr_get(i, vpath_reg, + status = __vxge_hw_vpath_addr_get(&vpath, hw_info->mac_addrs[i], hw_info->mac_addr_masks[i]); if (status != VXGE_HW_OK) @@ -776,14 +1219,12 @@ vxge_hw_device_initialize( if (status != VXGE_HW_OK) goto exit; - hldev = (struct __vxge_hw_device *) - vmalloc(sizeof(struct __vxge_hw_device)); + hldev = vzalloc(sizeof(struct __vxge_hw_device)); if (hldev == NULL) { status = VXGE_HW_ERR_OUT_OF_MEMORY; goto exit; } - memset(hldev, 0, sizeof(struct __vxge_hw_device)); hldev->magic = VXGE_HW_DEVICE_MAGIC; vxge_hw_device_debug_set(hldev, VXGE_ERR, VXGE_COMPONENT_ALL); @@ -806,7 +1247,6 @@ vxge_hw_device_initialize( vfree(hldev); goto exit; } - __vxge_hw_device_id_get(hldev); __vxge_hw_device_host_info_get(hldev); @@ -814,7 +1254,6 @@ vxge_hw_device_initialize( nblocks++; for (i = 0; i < VXGE_HW_MAX_VIRTUAL_PATHS; i++) { - if (!(hldev->vpath_assignments & vxge_mBIT(i))) continue; @@ -839,7 +1278,6 @@ vxge_hw_device_initialize( } status = __vxge_hw_device_initialize(hldev); - if (status != VXGE_HW_OK) { vxge_hw_device_terminate(hldev); goto exit; @@ -876,7 +1314,6 @@ vxge_hw_device_stats_get(struct __vxge_hw_device *hldev, enum vxge_hw_status status = VXGE_HW_OK; for (i = 0; i < VXGE_HW_MAX_VIRTUAL_PATHS; i++) { - if (!(hldev->vpaths_deployed & vxge_mBIT(i)) || (hldev->virtual_paths[i].vp_open == VXGE_HW_VP_NOT_OPEN)) @@ -1165,7 +1602,6 @@ exit: * It can be used to set or reset Pause frame generation or reception * support of the NIC. */ - enum vxge_hw_status vxge_hw_device_setpause_data(struct __vxge_hw_device *hldev, u32 port, u32 tx, u32 rx) { @@ -1409,7 +1845,6 @@ exit: /* * __vxge_hw_ring_create - Create a Ring * This function creates Ring and initializes it. - * */ static enum vxge_hw_status __vxge_hw_ring_create(struct __vxge_hw_vpath_handle *vp, @@ -1627,15 +2062,12 @@ __vxge_hw_mempool_grow(struct vxge_hw_mempool *mempool, u32 num_allocate, * allocate new memblock and its private part at once. * This helps to minimize memory usage a lot. */ mempool->memblocks_priv_arr[i] = - vmalloc(mempool->items_priv_size * n_items); + vzalloc(mempool->items_priv_size * n_items); if (mempool->memblocks_priv_arr[i] == NULL) { status = VXGE_HW_ERR_OUT_OF_MEMORY; goto exit; } - memset(mempool->memblocks_priv_arr[i], 0, - mempool->items_priv_size * n_items); - /* allocate DMA-capable memblock */ mempool->memblocks_arr[i] = __vxge_hw_blockpool_malloc(mempool->devh, @@ -1707,13 +2139,11 @@ __vxge_hw_mempool_create( goto exit; } - mempool = (struct vxge_hw_mempool *) - vmalloc(sizeof(struct vxge_hw_mempool)); + mempool = vzalloc(sizeof(struct vxge_hw_mempool)); if (mempool == NULL) { status = VXGE_HW_ERR_OUT_OF_MEMORY; goto exit; } - memset(mempool, 0, sizeof(struct vxge_hw_mempool)); mempool->devh = devh; mempool->memblock_size = memblock_size; @@ -1733,31 +2163,27 @@ __vxge_hw_mempool_create( /* allocate array of memblocks */ mempool->memblocks_arr = - (void **) vmalloc(sizeof(void *) * mempool->memblocks_max); + vzalloc(sizeof(void *) * mempool->memblocks_max); if (mempool->memblocks_arr == NULL) { __vxge_hw_mempool_destroy(mempool); status = VXGE_HW_ERR_OUT_OF_MEMORY; mempool = NULL; goto exit; } - memset(mempool->memblocks_arr, 0, - sizeof(void *) * mempool->memblocks_max); /* allocate array of private parts of items per memblocks */ mempool->memblocks_priv_arr = - (void **) vmalloc(sizeof(void *) * mempool->memblocks_max); + vzalloc(sizeof(void *) * mempool->memblocks_max); if (mempool->memblocks_priv_arr == NULL) { __vxge_hw_mempool_destroy(mempool); status = VXGE_HW_ERR_OUT_OF_MEMORY; mempool = NULL; goto exit; } - memset(mempool->memblocks_priv_arr, 0, - sizeof(void *) * mempool->memblocks_max); /* allocate array of memblocks DMA objects */ - mempool->memblocks_dma_arr = (struct vxge_hw_mempool_dma *) - vmalloc(sizeof(struct vxge_hw_mempool_dma) * + mempool->memblocks_dma_arr = + vzalloc(sizeof(struct vxge_hw_mempool_dma) * mempool->memblocks_max); if (mempool->memblocks_dma_arr == NULL) { @@ -1766,20 +2192,15 @@ __vxge_hw_mempool_create( mempool = NULL; goto exit; } - memset(mempool->memblocks_dma_arr, 0, - sizeof(struct vxge_hw_mempool_dma) * - mempool->memblocks_max); /* allocate hash array of items */ - mempool->items_arr = - (void **) vmalloc(sizeof(void *) * mempool->items_max); + mempool->items_arr = vzalloc(sizeof(void *) * mempool->items_max); if (mempool->items_arr == NULL) { __vxge_hw_mempool_destroy(mempool); status = VXGE_HW_ERR_OUT_OF_MEMORY; mempool = NULL; goto exit; } - memset(mempool->items_arr, 0, sizeof(void *) * mempool->items_max); /* calculate initial number of memblocks */ memblocks_to_allocate = (mempool->items_initial + @@ -1845,7 +2266,7 @@ static void __vxge_hw_mempool_destroy(struct vxge_hw_mempool *mempool) * __vxge_hw_device_fifo_config_check - Check fifo configuration. * Check the fifo configuration */ -enum vxge_hw_status +static enum vxge_hw_status __vxge_hw_device_fifo_config_check(struct vxge_hw_fifo_config *fifo_config) { if ((fifo_config->fifo_blocks < VXGE_HW_MIN_FIFO_BLOCKS) || @@ -1893,7 +2314,7 @@ __vxge_hw_device_vpath_config_check(struct vxge_hw_vp_config *vp_config) * __vxge_hw_device_config_check - Check device configuration. * Check the device configuration */ -enum vxge_hw_status +static enum vxge_hw_status __vxge_hw_device_config_check(struct vxge_hw_device_config *new_config) { u32 i; @@ -2453,7 +2874,7 @@ __vxge_hw_fifo_mempool_item_alloc( * __vxge_hw_fifo_create - Create a FIFO * This function creates FIFO and initializes it. */ -enum vxge_hw_status +static enum vxge_hw_status __vxge_hw_fifo_create(struct __vxge_hw_vpath_handle *vp, struct vxge_hw_fifo_attr *attr) { @@ -2617,7 +3038,8 @@ static enum vxge_hw_status __vxge_hw_fifo_reset(struct __vxge_hw_fifo *fifo) * __vxge_hw_fifo_delete - Removes the FIFO * This function freeup the memory pool and removes the FIFO */ -enum vxge_hw_status __vxge_hw_fifo_delete(struct __vxge_hw_vpath_handle *vp) +static enum vxge_hw_status +__vxge_hw_fifo_delete(struct __vxge_hw_vpath_handle *vp) { struct __vxge_hw_fifo *fifo = vp->vpath->fifoh; @@ -2675,297 +3097,6 @@ exit: return status; } -/* - * __vxge_hw_vpath_func_id_get - Get the function id of the vpath. - * Returns the function number of the vpath. - */ -static u32 -__vxge_hw_vpath_func_id_get(u32 vp_id, - struct vxge_hw_vpmgmt_reg __iomem *vpmgmt_reg) -{ - u64 val64; - - val64 = readq(&vpmgmt_reg->vpath_to_func_map_cfg1); - - return - (u32)VXGE_HW_VPATH_TO_FUNC_MAP_CFG1_GET_VPATH_TO_FUNC_MAP_CFG1(val64); -} - -/* - * __vxge_hw_read_rts_ds - Program RTS steering critieria - */ -static inline void -__vxge_hw_read_rts_ds(struct vxge_hw_vpath_reg __iomem *vpath_reg, - u64 dta_struct_sel) -{ - writeq(0, &vpath_reg->rts_access_steer_ctrl); - wmb(); - writeq(dta_struct_sel, &vpath_reg->rts_access_steer_data0); - writeq(0, &vpath_reg->rts_access_steer_data1); - wmb(); -} - - -/* - * __vxge_hw_vpath_card_info_get - Get the serial numbers, - * part number and product description. - */ -static enum vxge_hw_status -__vxge_hw_vpath_card_info_get( - u32 vp_id, - struct vxge_hw_vpath_reg __iomem *vpath_reg, - struct vxge_hw_device_hw_info *hw_info) -{ - u32 i, j; - u64 val64; - u64 data1 = 0ULL; - u64 data2 = 0ULL; - enum vxge_hw_status status = VXGE_HW_OK; - u8 *serial_number = hw_info->serial_number; - u8 *part_number = hw_info->part_number; - u8 *product_desc = hw_info->product_desc; - - __vxge_hw_read_rts_ds(vpath_reg, - VXGE_HW_RTS_ACCESS_STEER_DATA0_MEMO_ITEM_SERIAL_NUMBER); - - val64 = VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION( - VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION_READ_MEMO_ENTRY) | - VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL( - VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_FW_MEMO) | - VXGE_HW_RTS_ACCESS_STEER_CTRL_STROBE | - VXGE_HW_RTS_ACCESS_STEER_CTRL_OFFSET(0); - - status = __vxge_hw_pio_mem_write64(val64, - &vpath_reg->rts_access_steer_ctrl, - VXGE_HW_RTS_ACCESS_STEER_CTRL_STROBE, - VXGE_HW_DEF_DEVICE_POLL_MILLIS); - - if (status != VXGE_HW_OK) - return status; - - val64 = readq(&vpath_reg->rts_access_steer_ctrl); - - if (val64 & VXGE_HW_RTS_ACCESS_STEER_CTRL_RMACJ_STATUS) { - data1 = readq(&vpath_reg->rts_access_steer_data0); - ((u64 *)serial_number)[0] = be64_to_cpu(data1); - - data2 = readq(&vpath_reg->rts_access_steer_data1); - ((u64 *)serial_number)[1] = be64_to_cpu(data2); - status = VXGE_HW_OK; - } else - *serial_number = 0; - - __vxge_hw_read_rts_ds(vpath_reg, - VXGE_HW_RTS_ACCESS_STEER_DATA0_MEMO_ITEM_PART_NUMBER); - - val64 = VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION( - VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION_READ_MEMO_ENTRY) | - VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL( - VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_FW_MEMO) | - VXGE_HW_RTS_ACCESS_STEER_CTRL_STROBE | - VXGE_HW_RTS_ACCESS_STEER_CTRL_OFFSET(0); - - status = __vxge_hw_pio_mem_write64(val64, - &vpath_reg->rts_access_steer_ctrl, - VXGE_HW_RTS_ACCESS_STEER_CTRL_STROBE, - VXGE_HW_DEF_DEVICE_POLL_MILLIS); - - if (status != VXGE_HW_OK) - return status; - - val64 = readq(&vpath_reg->rts_access_steer_ctrl); - - if (val64 & VXGE_HW_RTS_ACCESS_STEER_CTRL_RMACJ_STATUS) { - - data1 = readq(&vpath_reg->rts_access_steer_data0); - ((u64 *)part_number)[0] = be64_to_cpu(data1); - - data2 = readq(&vpath_reg->rts_access_steer_data1); - ((u64 *)part_number)[1] = be64_to_cpu(data2); - - status = VXGE_HW_OK; - - } else - *part_number = 0; - - j = 0; - - for (i = VXGE_HW_RTS_ACCESS_STEER_DATA0_MEMO_ITEM_DESC_0; - i <= VXGE_HW_RTS_ACCESS_STEER_DATA0_MEMO_ITEM_DESC_3; i++) { - - __vxge_hw_read_rts_ds(vpath_reg, i); - - val64 = VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION( - VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION_READ_MEMO_ENTRY) | - VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL( - VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_FW_MEMO) | - VXGE_HW_RTS_ACCESS_STEER_CTRL_STROBE | - VXGE_HW_RTS_ACCESS_STEER_CTRL_OFFSET(0); - - status = __vxge_hw_pio_mem_write64(val64, - &vpath_reg->rts_access_steer_ctrl, - VXGE_HW_RTS_ACCESS_STEER_CTRL_STROBE, - VXGE_HW_DEF_DEVICE_POLL_MILLIS); - - if (status != VXGE_HW_OK) - return status; - - val64 = readq(&vpath_reg->rts_access_steer_ctrl); - - if (val64 & VXGE_HW_RTS_ACCESS_STEER_CTRL_RMACJ_STATUS) { - - data1 = readq(&vpath_reg->rts_access_steer_data0); - ((u64 *)product_desc)[j++] = be64_to_cpu(data1); - - data2 = readq(&vpath_reg->rts_access_steer_data1); - ((u64 *)product_desc)[j++] = be64_to_cpu(data2); - - status = VXGE_HW_OK; - } else - *product_desc = 0; - } - - return status; -} - -/* - * __vxge_hw_vpath_fw_ver_get - Get the fw version - * Returns FW Version - */ -static enum vxge_hw_status -__vxge_hw_vpath_fw_ver_get( - u32 vp_id, - struct vxge_hw_vpath_reg __iomem *vpath_reg, - struct vxge_hw_device_hw_info *hw_info) -{ - u64 val64; - u64 data1 = 0ULL; - u64 data2 = 0ULL; - struct vxge_hw_device_version *fw_version = &hw_info->fw_version; - struct vxge_hw_device_date *fw_date = &hw_info->fw_date; - struct vxge_hw_device_version *flash_version = &hw_info->flash_version; - struct vxge_hw_device_date *flash_date = &hw_info->flash_date; - enum vxge_hw_status status = VXGE_HW_OK; - - val64 = VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION( - VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION_READ_ENTRY) | - VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL( - VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_FW_MEMO) | - VXGE_HW_RTS_ACCESS_STEER_CTRL_STROBE | - VXGE_HW_RTS_ACCESS_STEER_CTRL_OFFSET(0); - - status = __vxge_hw_pio_mem_write64(val64, - &vpath_reg->rts_access_steer_ctrl, - VXGE_HW_RTS_ACCESS_STEER_CTRL_STROBE, - VXGE_HW_DEF_DEVICE_POLL_MILLIS); - - if (status != VXGE_HW_OK) - goto exit; - - val64 = readq(&vpath_reg->rts_access_steer_ctrl); - - if (val64 & VXGE_HW_RTS_ACCESS_STEER_CTRL_RMACJ_STATUS) { - - data1 = readq(&vpath_reg->rts_access_steer_data0); - data2 = readq(&vpath_reg->rts_access_steer_data1); - - fw_date->day = - (u32)VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_FW_VER_DAY( - data1); - fw_date->month = - (u32)VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_FW_VER_MONTH( - data1); - fw_date->year = - (u32)VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_FW_VER_YEAR( - data1); - - snprintf(fw_date->date, VXGE_HW_FW_STRLEN, "%2.2d/%2.2d/%4.4d", - fw_date->month, fw_date->day, fw_date->year); - - fw_version->major = - (u32)VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_FW_VER_MAJOR(data1); - fw_version->minor = - (u32)VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_FW_VER_MINOR(data1); - fw_version->build = - (u32)VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_FW_VER_BUILD(data1); - - snprintf(fw_version->version, VXGE_HW_FW_STRLEN, "%d.%d.%d", - fw_version->major, fw_version->minor, fw_version->build); - - flash_date->day = - (u32)VXGE_HW_RTS_ACCESS_STEER_DATA1_GET_FLASH_VER_DAY(data2); - flash_date->month = - (u32)VXGE_HW_RTS_ACCESS_STEER_DATA1_GET_FLASH_VER_MONTH(data2); - flash_date->year = - (u32)VXGE_HW_RTS_ACCESS_STEER_DATA1_GET_FLASH_VER_YEAR(data2); - - snprintf(flash_date->date, VXGE_HW_FW_STRLEN, - "%2.2d/%2.2d/%4.4d", - flash_date->month, flash_date->day, flash_date->year); - - flash_version->major = - (u32)VXGE_HW_RTS_ACCESS_STEER_DATA1_GET_FLASH_VER_MAJOR(data2); - flash_version->minor = - (u32)VXGE_HW_RTS_ACCESS_STEER_DATA1_GET_FLASH_VER_MINOR(data2); - flash_version->build = - (u32)VXGE_HW_RTS_ACCESS_STEER_DATA1_GET_FLASH_VER_BUILD(data2); - - snprintf(flash_version->version, VXGE_HW_FW_STRLEN, "%d.%d.%d", - flash_version->major, flash_version->minor, - flash_version->build); - - status = VXGE_HW_OK; - - } else - status = VXGE_HW_FAIL; -exit: - return status; -} - -/* - * __vxge_hw_vpath_pci_func_mode_get - Get the pci mode - * Returns pci function mode - */ -static u64 -__vxge_hw_vpath_pci_func_mode_get( - u32 vp_id, - struct vxge_hw_vpath_reg __iomem *vpath_reg) -{ - u64 val64; - u64 data1 = 0ULL; - enum vxge_hw_status status = VXGE_HW_OK; - - __vxge_hw_read_rts_ds(vpath_reg, - VXGE_HW_RTS_ACCESS_STEER_DATA0_MEMO_ITEM_PCI_MODE); - - val64 = VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION( - VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION_READ_MEMO_ENTRY) | - VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL( - VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_FW_MEMO) | - VXGE_HW_RTS_ACCESS_STEER_CTRL_STROBE | - VXGE_HW_RTS_ACCESS_STEER_CTRL_OFFSET(0); - - status = __vxge_hw_pio_mem_write64(val64, - &vpath_reg->rts_access_steer_ctrl, - VXGE_HW_RTS_ACCESS_STEER_CTRL_STROBE, - VXGE_HW_DEF_DEVICE_POLL_MILLIS); - - if (status != VXGE_HW_OK) - goto exit; - - val64 = readq(&vpath_reg->rts_access_steer_ctrl); - - if (val64 & VXGE_HW_RTS_ACCESS_STEER_CTRL_RMACJ_STATUS) { - data1 = readq(&vpath_reg->rts_access_steer_data0); - status = VXGE_HW_OK; - } else { - data1 = 0; - status = VXGE_HW_FAIL; - } -exit: - return data1; -} - /** * vxge_hw_device_flick_link_led - Flick (blink) link LED. * @hldev: HW device. @@ -2974,37 +3105,24 @@ exit: * Flicker the link LED. */ enum vxge_hw_status -vxge_hw_device_flick_link_led(struct __vxge_hw_device *hldev, - u64 on_off) +vxge_hw_device_flick_link_led(struct __vxge_hw_device *hldev, u64 on_off) { - u64 val64; - enum vxge_hw_status status = VXGE_HW_OK; - struct vxge_hw_vpath_reg __iomem *vp_reg; + struct __vxge_hw_virtualpath *vpath; + u64 data0, data1 = 0, steer_ctrl = 0; + enum vxge_hw_status status; if (hldev == NULL) { status = VXGE_HW_ERR_INVALID_DEVICE; goto exit; } - vp_reg = hldev->vpath_reg[hldev->first_vp_id]; - - writeq(0, &vp_reg->rts_access_steer_ctrl); - wmb(); - writeq(on_off, &vp_reg->rts_access_steer_data0); - writeq(0, &vp_reg->rts_access_steer_data1); - wmb(); - - val64 = VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION( - VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION_LED_CONTROL) | - VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL( - VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_FW_MEMO) | - VXGE_HW_RTS_ACCESS_STEER_CTRL_STROBE | - VXGE_HW_RTS_ACCESS_STEER_CTRL_OFFSET(0); + vpath = &hldev->virtual_paths[hldev->first_vp_id]; - status = __vxge_hw_pio_mem_write64(val64, - &vp_reg->rts_access_steer_ctrl, - VXGE_HW_RTS_ACCESS_STEER_CTRL_STROBE, - VXGE_HW_DEF_DEVICE_POLL_MILLIS); + data0 = on_off; + status = vxge_hw_vpath_fw_api(vpath, + VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION_LED_CONTROL, + VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_FW_MEMO, + 0, &data0, &data1, &steer_ctrl); exit: return status; } @@ -3013,63 +3131,38 @@ exit: * __vxge_hw_vpath_rts_table_get - Get the entries from RTS access tables */ enum vxge_hw_status -__vxge_hw_vpath_rts_table_get( - struct __vxge_hw_vpath_handle *vp, - u32 action, u32 rts_table, u32 offset, u64 *data1, u64 *data2) +__vxge_hw_vpath_rts_table_get(struct __vxge_hw_vpath_handle *vp, + u32 action, u32 rts_table, u32 offset, + u64 *data0, u64 *data1) { - u64 val64; - struct __vxge_hw_virtualpath *vpath; - struct vxge_hw_vpath_reg __iomem *vp_reg; - - enum vxge_hw_status status = VXGE_HW_OK; + enum vxge_hw_status status; + u64 steer_ctrl = 0; if (vp == NULL) { status = VXGE_HW_ERR_INVALID_HANDLE; goto exit; } - vpath = vp->vpath; - vp_reg = vpath->vp_reg; - - val64 = VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION(action) | - VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL(rts_table) | - VXGE_HW_RTS_ACCESS_STEER_CTRL_STROBE | - VXGE_HW_RTS_ACCESS_STEER_CTRL_OFFSET(offset); - if ((rts_table == - VXGE_HW_RTS_ACS_STEER_CTRL_DATA_STRUCT_SEL_RTH_SOLO_IT) || + VXGE_HW_RTS_ACS_STEER_CTRL_DATA_STRUCT_SEL_RTH_SOLO_IT) || (rts_table == - VXGE_HW_RTS_ACS_STEER_CTRL_DATA_STRUCT_SEL_RTH_MULTI_IT) || + VXGE_HW_RTS_ACS_STEER_CTRL_DATA_STRUCT_SEL_RTH_MULTI_IT) || (rts_table == - VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_RTH_MASK) || + VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_RTH_MASK) || (rts_table == - VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_RTH_KEY)) { - val64 = val64 | VXGE_HW_RTS_ACCESS_STEER_CTRL_TABLE_SEL; + VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_RTH_KEY)) { + steer_ctrl = VXGE_HW_RTS_ACCESS_STEER_CTRL_TABLE_SEL; } - status = __vxge_hw_pio_mem_write64(val64, - &vp_reg->rts_access_steer_ctrl, - VXGE_HW_RTS_ACCESS_STEER_CTRL_STROBE, - vpath->hldev->config.device_poll_millis); - + status = vxge_hw_vpath_fw_api(vp->vpath, action, rts_table, offset, + data0, data1, &steer_ctrl); if (status != VXGE_HW_OK) goto exit; - val64 = readq(&vp_reg->rts_access_steer_ctrl); - - if (val64 & VXGE_HW_RTS_ACCESS_STEER_CTRL_RMACJ_STATUS) { - - *data1 = readq(&vp_reg->rts_access_steer_data0); - - if ((rts_table == - VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_DA) || - (rts_table == - VXGE_HW_RTS_ACS_STEER_CTRL_DATA_STRUCT_SEL_RTH_MULTI_IT)) { - *data2 = readq(&vp_reg->rts_access_steer_data1); - } - status = VXGE_HW_OK; - } else - status = VXGE_HW_FAIL; + if ((rts_table != VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_DA) || + (rts_table != + VXGE_HW_RTS_ACS_STEER_CTRL_DATA_STRUCT_SEL_RTH_MULTI_IT)) + *data1 = 0; exit: return status; } @@ -3078,107 +3171,27 @@ exit: * __vxge_hw_vpath_rts_table_set - Set the entries of RTS access tables */ enum vxge_hw_status -__vxge_hw_vpath_rts_table_set( - struct __vxge_hw_vpath_handle *vp, u32 action, u32 rts_table, - u32 offset, u64 data1, u64 data2) +__vxge_hw_vpath_rts_table_set(struct __vxge_hw_vpath_handle *vp, u32 action, + u32 rts_table, u32 offset, u64 steer_data0, + u64 steer_data1) { - u64 val64; - struct __vxge_hw_virtualpath *vpath; - enum vxge_hw_status status = VXGE_HW_OK; - struct vxge_hw_vpath_reg __iomem *vp_reg; + u64 data0, data1 = 0, steer_ctrl = 0; + enum vxge_hw_status status; if (vp == NULL) { status = VXGE_HW_ERR_INVALID_HANDLE; goto exit; } - vpath = vp->vpath; - vp_reg = vpath->vp_reg; - - writeq(data1, &vp_reg->rts_access_steer_data0); - wmb(); + data0 = steer_data0; if ((rts_table == VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_DA) || (rts_table == - VXGE_HW_RTS_ACS_STEER_CTRL_DATA_STRUCT_SEL_RTH_MULTI_IT)) { - writeq(data2, &vp_reg->rts_access_steer_data1); - wmb(); - } + VXGE_HW_RTS_ACS_STEER_CTRL_DATA_STRUCT_SEL_RTH_MULTI_IT)) + data1 = steer_data1; - val64 = VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION(action) | - VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL(rts_table) | - VXGE_HW_RTS_ACCESS_STEER_CTRL_STROBE | - VXGE_HW_RTS_ACCESS_STEER_CTRL_OFFSET(offset); - - status = __vxge_hw_pio_mem_write64(val64, - &vp_reg->rts_access_steer_ctrl, - VXGE_HW_RTS_ACCESS_STEER_CTRL_STROBE, - vpath->hldev->config.device_poll_millis); - - if (status != VXGE_HW_OK) - goto exit; - - val64 = readq(&vp_reg->rts_access_steer_ctrl); - - if (val64 & VXGE_HW_RTS_ACCESS_STEER_CTRL_RMACJ_STATUS) - status = VXGE_HW_OK; - else - status = VXGE_HW_FAIL; -exit: - return status; -} - -/* - * __vxge_hw_vpath_addr_get - Get the hw address entry for this vpath - * from MAC address table. - */ -static enum vxge_hw_status -__vxge_hw_vpath_addr_get( - u32 vp_id, struct vxge_hw_vpath_reg __iomem *vpath_reg, - u8 (macaddr)[ETH_ALEN], u8 (macaddr_mask)[ETH_ALEN]) -{ - u32 i; - u64 val64; - u64 data1 = 0ULL; - u64 data2 = 0ULL; - enum vxge_hw_status status = VXGE_HW_OK; - - val64 = VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION( - VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION_LIST_FIRST_ENTRY) | - VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL( - VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_DA) | - VXGE_HW_RTS_ACCESS_STEER_CTRL_STROBE | - VXGE_HW_RTS_ACCESS_STEER_CTRL_OFFSET(0); - - status = __vxge_hw_pio_mem_write64(val64, - &vpath_reg->rts_access_steer_ctrl, - VXGE_HW_RTS_ACCESS_STEER_CTRL_STROBE, - VXGE_HW_DEF_DEVICE_POLL_MILLIS); - - if (status != VXGE_HW_OK) - goto exit; - - val64 = readq(&vpath_reg->rts_access_steer_ctrl); - - if (val64 & VXGE_HW_RTS_ACCESS_STEER_CTRL_RMACJ_STATUS) { - - data1 = readq(&vpath_reg->rts_access_steer_data0); - data2 = readq(&vpath_reg->rts_access_steer_data1); - - data1 = VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_DA_MAC_ADDR(data1); - data2 = VXGE_HW_RTS_ACCESS_STEER_DATA1_GET_DA_MAC_ADDR_MASK( - data2); - - for (i = ETH_ALEN; i > 0; i--) { - macaddr[i-1] = (u8)(data1 & 0xFF); - data1 >>= 8; - - macaddr_mask[i-1] = (u8)(data2 & 0xFF); - data2 >>= 8; - } - status = VXGE_HW_OK; - } else - status = VXGE_HW_FAIL; + status = vxge_hw_vpath_fw_api(vp->vpath, action, rts_table, offset, + &data0, &data1, &steer_ctrl); exit: return status; } @@ -3204,6 +3217,8 @@ enum vxge_hw_status vxge_hw_vpath_rts_rth_set( VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION_READ_ENTRY, VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_RTH_GEN_CFG, 0, &data0, &data1); + if (status != VXGE_HW_OK) + goto exit; data0 &= ~(VXGE_HW_RTS_ACCESS_STEER_DATA0_RTH_GEN_BUCKET_SIZE(0xf) | VXGE_HW_RTS_ACCESS_STEER_DATA0_RTH_GEN_ALG_SEL(0x3)); @@ -4117,6 +4132,7 @@ __vxge_hw_vp_initialize(struct __vxge_hw_device *hldev, u32 vp_id, vpath = &hldev->virtual_paths[vp_id]; + spin_lock_init(&hldev->virtual_paths[vp_id].lock); vpath->vp_id = vp_id; vpath->vp_open = VXGE_HW_VP_OPEN; vpath->hldev = hldev; @@ -4127,14 +4143,12 @@ __vxge_hw_vp_initialize(struct __vxge_hw_device *hldev, u32 vp_id, __vxge_hw_vpath_reset(hldev, vp_id); status = __vxge_hw_vpath_reset_check(vpath); - if (status != VXGE_HW_OK) { memset(vpath, 0, sizeof(struct __vxge_hw_virtualpath)); goto exit; } status = __vxge_hw_vpath_mgmt_read(hldev, vpath); - if (status != VXGE_HW_OK) { memset(vpath, 0, sizeof(struct __vxge_hw_virtualpath)); goto exit; @@ -4148,7 +4162,6 @@ __vxge_hw_vp_initialize(struct __vxge_hw_device *hldev, u32 vp_id, hldev->tim_int_mask1, vp_id); status = __vxge_hw_vpath_initialize(hldev, vp_id); - if (status != VXGE_HW_OK) __vxge_hw_vp_terminate(hldev, vp_id); exit: @@ -4242,15 +4255,12 @@ vxge_hw_vpath_open(struct __vxge_hw_device *hldev, if (status != VXGE_HW_OK) goto vpath_open_exit1; - vp = (struct __vxge_hw_vpath_handle *) - vmalloc(sizeof(struct __vxge_hw_vpath_handle)); + vp = vzalloc(sizeof(struct __vxge_hw_vpath_handle)); if (vp == NULL) { status = VXGE_HW_ERR_OUT_OF_MEMORY; goto vpath_open_exit2; } - memset(vp, 0, sizeof(struct __vxge_hw_vpath_handle)); - vp->vpath = vpath; if (vpath->vp_config->fifo.enable == VXGE_HW_FIFO_ENABLE) { @@ -4335,16 +4345,18 @@ vpath_open_exit1: void vxge_hw_vpath_rx_doorbell_init(struct __vxge_hw_vpath_handle *vp) { - struct __vxge_hw_virtualpath *vpath = NULL; + struct __vxge_hw_virtualpath *vpath = vp->vpath; + struct __vxge_hw_ring *ring = vpath->ringh; + struct vxgedev *vdev = netdev_priv(vpath->hldev->ndev); u64 new_count, val64, val164; - struct __vxge_hw_ring *ring; - vpath = vp->vpath; - ring = vpath->ringh; + if (vdev->titan1) { + new_count = readq(&vpath->vp_reg->rxdmem_size); + new_count &= 0x1fff; + } else + new_count = ring->config->ring_blocks * VXGE_HW_BLOCK_SIZE / 8; - new_count = readq(&vpath->vp_reg->rxdmem_size); - new_count &= 0x1fff; - val164 = (VXGE_HW_RXDMEM_SIZE_PRC_RXDMEM_SIZE(new_count)); + val164 = VXGE_HW_RXDMEM_SIZE_PRC_RXDMEM_SIZE(new_count); writeq(VXGE_HW_PRC_RXD_DOORBELL_NEW_QW_CNT(val164), &vpath->vp_reg->prc_rxd_doorbell); @@ -4414,7 +4426,9 @@ enum vxge_hw_status vxge_hw_vpath_close(struct __vxge_hw_vpath_handle *vp) __vxge_hw_vp_terminate(devh, vp_id); + spin_lock(&vpath->lock); vpath->vp_open = VXGE_HW_VP_NOT_OPEN; + spin_unlock(&vpath->lock); vpath_close_exit: return status; @@ -4810,7 +4824,7 @@ static void vxge_os_dma_free(struct pci_dev *pdev, const void *vaddr, * __vxge_hw_blockpool_create - Create block pool */ -enum vxge_hw_status +static enum vxge_hw_status __vxge_hw_blockpool_create(struct __vxge_hw_device *hldev, struct __vxge_hw_blockpool *blockpool, u32 pool_size, @@ -4910,7 +4924,7 @@ blockpool_create_exit: * __vxge_hw_blockpool_destroy - Deallocates the block pool */ -void __vxge_hw_blockpool_destroy(struct __vxge_hw_blockpool *blockpool) +static void __vxge_hw_blockpool_destroy(struct __vxge_hw_blockpool *blockpool) { struct __vxge_hw_device *hldev; @@ -5047,8 +5061,7 @@ static void vxge_hw_blockpool_block_add(struct __vxge_hw_device *devh, item); if (entry == NULL) - entry = (struct __vxge_hw_blockpool_entry *) - vmalloc(sizeof(struct __vxge_hw_blockpool_entry)); + entry = vmalloc(sizeof(struct __vxge_hw_blockpool_entry)); else list_del(&entry->item); @@ -5076,7 +5089,7 @@ exit: * Allocates a block of memory of given size, either from block pool * or by calling vxge_os_dma_malloc() */ -void * +static void * __vxge_hw_blockpool_malloc(struct __vxge_hw_device *devh, u32 size, struct vxge_hw_mempool_dma *dma_object) { @@ -5140,7 +5153,7 @@ exit: * __vxge_hw_blockpool_free - Frees the memory allcoated with __vxge_hw_blockpool_malloc */ -void +static void __vxge_hw_blockpool_free(struct __vxge_hw_device *devh, void *memblock, u32 size, struct vxge_hw_mempool_dma *dma_object) @@ -5164,8 +5177,7 @@ __vxge_hw_blockpool_free(struct __vxge_hw_device *devh, item); if (entry == NULL) - entry = (struct __vxge_hw_blockpool_entry *) - vmalloc(sizeof( + entry = vmalloc(sizeof( struct __vxge_hw_blockpool_entry)); else list_del(&entry->item); @@ -5192,7 +5204,7 @@ __vxge_hw_blockpool_free(struct __vxge_hw_device *devh, * __vxge_hw_blockpool_block_allocate - Allocates a block from block pool * This function allocates a block from block pool or from the system */ -struct __vxge_hw_blockpool_entry * +static struct __vxge_hw_blockpool_entry * __vxge_hw_blockpool_block_allocate(struct __vxge_hw_device *devh, u32 size) { struct __vxge_hw_blockpool_entry *entry = NULL; @@ -5227,7 +5239,7 @@ __vxge_hw_blockpool_block_allocate(struct __vxge_hw_device *devh, u32 size) * * This function frees a block from block pool */ -void +static void __vxge_hw_blockpool_block_free(struct __vxge_hw_device *devh, struct __vxge_hw_blockpool_entry *entry) { diff --git a/drivers/net/vxge/vxge-config.h b/drivers/net/vxge/vxge-config.h index 5c00861b6c2c..5b2c8313426d 100644 --- a/drivers/net/vxge/vxge-config.h +++ b/drivers/net/vxge/vxge-config.h @@ -20,13 +20,6 @@ #define VXGE_CACHE_LINE_SIZE 128 #endif -#define vxge_os_vaprintf(level, mask, fmt, ...) { \ - char buff[255]; \ - snprintf(buff, 255, fmt, __VA_ARGS__); \ - printk(buff); \ - printk("\n"); \ -} - #ifndef VXGE_ALIGN #define VXGE_ALIGN(adrs, size) \ (((size) - (((u64)adrs) & ((size)-1))) & ((size)-1)) @@ -36,8 +29,16 @@ #define VXGE_HW_MAX_MTU 9600 #define VXGE_HW_DEFAULT_MTU 1500 -#ifdef VXGE_DEBUG_ASSERT +#define VXGE_HW_MAX_ROM_IMAGES 8 + +struct eprom_image { + u8 is_valid:1; + u8 index; + u8 type; + u16 version; +}; +#ifdef VXGE_DEBUG_ASSERT /** * vxge_assert * @test: C-condition to check @@ -48,16 +49,13 @@ * compilation * time. */ -#define vxge_assert(test) { \ - if (!(test)) \ - vxge_os_bug("bad cond: "#test" at %s:%d\n", \ - __FILE__, __LINE__); } +#define vxge_assert(test) BUG_ON(!(test)) #else #define vxge_assert(test) #endif /* end of VXGE_DEBUG_ASSERT */ /** - * enum enum vxge_debug_level + * enum vxge_debug_level * @VXGE_NONE: debug disabled * @VXGE_ERR: all errors going to be logged out * @VXGE_TRACE: all errors plus all kind of verbose tracing print outs @@ -159,6 +157,47 @@ enum vxge_hw_device_link_state { }; /** + * enum enum vxge_hw_fw_upgrade_code - FW upgrade return codes. + * @VXGE_HW_FW_UPGRADE_OK: All OK send next 16 bytes + * @VXGE_HW_FW_UPGRADE_DONE: upload completed + * @VXGE_HW_FW_UPGRADE_ERR: upload error + * @VXGE_FW_UPGRADE_BYTES2SKIP: skip bytes in the stream + * + */ +enum vxge_hw_fw_upgrade_code { + VXGE_HW_FW_UPGRADE_OK = 0, + VXGE_HW_FW_UPGRADE_DONE = 1, + VXGE_HW_FW_UPGRADE_ERR = 2, + VXGE_FW_UPGRADE_BYTES2SKIP = 3 +}; + +/** + * enum enum vxge_hw_fw_upgrade_err_code - FW upgrade error codes. + * @VXGE_HW_FW_UPGRADE_ERR_CORRUPT_DATA_1: corrupt data + * @VXGE_HW_FW_UPGRADE_ERR_BUFFER_OVERFLOW: buffer overflow + * @VXGE_HW_FW_UPGRADE_ERR_INV_NCF_FILE_3: invalid .ncf file + * @VXGE_HW_FW_UPGRADE_ERR_INV_NCF_FILE_4: invalid .ncf file + * @VXGE_HW_FW_UPGRADE_ERR_INV_NCF_FILE_5: invalid .ncf file + * @VXGE_HW_FW_UPGRADE_ERR_INV_NCF_FILE_6: invalid .ncf file + * @VXGE_HW_FW_UPGRADE_ERR_CORRUPT_DATA_7: corrupt data + * @VXGE_HW_FW_UPGRADE_ERR_INV_NCF_FILE_8: invalid .ncf file + * @VXGE_HW_FW_UPGRADE_ERR_GENERIC_ERROR_UNKNOWN: generic error unknown type + * @VXGE_HW_FW_UPGRADE_ERR_FAILED_TO_FLASH: failed to flash image check failed + */ +enum vxge_hw_fw_upgrade_err_code { + VXGE_HW_FW_UPGRADE_ERR_CORRUPT_DATA_1 = 1, + VXGE_HW_FW_UPGRADE_ERR_BUFFER_OVERFLOW = 2, + VXGE_HW_FW_UPGRADE_ERR_INV_NCF_FILE_3 = 3, + VXGE_HW_FW_UPGRADE_ERR_INV_NCF_FILE_4 = 4, + VXGE_HW_FW_UPGRADE_ERR_INV_NCF_FILE_5 = 5, + VXGE_HW_FW_UPGRADE_ERR_INV_NCF_FILE_6 = 6, + VXGE_HW_FW_UPGRADE_ERR_CORRUPT_DATA_7 = 7, + VXGE_HW_FW_UPGRADE_ERR_INV_NCF_FILE_8 = 8, + VXGE_HW_FW_UPGRADE_ERR_GENERIC_ERROR_UNKNOWN = 9, + VXGE_HW_FW_UPGRADE_ERR_FAILED_TO_FLASH = 10 +}; + +/** * struct vxge_hw_device_date - Date Format * @day: Day * @month: Month @@ -465,7 +504,6 @@ struct vxge_hw_device_config { * See also: vxge_hw_driver_initialize(). */ struct vxge_hw_uld_cbs { - void (*link_up)(struct __vxge_hw_device *devh); void (*link_down)(struct __vxge_hw_device *devh); void (*crit_err)(struct __vxge_hw_device *devh, @@ -652,6 +690,7 @@ struct __vxge_hw_virtualpath { struct vxge_hw_vpath_stats_hw_info *hw_stats; struct vxge_hw_vpath_stats_hw_info *hw_stats_sav; struct vxge_hw_vpath_stats_sw_info *sw_stats; + spinlock_t lock; }; /* @@ -674,9 +713,6 @@ struct __vxge_hw_vpath_handle{ /** * struct __vxge_hw_device - Hal device object * @magic: Magic Number - * @device_id: PCI Device Id of the adapter - * @major_revision: PCI Device major revision - * @minor_revision: PCI Device minor revision * @bar0: BAR0 virtual address. * @pdev: Physical device handle * @config: Confguration passed by the LL driver at initialization @@ -688,9 +724,6 @@ struct __vxge_hw_device { u32 magic; #define VXGE_HW_DEVICE_MAGIC 0x12345678 #define VXGE_HW_DEVICE_DEAD 0xDEADDEAD - u16 device_id; - u8 major_revision; - u8 minor_revision; void __iomem *bar0; struct pci_dev *pdev; struct net_device *ndev; @@ -731,6 +764,7 @@ struct __vxge_hw_device { u32 debug_level; u32 level_err; u32 level_trace; + u16 eprom_versions[VXGE_HW_MAX_ROM_IMAGES]; }; #define VXGE_HW_INFO_LEN 64 @@ -1413,12 +1447,12 @@ enum vxge_hw_rth_algoritms { * See also: vxge_hw_vpath_rts_rth_set(), vxge_hw_vpath_rts_rth_get(). */ struct vxge_hw_rth_hash_types { - u8 hash_type_tcpipv4_en; - u8 hash_type_ipv4_en; - u8 hash_type_tcpipv6_en; - u8 hash_type_ipv6_en; - u8 hash_type_tcpipv6ex_en; - u8 hash_type_ipv6ex_en; + u8 hash_type_tcpipv4_en:1, + hash_type_ipv4_en:1, + hash_type_tcpipv6_en:1, + hash_type_ipv6_en:1, + hash_type_tcpipv6ex_en:1, + hash_type_ipv6ex_en:1; }; void vxge_hw_device_debug_set( @@ -2000,7 +2034,7 @@ enum vxge_hw_status vxge_hw_vpath_strip_fcs_check(struct __vxge_hw_device *hldev, u64 vpath_mask); /** - * vxge_debug + * vxge_debug_ll * @level: level of debug verbosity. * @mask: mask for the debug * @buf: Circular buffer for tracing @@ -2012,26 +2046,13 @@ vxge_hw_vpath_strip_fcs_check(struct __vxge_hw_device *hldev, u64 vpath_mask); * may be compiled out if DEBUG macro was never defined. * See also: enum vxge_debug_level{}. */ - -#define vxge_trace_aux(level, mask, fmt, ...) \ -{\ - vxge_os_vaprintf(level, mask, fmt, __VA_ARGS__);\ -} - -#define vxge_debug(module, level, mask, fmt, ...) { \ -if ((level >= VXGE_TRACE && ((module & VXGE_DEBUG_TRACE_MASK) == module)) || \ - (level >= VXGE_ERR && ((module & VXGE_DEBUG_ERR_MASK) == module))) {\ - if ((mask & VXGE_DEBUG_MASK) == mask)\ - vxge_trace_aux(level, mask, fmt, __VA_ARGS__); \ -} \ -} - #if (VXGE_COMPONENT_LL & VXGE_DEBUG_MODULE_MASK) -#define vxge_debug_ll(level, mask, fmt, ...) \ -{\ - vxge_debug(VXGE_COMPONENT_LL, level, mask, fmt, __VA_ARGS__);\ -} - +#define vxge_debug_ll(level, mask, fmt, ...) do { \ + if ((level >= VXGE_ERR && VXGE_COMPONENT_LL & VXGE_DEBUG_ERR_MASK) || \ + (level >= VXGE_TRACE && VXGE_COMPONENT_LL & VXGE_DEBUG_TRACE_MASK))\ + if ((mask & VXGE_DEBUG_MASK) == mask) \ + printk(fmt "\n", __VA_ARGS__); \ +} while (0) #else #define vxge_debug_ll(level, mask, fmt, ...) #endif @@ -2051,4 +2072,26 @@ enum vxge_hw_status vxge_hw_vpath_rts_rth_set( enum vxge_hw_status __vxge_hw_device_is_privilaged(u32 host_type, u32 func_id); + +#define VXGE_HW_MIN_SUCCESSIVE_IDLE_COUNT 5 +#define VXGE_HW_MAX_POLLING_COUNT 100 + +void +vxge_hw_device_wait_receive_idle(struct __vxge_hw_device *hldev); + +enum vxge_hw_status +vxge_hw_upgrade_read_version(struct __vxge_hw_device *hldev, u32 *major, + u32 *minor, u32 *build); + +enum vxge_hw_status vxge_hw_flash_fw(struct __vxge_hw_device *hldev); + +enum vxge_hw_status +vxge_update_fw_image(struct __vxge_hw_device *hldev, const u8 *filebuf, + int size); + +enum vxge_hw_status +vxge_hw_vpath_eprom_img_ver_get(struct __vxge_hw_device *hldev, + struct eprom_image *eprom_image_data); + +int vxge_hw_vpath_wait_receive_idle(struct __vxge_hw_device *hldev, u32 vp_id); #endif diff --git a/drivers/net/vxge/vxge-ethtool.c b/drivers/net/vxge/vxge-ethtool.c index b67746eef923..bc9bd1035706 100644 --- a/drivers/net/vxge/vxge-ethtool.c +++ b/drivers/net/vxge/vxge-ethtool.c @@ -11,7 +11,7 @@ * Virtualized Server Adapter. * Copyright(c) 2002-2010 Exar Corp. ******************************************************************************/ -#include<linux/ethtool.h> +#include <linux/ethtool.h> #include <linux/slab.h> #include <linux/pci.h> #include <linux/etherdevice.h> @@ -29,7 +29,6 @@ * Return value: * 0 on success. */ - static int vxge_ethtool_sset(struct net_device *dev, struct ethtool_cmd *info) { /* We currently only support 10Gb/FULL */ @@ -79,10 +78,9 @@ static int vxge_ethtool_gset(struct net_device *dev, struct ethtool_cmd *info) * Returns driver specefic information like name, version etc.. to ethtool. */ static void vxge_ethtool_gdrvinfo(struct net_device *dev, - struct ethtool_drvinfo *info) + struct ethtool_drvinfo *info) { - struct vxgedev *vdev; - vdev = (struct vxgedev *)netdev_priv(dev); + struct vxgedev *vdev = netdev_priv(dev); strlcpy(info->driver, VXGE_DRIVER_NAME, sizeof(VXGE_DRIVER_NAME)); strlcpy(info->version, DRV_VERSION, sizeof(DRV_VERSION)); strlcpy(info->fw_version, vdev->fw_version, VXGE_HW_FW_STRLEN); @@ -104,15 +102,14 @@ static void vxge_ethtool_gdrvinfo(struct net_device *dev, * buffer area. */ static void vxge_ethtool_gregs(struct net_device *dev, - struct ethtool_regs *regs, void *space) + struct ethtool_regs *regs, void *space) { int index, offset; enum vxge_hw_status status; u64 reg; - u64 *reg_space = (u64 *) space; - struct vxgedev *vdev = (struct vxgedev *)netdev_priv(dev); - struct __vxge_hw_device *hldev = (struct __vxge_hw_device *) - pci_get_drvdata(vdev->pdev); + u64 *reg_space = (u64 *)space; + struct vxgedev *vdev = netdev_priv(dev); + struct __vxge_hw_device *hldev = vdev->devh; regs->len = sizeof(struct vxge_hw_vpath_reg) * vdev->no_of_vpath; regs->version = vdev->pdev->subsystem_device; @@ -147,9 +144,8 @@ static void vxge_ethtool_gregs(struct net_device *dev, */ static int vxge_ethtool_idnic(struct net_device *dev, u32 data) { - struct vxgedev *vdev = (struct vxgedev *)netdev_priv(dev); - struct __vxge_hw_device *hldev = (struct __vxge_hw_device *) - pci_get_drvdata(vdev->pdev); + struct vxgedev *vdev = netdev_priv(dev); + struct __vxge_hw_device *hldev = vdev->devh; vxge_hw_device_flick_link_led(hldev, VXGE_FLICKER_ON); msleep_interruptible(data ? (data * HZ) : VXGE_MAX_FLICKER_TIME); @@ -168,11 +164,10 @@ static int vxge_ethtool_idnic(struct net_device *dev, u32 data) * void */ static void vxge_ethtool_getpause_data(struct net_device *dev, - struct ethtool_pauseparam *ep) + struct ethtool_pauseparam *ep) { - struct vxgedev *vdev = (struct vxgedev *)netdev_priv(dev); - struct __vxge_hw_device *hldev = (struct __vxge_hw_device *) - pci_get_drvdata(vdev->pdev); + struct vxgedev *vdev = netdev_priv(dev); + struct __vxge_hw_device *hldev = vdev->devh; vxge_hw_device_getpause_data(hldev, 0, &ep->tx_pause, &ep->rx_pause); } @@ -188,11 +183,10 @@ static void vxge_ethtool_getpause_data(struct net_device *dev, * int, returns 0 on Success */ static int vxge_ethtool_setpause_data(struct net_device *dev, - struct ethtool_pauseparam *ep) + struct ethtool_pauseparam *ep) { - struct vxgedev *vdev = (struct vxgedev *)netdev_priv(dev); - struct __vxge_hw_device *hldev = (struct __vxge_hw_device *) - pci_get_drvdata(vdev->pdev); + struct vxgedev *vdev = netdev_priv(dev); + struct __vxge_hw_device *hldev = vdev->devh; vxge_hw_device_setpause_data(hldev, 0, ep->tx_pause, ep->rx_pause); @@ -209,9 +203,8 @@ static void vxge_get_ethtool_stats(struct net_device *dev, enum vxge_hw_status status; enum vxge_hw_status swstatus; struct vxge_vpath *vpath = NULL; - - struct vxgedev *vdev = (struct vxgedev *)netdev_priv(dev); - struct __vxge_hw_device *hldev = vdev->devh; + struct vxgedev *vdev = netdev_priv(dev); + struct __vxge_hw_device *hldev = vdev->devh; struct vxge_hw_xmac_stats *xmac_stats; struct vxge_hw_device_stats_sw_info *sw_stats; struct vxge_hw_device_stats_hw_info *hw_stats; @@ -574,12 +567,12 @@ static void vxge_get_ethtool_stats(struct net_device *dev, kfree(hw_stats); } -static void vxge_ethtool_get_strings(struct net_device *dev, - u32 stringset, u8 *data) +static void vxge_ethtool_get_strings(struct net_device *dev, u32 stringset, + u8 *data) { int stat_size = 0; int i, j; - struct vxgedev *vdev = (struct vxgedev *)netdev_priv(dev); + struct vxgedev *vdev = netdev_priv(dev); switch (stringset) { case ETH_SS_STATS: vxge_add_string("VPATH STATISTICS%s\t\t\t", @@ -1066,21 +1059,21 @@ static void vxge_ethtool_get_strings(struct net_device *dev, static int vxge_ethtool_get_regs_len(struct net_device *dev) { - struct vxgedev *vdev = (struct vxgedev *)netdev_priv(dev); + struct vxgedev *vdev = netdev_priv(dev); return sizeof(struct vxge_hw_vpath_reg) * vdev->no_of_vpath; } static u32 vxge_get_rx_csum(struct net_device *dev) { - struct vxgedev *vdev = (struct vxgedev *)netdev_priv(dev); + struct vxgedev *vdev = netdev_priv(dev); return vdev->rx_csum; } static int vxge_set_rx_csum(struct net_device *dev, u32 data) { - struct vxgedev *vdev = (struct vxgedev *)netdev_priv(dev); + struct vxgedev *vdev = netdev_priv(dev); if (data) vdev->rx_csum = 1; @@ -1102,7 +1095,7 @@ static int vxge_ethtool_op_set_tso(struct net_device *dev, u32 data) static int vxge_ethtool_get_sset_count(struct net_device *dev, int sset) { - struct vxgedev *vdev = (struct vxgedev *)netdev_priv(dev); + struct vxgedev *vdev = netdev_priv(dev); switch (sset) { case ETH_SS_STATS: @@ -1119,6 +1112,59 @@ static int vxge_ethtool_get_sset_count(struct net_device *dev, int sset) } } +static int vxge_set_flags(struct net_device *dev, u32 data) +{ + struct vxgedev *vdev = netdev_priv(dev); + enum vxge_hw_status status; + + if (data & ~ETH_FLAG_RXHASH) + return -EOPNOTSUPP; + + if (!!(data & ETH_FLAG_RXHASH) == vdev->devh->config.rth_en) + return 0; + + if (netif_running(dev) || (vdev->config.rth_steering == NO_STEERING)) + return -EINVAL; + + vdev->devh->config.rth_en = !!(data & ETH_FLAG_RXHASH); + + /* Enabling RTH requires some of the logic in vxge_device_register and a + * vpath reset. Due to these restrictions, only allow modification + * while the interface is down. + */ + status = vxge_reset_all_vpaths(vdev); + if (status != VXGE_HW_OK) { + vdev->devh->config.rth_en = !vdev->devh->config.rth_en; + return -EFAULT; + } + + if (vdev->devh->config.rth_en) + dev->features |= NETIF_F_RXHASH; + else + dev->features &= ~NETIF_F_RXHASH; + + return 0; +} + +static int vxge_fw_flash(struct net_device *dev, struct ethtool_flash *parms) +{ + struct vxgedev *vdev = netdev_priv(dev); + + if (vdev->max_vpath_supported != VXGE_HW_MAX_VIRTUAL_PATHS) { + printk(KERN_INFO "Single Function Mode is required to flash the" + " firmware\n"); + return -EINVAL; + } + + if (netif_running(dev)) { + printk(KERN_INFO "Interface %s must be down to flash the " + "firmware\n", dev->name); + return -EBUSY; + } + + return vxge_fw_upgrade(vdev, parms->data, 1); +} + static const struct ethtool_ops vxge_ethtool_ops = { .get_settings = vxge_ethtool_gset, .set_settings = vxge_ethtool_sset, @@ -1140,6 +1186,8 @@ static const struct ethtool_ops vxge_ethtool_ops = { .phys_id = vxge_ethtool_idnic, .get_sset_count = vxge_ethtool_get_sset_count, .get_ethtool_stats = vxge_get_ethtool_stats, + .set_flags = vxge_set_flags, + .flash_device = vxge_fw_flash, }; void vxge_initialize_ethtool_ops(struct net_device *ndev) diff --git a/drivers/net/vxge/vxge-main.c b/drivers/net/vxge/vxge-main.c index 813829f3d024..8a84152e320a 100644 --- a/drivers/net/vxge/vxge-main.c +++ b/drivers/net/vxge/vxge-main.c @@ -50,6 +50,8 @@ #include <net/ip.h> #include <linux/netdevice.h> #include <linux/etherdevice.h> +#include <linux/firmware.h> +#include <linux/net_tstamp.h> #include "vxge-main.h" #include "vxge-reg.h" @@ -90,7 +92,6 @@ static int vxge_mac_list_add(struct vxge_vpath *vpath, struct macInfo *mac); static int vxge_mac_list_del(struct vxge_vpath *vpath, struct macInfo *mac); static enum vxge_hw_status vxge_restore_vpath_vid_table(struct vxge_vpath *vpath); static enum vxge_hw_status vxge_restore_vpath_mac_addr(struct vxge_vpath *vpath); -static enum vxge_hw_status vxge_reset_all_vpaths(struct vxgedev *vdev); static inline int is_vxge_card_up(struct vxgedev *vdev) { @@ -152,7 +153,7 @@ static void vxge_callback_link_up(struct __vxge_hw_device *hldev) { struct net_device *dev = hldev->ndev; - struct vxgedev *vdev = (struct vxgedev *)netdev_priv(dev); + struct vxgedev *vdev = netdev_priv(dev); vxge_debug_entryexit(VXGE_TRACE, "%s: %s:%d", vdev->ndev->name, __func__, __LINE__); @@ -176,7 +177,7 @@ static void vxge_callback_link_down(struct __vxge_hw_device *hldev) { struct net_device *dev = hldev->ndev; - struct vxgedev *vdev = (struct vxgedev *)netdev_priv(dev); + struct vxgedev *vdev = netdev_priv(dev); vxge_debug_entryexit(VXGE_TRACE, "%s: %s:%d", vdev->ndev->name, __func__, __LINE__); @@ -369,7 +370,7 @@ vxge_rx_1b_compl(struct __vxge_hw_ring *ringh, void *dtr, u8 t_code, void *userdata) { struct vxge_ring *ring = (struct vxge_ring *)userdata; - struct net_device *dev = ring->ndev; + struct net_device *dev = ring->ndev; unsigned int dma_sizes; void *first_dtr = NULL; int dtr_cnt = 0; @@ -513,6 +514,23 @@ vxge_rx_1b_compl(struct __vxge_hw_ring *ringh, void *dtr, else skb_checksum_none_assert(skb); + + if (ring->rx_hwts) { + struct skb_shared_hwtstamps *skb_hwts; + u32 ns = *(u32 *)(skb->head + pkt_length); + + skb_hwts = skb_hwtstamps(skb); + skb_hwts->hwtstamp = ns_to_ktime(ns); + skb_hwts->syststamp.tv64 = 0; + } + + /* rth_hash_type and rth_it_hit are non-zero regardless of + * whether rss is enabled. Only the rth_value is zero/non-zero + * if rss is disabled/enabled, so key off of that. + */ + if (ext_info.rth_value) + skb->rxhash = ext_info.rth_value; + vxge_rx_complete(ring, skb, ext_info.vlan, pkt_length, &ext_info); @@ -670,7 +688,7 @@ static int vxge_learn_mac(struct vxgedev *vdev, u8 *mac_header) struct vxge_vpath *vpath = NULL; struct __vxge_hw_device *hldev; - hldev = (struct __vxge_hw_device *) pci_get_drvdata(vdev->pdev); + hldev = pci_get_drvdata(vdev->pdev); mac_address = (u8 *)&mac_addr; memcpy(mac_address, mac_header, ETH_ALEN); @@ -769,7 +787,7 @@ vxge_xmit(struct sk_buff *skb, struct net_device *dev) return NETDEV_TX_OK; } - vdev = (struct vxgedev *)netdev_priv(dev); + vdev = netdev_priv(dev); if (unlikely(!is_vxge_card_up(vdev))) { vxge_debug_tx(VXGE_ERR, @@ -1034,7 +1052,7 @@ static void vxge_set_multicast(struct net_device *dev) vxge_debug_entryexit(VXGE_TRACE, "%s:%d", __func__, __LINE__); - vdev = (struct vxgedev *)netdev_priv(dev); + vdev = netdev_priv(dev); hldev = (struct __vxge_hw_device *)vdev->devh; if (unlikely(!is_vxge_card_up(vdev))) @@ -1094,7 +1112,7 @@ static void vxge_set_multicast(struct net_device *dev) /* Delete previous MC's */ for (i = 0; i < mcast_cnt; i++) { list_for_each_safe(entry, next, list_head) { - mac_entry = (struct vxge_mac_addrs *) entry; + mac_entry = (struct vxge_mac_addrs *)entry; /* Copy the mac address to delete */ mac_address = (u8 *)&mac_entry->macaddr; memcpy(mac_info.macaddr, mac_address, ETH_ALEN); @@ -1137,7 +1155,7 @@ _set_all_mcast: /* Delete previous MC's */ for (i = 0; i < mcast_cnt; i++) { list_for_each_safe(entry, next, list_head) { - mac_entry = (struct vxge_mac_addrs *) entry; + mac_entry = (struct vxge_mac_addrs *)entry; /* Copy the mac address to delete */ mac_address = (u8 *)&mac_entry->macaddr; memcpy(mac_info.macaddr, mac_address, ETH_ALEN); @@ -1184,14 +1202,14 @@ static int vxge_set_mac_addr(struct net_device *dev, void *p) { struct sockaddr *addr = p; struct vxgedev *vdev; - struct __vxge_hw_device *hldev; + struct __vxge_hw_device *hldev; enum vxge_hw_status status = VXGE_HW_OK; struct macInfo mac_info_new, mac_info_old; int vpath_idx = 0; vxge_debug_entryexit(VXGE_TRACE, "%s:%d", __func__, __LINE__); - vdev = (struct vxgedev *)netdev_priv(dev); + vdev = netdev_priv(dev); hldev = vdev->devh; if (!is_valid_ether_addr(addr->sa_data)) @@ -1292,8 +1310,13 @@ static void vxge_vpath_intr_enable(struct vxgedev *vdev, int vp_id) static void vxge_vpath_intr_disable(struct vxgedev *vdev, int vp_id) { struct vxge_vpath *vpath = &vdev->vpaths[vp_id]; + struct __vxge_hw_device *hldev; int msix_id; + hldev = pci_get_drvdata(vdev->pdev); + + vxge_hw_vpath_wait_receive_idle(hldev, vpath->device_id); + vxge_hw_vpath_intr_disable(vpath->handle); if (vdev->config.intr_type == INTA) @@ -1423,6 +1446,7 @@ static int do_vxge_reset(struct vxgedev *vdev, int event) } if (event == VXGE_LL_FULL_RESET) { + vxge_hw_device_wait_receive_idle(vdev->devh); vxge_hw_device_intr_disable(vdev->devh); switch (vdev->cric_err_event) { @@ -1608,8 +1632,7 @@ static int vxge_poll_inta(struct napi_struct *napi, int budget) int budget_org = budget; struct vxge_ring *ring; - struct __vxge_hw_device *hldev = (struct __vxge_hw_device *) - pci_get_drvdata(vdev->pdev); + struct __vxge_hw_device *hldev = pci_get_drvdata(vdev->pdev); for (i = 0; i < vdev->no_of_vpath; i++) { ring = &vdev->vpaths[i].ring; @@ -1645,11 +1668,11 @@ static int vxge_poll_inta(struct napi_struct *napi, int budget) */ static void vxge_netpoll(struct net_device *dev) { - struct __vxge_hw_device *hldev; + struct __vxge_hw_device *hldev; struct vxgedev *vdev; - vdev = (struct vxgedev *)netdev_priv(dev); - hldev = (struct __vxge_hw_device *)pci_get_drvdata(vdev->pdev); + vdev = netdev_priv(dev); + hldev = pci_get_drvdata(vdev->pdev); vxge_debug_entryexit(VXGE_TRACE, "%s:%d", __func__, __LINE__); @@ -1689,15 +1712,6 @@ static enum vxge_hw_status vxge_rth_configure(struct vxgedev *vdev) mtable[index] = index % vdev->no_of_vpath; } - /* Fill RTH hash types */ - hash_types.hash_type_tcpipv4_en = vdev->config.rth_hash_type_tcpipv4; - hash_types.hash_type_ipv4_en = vdev->config.rth_hash_type_ipv4; - hash_types.hash_type_tcpipv6_en = vdev->config.rth_hash_type_tcpipv6; - hash_types.hash_type_ipv6_en = vdev->config.rth_hash_type_ipv6; - hash_types.hash_type_tcpipv6ex_en = - vdev->config.rth_hash_type_tcpipv6ex; - hash_types.hash_type_ipv6ex_en = vdev->config.rth_hash_type_ipv6ex; - /* set indirection table, bucket-to-vpath mapping */ status = vxge_hw_vpath_rts_rth_itable_set(vdev->vp_handles, vdev->no_of_vpath, @@ -1710,12 +1724,21 @@ static enum vxge_hw_status vxge_rth_configure(struct vxgedev *vdev) return status; } + /* Fill RTH hash types */ + hash_types.hash_type_tcpipv4_en = vdev->config.rth_hash_type_tcpipv4; + hash_types.hash_type_ipv4_en = vdev->config.rth_hash_type_ipv4; + hash_types.hash_type_tcpipv6_en = vdev->config.rth_hash_type_tcpipv6; + hash_types.hash_type_ipv6_en = vdev->config.rth_hash_type_ipv6; + hash_types.hash_type_tcpipv6ex_en = + vdev->config.rth_hash_type_tcpipv6ex; + hash_types.hash_type_ipv6ex_en = vdev->config.rth_hash_type_ipv6ex; + /* - * Because the itable_set() method uses the active_table field - * for the target virtual path the RTH config should be updated - * for all VPATHs. The h/w only uses the lowest numbered VPATH - * when steering frames. - */ + * Because the itable_set() method uses the active_table field + * for the target virtual path the RTH config should be updated + * for all VPATHs. The h/w only uses the lowest numbered VPATH + * when steering frames. + */ for (index = 0; index < vdev->no_of_vpath; index++) { status = vxge_hw_vpath_rts_rth_set( vdev->vpaths[index].handle, @@ -1797,7 +1820,7 @@ static int vxge_mac_list_del(struct vxge_vpath *vpath, struct macInfo *mac) { struct list_head *entry, *next; u64 del_mac = 0; - u8 *mac_address = (u8 *) (&del_mac); + u8 *mac_address = (u8 *)(&del_mac); /* Copy the mac address to delete from the list */ memcpy(mac_address, mac->macaddr, ETH_ALEN); @@ -1928,7 +1951,7 @@ static enum vxge_hw_status vxge_restore_vpath_mac_addr(struct vxge_vpath *vpath) } /* reset vpaths */ -static enum vxge_hw_status vxge_reset_all_vpaths(struct vxgedev *vdev) +enum vxge_hw_status vxge_reset_all_vpaths(struct vxgedev *vdev) { enum vxge_hw_status status = VXGE_HW_OK; struct vxge_vpath *vpath; @@ -1988,8 +2011,23 @@ static int vxge_open_vpaths(struct vxgedev *vdev) for (i = 0; i < vdev->no_of_vpath; i++) { vpath = &vdev->vpaths[i]; - vxge_assert(vpath->is_configured); + + if (!vdev->titan1) { + struct vxge_hw_vp_config *vcfg; + vcfg = &vdev->devh->config.vp_config[vpath->device_id]; + + vcfg->rti.urange_a = RTI_T1A_RX_URANGE_A; + vcfg->rti.urange_b = RTI_T1A_RX_URANGE_B; + vcfg->rti.urange_c = RTI_T1A_RX_URANGE_C; + vcfg->tti.uec_a = TTI_T1A_TX_UFC_A; + vcfg->tti.uec_b = TTI_T1A_TX_UFC_B; + vcfg->tti.uec_c = TTI_T1A_TX_UFC_C(vdev->mtu); + vcfg->tti.uec_d = TTI_T1A_TX_UFC_D(vdev->mtu); + vcfg->tti.ltimer_val = VXGE_T1A_TTI_LTIMER_VAL; + vcfg->tti.rtimer_val = VXGE_T1A_TTI_RTIMER_VAL; + } + attr.vp_id = vpath->device_id; attr.fifo_attr.callback = vxge_xmit_compl; attr.fifo_attr.txdl_term = vxge_tx_term; @@ -2024,6 +2062,7 @@ static int vxge_open_vpaths(struct vxgedev *vdev) vdev->config.fifo_indicate_max_pkts; vpath->ring.rx_vector_no = 0; vpath->ring.rx_csum = vdev->rx_csum; + vpath->ring.rx_hwts = vdev->rx_hwts; vpath->is_open = 1; vdev->vp_handles[i] = vpath->handle; vpath->ring.gro_enable = vdev->config.gro_enable; @@ -2062,18 +2101,18 @@ static irqreturn_t vxge_isr_napi(int irq, void *dev_id) struct __vxge_hw_device *hldev; u64 reason; enum vxge_hw_status status; - struct vxgedev *vdev = (struct vxgedev *) dev_id;; + struct vxgedev *vdev = (struct vxgedev *)dev_id; vxge_debug_intr(VXGE_TRACE, "%s:%d", __func__, __LINE__); dev = vdev->ndev; - hldev = (struct __vxge_hw_device *)pci_get_drvdata(vdev->pdev); + hldev = pci_get_drvdata(vdev->pdev); if (pci_channel_offline(vdev->pdev)) return IRQ_NONE; if (unlikely(!is_vxge_card_up(vdev))) - return IRQ_NONE; + return IRQ_HANDLED; status = vxge_hw_device_begin_irq(hldev, vdev->exec_mode, &reason); @@ -2301,8 +2340,8 @@ static void vxge_rem_msix_isr(struct vxgedev *vdev) static void vxge_rem_isr(struct vxgedev *vdev) { - struct __vxge_hw_device *hldev; - hldev = (struct __vxge_hw_device *) pci_get_drvdata(vdev->pdev); + struct __vxge_hw_device *hldev; + hldev = pci_get_drvdata(vdev->pdev); #ifdef CONFIG_PCI_MSI if (vdev->config.intr_type == MSI_X) { @@ -2542,8 +2581,8 @@ vxge_open(struct net_device *dev) vxge_debug_entryexit(VXGE_TRACE, "%s: %s:%d", dev->name, __func__, __LINE__); - vdev = (struct vxgedev *)netdev_priv(dev); - hldev = (struct __vxge_hw_device *) pci_get_drvdata(vdev->pdev); + vdev = netdev_priv(dev); + hldev = pci_get_drvdata(vdev->pdev); function_mode = vdev->config.device_hw_info.function_mode; /* make sure you have link off by default every time Nic is @@ -2598,6 +2637,8 @@ vxge_open(struct net_device *dev) goto out2; } } + printk(KERN_INFO "%s: Receive Hashing Offload %s\n", dev->name, + hldev->config.rth_en ? "enabled" : "disabled"); for (i = 0; i < vdev->no_of_vpath; i++) { vpath = &vdev->vpaths[i]; @@ -2683,9 +2724,10 @@ vxge_open(struct net_device *dev) vxge_os_timer(vdev->vp_reset_timer, vxge_poll_vp_reset, vdev, (HZ/2)); - if (vdev->vp_lockup_timer.function == NULL) - vxge_os_timer(vdev->vp_lockup_timer, - vxge_poll_vp_lockup, vdev, (HZ/2)); + /* There is no need to check for RxD leak and RxD lookup on Titan1A */ + if (vdev->titan1 && vdev->vp_lockup_timer.function == NULL) + vxge_os_timer(vdev->vp_lockup_timer, vxge_poll_vp_lockup, vdev, + HZ / 2); set_bit(__VXGE_STATE_CARD_UP, &vdev->state); @@ -2767,8 +2809,8 @@ static int do_vxge_close(struct net_device *dev, int do_io) vxge_debug_entryexit(VXGE_TRACE, "%s: %s:%d", dev->name, __func__, __LINE__); - vdev = (struct vxgedev *)netdev_priv(dev); - hldev = (struct __vxge_hw_device *) pci_get_drvdata(vdev->pdev); + vdev = netdev_priv(dev); + hldev = pci_get_drvdata(vdev->pdev); if (unlikely(!is_vxge_card_up(vdev))) return 0; @@ -2778,7 +2820,6 @@ static int do_vxge_close(struct net_device *dev, int do_io) while (test_and_set_bit(__VXGE_STATE_RESET_CARD, &vdev->state)) msleep(50); - clear_bit(__VXGE_STATE_CARD_UP, &vdev->state); if (do_io) { /* Put the vpath back in normal mode */ vpath_vector = vxge_mBIT(vdev->vpaths[0].device_id); @@ -2818,10 +2859,17 @@ static int do_vxge_close(struct net_device *dev, int do_io) smp_wmb(); } - del_timer_sync(&vdev->vp_lockup_timer); + + if (vdev->titan1) + del_timer_sync(&vdev->vp_lockup_timer); del_timer_sync(&vdev->vp_reset_timer); + if (do_io) + vxge_hw_device_wait_receive_idle(hldev); + + clear_bit(__VXGE_STATE_CARD_UP, &vdev->state); + /* Disable napi */ if (vdev->config.intr_type != MSI_X) napi_disable(&vdev->napi); @@ -2838,8 +2886,6 @@ static int do_vxge_close(struct net_device *dev, int do_io) if (do_io) vxge_hw_device_intr_disable(vdev->devh); - mdelay(1000); - vxge_rem_isr(vdev); vxge_napi_del_all(vdev); @@ -2954,6 +3000,101 @@ vxge_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *net_stats) return net_stats; } +static enum vxge_hw_status vxge_timestamp_config(struct vxgedev *vdev, + int enable) +{ + enum vxge_hw_status status; + u64 val64; + + /* Timestamp is passed to the driver via the FCS, therefore we + * must disable the FCS stripping by the adapter. Since this is + * required for the driver to load (due to a hardware bug), + * there is no need to do anything special here. + */ + if (enable) + val64 = VXGE_HW_XMAC_TIMESTAMP_EN | + VXGE_HW_XMAC_TIMESTAMP_USE_LINK_ID(0) | + VXGE_HW_XMAC_TIMESTAMP_INTERVAL(0); + else + val64 = 0; + + status = vxge_hw_mgmt_reg_write(vdev->devh, + vxge_hw_mgmt_reg_type_mrpcim, + 0, + offsetof(struct vxge_hw_mrpcim_reg, + xmac_timestamp), + val64); + vxge_hw_device_flush_io(vdev->devh); + return status; +} + +static int vxge_hwtstamp_ioctl(struct vxgedev *vdev, void __user *data) +{ + struct hwtstamp_config config; + enum vxge_hw_status status; + int i; + + if (copy_from_user(&config, data, sizeof(config))) + return -EFAULT; + + /* reserved for future extensions */ + if (config.flags) + return -EINVAL; + + /* Transmit HW Timestamp not supported */ + switch (config.tx_type) { + case HWTSTAMP_TX_OFF: + break; + case HWTSTAMP_TX_ON: + default: + return -ERANGE; + } + + switch (config.rx_filter) { + case HWTSTAMP_FILTER_NONE: + status = vxge_timestamp_config(vdev, 0); + if (status != VXGE_HW_OK) + return -EFAULT; + + vdev->rx_hwts = 0; + config.rx_filter = HWTSTAMP_FILTER_NONE; + break; + + case HWTSTAMP_FILTER_ALL: + case HWTSTAMP_FILTER_SOME: + case HWTSTAMP_FILTER_PTP_V1_L4_EVENT: + case HWTSTAMP_FILTER_PTP_V1_L4_SYNC: + case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ: + case HWTSTAMP_FILTER_PTP_V2_L4_EVENT: + case HWTSTAMP_FILTER_PTP_V2_L4_SYNC: + case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ: + case HWTSTAMP_FILTER_PTP_V2_L2_EVENT: + case HWTSTAMP_FILTER_PTP_V2_L2_SYNC: + case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ: + case HWTSTAMP_FILTER_PTP_V2_EVENT: + case HWTSTAMP_FILTER_PTP_V2_SYNC: + case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ: + status = vxge_timestamp_config(vdev, 1); + if (status != VXGE_HW_OK) + return -EFAULT; + + vdev->rx_hwts = 1; + config.rx_filter = HWTSTAMP_FILTER_ALL; + break; + + default: + return -ERANGE; + } + + for (i = 0; i < vdev->no_of_vpath; i++) + vdev->vpaths[i].ring.rx_hwts = vdev->rx_hwts; + + if (copy_to_user(data, &config, sizeof(config))) + return -EFAULT; + + return 0; +} + /** * vxge_ioctl * @dev: Device pointer. @@ -2966,7 +3107,20 @@ vxge_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *net_stats) */ static int vxge_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { - return -EOPNOTSUPP; + struct vxgedev *vdev = netdev_priv(dev); + int ret; + + switch (cmd) { + case SIOCSHWTSTAMP: + ret = vxge_hwtstamp_ioctl(vdev, rq->ifr_data); + if (ret) + return ret; + break; + default: + return -EOPNOTSUPP; + } + + return 0; } /** @@ -2984,7 +3138,7 @@ vxge_tx_watchdog(struct net_device *dev) vxge_debug_entryexit(VXGE_TRACE, "%s:%d", __func__, __LINE__); - vdev = (struct vxgedev *)netdev_priv(dev); + vdev = netdev_priv(dev); vdev->cric_err_event = VXGE_HW_EVENT_RESET_START; @@ -3012,7 +3166,7 @@ vxge_vlan_rx_register(struct net_device *dev, struct vlan_group *grp) vxge_debug_entryexit(VXGE_TRACE, "%s:%d", __func__, __LINE__); - vdev = (struct vxgedev *)netdev_priv(dev); + vdev = netdev_priv(dev); vpath = &vdev->vpaths[0]; if ((NULL == grp) && (vpath->is_open)) { @@ -3061,7 +3215,7 @@ vxge_vlan_rx_add_vid(struct net_device *dev, unsigned short vid) struct vxge_vpath *vpath; int vp_id; - vdev = (struct vxgedev *)netdev_priv(dev); + vdev = netdev_priv(dev); /* Add these vlan to the vid table */ for (vp_id = 0; vp_id < vdev->no_of_vpath; vp_id++) { @@ -3088,7 +3242,7 @@ vxge_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) vxge_debug_entryexit(VXGE_TRACE, "%s:%d", __func__, __LINE__); - vdev = (struct vxgedev *)netdev_priv(dev); + vdev = netdev_priv(dev); vlan_group_set_device(vdev->vlgrp, vid, NULL); @@ -3125,6 +3279,19 @@ static const struct net_device_ops vxge_netdev_ops = { #endif }; +static int __devinit vxge_device_revision(struct vxgedev *vdev) +{ + int ret; + u8 revision; + + ret = pci_read_config_byte(vdev->pdev, PCI_REVISION_ID, &revision); + if (ret) + return -EIO; + + vdev->titan1 = (revision == VXGE_HW_TITAN1_PCI_REVISION); + return 0; +} + static int __devinit vxge_device_register(struct __vxge_hw_device *hldev, struct vxge_config *config, int high_dma, int no_of_vpath, @@ -3163,6 +3330,11 @@ static int __devinit vxge_device_register(struct __vxge_hw_device *hldev, vdev->pdev = hldev->pdev; memcpy(&vdev->config, config, sizeof(struct vxge_config)); vdev->rx_csum = 1; /* Enable Rx CSUM by default. */ + vdev->rx_hwts = 0; + + ret = vxge_device_revision(vdev); + if (ret < 0) + goto _out1; SET_NETDEV_DEV(ndev, &vdev->pdev->dev); @@ -3178,6 +3350,11 @@ static int __devinit vxge_device_register(struct __vxge_hw_device *hldev, vxge_initialize_ethtool_ops(ndev); + if (vdev->config.rth_steering != NO_STEERING) { + ndev->features |= NETIF_F_RXHASH; + hldev->config.rth_en = VXGE_HW_RTH_ENABLE; + } + /* Allocate memory for vpath */ vdev->vpaths = kzalloc((sizeof(struct vxge_vpath)) * no_of_vpath, GFP_KERNEL); @@ -3227,6 +3404,7 @@ static int __devinit vxge_device_register(struct __vxge_hw_device *hldev, "%s: Ethernet device registered", ndev->name); + hldev->ndev = ndev; *vdev_out = vdev; /* Resetting the Device stats */ @@ -3261,36 +3439,29 @@ _out0: * * This function will unregister and free network device */ -static void -vxge_device_unregister(struct __vxge_hw_device *hldev) +static void vxge_device_unregister(struct __vxge_hw_device *hldev) { struct vxgedev *vdev; struct net_device *dev; char buf[IFNAMSIZ]; -#if ((VXGE_DEBUG_INIT & VXGE_DEBUG_MASK) || \ - (VXGE_DEBUG_ENTRYEXIT & VXGE_DEBUG_MASK)) - u32 level_trace; -#endif dev = hldev->ndev; vdev = netdev_priv(dev); -#if ((VXGE_DEBUG_INIT & VXGE_DEBUG_MASK) || \ - (VXGE_DEBUG_ENTRYEXIT & VXGE_DEBUG_MASK)) - level_trace = vdev->level_trace; -#endif - vxge_debug_entryexit(level_trace, - "%s: %s:%d", vdev->ndev->name, __func__, __LINE__); - memcpy(buf, vdev->ndev->name, IFNAMSIZ); + vxge_debug_entryexit(vdev->level_trace, "%s: %s:%d", vdev->ndev->name, + __func__, __LINE__); + + strncpy(buf, dev->name, IFNAMSIZ); /* in 2.6 will call stop() if device is up */ unregister_netdev(dev); flush_scheduled_work(); - vxge_debug_init(level_trace, "%s: ethernet device unregistered", buf); - vxge_debug_entryexit(level_trace, - "%s: %s:%d Exiting...", buf, __func__, __LINE__); + vxge_debug_init(vdev->level_trace, "%s: ethernet device unregistered", + buf); + vxge_debug_entryexit(vdev->level_trace, "%s: %s:%d Exiting...", buf, + __func__, __LINE__); } /* @@ -3304,7 +3475,7 @@ vxge_callback_crit_err(struct __vxge_hw_device *hldev, enum vxge_hw_event type, u64 vp_id) { struct net_device *dev = hldev->ndev; - struct vxgedev *vdev = (struct vxgedev *)netdev_priv(dev); + struct vxgedev *vdev = netdev_priv(dev); struct vxge_vpath *vpath = NULL; int vpath_idx; @@ -3751,9 +3922,6 @@ static void __devinit vxge_print_parm(struct vxgedev *vdev, u64 vpath_mask) vxge_debug_init(VXGE_TRACE, "%s: MAC Address learning enabled", vdev->ndev->name); - vxge_debug_init(VXGE_TRACE, - "%s: Rx doorbell mode enabled", vdev->ndev->name); - for (i = 0; i < VXGE_HW_MAX_VIRTUAL_PATHS; i++) { if (!vxge_bVALn(vpath_mask, i, 1)) continue; @@ -3766,14 +3934,6 @@ static void __devinit vxge_print_parm(struct vxgedev *vdev, u64 vpath_mask) ((struct __vxge_hw_device *)(vdev->devh))-> config.vp_config[i].rpa_strip_vlan_tag ? "Enabled" : "Disabled"); - vxge_debug_init(VXGE_TRACE, - "%s: Ring blocks : %d", vdev->ndev->name, - ((struct __vxge_hw_device *)(vdev->devh))-> - config.vp_config[i].ring.ring_blocks); - vxge_debug_init(VXGE_TRACE, - "%s: Fifo blocks : %d", vdev->ndev->name, - ((struct __vxge_hw_device *)(vdev->devh))-> - config.vp_config[i].fifo.fifo_blocks); vxge_debug_ll_config(VXGE_TRACE, "%s: Max frags : %d", vdev->ndev->name, ((struct __vxge_hw_device *)(vdev->devh))-> @@ -3813,8 +3973,7 @@ static int vxge_pm_resume(struct pci_dev *pdev) static pci_ers_result_t vxge_io_error_detected(struct pci_dev *pdev, pci_channel_state_t state) { - struct __vxge_hw_device *hldev = - (struct __vxge_hw_device *) pci_get_drvdata(pdev); + struct __vxge_hw_device *hldev = pci_get_drvdata(pdev); struct net_device *netdev = hldev->ndev; netif_device_detach(netdev); @@ -3843,8 +4002,7 @@ static pci_ers_result_t vxge_io_error_detected(struct pci_dev *pdev, */ static pci_ers_result_t vxge_io_slot_reset(struct pci_dev *pdev) { - struct __vxge_hw_device *hldev = - (struct __vxge_hw_device *) pci_get_drvdata(pdev); + struct __vxge_hw_device *hldev = pci_get_drvdata(pdev); struct net_device *netdev = hldev->ndev; struct vxgedev *vdev = netdev_priv(netdev); @@ -3869,8 +4027,7 @@ static pci_ers_result_t vxge_io_slot_reset(struct pci_dev *pdev) */ static void vxge_io_resume(struct pci_dev *pdev) { - struct __vxge_hw_device *hldev = - (struct __vxge_hw_device *) pci_get_drvdata(pdev); + struct __vxge_hw_device *hldev = pci_get_drvdata(pdev); struct net_device *netdev = hldev->ndev; if (netif_running(netdev)) { @@ -3914,6 +4071,142 @@ static inline u32 vxge_get_num_vfs(u64 function_mode) return num_functions; } +int vxge_fw_upgrade(struct vxgedev *vdev, char *fw_name, int override) +{ + struct __vxge_hw_device *hldev = vdev->devh; + u32 maj, min, bld, cmaj, cmin, cbld; + enum vxge_hw_status status; + const struct firmware *fw; + int ret; + + ret = request_firmware(&fw, fw_name, &vdev->pdev->dev); + if (ret) { + vxge_debug_init(VXGE_ERR, "%s: Firmware file '%s' not found", + VXGE_DRIVER_NAME, fw_name); + goto out; + } + + /* Load the new firmware onto the adapter */ + status = vxge_update_fw_image(hldev, fw->data, fw->size); + if (status != VXGE_HW_OK) { + vxge_debug_init(VXGE_ERR, + "%s: FW image download to adapter failed '%s'.", + VXGE_DRIVER_NAME, fw_name); + ret = -EIO; + goto out; + } + + /* Read the version of the new firmware */ + status = vxge_hw_upgrade_read_version(hldev, &maj, &min, &bld); + if (status != VXGE_HW_OK) { + vxge_debug_init(VXGE_ERR, + "%s: Upgrade read version failed '%s'.", + VXGE_DRIVER_NAME, fw_name); + ret = -EIO; + goto out; + } + + cmaj = vdev->config.device_hw_info.fw_version.major; + cmin = vdev->config.device_hw_info.fw_version.minor; + cbld = vdev->config.device_hw_info.fw_version.build; + /* It's possible the version in /lib/firmware is not the latest version. + * If so, we could get into a loop of trying to upgrade to the latest + * and flashing the older version. + */ + if (VXGE_FW_VER(maj, min, bld) == VXGE_FW_VER(cmaj, cmin, cbld) && + !override) { + ret = -EINVAL; + goto out; + } + + printk(KERN_NOTICE "Upgrade to firmware version %d.%d.%d commencing\n", + maj, min, bld); + + /* Flash the adapter with the new firmware */ + status = vxge_hw_flash_fw(hldev); + if (status != VXGE_HW_OK) { + vxge_debug_init(VXGE_ERR, "%s: Upgrade commit failed '%s'.", + VXGE_DRIVER_NAME, fw_name); + ret = -EIO; + goto out; + } + + printk(KERN_NOTICE "Upgrade of firmware successful! Adapter must be " + "hard reset before using, thus requiring a system reboot or a " + "hotplug event.\n"); + +out: + return ret; +} + +static int vxge_probe_fw_update(struct vxgedev *vdev) +{ + u32 maj, min, bld; + int ret, gpxe = 0; + char *fw_name; + + maj = vdev->config.device_hw_info.fw_version.major; + min = vdev->config.device_hw_info.fw_version.minor; + bld = vdev->config.device_hw_info.fw_version.build; + + if (VXGE_FW_VER(maj, min, bld) == VXGE_CERT_FW_VER) + return 0; + + /* Ignore the build number when determining if the current firmware is + * "too new" to load the driver + */ + if (VXGE_FW_VER(maj, min, 0) > VXGE_CERT_FW_VER) { + vxge_debug_init(VXGE_ERR, "%s: Firmware newer than last known " + "version, unable to load driver\n", + VXGE_DRIVER_NAME); + return -EINVAL; + } + + /* Firmware 1.4.4 and older cannot be upgraded, and is too ancient to + * work with this driver. + */ + if (VXGE_FW_VER(maj, min, bld) <= VXGE_FW_DEAD_VER) { + vxge_debug_init(VXGE_ERR, "%s: Firmware %d.%d.%d cannot be " + "upgraded\n", VXGE_DRIVER_NAME, maj, min, bld); + return -EINVAL; + } + + /* If file not specified, determine gPXE or not */ + if (VXGE_FW_VER(maj, min, bld) >= VXGE_EPROM_FW_VER) { + int i; + for (i = 0; i < VXGE_HW_MAX_ROM_IMAGES; i++) + if (vdev->devh->eprom_versions[i]) { + gpxe = 1; + break; + } + } + if (gpxe) + fw_name = "vxge/X3fw-pxe.ncf"; + else + fw_name = "vxge/X3fw.ncf"; + + ret = vxge_fw_upgrade(vdev, fw_name, 0); + /* -EINVAL and -ENOENT are not fatal errors for flashing firmware on + * probe, so ignore them + */ + if (ret != -EINVAL && ret != -ENOENT) + return -EIO; + else + ret = 0; + + if (VXGE_FW_VER(VXGE_CERT_FW_VER_MAJOR, VXGE_CERT_FW_VER_MINOR, 0) > + VXGE_FW_VER(maj, min, 0)) { + vxge_debug_init(VXGE_ERR, "%s: Firmware %d.%d.%d is too old to" + " be used with this driver.\n" + "Please get the latest version from " + "ftp://ftp.s2io.com/pub/X3100-Drivers/FIRMWARE", + VXGE_DRIVER_NAME, maj, min, bld); + return -EINVAL; + } + + return ret; +} + /** * vxge_probe * @pdev : structure containing the PCI related information of the device. @@ -3928,7 +4221,7 @@ static inline u32 vxge_get_num_vfs(u64 function_mode) static int __devinit vxge_probe(struct pci_dev *pdev, const struct pci_device_id *pre) { - struct __vxge_hw_device *hldev; + struct __vxge_hw_device *hldev; enum vxge_hw_status status; int ret; int high_dma = 0; @@ -4072,16 +4365,6 @@ vxge_probe(struct pci_dev *pdev, const struct pci_device_id *pre) goto _exit3; } - if (ll_config->device_hw_info.fw_version.major != - VXGE_DRIVER_FW_VERSION_MAJOR) { - vxge_debug_init(VXGE_ERR, - "%s: Incorrect firmware version." - "Please upgrade the firmware to version 1.x.x", - VXGE_DRIVER_NAME); - ret = -EINVAL; - goto _exit3; - } - vpath_mask = ll_config->device_hw_info.vpath_mask; if (vpath_mask == 0) { vxge_debug_ll_config(VXGE_TRACE, @@ -4145,11 +4428,37 @@ vxge_probe(struct pci_dev *pdev, const struct pci_device_id *pre) goto _exit3; } + if (VXGE_FW_VER(ll_config->device_hw_info.fw_version.major, + ll_config->device_hw_info.fw_version.minor, + ll_config->device_hw_info.fw_version.build) >= + VXGE_EPROM_FW_VER) { + struct eprom_image img[VXGE_HW_MAX_ROM_IMAGES]; + + status = vxge_hw_vpath_eprom_img_ver_get(hldev, img); + if (status != VXGE_HW_OK) { + vxge_debug_init(VXGE_ERR, "%s: Reading of EPROM failed", + VXGE_DRIVER_NAME); + /* This is a non-fatal error, continue */ + } + + for (i = 0; i < VXGE_HW_MAX_ROM_IMAGES; i++) { + hldev->eprom_versions[i] = img[i].version; + if (!img[i].is_valid) + break; + vxge_debug_init(VXGE_TRACE, "%s: EPROM %d, version " + "%d.%d.%d.%d\n", VXGE_DRIVER_NAME, i, + VXGE_EPROM_IMG_MAJOR(img[i].version), + VXGE_EPROM_IMG_MINOR(img[i].version), + VXGE_EPROM_IMG_FIX(img[i].version), + VXGE_EPROM_IMG_BUILD(img[i].version)); + } + } + /* if FCS stripping is not disabled in MAC fail driver load */ - if (vxge_hw_vpath_strip_fcs_check(hldev, vpath_mask) != VXGE_HW_OK) { - vxge_debug_init(VXGE_ERR, - "%s: FCS stripping is not disabled in MAC" - " failing driver load", VXGE_DRIVER_NAME); + status = vxge_hw_vpath_strip_fcs_check(hldev, vpath_mask); + if (status != VXGE_HW_OK) { + vxge_debug_init(VXGE_ERR, "%s: FCS stripping is enabled in MAC" + " failing driver load", VXGE_DRIVER_NAME); ret = -EINVAL; goto _exit4; } @@ -4163,28 +4472,32 @@ vxge_probe(struct pci_dev *pdev, const struct pci_device_id *pre) ll_config->fifo_indicate_max_pkts = VXGE_FIFO_INDICATE_MAX_PKTS; ll_config->addr_learn_en = addr_learn_en; ll_config->rth_algorithm = RTH_ALG_JENKINS; - ll_config->rth_hash_type_tcpipv4 = VXGE_HW_RING_HASH_TYPE_TCP_IPV4; - ll_config->rth_hash_type_ipv4 = VXGE_HW_RING_HASH_TYPE_NONE; - ll_config->rth_hash_type_tcpipv6 = VXGE_HW_RING_HASH_TYPE_NONE; - ll_config->rth_hash_type_ipv6 = VXGE_HW_RING_HASH_TYPE_NONE; - ll_config->rth_hash_type_tcpipv6ex = VXGE_HW_RING_HASH_TYPE_NONE; - ll_config->rth_hash_type_ipv6ex = VXGE_HW_RING_HASH_TYPE_NONE; + ll_config->rth_hash_type_tcpipv4 = 1; + ll_config->rth_hash_type_ipv4 = 0; + ll_config->rth_hash_type_tcpipv6 = 0; + ll_config->rth_hash_type_ipv6 = 0; + ll_config->rth_hash_type_tcpipv6ex = 0; + ll_config->rth_hash_type_ipv6ex = 0; ll_config->rth_bkt_sz = RTH_BUCKET_SIZE; ll_config->tx_pause_enable = VXGE_PAUSE_CTRL_ENABLE; ll_config->rx_pause_enable = VXGE_PAUSE_CTRL_ENABLE; - if (vxge_device_register(hldev, ll_config, high_dma, no_of_vpath, - &vdev)) { + ret = vxge_device_register(hldev, ll_config, high_dma, no_of_vpath, + &vdev); + if (ret) { ret = -EINVAL; goto _exit4; } + ret = vxge_probe_fw_update(vdev); + if (ret) + goto _exit5; + vxge_hw_device_debug_set(hldev, VXGE_TRACE, VXGE_COMPONENT_LL); VXGE_COPY_DEBUG_INFO_TO_LL(vdev, vxge_hw_device_error_level_get(hldev), vxge_hw_device_trace_level_get(hldev)); /* set private HW device info */ - hldev->ndev = vdev->ndev; vdev->mtu = VXGE_HW_DEFAULT_MTU; vdev->bar0 = attr.bar0; vdev->max_vpath_supported = max_vpath_supported; @@ -4278,15 +4591,13 @@ vxge_probe(struct pci_dev *pdev, const struct pci_device_id *pre) /* Copy the station mac address to the list */ for (i = 0; i < vdev->no_of_vpath; i++) { - entry = (struct vxge_mac_addrs *) - kzalloc(sizeof(struct vxge_mac_addrs), - GFP_KERNEL); + entry = kzalloc(sizeof(struct vxge_mac_addrs), GFP_KERNEL); if (NULL == entry) { vxge_debug_init(VXGE_ERR, "%s: mac_addr_list : memory allocation failed", vdev->ndev->name); ret = -EPERM; - goto _exit5; + goto _exit6; } macaddr = (u8 *)&entry->macaddr; memcpy(macaddr, vdev->ndev->dev_addr, ETH_ALEN); @@ -4326,10 +4637,10 @@ vxge_probe(struct pci_dev *pdev, const struct pci_device_id *pre) kfree(ll_config); return 0; -_exit5: +_exit6: for (i = 0; i < vdev->no_of_vpath; i++) vxge_free_mac_add_list(&vdev->vpaths[i]); - +_exit5: vxge_device_unregister(hldev); _exit4: pci_disable_sriov(pdev); @@ -4354,34 +4665,25 @@ _exit0: * Description: This function is called by the Pci subsystem to release a * PCI device and free up all resource held up by the device. */ -static void __devexit -vxge_remove(struct pci_dev *pdev) +static void __devexit vxge_remove(struct pci_dev *pdev) { - struct __vxge_hw_device *hldev; + struct __vxge_hw_device *hldev; struct vxgedev *vdev = NULL; struct net_device *dev; int i = 0; -#if ((VXGE_DEBUG_INIT & VXGE_DEBUG_MASK) || \ - (VXGE_DEBUG_ENTRYEXIT & VXGE_DEBUG_MASK)) - u32 level_trace; -#endif - hldev = (struct __vxge_hw_device *) pci_get_drvdata(pdev); + hldev = pci_get_drvdata(pdev); if (hldev == NULL) return; + dev = hldev->ndev; vdev = netdev_priv(dev); -#if ((VXGE_DEBUG_INIT & VXGE_DEBUG_MASK) || \ - (VXGE_DEBUG_ENTRYEXIT & VXGE_DEBUG_MASK)) - level_trace = vdev->level_trace; -#endif - vxge_debug_entryexit(level_trace, - "%s:%d", __func__, __LINE__); + vxge_debug_entryexit(vdev->level_trace, "%s:%d", __func__, __LINE__); - vxge_debug_init(level_trace, - "%s : removing PCI device...", __func__); + vxge_debug_init(vdev->level_trace, "%s : removing PCI device...", + __func__); vxge_device_unregister(hldev); for (i = 0; i < vdev->no_of_vpath; i++) { @@ -4399,16 +4701,16 @@ vxge_remove(struct pci_dev *pdev) /* we are safe to free it now */ free_netdev(dev); - vxge_debug_init(level_trace, - "%s:%d Device unregistered", __func__, __LINE__); + vxge_debug_init(vdev->level_trace, "%s:%d Device unregistered", + __func__, __LINE__); vxge_hw_device_terminate(hldev); pci_disable_device(pdev); pci_release_regions(pdev); pci_set_drvdata(pdev, NULL); - vxge_debug_entryexit(level_trace, - "%s:%d Exiting...", __func__, __LINE__); + vxge_debug_entryexit(vdev->level_trace, "%s:%d Exiting...", __func__, + __LINE__); } static struct pci_error_handlers vxge_err_handler = { diff --git a/drivers/net/vxge/vxge-main.h b/drivers/net/vxge/vxge-main.h index de64536cb7d0..953cb0ded3e1 100644 --- a/drivers/net/vxge/vxge-main.h +++ b/drivers/net/vxge/vxge-main.h @@ -29,6 +29,9 @@ #define PCI_DEVICE_ID_TITAN_WIN 0x5733 #define PCI_DEVICE_ID_TITAN_UNI 0x5833 +#define VXGE_HW_TITAN1_PCI_REVISION 1 +#define VXGE_HW_TITAN1A_PCI_REVISION 2 + #define VXGE_USE_DEFAULT 0xffffffff #define VXGE_HW_VPATH_MSIX_ACTIVE 4 #define VXGE_ALARM_MSIX_ID 2 @@ -53,11 +56,13 @@ #define VXGE_TTI_BTIMER_VAL 250000 -#define VXGE_TTI_LTIMER_VAL 1000 -#define VXGE_TTI_RTIMER_VAL 0 -#define VXGE_RTI_BTIMER_VAL 250 -#define VXGE_RTI_LTIMER_VAL 100 -#define VXGE_RTI_RTIMER_VAL 0 +#define VXGE_TTI_LTIMER_VAL 1000 +#define VXGE_T1A_TTI_LTIMER_VAL 80 +#define VXGE_TTI_RTIMER_VAL 0 +#define VXGE_T1A_TTI_RTIMER_VAL 400 +#define VXGE_RTI_BTIMER_VAL 250 +#define VXGE_RTI_LTIMER_VAL 100 +#define VXGE_RTI_RTIMER_VAL 0 #define VXGE_FIFO_INDICATE_MAX_PKTS VXGE_DEF_FIFO_LENGTH #define VXGE_ISR_POLLING_CNT 8 #define VXGE_MAX_CONFIG_DEV 0xFF @@ -76,14 +81,32 @@ #define TTI_TX_UFC_B 40 #define TTI_TX_UFC_C 60 #define TTI_TX_UFC_D 100 +#define TTI_T1A_TX_UFC_A 30 +#define TTI_T1A_TX_UFC_B 80 +/* Slope - (max_mtu - min_mtu)/(max_mtu_ufc - min_mtu_ufc) */ +/* Slope - 93 */ +/* 60 - 9k Mtu, 140 - 1.5k mtu */ +#define TTI_T1A_TX_UFC_C(mtu) (60 + ((VXGE_HW_MAX_MTU - mtu) / 93)) + +/* Slope - 37 */ +/* 100 - 9k Mtu, 300 - 1.5k mtu */ +#define TTI_T1A_TX_UFC_D(mtu) (100 + ((VXGE_HW_MAX_MTU - mtu) / 37)) + + +#define RTI_RX_URANGE_A 5 +#define RTI_RX_URANGE_B 15 +#define RTI_RX_URANGE_C 40 +#define RTI_T1A_RX_URANGE_A 1 +#define RTI_T1A_RX_URANGE_B 20 +#define RTI_T1A_RX_URANGE_C 50 +#define RTI_RX_UFC_A 1 +#define RTI_RX_UFC_B 5 +#define RTI_RX_UFC_C 10 +#define RTI_RX_UFC_D 15 +#define RTI_T1A_RX_UFC_B 20 +#define RTI_T1A_RX_UFC_C 50 +#define RTI_T1A_RX_UFC_D 60 -#define RTI_RX_URANGE_A 5 -#define RTI_RX_URANGE_B 15 -#define RTI_RX_URANGE_C 40 -#define RTI_RX_UFC_A 1 -#define RTI_RX_UFC_B 5 -#define RTI_RX_UFC_C 10 -#define RTI_RX_UFC_D 15 /* Milli secs timer period */ #define VXGE_TIMER_DELAY 10000 @@ -145,15 +168,15 @@ struct vxge_config { int addr_learn_en; - int rth_steering; - int rth_algorithm; - int rth_hash_type_tcpipv4; - int rth_hash_type_ipv4; - int rth_hash_type_tcpipv6; - int rth_hash_type_ipv6; - int rth_hash_type_tcpipv6ex; - int rth_hash_type_ipv6ex; - int rth_bkt_sz; + u32 rth_steering:2, + rth_algorithm:2, + rth_hash_type_tcpipv4:1, + rth_hash_type_ipv4:1, + rth_hash_type_tcpipv6:1, + rth_hash_type_ipv6:1, + rth_hash_type_tcpipv6ex:1, + rth_hash_type_ipv6ex:1, + rth_bkt_sz:8; int rth_jhash_golden_ratio; int tx_steering_type; int fifo_indicate_max_pkts; @@ -248,8 +271,9 @@ struct vxge_ring { */ int driver_id; - /* copy of the flag indicating whether rx_csum is to be used */ - u32 rx_csum; + /* copy of the flag indicating whether rx_csum is to be used */ + u32 rx_csum:1, + rx_hwts:1; int pkts_processed; int budget; @@ -327,7 +351,9 @@ struct vxgedev { u16 all_multi_flg; /* A flag indicating whether rx_csum is to be used or not. */ - u32 rx_csum; + u32 rx_csum:1, + rx_hwts:1, + titan1:1; struct vxge_msix_entry *vxge_entries; struct msix_entry *entries; @@ -387,8 +413,6 @@ struct vxge_tx_priv { static int p = val; \ module_param(p, int, 0) -#define vxge_os_bug(fmt...) { printk(fmt); BUG(); } - #define vxge_os_timer(timer, handle, arg, exp) do { \ init_timer(&timer); \ timer.function = handle; \ @@ -397,6 +421,11 @@ struct vxge_tx_priv { } while (0); extern void vxge_initialize_ethtool_ops(struct net_device *ndev); + +enum vxge_hw_status vxge_reset_all_vpaths(struct vxgedev *vdev); + +int vxge_fw_upgrade(struct vxgedev *vdev, char *fw_name, int override); + /** * #define VXGE_DEBUG_INIT: debug for initialization functions * #define VXGE_DEBUG_TX : debug transmit related functions diff --git a/drivers/net/vxge/vxge-reg.h b/drivers/net/vxge/vxge-reg.h index 3dd5c9615ef9..3e658b175947 100644 --- a/drivers/net/vxge/vxge-reg.h +++ b/drivers/net/vxge/vxge-reg.h @@ -49,6 +49,33 @@ #define VXGE_HW_TITAN_VPMGMT_REG_SPACES 17 #define VXGE_HW_TITAN_VPATH_REG_SPACES 17 +#define VXGE_HW_FW_API_GET_EPROM_REV 31 + +#define VXGE_EPROM_IMG_MAJOR(val) (u32) vxge_bVALn(val, 48, 4) +#define VXGE_EPROM_IMG_MINOR(val) (u32) vxge_bVALn(val, 52, 4) +#define VXGE_EPROM_IMG_FIX(val) (u32) vxge_bVALn(val, 56, 4) +#define VXGE_EPROM_IMG_BUILD(val) (u32) vxge_bVALn(val, 60, 4) + +#define VXGE_HW_GET_EPROM_IMAGE_INDEX(val) vxge_bVALn(val, 16, 8) +#define VXGE_HW_GET_EPROM_IMAGE_VALID(val) vxge_bVALn(val, 31, 1) +#define VXGE_HW_GET_EPROM_IMAGE_TYPE(val) vxge_bVALn(val, 40, 8) +#define VXGE_HW_GET_EPROM_IMAGE_REV(val) vxge_bVALn(val, 48, 16) +#define VXGE_HW_RTS_ACCESS_STEER_ROM_IMAGE_INDEX(val) vxge_vBIT(val, 16, 8) + +#define VXGE_HW_FW_API_GET_FUNC_MODE 29 +#define VXGE_HW_GET_FUNC_MODE_VAL(val) (val & 0xFF) + +#define VXGE_HW_FW_UPGRADE_MEMO 13 +#define VXGE_HW_FW_UPGRADE_ACTION 16 +#define VXGE_HW_FW_UPGRADE_OFFSET_START 2 +#define VXGE_HW_FW_UPGRADE_OFFSET_SEND 3 +#define VXGE_HW_FW_UPGRADE_OFFSET_COMMIT 4 +#define VXGE_HW_FW_UPGRADE_OFFSET_READ 5 + +#define VXGE_HW_FW_UPGRADE_BLK_SIZE 16 +#define VXGE_HW_UPGRADE_GET_RET_ERR_CODE(val) (val & 0xff) +#define VXGE_HW_UPGRADE_GET_SEC_ERR_CODE(val) ((val >> 8) & 0xff) + #define VXGE_HW_ASIC_MODE_RESERVED 0 #define VXGE_HW_ASIC_MODE_NO_IOV 1 #define VXGE_HW_ASIC_MODE_SR_IOV 2 @@ -165,13 +192,13 @@ #define VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_ETYPE 2 #define VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_PN 3 #define VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_RTH_GEN_CFG 5 -#define VXGE_HW_RTS_ACS_STEER_CTRL_DATA_STRUCT_SEL_RTH_SOLO_IT 6 +#define VXGE_HW_RTS_ACS_STEER_CTRL_DATA_STRUCT_SEL_RTH_SOLO_IT 6 #define VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_RTH_JHASH_CFG 7 #define VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_RTH_MASK 8 #define VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_RTH_KEY 9 #define VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_QOS 10 #define VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_DS 11 -#define VXGE_HW_RTS_ACS_STEER_CTRL_DATA_STRUCT_SEL_RTH_MULTI_IT 12 +#define VXGE_HW_RTS_ACS_STEER_CTRL_DATA_STRUCT_SEL_RTH_MULTI_IT 12 #define VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_FW_MEMO 13 #define VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_DA_MAC_ADDR(bits) \ @@ -437,6 +464,7 @@ #define VXGE_HW_RTS_ACCESS_STEER_DATA1_GET_FLASH_VER_BUILD(bits) \ vxge_bVALn(bits, 48, 16) #define VXGE_HW_RTS_ACCESS_STEER_DATA1_FLASH_VER_BUILD vxge_vBIT(val, 48, 16) +#define VXGE_HW_RTS_ACCESS_STEER_CTRL_GET_ACTION(bits) vxge_bVALn(bits, 0, 8) #define VXGE_HW_SRPCIM_TO_VPATH_ALARM_REG_GET_PPIF_SRPCIM_TO_VPATH_ALARM(bits)\ vxge_bVALn(bits, 0, 18) @@ -3998,6 +4026,7 @@ struct vxge_hw_vpath_reg { #define VXGE_HW_PRC_CFG6_L4_CPC_TRSFR_CODE_EN vxge_mBIT(9) #define VXGE_HW_PRC_CFG6_RXD_CRXDT(val) vxge_vBIT(val, 23, 9) #define VXGE_HW_PRC_CFG6_RXD_SPAT(val) vxge_vBIT(val, 36, 9) +#define VXGE_HW_PRC_CFG6_GET_RXD_SPAT(val) vxge_bVALn(val, 36, 9) /*0x00a78*/ u64 prc_cfg7; #define VXGE_HW_PRC_CFG7_SCATTER_MODE(val) vxge_vBIT(val, 6, 2) #define VXGE_HW_PRC_CFG7_SMART_SCAT_EN vxge_mBIT(11) diff --git a/drivers/net/vxge/vxge-traffic.h b/drivers/net/vxge/vxge-traffic.h index 9890d4d596d0..1fceee876228 100644 --- a/drivers/net/vxge/vxge-traffic.h +++ b/drivers/net/vxge/vxge-traffic.h @@ -1904,34 +1904,6 @@ enum vxge_hw_ring_tcode { VXGE_HW_RING_T_CODE_MULTI_ERR = 0xF }; -/** - * enum enum vxge_hw_ring_hash_type - RTH hash types - * @VXGE_HW_RING_HASH_TYPE_NONE: No Hash - * @VXGE_HW_RING_HASH_TYPE_TCP_IPV4: TCP IPv4 - * @VXGE_HW_RING_HASH_TYPE_UDP_IPV4: UDP IPv4 - * @VXGE_HW_RING_HASH_TYPE_IPV4: IPv4 - * @VXGE_HW_RING_HASH_TYPE_TCP_IPV6: TCP IPv6 - * @VXGE_HW_RING_HASH_TYPE_UDP_IPV6: UDP IPv6 - * @VXGE_HW_RING_HASH_TYPE_IPV6: IPv6 - * @VXGE_HW_RING_HASH_TYPE_TCP_IPV6_EX: TCP IPv6 extension - * @VXGE_HW_RING_HASH_TYPE_UDP_IPV6_EX: UDP IPv6 extension - * @VXGE_HW_RING_HASH_TYPE_IPV6_EX: IPv6 extension - * - * RTH hash types - */ -enum vxge_hw_ring_hash_type { - VXGE_HW_RING_HASH_TYPE_NONE = 0x0, - VXGE_HW_RING_HASH_TYPE_TCP_IPV4 = 0x1, - VXGE_HW_RING_HASH_TYPE_UDP_IPV4 = 0x2, - VXGE_HW_RING_HASH_TYPE_IPV4 = 0x3, - VXGE_HW_RING_HASH_TYPE_TCP_IPV6 = 0x4, - VXGE_HW_RING_HASH_TYPE_UDP_IPV6 = 0x5, - VXGE_HW_RING_HASH_TYPE_IPV6 = 0x6, - VXGE_HW_RING_HASH_TYPE_TCP_IPV6_EX = 0x7, - VXGE_HW_RING_HASH_TYPE_UDP_IPV6_EX = 0x8, - VXGE_HW_RING_HASH_TYPE_IPV6_EX = 0x9 -}; - enum vxge_hw_status vxge_hw_ring_rxd_reserve( struct __vxge_hw_ring *ring_handle, void **rxdh); diff --git a/drivers/net/vxge/vxge-version.h b/drivers/net/vxge/vxge-version.h index 53fefe137368..9c93e0a17175 100644 --- a/drivers/net/vxge/vxge-version.h +++ b/drivers/net/vxge/vxge-version.h @@ -16,7 +16,34 @@ #define VXGE_VERSION_MAJOR "2" #define VXGE_VERSION_MINOR "0" -#define VXGE_VERSION_FIX "9" -#define VXGE_VERSION_BUILD "20840" +#define VXGE_VERSION_FIX "11" +#define VXGE_VERSION_BUILD "21932" #define VXGE_VERSION_FOR "k" + +#define VXGE_FW_VER(maj, min, bld) (((maj) << 16) + ((min) << 8) + (bld)) + +#define VXGE_DEAD_FW_VER_MAJOR 1 +#define VXGE_DEAD_FW_VER_MINOR 4 +#define VXGE_DEAD_FW_VER_BUILD 4 + +#define VXGE_FW_DEAD_VER VXGE_FW_VER(VXGE_DEAD_FW_VER_MAJOR, \ + VXGE_DEAD_FW_VER_MINOR, \ + VXGE_DEAD_FW_VER_BUILD) + +#define VXGE_EPROM_FW_VER_MAJOR 1 +#define VXGE_EPROM_FW_VER_MINOR 6 +#define VXGE_EPROM_FW_VER_BUILD 1 + +#define VXGE_EPROM_FW_VER VXGE_FW_VER(VXGE_EPROM_FW_VER_MAJOR, \ + VXGE_EPROM_FW_VER_MINOR, \ + VXGE_EPROM_FW_VER_BUILD) + +#define VXGE_CERT_FW_VER_MAJOR 1 +#define VXGE_CERT_FW_VER_MINOR 8 +#define VXGE_CERT_FW_VER_BUILD 1 + +#define VXGE_CERT_FW_VER VXGE_FW_VER(VXGE_CERT_FW_VER_MAJOR, \ + VXGE_CERT_FW_VER_MINOR, \ + VXGE_CERT_FW_VER_BUILD) + #endif diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig index ade30251608e..6f383cd684b0 100644 --- a/drivers/net/wireless/rt2x00/Kconfig +++ b/drivers/net/wireless/rt2x00/Kconfig @@ -209,9 +209,6 @@ config RT2X00_LIB_LEDS boolean default y if (RT2X00_LIB=y && LEDS_CLASS=y) || (RT2X00_LIB=m && LEDS_CLASS!=n) -comment "rt2x00 leds support disabled due to modularized LEDS_CLASS and built-in rt2x00" - depends on RT2X00_LIB=y && LEDS_CLASS=m - config RT2X00_LIB_DEBUGFS bool "Ralink debugfs support" depends on RT2X00_LIB && MAC80211_DEBUGFS diff --git a/drivers/net/wireless/zd1211rw/zd_chip.c b/drivers/net/wireless/zd1211rw/zd_chip.c index 30f8d404958b..6a9b66051cf7 100644 --- a/drivers/net/wireless/zd1211rw/zd_chip.c +++ b/drivers/net/wireless/zd1211rw/zd_chip.c @@ -117,6 +117,7 @@ int zd_ioread32v_locked(struct zd_chip *chip, u32 *values, const zd_addr_t *addr /* Allocate a single memory block for values and addresses. */ count16 = 2*count; + /* zd_addr_t is __nocast, so the kmalloc needs an explicit cast */ a16 = (zd_addr_t *) kmalloc(count16 * (sizeof(zd_addr_t) + sizeof(u16)), GFP_KERNEL); if (!a16) { diff --git a/drivers/net/xilinx_emaclite.c b/drivers/net/xilinx_emaclite.c index 14f0955eca68..2de52d18152f 100644 --- a/drivers/net/xilinx_emaclite.c +++ b/drivers/net/xilinx_emaclite.c @@ -515,7 +515,7 @@ static void xemaclite_update_address(struct net_local *drvdata, */ static int xemaclite_set_mac_address(struct net_device *dev, void *address) { - struct net_local *lp = (struct net_local *) netdev_priv(dev); + struct net_local *lp = netdev_priv(dev); struct sockaddr *addr = address; if (netif_running(dev)) @@ -534,7 +534,7 @@ static int xemaclite_set_mac_address(struct net_device *dev, void *address) */ static void xemaclite_tx_timeout(struct net_device *dev) { - struct net_local *lp = (struct net_local *) netdev_priv(dev); + struct net_local *lp = netdev_priv(dev); unsigned long flags; dev_err(&lp->ndev->dev, "Exceeded transmit timeout of %lu ms\n", @@ -578,7 +578,7 @@ static void xemaclite_tx_timeout(struct net_device *dev) */ static void xemaclite_tx_handler(struct net_device *dev) { - struct net_local *lp = (struct net_local *) netdev_priv(dev); + struct net_local *lp = netdev_priv(dev); dev->stats.tx_packets++; if (lp->deferred_skb) { @@ -605,7 +605,7 @@ static void xemaclite_tx_handler(struct net_device *dev) */ static void xemaclite_rx_handler(struct net_device *dev) { - struct net_local *lp = (struct net_local *) netdev_priv(dev); + struct net_local *lp = netdev_priv(dev); struct sk_buff *skb; unsigned int align; u32 len; @@ -661,7 +661,7 @@ static irqreturn_t xemaclite_interrupt(int irq, void *dev_id) { bool tx_complete = 0; struct net_device *dev = dev_id; - struct net_local *lp = (struct net_local *) netdev_priv(dev); + struct net_local *lp = netdev_priv(dev); void __iomem *base_addr = lp->base_addr; u32 tx_status; @@ -918,7 +918,7 @@ void xemaclite_adjust_link(struct net_device *ndev) */ static int xemaclite_open(struct net_device *dev) { - struct net_local *lp = (struct net_local *) netdev_priv(dev); + struct net_local *lp = netdev_priv(dev); int retval; /* Just to be safe, stop the device first */ @@ -987,7 +987,7 @@ static int xemaclite_open(struct net_device *dev) */ static int xemaclite_close(struct net_device *dev) { - struct net_local *lp = (struct net_local *) netdev_priv(dev); + struct net_local *lp = netdev_priv(dev); netif_stop_queue(dev); xemaclite_disable_interrupts(lp); @@ -1031,7 +1031,7 @@ static struct net_device_stats *xemaclite_get_stats(struct net_device *dev) */ static int xemaclite_send(struct sk_buff *orig_skb, struct net_device *dev) { - struct net_local *lp = (struct net_local *) netdev_priv(dev); + struct net_local *lp = netdev_priv(dev); struct sk_buff *new_skb; unsigned int len; unsigned long flags; @@ -1068,7 +1068,7 @@ static int xemaclite_send(struct sk_buff *orig_skb, struct net_device *dev) static void xemaclite_remove_ndev(struct net_device *ndev) { if (ndev) { - struct net_local *lp = (struct net_local *) netdev_priv(ndev); + struct net_local *lp = netdev_priv(ndev); if (lp->base_addr) iounmap((void __iomem __force *) (lp->base_addr)); @@ -1245,7 +1245,7 @@ static int __devexit xemaclite_of_remove(struct platform_device *of_dev) struct device *dev = &of_dev->dev; struct net_device *ndev = dev_get_drvdata(dev); - struct net_local *lp = (struct net_local *) netdev_priv(ndev); + struct net_local *lp = netdev_priv(ndev); /* Un-register the mii_bus, if configured */ if (lp->has_mdio) { diff --git a/drivers/net/znet.c b/drivers/net/znet.c index c3a329204511..ae07b3dfbcc1 100644 --- a/drivers/net/znet.c +++ b/drivers/net/znet.c @@ -124,7 +124,7 @@ MODULE_LICENSE("GPL"); #define TX_BUF_SIZE 8192 #define DMA_BUF_SIZE (RX_BUF_SIZE + 16) /* 8k + 16 bytes for trailers */ -#define TX_TIMEOUT 10 +#define TX_TIMEOUT (HZ/10) struct znet_private { int rx_dma, tx_dma; |