diff options
Diffstat (limited to 'drivers/net/ethernet/emulex/benet/be_main.c')
-rw-r--r-- | drivers/net/ethernet/emulex/benet/be_main.c | 370 |
1 files changed, 178 insertions, 192 deletions
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index 679b8041e43..d6a232a300a 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c @@ -114,6 +114,13 @@ static const char * const ue_status_hi_desc[] = { "Unknown" }; +/* Is BE in a multi-channel mode */ +static inline bool be_is_mc(struct be_adapter *adapter) { + return (adapter->function_mode & FLEX10_MODE || + adapter->function_mode & VNIC_MODE || + adapter->function_mode & UMC_ENABLED); +} + static void be_queue_free(struct be_adapter *adapter, struct be_queue_info *q) { struct be_dma_mem *mem = &q->dma_mem; @@ -636,17 +643,17 @@ static int make_tx_wrbs(struct be_adapter *adapter, struct be_queue_info *txq, } for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { - struct skb_frag_struct *frag = + const struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[i]; busaddr = skb_frag_dma_map(dev, frag, 0, - frag->size, DMA_TO_DEVICE); + skb_frag_size(frag), DMA_TO_DEVICE); if (dma_mapping_error(dev, busaddr)) goto dma_err; wrb = queue_head_node(txq); - wrb_fill(wrb, busaddr, frag->size); + wrb_fill(wrb, busaddr, skb_frag_size(frag)); be_dws_cpu_to_le(wrb, sizeof(*wrb)); queue_head_inc(txq); - copied += frag->size; + copied += skb_frag_size(frag); } if (dummy_wrb) { @@ -796,7 +803,7 @@ static void be_vlan_rem_vid(struct net_device *netdev, u16 vid) be_vid_config(adapter, false, 0); } -static void be_set_multicast_list(struct net_device *netdev) +static void be_set_rx_mode(struct net_device *netdev) { struct be_adapter *adapter = netdev_priv(netdev); @@ -1069,7 +1076,7 @@ static void skb_fill_rx_data(struct be_adapter *adapter, struct be_rx_obj *rxo, skb_frag_set_page(skb, 0, page_info->page); skb_shinfo(skb)->frags[0].page_offset = page_info->page_offset + hdr_len; - skb_shinfo(skb)->frags[0].size = curr_frag_len - hdr_len; + skb_frag_size_set(&skb_shinfo(skb)->frags[0], curr_frag_len - hdr_len); skb->data_len = curr_frag_len - hdr_len; skb->truesize += rx_frag_size; skb->tail += hdr_len; @@ -1095,13 +1102,13 @@ static void skb_fill_rx_data(struct be_adapter *adapter, struct be_rx_obj *rxo, skb_frag_set_page(skb, j, page_info->page); skb_shinfo(skb)->frags[j].page_offset = page_info->page_offset; - skb_shinfo(skb)->frags[j].size = 0; + skb_frag_size_set(&skb_shinfo(skb)->frags[j], 0); skb_shinfo(skb)->nr_frags++; } else { put_page(page_info->page); } - skb_shinfo(skb)->frags[j].size += curr_frag_len; + skb_frag_size_add(&skb_shinfo(skb)->frags[j], curr_frag_len); skb->len += curr_frag_len; skb->data_len += curr_frag_len; skb->truesize += rx_frag_size; @@ -1176,11 +1183,11 @@ static void be_rx_compl_process_gro(struct be_adapter *adapter, skb_frag_set_page(skb, j, page_info->page); skb_shinfo(skb)->frags[j].page_offset = page_info->page_offset; - skb_shinfo(skb)->frags[j].size = 0; + skb_frag_size_set(&skb_shinfo(skb)->frags[j], 0); } else { put_page(page_info->page); } - skb_shinfo(skb)->frags[j].size += curr_frag_len; + skb_frag_size_add(&skb_shinfo(skb)->frags[j], curr_frag_len); skb->truesize += rx_frag_size; remaining -= curr_frag_len; index_inc(&rxcp->rxq_idx, rxq->len); @@ -1289,7 +1296,7 @@ static struct be_rx_compl_info *be_rx_compl_get(struct be_rx_obj *rxo) if (rxcp->vlanf) { /* vlanf could be wrongly set in some cards. * ignore if vtm is not set */ - if ((adapter->function_mode & 0x400) && !rxcp->vtm) + if ((adapter->function_mode & FLEX10_MODE) && !rxcp->vtm) rxcp->vlanf = 0; if (!lancer_chip(adapter)) @@ -1633,6 +1640,17 @@ static void be_tx_queues_destroy(struct be_adapter *adapter) be_queue_free(adapter, q); } +static int be_num_txqs_want(struct be_adapter *adapter) +{ + if ((num_vfs && adapter->sriov_enabled) || + be_is_mc(adapter) || + lancer_chip(adapter) || !be_physfn(adapter) || + adapter->generation == BE_GEN2) + return 1; + else + return MAX_TX_QS; +} + /* One TX event queue is shared by all TX compl qs */ static int be_tx_queues_create(struct be_adapter *adapter) { @@ -1640,6 +1658,11 @@ static int be_tx_queues_create(struct be_adapter *adapter) struct be_tx_obj *txo; u8 i; + adapter->num_tx_qs = be_num_txqs_want(adapter); + if (adapter->num_tx_qs != MAX_TX_QS) + netif_set_real_num_tx_queues(adapter->netdev, + adapter->num_tx_qs); + adapter->tx_eq.max_eqd = 0; adapter->tx_eq.min_eqd = 0; adapter->tx_eq.cur_eqd = 96; @@ -1702,7 +1725,8 @@ static void be_rx_queues_destroy(struct be_adapter *adapter) static u32 be_num_rxqs_want(struct be_adapter *adapter) { if ((adapter->function_caps & BE_FUNCTION_CAPS_RSS) && - !adapter->sriov_enabled && !(adapter->function_mode & 0x400)) { + !adapter->sriov_enabled && be_physfn(adapter) && + !be_is_mc(adapter)) { return 1 + MAX_RSS_QS; /* one default non-RSS queue */ } else { dev_warn(&adapter->pdev->dev, @@ -2069,7 +2093,7 @@ done: return; } -static void be_sriov_enable(struct be_adapter *adapter) +static int be_sriov_enable(struct be_adapter *adapter) { be_check_sriov_fn_type(adapter); #ifdef CONFIG_PCI_IOV @@ -2091,8 +2115,17 @@ static void be_sriov_enable(struct be_adapter *adapter) status = pci_enable_sriov(adapter->pdev, num_vfs); adapter->sriov_enabled = status ? false : true; + + if (adapter->sriov_enabled) { + adapter->vf_cfg = kcalloc(num_vfs, + sizeof(struct be_vf_cfg), + GFP_KERNEL); + if (!adapter->vf_cfg) + return -ENOMEM; + } } #endif + return 0; } static void be_sriov_disable(struct be_adapter *adapter) @@ -2100,6 +2133,7 @@ static void be_sriov_disable(struct be_adapter *adapter) #ifdef CONFIG_PCI_IOV if (adapter->sriov_enabled) { pci_disable_sriov(adapter->pdev); + kfree(adapter->vf_cfg); adapter->sriov_enabled = false; } #endif @@ -2352,17 +2386,6 @@ static int be_open(struct net_device *netdev) /* Now that interrupts are on we can process async mcc */ be_async_mcc_enable(adapter); - if (be_physfn(adapter)) { - status = be_vid_config(adapter, false, 0); - if (status) - goto err; - - status = be_cmd_set_flow_control(adapter, - adapter->tx_fc, adapter->rx_fc); - if (status) - goto err; - } - return 0; err: be_close(adapter->netdev); @@ -2416,7 +2439,7 @@ static int be_setup_wol(struct be_adapter *adapter, bool enable) */ static inline int be_vf_eth_addr_config(struct be_adapter *adapter) { - u32 vf = 0; + u32 vf; int status = 0; u8 mac[ETH_ALEN]; @@ -2438,7 +2461,7 @@ static inline int be_vf_eth_addr_config(struct be_adapter *adapter) return status; } -static inline void be_vf_eth_addr_rem(struct be_adapter *adapter) +static void be_vf_clear(struct be_adapter *adapter) { u32 vf; @@ -2448,135 +2471,159 @@ static inline void be_vf_eth_addr_rem(struct be_adapter *adapter) adapter->vf_cfg[vf].vf_if_handle, adapter->vf_cfg[vf].vf_pmac_id, vf + 1); } + + for (vf = 0; vf < num_vfs; vf++) + if (adapter->vf_cfg[vf].vf_if_handle) + be_cmd_if_destroy(adapter, + adapter->vf_cfg[vf].vf_if_handle, vf + 1); } -static int be_setup(struct be_adapter *adapter) +static int be_clear(struct be_adapter *adapter) { - struct net_device *netdev = adapter->netdev; - u32 cap_flags, en_flags, vf = 0; - int status; - u8 mac[ETH_ALEN]; + if (be_physfn(adapter) && adapter->sriov_enabled) + be_vf_clear(adapter); - be_cmd_req_native_mode(adapter); + be_cmd_if_destroy(adapter, adapter->if_handle, 0); - cap_flags = en_flags = BE_IF_FLAGS_UNTAGGED | - BE_IF_FLAGS_BROADCAST | - BE_IF_FLAGS_MULTICAST; + be_mcc_queues_destroy(adapter); + be_rx_queues_destroy(adapter); + be_tx_queues_destroy(adapter); + adapter->eq_next_idx = 0; - if (be_physfn(adapter)) { - cap_flags |= BE_IF_FLAGS_MCAST_PROMISCUOUS | - BE_IF_FLAGS_PROMISCUOUS | - BE_IF_FLAGS_PASS_L3L4_ERRORS; - en_flags |= BE_IF_FLAGS_PASS_L3L4_ERRORS; - - if (adapter->function_caps & BE_FUNCTION_CAPS_RSS) { - cap_flags |= BE_IF_FLAGS_RSS; - en_flags |= BE_IF_FLAGS_RSS; - } - } + adapter->be3_native = false; + adapter->promiscuous = false; - status = be_cmd_if_create(adapter, cap_flags, en_flags, - netdev->dev_addr, false/* pmac_invalid */, - &adapter->if_handle, &adapter->pmac_id, 0); - if (status != 0) - goto do_none; + /* tell fw we're done with firing cmds */ + be_cmd_fw_clean(adapter); + return 0; +} - if (be_physfn(adapter)) { - if (adapter->sriov_enabled) { - while (vf < num_vfs) { - cap_flags = en_flags = BE_IF_FLAGS_UNTAGGED | - BE_IF_FLAGS_BROADCAST; - status = be_cmd_if_create(adapter, cap_flags, - en_flags, mac, true, +static int be_vf_setup(struct be_adapter *adapter) +{ + u32 cap_flags, en_flags, vf; + u16 lnk_speed; + int status; + + cap_flags = en_flags = BE_IF_FLAGS_UNTAGGED | BE_IF_FLAGS_BROADCAST; + for (vf = 0; vf < num_vfs; vf++) { + status = be_cmd_if_create(adapter, cap_flags, en_flags, NULL, &adapter->vf_cfg[vf].vf_if_handle, NULL, vf+1); - if (status) { - dev_err(&adapter->pdev->dev, - "Interface Create failed for VF %d\n", - vf); - goto if_destroy; - } - adapter->vf_cfg[vf].vf_pmac_id = - BE_INVALID_PMAC_ID; - vf++; - } - } - } else { - status = be_cmd_mac_addr_query(adapter, mac, - MAC_ADDRESS_TYPE_NETWORK, false, adapter->if_handle); - if (!status) { - memcpy(adapter->netdev->dev_addr, mac, ETH_ALEN); - memcpy(adapter->netdev->perm_addr, mac, ETH_ALEN); - } + if (status) + goto err; + adapter->vf_cfg[vf].vf_pmac_id = BE_INVALID_PMAC_ID; } + if (!lancer_chip(adapter)) { + status = be_vf_eth_addr_config(adapter); + if (status) + goto err; + } + + for (vf = 0; vf < num_vfs; vf++) { + status = be_cmd_link_status_query(adapter, NULL, &lnk_speed, + vf + 1); + if (status) + goto err; + adapter->vf_cfg[vf].vf_tx_rate = lnk_speed * 10; + } + return 0; +err: + return status; +} + +static int be_setup(struct be_adapter *adapter) +{ + struct net_device *netdev = adapter->netdev; + u32 cap_flags, en_flags; + u32 tx_fc, rx_fc; + int status; + u8 mac[ETH_ALEN]; + + /* Allow all priorities by default. A GRP5 evt may modify this */ + adapter->vlan_prio_bmap = 0xff; + adapter->link_speed = -1; + + be_cmd_req_native_mode(adapter); + status = be_tx_queues_create(adapter); if (status != 0) - goto if_destroy; + goto err; status = be_rx_queues_create(adapter); if (status != 0) - goto tx_qs_destroy; - - /* Allow all priorities by default. A GRP5 evt may modify this */ - adapter->vlan_prio_bmap = 0xff; + goto err; status = be_mcc_queues_create(adapter); if (status != 0) - goto rx_qs_destroy; - - adapter->link_speed = -1; + goto err; - be_cmd_get_fw_ver(adapter, adapter->fw_ver, NULL); + memset(mac, 0, ETH_ALEN); + status = be_cmd_mac_addr_query(adapter, mac, MAC_ADDRESS_TYPE_NETWORK, + true /*permanent */, 0); + if (status) + return status; + memcpy(adapter->netdev->dev_addr, mac, ETH_ALEN); + memcpy(adapter->netdev->perm_addr, mac, ETH_ALEN); - pcie_set_readrq(adapter->pdev, 4096); - return 0; + en_flags = BE_IF_FLAGS_UNTAGGED | BE_IF_FLAGS_BROADCAST | + BE_IF_FLAGS_MULTICAST | BE_IF_FLAGS_PASS_L3L4_ERRORS; + cap_flags = en_flags | BE_IF_FLAGS_MCAST_PROMISCUOUS | + BE_IF_FLAGS_PROMISCUOUS; + if (adapter->function_caps & BE_FUNCTION_CAPS_RSS) { + cap_flags |= BE_IF_FLAGS_RSS; + en_flags |= BE_IF_FLAGS_RSS; + } + status = be_cmd_if_create(adapter, cap_flags, en_flags, + netdev->dev_addr, &adapter->if_handle, + &adapter->pmac_id, 0); + if (status != 0) + goto err; -rx_qs_destroy: - be_rx_queues_destroy(adapter); -tx_qs_destroy: - be_tx_queues_destroy(adapter); -if_destroy: - if (be_physfn(adapter) && adapter->sriov_enabled) - for (vf = 0; vf < num_vfs; vf++) - if (adapter->vf_cfg[vf].vf_if_handle) - be_cmd_if_destroy(adapter, - adapter->vf_cfg[vf].vf_if_handle, - vf + 1); - be_cmd_if_destroy(adapter, adapter->if_handle, 0); -do_none: - return status; -} + /* For BEx, the VF's permanent mac queried from card is incorrect. + * Query the mac configued by the PF using if_handle + */ + if (!be_physfn(adapter) && !lancer_chip(adapter)) { + status = be_cmd_mac_addr_query(adapter, mac, + MAC_ADDRESS_TYPE_NETWORK, false, adapter->if_handle); + if (!status) { + memcpy(adapter->netdev->dev_addr, mac, ETH_ALEN); + memcpy(adapter->netdev->perm_addr, mac, ETH_ALEN); + } + } -static int be_clear(struct be_adapter *adapter) -{ - int vf; + be_cmd_get_fw_ver(adapter, adapter->fw_ver, NULL); - if (be_physfn(adapter) && adapter->sriov_enabled) - be_vf_eth_addr_rem(adapter); + status = be_vid_config(adapter, false, 0); + if (status) + goto err; - be_mcc_queues_destroy(adapter); - be_rx_queues_destroy(adapter); - be_tx_queues_destroy(adapter); - adapter->eq_next_idx = 0; + be_set_rx_mode(adapter->netdev); - if (be_physfn(adapter) && adapter->sriov_enabled) - for (vf = 0; vf < num_vfs; vf++) - if (adapter->vf_cfg[vf].vf_if_handle) - be_cmd_if_destroy(adapter, - adapter->vf_cfg[vf].vf_if_handle, - vf + 1); + status = be_cmd_get_flow_control(adapter, &tx_fc, &rx_fc); + if (status) + goto err; + if (rx_fc != adapter->rx_fc || tx_fc != adapter->tx_fc) { + status = be_cmd_set_flow_control(adapter, adapter->tx_fc, + adapter->rx_fc); + if (status) + goto err; + } - be_cmd_if_destroy(adapter, adapter->if_handle, 0); + pcie_set_readrq(adapter->pdev, 4096); - adapter->be3_native = 0; + if (be_physfn(adapter) && adapter->sriov_enabled) { + status = be_vf_setup(adapter); + if (status) + goto err; + } - /* tell fw we're done with firing cmds */ - be_cmd_fw_clean(adapter); return 0; +err: + be_clear(adapter); + return status; } - #define FW_FILE_HDR_SIGN "ServerEngines Corp. " static bool be_flash_redboot(struct be_adapter *adapter, const u8 *p, u32 img_start, int image_size, @@ -2915,7 +2962,7 @@ static struct net_device_ops be_netdev_ops = { .ndo_open = be_open, .ndo_stop = be_close, .ndo_start_xmit = be_xmit, - .ndo_set_rx_mode = be_set_multicast_list, + .ndo_set_rx_mode = be_set_rx_mode, .ndo_set_mac_address = be_mac_addr_set, .ndo_change_mtu = be_change_mtu, .ndo_get_stats64 = be_get_stats64, @@ -2948,10 +2995,6 @@ static void be_netdev_init(struct net_device *netdev) netdev->flags |= IFF_MULTICAST; - /* Default settings for Rx and Tx flow control */ - adapter->rx_fc = true; - adapter->tx_fc = true; - netif_set_gso_max_size(netdev, 65535); BE_SET_NETDEV_OPS(netdev, &be_netdev_ops); @@ -3132,7 +3175,6 @@ static void __devexit be_remove(struct pci_dev *pdev) be_ctrl_cleanup(adapter); - kfree(adapter->vf_cfg); be_sriov_disable(adapter); be_msix_disable(adapter); @@ -3147,31 +3189,13 @@ static void __devexit be_remove(struct pci_dev *pdev) static int be_get_config(struct be_adapter *adapter) { int status; - u8 mac[ETH_ALEN]; status = be_cmd_query_fw_cfg(adapter, &adapter->port_num, &adapter->function_mode, &adapter->function_caps); if (status) return status; - memset(mac, 0, ETH_ALEN); - - /* A default permanent address is given to each VF for Lancer*/ - if (be_physfn(adapter) || lancer_chip(adapter)) { - status = be_cmd_mac_addr_query(adapter, mac, - MAC_ADDRESS_TYPE_NETWORK, true /*permanent */, 0); - - if (status) - return status; - - if (!is_valid_ether_addr(mac)) - return -EADDRNOTAVAIL; - - memcpy(adapter->netdev->dev_addr, mac, ETH_ALEN); - memcpy(adapter->netdev->perm_addr, mac, ETH_ALEN); - } - - if (adapter->function_mode & 0x400) + if (adapter->function_mode & FLEX10_MODE) adapter->max_vlans = BE_NUM_VLANS_SUPPORTED/4; else adapter->max_vlans = BE_NUM_VLANS_SUPPORTED; @@ -3180,16 +3204,6 @@ static int be_get_config(struct be_adapter *adapter) if (status) return status; - if ((num_vfs && adapter->sriov_enabled) || - (adapter->function_mode & 0x400) || - lancer_chip(adapter) || !be_physfn(adapter)) { - adapter->num_tx_qs = 1; - netif_set_real_num_tx_queues(adapter->netdev, - adapter->num_tx_qs); - } else { - adapter->num_tx_qs = MAX_TX_QS; - } - return 0; } @@ -3319,18 +3333,13 @@ static int __devinit be_probe(struct pci_dev *pdev, } } - be_sriov_enable(adapter); - if (adapter->sriov_enabled) { - adapter->vf_cfg = kcalloc(num_vfs, - sizeof(struct be_vf_cfg), GFP_KERNEL); - - if (!adapter->vf_cfg) - goto free_netdev; - } + status = be_sriov_enable(adapter); + if (status) + goto free_netdev; status = be_ctrl_init(adapter); if (status) - goto free_vf_cfg; + goto disable_sriov; if (lancer_chip(adapter)) { status = lancer_test_and_set_rdy_state(adapter); @@ -3373,6 +3382,7 @@ static int __devinit be_probe(struct pci_dev *pdev, be_msix_enable(adapter); INIT_DELAYED_WORK(&adapter->work, be_worker); + adapter->rx_fc = adapter->tx_fc = true; status = be_setup(adapter); if (status) @@ -3383,33 +3393,11 @@ static int __devinit be_probe(struct pci_dev *pdev, if (status != 0) goto unsetup; - if (be_physfn(adapter) && adapter->sriov_enabled) { - u8 mac_speed; - u16 vf, lnk_speed; - - if (!lancer_chip(adapter)) { - status = be_vf_eth_addr_config(adapter); - if (status) - goto unreg_netdev; - } - - for (vf = 0; vf < num_vfs; vf++) { - status = be_cmd_link_status_query(adapter, &mac_speed, - &lnk_speed, vf + 1); - if (!status) - adapter->vf_cfg[vf].vf_tx_rate = lnk_speed * 10; - else - goto unreg_netdev; - } - } - dev_info(&pdev->dev, "%s port %d\n", nic_name(pdev), adapter->port_num); schedule_delayed_work(&adapter->work, msecs_to_jiffies(100)); return 0; -unreg_netdev: - unregister_netdev(netdev); unsetup: be_clear(adapter); msix_disable: @@ -3418,10 +3406,9 @@ stats_clean: be_stats_cleanup(adapter); ctrl_clean: be_ctrl_cleanup(adapter); -free_vf_cfg: - kfree(adapter->vf_cfg); -free_netdev: +disable_sriov: be_sriov_disable(adapter); +free_netdev: free_netdev(netdev); pci_set_drvdata(pdev, NULL); rel_reg: @@ -3448,7 +3435,6 @@ static int be_suspend(struct pci_dev *pdev, pm_message_t state) be_close(netdev); rtnl_unlock(); } - be_cmd_get_flow_control(adapter, &adapter->tx_fc, &adapter->rx_fc); be_clear(adapter); be_msix_disable(adapter); |