drivers/scsi/lpfc/lpfc_vmid.c

Source file repositories/reference/linux-study-clean/drivers/scsi/lpfc/lpfc_vmid.c

File Facts

System
Linux kernel
Corpus path
drivers/scsi/lpfc/lpfc_vmid.c
Extension
.c
Size
10040 bytes
Lines
326
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

if (vmp && vmp->flag & LPFC_VMID_REGISTERED) {
			lpfc_vmid_update_entry(vport, iodir, vmp, tag);
			write_unlock(&vport->vmid_lock);
			return 0;
		} else if (vmp && vmp->flag & LPFC_VMID_REQ_REGISTER) {
			write_unlock(&vport->vmid_lock);
			return -EBUSY;
		}

		/* else search and allocate a free slot in the hash table */
		if (vport->cur_vmid_cnt < vport->max_vmid) {
			for (i = 0; i < vport->max_vmid; i++) {
				vmp = vport->vmid + i;
				if (vmp->flag == LPFC_VMID_SLOT_FREE)
					break;
			}
			if (i == vport->max_vmid)
				vmp = NULL;
		} else {
			vmp = NULL;
		}

		if (!vmp) {
			write_unlock(&vport->vmid_lock);
			return -ENOMEM;
		}

		/* Add the vmid and register */
		lpfc_put_vmid_in_hashtable(vport, hash, vmp);
		vmp->vmid_len = len;
		memcpy(vmp->host_vmid, uuid, vmp->vmid_len);
		vmp->io_rd_cnt = 0;
		vmp->io_wr_cnt = 0;
		vmp->flag = LPFC_VMID_SLOT_USED;

		vmp->delete_inactive =
			vport->vmid_inactivity_timeout ? 1 : 0;

		/* if type priority tag, get next available VMID */
		if (vport->phba->pport->vmid_flag & LPFC_VMID_TYPE_PRIO)
			lpfc_vmid_assign_cs_ctl(vport, vmp);

		/* allocate the per cpu variable for holding */
		/* the last access time stamp only if VMID is enabled */
		if (!vmp->last_io_time)
			vmp->last_io_time = alloc_percpu_gfp(u64, GFP_ATOMIC);
		if (!vmp->last_io_time) {
			hash_del(&vmp->hnode);
			vmp->flag = LPFC_VMID_SLOT_FREE;
			write_unlock(&vport->vmid_lock);
			return -EIO;
		}

		write_unlock(&vport->vmid_lock);

		/* complete transaction with switch */
		if (vport->phba->pport->vmid_flag & LPFC_VMID_TYPE_PRIO)
			rc = lpfc_vmid_uvem(vport, vmp, true);
		else if (vport->phba->cfg_vmid_app_header)
			rc = lpfc_vmid_cmd(vport, SLI_CTAS_RAPP_IDENT, vmp);
		if (!rc) {
			write_lock(&vport->vmid_lock);
			vport->cur_vmid_cnt++;
			vmp->flag |= LPFC_VMID_REQ_REGISTER;
			write_unlock(&vport->vmid_lock);
		} else {
			write_lock(&vport->vmid_lock);
			hash_del(&vmp->hnode);
			vmp->flag = LPFC_VMID_SLOT_FREE;
			free_percpu(vmp->last_io_time);
			write_unlock(&vport->vmid_lock);
			return -EIO;
		}

		/* finally, enable the idle timer once */
		if (!(vport->phba->pport->vmid_flag & LPFC_VMID_TIMER_ENBLD)) {
			mod_timer(&vport->phba->inactive_vmid_poll,
				  jiffies +
				  secs_to_jiffies(LPFC_VMID_TIMER));
			vport->phba->pport->vmid_flag |= LPFC_VMID_TIMER_ENBLD;
		}
	}
	return rc;
}

/*
 * lpfc_reinit_vmid - reinitializes the vmid data structure
 * @vport: pointer to vport data structure
 *
 * This routine reinitializes the vmid post flogi completion

Annotation

Implementation Notes