brintos

brintos / linux-shallow public Read only

0
0
Text · 18.8 KiB · 27d32b8 Raw
687 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Aic94xx Task Management Functions4 *5 * Copyright (C) 2005 Adaptec, Inc.  All rights reserved.6 * Copyright (C) 2005 Luben Tuikov <luben_tuikov@adaptec.com>7 */8 9#include <linux/spinlock.h>10#include <linux/gfp.h>11#include "aic94xx.h"12#include "aic94xx_sas.h"13#include "aic94xx_hwi.h"14 15/* ---------- Internal enqueue ---------- */16 17static int asd_enqueue_internal(struct asd_ascb *ascb,18		void (*tasklet_complete)(struct asd_ascb *,19					 struct done_list_struct *),20				void (*timed_out)(struct timer_list *t))21{22	int res;23 24	ascb->tasklet_complete = tasklet_complete;25	ascb->uldd_timer = 1;26 27	ascb->timer.function = timed_out;28	ascb->timer.expires = jiffies + AIC94XX_SCB_TIMEOUT;29 30	add_timer(&ascb->timer);31 32	res = asd_post_ascb_list(ascb->ha, ascb, 1);33	if (unlikely(res))34		del_timer(&ascb->timer);35	return res;36}37 38/* ---------- CLEAR NEXUS ---------- */39 40struct tasklet_completion_status {41	int	dl_opcode;42	int	tmf_state;43	u8	tag_valid:1;44	__be16	tag;45};46 47#define DECLARE_TCS(tcs) \48	struct tasklet_completion_status tcs = { \49		.dl_opcode = 0, \50		.tmf_state = 0, \51		.tag_valid = 0, \52		.tag = 0, \53	}54 55 56static void asd_clear_nexus_tasklet_complete(struct asd_ascb *ascb,57					     struct done_list_struct *dl)58{59	struct tasklet_completion_status *tcs = ascb->uldd_task;60	ASD_DPRINTK("%s: here\n", __func__);61	if (!del_timer(&ascb->timer)) {62		ASD_DPRINTK("%s: couldn't delete timer\n", __func__);63		return;64	}65	ASD_DPRINTK("%s: opcode: 0x%x\n", __func__, dl->opcode);66	tcs->dl_opcode = dl->opcode;67	complete(ascb->completion);68	asd_ascb_free(ascb);69}70 71static void asd_clear_nexus_timedout(struct timer_list *t)72{73	struct asd_ascb *ascb = from_timer(ascb, t, timer);74	struct tasklet_completion_status *tcs = ascb->uldd_task;75 76	ASD_DPRINTK("%s: here\n", __func__);77	tcs->dl_opcode = TMF_RESP_FUNC_FAILED;78	complete(ascb->completion);79}80 81#define CLEAR_NEXUS_PRE         \82	struct asd_ascb *ascb; \83	struct scb *scb; \84	int res; \85	DECLARE_COMPLETION_ONSTACK(completion); \86	DECLARE_TCS(tcs); \87		\88	ASD_DPRINTK("%s: PRE\n", __func__); \89        res = 1;                \90	ascb = asd_ascb_alloc_list(asd_ha, &res, GFP_KERNEL); \91	if (!ascb)              \92		return -ENOMEM; \93                                \94	ascb->completion = &completion; \95	ascb->uldd_task = &tcs; \96	scb = ascb->scb;        \97	scb->header.opcode = CLEAR_NEXUS98 99#define CLEAR_NEXUS_POST        \100	ASD_DPRINTK("%s: POST\n", __func__); \101	res = asd_enqueue_internal(ascb, asd_clear_nexus_tasklet_complete, \102				   asd_clear_nexus_timedout);              \103	if (res)                \104		goto out_err;   \105	ASD_DPRINTK("%s: clear nexus posted, waiting...\n", __func__); \106	wait_for_completion(&completion); \107	res = tcs.dl_opcode; \108	if (res == TC_NO_ERROR) \109		res = TMF_RESP_FUNC_COMPLETE;   \110	return res; \111out_err:                        \112	asd_ascb_free(ascb);    \113	return res114 115int asd_clear_nexus_ha(struct sas_ha_struct *sas_ha)116{117	struct asd_ha_struct *asd_ha = sas_ha->lldd_ha;118 119	CLEAR_NEXUS_PRE;120	scb->clear_nexus.nexus = NEXUS_ADAPTER;121	CLEAR_NEXUS_POST;122}123 124int asd_clear_nexus_port(struct asd_sas_port *port)125{126	struct asd_ha_struct *asd_ha = port->ha->lldd_ha;127 128	CLEAR_NEXUS_PRE;129	scb->clear_nexus.nexus = NEXUS_PORT;130	scb->clear_nexus.conn_mask = port->phy_mask;131	CLEAR_NEXUS_POST;132}133 134enum clear_nexus_phase {135	NEXUS_PHASE_PRE,136	NEXUS_PHASE_POST,137	NEXUS_PHASE_RESUME,138};139 140static int asd_clear_nexus_I_T(struct domain_device *dev,141			       enum clear_nexus_phase phase)142{143	struct asd_ha_struct *asd_ha = dev->port->ha->lldd_ha;144 145	CLEAR_NEXUS_PRE;146	scb->clear_nexus.nexus = NEXUS_I_T;147	switch (phase) {148	case NEXUS_PHASE_PRE:149		scb->clear_nexus.flags = EXEC_Q | SUSPEND_TX;150		break;151	case NEXUS_PHASE_POST:152		scb->clear_nexus.flags = SEND_Q | NOTINQ;153		break;154	case NEXUS_PHASE_RESUME:155		scb->clear_nexus.flags = RESUME_TX;156	}157	scb->clear_nexus.conn_handle = cpu_to_le16((u16)(unsigned long)158						   dev->lldd_dev);159	CLEAR_NEXUS_POST;160}161 162int asd_I_T_nexus_reset(struct domain_device *dev)163{164	int res, tmp_res, i;165	struct sas_phy *phy = sas_get_local_phy(dev);166	/* Standard mandates link reset for ATA  (type 0) and167	 * hard reset for SSP (type 1) */168	int reset_type = (dev->dev_type == SAS_SATA_DEV ||169			  (dev->tproto & SAS_PROTOCOL_STP)) ? 0 : 1;170 171	asd_clear_nexus_I_T(dev, NEXUS_PHASE_PRE);172	/* send a hard reset */173	ASD_DPRINTK("sending %s reset to %s\n",174		    reset_type ? "hard" : "soft", dev_name(&phy->dev));175	res = sas_phy_reset(phy, reset_type);176	if (res == TMF_RESP_FUNC_COMPLETE || res == -ENODEV) {177		/* wait for the maximum settle time */178		msleep(500);179		/* clear all outstanding commands (keep nexus suspended) */180		asd_clear_nexus_I_T(dev, NEXUS_PHASE_POST);181	}182	for (i = 0 ; i < 3; i++) {183		tmp_res = asd_clear_nexus_I_T(dev, NEXUS_PHASE_RESUME);184		if (tmp_res == TC_RESUME)185			goto out;186		msleep(500);187	}188 189	/* This is a bit of a problem:  the sequencer is still suspended190	 * and is refusing to resume.  Hope it will resume on a bigger hammer191	 * or the disk is lost */192	dev_printk(KERN_ERR, &phy->dev,193		   "Failed to resume nexus after reset 0x%x\n", tmp_res);194 195	res = TMF_RESP_FUNC_FAILED;196 out:197	sas_put_local_phy(phy);198	return res;199}200 201static int asd_clear_nexus_I_T_L(struct domain_device *dev, u8 *lun)202{203	struct asd_ha_struct *asd_ha = dev->port->ha->lldd_ha;204 205	CLEAR_NEXUS_PRE;206	scb->clear_nexus.nexus = NEXUS_I_T_L;207	scb->clear_nexus.flags = SEND_Q | EXEC_Q | NOTINQ;208	memcpy(scb->clear_nexus.ssp_task.lun, lun, 8);209	scb->clear_nexus.conn_handle = cpu_to_le16((u16)(unsigned long)210						   dev->lldd_dev);211	CLEAR_NEXUS_POST;212}213 214static int asd_clear_nexus_tag(struct sas_task *task)215{216	struct asd_ha_struct *asd_ha = task->dev->port->ha->lldd_ha;217	struct asd_ascb *tascb = task->lldd_task;218 219	CLEAR_NEXUS_PRE;220	scb->clear_nexus.nexus = NEXUS_TAG;221	memcpy(scb->clear_nexus.ssp_task.lun, task->ssp_task.LUN, 8);222	scb->clear_nexus.ssp_task.tag = tascb->tag;223	if (task->dev->tproto)224		scb->clear_nexus.conn_handle = cpu_to_le16((u16)(unsigned long)225							  task->dev->lldd_dev);226	CLEAR_NEXUS_POST;227}228 229static int asd_clear_nexus_index(struct sas_task *task)230{231	struct asd_ha_struct *asd_ha = task->dev->port->ha->lldd_ha;232	struct asd_ascb *tascb = task->lldd_task;233 234	CLEAR_NEXUS_PRE;235	scb->clear_nexus.nexus = NEXUS_TRANS_CX;236	if (task->dev->tproto)237		scb->clear_nexus.conn_handle = cpu_to_le16((u16)(unsigned long)238							  task->dev->lldd_dev);239	scb->clear_nexus.index = cpu_to_le16(tascb->tc_index);240	CLEAR_NEXUS_POST;241}242 243/* ---------- TMFs ---------- */244 245static void asd_tmf_timedout(struct timer_list *t)246{247	struct asd_ascb *ascb = from_timer(ascb, t, timer);248	struct tasklet_completion_status *tcs = ascb->uldd_task;249 250	ASD_DPRINTK("tmf timed out\n");251	tcs->tmf_state = TMF_RESP_FUNC_FAILED;252	complete(ascb->completion);253}254 255static int asd_get_tmf_resp_tasklet(struct asd_ascb *ascb,256				    struct done_list_struct *dl)257{258	struct asd_ha_struct *asd_ha = ascb->ha;259	unsigned long flags;260	struct tc_resp_sb_struct {261		__le16 index_escb;262		u8     len_lsb;263		u8     flags;264	} __attribute__ ((packed)) *resp_sb = (void *) dl->status_block;265 266	int  edb_id = ((resp_sb->flags & 0x70) >> 4)-1;267	struct asd_ascb *escb;268	struct asd_dma_tok *edb;269	struct ssp_frame_hdr *fh;270	struct ssp_response_iu   *ru;271	int res = TMF_RESP_FUNC_FAILED;272 273	ASD_DPRINTK("tmf resp tasklet\n");274 275	spin_lock_irqsave(&asd_ha->seq.tc_index_lock, flags);276	escb = asd_tc_index_find(&asd_ha->seq,277				 (int)le16_to_cpu(resp_sb->index_escb));278	spin_unlock_irqrestore(&asd_ha->seq.tc_index_lock, flags);279 280	if (!escb) {281		ASD_DPRINTK("Uh-oh! No escb for this dl?!\n");282		return res;283	}284 285	edb = asd_ha->seq.edb_arr[edb_id + escb->edb_index];286	ascb->tag = *(__be16 *)(edb->vaddr+4);287	fh = edb->vaddr + 16;288	ru = edb->vaddr + 16 + sizeof(*fh);289	res = ru->status;290	if (ru->datapres == SAS_DATAPRES_RESPONSE_DATA)291		res = ru->resp_data[3];292#if 0293	ascb->tag = fh->tag;294#endif295	ascb->tag_valid = 1;296 297	asd_invalidate_edb(escb, edb_id);298	return res;299}300 301static void asd_tmf_tasklet_complete(struct asd_ascb *ascb,302				     struct done_list_struct *dl)303{304	struct tasklet_completion_status *tcs;305 306	if (!del_timer(&ascb->timer))307		return;308 309	tcs = ascb->uldd_task;310	ASD_DPRINTK("tmf tasklet complete\n");311 312	tcs->dl_opcode = dl->opcode;313 314	if (dl->opcode == TC_SSP_RESP) {315		tcs->tmf_state = asd_get_tmf_resp_tasklet(ascb, dl);316		tcs->tag_valid = ascb->tag_valid;317		tcs->tag = ascb->tag;318	}319 320	complete(ascb->completion);321	asd_ascb_free(ascb);322}323 324static int asd_clear_nexus(struct sas_task *task)325{326	int res = TMF_RESP_FUNC_FAILED;327	int leftover;328	struct asd_ascb *tascb = task->lldd_task;329	DECLARE_COMPLETION_ONSTACK(completion);330	unsigned long flags;331 332	tascb->completion = &completion;333 334	ASD_DPRINTK("task not done, clearing nexus\n");335	if (tascb->tag_valid)336		res = asd_clear_nexus_tag(task);337	else338		res = asd_clear_nexus_index(task);339	leftover = wait_for_completion_timeout(&completion,340					       AIC94XX_SCB_TIMEOUT);341	tascb->completion = NULL;342	ASD_DPRINTK("came back from clear nexus\n");343	spin_lock_irqsave(&task->task_state_lock, flags);344	if (leftover < 1)345		res = TMF_RESP_FUNC_FAILED;346	if (task->task_state_flags & SAS_TASK_STATE_DONE)347		res = TMF_RESP_FUNC_COMPLETE;348	spin_unlock_irqrestore(&task->task_state_lock, flags);349 350	return res;351}352 353/**354 * asd_abort_task -- ABORT TASK TMF355 * @task: the task to be aborted356 *357 * Before calling ABORT TASK the task state flags should be ORed with358 * SAS_TASK_STATE_ABORTED (unless SAS_TASK_STATE_DONE is set) under359 * the task_state_lock IRQ spinlock, then ABORT TASK *must* be called.360 *361 * Implements the ABORT TASK TMF, I_T_L_Q nexus.362 * Returns: SAS TMF responses (see sas_task.h),363 *          -ENOMEM,364 *          -SAS_QUEUE_FULL.365 *366 * When ABORT TASK returns, the caller of ABORT TASK checks first the367 * task->task_state_flags, and then the return value of ABORT TASK.368 *369 * If the task has task state bit SAS_TASK_STATE_DONE set, then the370 * task was completed successfully prior to it being aborted.  The371 * caller of ABORT TASK has responsibility to call task->task_done()372 * xor free the task, depending on their framework.  The return code373 * is TMF_RESP_FUNC_FAILED in this case.374 *375 * Else the SAS_TASK_STATE_DONE bit is not set,376 * 	If the return code is TMF_RESP_FUNC_COMPLETE, then377 * 		the task was aborted successfully.  The caller of378 * 		ABORT TASK has responsibility to call task->task_done()379 *              to finish the task, xor free the task depending on their380 *		framework.381 *	else382 * 		the ABORT TASK returned some kind of error. The task383 *              was _not_ cancelled.  Nothing can be assumed.384 *		The caller of ABORT TASK may wish to retry.385 */386int asd_abort_task(struct sas_task *task)387{388	struct asd_ascb *tascb = task->lldd_task;389	struct asd_ha_struct *asd_ha = tascb->ha;390	int res = 1;391	unsigned long flags;392	struct asd_ascb *ascb = NULL;393	struct scb *scb;394	int leftover;395	DECLARE_TCS(tcs);396	DECLARE_COMPLETION_ONSTACK(completion);397	DECLARE_COMPLETION_ONSTACK(tascb_completion);398 399	tascb->completion = &tascb_completion;400 401	spin_lock_irqsave(&task->task_state_lock, flags);402	if (task->task_state_flags & SAS_TASK_STATE_DONE) {403		spin_unlock_irqrestore(&task->task_state_lock, flags);404		res = TMF_RESP_FUNC_COMPLETE;405		ASD_DPRINTK("%s: task 0x%p done\n", __func__, task);406		goto out_done;407	}408	spin_unlock_irqrestore(&task->task_state_lock, flags);409 410	ascb = asd_ascb_alloc_list(asd_ha, &res, GFP_KERNEL);411	if (!ascb)412		return -ENOMEM;413 414	ascb->uldd_task = &tcs;415	ascb->completion = &completion;416	scb = ascb->scb;417	scb->header.opcode = SCB_ABORT_TASK;418 419	switch (task->task_proto) {420	case SAS_PROTOCOL_SATA:421	case SAS_PROTOCOL_STP:422		scb->abort_task.proto_conn_rate = (1 << 5); /* STP */423		break;424	case SAS_PROTOCOL_SSP:425		scb->abort_task.proto_conn_rate  = (1 << 4); /* SSP */426		scb->abort_task.proto_conn_rate |= task->dev->linkrate;427		break;428	case SAS_PROTOCOL_SMP:429		break;430	default:431		break;432	}433 434	if (task->task_proto == SAS_PROTOCOL_SSP) {435		scb->abort_task.ssp_frame.frame_type = SSP_TASK;436		memcpy(scb->abort_task.ssp_frame.hashed_dest_addr,437		       task->dev->hashed_sas_addr, HASHED_SAS_ADDR_SIZE);438		memcpy(scb->abort_task.ssp_frame.hashed_src_addr,439		       task->dev->port->ha->hashed_sas_addr,440		       HASHED_SAS_ADDR_SIZE);441		scb->abort_task.ssp_frame.tptt = cpu_to_be16(0xFFFF);442 443		memcpy(scb->abort_task.ssp_task.lun, task->ssp_task.LUN, 8);444		scb->abort_task.ssp_task.tmf = TMF_ABORT_TASK;445		scb->abort_task.ssp_task.tag = cpu_to_be16(0xFFFF);446	}447 448	scb->abort_task.sister_scb = cpu_to_le16(0xFFFF);449	scb->abort_task.conn_handle = cpu_to_le16(450		(u16)(unsigned long)task->dev->lldd_dev);451	scb->abort_task.retry_count = 1;452	scb->abort_task.index = cpu_to_le16((u16)tascb->tc_index);453	scb->abort_task.itnl_to = cpu_to_le16(ITNL_TIMEOUT_CONST);454 455	res = asd_enqueue_internal(ascb, asd_tmf_tasklet_complete,456				   asd_tmf_timedout);457	if (res)458		goto out_free;459	wait_for_completion(&completion);460	ASD_DPRINTK("tmf came back\n");461 462	tascb->tag = tcs.tag;463	tascb->tag_valid = tcs.tag_valid;464 465	spin_lock_irqsave(&task->task_state_lock, flags);466	if (task->task_state_flags & SAS_TASK_STATE_DONE) {467		spin_unlock_irqrestore(&task->task_state_lock, flags);468		res = TMF_RESP_FUNC_COMPLETE;469		ASD_DPRINTK("%s: task 0x%p done\n", __func__, task);470		goto out_done;471	}472	spin_unlock_irqrestore(&task->task_state_lock, flags);473 474	if (tcs.dl_opcode == TC_SSP_RESP) {475		/* The task to be aborted has been sent to the device.476		 * We got a Response IU for the ABORT TASK TMF. */477		if (tcs.tmf_state == TMF_RESP_FUNC_COMPLETE)478			res = asd_clear_nexus(task);479		else480			res = tcs.tmf_state;481	} else if (tcs.dl_opcode == TC_NO_ERROR &&482		   tcs.tmf_state == TMF_RESP_FUNC_FAILED) {483		/* timeout */484		res = TMF_RESP_FUNC_FAILED;485	} else {486		/* In the following we assume that the managing layer487		 * will _never_ make a mistake, when issuing ABORT488		 * TASK.489		 */490		switch (tcs.dl_opcode) {491		default:492			res = asd_clear_nexus(task);493			fallthrough;494		case TC_NO_ERROR:495			break;496			/* The task hasn't been sent to the device xor497			 * we never got a (sane) Response IU for the498			 * ABORT TASK TMF.499			 */500		case TF_NAK_RECV:501			res = TMF_RESP_INVALID_FRAME;502			break;503		case TF_TMF_TASK_DONE:	/* done but not reported yet */504			res = TMF_RESP_FUNC_FAILED;505			leftover =506				wait_for_completion_timeout(&tascb_completion,507							  AIC94XX_SCB_TIMEOUT);508			spin_lock_irqsave(&task->task_state_lock, flags);509			if (leftover < 1)510				res = TMF_RESP_FUNC_FAILED;511			if (task->task_state_flags & SAS_TASK_STATE_DONE)512				res = TMF_RESP_FUNC_COMPLETE;513			spin_unlock_irqrestore(&task->task_state_lock, flags);514			break;515		case TF_TMF_NO_TAG:516		case TF_TMF_TAG_FREE: /* the tag is in the free list */517		case TF_TMF_NO_CONN_HANDLE: /* no such device */518			res = TMF_RESP_FUNC_COMPLETE;519			break;520		case TF_TMF_NO_CTX: /* not in seq, or proto != SSP */521			res = TMF_RESP_FUNC_ESUPP;522			break;523		}524	}525 out_done:526	tascb->completion = NULL;527	if (res == TMF_RESP_FUNC_COMPLETE) {528		task->lldd_task = NULL;529		mb();530		asd_ascb_free(tascb);531	}532	ASD_DPRINTK("task 0x%p aborted, res: 0x%x\n", task, res);533	return res;534 535 out_free:536	asd_ascb_free(ascb);537	ASD_DPRINTK("task 0x%p aborted, res: 0x%x\n", task, res);538	return res;539}540 541/**542 * asd_initiate_ssp_tmf -- send a TMF to an I_T_L or I_T_L_Q nexus543 * @dev: pointer to struct domain_device of interest544 * @lun: pointer to u8[8] which is the LUN545 * @tmf: the TMF to be performed (see sas_task.h or the SAS spec)546 * @index: the transaction context of the task to be queried if QT TMF547 *548 * This function is used to send ABORT TASK SET, CLEAR ACA,549 * CLEAR TASK SET, LU RESET and QUERY TASK TMFs.550 *551 * No SCBs should be queued to the I_T_L nexus when this SCB is552 * pending.553 *554 * Returns: TMF response code (see sas_task.h or the SAS spec)555 */556static int asd_initiate_ssp_tmf(struct domain_device *dev, u8 *lun,557				int tmf, int index)558{559	struct asd_ha_struct *asd_ha = dev->port->ha->lldd_ha;560	struct asd_ascb *ascb;561	int res = 1;562	struct scb *scb;563	DECLARE_COMPLETION_ONSTACK(completion);564	DECLARE_TCS(tcs);565 566	if (!(dev->tproto & SAS_PROTOCOL_SSP))567		return TMF_RESP_FUNC_ESUPP;568 569	ascb = asd_ascb_alloc_list(asd_ha, &res, GFP_KERNEL);570	if (!ascb)571		return -ENOMEM;572 573	ascb->completion = &completion;574	ascb->uldd_task = &tcs;575	scb = ascb->scb;576 577	if (tmf == TMF_QUERY_TASK)578		scb->header.opcode = QUERY_SSP_TASK;579	else580		scb->header.opcode = INITIATE_SSP_TMF;581 582	scb->ssp_tmf.proto_conn_rate  = (1 << 4); /* SSP */583	scb->ssp_tmf.proto_conn_rate |= dev->linkrate;584	/* SSP frame header */585	scb->ssp_tmf.ssp_frame.frame_type = SSP_TASK;586	memcpy(scb->ssp_tmf.ssp_frame.hashed_dest_addr,587	       dev->hashed_sas_addr, HASHED_SAS_ADDR_SIZE);588	memcpy(scb->ssp_tmf.ssp_frame.hashed_src_addr,589	       dev->port->ha->hashed_sas_addr, HASHED_SAS_ADDR_SIZE);590	scb->ssp_tmf.ssp_frame.tptt = cpu_to_be16(0xFFFF);591	/* SSP Task IU */592	memcpy(scb->ssp_tmf.ssp_task.lun, lun, 8);593	scb->ssp_tmf.ssp_task.tmf = tmf;594 595	scb->ssp_tmf.sister_scb = cpu_to_le16(0xFFFF);596	scb->ssp_tmf.conn_handle= cpu_to_le16((u16)(unsigned long)597					      dev->lldd_dev);598	scb->ssp_tmf.retry_count = 1;599	scb->ssp_tmf.itnl_to = cpu_to_le16(ITNL_TIMEOUT_CONST);600	if (tmf == TMF_QUERY_TASK)601		scb->ssp_tmf.index = cpu_to_le16(index);602 603	res = asd_enqueue_internal(ascb, asd_tmf_tasklet_complete,604				   asd_tmf_timedout);605	if (res)606		goto out_err;607	wait_for_completion(&completion);608 609	switch (tcs.dl_opcode) {610	case TC_NO_ERROR:611		res = TMF_RESP_FUNC_COMPLETE;612		break;613	case TF_NAK_RECV:614		res = TMF_RESP_INVALID_FRAME;615		break;616	case TF_TMF_TASK_DONE:617		res = TMF_RESP_FUNC_FAILED;618		break;619	case TF_TMF_NO_TAG:620	case TF_TMF_TAG_FREE: /* the tag is in the free list */621	case TF_TMF_NO_CONN_HANDLE: /* no such device */622		res = TMF_RESP_FUNC_COMPLETE;623		break;624	case TF_TMF_NO_CTX: /* not in seq, or proto != SSP */625		res = TMF_RESP_FUNC_ESUPP;626		break;627	default:628		/* Allow TMF response codes to propagate upwards */629		res = tcs.dl_opcode;630		break;631	}632	return res;633out_err:634	asd_ascb_free(ascb);635	return res;636}637 638int asd_abort_task_set(struct domain_device *dev, u8 *lun)639{640	int res = asd_initiate_ssp_tmf(dev, lun, TMF_ABORT_TASK_SET, 0);641 642	if (res == TMF_RESP_FUNC_COMPLETE)643		asd_clear_nexus_I_T_L(dev, lun);644	return res;645}646 647int asd_clear_task_set(struct domain_device *dev, u8 *lun)648{649	int res = asd_initiate_ssp_tmf(dev, lun, TMF_CLEAR_TASK_SET, 0);650 651	if (res == TMF_RESP_FUNC_COMPLETE)652		asd_clear_nexus_I_T_L(dev, lun);653	return res;654}655 656int asd_lu_reset(struct domain_device *dev, u8 *lun)657{658	int res = asd_initiate_ssp_tmf(dev, lun, TMF_LU_RESET, 0);659 660	if (res == TMF_RESP_FUNC_COMPLETE)661		asd_clear_nexus_I_T_L(dev, lun);662	return res;663}664 665/**666 * asd_query_task -- send a QUERY TASK TMF to an I_T_L_Q nexus667 * @task: pointer to sas_task struct of interest668 *669 * Returns: TMF_RESP_FUNC_COMPLETE if the task is not in the task set,670 * or TMF_RESP_FUNC_SUCC if the task is in the task set.671 *672 * Normally the management layer sets the task to aborted state,673 * and then calls query task and then abort task.674 */675int asd_query_task(struct sas_task *task)676{677	struct asd_ascb *ascb = task->lldd_task;678	int index;679 680	if (ascb) {681		index = ascb->tc_index;682		return asd_initiate_ssp_tmf(task->dev, task->ssp_task.LUN,683					    TMF_QUERY_TASK, index);684	}685	return TMF_RESP_FUNC_COMPLETE;686}687