drivers/scsi/aic94xx/aic94xx_tmf.c

Source file repositories/reference/linux-study-clean/drivers/scsi/aic94xx/aic94xx_tmf.c

File Facts

System
Linux kernel
Corpus path
drivers/scsi/aic94xx/aic94xx_tmf.c
Extension
.c
Size
19282 bytes
Lines
687
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 tasklet_completion_status {
	int	dl_opcode;
	int	tmf_state;
	u8	tag_valid:1;
	__be16	tag;
};

#define DECLARE_TCS(tcs) \
	struct tasklet_completion_status tcs = { \
		.dl_opcode = 0, \
		.tmf_state = 0, \
		.tag_valid = 0, \
		.tag = 0, \
	}


static void asd_clear_nexus_tasklet_complete(struct asd_ascb *ascb,
					     struct done_list_struct *dl)
{
	struct tasklet_completion_status *tcs = ascb->uldd_task;
	ASD_DPRINTK("%s: here\n", __func__);
	if (!timer_delete(&ascb->timer)) {
		ASD_DPRINTK("%s: couldn't delete timer\n", __func__);
		return;
	}
	ASD_DPRINTK("%s: opcode: 0x%x\n", __func__, dl->opcode);
	tcs->dl_opcode = dl->opcode;
	complete(ascb->completion);
	asd_ascb_free(ascb);
}

static void asd_clear_nexus_timedout(struct timer_list *t)
{
	struct asd_ascb *ascb = timer_container_of(ascb, t, timer);
	struct tasklet_completion_status *tcs = ascb->uldd_task;

	ASD_DPRINTK("%s: here\n", __func__);
	tcs->dl_opcode = TMF_RESP_FUNC_FAILED;
	complete(ascb->completion);
}

#define CLEAR_NEXUS_PRE         \
	struct asd_ascb *ascb; \
	struct scb *scb; \
	int res; \
	DECLARE_COMPLETION_ONSTACK(completion); \
	DECLARE_TCS(tcs); \
		\
	ASD_DPRINTK("%s: PRE\n", __func__); \
        res = 1;                \
	ascb = asd_ascb_alloc_list(asd_ha, &res, GFP_KERNEL); \
	if (!ascb)              \
		return -ENOMEM; \
                                \
	ascb->completion = &completion; \
	ascb->uldd_task = &tcs; \
	scb = ascb->scb;        \
	scb->header.opcode = CLEAR_NEXUS

#define CLEAR_NEXUS_POST        \
	ASD_DPRINTK("%s: POST\n", __func__); \
	res = asd_enqueue_internal(ascb, asd_clear_nexus_tasklet_complete, \
				   asd_clear_nexus_timedout);              \
	if (res)                \
		goto out_err;   \
	ASD_DPRINTK("%s: clear nexus posted, waiting...\n", __func__); \
	wait_for_completion(&completion); \
	res = tcs.dl_opcode; \
	if (res == TC_NO_ERROR) \
		res = TMF_RESP_FUNC_COMPLETE;   \
	return res; \
out_err:                        \
	asd_ascb_free(ascb);    \
	return res

int asd_clear_nexus_ha(struct sas_ha_struct *sas_ha)
{
	struct asd_ha_struct *asd_ha = sas_ha->lldd_ha;

	CLEAR_NEXUS_PRE;
	scb->clear_nexus.nexus = NEXUS_ADAPTER;
	CLEAR_NEXUS_POST;
}

int asd_clear_nexus_port(struct asd_sas_port *port)
{
	struct asd_ha_struct *asd_ha = port->ha->lldd_ha;

	CLEAR_NEXUS_PRE;
	scb->clear_nexus.nexus = NEXUS_PORT;

Annotation

Implementation Notes