task.c 23.4 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
/*
 * This file is provided under a dual BSD/GPLv2 license.  When using or
 * redistributing this file, you may do so under either license.
 *
 * GPL LICENSE SUMMARY
 *
 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of version 2 of the GNU General Public License as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
 * The full GNU General Public License is included in this distribution
 * in the file called LICENSE.GPL.
 *
 * BSD LICENSE
 *
 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *   * Neither the name of Intel Corporation nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <linux/completion.h>
57
#include <linux/irqflags.h>
58
#include "sas.h"
59
#include <scsi/libsas.h>
60 61
#include "remote_device.h"
#include "remote_node_context.h"
62 63 64
#include "isci.h"
#include "request.h"
#include "task.h"
65
#include "host.h"
66

67
/**
68 69 70 71 72 73
* isci_task_refuse() - complete the request to the upper layer driver in
*     the case where an I/O needs to be completed back in the submit path.
* @ihost: host on which the the request was queued
* @task: request to complete
* @response: response code for the completed task.
* @status: status code for the completed task.
74 75
*
*/
76 77 78 79
static void isci_task_refuse(struct isci_host *ihost, struct sas_task *task,
			     enum service_response response,
			     enum exec_status status)

80
{
81
	unsigned long flags;
82

83 84 85
	/* Normal notification (task_done) */
	dev_dbg(&ihost->pdev->dev, "%s: task = %p, response=%d, status=%d\n",
		__func__, task, response, status);
86

87
	spin_lock_irqsave(&task->task_state_lock, flags);
88

89 90
	task->task_status.resp = response;
	task->task_status.stat = status;
91

92 93 94 95 96 97 98 99
	/* Normal notification (task_done) */
	task->task_state_flags |= SAS_TASK_STATE_DONE;
	task->task_state_flags &= ~(SAS_TASK_AT_INITIATOR |
				    SAS_TASK_STATE_PENDING);
	task->lldd_task = NULL;
	spin_unlock_irqrestore(&task->task_state_lock, flags);

	task->task_done(task);
100
}
101

102 103 104 105
#define for_each_sas_task(num, task) \
	for (; num > 0; num--,\
	     task = list_entry(task->list.next, struct sas_task, list))

106 107 108 109 110 111 112 113 114

static inline int isci_device_io_ready(struct isci_remote_device *idev,
				       struct sas_task *task)
{
	return idev ? test_bit(IDEV_IO_READY, &idev->flags) ||
		      (test_bit(IDEV_IO_NCQERROR, &idev->flags) &&
		       isci_task_is_ncq_recovery(task))
		    : 0;
}
115 116 117 118 119 120 121 122 123 124 125 126
/**
 * isci_task_execute_task() - This function is one of the SAS Domain Template
 *    functions. This function is called by libsas to send a task down to
 *    hardware.
 * @task: This parameter specifies the SAS task to send.
 * @num: This parameter specifies the number of tasks to queue.
 * @gfp_flags: This parameter specifies the context of this call.
 *
 * status, zero indicates success.
 */
