diff options
author | Brett Creeley <brett.creeley@intel.com> | 2019-02-08 15:50:34 -0500 |
---|---|---|
committer | Jeff Kirsher <jeffrey.t.kirsher@intel.com> | 2019-02-25 11:56:01 -0500 |
commit | 0e04e8e14b558c84a7c7a64d3e94655f5071eef5 (patch) | |
tree | 579e884e2305a913fe1722f021302da0657ad3dd /drivers/net/ethernet/intel/ice/ice_main.c | |
parent | f9264dd687f8d3f9104c9900f8f3e5e419f27c55 (diff) |
ice: fix issue where host reboots on unload when iommu=on
Currently if the kernel has the intel_iommu=on parameter set, on some
platforms removing the driver causes a system reboot. In initialization
we associate the control queue interrupts with the pf->hw_oicr_idx and
enable the interrupts by setting the CAUSE_ENA bit. The problem comes
on teardown because we are not clearing the CAUSE_ENA bit for the
control queues, but the vector at pf->hw_oicr_idx (miscellaneous
interrupt vector) gets disabled.
Fix this by clearing the CAUSE_ENA bit in the appropriate control queue
registers on when freeing the miscellaneous interrupt vector. Also,
move the call to ice_free_irq_msix_misc() to after ice_deinit_sw() in
ice_remove() because ice_deinit_sw() makes an AQ call, but
ice_free_irq_msix_misc() disables the miscellaneous vector and it's
associated interrupts.
Also, create two small helper functions to enable and disable the
control queue interrupts respectively.
Signed-off-by: Brett Creeley <brett.creeley@intel.com>
Signed-off-by: Anirudh Venkataramanan <anirudh.venkataramanan@intel.com>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Diffstat (limited to 'drivers/net/ethernet/intel/ice/ice_main.c')
-rw-r--r-- | drivers/net/ethernet/intel/ice/ice_main.c | 71 |
1 files changed, 54 insertions, 17 deletions
diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c index aff348e42562..fb04a5ebdc0b 100644 --- a/drivers/net/ethernet/intel/ice/ice_main.c +++ b/drivers/net/ethernet/intel/ice/ice_main.c | |||
@@ -1356,14 +1356,39 @@ static irqreturn_t ice_misc_intr(int __always_unused irq, void *data) | |||
1356 | } | 1356 | } |
1357 | 1357 | ||
1358 | /** | 1358 | /** |
1359 | * ice_dis_ctrlq_interrupts - disable control queue interrupts | ||
1360 | * @hw: pointer to HW structure | ||
1361 | */ | ||
1362 | static void ice_dis_ctrlq_interrupts(struct ice_hw *hw) | ||
1363 | { | ||
1364 | /* disable Admin queue Interrupt causes */ | ||
1365 | wr32(hw, PFINT_FW_CTL, | ||
1366 | rd32(hw, PFINT_FW_CTL) & ~PFINT_FW_CTL_CAUSE_ENA_M); | ||
1367 | |||
1368 | /* disable Mailbox queue Interrupt causes */ | ||
1369 | wr32(hw, PFINT_MBX_CTL, | ||
1370 | rd32(hw, PFINT_MBX_CTL) & ~PFINT_MBX_CTL_CAUSE_ENA_M); | ||
1371 | |||
1372 | /* disable Control queue Interrupt causes */ | ||
1373 | wr32(hw, PFINT_OICR_CTL, | ||
1374 | rd32(hw, PFINT_OICR_CTL) & ~PFINT_OICR_CTL_CAUSE_ENA_M); | ||
1375 | |||
1376 | ice_flush(hw); | ||
1377 | } | ||
1378 | |||
1379 | /** | ||
1359 | * ice_free_irq_msix_misc - Unroll misc vector setup | 1380 | * ice_free_irq_msix_misc - Unroll misc vector setup |
1360 | * @pf: board private structure | 1381 | * @pf: board private structure |
1361 | */ | 1382 | */ |
1362 | static void ice_free_irq_msix_misc(struct ice_pf *pf) | 1383 | static void ice_free_irq_msix_misc(struct ice_pf *pf) |
1363 | { | 1384 | { |
1385 | struct ice_hw *hw = &pf->hw; | ||
1386 | |||
1387 | ice_dis_ctrlq_interrupts(hw); | ||
1388 | |||
1364 | /* disable OICR interrupt */ | 1389 | /* disable OICR interrupt */ |
1365 | wr32(&pf->hw, PFINT_OICR_ENA, 0); | 1390 | wr32(hw, PFINT_OICR_ENA, 0); |
1366 | ice_flush(&pf->hw); | 1391 | ice_flush(hw); |
1367 | 1392 | ||
1368 | if (test_bit(ICE_FLAG_MSIX_ENA, pf->flags) && pf->msix_entries) { | 1393 | if (test_bit(ICE_FLAG_MSIX_ENA, pf->flags) && pf->msix_entries) { |
1369 | synchronize_irq(pf->msix_entries[pf->sw_oicr_idx].vector); | 1394 | synchronize_irq(pf->msix_entries[pf->sw_oicr_idx].vector); |
@@ -1378,6 +1403,32 @@ static void ice_free_irq_msix_misc(struct ice_pf *pf) | |||
1378 | } | 1403 | } |
1379 | 1404 | ||
1380 | /** | 1405 | /** |
1406 | * ice_ena_ctrlq_interrupts - enable control queue interrupts | ||
1407 | * @hw: pointer to HW structure | ||
1408 | * @v_idx: HW vector index to associate the control queue interrupts with | ||
1409 | */ | ||
1410 | static void ice_ena_ctrlq_interrupts(struct ice_hw *hw, u16 v_idx) | ||
1411 | { | ||
1412 | u32 val; | ||
1413 | |||
1414 | val = ((v_idx & PFINT_OICR_CTL_MSIX_INDX_M) | | ||
1415 | PFINT_OICR_CTL_CAUSE_ENA_M); | ||
1416 | wr32(hw, PFINT_OICR_CTL, val); | ||
1417 | |||
1418 | /* enable Admin queue Interrupt causes */ | ||
1419 | val = ((v_idx & PFINT_FW_CTL_MSIX_INDX_M) | | ||
1420 | PFINT_FW_CTL_CAUSE_ENA_M); | ||
1421 | wr32(hw, PFINT_FW_CTL, val); | ||
1422 | |||
1423 | /* enable Mailbox queue Interrupt causes */ | ||
1424 | val = ((v_idx & PFINT_MBX_CTL_MSIX_INDX_M) | | ||
1425 | PFINT_MBX_CTL_CAUSE_ENA_M); | ||
1426 | wr32(hw, PFINT_MBX_CTL, val); | ||
1427 | |||
1428 | ice_flush(hw); | ||
1429 | } | ||
1430 | |||
1431 | /** | ||
1381 | * ice_req_irq_msix_misc - Setup the misc vector to handle non queue events | 1432 | * ice_req_irq_msix_misc - Setup the misc vector to handle non queue events |
1382 | * @pf: board private structure | 1433 | * @pf: board private structure |
1383 | * | 1434 | * |
@@ -1389,7 +1440,6 @@ static int ice_req_irq_msix_misc(struct ice_pf *pf) | |||
1389 | { | 1440 | { |
1390 | struct ice_hw *hw = &pf->hw; | 1441 | struct ice_hw *hw = &pf->hw; |
1391 | int oicr_idx, err = 0; | 1442 | int oicr_idx, err = 0; |
1392 | u32 val; | ||
1393 | 1443 | ||
1394 | if (!pf->int_name[0]) | 1444 | if (!pf->int_name[0]) |
1395 | snprintf(pf->int_name, sizeof(pf->int_name) - 1, "%s-%s:misc", | 1445 | snprintf(pf->int_name, sizeof(pf->int_name) - 1, "%s-%s:misc", |
@@ -1438,20 +1488,7 @@ static int ice_req_irq_msix_misc(struct ice_pf *pf) | |||
1438 | skip_req_irq: | 1488 | skip_req_irq: |
1439 | ice_ena_misc_vector(pf); | 1489 | ice_ena_misc_vector(pf); |
1440 | 1490 | ||
1441 | val = ((pf->hw_oicr_idx & PFINT_OICR_CTL_MSIX_INDX_M) | | 1491 | ice_ena_ctrlq_interrupts(hw, pf->hw_oicr_idx); |
1442 | PFINT_OICR_CTL_CAUSE_ENA_M); | ||
1443 | wr32(hw, PFINT_OICR_CTL, val); | ||
1444 | |||
1445 | /* This enables Admin queue Interrupt causes */ | ||
1446 | val = ((pf->hw_oicr_idx & PFINT_FW_CTL_MSIX_INDX_M) | | ||
1447 | PFINT_FW_CTL_CAUSE_ENA_M); | ||
1448 | wr32(hw, PFINT_FW_CTL, val); | ||
1449 | |||
1450 | /* This enables Mailbox queue Interrupt causes */ | ||
1451 | val = ((pf->hw_oicr_idx & PFINT_MBX_CTL_MSIX_INDX_M) | | ||
1452 | PFINT_MBX_CTL_CAUSE_ENA_M); | ||
1453 | wr32(hw, PFINT_MBX_CTL, val); | ||
1454 | |||
1455 | wr32(hw, GLINT_ITR(ICE_RX_ITR, pf->hw_oicr_idx), | 1492 | wr32(hw, GLINT_ITR(ICE_RX_ITR, pf->hw_oicr_idx), |
1456 | ITR_REG_ALIGN(ICE_ITR_8K) >> ICE_ITR_GRAN_S); | 1493 | ITR_REG_ALIGN(ICE_ITR_8K) >> ICE_ITR_GRAN_S); |
1457 | 1494 | ||