diff options
author | Sathya Perla <sathya.perla@emulex.com> | 2013-07-23 05:54:59 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-07-24 18:41:52 -0400 |
commit | 5a712c13d3641a3bed243753f115434a7125e440 (patch) | |
tree | 361cad56f54dea9350d201298f96fdfb801d9a67 /drivers/net/ethernet/emulex | |
parent | e18dbf7efcb7a727e5db773597ddfd6981a530e6 (diff) |
be2net: fix MAC address modification for VF
Currently, the VFs by default don't have the privilege to modify MAC address.
This will change in a subsequent fix wherein VFs will have the ability to
modify MAC/VLAN filters.
Fix be_mac_addr_set() logic to support MAC address modification on a
privileged VF too.
Signed-off-by: Sathya Perla <sathya.perla@emulex.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/emulex')
-rw-r--r-- | drivers/net/ethernet/emulex/benet/be_cmds.c | 43 | ||||
-rw-r--r-- | drivers/net/ethernet/emulex/benet/be_cmds.h | 2 | ||||
-rw-r--r-- | drivers/net/ethernet/emulex/benet/be_main.c | 66 |
3 files changed, 73 insertions, 38 deletions
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c index 6e6e0a117ee2..632c0d323867 100644 --- a/drivers/net/ethernet/emulex/benet/be_cmds.c +++ b/drivers/net/ethernet/emulex/benet/be_cmds.c | |||
@@ -2606,9 +2606,12 @@ err: | |||
2606 | return status; | 2606 | return status; |
2607 | } | 2607 | } |
2608 | 2608 | ||
2609 | /* Uses synchronous MCCQ */ | 2609 | /* pmac_id_valid: true => pmac_id is supplied and MAC address is requested. |
2610 | * pmac_id_valid: false => pmac_id or MAC address is requested. | ||
2611 | * If pmac_id is returned, pmac_id_valid is returned as true | ||
2612 | */ | ||
2610 | int be_cmd_get_mac_from_list(struct be_adapter *adapter, u8 *mac, | 2613 | int be_cmd_get_mac_from_list(struct be_adapter *adapter, u8 *mac, |
2611 | bool *pmac_id_active, u32 *pmac_id, u8 domain) | 2614 | bool *pmac_id_valid, u32 *pmac_id, u8 domain) |
2612 | { | 2615 | { |
2613 | struct be_mcc_wrb *wrb; | 2616 | struct be_mcc_wrb *wrb; |
2614 | struct be_cmd_req_get_mac_list *req; | 2617 | struct be_cmd_req_get_mac_list *req; |
@@ -2644,12 +2647,25 @@ int be_cmd_get_mac_from_list(struct be_adapter *adapter, u8 *mac, | |||
2644 | get_mac_list_cmd.size, wrb, &get_mac_list_cmd); | 2647 | get_mac_list_cmd.size, wrb, &get_mac_list_cmd); |
2645 | req->hdr.domain = domain; | 2648 | req->hdr.domain = domain; |
2646 | req->mac_type = MAC_ADDRESS_TYPE_NETWORK; | 2649 | req->mac_type = MAC_ADDRESS_TYPE_NETWORK; |
2647 | req->perm_override = 1; | 2650 | if (*pmac_id_valid) { |
2651 | req->mac_id = cpu_to_le32(*pmac_id); | ||
2652 | req->iface_id = cpu_to_le16(adapter->if_handle); | ||
2653 | req->perm_override = 0; | ||
2654 | } else { | ||
2655 | req->perm_override = 1; | ||
2656 | } | ||
2648 | 2657 | ||
2649 | status = be_mcc_notify_wait(adapter); | 2658 | status = be_mcc_notify_wait(adapter); |
2650 | if (!status) { | 2659 | if (!status) { |
2651 | struct be_cmd_resp_get_mac_list *resp = | 2660 | struct be_cmd_resp_get_mac_list *resp = |
2652 | get_mac_list_cmd.va; | 2661 | get_mac_list_cmd.va; |
2662 | |||
2663 | if (*pmac_id_valid) { | ||
2664 | memcpy(mac, resp->macid_macaddr.mac_addr_id.macaddr, | ||
2665 | ETH_ALEN); | ||
2666 | goto out; | ||
2667 | } | ||
2668 | |||
2653 | mac_count = resp->true_mac_count + resp->pseudo_mac_count; | 2669 | mac_count = resp->true_mac_count + resp->pseudo_mac_count; |
2654 | /* Mac list returned could contain one or more active mac_ids | 2670 | /* Mac list returned could contain one or more active mac_ids |
2655 | * or one or more true or pseudo permanant mac addresses. | 2671 | * or one or more true or pseudo permanant mac addresses. |
@@ -2667,14 +2683,14 @@ int be_cmd_get_mac_from_list(struct be_adapter *adapter, u8 *mac, | |||
2667 | * is 6 bytes | 2683 | * is 6 bytes |
2668 | */ | 2684 | */ |
2669 | if (mac_addr_size == sizeof(u32)) { | 2685 | if (mac_addr_size == sizeof(u32)) { |
2670 | *pmac_id_active = true; | 2686 | *pmac_id_valid = true; |
2671 | mac_id = mac_entry->mac_addr_id.s_mac_id.mac_id; | 2687 | mac_id = mac_entry->mac_addr_id.s_mac_id.mac_id; |
2672 | *pmac_id = le32_to_cpu(mac_id); | 2688 | *pmac_id = le32_to_cpu(mac_id); |
2673 | goto out; | 2689 | goto out; |
2674 | } | 2690 | } |
2675 | } | 2691 | } |
2676 | /* If no active mac_id found, return first mac addr */ | 2692 | /* If no active mac_id found, return first mac addr */ |
2677 | *pmac_id_active = false; | 2693 | *pmac_id_valid = false; |
2678 | memcpy(mac, resp->macaddr_list[0].mac_addr_id.macaddr, | 2694 | memcpy(mac, resp->macaddr_list[0].mac_addr_id.macaddr, |
2679 | ETH_ALEN); | 2695 | ETH_ALEN); |
2680 | } | 2696 | } |
@@ -2686,6 +2702,23 @@ out: | |||
2686 | return status; | 2702 | return status; |
2687 | } | 2703 | } |
2688 | 2704 | ||
2705 | int be_cmd_get_active_mac(struct be_adapter *adapter, u32 curr_pmac_id, u8 *mac) | ||
2706 | { | ||
2707 | int status; | ||
2708 | bool active = true; | ||
2709 | |||
2710 | /* When SH FW is ready, SH should use Lancer path too */ | ||
2711 | if (lancer_chip(adapter)) { | ||
2712 | /* Fetch the MAC address using pmac_id */ | ||
2713 | status = be_cmd_get_mac_from_list(adapter, mac, &active, | ||
2714 | &curr_pmac_id, 0); | ||
2715 | return status; | ||
2716 | } else { | ||
2717 | return be_cmd_mac_addr_query(adapter, mac, false, | ||
2718 | adapter->if_handle, curr_pmac_id); | ||
2719 | } | ||
2720 | } | ||
2721 | |||
2689 | /* Uses synchronous MCCQ */ | 2722 | /* Uses synchronous MCCQ */ |
2690 | int be_cmd_set_mac_list(struct be_adapter *adapter, u8 *mac_array, | 2723 | int be_cmd_set_mac_list(struct be_adapter *adapter, u8 *mac_array, |
2691 | u8 mac_count, u32 domain) | 2724 | u8 mac_count, u32 domain) |
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.h b/drivers/net/ethernet/emulex/benet/be_cmds.h index 5228d88c5a02..7ecca3b591a6 100644 --- a/drivers/net/ethernet/emulex/benet/be_cmds.h +++ b/drivers/net/ethernet/emulex/benet/be_cmds.h | |||
@@ -1924,6 +1924,8 @@ extern int be_cmd_get_fn_privileges(struct be_adapter *adapter, | |||
1924 | extern int be_cmd_get_mac_from_list(struct be_adapter *adapter, u8 *mac, | 1924 | extern int be_cmd_get_mac_from_list(struct be_adapter *adapter, u8 *mac, |
1925 | bool *pmac_id_active, u32 *pmac_id, | 1925 | bool *pmac_id_active, u32 *pmac_id, |
1926 | u8 domain); | 1926 | u8 domain); |
1927 | extern int be_cmd_get_active_mac(struct be_adapter *adapter, u32 pmac_id, | ||
1928 | u8 *mac); | ||
1927 | extern int be_cmd_set_mac_list(struct be_adapter *adapter, u8 *mac_array, | 1929 | extern int be_cmd_set_mac_list(struct be_adapter *adapter, u8 *mac_array, |
1928 | u8 mac_count, u32 domain); | 1930 | u8 mac_count, u32 domain); |
1929 | extern int be_cmd_set_hsw_config(struct be_adapter *adapter, u16 pvid, | 1931 | extern int be_cmd_set_hsw_config(struct be_adapter *adapter, u16 pvid, |
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index 181edb522450..29e7870e0b35 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c | |||
@@ -247,54 +247,54 @@ void be_cq_notify(struct be_adapter *adapter, u16 qid, bool arm, u16 num_popped) | |||
247 | static int be_mac_addr_set(struct net_device *netdev, void *p) | 247 | static int be_mac_addr_set(struct net_device *netdev, void *p) |
248 | { | 248 | { |
249 | struct be_adapter *adapter = netdev_priv(netdev); | 249 | struct be_adapter *adapter = netdev_priv(netdev); |
250 | struct device *dev = &adapter->pdev->dev; | ||
250 | struct sockaddr *addr = p; | 251 | struct sockaddr *addr = p; |
251 | int status = 0; | 252 | int status; |
252 | u8 current_mac[ETH_ALEN]; | 253 | u8 mac[ETH_ALEN]; |
253 | u32 pmac_id = adapter->pmac_id[0]; | 254 | u32 old_pmac_id = adapter->pmac_id[0], curr_pmac_id = 0; |
254 | bool active_mac = true; | ||
255 | 255 | ||
256 | if (!is_valid_ether_addr(addr->sa_data)) | 256 | if (!is_valid_ether_addr(addr->sa_data)) |
257 | return -EADDRNOTAVAIL; | 257 | return -EADDRNOTAVAIL; |
258 | 258 | ||
259 | /* For BE VF, MAC address is already activated by PF. | 259 | /* The PMAC_ADD cmd may fail if the VF doesn't have FILTMGMT |
260 | * Hence only operation left is updating netdev->devaddr. | 260 | * privilege or if PF did not provision the new MAC address. |
261 | * Update it if user is passing the same MAC which was used | 261 | * On BE3, this cmd will always fail if the VF doesn't have the |
262 | * during configuring VF MAC from PF(Hypervisor). | 262 | * FILTMGMT privilege. This failure is OK, only if the PF programmed |
263 | * the MAC for the VF. | ||
263 | */ | 264 | */ |
264 | if (!lancer_chip(adapter) && !be_physfn(adapter)) { | 265 | status = be_cmd_pmac_add(adapter, (u8 *)addr->sa_data, |
265 | status = be_cmd_mac_addr_query(adapter, current_mac, | 266 | adapter->if_handle, &adapter->pmac_id[0], 0); |
266 | false, adapter->if_handle, 0); | 267 | if (!status) { |
267 | if (!status && !memcmp(current_mac, addr->sa_data, ETH_ALEN)) | 268 | curr_pmac_id = adapter->pmac_id[0]; |
268 | goto done; | ||
269 | else | ||
270 | goto err; | ||
271 | } | ||
272 | 269 | ||
273 | if (!memcmp(addr->sa_data, netdev->dev_addr, ETH_ALEN)) | 270 | /* Delete the old programmed MAC. This call may fail if the |
274 | goto done; | 271 | * old MAC was already deleted by the PF driver. |
272 | */ | ||
273 | if (adapter->pmac_id[0] != old_pmac_id) | ||
274 | be_cmd_pmac_del(adapter, adapter->if_handle, | ||
275 | old_pmac_id, 0); | ||
276 | } | ||
275 | 277 | ||
276 | /* For Lancer check if any MAC is active. | 278 | /* Decide if the new MAC is successfully activated only after |
277 | * If active, get its mac id. | 279 | * querying the FW |
278 | */ | 280 | */ |
279 | if (lancer_chip(adapter) && !be_physfn(adapter)) | 281 | status = be_cmd_get_active_mac(adapter, curr_pmac_id, mac); |
280 | be_cmd_get_mac_from_list(adapter, current_mac, &active_mac, | ||
281 | &pmac_id, 0); | ||
282 | |||
283 | status = be_cmd_pmac_add(adapter, (u8 *)addr->sa_data, | ||
284 | adapter->if_handle, | ||
285 | &adapter->pmac_id[0], 0); | ||
286 | |||
287 | if (status) | 282 | if (status) |
288 | goto err; | 283 | goto err; |
289 | 284 | ||
290 | if (active_mac) | 285 | /* The MAC change did not happen, either due to lack of privilege |
291 | be_cmd_pmac_del(adapter, adapter->if_handle, | 286 | * or PF didn't pre-provision. |
292 | pmac_id, 0); | 287 | */ |
293 | done: | 288 | if (memcmp(addr->sa_data, mac, ETH_ALEN)) { |
289 | status = -EPERM; | ||
290 | goto err; | ||
291 | } | ||
292 | |||
294 | memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); | 293 | memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); |
294 | dev_info(dev, "MAC address changed to %pM\n", mac); | ||
295 | return 0; | 295 | return 0; |
296 | err: | 296 | err: |
297 | dev_err(&adapter->pdev->dev, "MAC %pM set Failed\n", addr->sa_data); | 297 | dev_warn(dev, "MAC address change to %pM failed\n", addr->sa_data); |
298 | return status; | 298 | return status; |
299 | } | 299 | } |
300 | 300 | ||