diff options
Diffstat (limited to 'drivers/net/bnx2x/bnx2x_main.c')
-rw-r--r-- | drivers/net/bnx2x/bnx2x_main.c | 360 |
1 files changed, 98 insertions, 262 deletions
diff --git a/drivers/net/bnx2x/bnx2x_main.c b/drivers/net/bnx2x/bnx2x_main.c index a97a4a1c344f..f45c0caf3240 100644 --- a/drivers/net/bnx2x/bnx2x_main.c +++ b/drivers/net/bnx2x/bnx2x_main.c @@ -1,6 +1,6 @@ /* bnx2x_main.c: Broadcom Everest network driver. * - * Copyright (c) 2007-2010 Broadcom Corporation + * Copyright (c) 2007-2011 Broadcom Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -2036,7 +2036,7 @@ static int bnx2x_get_cmng_fns_mode(struct bnx2x *bp) return CMNG_FNS_NONE; } -static void bnx2x_read_mf_cfg(struct bnx2x *bp) +void bnx2x_read_mf_cfg(struct bnx2x *bp) { int vn, n = (CHIP_MODE_IS_4_PORT(bp) ? 2 : 1); @@ -2123,7 +2123,6 @@ static inline void bnx2x_link_sync_notify(struct bnx2x *bp) /* This function is called upon link interrupt */ static void bnx2x_link_attn(struct bnx2x *bp) { - u32 prev_link_status = bp->link_vars.link_status; /* Make sure that we are synced with the current statistics */ bnx2x_stats_handle(bp, STATS_EVENT_STOP); @@ -2168,17 +2167,15 @@ static void bnx2x_link_attn(struct bnx2x *bp) "single function mode without fairness\n"); } + __bnx2x_link_report(bp); + if (IS_MF(bp)) bnx2x_link_sync_notify(bp); - - /* indicate link status only if link status actually changed */ - if (prev_link_status != bp->link_vars.link_status) - bnx2x_link_report(bp); } void bnx2x__link_status_update(struct bnx2x *bp) { - if ((bp->state != BNX2X_STATE_OPEN) || (bp->flags & MF_FUNC_DIS)) + if (bp->state != BNX2X_STATE_OPEN) return; bnx2x_link_status_update(&bp->link_params, &bp->link_vars); @@ -2188,10 +2185,6 @@ void bnx2x__link_status_update(struct bnx2x *bp) else bnx2x_stats_handle(bp, STATS_EVENT_STOP); - /* the link status update could be the result of a DCC event - hence re-read the shmem mf configuration */ - bnx2x_read_mf_cfg(bp); - /* indicate link status */ bnx2x_link_report(bp); } @@ -3120,10 +3113,14 @@ static inline void bnx2x_attn_int_deasserted3(struct bnx2x *bp, u32 attn) 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); + /* Always call it here: bnx2x_link_report() will + * prevent the link indication duplication. + */ + bnx2x__link_status_update(bp); + if (bp->port.pmf && (val & DRV_STATUS_DCBX_NEGOTIATION_RESULTS) && bp->dcbx_enabled > 0) @@ -3904,10 +3901,9 @@ static void bnx2x_timer(unsigned long data) if (poll) { struct bnx2x_fastpath *fp = &bp->fp[0]; - int rc; bnx2x_tx_int(fp); - rc = bnx2x_rx_int(fp, 1000); + bnx2x_rx_int(fp, 1000); } if (!BP_NOMCP(bp)) { @@ -4062,7 +4058,6 @@ static void bnx2x_init_sb(struct bnx2x *bp, dma_addr_t mapping, int vfid, struct hc_status_block_data_e2 sb_data_e2; struct hc_status_block_data_e1x sb_data_e1x; struct hc_status_block_sm *hc_sm_p; - struct hc_index_data *hc_index_p; int data_size; u32 *sb_data_p; @@ -4083,7 +4078,6 @@ static void bnx2x_init_sb(struct bnx2x *bp, dma_addr_t mapping, int vfid, sb_data_e2.common.host_sb_addr.hi = U64_HI(mapping); sb_data_e2.common.host_sb_addr.lo = U64_LO(mapping); hc_sm_p = sb_data_e2.common.state_machine; - hc_index_p = sb_data_e2.index_data; sb_data_p = (u32 *)&sb_data_e2; data_size = sizeof(struct hc_status_block_data_e2)/sizeof(u32); } else { @@ -4097,7 +4091,6 @@ static void bnx2x_init_sb(struct bnx2x *bp, dma_addr_t mapping, int vfid, sb_data_e1x.common.host_sb_addr.hi = U64_HI(mapping); sb_data_e1x.common.host_sb_addr.lo = U64_LO(mapping); hc_sm_p = sb_data_e1x.common.state_machine; - hc_index_p = sb_data_e1x.index_data; sb_data_p = (u32 *)&sb_data_e1x; data_size = sizeof(struct hc_status_block_data_e1x)/sizeof(u32); } @@ -4454,7 +4447,7 @@ static void bnx2x_init_fp_sb(struct bnx2x *bp, int fp_idx) fp->state = BNX2X_FP_STATE_CLOSED; - fp->index = fp->cid = fp_idx; + fp->cid = fp_idx; fp->cl_id = BP_L_ID(bp) + fp_idx; fp->fw_sb_id = bp->base_fw_ndsb + fp->cl_id + CNIC_CONTEXT_USE; fp->igu_sb_id = bp->igu_base_sb + fp_idx + CNIC_CONTEXT_USE; @@ -4566,9 +4559,11 @@ gunzip_nomem1: static void bnx2x_gunzip_end(struct bnx2x *bp) { - kfree(bp->strm->workspace); - kfree(bp->strm); - bp->strm = NULL; + if (bp->strm) { + kfree(bp->strm->workspace); + kfree(bp->strm); + bp->strm = NULL; + } if (bp->gunzip_buf) { dma_free_coherent(&bp->pdev->dev, FW_BUF_SIZE, bp->gunzip_buf, @@ -5876,9 +5871,6 @@ int bnx2x_init_hw(struct bnx2x *bp, u32 load_code) bp->dmae_ready = 0; spin_lock_init(&bp->dmae_lock); - rc = bnx2x_gunzip_init(bp); - if (rc) - return rc; switch (load_code) { case FW_MSG_CODE_DRV_LOAD_COMMON: @@ -5922,80 +5914,10 @@ init_hw_err: void bnx2x_free_mem(struct bnx2x *bp) { - -#define BNX2X_PCI_FREE(x, y, size) \ - do { \ - if (x) { \ - dma_free_coherent(&bp->pdev->dev, size, (void *)x, y); \ - x = NULL; \ - y = 0; \ - } \ - } while (0) - -#define BNX2X_FREE(x) \ - do { \ - if (x) { \ - kfree((void *)x); \ - x = NULL; \ - } \ - } while (0) - - int i; + bnx2x_gunzip_end(bp); /* fastpath */ - /* Common */ - for_each_queue(bp, i) { -#ifdef BCM_CNIC - /* FCoE client uses default status block */ - if (IS_FCOE_IDX(i)) { - union host_hc_status_block *sb = - &bnx2x_fp(bp, i, status_blk); - memset(sb, 0, sizeof(union host_hc_status_block)); - bnx2x_fp(bp, i, status_blk_mapping) = 0; - } else { -#endif - /* status blocks */ - if (CHIP_IS_E2(bp)) - BNX2X_PCI_FREE(bnx2x_fp(bp, i, status_blk.e2_sb), - bnx2x_fp(bp, i, status_blk_mapping), - sizeof(struct host_hc_status_block_e2)); - else - BNX2X_PCI_FREE(bnx2x_fp(bp, i, status_blk.e1x_sb), - bnx2x_fp(bp, i, status_blk_mapping), - sizeof(struct host_hc_status_block_e1x)); -#ifdef BCM_CNIC - } -#endif - } - /* Rx */ - for_each_rx_queue(bp, i) { - - /* fastpath rx rings: rx_buf rx_desc rx_comp */ - BNX2X_FREE(bnx2x_fp(bp, i, rx_buf_ring)); - BNX2X_PCI_FREE(bnx2x_fp(bp, i, rx_desc_ring), - bnx2x_fp(bp, i, rx_desc_mapping), - sizeof(struct eth_rx_bd) * NUM_RX_BD); - - BNX2X_PCI_FREE(bnx2x_fp(bp, i, rx_comp_ring), - bnx2x_fp(bp, i, rx_comp_mapping), - sizeof(struct eth_fast_path_rx_cqe) * - NUM_RCQ_BD); - - /* SGE ring */ - BNX2X_FREE(bnx2x_fp(bp, i, rx_page_ring)); - BNX2X_PCI_FREE(bnx2x_fp(bp, i, rx_sge_ring), - bnx2x_fp(bp, i, rx_sge_mapping), - BCM_PAGE_SIZE * NUM_RX_SGE_PAGES); - } - /* Tx */ - for_each_tx_queue(bp, i) { - - /* fastpath tx rings: tx_buf tx_desc */ - BNX2X_FREE(bnx2x_fp(bp, i, tx_buf_ring)); - BNX2X_PCI_FREE(bnx2x_fp(bp, i, tx_desc_ring), - bnx2x_fp(bp, i, tx_desc_mapping), - sizeof(union eth_tx_bd_types) * NUM_TX_BD); - } + bnx2x_free_fp_mem(bp); /* end of fastpath */ BNX2X_PCI_FREE(bp->def_status_blk, bp->def_status_blk_mapping, @@ -6028,101 +5950,13 @@ void bnx2x_free_mem(struct bnx2x *bp) BCM_PAGE_SIZE * NUM_EQ_PAGES); BNX2X_FREE(bp->rx_indir_table); - -#undef BNX2X_PCI_FREE -#undef BNX2X_KFREE } -static inline void set_sb_shortcuts(struct bnx2x *bp, int index) -{ - union host_hc_status_block status_blk = bnx2x_fp(bp, index, status_blk); - if (CHIP_IS_E2(bp)) { - bnx2x_fp(bp, index, sb_index_values) = - (__le16 *)status_blk.e2_sb->sb.index_values; - bnx2x_fp(bp, index, sb_running_index) = - (__le16 *)status_blk.e2_sb->sb.running_index; - } else { - bnx2x_fp(bp, index, sb_index_values) = - (__le16 *)status_blk.e1x_sb->sb.index_values; - bnx2x_fp(bp, index, sb_running_index) = - (__le16 *)status_blk.e1x_sb->sb.running_index; - } -} int bnx2x_alloc_mem(struct bnx2x *bp) { -#define BNX2X_PCI_ALLOC(x, y, size) \ - do { \ - x = dma_alloc_coherent(&bp->pdev->dev, size, y, GFP_KERNEL); \ - if (x == NULL) \ - goto alloc_mem_err; \ - memset(x, 0, size); \ - } while (0) - -#define BNX2X_ALLOC(x, size) \ - do { \ - x = kzalloc(size, GFP_KERNEL); \ - if (x == NULL) \ - goto alloc_mem_err; \ - } while (0) - - int i; - - /* fastpath */ - /* Common */ - for_each_queue(bp, i) { - union host_hc_status_block *sb = &bnx2x_fp(bp, i, status_blk); - bnx2x_fp(bp, i, bp) = bp; - /* status blocks */ -#ifdef BCM_CNIC - if (!IS_FCOE_IDX(i)) { -#endif - if (CHIP_IS_E2(bp)) - BNX2X_PCI_ALLOC(sb->e2_sb, - &bnx2x_fp(bp, i, status_blk_mapping), - sizeof(struct host_hc_status_block_e2)); - else - BNX2X_PCI_ALLOC(sb->e1x_sb, - &bnx2x_fp(bp, i, status_blk_mapping), - sizeof(struct host_hc_status_block_e1x)); -#ifdef BCM_CNIC - } -#endif - set_sb_shortcuts(bp, i); - } - /* Rx */ - for_each_queue(bp, i) { - - /* fastpath rx rings: rx_buf rx_desc rx_comp */ - BNX2X_ALLOC(bnx2x_fp(bp, i, rx_buf_ring), - sizeof(struct sw_rx_bd) * NUM_RX_BD); - BNX2X_PCI_ALLOC(bnx2x_fp(bp, i, rx_desc_ring), - &bnx2x_fp(bp, i, rx_desc_mapping), - sizeof(struct eth_rx_bd) * NUM_RX_BD); - - BNX2X_PCI_ALLOC(bnx2x_fp(bp, i, rx_comp_ring), - &bnx2x_fp(bp, i, rx_comp_mapping), - sizeof(struct eth_fast_path_rx_cqe) * - NUM_RCQ_BD); - - /* SGE ring */ - BNX2X_ALLOC(bnx2x_fp(bp, i, rx_page_ring), - sizeof(struct sw_rx_page) * NUM_RX_SGE); - BNX2X_PCI_ALLOC(bnx2x_fp(bp, i, rx_sge_ring), - &bnx2x_fp(bp, i, rx_sge_mapping), - BCM_PAGE_SIZE * NUM_RX_SGE_PAGES); - } - /* Tx */ - for_each_queue(bp, i) { - - /* fastpath tx rings: tx_buf tx_desc */ - BNX2X_ALLOC(bnx2x_fp(bp, i, tx_buf_ring), - sizeof(struct sw_tx_bd) * NUM_TX_BD); - BNX2X_PCI_ALLOC(bnx2x_fp(bp, i, tx_desc_ring), - &bnx2x_fp(bp, i, tx_desc_mapping), - sizeof(union eth_tx_bd_types) * NUM_TX_BD); - } - /* end of fastpath */ + if (bnx2x_gunzip_init(bp)) + return -ENOMEM; #ifdef BCM_CNIC if (CHIP_IS_E2(bp)) @@ -6162,14 +5996,18 @@ int bnx2x_alloc_mem(struct bnx2x *bp) BNX2X_ALLOC(bp->rx_indir_table, sizeof(bp->rx_indir_table[0]) * TSTORM_INDIRECTION_TABLE_SIZE); + + /* fastpath */ + /* need to be done at the end, since it's self adjusting to amount + * of memory available for RSS queues + */ + if (bnx2x_alloc_fp_mem(bp)) + goto alloc_mem_err; return 0; alloc_mem_err: bnx2x_free_mem(bp); return -ENOMEM; - -#undef BNX2X_PCI_ALLOC -#undef BNX2X_ALLOC } /* @@ -6197,14 +6035,14 @@ static int bnx2x_func_stop(struct bnx2x *bp) } /** - * Sets a MAC in a CAM for a few L2 Clients for E1x chips + * bnx2x_set_mac_addr_gen - set a MAC in a CAM for a few L2 Clients for E1x chips * - * @param bp driver descriptor - * @param set set or clear an entry (1 or 0) - * @param mac pointer to a buffer containing a MAC - * @param cl_bit_vec bit vector of clients to register a MAC for - * @param cam_offset offset in a CAM to use - * @param is_bcast is the set MAC a broadcast address (for E1 only) + * @bp: driver handle + * @set: set or clear an entry (1 or 0) + * @mac: pointer to a buffer containing a MAC + * @cl_bit_vec: bit vector of clients to register a MAC for + * @cam_offset: offset in a CAM to use + * @is_bcast: is the set MAC a broadcast address (for E1 only) */ static void bnx2x_set_mac_addr_gen(struct bnx2x *bp, int set, const u8 *mac, u32 cl_bit_vec, u8 cam_offset, @@ -6564,14 +6402,13 @@ void bnx2x_invalidate_e1h_mc_list(struct bnx2x *bp) #ifdef BCM_CNIC /** - * Set iSCSI MAC(s) at the next enties in the CAM after the ETH - * MAC(s). This function will wait until the ramdord completion - * returns. + * bnx2x_set_iscsi_eth_mac_addr - set iSCSI MAC(s). * - * @param bp driver handle - * @param set set or clear the CAM entry + * @bp: driver handle + * @set: set or clear the CAM entry * - * @return 0 if cussess, -ENODEV if ramrod doesn't return. + * This function will wait until the ramdord completion returns. + * Return 0 if success, -ENODEV if ramrod doesn't return. */ static int bnx2x_set_iscsi_eth_mac_addr(struct bnx2x *bp, int set) { @@ -6592,14 +6429,13 @@ static int bnx2x_set_iscsi_eth_mac_addr(struct bnx2x *bp, int set) } /** - * Set FCoE L2 MAC(s) at the next enties in the CAM after the - * ETH MAC(s). This function will wait until the ramdord - * completion returns. + * bnx2x_set_fip_eth_mac_addr - set FCoE L2 MAC(s) * - * @param bp driver handle - * @param set set or clear the CAM entry + * @bp: driver handle + * @set: set or clear the CAM entry * - * @return 0 if cussess, -ENODEV if ramrod doesn't return. + * This function will wait until the ramrod completion returns. + * Returns 0 if success, -ENODEV if ramrod doesn't return. */ int bnx2x_set_fip_eth_mac_addr(struct bnx2x *bp, int set) { @@ -6803,12 +6639,11 @@ static int bnx2x_setup_fw_client(struct bnx2x *bp, } /** - * Configure interrupt mode according to current configuration. - * In case of MSI-X it will also try to enable MSI-X. + * bnx2x_set_int_mode - configure interrupt mode * - * @param bp + * @bp: driver handle * - * @return int + * In case of MSI-X it will also try to enable MSI-X. */ static int __devinit bnx2x_set_int_mode(struct bnx2x *bp) { @@ -7392,10 +7227,11 @@ static void bnx2x_clp_reset_prep(struct bnx2x *bp, u32 *magic_val) MF_CFG_WR(bp, shared_mf_config.clp_mb, val | SHARED_MF_CLP_MAGIC); } -/* Restore the value of the `magic' bit. +/** + * bnx2x_clp_reset_done - restore the value of the `magic' bit. * - * @param pdev Device handle. - * @param magic_val Old value of the `magic' bit. + * @bp: driver handle + * @magic_val: old value of the `magic' bit. */ static void bnx2x_clp_reset_done(struct bnx2x *bp, u32 magic_val) { @@ -7406,10 +7242,12 @@ static void bnx2x_clp_reset_done(struct bnx2x *bp, u32 magic_val) } /** - * Prepares for MCP reset: takes care of CLP configurations. + * bnx2x_reset_mcp_prep - prepare for MCP reset. * - * @param bp - * @param magic_val Old value of 'magic' bit. + * @bp: driver handle + * @magic_val: old value of 'magic' bit. + * + * Takes care of CLP configurations. */ static void bnx2x_reset_mcp_prep(struct bnx2x *bp, u32 *magic_val) { @@ -7434,10 +7272,10 @@ static void bnx2x_reset_mcp_prep(struct bnx2x *bp, u32 *magic_val) #define MCP_TIMEOUT 5000 /* 5 seconds (in ms) */ #define MCP_ONE_TIMEOUT 100 /* 100 ms */ -/* Waits for MCP_ONE_TIMEOUT or MCP_ONE_TIMEOUT*10, - * depending on the HW type. +/** + * bnx2x_mcp_wait_one - wait for MCP_ONE_TIMEOUT * - * @param bp + * @bp: driver handle */ static inline void bnx2x_mcp_wait_one(struct bnx2x *bp) { @@ -8059,13 +7897,9 @@ static void __devinit bnx2x_get_common_hwinfo(struct bnx2x *bp) (val >= REQ_BC_VER_4_VRFY_SPECIFIC_PHY_OPT_MDL) ? FEATURE_CONFIG_BC_SUPPORTS_DUAL_PHY_OPT_MDL_VRFY : 0; - if (BP_E1HVN(bp) == 0) { - pci_read_config_word(bp->pdev, bp->pm_cap + PCI_PM_PMC, &pmc); - bp->flags |= (pmc & PCI_PM_CAP_PME_D3cold) ? 0 : NO_WOL_FLAG; - } else { - /* no WOL capability for E1HVN != 0 */ - bp->flags |= NO_WOL_FLAG; - } + pci_read_config_word(bp->pdev, bp->pm_cap + PCI_PM_PMC, &pmc); + bp->flags |= (pmc & PCI_PM_CAP_PME_D3cold) ? 0 : NO_WOL_FLAG; + BNX2X_DEV_INFO("%sWoL capable\n", (bp->flags & NO_WOL_FLAG) ? "not " : ""); @@ -8571,15 +8405,6 @@ static void __devinit bnx2x_get_mac_hwinfo(struct bnx2x *bp) BNX2X_DEV_INFO("Read iSCSI MAC: " "0x%x:0x%04x\n", val2, val); bnx2x_set_mac_buf(iscsi_mac, val, val2); - - /* Disable iSCSI OOO if MAC configuration is - * invalid. - */ - if (!is_valid_ether_addr(iscsi_mac)) { - bp->flags |= NO_ISCSI_OOO_FLAG | - NO_ISCSI_FLAG; - memset(iscsi_mac, 0, ETH_ALEN); - } } else bp->flags |= NO_ISCSI_OOO_FLAG | NO_ISCSI_FLAG; @@ -8592,13 +8417,6 @@ static void __devinit bnx2x_get_mac_hwinfo(struct bnx2x *bp) "0x%x:0x%04x\n", val2, val); bnx2x_set_mac_buf(fip_mac, val, val2); - /* Disable FCoE if MAC configuration is - * invalid. - */ - if (!is_valid_ether_addr(fip_mac)) { - bp->flags |= NO_FCOE_FLAG; - memset(bp->fip_mac, 0, ETH_ALEN); - } } else bp->flags |= NO_FCOE_FLAG; } @@ -8629,13 +8447,29 @@ static void __devinit bnx2x_get_mac_hwinfo(struct bnx2x *bp) else if (!IS_MF(bp)) memcpy(fip_mac, iscsi_mac, ETH_ALEN); } + + /* Disable iSCSI if MAC configuration is + * invalid. + */ + if (!is_valid_ether_addr(iscsi_mac)) { + bp->flags |= NO_ISCSI_FLAG; + memset(iscsi_mac, 0, ETH_ALEN); + } + + /* Disable FCoE if MAC configuration is + * invalid. + */ + if (!is_valid_ether_addr(fip_mac)) { + bp->flags |= NO_FCOE_FLAG; + memset(bp->fip_mac, 0, ETH_ALEN); + } #endif } static int __devinit bnx2x_get_hwinfo(struct bnx2x *bp) { int /*abs*/func = BP_ABS_FUNC(bp); - int vn, port; + int vn; u32 val = 0; int rc = 0; @@ -8670,7 +8504,6 @@ 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, @@ -8904,8 +8737,6 @@ static int __devinit bnx2x_init_bp(struct bnx2x *bp) bp->multi_mode = multi_mode; bp->int_mode = int_mode; - bp->dev->features |= NETIF_F_GRO; - /* Set TPA flags */ if (disable_tpa) { bp->flags &= ~TPA_ENABLE_FLAG; @@ -8925,8 +8756,6 @@ static int __devinit bnx2x_init_bp(struct bnx2x *bp) bp->tx_ring_size = MAX_TX_AVAIL; - bp->rx_csum = 1; - /* make sure that the numbers are in the right granularity */ bp->tx_ticks = (50 / BNX2X_BTR) * BNX2X_BTR; bp->rx_ticks = (25 / BNX2X_BTR) * BNX2X_BTR; @@ -9304,6 +9133,8 @@ static const struct net_device_ops bnx2x_netdev_ops = { .ndo_validate_addr = eth_validate_addr, .ndo_do_ioctl = bnx2x_ioctl, .ndo_change_mtu = bnx2x_change_mtu, + .ndo_fix_features = bnx2x_fix_features, + .ndo_set_features = bnx2x_set_features, .ndo_tx_timeout = bnx2x_tx_timeout, #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = poll_bnx2x, @@ -9430,20 +9261,20 @@ static int __devinit bnx2x_init_dev(struct pci_dev *pdev, dev->netdev_ops = &bnx2x_netdev_ops; bnx2x_set_ethtool_ops(dev); - dev->features |= NETIF_F_SG; - dev->features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM; + + dev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | + NETIF_F_TSO | NETIF_F_TSO_ECN | NETIF_F_TSO6 | + NETIF_F_RXCSUM | NETIF_F_LRO | NETIF_F_HW_VLAN_TX; + + dev->vlan_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | + NETIF_F_TSO | NETIF_F_TSO_ECN | NETIF_F_TSO6 | NETIF_F_HIGHDMA; + + dev->features |= dev->hw_features | NETIF_F_HW_VLAN_RX; if (bp->flags & USING_DAC_FLAG) dev->features |= NETIF_F_HIGHDMA; - dev->features |= (NETIF_F_TSO | NETIF_F_TSO_ECN); - dev->features |= NETIF_F_TSO6; - dev->features |= (NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX); - dev->vlan_features |= NETIF_F_SG; - dev->vlan_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM; - if (bp->flags & USING_DAC_FLAG) - dev->vlan_features |= NETIF_F_HIGHDMA; - dev->vlan_features |= (NETIF_F_TSO | NETIF_F_TSO_ECN); - dev->vlan_features |= NETIF_F_TSO6; + /* Add Loopback capability to the device */ + dev->hw_features |= NETIF_F_LOOPBACK; #ifdef BCM_DCBNL dev->dcbnl_ops = &bnx2x_dcbnl_ops; @@ -10342,6 +10173,11 @@ static int bnx2x_drv_ctl(struct net_device *dev, struct drv_ctl_info *ctl) break; } + case DRV_CTL_ISCSI_STOPPED_CMD: { + bnx2x_dcbx_set_params(bp, BNX2X_DCBX_STATE_ISCSI_STOPPED); + break; + } + default: BNX2X_ERR("unknown command %x\n", ctl->cmd); rc = -EINVAL; |