diff options
Diffstat (limited to 'drivers/net/sfc/efx.c')
-rw-r--r-- | drivers/net/sfc/efx.c | 61 |
1 files changed, 34 insertions, 27 deletions
diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c index 3dd71aa310cd..4b42e61e3c7d 100644 --- a/drivers/net/sfc/efx.c +++ b/drivers/net/sfc/efx.c | |||
@@ -114,7 +114,7 @@ static struct workqueue_struct *reset_workqueue; | |||
114 | * This is only used in MSI-X interrupt mode | 114 | * This is only used in MSI-X interrupt mode |
115 | */ | 115 | */ |
116 | static unsigned int separate_tx_channels; | 116 | static unsigned int separate_tx_channels; |
117 | module_param(separate_tx_channels, uint, 0644); | 117 | module_param(separate_tx_channels, uint, 0444); |
118 | MODULE_PARM_DESC(separate_tx_channels, | 118 | MODULE_PARM_DESC(separate_tx_channels, |
119 | "Use separate channels for TX and RX"); | 119 | "Use separate channels for TX and RX"); |
120 | 120 | ||
@@ -334,6 +334,7 @@ void efx_process_channel_now(struct efx_channel *channel) | |||
334 | { | 334 | { |
335 | struct efx_nic *efx = channel->efx; | 335 | struct efx_nic *efx = channel->efx; |
336 | 336 | ||
337 | BUG_ON(channel->channel >= efx->n_channels); | ||
337 | BUG_ON(!channel->enabled); | 338 | BUG_ON(!channel->enabled); |
338 | 339 | ||
339 | /* Disable interrupts and wait for ISRs to complete */ | 340 | /* Disable interrupts and wait for ISRs to complete */ |
@@ -1098,26 +1099,32 @@ static void efx_remove_interrupts(struct efx_nic *efx) | |||
1098 | efx->legacy_irq = 0; | 1099 | efx->legacy_irq = 0; |
1099 | } | 1100 | } |
1100 | 1101 | ||
1102 | struct efx_tx_queue * | ||
1103 | efx_get_tx_queue(struct efx_nic *efx, unsigned index, unsigned type) | ||
1104 | { | ||
1105 | unsigned tx_channel_offset = | ||
1106 | separate_tx_channels ? efx->n_channels - efx->n_tx_channels : 0; | ||
1107 | EFX_BUG_ON_PARANOID(index >= efx->n_tx_channels || | ||
1108 | type >= EFX_TXQ_TYPES); | ||
1109 | return &efx->channel[tx_channel_offset + index]->tx_queue[type]; | ||
1110 | } | ||
1111 | |||
1101 | static void efx_set_channels(struct efx_nic *efx) | 1112 | static void efx_set_channels(struct efx_nic *efx) |
1102 | { | 1113 | { |
1103 | struct efx_channel *channel; | 1114 | struct efx_channel *channel; |
1104 | struct efx_tx_queue *tx_queue; | 1115 | struct efx_tx_queue *tx_queue; |
1105 | struct efx_rx_queue *rx_queue; | ||
1106 | unsigned tx_channel_offset = | 1116 | unsigned tx_channel_offset = |
1107 | separate_tx_channels ? efx->n_channels - efx->n_tx_channels : 0; | 1117 | separate_tx_channels ? efx->n_channels - efx->n_tx_channels : 0; |
1108 | 1118 | ||
1119 | /* Channel pointers were set in efx_init_struct() but we now | ||
1120 | * need to clear them for TX queues in any RX-only channels. */ | ||
1109 | efx_for_each_channel(channel, efx) { | 1121 | efx_for_each_channel(channel, efx) { |
1110 | if (channel->channel - tx_channel_offset < efx->n_tx_channels) { | 1122 | if (channel->channel - tx_channel_offset >= |
1111 | channel->tx_queue = &efx->tx_queue[ | 1123 | efx->n_tx_channels) { |
1112 | (channel->channel - tx_channel_offset) * | ||
1113 | EFX_TXQ_TYPES]; | ||
1114 | efx_for_each_channel_tx_queue(tx_queue, channel) | 1124 | efx_for_each_channel_tx_queue(tx_queue, channel) |
1115 | tx_queue->channel = channel; | 1125 | tx_queue->channel = NULL; |
1116 | } | 1126 | } |
1117 | } | 1127 | } |
1118 | |||
1119 | efx_for_each_rx_queue(rx_queue, efx) | ||
1120 | rx_queue->channel = &efx->channel[rx_queue->queue]; | ||
1121 | } | 1128 | } |
1122 | 1129 | ||
1123 | static int efx_probe_nic(struct efx_nic *efx) | 1130 | static int efx_probe_nic(struct efx_nic *efx) |
@@ -2044,7 +2051,7 @@ static int efx_init_struct(struct efx_nic *efx, struct efx_nic_type *type, | |||
2044 | struct efx_channel *channel; | 2051 | struct efx_channel *channel; |
2045 | struct efx_tx_queue *tx_queue; | 2052 | struct efx_tx_queue *tx_queue; |
2046 | struct efx_rx_queue *rx_queue; | 2053 | struct efx_rx_queue *rx_queue; |
2047 | int i; | 2054 | int i, j; |
2048 | 2055 | ||
2049 | /* Initialise common structures */ | 2056 | /* Initialise common structures */ |
2050 | memset(efx, 0, sizeof(*efx)); | 2057 | memset(efx, 0, sizeof(*efx)); |
@@ -2072,27 +2079,22 @@ static int efx_init_struct(struct efx_nic *efx, struct efx_nic_type *type, | |||
2072 | INIT_WORK(&efx->mac_work, efx_mac_work); | 2079 | INIT_WORK(&efx->mac_work, efx_mac_work); |
2073 | 2080 | ||
2074 | for (i = 0; i < EFX_MAX_CHANNELS; i++) { | 2081 | for (i = 0; i < EFX_MAX_CHANNELS; i++) { |
2075 | channel = &efx->channel[i]; | 2082 | efx->channel[i] = kzalloc(sizeof(*channel), GFP_KERNEL); |
2083 | channel = efx->channel[i]; | ||
2076 | channel->efx = efx; | 2084 | channel->efx = efx; |
2077 | channel->channel = i; | 2085 | channel->channel = i; |
2078 | channel->work_pending = false; | ||
2079 | spin_lock_init(&channel->tx_stop_lock); | 2086 | spin_lock_init(&channel->tx_stop_lock); |
2080 | atomic_set(&channel->tx_stop_count, 1); | 2087 | atomic_set(&channel->tx_stop_count, 1); |
2081 | } | 2088 | |
2082 | for (i = 0; i < EFX_MAX_TX_QUEUES; i++) { | 2089 | for (j = 0; j < EFX_TXQ_TYPES; j++) { |
2083 | tx_queue = &efx->tx_queue[i]; | 2090 | tx_queue = &channel->tx_queue[j]; |
2084 | tx_queue->efx = efx; | 2091 | tx_queue->efx = efx; |
2085 | tx_queue->queue = i; | 2092 | tx_queue->queue = i * EFX_TXQ_TYPES + j; |
2086 | tx_queue->buffer = NULL; | 2093 | tx_queue->channel = channel; |
2087 | tx_queue->channel = &efx->channel[0]; /* for safety */ | 2094 | } |
2088 | tx_queue->tso_headers_free = NULL; | 2095 | |
2089 | } | 2096 | rx_queue = &channel->rx_queue; |
2090 | for (i = 0; i < EFX_MAX_RX_QUEUES; i++) { | ||
2091 | rx_queue = &efx->rx_queue[i]; | ||
2092 | rx_queue->efx = efx; | 2097 | rx_queue->efx = efx; |
2093 | rx_queue->queue = i; | ||
2094 | rx_queue->channel = &efx->channel[0]; /* for safety */ | ||
2095 | rx_queue->buffer = NULL; | ||
2096 | setup_timer(&rx_queue->slow_fill, efx_rx_slow_fill, | 2098 | setup_timer(&rx_queue->slow_fill, efx_rx_slow_fill, |
2097 | (unsigned long)rx_queue); | 2099 | (unsigned long)rx_queue); |
2098 | } | 2100 | } |
@@ -2120,6 +2122,11 @@ static int efx_init_struct(struct efx_nic *efx, struct efx_nic_type *type, | |||
2120 | 2122 | ||
2121 | static void efx_fini_struct(struct efx_nic *efx) | 2123 | static void efx_fini_struct(struct efx_nic *efx) |
2122 | { | 2124 | { |
2125 | int i; | ||
2126 | |||
2127 | for (i = 0; i < EFX_MAX_CHANNELS; i++) | ||
2128 | kfree(efx->channel[i]); | ||
2129 | |||
2123 | if (efx->workqueue) { | 2130 | if (efx->workqueue) { |
2124 | destroy_workqueue(efx->workqueue); | 2131 | destroy_workqueue(efx->workqueue); |
2125 | efx->workqueue = NULL; | 2132 | efx->workqueue = NULL; |