Skip to content

Commit f92fcb5

Browse files
committed
Merge branch 'ice-avoid-sleeping-scheduling-in-atomic-contexts'
Alexander Lobakin says: ==================== ice: avoid sleeping/scheduling in atomic contexts The `ice_misc_intr() + ice_send_event_to_aux()` infamous pair failed once again. Fix yet another (hopefully last one) 'scheduling while atomic' splat and finally plug the hole to gracefully return prematurely when invoked in wrong context instead of panicking. ==================== Link: https://lore.kernel.org/r/20220323124353.2762181-1-alexandr.lobakin@intel.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2 parents 6a7d8cf + 5a31569 commit f92fcb5

3 files changed

Lines changed: 20 additions & 10 deletions

File tree

drivers/net/ethernet/intel/ice/ice.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,7 @@ enum ice_pf_state {
290290
ICE_LINK_DEFAULT_OVERRIDE_PENDING,
291291
ICE_PHY_INIT_COMPLETE,
292292
ICE_FD_VF_FLUSH_CTX, /* set at FD Rx IRQ or timeout */
293+
ICE_AUX_ERR_PENDING,
293294
ICE_STATE_NBITS /* must be last */
294295
};
295296

@@ -559,6 +560,7 @@ struct ice_pf {
559560
wait_queue_head_t reset_wait_queue;
560561

561562
u32 hw_csum_rx_error;
563+
u32 oicr_err_reg;
562564
u16 oicr_idx; /* Other interrupt cause MSIX vector index */
563565
u16 num_avail_sw_msix; /* remaining MSIX SW vectors left unclaimed */
564566
u16 max_pf_txqs; /* Total Tx queues PF wide */

drivers/net/ethernet/intel/ice/ice_idc.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ void ice_send_event_to_aux(struct ice_pf *pf, struct iidc_event *event)
3434
{
3535
struct iidc_auxiliary_drv *iadrv;
3636

37+
if (WARN_ON_ONCE(!in_task()))
38+
return;
39+
3740
if (!pf->adev)
3841
return;
3942

drivers/net/ethernet/intel/ice/ice_main.c

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2255,6 +2255,19 @@ static void ice_service_task(struct work_struct *work)
22552255
return;
22562256
}
22572257

2258+
if (test_and_clear_bit(ICE_AUX_ERR_PENDING, pf->state)) {
2259+
struct iidc_event *event;
2260+
2261+
event = kzalloc(sizeof(*event), GFP_KERNEL);
2262+
if (event) {
2263+
set_bit(IIDC_EVENT_CRIT_ERR, event->type);
2264+
/* report the entire OICR value to AUX driver */
2265+
swap(event->reg, pf->oicr_err_reg);
2266+
ice_send_event_to_aux(pf, event);
2267+
kfree(event);
2268+
}
2269+
}
2270+
22582271
if (test_bit(ICE_FLAG_PLUG_AUX_DEV, pf->flags)) {
22592272
/* Plug aux device per request */
22602273
ice_plug_aux_dev(pf);
@@ -3041,17 +3054,9 @@ static irqreturn_t ice_misc_intr(int __always_unused irq, void *data)
30413054

30423055
#define ICE_AUX_CRIT_ERR (PFINT_OICR_PE_CRITERR_M | PFINT_OICR_HMC_ERR_M | PFINT_OICR_PE_PUSH_M)
30433056
if (oicr & ICE_AUX_CRIT_ERR) {
3044-
struct iidc_event *event;
3045-
3057+
pf->oicr_err_reg |= oicr;
3058+
set_bit(ICE_AUX_ERR_PENDING, pf->state);
30463059
ena_mask &= ~ICE_AUX_CRIT_ERR;
3047-
event = kzalloc(sizeof(*event), GFP_ATOMIC);
3048-
if (event) {
3049-
set_bit(IIDC_EVENT_CRIT_ERR, event->type);
3050-
/* report the entire OICR value to AUX driver */
3051-
event->reg = oicr;
3052-
ice_send_event_to_aux(pf, event);
3053-
kfree(event);
3054-
}
30553060
}
30563061

30573062
/* Report any remaining unexpected interrupts */

0 commit comments

Comments
 (0)