Reset the list of frames to send at the end of qcc_io_send() if at least
one QCS instance was moved to the qcs_failed list and is reinserted into
the send list. This is mandatory to ensure frame generation will be
performed again for the failed QCS instances.
This issue is detected as it triggers a BUG_ON() crash on the second
qcc_io_send() call, as the send list will contain the previously failed
QCS after qcc_send_frames() despite not being blocked on flow control or
buffer allocation.
This bug occurs after qcs_send() failure, which is either due to the
connection currently being subscribed for send after a transient network
error or after a frame allocation failure under memory pressure.
However, the first case cannot occur as a transient error will not leave
any QCS in failed list. Thus, this fix is only relevant for memory
allocation failure, which explains its minor severity.
This must be backported up to 3.2 after a period of observation. For
older releases, a local frame list is used instead in qcc_io_send().
LIST_APPEND(&qcc->send_list, &qcs->el_send);
}
+ /* If at least one QCS has failed, need to refresh the whole
+ * frame list. This prevents BUG_ON() crash on the above loop
+ * about QCS present in send_list not blocked on flow control
+ * or buf allocation. This only occurs after qcs_send() failure
+ * on frame allocation. Error path for send subscribing cannot
+ * reach this code, thus there is no unnecessary frames cleanup
+ * on a transient network error.
+ */
+ qcc_clear_frms(qcc);
+
if (!qfctl_rblocked(&qcc->tx.fc))
tasklet_wakeup(qcc->wait_event.tasklet);
}