drivers/infiniband/hw/bnxt_re/qplib_rcfw.c

Source file repositories/reference/linux-study-clean/drivers/infiniband/hw/bnxt_re/qplib_rcfw.c

File Facts

System
Linux kernel
Corpus path
drivers/infiniband/hw/bnxt_re/qplib_rcfw.c
Extension
.c
Size
35129 bytes
Lines
1202
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

if (!qp) {
			spin_unlock(&rcfw->tbl_lock);
			break;
		}
		bnxt_qplib_mark_qp_error(qp);
		rc = rcfw->creq.aeq_handler(rcfw, qp_event, qp);
		spin_unlock(&rcfw->tbl_lock);
		dev_dbg(&pdev->dev, "Received QP error notification\n");
		dev_dbg(&pdev->dev,
			"qpid 0x%x, req_err=0x%x, resp_err=0x%x\n",
			qp_id, err_event->req_err_state_reason,
			err_event->res_err_state_reason);
		break;
	default:
		/*
		 * Command Response
		 * cmdq->lock needs to be acquired to synchronie
		 * the command send and completion reaping. This function
		 * is always called with creq->lock held. Using
		 * the nested variant of spin_lock.
		 *
		 */

		spin_lock_nested(&hwq->lock, SINGLE_DEPTH_NESTING);
		cookie = le16_to_cpu(qp_event->cookie);
		blocked = cookie & RCFW_CMD_IS_BLOCKING;
		cookie &= RCFW_MAX_COOKIE_VALUE;
		crsqe = &rcfw->crsqe_tbl[cookie];

		if (WARN_ONCE(test_bit(FIRMWARE_STALL_DETECTED,
				       &rcfw->cmdq.flags),
		    "QPLIB: Unreponsive rcfw channel detected.!!")) {
			dev_info(&pdev->dev,
				 "rcfw timedout: cookie = %#x, free_slots = %d",
				 cookie, crsqe->free_slots);
			spin_unlock(&hwq->lock);
			return rc;
		}

		if (crsqe->is_internal_cmd && !qp_event->status)
			atomic_dec(&rcfw->timeout_send);

		if (crsqe->is_waiter_alive) {
			if (crsqe->resp) {
				memcpy(crsqe->resp, qp_event, sizeof(*qp_event));
				/* Insert write memory barrier to ensure that
				 * response data is copied before clearing the
				 * flags
				 */
				smp_wmb();
			}
			if (!blocked)
				wait_cmds++;
		}

		req_size = crsqe->req_size;
		is_waiter_alive = crsqe->is_waiter_alive;

		crsqe->req_size = 0;
		if (!is_waiter_alive)
			crsqe->resp = NULL;

		crsqe->is_in_used = false;

		hwq->cons += req_size;

		/* This is a case to handle below scenario -
		 * Create AH is completed successfully by firmware,
		 * but completion took more time and driver already lost
		 * the context of create_ah from caller.
		 * We have already return failure for create_ah verbs,
		 * so let's destroy the same address vector since it is
		 * no more used in stack. We don't care about completion
		 * in __send_message_no_waiter.
		 * If destroy_ah is failued by firmware, there will be AH
		 * resource leak and relatively not critical +  unlikely
		 * scenario. Current design is not to handle such case.
		 */
		if (!is_waiter_alive && !qp_event->status &&
		    qp_event->event == CREQ_QP_EVENT_EVENT_CREATE_AH)
			__destroy_timedout_ah(rcfw,
					      (struct creq_create_ah_resp *)
					      qp_event);
		spin_unlock(&hwq->lock);
	}
	*num_wait += wait_cmds;
	return rc;
}

/* SP - CREQ Completion handlers */

Annotation

Implementation Notes