int isci_task_execute_task(struct sas_task *task, int num, gfp_t gfp_flags)
{
127
	struct isci_host *ihost = dev_to_ihost(task->dev);
128
	struct isci_remote_device *idev;
129
	unsigned long flags;
130
	bool io_ready;
131
	u16 tag;
132

133
	dev_dbg(&ihost->pdev->dev, "%s: num=%d\n", __func__, num);
134

135
	for_each_sas_task(num, task) {
136 137
		enum sci_status status = SCI_FAILURE;

138 139
		spin_lock_irqsave(&ihost->scic_lock, flags);
		idev = isci_lookup_device(task->dev);
140
		io_ready = isci_device_io_ready(idev, task);
141
		tag = isci_alloc_tag(ihost);
142
		spin_unlock_irqrestore(&ihost->scic_lock, flags);
143

144 145 146 147
		dev_dbg(&ihost->pdev->dev,
			"task: %p, num: %d dev: %p idev: %p:%#lx cmd = %p\n",
			task, num, task->dev, idev, idev ? idev->flags : 0,
			task->uldd_task);
148

149 150 151
		if (!idev) {
			isci_task_refuse(ihost, task, SAS_TASK_UNDELIVERED,
					 SAS_DEVICE_UNKNOWN);
152
		} else if (!io_ready || tag == SCI_CONTROLLER_INVALID_IO_TAG) {
153 154 155 156 157
			/* Indicate QUEUE_FULL so that the scsi midlayer
			 * retries.
			  */
			isci_task_refuse(ihost, task, SAS_TASK_COMPLETE,
					 SAS_QUEUE_FULL);
158 159 160
		} else {
			/* There is a device and it's ready for I/O. */
			spin_lock_irqsave(&task->task_state_lock, flags);
161

162
			if (task->task_state_flags & SAS_TASK_STATE_ABORTED) {
163
				/* The I/O was aborted. */
164 165
				spin_unlock_irqrestore(&task->task_state_lock,
						       flags);
166

167 168 169
				isci_task_refuse(ihost, task,
						 SAS_TASK_UNDELIVERED,
						 SAM_STAT_TASK_ABORTED);
170
			} else {
171 172
				task->task_state_flags |= SAS_TASK_AT_INITIATOR;
				spin_unlock_irqrestore(&task->task_state_lock, flags);
173 174

				/* build and send the request. */
D
Dan Williams 已提交
175
				status = isci_request_execute(ihost, idev, task, tag);
176 177 178 179 180 181 182 183

				if (status != SCI_SUCCESS) {

					spin_lock_irqsave(&task->task_state_lock, flags);
					/* Did not really start this command. */
					task->task_state_flags &= ~SAS_TASK_AT_INITIATOR;
					spin_unlock_irqrestore(&task->task_state_lock, flags);

184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204
					if (test_bit(IDEV_GONE, &idev->flags)) {

						/* Indicate that the device
						 * is gone.
						 */
						isci_task_refuse(ihost, task,
							SAS_TASK_UNDELIVERED,
							SAS_DEVICE_UNKNOWN);
					} else {
						/* Indicate QUEUE_FULL so that
						 * the scsi midlayer retries.
						 * If the request failed for
						 * remote device reasons, it
						 * gets returned as
						 * SAS_TASK_UNDELIVERED next
						 * time through.
						 */
						isci_task_refuse(ihost, task,
							SAS_TASK_COMPLETE,
							SAS_QUEUE_FULL);
					}
205
				}
206 207
			}
		}
208 209 210 211 212 213 214 215
		if (status != SCI_SUCCESS && tag != SCI_CONTROLLER_INVALID_IO_TAG) {
			spin_lock_irqsave(&ihost->scic_lock, flags);
			/* command never hit the device, so just free
			 * the tci and skip the sequence increment
			 */
			isci_tci_free(ihost, ISCI_TAG_TCI(tag));
			spin_unlock_irqrestore(&ihost->scic_lock, flags);
		}
216
		isci_put_device(idev);
217
	}
218 219 220
	return 0;
}

D
Dan Williams 已提交
221
static struct isci_request *isci_task_request_build(struct isci_host *ihost,
222
						    struct isci_remote_device *idev,
223
						    u16 tag, struct isci_tmf *isci_tmf)
