drivers/scsi/fnic/fnic_scsi.c

Source file repositories/reference/linux-study-clean/drivers/scsi/fnic/fnic_scsi.c

File Facts

System
Linux kernel
Corpus path
drivers/scsi/fnic/fnic_scsi.c
Extension
.c
Size
91903 bytes
Lines
3036
Domain
Driver Families
Bucket
drivers/scsi
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

struct fnic_rport_abort_io_iter_data {
	struct fnic *fnic;
	u32 port_id;
	int term_cnt;
};

static bool fnic_rport_abort_io_iter(struct scsi_cmnd *sc, void *data)
{
	struct request *const rq = scsi_cmd_to_rq(sc);
	struct fnic_rport_abort_io_iter_data *iter_data = data;
	struct fnic *fnic = iter_data->fnic;
	int abt_tag = 0;
	struct fnic_io_req *io_req;
	struct reset_stats *reset_stats = &fnic->fnic_stats.reset_stats;
	struct terminate_stats *term_stats = &fnic->fnic_stats.term_stats;
	struct scsi_lun fc_lun;
	enum fnic_ioreq_state old_ioreq_state;
	uint16_t hwq = 0;
	unsigned long flags;

	abt_tag = blk_mq_unique_tag(rq);
	hwq = blk_mq_unique_tag_to_hwq(abt_tag);

	if (!sc) {
		FNIC_SCSI_DBG(KERN_DEBUG, fnic->host, fnic->fnic_num,
					  "sc is NULL abt_tag: 0x%x hwq: %d\n", abt_tag, hwq);
		return true;
	}

	spin_lock_irqsave(&fnic->wq_copy_lock[hwq], flags);
	io_req = fnic_priv(sc)->io_req;
	if (!io_req || io_req->port_id != iter_data->port_id) {
		spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
		return true;
	}

	if ((fnic_priv(sc)->flags & FNIC_DEVICE_RESET) &&
	    !(fnic_priv(sc)->flags & FNIC_DEV_RST_ISSUED)) {
		FNIC_SCSI_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
			"hwq: %d abt_tag: 0x%x flags: 0x%x Device reset is not pending\n",
			hwq, abt_tag, fnic_priv(sc)->flags);
		spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
		return true;
	}

	/*
	 * Found IO that is still pending with firmware and
	 * belongs to rport that went away
	 */
	if (fnic_priv(sc)->state == FNIC_IOREQ_ABTS_PENDING) {
		spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
		return true;
	}

	if (io_req->abts_done) {
		shost_printk(KERN_ERR, fnic->host,
			"fnic_rport_exch_reset: io_req->abts_done is set state is %s\n",
			fnic_ioreq_state_to_str(fnic_priv(sc)->state));
	}

	if (!(fnic_priv(sc)->flags & FNIC_IO_ISSUED)) {
		shost_printk(KERN_ERR, fnic->host,
			"rport_exch_reset IO not yet issued %p abt_tag 0x%x",
			sc, abt_tag);
		shost_printk(KERN_ERR, fnic->host,
			"flags %x state %d\n", fnic_priv(sc)->flags,
			fnic_priv(sc)->state);
	}
	old_ioreq_state = fnic_priv(sc)->state;
	fnic_priv(sc)->state = FNIC_IOREQ_ABTS_PENDING;
	fnic_priv(sc)->abts_status = FCPIO_INVALID_CODE;

	if (fnic_priv(sc)->flags & FNIC_DEVICE_RESET) {
		atomic64_inc(&reset_stats->device_reset_terminates);
		abt_tag |= FNIC_TAG_DEV_RST;
		FNIC_SCSI_DBG(KERN_DEBUG, fnic->host, fnic->fnic_num,
					  "dev reset sc 0x%p\n", sc);
	}
	FNIC_SCSI_DBG(KERN_DEBUG, fnic->host, fnic->fnic_num,
		      "fnic_rport_exch_reset: dev rst sc 0x%p\n", sc);
	WARN_ON_ONCE(io_req->abts_done);
	FNIC_SCSI_DBG(KERN_DEBUG, fnic->host, fnic->fnic_num,
		      "fnic_rport_reset_exch: Issuing abts\n");

	spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);

	/* Queue the abort command to firmware */
	int_to_scsilun(sc->device->lun, &fc_lun);

	if (fnic_queue_abort_io_req(fnic, abt_tag,

Annotation

Implementation Notes