diff options
author | Ben Hutchings <bhutchings@solarflare.com> | 2010-09-10 02:42:33 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-09-10 15:27:34 -0400 |
commit | 4642610c77b345130d6b5a08c75d23ad98601fd5 (patch) | |
tree | bf6345d84e6dbd3a3d44ff4e050dc862f01a01fc /drivers/net/sfc | |
parent | ecc910f520ba8f22848982ee816ad75c449b805d (diff) |
sfc: Allow changing the DMA ring sizes dynamically via ethtool
This requires some reorganisation of channel setup and teardown to
ensure that we can always roll-back a failed change.
Based on work by Steve Hodgson <shodgson@solarflare.com>
Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/sfc')
-rw-r--r-- | drivers/net/sfc/efx.c | 218 | ||||
-rw-r--r-- | drivers/net/sfc/efx.h | 7 | ||||
-rw-r--r-- | drivers/net/sfc/ethtool.c | 38 | ||||
-rw-r--r-- | drivers/net/sfc/net_driver.h | 4 | ||||
-rw-r--r-- | drivers/net/sfc/nic.c | 9 |
5 files changed, 224 insertions, 52 deletions
diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c index 6166e2207160..f702f1fb63b6 100644 --- a/drivers/net/sfc/efx.c +++ b/drivers/net/sfc/efx.c | |||
@@ -201,10 +201,13 @@ MODULE_PARM_DESC(debug, "Bitmapped debugging message enable value"); | |||
201 | * Utility functions and prototypes | 201 | * Utility functions and prototypes |
202 | * | 202 | * |
203 | *************************************************************************/ | 203 | *************************************************************************/ |
204 | static void efx_remove_channel(struct efx_channel *channel); | 204 | |
205 | static void efx_remove_channels(struct efx_nic *efx); | ||
205 | static void efx_remove_port(struct efx_nic *efx); | 206 | static void efx_remove_port(struct efx_nic *efx); |
206 | static void efx_fini_napi(struct efx_nic *efx); | 207 | static void efx_fini_napi(struct efx_nic *efx); |
207 | static void efx_fini_channels(struct efx_nic *efx); | 208 | static void efx_fini_struct(struct efx_nic *efx); |
209 | static void efx_start_all(struct efx_nic *efx); | ||
210 | static void efx_stop_all(struct efx_nic *efx); | ||
208 | 211 | ||
209 | #define EFX_ASSERT_RESET_SERIALISED(efx) \ | 212 | #define EFX_ASSERT_RESET_SERIALISED(efx) \ |
210 | do { \ | 213 | do { \ |
@@ -413,6 +416,63 @@ static void efx_remove_eventq(struct efx_channel *channel) | |||
413 | * | 416 | * |
414 | *************************************************************************/ | 417 | *************************************************************************/ |
415 | 418 | ||
419 | /* Allocate and initialise a channel structure, optionally copying | ||
420 | * parameters (but not resources) from an old channel structure. */ | ||
421 | static struct efx_channel * | ||
422 | efx_alloc_channel(struct efx_nic *efx, int i, struct efx_channel *old_channel) | ||
423 | { | ||
424 | struct efx_channel *channel; | ||
425 | struct efx_rx_queue *rx_queue; | ||
426 | struct efx_tx_queue *tx_queue; | ||
427 | int j; | ||
428 | |||
429 | if (old_channel) { | ||
430 | channel = kmalloc(sizeof(*channel), GFP_KERNEL); | ||
431 | if (!channel) | ||
432 | return NULL; | ||
433 | |||
434 | *channel = *old_channel; | ||
435 | |||
436 | memset(&channel->eventq, 0, sizeof(channel->eventq)); | ||
437 | |||
438 | rx_queue = &channel->rx_queue; | ||
439 | rx_queue->buffer = NULL; | ||
440 | memset(&rx_queue->rxd, 0, sizeof(rx_queue->rxd)); | ||
441 | |||
442 | for (j = 0; j < EFX_TXQ_TYPES; j++) { | ||
443 | tx_queue = &channel->tx_queue[j]; | ||
444 | if (tx_queue->channel) | ||
445 | tx_queue->channel = channel; | ||
446 | tx_queue->buffer = NULL; | ||
447 | memset(&tx_queue->txd, 0, sizeof(tx_queue->txd)); | ||
448 | } | ||
449 | } else { | ||
450 | channel = kzalloc(sizeof(*channel), GFP_KERNEL); | ||
451 | if (!channel) | ||
452 | return NULL; | ||
453 | |||
454 | channel->efx = efx; | ||
455 | channel->channel = i; | ||
456 | |||
457 | for (j = 0; j < EFX_TXQ_TYPES; j++) { | ||
458 | tx_queue = &channel->tx_queue[j]; | ||
459 | tx_queue->efx = efx; | ||
460 | tx_queue->queue = i * EFX_TXQ_TYPES + j; | ||
461 | tx_queue->channel = channel; | ||
462 | } | ||
463 | } | ||
464 | |||
465 | spin_lock_init(&channel->tx_stop_lock); | ||
466 | atomic_set(&channel->tx_stop_count, 1); | ||
467 | |||
468 | rx_queue = &channel->rx_queue; | ||
469 | rx_queue->efx = efx; | ||
470 | setup_timer(&rx_queue->slow_fill, efx_rx_slow_fill, | ||
471 | (unsigned long)rx_queue); | ||
472 | |||
473 | return channel; | ||
474 | } | ||
475 | |||
416 | static int efx_probe_channel(struct efx_channel *channel) | 476 | static int efx_probe_channel(struct efx_channel *channel) |
417 | { | 477 | { |
418 | struct efx_tx_queue *tx_queue; | 478 | struct efx_tx_queue *tx_queue; |
@@ -469,11 +529,38 @@ static void efx_set_channel_names(struct efx_nic *efx) | |||
469 | number -= efx->n_rx_channels; | 529 | number -= efx->n_rx_channels; |
470 | } | 530 | } |
471 | } | 531 | } |
472 | snprintf(channel->name, sizeof(channel->name), | 532 | snprintf(efx->channel_name[channel->channel], |
533 | sizeof(efx->channel_name[0]), | ||
473 | "%s%s-%d", efx->name, type, number); | 534 | "%s%s-%d", efx->name, type, number); |
474 | } | 535 | } |
475 | } | 536 | } |
476 | 537 | ||
538 | static int efx_probe_channels(struct efx_nic *efx) | ||
539 | { | ||
540 | struct efx_channel *channel; | ||
541 | int rc; | ||
542 | |||
543 | /* Restart special buffer allocation */ | ||
544 | efx->next_buffer_table = 0; | ||
545 | |||
546 | efx_for_each_channel(channel, efx) { | ||
547 | rc = efx_probe_channel(channel); | ||
548 | if (rc) { | ||
549 | netif_err(efx, probe, efx->net_dev, | ||
550 | "failed to create channel %d\n", | ||
551 | channel->channel); | ||
552 | goto fail; | ||
553 | } | ||
554 | } | ||
555 | efx_set_channel_names(efx); | ||
556 | |||
557 | return 0; | ||
558 | |||
559 | fail: | ||
560 | efx_remove_channels(efx); | ||
561 | return rc; | ||
562 | } | ||
563 | |||
477 | /* Channels are shutdown and reinitialised whilst the NIC is running | 564 | /* Channels are shutdown and reinitialised whilst the NIC is running |
478 | * to propagate configuration changes (mtu, checksum offload), or | 565 | * to propagate configuration changes (mtu, checksum offload), or |
479 | * to clear hardware error conditions | 566 | * to clear hardware error conditions |
@@ -611,6 +698,75 @@ static void efx_remove_channel(struct efx_channel *channel) | |||
611 | efx_remove_eventq(channel); | 698 | efx_remove_eventq(channel); |
612 | } | 699 | } |
613 | 700 | ||
701 | static void efx_remove_channels(struct efx_nic *efx) | ||
702 | { | ||
703 | struct efx_channel *channel; | ||
704 | |||
705 | efx_for_each_channel(channel, efx) | ||
706 | efx_remove_channel(channel); | ||
707 | } | ||
708 | |||
709 | int | ||
710 | efx_realloc_channels(struct efx_nic *efx, u32 rxq_entries, u32 txq_entries) | ||
711 | { | ||
712 | struct efx_channel *other_channel[EFX_MAX_CHANNELS], *channel; | ||
713 | u32 old_rxq_entries, old_txq_entries; | ||
714 | unsigned i; | ||
715 | int rc; | ||
716 | |||
717 | efx_stop_all(efx); | ||
718 | efx_fini_channels(efx); | ||
719 | |||
720 | /* Clone channels */ | ||
721 | memset(other_channel, 0, sizeof(other_channel)); | ||
722 | for (i = 0; i < efx->n_channels; i++) { | ||
723 | channel = efx_alloc_channel(efx, i, efx->channel[i]); | ||
724 | if (!channel) { | ||
725 | rc = -ENOMEM; | ||
726 | goto out; | ||
727 | } | ||
728 | other_channel[i] = channel; | ||
729 | } | ||
730 | |||
731 | /* Swap entry counts and channel pointers */ | ||
732 | old_rxq_entries = efx->rxq_entries; | ||
733 | old_txq_entries = efx->txq_entries; | ||
734 | efx->rxq_entries = rxq_entries; | ||
735 | efx->txq_entries = txq_entries; | ||
736 | for (i = 0; i < efx->n_channels; i++) { | ||
737 | channel = efx->channel[i]; | ||
738 | efx->channel[i] = other_channel[i]; | ||
739 | other_channel[i] = channel; | ||
740 | } | ||
741 | |||
742 | rc = efx_probe_channels(efx); | ||
743 | if (rc) | ||
744 | goto rollback; | ||
745 | |||
746 | /* Destroy old channels */ | ||
747 | for (i = 0; i < efx->n_channels; i++) | ||
748 | efx_remove_channel(other_channel[i]); | ||
749 | out: | ||
750 | /* Free unused channel structures */ | ||
751 | for (i = 0; i < efx->n_channels; i++) | ||
752 | kfree(other_channel[i]); | ||
753 | |||
754 | efx_init_channels(efx); | ||
755 | efx_start_all(efx); | ||
756 | return rc; | ||
757 | |||
758 | rollback: | ||
759 | /* Swap back */ | ||
760 | efx->rxq_entries = old_rxq_entries; | ||
761 | efx->txq_entries = old_txq_entries; | ||
762 | for (i = 0; i < efx->n_channels; i++) { | ||
763 | channel = efx->channel[i]; | ||
764 | efx->channel[i] = other_channel[i]; | ||
765 | other_channel[i] = channel; | ||
766 | } | ||
767 | goto out; | ||
768 | } | ||
769 | |||
614 | void efx_schedule_slow_fill(struct efx_rx_queue *rx_queue) | 770 | void efx_schedule_slow_fill(struct efx_rx_queue *rx_queue) |
615 | { | 771 | { |
616 | mod_timer(&rx_queue->slow_fill, jiffies + msecs_to_jiffies(100)); | 772 | mod_timer(&rx_queue->slow_fill, jiffies + msecs_to_jiffies(100)); |
@@ -1182,41 +1338,28 @@ static void efx_remove_nic(struct efx_nic *efx) | |||
1182 | 1338 | ||
1183 | static int efx_probe_all(struct efx_nic *efx) | 1339 | static int efx_probe_all(struct efx_nic *efx) |
1184 | { | 1340 | { |
1185 | struct efx_channel *channel; | ||
1186 | int rc; | 1341 | int rc; |
1187 | 1342 | ||
1188 | /* Create NIC */ | ||
1189 | rc = efx_probe_nic(efx); | 1343 | rc = efx_probe_nic(efx); |
1190 | if (rc) { | 1344 | if (rc) { |
1191 | netif_err(efx, probe, efx->net_dev, "failed to create NIC\n"); | 1345 | netif_err(efx, probe, efx->net_dev, "failed to create NIC\n"); |
1192 | goto fail1; | 1346 | goto fail1; |
1193 | } | 1347 | } |
1194 | 1348 | ||
1195 | /* Create port */ | ||
1196 | rc = efx_probe_port(efx); | 1349 | rc = efx_probe_port(efx); |
1197 | if (rc) { | 1350 | if (rc) { |
1198 | netif_err(efx, probe, efx->net_dev, "failed to create port\n"); | 1351 | netif_err(efx, probe, efx->net_dev, "failed to create port\n"); |
1199 | goto fail2; | 1352 | goto fail2; |
1200 | } | 1353 | } |
1201 | 1354 | ||
1202 | /* Create channels */ | ||
1203 | efx->rxq_entries = efx->txq_entries = EFX_DEFAULT_DMAQ_SIZE; | 1355 | efx->rxq_entries = efx->txq_entries = EFX_DEFAULT_DMAQ_SIZE; |
1204 | efx_for_each_channel(channel, efx) { | 1356 | rc = efx_probe_channels(efx); |
1205 | rc = efx_probe_channel(channel); | 1357 | if (rc) |
1206 | if (rc) { | 1358 | goto fail3; |
1207 | netif_err(efx, probe, efx->net_dev, | ||
1208 | "failed to create channel %d\n", | ||
1209 | channel->channel); | ||
1210 | goto fail3; | ||
1211 | } | ||
1212 | } | ||
1213 | efx_set_channel_names(efx); | ||
1214 | 1359 | ||
1215 | return 0; | 1360 | return 0; |
1216 | 1361 | ||
1217 | fail3: | 1362 | fail3: |
1218 | efx_for_each_channel(channel, efx) | ||
1219 | efx_remove_channel(channel); | ||
1220 | efx_remove_port(efx); | 1363 | efx_remove_port(efx); |
1221 | fail2: | 1364 | fail2: |
1222 | efx_remove_nic(efx); | 1365 | efx_remove_nic(efx); |
@@ -1346,10 +1489,7 @@ static void efx_stop_all(struct efx_nic *efx) | |||
1346 | 1489 | ||
1347 | static void efx_remove_all(struct efx_nic *efx) | 1490 | static void efx_remove_all(struct efx_nic *efx) |
1348 | { | 1491 | { |
1349 | struct efx_channel *channel; | 1492 | efx_remove_channels(efx); |
1350 | |||
1351 | efx_for_each_channel(channel, efx) | ||
1352 | efx_remove_channel(channel); | ||
1353 | efx_remove_port(efx); | 1493 | efx_remove_port(efx); |
1354 | efx_remove_nic(efx); | 1494 | efx_remove_nic(efx); |
1355 | } | 1495 | } |
@@ -2058,10 +2198,7 @@ static struct efx_phy_operations efx_dummy_phy_operations = { | |||
2058 | static int efx_init_struct(struct efx_nic *efx, struct efx_nic_type *type, | 2198 | static int efx_init_struct(struct efx_nic *efx, struct efx_nic_type *type, |
2059 | struct pci_dev *pci_dev, struct net_device *net_dev) | 2199 | struct pci_dev *pci_dev, struct net_device *net_dev) |
2060 | { | 2200 | { |
2061 | struct efx_channel *channel; | 2201 | int i; |
2062 | struct efx_tx_queue *tx_queue; | ||
2063 | struct efx_rx_queue *rx_queue; | ||
2064 | int i, j; | ||
2065 | 2202 | ||
2066 | /* Initialise common structures */ | 2203 | /* Initialise common structures */ |
2067 | memset(efx, 0, sizeof(*efx)); | 2204 | memset(efx, 0, sizeof(*efx)); |
@@ -2089,24 +2226,9 @@ static int efx_init_struct(struct efx_nic *efx, struct efx_nic_type *type, | |||
2089 | INIT_WORK(&efx->mac_work, efx_mac_work); | 2226 | INIT_WORK(&efx->mac_work, efx_mac_work); |
2090 | 2227 | ||
2091 | for (i = 0; i < EFX_MAX_CHANNELS; i++) { | 2228 | for (i = 0; i < EFX_MAX_CHANNELS; i++) { |
2092 | efx->channel[i] = kzalloc(sizeof(*channel), GFP_KERNEL); | 2229 | efx->channel[i] = efx_alloc_channel(efx, i, NULL); |
2093 | channel = efx->channel[i]; | 2230 | if (!efx->channel[i]) |
2094 | channel->efx = efx; | 2231 | goto fail; |
2095 | channel->channel = i; | ||
2096 | spin_lock_init(&channel->tx_stop_lock); | ||
2097 | atomic_set(&channel->tx_stop_count, 1); | ||
2098 | |||
2099 | for (j = 0; j < EFX_TXQ_TYPES; j++) { | ||
2100 | tx_queue = &channel->tx_queue[j]; | ||
2101 | tx_queue->efx = efx; | ||
2102 | tx_queue->queue = i * EFX_TXQ_TYPES + j; | ||
2103 | tx_queue->channel = channel; | ||
2104 | } | ||
2105 | |||
2106 | rx_queue = &channel->rx_queue; | ||
2107 | rx_queue->efx = efx; | ||
2108 | setup_timer(&rx_queue->slow_fill, efx_rx_slow_fill, | ||
2109 | (unsigned long)rx_queue); | ||
2110 | } | 2232 | } |
2111 | 2233 | ||
2112 | efx->type = type; | 2234 | efx->type = type; |
@@ -2122,9 +2244,13 @@ static int efx_init_struct(struct efx_nic *efx, struct efx_nic_type *type, | |||
2122 | pci_name(pci_dev)); | 2244 | pci_name(pci_dev)); |
2123 | efx->workqueue = create_singlethread_workqueue(efx->workqueue_name); | 2245 | efx->workqueue = create_singlethread_workqueue(efx->workqueue_name); |
2124 | if (!efx->workqueue) | 2246 | if (!efx->workqueue) |
2125 | return -ENOMEM; | 2247 | goto fail; |
2126 | 2248 | ||
2127 | return 0; | 2249 | return 0; |
2250 | |||
2251 | fail: | ||
2252 | efx_fini_struct(efx); | ||
2253 | return -ENOMEM; | ||
2128 | } | 2254 | } |
2129 | 2255 | ||
2130 | static void efx_fini_struct(struct efx_nic *efx) | 2256 | static void efx_fini_struct(struct efx_nic *efx) |
diff --git a/drivers/net/sfc/efx.h b/drivers/net/sfc/efx.h index c15a2d3c2c23..e783c0fedfd8 100644 --- a/drivers/net/sfc/efx.h +++ b/drivers/net/sfc/efx.h | |||
@@ -59,8 +59,15 @@ extern void efx_schedule_slow_fill(struct efx_rx_queue *rx_queue); | |||
59 | #define EFX_MAX_EVQ_SIZE 16384UL | 59 | #define EFX_MAX_EVQ_SIZE 16384UL |
60 | #define EFX_MIN_EVQ_SIZE 512UL | 60 | #define EFX_MIN_EVQ_SIZE 512UL |
61 | 61 | ||
62 | /* The smallest [rt]xq_entries that the driver supports. Callers of | ||
63 | * efx_wake_queue() assume that they can subsequently send at least one | ||
64 | * skb. Falcon/A1 may require up to three descriptors per skb_frag. */ | ||
65 | #define EFX_MIN_RING_SIZE (roundup_pow_of_two(2 * 3 * MAX_SKB_FRAGS)) | ||
66 | |||
62 | /* Channels */ | 67 | /* Channels */ |
63 | extern void efx_process_channel_now(struct efx_channel *channel); | 68 | extern void efx_process_channel_now(struct efx_channel *channel); |
69 | extern int | ||
70 | efx_realloc_channels(struct efx_nic *efx, u32 rxq_entries, u32 txq_entries); | ||
64 | 71 | ||
65 | /* Ports */ | 72 | /* Ports */ |
66 | extern int efx_reconfigure_port(struct efx_nic *efx); | 73 | extern int efx_reconfigure_port(struct efx_nic *efx); |
diff --git a/drivers/net/sfc/ethtool.c b/drivers/net/sfc/ethtool.c index b9291db023bb..7f735d804801 100644 --- a/drivers/net/sfc/ethtool.c +++ b/drivers/net/sfc/ethtool.c | |||
@@ -742,6 +742,42 @@ static int efx_ethtool_set_coalesce(struct net_device *net_dev, | |||
742 | return 0; | 742 | return 0; |
743 | } | 743 | } |
744 | 744 | ||
745 | static void efx_ethtool_get_ringparam(struct net_device *net_dev, | ||
746 | struct ethtool_ringparam *ring) | ||
747 | { | ||
748 | struct efx_nic *efx = netdev_priv(net_dev); | ||
749 | |||
750 | ring->rx_max_pending = EFX_MAX_DMAQ_SIZE; | ||
751 | ring->tx_max_pending = EFX_MAX_DMAQ_SIZE; | ||
752 | ring->rx_mini_max_pending = 0; | ||
753 | ring->rx_jumbo_max_pending = 0; | ||
754 | ring->rx_pending = efx->rxq_entries; | ||
755 | ring->tx_pending = efx->txq_entries; | ||
756 | ring->rx_mini_pending = 0; | ||
757 | ring->rx_jumbo_pending = 0; | ||
758 | } | ||
759 | |||
760 | static int efx_ethtool_set_ringparam(struct net_device *net_dev, | ||
761 | struct ethtool_ringparam *ring) | ||
762 | { | ||
763 | struct efx_nic *efx = netdev_priv(net_dev); | ||
764 | |||
765 | if (ring->rx_mini_pending || ring->rx_jumbo_pending || | ||
766 | ring->rx_pending > EFX_MAX_DMAQ_SIZE || | ||
767 | ring->tx_pending > EFX_MAX_DMAQ_SIZE) | ||
768 | return -EINVAL; | ||
769 | |||
770 | if (ring->rx_pending < EFX_MIN_RING_SIZE || | ||
771 | ring->tx_pending < EFX_MIN_RING_SIZE) { | ||
772 | netif_err(efx, drv, efx->net_dev, | ||
773 | "TX and RX queues cannot be smaller than %ld\n", | ||
774 | EFX_MIN_RING_SIZE); | ||
775 | return -EINVAL; | ||
776 | } | ||
777 | |||
778 | return efx_realloc_channels(efx, ring->rx_pending, ring->tx_pending); | ||
779 | } | ||
780 | |||
745 | static int efx_ethtool_set_pauseparam(struct net_device *net_dev, | 781 | static int efx_ethtool_set_pauseparam(struct net_device *net_dev, |
746 | struct ethtool_pauseparam *pause) | 782 | struct ethtool_pauseparam *pause) |
747 | { | 783 | { |
@@ -972,6 +1008,8 @@ const struct ethtool_ops efx_ethtool_ops = { | |||
972 | .set_eeprom = efx_ethtool_set_eeprom, | 1008 | .set_eeprom = efx_ethtool_set_eeprom, |
973 | .get_coalesce = efx_ethtool_get_coalesce, | 1009 | .get_coalesce = efx_ethtool_get_coalesce, |
974 | .set_coalesce = efx_ethtool_set_coalesce, | 1010 | .set_coalesce = efx_ethtool_set_coalesce, |
1011 | .get_ringparam = efx_ethtool_get_ringparam, | ||
1012 | .set_ringparam = efx_ethtool_set_ringparam, | ||
975 | .get_pauseparam = efx_ethtool_get_pauseparam, | 1013 | .get_pauseparam = efx_ethtool_get_pauseparam, |
976 | .set_pauseparam = efx_ethtool_set_pauseparam, | 1014 | .set_pauseparam = efx_ethtool_set_pauseparam, |
977 | .get_rx_csum = efx_ethtool_get_rx_csum, | 1015 | .get_rx_csum = efx_ethtool_get_rx_csum, |
diff --git a/drivers/net/sfc/net_driver.h b/drivers/net/sfc/net_driver.h index ac622ab72e11..4b3f680ba69e 100644 --- a/drivers/net/sfc/net_driver.h +++ b/drivers/net/sfc/net_driver.h | |||
@@ -299,7 +299,6 @@ enum efx_rx_alloc_method { | |||
299 | * | 299 | * |
300 | * @efx: Associated Efx NIC | 300 | * @efx: Associated Efx NIC |
301 | * @channel: Channel instance number | 301 | * @channel: Channel instance number |
302 | * @name: Name for channel and IRQ | ||
303 | * @enabled: Channel enabled indicator | 302 | * @enabled: Channel enabled indicator |
304 | * @irq: IRQ number (MSI and MSI-X only) | 303 | * @irq: IRQ number (MSI and MSI-X only) |
305 | * @irq_moderation: IRQ moderation value (in hardware ticks) | 304 | * @irq_moderation: IRQ moderation value (in hardware ticks) |
@@ -333,7 +332,6 @@ enum efx_rx_alloc_method { | |||
333 | struct efx_channel { | 332 | struct efx_channel { |
334 | struct efx_nic *efx; | 333 | struct efx_nic *efx; |
335 | int channel; | 334 | int channel; |
336 | char name[IFNAMSIZ + 6]; | ||
337 | bool enabled; | 335 | bool enabled; |
338 | int irq; | 336 | int irq; |
339 | unsigned int irq_moderation; | 337 | unsigned int irq_moderation; |
@@ -644,6 +642,7 @@ union efx_multicast_hash { | |||
644 | * @tx_queue: TX DMA queues | 642 | * @tx_queue: TX DMA queues |
645 | * @rx_queue: RX DMA queues | 643 | * @rx_queue: RX DMA queues |
646 | * @channel: Channels | 644 | * @channel: Channels |
645 | * @channel_name: Names for channels and their IRQs | ||
647 | * @rxq_entries: Size of receive queues requested by user. | 646 | * @rxq_entries: Size of receive queues requested by user. |
648 | * @txq_entries: Size of transmit queues requested by user. | 647 | * @txq_entries: Size of transmit queues requested by user. |
649 | * @next_buffer_table: First available buffer table id | 648 | * @next_buffer_table: First available buffer table id |
@@ -730,6 +729,7 @@ struct efx_nic { | |||
730 | enum reset_type reset_pending; | 729 | enum reset_type reset_pending; |
731 | 730 | ||
732 | struct efx_channel *channel[EFX_MAX_CHANNELS]; | 731 | struct efx_channel *channel[EFX_MAX_CHANNELS]; |
732 | char channel_name[IFNAMSIZ + 6][EFX_MAX_CHANNELS]; | ||
733 | 733 | ||
734 | unsigned rxq_entries; | 734 | unsigned rxq_entries; |
735 | unsigned txq_entries; | 735 | unsigned txq_entries; |
diff --git a/drivers/net/sfc/nic.c b/drivers/net/sfc/nic.c index 0deb5c38efff..6c5c0cefa9d8 100644 --- a/drivers/net/sfc/nic.c +++ b/drivers/net/sfc/nic.c | |||
@@ -1478,7 +1478,7 @@ static irqreturn_t efx_legacy_interrupt(int irq, void *dev_id) | |||
1478 | */ | 1478 | */ |
1479 | static irqreturn_t efx_msi_interrupt(int irq, void *dev_id) | 1479 | static irqreturn_t efx_msi_interrupt(int irq, void *dev_id) |
1480 | { | 1480 | { |
1481 | struct efx_channel *channel = dev_id; | 1481 | struct efx_channel *channel = *(struct efx_channel **)dev_id; |
1482 | struct efx_nic *efx = channel->efx; | 1482 | struct efx_nic *efx = channel->efx; |
1483 | efx_oword_t *int_ker = efx->irq_status.addr; | 1483 | efx_oword_t *int_ker = efx->irq_status.addr; |
1484 | int syserr; | 1484 | int syserr; |
@@ -1553,7 +1553,8 @@ int efx_nic_init_interrupt(struct efx_nic *efx) | |||
1553 | efx_for_each_channel(channel, efx) { | 1553 | efx_for_each_channel(channel, efx) { |
1554 | rc = request_irq(channel->irq, efx_msi_interrupt, | 1554 | rc = request_irq(channel->irq, efx_msi_interrupt, |
1555 | IRQF_PROBE_SHARED, /* Not shared */ | 1555 | IRQF_PROBE_SHARED, /* Not shared */ |
1556 | channel->name, channel); | 1556 | efx->channel_name[channel->channel], |
1557 | &efx->channel[channel->channel]); | ||
1557 | if (rc) { | 1558 | if (rc) { |
1558 | netif_err(efx, drv, efx->net_dev, | 1559 | netif_err(efx, drv, efx->net_dev, |
1559 | "failed to hook IRQ %d\n", channel->irq); | 1560 | "failed to hook IRQ %d\n", channel->irq); |
@@ -1565,7 +1566,7 @@ int efx_nic_init_interrupt(struct efx_nic *efx) | |||
1565 | 1566 | ||
1566 | fail2: | 1567 | fail2: |
1567 | efx_for_each_channel(channel, efx) | 1568 | efx_for_each_channel(channel, efx) |
1568 | free_irq(channel->irq, channel); | 1569 | free_irq(channel->irq, &efx->channel[channel->channel]); |
1569 | fail1: | 1570 | fail1: |
1570 | return rc; | 1571 | return rc; |
1571 | } | 1572 | } |
@@ -1578,7 +1579,7 @@ void efx_nic_fini_interrupt(struct efx_nic *efx) | |||
1578 | /* Disable MSI/MSI-X interrupts */ | 1579 | /* Disable MSI/MSI-X interrupts */ |
1579 | efx_for_each_channel(channel, efx) { | 1580 | efx_for_each_channel(channel, efx) { |
1580 | if (channel->irq) | 1581 | if (channel->irq) |
1581 | free_irq(channel->irq, channel); | 1582 | free_irq(channel->irq, &efx->channel[channel->channel]); |
1582 | } | 1583 | } |
1583 | 1584 | ||
1584 | /* ACK legacy interrupt */ | 1585 | /* ACK legacy interrupt */ |