+static void
+ionic_link_status_check(struct ionic_lif *lif)
+{
+ struct ionic_adapter *adapter = lif->adapter;
+ bool link_up;
+
+ lif->state &= ~IONIC_LIF_F_LINK_CHECK_NEEDED;
+
+ if (!lif->info)
+ return;
+
+ link_up = (lif->info->status.link_status == IONIC_PORT_OPER_STATUS_UP);
+
+ if ((link_up && adapter->link_up) ||
+ (!link_up && !adapter->link_up))
+ return;
+
+ if (link_up) {
+ IONIC_PRINT(DEBUG, "Link up - %d Gbps",
+ lif->info->status.link_speed);
+ adapter->link_speed = lif->info->status.link_speed;
+ } else {
+ IONIC_PRINT(DEBUG, "Link down");
+ }
+
+ adapter->link_up = link_up;
+}
+
+static bool
+ionic_notifyq_cb(struct ionic_cq *cq, uint32_t cq_desc_index, void *cb_arg)
+{
+ union ionic_notifyq_comp *cq_desc_base = cq->base;
+ union ionic_notifyq_comp *cq_desc = &cq_desc_base[cq_desc_index];
+ struct ionic_lif *lif = cb_arg;
+
+ IONIC_PRINT(DEBUG, "Notifyq callback eid = %jd ecode = %d",
+ cq_desc->event.eid, cq_desc->event.ecode);
+
+ /* Have we run out of new completions to process? */
+ if (!(cq_desc->event.eid > lif->last_eid))
+ return false;
+
+ lif->last_eid = cq_desc->event.eid;
+
+ switch (cq_desc->event.ecode) {
+ case IONIC_EVENT_LINK_CHANGE:
+ IONIC_PRINT(DEBUG,
+ "Notifyq IONIC_EVENT_LINK_CHANGE eid=%jd link_status=%d link_speed=%d",
+ cq_desc->event.eid,
+ cq_desc->link_change.link_status,
+ cq_desc->link_change.link_speed);
+
+ lif->state |= IONIC_LIF_F_LINK_CHECK_NEEDED;
+
+ break;
+ default:
+ IONIC_PRINT(WARNING, "Notifyq bad event ecode=%d eid=%jd",
+ cq_desc->event.ecode, cq_desc->event.eid);
+ break;
+ }
+
+ return true;
+}
+
+int
+ionic_notifyq_handler(struct ionic_lif *lif, int budget)
+{
+ struct ionic_dev *idev = &lif->adapter->idev;
+ struct ionic_qcq *qcq = lif->notifyqcq;
+ uint32_t work_done;
+
+ if (!(qcq->flags & IONIC_QCQ_F_INITED)) {
+ IONIC_PRINT(DEBUG, "Notifyq not yet initialized");
+ return -1;
+ }
+
+ ionic_intr_mask(idev->intr_ctrl, qcq->intr.index,
+ IONIC_INTR_MASK_SET);
+
+ work_done = ionic_qcq_service(qcq, budget, ionic_notifyq_cb, lif);
+
+ if (lif->state & IONIC_LIF_F_LINK_CHECK_NEEDED)
+ ionic_link_status_check(lif);
+
+ ionic_intr_credits(idev->intr_ctrl, qcq->intr.index,
+ work_done, IONIC_INTR_CRED_RESET_COALESCE);
+
+ ionic_intr_mask(idev->intr_ctrl, qcq->intr.index,
+ IONIC_INTR_MASK_CLEAR);
+
+ return 0;
+}
+