Skip to content

Commit fc50db9

Browse files
Eli Cohendavem330
authored andcommitted
net/mlx5_core: Add base sriov support
This patch adds SRIOV base support for mlx5 supported devices. The same driver is used for both PFs and VFs; VFs are identified by the driver through the flag MLX5_PCI_DEV_IS_VF added to the pci table entries. Virtual functions are created as usual through writing a value to the sriov_numvs sysfs file of the PF device. Upon instantiating VFs, they will all be probed by the driver on the hypervisor. One can gracefully unbind them through /sys/bus/pci/drivers/mlx5_core/unbind. mlx5_wait_for_vf_pages() was added to ensure that when a VF dies without executing proper teardown, the hypervisor driver waits till all of the pages that were allocated at the hypervisor to maintain its operation are returned. In order for the VF to be operational, the PF needs to call enable_hca for it. This can be done before the VFs are created through a call to pci_enable_sriov. If the there are VFs assigned to a VMs when the driver of the PF is unloaded, all the VF will experience system error and PF driver unloads cleanly; in this case pci_disable_sriov is not called and the devices will show when running lspci. Once the PF driver is reloaded, it will sync its data structures which maintain state on its VFs. Signed-off-by: Eli Cohen <eli@mellanox.com> Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 0b10710 commit fc50db9

File tree

7 files changed

+318
-9
lines changed

7 files changed

+318
-9
lines changed

drivers/net/ethernet/mellanox/mlx5/core/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ obj-$(CONFIG_MLX5_CORE) += mlx5_core.o
22

33
mlx5_core-y := main.o cmd.o debugfs.o fw.o eq.o uar.o pagealloc.o \
44
health.o mcg.o cq.o srq.o alloc.o qp.o port.o mr.o pd.o \
5-
mad.o transobj.o vport.o
5+
mad.o transobj.o vport.o sriov.o
66
mlx5_core-$(CONFIG_MLX5_CORE_EN) += wq.o flow_table.o \
77
en_main.o en_flow_table.o en_ethtool.o en_tx.o en_rx.o \
88
en_txrx.o

drivers/net/ethernet/mellanox/mlx5/core/main.c

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -454,6 +454,9 @@ static int set_hca_ctrl(struct mlx5_core_dev *dev)
454454
struct mlx5_reg_host_endianess he_out;
455455
int err;
456456