224 225
{
	enum sci_status status = SCI_FAILURE;
D
Dan Williams 已提交
226
	struct isci_request *ireq = NULL;
227
	struct domain_device *dev;
228

D
Dan Williams 已提交
229
	dev_dbg(&ihost->pdev->dev,
230 231
		"%s: isci_tmf = %p\n", __func__, isci_tmf);

D
Dan Williams 已提交
232
	dev = idev->domain_dev;
233 234

	/* do common allocation and init of request object. */
D
Dan Williams 已提交
235
	ireq = isci_tmf_request_from_tag(ihost, isci_tmf, tag);
D
Dan Williams 已提交
236 237
	if (!ireq)
		return NULL;
238 239

	/* let the core do it's construct. */
240
	status = sci_task_request_construct(ihost, idev, tag,
241
					     ireq);
242 243

	if (status != SCI_SUCCESS) {
D
Dan Williams 已提交
244
		dev_warn(&ihost->pdev->dev,
245
			 "%s: sci_task_request_construct failed - "
246 247 248
			 "status = 0x%x\n",
			 __func__,
			 status);
D
Dan Williams 已提交
249
		return NULL;
250 251
	}

252 253
	/* XXX convert to get this from task->tproto like other drivers */
	if (dev->dev_type == SAS_END_DEV) {
254
		isci_tmf->proto = SAS_PROTOCOL_SSP;
255
		status = sci_task_request_construct_ssp(ireq);
256
		if (status != SCI_SUCCESS)
D
Dan Williams 已提交
257
			return NULL;
258 259
	}

D
Dan Williams 已提交
260
	return ireq;
261 262
}

263 264 265
static int isci_task_execute_tmf(struct isci_host *ihost,
				 struct isci_remote_device *idev,
				 struct isci_tmf *tmf, unsigned long timeout_ms)
266 267
{
	DECLARE_COMPLETION_ONSTACK(completion);
268
	enum sci_task_status status = SCI_TASK_FAILURE;
D
Dan Williams 已提交
269
	struct isci_request *ireq;
270 271
	int ret = TMF_RESP_FUNC_FAILED;
	unsigned long flags;
E
Edmund Nadolski 已提交
272
	unsigned long timeleft;
273 274 275 276 277 278 279 280
	u16 tag;

	spin_lock_irqsave(&ihost->scic_lock, flags);
	tag = isci_alloc_tag(ihost);
	spin_unlock_irqrestore(&ihost->scic_lock, flags);

	if (tag == SCI_CONTROLLER_INVALID_IO_TAG)
		return ret;
281 282 283 284

	/* sanity check, return TMF_RESP_FUNC_FAILED
	 * if the device is not there and ready.
	 */
285 286 287
	if (!idev ||
	    (!test_bit(IDEV_IO_READY, &idev->flags) &&
	     !test_bit(IDEV_IO_NCQERROR, &idev->flags))) {
D
Dan Williams 已提交
288
		dev_dbg(&ihost->pdev->dev,
289
			"%s: idev = %p not ready (%#lx)\n",
290
			__func__,
291
			idev, idev ? idev->flags : 0);
292
		goto err_tci;
293
	} else
D
Dan Williams 已提交
294
		dev_dbg(&ihost->pdev->dev,
295 296
			"%s: idev = %p\n",
			__func__, idev);
297 298 299

	/* Assign the pointer to the TMF's completion kernel wait structure. */
	tmf->complete = &completion;
300
	tmf->status = SCI_FAILURE_TIMEOUT;
301

302
	ireq = isci_task_request_build(ihost, idev, tag, tmf);
303 304
	if (!ireq)
		goto err_tci;
305

D
Dan Williams 已提交
306
	spin_lock_irqsave(&ihost->scic_lock, flags);
307 308

	/* start the TMF io. */
309
	status = sci_controller_start_task(ihost, idev, ireq);
310

311
	if (status != SCI_TASK_SUCCESS) {
D
Dan Williams 已提交
312
		dev_dbg(&ihost->pdev->dev,
313 314 315
			 "%s: start_io failed - status = 0x%x, request = %p\n",
			 __func__,
			 status,
D
Dan Williams 已提交
316 317
			 ireq);
		spin_unlock_irqrestore(&ihost->scic_lock, flags);
D
Dan Williams 已提交
318
		goto err_tci;
319
	}
320 321 322
	/* The RNC must be unsuspended before the TMF can get a response. */
	sci_remote_device_resume(idev, NULL, NULL);

D
Dan Williams 已提交
323
	spin_unlock_irqrestore(&ihost->scic_lock, flags);
324 325

	/* Wait for the TMF to complete, or a timeout. */
E
Edmund Nadolski 已提交
326
	timeleft = wait_for_completion_timeout(&completion,
327
					       msecs_to_jiffies(timeout_ms));
E
Edmund Nadolski 已提交
328 329

	if (timeleft == 0) {
330 331 332
		/* The TMF did not complete - this could be because
		 * of an unplug.  Terminate the TMF request now.
		 */
333
		isci_remote_device_suspend_terminate(ihost, idev, ireq);
E
Edmund Nadolski 已提交
334
	}
335

336
	isci_print_tmf(ihost, tmf);
337 338 339 340

	if (tmf->status == SCI_SUCCESS)
		ret =  TMF_RESP_FUNC_COMPLETE;
	else if (tmf->status == SCI_FAILURE_IO_RESPONSE_VALID) {
D
Dan Williams 已提交
341
		dev_dbg(&ihost->pdev->dev,
342 343 344 345 346 347 348
			"%s: tmf.status == "
			"SCI_FAILURE_IO_RESPONSE_VALID\n",
			__func__);
		ret =  TMF_RESP_FUNC_COMPLETE;
	}
	/* Else - leave the default "failed" status alone. */

D
Dan Williams 已提交
349
	dev_dbg(&ihost->pdev->dev,
350 351
		"%s: completed request = %p\n",
		__func__,
D
Dan Williams 已提交
352
		ireq);
353 354

	return ret;
355 356 357 358 359 360 361

 err_tci:
	spin_lock_irqsave(&ihost->scic_lock, flags);
	isci_tci_free(ihost, ISCI_TAG_TCI(tag));
	spin_unlock_irqrestore(&ihost->scic_lock, flags);

	return ret;
362 363
}

