drivers/scsi/elx/libefc/efc_device.c

Source file repositories/reference/linux-study-clean/drivers/scsi/elx/libefc/efc_device.c

File Facts

System
Linux kernel
Corpus path
drivers/scsi/elx/libefc/efc_device.c
Extension
.c
Size
41036 bytes
Lines
1603
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 (node->init && !node->targ) {
			efc_log_info(node->efc,
				     "[%s] delete (initiator) WWPN %s WWNN %s\n",
				node->display_name,
				node->wwpn, node->wwnn);
			efc_node_transition(node,
					    __efc_d_wait_del_node,
					     NULL);
			if (node->nport->enable_tgt)
				rc = efc->tt.scsi_del_node(efc, node,
					EFC_SCSI_INITIATOR_DELETED);

			if (rc == EFC_SCSI_CALL_COMPLETE || rc < 0)
				efc_node_post_event(node,
					EFC_EVT_NODE_DEL_INI_COMPLETE, NULL);

		} else if (node->targ && !node->init) {
			efc_log_info(node->efc,
				     "[%s] delete (target) WWPN %s WWNN %s\n",
				node->display_name,
				node->wwpn, node->wwnn);
			efc_node_transition(node,
					    __efc_d_wait_del_node,
					     NULL);
			if (node->nport->enable_ini)
				rc = efc->tt.scsi_del_node(efc, node,
					EFC_SCSI_TARGET_DELETED);

			if (rc == EFC_SCSI_CALL_COMPLETE)
				efc_node_post_event(node,
					EFC_EVT_NODE_DEL_TGT_COMPLETE, NULL);

		} else if (node->init && node->targ) {
			efc_log_info(node->efc,
				     "[%s] delete (I+T) WWPN %s WWNN %s\n",
				node->display_name, node->wwpn, node->wwnn);
			efc_node_transition(node, __efc_d_wait_del_ini_tgt,
					    NULL);
			if (node->nport->enable_tgt)
				rc = efc->tt.scsi_del_node(efc, node,
						EFC_SCSI_INITIATOR_DELETED);

			if (rc == EFC_SCSI_CALL_COMPLETE)
				efc_node_post_event(node,
					EFC_EVT_NODE_DEL_INI_COMPLETE, NULL);
			/* assume no wait needed */
			rc = EFC_SCSI_CALL_COMPLETE;
			if (node->nport->enable_ini)
				rc = efc->tt.scsi_del_node(efc, node,
						EFC_SCSI_TARGET_DELETED);

			if (rc == EFC_SCSI_CALL_COMPLETE)
				efc_node_post_event(node,
					EFC_EVT_NODE_DEL_TGT_COMPLETE, NULL);
		}

		/* we've initiated the upcalls as needed, now kick off the node
		 * detach to precipitate the aborting of outstanding exchanges
		 * associated with said node
		 *
		 * Beware: if we've made upcall(s), we've already transitioned
		 * to a new state by the time we execute this.
		 * consider doing this before the upcalls?
		 */
		if (node->attached) {
			/* issue hw node free; don't care if succeeds right
			 * away or sometime later, will check node->attached
			 * later in shutdown process
			 */
			rc = efc_cmd_node_detach(efc, &node->rnode);
			if (rc < 0)
				node_printf(node,
					    "Failed freeing HW node, rc=%d\n",
					rc);
		}

		/* if neither initiator nor target, proceed to cleanup */
		if (!node->init && !node->targ) {
			/*
			 * node has either been detached or is in
			 * the process of being detached,
			 * call common node's initiate cleanup function
			 */
			efc_node_initiate_cleanup(node);
		}
		break;
	}
	case EFC_EVT_ALL_CHILD_NODES_FREE:
		/* Ignore, this can happen if an ELS is
		 * aborted while in a delay/retry state

Annotation

Implementation Notes