drivers/scsi/qedi/qedi_main.c

Source file repositories/reference/linux-study-clean/drivers/scsi/qedi/qedi_main.c

File Facts

System
Linux kernel
Corpus path
drivers/scsi/qedi/qedi_main.c
Extension
.c
Size
74183 bytes
Lines
2956
Domain
Driver Families
Bucket
drivers/scsi
Inferred role
Driver Families: operation-table or driver-model contract
Status
pattern 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

static struct pci_driver qedi_pci_driver;
static DEFINE_PER_CPU(struct qedi_percpu_s, qedi_percpu);
static LIST_HEAD(qedi_udev_list);
/* Static function declaration */
static int qedi_alloc_global_queues(struct qedi_ctx *qedi);
static void qedi_free_global_queues(struct qedi_ctx *qedi);
static struct qedi_cmd *qedi_get_cmd_from_tid(struct qedi_ctx *qedi, u32 tid);
static void qedi_reset_uio_rings(struct qedi_uio_dev *udev);
static void qedi_ll2_free_skbs(struct qedi_ctx *qedi);
static struct nvm_iscsi_block *qedi_get_nvram_block(struct qedi_ctx *qedi);
static void qedi_recovery_handler(struct work_struct *work);
static void qedi_schedule_hw_err_handler(void *dev,
					 enum qed_hw_err_type err_type);
static int qedi_suspend(struct pci_dev *pdev, pm_message_t state);

static int qedi_iscsi_event_cb(void *context, u8 fw_event_code, void *fw_handle)
{
	struct qedi_ctx *qedi;
	struct qedi_endpoint *qedi_ep;
	struct iscsi_eqe_data *data;
	int rval = 0;

	if (!context || !fw_handle) {
		QEDI_ERR(NULL, "Recv event with ctx NULL\n");
		return -EINVAL;
	}

	qedi = (struct qedi_ctx *)context;
	QEDI_INFO(&qedi->dbg_ctx, QEDI_LOG_INFO,
		  "Recv Event %d fw_handle %p\n", fw_event_code, fw_handle);

	data = (struct iscsi_eqe_data *)fw_handle;
	QEDI_INFO(&qedi->dbg_ctx, QEDI_LOG_INFO,
		  "icid=0x%x conn_id=0x%x err-code=0x%x error-pdu-opcode-reserved=0x%x\n",
		   data->icid, data->conn_id, data->error_code,
		   data->error_pdu_opcode_reserved);

	qedi_ep = qedi->ep_tbl[data->icid];

	if (!qedi_ep) {
		QEDI_WARN(&qedi->dbg_ctx,
			  "Cannot process event, ep already disconnected, cid=0x%x\n",
			   data->icid);
		WARN_ON(1);
		return -ENODEV;
	}

	switch (fw_event_code) {
	case ISCSI_EVENT_TYPE_ASYN_CONNECT_COMPLETE:
		if (qedi_ep->state == EP_STATE_OFLDCONN_START)
			qedi_ep->state = EP_STATE_OFLDCONN_COMPL;

		wake_up_interruptible(&qedi_ep->tcp_ofld_wait);
		break;
	case ISCSI_EVENT_TYPE_ASYN_TERMINATE_DONE:
		qedi_ep->state = EP_STATE_DISCONN_COMPL;
		wake_up_interruptible(&qedi_ep->tcp_ofld_wait);
		break;
	case ISCSI_EVENT_TYPE_ISCSI_CONN_ERROR:
		qedi_process_iscsi_error(qedi_ep, data);
		break;
	case ISCSI_EVENT_TYPE_ASYN_ABORT_RCVD:
	case ISCSI_EVENT_TYPE_ASYN_SYN_RCVD:
	case ISCSI_EVENT_TYPE_ASYN_MAX_RT_TIME:
	case ISCSI_EVENT_TYPE_ASYN_MAX_RT_CNT:
	case ISCSI_EVENT_TYPE_ASYN_MAX_KA_PROBES_CNT:
	case ISCSI_EVENT_TYPE_ASYN_FIN_WAIT2:
	case ISCSI_EVENT_TYPE_TCP_CONN_ERROR:
		qedi_process_tcp_error(qedi_ep, data);
		break;
	default:
		QEDI_ERR(&qedi->dbg_ctx, "Recv Unknown Event %u\n",
			 fw_event_code);
	}

	return rval;
}

static int qedi_uio_open(struct uio_info *uinfo, struct inode *inode)
{
	struct qedi_uio_dev *udev = uinfo->priv;
	struct qedi_ctx *qedi = udev->qedi;

	if (!capable(CAP_NET_ADMIN))
		return -EPERM;

	if (udev->uio_dev != -1)
		return -EBUSY;

	rtnl_lock();

Annotation

Implementation Notes