364
static void isci_task_build_tmf(struct isci_tmf *tmf,
365
				enum isci_tmf_function_codes code)
366 367
{
	memset(tmf, 0, sizeof(*tmf));
368
	tmf->tmf_code = code;
369
}
370

371 372 373
static void isci_task_build_abort_task_tmf(struct isci_tmf *tmf,
					   enum isci_tmf_function_codes code,
					   struct isci_request *old_request)
374
{
375
	isci_task_build_tmf(tmf, code);
376
	tmf->io_tag = old_request->io_tag;
377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401
}

/**
 * isci_task_send_lu_reset_sas() - This function is called by of the SAS Domain
 *    Template functions.
 * @lun: This parameter specifies the lun to be reset.
 *
 * status, zero indicates success.
 */
static int isci_task_send_lu_reset_sas(
	struct isci_host *isci_host,
	struct isci_remote_device *isci_device,
	u8 *lun)
{
	struct isci_tmf tmf;
	int ret = TMF_RESP_FUNC_FAILED;

	dev_dbg(&isci_host->pdev->dev,
		"%s: isci_host = %p, isci_device = %p\n",
		__func__, isci_host, isci_device);
	/* Send the LUN reset to the target.  By the time the call returns,
	 * the TMF has fully exected in the target (in which case the return
	 * value is "TMF_RESP_FUNC_COMPLETE", or the request timed-out (or
	 * was otherwise unable to be executed ("TMF_RESP_FUNC_FAILED").
	 */
402
	isci_task_build_tmf(&tmf, isci_tmf_ssp_lun_reset);
403 404

	#define ISCI_LU_RESET_TIMEOUT_MS 2000 /* 2 second timeout. */
405
	ret = isci_task_execute_tmf(isci_host, isci_device, &tmf, ISCI_LU_RESET_TIMEOUT_MS);
406 407 408 409 410 411 412 413 414 415 416 417 418

	if (ret == TMF_RESP_FUNC_COMPLETE)
		dev_dbg(&isci_host->pdev->dev,
			"%s: %p: TMF_LU_RESET passed\n",
			__func__, isci_device);
	else
		dev_dbg(&isci_host->pdev->dev,
			"%s: %p: TMF_LU_RESET failed (%x)\n",
			__func__, isci_device, ret);

	return ret;
}

