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>
This commit is contained in:
commit
f92fcb5c00
@ -290,6 +290,7 @@ enum ice_pf_state {
|
||||
ICE_LINK_DEFAULT_OVERRIDE_PENDING,
|
||||
ICE_PHY_INIT_COMPLETE,
|
||||
ICE_FD_VF_FLUSH_CTX, /* set at FD Rx IRQ or timeout */
|
||||
ICE_AUX_ERR_PENDING,
|
||||
ICE_STATE_NBITS /* must be last */
|
||||
};
|
||||
|
||||
@ -559,6 +560,7 @@ struct ice_pf {
|
||||
wait_queue_head_t reset_wait_queue;
|
||||
|
||||
u32 hw_csum_rx_error;
|
||||
u32 oicr_err_reg;
|
||||
u16 oicr_idx; /* Other interrupt cause MSIX vector index */
|
||||
u16 num_avail_sw_msix; /* remaining MSIX SW vectors left unclaimed */
|
||||
u16 max_pf_txqs; /* Total Tx queues PF wide */
|
||||
|
@ -34,6 +34,9 @@ void ice_send_event_to_aux(struct ice_pf *pf, struct iidc_event *event)
|
||||
{
|
||||
struct iidc_auxiliary_drv *iadrv;
|
||||
|
||||
if (WARN_ON_ONCE(!in_task()))
|
||||
return;
|
||||
|
||||
if (!pf->adev)
|
||||
return;
|
||||
|
||||
|
@ -2255,6 +2255,19 @@ static void ice_service_task(struct work_struct *work)
|
||||
return;
|
||||
}
|
||||
|
||||
if (test_and_clear_bit(ICE_AUX_ERR_PENDING, pf->state)) {
|
||||
struct iidc_event *event;
|
||||
|
||||
event = kzalloc(sizeof(*event), GFP_KERNEL);
|
||||
if (event) {
|
||||
set_bit(IIDC_EVENT_CRIT_ERR, event->type);
|
||||
/* report the entire OICR value to AUX driver */
|
||||
swap(event->reg, pf->oicr_err_reg);
|
||||
ice_send_event_to_aux(pf, event);
|
||||
kfree(event);
|
||||
}
|
||||
}
|
||||
|
||||
if (test_bit(ICE_FLAG_PLUG_AUX_DEV, pf->flags)) {
|
||||
/* Plug aux device per request */
|
||||
ice_plug_aux_dev(pf);
|
||||
@ -3041,17 +3054,9 @@ static irqreturn_t ice_misc_intr(int __always_unused irq, void *data)
|
||||
|
||||
#define ICE_AUX_CRIT_ERR (PFINT_OICR_PE_CRITERR_M | PFINT_OICR_HMC_ERR_M | PFINT_OICR_PE_PUSH_M)
|
||||
if (oicr & ICE_AUX_CRIT_ERR) {
|
||||
struct iidc_event *event;
|
||||
|
||||
pf->oicr_err_reg |= oicr;
|
||||
set_bit(ICE_AUX_ERR_PENDING, pf->state);
|
||||
ena_mask &= ~ICE_AUX_CRIT_ERR;
|
||||
event = kzalloc(sizeof(*event), GFP_ATOMIC);
|
||||
if (event) {
|
||||
set_bit(IIDC_EVENT_CRIT_ERR, event->type);
|
||||
/* report the entire OICR value to AUX driver */
|
||||
event->reg = oicr;
|
||||
ice_send_event_to_aux(pf, event);
|
||||
kfree(event);
|
||||
}
|
||||
}
|
||||
|
||||
/* Report any remaining unexpected interrupts */
|
||||
|
Loading…
Reference in New Issue
Block a user