diff options
Diffstat (limited to 'drivers/net/ethernet/emulex/benet/be_main.c')
-rw-r--r-- | drivers/net/ethernet/emulex/benet/be_main.c | 95 |
1 files changed, 84 insertions, 11 deletions
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index e3822788f53..528a886bc2c 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c @@ -235,7 +235,7 @@ static int be_mac_addr_set(struct net_device *netdev, void *p) struct sockaddr *addr = p; int status = 0; u8 current_mac[ETH_ALEN]; - u32 pmac_id = adapter->pmac_id; + u32 pmac_id = adapter->pmac_id[0]; if (!is_valid_ether_addr(addr->sa_data)) return -EADDRNOTAVAIL; @@ -248,7 +248,7 @@ static int be_mac_addr_set(struct net_device *netdev, void *p) if (memcmp(addr->sa_data, current_mac, ETH_ALEN)) { status = be_cmd_pmac_add(adapter, (u8 *)addr->sa_data, - adapter->if_handle, &adapter->pmac_id, 0); + adapter->if_handle, &adapter->pmac_id[0], 0); if (status) goto err; @@ -885,6 +885,29 @@ static void be_set_rx_mode(struct net_device *netdev) goto done; } + if (netdev_uc_count(netdev) != adapter->uc_macs) { + struct netdev_hw_addr *ha; + int i = 1; /* First slot is claimed by the Primary MAC */ + + for (; adapter->uc_macs > 0; adapter->uc_macs--, i++) { + be_cmd_pmac_del(adapter, adapter->if_handle, + adapter->pmac_id[i], 0); + } + + if (netdev_uc_count(netdev) > adapter->max_pmac_cnt) { + be_cmd_rx_filter(adapter, IFF_PROMISC, ON); + adapter->promiscuous = true; + goto done; + } + + netdev_for_each_uc_addr(ha, adapter->netdev) { + adapter->uc_macs++; /* First slot is for Primary MAC */ + be_cmd_pmac_add(adapter, (u8 *)ha->addr, + adapter->if_handle, + &adapter->pmac_id[adapter->uc_macs], 0); + } + } + be_cmd_rx_filter(adapter, IFF_MULTICAST, ON); done: return; @@ -955,14 +978,21 @@ static int be_set_vf_vlan(struct net_device *netdev, return -EINVAL; if (vlan) { - adapter->vf_cfg[vf].vlan_tag = vlan; - adapter->vlans_added++; + if (adapter->vf_cfg[vf].vlan_tag != vlan) { + /* If this is new value, program it. Else skip. */ + adapter->vf_cfg[vf].vlan_tag = vlan; + + status = be_cmd_set_hsw_config(adapter, vlan, + vf + 1, adapter->vf_cfg[vf].if_handle); + } } else { + /* Reset Transparent Vlan Tagging. */ adapter->vf_cfg[vf].vlan_tag = 0; - adapter->vlans_added--; + vlan = adapter->vf_cfg[vf].def_vid; + status = be_cmd_set_hsw_config(adapter, vlan, vf + 1, + adapter->vf_cfg[vf].if_handle); } - status = be_vid_config(adapter, true, vf); if (status) dev_info(&adapter->pdev->dev, @@ -2458,6 +2488,8 @@ static void be_vf_clear(struct be_adapter *adapter) static int be_clear(struct be_adapter *adapter) { + int i = 1; + if (adapter->flags & BE_FLAGS_WORKER_SCHEDULED) { cancel_delayed_work_sync(&adapter->work); adapter->flags &= ~BE_FLAGS_WORKER_SCHEDULED; @@ -2466,6 +2498,10 @@ static int be_clear(struct be_adapter *adapter) if (sriov_enabled(adapter)) be_vf_clear(adapter); + for (; adapter->uc_macs > 0; adapter->uc_macs--, i++) + be_cmd_pmac_del(adapter, adapter->if_handle, + adapter->pmac_id[i], 0); + be_cmd_if_destroy(adapter, adapter->if_handle, 0); be_mcc_queues_destroy(adapter); @@ -2477,6 +2513,7 @@ static int be_clear(struct be_adapter *adapter) be_cmd_fw_clean(adapter); be_msix_disable(adapter); + kfree(adapter->pmac_id); return 0; } @@ -2495,7 +2532,7 @@ static int be_vf_setup(struct be_adapter *adapter) { struct be_vf_cfg *vf_cfg; u32 cap_flags, en_flags, vf; - u16 lnk_speed; + u16 def_vlan, lnk_speed; int status; be_vf_setup_init(adapter); @@ -2519,6 +2556,12 @@ static int be_vf_setup(struct be_adapter *adapter) if (status) goto err; vf_cfg->tx_rate = lnk_speed * 10; + + status = be_cmd_get_hsw_config(adapter, &def_vlan, + vf + 1, vf_cfg->if_handle); + if (status) + goto err; + vf_cfg->def_vid = def_vlan; } return 0; err: @@ -2552,10 +2595,10 @@ static int be_add_mac_from_list(struct be_adapter *adapter, u8 *mac) false, adapter->if_handle, pmac_id); if (!status) - adapter->pmac_id = pmac_id; + adapter->pmac_id[0] = pmac_id; } else { status = be_cmd_pmac_add(adapter, mac, - adapter->if_handle, &adapter->pmac_id, 0); + adapter->if_handle, &adapter->pmac_id[0], 0); } do_none: return status; @@ -2610,7 +2653,7 @@ static int be_setup(struct be_adapter *adapter) } status = be_cmd_if_create(adapter, cap_flags, en_flags, netdev->dev_addr, &adapter->if_handle, - &adapter->pmac_id, 0); + &adapter->pmac_id[0], 0); if (status != 0) goto err; @@ -3059,6 +3102,8 @@ static void be_netdev_init(struct net_device *netdev) netdev->vlan_features |= NETIF_F_SG | NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM; + netdev->priv_flags |= IFF_UNICAST_FLT; + netdev->flags |= IFF_MULTICAST; netif_set_gso_max_size(netdev, 65535); @@ -3244,6 +3289,12 @@ static void __devexit be_remove(struct pci_dev *pdev) free_netdev(adapter->netdev); } +bool be_is_wol_supported(struct be_adapter *adapter) +{ + return ((adapter->wol_cap & BE_WOL_CAP) && + !be_is_wol_excluded(adapter)) ? true : false; +} + static int be_get_config(struct be_adapter *adapter) { int status; @@ -3254,14 +3305,36 @@ static int be_get_config(struct be_adapter *adapter) return status; if (adapter->function_mode & FLEX10_MODE) - adapter->max_vlans = BE_NUM_VLANS_SUPPORTED/4; + adapter->max_vlans = BE_NUM_VLANS_SUPPORTED/8; else adapter->max_vlans = BE_NUM_VLANS_SUPPORTED; + if (be_physfn(adapter)) + adapter->max_pmac_cnt = BE_UC_PMAC_COUNT; + else + adapter->max_pmac_cnt = BE_VF_UC_PMAC_COUNT; + + /* primary mac needs 1 pmac entry */ + adapter->pmac_id = kcalloc(adapter->max_pmac_cnt + 1, + sizeof(u32), GFP_KERNEL); + if (!adapter->pmac_id) + return -ENOMEM; + status = be_cmd_get_cntl_attributes(adapter); if (status) return status; + status = be_cmd_get_acpi_wol_cap(adapter); + if (status) { + /* in case of a failure to get wol capabillities + * check the exclusion list to determine WOL capability */ + if (!be_is_wol_excluded(adapter)) + adapter->wol_cap |= BE_WOL_CAP; + } + + if (be_is_wol_supported(adapter)) + adapter->wol = true; + return 0; } |