419
int isci_task_lu_reset(struct domain_device *dev, u8 *lun)
420
{
421
	struct isci_host *ihost = dev_to_ihost(dev);
422
	struct isci_remote_device *idev;
423
	unsigned long flags;
424 425
	int ret;

426
	spin_lock_irqsave(&ihost->scic_lock, flags);
427
	idev = isci_get_device(dev->lldd_dev);
428
	spin_unlock_irqrestore(&ihost->scic_lock, flags);
429

430
	dev_dbg(&ihost->pdev->dev,
431
		"%s: domain_device=%p, isci_host=%p; isci_device=%p\n",
432
		__func__, dev, ihost, idev);
433

434
	if (!idev) {
435
		/* If the device is gone, escalate to I_T_Nexus_Reset. */
436
		dev_dbg(&ihost->pdev->dev, "%s: No dev\n", __func__);
437

438
		ret = TMF_RESP_FUNC_FAILED;
439
		goto out;
440 441
	}

442 443 444
	if (dev_is_sata(dev)) {
		sas_ata_schedule_reset(dev);
		ret = TMF_RESP_FUNC_COMPLETE;
445 446 447 448 449 450 451 452 453
	} else {
		/* Suspend the RNC, kill all TCs */
		if (isci_remote_device_suspend_terminate(ihost, idev, NULL)
		    != SCI_SUCCESS) {
			ret = TMF_RESP_FUNC_FAILED;
			goto out;
		}
		/* Send the task management part of the reset. */
		ret = isci_task_send_lu_reset_sas(ihost, idev, lun);
454
	}
455
 out:
456
	isci_put_device(idev);
457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484
	return ret;
}


/*	 int (*lldd_clear_nexus_port)(struct asd_sas_port *); */
int isci_task_clear_nexus_port(struct asd_sas_port *port)
{
	return TMF_RESP_FUNC_FAILED;
}



int isci_task_clear_nexus_ha(struct sas_ha_struct *ha)
{
	return TMF_RESP_FUNC_FAILED;
}

/* Task Management Functions. Must be called from process context.	 */

/**
 * isci_task_abort_task() - This function is one of the SAS Domain Template
 *    functions. This function is called by libsas to abort a specified task.
 * @task: This parameter specifies the SAS task to abort.
 *
 * status, zero indicates success.
 */
