diff options
Diffstat (limited to 'drivers/net')
30 files changed, 784 insertions, 458 deletions
diff --git a/drivers/net/3c515.c b/drivers/net/3c515.c index 85ffd132bad..3116410b349 100644 --- a/drivers/net/3c515.c +++ b/drivers/net/3c515.c @@ -832,7 +832,9 @@ static int corkscrew_open(struct net_device *dev) skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */ vp->rx_ring[i].addr = isa_virt_to_bus(skb->data); } - vp->rx_ring[i - 1].next = isa_virt_to_bus(&vp->rx_ring[0]); /* Wrap the ring. */ + if (i != 0) + vp->rx_ring[i - 1].next = + isa_virt_to_bus(&vp->rx_ring[0]); /* Wrap the ring. */ outl(isa_virt_to_bus(&vp->rx_ring[0]), ioaddr + UpListPtr); } if (vp->full_bus_master_tx) { /* Boomerang bus master Tx. */ diff --git a/drivers/net/at1700.c b/drivers/net/at1700.c index c2227d79673..5349c58d1fa 100644 --- a/drivers/net/at1700.c +++ b/drivers/net/at1700.c @@ -318,7 +318,7 @@ static int __init at1700_probe1(struct net_device *dev, int ioaddr) pos3 = mca_read_stored_pos( slot, 3 ); pos4 = mca_read_stored_pos( slot, 4 ); - for (l_i = 0; l_i < 0x09; l_i++) + for (l_i = 0; l_i < 8; l_i++) if (( pos3 & 0x07) == at1700_ioaddr_pattern[l_i]) break; ioaddr = at1700_mca_probe_list[l_i]; diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index a2de0cd9c9f..2d035d795f0 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -56,8 +56,8 @@ #include "bnx2x_init_ops.h" #include "bnx2x_dump.h" -#define DRV_MODULE_VERSION "1.48.113-1" -#define DRV_MODULE_RELDATE "2009/07/21" +#define DRV_MODULE_VERSION "1.48.114-1" +#define DRV_MODULE_RELDATE "2009/07/29" #define BNX2X_BC_VER 0x040200 #include <linux/firmware.h> @@ -4831,7 +4831,14 @@ static void bnx2x_set_storm_rx_mode(struct bnx2x *bp) int mode = bp->rx_mode; int mask = (1 << BP_L_ID(bp)); int func = BP_FUNC(bp); + int port = BP_PORT(bp); int i; + /* All but management unicast packets should pass to the host as well */ + u32 llh_mask = + NIG_LLH0_BRB1_DRV_MASK_REG_LLH0_BRB1_DRV_MASK_BRCST | + NIG_LLH0_BRB1_DRV_MASK_REG_LLH0_BRB1_DRV_MASK_MLCST | + NIG_LLH0_BRB1_DRV_MASK_REG_LLH0_BRB1_DRV_MASK_VLAN | + NIG_LLH0_BRB1_DRV_MASK_REG_LLH0_BRB1_DRV_MASK_NO_VLAN; DP(NETIF_MSG_IFUP, "rx mode %d mask 0x%x\n", mode, mask); @@ -4855,6 +4862,8 @@ static void bnx2x_set_storm_rx_mode(struct bnx2x *bp) tstorm_mac_filter.ucast_accept_all = mask; tstorm_mac_filter.mcast_accept_all = mask; tstorm_mac_filter.bcast_accept_all = mask; + /* pass management unicast packets as well */ + llh_mask |= NIG_LLH0_BRB1_DRV_MASK_REG_LLH0_BRB1_DRV_MASK_UNCST; break; default: @@ -4862,6 +4871,10 @@ static void bnx2x_set_storm_rx_mode(struct bnx2x *bp) break; } + REG_WR(bp, + (port ? NIG_REG_LLH1_BRB1_DRV_MASK : NIG_REG_LLH0_BRB1_DRV_MASK), + llh_mask); + for (i = 0; i < sizeof(struct tstorm_eth_mac_filter_config)/4; i++) { REG_WR(bp, BAR_TSTRORM_INTMEM + TSTORM_MAC_FILTER_CONFIG_OFFSET(func) + i * 4, @@ -7341,17 +7354,17 @@ static int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode) for (i = 0; i < MC_HASH_SIZE; i++) REG_WR(bp, MC_HASH_OFFSET(bp, i), 0); + + REG_WR(bp, MISC_REG_E1HMF_MODE, 0); } if (unload_mode == UNLOAD_NORMAL) reset_code = DRV_MSG_CODE_UNLOAD_REQ_WOL_DIS; - else if (bp->flags & NO_WOL_FLAG) { + else if (bp->flags & NO_WOL_FLAG) reset_code = DRV_MSG_CODE_UNLOAD_REQ_WOL_MCP; - if (CHIP_IS_E1H(bp)) - REG_WR(bp, MISC_REG_E1HMF_MODE, 0); - } else if (bp->wol) { + else if (bp->wol) { u32 emac_base = port ? GRCBASE_EMAC1 : GRCBASE_EMAC0; u8 *mac_addr = bp->dev->dev_addr; u32 val; @@ -9402,10 +9415,9 @@ static int bnx2x_test_registers(struct bnx2x *bp) { XCM_REG_WU_DA_SET_TMR_CNT_FLG_CMD00, 4, 0x00000001 }, { XCM_REG_WU_DA_CNT_CMD00, 4, 0x00000003 }, { XCM_REG_GLB_DEL_ACK_MAX_CNT_0, 4, 0x000000ff }, - { NIG_REG_EGRESS_MNG0_FIFO, 20, 0xffffffff }, { NIG_REG_LLH0_T_BIT, 4, 0x00000001 }, -/* 20 */ { NIG_REG_EMAC0_IN_EN, 4, 0x00000001 }, - { NIG_REG_BMAC0_IN_EN, 4, 0x00000001 }, + { NIG_REG_EMAC0_IN_EN, 4, 0x00000001 }, +/* 20 */ { NIG_REG_BMAC0_IN_EN, 4, 0x00000001 }, { NIG_REG_XCM0_OUT_EN, 4, 0x00000001 }, { NIG_REG_BRB0_OUT_EN, 4, 0x00000001 }, { NIG_REG_LLH0_XCM_MASK, 4, 0x00000007 }, @@ -9414,8 +9426,8 @@ static int bnx2x_test_registers(struct bnx2x *bp) { NIG_REG_LLH0_DEST_MAC_0_0, 160, 0xffffffff }, { NIG_REG_LLH0_DEST_IP_0_1, 160, 0xffffffff }, { NIG_REG_LLH0_IPV4_IPV6_0, 160, 0x00000001 }, -/* 30 */ { NIG_REG_LLH0_DEST_UDP_0, 160, 0x0000ffff }, - { NIG_REG_LLH0_DEST_TCP_0, 160, 0x0000ffff }, + { NIG_REG_LLH0_DEST_UDP_0, 160, 0x0000ffff }, +/* 30 */ { NIG_REG_LLH0_DEST_TCP_0, 160, 0x0000ffff }, { NIG_REG_LLH0_VLAN_ID_0, 160, 0x00000fff }, { NIG_REG_XGXS_SERDES0_MODE_SEL, 4, 0x00000001 }, { NIG_REG_LED_CONTROL_OVERRIDE_TRAFFIC_P0, 4, 0x00000001 }, diff --git a/drivers/net/bnx2x_reg.h b/drivers/net/bnx2x_reg.h index d771168ec20..8e9e7a24f2f 100644 --- a/drivers/net/bnx2x_reg.h +++ b/drivers/net/bnx2x_reg.h @@ -1616,6 +1616,11 @@ /* [RW 1] Set by the MCP to remember if one or more of the drivers is/are loaded; 0-prepare; -unprepare */ #define MISC_REG_UNPREPARED 0xa424 +#define NIG_LLH0_BRB1_DRV_MASK_REG_LLH0_BRB1_DRV_MASK_BRCST (0x1<<0) +#define NIG_LLH0_BRB1_DRV_MASK_REG_LLH0_BRB1_DRV_MASK_MLCST (0x1<<1) +#define NIG_LLH0_BRB1_DRV_MASK_REG_LLH0_BRB1_DRV_MASK_NO_VLAN (0x1<<4) +#define NIG_LLH0_BRB1_DRV_MASK_REG_LLH0_BRB1_DRV_MASK_UNCST (0x1<<2) +#define NIG_LLH0_BRB1_DRV_MASK_REG_LLH0_BRB1_DRV_MASK_VLAN (0x1<<3) #define NIG_MASK_INTERRUPT_PORT0_REG_MASK_EMAC0_MISC_MI_INT (0x1<<0) #define NIG_MASK_INTERRUPT_PORT0_REG_MASK_SERDES0_LINK_STATUS (0x1<<9) #define NIG_MASK_INTERRUPT_PORT0_REG_MASK_XGXS0_LINK10G (0x1<<15) diff --git a/drivers/net/cnic.c b/drivers/net/cnic.c index 4d1515f45ba..4869d77cbe9 100644 --- a/drivers/net/cnic.c +++ b/drivers/net/cnic.c @@ -227,7 +227,7 @@ static int cnic_send_nlmsg(struct cnic_local *cp, u32 type, } rcu_read_lock(); - ulp_ops = rcu_dereference(cp->ulp_ops[CNIC_ULP_ISCSI]); + ulp_ops = rcu_dereference(cnic_ulp_tbl[CNIC_ULP_ISCSI]); if (ulp_ops) ulp_ops->iscsi_nl_send_msg(cp->dev, msg_type, buf, len); rcu_read_unlock(); @@ -319,6 +319,20 @@ static int cnic_abort_prep(struct cnic_sock *csk) return 0; } +static void cnic_uio_stop(void) +{ + struct cnic_dev *dev; + + read_lock(&cnic_dev_lock); + list_for_each_entry(dev, &cnic_dev_list, list) { + struct cnic_local *cp = dev->cnic_priv; + + if (cp->cnic_uinfo) + cnic_send_nlmsg(cp, ISCSI_KEVENT_IF_DOWN, NULL); + } + read_unlock(&cnic_dev_lock); +} + int cnic_register_driver(int ulp_type, struct cnic_ulp_ops *ulp_ops) { struct cnic_dev *dev; @@ -390,6 +404,9 @@ int cnic_unregister_driver(int ulp_type) } read_unlock(&cnic_dev_lock); + if (ulp_type == CNIC_ULP_ISCSI) + cnic_uio_stop(); + rcu_assign_pointer(cnic_ulp_tbl[ulp_type], NULL); mutex_unlock(&cnic_lock); @@ -632,7 +649,6 @@ static void cnic_free_resc(struct cnic_dev *dev) int i = 0; if (cp->cnic_uinfo) { - cnic_send_nlmsg(cp, ISCSI_KEVENT_IF_DOWN, NULL); while (cp->uio_dev != -1 && i < 15) { msleep(100); i++; @@ -1057,6 +1073,9 @@ static void cnic_ulp_stop(struct cnic_dev *dev) struct cnic_local *cp = dev->cnic_priv; int if_type; + if (cp->cnic_uinfo) + cnic_send_nlmsg(cp, ISCSI_KEVENT_IF_DOWN, NULL); + rcu_read_lock(); for (if_type = 0; if_type < MAX_CNIC_ULP_TYPE; if_type++) { struct cnic_ulp_ops *ulp_ops; diff --git a/drivers/net/eepro.c b/drivers/net/eepro.c index 71605d63708..53317a83857 100644 --- a/drivers/net/eepro.c +++ b/drivers/net/eepro.c @@ -1784,7 +1784,7 @@ int __init init_module(void) printk(KERN_INFO "eepro_init_module: Auto-detecting boards (May God protect us...)\n"); } - for (i = 0; io[i] != -1 && i < MAX_EEPRO; i++) { + for (i = 0; i < MAX_EEPRO && io[i] != -1; i++) { dev = alloc_etherdev(sizeof(struct eepro_local)); if (!dev) break; diff --git a/drivers/net/eexpress.c b/drivers/net/eexpress.c index 8c44ef4ba35..d1b6368faac 100644 --- a/drivers/net/eexpress.c +++ b/drivers/net/eexpress.c @@ -1474,13 +1474,13 @@ static void eexp_hw_init586(struct net_device *dev) outw(0x0000, ioaddr + 0x800c); outw(0x0000, ioaddr + 0x800e); - for (i = 0; i < (sizeof(start_code)); i+=32) { + for (i = 0; i < ARRAY_SIZE(start_code) * 2; i+=32) { int j; outw(i, ioaddr + SM_PTR); - for (j = 0; j < 16; j+=2) + for (j = 0; j < 16 && (i+j)/2 < ARRAY_SIZE(start_code); j+=2) outw(start_code[(i+j)/2], ioaddr+0x4000+j); - for (j = 0; j < 16; j+=2) + for (j = 0; j < 16 && (i+j+16)/2 < ARRAY_SIZE(start_code); j+=2) outw(start_code[(i+j+16)/2], ioaddr+0x8000+j); } diff --git a/drivers/net/ethoc.c b/drivers/net/ethoc.c index ceb6a9c357a..4dbe5f17327 100644 --- a/drivers/net/ethoc.c +++ b/drivers/net/ethoc.c @@ -894,7 +894,7 @@ static int ethoc_probe(struct platform_device *pdev) mmio = devm_request_mem_region(&pdev->dev, res->start, res->end - res->start + 1, res->name); - if (!res) { + if (!mmio) { dev_err(&pdev->dev, "cannot request I/O memory space\n"); ret = -ENXIO; goto free; diff --git a/drivers/net/fealnx.c b/drivers/net/fealnx.c index 75e5fe5153d..b2d617206bd 100644 --- a/drivers/net/fealnx.c +++ b/drivers/net/fealnx.c @@ -584,7 +584,8 @@ static int __devinit fealnx_init_one(struct pci_dev *pdev, if (np->flags == HAS_MII_XCVR) { int phy, phy_idx = 0; - for (phy = 1; phy < 32 && phy_idx < 4; phy++) { + for (phy = 1; phy < 32 && phy_idx < ARRAY_SIZE(np->phys); + phy++) { int mii_status = mdio_read(dev, phy, 1); if (mii_status != 0xffff && mii_status != 0x0000) { diff --git a/drivers/net/gianfar_ethtool.c b/drivers/net/gianfar_ethtool.c index dbf06e9313c..2234118eedb 100644 --- a/drivers/net/gianfar_ethtool.c +++ b/drivers/net/gianfar_ethtool.c @@ -366,9 +366,8 @@ static int gfar_scoalesce(struct net_device *dev, struct ethtool_coalesce *cvals return -EINVAL; } - priv->rxic = mk_ic_value( - gfar_usecs2ticks(priv, cvals->rx_coalesce_usecs), - cvals->rx_max_coalesced_frames); + priv->rxic = mk_ic_value(cvals->rx_max_coalesced_frames, + gfar_usecs2ticks(priv, cvals->rx_coalesce_usecs)); /* Set up tx coalescing */ if ((cvals->tx_coalesce_usecs == 0) || @@ -390,9 +389,8 @@ static int gfar_scoalesce(struct net_device *dev, struct ethtool_coalesce *cvals return -EINVAL; } - priv->txic = mk_ic_value( - gfar_usecs2ticks(priv, cvals->tx_coalesce_usecs), - cvals->tx_max_coalesced_frames); + priv->txic = mk_ic_value(cvals->tx_max_coalesced_frames, + gfar_usecs2ticks(priv, cvals->tx_coalesce_usecs)); gfar_write(&priv->regs->rxic, 0); if (priv->rxcoalescing) diff --git a/drivers/net/ixgbe/ixgbe.h b/drivers/net/ixgbe/ixgbe.h index dc3cc4348d1..62b6c028ae8 100644 --- a/drivers/net/ixgbe/ixgbe.h +++ b/drivers/net/ixgbe/ixgbe.h @@ -96,6 +96,8 @@ #define IXGBE_TX_FLAGS_VLAN_PRIO_MASK 0x0000e000 #define IXGBE_TX_FLAGS_VLAN_SHIFT 16 +#define IXGBE_MAX_RSC_INT_RATE 162760 + /* wrapper around a pointer to a socket buffer, * so a DMA handle can be stored along with the buffer */ struct ixgbe_tx_buffer { diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c index 1464b33f1b8..c6db9a04187 100644 --- a/drivers/net/ixgbe/ixgbe_ethtool.c +++ b/drivers/net/ixgbe/ixgbe_ethtool.c @@ -1980,7 +1980,10 @@ static int ixgbe_set_coalesce(struct net_device *netdev, * any other value means disable eitr, which is best * served by setting the interrupt rate very high */ - adapter->eitr_param = IXGBE_MAX_INT_RATE; + if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED) + adapter->eitr_param = IXGBE_MAX_RSC_INT_RATE; + else + adapter->eitr_param = IXGBE_MAX_INT_RATE; adapter->itr_setting = 0; } @@ -2004,13 +2007,13 @@ static int ixgbe_set_flags(struct net_device *netdev, u32 data) ethtool_op_set_flags(netdev, data); - if (!(adapter->flags & IXGBE_FLAG2_RSC_CAPABLE)) + if (!(adapter->flags2 & IXGBE_FLAG2_RSC_CAPABLE)) return 0; /* if state changes we need to update adapter->flags and reset */ if ((!!(data & ETH_FLAG_LRO)) != - (!!(adapter->flags & IXGBE_FLAG2_RSC_ENABLED))) { - adapter->flags ^= IXGBE_FLAG2_RSC_ENABLED; + (!!(adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED))) { + adapter->flags2 ^= IXGBE_FLAG2_RSC_ENABLED; if (netif_running(netdev)) ixgbe_reinit_locked(adapter); else diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 50709da922c..44adc986282 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -513,8 +513,11 @@ static void ixgbe_receive_skb(struct ixgbe_q_vector *q_vector, * @skb: skb currently being received and modified **/ static inline void ixgbe_rx_checksum(struct ixgbe_adapter *adapter, - u32 status_err, struct sk_buff *skb) + union ixgbe_adv_rx_desc *rx_desc, + struct sk_buff *skb) { + u32 status_err = le32_to_cpu(rx_desc->wb.upper.status_error); + skb->ip_summed = CHECKSUM_NONE; /* Rx csum disabled */ @@ -532,6 +535,16 @@ static inline void ixgbe_rx_checksum(struct ixgbe_adapter *adapter, return; if (status_err & IXGBE_RXDADV_ERR_TCPE) { + u16 pkt_info = rx_desc->wb.lower.lo_dword.hs_rss.pkt_info; + + /* + * 82599 errata, UDP frames with a 0 checksum can be marked as + * checksum errors. + */ + if ((pkt_info & IXGBE_RXDADV_PKTTYPE_UDP) && + (adapter->hw.mac.type == ixgbe_mac_82599EB)) + return; + adapter->hw_csum_rx_error++; return; } @@ -769,7 +782,7 @@ static bool ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector, prefetch(next_rxd); cleaned_count++; - if (adapter->flags & IXGBE_FLAG2_RSC_CAPABLE) + if (adapter->flags2 & IXGBE_FLAG2_RSC_CAPABLE) rsc_count = ixgbe_get_rsc_count(rx_desc); if (rsc_count) { @@ -805,7 +818,7 @@ static bool ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector, goto next_desc; } - ixgbe_rx_checksum(adapter, staterr, skb); + ixgbe_rx_checksum(adapter, rx_desc, skb); /* probably a little skewed due to removing CRC */ total_rx_bytes += skb->len; @@ -2025,7 +2038,7 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter) IXGBE_WRITE_REG(hw, IXGBE_PSRTYPE(0), psrtype); } } else { - if (!(adapter->flags & IXGBE_FLAG2_RSC_ENABLED) && + if (!(adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED) && (netdev->mtu <= ETH_DATA_LEN)) rx_buf_len = MAXIMUM_ETHERNET_VLAN_SIZE; else @@ -2154,7 +2167,7 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter) IXGBE_WRITE_REG(hw, IXGBE_RDRXCTL, rdrxctl); } - if (adapter->flags & IXGBE_FLAG2_RSC_ENABLED) { + if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED) { /* Enable 82599 HW-RSC */ for (i = 0; i < adapter->num_rx_queues; i++) { j = adapter->rx_ring[i].reg_idx; @@ -3801,8 +3814,8 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter) adapter->max_msix_q_vectors = MAX_MSIX_Q_VECTORS_82598; } else if (hw->mac.type == ixgbe_mac_82599EB) { adapter->max_msix_q_vectors = MAX_MSIX_Q_VECTORS_82599; - adapter->flags |= IXGBE_FLAG2_RSC_CAPABLE; - adapter->flags |= IXGBE_FLAG2_RSC_ENABLED; + adapter->flags2 |= IXGBE_FLAG2_RSC_CAPABLE; + adapter->flags2 |= IXGBE_FLAG2_RSC_ENABLED; adapter->flags |= IXGBE_FLAG_FDIR_HASH_CAPABLE; adapter->ring_feature[RING_F_FDIR].indices = IXGBE_MAX_FDIR_INDICES; @@ -5349,12 +5362,19 @@ static int ixgbe_del_sanmac_netdev(struct net_device *dev) static void ixgbe_netpoll(struct net_device *netdev) { struct ixgbe_adapter *adapter = netdev_priv(netdev); + int i; - disable_irq(adapter->pdev->irq); adapter->flags |= IXGBE_FLAG_IN_NETPOLL; - ixgbe_intr(adapter->pdev->irq, netdev); + if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) { + int num_q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS; + for (i = 0; i < num_q_vectors; i++) { + struct ixgbe_q_vector *q_vector = adapter->q_vector[i]; + ixgbe_msix_clean_many(0, q_vector); + } + } else { + ixgbe_intr(adapter->pdev->irq, netdev); + } adapter->flags &= ~IXGBE_FLAG_IN_NETPOLL; - enable_irq(adapter->pdev->irq); } #endif @@ -5600,7 +5620,7 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, if (pci_using_dac) netdev->features |= NETIF_F_HIGHDMA; - if (adapter->flags & IXGBE_FLAG2_RSC_ENABLED) + if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED) netdev->features |= NETIF_F_LRO; /* make sure the EEPROM is good */ diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h index f86e05047d1..e22d0861589 100644 --- a/drivers/net/netxen/netxen_nic.h +++ b/drivers/net/netxen/netxen_nic.h @@ -57,8 +57,8 @@ #define _NETXEN_NIC_LINUX_MAJOR 4 #define _NETXEN_NIC_LINUX_MINOR 0 -#define _NETXEN_NIC_LINUX_SUBVERSION 30 -#define NETXEN_NIC_LINUX_VERSIONID "4.0.30" +#define _NETXEN_NIC_LINUX_SUBVERSION 41 +#define NETXEN_NIC_LINUX_VERSIONID "4.0.41" #define NETXEN_VERSION_CODE(a, b, c) (((a) << 24) + ((b) << 16) + (c)) #define _major(v) (((v) >> 24) & 0xff) @@ -143,18 +143,13 @@ #define NX_ETHERMTU 1500 #define NX_MAX_ETHERHDR 32 /* This contains some padding */ -#define NX_RX_NORMAL_BUF_MAX_LEN (NX_MAX_ETHERHDR + NX_ETHERMTU) +#define NX_P2_RX_BUF_MAX_LEN 1760 +#define NX_P3_RX_BUF_MAX_LEN (NX_MAX_ETHERHDR + NX_ETHERMTU) #define NX_P2_RX_JUMBO_BUF_MAX_LEN (NX_MAX_ETHERHDR + P2_MAX_MTU) #define NX_P3_RX_JUMBO_BUF_MAX_LEN (NX_MAX_ETHERHDR + P3_MAX_MTU) #define NX_CT_DEFAULT_RX_BUF_LEN 2048 -#define MAX_RX_BUFFER_LENGTH 1760 -#define MAX_RX_JUMBO_BUFFER_LENGTH 8062 -#define MAX_RX_LRO_BUFFER_LENGTH (8062) -#define RX_DMA_MAP_LEN (MAX_RX_BUFFER_LENGTH - 2) -#define RX_JUMBO_DMA_MAP_LEN \ - (MAX_RX_JUMBO_BUFFER_LENGTH - 2) -#define RX_LRO_DMA_MAP_LEN (MAX_RX_LRO_BUFFER_LENGTH - 2) +#define NX_RX_LRO_BUFFER_LENGTH (8060) /* * Maximum number of ring contexts @@ -200,13 +195,20 @@ #define RCV_RING_JUMBO 1 #define RCV_RING_LRO 2 -#define MAX_CMD_DESCRIPTORS 4096 -#define MAX_RCV_DESCRIPTORS 16384 -#define MAX_CMD_DESCRIPTORS_HOST 1024 -#define MAX_RCV_DESCRIPTORS_1G 2048 -#define MAX_RCV_DESCRIPTORS_10G 4096 -#define MAX_JUMBO_RCV_DESCRIPTORS 1024 +#define MIN_CMD_DESCRIPTORS 64 +#define MIN_RCV_DESCRIPTORS 64 +#define MIN_JUMBO_DESCRIPTORS 32 + +#define MAX_CMD_DESCRIPTORS 1024 +#define MAX_RCV_DESCRIPTORS_1G 4096 +#define MAX_RCV_DESCRIPTORS_10G 8192 +#define MAX_JUMBO_RCV_DESCRIPTORS_1G 512 +#define MAX_JUMBO_RCV_DESCRIPTORS_10G 1024 #define MAX_LRO_RCV_DESCRIPTORS 8 + +#define DEFAULT_RCV_DESCRIPTORS_1G 2048 +#define DEFAULT_RCV_DESCRIPTORS_10G 4096 + #define NETXEN_CTX_SIGNATURE 0xdee0 #define NETXEN_CTX_SIGNATURE_V2 0x0002dee0 #define NETXEN_CTX_RESET 0xbad0 @@ -302,6 +304,10 @@ struct netxen_ring_ctx { #define FLAGS_IPSEC_SA_ADD 0x04 #define FLAGS_IPSEC_SA_DELETE 0x08 #define FLAGS_VLAN_TAGGED 0x10 +#define FLAGS_VLAN_OOB 0x40 + +#define netxen_set_tx_vlan_tci(cmd_desc, v) \ + (cmd_desc)->vlan_TCI = cpu_to_le16(v); #define netxen_set_cmd_desc_port(cmd_desc, var) \ ((cmd_desc)->port_ctxid |= ((var) & 0x0F)) @@ -316,58 +322,33 @@ struct netxen_ring_ctx { cpu_to_le16(((_flags) & 0x7f) | (((_opcode) & 0x3f) << 7)) #define netxen_set_tx_frags_len(_desc, _frags, _len) \ - (_desc)->num_of_buffers_total_length = \ + (_desc)->nfrags__length = \ cpu_to_le32(((_frags) & 0xff) | (((_len) & 0xffffff) << 8)) struct cmd_desc_type0 { u8 tcp_hdr_offset; /* For LSO only */ u8 ip_hdr_offset; /* For LSO only */ - /* Bit pattern: 0-6 flags, 7-12 opcode, 13-15 unused */ - __le16 flags_opcode; - /* Bit pattern: 0-7 total number of segments, - 8-31 Total size of the packet */ - __le32 num_of_buffers_total_length; - union { - struct { - __le32 addr_low_part2; - __le32 addr_high_part2; - }; - __le64 addr_buffer2; - }; + __le16 flags_opcode; /* 15:13 unused, 12:7 opcode, 6:0 flags */ + __le32 nfrags__length; /* 31:8 total len, 7:0 frag count */ + + __le64 addr_buffer2; - __le16 reference_handle; /* changed to u16 to add mss */ - __le16 mss; /* passed by NDIS_PACKET for LSO */ - /* Bit pattern 0-3 port, 0-3 ctx id */ - u8 port_ctxid; + __le16 reference_handle; + __le16 mss; + u8 port_ctxid; /* 7:4 ctxid 3:0 port */ u8 total_hdr_length; /* LSO only : MAC+IP+TCP Hdr size */ __le16 conn_id; /* IPSec offoad only */ - union { - struct { - __le32 addr_low_part3; - __le32 addr_high_part3; - }; - __le64 addr_buffer3; - }; - union { - struct { - __le32 addr_low_part1; - __le32 addr_high_part1; - }; - __le64 addr_buffer1; - }; + __le64 addr_buffer3; + __le64 addr_buffer1; __le16 buffer_length[4]; - union { - struct { - __le32 addr_low_part4; - __le32 addr_high_part4; - }; - __le64 addr_buffer4; - }; + __le64 addr_buffer4; - __le64 unused; + __le16 vlan_TCI; + __le16 reserved; + __le32 reserved2; } __attribute__ ((aligned(64))); @@ -380,6 +361,7 @@ struct rcv_desc { }; /* opcode field in status_desc */ +#define NETXEN_NIC_SYN_OFFLOAD 0x03 #define NETXEN_NIC_RXPKT_DESC 0x04 #define NETXEN_OLD_RXPKT_DESC 0x3f #define NETXEN_NIC_RESPONSE_DESC 0x05 @@ -1078,6 +1060,9 @@ typedef struct { #define NX_MAC_EVENT 0x1 +#define NX_IP_UP 2 +#define NX_IP_DOWN 3 + /* * Driver --> Firmware */ @@ -1132,6 +1117,9 @@ typedef struct { #define NX_FW_CAPABILITY_LINK_NOTIFICATION (1 << 5) #define NX_FW_CAPABILITY_SWITCHING (1 << 6) +#define NX_FW_CAPABILITY_PEXQ (1 << 7) +#define NX_FW_CAPABILITY_BDG (1 << 8) +#define NX_FW_CAPABILITY_FVLANTX (1 << 9) /* module types */ #define LINKEVENT_MODULE_NOT_PRESENT 1 @@ -1315,29 +1303,11 @@ struct netxen_adapter { nx_nic_intr_coalesce_t coal; - u32 fw_major; + u32 resv5; u32 fw_version; const struct firmware *fw; }; -/* - * NetXen dma watchdog control structure - * - * Bit 0 : enabled => R/O: 1 watchdog active, 0 inactive - * Bit 1 : disable_request => 1 req disable dma watchdog - * Bit 2 : enable_request => 1 req enable dma watchdog - * Bit 3-31 : unused - */ - -#define netxen_set_dma_watchdog_disable_req(config_word) \ - _netxen_set_bits(config_word, 1, 1, 1) -#define netxen_set_dma_watchdog_enable_req(config_word) \ - _netxen_set_bits(config_word, 2, 1, 1) -#define netxen_get_dma_watchdog_enabled(config_word) \ - ((config_word) & 0x1) -#define netxen_get_dma_watchdog_disabled(config_word) \ - (((config_word) >> 1) & 0x1) - int netxen_niu_xgbe_enable_phy_interrupts(struct netxen_adapter *adapter); int netxen_niu_gbe_enable_phy_interrupts(struct netxen_adapter *adapter); int netxen_niu_xgbe_disable_phy_interrupts(struct netxen_adapter *adapter); @@ -1398,8 +1368,9 @@ unsigned long netxen_nic_pci_set_window_2M(struct netxen_adapter *adapter, unsigned long long addr); /* Functions from netxen_nic_init.c */ -void netxen_free_adapter_offload(struct netxen_adapter *adapter); -int netxen_initialize_adapter_offload(struct netxen_adapter *adapter); +int netxen_init_dummy_dma(struct netxen_adapter *adapter); +void netxen_free_dummy_dma(struct netxen_adapter *adapter); + int netxen_phantom_init(struct netxen_adapter *adapter, int pegtune_val); int netxen_load_firmware(struct netxen_adapter *adapter); int netxen_need_fw_reset(struct netxen_adapter *adapter); @@ -1443,6 +1414,7 @@ void netxen_p3_free_mac_list(struct netxen_adapter *adapter); int netxen_p3_nic_set_promisc(struct netxen_adapter *adapter, u32); int netxen_config_intr_coalesce(struct netxen_adapter *adapter); int netxen_config_rss(struct netxen_adapter *adapter, int enable); +int netxen_config_ipaddr(struct netxen_adapter *adapter, u32 ip, int cmd); int netxen_linkevent_request(struct netxen_adapter *adapter, int enable); void netxen_advert_link_change(struct netxen_adapter *adapter, int linkup); @@ -1455,6 +1427,9 @@ struct net_device_stats *netxen_nic_get_stats(struct net_device *netdev); void netxen_nic_update_cmd_producer(struct netxen_adapter *adapter, struct nx_host_tx_ring *tx_ring); +/* Functions from netxen_nic_main.c */ +int netxen_nic_reset_context(struct netxen_adapter *); + /* * NetXen Board information */ @@ -1505,56 +1480,6 @@ static inline void get_brd_name_by_type(u32 type, char *name) name = "Unknown"; } -static inline int -dma_watchdog_shutdown_request(struct netxen_adapter *adapter) -{ - u32 ctrl; - - /* check if already inactive */ - ctrl = adapter->hw_read_wx(adapter, - NETXEN_CAM_RAM(NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL)); - - if (netxen_get_dma_watchdog_enabled(ctrl) == 0) - return 1; - - /* Send the disable request */ - netxen_set_dma_watchdog_disable_req(ctrl); - NXWR32(adapter, NETXEN_CAM_RAM(NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL), ctrl); - - return 0; -} - -static inline int -dma_watchdog_shutdown_poll_result(struct netxen_adapter *adapter) -{ - u32 ctrl; - - ctrl = adapter->hw_read_wx(adapter, - NETXEN_CAM_RAM(NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL)); - - return (netxen_get_dma_watchdog_enabled(ctrl) == 0); -} - -static inline int -dma_watchdog_wakeup(struct netxen_adapter *adapter) -{ - u32 ctrl; - - ctrl = adapter->hw_read_wx(adapter, - NETXEN_CAM_RAM(NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL)); - - if (netxen_get_dma_watchdog_enabled(ctrl)) - return 1; - - /* send the wakeup request */ - netxen_set_dma_watchdog_enable_req(ctrl); - - NXWR32(adapter, NETXEN_CAM_RAM(NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL), ctrl); - - return 0; -} - - static inline u32 netxen_tx_avail(struct nx_host_tx_ring *tx_ring) { smp_mb(); diff --git a/drivers/net/netxen/netxen_nic_ctx.c b/drivers/net/netxen/netxen_nic_ctx.c index 9f8ae4719e2..9e0469643d3 100644 --- a/drivers/net/netxen/netxen_nic_ctx.c +++ b/drivers/net/netxen/netxen_nic_ctx.c @@ -647,7 +647,7 @@ int netxen_alloc_hw_resources(struct netxen_adapter *adapter) } rds_ring->desc_head = (struct rcv_desc *)addr; - if (adapter->fw_major < 4) + if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) rds_ring->crb_rcv_producer = recv_crb_registers[port].crb_rcv_producer[ring]; } @@ -675,7 +675,7 @@ int netxen_alloc_hw_resources(struct netxen_adapter *adapter) } - if (adapter->fw_major >= 4) { + if (!NX_IS_REVISION_P2(adapter->ahw.revision_id)) { err = nx_fw_cmd_create_rx_ctx(adapter); if (err) goto err_out_free; @@ -705,7 +705,7 @@ void netxen_free_hw_resources(struct netxen_adapter *adapter) int port = adapter->portnum; - if (adapter->fw_major >= 4) { + if (!NX_IS_REVISION_P2(adapter->ahw.revision_id)) { nx_fw_cmd_destroy_rx_ctx(adapter); nx_fw_cmd_destroy_tx_ctx(adapter); } else { diff --git a/drivers/net/netxen/netxen_nic_ethtool.c b/drivers/net/netxen/netxen_nic_ethtool.c index e16ea46c24b..39a308c363c 100644 --- a/drivers/net/netxen/netxen_nic_ethtool.c +++ b/drivers/net/netxen/netxen_nic_ethtool.c @@ -490,28 +490,86 @@ netxen_nic_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, } static void -netxen_nic_get_ringparam(struct net_device *dev, struct ethtool_ringparam *ring) +netxen_nic_get_ringparam(struct net_device *dev, + struct ethtool_ringparam *ring) { struct netxen_adapter *adapter = netdev_priv(dev); - ring->rx_pending = 0; - ring->rx_jumbo_pending = 0; - ring->rx_pending += adapter->recv_ctx. - rds_rings[RCV_RING_NORMAL].num_desc; - ring->rx_jumbo_pending += adapter->recv_ctx. - rds_rings[RCV_RING_JUMBO].num_desc; + ring->rx_pending = adapter->num_rxd; + ring->rx_jumbo_pending = adapter->num_jumbo_rxd; + ring->rx_jumbo_pending += adapter->num_lro_rxd; ring->tx_pending = adapter->num_txd; - if (adapter->ahw.port_type == NETXEN_NIC_GBE) + if (adapter->ahw.port_type == NETXEN_NIC_GBE) { ring->rx_max_pending = MAX_RCV_DESCRIPTORS_1G; - else + ring->rx_jumbo_max_pending = MAX_JUMBO_RCV_DESCRIPTORS_1G; + } else { ring->rx_max_pending = MAX_RCV_DESCRIPTORS_10G; - ring->tx_max_pending = MAX_CMD_DESCRIPTORS_HOST; - ring->rx_jumbo_max_pending = MAX_JUMBO_RCV_DESCRIPTORS; + ring->rx_jumbo_max_pending = MAX_JUMBO_RCV_DESCRIPTORS_10G; + } + + ring->tx_max_pending = MAX_CMD_DESCRIPTORS; + ring->rx_mini_max_pending = 0; ring->rx_mini_pending = 0; } +static u32 +netxen_validate_ringparam(u32 val, u32 min, u32 max, char *r_name) +{ + u32 num_desc; + num_desc = max(val, min); + num_desc = min(num_desc, max); + num_desc = roundup_pow_of_two(num_desc); + + if (val != num_desc) { + printk(KERN_INFO "%s: setting %s ring size %d instead of %d\n", + netxen_nic_driver_name, r_name, num_desc, val); + } + + return num_desc; +} + +static int +netxen_nic_set_ringparam(struct net_device *dev, + struct ethtool_ringparam *ring) +{ + struct netxen_adapter *adapter = netdev_priv(dev); + u16 max_rcv_desc = MAX_RCV_DESCRIPTORS_10G; + u16 max_jumbo_desc = MAX_JUMBO_RCV_DESCRIPTORS_10G; + u16 num_rxd, num_jumbo_rxd, num_txd; + + if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) + return -EOPNOTSUPP; + + if (ring->rx_mini_pending) + return -EOPNOTSUPP; + + if (adapter->ahw.port_type == NETXEN_NIC_GBE) { + max_rcv_desc = MAX_RCV_DESCRIPTORS_1G; + max_jumbo_desc = MAX_JUMBO_RCV_DESCRIPTORS_10G; + } + + num_rxd = netxen_validate_ringparam(ring->rx_pending, + MIN_RCV_DESCRIPTORS, max_rcv_desc, "rx"); + + num_jumbo_rxd = netxen_validate_ringparam(ring->rx_jumbo_pending, + MIN_JUMBO_DESCRIPTORS, max_jumbo_desc, "rx jumbo"); + + num_txd = netxen_validate_ringparam(ring->tx_pending, + MIN_CMD_DESCRIPTORS, MAX_CMD_DESCRIPTORS, "tx"); + + if (num_rxd == adapter->num_rxd && num_txd == adapter->num_txd && + num_jumbo_rxd == adapter->num_jumbo_rxd) + return 0; + + adapter->num_rxd = num_rxd; + adapter->num_jumbo_rxd = num_jumbo_rxd; + adapter->num_txd = num_txd; + + return netxen_nic_reset_context(adapter); +} + static void netxen_nic_get_pauseparam(struct net_device *dev, struct ethtool_pauseparam *pause) @@ -893,6 +951,7 @@ struct ethtool_ops netxen_nic_ethtool_ops = { .get_eeprom_len = netxen_nic_get_eeprom_len, .get_eeprom = netxen_nic_get_eeprom, .get_ringparam = netxen_nic_get_ringparam, + .set_ringparam = netxen_nic_set_ringparam, .get_pauseparam = netxen_nic_get_pauseparam, .set_pauseparam = netxen_nic_set_pauseparam, .set_tx_csum = ethtool_op_set_tx_csum, diff --git a/drivers/net/netxen/netxen_nic_hdr.h b/drivers/net/netxen/netxen_nic_hdr.h index 82410367564..a7328584a21 100644 --- a/drivers/net/netxen/netxen_nic_hdr.h +++ b/drivers/net/netxen/netxen_nic_hdr.h @@ -852,7 +852,7 @@ enum { #define NX_PEG_TUNE_MN_PRESENT 0x1 #define NX_PEG_TUNE_CAPABILITY (NETXEN_CAM_RAM(0x02c)) -#define NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL (0x14) +#define NETXEN_DMA_WATCHDOG_CTRL (NETXEN_CAM_RAM(0x14)) #define NETXEN_PEG_ALIVE_COUNTER (NETXEN_CAM_RAM(0xb0)) #define ISR_MSI_INT_TRIGGER(FUNC) (NETXEN_PCIX_PS_REG(PCIX_MSI_F(FUNC))) diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c index b9123d445c9..ddb9deb12b3 100644 --- a/drivers/net/netxen/netxen_nic_hw.c +++ b/drivers/net/netxen/netxen_nic_hw.c @@ -706,6 +706,30 @@ int netxen_config_rss(struct netxen_adapter *adapter, int enable) return rv; } +int netxen_config_ipaddr(struct netxen_adapter *adapter, u32 ip, int cmd) +{ + nx_nic_req_t req; + u64 word; + int rv; + + memset(&req, 0, sizeof(nx_nic_req_t)); + req.qhdr = cpu_to_le64(NX_HOST_REQUEST << 23); + + word = NX_NIC_H2C_OPCODE_CONFIG_IPADDR | ((u64)adapter->portnum << 16); + req.req_hdr = cpu_to_le64(word); + + req.words[0] = cpu_to_le64(cmd); + req.words[1] = cpu_to_le64(ip); + + rv = netxen_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1); + if (rv != 0) { + printk(KERN_ERR "%s: could not notify %s IP 0x%x reuqest\n", + adapter->netdev->name, + (cmd == NX_IP_UP) ? "Add" : "Remove", ip); + } + return rv; +} + int netxen_linkevent_request(struct netxen_adapter *adapter, int enable) { nx_nic_req_t req; @@ -2021,7 +2045,6 @@ void netxen_nic_get_firmware_info(struct netxen_adapter *adapter) fw_minor = NXRD32(adapter, NETXEN_FW_VERSION_MINOR); fw_build = NXRD32(adapter, NETXEN_FW_VERSION_SUB); - adapter->fw_major = fw_major; adapter->fw_version = NETXEN_VERSION_CODE(fw_major, fw_minor, fw_build); if (adapter->portnum == 0) { @@ -2047,6 +2070,9 @@ void netxen_nic_get_firmware_info(struct netxen_adapter *adapter) dev_info(&pdev->dev, "firmware running in %s mode\n", adapter->ahw.cut_through ? "cut-through" : "legacy"); } + + if (adapter->fw_version >= NETXEN_VERSION_CODE(4, 0, 222)) + adapter->capabilities = NXRD32(adapter, CRB_FW_CAPABILITIES_1); } int diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c index 5d3343ef3d8..81253abbfa3 100644 --- a/drivers/net/netxen/netxen_nic_init.c +++ b/drivers/net/netxen/netxen_nic_init.c @@ -184,6 +184,13 @@ void netxen_free_sw_resources(struct netxen_adapter *adapter) kfree(recv_ctx->rds_rings); skip_rds: + if (recv_ctx->sds_rings == NULL) + goto skip_sds; + + for(ring = 0; ring < adapter->max_sds_rings; ring++) + recv_ctx->sds_rings[ring].consumer = 0; + +skip_sds: if (adapter->tx_ring == NULL) return; @@ -247,9 +254,14 @@ int netxen_alloc_sw_resources(struct netxen_adapter *adapter) rds_ring->skb_size = NX_CT_DEFAULT_RX_BUF_LEN; } else { - rds_ring->dma_size = RX_DMA_MAP_LEN; + if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) + rds_ring->dma_size = + NX_P3_RX_BUF_MAX_LEN; + else + rds_ring->dma_size = + NX_P2_RX_BUF_MAX_LEN; rds_ring->skb_size = - MAX_RX_BUFFER_LENGTH; + rds_ring->dma_size + NET_IP_ALIGN; } break; @@ -267,8 +279,8 @@ int netxen_alloc_sw_resources(struct netxen_adapter *adapter) case RCV_RING_LRO: rds_ring->num_desc = adapter->num_lro_rxd; - rds_ring->dma_size = RX_LRO_DMA_MAP_LEN; - rds_ring->skb_size = MAX_RX_LRO_BUFFER_LENGTH; + rds_ring->dma_size = NX_RX_LRO_BUFFER_LENGTH; + rds_ring->skb_size = rds_ring->dma_size + NET_IP_ALIGN; break; } @@ -880,22 +892,10 @@ netxen_validate_firmware(struct netxen_adapter *adapter, const char *fwname) return 0; } -void netxen_request_firmware(struct netxen_adapter *adapter) +static int +netxen_p3_has_mn(struct netxen_adapter *adapter) { u32 capability, flashed_ver; - u8 fw_type; - struct pci_dev *pdev = adapter->pdev; - int rc = 0; - - if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) { - fw_type = NX_P2_MN_ROMIMAGE; - goto request_fw; - } else { - fw_type = NX_P3_CT_ROMIMAGE; - goto request_fw; - } - -request_mn: capability = 0; netxen_rom_fast_read(adapter, @@ -903,23 +903,35 @@ request_mn: flashed_ver = NETXEN_DECODE_VERSION(flashed_ver); if (flashed_ver >= NETXEN_VERSION_CODE(4, 0, 220)) { + capability = NXRD32(adapter, NX_PEG_TUNE_CAPABILITY); - if (capability & NX_PEG_TUNE_MN_PRESENT) { - fw_type = NX_P3_MN_ROMIMAGE; - goto request_fw; - } + if (capability & NX_PEG_TUNE_MN_PRESENT) + return 1; } + return 0; +} - fw_type = NX_FLASH_ROMIMAGE; - adapter->fw = NULL; - goto done; +void netxen_request_firmware(struct netxen_adapter *adapter) +{ + u8 fw_type; + struct pci_dev *pdev = adapter->pdev; + int rc = 0; + + if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) { + fw_type = NX_P2_MN_ROMIMAGE; + goto request_fw; + } + + fw_type = netxen_p3_has_mn(adapter) ? + NX_P3_MN_ROMIMAGE : NX_P3_CT_ROMIMAGE; request_fw: rc = request_firmware(&adapter->fw, fw_name[fw_type], &pdev->dev); if (rc != 0) { - if (fw_type == NX_P3_CT_ROMIMAGE) { + if (fw_type == NX_P3_MN_ROMIMAGE) { msleep(1); - goto request_mn; + fw_type = NX_P3_CT_ROMIMAGE; + goto request_fw; } fw_type = NX_FLASH_ROMIMAGE; @@ -931,9 +943,10 @@ request_fw: if (rc != 0) { release_firmware(adapter->fw); - if (fw_type == NX_P3_CT_ROMIMAGE) { + if (fw_type == NX_P3_MN_ROMIMAGE) { msleep(1); - goto request_mn; + fw_type = NX_P3_CT_ROMIMAGE; + goto request_fw; } fw_type = NX_FLASH_ROMIMAGE; @@ -953,19 +966,20 @@ netxen_release_firmware(struct netxen_adapter *adapter) release_firmware(adapter->fw); } -int netxen_initialize_adapter_offload(struct netxen_adapter *adapter) +int netxen_init_dummy_dma(struct netxen_adapter *adapter) { - uint64_t addr; - uint32_t hi; - uint32_t lo; + u64 addr; + u32 hi, lo; + + if (!NX_IS_REVISION_P2(adapter->ahw.revision_id)) + return 0; - adapter->dummy_dma.addr = - pci_alloc_consistent(adapter->pdev, + adapter->dummy_dma.addr = pci_alloc_consistent(adapter->pdev, NETXEN_HOST_DUMMY_DMA_SIZE, &adapter->dummy_dma.phys_addr); if (adapter->dummy_dma.addr == NULL) { - printk("%s: ERROR: Could not allocate dummy DMA memory\n", - __func__); + dev_err(&adapter->pdev->dev, + "ERROR: Could not allocate dummy DMA memory\n"); return -ENOMEM; } @@ -976,29 +990,41 @@ int netxen_initialize_adapter_offload(struct netxen_adapter *adapter) NXWR32(adapter, CRB_HOST_DUMMY_BUF_ADDR_HI, hi); NXWR32(adapter, CRB_HOST_DUMMY_BUF_ADDR_LO, lo); - if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) { - uint32_t temp = 0; - NXWR32(adapter, CRB_HOST_DUMMY_BUF, temp); - } - return 0; } -void netxen_free_adapter_offload(struct netxen_adapter *adapter) +/* + * NetXen DMA watchdog control: + * + * Bit 0 : enabled => R/O: 1 watchdog active, 0 inactive + * Bit 1 : disable_request => 1 req disable dma watchdog + * Bit 2 : enable_request => 1 req enable dma watchdog + * Bit 3-31 : unused + */ +void netxen_free_dummy_dma(struct netxen_adapter *adapter) { int i = 100; + u32 ctrl; + + if (!NX_IS_REVISION_P2(adapter->ahw.revision_id)) + return; if (!adapter->dummy_dma.addr) return; - if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) { - do { - if (dma_watchdog_shutdown_request(adapter) == 1) - break; + ctrl = NXRD32(adapter, NETXEN_DMA_WATCHDOG_CTRL); + if ((ctrl & 0x1) != 0) { + NXWR32(adapter, NETXEN_DMA_WATCHDOG_CTRL, (ctrl | 0x2)); + + while ((ctrl & 0x1) != 0) { + msleep(50); - if (dma_watchdog_shutdown_poll_result(adapter) == 1) + + ctrl = NXRD32(adapter, NETXEN_DMA_WATCHDOG_CTRL); + + if (--i == 0) break; - } while (--i); + }; } if (i) { @@ -1007,10 +1033,8 @@ void netxen_free_adapter_offload(struct netxen_adapter *adapter) adapter->dummy_dma.addr, adapter->dummy_dma.phys_addr); adapter->dummy_dma.addr = NULL; - } else { - printk(KERN_ERR "%s: dma_watchdog_shutdown failed\n", - adapter->netdev->name); - } + } else + dev_err(&adapter->pdev->dev, "dma_watchdog_shutdown failed\n"); } int netxen_phantom_init(struct netxen_adapter *adapter, int pegtune_val) @@ -1083,10 +1107,6 @@ int netxen_init_firmware(struct netxen_adapter *adapter) NXWR32(adapter, CRB_MPORT_MODE, MPORT_MULTI_FUNCTION_MODE); NXWR32(adapter, CRB_CMDPEG_STATE, PHAN_INITIALIZE_ACK); - if (adapter->fw_version >= NETXEN_VERSION_CODE(4, 0, 222)) { - adapter->capabilities = NXRD32(adapter, CRB_FW_CAPABILITIES_1); - } - return err; } @@ -1296,6 +1316,7 @@ netxen_process_rcv_ring(struct nx_host_sds_ring *sds_ring, int max) switch (opcode) { case NETXEN_NIC_RXPKT_DESC: case NETXEN_OLD_RXPKT_DESC: + case NETXEN_NIC_SYN_OFFLOAD: break; case NETXEN_NIC_RESPONSE_DESC: netxen_handle_fw_message(desc_cnt, consumer, sds_ring); @@ -1468,7 +1489,7 @@ netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ringid, NXWR32(adapter, rds_ring->crb_rcv_producer, (producer-1) & (rds_ring->num_desc-1)); - if (adapter->fw_major < 4) { + if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) { /* * Write a doorbell msg to tell phanmon of change in * receive ring producer diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index 637ac8b89ba..40549a0e9ff 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -39,6 +39,7 @@ #include <linux/if_vlan.h> #include <net/ip.h> #include <linux/ipv6.h> +#include <linux/inetdevice.h> MODULE_DESCRIPTION("NetXen Multi port (1/10) Gigabit Network Driver"); MODULE_LICENSE("GPL"); @@ -65,7 +66,7 @@ static int netxen_nic_open(struct net_device *netdev); static int netxen_nic_close(struct net_device *netdev); static int netxen_nic_xmit_frame(struct sk_buff *, struct net_device *); static void netxen_tx_timeout(struct net_device *netdev); -static void netxen_tx_timeout_task(struct work_struct *work); +static void netxen_reset_task(struct work_struct *work); static void netxen_watchdog(unsigned long); static int netxen_nic_poll(struct napi_struct *napi, int budget); #ifdef CONFIG_NET_POLL_CONTROLLER @@ -181,7 +182,7 @@ netxen_napi_add(struct netxen_adapter *adapter, struct net_device *netdev) struct netxen_recv_context *recv_ctx = &adapter->recv_ctx; if (netxen_alloc_sds_rings(recv_ctx, adapter->max_sds_rings)) - return 1; + return -ENOMEM; for (ring = 0; ring < adapter->max_sds_rings; ring++) { sds_ring = &recv_ctx->sds_rings[ring]; @@ -282,12 +283,16 @@ nx_update_dma_mask(struct netxen_adapter *adapter) return 0; } -static void netxen_check_options(struct netxen_adapter *adapter) +static void +netxen_check_options(struct netxen_adapter *adapter) { - if (adapter->ahw.port_type == NETXEN_NIC_XGBE) - adapter->num_rxd = MAX_RCV_DESCRIPTORS_10G; - else if (adapter->ahw.port_type == NETXEN_NIC_GBE) - adapter->num_rxd = MAX_RCV_DESCRIPTORS_1G; + if (adapter->ahw.port_type == NETXEN_NIC_XGBE) { + adapter->num_rxd = DEFAULT_RCV_DESCRIPTORS_10G; + adapter->num_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS_10G; + } else if (adapter->ahw.port_type == NETXEN_NIC_GBE) { + adapter->num_rxd = DEFAULT_RCV_DESCRIPTORS_1G; + adapter->num_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS_1G; + } adapter->msix_supported = 0; if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) { @@ -305,11 +310,15 @@ static void netxen_check_options(struct netxen_adapter *adapter) } } - adapter->num_txd = MAX_CMD_DESCRIPTORS_HOST; - adapter->num_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS; - adapter->num_lro_rxd = MAX_LRO_RCV_DESCRIPTORS; + adapter->num_txd = MAX_CMD_DESCRIPTORS; - return; + if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) { + adapter->num_lro_rxd = MAX_LRO_RCV_DESCRIPTORS; + adapter->max_rds_rings = 3; + } else { + adapter->num_lro_rxd = 0; + adapter->max_rds_rings = 2; + } } static int @@ -744,7 +753,7 @@ netxen_start_firmware(struct netxen_adapter *adapter, int request_fw) } - err = netxen_initialize_adapter_offload(adapter); + err = netxen_init_dummy_dma(adapter); if (err) return err; @@ -760,10 +769,14 @@ wait_init: /* Handshake with the card before we register the devices. */ err = netxen_phantom_init(adapter, NETXEN_NIC_PEG_TUNE); if (err) { - netxen_free_adapter_offload(adapter); + netxen_free_dummy_dma(adapter); return err; } + nx_update_dma_mask(adapter); + + netxen_nic_get_firmware_info(adapter); + return 0; } @@ -814,6 +827,20 @@ netxen_nic_free_irq(struct netxen_adapter *adapter) } } +static void +netxen_nic_init_coalesce_defaults(struct netxen_adapter *adapter) +{ + adapter->coal.flags = NETXEN_NIC_INTR_DEFAULT; + adapter->coal.normal.data.rx_time_us = + NETXEN_DEFAULT_INTR_COALESCE_RX_TIME_US; + adapter->coal.normal.data.rx_packets = + NETXEN_DEFAULT_INTR_COALESCE_RX_PACKETS; + adapter->coal.normal.data.tx_time_us = + NETXEN_DEFAULT_INTR_COALESCE_TX_TIME_US; + adapter->coal.normal.data.tx_packets = + NETXEN_DEFAULT_INTR_COALESCE_TX_PACKETS; +} + static int netxen_nic_up(struct netxen_adapter *adapter, struct net_device *netdev) { @@ -836,6 +863,9 @@ netxen_nic_up(struct netxen_adapter *adapter, struct net_device *netdev) if (adapter->max_sds_rings > 1) netxen_config_rss(adapter, 1); + if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) + netxen_config_intr_coalesce(adapter); + netxen_napi_enable(adapter); if (adapter->capabilities & NX_FW_CAPABILITY_LINK_NOTIFICATION) @@ -880,17 +910,15 @@ netxen_nic_attach(struct netxen_adapter *adapter) struct nx_host_rds_ring *rds_ring; struct nx_host_tx_ring *tx_ring; + if (adapter->is_up == NETXEN_ADAPTER_UP_MAGIC) + return 0; + err = netxen_init_firmware(adapter); if (err != 0) { printk(KERN_ERR "Failed to init firmware\n"); return -EIO; } - if (adapter->fw_major < 4) - adapter->max_rds_rings = 3; - else - adapter->max_rds_rings = 2; - err = netxen_alloc_sw_resources(adapter); if (err) { printk(KERN_ERR "%s: Error in setting sw resources\n", @@ -907,7 +935,7 @@ netxen_nic_attach(struct netxen_adapter *adapter) goto err_out_free_sw; } - if (adapter->fw_major < 4) { + if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) { tx_ring = adapter->tx_ring; tx_ring->crb_cmd_producer = crb_cmd_producer[adapter->portnum]; tx_ring->crb_cmd_consumer = crb_cmd_consumer[adapter->portnum]; @@ -931,6 +959,9 @@ netxen_nic_attach(struct netxen_adapter *adapter) goto err_out_free_rxbuf; } + if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) + netxen_nic_init_coalesce_defaults(adapter); + adapter->is_up = NETXEN_ADAPTER_UP_MAGIC; return 0; @@ -945,6 +976,9 @@ err_out_free_sw: static void netxen_nic_detach(struct netxen_adapter *adapter) { + if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC) + return; + netxen_free_hw_resources(adapter); netxen_release_rx_buffers(adapter); netxen_nic_free_irq(adapter); @@ -953,6 +987,95 @@ netxen_nic_detach(struct netxen_adapter *adapter) adapter->is_up = 0; } +int +netxen_nic_reset_context(struct netxen_adapter *adapter) +{ + int err = 0; + struct net_device *netdev = adapter->netdev; + + if (adapter->is_up == NETXEN_ADAPTER_UP_MAGIC) { + + if (netif_running(netdev)) + netxen_nic_down(adapter, netdev); + + netxen_nic_detach(adapter); + + err = netxen_nic_attach(adapter); + if (err) + goto done; + + if (netif_running(netdev)) + err = netxen_nic_up(adapter, netdev); + } +done: + return err; +} + +static int +netxen_setup_netdev(struct netxen_adapter *adapter, + struct net_device *netdev) +{ + int err = 0; + struct pci_dev *pdev = adapter->pdev; + + adapter->rx_csum = 1; + adapter->mc_enabled = 0; + if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) + adapter->max_mc_count = 38; + else + adapter->max_mc_count = 16; + + netdev->netdev_ops = &netxen_netdev_ops; + netdev->watchdog_timeo = 2*HZ; + + netxen_nic_change_mtu(netdev, netdev->mtu); + + SET_ETHTOOL_OPS(netdev, &netxen_nic_ethtool_ops); + + netdev->features |= (NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO); + netdev->features |= (NETIF_F_GRO); + netdev->vlan_features |= (NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO); + + if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) { + netdev->features |= (NETIF_F_IPV6_CSUM | NETIF_F_TSO6); + netdev->vlan_features |= (NETIF_F_IPV6_CSUM | NETIF_F_TSO6); + } + + if (adapter->pci_using_dac) { + netdev->features |= NETIF_F_HIGHDMA; + netdev->vlan_features |= NETIF_F_HIGHDMA; + } + + if (adapter->capabilities & NX_FW_CAPABILITY_FVLANTX) + netdev->features |= (NETIF_F_HW_VLAN_TX); + + netdev->irq = adapter->msix_entries[0].vector; + + err = netxen_napi_add(adapter, netdev); + if (err) + return err; + + init_timer(&adapter->watchdog_timer); + adapter->watchdog_timer.function = &netxen_watchdog; + adapter->watchdog_timer.data = (unsigned long)adapter; + INIT_WORK(&adapter->watchdog_task, netxen_watchdog_task); + INIT_WORK(&adapter->tx_timeout_task, netxen_reset_task); + + if (netxen_read_mac_addr(adapter)) + dev_warn(&pdev->dev, "failed to read mac addr\n"); + + netif_carrier_off(netdev); + netif_stop_queue(netdev); + + err = register_netdev(netdev); + if (err) { + dev_err(&pdev->dev, "failed to register net device\n"); + return err; + } + + return 0; +} + static int __devinit netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { @@ -990,9 +1113,8 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) netdev = alloc_etherdev(sizeof(struct netxen_adapter)); if(!netdev) { - printk(KERN_ERR"%s: Failed to allocate memory for the " - "device block.Check system memory resource" - " usage.\n", netxen_nic_driver_name); + dev_err(&pdev->dev, "failed to allocate net_device\n"); + err = -ENOMEM; goto err_out_free_res; } @@ -1020,38 +1142,10 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) /* This will be reset for mezz cards */ adapter->portnum = pci_func_id; - adapter->rx_csum = 1; - adapter->mc_enabled = 0; - if (NX_IS_REVISION_P3(revision_id)) - adapter->max_mc_count = 38; - else - adapter->max_mc_count = 16; - - netdev->netdev_ops = &netxen_netdev_ops; - netdev->watchdog_timeo = 2*HZ; - - netxen_nic_change_mtu(netdev, netdev->mtu); - SET_ETHTOOL_OPS(netdev, &netxen_nic_ethtool_ops); - - netdev->features |= (NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO); - netdev->features |= (NETIF_F_GRO); - netdev->vlan_features |= (NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO); - - if (NX_IS_REVISION_P3(revision_id)) { - netdev->features |= (NETIF_F_IPV6_CSUM | NETIF_F_TSO6); - netdev->vlan_features |= (NETIF_F_IPV6_CSUM | NETIF_F_TSO6); - } - - if (adapter->pci_using_dac) { - netdev->features |= NETIF_F_HIGHDMA; - netdev->vlan_features |= NETIF_F_HIGHDMA; - } - - if (netxen_nic_get_board_info(adapter) != 0) { - printk("%s: Error getting board config info.\n", - netxen_nic_driver_name); - err = -EIO; + err = netxen_nic_get_board_info(adapter); + if (err) { + dev_err(&pdev->dev, "Error getting board config info.\n"); goto err_out_iounmap; } @@ -1072,15 +1166,11 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) if (err) goto err_out_iounmap; - nx_update_dma_mask(adapter); - - netxen_nic_get_firmware_info(adapter); - /* * See if the firmware gave us a virtual-physical port mapping. */ adapter->physical_port = adapter->portnum; - if (adapter->fw_major < 4) { + if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) { i = NXRD32(adapter, CRB_V2P(adapter->portnum)); if (i != 0x55555555) adapter->physical_port = i; @@ -1090,31 +1180,9 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) netxen_setup_intr(adapter); - netdev->irq = adapter->msix_entries[0].vector; - - if (netxen_napi_add(adapter, netdev)) - goto err_out_disable_msi; - - init_timer(&adapter->watchdog_timer); - adapter->watchdog_timer.function = &netxen_watchdog; - adapter->watchdog_timer.data = (unsigned long)adapter; - INIT_WORK(&adapter->watchdog_task, netxen_watchdog_task); - INIT_WORK(&adapter->tx_timeout_task, netxen_tx_timeout_task); - - err = netxen_read_mac_addr(adapter); + err = netxen_setup_netdev(adapter, netdev); if (err) - dev_warn(&pdev->dev, "failed to read mac addr\n"); - - netif_carrier_off(netdev); - netif_stop_queue(netdev); - - if ((err = register_netdev(netdev))) { - printk(KERN_ERR "%s: register_netdev failed port #%d" - " aborting\n", netxen_nic_driver_name, - adapter->portnum); - err = -EIO; goto err_out_disable_msi; - } pci_set_drvdata(pdev, adapter); @@ -1134,7 +1202,7 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) err_out_disable_msi: netxen_teardown_intr(adapter); - netxen_free_adapter_offload(adapter); + netxen_free_dummy_dma(adapter); err_out_iounmap: netxen_cleanup_pci_map(adapter); @@ -1164,12 +1232,10 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev) unregister_netdev(netdev); - if (adapter->is_up == NETXEN_ADAPTER_UP_MAGIC) { - netxen_nic_detach(adapter); - } + netxen_nic_detach(adapter); if (adapter->portnum == 0) - netxen_free_adapter_offload(adapter); + netxen_free_dummy_dma(adapter); netxen_teardown_intr(adapter); netxen_free_sds_rings(&adapter->recv_ctx); @@ -1198,8 +1264,7 @@ netxen_nic_suspend(struct pci_dev *pdev, pm_message_t state) if (netif_running(netdev)) netxen_nic_down(adapter, netdev); - if (adapter->is_up == NETXEN_ADAPTER_UP_MAGIC) - netxen_nic_detach(adapter); + netxen_nic_detach(adapter); pci_save_state(pdev); @@ -1260,11 +1325,9 @@ static int netxen_nic_open(struct net_device *netdev) if (adapter->driver_mismatch) return -EIO; - if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC) { - err = netxen_nic_attach(adapter); - if (err) - return err; - } + err = netxen_nic_attach(adapter); + if (err) + return err; err = netxen_nic_up(adapter, netdev); if (err) @@ -1290,30 +1353,52 @@ static int netxen_nic_close(struct net_device *netdev) return 0; } -static bool netxen_tso_check(struct net_device *netdev, - struct cmd_desc_type0 *desc, struct sk_buff *skb) +static void +netxen_tso_check(struct net_device *netdev, + struct nx_host_tx_ring *tx_ring, + struct cmd_desc_type0 *first_desc, + struct sk_buff *skb) { - bool tso = false; u8 opcode = TX_ETHER_PKT; __be16 protocol = skb->protocol; - u16 flags = 0; + u16 flags = 0, vid = 0; + u32 producer; + int copied, offset, copy_len, hdr_len = 0, tso = 0, vlan_oob = 0; + struct cmd_desc_type0 *hwdesc; + struct vlan_ethhdr *vh; if (protocol == cpu_to_be16(ETH_P_8021Q)) { - struct vlan_ethhdr *vh = (struct vlan_ethhdr *)skb->data; + + vh = (struct vlan_ethhdr *)skb->data; protocol = vh->h_vlan_encapsulated_proto; flags = FLAGS_VLAN_TAGGED; + + } else if (vlan_tx_tag_present(skb)) { + + flags = FLAGS_VLAN_OOB; + vid = vlan_tx_tag_get(skb); + netxen_set_tx_vlan_tci(first_desc, vid); + vlan_oob = 1; } if ((netdev->features & (NETIF_F_TSO | NETIF_F_TSO6)) && skb_shinfo(skb)->gso_size > 0) { - desc->mss = cpu_to_le16(skb_shinfo(skb)->gso_size); - desc->total_hdr_length = - skb_transport_offset(skb) + tcp_hdrlen(skb); + hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb); + + first_desc->mss = cpu_to_le16(skb_shinfo(skb)->gso_size); + first_desc->total_hdr_length = hdr_len; + if (vlan_oob) { + first_desc->total_hdr_length += VLAN_HLEN; + first_desc->tcp_hdr_offset = VLAN_HLEN; + first_desc->ip_hdr_offset = VLAN_HLEN; + /* Only in case of TSO on vlan device */ + flags |= FLAGS_VLAN_TAGGED; + } opcode = (protocol == cpu_to_be16(ETH_P_IPV6)) ? TX_TCP_LSO6 : TX_TCP_LSO; - tso = true; + tso = 1; } else if (skb->ip_summed == CHECKSUM_PARTIAL) { u8 l4proto; @@ -1334,10 +1419,62 @@ static bool netxen_tso_check(struct net_device *netdev, opcode = TX_UDPV6_PKT; } } - desc->tcp_hdr_offset = skb_transport_offset(skb); - desc->ip_hdr_offset = skb_network_offset(skb); - netxen_set_tx_flags_opcode(desc, flags, opcode); - return tso; + + first_desc->tcp_hdr_offset += skb_transport_offset(skb); + first_desc->ip_hdr_offset += skb_network_offset(skb); + netxen_set_tx_flags_opcode(first_desc, flags, opcode); + + if (!tso) + return; + + /* For LSO, we need to copy the MAC/IP/TCP headers into + * the descriptor ring + */ + producer = tx_ring->producer; + copied = 0; + offset = 2; + + if (vlan_oob) { + /* Create a TSO vlan header template for firmware */ + + hwdesc = &tx_ring->desc_head[producer]; + tx_ring->cmd_buf_arr[producer].skb = NULL; + + copy_len = min((int)sizeof(struct cmd_desc_type0) - offset, + hdr_len + VLAN_HLEN); + + vh = (struct vlan_ethhdr *)((char *)hwdesc + 2); + skb_copy_from_linear_data(skb, vh, 12); + vh->h_vlan_proto = htons(ETH_P_8021Q); + vh->h_vlan_TCI = htons(vid); + skb_copy_from_linear_data_offset(skb, 12, + (char *)vh + 16, copy_len - 16); + + copied = copy_len; + offset = 0; + + producer = get_next_index(producer, tx_ring->num_desc); + } + + while (copied < hdr_len) { + + copy_len = min((int)sizeof(struct cmd_desc_type0) - offset, + (hdr_len - copied)); + + hwdesc = &tx_ring->desc_head[producer]; + tx_ring->cmd_buf_arr[producer].skb = NULL; + + skb_copy_from_linear_data_offset(skb, copied, + (char *)hwdesc + offset, copy_len); + + copied += copy_len; + offset = 0; + + producer = get_next_index(producer, tx_ring->num_desc); + } + + tx_ring->producer = producer; + barrier(); } static void @@ -1361,9 +1498,8 @@ netxen_clean_tx_dma_mapping(struct pci_dev *pdev, static inline void netxen_clear_cmddesc(u64 *desc) { - int i; - for (i = 0; i < 8; i++) - desc[i] = 0ULL; + desc[0] = 0ULL; + desc[2] = 0ULL; } static int @@ -1371,18 +1507,18 @@ netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) { struct netxen_adapter *adapter = netdev_priv(netdev); struct nx_host_tx_ring *tx_ring = adapter->tx_ring; - unsigned int first_seg_len = skb->len - skb->data_len; + struct skb_frag_struct *frag; struct netxen_cmd_buffer *pbuf; struct netxen_skb_frag *buffrag; - struct cmd_desc_type0 *hwdesc; - struct pci_dev *pdev = adapter->pdev; + struct cmd_desc_type0 *hwdesc, *first_desc; + struct pci_dev *pdev; dma_addr_t temp_dma; int i, k; + unsigned long offset; u32 producer; - int frag_count, no_of_desc; + int len, frag_count, no_of_desc; u32 num_txd = tx_ring->num_desc; - bool is_tso = false; frag_count = skb_shinfo(skb)->nr_frags + 1; @@ -1396,32 +1532,30 @@ netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) producer = tx_ring->producer; - hwdesc = &tx_ring->desc_head[producer]; - netxen_clear_cmddesc((u64 *)hwdesc); - pbuf = &tx_ring->cmd_buf_arr[producer]; + pdev = adapter->pdev; + len = skb->len - skb->data_len; - is_tso = netxen_tso_check(netdev, hwdesc, skb); + temp_dma = pci_map_single(pdev, skb->data, len, PCI_DMA_TODEVICE); + if (pci_dma_mapping_error(pdev, temp_dma)) + goto drop_packet; + pbuf = &tx_ring->cmd_buf_arr[producer]; pbuf->skb = skb; pbuf->frag_count = frag_count; - buffrag = &pbuf->frag_array[0]; - temp_dma = pci_map_single(pdev, skb->data, first_seg_len, - PCI_DMA_TODEVICE); - if (pci_dma_mapping_error(pdev, temp_dma)) - goto drop_packet; + buffrag = &pbuf->frag_array[0]; buffrag->dma = temp_dma; - buffrag->length = first_seg_len; + buffrag->length = len; + + first_desc = hwdesc = &tx_ring->desc_head[producer]; + netxen_clear_cmddesc((u64 *)hwdesc); netxen_set_tx_frags_len(hwdesc, frag_count, skb->len); netxen_set_tx_port(hwdesc, adapter->portnum); - hwdesc->buffer_length[0] = cpu_to_le16(first_seg_len); - hwdesc->addr_buffer1 = cpu_to_le64(buffrag->dma); + hwdesc->buffer_length[0] = cpu_to_le16(len); + hwdesc->addr_buffer1 = cpu_to_le64(temp_dma); for (i = 1, k = 1; i < frag_count; i++, k++) { - struct skb_frag_struct *frag; - int len, temp_len; - unsigned long offset; /* move to next desc. if there is a need */ if ((i & 0x3) == 0) { @@ -1432,11 +1566,11 @@ netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) pbuf = &tx_ring->cmd_buf_arr[producer]; pbuf->skb = NULL; } + buffrag = &pbuf->frag_array[i]; frag = &skb_shinfo(skb)->frags[i - 1]; len = frag->size; offset = frag->page_offset; - temp_len = len; temp_dma = pci_map_page(pdev, frag->page, offset, len, PCI_DMA_TODEVICE); if (pci_dma_mapping_error(pdev, temp_dma)) { @@ -1444,11 +1578,10 @@ netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) goto drop_packet; } - buffrag++; buffrag->dma = temp_dma; - buffrag->length = temp_len; + buffrag->length = len; - hwdesc->buffer_length[k] = cpu_to_le16(temp_len); + hwdesc->buffer_length[k] = cpu_to_le16(len); switch (k) { case 0: hwdesc->addr_buffer1 = cpu_to_le64(temp_dma); @@ -1463,53 +1596,14 @@ netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) hwdesc->addr_buffer4 = cpu_to_le64(temp_dma); break; } - frag++; - } - producer = get_next_index(producer, num_txd); - - /* For LSO, we need to copy the MAC/IP/TCP headers into - * the descriptor ring - */ - if (is_tso) { - int hdr_len, first_hdr_len, more_hdr; - hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb); - if (hdr_len > (sizeof(struct cmd_desc_type0) - 2)) { - first_hdr_len = sizeof(struct cmd_desc_type0) - 2; - more_hdr = 1; - } else { - first_hdr_len = hdr_len; - more_hdr = 0; - } - /* copy the MAC/IP/TCP headers to the cmd descriptor list */ - hwdesc = &tx_ring->desc_head[producer]; - pbuf = &tx_ring->cmd_buf_arr[producer]; - pbuf->skb = NULL; - - /* copy the first 64 bytes */ - memcpy(((void *)hwdesc) + 2, - (void *)(skb->data), first_hdr_len); - producer = get_next_index(producer, num_txd); - - if (more_hdr) { - hwdesc = &tx_ring->desc_head[producer]; - pbuf = &tx_ring->cmd_buf_arr[producer]; - pbuf->skb = NULL; - /* copy the next 64 bytes - should be enough except - * for pathological case - */ - skb_copy_from_linear_data_offset(skb, first_hdr_len, - hwdesc, - (hdr_len - - first_hdr_len)); - producer = get_next_index(producer, num_txd); - } } + tx_ring->producer = get_next_index(producer, num_txd); - tx_ring->producer = producer; - adapter->stats.txbytes += skb->len; + netxen_tso_check(netdev, tx_ring, first_desc, skb); netxen_nic_update_cmd_producer(adapter, tx_ring); + adapter->stats.txbytes += skb->len; adapter->stats.xmitcalled++; return NETDEV_TX_OK; @@ -1641,10 +1735,13 @@ static void netxen_tx_timeout(struct net_device *netdev) { struct netxen_adapter *adapter = (struct netxen_adapter *) netdev_priv(netdev); + + dev_err(&netdev->dev, "transmit timeout, resetting.\n"); + SCHEDULE_WORK(&adapter->tx_timeout_task); } -static void netxen_tx_timeout_task(struct work_struct *work) +static void netxen_reset_task(struct work_struct *work) { struct netxen_adapter *adapter = container_of(work, struct netxen_adapter, tx_timeout_task); @@ -1652,9 +1749,6 @@ static void netxen_tx_timeout_task(struct work_struct *work) if (!netif_running(adapter->netdev)) return; - printk(KERN_ERR "%s %s: transmit timeout, resetting.\n", - netxen_nic_driver_name, adapter->netdev->name); - netxen_napi_disable(adapter); adapter->netdev->trans_start = jiffies; @@ -1712,7 +1806,7 @@ static irqreturn_t netxen_intr(int irq, void *data) } /* clear interrupt */ - if (adapter->fw_major < 4) + if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) netxen_nic_disable_int(sds_ring); adapter->pci_write_immediate(adapter, @@ -1781,6 +1875,128 @@ static void netxen_nic_poll_controller(struct net_device *netdev) } #endif +#ifdef CONFIG_INET + +#define is_netxen_netdev(dev) (dev->netdev_ops == &netxen_netdev_ops) + +static int +netxen_destip_supported(struct netxen_adapter *adapter) +{ + if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) + return 0; + + if (adapter->ahw.cut_through) + return 0; + + return 1; +} + +static int netxen_netdev_event(struct notifier_block *this, + unsigned long event, void *ptr) +{ + struct netxen_adapter *adapter; + struct net_device *dev = (struct net_device *)ptr; + struct in_device *indev; + +recheck: + if (dev == NULL) + goto done; + + if (dev->priv_flags & IFF_802_1Q_VLAN) { + dev = vlan_dev_real_dev(dev); + goto recheck; + } + + if (!is_netxen_netdev(dev)) + goto done; + + adapter = netdev_priv(dev); + + if (!adapter || !netxen_destip_supported(adapter)) + goto done; + + if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC) + goto done; + + indev = in_dev_get(dev); + if (!indev) + goto done; + + for_ifa(indev) { + switch (event) { + case NETDEV_UP: + netxen_config_ipaddr(adapter, + ifa->ifa_address, NX_IP_UP); + break; + case NETDEV_DOWN: + netxen_config_ipaddr(adapter, + ifa->ifa_address, NX_IP_DOWN); + break; + default: + break; + } + } endfor_ifa(indev); + + in_dev_put(indev); +done: + return NOTIFY_DONE; +} + +static int +netxen_inetaddr_event(struct notifier_block *this, + unsigned long event, void *ptr) +{ + struct netxen_adapter *adapter; + struct net_device *dev; + + struct in_ifaddr *ifa = (struct in_ifaddr *)ptr; + + dev = ifa->ifa_dev ? ifa->ifa_dev->dev : NULL; + +recheck: + if (dev == NULL || !netif_running(dev)) + goto done; + + if (dev->priv_flags & IFF_802_1Q_VLAN) { + dev = vlan_dev_real_dev(dev); + goto recheck; + } + + if (!is_netxen_netdev(dev)) + goto done; + + adapter = netdev_priv(dev); + + if (!adapter || !netxen_destip_supported(adapter)) + goto done; + + if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC) + goto done; + + switch (event) { + case NETDEV_UP: + netxen_config_ipaddr(adapter, ifa->ifa_address, NX_IP_UP); + break; + case NETDEV_DOWN: + netxen_config_ipaddr(adapter, ifa->ifa_address, NX_IP_DOWN); + break; + default: + break; + } + +done: + return NOTIFY_DONE; +} + +static struct notifier_block netxen_netdev_cb = { + .notifier_call = netxen_netdev_event, +}; + +static struct notifier_block netxen_inetaddr_cb = { + .notifier_call = netxen_inetaddr_event, +}; +#endif + static struct pci_driver netxen_driver = { .name = netxen_nic_driver_name, .id_table = netxen_pci_tbl, @@ -1792,8 +2008,6 @@ static struct pci_driver netxen_driver = { #endif }; -/* Driver Registration on NetXen card */ - static int __init netxen_init_module(void) { printk(KERN_INFO "%s\n", netxen_nic_driver_string); @@ -1801,6 +2015,11 @@ static int __init netxen_init_module(void) if ((netxen_workq = create_singlethread_workqueue("netxen")) == NULL) return -ENOMEM; +#ifdef CONFIG_INET + register_netdevice_notifier(&netxen_netdev_cb); + register_inetaddr_notifier(&netxen_inetaddr_cb); +#endif + return pci_register_driver(&netxen_driver); } @@ -1809,6 +2028,11 @@ module_init(netxen_init_module); static void __exit netxen_exit_module(void) { pci_unregister_driver(&netxen_driver); + +#ifdef CONFIG_INET + unregister_inetaddr_notifier(&netxen_inetaddr_cb); + unregister_netdevice_notifier(&netxen_netdev_cb); +#endif destroy_workqueue(netxen_workq); } diff --git a/drivers/net/pppoe.c b/drivers/net/pppoe.c index f0031f1f97e..5f2090233d7 100644 --- a/drivers/net/pppoe.c +++ b/drivers/net/pppoe.c @@ -1063,6 +1063,7 @@ static void *pppoe_seq_next(struct seq_file *seq, void *v, loff_t *pos) else { int hash = hash_item(po->pppoe_pa.sid, po->pppoe_pa.remote); + po = NULL; while (++hash < PPPOE_HASH_SIZE) { po = pn->hash_table[hash]; if (po) diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 4b53b58d75f..b82780d805f 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -2060,8 +2060,6 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) } } - pci_set_master(pdev); - /* ioremap MMIO region */ ioaddr = ioremap(pci_resource_start(pdev, region), R8169_REGS_SIZE); if (!ioaddr) { @@ -2089,6 +2087,8 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) RTL_W16(IntrStatus, 0xffff); + pci_set_master(pdev); + /* Identify chip attached to board */ rtl8169_get_mac_version(tp, ioaddr); @@ -3874,6 +3874,15 @@ static void rtl_shutdown(struct pci_dev *pdev) spin_unlock_irq(&tp->lock); if (system_state == SYSTEM_POWER_OFF) { + /* WoL fails with some 8168 when the receiver is disabled. */ + if (tp->features & RTL_FEATURE_WOL) { + pci_clear_master(pdev); + + RTL_W8(ChipCmd, CmdRxEnb); + /* PCI commit */ + RTL_R8(ChipCmd); + } + pci_wake_from_d3(pdev, true); pci_set_power_state(pdev, PCI_D3hot); } diff --git a/drivers/net/smc91x.h b/drivers/net/smc91x.h index f1f773b17fe..57a159fac99 100644 --- a/drivers/net/smc91x.h +++ b/drivers/net/smc91x.h @@ -186,7 +186,8 @@ static inline void SMC_outw(u16 val, void __iomem *ioaddr, int reg) #define SMC_outsb(a, r, p, l) writesb((a) + (r), p, (l)) #define SMC_IRQ_FLAGS (-1) /* from resource */ -#elif defined(CONFIG_MACH_LOGICPD_PXA270) +#elif defined(CONFIG_MACH_LOGICPD_PXA270) \ + || defined(CONFIG_MACH_NOMADIK_8815NHK) #define SMC_CAN_USE_8BIT 0 #define SMC_CAN_USE_16BIT 1 diff --git a/drivers/net/tokenring/ibmtr.c b/drivers/net/tokenring/ibmtr.c index 6472ba5cfc5..96d00c8f8d3 100644 --- a/drivers/net/tokenring/ibmtr.c +++ b/drivers/net/tokenring/ibmtr.c @@ -1912,7 +1912,7 @@ static int __init ibmtr_init(void) find_turbo_adapters(io); - for (i = 0; io[i] && (i < IBMTR_MAX_ADAPTERS); i++) { + for (i = 0; i < IBMTR_MAX_ADAPTERS && io[i]; i++) { struct net_device *dev; irq[i] = 0; mem[i] = 0; diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c index 49f3139a3fe..c150c485857 100644 --- a/drivers/net/wireless/airo.c +++ b/drivers/net/wireless/airo.c @@ -5918,20 +5918,19 @@ static int airo_set_essid(struct net_device *dev, readSsidRid(local, &SSID_rid); /* Check if we asked for `any' */ - if(dwrq->flags == 0) { + if (dwrq->flags == 0) { /* Just send an empty SSID list */ memset(&SSID_rid, 0, sizeof(SSID_rid)); } else { - int index = (dwrq->flags & IW_ENCODE_INDEX) - 1; + unsigned index = (dwrq->flags & IW_ENCODE_INDEX) - 1; /* Check the size of the string */ - if(dwrq->length > IW_ESSID_MAX_SIZE) { + if (dwrq->length > IW_ESSID_MAX_SIZE) return -E2BIG ; - } + /* Check if index is valid */ - if((index < 0) || (index >= 4)) { + if (index >= ARRAY_SIZE(SSID_rid.ssids)) return -EINVAL; - } /* Set the SSID */ memset(SSID_rid.ssids[index].ssid, 0, @@ -6819,7 +6818,7 @@ static int airo_set_txpow(struct net_device *dev, return -EINVAL; } clear_bit (FLAG_RADIO_OFF, &local->flags); - for (i = 0; cap_rid.txPowerLevels[i] && (i < 8); i++) + for (i = 0; i < 8 && cap_rid.txPowerLevels[i]; i++) if (v == cap_rid.txPowerLevels[i]) { readConfigRid(local, 1); local->config.txPower = v; diff --git a/drivers/net/wireless/ath/ath9k/eeprom.c b/drivers/net/wireless/ath/ath9k/eeprom.c index 9b1d960dc80..6fb1a8034b3 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom.c +++ b/drivers/net/wireless/ath/ath9k/eeprom.c @@ -460,7 +460,7 @@ static int ath9k_hw_4k_check_eeprom(struct ath_hw *ah) integer = swab32(eep->modalHeader.antCtrlCommon); eep->modalHeader.antCtrlCommon = integer; - for (i = 0; i < AR5416_MAX_CHAINS; i++) { + for (i = 0; i < AR5416_EEP4K_MAX_CHAINS; i++) { integer = swab32(eep->modalHeader.antCtrlChain[i]); eep->modalHeader.antCtrlChain[i] = integer; } @@ -914,7 +914,7 @@ static void ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah, ctlMode, numCtlModes, isHt40CtlMode, (pCtlMode[ctlMode] & EXT_ADDITIVE)); - for (i = 0; (i < AR5416_NUM_CTLS) && + for (i = 0; (i < AR5416_EEP4K_NUM_CTLS) && pEepData->ctlIndex[i]; i++) { DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, " LOOP-Ctlidx %d: cfgCtl 0x%2.2x " diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index 660d1a76292..6bb9602f347 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c @@ -737,8 +737,6 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) goto drop_unlock; } - spin_unlock_irqrestore(&priv->lock, flags); - hdr_len = ieee80211_hdrlen(fc); /* Find (or create) index into station table for destination station */ @@ -746,7 +744,7 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) if (sta_id == IWL_INVALID_STATION) { IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n", hdr->addr1); - goto drop; + goto drop_unlock; } IWL_DEBUG_TX(priv, "station Id %d\n", sta_id); @@ -764,14 +762,17 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) /* aggregation is on for this <sta,tid> */ if (info->flags & IEEE80211_TX_CTL_AMPDU) txq_id = priv->stations[sta_id].tid[tid].agg.txq_id; - priv->stations[sta_id].tid[tid].tfds_in_queue++; } txq = &priv->txq[txq_id]; swq_id = txq->swq_id; q = &txq->q; - spin_lock_irqsave(&priv->lock, flags); + if (unlikely(iwl_queue_space(q) < q->high_mark)) + goto drop_unlock; + + if (ieee80211_is_data_qos(fc)) + priv->stations[sta_id].tid[tid].tfds_in_queue++; /* Set up driver data for this TFD */ memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct iwl_tx_info)); @@ -917,7 +918,6 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) drop_unlock: spin_unlock_irqrestore(&priv->lock, flags); -drop: return -1; } EXPORT_SYMBOL(iwl_tx_skb); @@ -1194,6 +1194,8 @@ int iwl_tx_agg_start(struct iwl_priv *priv, const u8 *ra, u16 tid, u16 *ssn) IWL_ERR(priv, "Start AGG on invalid station\n"); return -ENXIO; } + if (unlikely(tid >= MAX_TID_COUNT)) + return -EINVAL; if (priv->stations[sta_id].tid[tid].agg.state != IWL_AGG_OFF) { IWL_ERR(priv, "Start AGG when state is not IWL_AGG_OFF !\n"); diff --git a/drivers/net/wireless/iwmc3200wifi/netdev.c b/drivers/net/wireless/iwmc3200wifi/netdev.c index 30116d1b448..35ec006c2d2 100644 --- a/drivers/net/wireless/iwmc3200wifi/netdev.c +++ b/drivers/net/wireless/iwmc3200wifi/netdev.c @@ -99,10 +99,8 @@ void *iwm_if_alloc(int sizeof_bus, struct device *dev, int ret = 0; wdev = iwm_wdev_alloc(sizeof_bus, dev); - if (!wdev) { - dev_err(dev, "no memory for wireless device instance\n"); - return ERR_PTR(-ENOMEM); - } + if (IS_ERR(wdev)) + return wdev; iwm = wdev_to_iwm(wdev); iwm->bus_ops = if_ops; diff --git a/drivers/net/wireless/libertas/assoc.c b/drivers/net/wireless/libertas/assoc.c index 385b50f4b10..1902b6f0b78 100644 --- a/drivers/net/wireless/libertas/assoc.c +++ b/drivers/net/wireless/libertas/assoc.c @@ -1,6 +1,7 @@ /* Copyright (C) 2006, Red Hat, Inc. */ #include <linux/types.h> +#include <linux/kernel.h> #include <linux/etherdevice.h> #include <linux/ieee80211.h> #include <linux/if_arp.h> @@ -43,21 +44,21 @@ static int get_common_rates(struct lbs_private *priv, u16 *rates_size) { u8 *card_rates = lbs_bg_rates; - size_t num_card_rates = sizeof(lbs_bg_rates); int ret = 0, i, j; - u8 tmp[30]; + u8 tmp[(ARRAY_SIZE(lbs_bg_rates) - 1) * (*rates_size - 1)]; size_t tmp_size = 0; /* For each rate in card_rates that exists in rate1, copy to tmp */ - for (i = 0; card_rates[i] && (i < num_card_rates); i++) { - for (j = 0; rates[j] && (j < *rates_size); j++) { + for (i = 0; i < ARRAY_SIZE(lbs_bg_rates) && card_rates[i]; i++) { + for (j = 0; j < *rates_size && rates[j]; j++) { if (rates[j] == card_rates[i]) tmp[tmp_size++] = card_rates[i]; } } lbs_deb_hex(LBS_DEB_JOIN, "AP rates ", rates, *rates_size); - lbs_deb_hex(LBS_DEB_JOIN, "card rates ", card_rates, num_card_rates); + lbs_deb_hex(LBS_DEB_JOIN, "card rates ", card_rates, + ARRAY_SIZE(lbs_bg_rates)); lbs_deb_hex(LBS_DEB_JOIN, "common rates", tmp, tmp_size); lbs_deb_join("TX data rate 0x%02x\n", priv->cur_rate); @@ -69,10 +70,7 @@ static int get_common_rates(struct lbs_private *priv, lbs_pr_alert("Previously set fixed data rate %#x isn't " "compatible with the network.\n", priv->cur_rate); ret = -1; - goto done; } - ret = 0; - done: memset(rates, 0, *rates_size); *rates_size = min_t(int, tmp_size, *rates_size); @@ -320,7 +318,7 @@ static int lbs_associate(struct lbs_private *priv, rates = (struct mrvl_ie_rates_param_set *) pos; rates->header.type = cpu_to_le16(TLV_TYPE_RATES); memcpy(&rates->rates, &bss->rates, MAX_RATES); - tmplen = MAX_RATES; + tmplen = min_t(u16, ARRAY_SIZE(rates->rates), MAX_RATES); if (get_common_rates(priv, rates->rates, &tmplen)) { ret = -1; goto done; @@ -594,7 +592,7 @@ static int lbs_adhoc_join(struct lbs_private *priv, /* Copy Data rates from the rates recorded in scan response */ memset(cmd.bss.rates, 0, sizeof(cmd.bss.rates)); - ratesize = min_t(u16, sizeof(cmd.bss.rates), MAX_RATES); + ratesize = min_t(u16, ARRAY_SIZE(cmd.bss.rates), MAX_RATES); memcpy(cmd.bss.rates, bss->rates, ratesize); if (get_common_rates(priv, cmd.bss.rates, &ratesize)) { lbs_deb_join("ADHOC_JOIN: get_common_rates returned error.\n"); diff --git a/drivers/net/wireless/libertas/scan.c b/drivers/net/wireless/libertas/scan.c index 601b5424967..6c95af3023c 100644 --- a/drivers/net/wireless/libertas/scan.c +++ b/drivers/net/wireless/libertas/scan.c @@ -5,6 +5,7 @@ * for sending scan commands to the firmware. */ #include <linux/types.h> +#include <linux/kernel.h> #include <linux/etherdevice.h> #include <linux/if_arp.h> #include <asm/unaligned.h> @@ -876,7 +877,7 @@ static inline char *lbs_translate_scan(struct lbs_private *priv, iwe.u.bitrate.disabled = 0; iwe.u.bitrate.value = 0; - for (j = 0; bss->rates[j] && (j < sizeof(bss->rates)); j++) { + for (j = 0; j < ARRAY_SIZE(bss->rates) && bss->rates[j]; j++) { /* Bit rate given in 500 kb/s units */ iwe.u.bitrate.value = bss->rates[j] * 500000; current_val = iwe_stream_add_value(info, start, current_val, |