.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /**************************************************************************** |
---|
2 | 3 | * Driver for Solarflare network controllers and boards |
---|
3 | 4 | * Copyright 2015 Solarflare Communications Inc. |
---|
4 | | - * |
---|
5 | | - * This program is free software; you can redistribute it and/or modify it |
---|
6 | | - * under the terms of the GNU General Public License version 2 as published |
---|
7 | | - * by the Free Software Foundation, incorporated herein by reference. |
---|
8 | 5 | */ |
---|
9 | 6 | #include <linux/etherdevice.h> |
---|
10 | 7 | #include <linux/pci.h> |
---|
.. | .. |
---|
235 | 232 | |
---|
236 | 233 | static int efx_ef10_vadaptor_alloc_set_features(struct efx_nic *efx) |
---|
237 | 234 | { |
---|
238 | | - struct efx_ef10_nic_data *nic_data = efx->nic_data; |
---|
239 | 235 | u32 port_flags; |
---|
240 | 236 | int rc; |
---|
241 | 237 | |
---|
242 | | - rc = efx_ef10_vadaptor_alloc(efx, nic_data->vport_id); |
---|
| 238 | + rc = efx_ef10_vadaptor_alloc(efx, efx->vport_id); |
---|
243 | 239 | if (rc) |
---|
244 | 240 | goto fail_vadaptor_alloc; |
---|
245 | 241 | |
---|
246 | | - rc = efx_ef10_vadaptor_query(efx, nic_data->vport_id, |
---|
| 242 | + rc = efx_ef10_vadaptor_query(efx, efx->vport_id, |
---|
247 | 243 | &port_flags, NULL, NULL); |
---|
248 | 244 | if (rc) |
---|
249 | 245 | goto fail_vadaptor_query; |
---|
.. | .. |
---|
284 | 280 | |
---|
285 | 281 | rc = efx_ef10_vport_alloc(efx, EVB_PORT_ID_ASSIGNED, |
---|
286 | 282 | MC_CMD_VPORT_ALLOC_IN_VPORT_TYPE_NORMAL, |
---|
287 | | - EFX_EF10_NO_VLAN, &nic_data->vport_id); |
---|
| 283 | + EFX_EF10_NO_VLAN, &efx->vport_id); |
---|
288 | 284 | if (rc) |
---|
289 | 285 | goto fail2; |
---|
290 | 286 | |
---|
291 | | - rc = efx_ef10_vport_add_mac(efx, nic_data->vport_id, net_dev->dev_addr); |
---|
| 287 | + rc = efx_ef10_vport_add_mac(efx, efx->vport_id, net_dev->dev_addr); |
---|
292 | 288 | if (rc) |
---|
293 | 289 | goto fail3; |
---|
294 | 290 | ether_addr_copy(nic_data->vport_mac, net_dev->dev_addr); |
---|
.. | .. |
---|
299 | 295 | |
---|
300 | 296 | return 0; |
---|
301 | 297 | fail4: |
---|
302 | | - efx_ef10_vport_del_mac(efx, nic_data->vport_id, nic_data->vport_mac); |
---|
| 298 | + efx_ef10_vport_del_mac(efx, efx->vport_id, nic_data->vport_mac); |
---|
303 | 299 | eth_zero_addr(nic_data->vport_mac); |
---|
304 | 300 | fail3: |
---|
305 | | - efx_ef10_vport_free(efx, nic_data->vport_id); |
---|
306 | | - nic_data->vport_id = EVB_PORT_ID_ASSIGNED; |
---|
| 301 | + efx_ef10_vport_free(efx, efx->vport_id); |
---|
| 302 | + efx->vport_id = EVB_PORT_ID_ASSIGNED; |
---|
307 | 303 | fail2: |
---|
308 | 304 | efx_ef10_vswitch_free(efx, EVB_PORT_ID_ASSIGNED); |
---|
309 | 305 | fail1: |
---|
.. | .. |
---|
358 | 354 | |
---|
359 | 355 | efx_ef10_sriov_free_vf_vswitching(efx); |
---|
360 | 356 | |
---|
361 | | - efx_ef10_vadaptor_free(efx, nic_data->vport_id); |
---|
| 357 | + efx_ef10_vadaptor_free(efx, efx->vport_id); |
---|
362 | 358 | |
---|
363 | | - if (nic_data->vport_id == EVB_PORT_ID_ASSIGNED) |
---|
| 359 | + if (efx->vport_id == EVB_PORT_ID_ASSIGNED) |
---|
364 | 360 | return; /* No vswitch was ever created */ |
---|
365 | 361 | |
---|
366 | 362 | if (!is_zero_ether_addr(nic_data->vport_mac)) { |
---|
367 | | - efx_ef10_vport_del_mac(efx, nic_data->vport_id, |
---|
| 363 | + efx_ef10_vport_del_mac(efx, efx->vport_id, |
---|
368 | 364 | efx->net_dev->dev_addr); |
---|
369 | 365 | eth_zero_addr(nic_data->vport_mac); |
---|
370 | 366 | } |
---|
371 | | - efx_ef10_vport_free(efx, nic_data->vport_id); |
---|
372 | | - nic_data->vport_id = EVB_PORT_ID_ASSIGNED; |
---|
| 367 | + efx_ef10_vport_free(efx, efx->vport_id); |
---|
| 368 | + efx->vport_id = EVB_PORT_ID_ASSIGNED; |
---|
373 | 369 | |
---|
374 | 370 | /* Only free the vswitch if no VFs are assigned */ |
---|
375 | 371 | if (!pci_vfs_assigned(efx->pci_dev)) |
---|
376 | | - efx_ef10_vswitch_free(efx, nic_data->vport_id); |
---|
| 372 | + efx_ef10_vswitch_free(efx, efx->vport_id); |
---|
377 | 373 | } |
---|
378 | 374 | |
---|
379 | 375 | void efx_ef10_vswitching_remove_vf(struct efx_nic *efx) |
---|
.. | .. |
---|
415 | 411 | static int efx_ef10_pci_sriov_disable(struct efx_nic *efx, bool force) |
---|
416 | 412 | { |
---|
417 | 413 | struct pci_dev *dev = efx->pci_dev; |
---|
| 414 | + struct efx_ef10_nic_data *nic_data = efx->nic_data; |
---|
418 | 415 | unsigned int vfs_assigned = pci_vfs_assigned(dev); |
---|
419 | | - int rc = 0; |
---|
| 416 | + int i, rc = 0; |
---|
420 | 417 | |
---|
421 | 418 | if (vfs_assigned && !force) { |
---|
422 | 419 | netif_info(efx, drv, efx->net_dev, "VFs are assigned to guests; " |
---|
.. | .. |
---|
424 | 421 | return -EBUSY; |
---|
425 | 422 | } |
---|
426 | 423 | |
---|
427 | | - if (!vfs_assigned) |
---|
| 424 | + if (!vfs_assigned) { |
---|
| 425 | + for (i = 0; i < efx->vf_count; i++) |
---|
| 426 | + nic_data->vf[i].pci_dev = NULL; |
---|
428 | 427 | pci_disable_sriov(dev); |
---|
429 | | - else |
---|
| 428 | + } else { |
---|
430 | 429 | rc = -EBUSY; |
---|
| 430 | + } |
---|
431 | 431 | |
---|
432 | 432 | efx_ef10_sriov_free_vf_vswitching(efx); |
---|
433 | 433 | efx->vf_count = 0; |
---|
.. | .. |
---|
524 | 524 | |
---|
525 | 525 | if (!is_zero_ether_addr(mac)) { |
---|
526 | 526 | rc = efx_ef10_vport_add_mac(efx, vf->vport_id, mac); |
---|
527 | | - if (rc) { |
---|
528 | | - eth_zero_addr(vf->mac); |
---|
| 527 | + if (rc) |
---|
529 | 528 | goto fail; |
---|
530 | | - } |
---|
| 529 | + |
---|
531 | 530 | if (vf->efx) |
---|
532 | 531 | ether_addr_copy(vf->efx->net_dev->dev_addr, mac); |
---|
533 | 532 | } |
---|
.. | .. |
---|
688 | 687 | return rc ? rc : rc2; |
---|
689 | 688 | } |
---|
690 | 689 | |
---|
691 | | -int efx_ef10_sriov_set_vf_spoofchk(struct efx_nic *efx, int vf_i, |
---|
692 | | - bool spoofchk) |
---|
| 690 | +static int efx_ef10_sriov_set_privilege_mask(struct efx_nic *efx, int vf_i, |
---|
| 691 | + u32 mask, u32 value) |
---|
693 | 692 | { |
---|
694 | | - return spoofchk ? -EOPNOTSUPP : 0; |
---|
| 693 | + MCDI_DECLARE_BUF(pm_outbuf, MC_CMD_PRIVILEGE_MASK_OUT_LEN); |
---|
| 694 | + MCDI_DECLARE_BUF(pm_inbuf, MC_CMD_PRIVILEGE_MASK_IN_LEN); |
---|
| 695 | + struct efx_ef10_nic_data *nic_data = efx->nic_data; |
---|
| 696 | + u32 old_mask, new_mask; |
---|
| 697 | + size_t outlen; |
---|
| 698 | + int rc; |
---|
| 699 | + |
---|
| 700 | + EFX_WARN_ON_PARANOID((value & ~mask) != 0); |
---|
| 701 | + |
---|
| 702 | + /* Get privilege mask */ |
---|
| 703 | + MCDI_POPULATE_DWORD_2(pm_inbuf, PRIVILEGE_MASK_IN_FUNCTION, |
---|
| 704 | + PRIVILEGE_MASK_IN_FUNCTION_PF, nic_data->pf_index, |
---|
| 705 | + PRIVILEGE_MASK_IN_FUNCTION_VF, vf_i); |
---|
| 706 | + |
---|
| 707 | + rc = efx_mcdi_rpc(efx, MC_CMD_PRIVILEGE_MASK, |
---|
| 708 | + pm_inbuf, sizeof(pm_inbuf), |
---|
| 709 | + pm_outbuf, sizeof(pm_outbuf), &outlen); |
---|
| 710 | + |
---|
| 711 | + if (rc != 0) |
---|
| 712 | + return rc; |
---|
| 713 | + if (outlen != MC_CMD_PRIVILEGE_MASK_OUT_LEN) |
---|
| 714 | + return -EIO; |
---|
| 715 | + |
---|
| 716 | + old_mask = MCDI_DWORD(pm_outbuf, PRIVILEGE_MASK_OUT_OLD_MASK); |
---|
| 717 | + |
---|
| 718 | + new_mask = old_mask & ~mask; |
---|
| 719 | + new_mask |= value; |
---|
| 720 | + |
---|
| 721 | + if (new_mask == old_mask) |
---|
| 722 | + return 0; |
---|
| 723 | + |
---|
| 724 | + new_mask |= MC_CMD_PRIVILEGE_MASK_IN_DO_CHANGE; |
---|
| 725 | + |
---|
| 726 | + /* Set privilege mask */ |
---|
| 727 | + MCDI_SET_DWORD(pm_inbuf, PRIVILEGE_MASK_IN_NEW_MASK, new_mask); |
---|
| 728 | + |
---|
| 729 | + rc = efx_mcdi_rpc(efx, MC_CMD_PRIVILEGE_MASK, |
---|
| 730 | + pm_inbuf, sizeof(pm_inbuf), |
---|
| 731 | + pm_outbuf, sizeof(pm_outbuf), &outlen); |
---|
| 732 | + |
---|
| 733 | + if (rc != 0) |
---|
| 734 | + return rc; |
---|
| 735 | + if (outlen != MC_CMD_PRIVILEGE_MASK_OUT_LEN) |
---|
| 736 | + return -EIO; |
---|
| 737 | + |
---|
| 738 | + return 0; |
---|
| 739 | +} |
---|
| 740 | + |
---|
| 741 | +int efx_ef10_sriov_set_vf_spoofchk(struct efx_nic *efx, int vf_i, bool spoofchk) |
---|
| 742 | +{ |
---|
| 743 | + struct efx_ef10_nic_data *nic_data = efx->nic_data; |
---|
| 744 | + |
---|
| 745 | + /* Can't enable spoofchk if firmware doesn't support it. */ |
---|
| 746 | + if (!(nic_data->datapath_caps & |
---|
| 747 | + BIT(MC_CMD_GET_CAPABILITIES_OUT_TX_MAC_SECURITY_FILTERING_LBN)) && |
---|
| 748 | + spoofchk) |
---|
| 749 | + return -EOPNOTSUPP; |
---|
| 750 | + |
---|
| 751 | + return efx_ef10_sriov_set_privilege_mask(efx, vf_i, |
---|
| 752 | + MC_CMD_PRIVILEGE_MASK_IN_GRP_MAC_SPOOFING_TX, |
---|
| 753 | + spoofchk ? 0 : MC_CMD_PRIVILEGE_MASK_IN_GRP_MAC_SPOOFING_TX); |
---|
695 | 754 | } |
---|
696 | 755 | |
---|
697 | 756 | int efx_ef10_sriov_set_vf_link_state(struct efx_nic *efx, int vf_i, |
---|