int isci_task_abort_task(struct sas_task *task)
{
485
	struct isci_host *ihost = dev_to_ihost(task->dev);
486
	DECLARE_COMPLETION_ONSTACK(aborted_io_completion);
487
	struct isci_request       *old_request = NULL;
488
	struct isci_remote_device *idev = NULL;
489 490 491
	struct isci_tmf           tmf;
	int                       ret = TMF_RESP_FUNC_FAILED;
	unsigned long             flags;
492 493 494 495 496 497

	/* Get the isci_request reference from the task.  Note that
	 * this check does not depend on the pending request list
	 * in the device, because tasks driving resets may land here
	 * after completion in the core.
	 */
498
	spin_lock_irqsave(&ihost->scic_lock, flags);
499 500 501 502 503 504 505 506
	spin_lock(&task->task_state_lock);

	old_request = task->lldd_task;

	/* If task is already done, the request isn't valid */
	if (!(task->task_state_flags & SAS_TASK_STATE_DONE) &&
	    (task->task_state_flags & SAS_TASK_AT_INITIATOR) &&
	    old_request)
507
		idev = isci_get_device(task->dev->lldd_dev);
508 509

	spin_unlock(&task->task_state_lock);
510
	spin_unlock_irqrestore(&ihost->scic_lock, flags);
511

512 513 514
	dev_warn(&ihost->pdev->dev,
		 "%s: dev = %p, task = %p, old_request == %p\n",
		 __func__, idev, task, old_request);
515

516 517 518
	/* Device reset conditions signalled in task_state_flags are the
	 * responsbility of libsas to observe at the start of the error
	 * handler thread.
519
	 */
520
	if (!idev || !old_request) {
521 522 523 524 525 526 527 528 529 530
		/* The request has already completed and there
		* is nothing to do here other than to set the task
		* done bit, and indicate that the task abort function
		* was sucessful.
		*/
		spin_lock_irqsave(&task->task_state_lock, flags);
		task->task_state_flags |= SAS_TASK_STATE_DONE;
		task->task_state_flags &= ~(SAS_TASK_AT_INITIATOR |
					    SAS_TASK_STATE_PENDING);
		spin_unlock_irqrestore(&task->task_state_lock, flags);
531

532
		ret = TMF_RESP_FUNC_COMPLETE;
533

534 535 536
		dev_warn(&ihost->pdev->dev,
			 "%s: abort task not needed for %p\n",
			 __func__, task);
537
		goto out;
538
	}
539 540 541 542 543 544 545 546
	/* Suspend the RNC, kill the TC */
	if (isci_remote_device_suspend_terminate(ihost, idev, old_request)
	    != SCI_SUCCESS) {
		dev_warn(&ihost->pdev->dev,
			 "%s: isci_remote_device_reset_terminate(dev=%p, "
				 "req=%p, task=%p) failed\n",
			 __func__, idev, old_request, task);
		ret = TMF_RESP_FUNC_FAILED;
547
		goto out;
548
	}
549 550
	spin_lock_irqsave(&ihost->scic_lock, flags);

D
Dan Williams 已提交
551
	if (task->task_proto == SAS_PROTOCOL_SMP ||
552
	    sas_protocol_ata(task->task_proto) ||
D
Dan Williams 已提交
553
	    test_bit(IREQ_COMPLETE_IN_TARGET, &old_request->flags)) {
554

555 556
		/* No task to send, so explicitly resume the device here */
		sci_remote_device_resume(idev, NULL, NULL);
557

558
		spin_unlock_irqrestore(&ihost->scic_lock, flags);
559

560 561 562 563 564 565 566 567 568 569 570 571
		dev_warn(&ihost->pdev->dev,
			 "%s: %s request"
				 " or complete_in_target (%d), thus no TMF\n",
			 __func__,
			 ((task->task_proto == SAS_PROTOCOL_SMP)
			  ? "SMP"
			  : (sas_protocol_ata(task->task_proto)
				? "SATA/STP"
				: "<other>")
			  ),
			 test_bit(IREQ_COMPLETE_IN_TARGET,
				  &old_request->flags));
572

573 574 575 576 577 578 579
		spin_lock_irqsave(&task->task_state_lock, flags);
		task->task_state_flags &= ~(SAS_TASK_AT_INITIATOR |
					    SAS_TASK_STATE_PENDING);
		task->task_state_flags |= SAS_TASK_STATE_DONE;
		spin_unlock_irqrestore(&task->task_state_lock, flags);

		ret = TMF_RESP_FUNC_COMPLETE;
580 581
	} else {
		/* Fill in the tmf stucture */
582
		isci_task_build_abort_task_tmf(&tmf, isci_tmf_ssp_task_abort,
583
					       old_request);
584

585
		spin_unlock_irqrestore(&ihost->scic_lock, flags);
586

587
		/* Send the task management request. */
588
		#define ISCI_ABORT_TASK_TIMEOUT_MS 500 /* 1/2 second timeout */
589
		ret = isci_task_execute_tmf(ihost, idev, &tmf,
590
					    ISCI_ABORT_TASK_TIMEOUT_MS);
591
	}
592
out:
593 594 595
	dev_warn(&ihost->pdev->dev,
		 "%s: Done; dev = %p, task = %p , old_request == %p\n",
		 __func__, idev, task, old_request);
596
	isci_put_device(idev);
597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674
	return ret;
}

