diff options
Diffstat (limited to 'drivers/net/ethernet/emulex/benet/be_main.c')
-rw-r--r-- | drivers/net/ethernet/emulex/benet/be_main.c | 98 |
1 files changed, 76 insertions, 22 deletions
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index 0a816859aca5..eb2bed92bf60 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 | ||
@@ -3339,7 +3390,6 @@ static int be_if_create(struct be_adapter *adapter, u32 *if_handle, | |||
3339 | u32 cap_flags, u32 vf) | 3390 | u32 cap_flags, u32 vf) |
3340 | { | 3391 | { |
3341 | u32 en_flags; | 3392 | u32 en_flags; |
3342 | int status; | ||
3343 | 3393 | ||
3344 | en_flags = BE_IF_FLAGS_UNTAGGED | BE_IF_FLAGS_BROADCAST | | 3394 | en_flags = BE_IF_FLAGS_UNTAGGED | BE_IF_FLAGS_BROADCAST | |
3345 | BE_IF_FLAGS_MULTICAST | BE_IF_FLAGS_PASS_L3L4_ERRORS | | 3395 | BE_IF_FLAGS_MULTICAST | BE_IF_FLAGS_PASS_L3L4_ERRORS | |
@@ -3347,10 +3397,7 @@ static int be_if_create(struct be_adapter *adapter, u32 *if_handle, | |||
3347 | 3397 | ||
3348 | en_flags &= cap_flags; | 3398 | en_flags &= cap_flags; |
3349 | 3399 | ||
3350 | status = be_cmd_if_create(adapter, cap_flags, en_flags, | 3400 | return be_cmd_if_create(adapter, cap_flags, en_flags, if_handle, vf); |
3351 | if_handle, vf); | ||
3352 | |||
3353 | return status; | ||
3354 | } | 3401 | } |
3355 | 3402 | ||
3356 | static int be_vfs_if_create(struct be_adapter *adapter) | 3403 | static int be_vfs_if_create(struct be_adapter *adapter) |
@@ -3368,8 +3415,13 @@ static int be_vfs_if_create(struct be_adapter *adapter) | |||
3368 | if (!BE3_chip(adapter)) { | 3415 | if (!BE3_chip(adapter)) { |
3369 | status = be_cmd_get_profile_config(adapter, &res, | 3416 | status = be_cmd_get_profile_config(adapter, &res, |
3370 | vf + 1); | 3417 | vf + 1); |
3371 | if (!status) | 3418 | if (!status) { |
3372 | cap_flags = res.if_cap_flags; | 3419 | cap_flags = res.if_cap_flags; |
3420 | /* Prevent VFs from enabling VLAN promiscuous | ||
3421 | * mode | ||
3422 | */ | ||
3423 | cap_flags &= ~BE_IF_FLAGS_VLAN_PROMISCUOUS; | ||
3424 | } | ||
3373 | } | 3425 | } |
3374 | 3426 | ||
3375 | status = be_if_create(adapter, &vf_cfg->if_handle, | 3427 | status = be_if_create(adapter, &vf_cfg->if_handle, |
@@ -3403,7 +3455,6 @@ static int be_vf_setup(struct be_adapter *adapter) | |||
3403 | struct device *dev = &adapter->pdev->dev; | 3455 | struct device *dev = &adapter->pdev->dev; |
3404 | struct be_vf_cfg *vf_cfg; | 3456 | struct be_vf_cfg *vf_cfg; |
3405 | int status, old_vfs, vf; | 3457 | int status, old_vfs, vf; |
3406 | u32 privileges; | ||
3407 | 3458 | ||
3408 | old_vfs = pci_num_vf(adapter->pdev); | 3459 | old_vfs = pci_num_vf(adapter->pdev); |
3409 | 3460 | ||
@@ -3433,15 +3484,18 @@ static int be_vf_setup(struct be_adapter *adapter) | |||
3433 | 3484 | ||
3434 | for_all_vfs(adapter, vf_cfg, vf) { | 3485 | for_all_vfs(adapter, vf_cfg, vf) { |
3435 | /* Allow VFs to programs MAC/VLAN filters */ | 3486 | /* Allow VFs to programs MAC/VLAN filters */ |
3436 | status = be_cmd_get_fn_privileges(adapter, &privileges, vf + 1); | 3487 | status = be_cmd_get_fn_privileges(adapter, &vf_cfg->privileges, |
3437 | if (!status && !(privileges & BE_PRIV_FILTMGMT)) { | 3488 | vf + 1); |
3489 | if (!status && !(vf_cfg->privileges & BE_PRIV_FILTMGMT)) { | ||
3438 | status = be_cmd_set_fn_privileges(adapter, | 3490 | status = be_cmd_set_fn_privileges(adapter, |
3439 | privileges | | 3491 | vf_cfg->privileges | |
3440 | BE_PRIV_FILTMGMT, | 3492 | BE_PRIV_FILTMGMT, |
3441 | vf + 1); | 3493 | vf + 1); |
3442 | if (!status) | 3494 | if (!status) { |
3495 | vf_cfg->privileges |= BE_PRIV_FILTMGMT; | ||
3443 | dev_info(dev, "VF%d has FILTMGMT privilege\n", | 3496 | dev_info(dev, "VF%d has FILTMGMT privilege\n", |
3444 | vf); | 3497 | vf); |
3498 | } | ||
3445 | } | 3499 | } |
3446 | 3500 | ||
3447 | /* Allow full available bandwidth */ | 3501 | /* Allow full available bandwidth */ |