aboutsummaryrefslogtreecommitdiff
path: root/drivers/net/ethernet/emulex/benet/be_main.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/ethernet/emulex/benet/be_main.c')
-rw-r--r--drivers/net/ethernet/emulex/benet/be_main.c95
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;
}