/**
 * isci_task_abort_task_set() - This function is one of the SAS Domain Template
 *    functions. This is one of the Task Management functoins called by libsas,
 *    to abort all task for the given lun.
 * @d_device: This parameter specifies the domain device associated with this
 *    request.
 * @lun: This parameter specifies the lun associated with this request.
 *
 * status, zero indicates success.
 */
int isci_task_abort_task_set(
	struct domain_device *d_device,
	u8 *lun)
{
	return TMF_RESP_FUNC_FAILED;
}


/**
 * isci_task_clear_aca() - This function is one of the SAS Domain Template
 *    functions. This is one of the Task Management functoins called by libsas.
 * @d_device: This parameter specifies the domain device associated with this
 *    request.
 * @lun: This parameter specifies the lun	 associated with this request.
 *
 * status, zero indicates success.
 */
int isci_task_clear_aca(
	struct domain_device *d_device,
	u8 *lun)
{
	return TMF_RESP_FUNC_FAILED;
}



/**
 * isci_task_clear_task_set() - This function is one of the SAS Domain Template
 *    functions. This is one of the Task Management functoins called by libsas.
 * @d_device: This parameter specifies the domain device associated with this
 *    request.
 * @lun: This parameter specifies the lun	 associated with this request.
 *
 * status, zero indicates success.
 */
int isci_task_clear_task_set(
	struct domain_device *d_device,
	u8 *lun)
{
	return TMF_RESP_FUNC_FAILED;
}


/**
 * isci_task_query_task() - This function is implemented to cause libsas to
 *    correctly escalate the failed abort to a LUN or target reset (this is
 *    because sas_scsi_find_task libsas function does not correctly interpret
 *    all return codes from the abort task call).  When TMF_RESP_FUNC_SUCC is
 *    returned, libsas turns this into a LUN reset; when FUNC_FAILED is
 *    returned, libsas will turn this into a target reset
 * @task: This parameter specifies the sas task being queried.
 * @lun: This parameter specifies the lun associated with this request.
 *
 * status, zero indicates success.
 */
int isci_task_query_task(
	struct sas_task *task)
{
	/* See if there is a pending device reset for this device. */
	if (task->task_state_flags & SAS_TASK_NEED_DEV_RESET)
		return TMF_RESP_FUNC_FAILED;
	else
		return TMF_RESP_FUNC_SUCC;
}

675
/*
676 677
 * isci_task_request_complete() - This function is called by the sci core when
 *    an task request completes.
678 679
 * @ihost: This parameter specifies the ISCI host object
 * @ireq: This parameter is the completed isci_request object.
680 681 682 683 684
 * @completion_status: This parameter specifies the completion status from the
 *    sci core.
 *
 * none.
 */
685 686 687 688
void
isci_task_request_complete(struct isci_host *ihost,
			   struct isci_request *ireq,
			   enum sci_task_status completion_status)
