diff options
author | Ben Hutchings <bhutchings@solarflare.com> | 2011-02-07 18:04:38 -0500 |
---|---|---|
committer | Ben Hutchings <bhutchings@solarflare.com> | 2011-02-15 14:45:34 -0500 |
commit | 525da9072c28df815bff64bf00f3b11ab88face8 (patch) | |
tree | 0649a1fff4d110796dd7f22168c9413cd8eb5caa /drivers/net/sfc | |
parent | 60031fcc17057e21566ed34ba23e93fffda1aa27 (diff) |
sfc: Distinguish queue lookup from test for queue existence
efx_channel_get_{rx,tx}_queue() currently return NULL if the channel
isn't used for traffic in that direction. In most cases this is a
bug, but some callers rely on it as an existence test.
Add existence test functions efx_channel_has_{rx_queue,tx_queues}()
and use them as appropriate.
Change efx_channel_get_{rx,tx}_queue() to assert that the requested
queue exists.
Remove now-redundant initialisation from efx_set_channels().
Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
Diffstat (limited to 'drivers/net/sfc')
-rw-r--r-- | drivers/net/sfc/efx.c | 17 | ||||
-rw-r--r-- | drivers/net/sfc/ethtool.c | 6 | ||||
-rw-r--r-- | drivers/net/sfc/net_driver.h | 39 |
3 files changed, 33 insertions, 29 deletions
diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c index c559bc372fc1..6189d3066018 100644 --- a/drivers/net/sfc/efx.c +++ b/drivers/net/sfc/efx.c | |||
@@ -1271,21 +1271,8 @@ static void efx_remove_interrupts(struct efx_nic *efx) | |||
1271 | 1271 | ||
1272 | static void efx_set_channels(struct efx_nic *efx) | 1272 | static void efx_set_channels(struct efx_nic *efx) |
1273 | { | 1273 | { |
1274 | struct efx_channel *channel; | ||
1275 | struct efx_tx_queue *tx_queue; | ||
1276 | |||
1277 | efx->tx_channel_offset = | 1274 | efx->tx_channel_offset = |
1278 | separate_tx_channels ? efx->n_channels - efx->n_tx_channels : 0; | 1275 | separate_tx_channels ? efx->n_channels - efx->n_tx_channels : 0; |
1279 | |||
1280 | /* Channel pointers were set in efx_init_struct() but we now | ||
1281 | * need to clear them for TX queues in any RX-only channels. */ | ||
1282 | efx_for_each_channel(channel, efx) { | ||
1283 | if (channel->channel - efx->tx_channel_offset >= | ||
1284 | efx->n_tx_channels) { | ||
1285 | efx_for_each_channel_tx_queue(tx_queue, channel) | ||
1286 | tx_queue->channel = NULL; | ||
1287 | } | ||
1288 | } | ||
1289 | } | 1276 | } |
1290 | 1277 | ||
1291 | static int efx_probe_nic(struct efx_nic *efx) | 1278 | static int efx_probe_nic(struct efx_nic *efx) |
@@ -1531,9 +1518,9 @@ void efx_init_irq_moderation(struct efx_nic *efx, int tx_usecs, int rx_usecs, | |||
1531 | efx->irq_rx_adaptive = rx_adaptive; | 1518 | efx->irq_rx_adaptive = rx_adaptive; |
1532 | efx->irq_rx_moderation = rx_ticks; | 1519 | efx->irq_rx_moderation = rx_ticks; |
1533 | efx_for_each_channel(channel, efx) { | 1520 | efx_for_each_channel(channel, efx) { |
1534 | if (efx_channel_get_rx_queue(channel)) | 1521 | if (efx_channel_has_rx_queue(channel)) |
1535 | channel->irq_moderation = rx_ticks; | 1522 | channel->irq_moderation = rx_ticks; |
1536 | else if (efx_channel_get_tx_queue(channel, 0)) | 1523 | else if (efx_channel_has_tx_queues(channel)) |
1537 | channel->irq_moderation = tx_ticks; | 1524 | channel->irq_moderation = tx_ticks; |
1538 | } | 1525 | } |
1539 | } | 1526 | } |
diff --git a/drivers/net/sfc/ethtool.c b/drivers/net/sfc/ethtool.c index 713969accdbd..272cfe724e1b 100644 --- a/drivers/net/sfc/ethtool.c +++ b/drivers/net/sfc/ethtool.c | |||
@@ -631,7 +631,7 @@ static int efx_ethtool_get_coalesce(struct net_device *net_dev, | |||
631 | /* Find lowest IRQ moderation across all used TX queues */ | 631 | /* Find lowest IRQ moderation across all used TX queues */ |
632 | coalesce->tx_coalesce_usecs_irq = ~((u32) 0); | 632 | coalesce->tx_coalesce_usecs_irq = ~((u32) 0); |
633 | efx_for_each_channel(channel, efx) { | 633 | efx_for_each_channel(channel, efx) { |
634 | if (!efx_channel_get_tx_queue(channel, 0)) | 634 | if (!efx_channel_has_tx_queues(channel)) |
635 | continue; | 635 | continue; |
636 | if (channel->irq_moderation < coalesce->tx_coalesce_usecs_irq) { | 636 | if (channel->irq_moderation < coalesce->tx_coalesce_usecs_irq) { |
637 | if (channel->channel < efx->n_rx_channels) | 637 | if (channel->channel < efx->n_rx_channels) |
@@ -676,8 +676,8 @@ static int efx_ethtool_set_coalesce(struct net_device *net_dev, | |||
676 | 676 | ||
677 | /* If the channel is shared only allow RX parameters to be set */ | 677 | /* If the channel is shared only allow RX parameters to be set */ |
678 | efx_for_each_channel(channel, efx) { | 678 | efx_for_each_channel(channel, efx) { |
679 | if (efx_channel_get_rx_queue(channel) && | 679 | if (efx_channel_has_rx_queue(channel) && |
680 | efx_channel_get_tx_queue(channel, 0) && | 680 | efx_channel_has_tx_queues(channel) && |
681 | tx_usecs) { | 681 | tx_usecs) { |
682 | netif_err(efx, drv, efx->net_dev, "Channel is shared. " | 682 | netif_err(efx, drv, efx->net_dev, "Channel is shared. " |
683 | "Only RX coalescing may be set\n"); | 683 | "Only RX coalescing may be set\n"); |
diff --git a/drivers/net/sfc/net_driver.h b/drivers/net/sfc/net_driver.h index c65270241d2d..77b7ce451519 100644 --- a/drivers/net/sfc/net_driver.h +++ b/drivers/net/sfc/net_driver.h | |||
@@ -938,19 +938,28 @@ efx_get_tx_queue(struct efx_nic *efx, unsigned index, unsigned type) | |||
938 | return &efx->channel[efx->tx_channel_offset + index]->tx_queue[type]; | 938 | return &efx->channel[efx->tx_channel_offset + index]->tx_queue[type]; |
939 | } | 939 | } |
940 | 940 | ||
941 | static inline bool efx_channel_has_tx_queues(struct efx_channel *channel) | ||
942 | { | ||
943 | return channel->channel - channel->efx->tx_channel_offset < | ||
944 | channel->efx->n_tx_channels; | ||
945 | } | ||
946 | |||
941 | static inline struct efx_tx_queue * | 947 | static inline struct efx_tx_queue * |
942 | efx_channel_get_tx_queue(struct efx_channel *channel, unsigned type) | 948 | efx_channel_get_tx_queue(struct efx_channel *channel, unsigned type) |
943 | { | 949 | { |
944 | struct efx_tx_queue *tx_queue = channel->tx_queue; | 950 | EFX_BUG_ON_PARANOID(!efx_channel_has_tx_queues(channel) || |
945 | EFX_BUG_ON_PARANOID(type >= EFX_TXQ_TYPES); | 951 | type >= EFX_TXQ_TYPES); |
946 | return tx_queue->channel ? tx_queue + type : NULL; | 952 | return &channel->tx_queue[type]; |
947 | } | 953 | } |
948 | 954 | ||
949 | /* Iterate over all TX queues belonging to a channel */ | 955 | /* Iterate over all TX queues belonging to a channel */ |
950 | #define efx_for_each_channel_tx_queue(_tx_queue, _channel) \ | 956 | #define efx_for_each_channel_tx_queue(_tx_queue, _channel) \ |
951 | for (_tx_queue = efx_channel_get_tx_queue(channel, 0); \ | 957 | if (!efx_channel_has_tx_queues(_channel)) \ |
952 | _tx_queue && _tx_queue < (_channel)->tx_queue + EFX_TXQ_TYPES; \ | 958 | ; \ |
953 | _tx_queue++) | 959 | else \ |
960 | for (_tx_queue = (_channel)->tx_queue; \ | ||
961 | _tx_queue < (_channel)->tx_queue + EFX_TXQ_TYPES; \ | ||
962 | _tx_queue++) | ||
954 | 963 | ||
955 | static inline struct efx_rx_queue * | 964 | static inline struct efx_rx_queue * |
956 | efx_get_rx_queue(struct efx_nic *efx, unsigned index) | 965 | efx_get_rx_queue(struct efx_nic *efx, unsigned index) |
@@ -959,18 +968,26 @@ efx_get_rx_queue(struct efx_nic *efx, unsigned index) | |||
959 | return &efx->channel[index]->rx_queue; | 968 | return &efx->channel[index]->rx_queue; |
960 | } | 969 | } |
961 | 970 | ||
971 | static inline bool efx_channel_has_rx_queue(struct efx_channel *channel) | ||
972 | { | ||
973 | return channel->channel < channel->efx->n_rx_channels; | ||
974 | } | ||
975 | |||
962 | static inline struct efx_rx_queue * | 976 | static inline struct efx_rx_queue * |
963 | efx_channel_get_rx_queue(struct efx_channel *channel) | 977 | efx_channel_get_rx_queue(struct efx_channel *channel) |
964 | { | 978 | { |
965 | return channel->channel < channel->efx->n_rx_channels ? | 979 | EFX_BUG_ON_PARANOID(!efx_channel_has_rx_queue(channel)); |
966 | &channel->rx_queue : NULL; | 980 | return &channel->rx_queue; |
967 | } | 981 | } |
968 | 982 | ||
969 | /* Iterate over all RX queues belonging to a channel */ | 983 | /* Iterate over all RX queues belonging to a channel */ |
970 | #define efx_for_each_channel_rx_queue(_rx_queue, _channel) \ | 984 | #define efx_for_each_channel_rx_queue(_rx_queue, _channel) \ |
971 | for (_rx_queue = efx_channel_get_rx_queue(channel); \ | 985 | if (!efx_channel_has_rx_queue(_channel)) \ |
972 | _rx_queue; \ | 986 | ; \ |
973 | _rx_queue = NULL) | 987 | else \ |
988 | for (_rx_queue = &(_channel)->rx_queue; \ | ||
989 | _rx_queue; \ | ||
990 | _rx_queue = NULL) | ||
974 | 991 | ||
975 | static inline struct efx_channel * | 992 | static inline struct efx_channel * |
976 | efx_rx_queue_channel(struct efx_rx_queue *rx_queue) | 993 | efx_rx_queue_channel(struct efx_rx_queue *rx_queue) |