diff options
Diffstat (limited to 'drivers/net/qlcnic/qlcnic_main.c')
-rw-r--r-- | drivers/net/qlcnic/qlcnic_main.c | 146 |
1 files changed, 116 insertions, 30 deletions
diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c index 6e619514feee..d6cc4d479591 100644 --- a/drivers/net/qlcnic/qlcnic_main.c +++ b/drivers/net/qlcnic/qlcnic_main.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/inetdevice.h> | 18 | #include <linux/inetdevice.h> |
19 | #include <linux/sysfs.h> | 19 | #include <linux/sysfs.h> |
20 | #include <linux/aer.h> | 20 | #include <linux/aer.h> |
21 | #include <linux/log2.h> | ||
21 | 22 | ||
22 | MODULE_DESCRIPTION("QLogic 1/10 GbE Converged/Intelligent Ethernet Driver"); | 23 | MODULE_DESCRIPTION("QLogic 1/10 GbE Converged/Intelligent Ethernet Driver"); |
23 | MODULE_LICENSE("GPL"); | 24 | MODULE_LICENSE("GPL"); |
@@ -350,39 +351,17 @@ static struct qlcnic_nic_template qlcnic_vf_ops = { | |||
350 | .start_firmware = qlcnicvf_start_firmware | 351 | .start_firmware = qlcnicvf_start_firmware |
351 | }; | 352 | }; |
352 | 353 | ||
353 | static void | 354 | static int qlcnic_enable_msix(struct qlcnic_adapter *adapter, u32 num_msix) |
354 | qlcnic_setup_intr(struct qlcnic_adapter *adapter) | ||
355 | { | 355 | { |
356 | const struct qlcnic_legacy_intr_set *legacy_intrp; | ||
357 | struct pci_dev *pdev = adapter->pdev; | 356 | struct pci_dev *pdev = adapter->pdev; |
358 | int err, num_msix; | 357 | int err = -1; |
359 | |||
360 | if (adapter->msix_supported) { | ||
361 | num_msix = (num_online_cpus() >= MSIX_ENTRIES_PER_ADAPTER) ? | ||
362 | MSIX_ENTRIES_PER_ADAPTER : 2; | ||
363 | } else | ||
364 | num_msix = 1; | ||
365 | 358 | ||
366 | adapter->max_sds_rings = 1; | 359 | adapter->max_sds_rings = 1; |
367 | |||
368 | adapter->flags &= ~(QLCNIC_MSI_ENABLED | QLCNIC_MSIX_ENABLED); | 360 | adapter->flags &= ~(QLCNIC_MSI_ENABLED | QLCNIC_MSIX_ENABLED); |
369 | |||
370 | legacy_intrp = &legacy_intr[adapter->ahw->pci_func]; | ||
371 | |||
372 | adapter->int_vec_bit = legacy_intrp->int_vec_bit; | ||
373 | adapter->tgt_status_reg = qlcnic_get_ioaddr(adapter, | ||
374 | legacy_intrp->tgt_status_reg); | ||
375 | adapter->tgt_mask_reg = qlcnic_get_ioaddr(adapter, | ||
376 | legacy_intrp->tgt_mask_reg); | ||
377 | adapter->isr_int_vec = qlcnic_get_ioaddr(adapter, ISR_INT_VECTOR); | ||
378 | |||
379 | adapter->crb_int_state_reg = qlcnic_get_ioaddr(adapter, | ||
380 | ISR_INT_STATE_REG); | ||
381 | |||
382 | qlcnic_set_msix_bit(pdev, 0); | 361 | qlcnic_set_msix_bit(pdev, 0); |
383 | 362 | ||
384 | if (adapter->msix_supported) { | 363 | if (adapter->msix_supported) { |
385 | 364 | enable_msix: | |
386 | qlcnic_init_msix_entries(adapter, num_msix); | 365 | qlcnic_init_msix_entries(adapter, num_msix); |
387 | err = pci_enable_msix(pdev, adapter->msix_entries, num_msix); | 366 | err = pci_enable_msix(pdev, adapter->msix_entries, num_msix); |
388 | if (err == 0) { | 367 | if (err == 0) { |
@@ -392,14 +371,22 @@ qlcnic_setup_intr(struct qlcnic_adapter *adapter) | |||
392 | adapter->max_sds_rings = num_msix; | 371 | adapter->max_sds_rings = num_msix; |
393 | 372 | ||
394 | dev_info(&pdev->dev, "using msi-x interrupts\n"); | 373 | dev_info(&pdev->dev, "using msi-x interrupts\n"); |
395 | return; | 374 | return err; |
396 | } | 375 | } |
376 | if (err > 0) { | ||
377 | num_msix = rounddown_pow_of_two(err); | ||
378 | if (num_msix) | ||
379 | goto enable_msix; | ||
380 | } | ||
381 | } | ||
382 | return err; | ||
383 | } | ||
397 | 384 | ||
398 | if (err > 0) | ||
399 | pci_disable_msix(pdev); | ||
400 | 385 | ||
401 | /* fall through for msi */ | 386 | static void qlcnic_enable_msi_legacy(struct qlcnic_adapter *adapter) |
402 | } | 387 | { |
388 | const struct qlcnic_legacy_intr_set *legacy_intrp; | ||
389 | struct pci_dev *pdev = adapter->pdev; | ||
403 | 390 | ||
404 | if (use_msi && !pci_enable_msi(pdev)) { | 391 | if (use_msi && !pci_enable_msi(pdev)) { |
405 | adapter->flags |= QLCNIC_MSI_ENABLED; | 392 | adapter->flags |= QLCNIC_MSI_ENABLED; |
@@ -410,11 +397,41 @@ qlcnic_setup_intr(struct qlcnic_adapter *adapter) | |||
410 | return; | 397 | return; |
411 | } | 398 | } |
412 | 399 | ||
400 | legacy_intrp = &legacy_intr[adapter->ahw->pci_func]; | ||
401 | |||
402 | adapter->int_vec_bit = legacy_intrp->int_vec_bit; | ||
403 | adapter->tgt_status_reg = qlcnic_get_ioaddr(adapter, | ||
404 | legacy_intrp->tgt_status_reg); | ||
405 | adapter->tgt_mask_reg = qlcnic_get_ioaddr(adapter, | ||
406 | legacy_intrp->tgt_mask_reg); | ||
407 | adapter->isr_int_vec = qlcnic_get_ioaddr(adapter, ISR_INT_VECTOR); | ||
408 | |||
409 | adapter->crb_int_state_reg = qlcnic_get_ioaddr(adapter, | ||
410 | ISR_INT_STATE_REG); | ||
413 | dev_info(&pdev->dev, "using legacy interrupts\n"); | 411 | dev_info(&pdev->dev, "using legacy interrupts\n"); |
414 | adapter->msix_entries[0].vector = pdev->irq; | 412 | adapter->msix_entries[0].vector = pdev->irq; |
415 | } | 413 | } |
416 | 414 | ||
417 | static void | 415 | static void |
416 | qlcnic_setup_intr(struct qlcnic_adapter *adapter) | ||
417 | { | ||
418 | int num_msix; | ||
419 | |||
420 | if (adapter->msix_supported) { | ||
421 | num_msix = (num_online_cpus() >= | ||
422 | QLCNIC_DEF_NUM_STS_DESC_RINGS) ? | ||
423 | QLCNIC_DEF_NUM_STS_DESC_RINGS : | ||
424 | QLCNIC_MIN_NUM_RSS_RINGS; | ||
425 | } else | ||
426 | num_msix = 1; | ||
427 | |||
428 | if (!qlcnic_enable_msix(adapter, num_msix)) | ||
429 | return; | ||
430 | |||
431 | qlcnic_enable_msi_legacy(adapter); | ||
432 | } | ||
433 | |||
434 | static void | ||
418 | qlcnic_teardown_intr(struct qlcnic_adapter *adapter) | 435 | qlcnic_teardown_intr(struct qlcnic_adapter *adapter) |
419 | { | 436 | { |
420 | if (adapter->flags & QLCNIC_MSIX_ENABLED) | 437 | if (adapter->flags & QLCNIC_MSIX_ENABLED) |
@@ -1493,6 +1510,19 @@ static int qlcnic_set_dma_mask(struct pci_dev *pdev, u8 *pci_using_dac) | |||
1493 | return 0; | 1510 | return 0; |
1494 | } | 1511 | } |
1495 | 1512 | ||
1513 | static int | ||
1514 | qlcnic_alloc_msix_entries(struct qlcnic_adapter *adapter, u16 count) | ||
1515 | { | ||
1516 | adapter->msix_entries = kcalloc(count, sizeof(struct msix_entry), | ||
1517 | GFP_KERNEL); | ||
1518 | |||
1519 | if (adapter->msix_entries) | ||
1520 | return 0; | ||
1521 | |||
1522 | dev_err(&adapter->pdev->dev, "failed allocating msix_entries\n"); | ||
1523 | return -ENOMEM; | ||
1524 | } | ||
1525 | |||
1496 | static int __devinit | 1526 | static int __devinit |
1497 | qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | 1527 | qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) |
1498 | { | 1528 | { |
@@ -1587,6 +1617,10 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
1587 | 1617 | ||
1588 | qlcnic_clear_stats(adapter); | 1618 | qlcnic_clear_stats(adapter); |
1589 | 1619 | ||
1620 | err = qlcnic_alloc_msix_entries(adapter, adapter->max_rx_ques); | ||
1621 | if (err) | ||
1622 | goto err_out_decr_ref; | ||
1623 | |||
1590 | qlcnic_setup_intr(adapter); | 1624 | qlcnic_setup_intr(adapter); |
1591 | 1625 | ||
1592 | err = qlcnic_setup_netdev(adapter, netdev, pci_using_dac); | 1626 | err = qlcnic_setup_netdev(adapter, netdev, pci_using_dac); |
@@ -1615,6 +1649,7 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
1615 | 1649 | ||
1616 | err_out_disable_msi: | 1650 | err_out_disable_msi: |
1617 | qlcnic_teardown_intr(adapter); | 1651 | qlcnic_teardown_intr(adapter); |
1652 | kfree(adapter->msix_entries); | ||
1618 | 1653 | ||
1619 | err_out_decr_ref: | 1654 | err_out_decr_ref: |
1620 | qlcnic_clr_all_drv_state(adapter, 0); | 1655 | qlcnic_clr_all_drv_state(adapter, 0); |
@@ -1666,6 +1701,7 @@ static void __devexit qlcnic_remove(struct pci_dev *pdev) | |||
1666 | qlcnic_free_lb_filters_mem(adapter); | 1701 | qlcnic_free_lb_filters_mem(adapter); |
1667 | 1702 | ||
1668 | qlcnic_teardown_intr(adapter); | 1703 | qlcnic_teardown_intr(adapter); |
1704 | kfree(adapter->msix_entries); | ||
1669 | 1705 | ||
1670 | qlcnic_remove_diag_entries(adapter); | 1706 | qlcnic_remove_diag_entries(adapter); |
1671 | 1707 | ||
@@ -3299,6 +3335,56 @@ static struct device_attribute dev_attr_diag_mode = { | |||
3299 | .store = qlcnic_store_diag_mode, | 3335 | .store = qlcnic_store_diag_mode, |
3300 | }; | 3336 | }; |
3301 | 3337 | ||
3338 | int qlcnic_validate_max_rss(struct net_device *netdev, u8 max_hw, u8 val) | ||
3339 | { | ||
3340 | if (!use_msi_x && !use_msi) { | ||
3341 | netdev_info(netdev, "no msix or msi support, hence no rss\n"); | ||
3342 | return -EINVAL; | ||
3343 | } | ||
3344 | |||
3345 | if ((val > max_hw) || (val < 2) || !is_power_of_2(val)) { | ||
3346 | netdev_info(netdev, "rss_ring valid range [2 - %x] in " | ||
3347 | " powers of 2\n", max_hw); | ||
3348 | return -EINVAL; | ||
3349 | } | ||
3350 | return 0; | ||
3351 | |||
3352 | } | ||
3353 | |||
3354 | int qlcnic_set_max_rss(struct qlcnic_adapter *adapter, u8 data) | ||
3355 | { | ||
3356 | struct net_device *netdev = adapter->netdev; | ||
3357 | int err = 0; | ||
3358 | |||
3359 | if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state)) | ||
3360 | return -EBUSY; | ||
3361 | |||
3362 | netif_device_detach(netdev); | ||
3363 | if (netif_running(netdev)) | ||
3364 | __qlcnic_down(adapter, netdev); | ||
3365 | qlcnic_detach(adapter); | ||
3366 | qlcnic_teardown_intr(adapter); | ||
3367 | |||
3368 | if (qlcnic_enable_msix(adapter, data)) { | ||
3369 | netdev_info(netdev, "failed setting max_rss; rss disabled\n"); | ||
3370 | qlcnic_enable_msi_legacy(adapter); | ||
3371 | } | ||
3372 | |||
3373 | if (netif_running(netdev)) { | ||
3374 | err = qlcnic_attach(adapter); | ||
3375 | if (err) | ||
3376 | goto done; | ||
3377 | err = __qlcnic_up(adapter, netdev); | ||
3378 | if (err) | ||
3379 | goto done; | ||
3380 | qlcnic_restore_indev_addr(netdev, NETDEV_UP); | ||
3381 | } | ||
3382 | done: | ||
3383 | netif_device_attach(netdev); | ||
3384 | clear_bit(__QLCNIC_RESETTING, &adapter->state); | ||
3385 | return err; | ||
3386 | } | ||
3387 | |||
3302 | static int | 3388 | static int |
3303 | qlcnic_sysfs_validate_crb(struct qlcnic_adapter *adapter, | 3389 | qlcnic_sysfs_validate_crb(struct qlcnic_adapter *adapter, |
3304 | loff_t offset, size_t size) | 3390 | loff_t offset, size_t size) |