689
{
690
	struct isci_tmf *tmf = isci_request_access_tmf(ireq);
691
	struct completion *tmf_complete = NULL;
692

693
	dev_dbg(&ihost->pdev->dev,
694
		"%s: request = %p, status=%d\n",
695
		__func__, ireq, completion_status);
696

D
Dan Williams 已提交
697
	set_bit(IREQ_COMPLETE_IN_TARGET, &ireq->flags);
698

699 700 701 702 703 704 705 706 707 708 709 710 711 712
	if (tmf) {
		tmf->status = completion_status;

		if (tmf->proto == SAS_PROTOCOL_SSP) {
			memcpy(&tmf->resp.resp_iu,
			       &ireq->ssp.rsp,
			       SSP_RESP_IU_MAX_SIZE);
		} else if (tmf->proto == SAS_PROTOCOL_SATA) {
			memcpy(&tmf->resp.d2h_fis,
			       &ireq->stp.rsp,
			       sizeof(struct dev_to_host_fis));
		}
		/* PRINT_TMF( ((struct isci_tmf *)request->task)); */
		tmf_complete = tmf->complete;
713
	}
714
	sci_controller_complete_io(ihost, ireq->target_device, ireq);
715
	/* set the 'terminated' flag handle to make sure it cannot be terminated
716 717
	 *  or completed again.
	 */
D
Dan Williams 已提交
718
	set_bit(IREQ_TERMINATED, &ireq->flags);
719

720
	isci_free_tag(ihost, ireq->io_tag);
721

722
	/* The task management part completes last. */
723 724
	if (tmf_complete)
		complete(tmf_complete);
725 726
}

727
static int isci_reset_device(struct isci_host *ihost,
728
			     struct domain_device *dev,
729
			     struct isci_remote_device *idev)
730
{
731
	int rc = TMF_RESP_FUNC_COMPLETE, reset_stat;
732 733
	struct sas_phy *phy = sas_get_local_phy(dev);
	struct isci_port *iport = dev->port->lldd_port;
734

D
Dan Williams 已提交
735
	dev_dbg(&ihost->pdev->dev, "%s: idev %p\n", __func__, idev);
736

737 738 739
	/* Suspend the RNC, terminate all outstanding TCs. */
	if (isci_remote_device_suspend_terminate(ihost, idev, NULL)
	    != SCI_SUCCESS) {
740 741
		rc = TMF_RESP_FUNC_FAILED;
		goto out;
742
	}
743 744 745 746 747 748
	/* Note that since the termination for outstanding requests succeeded,
	 * this function will return success.  This is because the resets will
	 * only fail if the device has been removed (ie. hotplug), and the
	 * primary duty of this function is to cleanup tasks, so that is the
	 * relevant status.
	 */
749

750 751 752
	if (scsi_is_sas_phy_local(phy)) {
		struct isci_phy *iphy = &ihost->phys[phy->number];

753
		reset_stat = isci_port_perform_hard_reset(ihost, iport, iphy);
754
	} else
755
		reset_stat = sas_phy_reset(phy, !dev_is_sata(dev));
756

757 758
	/* Explicitly resume the RNC here, since there was no task sent. */
	isci_remote_device_resume(ihost, idev, NULL, NULL);
759

760 761
	dev_dbg(&ihost->pdev->dev, "%s: idev %p complete, reset_stat=%d.\n",
		__func__, idev, reset_stat);
762 763
 out:
	sas_put_local_phy(phy);
D
Dan Williams 已提交
764 765
	return rc;
}
766

D
Dan Williams 已提交
767 768 769 770 771
int isci_task_I_T_nexus_reset(struct domain_device *dev)
{
	struct isci_host *ihost = dev_to_ihost(dev);
	struct isci_remote_device *idev;
	unsigned long flags;
772
	int ret;
D
Dan Williams 已提交
773 774

	spin_lock_irqsave(&ihost->scic_lock, flags);
775
	idev = isci_get_device(dev->lldd_dev);
D
Dan Williams 已提交
776 777
	spin_unlock_irqrestore(&ihost->scic_lock, flags);

778 779 780 781
	if (!idev) {
		/* XXX: need to cleanup any ireqs targeting this
		 * domain_device
		 */
782 783 784
		ret = TMF_RESP_FUNC_COMPLETE;
		goto out;
	}
D
Dan Williams 已提交
785

786
	ret = isci_reset_device(ihost, dev, idev);
787 788 789
 out:
	isci_put_device(idev);
	return ret;
D
Dan Williams 已提交
790
}