diff options
| -rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/main.c | 109 | ||||
| -rw-r--r-- | include/linux/mlx4/device.h | 7 |
2 files changed, 92 insertions, 24 deletions
diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c index abd0b1d277aa..e1a55857af71 100644 --- a/drivers/net/ethernet/mellanox/mlx4/main.c +++ b/drivers/net/ethernet/mellanox/mlx4/main.c | |||
| @@ -2193,6 +2193,10 @@ static int __mlx4_init_one(struct pci_dev *pdev, int pci_dev_data) | |||
| 2193 | struct mlx4_dev *dev; | 2193 | struct mlx4_dev *dev; |
| 2194 | int err; | 2194 | int err; |
| 2195 | int port; | 2195 | int port; |
| 2196 | int nvfs[MLX4_MAX_PORTS + 1], prb_vf[MLX4_MAX_PORTS + 1]; | ||
| 2197 | unsigned total_vfs = 0; | ||
| 2198 | int sriov_initialized = 0; | ||
| 2199 | unsigned int i; | ||
| 2196 | 2200 | ||
| 2197 | pr_info(DRV_NAME ": Initializing %s\n", pci_name(pdev)); | 2201 | pr_info(DRV_NAME ": Initializing %s\n", pci_name(pdev)); |
| 2198 | 2202 | ||
| @@ -2207,17 +2211,39 @@ static int __mlx4_init_one(struct pci_dev *pdev, int pci_dev_data) | |||
| 2207 | * per port, we must limit the number of VFs to 63 (since their are | 2211 | * per port, we must limit the number of VFs to 63 (since their are |
| 2208 | * 128 MACs) | 2212 | * 128 MACs) |
| 2209 | */ | 2213 | */ |
| 2210 | if (num_vfs >= MLX4_MAX_NUM_VF) { | 2214 | for (i = 0; i < sizeof(nvfs)/sizeof(nvfs[0]); |
| 2215 | total_vfs += nvfs[i], i++) { | ||
| 2216 | nvfs[i] = i == MLX4_MAX_PORTS ? num_vfs : 0; | ||
| 2217 | if (nvfs[i] < 0) { | ||
| 2218 | dev_err(&pdev->dev, "num_vfs module parameter cannot be negative\n"); | ||
| 2219 | return -EINVAL; | ||
| 2220 | } | ||
| 2221 | } | ||
| 2222 | for (i = 0; i < sizeof(prb_vf)/sizeof(prb_vf[0]); i++) { | ||
| 2223 | prb_vf[i] = i == MLX4_MAX_PORTS ? probe_vf : 0; | ||
| 2224 | if (prb_vf[i] < 0 || prb_vf[i] > nvfs[i]) { | ||
| 2225 | dev_err(&pdev->dev, "probe_vf module parameter cannot be negative or greater than num_vfs\n"); | ||
| 2226 | return -EINVAL; | ||
| 2227 | } | ||
| 2228 | } | ||
| 2229 | if (total_vfs >= MLX4_MAX_NUM_VF) { | ||
| 2211 | dev_err(&pdev->dev, | 2230 | dev_err(&pdev->dev, |
| 2212 | "Requested more VF's (%d) than allowed (%d)\n", | 2231 | "Requested more VF's (%d) than allowed (%d)\n", |
| 2213 | num_vfs, MLX4_MAX_NUM_VF - 1); | 2232 | total_vfs, MLX4_MAX_NUM_VF - 1); |
| 2214 | return -EINVAL; | 2233 | return -EINVAL; |
| 2215 | } | 2234 | } |
| 2216 | 2235 | ||
| 2217 | if (num_vfs < 0) { | 2236 | for (i = 0; i < MLX4_MAX_PORTS; i++) { |
| 2218 | pr_err("num_vfs module parameter cannot be negative\n"); | 2237 | if (nvfs[i] + nvfs[2] >= MLX4_MAX_NUM_VF_P_PORT) { |
| 2219 | return -EINVAL; | 2238 | dev_err(&pdev->dev, |
| 2239 | "Requested more VF's (%d) for port (%d) than allowed (%d)\n", | ||
| 2240 | nvfs[i] + nvfs[2], i + 1, | ||
| 2241 | MLX4_MAX_NUM_VF_P_PORT - 1); | ||
| 2242 | return -EINVAL; | ||
| 2243 | } | ||
| 2220 | } | 2244 | } |
| 2245 | |||
| 2246 | |||
| 2221 | /* | 2247 | /* |
| 2222 | * Check for BARs. | 2248 | * Check for BARs. |
| 2223 | */ | 2249 | */ |
| @@ -2292,11 +2318,23 @@ static int __mlx4_init_one(struct pci_dev *pdev, int pci_dev_data) | |||
| 2292 | if (pci_dev_data & MLX4_PCI_DEV_IS_VF) { | 2318 | if (pci_dev_data & MLX4_PCI_DEV_IS_VF) { |
| 2293 | /* When acting as pf, we normally skip vfs unless explicitly | 2319 | /* When acting as pf, we normally skip vfs unless explicitly |
| 2294 | * requested to probe them. */ | 2320 | * requested to probe them. */ |
| 2295 | if (num_vfs && extended_func_num(pdev) > probe_vf) { | 2321 | if (total_vfs) { |
| 2296 | mlx4_warn(dev, "Skipping virtual function:%d\n", | 2322 | unsigned vfs_offset = 0; |
| 2297 | extended_func_num(pdev)); | 2323 | for (i = 0; i < sizeof(nvfs)/sizeof(nvfs[0]) && |
| 2298 | err = -ENODEV; | 2324 | vfs_offset + nvfs[i] < extended_func_num(pdev); |
| 2299 | goto err_free_dev; | 2325 | vfs_offset += nvfs[i], i++) |
| 2326 | ; | ||
| 2327 | if (i == sizeof(nvfs)/sizeof(nvfs[0])) { | ||
| 2328 | err = -ENODEV; | ||
| 2329 | goto err_free_dev; | ||
| 2330 | } | ||
| 2331 | if ((extended_func_num(pdev) - vfs_offset) | ||
| 2332 | > prb_vf[i]) { | ||
| 2333 | mlx4_warn(dev, "Skipping virtual function:%d\n", | ||
| 2334 | extended_func_num(pdev)); | ||
| 2335 | err = -ENODEV; | ||
| 2336 | goto err_free_dev; | ||
| 2337 | } | ||
| 2300 | } | 2338 | } |
| 2301 | mlx4_warn(dev, "Detected virtual function - running in slave mode\n"); | 2339 | mlx4_warn(dev, "Detected virtual function - running in slave mode\n"); |
| 2302 | dev->flags |= MLX4_FLAG_SLAVE; | 2340 | dev->flags |= MLX4_FLAG_SLAVE; |
| @@ -2316,22 +2354,30 @@ static int __mlx4_init_one(struct pci_dev *pdev, int pci_dev_data) | |||
| 2316 | } | 2354 | } |
| 2317 | } | 2355 | } |
| 2318 | 2356 | ||
| 2319 | if (num_vfs) { | 2357 | if (total_vfs) { |
| 2320 | mlx4_warn(dev, "Enabling SR-IOV with %d VFs\n", num_vfs); | 2358 | mlx4_warn(dev, "Enabling SR-IOV with %d VFs\n", |
| 2321 | 2359 | total_vfs); | |
| 2322 | atomic_inc(&pf_loading); | 2360 | dev->dev_vfs = kzalloc( |
| 2323 | err = pci_enable_sriov(pdev, num_vfs); | 2361 | total_vfs * sizeof(*dev->dev_vfs), |
| 2324 | atomic_dec(&pf_loading); | 2362 | GFP_KERNEL); |
| 2325 | 2363 | if (NULL == dev->dev_vfs) { | |
| 2326 | if (err) { | 2364 | mlx4_err(dev, "Failed to allocate memory for VFs\n"); |
| 2327 | mlx4_err(dev, "Failed to enable SR-IOV, continuing without SR-IOV (err = %d).\n", | ||
| 2328 | err); | ||
| 2329 | err = 0; | 2365 | err = 0; |
| 2330 | } else { | 2366 | } else { |
| 2331 | mlx4_warn(dev, "Running in master mode\n"); | 2367 | atomic_inc(&pf_loading); |
| 2332 | dev->flags |= MLX4_FLAG_SRIOV | | 2368 | err = pci_enable_sriov(pdev, total_vfs); |
| 2333 | MLX4_FLAG_MASTER; | 2369 | atomic_dec(&pf_loading); |
| 2334 | dev->num_vfs = num_vfs; | 2370 | if (err) { |
| 2371 | mlx4_err(dev, "Failed to enable SR-IOV, continuing without SR-IOV (err = %d).\n", | ||
| 2372 | err); | ||
| 2373 | err = 0; | ||
| 2374 | } else { | ||
| 2375 | mlx4_warn(dev, "Running in master mode\n"); | ||
| 2376 | dev->flags |= MLX4_FLAG_SRIOV | | ||
| 2377 | MLX4_FLAG_MASTER; | ||
| 2378 | dev->num_vfs = total_vfs; | ||
| 2379 | sriov_initialized = 1; | ||
| 2380 | } | ||
| 2335 | } | 2381 | } |
| 2336 | } | 2382 | } |
| 2337 | 2383 | ||
| @@ -2396,12 +2442,24 @@ slave_start: | |||
| 2396 | /* In master functions, the communication channel must be initialized | 2442 | /* In master functions, the communication channel must be initialized |
| 2397 | * after obtaining its address from fw */ | 2443 | * after obtaining its address from fw */ |
| 2398 | if (mlx4_is_master(dev)) { | 2444 | if (mlx4_is_master(dev)) { |
| 2445 | unsigned sum = 0; | ||
| 2399 | err = mlx4_multi_func_init(dev); | 2446 | err = mlx4_multi_func_init(dev); |
| 2400 | if (err) { | 2447 | if (err) { |
| 2401 | mlx4_err(dev, "Failed to init master mfunc" | 2448 | mlx4_err(dev, "Failed to init master mfunc" |
| 2402 | "interface, aborting.\n"); | 2449 | "interface, aborting.\n"); |
| 2403 | goto err_close; | 2450 | goto err_close; |
| 2404 | } | 2451 | } |
| 2452 | if (sriov_initialized) { | ||
| 2453 | for (i = 0; i < sizeof(nvfs)/sizeof(nvfs[0]); i++) { | ||
| 2454 | unsigned j; | ||
| 2455 | for (j = 0; j < nvfs[i]; ++sum, ++j) { | ||
| 2456 | dev->dev_vfs[sum].min_port = | ||
| 2457 | i < 2 ? i + 1 : 1; | ||
| 2458 | dev->dev_vfs[sum].n_ports = i < 2 ? 1 : | ||
| 2459 | dev->caps.num_ports; | ||
| 2460 | } | ||
| 2461 | } | ||
| 2462 | } | ||
| 2405 | } | 2463 | } |
| 2406 | 2464 | ||
| 2407 | err = mlx4_alloc_eq_table(dev); | 2465 | err = mlx4_alloc_eq_table(dev); |
| @@ -2509,6 +2567,8 @@ err_rel_own: | |||
| 2509 | if (!mlx4_is_slave(dev)) | 2567 | if (!mlx4_is_slave(dev)) |
| 2510 | mlx4_free_ownership(dev); | 2568 | mlx4_free_ownership(dev); |
| 2511 | 2569 | ||
| 2570 | kfree(priv->dev.dev_vfs); | ||
| 2571 | |||
| 2512 | err_free_dev: | 2572 | err_free_dev: |
| 2513 | kfree(priv); | 2573 | kfree(priv); |
