diff options
Diffstat (limited to 'drivers/net/sfc/nic.c')
-rw-r--r-- | drivers/net/sfc/nic.c | 63 |
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 | ||
1026 | void efx_nic_init_eventq(struct efx_channel *channel) | 1029 | void 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, ®, 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, ®, 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 | ||
1052 | void efx_nic_fini_eventq(struct efx_channel *channel) | 1063 | void 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, ®, 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, ®, 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) { |