457+
if (!mlx5_core_is_pf(dev))
458+
return 0;
459+
457460
memset(&he_in, 0, sizeof(he_in));
458461
he_in.he = MLX5_SET_HOST_ENDIANNESS;
459462
err = mlx5_core_access_reg(dev, &he_in, sizeof(he_in),
@@ -1049,6 +1052,12 @@ static int mlx5_load_one(struct mlx5_core_dev *dev, struct mlx5_priv *priv)
10491052
mlx5_init_srq_table(dev);
10501053
mlx5_init_mr_table(dev);
10511054

1055+
err = mlx5_sriov_init(dev);
1056+
if (err) {
1057+
dev_err(&pdev->dev, "sriov init failed %d\n", err);
1058+
goto err_sriov;
1059+
}
1060+
10521061
err = mlx5_register_device(dev);
10531062
if (err) {
10541063
dev_err(&pdev->dev, "mlx5_register_device failed %d\n", err);
@@ -1065,6 +1074,10 @@ static int mlx5_load_one(struct mlx5_core_dev *dev, struct mlx5_priv *priv)
10651074

10661075
return 0;
10671076

1077+
err_sriov:
1078+
if (mlx5_sriov_cleanup(dev))
1079+
dev_err(&dev->pdev->dev, "sriov cleanup failed\n");
1080+
10681081
err_reg_dev:
10691082
mlx5_cleanup_mr_table(dev);
10701083
mlx5_cleanup_srq_table(dev);
@@ -1120,6 +1133,13 @@ static int mlx5_unload_one(struct mlx5_core_dev *dev, struct mlx5_priv *priv)
11201133
{
11211134
int err = 0;
11221135

1136+
err = mlx5_sriov_cleanup(dev);
1137+
if (err) {
1138+
dev_warn(&dev->pdev->dev, "%s: sriov cleanup failed - abort\n",
1139+
__func__);
1140+
return err;
1141+
}
1142+
11231143
mutex_lock(&dev->intf_state_mutex);
11241144
if (dev->interface_state == MLX5_INTERFACE_STATE_DOWN) {
11251145
dev_warn(&dev->pdev->dev, "%s: interface is down, NOP\n",
@@ -1192,6 +1212,7 @@ static int init_one(struct pci_dev *pdev,
11921212
return -ENOMEM;
11931213
}
11941214
priv = &dev->priv;
1215+
priv->pci_dev_data = id->driver_data;
11951216

11961217
pci_set_drvdata(pdev, dev);
11971218

@@ -1362,12 +1383,12 @@ static const struct pci_error_handlers mlx5_err_handler = {
13621383
};
13631384

13641385
static const struct pci_device_id mlx5_core_pci_table[] = {
1365-
{ PCI_VDEVICE(MELLANOX, 0x1011) }, /* Connect-IB */
1366-
{ PCI_VDEVICE(MELLANOX, 0x1012) }, /* Connect-IB VF */
1367-
{ PCI_VDEVICE(MELLANOX, 0x1013) }, /* ConnectX-4 */
1368-
{ PCI_VDEVICE(MELLANOX, 0x1014) }, /* ConnectX-4 VF */
1369-
{ PCI_VDEVICE(MELLANOX, 0x1015) }, /* ConnectX-4LX */
1370-
{ PCI_VDEVICE(MELLANOX, 0x1016) }, /* ConnectX-4LX VF */
1386+
{ PCI_VDEVICE(MELLANOX, 0x1011) }, /* Connect-IB */
1387+
{ PCI_VDEVICE(MELLANOX, 0x1012), MLX5_PCI_DEV_IS_VF}, /* Connect-IB VF */
1388+
{ PCI_VDEVICE(MELLANOX, 0x1013) }, /* ConnectX-4 */
1389+
{ PCI_VDEVICE(MELLANOX, 0x1014), MLX5_PCI_DEV_IS_VF}, /* ConnectX-4 VF */
1390+
{ PCI_VDEVICE(MELLANOX, 0x1015) }, /* ConnectX-4LX */
1391+
{ PCI_VDEVICE(MELLANOX, 0x1016), MLX5_PCI_DEV_IS_VF}, /* ConnectX-4LX VF */
13711392
{ 0, }
13721393
};
13731394

@@ -1378,7 +1399,8 @@ static struct pci_driver mlx5_core_driver = {
13781399
.id_table = mlx5_core_pci_table,
13791400
.probe = init_one,
13801401
.remove = remove_one,
1381-
.err_handler = &mlx5_err_handler
1402+
.err_handler = &mlx5_err_handler,
1403+
.sriov_configure = mlx5_core_sriov_configure,
13821404
};
13831405

13841406
static int __init init(void)

drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,8 +90,10 @@ void mlx5_core_event(struct mlx5_core_dev *dev, enum mlx5_dev_event event,
9090
unsigned long param);
9191
void mlx5_enter_error_state(struct mlx5_core_dev *dev);
9292
void mlx5_disable_device(struct mlx5_core_dev *dev);
93+
int mlx5_core_sriov_configure(struct pci_dev *dev, int num_vfs);
9394
int mlx5_core_enable_hca(struct mlx5_core_dev *dev, u16 func_id);
9495
int mlx5_core_disable_hca(struct mlx5_core_dev *dev, u16 func_id);
96+
int mlx5_wait_for_vf_pages(struct mlx5_core_dev *dev);
9597

9698
void mlx5e_init(void);
9799
void mlx5e_cleanup(void);

drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
#include <linux/highmem.h>
3434
#include <linux/kernel.h>
3535
#include <linux/module.h>
36+
#include <linux/delay.h>
3637
#include <linux/mlx5/driver.h>
3738
#include <linux/mlx5/cmd.h>
3839
#include "mlx5_core.h"
@@ -95,6 +96,7 @@ struct mlx5_manage_pages_outbox {
9596

9697
enum {
9798
MAX_RECLAIM_TIME_MSECS = 5000,
99+
MAX_RECLAIM_VFS_PAGES_TIME_MSECS = 2 * 1000 * 60,
98100
};
99101

100102
enum {
@@ -352,6 +354,10 @@ static int give_pages(struct mlx5_core_dev *dev, u16 func_id, int npages,
352354
goto out_4k;
353355
}
354356

357+
dev->priv.fw_pages += npages;
358+
if (func_id)
359+
dev->priv.vfs_pages += npages;
360+
355361
mlx5_core_dbg(dev, "err %d\n", err);
356362

357363
kvfree(in);
@@ -405,13 +411,22 @@ static int reclaim_pages(struct mlx5_core_dev *dev, u32 func_id, int npages,
405411
}
406412

407413
num_claimed = be32_to_cpu(out->num_entries);
414+
if (num_claimed > npages) {
415+
mlx5_core_warn(dev, "fw returned %d, driver asked %d => corruption\n",
416+
num_claimed, npages);
417+
err = -EINVAL;
418+
goto out_free;
419+
}
408420
if (nclaimed)
409421
*nclaimed = num_claimed;
410422

411423
for (i = 0; i < num_claimed; i++) {
412424
addr = be64_to_cpu(out->pas[i]);
413425
free_4k(dev, addr);
414426
}
427+
dev->priv.fw_pages -= num_claimed;
428+
if (func_id)
429+
dev->priv.vfs_pages -= num_claimed;
415430

416431
out_free:
417432
kvfree(out);
@@ -548,3 +563,26 @@ void mlx5_pagealloc_stop(struct mlx5_core_dev *dev)
548563
{
549564
destroy_workqueue(dev->priv.pg_wq);
550565
}
566+
567+
int mlx5_wait_for_vf_pages(struct mlx5_core_dev *dev)
568+
{
569+
unsigned long end = jiffies + msecs_to_jiffies(MAX_RECLAIM_VFS_PAGES_TIME_MSECS);
570+
int prev_vfs_pages = dev->priv.vfs_pages;
571+
572+
mlx5_core_dbg(dev, "Waiting for %d pages from %s\n", prev_vfs_pages,
573+
dev->priv.name);
574+
while (dev->priv.vfs_pages) {
575+
if (time_after(jiffies, end)) {
576+
mlx5_core_warn(dev, "aborting while there are %d pending pages\n", dev->priv.vfs_pages);
577+
return -ETIMEDOUT;
578+
}
579+
if (dev->priv.vfs_pages < prev_vfs_pages) {
580+
end = jiffies + msecs_to_jiffies(MAX_RECLAIM_VFS_PAGES_TIME_MSECS);
581+
prev_vfs_pages = dev->priv.vfs_pages;
582+
}
583+
msleep(50);
584+
}
585+
586+
mlx5_core_dbg(dev, "All pages received from %s\n", dev->priv.name);
587+
return 0;
588+
}

0 commit comments

Comments
 (0)