diff options
Diffstat (limited to 'drivers/net/ethernet/emulex/benet/be_main.c')
-rw-r--r-- | drivers/net/ethernet/emulex/benet/be_main.c | 131 |
1 files changed, 98 insertions, 33 deletions
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index 0a816859aca5..e6b790f0d9dc 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c | |||
@@ -1171,7 +1171,7 @@ static int be_vid_config(struct be_adapter *adapter) | |||
1171 | for_each_set_bit(i, adapter->vids, VLAN_N_VID) | 1171 | for_each_set_bit(i, adapter->vids, VLAN_N_VID) |
1172 | vids[num++] = cpu_to_le16(i); | 1172 | vids[num++] = cpu_to_le16(i); |
1173 | 1173 | ||
1174 | status = be_cmd_vlan_config(adapter, adapter->if_handle, vids, num); | 1174 | status = be_cmd_vlan_config(adapter, adapter->if_handle, vids, num, 0); |
1175 | if (status) { | 1175 | if (status) { |
1176 | dev_err(dev, "Setting HW VLAN filtering failed\n"); | 1176 | dev_err(dev, "Setting HW VLAN filtering failed\n"); |
1177 | /* Set to VLAN promisc mode as setting VLAN filter failed */ | 1177 | /* Set to VLAN promisc mode as setting VLAN filter failed */ |
@@ -1380,11 +1380,67 @@ static int be_get_vf_config(struct net_device *netdev, int vf, | |||
1380 | return 0; | 1380 | return 0; |
1381 | } | 1381 | } |
1382 | 1382 | ||
1383 | static int be_set_vf_tvt(struct be_adapter *adapter, int vf, u16 vlan) | ||
1384 | { | ||
1385 | struct be_vf_cfg *vf_cfg = &adapter->vf_cfg[vf]; | ||
1386 | u16 vids[BE_NUM_VLANS_SUPPORTED]; | ||
1387 | int vf_if_id = vf_cfg->if_handle; | ||
1388 | int status; | ||
1389 | |||
1390 | /* Enable Transparent VLAN Tagging */ | ||
1391 | status = be_cmd_set_hsw_config(adapter, vlan, vf + 1, vf_if_id, 0); | ||
1392 | if (status) | ||
1393 | return status; | ||
1394 | |||
1395 | /* Clear pre-programmed VLAN filters on VF if any, if TVT is enabled */ | ||
1396 | vids[0] = 0; | ||
1397 | status = be_cmd_vlan_config(adapter, vf_if_id, vids, 1, vf + 1); | ||
1398 | if (!status) | ||
1399 | dev_info(&adapter->pdev->dev, | ||
1400 | "Cleared guest VLANs on VF%d", vf); | ||
1401 | |||
1402 | /* After TVT is enabled, disallow VFs to program VLAN filters */ | ||
1403 | if (vf_cfg->privileges & BE_PRIV_FILTMGMT) { | ||
1404 | status = be_cmd_set_fn_privileges(adapter, vf_cfg->privileges & | ||
1405 | ~BE_PRIV_FILTMGMT, vf + 1); | ||
1406 | if (!status) | ||
1407 | vf_cfg->privileges &= ~BE_PRIV_FILTMGMT; | ||
1408 | } | ||
1409 | return 0; | ||
1410 | } | ||
1411 | |||
1412 | static int be_clear_vf_tvt(struct be_adapter *adapter, int vf) | ||
1413 | { | ||
1414 | struct be_vf_cfg *vf_cfg = &adapter->vf_cfg[vf]; | ||
1415 | struct device *dev = &adapter->pdev->dev; | ||
1416 | int status; | ||
1417 | |||
1418 | /* Reset Transparent VLAN Tagging. */ | ||
1419 | status = be_cmd_set_hsw_config(adapter, BE_RESET_VLAN_TAG_ID, vf + 1, | ||
1420 | vf_cfg->if_handle, 0); | ||
1421 | if (status) | ||
1422 | return status; | ||
1423 | |||
1424 | /* Allow VFs to program VLAN filtering */ | ||
1425 | if (!(vf_cfg->privileges & BE_PRIV_FILTMGMT)) { | ||
1426 | status = be_cmd_set_fn_privileges(adapter, vf_cfg->privileges | | ||
1427 | BE_PRIV_FILTMGMT, vf + 1); | ||
1428 | if (!status) { | ||
1429 | vf_cfg->privileges |= BE_PRIV_FILTMGMT; | ||
1430 | dev_info(dev, "VF%d: FILTMGMT priv enabled", vf); | ||
1431 | } | ||
1432 | } | ||
1433 | |||
1434 | dev_info(dev, | ||
1435 | "Disable/re-enable i/f in VM to clear Transparent VLAN tag"); | ||
1436 | return 0; | ||
1437 | } | ||
1438 | |||
1383 | static int be_set_vf_vlan(struct net_device *netdev, int vf, u16 vlan, u8 qos) | 1439 | static int be_set_vf_vlan(struct net_device *netdev, int vf, u16 vlan, u8 qos) |
1384 | { | 1440 | { |
1385 | struct be_adapter *adapter = netdev_priv(netdev); | 1441 | struct be_adapter *adapter = netdev_priv(netdev); |
1386 | struct be_vf_cfg *vf_cfg = &adapter->vf_cfg[vf]; | 1442 | struct be_vf_cfg *vf_cfg = &adapter->vf_cfg[vf]; |
1387 | int status = 0; | 1443 | int status; |
1388 | 1444 | ||
1389 | if (!sriov_enabled(adapter)) | 1445 | if (!sriov_enabled(adapter)) |
1390 | return -EPERM; | 1446 | return -EPERM; |
@@ -1394,24 +1450,19 @@ static int be_set_vf_vlan(struct net_device *netdev, int vf, u16 vlan, u8 qos) | |||
1394 | 1450 | ||
1395 | if (vlan || qos) { | 1451 | if (vlan || qos) { |
1396 | vlan |= qos << VLAN_PRIO_SHIFT; | 1452 | vlan |= qos << VLAN_PRIO_SHIFT; |
1397 | if (vf_cfg->vlan_tag != vlan) | 1453 | status = be_set_vf_tvt(adapter, vf, vlan); |
1398 | status = be_cmd_set_hsw_config(adapter, vlan, vf + 1, | ||
1399 | vf_cfg->if_handle, 0); | ||
1400 | } else { | 1454 | } else { |
1401 | /* Reset Transparent Vlan Tagging. */ | 1455 | status = be_clear_vf_tvt(adapter, vf); |
1402 | status = be_cmd_set_hsw_config(adapter, BE_RESET_VLAN_TAG_ID, | ||
1403 | vf + 1, vf_cfg->if_handle, 0); | ||
1404 | } | 1456 | } |
1405 | 1457 | ||
1406 | if (status) { | 1458 | if (status) { |
1407 | dev_err(&adapter->pdev->dev, | 1459 | dev_err(&adapter->pdev->dev, |
1408 | "VLAN %d config on VF %d failed : %#x\n", vlan, | 1460 | "VLAN %d config on VF %d failed : %#x\n", vlan, vf, |
1409 | vf, status); | 1461 | status); |
1410 | return be_cmd_status(status); | 1462 | return be_cmd_status(status); |
1411 | } | 1463 | } |
1412 | 1464 | ||
1413 | vf_cfg->vlan_tag = vlan; | 1465 | vf_cfg->vlan_tag = vlan; |
1414 | |||
1415 | return 0; | 1466 | return 0; |
1416 | } | 1467 | } |
1417 | 1468 | ||
@@ -2772,14 +2823,12 @@ void be_detect_error(struct be_adapter *adapter) | |||
2772 | } | 2823 | } |
2773 | } | 2824 | } |
2774 | } else { | 2825 | } else { |
2775 | pci_read_config_dword(adapter->pdev, | 2826 | ue_lo = ioread32(adapter->pcicfg + PCICFG_UE_STATUS_LOW); |
2776 | PCICFG_UE_STATUS_LOW, &ue_lo); | 2827 | ue_hi = ioread32(adapter->pcicfg + PCICFG_UE_STATUS_HIGH); |
2777 | pci_read_config_dword(adapter->pdev, | 2828 | ue_lo_mask = ioread32(adapter->pcicfg + |
2778 | PCICFG_UE_STATUS_HIGH, &ue_hi); | 2829 | PCICFG_UE_STATUS_LOW_MASK); |
2779 | pci_read_config_dword(adapter->pdev, | 2830 | ue_hi_mask = ioread32(adapter->pcicfg + |
2780 | PCICFG_UE_STATUS_LOW_MASK, &ue_lo_mask); | 2831 | PCICFG_UE_STATUS_HI_MASK); |
2781 | pci_read_config_dword(adapter->pdev, | ||
2782 | PCICFG_UE_STATUS_HI_MASK, &ue_hi_mask); | ||
2783 | 2832 | ||
2784 | ue_lo = (ue_lo & ~ue_lo_mask); | 2833 | ue_lo = (ue_lo & ~ue_lo_mask); |
2785 | ue_hi = (ue_hi & ~ue_hi_mask); | 2834 | ue_hi = (ue_hi & ~ue_hi_mask); |
@@ -3339,7 +3388,6 @@ static int be_if_create(struct be_adapter *adapter, u32 *if_handle, | |||
3339 | u32 cap_flags, u32 vf) | 3388 | u32 cap_flags, u32 vf) |
3340 | { | 3389 | { |
3341 | u32 en_flags; | 3390 | u32 en_flags; |
3342 | int status; | ||
3343 | 3391 | ||
3344 | en_flags = BE_IF_FLAGS_UNTAGGED | BE_IF_FLAGS_BROADCAST | | 3392 | en_flags = BE_IF_FLAGS_UNTAGGED | BE_IF_FLAGS_BROADCAST | |
3345 | BE_IF_FLAGS_MULTICAST | BE_IF_FLAGS_PASS_L3L4_ERRORS | | 3393 | BE_IF_FLAGS_MULTICAST | BE_IF_FLAGS_PASS_L3L4_ERRORS | |
@@ -3347,10 +3395,7 @@ static int be_if_create(struct be_adapter *adapter, u32 *if_handle, | |||
3347 | 3395 | ||
3348 | en_flags &= cap_flags; | 3396 | en_flags &= cap_flags; |
3349 | 3397 | ||
3350 | status = be_cmd_if_create(adapter, cap_flags, en_flags, | 3398 | return be_cmd_if_create(adapter, cap_flags, en_flags, if_handle, vf); |
3351 | if_handle, vf); | ||
3352 | |||
3353 | return status; | ||
3354 | } | 3399 | } |
3355 | 3400 | ||
3356 | static int be_vfs_if_create(struct be_adapter *adapter) | 3401 | static int be_vfs_if_create(struct be_adapter *adapter) |
@@ -3368,8 +3413,13 @@ static int be_vfs_if_create(struct be_adapter *adapter) | |||
3368 | if (!BE3_chip(adapter)) { | 3413 | if (!BE3_chip(adapter)) { |
3369 | status = be_cmd_get_profile_config(adapter, &res, | 3414 | status = be_cmd_get_profile_config(adapter, &res, |
3370 | vf + 1); | 3415 | vf + 1); |
3371 | if (!status) | 3416 | if (!status) { |
3372 | cap_flags = res.if_cap_flags; | 3417 | cap_flags = res.if_cap_flags; |
3418 | /* Prevent VFs from enabling VLAN promiscuous | ||
3419 | * mode | ||
3420 | */ | ||
3421 | cap_flags &= ~BE_IF_FLAGS_VLAN_PROMISCUOUS; | ||
3422 | } | ||
3373 | } | 3423 | } |
3374 | 3424 | ||
3375 | status = be_if_create(adapter, &vf_cfg->if_handle, | 3425 | status = be_if_create(adapter, &vf_cfg->if_handle, |
@@ -3403,7 +3453,6 @@ static int be_vf_setup(struct be_adapter *adapter) | |||
3403 | struct device *dev = &adapter->pdev->dev; | 3453 | struct device *dev = &adapter->pdev->dev; |
3404 | struct be_vf_cfg *vf_cfg; | 3454 | struct be_vf_cfg *vf_cfg; |
3405 | int status, old_vfs, vf; | 3455 | int status, old_vfs, vf; |
3406 | u32 privileges; | ||
3407 | 3456 | ||
3408 | old_vfs = pci_num_vf(adapter->pdev); | 3457 | old_vfs = pci_num_vf(adapter->pdev); |
3409 | 3458 | ||
@@ -3433,15 +3482,18 @@ static int be_vf_setup(struct be_adapter *adapter) | |||
3433 | 3482 | ||
3434 | for_all_vfs(adapter, vf_cfg, vf) { | 3483 | for_all_vfs(adapter, vf_cfg, vf) { |
3435 | /* Allow VFs to programs MAC/VLAN filters */ | 3484 | /* Allow VFs to programs MAC/VLAN filters */ |
3436 | status = be_cmd_get_fn_privileges(adapter, &privileges, vf + 1); | 3485 | status = be_cmd_get_fn_privileges(adapter, &vf_cfg->privileges, |
3437 | if (!status && !(privileges & BE_PRIV_FILTMGMT)) { | 3486 | vf + 1); |
3487 | if (!status && !(vf_cfg->privileges & BE_PRIV_FILTMGMT)) { | ||
3438 | status = be_cmd_set_fn_privileges(adapter, | 3488 | status = be_cmd_set_fn_privileges(adapter, |
3439 | privileges | | 3489 | vf_cfg->privileges | |
3440 | BE_PRIV_FILTMGMT, | 3490 | BE_PRIV_FILTMGMT, |
3441 | vf + 1); | 3491 | vf + 1); |
3442 | if (!status) | 3492 | if (!status) { |
3493 | vf_cfg->privileges |= BE_PRIV_FILTMGMT; | ||
3443 | dev_info(dev, "VF%d has FILTMGMT privilege\n", | 3494 | dev_info(dev, "VF%d has FILTMGMT privilege\n", |
3444 | vf); | 3495 | vf); |
3496 | } | ||
3445 | } | 3497 | } |
3446 | 3498 | ||
3447 | /* Allow full available bandwidth */ | 3499 | /* Allow full available bandwidth */ |
@@ -4820,24 +4872,37 @@ static int be_roce_map_pci_bars(struct be_adapter *adapter) | |||
4820 | 4872 | ||
4821 | static int be_map_pci_bars(struct be_adapter *adapter) | 4873 | static int be_map_pci_bars(struct be_adapter *adapter) |
4822 | { | 4874 | { |
4875 | struct pci_dev *pdev = adapter->pdev; | ||
4823 | u8 __iomem *addr; | 4876 | u8 __iomem *addr; |
4824 | 4877 | ||
4825 | if (BEx_chip(adapter) && be_physfn(adapter)) { | 4878 | if (BEx_chip(adapter) && be_physfn(adapter)) { |
4826 | adapter->csr = pci_iomap(adapter->pdev, 2, 0); | 4879 | adapter->csr = pci_iomap(pdev, 2, 0); |
4827 | if (!adapter->csr) | 4880 | if (!adapter->csr) |
4828 | return -ENOMEM; | 4881 | return -ENOMEM; |
4829 | } | 4882 | } |
4830 | 4883 | ||
4831 | addr = pci_iomap(adapter->pdev, db_bar(adapter), 0); | 4884 | addr = pci_iomap(pdev, db_bar(adapter), 0); |
4832 | if (!addr) | 4885 | if (!addr) |
4833 | goto pci_map_err; | 4886 | goto pci_map_err; |
4834 | adapter->db = addr; | 4887 | adapter->db = addr; |
4835 | 4888 | ||
4889 | if (skyhawk_chip(adapter) || BEx_chip(adapter)) { | ||
4890 | if (be_physfn(adapter)) { | ||
4891 | /* PCICFG is the 2nd BAR in BE2 */ | ||
4892 | addr = pci_iomap(pdev, BE2_chip(adapter) ? 1 : 0, 0); | ||
4893 | if (!addr) | ||
4894 | goto pci_map_err; | ||
4895 | adapter->pcicfg = addr; | ||
4896 | } else { | ||
4897 | adapter->pcicfg = adapter->db + SRIOV_VF_PCICFG_OFFSET; | ||
4898 | } | ||
4899 | } | ||
4900 | |||
4836 | be_roce_map_pci_bars(adapter); | 4901 | be_roce_map_pci_bars(adapter); |
4837 | return 0; | 4902 | return 0; |
4838 | 4903 | ||
4839 | pci_map_err: | 4904 | pci_map_err: |
4840 | dev_err(&adapter->pdev->dev, "Error in mapping PCI BARs\n"); | 4905 | dev_err(&pdev->dev, "Error in mapping PCI BARs\n"); |
4841 | be_unmap_pci_bars(adapter); | 4906 | be_unmap_pci_bars(adapter); |
4842 | return -ENOMEM; | 4907 | return -ENOMEM; |
4843 | } | 4908 | } |