drivers/infiniband/hw/ionic/ionic_admin.c

Source file repositories/reference/linux-study-clean/drivers/infiniband/hw/ionic/ionic_admin.c

File Facts

System
Linux kernel
Corpus path
drivers/infiniband/hw/ionic/ionic_admin.c
Extension
.c
Size
29390 bytes
Lines
1228
Domain
Driver Families
Bucket
drivers/infiniband
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

list_for_each_entry_safe(wr, wr_next, &aq->wr_prod, aq_ent) {
			INIT_LIST_HEAD(&wr->aq_ent);
			aq->q_wr[wr->status].wr = NULL;
			wr->status = atomic_read(&aq->admin_state);
			complete_all(&wr->work);
		}
		INIT_LIST_HEAD(&aq->wr_prod);

		list_for_each_entry_safe(wr, wr_next, &aq->wr_post, aq_ent) {
			INIT_LIST_HEAD(&wr->aq_ent);
			wr->status = atomic_read(&aq->admin_state);
			complete_all(&wr->work);
		}
		INIT_LIST_HEAD(&aq->wr_post);

		return;
	}

	old_prod = cq->q.prod;

	while (ionic_admin_next_cqe(dev, cq, &cqe)) {
		qtf = ionic_v1_cqe_qtf(cqe);
		qid = ionic_v1_cqe_qtf_qid(qtf);
		type = ionic_v1_cqe_qtf_type(qtf);

		if (unlikely(type != IONIC_V1_CQE_TYPE_ADMIN)) {
			ibdev_warn_ratelimited(&dev->ibdev,
					       "bad cqe type %u\n", type);
			goto cq_next;
		}

		if (unlikely(qid != aq->aqid)) {
			ibdev_warn_ratelimited(&dev->ibdev,
					       "bad cqe qid %u\n", qid);
			goto cq_next;
		}

		if (unlikely(be16_to_cpu(cqe->admin.cmd_idx) != aq->q.cons)) {
			ibdev_warn_ratelimited(&dev->ibdev,
					       "bad idx %u cons %u qid %u\n",
					       be16_to_cpu(cqe->admin.cmd_idx),
					       aq->q.cons, qid);
			goto cq_next;
		}

		if (unlikely(ionic_queue_empty(&aq->q))) {
			ibdev_warn_ratelimited(&dev->ibdev,
					       "bad cqe for empty adminq\n");
			goto cq_next;
		}

		wr = aq->q_wr[aq->q.cons].wr;
		if (wr) {
			aq->q_wr[aq->q.cons].wr = NULL;
			list_del_init(&wr->aq_ent);

			wr->cqe = *cqe;
			wr->status = atomic_read(&aq->admin_state);
			complete_all(&wr->work);
		}

		ionic_queue_consume_entries(&aq->q,
					    aq->q_wr[aq->q.cons].wqe_strides);

cq_next:
		ionic_queue_produce(&cq->q);
		cq->color = ionic_color_wrap(cq->q.prod, cq->color);
	}

	if (old_prod != cq->q.prod) {
		ionic_admin_reset_wdog(aq);
		cq->q.cons = cq->q.prod;
		ionic_dbell_ring(dev->lif_cfg.dbpage, dev->lif_cfg.cq_qtype,
				 ionic_queue_dbell_val(&cq->q));
		queue_work(ionic_evt_workq, &aq->work);
	} else if (!aq->armed) {
		aq->armed = true;
		cq->arm_any_prod = ionic_queue_next(&cq->q, cq->arm_any_prod);
		ionic_dbell_ring(dev->lif_cfg.dbpage, dev->lif_cfg.cq_qtype,
				 cq->q.dbell | IONIC_CQ_RING_ARM |
				 cq->arm_any_prod);
		queue_work(ionic_evt_workq, &aq->work);
	}

	if (atomic_read(&aq->admin_state) != IONIC_ADMIN_ACTIVE)
		return;

	old_prod = aq->q.prod;

	if (ionic_queue_empty(&aq->q) && !list_empty(&aq->wr_post))

Annotation

Implementation Notes