aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/sfc/efx.c4
-rw-r--r--drivers/net/sfc/net_driver.h2
-rw-r--r--drivers/net/sfc/nic.c22
-rw-r--r--drivers/net/sfc/nic.h1
-rw-r--r--drivers/net/sfc/selftest.c23
5 files changed, 23 insertions, 29 deletions
diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c
index 0dc800b5a4ea..a3c2aab53de8 100644
--- a/drivers/net/sfc/efx.c
+++ b/drivers/net/sfc/efx.c
@@ -328,7 +328,8 @@ static int efx_poll(struct napi_struct *napi, int budget)
328 * processing to finish, then directly poll (and ack ) the eventq. 328 * processing to finish, then directly poll (and ack ) the eventq.
329 * Finally reenable NAPI and interrupts. 329 * Finally reenable NAPI and interrupts.
330 * 330 *
331 * Since we are touching interrupts the caller should hold the suspend lock 331 * This is for use only during a loopback self-test. It must not
332 * deliver any packets up the stack as this can result in deadlock.
332 */ 333 */
333void efx_process_channel_now(struct efx_channel *channel) 334void efx_process_channel_now(struct efx_channel *channel)
334{ 335{
@@ -336,6 +337,7 @@ void efx_process_channel_now(struct efx_channel *channel)
336 337
337 BUG_ON(channel->channel >= efx->n_channels); 338 BUG_ON(channel->channel >= efx->n_channels);
338 BUG_ON(!channel->enabled); 339 BUG_ON(!channel->enabled);
340 BUG_ON(!efx->loopback_selftest);
339 341
340 /* Disable interrupts and wait for ISRs to complete */ 342 /* Disable interrupts and wait for ISRs to complete */
341 efx_nic_disable_interrupts(efx); 343 efx_nic_disable_interrupts(efx);
diff --git a/drivers/net/sfc/net_driver.h b/drivers/net/sfc/net_driver.h
index 9ffa9a6b55a0..191a311da2dc 100644
--- a/drivers/net/sfc/net_driver.h
+++ b/drivers/net/sfc/net_driver.h
@@ -330,7 +330,6 @@ enum efx_rx_alloc_method {
330 * @eventq_mask: Event queue pointer mask 330 * @eventq_mask: Event queue pointer mask
331 * @eventq_read_ptr: Event queue read pointer 331 * @eventq_read_ptr: Event queue read pointer
332 * @last_eventq_read_ptr: Last event queue read pointer value. 332 * @last_eventq_read_ptr: Last event queue read pointer value.
333 * @magic_count: Event queue test event count
334 * @irq_count: Number of IRQs since last adaptive moderation decision 333 * @irq_count: Number of IRQs since last adaptive moderation decision
335 * @irq_mod_score: IRQ moderation score 334 * @irq_mod_score: IRQ moderation score
336 * @rx_alloc_level: Watermark based heuristic counter for pushing descriptors 335 * @rx_alloc_level: Watermark based heuristic counter for pushing descriptors
@@ -360,7 +359,6 @@ struct efx_channel {
360 unsigned int eventq_mask; 359 unsigned int eventq_mask;
361 unsigned int eventq_read_ptr; 360 unsigned int eventq_read_ptr;
362 unsigned int last_eventq_read_ptr; 361 unsigned int last_eventq_read_ptr;
363 unsigned int magic_count;
364 362
365 unsigned int irq_count; 363 unsigned int irq_count;
366 unsigned int irq_mod_score; 364 unsigned int irq_mod_score;
diff --git a/drivers/net/sfc/nic.c b/drivers/net/sfc/nic.c
index e8396614daf3..10f1cb79c147 100644
--- a/drivers/net/sfc/nic.c
+++ b/drivers/net/sfc/nic.c
@@ -84,7 +84,8 @@ static inline void efx_write_buf_tbl(struct efx_nic *efx, efx_qword_t *value,
84static inline efx_qword_t *efx_event(struct efx_channel *channel, 84static inline efx_qword_t *efx_event(struct efx_channel *channel,
85 unsigned int index) 85 unsigned int index)
86{ 86{
87 return ((efx_qword_t *) (channel->eventq.addr)) + index; 87 return ((efx_qword_t *) (channel->eventq.addr)) +
88 (index & channel->eventq_mask);
88} 89}
89 90
90/* See if an event is present 91/* See if an event is present
@@ -673,7 +674,8 @@ void efx_nic_eventq_read_ack(struct efx_channel *channel)
673 efx_dword_t reg; 674 efx_dword_t reg;
674 struct efx_nic *efx = channel->efx; 675 struct efx_nic *efx = channel->efx;
675 676
676 EFX_POPULATE_DWORD_1(reg, FRF_AZ_EVQ_RPTR, channel->eventq_read_ptr); 677 EFX_POPULATE_DWORD_1(reg, FRF_AZ_EVQ_RPTR,
678 channel->eventq_read_ptr & channel->eventq_mask);
677 efx_writed_table(efx, &reg, efx->type->evq_rptr_tbl_base, 679 efx_writed_table(efx, &reg, efx->type->evq_rptr_tbl_base,
678 channel->channel); 680 channel->channel);
679} 681}
@@ -908,7 +910,7 @@ efx_handle_generated_event(struct efx_channel *channel, efx_qword_t *event)
908 910
909 code = EFX_QWORD_FIELD(*event, FSF_AZ_DRV_GEN_EV_MAGIC); 911 code = EFX_QWORD_FIELD(*event, FSF_AZ_DRV_GEN_EV_MAGIC);
910 if (code == EFX_CHANNEL_MAGIC_TEST(channel)) 912 if (code == EFX_CHANNEL_MAGIC_TEST(channel))
911 ++channel->magic_count; 913 ; /* ignore */
912 else if (code == EFX_CHANNEL_MAGIC_FILL(channel)) 914 else if (code == EFX_CHANNEL_MAGIC_FILL(channel))
913 /* The queue must be empty, so we won't receive any rx 915 /* The queue must be empty, so we won't receive any rx
914 * events, so efx_process_channel() won't refill the 916 * events, so efx_process_channel() won't refill the
@@ -1015,8 +1017,7 @@ int efx_nic_process_eventq(struct efx_channel *channel, int budget)
1015 /* Clear this event by marking it all ones */ 1017 /* Clear this event by marking it all ones */
1016 EFX_SET_QWORD(*p_event); 1018 EFX_SET_QWORD(*p_event);
1017 1019
1018 /* Increment read pointer */ 1020 ++read_ptr;
1019 read_ptr = (read_ptr + 1) & channel->eventq_mask;
1020 1021
1021 ev_code = EFX_QWORD_FIELD(event, FSF_AZ_EV_CODE); 1022 ev_code = EFX_QWORD_FIELD(event, FSF_AZ_EV_CODE);
1022 1023
@@ -1060,6 +1061,13 @@ out:
1060 return spent; 1061 return spent;
1061} 1062}
1062 1063
1064/* Check whether an event is present in the eventq at the current
1065 * read pointer. Only useful for self-test.
1066 */
1067bool efx_nic_event_present(struct efx_channel *channel)
1068{
1069 return efx_event_present(efx_event(channel, channel->eventq_read_ptr));
1070}
1063 1071
1064/* Allocate buffer table entries for event queue */ 1072/* Allocate buffer table entries for event queue */
1065int efx_nic_probe_eventq(struct efx_channel *channel) 1073int efx_nic_probe_eventq(struct efx_channel *channel)
@@ -1165,7 +1173,7 @@ static void efx_poll_flush_events(struct efx_nic *efx)
1165 struct efx_tx_queue *tx_queue; 1173 struct efx_tx_queue *tx_queue;
1166 struct efx_rx_queue *rx_queue; 1174 struct efx_rx_queue *rx_queue;
1167 unsigned int read_ptr = channel->eventq_read_ptr; 1175 unsigned int read_ptr = channel->eventq_read_ptr;
1168 unsigned int end_ptr = (read_ptr - 1) & channel->eventq_mask; 1176 unsigned int end_ptr = read_ptr + channel->eventq_mask - 1;
1169 1177
1170 do { 1178 do {
1171 efx_qword_t *event = efx_event(channel, read_ptr); 1179 efx_qword_t *event = efx_event(channel, read_ptr);
@@ -1205,7 +1213,7 @@ static void efx_poll_flush_events(struct efx_nic *efx)
1205 * it's ok to throw away every non-flush event */ 1213 * it's ok to throw away every non-flush event */
1206 EFX_SET_QWORD(*event); 1214 EFX_SET_QWORD(*event);
1207 1215
1208 read_ptr = (read_ptr + 1) & channel->eventq_mask; 1216 ++read_ptr;
1209 } while (read_ptr != end_ptr); 1217 } while (read_ptr != end_ptr);
1210 1218
1211 channel->eventq_read_ptr = read_ptr; 1219 channel->eventq_read_ptr = read_ptr;
diff --git a/drivers/net/sfc/nic.h b/drivers/net/sfc/nic.h
index d9de1b647d41..a42db6e35be3 100644
--- a/drivers/net/sfc/nic.h
+++ b/drivers/net/sfc/nic.h
@@ -184,6 +184,7 @@ extern void efx_nic_fini_eventq(struct efx_channel *channel);
184extern void efx_nic_remove_eventq(struct efx_channel *channel); 184extern void efx_nic_remove_eventq(struct efx_channel *channel);
185extern int efx_nic_process_eventq(struct efx_channel *channel, int rx_quota); 185extern int efx_nic_process_eventq(struct efx_channel *channel, int rx_quota);
186extern void efx_nic_eventq_read_ack(struct efx_channel *channel); 186extern void efx_nic_eventq_read_ack(struct efx_channel *channel);
187extern bool efx_nic_event_present(struct efx_channel *channel);
187 188
188/* MAC/PHY */ 189/* MAC/PHY */
189extern void falcon_drain_tx_fifo(struct efx_nic *efx); 190extern void falcon_drain_tx_fifo(struct efx_nic *efx);
diff --git a/drivers/net/sfc/selftest.c b/drivers/net/sfc/selftest.c
index 845808408924..50ad3bcaf68a 100644
--- a/drivers/net/sfc/selftest.c
+++ b/drivers/net/sfc/selftest.c
@@ -131,8 +131,6 @@ static int efx_test_chip(struct efx_nic *efx, struct efx_self_tests *tests)
131static int efx_test_interrupts(struct efx_nic *efx, 131static int efx_test_interrupts(struct efx_nic *efx,
132 struct efx_self_tests *tests) 132 struct efx_self_tests *tests)
133{ 133{
134 struct efx_channel *channel;
135
136 netif_dbg(efx, drv, efx->net_dev, "testing interrupts\n"); 134 netif_dbg(efx, drv, efx->net_dev, "testing interrupts\n");
137 tests->interrupt = -1; 135 tests->interrupt = -1;
138 136
@@ -140,15 +138,6 @@ static int efx_test_interrupts(struct efx_nic *efx,
140 efx->last_irq_cpu = -1; 138 efx->last_irq_cpu = -1;
141 smp_wmb(); 139 smp_wmb();
142 140
143 /* ACK each interrupting event queue. Receiving an interrupt due to
144 * traffic before a test event is raised is considered a pass */
145 efx_for_each_channel(channel, efx) {
146 if (channel->work_pending)
147 efx_process_channel_now(channel);
148 if (efx->last_irq_cpu >= 0)
149 goto success;
150 }
151
152 efx_nic_generate_interrupt(efx); 141 efx_nic_generate_interrupt(efx);
153 142
154 /* Wait for arrival of test interrupt. */ 143 /* Wait for arrival of test interrupt. */
@@ -173,13 +162,13 @@ static int efx_test_eventq_irq(struct efx_channel *channel,
173 struct efx_self_tests *tests) 162 struct efx_self_tests *tests)
174{ 163{
175 struct efx_nic *efx = channel->efx; 164 struct efx_nic *efx = channel->efx;
176 unsigned int magic_count, count; 165 unsigned int read_ptr, count;
177 166
178 tests->eventq_dma[channel->channel] = -1; 167 tests->eventq_dma[channel->channel] = -1;
179 tests->eventq_int[channel->channel] = -1; 168 tests->eventq_int[channel->channel] = -1;
180 tests->eventq_poll[channel->channel] = -1; 169 tests->eventq_poll[channel->channel] = -1;
181 170
182 magic_count = channel->magic_count; 171 read_ptr = channel->eventq_read_ptr;
183 channel->efx->last_irq_cpu = -1; 172 channel->efx->last_irq_cpu = -1;
184 smp_wmb(); 173 smp_wmb();
185 174
@@ -190,10 +179,7 @@ static int efx_test_eventq_irq(struct efx_channel *channel,
190 do { 179 do {
191 schedule_timeout_uninterruptible(HZ / 100); 180 schedule_timeout_uninterruptible(HZ / 100);
192 181
193 if (channel->work_pending) 182 if (ACCESS_ONCE(channel->eventq_read_ptr) != read_ptr)
194 efx_process_channel_now(channel);
195
196 if (channel->magic_count != magic_count)
197 goto eventq_ok; 183 goto eventq_ok;
198 } while (++count < 2); 184 } while (++count < 2);
199 185
@@ -211,8 +197,7 @@ static int efx_test_eventq_irq(struct efx_channel *channel,
211 } 197 }
212 198
213 /* Check to see if event was received even if interrupt wasn't */ 199 /* Check to see if event was received even if interrupt wasn't */
214 efx_process_channel_now(channel); 200 if (efx_nic_event_present(channel)) {
215 if (channel->magic_count != magic_count) {
216 netif_err(efx, drv, efx->net_dev, 201 netif_err(efx, drv, efx->net_dev,
217 "channel %d event was generated, but " 202 "channel %d event was generated, but "
218 "failed to trigger an interrupt\n", channel->channel); 203 "failed to trigger an interrupt\n", channel->channel);