aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/sfc/nic.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/sfc/nic.c')
-rw-r--r--drivers/net/sfc/nic.c63
1 files changed, 49 insertions, 14 deletions
diff --git a/drivers/net/sfc/nic.c b/drivers/net/sfc/nic.c
index 55dbd7994b64..5ac4b1af8391 100644
--- a/drivers/net/sfc/nic.c
+++ b/drivers/net/sfc/nic.c
@@ -997,6 +997,9 @@ int efx_nic_process_eventq(struct efx_channel *channel, int rx_quota)
997 case FSE_AZ_EV_CODE_DRIVER_EV: 997 case FSE_AZ_EV_CODE_DRIVER_EV:
998 efx_handle_driver_event(channel, &event); 998 efx_handle_driver_event(channel, &event);
999 break; 999 break;
1000 case FSE_CZ_EV_CODE_MCDI_EV:
1001 efx_mcdi_process_event(channel, &event);
1002 break;
1000 default: 1003 default:
1001 EFX_ERR(channel->efx, "channel %d unknown event type %d" 1004 EFX_ERR(channel->efx, "channel %d unknown event type %d"
1002 " (data " EFX_QWORD_FMT ")\n", channel->channel, 1005 " (data " EFX_QWORD_FMT ")\n", channel->channel,
@@ -1025,13 +1028,21 @@ int efx_nic_probe_eventq(struct efx_channel *channel)
1025 1028
1026void efx_nic_init_eventq(struct efx_channel *channel) 1029void efx_nic_init_eventq(struct efx_channel *channel)
1027{ 1030{
1028 efx_oword_t evq_ptr; 1031 efx_oword_t reg;
1029 struct efx_nic *efx = channel->efx; 1032 struct efx_nic *efx = channel->efx;
1030 1033
1031 EFX_LOG(efx, "channel %d event queue in special buffers %d-%d\n", 1034 EFX_LOG(efx, "channel %d event queue in special buffers %d-%d\n",
1032 channel->channel, channel->eventq.index, 1035 channel->channel, channel->eventq.index,
1033 channel->eventq.index + channel->eventq.entries - 1); 1036 channel->eventq.index + channel->eventq.entries - 1);
1034 1037
1038 if (efx_nic_rev(efx) >= EFX_REV_SIENA_A0) {
1039 EFX_POPULATE_OWORD_3(reg,
1040 FRF_CZ_TIMER_Q_EN, 1,
1041 FRF_CZ_HOST_NOTIFY_MODE, 0,
1042 FRF_CZ_TIMER_MODE, FFE_CZ_TIMER_MODE_DIS);
1043 efx_writeo_table(efx, &reg, FR_BZ_TIMER_TBL, channel->channel);
1044 }
1045
1035 /* Pin event queue buffer */ 1046 /* Pin event queue buffer */
1036 efx_init_special_buffer(efx, &channel->eventq); 1047 efx_init_special_buffer(efx, &channel->eventq);
1037 1048
@@ -1039,11 +1050,11 @@ void efx_nic_init_eventq(struct efx_channel *channel)
1039 memset(channel->eventq.addr, 0xff, channel->eventq.len); 1050 memset(channel->eventq.addr, 0xff, channel->eventq.len);
1040 1051
1041 /* Push event queue to card */ 1052 /* Push event queue to card */
1042 EFX_POPULATE_OWORD_3(evq_ptr, 1053 EFX_POPULATE_OWORD_3(reg,
1043 FRF_AZ_EVQ_EN, 1, 1054 FRF_AZ_EVQ_EN, 1,
1044 FRF_AZ_EVQ_SIZE, __ffs(channel->eventq.entries), 1055 FRF_AZ_EVQ_SIZE, __ffs(channel->eventq.entries),
1045 FRF_AZ_EVQ_BUF_BASE_ID, channel->eventq.index); 1056 FRF_AZ_EVQ_BUF_BASE_ID, channel->eventq.index);
1046 efx_writeo_table(efx, &evq_ptr, efx->type->evq_ptr_tbl_base, 1057 efx_writeo_table(efx, &reg, efx->type->evq_ptr_tbl_base,
1047 channel->channel); 1058 channel->channel);
1048 1059
1049 efx->type->push_irq_moderation(channel); 1060 efx->type->push_irq_moderation(channel);
@@ -1051,13 +1062,15 @@ void efx_nic_init_eventq(struct efx_channel *channel)
1051 1062
1052void efx_nic_fini_eventq(struct efx_channel *channel) 1063void efx_nic_fini_eventq(struct efx_channel *channel)
1053{ 1064{
1054 efx_oword_t eventq_ptr; 1065 efx_oword_t reg;
1055 struct efx_nic *efx = channel->efx; 1066 struct efx_nic *efx = channel->efx;
1056 1067
1057 /* Remove event queue from card */ 1068 /* Remove event queue from card */
1058 EFX_ZERO_OWORD(eventq_ptr); 1069 EFX_ZERO_OWORD(reg);
1059 efx_writeo_table(efx, &eventq_ptr, efx->type->evq_ptr_tbl_base, 1070 efx_writeo_table(efx, &reg, efx->type->evq_ptr_tbl_base,
1060 channel->channel); 1071 channel->channel);
1072 if (efx_nic_rev(efx) >= EFX_REV_SIENA_A0)
1073 efx_writeo_table(efx, &reg, FR_BZ_TIMER_TBL, channel->channel);
1061 1074
1062 /* Unpin event queue */ 1075 /* Unpin event queue */
1063 efx_fini_special_buffer(efx, &channel->eventq); 1076 efx_fini_special_buffer(efx, &channel->eventq);
@@ -1220,8 +1233,15 @@ static inline void efx_nic_interrupts(struct efx_nic *efx,
1220 bool enabled, bool force) 1233 bool enabled, bool force)
1221{ 1234{
1222 efx_oword_t int_en_reg_ker; 1235 efx_oword_t int_en_reg_ker;
1236 unsigned int level = 0;
1237
1238 if (EFX_WORKAROUND_17213(efx) && !EFX_INT_MODE_USE_MSI(efx))
1239 /* Set the level always even if we're generating a test
1240 * interrupt, because our legacy interrupt handler is safe */
1241 level = 0x1f;
1223 1242
1224 EFX_POPULATE_OWORD_2(int_en_reg_ker, 1243 EFX_POPULATE_OWORD_3(int_en_reg_ker,
1244 FRF_AZ_KER_INT_LEVE_SEL, level,
1225 FRF_AZ_KER_INT_KER, force, 1245 FRF_AZ_KER_INT_KER, force,
1226 FRF_AZ_DRV_INT_EN_KER, enabled); 1246 FRF_AZ_DRV_INT_EN_KER, enabled);
1227 efx_writeo(efx, &int_en_reg_ker, FR_AZ_INT_EN_KER); 1247 efx_writeo(efx, &int_en_reg_ker, FR_AZ_INT_EN_KER);
@@ -1334,15 +1354,30 @@ static irqreturn_t efx_legacy_interrupt(int irq, void *dev_id)
1334 if (unlikely(syserr)) 1354 if (unlikely(syserr))
1335 return efx_nic_fatal_interrupt(efx); 1355 return efx_nic_fatal_interrupt(efx);
1336 1356
1337 /* Schedule processing of any interrupting queues */ 1357 if (queues != 0) {
1338 efx_for_each_channel(channel, efx) { 1358 if (EFX_WORKAROUND_15783(efx))
1339 if ((queues & 1) || 1359 efx->irq_zero_count = 0;
1340 efx_event_present( 1360
1341 efx_event(channel, channel->eventq_read_ptr))) { 1361 /* Schedule processing of any interrupting queues */
1362 efx_for_each_channel(channel, efx) {
1363 if (queues & 1)
1364 efx_schedule_channel(channel);
1365 queues >>= 1;
1366 }
1367 result = IRQ_HANDLED;
1368
1369 } else if (EFX_WORKAROUND_15783(efx) &&
1370 efx->irq_zero_count++ == 0) {
1371 efx_qword_t *event;
1372
1373 /* Ensure we rearm all event queues */
1374 efx_for_each_channel(channel, efx) {
1375 event = efx_event(channel, channel->eventq_read_ptr);
1376 if (efx_event_present(event))
1342 efx_schedule_channel(channel); 1377 efx_schedule_channel(channel);
1343 result = IRQ_HANDLED;
1344 } 1378 }
1345 queues >>= 1; 1379
1380 result = IRQ_HANDLED;
1346 } 1381 }
1347 1382
1348 if (result == IRQ_HANDLED) { 1383 if (result == IRQ_HANDLED) {