/* Don't process AdminQ when it's not up */ if (!pdsc_adminq_inc_if_up(pdsc)) {
dev_err(pdsc->dev, "%s: called while adminq is unavailable\n",
__func__); return;
}
/* Check for NotifyQ event */
nq_work = pdsc_process_notifyq(&pdsc->notifyqcq);
/* Check for empty queue, which can happen if the interrupt was * for a NotifyQ event and there are no new AdminQ completions.
*/ if (q->tail_idx == q->head_idx) goto credits;
/* Find the first completion to clean, * run the callback in the related q_info, * and continue while we still match done color
*/
spin_lock_irqsave(&pdsc->adminq_lock, irqflags);
comp = cq->info[cq->tail_idx].comp; while (pdsc_color_match(comp->color, cq->done_color)) {
q_info = &q->info[q->tail_idx];
q->tail_idx = (q->tail_idx + 1) & (q->num_descs - 1);
if (!completion_done(&q_info->completion)) {
memcpy(q_info->dest, comp, sizeof(*comp));
complete(&q_info->completion);
}
credits: /* Return the interrupt credits, one for each completion */
pds_core_intr_credits(&pdsc->intr_ctrl[qcq->intx],
nq_work + aq_work,
PDS_CORE_INTR_CRED_REARM);
refcount_dec(&pdsc->adminq_refcnt);
}
/* Don't process AdminQ when it's not up */ if (!pdsc_adminq_inc_if_up(pdsc)) {
dev_err(pdsc->dev, "%s: called while adminq is unavailable\n",
__func__); return IRQ_HANDLED;
}
index = __pdsc_adminq_post(pdsc, &pdsc->adminqcq, cmd, comp); if (index < 0) {
err = index; goto err_out;
}
wc = &pdsc->adminqcq.q.info[index].completion;
time_start = jiffies;
time_limit = time_start + HZ * pdsc->devcmd_timeout; do { /* Timeslice the actual wait to catch IO errors etc early */
poll_jiffies = usecs_to_jiffies(poll_interval);
remaining = wait_for_completion_timeout(wc, poll_jiffies); if (remaining) break;
if (!pdsc_is_fw_running(pdsc)) { if (pdsc->info_regs) {
u8 fw_status =
ioread8(&pdsc->info_regs->fw_status);
dev_dbg(pdsc->dev, "%s: post wait failed - fw not running %#02x:\n",
__func__, fw_status);
} else {
dev_dbg(pdsc->dev, "%s: post wait failed - BARs not setup\n",
__func__);
}
err = -ENXIO; break;
}
/* When fast_poll is not requested, prevent aggressive polling * on failures due to timeouts by doing exponential back off.
*/ if (!fast_poll && poll_interval < PDSC_ADMINQ_MAX_POLL_INTERVAL)
poll_interval <<= 1;
} while (time_before(jiffies, time_limit));
time_done = jiffies;
dev_dbg(pdsc->dev, "%s: elapsed %d msecs\n",
__func__, jiffies_to_msecs(time_done - time_start));
/* Check the results and clear an un-completed timeout */ if (time_after_eq(time_done, time_limit) && !completion_done(wc)) {
err = -ETIMEDOUT;
complete(wc);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.